From 37f3b5b2cc84211dc8a68fbdbb0904df0bfceb0b Mon Sep 17 00:00:00 2001 From: Davidson Souza Date: Wed, 16 Aug 2023 21:16:09 -0300 Subject: [PATCH 1/2] Refactor the ChainStore trait and remove hardcoded KvDatabase --- Cargo.lock | 21 ++++++--- crates/floresta-chain/Cargo.toml | 16 +++---- .../src/pruned_utreexo/chain_state.rs | 4 +- .../src/pruned_utreexo/chain_state_builder.rs | 4 +- .../src/pruned_utreexo/chainstore.rs | 43 ++++++++++--------- .../src/pruned_utreexo/consensus.rs | 8 +++- .../src/pruned_utreexo/error.rs | 16 +++++-- .../src/pruned_utreexo/partial_chain.rs | 16 ++++--- crates/floresta-common/src/lib.rs | 3 +- crates/floresta-wire/Cargo.toml | 4 +- crates/floresta-wire/src/lib.rs | 4 +- crates/floresta/Cargo.toml | 2 +- 12 files changed, 86 insertions(+), 55 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4676180d..2d500a25 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -742,7 +742,7 @@ dependencies = [ "floresta-wire", "hashbrown 0.14.0", "miniscript 10.0.0", - "rustreexo", + "rustreexo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -760,8 +760,8 @@ dependencies = [ "log", "pretty_assertions", "rand 0.8.5", - "rustreexo", - "secp256k1 0.27.0", + "rustreexo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "secp256k1 0.24.3", "serde", "serde_json", "sha2", @@ -808,7 +808,7 @@ dependencies = [ "pretty_assertions", "rand 0.8.5", "rmp-serde", - "rustreexo", + "rustreexo 0.1.0 (git+https://www.github.com/mit-dci/rustreexo)", "serde", "serde_json", "sha2", @@ -849,7 +849,7 @@ dependencies = [ "pretty_assertions", "rand 0.8.5", "rmp-serde", - "rustreexo", + "rustreexo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde", "serde_json", "sha2", @@ -885,7 +885,7 @@ dependencies = [ "pretty_env_logger", "rand 0.8.5", "rmp-serde", - "rustreexo", + "rustreexo 0.1.0 (git+https://www.github.com/mit-dci/rustreexo)", "serde", "serde_json", "sha2", @@ -2181,6 +2181,15 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "rustreexo" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4852cab7dec3e1d89bb3ce30ca3461f7d6baee2143d0460c07bf1a718af68997" +dependencies = [ + "bitcoin_hashes 0.12.0", +] + [[package]] name = "rustreexo" version = "0.1.0" diff --git a/crates/floresta-chain/Cargo.toml b/crates/floresta-chain/Cargo.toml index 84f6b081..b2f55542 100644 --- a/crates/floresta-chain/Cargo.toml +++ b/crates/floresta-chain/Cargo.toml @@ -4,27 +4,26 @@ version = "0.1.0" edition = "2021" [lib] -crate-type = ["rlib"] +crate-type = ["cdylib", "rlib"] [dependencies] -rustreexo = { git = "https://www.github.com/mit-dci/rustreexo" } +rustreexo = "0.1.0" sha2 = "^0.10.6" log = "0.4" kv = "0.24.0" bitcoin = { version = "0.29", features = [ "serde", "no-std", - "bitcoinconsensus", -] } +], default-features = false } spin = "0.9.8" core2 = { version = "0.4.0", optional = true } hashbrown = { version = "0.14.0", optional = true } -secp256k1 = { version = "*", features = ["alloc"] } +secp256k1 = { version = "*", features = ["alloc"], optional = true } async-std = { version = "1.12.0", default-features = false, features = [ "std", "futures-core", ] } -floresta-common = { path = "../floresta-common" } +floresta-common = { path = "../floresta-common", default-features = false } futures = "0.3.28" wasm-bindgen = "0.2.87" @@ -34,7 +33,4 @@ rand = "0.8.5" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" zstd = "0.12.3" -hex = "0.4.3" - -[features] -no-std = ["hashbrown", "core2"] +hex = "0.4.3" \ No newline at end of file diff --git a/crates/floresta-chain/src/pruned_utreexo/chain_state.rs b/crates/floresta-chain/src/pruned_utreexo/chain_state.rs index af76475b..d5a4edc9 100644 --- a/crates/floresta-chain/src/pruned_utreexo/chain_state.rs +++ b/crates/floresta-chain/src/pruned_utreexo/chain_state.rs @@ -410,10 +410,10 @@ impl ChainState { } pub fn new( - chainstore: KvChainStore, + chainstore: PersistedState, network: Network, assume_valid: Option, - ) -> ChainState { + ) -> ChainState { let genesis = genesis_block(network.into()); chainstore .save_header(&super::chainstore::DiskBlockHeader::FullyValid( diff --git a/crates/floresta-chain/src/pruned_utreexo/chain_state_builder.rs b/crates/floresta-chain/src/pruned_utreexo/chain_state_builder.rs index 1eb17cca..df78472b 100644 --- a/crates/floresta-chain/src/pruned_utreexo/chain_state_builder.rs +++ b/crates/floresta-chain/src/pruned_utreexo/chain_state_builder.rs @@ -2,7 +2,9 @@ use bitcoin::hashes::Hash; use bitcoin::BlockHash; use rustreexo::accumulator::stump::Stump; -use crate::{BestChain, ChainParams, ChainState, ChainStore}; +use super::chain_state::{BestChain, ChainState}; +use super::chainparams::ChainParams; +use super::chainstore::ChainStore; #[derive(Clone, Debug)] pub enum BlockchainBuilderError { diff --git a/crates/floresta-chain/src/pruned_utreexo/chainstore.rs b/crates/floresta-chain/src/pruned_utreexo/chainstore.rs index f8827720..9619810e 100644 --- a/crates/floresta-chain/src/pruned_utreexo/chainstore.rs +++ b/crates/floresta-chain/src/pruned_utreexo/chainstore.rs @@ -3,7 +3,6 @@ //! This is a basic kv database that stores all metadata about our blockchain and utreexo //! state. //! Author: Davidson Souza -type Result = core::result::Result; use crate::prelude::*; use bitcoin::{ @@ -110,24 +109,25 @@ impl Encodable for DiskBlockHeader { } use kv::{Config, Integer, Store}; -use super::chain_state::BestChain; +use super::{chain_state::BestChain, error::DatabaseError}; pub trait ChainStore { + type Error: DatabaseError; /// Saves the current state of our accumulator. - fn save_roots(&self, roots: Vec) -> Result<()>; + fn save_roots(&self, roots: Vec) -> Result<(), Self::Error>; /// Loads the state of our accumulator. - fn load_roots(&self) -> Result>>; + fn load_roots(&self) -> Result>, Self::Error>; /// Loads the blockchain height - fn load_height(&self) -> Result>; - fn save_height(&self, height: &BestChain) -> Result<()>; - fn get_header(&self, block_hash: &BlockHash) -> Result>; - fn save_header(&self, header: &DiskBlockHeader) -> Result<()>; - fn get_block_hash(&self, height: u32) -> Result>; - fn flush(&self) -> Result<()>; - fn update_block_index(&self, height: u32, hash: BlockHash) -> Result<()>; + fn load_height(&self) -> Result, Self::Error>; + fn save_height(&self, height: &BestChain) -> Result<(), Self::Error>; + fn get_header(&self, block_hash: &BlockHash) -> Result, Self::Error>; + fn save_header(&self, header: &DiskBlockHeader) -> Result<(), Self::Error>; + fn get_block_hash(&self, height: u32) -> Result, Self::Error>; + fn flush(&self) -> Result<(), Self::Error>; + fn update_block_index(&self, height: u32, hash: BlockHash) -> Result<(), Self::Error>; } pub struct KvChainStore(Store); impl KvChainStore { - pub fn new(datadir: String) -> Result { + pub fn new(datadir: String) -> Result { // Configure the database let cfg = Config::new(datadir + "/chain_data").cache_capacity(100_000_000); @@ -138,18 +138,19 @@ impl KvChainStore { } } impl ChainStore for KvChainStore { - fn load_roots(&self) -> Result>> { + type Error = kv::Error; + fn load_roots(&self) -> Result>, Self::Error> { let bucket = self.0.bucket::<&str, Vec>(None)?; bucket.get(&"roots") } - fn save_roots(&self, roots: Vec) -> Result<()> { + fn save_roots(&self, roots: Vec) -> Result<(), Self::Error> { let bucket = self.0.bucket::<&str, Vec>(None)?; bucket.set(&"roots", &roots)?; Ok(()) } - fn load_height(&self) -> Result> { + fn load_height(&self) -> Result, Self::Error> { let bucket = self.0.bucket::<&str, Vec>(None)?; let height = bucket.get(&"height")?; @@ -159,13 +160,13 @@ impl ChainStore for KvChainStore { Ok(None) } - fn save_height(&self, height: &BestChain) -> Result<()> { + fn save_height(&self, height: &BestChain) -> Result<(), Self::Error> { let bucket = self.0.bucket::<&str, Vec>(None)?; let height = serialize(height); bucket.set(&"height", &height)?; Ok(()) } - fn get_header(&self, block_hash: &BlockHash) -> Result> { + fn get_header(&self, block_hash: &BlockHash) -> Result, Self::Error> { let bucket = self.0.bucket::<&[u8], Vec>(Some("header"))?; let block_hash = serialize(&block_hash); @@ -175,7 +176,7 @@ impl ChainStore for KvChainStore { } Ok(None) } - fn flush(&self) -> Result<()> { + fn flush(&self) -> Result<(), Self::Error> { // Flush the header bucket let bucket = self.0.bucket::<&[u8], Vec>(Some("header"))?; bucket.flush()?; @@ -188,7 +189,7 @@ impl ChainStore for KvChainStore { Ok(()) } - fn save_header(&self, header: &DiskBlockHeader) -> Result<()> { + fn save_header(&self, header: &DiskBlockHeader) -> Result<(), Self::Error> { let ser_header = serialize(header); let block_hash = serialize(&header.block_hash()); let bucket = self.0.bucket::<&[u8], Vec>(Some("header"))?; @@ -196,7 +197,7 @@ impl ChainStore for KvChainStore { Ok(()) } - fn get_block_hash(&self, height: u32) -> Result> { + fn get_block_hash(&self, height: u32) -> Result, Self::Error> { let bucket = self.0.bucket::>(Some("index"))?; let block = bucket.get(&Integer::from(height))?; if let Some(block) = block { @@ -205,7 +206,7 @@ impl ChainStore for KvChainStore { Ok(None) } - fn update_block_index(&self, height: u32, hash: BlockHash) -> Result<()> { + fn update_block_index(&self, height: u32, hash: BlockHash) -> Result<(), Self::Error> { let bucket = self.0.bucket::>(Some("index"))?; let block_hash = serialize(&hash); diff --git a/crates/floresta-chain/src/pruned_utreexo/consensus.rs b/crates/floresta-chain/src/pruned_utreexo/consensus.rs index 74177d57..2940c6b5 100644 --- a/crates/floresta-chain/src/pruned_utreexo/consensus.rs +++ b/crates/floresta-chain/src/pruned_utreexo/consensus.rs @@ -16,7 +16,11 @@ use core::ffi::c_uint; use rustreexo::accumulator::{node_hash::NodeHash, proof::Proof, stump::Stump}; use sha2::{Digest, Sha512_256}; -use crate::{BlockValidationErrors, BlockchainError, ChainParams}; +use super::{ + chainparams::ChainParams, + error::{BlockValidationErrors, BlockchainError}, +}; + /// This struct contains all the information and methods needed to validate a block, /// it is used by the [ChainState] to validate blocks and transactions. #[derive(Debug, Clone)] @@ -180,7 +184,7 @@ impl Consensus { .map(|hash| NodeHash::from(hash.into_inner())) .collect::>(); // Verify the proof of inclusion of the deleted nodes - if !proof.verify(&del_hashes, acc)? { + if !acc.verify(&proof, &del_hashes)? { return Err(BlockValidationErrors::InvalidProof.into()); } // Get inputs from the block, we'll need this HashSet to check if an output is spent diff --git a/crates/floresta-chain/src/pruned_utreexo/error.rs b/crates/floresta-chain/src/pruned_utreexo/error.rs index ad12a79a..13775337 100644 --- a/crates/floresta-chain/src/pruned_utreexo/error.rs +++ b/crates/floresta-chain/src/pruned_utreexo/error.rs @@ -1,9 +1,11 @@ use crate::prelude::*; + use bitcoin::blockdata::script; #[cfg(feature = "cli-blockchain")] use btcd_rpc::error::UtreexodError; +use core::fmt::Debug; use floresta_common::impl_error_from; - +pub trait DatabaseError: Debug + Send + Sync + 'static {} #[derive(Debug)] pub enum BlockchainError { BlockNotPresent, @@ -14,7 +16,7 @@ pub enum BlockchainError { BlockValidationError(BlockValidationErrors), InvalidProof, UtreexoError(String), - DatabaseError(kv::Error), + DatabaseError(Box), ConsensusDecodeError(bitcoin::consensus::encode::Error), ChainNotInitialized, InvalidTip(String), @@ -67,7 +69,13 @@ impl Display for BlockValidationErrors { } } } -impl_error_from!(BlockchainError, kv::Error, DatabaseError); + +impl From for BlockchainError { + fn from(value: T) -> Self { + BlockchainError::DatabaseError(Box::new(value)) + } +} + impl_error_from!(BlockchainError, ioError, IoError); impl_error_from!( BlockchainError, @@ -78,3 +86,5 @@ impl_error_from!(BlockchainError, BlockValidationErrors, BlockValidationError); impl_error_from!(BlockchainError, bitcoin::hashes::hex::Error, ParsingError); impl_error_from!(BlockchainError, String, UtreexoError); impl_error_from!(BlockchainError, script::Error, ScriptValidationFailed); + +impl DatabaseError for kv::Error {} diff --git a/crates/floresta-chain/src/pruned_utreexo/partial_chain.rs b/crates/floresta-chain/src/pruned_utreexo/partial_chain.rs index 81588eaf..b4aa61bc 100644 --- a/crates/floresta-chain/src/pruned_utreexo/partial_chain.rs +++ b/crates/floresta-chain/src/pruned_utreexo/partial_chain.rs @@ -5,14 +5,16 @@ use floresta_common::prelude::*; -use super::consensus::Consensus; +use super::{ + chainparams::ChainParams, + consensus::Consensus, + error::{BlockValidationErrors, BlockchainError}, +}; use bitcoin::{bitcoinconsensus, BlockHeader}; use core::ffi::c_uint; use log::info; use rustreexo::accumulator::stump::Stump; -use crate::{BlockValidationErrors, BlockchainError, ChainParams}; - /// A partial chain is a chain that only contains a subset of the blocks in the /// full chain. We use multiple partial chains to sync up with the full chain, /// and then merge them together to get the full chain. This allows us to conduct @@ -216,11 +218,15 @@ mod tests { use core::str::FromStr; use std::collections::HashMap; - use crate::{BlockValidationErrors, Network}; use bitcoin::{consensus::deserialize, Block}; use rustreexo::accumulator::{node_hash::NodeHash, proof::Proof, stump::Stump}; - use crate::{pruned_utreexo::consensus::Consensus, ChainParams}; + use crate::{ + pruned_utreexo::{ + chainparams::ChainParams, consensus::Consensus, error::BlockValidationErrors, + }, + Network, + }; use super::PartialChainState; #[test] diff --git a/crates/floresta-common/src/lib.rs b/crates/floresta-common/src/lib.rs index 9b52adec..8cff3106 100644 --- a/crates/floresta-common/src/lib.rs +++ b/crates/floresta-common/src/lib.rs @@ -37,7 +37,7 @@ pub fn parse_descriptors( #[cfg(feature = "no-std")] pub mod prelude { extern crate alloc; - pub use alloc::{borrow::ToOwned, string::String, vec, vec::Vec}; + pub use alloc::{borrow::ToOwned, boxed::Box, string::String, vec, vec::Vec}; pub use core::{ cmp, convert, core::str::FromStr, @@ -59,6 +59,7 @@ pub mod prelude { extern crate std; pub use std::borrow::ToOwned; pub use std::{ + boxed::Box, collections::{hash_map::Entry, HashMap, HashSet}, error::Error, fmt::{self, Display, Formatter}, diff --git a/crates/floresta-wire/Cargo.toml b/crates/floresta-wire/Cargo.toml index e2b5aaed..31673121 100644 --- a/crates/floresta-wire/Cargo.toml +++ b/crates/floresta-wire/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -rustreexo = { git = "https://www.github.com/mit-dci/rustreexo" } +rustreexo = "0.1.0" btcd-rpc = { git = "https://github.com/Davidson-Souza/rust-btcd-rpc", features = [ "utreexod", ], branch = "use-reqwest", optional = true } @@ -31,4 +31,4 @@ pretty_assertions = "1" [features] default = [] -pruned_utreexo_chainstate = [] +pruned_utreexo_chainstate = [] \ No newline at end of file diff --git a/crates/floresta-wire/src/lib.rs b/crates/floresta-wire/src/lib.rs index 05388279..80fb4b20 100644 --- a/crates/floresta-wire/src/lib.rs +++ b/crates/floresta-wire/src/lib.rs @@ -1,7 +1,9 @@ +#[cfg(not(target_arch = "wasm32"))] mod p2p_wire; +#[cfg(not(target_arch = "wasm32"))] +pub use p2p_wire::{address_man, mempool, node, node_context, node_interface}; use bitcoin::{Block, BlockHeader, Transaction}; -pub use p2p_wire::{address_man, mempool, node, node_context, node_interface}; /// NodeHooks is a trait that defines the hooks that a node can use to interact with the network /// and the blockchain. Every time an event happens, the node will call the corresponding hook. diff --git a/crates/floresta/Cargo.toml b/crates/floresta/Cargo.toml index 947c3f3b..7caebab6 100644 --- a/crates/floresta/Cargo.toml +++ b/crates/floresta/Cargo.toml @@ -20,7 +20,7 @@ floresta-watch-only = { path = "../floresta-watch-only", features = ["memory-dat hashbrown = "0.14.0" [dev-dependencies] -rustreexo = { git = "https://www.github.com/mit-dci/rustreexo" } +rustreexo = "0.1.0" miniscript = "10.0.0" async-std = "1.12.0" bitcoin = { version = "0.29", features = [ From 76229d8642cfb56dfe2437fe110718fe29985ef1 Mon Sep 17 00:00:00 2001 From: Davidson Souza Date: Thu, 17 Aug 2023 17:53:09 -0300 Subject: [PATCH 2/2] Make libbitcoinconsensus an optional feature --- crates/floresta-chain/Cargo.toml | 5 +- .../src/pruned_utreexo/chain_state.rs | 10 +++- .../src/pruned_utreexo/chainparams.rs | 54 ++++++++++++------- .../src/pruned_utreexo/consensus.rs | 1 + .../src/pruned_utreexo/partial_chain.rs | 8 ++- crates/floresta-common/Cargo.toml | 6 ++- crates/floresta-common/src/lib.rs | 2 + 7 files changed, 61 insertions(+), 25 deletions(-) diff --git a/crates/floresta-chain/Cargo.toml b/crates/floresta-chain/Cargo.toml index b2f55542..5f958ec7 100644 --- a/crates/floresta-chain/Cargo.toml +++ b/crates/floresta-chain/Cargo.toml @@ -33,4 +33,7 @@ rand = "0.8.5" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" zstd = "0.12.3" -hex = "0.4.3" \ No newline at end of file +hex = "0.4.3" + +[features] +bitcoinconsensus = ["bitcoin/bitcoinconsensus"] \ No newline at end of file diff --git a/crates/floresta-chain/src/pruned_utreexo/chain_state.rs b/crates/floresta-chain/src/pruned_utreexo/chain_state.rs index d5a4edc9..44ae6ab6 100644 --- a/crates/floresta-chain/src/pruned_utreexo/chain_state.rs +++ b/crates/floresta-chain/src/pruned_utreexo/chain_state.rs @@ -11,8 +11,10 @@ use crate::prelude::*; use crate::{read_lock, write_lock, Network}; use alloc::{borrow::ToOwned, fmt::format, string::ToString, vec::Vec}; use async_std::channel::Sender; +#[cfg(feature = "bitcoinconsensus")] +use bitcoin::bitcoinconsensus; + use bitcoin::{ - bitcoinconsensus, blockdata::constants::genesis_block, consensus::{deserialize_partial, Decodable, Encodable}, hashes::{hex::FromHex, sha256}, @@ -71,6 +73,7 @@ impl ChainState { _ => {} } } + #[cfg(feature = "bitcoinconsensus")] /// Returns the validation flags, given the current block height fn get_validation_flags(&self, height: u32) -> c_uint { let chains_params = &read_lock!(self).consensus.parameters; @@ -661,7 +664,10 @@ impl ChainState { // 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); + #[cfg(not(feature = "bitcoinconsensus"))] + let flags = 0; Consensus::verify_block_transactions(inputs, &block.txdata, subsidy, verify_script, flags) .map_err(|_| BlockchainError::BlockValidationError(BlockValidationErrors::InvalidTx))?; Ok(()) @@ -962,7 +968,7 @@ macro_rules! write_lock { }; } -#[derive(Clone)] +#[derive(Clone, Debug)] /// Internal representation of the chain we are in pub struct BestChain { /// Hash of the last block in the chain we believe has more work on diff --git a/crates/floresta-chain/src/pruned_utreexo/chainparams.rs b/crates/floresta-chain/src/pruned_utreexo/chainparams.rs index c1d99a41..a24a8920 100644 --- a/crates/floresta-chain/src/pruned_utreexo/chainparams.rs +++ b/crates/floresta-chain/src/pruned_utreexo/chainparams.rs @@ -3,10 +3,15 @@ use crate::prelude::*; use alloc::vec::Vec; use crate::Network; + +#[cfg(feature = "bitcoinconsensus")] use bitcoin::{ bitcoinconsensus::{VERIFY_NONE, VERIFY_P2SH, VERIFY_WITNESS}, - blockdata::constants::{genesis_block, max_target}, hashes::hex::FromHex, +}; + +use bitcoin::{ + blockdata::constants::{genesis_block, max_target}, util::uint::Uint256, Block, BlockHash, }; @@ -71,29 +76,38 @@ impl ChainParams { } } } +#[cfg(feature = "bitcoinconsensus")] +fn get_exceptions() -> HashMap { + // For some reason, some blocks in the mainnet and testnet have different rules than it should + // be, so we need to keep a list of exceptions and treat them differently + let mut exceptions = HashMap::new(); + exceptions.insert( + BlockHash::from_hex("00000000000002dc756eebf4f49723ed8d30cc28a5f108eb94b1ba88ac4f9c22") + .unwrap(), + VERIFY_NONE, + ); // BIP16 exception on main net + exceptions.insert( + BlockHash::from_hex("0000000000000000000f14c35b2d841e986ab5441de8c585d5ffe55ea1e395ad") + .unwrap(), + VERIFY_P2SH | VERIFY_WITNESS, + ); // Taproot exception on main net + exceptions.insert( + BlockHash::from_hex("00000000dd30457c001f4095d208cc1296b0eed002427aa599874af7a432b105") + .unwrap(), + VERIFY_NONE, + ); // BIP16 exception on test net + exceptions +} + +#[cfg(not(feature = "bitcoinconsensus"))] +fn get_exceptions() -> HashMap { + HashMap::new() +} impl From for ChainParams { fn from(net: Network) -> Self { let genesis = genesis_block(net.into()); let max_target = ChainParams::max_target(net); - // For some reason, some blocks in the mainnet and testnet have different rules than it should - // be, so we need to keep a list of exceptions and treat them differently - let mut exceptions = HashMap::new(); - exceptions.insert( - BlockHash::from_hex("00000000000002dc756eebf4f49723ed8d30cc28a5f108eb94b1ba88ac4f9c22") - .unwrap(), - VERIFY_NONE, - ); // BIP16 exception on main net - exceptions.insert( - BlockHash::from_hex("0000000000000000000f14c35b2d841e986ab5441de8c585d5ffe55ea1e395ad") - .unwrap(), - VERIFY_P2SH | VERIFY_WITNESS, - ); // Taproot exception on main net - exceptions.insert( - BlockHash::from_hex("00000000dd30457c001f4095d208cc1296b0eed002427aa599874af7a432b105") - .unwrap(), - VERIFY_NONE, - ); // BIP16 exception on test net - + let exceptions = get_exceptions(); match net { Network::Bitcoin => ChainParams { genesis, diff --git a/crates/floresta-chain/src/pruned_utreexo/consensus.rs b/crates/floresta-chain/src/pruned_utreexo/consensus.rs index 2940c6b5..f3bc05c2 100644 --- a/crates/floresta-chain/src/pruned_utreexo/consensus.rs +++ b/crates/floresta-chain/src/pruned_utreexo/consensus.rs @@ -122,6 +122,7 @@ impl Consensus { // Fee is the difference between inputs and outputs fee += in_value - output_value; // Verify the tx script + #[cfg(feature = "bitcoinconsensus")] if verify_script { transaction.verify_with_flags(|outpoint| utxos.remove(outpoint), flags)?; } diff --git a/crates/floresta-chain/src/pruned_utreexo/partial_chain.rs b/crates/floresta-chain/src/pruned_utreexo/partial_chain.rs index b4aa61bc..43c56d2d 100644 --- a/crates/floresta-chain/src/pruned_utreexo/partial_chain.rs +++ b/crates/floresta-chain/src/pruned_utreexo/partial_chain.rs @@ -10,7 +10,9 @@ use super::{ consensus::Consensus, error::{BlockValidationErrors, BlockchainError}, }; -use bitcoin::{bitcoinconsensus, BlockHeader}; +#[cfg(feature = "bitcoinconsensus")] +use bitcoin::bitcoinconsensus; +use bitcoin::BlockHeader; use core::ffi::c_uint; use log::info; use rustreexo::accumulator::stump::Stump; @@ -73,6 +75,7 @@ impl PartialChainState { let index = height - self.initial_height; self.blocks.get(index as usize) } + #[cfg(feature = "bitcoinconsensus")] /// Returns the validation flags, given the current block height fn get_validation_flags(&self, height: u32) -> c_uint { let chains_params = &self.consensus.parameters; @@ -196,7 +199,10 @@ impl PartialChainState { // Validate block transactions let subsidy = self.consensus.get_subsidy(height); let verify_script = self.assume_valid; + #[cfg(feature = "bitcoinconsensus")] let flags = self.get_validation_flags(height); + #[cfg(not(feature = "bitcoinconsensus"))] + let flags = 0; let valid = Consensus::verify_block_transactions( inputs, &block.txdata, diff --git a/crates/floresta-common/Cargo.toml b/crates/floresta-common/Cargo.toml index 56c50f03..e88f7f1b 100644 --- a/crates/floresta-common/Cargo.toml +++ b/crates/floresta-common/Cargo.toml @@ -9,4 +9,8 @@ license = "MIT" [dependencies] sha2 = "^0.10.6" bitcoin = "0.29.2" -miniscript = { git = "https://github.com/douglaz/rust-miniscript.git", branch = "master-2023-03-30" } +miniscript = { git = "https://github.com/douglaz/rust-miniscript.git", optional = true, branch = "master-2023-03-30" } + +[features] +default = ["descriptors"] +descriptors = ["miniscript"] diff --git a/crates/floresta-common/src/lib.rs b/crates/floresta-common/src/lib.rs index 8cff3106..7ffa11f0 100644 --- a/crates/floresta-common/src/lib.rs +++ b/crates/floresta-common/src/lib.rs @@ -1,6 +1,7 @@ #![no_std] use bitcoin::hashes::{sha256, Hash}; use bitcoin::Script; +#[cfg(feature = "descriptors")] use miniscript::{Descriptor, DescriptorPublicKey}; use prelude::*; @@ -18,6 +19,7 @@ pub fn get_spk_hash(spk: &Script) -> sha256::Hash { hash.reverse(); sha256::Hash::from_slice(hash.as_slice()).expect("Engines shouldn't be Err") } +#[cfg(feature = "descriptors")] pub fn parse_descriptors( descriptors: &[String], ) -> Result>, miniscript::Error> {