def __init__( self, datadir, noise_priv, bitcoin_priv, listen_port, managers_noisekeys, ): TailableProc.__init__(self, datadir, verbose=VERBOSE) self.conf_file = os.path.join(datadir, "config.toml") self.cmd_line = [COSIGNERD_PATH, "--conf", f"{self.conf_file}"] self.prefix = "cosignerd" noise_secret_file = os.path.join(datadir, "noise_secret") with open(noise_secret_file, "wb") as f: f.write(noise_priv) bitcoin_secret_file = os.path.join(datadir, "bitcoin_secret") with open(bitcoin_secret_file, "wb") as f: f.write(bitcoin_priv) with open(self.conf_file, "w") as f: f.write("daemon = false\n") f.write(f'data_dir = "{datadir}"\n') f.write(f'log_level = "{LOG_LEVEL}"\n') f.write(f'listen = "127.0.0.1:{listen_port}"\n') for k in managers_noisekeys: f.write("[[managers]]\n") f.write(f' noise_key = "{k.hex()}"\n')
def start(self): TailableProc.start(self) self.wait_for_logs([ "revaultd started on network regtest", "bitcoind now synced", "JSONRPC server started", "Signature fetcher thread started", ])
def test_sigfetcher(revault_network, bitcoind, executor): rn = revault_network rn.deploy(7, 3, n_stkmanagers=2) # First of all, activate a vault vault = revault_network.fund(0.05) revault_network.secure_vault(vault) revault_network.activate_vault(vault) # Stopping revaultd, deleting the database for w in rn.participants(): w.stop() datadir_db = os.path.join(w.datadir_with_network, "revaultd.sqlite3") os.remove(datadir_db) # Starting revaultd again for w in rn.participants(): # Manually starting it so that we can check that # the db is being created again TailableProc.start(w) w.wait_for_logs([ "No database at .*, creating a new one", "revaultd started on network regtest", "bitcoind now synced", "JSONRPC server started", "Signature fetcher thread started", ]) # They should all get back to the 'active' state, pulling sigs from the coordinator for w in rn.participants(): w.wait_for_log("Got a new unconfirmed deposit") wait_for(lambda: len(w.rpc.listvaults(["funded"], [])) == 1) for w in rn.stks(): w.wait_for_logs([ "Syncing Unvault Emergency signature", "Syncing Emergency signature", "Syncing Cancel signature", "Syncing Unvault signature", ]) for w in rn.man_wallets: w.wait_for_logs([ "Syncing Cancel signature", "Syncing Unvault signature", ])
def stop(self, timeout=10): try: self.rpc.stop() self.wait_for_logs([ "Stopping revaultd.", "Bitcoind received shutdown.", "Signature fetcher thread received shutdown.", ]) self.proc.wait(timeout) except Exception as e: logging.error(f"{self.prefix} : error when calling stop: '{e}'") return TailableProc.stop(self)
def __init__(self, bitcoin_dir, rpcport=None): TailableProc.__init__(self, bitcoin_dir, verbose=False) if rpcport is None: rpcport = reserve() self.bitcoin_dir = bitcoin_dir self.rpcport = rpcport self.p2pport = reserve() self.prefix = "bitcoind" regtestdir = os.path.join(bitcoin_dir, "regtest") if not os.path.exists(regtestdir): os.makedirs(regtestdir) self.cmd_line = [ "bitcoind", "-datadir={}".format(bitcoin_dir), "-printtoconsole", "-server", "-logtimestamps", "-rpcthreads=4", ] bitcoind_conf = { "port": self.p2pport, "rpcport": rpcport, "debug": 1, "fallbackfee": Decimal(1000) / bitcoin.core.COIN, } self.conf_file = os.path.join(bitcoin_dir, "bitcoin.conf") with open(self.conf_file, "w") as f: f.write("chain=regtest\n") f.write("[regtest]\n") for k, v in bitcoind_conf.items(): f.write(f"{k}={v}\n") self.rpc = SimpleBitcoinProxy( bitcoind_dir=self.bitcoin_dir, bitcoind_port=self.rpcport ) self.proxies = []
def __init__(self, bitcoin_dir, rpcport=None): TailableProc.__init__(self, bitcoin_dir, verbose=False) if rpcport is None: rpcport = reserve() self.bitcoin_dir = bitcoin_dir self.rpcport = rpcport self.p2pport = reserve() self.prefix = "bitcoind" regtestdir = os.path.join(bitcoin_dir, "regtest") if not os.path.exists(regtestdir): os.makedirs(regtestdir) self.cmd_line = [ BITCOIND_PATH, "-datadir={}".format(bitcoin_dir), "-printtoconsole", "-server", ] bitcoind_conf = { "port": self.p2pport, "rpcport": rpcport, "debug": 1, "fallbackfee": Decimal(1000) / COIN, "rpcthreads": 32, } self.conf_file = os.path.join(bitcoin_dir, "bitcoin.conf") with open(self.conf_file, "w") as f: f.write("chain=regtest\n") f.write("[regtest]\n") for k, v in bitcoind_conf.items(): f.write(f"{k}={v}\n") self.rpc = BitcoindRpcInterface(bitcoin_dir, "regtest", rpcport)
def start(self): TailableProc.start(self) self.wait_for_log("Started cosignerd daemon")
def __init__( self, datadir, deposit_desc, unvault_desc, cpfp_desc, noise_priv, coordinator_noise_key, coordinator_port, bitcoind, stk_config=None, man_config=None, ): assert stk_config is not None or man_config is not None TailableProc.__init__(self, datadir, verbose=VERBOSE) self.prefix = os.path.split(datadir)[-1] # The data is stored in a per-network directory. We need to create it # in order to write the Noise private key self.datadir_with_network = os.path.join(datadir, "regtest") os.makedirs(self.datadir_with_network, exist_ok=True) bin = os.path.join(os.path.dirname(__file__), "..", "..", "target/debug/revaultd") self.conf_file = os.path.join(datadir, "config.toml") self.cmd_line = [bin, "--conf", f"{self.conf_file}"] socket_path = os.path.join(self.datadir_with_network, "revaultd_rpc") self.rpc = UnixDomainSocketRpc(socket_path) noise_secret_file = os.path.join(self.datadir_with_network, "noise_secret") with open(noise_secret_file, "wb") as f: f.write(noise_priv) bitcoind_cookie = os.path.join(bitcoind.bitcoin_dir, "regtest", ".cookie") with open(self.conf_file, "w") as f: f.write(f"data_dir = '{datadir}'\n") f.write("daemon = false\n") f.write(f"log_level = '{LOG_LEVEL}'\n") f.write(f'coordinator_host = "127.0.0.1:{coordinator_port}"\n') f.write(f'coordinator_noise_key = "{coordinator_noise_key}"\n') f.write("coordinator_poll_seconds = 5\n") f.write("[scripts_config]\n") f.write(f'deposit_descriptor = "{deposit_desc}"\n') f.write(f'unvault_descriptor = "{unvault_desc}"\n') f.write(f'cpfp_descriptor = "{cpfp_desc}"\n') f.write("[bitcoind_config]\n") f.write('network = "regtest"\n') f.write(f"cookie_path = '{bitcoind_cookie}'\n") f.write(f"addr = '127.0.0.1:{bitcoind.rpcport}'\n") f.write("poll_interval_secs = 10\n") if stk_config is not None: f.write("[stakeholder_config]\n") self.stk_keychain = stk_config["keychain"] f.write(f'xpub = "{self.stk_keychain.get_xpub()}"\n') f.write("watchtowers = [") for wt in stk_config["watchtowers"]: f.write(f"{{ \"host\" = \"{wt['host']}\", \"noise_key\" = " f"\"{wt['noise_key'].hex()}\" }}, ") f.write("]\n") f.write( f"emergency_address = \"{stk_config['emergency_address']}\"\n" ) if man_config is not None: f.write("[manager_config]\n") self.man_keychain = man_config["keychain"] f.write(f'xpub = "{self.man_keychain.get_xpub()}"\n') for cosig in man_config["cosigners"]: f.write("[[manager_config.cosigners]]\n") f.write(f"host = \"{cosig['host']}\"\n") f.write(f"noise_key = \"{cosig['noise_key'].hex()}\"\n")
def stop(self, timeout=10): return TailableProc.stop(self)
def start(self): TailableProc.start(self) self.wait_for_logs([ "bitcoind now synced", "Listener thread started", "Started miradord." ])
def __init__( self, datadir, deposit_desc, unvault_desc, cpfp_desc, emer_addr, listen_port, noise_priv, stk_noise_key, coordinator_noise_key, coordinator_port, bitcoind_rpcport, bitcoind_cookie, plugins=[], ): """All public keys must be hex""" TailableProc.__init__(self, datadir, verbose=VERBOSE) self.prefix = os.path.split(datadir)[-1] self.noise_secret = noise_priv self.listen_port = listen_port self.deposit_desc = deposit_desc self.unvault_desc = unvault_desc self.cpfp_desc = cpfp_desc self.emer_addr = emer_addr # The data is stored in a per-network directory. We need to create it # in order to write the Noise private key self.datadir_with_network = os.path.join(datadir, "regtest") os.makedirs(self.datadir_with_network, exist_ok=True) self.conf_file = os.path.join(datadir, "config.toml") self.cmd_line = [MIRADORD_PATH, "--conf", f"{self.conf_file}"] self.noise_secret_file = os.path.join(self.datadir_with_network, "noise_secret") with open(self.noise_secret_file, "wb") as f: f.write(noise_priv) wt_noise_key = bytes(Curve25519Private(noise_priv).public_key) logging.debug( f"Watchtower Noise key: {wt_noise_key.hex()}, Stakeholder Noise key: {stk_noise_key}" ) with open(self.conf_file, "w") as f: f.write(f"data_dir = '{datadir}'\n") f.write("daemon = false\n") f.write(f"log_level = '{LOG_LEVEL}'\n") f.write(f'stakeholder_noise_key = "{stk_noise_key}"\n') f.write(f'coordinator_host = "127.0.0.1:{coordinator_port}"\n') f.write(f'coordinator_noise_key = "{coordinator_noise_key}"\n') f.write("coordinator_poll_seconds = 5\n") f.write(f'listen = "127.0.0.1:{listen_port}"\n') f.write("[scripts_config]\n") f.write(f'deposit_descriptor = "{deposit_desc}"\n') f.write(f'unvault_descriptor = "{unvault_desc}"\n') f.write(f'cpfp_descriptor = "{cpfp_desc}"\n') f.write(f'emergency_address = "{emer_addr}"\n') f.write("[bitcoind_config]\n") f.write('network = "regtest"\n') f.write(f"cookie_path = '{bitcoind_cookie}'\n") f.write(f"addr = '127.0.0.1:{bitcoind_rpcport}'\n") f.write("poll_interval_secs = 5\n") f.write(f"\n{toml.dumps({'plugins': plugins})}\n")
def start(self): TailableProc.start(self) self.wait_for_log("Done loading", timeout=TIMEOUT) logging.info("BitcoinD started")
def stop(self): for p in self.proxies: p.stop() self.rpc.stop() return TailableProc.stop(self)
def start(self): TailableProc.start(self) self.wait_for_logs(["Started revault_coordinatord"])
def __init__( self, datadir, noise_priv, managers_keys, stakeholders_keys, watchtowers_keys, listen_port, bitcoind_rpc_port, bitcoind_cookie_path, postgres_user, postgres_pass, postgres_host="localhost", ): # FIXME: reduce DEBUG log load TailableProc.__init__(self, datadir, verbose=VERBOSE) self.conf_file = os.path.join(datadir, "config.toml") self.cmd_line = [COORDINATORD_PATH, "--conf", f"{self.conf_file}"] self.prefix = "coordinatord" self.postgres_user = postgres_user self.postgres_pass = postgres_pass self.postgres_host = postgres_host # Use the directory fixture uid uid = os.path.basename(os.path.dirname( os.path.dirname(datadir))).replace("-", "") self.db_name = f"revault_coordinatord_{uid}" # Cleanup a potential leftover from a crashed test try: self.postgres_exec(f"DROP DATABASE {self.db_name}") except psycopg2.errors.InvalidCatalogName: pass # Now actually create it self.postgres_exec( f"CREATE DATABASE {self.db_name} OWNER {postgres_user}") noise_secret_file = os.path.join(datadir, "noise_secret") with open(noise_secret_file, "wb") as f: f.write(noise_priv) with open(self.conf_file, "w") as f: f.write("daemon = false\n") f.write(f'data_dir = "{datadir}"\n') f.write(f'log_level = "{LOG_LEVEL}"\n') uri = (f"postgresql://{postgres_user}:{postgres_pass}" f"@{postgres_host}/{self.db_name}") f.write(f'postgres_uri = "{uri}"\n') f.write("managers = [") for k in managers_keys: f.write(f'"{k.hex()}", ') f.write("]\n") f.write("stakeholders = [") for k in stakeholders_keys: f.write(f'"{k.hex()}", ') f.write("]\n") f.write("watchtowers = [") for k in watchtowers_keys: f.write(f'"{k.hex()}", ') f.write("]\n") f.write(f'listen = "127.0.0.1:{listen_port}"\n') f.write("[bitcoind_config]\n") f.write(f"cookie_path = '{bitcoind_cookie_path}'\n") f.write(f"addr = '127.0.0.1:{bitcoind_rpc_port}'\n") f.write("broadcast_interval = 5\n")
def __init__( self, datadir, stks, cosigs, mans, csv, noise_priv, coordinator_noise_key, coordinator_port, bitcoind, stk_config=None, man_config=None, ): assert stk_config is not None or man_config is not None assert len(stks) == len(cosigs) TailableProc.__init__(self, datadir, verbose=VERBOSE) self.prefix = os.path.split(datadir)[-1] # The data is stored in a per-network directory. We need to create it # in order to write the Noise private key self.datadir_with_network = os.path.join(datadir, "regtest") os.makedirs(self.datadir_with_network, exist_ok=True) bin = os.path.join(os.path.dirname(__file__), "..", "..", "target/debug/revaultd") self.conf_file = os.path.join(datadir, "config.toml") self.cmd_line = [bin, "--conf", f"{self.conf_file}"] socket_path = os.path.join(self.datadir_with_network, "revaultd_rpc") self.rpc = UnixDomainSocketRpc(socket_path) noise_secret_file = os.path.join(self.datadir_with_network, "noise_secret") with open(noise_secret_file, "wb") as f: f.write(noise_priv) bitcoind_cookie = os.path.join(bitcoind.bitcoin_dir, "regtest", ".cookie") with open(self.conf_file, "w") as f: f.write(f"unvault_csv = {csv}\n") f.write(f"data_dir = '{datadir}'\n") f.write("daemon = false\n") f.write(f"log_level = '{LOG_LEVEL}'\n") f.write(f'coordinator_host = "127.0.0.1:{coordinator_port}"\n') f.write(f'coordinator_noise_key = "{coordinator_noise_key}"\n') f.write("coordinator_poll_seconds = 2\n") f.write("stakeholders_xpubs = [") for stk in stks: f.write(f'"{stk.get_xpub()}", ') f.write("]\n") f.write("managers_xpubs = [") for man in mans: f.write(f'"{man.get_xpub()}", ') f.write("]\n") f.write("cosigners_keys = [") for cosig in cosigs: f.write(f'"{cosig.get_static_key().hex()}", ') f.write("]\n") f.write("[bitcoind_config]\n") f.write('network = "regtest"\n') f.write(f"cookie_path = '{bitcoind_cookie}'\n") f.write(f"addr = '127.0.0.1:{bitcoind.rpcport}'\n") f.write("poll_interval_secs = 3\n") if stk_config is not None: f.write("[stakeholder_config]\n") self.stk_keychain = stk_config["keychain"] f.write(f'xpub = "{self.stk_keychain.get_xpub()}"\n') f.write("watchtowers = [") for wt in stk_config["watchtowers"]: f.write(f"{{ \"host\" = \"{wt['host']}\", \"noise_key\" = " f"\"{wt['noise_key'].hex()}\" }}, ") f.write("]\n") # FIXME: eventually use a real one here f.write( "emergency_address = " '"bcrt1qewc2348370pgw8kjz8gy09z8xyh0d9fxde6nzamd3txc9gkmjqmq8m4cdq"\n' ) if man_config is not None: f.write("[manager_config]\n") self.man_keychain = man_config["keychain"] f.write(f'xpub = "{self.man_keychain.get_xpub()}"\n') for cosig in man_config["cosigners"]: f.write("[[manager_config.cosigners]]\n") f.write(f"host = \"{cosig['host']}\"\n") f.write(f"noise_key = \"{cosig['noise_key'].hex()}\"\n")