Skip to content

Commit

Permalink
Derive clap::ValueEnum under cli feature (paritytech#11)
Browse files Browse the repository at this point in the history
* Derive clap::ValueEnum under cli feature

* Remove duplicate CoinStorageKey

* Parse listen_on as PeerId in CLI

* Increase the finalization step to 100 when major sync

Disk performance on mac M1 is so much faster that the race conditions
are still possible with 10 blocks, 100 blocks is fine now.

* Update README.md
  • Loading branch information
liuchengxu authored Jul 11, 2024
1 parent b569d15 commit 6e61e5f
Show file tree
Hide file tree
Showing 14 changed files with 37 additions and 57 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

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

4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ planning stages.
## Pros

- 🔄 **Fast Sync**. Employs Substrate's advanced state sync strategy, enabling Bitcoin fast sync
by downloading all headers and the state at a specific block.
- 🔗 **Substrate Integration**: Utilizes Substrate framework provide production-level blockchain infrastructures.
by downloading all headers and the state at a specific block, in decentralized manner.
- 🔗 **Substrate Integration**: Utilizes Substrate framework to provide production-level blockchain infrastructures.

## Disclaimer

Expand Down
5 changes: 5 additions & 0 deletions crates/sc-consensus-nakamoto/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ license.workspace = true
[dependencies]
async-trait = { workspace = true }
bitcoin = { workspace = true }
clap = { workspace = true, optional = true }
codec = { workspace = true }
futures = { workspace = true }
hex-literal = { workspace = true }
Expand All @@ -25,3 +26,7 @@ sp-state-machine = { workspace = true }
subcoin-primitives = { workspace = true }
thiserror = { workspace = true }
tracing = { workspace = true }

[features]
default = []
cli = ["clap"]
2 changes: 2 additions & 0 deletions crates/sc-consensus-nakamoto/src/block_import.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ fn clone_block_import_params<Block: BlockT>(
import_params
}

/// Block import configuration.
#[derive(Debug, Clone)]
pub struct ImportConfig {
/// Bitcoin network type.
Expand Down Expand Up @@ -151,6 +152,7 @@ where
}
}

/// Sets new block executor.
pub fn set_block_executor(&mut self, new_executor: Box<dyn BlockExecutor<Block>>) {
self.block_executor = new_executor;
}
Expand Down
18 changes: 1 addition & 17 deletions crates/sc-consensus-nakamoto/src/verification.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ use sc_client_api::{AuxStore, Backend, StorageProvider};
use sp_blockchain::HeaderBackend;
use sp_runtime::traits::Block as BlockT;
use std::marker::PhantomData;
use std::str::FromStr;
use std::sync::Arc;
use std::time::{SystemTime, UNIX_EPOCH};
use subcoin_primitives::runtime::bitcoin_block_subsidy;
use subcoin_primitives::{BackendExt, CoinStorageKey};

/// Represents the level of block verification.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "cli", derive(clap::ValueEnum))]
pub enum BlockVerification {
/// No verification performed.
None,
Expand All @@ -23,22 +23,6 @@ pub enum BlockVerification {
HeaderOnly,
}

impl FromStr for BlockVerification {
type Err = String;

fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_str() {
"none" => Ok(Self::None),
"full" => Ok(Self::Full),
"header-only" => Ok(Self::HeaderOnly),
_ => Err(format!(
"Invalid block verification value: {s}, \
possible values: [\"none\", \"full\", \"header-only\"]"
)),
}
}
}

