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.

114 lines
2.6 KiB

  1. package types
  2. import (
  3. "bytes"
  4. "errors"
  5. abci "github.com/tendermint/abci/types"
  6. "github.com/tendermint/go-wire/data"
  7. "github.com/tendermint/tmlibs/merkle"
  8. )
  9. type Tx []byte
  10. // NOTE: this is the hash of the go-wire encoded Tx.
  11. // Tx has no types at this level, so just length-prefixed.
  12. // Alternatively, it may make sense to add types here and let
  13. // []byte be type 0x1 so we can have versioned txs if need be in the future.
  14. func (tx Tx) Hash() []byte {
  15. return merkle.SimpleHashFromBinary(tx)
  16. }
  17. type Txs []Tx
  18. func (txs Txs) Hash() []byte {
  19. // Recursive impl.
  20. // Copied from tmlibs/merkle to avoid allocations
  21. switch len(txs) {
  22. case 0:
  23. return nil
  24. case 1:
  25. return txs[0].Hash()
  26. default:
  27. left := Txs(txs[:(len(txs)+1)/2]).Hash()
  28. right := Txs(txs[(len(txs)+1)/2:]).Hash()
  29. return merkle.SimpleHashFromTwoHashes(left, right)
  30. }
  31. }
  32. // Index returns the index of this transaction in the list, or -1 if not found
  33. func (txs Txs) Index(tx Tx) int {
  34. for i := range txs {
  35. if bytes.Equal(txs[i], tx) {
  36. return i
  37. }
  38. }
  39. return -1
  40. }
  41. // Index returns the index of this transaction hash in the list, or -1 if not found
  42. func (txs Txs) IndexByHash(hash []byte) int {
  43. for i := range txs {
  44. if bytes.Equal(txs[i].Hash(), hash) {
  45. return i
  46. }
  47. }
  48. return -1
  49. }
  50. // Proof returns a simple merkle proof for this node.
  51. //
  52. // Panics if i < 0 or i >= len(txs)
  53. //
  54. // TODO: optimize this!
  55. func (txs Txs) Proof(i int) TxProof {
  56. l := len(txs)
  57. hashables := make([]merkle.Hashable, l)
  58. for i := 0; i < l; i++ {
  59. hashables[i] = txs[i]
  60. }
  61. root, proofs := merkle.SimpleProofsFromHashables(hashables)
  62. return TxProof{
  63. Index: i,
  64. Total: l,
  65. RootHash: root,
  66. Data: txs[i],
  67. Proof: *proofs[i],
  68. }
  69. }
  70. type TxProof struct {
  71. Index, Total int
  72. RootHash data.Bytes
  73. Data Tx
  74. Proof merkle.SimpleProof
  75. }
  76. func (tp TxProof) LeafHash() []byte {
  77. return tp.Data.Hash()
  78. }
  79. // Validate returns nil if it matches the dataHash, and is internally consistent
  80. // otherwise, returns a sensible error
  81. func (tp TxProof) Validate(dataHash []byte) error {
  82. if !bytes.Equal(dataHash, tp.RootHash) {
  83. return errors.New("Proof matches different data hash")
  84. }
  85. valid := tp.Proof.Verify(tp.Index, tp.Total, tp.LeafHash(), tp.RootHash)
  86. if !valid {
  87. return errors.New("Proof is not internally consistent")
  88. }
  89. return nil
  90. }
  91. // TxResult contains results of executing the transaction.
  92. //
  93. // One usage is indexing transaction results.
  94. type TxResult struct {
  95. Height uint64 `json:"height"`
  96. Index uint32 `json:"index"`
  97. Tx Tx `json:"tx"`
  98. Result abci.ResponseDeliverTx `json:"result"`
  99. }