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.

138 lines
4.2 KiB

7 years ago
7 years ago
7 years ago
  1. package types
  2. import (
  3. "bytes"
  4. "errors"
  5. "fmt"
  6. amino "github.com/tendermint/go-amino"
  7. abci "github.com/tendermint/tendermint/abci/types"
  8. "github.com/tendermint/tendermint/crypto/merkle"
  9. "github.com/tendermint/tendermint/crypto/tmhash"
  10. cmn "github.com/tendermint/tendermint/libs/common"
  11. )
  12. // Tx is an arbitrary byte array.
  13. // NOTE: Tx has no types at this level, so when wire encoded it's just length-prefixed.
  14. // Might we want types here ?
  15. type Tx []byte
  16. // Hash computes the TMHASH hash of the wire encoded transaction.
  17. func (tx Tx) Hash() []byte {
  18. return tmhash.Sum(tx)
  19. }
  20. // String returns the hex-encoded transaction as a string.
  21. func (tx Tx) String() string {
  22. return fmt.Sprintf("Tx{%X}", []byte(tx))
  23. }
  24. // Txs is a slice of Tx.
  25. type Txs []Tx
  26. // Hash returns the Merkle root hash of the transaction hashes.
  27. // i.e. the leaves of the tree are the hashes of the txs.
  28. func (txs Txs) Hash() []byte {
  29. // These allocations will be removed once Txs is switched to [][]byte,
  30. // ref #2603. This is because golang does not allow type casting slices without unsafe
  31. txBzs := make([][]byte, len(txs))
  32. for i := 0; i < len(txs); i++ {
  33. txBzs[i] = txs[i].Hash()
  34. }
  35. return merkle.SimpleHashFromByteSlices(txBzs)
  36. }
  37. // Index returns the index of this transaction in the list, or -1 if not found
  38. func (txs Txs) Index(tx Tx) int {
  39. for i := range txs {
  40. if bytes.Equal(txs[i], tx) {
  41. return i
  42. }
  43. }
  44. return -1
  45. }
  46. // IndexByHash returns the index of this transaction hash in the list, or -1 if not found
  47. func (txs Txs) IndexByHash(hash []byte) int {
  48. for i := range txs {
  49. if bytes.Equal(txs[i].Hash(), hash) {
  50. return i
  51. }
  52. }
  53. return -1
  54. }
  55. // Proof returns a simple merkle proof for this node.
  56. // Panics if i < 0 or i >= len(txs)
  57. // TODO: optimize this!
  58. func (txs Txs) Proof(i int) TxProof {
  59. l := len(txs)
  60. bzs := make([][]byte, l)
  61. for i := 0; i < l; i++ {
  62. bzs[i] = txs[i].Hash()
  63. }
  64. root, proofs := merkle.SimpleProofsFromByteSlices(bzs)
  65. return TxProof{
  66. RootHash: root,
  67. Data: txs[i],
  68. Proof: *proofs[i],
  69. }
  70. }
  71. // TxProof represents a Merkle proof of the presence of a transaction in the Merkle tree.
  72. type TxProof struct {
  73. RootHash cmn.HexBytes `json:"root_hash"`
  74. Data Tx `json:"data"`
  75. Proof merkle.SimpleProof `json:"proof"`
  76. }
  77. // Leaf returns the hash(tx), which is the leaf in the merkle tree which this proof refers to.
  78. func (tp TxProof) Leaf() []byte {
  79. return tp.Data.Hash()
  80. }
  81. // Validate verifies the proof. It returns nil if the RootHash matches the dataHash argument,
  82. // and if the proof is internally consistent. Otherwise, it returns a sensible error.
  83. func (tp TxProof) Validate(dataHash []byte) error {
  84. if !bytes.Equal(dataHash, tp.RootHash) {
  85. return errors.New("Proof matches different data hash")
  86. }
  87. if tp.Proof.Index < 0 {
  88. return errors.New("Proof index cannot be negative")
  89. }
  90. if tp.Proof.Total <= 0 {
  91. return errors.New("Proof total must be positive")
  92. }
  93. valid := tp.Proof.Verify(tp.RootHash, tp.Leaf())
  94. if valid != nil {
  95. return errors.New("Proof is not internally consistent")
  96. }
  97. return nil
  98. }
  99. // TxResult contains results of executing the transaction.
  100. //
  101. // One usage is indexing transaction results.
  102. type TxResult struct {
  103. Height int64 `json:"height"`
  104. Index uint32 `json:"index"`
  105. Tx Tx `json:"tx"`
  106. Result abci.ResponseDeliverTx `json:"result"`
  107. }
  108. // ComputeAminoOverhead calculates the overhead for amino encoding a transaction.
  109. // The overhead consists of varint encoding the field number and the wire type
  110. // (= length-delimited = 2), and another varint encoding the length of the
  111. // transaction.
  112. // The field number can be the field number of the particular transaction, or
  113. // the field number of the parenting struct that contains the transactions []Tx
  114. // as a field (this field number is repeated for each contained Tx).
  115. // If some []Tx are encoded directly (without a parenting struct), the default
  116. // fieldNum is also 1 (see BinFieldNum in amino.MarshalBinaryBare).
  117. func ComputeAminoOverhead(tx Tx, fieldNum int) int64 {
  118. fnum := uint64(fieldNum)
  119. typ3AndFieldNum := (fnum << 3) | uint64(amino.Typ3_ByteLength)
  120. return int64(amino.UvarintSize(typ3AndFieldNum)) + int64(amino.UvarintSize(uint64(len(tx))))
  121. }