Skip to content
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

lnrpc+peer: custom peer messages #5346

Merged
merged 2 commits into from
Oct 19, 2021

Conversation

joostjager
Copy link
Contributor

@joostjager joostjager commented May 31, 2021

Lightning nodes have a connection to each of their peers for exchanging messages. In regular operation, these messages coordinate processes such as channel opening and payment forwarding.

The lightning spec however also defines a custom range (>= 32768) for experimental and application-specific peer messages.

Custom peer messages open up a whole range of interesting new possibilities. They allow the lightning protocol with its transport mechanisms (including tor) and public key authentication to be leveraged for application-level communication. Note that peers exchange these messages directly. There is no routing/path finding involved.

Some examples:

  • Retrieve node website url or other static information
  • Retrieve channel acceptance policy (for example max channel size)
  • Retrieve channel balances
  • Retrieve message of the day
  • Deliver human-readable messages to the node operator
  • Request liquidity in a specific direction as a preparation for a larger volume of payments that is anticipated
  • Place a web shop order with the lightning invoice in the return message
  • Retrieve web shop price list (assuming the node has something for sale)
  • LNURL over the lightning protocol - eliminate the web server

Application-level communication was already possible using custom tlv records, but considerable restrictions apply. The most obvious being an absolute maximum message size of ~1300 bytes (depending on the route). Also there is no easy way for the receiving node to send a message back. This would involve finding a separate (possibly non-existent) return route. The upside of using custom tlv records is that the data is onion routed just as the carrying payment is, protecting the sender's identity.

For peers that already know each other (for example because they maintain a channel) or don't mind knowing each other, custom tlv records don't make too much sense but do make communication cumbersome and unreliable.

This PR adds to lnd the capability to send and receive custom peer messages via new SendCustomMessage and SubscribeCustomMessages rpc methods. For easy testing, lncli commands are provided.

To send a message:

lncli sendcustom --peer 03e3927c8e408c92be06a3dd0031600ff599abd00588e0e4bb9db217c6f16f0138 --type 42000 --data ff00ff11

To listen for incoming messages:

lncli subscribecustom

Looking for concept ACK.

Todo:

  • tests
  • remove lncli test commands (tbd)

@Crypt-iQ
Copy link
Collaborator

Crypt-iQ commented Jun 4, 2021

Concept ACK

@Crypt-iQ Crypt-iQ added p2p Code related to the peer-to-peer behaviour rpc Related to the RPC interface wire protocol Encoding of messages for the communication between nodes labels Jun 4, 2021
server.go Show resolved Hide resolved
@joostjager joostjager force-pushed the custom-messages branch 2 times, most recently from 2a118cb to 0eb5424 Compare June 12, 2021 16:48
@joostjager joostjager requested a review from Crypt-iQ June 12, 2021 16:51
@joostjager
Copy link
Contributor Author

Unit test added

@joostjager joostjager force-pushed the custom-messages branch 4 times, most recently from 3cbd4c8 to 6789090 Compare June 14, 2021 16:38
@joostjager
Copy link
Contributor Author

I think this PR is complete and has a concept-ack. Is it worth the 0.14 tag?

@BitcoinErrorLog
Copy link

I'm here to ACK and let everyone know that we need this, to enable Offers, a set of features we would like to have access to for wallets ASAP.

@Roasbeef
Copy link
Member

Roasbeef commented Jul 1, 2021

