diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 4680dd209..94f70af99 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -69,21 +69,4 @@ jobs: - name: Running cargo env: DO_FEATURE_MATRIX: true - run: ./contrib/test.sh - - IntTests: - name: Integration tests - runs-on: ubuntu-latest - steps: - - name: Checkout Crate - uses: actions/checkout@v2 - - name: Checkout Toolchain - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true - - name: Running cargo - env: - BITCOINVERSION: '22.0' - run: ./contrib/test.sh + run: ./contrib/test.sh \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index 57da5b57d..150e41d2e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,6 +22,11 @@ rand = ["bitcoin/rand"] bitcoin = "0.28.0" serde = { version = "1.0", optional = true} +[dev-dependencies] +bitcoind = {version = "0.26.1", features=["22_0"]} +actual-rand = { package = "rand", version = "0.8.4"} +bitcoin = { version = "0.28", features = ["rand"]} + [[example]] name = "htlc" required-features = ["compiler"] diff --git a/contrib/test.sh b/contrib/test.sh index 706ac51ca..34b4109b2 100755 --- a/contrib/test.sh +++ b/contrib/test.sh @@ -66,17 +66,4 @@ if [ "$DO_DOCS" = true ]; then RUSTDOCFLAGS="--cfg docsrs" cargo doc --all --features="$FEATURES" fi -# Run Integration tests if told so -if [ -n "$BITCOINVERSION" ]; then - set -e - cd integration_test - curl https://bitcoincore.org/bin/bitcoin-core-$BITCOINVERSION/bitcoin-$BITCOINVERSION-x86_64-linux-gnu.tar.gz | tar xvzf - bitcoin-$BITCOINVERSION/bin/bitcoind # will abort if the check fails. - sha256sum --check bitcoin-core-$BITCOINVERSION.sha256sum - export PATH=$PATH:$(pwd)/bitcoin-$BITCOINVERSION/bin - ./run.sh - # Cleanups - rm -rf bitcoin-$BITCOINVERSION - exit 0 -fi - exit 0 diff --git a/integration_test/Cargo.toml b/integration_test/Cargo.toml deleted file mode 100644 index 6bcba6538..000000000 --- a/integration_test/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "integration_tests_miniscript" -version = "0.1.0" -authors = ["Steven Roose ", "Sanket K "] -edition = "2018" - -[dependencies] -miniscript = {path = "../"} - -# Until 0.26 support is released on rust-bitcoincore-rpc -bitcoincore-rpc = {git = "https://github.com/sanket1729/rust-bitcoincore-rpc",rev = "1ee9a3e808815702ac1a4b974689fcb33b5648c3"} -bitcoin = { version = "0.28", features = ["rand"]} -log = "0.4" -rand = "0.8.4" \ No newline at end of file diff --git a/integration_test/bitcoin-core-0.21.0.sha256sum b/integration_test/bitcoin-core-0.21.0.sha256sum deleted file mode 100644 index cd92870b5..000000000 --- a/integration_test/bitcoin-core-0.21.0.sha256sum +++ /dev/null @@ -1 +0,0 @@ -7955542df199c6ce4ca0bb3966dcf9cc71199c592fec38508dad58301a3298d0 ./bitcoin-0.21.0/bin/bitcoind diff --git a/integration_test/bitcoin-core-22.0.sha256sum b/integration_test/bitcoin-core-22.0.sha256sum deleted file mode 100644 index c222da3f6..000000000 --- a/integration_test/bitcoin-core-22.0.sha256sum +++ /dev/null @@ -1 +0,0 @@ -4aebceb3caf83f27bd3dd9030da637bacc836912a65a896860dc0252d0ebfad9 ./bitcoin-22.0/bin/bitcoind diff --git a/integration_test/random_ms.txt b/integration_test/random_ms.txt deleted file mode 100644 index 4aa5d4fc8..000000000 --- a/integration_test/random_ms.txt +++ /dev/null @@ -1,34 +0,0 @@ -and_b(lltvln:after(1231488000),s:pk(03d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a)) -uuj:and_v(v:multi(2,03d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a,025601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7cc),after(1231488000)) -or_b(un:multi(2,03daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729,024ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97),al:older(16)) -j:and_v(vdv:after(1567547623),older(16)) -t:and_v(vu:hash256(H),v:sha256(H)) -t:andor(multi(3,02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e,03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556,02e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13),v:older(4194305),v:sha256(H)) -or_d(multi(1,02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9),or_b(multi(3,022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01,032fa2104d6b38d11b0230010559879124e42ab8dfeff5ff29dc9cdadd4ecacc3f,03d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a),su:after(500000))) -or_d(sha256(H),and_n(un:after(499999999),older(4194305))) -and_v(or_i(v:multi(2,02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5,03774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb),v:multi(2,03e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a,025cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc)),sha256(H)) -j:and_b(multi(2,0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798,024ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97),s:or_i(older(1),older(4252898))) -and_b(older(16),s:or_d(sha256(H),n:after(1567547623))) -j:and_v(v:ripemd160(H),or_d(sha256(H),older(16))) -and_b(hash256(H),a:and_b(hash256(H),a:older(1))) -thresh(2,multi(2,03a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7,036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a00),a:multi(1,036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a00),ac:pk_k(022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01)) -and_n(sha256(H),t:or_i(v:older(4252898),v:older(16))) -or_d(nd:and_v(v:older(4252898),v:older(4252898)),sha256(H)) -c:and_v(or_c(sha256(H),v:multi(1,02c44d12c7065d812e8acf28d7cbb19f9011ecd9e9fdf281b0e6a3b5e87d22e7db)),pk_k(03acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbe)) -c:and_v(or_c(multi(2,036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a00,02352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d5),v:ripemd160(H)),pk_k(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556)) -and_v(andor(hash256(H),v:hash256(H),v:older(50000)),after(1231488000)) -andor(hash256(H),j:and_v(v:ripemd160(H),older(4194305)),ripemd160(H)) -or_i(c:and_v(v:after(500000),pk_k(02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5)),sha256(H)) -thresh(2,c:pk_h(025cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc),s:sha256(H),a:ripemd160(H)) -and_n(sha256(H),uc:and_v(v:older(16),pk_k(03fe72c435413d33d48ac09c9161ba8b09683215439d62b7940502bda8b202e6ce))) -and_n(c:pk_k(03daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729),and_b(l:older(15),a:older(16))) -c:or_i(and_v(v:older(16),pk_h(02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e)),pk_h(026a245bf6dc698504c89a20cfded60853152b695336c28063b61c65cbd269e6b4)) -or_d(c:pk_h(02e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13),andor(c:pk_k(024ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97),older(2016),after(1567547623))) -c:andor(ripemd160(H),pk_h(02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e),and_v(v:hash256(H),pk_h(03d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a))) -c:andor(u:ripemd160(H),pk_h(03daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729),or_i(pk_h(022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01),pk_h(0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798))) -c:or_i(andor(c:pk_h(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),pk_h(022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01),pk_h(02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5)),pk_k(02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e)) -multi(2,03a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7,036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a00) -multi(1,036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a00) -thresh(2,multi(2,03a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7,036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a00),a:multi(1,036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a00)) -thresh(2,multi(2,03a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7,036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a00),a:multi(1,036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a00),ac:pk_k(022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01)) -c:pk_k(022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01) \ No newline at end of file diff --git a/integration_test/run.sh b/integration_test/run.sh deleted file mode 100755 index 5d8fb64e6..000000000 --- a/integration_test/run.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/sh - -RAND_DIR=$(head -c 4 /dev/null - -BLOCKFILTERARG="" -if bitcoind -version | grep -q "v0\.\(19\|2\)"; then - BLOCKFILTERARG="-blockfilterindex=1" -fi - -FALLBACKFEEARG="" -if bitcoind -version | grep -q -e "v0\.2" -e "v2[2-9]"; then - FALLBACKFEEARG="-fallbackfee=0.00001000" -fi - -bitcoind -regtest $FALLBACKFEEARG \ - -datadir=${TESTDIR}/1 \ - -rpcport=12348 \ - -server=1 \ - -printtoconsole=0 & -PID1=$! - -# Make sure it's listening. -sleep 3 - -RPC_URL=http://localhost:12348 \ - RPC_COOKIE=${TESTDIR}/1/regtest/.cookie \ - cargo run - -RESULT=$? - -kill -9 $PID1 -rm -rf ${TESTDIR} -exit $RESULT diff --git a/integration_test/src/main.rs b/integration_test/src/main.rs deleted file mode 100644 index 28a6c39dd..000000000 --- a/integration_test/src/main.rs +++ /dev/null @@ -1,132 +0,0 @@ -//! # rust-miniscript integration test -//! -//! This is how some external user would use rust-miniscript - -use bitcoincore_rpc::{Auth, Client, RpcApi}; - -mod test_cpp; -mod test_desc; -mod test_util; -use crate::test_util::TestData; - -struct StdLogger; - -impl log::Log for StdLogger { - fn enabled(&self, metadata: &log::Metadata<'_>) -> bool { - metadata.target().contains("jsonrpc") || metadata.target().contains("bitcoincore_rpc") - } - - fn log(&self, record: &log::Record<'_>) { - if self.enabled(record.metadata()) { - println!( - "[{}][{}]: {}", - record.level(), - record.metadata().target(), - record.args() - ); - } - } - - fn flush(&self) {} -} - -static LOGGER: StdLogger = StdLogger; - -fn get_rpc_url() -> String { - return std::env::var("RPC_URL").expect("RPC_URL must be set"); -} - -fn get_auth() -> bitcoincore_rpc::Auth { - if let Ok(cookie) = std::env::var("RPC_COOKIE") { - return Auth::CookieFile(cookie.into()); - } else if let Ok(user) = std::env::var("RPC_USER") { - return Auth::UserPass(user, std::env::var("RPC_PASS").unwrap_or_default()); - } else { - panic!("Either RPC_COOKIE or RPC_USER + RPC_PASS must be set."); - }; -} - -fn main() { - log::set_logger(&LOGGER) - .map(|()| log::set_max_level(log::LevelFilter::max())) - .unwrap(); - - let rpc_url = format!("{}/wallet/testwallet", get_rpc_url()); - let auth = get_auth(); - - let cl = Client::new(&rpc_url, auth).unwrap(); - - // 0.21 does not create default wallet.. - cl.create_wallet("testwallet", None, None, None, None) - .unwrap(); - - let testdata = TestData::new_fixed_data(50); - test_cpp::test_from_cpp_ms(&cl, &testdata); - - test_descs(&cl, &testdata); -} - -fn test_descs(cl: &Client, testdata: &TestData) { - // K : Compressed key available - // K!: Compressed key with corresponding secret key unknown - // X: X-only key available - // X!: X-only key with corresponding secret key unknown - - // Test 1: Simple spend with internal key - let wit = test_desc::test_desc_satisfy(cl, testdata, "tr(X)"); - assert!(wit.len() == 1); - - // Test 2: Same as above, but with leaves - let wit = test_desc::test_desc_satisfy(cl, testdata, "tr(X,{pk(X1!),pk(X2!)})"); - assert!(wit.len() == 1); - - // Test 3: Force to spend with script spend. Unknown internal key and only one known script path - // X! -> Internal key unknown - // Leaf 1 -> pk(X1) with X1 known - // Leaf 2-> and_v(v:pk(X2),pk(X3!)) with partial witness only to X2 known - let wit = test_desc::test_desc_satisfy(cl, testdata, "tr(X!,{pk(X1),and_v(v:pk(X2),pk(X3!))})"); - assert!(wit.len() == 3); // control block, script and signature - - // Test 4: Force to spend with script spend. Unknown internal key and multiple script paths - // Should select the one with minimum weight - // X! -> Internal key unknown - // Leaf 1 -> pk(X1!) with X1 unknown - // Leaf 2-> and_v(v:pk(X2),pk(X3)) X2 and X3 known - let wit = test_desc::test_desc_satisfy(cl, testdata, "tr(X!,{pk(X1),and_v(v:pk(X2),pk(X3))})"); - assert!(wit.len() == 3); // control block, script and one signatures - - // Test 5: When everything is available, we should select the key spend path - let wit = test_desc::test_desc_satisfy(cl, testdata, "tr(X,{pk(X1),and_v(v:pk(X2),pk(X3!))})"); - assert!(wit.len() == 1); // control block, script and signature - - // Test 6: Test the new multi_a opcodes - test_desc::test_desc_satisfy(cl, testdata, "tr(X!,{pk(X1!),multi_a(1,X2,X3!,X4!,X5!)})"); - test_desc::test_desc_satisfy(cl, testdata, "tr(X!,{pk(X1!),multi_a(2,X2,X3,X4!,X5!)})"); - test_desc::test_desc_satisfy(cl, testdata, "tr(X!,{pk(X1!),multi_a(3,X2,X3,X4,X5!)})"); - test_desc::test_desc_satisfy(cl, testdata, "tr(X!,{pk(X1!),multi_a(4,X2,X3,X4,X5)})"); - - // Test 7: Test script tree of depth 127 is valid, only X128 is known - test_desc::test_desc_satisfy(cl, testdata, "tr(X!,{pk(X1!),{pk(X2!),{pk(X3!),{pk(X4!),{pk(X5!),{pk(X6!),{pk(X7!),{pk(X8!),{pk(X9!),{pk(X10!),{pk(X11!),{pk(X12!),{pk(X13!),{pk(X14!),{pk(X15!),{pk(X16!),{pk(X17!),{pk(X18!),{pk(X19!),{pk(X20!),{pk(X21!),{pk(X22!),{pk(X23!),{pk(X24!),{pk(X25!),{pk(X26!),{pk(X27!),{pk(X28!),{pk(X29!),{pk(X30!),{pk(X31!),{pk(X32!),{pk(X33!),{pk(X34!),{pk(X35!),{pk(X36!),{pk(X37!),{pk(X38!),{pk(X39!),{pk(X40!),{pk(X41!),{pk(X42!),{pk(X43!),{pk(X44!),{pk(X45!),{pk(X46!),{pk(X47!),{pk(X48!),{pk(X49!),{pk(X50!),{pk(X51!),{pk(X52!),{pk(X53!),{pk(X54!),{pk(X55!),{pk(X56!),{pk(X57!),{pk(X58!),{pk(X59!),{pk(X60!),{pk(X61!),{pk(X62!),{pk(X63!),{pk(X64!),{pk(X65!),{pk(X66!),{pk(X67!),{pk(X68!),{pk(X69!),{pk(X70!),{pk(X71!),{pk(X72!),{pk(X73!),{pk(X74!),{pk(X75!),{pk(X76!),{pk(X77!),{pk(X78!),{pk(X79!),{pk(X80!),{pk(X81!),{pk(X82!),{pk(X83!),{pk(X84!),{pk(X85!),{pk(X86!),{pk(X87!),{pk(X88!),{pk(X89!),{pk(X90!),{pk(X91!),{pk(X92!),{pk(X93!),{pk(X94!),{pk(X95!),{pk(X96!),{pk(X97!),{pk(X98!),{pk(X99!),{pk(X100!),{pk(X101!),{pk(X102!),{pk(X103!),{pk(X104!),{pk(X105!),{pk(X106!),{pk(X107!),{pk(X108!),{pk(X109!),{pk(X110!),{pk(X111!),{pk(X112!),{pk(X113!),{pk(X114!),{pk(X115!),{pk(X116!),{pk(X117!),{pk(X118!),{pk(X119!),{pk(X120!),{pk(X121!),{pk(X122!),{pk(X123!),{pk(X124!),{pk(X125!),{pk(X126!),{pk(X127!),pk(X128)}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}})"); - - // Test 8: Test script tree of depth 128 is valid, only X129 is known - test_desc::test_desc_satisfy(cl, testdata, "tr(X!,{pk(X1!),{pk(X2!),{pk(X3!),{pk(X4!),{pk(X5!),{pk(X6!),{pk(X7!),{pk(X8!),{pk(X9!),{pk(X10!),{pk(X11!),{pk(X12!),{pk(X13!),{pk(X14!),{pk(X15!),{pk(X16!),{pk(X17!),{pk(X18!),{pk(X19!),{pk(X20!),{pk(X21!),{pk(X22!),{pk(X23!),{pk(X24!),{pk(X25!),{pk(X26!),{pk(X27!),{pk(X28!),{pk(X29!),{pk(X30!),{pk(X31!),{pk(X32!),{pk(X33!),{pk(X34!),{pk(X35!),{pk(X36!),{pk(X37!),{pk(X38!),{pk(X39!),{pk(X40!),{pk(X41!),{pk(X42!),{pk(X43!),{pk(X44!),{pk(X45!),{pk(X46!),{pk(X47!),{pk(X48!),{pk(X49!),{pk(X50!),{pk(X51!),{pk(X52!),{pk(X53!),{pk(X54!),{pk(X55!),{pk(X56!),{pk(X57!),{pk(X58!),{pk(X59!),{pk(X60!),{pk(X61!),{pk(X62!),{pk(X63!),{pk(X64!),{pk(X65!),{pk(X66!),{pk(X67!),{pk(X68!),{pk(X69!),{pk(X70!),{pk(X71!),{pk(X72!),{pk(X73!),{pk(X74!),{pk(X75!),{pk(X76!),{pk(X77!),{pk(X78!),{pk(X79!),{pk(X80!),{pk(X81!),{pk(X82!),{pk(X83!),{pk(X84!),{pk(X85!),{pk(X86!),{pk(X87!),{pk(X88!),{pk(X89!),{pk(X90!),{pk(X91!),{pk(X92!),{pk(X93!),{pk(X94!),{pk(X95!),{pk(X96!),{pk(X97!),{pk(X98!),{pk(X99!),{pk(X100!),{pk(X101!),{pk(X102!),{pk(X103!),{pk(X104!),{pk(X105!),{pk(X106!),{pk(X107!),{pk(X108!),{pk(X109!),{pk(X110!),{pk(X111!),{pk(X112!),{pk(X113!),{pk(X114!),{pk(X115!),{pk(X116!),{pk(X117!),{pk(X118!),{pk(X119!),{pk(X120!),{pk(X121!),{pk(X122!),{pk(X123!),{pk(X124!),{pk(X125!),{pk(X126!),{pk(X127!),{pk(X128!),pk(X129)}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}})"); - - // Test 9: Test script complete tree having 128 leaves with depth log(128), only X1 is known - test_desc::test_desc_satisfy(cl, testdata, "tr(X!,{{{{{{{pk(X1),pk(X2!)},{pk(X3!),pk(X4!)}},{{pk(X5!),pk(X6!)},{pk(X7!),pk(X8!)}}},{{{pk(X9!),pk(X10!)},{pk(X11!),pk(X12!)}},{{pk(X13!),pk(X14!)},{pk(X15!),pk(X16!)}}}},{{{{pk(X17!),pk(X18!)},{pk(X19!),pk(X20!)}},{{pk(X21!),pk(X22!)},{pk(X23!),pk(X24!)}}},{{{pk(X25!),pk(X26!)},{pk(X27!),pk(X28!)}},{{pk(X29!),pk(X30!)},{pk(X31!),pk(X32!)}}}}},{{{{{pk(X33!),pk(X34!)},{pk(X35!),pk(X36!)}},{{pk(X37!),pk(X38!)},{pk(X39!),pk(X40!)}}},{{{pk(X41!),pk(X42!)},{pk(X43!),pk(X44!)}},{{pk(X45!),pk(X46!)},{pk(X47!),pk(X48!)}}}},{{{{pk(X49!),pk(X50!)},{pk(X51!),pk(X52!)}},{{pk(X53!),pk(X54!)},{pk(X55!),pk(X56!)}}},{{{pk(X57!),pk(X58!)},{pk(X59!),pk(X60!)}},{{pk(X61!),pk(X62!)},{pk(X63!),pk(X64!)}}}}}},{{{{{{pk(X65!),pk(X66!)},{pk(X67!),pk(X68!)}},{{pk(X69!),pk(X70!)},{pk(X71!),pk(X72!)}}},{{{pk(X73!),pk(X74!)},{pk(X75!),pk(X76!)}},{{pk(X77!),pk(X78!)},{pk(X79!),pk(X80!)}}}},{{{{pk(X81!),pk(X82!)},{pk(X83!),pk(X84!)}},{{pk(X85!),pk(X86!)},{pk(X87!),pk(X88!)}}},{{{pk(X89!),pk(X90!)},{pk(X91!),pk(X92!)}},{{pk(X93!),pk(X94!)},{pk(X95!),pk(X96!)}}}}},{{{{{pk(X97!),pk(X98!)},{pk(X99!),pk(X100!)}},{{pk(X101!),pk(X102!)},{pk(X103!),pk(X104!)}}},{{{pk(X105!),pk(X106!)},{pk(X107!),pk(X108!)}},{{pk(X109!),pk(X110!)},{pk(X111!),pk(X112!)}}}},{{{{pk(X113!),pk(X114!)},{pk(X115!),pk(X116!)}},{{pk(X117!),pk(X118!)},{pk(X119!),pk(X120!)}}},{{{pk(X121!),pk(X122!)},{pk(X123!),pk(X124!)}},{{pk(X125!),pk(X126!)},{pk(X127!),pk(X128!)}}}}}}})"); - - // Misc tests for other descriptors that we support - // Keys - test_desc::test_desc_satisfy(cl, testdata, "wpkh(K)"); - test_desc::test_desc_satisfy(cl, testdata, "pkh(K)"); - test_desc::test_desc_satisfy(cl, testdata, "sh(wpkh(K))"); - - // sorted multi - test_desc::test_desc_satisfy(cl, testdata, "sh(sortedmulti(2,K1,K2,K3))"); - test_desc::test_desc_satisfy(cl, testdata, "wsh(sortedmulti(2,K1,K2,K3))"); - test_desc::test_desc_satisfy(cl, testdata, "sh(wsh(sortedmulti(2,K1,K2,K3)))"); - - // Miniscripts - test_desc::test_desc_satisfy(cl, testdata, "sh(and_v(v:pk(K1),pk(K2)))"); - test_desc::test_desc_satisfy(cl, testdata, "wsh(and_v(v:pk(K1),pk(K2)))"); - test_desc::test_desc_satisfy(cl, testdata, "sh(wsh(and_v(v:pk(K1),pk(K2))))"); -} diff --git a/tests/setup/mod.rs b/tests/setup/mod.rs new file mode 100644 index 000000000..9ff0eff13 --- /dev/null +++ b/tests/setup/mod.rs @@ -0,0 +1,29 @@ +extern crate miniscript; + +use bitcoind::bitcoincore_rpc::RpcApi; +use bitcoind::BitcoinD; +use miniscript::bitcoin; + +pub mod test_util; + +// Launch an instance of bitcoind with +pub fn setup() -> BitcoinD { + let exe_path = bitcoind::exe_path().unwrap(); + let bitcoind = bitcoind::BitcoinD::new(exe_path).unwrap(); + let cl = &bitcoind.client; + // generate to an address by the wallet. And wait for funds to mature + let addr = cl.get_new_address(None, None).unwrap(); + let blks = cl.generate_to_address(101, &addr).unwrap(); + assert_eq!(blks.len(), 101); + + assert_eq!( + cl.get_balance(Some(1) /*min conf*/, None).unwrap(), + bitcoin::Amount::from_sat(100_000_000 * 50) + ); + bitcoind +} + +#[test] +fn test_setup() { + setup(); +} diff --git a/integration_test/src/test_util.rs b/tests/setup/test_util.rs similarity index 96% rename from integration_test/src/test_util.rs rename to tests/setup/test_util.rs index 145a98f16..019b7c179 100644 --- a/integration_test/src/test_util.rs +++ b/tests/setup/test_util.rs @@ -17,14 +17,15 @@ //! The keys/hashes are automatically translated so that the tests knows how to satisfy things that don't end with ! //! -use bitcoin::hashes::{hex::ToHex, Hash}; -use miniscript::descriptor::{SinglePub, SinglePubKey}; -use miniscript::{Descriptor, DescriptorPublicKey, Miniscript, ScriptContext, TranslatePk}; -use rand::RngCore; use std::str::FromStr; -use bitcoin::hashes::{hash160, ripemd160, sha256, sha256d}; +use actual_rand as rand; +use bitcoin::hashes::hex::ToHex; +use bitcoin::hashes::{hash160, ripemd160, sha256, sha256d, Hash}; use bitcoin::secp256k1; +use miniscript::descriptor::{SinglePub, SinglePubKey}; +use miniscript::{Descriptor, DescriptorPublicKey, Miniscript, ScriptContext, TranslatePk}; +use rand::RngCore; #[derive(Clone, Debug)] pub struct PubData { @@ -142,6 +143,8 @@ pub fn random_pk(mut seed: u8) -> bitcoin::PublicKey { } } +#[allow(dead_code)] +// https://github.com/rust-lang/rust/issues/46379. The code is pub fn and integration test, but still shows warnings /// Parse an insane miniscript into a miniscript with the format described above at file header pub fn parse_insane_ms( ms: &str, @@ -213,6 +216,8 @@ pub fn parse_insane_ms( ms } +#[allow(dead_code)] +// https://github.com/rust-lang/rust/issues/46379. The code is pub fn and integration test, but still shows warnings pub fn parse_test_desc(desc: &str, pubdata: &PubData) -> Descriptor { let desc = subs_hash_frag(desc, pubdata); let desc = diff --git a/integration_test/src/test_cpp.rs b/tests/test_cpp.rs similarity index 96% rename from integration_test/src/test_cpp.rs rename to tests/test_cpp.rs index 2e6e8ab46..70e7f0daa 100644 --- a/integration_test/src/test_cpp.rs +++ b/tests/test_cpp.rs @@ -4,23 +4,22 @@ //! which we know how to satisfy //! +use std::collections::BTreeMap; +use std::fs::File; +use std::io::{self, BufRead}; +use std::path::Path; + use bitcoin::secp256k1::{self, Secp256k1}; use bitcoin::util::psbt; use bitcoin::util::psbt::PartiallySignedTransaction as Psbt; use bitcoin::{self, Amount, OutPoint, Transaction, TxIn, TxOut, Txid}; -use bitcoincore_rpc::{json, Client, RpcApi}; +use bitcoind::bitcoincore_rpc::{json, Client, RpcApi}; use miniscript::miniscript::iter; use miniscript::psbt::PsbtExt; -use miniscript::MiniscriptKey; -use miniscript::Segwitv0; -use miniscript::{Descriptor, Miniscript}; -use std::collections::BTreeMap; -use std::fs::File; -use std::io::{self, BufRead}; -use std::path::Path; +use miniscript::{Descriptor, Miniscript, MiniscriptKey, Segwitv0}; -use super::test_util::PubData; -use crate::test_util::{self, TestData}; +mod setup; +use setup::test_util::{self, PubData, TestData}; // parse ~30 miniscripts from file pub(crate) fn parse_miniscripts( @@ -241,3 +240,10 @@ pub fn test_from_cpp_ms(cl: &Client, testdata: &TestData) { assert!(num_conf > 0); } } + +#[test] +fn tests_from_cpp() { + let cl = &setup::setup().client; + let testdata = TestData::new_fixed_data(50); + test_from_cpp_ms(cl, &testdata); +} diff --git a/integration_test/src/test_desc.rs b/tests/test_desc.rs similarity index 62% rename from integration_test/src/test_desc.rs rename to tests/test_desc.rs index 789a34647..d522c335f 100644 --- a/integration_test/src/test_desc.rs +++ b/tests/test_desc.rs @@ -4,22 +4,24 @@ //! which we know how to satisfy //! +use std::collections::BTreeMap; + use bitcoin::blockdata::witness::Witness; -use bitcoin::secp256k1; use bitcoin::util::psbt::PartiallySignedTransaction as Psbt; use bitcoin::util::sighash::SighashCache; use bitcoin::util::taproot::{LeafVersion, TapLeafHash}; use bitcoin::util::{psbt, sighash}; -use bitcoin::{self, Amount, OutPoint, SchnorrSig, Script, Transaction, TxIn, TxOut, Txid}; -use bitcoincore_rpc::{json, Client, RpcApi}; +use bitcoin::{ + self, secp256k1, Amount, OutPoint, SchnorrSig, Script, Transaction, TxIn, TxOut, Txid, +}; +use bitcoind::bitcoincore_rpc::{json, Client, RpcApi}; use miniscript::miniscript::iter; use miniscript::psbt::{PsbtExt, PsbtInputExt}; -use miniscript::{Descriptor, Miniscript, ToPublicKey}; -use miniscript::{MiniscriptKey, ScriptContext}; -use std::collections::BTreeMap; +use miniscript::{Descriptor, Miniscript, MiniscriptKey, ScriptContext, ToPublicKey}; -use crate::test_util::{self, TestData}; +mod setup; +use setup::test_util::{self, TestData}; /// Quickly create a BTC amount. fn btc>(btc: F) -> Amount { Amount::from_btc(btc.into()).unwrap() @@ -104,7 +106,7 @@ pub fn test_desc_satisfy(cl: &Client, testdata: &TestData, desc: &str) -> Witnes let addr = cl .get_new_address(None, Some(json::AddressType::Bech32)) .unwrap(); - // Had to decrease 'value', so that fees can be increased + // Had to decrease 'value', so that fees can be increased // (Was getting insufficient fees error, for deep script trees) psbt.unsigned_tx.output.push(TxOut { value: 99_997_000, @@ -324,3 +326,75 @@ fn find_sk_single_key(pk: bitcoin::PublicKey, testdata: &TestData) -> Vec Internal key unknown + // Leaf 1 -> pk(X1) with X1 known + // Leaf 2-> and_v(v:pk(X2),pk(X3!)) with partial witness only to X2 known + let wit = test_desc_satisfy(cl, testdata, "tr(X!,{pk(X1),and_v(v:pk(X2),pk(X3!))})"); + assert!(wit.len() == 3); // control block, script and signature + + // Test 4: Force to spend with script spend. Unknown internal key and multiple script paths + // Should select the one with minimum weight + // X! -> Internal key unknown + // Leaf 1 -> pk(X1!) with X1 unknown + // Leaf 2-> and_v(v:pk(X2),pk(X3)) X2 and X3 known + let wit = test_desc_satisfy(cl, testdata, "tr(X!,{pk(X1),and_v(v:pk(X2),pk(X3))})"); + assert!(wit.len() == 3); // control block, script and one signatures + + // Test 5: When everything is available, we should select the key spend path + let wit = test_desc_satisfy(cl, testdata, "tr(X,{pk(X1),and_v(v:pk(X2),pk(X3!))})"); + assert!(wit.len() == 1); // control block, script and signature + + // Test 6: Test the new multi_a opcodes + test_desc_satisfy(cl, testdata, "tr(X!,{pk(X1!),multi_a(1,X2,X3!,X4!,X5!)})"); + test_desc_satisfy(cl, testdata, "tr(X!,{pk(X1!),multi_a(2,X2,X3,X4!,X5!)})"); + test_desc_satisfy(cl, testdata, "tr(X!,{pk(X1!),multi_a(3,X2,X3,X4,X5!)})"); + test_desc_satisfy(cl, testdata, "tr(X!,{pk(X1!),multi_a(4,X2,X3,X4,X5)})"); + + // Test 7: Test script tree of depth 127 is valid, only X128 is known + test_desc_satisfy(cl, testdata, "tr(X!,{pk(X1!),{pk(X2!),{pk(X3!),{pk(X4!),{pk(X5!),{pk(X6!),{pk(X7!),{pk(X8!),{pk(X9!),{pk(X10!),{pk(X11!),{pk(X12!),{pk(X13!),{pk(X14!),{pk(X15!),{pk(X16!),{pk(X17!),{pk(X18!),{pk(X19!),{pk(X20!),{pk(X21!),{pk(X22!),{pk(X23!),{pk(X24!),{pk(X25!),{pk(X26!),{pk(X27!),{pk(X28!),{pk(X29!),{pk(X30!),{pk(X31!),{pk(X32!),{pk(X33!),{pk(X34!),{pk(X35!),{pk(X36!),{pk(X37!),{pk(X38!),{pk(X39!),{pk(X40!),{pk(X41!),{pk(X42!),{pk(X43!),{pk(X44!),{pk(X45!),{pk(X46!),{pk(X47!),{pk(X48!),{pk(X49!),{pk(X50!),{pk(X51!),{pk(X52!),{pk(X53!),{pk(X54!),{pk(X55!),{pk(X56!),{pk(X57!),{pk(X58!),{pk(X59!),{pk(X60!),{pk(X61!),{pk(X62!),{pk(X63!),{pk(X64!),{pk(X65!),{pk(X66!),{pk(X67!),{pk(X68!),{pk(X69!),{pk(X70!),{pk(X71!),{pk(X72!),{pk(X73!),{pk(X74!),{pk(X75!),{pk(X76!),{pk(X77!),{pk(X78!),{pk(X79!),{pk(X80!),{pk(X81!),{pk(X82!),{pk(X83!),{pk(X84!),{pk(X85!),{pk(X86!),{pk(X87!),{pk(X88!),{pk(X89!),{pk(X90!),{pk(X91!),{pk(X92!),{pk(X93!),{pk(X94!),{pk(X95!),{pk(X96!),{pk(X97!),{pk(X98!),{pk(X99!),{pk(X100!),{pk(X101!),{pk(X102!),{pk(X103!),{pk(X104!),{pk(X105!),{pk(X106!),{pk(X107!),{pk(X108!),{pk(X109!),{pk(X110!),{pk(X111!),{pk(X112!),{pk(X113!),{pk(X114!),{pk(X115!),{pk(X116!),{pk(X117!),{pk(X118!),{pk(X119!),{pk(X120!),{pk(X121!),{pk(X122!),{pk(X123!),{pk(X124!),{pk(X125!),{pk(X126!),{pk(X127!),pk(X128)}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}})"); + + // Test 8: Test script tree of depth 128 is valid, only X129 is known + test_desc_satisfy(cl, testdata, "tr(X!,{pk(X1!),{pk(X2!),{pk(X3!),{pk(X4!),{pk(X5!),{pk(X6!),{pk(X7!),{pk(X8!),{pk(X9!),{pk(X10!),{pk(X11!),{pk(X12!),{pk(X13!),{pk(X14!),{pk(X15!),{pk(X16!),{pk(X17!),{pk(X18!),{pk(X19!),{pk(X20!),{pk(X21!),{pk(X22!),{pk(X23!),{pk(X24!),{pk(X25!),{pk(X26!),{pk(X27!),{pk(X28!),{pk(X29!),{pk(X30!),{pk(X31!),{pk(X32!),{pk(X33!),{pk(X34!),{pk(X35!),{pk(X36!),{pk(X37!),{pk(X38!),{pk(X39!),{pk(X40!),{pk(X41!),{pk(X42!),{pk(X43!),{pk(X44!),{pk(X45!),{pk(X46!),{pk(X47!),{pk(X48!),{pk(X49!),{pk(X50!),{pk(X51!),{pk(X52!),{pk(X53!),{pk(X54!),{pk(X55!),{pk(X56!),{pk(X57!),{pk(X58!),{pk(X59!),{pk(X60!),{pk(X61!),{pk(X62!),{pk(X63!),{pk(X64!),{pk(X65!),{pk(X66!),{pk(X67!),{pk(X68!),{pk(X69!),{pk(X70!),{pk(X71!),{pk(X72!),{pk(X73!),{pk(X74!),{pk(X75!),{pk(X76!),{pk(X77!),{pk(X78!),{pk(X79!),{pk(X80!),{pk(X81!),{pk(X82!),{pk(X83!),{pk(X84!),{pk(X85!),{pk(X86!),{pk(X87!),{pk(X88!),{pk(X89!),{pk(X90!),{pk(X91!),{pk(X92!),{pk(X93!),{pk(X94!),{pk(X95!),{pk(X96!),{pk(X97!),{pk(X98!),{pk(X99!),{pk(X100!),{pk(X101!),{pk(X102!),{pk(X103!),{pk(X104!),{pk(X105!),{pk(X106!),{pk(X107!),{pk(X108!),{pk(X109!),{pk(X110!),{pk(X111!),{pk(X112!),{pk(X113!),{pk(X114!),{pk(X115!),{pk(X116!),{pk(X117!),{pk(X118!),{pk(X119!),{pk(X120!),{pk(X121!),{pk(X122!),{pk(X123!),{pk(X124!),{pk(X125!),{pk(X126!),{pk(X127!),{pk(X128!),pk(X129)}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}})"); + + // Test 9: Test script complete tree having 128 leaves with depth log(128), only X1 is known + test_desc_satisfy(cl, testdata, "tr(X!,{{{{{{{pk(X1),pk(X2!)},{pk(X3!),pk(X4!)}},{{pk(X5!),pk(X6!)},{pk(X7!),pk(X8!)}}},{{{pk(X9!),pk(X10!)},{pk(X11!),pk(X12!)}},{{pk(X13!),pk(X14!)},{pk(X15!),pk(X16!)}}}},{{{{pk(X17!),pk(X18!)},{pk(X19!),pk(X20!)}},{{pk(X21!),pk(X22!)},{pk(X23!),pk(X24!)}}},{{{pk(X25!),pk(X26!)},{pk(X27!),pk(X28!)}},{{pk(X29!),pk(X30!)},{pk(X31!),pk(X32!)}}}}},{{{{{pk(X33!),pk(X34!)},{pk(X35!),pk(X36!)}},{{pk(X37!),pk(X38!)},{pk(X39!),pk(X40!)}}},{{{pk(X41!),pk(X42!)},{pk(X43!),pk(X44!)}},{{pk(X45!),pk(X46!)},{pk(X47!),pk(X48!)}}}},{{{{pk(X49!),pk(X50!)},{pk(X51!),pk(X52!)}},{{pk(X53!),pk(X54!)},{pk(X55!),pk(X56!)}}},{{{pk(X57!),pk(X58!)},{pk(X59!),pk(X60!)}},{{pk(X61!),pk(X62!)},{pk(X63!),pk(X64!)}}}}}},{{{{{{pk(X65!),pk(X66!)},{pk(X67!),pk(X68!)}},{{pk(X69!),pk(X70!)},{pk(X71!),pk(X72!)}}},{{{pk(X73!),pk(X74!)},{pk(X75!),pk(X76!)}},{{pk(X77!),pk(X78!)},{pk(X79!),pk(X80!)}}}},{{{{pk(X81!),pk(X82!)},{pk(X83!),pk(X84!)}},{{pk(X85!),pk(X86!)},{pk(X87!),pk(X88!)}}},{{{pk(X89!),pk(X90!)},{pk(X91!),pk(X92!)}},{{pk(X93!),pk(X94!)},{pk(X95!),pk(X96!)}}}}},{{{{{pk(X97!),pk(X98!)},{pk(X99!),pk(X100!)}},{{pk(X101!),pk(X102!)},{pk(X103!),pk(X104!)}}},{{{pk(X105!),pk(X106!)},{pk(X107!),pk(X108!)}},{{pk(X109!),pk(X110!)},{pk(X111!),pk(X112!)}}}},{{{{pk(X113!),pk(X114!)},{pk(X115!),pk(X116!)}},{{pk(X117!),pk(X118!)},{pk(X119!),pk(X120!)}}},{{{pk(X121!),pk(X122!)},{pk(X123!),pk(X124!)}},{{pk(X125!),pk(X126!)},{pk(X127!),pk(X128!)}}}}}}})"); + + // Misc tests for other descriptors that we support + // Keys + test_desc_satisfy(cl, testdata, "wpkh(K)"); + test_desc_satisfy(cl, testdata, "pkh(K)"); + test_desc_satisfy(cl, testdata, "sh(wpkh(K))"); + + // sorted multi + test_desc_satisfy(cl, testdata, "sh(sortedmulti(2,K1,K2,K3))"); + test_desc_satisfy(cl, testdata, "wsh(sortedmulti(2,K1,K2,K3))"); + test_desc_satisfy(cl, testdata, "sh(wsh(sortedmulti(2,K1,K2,K3)))"); + + // Miniscripts + test_desc_satisfy(cl, testdata, "sh(and_v(v:pk(K1),pk(K2)))"); + test_desc_satisfy(cl, testdata, "wsh(and_v(v:pk(K1),pk(K2)))"); + test_desc_satisfy(cl, testdata, "sh(wsh(and_v(v:pk(K1),pk(K2))))"); +} + +#[test] +fn test_satisfy() { + let testdata = TestData::new_fixed_data(50); + let cl = &setup::setup().client; + test_descs(cl, &testdata); +}