github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/tm2/pkg/iavl/proof_iavl_value.go (about) 1 package iavl 2 3 import ( 4 "fmt" 5 6 "github.com/gnolang/gno/tm2/pkg/crypto/merkle" 7 "github.com/gnolang/gno/tm2/pkg/errors" 8 ) 9 10 const ProofOpIAVLValue = "iavl:v" 11 12 // IAVLValueOp takes a key and a single value as argument and 13 // produces the root hash. 14 // 15 // If the produced root hash matches the expected hash, the proof 16 // is good. 17 type IAVLValueOp struct { 18 // Encoded in ProofOp.Key. 19 key []byte 20 21 // To encode in ProofOp.Data. 22 // Proof is nil for an empty tree. 23 // The hash of an empty tree is nil. 24 Proof *RangeProof `json:"proof"` 25 } 26 27 var _ merkle.ProofOperator = IAVLValueOp{} 28 29 func NewIAVLValueOp(key []byte, proof *RangeProof) IAVLValueOp { 30 return IAVLValueOp{ 31 key: key, 32 Proof: proof, 33 } 34 } 35 36 func IAVLValueOpDecoder(pop merkle.ProofOp) (merkle.ProofOperator, error) { 37 if pop.Type != ProofOpIAVLValue { 38 return nil, errors.New("unexpected ProofOp.Type; got %v, want %v", pop.Type, ProofOpIAVLValue) 39 } 40 var op IAVLValueOp // a bit strange as we'll discard this, but it works. 41 err := cdc.UnmarshalSized(pop.Data, &op) 42 if err != nil { 43 return nil, errors.Wrap(err, "decoding ProofOp.Data into IAVLValueOp") 44 } 45 return NewIAVLValueOp(pop.Key, op.Proof), nil 46 } 47 48 func (op IAVLValueOp) ProofOp() merkle.ProofOp { 49 bz := cdc.MustMarshalSized(op) 50 return merkle.ProofOp{ 51 Type: ProofOpIAVLValue, 52 Key: op.key, 53 Data: bz, 54 } 55 } 56 57 func (op IAVLValueOp) String() string { 58 return fmt.Sprintf("IAVLValueOp{%v}", op.GetKey()) 59 } 60 61 func (op IAVLValueOp) Run(args [][]byte) ([][]byte, error) { 62 if len(args) != 1 { 63 return nil, errors.New("Value size is not 1") 64 } 65 value := args[0] 66 67 // Compute the root hash and assume it is valid. 68 // The caller checks the ultimate root later. 69 root := op.Proof.ComputeRootHash() 70 err := op.Proof.Verify(root) 71 if err != nil { 72 return nil, errors.Wrap(err, "computing root hash") 73 } 74 // XXX What is the encoding for keys? 75 // We should decode the key depending on whether it's a string or hex, 76 // maybe based on quotes and 0x prefix? 77 err = op.Proof.VerifyItem(op.key, value) 78 if err != nil { 79 return nil, errors.Wrap(err, "verifying value") 80 } 81 return [][]byte{root}, nil 82 } 83 84 func (op IAVLValueOp) GetKey() []byte { 85 return op.key 86 }