/// Block verification error.
#[derive(Debug, thiserror::Error)]
pub enum Error {
Expand Down
5 changes: 5 additions & 0 deletions crates/subcoin-network/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ license.workspace = true
async-trait = { workspace = true }
bitcoin = { workspace = true }
chrono = { workspace = true }
clap = { workspace = true, optional = true }
fastrand = { workspace = true }
futures = { workspace = true }
indexmap = { workspace = true }
Expand All @@ -35,3 +36,7 @@ tracing = { workspace = true }
sp-tracing = { workspace = true }
subcoin-service = { workspace = true }
subcoin-test-service = { workspace = true }

[features]
default = []
cli = ["clap"]
31 changes: 10 additions & 21 deletions crates/subcoin-network/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ use serde::{Deserialize, Serialize};
use sp_runtime::traits::Block as BlockT;
use std::marker::PhantomData;
use std::net::{AddrParseError, SocketAddr, ToSocketAddrs};
use std::str::FromStr;
use std::sync::atomic::{AtomicBool, AtomicU64};
use std::sync::Arc;
use tokio::net::TcpListener;
Expand Down Expand Up @@ -149,6 +148,7 @@ fn seednodes(network: BitcoinNetwork) -> Vec<&'static str> {

/// Represents the strategy for block syncing.
#[derive(Debug, Clone, Copy, Default)]
#[cfg_attr(feature = "cli", derive(clap::ValueEnum))]
pub enum SyncStrategy {
/// Download the headers first, followed by the block bodies.
#[default]
Expand All @@ -157,21 +157,6 @@ pub enum SyncStrategy {
BlocksFirst,
}

impl FromStr for SyncStrategy {
type Err = String;

fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_str() {
"blocks-first" => Ok(Self::BlocksFirst),
"headers-first" => Ok(Self::HeadersFirst),
_ => Err(format!(
"Invalid sync strategy value: {s}, \
possible values: [\"blocks-first\", \"headers-first\"]"
)),
}
}
}

// Ignore the peer if it is not full with witness enabled as we only want to
// download from peers that can provide use full witness data for blocks.
fn validate_outbound_services(services: ServiceFlags) -> Result<(), Error> {
Expand Down Expand Up @@ -288,7 +273,7 @@ pub struct Params {
/// Bitcoin network type.
pub network: BitcoinNetwork,
/// Specify the local listen address.
pub listen_on: String,
pub listen_on: PeerId,
/// List of seednodes.
pub bootnodes: Vec<String>,
/// Whether to connect to the bootnode only.
Expand Down Expand Up @@ -365,6 +350,8 @@ where
}

/// Starts the network.
///
/// This must be run in a background task.
pub async fn run(self) -> Result<(), Error> {
let Self {
client,
Expand All @@ -376,14 +363,18 @@ where
_phantom,
} = self;

let listener = match TcpListener::bind(&params.listen_on).await {
let mut listen_on = params.listen_on;
let listener = match TcpListener::bind(&listen_on).await {
Ok(listener) => listener,
Err(e) if e.kind() == std::io::ErrorKind::AddrInUse => {
tracing::warn!(
"{} is occupied, trying any available port.",
params.listen_on
);
TcpListener::bind("0.0.0.0:0").await?

listen_on.set_port(0);

TcpListener::bind(listen_on).await?
}
Err(err) => return Err(err.into()),
};
Expand Down Expand Up @@ -437,8 +428,6 @@ where

network_worker.run(worker_msg_receiver, bandwidth).await;

tracing::error!("Subcoin network worker exited");

Ok(())
}
}
4 changes: 2 additions & 2 deletions crates/subcoin-node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pallet-bitcoin = { workspace = true }
sc-cli = { workspace = true }
sc-client-api = { workspace = true }
sc-consensus = { workspace = true }
sc-consensus-nakamoto = { workspace = true }
sc-consensus-nakamoto = { workspace = true, features = ["cli"] }
sc-executor = { workspace = true }
sc-informant = { workspace = true }
sc-network = { workspace = true }
Expand All @@ -44,7 +44,7 @@ sp-core = { workspace = true }
sp-io = { workspace = true }
sp-runtime = { workspace = true }
subcoin-informant = { workspace = true }
subcoin-network = { workspace = true }
subcoin-network = { workspace = true, features = ["cli"] }
subcoin-primitives = { workspace = true }
subcoin-rpc = { workspace = true }
subcoin-runtime = { workspace = true }
Expand Down
2 changes: 1 addition & 1 deletion crates/subcoin-node/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ pub fn run() -> sc_cli::Result<()> {
block_verification: run.block_verification,
execute_block: true,
},
Arc::new(crate::CoinStorageKey),
Arc::new(subcoin_service::CoinStorageKey),
block_executor,
);

Expand Down
3 changes: 2 additions & 1 deletion crates/subcoin-node/src/cli/params.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use clap::Parser;
use sc_consensus_nakamoto::{BlockExecutionStrategy, ExecutionBackend};
use std::path::PathBuf;
use subcoin_network::PeerId;

/// Chain.
///
Expand Down Expand Up @@ -37,7 +38,7 @@ pub struct NetworkParams {

/// Specify the local address and listen on it.
#[clap(long, default_value = "127.0.0.1:8333")]
pub listen: String,
pub listen: PeerId,

/// Whether to connect to the nodes using IPv6 address.
#[clap(long)]
Expand Down
2 changes: 1 addition & 1 deletion crates/subcoin-node/src/commands/import_blocks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ impl ImportBlocksCmd {
block_verification: BlockVerification::None,
execute_block: self.execute_block,
},
Arc::new(crate::CoinStorageKey),
Arc::new(subcoin_service::CoinStorageKey),
block_executor,
);

Expand Down
6 changes: 3 additions & 3 deletions crates/subcoin-node/src/commands/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ use subcoin_network::SyncStrategy;
#[derive(Debug, Clone, Parser)]
pub struct Run {
/// Specify the major sync strategy.
#[clap(long, value_parser = clap::value_parser!(SyncStrategy))]
#[clap(long, default_value = "headers-first")]
pub sync_strategy: SyncStrategy,

/// Specify the block verification level.
#[clap(long, value_parser = clap::value_parser!(BlockVerification), default_value = "full")]
#[clap(long, default_value = "full")]
pub block_verification: BlockVerification,

/// Do not run the finalizer which will finalize the blocks on confirmation depth.
Expand All @@ -33,7 +33,7 @@ impl Run {
pub fn subcoin_network_params(&self, network: bitcoin::Network) -> subcoin_network::Params {
subcoin_network::Params {
network,
listen_on: self.network_params.listen.clone(),
listen_on: self.network_params.listen,
bootnodes: self.network_params.bootnode.clone(),
bootnode_only: self.network_params.bootnode_only,
ipv4_only: self.network_params.ipv4_only,
Expand Down
8 changes: 0 additions & 8 deletions crates/subcoin-node/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,6 @@ mod transaction_pool;

pub use self::cli::run;

pub struct CoinStorageKey;

impl subcoin_primitives::CoinStorageKey for CoinStorageKey {
fn storage_key(&self, txid: bitcoin::Txid, vout: u32) -> Vec<u8> {
pallet_bitcoin::coin_storage_key::<subcoin_runtime::Runtime>(txid, vout)
}
}

#[cfg(test)]
mod tests {
use sc_cli::Database;
Expand Down
2 changes: 1 addition & 1 deletion crates/subcoin-service/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ pub async fn finalize_confirmed_blocks<Block, Client, Backend>(
Client: HeaderBackend<Block> + Finalizer<Block, Backend> + BlockchainEvents<Block> + 'static,
Backend: sc_client_api::backend::Backend<Block> + 'static,
{
const MAJOR_SYNC_FINALIZATION_STEP: u32 = 10;
const MAJOR_SYNC_FINALIZATION_STEP: u32 = 100;

let mut block_import_stream = client.import_notification_stream();

Expand Down

0 comments on commit 6e61e5f

Please sign in to comment.