mirror of
https://github.com/Cuprate/cuprate.git
synced 2024-12-23 03:59:31 +00:00
add last service request
This commit is contained in:
parent
029f439f0b
commit
6927b05f81
14 changed files with 306 additions and 66 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -531,6 +531,7 @@ dependencies = [
|
|||
"monero-serai",
|
||||
"pretty_assertions",
|
||||
"proptest",
|
||||
"rand",
|
||||
"rayon",
|
||||
"serde",
|
||||
"tempfile",
|
||||
|
|
|
@ -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 }
|
||||
|
||||
|
|
|
@ -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<ConcreteEnv, InitError> {
|
|||
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 {
|
||||
|
|
|
@ -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::<Result<_, RuntimeError>>()?;
|
||||
|
||||
Ok(AltBlockInformation {
|
||||
block,
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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::<AltChainInfos>(tx_rw)?;
|
||||
env_inner.clear_db::<AltBlockHeights>(tx_rw)?;
|
||||
env_inner.clear_db::<AltBlocksInfo>(tx_rw)?;
|
||||
env_inner.clear_db::<AltBlockBlobs>(tx_rw)?;
|
||||
env_inner.clear_db::<AltTransactionBlobs>(tx_rw)?;
|
||||
env_inner.clear_db::<AltTransactionInfos>(tx_rw)
|
||||
}
|
||||
|
|
|
@ -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<u8>,
|
||||
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<Vec<u8>, RuntimeError> {
|
||||
match tables.alt_transaction_blobs().get(tx_hash) {
|
||||
Ok(blob) => Ok(blob.0),
|
||||
) -> Result<VerifiedTransactionInformation, RuntimeError> {
|
||||
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,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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<ChainId>,
|
||||
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);
|
||||
|
||||
|
|
|
@ -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<const INITIAL_BLOCKS: u
|
|||
top_block_height > 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::<u64>();
|
||||
let total_miner_output = alt_block
|
||||
.block
|
||||
.miner_transaction
|
||||
.prefix()
|
||||
.outputs
|
||||
.iter()
|
||||
.map(|out| out.amount.unwrap_or(0))
|
||||
.sum::<u64>();
|
||||
|
||||
VerifiedBlockInformation {
|
||||
block: alt_block.block,
|
||||
block_blob: alt_block.block_blob,
|
||||
txs: alt_block
|
||||
.txs
|
||||
.into_iter()
|
||||
.map(TryInto::try_into)
|
||||
.collect::<Result<_, _>>()
|
||||
.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)]
|
||||
|
|
|
@ -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::<Vec<_>>();
|
||||
|
||||
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 {
|
||||
|
|
|
@ -145,6 +145,9 @@ cuprate_database::define_tables! {
|
|||
|
||||
19 => AltTransactionBlobs,
|
||||
TxHash => TxBlob,
|
||||
|
||||
20 => AltTransactionInfos,
|
||||
TxHash => AltTransactionInfo,
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Tests
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<AltBlockInformation>,
|
||||
},
|
||||
/// The response for [`BlockchainWriteRequest::PopBlocks`].
|
||||
///
|
||||
/// The inner value is the alt-chain ID for the old main chain blocks.
|
||||
PopBlocks(ChainId),
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Tests
|
||||
|
|
|
@ -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<u8>,
|
||||
/// All the transactions in the block, excluding the [`Block::miner_transaction`].
|
||||
pub txs: Vec<Vec<u8>>,
|
||||
pub txs: Vec<VerifiedTransactionInformation>,
|
||||
/// The block's hash.
|
||||
///
|
||||
/// [`Block::hash`].
|
||||
|
|
Loading…
Reference in a new issue