github.com/okex/exchain@v1.8.0/libs/tendermint/abci/example/counter/counter.go (about)

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