github.com/okex/exchain@v1.8.0/libs/tendermint/abci/example/counter/counter.go (about) 1 package counter 2 3 import ( 4 "encoding/binary" 5 "encoding/json" 6 "fmt" 7 "math/big" 8 9 sdk "github.com/okex/exchain/libs/cosmos-sdk/types" 10 11 "github.com/okex/exchain/libs/tendermint/abci/example/code" 12 "github.com/okex/exchain/libs/tendermint/abci/types" 13 ) 14 15 type MockExTxInfo struct { 16 Sender string `json:"sender"` 17 SenderNonce uint64 `json:"sender_nonce"` 18 GasPrice *big.Int `json:"gas_price"` 19 Nonce uint64 `json:"nonce"` 20 } 21 22 type Application struct { 23 types.BaseApplication 24 25 hashCount int 26 txCount int 27 serial bool 28 } 29 30 func NewApplication(serial bool) *Application { 31 return &Application{serial: serial} 32 } 33 34 func (app *Application) Info(req types.RequestInfo) types.ResponseInfo { 35 return types.ResponseInfo{Data: fmt.Sprintf("{\"hashes\":%v,\"txs\":%v}", app.hashCount, app.txCount)} 36 } 37 38 func (app *Application) SetOption(req types.RequestSetOption) types.ResponseSetOption { 39 key, value := req.Key, req.Value 40 if key == "serial" && value == "on" { 41 app.serial = true 42 } else { 43 /* 44 TODO Panic and have the ABCI server pass an exception. 45 The client can call SetOptionSync() and get an `error`. 46 return types.ResponseSetOption{ 47 Error: fmt.Sprintf("Unknown key (%s) or value (%s)", key, value), 48 } 49 */ 50 return types.ResponseSetOption{} 51 } 52 53 return types.ResponseSetOption{} 54 } 55 56 func (app *Application) DeliverTx(req types.RequestDeliverTx) types.ResponseDeliverTx { 57 if app.serial { 58 if len(req.Tx) > 8 { 59 return types.ResponseDeliverTx{ 60 Code: code.CodeTypeEncodingError, 61 Log: fmt.Sprintf("Max tx size is 8 bytes, got %d", len(req.Tx))} 62 } 63 tx8 := make([]byte, 8) 64 copy(tx8[len(tx8)-len(req.Tx):], req.Tx) 65 txValue := binary.BigEndian.Uint64(tx8) 66 if txValue != uint64(app.txCount) { 67 return types.ResponseDeliverTx{ 68 Code: code.CodeTypeBadNonce, 69 Log: fmt.Sprintf("Invalid nonce. Expected %v, got %v", app.txCount, txValue)} 70 } 71 } 72 app.txCount++ 73 return types.ResponseDeliverTx{Code: code.CodeTypeOK} 74 } 75 76 type tx struct { 77 sdk.BaseTx 78 } 79 80 func (tx *tx) GetGasPrice() *big.Int { 81 return big.NewInt(1) 82 } 83 84 func (app *Application) CheckTx(req types.RequestCheckTx) types.ResponseCheckTx { 85 if app.serial { 86 if len(req.Tx) > 8 { 87 return types.ResponseCheckTx{ 88 Code: code.CodeTypeEncodingError, 89 Log: fmt.Sprintf("Max tx size is 8 bytes, got %d", len(req.Tx))} 90 } 91 tx8 := make([]byte, 8) 92 copy(tx8[len(tx8)-len(req.Tx):], req.Tx) 93 txValue := binary.BigEndian.Uint64(tx8) 94 if txValue < uint64(app.txCount) { 95 return types.ResponseCheckTx{ 96 Code: code.CodeTypeBadNonce, 97 Log: fmt.Sprintf("Invalid nonce. Expected >= %v, got %v", app.txCount, txValue)} 98 } 99 } 100 data, _ := json.Marshal(&MockExTxInfo{Sender: fmt.Sprintf("%+x", req.Tx), GasPrice: big.NewInt(1)}) 101 return types.ResponseCheckTx{Tx: &tx{sdk.BaseTx{From: fmt.Sprintf("%+x", req.Tx)}}, Code: code.CodeTypeOK, Data: data} 102 } 103 104 func (app *Application) Commit(req types.RequestCommit) types.ResponseCommit { 105 app.hashCount++ 106 if app.txCount == 0 { 107 return types.ResponseCommit{} 108 } 109 hash := make([]byte, 8) 110 binary.BigEndian.PutUint64(hash, uint64(app.txCount)) 111 return types.ResponseCommit{Data: hash} 112 } 113 114 func (app *Application) Query(reqQuery types.RequestQuery) types.ResponseQuery { 115 switch reqQuery.Path { 116 case "hash": 117 return types.ResponseQuery{Value: []byte(fmt.Sprintf("%v", app.hashCount))} 118 case "tx": 119 return types.ResponseQuery{Value: []byte(fmt.Sprintf("%v", app.txCount))} 120 default: 121 return types.ResponseQuery{Log: fmt.Sprintf("Invalid query path. Expected hash or tx, got %v", reqQuery.Path)} 122 } 123 }