diff --git a/lianad/src/bitcoin/poller/looper.rs b/lianad/src/bitcoin/poller/looper.rs index 74c9ba8e..8654a6b4 100644 --- a/lianad/src/bitcoin/poller/looper.rs +++ b/lianad/src/bitcoin/poller/looper.rs @@ -73,10 +73,9 @@ fn update_coins( }; // First of if we are receiving coins that are beyond our next derivation index, // adjust it. - if derivation_index > db_conn.receive_index() { + if !is_change && derivation_index > db_conn.receive_index() { db_conn.set_receive_index(derivation_index, secp); - } - if derivation_index > db_conn.change_index() { + } else if is_change && derivation_index > db_conn.change_index() { db_conn.set_change_index(derivation_index, secp); } diff --git a/tests/test_rpc.py b/tests/test_rpc.py index 318298a8..2a201174 100644 --- a/tests/test_rpc.py +++ b/tests/test_rpc.py @@ -406,27 +406,18 @@ def test_listrevealedaddresses(lianad, bitcoind): assert list_rec["continue_from"] == 7 # same as starting index assert len(list_rec["addresses"]) == 0 - # The poller currently sets the change index to match the receive index. - # See https://github.com/wizardsardine/liana/issues/1333. + # The change index has index 0 as "revealed". assert lianad.rpc.getinfo()["receive_index"] == 7 - assert lianad.rpc.getinfo()["change_index"] == 7 + assert lianad.rpc.getinfo()["change_index"] == 0 - # We can get change addresses: + # We can get the single revealed change address: list_cha = lianad.rpc.listrevealedaddresses(True, False, 3) - assert list_cha["continue_from"] == 4 - assert len(list_cha["addresses"]) == 3 - assert list_cha["addresses"][0]["index"] == 7 - assert list_cha["addresses"][0]["address"] == addresses[7]["change"] + assert list_cha["continue_from"] is None + assert len(list_cha["addresses"]) == 1 + assert list_cha["addresses"][0]["index"] == 0 + assert list_cha["addresses"][0]["address"] == addresses[0]["change"] assert list_cha["addresses"][0]["used_count"] == 0 assert list_cha["addresses"][0]["label"] is None - assert list_cha["addresses"][1]["index"] == 6 - assert list_cha["addresses"][1]["address"] == addresses[6]["change"] - assert list_cha["addresses"][1]["used_count"] == 0 - assert list_cha["addresses"][1]["label"] is None - assert list_cha["addresses"][2]["index"] == 5 - assert list_cha["addresses"][2]["address"] == addresses[5]["change"] - assert list_cha["addresses"][2]["used_count"] == 0 - assert list_cha["addresses"][2]["label"] is None def test_listcoins(lianad, bitcoind): @@ -771,10 +762,8 @@ def test_create_spend(lianad, bitcoind): # 15 new receive addresses have been generated (starting at index 1), # so last used value is 15: assert lianad.rpc.getinfo()["receive_index"] == 15 - # For each received coin, the change index has also been updated by the poller - # (see https://github.com/wizardsardine/liana/issues/1333), so is also 15. - # Then `createspend` will use the next index for change and update the DB value accordingly: - assert lianad.rpc.getinfo()["change_index"] == 16 + # `createspend` will use the next index for change and update the DB value accordingly: + assert lianad.rpc.getinfo()["change_index"] == 1 # The transaction must contain the spent transaction for each input for P2WSH. But not for Taproot. # We don't make assumptions about the ordering of PSBT inputs. diff --git a/tests/test_spend.py b/tests/test_spend.py index c6b08f02..a71ef438 100644 --- a/tests/test_spend.py +++ b/tests/test_spend.py @@ -242,9 +242,7 @@ def test_send_to_self(lianad, bitcoind): info = lianad.rpc.getinfo() assert info["receive_index"] == 3 - # Change index has been updated by poller, even though none used - # (see https://github.com/wizardsardine/liana/issues/1333): - assert info["change_index"] == 3 + assert info["change_index"] == 0 # Then create a send-to-self transaction (by not providing any destination) that # sweeps them all. @@ -258,7 +256,7 @@ def test_send_to_self(lianad, bitcoind): # Send to self didn't use any receive addresses... assert info["receive_index"] == 3 # ... but it did use a new change address: - assert info["change_index"] == 4 + assert info["change_index"] == 1 # Note they may ask for an impossible send-to-self. In this case we'll report missing amount. huge_feerate = 50_000 if USE_TAPROOT else 40_500 @@ -285,23 +283,32 @@ def test_send_to_self(lianad, bitcoind): wait_for(lambda: len(list(unspent_coins())) == 1) info = lianad.rpc.getinfo() - # The poller has updated the receive index based on the change index - # (see https://github.com/wizardsardine/liana/issues/1333): - assert info["receive_index"] == 4 - assert info["change_index"] == 4 + # The indices have not changed: + assert info["receive_index"] == 3 + assert info["change_index"] == 1 # Create a new spend to the receive address with index 3. recv_addr = lianad.rpc.listaddresses(3, 1)["addresses"][0]["receive"] res = lianad.rpc.createspend( {recv_addr: 11_965_000 if USE_TAPROOT else 11_955_000}, [], 2 ) assert "psbt" in res - # Max(receive_index, change_index) is now 4, so we return addresses 0, 1, 2, 3, 4: - assert len(lianad.rpc.listaddresses()["addresses"]) == 5 + # Max(receive_index, change_index) is 3, so we return addresses 0, 1, 2, 3: + assert len(lianad.rpc.listaddresses()["addresses"]) == 4 # But the spend has no change: psbt = PSBT.from_base64(res["psbt"]) assert len(psbt.o) == 1 - # As the spend has no change, only the receive index was incremented. - # Therefore, the DB receive index is now 4. + + # Now sign and broadcast the spend: + signed_psbt = lianad.signer.sign_psbt(psbt) + lianad.rpc.updatespend(signed_psbt.to_base64()) + spend_txid = signed_psbt.tx.txid().hex() + lianad.rpc.broadcastspend(spend_txid) + # Wait for coin to be detected by poller: + wait_for(lambda: len(lianad.rpc.listcoins([], [f"{spend_txid}:0"])["coins"]) == 1) + # The indices have not changed: + info = lianad.rpc.getinfo() + assert info["receive_index"] == 3 + assert info["change_index"] == 1 def test_coin_selection(lianad, bitcoind):