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  }