|
1 | 1 | import os |
2 | 2 | import tempfile |
3 | | -import time |
| 3 | + |
| 4 | +from base64 import b64encode |
4 | 5 |
|
5 | 6 | from fixtures import * |
6 | 7 | from test_framework.utils import COIN, DEPOSIT_ADDRESS, DERIV_INDEX, CSV |
@@ -119,6 +120,73 @@ def test_max_value_in_flight(miradord, bitcoind): |
119 | 120 | miradord.wait_for_log(f"Forgetting about consumed vault at '{deposit_outpoint}'") |
120 | 121 |
|
121 | 122 |
|
| 123 | +def test_revault_attempts_without_spend_tx(miradord, bitcoind, coordinator, noise_keys): |
| 124 | + """ |
| 125 | + Sanity check that we are only going to revault attempts that have no candidate |
| 126 | + spend transaction. |
| 127 | + """ |
| 128 | + plugin_path = os.path.join( |
| 129 | + os.path.dirname(__file__), "plugins", "revault_no_spend.py" |
| 130 | + ) |
| 131 | + miradord.add_plugins([{"path": plugin_path}]) |
| 132 | + |
| 133 | + # Should get us exactly to the max value |
| 134 | + vaults_txs = [] |
| 135 | + vaults_outpoints = [] |
| 136 | + deposit_value = 4 |
| 137 | + for _ in range(2): |
| 138 | + deposit_txid, deposit_outpoint = bitcoind.create_utxo( |
| 139 | + DEPOSIT_ADDRESS, deposit_value, |
| 140 | + ) |
| 141 | + bitcoind.generate_block(1, deposit_txid) |
| 142 | + txs = miradord.watch_vault(deposit_outpoint, deposit_value * COIN, DERIV_INDEX) |
| 143 | + vaults_outpoints.append(deposit_outpoint) |
| 144 | + vaults_txs.append(txs) |
| 145 | + |
| 146 | + # We share the spend to the coordinator only for vault #0 |
| 147 | + spend_tx = b64encode(bytes.fromhex(vaults_txs[0]["spend"]["tx"])).decode() |
| 148 | + coordinator.set_spend_tx(noise_keys["manager"].privkey, [vaults_outpoints[0]], spend_tx) |
| 149 | + |
| 150 | + bitcoind.rpc.sendrawtransaction(vaults_txs[0]["unvault"]["tx"]) |
| 151 | + unvault_txid = bitcoind.rpc.decoderawtransaction(vaults_txs[0]["unvault"]["tx"])["txid"] |
| 152 | + bitcoind.generate_block(1, unvault_txid) |
| 153 | + miradord.wait_for_logs( |
| 154 | + [ |
| 155 | + f"Got a confirmed Unvault UTXO for vault at '{vaults_outpoints[0]}'", |
| 156 | + "Done processing block", |
| 157 | + ] |
| 158 | + ) |
| 159 | + bitcoind.rpc.sendrawtransaction(vaults_txs[1]["unvault"]["tx"]) |
| 160 | + unvault_txid = bitcoind.rpc.decoderawtransaction(vaults_txs[1]["unvault"]["tx"])["txid"] |
| 161 | + bitcoind.generate_block(1, unvault_txid) |
| 162 | + miradord.wait_for_logs( |
| 163 | + [ |
| 164 | + f"Got a confirmed Unvault UTXO for vault at '{vaults_outpoints[1]}'", |
| 165 | + f"Broadcasted Cancel transaction '{vaults_txs[1]['cancel']['tx']['20']}'", |
| 166 | + ] |
| 167 | + ) |
| 168 | + |
| 169 | + # The Cancel transactions has been broadcast because the spend was not |
| 170 | + # shared to coordinator. |
| 171 | + cancel_txid = bitcoind.rpc.decoderawtransaction(vaults_txs[1]["cancel"]["tx"]["20"])["txid"] |
| 172 | + bitcoind.generate_block(1, wait_for_mempool=cancel_txid) |
| 173 | + miradord.wait_for_log( |
| 174 | + f"Cancel transaction was confirmed for vault at '{vaults_outpoints[1]}'" |
| 175 | + ) |
| 176 | + |
| 177 | + # Now mine the spend tx for vault #0 |
| 178 | + bitcoind.generate_block(CSV) |
| 179 | + bitcoind.rpc.sendrawtransaction(vaults_txs[0]["spend"]["tx"]) |
| 180 | + spend_txid = bitcoind.rpc.decoderawtransaction(vaults_txs[0]["spend"]["tx"])["txid"] |
| 181 | + bitcoind.generate_block(1, wait_for_mempool=spend_txid) |
| 182 | + miradord.wait_for_log( |
| 183 | + f"Noticed .* that Spend transaction was confirmed for vault at '{vaults_outpoints[0]}'" |
| 184 | + ) |
| 185 | + # Generate two days worth of blocks, the WT should forget about this vault |
| 186 | + bitcoind.generate_block(288) |
| 187 | + miradord.wait_for_log(f"Forgetting about consumed vault at '{deposit_outpoint}'") |
| 188 | + |
| 189 | + |
122 | 190 | def test_multiple_plugins(miradord, bitcoind): |
123 | 191 | """Test we use the union of all plugins output to revault. That is, the stricter one |
124 | 192 | will always rule.""" |
|
0 commit comments