Skip to content

Commit 74e1232

Browse files
committed
multi: add new method ChainArbitrator.RedispatchBlockbeat
This commit adds a new method to enable us resending the blockbeat in `ChainArbitrator`, which is needed for the channel restore as the chain watcher and channel arbitrator are added after the start of the chain arbitrator.
1 parent fb50f54 commit 74e1232

File tree

3 files changed

+52
-6
lines changed

3 files changed

+52
-6
lines changed

chanrestore.go

+12-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"github.com/btcsuite/btcd/btcec/v2"
99
"github.com/btcsuite/btcd/chaincfg"
1010
"github.com/btcsuite/btcd/chaincfg/chainhash"
11+
"github.com/btcsuite/btcd/wire"
1112
"github.com/lightningnetwork/lnd/chanbackup"
1213
"github.com/lightningnetwork/lnd/channeldb"
1314
"github.com/lightningnetwork/lnd/contractcourt"
@@ -286,6 +287,9 @@ func (c *chanDBRestorer) RestoreChansFromSingles(backups ...chanbackup.Single) e
286287

287288
ltndLog.Infof("Informing chain watchers of new restored channels")
288289

290+
// Create a slice of channel points.
291+
chanPoints := make([]wire.OutPoint, 0, len(channelShells))
292+
289293
// Finally, we'll need to inform the chain arbitrator of these new
290294
// channels so we'll properly watch for their ultimate closure on chain
291295
// and sweep them via the DLP.
@@ -294,8 +298,15 @@ func (c *chanDBRestorer) RestoreChansFromSingles(backups ...chanbackup.Single) e
294298
if err != nil {
295299
return err
296300
}
301+
302+
chanPoints = append(
303+
chanPoints, restoredChannel.Chan.FundingOutpoint,
304+
)
297305
}
298306

307+
// With all the channels restored, we'll now re-send the blockbeat.
308+
c.chainArb.RedispatchBlockbeat(chanPoints)
309+
299310
return nil
300311
}
301312

@@ -314,7 +325,7 @@ func (s *server) ConnectPeer(nodePub *btcec.PublicKey, addrs []net.Addr) error {
314325
// to ensure the new connection is created after this new link/channel
315326
// is known.
316327
if err := s.DisconnectPeer(nodePub); err != nil {
317-
ltndLog.Infof("Peer(%v) is already connected, proceeding "+
328+
ltndLog.Infof("Peer(%x) is already connected, proceeding "+
318329
"with chan restore", nodePub.SerializeCompressed())
319330
}
320331

contractcourt/chain_arbitrator.go

+39
Original file line numberDiff line numberDiff line change
@@ -1341,3 +1341,42 @@ func (c *ChainArbitrator) FindOutgoingHTLCDeadline(scid lnwire.ShortChannelID,
13411341
func (c *ChainArbitrator) Name() string {
13421342
return "ChainArbitrator"
13431343
}
1344+
1345+
// RedispatchBlockbeat resends the current blockbeat to the channels specified
1346+
// by the chanPoints. It is used when a channel is added to the chain
1347+
// arbitrator after it has been started, e.g., during the channel restore
1348+
// process.
1349+
func (c *ChainArbitrator) RedispatchBlockbeat(chanPoints []wire.OutPoint) {
1350+
// Get the current blockbeat.
1351+
beat := c.CurrentBeat()
1352+
1353+
// Prepare two sets of consumers.
1354+
channels := make([]chainio.Consumer, 0, len(chanPoints))
1355+
watchers := make([]chainio.Consumer, 0, len(chanPoints))
1356+
1357+
// Read the active channels in a lock.
1358+
c.Lock()
1359+
for _, op := range chanPoints {
1360+
if channel, ok := c.activeChannels[op]; ok {
1361+
channels = append(channels, channel)
1362+
}
1363+
1364+
if watcher, ok := c.activeWatchers[op]; ok {
1365+
watchers = append(watchers, watcher)
1366+
}
1367+
}
1368+
c.Unlock()
1369+
1370+
// Iterate all the copied watchers and send the blockbeat to them.
1371+
err := beat.DispatchConcurrent(watchers)
1372+
if err != nil {
1373+
log.Errorf("Notify blockbeat failed: %v", err)
1374+
}
1375+
1376+
// Iterate all the copied channels and send the blockbeat to them.
1377+
err = beat.DispatchConcurrent(channels)
1378+
if err != nil {
1379+
// Shutdown lnd if there's an error processing the block.
1380+
log.Errorf("Notify blockbeat failed: %v", err)
1381+
}
1382+
}

itest/lnd_channel_backup_test.go

+1-5
Original file line numberDiff line numberDiff line change
@@ -1438,9 +1438,6 @@ func assertTimeLockSwept(ht *lntest.HarnessTest, carol, dave *node.HarnessNode,
14381438
// tx. In addition, Dave will attempt to sweep his anchor output but
14391439
// fail due to the sweeping tx being uneconomical.
14401440
expectedTxes := 1
1441-
1442-
// Mine a block to trigger the sweeps.
1443-
ht.MineBlocks(1)
14441441
ht.AssertNumTxsInMempool(expectedTxes)
14451442

14461443
// Carol should consider the channel pending force close (since she is
@@ -1470,11 +1467,10 @@ func assertTimeLockSwept(ht *lntest.HarnessTest, carol, dave *node.HarnessNode,
14701467
// The commit sweep resolver publishes the sweep tx at defaultCSV-1 and
14711468
// we already mined one block after the commitment was published, and
14721469
// one block to trigger Carol's sweeps, so take that into account.
1473-
ht.MineEmptyBlocks(1)
1470+
ht.MineEmptyBlocks(2)
14741471
ht.AssertNumPendingSweeps(dave, 2)
14751472

14761473
// Mine a block to trigger the sweeps.
1477-
ht.MineEmptyBlocks(1)
14781474
daveSweep := ht.AssertNumTxsInMempool(1)[0]
14791475
block := ht.MineBlocksAndAssertNumTxes(1, 1)[0]
14801476
ht.AssertTxInBlock(block, daveSweep)

0 commit comments

Comments
 (0)