mirror of
https://github.com/fluencelabs/tendermint
synced 2025-04-25 06:42:16 +00:00
CheckTx and DeliverTx return ResponseCheckTx and ResponseDeliverTx respectively
Commit now returns ResponseCommit
This commit is contained in:
parent
92801dbd72
commit
3a3d508e5c
@ -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()
|
||||
|
@ -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 {
|
||||
|
@ -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) {
|
||||
|
@ -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}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
//------------------------------------
|
||||
|
@ -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 {
|
||||
|
@ -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"`
|
||||
|
Loading…
x
Reference in New Issue
Block a user