Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add: new struct for utxo: UtxoData, new trait for time functionalitie…
Browse files Browse the repository at this point in the history
…s: NodeTime.

add: get_mtp() method for Persisted ChainState.
fix: time-related validation for Persisted ChainState.
jaoleal committed Jan 27, 2025
1 parent fac9963 commit b247973
Showing 10 changed files with 347 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
@@ -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;
@@ -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();

@@ -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");
68 changes: 61 additions & 7 deletions crates/floresta-chain/src/pruned_utreexo/chain_state.rs
Original file line number Diff line number Diff line change
@@ -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;
@@ -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;
@@ -750,8 +750,20 @@ impl<PersistedState: ChainStore> ChainState<PersistedState> {
&self,
block: &Block,
height: u32,
inputs: HashMap<OutPoint, TxOut>,
inputs: UtxoMap,
) -> Result<(), BlockchainError> {
let mtp = match self.get_mtp(height) {
Ok(mtp) => {
#[cfg(not(feature = "std"))]
let time = DisableTime;
#[cfg(feature = "std")]
let time = StdNodeTime;
Consensus::validate_block_time(block.header.time, mtp, time)?;
Some(mtp)
}
_ => None,
};

if !block.check_merkle_root() {
return Err(BlockchainError::BlockValidation(
BlockValidationErrors::BadMerkleRoot,
@@ -775,12 +787,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,
mtp,
inputs,
&block.txdata,
subsidy,
@@ -828,7 +842,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> {
@@ -1001,6 +1015,37 @@ 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,
_ => {
warn!("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 mut ret = initial_array
.iter()
.filter(|t| **t != 0)
.collect::<Vec<_>>();

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)
@@ -1071,7 +1116,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())?;
@@ -1351,6 +1396,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;
@@ -1367,7 +1413,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();

@@ -1381,7 +1427,15 @@ 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),
locked_by: 0,
},
)
})
.collect();

assert!(stxos.is_empty(), "Moved all stxos to the inputs map");
98 changes: 87 additions & 11 deletions crates/floresta-chain/src/pruned_utreexo/consensus.rs
Original file line number Diff line number Diff line change
@@ -5,15 +5,17 @@
extern crate alloc;

use core::ffi::c_uint;
use core::ops::Sub;

use bitcoin::absolute::Height;
use bitcoin::absolute::Time;
use bitcoin::block::Header as BlockHeader;
use bitcoin::consensus::Encodable;
use bitcoin::hashes::sha256;
use bitcoin::hashes::Hash;
use bitcoin::Block;
use bitcoin::BlockHash;
use bitcoin::CompactTarget;
use bitcoin::OutPoint;
use bitcoin::ScriptBuf;
use bitcoin::Target;
use bitcoin::Transaction;
@@ -30,8 +32,14 @@ use sha2::Sha512_256;
use super::chainparams::ChainParams;
use super::error::BlockValidationErrors;
use super::error::BlockchainError;
use super::nodetime::DisableTime;
use super::nodetime::NodeTime;
use super::nodetime::HOUR;
use super::utxo_data::UtxoMap;
use crate::TransactionError;

pub const SEQUENCE_LOCKTIME_MASK: u32 = 0x0000_ffff;

/// The value of a single coin in satoshis.
pub const COIN_VALUE: u64 = 100_000_000;

@@ -110,10 +118,10 @@ impl Consensus {
/// - The transaction must not have duplicate inputs
/// - The transaction must not spend more coins than it claims in the inputs
/// - The transaction must have valid scripts
#[allow(unused)]
pub fn verify_block_transactions(
height: u32,
mut utxos: HashMap<OutPoint, TxOut>,
mtp: Option<u32>,
mut utxos: UtxoMap,
transactions: &[Transaction],
subsidy: u64,
verify_script: bool,
@@ -170,6 +178,14 @@ impl Consensus {
error,
}
})?;
if let Some(mtp) = mtp {
Self::validate_locktime(input, transaction, &utxos, height, mtp).map_err(
|error| TransactionError {
txid: transaction.compute_txid(),
error,
},
)?;
}
// TODO check also witness script size
}

