-
Notifications
You must be signed in to change notification settings - Fork 3.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
onion messages #9039
base: master
Are you sure you want to change the base?
onion messages #9039
Conversation
693e836
to
8c707dc
Compare
2475cc9
to
62ea5d6
Compare
62ea5d6
to
0b53afa
Compare
this branch is now |
4ce8580
to
9c4bec1
Compare
d7d81e9
to
20b8bd9
Compare
652ced0
to
c38ba15
Compare
7bb7596
to
d0251c1
Compare
480777f
to
7c70ce3
Compare
9717523
to
570370a
Compare
…bkey case also clear up some comment phrasing
additional reply_path route strategies; use peers or connect to wellknown, fix dest/intropoint is direct peer
0b4db71
to
c731d4d
Compare
|
||
def test_create_blinded_path(self): | ||
pubkey = bfh('02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619') # alice | ||
session_key = bfh('3030303030303030303030303030303030303030303030303030303030303030') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
any reason why session_key is '303030..' and not '030303...' here? is this a typo?
The current version of Firstly, there is redundancy between Secondly, passing a boolean that affects the type of the returned result is also not very beautiful. I think this method should always return I suggest to rewrite def get_shared_secrets_along_route(payment_path_pubkeys: Sequence[bytes],
- session_key: bytes) -> Sequence[bytes]:
+ session_key: bytes) -> Tuple[Sequence[bytes], Sequence[bytes]]:
num_hops = len(payment_path_pubkeys)
hop_shared_secrets = num_hops * [b'']
+ hop_blinded_node_ids = num_hops * [b'']
ephemeral_key = session_key
# compute shared key for each hop
for i in range(0, num_hops):
hop_shared_secrets[i] = get_ecdh(ephemeral_key, payment_path_pubkeys[i])
+ hop_blinded_node_ids[i] = get_blinded_node_id(payment_path_pubkeys[i], hop_shared_secrets[i])
ephemeral_pubkey = ecc.ECPrivkey(ephemeral_key).get_public_key_bytes()
blinding_factor = sha256(ephemeral_pubkey + hop_shared_secrets[i])
blinding_factor_int = int.from_bytes(blinding_factor, byteorder="big")
ephemeral_key_int = int.from_bytes(ephemeral_key, byteorder="big")
ephemeral_key_int = ephemeral_key_int * blinding_factor_int % ecc.CURVE_ORDER
ephemeral_key = ephemeral_key_int.to_bytes(32, byteorder="big")
- return hop_shared_secrets
+ return hop_shared_secrets, hop_blinded_node_ids
This is a lot simpler than the current PR, and I believe this is sufficient. If we need to create a blinded path with an override (for the moment this is only needed in the unit tests AFAICT), then it is easy to do that by calling the above method twice, and concatenate the results: hop_shared_secrets1, blinded_node_ids1 = get_shared_secrets_along_route([ALICE_PUBKEY], BLINDING_SECRET)
hop_shared_secrets2, blinded_node_ids2 = get_shared_secrets_along_route([BOB_PUBKEY, CAROL_PUBKEY, DAVE_PUBKEY], BLINDING_OVERRIDE_SECRET)
hop_shared_secrets = hop_shared_secrets1 + hop_shared_secrets2
blinded_node_ids = blinded_node_ids1 + blinded_node_ids2 |
electrum/lnonion.py
Outdated
@@ -211,6 +259,29 @@ def new_onion_packet( | |||
hmac=next_hmac) | |||
|
|||
|
|||
def encrypt_encrypted_data_tlv(*, shared_secret, **kwargs): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This name is unfortunate. It suggests that we are encrypting a second time something that was already encrypted. It is enough to call this method encrypt_data_tlv
(and to call the next one decrypt_data_tlv
). And, yes, I am aware that the name encrypted_data_tlv
is part of the spec. That's not a reason.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, this looks confusing. I would suggest encrypt_onionmsg_data_tlv
then, to indicate it is an onion message record.
@@ -1462,7 +1461,7 @@ def send_node_announcement(self, alias:str): | |||
addrlen=len(addresses), | |||
addresses=addresses) | |||
h = sha256d(raw_msg[64+2:]) | |||
signature = ecc.ECPrivkey(self.privkey).ecdsa_sign(h, sigencode=ecdsa_sig64_from_r_and_s) | |||
signature = ECPrivkey(self.privkey).ecdsa_sign(h, sigencode=ecdsa_sig64_from_r_and_s) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This kind of cosmetic change can be committed to master independently of this pull request. It is not useful to include it in the pull request.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was done to be consistent with ECPubkey
, which was already imported and used without ecc.
our_onion_private_key=self.privkey, | ||
associated_data=payment_hash, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here, no reason to overload a PR with parameter reordering.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
well, associated_data
was moved to a kwarg, so it makes sense here.
if peer_addr := lnwallet.channel_db.get_last_good_address(node_id): | ||
peer = await lnwallet.add_peer(str(peer_addr)) | ||
await peer.initialized | ||
return [PathEdge(short_channel_id=None, start_node=None, end_node=node_id)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this really needed? Bolt-04 suggests that onion messages should use already existing connections, not create new ones:
Onion messages allow peers to use existing connections
I would rather not have methods that create extra peer connections as side-effect, unless there is a clear use case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently, the number of onion message supporting nodes is very limited. If the user has only channels with nodes that do not support onion messages, doing a bolt12 invoice_request
will always fail.
In the future, when most of the network is onion message capable, this will not be an issue anymore, so it can be seen as a transitional feature.
Note1: we only open a peer connection if the client wants to perform a invoice_request
and no route can be found over the existing channel peers, so there's a clear use-case.
Note2: C-Lightning currently opens new peer connections as well, if needed.
Another thing that needs to be improved is the unit tests provided in this PR. We should refrain from copy-pasting long hexadecimal strings in our code. Since there is a json file provided by the RFC, why not use that file directly? Here is a branch where I started to do that: |
Also note that some of the provided unit tests are not very useful ( |
Renaming |
A general note on formatting: if we use multiple lines for the parameters passed to a function, we should avoid indenting them at the level of the opening parenthesis, but use an extra line instead. Example: - blinded_path = OnionWireSerializer._read_complex_field(fd=blinded_path_fd,
- field_type='blinded_path',
- count=1)
+ blinded_path = OnionWireSerializer._read_complex_field(
+ fd=blinded_path_fd,
+ field_type='blinded_path',
+ count=1) Why? because changing the method name will trigger reindentation of all the lines in the first case, not in the second case. This results in larger diffs. See for example the commit where |
…t_onionmsg_data_tlv
…test_path_pubkeys_blinded_path_appended
Yes I don't like it either.
Yes this is much better |
This PR is ready for review.
get_blinded_path_via
to construct a blinded pathsend_onion_message
to send a textonionmsg_tlv.message
payload to a node_id or blinded pathinfo
levelOnionMessageManager
class implementing queues for rate limitingonionmsg_tlv.message
payloads, which are fire-and-forget, but eventually bolt12 will need this for e.g. 'invoice_request')subtype
declarations in wire definitionsTesting
Alice <-> Bob <-> Carol <-> Dave
using node_ids and blinded paths as destination.alice get_blinded_path_via $(bob nodeid)
carol send_onion_message <blinded path> hello
Alice <-> cln01 <-> cln02 <-> cln03 <-> Bob
bolt12
branch to issueinvoice_request
fromoffer
)known issues