qbase
是QOS通用区块链应用框架,基于此框架开发QOS公链和联盟区块链应用,提供了通用的存储、交易和QCP跨链协议。
qbase
代码结构:
account
: 对账户的抽象及基础操作的封装baseabci
: 基于tendermint
实现的基础ABCI APP模板client
: 与qbase
交互的客户端命令集context
: 上下文工具类example
: 提供basecoin
和kvstore
示例keys
: 助记符生成及恢复mapper
:store
操作的基础封装qcp
: 跨链协议操作封装server
: 启动服务封装store
: 基于Merkle
树的数据库通用存储txs
: transaction封装types
: 工具类及通用结构
qbase
项目包含以下几类Application:
- ABCI App
Tendermint
定义的接口规范
The basic ABCI interface allowing Tendermint to drive the applications state machine with transaction blocks.
- baseabci App
ABCI App
接口实现的基础模板,实现了账户签名校验、账户nonce
校验及跨链qcp
业务等通用操作,并提供了扩展接口用于自定义业务扩展。
- basecoin App
基于baseabci app
实现的示例,提供了转账、跨链转账功能。
- your custom App
基于baseabci app
开发的项目APP,可以在App中实现以下功能:
- 增强
account
功能 - 自定义
mapper
存储数据 - 自定义
tx
业务逻辑 - ...
定义具体的业务内容,可以包含其他的信息。 自定义Tx需要实现txs.ITx
接口:
qbase
使用go-amino进行编码解码,自定义Tx中的成员必须为可导出的(即成员首字母需为大写)。
type ITx interface {
ValidateData(ctx context.Context) error // 校验业务数据
Exec(ctx context.Context) (result types.Result, crossTxQcp *TxQcp)
GetSigner() []types.AccAddress //签名者
CalcGas() types.BigInt //计算gas
GetGasPayer() types.AccAddress //gas付费人
GetSignData() []byte //获取签名字段
}
qbase
SDK处理的标准Tx,包含以下字段:
type TxStd struct {
ITx ITx `json:"itx"` //ITx接口,将被具体Tx结构实例化
Signature []Signature `json:"sigature"` //签名数组
ChainID string `json:"chainid"` //ChainID: 执行ITx.exec方法的链ID
MaxGas types.BigInt `json:"maxgas"` //Gas消耗的最大值
}
基于跨链QCP协议的跨链业务数据封装:
type TxQcp struct {
TxStd *TxStd `json:"txstd"` //TxStd结构
From string `json:"from"` //qscName
To string `json:"to"` //qosName
Sequence int64 `json:"sequence"` //发送Sequence
Sig Signature `json:"sig"` //签名
BlockHeight int64 `json:"blockheight"` //Tx所在block高度
TxIndex int64 `json:"txindex"` //Tx在block的位置
IsResult bool `json:"isresult"` //是否为Result
Extends string `json:"extends"` //扩展字段
}
数据持久层,对底层数据的通用访问接口。具体方法参见store.store.go
文件
基于KVStore
的业务封装,使用amino对数据进行编码保存。
自定义Mapper需要实现mapper.IMapper
接口:
自定义Mapper通过调用baseapp.RegisterMapper方法后使用
type IMapper interface {
Copy() IMapper
//BaseMapper implement below methods
MapperName() string
GetStoreKey() store.StoreKey
SetStore(store store.KVStore)
SetCodec(cdc *go_amino.Codec)
}
qbase
提供BaseMapper
用于对IMapper
的快速实现,自定义Mapper仅需实现Copy()
方法即可:
type YourMapper struct {
*mapper.BaseMapper
//other fields
}
var _ mapper.IMapper = (*YourMapper)(nil)
func NewYourMapper(mapperName string) *YourMapper {
var yourMapper = YourMapper{}
yourMapper.BaseMapper = mapper.NewBaseMapper(nil, mapperName)
return &yourMapper
}
func (mapper *YourMapper) Copy() mapper.IMapper {
cpyMapper := &YourMapper{}
cpyMapper.BaseMapper = mapper.BaseMapper.Copy()
//other fields copy
return cpyMapper
}
account
包中提供了对账户体系的基础封装,包含账户的地址、nonce
、pubkey
等。
可以通过以下方式对账户进行扩展:
扩展的账户类型需要通过 app.RegisterAccountProto进行注册
调用
baseapp.RegisterAccountProto
后,qbase
会自动注册account.AccountMapper
。account.AccountMapper
提供了对账户的查询,保存操作。
type YourAccount struct {
account.BaseAccount `json:"base_account"`
Coins types.BaseCoins `json:"coins"`
//other fields
}
参见: QCP
abci.Application
接口的实现。并提供以下注册方法:
-
RegisterAccountProto(proto func() account.Account): 注册自定义账户。调用此方法时,将注册account.AccountMapper
-
RegisterMapper(mapper mapper.IMapper): 注册自定义Mapper
-
RegisterCustomQueryHandler(handler CustomQueryHandler): 注册自定义查询handler
-
RegisterTxQcpSigner(signer crypto.PrivKey): 注册对跨链TxQcp进行签名的私钥
-
RegisterTxQcpResultHandler(txQcpResultHandler TxQcpResultHandler): 注册对跨链交易结果处理handler
BaseApp中提供以下方法对ABCI中initChain
,beginBlock
,endBlock
阶段进行自定义处理:
-
SetInitChainer(initChainer InitChainHandler)
-
SetBeginBlocker(beginBlocker BeginBlockHandler)
-
SetEndBlocker(endBlocker EndBlockHandler)
qbase
提供以下方式用于查询数据:
-
/store/{KVStoreKey}/key
: 通过key查询index为{KVStoreKey}的数据。 -
/custom/{CustomPath1}/{CustomPath2}/...
: 自定义查询路径。需要实现baseabci.CustomQueryHandler
方法:
var customQueryHandler = func(ctx ctx.Context, route []string, req abci.RequestQuery) (res []byte, err types.Error) {
//检查route长度
// if route[0] == {CustomPath1} && route[1] == {CustomPath2} ... {
// do something...
//}
}
//注册自定义查询Handler
baseapp.RegisterCustomQueryHandler(customQueryHandler)
参见: 客户端命令