revm_database_interface/
async_db.rs1use core::future::Future;
2
3use crate::{DBErrorMarker, Database, DatabaseRef};
4use core::error::Error;
5use primitives::{Address, StorageKey, StorageValue, B256};
6use state::{AccountInfo, Bytecode};
7use tokio::runtime::{Handle, Runtime};
8
9pub trait DatabaseAsync {
15 type Error: Send + DBErrorMarker + Error;
17
18 fn basic_async(
20 &mut self,
21 address: Address,
22 ) -> impl Future<Output = Result<Option<AccountInfo>, Self::Error>> + Send;
23
24 fn code_by_hash_async(
26 &mut self,
27 code_hash: B256,
28 ) -> impl Future<Output = Result<Bytecode, Self::Error>> + Send;
29
30 fn storage_async(
32 &mut self,
33 address: Address,
34 index: StorageKey,
35 ) -> impl Future<Output = Result<StorageValue, Self::Error>> + Send;
36
37 fn block_hash_async(
39 &mut self,
40 number: u64,
41 ) -> impl Future<Output = Result<B256, Self::Error>> + Send;
42}
43
44pub trait DatabaseAsyncRef {
50 type Error: Send + DBErrorMarker + Error;
52
53 fn basic_async_ref(
55 &self,
56 address: Address,
57 ) -> impl Future<Output = Result<Option<AccountInfo>, Self::Error>> + Send;
58
59 fn code_by_hash_async_ref(
61 &self,
62 code_hash: B256,
63 ) -> impl Future<Output = Result<Bytecode, Self::Error>> + Send;
64
65 fn storage_async_ref(
67 &self,
68 address: Address,
69 index: StorageKey,
70 ) -> impl Future<Output = Result<StorageValue, Self::Error>> + Send;
71
72 fn block_hash_async_ref(
74 &self,
75 number: u64,
76 ) -> impl Future<Output = Result<B256, Self::Error>> + Send;
77}
78
79#[derive(Debug)]
81pub struct WrapDatabaseAsync<T> {
82 db: T,
83 rt: HandleOrRuntime,
84}
85
86impl<T> WrapDatabaseAsync<T> {
87 pub fn new(db: T) -> Option<Self> {
91 let rt = match Handle::try_current() {
92 Ok(handle) => match handle.runtime_flavor() {
93 tokio::runtime::RuntimeFlavor::CurrentThread => return None,
94 _ => HandleOrRuntime::Handle(handle),
95 },
96 Err(_) => return None,
97 };
98 Some(Self { db, rt })
99 }
100
101 pub fn with_runtime(db: T, runtime: Runtime) -> Self {
107 let rt = HandleOrRuntime::Runtime(runtime);
108 Self { db, rt }
109 }
110
111 pub fn with_handle(db: T, handle: Handle) -> Self {
118 let rt = HandleOrRuntime::Handle(handle);
119 Self { db, rt }
120 }
121}
122
123impl<T: DatabaseAsync> Database for WrapDatabaseAsync<T> {
124 type Error = T::Error;
125
126 #[inline]
127 fn basic(&mut self, address: Address) -> Result<Option<AccountInfo>, Self::Error> {
128 self.rt.block_on(self.db.basic_async(address))
129 }
130
131 #[inline]
132 fn code_by_hash(&mut self, code_hash: B256) -> Result<Bytecode, Self::Error> {
133 self.rt.block_on(self.db.code_by_hash_async(code_hash))
134 }
135
136 #[inline]
137 fn storage(
138 &mut self,
139 address: Address,
140 index: StorageKey,
141 ) -> Result<StorageValue, Self::Error> {
142 self.rt.block_on(self.db.storage_async(address, index))
143 }
144
145 #[inline]
146 fn block_hash(&mut self, number: u64) -> Result<B256, Self::Error> {
147 self.rt.block_on(self.db.block_hash_async(number))
148 }
149}
150
151impl<T: DatabaseAsyncRef> DatabaseRef for WrapDatabaseAsync<T> {
152 type Error = T::Error;
153
154 #[inline]
155 fn basic_ref(&self, address: Address) -> Result<Option<AccountInfo>, Self::Error> {
156 self.rt.block_on(self.db.basic_async_ref(address))
157 }
158
159 #[inline]
160 fn code_by_hash_ref(&self, code_hash: B256) -> Result<Bytecode, Self::Error> {
161 self.rt.block_on(self.db.code_by_hash_async_ref(code_hash))
162 }
163
164 #[inline]
165 fn storage_ref(
166 &self,
167 address: Address,
168 index: StorageKey,
169 ) -> Result<StorageValue, Self::Error> {
170 self.rt.block_on(self.db.storage_async_ref(address, index))
171 }
172
173 #[inline]
174 fn block_hash_ref(&self, number: u64) -> Result<B256, Self::Error> {
175 self.rt.block_on(self.db.block_hash_async_ref(number))
176 }
177}
178
179#[derive(Debug)]
181enum HandleOrRuntime {
182 Handle(Handle),
183 Runtime(Runtime),
184}
185
186impl HandleOrRuntime {
187 #[inline]
188 fn block_on<F>(&self, f: F) -> F::Output
189 where
190 F: Future + Send,
191 F::Output: Send,
192 {
193 match self {
194 Self::Handle(handle) => tokio::task::block_in_place(move || handle.block_on(f)),
195 Self::Runtime(rt) => rt.block_on(f),
196 }
197 }
198}