@@ -193,7 +209,11 @@ impl Consensus {
#[cfg(feature = "bitcoinconsensus")]
if verify_script {
transaction
.verify_with_flags(|outpoint| utxos.remove(outpoint), flags)
.verify_with_flags(
// TO-DO: Make this less horrible to understand
|outpoint| utxos.remove(outpoint).map(|utxodata| utxodata.txout),
flags,
)
.map_err(|err| TransactionError {
txid: transaction.compute_txid(),
error: BlockValidationErrors::ScriptValidationError(err.to_string()),
@@ -224,12 +244,9 @@ impl Consensus {
/// Returns the TxOut being spent by the given input.
///
/// Fails if the UTXO is not present in the given hashmap.
fn get_utxo<'a>(
input: &TxIn,
utxos: &'a HashMap<OutPoint, TxOut>,
) -> Result<&'a TxOut, BlockValidationErrors> {
fn get_utxo<'a>(input: &TxIn, utxos: &'a UtxoMap) -> Result<&'a TxOut, BlockValidationErrors> {
match utxos.get(&input.previous_output) {
Some(txout) => Ok(txout),
Some(txout) => Ok(&txout.txout),
None => Err(
// This is the case when the spender:
// - Spends an UTXO that doesn't exist
@@ -238,13 +255,72 @@ impl Consensus {
),
}
}
#[allow(unused)]

/// From a block timestamp with a, given mtp and a real world time, validate if a block timestamp
/// is correct.
pub fn validate_block_time(
block_timestamp: u32,
mtp: u32,
time: impl NodeTime,
) -> Result<(), BlockValidationErrors> {
if time.get_time() == 0 {
return Ok(());
} // The check for skipping time validation.

let its_too_old = mtp > block_timestamp;
let its_too_new = block_timestamp > (time.get_time() + (2 * HOUR));
if its_too_old {
return Err(BlockValidationErrors::BlockTooNew);
}
if its_too_new {
return Err(BlockValidationErrors::BlockTooNew);
}
Ok(())
}

/// Validate the transaction locktime.
fn validate_locktime(
input: &TxIn,
transaction: &Transaction,
out_map: &UtxoMap,
height: u32,
mtp: u32,
) -> Result<(), BlockValidationErrors> {
unimplemented!("validate_locktime")
let is_relative_locked = input.sequence.is_relative_lock_time();
if is_relative_locked {
//validate lock time
let prevout = out_map.get(&input.previous_output).unwrap();

let is_block_locked = input.sequence.is_height_locked();

if is_block_locked {
let committed_height = prevout.locked_by;
// to retrieve the span contained in the sequence we have to just get the u32 value that the sequence contains.
let height_span = input.sequence.0 & SEQUENCE_LOCKTIME_MASK;
// if the committed height + the span is greater than the current height, the transaction is invalid.
if committed_height + height_span > height {
return Err(BlockValidationErrors::BadRelativeLockTime);
}
}
if !is_block_locked {
let committed_time = prevout.locked_by;
// here we have to shift the sequence 16 bits to the left and 16 to the right get the time lock without the flag messing with us.
let time_lock = (input.sequence.0 & SEQUENCE_LOCKTIME_MASK) * 512_u32;
if committed_time + time_lock > mtp {
return Err(BlockValidationErrors::BadRelativeLockTime);
}
}
}

let is_locktime_satisfied = !transaction.is_absolute_timelock_satisfied(
Height::from_consensus(height).unwrap(),
Time::from_consensus(mtp).unwrap(),
);

if !is_relative_locked && is_locktime_satisfied {
return Err(BlockValidationErrors::BadAbsoluteLockTime);
}
Ok(())
}
/// Validates the script size and the number of sigops in a scriptpubkey or scriptsig.
fn validate_script_size(script: &ScriptBuf) -> Result<(), BlockValidationErrors> {
20 changes: 20 additions & 0 deletions crates/floresta-chain/src/pruned_utreexo/error.rs
Original file line number Diff line number Diff line change
@@ -35,6 +35,9 @@ pub struct TransactionError {

#[derive(Clone, Debug, PartialEq)]
pub enum BlockValidationErrors {
BlockTooNew,
BlockTooOld,
InvalidBlockTimestamp,
InvalidCoinbase(String),
UtxoNotFound(OutPoint),
ScriptValidationError(String),
@@ -53,6 +56,8 @@ pub enum BlockValidationErrors {
BadBip34,
InvalidProof,
CoinbaseNotMatured,
BadRelativeLockTime,
BadAbsoluteLockTime,
}

impl Display for TransactionError {
@@ -64,6 +69,21 @@ impl Display for TransactionError {
impl Display for BlockValidationErrors {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
BlockValidationErrors::BlockTooNew => {
write!(f, "A block is too new for the MTP at its height")
}
BlockValidationErrors::BlockTooOld => {
write!(f, "A block is too old for the MTP at its height")
}
BlockValidationErrors::InvalidBlockTimestamp => {
write!(f, "A block contains a invalid timestamp")
}
BlockValidationErrors::BadAbsoluteLockTime => {
write!(f, "A transaction contains a invalid absolute lock time.",)
}
BlockValidationErrors::BadRelativeLockTime => {
write!(f, "A transaction contains a invalid relative lock time.",)
}
BlockValidationErrors::ScriptValidationError(e) => {
write!(f, "{}", e)
}
142 changes: 137 additions & 5 deletions crates/floresta-chain/src/pruned_utreexo/mod.rs
Original file line number Diff line number Diff line change
@@ -15,14 +15,14 @@ use bitcoin::block::Header as BlockHeader;
use bitcoin::hashes::sha256;
use bitcoin::Block;
use bitcoin::BlockHash;
use bitcoin::OutPoint;
use bitcoin::Transaction;
use bitcoin::TxOut;
use rustreexo::accumulator::node_hash::NodeHash;
use rustreexo::accumulator::proof::Proof;
use rustreexo::accumulator::stump::Stump;

use self::partial_chain::PartialChainState;
use self::utxo_data::UtxoMap;
use crate::prelude::*;
use crate::BestChain;
use crate::BlockConsumer;
@@ -88,7 +88,7 @@ pub trait BlockchainInterface {
&self,
block: &Block,
proof: Proof,
inputs: HashMap<OutPoint, TxOut>,
inputs: UtxoMap,
del_hashes: Vec<sha256::Hash>,
acc: Stump,
) -> Result<(), Self::Error>;
@@ -108,7 +108,7 @@ pub trait UpdatableChainstate {
&self,
block: &Block,
proof: Proof,
inputs: HashMap<OutPoint, TxOut>,
inputs: UtxoMap,
del_hashes: Vec<sha256::Hash>,
) -> Result<u32, BlockchainError>;

@@ -155,6 +155,17 @@ pub trait UpdatableChainstate {
/// This mimics the behaviour of checking every block before this block, and continues
/// from this point
fn mark_chain_as_assumed(&self, acc: Stump, tip: BlockHash) -> Result<bool, BlockchainError>;

/// Get the mtp of the block from the given height
///
/// The mtp is a 11 timestamps sorted array that is used to calculate the median time past of
/// the last 11 blocks.
///
/// The value of a MTP is, from the sorted array, array[array.len()/2].
/// array.len()/2 being a unsigned integer greater than 1.
///
/// Fails if the block isnt found.
fn get_mtp(&self, height: u32) -> Result<u32, BlockchainError>;
}

/// [ChainStore] is a trait defining how we interact with our chain database. This definitions
@@ -201,6 +212,10 @@ pub enum Notification {
}

impl<T: UpdatableChainstate> UpdatableChainstate for Arc<T> {
fn get_mtp(&self, height: u32) -> Result<u32, BlockchainError> {
T::get_mtp(self, height)
}

fn flush(&self) -> Result<(), BlockchainError> {
T::flush(self)
}
@@ -213,7 +228,7 @@ impl<T: UpdatableChainstate> UpdatableChainstate for Arc<T> {
&self,
block: &Block,
proof: Proof,
inputs: HashMap<OutPoint, TxOut>,
inputs: UtxoMap,
del_hashes: Vec<sha256::Hash>,
) -> Result<u32, BlockchainError> {
T::connect_block(self, block, proof, inputs, del_hashes)
@@ -347,7 +362,7 @@ impl<T: BlockchainInterface> BlockchainInterface for Arc<T> {
&self,
block: &Block,
proof: Proof,
inputs: HashMap<OutPoint, TxOut>,
inputs: UtxoMap,
del_hashes: Vec<sha256::Hash>,
acc: Stump,
) -> Result<(), Self::Error> {
@@ -358,3 +373,120 @@ impl<T: BlockchainInterface> BlockchainInterface for Arc<T> {
T::get_fork_point(self, block)
}
}
/// Module to delegate local-time context.
///
/// The consumer of `Floresta-chain` has the option to implement [`NodeTime`] if on a non-std environment.([`get_time()`] implementation that returns 0u32 will disable time checks.)
///
/// On std you can just use a instance [`StdNodeTime`] as input.
pub mod nodetime {
/// Disable empty struct.
///
/// Meant to be used in cases to disable time verifications
pub struct DisableTime;
/// One Hour in seconds constant.
pub const HOUR: u32 = 60 * 60;
/// Trait to return time-related context of the chain.
///
/// [`get_time()`] should return a the latest [unix timestamp](https://en.wikipedia.org/wiki/Unix_time) when the consumer has time-notion.
///
/// if the consumer does not have any time notion or MTP control, its safe to use `0u32` to disable any validations on time.
pub trait NodeTime {
/// Should return a unix timestamp or 0 to skip any time related validation.
fn get_time(&self) -> u32;
}
impl NodeTime for DisableTime {
fn get_time(&self) -> u32 {
// we simply return zero to disable time checks
0
}
}
#[cfg(feature = "std")]
/// A module to provide the standard implementation of [`NodeTime`] trait. It uses [`std::time::SystemTime`] to get the current time.
pub mod standard_node_time {
extern crate std;
use std::time;
/// A empty struct to implement [`NodeTime`] trait using [`std::time::SystemTime`]
pub struct StdNodeTime;
impl super::NodeTime for StdNodeTime {
fn get_time(&self) -> u32 {
time::SystemTime::now()
.duration_since(time::UNIX_EPOCH)
.unwrap()
.as_secs() as u32
}
}
}
}
///Module to hold methods and structs related to UTXO data.
pub mod utxo_data {

use bitcoin::OutPoint;

use super::*;

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
/// A struct to hold unverified UTXOs and its metadata.
pub struct UtxoData {
/// The transaction output that created this UTXO.
pub(crate) txout: bitcoin::TxOut,
/// The time lock value of the utxo.
pub(crate) locked_by: u32,
}

impl From<TxOut> for UtxoData {
fn from(txout: TxOut) -> Self {
UtxoData {
txout,
locked_by: 0,
}
}
}
impl From<&TxOut> for UtxoData {
fn from(txout: &TxOut) -> Self {
UtxoData {
txout: txout.clone(),
locked_by: 0,
}
}
}

/// From a transaction, gets the u32 value thats locking this outpoint.
///
/// Returns 0 if isnt time locked at all.
pub fn extract_lock_value(tx: &Transaction) -> u32 {
if !tx.is_lock_time_enabled() {
return 0;
}
if tx.is_lock_time_enabled() {
return tx.lock_time.to_consensus_u32();
}

// # Getting the value
//
// Sometimes the sequence holds a u16 value when its set to
// lock the input as a relative time lock.
//
// Here i checking if any of the sequences present is set
// to lock the transaction and i store the highest lock from
// the transaction.
let mut sequence_value: u32 = 0;

let mut is_sequence_locked: bool = false;

for inp in tx.input.iter() {
if inp.sequence.is_time_locked() {
if &inp.sequence.0 > &sequence_value {
sequence_value = inp.sequence.0.clone();
is_sequence_locked = true;
continue;
}
}
}

if is_sequence_locked {
return sequence_value;
}
return 0;
}
pub(crate) type UtxoMap = HashMap<OutPoint, UtxoData>;
}
19 changes: 12 additions & 7 deletions crates/floresta-chain/src/pruned_utreexo/partial_chain.rs
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@
//! This choice removes the use of costly atomic operations, but opens space for design flaws
//! and memory unsoundness, so here are some tips about this module and how people looking for
//! extend or use this code should proceed:
//!
//!
//! - Shared ownership is forbidden: if you have two threads or tasks owning this, you'll have
//! data race. If you want to hold shared ownership for this module, you need to place a
//! [PartialChainState] inside an `Arc<Mutex>` yourself. Don't just Arc this and expect it to
@@ -36,6 +36,7 @@ use super::chainparams::ChainParams;
use super::consensus::Consensus;
use super::error::BlockValidationErrors;
use super::error::BlockchainError;
use super::utxo_data::UtxoMap;
use super::BlockchainInterface;
use super::UpdatableChainstate;
use crate::UtreexoBlock;
@@ -171,7 +172,7 @@ impl PartialChainStateInner {
&mut self,
block: &bitcoin::Block,
proof: rustreexo::accumulator::proof::Proof,
inputs: HashMap<bitcoin::OutPoint, bitcoin::TxOut>,
inputs: UtxoMap,
del_hashes: Vec<bitcoin::hashes::sha256::Hash>,
) -> Result<u32, BlockchainError> {
let height = self.current_height + 1;
@@ -208,7 +209,7 @@ impl PartialChainStateInner {
&self,
block: &bitcoin::Block,
height: u32,
inputs: HashMap<bitcoin::OutPoint, bitcoin::TxOut>,
inputs: UtxoMap,
) -> Result<(), BlockchainError> {
if !block.check_merkle_root() {
return Err(BlockchainError::BlockValidation(
@@ -244,6 +245,7 @@ impl PartialChainStateInner {
let flags = 0;
Consensus::verify_block_transactions(
height,
None,
inputs,
&block.txdata,
subsidy,
@@ -262,7 +264,7 @@ impl PartialChainState {
/// [PartialChainState] is through our APIs, and we make sure this [UnsafeCell] is
/// always valid.
/// The reference returned here **should not** leak through the API, as there's no
/// synchronization mechanims for it.
/// synchronization mechanism for it.
#[inline(always)]
#[must_use]
#[doc(hidden)]
@@ -277,7 +279,7 @@ impl PartialChainState {
/// [PartialChainState] is through our APIs, and we make sure this [UnsafeCell] is
/// always valid.
/// The reference returned here **should not** leak through the API, as there's no
/// synchronization mechanims for it.
/// synchronization mechanism for it.
#[inline(always)]
#[allow(clippy::mut_from_ref)]
#[must_use]
@@ -307,11 +309,14 @@ impl PartialChainState {
}

impl UpdatableChainstate for PartialChainState {
fn get_mtp(&self, _height: u32) -> Result<u32, BlockchainError> {
unimplemented!("a partialChainState will probably give an incomplete MTP")
}
fn connect_block(
&self,
block: &bitcoin::Block,
proof: rustreexo::accumulator::proof::Proof,
inputs: HashMap<bitcoin::OutPoint, bitcoin::TxOut>,
inputs: UtxoMap,
del_hashes: Vec<bitcoin::hashes::sha256::Hash>,
) -> Result<u32, BlockchainError> {
self.inner_mut()
@@ -429,7 +434,7 @@ impl BlockchainInterface for PartialChainState {
&self,
_block: &bitcoin::Block,
_proof: rustreexo::accumulator::proof::Proof,
_inputs: HashMap<bitcoin::OutPoint, bitcoin::TxOut>,
_inputs: UtxoMap,
_del_hashes: Vec<bitcoin::hashes::sha256::Hash>,
_acc: Stump,
) -> Result<(), Self::Error> {
19 changes: 16 additions & 3 deletions crates/floresta-chain/src/pruned_utreexo/udata.rs
Original file line number Diff line number Diff line change
@@ -300,6 +300,8 @@ pub mod proof_util {

use super::LeafData;
use crate::prelude::*;
use crate::pruned_utreexo::utxo_data::extract_lock_value;
use crate::pruned_utreexo::utxo_data::UtxoData;
use crate::pruned_utreexo::BlockchainInterface;
use crate::CompactLeafData;
use crate::ScriptPubkeyType;
@@ -333,7 +335,7 @@ pub mod proof_util {
udata: &UData,
transactions: &[Transaction],
chain: &Chain,
) -> Result<(Proof, Vec<sha256::Hash>, HashMap<OutPoint, TxOut>), Chain::Error> {
) -> Result<(Proof, Vec<sha256::Hash>, HashMap<OutPoint, UtxoData>), Chain::Error> {
let targets = udata.proof.targets.iter().map(|target| target.0).collect();
let hashes = udata
.proof
@@ -350,14 +352,19 @@ pub mod proof_util {
tx_iter.next(); // Skip coinbase

for tx in tx_iter {
let tx_lock = extract_lock_value(tx);

let txid = tx.compute_txid();
for (vout, out) in tx.output.iter().enumerate() {
inputs.insert(
OutPoint {
txid,
vout: vout as u32,
},
out.clone(),
UtxoData {
txout: out.clone(),
locked_by: 0,
},
);
}

@@ -369,7 +376,13 @@ pub mod proof_util {
let leaf =
reconstruct_leaf_data(&leaf, input, hash).expect("Invalid proof");
hashes.push(leaf._get_leaf_hashes());
inputs.insert(leaf.prevout, leaf.utxo);
inputs.insert(
leaf.prevout,
UtxoData {
txout: leaf.utxo,
locked_by: tx_lock,
},
);
}
}
}
2 changes: 1 addition & 1 deletion crates/floresta-wire/src/p2p_wire/node.rs
Original file line number Diff line number Diff line change
@@ -227,7 +227,7 @@ where
.fixed_peer
.as_ref()
.map(|address| {
Self::resolve_connect_host(&address, Self::get_port(config.network.into()))
Self::resolve_connect_host(address, Self::get_port(config.network.into()))
})
.transpose()?;

5 changes: 5 additions & 0 deletions crates/floresta-wire/src/p2p_wire/running_node.rs
Original file line number Diff line number Diff line change
@@ -677,11 +677,16 @@ where
// to be invalidated.
match e {
BlockValidationErrors::InvalidCoinbase(_)
| BlockValidationErrors::InvalidBlockTimestamp
| BlockValidationErrors::UtxoNotFound(_)
| BlockValidationErrors::BadAbsoluteLockTime
| BlockValidationErrors::BadRelativeLockTime
| BlockValidationErrors::ScriptValidationError(_)
| BlockValidationErrors::InvalidOutput
| BlockValidationErrors::ScriptError
| BlockValidationErrors::BlockTooBig
| BlockValidationErrors::BlockTooNew
| BlockValidationErrors::BlockTooOld
| BlockValidationErrors::NotEnoughPow
| BlockValidationErrors::TooManyCoins
| BlockValidationErrors::BadMerkleRoot
5 changes: 5 additions & 0 deletions crates/floresta-wire/src/p2p_wire/sync_node.rs
Original file line number Diff line number Diff line change
@@ -220,11 +220,16 @@ where
// to be invalidated.
match e {
BlockValidationErrors::InvalidCoinbase(_)
| BlockValidationErrors::InvalidBlockTimestamp
| BlockValidationErrors::UtxoNotFound(_)
| BlockValidationErrors::BadAbsoluteLockTime
| BlockValidationErrors::BadRelativeLockTime
| BlockValidationErrors::ScriptValidationError(_)
| BlockValidationErrors::InvalidOutput
| BlockValidationErrors::ScriptError
| BlockValidationErrors::BlockTooBig
| BlockValidationErrors::BlockTooNew
| BlockValidationErrors::BlockTooOld
| BlockValidationErrors::NotEnoughPow
| BlockValidationErrors::TooManyCoins
| BlockValidationErrors::BadMerkleRoot

0 comments on commit b247973

Please sign in to comment.