From 968a7d17a02bc776c38274fc9e61235163c22442 Mon Sep 17 00:00:00 2001 From: Antoine Poinsot Date: Thu, 17 Nov 2022 16:49:08 +0100 Subject: [PATCH] daemon: rename Minisafe to Liana --- .cirrus.yml | 4 +- .github/workflows/main.yml | 2 +- Cargo.lock | 36 ++-- Cargo.toml | 10 +- LICENCE | 2 +- src/bin/cli.rs | 10 +- src/bin/daemon.rs | 4 +- src/commands/mod.rs | 12 +- src/config.rs | 20 +- src/database/mod.rs | 2 +- src/database/sqlite/mod.rs | 4 +- src/jsonrpc/server.rs | 16 +- src/lib.rs | 18 +- src/testutils.rs | 10 +- tests/README.md | 4 +- tests/fixtures.py | 18 +- tests/test_chain.py | 132 ++++++------ tests/test_framework/bitcoind.py | 2 +- .../{minisafed.py => lianad.py} | 12 +- tests/test_framework/utils.py | 14 +- tests/test_misc.py | 2 +- tests/test_rpc.py | 196 +++++++++--------- tests/test_spend.py | 30 +-- 23 files changed, 280 insertions(+), 280 deletions(-) rename tests/test_framework/{minisafed.py => lianad.py} (96%) diff --git a/.cirrus.yml b/.cirrus.yml index 311ccf056..95f3413f6 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -31,7 +31,7 @@ task: fingerprint_script: - rustc --version - cat Cargo.lock - minisafed_build_script: cargo build --release + lianad_build_script: cargo build --release deps_script: apt update && apt install -y python3 python3-pip @@ -50,6 +50,6 @@ task: export BITCOIND_PATH=bitcoin-24.0rc1/bin/bitcoind # Run the functional tests - MINISAFED_PATH=$PWD/target/release/minisafed pytest $TEST_GROUP -vvv -n 2 + LIANAD_PATH=$PWD/target/release/lianad pytest $TEST_GROUP -vvv -n 2 before_cache_script: rm -rf $CARGO_HOME/registry/index diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2e83b210c..37c35488d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -26,7 +26,7 @@ jobs: - nightly os: - ubuntu-latest - # See issue https://github.com/revault/minisafe/issues/69 + # See issue https://github.com/revault/liana/issues/69 #- macOS-latest - windows-latest runs-on: ${{ matrix.os }} diff --git a/Cargo.lock b/Cargo.lock index 7559b5095..169a45793 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -203,6 +203,24 @@ dependencies = [ "serde_json", ] +[[package]] +name = "liana" +version = "0.0.1" +dependencies = [ + "backtrace", + "base64", + "dirs", + "fern", + "jsonrpc", + "libc", + "log", + "miniscript", + "rusqlite", + "serde", + "serde_json", + "toml", +] + [[package]] name = "libc" version = "0.2.135" @@ -235,24 +253,6 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" -[[package]] -name = "minisafe" -version = "0.0.1" -dependencies = [ - "backtrace", - "base64", - "dirs", - "fern", - "jsonrpc", - "libc", - "log", - "miniscript", - "rusqlite", - "serde", - "serde_json", - "toml", -] - [[package]] name = "miniscript" version = "8.0.0" diff --git a/Cargo.toml b/Cargo.toml index 36033c173..3313d8aea 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,21 +1,21 @@ [package] -name = "minisafe" +name = "liana" version = "0.0.1" authors = ["Antoine Poinsot "] edition = "2018" -repository = "https://github.com/revault/minisafed" +repository = "https://github.com/revault/liana" license-file = "LICENCE" keywords = ["bitcoin", "wallet", "safe", "script", "miniscript", "inheritance", "recovery"] -description = "Minisafe wallet daemon" +description = "Liana wallet daemon" exclude = [".github/", ".cirrus.yml", "tests/", "test_data/", "contrib/", "pyproject.toml"] [[bin]] -name = "minisafed" +name = "lianad" path = "src/bin/daemon.rs" required-features = ["jsonrpc_server"] [[bin]] -name = "minisafe-cli" +name = "liana-cli" path = "src/bin/cli.rs" required-features = ["jsonrpc_server"] diff --git a/LICENCE b/LICENCE index 5f3bb754b..f7885c8ef 100644 --- a/LICENCE +++ b/LICENCE @@ -1,6 +1,6 @@ BSD 3-Clause License -Copyright (c) 2022, The Minisafe developers +Copyright (c) 2022, The Liana developers All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/src/bin/cli.rs b/src/bin/cli.rs index 38c6f569c..5841c7c36 100644 --- a/src/bin/cli.rs +++ b/src/bin/cli.rs @@ -1,4 +1,4 @@ -use minisafe::config::{config_folder_path, Config}; +use liana::config::{config_folder_path, Config}; use std::{ env, @@ -14,7 +14,7 @@ use std::os::unix::net::UnixStream; // Exits with error fn show_usage() { eprintln!("Usage:"); - eprintln!(" minisafe-cli [--conf conf_path] [--raw] [ ...]"); + eprintln!(" liana-cli [--conf conf_path] [--raw] [ ...]"); process::exit(1); } @@ -73,7 +73,7 @@ fn rpc_request(method: String, params: Vec) -> Json { object.insert("jsonrpc".to_string(), Json::String("2.0".to_string())); object.insert( "id".to_string(), - Json::String(format!("minisafe-cli-{}", process::id())), + Json::String(format!("liana-cli-{}", process::id())), ); object.insert("method".to_string(), method); object.insert("params".to_string(), params); @@ -94,7 +94,7 @@ fn socket_file(conf_file: Option) -> PathBuf { [ data_dir, config.bitcoin_config.network.to_string().as_str(), - "minisafed_rpc", + "lianad_rpc", ] .iter() .collect() @@ -160,7 +160,7 @@ fn main() { println!("{:#}", serde_json::json!({ "error": e })); } else { log::warn!( - "minisafed response doesn't contain result or error: '{}'", + "lianad response doesn't contain result or error: '{}'", response ); println!("{:#}", response); diff --git a/src/bin/daemon.rs b/src/bin/daemon.rs index 13e7b3669..7aeae860b 100644 --- a/src/bin/daemon.rs +++ b/src/bin/daemon.rs @@ -5,7 +5,7 @@ use std::{ process, thread, time, }; -use minisafe::{config::Config, DaemonHandle}; +use liana::{config::Config, DaemonHandle}; fn parse_args(args: Vec) -> Option { if args.len() == 1 { @@ -61,7 +61,7 @@ fn main() { let daemon = DaemonHandle::start_default(config).unwrap_or_else(|e| { // The panic hook will log::error - panic!("Starting Minisafe daemon: {}", e); + panic!("Starting Liana daemon: {}", e); }); daemon .rpc_server() diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 9f54de367..755b9e5fa 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -1,6 +1,6 @@ -//! # Minisafe commands +//! # Liana commands //! -//! External interface to the Minisafe daemon. +//! External interface to the Liana daemon. mod utils; @@ -632,7 +632,7 @@ mod tests { #[test] fn getinfo() { - let ms = DummyMinisafe::new(); + let ms = DummyLiana::new(); // We can query getinfo ms.handle.control.get_info(); ms.shutdown(); @@ -640,7 +640,7 @@ mod tests { #[test] fn getnewaddress() { - let ms = DummyMinisafe::new(); + let ms = DummyLiana::new(); let control = &ms.handle.control; // We can get an address @@ -661,7 +661,7 @@ mod tests { #[test] fn create_spend() { - let ms = DummyMinisafe::new(); + let ms = DummyLiana::new(); let control = &ms.handle.control; // Arguments sanity checking @@ -777,7 +777,7 @@ mod tests { #[test] fn update_spend() { - let ms = DummyMinisafe::new(); + let ms = DummyLiana::new(); let control = &ms.handle.control; let mut db_conn = control.db().lock().unwrap().connection(); diff --git a/src/config.rs b/src/config.rs index 347ee76c5..9e6b288d0 100644 --- a/src/config.rs +++ b/src/config.rs @@ -144,11 +144,11 @@ impl From for ConfigError { impl std::error::Error for ConfigError {} -/// Get the absolute path to the minisafe configuration folder. +/// Get the absolute path to the liana configuration folder. /// -/// It's a "minisafe//" directory in the XDG standard configuration directory for -/// all OSes but Linux-based ones, for which it's `~/.minisafe//`. -/// There is only one config file at `minisafe/config.toml`, which specifies the network. +/// It's a "liana//" directory in the XDG standard configuration directory for +/// all OSes but Linux-based ones, for which it's `~/.liana//`. +/// There is only one config file at `liana/config.toml`, which specifies the network. /// Rationale: we want to have the database, RPC socket, etc.. in the same folder as the /// configuration file but for Linux the XDG specifoes a data directory (`~/.local/share/`) /// different from the configuration one (`~/.config/`). @@ -161,10 +161,10 @@ pub fn config_folder_path() -> Option { if let Some(mut path) = configs_dir { #[cfg(target_os = "linux")] - path.push(".minisafe"); + path.push(".liana"); #[cfg(not(target_os = "linux"))] - path.push("Minisafe"); + path.push("Liana"); return Some(path); } @@ -174,7 +174,7 @@ pub fn config_folder_path() -> Option { fn config_file_path() -> Option { config_folder_path().map(|mut path| { - path.push("minisafe.toml"); + path.push("liana.toml"); path }) } @@ -306,17 +306,17 @@ mod tests { #[cfg(target_os = "linux")] { assert!(filepath.as_path().starts_with("/home/")); - assert!(filepath.as_path().ends_with(".minisafe/minisafe.toml")); + assert!(filepath.as_path().ends_with(".liana/liana.toml")); } #[cfg(target_os = "macos")] assert!(filepath .as_path() - .ends_with("Library/Application Support/Minisafe/minisafe.toml")); + .ends_with("Library/Application Support/Liana/liana.toml")); #[cfg(target_os = "windows")] assert!(filepath .as_path() - .ends_with(r#"AppData\Roaming\Minisafe\minisafe.toml"#)); + .ends_with(r#"AppData\Roaming\Liana\liana.toml"#)); } } diff --git a/src/database/mod.rs b/src/database/mod.rs index 095fe40fb..acdfb3190 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -1,4 +1,4 @@ -///! Database interface for Minisafe. +///! Database interface for Liana. ///! ///! Record wallet metadata, spent and unspent coins, ongoing transactions. pub mod sqlite; diff --git a/src/database/sqlite/mod.rs b/src/database/sqlite/mod.rs index b11d8f3d9..865dea963 100644 --- a/src/database/sqlite/mod.rs +++ b/src/database/sqlite/mod.rs @@ -563,7 +563,7 @@ mod tests { fs::create_dir_all(&tmp_dir).unwrap(); let secp = secp256k1::Secp256k1::verification_only(); - let db_path: path::PathBuf = [tmp_dir.as_path(), path::Path::new("minisafed.sqlite3")] + let db_path: path::PathBuf = [tmp_dir.as_path(), path::Path::new("lianad.sqlite3")] .iter() .collect(); let options = dummy_options(); @@ -578,7 +578,7 @@ mod tests { fs::create_dir_all(&tmp_dir).unwrap(); let secp = secp256k1::Secp256k1::verification_only(); - let db_path: path::PathBuf = [tmp_dir.as_path(), path::Path::new("minisafed.sqlite3")] + let db_path: path::PathBuf = [tmp_dir.as_path(), path::Path::new("lianad.sqlite3")] .iter() .collect(); assert!(SqliteDb::new(db_path.clone(), None, &secp) diff --git a/src/jsonrpc/server.rs b/src/jsonrpc/server.rs index b281b0a2c..d39fe98a8 100644 --- a/src/jsonrpc/server.rs +++ b/src/jsonrpc/server.rs @@ -101,7 +101,7 @@ fn connection_handler( let req_id = req.id.clone(); if &req.method == "stop" { shutdown.store(true, atomic::Ordering::Relaxed); - log::info!("Stopping the minisafe daemon."); + log::info!("Stopping the liana daemon."); } log::trace!("JSONRPC request: {:?}", serde_json::to_string(&req)); @@ -146,7 +146,7 @@ pub fn rpcserver_loop( let handler_id = connections_counter.load(atomic::Ordering::Relaxed); thread::Builder::new() - .name(format!("minisafe-jsonrpc-{}", handler_id)) + .name(format!("liana-jsonrpc-{}", handler_id)) .spawn({ let control = daemon_control.clone(); let counter = connections_counter.clone(); @@ -260,7 +260,7 @@ mod tests { #[test] fn command_read_single() { let socket_path = env::temp_dir().join(format!( - "minisafed-jsonrpc-socket-{}-{:?}", + "lianad-jsonrpc-socket-{}-{:?}", process::id(), thread::current().id() )); @@ -287,7 +287,7 @@ mod tests { #[test] fn command_read_parts() { let socket_path = env::temp_dir().join(format!( - "minisafed-jsonrpc-socket-{}-{:?}", + "lianad-jsonrpc-socket-{}-{:?}", process::id(), thread::current().id() )); @@ -320,7 +320,7 @@ mod tests { #[test] fn command_read_multiple() { let socket_path = env::temp_dir().join(format!( - "minisafed-jsonrpc-socket-{}-{:?}", + "lianad-jsonrpc-socket-{}-{:?}", process::id(), thread::current().id() )); @@ -367,7 +367,7 @@ mod tests { #[test] fn command_read_linebreak() { let socket_path = env::temp_dir().join(format!( - "minisafed-jsonrpc-socket-{}-{:?}", + "lianad-jsonrpc-socket-{}-{:?}", process::id(), thread::current().id() )); @@ -400,12 +400,12 @@ mod tests { #[cfg(not(target_os = "macos"))] #[test] fn server_sanity_check() { - let ms = DummyMinisafe::new(); + let ms = DummyLiana::new(); let socket_path: path::PathBuf = [ ms.tmp_dir.as_path(), path::Path::new("d"), path::Path::new("bitcoin"), - path::Path::new("minisafed_rpc"), + path::Path::new("lianad_rpc"), ] .iter() .collect(); diff --git a/src/lib.rs b/src/lib.rs index 2c7d8cc85..9daf12586 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -163,7 +163,7 @@ fn setup_sqlite( fresh_data_dir: bool, secp: &secp256k1::Secp256k1, ) -> Result { - let db_path: path::PathBuf = [data_dir, path::Path::new("minisafed.sqlite3")] + let db_path: path::PathBuf = [data_dir, path::Path::new("lianad.sqlite3")] .iter() .collect(); let options = if fresh_data_dir { @@ -189,7 +189,7 @@ fn setup_bitcoind( fresh_data_dir: bool, ) -> Result { // Now set up the bitcoind interface - let wo_path: path::PathBuf = [data_dir, path::Path::new("minisafed_watchonly_wallet")] + let wo_path: path::PathBuf = [data_dir, path::Path::new("lianad_watchonly_wallet")] .iter() .collect(); let bitcoind = BitcoinD::new( @@ -247,7 +247,7 @@ pub struct DaemonHandle { } impl DaemonHandle { - /// This starts the Minisafe daemon. Call `shutdown` to shut it down. + /// This starts the Liana daemon. Call `shutdown` to shut it down. /// /// You may specify a custom Bitcoin interface through the `bitcoin` parameter. If `None`, the /// default Bitcoin interface (`bitcoind` JSONRPC) will be used. @@ -329,7 +329,7 @@ impl DaemonHandle { }) } - /// Start the Minisafe daemon with the default Bitcoin and database interfaces (`bitcoind` RPC + /// Start the Liana daemon with the default Bitcoin and database interfaces (`bitcoind` RPC /// and SQLite). pub fn start_default(config: Config) -> Result { DaemonHandle::start(config, Option::::None, Option::::None) @@ -351,7 +351,7 @@ impl DaemonHandle { .expect("Didn't fail at startup, must not now") .as_path(), path::Path::new(&control.config.bitcoin_config.network.to_string()), - path::Path::new("minisafed_rpc"), + path::Path::new("lianad_rpc"), ] .iter() .collect(); @@ -367,12 +367,12 @@ impl DaemonHandle { } // NOTE: this moves out the data as it should not be reused after shutdown - /// Shut down the Minisafe daemon. + /// Shut down the Liana daemon. pub fn shutdown(self) { self.bitcoin_poller.stop(); } - // We need a shutdown utility that does not move for implementing Drop for the DummyMinisafe + // We need a shutdown utility that does not move for implementing Drop for the DummyLiana #[cfg(test)] pub fn test_shutdown(&mut self) { self.bitcoin_poller.test_stop(); @@ -553,7 +553,7 @@ mod tests { } // TODO: we could move the dummy bitcoind thread stuff to the bitcoind module to test the - // bitcoind interface, and use the DummyMinisafe from testutils to sanity check the startup. + // bitcoind interface, and use the DummyLiana from testutils to sanity check the startup. // Note that startup as checked by this unit test is also tested in the functional test // framework. #[test] @@ -566,7 +566,7 @@ mod tests { let wo_path: path::PathBuf = [ data_dir.as_path(), path::Path::new("bitcoin"), - path::Path::new("minisafed_watchonly_wallet"), + path::Path::new("lianad_watchonly_wallet"), ] .iter() .collect(); diff --git a/src/testutils.rs b/src/testutils.rs index 51933dc17..745d4a2eb 100644 --- a/src/testutils.rs +++ b/src/testutils.rs @@ -286,7 +286,7 @@ impl DatabaseConnection for DummyDbConn { } } -pub struct DummyMinisafe { +pub struct DummyLiana { pub tmp_dir: path::PathBuf, pub handle: DaemonHandle, } @@ -302,15 +302,15 @@ fn uid() -> usize { pub fn tmp_dir() -> path::PathBuf { env::temp_dir().join(format!( - "minisafed-{}-{:?}-{}", + "lianad-{}-{:?}-{}", process::id(), thread::current().id(), uid(), )) } -impl DummyMinisafe { - pub fn new() -> DummyMinisafe { +impl DummyLiana { + pub fn new() -> DummyLiana { let tmp_dir = tmp_dir(); fs::create_dir_all(&tmp_dir).unwrap(); // Use a shorthand for 'datadir', to avoid overflowing SUN_LEN on MacOS. @@ -338,7 +338,7 @@ impl DummyMinisafe { let db = sync::Arc::from(sync::RwLock::from(DummyDb::new())); let handle = DaemonHandle::start(config, Some(DummyBitcoind {}), Some(db)).unwrap(); - DummyMinisafe { tmp_dir, handle } + DummyLiana { tmp_dir, handle } } #[cfg(feature = "jsonrpc_server")] diff --git a/tests/README.md b/tests/README.md index 5f0008c79..d6c2830d8 100644 --- a/tests/README.md +++ b/tests/README.md @@ -1,6 +1,6 @@ -## Minisafed blackbox tests +## Lianad blackbox tests -Here we test `minisafed` by starting it on a regression testing Bitcoin network, +Here we test `lianad` by starting it on a regression testing Bitcoin network, and by then talking to it as an user would, from the outside. Python scripts are used for the automation, and specifically the [`pytest` framework](https://docs.pytest.org/en/stable/index.html). diff --git a/tests/fixtures.py b/tests/fixtures.py index 2a7bbe5b6..1d5beaf51 100644 --- a/tests/fixtures.py +++ b/tests/fixtures.py @@ -3,7 +3,7 @@ from concurrent import futures from ephemeral_port_reserve import reserve from test_framework.bitcoind import Bitcoind -from test_framework.minisafed import Minisafed +from test_framework.lianad import Lianad from test_framework.utils import ( EXECUTOR_WORKERS, ) @@ -24,7 +24,7 @@ def test_base_dir(): d = os.getenv("TEST_DIR", "/tmp") - directory = tempfile.mkdtemp(prefix="minisafed-tests-", dir=d) + directory = tempfile.mkdtemp(prefix="lianad-tests-", dir=d) print("Running tests in {}".format(directory)) yield directory @@ -114,8 +114,8 @@ def bitcoind(directory): @pytest.fixture -def minisafed(bitcoind, directory): - datadir = os.path.join(directory, "minisafed") +def lianad(bitcoind, directory): + datadir = os.path.join(directory, "lianad") os.makedirs(datadir, exist_ok=True) bitcoind_cookie = os.path.join(bitcoind.bitcoin_dir, "regtest", ".cookie") @@ -123,7 +123,7 @@ def minisafed(bitcoind, directory): owner_xpub = owner_hd.get_xpub() main_desc = Descriptor.from_str(f"wsh(or_d(pk({owner_xpub}/<0;1>/*),and_v(v:pkh(tpubD9vQiBdDxYzU4cVFtApWj4devZrvcfWaPXX1zHdDc7GPfUsDKqGnbhraccfm7BAXgRgUbVQUV2v2o4NitjGEk7hpbuP85kvBrD4ahFDtNBJ/<0;1>/*),older(65000))))") - minisafed = Minisafed( + lianad = Lianad( datadir, owner_hd, main_desc, @@ -132,10 +132,10 @@ def minisafed(bitcoind, directory): ) try: - minisafed.start() - yield minisafed + lianad.start() + yield lianad except Exception: - minisafed.cleanup() + lianad.cleanup() raise - minisafed.cleanup() + lianad.cleanup() diff --git a/tests/test_chain.py b/tests/test_chain.py index e23987d8e..6d54ae1b4 100644 --- a/tests/test_chain.py +++ b/tests/test_chain.py @@ -4,88 +4,88 @@ from test_framework.utils import wait_for, get_txid, spend_coins -def get_coin(minisafed, outpoint_or_txid): +def get_coin(lianad, outpoint_or_txid): return next( c - for c in minisafed.rpc.listcoins()["coins"] + for c in lianad.rpc.listcoins()["coins"] if outpoint_or_txid in c["outpoint"] ) -def test_reorg_detection(minisafed, bitcoind): +def test_reorg_detection(lianad, bitcoind): """Test we detect block chain reorganization under various conditions.""" initial_height = bitcoind.rpc.getblockcount() - wait_for(lambda: minisafed.rpc.getinfo()["blockheight"] == initial_height) + wait_for(lambda: lianad.rpc.getinfo()["blockheight"] == initial_height) # Re-mine the last block. We should detect it as a reorg. bitcoind.invalidate_remine(initial_height) - minisafed.wait_for_logs( + lianad.wait_for_logs( ["Block chain reorganization detected.", "Tip was rolled back."] ) - wait_for(lambda: minisafed.rpc.getinfo()["blockheight"] == initial_height) + wait_for(lambda: lianad.rpc.getinfo()["blockheight"] == initial_height) # Same if we re-mine the next-to-last block. bitcoind.invalidate_remine(initial_height - 1) - minisafed.wait_for_logs( + lianad.wait_for_logs( ["Block chain reorganization detected.", "Tip was rolled back."] ) - wait_for(lambda: minisafed.rpc.getinfo()["blockheight"] == initial_height) + wait_for(lambda: lianad.rpc.getinfo()["blockheight"] == initial_height) # Same if we re-mine a deep block. bitcoind.invalidate_remine(initial_height - 50) - minisafed.wait_for_logs( + lianad.wait_for_logs( ["Block chain reorganization detected.", "Tip was rolled back."] ) - wait_for(lambda: minisafed.rpc.getinfo()["blockheight"] == initial_height) + wait_for(lambda: lianad.rpc.getinfo()["blockheight"] == initial_height) # Same if the new chain is longer. bitcoind.simple_reorg(initial_height - 10, shift=20) - minisafed.wait_for_logs( + lianad.wait_for_logs( ["Block chain reorganization detected.", "Tip was rolled back."] ) - wait_for(lambda: minisafed.rpc.getinfo()["blockheight"] == initial_height + 10) + wait_for(lambda: lianad.rpc.getinfo()["blockheight"] == initial_height + 10) -def test_reorg_exclusion(minisafed, bitcoind): +def test_reorg_exclusion(lianad, bitcoind): """Test the unconfirmation by a reorg of a coin in various states.""" initial_height = bitcoind.rpc.getblockcount() - wait_for(lambda: minisafed.rpc.getinfo()["blockheight"] == initial_height) + wait_for(lambda: lianad.rpc.getinfo()["blockheight"] == initial_height) # A confirmed received coin - addr = minisafed.rpc.getnewaddress()["address"] + addr = lianad.rpc.getnewaddress()["address"] txid = bitcoind.rpc.sendtoaddress(addr, 1) bitcoind.generate_block(1, wait_for_mempool=txid) - wait_for(lambda: len(minisafed.rpc.listcoins()["coins"]) == 1) - coin_a = minisafed.rpc.listcoins()["coins"][0] + wait_for(lambda: len(lianad.rpc.listcoins()["coins"]) == 1) + coin_a = lianad.rpc.listcoins()["coins"][0] # A confirmed and 'spending' (unconfirmed spend) coin - addr = minisafed.rpc.getnewaddress()["address"] + addr = lianad.rpc.getnewaddress()["address"] txid = bitcoind.rpc.sendtoaddress(addr, 2) bitcoind.generate_block(1, wait_for_mempool=txid) - wait_for(lambda: len(minisafed.rpc.listcoins()["coins"]) == 2) - coin_b = get_coin(minisafed, txid) - b_spend_tx = spend_coins(minisafed, bitcoind, [coin_b]) + wait_for(lambda: len(lianad.rpc.listcoins()["coins"]) == 2) + coin_b = get_coin(lianad, txid) + b_spend_tx = spend_coins(lianad, bitcoind, [coin_b]) # A confirmed and spent coin - addr = minisafed.rpc.getnewaddress()["address"] + addr = lianad.rpc.getnewaddress()["address"] txid = bitcoind.rpc.sendtoaddress(addr, 3) bitcoind.generate_block(1, wait_for_mempool=txid) - wait_for(lambda: len(minisafed.rpc.listcoins()["coins"]) == 3) - coin_c = get_coin(minisafed, txid) - c_spend_tx = spend_coins(minisafed, bitcoind, [coin_c]) + wait_for(lambda: len(lianad.rpc.listcoins()["coins"]) == 3) + coin_c = get_coin(lianad, txid) + c_spend_tx = spend_coins(lianad, bitcoind, [coin_c]) bitcoind.generate_block(1, wait_for_mempool=1) # Reorg the chain down to the initial height, excluding all transactions. current_height = bitcoind.rpc.getblockcount() bitcoind.simple_reorg(initial_height, shift=-1) - wait_for(lambda: minisafed.rpc.getinfo()["blockheight"] == current_height + 1) + wait_for(lambda: lianad.rpc.getinfo()["blockheight"] == current_height + 1) # They must all be marked as unconfirmed. - new_coin_a = get_coin(minisafed, coin_a["outpoint"]) + new_coin_a = get_coin(lianad, coin_a["outpoint"]) assert new_coin_a["block_height"] is None - new_coin_b = get_coin(minisafed, coin_b["outpoint"]) + new_coin_b = get_coin(lianad, coin_b["outpoint"]) assert new_coin_b["block_height"] is None - new_coin_c = get_coin(minisafed, coin_c["outpoint"]) + new_coin_c = get_coin(lianad, coin_c["outpoint"]) assert new_coin_c["block_height"] is None # And if we now confirm everything, they'll be marked as such. The one that was 'spending' @@ -99,13 +99,13 @@ def test_reorg_exclusion(minisafed, bitcoind): bitcoind.rpc.sendrawtransaction(c_spend_tx) bitcoind.generate_block(1, wait_for_mempool=5) new_height = bitcoind.rpc.getblockcount() - wait_for(lambda: minisafed.rpc.getinfo()["blockheight"] == new_height) + wait_for(lambda: lianad.rpc.getinfo()["blockheight"] == new_height) assert all( - c["block_height"] == new_height for c in minisafed.rpc.listcoins()["coins"] - ), (minisafed.rpc.listcoins()["coins"], new_height) + c["block_height"] == new_height for c in lianad.rpc.listcoins()["coins"] + ), (lianad.rpc.listcoins()["coins"], new_height) new_coin_b = next( c - for c in minisafed.rpc.listcoins()["coins"] + for c in lianad.rpc.listcoins()["coins"] if coin_b["outpoint"] == c["outpoint"] ) b_spend_txid = get_txid(b_spend_tx) @@ -113,7 +113,7 @@ def test_reorg_exclusion(minisafed, bitcoind): assert new_coin_b["spend_info"]["height"] == new_height new_coin_c = next( c - for c in minisafed.rpc.listcoins()["coins"] + for c in lianad.rpc.listcoins()["coins"] if coin_c["outpoint"] == c["outpoint"] ) c_spend_txid = get_txid(c_spend_tx) @@ -123,8 +123,8 @@ def test_reorg_exclusion(minisafed, bitcoind): # TODO: maybe test with some malleation for the deposit and spending txs? -def spend_confirmed_noticed(minisafed, outpoint): - c = get_coin(minisafed, outpoint) +def spend_confirmed_noticed(lianad, outpoint): + c = get_coin(lianad, outpoint) if c["spend_info"] is None: return False if c["spend_info"]["height"] is None: @@ -132,53 +132,53 @@ def spend_confirmed_noticed(minisafed, outpoint): return True -def test_reorg_status_recovery(minisafed, bitcoind): +def test_reorg_status_recovery(lianad, bitcoind): """ Test the coins that were not unconfirmed recover their initial state after a reorg. """ - list_coins = lambda: minisafed.rpc.listcoins()["coins"] + list_coins = lambda: lianad.rpc.listcoins()["coins"] # Create two confirmed coins. Note how we take the initial_height after having # mined them, as we'll reorg back to this height and due to anti fee-sniping # these deposit transactions might not be valid anymore! - addresses = (minisafed.rpc.getnewaddress()["address"] for _ in range(2)) + addresses = (lianad.rpc.getnewaddress()["address"] for _ in range(2)) txids = [bitcoind.rpc.sendtoaddress(addr, 0.5670) for addr in addresses] bitcoind.generate_block(1, wait_for_mempool=txids) initial_height = bitcoind.rpc.getblockcount() - wait_for(lambda: minisafed.rpc.getinfo()["blockheight"] == initial_height) + wait_for(lambda: lianad.rpc.getinfo()["blockheight"] == initial_height) # Both coins are confirmed. Spend the second one then get their infos. wait_for(lambda: len(list_coins()) == 2) wait_for(lambda: all(c["block_height"] is not None for c in list_coins())) - coin_b = get_coin(minisafed, txids[1]) - spend_coins(minisafed, bitcoind, [coin_b]) + coin_b = get_coin(lianad, txids[1]) + spend_coins(lianad, bitcoind, [coin_b]) bitcoind.generate_block(1, wait_for_mempool=1) - wait_for(lambda: spend_confirmed_noticed(minisafed, coin_b["outpoint"])) - coin_a = get_coin(minisafed, txids[0]) - coin_b = get_coin(minisafed, txids[1]) + wait_for(lambda: spend_confirmed_noticed(lianad, coin_b["outpoint"])) + coin_a = get_coin(lianad, txids[0]) + coin_b = get_coin(lianad, txids[1]) # Reorg the chain down to the initial height without shifting nor malleating # any transaction. The coin info should be identical (except the transaction # spending the second coin will be mined at the height the reorg happened). bitcoind.simple_reorg(initial_height, shift=0) new_height = bitcoind.rpc.getblockcount() - wait_for(lambda: minisafed.rpc.getinfo()["blockheight"] == new_height) - new_coin_a = get_coin(minisafed, coin_a["outpoint"]) + wait_for(lambda: lianad.rpc.getinfo()["blockheight"] == new_height) + new_coin_a = get_coin(lianad, coin_a["outpoint"]) assert coin_a == new_coin_a - new_coin_b = get_coin(minisafed, coin_b["outpoint"]) + new_coin_b = get_coin(lianad, coin_b["outpoint"]) coin_b["spend_info"]["height"] = initial_height assert new_coin_b == coin_b -def test_rescan_edge_cases(minisafed, bitcoind): +def test_rescan_edge_cases(lianad, bitcoind): """Test some specific cases that could arise when rescanning the chain.""" initial_tip = bitcoind.rpc.getblockheader(bitcoind.rpc.getbestblockhash()) # Some helpers - list_coins = lambda: minisafed.rpc.listcoins()["coins"] + list_coins = lambda: lianad.rpc.listcoins()["coins"] sorted_coins = lambda: sorted(list_coins(), key=lambda c: c["outpoint"]) wait_synced = lambda: wait_for( - lambda: minisafed.rpc.getinfo()["blockheight"] == bitcoind.rpc.getblockcount() + lambda: lianad.rpc.getinfo()["blockheight"] == bitcoind.rpc.getblockcount() ) def reorg_shift(height, txs): @@ -196,12 +196,12 @@ def reorg_shift(height, txs): # rebroadcast them on reorgs. txs = [] for _ in range(3): - addr = minisafed.rpc.getnewaddress()["address"] + addr = lianad.rpc.getnewaddress()["address"] amount = 0.356 txid = bitcoind.rpc.sendtoaddress(addr, amount) txs.append(bitcoind.rpc.gettransaction(txid)["hex"]) wait_for(lambda: len(list_coins()) == 3) - txs.append(spend_coins(minisafed, bitcoind, list_coins()[:2])) + txs.append(spend_coins(lianad, bitcoind, list_coins()[:2])) bitcoind.generate_block(1, wait_for_mempool=4) wait_synced() @@ -214,27 +214,27 @@ def reorg_shift(height, txs): coins_before = sorted_coins() outpoints_before = set(c["outpoint"] for c in coins_before) bitcoind.generate_block(1) - minisafed.restart_fresh(bitcoind) + lianad.restart_fresh(bitcoind) assert len(list_coins()) == 0 # We can be stopped while we are rescanning - minisafed.rpc.startrescan(initial_tip["time"]) - minisafed.stop() - minisafed.start() - wait_for(lambda: minisafed.rpc.getinfo()["rescan_progress"] is None) + lianad.rpc.startrescan(initial_tip["time"]) + lianad.stop() + lianad.start() + wait_for(lambda: lianad.rpc.getinfo()["rescan_progress"] is None) assert coins_before == sorted_coins() # Lose our state again bitcoind.generate_block(1) - minisafed.restart_fresh(bitcoind) - wait_for(lambda: minisafed.rpc.getinfo()["rescan_progress"] is None) + lianad.restart_fresh(bitcoind) + wait_for(lambda: lianad.rpc.getinfo()["rescan_progress"] is None) assert len(list_coins()) == 0 # There can be a reorg when we start rescanning reorg_shift(initial_tip["height"], txs) - minisafed.rpc.startrescan(initial_tip["time"]) + lianad.rpc.startrescan(initial_tip["time"]) wait_synced() - wait_for(lambda: minisafed.rpc.getinfo()["rescan_progress"] is None) + wait_for(lambda: lianad.rpc.getinfo()["rescan_progress"] is None) assert len(sorted_coins()) == len(coins_before) assert all(c["outpoint"] in outpoints_before for c in list_coins()) @@ -244,15 +244,15 @@ def reorg_shift(height, txs): # Lose our state again bitcoind.generate_block(1) - minisafed.restart_fresh(bitcoind) + lianad.restart_fresh(bitcoind) wait_synced() - wait_for(lambda: minisafed.rpc.getinfo()["rescan_progress"] is None) + wait_for(lambda: lianad.rpc.getinfo()["rescan_progress"] is None) assert len(list_coins()) == 0 # We can be rescanning when a reorg happens - minisafed.rpc.startrescan(initial_tip["time"]) + lianad.rpc.startrescan(initial_tip["time"]) reorg_shift(initial_tip["height"] + 1, txs) wait_synced() - wait_for(lambda: minisafed.rpc.getinfo()["rescan_progress"] is None) + wait_for(lambda: lianad.rpc.getinfo()["rescan_progress"] is None) assert len(sorted_coins()) == len(coins_before) assert all(c["outpoint"] in outpoints_before for c in list_coins()) diff --git a/tests/test_framework/bitcoind.py b/tests/test_framework/bitcoind.py index fd1588bff..5555d6b42 100644 --- a/tests/test_framework/bitcoind.py +++ b/tests/test_framework/bitcoind.py @@ -71,7 +71,7 @@ def __init__(self, bitcoin_dir, rpcport=None): # An RPC interface with our internal wallet, and an RPC interface with no # wallet to be able to call 'unloadwallet' on any wallet. self.rpc = BitcoindRpcInterface( - bitcoin_dir, "regtest", rpcport, wallet="minisafed-tests" + bitcoin_dir, "regtest", rpcport, wallet="lianad-tests" ) self.node_rpc = BitcoindRpcInterface(bitcoin_dir, "regtest", rpcport) diff --git a/tests/test_framework/minisafed.py b/tests/test_framework/lianad.py similarity index 96% rename from tests/test_framework/minisafed.py rename to tests/test_framework/lianad.py index 8cfc137fb..8a9096ae3 100644 --- a/tests/test_framework/minisafed.py +++ b/tests/test_framework/lianad.py @@ -10,7 +10,7 @@ TailableProc, VERBOSE, LOG_LEVEL, - MINISAFED_PATH, + LIANAD_PATH, wait_for, ) from test_framework.serializations import ( @@ -25,7 +25,7 @@ ) -class Minisafed(TailableProc): +class Lianad(TailableProc): def __init__( self, datadir, @@ -44,8 +44,8 @@ def __init__( self.receive_desc, self.change_desc = multi_desc.singlepath_descriptors() self.conf_file = os.path.join(datadir, "config.toml") - self.cmd_line = [MINISAFED_PATH, "--conf", f"{self.conf_file}"] - socket_path = os.path.join(os.path.join(datadir, "regtest"), "minisafed_rpc") + self.cmd_line = [LIANAD_PATH, "--conf", f"{self.conf_file}"] + socket_path = os.path.join(os.path.join(datadir, "regtest"), "lianad_rpc") self.rpc = UnixDomainSocketRpc(socket_path) with open(self.conf_file, "w") as f: @@ -153,7 +153,7 @@ def restart_fresh(self, bitcoind): self.stop() dir_path = os.path.join(self.datadir, "regtest") shutil.rmtree(dir_path) - wallet_path = os.path.join(dir_path, "minisafed_watchonly_wallet") + wallet_path = os.path.join(dir_path, "lianad_watchonly_wallet") bitcoind.node_rpc.unloadwallet(wallet_path) self.start() wait_for( @@ -174,7 +174,7 @@ def stop(self, timeout=5): try: self.rpc.stop() self.wait_for_log( - "Stopping the minisafe daemon.", + "Stopping the liana daemon.", ) self.proc.wait(timeout) except Exception as e: diff --git a/tests/test_framework/utils.py b/tests/test_framework/utils.py index e9f89e02f..f2d90efde 100644 --- a/tests/test_framework/utils.py +++ b/tests/test_framework/utils.py @@ -17,9 +17,9 @@ LOG_LEVEL = os.getenv("LOG_LEVEL", "debug") assert LOG_LEVEL in ["trace", "debug", "info", "warn", "error"] DEFAULT_MS_PATH = os.path.join( - os.path.dirname(__file__), "..", "..", "target/debug/minisafed" + os.path.dirname(__file__), "..", "..", "target/debug/lianad" ) -MINISAFED_PATH = os.getenv("MINISAFED_PATH", DEFAULT_MS_PATH) +LIANAD_PATH = os.getenv("LIANAD_PATH", DEFAULT_MS_PATH) DEFAULT_BITCOIND_PATH = "bitcoind" BITCOIND_PATH = os.getenv("BITCOIND_PATH", DEFAULT_BITCOIND_PATH) @@ -53,7 +53,7 @@ def get_txid(hex_tx): return tx.txid().hex() -def spend_coins(minisafed, bitcoind, coins): +def spend_coins(lianad, bitcoind, coins): """Spend these coins, no matter how. This will create a single transaction spending them all at once at the minimum feerate. This will broadcast but not confirm the transaction. @@ -65,10 +65,10 @@ def spend_coins(minisafed, bitcoind, coins): destinations = { bitcoind.rpc.getnewaddress(): total_value - 11 - 31 - 300 * len(coins) } - res = minisafed.rpc.createspend(destinations, [c["outpoint"] for c in coins], 1) + res = lianad.rpc.createspend(destinations, [c["outpoint"] for c in coins], 1) - signed_psbt = minisafed.sign_psbt(PSBT.from_base64(res["psbt"])) - finalized_psbt = minisafed.finalize_psbt(signed_psbt) + signed_psbt = lianad.sign_psbt(PSBT.from_base64(res["psbt"])) + finalized_psbt = lianad.finalize_psbt(signed_psbt) tx = finalized_psbt.tx.serialize_with_witness().hex() bitcoind.rpc.sendrawtransaction(tx) @@ -175,7 +175,7 @@ def _readobj(self, sock): except json.JSONDecodeError: # There is more to read, continue # FIXME: this is a workaround for large reads taken from revaultd. - # We should use the '\n' marker instead since minisafed uses that. + # We should use the '\n' marker instead since lianad uses that. continue def __getattr__(self, name): diff --git a/tests/test_misc.py b/tests/test_misc.py index d2f7775f2..82d91b646 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -1,5 +1,5 @@ from fixtures import * -def test_startup(minisafed): +def test_startup(lianad): pass diff --git a/tests/test_rpc.py b/tests/test_rpc.py index 271c8ae81..d13ce1804 100644 --- a/tests/test_rpc.py +++ b/tests/test_rpc.py @@ -9,36 +9,36 @@ from test_framework.utils import wait_for, COIN, RpcError, get_txid, spend_coins -def test_getinfo(minisafed): - res = minisafed.rpc.getinfo() +def test_getinfo(lianad): + res = lianad.rpc.getinfo() assert res["version"] == "0.1" assert res["network"] == "regtest" - wait_for(lambda: minisafed.rpc.getinfo()["blockheight"] == 101) - res = minisafed.rpc.getinfo() + wait_for(lambda: lianad.rpc.getinfo()["blockheight"] == 101) + res = lianad.rpc.getinfo() assert res["sync"] == 1.0 assert "main" in res["descriptors"] assert res["rescan_progress"] is None -def test_getaddress(minisafed): - res = minisafed.rpc.getnewaddress() +def test_getaddress(lianad): + res = lianad.rpc.getnewaddress() assert "address" in res # We'll get a new one at every call - assert res["address"] != minisafed.rpc.getnewaddress()["address"] + assert res["address"] != lianad.rpc.getnewaddress()["address"] -def test_listcoins(minisafed, bitcoind): +def test_listcoins(lianad, bitcoind): # Initially empty - res = minisafed.rpc.listcoins() + res = lianad.rpc.listcoins() assert "coins" in res assert len(res["coins"]) == 0 # If we send a coin, we'll get a new entry. Note we monitor for unconfirmed # funds as well. - addr = minisafed.rpc.getnewaddress()["address"] + addr = lianad.rpc.getnewaddress()["address"] txid = bitcoind.rpc.sendtoaddress(addr, 1) - wait_for(lambda: len(minisafed.rpc.listcoins()["coins"]) == 1) - res = minisafed.rpc.listcoins()["coins"] + wait_for(lambda: len(lianad.rpc.listcoins()["coins"]) == 1) + res = lianad.rpc.listcoins()["coins"] assert txid == res[0]["outpoint"][:64] assert res[0]["amount"] == 1 * COIN assert res[0]["block_height"] is None @@ -48,66 +48,66 @@ def test_listcoins(minisafed, bitcoind): bitcoind.generate_block(1, wait_for_mempool=txid) block_height = bitcoind.rpc.getblockcount() wait_for( - lambda: minisafed.rpc.listcoins()["coins"][0]["block_height"] == block_height + lambda: lianad.rpc.listcoins()["coins"][0]["block_height"] == block_height ) # Same if the coin gets spent. - spend_tx = spend_coins(minisafed, bitcoind, (res[0],)) + spend_tx = spend_coins(lianad, bitcoind, (res[0],)) spend_txid = get_txid(spend_tx) - wait_for(lambda: minisafed.rpc.listcoins()["coins"][0]["spend_info"] is not None) - spend_info = minisafed.rpc.listcoins()["coins"][0]["spend_info"] + wait_for(lambda: lianad.rpc.listcoins()["coins"][0]["spend_info"] is not None) + spend_info = lianad.rpc.listcoins()["coins"][0]["spend_info"] assert spend_info["txid"] == spend_txid assert spend_info["height"] is None # And if this spending tx gets confirmed. bitcoind.generate_block(1, wait_for_mempool=spend_txid) curr_height = bitcoind.rpc.getblockcount() - wait_for(lambda: minisafed.rpc.getinfo()["blockheight"] == curr_height) - spend_info = minisafed.rpc.listcoins()["coins"][0]["spend_info"] + wait_for(lambda: lianad.rpc.getinfo()["blockheight"] == curr_height) + spend_info = lianad.rpc.listcoins()["coins"][0]["spend_info"] assert spend_info["txid"] == spend_txid assert spend_info["height"] == curr_height -def test_jsonrpc_server(minisafed, bitcoind): +def test_jsonrpc_server(lianad, bitcoind): """Test passing parameters as a list or a mapping.""" - addr = minisafed.rpc.getnewaddress()["address"] + addr = lianad.rpc.getnewaddress()["address"] bitcoind.rpc.sendtoaddress(addr, 1) - wait_for(lambda: len(minisafed.rpc.listcoins()["coins"]) == 1) - outpoints = [minisafed.rpc.listcoins()["coins"][0]["outpoint"]] + wait_for(lambda: len(lianad.rpc.listcoins()["coins"]) == 1) + outpoints = [lianad.rpc.listcoins()["coins"][0]["outpoint"]] destinations = { bitcoind.rpc.getnewaddress(): 20_000, } - res = minisafed.rpc.createspend(destinations, outpoints, 18) + res = lianad.rpc.createspend(destinations, outpoints, 18) assert "psbt" in res - res = minisafed.rpc.createspend( + res = lianad.rpc.createspend( outpoints=outpoints, destinations=destinations, feerate=18 ) assert "psbt" in res -def test_create_spend(minisafed, bitcoind): +def test_create_spend(lianad, bitcoind): # Receive a number of coins in different blocks on different addresses, and # one more on the same address. for _ in range(15): - addr = minisafed.rpc.getnewaddress()["address"] + addr = lianad.rpc.getnewaddress()["address"] txid = bitcoind.rpc.sendtoaddress(addr, 0.01) bitcoind.generate_block(1, wait_for_mempool=txid) txid = bitcoind.rpc.sendtoaddress(addr, 0.3556) bitcoind.generate_block(1, wait_for_mempool=txid) - wait_for(lambda: len(minisafed.rpc.listcoins()["coins"]) == 16) + wait_for(lambda: len(lianad.rpc.listcoins()["coins"]) == 16) # Stop the daemon, should be a no-op - minisafed.stop() - minisafed.start() + lianad.stop() + lianad.start() # Now create a transaction spending all those coins to a few addresses - outpoints = [c["outpoint"] for c in minisafed.rpc.listcoins()["coins"]] + outpoints = [c["outpoint"] for c in lianad.rpc.listcoins()["coins"]] destinations = { bitcoind.rpc.getnewaddress(): 200_000, bitcoind.rpc.getnewaddress(): 400_000, bitcoind.rpc.getnewaddress(): 1_000_000, } - res = minisafed.rpc.createspend(destinations, outpoints, 18) + res = lianad.rpc.createspend(destinations, outpoints, 18) assert "psbt" in res # The transaction must contain a change output. @@ -116,45 +116,45 @@ def test_create_spend(minisafed, bitcoind): assert len(spend_psbt.tx.vout) == 4 # We can sign it and broadcast it. - signed_psbt = minisafed.sign_psbt(PSBT.from_base64(res["psbt"])) - finalized_psbt = minisafed.finalize_psbt(signed_psbt) + signed_psbt = lianad.sign_psbt(PSBT.from_base64(res["psbt"])) + finalized_psbt = lianad.finalize_psbt(signed_psbt) tx = finalized_psbt.tx.serialize_with_witness().hex() bitcoind.rpc.sendrawtransaction(tx) -def test_list_spend(minisafed, bitcoind): +def test_list_spend(lianad, bitcoind): # Start by creating two conflicting Spend PSBTs. The first one will have a change # output but not the second one. - addr = minisafed.rpc.getnewaddress()["address"] + addr = lianad.rpc.getnewaddress()["address"] value_a = 0.2567 bitcoind.rpc.sendtoaddress(addr, value_a) - wait_for(lambda: len(minisafed.rpc.listcoins()["coins"]) == 1) - outpoints = [c["outpoint"] for c in minisafed.rpc.listcoins()["coins"]] + wait_for(lambda: len(lianad.rpc.listcoins()["coins"]) == 1) + outpoints = [c["outpoint"] for c in lianad.rpc.listcoins()["coins"]] destinations = { bitcoind.rpc.getnewaddress(): int(value_a * COIN // 2), } - res = minisafed.rpc.createspend(destinations, outpoints, 6) + res = lianad.rpc.createspend(destinations, outpoints, 6) assert "psbt" in res - addr = minisafed.rpc.getnewaddress()["address"] + addr = lianad.rpc.getnewaddress()["address"] value_b = 0.0987 bitcoind.rpc.sendtoaddress(addr, value_b) - wait_for(lambda: len(minisafed.rpc.listcoins()["coins"]) == 2) - outpoints = [c["outpoint"] for c in minisafed.rpc.listcoins()["coins"]] + wait_for(lambda: len(lianad.rpc.listcoins()["coins"]) == 2) + outpoints = [c["outpoint"] for c in lianad.rpc.listcoins()["coins"]] destinations = { bitcoind.rpc.getnewaddress(): int((value_a + value_b) * COIN - 1_000), } - res_b = minisafed.rpc.createspend(destinations, outpoints, 2) + res_b = lianad.rpc.createspend(destinations, outpoints, 2) assert "psbt" in res_b # Store them both in DB. - assert len(minisafed.rpc.listspendtxs()["spend_txs"]) == 0 - minisafed.rpc.updatespend(res["psbt"]) - minisafed.rpc.updatespend(res_b["psbt"]) + assert len(lianad.rpc.listspendtxs()["spend_txs"]) == 0 + lianad.rpc.updatespend(res["psbt"]) + lianad.rpc.updatespend(res_b["psbt"]) # Listing all Spend transactions will list them both. It'll tell us which one has # change and which one doesn't. - list_res = minisafed.rpc.listspendtxs()["spend_txs"] + list_res = lianad.rpc.listspendtxs()["spend_txs"] assert len(list_res) == 2 first_psbt = next(entry for entry in list_res if entry["psbt"] == res["psbt"]) assert first_psbt["change_index"] == 1 @@ -163,34 +163,34 @@ def test_list_spend(minisafed, bitcoind): # If we delete the first one, we'll get only the second one. first_psbt = PSBT.from_base64(res["psbt"]) - minisafed.rpc.delspendtx(first_psbt.tx.txid().hex()) - list_res = minisafed.rpc.listspendtxs()["spend_txs"] + lianad.rpc.delspendtx(first_psbt.tx.txid().hex()) + list_res = lianad.rpc.listspendtxs()["spend_txs"] assert len(list_res) == 1 assert list_res[0]["psbt"] == res_b["psbt"] # If we delete the second one, result will be empty. second_psbt = PSBT.from_base64(res_b["psbt"]) - minisafed.rpc.delspendtx(second_psbt.tx.txid().hex()) - list_res = minisafed.rpc.listspendtxs()["spend_txs"] + lianad.rpc.delspendtx(second_psbt.tx.txid().hex()) + list_res = lianad.rpc.listspendtxs()["spend_txs"] assert len(list_res) == 0 -def test_update_spend(minisafed, bitcoind): +def test_update_spend(lianad, bitcoind): # Start by creating a Spend PSBT - addr = minisafed.rpc.getnewaddress()["address"] + addr = lianad.rpc.getnewaddress()["address"] bitcoind.rpc.sendtoaddress(addr, 0.2567) - wait_for(lambda: len(minisafed.rpc.listcoins()["coins"]) > 0) - outpoints = [c["outpoint"] for c in minisafed.rpc.listcoins()["coins"]] + wait_for(lambda: len(lianad.rpc.listcoins()["coins"]) > 0) + outpoints = [c["outpoint"] for c in lianad.rpc.listcoins()["coins"]] destinations = { bitcoind.rpc.getnewaddress(): 200_000, } - res = minisafed.rpc.createspend(destinations, outpoints, 6) + res = lianad.rpc.createspend(destinations, outpoints, 6) assert "psbt" in res # Now update it - assert len(minisafed.rpc.listspendtxs()["spend_txs"]) == 0 - minisafed.rpc.updatespend(res["psbt"]) - list_res = minisafed.rpc.listspendtxs()["spend_txs"] + assert len(lianad.rpc.listspendtxs()["spend_txs"]) == 0 + lianad.rpc.updatespend(res["psbt"]) + list_res = lianad.rpc.listspendtxs()["spend_txs"] assert len(list_res) == 1 assert list_res[0]["psbt"] == res["psbt"] @@ -204,10 +204,10 @@ def test_update_spend(minisafed, bitcoind): ) psbt_sig_a.i[0].map[PSBT_IN_PARTIAL_SIG] = {dummy_pk_a: dummy_sig_a} psbt_sig_a_ser = psbt_sig_a.to_base64() - minisafed.rpc.updatespend(psbt_sig_a_ser) + lianad.rpc.updatespend(psbt_sig_a_ser) # We'll get it when querying - list_res = minisafed.rpc.listspendtxs()["spend_txs"] + list_res = lianad.rpc.listspendtxs()["spend_txs"] assert len(list_res) == 1 assert list_res[0]["psbt"] == psbt_sig_a_ser @@ -221,10 +221,10 @@ def test_update_spend(minisafed, bitcoind): ) psbt_sig_b.i[0].map[PSBT_IN_PARTIAL_SIG] = {dummy_pk_b: dummy_sig_b} psbt_sig_b_ser = psbt_sig_b.to_base64() - minisafed.rpc.updatespend(psbt_sig_b_ser) + lianad.rpc.updatespend(psbt_sig_b_ser) # It will have merged both. - list_res = minisafed.rpc.listspendtxs()["spend_txs"] + list_res = lianad.rpc.listspendtxs()["spend_txs"] assert len(list_res) == 1 psbt_merged = PSBT.from_base64(list_res[0]["psbt"]) assert len(psbt_merged.i[0].map[PSBT_IN_PARTIAL_SIG]) == 2 @@ -232,45 +232,45 @@ def test_update_spend(minisafed, bitcoind): assert psbt_merged.i[0].map[PSBT_IN_PARTIAL_SIG][dummy_pk_b] == dummy_sig_b -def test_broadcast_spend(minisafed, bitcoind): +def test_broadcast_spend(lianad, bitcoind): # Create a new coin and a spending tx for it. - addr = minisafed.rpc.getnewaddress()["address"] + addr = lianad.rpc.getnewaddress()["address"] bitcoind.rpc.sendtoaddress(addr, 0.2567) - wait_for(lambda: len(minisafed.rpc.listcoins()["coins"]) > 0) - outpoints = [c["outpoint"] for c in minisafed.rpc.listcoins()["coins"]] + wait_for(lambda: len(lianad.rpc.listcoins()["coins"]) > 0) + outpoints = [c["outpoint"] for c in lianad.rpc.listcoins()["coins"]] destinations = { bitcoind.rpc.getnewaddress(): 200_000, } - res = minisafed.rpc.createspend(destinations, outpoints, 6) + res = lianad.rpc.createspend(destinations, outpoints, 6) psbt = PSBT.from_base64(res["psbt"]) txid = psbt.tx.txid().hex() # We can't broadcast an unknown Spend with pytest.raises(RpcError, match="Unknown spend transaction.*"): - minisafed.rpc.broadcastspend(txid) - minisafed.rpc.updatespend(res["psbt"]) + lianad.rpc.broadcastspend(txid) + lianad.rpc.updatespend(res["psbt"]) # We can't broadcast an unsigned transaction with pytest.raises(RpcError, match="Failed to finalize the spend transaction.*"): - minisafed.rpc.broadcastspend(txid) - signed_psbt = minisafed.sign_psbt(PSBT.from_base64(res["psbt"])) - minisafed.rpc.updatespend(signed_psbt.to_base64()) + lianad.rpc.broadcastspend(txid) + signed_psbt = lianad.sign_psbt(PSBT.from_base64(res["psbt"])) + lianad.rpc.updatespend(signed_psbt.to_base64()) # Now we've signed and stored it, the daemon will take care of finalizing # the PSBT before broadcasting the transaction. - minisafed.rpc.broadcastspend(txid) + lianad.rpc.broadcastspend(txid) -def test_start_rescan(minisafed, bitcoind): +def test_start_rescan(lianad, bitcoind): """Test we successfully retrieve all our transactions after losing state by rescanning.""" initial_timestamp = int(time.time()) - first_address = minisafed.rpc.getnewaddress() - second_address = minisafed.rpc.getnewaddress() + first_address = lianad.rpc.getnewaddress() + second_address = lianad.rpc.getnewaddress() # Some utility functions to DRY - list_coins = lambda: minisafed.rpc.listcoins()["coins"] + list_coins = lambda: lianad.rpc.listcoins()["coins"] unspent_coins = lambda: ( - c for c in minisafed.rpc.listcoins()["coins"] if c["spend_info"] is None + c for c in lianad.rpc.listcoins()["coins"] if c["spend_info"] is None ) sorted_coins = lambda: sorted(list_coins(), key=lambda c: c["outpoint"]) @@ -283,24 +283,24 @@ def all_spent(coins): # We can rescan from one second before the tip timestamp, that's almost a no-op. tip_timestamp = bitcoind.rpc.getblockheader(bitcoind.rpc.getbestblockhash())["time"] - minisafed.rpc.startrescan(tip_timestamp - 1) - wait_for(lambda: minisafed.rpc.getinfo()["rescan_progress"] is None) + lianad.rpc.startrescan(tip_timestamp - 1) + wait_for(lambda: lianad.rpc.getinfo()["rescan_progress"] is None) # We can't rescan from an insane timestamp though. with pytest.raises(RpcError, match="Insane timestamp.*"): - minisafed.rpc.startrescan(tip_timestamp) - assert minisafed.rpc.getinfo()["rescan_progress"] is None + lianad.rpc.startrescan(tip_timestamp) + assert lianad.rpc.getinfo()["rescan_progress"] is None future_timestamp = tip_timestamp + 60 * 60 with pytest.raises(RpcError, match="Insane timestamp.*"): - minisafed.rpc.startrescan(future_timestamp) - assert minisafed.rpc.getinfo()["rescan_progress"] is None + lianad.rpc.startrescan(future_timestamp) + assert lianad.rpc.getinfo()["rescan_progress"] is None prebitcoin_timestamp = 1231006505 - 1 with pytest.raises(RpcError, match="Insane timestamp."): - minisafed.rpc.startrescan(prebitcoin_timestamp) - assert minisafed.rpc.getinfo()["rescan_progress"] is None + lianad.rpc.startrescan(prebitcoin_timestamp) + assert lianad.rpc.getinfo()["rescan_progress"] is None # First, get some coins for _ in range(10): - addr = minisafed.rpc.getnewaddress()["address"] + addr = lianad.rpc.getnewaddress()["address"] amount = random.randint(1, COIN * 10) / COIN txid = bitcoind.rpc.sendtoaddress(addr, amount) bitcoind.generate_block(random.randint(1, 10), wait_for_mempool=txid) @@ -310,20 +310,20 @@ def all_spent(coins): # TODO: instead of having randomness we should lay down all different cases (with or # without change, single or multiple inputs, sending externally or to self). for _ in range(5): - addr = minisafed.rpc.getnewaddress()["address"] + addr = lianad.rpc.getnewaddress()["address"] amount = random.randint(1, COIN * 10) / COIN txid = bitcoind.rpc.sendtoaddress(addr, amount) avail = list(unspent_coins()) to_spend = random.sample(avail, random.randint(1, len(avail))) - spend_coins(minisafed, bitcoind, to_spend) + spend_coins(lianad, bitcoind, to_spend) bitcoind.generate_block(random.randint(1, 5), wait_for_mempool=2) wait_for(lambda: all_spent(to_spend)) wait_for( - lambda: minisafed.rpc.getinfo()["blockheight"] == bitcoind.rpc.getblockcount() + lambda: lianad.rpc.getinfo()["blockheight"] == bitcoind.rpc.getblockcount() ) # Receiving addresses are derived at much higher indexes now. - assert minisafed.rpc.getnewaddress() not in (first_address, second_address) + assert lianad.rpc.getnewaddress() not in (first_address, second_address) # Move time forward one day as bitcoind will rescan the last 2 hours of block upon # importing a descriptor. @@ -336,23 +336,23 @@ def all_spent(coins): # and watchonly wallet. Those won't be aware of past coins for the configured # descriptor. coins_before = sorted_coins() - minisafed.restart_fresh(bitcoind) + lianad.restart_fresh(bitcoind) assert len(list_coins()) == 0 # The wallet isn't aware what derivation indexes were used. Necessarily it'll start # from 0. - assert minisafed.rpc.getnewaddress() == first_address + assert lianad.rpc.getnewaddress() == first_address # Once the rescan is done, we must have detected all previous transactions. - minisafed.rpc.startrescan(initial_timestamp) - rescan_progress = minisafed.rpc.getinfo()["rescan_progress"] + lianad.rpc.startrescan(initial_timestamp) + rescan_progress = lianad.rpc.getinfo()["rescan_progress"] assert rescan_progress is None or 0 <= rescan_progress <= 1 - wait_for(lambda: minisafed.rpc.getinfo()["rescan_progress"] is None) + wait_for(lambda: lianad.rpc.getinfo()["rescan_progress"] is None) wait_for( - lambda: minisafed.rpc.getinfo()["blockheight"] == bitcoind.rpc.getblockcount() + lambda: lianad.rpc.getinfo()["blockheight"] == bitcoind.rpc.getblockcount() ) assert coins_before == sorted_coins() # Now that it caught up it noticed which one were used onchain, so it won't reuse # this derivation indexes anymore. - assert minisafed.rpc.getnewaddress() not in (first_address, second_address) + assert lianad.rpc.getnewaddress() not in (first_address, second_address) diff --git a/tests/test_spend.py b/tests/test_spend.py index 9969a4d9c..4458f6a0c 100644 --- a/tests/test_spend.py +++ b/tests/test_spend.py @@ -3,22 +3,22 @@ from test_framework.utils import wait_for -def test_spend_change(minisafed, bitcoind): +def test_spend_change(lianad, bitcoind): """We can spend a coin that was received on a change address.""" # Receive a coin on a receive address - addr = minisafed.rpc.getnewaddress()["address"] + addr = lianad.rpc.getnewaddress()["address"] txid = bitcoind.rpc.sendtoaddress(addr, 0.01) bitcoind.generate_block(1, wait_for_mempool=txid) - wait_for(lambda: len(minisafed.rpc.listcoins()["coins"]) == 1) + wait_for(lambda: len(lianad.rpc.listcoins()["coins"]) == 1) # Create a transaction that will spend this coin to 1) one of our receive # addresses 2) an external address 3) one of our change addresses. - outpoints = [c["outpoint"] for c in minisafed.rpc.listcoins()["coins"]] + outpoints = [c["outpoint"] for c in lianad.rpc.listcoins()["coins"]] destinations = { bitcoind.rpc.getnewaddress(): 100_000, - minisafed.rpc.getnewaddress()["address"]: 100_000, + lianad.rpc.getnewaddress()["address"]: 100_000, } - res = minisafed.rpc.createspend(destinations, outpoints, 2) + res = lianad.rpc.createspend(destinations, outpoints, 2) assert "psbt" in res # The transaction must contain a change output. @@ -27,29 +27,29 @@ def test_spend_change(minisafed, bitcoind): assert len(spend_psbt.tx.vout) == 3 # Sign and broadcast this first Spend transaction. - signed_psbt = minisafed.sign_psbt(spend_psbt) - minisafed.rpc.updatespend(signed_psbt.to_base64()) + signed_psbt = lianad.sign_psbt(spend_psbt) + lianad.rpc.updatespend(signed_psbt.to_base64()) spend_txid = signed_psbt.tx.txid().hex() - minisafed.rpc.broadcastspend(spend_txid) + lianad.rpc.broadcastspend(spend_txid) bitcoind.generate_block(1, wait_for_mempool=spend_txid) - wait_for(lambda: len(minisafed.rpc.listcoins()["coins"]) == 3) + wait_for(lambda: len(lianad.rpc.listcoins()["coins"]) == 3) # Now create a new transaction that spends the change output as well as # the output sent to the receive address. outpoints = [ c["outpoint"] - for c in minisafed.rpc.listcoins()["coins"] + for c in lianad.rpc.listcoins()["coins"] if c["spend_info"] is None ] destinations = { bitcoind.rpc.getnewaddress(): 100_000, } - res = minisafed.rpc.createspend(destinations, outpoints, 2) + res = lianad.rpc.createspend(destinations, outpoints, 2) spend_psbt = PSBT.from_base64(res["psbt"]) # We can sign and broadcast it. - signed_psbt = minisafed.sign_psbt(spend_psbt) - minisafed.rpc.updatespend(signed_psbt.to_base64()) + signed_psbt = lianad.sign_psbt(spend_psbt) + lianad.rpc.updatespend(signed_psbt.to_base64()) spend_txid = signed_psbt.tx.txid().hex() - minisafed.rpc.broadcastspend(spend_txid) + lianad.rpc.broadcastspend(spend_txid) bitcoind.generate_block(1, wait_for_mempool=spend_txid)