github.com/decred/dcrlnd@v0.7.6/contractcourt/htlc_timeout_resolver_test.go (about)

     1  package contractcourt
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"reflect"
     7  	"sync"
     8  	"testing"
     9  	"time"
    10  
    11  	"github.com/decred/dcrd/chaincfg/chainhash"
    12  	"github.com/decred/dcrd/chaincfg/v3"
    13  	"github.com/decred/dcrd/dcrutil/v4"
    14  	"github.com/decred/dcrd/txscript/v4"
    15  	"github.com/decred/dcrd/wire"
    16  	"github.com/decred/dcrlnd/chainntnfs"
    17  	"github.com/decred/dcrlnd/channeldb"
    18  	"github.com/decred/dcrlnd/input"
    19  	"github.com/decred/dcrlnd/kvdb"
    20  	"github.com/decred/dcrlnd/lntest/mock"
    21  	"github.com/decred/dcrlnd/lntypes"
    22  	"github.com/decred/dcrlnd/lnwallet"
    23  	"github.com/stretchr/testify/require"
    24  )
    25  
    26  type mockWitnessBeacon struct {
    27  	preImageUpdates chan lntypes.Preimage
    28  	newPreimages    chan []lntypes.Preimage
    29  	lookupPreimage  map[lntypes.Hash]lntypes.Preimage
    30  }
    31  
    32  func newMockWitnessBeacon() *mockWitnessBeacon {
    33  	return &mockWitnessBeacon{
    34  		preImageUpdates: make(chan lntypes.Preimage, 1),
    35  		newPreimages:    make(chan []lntypes.Preimage),
    36  		lookupPreimage:  make(map[lntypes.Hash]lntypes.Preimage),
    37  	}
    38  }
    39  
    40  func (m *mockWitnessBeacon) SubscribeUpdates() *WitnessSubscription {
    41  	return &WitnessSubscription{
    42  		WitnessUpdates:     m.preImageUpdates,
    43  		CancelSubscription: func() {},
    44  	}
    45  }
    46  
    47  func (m *mockWitnessBeacon) LookupPreimage(payhash lntypes.Hash) (lntypes.Preimage, bool) {
    48  	preimage, ok := m.lookupPreimage[payhash]
    49  	if !ok {
    50  		return lntypes.Preimage{}, false
    51  	}
    52  	return preimage, true
    53  }
    54  
    55  func (m *mockWitnessBeacon) AddPreimages(preimages ...lntypes.Preimage) error {
    56  	m.newPreimages <- preimages
    57  	return nil
    58  }
    59  
    60  // TestHtlcTimeoutResolver tests that the timeout resolver properly handles all
    61  // variations of possible local+remote spends.
    62  func TestHtlcTimeoutResolver(t *testing.T) {
    63  	t.Parallel()
    64  
    65  	netParams := chaincfg.RegNetParams()
    66  
    67  	fakePreimageBytes := bytes.Repeat([]byte{1}, lntypes.HashSize)
    68  
    69  	var (
    70  		htlcOutpoint wire.OutPoint
    71  		fakePreimage lntypes.Preimage
    72  	)
    73  	fakeSignDesc := &input.SignDescriptor{
    74  		Output: &wire.TxOut{},
    75  	}
    76  
    77  	copy(fakePreimage[:], fakePreimageBytes)
    78  
    79  	signer := &mock.DummySigner{}
    80  	sweepTx := &wire.MsgTx{
    81  		TxIn: []*wire.TxIn{
    82  			{
    83  				PreviousOutPoint: htlcOutpoint,
    84  				SignatureScript:  []byte{0x01, 0x01},
    85  			},
    86  		},
    87  	}
    88  	fakeTimeout := int32(5)
    89  	_ = fakeTimeout // XXX
    90  
    91  	templateTx := &wire.MsgTx{
    92  		TxIn: []*wire.TxIn{
    93  			{
    94  				PreviousOutPoint: htlcOutpoint,
    95  			},
    96  		},
    97  	}
    98  
    99  	testCases := []struct {
   100  		// name is a human readable description of the test case.
   101  		name string
   102  
   103  		// remoteCommit denotes if the commitment broadcast was the
   104  		// remote commitment or not.
   105  		remoteCommit bool
   106  
   107  		// timeout denotes if the HTLC should be let timeout, or if the
   108  		// "remote" party should sweep it on-chain. This also affects
   109  		// what type of resolution message we expect.
   110  		timeout bool
   111  
   112  		// txToBroadcast is a function closure that should generate the
   113  		// transaction that should spend the HTLC output. Test authors
   114  		// can use this to customize the witness used when spending to
   115  		// trigger various redemption cases.
   116  		txToBroadcast func() (*wire.MsgTx, error)
   117  
   118  		// outcome is the resolver outcome that we expect to be reported
   119  		// once the contract is fully resolved.
   120  		outcome channeldb.ResolverOutcome
   121  	}{
   122  		// Remote commitment is broadcast, we time out the HTLC on
   123  		// chain, and should expect a fail HTLC resolution.
   124  		{
   125  			name:         "timeout remote tx",
   126  			remoteCommit: true,
   127  			timeout:      true,
   128  			txToBroadcast: func() (*wire.MsgTx, error) {
   129  				witness, err := input.ReceiverHtlcSpendTimeout(
   130  					signer, fakeSignDesc, sweepTx,
   131  					fakeTimeout,
   132  				)
   133  				if err != nil {
   134  					return nil, err
   135  				}
   136  
   137  				sigScript, err := input.WitnessStackToSigScript(witness)
   138  				if err != nil {
   139  					return nil, err
   140  				}
   141  
   142  				// To avoid triggering the race detector by
   143  				// setting the witness the second time this
   144  				// method is called during tests, we return
   145  				// immediately if the witness is already set
   146  				// correctly.
   147  				if reflect.DeepEqual(
   148  					templateTx.TxIn[0].SignatureScript, sigScript,
   149  				) {
   150  					return templateTx, nil
   151  				}
   152  
   153  				templateTx.TxIn[0].SignatureScript = sigScript
   154  				return templateTx, nil
   155  			},
   156  			outcome: channeldb.ResolverOutcomeTimeout,
   157  		},
   158  
   159  		// Our local commitment is broadcast, we timeout the HTLC and
   160  		// still expect an HTLC fail resolution.
   161  		{
   162  			name:         "timeout local tx",
   163  			remoteCommit: false,
   164  			timeout:      true,
   165  			txToBroadcast: func() (*wire.MsgTx, error) {
   166  				witness, err := input.SenderHtlcSpendTimeout(
   167  					&mock.DummySignature{}, txscript.SigHashAll,
   168  					signer, fakeSignDesc, sweepTx,
   169  				)
   170  				if err != nil {
   171  					return nil, err
   172  				}
   173  
   174  				sigScript, err := input.WitnessStackToSigScript(witness)
   175  				if err != nil {
   176  					return nil, err
   177  				}
   178  
   179  				// To avoid triggering the race detector by
   180  				// setting the witness the second time this
   181  				// method is called during tests, we return
   182  				// immediately if the witness is already set
   183  				// correctly.
   184  				if reflect.DeepEqual(
   185  					templateTx.TxIn[0].SignatureScript, sigScript,
   186  				) {
   187  					return templateTx, nil
   188  				}
   189  
   190  				templateTx.TxIn[0].SignatureScript = sigScript
   191  
   192  				// Set the outpoint to be on our commitment,
   193  				// since we need to claim in two stages.
   194  				templateTx.TxIn[0].PreviousOutPoint = testChanPoint1
   195  				return templateTx, nil
   196  			},
   197  			outcome: channeldb.ResolverOutcomeTimeout,
   198  		},
   199  
   200  		// The remote commitment is broadcast, they sweep with the
   201  		// pre-image, we should get a settle HTLC resolution.
   202  		{
   203  			name:         "success remote tx",
   204  			remoteCommit: true,
   205  			timeout:      false,
   206  			txToBroadcast: func() (*wire.MsgTx, error) {
   207  				witness, err := input.ReceiverHtlcSpendRedeem(
   208  					&mock.DummySignature{}, txscript.SigHashAll,
   209  					fakePreimageBytes, signer, fakeSignDesc,
   210  					sweepTx,
   211  				)
   212  				if err != nil {
   213  					return nil, err
   214  				}
   215  
   216  				sigScript, err := input.WitnessStackToSigScript(witness)
   217  				if err != nil {
   218  					return nil, err
   219  				}
   220  
   221  				// To avoid triggering the race detector by
   222  				// setting the witness the second time this
   223  				// method is called during tests, we return
   224  				// immediately if the witness is already set
   225  				// correctly.
   226  				if reflect.DeepEqual(
   227  					templateTx.TxIn[0].SignatureScript, sigScript,
   228  				) {
   229  					return templateTx, nil
   230  				}
   231  
   232  				templateTx.TxIn[0].SignatureScript = sigScript
   233  				return templateTx, nil
   234  			},
   235  			outcome: channeldb.ResolverOutcomeClaimed,
   236  		},
   237  
   238  		// The local commitment is broadcast, they sweep it with a
   239  		// timeout from the output, and we should still get the HTLC
   240  		// settle resolution back.
   241  		{
   242  			name:         "success local tx",
   243  			remoteCommit: false,
   244  			timeout:      false,
   245  			txToBroadcast: func() (*wire.MsgTx, error) {
   246  				witness, err := input.SenderHtlcSpendRedeem(
   247  					signer, fakeSignDesc, sweepTx,
   248  					fakePreimageBytes,
   249  				)
   250  				if err != nil {
   251  					return nil, err
   252  				}
   253  
   254  				sigScript, err := input.WitnessStackToSigScript(witness)
   255  				if err != nil {
   256  					return nil, err
   257  				}
   258  
   259  				// To avoid triggering the race detector by
   260  				// setting the witness the second time this
   261  				// method is called during tests, we return
   262  				// immediately if the witness is already set
   263  				// correctly.
   264  				if reflect.DeepEqual(
   265  					templateTx.TxIn[0].SignatureScript, sigScript,
   266  				) {
   267  					return templateTx, nil
   268  				}
   269  
   270  				templateTx.TxIn[0].SignatureScript = sigScript
   271  				return templateTx, nil
   272  			},
   273  			outcome: channeldb.ResolverOutcomeClaimed,
   274  		},
   275  	}
   276  
   277  	notifier := &mock.ChainNotifier{
   278  		EpochChan: make(chan *chainntnfs.BlockEpoch),
   279  		SpendChan: make(chan *chainntnfs.SpendDetail),
   280  		ConfChan:  make(chan *chainntnfs.TxConfirmation),
   281  	}
   282  	witnessBeacon := newMockWitnessBeacon()
   283  
   284  	for _, testCase := range testCases {
   285  		t.Logf("Running test case: %v", testCase.name)
   286  
   287  		checkPointChan := make(chan struct{}, 1)
   288  		incubateChan := make(chan struct{}, 1)
   289  		resolutionChan := make(chan ResolutionMsg, 1)
   290  		reportChan := make(chan *channeldb.ResolverReport)
   291  
   292  		chainCfg := ChannelArbitratorConfig{
   293  			ChainArbitratorConfig: ChainArbitratorConfig{
   294  				NetParams:  netParams,
   295  				Notifier:   notifier,
   296  				PreimageDB: witnessBeacon,
   297  				IncubateOutputs: func(wire.OutPoint,
   298  					*lnwallet.OutgoingHtlcResolution,
   299  					*lnwallet.IncomingHtlcResolution,
   300  					uint32) error {
   301  
   302  					incubateChan <- struct{}{}
   303  					return nil
   304  				},
   305  				DeliverResolutionMsg: func(msgs ...ResolutionMsg) error {
   306  					if len(msgs) != 1 {
   307  						return fmt.Errorf("expected 1 "+
   308  							"resolution msg, instead got %v",
   309  							len(msgs))
   310  					}
   311  
   312  					resolutionChan <- msgs[0]
   313  					return nil
   314  				},
   315  			},
   316  			PutResolverReport: func(_ kvdb.RwTx,
   317  				_ *channeldb.ResolverReport) error {
   318  
   319  				return nil
   320  			},
   321  		}
   322  
   323  		cfg := ResolverConfig{
   324  			ChannelArbitratorConfig: chainCfg,
   325  			Checkpoint: func(_ ContractResolver,
   326  				reports ...*channeldb.ResolverReport) error {
   327  
   328  				checkPointChan <- struct{}{}
   329  
   330  				// Send all of our reports into the channel.
   331  				for _, report := range reports {
   332  					reportChan <- report
   333  				}
   334  
   335  				return nil
   336  			},
   337  		}
   338  		resolver := &htlcTimeoutResolver{
   339  			htlcResolution: lnwallet.OutgoingHtlcResolution{
   340  				ClaimOutpoint: testChanPoint2,
   341  				SweepSignDesc: *fakeSignDesc,
   342  			},
   343  			contractResolverKit: *newContractResolverKit(
   344  				cfg,
   345  			),
   346  			htlc: channeldb.HTLC{
   347  				Amt: testHtlcAmt,
   348  			},
   349  		}
   350  
   351  		var reports []*channeldb.ResolverReport
   352  
   353  		// If the test case needs the remote commitment to be
   354  		// broadcast, then we'll set the timeout commit to a fake
   355  		// transaction to force the code path.
   356  		if !testCase.remoteCommit {
   357  			timeoutTx, err := testCase.txToBroadcast()
   358  			require.NoError(t, err)
   359  
   360  			resolver.htlcResolution.SignedTimeoutTx = timeoutTx
   361  
   362  			if testCase.timeout {
   363  				timeoutTxID := timeoutTx.TxHash()
   364  				reports = append(reports, &channeldb.ResolverReport{
   365  					OutPoint:        timeoutTx.TxIn[0].PreviousOutPoint,
   366  					Amount:          testHtlcAmt.ToAtoms(),
   367  					ResolverType:    channeldb.ResolverTypeOutgoingHtlc,
   368  					ResolverOutcome: channeldb.ResolverOutcomeFirstStage,
   369  					SpendTxID:       &timeoutTxID,
   370  				})
   371  			}
   372  		}
   373  
   374  		// With all the setup above complete, we can initiate the
   375  		// resolution process, and the bulk of our test.
   376  		var wg sync.WaitGroup
   377  		resolveErr := make(chan error, 1)
   378  		wg.Add(1)
   379  		go func() {
   380  			defer wg.Done()
   381  
   382  			_, err := resolver.Resolve()
   383  			if err != nil {
   384  				resolveErr <- err
   385  			}
   386  		}()
   387  
   388  		// At the output isn't yet in the nursery, we expect that we
   389  		// should receive an incubation request.
   390  		select {
   391  		case <-incubateChan:
   392  		case err := <-resolveErr:
   393  			t.Fatalf("unable to resolve HTLC: %v", err)
   394  		case <-time.After(time.Second * 5):
   395  			t.Fatalf("failed to receive incubation request")
   396  		}
   397  
   398  		// Next, the resolver should request a spend notification for
   399  		// the direct HTLC output. We'll use the txToBroadcast closure
   400  		// for the test case to generate the transaction that we'll
   401  		// send to the resolver.
   402  		spendingTx, err := testCase.txToBroadcast()
   403  		if err != nil {
   404  			t.Fatalf("unable to generate tx: %v", err)
   405  		}
   406  		spendTxHash := spendingTx.TxHash()
   407  
   408  		select {
   409  		case notifier.SpendChan <- &chainntnfs.SpendDetail{
   410  			SpendingTx:    spendingTx,
   411  			SpenderTxHash: &spendTxHash,
   412  		}:
   413  		case <-time.After(time.Second * 5):
   414  			t.Fatalf("failed to request spend ntfn")
   415  		}
   416  
   417  		if !testCase.timeout {
   418  			// If the resolver should settle now, then we'll
   419  			// extract the pre-image to be extracted and the
   420  			// resolution message sent.
   421  			select {
   422  			case newPreimage := <-witnessBeacon.newPreimages:
   423  				if newPreimage[0] != fakePreimage {
   424  					t.Fatalf("wrong pre-image: "+
   425  						"expected %v, got %v",
   426  						fakePreimage, newPreimage)
   427  				}
   428  
   429  			case <-time.After(time.Second * 5):
   430  				t.Fatalf("pre-image not added")
   431  			}
   432  
   433  			// Finally, we should get a resolution message with the
   434  			// pre-image set within the message.
   435  			select {
   436  			case resolutionMsg := <-resolutionChan:
   437  				// Once again, the pre-images should match up.
   438  				if *resolutionMsg.PreImage != fakePreimage {
   439  					t.Fatalf("wrong pre-image: "+
   440  						"expected %v, got %v",
   441  						fakePreimage, resolutionMsg.PreImage)
   442  				}
   443  			case <-time.After(time.Second * 5):
   444  				t.Fatalf("resolution not sent")
   445  			}
   446  		} else {
   447  
   448  			// Otherwise, the HTLC should now timeout.  First, we
   449  			// should get a resolution message with a populated
   450  			// failure message.
   451  			select {
   452  			case resolutionMsg := <-resolutionChan:
   453  				if resolutionMsg.Failure == nil {
   454  					t.Fatalf("expected failure resolution msg")
   455  				}
   456  			case <-time.After(time.Second * 5):
   457  				t.Fatalf("resolution not sent")
   458  			}
   459  
   460  			// We should also get another request for the spend
   461  			// notification of the second-level transaction to
   462  			// indicate that it's been swept by the nursery, but
   463  			// only if this is a local commitment transaction.
   464  			if !testCase.remoteCommit {
   465  				select {
   466  				case notifier.SpendChan <- &chainntnfs.SpendDetail{
   467  					SpendingTx:    spendingTx,
   468  					SpenderTxHash: &spendTxHash,
   469  				}:
   470  				case <-time.After(time.Second * 5):
   471  					t.Fatalf("failed to request spend ntfn")
   472  				}
   473  			}
   474  		}
   475  
   476  		// In any case, before the resolver exits, it should checkpoint
   477  		// its final state.
   478  		select {
   479  		case <-checkPointChan:
   480  		case err := <-resolveErr:
   481  			t.Fatalf("unable to resolve HTLC: %v", err)
   482  		case <-time.After(time.Second * 5):
   483  			t.Fatalf("check point not received")
   484  		}
   485  
   486  		// Add a report to our set of expected reports with the outcome
   487  		// that the test specifies (either success or timeout).
   488  		spendTxID := spendingTx.TxHash()
   489  		amt := dcrutil.Amount(fakeSignDesc.Output.Value)
   490  
   491  		reports = append(reports, &channeldb.ResolverReport{
   492  			OutPoint:        testChanPoint2,
   493  			Amount:          amt,
   494  			ResolverType:    channeldb.ResolverTypeOutgoingHtlc,
   495  			ResolverOutcome: testCase.outcome,
   496  			SpendTxID:       &spendTxID,
   497  		})
   498  
   499  		for _, report := range reports {
   500  			assertResolverReport(t, reportChan, report)
   501  		}
   502  
   503  		wg.Wait()
   504  
   505  		// Finally, the resolver should be marked as resolved.
   506  		if !resolver.resolved {
   507  			t.Fatalf("resolver should be marked as resolved")
   508  		}
   509  	}
   510  }
   511  
   512  // NOTE: the following tests essentially checks many of the same scenarios as
   513  // the test above, but they expand on it by checking resuming from checkpoints
   514  // at every stage.
   515  
   516  // TestHtlcTimeoutSingleStage tests a remote commitment confirming, and the
   517  // local node sweeping the HTLC output directly after timeout.
   518  func TestHtlcTimeoutSingleStage(t *testing.T) {
   519  	commitOutpoint := wire.OutPoint{Index: 3}
   520  
   521  	sweepTx := &wire.MsgTx{
   522  		TxIn:  []*wire.TxIn{{}},
   523  		TxOut: []*wire.TxOut{{}},
   524  	}
   525  
   526  	// singleStageResolution is a resolution for a htlc on the remote
   527  	// party's commitment.
   528  	singleStageResolution := lnwallet.OutgoingHtlcResolution{
   529  		ClaimOutpoint: commitOutpoint,
   530  		SweepSignDesc: testSignDesc,
   531  	}
   532  
   533  	sweepTxid := sweepTx.TxHash()
   534  	claim := &channeldb.ResolverReport{
   535  		OutPoint:        commitOutpoint,
   536  		Amount:          dcrutil.Amount(testSignDesc.Output.Value),
   537  		ResolverType:    channeldb.ResolverTypeOutgoingHtlc,
   538  		ResolverOutcome: channeldb.ResolverOutcomeTimeout,
   539  		SpendTxID:       &sweepTxid,
   540  	}
   541  
   542  	checkpoints := []checkpoint{
   543  		{
   544  			// Output should be handed off to the nursery.
   545  			incubating: true,
   546  		},
   547  		{
   548  			// We send a confirmation the sweep tx from published
   549  			// by the nursery.
   550  			preCheckpoint: func(ctx *htlcResolverTestContext,
   551  				_ bool) error {
   552  				// The nursery will create and publish a sweep
   553  				// tx.
   554  				ctx.notifier.SpendChan <- &chainntnfs.SpendDetail{
   555  					SpendingTx:    sweepTx,
   556  					SpenderTxHash: &sweepTxid,
   557  				}
   558  
   559  				// The resolver should deliver a failure
   560  				// resolition message (indicating we
   561  				// successfully timed out the HTLC).
   562  				select {
   563  				case resolutionMsg := <-ctx.resolutionChan:
   564  					if resolutionMsg.Failure == nil {
   565  						t.Fatalf("expected failure resolution msg")
   566  					}
   567  				case <-time.After(time.Second * 5):
   568  					t.Fatalf("resolution not sent")
   569  				}
   570  
   571  				return nil
   572  			},
   573  
   574  			// After the sweep has confirmed, we expect the
   575  			// checkpoint to be resolved, and with the above
   576  			// report.
   577  			incubating: true,
   578  			resolved:   true,
   579  			reports: []*channeldb.ResolverReport{
   580  				claim,
   581  			},
   582  		},
   583  	}
   584  
   585  	testHtlcTimeout(
   586  		t, singleStageResolution, checkpoints,
   587  	)
   588  }
   589  
   590  // TestHtlcTimeoutSecondStage tests a local commitment being confirmed, and the
   591  // local node claiming the HTLC output using the second-level timeout tx.
   592  func TestHtlcTimeoutSecondStage(t *testing.T) {
   593  	commitOutpoint := wire.OutPoint{Index: 2}
   594  	htlcOutpoint := wire.OutPoint{Index: 3}
   595  
   596  	sweepTx := &wire.MsgTx{
   597  		TxIn:  []*wire.TxIn{{}},
   598  		TxOut: []*wire.TxOut{{}},
   599  	}
   600  	sweepHash := sweepTx.TxHash()
   601  
   602  	timeoutTx := &wire.MsgTx{
   603  		TxIn: []*wire.TxIn{
   604  			{
   605  				PreviousOutPoint: commitOutpoint,
   606  			},
   607  		},
   608  		TxOut: []*wire.TxOut{
   609  			{
   610  				Value:    111,
   611  				PkScript: []byte{0xaa, 0xaa},
   612  			},
   613  		},
   614  	}
   615  
   616  	signer := &mock.DummySigner{}
   617  	witness, err := input.SenderHtlcSpendTimeout(
   618  		&mock.DummySignature{}, txscript.SigHashAll,
   619  		signer, &testSignDesc, timeoutTx,
   620  	)
   621  	require.NoError(t, err)
   622  	timeoutTx.TxIn[0].SignatureScript, err = input.WitnessStackToSigScript(witness)
   623  	require.NoError(t, err)
   624  
   625  	timeoutTxid := timeoutTx.TxHash()
   626  
   627  	// twoStageResolution is a resolution for a htlc on the local
   628  	// party's commitment.
   629  	twoStageResolution := lnwallet.OutgoingHtlcResolution{
   630  		ClaimOutpoint:   htlcOutpoint,
   631  		SignedTimeoutTx: timeoutTx,
   632  		SweepSignDesc:   testSignDesc,
   633  	}
   634  
   635  	firstStage := &channeldb.ResolverReport{
   636  		OutPoint:        commitOutpoint,
   637  		Amount:          testHtlcAmt.ToAtoms(),
   638  		ResolverType:    channeldb.ResolverTypeOutgoingHtlc,
   639  		ResolverOutcome: channeldb.ResolverOutcomeFirstStage,
   640  		SpendTxID:       &timeoutTxid,
   641  	}
   642  
   643  	secondState := &channeldb.ResolverReport{
   644  		OutPoint:        htlcOutpoint,
   645  		Amount:          dcrutil.Amount(testSignDesc.Output.Value),
   646  		ResolverType:    channeldb.ResolverTypeOutgoingHtlc,
   647  		ResolverOutcome: channeldb.ResolverOutcomeTimeout,
   648  		SpendTxID:       &sweepHash,
   649  	}
   650  
   651  	checkpoints := []checkpoint{
   652  		{
   653  			// Output should be handed off to the nursery.
   654  			incubating: true,
   655  		},
   656  		{
   657  			// We send a confirmation for our sweep tx to indicate
   658  			// that our sweep succeeded.
   659  			preCheckpoint: func(ctx *htlcResolverTestContext,
   660  				_ bool) error {
   661  				// The nursery will publish the timeout tx.
   662  				ctx.notifier.SpendChan <- &chainntnfs.SpendDetail{
   663  					SpendingTx:    timeoutTx,
   664  					SpenderTxHash: &timeoutTxid,
   665  				}
   666  
   667  				// The resolver should deliver a failure
   668  				// resolution message (indicating we
   669  				// successfully timed out the HTLC).
   670  				select {
   671  				case resolutionMsg := <-ctx.resolutionChan:
   672  					if resolutionMsg.Failure == nil {
   673  						t.Fatalf("expected failure resolution msg")
   674  					}
   675  				case <-time.After(time.Second * 1):
   676  					t.Fatalf("resolution not sent")
   677  				}
   678  
   679  				// Deliver spend of timeout tx.
   680  				ctx.notifier.SpendChan <- &chainntnfs.SpendDetail{
   681  					SpendingTx:    sweepTx,
   682  					SpenderTxHash: &sweepHash,
   683  				}
   684  
   685  				return nil
   686  			},
   687  
   688  			// After the sweep has confirmed, we expect the
   689  			// checkpoint to be resolved, and with the above
   690  			// reports.
   691  			incubating: true,
   692  			resolved:   true,
   693  			reports: []*channeldb.ResolverReport{
   694  				firstStage, secondState,
   695  			},
   696  		},
   697  	}
   698  
   699  	testHtlcTimeout(
   700  		t, twoStageResolution, checkpoints,
   701  	)
   702  }
   703  
   704  // TestHtlcTimeoutSingleStageRemoteSpend tests that when a local commitment
   705  // confirms, and the remote spends the HTLC output directly, we detect this and
   706  // extract the preimage.
   707  func TestHtlcTimeoutSingleStageRemoteSpend(t *testing.T) {
   708  	commitOutpoint := wire.OutPoint{Index: 2}
   709  	htlcOutpoint := wire.OutPoint{Index: 3}
   710  
   711  	spendTx := &wire.MsgTx{
   712  		TxIn:  []*wire.TxIn{{}},
   713  		TxOut: []*wire.TxOut{{}},
   714  	}
   715  
   716  	fakePreimageBytes := bytes.Repeat([]byte{1}, lntypes.HashSize)
   717  	var fakePreimage lntypes.Preimage
   718  	copy(fakePreimage[:], fakePreimageBytes)
   719  
   720  	signer := &mock.DummySigner{}
   721  	witness, err := input.SenderHtlcSpendRedeem(
   722  		signer, &testSignDesc, spendTx,
   723  		fakePreimageBytes,
   724  	)
   725  	require.NoError(t, err)
   726  	spendTx.TxIn[0].SignatureScript, err = input.WitnessStackToSigScript(witness)
   727  	require.NoError(t, err)
   728  
   729  	spendTxHash := spendTx.TxHash()
   730  
   731  	timeoutTx := &wire.MsgTx{
   732  		TxIn: []*wire.TxIn{
   733  			{
   734  				PreviousOutPoint: commitOutpoint,
   735  			},
   736  		},
   737  		TxOut: []*wire.TxOut{
   738  			{
   739  				Value:    123,
   740  				PkScript: []byte{0xff, 0xff},
   741  			},
   742  		},
   743  	}
   744  
   745  	timeoutWitness, err := input.SenderHtlcSpendTimeout(
   746  		&mock.DummySignature{}, txscript.SigHashAll,
   747  		signer, &testSignDesc, timeoutTx,
   748  	)
   749  	require.NoError(t, err)
   750  	timeoutTx.TxIn[0].SignatureScript, err = input.WitnessStackToSigScript(timeoutWitness)
   751  	require.NoError(t, err)
   752  
   753  	// twoStageResolution is a resolution for a htlc on the local
   754  	// party's commitment.
   755  	twoStageResolution := lnwallet.OutgoingHtlcResolution{
   756  		ClaimOutpoint:   htlcOutpoint,
   757  		SignedTimeoutTx: timeoutTx,
   758  		SweepSignDesc:   testSignDesc,
   759  	}
   760  
   761  	claim := &channeldb.ResolverReport{
   762  		OutPoint:        htlcOutpoint,
   763  		Amount:          dcrutil.Amount(testSignDesc.Output.Value),
   764  		ResolverType:    channeldb.ResolverTypeOutgoingHtlc,
   765  		ResolverOutcome: channeldb.ResolverOutcomeClaimed,
   766  		SpendTxID:       &spendTxHash,
   767  	}
   768  
   769  	checkpoints := []checkpoint{
   770  		{
   771  			// Output should be handed off to the nursery.
   772  			incubating: true,
   773  		},
   774  		{
   775  			// We send a spend notification for a remote spend with
   776  			// the preimage.
   777  			preCheckpoint: func(ctx *htlcResolverTestContext,
   778  				_ bool) error {
   779  
   780  				witnessBeacon := ctx.resolver.(*htlcTimeoutResolver).PreimageDB.(*mockWitnessBeacon)
   781  
   782  				// The remote spends the output direcly with
   783  				// the preimage.
   784  				ctx.notifier.SpendChan <- &chainntnfs.SpendDetail{
   785  					SpendingTx:    spendTx,
   786  					SpenderTxHash: &spendTxHash,
   787  				}
   788  
   789  				// We should extract the preimage.
   790  				select {
   791  				case newPreimage := <-witnessBeacon.newPreimages:
   792  					if newPreimage[0] != fakePreimage {
   793  						t.Fatalf("wrong pre-image: "+
   794  							"expected %v, got %v",
   795  							fakePreimage, newPreimage)
   796  					}
   797  
   798  				case <-time.After(time.Second * 5):
   799  					t.Fatalf("pre-image not added")
   800  				}
   801  
   802  				// Finally, we should get a resolution message
   803  				// with the pre-image set within the message.
   804  				select {
   805  				case resolutionMsg := <-ctx.resolutionChan:
   806  					if *resolutionMsg.PreImage != fakePreimage {
   807  						t.Fatalf("wrong pre-image: "+
   808  							"expected %v, got %v",
   809  							fakePreimage, resolutionMsg.PreImage)
   810  					}
   811  				case <-time.After(time.Second * 5):
   812  					t.Fatalf("resolution not sent")
   813  				}
   814  
   815  				return nil
   816  			},
   817  
   818  			// After the success tx has confirmed, we expect the
   819  			// checkpoint to be resolved, and with the above
   820  			// report.
   821  			incubating: true,
   822  			resolved:   true,
   823  			reports: []*channeldb.ResolverReport{
   824  				claim,
   825  			},
   826  		},
   827  	}
   828  
   829  	testHtlcTimeout(
   830  		t, twoStageResolution, checkpoints,
   831  	)
   832  }
   833  
   834  // TestHtlcTimeoutSecondStageRemoteSpend tests that when a remite commitment
   835  // confirms, and the remote spends the output using the success tx, we
   836  // properly detect this and extract the preimage.
   837  func TestHtlcTimeoutSecondStageRemoteSpend(t *testing.T) {
   838  	commitOutpoint := wire.OutPoint{Index: 2}
   839  
   840  	remoteSuccessTx := &wire.MsgTx{
   841  		TxIn: []*wire.TxIn{
   842  			{
   843  				PreviousOutPoint: commitOutpoint,
   844  			},
   845  		},
   846  		TxOut: []*wire.TxOut{},
   847  	}
   848  
   849  	fakePreimageBytes := bytes.Repeat([]byte{1}, lntypes.HashSize)
   850  	var fakePreimage lntypes.Preimage
   851  	copy(fakePreimage[:], fakePreimageBytes)
   852  
   853  	signer := &mock.DummySigner{}
   854  	witness, err := input.ReceiverHtlcSpendRedeem(
   855  		&mock.DummySignature{}, txscript.SigHashAll,
   856  		fakePreimageBytes, signer,
   857  		&testSignDesc, remoteSuccessTx,
   858  	)
   859  	require.NoError(t, err)
   860  
   861  	remoteSuccessTx.TxIn[0].SignatureScript, err = input.WitnessStackToSigScript(witness)
   862  	require.NoError(t, err)
   863  	successTxid := remoteSuccessTx.TxHash()
   864  
   865  	// singleStageResolution allwoing the local node to sweep HTLC output
   866  	// directly from the remote commitment after timeout.
   867  	singleStageResolution := lnwallet.OutgoingHtlcResolution{
   868  		ClaimOutpoint: commitOutpoint,
   869  		SweepSignDesc: testSignDesc,
   870  	}
   871  
   872  	claim := &channeldb.ResolverReport{
   873  		OutPoint:        commitOutpoint,
   874  		Amount:          dcrutil.Amount(testSignDesc.Output.Value),
   875  		ResolverType:    channeldb.ResolverTypeOutgoingHtlc,
   876  		ResolverOutcome: channeldb.ResolverOutcomeClaimed,
   877  		SpendTxID:       &successTxid,
   878  	}
   879  
   880  	checkpoints := []checkpoint{
   881  		{
   882  			// Output should be handed off to the nursery.
   883  			incubating: true,
   884  		},
   885  		{
   886  			// We send a confirmation for the remote's second layer
   887  			// success transcation.
   888  			preCheckpoint: func(ctx *htlcResolverTestContext,
   889  				_ bool) error {
   890  				ctx.notifier.SpendChan <- &chainntnfs.SpendDetail{
   891  					SpendingTx:    remoteSuccessTx,
   892  					SpenderTxHash: &successTxid,
   893  				}
   894  
   895  				witnessBeacon := ctx.resolver.(*htlcTimeoutResolver).PreimageDB.(*mockWitnessBeacon)
   896  
   897  				// We expect the preimage to be extracted,
   898  				select {
   899  				case newPreimage := <-witnessBeacon.newPreimages:
   900  					if newPreimage[0] != fakePreimage {
   901  						t.Fatalf("wrong pre-image: "+
   902  							"expected %v, got %v",
   903  							fakePreimage, newPreimage)
   904  					}
   905  
   906  				case <-time.After(time.Second * 5):
   907  					t.Fatalf("pre-image not added")
   908  				}
   909  
   910  				// Finally, we should get a resolution message with the
   911  				// pre-image set within the message.
   912  				select {
   913  				case resolutionMsg := <-ctx.resolutionChan:
   914  					if *resolutionMsg.PreImage != fakePreimage {
   915  						t.Fatalf("wrong pre-image: "+
   916  							"expected %v, got %v",
   917  							fakePreimage, resolutionMsg.PreImage)
   918  					}
   919  				case <-time.After(time.Second * 5):
   920  					t.Fatalf("resolution not sent")
   921  				}
   922  
   923  				return nil
   924  			},
   925  
   926  			// After the sweep has confirmed, we expect the
   927  			// checkpoint to be resolved, and with the above
   928  			// report.
   929  			incubating: true,
   930  			resolved:   true,
   931  			reports: []*channeldb.ResolverReport{
   932  				claim,
   933  			},
   934  		},
   935  	}
   936  
   937  	testHtlcTimeout(
   938  		t, singleStageResolution, checkpoints,
   939  	)
   940  }
   941  
   942  // TestHtlcTimeoutSecondStageSweeper tests that for anchor channels, when a
   943  // local commitment confirms, the timeout tx is handed to the sweeper to claim
   944  // the HTLC output.
   945  func TestHtlcTimeoutSecondStageSweeper(t *testing.T) {
   946  	commitOutpoint := wire.OutPoint{Index: 2}
   947  	htlcOutpoint := wire.OutPoint{Index: 3}
   948  
   949  	sweepTx := &wire.MsgTx{
   950  		TxIn:  []*wire.TxIn{{}},
   951  		TxOut: []*wire.TxOut{{}},
   952  	}
   953  	sweepHash := sweepTx.TxHash()
   954  
   955  	timeoutTx := &wire.MsgTx{
   956  		TxIn: []*wire.TxIn{
   957  			{
   958  				PreviousOutPoint: commitOutpoint,
   959  			},
   960  		},
   961  		TxOut: []*wire.TxOut{
   962  			{
   963  				Value:    123,
   964  				PkScript: []byte{0xff, 0xff},
   965  			},
   966  		},
   967  	}
   968  
   969  	// We set the timeout witness since the script is used when subscribing
   970  	// to spends.
   971  	signer := &mock.DummySigner{}
   972  	timeoutWitness, err := input.SenderHtlcSpendTimeout(
   973  		&mock.DummySignature{}, txscript.SigHashAll,
   974  		signer, &testSignDesc, timeoutTx,
   975  	)
   976  	require.NoError(t, err)
   977  	timeoutTx.TxIn[0].SignatureScript, err = input.WitnessStackToSigScript(timeoutWitness)
   978  	require.NoError(t, err)
   979  
   980  	reSignedTimeoutTx := &wire.MsgTx{
   981  		TxIn: []*wire.TxIn{
   982  			{
   983  				PreviousOutPoint: wire.OutPoint{
   984  					Hash:  chainhash.Hash{0xaa, 0xbb},
   985  					Index: 0,
   986  				},
   987  			},
   988  			timeoutTx.TxIn[0],
   989  			{
   990  				PreviousOutPoint: wire.OutPoint{
   991  					Hash:  chainhash.Hash{0xaa, 0xbb},
   992  					Index: 2,
   993  				},
   994  			},
   995  		},
   996  
   997  		TxOut: []*wire.TxOut{
   998  			{
   999  				Value:    111,
  1000  				PkScript: []byte{0xaa, 0xaa},
  1001  			},
  1002  			timeoutTx.TxOut[0],
  1003  		},
  1004  	}
  1005  	reSignedHash := reSignedTimeoutTx.TxHash()
  1006  	reSignedOutPoint := wire.OutPoint{
  1007  		Hash:  reSignedHash,
  1008  		Index: 1,
  1009  	}
  1010  
  1011  	// twoStageResolution is a resolution for a htlc on the local
  1012  	// party's commitment, where the timout tx can be re-signed.
  1013  	twoStageResolution := lnwallet.OutgoingHtlcResolution{
  1014  		ClaimOutpoint:   htlcOutpoint,
  1015  		SignedTimeoutTx: timeoutTx,
  1016  		SignDetails: &input.SignDetails{
  1017  			SignDesc: testSignDesc,
  1018  			PeerSig:  testSig,
  1019  		},
  1020  		SweepSignDesc: testSignDesc,
  1021  	}
  1022  
  1023  	firstStage := &channeldb.ResolverReport{
  1024  		OutPoint:        commitOutpoint,
  1025  		Amount:          testHtlcAmt.ToAtoms(),
  1026  		ResolverType:    channeldb.ResolverTypeOutgoingHtlc,
  1027  		ResolverOutcome: channeldb.ResolverOutcomeFirstStage,
  1028  		SpendTxID:       &reSignedHash,
  1029  	}
  1030  
  1031  	secondState := &channeldb.ResolverReport{
  1032  		OutPoint:        reSignedOutPoint,
  1033  		Amount:          dcrutil.Amount(testSignDesc.Output.Value),
  1034  		ResolverType:    channeldb.ResolverTypeOutgoingHtlc,
  1035  		ResolverOutcome: channeldb.ResolverOutcomeTimeout,
  1036  		SpendTxID:       &sweepHash,
  1037  	}
  1038  
  1039  	checkpoints := []checkpoint{
  1040  		{
  1041  			// The output should be given to the sweeper.
  1042  			preCheckpoint: func(ctx *htlcResolverTestContext,
  1043  				_ bool) error {
  1044  
  1045  				resolver := ctx.resolver.(*htlcTimeoutResolver)
  1046  				inp := <-resolver.Sweeper.(*mockSweeper).sweptInputs
  1047  				op := inp.OutPoint()
  1048  				if *op != commitOutpoint {
  1049  					return fmt.Errorf("outpoint %v swept, "+
  1050  						"expected %v", op,
  1051  						commitOutpoint)
  1052  				}
  1053  
  1054  				// Emulat the sweeper spending using the
  1055  				// re-signed timeout tx.
  1056  				ctx.notifier.SpendChan <- &chainntnfs.SpendDetail{
  1057  					SpendingTx:        reSignedTimeoutTx,
  1058  					SpenderInputIndex: 1,
  1059  					SpenderTxHash:     &reSignedHash,
  1060  					SpendingHeight:    10,
  1061  				}
  1062  
  1063  				return nil
  1064  			},
  1065  			// incubating=true is used to signal that the
  1066  			// second-level transaction was confirmed.
  1067  			incubating: true,
  1068  		},
  1069  		{
  1070  			// We send a confirmation for our sweep tx to indicate
  1071  			// that our sweep succeeded.
  1072  			preCheckpoint: func(ctx *htlcResolverTestContext,
  1073  				resumed bool) error {
  1074  
  1075  				// If we are resuming from a checkpoing, we
  1076  				// expect the resolver to re-subscribe to a
  1077  				// spend, hence we must resend it.
  1078  				if resumed {
  1079  					ctx.notifier.SpendChan <- &chainntnfs.SpendDetail{
  1080  						SpendingTx:        reSignedTimeoutTx,
  1081  						SpenderInputIndex: 1,
  1082  						SpenderTxHash:     &reSignedHash,
  1083  						SpendingHeight:    10,
  1084  					}
  1085  				}
  1086  
  1087  				// The resolver should deliver a failure
  1088  				// resolution message (indicating we
  1089  				// successfully timed out the HTLC).
  1090  				select {
  1091  				case resolutionMsg := <-ctx.resolutionChan:
  1092  					if resolutionMsg.Failure == nil {
  1093  						t.Fatalf("expected failure resolution msg")
  1094  					}
  1095  				case <-time.After(time.Second * 1):
  1096  					t.Fatalf("resolution not sent")
  1097  				}
  1098  
  1099  				// Mimic CSV lock expiring.
  1100  				ctx.notifier.EpochChan <- &chainntnfs.BlockEpoch{
  1101  					Height: 13,
  1102  				}
  1103  
  1104  				// The timout tx output should now be given to
  1105  				// the sweeper.
  1106  				resolver := ctx.resolver.(*htlcTimeoutResolver)
  1107  				inp := <-resolver.Sweeper.(*mockSweeper).sweptInputs
  1108  				op := inp.OutPoint()
  1109  				exp := wire.OutPoint{
  1110  					Hash:  reSignedHash,
  1111  					Index: 1,
  1112  				}
  1113  				if *op != exp {
  1114  					return fmt.Errorf("wrong outpoint swept")
  1115  				}
  1116  
  1117  				// Notify about the spend, which should resolve
  1118  				// the resolver.
  1119  				ctx.notifier.SpendChan <- &chainntnfs.SpendDetail{
  1120  					SpendingTx:     sweepTx,
  1121  					SpenderTxHash:  &sweepHash,
  1122  					SpendingHeight: 14,
  1123  				}
  1124  
  1125  				return nil
  1126  			},
  1127  
  1128  			// After the sweep has confirmed, we expect the
  1129  			// checkpoint to be resolved, and with the above
  1130  			// reports.
  1131  			incubating: true,
  1132  			resolved:   true,
  1133  			reports: []*channeldb.ResolverReport{
  1134  				firstStage,
  1135  				secondState,
  1136  			},
  1137  		},
  1138  	}
  1139  
  1140  	testHtlcTimeout(
  1141  		t, twoStageResolution, checkpoints,
  1142  	)
  1143  }
  1144  
  1145  // TestHtlcTimeoutSecondStageSweeperRemoteSpend tests that if a local timeout
  1146  // tx is offered to the sweeper, but the output is swept by the remote node, we
  1147  // properly detect this and extract the preimage.
  1148  func TestHtlcTimeoutSecondStageSweeperRemoteSpend(t *testing.T) {
  1149  	commitOutpoint := wire.OutPoint{Index: 2}
  1150  	htlcOutpoint := wire.OutPoint{Index: 3}
  1151  
  1152  	timeoutTx := &wire.MsgTx{
  1153  		TxIn: []*wire.TxIn{
  1154  			{
  1155  				PreviousOutPoint: commitOutpoint,
  1156  			},
  1157  		},
  1158  		TxOut: []*wire.TxOut{
  1159  			{
  1160  				Value:    123,
  1161  				PkScript: []byte{0xff, 0xff},
  1162  			},
  1163  		},
  1164  	}
  1165  
  1166  	// We set the timeout witness since the script is used when subscribing
  1167  	// to spends.
  1168  	signer := &mock.DummySigner{}
  1169  	timeoutWitness, err := input.SenderHtlcSpendTimeout(
  1170  		&mock.DummySignature{}, txscript.SigHashAll,
  1171  		signer, &testSignDesc, timeoutTx,
  1172  	)
  1173  	require.NoError(t, err)
  1174  	timeoutTx.TxIn[0].SignatureScript, err = input.WitnessStackToSigScript(timeoutWitness)
  1175  	require.NoError(t, err)
  1176  
  1177  	spendTx := &wire.MsgTx{
  1178  		TxIn:  []*wire.TxIn{{}},
  1179  		TxOut: []*wire.TxOut{{}},
  1180  	}
  1181  
  1182  	fakePreimageBytes := bytes.Repeat([]byte{1}, lntypes.HashSize)
  1183  	var fakePreimage lntypes.Preimage
  1184  	copy(fakePreimage[:], fakePreimageBytes)
  1185  
  1186  	witness, err := input.SenderHtlcSpendRedeem(
  1187  		signer, &testSignDesc, spendTx,
  1188  		fakePreimageBytes,
  1189  	)
  1190  	require.NoError(t, err)
  1191  	spendTx.TxIn[0].SignatureScript, err = input.WitnessStackToSigScript(witness)
  1192  	require.NoError(t, err)
  1193  
  1194  	spendTxHash := spendTx.TxHash()
  1195  
  1196  	// twoStageResolution is a resolution for a htlc on the local
  1197  	// party's commitment, where the timout tx can be re-signed.
  1198  	twoStageResolution := lnwallet.OutgoingHtlcResolution{
  1199  		ClaimOutpoint:   htlcOutpoint,
  1200  		SignedTimeoutTx: timeoutTx,
  1201  		SignDetails: &input.SignDetails{
  1202  			SignDesc: testSignDesc,
  1203  			PeerSig:  testSig,
  1204  		},
  1205  		SweepSignDesc: testSignDesc,
  1206  	}
  1207  
  1208  	claim := &channeldb.ResolverReport{
  1209  		OutPoint:        htlcOutpoint,
  1210  		Amount:          dcrutil.Amount(testSignDesc.Output.Value),
  1211  		ResolverType:    channeldb.ResolverTypeOutgoingHtlc,
  1212  		ResolverOutcome: channeldb.ResolverOutcomeClaimed,
  1213  		SpendTxID:       &spendTxHash,
  1214  	}
  1215  
  1216  	checkpoints := []checkpoint{
  1217  		{
  1218  			// The output should be given to the sweeper.
  1219  			preCheckpoint: func(ctx *htlcResolverTestContext,
  1220  				_ bool) error {
  1221  
  1222  				resolver := ctx.resolver.(*htlcTimeoutResolver)
  1223  				inp := <-resolver.Sweeper.(*mockSweeper).sweptInputs
  1224  				op := inp.OutPoint()
  1225  				if *op != commitOutpoint {
  1226  					return fmt.Errorf("outpoint %v swept, "+
  1227  						"expected %v", op,
  1228  						commitOutpoint)
  1229  				}
  1230  
  1231  				// Emulate the remote sweeping the output with the preimage.
  1232  				// re-signed timeout tx.
  1233  				ctx.notifier.SpendChan <- &chainntnfs.SpendDetail{
  1234  					SpendingTx:    spendTx,
  1235  					SpenderTxHash: &spendTxHash,
  1236  				}
  1237  
  1238  				return nil
  1239  			},
  1240  			// incubating=true is used to signal that the
  1241  			// second-level transaction was confirmed.
  1242  			incubating: true,
  1243  		},
  1244  		{
  1245  			// We send a confirmation for our sweep tx to indicate
  1246  			// that our sweep succeeded.
  1247  			preCheckpoint: func(ctx *htlcResolverTestContext,
  1248  				resumed bool) error {
  1249  
  1250  				// If we are resuming from a checkpoing, we
  1251  				// expect the resolver to re-subscribe to a
  1252  				// spend, hence we must resend it.
  1253  				if resumed {
  1254  					fmt.Println("resumed")
  1255  					ctx.notifier.SpendChan <- &chainntnfs.SpendDetail{
  1256  						SpendingTx:    spendTx,
  1257  						SpenderTxHash: &spendTxHash,
  1258  					}
  1259  				}
  1260  
  1261  				witnessBeacon := ctx.resolver.(*htlcTimeoutResolver).PreimageDB.(*mockWitnessBeacon)
  1262  
  1263  				// We should extract the preimage.
  1264  				select {
  1265  				case newPreimage := <-witnessBeacon.newPreimages:
  1266  					if newPreimage[0] != fakePreimage {
  1267  						t.Fatalf("wrong pre-image: "+
  1268  							"expected %v, got %v",
  1269  							fakePreimage, newPreimage)
  1270  					}
  1271  
  1272  				case <-time.After(time.Second * 5):
  1273  					t.Fatalf("pre-image not added")
  1274  				}
  1275  
  1276  				// Finally, we should get a resolution message
  1277  				// with the pre-image set within the message.
  1278  				select {
  1279  				case resolutionMsg := <-ctx.resolutionChan:
  1280  					if *resolutionMsg.PreImage != fakePreimage {
  1281  						t.Fatalf("wrong pre-image: "+
  1282  							"expected %v, got %v",
  1283  							fakePreimage, resolutionMsg.PreImage)
  1284  					}
  1285  				case <-time.After(time.Second * 5):
  1286  					t.Fatalf("resolution not sent")
  1287  				}
  1288  
  1289  				return nil
  1290  			},
  1291  
  1292  			// After the sweep has confirmed, we expect the
  1293  			// checkpoint to be resolved, and with the above
  1294  			// reports.
  1295  			incubating: true,
  1296  			resolved:   true,
  1297  			reports: []*channeldb.ResolverReport{
  1298  				claim,
  1299  			},
  1300  		},
  1301  	}
  1302  
  1303  	testHtlcTimeout(
  1304  		t, twoStageResolution, checkpoints,
  1305  	)
  1306  }
  1307  
  1308  func testHtlcTimeout(t *testing.T, resolution lnwallet.OutgoingHtlcResolution,
  1309  	checkpoints []checkpoint) {
  1310  
  1311  	defer timeout(t)()
  1312  
  1313  	// We first run the resolver from start to finish, ensuring it gets
  1314  	// checkpointed at every expected stage. We store the checkpointed data
  1315  	// for the next portion of the test.
  1316  	ctx := newHtlcResolverTestContext(t,
  1317  		func(htlc channeldb.HTLC, cfg ResolverConfig) ContractResolver {
  1318  			return &htlcTimeoutResolver{
  1319  				contractResolverKit: *newContractResolverKit(cfg),
  1320  				htlc:                htlc,
  1321  				htlcResolution:      resolution,
  1322  			}
  1323  		},
  1324  	)
  1325  
  1326  	checkpointedState := runFromCheckpoint(t, ctx, checkpoints)
  1327  
  1328  	// Now, from every checkpoint created, we re-create the resolver, and
  1329  	// run the test from that checkpoint.
  1330  	for i := range checkpointedState {
  1331  		cp := bytes.NewReader(checkpointedState[i])
  1332  		ctx := newHtlcResolverTestContext(t,
  1333  			func(htlc channeldb.HTLC, cfg ResolverConfig) ContractResolver {
  1334  				resolver, err := newTimeoutResolverFromReader(cp, cfg)
  1335  				if err != nil {
  1336  					t.Fatal(err)
  1337  				}
  1338  
  1339  				resolver.Supplement(htlc)
  1340  				resolver.htlcResolution = resolution
  1341  				return resolver
  1342  			},
  1343  		)
  1344  
  1345  		// Run from the given checkpoint, ensuring we'll hit the rest.
  1346  		_ = runFromCheckpoint(t, ctx, checkpoints[i+1:])
  1347  	}
  1348  }