Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: Create some very basic mempool stuff #346

Merged
merged 3 commits into from
Feb 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion crates/floresta-chain/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ categories = ["cryptography::cryptocurrencies", "database"]
crate-type = ["cdylib", "rlib"]

[dependencies]
rustreexo = "0.3.0"
rustreexo = "0.4"
sha2 = "^0.10.6"
log = "0.4"
kv = "0.24.0"
Expand Down
8 changes: 4 additions & 4 deletions crates/floresta-chain/src/pruned_utreexo/chain_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use log::trace;
use log::warn;
#[cfg(feature = "metrics")]
use metrics;
use rustreexo::accumulator::node_hash::NodeHash;
use rustreexo::accumulator::node_hash::BitcoinNodeHash;
use rustreexo::accumulator::proof::Proof;
use rustreexo::accumulator::stump::Stump;
use spin::RwLock;
Expand Down Expand Up @@ -634,7 +634,7 @@ impl<PersistedState: ChainStore> ChainState<PersistedState> {
assert_eq!(acc.len() % 32, 0);
while acc.len() >= 32 {
let root = acc.drain(0..32).collect::<Vec<u8>>();
let root = NodeHash::from(&*root);
let root = BitcoinNodeHash::from(&*root);
roots.push(root);
}
Stump { leaves, roots }
Expand Down Expand Up @@ -831,7 +831,7 @@ impl<PersistedState: ChainStore> BlockchainInterface for ChainState<PersistedSta
// verify the proof
let del_hashes = del_hashes
.iter()
.map(|hash| NodeHash::from(hash.as_byte_array()))
.map(|hash| BitcoinNodeHash::from(hash.as_byte_array()))
.collect::<Vec<_>>();

if !acc.verify(&proof, &del_hashes)? {
Expand Down Expand Up @@ -1170,7 +1170,7 @@ impl<PersistedState: ChainStore> UpdatableChainstate for ChainState<PersistedSta
Ok(())
}

fn get_root_hashes(&self) -> Vec<NodeHash> {
fn get_root_hashes(&self) -> Vec<BitcoinNodeHash> {
let inner = read_lock!(self);
inner.acc.roots.clone()
}
Expand Down
6 changes: 3 additions & 3 deletions crates/floresta-chain/src/pruned_utreexo/chainparams.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use bitcoin::p2p::ServiceFlags;
use bitcoin::params::Params;
use bitcoin::Block;
use bitcoin::BlockHash;
use rustreexo::accumulator::node_hash::NodeHash;
use rustreexo::accumulator::node_hash::BitcoinNodeHash;

use crate::prelude::*;
use crate::AssumeValidArg;
Expand Down Expand Up @@ -74,7 +74,7 @@ pub struct AssumeUtreexoValue {
/// Same as block_hash, but in height
pub height: u32,
/// The roots of the Utreexo accumulator at this block
pub roots: Vec<NodeHash>,
pub roots: Vec<BitcoinNodeHash>,
/// The number of leaves in the Utreexo accumulator at this block
pub leaves: u64,
}
Expand Down Expand Up @@ -109,7 +109,7 @@ impl ChainParams {
"972ea2c7472c22e4eab49e9c2db5757a048b271b6251883ce89ccfeaa38b47ab",
]
.into_iter()
.map(|x| NodeHash::from_str(x).unwrap())
.map(|x| BitcoinNodeHash::from_str(x).unwrap())
.collect(),
leaves: 2587882501,
},
Expand Down
86 changes: 7 additions & 79 deletions crates/floresta-chain/src/pruned_utreexo/consensus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,9 @@ extern crate alloc;
use core::ffi::c_uint;

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;
Expand All @@ -21,15 +19,14 @@ use bitcoin::TxIn;
use bitcoin::TxOut;
use bitcoin::Txid;
use floresta_common::prelude::*;
use rustreexo::accumulator::node_hash::NodeHash;
use rustreexo::accumulator::node_hash::BitcoinNodeHash;
use rustreexo::accumulator::proof::Proof;
use rustreexo::accumulator::stump::Stump;
use sha2::Digest;
use sha2::Sha512_256;

use super::chainparams::ChainParams;
use super::error::BlockValidationErrors;
use super::error::BlockchainError;
use super::udata;
use crate::TransactionError;

/// The value of a single coin in satoshis.
Expand Down Expand Up @@ -69,37 +66,6 @@ impl Consensus {
subsidy
}

/// Returns the hash of a leaf node in the utreexo accumulator.
#[inline]
fn get_leaf_hashes(
transaction: &Transaction,
vout: u32,
height: u32,
block_hash: BlockHash,
) -> sha256::Hash {
let header_code = height << 1;

let mut ser_utxo = Vec::new();
let utxo = transaction.output.get(vout as usize).unwrap();
utxo.consensus_encode(&mut ser_utxo).unwrap();
let header_code = if transaction.is_coinbase() {
header_code | 1
} else {
header_code
};

let leaf_hash = Sha512_256::new()
.chain_update(UTREEXO_TAG_V1)
.chain_update(UTREEXO_TAG_V1)
.chain_update(block_hash)
.chain_update(transaction.compute_txid())
.chain_update(vout.to_le_bytes())
.chain_update(header_code.to_le_bytes())
.chain_update(ser_utxo)
.finalize();
sha256::Hash::from_slice(leaf_hash.as_slice())
.expect("parent_hash: Engines shouldn't be Err")
}
/// Verify if all transactions in a block are valid. Here we check the following:
/// - The block must contain at least one transaction, and this transaction must be coinbase
/// - The first transaction in the block must be coinbase
Expand Down Expand Up @@ -279,6 +245,7 @@ impl Consensus {
CompactTarget::from_next_work_required(first_block.bits, actual_timespan as u64, params)
.into()
}

/// Updates our accumulator with the new block. This is done by calculating the new
/// root hash of the accumulator, and then verifying the proof of inclusion of the
/// deleted nodes. If the proof is valid, we return the new accumulator. Otherwise,
Expand All @@ -292,56 +259,17 @@ impl Consensus {
del_hashes: Vec<sha256::Hash>,
) -> Result<Stump, BlockchainError> {
let block_hash = block.block_hash();
let mut leaf_hashes = Vec::new();
let del_hashes = del_hashes
.iter()
.map(|hash| NodeHash::from(hash.as_byte_array()))
.map(|hash| BitcoinNodeHash::from(hash.as_byte_array()))
.collect::<Vec<_>>();
// Get inputs from the block, we'll need this HashSet to check if an output is spent
// in the same block. If it is, we don't need to add it to the accumulator.
let mut block_inputs = HashSet::new();
for transaction in block.txdata.iter() {
for input in transaction.input.iter() {
block_inputs.insert((input.previous_output.txid, input.previous_output.vout));
}
}

// Get all leaf hashes that will be added to the accumulator
for transaction in block.txdata.iter() {
for (i, output) in transaction.output.iter().enumerate() {
if !Self::is_unspendable(&output.script_pubkey)
&& !block_inputs.contains(&(transaction.compute_txid(), i as u32))
{
leaf_hashes.push(Self::get_leaf_hashes(
transaction,
i as u32,
height,
block_hash,
))
}
}
}
// Convert the leaf hashes to NodeHashes used in Rustreexo
let hashes: Vec<NodeHash> = leaf_hashes
.iter()
.map(|&hash| NodeHash::from(hash.as_byte_array()))
.collect();
let adds = udata::proof_util::get_block_adds(block, height, block_hash);

// Update the accumulator
let acc = acc.modify(&hashes, &del_hashes, &proof)?.0;
let acc = acc.modify(&adds, &del_hashes, &proof)?.0;
Ok(acc)
}

fn is_unspendable(script: &ScriptBuf) -> bool {
if script.len() > 10_000 {
return true;
}

if !script.is_empty() && script.as_bytes()[0] == 0x6a {
return true;
}

false
}
}
#[cfg(test)]
mod tests {
Expand Down
6 changes: 3 additions & 3 deletions crates/floresta-chain/src/pruned_utreexo/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use bitcoin::BlockHash;
use bitcoin::OutPoint;
use bitcoin::Transaction;
use bitcoin::TxOut;
use rustreexo::accumulator::node_hash::NodeHash;
use rustreexo::accumulator::node_hash::BitcoinNodeHash;
use rustreexo::accumulator::proof::Proof;
use rustreexo::accumulator::stump::Stump;

Expand Down Expand Up @@ -132,7 +132,7 @@ pub trait UpdatableChainstate {
/// marked as invalid.
fn mark_block_as_valid(&self, block: BlockHash) -> Result<(), BlockchainError>;
/// Returns the root hashes of our utreexo forest
fn get_root_hashes(&self) -> Vec<NodeHash>;
fn get_root_hashes(&self) -> Vec<BitcoinNodeHash>;
/// Returns a partial chainstate from a range of blocks.
///
/// [PartialChainState] is a simplified version of `ChainState` that is used during IBD.
Expand Down Expand Up @@ -223,7 +223,7 @@ impl<T: UpdatableChainstate> UpdatableChainstate for Arc<T> {
T::accept_header(self, header)
}

fn get_root_hashes(&self) -> Vec<NodeHash> {
fn get_root_hashes(&self) -> Vec<BitcoinNodeHash> {
T::get_root_hashes(self)
}

Expand Down
9 changes: 5 additions & 4 deletions crates/floresta-chain/src/pruned_utreexo/partial_chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
//! threads, as long as the origin thread gives away the ownership.
use bitcoin::BlockHash;
use floresta_common::prelude::*;
use rustreexo::accumulator::node_hash::BitcoinNodeHash;
extern crate alloc;

use core::cell::UnsafeCell;
Expand Down Expand Up @@ -318,7 +319,7 @@ impl UpdatableChainstate for PartialChainState {
.process_block(block, proof, inputs, del_hashes)
}

fn get_root_hashes(&self) -> Vec<rustreexo::accumulator::node_hash::NodeHash> {
fn get_root_hashes(&self) -> Vec<BitcoinNodeHash> {
self.inner().current_acc.roots.clone()
}

Expand Down Expand Up @@ -506,7 +507,7 @@ mod tests {
use bitcoin::block::Header;
use bitcoin::consensus::deserialize;
use bitcoin::Block;
use rustreexo::accumulator::node_hash::NodeHash;
use rustreexo::accumulator::node_hash::BitcoinNodeHash;
use rustreexo::accumulator::proof::Proof;
use rustreexo::accumulator::stump::Stump;

Expand Down Expand Up @@ -641,7 +642,7 @@ mod tests {
"bedb648c9a3c5741660f926c1552d83ebb4cb1842cca6855b6d1089bb4951ce1",
]
.iter()
.map(|hash| NodeHash::from_str(hash).unwrap())
.map(|hash| BitcoinNodeHash::from_str(hash).unwrap())
.collect();

let acc2 = Stump { roots, leaves: 100 };
Expand Down Expand Up @@ -682,7 +683,7 @@ mod tests {
"1864a4982532447dcb3d9a5d2fea9f8ed4e3b1e759d55b8a427fb599fed0c302",
]
.iter()
.map(|x| NodeHash::from(hex::decode(x).unwrap().as_slice()))
.map(|x| BitcoinNodeHash::from(hex::decode(x).unwrap().as_slice()))
.collect::<Vec<_>>();

let expected_acc: Stump = Stump { leaves: 150, roots };
Expand Down
Loading