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.

87 lines
1.9 KiB

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