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, SpendingId, SpentTransaction, Transaction,
15};
16use node_data::message::{payload, ConsensusHeader};
17use serde::{Deserialize, Serialize};
18
19pub struct LightBlock {
20 pub header: Header,
21 pub transactions_ids: Vec<[u8; 32]>,
22 pub faults_ids: Vec<[u8; 32]>,
23}
24
25pub trait DB: Send + Sync + 'static {
26 type P<'a>: Persist;
27
28 fn create_or_open<T>(path: T, opts: DatabaseOptions) -> Self
32 where
33 T: AsRef<Path>;
34
35 fn view<F, T>(&self, f: F) -> T
37 where
38 F: for<'a> FnOnce(&Self::P<'a>) -> T;
39
40 fn update<F, T>(&self, f: F) -> Result<T>
48 where
49 F: for<'a> FnOnce(&mut Self::P<'a>) -> Result<T>;
50
51 fn update_dry_run<F, T>(&self, dry_run: bool, f: F) -> Result<T>
52 where
53 F: for<'a> FnOnce(&mut Self::P<'a>) -> Result<T>;
54
55 fn close(&mut self);
56}
57
58pub 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 block_exists(&self, hash: &[u8]) -> Result<bool>;
81
82 fn ledger_tx(&self, tx_id: &[u8]) -> Result<Option<SpentTransaction>>;
83 fn ledger_txs(
84 &self,
85 tx_ids: Vec<&[u8; 32]>,
86 ) -> Result<Vec<SpentTransaction>>;
87
88 fn ledger_tx_exists(&self, tx_id: &[u8]) -> Result<bool>;
89
90 fn block_label_by_height(
91 &self,
92 height: u64,
93 ) -> Result<Option<([u8; 32], Label)>>;
94
95 fn store_block_label(
96 &mut self,
97 height: u64,
98 hash: &[u8; 32],
99 label: Label,
100 ) -> Result<()>;
101
102 fn faults_by_block(&self, start_height: u64) -> Result<Vec<Fault>>;
103 fn faults(&self, faults_ids: &[[u8; 32]]) -> Result<Vec<Fault>>;
104}
105
106pub trait ConsensusStorage {
107 fn store_candidate(&mut self, cm: Block) -> Result<()>;
109 fn candidate(&self, hash: &[u8]) -> Result<Option<Block>>;
110
111 fn candidate_by_iteration(
113 &self,
114 ch: &ConsensusHeader,
115 ) -> Result<Option<Block>>;
116
117 fn clear_candidates(&mut self) -> Result<()>;
118
119 fn delete_candidate<F>(&mut self, closure: F) -> Result<()>
120 where
121 F: FnOnce(u64) -> bool + std::marker::Copy;
122
123 fn count_candidates(&self) -> usize;
124
125 fn store_validation_result(
127 &mut self,
128 ch: &ConsensusHeader,
129 vr: &payload::ValidationResult,
130 ) -> Result<()>;
131
132 fn validation_result(
133 &self,
134 ch: &ConsensusHeader,
135 ) -> Result<Option<payload::ValidationResult>>;
136
137 fn clear_validation_results(&mut self) -> Result<()>;
138
139 fn delete_validation_results<F>(&mut self, closure: F) -> Result<()>
140 where
141 F: FnOnce([u8; 32]) -> bool + std::marker::Copy;
142
143 fn count_validation_results(&self) -> usize;
144}
145
146pub trait Mempool {
147 fn store_mempool_tx(
149 &mut self,
150 tx: &Transaction,
151 timestamp: u64,
152 ) -> Result<()>;
153
154 fn mempool_tx(&self, tx_id: [u8; 32]) -> Result<Option<Transaction>>;
156
157 fn mempool_tx_exists(&self, tx_id: [u8; 32]) -> Result<bool>;
159
160 fn delete_mempool_tx(
166 &mut self,
167 tx_id: [u8; 32],
168 cascade: bool,
169 ) -> Result<Vec<[u8; 32]>>;
170
171 fn mempool_txs_by_spendable_ids(
173 &self,
174 n: &[SpendingId],
175 ) -> HashSet<[u8; 32]>;
176
177 fn mempool_txs_sorted_by_fee(
179 &self,
180 ) -> Result<Box<dyn Iterator<Item = Transaction> + '_>>;
181
182 fn mempool_txs_ids_sorted_by_fee(
184 &self,
185 ) -> Result<Box<dyn Iterator<Item = (u64, [u8; 32])> + '_>>;
186
187 fn mempool_txs_ids_sorted_by_low_fee(
189 &self,
190 ) -> Result<Box<dyn Iterator<Item = (u64, [u8; 32])> + '_>>;
191
192 fn mempool_txs_ids(&self) -> Result<Vec<[u8; 32]>>;
194
195 fn mempool_expired_txs(&self, timestamp: u64) -> Result<Vec<[u8; 32]>>;
197
198 fn mempool_txs_count(&self) -> usize;
200}
201
202pub trait Metadata {
203 fn op_write<T: AsRef<[u8]>>(&mut self, key: &[u8], value: T) -> Result<()>;
205
206 fn op_read(&self, key: &[u8]) -> Result<Option<Vec<u8>>>;
208}
209
210pub trait Persist:
211 Ledger + ConsensusStorage + Mempool + Metadata + core::fmt::Debug
212{
213 fn clear_database(&mut self) -> Result<()>;
216 fn commit(self) -> Result<()>;
217 fn rollback(self) -> Result<()>;
218}
219
220pub fn into_array<const N: usize>(value: &[u8]) -> [u8; N] {
221 let mut res = [0u8; N];
222 res.copy_from_slice(&value[0..N]);
223 res
224}
225
226#[derive(Serialize, Deserialize, Clone, Debug)]
227pub struct DatabaseOptions {
228 pub blocks_cf_max_write_buffer_size: usize,
231
232 pub blocks_cf_disable_block_cache: bool,
238
239 pub mempool_cf_max_write_buffer_size: usize,
241
242 pub enable_debug: bool,
244
245 pub create_if_missing: bool,
247}
248
249impl Default for DatabaseOptions {
250 fn default() -> Self {
251 Self {
252 blocks_cf_max_write_buffer_size: 1024 * 1024, mempool_cf_max_write_buffer_size: 10 * 1024 * 1024, blocks_cf_disable_block_cache: true,
255 enable_debug: false,
256 create_if_missing: true,
257 }
258 }
259}