mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-06-30 18:43:42 +02:00
fundingmanager: define stateStep, make advanceFundingState sync
This commit make the advanceFundingStateMethod synchronous. It will now query the database for a channel's opening state, and call the method stateStep until the channel has finished the opening procedure.
This commit is contained in:
@ -598,10 +598,8 @@ func (f *fundingManager) start() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, channel := range openChannels {
|
for _, channel := range openChannels {
|
||||||
err = f.advanceFundingState(channel)
|
f.wg.Add(1)
|
||||||
if err != nil {
|
go f.advanceFundingState(channel, nil)
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
f.wg.Add(1) // TODO(roasbeef): tune
|
f.wg.Add(1) // TODO(roasbeef): tune
|
||||||
@ -829,109 +827,130 @@ func (f *fundingManager) reservationCoordinator() {
|
|||||||
// advanceFundingState will advance the channel fromt the markedOpen state to
|
// advanceFundingState will advance the channel fromt the markedOpen state to
|
||||||
// the point where the channel is ready for operation. This includes sending
|
// the point where the channel is ready for operation. This includes sending
|
||||||
// funding locked to the peer, adding the channel to the router graph, and
|
// funding locked to the peer, adding the channel to the router graph, and
|
||||||
// announcing the channel.
|
// announcing the channel. The updateChan can be set non-nil to get
|
||||||
func (f *fundingManager) advanceFundingState(
|
// OpenStatusUpdates.
|
||||||
channel *channeldb.OpenChannel) error {
|
//
|
||||||
|
// NOTE: This MUST be run as a goroutine.
|
||||||
|
func (f *fundingManager) advanceFundingState(channel *channeldb.OpenChannel,
|
||||||
|
updateChan chan<- *lnrpc.OpenStatusUpdate) {
|
||||||
|
|
||||||
channelState, shortChanID, err := f.getChannelOpeningState(
|
defer f.wg.Done()
|
||||||
&channel.FundingOutpoint)
|
|
||||||
if err == ErrChannelNotFound {
|
// We create the state-machine object which wraps the database state.
|
||||||
// Channel not in fundingManager's opening database,
|
lnChannel, err := lnwallet.NewLightningChannel(
|
||||||
// meaning it was successfully announced to the
|
nil, channel, nil,
|
||||||
// network.
|
)
|
||||||
return nil
|
if err != nil {
|
||||||
} else if err != nil {
|
fndgLog.Errorf("Unable to create LightningChannel(%v): %v",
|
||||||
return err
|
channel.FundingOutpoint, err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
chanID := lnwire.NewChanIDFromOutPoint(&channel.FundingOutpoint)
|
for {
|
||||||
fndgLog.Debugf("channel (%v) with opening state %v found",
|
channelState, shortChanID, err := f.getChannelOpeningState(
|
||||||
chanID, channelState)
|
&channel.FundingOutpoint,
|
||||||
|
)
|
||||||
|
if err == ErrChannelNotFound {
|
||||||
|
// Channel not in fundingManager's opening database,
|
||||||
|
// meaning it was successfully announced to the
|
||||||
|
// network.
|
||||||
|
return
|
||||||
|
} else if err != nil {
|
||||||
|
fndgLog.Errorf("Unable to query database for "+
|
||||||
|
"channel opening state(%v): %v",
|
||||||
|
channel.FundingOutpoint, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we did find the channel in the opening state database, we
|
||||||
|
// have seen the funding transaction being confirmed, but there
|
||||||
|
// are still steps left of the setup procedure. We continue the
|
||||||
|
// procedure where we left off.
|
||||||
|
err = f.stateStep(
|
||||||
|
channel, lnChannel, shortChanID, channelState,
|
||||||
|
updateChan,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
fndgLog.Errorf("Unable to advance state(%v): %v",
|
||||||
|
channel.FundingOutpoint, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// stateStep advances the confirmed channel one step in the funding state
|
||||||
|
// machine. This method is synchronous and the new channel opening state will
|
||||||
|
// have been written to the database when it successfully returns. The
|
||||||
|
// updateChan can be set non-nil to get OpenStatusUpdates.
|
||||||
|
func (f *fundingManager) stateStep(channel *channeldb.OpenChannel,
|
||||||
|
lnChannel *lnwallet.LightningChannel,
|
||||||
|
shortChanID *lnwire.ShortChannelID, channelState channelOpeningState,
|
||||||
|
updateChan chan<- *lnrpc.OpenStatusUpdate) error {
|
||||||
|
|
||||||
|
chanID := lnwire.NewChanIDFromOutPoint(&channel.FundingOutpoint)
|
||||||
|
fndgLog.Debugf("Channel(%v) with ShortChanID %v has opening state %v",
|
||||||
|
chanID, shortChanID, channelState)
|
||||||
|
|
||||||
// If we did find the channel in the opening state database, we have
|
|
||||||
// seen the funding transaction being confirmed, but we did not finish
|
|
||||||
// the rest of the setup procedure before we shut down. We handle the
|
|
||||||
// remaining steps of this setup by continuing the procedure where we
|
|
||||||
// left off.
|
|
||||||
switch channelState {
|
switch channelState {
|
||||||
|
|
||||||
// The funding transaction was confirmed, but we did not successfully
|
// The funding transaction was confirmed, but we did not successfully
|
||||||
// send the fundingLocked message to the peer, so let's do that now.
|
// send the fundingLocked message to the peer, so let's do that now.
|
||||||
case markedOpen:
|
case markedOpen:
|
||||||
f.wg.Add(1)
|
peerChan := make(chan lnpeer.Peer, 1)
|
||||||
go func(dbChan *channeldb.OpenChannel) {
|
|
||||||
defer f.wg.Done()
|
|
||||||
|
|
||||||
peerChan := make(chan lnpeer.Peer, 1)
|
var peerKey [33]byte
|
||||||
|
copy(peerKey[:], channel.IdentityPub.SerializeCompressed())
|
||||||
|
|
||||||
var peerKey [33]byte
|
f.cfg.NotifyWhenOnline(peerKey, peerChan)
|
||||||
copy(peerKey[:], dbChan.IdentityPub.SerializeCompressed())
|
|
||||||
|
|
||||||
f.cfg.NotifyWhenOnline(peerKey, peerChan)
|
var peer lnpeer.Peer
|
||||||
|
select {
|
||||||
|
case peer = <-peerChan:
|
||||||
|
case <-f.quit:
|
||||||
|
return ErrFundingManagerShuttingDown
|
||||||
|
}
|
||||||
|
|
||||||
var peer lnpeer.Peer
|
err := f.sendFundingLocked(
|
||||||
select {
|
peer, channel, lnChannel, shortChanID,
|
||||||
case peer = <-peerChan:
|
)
|
||||||
case <-f.quit:
|
if err != nil {
|
||||||
return
|
return fmt.Errorf("failed sending fundingLocked: %v",
|
||||||
}
|
err)
|
||||||
err := f.handleFundingConfirmation(
|
}
|
||||||
peer, dbChan, shortChanID,
|
|
||||||
)
|
fndgLog.Debugf("Channel(%v) with ShortChanID %v: successfully "+
|
||||||
if err != nil {
|
"sent FundingLocked", chanID, shortChanID)
|
||||||
fndgLog.Errorf("Failed to handle "+
|
return nil
|
||||||
"funding confirmation: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}(channel)
|
|
||||||
|
|
||||||
// fundingLocked was sent to peer, but the channel was not added to the
|
// fundingLocked was sent to peer, but the channel was not added to the
|
||||||
// router graph and the channel announcement was not sent.
|
// router graph and the channel announcement was not sent.
|
||||||
case fundingLockedSent:
|
case fundingLockedSent:
|
||||||
f.wg.Add(1)
|
err := f.addToRouterGraph(channel, shortChanID)
|
||||||
go func(dbChan *channeldb.OpenChannel) {
|
if err != nil {
|
||||||
defer f.wg.Done()
|
return fmt.Errorf("failed adding to "+
|
||||||
|
"router graph: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
err = f.addToRouterGraph(dbChan, shortChanID)
|
fndgLog.Debugf("Channel(%v) with ShortChanID %v: successfully "+
|
||||||
if err != nil {
|
"added to router graph", chanID, shortChanID)
|
||||||
fndgLog.Errorf("failed adding to "+
|
|
||||||
"router graph: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(halseth): should create a state machine
|
return nil
|
||||||
// that can more easily be resumed from
|
|
||||||
// different states, to avoid this code
|
|
||||||
// duplication.
|
|
||||||
err = f.annAfterSixConfs(dbChan, shortChanID)
|
|
||||||
if err != nil {
|
|
||||||
fndgLog.Errorf("error sending channel "+
|
|
||||||
"announcements: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}(channel)
|
|
||||||
|
|
||||||
// The channel was added to the Router's topology, but the channel
|
// The channel was added to the Router's topology, but the channel
|
||||||
// announcement was not sent.
|
// announcement was not sent.
|
||||||
case addedToRouterGraph:
|
case addedToRouterGraph:
|
||||||
f.wg.Add(1)
|
err := f.annAfterSixConfs(channel, shortChanID)
|
||||||
go func(dbChan *channeldb.OpenChannel) {
|
if err != nil {
|
||||||
defer f.wg.Done()
|
return fmt.Errorf("error sending channel "+
|
||||||
|
"announcement: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
err = f.annAfterSixConfs(dbChan, shortChanID)
|
fndgLog.Debugf("Channel(%v) with ShortChanID %v: successfully "+
|
||||||
if err != nil {
|
"announced", chanID, shortChanID)
|
||||||
fndgLog.Errorf("error sending channel "+
|
return nil
|
||||||
"announcement: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}(channel)
|
|
||||||
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("undefined channelState: %v",
|
|
||||||
channelState)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return fmt.Errorf("undefined channelState: %v", channelState)
|
||||||
}
|
}
|
||||||
|
|
||||||
// handlePendingChannels responds to a request for details concerning all
|
// handlePendingChannels responds to a request for details concerning all
|
||||||
|
Reference in New Issue
Block a user