Skip to content

Add "Joint Channels" support (a.k.a FROST integration) #1665

Open
@ariard

Description

@ariard

The "joint" channel functionality would be to make all the funding/closing and payments operations to be jointly signed by a group of N entities. This assumes Schnorr support being specified out in Lightning and supported by LDK. Few different multi-party schemes are in specification across the Bitcoin ecosystem. The first one is Musig2, a n-of-n scheme, another one is FROST, a t-of-n scheme.

FROST is a threshold signature schemes defining a signing protocol that can be used as either a two-round protocol where signers send and receive two messages in total, or optimized to a single-round signing protocol with a preprocessing stage. This optimization is agnostic to the choice of the signing coalition.

This t-of-n scheme is especially interesting for a LN context, where latency, security and fault-tolerance matters if you're a high-volume payment node or a competing routing node. Latency both as a UX reason and routing operational issue (e.g it could be expected slow forward HTLC to be monitored by scoring algos in the future), fault-tolerance as t-1 wouldn't halt the node operation and security as you increase your supply-chain attacks robustness if you have a diversity of platforms for the signing devices.

There is currently a WIP PR in libsecp256k1-zkp implementing this scheme.

The protocol has the following steps (cf. examples/frost.c in FROST branch)

  1. KeyGen: Each signer generates a polynomial share and a sequence of VSS commitments.
  2. KeyGen: Each signer broadcasts his share, receives the ones from each participant, aggregates the shares, and then aggregates the commitment to each participant to derive the aggregate public key.
  3. KeyGen: Each signer signs the hash of the VSS commitments of all participants, broadcasts the signature and verifies the one from each other participant.
  4. Signing: Nonces are exchanged and each signer generates a partial signature.
  5. Signing: Partial signatures are aggregated and the aggregate signature is produced.

KeyGen:

     _______     A's VSS commitment + share   ___________________
    |       |------------------------------->|                   |
    | Alice |    B's VSS commitment + share  |                   |
    |_______|<-------------------------------|                   |
                                             | Commitment Server |
     _______     B's VSS commitment + share  |                   |
    |       |------------------------------->|                   |
    |  Bob  |    A's VSS commitment + share  |                   |
    |_______|<-------------------------------|___________________|

Sign:

     _______           A's nonce             ______________________
    |       |------------------------------>|                      |
    |       |          B's nonce            |                      |
    | Alice |<------------------------------|                      |
    |       |       A's partial_sig         |                      |
    |_______|<------------------------------|                      |
                                            | Signature Aggregator |
     _______           B's nonce            |                      |
    |       |------------------------------>|                      |
    |       |          A's nonce            |                      |
    |  Bob  |<------------------------------|                      |
    |       |       B's partial_sig         |                      |
    |_______|<------------------------------|______________________|

I don't think a signature aggregator module is aimed to be scoped by libsecp256k1-zkp, so we might need to have one on our side. We could wrap the commitment server in a centralized coordinator. Note, there is the option to perform FROST in a full decentralized setting by assuming a broadcast channel between signers. While there is no signature forgery trust poured on the signature aggregator, not relying on it removes a DoS vector and potential fault-tolerance issue, at the cost of one more round-trip from my understanding.

Beyond the protocol assumes the following security assumptions and we would need middleware to support them:

  • Message Validation: every participant checks the validity of the message m to be signed
    before issuing its signature share.
  • Reliable Message Delivery: messages are sent between participants using a reliable network
    channel.
  • Participant Identification: value submitted by participants should be identifiable within
    the signing group.

For message validation, the message semantics we're aiming to enforce here should be the channel funding/closing and flows correctness. I think here we can reuse the ones already captured by VLS's policy controls and depends of the level of integration we wish with VLS, one direction could be to wish for an abstract internal signing interface there to support multi-signature scheme.

For reliable message delivery, I think we would need some state machine implementing TCP-like properties (recover data that is damaged, lost, duplicated or delivered out-of-order). I believe we would need such reliable message delivery module anyway to exchange ChannelMonitorUpdate between our ChannelManager and monitor replicas/watchtower backend.

For participant identification, I think we could reuse our BOLT8 implementation (PeerChannelEncryptor). From memory, we might have to refactor this module to make it reusable. We might have also to check if the handshake pattern Noise_XK works well for this use-case. The key ceremony and how the identification keys are distributed over the signers should be deferred to the operators, though we might provide operational guidelines.

Finally, I think we shouldn't forget rust-bindings for the libsecp256k1-zkp module.

This is a first picture of how we would integrate FROST in LDK/VLS, and as such there are likely approximations. Note the FROST implementation/BIPs are also in flux. To maintain the issue updated in function of advancements there.

(Maintenance note: I believe we don't need to have all the modules part of the "Joint Channel" feature support in this tree, as long as there are somewhere and well-maintained)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions