From d6488719661f82461a24351ab41bfa2fcf3e2eb9 Mon Sep 17 00:00:00 2001 From: Boog900 <54e72d8a-345f-4599-bd90-c6b9bc7d0ec5@aleeas.com> Date: Thu, 29 Aug 2024 18:44:34 +0100 Subject: [PATCH 01/31] add new tables & types --- storage/blockchain/src/lib.rs | 2 +- storage/blockchain/src/tables.rs | 25 ++++++-- storage/blockchain/src/types.rs | 101 ++++++++++++++++++++++++++++++- types/src/types.rs | 3 +- 4 files changed, 123 insertions(+), 8 deletions(-) diff --git a/storage/blockchain/src/lib.rs b/storage/blockchain/src/lib.rs index e544a69e9..0dea345b3 100644 --- a/storage/blockchain/src/lib.rs +++ b/storage/blockchain/src/lib.rs @@ -52,7 +52,7 @@ unused_crate_dependencies, unused_doc_comments, unused_mut, - missing_docs, + //missing_docs, deprecated, unused_comparisons, nonstandard_style diff --git a/storage/blockchain/src/tables.rs b/storage/blockchain/src/tables.rs index 122ac31b4..6db768167 100644 --- a/storage/blockchain/src/tables.rs +++ b/storage/blockchain/src/tables.rs @@ -16,11 +16,7 @@ //! accessing _all_ tables defined here at once. //---------------------------------------------------------------------------------------------------- Import -use crate::types::{ - Amount, AmountIndex, AmountIndices, BlockBlob, BlockHash, BlockHeight, BlockInfo, KeyImage, - Output, PreRctOutputId, PrunableBlob, PrunableHash, PrunedBlob, RctOutput, TxBlob, TxHash, - TxId, UnlockTime, -}; +use crate::types::{Amount, AmountIndex, AmountIndices, BlockBlob, BlockHash, BlockHeight, BlockInfo, KeyImage, Output, PreRctOutputId, PrunableBlob, PrunableHash, PrunedBlob, RctOutput, TxBlob, TxHash, TxId, UnlockTime, RawChainId, AltChainInfo, AltBlockHeight, CompactAltBlockInfo, AltTransactionInfo}; //---------------------------------------------------------------------------------------------------- Tables // Notes: @@ -129,6 +125,25 @@ cuprate_database::define_tables! { /// Transactions without unlock times will not exist in this table. 14 => TxUnlockTime, TxId => UnlockTime, + + 15 => AltChainInfos, + RawChainId => AltChainInfo, + + 16 => AltBlockHeights, + BlockHash => AltBlockHeight, + + 17 => AltBlocksInfo, + AltBlockHeight => CompactAltBlockInfo, + + 18 => AltBlockBlobs, + AltBlockHeight => BlockBlob, + + 19 => AltTransactionBlobs, + TxHash => TxBlob, + + 20 => AltTransactionInfos, + TxHash => AltTransactionInfo, + } //---------------------------------------------------------------------------------------------------- Tests diff --git a/storage/blockchain/src/types.rs b/storage/blockchain/src/types.rs index eb1dc6479..73c7614f3 100644 --- a/storage/blockchain/src/types.rs +++ b/storage/blockchain/src/types.rs @@ -41,13 +41,15 @@ #![forbid(unsafe_code)] // if you remove this line i will steal your monero //---------------------------------------------------------------------------------------------------- Import +use std::num::NonZero; + use bytemuck::{Pod, Zeroable}; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; use cuprate_database::{Key, StorableVec}; - +use cuprate_types::{Chain, ChainId}; //---------------------------------------------------------------------------------------------------- Aliases // These type aliases exist as many Monero-related types are the exact same. // For clarity, they're given type aliases as to not confuse them. @@ -324,6 +326,103 @@ pub struct RctOutput { } // TODO: local_index? +//---------------------------------------------------------------------------------------------------- RawChain +#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Pod, Zeroable)] +#[repr(transparent)] +pub struct RawChain(u64); + +impl From for RawChain { + fn from(value: Chain) -> Self { + match value { + Chain::Main => RawChain(0), + Chain::Alt(chain_id) => RawChain(chain_id.0.get()), + } + } +} + +impl From for Chain { + fn from(value: RawChain) -> Self { + NonZero::new(value.0) + .map(|id| Chain::Alt(ChainId(id))) + .unwrap_or(Chain::Main) + } +} + +//---------------------------------------------------------------------------------------------------- RawChainId +#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Pod, Zeroable)] +#[repr(transparent)] +pub struct RawChainId(u64); + +impl From for RawChainId { + fn from(value: ChainId) -> Self { + RawChainId(value.0.get()) + } +} + +impl From for ChainId { + fn from(value: RawChainId) -> Self { + ChainId(NonZero::new(value.0).expect("RawChainId mut not have a value of `0`")) + } +} + +impl Key for RawChainId {} + +//---------------------------------------------------------------------------------------------------- AltChainInfo +#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Pod, Zeroable)] +#[repr(C)] +pub struct AltChainInfo { + parent_chain: RawChain, + common_ancestor_height: u64 +} + +//---------------------------------------------------------------------------------------------------- AltBlockHeight +#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Pod, Zeroable)] +#[repr(C)] +pub struct AltBlockHeight { + chain_id: u64, + height: u64, +} + +impl Key for AltBlockHeight {} + +//---------------------------------------------------------------------------------------------------- CompactAltBlockInfo +#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Pod, Zeroable)] +#[repr(C)] +pub struct CompactAltBlockInfo { + /// The block's hash. + /// + /// [`Block::hash`]. + pub block_hash: [u8; 32], + /// The block's proof-of-work hash. + pub pow_hash: [u8; 32], + /// The block's height. + pub height: u64, + /// The adjusted block size, in bytes. + pub weight: usize, + /// The long term block weight, which is the weight factored in with previous block weights. + pub long_term_weight: usize, + /// The cumulative difficulty of all blocks up until and including this block. + pub cumulative_difficulty_low: u64, + pub cumulative_difficulty_high: u64, + +} + +//---------------------------------------------------------------------------------------------------- AltTransactionInfo +#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Pod, Zeroable)] +#[repr(C)] +pub struct AltTransactionInfo { + /// The transaction's weight. + /// + /// [`Transaction::weight`]. + pub tx_weight: usize, + /// The transaction's total fees. + pub fee: u64, + /// The transaction's hash. + /// + /// [`Transaction::hash`]. + pub tx_hash: [u8; 32], +} + //---------------------------------------------------------------------------------------------------- Tests #[cfg(test)] mod test { diff --git a/types/src/types.rs b/types/src/types.rs index 4b6e2e126..da4422a15 100644 --- a/types/src/types.rs +++ b/types/src/types.rs @@ -1,5 +1,6 @@ //! Various shared data types in Cuprate. +use std::num::NonZero; //---------------------------------------------------------------------------------------------------- Import use curve25519_dalek::edwards::EdwardsPoint; use monero_serai::{ @@ -97,7 +98,7 @@ pub struct VerifiedBlockInformation { /// /// The inner value is meaningless. #[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)] -pub struct ChainId(pub u64); +pub struct ChainId(pub NonZero); //---------------------------------------------------------------------------------------------------- Chain /// An identifier for a chain. From e1ae84836911acab79fe3eb853725ca94fc4ff3e Mon Sep 17 00:00:00 2001 From: Boog900 <54e72d8a-345f-4599-bd90-c6b9bc7d0ec5@aleeas.com> Date: Fri, 30 Aug 2024 03:01:23 +0100 Subject: [PATCH 02/31] add function to fully add an alt block --- storage/blockchain/src/ops/alt_block.rs | 104 ++++++++++++++++++++++++ storage/blockchain/src/ops/mod.rs | 1 + storage/blockchain/src/tables.rs | 7 +- storage/blockchain/src/types.rs | 19 +++-- 4 files changed, 124 insertions(+), 7 deletions(-) create mode 100644 storage/blockchain/src/ops/alt_block.rs diff --git a/storage/blockchain/src/ops/alt_block.rs b/storage/blockchain/src/ops/alt_block.rs new file mode 100644 index 000000000..d04899efc --- /dev/null +++ b/storage/blockchain/src/ops/alt_block.rs @@ -0,0 +1,104 @@ +use bytemuck::TransparentWrapper; + +use cuprate_database::{DatabaseRw, RuntimeError, StorableVec, DatabaseRo}; +use cuprate_helper::map::split_u128_into_low_high_bits; +use cuprate_types::{AltBlockInformation, Chain, VerifiedTransactionInformation}; + +use crate::{ + tables::TablesMut, + types::{AltBlockHeight, AltChainInfo, AltTransactionInfo, BlockHash, CompactAltBlockInfo}, +}; + +pub fn add_alt_block( + alt_block: &AltBlockInformation, + tables: &mut impl TablesMut, +) -> Result<(), RuntimeError> { + let alt_block_height = AltBlockHeight { + chain_id: alt_block.chain_id.into(), + height: alt_block.height, + }; + + tables + .alt_block_heights_mut() + .put(&alt_block.block_hash, &alt_block_height)?; + + check_add_alt_chain_info(&alt_block_height, &alt_block.block.header.previous, tables)?; + + let (cumulative_difficulty_low, cumulative_difficulty_high) = + split_u128_into_low_high_bits(alt_block.cumulative_difficulty); + + let alt_block_info = CompactAltBlockInfo { + block_hash: alt_block.block_hash, + pow_hash: alt_block.pow_hash, + height: alt_block.height, + weight: alt_block.weight, + long_term_weight: alt_block.long_term_weight, + cumulative_difficulty_low, + cumulative_difficulty_high, + }; + + tables + .alt_blocks_info_mut() + .put(&alt_block_height, &alt_block_info)?; + + tables.alt_block_blobs_mut().put( + &alt_block_height, + StorableVec::wrap_ref(&alt_block.block_blob), + )?; + + for tx in &alt_block.txs { + add_alt_transaction(&tx, tables)?; + } + + Ok(()) +} + +pub fn add_alt_transaction( + tx: &VerifiedTransactionInformation, + tables: &mut impl TablesMut, +) -> Result<(), RuntimeError> { + if tables.tx_ids().get(&tx.tx_hash).is_ok() + || tables.alt_transaction_infos().get(&tx.tx_hash).is_ok() + { + return Ok(()); + } + + tables.alt_transaction_infos_mut().put( + &tx.tx_hash, + &AltTransactionInfo { + tx_weight: tx.tx_weight, + fee: tx.fee, + tx_hash: tx.tx_hash, + }, + )?; + + tables + .alt_transaction_blobs_mut() + .put(&tx.tx_hash, StorableVec::wrap_ref(&tx.tx_blob)) +} + +pub fn check_add_alt_chain_info( + alt_block_height: &AltBlockHeight, + prev_hash: &BlockHash, + tables: &mut impl TablesMut, +) -> Result<(), RuntimeError> { + match tables.alt_chain_infos().get(&alt_block_height.chain_id) { + Ok(_) => return Ok(()), + Err(RuntimeError::KeyNotFound) => (), + Err(e) => return Err(e), + } + + let parent_chain = match tables.alt_block_heights().get(prev_hash) { + Ok(alt_parent_height) => Chain::Alt(alt_parent_height.chain_id.into()), + Err(RuntimeError::KeyNotFound) => Chain::Main, + Err(e) => return Err(e), + }; + + tables.alt_chain_infos_mut().put( + &alt_block_height.chain_id, + &AltChainInfo { + parent_chain: parent_chain.into(), + common_ancestor_height: alt_block_height.height - 1, + }, + ) +} diff --git a/storage/blockchain/src/ops/mod.rs b/storage/blockchain/src/ops/mod.rs index 4ff7dff1e..1ec9c237a 100644 --- a/storage/blockchain/src/ops/mod.rs +++ b/storage/blockchain/src/ops/mod.rs @@ -108,5 +108,6 @@ pub mod key_image; pub mod output; pub mod property; pub mod tx; +pub mod alt_block; mod macros; diff --git a/storage/blockchain/src/tables.rs b/storage/blockchain/src/tables.rs index 6db768167..381430d73 100644 --- a/storage/blockchain/src/tables.rs +++ b/storage/blockchain/src/tables.rs @@ -16,7 +16,12 @@ //! accessing _all_ tables defined here at once. //---------------------------------------------------------------------------------------------------- Import -use crate::types::{Amount, AmountIndex, AmountIndices, BlockBlob, BlockHash, BlockHeight, BlockInfo, KeyImage, Output, PreRctOutputId, PrunableBlob, PrunableHash, PrunedBlob, RctOutput, TxBlob, TxHash, TxId, UnlockTime, RawChainId, AltChainInfo, AltBlockHeight, CompactAltBlockInfo, AltTransactionInfo}; +use crate::types::{ + AltBlockHeight, AltChainInfo, AltTransactionInfo, Amount, AmountIndex, AmountIndices, + BlockBlob, BlockHash, BlockHeight, BlockInfo, CompactAltBlockInfo, KeyImage, Output, + PreRctOutputId, PrunableBlob, PrunableHash, PrunedBlob, RawChainId, RctOutput, TxBlob, TxHash, + TxId, UnlockTime, +}; //---------------------------------------------------------------------------------------------------- Tables // Notes: diff --git a/storage/blockchain/src/types.rs b/storage/blockchain/src/types.rs index 73c7614f3..88ece10b0 100644 --- a/storage/blockchain/src/types.rs +++ b/storage/blockchain/src/types.rs @@ -348,6 +348,14 @@ impl From for Chain { } } +impl From for RawChain { + fn from(value: RawChainId) -> Self { + assert_ne!(value.0, 0); + + RawChain(value.0) + } +} + //---------------------------------------------------------------------------------------------------- RawChainId #[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Pod, Zeroable)] #[repr(transparent)] @@ -371,16 +379,16 @@ impl Key for RawChainId {} #[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Pod, Zeroable)] #[repr(C)] pub struct AltChainInfo { - parent_chain: RawChain, - common_ancestor_height: u64 + pub parent_chain: RawChain, + pub common_ancestor_height: usize, } //---------------------------------------------------------------------------------------------------- AltBlockHeight #[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Pod, Zeroable)] #[repr(C)] pub struct AltBlockHeight { - chain_id: u64, - height: u64, + pub chain_id: RawChainId, + pub height: usize, } impl Key for AltBlockHeight {} @@ -396,7 +404,7 @@ pub struct CompactAltBlockInfo { /// The block's proof-of-work hash. pub pow_hash: [u8; 32], /// The block's height. - pub height: u64, + pub height: usize, /// The adjusted block size, in bytes. pub weight: usize, /// The long term block weight, which is the weight factored in with previous block weights. @@ -404,7 +412,6 @@ pub struct CompactAltBlockInfo { /// The cumulative difficulty of all blocks up until and including this block. pub cumulative_difficulty_low: u64, pub cumulative_difficulty_high: u64, - } //---------------------------------------------------------------------------------------------------- AltTransactionInfo From ed887a7c859d45fce68cbf4e70f56e4b46449492 Mon Sep 17 00:00:00 2001 From: Boog900 <54e72d8a-345f-4599-bd90-c6b9bc7d0ec5@aleeas.com> Date: Fri, 30 Aug 2024 23:06:30 +0100 Subject: [PATCH 03/31] resolve current todo!s --- storage/blockchain/src/lib.rs | 2 + storage/blockchain/src/ops/alt_block.rs | 137 ++++++++++++++++++++++-- storage/blockchain/src/ops/block.rs | 10 +- storage/blockchain/src/ops/mod.rs | 2 +- storage/blockchain/src/service/read.rs | 43 +++++++- 5 files changed, 178 insertions(+), 16 deletions(-) diff --git a/storage/blockchain/src/lib.rs b/storage/blockchain/src/lib.rs index 0dea345b3..8a6f96b6c 100644 --- a/storage/blockchain/src/lib.rs +++ b/storage/blockchain/src/lib.rs @@ -98,6 +98,8 @@ clippy::too_many_lines ) )] +extern crate core; + // Only allow building 64-bit targets. // // This allows us to assume 64-bit diff --git a/storage/blockchain/src/ops/alt_block.rs b/storage/blockchain/src/ops/alt_block.rs index d04899efc..82a37ba8e 100644 --- a/storage/blockchain/src/ops/alt_block.rs +++ b/storage/blockchain/src/ops/alt_block.rs @@ -1,12 +1,21 @@ -use bytemuck::TransparentWrapper; +use std::cmp::max; -use cuprate_database::{DatabaseRw, RuntimeError, StorableVec, DatabaseRo}; -use cuprate_helper::map::split_u128_into_low_high_bits; -use cuprate_types::{AltBlockInformation, Chain, VerifiedTransactionInformation}; +use bytemuck::TransparentWrapper; +use cuprate_database::{DatabaseRo, DatabaseRw, RuntimeError, StorableVec}; +use cuprate_helper::map::{combine_low_high_bits_to_u128, split_u128_into_low_high_bits}; +use cuprate_types::{ + AltBlockInformation, Chain, ChainId, ExtendedBlockHeader, HardFork, + VerifiedTransactionInformation, +}; +use monero_serai::block::BlockHeader; use crate::{ - tables::TablesMut, - types::{AltBlockHeight, AltChainInfo, AltTransactionInfo, BlockHash, CompactAltBlockInfo}, + ops::block::{get_block_extended_header_from_height, get_block_info}, + tables::{Tables, TablesMut}, + types::{ + AltBlockHeight, AltChainInfo, AltTransactionInfo, BlockHash, BlockHeight, + CompactAltBlockInfo, + }, }; pub fn add_alt_block( @@ -102,3 +111,119 @@ pub fn check_add_alt_chain_info( }, ) } + +pub fn alt_block_hash( + block_height: &BlockHeight, + alt_chain: ChainId, + tables: &mut impl Tables, +) -> Result { + let alt_chains = tables.alt_chain_infos(); + + let original_chain = { + let mut chain = alt_chain.into(); + loop { + let chain_info = alt_chains.get(&chain)?; + + if chain_info.common_ancestor_height < *block_height { + break Chain::Alt(chain.into()); + } + + match chain_info.parent_chain.into() { + Chain::Main => break Chain::Main, + Chain::Alt(alt_chain_id) => { + chain = alt_chain_id.into(); + continue; + } + } + } + }; + + match original_chain { + Chain::Main => { + get_block_info(&block_height, tables.block_infos()).map(|info| info.block_hash) + } + Chain::Alt(chain_id) => tables + .alt_blocks_info() + .get(&AltBlockHeight { + chain_id: chain_id.into(), + height: *block_height, + }) + .map(|info| info.block_hash), + } +} + +pub fn alt_extended_headers_in_range( + range: std::ops::Range, + alt_chain: ChainId, + tables: &impl Tables, +) -> Result, RuntimeError> { + // TODO: this function does not use rayon, however it probably should. + + let mut ranges = Vec::with_capacity(5); + let alt_chains = tables.alt_chain_infos(); + + let mut i = range.end; + let mut current_chain_id = alt_chain.into(); + while i > range.start { + let chain_info = alt_chains.get(¤t_chain_id)?; + + let start_height = max(range.start, chain_info.common_ancestor_height + 1); + + ranges.push((chain_info.parent_chain.into(), start_height..i)); + i = chain_info.common_ancestor_height; + + match chain_info.parent_chain.into() { + Chain::Main => { + ranges.push((Chain::Main, range.start..i)); + break; + } + Chain::Alt(alt_chain_id) => { + current_chain_id = alt_chain_id.into(); + continue; + } + } + } + + let res = ranges + .into_iter() + .rev() + .map(|(chain, range)| { + range.into_iter().map(move |height| match chain { + Chain::Main => get_block_extended_header_from_height(&height, tables), + Chain::Alt(chain_id) => get_alt_block_extended_header_from_height( + &AltBlockHeight { + chain_id: chain_id.into(), + height, + }, + tables, + ), + }) + }) + .flatten() + .collect::>()?; + + Ok(res) +} + +pub fn get_alt_block_extended_header_from_height( + height: &AltBlockHeight, + table: &impl Tables, +) -> Result { + let block_info = table.alt_blocks_info().get(height)?; + + let block_blob = table.alt_block_blobs().get(height)?.0; + + let block_header = BlockHeader::read(&mut block_blob.as_slice())?; + + Ok(ExtendedBlockHeader { + version: HardFork::from_version(0).expect("Block in DB must have correct version"), + vote: block_header.hardfork_version, + timestamp: block_header.timestamp, + cumulative_difficulty: combine_low_high_bits_to_u128( + block_info.cumulative_difficulty_low, + block_info.cumulative_difficulty_high, + ), + block_weight: block_info.weight, + long_term_weight: block_info.long_term_weight, + }) +} diff --git a/storage/blockchain/src/ops/block.rs b/storage/blockchain/src/ops/block.rs index 4f77d736e..2e110fedf 100644 --- a/storage/blockchain/src/ops/block.rs +++ b/storage/blockchain/src/ops/block.rs @@ -2,7 +2,7 @@ //---------------------------------------------------------------------------------------------------- Import use bytemuck::TransparentWrapper; -use monero_serai::block::Block; +use monero_serai::block::{Block, BlockHeader}; use cuprate_database::{ RuntimeError, StorableVec, {DatabaseRo, DatabaseRw}, @@ -190,7 +190,7 @@ pub fn get_block_extended_header_from_height( ) -> Result { let block_info = tables.block_infos().get(block_height)?; let block_blob = tables.block_blobs().get(block_height)?.0; - let block = Block::read(&mut block_blob.as_slice())?; + let block_header = BlockHeader::read(&mut block_blob.as_slice())?; let cumulative_difficulty = combine_low_high_bits_to_u128( block_info.cumulative_difficulty_low, @@ -201,10 +201,10 @@ pub fn get_block_extended_header_from_height( #[allow(clippy::cast_possible_truncation)] Ok(ExtendedBlockHeader { cumulative_difficulty, - version: HardFork::from_version(block.header.hardfork_version) + version: HardFork::from_version(block_header.hardfork_version) .expect("Stored block must have a valid hard-fork"), - vote: block.header.hardfork_signal, - timestamp: block.header.timestamp, + vote: block_header.hardfork_signal, + timestamp: block_header.timestamp, block_weight: block_info.weight as usize, long_term_weight: block_info.long_term_weight as usize, }) diff --git a/storage/blockchain/src/ops/mod.rs b/storage/blockchain/src/ops/mod.rs index 1ec9c237a..8a8f0f158 100644 --- a/storage/blockchain/src/ops/mod.rs +++ b/storage/blockchain/src/ops/mod.rs @@ -102,12 +102,12 @@ //! # Ok(()) } //! ``` +pub mod alt_block; pub mod block; pub mod blockchain; pub mod key_image; pub mod output; pub mod property; pub mod tx; -pub mod alt_block; mod macros; diff --git a/storage/blockchain/src/service/read.rs b/storage/blockchain/src/service/read.rs index 207da4163..eef40b5e5 100644 --- a/storage/blockchain/src/service/read.rs +++ b/storage/blockchain/src/service/read.rs @@ -22,6 +22,7 @@ use cuprate_types::{ use crate::{ ops::{ + alt_block::{alt_block_hash, alt_extended_headers_in_range}, block::{ block_exists, get_block_extended_header_from_height, get_block_height, get_block_info, }, @@ -33,7 +34,7 @@ use crate::{ free::{compact_history_genesis_not_included, compact_history_index_to_height_offset}, types::{BlockchainReadHandle, ResponseResult}, }, - tables::{BlockHeights, BlockInfos, OpenTables, Tables}, + tables::{AltBlockHeights, BlockHeights, BlockInfos, OpenTables, Tables}, types::{Amount, AmountIndex, BlockHash, BlockHeight, KeyImage, PreRctOutputId}, }; @@ -87,7 +88,7 @@ fn map_request( match request { R::BlockExtendedHeader(block) => block_extended_header(env, block), R::BlockHash(block, chain) => block_hash(env, block, chain), - R::FindBlock(_) => todo!("Add alt blocks to DB"), + R::FindBlock(block_hash) => find_block(env, block_hash), R::FilterUnknownHashes(hashes) => filter_unknown_hashes(env, hashes), R::BlockExtendedHeaderInRange(range, chain) => { block_extended_header_in_range(env, range, chain) @@ -198,12 +199,39 @@ fn block_hash(env: &ConcreteEnv, block_height: BlockHeight, chain: Chain) -> Res let block_hash = match chain { Chain::Main => get_block_info(&block_height, &table_block_infos)?.block_hash, - Chain::Alt(_) => todo!("Add alt blocks to DB"), + Chain::Alt(chain) => { + alt_block_hash(&block_height, chain, &mut env_inner.open_tables(&tx_ro)?)? + } }; Ok(BlockchainResponse::BlockHash(block_hash)) } +/// [`BlockchainReadRequest::FindBlock`] +fn find_block(env: &ConcreteEnv, block_hash: BlockHash) -> ResponseResult { + // Single-threaded, no `ThreadLocal` required. + let env_inner = env.env_inner(); + let tx_ro = env_inner.tx_ro()?; + + let table_block_heights = env_inner.open_db_ro::(&tx_ro)?; + + // Check the main chain first. + match table_block_heights.get(&block_hash) { + Ok(height) => return Ok(BlockchainResponse::FindBlock(Some((Chain::Main, height)))), + Err(RuntimeError::KeyNotFound) => (), + Err(e) => return Err(e), + } + + let table_alt_block_heights = env_inner.open_db_ro::(&tx_ro)?; + + let height = table_alt_block_heights.get(&block_hash)?; + + Ok(BlockchainResponse::FindBlock(Some(( + Chain::Alt(height.chain_id.into()), + height.height, + )))) +} + /// [`BlockchainReadRequest::FilterUnknownHashes`]. #[inline] fn filter_unknown_hashes(env: &ConcreteEnv, mut hashes: HashSet) -> ResponseResult { @@ -254,7 +282,14 @@ fn block_extended_header_in_range( get_block_extended_header_from_height(&block_height, tables) }) .collect::, RuntimeError>>()?, - Chain::Alt(_) => todo!("Add alt blocks to DB"), + Chain::Alt(chain_id) => { + let tx_ro = tx_ro.get_or_try(|| env_inner.tx_ro())?; + alt_extended_headers_in_range( + range, + chain_id, + get_tables!(env_inner, tx_ro, tables)?.as_ref(), + )? + } }; Ok(BlockchainResponse::BlockExtendedHeaderInRange(vec)) From bc619b61eb06d54647dbba14530ebba6e110697f Mon Sep 17 00:00:00 2001 From: Boog900 <54e72d8a-345f-4599-bd90-c6b9bc7d0ec5@aleeas.com> Date: Sat, 31 Aug 2024 01:22:30 +0100 Subject: [PATCH 04/31] add new requests --- storage/blockchain/src/service/write.rs | 4 +++ types/src/blockchain.rs | 42 +++++++++++++++++++++---- 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/storage/blockchain/src/service/write.rs b/storage/blockchain/src/service/write.rs index 816afc4f5..a2cc71c7b 100644 --- a/storage/blockchain/src/service/write.rs +++ b/storage/blockchain/src/service/write.rs @@ -29,6 +29,10 @@ fn handle_blockchain_request( ) -> Result { match req { BlockchainWriteRequest::WriteBlock(block) => write_block(env, block), + BlockchainWriteRequest::WriteAltBlock(_) => todo!(), + BlockchainWriteRequest::StartReorg(_) => todo!(), + BlockchainWriteRequest::ReverseReorg(_) => todo!(), + BlockchainWriteRequest::FlushAltBlocks => todo!(), } } diff --git a/types/src/blockchain.rs b/types/src/blockchain.rs index b502c3fa8..48eab292e 100644 --- a/types/src/blockchain.rs +++ b/types/src/blockchain.rs @@ -8,7 +8,7 @@ use std::{ collections::{HashMap, HashSet}, ops::Range, }; - +use crate::{AltBlockInformation, ChainId}; use crate::types::{Chain, ExtendedBlockHeader, OutputOnChain, VerifiedBlockInformation}; //---------------------------------------------------------------------------------------------------- ReadRequest @@ -112,6 +112,27 @@ pub enum BlockchainWriteRequest { /// /// Input is an already verified block. WriteBlock(VerifiedBlockInformation), + /// Write an alternative block to the database, + /// + /// Input is the alternative block. + WriteAltBlock(AltBlockInformation), + /// A request to start the re-org process. + /// + /// The inner value is the [`ChainId`] of the alt-chain we want to re-org to. + /// + /// This will: + /// - pop blocks from the main chain + /// - retrieve all alt-blocks in this alt-chain + /// - flush all other alt blocks + StartReorg(ChainId), + /// A request to reverse the re-org process. + /// + /// The inner value is the [`ChainId`] of the old main chain. + /// + /// It is invalid to call this with a [`ChainId`] that was not returned from [`BlockchainWriteRequest::StartReorg`]. + ReverseReorg(ChainId), + /// A request to flush all alternative blocks. + FlushAltBlocks, } //---------------------------------------------------------------------------------------------------- Response @@ -198,11 +219,20 @@ pub enum BlockchainResponse { FindFirstUnknown(Option<(usize, usize)>), //------------------------------------------------------ Writes - /// Response to [`BlockchainWriteRequest::WriteBlock`]. - /// - /// This response indicates that the requested block has - /// successfully been written to the database without error. - WriteBlockOk, + /// A generic Ok response to indicate a request was successfully handled. + /// + /// currently the response for: + /// - [`BlockchainWriteRequest::WriteBlock`] + /// - [`BlockchainWriteRequest::ReverseReorg`] + /// - [`BlockchainWriteRequest::FlushAltBlocks`] + Ok, + /// The response for [`BlockchainWriteRequest::StartReorg`]. + StartReorg { + /// The [`ChainId`] of the old main chain blocks that were popped. + old_main_chain_id: ChainId, + /// The next alt chain blocks. + alt_chain: Vec + }, } //---------------------------------------------------------------------------------------------------- Tests From 029f439f0b5e48230c34fb7598a2f7d4a149f11d Mon Sep 17 00:00:00 2001 From: Boog900 <54e72d8a-345f-4599-bd90-c6b9bc7d0ec5@aleeas.com> Date: Sun, 1 Sep 2024 02:15:16 +0100 Subject: [PATCH 05/31] WIP: starting re-orgs --- .../ops/{alt_block.rs => alt_block/block.rs} | 134 ++++++------------ storage/blockchain/src/ops/alt_block/chain.rs | 63 ++++++++ storage/blockchain/src/ops/alt_block/mod.rs | 7 + storage/blockchain/src/ops/alt_block/tx.rs | 35 +++++ storage/blockchain/src/service/read.rs | 6 +- storage/blockchain/src/service/write.rs | 57 +++++++- storage/blockchain/src/tables.rs | 4 - types/src/blockchain.rs | 7 +- types/src/types.rs | 5 +- 9 files changed, 214 insertions(+), 104 deletions(-) rename storage/blockchain/src/ops/{alt_block.rs => alt_block/block.rs} (61%) create mode 100644 storage/blockchain/src/ops/alt_block/chain.rs create mode 100644 storage/blockchain/src/ops/alt_block/mod.rs create mode 100644 storage/blockchain/src/ops/alt_block/tx.rs diff --git a/storage/blockchain/src/ops/alt_block.rs b/storage/blockchain/src/ops/alt_block/block.rs similarity index 61% rename from storage/blockchain/src/ops/alt_block.rs rename to storage/blockchain/src/ops/alt_block/block.rs index 82a37ba8e..171cdd7b5 100644 --- a/storage/blockchain/src/ops/alt_block.rs +++ b/storage/blockchain/src/ops/alt_block/block.rs @@ -1,22 +1,20 @@ -use std::cmp::max; - +use crate::ops::alt_block::{ + add_alt_transaction_blob, check_add_alt_chain_info, get_alt_chain_history_ranges, + get_alt_transaction_blob, +}; +use crate::ops::block::{get_block_extended_header_from_height, get_block_info}; +use crate::tables::{Tables, TablesMut}; +use crate::types::{ + AltBlockHeight, AltTransactionInfo, BlockHash, BlockHeight, CompactAltBlockInfo, +}; use bytemuck::TransparentWrapper; -use cuprate_database::{DatabaseRo, DatabaseRw, RuntimeError, StorableVec}; +use cuprate_database::{RuntimeError, StorableVec}; use cuprate_helper::map::{combine_low_high_bits_to_u128, split_u128_into_low_high_bits}; use cuprate_types::{ AltBlockInformation, Chain, ChainId, ExtendedBlockHeader, HardFork, VerifiedTransactionInformation, }; -use monero_serai::block::BlockHeader; - -use crate::{ - ops::block::{get_block_extended_header_from_height, get_block_info}, - tables::{Tables, TablesMut}, - types::{ - AltBlockHeight, AltChainInfo, AltTransactionInfo, BlockHash, BlockHeight, - CompactAltBlockInfo, - }, -}; +use monero_serai::block::{Block, BlockHeader}; pub fn add_alt_block( alt_block: &AltBlockInformation, @@ -55,64 +53,48 @@ pub fn add_alt_block( StorableVec::wrap_ref(&alt_block.block_blob), )?; - for tx in &alt_block.txs { - add_alt_transaction(&tx, tables)?; + assert_eq!(alt_block.txs.len(), alt_block.block.transactions.len()); + for (tx, tx_hash) in alt_block.txs.iter().zip(&alt_block.block.transactions) { + add_alt_transaction_blob(tx_hash, StorableVec::wrap_ref(tx), tables)?; } Ok(()) } -pub fn add_alt_transaction( - tx: &VerifiedTransactionInformation, - tables: &mut impl TablesMut, -) -> Result<(), RuntimeError> { - if tables.tx_ids().get(&tx.tx_hash).is_ok() - || tables.alt_transaction_infos().get(&tx.tx_hash).is_ok() - { - return Ok(()); - } - - tables.alt_transaction_infos_mut().put( - &tx.tx_hash, - &AltTransactionInfo { - tx_weight: tx.tx_weight, - fee: tx.fee, - tx_hash: tx.tx_hash, - }, - )?; - - tables - .alt_transaction_blobs_mut() - .put(&tx.tx_hash, StorableVec::wrap_ref(&tx.tx_blob)) -} - -pub fn check_add_alt_chain_info( +pub fn get_alt_block( alt_block_height: &AltBlockHeight, - prev_hash: &BlockHash, - tables: &mut impl TablesMut, -) -> Result<(), RuntimeError> { - match tables.alt_chain_infos().get(&alt_block_height.chain_id) { - Ok(_) => return Ok(()), - Err(RuntimeError::KeyNotFound) => (), - Err(e) => return Err(e), - } - - let parent_chain = match tables.alt_block_heights().get(prev_hash) { - Ok(alt_parent_height) => Chain::Alt(alt_parent_height.chain_id.into()), - Err(RuntimeError::KeyNotFound) => Chain::Main, - Err(e) => return Err(e), - }; - - tables.alt_chain_infos_mut().put( - &alt_block_height.chain_id, - &AltChainInfo { - parent_chain: parent_chain.into(), - common_ancestor_height: alt_block_height.height - 1, - }, - ) + tables: &impl Tables, +) -> Result { + let block_info = tables.alt_blocks_info().get(alt_block_height)?; + + let block_blob = tables.alt_block_blobs().get(alt_block_height)?.0; + + let block = Block::read(&mut block_blob.as_slice())?; + + let txs = block + .transactions + .iter() + .map(|tx_hash| get_alt_transaction_blob(tx_hash, tables)) + .collect()?; + + Ok(AltBlockInformation { + block, + block_blob, + txs, + block_hash: block_info.block_hash, + pow_hash: block_info.pow_hash, + height: block_info.height, + weight: block_info.weight, + long_term_weight: block_info.long_term_weight, + cumulative_difficulty: combine_low_high_bits_to_u128( + block_info.cumulative_difficulty_low, + block_info.cumulative_difficulty_high, + ), + chain_id: alt_block_height.chain_id.into(), + }) } -pub fn alt_block_hash( +pub fn get_alt_block_hash( block_height: &BlockHeight, alt_chain: ChainId, tables: &mut impl Tables, @@ -152,37 +134,15 @@ pub fn alt_block_hash( } } -pub fn alt_extended_headers_in_range( +pub fn get_alt_extended_headers_in_range( range: std::ops::Range, alt_chain: ChainId, tables: &impl Tables, ) -> Result, RuntimeError> { // TODO: this function does not use rayon, however it probably should. - let mut ranges = Vec::with_capacity(5); let alt_chains = tables.alt_chain_infos(); - - let mut i = range.end; - let mut current_chain_id = alt_chain.into(); - while i > range.start { - let chain_info = alt_chains.get(¤t_chain_id)?; - - let start_height = max(range.start, chain_info.common_ancestor_height + 1); - - ranges.push((chain_info.parent_chain.into(), start_height..i)); - i = chain_info.common_ancestor_height; - - match chain_info.parent_chain.into() { - Chain::Main => { - ranges.push((Chain::Main, range.start..i)); - break; - } - Chain::Alt(alt_chain_id) => { - current_chain_id = alt_chain_id.into(); - continue; - } - } - } + let ranges = get_alt_chain_history_ranges(range, alt_chain, alt_chains)?; let res = ranges .into_iter() diff --git a/storage/blockchain/src/ops/alt_block/chain.rs b/storage/blockchain/src/ops/alt_block/chain.rs new file mode 100644 index 000000000..4259d4dc9 --- /dev/null +++ b/storage/blockchain/src/ops/alt_block/chain.rs @@ -0,0 +1,63 @@ +use crate::tables::{AltChainInfos, TablesMut}; +use crate::types::{AltBlockHeight, AltChainInfo, BlockHash, BlockHeight}; +use cuprate_database::{DatabaseRo, RuntimeError}; +use cuprate_types::{Chain, ChainId}; +use std::cmp::max; + +pub fn check_add_alt_chain_info( + alt_block_height: &AltBlockHeight, + prev_hash: &BlockHash, + tables: &mut impl TablesMut, +) -> Result<(), RuntimeError> { + match tables.alt_chain_infos().get(&alt_block_height.chain_id) { + Ok(_) => return Ok(()), + Err(RuntimeError::KeyNotFound) => (), + Err(e) => return Err(e), + } + + let parent_chain = match tables.alt_block_heights().get(prev_hash) { + Ok(alt_parent_height) => Chain::Alt(alt_parent_height.chain_id.into()), + Err(RuntimeError::KeyNotFound) => Chain::Main, + Err(e) => return Err(e), + }; + + tables.alt_chain_infos_mut().put( + &alt_block_height.chain_id, + &AltChainInfo { + parent_chain: parent_chain.into(), + common_ancestor_height: alt_block_height.height - 1, + }, + ) +} + +pub fn get_alt_chain_history_ranges( + range: std::ops::Range, + alt_chain: ChainId, + alt_chain_infos: &impl DatabaseRo, +) -> Result)>, RuntimeError> { + let mut ranges = Vec::with_capacity(5); + + let mut i = range.end; + let mut current_chain_id = alt_chain.into(); + while i > range.start { + let chain_info = alt_chain_infos.get(¤t_chain_id)?; + + let start_height = max(range.start, chain_info.common_ancestor_height + 1); + + ranges.push((chain_info.parent_chain.into(), start_height..i)); + i = chain_info.common_ancestor_height; + + match chain_info.parent_chain.into() { + Chain::Main => { + ranges.push((Chain::Main, range.start..i)); + break; + } + Chain::Alt(alt_chain_id) => { + current_chain_id = alt_chain_id.into(); + continue; + } + } + } + + Ok(ranges) +} diff --git a/storage/blockchain/src/ops/alt_block/mod.rs b/storage/blockchain/src/ops/alt_block/mod.rs new file mode 100644 index 000000000..8b2d1f172 --- /dev/null +++ b/storage/blockchain/src/ops/alt_block/mod.rs @@ -0,0 +1,7 @@ +mod block; +mod chain; +mod tx; + +pub use block::*; +pub use chain::*; +pub use tx::*; diff --git a/storage/blockchain/src/ops/alt_block/tx.rs b/storage/blockchain/src/ops/alt_block/tx.rs new file mode 100644 index 000000000..aad4dc3dd --- /dev/null +++ b/storage/blockchain/src/ops/alt_block/tx.rs @@ -0,0 +1,35 @@ +use crate::tables::{Tables, TablesMut}; +use crate::types::{AltTransactionInfo, TxHash}; +use bytemuck::TransparentWrapper; +use cuprate_database::{RuntimeError, StorableVec}; +use cuprate_types::VerifiedTransactionInformation; + +pub fn add_alt_transaction_blob( + tx_hash: &TxHash, + tx_block: &StorableVec, + tables: &mut impl TablesMut, +) -> Result<(), RuntimeError> { + if tables.tx_ids().get(&tx_hash).is_ok() || tables.alt_transaction_blobs().get(&tx_hash).is_ok() + { + return Ok(()); + } + + tables.alt_transaction_blobs_mut().put(&tx_hash, tx_block) +} + +pub fn get_alt_transaction_blob( + tx_hash: &TxHash, + tables: &impl Tables, +) -> Result, RuntimeError> { + match tables.alt_transaction_blobs().get(tx_hash) { + Ok(blob) => Ok(blob.0), + Err(RuntimeError::KeyNotFound) => { + let tx_id = tables.tx_ids().get(tx_hash)?; + + let blob = tables.tx_blobs().get(&tx_id)?; + + Ok(blob.0) + } + Err(e) => return Err(e), + } +} diff --git a/storage/blockchain/src/service/read.rs b/storage/blockchain/src/service/read.rs index eef40b5e5..70da01b3e 100644 --- a/storage/blockchain/src/service/read.rs +++ b/storage/blockchain/src/service/read.rs @@ -22,7 +22,7 @@ use cuprate_types::{ use crate::{ ops::{ - alt_block::{alt_block_hash, alt_extended_headers_in_range}, + alt_block::{get_alt_block_hash, get_alt_extended_headers_in_range}, block::{ block_exists, get_block_extended_header_from_height, get_block_height, get_block_info, }, @@ -200,7 +200,7 @@ fn block_hash(env: &ConcreteEnv, block_height: BlockHeight, chain: Chain) -> Res let block_hash = match chain { Chain::Main => get_block_info(&block_height, &table_block_infos)?.block_hash, Chain::Alt(chain) => { - alt_block_hash(&block_height, chain, &mut env_inner.open_tables(&tx_ro)?)? + get_alt_block_hash(&block_height, chain, &mut env_inner.open_tables(&tx_ro)?)? } }; @@ -284,7 +284,7 @@ fn block_extended_header_in_range( .collect::, RuntimeError>>()?, Chain::Alt(chain_id) => { let tx_ro = tx_ro.get_or_try(|| env_inner.tx_ro())?; - alt_extended_headers_in_range( + get_alt_extended_headers_in_range( range, chain_id, get_tables!(env_inner, tx_ro, tables)?.as_ref(), diff --git a/storage/blockchain/src/service/write.rs b/storage/blockchain/src/service/write.rs index a2cc71c7b..067ba7f18 100644 --- a/storage/blockchain/src/service/write.rs +++ b/storage/blockchain/src/service/write.rs @@ -7,7 +7,7 @@ use cuprate_database::{ConcreteEnv, Env, EnvInner, RuntimeError, TxRw}; use cuprate_database_service::DatabaseWriteHandle; use cuprate_types::{ blockchain::{BlockchainResponse, BlockchainWriteRequest}, - VerifiedBlockInformation, + AltBlockInformation, VerifiedBlockInformation, }; use crate::{ @@ -29,10 +29,10 @@ fn handle_blockchain_request( ) -> Result { match req { BlockchainWriteRequest::WriteBlock(block) => write_block(env, block), - BlockchainWriteRequest::WriteAltBlock(_) => todo!(), + BlockchainWriteRequest::WriteAltBlock(alt_block) => write_alt_block(env, alt_block), BlockchainWriteRequest::StartReorg(_) => todo!(), BlockchainWriteRequest::ReverseReorg(_) => todo!(), - BlockchainWriteRequest::FlushAltBlocks => todo!(), + BlockchainWriteRequest::FlushAltBlocks => flush_alt_blocks(env), } } @@ -59,7 +59,56 @@ fn write_block(env: &ConcreteEnv, block: &VerifiedBlockInformation) -> ResponseR match result { Ok(()) => { TxRw::commit(tx_rw)?; - Ok(BlockchainResponse::WriteBlockOk) + Ok(BlockchainResponse::Ok) + } + Err(e) => { + // INVARIANT: ensure database atomicity by aborting + // the transaction on `add_block()` failures. + TxRw::abort(tx_rw) + .expect("could not maintain database atomicity by aborting write transaction"); + Err(e) + } + } +} + +/// [`BlockchainWriteRequest::WriteAltBlock`]. +#[inline] +fn write_alt_block(env: &ConcreteEnv, block: &AltBlockInformation) -> ResponseResult { + let env_inner = env.env_inner(); + let tx_rw = env_inner.tx_rw()?; + + let result = { + let mut tables_mut = env_inner.open_tables_mut(&tx_rw)?; + crate::ops::alt_block::add_alt_block(block, &mut tables_mut) + }; + + match result { + Ok(()) => { + TxRw::commit(tx_rw)?; + Ok(BlockchainResponse::Ok) + } + Err(e) => { + // INVARIANT: ensure database atomicity by aborting + // the transaction on `add_block()` failures. + TxRw::abort(tx_rw) + .expect("could not maintain database atomicity by aborting write transaction"); + Err(e) + } + } +} + +/// [`BlockchainWriteRequest::FlushAltBlocks`]. +#[inline] +fn flush_alt_blocks(env: &ConcreteEnv) -> ResponseResult { + let env_inner = env.env_inner(); + let mut tx_rw = env_inner.tx_rw()?; + + let result = { crate::ops::alt_block::flush_alt_blocks(&env_inner, &mut tx_rw) }; + + match result { + Ok(()) => { + TxRw::commit(tx_rw)?; + Ok(BlockchainResponse::Ok) } Err(e) => { // INVARIANT: ensure database atomicity by aborting diff --git a/storage/blockchain/src/tables.rs b/storage/blockchain/src/tables.rs index 381430d73..deb957ea7 100644 --- a/storage/blockchain/src/tables.rs +++ b/storage/blockchain/src/tables.rs @@ -145,10 +145,6 @@ cuprate_database::define_tables! { 19 => AltTransactionBlobs, TxHash => TxBlob, - - 20 => AltTransactionInfos, - TxHash => AltTransactionInfo, - } //---------------------------------------------------------------------------------------------------- Tests diff --git a/types/src/blockchain.rs b/types/src/blockchain.rs index 48eab292e..33c3e8bd4 100644 --- a/types/src/blockchain.rs +++ b/types/src/blockchain.rs @@ -4,12 +4,12 @@ //! responses are also tested in Cuprate's blockchain database crate. //---------------------------------------------------------------------------------------------------- Import +use crate::types::{Chain, ExtendedBlockHeader, OutputOnChain, VerifiedBlockInformation}; +use crate::{AltBlockInformation, ChainId}; use std::{ collections::{HashMap, HashSet}, ops::Range, }; -use crate::{AltBlockInformation, ChainId}; -use crate::types::{Chain, ExtendedBlockHeader, OutputOnChain, VerifiedBlockInformation}; //---------------------------------------------------------------------------------------------------- ReadRequest /// A read request to the blockchain database. @@ -223,6 +223,7 @@ pub enum BlockchainResponse { /// /// currently the response for: /// - [`BlockchainWriteRequest::WriteBlock`] + /// - [`BlockchainWriteRequest::WriteAltBlock`] /// - [`BlockchainWriteRequest::ReverseReorg`] /// - [`BlockchainWriteRequest::FlushAltBlocks`] Ok, @@ -231,7 +232,7 @@ pub enum BlockchainResponse { /// The [`ChainId`] of the old main chain blocks that were popped. old_main_chain_id: ChainId, /// The next alt chain blocks. - alt_chain: Vec + alt_chain: Vec, }, } diff --git a/types/src/types.rs b/types/src/types.rs index da4422a15..cc4543e67 100644 --- a/types/src/types.rs +++ b/types/src/types.rs @@ -39,8 +39,7 @@ pub struct ExtendedBlockHeader { //---------------------------------------------------------------------------------------------------- VerifiedTransactionInformation /// Verified information of a transaction. /// -/// - If this is in a [`VerifiedBlockInformation`] this represents a valid transaction -/// - If this is in an [`AltBlockInformation`] this represents a potentially valid transaction +/// This represents a valid transaction #[derive(Clone, Debug, PartialEq, Eq)] pub struct VerifiedTransactionInformation { /// The transaction itself. @@ -121,7 +120,7 @@ pub struct AltBlockInformation { /// [`Block::serialize`]. pub block_blob: Vec, /// All the transactions in the block, excluding the [`Block::miner_transaction`]. - pub txs: Vec, + pub txs: Vec>, /// The block's hash. /// /// [`Block::hash`]. From 6927b05f81c0de3a82a406d11ff365bb3a4aa826 Mon Sep 17 00:00:00 2001 From: Boog900 <54e72d8a-345f-4599-bd90-c6b9bc7d0ec5@aleeas.com> Date: Fri, 6 Sep 2024 00:23:55 +0100 Subject: [PATCH 06/31] add last service request --- Cargo.lock | 1 + storage/blockchain/Cargo.toml | 3 +- storage/blockchain/src/free.rs | 32 +++++ storage/blockchain/src/ops/alt_block/block.rs | 21 ++-- storage/blockchain/src/ops/alt_block/chain.rs | 3 +- storage/blockchain/src/ops/alt_block/mod.rs | 17 +++ storage/blockchain/src/ops/alt_block/tx.rs | 44 +++++-- storage/blockchain/src/ops/block.rs | 61 ++++++--- storage/blockchain/src/service/free.rs | 37 +++++- storage/blockchain/src/service/write.rs | 118 +++++++++++++++++- storage/blockchain/src/tables.rs | 3 + storage/blockchain/src/types.rs | 5 +- types/src/blockchain.rs | 24 ++-- types/src/types.rs | 3 +- 14 files changed, 306 insertions(+), 66 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 77531897a..d5d64902a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -531,6 +531,7 @@ dependencies = [ "monero-serai", "pretty_assertions", "proptest", + "rand", "rayon", "serde", "tempfile", diff --git a/storage/blockchain/Cargo.toml b/storage/blockchain/Cargo.toml index 7e79305ac..b03ef0386 100644 --- a/storage/blockchain/Cargo.toml +++ b/storage/blockchain/Cargo.toml @@ -25,11 +25,12 @@ cuprate-database = { path = "../database" } cuprate-database-service = { path = "../service" } cuprate-helper = { path = "../../helper", features = ["fs", "thread", "map"] } cuprate-types = { path = "../../types", features = ["blockchain"] } +cuprate-pruning = { path = "../../pruning" } bitflags = { workspace = true, features = ["std", "serde", "bytemuck"] } bytemuck = { workspace = true, features = ["must_cast", "derive", "min_const_generics", "extern_crate_alloc"] } curve25519-dalek = { workspace = true } -cuprate-pruning = { path = "../../pruning" } +rand = { workspace = true } monero-serai = { workspace = true, features = ["std"] } serde = { workspace = true, optional = true } diff --git a/storage/blockchain/src/free.rs b/storage/blockchain/src/free.rs index 8288e65f7..20d56226d 100644 --- a/storage/blockchain/src/free.rs +++ b/storage/blockchain/src/free.rs @@ -1,5 +1,6 @@ //! General free functions (related to the database). +use monero_serai::transaction::{Input, Transaction}; //---------------------------------------------------------------------------------------------------- Import use cuprate_database::{ConcreteEnv, Env, EnvInner, InitError, RuntimeError, TxRw}; @@ -61,6 +62,37 @@ pub fn open(config: Config) -> Result { Ok(env) } +//---------------------------------------------------------------------------------------------------- Tx Fee +/// Calculates the fee of the [`Transaction`]. +/// +/// # Panics +/// This will panic if the inputs overflow or the transaction outputs too much. +pub(crate) fn tx_fee(tx: &Transaction) -> u64 { + let mut fee = 0_u64; + + match &tx { + Transaction::V1 { prefix, .. } => { + for input in &prefix.inputs { + match input { + Input::Gen(_) => return 0, + Input::ToKey { amount, .. } => { + fee = fee.checked_add(amount.unwrap_or(0)).unwrap(); + } + } + } + + for output in &prefix.outputs { + fee.checked_sub(output.amount.unwrap_or(0)).unwrap(); + } + } + Transaction::V2 { proofs, .. } => { + fee = proofs.as_ref().unwrap().base.fee; + } + }; + + fee +} + //---------------------------------------------------------------------------------------------------- Tests #[cfg(test)] mod test { diff --git a/storage/blockchain/src/ops/alt_block/block.rs b/storage/blockchain/src/ops/alt_block/block.rs index 171cdd7b5..a429eab84 100644 --- a/storage/blockchain/src/ops/alt_block/block.rs +++ b/storage/blockchain/src/ops/alt_block/block.rs @@ -1,19 +1,14 @@ use crate::ops::alt_block::{ add_alt_transaction_blob, check_add_alt_chain_info, get_alt_chain_history_ranges, - get_alt_transaction_blob, + get_alt_transaction, }; use crate::ops::block::{get_block_extended_header_from_height, get_block_info}; use crate::tables::{Tables, TablesMut}; -use crate::types::{ - AltBlockHeight, AltTransactionInfo, BlockHash, BlockHeight, CompactAltBlockInfo, -}; +use crate::types::{AltBlockHeight, BlockHash, BlockHeight, CompactAltBlockInfo}; use bytemuck::TransparentWrapper; -use cuprate_database::{RuntimeError, StorableVec}; +use cuprate_database::{DatabaseRo, DatabaseRw, RuntimeError, StorableVec}; use cuprate_helper::map::{combine_low_high_bits_to_u128, split_u128_into_low_high_bits}; -use cuprate_types::{ - AltBlockInformation, Chain, ChainId, ExtendedBlockHeader, HardFork, - VerifiedTransactionInformation, -}; +use cuprate_types::{AltBlockInformation, Chain, ChainId, ExtendedBlockHeader, HardFork}; use monero_serai::block::{Block, BlockHeader}; pub fn add_alt_block( @@ -54,8 +49,8 @@ pub fn add_alt_block( )?; assert_eq!(alt_block.txs.len(), alt_block.block.transactions.len()); - for (tx, tx_hash) in alt_block.txs.iter().zip(&alt_block.block.transactions) { - add_alt_transaction_blob(tx_hash, StorableVec::wrap_ref(tx), tables)?; + for tx in alt_block.txs.iter() { + add_alt_transaction_blob(tx, tables)?; } Ok(()) @@ -74,8 +69,8 @@ pub fn get_alt_block( let txs = block .transactions .iter() - .map(|tx_hash| get_alt_transaction_blob(tx_hash, tables)) - .collect()?; + .map(|tx_hash| get_alt_transaction(tx_hash, tables)) + .collect::>()?; Ok(AltBlockInformation { block, diff --git a/storage/blockchain/src/ops/alt_block/chain.rs b/storage/blockchain/src/ops/alt_block/chain.rs index 4259d4dc9..1162a9cde 100644 --- a/storage/blockchain/src/ops/alt_block/chain.rs +++ b/storage/blockchain/src/ops/alt_block/chain.rs @@ -1,6 +1,6 @@ use crate::tables::{AltChainInfos, TablesMut}; use crate::types::{AltBlockHeight, AltChainInfo, BlockHash, BlockHeight}; -use cuprate_database::{DatabaseRo, RuntimeError}; +use cuprate_database::{DatabaseRo, DatabaseRw, RuntimeError}; use cuprate_types::{Chain, ChainId}; use std::cmp::max; @@ -26,6 +26,7 @@ pub fn check_add_alt_chain_info( &AltChainInfo { parent_chain: parent_chain.into(), common_ancestor_height: alt_block_height.height - 1, + chain_height: alt_block_height.height, }, ) } diff --git a/storage/blockchain/src/ops/alt_block/mod.rs b/storage/blockchain/src/ops/alt_block/mod.rs index 8b2d1f172..72e0933ef 100644 --- a/storage/blockchain/src/ops/alt_block/mod.rs +++ b/storage/blockchain/src/ops/alt_block/mod.rs @@ -5,3 +5,20 @@ mod tx; pub use block::*; pub use chain::*; pub use tx::*; + +pub fn flush_alt_blocks<'a, E: cuprate_database::EnvInner<'a>>( + env_inner: &E, + tx_rw: &mut E::Rw<'_>, +) -> Result<(), cuprate_database::RuntimeError> { + use crate::tables::{ + AltBlockBlobs, AltBlockHeights, AltBlocksInfo, AltChainInfos, AltTransactionBlobs, + AltTransactionInfos, + }; + + env_inner.clear_db::(tx_rw)?; + env_inner.clear_db::(tx_rw)?; + env_inner.clear_db::(tx_rw)?; + env_inner.clear_db::(tx_rw)?; + env_inner.clear_db::(tx_rw)?; + env_inner.clear_db::(tx_rw) +} diff --git a/storage/blockchain/src/ops/alt_block/tx.rs b/storage/blockchain/src/ops/alt_block/tx.rs index aad4dc3dd..a49c72ae7 100644 --- a/storage/blockchain/src/ops/alt_block/tx.rs +++ b/storage/blockchain/src/ops/alt_block/tx.rs @@ -1,35 +1,57 @@ use crate::tables::{Tables, TablesMut}; use crate::types::{AltTransactionInfo, TxHash}; use bytemuck::TransparentWrapper; -use cuprate_database::{RuntimeError, StorableVec}; +use cuprate_database::{DatabaseRo, DatabaseRw, RuntimeError, StorableVec}; use cuprate_types::VerifiedTransactionInformation; +use monero_serai::transaction::Transaction; pub fn add_alt_transaction_blob( - tx_hash: &TxHash, - tx_block: &StorableVec, + tx: &VerifiedTransactionInformation, tables: &mut impl TablesMut, ) -> Result<(), RuntimeError> { - if tables.tx_ids().get(&tx_hash).is_ok() || tables.alt_transaction_blobs().get(&tx_hash).is_ok() + tables.alt_transaction_infos_mut().put( + &tx.tx_hash, + &AltTransactionInfo { + tx_weight: tx.tx_weight, + fee: tx.fee, + tx_hash: tx.tx_hash, + }, + )?; + + if tables.tx_ids().get(&tx.tx_hash).is_ok() + || tables.alt_transaction_blobs().get(&tx.tx_hash).is_ok() { return Ok(()); } - tables.alt_transaction_blobs_mut().put(&tx_hash, tx_block) + tables + .alt_transaction_blobs_mut() + .put(&tx.tx_hash, StorableVec::wrap_ref(&tx.tx_blob)) } -pub fn get_alt_transaction_blob( +pub fn get_alt_transaction( tx_hash: &TxHash, tables: &impl Tables, -) -> Result, RuntimeError> { - match tables.alt_transaction_blobs().get(tx_hash) { - Ok(blob) => Ok(blob.0), +) -> Result { + let tx_info = tables.alt_transaction_infos().get(tx_hash)?; + + let tx_blob = match tables.alt_transaction_blobs().get(tx_hash) { + Ok(blob) => blob.0, Err(RuntimeError::KeyNotFound) => { let tx_id = tables.tx_ids().get(tx_hash)?; let blob = tables.tx_blobs().get(&tx_id)?; - Ok(blob.0) + blob.0 } Err(e) => return Err(e), - } + }; + + Ok(VerifiedTransactionInformation { + tx: Transaction::read(&mut tx_blob.as_slice()).unwrap(), + tx_blob, + tx_weight: tx_info.tx_weight, + fee: tx_info.fee, + tx_hash: tx_info.tx_hash, + }) } diff --git a/storage/blockchain/src/ops/block.rs b/storage/blockchain/src/ops/block.rs index 2e110fedf..5cb3b4bcc 100644 --- a/storage/blockchain/src/ops/block.rs +++ b/storage/blockchain/src/ops/block.rs @@ -8,8 +8,13 @@ use cuprate_database::{ RuntimeError, StorableVec, {DatabaseRo, DatabaseRw}, }; use cuprate_helper::map::{combine_low_high_bits_to_u128, split_u128_into_low_high_bits}; -use cuprate_types::{ExtendedBlockHeader, HardFork, VerifiedBlockInformation}; +use cuprate_types::{ + AltBlockInformation, ChainId, ExtendedBlockHeader, HardFork, VerifiedBlockInformation, + VerifiedTransactionInformation, +}; +use crate::free::tx_fee; +use crate::ops::alt_block; use crate::{ ops::{ blockchain::{chain_height, cumulative_generated_coins}, @@ -106,9 +111,8 @@ pub fn add_block( cumulative_rct_outs, timestamp: block.block.header.timestamp, block_hash: block.block_hash, - // INVARIANT: #[cfg] @ lib.rs asserts `usize == u64` - weight: block.weight as u64, - long_term_weight: block.long_term_weight as u64, + weight: block.weight, + long_term_weight: block.long_term_weight, }, )?; @@ -135,17 +139,15 @@ pub fn add_block( /// will be returned if there are no blocks left. // no inline, too big pub fn pop_block( + move_to_alt_chain: Option, tables: &mut impl TablesMut, ) -> Result<(BlockHeight, BlockHash, Block), RuntimeError> { //------------------------------------------------------ Block Info // Remove block data from tables. - let (block_height, block_hash) = { - let (block_height, block_info) = tables.block_infos_mut().pop_last()?; - (block_height, block_info.block_hash) - }; + let (block_height, block_info) = tables.block_infos_mut().pop_last()?; // Block heights. - tables.block_heights_mut().delete(&block_hash)?; + tables.block_heights_mut().delete(&block_info.block_hash)?; // Block blobs. // We deserialize the block blob into a `Block`, such @@ -154,12 +156,42 @@ pub fn pop_block( let block = Block::read(&mut block_blob.as_slice())?; //------------------------------------------------------ Transaction / Outputs / Key Images + let mut txs = Vec::with_capacity(block.transactions.len()); + remove_tx(&block.miner_transaction.hash(), tables)?; for tx_hash in &block.transactions { - remove_tx(tx_hash, tables)?; + let (_, tx) = remove_tx(tx_hash, tables)?; + + if move_to_alt_chain.is_some() { + txs.push(VerifiedTransactionInformation { + tx_weight: tx.weight(), + tx_blob: tx.serialize(), + tx_hash: tx.hash(), + fee: tx_fee(&tx), + tx, + }) + } + } + + if let Some(chain_id) = move_to_alt_chain { + alt_block::add_alt_block( + &AltBlockInformation { + block: block.clone(), + block_blob, + txs, + block_hash: block_info.block_hash, + pow_hash: [255; 32], + height: block_height, + weight: block_info.weight, + long_term_weight: block_info.long_term_weight, + cumulative_difficulty: 0, + chain_id, + }, + tables, + )?; } - Ok((block_height, block_hash, block)) + Ok((block_height, block_info.block_hash, block)) } //---------------------------------------------------------------------------------------------------- `get_block_extended_header_*` @@ -205,8 +237,8 @@ pub fn get_block_extended_header_from_height( .expect("Stored block must have a valid hard-fork"), vote: block_header.hardfork_signal, timestamp: block_header.timestamp, - block_weight: block_info.weight as usize, - long_term_weight: block_info.long_term_weight as usize, + block_weight: block_info.weight, + long_term_weight: block_info.long_term_weight, }) } @@ -412,7 +444,8 @@ mod test { for block_hash in block_hashes.into_iter().rev() { println!("pop_block(): block_hash: {}", hex::encode(block_hash)); - let (_popped_height, popped_hash, _popped_block) = pop_block(&mut tables).unwrap(); + let (_popped_height, popped_hash, _popped_block) = + pop_block(None, &mut tables).unwrap(); assert_eq!(block_hash, popped_hash); diff --git a/storage/blockchain/src/service/free.rs b/storage/blockchain/src/service/free.rs index e748bbbe4..aa8238f95 100644 --- a/storage/blockchain/src/service/free.rs +++ b/storage/blockchain/src/service/free.rs @@ -3,13 +3,13 @@ //---------------------------------------------------------------------------------------------------- Import use std::sync::Arc; -use cuprate_database::{ConcreteEnv, InitError}; - use crate::service::{init_read_service, init_write_service}; use crate::{ config::Config, service::types::{BlockchainReadHandle, BlockchainWriteHandle}, }; +use cuprate_database::{ConcreteEnv, InitError}; +use cuprate_types::{AltBlockInformation, VerifiedBlockInformation}; //---------------------------------------------------------------------------------------------------- Init #[cold] @@ -81,6 +81,39 @@ pub(super) const fn compact_history_genesis_not_included INITIAL_BLOCKS && !(top_block_height - INITIAL_BLOCKS + 2).is_power_of_two() } +//---------------------------------------------------------------------------------------------------- Compact history +pub(super) fn map_valid_alt_block_to_verified_block( + alt_block: AltBlockInformation, +) -> VerifiedBlockInformation { + let total_fees = alt_block.txs.iter().map(|tx| tx.fee).sum::(); + let total_miner_output = alt_block + .block + .miner_transaction + .prefix() + .outputs + .iter() + .map(|out| out.amount.unwrap_or(0)) + .sum::(); + + VerifiedBlockInformation { + block: alt_block.block, + block_blob: alt_block.block_blob, + txs: alt_block + .txs + .into_iter() + .map(TryInto::try_into) + .collect::>() + .unwrap(), + block_hash: alt_block.block_hash, + pow_hash: alt_block.pow_hash, + height: alt_block.height, + generated_coins: total_miner_output - total_fees, + weight: alt_block.weight, + long_term_weight: alt_block.long_term_weight, + cumulative_difficulty: alt_block.cumulative_difficulty, + } +} + //---------------------------------------------------------------------------------------------------- Tests #[cfg(test)] diff --git a/storage/blockchain/src/service/write.rs b/storage/blockchain/src/service/write.rs index 067ba7f18..95124d41a 100644 --- a/storage/blockchain/src/service/write.rs +++ b/storage/blockchain/src/service/write.rs @@ -1,18 +1,20 @@ //! Database writer thread definitions and logic. - //---------------------------------------------------------------------------------------------------- Import use std::sync::Arc; -use cuprate_database::{ConcreteEnv, Env, EnvInner, RuntimeError, TxRw}; +use cuprate_database::{ConcreteEnv, DatabaseRo, DatabaseRw, Env, EnvInner, RuntimeError, TxRw}; use cuprate_database_service::DatabaseWriteHandle; use cuprate_types::{ blockchain::{BlockchainResponse, BlockchainWriteRequest}, - AltBlockInformation, VerifiedBlockInformation, + AltBlockInformation, Chain, ChainId, VerifiedBlockInformation, }; +use crate::service::free::map_valid_alt_block_to_verified_block; +use crate::types::AltBlockHeight; use crate::{ service::types::{BlockchainWriteHandle, ResponseResult}, - tables::OpenTables, + tables::{OpenTables, Tables, TablesMut}, + types::AltChainInfo, }; //---------------------------------------------------------------------------------------------------- init_write_service @@ -30,8 +32,10 @@ fn handle_blockchain_request( match req { BlockchainWriteRequest::WriteBlock(block) => write_block(env, block), BlockchainWriteRequest::WriteAltBlock(alt_block) => write_alt_block(env, alt_block), - BlockchainWriteRequest::StartReorg(_) => todo!(), - BlockchainWriteRequest::ReverseReorg(_) => todo!(), + BlockchainWriteRequest::PopBlocks(numb_blocks) => pop_blocks(env, *numb_blocks), + BlockchainWriteRequest::ReverseReorg(old_main_chain_id) => { + reverse_reorg(env, *old_main_chain_id) + } BlockchainWriteRequest::FlushAltBlocks => flush_alt_blocks(env), } } @@ -97,6 +101,108 @@ fn write_alt_block(env: &ConcreteEnv, block: &AltBlockInformation) -> ResponseRe } } +/// [`BlockchainWriteRequest::PopBlocks`]. +fn pop_blocks(env: &ConcreteEnv, numb_blocks: usize) -> ResponseResult { + let env_inner = env.env_inner(); + let mut tx_rw = env_inner.tx_rw()?; + + let result = { + crate::ops::alt_block::flush_alt_blocks(&env_inner, &mut tx_rw)?; + + let mut tables_mut = env_inner.open_tables_mut(&tx_rw)?; + + let old_main_chain_id = ChainId(rand::random()); + + let mut last_block_height = 0; + for _ in 0..numb_blocks { + (last_block_height, _, _) = + crate::ops::block::pop_block(Some(old_main_chain_id), &mut tables_mut)?; + } + + tables_mut.alt_chain_infos_mut().put( + &old_main_chain_id.into(), + &AltChainInfo { + parent_chain: Chain::Main.into(), + common_ancestor_height: last_block_height - 1, + chain_height: last_block_height + numb_blocks, + }, + )?; + + Ok(old_main_chain_id) + }; + + match result { + Ok(old_main_chain_id) => { + TxRw::commit(tx_rw)?; + Ok(BlockchainResponse::PopBlocks(old_main_chain_id)) + } + Err(e) => { + // INVARIANT: ensure database atomicity by aborting + // the transaction on `add_block()` failures. + TxRw::abort(tx_rw) + .expect("could not maintain database atomicity by aborting write transaction"); + Err(e) + } + } +} + +/// [`BlockchainWriteRequest::ReverseReorg`]. +fn reverse_reorg(env: &ConcreteEnv, chain_id: ChainId) -> ResponseResult { + let env_inner = env.env_inner(); + let tx_rw = env_inner.tx_rw()?; + + let result = { + let mut tables_mut = env_inner.open_tables_mut(&tx_rw)?; + + let chain_info = tables_mut.alt_chain_infos().get(&chain_id.into())?; + assert_eq!(Chain::from(chain_info.parent_chain), Chain::Main); + + let tob_block_height = + crate::ops::blockchain::top_block_height(tables_mut.block_heights())?; + + for _ in chain_info.common_ancestor_height..tob_block_height { + crate::ops::block::pop_block(None, &mut tables_mut)?; + } + + // Rust borrow rules requires us to collect into a Vec first before looping over the Vec. + let alt_blocks = (chain_info.common_ancestor_height..chain_info.chain_height) + .map(|height| { + crate::ops::alt_block::get_alt_block( + &AltBlockHeight { + chain_id: chain_id.into(), + height, + }, + &tables_mut, + ) + }) + .collect::>(); + + for res_alt_block in alt_blocks { + let alt_block = res_alt_block?; + + let verified_block = map_valid_alt_block_to_verified_block(alt_block); + + crate::ops::block::add_block(&verified_block, &mut tables_mut)?; + } + + Ok(()) + }; + + match result { + Ok(()) => { + TxRw::commit(tx_rw)?; + Ok(BlockchainResponse::Ok) + } + Err(e) => { + // INVARIANT: ensure database atomicity by aborting + // the transaction on `add_block()` failures. + TxRw::abort(tx_rw) + .expect("could not maintain database atomicity by aborting write transaction"); + Err(e) + } + } +} + /// [`BlockchainWriteRequest::FlushAltBlocks`]. #[inline] fn flush_alt_blocks(env: &ConcreteEnv) -> ResponseResult { diff --git a/storage/blockchain/src/tables.rs b/storage/blockchain/src/tables.rs index deb957ea7..fa568ae6b 100644 --- a/storage/blockchain/src/tables.rs +++ b/storage/blockchain/src/tables.rs @@ -145,6 +145,9 @@ cuprate_database::define_tables! { 19 => AltTransactionBlobs, TxHash => TxBlob, + + 20 => AltTransactionInfos, + TxHash => AltTransactionInfo, } //---------------------------------------------------------------------------------------------------- Tests diff --git a/storage/blockchain/src/types.rs b/storage/blockchain/src/types.rs index 88ece10b0..14917249f 100644 --- a/storage/blockchain/src/types.rs +++ b/storage/blockchain/src/types.rs @@ -189,7 +189,7 @@ pub struct BlockInfo { /// The adjusted block size, in bytes. /// /// See [`block_weight`](https://monero-book.cuprate.org/consensus_rules/blocks/weights.html#blocks-weight). - pub weight: u64, + pub weight: usize, /// Least-significant 64 bits of the 128-bit cumulative difficulty. pub cumulative_difficulty_low: u64, /// Most-significant 64 bits of the 128-bit cumulative difficulty. @@ -201,7 +201,7 @@ pub struct BlockInfo { /// The long term block weight, based on the median weight of the preceding `100_000` blocks. /// /// See [`long_term_weight`](https://monero-book.cuprate.org/consensus_rules/blocks/weights.html#long-term-block-weight). - pub long_term_weight: u64, + pub long_term_weight: usize, } //---------------------------------------------------------------------------------------------------- OutputFlags @@ -381,6 +381,7 @@ impl Key for RawChainId {} pub struct AltChainInfo { pub parent_chain: RawChain, pub common_ancestor_height: usize, + pub chain_height: usize, } //---------------------------------------------------------------------------------------------------- AltBlockHeight diff --git a/types/src/blockchain.rs b/types/src/blockchain.rs index 33c3e8bd4..c2a5517da 100644 --- a/types/src/blockchain.rs +++ b/types/src/blockchain.rs @@ -116,20 +116,17 @@ pub enum BlockchainWriteRequest { /// /// Input is the alternative block. WriteAltBlock(AltBlockInformation), - /// A request to start the re-org process. + /// A request to pop some blocks from the top of the main chain /// - /// The inner value is the [`ChainId`] of the alt-chain we want to re-org to. + /// Input is the amount of blocks to pop. /// - /// This will: - /// - pop blocks from the main chain - /// - retrieve all alt-blocks in this alt-chain - /// - flush all other alt blocks - StartReorg(ChainId), + /// This request flush all alt-chains from the cache before adding the popped blocks to the alt cache. + PopBlocks(usize), /// A request to reverse the re-org process. /// /// The inner value is the [`ChainId`] of the old main chain. /// - /// It is invalid to call this with a [`ChainId`] that was not returned from [`BlockchainWriteRequest::StartReorg`]. + /// It is invalid to call this with a [`ChainId`] that was not returned from [`BlockchainWriteRequest::PopBlocks`]. ReverseReorg(ChainId), /// A request to flush all alternative blocks. FlushAltBlocks, @@ -227,13 +224,10 @@ pub enum BlockchainResponse { /// - [`BlockchainWriteRequest::ReverseReorg`] /// - [`BlockchainWriteRequest::FlushAltBlocks`] Ok, - /// The response for [`BlockchainWriteRequest::StartReorg`]. - StartReorg { - /// The [`ChainId`] of the old main chain blocks that were popped. - old_main_chain_id: ChainId, - /// The next alt chain blocks. - alt_chain: Vec, - }, + /// The response for [`BlockchainWriteRequest::PopBlocks`]. + /// + /// The inner value is the alt-chain ID for the old main chain blocks. + PopBlocks(ChainId), } //---------------------------------------------------------------------------------------------------- Tests diff --git a/types/src/types.rs b/types/src/types.rs index cc4543e67..c6e83d093 100644 --- a/types/src/types.rs +++ b/types/src/types.rs @@ -79,6 +79,7 @@ pub struct VerifiedBlockInformation { /// [`Block::hash`]. pub block_hash: [u8; 32], /// The block's proof-of-work hash. + // TODO: make this an option. pub pow_hash: [u8; 32], /// The block's height. pub height: usize, @@ -120,7 +121,7 @@ pub struct AltBlockInformation { /// [`Block::serialize`]. pub block_blob: Vec, /// All the transactions in the block, excluding the [`Block::miner_transaction`]. - pub txs: Vec>, + pub txs: Vec, /// The block's hash. /// /// [`Block::hash`]. From 21e4b3a20a56323961f65e100ca826f0677a41e5 Mon Sep 17 00:00:00 2001 From: Boog900 <54e72d8a-345f-4599-bd90-c6b9bc7d0ec5@aleeas.com> Date: Fri, 6 Sep 2024 00:26:36 +0100 Subject: [PATCH 07/31] commit Cargo.lock --- Cargo.lock | 39 +++++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d5d64902a..e277e3f7d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,12 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + [[package]] name = "ahash" version = "0.8.11" @@ -160,7 +166,7 @@ dependencies = [ "cc", "cfg-if", "libc", - "miniz_oxide", + "miniz_oxide 0.7.3", "object", "rustc-demangle", ] @@ -1080,12 +1086,12 @@ checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" [[package]] name = "flate2" -version = "1.0.30" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" +checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" dependencies = [ "crc32fast", - "miniz_oxide", + "miniz_oxide 0.8.0", ] [[package]] @@ -1239,9 +1245,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa82e28a107a8cc405f0839610bdc9b15f1e25ec7d696aa5cf173edbcb1486ab" +checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" dependencies = [ "atomic-waker", "bytes", @@ -1735,6 +1741,15 @@ dependencies = [ "adler", ] +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + [[package]] name = "mio" version = "0.8.11" @@ -2397,9 +2412,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" +checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" [[package]] name = "rustls-webpki" @@ -2958,9 +2973,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "ureq" -version = "2.10.0" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72139d247e5f97a3eff96229a7ae85ead5328a39efe76f8bf5a06313d505b6ea" +checksum = "b74fc6b57825be3373f7054754755f03ac3a8f5d70015ccad699ba2029956f4a" dependencies = [ "base64", "flate2", @@ -3083,9 +3098,9 @@ checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "webpki-roots" -version = "0.26.3" +version = "0.26.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" +checksum = "0bd24728e5af82c6c4ec1b66ac4844bdf8156257fccda846ec58b42cd0cdbe6a" dependencies = [ "rustls-pki-types", ] From 123aedd6a986f7884efdc922eca046c86b7169ae Mon Sep 17 00:00:00 2001 From: Boog900 <54e72d8a-345f-4599-bd90-c6b9bc7d0ec5@aleeas.com> Date: Fri, 6 Sep 2024 02:39:40 +0100 Subject: [PATCH 08/31] add test --- storage/blockchain/src/ops/alt_block/block.rs | 100 +++++++++++++++++- storage/blockchain/src/ops/alt_block/chain.rs | 2 +- storage/blockchain/src/ops/block.rs | 2 +- storage/blockchain/src/ops/mod.rs | 2 +- storage/blockchain/src/service/mod.rs | 2 +- storage/blockchain/src/service/tests.rs | 2 +- storage/blockchain/src/tests.rs | 16 +++ 7 files changed, 120 insertions(+), 6 deletions(-) diff --git a/storage/blockchain/src/ops/alt_block/block.rs b/storage/blockchain/src/ops/alt_block/block.rs index a429eab84..83d04ba74 100644 --- a/storage/blockchain/src/ops/alt_block/block.rs +++ b/storage/blockchain/src/ops/alt_block/block.rs @@ -171,7 +171,7 @@ pub fn get_alt_block_extended_header_from_height( let block_header = BlockHeader::read(&mut block_blob.as_slice())?; Ok(ExtendedBlockHeader { - version: HardFork::from_version(0).expect("Block in DB must have correct version"), + version: HardFork::from_version(block_header.hardfork_version).expect("Block in DB must have correct version"), vote: block_header.hardfork_version, timestamp: block_header.timestamp, cumulative_difficulty: combine_low_high_bits_to_u128( @@ -182,3 +182,101 @@ pub fn get_alt_block_extended_header_from_height( long_term_weight: block_info.long_term_weight, }) } + +#[cfg(test)] +mod tests { + use std::num::NonZero; + use cuprate_database::{Env, EnvInner, TxRw}; + use cuprate_test_utils::data::{BLOCK_V1_TX2, BLOCK_V9_TX3, BLOCK_V16_TX0}; + use cuprate_types::ChainId; + use crate::ops::alt_block::{add_alt_block, flush_alt_blocks, get_alt_block, get_alt_extended_headers_in_range}; + use crate::ops::block::{add_block, pop_block}; + use crate::tables::OpenTables; + use crate::tests::{assert_all_tables_are_empty, map_verified_block_to_alt, tmp_concrete_env}; + use crate::types::AltBlockHeight; + + #[test] + fn all_alt_blocks() { + let (env, _tmp) = tmp_concrete_env(); + let env_inner = env.env_inner(); + assert_all_tables_are_empty(&env); + + let chain_id = ChainId(NonZero::new(1).unwrap()).into(); + + // Add initial block. + { + let tx_rw = env_inner.tx_rw().unwrap(); + let mut tables = env_inner.open_tables_mut(&tx_rw).unwrap(); + + let mut initial_block = BLOCK_V1_TX2.clone(); + initial_block.height = 0; + + add_block(&initial_block, &mut tables).unwrap(); + + drop(tables); + TxRw::commit(tx_rw).unwrap(); + } + + let alt_blocks = [ + map_verified_block_to_alt(BLOCK_V9_TX3.clone(), chain_id), + map_verified_block_to_alt(BLOCK_V16_TX0.clone(), chain_id), + ]; + + // Add alt-blocks + { + let tx_rw = env_inner.tx_rw().unwrap(); + let mut tables = env_inner.open_tables_mut(&tx_rw).unwrap(); + + let mut prev_hash = BLOCK_V1_TX2.block_hash; + for (i, mut alt_block) in alt_blocks.into_iter().enumerate() { + let height = i + 1; + + alt_block.height = height; + alt_block.block.header.previous = prev_hash; + alt_block.block_blob = alt_block.block.serialize(); + + add_alt_block(&alt_block, &mut tables).unwrap(); + + let alt_height = AltBlockHeight { + chain_id: chain_id.into(), + height, + }; + + let alt_block_2 = get_alt_block(&alt_height, &tables).unwrap(); + assert_eq!(alt_block.block, alt_block_2.block); + + let headers = get_alt_extended_headers_in_range(0..(height + 1), chain_id, &tables).unwrap(); + assert_eq!(headers.len(), height); + + let last_header = headers.last().unwrap(); + assert_eq!(last_header.timestamp, alt_block.block.header.timestamp); + assert_eq!(last_header.block_weight, alt_block.weight); + assert_eq!(last_header.long_term_weight, alt_block.long_term_weight); + assert_eq!(last_header.cumulative_difficulty, alt_block.cumulative_difficulty); + assert_eq!(last_header.version.as_u8(), alt_block.block.header.hardfork_version); + assert_eq!(last_header.vote, alt_block.block.header.hardfork_signal); + + prev_hash = alt_block.block_hash; + } + + drop(tables); + TxRw::commit(tx_rw).unwrap(); + } + + + { + let mut tx_rw = env_inner.tx_rw().unwrap(); + + flush_alt_blocks(&env_inner, &mut tx_rw).unwrap(); + + let mut tables = env_inner.open_tables_mut(&tx_rw).unwrap(); + pop_block(None, &mut tables).unwrap(); + + drop(tables); + TxRw::commit(tx_rw).unwrap(); + } + + assert_all_tables_are_empty(&env); + } + +} diff --git a/storage/blockchain/src/ops/alt_block/chain.rs b/storage/blockchain/src/ops/alt_block/chain.rs index 1162a9cde..166a294a5 100644 --- a/storage/blockchain/src/ops/alt_block/chain.rs +++ b/storage/blockchain/src/ops/alt_block/chain.rs @@ -45,7 +45,7 @@ pub fn get_alt_chain_history_ranges( let start_height = max(range.start, chain_info.common_ancestor_height + 1); - ranges.push((chain_info.parent_chain.into(), start_height..i)); + ranges.push((Chain::Alt(current_chain_id.into()), start_height..i)); i = chain_info.common_ancestor_height; match chain_info.parent_chain.into() { diff --git a/storage/blockchain/src/ops/block.rs b/storage/blockchain/src/ops/block.rs index 229d35e1d..b0997f760 100644 --- a/storage/blockchain/src/ops/block.rs +++ b/storage/blockchain/src/ops/block.rs @@ -180,7 +180,7 @@ pub fn pop_block( block_blob, txs, block_hash: block_info.block_hash, - pow_hash: [255; 32], + pow_hash: [0; 32], height: block_height, weight: block_info.weight, long_term_weight: block_info.long_term_weight, diff --git a/storage/blockchain/src/ops/mod.rs b/storage/blockchain/src/ops/mod.rs index 8a8f0f158..285aa2440 100644 --- a/storage/blockchain/src/ops/mod.rs +++ b/storage/blockchain/src/ops/mod.rs @@ -94,7 +94,7 @@ //! // Read the data, assert it is correct. //! let tx_rw = env_inner.tx_rw()?; //! let mut tables = env_inner.open_tables_mut(&tx_rw)?; -//! let (height, hash, serai_block) = pop_block(&mut tables)?; +//! let (height, hash, serai_block) = pop_block(None, &mut tables)?; //! //! assert_eq!(height, 0); //! assert_eq!(serai_block, block.block); diff --git a/storage/blockchain/src/service/mod.rs b/storage/blockchain/src/service/mod.rs index c774ee493..aa322d06e 100644 --- a/storage/blockchain/src/service/mod.rs +++ b/storage/blockchain/src/service/mod.rs @@ -98,7 +98,7 @@ //! //! // Block write was OK. //! let response = response_channel.await?; -//! assert_eq!(response, BlockchainResponse::WriteBlockOk); +//! assert_eq!(response, BlockchainResponse::Ok); //! //! // Now, let's try getting the block hash //! // of the block we just wrote. diff --git a/storage/blockchain/src/service/tests.rs b/storage/blockchain/src/service/tests.rs index b68b5444c..78cb6944a 100644 --- a/storage/blockchain/src/service/tests.rs +++ b/storage/blockchain/src/service/tests.rs @@ -84,7 +84,7 @@ async fn test_template( let request = BlockchainWriteRequest::WriteBlock(block); let response_channel = writer.call(request); let response = response_channel.await.unwrap(); - assert_eq!(response, BlockchainResponse::WriteBlockOk); + assert_eq!(response, BlockchainResponse::Ok); } //----------------------------------------------------------------------- Reset the transaction diff --git a/storage/blockchain/src/tests.rs b/storage/blockchain/src/tests.rs index 65527e102..602391273 100644 --- a/storage/blockchain/src/tests.rs +++ b/storage/blockchain/src/tests.rs @@ -10,6 +10,7 @@ use std::{borrow::Cow, fmt::Debug}; use pretty_assertions::assert_eq; use cuprate_database::{ConcreteEnv, DatabaseRo, Env, EnvInner}; +use cuprate_types::{AltBlockInformation, ChainId, VerifiedBlockInformation}; use crate::{ config::ConfigBuilder, @@ -88,3 +89,18 @@ pub(crate) fn assert_all_tables_are_empty(env: &ConcreteEnv) { assert!(tables.all_tables_empty().unwrap()); assert_eq!(crate::ops::tx::get_num_tx(tables.tx_ids()).unwrap(), 0); } + +pub(crate) fn map_verified_block_to_alt(verified_block: VerifiedBlockInformation, chain_id: ChainId) -> AltBlockInformation { + AltBlockInformation { + block: verified_block.block, + block_blob: verified_block.block_blob, + txs: verified_block.txs, + block_hash: verified_block.block_hash, + pow_hash: verified_block.pow_hash, + height: verified_block.height, + weight: verified_block.weight, + long_term_weight: verified_block.long_term_weight, + cumulative_difficulty: verified_block.cumulative_difficulty, + chain_id, + } +} \ No newline at end of file From ba5c5ac45d958f43382df21dd12eeca520a7c870 Mon Sep 17 00:00:00 2001 From: Boog900 <54e72d8a-345f-4599-bd90-c6b9bc7d0ec5@aleeas.com> Date: Sat, 7 Sep 2024 02:02:19 +0100 Subject: [PATCH 09/31] more docs + cleanup + alt blocks request --- storage/blockchain/src/ops/alt_block/block.rs | 164 +++++++++++------- storage/blockchain/src/ops/alt_block/chain.rs | 47 ++++- storage/blockchain/src/ops/alt_block/mod.rs | 59 ++++++- storage/blockchain/src/ops/alt_block/tx.rs | 21 ++- storage/blockchain/src/ops/block.rs | 23 +-- storage/blockchain/src/ops/macros.rs | 21 +++ storage/blockchain/src/service/read.rs | 98 +++++++++-- storage/blockchain/src/service/write.rs | 19 +- storage/blockchain/src/tests.rs | 7 +- types/src/blockchain.rs | 20 ++- 10 files changed, 365 insertions(+), 114 deletions(-) diff --git a/storage/blockchain/src/ops/alt_block/block.rs b/storage/blockchain/src/ops/alt_block/block.rs index 83d04ba74..07878d55b 100644 --- a/storage/blockchain/src/ops/alt_block/block.rs +++ b/storage/blockchain/src/ops/alt_block/block.rs @@ -1,16 +1,35 @@ -use crate::ops::alt_block::{ - add_alt_transaction_blob, check_add_alt_chain_info, get_alt_chain_history_ranges, - get_alt_transaction, -}; -use crate::ops::block::{get_block_extended_header_from_height, get_block_info}; -use crate::tables::{Tables, TablesMut}; -use crate::types::{AltBlockHeight, BlockHash, BlockHeight, CompactAltBlockInfo}; use bytemuck::TransparentWrapper; +use monero_serai::block::{Block, BlockHeader}; + use cuprate_database::{DatabaseRo, DatabaseRw, RuntimeError, StorableVec}; use cuprate_helper::map::{combine_low_high_bits_to_u128, split_u128_into_low_high_bits}; use cuprate_types::{AltBlockInformation, Chain, ChainId, ExtendedBlockHeader, HardFork}; -use monero_serai::block::{Block, BlockHeader}; +use crate::{ + ops::{ + alt_block::{add_alt_transaction_blob, get_alt_transaction, update_alt_chain_info}, + block::get_block_info, + macros::doc_error, + }, + tables::{Tables, TablesMut}, + types::{AltBlockHeight, BlockHash, BlockHeight, CompactAltBlockInfo}, +}; + +/// Add a [`AltBlockInformation`] to the database. +/// +/// This extracts all the data from the input block and +/// maps/adds them to the appropriate database tables. +/// +#[doc = doc_error!()] +/// +/// # Panics +/// This function will panic if: +/// - `block.height` is == `0` +/// +/// # Already exists +/// This function will operate normally even if `block` already +/// exists, i.e., this function will not return `Err` even if you +/// call this function infinitely with the same block. pub fn add_alt_block( alt_block: &AltBlockInformation, tables: &mut impl TablesMut, @@ -24,7 +43,7 @@ pub fn add_alt_block( .alt_block_heights_mut() .put(&alt_block.block_hash, &alt_block_height)?; - check_add_alt_chain_info(&alt_block_height, &alt_block.block.header.previous, tables)?; + update_alt_chain_info(&alt_block_height, &alt_block.block.header.previous, tables)?; let (cumulative_difficulty_low, cumulative_difficulty_high) = split_u128_into_low_high_bits(alt_block.cumulative_difficulty); @@ -49,13 +68,18 @@ pub fn add_alt_block( )?; assert_eq!(alt_block.txs.len(), alt_block.block.transactions.len()); - for tx in alt_block.txs.iter() { + for tx in &alt_block.txs { add_alt_transaction_blob(tx, tables)?; } Ok(()) } +/// Retrieves an [`AltBlockInformation`] from the database. +/// +/// This function will look at only the blocks with the given [`AltBlockHeight::chain_id`], no others +/// even if they are technically part of this chain. +#[doc = doc_error!()] pub fn get_alt_block( alt_block_height: &AltBlockHeight, tables: &impl Tables, @@ -89,13 +113,21 @@ pub fn get_alt_block( }) } +/// Retrieves the hash of the block at the given `block_height` on the alt chain with +/// the given [`ChainId`]. +/// +/// This function will get blocks from the whole chain, for example if you were to ask for height +/// `0` with any [`ChainId`] (as long that chain actually exists) you will get the main chain genesis. +/// +#[doc = doc_error!()] pub fn get_alt_block_hash( block_height: &BlockHeight, alt_chain: ChainId, - tables: &mut impl Tables, + tables: &impl Tables, ) -> Result { let alt_chains = tables.alt_chain_infos(); + // First find what [`ChainId`] this block would be stored under. let original_chain = { let mut chain = alt_chain.into(); loop { @@ -115,9 +147,10 @@ pub fn get_alt_block_hash( } }; + // Get the block hash. match original_chain { Chain::Main => { - get_block_info(&block_height, tables.block_infos()).map(|info| info.block_hash) + get_block_info(block_height, tables.block_infos()).map(|info| info.block_hash) } Chain::Alt(chain_id) => tables .alt_blocks_info() @@ -129,37 +162,12 @@ pub fn get_alt_block_hash( } } -pub fn get_alt_extended_headers_in_range( - range: std::ops::Range, - alt_chain: ChainId, - tables: &impl Tables, -) -> Result, RuntimeError> { - // TODO: this function does not use rayon, however it probably should. - - let alt_chains = tables.alt_chain_infos(); - let ranges = get_alt_chain_history_ranges(range, alt_chain, alt_chains)?; - - let res = ranges - .into_iter() - .rev() - .map(|(chain, range)| { - range.into_iter().map(move |height| match chain { - Chain::Main => get_block_extended_header_from_height(&height, tables), - Chain::Alt(chain_id) => get_alt_block_extended_header_from_height( - &AltBlockHeight { - chain_id: chain_id.into(), - height, - }, - tables, - ), - }) - }) - .flatten() - .collect::>()?; - - Ok(res) -} - +/// Retrieves the [`ExtendedBlockHeader`] of the alt-block with an exact [`AltBlockHeight`]. +/// +/// This function will look at only the blocks with the given [`AltBlockHeight::chain_id`], no others +/// even if they are technically part of this chain. +/// +#[doc = doc_error!()] pub fn get_alt_block_extended_header_from_height( height: &AltBlockHeight, table: &impl Tables, @@ -171,7 +179,8 @@ pub fn get_alt_block_extended_header_from_height( let block_header = BlockHeader::read(&mut block_blob.as_slice())?; Ok(ExtendedBlockHeader { - version: HardFork::from_version(block_header.hardfork_version).expect("Block in DB must have correct version"), + version: HardFork::from_version(block_header.hardfork_version) + .expect("Block in DB must have correct version"), vote: block_header.hardfork_version, timestamp: block_header.timestamp, cumulative_difficulty: combine_low_high_bits_to_u128( @@ -186,22 +195,33 @@ pub fn get_alt_block_extended_header_from_height( #[cfg(test)] mod tests { use std::num::NonZero; + use cuprate_database::{Env, EnvInner, TxRw}; - use cuprate_test_utils::data::{BLOCK_V1_TX2, BLOCK_V9_TX3, BLOCK_V16_TX0}; - use cuprate_types::ChainId; - use crate::ops::alt_block::{add_alt_block, flush_alt_blocks, get_alt_block, get_alt_extended_headers_in_range}; - use crate::ops::block::{add_block, pop_block}; - use crate::tables::OpenTables; - use crate::tests::{assert_all_tables_are_empty, map_verified_block_to_alt, tmp_concrete_env}; - use crate::types::AltBlockHeight; + use cuprate_test_utils::data::{BLOCK_V16_TX0, BLOCK_V1_TX2, BLOCK_V9_TX3}; + use cuprate_types::{Chain, ChainId}; + + use crate::{ + ops::{ + alt_block::{ + add_alt_block, flush_alt_blocks, get_alt_block, + get_alt_block_extended_header_from_height, get_alt_block_hash, + get_alt_chain_history_ranges, + }, + block::{add_block, pop_block}, + }, + tables::{OpenTables, Tables}, + tests::{assert_all_tables_are_empty, map_verified_block_to_alt, tmp_concrete_env}, + types::AltBlockHeight, + }; + #[allow(clippy::range_plus_one)] #[test] fn all_alt_blocks() { let (env, _tmp) = tmp_concrete_env(); let env_inner = env.env_inner(); assert_all_tables_are_empty(&env); - let chain_id = ChainId(NonZero::new(1).unwrap()).into(); + let chain_id = ChainId(NonZero::new(1).unwrap()); // Add initial block. { @@ -245,25 +265,44 @@ mod tests { let alt_block_2 = get_alt_block(&alt_height, &tables).unwrap(); assert_eq!(alt_block.block, alt_block_2.block); - let headers = get_alt_extended_headers_in_range(0..(height + 1), chain_id, &tables).unwrap(); - assert_eq!(headers.len(), height); + let headers = get_alt_chain_history_ranges( + 0..(height + 1), + chain_id, + tables.alt_chain_infos(), + ) + .unwrap(); - let last_header = headers.last().unwrap(); - assert_eq!(last_header.timestamp, alt_block.block.header.timestamp); - assert_eq!(last_header.block_weight, alt_block.weight); - assert_eq!(last_header.long_term_weight, alt_block.long_term_weight); - assert_eq!(last_header.cumulative_difficulty, alt_block.cumulative_difficulty); - assert_eq!(last_header.version.as_u8(), alt_block.block.header.hardfork_version); - assert_eq!(last_header.vote, alt_block.block.header.hardfork_signal); + assert_eq!(headers.len(), 2); + assert_eq!(headers[1], (Chain::Main, 0..1)); + assert_eq!(headers[0], (Chain::Alt(chain_id), 1..(height + 1))); prev_hash = alt_block.block_hash; + + let header = + get_alt_block_extended_header_from_height(&alt_height, &tables).unwrap(); + + assert_eq!(header.timestamp, alt_block.block.header.timestamp); + assert_eq!(header.block_weight, alt_block.weight); + assert_eq!(header.long_term_weight, alt_block.long_term_weight); + assert_eq!( + header.cumulative_difficulty, + alt_block.cumulative_difficulty + ); + assert_eq!( + header.version.as_u8(), + alt_block.block.header.hardfork_version + ); + assert_eq!(header.vote, alt_block.block.header.hardfork_signal); + + let block_hash = get_alt_block_hash(&height, chain_id, &tables).unwrap(); + + assert_eq!(block_hash, alt_block.block_hash); } drop(tables); TxRw::commit(tx_rw).unwrap(); } - { let mut tx_rw = env_inner.tx_rw().unwrap(); @@ -278,5 +317,4 @@ mod tests { assert_all_tables_are_empty(&env); } - } diff --git a/storage/blockchain/src/ops/alt_block/chain.rs b/storage/blockchain/src/ops/alt_block/chain.rs index 166a294a5..3e27d7d4b 100644 --- a/storage/blockchain/src/ops/alt_block/chain.rs +++ b/storage/blockchain/src/ops/alt_block/chain.rs @@ -1,20 +1,43 @@ -use crate::tables::{AltChainInfos, TablesMut}; -use crate::types::{AltBlockHeight, AltChainInfo, BlockHash, BlockHeight}; +use std::cmp::max; + use cuprate_database::{DatabaseRo, DatabaseRw, RuntimeError}; use cuprate_types::{Chain, ChainId}; -use std::cmp::max; -pub fn check_add_alt_chain_info( +use crate::{ + ops::macros::{doc_add_alt_block_inner_invariant, doc_error}, + tables::{AltChainInfos, TablesMut}, + types::{AltBlockHeight, AltChainInfo, BlockHash, BlockHeight}, +}; + +/// Updates the [`AltChainInfo`] with information on a new alt-block. +/// +#[doc = doc_add_alt_block_inner_invariant!()] +#[doc = doc_error!()] +/// +/// # Panics +/// +/// This will panic if [`AltBlockHeight::height`] == `0`. +pub fn update_alt_chain_info( alt_block_height: &AltBlockHeight, prev_hash: &BlockHash, tables: &mut impl TablesMut, ) -> Result<(), RuntimeError> { - match tables.alt_chain_infos().get(&alt_block_height.chain_id) { - Ok(_) => return Ok(()), + // try update the info if one exists for this chain. + let update = tables + .alt_chain_infos_mut() + .update(&alt_block_height.chain_id, |mut info| { + info.chain_height = alt_block_height.height + 1; + Some(info) + }); + + match update { + Ok(()) => return Ok(()), Err(RuntimeError::KeyNotFound) => (), Err(e) => return Err(e), } + // If one doesn't already exist add it. + let parent_chain = match tables.alt_block_heights().get(prev_hash) { Ok(alt_parent_height) => Chain::Alt(alt_parent_height.chain_id.into()), Err(RuntimeError::KeyNotFound) => Chain::Main, @@ -25,12 +48,18 @@ pub fn check_add_alt_chain_info( &alt_block_height.chain_id, &AltChainInfo { parent_chain: parent_chain.into(), - common_ancestor_height: alt_block_height.height - 1, - chain_height: alt_block_height.height, + common_ancestor_height: alt_block_height.height.checked_sub(1).unwrap(), + chain_height: alt_block_height.height + 1, }, ) } +/// Get the height history of an alt-chain in reverse chronological order. +/// +/// Height history is a list of height ranges with the corresponding [`Chain`] they are stored under. +/// For example if your range goes from height `0` the last entry in the list will be [`Chain::Main`] +/// upto the height where the first split occurs. +#[doc = doc_error!()] pub fn get_alt_chain_history_ranges( range: std::ops::Range, alt_chain: ChainId, @@ -46,7 +75,7 @@ pub fn get_alt_chain_history_ranges( let start_height = max(range.start, chain_info.common_ancestor_height + 1); ranges.push((Chain::Alt(current_chain_id.into()), start_height..i)); - i = chain_info.common_ancestor_height; + i = chain_info.common_ancestor_height + 1; match chain_info.parent_chain.into() { Chain::Main => { diff --git a/storage/blockchain/src/ops/alt_block/mod.rs b/storage/blockchain/src/ops/alt_block/mod.rs index 72e0933ef..36e4768ec 100644 --- a/storage/blockchain/src/ops/alt_block/mod.rs +++ b/storage/blockchain/src/ops/alt_block/mod.rs @@ -1,11 +1,62 @@ -mod block; -mod chain; -mod tx; - +//! Alternative Block/Chain Ops +//! +//! Alternative chains are chains that potentially have more proof-of-work than the main-chain +//! which we are tracking to potentially re-org to. +//! +//! Cuprate uses an ID system for alt-chains. When a split is made from the main-chain we generate +//! a random [`ChainID`](cuprate_types::ChainId) and assign it to the chain: +//! +//! ```text +//! | +//! | +//! | split +//! |------------- +//! | | +//! | | +//! \|/ \|/ +//! main-chain ChainID(X) +//! ``` +//! +//! In that example if we were to receive an alt-block which immediately follows the top block of `ChainID(X)` +//! then that block will also be stored under `ChainID(X)`. However if it follows from another block from `ChainID(X)` +//! we will split into a chain with a different ID. +//! +//! ```text +//! | +//! | +//! | split +//! |------------- +//! | | split +//! | |-------------| +//! | | | +//! | | | +//! | | | +//! \|/ \|/ \|/ +//! main-chain ChainID(X) ChainID(Z) +//! ``` +//! +//! As you can see if we wanted to get all the alt-blocks in `ChainID(Z)` that now includes some blocks from `ChainID(X)` as well. +//! [`get_alt_chain_history_ranges`] covers this and is the method to get the ranges of heights needed from each [`ChainID`](cuprate_types::ChainId) +//! to get all the alt-blocks in a given [`ChainID`](cuprate_types::ChainId). +//! +//! Although this should be kept in mind as a possibility because Cuprate's block downloader will only track a single chain it is +//! unlikely that we will be tracking [`ChainID`](cuprate_types::ChainId) that don't immediately connect to the main-chain. +//! +//! ## Why not use block's previous field? +//! +//! Although that would be easier, it makes getting a range of block extremely slow, as we have to build the weight cache to verify +//! blocks, roughly 100,000 block headers needed, this cost was seen as too high. pub use block::*; pub use chain::*; pub use tx::*; +mod block; +mod chain; +mod tx; + +/// Flush all alt-block data from all the alt-block tables. +/// +/// This function completely empties the alt block tables. pub fn flush_alt_blocks<'a, E: cuprate_database::EnvInner<'a>>( env_inner: &E, tx_rw: &mut E::Rw<'_>, diff --git a/storage/blockchain/src/ops/alt_block/tx.rs b/storage/blockchain/src/ops/alt_block/tx.rs index a49c72ae7..5671e4b45 100644 --- a/storage/blockchain/src/ops/alt_block/tx.rs +++ b/storage/blockchain/src/ops/alt_block/tx.rs @@ -1,10 +1,22 @@ -use crate::tables::{Tables, TablesMut}; -use crate::types::{AltTransactionInfo, TxHash}; use bytemuck::TransparentWrapper; +use monero_serai::transaction::Transaction; + use cuprate_database::{DatabaseRo, DatabaseRw, RuntimeError, StorableVec}; use cuprate_types::VerifiedTransactionInformation; -use monero_serai::transaction::Transaction; +use crate::ops::macros::{doc_add_alt_block_inner_invariant, doc_error}; +use crate::tables::{Tables, TablesMut}; +use crate::types::{AltTransactionInfo, TxHash}; + +/// Adds a [`VerifiedTransactionInformation`] form an alt-block to the DB, if +/// that transaction is not already in the DB. +/// +/// If the transaction is in the main-chain this function will still fill in the +/// [`AltTransactionInfos`](crate::tables::AltTransactionInfos) table, as that +/// table holds data which we don't keep around for main-chain txs. +/// +#[doc = doc_add_alt_block_inner_invariant!()] +#[doc = doc_error!()] pub fn add_alt_transaction_blob( tx: &VerifiedTransactionInformation, tables: &mut impl TablesMut, @@ -29,6 +41,9 @@ pub fn add_alt_transaction_blob( .put(&tx.tx_hash, StorableVec::wrap_ref(&tx.tx_blob)) } +/// Retrieve a [`VerifiedTransactionInformation`] from the database. +/// +#[doc = doc_error!()] pub fn get_alt_transaction( tx_hash: &TxHash, tables: &impl Tables, diff --git a/storage/blockchain/src/ops/block.rs b/storage/blockchain/src/ops/block.rs index b0997f760..45bab41cf 100644 --- a/storage/blockchain/src/ops/block.rs +++ b/storage/blockchain/src/ops/block.rs @@ -38,11 +38,6 @@ use crate::{ /// This function will panic if: /// - `block.height > u32::MAX` (not normally possible) /// - `block.height` is not != [`chain_height`] -/// -/// # Already exists -/// This function will operate normally even if `block` already -/// exists, i.e., this function will not return `Err` even if you -/// call this function infinitely with the same block. // no inline, too big. pub fn add_block( block: &VerifiedBlockInformation, @@ -133,6 +128,9 @@ pub fn add_block( /// Remove the top/latest block from the database. /// /// The removed block's data is returned. +/// +/// If a [`ChainId`] is specified the popped block will be added to the alt block tables under +/// that [`ChainId`]. Otherwise, the block will be completely removed from the DB. #[doc = doc_error!()] /// /// In `pop_block()`'s case, [`RuntimeError::KeyNotFound`] @@ -169,7 +167,7 @@ pub fn pop_block( tx_hash: tx.hash(), fee: tx_fee(&tx), tx, - }) + }); } } @@ -180,11 +178,16 @@ pub fn pop_block( block_blob, txs, block_hash: block_info.block_hash, + // We know the PoW is valid for this block so just set it so it will always verify as + // valid. pow_hash: [0; 32], height: block_height, weight: block_info.weight, long_term_weight: block_info.long_term_weight, - cumulative_difficulty: 0, + cumulative_difficulty: combine_low_high_bits_to_u128( + block_info.cumulative_difficulty_low, + block_info.cumulative_difficulty_high, + ), chain_id, }, tables, @@ -229,8 +232,6 @@ pub fn get_block_extended_header_from_height( block_info.cumulative_difficulty_high, ); - // INVARIANT: #[cfg] @ lib.rs asserts `usize == u64` - #[allow(clippy::cast_possible_truncation)] Ok(ExtendedBlockHeader { cumulative_difficulty, version: HardFork::from_version(block_header.hardfork_version) @@ -302,14 +303,14 @@ mod test { use cuprate_database::{Env, EnvInner, TxRw}; use cuprate_test_utils::data::{BLOCK_V16_TX0, BLOCK_V1_TX2, BLOCK_V9_TX3}; - use super::*; - use crate::{ ops::tx::{get_tx, tx_exists}, tables::OpenTables, tests::{assert_all_tables_are_empty, tmp_concrete_env, AssertTableLen}, }; + use super::*; + /// Tests all above block functions. /// /// Note that this doesn't test the correctness of values added, as the diff --git a/storage/blockchain/src/ops/macros.rs b/storage/blockchain/src/ops/macros.rs index b7cdba474..e547c7f24 100644 --- a/storage/blockchain/src/ops/macros.rs +++ b/storage/blockchain/src/ops/macros.rs @@ -31,3 +31,24 @@ When calling this function, ensure that either: }; } pub(super) use doc_add_block_inner_invariant; + +// This is pretty much the same as [`doc_add_block_inner_invariant`], it's not worth the effort to reduce +// the duplication. +/// Generate `# Invariant` documentation for internal alt block `fn`'s +/// that should be called directly with caution. +macro_rules! doc_add_alt_block_inner_invariant { + () => { + r#"# ⚠️ Invariant ⚠️ +This function mainly exists to be used internally by the parent function [`crate::ops::alt_block::add_alt_block`]. + +`add_alt_block()` makes sure all data related to the input is mutated, while +this function _does not_, it specifically mutates _particular_ tables. + +This is usually undesired - although this function is still available to call directly. + +When calling this function, ensure that either: +1. This effect (incomplete database mutation) is what is desired, or that... +2. ...the other tables will also be mutated to a correct state"# + }; +} +pub(super) use doc_add_alt_block_inner_invariant; diff --git a/storage/blockchain/src/service/read.rs b/storage/blockchain/src/service/read.rs index 70da01b3e..416e61372 100644 --- a/storage/blockchain/src/service/read.rs +++ b/storage/blockchain/src/service/read.rs @@ -1,28 +1,32 @@ //! Database reader thread-pool definitions and logic. -//---------------------------------------------------------------------------------------------------- Import use std::{ collections::{HashMap, HashSet}, sync::Arc, }; +//---------------------------------------------------------------------------------------------------- Import use rayon::{ iter::{IntoParallelIterator, ParallelIterator}, + prelude::*, ThreadPool, }; use thread_local::ThreadLocal; use cuprate_database::{ConcreteEnv, DatabaseRo, Env, EnvInner, RuntimeError}; -use cuprate_database_service::{init_thread_pool, DatabaseReadService, ReaderThreads}; +use cuprate_database_service::{DatabaseReadService, init_thread_pool, ReaderThreads}; use cuprate_helper::map::combine_low_high_bits_to_u128; use cuprate_types::{ blockchain::{BlockchainReadRequest, BlockchainResponse}, - Chain, ExtendedBlockHeader, OutputOnChain, + Chain, ChainId, ExtendedBlockHeader, OutputOnChain, }; use crate::{ ops::{ - alt_block::{get_alt_block_hash, get_alt_extended_headers_in_range}, + alt_block::{ + get_alt_block_extended_header_from_height, get_alt_block_hash, + get_alt_chain_history_ranges, + }, block::{ block_exists, get_block_extended_header_from_height, get_block_height, get_block_info, }, @@ -35,8 +39,11 @@ use crate::{ types::{BlockchainReadHandle, ResponseResult}, }, tables::{AltBlockHeights, BlockHeights, BlockInfos, OpenTables, Tables}, - types::{Amount, AmountIndex, BlockHash, BlockHeight, KeyImage, PreRctOutputId}, + types::{ + AltBlockHeight, Amount, AmountIndex, BlockHash, BlockHeight, KeyImage, PreRctOutputId, + }, }; +use crate::ops::alt_block::get_alt_block; //---------------------------------------------------------------------------------------------------- init_read_service /// Initialize the [`BlockchainReadHandle`] thread-pool backed by [`rayon`]. @@ -100,6 +107,7 @@ fn map_request( R::KeyImagesSpent(set) => key_images_spent(env, set), R::CompactChainHistory => compact_chain_history(env), R::FindFirstUnknown(block_ids) => find_first_unknown(env, &block_ids), + R::AltBlocksInChain(chain_id) => alt_blocks_in_chain(env, chain_id), } /* SOMEDAY: post-request handling, run some code for each request? */ @@ -200,7 +208,7 @@ fn block_hash(env: &ConcreteEnv, block_height: BlockHeight, chain: Chain) -> Res let block_hash = match chain { Chain::Main => get_block_info(&block_height, &table_block_infos)?.block_hash, Chain::Alt(chain) => { - get_alt_block_hash(&block_height, chain, &mut env_inner.open_tables(&tx_ro)?)? + get_alt_block_hash(&block_height, chain, &env_inner.open_tables(&tx_ro)?)? } }; @@ -283,12 +291,36 @@ fn block_extended_header_in_range( }) .collect::, RuntimeError>>()?, Chain::Alt(chain_id) => { - let tx_ro = tx_ro.get_or_try(|| env_inner.tx_ro())?; - get_alt_extended_headers_in_range( - range, - chain_id, - get_tables!(env_inner, tx_ro, tables)?.as_ref(), - )? + let ranges = { + let tx_ro = tx_ro.get_or_try(|| env_inner.tx_ro())?; + let tables = get_tables!(env_inner, tx_ro, tables)?.as_ref(); + let alt_chains = tables.alt_chain_infos(); + + get_alt_chain_history_ranges(range, chain_id, alt_chains)? + }; + + ranges + .par_iter() + .rev() + .map(|(chain, range)| { + range.clone().into_par_iter().map(|height| { + let tx_ro = tx_ro.get_or_try(|| env_inner.tx_ro())?; + let tables = get_tables!(env_inner, tx_ro, tables)?.as_ref(); + + match *chain { + Chain::Main => get_block_extended_header_from_height(&height, tables), + Chain::Alt(chain_id) => get_alt_block_extended_header_from_height( + &AltBlockHeight { + chain_id: chain_id.into(), + height, + }, + tables, + ), + } + }) + }) + .flatten() + .collect::, _>>()? } }; @@ -524,3 +556,45 @@ fn find_first_unknown(env: &ConcreteEnv, block_ids: &[BlockHash]) -> ResponseRes BlockchainResponse::FindFirstUnknown(Some((idx, last_known_height + 1))) }) } + +/// [`BlockchainReadRequest::AltBlocksInChain`] +fn alt_blocks_in_chain(env: &ConcreteEnv, chain_id: ChainId) -> ResponseResult { + // Prepare tx/tables in `ThreadLocal`. + let env_inner = env.env_inner(); + let tx_ro = thread_local(env); + let tables = thread_local(env); + + // Get the history of this alt-chain. + let history = { + let tx_ro = tx_ro.get_or_try(|| env_inner.tx_ro())?; + let tables = get_tables!(env_inner, tx_ro, tables)?.as_ref(); + get_alt_chain_history_ranges(0..usize::MAX, chain_id, tables.alt_chain_infos())? + }; + + // Get all the blocks until we join the main-chain. + let blocks = history + .par_iter() + .rev() + .skip(1) + .flat_map(|(chain_id, range)| { + let Chain::Alt(chain_id) = chain_id else { + panic!("Should not have main chain blocks here we skipped last range"); + }; + + range.clone().into_par_iter().map(|height| { + let tx_ro = tx_ro.get_or_try(|| env_inner.tx_ro())?; + let tables = get_tables!(env_inner, tx_ro, tables)?.as_ref(); + + get_alt_block( + &AltBlockHeight { + chain_id: (*chain_id).into(), + height, + }, + tables, + ) + }) + }) + .collect::>()?; + + Ok(BlockchainResponse::AltBlocksInChain(blocks)) +} diff --git a/storage/blockchain/src/service/write.rs b/storage/blockchain/src/service/write.rs index 95124d41a..849a3030f 100644 --- a/storage/blockchain/src/service/write.rs +++ b/storage/blockchain/src/service/write.rs @@ -9,12 +9,13 @@ use cuprate_types::{ AltBlockInformation, Chain, ChainId, VerifiedBlockInformation, }; -use crate::service::free::map_valid_alt_block_to_verified_block; -use crate::types::AltBlockHeight; use crate::{ - service::types::{BlockchainWriteHandle, ResponseResult}, + service::{ + free::map_valid_alt_block_to_verified_block, + types::{BlockchainWriteHandle, ResponseResult}, + }, tables::{OpenTables, Tables, TablesMut}, - types::AltChainInfo, + types::{AltBlockHeight, AltChainInfo}, }; //---------------------------------------------------------------------------------------------------- init_write_service @@ -106,19 +107,23 @@ fn pop_blocks(env: &ConcreteEnv, numb_blocks: usize) -> ResponseResult { let env_inner = env.env_inner(); let mut tx_rw = env_inner.tx_rw()?; + // TODO: try blocks let result = { + // flush all the current alt blocks as they may reference blocks to be popped. crate::ops::alt_block::flush_alt_blocks(&env_inner, &mut tx_rw)?; let mut tables_mut = env_inner.open_tables_mut(&tx_rw)?; - + // generate a `ChainId` for the popped blocks. let old_main_chain_id = ChainId(rand::random()); + // pop the blocks let mut last_block_height = 0; for _ in 0..numb_blocks { (last_block_height, _, _) = crate::ops::block::pop_block(Some(old_main_chain_id), &mut tables_mut)?; } + // Update the alt_chain_info with the correct information. tables_mut.alt_chain_infos_mut().put( &old_main_chain_id.into(), &AltChainInfo { @@ -155,11 +160,14 @@ fn reverse_reorg(env: &ConcreteEnv, chain_id: ChainId) -> ResponseResult { let mut tables_mut = env_inner.open_tables_mut(&tx_rw)?; let chain_info = tables_mut.alt_chain_infos().get(&chain_id.into())?; + // Although this doesn't guarantee the chain was popped from the main-chain, it's an easy + // thing for us to check. assert_eq!(Chain::from(chain_info.parent_chain), Chain::Main); let tob_block_height = crate::ops::blockchain::top_block_height(tables_mut.block_heights())?; + // pop any blocks that were added as part of a re-org. for _ in chain_info.common_ancestor_height..tob_block_height { crate::ops::block::pop_block(None, &mut tables_mut)?; } @@ -177,6 +185,7 @@ fn reverse_reorg(env: &ConcreteEnv, chain_id: ChainId) -> ResponseResult { }) .collect::>(); + // Add the old main chain blocks back to the main chain. for res_alt_block in alt_blocks { let alt_block = res_alt_block?; diff --git a/storage/blockchain/src/tests.rs b/storage/blockchain/src/tests.rs index 602391273..d57a37154 100644 --- a/storage/blockchain/src/tests.rs +++ b/storage/blockchain/src/tests.rs @@ -90,7 +90,10 @@ pub(crate) fn assert_all_tables_are_empty(env: &ConcreteEnv) { assert_eq!(crate::ops::tx::get_num_tx(tables.tx_ids()).unwrap(), 0); } -pub(crate) fn map_verified_block_to_alt(verified_block: VerifiedBlockInformation, chain_id: ChainId) -> AltBlockInformation { +pub(crate) fn map_verified_block_to_alt( + verified_block: VerifiedBlockInformation, + chain_id: ChainId, +) -> AltBlockInformation { AltBlockInformation { block: verified_block.block, block_blob: verified_block.block_blob, @@ -103,4 +106,4 @@ pub(crate) fn map_verified_block_to_alt(verified_block: VerifiedBlockInformation cumulative_difficulty: verified_block.cumulative_difficulty, chain_id, } -} \ No newline at end of file +} diff --git a/types/src/blockchain.rs b/types/src/blockchain.rs index c2a5517da..9f79c3a39 100644 --- a/types/src/blockchain.rs +++ b/types/src/blockchain.rs @@ -3,14 +3,15 @@ //! Tests that assert particular requests lead to particular //! responses are also tested in Cuprate's blockchain database crate. -//---------------------------------------------------------------------------------------------------- Import -use crate::types::{Chain, ExtendedBlockHeader, OutputOnChain, VerifiedBlockInformation}; -use crate::{AltBlockInformation, ChainId}; use std::{ collections::{HashMap, HashSet}, ops::Range, }; +use crate::{AltBlockInformation, ChainId}; +//---------------------------------------------------------------------------------------------------- Import +use crate::types::{Chain, ExtendedBlockHeader, OutputOnChain, VerifiedBlockInformation}; + //---------------------------------------------------------------------------------------------------- ReadRequest /// A read request to the blockchain database. /// @@ -92,12 +93,14 @@ pub enum BlockchainReadRequest { CompactChainHistory, /// A request to find the first unknown block ID in a list of block IDs. - //// + /// /// # Invariant /// The [`Vec`] containing the block IDs must be sorted in chronological block /// order, or else the returned response is unspecified and meaningless, /// as this request performs a binary search. FindFirstUnknown(Vec<[u8; 32]>), + /// A request for all alt blocks in the chain with the given [`ChainId`]. + AltBlocksInChain(ChainId), } //---------------------------------------------------------------------------------------------------- WriteRequest @@ -120,12 +123,14 @@ pub enum BlockchainWriteRequest { /// /// Input is the amount of blocks to pop. /// - /// This request flush all alt-chains from the cache before adding the popped blocks to the alt cache. + /// This request flushes all alt-chains from the cache before adding the popped blocks to the + /// alt cache. PopBlocks(usize), /// A request to reverse the re-org process. /// /// The inner value is the [`ChainId`] of the old main chain. /// + /// # Invariant /// It is invalid to call this with a [`ChainId`] that was not returned from [`BlockchainWriteRequest::PopBlocks`]. ReverseReorg(ChainId), /// A request to flush all alternative blocks. @@ -215,6 +220,11 @@ pub enum BlockchainResponse { /// This will be [`None`] if all blocks were known. FindFirstUnknown(Option<(usize, usize)>), + /// The response for [`BlockchainReadRequest::AltBlocksInChain`]. + /// + /// Contains all the alt blocks in the alt-chain in chronological order. + AltBlocksInChain(Vec), + //------------------------------------------------------ Writes /// A generic Ok response to indicate a request was successfully handled. /// From f92375f6a61d72fa802e4a75ca7cba3f8d968363 Mon Sep 17 00:00:00 2001 From: Boog900 <54e72d8a-345f-4599-bd90-c6b9bc7d0ec5@aleeas.com> Date: Sat, 7 Sep 2024 02:07:23 +0100 Subject: [PATCH 10/31] clippy + fmt --- storage/blockchain/src/service/read.rs | 4 ++-- storage/blockchain/src/types.rs | 16 +++++++--------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/storage/blockchain/src/service/read.rs b/storage/blockchain/src/service/read.rs index 416e61372..835f2d6a6 100644 --- a/storage/blockchain/src/service/read.rs +++ b/storage/blockchain/src/service/read.rs @@ -14,13 +14,14 @@ use rayon::{ use thread_local::ThreadLocal; use cuprate_database::{ConcreteEnv, DatabaseRo, Env, EnvInner, RuntimeError}; -use cuprate_database_service::{DatabaseReadService, init_thread_pool, ReaderThreads}; +use cuprate_database_service::{init_thread_pool, DatabaseReadService, ReaderThreads}; use cuprate_helper::map::combine_low_high_bits_to_u128; use cuprate_types::{ blockchain::{BlockchainReadRequest, BlockchainResponse}, Chain, ChainId, ExtendedBlockHeader, OutputOnChain, }; +use crate::ops::alt_block::get_alt_block; use crate::{ ops::{ alt_block::{ @@ -43,7 +44,6 @@ use crate::{ AltBlockHeight, Amount, AmountIndex, BlockHash, BlockHeight, KeyImage, PreRctOutputId, }, }; -use crate::ops::alt_block::get_alt_block; //---------------------------------------------------------------------------------------------------- init_read_service /// Initialize the [`BlockchainReadHandle`] thread-pool backed by [`rayon`]. diff --git a/storage/blockchain/src/types.rs b/storage/blockchain/src/types.rs index 14917249f..13c449941 100644 --- a/storage/blockchain/src/types.rs +++ b/storage/blockchain/src/types.rs @@ -44,12 +44,12 @@ use std::num::NonZero; use bytemuck::{Pod, Zeroable}; - #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; use cuprate_database::{Key, StorableVec}; use cuprate_types::{Chain, ChainId}; + //---------------------------------------------------------------------------------------------------- Aliases // These type aliases exist as many Monero-related types are the exact same. // For clarity, they're given type aliases as to not confuse them. @@ -334,17 +334,15 @@ pub struct RawChain(u64); impl From for RawChain { fn from(value: Chain) -> Self { match value { - Chain::Main => RawChain(0), - Chain::Alt(chain_id) => RawChain(chain_id.0.get()), + Chain::Main => Self(0), + Chain::Alt(chain_id) => Self(chain_id.0.get()), } } } impl From for Chain { fn from(value: RawChain) -> Self { - NonZero::new(value.0) - .map(|id| Chain::Alt(ChainId(id))) - .unwrap_or(Chain::Main) + NonZero::new(value.0).map_or(Self::Main, |id| Self::Alt(ChainId(id))) } } @@ -352,7 +350,7 @@ impl From for RawChain { fn from(value: RawChainId) -> Self { assert_ne!(value.0, 0); - RawChain(value.0) + Self(value.0) } } @@ -363,13 +361,13 @@ pub struct RawChainId(u64); impl From for RawChainId { fn from(value: ChainId) -> Self { - RawChainId(value.0.get()) + Self(value.0.get()) } } impl From for ChainId { fn from(value: RawChainId) -> Self { - ChainId(NonZero::new(value.0).expect("RawChainId mut not have a value of `0`")) + Self(NonZero::new(value.0).expect("RawChainId mut not have a value of `0`")) } } From a864f934be9f2e42cbda24d66dfb83ee9ff84f91 Mon Sep 17 00:00:00 2001 From: Boog900 <54e72d8a-345f-4599-bd90-c6b9bc7d0ec5@aleeas.com> Date: Sat, 7 Sep 2024 02:45:45 +0100 Subject: [PATCH 11/31] document types --- storage/blockchain/src/types.rs | 164 ++++++++++++++++++++++++++++++-- types/src/blockchain.rs | 4 - 2 files changed, 157 insertions(+), 11 deletions(-) diff --git a/storage/blockchain/src/types.rs b/storage/blockchain/src/types.rs index 13c449941..e96656951 100644 --- a/storage/blockchain/src/types.rs +++ b/storage/blockchain/src/types.rs @@ -327,6 +327,29 @@ pub struct RctOutput { // TODO: local_index? //---------------------------------------------------------------------------------------------------- RawChain +/// [`Chain`] in a format which can be stored in the DB. +/// +/// Implements [`Into`] and [`From`] for [`Chain`]. +/// +/// ```rust +/// # use std::borrow::*; +/// # use cuprate_blockchain::{*, types::*}; +/// use cuprate_database::Storable; +/// use cuprate_types::Chain; +/// +/// // Assert Storable is correct. +/// let a: RawChain = Chain::Main.into(); +/// let b = Storable::as_bytes(&a); +/// let c: RawChain = Storable::from_bytes(b); +/// assert_eq!(a, c); +/// ``` +/// +/// # Size & Alignment +/// ```rust +/// # use cuprate_blockchain::types::*; +/// assert_eq!(size_of::(), 8); +/// assert_eq!(align_of::(), 8); +/// ``` #[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Pod, Zeroable)] #[repr(transparent)] pub struct RawChain(u64); @@ -348,6 +371,7 @@ impl From for Chain { impl From for RawChain { fn from(value: RawChainId) -> Self { + // A [`ChainID`] with an inner value of `0` is invalid. assert_ne!(value.0, 0); Self(value.0) @@ -355,6 +379,29 @@ impl From for RawChain { } //---------------------------------------------------------------------------------------------------- RawChainId +/// [`ChainId`] in a format which can be stored in the DB. +/// +/// Implements [`Into`] and [`From`] for [`ChainId`]. +/// +/// ```rust +/// # use std::borrow::*; +/// # use cuprate_blockchain::{*, types::*}; +/// use cuprate_database::Storable; +/// use cuprate_types::ChainId; +/// +/// // Assert Storable is correct. +/// let a: RawChainId = ChainId(10.try_into().unwrap()).into(); +/// let b = Storable::as_bytes(&a); +/// let c: RawChainId = Storable::from_bytes(b); +/// assert_eq!(a, c); +/// ``` +/// +/// # Size & Alignment +/// ```rust +/// # use cuprate_blockchain::types::*; +/// assert_eq!(size_of::(), 8); +/// assert_eq!(align_of::(), 8); +/// ``` #[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Pod, Zeroable)] #[repr(transparent)] pub struct RawChainId(u64); @@ -374,31 +421,112 @@ impl From for ChainId { impl Key for RawChainId {} //---------------------------------------------------------------------------------------------------- AltChainInfo +/// Information on an alternative chain. +/// +/// ```rust +/// # use std::borrow::*; +/// # use cuprate_blockchain::{*, types::*}; +/// use cuprate_database::Storable; +/// use cuprate_types::Chain; +/// +/// // Assert Storable is correct. +/// let a: AltChainInfo = AltChainInfo { +/// parent_chain: Chain::Main.into(), +/// common_ancestor_height: 0, +/// chain_height: 1, +/// }; +/// let b = Storable::as_bytes(&a); +/// let c: AltChainInfo = Storable::from_bytes(b); +/// assert_eq!(a, c); +/// ``` +/// +/// # Size & Alignment +/// ```rust +/// # use cuprate_blockchain::types::*; +/// assert_eq!(size_of::(), 24); +/// assert_eq!(align_of::(), 8); +/// ``` #[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Pod, Zeroable)] #[repr(C)] pub struct AltChainInfo { + /// The chain this alt chain forks from. pub parent_chain: RawChain, + /// The height of the first block we share with the parent chain. pub common_ancestor_height: usize, + /// The chain height of the blocks in this alt chain. pub chain_height: usize, } //---------------------------------------------------------------------------------------------------- AltBlockHeight +/// Represents the height of a block on an alt-chain. +/// +/// ```rust +/// # use std::borrow::*; +/// # use cuprate_blockchain::{*, types::*}; +/// use cuprate_database::Storable; +/// use cuprate_types::ChainId; +/// +/// // Assert Storable is correct. +/// let a: AltBlockHeight = AltBlockHeight { +/// chain_id: ChainId(1.try_into().unwrap()).into(), +/// height: 1, +/// }; +/// let b = Storable::as_bytes(&a); +/// let c: AltBlockHeight = Storable::from_bytes(b); +/// assert_eq!(a, c); +/// ``` +/// +/// # Size & Alignment +/// ```rust +/// # use cuprate_blockchain::types::*; +/// assert_eq!(size_of::(), 16); +/// assert_eq!(align_of::(), 8); +/// ``` #[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Pod, Zeroable)] #[repr(C)] pub struct AltBlockHeight { + /// The [`ChainId`] of the chain this alt block is on, in raw form. pub chain_id: RawChainId, + /// The height of this alt-block. pub height: usize, } impl Key for AltBlockHeight {} //---------------------------------------------------------------------------------------------------- CompactAltBlockInfo +/// Represents information on an alt-chain. +/// +/// ```rust +/// # use std::borrow::*; +/// # use cuprate_blockchain::{*, types::*}; +/// use cuprate_database::Storable; +/// +/// // Assert Storable is correct. +/// let a: CompactAltBlockInfo = CompactAltBlockInfo { +/// block_hash: [1; 32], +/// pow_hash: [2; 32], +/// height: 10, +/// weight: 20, +/// long_term_weight: 30, +/// cumulative_difficulty_low: 40, +/// cumulative_difficulty_high: 50, +/// }; +/// +/// let b = Storable::as_bytes(&a); +/// let c: CompactAltBlockInfo = Storable::from_bytes(b); +/// assert_eq!(a, c); +/// ``` +/// +/// # Size & Alignment +/// ```rust +/// # use cuprate_blockchain::types::*; +/// assert_eq!(size_of::(), 104); +/// assert_eq!(align_of::(), 8); +/// ``` #[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Pod, Zeroable)] #[repr(C)] pub struct CompactAltBlockInfo { /// The block's hash. - /// - /// [`Block::hash`]. pub block_hash: [u8; 32], /// The block's proof-of-work hash. pub pow_hash: [u8; 32], @@ -408,24 +536,46 @@ pub struct CompactAltBlockInfo { pub weight: usize, /// The long term block weight, which is the weight factored in with previous block weights. pub long_term_weight: usize, - /// The cumulative difficulty of all blocks up until and including this block. + /// The low 64 bits of the cumulative difficulty. pub cumulative_difficulty_low: u64, + /// The high 64 bits of the cumulative difficulty. pub cumulative_difficulty_high: u64, } //---------------------------------------------------------------------------------------------------- AltTransactionInfo +/// Represents information on an alt transaction. +/// +/// ```rust +/// # use std::borrow::*; +/// # use cuprate_blockchain::{*, types::*}; +/// use cuprate_database::Storable; +/// +/// // Assert Storable is correct. +/// let a: AltTransactionInfo = AltTransactionInfo { +/// tx_weight: 1, +/// fee: 6, +/// tx_hash: [6; 32], +/// }; +/// +/// let b = Storable::as_bytes(&a); +/// let c: AltTransactionInfo = Storable::from_bytes(b); +/// assert_eq!(a, c); +/// ``` +/// +/// # Size & Alignment +/// ```rust +/// # use cuprate_blockchain::types::*; +/// assert_eq!(size_of::(), 48); +/// assert_eq!(align_of::(), 8); +/// ``` #[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Pod, Zeroable)] #[repr(C)] pub struct AltTransactionInfo { /// The transaction's weight. - /// - /// [`Transaction::weight`]. pub tx_weight: usize, /// The transaction's total fees. pub fee: u64, /// The transaction's hash. - /// - /// [`Transaction::hash`]. pub tx_hash: [u8; 32], } diff --git a/types/src/blockchain.rs b/types/src/blockchain.rs index 9f79c3a39..6c7ecf37b 100644 --- a/types/src/blockchain.rs +++ b/types/src/blockchain.rs @@ -105,10 +105,6 @@ pub enum BlockchainReadRequest { //---------------------------------------------------------------------------------------------------- WriteRequest /// A write request to the blockchain database. -/// -/// There is currently only 1 write request to the database, -/// as such, the only valid [`BlockchainResponse`] to this request is -/// the proper response for a [`BlockchainResponse::WriteBlockOk`]. #[derive(Debug, Clone, PartialEq, Eq)] pub enum BlockchainWriteRequest { /// Request that a block be written to the database. From 6119972fe81ff9969a64cc07cbcb2f8bd7fc9220 Mon Sep 17 00:00:00 2001 From: Boog900 <54e72d8a-345f-4599-bd90-c6b9bc7d0ec5@aleeas.com> Date: Sun, 8 Sep 2024 02:08:20 +0100 Subject: [PATCH 12/31] move tx_fee to helper --- helper/Cargo.toml | 4 ++- helper/src/lib.rs | 2 ++ helper/src/tx_utils.rs | 34 ++++++++++++++++++++++++ storage/blockchain/src/free.rs | 32 ----------------------- storage/blockchain/src/ops/block.rs | 8 +++--- test-utils/Cargo.toml | 2 +- test-utils/src/data/statics.rs | 40 ++++------------------------- 7 files changed, 50 insertions(+), 72 deletions(-) create mode 100644 helper/src/tx_utils.rs diff --git a/helper/Cargo.toml b/helper/Cargo.toml index c74e40fd4..4bd17ca89 100644 --- a/helper/Cargo.toml +++ b/helper/Cargo.toml @@ -9,8 +9,9 @@ repository = "https://github.com/Cuprate/cuprate/tree/main/consensus" [features] +# TODO: I don't think this is a good idea # All features on by default. -default = ["std", "atomic", "asynch", "cast", "fs", "num", "map", "time", "thread", "constants"] +default = ["std", "atomic", "asynch", "cast", "fs", "num", "map", "time", "thread", "constants", "tx-utils"] std = [] atomic = ["dep:crossbeam"] asynch = ["dep:futures", "dep:rayon"] @@ -21,6 +22,7 @@ num = [] map = ["cast", "dep:monero-serai"] time = ["dep:chrono", "std"] thread = ["std", "dep:target_os_lib"] +tx-utils = ["dep:monero-serai"] [dependencies] crossbeam = { workspace = true, optional = true } diff --git a/helper/src/lib.rs b/helper/src/lib.rs index de0d95558..e82ec827d 100644 --- a/helper/src/lib.rs +++ b/helper/src/lib.rs @@ -31,6 +31,8 @@ pub mod thread; #[cfg(feature = "time")] pub mod time; +#[cfg(feature = "tx-utils")] +pub mod tx_utils; //---------------------------------------------------------------------------------------------------- Private Usage //---------------------------------------------------------------------------------------------------- diff --git a/helper/src/tx_utils.rs b/helper/src/tx_utils.rs new file mode 100644 index 000000000..aeccf32b2 --- /dev/null +++ b/helper/src/tx_utils.rs @@ -0,0 +1,34 @@ +//! Utils for working with [`Transaction`] + +use monero_serai::transaction::{Input, Transaction}; + +/// Calculates the fee of the [`Transaction`]. +/// +/// # Panics +/// This will panic if the inputs overflow or the transaction outputs too much, so should only +/// be used on known to be valid txs. +pub fn tx_fee(tx: &Transaction) -> u64 { + let mut fee = 0_u64; + + match &tx { + Transaction::V1 { prefix, .. } => { + for input in &prefix.inputs { + match input { + Input::Gen(_) => return 0, + Input::ToKey { amount, .. } => { + fee = fee.checked_add(amount.unwrap_or(0)).unwrap(); + } + } + } + + for output in &prefix.outputs { + fee.checked_sub(output.amount.unwrap_or(0)).unwrap(); + } + } + Transaction::V2 { proofs, .. } => { + fee = proofs.as_ref().unwrap().base.fee; + } + }; + + fee +} diff --git a/storage/blockchain/src/free.rs b/storage/blockchain/src/free.rs index 20d56226d..8288e65f7 100644 --- a/storage/blockchain/src/free.rs +++ b/storage/blockchain/src/free.rs @@ -1,6 +1,5 @@ //! General free functions (related to the database). -use monero_serai::transaction::{Input, Transaction}; //---------------------------------------------------------------------------------------------------- Import use cuprate_database::{ConcreteEnv, Env, EnvInner, InitError, RuntimeError, TxRw}; @@ -62,37 +61,6 @@ pub fn open(config: Config) -> Result { Ok(env) } -//---------------------------------------------------------------------------------------------------- Tx Fee -/// Calculates the fee of the [`Transaction`]. -/// -/// # Panics -/// This will panic if the inputs overflow or the transaction outputs too much. -pub(crate) fn tx_fee(tx: &Transaction) -> u64 { - let mut fee = 0_u64; - - match &tx { - Transaction::V1 { prefix, .. } => { - for input in &prefix.inputs { - match input { - Input::Gen(_) => return 0, - Input::ToKey { amount, .. } => { - fee = fee.checked_add(amount.unwrap_or(0)).unwrap(); - } - } - } - - for output in &prefix.outputs { - fee.checked_sub(output.amount.unwrap_or(0)).unwrap(); - } - } - Transaction::V2 { proofs, .. } => { - fee = proofs.as_ref().unwrap().base.fee; - } - }; - - fee -} - //---------------------------------------------------------------------------------------------------- Tests #[cfg(test)] mod test { diff --git a/storage/blockchain/src/ops/block.rs b/storage/blockchain/src/ops/block.rs index 45bab41cf..295869257 100644 --- a/storage/blockchain/src/ops/block.rs +++ b/storage/blockchain/src/ops/block.rs @@ -7,16 +7,18 @@ use monero_serai::block::{Block, BlockHeader}; use cuprate_database::{ RuntimeError, StorableVec, {DatabaseRo, DatabaseRw}, }; -use cuprate_helper::map::{combine_low_high_bits_to_u128, split_u128_into_low_high_bits}; +use cuprate_helper::{ + map::{combine_low_high_bits_to_u128, split_u128_into_low_high_bits}, + tx_utils::tx_fee, +}; use cuprate_types::{ AltBlockInformation, ChainId, ExtendedBlockHeader, HardFork, VerifiedBlockInformation, VerifiedTransactionInformation, }; -use crate::free::tx_fee; -use crate::ops::alt_block; use crate::{ ops::{ + alt_block, blockchain::{chain_height, cumulative_generated_coins}, macros::doc_error, output::get_rct_num_outputs, diff --git a/test-utils/Cargo.toml b/test-utils/Cargo.toml index a96a9cfcd..9c64bd81b 100644 --- a/test-utils/Cargo.toml +++ b/test-utils/Cargo.toml @@ -7,7 +7,7 @@ authors = ["Boog900", "hinto-janai"] [dependencies] cuprate-types = { path = "../types" } -cuprate-helper = { path = "../helper", features = ["map"] } +cuprate-helper = { path = "../helper", features = ["map", "tx-utils"] } cuprate-wire = { path = "../net/wire" } cuprate-p2p-core = { path = "../p2p/p2p-core", features = ["borsh"] } diff --git a/test-utils/src/data/statics.rs b/test-utils/src/data/statics.rs index 8b98171a2..a45cc13fa 100644 --- a/test-utils/src/data/statics.rs +++ b/test-utils/src/data/statics.rs @@ -8,12 +8,12 @@ //---------------------------------------------------------------------------------------------------- Import use std::sync::LazyLock; -use cuprate_helper::map::combine_low_high_bits_to_u128; -use cuprate_types::{VerifiedBlockInformation, VerifiedTransactionInformation}; use hex_literal::hex; -use monero_serai::transaction::Input; use monero_serai::{block::Block, transaction::Transaction}; +use cuprate_helper::{map::combine_low_high_bits_to_u128, tx_utils::tx_fee}; +use cuprate_types::{VerifiedBlockInformation, VerifiedTransactionInformation}; + use crate::data::constants::{ BLOCK_43BD1F, BLOCK_5ECB7E, BLOCK_F91043, TX_2180A8, TX_3BC7FF, TX_84D48D, TX_9E3F73, TX_B6B439, TX_D7FEBD, TX_E2D393, TX_E57440, @@ -110,36 +110,6 @@ fn to_tx_verification_data(tx_blob: impl AsRef<[u8]>) -> VerifiedTransactionInfo } } -/// Calculates the fee of the [`Transaction`]. -/// -/// # Panics -/// This will panic if the inputs overflow or the transaction outputs too much. -pub fn tx_fee(tx: &Transaction) -> u64 { - let mut fee = 0_u64; - - match &tx { - Transaction::V1 { prefix, .. } => { - for input in &prefix.inputs { - match input { - Input::Gen(_) => return 0, - Input::ToKey { amount, .. } => { - fee = fee.checked_add(amount.unwrap_or(0)).unwrap(); - } - } - } - - for output in &prefix.outputs { - fee.checked_sub(output.amount.unwrap_or(0)).unwrap(); - } - } - Transaction::V2 { proofs, .. } => { - fee = proofs.as_ref().unwrap().base.fee; - } - }; - - fee -} - //---------------------------------------------------------------------------------------------------- Blocks /// Generate a `static LazyLock`. /// @@ -311,12 +281,12 @@ transaction_verification_data! { //---------------------------------------------------------------------------------------------------- TESTS #[cfg(test)] mod tests { - use super::*; - use pretty_assertions::assert_eq; use crate::rpc::client::HttpRpcClient; + use super::*; + /// Assert the defined blocks are the same compared to ones received from a local RPC call. #[ignore] // FIXME: doesn't work in CI, we need a real unrestricted node #[tokio::test] From b211210fa24c220dac1c46824430e1a1accaaebf Mon Sep 17 00:00:00 2001 From: Boog900 <54e72d8a-345f-4599-bd90-c6b9bc7d0ec5@aleeas.com> Date: Sun, 8 Sep 2024 15:34:30 +0100 Subject: [PATCH 13/31] more doc updates --- storage/blockchain/src/ops/alt_block/block.rs | 7 ++----- storage/blockchain/src/ops/alt_block/mod.rs | 6 +++--- storage/blockchain/src/ops/alt_block/tx.rs | 8 +++++--- storage/blockchain/src/service/free.rs | 14 ++++++++++---- storage/blockchain/src/service/read.rs | 7 +++---- storage/blockchain/src/service/write.rs | 17 +++++++++-------- storage/blockchain/src/tables.rs | 16 ++++++++++++++++ test-utils/src/data/mod.rs | 6 ++---- test-utils/src/rpc/client.rs | 13 ++++++------- 9 files changed, 56 insertions(+), 38 deletions(-) diff --git a/storage/blockchain/src/ops/alt_block/block.rs b/storage/blockchain/src/ops/alt_block/block.rs index 07878d55b..5bc052b74 100644 --- a/storage/blockchain/src/ops/alt_block/block.rs +++ b/storage/blockchain/src/ops/alt_block/block.rs @@ -24,12 +24,9 @@ use crate::{ /// /// # Panics /// This function will panic if: -/// - `block.height` is == `0` +/// - `alt_block.height` is == `0` +/// - `alt_block.txs.len()` != `alt_block.block.transactions.len()` /// -/// # Already exists -/// This function will operate normally even if `block` already -/// exists, i.e., this function will not return `Err` even if you -/// call this function infinitely with the same block. pub fn add_alt_block( alt_block: &AltBlockInformation, tables: &mut impl TablesMut, diff --git a/storage/blockchain/src/ops/alt_block/mod.rs b/storage/blockchain/src/ops/alt_block/mod.rs index 36e4768ec..96c1cecff 100644 --- a/storage/blockchain/src/ops/alt_block/mod.rs +++ b/storage/blockchain/src/ops/alt_block/mod.rs @@ -18,8 +18,8 @@ //! ``` //! //! In that example if we were to receive an alt-block which immediately follows the top block of `ChainID(X)` -//! then that block will also be stored under `ChainID(X)`. However if it follows from another block from `ChainID(X)` -//! we will split into a chain with a different ID. +//! then that block will also be stored under `ChainID(X)`. However, if it follows from another block from `ChainID(X)` +//! we will split into a chain with a different ID: //! //! ```text //! | @@ -39,7 +39,7 @@ //! [`get_alt_chain_history_ranges`] covers this and is the method to get the ranges of heights needed from each [`ChainID`](cuprate_types::ChainId) //! to get all the alt-blocks in a given [`ChainID`](cuprate_types::ChainId). //! -//! Although this should be kept in mind as a possibility because Cuprate's block downloader will only track a single chain it is +//! Although this should be kept in mind as a possibility, because Cuprate's block downloader will only track a single chain it is //! unlikely that we will be tracking [`ChainID`](cuprate_types::ChainId) that don't immediately connect to the main-chain. //! //! ## Why not use block's previous field? diff --git a/storage/blockchain/src/ops/alt_block/tx.rs b/storage/blockchain/src/ops/alt_block/tx.rs index 5671e4b45..aa2e82f40 100644 --- a/storage/blockchain/src/ops/alt_block/tx.rs +++ b/storage/blockchain/src/ops/alt_block/tx.rs @@ -4,9 +4,11 @@ use monero_serai::transaction::Transaction; use cuprate_database::{DatabaseRo, DatabaseRw, RuntimeError, StorableVec}; use cuprate_types::VerifiedTransactionInformation; -use crate::ops::macros::{doc_add_alt_block_inner_invariant, doc_error}; -use crate::tables::{Tables, TablesMut}; -use crate::types::{AltTransactionInfo, TxHash}; +use crate::{ + ops::macros::{doc_add_alt_block_inner_invariant, doc_error}, + tables::{Tables, TablesMut}, + types::{AltTransactionInfo, TxHash}, +}; /// Adds a [`VerifiedTransactionInformation`] form an alt-block to the DB, if /// that transaction is not already in the DB. diff --git a/storage/blockchain/src/service/free.rs b/storage/blockchain/src/service/free.rs index 7a4e6ce6d..d12844f35 100644 --- a/storage/blockchain/src/service/free.rs +++ b/storage/blockchain/src/service/free.rs @@ -3,13 +3,14 @@ //---------------------------------------------------------------------------------------------------- Import use std::sync::Arc; -use crate::service::{init_read_service, init_write_service}; +use cuprate_database::{ConcreteEnv, InitError}; +use cuprate_types::{AltBlockInformation, VerifiedBlockInformation}; + use crate::{ config::Config, service::types::{BlockchainReadHandle, BlockchainWriteHandle}, }; -use cuprate_database::{ConcreteEnv, InitError}; -use cuprate_types::{AltBlockInformation, VerifiedBlockInformation}; +use crate::service::{init_read_service, init_write_service}; //---------------------------------------------------------------------------------------------------- Init #[cold] @@ -81,7 +82,12 @@ pub(super) const fn compact_history_genesis_not_included INITIAL_BLOCKS && !(top_block_height - INITIAL_BLOCKS + 2).is_power_of_two() } -//---------------------------------------------------------------------------------------------------- Compact history +//---------------------------------------------------------------------------------------------------- Map Block +/// Maps [`AltBlockInformation`] to [`VerifiedBlockInformation`] +/// +/// # Panics +/// This will panic if the block is invalid, so should only be used on blocks that have been popped from +/// the main-chain. pub(super) fn map_valid_alt_block_to_verified_block( alt_block: AltBlockInformation, ) -> VerifiedBlockInformation { diff --git a/storage/blockchain/src/service/read.rs b/storage/blockchain/src/service/read.rs index 835f2d6a6..3d0379e05 100644 --- a/storage/blockchain/src/service/read.rs +++ b/storage/blockchain/src/service/read.rs @@ -1,11 +1,11 @@ //! Database reader thread-pool definitions and logic. +//---------------------------------------------------------------------------------------------------- Import use std::{ collections::{HashMap, HashSet}, sync::Arc, }; -//---------------------------------------------------------------------------------------------------- Import use rayon::{ iter::{IntoParallelIterator, ParallelIterator}, prelude::*, @@ -14,18 +14,17 @@ use rayon::{ use thread_local::ThreadLocal; use cuprate_database::{ConcreteEnv, DatabaseRo, Env, EnvInner, RuntimeError}; -use cuprate_database_service::{init_thread_pool, DatabaseReadService, ReaderThreads}; +use cuprate_database_service::{DatabaseReadService, init_thread_pool, ReaderThreads}; use cuprate_helper::map::combine_low_high_bits_to_u128; use cuprate_types::{ blockchain::{BlockchainReadRequest, BlockchainResponse}, Chain, ChainId, ExtendedBlockHeader, OutputOnChain, }; -use crate::ops::alt_block::get_alt_block; use crate::{ ops::{ alt_block::{ - get_alt_block_extended_header_from_height, get_alt_block_hash, + get_alt_block, get_alt_block_extended_header_from_height, get_alt_block_hash, get_alt_chain_history_ranges, }, block::{ diff --git a/storage/blockchain/src/service/write.rs b/storage/blockchain/src/service/write.rs index 849a3030f..723843f53 100644 --- a/storage/blockchain/src/service/write.rs +++ b/storage/blockchain/src/service/write.rs @@ -5,8 +5,8 @@ use std::sync::Arc; use cuprate_database::{ConcreteEnv, DatabaseRo, DatabaseRw, Env, EnvInner, RuntimeError, TxRw}; use cuprate_database_service::DatabaseWriteHandle; use cuprate_types::{ - blockchain::{BlockchainResponse, BlockchainWriteRequest}, - AltBlockInformation, Chain, ChainId, VerifiedBlockInformation, + AltBlockInformation, + blockchain::{BlockchainResponse, BlockchainWriteRequest}, Chain, ChainId, VerifiedBlockInformation, }; use crate::{ @@ -107,8 +107,8 @@ fn pop_blocks(env: &ConcreteEnv, numb_blocks: usize) -> ResponseResult { let env_inner = env.env_inner(); let mut tx_rw = env_inner.tx_rw()?; - // TODO: try blocks - let result = { + // TODO: turn this function into a try block once stable. + let mut result = || { // flush all the current alt blocks as they may reference blocks to be popped. crate::ops::alt_block::flush_alt_blocks(&env_inner, &mut tx_rw)?; @@ -136,7 +136,7 @@ fn pop_blocks(env: &ConcreteEnv, numb_blocks: usize) -> ResponseResult { Ok(old_main_chain_id) }; - match result { + match result() { Ok(old_main_chain_id) => { TxRw::commit(tx_rw)?; Ok(BlockchainResponse::PopBlocks(old_main_chain_id)) @@ -156,7 +156,8 @@ fn reverse_reorg(env: &ConcreteEnv, chain_id: ChainId) -> ResponseResult { let env_inner = env.env_inner(); let tx_rw = env_inner.tx_rw()?; - let result = { + // TODO: turn this function into a try block once stable. + let result = || { let mut tables_mut = env_inner.open_tables_mut(&tx_rw)?; let chain_info = tables_mut.alt_chain_infos().get(&chain_id.into())?; @@ -197,7 +198,7 @@ fn reverse_reorg(env: &ConcreteEnv, chain_id: ChainId) -> ResponseResult { Ok(()) }; - match result { + match result() { Ok(()) => { TxRw::commit(tx_rw)?; Ok(BlockchainResponse::Ok) @@ -218,7 +219,7 @@ fn flush_alt_blocks(env: &ConcreteEnv) -> ResponseResult { let env_inner = env.env_inner(); let mut tx_rw = env_inner.tx_rw()?; - let result = { crate::ops::alt_block::flush_alt_blocks(&env_inner, &mut tx_rw) }; + let result = crate::ops::alt_block::flush_alt_blocks(&env_inner, &mut tx_rw); match result { Ok(()) => { diff --git a/storage/blockchain/src/tables.rs b/storage/blockchain/src/tables.rs index fa568ae6b..74d2e591e 100644 --- a/storage/blockchain/src/tables.rs +++ b/storage/blockchain/src/tables.rs @@ -131,21 +131,37 @@ cuprate_database::define_tables! { 14 => TxUnlockTime, TxId => UnlockTime, + /// Information on alt-chains. 15 => AltChainInfos, RawChainId => AltChainInfo, + /// Alt-block heights. + /// + /// Contains the height of all alt-blocks. 16 => AltBlockHeights, BlockHash => AltBlockHeight, + /// Alt-block information. + /// + /// Contains information on all alt-blocks. 17 => AltBlocksInfo, AltBlockHeight => CompactAltBlockInfo, + /// Alt-block blobs. + /// + /// Contains the raw bytes of all alt-blocks. 18 => AltBlockBlobs, AltBlockHeight => BlockBlob, + /// Alt-Block transactions blobs. + /// + /// Contains the raw bytes of alt transactions, if those transactions are not in the main-chain. 19 => AltTransactionBlobs, TxHash => TxBlob, + /// Alt-Block transactions information. + /// + /// Contains information on all alt transactions, even if they are in the main-chain. 20 => AltTransactionInfos, TxHash => AltTransactionInfo, } diff --git a/test-utils/src/data/mod.rs b/test-utils/src/data/mod.rs index b9d42fb86..3be409fe1 100644 --- a/test-utils/src/data/mod.rs +++ b/test-utils/src/data/mod.rs @@ -25,13 +25,11 @@ //! let tx: VerifiedTransactionInformation = TX_V1_SIG0.clone(); //! ``` -mod constants; pub use constants::{ BLOCK_43BD1F, BLOCK_5ECB7E, BLOCK_BBD604, BLOCK_F91043, TX_2180A8, TX_3BC7FF, TX_84D48D, TX_9E3F73, TX_B6B439, TX_D7FEBD, TX_E2D393, TX_E57440, }; +pub use statics::{BLOCK_V16_TX0, BLOCK_V1_TX2, BLOCK_V9_TX3, TX_V1_SIG0, TX_V1_SIG2, TX_V2_RCT3}; +mod constants; mod statics; -pub use statics::{ - tx_fee, BLOCK_V16_TX0, BLOCK_V1_TX2, BLOCK_V9_TX3, TX_V1_SIG0, TX_V1_SIG2, TX_V2_RCT3, -}; diff --git a/test-utils/src/rpc/client.rs b/test-utils/src/rpc/client.rs index fbe6fb9e4..3711334b7 100644 --- a/test-utils/src/rpc/client.rs +++ b/test-utils/src/rpc/client.rs @@ -1,18 +1,16 @@ //! HTTP RPC client. //---------------------------------------------------------------------------------------------------- Use -use serde::Deserialize; -use serde_json::json; -use tokio::task::spawn_blocking; - use monero_rpc::Rpc; use monero_serai::block::Block; use monero_simple_request_rpc::SimpleRequestRpc; +use serde::Deserialize; +use serde_json::json; +use tokio::task::spawn_blocking; +use cuprate_helper::tx_utils::tx_fee; use cuprate_types::{VerifiedBlockInformation, VerifiedTransactionInformation}; -use crate::data::tx_fee; - //---------------------------------------------------------------------------------------------------- Constants /// The default URL used for Monero RPC connections. pub const LOCALHOST_RPC_URL: &str = "http://127.0.0.1:18081"; @@ -184,9 +182,10 @@ impl HttpRpcClient { //---------------------------------------------------------------------------------------------------- TESTS #[cfg(test)] mod tests { - use super::*; use hex_literal::hex; + use super::*; + /// Assert the default address is localhost. #[tokio::test] async fn localhost() { From 68807e7563a86ac189b005797a687dd513a3b10d Mon Sep 17 00:00:00 2001 From: Boog900 <54e72d8a-345f-4599-bd90-c6b9bc7d0ec5@aleeas.com> Date: Sun, 8 Sep 2024 15:37:01 +0100 Subject: [PATCH 14/31] fmt --- storage/blockchain/src/service/free.rs | 6 ++++-- storage/blockchain/src/service/read.rs | 2 +- storage/blockchain/src/service/write.rs | 4 ++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/storage/blockchain/src/service/free.rs b/storage/blockchain/src/service/free.rs index d12844f35..d8a878c93 100644 --- a/storage/blockchain/src/service/free.rs +++ b/storage/blockchain/src/service/free.rs @@ -8,9 +8,11 @@ use cuprate_types::{AltBlockInformation, VerifiedBlockInformation}; use crate::{ config::Config, - service::types::{BlockchainReadHandle, BlockchainWriteHandle}, + service::{ + init_read_service, init_write_service, + types::{BlockchainReadHandle, BlockchainWriteHandle}, + }, }; -use crate::service::{init_read_service, init_write_service}; //---------------------------------------------------------------------------------------------------- Init #[cold] diff --git a/storage/blockchain/src/service/read.rs b/storage/blockchain/src/service/read.rs index 3d0379e05..73b2d2205 100644 --- a/storage/blockchain/src/service/read.rs +++ b/storage/blockchain/src/service/read.rs @@ -14,7 +14,7 @@ use rayon::{ use thread_local::ThreadLocal; use cuprate_database::{ConcreteEnv, DatabaseRo, Env, EnvInner, RuntimeError}; -use cuprate_database_service::{DatabaseReadService, init_thread_pool, ReaderThreads}; +use cuprate_database_service::{init_thread_pool, DatabaseReadService, ReaderThreads}; use cuprate_helper::map::combine_low_high_bits_to_u128; use cuprate_types::{ blockchain::{BlockchainReadRequest, BlockchainResponse}, diff --git a/storage/blockchain/src/service/write.rs b/storage/blockchain/src/service/write.rs index 723843f53..4038d94a5 100644 --- a/storage/blockchain/src/service/write.rs +++ b/storage/blockchain/src/service/write.rs @@ -5,8 +5,8 @@ use std::sync::Arc; use cuprate_database::{ConcreteEnv, DatabaseRo, DatabaseRw, Env, EnvInner, RuntimeError, TxRw}; use cuprate_database_service::DatabaseWriteHandle; use cuprate_types::{ - AltBlockInformation, - blockchain::{BlockchainResponse, BlockchainWriteRequest}, Chain, ChainId, VerifiedBlockInformation, + blockchain::{BlockchainResponse, BlockchainWriteRequest}, + AltBlockInformation, Chain, ChainId, VerifiedBlockInformation, }; use crate::{ From c03065bcd5569a631cc28687667445bfd0e5e151 Mon Sep 17 00:00:00 2001 From: Boog900 <54e72d8a-345f-4599-bd90-c6b9bc7d0ec5@aleeas.com> Date: Sun, 8 Sep 2024 18:42:25 +0100 Subject: [PATCH 15/31] fix imports --- types/src/blockchain.rs | 10 ++++++---- types/src/types.rs | 3 ++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/types/src/blockchain.rs b/types/src/blockchain.rs index 6c7ecf37b..f246e59a5 100644 --- a/types/src/blockchain.rs +++ b/types/src/blockchain.rs @@ -2,15 +2,17 @@ //! //! Tests that assert particular requests lead to particular //! responses are also tested in Cuprate's blockchain database crate. - +//! +//---------------------------------------------------------------------------------------------------- Import use std::{ collections::{HashMap, HashSet}, ops::Range, }; -use crate::{AltBlockInformation, ChainId}; -//---------------------------------------------------------------------------------------------------- Import -use crate::types::{Chain, ExtendedBlockHeader, OutputOnChain, VerifiedBlockInformation}; +use crate::{ + types::{Chain, ExtendedBlockHeader, OutputOnChain, VerifiedBlockInformation}, + AltBlockInformation, ChainId, +}; //---------------------------------------------------------------------------------------------------- ReadRequest /// A read request to the blockchain database. diff --git a/types/src/types.rs b/types/src/types.rs index c6e83d093..a60ce6c60 100644 --- a/types/src/types.rs +++ b/types/src/types.rs @@ -1,7 +1,8 @@ //! Various shared data types in Cuprate. -use std::num::NonZero; //---------------------------------------------------------------------------------------------------- Import +use std::num::NonZero; + use curve25519_dalek::edwards::EdwardsPoint; use monero_serai::{ block::Block, From 18d700b91dfcd38e5afd599312e0e2ac492ba41c Mon Sep 17 00:00:00 2001 From: Boog900 <54e72d8a-345f-4599-bd90-c6b9bc7d0ec5@aleeas.com> Date: Mon, 9 Sep 2024 22:56:35 +0100 Subject: [PATCH 16/31] fix fee --- helper/src/tx_utils.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helper/src/tx_utils.rs b/helper/src/tx_utils.rs index aeccf32b2..328c5bad5 100644 --- a/helper/src/tx_utils.rs +++ b/helper/src/tx_utils.rs @@ -22,7 +22,7 @@ pub fn tx_fee(tx: &Transaction) -> u64 { } for output in &prefix.outputs { - fee.checked_sub(output.amount.unwrap_or(0)).unwrap(); + fee = fee.checked_sub(output.amount.unwrap_or(0)).unwrap(); } } Transaction::V2 { proofs, .. } => { From 28f76057fb69a7de4daeea3ed0170a75e5a85ec4 Mon Sep 17 00:00:00 2001 From: Boog900 Date: Sun, 15 Sep 2024 18:17:25 +0100 Subject: [PATCH 17/31] Apply suggestions from code review Co-authored-by: hinto-janai --- storage/blockchain/src/ops/alt_block/mod.rs | 6 +++--- storage/blockchain/src/ops/alt_block/tx.rs | 4 ++-- storage/blockchain/src/ops/block.rs | 3 +-- storage/blockchain/src/ops/macros.rs | 5 +++-- storage/blockchain/src/service/write.rs | 8 ++++---- storage/blockchain/src/tables.rs | 4 ++-- storage/blockchain/src/types.rs | 2 +- types/src/blockchain.rs | 1 + 8 files changed, 17 insertions(+), 16 deletions(-) diff --git a/storage/blockchain/src/ops/alt_block/mod.rs b/storage/blockchain/src/ops/alt_block/mod.rs index 96c1cecff..e223cebe5 100644 --- a/storage/blockchain/src/ops/alt_block/mod.rs +++ b/storage/blockchain/src/ops/alt_block/mod.rs @@ -40,12 +40,12 @@ //! to get all the alt-blocks in a given [`ChainID`](cuprate_types::ChainId). //! //! Although this should be kept in mind as a possibility, because Cuprate's block downloader will only track a single chain it is -//! unlikely that we will be tracking [`ChainID`](cuprate_types::ChainId) that don't immediately connect to the main-chain. +//! unlikely that we will be tracking [`ChainID`](cuprate_types::ChainId)s that don't immediately connect to the main-chain. //! -//! ## Why not use block's previous field? +//! ## Why not use the block's `previous` field? //! //! Although that would be easier, it makes getting a range of block extremely slow, as we have to build the weight cache to verify -//! blocks, roughly 100,000 block headers needed, this cost was seen as too high. +//! blocks, roughly 100,000 block headers needed, this cost is too high. pub use block::*; pub use chain::*; pub use tx::*; diff --git a/storage/blockchain/src/ops/alt_block/tx.rs b/storage/blockchain/src/ops/alt_block/tx.rs index aa2e82f40..f2df6d8b9 100644 --- a/storage/blockchain/src/ops/alt_block/tx.rs +++ b/storage/blockchain/src/ops/alt_block/tx.rs @@ -10,8 +10,8 @@ use crate::{ types::{AltTransactionInfo, TxHash}, }; -/// Adds a [`VerifiedTransactionInformation`] form an alt-block to the DB, if -/// that transaction is not already in the DB. +/// Adds a [`VerifiedTransactionInformation`] from an alt-block +/// if it is not already in the DB. /// /// If the transaction is in the main-chain this function will still fill in the /// [`AltTransactionInfos`](crate::tables::AltTransactionInfos) table, as that diff --git a/storage/blockchain/src/ops/block.rs b/storage/blockchain/src/ops/block.rs index 295869257..55123931f 100644 --- a/storage/blockchain/src/ops/block.rs +++ b/storage/blockchain/src/ops/block.rs @@ -180,8 +180,7 @@ pub fn pop_block( block_blob, txs, block_hash: block_info.block_hash, - // We know the PoW is valid for this block so just set it so it will always verify as - // valid. + // We know the PoW is valid for this block so just set it so it will always verify as valid. pow_hash: [0; 32], height: block_height, weight: block_info.weight, diff --git a/storage/blockchain/src/ops/macros.rs b/storage/blockchain/src/ops/macros.rs index e547c7f24..18ec50687 100644 --- a/storage/blockchain/src/ops/macros.rs +++ b/storage/blockchain/src/ops/macros.rs @@ -32,10 +32,11 @@ When calling this function, ensure that either: } pub(super) use doc_add_block_inner_invariant; -// This is pretty much the same as [`doc_add_block_inner_invariant`], it's not worth the effort to reduce -// the duplication. /// Generate `# Invariant` documentation for internal alt block `fn`'s /// that should be called directly with caution. +/// +/// This is pretty much the same as [`doc_add_block_inner_invariant`], +/// it's not worth the effort to reduce the duplication. macro_rules! doc_add_alt_block_inner_invariant { () => { r#"# ⚠️ Invariant ⚠️ diff --git a/storage/blockchain/src/service/write.rs b/storage/blockchain/src/service/write.rs index 4038d94a5..cbfc3dba6 100644 --- a/storage/blockchain/src/service/write.rs +++ b/storage/blockchain/src/service/write.rs @@ -107,7 +107,7 @@ fn pop_blocks(env: &ConcreteEnv, numb_blocks: usize) -> ResponseResult { let env_inner = env.env_inner(); let mut tx_rw = env_inner.tx_rw()?; - // TODO: turn this function into a try block once stable. + // FIXME: turn this function into a try block once stable. let mut result = || { // flush all the current alt blocks as they may reference blocks to be popped. crate::ops::alt_block::flush_alt_blocks(&env_inner, &mut tx_rw)?; @@ -156,7 +156,7 @@ fn reverse_reorg(env: &ConcreteEnv, chain_id: ChainId) -> ResponseResult { let env_inner = env.env_inner(); let tx_rw = env_inner.tx_rw()?; - // TODO: turn this function into a try block once stable. + // FIXME: turn this function into a try block once stable. let result = || { let mut tables_mut = env_inner.open_tables_mut(&tx_rw)?; @@ -165,11 +165,11 @@ fn reverse_reorg(env: &ConcreteEnv, chain_id: ChainId) -> ResponseResult { // thing for us to check. assert_eq!(Chain::from(chain_info.parent_chain), Chain::Main); - let tob_block_height = + let top_block_height = crate::ops::blockchain::top_block_height(tables_mut.block_heights())?; // pop any blocks that were added as part of a re-org. - for _ in chain_info.common_ancestor_height..tob_block_height { + for _ in chain_info.common_ancestor_height..top_block_height { crate::ops::block::pop_block(None, &mut tables_mut)?; } diff --git a/storage/blockchain/src/tables.rs b/storage/blockchain/src/tables.rs index 74d2e591e..75c33ae7b 100644 --- a/storage/blockchain/src/tables.rs +++ b/storage/blockchain/src/tables.rs @@ -153,13 +153,13 @@ cuprate_database::define_tables! { 18 => AltBlockBlobs, AltBlockHeight => BlockBlob, - /// Alt-Block transactions blobs. + /// Alt-block transaction blobs. /// /// Contains the raw bytes of alt transactions, if those transactions are not in the main-chain. 19 => AltTransactionBlobs, TxHash => TxBlob, - /// Alt-Block transactions information. + /// Alt-block transaction information. /// /// Contains information on all alt transactions, even if they are in the main-chain. 20 => AltTransactionInfos, diff --git a/storage/blockchain/src/types.rs b/storage/blockchain/src/types.rs index e96656951..6afd3d4bb 100644 --- a/storage/blockchain/src/types.rs +++ b/storage/blockchain/src/types.rs @@ -414,7 +414,7 @@ impl From for RawChainId { impl From for ChainId { fn from(value: RawChainId) -> Self { - Self(NonZero::new(value.0).expect("RawChainId mut not have a value of `0`")) + Self(NonZero::new(value.0).expect("RawChainId cannot have a value of `0`")) } } diff --git a/types/src/blockchain.rs b/types/src/blockchain.rs index f246e59a5..099668c05 100644 --- a/types/src/blockchain.rs +++ b/types/src/blockchain.rs @@ -101,6 +101,7 @@ pub enum BlockchainReadRequest { /// order, or else the returned response is unspecified and meaningless, /// as this request performs a binary search. FindFirstUnknown(Vec<[u8; 32]>), + /// A request for all alt blocks in the chain with the given [`ChainId`]. AltBlocksInChain(ChainId), } From 0907454e25a79e2b4eb2b6fa015b4eb31a285498 Mon Sep 17 00:00:00 2001 From: Boog900 <54e72d8a-345f-4599-bd90-c6b9bc7d0ec5@aleeas.com> Date: Sun, 15 Sep 2024 18:20:42 +0100 Subject: [PATCH 18/31] remove default features from `cuprate-helper` --- helper/Cargo.toml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/helper/Cargo.toml b/helper/Cargo.toml index 4bd17ca89..c9bee5181 100644 --- a/helper/Cargo.toml +++ b/helper/Cargo.toml @@ -9,9 +9,8 @@ repository = "https://github.com/Cuprate/cuprate/tree/main/consensus" [features] -# TODO: I don't think this is a good idea -# All features on by default. -default = ["std", "atomic", "asynch", "cast", "fs", "num", "map", "time", "thread", "constants", "tx-utils"] +# All features off by default. +default = [] std = [] atomic = ["dep:crossbeam"] asynch = ["dep:futures", "dep:rayon"] From 47fb1a2d4a1460889411293f6c87ef23dd115d37 Mon Sep 17 00:00:00 2001 From: Boog900 <54e72d8a-345f-4599-bd90-c6b9bc7d0ec5@aleeas.com> Date: Sun, 15 Sep 2024 18:38:00 +0100 Subject: [PATCH 19/31] review fixes --- helper/src/lib.rs | 2 +- helper/src/{tx_utils.rs => tx.rs} | 0 storage/blockchain/src/ops/block.rs | 8 ++++++-- test-utils/src/data/statics.rs | 2 +- test-utils/src/rpc/client.rs | 2 +- types/src/blockchain.rs | 5 ++++- 6 files changed, 13 insertions(+), 6 deletions(-) rename helper/src/{tx_utils.rs => tx.rs} (100%) diff --git a/helper/src/lib.rs b/helper/src/lib.rs index e82ec827d..ed78af1ea 100644 --- a/helper/src/lib.rs +++ b/helper/src/lib.rs @@ -32,7 +32,7 @@ pub mod thread; pub mod time; #[cfg(feature = "tx-utils")] -pub mod tx_utils; +pub mod tx; //---------------------------------------------------------------------------------------------------- Private Usage //---------------------------------------------------------------------------------------------------- diff --git a/helper/src/tx_utils.rs b/helper/src/tx.rs similarity index 100% rename from helper/src/tx_utils.rs rename to helper/src/tx.rs diff --git a/storage/blockchain/src/ops/block.rs b/storage/blockchain/src/ops/block.rs index 55123931f..a9a0df4f2 100644 --- a/storage/blockchain/src/ops/block.rs +++ b/storage/blockchain/src/ops/block.rs @@ -9,7 +9,7 @@ use cuprate_database::{ }; use cuprate_helper::{ map::{combine_low_high_bits_to_u128, split_u128_into_low_high_bits}, - tx_utils::tx_fee, + tx::tx_fee, }; use cuprate_types::{ AltBlockInformation, ChainId, ExtendedBlockHeader, HardFork, VerifiedBlockInformation, @@ -156,7 +156,11 @@ pub fn pop_block( let block = Block::read(&mut block_blob.as_slice())?; //------------------------------------------------------ Transaction / Outputs / Key Images - let mut txs = Vec::with_capacity(block.transactions.len()); + let mut txs = if move_to_alt_chain.is_some() { + Vec::with_capacity(block.transactions.len()) + } else { + Vec::new() + }; remove_tx(&block.miner_transaction.hash(), tables)?; for tx_hash in &block.transactions { diff --git a/test-utils/src/data/statics.rs b/test-utils/src/data/statics.rs index a45cc13fa..2ae97115f 100644 --- a/test-utils/src/data/statics.rs +++ b/test-utils/src/data/statics.rs @@ -11,7 +11,7 @@ use std::sync::LazyLock; use hex_literal::hex; use monero_serai::{block::Block, transaction::Transaction}; -use cuprate_helper::{map::combine_low_high_bits_to_u128, tx_utils::tx_fee}; +use cuprate_helper::{map::combine_low_high_bits_to_u128, tx::tx_fee}; use cuprate_types::{VerifiedBlockInformation, VerifiedTransactionInformation}; use crate::data::constants::{ diff --git a/test-utils/src/rpc/client.rs b/test-utils/src/rpc/client.rs index 3711334b7..cd54066a0 100644 --- a/test-utils/src/rpc/client.rs +++ b/test-utils/src/rpc/client.rs @@ -8,7 +8,7 @@ use serde::Deserialize; use serde_json::json; use tokio::task::spawn_blocking; -use cuprate_helper::tx_utils::tx_fee; +use cuprate_helper::tx::tx_fee; use cuprate_types::{VerifiedBlockInformation, VerifiedTransactionInformation}; //---------------------------------------------------------------------------------------------------- Constants diff --git a/types/src/blockchain.rs b/types/src/blockchain.rs index 099668c05..f2b96db00 100644 --- a/types/src/blockchain.rs +++ b/types/src/blockchain.rs @@ -2,7 +2,6 @@ //! //! Tests that assert particular requests lead to particular //! responses are also tested in Cuprate's blockchain database crate. -//! //---------------------------------------------------------------------------------------------------- Import use std::{ collections::{HashMap, HashSet}, @@ -114,10 +113,12 @@ pub enum BlockchainWriteRequest { /// /// Input is an already verified block. WriteBlock(VerifiedBlockInformation), + /// Write an alternative block to the database, /// /// Input is the alternative block. WriteAltBlock(AltBlockInformation), + /// A request to pop some blocks from the top of the main chain /// /// Input is the amount of blocks to pop. @@ -125,6 +126,7 @@ pub enum BlockchainWriteRequest { /// This request flushes all alt-chains from the cache before adding the popped blocks to the /// alt cache. PopBlocks(usize), + /// A request to reverse the re-org process. /// /// The inner value is the [`ChainId`] of the old main chain. @@ -132,6 +134,7 @@ pub enum BlockchainWriteRequest { /// # Invariant /// It is invalid to call this with a [`ChainId`] that was not returned from [`BlockchainWriteRequest::PopBlocks`]. ReverseReorg(ChainId), + /// A request to flush all alternative blocks. FlushAltBlocks, } From 19117bbef3687104b875fbe736721555c660972b Mon Sep 17 00:00:00 2001 From: Boog900 <54e72d8a-345f-4599-bd90-c6b9bc7d0ec5@aleeas.com> Date: Sun, 15 Sep 2024 19:42:48 +0100 Subject: [PATCH 20/31] fix find_block --- storage/blockchain/src/service/read.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/storage/blockchain/src/service/read.rs b/storage/blockchain/src/service/read.rs index 73b2d2205..3a5dc8425 100644 --- a/storage/blockchain/src/service/read.rs +++ b/storage/blockchain/src/service/read.rs @@ -231,12 +231,14 @@ fn find_block(env: &ConcreteEnv, block_hash: BlockHash) -> ResponseResult { let table_alt_block_heights = env_inner.open_db_ro::(&tx_ro)?; - let height = table_alt_block_heights.get(&block_hash)?; - - Ok(BlockchainResponse::FindBlock(Some(( - Chain::Alt(height.chain_id.into()), - height.height, - )))) + match table_alt_block_heights.get(&block_hash) { + Ok(height) => Ok(BlockchainResponse::FindBlock(Some(( + Chain::Alt(height.chain_id.into()), + height.height, + )))), + Err(RuntimeError::KeyNotFound) => Ok(BlockchainResponse::FindBlock(None)), + Err(e) => Err(e), + } } /// [`BlockchainReadRequest::FilterUnknownHashes`]. From 0a9528304005567c58752b45d187c33b7e101d03 Mon Sep 17 00:00:00 2001 From: Boog900 <54e72d8a-345f-4599-bd90-c6b9bc7d0ec5@aleeas.com> Date: Mon, 16 Sep 2024 02:45:40 +0100 Subject: [PATCH 21/31] add a test and fix some issues in chain history --- storage/blockchain/src/ops/alt_block/chain.rs | 20 +++- storage/blockchain/src/service/tests.rs | 93 ++++++++++++++++++- storage/blockchain/src/service/write.rs | 9 +- 3 files changed, 115 insertions(+), 7 deletions(-) diff --git a/storage/blockchain/src/ops/alt_block/chain.rs b/storage/blockchain/src/ops/alt_block/chain.rs index 3e27d7d4b..988c4c432 100644 --- a/storage/blockchain/src/ops/alt_block/chain.rs +++ b/storage/blockchain/src/ops/alt_block/chain.rs @@ -1,4 +1,4 @@ -use std::cmp::max; +use std::cmp::{max, min}; use cuprate_database::{DatabaseRo, DatabaseRw, RuntimeError}; use cuprate_types::{Chain, ChainId}; @@ -73,8 +73,12 @@ pub fn get_alt_chain_history_ranges( let chain_info = alt_chain_infos.get(¤t_chain_id)?; let start_height = max(range.start, chain_info.common_ancestor_height + 1); + let end_height = min(i, chain_info.chain_height); - ranges.push((Chain::Alt(current_chain_id.into()), start_height..i)); + ranges.push(( + Chain::Alt(current_chain_id.into()), + start_height..end_height, + )); i = chain_info.common_ancestor_height + 1; match chain_info.parent_chain.into() { @@ -83,7 +87,17 @@ pub fn get_alt_chain_history_ranges( break; } Chain::Alt(alt_chain_id) => { - current_chain_id = alt_chain_id.into(); + let alt_chain_id = alt_chain_id.into(); + + // This shouldn't be possible to hit, however in a test with custom (invalid) block data + // this caused an infinite loop. + if alt_chain_id == current_chain_id { + return Err(RuntimeError::Io(std::io::Error::other( + "Loop detected in ChainIDs, invalid alt chain.", + ))); + } + + current_chain_id = alt_chain_id; continue; } } diff --git a/storage/blockchain/src/service/tests.rs b/storage/blockchain/src/service/tests.rs index 78cb6944a..a96b09273 100644 --- a/storage/blockchain/src/service/tests.rs +++ b/storage/blockchain/src/service/tests.rs @@ -13,15 +13,17 @@ use std::{ }; use pretty_assertions::assert_eq; +use rand::Rng; use tower::{Service, ServiceExt}; use cuprate_database::{ConcreteEnv, DatabaseIter, DatabaseRo, Env, EnvInner, RuntimeError}; use cuprate_test_utils::data::{BLOCK_V16_TX0, BLOCK_V1_TX2, BLOCK_V9_TX3}; use cuprate_types::{ blockchain::{BlockchainReadRequest, BlockchainResponse, BlockchainWriteRequest}, - Chain, OutputOnChain, VerifiedBlockInformation, + Chain, ChainId, OutputOnChain, VerifiedBlockInformation, }; +use crate::tests::map_verified_block_to_alt; use crate::{ config::ConfigBuilder, ops::{ @@ -407,3 +409,92 @@ async fn v16_tx0() { ) .await; } + +/// Tests the alt-chain requests and responses. +#[tokio::test] +async fn alt_chain_requests() { + let (reader, mut writer, _, _tempdir) = init_service(); + + // Set up the test by adding blocks to the main-chain. + for (i, mut block) in [BLOCK_V9_TX3.clone(), BLOCK_V16_TX0.clone()] + .into_iter() + .enumerate() + { + block.height = i; + + let request = BlockchainWriteRequest::WriteBlock(block); + writer.call(request).await.unwrap(); + } + + // Generate the alt-blocks. + let mut prev_hash = BLOCK_V9_TX3.block_hash; + let mut chain_id = 1; + let alt_blocks = [&BLOCK_V16_TX0, &BLOCK_V9_TX3, &BLOCK_V1_TX2] + .into_iter() + .enumerate() + .map(|(i, block)| { + let mut block = (**block).clone(); + block.height = i + 1; + block.block.header.previous = prev_hash; + block.block_blob = block.block.serialize(); + + prev_hash = block.block_hash; + // Randomly either keep the [`ChainId`] the same or change it to a new value. + chain_id += rand::thread_rng().gen_range(0..=1); + + map_verified_block_to_alt(block, ChainId(chain_id.try_into().unwrap())) + }) + .collect::>(); + + for block in alt_blocks.iter() { + // Request a block to be written, assert it was written. + let request = BlockchainWriteRequest::WriteAltBlock(block.clone()); + let response_channel = writer.call(request); + let response = response_channel.await.unwrap(); + assert_eq!(response, BlockchainResponse::Ok); + } + + // Get the full alt-chain + let request = BlockchainReadRequest::AltBlocksInChain(ChainId(chain_id.try_into().unwrap())); + let response = reader.clone().oneshot(request).await.unwrap(); + + let BlockchainResponse::AltBlocksInChain(blocks) = response else { + panic!("Wrong response type was returned"); + }; + + assert_eq!(blocks.len(), alt_blocks.len()); + for (got_block, alt_block) in blocks.into_iter().zip(alt_blocks) { + assert_eq!(got_block.block_blob, alt_block.block_blob); + assert_eq!(got_block.block_hash, alt_block.block_hash); + assert_eq!(got_block.chain_id, alt_block.chain_id); + assert_eq!(got_block.txs, alt_block.txs); + } + + // Flush all alt blocks. + let request = BlockchainWriteRequest::FlushAltBlocks; + let response = writer.ready().await.unwrap().call(request).await.unwrap(); + assert_eq!(response, BlockchainResponse::Ok); + + // Pop blocks from the main chain + let request = BlockchainWriteRequest::PopBlocks(1); + let response = writer.ready().await.unwrap().call(request).await.unwrap(); + + let BlockchainResponse::PopBlocks(old_main_chain_id) = response else { + panic!("Wrong response type was returned"); + }; + + // Check we have popped the top block. + let request = BlockchainReadRequest::ChainHeight; + let response = reader.clone().oneshot(request).await.unwrap(); + assert!(matches!(response, BlockchainResponse::ChainHeight(1, _))); + + // Attempt to add the popped block back. + let request = BlockchainWriteRequest::ReverseReorg(old_main_chain_id); + let response = writer.ready().await.unwrap().call(request).await.unwrap(); + assert_eq!(response, BlockchainResponse::Ok); + + // Check we have the popped block back. + let request = BlockchainReadRequest::ChainHeight; + let response = reader.clone().oneshot(request).await.unwrap(); + assert!(matches!(response, BlockchainResponse::ChainHeight(2, _))); +} diff --git a/storage/blockchain/src/service/write.rs b/storage/blockchain/src/service/write.rs index cbfc3dba6..176ab518f 100644 --- a/storage/blockchain/src/service/write.rs +++ b/storage/blockchain/src/service/write.rs @@ -154,10 +154,10 @@ fn pop_blocks(env: &ConcreteEnv, numb_blocks: usize) -> ResponseResult { /// [`BlockchainWriteRequest::ReverseReorg`]. fn reverse_reorg(env: &ConcreteEnv, chain_id: ChainId) -> ResponseResult { let env_inner = env.env_inner(); - let tx_rw = env_inner.tx_rw()?; + let mut tx_rw = env_inner.tx_rw()?; // FIXME: turn this function into a try block once stable. - let result = || { + let mut result = || { let mut tables_mut = env_inner.open_tables_mut(&tx_rw)?; let chain_info = tables_mut.alt_chain_infos().get(&chain_id.into())?; @@ -174,7 +174,7 @@ fn reverse_reorg(env: &ConcreteEnv, chain_id: ChainId) -> ResponseResult { } // Rust borrow rules requires us to collect into a Vec first before looping over the Vec. - let alt_blocks = (chain_info.common_ancestor_height..chain_info.chain_height) + let alt_blocks = ((chain_info.common_ancestor_height + 1)..chain_info.chain_height) .map(|height| { crate::ops::alt_block::get_alt_block( &AltBlockHeight { @@ -195,6 +195,9 @@ fn reverse_reorg(env: &ConcreteEnv, chain_id: ChainId) -> ResponseResult { crate::ops::block::add_block(&verified_block, &mut tables_mut)?; } + drop(tables_mut); + crate::ops::alt_block::flush_alt_blocks(&env_inner, &mut tx_rw)?; + Ok(()) }; From 060e7cab0809c38e2331dc5c0c4d045ffc0a79cc Mon Sep 17 00:00:00 2001 From: Boog900 <54e72d8a-345f-4599-bd90-c6b9bc7d0ec5@aleeas.com> Date: Mon, 16 Sep 2024 02:57:17 +0100 Subject: [PATCH 22/31] fix clippy --- storage/blockchain/src/service/tests.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/storage/blockchain/src/service/tests.rs b/storage/blockchain/src/service/tests.rs index a96b09273..15c54de2b 100644 --- a/storage/blockchain/src/service/tests.rs +++ b/storage/blockchain/src/service/tests.rs @@ -23,7 +23,6 @@ use cuprate_types::{ Chain, ChainId, OutputOnChain, VerifiedBlockInformation, }; -use crate::tests::map_verified_block_to_alt; use crate::{ config::ConfigBuilder, ops::{ @@ -33,7 +32,7 @@ use crate::{ }, service::{init, BlockchainReadHandle, BlockchainWriteHandle}, tables::{OpenTables, Tables, TablesIter}, - tests::AssertTableLen, + tests::{AssertTableLen, map_verified_block_to_alt}, types::{Amount, AmountIndex, PreRctOutputId}, }; @@ -446,7 +445,7 @@ async fn alt_chain_requests() { }) .collect::>(); - for block in alt_blocks.iter() { + for block in &alt_blocks { // Request a block to be written, assert it was written. let request = BlockchainWriteRequest::WriteAltBlock(block.clone()); let response_channel = writer.call(request); From fb592e3cda6831f1ec9ed4cac345132875032ce3 Mon Sep 17 00:00:00 2001 From: Boog900 <54e72d8a-345f-4599-bd90-c6b9bc7d0ec5@aleeas.com> Date: Mon, 16 Sep 2024 02:58:08 +0100 Subject: [PATCH 23/31] fmt --- storage/blockchain/src/service/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/blockchain/src/service/tests.rs b/storage/blockchain/src/service/tests.rs index 15c54de2b..cb66303ed 100644 --- a/storage/blockchain/src/service/tests.rs +++ b/storage/blockchain/src/service/tests.rs @@ -32,7 +32,7 @@ use crate::{ }, service::{init, BlockchainReadHandle, BlockchainWriteHandle}, tables::{OpenTables, Tables, TablesIter}, - tests::{AssertTableLen, map_verified_block_to_alt}, + tests::{map_verified_block_to_alt, AssertTableLen}, types::{Amount, AmountIndex, PreRctOutputId}, }; From 6aeb720dcd080fcf796c7fac23f2ade347da4c4f Mon Sep 17 00:00:00 2001 From: Boog900 Date: Wed, 18 Sep 2024 16:40:09 +0100 Subject: [PATCH 24/31] Apply suggestions from code review Co-authored-by: hinto-janai --- helper/Cargo.toml | 2 +- helper/src/lib.rs | 2 +- helper/src/tx.rs | 36 +++++++++++++++++++++ storage/blockchain/src/ops/alt_block/mod.rs | 10 +++--- storage/blockchain/src/ops/alt_block/tx.rs | 4 ++- test-utils/Cargo.toml | 2 +- 6 files changed, 48 insertions(+), 8 deletions(-) diff --git a/helper/Cargo.toml b/helper/Cargo.toml index c9bee5181..cc6627f73 100644 --- a/helper/Cargo.toml +++ b/helper/Cargo.toml @@ -21,7 +21,7 @@ num = [] map = ["cast", "dep:monero-serai"] time = ["dep:chrono", "std"] thread = ["std", "dep:target_os_lib"] -tx-utils = ["dep:monero-serai"] +tx = ["dep:monero-serai"] [dependencies] crossbeam = { workspace = true, optional = true } diff --git a/helper/src/lib.rs b/helper/src/lib.rs index ed78af1ea..f29c49949 100644 --- a/helper/src/lib.rs +++ b/helper/src/lib.rs @@ -31,7 +31,7 @@ pub mod thread; #[cfg(feature = "time")] pub mod time; -#[cfg(feature = "tx-utils")] +#[cfg(feature = "tx")] pub mod tx; //---------------------------------------------------------------------------------------------------- Private Usage diff --git a/helper/src/tx.rs b/helper/src/tx.rs index 328c5bad5..53706ecf2 100644 --- a/helper/src/tx.rs +++ b/helper/src/tx.rs @@ -32,3 +32,39 @@ pub fn tx_fee(tx: &Transaction) -> u64 { fee } + +#[cfg(test)] +mod test { + use curve25519_dalek::{edwards::CompressedEdwardsY, EdwardsPoint}; + use monero_serai::transaction::{NotPruned, Output, Timelock, TransactionPrefix}; + + use super::*; + + #[test] + #[should_panic(expected = "called `Option::unwrap()` on a `None` value")] + fn tx_fee_panic() { + let input = Input::ToKey { + amount: Some(u64::MAX), + key_offsets: vec![], + key_image: EdwardsPoint::default(), + }; + + let output = Output { + amount: Some(u64::MAX), + key: CompressedEdwardsY::default(), + view_tag: None, + }; + + let tx = Transaction::::V1 { + prefix: TransactionPrefix { + additional_timelock: Timelock::None, + inputs: vec![input; 2], + outputs: vec![output], + extra: vec![], + }, + signatures: vec![], + }; + + tx_fee(&tx); + } +} diff --git a/storage/blockchain/src/ops/alt_block/mod.rs b/storage/blockchain/src/ops/alt_block/mod.rs index e223cebe5..8d102c86a 100644 --- a/storage/blockchain/src/ops/alt_block/mod.rs +++ b/storage/blockchain/src/ops/alt_block/mod.rs @@ -46,14 +46,16 @@ //! //! Although that would be easier, it makes getting a range of block extremely slow, as we have to build the weight cache to verify //! blocks, roughly 100,000 block headers needed, this cost is too high. -pub use block::*; -pub use chain::*; -pub use tx::*; - mod block; mod chain; mod tx; +pub use block::{ + add_alt_block, get_alt_block, get_alt_block_extended_header_from_height, get_alt_block_hash, +}; +pub use chain::{get_alt_chain_history_ranges, update_alt_chain_info}; +pub use tx::{add_alt_transaction_blob, get_alt_transaction}; + /// Flush all alt-block data from all the alt-block tables. /// /// This function completely empties the alt block tables. diff --git a/storage/blockchain/src/ops/alt_block/tx.rs b/storage/blockchain/src/ops/alt_block/tx.rs index f2df6d8b9..4185c6cb1 100644 --- a/storage/blockchain/src/ops/alt_block/tx.rs +++ b/storage/blockchain/src/ops/alt_block/tx.rs @@ -40,7 +40,9 @@ pub fn add_alt_transaction_blob( tables .alt_transaction_blobs_mut() - .put(&tx.tx_hash, StorableVec::wrap_ref(&tx.tx_blob)) + .put(&tx.tx_hash, StorableVec::wrap_ref(&tx.tx_blob))?; + + Ok(()) } /// Retrieve a [`VerifiedTransactionInformation`] from the database. diff --git a/test-utils/Cargo.toml b/test-utils/Cargo.toml index 9c64bd81b..a38f6c9ab 100644 --- a/test-utils/Cargo.toml +++ b/test-utils/Cargo.toml @@ -7,7 +7,7 @@ authors = ["Boog900", "hinto-janai"] [dependencies] cuprate-types = { path = "../types" } -cuprate-helper = { path = "../helper", features = ["map", "tx-utils"] } +cuprate-helper = { path = "../helper", features = ["map", "tx"] } cuprate-wire = { path = "../net/wire" } cuprate-p2p-core = { path = "../p2p/p2p-core", features = ["borsh"] } From c4c025aade0766cb5fac9c6ccb3158e9b85ed71c Mon Sep 17 00:00:00 2001 From: Boog900 <54e72d8a-345f-4599-bd90-c6b9bc7d0ec5@aleeas.com> Date: Wed, 18 Sep 2024 17:13:09 +0100 Subject: [PATCH 25/31] add dev dep --- Cargo.lock | 1 + helper/Cargo.toml | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 41847c6f2..7485ff268 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -696,6 +696,7 @@ version = "0.1.0" dependencies = [ "chrono", "crossbeam", + "curve25519-dalek", "dirs", "futures", "libc", diff --git a/helper/Cargo.toml b/helper/Cargo.toml index cc6627f73..baa3f23ed 100644 --- a/helper/Cargo.toml +++ b/helper/Cargo.toml @@ -40,7 +40,8 @@ target_os_lib = { package = "windows", version = ">=0.51", features = ["Win32_Sy target_os_lib = { package = "libc", version = "0.2.151", optional = true } [dev-dependencies] -tokio = { workspace = true, features = ["full"] } +tokio = { workspace = true, features = ["full"] } +curve25519-dalek = { workspace = true } [lints] workspace = true \ No newline at end of file From 51aa1b6ce497000ae64ebe2f54cd4c35e7ad0e12 Mon Sep 17 00:00:00 2001 From: Boog900 <54e72d8a-345f-4599-bd90-c6b9bc7d0ec5@aleeas.com> Date: Wed, 18 Sep 2024 18:03:59 +0100 Subject: [PATCH 26/31] cargo update --- Cargo.lock | 832 ++++++++++++++++++++--------------------------------- 1 file changed, 309 insertions(+), 523 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7485ff268..0e373caa3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,19 +4,13 @@ version = 3 [[package]] name = "addr2line" -version = "0.22.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375" dependencies = [ "gimli", ] -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - [[package]] name = "adler2" version = "2.0.0" @@ -52,9 +46,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" [[package]] name = "async-stream" @@ -75,18 +69,18 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.77", ] [[package]] name = "async-trait" -version = "0.1.80" +version = "0.1.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" +checksum = "a27b8a3a6e1a44fa4c8baf1f653e4172e81486d4941f2237e20dc2d0cf4ddff1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.77", ] [[package]] @@ -158,17 +152,17 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.73" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cc", "cfg-if", "libc", - "miniz_oxide 0.7.3", + "miniz_oxide", "object", "rustc-demangle", + "windows-targets 0.52.6", ] [[package]] @@ -209,9 +203,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" dependencies = [ "bytemuck", "serde", @@ -267,7 +261,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.77", "syn_derive", ] @@ -279,22 +273,22 @@ checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytemuck" -version = "1.16.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78834c15cb5d5efe3452d58b1e8ba890dd62d21907f867f383358198e56ebca5" +checksum = "94bbb0ad554ad961ddc5da507a12a29b14e4ae5bda06b19f575a3e6079d2e2ae" dependencies = [ "bytemuck_derive", ] [[package]] name = "bytemuck_derive" -version = "1.7.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ee891b04274a59bd38b412188e24b849617b2e45a0fd8d057deb63e7403761b" +checksum = "0cc8b54b395f2fcfbb3d90c47b01c7f444d94d05bdeb775811dec868ac3bbc26" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.77", ] [[package]] @@ -305,18 +299,21 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.6.0" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" dependencies = [ "serde", ] [[package]] name = "cc" -version = "1.0.99" +version = "1.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" +checksum = "07b1695e2c7e8fc85310cde85aeaab7e3097f593c91d209d3f9df76c928100f0" +dependencies = [ + "shlex", +] [[package]] name = "cfg-if" @@ -339,14 +336,14 @@ dependencies = [ "android-tzdata", "iana-time-zone", "num-traits", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] name = "clap" -version = "4.5.7" +version = "4.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f" +checksum = "3e5a21b8495e732f1b3c364c9949b201ca7bae518c502c80256c96ad79eaf6ac" dependencies = [ "clap_builder", "clap_derive", @@ -354,9 +351,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.7" +version = "4.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f" +checksum = "8cf2dd12af7a047ad9d6da2b6b249759a22a7abc0f474c1dae1777afa4b21a73" dependencies = [ "anstyle", "clap_lex", @@ -364,21 +361,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.5" +version = "4.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6" +checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.77", ] [[package]] name = "clap_lex" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" [[package]] name = "core-foundation" @@ -392,15 +389,15 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" dependencies = [ "libc", ] @@ -523,7 +520,7 @@ dependencies = [ name = "cuprate-blockchain" version = "0.0.0" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "bytemuck", "cuprate-database", "cuprate-database-service", @@ -720,7 +717,7 @@ dependencies = [ name = "cuprate-levin" version = "0.1.0" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "bytes", "cuprate-helper", "futures", @@ -859,7 +856,7 @@ dependencies = [ name = "cuprate-txpool" version = "0.0.0" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "bytemuck", "cuprate-database", "cuprate-database-service", @@ -896,7 +893,7 @@ dependencies = [ name = "cuprate-wire" version = "0.1.0" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "bytes", "cuprate-epee-encoding", "cuprate-fixed-bytes", @@ -937,7 +934,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.77", ] [[package]] @@ -1020,17 +1017,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "displaydoc" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", -] - [[package]] name = "doxygen-rs" version = "0.4.2" @@ -1042,9 +1028,9 @@ dependencies = [ [[package]] name = "either" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "equivalent" @@ -1064,9 +1050,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" [[package]] name = "ff" @@ -1092,7 +1078,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" dependencies = [ "crc32fast", - "miniz_oxide 0.8.0", + "miniz_oxide", ] [[package]] @@ -1173,7 +1159,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.77", ] [[package]] @@ -1229,9 +1215,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.29.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" +checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" [[package]] name = "group" @@ -1280,11 +1266,11 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "heed" -version = "0.20.2" +version = "0.20.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f60d7cff16094be9627830b399c087a25017e93fb3768b87cd656a68ccb1ebe8" +checksum = "7d4f449bab7320c56003d37732a917e18798e2f1709d80263face2b4f9436ddb" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "byteorder", "heed-traits", "heed-types", @@ -1305,9 +1291,9 @@ checksum = "eb3130048d404c57ce5a1ac61a903696e8fcde7e8c2991e9fcfc1f27c3ef74ff" [[package]] name = "heed-types" -version = "0.20.0" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cb0d6ba3700c9a57e83c013693e3eddb68a6d9b6781cacafc62a0d992e8ddb3" +checksum = "9d3f528b053a6d700b2734eabcd0fd49cb8230647aa72958467527b0b7917114" dependencies = [ "bincode", "byteorder", @@ -1347,9 +1333,9 @@ dependencies = [ [[package]] name = "http-body" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", "http", @@ -1370,9 +1356,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.9.3" +version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0e7a4dd27b9476dc40cb050d3632d3bba3a70ddbff012285f7f8559a1e7e545" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" [[package]] name = "httpdate" @@ -1382,9 +1368,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "1.3.1" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" dependencies = [ "bytes", "futures-channel", @@ -1403,9 +1389,9 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.2" +version = "0.27.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" +checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" dependencies = [ "futures-util", "http", @@ -1421,9 +1407,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.5" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b875924a60b96e5d7b9ae7b066540b1dd1cbd90d1828f54c92e02a283351c56" +checksum = "da62f120a8a37763efb0cf8fdf264b884c7b8b9ac8660b900c8661030c00e6ba" dependencies = [ "bytes", "futures-channel", @@ -1441,9 +1427,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.60" +version = "0.1.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -1462,141 +1448,21 @@ dependencies = [ "cc", ] -[[package]] -name = "icu_collections" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" -dependencies = [ - "displaydoc", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_locid" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" -dependencies = [ - "displaydoc", - "litemap", - "tinystr", - "writeable", - "zerovec", -] - -[[package]] -name = "icu_locid_transform" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_locid_transform_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_locid_transform_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" - -[[package]] -name = "icu_normalizer" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_normalizer_data", - "icu_properties", - "icu_provider", - "smallvec", - "utf16_iter", - "utf8_iter", - "write16", - "zerovec", -] - -[[package]] -name = "icu_normalizer_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" - -[[package]] -name = "icu_properties" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f8ac670d7422d7f76b32e17a5db556510825b29ec9154f235977c9caba61036" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_locid_transform", - "icu_properties_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_properties_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" - -[[package]] -name = "icu_provider" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_provider_macros", - "stable_deref_trait", - "tinystr", - "writeable", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_provider_macros" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", -] - [[package]] name = "idna" -version = "1.0.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4716a3a0933a1d01c2f72450e89596eb51dd34ef3c211ccd875acdf1f8fe47ed" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ - "icu_normalizer", - "icu_properties", - "smallvec", - "utf8_iter", + "unicode-bidi", + "unicode-normalization", ] [[package]] name = "indexmap" -version = "2.2.6" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" dependencies = [ "equivalent", "hashbrown", @@ -1610,9 +1476,9 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "js-sys" -version = "0.3.69" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" dependencies = [ "wasm-bindgen", ] @@ -1628,15 +1494,15 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.155" +version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" [[package]] name = "libm" @@ -1650,7 +1516,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "libc", ] @@ -1660,17 +1526,11 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" -[[package]] -name = "litemap" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" - [[package]] name = "lmdb-master-sys" -version = "0.2.1" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5142795c220effa4c8f4813537bd4c88113a07e45e93100ccb2adc5cec6c7f3" +checksum = "472c3760e2a8d0f61f322fb36788021bb36d573c502b50fa3e2bcaac3ec326c9" dependencies = [ "cc", "doxygen-rs", @@ -1689,9 +1549,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.21" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "matchit" @@ -1711,9 +1571,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.2" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "merlin" @@ -1733,15 +1593,6 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" -[[package]] -name = "miniz_oxide" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" -dependencies = [ - "adler", -] - [[package]] name = "miniz_oxide" version = "0.8.0" @@ -1753,13 +1604,14 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.11" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ + "hermit-abi", "libc", "wasi", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -1931,21 +1783,11 @@ dependencies = [ "libm", ] -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi", - "libc", -] - [[package]] name = "object" -version = "0.36.0" +version = "0.36.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" +checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" dependencies = [ "memchr", ] @@ -1998,7 +1840,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -2043,7 +1885,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.77", ] [[package]] @@ -2072,7 +1914,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.77", ] [[package]] @@ -2089,15 +1931,18 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "pretty_assertions" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66" +checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d" dependencies = [ "diff", "yansi", @@ -2105,9 +1950,9 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "3.1.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" dependencies = [ "toml_edit", ] @@ -2137,22 +1982,22 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.85" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] [[package]] name = "proptest" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31b476131c3c86cb68032fdc5cb6d5a1045e3e42d96b69fa599fd77701e1f5bf" +checksum = "b4c2511913b88df1637da85cc8d96ec8e43a3f8bb8ccb71ee1ac240d6f3df58d" dependencies = [ "bit-set", "bit-vec", - "bitflags 2.5.0", + "bitflags 2.6.0", "lazy_static", "num-traits", "rand", @@ -2183,9 +2028,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -2277,27 +2122,27 @@ dependencies = [ [[package]] name = "redb" -version = "2.1.1" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6dd20d3cdeb9c7d2366a0b16b93b35b75aec15309fbeb7ce477138c9f68c8c0" +checksum = "e4760ad04a88ef77075ba86ba9ea79b919e6bab29c1764c5747237cd6eaedcaa" dependencies = [ "libc", ] [[package]] name = "redox_syscall" -version = "0.5.1" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" +checksum = "0884ad60e090bf1345b93da0a5de8923c93884cd03f40dfcfddd3b4bee661853" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", ] [[package]] name = "redox_users" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom", "libredox", @@ -2321,7 +2166,7 @@ checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.77", ] [[package]] @@ -2353,20 +2198,20 @@ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] [[package]] name = "rustix" -version = "0.38.34" +version = "0.38.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", @@ -2375,9 +2220,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.10" +version = "0.23.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05cff451f60db80f490f3c182b77c35260baace73209e9cdbbe526bfe3a4d402" +checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8" dependencies = [ "log", "once_cell", @@ -2390,9 +2235,9 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f1fb85efa936c42c6d5fc28d2629bb51e4b2f4b8a5211e297d599cc5a093792" +checksum = "fcaf18a4f2be7326cd874a5fa579fae794320a0f388d365dca7e480e55f83f8a" dependencies = [ "openssl-probe", "rustls-pemfile", @@ -2403,9 +2248,9 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "2.1.2" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" +checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" dependencies = [ "base64", "rustls-pki-types", @@ -2419,9 +2264,9 @@ checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" [[package]] name = "rustls-webpki" -version = "0.102.4" +version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff448f7e92e913c4b7d4c6d8e4540a1724b319b4152b8aef6d4cf8339712b33e" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" dependencies = [ "ring", "rustls-pki-types", @@ -2454,11 +2299,11 @@ checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "schannel" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +checksum = "e9aaafd5a2b6e3d657ff009d82fbd630b6bd54dd4eb06f21693925cdf80f9b8b" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2469,11 +2314,11 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "security-framework" -version = "2.11.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "core-foundation", "core-foundation-sys", "libc", @@ -2482,9 +2327,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.11.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" +checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" dependencies = [ "core-foundation-sys", "libc", @@ -2498,31 +2343,32 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.203" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.203" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.77", ] [[package]] name = "serde_json" -version = "1.0.117" +version = "1.0.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] @@ -2570,6 +2416,12 @@ dependencies = [ "keccak", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "signal-hook-registry" version = "1.4.2" @@ -2629,12 +2481,6 @@ version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - [[package]] name = "std-shims" version = "0.1.1" @@ -2646,9 +2492,9 @@ dependencies = [ [[package]] name = "subtle" -version = "2.5.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" @@ -2663,9 +2509,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.66" +version = "2.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" dependencies = [ "proc-macro2", "quote", @@ -2681,7 +2527,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.77", ] [[package]] @@ -2705,17 +2551,6 @@ dependencies = [ "crossbeam-queue", ] -[[package]] -name = "synstructure" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", -] - [[package]] name = "tap" version = "1.0.1" @@ -2724,34 +2559,35 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.10.1" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" dependencies = [ "cfg-if", "fastrand", + "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "thiserror" -version = "1.0.61" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.61" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.77", ] [[package]] @@ -2765,43 +2601,47 @@ dependencies = [ ] [[package]] -name = "tinystr" -version = "0.7.6" +name = "tinyvec" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" dependencies = [ - "displaydoc", - "zerovec", + "tinyvec_macros", ] +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + [[package]] name = "tokio" -version = "1.38.0" +version = "1.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" dependencies = [ "backtrace", "bytes", "libc", "mio", - "num_cpus", "parking_lot", "pin-project-lite", "signal-hook-registry", "socket2", "tokio-macros", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "tokio-macros" -version = "2.3.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.77", ] [[package]] @@ -2817,9 +2657,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" dependencies = [ "futures-core", "pin-project-lite", @@ -2842,9 +2682,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.11" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" dependencies = [ "bytes", "futures-core", @@ -2857,15 +2697,15 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.6" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" [[package]] name = "toml_edit" -version = "0.21.1" +version = "0.22.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" +checksum = "3b072cee73c449a636ffd6f32bd8de3a9f7119139aff882f44943ce2986dc5cf" dependencies = [ "indexmap", "toml_datetime", @@ -2891,15 +2731,15 @@ dependencies = [ [[package]] name = "tower-layer" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" @@ -2921,7 +2761,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.77", ] [[package]] @@ -2960,11 +2800,26 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" +[[package]] +name = "unicode-bidi" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" + [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "unicode-normalization" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" +dependencies = [ + "tinyvec", +] [[package]] name = "untrusted" @@ -2992,32 +2847,20 @@ dependencies = [ [[package]] name = "url" -version = "2.5.1" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7c25da092f0a868cdf09e8674cd3b7ef3a7d92a24253e663a2fb85e2496de56" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", "idna", "percent-encoding", ] -[[package]] -name = "utf16_iter" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" - -[[package]] -name = "utf8_iter" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" - [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "wait-timeout" @@ -3045,34 +2888,35 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.77", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3080,22 +2924,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.77", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" [[package]] name = "webpki-roots" @@ -3130,12 +2974,12 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows" -version = "0.57.0" +version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143" +checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" dependencies = [ - "windows-core 0.57.0", - "windows-targets 0.52.5", + "windows-core 0.58.0", + "windows-targets 0.52.6", ] [[package]] @@ -3144,50 +2988,61 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] name = "windows-core" -version = "0.57.0" +version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d" +checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" dependencies = [ "windows-implement", "windows-interface", "windows-result", - "windows-targets 0.52.5", + "windows-strings", + "windows-targets 0.52.6", ] [[package]] name = "windows-implement" -version = "0.57.0" +version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" +checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.77", ] [[package]] name = "windows-interface" -version = "0.57.0" +version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" +checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.77", ] [[package]] name = "windows-result" -version = "0.1.2" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets 0.52.6", ] [[package]] @@ -3205,7 +3060,16 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", ] [[package]] @@ -3225,18 +3089,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.5", - "windows_aarch64_msvc 0.52.5", - "windows_i686_gnu 0.52.5", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.5", - "windows_x86_64_gnu 0.52.5", - "windows_x86_64_gnullvm 0.52.5", - "windows_x86_64_msvc 0.52.5", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -3247,9 +3111,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -3259,9 +3123,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -3271,15 +3135,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -3289,9 +3153,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -3301,9 +3165,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -3313,9 +3177,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -3325,31 +3189,19 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.5.40" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" dependencies = [ "memchr", ] -[[package]] -name = "write16" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" - -[[package]] -name = "writeable" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" - [[package]] name = "wyz" version = "0.5.1" @@ -3361,73 +3213,29 @@ dependencies = [ [[package]] name = "yansi" -version = "0.5.1" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" - -[[package]] -name = "yoke" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" -dependencies = [ - "serde", - "stable_deref_trait", - "yoke-derive", - "zerofrom", -] - -[[package]] -name = "yoke-derive" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", - "synstructure", -] +checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" [[package]] name = "zerocopy" -version = "0.7.34" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ + "byteorder", "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.34" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", -] - -[[package]] -name = "zerofrom" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" -dependencies = [ - "zerofrom-derive", -] - -[[package]] -name = "zerofrom-derive" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", - "synstructure", + "syn 2.0.77", ] [[package]] @@ -3447,27 +3255,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", -] - -[[package]] -name = "zerovec" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" -dependencies = [ - "yoke", - "zerofrom", - "zerovec-derive", -] - -[[package]] -name = "zerovec-derive" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", + "syn 2.0.77", ] From a92313b52eb48f5a35cf94dbf3092ccf522da9fc Mon Sep 17 00:00:00 2001 From: Boog900 <54e72d8a-345f-4599-bd90-c6b9bc7d0ec5@aleeas.com> Date: Wed, 18 Sep 2024 21:38:34 +0100 Subject: [PATCH 27/31] move `flush_alt_blocks` --- storage/blockchain/src/ops/alt_block/block.rs | 20 +++++++++++++++++++ storage/blockchain/src/ops/alt_block/mod.rs | 20 ------------------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/storage/blockchain/src/ops/alt_block/block.rs b/storage/blockchain/src/ops/alt_block/block.rs index 5bc052b74..12a853b50 100644 --- a/storage/blockchain/src/ops/alt_block/block.rs +++ b/storage/blockchain/src/ops/alt_block/block.rs @@ -15,6 +15,26 @@ use crate::{ types::{AltBlockHeight, BlockHash, BlockHeight, CompactAltBlockInfo}, }; +/// Flush all alt-block data from all the alt-block tables. +/// +/// This function completely empties the alt block tables. +pub fn flush_alt_blocks<'a, E: cuprate_database::EnvInner<'a>>( + env_inner: &E, + tx_rw: &mut E::Rw<'_>, +) -> Result<(), RuntimeError> { + use crate::tables::{ + AltBlockBlobs, AltBlockHeights, AltBlocksInfo, AltChainInfos, AltTransactionBlobs, + AltTransactionInfos, + }; + + env_inner.clear_db::(tx_rw)?; + env_inner.clear_db::(tx_rw)?; + env_inner.clear_db::(tx_rw)?; + env_inner.clear_db::(tx_rw)?; + env_inner.clear_db::(tx_rw)?; + env_inner.clear_db::(tx_rw) +} + /// Add a [`AltBlockInformation`] to the database. /// /// This extracts all the data from the input block and diff --git a/storage/blockchain/src/ops/alt_block/mod.rs b/storage/blockchain/src/ops/alt_block/mod.rs index 8d102c86a..cc525094e 100644 --- a/storage/blockchain/src/ops/alt_block/mod.rs +++ b/storage/blockchain/src/ops/alt_block/mod.rs @@ -55,23 +55,3 @@ pub use block::{ }; pub use chain::{get_alt_chain_history_ranges, update_alt_chain_info}; pub use tx::{add_alt_transaction_blob, get_alt_transaction}; - -/// Flush all alt-block data from all the alt-block tables. -/// -/// This function completely empties the alt block tables. -pub fn flush_alt_blocks<'a, E: cuprate_database::EnvInner<'a>>( - env_inner: &E, - tx_rw: &mut E::Rw<'_>, -) -> Result<(), cuprate_database::RuntimeError> { - use crate::tables::{ - AltBlockBlobs, AltBlockHeights, AltBlocksInfo, AltChainInfos, AltTransactionBlobs, - AltTransactionInfos, - }; - - env_inner.clear_db::(tx_rw)?; - env_inner.clear_db::(tx_rw)?; - env_inner.clear_db::(tx_rw)?; - env_inner.clear_db::(tx_rw)?; - env_inner.clear_db::(tx_rw)?; - env_inner.clear_db::(tx_rw) -} From be3114bc1381a29e639bc826ef09579f08384c71 Mon Sep 17 00:00:00 2001 From: Boog900 <54e72d8a-345f-4599-bd90-c6b9bc7d0ec5@aleeas.com> Date: Wed, 18 Sep 2024 22:03:12 +0100 Subject: [PATCH 28/31] review fixes --- storage/blockchain/src/ops/block.rs | 39 ++++++++++++++++------------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/storage/blockchain/src/ops/block.rs b/storage/blockchain/src/ops/block.rs index a9a0df4f2..caa01966d 100644 --- a/storage/blockchain/src/ops/block.rs +++ b/storage/blockchain/src/ops/block.rs @@ -156,28 +156,27 @@ pub fn pop_block( let block = Block::read(&mut block_blob.as_slice())?; //------------------------------------------------------ Transaction / Outputs / Key Images - let mut txs = if move_to_alt_chain.is_some() { - Vec::with_capacity(block.transactions.len()) - } else { - Vec::new() - }; - remove_tx(&block.miner_transaction.hash(), tables)?; - for tx_hash in &block.transactions { - let (_, tx) = remove_tx(tx_hash, tables)?; - if move_to_alt_chain.is_some() { - txs.push(VerifiedTransactionInformation { - tx_weight: tx.weight(), - tx_blob: tx.serialize(), - tx_hash: tx.hash(), - fee: tx_fee(&tx), - tx, - }); - } - } + let remove_tx_iter = block.transactions.iter().map(|tx_hash| { + let (_, tx) = remove_tx(tx_hash, tables)?; + Ok::<_, RuntimeError>(tx) + }); if let Some(chain_id) = move_to_alt_chain { + let txs = remove_tx_iter + .map(|result| { + let tx = result?; + Ok(VerifiedTransactionInformation { + tx_weight: tx.weight(), + tx_blob: tx.serialize(), + tx_hash: tx.hash(), + fee: tx_fee(&tx), + tx, + }) + }) + .collect::, RuntimeError>>()?; + alt_block::add_alt_block( &AltBlockInformation { block: block.clone(), @@ -197,6 +196,10 @@ pub fn pop_block( }, tables, )?; + } else { + for result in remove_tx_iter { + drop(result?); + } } Ok((block_height, block_info.block_hash, block)) From 4e00cd0aacc7397b11e534af8b94a3117a99052f Mon Sep 17 00:00:00 2001 From: Boog900 <54e72d8a-345f-4599-bd90-c6b9bc7d0ec5@aleeas.com> Date: Wed, 18 Sep 2024 22:23:22 +0100 Subject: [PATCH 29/31] more review fixes --- storage/blockchain/src/ops/alt_block/chain.rs | 22 ++++-- storage/blockchain/src/ops/alt_block/mod.rs | 3 +- storage/blockchain/src/service/read.rs | 3 +- storage/blockchain/src/service/write.rs | 67 +++++++------------ 4 files changed, 43 insertions(+), 52 deletions(-) diff --git a/storage/blockchain/src/ops/alt_block/chain.rs b/storage/blockchain/src/ops/alt_block/chain.rs index 988c4c432..5b5f3cb1f 100644 --- a/storage/blockchain/src/ops/alt_block/chain.rs +++ b/storage/blockchain/src/ops/alt_block/chain.rs @@ -22,10 +22,26 @@ pub fn update_alt_chain_info( prev_hash: &BlockHash, tables: &mut impl TablesMut, ) -> Result<(), RuntimeError> { + let parent_chain = match tables.alt_block_heights().get(prev_hash) { + Ok(alt_parent_height) => Chain::Alt(alt_parent_height.chain_id.into()), + Err(RuntimeError::KeyNotFound) => Chain::Main, + Err(e) => return Err(e), + }; + // try update the info if one exists for this chain. let update = tables .alt_chain_infos_mut() .update(&alt_block_height.chain_id, |mut info| { + if info.chain_height < alt_block_height.height + 1 { + // If the chain height is increasing we only need to update the chain height. + info.chain_height = alt_block_height.height + 1; + } else { + // If the chain height is not increasing we are popping blocks and need to update the + // split point. + info.common_ancestor_height = alt_block_height.height.checked_sub(1).unwrap(); + info.parent_chain = parent_chain.into(); + } + info.chain_height = alt_block_height.height + 1; Some(info) }); @@ -38,12 +54,6 @@ pub fn update_alt_chain_info( // If one doesn't already exist add it. - let parent_chain = match tables.alt_block_heights().get(prev_hash) { - Ok(alt_parent_height) => Chain::Alt(alt_parent_height.chain_id.into()), - Err(RuntimeError::KeyNotFound) => Chain::Main, - Err(e) => return Err(e), - }; - tables.alt_chain_infos_mut().put( &alt_block_height.chain_id, &AltChainInfo { diff --git a/storage/blockchain/src/ops/alt_block/mod.rs b/storage/blockchain/src/ops/alt_block/mod.rs index cc525094e..1654d274c 100644 --- a/storage/blockchain/src/ops/alt_block/mod.rs +++ b/storage/blockchain/src/ops/alt_block/mod.rs @@ -51,7 +51,8 @@ mod chain; mod tx; pub use block::{ - add_alt_block, get_alt_block, get_alt_block_extended_header_from_height, get_alt_block_hash, + add_alt_block, flush_alt_blocks, get_alt_block, get_alt_block_extended_header_from_height, + get_alt_block_hash, }; pub use chain::{get_alt_chain_history_ranges, update_alt_chain_info}; pub use tx::{add_alt_transaction_blob, get_alt_transaction}; diff --git a/storage/blockchain/src/service/read.rs b/storage/blockchain/src/service/read.rs index 3a5dc8425..cdb716f1e 100644 --- a/storage/blockchain/src/service/read.rs +++ b/storage/blockchain/src/service/read.rs @@ -303,7 +303,7 @@ fn block_extended_header_in_range( ranges .par_iter() .rev() - .map(|(chain, range)| { + .flat_map(|(chain, range)| { range.clone().into_par_iter().map(|height| { let tx_ro = tx_ro.get_or_try(|| env_inner.tx_ro())?; let tables = get_tables!(env_inner, tx_ro, tables)?.as_ref(); @@ -320,7 +320,6 @@ fn block_extended_header_in_range( } }) }) - .flatten() .collect::, _>>()? } }; diff --git a/storage/blockchain/src/service/write.rs b/storage/blockchain/src/service/write.rs index 176ab518f..af205de4b 100644 --- a/storage/blockchain/src/service/write.rs +++ b/storage/blockchain/src/service/write.rs @@ -2,7 +2,7 @@ //---------------------------------------------------------------------------------------------------- Import use std::sync::Arc; -use cuprate_database::{ConcreteEnv, DatabaseRo, DatabaseRw, Env, EnvInner, RuntimeError, TxRw}; +use cuprate_database::{ConcreteEnv, DatabaseRo, Env, EnvInner, RuntimeError, TxRw}; use cuprate_database_service::DatabaseWriteHandle; use cuprate_types::{ blockchain::{BlockchainResponse, BlockchainWriteRequest}, @@ -14,10 +14,17 @@ use crate::{ free::map_valid_alt_block_to_verified_block, types::{BlockchainWriteHandle, ResponseResult}, }, - tables::{OpenTables, Tables, TablesMut}, - types::{AltBlockHeight, AltChainInfo}, + tables::{OpenTables, Tables}, + types::AltBlockHeight, }; +/// Write functions within this module abort if the write transaction +/// could not be aborted successfully to maintain atomicity. +/// +/// This is the panic message if the `abort()` fails. +const TX_RW_ABORT_FAIL: &str = + "Could not maintain blockchain database atomicity by aborting write transaction"; + //---------------------------------------------------------------------------------------------------- init_write_service /// Initialize the blockchain write service from a [`ConcreteEnv`]. pub fn init_write_service(env: Arc) -> BlockchainWriteHandle { @@ -69,8 +76,7 @@ fn write_block(env: &ConcreteEnv, block: &VerifiedBlockInformation) -> ResponseR Err(e) => { // INVARIANT: ensure database atomicity by aborting // the transaction on `add_block()` failures. - TxRw::abort(tx_rw) - .expect("could not maintain database atomicity by aborting write transaction"); + TxRw::abort(tx_rw).expect(TX_RW_ABORT_FAIL); Err(e) } } @@ -95,8 +101,7 @@ fn write_alt_block(env: &ConcreteEnv, block: &AltBlockInformation) -> ResponseRe Err(e) => { // INVARIANT: ensure database atomicity by aborting // the transaction on `add_block()` failures. - TxRw::abort(tx_rw) - .expect("could not maintain database atomicity by aborting write transaction"); + TxRw::abort(tx_rw).expect(TX_RW_ABORT_FAIL); Err(e) } } @@ -117,22 +122,10 @@ fn pop_blocks(env: &ConcreteEnv, numb_blocks: usize) -> ResponseResult { let old_main_chain_id = ChainId(rand::random()); // pop the blocks - let mut last_block_height = 0; for _ in 0..numb_blocks { - (last_block_height, _, _) = - crate::ops::block::pop_block(Some(old_main_chain_id), &mut tables_mut)?; + crate::ops::block::pop_block(Some(old_main_chain_id), &mut tables_mut)?; } - // Update the alt_chain_info with the correct information. - tables_mut.alt_chain_infos_mut().put( - &old_main_chain_id.into(), - &AltChainInfo { - parent_chain: Chain::Main.into(), - common_ancestor_height: last_block_height - 1, - chain_height: last_block_height + numb_blocks, - }, - )?; - Ok(old_main_chain_id) }; @@ -144,8 +137,7 @@ fn pop_blocks(env: &ConcreteEnv, numb_blocks: usize) -> ResponseResult { Err(e) => { // INVARIANT: ensure database atomicity by aborting // the transaction on `add_block()` failures. - TxRw::abort(tx_rw) - .expect("could not maintain database atomicity by aborting write transaction"); + TxRw::abort(tx_rw).expect(TX_RW_ABORT_FAIL); Err(e) } } @@ -173,25 +165,16 @@ fn reverse_reorg(env: &ConcreteEnv, chain_id: ChainId) -> ResponseResult { crate::ops::block::pop_block(None, &mut tables_mut)?; } - // Rust borrow rules requires us to collect into a Vec first before looping over the Vec. - let alt_blocks = ((chain_info.common_ancestor_height + 1)..chain_info.chain_height) - .map(|height| { - crate::ops::alt_block::get_alt_block( - &AltBlockHeight { - chain_id: chain_id.into(), - height, - }, - &tables_mut, - ) - }) - .collect::>(); - // Add the old main chain blocks back to the main chain. - for res_alt_block in alt_blocks { - let alt_block = res_alt_block?; - + for height in (chain_info.common_ancestor_height + 1)..chain_info.chain_height { + let alt_block = crate::ops::alt_block::get_alt_block( + &AltBlockHeight { + chain_id: chain_id.into(), + height, + }, + &tables_mut, + )?; let verified_block = map_valid_alt_block_to_verified_block(alt_block); - crate::ops::block::add_block(&verified_block, &mut tables_mut)?; } @@ -209,8 +192,7 @@ fn reverse_reorg(env: &ConcreteEnv, chain_id: ChainId) -> ResponseResult { Err(e) => { // INVARIANT: ensure database atomicity by aborting // the transaction on `add_block()` failures. - TxRw::abort(tx_rw) - .expect("could not maintain database atomicity by aborting write transaction"); + TxRw::abort(tx_rw).expect(TX_RW_ABORT_FAIL); Err(e) } } @@ -232,8 +214,7 @@ fn flush_alt_blocks(env: &ConcreteEnv) -> ResponseResult { Err(e) => { // INVARIANT: ensure database atomicity by aborting // the transaction on `add_block()` failures. - TxRw::abort(tx_rw) - .expect("could not maintain database atomicity by aborting write transaction"); + TxRw::abort(tx_rw).expect(TX_RW_ABORT_FAIL); Err(e) } } From 66a82a377e255a253c2bdffba0d1fd5c6391d154 Mon Sep 17 00:00:00 2001 From: Boog900 <54e72d8a-345f-4599-bd90-c6b9bc7d0ec5@aleeas.com> Date: Wed, 18 Sep 2024 22:35:28 +0100 Subject: [PATCH 30/31] fix clippy --- Cargo.lock | 2 +- storage/blockchain/src/ops/alt_block/block.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b34a04f9a..f316fa70d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -917,7 +917,7 @@ version = "0.1.0" dependencies = [ "anyhow", "async-trait", - "bitflags 2.5.0", + "bitflags 2.6.0", "borsh", "bytemuck", "bytes", diff --git a/storage/blockchain/src/ops/alt_block/block.rs b/storage/blockchain/src/ops/alt_block/block.rs index 12a853b50..6bd01cb37 100644 --- a/storage/blockchain/src/ops/alt_block/block.rs +++ b/storage/blockchain/src/ops/alt_block/block.rs @@ -231,7 +231,7 @@ mod tests { types::AltBlockHeight, }; - #[allow(clippy::range_plus_one)] + #[expect(clippy::range_plus_one)] #[test] fn all_alt_blocks() { let (env, _tmp) = tmp_concrete_env(); From e23a3f61c6816a53cb96cb48e4c358a93922b788 Mon Sep 17 00:00:00 2001 From: Boog900 <54e72d8a-345f-4599-bd90-c6b9bc7d0ec5@aleeas.com> Date: Thu, 19 Sep 2024 16:35:04 +0100 Subject: [PATCH 31/31] remove INVARIANT comments --- storage/blockchain/src/service/write.rs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/storage/blockchain/src/service/write.rs b/storage/blockchain/src/service/write.rs index af205de4b..07162d2ac 100644 --- a/storage/blockchain/src/service/write.rs +++ b/storage/blockchain/src/service/write.rs @@ -74,8 +74,6 @@ fn write_block(env: &ConcreteEnv, block: &VerifiedBlockInformation) -> ResponseR Ok(BlockchainResponse::Ok) } Err(e) => { - // INVARIANT: ensure database atomicity by aborting - // the transaction on `add_block()` failures. TxRw::abort(tx_rw).expect(TX_RW_ABORT_FAIL); Err(e) } @@ -99,8 +97,6 @@ fn write_alt_block(env: &ConcreteEnv, block: &AltBlockInformation) -> ResponseRe Ok(BlockchainResponse::Ok) } Err(e) => { - // INVARIANT: ensure database atomicity by aborting - // the transaction on `add_block()` failures. TxRw::abort(tx_rw).expect(TX_RW_ABORT_FAIL); Err(e) } @@ -135,8 +131,6 @@ fn pop_blocks(env: &ConcreteEnv, numb_blocks: usize) -> ResponseResult { Ok(BlockchainResponse::PopBlocks(old_main_chain_id)) } Err(e) => { - // INVARIANT: ensure database atomicity by aborting - // the transaction on `add_block()` failures. TxRw::abort(tx_rw).expect(TX_RW_ABORT_FAIL); Err(e) } @@ -190,8 +184,6 @@ fn reverse_reorg(env: &ConcreteEnv, chain_id: ChainId) -> ResponseResult { Ok(BlockchainResponse::Ok) } Err(e) => { - // INVARIANT: ensure database atomicity by aborting - // the transaction on `add_block()` failures. TxRw::abort(tx_rw).expect(TX_RW_ABORT_FAIL); Err(e) } @@ -212,8 +204,6 @@ fn flush_alt_blocks(env: &ConcreteEnv) -> ResponseResult { Ok(BlockchainResponse::Ok) } Err(e) => { - // INVARIANT: ensure database atomicity by aborting - // the transaction on `add_block()` failures. TxRw::abort(tx_rw).expect(TX_RW_ABORT_FAIL); Err(e) }