mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-03-31 16:09:02 +02:00
contractcourt: remove waitForHeight
in resolvers
The sweeper can handle the waiting so there's no need to wait for blocks inside the resolvers. By offering the inputs prior to their mature heights also guarantees the inputs with the same deadline are aggregated.
This commit is contained in:
parent
3ac6752a77
commit
5f9d473702
@ -101,36 +101,6 @@ func (c *commitSweepResolver) ResolverKey() []byte {
|
||||
return key[:]
|
||||
}
|
||||
|
||||
// waitForHeight registers for block notifications and waits for the provided
|
||||
// block height to be reached.
|
||||
func waitForHeight(waitHeight uint32, notifier chainntnfs.ChainNotifier,
|
||||
quit <-chan struct{}) error {
|
||||
|
||||
// Register for block epochs. After registration, the current height
|
||||
// will be sent on the channel immediately.
|
||||
blockEpochs, err := notifier.RegisterBlockEpochNtfn(nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer blockEpochs.Cancel()
|
||||
|
||||
for {
|
||||
select {
|
||||
case newBlock, ok := <-blockEpochs.Epochs:
|
||||
if !ok {
|
||||
return errResolverShuttingDown
|
||||
}
|
||||
height := newBlock.Height
|
||||
if height >= int32(waitHeight) {
|
||||
return nil
|
||||
}
|
||||
|
||||
case <-quit:
|
||||
return errResolverShuttingDown
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// waitForSpend waits for the given outpoint to be spent, and returns the
|
||||
// details of the spending tx.
|
||||
func waitForSpend(op *wire.OutPoint, pkScript []byte, heightHint uint32,
|
||||
@ -225,39 +195,6 @@ func (c *commitSweepResolver) Resolve(_ bool) (ContractResolver, error) {
|
||||
c.currentReport.MaturityHeight = unlockHeight
|
||||
c.reportLock.Unlock()
|
||||
|
||||
// If there is a csv/cltv lock, we'll wait for that.
|
||||
if c.commitResolution.MaturityDelay > 0 || c.hasCLTV() {
|
||||
// Determine what height we should wait until for the locks to
|
||||
// expire.
|
||||
var waitHeight uint32
|
||||
switch {
|
||||
// If we have both a csv and cltv lock, we'll need to look at
|
||||
// both and see which expires later.
|
||||
case c.commitResolution.MaturityDelay > 0 && c.hasCLTV():
|
||||
c.log.Debugf("waiting for CSV and CLTV lock to expire "+
|
||||
"at height %v", unlockHeight)
|
||||
// If the CSV expires after the CLTV, or there is no
|
||||
// CLTV, then we can broadcast a sweep a block before.
|
||||
// Otherwise, we need to broadcast at our expected
|
||||
// unlock height.
|
||||
waitHeight = uint32(math.Max(
|
||||
float64(unlockHeight-1), float64(c.leaseExpiry),
|
||||
))
|
||||
|
||||
// If we only have a csv lock, wait for the height before the
|
||||
// lock expires as the spend path should be unlocked by then.
|
||||
case c.commitResolution.MaturityDelay > 0:
|
||||
c.log.Debugf("waiting for CSV lock to expire at "+
|
||||
"height %v", unlockHeight)
|
||||
waitHeight = unlockHeight - 1
|
||||
}
|
||||
|
||||
err := waitForHeight(waitHeight, c.Notifier, c.quit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
isLocalCommitTx bool
|
||||
|
||||
|
@ -90,12 +90,6 @@ func (i *commitSweepResolverTestContext) resolve() {
|
||||
}()
|
||||
}
|
||||
|
||||
func (i *commitSweepResolverTestContext) notifyEpoch(height int32) {
|
||||
i.notifier.EpochChan <- &chainntnfs.BlockEpoch{
|
||||
Height: height,
|
||||
}
|
||||
}
|
||||
|
||||
func (i *commitSweepResolverTestContext) waitForResult() {
|
||||
i.t.Helper()
|
||||
|
||||
@ -292,22 +286,10 @@ func testCommitSweepResolverDelay(t *testing.T, sweepErr error) {
|
||||
t.Fatal("report maturity height incorrect")
|
||||
}
|
||||
|
||||
// Notify initial block height. The csv lock is still in effect, so we
|
||||
// don't expect any sweep to happen yet.
|
||||
ctx.notifyEpoch(testInitialBlockHeight)
|
||||
|
||||
select {
|
||||
case <-ctx.sweeper.sweptInputs:
|
||||
t.Fatal("no sweep expected")
|
||||
case <-time.After(sweepProcessInterval):
|
||||
}
|
||||
|
||||
// A new block arrives. The commit tx confirmed at height -1 and the csv
|
||||
// is 3, so a spend will be valid in the first block after height +1.
|
||||
ctx.notifyEpoch(testInitialBlockHeight + 1)
|
||||
|
||||
<-ctx.sweeper.sweptInputs
|
||||
|
||||
// Notify initial block height. Although the csv lock is still in
|
||||
// effect, we expect the input being sent to the sweeper before the csv
|
||||
// lock expires.
|
||||
//
|
||||
// Set the resolution report outcome based on whether our sweep
|
||||
// succeeded.
|
||||
outcome := channeldb.ResolverOutcomeClaimed
|
||||
|
@ -359,30 +359,6 @@ func (h *htlcSuccessResolver) broadcastReSignedSuccessTx(immediate bool) (
|
||||
"height %v", h, h.htlc.RHash[:], waitHeight)
|
||||
}
|
||||
|
||||
// Deduct one block so this input is offered to the sweeper one block
|
||||
// earlier since the sweeper will wait for one block to trigger the
|
||||
// sweeping.
|
||||
//
|
||||
// TODO(yy): this is done so the outputs can be aggregated
|
||||
// properly. Suppose CSV locks of five 2nd-level outputs all
|
||||
// expire at height 840000, there is a race in block digestion
|
||||
// between contractcourt and sweeper:
|
||||
// - G1: block 840000 received in contractcourt, it now offers
|
||||
// the outputs to the sweeper.
|
||||
// - G2: block 840000 received in sweeper, it now starts to
|
||||
// sweep the received outputs - there's no guarantee all
|
||||
// fives have been received.
|
||||
// To solve this, we either offer the outputs earlier, or
|
||||
// implement `blockbeat`, and force contractcourt and sweeper
|
||||
// to consume each block sequentially.
|
||||
waitHeight--
|
||||
|
||||
// TODO(yy): let sweeper handles the wait?
|
||||
err := waitForHeight(waitHeight, h.Notifier, h.quit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// We'll use this input index to determine the second-level output
|
||||
// index on the transaction, as the signatures requires the indexes to
|
||||
// be the same. We don't look for the second-level output script
|
||||
@ -421,7 +397,7 @@ func (h *htlcSuccessResolver) broadcastReSignedSuccessTx(immediate bool) (
|
||||
h.htlc.RHash[:], budget, waitHeight)
|
||||
|
||||
// TODO(roasbeef): need to update above for leased types
|
||||
_, err = h.Sweeper.SweepInput(
|
||||
_, err := h.Sweeper.SweepInput(
|
||||
inp,
|
||||
sweep.Params{
|
||||
Budget: budget,
|
||||
|
@ -437,10 +437,6 @@ func TestHtlcSuccessSecondStageResolutionSweeper(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
ctx.notifier.EpochChan <- &chainntnfs.BlockEpoch{
|
||||
Height: 13,
|
||||
}
|
||||
|
||||
// We expect it to sweep the second-level
|
||||
// transaction we notfied about above.
|
||||
resolver := ctx.resolver.(*htlcSuccessResolver)
|
||||
|
@ -789,30 +789,6 @@ func (h *htlcTimeoutResolver) handleCommitSpend(
|
||||
"height %v", h, h.htlc.RHash[:], waitHeight)
|
||||
}
|
||||
|
||||
// Deduct one block so this input is offered to the sweeper one
|
||||
// block earlier since the sweeper will wait for one block to
|
||||
// trigger the sweeping.
|
||||
//
|
||||
// TODO(yy): this is done so the outputs can be aggregated
|
||||
// properly. Suppose CSV locks of five 2nd-level outputs all
|
||||
// expire at height 840000, there is a race in block digestion
|
||||
// between contractcourt and sweeper:
|
||||
// - G1: block 840000 received in contractcourt, it now offers
|
||||
// the outputs to the sweeper.
|
||||
// - G2: block 840000 received in sweeper, it now starts to
|
||||
// sweep the received outputs - there's no guarantee all
|
||||
// fives have been received.
|
||||
// To solve this, we either offer the outputs earlier, or
|
||||
// implement `blockbeat`, and force contractcourt and sweeper
|
||||
// to consume each block sequentially.
|
||||
waitHeight--
|
||||
|
||||
// TODO(yy): let sweeper handles the wait?
|
||||
err := waitForHeight(waitHeight, h.Notifier, h.quit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// We'll use this input index to determine the second-level
|
||||
// output index on the transaction, as the signatures requires
|
||||
// the indexes to be the same. We don't look for the
|
||||
@ -853,7 +829,7 @@ func (h *htlcTimeoutResolver) handleCommitSpend(
|
||||
"sweeper with no deadline and budget=%v at height=%v",
|
||||
h, h.htlc.RHash[:], budget, waitHeight)
|
||||
|
||||
_, err = h.Sweeper.SweepInput(
|
||||
_, err := h.Sweeper.SweepInput(
|
||||
inp,
|
||||
sweep.Params{
|
||||
Budget: budget,
|
||||
|
@ -1120,11 +1120,6 @@ func TestHtlcTimeoutSecondStageSweeper(t *testing.T) {
|
||||
t.Fatalf("resolution not sent")
|
||||
}
|
||||
|
||||
// Mimic CSV lock expiring.
|
||||
ctx.notifier.EpochChan <- &chainntnfs.BlockEpoch{
|
||||
Height: 13,
|
||||
}
|
||||
|
||||
// The timeout tx output should now be given to
|
||||
// the sweeper.
|
||||
resolver := ctx.resolver.(*htlcTimeoutResolver)
|
||||
|
Loading…
x
Reference in New Issue
Block a user