1use crate::{DatabaseHashedCursorFactory, DatabaseTrieCursorFactory};
2use alloy_primitives::{keccak256, map::HashMap, Address, B256};
3use reth_db_api::transaction::DbTx;
4use reth_execution_errors::StateProofError;
5use reth_trie::{
6 hashed_cursor::HashedPostStateCursorFactory,
7 proof::{Proof, StorageProof},
8 trie_cursor::InMemoryTrieCursorFactory,
9 AccountProof, HashedPostStateSorted, HashedStorage, MultiProof, MultiProofTargets,
10 StorageMultiProof, TrieInput,
11};
12
13pub trait DatabaseProof<'a, TX> {
15 fn from_tx(tx: &'a TX) -> Self;
17
18 fn overlay_account_proof(
20 tx: &'a TX,
21 input: TrieInput,
22 address: Address,
23 slots: &[B256],
24 ) -> Result<AccountProof, StateProofError>;
25
26 fn overlay_multiproof(
28 tx: &'a TX,
29 input: TrieInput,
30 targets: MultiProofTargets,
31 ) -> Result<MultiProof, StateProofError>;
32}
33
34impl<'a, TX: DbTx> DatabaseProof<'a, TX>
35 for Proof<DatabaseTrieCursorFactory<'a, TX>, DatabaseHashedCursorFactory<'a, TX>>
36{
37 fn from_tx(tx: &'a TX) -> Self {
39 Self::new(DatabaseTrieCursorFactory::new(tx), DatabaseHashedCursorFactory::new(tx))
40 }
41
42 fn overlay_account_proof(
43 tx: &'a TX,
44 input: TrieInput,
45 address: Address,
46 slots: &[B256],
47 ) -> Result<AccountProof, StateProofError> {
48 let nodes_sorted = input.nodes.into_sorted();
49 let state_sorted = input.state.into_sorted();
50 Self::from_tx(tx)
51 .with_trie_cursor_factory(InMemoryTrieCursorFactory::new(
52 DatabaseTrieCursorFactory::new(tx),
53 &nodes_sorted,
54 ))
55 .with_hashed_cursor_factory(HashedPostStateCursorFactory::new(
56 DatabaseHashedCursorFactory::new(tx),
57 &state_sorted,
58 ))
59 .with_prefix_sets_mut(input.prefix_sets)
60 .account_proof(address, slots)
61 }
62
63 fn overlay_multiproof(
64 tx: &'a TX,
65 input: TrieInput,
66 targets: MultiProofTargets,
67 ) -> Result<MultiProof, StateProofError> {
68 let nodes_sorted = input.nodes.into_sorted();
69 let state_sorted = input.state.into_sorted();
70 Self::from_tx(tx)
71 .with_trie_cursor_factory(InMemoryTrieCursorFactory::new(
72 DatabaseTrieCursorFactory::new(tx),
73 &nodes_sorted,
74 ))
75 .with_hashed_cursor_factory(HashedPostStateCursorFactory::new(
76 DatabaseHashedCursorFactory::new(tx),
77 &state_sorted,
78 ))
79 .with_prefix_sets_mut(input.prefix_sets)
80 .multiproof(targets)
81 }
82}
83
84pub trait DatabaseStorageProof<'a, TX> {
86 fn from_tx(tx: &'a TX, address: Address) -> Self;
88
89 fn overlay_storage_proof(
91 tx: &'a TX,
92 address: Address,
93 slot: B256,
94 storage: HashedStorage,
95 ) -> Result<reth_trie::StorageProof, StateProofError>;
96
97 fn overlay_storage_multiproof(
99 tx: &'a TX,
100 address: Address,
101 slots: &[B256],
102 storage: HashedStorage,
103 ) -> Result<StorageMultiProof, StateProofError>;
104}
105
106impl<'a, TX: DbTx> DatabaseStorageProof<'a, TX>
107 for StorageProof<DatabaseTrieCursorFactory<'a, TX>, DatabaseHashedCursorFactory<'a, TX>>
108{
109 fn from_tx(tx: &'a TX, address: Address) -> Self {
110 Self::new(DatabaseTrieCursorFactory::new(tx), DatabaseHashedCursorFactory::new(tx), address)
111 }
112
113 fn overlay_storage_proof(
114 tx: &'a TX,
115 address: Address,
116 slot: B256,
117 storage: HashedStorage,
118 ) -> Result<reth_trie::StorageProof, StateProofError> {
119 let hashed_address = keccak256(address);
120 let prefix_set = storage.construct_prefix_set();
121 let state_sorted = HashedPostStateSorted::new(
122 Default::default(),
123 HashMap::from_iter([(hashed_address, storage.into_sorted())]),
124 );
125 Self::from_tx(tx, address)
126 .with_hashed_cursor_factory(HashedPostStateCursorFactory::new(
127 DatabaseHashedCursorFactory::new(tx),
128 &state_sorted,
129 ))
130 .with_prefix_set_mut(prefix_set)
131 .storage_proof(slot)
132 }
133
134 fn overlay_storage_multiproof(
135 tx: &'a TX,
136 address: Address,
137 slots: &[B256],
138 storage: HashedStorage,
139 ) -> Result<StorageMultiProof, StateProofError> {
140 let hashed_address = keccak256(address);
141 let targets = slots.iter().map(keccak256).collect();
142 let prefix_set = storage.construct_prefix_set();
143 let state_sorted = HashedPostStateSorted::new(
144 Default::default(),
145 HashMap::from_iter([(hashed_address, storage.into_sorted())]),
146 );
147 Self::from_tx(tx, address)
148 .with_hashed_cursor_factory(HashedPostStateCursorFactory::new(
149 DatabaseHashedCursorFactory::new(tx),
150 &state_sorted,
151 ))
152 .with_prefix_set_mut(prefix_set)
153 .storage_multiproof(targets)
154 }
155}