From d779132178482a4ffafdfba564d09c689107d80e Mon Sep 17 00:00:00 2001 From: Adam Gibson Date: Tue, 26 Sep 2023 08:33:40 -0600 Subject: [PATCH] first draft --- src/jmdaemon/daemon_protocol.py | 42 ++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/src/jmdaemon/daemon_protocol.py b/src/jmdaemon/daemon_protocol.py index 9fdd641d6..6a9578fa2 100644 --- a/src/jmdaemon/daemon_protocol.py +++ b/src/jmdaemon/daemon_protocol.py @@ -873,6 +873,17 @@ def on_pubkey(self, nick, maker_pk): """This is handled locally in the daemon; set up e2e encrypted messaging with this counterparty """ + # We have a time-out of 60 seconds after which a received + # pubkey message is too delayed; if we receive that here we + # have to just ignore the counterparty. + if "auth_sent" in self.active_orders.keys(): + return + # by the same token, as soon as we have received at least + # one !pubkey message, we start the countdown (60s) to just + # going ahead: + if not "taker_waiting_for_pubkey" in self.active_orders.keys(): + reactor.callLater(60.0, self.send_all_auth) + self.active_orders["taker_waiting_for_pubkey"] = True if nick not in self.active_orders.keys(): log.msg("Counterparty not part of this transaction. Ignoring") return @@ -883,7 +894,36 @@ def on_pubkey(self, nick, maker_pk): print("Unable to setup crypto box with " + nick + ": " + repr(e)) self.mcc.send_error(nick, "invalid nacl pubkey: " + maker_pk) return - self.mcc.prepare_privmsg(nick, "auth", str(self.revelation)) + self.active_orders[nick]["received_pubkey"] = True + self.send_all_auth() + + @taker_only + def send_all_auth(self, force:bool =False) -> None: + """ We enforce the condition that the !auth messages + are only sent to each maker after *every* participating + maker has already sent their !pubkey message. This prevents + the possibility of one maker already reaching the !ioauth + stage, and broadcasting the commitment, before another maker + has even received the !fill message (which can cause + erroneous blacklisting/preventing taking part in the coinjoin), + in cases where there is a very big mismatch in connection + speed. + If `force` is True, this function will send the auth messages + to all makers that have currently replied, and consider the + other makers in the `active_orders` dict to be unreachable, + and ignore them for the rest of the coinjoin construction. + """ + if not all(["received_pubkey" in x + for x in self.active_orders]) and not force: + return + # the laggards should be wiped out from the dict, in order to + # continue phase 2 cleanly: + l = [k for k in self.active_orders + if "received_pubkey" in self.active_orders[k]] + self.active_orders = {k: self.active_orders[k] for k in l} + for nick in self.active_orders: + self.mcc.prepare_privmsg(nick, "auth", str(self.revelation)) + self.active_orders["auth_sent"] = True @taker_only def on_ioauth(self, nick, utxo_list, auth_pub, cj_addr, change_addr,