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