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