github.com/devwanda/aphelion-staking@v0.33.9/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/devwanda/aphelion-staking/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  }