You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

103 lines
2.9 KiB

9 years ago
9 years ago
9 years ago
8 years ago
9 years ago
9 years ago
9 years ago
9 years ago
7 years ago
7 years ago
9 years ago
7 years ago
7 years ago
9 years ago
9 years ago
  1. package counter
  2. import (
  3. "encoding/binary"
  4. "fmt"
  5. "github.com/tendermint/tendermint/abci/example/code"
  6. "github.com/tendermint/tendermint/abci/types"
  7. )
  8. type CounterApplication struct {
  9. types.BaseApplication
  10. hashCount int
  11. txCount int
  12. serial bool
  13. }
  14. func NewCounterApplication(serial bool) *CounterApplication {
  15. return &CounterApplication{serial: serial}
  16. }
  17. func (app *CounterApplication) Info(req types.RequestInfo) types.ResponseInfo {
  18. return types.ResponseInfo{Data: fmt.Sprintf("{\"hashes\":%v,\"txs\":%v}", app.hashCount, app.txCount)}
  19. }
  20. func (app *CounterApplication) SetOption(req types.RequestSetOption) types.ResponseSetOption {
  21. key, value := req.Key, req.Value
  22. if key == "serial" && value == "on" {
  23. app.serial = true
  24. } else {
  25. /*
  26. TODO Panic and have the ABCI server pass an exception.
  27. The client can call SetOptionSync() and get an `error`.
  28. return types.ResponseSetOption{
  29. Error: fmt.Sprintf("Unknown key (%s) or value (%s)", key, value),
  30. }
  31. */
  32. return types.ResponseSetOption{}
  33. }
  34. return types.ResponseSetOption{}
  35. }
  36. func (app *CounterApplication) DeliverTx(tx []byte) types.ResponseDeliverTx {
  37. if app.serial {
  38. if len(tx) > 8 {
  39. return types.ResponseDeliverTx{
  40. Code: code.CodeTypeEncodingError,
  41. Log: fmt.Sprintf("Max tx size is 8 bytes, got %d", len(tx))}
  42. }
  43. tx8 := make([]byte, 8)
  44. copy(tx8[len(tx8)-len(tx):], tx)
  45. txValue := binary.BigEndian.Uint64(tx8)
  46. if txValue != uint64(app.txCount) {
  47. return types.ResponseDeliverTx{
  48. Code: code.CodeTypeBadNonce,
  49. Log: fmt.Sprintf("Invalid nonce. Expected %v, got %v", app.txCount, txValue)}
  50. }
  51. }
  52. app.txCount++
  53. return types.ResponseDeliverTx{Code: code.CodeTypeOK}
  54. }
  55. func (app *CounterApplication) CheckTx(tx []byte) types.ResponseCheckTx {
  56. if app.serial {
  57. if len(tx) > 8 {
  58. return types.ResponseCheckTx{
  59. Code: code.CodeTypeEncodingError,
  60. Log: fmt.Sprintf("Max tx size is 8 bytes, got %d", len(tx))}
  61. }
  62. tx8 := make([]byte, 8)
  63. copy(tx8[len(tx8)-len(tx):], tx)
  64. txValue := binary.BigEndian.Uint64(tx8)
  65. if txValue < uint64(app.txCount) {
  66. return types.ResponseCheckTx{
  67. Code: code.CodeTypeBadNonce,
  68. Log: fmt.Sprintf("Invalid nonce. Expected >= %v, got %v", app.txCount, txValue)}
  69. }
  70. }
  71. return types.ResponseCheckTx{Code: code.CodeTypeOK}
  72. }
  73. func (app *CounterApplication) Commit() (resp types.ResponseCommit) {
  74. app.hashCount++
  75. if app.txCount == 0 {
  76. return types.ResponseCommit{}
  77. }
  78. hash := make([]byte, 8)
  79. binary.BigEndian.PutUint64(hash, uint64(app.txCount))
  80. return types.ResponseCommit{Data: hash}
  81. }
  82. func (app *CounterApplication) Query(reqQuery types.RequestQuery) types.ResponseQuery {
  83. switch reqQuery.Path {
  84. case "hash":
  85. return types.ResponseQuery{Value: []byte(fmt.Sprintf("%v", app.hashCount))}
  86. case "tx":
  87. return types.ResponseQuery{Value: []byte(fmt.Sprintf("%v", app.txCount))}
  88. default:
  89. return types.ResponseQuery{Log: fmt.Sprintf("Invalid query path. Expected hash or tx, got %v", reqQuery.Path)}
  90. }
  91. }