github.com/project-88388/tendermint-v0.34.14-terra.2@v1.0.0/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 "github.com/stretchr/testify/require" 10 11 tmcrypto "github.com/tendermint/tendermint/proto/tendermint/crypto" 12 ) 13 14 const ProofOpDomino = "test:domino" 15 16 // Expects given input, produces given output. 17 // Like the game dominos. 18 type DominoOp struct { 19 key string // unexported, may be empty 20 Input string 21 Output string 22 } 23 24 func NewDominoOp(key, input, output string) DominoOp { 25 return DominoOp{ 26 key: key, 27 Input: input, 28 Output: output, 29 } 30 } 31 32 func (dop DominoOp) ProofOp() tmcrypto.ProofOp { 33 dopb := tmcrypto.DominoOp{ 34 Key: dop.key, 35 Input: dop.Input, 36 Output: dop.Output, 37 } 38 bz, err := dopb.Marshal() 39 if err != nil { 40 panic(err) 41 } 42 43 return tmcrypto.ProofOp{ 44 Type: ProofOpDomino, 45 Key: []byte(dop.key), 46 Data: bz, 47 } 48 } 49 50 func (dop DominoOp) Run(input [][]byte) (output [][]byte, err error) { 51 if len(input) != 1 { 52 return nil, errors.New("expected input of length 1") 53 } 54 if string(input[0]) != dop.Input { 55 return nil, fmt.Errorf("expected input %v, got %v", 56 dop.Input, string(input[0])) 57 } 58 return [][]byte{[]byte(dop.Output)}, nil 59 } 60 61 func (dop DominoOp) GetKey() []byte { 62 return []byte(dop.key) 63 } 64 65 //---------------------------------------- 66 67 func TestProofOperators(t *testing.T) { 68 var err error 69 70 // ProofRuntime setup 71 // TODO test this somehow. 72 73 // ProofOperators setup 74 op1 := NewDominoOp("KEY1", "INPUT1", "INPUT2") 75 op2 := NewDominoOp("KEY2", "INPUT2", "INPUT3") 76 op3 := NewDominoOp("", "INPUT3", "INPUT4") 77 op4 := NewDominoOp("KEY4", "INPUT4", "OUTPUT4") 78 79 // Good 80 popz := ProofOperators([]ProofOperator{op1, op2, op3, op4}) 81 err = popz.Verify(bz("OUTPUT4"), "/KEY4/KEY2/KEY1", [][]byte{bz("INPUT1")}) 82 assert.Nil(t, err) 83 err = popz.VerifyValue(bz("OUTPUT4"), "/KEY4/KEY2/KEY1", bz("INPUT1")) 84 assert.Nil(t, err) 85 86 // BAD INPUT 87 err = popz.Verify(bz("OUTPUT4"), "/KEY4/KEY2/KEY1", [][]byte{bz("INPUT1_WRONG")}) 88 assert.NotNil(t, err) 89 err = popz.VerifyValue(bz("OUTPUT4"), "/KEY4/KEY2/KEY1", bz("INPUT1_WRONG")) 90 assert.NotNil(t, err) 91 92 // BAD KEY 1 93 err = popz.Verify(bz("OUTPUT4"), "/KEY3/KEY2/KEY1", [][]byte{bz("INPUT1")}) 94 assert.NotNil(t, err) 95 96 // BAD KEY 2 97 err = popz.Verify(bz("OUTPUT4"), "KEY4/KEY2/KEY1", [][]byte{bz("INPUT1")}) 98 assert.NotNil(t, err) 99 100 // BAD KEY 3 101 err = popz.Verify(bz("OUTPUT4"), "/KEY4/KEY2/KEY1/", [][]byte{bz("INPUT1")}) 102 assert.NotNil(t, err) 103 104 // BAD KEY 4 105 err = popz.Verify(bz("OUTPUT4"), "//KEY4/KEY2/KEY1", [][]byte{bz("INPUT1")}) 106 assert.NotNil(t, err) 107 108 // BAD KEY 5 109 err = popz.Verify(bz("OUTPUT4"), "/KEY2/KEY1", [][]byte{bz("INPUT1")}) 110 assert.NotNil(t, err) 111 112 // BAD OUTPUT 1 113 err = popz.Verify(bz("OUTPUT4_WRONG"), "/KEY4/KEY2/KEY1", [][]byte{bz("INPUT1")}) 114 assert.NotNil(t, err) 115 116 // BAD OUTPUT 2 117 err = popz.Verify(bz(""), "/KEY4/KEY2/KEY1", [][]byte{bz("INPUT1")}) 118 assert.NotNil(t, err) 119 120 // BAD POPZ 1 121 popz = []ProofOperator{op1, op2, op4} 122 err = popz.Verify(bz("OUTPUT4"), "/KEY4/KEY2/KEY1", [][]byte{bz("INPUT1")}) 123 assert.NotNil(t, err) 124 125 // BAD POPZ 2 126 popz = []ProofOperator{op4, op3, op2, op1} 127 err = popz.Verify(bz("OUTPUT4"), "/KEY4/KEY2/KEY1", [][]byte{bz("INPUT1")}) 128 assert.NotNil(t, err) 129 130 // BAD POPZ 3 131 popz = []ProofOperator{} 132 err = popz.Verify(bz("OUTPUT4"), "/KEY4/KEY2/KEY1", [][]byte{bz("INPUT1")}) 133 assert.NotNil(t, err) 134 } 135 136 func bz(s string) []byte { 137 return []byte(s) 138 } 139 140 func TestProofValidateBasic(t *testing.T) { 141 testCases := []struct { 142 testName string 143 malleateProof func(*Proof) 144 errStr string 145 }{ 146 {"Good", func(sp *Proof) {}, ""}, 147 {"Negative Total", func(sp *Proof) { sp.Total = -1 }, "negative Total"}, 148 {"Negative Index", func(sp *Proof) { sp.Index = -1 }, "negative Index"}, 149 {"Invalid LeafHash", func(sp *Proof) { sp.LeafHash = make([]byte, 10) }, 150 "expected LeafHash size to be 32, got 10"}, 151 {"Too many Aunts", func(sp *Proof) { sp.Aunts = make([][]byte, MaxAunts+1) }, 152 "expected no more than 100 aunts, got 101"}, 153 {"Invalid Aunt", func(sp *Proof) { sp.Aunts[0] = make([]byte, 10) }, 154 "expected Aunts#0 size to be 32, got 10"}, 155 } 156 157 for _, tc := range testCases { 158 tc := tc 159 t.Run(tc.testName, func(t *testing.T) { 160 _, proofs := ProofsFromByteSlices([][]byte{ 161 []byte("apple"), 162 []byte("watermelon"), 163 []byte("kiwi"), 164 }) 165 tc.malleateProof(proofs[0]) 166 err := proofs[0].ValidateBasic() 167 if tc.errStr != "" { 168 assert.Contains(t, err.Error(), tc.errStr) 169 } 170 }) 171 } 172 } 173 func TestVoteProtobuf(t *testing.T) { 174 175 _, proofs := ProofsFromByteSlices([][]byte{ 176 []byte("apple"), 177 []byte("watermelon"), 178 []byte("kiwi"), 179 }) 180 testCases := []struct { 181 testName string 182 v1 *Proof 183 expPass bool 184 }{ 185 {"empty proof", &Proof{}, false}, 186 {"failure nil", nil, false}, 187 {"success", proofs[0], true}, 188 } 189 for _, tc := range testCases { 190 pb := tc.v1.ToProto() 191 192 v, err := ProofFromProto(pb) 193 if tc.expPass { 194 require.NoError(t, err) 195 require.Equal(t, tc.v1, v, tc.testName) 196 } else { 197 require.Error(t, err) 198 } 199 } 200 }