Tendermint包括两大组件,tendermint core和ABCI两大组件,开发者只要实现ABCI的接口即可定制开发自己的区块链逻辑。
安装tendermint core
go get github.com/tendermint/tendermint/cmd/tendermint
go install ./cmd/...
go get github.com/Masterminds/glide
cd $GOPATH/src/github.com/tendermint/tendermint
glide install
go install ./cmd/...
编写ABCI代码
新增ezapp.go,实现CheckTx方法,对放入mempool的交易进行校验
package ezapp
import (
"bytes"
"encoding/binary"
"github.com/tendermint/tendermint/abci/types"
)
var _ types.Application = (*Application)(nil)
type Application struct {
types.BaseApplication
}
func NewApplication() *Application {
return &Application{}
}
func (app *Application) CheckTx(req types.RequestCheckTx) types.ResponseCheckTx {
bin_buf := bytes.NewBuffer(req.Tx)
var x int32
binary.Read(bin_buf, binary.BigEndian, &x)
if x < 0x04 {
return types.ResponseCheckTx{}
}
return types.ResponseCheckTx{Code:1,Log:"bad tx rejected"}
}
修改abci-cli.go,见代码中注释ezapp处。
var RootCmd = &cobra.Command{
Use: "abci-cli",
Short: "the ABCI CLI tool wraps an ABCI client",
Long: "the ABCI CLI tool wraps an ABCI client and is used for testing ABCI servers",
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
switch cmd.Use {
//ezapp,增加一个ezapp,否则启动后一直会报错
case "counter", "kvstore","ezapp": // for the examples apps, don't pre-run
return nil
case "version": // skip running for version command
return nil
}
if logger == nil {
allowLevel, err := log.AllowLevel(flagLogLevel)
if err != nil {
return err
}
logger = log.NewFilter(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), allowLevel)
}
if client == nil {
var err error
client, err = abcicli.NewClient(flagAddress, flagAbci, false)
if err != nil {
return err
}
client.SetLogger(logger.With("module", "abci-client"))
if err := client.Start(); err != nil {
return err
}
}
return nil
},
}
//增加addezappFlags方法
func addezappFlags() {
ezappCmd.PersistentFlags().StringVarP(&flagPersist, "persist", "", "", "directory to use for a database")
}
func addCommands() {
RootCmd.AddCommand(batchCmd)
RootCmd.AddCommand(consoleCmd)
RootCmd.AddCommand(echoCmd)
RootCmd.AddCommand(infoCmd)
RootCmd.AddCommand(setOptionCmd)
RootCmd.AddCommand(deliverTxCmd)
RootCmd.AddCommand(checkTxCmd)
RootCmd.AddCommand(commitCmd)
RootCmd.AddCommand(versionCmd)
RootCmd.AddCommand(testCmd)
addQueryFlags()
RootCmd.AddCommand(queryCmd)
// examples
addCounterFlags()
RootCmd.AddCommand(counterCmd)
addKVStoreFlags()
RootCmd.AddCommand(kvstoreCmd)
//ezapp增加这两行代码
addezappFlags()
RootCmd.AddCommand(ezappCmd)
}
//ezapp,新增ezappCmd
var ezappCmd = &cobra.Command{
Use: "ezapp",
Short: "ezapp demo example",
Long: "ezapp demo example",
Args: cobra.ExactArgs(0),
RunE: cmdEzapp,
}
func cmdEzapp(cmd *cobra.Command, args []string) error {
var app types.Application
app = ezapp.NewApplication()
logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout))
// Start the listener
srv, err := server.NewServer(flagAddress, flagAbci, app)
if err != nil {
return err
}
srv.SetLogger(logger.With("module", "abci-server"))
if err := srv.Start(); err != nil {
return err
}
// Stop upon receiving SIGTERM or CTRL-C.
tmos.TrapSignal(logger, func() {
// Cleanup
srv.Stop()
})
// Run forever.
select {}
}
编译运行abci-cli
cd %GOPATH/src/github.com/tendermint/abci/cmd/abci-cli
go build
abci-cli ezapp
启动tendermint core
tendermint init
tendermint node
curl -l http://localhost:26657/broadcast_tx_commit?tx=2
{
"jsonrpc": "2.0",
"id": -1,
"result": {
"check_tx": {
"code": 0,
"data": null,
"log": "",
"info": "",
"gasWanted": "0",
"gasUsed": "0",
"events": [],
"codespace": ""
},
"deliver_tx": {
"code": 0,
"data": null,
"log": "",
"info": "",
"gasWanted": "0",
"gasUsed": "0",
"events": [],
"codespace": ""
},
"hash": "D4735E3A265E16EEE03F59718B9B5D03019C07D8B6C51F90DA3A666EEC13AB35",
"height": "7"
}
}