github.com/Night-mk/quorum@v21.1.0+incompatible/core/state/statedb_test.go (about) 1 // Copyright 2016 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 state 18 19 import ( 20 "bytes" 21 "encoding/binary" 22 "fmt" 23 "math" 24 "math/big" 25 "math/rand" 26 "reflect" 27 "strings" 28 "sync" 29 "testing" 30 "testing/quick" 31 32 "github.com/ethereum/go-ethereum/private/engine" 33 34 "gopkg.in/check.v1" 35 36 "github.com/ethereum/go-ethereum/common" 37 "github.com/ethereum/go-ethereum/core/rawdb" 38 "github.com/ethereum/go-ethereum/core/types" 39 ) 40 41 // Tests that updating a state trie does not leak any database writes prior to 42 // actually committing the state. 43 func TestUpdateLeaks(t *testing.T) { 44 // Create an empty state database 45 db := rawdb.NewMemoryDatabase() 46 state, _ := New(common.Hash{}, NewDatabase(db)) 47 48 // Update it with some accounts 49 for i := byte(0); i < 255; i++ { 50 addr := common.BytesToAddress([]byte{i}) 51 state.AddBalance(addr, big.NewInt(int64(11*i))) 52 state.SetNonce(addr, uint64(42*i)) 53 if i%2 == 0 { 54 state.SetState(addr, common.BytesToHash([]byte{i, i, i}), common.BytesToHash([]byte{i, i, i, i})) 55 } 56 if i%3 == 0 { 57 state.SetCode(addr, []byte{i, i, i, i, i}) 58 } 59 } 60 61 root := state.IntermediateRoot(false) 62 if err := state.Database().TrieDB().Commit(root, false); err != nil { 63 t.Errorf("can not commit trie %v to persistent database", root.Hex()) 64 } 65 66 // Ensure that no data was leaked into the database 67 it := db.NewIterator() 68 for it.Next() { 69 t.Errorf("State leaked into database: %x -> %x", it.Key(), it.Value()) 70 } 71 it.Release() 72 } 73 74 // Tests that no intermediate state of an object is stored into the database, 75 // only the one right before the commit. 76 func TestIntermediateLeaks(t *testing.T) { 77 // Create two state databases, one transitioning to the final state, the other final from the beginning 78 transDb := rawdb.NewMemoryDatabase() 79 finalDb := rawdb.NewMemoryDatabase() 80 transState, _ := New(common.Hash{}, NewDatabase(transDb)) 81 finalState, _ := New(common.Hash{}, NewDatabase(finalDb)) 82 83 modify := func(state *StateDB, addr common.Address, i, tweak byte) { 84 state.SetBalance(addr, big.NewInt(int64(11*i)+int64(tweak))) 85 state.SetNonce(addr, uint64(42*i+tweak)) 86 if i%2 == 0 { 87 state.SetState(addr, common.Hash{i, i, i, 0}, common.Hash{}) 88 state.SetState(addr, common.Hash{i, i, i, tweak}, common.Hash{i, i, i, i, tweak}) 89 } 90 if i%3 == 0 { 91 state.SetCode(addr, []byte{i, i, i, i, i, tweak}) 92 } 93 } 94 95 // Modify the transient state. 96 for i := byte(0); i < 255; i++ { 97 modify(transState, common.Address{i}, i, 0) 98 } 99 // Write modifications to trie. 100 transState.IntermediateRoot(false) 101 102 // Overwrite all the data with new values in the transient database. 103 for i := byte(0); i < 255; i++ { 104 modify(transState, common.Address{i}, i, 99) 105 modify(finalState, common.Address{i}, i, 99) 106 } 107 108 // Commit and cross check the databases. 109 transRoot, err := transState.Commit(false) 110 if err != nil { 111 t.Fatalf("failed to commit transition state: %v", err) 112 } 113 if err = transState.Database().TrieDB().Commit(transRoot, false); err != nil { 114 t.Errorf("can not commit trie %v to persistent database", transRoot.Hex()) 115 } 116 117 finalRoot, err := finalState.Commit(false) 118 if err != nil { 119 t.Fatalf("failed to commit final state: %v", err) 120 } 121 if err = finalState.Database().TrieDB().Commit(finalRoot, false); err != nil { 122 t.Errorf("can not commit trie %v to persistent database", finalRoot.Hex()) 123 } 124 125 it := finalDb.NewIterator() 126 for it.Next() { 127 key, fvalue := it.Key(), it.Value() 128 tvalue, err := transDb.Get(key) 129 if err != nil { 130 t.Errorf("entry missing from the transition database: %x -> %x", key, fvalue) 131 } 132 if !bytes.Equal(fvalue, tvalue) { 133 t.Errorf("the value associate key %x is mismatch,: %x in transition database ,%x in final database", key, tvalue, fvalue) 134 } 135 } 136 it.Release() 137 138 it = transDb.NewIterator() 139 for it.Next() { 140 key, tvalue := it.Key(), it.Value() 141 fvalue, err := finalDb.Get(key) 142 if err != nil { 143 t.Errorf("extra entry in the transition database: %x -> %x", key, it.Value()) 144 } 145 if !bytes.Equal(fvalue, tvalue) { 146 t.Errorf("the value associate key %x is mismatch,: %x in transition database ,%x in final database", key, tvalue, fvalue) 147 } 148 } 149 } 150 151 func TestStorageRoot(t *testing.T) { 152 var ( 153 mem = rawdb.NewMemoryDatabase() 154 db = NewDatabase(mem) 155 state, _ = New(common.Hash{}, db) 156 addr = common.Address{1} 157 key = common.Hash{1} 158 value = common.Hash{42} 159 160 empty = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") 161 ) 162 163 so := state.GetOrNewStateObject(addr) 164 165 emptyRoot := so.storageRoot(db) 166 if emptyRoot != empty { 167 t.Errorf("Invalid empty storage root, expected %x, got %x", empty, emptyRoot) 168 } 169 170 // add a bit of state 171 so.SetState(db, key, value) 172 state.Commit(false) 173 174 root := so.storageRoot(db) 175 expected := common.HexToHash("63511abd258fa907afa30cb118b53744a4f49055bb3f531da512c6b866fc2ffb") 176 177 if expected != root { 178 t.Errorf("Invalid storage root, expected %x, got %x", expected, root) 179 } 180 } 181 182 // TestCopy tests that copying a statedb object indeed makes the original and 183 // the copy independent of each other. This test is a regression test against 184 // https://github.com/ethereum/go-ethereum/pull/15549. 185 func TestCopy(t *testing.T) { 186 // Create a random state test to copy and modify "independently" 187 orig, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase())) 188 189 for i := byte(0); i < 255; i++ { 190 obj := orig.GetOrNewStateObject(common.BytesToAddress([]byte{i})) 191 obj.AddBalance(big.NewInt(int64(i))) 192 orig.updateStateObject(obj) 193 } 194 orig.Finalise(false) 195 196 // Copy the state 197 copy := orig.Copy() 198 199 // Copy the copy state 200 ccopy := copy.Copy() 201 202 // modify all in memory 203 for i := byte(0); i < 255; i++ { 204 origObj := orig.GetOrNewStateObject(common.BytesToAddress([]byte{i})) 205 copyObj := copy.GetOrNewStateObject(common.BytesToAddress([]byte{i})) 206 ccopyObj := ccopy.GetOrNewStateObject(common.BytesToAddress([]byte{i})) 207 208 origObj.AddBalance(big.NewInt(2 * int64(i))) 209 copyObj.AddBalance(big.NewInt(3 * int64(i))) 210 ccopyObj.AddBalance(big.NewInt(4 * int64(i))) 211 212 orig.updateStateObject(origObj) 213 copy.updateStateObject(copyObj) 214 ccopy.updateStateObject(copyObj) 215 } 216 217 // Finalise the changes on all concurrently 218 finalise := func(wg *sync.WaitGroup, db *StateDB) { 219 defer wg.Done() 220 db.Finalise(true) 221 } 222 223 var wg sync.WaitGroup 224 wg.Add(3) 225 go finalise(&wg, orig) 226 go finalise(&wg, copy) 227 go finalise(&wg, ccopy) 228 wg.Wait() 229 230 // Verify that the three states have been updated independently 231 for i := byte(0); i < 255; i++ { 232 origObj := orig.GetOrNewStateObject(common.BytesToAddress([]byte{i})) 233 copyObj := copy.GetOrNewStateObject(common.BytesToAddress([]byte{i})) 234 ccopyObj := ccopy.GetOrNewStateObject(common.BytesToAddress([]byte{i})) 235 236 if want := big.NewInt(3 * int64(i)); origObj.Balance().Cmp(want) != 0 { 237 t.Errorf("orig obj %d: balance mismatch: have %v, want %v", i, origObj.Balance(), want) 238 } 239 if want := big.NewInt(4 * int64(i)); copyObj.Balance().Cmp(want) != 0 { 240 t.Errorf("copy obj %d: balance mismatch: have %v, want %v", i, copyObj.Balance(), want) 241 } 242 if want := big.NewInt(5 * int64(i)); ccopyObj.Balance().Cmp(want) != 0 { 243 t.Errorf("copy obj %d: balance mismatch: have %v, want %v", i, ccopyObj.Balance(), want) 244 } 245 } 246 } 247 248 func TestSnapshotRandom(t *testing.T) { 249 config := &quick.Config{MaxCount: 1000} 250 err := quick.Check((*snapshotTest).run, config) 251 if cerr, ok := err.(*quick.CheckError); ok { 252 test := cerr.In[0].(*snapshotTest) 253 t.Errorf("%v:\n%s", test.err, test) 254 } else if err != nil { 255 t.Error(err) 256 } 257 } 258 259 // A snapshotTest checks that reverting StateDB snapshots properly undoes all changes 260 // captured by the snapshot. Instances of this test with pseudorandom content are created 261 // by Generate. 262 // 263 // The test works as follows: 264 // 265 // A new state is created and all actions are applied to it. Several snapshots are taken 266 // in between actions. The test then reverts each snapshot. For each snapshot the actions 267 // leading up to it are replayed on a fresh, empty state. The behaviour of all public 268 // accessor methods on the reverted state must match the return value of the equivalent 269 // methods on the replayed state. 270 type snapshotTest struct { 271 addrs []common.Address // all account addresses 272 actions []testAction // modifications to the state 273 snapshots []int // actions indexes at which snapshot is taken 274 err error // failure details are reported through this field 275 } 276 277 type testAction struct { 278 name string 279 fn func(testAction, *StateDB) 280 args []int64 281 noAddr bool 282 } 283 284 // newTestAction creates a random action that changes state. 285 func newTestAction(addr common.Address, r *rand.Rand) testAction { 286 actions := []testAction{ 287 { 288 name: "SetBalance", 289 fn: func(a testAction, s *StateDB) { 290 s.SetBalance(addr, big.NewInt(a.args[0])) 291 }, 292 args: make([]int64, 1), 293 }, 294 { 295 name: "AddBalance", 296 fn: func(a testAction, s *StateDB) { 297 s.AddBalance(addr, big.NewInt(a.args[0])) 298 }, 299 args: make([]int64, 1), 300 }, 301 { 302 name: "SetNonce", 303 fn: func(a testAction, s *StateDB) { 304 s.SetNonce(addr, uint64(a.args[0])) 305 }, 306 args: make([]int64, 1), 307 }, 308 { 309 name: "SetState", 310 fn: func(a testAction, s *StateDB) { 311 var key, val common.Hash 312 binary.BigEndian.PutUint16(key[:], uint16(a.args[0])) 313 binary.BigEndian.PutUint16(val[:], uint16(a.args[1])) 314 s.SetState(addr, key, val) 315 }, 316 args: make([]int64, 2), 317 }, 318 { 319 name: "SetCode", 320 fn: func(a testAction, s *StateDB) { 321 code := make([]byte, 16) 322 binary.BigEndian.PutUint64(code, uint64(a.args[0])) 323 binary.BigEndian.PutUint64(code[8:], uint64(a.args[1])) 324 s.SetCode(addr, code) 325 }, 326 args: make([]int64, 2), 327 }, 328 { 329 name: "SetPrivacyMetadata", 330 fn: func(a testAction, s *StateDB) { 331 332 privFlag := engine.PrivacyFlagType((uint64(a.args[0])%2)*2 + 1) // the only possible values should be 1 and 3 333 b := make([]byte, 8) 334 binary.BigEndian.PutUint64(b, uint64(a.args[1])) 335 hash := common.BytesToEncryptedPayloadHash(b) 336 337 s.SetPrivacyMetadata(addr, &PrivacyMetadata{ 338 CreationTxHash: hash, 339 PrivacyFlag: privFlag, 340 }) 341 }, 342 args: make([]int64, 2), 343 }, 344 { 345 name: "CreateAccount", 346 fn: func(a testAction, s *StateDB) { 347 s.CreateAccount(addr) 348 }, 349 }, 350 { 351 name: "Suicide", 352 fn: func(a testAction, s *StateDB) { 353 s.Suicide(addr) 354 }, 355 }, 356 { 357 name: "AddRefund", 358 fn: func(a testAction, s *StateDB) { 359 s.AddRefund(uint64(a.args[0])) 360 }, 361 args: make([]int64, 1), 362 noAddr: true, 363 }, 364 { 365 name: "AddLog", 366 fn: func(a testAction, s *StateDB) { 367 data := make([]byte, 2) 368 binary.BigEndian.PutUint16(data, uint16(a.args[0])) 369 s.AddLog(&types.Log{Address: addr, Data: data}) 370 }, 371 args: make([]int64, 1), 372 }, 373 { 374 name: "AddPreimage", 375 fn: func(a testAction, s *StateDB) { 376 preimage := []byte{1} 377 hash := common.BytesToHash(preimage) 378 s.AddPreimage(hash, preimage) 379 }, 380 args: make([]int64, 1), 381 }, 382 } 383 action := actions[r.Intn(len(actions))] 384 var nameargs []string 385 if !action.noAddr { 386 nameargs = append(nameargs, addr.Hex()) 387 } 388 for i := range action.args { 389 action.args[i] = rand.Int63n(100) 390 nameargs = append(nameargs, fmt.Sprint(action.args[i])) 391 } 392 action.name += strings.Join(nameargs, ", ") 393 return action 394 } 395 396 // Generate returns a new snapshot test of the given size. All randomness is 397 // derived from r. 398 func (*snapshotTest) Generate(r *rand.Rand, size int) reflect.Value { 399 // Generate random actions. 400 addrs := make([]common.Address, 50) 401 for i := range addrs { 402 addrs[i][0] = byte(i) 403 } 404 actions := make([]testAction, size) 405 for i := range actions { 406 addr := addrs[r.Intn(len(addrs))] 407 actions[i] = newTestAction(addr, r) 408 } 409 // Generate snapshot indexes. 410 nsnapshots := int(math.Sqrt(float64(size))) 411 if size > 0 && nsnapshots == 0 { 412 nsnapshots = 1 413 } 414 snapshots := make([]int, nsnapshots) 415 snaplen := len(actions) / nsnapshots 416 for i := range snapshots { 417 // Try to place the snapshots some number of actions apart from each other. 418 snapshots[i] = (i * snaplen) + r.Intn(snaplen) 419 } 420 return reflect.ValueOf(&snapshotTest{addrs, actions, snapshots, nil}) 421 } 422 423 func (test *snapshotTest) String() string { 424 out := new(bytes.Buffer) 425 sindex := 0 426 for i, action := range test.actions { 427 if len(test.snapshots) > sindex && i == test.snapshots[sindex] { 428 fmt.Fprintf(out, "---- snapshot %d ----\n", sindex) 429 sindex++ 430 } 431 fmt.Fprintf(out, "%4d: %s\n", i, action.name) 432 } 433 return out.String() 434 } 435 436 func (test *snapshotTest) run() bool { 437 // Run all actions and create snapshots. 438 var ( 439 state, _ = New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase())) 440 snapshotRevs = make([]int, len(test.snapshots)) 441 sindex = 0 442 ) 443 for i, action := range test.actions { 444 if len(test.snapshots) > sindex && i == test.snapshots[sindex] { 445 snapshotRevs[sindex] = state.Snapshot() 446 sindex++ 447 } 448 action.fn(action, state) 449 } 450 // Revert all snapshots in reverse order. Each revert must yield a state 451 // that is equivalent to fresh state with all actions up the snapshot applied. 452 for sindex--; sindex >= 0; sindex-- { 453 checkstate, _ := New(common.Hash{}, state.Database()) 454 for _, action := range test.actions[:test.snapshots[sindex]] { 455 action.fn(action, checkstate) 456 } 457 state.RevertToSnapshot(snapshotRevs[sindex]) 458 if err := test.checkEqual(state, checkstate); err != nil { 459 test.err = fmt.Errorf("state mismatch after revert to snapshot %d\n%v", sindex, err) 460 return false 461 } 462 } 463 return true 464 } 465 466 // checkEqual checks that methods of state and checkstate return the same values. 467 func (test *snapshotTest) checkEqual(state, checkstate *StateDB) error { 468 for _, addr := range test.addrs { 469 var err error 470 checkeq := func(op string, a, b interface{}) bool { 471 if err == nil && !reflect.DeepEqual(a, b) { 472 err = fmt.Errorf("got %s(%s) == %v, want %v", op, addr.Hex(), a, b) 473 return false 474 } 475 return true 476 } 477 // Check basic accessor methods. 478 checkeq("Exist", state.Exist(addr), checkstate.Exist(addr)) 479 checkeq("HasSuicided", state.HasSuicided(addr), checkstate.HasSuicided(addr)) 480 checkeq("GetBalance", state.GetBalance(addr), checkstate.GetBalance(addr)) 481 checkeq("GetNonce", state.GetNonce(addr), checkstate.GetNonce(addr)) 482 checkeq("GetCode", state.GetCode(addr), checkstate.GetCode(addr)) 483 checkeq("GetCodeHash", state.GetCodeHash(addr), checkstate.GetCodeHash(addr)) 484 checkeq("GetCodeSize", state.GetCodeSize(addr), checkstate.GetCodeSize(addr)) 485 statePM, _ := state.GetPrivacyMetadata(addr) 486 checkStatePM, _ := checkstate.GetPrivacyMetadata(addr) 487 checkeq("GetPrivacyMetadata", statePM, checkStatePM) 488 // Check storage. 489 if obj := state.getStateObject(addr); obj != nil { 490 state.ForEachStorage(addr, func(key, value common.Hash) bool { 491 return checkeq("GetState("+key.Hex()+")", checkstate.GetState(addr, key), value) 492 }) 493 checkstate.ForEachStorage(addr, func(key, value common.Hash) bool { 494 return checkeq("GetState("+key.Hex()+")", checkstate.GetState(addr, key), value) 495 }) 496 } 497 if err != nil { 498 return err 499 } 500 } 501 502 if state.GetRefund() != checkstate.GetRefund() { 503 return fmt.Errorf("got GetRefund() == %d, want GetRefund() == %d", 504 state.GetRefund(), checkstate.GetRefund()) 505 } 506 if !reflect.DeepEqual(state.GetLogs(common.Hash{}), checkstate.GetLogs(common.Hash{})) { 507 return fmt.Errorf("got GetLogs(common.Hash{}) == %v, want GetLogs(common.Hash{}) == %v", 508 state.GetLogs(common.Hash{}), checkstate.GetLogs(common.Hash{})) 509 } 510 return nil 511 } 512 513 func (s *StateSuite) TestTouchDelete(c *check.C) { 514 s.state.GetOrNewStateObject(common.Address{}) 515 root, _ := s.state.Commit(false) 516 s.state.Reset(root) 517 518 snapshot := s.state.Snapshot() 519 s.state.AddBalance(common.Address{}, new(big.Int)) 520 521 if len(s.state.journal.dirties) != 1 { 522 c.Fatal("expected one dirty state object") 523 } 524 s.state.RevertToSnapshot(snapshot) 525 if len(s.state.journal.dirties) != 0 { 526 c.Fatal("expected no dirty state object") 527 } 528 } 529 530 // TestCopyOfCopy tests that modified objects are carried over to the copy, and the copy of the copy. 531 // See https://github.com/ethereum/go-ethereum/pull/15225#issuecomment-380191512 532 func TestCopyOfCopy(t *testing.T) { 533 state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase())) 534 addr := common.HexToAddress("aaaa") 535 state.SetBalance(addr, big.NewInt(42)) 536 537 if got := state.Copy().GetBalance(addr).Uint64(); got != 42 { 538 t.Fatalf("1st copy fail, expected 42, got %v", got) 539 } 540 if got := state.Copy().Copy().GetBalance(addr).Uint64(); got != 42 { 541 t.Fatalf("2nd copy fail, expected 42, got %v", got) 542 } 543 } 544 545 // Tests a regression where committing a copy lost some internal meta information, 546 // leading to corrupted subsequent copies. 547 // 548 // See https://github.com/ethereum/go-ethereum/issues/20106. 549 func TestCopyCommitCopy(t *testing.T) { 550 state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase())) 551 552 // Create an account and check if the retrieved balance is correct 553 addr := common.HexToAddress("0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe") 554 skey := common.HexToHash("aaa") 555 sval := common.HexToHash("bbb") 556 557 state.SetBalance(addr, big.NewInt(42)) // Change the account trie 558 state.SetCode(addr, []byte("hello")) // Change an external metadata 559 state.SetState(addr, skey, sval) // Change the storage trie 560 561 if balance := state.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { 562 t.Fatalf("initial balance mismatch: have %v, want %v", balance, 42) 563 } 564 if code := state.GetCode(addr); !bytes.Equal(code, []byte("hello")) { 565 t.Fatalf("initial code mismatch: have %x, want %x", code, []byte("hello")) 566 } 567 if val := state.GetState(addr, skey); val != sval { 568 t.Fatalf("initial non-committed storage slot mismatch: have %x, want %x", val, sval) 569 } 570 if val := state.GetCommittedState(addr, skey); val != (common.Hash{}) { 571 t.Fatalf("initial committed storage slot mismatch: have %x, want %x", val, common.Hash{}) 572 } 573 // Copy the non-committed state database and check pre/post commit balance 574 copyOne := state.Copy() 575 if balance := copyOne.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { 576 t.Fatalf("first copy pre-commit balance mismatch: have %v, want %v", balance, 42) 577 } 578 if code := copyOne.GetCode(addr); !bytes.Equal(code, []byte("hello")) { 579 t.Fatalf("first copy pre-commit code mismatch: have %x, want %x", code, []byte("hello")) 580 } 581 if val := copyOne.GetState(addr, skey); val != sval { 582 t.Fatalf("first copy pre-commit non-committed storage slot mismatch: have %x, want %x", val, sval) 583 } 584 if val := copyOne.GetCommittedState(addr, skey); val != (common.Hash{}) { 585 t.Fatalf("first copy pre-commit committed storage slot mismatch: have %x, want %x", val, common.Hash{}) 586 } 587 588 copyOne.Commit(false) 589 if balance := copyOne.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { 590 t.Fatalf("first copy post-commit balance mismatch: have %v, want %v", balance, 42) 591 } 592 if code := copyOne.GetCode(addr); !bytes.Equal(code, []byte("hello")) { 593 t.Fatalf("first copy post-commit code mismatch: have %x, want %x", code, []byte("hello")) 594 } 595 if val := copyOne.GetState(addr, skey); val != sval { 596 t.Fatalf("first copy post-commit non-committed storage slot mismatch: have %x, want %x", val, sval) 597 } 598 if val := copyOne.GetCommittedState(addr, skey); val != sval { 599 t.Fatalf("first copy post-commit committed storage slot mismatch: have %x, want %x", val, sval) 600 } 601 // Copy the copy and check the balance once more 602 copyTwo := copyOne.Copy() 603 if balance := copyTwo.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { 604 t.Fatalf("second copy balance mismatch: have %v, want %v", balance, 42) 605 } 606 if code := copyTwo.GetCode(addr); !bytes.Equal(code, []byte("hello")) { 607 t.Fatalf("second copy code mismatch: have %x, want %x", code, []byte("hello")) 608 } 609 if val := copyTwo.GetState(addr, skey); val != sval { 610 t.Fatalf("second copy non-committed storage slot mismatch: have %x, want %x", val, sval) 611 } 612 if val := copyTwo.GetCommittedState(addr, skey); val != sval { 613 t.Fatalf("second copy post-commit committed storage slot mismatch: have %x, want %x", val, sval) 614 } 615 } 616 617 // Tests a regression where committing a copy lost some internal meta information, 618 // leading to corrupted subsequent copies. 619 // 620 // See https://github.com/ethereum/go-ethereum/issues/20106. 621 func TestCopyCopyCommitCopy(t *testing.T) { 622 state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase())) 623 624 // Create an account and check if the retrieved balance is correct 625 addr := common.HexToAddress("0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe") 626 skey := common.HexToHash("aaa") 627 sval := common.HexToHash("bbb") 628 629 state.SetBalance(addr, big.NewInt(42)) // Change the account trie 630 state.SetCode(addr, []byte("hello")) // Change an external metadata 631 state.SetState(addr, skey, sval) // Change the storage trie 632 633 if balance := state.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { 634 t.Fatalf("initial balance mismatch: have %v, want %v", balance, 42) 635 } 636 if code := state.GetCode(addr); !bytes.Equal(code, []byte("hello")) { 637 t.Fatalf("initial code mismatch: have %x, want %x", code, []byte("hello")) 638 } 639 if val := state.GetState(addr, skey); val != sval { 640 t.Fatalf("initial non-committed storage slot mismatch: have %x, want %x", val, sval) 641 } 642 if val := state.GetCommittedState(addr, skey); val != (common.Hash{}) { 643 t.Fatalf("initial committed storage slot mismatch: have %x, want %x", val, common.Hash{}) 644 } 645 // Copy the non-committed state database and check pre/post commit balance 646 copyOne := state.Copy() 647 if balance := copyOne.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { 648 t.Fatalf("first copy balance mismatch: have %v, want %v", balance, 42) 649 } 650 if code := copyOne.GetCode(addr); !bytes.Equal(code, []byte("hello")) { 651 t.Fatalf("first copy code mismatch: have %x, want %x", code, []byte("hello")) 652 } 653 if val := copyOne.GetState(addr, skey); val != sval { 654 t.Fatalf("first copy non-committed storage slot mismatch: have %x, want %x", val, sval) 655 } 656 if val := copyOne.GetCommittedState(addr, skey); val != (common.Hash{}) { 657 t.Fatalf("first copy committed storage slot mismatch: have %x, want %x", val, common.Hash{}) 658 } 659 // Copy the copy and check the balance once more 660 copyTwo := copyOne.Copy() 661 if balance := copyTwo.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { 662 t.Fatalf("second copy pre-commit balance mismatch: have %v, want %v", balance, 42) 663 } 664 if code := copyTwo.GetCode(addr); !bytes.Equal(code, []byte("hello")) { 665 t.Fatalf("second copy pre-commit code mismatch: have %x, want %x", code, []byte("hello")) 666 } 667 if val := copyTwo.GetState(addr, skey); val != sval { 668 t.Fatalf("second copy pre-commit non-committed storage slot mismatch: have %x, want %x", val, sval) 669 } 670 if val := copyTwo.GetCommittedState(addr, skey); val != (common.Hash{}) { 671 t.Fatalf("second copy pre-commit committed storage slot mismatch: have %x, want %x", val, common.Hash{}) 672 } 673 copyTwo.Commit(false) 674 if balance := copyTwo.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { 675 t.Fatalf("second copy post-commit balance mismatch: have %v, want %v", balance, 42) 676 } 677 if code := copyTwo.GetCode(addr); !bytes.Equal(code, []byte("hello")) { 678 t.Fatalf("second copy post-commit code mismatch: have %x, want %x", code, []byte("hello")) 679 } 680 if val := copyTwo.GetState(addr, skey); val != sval { 681 t.Fatalf("second copy post-commit non-committed storage slot mismatch: have %x, want %x", val, sval) 682 } 683 if val := copyTwo.GetCommittedState(addr, skey); val != sval { 684 t.Fatalf("second copy post-commit committed storage slot mismatch: have %x, want %x", val, sval) 685 } 686 // Copy the copy-copy and check the balance once more 687 copyThree := copyTwo.Copy() 688 if balance := copyThree.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { 689 t.Fatalf("third copy balance mismatch: have %v, want %v", balance, 42) 690 } 691 if code := copyThree.GetCode(addr); !bytes.Equal(code, []byte("hello")) { 692 t.Fatalf("third copy code mismatch: have %x, want %x", code, []byte("hello")) 693 } 694 if val := copyThree.GetState(addr, skey); val != sval { 695 t.Fatalf("third copy non-committed storage slot mismatch: have %x, want %x", val, sval) 696 } 697 if val := copyThree.GetCommittedState(addr, skey); val != sval { 698 t.Fatalf("third copy committed storage slot mismatch: have %x, want %x", val, sval) 699 } 700 } 701 702 // TestDeleteCreateRevert tests a weird state transition corner case that we hit 703 // while changing the internals of statedb. The workflow is that a contract is 704 // self destructed, then in a followup transaction (but same block) it's created 705 // again and the transaction reverted. 706 // 707 // The original statedb implementation flushed dirty objects to the tries after 708 // each transaction, so this works ok. The rework accumulated writes in memory 709 // first, but the journal wiped the entire state object on create-revert. 710 func TestDeleteCreateRevert(t *testing.T) { 711 // Create an initial state with a single contract 712 state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase())) 713 714 addr := toAddr([]byte("so")) 715 state.SetBalance(addr, big.NewInt(1)) 716 717 root, _ := state.Commit(false) 718 state.Reset(root) 719 720 // Simulate self-destructing in one transaction, then create-reverting in another 721 state.Suicide(addr) 722 state.Finalise(true) 723 724 id := state.Snapshot() 725 state.SetBalance(addr, big.NewInt(2)) 726 state.RevertToSnapshot(id) 727 728 // Commit the entire state and make sure we don't crash and have the correct state 729 root, _ = state.Commit(true) 730 state.Reset(root) 731 732 if state.getStateObject(addr) != nil { 733 t.Fatalf("self-destructed contract came alive") 734 } 735 } 736 737 // Quorum - Privacy Enhancements 738 func TestPrivacyMetadataIsSavedOnStateDbCommit(t *testing.T) { 739 ethDb := rawdb.NewMemoryDatabase() 740 stateDb := NewDatabase(ethDb) 741 state, _ := New(common.Hash{}, stateDb) 742 743 addr := common.Address{1} 744 state.CreateAccount(addr) 745 746 state.SetNonce(addr, uint64(1)) 747 state.SetPrivacyMetadata(addr, &PrivacyMetadata{ 748 PrivacyFlag: engine.PrivacyFlagPartyProtection, 749 CreationTxHash: common.EncryptedPayloadHash{1}, 750 }) 751 752 privMetaData, _ := state.GetCommittedStatePrivacyMetadata(addr) 753 if privMetaData != nil { 754 t.Errorf("privacy metadata should not have been stored before commit") 755 } 756 757 state.Commit(false) 758 759 privMetaData, _ = state.GetCommittedStatePrivacyMetadata(addr) 760 if privMetaData == nil { 761 t.Errorf("privacy metadata should have been stored during commit") 762 } 763 } 764 765 func TestPrivacyMetadataIsUpdatedOnAccountReCreateWithDifferentPrivacyMetadata(t *testing.T) { 766 ethDb := rawdb.NewMemoryDatabase() 767 stateDb := NewDatabase(ethDb) 768 state, _ := New(common.Hash{}, stateDb) 769 770 addr := common.Address{1} 771 state.CreateAccount(addr) 772 773 state.SetNonce(addr, uint64(1)) 774 state.SetPrivacyMetadata(addr, &PrivacyMetadata{ 775 PrivacyFlag: engine.PrivacyFlagPartyProtection, 776 CreationTxHash: common.EncryptedPayloadHash{1}, 777 }) 778 state.Commit(false) 779 780 privMetaData, _ := state.GetCommittedStatePrivacyMetadata(addr) 781 if privMetaData == nil { 782 t.Errorf("privacy metadata should have been stored during commit") 783 } 784 785 state.CreateAccount(addr) 786 state.SetNonce(addr, uint64(1)) 787 state.SetPrivacyMetadata(addr, &PrivacyMetadata{ 788 PrivacyFlag: engine.PrivacyFlagStateValidation, 789 CreationTxHash: common.EncryptedPayloadHash{1}, 790 }) 791 792 state.Commit(false) 793 794 privMetaData, _ = state.GetCommittedStatePrivacyMetadata(addr) 795 if privMetaData == nil { 796 t.Errorf("privacy metadata should have been updated during commit") 797 } else if privMetaData.PrivacyFlag != engine.PrivacyFlagStateValidation { 798 t.Errorf("privacy metadata should have StateValidation as the the privacy flag") 799 } 800 } 801 802 func TestPrivacyMetadataIsRemovedOnAccountSuicide(t *testing.T) { 803 ethDb := rawdb.NewMemoryDatabase() 804 stateDb := NewDatabase(ethDb) 805 state, _ := New(common.Hash{}, stateDb) 806 807 addr := common.Address{1} 808 state.CreateAccount(addr) 809 810 state.SetNonce(addr, uint64(1)) 811 state.SetPrivacyMetadata(addr, &PrivacyMetadata{ 812 PrivacyFlag: engine.PrivacyFlagPartyProtection, 813 CreationTxHash: common.EncryptedPayloadHash{1}, 814 }) 815 state.Commit(false) 816 817 privMetaData, _ := state.GetCommittedStatePrivacyMetadata(addr) 818 if privMetaData == nil { 819 t.Errorf("privacy metadata should have been stored during commit") 820 } 821 822 state.Suicide(addr) 823 state.Commit(false) 824 825 privMetaData, _ = state.GetCommittedStatePrivacyMetadata(addr) 826 if privMetaData != nil { 827 t.Errorf("privacy metadata should have been deleted during account suicide") 828 } 829 } 830 831 func TestPrivacyMetadataChangesAreRolledBackOnRevert(t *testing.T) { 832 ethDb := rawdb.NewMemoryDatabase() 833 stateDb := NewDatabase(ethDb) 834 state, _ := New(common.Hash{}, stateDb) 835 836 addr := common.Address{1} 837 state.CreateAccount(addr) 838 839 state.SetNonce(addr, uint64(1)) 840 state.SetPrivacyMetadata(addr, &PrivacyMetadata{ 841 PrivacyFlag: engine.PrivacyFlagPartyProtection, 842 CreationTxHash: common.BytesToEncryptedPayloadHash([]byte("one")), 843 }) 844 state.Commit(false) 845 846 privMetaData, _ := state.GetCommittedStatePrivacyMetadata(addr) 847 if privMetaData == nil { 848 t.Errorf("privacy metadata should have been stored during commit") 849 } 850 851 // update privacy metadata 852 state.SetPrivacyMetadata(addr, &PrivacyMetadata{ 853 PrivacyFlag: engine.PrivacyFlagStateValidation, 854 CreationTxHash: common.BytesToEncryptedPayloadHash([]byte("two")), 855 }) 856 857 // record the snapshot 858 snapshot := state.Snapshot() 859 860 privMetaData, _ = state.GetPrivacyMetadata(addr) 861 if privMetaData.CreationTxHash != common.BytesToEncryptedPayloadHash([]byte("two")) { 862 t.Errorf("current privacy metadata creation tx hash does not match the expected value") 863 } 864 865 // update the metadata 866 state.SetPrivacyMetadata(addr, &PrivacyMetadata{ 867 PrivacyFlag: engine.PrivacyFlagStateValidation, 868 CreationTxHash: common.BytesToEncryptedPayloadHash([]byte("three")), 869 }) 870 871 privMetaData, _ = state.GetPrivacyMetadata(addr) 872 if privMetaData.CreationTxHash != common.BytesToEncryptedPayloadHash([]byte("three")) { 873 t.Errorf("current privacy metadata creation tx hash does not match the expected value") 874 } 875 876 // revert to snapshot 877 state.RevertToSnapshot(snapshot) 878 879 privMetaData, _ = state.GetPrivacyMetadata(addr) 880 if privMetaData.CreationTxHash != common.BytesToEncryptedPayloadHash([]byte("two")) { 881 t.Errorf("current privacy metadata creation tx hash does not match the expected value") 882 } 883 884 } 885 886 // End Quorum - Privacy Enhancements