Skip to content

Commit

Permalink
add: time-related validation for blocks and transaction locks.
Browse files Browse the repository at this point in the history
  • Loading branch information
jaoleal committed Jan 29, 2025
1 parent d461216 commit 880bffb
Show file tree
Hide file tree
Showing 10 changed files with 462 additions and 36 deletions.
5 changes: 3 additions & 2 deletions crates/floresta-chain/benches/chain_state_bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use criterion::criterion_main;
use criterion::BatchSize;
use criterion::Criterion;
use criterion::SamplingMode;
use floresta_chain::pruned_utreexo::utxo_data::UtxoData;
use floresta_chain::pruned_utreexo::UpdatableChainstate;
use floresta_chain::AssumeValidArg;
use floresta_chain::ChainState;
Expand Down Expand Up @@ -44,7 +45,7 @@ fn setup_test_chain<'a>(
fn decode_block_and_inputs(
block_file: File,
stxos_file: File,
) -> (Block, HashMap<OutPoint, TxOut>) {
) -> (Block, HashMap<OutPoint, UtxoData>) {
let block_bytes = zstd::decode_all(block_file).unwrap();
let block: Block = deserialize(&block_bytes).unwrap();

Expand All @@ -58,7 +59,7 @@ fn decode_block_and_inputs(
.iter()
.skip(1) // Skip the coinbase transaction
.flat_map(|tx| &tx.input)
.map(|txin| (txin.previous_output, stxos.remove(0)))
.map(|txin| (txin.previous_output, stxos.remove(0).into()))
.collect();

assert!(stxos.is_empty(), "Moved all stxos to the inputs map");
Expand Down
70 changes: 63 additions & 7 deletions crates/floresta-chain/src/pruned_utreexo/chain_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,8 @@ use bitcoin::hashes::Hash;
use bitcoin::script;
use bitcoin::Block;
use bitcoin::BlockHash;
use bitcoin::OutPoint;
use bitcoin::Target;
use bitcoin::Transaction;
use bitcoin::TxOut;
use bitcoin::Work;
use floresta_common::Channel;
use log::info;
Expand All @@ -44,8 +42,10 @@ use super::chainstore::KvChainStore;
use super::consensus::Consensus;
use super::error::BlockValidationErrors;
use super::error::BlockchainError;
use super::nodetime::DisableTime;
use super::partial_chain::PartialChainState;
use super::partial_chain::PartialChainStateInner;
use super::utxo_data::UtxoMap;
use super::BlockchainInterface;
use super::ChainStore;
use super::UpdatableChainstate;
Expand Down Expand Up @@ -750,8 +750,16 @@ impl<PersistedState: ChainStore> ChainState<PersistedState> {
&self,
block: &Block,
height: u32,
inputs: HashMap<OutPoint, TxOut>,
inputs: UtxoMap,
) -> Result<(), BlockchainError> {
if let Ok(mtp) = self.get_mtp(height) {
#[cfg(not(feature = "std"))]
let time = DisableTime;
#[cfg(feature = "std")]
let time = StdNodeTime;
Consensus::validate_block_time(block.header.time, mtp, time)?;
}

if !block.check_merkle_root() {
return Err(BlockValidationErrors::BadMerkleRoot.into());
}
Expand All @@ -773,12 +781,14 @@ impl<PersistedState: ChainStore> ChainState<PersistedState> {
// Validate block transactions
let subsidy = read_lock!(self).consensus.get_subsidy(height);
let verify_script = self.verify_script(height);

#[cfg(feature = "bitcoinconsensus")]
let flags = self.get_validation_flags(height, block.header.block_hash());
#[cfg(not(feature = "bitcoinconsensus"))]
let flags = 0;
Consensus::verify_block_transactions(
height,
block.header.time,
inputs,
&block.txdata,
subsidy,
Expand Down Expand Up @@ -826,7 +836,7 @@ impl<PersistedState: ChainStore> BlockchainInterface for ChainState<PersistedSta
&self,
block: &Block,
proof: Proof,
inputs: HashMap<OutPoint, TxOut>,
inputs: UtxoMap,
del_hashes: Vec<sha256::Hash>,
acc: Stump,
) -> Result<(), Self::Error> {
Expand Down Expand Up @@ -999,6 +1009,42 @@ impl<PersistedState: ChainStore> BlockchainInterface for ChainState<PersistedSta
}
}
impl<PersistedState: ChainStore> UpdatableChainstate for ChainState<PersistedState> {
fn get_mtp(&self, height: u32) -> Result<u32, BlockchainError> {
let mut initial_array = [0u32; 11];

for i in 0..11 {
let time = match self.get_block_hash(height.saturating_sub(i)) {
Ok(hash) => self.get_block_header(&hash)?.time,
_ => {
info!("Block timestamp : {i} Not found");
0
}
};
initial_array[10 - i as usize] = time;
}

// This is the case where we didnt find even the block in the given height
if initial_array[10] == 0 {
return Err(BlockchainError::BlockNotPresent);
}
let needed_blocks: u32 = height.saturating_sub(11);

let mut ret = initial_array
.iter()
.filter(|t| **t != 0)
.collect::<Vec<_>>();

if ret.len() == needed_blocks as usize {
return Err(BlockchainError::BlockNotPresent);
}

ret.sort();

// At this point we have at least 1 block inside the array so we can safely
// divide the length by 2 to have its median.
Ok(*ret[ret.len() / 2])
}

fn switch_chain(&self, new_tip: BlockHash) -> Result<(), BlockchainError> {
let new_tip = self.get_block_header(&new_tip)?;
self.reorg(new_tip)
Expand Down Expand Up @@ -1069,7 +1115,7 @@ impl<PersistedState: ChainStore> UpdatableChainstate for ChainState<PersistedSta
&self,
block: &Block,
proof: Proof,
inputs: HashMap<OutPoint, TxOut>,
inputs: UtxoMap,
del_hashes: Vec<sha256::Hash>,
) -> Result<u32, BlockchainError> {
let header = self.get_disk_block_header(&block.block_hash())?;
Expand Down Expand Up @@ -1349,6 +1395,7 @@ mod test {
use super::UpdatableChainstate;
use crate::prelude::HashMap;
use crate::pruned_utreexo::consensus::Consensus;
use crate::pruned_utreexo::utxo_data::UtxoData;
use crate::AssumeValidArg;
use crate::KvChainStore;
use crate::Network;
Expand All @@ -1365,7 +1412,7 @@ mod test {
fn decode_block_and_inputs(
block_file: File,
stxos_file: File,
) -> (Block, HashMap<OutPoint, TxOut>) {
) -> (Block, HashMap<OutPoint, UtxoData>) {
let block_bytes = zstd::decode_all(block_file).unwrap();
let block: Block = deserialize(&block_bytes).unwrap();

Expand All @@ -1379,7 +1426,16 @@ mod test {
.iter()
.skip(1) // Skip the coinbase transaction
.flat_map(|tx| &tx.input)
.map(|txin| (txin.previous_output, stxos.remove(0)))
.map(|txin| {
(
txin.previous_output,
UtxoData {
txout: stxos.remove(0),
commited_height: 0,
commited_time: 0,
},
)
})
.collect();

assert!(stxos.is_empty(), "Moved all stxos to the inputs map");
Expand Down
Loading

0 comments on commit 880bffb

Please sign in to comment.