github.com/franono/tendermint@v0.32.2-0.20200527150959-749313264ce9/crypto/merkle/proof_test.go (about)

     1  package merkle
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"testing"
     7  
     8  	"github.com/stretchr/testify/assert"
     9  	amino "github.com/tendermint/go-amino"
    10  )
    11  
    12  const ProofOpDomino = "test:domino"
    13  
    14  // Expects given input, produces given output.
    15  // Like the game dominos.
    16  type DominoOp struct {
    17  	key    string // unexported, may be empty
    18  	Input  string
    19  	Output string
    20  }
    21  
    22  func NewDominoOp(key, input, output string) DominoOp {
    23  	return DominoOp{
    24  		key:    key,
    25  		Input:  input,
    26  		Output: output,
    27  	}
    28  }
    29  
    30  //nolint:unused
    31  func DominoOpDecoder(pop ProofOp) (ProofOperator, error) {
    32  	if pop.Type != ProofOpDomino {
    33  		panic("unexpected proof op type")
    34  	}
    35  	var op DominoOp // a bit strange as we'll discard this, but it works.
    36  	err := amino.UnmarshalBinaryLengthPrefixed(pop.Data, &op)
    37  	if err != nil {
    38  		return nil, fmt.Errorf("decoding ProofOp.Data into SimpleValueOp: %w", err)
    39  	}
    40  	return NewDominoOp(string(pop.Key), op.Input, op.Output), nil
    41  }
    42  
    43  func (dop DominoOp) ProofOp() ProofOp {
    44  	bz := amino.MustMarshalBinaryLengthPrefixed(dop)
    45  	return ProofOp{
    46  		Type: ProofOpDomino,
    47  		Key:  []byte(dop.key),
    48  		Data: bz,
    49  	}
    50  }
    51  
    52  func (dop DominoOp) Run(input [][]byte) (output [][]byte, err error) {
    53  	if len(input) != 1 {
    54  		return nil, errors.New("expected input of length 1")
    55  	}
    56  	if string(input[0]) != dop.Input {
    57  		return nil, fmt.Errorf("expected input %v, got %v",
    58  			dop.Input, string(input[0]))
    59  	}
    60  	return [][]byte{[]byte(dop.Output)}, nil
    61  }
    62  
    63  func (dop DominoOp) GetKey() []byte {
    64  	return []byte(dop.key)
    65  }
    66  
    67  //----------------------------------------
    68  
    69  func TestProofOperators(t *testing.T) {
    70  	var err error
    71  
    72  	// ProofRuntime setup
    73  	// TODO test this somehow.
    74  	// prt := NewProofRuntime()
    75  	// prt.RegisterOpDecoder(ProofOpDomino, DominoOpDecoder)
    76  
    77  	// ProofOperators setup
    78  	op1 := NewDominoOp("KEY1", "INPUT1", "INPUT2")
    79  	op2 := NewDominoOp("KEY2", "INPUT2", "INPUT3")
    80  	op3 := NewDominoOp("", "INPUT3", "INPUT4")
    81  	op4 := NewDominoOp("KEY4", "INPUT4", "OUTPUT4")
    82  
    83  	// Good
    84  	popz := ProofOperators([]ProofOperator{op1, op2, op3, op4})
    85  	err = popz.Verify(bz("OUTPUT4"), "/KEY4/KEY2/KEY1", [][]byte{bz("INPUT1")})
    86  	assert.Nil(t, err)
    87  	err = popz.VerifyValue(bz("OUTPUT4"), "/KEY4/KEY2/KEY1", bz("INPUT1"))
    88  	assert.Nil(t, err)
    89  
    90  	// BAD INPUT
    91  	err = popz.Verify(bz("OUTPUT4"), "/KEY4/KEY2/KEY1", [][]byte{bz("INPUT1_WRONG")})
    92  	assert.NotNil(t, err)
    93  	err = popz.VerifyValue(bz("OUTPUT4"), "/KEY4/KEY2/KEY1", bz("INPUT1_WRONG"))
    94  	assert.NotNil(t, err)
    95  
    96  	// BAD KEY 1
    97  	err = popz.Verify(bz("OUTPUT4"), "/KEY3/KEY2/KEY1", [][]byte{bz("INPUT1")})
    98  	assert.NotNil(t, err)
    99  
   100  	// BAD KEY 2
   101  	err = popz.Verify(bz("OUTPUT4"), "KEY4/KEY2/KEY1", [][]byte{bz("INPUT1")})
   102  	assert.NotNil(t, err)
   103  
   104  	// BAD KEY 3
   105  	err = popz.Verify(bz("OUTPUT4"), "/KEY4/KEY2/KEY1/", [][]byte{bz("INPUT1")})
   106  	assert.NotNil(t, err)
   107  
   108  	// BAD KEY 4
   109  	err = popz.Verify(bz("OUTPUT4"), "//KEY4/KEY2/KEY1", [][]byte{bz("INPUT1")})
   110  	assert.NotNil(t, err)
   111  
   112  	// BAD KEY 5
   113  	err = popz.Verify(bz("OUTPUT4"), "/KEY2/KEY1", [][]byte{bz("INPUT1")})
   114  	assert.NotNil(t, err)
   115  
   116  	// BAD OUTPUT 1
   117  	err = popz.Verify(bz("OUTPUT4_WRONG"), "/KEY4/KEY2/KEY1", [][]byte{bz("INPUT1")})
   118  	assert.NotNil(t, err)
   119  
   120  	// BAD OUTPUT 2
   121  	err = popz.Verify(bz(""), "/KEY4/KEY2/KEY1", [][]byte{bz("INPUT1")})
   122  	assert.NotNil(t, err)
   123  
   124  	// BAD POPZ 1
   125  	popz = []ProofOperator{op1, op2, op4}
   126  	err = popz.Verify(bz("OUTPUT4"), "/KEY4/KEY2/KEY1", [][]byte{bz("INPUT1")})
   127  	assert.NotNil(t, err)
   128  
   129  	// BAD POPZ 2
   130  	popz = []ProofOperator{op4, op3, op2, op1}
   131  	err = popz.Verify(bz("OUTPUT4"), "/KEY4/KEY2/KEY1", [][]byte{bz("INPUT1")})
   132  	assert.NotNil(t, err)
   133  
   134  	// BAD POPZ 3
   135  	popz = []ProofOperator{}
   136  	err = popz.Verify(bz("OUTPUT4"), "/KEY4/KEY2/KEY1", [][]byte{bz("INPUT1")})
   137  	assert.NotNil(t, err)
   138  }
   139  
   140  func bz(s string) []byte {
   141  	return []byte(s)
   142  }