tendermint执行流程

2 篇文章 0 订阅
1 篇文章 0 订阅

首先放两段代码

第一段是tendermint abci的代码

// +build trade

package trade

import (
	"dev.33.cn/33/btrade/tradeserver"
	"github.com/tendermint/abci/types"
)

type TradeApplication struct {
	state *tradeserver.TradeServer
}

func NewTradeApplication(dbDir string) *TradeApplication {
	state, err := tradeserver.Init(dbDir, "trade")
	if err != nil {
		panic(err)
	}
	return &TradeApplication{state: state}
}

func (app *TradeApplication) Info() (resInfo types.ResponseInfo) {
	return app.state.Info()
}

func (app *TradeApplication) SetOption(key string, value string) (log string) {
	return app.state.SetOption(key, value)
}

func (app *TradeApplication) DeliverTx(tx []byte) types.Result {
	result, err := app.state.Exec(tx)
	if err != nil {
		return types.NewResult(types.CodeType_InternalError, []byte(err.Error()), "")
	}
	return types.NewResultOK(result, "")
}

func (app *TradeApplication) CheckTx(tx []byte) types.Result {
	err := app.state.Check(tx)
	if err != nil {
		return types.NewResult(types.CodeType_InternalError, []byte(err.Error()), "")
	}
	return types.OK
}

func (app *TradeApplication) Commit() types.Result {
	return app.state.Commit()
}

func (app *TradeApplication) Query(reqQuery types.RequestQuery) (resQuery types.ResponseQuery) {
	value, err := app.state.Query(reqQuery.Data)
	if err != nil {
		resQuery.Code = types.CodeType_InternalError
		resQuery.Log = err.Error()
	}

	resQuery.Key = reqQuery.Data
	resQuery.Value = value
	return
}

// Save the validators in the merkle tree
func (app *TradeApplication) InitChain(validators []*types.Validator) {

}

// Track the block hash and header information
func (app *TradeApplication) BeginBlock(hash []byte, header *types.Header) {
	app.state.BeginBlock(hash, header)
}

// Update the validator set
func (app *TradeApplication) EndBlock(height uint64) (resEndBlock types.ResponseEndBlock) {
	return app.state.EndBlock(height)
}

第二段是做交易所的时候,测试调用的代码,用来模仿tendermint的运行步骤

func send(request *msq.WriteRequest) (*msq.Response, error) {
	height++
	hash := []byte("foo")
	header := &types.Header{
		Height: height,
	}

	trade.BeginBlock(hash, header)
	//先是req  再是request加密
	data, err := msq.MarshalMessage(request)
	if err != nil {
		return nil, err
	}

	err = trade.Check(data)
	if err != nil {
		return nil, err
	}

	res, err := trade.Exec(data)
	if err != nil {
		return nil, err
	}

	var resp msq.Response
	err = msq.UnmarshalMessage(res, &resp)
	if err != nil {
		return nil, err
	}

	trade.EndBlock(height)

	trade.Commit()
	return &resp, nil
}

可以看到,在测试代码中,先是定义了一个区块header,然后调用BeginBlock,来准备区块所需要的东西。可以看一下他的代码,头部的height++了,然后替换头部,别的东西都重置。


func (s *TradeServer) BeginBlock(hash []byte, header *types.Header) {
	// update latest block info
	s.blockHeader = header

	// reset valset changes
	s.changes = make([]*types.Validator, 0)

	// clear for new block
	txEvents = []*msq.Event{}
	txResults = []*msq.TxResult{}
	txInsIds = []int64{}
}

接下来是把数据编码,第二步调用Check方法,对请求验证他的合法性,基本上是对请求参数的一些校验,是否大于0之类的。

第三步是Exec,具体执行请求里的操作,一些业务代码,比如注册用户之类的。

第四步  EndBlock

// Update the validator set
func (s *TradeServer) EndBlock(height uint64) (resEndBlock types.ResponseEndBlock) {
	return types.ResponseEndBlock{Diffs: s.changes}
}

最后是commit,保存所需要的数据及区块

func (s *TradeServer) Commit() types.Result {
	batch := ldb.NewBatch()

	// save lastblock
	s.lastBlock.Height = s.blockHeader.Height
	s.lastBlock.AppHash = s.Hash() //块hash
	buf, err := msq.MarshalMessage(s.lastBlock)
	if err != nil {
		panic("cannot save last block")
	}
	batch.Put(lastBlockKey, buf)

	// save events
	putItems, delItems := s.processEvents(txEvents)
	for key, value := range putItems {
		//log.Println("process.put", key)
		batch.Put([]byte(key), value)
	}
	for key, _ := range delItems {
		//log.Println("process.del", key)
		batch.Delete([]byte(key))
	}

	batch.Commit()

	// after Commit, the matchcommon event has been set to db
	// when next time restart, app will known the last exec id
	// So, there is no need to store lastExecId additionly

	log.Printf("Saving block height: %v appHash: %X", s.lastBlock.Height, s.lastBlock.AppHash)
	return types.NewResultOK(s.lastBlock.AppHash, "")
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值