github.com/pokt-network/tendermint@v0.32.11-0.20230426215212-59310158d3e9/crypto/merkle/proof_simple_value.go (about) 1 package merkle 2 3 import ( 4 "bytes" 5 "fmt" 6 7 "github.com/pkg/errors" 8 9 "github.com/tendermint/tendermint/crypto/tmhash" 10 ) 11 12 const ProofOpSimpleValue = "simple:v" 13 14 // SimpleValueOp takes a key and a single value as argument and 15 // produces the root hash. The corresponding tree structure is 16 // the SimpleMap tree. SimpleMap takes a Hasher, and currently 17 // Tendermint uses aminoHasher. SimpleValueOp should support 18 // the hash function as used in aminoHasher. TODO support 19 // additional hash functions here as options/args to this 20 // operator. 21 // 22 // If the produced root hash matches the expected hash, the 23 // proof is good. 24 type SimpleValueOp struct { 25 // Encoded in ProofOp.Key. 26 key []byte 27 28 // To encode in ProofOp.Data 29 Proof *SimpleProof `json:"simple_proof"` 30 } 31 32 var _ ProofOperator = SimpleValueOp{} 33 34 func NewSimpleValueOp(key []byte, proof *SimpleProof) SimpleValueOp { 35 return SimpleValueOp{ 36 key: key, 37 Proof: proof, 38 } 39 } 40 41 func SimpleValueOpDecoder(pop ProofOp) (ProofOperator, error) { 42 if pop.Type != ProofOpSimpleValue { 43 return nil, errors.Errorf("unexpected ProofOp.Type; got %v, want %v", pop.Type, ProofOpSimpleValue) 44 } 45 var op SimpleValueOp // a bit strange as we'll discard this, but it works. 46 err := cdc.UnmarshalBinaryLengthPrefixed(pop.Data, &op) 47 if err != nil { 48 return nil, errors.Wrap(err, "decoding ProofOp.Data into SimpleValueOp") 49 } 50 return NewSimpleValueOp(pop.Key, op.Proof), nil 51 } 52 53 func (op SimpleValueOp) ProofOp() ProofOp { 54 bz := cdc.MustMarshalBinaryLengthPrefixed(op) 55 return ProofOp{ 56 Type: ProofOpSimpleValue, 57 Key: op.key, 58 Data: bz, 59 } 60 } 61 62 func (op SimpleValueOp) String() string { 63 return fmt.Sprintf("SimpleValueOp{%v}", op.GetKey()) 64 } 65 66 func (op SimpleValueOp) Run(args [][]byte) ([][]byte, error) { 67 if len(args) != 1 { 68 return nil, errors.Errorf("expected 1 arg, got %v", len(args)) 69 } 70 value := args[0] 71 hasher := tmhash.New() 72 hasher.Write(value) // does not error 73 vhash := hasher.Sum(nil) 74 75 bz := new(bytes.Buffer) 76 // Wrap <op.Key, vhash> to hash the KVPair. 77 encodeByteSlice(bz, op.key) // does not error 78 encodeByteSlice(bz, vhash) // does not error 79 kvhash := leafHash(bz.Bytes()) 80 81 if !bytes.Equal(kvhash, op.Proof.LeafHash) { 82 return nil, errors.Errorf("leaf hash mismatch: want %X got %X", op.Proof.LeafHash, kvhash) 83 } 84 85 return [][]byte{ 86 op.Proof.ComputeRootHash(), 87 }, nil 88 } 89 90 func (op SimpleValueOp) GetKey() []byte { 91 return op.key 92 }