darkfi/blockchain/
block_store.rs

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