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