@BitcoinErrorLog a PR like this in isolation doesn't enable stuff like Offers. Offers uses a distinct invoice format from BOLT 11 (so you'd need RPC calls to create/parse/pay them), and it also requires a new type of onion handling (handle the onion messages that don't have any HTLC attached) within the core routing network.

@Roasbeef
Copy link
Member

Roasbeef commented Jul 1, 2021

. Also there is no easy way for the receiving node to send a message back

What about just sending a reply pubkey (or hop hint) to use? Message extension RPCs like this are cool, but if you want to do end to end interactions (outside of connecting to a peer you knows offers these features to send stuff back and forward), you'd need to assume every node in the critical path understands the messages.

AFAICT, all the sample use cases you've enumerated assume that you're making direct connections as other wise you'd need to use the existing onion routing protocol which has the size constraints mentioned.

@Roasbeef Roasbeef added this to the v0.14.0 milestone Jul 1, 2021
@joostjager
Copy link
Contributor Author

What about just sending a reply pubkey (or hop hint) to use?

I call this 'not easy', because you aren't sure if there is a return path and the other complexities/edge cases that exist.

Message extension RPCs like this are cool, but if you want to do end to end interactions (outside of connecting to a peer you knows offers these features to send stuff back and forward), you'd need to assume every node in the critical path understands the messages.

AFAICT, all the sample use cases you've enumerated assume that you're making direct connections as other wise you'd need to use the existing onion routing protocol which has the size constraints mentioned.

Yes, my intention with these extensions is to just do direct communication. I guess you could use it to set up some kind of forwarding service as well, but haven't given that any thought.

Copy link
Member

@Roasbeef Roasbeef left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pretty straight forward diff, ends up adding a lot of utility fo general experimatntion in the protocol which is cool. The only thing I think we need to examine more closely, is how we handle the cases where there exits no subscription, and also how to govern ourt actions depending on if we receive an even or odd type for the unknown message.

lnwire/features.go Outdated Show resolved Hide resolved
lnrpc/rest-annotations.yaml Outdated Show resolved Hide resolved
peer/brontide_test.go Outdated Show resolved Hide resolved
@@ -512,6 +512,10 @@ func MainRPCServerPermissions() map[string][]bakery.Op {
Entity: "offchain",
Action: "write",
}},
"/lnrpc.Lightning/SendCustomMessage": {{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Open questions if which sub-server this should live in 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because there isn't an obvious sub-server for it to live in, I opted for the main one.

@@ -51,3 +52,32 @@ func sendCustom(ctx *cli.Context) error {

return err
}

var subscribeCustomCommand = cli.Command{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure how useful this CLI command will be in practice, but don't see much harm in including it /shruggie

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, its use is doubtful. But because this is generic functionality, there may be an unexpected use for it. In any case, it is useful in development.

peer/brontide.go Outdated
@@ -1422,6 +1431,13 @@ out:

discStream.AddMsg(msg)

case *lnwire.Custom:
err := p.cfg.HandleCustomMessage(p.PubKey(), msg)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there's no custom message handler, then we should treat this as an error. In addition, if the message's type is even, even if there's a handler, we should likely return an error state.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added error case, even though a handler is always registered currently.

Not sure about even types. lnd doesn't know whether the external handler understands an even message? This would probably require an ack from the external handler, similar to what the htlc interceptor does. But then also with support for multiple handlers. I think that would make this PR a whole lot more complex, because the messages stay up in the air until the external process has given a response. And if I am seeing this right, the only difference is in what is logged locally? Because there isn't an actual response message on the wire.

peer/brontide_test.go Outdated Show resolved Hide resolved
server.go Show resolved Hide resolved
@joostjager joostjager requested a review from Roasbeef August 17, 2021 11:08
@Roasbeef Roasbeef requested review from arshbot and removed request for Crypt-iQ August 22, 2021 20:48
Copy link
Contributor

@arshbot arshbot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great addition, I could think of a few usecases for this myself. The addition of an RPC interface adds loads of possibilities for the casual developer, and I think should be added for an easier development experience.

lnwire/custom.go Show resolved Hide resolved
lnwire/message.go Show resolved Hide resolved
rpcserver.go Show resolved Hide resolved
@Roasbeef Roasbeef added the P3 might get fixed, nice to have label Aug 31, 2021
@joostjager joostjager requested a review from arshbot September 3, 2021 06:56
@orijbot
Copy link

orijbot commented Sep 3, 2021

@odeke-em
Copy link

odeke-em commented Sep 3, 2021

@joostjager to get a baseline for gobencher, please first trigger a commit from your main/master branch then push again to a branch.

Copy link
Contributor

@arshbot arshbot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM (pending @Roasbeef)! Super excited for this one

@joostjager
Copy link
Contributor Author

Rebased

@joostjager
Copy link
Contributor Author

Re-rebased. Waiting for final review.

@Roasbeef
Copy link
Member

One last rebase?

@joostjager
Copy link
Contributor Author

One last rebase

@joostjager
Copy link
Contributor Author

Seems that there are test and linter issues.

@joostjager
Copy link
Contributor Author

Linter was just collateral damage of a broken test. All fixed now again.

Copy link
Member

@Roasbeef Roasbeef left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 🌳

@Roasbeef
Copy link
Member

Yeah we're aware of the flake, def not introduced by this PR.

@Roasbeef Roasbeef merged commit e6c65f1 into lightningnetwork:master Oct 19, 2021
@joostjager joostjager mentioned this pull request Feb 17, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
p2p Code related to the peer-to-peer behaviour P3 might get fixed, nice to have rpc Related to the RPC interface wire protocol Encoding of messages for the communication between nodes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants