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.

139 lines
4.1 KiB

  1. package merkle
  2. import (
  3. "bytes"
  4. "errors"
  5. "fmt"
  6. tmcrypto "github.com/tendermint/tendermint/proto/tendermint/crypto"
  7. )
  8. //----------------------------------------
  9. // ProofOp gets converted to an instance of ProofOperator:
  10. // ProofOperator is a layer for calculating intermediate Merkle roots
  11. // when a series of Merkle trees are chained together.
  12. // Run() takes leaf values from a tree and returns the Merkle
  13. // root for the corresponding tree. It takes and returns a list of bytes
  14. // to allow multiple leaves to be part of a single proof, for instance in a range proof.
  15. // ProofOp() encodes the ProofOperator in a generic way so it can later be
  16. // decoded with OpDecoder.
  17. type ProofOperator interface {
  18. Run([][]byte) ([][]byte, error)
  19. GetKey() []byte
  20. ProofOp() tmcrypto.ProofOp
  21. }
  22. //----------------------------------------
  23. // Operations on a list of ProofOperators
  24. // ProofOperators is a slice of ProofOperator(s).
  25. // Each operator will be applied to the input value sequentially
  26. // and the last Merkle root will be verified with already known data
  27. type ProofOperators []ProofOperator
  28. func (poz ProofOperators) VerifyValue(root []byte, keypath string, value []byte) (err error) {
  29. return poz.Verify(root, keypath, [][]byte{value})
  30. }
  31. func (poz ProofOperators) Verify(root []byte, keypath string, args [][]byte) (err error) {
  32. keys, err := KeyPathToKeys(keypath)
  33. if err != nil {
  34. return
  35. }
  36. for i, op := range poz {
  37. key := op.GetKey()
  38. if len(key) != 0 {
  39. if len(keys) == 0 {
  40. return fmt.Errorf("key path has insufficient # of parts: expected no more keys but got %+v", string(key))
  41. }
  42. lastKey := keys[len(keys)-1]
  43. if !bytes.Equal(lastKey, key) {
  44. return fmt.Errorf("key mismatch on operation #%d: expected %+v but got %+v", i, string(lastKey), string(key))
  45. }
  46. keys = keys[:len(keys)-1]
  47. }
  48. args, err = op.Run(args)
  49. if err != nil {
  50. return
  51. }
  52. }
  53. if !bytes.Equal(root, args[0]) {
  54. return fmt.Errorf("calculated root hash is invalid: expected %+v but got %+v", root, args[0])
  55. }
  56. if len(keys) != 0 {
  57. return errors.New("keypath not consumed all")
  58. }
  59. return nil
  60. }
  61. //----------------------------------------
  62. // ProofRuntime - main entrypoint
  63. type OpDecoder func(tmcrypto.ProofOp) (ProofOperator, error)
  64. type ProofRuntime struct {
  65. decoders map[string]OpDecoder
  66. }
  67. func NewProofRuntime() *ProofRuntime {
  68. return &ProofRuntime{
  69. decoders: make(map[string]OpDecoder),
  70. }
  71. }
  72. func (prt *ProofRuntime) RegisterOpDecoder(typ string, dec OpDecoder) {
  73. _, ok := prt.decoders[typ]
  74. if ok {
  75. panic("already registered for type " + typ)
  76. }
  77. prt.decoders[typ] = dec
  78. }
  79. func (prt *ProofRuntime) Decode(pop tmcrypto.ProofOp) (ProofOperator, error) {
  80. decoder := prt.decoders[pop.Type]
  81. if decoder == nil {
  82. return nil, fmt.Errorf("unrecognized proof type %v", pop.Type)
  83. }
  84. return decoder(pop)
  85. }
  86. func (prt *ProofRuntime) DecodeProof(proof *tmcrypto.ProofOps) (ProofOperators, error) {
  87. poz := make(ProofOperators, 0, len(proof.Ops))
  88. for _, pop := range proof.Ops {
  89. operator, err := prt.Decode(pop)
  90. if err != nil {
  91. return nil, fmt.Errorf("decoding a proof operator: %w", err)
  92. }
  93. poz = append(poz, operator)
  94. }
  95. return poz, nil
  96. }
  97. func (prt *ProofRuntime) VerifyValue(proof *tmcrypto.ProofOps, root []byte, keypath string, value []byte) (err error) {
  98. return prt.Verify(proof, root, keypath, [][]byte{value})
  99. }
  100. // TODO In the long run we'll need a method of classifcation of ops,
  101. // whether existence or absence or perhaps a third?
  102. func (prt *ProofRuntime) VerifyAbsence(proof *tmcrypto.ProofOps, root []byte, keypath string) (err error) {
  103. return prt.Verify(proof, root, keypath, nil)
  104. }
  105. func (prt *ProofRuntime) Verify(proof *tmcrypto.ProofOps, root []byte, keypath string, args [][]byte) (err error) {
  106. poz, err := prt.DecodeProof(proof)
  107. if err != nil {
  108. return fmt.Errorf("decoding proof: %w", err)
  109. }
  110. return poz.Verify(root, keypath, args)
  111. }
  112. // DefaultProofRuntime only knows about value proofs.
  113. // To use e.g. IAVL proofs, register op-decoders as
  114. // defined in the IAVL package.
  115. func DefaultProofRuntime() (prt *ProofRuntime) {
  116. prt = NewProofRuntime()
  117. prt.RegisterOpDecoder(ProofOpValue, ValueOpDecoder)
  118. return
  119. }