Cosmos Series-1. Tendermint

Tendermint

From the architectural level, blockchain can be simply divided into three conceptual layers:

  • Network layer: Responsible for node interconnection, transaction and data transmission, and synchronization
  • Consensus algorithm: responsible for ensuring the consistency of the state after different verification nodes have processed the transaction (transaction)
  • Application: transaction executor, changing state

The general framework is as follows:

image

Blockchain is a deterministic state machine that can replicate state between untrusted nodes. Based on the above architecture, Tendermint separates the application program from the bottom layer, and encapsulates the P2P network and consensus engine to form Tendermint Core. At the same time, the ABCI (Application BlockChain Interface) interface is provided to interact with the application layer, and
the logic of the application can be written in any language. What the application layer does is actually state machine control. In this way, developers can easily implement their own blockchain.

[External link image transfer failed (img-YnzxsQgL-1566198289277)(https://github.com/xueqianLu/icloudImages/raw/master/cosmos-images/10002.png)]

In summary, Tendermint can be understood as a modular blockchain software framework that allows developers to customize their own blockchain regardless of the implementation of consensus and network transmission.

ABCI

ABCI is a protocol defined in Tendermint for interaction between Application and Tendermint Core. The details are as follows:

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 interfaces can be divided into three categories: information query, transaction verification, and consensus-related processing. When Tendermint Core is started as an ABCI Client, it will establish three connections with the ABCI Server, which are used to process these three types of interface messages.

The following briefly describes the functions of several message types:

  • Info : The message is used by the consensus layer to obtain the state information of the application layer
  • SetOption : message is used to set some non-consensus application parameters
  • InitChain : message for genesis initialization
  • Query : The message is used by the application to obtain data from the current or past height of the chain
  • CheckTx : The message is used to verify the transaction. The mempool in Tendermint Core verifies the legitimacy of the transaction through this message, and will broadcast the transaction to other nodes after passing.
  • BeginBlock: Signals the beginning of a block execution
  • DeliverTx : The message is the main workflow of the application, through which the transaction is actually executed, including verifying the transaction and updating the state of the application.
  • EndBlock : Signals the end of a block execution, returning the changed set of validators.
  • Commit : The message is used to persist the application state and calculate the Merkle root.

Tendermint Core

The Tendermint consensus engine contains most of the functions required by the blockchain, mainly including:

  • Consensus algorithm (PoS based on Byzantine)
  • P2P
  • RPC
  • Others (transaction buffer pool/message queue, etc.)

Cosmos and Tendermint

Cosmos is an App implemented with rich plugins based on Tendermint.

[External link image transfer failed (img-JYGtPRTp-1566198289279)(https://github.com/xueqianLu/icloudImages/raw/master/cosmos-images/10003.png)]

instance kvstore

kvstore is a simple ABCI app, which can also be said to be a chain. The function of this app is only to store key-value, and does not involve account/balance/reward/transfer.

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 is the server side of abci, and tendermint is the client side of abci, so it is necessary to start the app first and then start tendermint to connect to the server. The
transaction is initiated by calling the rpc interface of tendermint, which is notified by tendermint to the app layer for processing.

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

From the above example, we can see that Tx is not the account transfer seen before, but a piece of data. The specific data analysis and use are processed at the App layer. The
data structure of Tx is just a piece of pure data.

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

Next

The basic knowledge of Tendermint Core and ABCI has been understood, the next step is to understand Cosmos-SDK

Guess you like

Origin blog.csdn.net/mynameislu/article/details/99728872