github.com/dominant-strategies/go-quai@v0.28.2/trie/stacktrie_test.go (about) 1 package trie 2 3 import ( 4 "bytes" 5 "math/big" 6 "testing" 7 8 "github.com/dominant-strategies/go-quai/common" 9 "github.com/dominant-strategies/go-quai/crypto" 10 "github.com/dominant-strategies/go-quai/ethdb/memorydb" 11 ) 12 13 func TestSizeBug(t *testing.T) { 14 st := NewStackTrie(nil) 15 nt, _ := New(common.Hash{}, NewDatabase(memorydb.New())) 16 17 leaf := common.FromHex("290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563") 18 value := common.FromHex("94cf40d0d2b44f2b66e07cace1372ca42b73cf21a3") 19 20 nt.TryUpdate(leaf, value) 21 st.TryUpdate(leaf, value) 22 23 if nt.Hash() != st.Hash() { 24 t.Fatalf("error %x != %x", st.Hash(), nt.Hash()) 25 } 26 } 27 28 func TestEmptyBug(t *testing.T) { 29 st := NewStackTrie(nil) 30 nt, _ := New(common.Hash{}, NewDatabase(memorydb.New())) 31 32 //leaf := common.FromHex("290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563") 33 //value := common.FromHex("94cf40d0d2b44f2b66e07cace1372ca42b73cf21a3") 34 kvs := []struct { 35 K string 36 V string 37 }{ 38 {K: "405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace", V: "9496f4ec2bf9dab484cac6be589e8417d84781be08"}, 39 {K: "40edb63a35fcf86c08022722aa3287cdd36440d671b4918131b2514795fefa9c", V: "01"}, 40 {K: "b10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6", V: "947a30f7736e48d6599356464ba4c150d8da0302ff"}, 41 {K: "c2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", V: "02"}, 42 } 43 44 for _, kv := range kvs { 45 nt.TryUpdate(common.FromHex(kv.K), common.FromHex(kv.V)) 46 st.TryUpdate(common.FromHex(kv.K), common.FromHex(kv.V)) 47 } 48 49 if nt.Hash() != st.Hash() { 50 t.Fatalf("error %x != %x", st.Hash(), nt.Hash()) 51 } 52 } 53 54 func TestValLength56(t *testing.T) { 55 st := NewStackTrie(nil) 56 nt, _ := New(common.Hash{}, NewDatabase(memorydb.New())) 57 58 //leaf := common.FromHex("290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563") 59 //value := common.FromHex("94cf40d0d2b44f2b66e07cace1372ca42b73cf21a3") 60 kvs := []struct { 61 K string 62 V string 63 }{ 64 {K: "405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace", V: "1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"}, 65 } 66 67 for _, kv := range kvs { 68 nt.TryUpdate(common.FromHex(kv.K), common.FromHex(kv.V)) 69 st.TryUpdate(common.FromHex(kv.K), common.FromHex(kv.V)) 70 } 71 72 if nt.Hash() != st.Hash() { 73 t.Fatalf("error %x != %x", st.Hash(), nt.Hash()) 74 } 75 } 76 77 // TestUpdateSmallNodes tests a case where the leaves are small (both key and value), 78 // which causes a lot of node-within-node. This case was found via fuzzing. 79 func TestUpdateSmallNodes(t *testing.T) { 80 st := NewStackTrie(nil) 81 nt, _ := New(common.Hash{}, NewDatabase(memorydb.New())) 82 kvs := []struct { 83 K string 84 V string 85 }{ 86 {"63303030", "3041"}, // stacktrie.Update 87 {"65", "3000"}, // stacktrie.Update 88 } 89 for _, kv := range kvs { 90 nt.TryUpdate(common.FromHex(kv.K), common.FromHex(kv.V)) 91 st.TryUpdate(common.FromHex(kv.K), common.FromHex(kv.V)) 92 } 93 if nt.Hash() != st.Hash() { 94 t.Fatalf("error %x != %x", st.Hash(), nt.Hash()) 95 } 96 } 97 98 // TestUpdateVariableKeys contains a case which stacktrie fails: when keys of different 99 // sizes are used, and the second one has the same prefix as the first, then the 100 // stacktrie fails, since it's unable to 'expand' on an already added leaf. 101 // For all practical purposes, this is fine, since keys are fixed-size length 102 // in account and storage tries. 103 // 104 // The test is marked as 'skipped', and exists just to have the behaviour documented. 105 // This case was found via fuzzing. 106 func TestUpdateVariableKeys(t *testing.T) { 107 t.SkipNow() 108 st := NewStackTrie(nil) 109 nt, _ := New(common.Hash{}, NewDatabase(memorydb.New())) 110 kvs := []struct { 111 K string 112 V string 113 }{ 114 {"0x33303534636532393561313031676174", "303030"}, 115 {"0x3330353463653239356131303167617430", "313131"}, 116 } 117 for _, kv := range kvs { 118 nt.TryUpdate(common.FromHex(kv.K), common.FromHex(kv.V)) 119 st.TryUpdate(common.FromHex(kv.K), common.FromHex(kv.V)) 120 } 121 if nt.Hash() != st.Hash() { 122 t.Fatalf("error %x != %x", st.Hash(), nt.Hash()) 123 } 124 } 125 126 // TestStacktrieNotModifyValues checks that inserting blobs of data into the 127 // stacktrie does not mutate the blobs 128 func TestStacktrieNotModifyValues(t *testing.T) { 129 st := NewStackTrie(nil) 130 { // Test a very small trie 131 // Give it the value as a slice with large backing alloc, 132 // so if the stacktrie tries to append, it won't have to realloc 133 value := make([]byte, 1, 100) 134 value[0] = 0x2 135 want := common.CopyBytes(value) 136 st.TryUpdate([]byte{0x01}, value) 137 st.Hash() 138 if have := value; !bytes.Equal(have, want) { 139 t.Fatalf("tiny trie: have %#x want %#x", have, want) 140 } 141 st = NewStackTrie(nil) 142 } 143 // Test with a larger trie 144 keyB := big.NewInt(1) 145 keyDelta := big.NewInt(1) 146 var vals [][]byte 147 getValue := func(i int) []byte { 148 if i%2 == 0 { // large 149 return crypto.Keccak256(big.NewInt(int64(i)).Bytes()) 150 } else { //small 151 return big.NewInt(int64(i)).Bytes() 152 } 153 } 154 for i := 0; i < 1000; i++ { 155 key := common.BigToHash(keyB) 156 value := getValue(i) 157 st.TryUpdate(key.Bytes(), value) 158 vals = append(vals, value) 159 keyB = keyB.Add(keyB, keyDelta) 160 keyDelta.Add(keyDelta, common.Big1) 161 } 162 st.Hash() 163 for i := 0; i < 1000; i++ { 164 want := getValue(i) 165 166 have := vals[i] 167 if !bytes.Equal(have, want) { 168 t.Fatalf("item %d, have %#x want %#x", i, have, want) 169 } 170 171 } 172 } 173 174 // TestStacktrieSerialization tests that the stacktrie works well if we 175 // serialize/unserialize it a lot 176 func TestStacktrieSerialization(t *testing.T) { 177 var ( 178 st = NewStackTrie(nil) 179 nt, _ = New(common.Hash{}, NewDatabase(memorydb.New())) 180 keyB = big.NewInt(1) 181 keyDelta = big.NewInt(1) 182 vals [][]byte 183 keys [][]byte 184 ) 185 getValue := func(i int) []byte { 186 if i%2 == 0 { // large 187 return crypto.Keccak256(big.NewInt(int64(i)).Bytes()) 188 } else { //small 189 return big.NewInt(int64(i)).Bytes() 190 } 191 } 192 for i := 0; i < 10; i++ { 193 vals = append(vals, getValue(i)) 194 keys = append(keys, common.BigToHash(keyB).Bytes()) 195 keyB = keyB.Add(keyB, keyDelta) 196 keyDelta.Add(keyDelta, common.Big1) 197 } 198 for i, k := range keys { 199 nt.TryUpdate(k, common.CopyBytes(vals[i])) 200 } 201 202 for i, k := range keys { 203 blob, err := st.MarshalBinary() 204 if err != nil { 205 t.Fatal(err) 206 } 207 newSt, err := NewFromBinary(blob, nil) 208 if err != nil { 209 t.Fatal(err) 210 } 211 st = newSt 212 st.TryUpdate(k, common.CopyBytes(vals[i])) 213 } 214 if have, want := st.Hash(), nt.Hash(); have != want { 215 t.Fatalf("have %#x want %#x", have, want) 216 } 217 }