mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-03-04 09:48:19 +01:00
contractcourt: update commitSweepResolver for taproot chans
This commit is contained in:
parent
2010239b63
commit
47f70dae3a
1 changed files with 58 additions and 22 deletions
|
@ -57,6 +57,9 @@ type commitSweepResolver struct {
|
|||
// leased channel.
|
||||
leaseExpiry uint32
|
||||
|
||||
// chanType denotes the type of channel the contract belongs to.
|
||||
chanType channeldb.ChannelType
|
||||
|
||||
// currentReport stores the current state of the resolver for reporting
|
||||
// over the rpc interface.
|
||||
currentReport ContractReport
|
||||
|
@ -148,13 +151,15 @@ func waitForSpend(op *wire.OutPoint, pkScript []byte, heightHint uint32,
|
|||
}
|
||||
}
|
||||
|
||||
// getCommitTxConfHeight waits for confirmation of the commitment tx and returns
|
||||
// the confirmation height.
|
||||
// getCommitTxConfHeight waits for confirmation of the commitment tx and
|
||||
// returns the confirmation height.
|
||||
func (c *commitSweepResolver) getCommitTxConfHeight() (uint32, error) {
|
||||
txID := c.commitResolution.SelfOutPoint.Hash
|
||||
signDesc := c.commitResolution.SelfOutputSignDesc
|
||||
pkScript := signDesc.Output.PkScript
|
||||
|
||||
const confDepth = 1
|
||||
|
||||
confChan, err := c.Notifier.RegisterConfirmationsNtfn(
|
||||
&txID, pkScript, confDepth, c.broadcastHeight,
|
||||
)
|
||||
|
@ -245,23 +250,50 @@ func (c *commitSweepResolver) Resolve() (ContractResolver, error) {
|
|||
}
|
||||
}
|
||||
|
||||
var (
|
||||
isLocalCommitTx bool
|
||||
|
||||
signDesc = c.commitResolution.SelfOutputSignDesc
|
||||
)
|
||||
switch {
|
||||
// For taproot channels, we'll know if this is the local commit based
|
||||
// on the witness script. For local channels, the witness script has an
|
||||
// OP_DROP value.
|
||||
//
|
||||
// TODO(roasbeef): revisit this after the script changes
|
||||
// * otherwise need to base off the key in script or the CSV value
|
||||
// (script num encode)
|
||||
case c.chanType.IsTaproot():
|
||||
scriptLen := len(signDesc.WitnessScript)
|
||||
isLocalCommitTx = signDesc.WitnessScript[scriptLen-1] ==
|
||||
txscript.OP_DROP
|
||||
|
||||
// The output is on our local commitment if the script starts with
|
||||
// OP_IF for the revocation clause. On the remote commitment it will
|
||||
// either be a regular P2WKH or a simple sig spend with a CSV delay.
|
||||
isLocalCommitTx := c.commitResolution.SelfOutputSignDesc.WitnessScript[0] == txscript.OP_IF
|
||||
default:
|
||||
isLocalCommitTx = signDesc.WitnessScript[0] == txscript.OP_IF
|
||||
}
|
||||
isDelayedOutput := c.commitResolution.MaturityDelay != 0
|
||||
|
||||
c.log.Debugf("isDelayedOutput=%v, isLocalCommitTx=%v", isDelayedOutput,
|
||||
isLocalCommitTx)
|
||||
|
||||
// There're three types of commitments, those that have tweaks
|
||||
// for the remote key (us in this case), those that don't, and a third
|
||||
// where there is no tweak and the output is delayed. On the local
|
||||
// commitment our output will always be delayed. We'll rely on the
|
||||
// presence of the commitment tweak to to discern which type of
|
||||
// commitment this is.
|
||||
// There're three types of commitments, those that have tweaks for the
|
||||
// remote key (us in this case), those that don't, and a third where
|
||||
// there is no tweak and the output is delayed. On the local commitment
|
||||
// our output will always be delayed. We'll rely on the presence of the
|
||||
// commitment tweak to to discern which type of commitment this is.
|
||||
var witnessType input.WitnessType
|
||||
switch {
|
||||
// The local delayed output for a taproot channel.
|
||||
case isLocalCommitTx && c.chanType.IsTaproot():
|
||||
witnessType = input.TaprootLocalCommitSpend
|
||||
|
||||
// The CSV 1 delayed output for a taproot channel.
|
||||
case !isLocalCommitTx && c.chanType.IsTaproot():
|
||||
witnessType = input.TaprootRemoteCommitSpend
|
||||
|
||||
// Delayed output to us on our local commitment for a channel lease in
|
||||
// which we are the initiator.
|
||||
case isLocalCommitTx && c.hasCLTV():
|
||||
|
@ -293,9 +325,9 @@ func (c *commitSweepResolver) Resolve() (ContractResolver, error) {
|
|||
|
||||
c.log.Infof("Sweeping with witness type: %v", witnessType)
|
||||
|
||||
// We'll craft an input with all the information required for
|
||||
// the sweeper to create a fully valid sweeping transaction to
|
||||
// recover these coins.
|
||||
// We'll craft an input with all the information required for the
|
||||
// sweeper to create a fully valid sweeping transaction to recover
|
||||
// these coins.
|
||||
var inp *input.BaseInput
|
||||
if c.hasCLTV() {
|
||||
inp = input.NewCsvInputWithCltv(
|
||||
|
@ -312,6 +344,9 @@ func (c *commitSweepResolver) Resolve() (ContractResolver, error) {
|
|||
)
|
||||
}
|
||||
|
||||
// TODO(roasbeef): instead of ading ctrl block to the sign desc, make
|
||||
// new input type, have sweeper set it?
|
||||
|
||||
// With our input constructed, we'll now offer it to the
|
||||
// sweeper.
|
||||
c.log.Infof("sweeping commit output")
|
||||
|
@ -326,28 +361,28 @@ func (c *commitSweepResolver) Resolve() (ContractResolver, error) {
|
|||
|
||||
var sweepTxID chainhash.Hash
|
||||
|
||||
// Sweeper is going to join this input with other inputs if
|
||||
// possible and publish the sweep tx. When the sweep tx
|
||||
// confirms, it signals us through the result channel with the
|
||||
// outcome. Wait for this to happen.
|
||||
// Sweeper is going to join this input with other inputs if possible
|
||||
// and publish the sweep tx. When the sweep tx confirms, it signals us
|
||||
// through the result channel with the outcome. Wait for this to
|
||||
// happen.
|
||||
outcome := channeldb.ResolverOutcomeClaimed
|
||||
select {
|
||||
case sweepResult := <-resultChan:
|
||||
switch sweepResult.Err {
|
||||
// If the remote party was able to sweep this output it's
|
||||
// likely what we sent was actually a revoked commitment.
|
||||
// Report the error and continue to wrap up the contract.
|
||||
case sweep.ErrRemoteSpend:
|
||||
// If the remote party was able to sweep this output
|
||||
// it's likely what we sent was actually a revoked
|
||||
// commitment. Report the error and continue to wrap up
|
||||
// the contract.
|
||||
c.log.Warnf("local commitment output was swept by "+
|
||||
"remote party via %v", sweepResult.Tx.TxHash())
|
||||
outcome = channeldb.ResolverOutcomeUnclaimed
|
||||
|
||||
// No errors, therefore continue processing.
|
||||
case nil:
|
||||
// No errors, therefore continue processing.
|
||||
c.log.Infof("local commitment output fully resolved by "+
|
||||
"sweep tx: %v", sweepResult.Tx.TxHash())
|
||||
// Unknown errors.
|
||||
default:
|
||||
// Unknown errors.
|
||||
c.log.Errorf("unable to sweep input: %v",
|
||||
sweepResult.Err)
|
||||
|
||||
|
@ -404,6 +439,7 @@ func (c *commitSweepResolver) SupplementState(state *channeldb.OpenChannel) {
|
|||
c.leaseExpiry = state.ThawHeight
|
||||
}
|
||||
c.channelInitiator = state.IsInitiator
|
||||
c.chanType = state.ChanType
|
||||
}
|
||||
|
||||
// hasCLTV denotes whether the resolver must wait for an additional CLTV to
|
||||
|
|
Loading…
Add table
Reference in a new issue