darkfi/blockchain/
block_store.rs

1/* This file is part of DarkFi (https://dark.fi)
2 *
3 * Copyright (C) 2020-2025 Dyne.org foundation
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Affero General Public License as
7 * published by the Free Software Foundation, either version 3 of the
8 * License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU Affero General Public License for more details.
14 *
15 * You should have received a copy of the GNU Affero General Public License
16 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 */
18
19use darkfi_sdk::{
20    crypto::{
21        schnorr::{SchnorrSecret, Signature},
22        MerkleTree, SecretKey,
23    },
24    pasta::{group::ff::FromUniformBytes, pallas},
25    tx::TransactionHash,
26};
27#[cfg(feature = "async-serial")]
28use darkfi_serial::async_trait;
29use darkfi_serial::{deserialize, serialize, SerialDecodable, SerialEncodable};
30use num_bigint::BigUint;
31use sled_overlay::{
32    serial::{parse_record, parse_u32_key_record},
33    sled, SledDbOverlayStateDiff,
34};
35
36use crate::{tx::Transaction, util::time::Timestamp, Error, Result};
37
38use super::{Header, HeaderHash, SledDbOverlayPtr};
39
40/// This struct represents a tuple of the form (`header`, `txs`, `signature`).
41///
42/// The header and transactions are stored as hashes, serving as pointers to the actual data
43/// in the sled database.
44/// NOTE: This struct fields are considered final, as it represents a blockchain block.
45#[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
46pub struct Block {
47    /// Block header
48    pub header: HeaderHash,
49    /// Trasaction hashes
50    pub txs: Vec<TransactionHash>,
51    /// Block producer signature
52    pub signature: Signature,
53}
54
55impl Block {
56    pub fn new(header: HeaderHash, txs: Vec<TransactionHash>, signature: Signature) -> Self {
57        Self { header, txs, signature }
58    }
59
60    /// A block's hash is the same as the hash of its header
61    pub fn hash(&self) -> HeaderHash {
62        self.header
63    }
64
65    /// Generate a `Block` from a `BlockInfo`
66    pub fn from_block_info(block_info: &BlockInfo) -> Self {
67        let header = block_info.header.hash();
68        let txs = block_info.txs.iter().map(|tx| tx.hash()).collect();
69        let signature = block_info.signature;
70        Self { header, txs, signature }
71    }
72}
73
74/// Structure representing full block data.
75///
76/// It acts as a wrapper struct over `Block`, enabling us
77/// to include more information that might be used in different
78/// block versions, without affecting the original struct.
79#[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
80pub struct BlockInfo {
81    /// Block header data
82    pub header: Header,
83    /// Transactions payload
84    pub txs: Vec<Transaction>,
85    /// Block producer signature
86    pub signature: Signature,
87}
88
89impl Default for BlockInfo {
90    /// Represents the genesis block on current timestamp
91    fn default() -> Self {
92        Self {
93            header: Header::default(),
94            txs: vec![Transaction::default()],
95            signature: Signature::dummy(),
96        }
97    }
98}
99
100impl BlockInfo {
101    pub fn new(header: Header, txs: Vec<Transaction>, signature: Signature) -> Self {
102        Self { header, txs, signature }
103    }
104
105    /// Generate an empty block for provided Header.
106    /// Transactions and the producer signature must be added after.
107    pub fn new_empty(header: Header) -> Self {
108        let txs = vec![];
109        let signature = Signature::dummy();
110        Self { header, txs, signature }
111    }
112
113    /// A block's hash is the same as the hash of its header
114    pub fn hash(&self) -> HeaderHash {
115        self.header.hash()
116    }
117
118    /// Append a transaction to the block. Also adds it to the Merkle tree.
119    /// Note: when we append a tx we rebuild the whole tree, so its preferable
120    /// to append them all at once using `append_txs`.
121    pub fn append_tx(&mut self, tx: Transaction) {
122        let mut tree = MerkleTree::new(1);
123        // Append existing block transactions to the tree
124        for block_tx in &self.txs {
125            append_tx_to_merkle_tree(&mut tree, block_tx);
126        }
127        // Append the new transaction
128        append_tx_to_merkle_tree(&mut tree, &tx);
129        self.txs.push(tx);
130        // Grab the tree root and store it in the header
131        self.header.transactions_root = tree.root(0).unwrap();
132    }
133
134    /// Append a vector of transactions to the block. Also adds them to the
135    /// Merkle tree.
136    /// Note: when we append txs we rebuild the whole tree, so its preferable
137    /// to append them all at once.
138    pub fn append_txs(&mut self, txs: Vec<Transaction>) {
139        let mut tree = MerkleTree::new(1);
140        // Append existing block transactions to the tree
141        for block_tx in &self.txs {
142            append_tx_to_merkle_tree(&mut tree, block_tx);
143        }
144        // Append the new transactions
145        for tx in txs {
146            append_tx_to_merkle_tree(&mut tree, &tx);
147            self.txs.push(tx);
148        }
149        // Grab the tree root and store it in the header
150        self.header.transactions_root = tree.root(0).unwrap();
151    }
152
153    /// Sign block header using provided secret key
154    pub fn sign(&mut self, secret_key: &SecretKey) {
155        self.signature = secret_key.sign(self.hash().inner());
156    }
157}
158
159/// Auxiliary structure used to keep track of blocks order.
160#[derive(Debug, SerialEncodable, SerialDecodable)]
161pub struct BlockOrder {
162    /// Block height
163    pub height: u32,
164    /// Block header hash of that height
165    pub block: HeaderHash,
166}
167
168/// Auxiliary structure used to keep track of block ranking information.
169///
170/// Note: we only need height cumulative ranks, but we also keep its actual
171/// ranks, so we can verify the sequence and/or know specific block height
172/// ranks, if ever needed.
173#[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
174pub struct BlockRanks {
175    /// Block target rank
176    pub target_rank: BigUint,
177    /// Height cumulative targets rank
178    pub targets_rank: BigUint,
179    /// Block hash rank
180    pub hash_rank: BigUint,
181    /// Height cumulative hashes rank
182    pub hashes_rank: BigUint,
183}
184
185impl BlockRanks {
186    pub fn new(
187        target_rank: BigUint,
188        targets_rank: BigUint,
189        hash_rank: BigUint,
190        hashes_rank: BigUint,
191    ) -> Self {
192        Self { target_rank, targets_rank, hash_rank, hashes_rank }
193    }
194}
195
196/// Auxiliary structure used to keep track of block PoW difficulty information.
197///
198/// Note: we only need height cumulative difficulty, but we also keep its actual
199/// difficulty, so we can verify the sequence and/or know specific block height
200/// difficulty, if ever needed.
201#[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
202pub struct BlockDifficulty {
203    /// Block height number
204    pub height: u32,
205    /// Block creation timestamp
206    pub timestamp: Timestamp,
207    /// Height difficulty
208    pub difficulty: BigUint,
209    /// Height cumulative difficulty (total + height difficulty)
210    pub cumulative_difficulty: BigUint,
211    /// Block ranks
212    pub ranks: BlockRanks,
213}
214
215impl BlockDifficulty {
216    pub fn new(
217        height: u32,
218        timestamp: Timestamp,
219        difficulty: BigUint,
220        cumulative_difficulty: BigUint,
221        ranks: BlockRanks,
222    ) -> Self {
223        Self { height, timestamp, difficulty, cumulative_difficulty, ranks }
224    }
225
226    /// Represents the genesis block difficulty
227    pub fn genesis(timestamp: Timestamp) -> Self {
228        let ranks = BlockRanks::new(
229            BigUint::from(0u64),
230            BigUint::from(0u64),
231            BigUint::from(0u64),
232            BigUint::from(0u64),
233        );
234        BlockDifficulty::new(0u32, timestamp, BigUint::from(0u64), BigUint::from(0u64), ranks)
235    }
236}
237
238pub const SLED_BLOCK_TREE: &[u8] = b"_blocks";
239pub const SLED_BLOCK_ORDER_TREE: &[u8] = b"_block_order";
240pub const SLED_BLOCK_DIFFICULTY_TREE: &[u8] = b"_block_difficulty";
241pub const SLED_BLOCK_STATE_INVERSE_DIFF_TREE: &[u8] = b"_block_state_inverse_diff";
242
243/// The `BlockStore` is a structure representing all `sled` trees related
244/// to storing the blockchain's blocks information.
245#[derive(Clone)]
246pub struct BlockStore {
247    /// Main `sled` tree, storing all the blockchain's blocks, where the
248    /// key is the blocks' hash, and value is the serialized block.
249    pub main: sled::Tree,
250    /// The `sled` tree storing the order of the blockchain's blocks,
251    /// where the key is the height number, and the value is the blocks'
252    /// hash.
253    pub order: sled::Tree,
254    /// The `sled` tree storing the difficulty information of the
255    /// blockchain's blocks, where the key is the block height number,
256    /// and the value is the blocks' hash.
257    pub difficulty: sled::Tree,
258    /// The `sled` tree storing each blocks' full database state inverse
259    /// changes, where the key is the block height number, and the value
260    /// is the serialized database inverse diff.
261    pub state_inverse_diff: sled::Tree,
262}
263
264impl BlockStore {
265    /// Opens a new or existing `BlockStore` on the given sled database.
266    pub fn new(db: &sled::Db) -> Result<Self> {
267        let main = db.open_tree(SLED_BLOCK_TREE)?;
268        let order = db.open_tree(SLED_BLOCK_ORDER_TREE)?;
269        let difficulty = db.open_tree(SLED_BLOCK_DIFFICULTY_TREE)?;
270        let state_inverse_diff = db.open_tree(SLED_BLOCK_STATE_INVERSE_DIFF_TREE)?;
271        Ok(Self { main, order, difficulty, state_inverse_diff })
272    }
273
274    /// Insert a slice of [`Block`] into the store's main tree.
275    pub fn insert(&self, blocks: &[Block]) -> Result<Vec<HeaderHash>> {
276        let (batch, ret) = self.insert_batch(blocks);
277        self.main.apply_batch(batch)?;
278        Ok(ret)
279    }
280
281    /// Insert a slice of `u32` and block hashes into the store's
282    /// order tree.
283    pub fn insert_order(&self, heights: &[u32], hashes: &[HeaderHash]) -> Result<()> {
284        let batch = self.insert_batch_order(heights, hashes);
285        self.order.apply_batch(batch)?;
286        Ok(())
287    }
288
289    /// Insert a slice of [`BlockDifficulty`] into the store's
290    /// difficulty tree.
291    pub fn insert_difficulty(&self, block_difficulties: &[BlockDifficulty]) -> Result<()> {
292        let batch = self.insert_batch_difficulty(block_difficulties);
293        self.difficulty.apply_batch(batch)?;
294        Ok(())
295    }
296
297    /// Insert a slice of `u32` and block inverse diffs into the
298    /// store's database inverse diffs tree.
299    pub fn insert_state_inverse_diff(
300        &self,
301        heights: &[u32],
302        diffs: &[SledDbOverlayStateDiff],
303    ) -> Result<()> {
304        let batch = self.insert_batch_state_inverse_diff(heights, diffs);
305        self.state_inverse_diff.apply_batch(batch)?;
306        Ok(())
307    }
308
309    /// Generate the sled batch corresponding to an insert to the main
310    /// tree, so caller can handle the write operation.
311    /// The block's hash() function output is used as the key,
312    /// while value is the serialized [`Block`] itself.
313    /// On success, the function returns the block hashes in the same order.
314    pub fn insert_batch(&self, blocks: &[Block]) -> (sled::Batch, Vec<HeaderHash>) {
315        let mut ret = Vec::with_capacity(blocks.len());
316        let mut batch = sled::Batch::default();
317
318        for block in blocks {
319            let blockhash = block.hash();
320            batch.insert(blockhash.inner(), serialize(block));
321            ret.push(blockhash);
322        }
323
324        (batch, ret)
325    }
326
327    /// Generate the sled batch corresponding to an insert to the order
328    /// tree, so caller can handle the write operation.
329    /// The block height is used as the key, and the block hash is used as value.
330    pub fn insert_batch_order(&self, heights: &[u32], hashes: &[HeaderHash]) -> sled::Batch {
331        let mut batch = sled::Batch::default();
332
333        for (i, height) in heights.iter().enumerate() {
334            batch.insert(&height.to_be_bytes(), hashes[i].inner());
335        }
336
337        batch
338    }
339
340    /// Generate the sled batch corresponding to an insert to the difficulty
341    /// tree, so caller can handle the write operation.
342    /// The block's height number is used as the key, while value is
343    //  the serialized [`BlockDifficulty`] itself.
344    pub fn insert_batch_difficulty(&self, block_difficulties: &[BlockDifficulty]) -> sled::Batch {
345        let mut batch = sled::Batch::default();
346
347        for block_difficulty in block_difficulties {
348            batch.insert(&block_difficulty.height.to_be_bytes(), serialize(block_difficulty));
349        }
350
351        batch
352    }
353
354    /// Generate the sled batch corresponding to an insert to the database
355    /// inverse diffs tree, so caller can handle the write operation.
356    /// The block height is used as the key, and the serialized database
357    /// inverse diff is used as value.
358    pub fn insert_batch_state_inverse_diff(
359        &self,
360        heights: &[u32],
361        diffs: &[SledDbOverlayStateDiff],
362    ) -> sled::Batch {
363        let mut batch = sled::Batch::default();
364
365        for (i, height) in heights.iter().enumerate() {
366            batch.insert(&height.to_be_bytes(), serialize(&diffs[i]));
367        }
368
369        batch
370    }
371
372    /// Check if the store's main tree contains a given block hash.
373    pub fn contains(&self, blockhash: &HeaderHash) -> Result<bool> {
374        Ok(self.main.contains_key(blockhash.inner())?)
375    }
376
377    /// Check if the store's order tree contains a given height.
378    pub fn contains_order(&self, height: u32) -> Result<bool> {
379        Ok(self.order.contains_key(height.to_be_bytes())?)
380    }
381
382    /// Fetch given block hashes from the store's main tree.
383    /// The resulting vector contains `Option`, which is `Some` if the block
384    /// was found in the block store, and otherwise it is `None`, if it has not.
385    /// The second parameter is a boolean which tells the function to fail in
386    /// case at least one block was not found.
387    pub fn get(&self, block_hashes: &[HeaderHash], strict: bool) -> Result<Vec<Option<Block>>> {
388        let mut ret = Vec::with_capacity(block_hashes.len());
389
390        for hash in block_hashes {
391            if let Some(found) = self.main.get(hash.inner())? {
392                let block = deserialize(&found)?;
393                ret.push(Some(block));
394                continue
395            }
396            if strict {
397                return Err(Error::BlockNotFound(hash.as_string()))
398            }
399            ret.push(None);
400        }
401
402        Ok(ret)
403    }
404
405    /// Fetch given heights from the store's order tree.
406    /// The resulting vector contains `Option`, which is `Some` if the height
407    /// was found in the block order store, and otherwise it is `None`, if it has not.
408    /// The second parameter is a boolean which tells the function to fail in
409    /// case at least one height was not found.
410    pub fn get_order(&self, heights: &[u32], strict: bool) -> Result<Vec<Option<HeaderHash>>> {
411        let mut ret = Vec::with_capacity(heights.len());
412
413        for height in heights {
414            if let Some(found) = self.order.get(height.to_be_bytes())? {
415                let block_hash = deserialize(&found)?;
416                ret.push(Some(block_hash));
417                continue
418            }
419            if strict {
420                return Err(Error::BlockHeightNotFound(*height))
421            }
422            ret.push(None);
423        }
424
425        Ok(ret)
426    }
427
428    /// Fetch given block height numbers from the store's difficulty tree.
429    /// The resulting vector contains `Option`, which is `Some` if the block
430    /// height number was found in the block difficulties store, and otherwise
431    /// it is `None`, if it has not.
432    /// The second parameter is a boolean which tells the function to fail in
433    /// case at least one block height number was not found.
434    pub fn get_difficulty(
435        &self,
436        heights: &[u32],
437        strict: bool,
438    ) -> Result<Vec<Option<BlockDifficulty>>> {
439        let mut ret = Vec::with_capacity(heights.len());
440
441        for height in heights {
442            if let Some(found) = self.difficulty.get(height.to_be_bytes())? {
443                let block_difficulty = deserialize(&found)?;
444                ret.push(Some(block_difficulty));
445                continue
446            }
447            if strict {
448                return Err(Error::BlockDifficultyNotFound(*height))
449            }
450            ret.push(None);
451        }
452
453        Ok(ret)
454    }
455
456    /// Fetch given block height numbers from the store's state inverse
457    /// diffs tree. The resulting vector contains `Option`, which is
458    /// `Some` if the block height number was found in the block database
459    /// inverse diffs store, and otherwise it is `None`, if it has not.
460    /// The second parameter is a boolean which tells the function to fail
461    /// in case at least one block height number was not found.
462    pub fn get_state_inverse_diff(
463        &self,
464        heights: &[u32],
465        strict: bool,
466    ) -> Result<Vec<Option<SledDbOverlayStateDiff>>> {
467        let mut ret = Vec::with_capacity(heights.len());
468
469        for height in heights {
470            if let Some(found) = self.state_inverse_diff.get(height.to_be_bytes())? {
471                let state_inverse_diff = deserialize(&found)?;
472                ret.push(Some(state_inverse_diff));
473                continue
474            }
475            if strict {
476                return Err(Error::BlockStateInverseDiffNotFound(*height))
477            }
478            ret.push(None);
479        }
480
481        Ok(ret)
482    }
483
484    /// Retrieve all blocks from the store's main tree in the form of a
485    /// tuple (`hash`, `block`).
486    /// Be careful as this will try to load everything in memory.
487    pub fn get_all(&self) -> Result<Vec<(HeaderHash, Block)>> {
488        let mut blocks = vec![];
489
490        for block in self.main.iter() {
491            blocks.push(parse_record(block.unwrap())?);
492        }
493
494        Ok(blocks)
495    }
496
497    /// Retrieve complete order from the store's order tree in the form
498    /// of a vector containing (`height`, `hash`) tuples.
499    /// Be careful as this will try to load everything in memory.
500    pub fn get_all_order(&self) -> Result<Vec<(u32, HeaderHash)>> {
501        let mut order = vec![];
502
503        for record in self.order.iter() {
504            order.push(parse_u32_key_record(record.unwrap())?);
505        }
506
507        Ok(order)
508    }
509
510    /// Fetches the blocks within a specified range of height from the store's order tree
511    /// returning a collection of block heights with their associated [`HeaderHash`]s.
512    pub fn get_order_by_range(&self, start: u32, end: u32) -> Result<Vec<(u32, HeaderHash)>> {
513        if start >= end {
514            return Err(Error::DatabaseError(format!("Heights range is invalid: {start}..{end}")))
515        }
516
517        let mut blocks = vec![];
518
519        let start_key = start.to_be_bytes();
520        let end_key = end.to_be_bytes();
521
522        for block in self.order.range(start_key..=end_key) {
523            blocks.push(parse_u32_key_record(block.unwrap())?);
524        }
525
526        Ok(blocks)
527    }
528
529    /// Retrieve all block difficulties from the store's difficulty tree in
530    /// the form of a vector containing (`height`, `difficulty`) tuples.
531    /// Be careful as this will try to load everything in memory.
532    pub fn get_all_difficulty(&self) -> Result<Vec<(u32, BlockDifficulty)>> {
533        let mut block_difficulties = vec![];
534
535        for record in self.difficulty.iter() {
536            block_difficulties.push(parse_u32_key_record(record.unwrap())?);
537        }
538
539        Ok(block_difficulties)
540    }
541
542    /// Fetch n hashes before given height. In the iteration, if an order
543    /// height is not found, the iteration stops and the function returns what
544    /// it has found so far in the store's order tree.
545    pub fn get_before(&self, height: u32, n: usize) -> Result<Vec<HeaderHash>> {
546        let mut ret = vec![];
547
548        let mut key = height;
549        let mut counter = 0;
550        while counter < n {
551            let record = self.order.get_lt(key.to_be_bytes())?;
552            if record.is_none() {
553                break
554            }
555            // Since the iterator grabs in right -> left order,
556            // we deserialize found records, and push them in reverse order
557            let (height, hash) = parse_u32_key_record(record.unwrap())?;
558            key = height;
559            ret.insert(0, hash);
560            counter += 1;
561        }
562
563        Ok(ret)
564    }
565
566    /// Fetch all hashes after given height. In the iteration, if an order
567    /// height is not found, the iteration stops and the function returns what
568    /// it has found so far in the store's order tree.
569    pub fn get_all_after(&self, height: u32) -> Result<Vec<HeaderHash>> {
570        let mut ret = vec![];
571
572        let mut key = height;
573        while let Some(found) = self.order.get_gt(key.to_be_bytes())? {
574            let (height, hash) = parse_u32_key_record(found)?;
575            key = height;
576            ret.push(hash);
577        }
578
579        Ok(ret)
580    }
581
582    /// Fetch the first block hash in the order tree, based on the `Ord`
583    /// implementation for `Vec<u8>`.
584    pub fn get_first(&self) -> Result<(u32, HeaderHash)> {
585        let Some(found) = self.order.first()? else { return Err(Error::BlockHeightNotFound(0u32)) };
586        let (height, hash) = parse_u32_key_record(found)?;
587
588        Ok((height, hash))
589    }
590
591    /// Fetch the last block hash in the order tree, based on the `Ord`
592    /// implementation for `Vec<u8>`.
593    pub fn get_last(&self) -> Result<(u32, HeaderHash)> {
594        let found = self.order.last()?.unwrap();
595        let (height, hash) = parse_u32_key_record(found)?;
596
597        Ok((height, hash))
598    }
599
600    /// Fetch the last N records from order tree
601    pub fn get_last_n_orders(&self, n: usize) -> Result<Vec<(u32, HeaderHash)>> {
602        // Build an iterator to retrieve last N records
603        let records = self.order.iter().rev().take(n);
604
605        // Since the iterator grabs in right -> left order,
606        // we deserialize found records, and push them in reverse order
607        let mut last_n = vec![];
608        for record in records {
609            let record = record?;
610            let parsed_record = parse_u32_key_record(record)?;
611            last_n.insert(0, parsed_record);
612        }
613        Ok(last_n)
614    }
615
616    /// Fetch the last record in the difficulty tree, based on the `Ord`
617    /// implementation for `Vec<u8>`. If the tree is empty,
618    /// returns `None`.
619    pub fn get_last_difficulty(&self) -> Result<Option<BlockDifficulty>> {
620        let Some(found) = self.difficulty.last()? else { return Ok(None) };
621        let block_difficulty = deserialize(&found.1)?;
622        Ok(Some(block_difficulty))
623    }
624
625    /// Fetch the last N records from the store's difficulty tree, in order.
626    pub fn get_last_n_difficulties(&self, n: usize) -> Result<Vec<BlockDifficulty>> {
627        // Build an iterator to retrieve last N records
628        let records = self.difficulty.iter().rev().take(n);
629        // Since the iterator grabs in right -> left order,
630        // we deserialize found records, and push them in reverse order
631        let mut last_n = vec![];
632        for record in records {
633            last_n.insert(0, deserialize(&record?.1)?);
634        }
635
636        Ok(last_n)
637    }
638
639    /// Fetch N records before given height from the store's difficulty tree, in order.
640    /// In the iteration, if a record height is not found, the iteration stops and the
641    /// function returns what it has found so far in the store's difficulty tree.
642    pub fn get_difficulties_before(&self, height: u32, n: usize) -> Result<Vec<BlockDifficulty>> {
643        let mut ret = vec![];
644
645        let mut key = height;
646        let mut counter = 0;
647        while counter < n {
648            let record = self.difficulty.get_lt(key.to_be_bytes())?;
649            if record.is_none() {
650                break
651            }
652            // Since the iterator grabs in right -> left order,
653            // we deserialize found records, and push them in reverse order
654            let (height, difficulty) = parse_u32_key_record(record.unwrap())?;
655            key = height;
656            ret.insert(0, difficulty);
657            counter += 1;
658        }
659
660        Ok(ret)
661    }
662
663    /// Fetch all state inverse diffs after given height. In the iteration,
664    /// if a state inverse diff is not found, the iteration stops and the
665    /// function returns what it has found so far in the store's state
666    /// inverse diffs tree.
667    pub fn get_state_inverse_diffs_after(
668        &self,
669        height: u32,
670    ) -> Result<Vec<SledDbOverlayStateDiff>> {
671        let mut ret = vec![];
672
673        let mut key = height;
674        while let Some(found) = self.state_inverse_diff.get_gt(key.to_be_bytes())? {
675            let (height, state_inverse_diff) = parse_u32_key_record(found)?;
676            key = height;
677            ret.push(state_inverse_diff);
678        }
679
680        Ok(ret)
681    }
682
683    /// Retrieve store's order tree records count.
684    pub fn len(&self) -> usize {
685        self.order.len()
686    }
687
688    /// Check if store's order tree contains any records.
689    pub fn is_empty(&self) -> bool {
690        self.order.is_empty()
691    }
692}
693
694/// Overlay structure over a [`BlockStore`] instance.
695pub struct BlockStoreOverlay(SledDbOverlayPtr);
696
697impl BlockStoreOverlay {
698    pub fn new(overlay: &SledDbOverlayPtr) -> Result<Self> {
699        overlay.lock().unwrap().open_tree(SLED_BLOCK_TREE, true)?;
700        overlay.lock().unwrap().open_tree(SLED_BLOCK_ORDER_TREE, true)?;
701        overlay.lock().unwrap().open_tree(SLED_BLOCK_DIFFICULTY_TREE, true)?;
702        overlay.lock().unwrap().open_tree(SLED_BLOCK_STATE_INVERSE_DIFF_TREE, true)?;
703        Ok(Self(overlay.clone()))
704    }
705
706    /// Insert a slice of [`Block`] into the overlay's main tree.
707    /// The block's hash() function output is used as the key,
708    /// while value is the serialized [`Block`] itself.
709    /// On success, the function returns the block hashes in the same order.
710    pub fn insert(&self, blocks: &[Block]) -> Result<Vec<HeaderHash>> {
711        let mut ret = Vec::with_capacity(blocks.len());
712        let mut lock = self.0.lock().unwrap();
713
714        for block in blocks {
715            let blockhash = block.hash();
716            lock.insert(SLED_BLOCK_TREE, blockhash.inner(), &serialize(block))?;
717            ret.push(blockhash);
718        }
719
720        Ok(ret)
721    }
722
723    /// Insert a slice of `u32` and block hashes into overlay's order tree.
724    /// The block height is used as the key, and the blockhash is used as value.
725    pub fn insert_order(&self, heights: &[u32], hashes: &[HeaderHash]) -> Result<()> {
726        if heights.len() != hashes.len() {
727            return Err(Error::InvalidInputLengths)
728        }
729
730        let mut lock = self.0.lock().unwrap();
731
732        for (i, height) in heights.iter().enumerate() {
733            lock.insert(SLED_BLOCK_ORDER_TREE, &height.to_be_bytes(), hashes[i].inner())?;
734        }
735
736        Ok(())
737    }
738
739    /// Insert a slice of [`BlockDifficulty`] into the overlay's difficulty tree.
740    pub fn insert_difficulty(&self, block_difficulties: &[BlockDifficulty]) -> Result<()> {
741        let mut lock = self.0.lock().unwrap();
742
743        for block_difficulty in block_difficulties {
744            lock.insert(
745                SLED_BLOCK_DIFFICULTY_TREE,
746                &block_difficulty.height.to_be_bytes(),
747                &serialize(block_difficulty),
748            )?;
749        }
750
751        Ok(())
752    }
753
754    /// Fetch given block hashes from the overlay's main tree.
755    /// The resulting vector contains `Option`, which is `Some` if the block
756    /// was found in the overlay, and otherwise it is `None`, if it has not.
757    /// The second parameter is a boolean which tells the function to fail in
758    /// case at least one block was not found.
759    pub fn get(&self, block_hashes: &[HeaderHash], strict: bool) -> Result<Vec<Option<Block>>> {
760        let mut ret = Vec::with_capacity(block_hashes.len());
761        let lock = self.0.lock().unwrap();
762
763        for hash in block_hashes {
764            if let Some(found) = lock.get(SLED_BLOCK_TREE, hash.inner())? {
765                let block = deserialize(&found)?;
766                ret.push(Some(block));
767                continue
768            }
769            if strict {
770                return Err(Error::BlockNotFound(hash.as_string()))
771            }
772            ret.push(None);
773        }
774
775        Ok(ret)
776    }
777
778    /// Fetch given heights from the overlay's order tree.
779    /// The resulting vector contains `Option`, which is `Some` if the height
780    /// was found in the overlay, and otherwise it is `None`, if it has not.
781    /// The second parameter is a boolean which tells the function to fail in
782    /// case at least one height was not found.
783    pub fn get_order(&self, heights: &[u32], strict: bool) -> Result<Vec<Option<HeaderHash>>> {
784        let mut ret = Vec::with_capacity(heights.len());
785        let lock = self.0.lock().unwrap();
786
787        for height in heights {
788            if let Some(found) = lock.get(SLED_BLOCK_ORDER_TREE, &height.to_be_bytes())? {
789                let block_hash = deserialize(&found)?;
790                ret.push(Some(block_hash));
791                continue
792            }
793            if strict {
794                return Err(Error::BlockHeightNotFound(*height))
795            }
796            ret.push(None);
797        }
798
799        Ok(ret)
800    }
801
802    /// Fetch the last block hash in the overlay's order tree, based on the `Ord`
803    /// implementation for `Vec<u8>`.
804    pub fn get_last(&self) -> Result<(u32, HeaderHash)> {
805        let found = match self.0.lock().unwrap().last(SLED_BLOCK_ORDER_TREE)? {
806            Some(b) => b,
807            None => return Err(Error::BlockHeightNotFound(0u32)),
808        };
809        let (height, hash) = parse_u32_key_record(found)?;
810
811        Ok((height, hash))
812    }
813
814    /// Check if overlay's order tree contains any records.
815    pub fn is_empty(&self) -> Result<bool> {
816        Ok(self.0.lock().unwrap().is_empty(SLED_BLOCK_ORDER_TREE)?)
817    }
818}
819
820/// Auxiliary function to append a transaction to a Merkle tree.
821pub fn append_tx_to_merkle_tree(tree: &mut MerkleTree, tx: &Transaction) {
822    let mut buf = [0u8; 64];
823    buf[..32].copy_from_slice(tx.hash().inner());
824    let leaf = pallas::Base::from_uniform_bytes(&buf);
825    tree.append(leaf.into());
826}