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 }