github.com/ethereum/go-ethereum@v1.16.1/triedb/pathdb/states_test.go (about) 1 // Copyright 2024 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 pathdb 18 19 import ( 20 "bytes" 21 "reflect" 22 "testing" 23 24 "github.com/ethereum/go-ethereum/common" 25 "github.com/ethereum/go-ethereum/rlp" 26 ) 27 28 func TestStatesMerge(t *testing.T) { 29 a := newStates( 30 map[common.Hash][]byte{ 31 {0xa}: {0xa0}, 32 {0xb}: {0xb0}, 33 {0xc}: {0xc0}, 34 }, 35 map[common.Hash]map[common.Hash][]byte{ 36 {0xa}: { 37 common.Hash{0x1}: {0x10}, 38 common.Hash{0x2}: {0x20}, 39 }, 40 {0xb}: { 41 common.Hash{0x1}: {0x10}, 42 }, 43 {0xc}: { 44 common.Hash{0x1}: {0x10}, 45 }, 46 }, 47 false, 48 ) 49 b := newStates( 50 map[common.Hash][]byte{ 51 {0xa}: {0xa1}, 52 {0xb}: {0xb1}, 53 {0xc}: nil, // delete account 54 }, 55 map[common.Hash]map[common.Hash][]byte{ 56 {0xa}: { 57 common.Hash{0x1}: {0x11}, 58 common.Hash{0x2}: nil, // delete slot 59 common.Hash{0x3}: {0x31}, 60 }, 61 {0xb}: { 62 common.Hash{0x1}: {0x11}, 63 }, 64 {0xc}: { 65 common.Hash{0x1}: nil, // delete slot 66 }, 67 }, 68 false, 69 ) 70 a.merge(b) 71 72 blob, exist := a.account(common.Hash{0xa}) 73 if !exist || !bytes.Equal(blob, []byte{0xa1}) { 74 t.Error("Unexpected value for account a") 75 } 76 blob, exist = a.account(common.Hash{0xb}) 77 if !exist || !bytes.Equal(blob, []byte{0xb1}) { 78 t.Error("Unexpected value for account b") 79 } 80 blob, exist = a.account(common.Hash{0xc}) 81 if !exist || len(blob) != 0 { 82 t.Error("Unexpected value for account c") 83 } 84 // unknown account 85 blob, exist = a.account(common.Hash{0xd}) 86 if exist || len(blob) != 0 { 87 t.Error("Unexpected value for account d") 88 } 89 90 blob, exist = a.storage(common.Hash{0xa}, common.Hash{0x1}) 91 if !exist || !bytes.Equal(blob, []byte{0x11}) { 92 t.Error("Unexpected value for a's storage") 93 } 94 blob, exist = a.storage(common.Hash{0xa}, common.Hash{0x2}) 95 if !exist || len(blob) != 0 { 96 t.Error("Unexpected value for a's storage") 97 } 98 blob, exist = a.storage(common.Hash{0xa}, common.Hash{0x3}) 99 if !exist || !bytes.Equal(blob, []byte{0x31}) { 100 t.Error("Unexpected value for a's storage") 101 } 102 blob, exist = a.storage(common.Hash{0xb}, common.Hash{0x1}) 103 if !exist || !bytes.Equal(blob, []byte{0x11}) { 104 t.Error("Unexpected value for b's storage") 105 } 106 blob, exist = a.storage(common.Hash{0xc}, common.Hash{0x1}) 107 if !exist || len(blob) != 0 { 108 t.Error("Unexpected value for c's storage") 109 } 110 111 // unknown storage slots 112 blob, exist = a.storage(common.Hash{0xd}, common.Hash{0x1}) 113 if exist || len(blob) != 0 { 114 t.Error("Unexpected value for d's storage") 115 } 116 } 117 118 func TestStatesRevert(t *testing.T) { 119 a := newStates( 120 map[common.Hash][]byte{ 121 {0xa}: {0xa0}, 122 {0xb}: {0xb0}, 123 {0xc}: {0xc0}, 124 }, 125 map[common.Hash]map[common.Hash][]byte{ 126 {0xa}: { 127 common.Hash{0x1}: {0x10}, 128 common.Hash{0x2}: {0x20}, 129 }, 130 {0xb}: { 131 common.Hash{0x1}: {0x10}, 132 }, 133 {0xc}: { 134 common.Hash{0x1}: {0x10}, 135 }, 136 }, 137 false, 138 ) 139 b := newStates( 140 map[common.Hash][]byte{ 141 {0xa}: {0xa1}, 142 {0xb}: {0xb1}, 143 {0xc}: nil, 144 }, 145 map[common.Hash]map[common.Hash][]byte{ 146 {0xa}: { 147 common.Hash{0x1}: {0x11}, 148 common.Hash{0x2}: nil, 149 common.Hash{0x3}: {0x31}, 150 }, 151 {0xb}: { 152 common.Hash{0x1}: {0x11}, 153 }, 154 {0xc}: { 155 common.Hash{0x1}: nil, 156 }, 157 }, 158 false, 159 ) 160 a.merge(b) 161 a.revertTo( 162 map[common.Hash][]byte{ 163 {0xa}: {0xa0}, 164 {0xb}: {0xb0}, 165 {0xc}: {0xc0}, 166 }, 167 map[common.Hash]map[common.Hash][]byte{ 168 {0xa}: { 169 common.Hash{0x1}: {0x10}, 170 common.Hash{0x2}: {0x20}, 171 common.Hash{0x3}: nil, 172 }, 173 {0xb}: { 174 common.Hash{0x1}: {0x10}, 175 }, 176 {0xc}: { 177 common.Hash{0x1}: {0x10}, 178 }, 179 }, 180 ) 181 182 blob, exist := a.account(common.Hash{0xa}) 183 if !exist || !bytes.Equal(blob, []byte{0xa0}) { 184 t.Error("Unexpected value for account a") 185 } 186 blob, exist = a.account(common.Hash{0xb}) 187 if !exist || !bytes.Equal(blob, []byte{0xb0}) { 188 t.Error("Unexpected value for account b") 189 } 190 blob, exist = a.account(common.Hash{0xc}) 191 if !exist || !bytes.Equal(blob, []byte{0xc0}) { 192 t.Error("Unexpected value for account c") 193 } 194 // unknown account 195 blob, exist = a.account(common.Hash{0xd}) 196 if exist || len(blob) != 0 { 197 t.Error("Unexpected value for account d") 198 } 199 200 blob, exist = a.storage(common.Hash{0xa}, common.Hash{0x1}) 201 if !exist || !bytes.Equal(blob, []byte{0x10}) { 202 t.Error("Unexpected value for a's storage") 203 } 204 blob, exist = a.storage(common.Hash{0xa}, common.Hash{0x2}) 205 if !exist || !bytes.Equal(blob, []byte{0x20}) { 206 t.Error("Unexpected value for a's storage") 207 } 208 blob, exist = a.storage(common.Hash{0xa}, common.Hash{0x3}) 209 if !exist || len(blob) != 0 { 210 t.Error("Unexpected value for a's storage") 211 } 212 blob, exist = a.storage(common.Hash{0xb}, common.Hash{0x1}) 213 if !exist || !bytes.Equal(blob, []byte{0x10}) { 214 t.Error("Unexpected value for b's storage") 215 } 216 blob, exist = a.storage(common.Hash{0xc}, common.Hash{0x1}) 217 if !exist || !bytes.Equal(blob, []byte{0x10}) { 218 t.Error("Unexpected value for c's storage") 219 } 220 // unknown storage slots 221 blob, exist = a.storage(common.Hash{0xd}, common.Hash{0x1}) 222 if exist || len(blob) != 0 { 223 t.Error("Unexpected value for d's storage") 224 } 225 } 226 227 // TestStateRevertAccountNullMarker tests the scenario that account x did not exist 228 // before and was created during transition w, reverting w will retain an x=nil 229 // entry in the set. 230 func TestStateRevertAccountNullMarker(t *testing.T) { 231 a := newStates(nil, nil, false) // empty initial state 232 b := newStates( 233 map[common.Hash][]byte{ 234 {0xa}: {0xa}, 235 }, 236 nil, 237 false, 238 ) 239 a.merge(b) // create account 0xa 240 a.revertTo( 241 map[common.Hash][]byte{ 242 {0xa}: nil, 243 }, 244 nil, 245 ) // revert the transition b 246 247 blob, exist := a.account(common.Hash{0xa}) 248 if !exist { 249 t.Fatal("null marker is not found") 250 } 251 if len(blob) != 0 { 252 t.Fatalf("Unexpected value for account, %v", blob) 253 } 254 } 255 256 // TestStateRevertStorageNullMarker tests the scenario that slot x did not exist 257 // before and was created during transition w, reverting w will retain an x=nil 258 // entry in the set. 259 func TestStateRevertStorageNullMarker(t *testing.T) { 260 a := newStates(map[common.Hash][]byte{ 261 {0xa}: {0xa}, 262 }, nil, false) // initial state with account 0xa 263 264 b := newStates( 265 nil, 266 map[common.Hash]map[common.Hash][]byte{ 267 {0xa}: { 268 common.Hash{0x1}: {0x1}, 269 }, 270 }, 271 false, 272 ) 273 a.merge(b) // create slot 0x1 274 a.revertTo( 275 nil, 276 map[common.Hash]map[common.Hash][]byte{ 277 {0xa}: { 278 common.Hash{0x1}: nil, 279 }, 280 }, 281 ) // revert the transition b 282 283 blob, exist := a.storage(common.Hash{0xa}, common.Hash{0x1}) 284 if !exist { 285 t.Fatal("null marker is not found") 286 } 287 if len(blob) != 0 { 288 t.Fatalf("Unexpected value for storage slot, %v", blob) 289 } 290 } 291 292 func TestStatesEncode(t *testing.T) { 293 testStatesEncode(t, false) 294 testStatesEncode(t, true) 295 } 296 297 func testStatesEncode(t *testing.T, rawStorageKey bool) { 298 s := newStates( 299 map[common.Hash][]byte{ 300 {0x1}: {0x1}, 301 }, 302 map[common.Hash]map[common.Hash][]byte{ 303 {0x1}: { 304 common.Hash{0x1}: {0x1}, 305 }, 306 }, 307 rawStorageKey, 308 ) 309 buf := bytes.NewBuffer(nil) 310 if err := s.encode(buf); err != nil { 311 t.Fatalf("Failed to encode states, %v", err) 312 } 313 var dec stateSet 314 if err := dec.decode(rlp.NewStream(buf, 0)); err != nil { 315 t.Fatalf("Failed to decode states, %v", err) 316 } 317 if !reflect.DeepEqual(s.accountData, dec.accountData) { 318 t.Fatal("Unexpected account data") 319 } 320 if !reflect.DeepEqual(s.storageData, dec.storageData) { 321 t.Fatal("Unexpected storage data") 322 } 323 if s.rawStorageKey != dec.rawStorageKey { 324 t.Fatal("Unexpected rawStorageKey flag") 325 } 326 } 327 328 func TestStateWithOriginEncode(t *testing.T) { 329 testStateWithOriginEncode(t, false) 330 testStateWithOriginEncode(t, true) 331 } 332 333 func testStateWithOriginEncode(t *testing.T, rawStorageKey bool) { 334 s := NewStateSetWithOrigin( 335 map[common.Hash][]byte{ 336 {0x1}: {0x1}, 337 }, 338 map[common.Hash]map[common.Hash][]byte{ 339 {0x1}: { 340 common.Hash{0x1}: {0x1}, 341 }, 342 }, 343 map[common.Address][]byte{ 344 {0x1}: {0x1}, 345 }, 346 map[common.Address]map[common.Hash][]byte{ 347 {0x1}: { 348 common.Hash{0x1}: {0x1}, 349 }, 350 }, 351 rawStorageKey, 352 ) 353 buf := bytes.NewBuffer(nil) 354 if err := s.encode(buf); err != nil { 355 t.Fatalf("Failed to encode states, %v", err) 356 } 357 var dec StateSetWithOrigin 358 if err := dec.decode(rlp.NewStream(buf, 0)); err != nil { 359 t.Fatalf("Failed to decode states, %v", err) 360 } 361 if !reflect.DeepEqual(s.accountData, dec.accountData) { 362 t.Fatal("Unexpected account data") 363 } 364 if !reflect.DeepEqual(s.storageData, dec.storageData) { 365 t.Fatal("Unexpected storage data") 366 } 367 if !reflect.DeepEqual(s.accountOrigin, dec.accountOrigin) { 368 t.Fatal("Unexpected account origin data") 369 } 370 if !reflect.DeepEqual(s.storageOrigin, dec.storageOrigin) { 371 t.Fatal("Unexpected storage origin data") 372 } 373 if s.rawStorageKey != dec.rawStorageKey { 374 t.Fatal("Unexpected rawStorageKey flag") 375 } 376 } 377 378 func TestStateSizeTracking(t *testing.T) { 379 expSizeA := 3*(common.HashLength+1) + /* account data */ 380 2*(2*common.HashLength+1) + /* storage data of 0xa */ 381 2*common.HashLength + 3 + /* storage data of 0xb */ 382 2*common.HashLength + 1 /* storage data of 0xc */ 383 384 a := newStates( 385 map[common.Hash][]byte{ 386 {0xa}: {0xa0}, // common.HashLength+1 387 {0xb}: {0xb0}, // common.HashLength+1 388 {0xc}: {0xc0}, // common.HashLength+1 389 }, 390 map[common.Hash]map[common.Hash][]byte{ 391 {0xa}: { 392 common.Hash{0x1}: {0x10}, // 2*common.HashLength+1 393 common.Hash{0x2}: {0x20}, // 2*common.HashLength+1 394 }, 395 {0xb}: { 396 common.Hash{0x1}: {0x10, 0x11, 0x12}, // 2*common.HashLength+3 397 }, 398 {0xc}: { 399 common.Hash{0x1}: {0x10}, // 2*common.HashLength+1 400 }, 401 }, 402 false, 403 ) 404 if a.size != uint64(expSizeA) { 405 t.Fatalf("Unexpected size, want: %d, got: %d", expSizeA, a.size) 406 } 407 408 expSizeB := common.HashLength + 2 + common.HashLength + 3 + common.HashLength + /* account data */ 409 2*common.HashLength + 3 + 2*common.HashLength + 2 + /* storage data of 0xa */ 410 2*common.HashLength + 2 + 2*common.HashLength + 2 + /* storage data of 0xb */ 411 3*2*common.HashLength /* storage data of 0xc */ 412 b := newStates( 413 map[common.Hash][]byte{ 414 {0xa}: {0xa1, 0xa1}, // common.HashLength+2 415 {0xb}: {0xb1, 0xb1, 0xb1}, // common.HashLength+3 416 {0xc}: nil, // common.HashLength, account deletion 417 }, 418 map[common.Hash]map[common.Hash][]byte{ 419 {0xa}: { 420 common.Hash{0x1}: {0x11, 0x11, 0x11}, // 2*common.HashLength+3 421 common.Hash{0x3}: {0x31, 0x31}, // 2*common.HashLength+2, slot creation 422 }, 423 {0xb}: { 424 common.Hash{0x1}: {0x11, 0x11}, // 2*common.HashLength+2 425 common.Hash{0x2}: {0x22, 0x22}, // 2*common.HashLength+2, slot creation 426 }, 427 // The storage of 0xc is entirely removed 428 {0xc}: { 429 common.Hash{0x1}: nil, // 2*common.HashLength, slot deletion 430 common.Hash{0x2}: nil, // 2*common.HashLength, slot deletion 431 common.Hash{0x3}: nil, // 2*common.HashLength, slot deletion 432 }, 433 }, 434 false, 435 ) 436 if b.size != uint64(expSizeB) { 437 t.Fatalf("Unexpected size, want: %d, got: %d", expSizeB, b.size) 438 } 439 440 a.merge(b) 441 mergeSize := expSizeA + 1 /* account a data change */ + 2 /* account b data change */ - 1 /* account c data change */ 442 mergeSize += 2*common.HashLength + 2 + 2 /* storage a change */ 443 mergeSize += 2*common.HashLength + 2 - 1 /* storage b change */ 444 mergeSize += 2*2*common.HashLength - 1 /* storage data removal of 0xc */ 445 446 if a.size != uint64(mergeSize) { 447 t.Fatalf("Unexpected size, want: %d, got: %d", mergeSize, a.size) 448 } 449 450 // Revert the set to original status 451 a.revertTo( 452 map[common.Hash][]byte{ 453 {0xa}: {0xa0}, 454 {0xb}: {0xb0}, 455 {0xc}: {0xc0}, 456 }, 457 map[common.Hash]map[common.Hash][]byte{ 458 {0xa}: { 459 common.Hash{0x1}: {0x10}, 460 common.Hash{0x2}: {0x20}, 461 common.Hash{0x3}: nil, // revert slot creation 462 }, 463 {0xb}: { 464 common.Hash{0x1}: {0x10, 0x11, 0x12}, 465 common.Hash{0x2}: nil, // revert slot creation 466 }, 467 {0xc}: { 468 common.Hash{0x1}: {0x10}, 469 common.Hash{0x2}: {0x20}, // resurrected slot 470 common.Hash{0x3}: {0x30}, // resurrected slot 471 }, 472 }, 473 ) 474 revertSize := expSizeA + 2*common.HashLength + 2*common.HashLength // delete-marker of a.3 and b.2 slot 475 revertSize += 2 * (2*common.HashLength + 1) // resurrected slot, c.2, c.3 476 if a.size != uint64(revertSize) { 477 t.Fatalf("Unexpected size, want: %d, got: %d", revertSize, a.size) 478 } 479 }