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