2-hop peerswap #397
YusukeShimizu
started this conversation in
Ideas
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Define the minimal extension that enables atomic swaps even over a 2-hop path
u → m → v.Motivation
PeerSwap can perform atomic swap between direct nodes. However, in real networks many two-hop paths exist where exactly one intermediary node forms the route,
u → m → v. We therefore want to enable swaps over these paths as well.Network Model
ch₁andch₂are public LN channelsuandvare already connected via p2p (TCP) and can exchange BOLT#1 custom messagesmsupports PeerSwap or notNotation
u: initiatorm: intermediaryv: responderMessages
Policy
Affected messages (type numbers stay the same)
swap_out_requestAdditional Fields
twohop: object — A container that signals 2-hop discovery mode.The receiver treats the message as 2-hop only when this object is present.
twohop.intermediary_pubkey: string (33-byte compressed pubkey, hex) —the pubkey of the intermediary node m
Behaviour
twohopis present, the receiver v derives its local channelch₂(m–v) fromintermediary_pubkey, computes its ownreceivable_msat, and decides whether the requested amount is within theexecutable range.
Compatibility
twohopignores the unknown field andwill safely reject the request for ordinary reasons (e.g. the
scidis not a direct channel or
amount = 0).swap_out_agreementAdditional Fields (all OPTIONAL)
twohop: object — The result of 2-hop discovery.twohop.incoming_scid: string (e.g."x:y:z") —the short_channel_id of
ch₂(m–v)Behaviour
twohopis present, the receiver u pays thepayreqvia a 2-hop routethat includes
incoming_scid.Notes
standard LN APIs).
swap_in_requestAdditional Fields
twohop: object — Container that signals 2-hop discovery mode.twohop.intermediary_pubkey: string (33-byte compressed pubkey, hex) —the pubkey of the intermediary node m
Behaviour
twohopis present, the receiver v identifies its localch₂(m–v) fromintermediary_pubkeyand checks whether the requestedamountcan be sent.Compatibility
twohopignores the field and rejectsthe request using the current rules (
scid,amount, etc.).swap_in_agreementAdditional Fields (all OPTIONAL)
twohop: object — The result of 2-hop discovery.twohop.incoming_scid: string (e.g."x:y:z") —the short_channel_id of
ch₂(m–v), viewed from v (m → v)Behaviour
twohopis present, the responder v, when making the payment, verifiesthat the receivable amount on
incoming_scid** is sufficient for**
amount.Doing the Swap
twohopis present, the swap maker locates its localch₁(u–m) usingintermediary_pubkey, then pays thepayreqover the2-hop route that includes
scid.Extension of the
pollMessage (Optional Proposal)Purpose
Let the intermediary m periodically broadcast its own
connected_peerslist.Doing so makes it easier for u and v to discover potential 2-hop routes.
Method
Add an optional
neighbors_adobject to the existingpollJSON.Nodes that do not understand the field simply ignore it, so backward compatibility is preserved.
In most cases it is sufficient to send it on the same schedule as the ordinary
poll.Example of the extended
pollmessage:{ "version": 5, "assets": ["btc", "lbtc"], "peer_allowed": true, "btc_swap_in_premium_rate_ppm": 100, "btc_swap_out_premium_rate_ppm": 200, "lbtc_swap_in_premium_rate_ppm": 50, "lbtc_swap_out_premium_rate_ppm": 150, "neighbors_ad": { "v": 1, "public_only": true, "limit": 20, "entries": [ { "node_id": "<pubkey-of-neighbor>", "channels": [ { "channel_id": 1234567890, "short_channel_id": "x:y:z", "active": true // Optional (not sent by default): // "local_balance": 0, // "remote_balance": 0 } ] } ] } }Sending policy
When transmitting, the LN node extracts public and active neighbours from its channel list.
By default no balance information is sent (privacy). The operator may opt-in to send approx values.
If the number of neighbours exceeds
limit, prune by random / score order.Send triggers: the regular
pollinterval and the reply to an initialrequest_poll.Receiver behaviour
A listener can build a list of 2-hop candidates — even to nodes with which it does not share a direct channel.
Conceptual example of a 2-hop candidate list:
[ { "nodeid": "<v_pubkey>", "intermediary_nodeid": "<m_pubkey>", "outgoing_scid": "<ch1 u–m>", "incoming_scid": "<ch2 m–v>", "spendable_msat": 0, "receivable_msat": 0, "sent": { "total_swaps_out": 2, "total_swaps_in": 1, "total_sats_swapped_out": 5300000, "total_sats_swapped_in": 302938 }, "received": { "total_swaps_out": 1, "total_swaps_in": 0, "total_sats_swapped_out": 2400000, "total_sats_swapped_in": 0 }, "total_fee_paid": 6082, "swap_in_premium_rate_ppm": 100, "swap_out_premium_rate_ppm": 100 } ]When actually executing a swap, the implementation can pick transparently from this list, but — given equal conditions — a direct 1-hop path should always be preferred.
Peer-Discovery Strategy
The
pollextension makes it easier to estimate whether a 2-hop swap is possible and what the rough capacity might be.Even without it, discovery can still be done by probing directly, but this is less efficient.
connected_peers)Beta Was this translation helpful? Give feedback.
All reactions