[Lightning-dev] Concurrent sigs in BOLT #2

Rusty Russell rusty at rustcorp.com.au
Tue Apr 26 02:21:00 UTC 2016


Pierre <pm+lists at acinq.fr> writes:
> Hello,

Hi Pierre!

        I'm glad I'm not the only one who had trouble with this.  I just
thought I was being dumb!  Concurrent updates are conceptually harder
than the previous synchronous model, unfortunately.

> I am trying to understand how we should handle concurrent signatures,
> and I am wondering if we couldn't use an ordering of some sort to
> resolve conflicts when they occur, for example by simply comparing
> signatures. If two nodes send each other a signature at the same time,
> they could agree that the one that sent the "greatest" signature has
> to immediately resend a new signature including all pending changes.
> This new signature would encompass all the changes both parties wanted
> in the first place so everybody would be happy.

I originally had an alternating priority scheme which worked, but I don't
think it's necessary any more.

This diagram is a simplification.  Each node tracks two commitment
states: its own and the state of the other side.  This is because they
can run independently.

The rules are simple (though the results might not be!):

1) Nodes must process packets in order.
2) When you send something, update their state.
3) When you ack something, update their state.
4) When you receive something, update your own state.
5) When you receive an ack for something, update your own state.

When you sign a commit tx, you sign their state at the time (this makes
sense: you're signing their commit tx, not yours).

So, when a node sends an ADD HTLC, it modifies the other side's state.
It only modifies its own state when it receives an ack covering that ADD
HTLC.

The ADD HTLC receiver modifies its own state, and modifies the other
side's state when it sends the next ack (in practice, we do that
immediately because it doesn't matter, but diagram below does it
strictly).

Thus, in your case:

           NODE A                            NODE B

    Committed: []                                 Committed: []
    States:    [] [X]                             States:    [] [Y]
                ADD HTLC X ----        ---- ADD HTLC Y
                               \      /
                                \    /
    Committed: []                \  /             Committed: []
    States:    [] [X]             \/              States:    [] [Y]
                    SIG A0 ---    /\    --- SIG B0
                              \  /  \  /
                               \/    \/
                               /\    /\
                           <---  \  /  --->
    Committed: []                 \/              Committed: []
    States:    [Y] [X]            /\              States: [X] [Y]
                                 /  \
                                /    \
                           <----      -----> 
    Committed: [Y]                                Committed: [X]
    States:    [Y] [X]                            States: [X] [Y]

Now, at this point both nodes have outstanding changes, so they can send
another SIG (which acks the received changes, thus modifying the other
state):

    Committed: [Y]                                Committed: [X]
    States:    [Y] [X Y]                          States: [X] [X Y]
                    SIG A1 ---          --- SIG B1
                              \        /
                               \      /
                                \    / 
                                 \  /      
                                  \/              
                                  /\              
                                 /  \
                                /    \
                           <----      -----> 
PROCESS ACK:
    Committed: [Y]                                Committed: [X]
    States:    [X Y] [X Y]                        States: [X Y] [X Y]
PROCESS SIG:
    Committed: [X Y]                              Committed: [X Y]
    States:    [X Y] [X Y]                        States: [X Y] [X Y]


FWIW, note that the minimum single-update case is still 1.5 round-trips:

           NODE A                            NODE B

    Committed: []                                 Committed: []
    States:    [] [X]                             States:    [] []
                ADD HTLC X -------------------->
                
    Committed: []                                 Committed: []
    States:    [] [X]                             States:    [X] []
                SIG A1 -------------------->
                
    Committed: []                                 Committed: [X]
    States:    [] [X]                             States:    [X] [X]
                <---------------------- REVOKE B0
                <------------------------- SIG B1
                
    Committed: [X]                                Committed: [X]
    States:    [X] [X]                            States:    [X] [X]
                ----------------------> REVOKE A0

Cheers,
Rusty.


More information about the Lightning-dev mailing list