reth_provider/writer/
mod.rs

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        // 0x00.. is created
106        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        // 0xff.. is changed (balance + 1, nonce + 1)
117        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        // Write plain state and reverts separately.
131        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        // Check plain state
145        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        // Check change set
157        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        // 0xff.. is destroyed
176        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        // Write plain state and reverts separately.
190        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        // Account B selfdestructed so flag for it should be present.
193        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        // Check new plain state for account B
207        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        // Check change set
214        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                    // 0x00 => 0 => 1
246                    // 0x01 => 0 => 2
247                    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                    // 0x01 => 1 => 2
266                    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        // Check plain storage state
287        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        // Check change set
326        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        // Delete account A
367        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        // Block #0: initial state.
424        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                // 0x00 => 0 => 1
432                // 0x01 => 0 => 2
433                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        // Block #1: change storage.
462        state.commit(HashMap::from_iter([(
463            address1,
464            RevmAccount {
465                status: AccountStatus::Touched,
466                info: account_info.clone(),
467                // 0x00 => 1 => 2
468                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        // Block #2: destroy account.
482        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        // Block #3: re-create account and change storage.
494        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        // Block #4: change storage.
506        state.commit(HashMap::from_iter([(
507            address1,
508            RevmAccount {
509                status: AccountStatus::Touched,
510                info: account_info.clone(),
511                // 0x00 => 0 => 2
512                // 0x02 => 0 => 4
513                // 0x06 => 0 => 6
514                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        // Block #5: Destroy account again.
534        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        // Block #6: Create, change, destroy and re-create in the same block.
546        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                // 0x00 => 0 => 2
561                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        // Block #7: Change storage.
589        state.commit(HashMap::from_iter([(
590            address1,
591            RevmAccount {
592                status: AccountStatus::Touched,
593                info: account_info,
594                // 0x00 => 0 => 9
595                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        // Iterate through all storage changes
620
621        // Block <number>
622        // <slot>: <expected value before>
623        // ...
624
625        // Block #0
626        // 0x00: 0
627        // 0x01: 0
628        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        // Block #1
644        // 0x00: 1
645        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        // Block #2 (destroyed)
654        // 0x00: 2
655        // 0x01: 2
656        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        // Block #3
672        // no storage changes
673
674        // Block #4
675        // 0x00: 0
676        // 0x02: 0
677        // 0x06: 0
678        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        // Block #5 (destroyed)
701        // 0x00: 2
702        // 0x02: 4
703        // 0x06: 6
704        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        // Block #6
727        // no storage changes (only inter block changes)
728
729        // Block #7
730        // 0x00: 0
731        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        // Block #0: initial state.
750        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                // 0x00 => 0 => 1
758                // 0x01 => 0 => 2
759                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        // Block #1: Destroy, re-create, change storage.
787        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                // 0x01 => 0 => 5
813                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        // Commit block #1 changes to the database.
822        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        // insert initial state to the database
898        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        // database only state root is correct
932        assert_state_root(&state, &prestate, "empty");
933
934        // destroy account 1
935        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        // change slot 2 in account 2
951        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        // change balance of account 3
984        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        // change nonce of account 4
1002        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        // recreate account 1
1020        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        // update storage for account 1
1036        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        // reverts num should stay the same.
1088        assert_eq!(end_state.reverts.len(), 1);
1089        // account1 is not overwritten.
1090        assert_eq!(end_state.state.get(&address1).unwrap().info, Some(account1_changed));
1091        // account2 got inserted
1092        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        // insert initial account storage
1104        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        // calculate database storage root and write intermediate storage nodes.
1119        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        // destroy the storage and re-create with new slots
1134        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        // re-calculate database storage root
1148        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}