github.com/ledgerwatch/erigon-lib@v1.0.0/commitment/hex_patricia_hashed_test.go (about) 1 /* 2 Copyright 2022 Erigon contributors 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package commitment 18 19 import ( 20 "encoding/hex" 21 "fmt" 22 "math/rand" 23 "testing" 24 25 "github.com/stretchr/testify/require" 26 27 "github.com/ledgerwatch/erigon-lib/common/length" 28 ) 29 30 func Test_HexPatriciaHashed_ResetThenSingularUpdates(t *testing.T) { 31 ms := NewMockState(t) 32 hph := NewHexPatriciaHashed(1, ms.branchFn, ms.accountFn, ms.storageFn) 33 hph.SetTrace(false) 34 plainKeys, hashedKeys, updates := NewUpdateBuilder(). 35 Balance("00", 4). 36 Balance("01", 5). 37 Balance("02", 6). 38 Balance("03", 7). 39 Balance("04", 8). 40 Storage("04", "01", "0401"). 41 Storage("03", "56", "050505"). 42 Storage("03", "57", "060606"). 43 Balance("05", 9). 44 Storage("05", "02", "8989"). 45 Storage("05", "04", "9898"). 46 Build() 47 48 err := ms.applyPlainUpdates(plainKeys, updates) 49 require.NoError(t, err) 50 51 firstRootHash, branchNodeUpdates, err := hph.ReviewKeys(plainKeys, hashedKeys) 52 require.NoError(t, err) 53 54 t.Logf("root hash %x\n", firstRootHash) 55 56 ms.applyBranchNodeUpdates(branchNodeUpdates) 57 58 fmt.Printf("1. Generated updates\n") 59 renderUpdates(branchNodeUpdates) 60 61 // More updates 62 hph.Reset() 63 hph.SetTrace(false) 64 plainKeys, hashedKeys, updates = NewUpdateBuilder(). 65 Storage("03", "58", "050505"). 66 Build() 67 err = ms.applyPlainUpdates(plainKeys, updates) 68 require.NoError(t, err) 69 70 secondRootHash, branchNodeUpdates, err := hph.ReviewKeys(plainKeys, hashedKeys) 71 require.NoError(t, err) 72 require.NotEqualValues(t, firstRootHash, secondRootHash) 73 74 ms.applyBranchNodeUpdates(branchNodeUpdates) 75 fmt.Printf("2. Generated single update\n") 76 renderUpdates(branchNodeUpdates) 77 78 // More updates 79 hph.Reset() 80 hph.SetTrace(false) 81 plainKeys, hashedKeys, updates = NewUpdateBuilder(). 82 Storage("03", "58", "070807"). 83 Build() 84 err = ms.applyPlainUpdates(plainKeys, updates) 85 require.NoError(t, err) 86 87 thirdRootHash, branchNodeUpdates, err := hph.ReviewKeys(plainKeys, hashedKeys) 88 require.NoError(t, err) 89 require.NotEqualValues(t, secondRootHash, thirdRootHash) 90 91 ms.applyBranchNodeUpdates(branchNodeUpdates) 92 fmt.Printf("3. Generated single update\n") 93 renderUpdates(branchNodeUpdates) 94 } 95 96 func Test_HexPatriciaHashed_EmptyUpdate(t *testing.T) { 97 ms := NewMockState(t) 98 hph := NewHexPatriciaHashed(1, ms.branchFn, ms.accountFn, ms.storageFn) 99 hph.SetTrace(false) 100 plainKeys, hashedKeys, updates := NewUpdateBuilder(). 101 Balance("00", 4). 102 Nonce("00", 246462653). 103 Balance("01", 5). 104 CodeHash("03", "aaaaaaaaaaf7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a870"). 105 Delete("00"). 106 Storage("04", "01", "0401"). 107 Storage("03", "56", "050505"). 108 Build() 109 110 err := ms.applyPlainUpdates(plainKeys, updates) 111 require.NoError(t, err) 112 113 hashBeforeEmptyUpdate, branchNodeUpdates, err := hph.ReviewKeys(plainKeys, hashedKeys) 114 require.NoError(t, err) 115 require.NotEmpty(t, hashBeforeEmptyUpdate) 116 117 ms.applyBranchNodeUpdates(branchNodeUpdates) 118 119 fmt.Println("1. Updates applied") 120 renderUpdates(branchNodeUpdates) 121 122 // generate empty updates and do NOT reset tree 123 hph.SetTrace(true) 124 125 plainKeys, hashedKeys, updates = NewUpdateBuilder().Build() 126 127 err = ms.applyPlainUpdates(plainKeys, updates) 128 require.NoError(t, err) 129 130 hashAfterEmptyUpdate, branchNodeUpdates, err := hph.ReviewKeys(plainKeys, hashedKeys) 131 require.NoError(t, err) 132 133 ms.applyBranchNodeUpdates(branchNodeUpdates) 134 fmt.Println("2. Empty updates applied without state reset") 135 136 require.EqualValues(t, hashBeforeEmptyUpdate, hashAfterEmptyUpdate) 137 } 138 139 func Test_HexPatriciaHashed_UniqueRepresentation(t *testing.T) { 140 ms := NewMockState(t) 141 ms2 := NewMockState(t) 142 143 plainKeys, hashedKeys, updates := NewUpdateBuilder(). 144 Balance("f5", 4). 145 Balance("ff", 900234). 146 Balance("04", 1233). 147 Storage("04", "01", "0401"). 148 Balance("ba", 065606). 149 Balance("00", 4). 150 Balance("01", 5). 151 Balance("02", 6). 152 Balance("03", 7). 153 Storage("03", "56", "050505"). 154 Balance("05", 9). 155 Storage("03", "87", "060606"). 156 Balance("b9", 6). 157 Nonce("ff", 169356). 158 Storage("05", "02", "8989"). 159 Storage("f5", "04", "9898"). 160 Build() 161 162 trieOne := NewHexPatriciaHashed(1, ms.branchFn, ms.accountFn, ms.storageFn) 163 trieTwo := NewHexPatriciaHashed(1, ms2.branchFn, ms2.accountFn, ms2.storageFn) 164 165 trieOne.SetTrace(true) 166 trieTwo.SetTrace(true) 167 168 // single sequential update 169 roots := make([][]byte, 0) 170 // branchNodeUpdatesOne := make(map[string]BranchData) 171 fmt.Printf("1. Trie sequential update generated following branch updates\n") 172 for i := 0; i < len(updates); i++ { 173 if err := ms.applyPlainUpdates(plainKeys[i:i+1], updates[i:i+1]); err != nil { 174 t.Fatal(err) 175 } 176 177 sequentialRoot, branchNodeUpdates, err := trieOne.ReviewKeys(plainKeys[i:i+1], hashedKeys[i:i+1]) 178 require.NoError(t, err) 179 roots = append(roots, sequentialRoot) 180 181 ms.applyBranchNodeUpdates(branchNodeUpdates) 182 renderUpdates(branchNodeUpdates) 183 } 184 185 err := ms2.applyPlainUpdates(plainKeys, updates) 186 require.NoError(t, err) 187 188 fmt.Printf("\n2. Trie batch update generated following branch updates\n") 189 // batch update 190 batchRoot, branchNodeUpdatesTwo, err := trieTwo.ReviewKeys(plainKeys, hashedKeys) 191 require.NoError(t, err) 192 renderUpdates(branchNodeUpdatesTwo) 193 194 fmt.Printf("\n sequential roots:\n") 195 for i, rh := range roots { 196 fmt.Printf("%2d %+v\n", i, hex.EncodeToString(rh)) 197 } 198 199 ms2.applyBranchNodeUpdates(branchNodeUpdatesTwo) 200 201 require.EqualValues(t, batchRoot, roots[len(roots)-1], 202 "expected equal roots, got sequential [%v] != batch [%v]", hex.EncodeToString(roots[len(roots)-1]), hex.EncodeToString(batchRoot)) 203 require.Lenf(t, batchRoot, 32, "root hash length should be equal to 32 bytes") 204 } 205 206 func Test_Sepolia(t *testing.T) { 207 ms := NewMockState(t) 208 209 type TestData struct { 210 balances map[string][]byte 211 expectedRoot string 212 } 213 214 tests := []TestData{ 215 { 216 expectedRoot: "5eb6e371a698b8d68f665192350ffcecbbbf322916f4b51bd79bb6887da3f494", 217 balances: map[string][]byte{ 218 "a2a6d93439144ffe4d27c9e088dcd8b783946263": {0xd3, 0xc2, 0x1b, 0xce, 0xcc, 0xed, 0xa1, 0x00, 0x00, 0x00}, 219 "bc11295936aa79d594139de1b2e12629414f3bdb": {0xd3, 0xc2, 0x1b, 0xce, 0xcc, 0xed, 0xa1, 0x00, 0x00, 0x00}, 220 "7cf5b79bfe291a67ab02b393e456ccc4c266f753": {0xd3, 0xc2, 0x1b, 0xce, 0xcc, 0xed, 0xa1, 0x00, 0x00, 0x00}, 221 "aaec86394441f915bce3e6ab399977e9906f3b69": {0xd3, 0xc2, 0x1b, 0xce, 0xcc, 0xed, 0xa1, 0x00, 0x00, 0x00}, 222 "f47cae1cf79ca6758bfc787dbd21e6bdbe7112b8": {0xd3, 0xc2, 0x1b, 0xce, 0xcc, 0xed, 0xa1, 0x00, 0x00, 0x00}, 223 "d7eddb78ed295b3c9629240e8924fb8d8874ddd8": {0xd3, 0xc2, 0x1b, 0xce, 0xcc, 0xed, 0xa1, 0x00, 0x00, 0x00}, 224 "8b7f0977bb4f0fbe7076fa22bc24aca043583f5e": {0xd3, 0xc2, 0x1b, 0xce, 0xcc, 0xed, 0xa1, 0x00, 0x00, 0x00}, 225 "e2e2659028143784d557bcec6ff3a0721048880a": {0xd3, 0xc2, 0x1b, 0xce, 0xcc, 0xed, 0xa1, 0x00, 0x00, 0x00}, 226 "d9a5179f091d85051d3c982785efd1455cec8699": {0xd3, 0xc2, 0x1b, 0xce, 0xcc, 0xed, 0xa1, 0x00, 0x00, 0x00}, 227 "beef32ca5b9a198d27b4e02f4c70439fe60356cf": {0xd3, 0xc2, 0x1b, 0xce, 0xcc, 0xed, 0xa1, 0x00, 0x00, 0x00}, 228 "0000006916a87b82333f4245046623b23794c65c": {0x08, 0x45, 0x95, 0x16, 0x14, 0x01, 0x48, 0x4a, 0x00, 0x00, 0x00}, 229 "b21c33de1fab3fa15499c62b59fe0cc3250020d1": {0x52, 0xb7, 0xd2, 0xdc, 0xc8, 0x0c, 0xd2, 0xe4, 0x00, 0x00, 0x00}, 230 "10f5d45854e038071485ac9e402308cf80d2d2fe": {0x52, 0xb7, 0xd2, 0xdc, 0xc8, 0x0c, 0xd2, 0xe4, 0x00, 0x00, 0x00}, 231 "d7d76c58b3a519e9fa6cc4d22dc017259bc49f1e": {0x52, 0xb7, 0xd2, 0xdc, 0xc8, 0x0c, 0xd2, 0xe4, 0x00, 0x00, 0x00}, 232 "799d329e5f583419167cd722962485926e338f4a": {0x0d, 0xe0, 0xb6, 0xb3, 0xa7, 0x64, 0x00, 0x00}, 233 }, 234 }, 235 { 236 expectedRoot: "c91d4ecd59dce3067d340b3aadfc0542974b4fb4db98af39f980a91ea00db9dc", 237 balances: map[string][]byte{ 238 "2f14582947e292a2ecd20c430b46f2d27cfe213c": {0x1B, 0xC1, 0x6D, 0x67, 0x4E, 0xC8, 0x00, 0x00}, 239 }, 240 }, 241 { 242 expectedRoot: "c91d4ecd59dce3067d340b3aadfc0542974b4fb4db98af39f980a91ea00db9dc", 243 balances: map[string][]byte{}, 244 }, 245 } 246 247 hph := NewHexPatriciaHashed(length.Addr, ms.branchFn, ms.accountFn, ms.storageFn) 248 hph.SetTrace(true) 249 250 for _, testData := range tests { 251 builder := NewUpdateBuilder() 252 253 for address, balance := range testData.balances { 254 builder.IncrementBalance(address, balance) 255 } 256 plainKeys, hashedKeys, updates := builder.Build() 257 258 if err := ms.applyPlainUpdates(plainKeys, updates); err != nil { 259 t.Fatal(err) 260 } 261 262 rootHash, branchNodeUpdates, err := hph.ReviewKeys(plainKeys, hashedKeys) 263 if err != nil { 264 t.Fatal(err) 265 } 266 ms.applyBranchNodeUpdates(branchNodeUpdates) 267 268 require.EqualValues(t, testData.expectedRoot, fmt.Sprintf("%x", rootHash)) 269 } 270 } 271 272 func Test_HexPatriciaHashed_StateEncode(t *testing.T) { 273 //trie := NewHexPatriciaHashed(length.Hash, nil, nil, nil) 274 var s state 275 s.Root = make([]byte, 128) 276 rnd := rand.New(rand.NewSource(42)) 277 n, err := rnd.Read(s.CurrentKey[:]) 278 require.NoError(t, err) 279 require.EqualValues(t, 128, n) 280 n, err = rnd.Read(s.Root[:]) 281 require.NoError(t, err) 282 require.EqualValues(t, len(s.Root), n) 283 s.RootPresent = true 284 s.RootTouched = true 285 s.RootChecked = true 286 287 s.CurrentKeyLen = int8(rnd.Intn(129)) 288 for i := 0; i < len(s.Depths); i++ { 289 s.Depths[i] = rnd.Intn(256) 290 } 291 for i := 0; i < len(s.TouchMap); i++ { 292 s.TouchMap[i] = uint16(rnd.Intn(1<<16 - 1)) 293 } 294 for i := 0; i < len(s.AfterMap); i++ { 295 s.AfterMap[i] = uint16(rnd.Intn(1<<16 - 1)) 296 } 297 for i := 0; i < len(s.BranchBefore); i++ { 298 if rnd.Intn(100) > 49 { 299 s.BranchBefore[i] = true 300 } 301 } 302 303 enc, err := s.Encode(nil) 304 require.NoError(t, err) 305 require.NotEmpty(t, enc) 306 307 var s1 state 308 err = s1.Decode(enc) 309 require.NoError(t, err) 310 311 require.EqualValues(t, s.Root[:], s1.Root[:]) 312 require.EqualValues(t, s.Depths[:], s1.Depths[:]) 313 require.EqualValues(t, s.CurrentKeyLen, s1.CurrentKeyLen) 314 require.EqualValues(t, s.CurrentKey[:], s1.CurrentKey[:]) 315 require.EqualValues(t, s.AfterMap[:], s1.AfterMap[:]) 316 require.EqualValues(t, s.TouchMap[:], s1.TouchMap[:]) 317 require.EqualValues(t, s.BranchBefore[:], s1.BranchBefore[:]) 318 require.EqualValues(t, s.RootTouched, s1.RootTouched) 319 require.EqualValues(t, s.RootPresent, s1.RootPresent) 320 require.EqualValues(t, s.RootChecked, s1.RootChecked) 321 } 322 323 func Test_HexPatriciaHashed_StateEncodeDecodeSetup(t *testing.T) { 324 ms := NewMockState(t) 325 326 plainKeys, hashedKeys, updates := NewUpdateBuilder(). 327 Balance("f5", 4). 328 Balance("ff", 900234). 329 Balance("03", 7). 330 Storage("03", "56", "050505"). 331 Balance("05", 9). 332 Storage("03", "87", "060606"). 333 Balance("b9", 6). 334 Nonce("ff", 169356). 335 Storage("05", "02", "8989"). 336 Storage("f5", "04", "9898"). 337 Build() 338 339 before := NewHexPatriciaHashed(1, ms.branchFn, ms.accountFn, ms.storageFn) 340 after := NewHexPatriciaHashed(1, ms.branchFn, ms.accountFn, ms.storageFn) 341 342 err := ms.applyPlainUpdates(plainKeys, updates) 343 require.NoError(t, err) 344 345 rhBefore, branchUpdates, err := before.ReviewKeys(plainKeys, hashedKeys) 346 require.NoError(t, err) 347 ms.applyBranchNodeUpdates(branchUpdates) 348 349 state, err := before.EncodeCurrentState(nil) 350 require.NoError(t, err) 351 352 err = after.SetState(state) 353 require.NoError(t, err) 354 355 rhAfter, err := after.RootHash() 356 require.NoError(t, err) 357 require.EqualValues(t, rhBefore, rhAfter) 358 359 // create new update and apply it to both tries 360 nextPK, nextHashed, nextUpdates := NewUpdateBuilder(). 361 Nonce("ff", 4). 362 Balance("b9", 6000000000). 363 Balance("ad", 8000000000). 364 Build() 365 366 err = ms.applyPlainUpdates(nextPK, nextUpdates) 367 require.NoError(t, err) 368 369 rh2Before, branchUpdates, err := before.ReviewKeys(nextPK, nextHashed) 370 require.NoError(t, err) 371 ms.applyBranchNodeUpdates(branchUpdates) 372 373 rh2After, branchUpdates, err := after.ReviewKeys(nextPK, nextHashed) 374 require.NoError(t, err) 375 376 _ = branchUpdates 377 378 require.EqualValues(t, rh2Before, rh2After) 379 } 380 381 func Test_HexPatriciaHashed_RestoreAndContinue(t *testing.T) { 382 ms := NewMockState(t) 383 ms2 := NewMockState(t) 384 385 plainKeys, hashedKeys, updates := NewUpdateBuilder(). 386 Balance("f5", 4). 387 Balance("ff", 900234). 388 Balance("04", 1233). 389 Storage("04", "01", "0401"). 390 Balance("ba", 065606). 391 Balance("00", 4). 392 Balance("01", 5). 393 Balance("02", 6). 394 Balance("03", 7). 395 Storage("03", "56", "050505"). 396 Balance("05", 9). 397 Storage("03", "87", "060606"). 398 Balance("b9", 6). 399 Nonce("ff", 169356). 400 Storage("05", "02", "8989"). 401 Storage("f5", "04", "9898"). 402 Build() 403 404 trieOne := NewHexPatriciaHashed(1, ms.branchFn, ms.accountFn, ms.storageFn) 405 trieTwo := NewHexPatriciaHashed(1, ms2.branchFn, ms2.accountFn, ms2.storageFn) 406 407 err := ms2.applyPlainUpdates(plainKeys, updates) 408 require.NoError(t, err) 409 410 _ = updates 411 412 batchRoot, branchNodeUpdatesTwo, err := trieTwo.ReviewKeys(plainKeys, hashedKeys) 413 require.NoError(t, err) 414 renderUpdates(branchNodeUpdatesTwo) 415 ms2.applyBranchNodeUpdates(branchNodeUpdatesTwo) 416 417 buf, err := trieTwo.EncodeCurrentState(nil) 418 require.NoError(t, err) 419 require.NotEmpty(t, buf) 420 421 err = trieOne.SetState(buf) 422 require.NoError(t, err) 423 require.EqualValues(t, batchRoot[:], trieOne.root.h[:]) 424 require.EqualValues(t, trieTwo.root.hl, trieOne.root.hl) 425 require.EqualValues(t, trieTwo.root.apl, trieOne.root.apl) 426 if trieTwo.root.apl > 0 { 427 require.EqualValues(t, trieTwo.root.apk, trieOne.root.apk) 428 } 429 require.EqualValues(t, trieTwo.root.spl, trieOne.root.spl) 430 if trieTwo.root.apl > 0 { 431 require.EqualValues(t, trieTwo.root.spk, trieOne.root.spk) 432 } 433 if trieTwo.root.downHashedLen > 0 { 434 require.EqualValues(t, trieTwo.root.downHashedKey, trieOne.root.downHashedKey) 435 } 436 require.EqualValues(t, trieTwo.root.Nonce, trieOne.root.Nonce) 437 //require.EqualValues(t, trieTwo.root.CodeHash, trieOne.root.CodeHash) 438 require.EqualValues(t, trieTwo.root.StorageLen, trieOne.root.StorageLen) 439 require.EqualValues(t, trieTwo.root.extension, trieOne.root.extension) 440 441 require.EqualValues(t, trieTwo.currentKey, trieOne.currentKey) 442 require.EqualValues(t, trieTwo.afterMap, trieOne.afterMap) 443 require.EqualValues(t, trieTwo.touchMap[:], trieOne.touchMap[:]) 444 require.EqualValues(t, trieTwo.branchBefore[:], trieOne.branchBefore[:]) 445 require.EqualValues(t, trieTwo.rootTouched, trieOne.rootTouched) 446 require.EqualValues(t, trieTwo.rootPresent, trieOne.rootPresent) 447 require.EqualValues(t, trieTwo.rootChecked, trieOne.rootChecked) 448 require.EqualValues(t, trieTwo.currentKeyLen, trieOne.currentKeyLen) 449 } 450 451 func Test_HexPatriciaHashed_ProcessUpdates_UniqueRepresentation_AfterStateRestore(t *testing.T) { 452 ms := NewMockState(t) 453 ms2 := NewMockState(t) 454 455 plainKeys, hashedKeys, updates := NewUpdateBuilder(). 456 Balance("f5", 4). 457 Balance("ff", 900234). 458 Balance("04", 1233). 459 Storage("04", "01", "0401"). 460 Balance("ba", 065606). 461 Balance("00", 4). 462 Balance("01", 5). 463 Balance("02", 6). 464 Balance("03", 7). 465 Storage("03", "56", "050505"). 466 Balance("05", 9). 467 Storage("03", "87", "060606"). 468 Balance("b9", 6). 469 Nonce("ff", 169356). 470 Storage("05", "02", "8989"). 471 Storage("f5", "04", "9898"). 472 Build() 473 474 sequential := NewHexPatriciaHashed(1, ms.branchFn, ms.accountFn, ms.storageFn) 475 batch := NewHexPatriciaHashed(1, ms2.branchFn, ms2.accountFn, ms2.storageFn) 476 477 batch.Reset() 478 sequential.Reset() 479 sequential.SetTrace(true) 480 batch.SetTrace(true) 481 482 // single sequential update 483 roots := make([][]byte, 0) 484 prevState := make([]byte, 0) 485 fmt.Printf("1. Trie sequential update generated following branch updates\n") 486 for i := 0; i < len(updates); i++ { 487 if err := ms.applyPlainUpdates(plainKeys[i:i+1], updates[i:i+1]); err != nil { 488 t.Fatal(err) 489 } 490 if i == (len(updates) / 2) { 491 sequential.Reset() 492 sequential.ResetFns(ms.branchFn, ms.accountFn, ms.storageFn) 493 err := sequential.SetState(prevState) 494 require.NoError(t, err) 495 } 496 497 sequentialRoot, branchNodeUpdates, err := sequential.ReviewKeys(plainKeys[i:i+1], hashedKeys[i:i+1]) 498 require.NoError(t, err) 499 roots = append(roots, sequentialRoot) 500 501 renderUpdates(branchNodeUpdates) 502 ms.applyBranchNodeUpdates(branchNodeUpdates) 503 504 if i == (len(updates)/2 - 1) { 505 prevState, err = sequential.EncodeCurrentState(nil) 506 require.NoError(t, err) 507 } 508 } 509 510 err := ms2.applyPlainUpdates(plainKeys, updates) 511 require.NoError(t, err) 512 513 fmt.Printf("\n2. Trie batch update generated following branch updates\n") 514 // batch update 515 batchRoot, branchNodeUpdatesTwo, err := batch.ReviewKeys(plainKeys, hashedKeys) 516 require.NoError(t, err) 517 renderUpdates(branchNodeUpdatesTwo) 518 ms2.applyBranchNodeUpdates(branchNodeUpdatesTwo) 519 520 require.EqualValues(t, batchRoot, roots[len(roots)-1], 521 "expected equal roots, got sequential [%v] != batch [%v]", hex.EncodeToString(roots[len(roots)-1]), hex.EncodeToString(batchRoot)) 522 require.Lenf(t, batchRoot, 32, "root hash length should be equal to 32 bytes") 523 }