Browse Source

CheckTx and DeliverTx return ResponseCheckTx and ResponseDeliverTx respectively

Commit now returns ResponseCommit
pull/1780/head
Anton Kaliaev 7 years ago
parent
commit
3a3d508e5c
No known key found for this signature in database GPG Key ID: 7B6881D965918214
7 changed files with 74 additions and 44 deletions
  1. +3
    -3
      client/local_client.go
  2. +20
    -11
      example/counter/counter.go
  3. +8
    -8
      example/dummy/dummy.go
  4. +26
    -13
      example/dummy/persistent_dummy.go
  5. +3
    -3
      types/application.go
  6. +6
    -6
      types/base_app.go
  7. +8
    -0
      types/result.go

+ 3
- 3
client/local_client.go View File

@ -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()


+ 20
- 11
example/counter/counter.go View File

@ -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 {


+ 8
- 8
example/dummy/dummy.go View File

@ -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) {


+ 26
- 13
example/dummy/persistent_dummy.go View File

@ -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}
}

+ 3
- 3
types/application.go View File

@ -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
}
//------------------------------------


+ 6
- 6
types/base_app.go View File

@ -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 {


+ 8
- 0
types/result.go View File

@ -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…
Cancel
Save