sidecar: on restart ensure recipient re-expects channel

Without this extra case on restart, the recipient would have an
unhandled state transition that would cause them to not expect the
channel as it should once the batch is finalized.
This commit is contained in:
Olaoluwa Osuntokun 2021-05-25 19:11:39 -07:00
parent ec12ec05ba
commit 67f01ec1b7
2 changed files with 24 additions and 13 deletions

View file

@ -16,11 +16,6 @@ import (
"github.com/lightningnetwork/lnd/lnwire"
)
// TODO(roasbeef): need to ensure have updates for termination, etc
// * finalize for the recreiver
// * need other hook for the provider
// * also delete as well (the mailbox)
// MailBox is an interface that abstracts over the HashMail functionality to
// represent a generic mailbox that both sides will use to communicate with
// each other.
@ -59,8 +54,6 @@ type MailBox interface {
// what will trigger a state transition.
type SidecarPacket struct {
// CurrentState is the current state of the negotiator.
//
// TODO(roasbeef): remove??
CurrentState sidecar.State
// ReceiverTicket is the current ticket of the receiver.
@ -432,9 +425,7 @@ func (a *SidecarNegotiator) stateStepRecipient(ctx context.Context,
// Now that we know the channel is valid, we'll wait for the
// channel to show up at our node, and allow things to advance
// to the completion state.
err = a.cfg.Driver.ExpectChannel(
ctx, pkt.ProviderTicket,
)
err = a.cfg.Driver.ExpectChannel(ctx, pkt.ProviderTicket)
if err != nil {
return nil, fmt.Errorf("failed to expect "+
"channel: %w", err)
@ -446,6 +437,22 @@ func (a *SidecarNegotiator) stateStepRecipient(ctx context.Context,
ProviderTicket: pkt.ProviderTicket,
}, nil
// If we come back up and we're already expecting the channel then we
// need to make sure we expect it again to ensure we re-register with
// the auctioneer to be able to receive the channel.
case pkt.CurrentState == sidecar.StateExpectingChannel:
err := a.cfg.Driver.ExpectChannel(ctx, pkt.ProviderTicket)
if err != nil {
return nil, fmt.Errorf("failed to expect "+
"channel: %w", err)
}
return &SidecarPacket{
CurrentState: sidecar.StateExpectingChannel,
ReceiverTicket: pkt.ReceiverTicket,
ProviderTicket: pkt.ProviderTicket,
}, nil
// If we fall through here, then either we read a buffered message or
// the remote party isn't following the protocol, so we'll just ignore
// it.
@ -464,9 +471,6 @@ func (a *SidecarNegotiator) autoSidecarProvider(ctx context.Context, startingPkt
defer a.wg.Done()
// TODO(roasbeef): subscribe to order state so know when things are
// done, use that to send the extra msg
packetChan := make(chan *sidecar.Ticket, 1)
cancelChan := make(chan struct{})

View file

@ -457,6 +457,8 @@ func (s *sidecarTestCtx) assertRecipientExpectsChannel() {
}
func (s *sidecarTestCtx) assertRecipientTicketUpdated(expectedState sidecar.State) {
s.t.Helper()
select {
case stateUpdate := <-s.recipientDriver.stateUpdates:
@ -639,6 +641,11 @@ func TestAutoSidecarNegotiation(t *testing.T) {
testCtx.assertNoProviderMsgsRecvd()
testCtx.assertNoReceiverMsgsRecvd()
// The recipient of the ticket should re-expect the channel to
// re-register with the auctioneer to ensure the channel can be
// executed amidst their restarts.
testCtx.assertRecipientExpectsChannel()
// We'll now signal to both goroutines that the channel has been
// finalized, at this point, we expect both ticket to transition to the
// terminal state and the goroutines to exit.