Merge commit 'refs/pull/375/head' of github.com:bitcoindevkit/bdk
This commit is contained in:
commit
bab9d99a00
41
.github/workflows/cont_integration.yml
vendored
41
.github/workflows/cont_integration.yml
vendored
@ -77,28 +77,14 @@ jobs:
|
|||||||
|
|
||||||
test-blockchains:
|
test-blockchains:
|
||||||
name: Test ${{ matrix.blockchain.name }}
|
name: Test ${{ matrix.blockchain.name }}
|
||||||
runs-on: ubuntu-16.04
|
runs-on: ubuntu-20.04
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
blockchain:
|
blockchain:
|
||||||
- name: electrum
|
- name: electrum
|
||||||
container: bitcoindevkit/electrs:0.4.0
|
|
||||||
start: /root/electrs --network regtest --cookie-file $GITHUB_WORKSPACE/.bitcoin/regtest/.cookie --jsonrpc-import
|
|
||||||
- name: esplora
|
|
||||||
container: bitcoindevkit/esplora:0.4.0
|
|
||||||
start: /root/electrs --network regtest -vvv --daemon-dir $GITHUB_WORKSPACE/.bitcoin --jsonrpc-import --electrum-rpc-addr=0.0.0.0:60401 --http-addr 0.0.0.0:3002
|
|
||||||
- name: rpc
|
- name: rpc
|
||||||
container: bitcoindevkit/electrs:0.4.0
|
- name: esplora
|
||||||
start: /root/electrs --network regtest --cookie-file $GITHUB_WORKSPACE/.bitcoin/regtest/.cookie --jsonrpc-import
|
|
||||||
container: ${{ matrix.blockchain.container }}
|
|
||||||
env:
|
|
||||||
BDK_RPC_AUTH: COOKIEFILE
|
|
||||||
BDK_RPC_COOKIEFILE: ${{ github.workspace }}/.bitcoin/regtest/.cookie
|
|
||||||
BDK_RPC_URL: 127.0.0.1:18443
|
|
||||||
BDK_RPC_WALLET: bdk-test
|
|
||||||
BDK_ELECTRUM_URL: tcp://127.0.0.1:60401
|
|
||||||
BDK_ESPLORA_URL: http://127.0.0.1:3002
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
@ -107,25 +93,18 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.cargo/registry
|
~/.cargo/registry
|
||||||
|
~/.cargo/bitcoin
|
||||||
|
~/.cargo/electrs
|
||||||
~/.cargo/git
|
~/.cargo/git
|
||||||
target
|
target
|
||||||
key: ${{ runner.os }}-cargo-${{ github.job }}-${{ hashFiles('**/Cargo.toml','**/Cargo.lock') }}
|
key: ${{ runner.os }}-cargo-${{ github.job }}-${{ hashFiles('**/Cargo.toml','**/Cargo.lock') }}
|
||||||
- name: get pkg-config # running esplora tests seems to need this
|
- name: Setup rust toolchain
|
||||||
run: apt update && apt install -y --fix-missing pkg-config libssl-dev
|
uses: actions-rs/toolchain@v1
|
||||||
- name: Install rustup
|
with:
|
||||||
run: curl https://sh.rustup.rs -sSf | sh -s -- -y
|
toolchain: stable
|
||||||
- name: Set default toolchain
|
override: true
|
||||||
run: $HOME/.cargo/bin/rustup default 1.53.0 # STABLE
|
|
||||||
- name: Set profile
|
|
||||||
run: $HOME/.cargo/bin/rustup set profile minimal
|
|
||||||
- name: Update toolchain
|
|
||||||
run: $HOME/.cargo/bin/rustup update
|
|
||||||
- name: Start core
|
|
||||||
run: ./ci/start-core.sh
|
|
||||||
- name: start ${{ matrix.blockchain.name }}
|
|
||||||
run: nohup ${{ matrix.blockchain.start }} & sleep 5
|
|
||||||
- name: Test
|
- name: Test
|
||||||
run: $HOME/.cargo/bin/cargo test --features test-${{ matrix.blockchain.name }},test-blockchains --no-default-features ${{ matrix.blockchain.name }}::bdk_blockchain_tests
|
run: cargo test --features test-${{ matrix.blockchain.name }} ${{ matrix.blockchain.name }}::bdk_blockchain_tests
|
||||||
|
|
||||||
check-wasm:
|
check-wasm:
|
||||||
name: Check WASM
|
name: Check WASM
|
||||||
|
10
Cargo.toml
10
Cargo.toml
@ -35,7 +35,6 @@ bitcoinconsensus = { version = "0.19.0-3", optional = true }
|
|||||||
|
|
||||||
# Needed by bdk_blockchain_tests macro
|
# Needed by bdk_blockchain_tests macro
|
||||||
bitcoincore-rpc = { version = "0.13", optional = true }
|
bitcoincore-rpc = { version = "0.13", optional = true }
|
||||||
serial_test = { version = "0.4", optional = true }
|
|
||||||
|
|
||||||
# Platform-specific dependencies
|
# Platform-specific dependencies
|
||||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||||
@ -63,17 +62,16 @@ rpc = ["bitcoincore-rpc"]
|
|||||||
|
|
||||||
# Debug/Test features
|
# Debug/Test features
|
||||||
test-blockchains = ["bitcoincore-rpc", "electrum-client"]
|
test-blockchains = ["bitcoincore-rpc", "electrum-client"]
|
||||||
test-electrum = ["electrum"]
|
test-electrum = ["electrum", "electrsd/electrs_0_8_10", "test-blockchains"]
|
||||||
test-rpc = ["rpc"]
|
test-rpc = ["rpc", "electrsd/electrs_0_8_10", "test-blockchains"]
|
||||||
test-esplora = ["esplora"]
|
test-esplora = ["esplora", "electrsd/legacy", "electrsd/esplora_a33e97e1", "test-blockchains"]
|
||||||
test-md-docs = ["electrum"]
|
test-md-docs = ["electrum"]
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
lazy_static = "1.4"
|
lazy_static = "1.4"
|
||||||
env_logger = "0.7"
|
env_logger = "0.7"
|
||||||
clap = "2.33"
|
clap = "2.33"
|
||||||
serial_test = "0.4"
|
electrsd = { version= "0.6", features = ["trigger", "bitcoind_0_21_1"] }
|
||||||
bitcoind = "0.10.0"
|
|
||||||
|
|
||||||
[[example]]
|
[[example]]
|
||||||
name = "address_validator"
|
name = "address_validator"
|
||||||
|
19
README.md
19
README.md
@ -151,6 +151,25 @@ fn main() -> Result<(), bdk::Error> {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
### Unit testing
|
||||||
|
|
||||||
|
```
|
||||||
|
cargo test
|
||||||
|
```
|
||||||
|
|
||||||
|
### Integration testing
|
||||||
|
|
||||||
|
Integration testing require testing features, for example:
|
||||||
|
|
||||||
|
```
|
||||||
|
cargo test --features test-electrum
|
||||||
|
```
|
||||||
|
|
||||||
|
The other options are `test-esplora` or `test-rpc`.
|
||||||
|
Note that `electrs` and `bitcoind` binaries are automatically downloaded (on mac and linux), to specify you already have installed binaries you must use `--no-default-features` and provide `BITCOIND_EXE` and `ELECTRS_EXE` as environment variables.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
Licensed under either of
|
Licensed under either of
|
||||||
|
@ -1,71 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
usage() {
|
|
||||||
cat <<'EOF'
|
|
||||||
Script for running the bdk blockchain tests for a specific blockchain by starting up the backend in docker.
|
|
||||||
|
|
||||||
Usage: ./run_blockchain_tests.sh [esplora|electrum|rpc] [test name].
|
|
||||||
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
eprintln(){
|
|
||||||
echo "$@" >&2
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanup() {
|
|
||||||
if test "$id"; then
|
|
||||||
eprintln "cleaning up $blockchain docker container $id";
|
|
||||||
docker rm -fv "$id" > /dev/null;
|
|
||||||
rm /tmp/regtest-"$id".cookie;
|
|
||||||
fi
|
|
||||||
trap - EXIT INT
|
|
||||||
}
|
|
||||||
|
|
||||||
# Makes sure we clean up the container at the end or if ^C
|
|
||||||
trap 'rc=$?; cleanup; exit $rc' EXIT INT
|
|
||||||
|
|
||||||
blockchain="$1"
|
|
||||||
test_name="$2"
|
|
||||||
|
|
||||||
case "$blockchain" in
|
|
||||||
electrum)
|
|
||||||
eprintln "starting electrs docker container"
|
|
||||||
id="$(docker run --detach -p 127.0.0.1:18443-18444:18443-18444/tcp -p 127.0.0.1:60401:60401/tcp bitcoindevkit/electrs:0.4.0)"
|
|
||||||
;;
|
|
||||||
esplora)
|
|
||||||
eprintln "starting esplora docker container"
|
|
||||||
id="$(docker run --detach -p 127.0.0.1:18443-18444:18443-18444/tcp -p 127.0.0.1:60401:60401/tcp -p 127.0.0.1:3002:3002/tcp bitcoindevkit/esplora:0.4.0)"
|
|
||||||
export BDK_ESPLORA_URL=http://127.0.0.1:3002
|
|
||||||
;;
|
|
||||||
rpc)
|
|
||||||
eprintln "starting bitcoind docker container (via electrs container)"
|
|
||||||
id="$(docker run --detach -p 127.0.0.1:18443-18444:18443-18444/tcp -p 127.0.0.1:60401:60401/tcp bitcoindevkit/electrs:0.4.0)"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
usage;
|
|
||||||
exit 1;
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# taken from https://github.com/bitcoindevkit/bitcoin-regtest-box
|
|
||||||
export BDK_RPC_AUTH=COOKIEFILE
|
|
||||||
export BDK_RPC_COOKIEFILE=/tmp/regtest-"$id".cookie
|
|
||||||
export BDK_RPC_URL=127.0.0.1:18443
|
|
||||||
export BDK_RPC_WALLET=bdk-test
|
|
||||||
export BDK_ELECTRUM_URL=tcp://127.0.0.1:60401
|
|
||||||
|
|
||||||
cli(){
|
|
||||||
docker exec -it "$id" /root/bitcoin-cli -regtest -datadir=/root/.bitcoin $@
|
|
||||||
}
|
|
||||||
|
|
||||||
#eprintln "running getwalletinfo until bitcoind seems to be alive"
|
|
||||||
while ! cli getwalletinfo >/dev/null; do sleep 1; done
|
|
||||||
|
|
||||||
# sleep again for good measure!
|
|
||||||
sleep 1;
|
|
||||||
|
|
||||||
# copy bitcoind cookie file to /tmp
|
|
||||||
docker cp "$id":/root/.bitcoin/regtest/.cookie /tmp/regtest-"$id".cookie
|
|
||||||
|
|
||||||
cargo test --features "test-blockchains,test-$blockchain" --no-default-features "$blockchain::bdk_blockchain_tests::$test_name"
|
|
@ -169,9 +169,10 @@ impl ConfigurableBlockchain for ElectrumBlockchain {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "test-blockchains")]
|
#[cfg(test)]
|
||||||
|
#[cfg(feature = "test-electrum")]
|
||||||
crate::bdk_blockchain_tests! {
|
crate::bdk_blockchain_tests! {
|
||||||
fn test_instance() -> ElectrumBlockchain {
|
fn test_instance(test_client: &TestClient) -> ElectrumBlockchain {
|
||||||
ElectrumBlockchain::from(Client::new(&testutils::blockchain_tests::get_electrum_url()).unwrap())
|
ElectrumBlockchain::from(Client::new(&test_client.electrsd.electrum_url).unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -415,9 +415,10 @@ impl_error!(std::num::ParseIntError, Parsing, EsploraError);
|
|||||||
impl_error!(consensus::encode::Error, BitcoinEncoding, EsploraError);
|
impl_error!(consensus::encode::Error, BitcoinEncoding, EsploraError);
|
||||||
impl_error!(bitcoin::hashes::hex::Error, Hex, EsploraError);
|
impl_error!(bitcoin::hashes::hex::Error, Hex, EsploraError);
|
||||||
|
|
||||||
#[cfg(feature = "test-blockchains")]
|
#[cfg(test)]
|
||||||
|
#[cfg(feature = "test-esplora")]
|
||||||
crate::bdk_blockchain_tests! {
|
crate::bdk_blockchain_tests! {
|
||||||
fn test_instance() -> EsploraBlockchain {
|
fn test_instance(test_client: &TestClient) -> EsploraBlockchain {
|
||||||
EsploraBlockchain::new(std::env::var("BDK_ESPLORA_URL").unwrap_or("127.0.0.1:3002".into()).as_str(), None)
|
EsploraBlockchain::new(&format!("http://{}",test_client.electrsd.esplora_url.as_ref().unwrap()), None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -422,27 +422,14 @@ fn list_wallet_dir(client: &Client) -> Result<Vec<String>, Error> {
|
|||||||
Ok(result.wallets.into_iter().map(|n| n.name).collect())
|
Ok(result.wallets.into_iter().map(|n| n.name).collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "test-blockchains")]
|
#[cfg(test)]
|
||||||
|
#[cfg(feature = "test-rpc")]
|
||||||
crate::bdk_blockchain_tests! {
|
crate::bdk_blockchain_tests! {
|
||||||
|
|
||||||
fn test_instance() -> RpcBlockchain {
|
fn test_instance(test_client: &TestClient) -> RpcBlockchain {
|
||||||
let url = std::env::var("BDK_RPC_URL").unwrap_or_else(|_| "127.0.0.1:18443".to_string());
|
|
||||||
let url = format!("http://{}", url);
|
|
||||||
|
|
||||||
// TODO same code in `fn get_auth` in testutils, make it public there
|
|
||||||
let auth = match std::env::var("BDK_RPC_AUTH").as_ref().map(String::as_ref) {
|
|
||||||
Ok("USER_PASS") => Auth::UserPass(
|
|
||||||
std::env::var("BDK_RPC_USER").unwrap(),
|
|
||||||
std::env::var("BDK_RPC_PASS").unwrap(),
|
|
||||||
),
|
|
||||||
_ => Auth::CookieFile(std::path::PathBuf::from(
|
|
||||||
std::env::var("BDK_RPC_COOKIEFILE")
|
|
||||||
.unwrap_or_else(|_| "/home/user/.bitcoin/regtest/.cookie".to_string()),
|
|
||||||
)),
|
|
||||||
};
|
|
||||||
let config = RpcConfig {
|
let config = RpcConfig {
|
||||||
url,
|
url: test_client.bitcoind.rpc_url(),
|
||||||
auth,
|
auth: Auth::CookieFile(test_client.bitcoind.params.cookie_file.clone()),
|
||||||
network: Network::Regtest,
|
network: Network::Regtest,
|
||||||
wallet_name: format!("client-wallet-test-{:?}", std::time::SystemTime::now() ),
|
wallet_name: format!("client-wallet-test-{:?}", std::time::SystemTime::now() ),
|
||||||
skip_blocks: None,
|
skip_blocks: None,
|
||||||
@ -450,227 +437,3 @@ crate::bdk_blockchain_tests! {
|
|||||||
RpcBlockchain::from_config(&config).unwrap()
|
RpcBlockchain::from_config(&config).unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "test-rpc")]
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
use super::{RpcBlockchain, RpcConfig};
|
|
||||||
use crate::bitcoin::consensus::deserialize;
|
|
||||||
use crate::bitcoin::{Address, Amount, Network, Transaction};
|
|
||||||
use crate::blockchain::rpc::wallet_name_from_descriptor;
|
|
||||||
use crate::blockchain::{noop_progress, Blockchain, Capability, ConfigurableBlockchain};
|
|
||||||
use crate::database::MemoryDatabase;
|
|
||||||
use crate::wallet::AddressIndex;
|
|
||||||
use crate::Wallet;
|
|
||||||
use bitcoin::secp256k1::Secp256k1;
|
|
||||||
use bitcoin::Txid;
|
|
||||||
use bitcoincore_rpc::json::CreateRawTransactionInput;
|
|
||||||
use bitcoincore_rpc::RawTx;
|
|
||||||
use bitcoincore_rpc::{Auth, RpcApi};
|
|
||||||
use bitcoind::BitcoinD;
|
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
fn create_rpc(
|
|
||||||
bitcoind: &BitcoinD,
|
|
||||||
desc: &str,
|
|
||||||
network: Network,
|
|
||||||
) -> Result<RpcBlockchain, crate::Error> {
|
|
||||||
let secp = Secp256k1::new();
|
|
||||||
let wallet_name = wallet_name_from_descriptor(desc, None, network, &secp).unwrap();
|
|
||||||
|
|
||||||
let config = RpcConfig {
|
|
||||||
url: bitcoind.rpc_url(),
|
|
||||||
auth: Auth::CookieFile(bitcoind.config.cookie_file.clone()),
|
|
||||||
network,
|
|
||||||
wallet_name,
|
|
||||||
skip_blocks: None,
|
|
||||||
};
|
|
||||||
RpcBlockchain::from_config(&config)
|
|
||||||
}
|
|
||||||
fn create_bitcoind(args: Vec<String>) -> BitcoinD {
|
|
||||||
let exe = std::env::var("BITCOIND_EXE").unwrap();
|
|
||||||
bitcoind::BitcoinD::with_args(exe, args, false, bitcoind::P2P::No).unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
const DESCRIPTOR_PUB: &'static str = "wpkh(tpubD6NzVbkrYhZ4X2yy78HWrr1M9NT8dKeWfzNiQqDdMqqa9UmmGztGGz6TaLFGsLfdft5iu32gxq1T4eMNxExNNWzVCpf9Y6JZi5TnqoC9wJq/*)";
|
|
||||||
const DESCRIPTOR_PRIV: &'static str = "wpkh(tprv8ZgxMBicQKsPdZxBDUcvTSMEaLwCTzTc6gmw8KBKwa3BJzWzec4g6VUbQBHJcutDH6mMEmBeVyN27H1NF3Nu8isZ1Sts4SufWyfLE6Mf1MB/*)";
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_rpc_wallet_setup() {
|
|
||||||
env_logger::try_init().unwrap();
|
|
||||||
let bitcoind = create_bitcoind(vec![]);
|
|
||||||
let node_address = bitcoind.client.get_new_address(None, None).unwrap();
|
|
||||||
let blockchain = create_rpc(&bitcoind, DESCRIPTOR_PUB, Network::Regtest).unwrap();
|
|
||||||
let db = MemoryDatabase::new();
|
|
||||||
let wallet = Wallet::new(DESCRIPTOR_PRIV, None, Network::Regtest, db, blockchain).unwrap();
|
|
||||||
|
|
||||||
wallet.sync(noop_progress(), None).unwrap();
|
|
||||||
generate(&bitcoind, 101);
|
|
||||||
wallet.sync(noop_progress(), None).unwrap();
|
|
||||||
let address = wallet.get_address(AddressIndex::New).unwrap();
|
|
||||||
let expected_address = "bcrt1q8dyvgt4vhr8ald4xuwewcxhdjha9a5k78wxm5t";
|
|
||||||
assert_eq!(expected_address, address.to_string());
|
|
||||||
send_to_address(&bitcoind, &address, 100_000);
|
|
||||||
wallet.sync(noop_progress(), None).unwrap();
|
|
||||||
assert_eq!(wallet.get_balance().unwrap(), 100_000);
|
|
||||||
|
|
||||||
let mut builder = wallet.build_tx();
|
|
||||||
builder.add_recipient(node_address.script_pubkey(), 50_000);
|
|
||||||
let (mut psbt, details) = builder.finish().unwrap();
|
|
||||||
let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
|
|
||||||
assert!(finalized, "Cannot finalize transaction");
|
|
||||||
let tx = psbt.extract_tx();
|
|
||||||
wallet.broadcast(tx).unwrap();
|
|
||||||
wallet.sync(noop_progress(), None).unwrap();
|
|
||||||
assert_eq!(
|
|
||||||
wallet.get_balance().unwrap(),
|
|
||||||
100_000 - 50_000 - details.fee.unwrap_or(0)
|
|
||||||
);
|
|
||||||
drop(wallet);
|
|
||||||
|
|
||||||
// test skip_blocks
|
|
||||||
generate(&bitcoind, 5);
|
|
||||||
let config = RpcConfig {
|
|
||||||
url: bitcoind.rpc_url(),
|
|
||||||
auth: Auth::CookieFile(bitcoind.config.cookie_file.clone()),
|
|
||||||
network: Network::Regtest,
|
|
||||||
wallet_name: "another-name".to_string(),
|
|
||||||
skip_blocks: Some(103),
|
|
||||||
};
|
|
||||||
let blockchain_skip = RpcBlockchain::from_config(&config).unwrap();
|
|
||||||
let db = MemoryDatabase::new();
|
|
||||||
let wallet_skip =
|
|
||||||
Wallet::new(DESCRIPTOR_PRIV, None, Network::Regtest, db, blockchain_skip).unwrap();
|
|
||||||
wallet_skip.sync(noop_progress(), None).unwrap();
|
|
||||||
send_to_address(&bitcoind, &address, 100_000);
|
|
||||||
wallet_skip.sync(noop_progress(), None).unwrap();
|
|
||||||
assert_eq!(wallet_skip.get_balance().unwrap(), 100_000);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_rpc_from_config() {
|
|
||||||
let bitcoind = create_bitcoind(vec![]);
|
|
||||||
let blockchain = create_rpc(&bitcoind, DESCRIPTOR_PUB, Network::Regtest);
|
|
||||||
assert!(blockchain.is_ok());
|
|
||||||
let blockchain = create_rpc(&bitcoind, DESCRIPTOR_PUB, Network::Testnet);
|
|
||||||
assert!(blockchain.is_err(), "wrong network doesn't error");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_rpc_capabilities_get_tx() {
|
|
||||||
let bitcoind = create_bitcoind(vec![]);
|
|
||||||
let rpc = create_rpc(&bitcoind, DESCRIPTOR_PUB, Network::Regtest).unwrap();
|
|
||||||
let capabilities = rpc.get_capabilities();
|
|
||||||
assert!(capabilities.contains(&Capability::FullHistory) && capabilities.len() == 1);
|
|
||||||
let bitcoind_indexed = create_bitcoind(vec!["-txindex".to_string()]);
|
|
||||||
let rpc_indexed = create_rpc(&bitcoind_indexed, DESCRIPTOR_PUB, Network::Regtest).unwrap();
|
|
||||||
assert_eq!(rpc_indexed.get_capabilities().len(), 3);
|
|
||||||
let address = generate(&bitcoind_indexed, 101);
|
|
||||||
let txid = send_to_address(&bitcoind_indexed, &address, 100_000);
|
|
||||||
assert!(rpc_indexed.get_tx(&txid).unwrap().is_some());
|
|
||||||
assert!(rpc.get_tx(&txid).is_err());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_rpc_estimate_fee_get_height() {
|
|
||||||
let bitcoind = create_bitcoind(vec![]);
|
|
||||||
let rpc = create_rpc(&bitcoind, DESCRIPTOR_PUB, Network::Regtest).unwrap();
|
|
||||||
let result = rpc.estimate_fee(2);
|
|
||||||
assert!(result.is_err());
|
|
||||||
let address = generate(&bitcoind, 100);
|
|
||||||
// create enough tx so that core give some fee estimation
|
|
||||||
for _ in 0..15 {
|
|
||||||
let _ = bitcoind.client.generate_to_address(1, &address).unwrap();
|
|
||||||
for _ in 0..2 {
|
|
||||||
send_to_address(&bitcoind, &address, 100_000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let result = rpc.estimate_fee(2);
|
|
||||||
assert!(result.is_ok());
|
|
||||||
assert_eq!(rpc.get_height().unwrap(), 115);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_rpc_node_synced_height() {
|
|
||||||
let bitcoind = create_bitcoind(vec![]);
|
|
||||||
let rpc = create_rpc(&bitcoind, DESCRIPTOR_PUB, Network::Regtest).unwrap();
|
|
||||||
let synced_height = rpc.get_node_synced_height().unwrap();
|
|
||||||
|
|
||||||
assert_eq!(synced_height, 0);
|
|
||||||
rpc.set_node_synced_height(1).unwrap();
|
|
||||||
|
|
||||||
let synced_height = rpc.get_node_synced_height().unwrap();
|
|
||||||
assert_eq!(synced_height, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_rpc_broadcast() {
|
|
||||||
let bitcoind = create_bitcoind(vec![]);
|
|
||||||
let rpc = create_rpc(&bitcoind, DESCRIPTOR_PUB, Network::Regtest).unwrap();
|
|
||||||
let address = generate(&bitcoind, 101);
|
|
||||||
let utxo = bitcoind
|
|
||||||
.client
|
|
||||||
.list_unspent(None, None, None, None, None)
|
|
||||||
.unwrap();
|
|
||||||
let input = CreateRawTransactionInput {
|
|
||||||
txid: utxo[0].txid,
|
|
||||||
vout: utxo[0].vout,
|
|
||||||
sequence: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let out: HashMap<_, _> = vec![(
|
|
||||||
address.to_string(),
|
|
||||||
utxo[0].amount - Amount::from_sat(100_000),
|
|
||||||
)]
|
|
||||||
.into_iter()
|
|
||||||
.collect();
|
|
||||||
let tx = bitcoind
|
|
||||||
.client
|
|
||||||
.create_raw_transaction(&[input], &out, None, None)
|
|
||||||
.unwrap();
|
|
||||||
let signed_tx = bitcoind
|
|
||||||
.client
|
|
||||||
.sign_raw_transaction_with_wallet(tx.raw_hex(), None, None)
|
|
||||||
.unwrap();
|
|
||||||
let parsed_tx: Transaction = deserialize(&signed_tx.hex).unwrap();
|
|
||||||
rpc.broadcast(&parsed_tx).unwrap();
|
|
||||||
assert!(bitcoind
|
|
||||||
.client
|
|
||||||
.get_raw_mempool()
|
|
||||||
.unwrap()
|
|
||||||
.contains(&tx.txid()));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_rpc_wallet_name() {
|
|
||||||
let secp = Secp256k1::new();
|
|
||||||
let name =
|
|
||||||
wallet_name_from_descriptor(DESCRIPTOR_PUB, None, Network::Regtest, &secp).unwrap();
|
|
||||||
assert_eq!("tmg7aqay", name);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn generate(bitcoind: &BitcoinD, blocks: u64) -> Address {
|
|
||||||
let address = bitcoind.client.get_new_address(None, None).unwrap();
|
|
||||||
bitcoind
|
|
||||||
.client
|
|
||||||
.generate_to_address(blocks, &address)
|
|
||||||
.unwrap();
|
|
||||||
address
|
|
||||||
}
|
|
||||||
|
|
||||||
fn send_to_address(bitcoind: &BitcoinD, address: &Address, amount: u64) -> Txid {
|
|
||||||
bitcoind
|
|
||||||
.client
|
|
||||||
.send_to_address(
|
|
||||||
&address,
|
|
||||||
Amount::from_sat(amount),
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
.unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -383,6 +383,7 @@ impl BatchDatabase for Tree {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
|
use lazy_static::lazy_static;
|
||||||
use std::sync::{Arc, Condvar, Mutex, Once};
|
use std::sync::{Arc, Condvar, Mutex, Once};
|
||||||
use std::time::{SystemTime, UNIX_EPOCH};
|
use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
|
|
||||||
|
@ -235,12 +235,6 @@ pub extern crate reqwest;
|
|||||||
pub extern crate sled;
|
pub extern crate sled;
|
||||||
|
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
#[cfg(test)]
|
|
||||||
#[allow(unused_imports)]
|
|
||||||
#[cfg(test)]
|
|
||||||
#[macro_use]
|
|
||||||
pub extern crate serial_test;
|
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
pub(crate) mod error;
|
pub(crate) mod error;
|
||||||
pub mod blockchain;
|
pub mod blockchain;
|
||||||
|
@ -6,38 +6,49 @@ use bitcoin::{Address, Amount, Script, Transaction, Txid};
|
|||||||
pub use bitcoincore_rpc::bitcoincore_rpc_json::AddressType;
|
pub use bitcoincore_rpc::bitcoincore_rpc_json::AddressType;
|
||||||
pub use bitcoincore_rpc::{Auth, Client as RpcClient, RpcApi};
|
pub use bitcoincore_rpc::{Auth, Client as RpcClient, RpcApi};
|
||||||
use core::str::FromStr;
|
use core::str::FromStr;
|
||||||
|
use electrsd::bitcoind::BitcoinD;
|
||||||
|
use electrsd::{bitcoind, ElectrsD};
|
||||||
pub use electrum_client::{Client as ElectrumClient, ElectrumApi};
|
pub use electrum_client::{Client as ElectrumClient, ElectrumApi};
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use log::{debug, error, info, trace};
|
use log::{debug, error, info, trace};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::path::PathBuf;
|
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
pub struct TestClient {
|
pub struct TestClient {
|
||||||
client: RpcClient,
|
pub bitcoind: BitcoinD,
|
||||||
electrum: ElectrumClient,
|
pub electrsd: ElectrsD,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TestClient {
|
impl TestClient {
|
||||||
pub fn new(rpc_host_and_wallet: String, rpc_wallet_name: String) -> Self {
|
pub fn new(bitcoind_exe: String, electrs_exe: String) -> Self {
|
||||||
let client = RpcClient::new(
|
debug!("launching {} and {}", &bitcoind_exe, &electrs_exe);
|
||||||
format!("http://{}/wallet/{}", rpc_host_and_wallet, rpc_wallet_name),
|
let bitcoind = BitcoinD::new(bitcoind_exe).unwrap();
|
||||||
get_auth(),
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
let electrum = ElectrumClient::new(&get_electrum_url()).unwrap();
|
|
||||||
|
|
||||||
TestClient { client, electrum }
|
let http_enabled = cfg!(feature = "test-esplora");
|
||||||
|
|
||||||
|
let electrsd = ElectrsD::new(electrs_exe, &bitcoind, false, http_enabled).unwrap();
|
||||||
|
|
||||||
|
let node_address = bitcoind.client.get_new_address(None, None).unwrap();
|
||||||
|
bitcoind
|
||||||
|
.client
|
||||||
|
.generate_to_address(101, &node_address)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let mut test_client = TestClient { bitcoind, electrsd };
|
||||||
|
TestClient::wait_for_block(&mut test_client, 101);
|
||||||
|
test_client
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wait_for_tx(&mut self, txid: Txid, monitor_script: &Script) {
|
fn wait_for_tx(&mut self, txid: Txid, monitor_script: &Script) {
|
||||||
// wait for electrs to index the tx
|
// wait for electrs to index the tx
|
||||||
exponential_backoff_poll(|| {
|
exponential_backoff_poll(|| {
|
||||||
|
self.electrsd.trigger().unwrap();
|
||||||
trace!("wait_for_tx {}", txid);
|
trace!("wait_for_tx {}", txid);
|
||||||
|
|
||||||
self.electrum
|
self.electrsd
|
||||||
|
.client
|
||||||
.script_get_history(monitor_script)
|
.script_get_history(monitor_script)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.iter()
|
.iter()
|
||||||
@ -46,12 +57,13 @@ impl TestClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn wait_for_block(&mut self, min_height: usize) {
|
fn wait_for_block(&mut self, min_height: usize) {
|
||||||
self.electrum.block_headers_subscribe().unwrap();
|
self.electrsd.client.block_headers_subscribe().unwrap();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let header = exponential_backoff_poll(|| {
|
let header = exponential_backoff_poll(|| {
|
||||||
self.electrum.ping().unwrap();
|
self.electrsd.trigger().unwrap();
|
||||||
self.electrum.block_headers_pop().unwrap()
|
self.electrsd.client.ping().unwrap();
|
||||||
|
self.electrsd.client.block_headers_pop().unwrap()
|
||||||
});
|
});
|
||||||
if header.height >= min_height {
|
if header.height >= min_height {
|
||||||
break;
|
break;
|
||||||
@ -96,10 +108,13 @@ impl TestClient {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// broadcast through electrum so that it caches the tx immediately
|
// broadcast through electrum so that it caches the tx immediately
|
||||||
|
|
||||||
let txid = self
|
let txid = self
|
||||||
.electrum
|
.electrsd
|
||||||
|
.client
|
||||||
.transaction_broadcast(&deserialize(&tx.hex).unwrap())
|
.transaction_broadcast(&deserialize(&tx.hex).unwrap())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
debug!("broadcasted to electrum {}", txid);
|
||||||
|
|
||||||
if let Some(num) = meta_tx.min_confirmations {
|
if let Some(num) = meta_tx.min_confirmations {
|
||||||
self.generate(num, None);
|
self.generate(num, None);
|
||||||
@ -209,7 +224,7 @@ impl TestClient {
|
|||||||
let block_hex: String = serialize(&block).to_hex();
|
let block_hex: String = serialize(&block).to_hex();
|
||||||
debug!("generated block hex: {}", block_hex);
|
debug!("generated block hex: {}", block_hex);
|
||||||
|
|
||||||
self.electrum.block_headers_subscribe().unwrap();
|
self.electrsd.client.block_headers_subscribe().unwrap();
|
||||||
|
|
||||||
let submit_result: serde_json::Value =
|
let submit_result: serde_json::Value =
|
||||||
self.call("submitblock", &[block_hex.into()]).unwrap();
|
self.call("submitblock", &[block_hex.into()]).unwrap();
|
||||||
@ -237,7 +252,7 @@ impl TestClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn invalidate(&mut self, num_blocks: u64) {
|
pub fn invalidate(&mut self, num_blocks: u64) {
|
||||||
self.electrum.block_headers_subscribe().unwrap();
|
self.electrsd.client.block_headers_subscribe().unwrap();
|
||||||
|
|
||||||
let best_hash = self.get_best_block_hash().unwrap();
|
let best_hash = self.get_best_block_hash().unwrap();
|
||||||
let initial_height = self.get_block_info(&best_hash).unwrap().height;
|
let initial_height = self.get_block_info(&best_hash).unwrap().height;
|
||||||
@ -288,16 +303,25 @@ impl Deref for TestClient {
|
|||||||
type Target = RpcClient;
|
type Target = RpcClient;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
&self.client
|
&self.bitcoind.client
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for TestClient {
|
impl Default for TestClient {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
let rpc_host_and_port =
|
let bitcoind_exe = env::var("BITCOIND_EXE")
|
||||||
env::var("BDK_RPC_URL").unwrap_or_else(|_| "127.0.0.1:18443".to_string());
|
.ok()
|
||||||
let wallet = env::var("BDK_RPC_WALLET").unwrap_or_else(|_| "bdk-test".to_string());
|
.or(bitcoind::downloaded_exe_path())
|
||||||
Self::new(rpc_host_and_port, wallet)
|
.expect(
|
||||||
|
"you should provide env var BITCOIND_EXE or specifiy a bitcoind version feature",
|
||||||
|
);
|
||||||
|
let electrs_exe = env::var("ELECTRS_EXE")
|
||||||
|
.ok()
|
||||||
|
.or(electrsd::downloaded_exe_path())
|
||||||
|
.expect(
|
||||||
|
"you should provide env var ELECTRS_EXE or specifiy a electrsd version feature",
|
||||||
|
);
|
||||||
|
Self::new(bitcoind_exe, electrs_exe)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -317,27 +341,13 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: we currently only support env vars, we could also parse a toml file
|
|
||||||
fn get_auth() -> Auth {
|
|
||||||
match env::var("BDK_RPC_AUTH").as_ref().map(String::as_ref) {
|
|
||||||
Ok("USER_PASS") => Auth::UserPass(
|
|
||||||
env::var("BDK_RPC_USER").unwrap(),
|
|
||||||
env::var("BDK_RPC_PASS").unwrap(),
|
|
||||||
),
|
|
||||||
_ => Auth::CookieFile(PathBuf::from(
|
|
||||||
env::var("BDK_RPC_COOKIEFILE")
|
|
||||||
.unwrap_or_else(|_| "/home/user/.bitcoin/regtest/.cookie".to_string()),
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This macro runs blockchain tests against a `Blockchain` implementation. It requires access to a
|
/// This macro runs blockchain tests against a `Blockchain` implementation. It requires access to a
|
||||||
/// Bitcoin core wallet via RPC. At the moment you have to dig into the code yourself and look at
|
/// Bitcoin core wallet via RPC. At the moment you have to dig into the code yourself and look at
|
||||||
/// the setup required to run the tests yourself.
|
/// the setup required to run the tests yourself.
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! bdk_blockchain_tests {
|
macro_rules! bdk_blockchain_tests {
|
||||||
(
|
(
|
||||||
fn test_instance() -> $blockchain:ty $block:block) => {
|
fn $_fn_name:ident ( $( $test_client:ident : &TestClient )? $(,)? ) -> $blockchain:ty $block:block) => {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod bdk_blockchain_tests {
|
mod bdk_blockchain_tests {
|
||||||
use $crate::bitcoin::Network;
|
use $crate::bitcoin::Network;
|
||||||
@ -347,16 +357,17 @@ macro_rules! bdk_blockchain_tests {
|
|||||||
use $crate::types::KeychainKind;
|
use $crate::types::KeychainKind;
|
||||||
use $crate::{Wallet, FeeRate};
|
use $crate::{Wallet, FeeRate};
|
||||||
use $crate::testutils;
|
use $crate::testutils;
|
||||||
use $crate::serial_test::serial;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
fn get_blockchain() -> $blockchain {
|
#[allow(unused_variables)]
|
||||||
|
fn get_blockchain(test_client: &TestClient) -> $blockchain {
|
||||||
|
$( let $test_client = test_client; )?
|
||||||
$block
|
$block
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_wallet_from_descriptors(descriptors: &(String, Option<String>)) -> Wallet<$blockchain, MemoryDatabase> {
|
fn get_wallet_from_descriptors(descriptors: &(String, Option<String>), test_client: &TestClient) -> Wallet<$blockchain, MemoryDatabase> {
|
||||||
Wallet::new(&descriptors.0.to_string(), descriptors.1.as_ref(), Network::Regtest, MemoryDatabase::new(), get_blockchain()).unwrap()
|
Wallet::new(&descriptors.0.to_string(), descriptors.1.as_ref(), Network::Regtest, MemoryDatabase::new(), get_blockchain(test_client)).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init_single_sig() -> (Wallet<$blockchain, MemoryDatabase>, (String, Option<String>), TestClient) {
|
fn init_single_sig() -> (Wallet<$blockchain, MemoryDatabase>, (String, Option<String>), TestClient) {
|
||||||
@ -367,7 +378,7 @@ macro_rules! bdk_blockchain_tests {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let test_client = TestClient::default();
|
let test_client = TestClient::default();
|
||||||
let wallet = get_wallet_from_descriptors(&descriptors);
|
let wallet = get_wallet_from_descriptors(&descriptors, &test_client);
|
||||||
|
|
||||||
// rpc need to call import_multi before receiving any tx, otherwise will not see tx in the mempool
|
// rpc need to call import_multi before receiving any tx, otherwise will not see tx in the mempool
|
||||||
#[cfg(feature = "test-rpc")]
|
#[cfg(feature = "test-rpc")]
|
||||||
@ -377,7 +388,6 @@ macro_rules! bdk_blockchain_tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[serial]
|
|
||||||
fn test_sync_simple() {
|
fn test_sync_simple() {
|
||||||
let (wallet, descriptors, mut test_client) = init_single_sig();
|
let (wallet, descriptors, mut test_client) = init_single_sig();
|
||||||
|
|
||||||
@ -400,7 +410,6 @@ macro_rules! bdk_blockchain_tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[serial]
|
|
||||||
fn test_sync_stop_gap_20() {
|
fn test_sync_stop_gap_20() {
|
||||||
let (wallet, descriptors, mut test_client) = init_single_sig();
|
let (wallet, descriptors, mut test_client) = init_single_sig();
|
||||||
|
|
||||||
@ -418,7 +427,6 @@ macro_rules! bdk_blockchain_tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[serial]
|
|
||||||
fn test_sync_before_and_after_receive() {
|
fn test_sync_before_and_after_receive() {
|
||||||
let (wallet, descriptors, mut test_client) = init_single_sig();
|
let (wallet, descriptors, mut test_client) = init_single_sig();
|
||||||
|
|
||||||
@ -436,7 +444,6 @@ macro_rules! bdk_blockchain_tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[serial]
|
|
||||||
fn test_sync_multiple_outputs_same_tx() {
|
fn test_sync_multiple_outputs_same_tx() {
|
||||||
let (wallet, descriptors, mut test_client) = init_single_sig();
|
let (wallet, descriptors, mut test_client) = init_single_sig();
|
||||||
|
|
||||||
@ -458,7 +465,6 @@ macro_rules! bdk_blockchain_tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[serial]
|
|
||||||
fn test_sync_receive_multi() {
|
fn test_sync_receive_multi() {
|
||||||
let (wallet, descriptors, mut test_client) = init_single_sig();
|
let (wallet, descriptors, mut test_client) = init_single_sig();
|
||||||
|
|
||||||
@ -477,7 +483,6 @@ macro_rules! bdk_blockchain_tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[serial]
|
|
||||||
fn test_sync_address_reuse() {
|
fn test_sync_address_reuse() {
|
||||||
let (wallet, descriptors, mut test_client) = init_single_sig();
|
let (wallet, descriptors, mut test_client) = init_single_sig();
|
||||||
|
|
||||||
@ -497,7 +502,6 @@ macro_rules! bdk_blockchain_tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[serial]
|
|
||||||
fn test_sync_receive_rbf_replaced() {
|
fn test_sync_receive_rbf_replaced() {
|
||||||
let (wallet, descriptors, mut test_client) = init_single_sig();
|
let (wallet, descriptors, mut test_client) = init_single_sig();
|
||||||
|
|
||||||
@ -536,7 +540,6 @@ macro_rules! bdk_blockchain_tests {
|
|||||||
// doesn't work for some reason.
|
// doesn't work for some reason.
|
||||||
#[cfg(not(feature = "esplora"))]
|
#[cfg(not(feature = "esplora"))]
|
||||||
#[test]
|
#[test]
|
||||||
#[serial]
|
|
||||||
fn test_sync_reorg_block() {
|
fn test_sync_reorg_block() {
|
||||||
let (wallet, descriptors, mut test_client) = init_single_sig();
|
let (wallet, descriptors, mut test_client) = init_single_sig();
|
||||||
|
|
||||||
@ -567,7 +570,6 @@ macro_rules! bdk_blockchain_tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[serial]
|
|
||||||
fn test_sync_after_send() {
|
fn test_sync_after_send() {
|
||||||
let (wallet, descriptors, mut test_client) = init_single_sig();
|
let (wallet, descriptors, mut test_client) = init_single_sig();
|
||||||
println!("{}", descriptors.0);
|
println!("{}", descriptors.0);
|
||||||
@ -588,7 +590,6 @@ macro_rules! bdk_blockchain_tests {
|
|||||||
let tx = psbt.extract_tx();
|
let tx = psbt.extract_tx();
|
||||||
println!("{}", bitcoin::consensus::encode::serialize_hex(&tx));
|
println!("{}", bitcoin::consensus::encode::serialize_hex(&tx));
|
||||||
wallet.broadcast(tx).unwrap();
|
wallet.broadcast(tx).unwrap();
|
||||||
|
|
||||||
wallet.sync(noop_progress(), None).unwrap();
|
wallet.sync(noop_progress(), None).unwrap();
|
||||||
assert_eq!(wallet.get_balance().unwrap(), details.received, "incorrect balance after send");
|
assert_eq!(wallet.get_balance().unwrap(), details.received, "incorrect balance after send");
|
||||||
|
|
||||||
@ -597,7 +598,6 @@ macro_rules! bdk_blockchain_tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[serial]
|
|
||||||
fn test_update_confirmation_time_after_generate() {
|
fn test_update_confirmation_time_after_generate() {
|
||||||
let (wallet, descriptors, mut test_client) = init_single_sig();
|
let (wallet, descriptors, mut test_client) = init_single_sig();
|
||||||
println!("{}", descriptors.0);
|
println!("{}", descriptors.0);
|
||||||
@ -623,9 +623,7 @@ macro_rules! bdk_blockchain_tests {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[serial]
|
|
||||||
fn test_sync_outgoing_from_scratch() {
|
fn test_sync_outgoing_from_scratch() {
|
||||||
let (wallet, descriptors, mut test_client) = init_single_sig();
|
let (wallet, descriptors, mut test_client) = init_single_sig();
|
||||||
let node_addr = test_client.get_node_address(None);
|
let node_addr = test_client.get_node_address(None);
|
||||||
@ -648,7 +646,7 @@ macro_rules! bdk_blockchain_tests {
|
|||||||
assert_eq!(wallet.get_balance().unwrap(), details.received, "incorrect balance after receive");
|
assert_eq!(wallet.get_balance().unwrap(), details.received, "incorrect balance after receive");
|
||||||
|
|
||||||
// empty wallet
|
// empty wallet
|
||||||
let wallet = get_wallet_from_descriptors(&descriptors);
|
let wallet = get_wallet_from_descriptors(&descriptors, &test_client);
|
||||||
|
|
||||||
#[cfg(feature = "rpc")] // rpc cannot see mempool tx before importmulti
|
#[cfg(feature = "rpc")] // rpc cannot see mempool tx before importmulti
|
||||||
test_client.generate(1, Some(node_addr));
|
test_client.generate(1, Some(node_addr));
|
||||||
@ -667,7 +665,6 @@ macro_rules! bdk_blockchain_tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[serial]
|
|
||||||
fn test_sync_long_change_chain() {
|
fn test_sync_long_change_chain() {
|
||||||
let (wallet, descriptors, mut test_client) = init_single_sig();
|
let (wallet, descriptors, mut test_client) = init_single_sig();
|
||||||
let node_addr = test_client.get_node_address(None);
|
let node_addr = test_client.get_node_address(None);
|
||||||
@ -698,7 +695,7 @@ macro_rules! bdk_blockchain_tests {
|
|||||||
|
|
||||||
// empty wallet
|
// empty wallet
|
||||||
|
|
||||||
let wallet = get_wallet_from_descriptors(&descriptors);
|
let wallet = get_wallet_from_descriptors(&descriptors, &test_client);
|
||||||
|
|
||||||
#[cfg(feature = "rpc")] // rpc cannot see mempool tx before importmulti
|
#[cfg(feature = "rpc")] // rpc cannot see mempool tx before importmulti
|
||||||
test_client.generate(1, Some(node_addr));
|
test_client.generate(1, Some(node_addr));
|
||||||
@ -709,7 +706,6 @@ macro_rules! bdk_blockchain_tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[serial]
|
|
||||||
fn test_sync_bump_fee_basic() {
|
fn test_sync_bump_fee_basic() {
|
||||||
let (wallet, descriptors, mut test_client) = init_single_sig();
|
let (wallet, descriptors, mut test_client) = init_single_sig();
|
||||||
let node_addr = test_client.get_node_address(None);
|
let node_addr = test_client.get_node_address(None);
|
||||||
@ -745,7 +741,6 @@ macro_rules! bdk_blockchain_tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[serial]
|
|
||||||
fn test_sync_bump_fee_remove_change() {
|
fn test_sync_bump_fee_remove_change() {
|
||||||
let (wallet, descriptors, mut test_client) = init_single_sig();
|
let (wallet, descriptors, mut test_client) = init_single_sig();
|
||||||
let node_addr = test_client.get_node_address(None);
|
let node_addr = test_client.get_node_address(None);
|
||||||
@ -781,7 +776,6 @@ macro_rules! bdk_blockchain_tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[serial]
|
|
||||||
fn test_sync_bump_fee_add_input_simple() {
|
fn test_sync_bump_fee_add_input_simple() {
|
||||||
let (wallet, descriptors, mut test_client) = init_single_sig();
|
let (wallet, descriptors, mut test_client) = init_single_sig();
|
||||||
let node_addr = test_client.get_node_address(None);
|
let node_addr = test_client.get_node_address(None);
|
||||||
@ -815,7 +809,6 @@ macro_rules! bdk_blockchain_tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[serial]
|
|
||||||
fn test_sync_bump_fee_add_input_no_change() {
|
fn test_sync_bump_fee_add_input_no_change() {
|
||||||
let (wallet, descriptors, mut test_client) = init_single_sig();
|
let (wallet, descriptors, mut test_client) = init_single_sig();
|
||||||
let node_addr = test_client.get_node_address(None);
|
let node_addr = test_client.get_node_address(None);
|
||||||
@ -852,7 +845,6 @@ macro_rules! bdk_blockchain_tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[serial]
|
|
||||||
fn test_sync_receive_coinbase() {
|
fn test_sync_receive_coinbase() {
|
||||||
let (wallet, _, mut test_client) = init_single_sig();
|
let (wallet, _, mut test_client) = init_single_sig();
|
||||||
|
|
||||||
@ -875,5 +867,10 @@ macro_rules! bdk_blockchain_tests {
|
|||||||
assert!(wallet.get_balance().unwrap() > 0, "incorrect balance after receiving coinbase");
|
assert!(wallet.get_balance().unwrap() > 0, "incorrect balance after receiving coinbase");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
( fn $fn_name:ident ($( $tt:tt )+) -> $blockchain:ty $block:block) => {
|
||||||
|
compile_error!(concat!("Invalid arguments `", stringify!($($tt)*), "` in the blockchain tests fn."));
|
||||||
|
compile_error!("Only the exact `&TestClient` type is supported, **without** any leading path items.");
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
// licenses.
|
// licenses.
|
||||||
#![allow(missing_docs)]
|
#![allow(missing_docs)]
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
#[cfg(feature = "test-blockchains")]
|
#[cfg(feature = "test-blockchains")]
|
||||||
pub mod blockchain_tests;
|
pub mod blockchain_tests;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user