diff --git a/.cirrus.yml b/.cirrus.yml index 3857f2dd..a6d41069 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -1,7 +1,7 @@ task: name: 'Functional tests' container: - image: rust:latest + image: rust:1-bookworm timeout_in: 90m # https://cirrus-ci.org/faq/#instance-timed-out env: @@ -37,7 +37,7 @@ task: pip_cache: folder: ~/.cache/pip - python_deps_script: pip install -r tests/requirements.txt + python_deps_script: pip install --break-system-packages -r tests/requirements.txt test_script: | set -xe @@ -48,6 +48,15 @@ task: tar -xzf bitcoin-24.0.1-x86_64-linux-gnu.tar.gz export BITCOIND_PATH=bitcoin-24.0.1/bin/bitcoind + # The misc tests have a backward compat test that need the path to a previous version of Liana. + # For now it requires using 0.3. + if [ "$TEST_GROUP" = "tests/test_misc.py" ]; then + curl -LO https://github.com/wizardsardine/liana/releases/download/0.3.1/liana-0.3.1-x86_64-linux-gnu.tar.gz + echo "70c8595554b6f78ccc7b66ef5f5ebc5bac03a7b1ce28afe8a076f69adf59c583 liana-0.3.1-x86_64-linux-gnu.tar.gz" | sha256sum -c + tar -xzf liana-0.3.1-x86_64-linux-gnu.tar.gz + export OLD_LIANAD_PATH="$PWD/liana-0.3.1-x86_64-linux-gnu/lianad" + fi + # Run the functional tests LIANAD_PATH=$PWD/target/release/lianad pytest $TEST_GROUP -vvv -n 2 diff --git a/tests/test_framework/signer.py b/tests/test_framework/signer.py index 9e0f86cc..48004556 100644 --- a/tests/test_framework/signer.py +++ b/tests/test_framework/signer.py @@ -74,6 +74,7 @@ class SingleSigner: :param psbt: PSBT of the transaction to be signed. :returns: PSBT with a signature in each input for the specified key. """ + assert isinstance(recovery, bool) return sign_psbt(psbt, [self.recovery_hd if recovery else self.primary_hd]) diff --git a/tests/test_framework/utils.py b/tests/test_framework/utils.py index d57c329c..15303250 100644 --- a/tests/test_framework/utils.py +++ b/tests/test_framework/utils.py @@ -22,6 +22,7 @@ DEFAULT_MS_PATH = os.path.join( LIANAD_PATH = os.getenv("LIANAD_PATH", DEFAULT_MS_PATH) DEFAULT_BITCOIND_PATH = "bitcoind" BITCOIND_PATH = os.getenv("BITCOIND_PATH", DEFAULT_BITCOIND_PATH) +OLD_LIANAD_PATH = os.getenv("OLD_LIANAD_PATH", None) COIN = 10 ** 8 diff --git a/tests/test_misc.py b/tests/test_misc.py index f268ec99..1d420da1 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -2,19 +2,25 @@ import pytest from fixtures import * from test_framework.serializations import PSBT -from test_framework.utils import wait_for, RpcError +from test_framework.utils import wait_for, RpcError, OLD_LIANAD_PATH, LIANAD_PATH def receive_and_send(lianad, bitcoind): + n_coins = len(lianad.rpc.listcoins()["coins"]) + # Receive 3 coins in different blocks on different addresses. for _ in range(3): addr = lianad.rpc.getnewaddress()["address"] txid = bitcoind.rpc.sendtoaddress(addr, 0.01) bitcoind.generate_block(1, wait_for_mempool=txid) - wait_for(lambda: len(lianad.rpc.listcoins()["coins"]) == 3) + wait_for(lambda: len(lianad.rpc.listcoins()["coins"]) == n_coins + 3) # Create a spend that will create a change output, sign and broadcast it. - outpoints = [lianad.rpc.listcoins()["coins"][0]["outpoint"]] + outpoints = [next( + c["outpoint"] + for c in lianad.rpc.listcoins()["coins"] + if c["spend_info"] is None + )] destinations = { bitcoind.rpc.getnewaddress(): 200_000, } @@ -182,3 +188,33 @@ def test_coinbase_deposit(lianad, bitcoind): # We must have detected a new deposit. wait_for(lambda: len(lianad.rpc.listcoins()["coins"]) == 1) + + +@pytest.mark.skipif( + OLD_LIANAD_PATH is None, reason="Need the old lianad binary to create the datadir." +) +def test_migration(lianad_multisig, bitcoind): + """Test we can start a newer lianad on a datadir created by an older lianad.""" + lianad = lianad_multisig + + # Set the old binary and re-create the datadir. + lianad.cmd_line[0] = OLD_LIANAD_PATH + lianad.restart_fresh(bitcoind) + assert lianad.rpc.getinfo()["version"] == "0.3.0" + + # Perform some transactions. On Liana v0.3 there was no "updated_at" for Spend + # transaction drafts. + receive_and_send(lianad, bitcoind) + spend_txs = lianad.rpc.listspendtxs()["spend_txs"] + assert len(spend_txs) == 2 and all("updated_at" not in s for s in spend_txs) + + # Set back the new binary. We should be able to read and, if necessary, upgrade + # the old database and generally all files from the datadir. + lianad.cmd_line[0] = LIANAD_PATH + lianad.restart_fresh(bitcoind) + + # And we can go on to create more deposits and transactions. Make sure we now have + # the "updated_at" field on tx drafts. + receive_and_send(lianad, bitcoind) + spend_txs = lianad.rpc.listspendtxs()["spend_txs"] + assert len(spend_txs) == 2 and all(s["updated_at"] is not None for s in spend_txs)