diff --git a/Cargo.lock b/Cargo.lock index 77531897..d5d64902 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 7e79305a..b03ef038 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 8288e65f..20d56226 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 171cdd7b..a429eab8 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 4259d4dc..1162a9cd 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 8b2d1f17..72e0933e 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 aad4dc3d..a49c72ae 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 2e110fed..5cb3b4bc 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, + }) + } } - Ok((block_height, block_hash, block)) + 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_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 e748bbbe..aa8238f9 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 067ba7f1..95124d41 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 deb957ea..fa568ae6 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 88ece10b..14917249 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 33c3e8bd..c2a5517d 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 cc4543e6..c6e83d09 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`].