网上看到一个建自己链的例子,但是只给了代码没有说具体怎么改,今天记录一下改的过程,下次再研究一下代码本身的意义。
首先大体说一下要实现的功能:
进入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
就是这样子了~