From f79bd2de18c82f6f16eeea5d45eb5d1d6fdafa84 Mon Sep 17 00:00:00 2001 From: skoupidi Date: Thu, 1 Feb 2024 19:18:42 +0200 Subject: [PATCH] sdk, blockchain, validator: removed slot stuff --- bin/darkfid/src/rpc_blockchain.rs | 2 +- bin/darkfid/src/tests/harness.rs | 7 +- bin/darkfid/src/tests/mod.rs | 12 +- src/blockchain/block_store.rs | 22 +- src/blockchain/header_store.rs | 2 +- src/blockchain/mod.rs | 137 ++---------- src/blockchain/slot_store.rs | 353 ------------------------------ src/sdk/src/blockchain.rs | 106 --------- src/validator/consensus.rs | 2 +- src/validator/mod.rs | 11 +- 10 files changed, 32 insertions(+), 622 deletions(-) delete mode 100644 src/blockchain/slot_store.rs diff --git a/bin/darkfid/src/rpc_blockchain.rs b/bin/darkfid/src/rpc_blockchain.rs index b812f2d47..7603b1cce 100644 --- a/bin/darkfid/src/rpc_blockchain.rs +++ b/bin/darkfid/src/rpc_blockchain.rs @@ -59,7 +59,7 @@ impl Darkfid { Err(_) => return JsonError::new(ParseError, None, id).into(), }; - let blocks = match self.validator.blockchain.get_blocks_by_slot(&[slot]) { + let blocks = match self.validator.blockchain.get_blocks_by_heights(&[slot]) { Ok(v) => v, Err(e) => { error!(target: "darkfid::rpc::blockchain_get_slot", "Failed fetching block by slot: {}", e); diff --git a/bin/darkfid/src/tests/harness.rs b/bin/darkfid/src/tests/harness.rs index 78a40fb42..eb01290ed 100644 --- a/bin/darkfid/src/tests/harness.rs +++ b/bin/darkfid/src/tests/harness.rs @@ -69,7 +69,6 @@ impl Harness { // Append genesis transactions and calculate their total genesis_block.txs.push(genesis_mint_tx); let genesis_txs_total = genesis_txs_total(&genesis_block.txs).await?; - genesis_block.slots[0].total_tokens = genesis_txs_total; // Generate validators configuration // NOTE: we are not using consensus constants here so we @@ -129,7 +128,7 @@ impl Harness { Ok(Self { config, vks, validator_config, alice, bob }) } - pub async fn validate_chains(&self, total_blocks: usize, total_slots: usize) -> Result<()> { + pub async fn validate_chains(&self, total_blocks: usize) -> Result<()> { let alice = &self.alice.validator; let bob = &self.bob.validator; @@ -151,10 +150,6 @@ impl Harness { assert_eq!(alice_blockchain_len, bob.blockchain.len()); assert_eq!(alice_blockchain_len, total_blocks); - let alice_slots_len = alice.blockchain.slots.len(); - assert_eq!(alice_slots_len, bob.blockchain.slots.len()); - assert_eq!(alice_slots_len, total_slots); - Ok(()) } diff --git a/bin/darkfid/src/tests/mod.rs b/bin/darkfid/src/tests/mod.rs index 3e05bb5be..7ce76edee 100644 --- a/bin/darkfid/src/tests/mod.rs +++ b/bin/darkfid/src/tests/mod.rs @@ -28,7 +28,7 @@ use harness::{generate_node, Harness, HarnessConfig}; mod forks; -async fn sync_pos_blocks_real(ex: Arc>) -> Result<()> { +async fn sync_blocks_real(ex: Arc>) -> Result<()> { init_logger(); // Initialize harness in testing mode @@ -49,14 +49,14 @@ async fn sync_pos_blocks_real(ex: Arc>) -> Result<()> { // Generate next block //let block1 = th.generate_next_block(&previous).await?; - // Generate next block, with 4 empty slots inbetween + // Generate next block //let block2 = th.generate_next_block(&block1).await?; // Add it to nodes //th.add_blocks(&vec![block1, block2]).await?; // Validate chains - th.validate_chains(1, 1).await?; + th.validate_chains(1).await?; // We are going to create a third node and try to sync from the previous two let mut sync_settings = @@ -74,22 +74,20 @@ async fn sync_pos_blocks_real(ex: Arc>) -> Result<()> { let charlie = &charlie.validator; charlie.validate_blockchain(vec![], pow_target, pow_fixed_difficulty).await?; assert_eq!(alice.blockchain.len(), charlie.blockchain.len()); - assert_eq!(alice.blockchain.slots.len(), charlie.blockchain.slots.len()); // Thanks for reading Ok(()) } #[test] -#[ignore] -fn sync_pos_blocks() -> Result<()> { +fn sync_blocks() -> Result<()> { let ex = Arc::new(Executor::new()); let (signal, shutdown) = smol::channel::unbounded::<()>(); easy_parallel::Parallel::new().each(0..4, |_| smol::block_on(ex.run(shutdown.recv()))).finish( || { smol::block_on(async { - sync_pos_blocks_real(ex.clone()).await.unwrap(); + sync_blocks_real(ex.clone()).await.unwrap(); drop(signal); }) }, diff --git a/src/blockchain/block_store.rs b/src/blockchain/block_store.rs index cb155b0dc..49eaa85a4 100644 --- a/src/blockchain/block_store.rs +++ b/src/blockchain/block_store.rs @@ -17,7 +17,6 @@ */ use darkfi_sdk::{ - blockchain::Slot, crypto::{ schnorr::{SchnorrSecret, Signature}, SecretKey, @@ -80,8 +79,6 @@ pub struct BlockInfo { pub txs: Vec, /// Block producer signature pub signature: Signature, - /// Slots payload - pub slots: Vec, } impl Default for BlockInfo { @@ -91,28 +88,21 @@ impl Default for BlockInfo { header: Header::default(), txs: vec![Transaction::default()], signature: Signature::dummy(), - slots: vec![Slot::default()], } } } impl BlockInfo { - pub fn new( - header: Header, - txs: Vec, - signature: Signature, - slots: Vec, - ) -> Self { - Self { header, txs, signature, slots } + pub fn new(header: Header, txs: Vec, signature: Signature) -> Self { + Self { header, txs, signature } } - /// Generate an empty block for provided Header - /// and slots vector. Transactions and the producer - /// signature must be added after. - pub fn new_empty(header: Header, slots: Vec) -> Self { + /// Generate an empty block for provided Header. + /// Transactions and the producer signature must be added after. + pub fn new_empty(header: Header) -> Self { let txs = vec![]; let signature = Signature::dummy(); - Self { header, txs, signature, slots } + Self { header, txs, signature } } /// A block's hash is the same as the hash of its header diff --git a/src/blockchain/header_store.rs b/src/blockchain/header_store.rs index 0d3ae2a59..be36a2a41 100644 --- a/src/blockchain/header_store.rs +++ b/src/blockchain/header_store.rs @@ -39,7 +39,7 @@ pub struct Header { pub previous: blake3::Hash, /// Epoch number pub epoch: u64, - /// Block/Slot height + /// Block height pub height: u64, /// Block creation timestamp pub timestamp: Timestamp, diff --git a/src/blockchain/mod.rs b/src/blockchain/mod.rs index e8adc26ff..8057183a8 100644 --- a/src/blockchain/mod.rs +++ b/src/blockchain/mod.rs @@ -21,7 +21,6 @@ use std::sync::{Arc, Mutex}; use log::debug; use sled::Transactional; -use darkfi_sdk::blockchain::Slot; use darkfi_serial::{deserialize, serialize, Decodable}; use crate::{tx::Transaction, Error, Result}; @@ -37,10 +36,6 @@ pub use block_store::{ pub mod header_store; pub use header_store::{Header, HeaderStore, HeaderStoreOverlay}; -/// Slots storage implementation -pub mod slot_store; -pub use slot_store::{BlocksSlotsStore, BlocksSlotsStoreOverlay, SlotStore, SlotStoreOverlay}; - /// Transactions related storage implementations pub mod tx_store; pub use tx_store::{PendingTxOrderStore, PendingTxStore, TxStore, TxStoreOverlay}; @@ -62,10 +57,6 @@ pub struct Blockchain { pub blocks: BlockStore, /// Block order sled tree pub order: BlockOrderStore, - /// Slot sled tree - pub slots: SlotStore, - /// Blocks Slots sled tree - pub blocks_slots: BlocksSlotsStore, /// Block height difficulties sled tree, pub difficulties: BlockDifficultyStore, /// Transactions sled tree @@ -86,8 +77,6 @@ impl Blockchain { let headers = HeaderStore::new(db)?; let blocks = BlockStore::new(db)?; let order = BlockOrderStore::new(db)?; - let slots = SlotStore::new(db)?; - let blocks_slots = BlocksSlotsStore::new(db)?; let difficulties = BlockDifficultyStore::new(db)?; let transactions = TxStore::new(db)?; let pending_txs = PendingTxStore::new(db)?; @@ -100,8 +89,6 @@ impl Blockchain { headers, blocks, order, - slots, - blocks_slots, difficulties, transactions, pending_txs, @@ -144,17 +131,6 @@ impl Blockchain { trees.push(self.order.0.clone()); batches.push(blocks_order_batch); - // Store block slots uids vector - let slots = block.slots.iter().map(|x| x.id).collect(); - let blocks_slots_bactch = self.blocks_slots.insert_batch(&block_hash_vec, &[&slots])?; - trees.push(self.blocks_slots.0.clone()); - batches.push(blocks_slots_bactch); - - // Store block slots - let slots_batch = self.slots.insert_batch(&block.slots)?; - trees.push(self.slots.0.clone()); - batches.push(slots_batch); - // Perform an atomic transaction over the trees and apply the batches. self.atomic_write(&trees, &batches)?; @@ -175,21 +151,6 @@ impl Blockchain { return Ok(false) } - // Check if we have block slots uids vector - let slots = match self.blocks_slots.get(&[blockhash], true) { - Ok(v) => v[0].clone().unwrap(), - Err(_) => return Ok(false), - }; - let provided_block_slots: Vec = block.slots.iter().map(|x| x.id).collect(); - if slots != provided_block_slots { - return Ok(false) - } - - // Check if we have all slots - if self.slots.get(&slots, true).is_err() { - return Ok(false) - } - // Check provided info produces the same hash Ok(blockhash == block.hash()?) } @@ -215,22 +176,17 @@ impl Blockchain { let txs = self.transactions.get(&block.txs, true)?; let txs = txs.iter().map(|x| x.clone().unwrap()).collect(); - let slots = self.blocks_slots.get(&[block.hash()], true)?; - let slots = slots[0].clone().unwrap(); - let slots = self.slots.get(&slots, true)?; - let block_slots = slots.iter().map(|x| x.clone().unwrap()).collect(); - - let info = BlockInfo::new(header, txs, block.signature, block_slots); + let info = BlockInfo::new(header, txs, block.signature); ret.push(info); } Ok(ret) } - /// Retrieve [`BlockInfo`]s by given slots. Does not fail if any of them are not found. - pub fn get_blocks_by_slot(&self, slots: &[u64]) -> Result> { - debug!(target: "blockchain", "get_blocks_by_slot(): {:?}", slots); - let blockhashes = self.order.get(slots, false)?; + /// Retrieve [`BlockInfo`]s by given heights. Does not fail if any of them are not found. + pub fn get_blocks_by_heights(&self, heights: &[u64]) -> Result> { + debug!(target: "blockchain", "get_blocks_by_heights(): {:?}", heights); + let blockhashes = self.order.get(heights, false)?; let mut hashes = vec![]; for i in blockhashes.into_iter().flatten() { @@ -240,10 +196,10 @@ impl Blockchain { self.get_blocks_by_hash(&hashes) } - /// Retrieve n blocks after given start slot. - pub fn get_blocks_after(&self, slot: u64, n: u64) -> Result> { - debug!(target: "blockchain", "get_blocks_after(): {} -> {}", slot, n); - let hashes = self.order.get_after(slot, n)?; + /// Retrieve n blocks after given start block height. + pub fn get_blocks_after(&self, height: u64, n: u64) -> Result> { + debug!(target: "blockchain", "get_blocks_after(): {} -> {}", height, n); + let hashes = self.order.get_after(height, n)?; self.get_blocks_by_hash(&hashes) } @@ -262,12 +218,12 @@ impl Blockchain { self.order.is_empty() } - /// Retrieve genesis (first) block slot and hash. + /// Retrieve genesis (first) block height and hash. pub fn genesis(&self) -> Result<(u64, blake3::Hash)> { self.order.get_first() } - /// Retrieve the last block slot and hash. + /// Retrieve the last block height and hash. pub fn last(&self) -> Result<(u64, blake3::Hash)> { self.order.get_last() } @@ -278,31 +234,9 @@ impl Blockchain { Ok(self.get_blocks_by_hash(&[hash])?[0].clone()) } - /// Retrieve the last slot. - pub fn last_slot(&self) -> Result { - self.slots.get_last() - } - - /// Retrieve n slots after given start slot. - pub fn get_slots_after(&self, slot: u64, n: u64) -> Result> { - debug!(target: "blockchain", "get_slots_after(): {} -> {}", slot, n); - self.slots.get_after(slot, n) - } - - /// Retrieve [`Slot`]s by given ids. Does not fail if any of them are not found. - pub fn get_slots_by_id(&self, ids: &[u64]) -> Result>> { - debug!(target: "blockchain", "get_slots_by_id(): {:?}", ids); - self.slots.get(ids, true) - } - - /// Check if the given [`Slot`] is in the database and all trees. - pub fn has_slot(&self, slot: &Slot) -> Result { - Ok(self.slots.get(&[slot.id], true).is_ok()) - } - - /// Check if block order for the given slot is in the database. - pub fn has_slot_order(&self, slot: u64) -> Result { - let vec = match self.order.get(&[slot], true) { + /// Check if block order for the given height is in the database. + pub fn has_height(&self, height: u64) -> Result { + let vec = match self.order.get(&[height], true) { Ok(v) => v, Err(_) => return Ok(false), }; @@ -410,10 +344,6 @@ pub struct BlockchainOverlay { pub blocks: BlockStoreOverlay, /// Block order overlay pub order: BlockOrderStoreOverlay, - /// Slots overlay - pub slots: SlotStoreOverlay, - /// Blocks slots overlay - pub blocks_slots: BlocksSlotsStoreOverlay, /// Block height difficulties overlay, pub difficulties: BlockDifficultyStoreOverlay, /// Transactions overlay @@ -431,8 +361,6 @@ impl BlockchainOverlay { let headers = HeaderStoreOverlay::new(&overlay)?; let blocks = BlockStoreOverlay::new(&overlay)?; let order = BlockOrderStoreOverlay::new(&overlay)?; - let slots = SlotStoreOverlay::new(&overlay)?; - let blocks_slots = BlocksSlotsStoreOverlay::new(&overlay)?; let difficulties = BlockDifficultyStoreOverlay::new(&overlay)?; let transactions = TxStoreOverlay::new(&overlay)?; let contracts = ContractStateStoreOverlay::new(&overlay)?; @@ -443,8 +371,6 @@ impl BlockchainOverlay { headers, blocks, order, - slots, - blocks_slots, difficulties, transactions, contracts, @@ -457,7 +383,7 @@ impl BlockchainOverlay { self.order.is_empty() } - /// Retrieve the last block slot and hash. + /// Retrieve the last block height and hash. pub fn last(&self) -> Result<(u64, blake3::Hash)> { self.order.get_last() } @@ -490,13 +416,6 @@ impl BlockchainOverlay { // Store block order self.order.insert(&[block.header.height], &block_hash_vec)?; - // Store block slots uids vector - let slots = block.slots.iter().map(|x| x.id).collect(); - self.blocks_slots.insert(&block_hash_vec, &[&slots])?; - - // Store block slots - self.slots.insert(&block.slots)?; - Ok(block_hash) } @@ -514,21 +433,6 @@ impl BlockchainOverlay { return Ok(false) } - // Check if we have block slots uids vector - let slots = match self.blocks_slots.get(&[blockhash], true) { - Ok(v) => v[0].clone().unwrap(), - Err(_) => return Ok(false), - }; - let provided_block_slots: Vec = block.slots.iter().map(|x| x.id).collect(); - if slots != provided_block_slots { - return Ok(false) - } - - // Check if we have all slots - if self.slots.get(&slots, true).is_err() { - return Ok(false) - } - // Check provided info produces the same hash Ok(blockhash == block.hash()?) } @@ -554,12 +458,7 @@ impl BlockchainOverlay { let txs = self.transactions.get(&block.txs, true)?; let txs = txs.iter().map(|x| x.clone().unwrap()).collect(); - let slots = self.blocks_slots.get(&[block.hash()], true)?; - let slots = slots[0].clone().unwrap(); - let slots = self.slots.get(&slots, true)?; - let block_slots = slots.iter().map(|x| x.clone().unwrap()).collect(); - - let info = BlockInfo::new(header, txs, block.signature, block_slots); + let info = BlockInfo::new(header, txs, block.signature); ret.push(info); } @@ -585,8 +484,6 @@ impl BlockchainOverlay { let headers = HeaderStoreOverlay::new(&overlay)?; let blocks = BlockStoreOverlay::new(&overlay)?; let order = BlockOrderStoreOverlay::new(&overlay)?; - let slots = SlotStoreOverlay::new(&overlay)?; - let blocks_slots = BlocksSlotsStoreOverlay::new(&overlay)?; let difficulties = BlockDifficultyStoreOverlay::new(&overlay)?; let transactions = TxStoreOverlay::new(&overlay)?; let contracts = ContractStateStoreOverlay::new(&overlay)?; @@ -597,8 +494,6 @@ impl BlockchainOverlay { headers, blocks, order, - slots, - blocks_slots, difficulties, transactions, contracts, diff --git a/src/blockchain/slot_store.rs b/src/blockchain/slot_store.rs deleted file mode 100644 index c4cc800c8..000000000 --- a/src/blockchain/slot_store.rs +++ /dev/null @@ -1,353 +0,0 @@ -/* This file is part of DarkFi (https://dark.fi) - * - * Copyright (C) 2020-2024 Dyne.org foundation - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -// [`Slot`] is defined in the sdk so contracts can use it -use darkfi_sdk::blockchain::Slot; -use darkfi_serial::{deserialize, serialize}; - -use crate::{Error, Result}; - -use super::{parse_record, parse_u64_key_record, SledDbOverlayPtr}; - -const SLED_SLOT_TREE: &[u8] = b"_slots"; - -/// The `SlotStore` is a `sled` tree storing the blockhains' slots, -/// where the key is the slot uid, and the value is is the serialized slot. -#[derive(Clone)] -pub struct SlotStore(pub sled::Tree); - -impl SlotStore { - /// Opens a new or existing `SlotStore` on the given sled database. - pub fn new(db: &sled::Db) -> Result { - let tree = db.open_tree(SLED_SLOT_TREE)?; - Ok(Self(tree)) - } - - /// Insert a slice of [`Slot`] into the slot store. - pub fn insert(&self, slots: &[Slot]) -> Result<()> { - let batch = self.insert_batch(slots)?; - self.0.apply_batch(batch)?; - Ok(()) - } - - /// Generate the sled batch corresponding to an insert, so caller - /// can handle the write operation. - /// The slot id is used as the key, while value is the serialized [`Slot`] itself. - pub fn insert_batch(&self, slots: &[Slot]) -> Result { - let mut batch = sled::Batch::default(); - - for slot in slots { - let serialized = serialize(slot); - batch.insert(&slot.id.to_be_bytes(), serialized); - } - - Ok(batch) - } - - /// Check if the slot store contains a given id. - pub fn contains(&self, id: u64) -> Result { - Ok(self.0.contains_key(id.to_be_bytes())?) - } - - /// Fetch given slots from the slot store. - /// The resulting vector contains `Option`, which is `Some` if the slot - /// was found in the slot store, and otherwise it is `None`, if it has not. - /// The second parameter is a boolean which tells the function to fail in - /// case at least one slot was not found. - pub fn get(&self, ids: &[u64], strict: bool) -> Result>> { - let mut ret = Vec::with_capacity(ids.len()); - - for id in ids { - if let Some(found) = self.0.get(id.to_be_bytes())? { - let slot = deserialize(&found)?; - ret.push(Some(slot)); - } else { - if strict { - return Err(Error::SlotNotFound(*id)) - } - ret.push(None); - } - } - - Ok(ret) - } - - /// Retrieve all slot from the slot store. - /// Be careful as this will try to load everything in memory. - pub fn get_all(&self) -> Result> { - let mut slots = vec![]; - - for slot in self.0.iter() { - let (_, slot): (u64, Slot) = parse_u64_key_record(slot.unwrap())?; - slots.push(slot); - } - - Ok(slots) - } - - /// Fetch n slots after given slot. In the iteration, if a slot is not - /// found, the iteration stops and the function returns what it has found - /// so far in the `SlotStore`. - pub fn get_after(&self, id: u64, n: u64) -> Result> { - let mut ret = vec![]; - - let mut key = id; - let mut counter = 0; - while counter <= n { - if let Some(found) = self.0.get_gt(key.to_be_bytes())? { - let (id, slot) = parse_u64_key_record(found)?; - key = id; - ret.push(slot); - counter += 1; - continue - } - break - } - - Ok(ret) - } - - /// Fetch the last slot in the tree, based on the `Ord` - /// implementation for `Vec`. This should not be able to - /// fail because we initialize the store with the genesis slot. - pub fn get_last(&self) -> Result { - let found = self.0.last()?.unwrap(); - let slot = deserialize(&found.1)?; - Ok(slot) - } - - /// Retrieve records count - pub fn len(&self) -> usize { - self.0.len() - } - - pub fn is_empty(&self) -> bool { - self.0.is_empty() - } -} - -/// Overlay structure over a [`SlotStore`] instance. -pub struct SlotStoreOverlay(SledDbOverlayPtr); - -impl SlotStoreOverlay { - pub fn new(overlay: &SledDbOverlayPtr) -> Result { - overlay.lock().unwrap().open_tree(SLED_SLOT_TREE)?; - Ok(Self(overlay.clone())) - } - - /// Insert a slice of [`Slot`] into the overlay. - /// The slot id is used as the key, while value is the serialized [`Slot`] itself. - pub fn insert(&self, slots: &[Slot]) -> Result<()> { - let mut lock = self.0.lock().unwrap(); - - for slot in slots { - let serialized = serialize(slot); - lock.insert(SLED_SLOT_TREE, &slot.id.to_be_bytes(), &serialized)?; - } - - Ok(()) - } - - /// Fetch slot from the overlay by id. - pub fn get_by_id(&self, id: u64) -> Result> { - match self.0.lock().unwrap().get(SLED_SLOT_TREE, &id.to_be_bytes())? { - Some(found) => Ok(found.to_vec()), - None => Err(Error::SlotNotFound(id)), - } - } - - /// Fetch given slots from the overlay. - /// The resulting vector contains `Option`, which is `Some` if the slot - /// was found in the overlay, and otherwise it is `None`, if it has not. - /// The second parameter is a boolean which tells the function to fail in - /// case at least one slot was not found. - pub fn get(&self, ids: &[u64], strict: bool) -> Result>> { - let mut ret = Vec::with_capacity(ids.len()); - let lock = self.0.lock().unwrap(); - - for id in ids { - if let Some(found) = lock.get(SLED_SLOT_TREE, &id.to_be_bytes())? { - let slot = deserialize(&found)?; - ret.push(Some(slot)); - } else { - if strict { - return Err(Error::SlotNotFound(*id)) - } - ret.push(None); - } - } - - Ok(ret) - } - - /// Fetch the last slot from the overlay, based on the `Ord` - /// implementation for `Vec`. - pub fn get_last(&self) -> Result { - let found = self.0.lock().unwrap().last(SLED_SLOT_TREE)?.unwrap(); - let slot = deserialize(&found.1)?; - Ok(slot) - } -} - -const SLED_BLOCK_SLOTS_TREE: &[u8] = b"_blocks_slots"; - -/// The `BlocksSlotsStore` is a `sled` tree storing all the blocks' corresponding slot -/// uids, meaning the slot numbers leading up to each block, where the key is the -/// blocks' hash, and value is the serialized slot uids vector. -#[derive(Clone)] -pub struct BlocksSlotsStore(pub sled::Tree); - -impl BlocksSlotsStore { - /// Opens a new or existing `BlocksSlotsStore` on the given sled database. - pub fn new(db: &sled::Db) -> Result { - let tree = db.open_tree(SLED_BLOCK_SLOTS_TREE)?; - Ok(Self(tree)) - } - - /// Insert a slice of block hashes and their `u64` vectors into the store. - pub fn insert(&self, hashes: &[blake3::Hash], slots: &[&Vec]) -> Result<()> { - let batch = self.insert_batch(hashes, slots)?; - self.0.apply_batch(batch)?; - Ok(()) - } - - /// Generate the sled batch corresponding to an insert, so caller - /// can handle the write operation. The block hash is used as the key, - /// and the block slots serialized vector is used as value. - pub fn insert_batch( - &self, - hashes: &[blake3::Hash], - slots: &[&Vec], - ) -> Result { - if hashes.len() != slots.len() { - return Err(Error::InvalidInputLengths) - } - - let mut batch = sled::Batch::default(); - - for (i, hash) in hashes.iter().enumerate() { - let serialized = serialize(slots[i]); - batch.insert(hash.as_bytes(), serialized); - } - - Ok(batch) - } - - /// Check if the blocks slots store contains a given block hash. - pub fn contains(&self, blockhash: &blake3::Hash) -> Result { - Ok(self.0.contains_key(blockhash.as_bytes())?) - } - - /// Fetch given blocks slots from the blocks slots store. - /// The resulting vector contains `Option`, which is `Some` if the block slots - /// were found in the blocks slots store, and otherwise it is `None`, if they have not. - /// The second parameter is a boolean which tells the function to fail in - /// case at least one block was not found. - pub fn get( - &self, - block_hashes: &[blake3::Hash], - strict: bool, - ) -> Result>>> { - let mut ret = Vec::with_capacity(block_hashes.len()); - - for hash in block_hashes { - if let Some(found) = self.0.get(hash.as_bytes())? { - let slots = deserialize(&found)?; - ret.push(Some(slots)); - } else { - if strict { - let s = hash.to_hex().as_str().to_string(); - return Err(Error::BlockSlotsNotFound(s)) - } - ret.push(None); - } - } - - Ok(ret) - } - - /// Retrieve all blocks slots from the block store in the form of a tuple - /// (`hash`, `Vec`). - /// Be careful as this will try to load everything in memory. - pub fn get_all(&self) -> Result)>> { - let mut blocks_slots = vec![]; - - for block_slots in self.0.iter() { - blocks_slots.push(parse_record(block_slots.unwrap())?); - } - - Ok(blocks_slots) - } -} - -/// Overlay structure over a [`BlocksSlotsStore`] instance. -pub struct BlocksSlotsStoreOverlay(SledDbOverlayPtr); - -impl BlocksSlotsStoreOverlay { - pub fn new(overlay: &SledDbOverlayPtr) -> Result { - overlay.lock().unwrap().open_tree(SLED_BLOCK_SLOTS_TREE)?; - Ok(Self(overlay.clone())) - } - - /// Insert a slice of block hashes and their `u64` vectors into the overlay. - /// The block hash is used as the key, and the block slots serialized vector - /// is used as value. - pub fn insert(&self, hashes: &[blake3::Hash], slots: &[&Vec]) -> Result<()> { - if hashes.len() != slots.len() { - return Err(Error::InvalidInputLengths) - } - - let mut lock = self.0.lock().unwrap(); - - for (i, hash) in hashes.iter().enumerate() { - let serialized = serialize(slots[i]); - lock.insert(SLED_BLOCK_SLOTS_TREE, hash.as_bytes(), &serialized)?; - } - - Ok(()) - } - - /// Fetch given blocks slots from the overlay. - /// The resulting vector contains `Option`, which is `Some` if the block slots - /// were found in the overlay, and otherwise it is `None`, if they have not. - /// The second parameter is a boolean which tells the function to fail in - /// case at least one block was not found. - pub fn get( - &self, - block_hashes: &[blake3::Hash], - strict: bool, - ) -> Result>>> { - let mut ret = Vec::with_capacity(block_hashes.len()); - let lock = self.0.lock().unwrap(); - - for hash in block_hashes { - if let Some(found) = lock.get(SLED_BLOCK_SLOTS_TREE, hash.as_bytes())? { - let slots = deserialize(&found)?; - ret.push(Some(slots)); - } else { - if strict { - let s = hash.to_hex().as_str().to_string(); - return Err(Error::BlockSlotsNotFound(s)) - } - ret.push(None); - } - } - - Ok(ret) - } -} diff --git a/src/sdk/src/blockchain.rs b/src/sdk/src/blockchain.rs index 9a46fb778..852fca7d5 100644 --- a/src/sdk/src/blockchain.rs +++ b/src/sdk/src/blockchain.rs @@ -16,112 +16,6 @@ * along with this program. If not, see . */ -#[cfg(feature = "async")] -use darkfi_serial::async_trait; -use darkfi_serial::{SerialDecodable, SerialEncodable}; -use pasta_curves::{group::ff::Field, pallas}; - -/// Auxiliary structure used to keep track of slots' previous slot -/// relevant validation parameters. -#[derive(Debug, Clone, PartialEq, SerialEncodable, SerialDecodable)] -pub struct PreviousSlot { - /// Block producers count - pub producers: u64, - /// Existing forks last proposal/block hashes, - /// as observed by the validator - pub last_hashes: Vec, - /// Existing forks second to last proposal/block hashes, - /// as observed by the validator - pub second_to_last_hashes: Vec, - /// Feedback error - pub error: f64, -} - -impl PreviousSlot { - pub fn new( - producers: u64, - last_hashes: Vec, - second_to_last_hashes: Vec, - error: f64, - ) -> Self { - Self { producers, last_hashes, second_to_last_hashes, error } - } -} - -impl Default for PreviousSlot { - /// Represents the genesis slot previous slot on current timestamp - fn default() -> Self { - Self::new(0, vec![], vec![], 0.0) - } -} - -/// Auxiliary structure used to keep track of slot PID output. -#[derive(Debug, Clone, PartialEq, SerialEncodable, SerialDecodable)] -pub struct PidOutput { - /// Inverse probability `f` of becoming a block producer - pub f: f64, - /// Feedback error - pub error: f64, - /// Slot sigma1 - pub sigma1: pallas::Base, - /// Slot sigma2 - pub sigma2: pallas::Base, -} - -impl PidOutput { - pub fn new(f: f64, error: f64, sigma1: pallas::Base, sigma2: pallas::Base) -> Self { - Self { f, error, sigma1, sigma2 } - } -} - -impl Default for PidOutput { - /// Represents the genesis slot PID output on current timestamp - fn default() -> Self { - Self::new(0.0, 0.0, pallas::Base::ZERO, pallas::Base::ZERO) - } -} - -/// Auxiliary structure used to keep track of slot validation parameters. -#[derive(Debug, Clone, PartialEq, SerialEncodable, SerialDecodable)] -pub struct Slot { - /// Slot UID - pub id: u64, - /// Previous slot information - pub previous: PreviousSlot, - /// Slot PID output - pub pid: PidOutput, - /// Last block/proposal nonce(eta) - pub last_nonce: pallas::Base, - /// Total tokens up until this slot - pub total_tokens: u64, - /// Slot reward - pub reward: u64, -} - -impl Slot { - pub fn new( - id: u64, - previous: PreviousSlot, - pid: PidOutput, - last_nonce: pallas::Base, - total_tokens: u64, - reward: u64, - ) -> Self { - Self { id, previous, pid, last_nonce, total_tokens, reward } - } -} - -impl Default for Slot { - /// Represents the genesis slot on current timestamp - fn default() -> Self { - Self::new(0, PreviousSlot::default(), PidOutput::default(), pallas::Base::ZERO, 0, 0) - } -} - -// TODO: This values are experimental, should be replaced with the proper ones once defined -pub const POW_CUTOFF: u64 = 1000000; -pub const POS_START: u64 = 1000001; - /// Auxiliary function to calculate provided block height block version. /// Currently, a single version(1) exists. pub fn block_version(_height: u64) -> u8 { diff --git a/src/validator/consensus.rs b/src/validator/consensus.rs index 16b2d8b7a..6ad0dd58f 100644 --- a/src/validator/consensus.rs +++ b/src/validator/consensus.rs @@ -97,7 +97,7 @@ impl Consensus { ); // Generate the block - let mut block = BlockInfo::new_empty(header, vec![]); + let mut block = BlockInfo::new_empty(header); // Add transactions to the block block.append_txs(unproposed_txs)?; diff --git a/src/validator/mod.rs b/src/validator/mod.rs index e1647c5a6..a823e24c7 100644 --- a/src/validator/mod.rs +++ b/src/validator/mod.rs @@ -18,7 +18,7 @@ use std::sync::Arc; -use darkfi_sdk::{blockchain::Slot, crypto::PublicKey}; +use darkfi_sdk::crypto::PublicKey; use darkfi_serial::serialize_async; use log::{debug, error, info, warn}; use num_bigint::BigUint; @@ -468,15 +468,6 @@ impl Validator { Ok(()) } - /// Append to canonical state received slot. - /// This should be only used for test purposes. - pub async fn receive_test_slot(&self, slot: &Slot) -> Result<()> { - debug!(target: "validator::receive_test_slot", "Appending slot to ledger"); - self.blockchain.slots.insert(&[slot.clone()])?; - - Ok(()) - } - /// Validate a producer `Transaction` and apply it if valid. /// In case the transactions fail, ir will be returned to the caller. /// The function takes a boolean called `write` which tells it to actually write