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  }