Cosmos系列-1. Tendermint

Tendermint

从架构层面,区块链可以简单的分为三个概念层:

  • 网络层: 负责节点互联,交易和数据传输以及同步
  • 共识算法:负责不同的验证节点处理完事务(交易)后,保证状态的一致
  • 应用程序:事务执行者,改变状态

大致框架如下:

image

区块链是一个具备确定性的状态机,可以在不信任的节点之间进行状态复制,Tendermint 基于上面的架构,将应用程序与底层进行了分离,将P2P网络和共识引擎封装组成Tendermint Core, 同时提供ABCI(Application BlockChain Interface)接口与应用层进行交互,
应用的逻辑可以用任何语言编写。应用层做的事情实际上就是状态机控制. 这样开发者可以很方便的实现自己的区块链.

[外链图片转存失败(img-YnzxsQgL-1566198289277)(https://github.com/xueqianLu/icloudImages/raw/master/cosmos-images/10002.png)]

总结,Tendermint可以理解为是一个模块化的区块链软件框架,使开发者可以不考虑共识以及网络传输的实现,个性化定制自己的区块链.

ABCI

ABCI是Tendermint中定义的一套Application与Tendermint Core之间交互的协议。详细如下:

type Application interface {
	// Info/Query Connection
	Info(RequestInfo) ResponseInfo                // Return application info
	SetOption(RequestSetOption) ResponseSetOption // Set application option
	Query(RequestQuery) ResponseQuery             // Query for state

	// Mempool Connection
	CheckTx(RequestCheckTx) ResponseCheckTx // Validate a tx for the mempool

	// Consensus Connection
	InitChain(RequestInitChain) ResponseInitChain    // Initialize blockchain with validators and other info from TendermintCore
	BeginBlock(RequestBeginBlock) ResponseBeginBlock // Signals the beginning of a block
	DeliverTx(RequestDeliverTx) ResponseDeliverTx    // Deliver a tx for full processing
	EndBlock(RequestEndBlock) ResponseEndBlock       // Signals the end of a block, returns changes to the validator set
	Commit() ResponseCommit                          // Commit the state and return the application Merkle root hash
}

ABCI接口可以分为三类:信息查询、交易校验以及共识相关处理。而Tendermint Core作为ABCI Client 在启动时,会与ABCI Server建立三个连接,分别用于这三类接口消息的处理。

下面简单描述几种消息类型的作用:

  • Info : 消息用于共识层获取应用层的状态信息
  • SetOption : 消息用于设置一些非共识的应用程序参数
  • InitChain : 消息用于创世初始化
  • Query : 消息用于应用程序从链的当前或过往的高度获取数据
  • CheckTx : 消息用于验证交易。Tendermint Core中的mempool通过此消息校验交易的合法性,通过之后才会将交易广播给其它节点。
  • BeginBlock: 一个块执行开始的信号
  • DeliverTx : 消息是应用的主要工作流程,通过此消息真正执行交易,包括验证交易、更新应用程序的状态。
  • EndBlock : 一个块执行结束的信号,会返回变化了的验证者集合.
  • Commit : 消息用于持久化应用状态, 计算Merkle root.

Tendermint Core

Tendermint共识引擎,包含区块链需要的大部分功能,主要包括:

  • 共识算法(基于拜占庭的PoS)
  • P2P
  • RPC
  • 其他(交易缓存池/消息队列等)

Cosmos 和 Tendermint

Cosmos 是在Tendermint 基础上丰富插件实现的App.

[外链图片转存失败(img-JYGtPRTp-1566198289279)(https://github.com/xueqianLu/icloudImages/raw/master/cosmos-images/10003.png)]

实例 kvstore

kvstore 是一个简单的ABCI app, 也可以说是一个链,这个app的功能仅仅是存储key-value, 不涉及账户/余额/奖励/转账等内容.

type KVStoreApplication struct {
    
    
	types.BaseApplication
	state State
}

func NewKVStoreApplication() *KVStoreApplication {
    
    
	state := loadState(dbm.NewMemDB())
	return &KVStoreApplication{
    
    state: state}
}

func (app *KVStoreApplication) Info(req types.RequestInfo) (resInfo types.ResponseInfo) {
    
    
	return types.ResponseInfo{
    
    
		Data:       fmt.Sprintf("{\"size\":%v}", app.state.Size),
		Version:    version.ABCIVersion,
		AppVersion: ProtocolVersion.Uint64(),
	}
}

// tx is either "key=value" or just arbitrary bytes
func (app *KVStoreApplication) DeliverTx(req types.RequestDeliverTx) types.ResponseDeliverTx {
    
    
	var key, value []byte
	parts := bytes.Split(req.Tx, []byte("="))
	if len(parts) == 2 {
    
    
		key, value = parts[0], parts[1]
	} else {
    
    
		key, value = req.Tx, req.Tx
	}

	app.state.db.Set(prefixKey(key), value)
	app.state.Size += 1

	events := []types.Event{
    
    
		{
    
    
			Type: "app",
			Attributes: []cmn.KVPair{
    
    
				{
    
    Key: []byte("creator"), Value: []byte("Cosmoshi Netowoko")},
				{
    
    Key: []byte("key"), Value: key},
			},
		},
	}

	return types.ResponseDeliverTx{
    
    Code: code.CodeTypeOK, Events: events}
}

func (app *KVStoreApplication) CheckTx(req types.RequestCheckTx) types.ResponseCheckTx {
    
    
	return types.ResponseCheckTx{
    
    Code: code.CodeTypeOK, GasWanted: 1}
}

func (app *KVStoreApplication) Commit() types.ResponseCommit {
    
    
	// Using a memdb - just return the big endian size of the db
	appHash := make([]byte, 8)
	binary.PutVarint(appHash, app.state.Size)
	app.state.AppHash = appHash
	app.state.Height += 1
	saveState(app.state)
	return types.ResponseCommit{
    
    Data: appHash}
}

func (app *KVStoreApplication) Query(reqQuery types.RequestQuery) (resQuery types.ResponseQuery) {
    
    
	resQuery.Key = reqQuery.Data
	value := app.state.db.Get(prefixKey(reqQuery.Data))
	resQuery.Value = value
	if value != nil {
    
    
		resQuery.Log = "exists"
	} else {
    
    
		resQuery.Log = "does not exist"
	}
	return
}

app是abci 的server端,而tendermint是abci的client端, 因此是需要先启动app然后再启动tendermint去连接server.
而事务是通过调用tendermint的rpc接口发起的,由tendermint通知到app层进行处理.

luxq@testpc:~$curl http://localhost:26657/broadcast_tx_commit?tx=\"abcd=121321\"
{
  "jsonrpc": "2.0",
  "id": "",
  "result": {
    "check_tx": {
      "gasWanted": "1"
    },
    "deliver_tx": {
      "tags": [
        {
          "key": "YXBwLmNyZWF0b3I=",                    //app.creator
          "value": "Q29zbW9zaGkgTmV0b3dva28="           //Cosmoshi Netowoko
        },
        {
          "key": "YXBwLmtleQ==",                        //app.key
          "value": "YWJjZA=="                           //abcd
        }
      ]
    },
    "hash": "2A71EC7647ACC0F582DC245F1080F0FC4C0D8DCDED53FBDFD6B1D899AC2D1373",
    "height": "51464"
  }
}
luxq@testpc:~$

Tx

从上面的例子中看到Tx并不是之前见到的账户转账,而是一段数据,具体的数据解析和使用是在App层做处理的.
Tx 的数据结构也只是一段纯数据.

//file:  tendermint/types/tx.go
type Tx []byte

Next

Tendermint Core 和ABCI 的基本知识已经了解,下一步了解Cosmos-SDK

猜你喜欢

转载自blog.csdn.net/mynameislu/article/details/99728872