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 {
60 fn store_block(
63 &mut self,
64 header: &Header,
65 txs: &[SpentTransaction],
66 faults: &[Fault],
67 label: Label,
68 ) -> Result<usize>;
69
70 fn delete_block(&mut self, b: &Block) -> Result<()>;
71 fn block_header(&self, hash: &[u8]) -> Result<Option<Header>>;
72
73 fn light_block(&self, hash: &[u8]) -> Result<Option<LightBlock>>;
74
75 fn block(&self, hash: &[u8]) -> Result<Option<Block>>;
76 fn block_hash_by_height(&self, height: u64) -> Result<Option<[u8; 32]>>;
77 fn block_by_height(&self, height: u64) -> Result<Option<Block>>;
78
79 fn store_blob_data(&self, hash: &[u8; 32], data: Vec<u8>) -> Result<()>;
80 fn blob_data_by_hash(&self, hash: &[u8; 32]) -> Result<Option<Vec<u8>>>;
81 fn store_blobs_height(
82 &self,
83 block_height: u64,
84 blob_hashes: &[[u8; 32]],
85 ) -> Result<()>;
86 fn blobs_by_height(
87 &self,
88 block_height: u64,
89 ) -> Result<Option<Vec<[u8; 32]>>>;
90 fn delete_blobs_by_height(&self, block_height: u64) -> Result<()>;
91
92 fn block_exists(&self, hash: &[u8]) -> Result<bool>;
93
94 fn ledger_tx(&self, tx_id: &[u8]) -> Result<Option<SpentTransaction>>;
95 fn ledger_txs(
96 &self,
97 tx_ids: Vec<&[u8; 32]>,
98 ) -> Result<Vec<SpentTransaction>>;
99
100 fn ledger_tx_exists(&self, tx_id: &[u8]) -> Result<bool>;
101
102 fn block_label_by_height(
103 &self,
104 height: u64,
105 ) -> Result<Option<([u8; 32], Label)>>;
106
107 fn store_block_label(
108 &mut self,
109 height: u64,
110 hash: &[u8; 32],
111 label: Label,
112 ) -> Result<()>;
113
114 fn faults_by_block(&self, start_height: u64) -> Result<Vec<Fault>>;
115 fn faults(&self, faults_ids: &[[u8; 32]]) -> Result<Vec<Fault>>;
116}
117
118pub trait ConsensusStorage {
119 fn store_candidate(&mut self, cm: Block) -> Result<()>;
121 fn candidate(&self, hash: &[u8]) -> Result<Option<Block>>;
122
123 fn candidate_by_iteration(
125 &self,
126 ch: &ConsensusHeader,
127 ) -> Result<Option<Block>>;
128
129 fn clear_candidates(&mut self) -> Result<()>;
130
131 fn delete_candidate<F>(&mut self, closure: F) -> Result<()>
132 where
133 F: FnOnce(u64) -> bool + std::marker::Copy;
134
135 fn count_candidates(&self) -> usize;
136
137 fn store_validation_result(
139 &mut self,
140 ch: &ConsensusHeader,
141 vr: &payload::ValidationResult,
142 ) -> Result<()>;
143
144 fn validation_result(
145 &self,
146 ch: &ConsensusHeader,
147 ) -> Result<Option<payload::ValidationResult>>;
148
149 fn clear_validation_results(&mut self) -> Result<()>;
150
151 fn delete_validation_results<F>(&mut self, closure: F) -> Result<()>
152 where
153 F: FnOnce([u8; 32]) -> bool + std::marker::Copy;
154
155 fn count_validation_results(&self) -> usize;
156}
157
158pub trait Mempool {
159 fn store_mempool_tx(
161 &mut self,
162 tx: &Transaction,
163 timestamp: u64,
164 ) -> Result<()>;
165
166 fn mempool_tx(&self, tx_id: [u8; 32]) -> Result<Option<Transaction>>;
168
169 fn mempool_tx_exists(&self, tx_id: [u8; 32]) -> Result<bool>;
171
172 fn delete_mempool_tx(
178 &mut self,
179 tx_id: [u8; 32],
180 cascade: bool,
181 ) -> Result<Vec<[u8; 32]>>;
182
183 fn mempool_txs_by_spendable_ids(
185 &self,
186 n: &[SpendingId],
187 ) -> HashSet<[u8; 32]>;
188
189 fn mempool_txs_sorted_by_fee(
191 &self,
192 ) -> Box<dyn Iterator<Item = Transaction> + '_>;
193
194 fn mempool_txs_ids_sorted_by_fee(
196 &self,
197 ) -> Box<dyn Iterator<Item = (u64, [u8; 32])> + '_>;
198
199 fn mempool_txs_ids_sorted_by_low_fee(
201 &self,
202 ) -> Box<dyn Iterator<Item = (u64, [u8; 32])> + '_>;
203
204 fn mempool_txs_ids(&self) -> Result<Vec<[u8; 32]>>;
206
207 fn mempool_expired_txs(&self, timestamp: u64) -> Result<Vec<[u8; 32]>>;
209
210 fn mempool_txs_count(&self) -> usize;
212}
213
214pub trait Metadata {
215 fn op_write<T: AsRef<[u8]>>(&mut self, key: &[u8], value: T) -> Result<()>;
217
218 fn op_read(&self, key: &[u8]) -> Result<Option<Vec<u8>>>;
220}
221
222pub trait Persist:
223 Ledger + ConsensusStorage + Mempool + Metadata + core::fmt::Debug
224{
225 fn clear_database(&mut self) -> Result<()>;
228 fn commit(self) -> Result<()>;
229 fn rollback(self) -> Result<()>;
230}
231
232pub fn into_array<const N: usize>(value: &[u8]) -> [u8; N] {
233 let mut res = [0u8; N];
234 res.copy_from_slice(&value[0..N]);
235 res
236}
237
238#[derive(Serialize, Deserialize, Clone, Debug)]
239pub struct DatabaseOptions {
240 pub blocks_cf_max_write_buffer_size: usize,
243
244 pub blocks_cf_disable_block_cache: bool,
250
251 pub mempool_cf_max_write_buffer_size: usize,
253
254 pub enable_debug: bool,
256
257 pub create_if_missing: bool,
259}
260
261impl Default for DatabaseOptions {
262 fn default() -> Self {
263 Self {
264 blocks_cf_max_write_buffer_size: 1024 * 1024, mempool_cf_max_write_buffer_size: 10 * 1024 * 1024, blocks_cf_disable_block_cache: true,
267 enable_debug: false,
268 create_if_missing: true,
269 }
270 }
271}