mirror of
https://github.com/basicswap/basicswap.git
synced 2025-11-05 18:38:09 +01:00
network: Automatically set direct simplex mode per bid.
This commit is contained in:
@@ -2296,7 +2296,7 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
|
||||
offer_bytes = msg_buf.to_bytes()
|
||||
payload_hex = str.format("{:02x}", MessageTypes.OFFER) + offer_bytes.hex()
|
||||
msg_valid: int = max(self.SMSG_SECONDS_IN_HOUR, valid_for_seconds)
|
||||
# Send offers to active and bridged networks, message_nets contains only the active networks.
|
||||
# Send offers to active and bridged networks
|
||||
offer_id = self.sendMessage(
|
||||
offer_addr, offer_addr_to, payload_hex, msg_valid, cursor
|
||||
)
|
||||
@@ -3277,8 +3277,11 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
|
||||
"amount_from": amount,
|
||||
"amount_to": amount_to,
|
||||
}
|
||||
bid_message_nets = self.selectMessageNetStringForConcept(
|
||||
Concepts.OFFER, offer_id, offer.message_nets, cursor
|
||||
)
|
||||
route_id, route_established = self.prepareMessageRoute(
|
||||
MessageNetworks.SIMPLEX,
|
||||
bid_message_nets,
|
||||
request_data,
|
||||
bid_addr,
|
||||
offer.addr_from,
|
||||
@@ -3291,10 +3294,6 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
|
||||
dt.datetime.fromtimestamp(now).date(), contract_count
|
||||
)
|
||||
|
||||
bid_message_nets = self.selectMessageNetStringForConcept(
|
||||
Concepts.OFFER, offer_id, offer.message_nets, cursor
|
||||
)
|
||||
|
||||
bid = Bid(
|
||||
protocol_version=PROTOCOL_VERSION_SECRET_HASH,
|
||||
active_ind=1,
|
||||
@@ -3905,7 +3904,7 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
|
||||
|
||||
def prepareMessageRoute(
|
||||
self,
|
||||
network_id,
|
||||
message_nets,
|
||||
req_data,
|
||||
addr_from: str,
|
||||
addr_to: str,
|
||||
@@ -3915,9 +3914,34 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
|
||||
if self._use_direct_message_routes is False:
|
||||
return None, False
|
||||
|
||||
# message_nets contains the network selected to use:
|
||||
# TODO: allow multiple networks
|
||||
self.logD(LC.NET, f"prepareMessageRoute message_nets {message_nets}")
|
||||
|
||||
if message_nets.startswith("b."):
|
||||
# TODO: get direct messages working through portals
|
||||
self.logD(LC.NET, "Not using route - bridged networks.")
|
||||
return None, False
|
||||
if len(message_nets) == 0:
|
||||
if len(self.active_networks) == 1:
|
||||
network_id: int = networkTypeToID(
|
||||
self.active_networks[0].get("type", "smsg")
|
||||
)
|
||||
else:
|
||||
raise RuntimeError(
|
||||
"Network must be specified if multiple networks are active."
|
||||
)
|
||||
else:
|
||||
network_id: int = networkTypeToID(message_nets)
|
||||
if network_id not in (MessageNetworks.SIMPLEX,):
|
||||
return None, False
|
||||
try:
|
||||
net_i = self.getActiveNetworkInterface(2)
|
||||
net_i = self.getActiveNetworkInterface(network_id)
|
||||
except Exception as e: # noqa: F841
|
||||
self.logD(
|
||||
LC.NET,
|
||||
f"Not using route - network interface not found for {network_id}.",
|
||||
)
|
||||
return None, False
|
||||
|
||||
# Look for active route
|
||||
@@ -3950,13 +3974,18 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
|
||||
|
||||
msg_valid: int = max(self.SMSG_SECONDS_IN_HOUR, valid_for_seconds)
|
||||
connect_req_msgid = self.sendMessage(
|
||||
addr_from, addr_to, payload_hex, msg_valid, cursor
|
||||
addr_from,
|
||||
addr_to,
|
||||
payload_hex,
|
||||
msg_valid,
|
||||
cursor,
|
||||
message_nets=message_nets,
|
||||
)
|
||||
|
||||
now: int = self.getTime()
|
||||
message_route = DirectMessageRoute(
|
||||
active_ind=2,
|
||||
network_id=2,
|
||||
network_id=network_id,
|
||||
linked_type=Concepts.OFFER,
|
||||
smsg_addr_local=addr_from,
|
||||
smsg_addr_remote=addr_to,
|
||||
@@ -4034,8 +4063,11 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
|
||||
"amount_from": amount,
|
||||
"amount_to": amount_to,
|
||||
}
|
||||
bid_message_nets = self.selectMessageNetStringForConcept(
|
||||
Concepts.OFFER, offer.offer_id, offer.message_nets, cursor
|
||||
)
|
||||
route_id, route_established = self.prepareMessageRoute(
|
||||
MessageNetworks.SIMPLEX,
|
||||
bid_message_nets,
|
||||
request_data,
|
||||
bid_addr,
|
||||
offer.addr_from,
|
||||
@@ -4043,9 +4075,6 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
|
||||
valid_for_seconds,
|
||||
)
|
||||
|
||||
bid_message_nets = self.selectMessageNetStringForConcept(
|
||||
Concepts.OFFER, offer.offer_id, offer.message_nets, cursor
|
||||
)
|
||||
reverse_bid: bool = self.is_reverse_ads_bid(coin_from, coin_to)
|
||||
if reverse_bid:
|
||||
reversed_rate: int = ci_to.make_int(amount / amount_to, r=1)
|
||||
@@ -7554,7 +7583,7 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
|
||||
self.log.debug("Ignoring expired offer.")
|
||||
return
|
||||
|
||||
_ = self.expandMessageNets(offer_data.message_nets) # Decode to validate
|
||||
self.validateMessageNets(offer_data.message_nets)
|
||||
|
||||
offer_rate: int = ci_from.make_int(
|
||||
offer_data.amount_to / offer_data.amount_from, r=1
|
||||
@@ -7997,7 +8026,7 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
|
||||
bid_rate: int = ci_from.make_int(bid_data.amount_to / bid_data.amount, r=1)
|
||||
self.validateBidAmount(offer, bid_data.amount, bid_rate)
|
||||
|
||||
_ = self.expandMessageNets(bid_data.message_nets) # Decode to validate
|
||||
self.validateMessageNets(bid_data.message_nets)
|
||||
|
||||
network_type: str = msg.get("msg_net", "smsg")
|
||||
network_type_received_on_id: int = networkTypeToID(network_type)
|
||||
@@ -8468,7 +8497,7 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
|
||||
if ci_to.curve_type() == Curves.ed25519:
|
||||
ensure(len(bid_data.kbsf_dleag) <= 16000, "Invalid kbsf_dleag size")
|
||||
|
||||
_ = self.expandMessageNets(bid_data.message_nets) # Decode to validate
|
||||
self.validateMessageNets(bid_data.message_nets)
|
||||
|
||||
bid_id = bytes.fromhex(msg["msgid"])
|
||||
|
||||
@@ -10006,7 +10035,7 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
|
||||
ensure(offer.swap_type == SwapTypes.XMR_SWAP, "Bid/offer swap type mismatch")
|
||||
ensure(xmr_offer, f"Adaptor-sig offer not found: {self.log.id(offer_id)}.")
|
||||
|
||||
_ = self.expandMessageNets(bid_data.message_nets) # Decode to validate
|
||||
self.validateMessageNets(bid_data.message_nets)
|
||||
|
||||
ci_from = self.ci(offer.coin_to)
|
||||
ci_to = self.ci(offer.coin_from)
|
||||
@@ -10027,7 +10056,7 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
|
||||
)
|
||||
self.validateBidAmount(offer, bid_data.amount_from, bid_rate)
|
||||
|
||||
_ = self.expandMessageNets(bid_data.message_nets)
|
||||
_, _ = self.expandMessageNets(bid_data.message_nets)
|
||||
|
||||
bid_id = bytes.fromhex(msg["msgid"])
|
||||
|
||||
@@ -10197,7 +10226,7 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
|
||||
offer_id = bytes.fromhex(req_data["offer_id"])
|
||||
bidder_addr = req_data["bsx_address"]
|
||||
|
||||
net_i = self.getActiveNetworkInterface(2)
|
||||
net_i = self.getActiveNetworkInterface(MessageNetworks.SIMPLEX)
|
||||
try:
|
||||
cursor = self.openDB()
|
||||
offer = self.getOffer(offer_id, cursor)
|
||||
|
||||
@@ -724,7 +724,7 @@ class DirectMessageRouteLink(Table):
|
||||
class NetworkPortal(Table):
|
||||
__tablename__ = "network_portals"
|
||||
|
||||
def __init__(
|
||||
def set(
|
||||
self, time_start, time_valid, network_from, network_to, address_from, address_to
|
||||
):
|
||||
super().__init__()
|
||||
|
||||
@@ -50,15 +50,18 @@ def networkTypeToID(type: str) -> int:
|
||||
return MessageNetworks.SMSG
|
||||
elif type == "simplex":
|
||||
return MessageNetworks.SIMPLEX
|
||||
raise RuntimeError(f"Unknown message type: {type}")
|
||||
raise RuntimeError(f"Unknown message network type: {type}")
|
||||
|
||||
|
||||
def networkIDToType(id: int) -> str:
|
||||
def networkIDToType(id: int, bridged: bool = False) -> str:
|
||||
network_name = None
|
||||
if id == MessageNetworks.SMSG:
|
||||
return "smsg"
|
||||
network_name = "smsg"
|
||||
elif id == MessageNetworks.SIMPLEX:
|
||||
return "simplex"
|
||||
raise RuntimeError(f"Unknown message network id: {id}")
|
||||
network_name = "simplex"
|
||||
else:
|
||||
raise RuntimeError(f"Unknown message network id: {id}")
|
||||
return ("b." if bridged else "") + network_name
|
||||
|
||||
|
||||
class BSXNetwork:
|
||||
@@ -350,7 +353,11 @@ class BSXNetwork:
|
||||
for bridged_network in network.get("bridged", []):
|
||||
bridged_network_type = bridged_network.get("type", "smsg")
|
||||
bridged_networks_set.add(bridged_network_type)
|
||||
all_networks = active_networks_set | bridged_networks_set
|
||||
all_networks = active_networks_set
|
||||
# Join without duplicates, bridged networks are prefixed with "b."
|
||||
for bridged_network in bridged_networks_set:
|
||||
if bridged_network not in active_networks_set:
|
||||
all_networks.add("b." + bridged_network)
|
||||
return ",".join(all_networks)
|
||||
|
||||
def selectMessageNetString(
|
||||
@@ -366,26 +373,42 @@ class BSXNetwork:
|
||||
for bridged_network in network.get("bridged", []):
|
||||
bridged_network_type = bridged_network.get("type", "smsg")
|
||||
bridged_networks_set.add(networkTypeToID(bridged_network_type))
|
||||
remote_network_ids = self.expandMessageNets(remote_message_nets)
|
||||
remote_active_network_ids, remote_bridged_network_ids = self.expandMessageNets(
|
||||
remote_message_nets
|
||||
)
|
||||
|
||||
if len(remote_network_ids) < 1 and len(received_on_network_ids) < 1:
|
||||
# If no data was sent it must be from an old version
|
||||
if (
|
||||
len(remote_active_network_ids) < 1
|
||||
and len(remote_bridged_network_ids) < 1
|
||||
and len(received_on_network_ids) < 1
|
||||
):
|
||||
return networkIDToType(random.choice(tuple(active_networks_set)))
|
||||
|
||||
# Choose which network to respond on
|
||||
# Pick the received on network if it's in the local node's active networks and the list of remote node's networks
|
||||
# Pick the received on network if it's in the local node's active networks and the list of remote node's active networks
|
||||
# else prefer a network the local node has active
|
||||
for received_on_id in received_on_network_ids:
|
||||
if (
|
||||
received_on_id in active_networks_set
|
||||
and received_on_id in remote_network_ids
|
||||
and received_on_id in remote_active_network_ids
|
||||
):
|
||||
return networkIDToType(received_on_id)
|
||||
# Prefer to use a network both nodes have active
|
||||
for local_net_id in active_networks_set:
|
||||
if local_net_id in remote_network_ids:
|
||||
if local_net_id in remote_active_network_ids:
|
||||
return networkIDToType(local_net_id)
|
||||
# Else prefer to use a network this node has active
|
||||
for local_net_id in active_networks_set:
|
||||
if local_net_id in remote_bridged_network_ids:
|
||||
return networkIDToType(local_net_id, True)
|
||||
|
||||
for local_net_id in bridged_networks_set:
|
||||
if local_net_id in remote_network_ids:
|
||||
return networkIDToType(local_net_id)
|
||||
if local_net_id in remote_active_network_ids:
|
||||
return networkIDToType(local_net_id, True)
|
||||
for local_net_id in bridged_networks_set:
|
||||
if local_net_id in remote_bridged_network_ids:
|
||||
return networkIDToType(local_net_id, True)
|
||||
raise RuntimeError("Unable to select network to respond on")
|
||||
|
||||
def selectMessageNetStringForConcept(
|
||||
@@ -409,18 +432,30 @@ class BSXNetwork:
|
||||
|
||||
return self.selectMessageNetString(received_on_network_ids, remote_message_nets)
|
||||
|
||||
def expandMessageNets(self, message_nets: str) -> list:
|
||||
def expandMessageNets(self, message_nets: str) -> (list, list):
|
||||
if message_nets is None or len(message_nets) < 1:
|
||||
return []
|
||||
return [], []
|
||||
if len(message_nets) > 256:
|
||||
raise ValueError("message_nets string is too large")
|
||||
rv = []
|
||||
active_networks = []
|
||||
bridged_networks = []
|
||||
for network_string in message_nets.split(","):
|
||||
add_to_list = active_networks
|
||||
if network_string.startswith("b."):
|
||||
network_string = network_string[2:]
|
||||
add_to_list = bridged_networks
|
||||
try:
|
||||
rv.append(networkTypeToID(network_string))
|
||||
network_id: int = networkTypeToID(network_string)
|
||||
except Exception as e: # noqa: F841
|
||||
self.log.debug(f"Unknown message_net {network_string}")
|
||||
return rv
|
||||
if network_id in active_networks or network_id in bridged_networks:
|
||||
raise ValueError("Malformed networks data.")
|
||||
add_to_list.append(network_id)
|
||||
return active_networks, bridged_networks
|
||||
|
||||
def validateMessageNets(self, message_nets: str) -> None:
|
||||
# Decode to validate
|
||||
_, _ = self.expandMessageNets(message_nets)
|
||||
|
||||
def getMessageRoute(
|
||||
self, network_id: int, address_from: str, address_to: str, cursor=None
|
||||
@@ -463,12 +498,14 @@ class BSXNetwork:
|
||||
linked_id=None,
|
||||
timestamp=None,
|
||||
deterministic=False,
|
||||
message_nets=None, # None -> all, else
|
||||
message_nets=None, # None|empty -> all
|
||||
) -> bytes:
|
||||
message_id: bytes = None
|
||||
networks_list = self.expandMessageNets(
|
||||
active_networks_list, bridged_networks_list = self.expandMessageNets(
|
||||
message_nets
|
||||
) # Empty list means send to all networks
|
||||
)
|
||||
# Empty list means send to all networks
|
||||
networks_list = active_networks_list + bridged_networks_list
|
||||
networks_sent_to = set()
|
||||
|
||||
# Message routes work only with simplex messages for now.
|
||||
@@ -478,7 +515,7 @@ class BSXNetwork:
|
||||
|
||||
message_route = self.getMessageRoute(2, addr_from, addr_to, cursor=cursor)
|
||||
if message_route:
|
||||
network = self.getActiveNetwork(2)
|
||||
network = self.getActiveNetwork(MessageNetworks.SIMPLEX)
|
||||
net_i = network["ws_thread"]
|
||||
|
||||
remote_name = None
|
||||
@@ -699,7 +736,7 @@ class BSXNetwork:
|
||||
self.num_smsg_messages_sent += 1
|
||||
|
||||
def processContactDisconnected(self, event_data) -> None:
|
||||
net_i = self.getActiveNetworkInterface(2)
|
||||
net_i = self.getActiveNetworkInterface(MessageNetworks.SIMPLEX)
|
||||
connId = getResponseData(event_data, "contact")["activeConn"]["connId"]
|
||||
self.log.info(f"Direct message route disconnected, connId: {connId}")
|
||||
closeSimplexChat(self, net_i, connId)
|
||||
@@ -727,7 +764,7 @@ class BSXNetwork:
|
||||
self.closeDB(cursor)
|
||||
|
||||
def closeMessageRoute(self, record_id, network_id, route_data, cursor):
|
||||
net_i = self.getActiveNetworkInterface(2)
|
||||
net_i = self.getActiveNetworkInterface(MessageNetworks.SIMPLEX)
|
||||
|
||||
connId = route_data["pccConnId"]
|
||||
|
||||
@@ -774,7 +811,8 @@ class BSXNetwork:
|
||||
addr_portal: str = self.prepareSMSGAddress(
|
||||
None, AddressTypes.PORTAL_LOCAL, cursor
|
||||
)
|
||||
portal = NetworkPortal(
|
||||
portal = NetworkPortal()
|
||||
portal.set(
|
||||
now, 30 * 60, network_from_id, network_to_id, addr_portal, addr_to
|
||||
)
|
||||
portal.created_at = now
|
||||
@@ -971,7 +1009,8 @@ class BSXNetwork:
|
||||
},
|
||||
)
|
||||
if received_portal is None:
|
||||
received_portal = NetworkPortal(
|
||||
received_portal = NetworkPortal()
|
||||
received_portal.set(
|
||||
time_start,
|
||||
portal_data.time_valid,
|
||||
portal_data.network_type_from,
|
||||
|
||||
Reference in New Issue
Block a user