github.com/line/ostracon@v1.0.10-0.20230328032236-7f20145f065d/abci/example/counter/counter.go (about) 1 package counter 2 3 import ( 4 "encoding/binary" 5 "fmt" 6 7 "github.com/tendermint/tendermint/abci/types" 8 9 "github.com/line/ostracon/abci/example/code" 10 ocabci "github.com/line/ostracon/abci/types" 11 ) 12 13 type Application struct { 14 ocabci.BaseApplication 15 16 hashCount int 17 txCount int 18 serial bool 19 } 20 21 func NewApplication(serial bool) *Application { 22 return &Application{serial: serial} 23 } 24 25 func (app *Application) Info(req types.RequestInfo) types.ResponseInfo { 26 return types.ResponseInfo{Data: fmt.Sprintf("{\"hashes\":%v,\"txs\":%v}", app.hashCount, app.txCount)} 27 } 28 29 func (app *Application) SetOption(req types.RequestSetOption) types.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 types.ResponseSetOption{ 38 Error: fmt.Sprintf("Unknown key (%s) or value (%s)", key, value), 39 } 40 */ 41 return types.ResponseSetOption{} 42 } 43 44 return types.ResponseSetOption{} 45 } 46 47 func (app *Application) DeliverTx(req types.RequestDeliverTx) types.ResponseDeliverTx { 48 if app.serial { 49 if len(req.Tx) > 8 { 50 return types.ResponseDeliverTx{ 51 Code: code.CodeTypeEncodingError, 52 Log: fmt.Sprintf("Max tx size is 8 bytes, got %d", len(req.Tx))} 53 } 54 tx8 := make([]byte, 8) 55 copy(tx8[len(tx8)-len(req.Tx):], req.Tx) 56 txValue := binary.BigEndian.Uint64(tx8) 57 if txValue != uint64(app.txCount) { 58 return types.ResponseDeliverTx{ 59 Code: code.CodeTypeBadNonce, 60 Log: fmt.Sprintf("Invalid nonce. Expected %v, got %v", app.txCount, txValue)} 61 } 62 } 63 app.txCount++ 64 return types.ResponseDeliverTx{Code: code.CodeTypeOK} 65 } 66 67 func (app *Application) CheckTxSync(req types.RequestCheckTx) ocabci.ResponseCheckTx { 68 return app.checkTx(req) 69 } 70 71 func (app *Application) CheckTxAsync(req types.RequestCheckTx, callback ocabci.CheckTxCallback) { 72 callback(app.checkTx(req)) 73 } 74 75 func (app *Application) checkTx(req types.RequestCheckTx) ocabci.ResponseCheckTx { 76 if app.serial { 77 if len(req.Tx) > 8 { 78 return ocabci.ResponseCheckTx{ 79 Code: code.CodeTypeEncodingError, 80 Log: fmt.Sprintf("Max tx size is 8 bytes, got %d", len(req.Tx))} 81 } 82 tx8 := make([]byte, 8) 83 copy(tx8[len(tx8)-len(req.Tx):], req.Tx) 84 txValue := binary.BigEndian.Uint64(tx8) 85 if txValue < uint64(app.txCount) { 86 return ocabci.ResponseCheckTx{ 87 Code: code.CodeTypeBadNonce, 88 Log: fmt.Sprintf("Invalid nonce. Expected >= %v, got %v", app.txCount, txValue)} 89 } 90 } 91 return ocabci.ResponseCheckTx{Code: code.CodeTypeOK} 92 } 93 94 func (app *Application) Commit() (resp types.ResponseCommit) { 95 app.hashCount++ 96 if app.txCount == 0 { 97 return types.ResponseCommit{} 98 } 99 hash := make([]byte, 8) 100 binary.BigEndian.PutUint64(hash, uint64(app.txCount)) 101 return types.ResponseCommit{Data: hash} 102 } 103 104 func (app *Application) Query(reqQuery types.RequestQuery) types.ResponseQuery { 105 switch reqQuery.Path { 106 case "hash": 107 return types.ResponseQuery{Value: []byte(fmt.Sprintf("%v", app.hashCount))} 108 case "tx": 109 return types.ResponseQuery{Value: []byte(fmt.Sprintf("%v", app.txCount))} 110 default: 111 return types.ResponseQuery{Log: fmt.Sprintf("Invalid query path. Expected hash or tx, got %v", reqQuery.Path)} 112 } 113 }