diff --git a/src/blockchain/compact_filters/mod.rs b/src/blockchain/compact_filters/mod.rs index e528db62..f27137b1 100644 --- a/src/blockchain/compact_filters/mod.rs +++ b/src/blockchain/compact_filters/mod.rs @@ -24,7 +24,7 @@ //! Compact Filters //! -//! This module contains a multithreaded implementation of an [`OnlineBlockchain`] backend that +//! This module contains a multithreaded implementation of an [`Blockchain`] backend that //! uses BIP157 (aka "Neutrino") to populate the wallet's [database](crate::database::Database) //! by downloading compact filters from the P2P network. //! @@ -76,7 +76,7 @@ mod peer; mod store; mod sync; -use super::{Blockchain, Capability, OnlineBlockchain, Progress}; +use super::{Blockchain, Capability, Progress}; use crate::database::{BatchDatabase, BatchOperations, DatabaseUtils}; use crate::error::Error; use crate::types::{ScriptType, TransactionDetails, UTXO}; @@ -97,7 +97,11 @@ const PROCESS_BLOCKS_COST: f32 = 20_000.0; /// ## Example /// See the [`blockchain::compact_filters`](crate::blockchain::compact_filters) module for a usage example. #[derive(Debug)] -pub struct CompactFiltersBlockchain(Option); +pub struct CompactFiltersBlockchain { + peers: Vec>, + headers: Arc>, + skip_blocks: Option, +} impl CompactFiltersBlockchain { /// Construct a new instance given a list of peers, a path to store headers and block @@ -108,29 +112,6 @@ impl CompactFiltersBlockchain { /// in parallel. It's currently recommended to only connect to a single peer to avoid /// inconsistencies in the data returned, optionally with multiple connections in parallel to /// speed-up the sync process. - pub fn new>( - peers: Vec, - storage_dir: P, - skip_blocks: Option, - ) -> Result { - Ok(CompactFiltersBlockchain(Some(CompactFilters::new( - peers, - storage_dir, - skip_blocks, - )?))) - } -} - -/// Internal struct that contains the state of a [`CompactFiltersBlockchain`] -#[derive(Debug)] -struct CompactFilters { - peers: Vec>, - headers: Arc>, - skip_blocks: Option, -} - -impl CompactFilters { - /// Constructor, see [`CompactFiltersBlockchain::new`] for the documentation pub fn new>( peers: Vec, storage_dir: P, @@ -160,7 +141,7 @@ impl CompactFilters { headers.recover_snapshot(cf_name)?; } - Ok(CompactFilters { + Ok(CompactFiltersBlockchain { peers: peers.into_iter().map(Arc::new).collect(), headers, skip_blocks, @@ -250,16 +231,6 @@ impl CompactFilters { } impl Blockchain for CompactFiltersBlockchain { - fn offline() -> Self { - CompactFiltersBlockchain(None) - } - - fn is_online(&self) -> bool { - self.0.is_some() - } -} - -impl OnlineBlockchain for CompactFiltersBlockchain { fn get_capabilities(&self) -> HashSet { vec![Capability::FullHistory].into_iter().collect() } @@ -270,14 +241,13 @@ impl OnlineBlockchain for CompactFiltersBlockchain { database: &mut D, progress_update: P, ) -> Result<(), Error> { - let inner = self.0.as_ref().ok_or(Error::OfflineClient)?; - let first_peer = &inner.peers[0]; + let first_peer = &self.peers[0]; - let skip_blocks = inner.skip_blocks.unwrap_or(0); + let skip_blocks = self.skip_blocks.unwrap_or(0); - let cf_sync = Arc::new(CFSync::new(Arc::clone(&inner.headers), skip_blocks, 0x00)?); + let cf_sync = Arc::new(CFSync::new(Arc::clone(&self.headers), skip_blocks, 0x00)?); - let initial_height = inner.headers.get_height()?; + let initial_height = self.headers.get_height()?; let total_bundles = (first_peer.get_version().start_height as usize) .checked_sub(skip_blocks) .map(|x| x / 1000) @@ -297,7 +267,7 @@ impl OnlineBlockchain for CompactFiltersBlockchain { if let Some(snapshot) = sync::sync_headers( Arc::clone(&first_peer), - Arc::clone(&inner.headers), + Arc::clone(&self.headers), |new_height| { let local_headers_cost = new_height.checked_sub(initial_height).unwrap_or(0) as f32 * SYNC_HEADERS_COST; @@ -307,13 +277,13 @@ impl OnlineBlockchain for CompactFiltersBlockchain { ) }, )? { - if snapshot.work()? > inner.headers.work()? { + if snapshot.work()? > self.headers.work()? { info!("Applying snapshot with work: {}", snapshot.work()?); - inner.headers.apply_snapshot(snapshot)?; + self.headers.apply_snapshot(snapshot)?; } } - let synced_height = inner.headers.get_height()?; + let synced_height = self.headers.get_height()?; let buried_height = synced_height .checked_sub(sync::BURIED_CONFIRMATIONS) .unwrap_or(0); @@ -333,11 +303,11 @@ impl OnlineBlockchain for CompactFiltersBlockchain { let synced_bundles = Arc::new(AtomicUsize::new(0)); let progress_update = Arc::new(Mutex::new(progress_update)); - let mut threads = Vec::with_capacity(inner.peers.len()); - for peer in &inner.peers { + let mut threads = Vec::with_capacity(self.peers.len()); + for peer in &self.peers { let cf_sync = Arc::clone(&cf_sync); let peer = Arc::clone(&peer); - let headers = Arc::clone(&inner.headers); + let headers = Arc::clone(&self.headers); let all_scripts = Arc::clone(&all_scripts); let last_synced_block = Arc::clone(&last_synced_block); let progress_update = Arc::clone(&progress_update); @@ -420,9 +390,9 @@ impl OnlineBlockchain for CompactFiltersBlockchain { let mut internal_max_deriv = None; let mut external_max_deriv = None; - for (height, block) in inner.headers.iter_full_blocks()? { + for (height, block) in self.headers.iter_full_blocks()? { for tx in &block.txdata { - inner.process_tx( + self.process_tx( database, tx, Some(height as u32), @@ -433,7 +403,7 @@ impl OnlineBlockchain for CompactFiltersBlockchain { } } for tx in first_peer.get_mempool().iter_txs().iter() { - inner.process_tx( + self.process_tx( database, tx, None, @@ -458,7 +428,7 @@ impl OnlineBlockchain for CompactFiltersBlockchain { } info!("Dropping blocks until {}", buried_height); - inner.headers.delete_blocks_until(buried_height)?; + self.headers.delete_blocks_until(buried_height)?; progress_update .lock() @@ -469,24 +439,19 @@ impl OnlineBlockchain for CompactFiltersBlockchain { } fn get_tx(&self, txid: &Txid) -> Result, Error> { - let inner = self.0.as_ref().ok_or(Error::OfflineClient)?; - - Ok(inner.peers[0] + Ok(self.peers[0] .get_mempool() .get_tx(&Inventory::Transaction(*txid))) } fn broadcast(&self, tx: &Transaction) -> Result<(), Error> { - let inner = self.0.as_ref().ok_or(Error::OfflineClient)?; - inner.peers[0].broadcast_tx(tx.clone())?; + self.peers[0].broadcast_tx(tx.clone())?; Ok(()) } fn get_height(&self) -> Result { - let inner = self.0.as_ref().ok_or(Error::OfflineClient)?; - - Ok(inner.headers.get_height()? as u32) + Ok(self.headers.get_height()? as u32) } fn estimate_fee(&self, _target: usize) -> Result { diff --git a/src/blockchain/compact_filters/peer.rs b/src/blockchain/compact_filters/peer.rs index eb2cb220..cb111a56 100644 --- a/src/blockchain/compact_filters/peer.rs +++ b/src/blockchain/compact_filters/peer.rs @@ -63,7 +63,7 @@ impl Mempool { /// Add a transaction to the mempool /// /// Note that this doesn't propagate the transaction to other - /// peers. To do that, [`broadcast`](crate::blockchain::OnlineBlockchain::broadcast) should be used. + /// peers. To do that, [`broadcast`](crate::blockchain::Blockchain::broadcast) should be used. pub fn add_tx(&self, tx: Transaction) { self.txs.write().unwrap().insert(tx.txid(), tx); } diff --git a/src/blockchain/electrum.rs b/src/blockchain/electrum.rs index 0f877467..7d62e5be 100644 --- a/src/blockchain/electrum.rs +++ b/src/blockchain/electrum.rs @@ -24,7 +24,7 @@ //! Electrum //! -//! This module defines an [`OnlineBlockchain`] struct that wraps an [`electrum_client::Client`] +//! This module defines a [`Blockchain`] struct that wraps an [`electrum_client::Client`] //! and implements the logic required to populate the wallet's [database](crate::database::Database) by //! querying the inner client. //! @@ -56,7 +56,7 @@ use crate::FeeRate; /// /// ## Example /// See the [`blockchain::electrum`](crate::blockchain::electrum) module for a usage example. -pub struct ElectrumBlockchain(Option); +pub struct ElectrumBlockchain(Client); #[cfg(test)] #[cfg(feature = "test-electrum")] @@ -67,21 +67,11 @@ fn local_electrs() -> ElectrumBlockchain { impl std::convert::From for ElectrumBlockchain { fn from(client: Client) -> Self { - ElectrumBlockchain(Some(client)) + ElectrumBlockchain(client) } } impl Blockchain for ElectrumBlockchain { - fn offline() -> Self { - ElectrumBlockchain(None) - } - - fn is_online(&self) -> bool { - self.0.is_some() - } -} - -impl OnlineBlockchain for ElectrumBlockchain { fn get_capabilities(&self) -> HashSet { vec![ Capability::FullHistory, @@ -99,27 +89,15 @@ impl OnlineBlockchain for ElectrumBlockchain { progress_update: P, ) -> Result<(), Error> { self.0 - .as_ref() - .ok_or(Error::OfflineClient)? .electrum_like_setup(stop_gap, database, progress_update) } fn get_tx(&self, txid: &Txid) -> Result, Error> { - Ok(self - .0 - .as_ref() - .ok_or(Error::OfflineClient)? - .transaction_get(txid) - .map(Option::Some)?) + Ok(self.0.transaction_get(txid).map(Option::Some)?) } fn broadcast(&self, tx: &Transaction) -> Result<(), Error> { - Ok(self - .0 - .as_ref() - .ok_or(Error::OfflineClient)? - .transaction_broadcast(tx) - .map(|_| ())?) + Ok(self.0.transaction_broadcast(tx).map(|_| ())?) } fn get_height(&self) -> Result { @@ -127,18 +105,13 @@ impl OnlineBlockchain for ElectrumBlockchain { Ok(self .0 - .as_ref() - .ok_or(Error::OfflineClient)? .block_headers_subscribe() .map(|data| data.height as u32)?) } fn estimate_fee(&self, target: usize) -> Result { Ok(FeeRate::from_btc_per_kvb( - self.0 - .as_ref() - .ok_or(Error::OfflineClient)? - .estimate_fee(target)? as f32, + self.0.estimate_fee(target)? as f32 )) } } diff --git a/src/blockchain/esplora.rs b/src/blockchain/esplora.rs index 7eaf4b57..214852ef 100644 --- a/src/blockchain/esplora.rs +++ b/src/blockchain/esplora.rs @@ -24,7 +24,7 @@ //! Esplora //! -//! This module defines an [`OnlineBlockchain`] struct that can query an Esplora backend +//! This module defines a [`Blockchain`] struct that can query an Esplora backend //! populate the wallet's [database](crate::database::Database) by //! //! ## Example @@ -71,36 +71,26 @@ struct UrlClient { /// ## Example /// See the [`blockchain::esplora`](crate::blockchain::esplora) module for a usage example. #[derive(Debug)] -pub struct EsploraBlockchain(Option); +pub struct EsploraBlockchain(UrlClient); impl std::convert::From for EsploraBlockchain { fn from(url_client: UrlClient) -> Self { - EsploraBlockchain(Some(url_client)) + EsploraBlockchain(url_client) } } impl EsploraBlockchain { /// Create a new instance of the client from a base URL pub fn new(base_url: &str) -> Self { - EsploraBlockchain(Some(UrlClient { + EsploraBlockchain(UrlClient { url: base_url.to_string(), client: Client::new(), - })) - } -} - -impl Blockchain for EsploraBlockchain { - fn offline() -> Self { - EsploraBlockchain(None) - } - - fn is_online(&self) -> bool { - self.0.is_some() + }) } } #[maybe_async] -impl OnlineBlockchain for EsploraBlockchain { +impl Blockchain for EsploraBlockchain { fn get_capabilities(&self) -> HashSet { vec![ Capability::FullHistory, @@ -119,41 +109,23 @@ impl OnlineBlockchain for EsploraBlockchain { ) -> Result<(), Error> { maybe_await!(self .0 - .as_ref() - .ok_or(Error::OfflineClient)? .electrum_like_setup(stop_gap, database, progress_update)) } fn get_tx(&self, txid: &Txid) -> Result, Error> { - Ok(await_or_block!(self - .0 - .as_ref() - .ok_or(Error::OfflineClient)? - ._get_tx(txid))?) + Ok(await_or_block!(self.0._get_tx(txid))?) } fn broadcast(&self, tx: &Transaction) -> Result<(), Error> { - Ok(await_or_block!(self - .0 - .as_ref() - .ok_or(Error::OfflineClient)? - ._broadcast(tx))?) + Ok(await_or_block!(self.0._broadcast(tx))?) } fn get_height(&self) -> Result { - Ok(await_or_block!(self - .0 - .as_ref() - .ok_or(Error::OfflineClient)? - ._get_height())?) + Ok(await_or_block!(self.0._get_height())?) } fn estimate_fee(&self, target: usize) -> Result { - let estimates = await_or_block!(self - .0 - .as_ref() - .ok_or(Error::OfflineClient)? - ._get_fee_estimates())?; + let estimates = await_or_block!(self.0._get_fee_estimates())?; let fee_val = estimates .into_iter() diff --git a/src/blockchain/mod.rs b/src/blockchain/mod.rs index dd78bfa6..8fcee951 100644 --- a/src/blockchain/mod.rs +++ b/src/blockchain/mod.rs @@ -26,17 +26,8 @@ //! //! This module provides the implementation of a few commonly-used backends like //! [Electrum](crate::blockchain::electrum), [Esplora](crate::blockchain::esplora) and -//! [Compact Filters/Neutrino](crate::blockchain::compact_filters), along with two generalized -//! traits [`Blockchain`] and [`OnlineBlockchain`] that can be implemented to build customized -//! backends. -//! -//! Types that only implement the [`Blockchain`] trait can be used as backends for [`Wallet`](crate::wallet::Wallet)s, but any -//! action that requires interacting with the blockchain won't be available ([`Wallet::sync`](crate::wallet::Wallet::sync) and -//! [`Wallet::broadcast`](crate::wallet::Wallet::broadcast)). This allows the creation of physically air-gapped wallets, that have no -//! ability to contact the outside world. An example of an offline-only client is [`OfflineBlockchain`]. -//! -//! Types that also implement [`OnlineBlockchain`] will make the two aforementioned actions -//! available. +//! [Compact Filters/Neutrino](crate::blockchain::compact_filters), along with a generalized trait +//! [`Blockchain`] that can be implemented to build customized backends. use std::collections::HashSet; use std::ops::Deref; @@ -69,7 +60,7 @@ pub mod compact_filters; #[cfg(feature = "compact_filters")] pub use self::compact_filters::CompactFiltersBlockchain; -/// Capabilities that can be supported by an [`OnlineBlockchain`] backend +/// Capabilities that can be supported by a [`Blockchain`] backend #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum Capability { /// Can recover the full history of a wallet and not only the set of currently spendable UTXOs @@ -80,56 +71,42 @@ pub enum Capability { AccurateFees, } -/// Base trait for a blockchain backend +/// Marker trait for a blockchain backend /// -/// This trait is always required, even for "air-gapped" backends that don't actually make any -/// external call. Clients that have the ability to make external calls must also implement `OnlineBlockchain`. -pub trait Blockchain { - /// Return whether or not the client has the ability to fullfill requests - /// - /// This should always be `false` for offline-only types, and can be true for types that also - /// implement [`OnlineBlockchain`], if they have the ability to fullfill requests. - fn is_online(&self) -> bool; +/// This is a marker trait for blockchain types. It is automatically implemented for types that +/// implement [`Blockchain`], so as a user of the library you won't have to implement this +/// manually. +/// +/// Users of the library will probably never have to implement this trait manually, but they +/// could still need to import it to define types and structs with generics; +/// Implementing only the marker trait is pointless, since [`OfflineBlockchain`] +/// already does that, and whenever [`Blockchain`] is implemented, the marker trait is also +/// automatically implemented by the library. +pub trait BlockchainMarker {} - /// Create a new instance of the client that is offline-only - /// - /// For types that also implement [`OnlineBlockchain`], this means creating an instance that - /// returns [`Error::OfflineClient`](crate::error::Error::OfflineClient) if any of the "online" - /// methods are called. - /// - /// This is generally implemented by wrapping the client in an [`Option`] that has [`Option::None`] value - /// when created with this method, and is [`Option::Some`] if properly instantiated. - fn offline() -> Self; -} +/// The [`BlockchainMarker`] marker trait is automatically implemented for [`Blockchain`] types +impl BlockchainMarker for T {} -/// Type that only implements [`Blockchain`] and is always offline +/// Type that only implements [`Blockchain`] and is always "offline" pub struct OfflineBlockchain; -impl Blockchain for OfflineBlockchain { - fn offline() -> Self { - OfflineBlockchain - } +impl BlockchainMarker for OfflineBlockchain {} - fn is_online(&self) -> bool { - false - } -} - -/// Trait that defines the actions that must be supported by an online [`Blockchain`] +/// Trait that defines the actions that must be supported by a blockchain backend #[maybe_async] -pub trait OnlineBlockchain: Blockchain { +pub trait Blockchain: BlockchainMarker { /// Return the set of [`Capability`] supported by this backend fn get_capabilities(&self) -> HashSet; /// Setup the backend and populate the internal database for the first time /// - /// This method is the equivalent of [`OnlineBlockchain::sync`], but it's guaranteed to only be + /// This method is the equivalent of [`Blockchain::sync`], but it's guaranteed to only be /// called once, at the first [`Wallet::sync`](crate::wallet::Wallet::sync). /// /// The rationale behind the distinction between `sync` and `setup` is that some custom backends /// might need to perform specific actions only the first time they are synced. /// /// For types that do not have that distinction, only this method can be implemented, since - /// [`OnlineBlockchain::sync`] defaults to calling this internally if not overridden. + /// [`Blockchain::sync`] defaults to calling this internally if not overridden. fn setup( &self, stop_gap: Option, @@ -138,7 +115,7 @@ pub trait OnlineBlockchain: Blockchain { ) -> Result<(), Error>; /// Populate the internal database with transactions and UTXOs /// - /// If not overridden, it defaults to calling [`OnlineBlockchain::setup`] internally. + /// If not overridden, it defaults to calling [`Blockchain::setup`] internally. /// /// This method should implement the logic required to iterate over the list of the wallet's /// script_pubkeys using [`Database::iter_script_pubkeys`] and look for relevant transactions @@ -178,8 +155,8 @@ pub trait OnlineBlockchain: Blockchain { /// Data sent with a progress update over a [`channel`] pub type ProgressData = (f32, Option); -/// Trait for types that can receive and process progress updates during [`OnlineBlockchain::sync`] and -/// [`OnlineBlockchain::setup`] +/// Trait for types that can receive and process progress updates during [`Blockchain::sync`] and +/// [`Blockchain::setup`] pub trait Progress: Send { /// Send a new progress update /// @@ -236,18 +213,8 @@ impl Progress for LogProgress { } } -impl Blockchain for Arc { - fn is_online(&self) -> bool { - self.deref().is_online() - } - - fn offline() -> Self { - Arc::new(T::offline()) - } -} - #[maybe_async] -impl OnlineBlockchain for Arc { +impl Blockchain for Arc { fn get_capabilities(&self) -> HashSet { maybe_await!(self.deref().get_capabilities()) } diff --git a/src/cli.rs b/src/cli.rs index e09fedd4..bf50d961 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -363,7 +363,7 @@ pub fn handle_matches( matches: ArgMatches<'_>, ) -> Result where - C: crate::blockchain::OnlineBlockchain, + C: crate::blockchain::Blockchain, D: crate::database::BatchDatabase, { if let Some(_sub_matches) = matches.subcommand_matches("get_new_address") { diff --git a/src/wallet/export.rs b/src/wallet/export.rs index 2df89bbe..42d94f30 100644 --- a/src/wallet/export.rs +++ b/src/wallet/export.rs @@ -73,7 +73,7 @@ use serde::{Deserialize, Serialize}; use miniscript::{Descriptor, ScriptContext, Terminal}; -use crate::blockchain::Blockchain; +use crate::blockchain::BlockchainMarker; use crate::database::BatchDatabase; use crate::wallet::Wallet; @@ -115,7 +115,7 @@ impl WalletExport { /// /// If the database is empty or `include_blockheight` is false, the `blockheight` field /// returned will be `0`. - pub fn export_wallet( + pub fn export_wallet( wallet: &Wallet, label: &str, include_blockheight: bool, diff --git a/src/wallet/mod.rs b/src/wallet/mod.rs index 48f5599f..d0a7ed62 100644 --- a/src/wallet/mod.rs +++ b/src/wallet/mod.rs @@ -58,7 +58,7 @@ use signer::{Signer, SignerId, SignerOrdering, SignersContainer}; use tx_builder::TxBuilder; use utils::{After, Older}; -use crate::blockchain::{Blockchain, OfflineBlockchain, OnlineBlockchain, Progress}; +use crate::blockchain::{Blockchain, BlockchainMarker, OfflineBlockchain, Progress}; use crate::database::{BatchDatabase, BatchOperations, DatabaseUtils}; use crate::descriptor::{ get_checksum, DescriptorMeta, DescriptorScripts, ExtendedDescriptor, ExtractPolicy, Policy, @@ -80,9 +80,9 @@ pub type OfflineWallet = Wallet; /// [creating transactions](Wallet::create_tx), etc. /// /// A wallet can be either "online" if the [`blockchain`](crate::blockchain) type provided -/// implements [`OnlineBlockchain`], or "offline" if it doesn't. Offline wallets only expose +/// implements [`Blockchain`], or "offline" [`OfflineBlockchain`] is used. Offline wallets only expose /// methods that don't need any interaction with the blockchain to work. -pub struct Wallet { +pub struct Wallet { descriptor: ExtendedDescriptor, change_descriptor: Option, @@ -95,14 +95,14 @@ pub struct Wallet { current_height: Option, - client: B, + client: Option, database: RefCell, } // offline actions, always available impl Wallet where - B: Blockchain, + B: BlockchainMarker, D: BatchDatabase, { /// Create a new "offline" wallet @@ -147,7 +147,7 @@ where current_height: None, - client: B::offline(), + client: None, database: RefCell::new(database), }) } @@ -1076,7 +1076,7 @@ where impl Wallet where - B: OnlineBlockchain, + B: Blockchain, D: BatchDatabase, { /// Create a new "online" wallet @@ -1091,7 +1091,7 @@ where let mut wallet = Self::new_offline(descriptor, change_descriptor, network, database)?; wallet.current_height = Some(maybe_await!(client.get_height())? as u32); - wallet.client = client; + wallet.client = Some(client); Ok(wallet) } @@ -1144,13 +1144,13 @@ where // TODO: what if i generate an address first and cache some addresses? // TODO: we should sync if generating an address triggers a new batch to be stored if run_setup { - maybe_await!(self.client.setup( + maybe_await!(self.client.as_ref().ok_or(Error::OfflineClient)?.setup( None, self.database.borrow_mut().deref_mut(), progress_update, )) } else { - maybe_await!(self.client.sync( + maybe_await!(self.client.as_ref().ok_or(Error::OfflineClient)?.sync( None, self.database.borrow_mut().deref_mut(), progress_update, @@ -1159,14 +1159,18 @@ where } /// Return a reference to the internal blockchain client - pub fn client(&self) -> &B { - &self.client + pub fn client(&self) -> Option<&B> { + self.client.as_ref() } /// Broadcast a transaction to the network #[maybe_async] pub fn broadcast(&self, tx: Transaction) -> Result { - maybe_await!(self.client.broadcast(&tx))?; + maybe_await!(self + .client + .as_ref() + .ok_or(Error::OfflineClient)? + .broadcast(&tx))?; Ok(tx.txid()) } diff --git a/testutils-macros/src/lib.rs b/testutils-macros/src/lib.rs index cf8fe424..25622d13 100644 --- a/testutils-macros/src/lib.rs +++ b/testutils-macros/src/lib.rs @@ -63,7 +63,7 @@ pub fn magical_blockchain_tests(attr: TokenStream, item: TokenStream) -> TokenSt ReturnType::Type(_, ref t) => t.clone(), ReturnType::Default => { return (quote! { - compile_error!("The tagged function must return a type that impl `OnlineBlockchain`") + compile_error!("The tagged function must return a type that impl `Blockchain`") }).into(); } }; @@ -79,7 +79,7 @@ pub fn magical_blockchain_tests(attr: TokenStream, item: TokenStream) -> TokenSt use testutils::{TestClient, serial}; - use #root_ident::blockchain::{OnlineBlockchain, noop_progress}; + use #root_ident::blockchain::{Blockchain, noop_progress}; use #root_ident::descriptor::ExtendedDescriptor; use #root_ident::database::MemoryDatabase; use #root_ident::types::ScriptType;