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