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

     1  package contractcourt
     2  
     3  import (
     4  	"encoding/binary"
     5  	"io"
     6  	"sync"
     7  
     8  	"github.com/davecgh/go-spew/spew"
     9  	"github.com/decred/dcrd/chaincfg/chainhash"
    10  	"github.com/decred/dcrd/dcrutil/v4"
    11  	"github.com/decred/dcrd/wire"
    12  
    13  	"github.com/decred/dcrlnd/chainntnfs"
    14  	"github.com/decred/dcrlnd/channeldb"
    15  	"github.com/decred/dcrlnd/input"
    16  	"github.com/decred/dcrlnd/labels"
    17  	"github.com/decred/dcrlnd/lnwallet"
    18  	"github.com/decred/dcrlnd/sweep"
    19  )
    20  
    21  // htlcSuccessResolver is a resolver that's capable of sweeping an incoming
    22  // HTLC output on-chain. If this is the remote party's commitment, we'll sweep
    23  // it directly from the commitment output *immediately*. If this is our
    24  // commitment, we'll first broadcast the success transaction, then send it to
    25  // the incubator for sweeping. That's it, no need to send any clean up
    26  // messages.
    27  //
    28  // TODO(roasbeef): don't need to broadcast?
    29  type htlcSuccessResolver struct {
    30  	// htlcResolution is the incoming HTLC resolution for this HTLC. It
    31  	// contains everything we need to properly resolve this HTLC.
    32  	htlcResolution lnwallet.IncomingHtlcResolution
    33  
    34  	// outputIncubating returns true if we've sent the output to the output
    35  	// incubator (utxo nursery). In case the htlcResolution has non-nil
    36  	// SignDetails, it means we will let the Sweeper handle broadcasting
    37  	// the secondd-level transaction, and sweeping its output. In this case
    38  	// we let this field indicate whether we need to broadcast the
    39  	// second-level tx (false) or if it has confirmed and we must sweep the
    40  	// second-level output (true).
    41  	outputIncubating bool
    42  
    43  	// resolved reflects if the contract has been fully resolved or not.
    44  	resolved bool
    45  
    46  	// broadcastHeight is the height that the original contract was
    47  	// broadcast to the main-chain at. We'll use this value to bound any
    48  	// historical queries to the chain for spends/confirmations.
    49  	broadcastHeight uint32
    50  
    51  	// sweepTx will be non-nil if we've already crafted a transaction to
    52  	// sweep a direct HTLC output. This is only a concern if we're sweeping
    53  	// from the commitment transaction of the remote party.
    54  	//
    55  	// TODO(roasbeef): send off to utxobundler
    56  	sweepTx *wire.MsgTx
    57  
    58  	// htlc contains information on the htlc that we are resolving
    59  	// on-chain.
    60  	htlc channeldb.HTLC
    61  
    62  	// currentReport stores the current state of the resolver for reporting
    63  	// over the rpc interface. This should only be reported in case we have
    64  	// a non-nil SignDetails on the htlcResolution, otherwise the nursery
    65  	// will produce reports.
    66  	currentReport ContractReport
    67  
    68  	// reportLock prevents concurrent access to the resolver report.
    69  	reportLock sync.Mutex
    70  
    71  	contractResolverKit
    72  }
    73  
    74  // newSuccessResolver instanties a new htlc success resolver.
    75  func newSuccessResolver(res lnwallet.IncomingHtlcResolution,
    76  	broadcastHeight uint32, htlc channeldb.HTLC,
    77  	resCfg ResolverConfig) *htlcSuccessResolver {
    78  
    79  	h := &htlcSuccessResolver{
    80  		contractResolverKit: *newContractResolverKit(resCfg),
    81  		htlcResolution:      res,
    82  		broadcastHeight:     broadcastHeight,
    83  		htlc:                htlc,
    84  	}
    85  
    86  	h.initReport()
    87  
    88  	return h
    89  }
    90  
    91  // ResolverKey returns an identifier which should be globally unique for this
    92  // particular resolver within the chain the original contract resides within.
    93  //
    94  // NOTE: Part of the ContractResolver interface.
    95  func (h *htlcSuccessResolver) ResolverKey() []byte {
    96  	// The primary key for this resolver will be the outpoint of the HTLC
    97  	// on the commitment transaction itself. If this is our commitment,
    98  	// then the output can be found within the signed success tx,
    99  	// otherwise, it's just the ClaimOutpoint.
   100  	var op wire.OutPoint
   101  	if h.htlcResolution.SignedSuccessTx != nil {
   102  		op = h.htlcResolution.SignedSuccessTx.TxIn[0].PreviousOutPoint
   103  	} else {
   104  		op = h.htlcResolution.ClaimOutpoint
   105  	}
   106  
   107  	key := newResolverID(op)
   108  	return key[:]
   109  }
   110  
   111  // Resolve attempts to resolve an unresolved incoming HTLC that we know the
   112  // preimage to. If the HTLC is on the commitment of the remote party, then we'll
   113  // simply sweep it directly. Otherwise, we'll hand this off to the utxo nursery
   114  // to do its duty. There is no need to make a call to the invoice registry
   115  // anymore. Every HTLC has already passed through the incoming contest resolver
   116  // and in there the invoice was already marked as settled.
   117  //
   118  // TODO(roasbeef): create multi to batch
   119  //
   120  // NOTE: Part of the ContractResolver interface.
   121  func (h *htlcSuccessResolver) Resolve() (ContractResolver, error) {
   122  	// If we're already resolved, then we can exit early.
   123  	if h.resolved {
   124  		return nil, nil
   125  	}
   126  
   127  	// If we don't have a success transaction, then this means that this is
   128  	// an output on the remote party's commitment transaction.
   129  	if h.htlcResolution.SignedSuccessTx == nil {
   130  		return h.resolveRemoteCommitOutput()
   131  	}
   132  
   133  	// Otherwise this an output on our own commitment, and we must start by
   134  	// broadcasting the second-level success transaction.
   135  	secondLevelOutpoint, err := h.broadcastSuccessTx()
   136  	if err != nil {
   137  		return nil, err
   138  	}
   139  
   140  	// To wrap this up, we'll wait until the second-level transaction has
   141  	// been spent, then fully resolve the contract.
   142  	log.Infof("%T(%x): waiting for second-level HTLC output to be spent "+
   143  		"after csv_delay=%v", h, h.htlc.RHash[:], h.htlcResolution.CsvDelay)
   144  
   145  	spend, err := waitForSpend(
   146  		secondLevelOutpoint,
   147  		h.htlcResolution.SweepSignDesc.Output.PkScript,
   148  		h.broadcastHeight, h.Notifier, h.quit,
   149  	)
   150  	if err != nil {
   151  		return nil, err
   152  	}
   153  
   154  	h.reportLock.Lock()
   155  	h.currentReport.RecoveredBalance = h.currentReport.LimboBalance
   156  	h.currentReport.LimboBalance = 0
   157  	h.reportLock.Unlock()
   158  
   159  	h.resolved = true
   160  	return nil, h.checkpointClaim(
   161  		spend.SpenderTxHash, channeldb.ResolverOutcomeClaimed,
   162  	)
   163  }
   164  
   165  // broadcastSuccessTx handles an HTLC output on our local commitment by
   166  // broadcasting the second-level success transaction. It returns the ultimate
   167  // outpoint of the second-level tx, that we must wait to be spent for the
   168  // resolver to be fully resolved.
   169  func (h *htlcSuccessResolver) broadcastSuccessTx() (*wire.OutPoint, error) {
   170  	// If we have non-nil SignDetails, this means that have a 2nd level
   171  	// HTLC transaction that is signed using sighash SINGLE|ANYONECANPAY
   172  	// (the case for anchor type channels). In this case we can re-sign it
   173  	// and attach fees at will. We let the sweeper handle this job.
   174  	// We use the checkpointed outputIncubating field to determine if we
   175  	// already swept the HTLC output into the second level transaction.
   176  	if h.htlcResolution.SignDetails != nil {
   177  		return h.broadcastReSignedSuccessTx()
   178  	}
   179  
   180  	// Otherwise we'll publish the second-level transaction directly and
   181  	// offer the resolution to the nursery to handle.
   182  	log.Infof("%T(%x): broadcasting second-layer transition tx: %v",
   183  		h, h.htlc.RHash[:], spew.Sdump(h.htlcResolution.SignedSuccessTx))
   184  
   185  	// We'll now broadcast the second layer transaction so we can kick off
   186  	// the claiming process.
   187  	//
   188  	// TODO(roasbeef): after changing sighashes send to tx bundler
   189  	label := labels.MakeLabel(
   190  		labels.LabelTypeChannelClose, &h.ShortChanID,
   191  	)
   192  	err := h.PublishTx(h.htlcResolution.SignedSuccessTx, label)
   193  	if err != nil {
   194  		return nil, err
   195  	}
   196  
   197  	// Otherwise, this is an output on our commitment transaction. In this
   198  	// case, we'll send it to the incubator, but only if we haven't already
   199  	// done so.
   200  	if !h.outputIncubating {
   201  		log.Infof("%T(%x): incubating incoming htlc output",
   202  			h, h.htlc.RHash[:])
   203  
   204  		err := h.IncubateOutputs(
   205  			h.ChanPoint, nil, &h.htlcResolution,
   206  			h.broadcastHeight,
   207  		)
   208  		if err != nil {
   209  			return nil, err
   210  		}
   211  
   212  		h.outputIncubating = true
   213  
   214  		if err := h.Checkpoint(h); err != nil {
   215  			log.Errorf("unable to Checkpoint: %v", err)
   216  			return nil, err
   217  		}
   218  	}
   219  
   220  	return &h.htlcResolution.ClaimOutpoint, nil
   221  }
   222  
   223  // broadcastReSignedSuccessTx handles the case where we have non-nil
   224  // SignDetails, and offers the second level transaction to the Sweeper, that
   225  // will re-sign it and attach fees at will.
   226  func (h *htlcSuccessResolver) broadcastReSignedSuccessTx() (
   227  	*wire.OutPoint, error) {
   228  
   229  	// Keep track of the tx spending the HTLC output on the commitment, as
   230  	// this will be the confirmed second-level tx we'll ultimately sweep.
   231  	var commitSpend *chainntnfs.SpendDetail
   232  
   233  	// We will have to let the sweeper re-sign the success tx and wait for
   234  	// it to confirm, if we haven't already.
   235  	if !h.outputIncubating {
   236  		log.Infof("%T(%x): offering second-layer transition tx to "+
   237  			"sweeper: %v", h, h.htlc.RHash[:],
   238  			spew.Sdump(h.htlcResolution.SignedSuccessTx))
   239  
   240  		secondLevelInput := input.MakeHtlcSecondLevelSuccessAnchorInput(
   241  			h.htlcResolution.SignedSuccessTx,
   242  			h.htlcResolution.SignDetails, h.htlcResolution.Preimage,
   243  			h.broadcastHeight,
   244  		)
   245  		_, err := h.Sweeper.SweepInput(
   246  			&secondLevelInput,
   247  			sweep.Params{
   248  				Fee: sweep.FeePreference{
   249  					ConfTarget: secondLevelConfTarget,
   250  				},
   251  			},
   252  		)
   253  		if err != nil {
   254  			return nil, err
   255  		}
   256  
   257  		log.Infof("%T(%x): waiting for second-level HTLC success "+
   258  			"transaction to confirm", h, h.htlc.RHash[:])
   259  
   260  		// Wait for the second level transaction to confirm.
   261  		commitSpend, err = waitForSpend(
   262  			&h.htlcResolution.SignedSuccessTx.TxIn[0].PreviousOutPoint,
   263  			h.htlcResolution.SignDetails.SignDesc.Output.PkScript,
   264  			h.broadcastHeight, h.Notifier, h.quit,
   265  		)
   266  		if err != nil {
   267  			return nil, err
   268  		}
   269  
   270  		// Now that the second-level transaction has confirmed, we
   271  		// checkpoint the state so we'll go to the next stage in case
   272  		// of restarts.
   273  		h.outputIncubating = true
   274  		if err := h.Checkpoint(h); err != nil {
   275  			log.Errorf("unable to Checkpoint: %v", err)
   276  			return nil, err
   277  		}
   278  
   279  		log.Infof("%T(%x): second-level HTLC success transaction "+
   280  			"confirmed!", h, h.htlc.RHash[:])
   281  	}
   282  
   283  	// If we ended up here after a restart, we must again get the
   284  	// spend notification.
   285  	if commitSpend == nil {
   286  		var err error
   287  		commitSpend, err = waitForSpend(
   288  			&h.htlcResolution.SignedSuccessTx.TxIn[0].PreviousOutPoint,
   289  			h.htlcResolution.SignDetails.SignDesc.Output.PkScript,
   290  			h.broadcastHeight, h.Notifier, h.quit,
   291  		)
   292  		if err != nil {
   293  			return nil, err
   294  		}
   295  	}
   296  
   297  	// The HTLC success tx has a CSV lock that we must wait for.
   298  	waitHeight := uint32(commitSpend.SpendingHeight) +
   299  		h.htlcResolution.CsvDelay - 1
   300  
   301  	// Now that the sweeper has broadcasted the second-level transaction,
   302  	// it has confirmed, and we have checkpointed our state, we'll sweep
   303  	// the second level output. We report the resolver has moved the next
   304  	// stage.
   305  	h.reportLock.Lock()
   306  	h.currentReport.Stage = 2
   307  	h.currentReport.MaturityHeight = waitHeight
   308  	h.reportLock.Unlock()
   309  
   310  	log.Infof("%T(%x): waiting for CSV lock to expire at height %v",
   311  		h, h.htlc.RHash[:], waitHeight)
   312  
   313  	err := waitForHeight(waitHeight, h.Notifier, h.quit)
   314  	if err != nil {
   315  		return nil, err
   316  	}
   317  
   318  	// We'll use this input index to determine the second-level output
   319  	// index on the transaction, as the signatures requires the indexes to
   320  	// be the same. We don't look for the second-level output script
   321  	// directly, as there might be more than one HTLC output to the same
   322  	// pkScript.
   323  	op := &wire.OutPoint{
   324  		Hash:  *commitSpend.SpenderTxHash,
   325  		Index: commitSpend.SpenderInputIndex,
   326  	}
   327  
   328  	// Finally, let the sweeper sweep the second-level output.
   329  	log.Infof("%T(%x): CSV lock expired, offering second-layer "+
   330  		"output to sweeper: %v", h, h.htlc.RHash[:], op)
   331  
   332  	inp := input.NewCsvInput(
   333  		op, input.HtlcAcceptedSuccessSecondLevel,
   334  		&h.htlcResolution.SweepSignDesc, h.broadcastHeight,
   335  		h.htlcResolution.CsvDelay,
   336  	)
   337  	_, err = h.Sweeper.SweepInput(
   338  		inp,
   339  		sweep.Params{
   340  			Fee: sweep.FeePreference{
   341  				ConfTarget: sweepConfTarget,
   342  			},
   343  		},
   344  	)
   345  	if err != nil {
   346  		return nil, err
   347  	}
   348  
   349  	// Will return this outpoint, when this is spent the resolver is fully
   350  	// resolved.
   351  	return op, nil
   352  }
   353  
   354  // resolveRemoteCommitOutput handles sweeping an HTLC output on the remote
   355  // commitment with the preimage. In this case we can sweep the output directly,
   356  // and don't have to broadcast a second-level transaction.
   357  func (h *htlcSuccessResolver) resolveRemoteCommitOutput() (
   358  	ContractResolver, error) {
   359  
   360  	// If we don't already have the sweep transaction constructed, we'll do
   361  	// so and broadcast it.
   362  	if h.sweepTx == nil {
   363  		log.Infof("%T(%x): crafting sweep tx for incoming+remote "+
   364  			"htlc confirmed", h, h.htlc.RHash[:])
   365  
   366  		// Before we can craft out sweeping transaction, we need to
   367  		// create an input which contains all the items required to add
   368  		// this input to a sweeping transaction, and generate a
   369  		// witness.
   370  		inp := input.MakeHtlcSucceedInput(
   371  			&h.htlcResolution.ClaimOutpoint,
   372  			&h.htlcResolution.SweepSignDesc,
   373  			h.htlcResolution.Preimage[:],
   374  			h.broadcastHeight,
   375  			h.htlcResolution.CsvDelay,
   376  		)
   377  
   378  		// With the input created, we can now generate the full sweep
   379  		// transaction, that we'll use to move these coins back into
   380  		// the backing wallet.
   381  		//
   382  		// TODO: Set tx lock time to current block height instead of
   383  		// zero. Will be taken care of once sweeper implementation is
   384  		// complete.
   385  		//
   386  		// TODO: Use time-based sweeper and result chan.
   387  		var err error
   388  		h.sweepTx, err = h.Sweeper.CreateSweepTx(
   389  			[]input.Input{&inp},
   390  			sweep.FeePreference{
   391  				ConfTarget: sweepConfTarget,
   392  			}, 0,
   393  		)
   394  		if err != nil {
   395  			return nil, err
   396  		}
   397  
   398  		log.Infof("%T(%x): crafted sweep tx=%v", h,
   399  			h.htlc.RHash[:], spew.Sdump(h.sweepTx))
   400  
   401  		// TODO(halseth): should checkpoint sweep tx to DB? Since after
   402  		// a restart we might create a different tx, that will conflict
   403  		// with the published one.
   404  	}
   405  
   406  	// Regardless of whether an existing transaction was found or newly
   407  	// constructed, we'll broadcast the sweep transaction to the network.
   408  	label := labels.MakeLabel(
   409  		labels.LabelTypeChannelClose, &h.ShortChanID,
   410  	)
   411  	err := h.PublishTx(h.sweepTx, label)
   412  	if err != nil {
   413  		log.Infof("%T(%x): unable to publish tx: %v",
   414  			h, h.htlc.RHash[:], err)
   415  		return nil, err
   416  	}
   417  
   418  	// With the sweep transaction broadcast, we'll wait for its
   419  	// confirmation.
   420  	sweepTXID := h.sweepTx.TxHash()
   421  	sweepScript := h.sweepTx.TxOut[0].PkScript
   422  	confNtfn, err := h.Notifier.RegisterConfirmationsNtfn(
   423  		&sweepTXID, sweepScript, 1, h.broadcastHeight,
   424  	)
   425  	if err != nil {
   426  		return nil, err
   427  	}
   428  
   429  	log.Infof("%T(%x): waiting for sweep tx (txid=%v) to be "+
   430  		"confirmed", h, h.htlc.RHash[:], sweepTXID)
   431  
   432  	select {
   433  	case _, ok := <-confNtfn.Confirmed:
   434  		if !ok {
   435  			return nil, errResolverShuttingDown
   436  		}
   437  
   438  	case <-h.quit:
   439  		return nil, errResolverShuttingDown
   440  	}
   441  
   442  	// Once the transaction has received a sufficient number of
   443  	// confirmations, we'll mark ourselves as fully resolved and exit.
   444  	h.resolved = true
   445  
   446  	// Checkpoint the resolver, and write the outcome to disk.
   447  	return nil, h.checkpointClaim(
   448  		&sweepTXID,
   449  		channeldb.ResolverOutcomeClaimed,
   450  	)
   451  }
   452  
   453  // checkpointClaim checkpoints the success resolver with the reports it needs.
   454  // If this htlc was claimed two stages, it will write reports for both stages,
   455  // otherwise it will just write for the single htlc claim.
   456  func (h *htlcSuccessResolver) checkpointClaim(spendTx *chainhash.Hash,
   457  	outcome channeldb.ResolverOutcome) error {
   458  
   459  	// Create a resolver report for claiming of the htlc itself.
   460  	amt := dcrutil.Amount(h.htlcResolution.SweepSignDesc.Output.Value)
   461  	reports := []*channeldb.ResolverReport{
   462  		{
   463  			OutPoint:        h.htlcResolution.ClaimOutpoint,
   464  			Amount:          amt,
   465  			ResolverType:    channeldb.ResolverTypeIncomingHtlc,
   466  			ResolverOutcome: outcome,
   467  			SpendTxID:       spendTx,
   468  		},
   469  	}
   470  
   471  	// If we have a success tx, we append a report to represent our first
   472  	// stage claim.
   473  	if h.htlcResolution.SignedSuccessTx != nil {
   474  		// If the SignedSuccessTx is not nil, we are claiming the htlc
   475  		// in two stages, so we need to create a report for the first
   476  		// stage transaction as well.
   477  		spendTx := h.htlcResolution.SignedSuccessTx
   478  		spendTxID := spendTx.TxHash()
   479  
   480  		report := &channeldb.ResolverReport{
   481  			OutPoint:        spendTx.TxIn[0].PreviousOutPoint,
   482  			Amount:          h.htlc.Amt.ToAtoms(),
   483  			ResolverType:    channeldb.ResolverTypeIncomingHtlc,
   484  			ResolverOutcome: channeldb.ResolverOutcomeFirstStage,
   485  			SpendTxID:       &spendTxID,
   486  		}
   487  		reports = append(reports, report)
   488  	}
   489  
   490  	// Finally, we checkpoint the resolver with our report(s).
   491  	return h.Checkpoint(h, reports...)
   492  }
   493  
   494  // Stop signals the resolver to cancel any current resolution processes, and
   495  // suspend.
   496  //
   497  // NOTE: Part of the ContractResolver interface.
   498  func (h *htlcSuccessResolver) Stop() {
   499  	close(h.quit)
   500  }
   501  
   502  // IsResolved returns true if the stored state in the resolve is fully
   503  // resolved. In this case the target output can be forgotten.
   504  //
   505  // NOTE: Part of the ContractResolver interface.
   506  func (h *htlcSuccessResolver) IsResolved() bool {
   507  	return h.resolved
   508  }
   509  
   510  // report returns a report on the resolution state of the contract.
   511  func (h *htlcSuccessResolver) report() *ContractReport {
   512  	// If the sign details are nil, the report will be created by handled
   513  	// by the nursery.
   514  	if h.htlcResolution.SignDetails == nil {
   515  		return nil
   516  	}
   517  
   518  	h.reportLock.Lock()
   519  	defer h.reportLock.Unlock()
   520  	copy := h.currentReport
   521  	return &copy
   522  }
   523  
   524  func (h *htlcSuccessResolver) initReport() {
   525  	// We create the initial report. This will only be reported for
   526  	// resolvers not handled by the nursery.
   527  	finalAmt := h.htlc.Amt.ToAtoms()
   528  	if h.htlcResolution.SignedSuccessTx != nil {
   529  		finalAmt = dcrutil.Amount(
   530  			h.htlcResolution.SignedSuccessTx.TxOut[0].Value,
   531  		)
   532  	}
   533  
   534  	h.currentReport = ContractReport{
   535  		Outpoint:       h.htlcResolution.ClaimOutpoint,
   536  		Type:           ReportOutputIncomingHtlc,
   537  		Amount:         finalAmt,
   538  		MaturityHeight: h.htlcResolution.CsvDelay,
   539  		LimboBalance:   finalAmt,
   540  		Stage:          1,
   541  	}
   542  }
   543  
   544  // Encode writes an encoded version of the ContractResolver into the passed
   545  // Writer.
   546  //
   547  // NOTE: Part of the ContractResolver interface.
   548  func (h *htlcSuccessResolver) Encode(w io.Writer) error {
   549  	// First we'll encode our inner HTLC resolution.
   550  	if err := encodeIncomingResolution(w, &h.htlcResolution); err != nil {
   551  		return err
   552  	}
   553  
   554  	// Next, we'll write out the fields that are specified to the contract
   555  	// resolver.
   556  	if err := binary.Write(w, endian, h.outputIncubating); err != nil {
   557  		return err
   558  	}
   559  	if err := binary.Write(w, endian, h.resolved); err != nil {
   560  		return err
   561  	}
   562  	if err := binary.Write(w, endian, h.broadcastHeight); err != nil {
   563  		return err
   564  	}
   565  	if _, err := w.Write(h.htlc.RHash[:]); err != nil {
   566  		return err
   567  	}
   568  
   569  	// We encode the sign details last for backwards compatibility.
   570  	err := encodeSignDetails(w, h.htlcResolution.SignDetails)
   571  	if err != nil {
   572  		return err
   573  	}
   574  
   575  	return nil
   576  }
   577  
   578  // newSuccessResolverFromReader attempts to decode an encoded ContractResolver
   579  // from the passed Reader instance, returning an active ContractResolver
   580  // instance.
   581  func newSuccessResolverFromReader(r io.Reader, resCfg ResolverConfig) (
   582  	*htlcSuccessResolver, error) {
   583  
   584  	h := &htlcSuccessResolver{
   585  		contractResolverKit: *newContractResolverKit(resCfg),
   586  	}
   587  
   588  	// First we'll decode our inner HTLC resolution.
   589  	if err := decodeIncomingResolution(r, &h.htlcResolution); err != nil {
   590  		return nil, err
   591  	}
   592  
   593  	// Next, we'll read all the fields that are specified to the contract
   594  	// resolver.
   595  	if err := binary.Read(r, endian, &h.outputIncubating); err != nil {
   596  		return nil, err
   597  	}
   598  	if err := binary.Read(r, endian, &h.resolved); err != nil {
   599  		return nil, err
   600  	}
   601  	if err := binary.Read(r, endian, &h.broadcastHeight); err != nil {
   602  		return nil, err
   603  	}
   604  	if _, err := io.ReadFull(r, h.htlc.RHash[:]); err != nil {
   605  		return nil, err
   606  	}
   607  
   608  	// Sign details is a new field that was added to the htlc resolution,
   609  	// so it is serialized last for backwards compatibility. We try to read
   610  	// it, but don't error out if there are not bytes left.
   611  	signDetails, err := decodeSignDetails(r)
   612  	if err == nil {
   613  		h.htlcResolution.SignDetails = signDetails
   614  	} else if err != io.EOF && err != io.ErrUnexpectedEOF {
   615  		return nil, err
   616  	}
   617  
   618  	h.initReport()
   619  
   620  	return h, nil
   621  }
   622  
   623  // Supplement adds additional information to the resolver that is required
   624  // before Resolve() is called.
   625  //
   626  // NOTE: Part of the htlcContractResolver interface.
   627  func (h *htlcSuccessResolver) Supplement(htlc channeldb.HTLC) {
   628  	h.htlc = htlc
   629  }
   630  
   631  // SupplementState allows the user of a ContractResolver to supplement it with
   632  // state required for the proper resolution of a contract.
   633  //
   634  // NOTE: Part of the ContractResolver interface.
   635  func (h *htlcSuccessResolver) SupplementState(_ *channeldb.OpenChannel) {
   636  }
   637  
   638  // HtlcPoint returns the htlc's outpoint on the commitment tx.
   639  //
   640  // NOTE: Part of the htlcContractResolver interface.
   641  func (h *htlcSuccessResolver) HtlcPoint() wire.OutPoint {
   642  	return h.htlcResolution.HtlcPoint()
   643  }
   644  
   645  // A compile time assertion to ensure htlcSuccessResolver meets the
   646  // ContractResolver interface.
   647  var _ htlcContractResolver = (*htlcSuccessResolver)(nil)