1use crate::{
2 db::HistoryRead,
3 model::{HotKvError, HotKvRead, HotKvWrite},
4 tables::{self, Bytecodes, DualKey, PlainAccountState, SingleKey, Table},
5};
6use alloy::primitives::{Address, B256, KECCAK256_EMPTY};
7use core::fmt;
8use signet_storage_types::Account;
9use std::borrow::Cow;
10use trevm::revm::{
11 database::{DBErrorMarker, Database, DatabaseRef, TryDatabaseCommit},
12 primitives::{HashMap, StorageKey, StorageValue},
13 state::{self, AccountInfo, Bytecode as RevmBytecode},
14};
15
16impl DBErrorMarker for HotKvError {}
18
19pub struct RevmRead<T: HotKvRead> {
25 reader: T,
26 height: Option<u64>,
27}
28
29impl<T: HotKvRead> RevmRead<T> {
30 pub const fn new(reader: T) -> Self {
32 Self { reader, height: None }
33 }
34
35 pub const fn at_height(reader: T, height: u64) -> Self {
47 Self { reader, height: Some(height) }
48 }
49}
50
51impl<T: HotKvRead> fmt::Debug for RevmRead<T> {
52 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53 f.debug_struct("RevmRead").finish()
54 }
55}
56
57impl<U: HotKvRead> HotKvRead for RevmRead<U> {
59 type Error = U::Error;
60
61 type Traverse<'a>
62 = U::Traverse<'a>
63 where
64 U: 'a;
65
66 fn raw_traverse<'a>(&'a self, table: &'static str) -> Result<Self::Traverse<'a>, Self::Error> {
67 self.reader.raw_traverse(table)
68 }
69
70 fn raw_get<'a>(
71 &'a self,
72 table: &'static str,
73 key: &[u8],
74 ) -> Result<Option<std::borrow::Cow<'a, [u8]>>, Self::Error> {
75 self.reader.raw_get(table, key)
76 }
77
78 fn raw_get_dual<'a>(
79 &'a self,
80 table: &'static str,
81 key1: &[u8],
82 key2: &[u8],
83 ) -> Result<Option<Cow<'a, [u8]>>, Self::Error> {
84 self.reader.raw_get_dual(table, key1, key2)
85 }
86
87 fn get<T: SingleKey>(&self, key: &T::Key) -> Result<Option<T::Value>, Self::Error> {
88 self.reader.get::<T>(key)
89 }
90
91 fn get_dual<T: DualKey>(
92 &self,
93 key1: &T::Key,
94 key2: &T::Key2,
95 ) -> Result<Option<T::Value>, Self::Error> {
96 self.reader.get_dual::<T>(key1, key2)
97 }
98}
99
100pub struct RevmWrite<U: HotKvWrite> {
105 writer: U,
106}
107
108impl<U: HotKvWrite> RevmWrite<U> {
109 pub const fn new(writer: U) -> Self {
111 Self { writer }
112 }
113
114 pub fn persist(self) -> Result<(), U::Error> {
116 self.writer.raw_commit()
117 }
118}
119
120impl<U: HotKvWrite> fmt::Debug for RevmWrite<U> {
121 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
122 f.debug_struct("RevmWrite").finish()
123 }
124}
125
126impl<U: HotKvWrite> HotKvRead for RevmWrite<U> {
128 type Error = U::Error;
129
130 type Traverse<'a>
131 = U::Traverse<'a>
132 where
133 U: 'a;
134
135 fn raw_traverse<'a>(&'a self, table: &'static str) -> Result<Self::Traverse<'a>, Self::Error> {
136 self.writer.raw_traverse(table)
137 }
138
139 fn raw_get<'a>(
140 &'a self,
141 table: &'static str,
142 key: &[u8],
143 ) -> Result<Option<std::borrow::Cow<'a, [u8]>>, Self::Error> {
144 self.writer.raw_get(table, key)
145 }
146
147 fn raw_get_dual<'a>(
148 &'a self,
149 table: &'static str,
150 key1: &[u8],
151 key2: &[u8],
152 ) -> Result<Option<Cow<'a, [u8]>>, Self::Error> {
153 self.writer.raw_get_dual(table, key1, key2)
154 }
155
156 fn get<T: SingleKey>(&self, key: &T::Key) -> Result<Option<T::Value>, Self::Error> {
157 self.writer.get::<T>(key)
158 }
159
160 fn get_dual<T: DualKey>(
161 &self,
162 key1: &T::Key,
163 key2: &T::Key2,
164 ) -> Result<Option<T::Value>, Self::Error> {
165 self.writer.get_dual::<T>(key1, key2)
166 }
167}
168
169impl<U: HotKvWrite> HotKvWrite for RevmWrite<U> {
170 type TraverseMut<'a>
171 = U::TraverseMut<'a>
172 where
173 U: 'a;
174
175 fn raw_traverse_mut<'a>(
176 &'a self,
177 table: &'static str,
178 ) -> Result<Self::TraverseMut<'a>, Self::Error> {
179 self.writer.raw_traverse_mut(table)
180 }
181
182 fn queue_raw_put(
183 &self,
184 table: &'static str,
185 key: &[u8],
186 value: &[u8],
187 ) -> Result<(), Self::Error> {
188 self.writer.queue_raw_put(table, key, value)
189 }
190
191 fn queue_raw_put_dual(
192 &self,
193 table: &'static str,
194 key1: &[u8],
195 key2: &[u8],
196 value: &[u8],
197 ) -> Result<(), Self::Error> {
198 self.writer.queue_raw_put_dual(table, key1, key2, value)
199 }
200
201 fn queue_raw_delete(&self, table: &'static str, key: &[u8]) -> Result<(), Self::Error> {
202 self.writer.queue_raw_delete(table, key)
203 }
204
205 fn queue_raw_delete_dual(
206 &self,
207 table: &'static str,
208 key1: &[u8],
209 key2: &[u8],
210 ) -> Result<(), Self::Error> {
211 self.writer.queue_raw_delete_dual(table, key1, key2)
212 }
213
214 fn queue_raw_clear(&self, table: &'static str) -> Result<(), Self::Error> {
215 self.writer.queue_raw_clear(table)
216 }
217
218 fn queue_raw_create(
219 &self,
220 table: &'static str,
221 dual_key: Option<usize>,
222 dual_fixed: Option<usize>,
223 ) -> Result<(), Self::Error> {
224 self.writer.queue_raw_create(table, dual_key, dual_fixed)
225 }
226
227 fn raw_commit(self) -> Result<(), Self::Error> {
228 self.writer.raw_commit()
229 }
230
231 fn queue_put<T: SingleKey>(&self, key: &T::Key, value: &T::Value) -> Result<(), Self::Error> {
232 self.writer.queue_put::<T>(key, value)
233 }
234
235 fn queue_put_dual<T: DualKey>(
236 &self,
237 key1: &T::Key,
238 key2: &T::Key2,
239 value: &T::Value,
240 ) -> Result<(), Self::Error> {
241 self.writer.queue_put_dual::<T>(key1, key2, value)
242 }
243
244 fn queue_delete<T: SingleKey>(&self, key: &T::Key) -> Result<(), Self::Error> {
245 self.writer.queue_delete::<T>(key)
246 }
247
248 fn queue_create<T>(&self) -> Result<(), Self::Error>
249 where
250 T: Table,
251 {
252 self.writer.queue_create::<T>()
253 }
254
255 fn queue_clear<T>(&self) -> Result<(), Self::Error>
256 where
257 T: Table,
258 {
259 self.writer.queue_clear::<T>()
260 }
261}
262
263impl<T: HotKvRead> DatabaseRef for RevmRead<T>
265where
266 T::Error: DBErrorMarker,
267{
268 type Error = T::Error;
269
270 fn basic_ref(&self, address: Address) -> Result<Option<AccountInfo>, Self::Error> {
271 let Some(account) = self.reader.get_account_at_height(&address, self.height)? else {
272 return Ok(None);
273 };
274
275 let code_hash = account.bytecode_hash.unwrap_or(KECCAK256_EMPTY);
276 let code = if code_hash != KECCAK256_EMPTY {
278 self.reader.get::<Bytecodes>(&code_hash)?
279 } else {
280 None
281 };
282
283 Ok(Some(AccountInfo {
284 balance: account.balance,
285 nonce: account.nonce,
286 code_hash,
287 code,
288 account_id: None,
289 }))
290 }
291
292 fn code_by_hash_ref(&self, code_hash: B256) -> Result<RevmBytecode, Self::Error> {
293 Ok(self.reader.get::<Bytecodes>(&code_hash)?.unwrap_or_default())
294 }
295
296 fn storage_ref(
297 &self,
298 address: Address,
299 index: StorageKey,
300 ) -> Result<StorageValue, Self::Error> {
301 Ok(self.reader.get_storage_at_height(&address, &index, self.height)?.unwrap_or_default())
302 }
303
304 fn block_hash_ref(&self, number: u64) -> Result<B256, Self::Error> {
305 Ok(self.reader.get::<tables::Headers>(&number)?.map_or(B256::ZERO, |h| h.hash()))
306 }
307}
308
309impl<T: HotKvRead> Database for RevmRead<T>
311where
312 T::Error: DBErrorMarker,
313{
314 type Error = T::Error;
315
316 fn basic(&mut self, address: Address) -> Result<Option<AccountInfo>, Self::Error> {
317 self.basic_ref(address)
318 }
319
320 fn code_by_hash(&mut self, code_hash: B256) -> Result<RevmBytecode, Self::Error> {
321 self.code_by_hash_ref(code_hash)
322 }
323
324 fn storage(
325 &mut self,
326 address: Address,
327 index: StorageKey,
328 ) -> Result<StorageValue, Self::Error> {
329 self.storage_ref(address, index)
330 }
331
332 fn block_hash(&mut self, number: u64) -> Result<B256, Self::Error> {
333 self.block_hash_ref(number)
334 }
335}
336
337impl<T: HotKvWrite> DatabaseRef for RevmWrite<T>
339where
340 T::Error: DBErrorMarker,
341{
342 type Error = T::Error;
343
344 fn basic_ref(&self, address: Address) -> Result<Option<AccountInfo>, Self::Error> {
345 let account_opt = self.writer.get::<PlainAccountState>(&address)?;
346
347 let Some(account) = account_opt else {
348 return Ok(None);
349 };
350
351 let code_hash = account.bytecode_hash.unwrap_or(KECCAK256_EMPTY);
352 let code = if code_hash != KECCAK256_EMPTY {
353 self.writer.get::<Bytecodes>(&code_hash)?
354 } else {
355 None
356 };
357
358 Ok(Some(AccountInfo {
359 balance: account.balance,
360 nonce: account.nonce,
361 code_hash,
362 code,
363 account_id: None,
364 }))
365 }
366
367 fn code_by_hash_ref(&self, code_hash: B256) -> Result<RevmBytecode, Self::Error> {
368 Ok(self.writer.get::<Bytecodes>(&code_hash)?.unwrap_or_default())
369 }
370
371 fn storage_ref(
372 &self,
373 address: Address,
374 index: StorageKey,
375 ) -> Result<StorageValue, Self::Error> {
376 Ok(self.writer.get_dual::<tables::PlainStorageState>(&address, &index)?.unwrap_or_default())
377 }
378
379 fn block_hash_ref(&self, number: u64) -> Result<B256, Self::Error> {
380 Ok(self.writer.get::<tables::Headers>(&number)?.map_or(B256::ZERO, |h| h.hash()))
381 }
382}
383
384impl<T: HotKvWrite> Database for RevmWrite<T>
386where
387 T::Error: DBErrorMarker,
388{
389 type Error = T::Error;
390
391 fn basic(&mut self, address: Address) -> Result<Option<AccountInfo>, Self::Error> {
392 self.basic_ref(address)
393 }
394
395 fn code_by_hash(&mut self, code_hash: B256) -> Result<RevmBytecode, Self::Error> {
396 self.code_by_hash_ref(code_hash)
397 }
398
399 fn storage(
400 &mut self,
401 address: Address,
402 index: StorageKey,
403 ) -> Result<StorageValue, Self::Error> {
404 self.storage_ref(address, index)
405 }
406
407 fn block_hash(&mut self, number: u64) -> Result<B256, Self::Error> {
408 self.block_hash_ref(number)
409 }
410}
411
412impl<T: HotKvWrite> TryDatabaseCommit for RevmWrite<T>
414where
415 T::Error: DBErrorMarker,
416{
417 type Error = T::Error;
418
419 fn try_commit(&mut self, changes: HashMap<Address, state::Account>) -> Result<(), Self::Error> {
420 for (address, account) in changes {
421 let account_data = Account {
423 nonce: account.info.nonce,
424 balance: account.info.balance,
425 bytecode_hash: (account.info.code_hash != KECCAK256_EMPTY)
426 .then_some(account.info.code_hash),
427 };
428 self.writer.queue_put::<PlainAccountState>(&address, &account_data)?;
429
430 for (key, value) in account.storage {
432 self.writer.queue_put_dual::<tables::PlainStorageState>(
433 &address,
434 &key,
435 &value.present_value(),
436 )?;
437 }
438 }
439
440 Ok(())
441 }
442}
443
444#[cfg(test)]
445mod tests {
446 use super::*;
447 use crate::{
448 db::{HistoryRead, UnsafeDbWrite, UnsafeHistoryWrite},
449 mem::MemKv,
450 model::{HotKv, HotKvRead, HotKvWrite},
451 tables::{Bytecodes, PlainAccountState},
452 };
453 use alloy::{
454 consensus::{Header, Sealable},
455 primitives::{Address, B256, U256},
456 };
457 use signet_storage_types::{Account, BlockNumberList};
458 use trevm::revm::{
459 database::{Database, DatabaseRef, TryDatabaseCommit},
460 primitives::{HashMap, StorageKey, StorageValue},
461 state::{Account as RevmAccount, AccountInfo, Bytecode},
462 };
463
464 fn create_test_account() -> (Address, Account) {
466 let address = Address::from_slice(&[0x1; 20]);
467 let account = Account {
468 nonce: 42,
469 balance: U256::from(1000u64),
470 bytecode_hash: Some(B256::from_slice(&[0x2; 32])),
471 };
472 (address, account)
473 }
474
475 fn create_test_bytecode() -> (B256, Bytecode) {
477 let hash = B256::from_slice(&[0x2; 32]);
478 let bytecode = RevmBytecode::new_raw(vec![0x60, 0x80, 0x60, 0x40].into());
479 (hash, bytecode)
480 }
481
482 #[test]
483 fn test_database_ref_traits() -> Result<(), Box<dyn std::error::Error>> {
484 let mem_kv = MemKv::default();
485
486 let (address, account) = create_test_account();
487 let (hash, bytecode) = create_test_bytecode();
488
489 {
490 let writer = mem_kv.revm_writer()?;
492 writer.queue_put::<PlainAccountState>(&address, &account)?;
493 writer.queue_put::<Bytecodes>(&hash, &bytecode)?;
494 writer.persist()?;
495 }
496
497 {
498 let reader = mem_kv.revm_reader()?;
500
501 let account_info = reader.basic_ref(address)?;
503 assert!(account_info.is_some());
504 let info = account_info.unwrap();
505 assert_eq!(info.nonce, 42);
506 assert_eq!(info.balance, U256::from(1000u64));
507 assert_eq!(info.code_hash, hash);
508
509 let retrieved_code = reader.code_by_hash_ref(hash)?;
511 assert_eq!(retrieved_code, bytecode);
512
513 let storage_val = reader.storage_ref(address, StorageKey::from(U256::from(123u64)))?;
515 assert_eq!(storage_val, U256::ZERO);
516
517 let block_hash = reader.block_hash_ref(999)?;
519 assert_eq!(block_hash, B256::ZERO);
520 }
521
522 let header = Header { number: 123, gas_limit: 1_000_000, ..Default::default() };
524 let sealed = header.seal_slow();
525 let expected_hash = sealed.hash();
526 {
527 let writer = mem_kv.writer()?;
528 writer.queue_put::<tables::Headers>(&123u64, &sealed)?;
529 writer.commit()?;
530 }
531 {
532 let reader = mem_kv.revm_reader()?;
533 let block_hash = reader.block_hash_ref(123)?;
534 assert_eq!(block_hash, expected_hash);
535 }
536
537 Ok(())
538 }
539
540 #[test]
541 fn test_database_mutable_traits() -> Result<(), Box<dyn std::error::Error>> {
542 let mem_kv = MemKv::default();
543
544 let (address, account) = create_test_account();
545 let (hash, bytecode) = create_test_bytecode();
546
547 {
548 let writer = mem_kv.revm_writer()?;
550 writer.queue_put::<PlainAccountState>(&address, &account)?;
551 writer.queue_put::<Bytecodes>(&hash, &bytecode)?;
552 writer.persist()?;
553 }
554
555 {
556 let mut reader = mem_kv.revm_reader()?;
558
559 let account_info = reader.basic(address)?;
561 assert!(account_info.is_some());
562 let info = account_info.unwrap();
563 assert_eq!(info.nonce, 42);
564 assert_eq!(info.balance, U256::from(1000u64));
565
566 let retrieved_code = reader.code_by_hash(hash)?;
568 assert_eq!(retrieved_code, bytecode);
569
570 let storage_val = reader.storage(address, StorageKey::from(U256::from(123u64)))?;
572 assert_eq!(storage_val, U256::ZERO);
573
574 let block_hash = reader.block_hash(999)?;
576 assert_eq!(block_hash, B256::ZERO);
577 }
578
579 let header = Header { number: 456, gas_limit: 1_000_000, ..Default::default() };
581 let sealed = header.seal_slow();
582 let expected_hash = sealed.hash();
583 {
584 let writer = mem_kv.writer()?;
585 writer.queue_put::<tables::Headers>(&456u64, &sealed)?;
586 writer.commit()?;
587 }
588 {
589 let mut reader = mem_kv.revm_reader()?;
590 let block_hash = reader.block_hash(456)?;
591 assert_eq!(block_hash, expected_hash);
592 }
593
594 Ok(())
595 }
596
597 #[test]
598 fn test_write_database_traits() -> Result<(), Box<dyn std::error::Error>> {
599 let mem_kv = MemKv::default();
600
601 let (address, account) = create_test_account();
602 let (hash, bytecode) = create_test_bytecode();
603
604 {
605 let writer = mem_kv.revm_writer()?;
607 writer.queue_put::<PlainAccountState>(&address, &account)?;
608 writer.queue_put::<Bytecodes>(&hash, &bytecode)?;
609 writer.persist()?;
610 }
611
612 {
613 let mut writer = mem_kv.revm_writer()?;
615
616 let account_info = writer.basic_ref(address)?;
618 assert!(account_info.is_some());
619
620 let account_info_mut = writer.basic(address)?;
621 assert!(account_info_mut.is_some());
622
623 let code = writer.code_by_hash_ref(hash)?;
624 assert_eq!(code, bytecode);
625
626 let code_mut = writer.code_by_hash(hash)?;
627 assert_eq!(code_mut, bytecode);
628
629 }
631
632 Ok(())
633 }
634
635 #[test]
636 fn test_try_database_commit() -> Result<(), Box<dyn std::error::Error>> {
637 let mem_kv = MemKv::default();
638
639 let address = Address::from_slice(&[0x1; 20]);
640
641 {
642 let mut writer = mem_kv.revm_writer()?;
643
644 let mut changes = HashMap::default();
646 let account_info = AccountInfo {
647 nonce: 55,
648 balance: U256::from(2000u64),
649 code_hash: KECCAK256_EMPTY,
650 code: None,
651 account_id: None,
652 };
653
654 let mut storage = HashMap::default();
655 storage.insert(
656 StorageKey::from(U256::from(100u64)),
657 trevm::revm::state::EvmStorageSlot::new(U256::from(200u64), 0),
658 );
659
660 let revm_account = RevmAccount {
661 info: account_info,
662 storage,
663 status: trevm::revm::state::AccountStatus::Touched,
664 transaction_id: 0,
665 original_info: Box::default(),
666 };
667
668 changes.insert(address, revm_account);
669
670 writer.try_commit(changes)?;
672 writer.persist()?;
673 }
674
675 {
676 let reader = mem_kv.revm_reader()?;
678
679 let account: Option<Account> = reader.get::<PlainAccountState>(&address)?;
680 assert!(account.is_some());
681 let acc = account.unwrap();
682 assert_eq!(acc.nonce, 55);
683 assert_eq!(acc.balance, U256::from(2000u64));
684 assert_eq!(acc.bytecode_hash, None);
685
686 let key = U256::from(100);
687 let storage_val: Option<StorageValue> =
688 reader.get_dual::<tables::PlainStorageState>(&address, &key)?;
689 assert_eq!(storage_val, Some(U256::from(200u64)));
690 }
691
692 Ok(())
693 }
694
695 #[test]
696 fn test_mixed_usage_patterns() -> Result<(), Box<dyn std::error::Error>> {
697 let mem_kv = MemKv::default();
698
699 let address1 = Address::from_slice(&[0x1; 20]);
700 let address2 = Address::from_slice(&[0x2; 20]);
701
702 {
704 let writer = mem_kv.revm_writer()?;
705 let account = Account { nonce: 10, balance: U256::from(500u64), bytecode_hash: None };
706 writer.queue_put::<PlainAccountState>(&address1, &account)?;
707 writer.persist()?;
708 }
709
710 {
712 let mut writer = mem_kv.revm_writer()?;
713 let mut changes = HashMap::default();
714 let revm_account = RevmAccount {
715 info: AccountInfo {
716 nonce: 20,
717 balance: U256::from(1500u64),
718 code_hash: KECCAK256_EMPTY,
719 code: None,
720 account_id: None,
721 },
722 storage: HashMap::default(),
723 status: trevm::revm::state::AccountStatus::Touched,
724 transaction_id: 0,
725 original_info: Box::default(),
726 };
727 changes.insert(address2, revm_account);
728 writer.try_commit(changes)?;
729 writer.persist()?;
730 }
731
732 {
734 let reader = mem_kv.revm_reader()?;
735
736 let account1: Option<Account> = reader.get::<PlainAccountState>(&address1)?;
738 assert!(account1.is_some());
739 assert_eq!(account1.unwrap().nonce, 10);
740
741 let account2_info = reader.basic_ref(address2)?;
743 assert!(account2_info.is_some());
744 assert_eq!(account2_info.unwrap().nonce, 20);
745 }
746
747 Ok(())
748 }
749
750 #[test]
751 fn test_error_handling() -> Result<(), Box<dyn std::error::Error>> {
752 let mem_kv = MemKv::default();
753
754 let address = Address::from_slice(&[0x1; 20]);
755 let hash = B256::from_slice(&[0x99; 32]);
756
757 let reader = mem_kv.revm_reader()?;
758
759 let account_info = reader.basic_ref(address)?;
761 assert!(account_info.is_none());
762
763 let code = reader.code_by_hash_ref(hash)?;
765 assert!(code.is_empty());
766
767 let storage = reader.storage_ref(address, StorageKey::from(U256::from(123u64)))?;
769 assert_eq!(storage, U256::ZERO);
770
771 Ok(())
772 }
773
774 #[test]
775 fn test_concurrent_readers() -> Result<(), Box<dyn std::error::Error>> {
776 let mem_kv = MemKv::default();
777
778 let (address, account) = create_test_account();
779
780 {
782 let writer = mem_kv.revm_writer()?;
783 writer.queue_put::<PlainAccountState>(&address, &account)?;
784 writer.persist()?;
785 }
786
787 let reader1 = mem_kv.revm_reader()?;
789 let reader2 = mem_kv.revm_reader()?;
790
791 let account1 = reader1.basic_ref(address)?;
793 let account2 = reader2.basic_ref(address)?;
794
795 assert_eq!(account1, account2);
796 assert!(account1.is_some());
797
798 Ok(())
799 }
800
801 fn setup_history_kv() -> (MemKv, Address) {
816 let mem_kv = MemKv::default();
817 let address = Address::from_slice(&[0x1; 20]);
818 let slot = U256::from(0x42u64);
819
820 let writer = mem_kv.writer().unwrap();
821
822 let header1 = alloy::consensus::Header { number: 1, ..Default::default() }.seal_slow();
824 writer.put_header_inconsistent(&header1).unwrap();
825
826 let header15 = alloy::consensus::Header { number: 15, ..Default::default() }.seal_slow();
827 writer.put_header_inconsistent(&header15).unwrap();
828
829 let current_account =
831 Account { nonce: 10, balance: U256::from(1000u64), bytecode_hash: None };
832 writer.put_account(&address, ¤t_account).unwrap();
833 writer.put_storage(&address, &slot, &U256::from(200u64)).unwrap();
834
835 let history = BlockNumberList::new([5, 10]).unwrap();
837 writer.write_account_history(&address, 10, &history).unwrap();
838
839 let pre_state_5 = Account { nonce: 1, balance: U256::from(100u64), bytecode_hash: None };
841 writer.write_account_prestate(5, address, &pre_state_5).unwrap();
842
843 let pre_state_10 = Account { nonce: 5, balance: U256::from(500u64), bytecode_hash: None };
844 writer.write_account_prestate(10, address, &pre_state_10).unwrap();
845
846 let storage_history = BlockNumberList::new([5, 10]).unwrap();
848 writer.write_storage_history(&address, slot, 10, &storage_history).unwrap();
849
850 writer.write_storage_prestate(5, address, &slot, &U256::ZERO).unwrap();
852 writer.write_storage_prestate(10, address, &slot, &U256::from(100u64)).unwrap();
853
854 writer.raw_commit().unwrap();
855
856 (mem_kv, address)
857 }
858
859 #[test]
860 fn test_account_at_height_before_any_changes() {
861 let (mem_kv, address) = setup_history_kv();
862 let reader = mem_kv.reader().unwrap();
863
864 let account = reader.get_account_at_height(&address, Some(3)).unwrap().unwrap();
866 assert_eq!(account.nonce, 1);
867 assert_eq!(account.balance, U256::from(100u64));
868 }
869
870 #[test]
871 fn test_account_at_height_between_changes() {
872 let (mem_kv, address) = setup_history_kv();
873 let reader = mem_kv.reader().unwrap();
874
875 let account = reader.get_account_at_height(&address, Some(7)).unwrap().unwrap();
877 assert_eq!(account.nonce, 5);
878 assert_eq!(account.balance, U256::from(500u64));
879 }
880
881 #[test]
882 fn test_account_at_height_after_all_changes() {
883 let (mem_kv, address) = setup_history_kv();
884 let reader = mem_kv.reader().unwrap();
885
886 let account = reader.get_account_at_height(&address, Some(15)).unwrap().unwrap();
888 assert_eq!(account.nonce, 10);
889 assert_eq!(account.balance, U256::from(1000u64));
890 }
891
892 #[test]
893 fn test_account_at_height_exactly_at_change() {
894 let (mem_kv, address) = setup_history_kv();
895 let reader = mem_kv.reader().unwrap();
896
897 let account = reader.get_account_at_height(&address, Some(5)).unwrap().unwrap();
900 assert_eq!(account.nonce, 5);
901 assert_eq!(account.balance, U256::from(500u64));
902 }
903
904 #[test]
905 fn test_account_at_height_exactly_at_last_change() {
906 let (mem_kv, address) = setup_history_kv();
907 let reader = mem_kv.reader().unwrap();
908
909 let account = reader.get_account_at_height(&address, Some(10)).unwrap().unwrap();
912 assert_eq!(account.nonce, 10);
913 assert_eq!(account.balance, U256::from(1000u64));
914 }
915
916 #[test]
917 fn test_storage_at_height_before_any_changes() {
918 let (mem_kv, address) = setup_history_kv();
919 let reader = mem_kv.reader().unwrap();
920 let slot = U256::from(0x42u64);
921
922 let value = reader.get_storage_at_height(&address, &slot, Some(3)).unwrap();
924 assert_eq!(value, Some(U256::ZERO));
925 }
926
927 #[test]
928 fn test_storage_at_height_between_changes() {
929 let (mem_kv, address) = setup_history_kv();
930 let reader = mem_kv.reader().unwrap();
931 let slot = U256::from(0x42u64);
932
933 let value = reader.get_storage_at_height(&address, &slot, Some(7)).unwrap();
935 assert_eq!(value, Some(U256::from(100u64)));
936 }
937
938 #[test]
939 fn test_storage_at_height_after_all_changes() {
940 let (mem_kv, address) = setup_history_kv();
941 let reader = mem_kv.reader().unwrap();
942 let slot = U256::from(0x42u64);
943
944 let value = reader.get_storage_at_height(&address, &slot, Some(15)).unwrap();
946 assert_eq!(value, Some(U256::from(200u64)));
947 }
948
949 #[test]
950 fn test_account_at_height_no_history() {
951 let (mem_kv, _) = setup_history_kv();
952 let reader = mem_kv.reader().unwrap();
953
954 let unknown = Address::from_slice(&[0xFF; 20]);
956 let result = reader.get_account_at_height(&unknown, Some(5)).unwrap();
957 assert!(result.is_none());
958 }
959
960 #[test]
961 fn test_storage_at_height_no_history() {
962 let (mem_kv, address) = setup_history_kv();
963 let reader = mem_kv.reader().unwrap();
964
965 let unknown_slot = U256::from(0x99u64);
967 let result = reader.get_storage_at_height(&address, &unknown_slot, Some(5)).unwrap();
968 assert!(result.is_none());
969 }
970
971 #[test]
972 fn test_revm_read_at_height() {
973 let (mem_kv, address) = setup_history_kv();
974 let slot = U256::from(0x42u64);
975
976 let reader = mem_kv.revm_reader_at_height(3).unwrap();
978 let info = reader.basic_ref(address).unwrap().unwrap();
979 assert_eq!(info.nonce, 1);
980 assert_eq!(info.balance, U256::from(100u64));
981
982 let storage = reader.storage_ref(address, StorageKey::from(slot)).unwrap();
983 assert_eq!(storage, U256::ZERO);
984 }
985
986 #[test]
987 fn test_revm_read_at_height_current_state() {
988 let (mem_kv, address) = setup_history_kv();
989 let slot = U256::from(0x42u64);
990
991 let reader = mem_kv.revm_reader_at_height(15).unwrap();
993 let info = reader.basic_ref(address).unwrap().unwrap();
994 assert_eq!(info.nonce, 10);
995 assert_eq!(info.balance, U256::from(1000u64));
996
997 let storage = reader.storage_ref(address, StorageKey::from(slot)).unwrap();
998 assert_eq!(storage, U256::from(200u64));
999 }
1000
1001 #[test]
1002 fn test_revm_read_none_height_uses_current() {
1003 let (mem_kv, address) = setup_history_kv();
1004 let slot = U256::from(0x42u64);
1005
1006 let reader = mem_kv.revm_reader().unwrap();
1008 let info = reader.basic_ref(address).unwrap().unwrap();
1009 assert_eq!(info.nonce, 10);
1010 assert_eq!(info.balance, U256::from(1000u64));
1011
1012 let storage = reader.storage_ref(address, StorageKey::from(slot)).unwrap();
1013 assert_eq!(storage, U256::from(200u64));
1014 }
1015
1016 #[test]
1017 fn test_revm_reader_at_height_past_tip() {
1018 let (mem_kv, _) = setup_history_kv();
1019
1020 let err = mem_kv.revm_reader_at_height(20).unwrap_err();
1022 assert!(
1023 matches!(err, HotKvError::HeightOutOfRange { height: 20, first: 1, last: 15 }),
1024 "expected HeightOutOfRange, got {err:?}"
1025 );
1026 }
1027
1028 #[test]
1029 fn test_revm_reader_at_height_before_first_block() {
1030 let (mem_kv, _) = setup_history_kv();
1031
1032 let err = mem_kv.revm_reader_at_height(0).unwrap_err();
1034 assert!(
1035 matches!(err, HotKvError::HeightOutOfRange { height: 0, first: 1, last: 15 }),
1036 "expected HeightOutOfRange, got {err:?}"
1037 );
1038 }
1039
1040 #[test]
1041 fn test_revm_reader_at_height_empty_db() {
1042 let mem_kv = MemKv::default();
1043
1044 let err = mem_kv.revm_reader_at_height(5).unwrap_err();
1046 assert!(matches!(err, HotKvError::NoBlocks), "expected NoBlocks, got {err:?}");
1047 }
1048
1049 #[test]
1050 fn test_checked_account_at_height_out_of_range() {
1051 let (mem_kv, address) = setup_history_kv();
1052 let reader = mem_kv.reader().unwrap();
1053
1054 let err = reader.get_account_at_height_checked(&address, Some(20)).unwrap_err();
1056 assert!(
1057 matches!(
1058 err,
1059 crate::db::HistoryError::HeightOutOfRange { height: 20, first: 1, last: 15 }
1060 ),
1061 "expected HeightOutOfRange, got {err:?}"
1062 );
1063 }
1064
1065 #[test]
1066 fn test_checked_storage_at_height_out_of_range() {
1067 let (mem_kv, address) = setup_history_kv();
1068 let reader = mem_kv.reader().unwrap();
1069 let slot = U256::from(0x42u64);
1070
1071 let err = reader.get_storage_at_height_checked(&address, &slot, Some(20)).unwrap_err();
1073 assert!(
1074 matches!(
1075 err,
1076 crate::db::HistoryError::HeightOutOfRange { height: 20, first: 1, last: 15 }
1077 ),
1078 "expected HeightOutOfRange, got {err:?}"
1079 );
1080 }
1081
1082 #[test]
1083 fn test_checked_methods_pass_for_valid_height() {
1084 let (mem_kv, address) = setup_history_kv();
1085 let reader = mem_kv.reader().unwrap();
1086 let slot = U256::from(0x42u64);
1087
1088 let account = reader.get_account_at_height_checked(&address, Some(7)).unwrap().unwrap();
1090 assert_eq!(account.nonce, 5);
1091
1092 let storage =
1093 reader.get_storage_at_height_checked(&address, &slot, Some(7)).unwrap().unwrap();
1094 assert_eq!(storage, U256::from(100u64));
1095 }
1096
1097 #[test]
1098 fn test_checked_methods_none_height() {
1099 let (mem_kv, address) = setup_history_kv();
1100 let reader = mem_kv.reader().unwrap();
1101 let slot = U256::from(0x42u64);
1102
1103 let account = reader.get_account_at_height_checked(&address, None).unwrap().unwrap();
1105 assert_eq!(account.nonce, 10);
1106
1107 let storage = reader.get_storage_at_height_checked(&address, &slot, None).unwrap().unwrap();
1108 assert_eq!(storage, U256::from(200u64));
1109 }
1110}