1use borsh::{maybestd, BorshDeserialize, BorshSerialize};
29use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
30use jmt::storage::{Node, NodeKey};
31use jmt::Version;
32use sov_rollup_interface::stf::{Event, EventKey};
33use sov_schema_db::schema::{KeyDecoder, KeyEncoder, ValueCodec};
34use sov_schema_db::{CodecError, SeekKeyEncoder};
35
36use super::types::{
37 AccessoryKey, AccessoryStateValue, BatchNumber, DbHash, EventNumber, JmtValue, SlotNumber,
38 StateKey, StoredBatch, StoredSlot, StoredTransaction, TxNumber,
39};
40
41pub const STATE_TABLES: &[&str] = &[
44 KeyHashToKey::table_name(),
45 JmtValues::table_name(),
46 JmtNodes::table_name(),
47];
48
49pub const LEDGER_TABLES: &[&str] = &[
52 SlotByNumber::table_name(),
53 SlotByHash::table_name(),
54 BatchByHash::table_name(),
55 BatchByNumber::table_name(),
56 TxByHash::table_name(),
57 TxByNumber::table_name(),
58 EventByKey::table_name(),
59 EventByNumber::table_name(),
60];
61
62pub const NATIVE_TABLES: &[&str] = &[ModuleAccessoryState::table_name()];
66
67macro_rules! define_table_without_codec {
87 ($(#[$docs:meta])+ ( $table_name:ident ) $key:ty => $value:ty) => {
88 $(#[$docs])+
89 #[doc = concat!("Takes [`", stringify!($key), "`] as a key and returns [`", stringify!($value), "`]")]
91 #[derive(Clone, Copy, Debug, Default)]
92 pub(crate) struct $table_name;
93
94 impl ::sov_schema_db::schema::Schema for $table_name {
95 const COLUMN_FAMILY_NAME: &'static str = $table_name::table_name();
96 type Key = $key;
97 type Value = $value;
98 }
99
100 impl $table_name {
101 #[doc=concat!("Return ", stringify!($table_name), " as it is present inside the database.")]
102 pub const fn table_name() -> &'static str {
103 ::core::stringify!($table_name)
104 }
105 }
106
107 impl ::std::fmt::Display for $table_name {
108 fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
109 ::core::write!(f, "{}", stringify!($table_name))
110 }
111 }
112 };
113}
114
115macro_rules! impl_borsh_value_codec {
116 ($table_name:ident, $value:ty) => {
117 impl ::sov_schema_db::schema::ValueCodec<$table_name> for $value {
118 fn encode_value(
119 &self,
120 ) -> ::std::result::Result<
121 ::sov_rollup_interface::maybestd::vec::Vec<u8>,
122 ::sov_schema_db::CodecError,
123 > {
124 ::borsh::BorshSerialize::try_to_vec(self).map_err(Into::into)
125 }
126
127 fn decode_value(
128 data: &[u8],
129 ) -> ::std::result::Result<Self, ::sov_schema_db::CodecError> {
130 ::borsh::BorshDeserialize::deserialize_reader(&mut &data[..]).map_err(Into::into)
131 }
132 }
133 };
134}
135
136macro_rules! define_table_with_default_codec {
147 ($(#[$docs:meta])+ ($table_name:ident) $key:ty => $value:ty) => {
148 define_table_without_codec!($(#[$docs])+ ( $table_name ) $key => $value);
149
150 impl ::sov_schema_db::schema::KeyEncoder<$table_name> for $key {
151 fn encode_key(&self) -> ::std::result::Result<::sov_rollup_interface::maybestd::vec::Vec<u8>, ::sov_schema_db::CodecError> {
152 ::borsh::BorshSerialize::try_to_vec(self).map_err(Into::into)
153 }
154 }
155
156 impl ::sov_schema_db::schema::KeyDecoder<$table_name> for $key {
157 fn decode_key(data: &[u8]) -> ::std::result::Result<Self, ::sov_schema_db::CodecError> {
158 ::borsh::BorshDeserialize::deserialize_reader(&mut &data[..]).map_err(Into::into)
159 }
160 }
161
162 impl_borsh_value_codec!($table_name, $value);
163 };
164}
165
166macro_rules! define_table_with_seek_key_codec {
172 ($(#[$docs:meta])+ ($table_name:ident) $key:ty => $value:ty) => {
173 define_table_without_codec!($(#[$docs])+ ( $table_name ) $key => $value);
174
175 impl ::sov_schema_db::schema::KeyEncoder<$table_name> for $key {
176 fn encode_key(&self) -> ::std::result::Result<::sov_rollup_interface::maybestd::vec::Vec<u8>, ::sov_schema_db::CodecError> {
177 use ::anyhow::Context as _;
178 use ::bincode::Options as _;
179
180 let bincode_options = ::bincode::options()
181 .with_fixint_encoding()
182 .with_big_endian();
183
184 bincode_options.serialize(self).context("Failed to serialize key").map_err(Into::into)
185 }
186 }
187
188 impl ::sov_schema_db::schema::KeyDecoder<$table_name> for $key {
189 fn decode_key(data: &[u8]) -> ::std::result::Result<Self, ::sov_schema_db::CodecError> {
190 use ::anyhow::Context as _;
191 use ::bincode::Options as _;
192
193 let bincode_options = ::bincode::options()
194 .with_fixint_encoding()
195 .with_big_endian();
196
197 bincode_options.deserialize_from(&mut &data[..]).context("Failed to deserialize key").map_err(Into::into)
198 }
199 }
200
201 impl ::sov_schema_db::SeekKeyEncoder<$table_name> for $key {
202 fn encode_seek_key(&self) -> ::std::result::Result<::sov_rollup_interface::maybestd::vec::Vec<u8>, ::sov_schema_db::CodecError> {
203 <Self as ::sov_schema_db::schema::KeyEncoder<$table_name>>::encode_key(self)
204 }
205 }
206
207 impl_borsh_value_codec!($table_name, $value);
208 };
209}
210
211define_table_with_seek_key_codec!(
213 (SlotByNumber) SlotNumber => StoredSlot
215);
216
217define_table_with_default_codec!(
218 (SlotByHash) DbHash => SlotNumber
220);
221
222define_table_with_default_codec!(
223 (ModuleAccessoryState) AccessoryKey => AccessoryStateValue
225);
226
227define_table_with_seek_key_codec!(
228 (BatchByNumber) BatchNumber => StoredBatch
230);
231
232define_table_with_default_codec!(
233 (BatchByHash) DbHash => BatchNumber
235);
236
237define_table_with_seek_key_codec!(
238 (TxByNumber) TxNumber => StoredTransaction
240);
241
242define_table_with_default_codec!(
243 (TxByHash) DbHash => TxNumber
245);
246
247define_table_with_seek_key_codec!(
248 (EventByNumber) EventNumber => Event
250);
251
252define_table_with_default_codec!(
253 (EventByKey) (EventKey, TxNumber, EventNumber) => ()
255);
256
257define_table_without_codec!(
258 (JmtNodes) NodeKey => Node
260);
261
262impl KeyEncoder<JmtNodes> for NodeKey {
263 fn encode_key(&self) -> sov_schema_db::schema::Result<Vec<u8>> {
264 self.try_to_vec().map_err(CodecError::from)
265 }
266}
267impl KeyDecoder<JmtNodes> for NodeKey {
268 fn decode_key(data: &[u8]) -> sov_schema_db::schema::Result<Self> {
269 Ok(Self::deserialize_reader(&mut &data[..])?)
270 }
271}
272
273impl ValueCodec<JmtNodes> for Node {
274 fn encode_value(&self) -> sov_schema_db::schema::Result<Vec<u8>> {
275 self.try_to_vec().map_err(CodecError::from)
276 }
277
278 fn decode_value(data: &[u8]) -> sov_schema_db::schema::Result<Self> {
279 Ok(Self::deserialize_reader(&mut &data[..])?)
280 }
281}
282
283define_table_without_codec!(
284 (JmtValues) (StateKey, Version) => JmtValue
286);
287
288impl<T: AsRef<[u8]> + PartialEq + core::fmt::Debug> KeyEncoder<JmtValues> for (T, Version) {
289 fn encode_key(&self) -> sov_schema_db::schema::Result<Vec<u8>> {
290 let mut out =
291 Vec::with_capacity(self.0.as_ref().len() + std::mem::size_of::<Version>() + 8);
292 self.0
293 .as_ref()
294 .serialize(&mut out)
295 .map_err(CodecError::from)?;
296 out.write_u64::<BigEndian>(self.1)
298 .expect("serialization to vec is infallible");
299 Ok(out)
300 }
301}
302
303impl<T: AsRef<[u8]> + PartialEq + core::fmt::Debug> SeekKeyEncoder<JmtValues> for (T, Version) {
304 fn encode_seek_key(&self) -> sov_schema_db::schema::Result<Vec<u8>> {
305 self.encode_key()
306 }
307}
308
309impl KeyDecoder<JmtValues> for (StateKey, Version) {
310 fn decode_key(data: &[u8]) -> sov_schema_db::schema::Result<Self> {
311 let mut cursor = maybestd::io::Cursor::new(data);
312 let key = Vec::<u8>::deserialize_reader(&mut cursor)?;
313 let version = cursor.read_u64::<BigEndian>()?;
314 Ok((key, version))
315 }
316}
317
318impl ValueCodec<JmtValues> for JmtValue {
319 fn encode_value(&self) -> sov_schema_db::schema::Result<Vec<u8>> {
320 self.try_to_vec().map_err(CodecError::from)
321 }
322
323 fn decode_value(data: &[u8]) -> sov_schema_db::schema::Result<Self> {
324 Ok(Self::deserialize_reader(&mut &data[..])?)
325 }
326}
327
328define_table_with_default_codec!(
329 (KeyHashToKey) [u8;32] => StateKey
334);