|
4 | 4 | from base64 import b64encode |
5 | 5 |
|
6 | 6 | from fixtures import * |
7 | | -from test_framework.utils import COIN, DEPOSIT_ADDRESS, DERIV_INDEX, CSV |
| 7 | +from test_framework.utils import COIN, DEPOSIT_ADDRESS, DERIV_INDEX, CSV, compile_rust_binary |
8 | 8 |
|
9 | 9 |
|
10 | 10 | def test_max_value_in_flight(miradord, bitcoind): |
@@ -195,6 +195,111 @@ def test_revault_attempts_without_spend_tx(miradord, bitcoind, coordinator, nois |
195 | 195 | miradord.wait_for_log(f"Forgetting about consumed vault at '{deposit_outpoint}'") |
196 | 196 |
|
197 | 197 |
|
| 198 | +def test_whitelist(miradord, bitcoind, coordinator, noise_keys): |
| 199 | + """ |
| 200 | + Sanity check that we are only going to revault attempts that have no candidate |
| 201 | + spend transaction. |
| 202 | + """ |
| 203 | + |
| 204 | + whitelist_file_path = os.path.join( |
| 205 | + os.path.dirname(__file__), "plugins", "whitelist.txt" |
| 206 | + ) |
| 207 | + whitelist_file = open(whitelist_file_path, "w") |
| 208 | + whitelist_file.close() |
| 209 | + |
| 210 | + whitelist_directory = os.path.join(os.path.dirname(__file__), "plugins", "whitelist") |
| 211 | + compile_rust_binary(whitelist_directory) |
| 212 | + |
| 213 | + plugin_path = os.path.join(whitelist_directory, "target", "debug", "whitelist") |
| 214 | + miradord.add_plugins( |
| 215 | + [{"path": plugin_path, "config": {"whitelist_file_path": whitelist_file_path}}] |
| 216 | + ) |
| 217 | + |
| 218 | + vaults_txs = [] |
| 219 | + vaults_outpoints = [] |
| 220 | + deposit_value = 4 |
| 221 | + for i in range(2): |
| 222 | + deposit_txid, deposit_outpoint = bitcoind.create_utxo( |
| 223 | + DEPOSIT_ADDRESS, |
| 224 | + deposit_value, |
| 225 | + ) |
| 226 | + bitcoind.generate_block(1, deposit_txid) |
| 227 | + txs = miradord.watch_vault( |
| 228 | + deposit_outpoint, deposit_value * COIN, DERIV_INDEX |
| 229 | + ) |
| 230 | + vaults_outpoints.append(deposit_outpoint) |
| 231 | + vaults_txs.append(txs) |
| 232 | + |
| 233 | + # We share the spend txs to the coordinators |
| 234 | + spend_tx = b64encode(bytes.fromhex(vaults_txs[0]["spend"]["tx"])).decode() |
| 235 | + coordinator.set_spend_tx( |
| 236 | + noise_keys["manager"].privkey, [vaults_outpoints[0]], spend_tx |
| 237 | + ) |
| 238 | + spend_tx = b64encode(bytes.fromhex(vaults_txs[1]["spend"]["tx"])).decode() |
| 239 | + coordinator.set_spend_tx( |
| 240 | + noise_keys["manager"].privkey, [vaults_outpoints[1]], spend_tx |
| 241 | + ) |
| 242 | + |
| 243 | + # Unvault the second vault |
| 244 | + bitcoind.rpc.sendrawtransaction(vaults_txs[1]["unvault"]["tx"]) |
| 245 | + unvault_txid = bitcoind.rpc.decoderawtransaction(vaults_txs[1]["unvault"]["tx"])[ |
| 246 | + "txid" |
| 247 | + ] |
| 248 | + bitcoind.generate_block(1, unvault_txid) |
| 249 | + miradord.wait_for_logs( |
| 250 | + [ |
| 251 | + f"Got a confirmed Unvault UTXO for vault at '{vaults_outpoints[1]}'", |
| 252 | + f"Broadcasted Cancel transaction '{vaults_txs[1]['cancel']['tx']['20']}'", |
| 253 | + ] |
| 254 | + ) |
| 255 | + |
| 256 | + # The Cancel transactions has been broadcast for vault #1 because the spend |
| 257 | + # was sending funds to an address not present in the whitelist file. |
| 258 | + cancel_txid = bitcoind.rpc.decoderawtransaction( |
| 259 | + vaults_txs[1]["cancel"]["tx"]["20"] |
| 260 | + )["txid"] |
| 261 | + bitcoind.generate_block(1, wait_for_mempool=cancel_txid) |
| 262 | + miradord.wait_for_log( |
| 263 | + f"Cancel transaction was confirmed for vault at '{vaults_outpoints[1]}'" |
| 264 | + ) |
| 265 | + |
| 266 | + # We append the address of the first spend tx to the whitelist |
| 267 | + whitelist_file = open(whitelist_file_path, "w") |
| 268 | + spend_tx = bitcoind.rpc.decoderawtransaction(vaults_txs[0]["spend"]["tx"]) |
| 269 | + for output in spend_tx["vout"]: |
| 270 | + whitelist_file.write(output["scriptPubKey"]["address"]) |
| 271 | + whitelist_file.write("\n") |
| 272 | + whitelist_file.close() |
| 273 | + |
| 274 | + # Unvault the first vault |
| 275 | + bitcoind.rpc.sendrawtransaction(vaults_txs[0]["unvault"]["tx"]) |
| 276 | + unvault_txid = bitcoind.rpc.decoderawtransaction(vaults_txs[0]["unvault"]["tx"])[ |
| 277 | + "txid" |
| 278 | + ] |
| 279 | + bitcoind.generate_block(1, unvault_txid) |
| 280 | + miradord.wait_for_logs( |
| 281 | + [ |
| 282 | + f"Got a confirmed Unvault UTXO for vault at '{vaults_outpoints[0]}'", |
| 283 | + "Done processing block", |
| 284 | + ] |
| 285 | + ) |
| 286 | + |
| 287 | + # Now mine the spend tx for vault #0 |
| 288 | + bitcoind.generate_block(CSV) |
| 289 | + bitcoind.rpc.sendrawtransaction(vaults_txs[0]["spend"]["tx"]) |
| 290 | + spend_txid = bitcoind.rpc.decoderawtransaction(vaults_txs[0]["spend"]["tx"])["txid"] |
| 291 | + bitcoind.generate_block(1, wait_for_mempool=spend_txid) |
| 292 | + miradord.wait_for_log( |
| 293 | + f"Noticed .* that Spend transaction was confirmed for vault at '{vaults_outpoints[0]}'" |
| 294 | + ) |
| 295 | + # Generate two days worth of blocks, the WT should forget about this vault |
| 296 | + bitcoind.generate_block(288) |
| 297 | + miradord.wait_for_log(f"Forgetting about consumed vault at '{deposit_outpoint}'") |
| 298 | + |
| 299 | + # clean the whitelist file |
| 300 | + os.remove(whitelist_file_path) |
| 301 | + |
| 302 | + |
198 | 303 | def test_multiple_plugins(miradord, bitcoind): |
199 | 304 | """Test we use the union of all plugins output to revault. That is, the stricter one |
200 | 305 | will always rule.""" |
|
0 commit comments