1use bytecode::{Bytecode, EOF_MAGIC_BYTES, EOF_MAGIC_HASH};
2use context_interface::journaled_state::{AccountLoad, Journal, JournalCheckpoint, TransferError};
3use database_interface::Database;
4use interpreter::{SStoreResult, SelfDestructResult, StateLoad};
5use primitives::{
6 hash_map::Entry, Address, Bytes, HashMap, HashSet, Log, B256, KECCAK_EMPTY, PRECOMPILE3, U256,
7};
8use specification::hardfork::{SpecId, SpecId::*};
9use state::{Account, EvmState, EvmStorageSlot, TransientStorage};
10
11use core::mem;
12use std::{vec, vec::Vec};
13
14use crate::JournalInit;
15
16#[derive(Debug, Clone, PartialEq, Eq)]
22#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
23pub struct JournaledState<DB> {
24 pub database: DB,
26 pub state: EvmState,
28 pub transient_storage: TransientStorage,
32 pub logs: Vec<Log>,
34 pub depth: usize,
36 pub journal: Vec<Vec<JournalEntry>>,
38 pub spec: SpecId,
48 pub warm_preloaded_addresses: HashSet<Address>,
55 pub precompiles: HashSet<Address>,
57}
58
59impl<DB: Database> Journal for JournaledState<DB> {
60 type Database = DB;
61 type FinalOutput = (EvmState, Vec<Log>);
63
64 fn new(database: DB) -> JournaledState<DB> {
65 Self::new(SpecId::LATEST, database)
66 }
67
68 fn db_ref(&self) -> &Self::Database {
69 &self.database
70 }
71
72 fn db(&mut self) -> &mut Self::Database {
73 &mut self.database
74 }
75
76 fn sload(
77 &mut self,
78 address: Address,
79 key: U256,
80 ) -> Result<StateLoad<U256>, <Self::Database as Database>::Error> {
81 self.sload(address, key)
82 }
83
84 fn sstore(
85 &mut self,
86 address: Address,
87 key: U256,
88 value: U256,
89 ) -> Result<StateLoad<SStoreResult>, <Self::Database as Database>::Error> {
90 self.sstore(address, key, value)
91 }
92
93 fn tload(&mut self, address: Address, key: U256) -> U256 {
94 self.tload(address, key)
95 }
96
97 fn tstore(&mut self, address: Address, key: U256, value: U256) {
98 self.tstore(address, key, value)
99 }
100
101 fn log(&mut self, log: Log) {
102 self.log(log)
103 }
104
105 fn selfdestruct(
106 &mut self,
107 address: Address,
108 target: Address,
109 ) -> Result<StateLoad<SelfDestructResult>, DB::Error> {
110 self.selfdestruct(address, target)
111 }
112
113 fn warm_account(&mut self, address: Address) {
114 self.warm_preloaded_addresses.insert(address);
115 }
116
117 fn warm_precompiles(&mut self, address: HashSet<Address>) {
118 self.precompiles = address;
119 self.warm_preloaded_addresses
120 .extend(self.precompiles.iter());
121 }
122
123 #[inline]
124 fn precompile_addresses(&self) -> &HashSet<Address> {
125 &self.precompiles
126 }
127
128 #[inline]
130 fn depth(&self) -> usize {
131 self.depth
132 }
133
134 fn warm_account_and_storage(
135 &mut self,
136 address: Address,
137 storage_keys: impl IntoIterator<Item = U256>,
138 ) -> Result<(), <Self::Database as Database>::Error> {
139 self.initial_account_load(address, storage_keys)?;
140 Ok(())
141 }
142
143 fn set_spec_id(&mut self, spec_id: SpecId) {
144 self.spec = spec_id;
145 }
146
147 fn code(
148 &mut self,
149 address: Address,
150 ) -> Result<StateLoad<primitives::Bytes>, <Self::Database as Database>::Error> {
151 self.code(address)
152 }
153
154 fn code_hash(
155 &mut self,
156 address: Address,
157 ) -> Result<StateLoad<B256>, <Self::Database as Database>::Error> {
158 self.code_hash(address)
159 }
160
161 fn transfer(
162 &mut self,
163 from: &Address,
164 to: &Address,
165 balance: U256,
166 ) -> Result<Option<TransferError>, DB::Error> {
167 self.transfer(from, to, balance)
168 }
169
170 fn touch_account(&mut self, address: Address) {
171 self.touch(&address);
172 }
173
174 fn inc_account_nonce(&mut self, address: Address) -> Result<Option<u64>, DB::Error> {
175 Ok(self.inc_nonce(address))
176 }
177
178 fn load_account(&mut self, address: Address) -> Result<StateLoad<&mut Account>, DB::Error> {
179 self.load_account(address)
180 }
181
182 fn load_account_code(
183 &mut self,
184 address: Address,
185 ) -> Result<StateLoad<&mut Account>, DB::Error> {
186 self.load_code(address)
187 }
188
189 fn load_account_delegated(
190 &mut self,
191 address: Address,
192 ) -> Result<StateLoad<AccountLoad>, DB::Error> {
193 self.load_account_delegated(address)
194 }
195
196 fn checkpoint(&mut self) -> JournalCheckpoint {
197 self.checkpoint()
198 }
199
200 fn checkpoint_commit(&mut self) {
201 self.checkpoint_commit()
202 }
203
204 fn checkpoint_revert(&mut self, checkpoint: JournalCheckpoint) {
205 self.checkpoint_revert(checkpoint)
206 }
207
208 fn set_code_with_hash(&mut self, address: Address, code: Bytecode, hash: B256) {
209 self.set_code_with_hash(address, code, hash);
210 }
211
212 fn clear(&mut self) {
213 self.state.clear();
215 self.transient_storage.clear();
216 self.logs.clear();
217 self.journal = vec![vec![]];
218 self.depth = 0;
219 self.warm_preloaded_addresses.clear();
220 }
221
222 fn create_account_checkpoint(
223 &mut self,
224 caller: Address,
225 address: Address,
226 balance: U256,
227 spec_id: SpecId,
228 ) -> Result<JournalCheckpoint, TransferError> {
229 self.create_account_checkpoint(caller, address, balance, spec_id)
231 }
232
233 fn finalize(&mut self) -> Self::FinalOutput {
234 let Self {
235 state,
236 transient_storage,
237 logs,
238 depth,
239 journal,
240 spec: _,
242 database: _,
243 warm_preloaded_addresses: _,
244 precompiles: _,
245 } = self;
246
247 *transient_storage = TransientStorage::default();
248 *journal = vec![vec![]];
249 *depth = 0;
250 let state = mem::take(state);
251 let logs = mem::take(logs);
252
253 (state, logs)
254 }
255}
256
257impl<DB: Database> JournaledState<DB> {
258 pub fn new(spec: SpecId, database: DB) -> JournaledState<DB> {
267 Self {
268 database,
269 state: HashMap::default(),
270 transient_storage: TransientStorage::default(),
271 logs: Vec::new(),
272 journal: vec![vec![]],
273 depth: 0,
274 spec,
275 warm_preloaded_addresses: HashSet::default(),
276 precompiles: HashSet::default(),
277 }
278 }
279
280 #[inline]
282 pub fn state(&mut self) -> &mut EvmState {
283 &mut self.state
284 }
285
286 #[inline]
288 pub fn set_spec_id(&mut self, spec: SpecId) {
289 self.spec = spec;
290 }
291
292 #[inline]
296 pub fn touch(&mut self, address: &Address) {
297 if let Some(account) = self.state.get_mut(address) {
298 Self::touch_account(self.journal.last_mut().unwrap(), address, account);
299 }
300 }
301
302 #[inline]
304 fn touch_account(journal: &mut Vec<JournalEntry>, address: &Address, account: &mut Account) {
305 if !account.is_touched() {
306 journal.push(JournalEntry::AccountTouched { address: *address });
307 account.mark_touch();
308 }
309 }
310
311 #[inline]
319 pub fn account(&self, address: Address) -> &Account {
320 self.state
321 .get(&address)
322 .expect("Account expected to be loaded") }
324
325 #[inline]
329 pub fn set_code_with_hash(&mut self, address: Address, code: Bytecode, hash: B256) {
330 let account = self.state.get_mut(&address).unwrap();
331 Self::touch_account(self.journal.last_mut().unwrap(), &address, account);
332
333 self.journal
334 .last_mut()
335 .unwrap()
336 .push(JournalEntry::CodeChange { address });
337
338 account.info.code_hash = hash;
339 account.info.code = Some(code);
340 }
341
342 #[inline]
346 pub fn set_code(&mut self, address: Address, code: Bytecode) {
347 let hash = code.hash_slow();
348 self.set_code_with_hash(address, code, hash)
349 }
350
351 #[inline]
352 pub fn inc_nonce(&mut self, address: Address) -> Option<u64> {
353 let account = self.state.get_mut(&address).unwrap();
354 if account.info.nonce == u64::MAX {
356 return None;
357 }
358 Self::touch_account(self.journal.last_mut().unwrap(), &address, account);
359 self.journal
360 .last_mut()
361 .unwrap()
362 .push(JournalEntry::NonceChange { address });
363
364 account.info.nonce += 1;
365
366 Some(account.info.nonce)
367 }
368
369 #[inline]
371 pub fn transfer(
372 &mut self,
373 from: &Address,
374 to: &Address,
375 balance: U256,
376 ) -> Result<Option<TransferError>, DB::Error> {
377 if balance.is_zero() {
378 self.load_account(*to)?;
379 let _ = self.load_account(*to)?;
380 let to_account = self.state.get_mut(to).unwrap();
381 Self::touch_account(self.journal.last_mut().unwrap(), to, to_account);
382 return Ok(None);
383 }
384 self.load_account(*from)?;
386 self.load_account(*to)?;
387
388 let from_account = &mut self.state.get_mut(from).unwrap();
390 Self::touch_account(self.journal.last_mut().unwrap(), from, from_account);
391 let from_balance = &mut from_account.info.balance;
392
393 let Some(from_balance_decr) = from_balance.checked_sub(balance) else {
394 return Ok(Some(TransferError::OutOfFunds));
395 };
396 *from_balance = from_balance_decr;
397
398 let to_account = &mut self.state.get_mut(to).unwrap();
400 Self::touch_account(self.journal.last_mut().unwrap(), to, to_account);
401 let to_balance = &mut to_account.info.balance;
402 let Some(to_balance_incr) = to_balance.checked_add(balance) else {
403 return Ok(Some(TransferError::OverflowPayment));
404 };
405 *to_balance = to_balance_incr;
406 self.journal
409 .last_mut()
410 .unwrap()
411 .push(JournalEntry::BalanceTransfer {
412 from: *from,
413 to: *to,
414 balance,
415 });
416
417 Ok(None)
418 }
419
420 #[inline]
426 pub fn code(&mut self, address: Address) -> Result<StateLoad<Bytes>, <DB as Database>::Error> {
427 let a = self.load_account_code(address)?;
428 let code = a.info.code.as_ref().unwrap();
430
431 let code = if code.is_eof() {
432 EOF_MAGIC_BYTES.clone()
433 } else {
434 code.original_bytes()
435 };
436
437 Ok(StateLoad::new(code, a.is_cold))
438 }
439
440 #[inline]
445 pub fn code_hash(
446 &mut self,
447 address: Address,
448 ) -> Result<StateLoad<B256>, <DB as Database>::Error> {
449 let acc = self.load_account_code(address)?;
450 if acc.is_empty() {
451 return Ok(StateLoad::new(B256::ZERO, acc.is_cold));
452 }
453 let code = acc.info.code.as_ref().unwrap();
455
456 let hash = if code.is_eof() {
457 EOF_MAGIC_HASH
458 } else {
459 acc.info.code_hash
460 };
461
462 Ok(StateLoad::new(hash, acc.is_cold))
463 }
464
465 #[inline]
481 pub fn create_account_checkpoint(
482 &mut self,
483 caller: Address,
484 target_address: Address,
485 balance: U256,
486 spec_id: SpecId,
487 ) -> Result<JournalCheckpoint, TransferError> {
488 let checkpoint = self.checkpoint();
490
491 let caller_acc = self.state.get_mut(&caller).unwrap();
493 if caller_acc.info.balance < balance {
495 self.checkpoint_revert(checkpoint);
496 return Err(TransferError::OutOfFunds);
497 }
498
499 let target_acc = self.state.get_mut(&target_address).unwrap();
501 let last_journal = self.journal.last_mut().unwrap();
502
503 if target_acc.info.code_hash != KECCAK_EMPTY || target_acc.info.nonce != 0 {
508 self.checkpoint_revert(checkpoint);
509 return Err(TransferError::CreateCollision);
510 }
511
512 target_acc.mark_created();
514
515 last_journal.push(JournalEntry::AccountCreated {
517 address: target_address,
518 });
519 target_acc.info.code = None;
520 if spec_id.is_enabled_in(SPURIOUS_DRAGON) {
522 target_acc.info.nonce = 1;
524 }
525
526 Self::touch_account(last_journal, &target_address, target_acc);
529
530 let Some(new_balance) = target_acc.info.balance.checked_add(balance) else {
532 self.checkpoint_revert(checkpoint);
533 return Err(TransferError::OverflowPayment);
534 };
535 target_acc.info.balance = new_balance;
536
537 self.state.get_mut(&caller).unwrap().info.balance -= balance;
539
540 last_journal.push(JournalEntry::BalanceTransfer {
542 from: caller,
543 to: target_address,
544 balance,
545 });
546
547 Ok(checkpoint)
548 }
549
550 #[inline]
552 fn journal_revert(
553 state: &mut EvmState,
554 transient_storage: &mut TransientStorage,
555 journal_entries: Vec<JournalEntry>,
556 is_spurious_dragon_enabled: bool,
557 ) {
558 for entry in journal_entries.into_iter().rev() {
559 match entry {
560 JournalEntry::AccountWarmed { address } => {
561 state.get_mut(&address).unwrap().mark_cold();
562 }
563 JournalEntry::AccountTouched { address } => {
564 if is_spurious_dragon_enabled && address == PRECOMPILE3 {
565 continue;
566 }
567 state.get_mut(&address).unwrap().unmark_touch();
569 }
570 JournalEntry::AccountDestroyed {
571 address,
572 target,
573 was_destroyed,
574 had_balance,
575 } => {
576 let account = state.get_mut(&address).unwrap();
577 if was_destroyed {
580 account.mark_selfdestruct();
582 } else {
583 account.unmark_selfdestruct();
585 }
586 account.info.balance += had_balance;
587
588 if address != target {
589 let target = state.get_mut(&target).unwrap();
590 target.info.balance -= had_balance;
591 }
592 }
593 JournalEntry::BalanceTransfer { from, to, balance } => {
594 let from = state.get_mut(&from).unwrap();
596 from.info.balance += balance;
597 let to = state.get_mut(&to).unwrap();
598 to.info.balance -= balance;
599 }
600 JournalEntry::NonceChange { address } => {
601 state.get_mut(&address).unwrap().info.nonce -= 1;
602 }
603 JournalEntry::AccountCreated { address } => {
604 let account = &mut state.get_mut(&address).unwrap();
605 account.unmark_created();
606 account
607 .storage
608 .values_mut()
609 .for_each(|slot| slot.mark_cold());
610 account.info.nonce = 0;
611 }
612 JournalEntry::StorageWarmed { address, key } => {
613 state
614 .get_mut(&address)
615 .unwrap()
616 .storage
617 .get_mut(&key)
618 .unwrap()
619 .mark_cold();
620 }
621 JournalEntry::StorageChanged {
622 address,
623 key,
624 had_value,
625 } => {
626 state
627 .get_mut(&address)
628 .unwrap()
629 .storage
630 .get_mut(&key)
631 .unwrap()
632 .present_value = had_value;
633 }
634 JournalEntry::TransientStorageChange {
635 address,
636 key,
637 had_value,
638 } => {
639 let tkey = (address, key);
640 if had_value.is_zero() {
641 transient_storage.remove(&tkey);
643 } else {
644 transient_storage.insert(tkey, had_value);
646 }
647 }
648 JournalEntry::CodeChange { address } => {
649 let acc = state.get_mut(&address).unwrap();
650 acc.info.code_hash = KECCAK_EMPTY;
651 acc.info.code = None;
652 }
653 }
654 }
655 }
656
657 #[inline]
659 pub fn checkpoint(&mut self) -> JournalCheckpoint {
660 let checkpoint = JournalCheckpoint {
661 log_i: self.logs.len(),
662 journal_i: self.journal.len(),
663 };
664 self.depth += 1;
665 self.journal.push(Default::default());
666 checkpoint
667 }
668
669 #[inline]
671 pub fn checkpoint_commit(&mut self) {
672 self.depth -= 1;
673 }
674
675 #[inline]
677 pub fn checkpoint_revert(&mut self, checkpoint: JournalCheckpoint) {
678 let is_spurious_dragon_enabled = self.spec.is_enabled_in(SPURIOUS_DRAGON);
679 let state = &mut self.state;
680 let transient_storage = &mut self.transient_storage;
681 self.depth -= 1;
682 let leng = self.journal.len();
684 self.journal
685 .iter_mut()
686 .rev()
687 .take(leng - checkpoint.journal_i)
688 .for_each(|cs| {
689 Self::journal_revert(
690 state,
691 transient_storage,
692 mem::take(cs),
693 is_spurious_dragon_enabled,
694 )
695 });
696
697 self.logs.truncate(checkpoint.log_i);
698 self.journal.truncate(checkpoint.journal_i);
699 }
700
701 #[inline]
713 pub fn selfdestruct(
714 &mut self,
715 address: Address,
716 target: Address,
717 ) -> Result<StateLoad<SelfDestructResult>, DB::Error> {
718 let spec = self.spec;
719 let account_load = self.load_account(target)?;
720 let is_cold = account_load.is_cold;
721 let is_empty = account_load.state_clear_aware_is_empty(spec);
722
723 if address != target {
724 let acc_balance = self.state.get_mut(&address).unwrap().info.balance;
727
728 let target_account = self.state.get_mut(&target).unwrap();
729 Self::touch_account(self.journal.last_mut().unwrap(), &target, target_account);
730 target_account.info.balance += acc_balance;
731 }
732
733 let acc = self.state.get_mut(&address).unwrap();
734 let balance = acc.info.balance;
735 let previously_destroyed = acc.is_selfdestructed();
736 let is_cancun_enabled = self.spec.is_enabled_in(CANCUN);
737
738 let journal_entry = if acc.is_created() || !is_cancun_enabled {
740 acc.mark_selfdestruct();
741 acc.info.balance = U256::ZERO;
742 Some(JournalEntry::AccountDestroyed {
743 address,
744 target,
745 was_destroyed: previously_destroyed,
746 had_balance: balance,
747 })
748 } else if address != target {
749 acc.info.balance = U256::ZERO;
750 Some(JournalEntry::BalanceTransfer {
751 from: address,
752 to: target,
753 balance,
754 })
755 } else {
756 None
761 };
762
763 if let Some(entry) = journal_entry {
764 self.journal.last_mut().unwrap().push(entry);
765 };
766
767 Ok(StateLoad {
768 data: SelfDestructResult {
769 had_value: !balance.is_zero(),
770 target_exists: !is_empty,
771 previously_destroyed,
772 },
773 is_cold,
774 })
775 }
776
777 #[inline]
779 pub fn initial_account_load(
780 &mut self,
781 address: Address,
782 storage_keys: impl IntoIterator<Item = U256>,
783 ) -> Result<&mut Account, DB::Error> {
784 let account = match self.state.entry(address) {
786 Entry::Occupied(entry) => entry.into_mut(),
787 Entry::Vacant(vac) => vac.insert(
788 self.database
789 .basic(address)?
790 .map(|i| i.into())
791 .unwrap_or(Account::new_not_existing()),
792 ),
793 };
794 for storage_key in storage_keys.into_iter() {
796 if let Entry::Vacant(entry) = account.storage.entry(storage_key) {
797 let storage = self.database.storage(address, storage_key)?;
798 entry.insert(EvmStorageSlot::new(storage));
799 }
800 }
801 Ok(account)
802 }
803
804 #[inline]
806 pub fn load_account(&mut self, address: Address) -> Result<StateLoad<&mut Account>, DB::Error> {
807 self.load_account_optional(address, false)
808 }
809
810 #[inline]
811 pub fn load_account_delegated(
812 &mut self,
813 address: Address,
814 ) -> Result<StateLoad<AccountLoad>, DB::Error> {
815 let spec = self.spec;
816 let account = self.load_code(address)?;
817 let is_empty = account.state_clear_aware_is_empty(spec);
818
819 let mut account_load = StateLoad::new(
820 AccountLoad {
821 is_delegate_account_cold: None,
822 is_empty,
823 },
824 account.is_cold,
825 );
826
827 if let Some(Bytecode::Eip7702(code)) = &account.info.code {
829 let address = code.address();
830 let delegate_account = self.load_account(address)?;
831 account_load.data.is_delegate_account_cold = Some(delegate_account.is_cold);
832 }
833
834 Ok(account_load)
835 }
836
837 pub fn load_code(&mut self, address: Address) -> Result<StateLoad<&mut Account>, DB::Error> {
838 self.load_account_optional(address, true)
839 }
840
841 #[inline]
843 pub fn load_account_optional(
844 &mut self,
845 address: Address,
846 load_code: bool,
847 ) -> Result<StateLoad<&mut Account>, DB::Error> {
848 let load = match self.state.entry(address) {
849 Entry::Occupied(entry) => {
850 let account = entry.into_mut();
851 let is_cold = account.mark_warm();
852 StateLoad {
853 data: account,
854 is_cold,
855 }
856 }
857 Entry::Vacant(vac) => {
858 let account = if let Some(account) = self.database.basic(address)? {
859 account.into()
860 } else {
861 Account::new_not_existing()
862 };
863
864 let is_cold = !self.warm_preloaded_addresses.contains(&address);
866
867 StateLoad {
868 data: vac.insert(account),
869 is_cold,
870 }
871 }
872 };
873 if load.is_cold {
875 self.journal
876 .last_mut()
877 .unwrap()
878 .push(JournalEntry::AccountWarmed { address });
879 }
880 if load_code {
881 let info = &mut load.data.info;
882 if info.code.is_none() {
883 if info.code_hash == KECCAK_EMPTY {
884 let empty = Bytecode::default();
885 info.code = Some(empty);
886 } else {
887 let code = self.database.code_by_hash(info.code_hash)?;
888 info.code = Some(code);
889 }
890 }
891 }
892
893 Ok(load)
894 }
895
896 #[inline]
902 pub fn sload(&mut self, address: Address, key: U256) -> Result<StateLoad<U256>, DB::Error> {
903 let account = self.state.get_mut(&address).unwrap();
905 let is_newly_created = account.is_created();
907 let (value, is_cold) = match account.storage.entry(key) {
908 Entry::Occupied(occ) => {
909 let slot = occ.into_mut();
910 let is_cold = slot.mark_warm();
911 (slot.present_value, is_cold)
912 }
913 Entry::Vacant(vac) => {
914 let value = if is_newly_created {
916 U256::ZERO
917 } else {
918 self.database.storage(address, key)?
919 };
920
921 vac.insert(EvmStorageSlot::new(value));
922
923 (value, true)
924 }
925 };
926
927 if is_cold {
928 self.journal
930 .last_mut()
931 .unwrap()
932 .push(JournalEntry::StorageWarmed { address, key });
933 }
934
935 Ok(StateLoad::new(value, is_cold))
936 }
937
938 #[inline]
944 pub fn sstore(
945 &mut self,
946 address: Address,
947 key: U256,
948 new: U256,
949 ) -> Result<StateLoad<SStoreResult>, DB::Error> {
950 let present = self.sload(address, key)?;
952 let acc = self.state.get_mut(&address).unwrap();
953
954 let slot = acc.storage.get_mut(&key).unwrap();
956
957 if present.data == new {
959 return Ok(StateLoad::new(
960 SStoreResult {
961 original_value: slot.original_value(),
962 present_value: present.data,
963 new_value: new,
964 },
965 present.is_cold,
966 ));
967 }
968
969 self.journal
970 .last_mut()
971 .unwrap()
972 .push(JournalEntry::StorageChanged {
973 address,
974 key,
975 had_value: present.data,
976 });
977 slot.present_value = new;
979 Ok(StateLoad::new(
980 SStoreResult {
981 original_value: slot.original_value(),
982 present_value: present.data,
983 new_value: new,
984 },
985 present.is_cold,
986 ))
987 }
988
989 #[inline]
993 pub fn tload(&mut self, address: Address, key: U256) -> U256 {
994 self.transient_storage
995 .get(&(address, key))
996 .copied()
997 .unwrap_or_default()
998 }
999
1000 #[inline]
1007 pub fn tstore(&mut self, address: Address, key: U256, new: U256) {
1008 let had_value = if new.is_zero() {
1009 self.transient_storage.remove(&(address, key))
1013 } else {
1014 let previous_value = self
1016 .transient_storage
1017 .insert((address, key), new)
1018 .unwrap_or_default();
1019
1020 if previous_value != new {
1022 Some(previous_value)
1024 } else {
1025 None
1026 }
1027 };
1028
1029 if let Some(had_value) = had_value {
1030 self.journal
1032 .last_mut()
1033 .unwrap()
1034 .push(JournalEntry::TransientStorageChange {
1035 address,
1036 key,
1037 had_value,
1038 });
1039 }
1040 }
1041
1042 #[inline]
1044 pub fn log(&mut self, log: Log) {
1045 self.logs.push(log);
1046 }
1047}
1048
1049#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1051#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1052pub enum JournalEntry {
1053 AccountWarmed { address: Address },
1057 AccountDestroyed {
1061 address: Address,
1062 target: Address,
1063 was_destroyed: bool, had_balance: U256,
1065 },
1066 AccountTouched { address: Address },
1071 BalanceTransfer {
1075 from: Address,
1076 to: Address,
1077 balance: U256,
1078 },
1079 NonceChange {
1083 address: Address, },
1085 AccountCreated { address: Address },
1089 StorageChanged {
1093 address: Address,
1094 key: U256,
1095 had_value: U256,
1096 },
1097 StorageWarmed { address: Address, key: U256 },
1101 TransientStorageChange {
1105 address: Address,
1106 key: U256,
1107 had_value: U256,
1108 },
1109 CodeChange { address: Address },
1113}
1114
1115impl<DB> JournaledState<DB> {
1116 pub fn from_init(init: &JournalInit, database: DB) -> Self {
1118 Self {
1119 database,
1120 state: init.state.clone(),
1121 transient_storage: init.transient_storage.clone(),
1122 logs: init.logs.clone(),
1123 depth: init.depth,
1124 journal: init.journal.clone(),
1125 spec: init.spec,
1126 warm_preloaded_addresses: init.warm_preloaded_addresses.clone(),
1127 precompiles: init.precompiles.clone(),
1128 }
1129 }
1130}