Skip to content

Commit

Permalink
wip whitelist
Browse files Browse the repository at this point in the history
  • Loading branch information
edouardparis committed Jul 5, 2022
1 parent 3814572 commit 669a235
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 0 deletions.
33 changes: 33 additions & 0 deletions tests/plugins/whitelist.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/usr/bin/env python3
"""A plugin which returns any attempt with a spend transaction sending funds to unknown addresses"""

import json
import sys
import bitcoin


def read_request():
"""Read a JSON request from stdin up to the '\n' delimiter."""
buf = ""
while len(buf) == 0 or buf[-1] != "\n":
buf += sys.stdin.read()
return json.loads(buf)


if __name__ == "__main__":
req = read_request()
block_info = req["block_info"]
whitelist_file = open(req["config"]["whitelist_file_path"], 'r')
whitelist = map(lambda address: address.strip(), whitelist_file.readlines())

vaults_without_spend_outpoints = []
for vault in block_info["new_attempts"]:
if vault["candidate_tx"] is None:
vaults_without_spend_outpoints.append(vault["deposit_outpoint"])
else:
candidate_tx = bitcoin.deserialize(vault["candidate_tx"])
vaults_without_spend_outpoints.append(vault["deposit_outpoint"])

resp = {"revault": vaults_without_spend_outpoints}
sys.stdout.write(json.dumps(resp))
sys.stdout.flush()
1 change: 1 addition & 0 deletions tests/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ bip32~=2.0
pynacl==1.4
noiseprotocol==0.3.1
toml==0.10.2
bitcoin==1.1.42

# For the bitcoind proxy
Flask==2.0.3
Expand Down
97 changes: 97 additions & 0 deletions tests/test_plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,103 @@ def test_revault_attempts_without_spend_tx(miradord, bitcoind, coordinator, nois
miradord.wait_for_log(f"Forgetting about consumed vault at '{deposit_outpoint}'")


def test_whitelist(miradord, bitcoind, coordinator, noise_keys):
"""
Sanity check that we are only going to revault attempts that have no candidate
spend transaction.
"""

whitelist_file_path = os.path.join(
os.path.dirname(__file__), "plugins", "whitelist.txt"
)
plugin_path = os.path.join(os.path.dirname(__file__), "plugins", "whitelist.py")
miradord.add_plugins(
[{"path": plugin_path, "config": {"whitelist_file_path": whitelist_file_path}}]
)

vaults_txs = []
vaults_outpoints = []
deposit_value = 4
for i in range(2):
deposit_txid, deposit_outpoint = bitcoind.create_utxo(
DEPOSIT_ADDRESS,
deposit_value,
)
bitcoind.generate_block(1, deposit_txid)
txs = miradord.watch_vault(
deposit_outpoint, deposit_value * COIN, DERIV_INDEX + i
)
vaults_outpoints.append(deposit_outpoint)
vaults_txs.append(txs)

# We append the address of the first spend tx to the whitelist
whitelist_file = open(whitelist_file_path, "w")
spend_tx = bitcoind.rpc.decoderawtransaction(vaults_txs[0]["spend"]["tx"])
for output in spend_tx["vout"]:
whitelist_file.write(output["scriptPubKey"]["address"])
whitelist_file.write("\n")
whitelist_file.close()

# We share the spend txs to the coordinators
spend_tx = b64encode(bytes.fromhex(vaults_txs[0]["spend"]["tx"])).decode()
coordinator.set_spend_tx(
noise_keys["manager"].privkey, [vaults_outpoints[0]], spend_tx
)
spend_tx = b64encode(bytes.fromhex(vaults_txs[1]["spend"]["tx"])).decode()
coordinator.set_spend_tx(
noise_keys["manager"].privkey, [vaults_outpoints[1]], spend_tx
)

# Unvault the two vaults
bitcoind.rpc.sendrawtransaction(vaults_txs[0]["unvault"]["tx"])
unvault_txid = bitcoind.rpc.decoderawtransaction(vaults_txs[0]["unvault"]["tx"])[
"txid"
]
bitcoind.generate_block(1, unvault_txid)
miradord.wait_for_logs(
[
f"Got a confirmed Unvault UTXO for vault at '{vaults_outpoints[0]}'",
"Done processing block",
]
)
bitcoind.rpc.sendrawtransaction(vaults_txs[1]["unvault"]["tx"])
unvault_txid = bitcoind.rpc.decoderawtransaction(vaults_txs[1]["unvault"]["tx"])[
"txid"
]
bitcoind.generate_block(1, unvault_txid)
miradord.wait_for_logs(
[
f"Got a confirmed Unvault UTXO for vault at '{vaults_outpoints[1]}'",
f"Broadcasted Cancel transaction '{vaults_txs[1]['cancel']['tx']['20']}'",
]
)

# The Cancel transactions has been broadcast for vault #1 because the spend
# was sending funds to an address not present in the whitelist file.
cancel_txid = bitcoind.rpc.decoderawtransaction(
vaults_txs[1]["cancel"]["tx"]["20"]
)["txid"]
bitcoind.generate_block(1, wait_for_mempool=cancel_txid)
miradord.wait_for_log(
f"Cancel transaction was confirmed for vault at '{vaults_outpoints[1]}'"
)

# Now mine the spend tx for vault #0
bitcoind.generate_block(CSV)
bitcoind.rpc.sendrawtransaction(vaults_txs[0]["spend"]["tx"])
spend_txid = bitcoind.rpc.decoderawtransaction(vaults_txs[0]["spend"]["tx"])["txid"]
bitcoind.generate_block(1, wait_for_mempool=spend_txid)
miradord.wait_for_log(
f"Noticed .* that Spend transaction was confirmed for vault at '{vaults_outpoints[0]}'"
)
# Generate two days worth of blocks, the WT should forget about this vault
bitcoind.generate_block(288)
miradord.wait_for_log(f"Forgetting about consumed vault at '{deposit_outpoint}'")

# clean the whitelist file
os.remove(whitelist_file_path)


def test_multiple_plugins(miradord, bitcoind):
"""Test we use the union of all plugins output to revault. That is, the stricter one
will always rule."""
Expand Down

0 comments on commit 669a235

Please sign in to comment.