[c-lightning] Plug-in design requirements

Rusty Russell rusty at rustcorp.com.au
Mon Dec 10 15:37:02 AEDT 2018

Corné Plooy <corne at bitonic.nl> writes:
> Hi,
> From a side discussion during the Lightning summit I understood that my
> input
> is wanted for the design of the plug-in system of C-Lightning. In this
> e-mail
> I'll sketch what I'd like to have. In various places, I'll quote structure
> names from BOLT 4.


> # Sending node behavior
> Application-specific code on the sending node must be able to send out a
> payment
> to the receiving node with an onion packet that is different from a regular
> onion packet in the following ways:
> * The onion data received by the receiving node indicates that, instead of
>   following the regular behavior of a Lightning node, the receiving node
> must
>   follow certain application-specific behavior. The preferred way of
> indicating
>   this is through a non-default `realm` number, but other methods have been
>   proposed as well (such as a non-existing `short_channel_id`).
> * The `per_hop` data received by the receiving node contains
>   application-specific data instead of, or in addition to, the regular
> `per_hop`
>   data.

Looks like we're headed to TLV data for the onion padding for 1.1, and
realm being a simple counter of number of extra fields.  This should fit
nicely with a JSON API which allows arbitrary data, I think...

> Obviously, if the `realm` number is used as indicator, and the
> application-specific data completely replaces the regular `per_hop`
> data, this
> maximizes the amount of application-specific data that can be sent.
> If more data needs to be sent than fits in a single `per_hop` element, the
> application might require the use of multiple `per_hop` elements, at the
> cost of
> reducing the maximum transaction route length. However, for my
> application that
> does not seem to be needed. Specifically, my application needs the following
> data in the onion:
> * 8 bytes: the amount to be forwarded in an application-specific way
> * ? bytes: an ID related to some data shared between sender and receiver.
>   Can be RIPEMD160 (20 bytes).

Assuming that this API disabled multipart payments (at least, to start
with) it could completely define the final TLV contents.  lightningd
would use enough hops_data to fit whatever the API hands in.

The definition of 'application-specific data' would be 'a TLV we don't
understand'.  I think the 'chainhop' and 'multipart' and a few other TLV
values have been proposed so far; we'd handle 'multipart' internally.

> # Receiving node behavior
> On receiving an incoming transaction that indicates application-specific
> behavior (as described above), the receiving node must do one of the
> following:
> * If no application-specific handler is present, fail the incoming
> transaction.

I think this should actually now depend on the odd/even rule: we would
be fine with odd bits we don't understand, and fail even ones.

> * If an application-specific handler is present, accept the incoming HTLC,
>   notify the handler of the incoming transaction and pass it the following
>   information:
>   - Incoming amount
>   - Incoming CLTV
>   - Incoming payment hash
>   - `realm` number
>   - `per_hop` data
> If more data needs to be sent than fits in a single `per_hop` element, the
> entire `hops_data` structure may need to be passed; TBD is whether the
> remaining
> hops need to be decrypted in a certain way. As far as my application
> goes, this
> will not be needed, since its data fits in a single `per_hop` element.

We'd hand all the hop data, I think.  The `realm` effectively encodes
the length, so may be redundant.

> If the application-specific code neither fails nor finishes the transaction,
> the Lightning node should respect the lock time of the incoming HTLC.
> To prevent the peer from closing the channel, the incoming transaction
> should be
> failed some short time before its lock time; we may want to make this time
> difference configurable, maybe even on a per-application basis.

Yes, this is similar to how we handle forwarded HTLCs, and I think
similar logic applies.

> To aid in crash recovery, it is recommended to add an extra interface
> (function)
> between application and Lightning node, to allow the Lightning node to query
> the application about ongoing transactions after application restart.
> Informally, the Lightning node asks "are you handling this
> transaction?", and
> the application answers yes or no. If it answers no, the Lightning node may
> fail the incoming transaction. The advantage is that transactions are failed
> faster than when waiting for the HTLC time-out.

In practice I think c-lightning would re-submit them on startup; plugins
should handle this case.

> Automatic restarting of the application may be desirable, but following
> the UNIX
> philosophy of "do one simple thing, and do it well" I don't think it
> should be
> the responsibility of the Lightning node. In fact, the whole concept of a
> persistent application process can be application-specific; for some
> applications, it might be better suited to kick off a new (script)
> process on
> every incoming transaction.

Yes, I think the plugin should be responsible for its own dispatch.

> On the receiver side, the decision of what signals "application-specific
> handling" may be delegated to application-specific code. It may be seen as a
> chain of handlers: an incoming transaction is offered to the handlers one by
> one, until a handler accepts the transaction. The last handler in the
> chain is
> always the default built-in handler of C-Lightning; it can not refuse a
> transaction, only accept it or fail it immediately. So the handler chain
> always
> has at least length one.

Well, this works quite neatly with the idea of TLV odd and even.  The
default behaviour is then correct; the application chooses whether its
option is compulsory or not.


More information about the c-lightning mailing list