1use std::collections::HashSet;
8use std::path::Path;
9
10pub mod rocksdb;
11
12use anyhow::Result;
13use node_data::ledger::{
14 Block, Fault, Header, Label, LedgerTransaction, SpendingId,
15 SpentTransaction,
16};
17use node_data::message::{ConsensusHeader, payload};
18use serde::{Deserialize, Serialize};
19
20pub struct LightBlock {
21 pub header: Header,
22 pub transactions_ids: Vec<[u8; 32]>,
23 pub faults_ids: Vec<[u8; 32]>,
24}
25
26pub trait DB: Send + Sync + 'static {
27 type P<'a>: Persist;
28
29 fn create_or_open<T>(path: T, opts: DatabaseOptions) -> Self
33 where
34 T: AsRef<Path>;
35
36 fn view<F, T>(&self, f: F) -> T
38 where
39 F: for<'a> FnOnce(&Self::P<'a>) -> T;
40
41 fn update<F, T>(&self, f: F) -> Result<T>
49 where
50 F: for<'a> FnOnce(&mut Self::P<'a>) -> Result<T>;
51
52 fn update_dry_run<F, T>(&self, dry_run: bool, f: F) -> Result<T>
53 where
54 F: for<'a> FnOnce(&mut Self::P<'a>) -> Result<T>;
55
56 fn close(&mut self);
57}
58
59pub trait Ledger {
61 fn store_block(
64 &mut self,
65 header: &Header,
66 txs: &[SpentTransaction],
67 faults: &[Fault],
68 label: Label,
69 ) -> Result<usize>;
70
71 fn delete_block(&mut self, b: &Block) -> Result<()>;
72 fn block_header(&self, hash: &[u8]) -> Result<Option<Header>>;
73
74 fn light_block(&self, hash: &[u8]) -> Result<Option<LightBlock>>;
75
76 fn block(&self, hash: &[u8]) -> Result<Option<Block>>;
77 fn block_hash_by_height(&self, height: u64) -> Result<Option<[u8; 32]>>;
78 fn block_by_height(&self, height: u64) -> Result<Option<Block>>;
79
80 fn store_blob_data(&self, hash: &[u8; 32], data: Vec<u8>) -> Result<()>;
81 fn blob_data_by_hash(&self, hash: &[u8; 32]) -> Result<Option<Vec<u8>>>;
82 fn store_blobs_height(
83 &self,
84 block_height: u64,
85 blob_hashes: &[[u8; 32]],
86 ) -> Result<()>;
87 fn blobs_by_height(
88 &self,
89 block_height: u64,
90 ) -> Result<Option<Vec<[u8; 32]>>>;
91 fn delete_blobs_by_height(&self, block_height: u64) -> Result<()>;
92
93 fn block_exists(&self, hash: &[u8]) -> Result<bool>;
94
95 fn ledger_tx(&self, tx_id: &[u8]) -> Result<Option<SpentTransaction>>;
96 fn ledger_txs(
97 &self,
98 tx_ids: Vec<&[u8; 32]>,
99 ) -> Result<Vec<SpentTransaction>>;
100
101 fn ledger_tx_exists(&self, tx_id: &[u8]) -> Result<bool>;
102
103 fn block_label_by_height(
104 &self,
105 height: u64,
106 ) -> Result<Option<([u8; 32], Label)>>;
107
108 fn store_block_label(
109 &mut self,
110 height: u64,
111 hash: &[u8; 32],
112 label: Label,
113 ) -> Result<()>;
114
115 fn faults_by_block(&self, start_height: u64) -> Result<Vec<Fault>>;
116 fn faults(&self, faults_ids: &[[u8; 32]]) -> Result<Vec<Fault>>;
117
118 fn latest_block_opt(&self) -> Result<Option<LightBlock>>;
119 fn latest_block(&self) -> Result<LightBlock>;
120}
121
122pub trait ConsensusStorage {
123 fn store_candidate(&mut self, cm: Block) -> Result<()>;
125 fn candidate(&self, hash: &[u8]) -> Result<Option<Block>>;
126
127 fn candidate_by_iteration(
129 &self,
130 ch: &ConsensusHeader,
131 ) -> Result<Option<Block>>;
132
133 fn clear_candidates(&mut self) -> Result<()>;
134
135 fn delete_candidate<F>(&mut self, closure: F) -> Result<()>
136 where
137 F: FnOnce(u64) -> bool + std::marker::Copy;
138
139 fn count_candidates(&self) -> usize;
140
141 fn store_validation_result(
143 &mut self,
144 ch: &ConsensusHeader,
145 vr: &payload::ValidationResult,
146 ) -> Result<()>;
147
148 fn validation_result(
149 &self,
150 ch: &ConsensusHeader,
151 ) -> Result<Option<payload::ValidationResult>>;
152
153 fn clear_validation_results(&mut self) -> Result<()>;
154
155 fn delete_validation_results<F>(&mut self, closure: F) -> Result<()>
156 where
157 F: FnOnce([u8; 32]) -> bool + std::marker::Copy;
158
159 fn count_validation_results(&self) -> usize;
160}
161
162pub trait Mempool {
163 fn store_mempool_tx(
165 &mut self,
166 tx: &LedgerTransaction,
167 timestamp: u64,
168 ) -> Result<()>;
169
170 fn mempool_tx(&self, tx_id: [u8; 32]) -> Result<Option<LedgerTransaction>>;
172
173 fn mempool_tx_exists(&self, tx_id: [u8; 32]) -> Result<bool>;
175
176 fn delete_mempool_tx(
182 &mut self,
183 tx_id: [u8; 32],
184 cascade: bool,
185 ) -> Result<Vec<[u8; 32]>>;
186
187 fn mempool_txs_by_spendable_ids(
189 &self,
190 n: &[SpendingId],
191 ) -> HashSet<[u8; 32]>;
192
193 fn mempool_txs_sorted_by_fee(
195 &self,
196 ) -> Box<dyn Iterator<Item = LedgerTransaction> + '_>;
197
198 fn mempool_txs_ids_sorted_by_fee(
200 &self,
201 ) -> Box<dyn Iterator<Item = (u64, [u8; 32])> + '_>;
202
203 fn mempool_txs_ids_sorted_by_low_fee(
205 &self,
206 ) -> Box<dyn Iterator<Item = (u64, [u8; 32])> + '_>;
207
208 fn mempool_txs_ids(&self) -> Result<Vec<[u8; 32]>>;
210
211 fn mempool_expired_txs(&self, timestamp: u64) -> Result<Vec<[u8; 32]>>;
213
214 fn mempool_txs_count(&self) -> usize;
216}
217
218pub trait Metadata {
219 fn op_write<T: AsRef<[u8]>>(&mut self, key: &[u8], value: T) -> Result<()>;
221
222 fn op_read(&self, key: &[u8]) -> Result<Option<Vec<u8>>>;
224}
225
226pub trait Persist:
227 Ledger + ConsensusStorage + Mempool + Metadata + core::fmt::Debug
228{
229 fn clear_database(&mut self) -> Result<()>;
232 fn commit(self) -> Result<()>;
233 fn rollback(self) -> Result<()>;
234}
235
236pub fn into_array<const N: usize>(value: &[u8]) -> [u8; N] {
237 let mut res = [0u8; N];
238 res.copy_from_slice(&value[0..N]);
239 res
240}
241
242#[derive(Serialize, Deserialize, Clone, Debug)]
243pub struct DatabaseOptions {
244 pub blocks_cf_max_write_buffer_size: usize,
247
248 pub blocks_cf_disable_block_cache: bool,
254
255 pub mempool_cf_max_write_buffer_size: usize,
257
258 pub enable_debug: bool,
260
261 pub create_if_missing: bool,
263}
264
265impl Default for DatabaseOptions {
266 fn default() -> Self {
267 Self {
268 blocks_cf_max_write_buffer_size: 1024 * 1024, mempool_cf_max_write_buffer_size: 10 * 1024 * 1024, blocks_cf_disable_block_cache: true,
271 enable_debug: false,
272 create_if_missing: true,
273 }
274 }
275}