1#[cfg(test)]
2mod tests {
3 use crate::{
4 test_utils::create_test_provider_factory, AccountReader, StorageTrieWriter, TrieWriter,
5 };
6 use alloy_primitives::{keccak256, map::HashMap, Address, B256, U256};
7 use reth_db_api::{
8 cursor::{DbCursorRO, DbCursorRW, DbDupCursorRO},
9 models::{AccountBeforeTx, BlockNumberAddress},
10 tables,
11 transaction::{DbTx, DbTxMut},
12 };
13 use reth_ethereum_primitives::Receipt;
14 use reth_execution_types::ExecutionOutcome;
15 use reth_primitives_traits::{Account, StorageEntry};
16 use reth_storage_api::{DatabaseProviderFactory, HashedPostStateProvider, StateWriter};
17 use reth_trie::{
18 test_utils::{state_root, storage_root_prehashed},
19 HashedPostState, HashedStorage, StateRoot, StorageRoot, StorageRootProgress,
20 };
21 use reth_trie_db::{DatabaseStateRoot, DatabaseStorageRoot};
22 use revm_database::{
23 states::{
24 bundle_state::BundleRetention, changes::PlainStorageRevert, PlainStorageChangeset,
25 },
26 BundleState, OriginalValuesKnown, State,
27 };
28 use revm_database_interface::{DatabaseCommit, EmptyDB};
29 use revm_state::{
30 Account as RevmAccount, AccountInfo as RevmAccountInfo, AccountStatus, EvmStorageSlot,
31 };
32 use std::{collections::BTreeMap, str::FromStr};
33
34 #[test]
35 fn wiped_entries_are_removed() {
36 let provider_factory = create_test_provider_factory();
37
38 let addresses = (0..10).map(|_| Address::random()).collect::<Vec<_>>();
39 let destroyed_address = *addresses.first().unwrap();
40 let destroyed_address_hashed = keccak256(destroyed_address);
41 let slot = B256::with_last_byte(1);
42 let hashed_slot = keccak256(slot);
43 {
44 let provider_rw = provider_factory.provider_rw().unwrap();
45 let mut accounts_cursor =
46 provider_rw.tx_ref().cursor_write::<tables::HashedAccounts>().unwrap();
47 let mut storage_cursor =
48 provider_rw.tx_ref().cursor_write::<tables::HashedStorages>().unwrap();
49
50 for address in addresses {
51 let hashed_address = keccak256(address);
52 accounts_cursor
53 .insert(hashed_address, &Account { nonce: 1, ..Default::default() })
54 .unwrap();
55 storage_cursor
56 .insert(
57 hashed_address,
58 &StorageEntry { key: hashed_slot, value: U256::from(1) },
59 )
60 .unwrap();
61 }
62 provider_rw.commit().unwrap();
63 }
64
65 let mut hashed_state = HashedPostState::default();
66 hashed_state.accounts.insert(destroyed_address_hashed, None);
67 hashed_state.storages.insert(destroyed_address_hashed, HashedStorage::new(true));
68
69 let provider_rw = provider_factory.provider_rw().unwrap();
70 assert!(matches!(provider_rw.write_hashed_state(&hashed_state.into_sorted()), Ok(())));
71 provider_rw.commit().unwrap();
72
73 let provider = provider_factory.provider().unwrap();
74 assert_eq!(
75 provider.tx_ref().get::<tables::HashedAccounts>(destroyed_address_hashed),
76 Ok(None)
77 );
78 assert_eq!(
79 provider
80 .tx_ref()
81 .cursor_read::<tables::HashedStorages>()
82 .unwrap()
83 .seek_by_key_subkey(destroyed_address_hashed, hashed_slot),
84 Ok(None)
85 );
86 }
87
88 #[test]
89 fn write_to_db_account_info() {
90 let factory = create_test_provider_factory();
91 let provider = factory.provider_rw().unwrap();
92
93 let address_a = Address::ZERO;
94 let address_b = Address::repeat_byte(0xff);
95
96 let account_a = RevmAccountInfo { balance: U256::from(1), nonce: 1, ..Default::default() };
97 let account_b = RevmAccountInfo { balance: U256::from(2), nonce: 2, ..Default::default() };
98 let account_b_changed =
99 RevmAccountInfo { balance: U256::from(3), nonce: 3, ..Default::default() };
100
101 let mut state = State::builder().with_bundle_update().build();
102 state.insert_not_existing(address_a);
103 state.insert_account(address_b, account_b.clone());
104
105 state.commit(HashMap::from_iter([(
107 address_a,
108 RevmAccount {
109 info: account_a.clone(),
110 status: AccountStatus::Touched | AccountStatus::Created,
111 storage: HashMap::default(),
112 transaction_id: 0,
113 },
114 )]));
115
116 state.commit(HashMap::from_iter([(
118 address_b,
119 RevmAccount {
120 info: account_b_changed.clone(),
121 status: AccountStatus::Touched,
122 storage: HashMap::default(),
123 transaction_id: 0,
124 },
125 )]));
126
127 state.merge_transitions(BundleRetention::Reverts);
128 let mut revm_bundle_state = state.take_bundle();
129
130 let reverts = revm_bundle_state.take_all_reverts().to_plain_state_reverts();
132 let plain_state = revm_bundle_state.to_plain_state(OriginalValuesKnown::Yes);
133 assert!(plain_state.storage.is_empty());
134 assert!(plain_state.contracts.is_empty());
135 provider.write_state_changes(plain_state).expect("Could not write plain state to DB");
136
137 assert_eq!(reverts.storage, [[]]);
138 provider.write_state_reverts(reverts, 1).expect("Could not write reverts to DB");
139
140 let reth_account_a = account_a.into();
141 let reth_account_b = account_b.into();
142 let reth_account_b_changed = (&account_b_changed).into();
143
144 assert_eq!(
146 provider.basic_account(&address_a).expect("Could not read account state"),
147 Some(reth_account_a),
148 "Account A state is wrong"
149 );
150 assert_eq!(
151 provider.basic_account(&address_b).expect("Could not read account state"),
152 Some(reth_account_b_changed),
153 "Account B state is wrong"
154 );
155
156 let mut changeset_cursor = provider
158 .tx_ref()
159 .cursor_dup_read::<tables::AccountChangeSets>()
160 .expect("Could not open changeset cursor");
161 assert_eq!(
162 changeset_cursor.seek_exact(1).expect("Could not read account change set"),
163 Some((1, AccountBeforeTx { address: address_a, info: None })),
164 "Account A changeset is wrong"
165 );
166 assert_eq!(
167 changeset_cursor.next_dup().expect("Changeset table is malformed"),
168 Some((1, AccountBeforeTx { address: address_b, info: Some(reth_account_b) })),
169 "Account B changeset is wrong"
170 );
171
172 let mut state = State::builder().with_bundle_update().build();
173 state.insert_account(address_b, account_b_changed.clone());
174
175 state.commit(HashMap::from_iter([(
177 address_b,
178 RevmAccount {
179 status: AccountStatus::Touched | AccountStatus::SelfDestructed,
180 info: account_b_changed,
181 storage: HashMap::default(),
182 transaction_id: 0,
183 },
184 )]));
185
186 state.merge_transitions(BundleRetention::Reverts);
187 let mut revm_bundle_state = state.take_bundle();
188
189 let reverts = revm_bundle_state.take_all_reverts().to_plain_state_reverts();
191 let plain_state = revm_bundle_state.to_plain_state(OriginalValuesKnown::Yes);
192 assert_eq!(
194 plain_state.storage,
195 [PlainStorageChangeset { address: address_b, wipe_storage: true, storage: vec![] }]
196 );
197 assert!(plain_state.contracts.is_empty());
198 provider.write_state_changes(plain_state).expect("Could not write plain state to DB");
199
200 assert_eq!(
201 reverts.storage,
202 [[PlainStorageRevert { address: address_b, wiped: true, storage_revert: vec![] }]]
203 );
204 provider.write_state_reverts(reverts, 2).expect("Could not write reverts to DB");
205
206 assert_eq!(
208 provider.basic_account(&address_b).expect("Could not read account state"),
209 None,
210 "Account B should be deleted"
211 );
212
213 assert_eq!(
215 changeset_cursor.seek_exact(2).expect("Could not read account change set"),
216 Some((2, AccountBeforeTx { address: address_b, info: Some(reth_account_b_changed) })),
217 "Account B changeset is wrong after deletion"
218 );
219 }
220
221 #[test]
222 fn write_to_db_storage() {
223 let factory = create_test_provider_factory();
224 let provider = factory.database_provider_rw().unwrap();
225
226 let address_a = Address::ZERO;
227 let address_b = Address::repeat_byte(0xff);
228
229 let account_b = RevmAccountInfo { balance: U256::from(2), nonce: 2, ..Default::default() };
230
231 let mut state = State::builder().with_bundle_update().build();
232 state.insert_not_existing(address_a);
233 state.insert_account_with_storage(
234 address_b,
235 account_b.clone(),
236 HashMap::from_iter([(U256::from(1), U256::from(1))]),
237 );
238
239 state.commit(HashMap::from_iter([
240 (
241 address_a,
242 RevmAccount {
243 status: AccountStatus::Touched | AccountStatus::Created,
244 info: RevmAccountInfo::default(),
245 storage: HashMap::from_iter([
248 (
249 U256::from(0),
250 EvmStorageSlot { present_value: U256::from(1), ..Default::default() },
251 ),
252 (
253 U256::from(1),
254 EvmStorageSlot { present_value: U256::from(2), ..Default::default() },
255 ),
256 ]),
257 transaction_id: 0,
258 },
259 ),
260 (
261 address_b,
262 RevmAccount {
263 status: AccountStatus::Touched,
264 info: account_b,
265 storage: HashMap::from_iter([(
267 U256::from(1),
268 EvmStorageSlot {
269 present_value: U256::from(2),
270 original_value: U256::from(1),
271 ..Default::default()
272 },
273 )]),
274 transaction_id: 0,
275 },
276 ),
277 ]));
278
279 state.merge_transitions(BundleRetention::Reverts);
280
281 let outcome = ExecutionOutcome::new(state.take_bundle(), Default::default(), 1, Vec::new());
282 provider
283 .write_state(&outcome, OriginalValuesKnown::Yes)
284 .expect("Could not write bundle state to DB");
285
286 let mut storage_cursor = provider
288 .tx_ref()
289 .cursor_dup_read::<tables::PlainStorageState>()
290 .expect("Could not open plain storage state cursor");
291
292 assert_eq!(
293 storage_cursor.seek_exact(address_a).unwrap(),
294 Some((address_a, StorageEntry { key: B256::ZERO, value: U256::from(1) })),
295 "Slot 0 for account A should be 1"
296 );
297 assert_eq!(
298 storage_cursor.next_dup().unwrap(),
299 Some((
300 address_a,
301 StorageEntry { key: B256::from(U256::from(1).to_be_bytes()), value: U256::from(2) }
302 )),
303 "Slot 1 for account A should be 2"
304 );
305 assert_eq!(
306 storage_cursor.next_dup().unwrap(),
307 None,
308 "Account A should only have 2 storage slots"
309 );
310
311 assert_eq!(
312 storage_cursor.seek_exact(address_b).unwrap(),
313 Some((
314 address_b,
315 StorageEntry { key: B256::from(U256::from(1).to_be_bytes()), value: U256::from(2) }
316 )),
317 "Slot 1 for account B should be 2"
318 );
319 assert_eq!(
320 storage_cursor.next_dup().unwrap(),
321 None,
322 "Account B should only have 1 storage slot"
323 );
324
325 let mut changeset_cursor = provider
327 .tx_ref()
328 .cursor_dup_read::<tables::StorageChangeSets>()
329 .expect("Could not open storage changeset cursor");
330 assert_eq!(
331 changeset_cursor.seek_exact(BlockNumberAddress((1, address_a))).unwrap(),
332 Some((
333 BlockNumberAddress((1, address_a)),
334 StorageEntry { key: B256::ZERO, value: U256::from(0) }
335 )),
336 "Slot 0 for account A should have changed from 0"
337 );
338 assert_eq!(
339 changeset_cursor.next_dup().unwrap(),
340 Some((
341 BlockNumberAddress((1, address_a)),
342 StorageEntry { key: B256::from(U256::from(1).to_be_bytes()), value: U256::from(0) }
343 )),
344 "Slot 1 for account A should have changed from 0"
345 );
346 assert_eq!(
347 changeset_cursor.next_dup().unwrap(),
348 None,
349 "Account A should only be in the changeset 2 times"
350 );
351
352 assert_eq!(
353 changeset_cursor.seek_exact(BlockNumberAddress((1, address_b))).unwrap(),
354 Some((
355 BlockNumberAddress((1, address_b)),
356 StorageEntry { key: B256::from(U256::from(1).to_be_bytes()), value: U256::from(1) }
357 )),
358 "Slot 1 for account B should have changed from 1"
359 );
360 assert_eq!(
361 changeset_cursor.next_dup().unwrap(),
362 None,
363 "Account B should only be in the changeset 1 time"
364 );
365
366 let mut state = State::builder().with_bundle_update().build();
368 state.insert_account(address_a, RevmAccountInfo::default());
369
370 state.commit(HashMap::from_iter([(
371 address_a,
372 RevmAccount {
373 status: AccountStatus::Touched | AccountStatus::SelfDestructed,
374 info: RevmAccountInfo::default(),
375 storage: HashMap::default(),
376 transaction_id: 0,
377 },
378 )]));
379
380 state.merge_transitions(BundleRetention::Reverts);
381 let outcome = ExecutionOutcome::new(state.take_bundle(), Default::default(), 2, Vec::new());
382 provider
383 .write_state(&outcome, OriginalValuesKnown::Yes)
384 .expect("Could not write bundle state to DB");
385
386 assert_eq!(
387 storage_cursor.seek_exact(address_a).unwrap(),
388 None,
389 "Account A should have no storage slots after deletion"
390 );
391
392 assert_eq!(
393 changeset_cursor.seek_exact(BlockNumberAddress((2, address_a))).unwrap(),
394 Some((
395 BlockNumberAddress((2, address_a)),
396 StorageEntry { key: B256::ZERO, value: U256::from(1) }
397 )),
398 "Slot 0 for account A should have changed from 1 on deletion"
399 );
400 assert_eq!(
401 changeset_cursor.next_dup().unwrap(),
402 Some((
403 BlockNumberAddress((2, address_a)),
404 StorageEntry { key: B256::from(U256::from(1).to_be_bytes()), value: U256::from(2) }
405 )),
406 "Slot 1 for account A should have changed from 2 on deletion"
407 );
408 assert_eq!(
409 changeset_cursor.next_dup().unwrap(),
410 None,
411 "Account A should only be in the changeset 2 times on deletion"
412 );
413 }
414
415 #[test]
416 fn write_to_db_multiple_selfdestructs() {
417 let factory = create_test_provider_factory();
418 let provider = factory.database_provider_rw().unwrap();
419
420 let address1 = Address::random();
421 let account_info = RevmAccountInfo { nonce: 1, ..Default::default() };
422
423 let mut init_state = State::builder().with_bundle_update().build();
425 init_state.insert_not_existing(address1);
426 init_state.commit(HashMap::from_iter([(
427 address1,
428 RevmAccount {
429 info: account_info.clone(),
430 status: AccountStatus::Touched | AccountStatus::Created,
431 storage: HashMap::from_iter([
434 (
435 U256::ZERO,
436 EvmStorageSlot { present_value: U256::from(1), ..Default::default() },
437 ),
438 (
439 U256::from(1),
440 EvmStorageSlot { present_value: U256::from(2), ..Default::default() },
441 ),
442 ]),
443 transaction_id: 0,
444 },
445 )]));
446 init_state.merge_transitions(BundleRetention::Reverts);
447
448 let outcome =
449 ExecutionOutcome::new(init_state.take_bundle(), Default::default(), 0, Vec::new());
450 provider
451 .write_state(&outcome, OriginalValuesKnown::Yes)
452 .expect("Could not write bundle state to DB");
453
454 let mut state = State::builder().with_bundle_update().build();
455 state.insert_account_with_storage(
456 address1,
457 account_info.clone(),
458 HashMap::from_iter([(U256::ZERO, U256::from(1)), (U256::from(1), U256::from(2))]),
459 );
460
461 state.commit(HashMap::from_iter([(
463 address1,
464 RevmAccount {
465 status: AccountStatus::Touched,
466 info: account_info.clone(),
467 storage: HashMap::from_iter([(
469 U256::ZERO,
470 EvmStorageSlot {
471 original_value: U256::from(1),
472 present_value: U256::from(2),
473 ..Default::default()
474 },
475 )]),
476 transaction_id: 0,
477 },
478 )]));
479 state.merge_transitions(BundleRetention::Reverts);
480
481 state.commit(HashMap::from_iter([(
483 address1,
484 RevmAccount {
485 status: AccountStatus::Touched | AccountStatus::SelfDestructed,
486 info: account_info.clone(),
487 storage: HashMap::default(),
488 transaction_id: 0,
489 },
490 )]));
491 state.merge_transitions(BundleRetention::Reverts);
492
493 state.commit(HashMap::from_iter([(
495 address1,
496 RevmAccount {
497 status: AccountStatus::Touched | AccountStatus::Created,
498 info: account_info.clone(),
499 storage: HashMap::default(),
500 transaction_id: 0,
501 },
502 )]));
503 state.merge_transitions(BundleRetention::Reverts);
504
505 state.commit(HashMap::from_iter([(
507 address1,
508 RevmAccount {
509 status: AccountStatus::Touched,
510 info: account_info.clone(),
511 storage: HashMap::from_iter([
515 (
516 U256::ZERO,
517 EvmStorageSlot { present_value: U256::from(2), ..Default::default() },
518 ),
519 (
520 U256::from(2),
521 EvmStorageSlot { present_value: U256::from(4), ..Default::default() },
522 ),
523 (
524 U256::from(6),
525 EvmStorageSlot { present_value: U256::from(6), ..Default::default() },
526 ),
527 ]),
528 transaction_id: 0,
529 },
530 )]));
531 state.merge_transitions(BundleRetention::Reverts);
532
533 state.commit(HashMap::from_iter([(
535 address1,
536 RevmAccount {
537 status: AccountStatus::Touched | AccountStatus::SelfDestructed,
538 info: account_info.clone(),
539 storage: HashMap::default(),
540 transaction_id: 0,
541 },
542 )]));
543 state.merge_transitions(BundleRetention::Reverts);
544
545 state.commit(HashMap::from_iter([(
547 address1,
548 RevmAccount {
549 status: AccountStatus::Touched | AccountStatus::Created,
550 info: account_info.clone(),
551 storage: HashMap::default(),
552 transaction_id: 0,
553 },
554 )]));
555 state.commit(HashMap::from_iter([(
556 address1,
557 RevmAccount {
558 status: AccountStatus::Touched,
559 info: account_info.clone(),
560 storage: HashMap::from_iter([(
562 U256::ZERO,
563 EvmStorageSlot { present_value: U256::from(2), ..Default::default() },
564 )]),
565 transaction_id: 0,
566 },
567 )]));
568 state.commit(HashMap::from_iter([(
569 address1,
570 RevmAccount {
571 status: AccountStatus::Touched | AccountStatus::SelfDestructed,
572 info: account_info.clone(),
573 storage: HashMap::default(),
574 transaction_id: 0,
575 },
576 )]));
577 state.commit(HashMap::from_iter([(
578 address1,
579 RevmAccount {
580 status: AccountStatus::Touched | AccountStatus::Created,
581 info: account_info.clone(),
582 storage: HashMap::default(),
583 transaction_id: 0,
584 },
585 )]));
586 state.merge_transitions(BundleRetention::Reverts);
587
588 state.commit(HashMap::from_iter([(
590 address1,
591 RevmAccount {
592 status: AccountStatus::Touched,
593 info: account_info,
594 storage: HashMap::from_iter([(
596 U256::ZERO,
597 EvmStorageSlot { present_value: U256::from(9), ..Default::default() },
598 )]),
599 transaction_id: 0,
600 },
601 )]));
602
603 state.merge_transitions(BundleRetention::Reverts);
604
605 let bundle = state.take_bundle();
606
607 let outcome: ExecutionOutcome =
608 ExecutionOutcome::new(bundle, Default::default(), 1, Vec::new());
609 provider
610 .write_state(&outcome, OriginalValuesKnown::Yes)
611 .expect("Could not write bundle state to DB");
612
613 let mut storage_changeset_cursor = provider
614 .tx_ref()
615 .cursor_dup_read::<tables::StorageChangeSets>()
616 .expect("Could not open plain storage state cursor");
617 let mut storage_changes = storage_changeset_cursor.walk_range(..).unwrap();
618
619 assert_eq!(
629 storage_changes.next(),
630 Some(Ok((
631 BlockNumberAddress((0, address1)),
632 StorageEntry { key: B256::with_last_byte(0), value: U256::ZERO }
633 )))
634 );
635 assert_eq!(
636 storage_changes.next(),
637 Some(Ok((
638 BlockNumberAddress((0, address1)),
639 StorageEntry { key: B256::with_last_byte(1), value: U256::ZERO }
640 )))
641 );
642
643 assert_eq!(
646 storage_changes.next(),
647 Some(Ok((
648 BlockNumberAddress((1, address1)),
649 StorageEntry { key: B256::with_last_byte(0), value: U256::from(1) }
650 )))
651 );
652
653 assert_eq!(
657 storage_changes.next(),
658 Some(Ok((
659 BlockNumberAddress((2, address1)),
660 StorageEntry { key: B256::with_last_byte(0), value: U256::from(2) }
661 )))
662 );
663 assert_eq!(
664 storage_changes.next(),
665 Some(Ok((
666 BlockNumberAddress((2, address1)),
667 StorageEntry { key: B256::with_last_byte(1), value: U256::from(2) }
668 )))
669 );
670
671 assert_eq!(
679 storage_changes.next(),
680 Some(Ok((
681 BlockNumberAddress((4, address1)),
682 StorageEntry { key: B256::with_last_byte(0), value: U256::ZERO }
683 )))
684 );
685 assert_eq!(
686 storage_changes.next(),
687 Some(Ok((
688 BlockNumberAddress((4, address1)),
689 StorageEntry { key: B256::with_last_byte(2), value: U256::ZERO }
690 )))
691 );
692 assert_eq!(
693 storage_changes.next(),
694 Some(Ok((
695 BlockNumberAddress((4, address1)),
696 StorageEntry { key: B256::with_last_byte(6), value: U256::ZERO }
697 )))
698 );
699
700 assert_eq!(
705 storage_changes.next(),
706 Some(Ok((
707 BlockNumberAddress((5, address1)),
708 StorageEntry { key: B256::with_last_byte(0), value: U256::from(2) }
709 )))
710 );
711 assert_eq!(
712 storage_changes.next(),
713 Some(Ok((
714 BlockNumberAddress((5, address1)),
715 StorageEntry { key: B256::with_last_byte(2), value: U256::from(4) }
716 )))
717 );
718 assert_eq!(
719 storage_changes.next(),
720 Some(Ok((
721 BlockNumberAddress((5, address1)),
722 StorageEntry { key: B256::with_last_byte(6), value: U256::from(6) }
723 )))
724 );
725
726 assert_eq!(
732 storage_changes.next(),
733 Some(Ok((
734 BlockNumberAddress((7, address1)),
735 StorageEntry { key: B256::with_last_byte(0), value: U256::ZERO }
736 )))
737 );
738 assert_eq!(storage_changes.next(), None);
739 }
740
741 #[test]
742 fn storage_change_after_selfdestruct_within_block() {
743 let factory = create_test_provider_factory();
744 let provider = factory.database_provider_rw().unwrap();
745
746 let address1 = Address::random();
747 let account1 = RevmAccountInfo { nonce: 1, ..Default::default() };
748
749 let mut init_state = State::builder().with_bundle_update().build();
751 init_state.insert_not_existing(address1);
752 init_state.commit(HashMap::from_iter([(
753 address1,
754 RevmAccount {
755 info: account1.clone(),
756 status: AccountStatus::Touched | AccountStatus::Created,
757 storage: HashMap::from_iter([
760 (
761 U256::ZERO,
762 EvmStorageSlot { present_value: U256::from(1), ..Default::default() },
763 ),
764 (
765 U256::from(1),
766 EvmStorageSlot { present_value: U256::from(2), ..Default::default() },
767 ),
768 ]),
769 transaction_id: 0,
770 },
771 )]));
772 init_state.merge_transitions(BundleRetention::Reverts);
773 let outcome =
774 ExecutionOutcome::new(init_state.take_bundle(), Default::default(), 0, Vec::new());
775 provider
776 .write_state(&outcome, OriginalValuesKnown::Yes)
777 .expect("Could not write bundle state to DB");
778
779 let mut state = State::builder().with_bundle_update().build();
780 state.insert_account_with_storage(
781 address1,
782 account1.clone(),
783 HashMap::from_iter([(U256::ZERO, U256::from(1)), (U256::from(1), U256::from(2))]),
784 );
785
786 state.commit(HashMap::from_iter([(
788 address1,
789 RevmAccount {
790 status: AccountStatus::Touched | AccountStatus::SelfDestructed,
791 info: account1.clone(),
792 storage: HashMap::default(),
793 transaction_id: 0,
794 },
795 )]));
796
797 state.commit(HashMap::from_iter([(
798 address1,
799 RevmAccount {
800 status: AccountStatus::Touched | AccountStatus::Created,
801 info: account1.clone(),
802 storage: HashMap::default(),
803 transaction_id: 0,
804 },
805 )]));
806
807 state.commit(HashMap::from_iter([(
808 address1,
809 RevmAccount {
810 status: AccountStatus::Touched,
811 info: account1,
812 storage: HashMap::from_iter([(
814 U256::from(1),
815 EvmStorageSlot { present_value: U256::from(5), ..Default::default() },
816 )]),
817 transaction_id: 0,
818 },
819 )]));
820
821 state.merge_transitions(BundleRetention::Reverts);
823 let outcome = ExecutionOutcome::new(state.take_bundle(), Default::default(), 1, Vec::new());
824 provider
825 .write_state(&outcome, OriginalValuesKnown::Yes)
826 .expect("Could not write bundle state to DB");
827
828 let mut storage_changeset_cursor = provider
829 .tx_ref()
830 .cursor_dup_read::<tables::StorageChangeSets>()
831 .expect("Could not open plain storage state cursor");
832 let range = BlockNumberAddress::range(1..=1);
833 let mut storage_changes = storage_changeset_cursor.walk_range(range).unwrap();
834
835 assert_eq!(
836 storage_changes.next(),
837 Some(Ok((
838 BlockNumberAddress((1, address1)),
839 StorageEntry { key: B256::with_last_byte(0), value: U256::from(1) }
840 )))
841 );
842 assert_eq!(
843 storage_changes.next(),
844 Some(Ok((
845 BlockNumberAddress((1, address1)),
846 StorageEntry { key: B256::with_last_byte(1), value: U256::from(2) }
847 )))
848 );
849 assert_eq!(storage_changes.next(), None);
850 }
851
852 #[test]
853 fn revert_to_indices() {
854 let base: ExecutionOutcome = ExecutionOutcome {
855 bundle: BundleState::default(),
856 receipts: vec![vec![Receipt::default(); 2]; 7],
857 first_block: 10,
858 requests: Vec::new(),
859 };
860
861 let mut this = base.clone();
862 assert!(this.revert_to(10));
863 assert_eq!(this.receipts.len(), 1);
864
865 let mut this = base.clone();
866 assert!(!this.revert_to(9));
867 assert_eq!(this.receipts.len(), 7);
868
869 let mut this = base.clone();
870 assert!(this.revert_to(15));
871 assert_eq!(this.receipts.len(), 6);
872
873 let mut this = base.clone();
874 assert!(this.revert_to(16));
875 assert_eq!(this.receipts.len(), 7);
876
877 let mut this = base;
878 assert!(!this.revert_to(17));
879 assert_eq!(this.receipts.len(), 7);
880 }
881
882 #[test]
883 fn bundle_state_state_root() {
884 type PreState = BTreeMap<Address, (Account, BTreeMap<B256, U256>)>;
885 let mut prestate: PreState = (0..10)
886 .map(|key| {
887 let account = Account { nonce: 1, balance: U256::from(key), bytecode_hash: None };
888 let storage =
889 (1..11).map(|key| (B256::with_last_byte(key), U256::from(key))).collect();
890 (Address::with_last_byte(key), (account, storage))
891 })
892 .collect();
893
894 let provider_factory = create_test_provider_factory();
895 let provider_rw = provider_factory.database_provider_rw().unwrap();
896
897 let tx = provider_rw.tx_ref();
899 for (address, (account, storage)) in &prestate {
900 let hashed_address = keccak256(address);
901 tx.put::<tables::HashedAccounts>(hashed_address, *account).unwrap();
902 for (slot, value) in storage {
903 tx.put::<tables::HashedStorages>(
904 hashed_address,
905 StorageEntry { key: keccak256(slot), value: *value },
906 )
907 .unwrap();
908 }
909 }
910
911 let (_, updates) = StateRoot::from_tx(tx).root_with_updates().unwrap();
912 provider_rw.write_trie_updates(&updates).unwrap();
913
914 let mut state = State::builder().with_bundle_update().build();
915
916 let assert_state_root = |state: &State<EmptyDB>, expected: &PreState, msg| {
917 assert_eq!(
918 StateRoot::overlay_root(
919 tx,
920 provider_factory.hashed_post_state(&state.bundle_state)
921 )
922 .unwrap(),
923 state_root(expected.clone().into_iter().map(|(address, (account, storage))| (
924 address,
925 (account, storage.into_iter())
926 ))),
927 "{msg}"
928 );
929 };
930
931 assert_state_root(&state, &prestate, "empty");
933
934 let address1 = Address::with_last_byte(1);
936 let account1_old = prestate.remove(&address1).unwrap();
937 state.insert_account(address1, account1_old.0.into());
938 state.commit(HashMap::from_iter([(
939 address1,
940 RevmAccount {
941 status: AccountStatus::Touched | AccountStatus::SelfDestructed,
942 info: RevmAccountInfo::default(),
943 storage: HashMap::default(),
944 transaction_id: 0,
945 },
946 )]));
947 state.merge_transitions(BundleRetention::PlainState);
948 assert_state_root(&state, &prestate, "destroyed account");
949
950 let address2 = Address::with_last_byte(2);
952 let slot2 = U256::from(2);
953 let slot2_key = B256::from(slot2);
954 let account2 = prestate.get_mut(&address2).unwrap();
955 let account2_slot2_old_value = *account2.1.get(&slot2_key).unwrap();
956 state.insert_account_with_storage(
957 address2,
958 account2.0.into(),
959 HashMap::from_iter([(slot2, account2_slot2_old_value)]),
960 );
961
962 let account2_slot2_new_value = U256::from(100);
963 account2.1.insert(slot2_key, account2_slot2_new_value);
964 state.commit(HashMap::from_iter([(
965 address2,
966 RevmAccount {
967 status: AccountStatus::Touched,
968 info: account2.0.into(),
969 storage: HashMap::from_iter([(
970 slot2,
971 EvmStorageSlot::new_changed(
972 account2_slot2_old_value,
973 account2_slot2_new_value,
974 0,
975 ),
976 )]),
977 transaction_id: 0,
978 },
979 )]));
980 state.merge_transitions(BundleRetention::PlainState);
981 assert_state_root(&state, &prestate, "changed storage");
982
983 let address3 = Address::with_last_byte(3);
985 let account3 = prestate.get_mut(&address3).unwrap();
986 state.insert_account(address3, account3.0.into());
987
988 account3.0.balance = U256::from(24);
989 state.commit(HashMap::from_iter([(
990 address3,
991 RevmAccount {
992 status: AccountStatus::Touched,
993 info: account3.0.into(),
994 storage: HashMap::default(),
995 transaction_id: 0,
996 },
997 )]));
998 state.merge_transitions(BundleRetention::PlainState);
999 assert_state_root(&state, &prestate, "changed balance");
1000
1001 let address4 = Address::with_last_byte(4);
1003 let account4 = prestate.get_mut(&address4).unwrap();
1004 state.insert_account(address4, account4.0.into());
1005
1006 account4.0.nonce = 128;
1007 state.commit(HashMap::from_iter([(
1008 address4,
1009 RevmAccount {
1010 status: AccountStatus::Touched,
1011 info: account4.0.into(),
1012 storage: HashMap::default(),
1013 transaction_id: 0,
1014 },
1015 )]));
1016 state.merge_transitions(BundleRetention::PlainState);
1017 assert_state_root(&state, &prestate, "changed nonce");
1018
1019 let account1_new =
1021 Account { nonce: 56, balance: U256::from(123), bytecode_hash: Some(B256::random()) };
1022 prestate.insert(address1, (account1_new, BTreeMap::default()));
1023 state.commit(HashMap::from_iter([(
1024 address1,
1025 RevmAccount {
1026 status: AccountStatus::Touched | AccountStatus::Created,
1027 info: account1_new.into(),
1028 storage: HashMap::default(),
1029 transaction_id: 0,
1030 },
1031 )]));
1032 state.merge_transitions(BundleRetention::PlainState);
1033 assert_state_root(&state, &prestate, "recreated");
1034
1035 let slot20 = U256::from(20);
1037 let slot20_key = B256::from(slot20);
1038 let account1_slot20_value = U256::from(12345);
1039 prestate.get_mut(&address1).unwrap().1.insert(slot20_key, account1_slot20_value);
1040 state.commit(HashMap::from_iter([(
1041 address1,
1042 RevmAccount {
1043 status: AccountStatus::Touched | AccountStatus::Created,
1044 info: account1_new.into(),
1045 storage: HashMap::from_iter([(
1046 slot20,
1047 EvmStorageSlot::new_changed(U256::ZERO, account1_slot20_value, 0),
1048 )]),
1049 transaction_id: 0,
1050 },
1051 )]));
1052 state.merge_transitions(BundleRetention::PlainState);
1053 assert_state_root(&state, &prestate, "recreated changed storage");
1054 }
1055
1056 #[test]
1057 fn prepend_state() {
1058 let address1 = Address::random();
1059 let address2 = Address::random();
1060
1061 let account1 = RevmAccountInfo { nonce: 1, ..Default::default() };
1062 let account1_changed = RevmAccountInfo { nonce: 1, ..Default::default() };
1063 let account2 = RevmAccountInfo { nonce: 1, ..Default::default() };
1064
1065 let present_state = BundleState::builder(2..=2)
1066 .state_present_account_info(address1, account1_changed.clone())
1067 .build();
1068 assert_eq!(present_state.reverts.len(), 1);
1069 let previous_state = BundleState::builder(1..=1)
1070 .state_present_account_info(address1, account1)
1071 .state_present_account_info(address2, account2.clone())
1072 .build();
1073 assert_eq!(previous_state.reverts.len(), 1);
1074
1075 let mut test: ExecutionOutcome = ExecutionOutcome {
1076 bundle: present_state,
1077 receipts: vec![vec![Receipt::default(); 2]; 1],
1078 first_block: 2,
1079 requests: Vec::new(),
1080 };
1081
1082 test.prepend_state(previous_state);
1083
1084 assert_eq!(test.receipts.len(), 1);
1085 let end_state = test.state();
1086 assert_eq!(end_state.state.len(), 2);
1087 assert_eq!(end_state.reverts.len(), 1);
1089 assert_eq!(end_state.state.get(&address1).unwrap().info, Some(account1_changed));
1091 assert_eq!(end_state.state.get(&address2).unwrap().info, Some(account2));
1093 }
1094
1095 #[test]
1096 fn hashed_state_storage_root() {
1097 let address = Address::random();
1098 let hashed_address = keccak256(address);
1099 let provider_factory = create_test_provider_factory();
1100 let provider_rw = provider_factory.provider_rw().unwrap();
1101 let tx = provider_rw.tx_ref();
1102
1103 let init_storage = HashedStorage::from_iter(
1105 false,
1106 [
1107 "50000000000000000000000000000004253371b55351a08cb3267d4d265530b6",
1108 "512428ed685fff57294d1a9cbb147b18ae5db9cf6ae4b312fa1946ba0561882e",
1109 "51e6784c736ef8548f856909870b38e49ef7a4e3e77e5e945e0d5e6fcaa3037f",
1110 ]
1111 .into_iter()
1112 .map(|str| (B256::from_str(str).unwrap(), U256::from(1))),
1113 );
1114 let mut state = HashedPostState::default();
1115 state.storages.insert(hashed_address, init_storage.clone());
1116 provider_rw.write_hashed_state(&state.clone().into_sorted()).unwrap();
1117
1118 let StorageRootProgress::Complete(storage_root, _, storage_updates) =
1120 StorageRoot::from_tx_hashed(tx, hashed_address)
1121 .with_no_threshold()
1122 .calculate(true)
1123 .unwrap()
1124 else {
1125 panic!("no threshold for root");
1126 };
1127 assert_eq!(storage_root, storage_root_prehashed(init_storage.storage));
1128 assert!(!storage_updates.is_empty());
1129 provider_rw
1130 .write_storage_trie_updates(core::iter::once((&hashed_address, &storage_updates)))
1131 .unwrap();
1132
1133 let updated_storage = HashedStorage::from_iter(
1135 true,
1136 [
1137 "00deb8486ad8edccfdedfc07109b3667b38a03a8009271aac250cce062d90917",
1138 "88d233b7380bb1bcdc866f6871c94685848f54cf0ee033b1480310b4ddb75fc9",
1139 ]
1140 .into_iter()
1141 .map(|str| (B256::from_str(str).unwrap(), U256::from(1))),
1142 );
1143 let mut state = HashedPostState::default();
1144 state.storages.insert(hashed_address, updated_storage.clone());
1145 provider_rw.write_hashed_state(&state.clone().into_sorted()).unwrap();
1146
1147 let storage_root = StorageRoot::overlay_root(tx, address, updated_storage.clone()).unwrap();
1149 assert_eq!(storage_root, storage_root_prehashed(updated_storage.storage));
1150 }
1151}