diff --git a/client/local_client.go b/client/local_client.go index 539c1eef0..89f984184 100644 --- a/client/local_client.go +++ b/client/local_client.go @@ -164,14 +164,14 @@ func (app *localClient) SetOptionSync(key string, value string) (res types.Resul return types.OK.SetLog(log) } -func (app *localClient) DeliverTxSync(tx []byte) (res types.Result) { +func (app *localClient) DeliverTxSync(tx []byte) (res types.ResponseDeliverTx) { app.mtx.Lock() res = app.Application.DeliverTx(tx) app.mtx.Unlock() return res } -func (app *localClient) CheckTxSync(tx []byte) (res types.Result) { +func (app *localClient) CheckTxSync(tx []byte) (res types.ResponseCheckTx) { app.mtx.Lock() res = app.Application.CheckTx(tx) app.mtx.Unlock() @@ -185,7 +185,7 @@ func (app *localClient) QuerySync(reqQuery types.RequestQuery) (resQuery types.R return resQuery, nil } -func (app *localClient) CommitSync() (res types.Result) { +func (app *localClient) CommitSync() (res types.ResponseCommit) { app.mtx.Lock() res = app.Application.Commit() app.mtx.Unlock() diff --git a/example/counter/counter.go b/example/counter/counter.go index d2478ae28..65cac4a0e 100644 --- a/example/counter/counter.go +++ b/example/counter/counter.go @@ -2,6 +2,7 @@ package counter import ( "encoding/binary" + "fmt" "github.com/tendermint/abci/types" cmn "github.com/tendermint/tmlibs/common" @@ -30,45 +31,53 @@ func (app *CounterApplication) SetOption(key string, value string) (log string) return "" } -func (app *CounterApplication) DeliverTx(tx []byte) types.Result { +func (app *CounterApplication) DeliverTx(tx []byte) types.ResponseDeliverTx { if app.serial { if len(tx) > 8 { - return types.ErrEncodingError.SetLog(cmn.Fmt("Max tx size is 8 bytes, got %d", len(tx))) + return types.ResponseDeliverTx{ + Code: types.CodeType_EncodingError, + Log: fmt.Sprintf("Max tx size is 8 bytes, got %d", len(tx))} } tx8 := make([]byte, 8) copy(tx8[len(tx8)-len(tx):], tx) txValue := binary.BigEndian.Uint64(tx8) if txValue != uint64(app.txCount) { - return types.ErrBadNonce.SetLog(cmn.Fmt("Invalid nonce. Expected %v, got %v", app.txCount, txValue)) + return types.ResponseDeliverTx{ + Code: types.CodeType_BadNonce, + Log: fmt.Sprintf("Invalid nonce. Expected %v, got %v", app.txCount, txValue)} } } app.txCount++ - return types.OK + return types.ResponseDeliverTx{Code: types.CodeType_OK} } -func (app *CounterApplication) CheckTx(tx []byte) types.Result { +func (app *CounterApplication) CheckTx(tx []byte) types.ResponseCheckTx { if app.serial { if len(tx) > 8 { - return types.ErrEncodingError.SetLog(cmn.Fmt("Max tx size is 8 bytes, got %d", len(tx))) + return types.ResponseCheckTx{ + Code: types.CodeType_EncodingError, + Log: fmt.Sprintf("Max tx size is 8 bytes, got %d", len(tx))} } tx8 := make([]byte, 8) copy(tx8[len(tx8)-len(tx):], tx) txValue := binary.BigEndian.Uint64(tx8) if txValue < uint64(app.txCount) { - return types.ErrBadNonce.SetLog(cmn.Fmt("Invalid nonce. Expected >= %v, got %v", app.txCount, txValue)) + return types.ResponseCheckTx{ + Code: types.CodeType_BadNonce, + Log: fmt.Sprintf("Invalid nonce. Expected >= %v, got %v", app.txCount, txValue)} } } - return types.OK + return types.ResponseCheckTx{Code: types.CodeType_OK} } -func (app *CounterApplication) Commit() types.Result { +func (app *CounterApplication) Commit() (resp types.ResponseCommit) { app.hashCount++ if app.txCount == 0 { - return types.OK + return types.ResponseCommit{Code: types.CodeType_OK} } hash := make([]byte, 8) binary.BigEndian.PutUint64(hash, uint64(app.txCount)) - return types.NewResultOK(hash, "") + return types.ResponseCommit{Code: types.CodeType_OK, Data: hash} } func (app *CounterApplication) Query(reqQuery types.RequestQuery) types.ResponseQuery { diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index 7e95c859b..a4edacac4 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -1,12 +1,12 @@ package dummy import ( + "fmt" "strings" "github.com/tendermint/abci/types" wire "github.com/tendermint/go-wire" "github.com/tendermint/iavl" - cmn "github.com/tendermint/tmlibs/common" dbm "github.com/tendermint/tmlibs/db" ) @@ -22,25 +22,25 @@ func NewDummyApplication() *DummyApplication { } func (app *DummyApplication) Info(req types.RequestInfo) (resInfo types.ResponseInfo) { - return types.ResponseInfo{Data: cmn.Fmt("{\"size\":%v}", app.state.Size())} + return types.ResponseInfo{Data: fmt.Sprintf("{\"size\":%v}", app.state.Size())} } // tx is either "key=value" or just arbitrary bytes -func (app *DummyApplication) DeliverTx(tx []byte) types.Result { +func (app *DummyApplication) DeliverTx(tx []byte) types.ResponseDeliverTx { parts := strings.Split(string(tx), "=") if len(parts) == 2 { app.state.Set([]byte(parts[0]), []byte(parts[1])) } else { app.state.Set(tx, tx) } - return types.OK + return types.ResponseDeliverTx{Code: types.CodeType_OK} } -func (app *DummyApplication) CheckTx(tx []byte) types.Result { - return types.OK +func (app *DummyApplication) CheckTx(tx []byte) types.ResponseCheckTx { + return types.ResponseCheckTx{Code: types.CodeType_OK} } -func (app *DummyApplication) Commit() types.Result { +func (app *DummyApplication) Commit() types.ResponseCommit { // Save a new version var hash []byte var err error @@ -55,7 +55,7 @@ func (app *DummyApplication) Commit() types.Result { } } - return types.NewResultOK(hash, "") + return types.ResponseCommit{Code: types.CodeType_OK, Data: hash} } func (app *DummyApplication) Query(reqQuery types.RequestQuery) (resQuery types.ResponseQuery) { diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index 4c4801755..8fa112820 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -3,6 +3,7 @@ package dummy import ( "bytes" "encoding/hex" + "fmt" "strconv" "strings" @@ -61,7 +62,7 @@ func (app *PersistentDummyApplication) SetOption(key string, value string) (log } // tx is either "val:pubkey/power" or "key=value" or just arbitrary bytes -func (app *PersistentDummyApplication) DeliverTx(tx []byte) types.Result { +func (app *PersistentDummyApplication) DeliverTx(tx []byte) types.ResponseDeliverTx { // if it starts with "val:", update the validator set // format is "val:pubkey/power" if isValidatorTx(tx) { @@ -74,12 +75,12 @@ func (app *PersistentDummyApplication) DeliverTx(tx []byte) types.Result { return app.app.DeliverTx(tx) } -func (app *PersistentDummyApplication) CheckTx(tx []byte) types.Result { +func (app *PersistentDummyApplication) CheckTx(tx []byte) types.ResponseCheckTx { return app.app.CheckTx(tx) } // Commit will panic if InitChain was not called -func (app *PersistentDummyApplication) Commit() types.Result { +func (app *PersistentDummyApplication) Commit() types.ResponseCommit { // Save a new version for next height height := app.app.state.LatestVersion() + 1 @@ -93,7 +94,7 @@ func (app *PersistentDummyApplication) Commit() types.Result { } app.logger.Info("Commit block", "height", height, "root", appHash) - return types.NewResultOK(appHash, "") + return types.ResponseCommit{Code: types.CodeType_OK, Data: appHash} } func (app *PersistentDummyApplication) Query(reqQuery types.RequestQuery) types.ResponseQuery { @@ -148,30 +149,38 @@ func isValidatorTx(tx []byte) bool { } // format is "val:pubkey1/power1,addr2/power2,addr3/power3"tx -func (app *PersistentDummyApplication) execValidatorTx(tx []byte) types.Result { +func (app *PersistentDummyApplication) execValidatorTx(tx []byte) types.ResponseDeliverTx { tx = tx[len(ValidatorSetChangePrefix):] //get the pubkey and power pubKeyAndPower := strings.Split(string(tx), "/") if len(pubKeyAndPower) != 2 { - return types.ErrEncodingError.SetLog(cmn.Fmt("Expected 'pubkey/power'. Got %v", pubKeyAndPower)) + return types.ResponseDeliverTx{ + Code: types.CodeType_EncodingError, + Log: fmt.Sprintf("Expected 'pubkey/power'. Got %v", pubKeyAndPower)} } pubkeyS, powerS := pubKeyAndPower[0], pubKeyAndPower[1] // decode the pubkey, ensuring its go-crypto encoded pubkey, err := hex.DecodeString(pubkeyS) if err != nil { - return types.ErrEncodingError.SetLog(cmn.Fmt("Pubkey (%s) is invalid hex", pubkeyS)) + return types.ResponseDeliverTx{ + Code: types.CodeType_EncodingError, + Log: fmt.Sprintf("Pubkey (%s) is invalid hex", pubkeyS)} } _, err = crypto.PubKeyFromBytes(pubkey) if err != nil { - return types.ErrEncodingError.SetLog(cmn.Fmt("Pubkey (%X) is invalid go-crypto encoded", pubkey)) + return types.ResponseDeliverTx{ + Code: types.CodeType_EncodingError, + Log: fmt.Sprintf("Pubkey (%X) is invalid go-crypto encoded", pubkey)} } // decode the power power, err := strconv.Atoi(powerS) if err != nil { - return types.ErrEncodingError.SetLog(cmn.Fmt("Power (%s) is not an int", powerS)) + return types.ResponseDeliverTx{ + Code: types.CodeType_EncodingError, + Log: fmt.Sprintf("Power (%s) is not an int", powerS)} } // update @@ -179,19 +188,23 @@ func (app *PersistentDummyApplication) execValidatorTx(tx []byte) types.Result { } // add, update, or remove a validator -func (app *PersistentDummyApplication) updateValidator(v *types.Validator) types.Result { +func (app *PersistentDummyApplication) updateValidator(v *types.Validator) types.ResponseDeliverTx { key := []byte("val:" + string(v.PubKey)) if v.Power == 0 { // remove validator if !app.app.state.Has(key) { - return types.ErrUnauthorized.SetLog(cmn.Fmt("Cannot remove non-existent validator %X", key)) + return types.ResponseDeliverTx{ + Code: types.CodeType_Unauthorized, + Log: fmt.Sprintf("Cannot remove non-existent validator %X", key)} } app.app.state.Remove(key) } else { // add or update validator value := bytes.NewBuffer(make([]byte, 0)) if err := types.WriteMessage(v, value); err != nil { - return types.ErrInternalError.SetLog(cmn.Fmt("Error encoding validator: %v", err)) + return types.ResponseDeliverTx{ + Code: types.CodeType_InternalError, + Log: fmt.Sprintf("Error encoding validator: %v", err)} } app.app.state.Set(key, value.Bytes()) } @@ -199,5 +212,5 @@ func (app *PersistentDummyApplication) updateValidator(v *types.Validator) types // we only update the changes array if we successfully updated the tree app.changes = append(app.changes, v) - return types.OK + return types.ResponseDeliverTx{Code: types.CodeType_OK} } diff --git a/types/application.go b/types/application.go index 51a1869b0..ed9b0d20d 100644 --- a/types/application.go +++ b/types/application.go @@ -13,14 +13,14 @@ type Application interface { Query(RequestQuery) ResponseQuery // Query for state // Mempool Connection - CheckTx(tx []byte) Result // Validate a tx for the mempool + CheckTx(tx []byte) ResponseCheckTx // Validate a tx for the mempool // Consensus Connection InitChain(RequestInitChain) // Initialize blockchain with validators and other info from TendermintCore BeginBlock(RequestBeginBlock) // Signals the beginning of a block - DeliverTx(tx []byte) Result // Deliver a tx for full processing + DeliverTx(tx []byte) ResponseDeliverTx // Deliver a tx for full processing EndBlock(height uint64) ResponseEndBlock // Signals the end of a block, returns changes to the validator set - Commit() Result // Commit the state and return the application Merkle root hash + Commit() ResponseCommit // Commit the state and return the application Merkle root hash } //------------------------------------ diff --git a/types/base_app.go b/types/base_app.go index 60bf43880..75fdae8d7 100644 --- a/types/base_app.go +++ b/types/base_app.go @@ -15,16 +15,16 @@ func (BaseApplication) SetOption(key string, value string) (log string) { return "" } -func (BaseApplication) DeliverTx(tx []byte) Result { - return NewResultOK(nil, "") +func (BaseApplication) DeliverTx(tx []byte) ResponseDeliverTx { + return ResponseDeliverTx{} } -func (BaseApplication) CheckTx(tx []byte) Result { - return NewResultOK(nil, "") +func (BaseApplication) CheckTx(tx []byte) ResponseCheckTx { + return ResponseCheckTx{} } -func (BaseApplication) Commit() Result { - return NewResultOK([]byte("nil"), "") +func (BaseApplication) Commit() ResponseCommit { + return ResponseCommit{Code: CodeType_OK, Data: []byte("nil")} } func (BaseApplication) Query(req RequestQuery) ResponseQuery { diff --git a/types/result.go b/types/result.go index 96dd4e795..ffd8966a9 100644 --- a/types/result.go +++ b/types/result.go @@ -106,6 +106,10 @@ func (r *ResponseCheckTx) Result() Result { } } +func (r ResponseCheckTx) IsErr() bool { + return r.Code != CodeType_OK +} + // Convert ResponseDeliverTx to standard Result func (r *ResponseDeliverTx) Result() Result { return Result{ @@ -116,6 +120,10 @@ func (r *ResponseDeliverTx) Result() Result { } } +func (r ResponseDeliverTx) IsErr() bool { + return r.Code != CodeType_OK +} + type ResultQuery struct { Code CodeType `json:"code"` Index int64 `json:"index"`