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.

104 lines
2.9 KiB

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