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