def close(self): # publish h2c commit if possible commit_rawtx = self.finalize_commit(self._get_wif, self.h2c_state) if commit_rawtx is not None: self._history_add_published_h2c_commit(commit_rawtx) # get h2c spend secret if no commits for channel h2c_spend_secret = None if len(self.h2c_state["commits_active"]) == 0: deposit_script = self.h2c_state["deposit_script"] spend_hash = scripts.get_deposit_spend_secret_hash(deposit_script) h2c_spend_secret = self.secrets[spend_hash] # tell hub to close the channel result = self.api.mph_close(handle=self.handle, spend_secret=h2c_spend_secret) # remember c2h spend secret if given c2h_spend_secret = result["spend_secret"] if c2h_spend_secret: secret_hash = util.hash160hex(c2h_spend_secret) self.secrets[secret_hash] = c2h_spend_secret return commit_rawtx
def publish_commits(): with etc.database_lock: txids = [] cursor = sql.get_cursor() for hub_connection in db.hub_connections_complete(cursor=cursor): asset = hub_connection["asset"] c2h_mpc_id = hub_connection["c2h_channel_id"] c2h_state = db.load_channel_state(c2h_mpc_id, asset, cursor=cursor) h2c_mpc_id = hub_connection["h2c_channel_id"] h2c_state = db.load_channel_state(h2c_mpc_id, asset, cursor=cursor) h2c_spend_secret_hash = get_deposit_spend_secret_hash( h2c_state["deposit_script"]) h2c_spend_secret = lib.get_secret(h2c_spend_secret_hash) c2h_expired = lib.is_expired(c2h_state, etc.expire_clearance) h2c_expired = lib.is_expired(h2c_state, etc.expire_clearance) expired = c2h_expired or h2c_expired h2c_commits_published = api.mpc_published_commits(state=h2c_state) closed = hub_connection["closed"] != 0 # connection expired or commit published or spend secret known if expired or closed or h2c_commits_published or h2c_spend_secret: if not closed: db.set_connection_closed(handle=hub_connection["handle"]) c2h_commits_published = api.mpc_published_commits( state=c2h_state) if len(c2h_commits_published) == 0: txid = Mpc(api).finalize_commit(lib.get_wif, c2h_state) if txid: txids.append(txid) return txids
def publish_commits(): with etc.database_lock: commit_rawtxs = [] cursor = sql.get_cursor() for hub_connection in db.hub_connections_complete(cursor=cursor): asset = hub_connection["asset"] c2h_mpc_id = hub_connection["c2h_channel_id"] c2h_state = db.load_channel_state(c2h_mpc_id, asset, cursor=cursor) h2c_mpc_id = hub_connection["h2c_channel_id"] h2c_state = db.load_channel_state(h2c_mpc_id, asset, cursor=cursor) h2c_spend_secret_hash = get_deposit_spend_secret_hash( h2c_state["deposit_script"] ) h2c_spend_secret = lib.get_secret(h2c_spend_secret_hash) c2h_expired = lib.is_expired(c2h_state, etc.expire_clearance) h2c_expired = lib.is_expired(h2c_state, etc.expire_clearance) expired = c2h_expired or h2c_expired h2c_commits_published = api.mpc_published_commits(state=h2c_state) closed = hub_connection["closed"] != 0 # connection expired or commit published or spend secret known if expired or closed or h2c_commits_published or h2c_spend_secret: if not closed: db.set_connection_closed(handle=hub_connection["handle"]) rawtx = Mpc(api).finalize_commit(lib.get_wif, c2h_state) if rawtx: commit_rawtxs.append(rawtx) return commit_rawtxs
def close_connection(handle, h2c_spend_secret=None): cursor = sql.get_cursor() hub_connection = db.hub_connection(handle=handle, cursor=cursor) # save secret if given and not already known if h2c_spend_secret is not None: secret_hash = util.hash160hex(h2c_spend_secret) if not get_secret(secret_hash): db.add_secret(secret_value=h2c_spend_secret, secret_hash=secret_hash, cursor=cursor) # close connection if not already done if not hub_connection["closed"]: db.set_connection_closed(handle=handle, cursor=cursor) # get c2h spend secret if no commits for channel c2h_spend_secret = None c2h_state = db.load_channel_state(hub_connection["c2h_channel_id"], hub_connection["asset"], cursor=cursor) if len(c2h_state["commits_active"]) == 0: c2h_spend_secret_hash = scripts.get_deposit_spend_secret_hash( c2h_state["deposit_script"]) c2h_spend_secret = get_secret(c2h_spend_secret_hash) hub_key = db.channel_payer_key(id=hub_connection["h2c_channel_id"]) return ({"spend_secret": c2h_spend_secret}, hub_key["wif"])
def close_connection(handle, h2c_spend_secret=None): cursor = sql.get_cursor() hub_connection = db.hub_connection(handle=handle, cursor=cursor) # save secret if given and not already known if h2c_spend_secret is not None: secret_hash = util.hash160hex(h2c_spend_secret) if not get_secret(secret_hash): db.add_secret(secret_value=h2c_spend_secret, secret_hash=secret_hash, cursor=cursor) # close connection if not already done if not hub_connection["closed"]: db.set_connection_closed(handle=handle, cursor=cursor) # get c2h spend secret if no commits for channel c2h_spend_secret = None c2h_state = db.load_channel_state(hub_connection["c2h_channel_id"], hub_connection["asset"], cursor=cursor) if len(c2h_state["commits_active"]) == 0: c2h_spend_secret_hash = scripts.get_deposit_spend_secret_hash( c2h_state["deposit_script"] ) c2h_spend_secret = get_secret(c2h_spend_secret_hash) hub_wif = load_wif() return ({"spend_secret": c2h_spend_secret}, hub_wif)
def full_duplex_recover_funds(self, get_wif_func, get_secret_func, recv_state, send_state): # get send spend secret if known send_spend_secret_hash = scripts.get_deposit_spend_secret_hash( send_state["deposit_script"] ) send_spend_secret = get_secret_func(send_spend_secret_hash) txids = [] # get payouts for payout_tx in self.api.mpc_payouts(state=recv_state): txids.append(self.recover_payout( get_wif_func=get_wif_func, get_secret_func=get_secret_func, **payout_tx )) rtxs = self.api.mpc_recoverables(state=send_state, spend_secret=send_spend_secret) for revoke_tx in rtxs["revoke"]: txids.append(self.recover_revoked( get_wif_func=get_wif_func, **revoke_tx )) for change_tx in rtxs["change"]: txids.append(self.recover_change( get_wif_func=get_wif_func, **change_tx )) for expire_tx in rtxs["expire"]: txids.append(self.recover_expired( get_wif_func=get_wif_func, **expire_tx )) return txids
def close_input(handle, client_pubkey, spend_secret): hub_connection(handle) _channel_client(handle, client_pubkey) # validate spend secret for h2c deposit if spend_secret is not None: validate.is_string(spend_secret) spend_secret_hash = util.hash160hex(spend_secret) deposit_script = db.h2c_channel(handle=handle)["deposit_script"] expected_hash = scripts.get_deposit_spend_secret_hash(deposit_script) if expected_hash != spend_secret_hash: raise err.InvalidSpendSecret(expected_hash, spend_secret)
def close_input(handle, client_pubkey, spend_secret): hub_connection(handle) _channel_client(handle, client_pubkey) # validate spend secret for h2c deposit if spend_secret is not None: validate.is_string(spend_secret) spend_secret_hash = util.hash160hex(spend_secret) deposit_script = db.h2c_channel(handle=handle)["deposit_script"] expected_hash = scripts.get_deposit_spend_secret_hash(deposit_script) if expected_hash != spend_secret_hash: raise err.InvalidSpendSecret(expected_hash, spend_secret)
def full_duplex_recover_funds(self, get_wif_func, get_secret_func, recv_state, send_state): # get send spend secret if known send_spend_secret_hash = scripts.get_deposit_spend_secret_hash( send_state["deposit_script"]) send_spend_secret = get_secret_func(send_spend_secret_hash) rawtxs = { "payout": {}, # {"txid": "rawtx"} "revoke": {}, # {"txid": "rawtx"} "change": {}, # {"txid": "rawtx"} "expire": {}, # {"txid": "rawtx"} "commit": {}, # {"txid": "rawtx"} "deposit": {}, # {"txid": "rawtx"} } # get payouts for payout_tx in self.api.mpc_payouts(state=recv_state): rawtx = self.recover_payout(get_wif_func=get_wif_func, get_secret_func=get_secret_func, **payout_tx) rawtxs["payout"][util.gettxid(rawtx)] = rawtx rtxs = self.api.mpc_recoverables(state=send_state, spend_secret=send_spend_secret) for revoke_tx in rtxs["revoke"]: rawtx = self.recover_revoked(get_wif_func=get_wif_func, **revoke_tx) rawtxs["revoke"][util.gettxid(rawtx)] = rawtx for change_tx in rtxs["change"]: rawtx = self.recover_change(get_wif_func=get_wif_func, **change_tx) rawtxs["change"][util.gettxid(rawtx)] = rawtx for expire_tx in rtxs["expire"]: rawtx = self.recover_expired(get_wif_func=get_wif_func, **expire_tx) rawtxs["expire"][util.gettxid(rawtx)] = rawtx return rawtxs
def close(self): commit_txid = self.finalize_commit(self._get_wif, self.h2c_state) # get h2c spend secret if no commits for channel h2c_spend_secret = None if len(self.h2c_state["commits_active"]) == 0: deposit_script = self.h2c_state["deposit_script"] spend_hash = scripts.get_deposit_spend_secret_hash(deposit_script) h2c_spend_secret = self.secrets[spend_hash] # tell hub to close the channel result = self.api.mph_close(handle=self.handle, spend_secret=h2c_spend_secret) # remember c2h spend secret if given c2h_spend_secret = result["spend_secret"] if c2h_spend_secret: secret_hash = util.hash160hex(c2h_spend_secret) self.secrets[secret_hash] = c2h_spend_secret return commit_txid
def full_duplex_channel_status(self, handle, netcode, send_state, recv_state, get_secret_func, clearance=6): assert (send_state["asset"] == recv_state["asset"]) asset = send_state["asset"] send_ttl = self.api.mpc_deposit_ttl(state=send_state, clearance=clearance) send_script = send_state["deposit_script"] send_deposit_expire_time = scripts.get_deposit_expire_time(send_script) send_deposit_address = util.script_address(send_script, netcode=netcode) send_balances = self.get_balances(send_deposit_address, ["BTC", asset]) send_deposit = send_balances.get(asset, 0) send_transferred = 0 if len(send_state["commits_active"]) > 0: send_transferred = self.api.mpc_transferred_amount( state=send_state) recv_ttl = self.api.mpc_deposit_ttl(state=recv_state, clearance=clearance) recv_script = recv_state["deposit_script"] recv_deposit_expire_time = scripts.get_deposit_expire_time(recv_script) recv_deposit_address = util.script_address(recv_script, netcode=netcode) recv_balances = self.get_balances(recv_deposit_address, ["BTC", asset]) recv_deposit = recv_balances.get(asset, 0) recv_transferred = 0 if len(recv_state["commits_active"]) > 0: recv_transferred = self.api.mpc_transferred_amount( state=recv_state) send_balance = send_deposit + recv_transferred - send_transferred recv_balance = recv_deposit + send_transferred - recv_transferred ttl = None if send_ttl is not None and recv_ttl is not None: ttl = min(send_ttl, recv_ttl) # get connection status status = "opening" if send_ttl and recv_ttl: status = "open" send_secret_hash = scripts.get_deposit_spend_secret_hash(send_script) send_secret = get_secret_func(send_secret_hash) send_commits_published = self.api.mpc_published_commits( state=send_state) expired = ttl == 0 # None explicitly ignore as channel opening if expired or send_secret or send_commits_published: status = "closed" send_balance = send_deposit recv_balance = 0 return { # FIXME get channel tx history "status": status, "asset": asset, "netcode": netcode, "balance": send_balance, "ttl": ttl, "send_balance": send_balance, "send_deposit_address": send_deposit_address, "send_deposit_ttl": send_ttl, "send_deposit_balances": send_balances, "send_deposit_expire_time": send_deposit_expire_time, "send_commits_published": send_commits_published, "send_transferred_quantity": send_transferred, "recv_balance": recv_balance, "recv_deposit_address": recv_deposit_address, "recv_deposit_ttl": recv_ttl, "recv_deposit_balances": recv_balances, "recv_deposit_expire_time": recv_deposit_expire_time, "recv_transferred_quantity": recv_transferred, }