tendermint建立一条自己的链----代码篇

网上看到一个建自己链的例子,但是只给了代码没有说具体怎么改,今天记录一下改的过程,下次再研究一下代码本身的意义。
首先大体说一下要实现的功能:
进入tendermint后可以查询初始化两个带有币的用户,以及可以实现转账功能。
1、更改代码的目录在abci/example/kvstore/kvstore.go
2、代码:

type Application struct {
	types.BaseApplication
	accountMap map[string]int
	state      State
}

func NewApplication() *Application {
	state := loadState(dbm.NewMemDB())
	fmt.Println("NewCounterApplication进来了吗")
	return &Application{accountMap: map[string]int{"xiaoMing": 100, "daZhuang": 100}, state: state}
}

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

// tx is either "key=value" or just arbitrary bytes
/*
func (app *Application) 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++

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

	return types.ResponseDeliverTx{Code: code.CodeTypeOK, Events: events}
}
*/
func (app *Application) DeliverTx(req types.RequestDeliverTx) types.ResponseDeliverTx {
	fmt.Println("DeliverTx进来了吗")
	//xiaoming转给dazhuang
	tx8 := make([]byte, 8)
	copy(tx8[len(tx8)-len(req.Tx):], req.Tx)
	balance := int(binary.BigEndian.Uint64(tx8))

	if app.accountMap["xiaoMing"] < balance {
		return types.ResponseDeliverTx{
			Code: code.CodeTypeEncodingError,
			Log:  fmt.Sprintf("Insufficient balance")}
	}
	app.accountMap["xiaoMing"] -= balance
	app.accountMap["daZhuang"] += balance
	return types.ResponseDeliverTx{Code: code.CodeTypeOK}
}

/*
func (app *Application) CheckTx(req types.RequestCheckTx) types.ResponseCheckTx {
	return types.ResponseCheckTx{Code: code.CodeTypeOK, GasWanted: 1}
}
*/
func (app *Application) CheckTx(req types.RequestCheckTx) types.ResponseCheckTx {
	fmt.Println("CheckTx进来了吗")
	//xiaoming转给dazhuang
	tx8 := make([]byte, 8)
	copy(tx8[len(tx8)-len(req.Tx):], req.Tx)
	balance := int(binary.BigEndian.Uint64(tx8))

	if app.accountMap["xiaoMing"] < balance {
		return types.ResponseCheckTx{
			Code: code.CodeTypeEncodingError,
			Log:  fmt.Sprintf("Insufficient balance")}
	}
	fmt.Println("CheckTx ok")
	return types.ResponseCheckTx{Code: code.CodeTypeOK}
}

/*
func (app *Application) 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++
	saveState(app.state)
	return types.ResponseCommit{Data: appHash}
}

// Returns an associated value or nil if missing.
func (app *Application) Query(reqQuery types.RequestQuery) (resQuery types.ResponseQuery) {
	if reqQuery.Prove {
		value, err := app.state.db.Get(prefixKey(reqQuery.Data))
		if err != nil {
			panic(err)
		}
		if value == nil {
			resQuery.Log = "does not exist"
		} else {
			resQuery.Log = "exists"
		}
		resQuery.Index = -1 // TODO make Proof return index
		resQuery.Key = reqQuery.Data
		resQuery.Value = value

		return
	}

	resQuery.Key = reqQuery.Data
	value, err := app.state.db.Get(prefixKey(reqQuery.Data))
	if err != nil {
		panic(err)
	}
	if value == nil {
		resQuery.Log = "does not exist"
	} else {
		resQuery.Log = "exists"
	}
	resQuery.Value = value

	return resQuery
}
*/
func (app *Application) Commit() (resp types.ResponseCommit) {
	fmt.Println("Commit进来了吗")
	appHash := make([]byte, 8)
	binary.PutVarint(appHash, int64(len(app.accountMap))) //这里随便commit了一个hash
	return types.ResponseCommit{Data: appHash}
}

func (app *Application) Query(reqQuery types.RequestQuery) types.ResponseQuery {
	fmt.Println("Query进来了吗")
	name := string(reqQuery.Data)
	amount, ok := app.accountMap[name]
	if !ok {
		return types.ResponseQuery{Log: fmt.Sprintf("Invalid name %v", reqQuery.Data)}
	}
	return types.ResponseQuery{Value: []byte(fmt.Sprintf("%v", amount))}
}

在结构体Application里新加accountMap map[string]int
注释里的是原文件里的代码,把源文件里相同名的函数用上述的函数代替。
3、重新编译,在上篇tendermint的安装中,我们第一次编译了abci-cli文件,并生成了abc-cli.exe文件.https://blog.csdn.net/guoyihaoguoyihao/article/details/104537782
我们用同样的方法进行编译并复制到bin目录下,我命名为abci-cli2。
4、测试:
首先在bin目录下打开cmd1,执行tendermint unsafe_reset_all来清楚原来的数据。再打开cmd2执行abci-cli kvstore:
在这里插入图片描述
在cmd1输入tendermint init来初始化
输入tendermint node来开始运行链。

在这里插入图片描述
最后,在bin打开cmd3查询

curl -s localhost:26657/abci_query?data=\"xiaoMing\"

在这里插入图片描述
在这里插入图片描述
显示有value值则表示改的代码成功!
对于具体代码的解读,可能之后会再补充。
最后附上代码的出处:http://www.qukuaiwang.com.cn/news/143278.html
就是这样子了~

发布了30 篇原创文章 · 获赞 5 · 访问量 5094

猜你喜欢

转载自blog.csdn.net/guoyihaoguoyihao/article/details/104594334