github.com/koko1123/flow-go-1@v0.29.6/storage/merkle/proof_test.go (about) 1 package merkle 2 3 import ( 4 "math/rand" 5 "testing" 6 "time" 7 8 "github.com/stretchr/testify/assert" 9 "github.com/stretchr/testify/require" 10 ) 11 12 // TestProofWithASingleKey tests proof generation and verification 13 // when trie includes only a single value 14 func TestProofWithASingleKey(t *testing.T) { 15 minKeyLength := 1 16 keyLengths := []int{minKeyLength, 32, maxKeyLength} 17 for _, keyLength := range keyLengths { 18 tree1, err := NewTree(keyLength) 19 assert.NoError(t, err) 20 21 key, val := randomKeyValuePair(keyLength, 128) 22 23 replaced, err := tree1.Put(key, val) 24 assert.NoError(t, err) 25 require.False(t, replaced) 26 27 // work for an existing key 28 proof, existed := tree1.Prove(key) 29 require.True(t, existed) 30 31 err = proof.Verify(tree1.Hash()) 32 assert.NoError(t, err) 33 34 // fail for non-existing key 35 key2, _ := randomKeyValuePair(keyLength, 128) 36 37 proof, existed = tree1.Prove(key2) 38 require.False(t, existed) 39 require.Nil(t, proof) 40 } 41 } 42 43 // TestValidateFormat tests cases a proof can not be valid 44 func TestValidateFormat(t *testing.T) { 45 46 // construct a valid proof 47 keyLength := 31 48 key := make([]byte, keyLength) 49 key[0] = uint8(5) 50 value := make([]byte, 128) 51 value[0] = uint8(6) 52 53 key2 := make([]byte, keyLength) 54 key2[0] = uint8(4) 55 value2 := make([]byte, 128) 56 57 tree1, err := NewTree(keyLength) 58 assert.NoError(t, err) 59 replaced, err := tree1.Put(key, value) 60 assert.NoError(t, err) 61 require.False(t, replaced) 62 replaced, err = tree1.Put(key2, value2) 63 assert.NoError(t, err) 64 require.False(t, replaced) 65 proof, existed := tree1.Prove(key) 66 require.True(t, existed) 67 68 // invalid key size 69 proof.Key = make([]byte, 0) 70 err = proof.validateFormat() 71 assert.True(t, IsMalformedProofError(err)) 72 assert.Equal(t, err.Error(), "malformed proof, key length in bytes must be in interval [1, 8191], but is 0") 73 74 // invalid key size (too large) 75 proof.Key = make([]byte, maxKeyLength+1) 76 err = proof.validateFormat() 77 assert.True(t, IsMalformedProofError(err)) 78 assert.Equal(t, err.Error(), "malformed proof, key length in bytes must be in interval [1, 8191], but is 8192") 79 80 // issue with the key size not matching the rest of the proof 81 proof.Key = make([]byte, 64) 82 err = proof.validateFormat() 83 assert.True(t, IsMalformedProofError(err)) 84 assert.Equal(t, err.Error(), "malformed proof, key length in bits (512) doesn't match the length of ShortPathLengths and SiblingHashes (248)") 85 86 // reset the key back to its original value 87 proof.Key = key 88 89 // empty InterimNodeTypes 90 InterimNodeTypesBackup := proof.InterimNodeTypes 91 proof.InterimNodeTypes = make([]byte, 0) 92 err = proof.validateFormat() 93 assert.True(t, IsMalformedProofError(err)) 94 assert.Equal(t, err.Error(), "malformed proof, the length of InterimNodeTypes doesn't match the length of ShortPathLengths and SiblingHashes") 95 96 // too many interim nodes 97 proof.InterimNodeTypes = make([]byte, maxKeyLength+1) 98 err = proof.validateFormat() 99 assert.True(t, IsMalformedProofError(err)) 100 assert.Equal(t, err.Error(), "malformed proof, InterimNodeTypes is larger than max key length allowed (8192 > 8191)") 101 102 // issue with the size of InterimNodeTypes 103 proof.InterimNodeTypes = append(InterimNodeTypesBackup, byte(0)) 104 err = proof.validateFormat() 105 assert.True(t, IsMalformedProofError(err)) 106 assert.Equal(t, err.Error(), "malformed proof, the length of InterimNodeTypes doesn't match the length of ShortPathLengths and SiblingHashes") 107 108 proof.InterimNodeTypes = InterimNodeTypesBackup 109 110 // issue with a short count 111 backupShortPathLengths := proof.ShortPathLengths 112 proof.ShortPathLengths[0] = uint16(10) 113 err = proof.validateFormat() 114 assert.True(t, IsMalformedProofError(err)) 115 assert.Equal(t, err.Error(), "malformed proof, key length in bits (248) doesn't match the length of ShortPathLengths and SiblingHashes (251)") 116 117 proof.ShortPathLengths[0] = uint16(0) 118 err = proof.validateFormat() 119 assert.True(t, IsMalformedProofError(err)) 120 assert.Equal(t, err.Error(), "malformed proof, short path length cannot be zero") 121 122 // drop a shortpathlength - index out of bound 123 proof.ShortPathLengths = proof.ShortPathLengths[:1] 124 proof.ShortPathLengths[0] = uint16(247) 125 err = proof.validateFormat() 126 assert.True(t, IsMalformedProofError(err)) 127 assert.Equal(t, err.Error(), "malformed proof, len(ShortPathLengths) (1) does not match number of set bits in InterimNodeTypes (2)") 128 proof.ShortPathLengths = backupShortPathLengths 129 130 // construct a new proof 131 proof, existed = tree1.Prove(key) 132 require.True(t, existed) 133 134 // trailing zero test 135 proof.InterimNodeTypes[len(proof.InterimNodeTypes)-1] = byte(129) 136 err = proof.validateFormat() 137 assert.True(t, IsMalformedProofError(err)) 138 assert.Equal(t, err.Error(), "malformed proof, tailing auxiliary bits in InterimNodeTypes should all be zero") 139 } 140 141 // TestProofsWithRandomKeys tests proof generation and verification 142 // when trie includes many random keys. (only a random subset of keys are checked for proofs) 143 func TestProofsWithRandomKeys(t *testing.T) { 144 // initialize random generator, two trees and zero hash 145 rand.Seed(time.Now().UnixNano()) 146 keyLength := 32 147 numberOfInsertions := 10000 148 numberOfProofsToVerify := 100 149 tree1, err := NewTree(keyLength) 150 assert.NoError(t, err) 151 152 // generate the desired number of keys and map a value to each key 153 keys := make([][]byte, 0, numberOfInsertions) 154 vals := make(map[string][]byte) 155 for i := 0; i < numberOfInsertions; i++ { 156 key, val := randomKeyValuePair(32, 128) 157 keys = append(keys, key) 158 vals[string(key)] = val 159 } 160 161 // insert all key-value paris into the first tree 162 for _, key := range keys { 163 val := vals[string(key)] 164 replaced, err := tree1.Put(key, val) 165 assert.NoError(t, err) 166 require.False(t, replaced) 167 } 168 169 // shuffle the keys and insert them with random order into the second tree 170 rand.Shuffle(len(keys), func(i int, j int) { 171 keys[i], keys[j] = keys[j], keys[i] 172 }) 173 174 // get proofs for keys and verify for a subset of keys 175 for _, key := range keys[:numberOfProofsToVerify] { 176 proof, existed := tree1.Prove(key) 177 require.True(t, existed) 178 err := proof.Verify(tree1.Hash()) 179 assert.NoError(t, err) 180 } 181 // pass a malformed proof and expect the verify to call the validate 182 malformedProof := &Proof{} 183 err = malformedProof.Verify(tree1.Hash()) 184 assert.True(t, IsMalformedProofError(err)) 185 }