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.
|
// leased channel.
|
||||||
leaseExpiry uint32
|
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
|
// currentReport stores the current state of the resolver for reporting
|
||||||
// over the rpc interface.
|
// over the rpc interface.
|
||||||
currentReport ContractReport
|
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
|
// getCommitTxConfHeight waits for confirmation of the commitment tx and
|
||||||
// the confirmation height.
|
// returns the confirmation height.
|
||||||
func (c *commitSweepResolver) getCommitTxConfHeight() (uint32, error) {
|
func (c *commitSweepResolver) getCommitTxConfHeight() (uint32, error) {
|
||||||
txID := c.commitResolution.SelfOutPoint.Hash
|
txID := c.commitResolution.SelfOutPoint.Hash
|
||||||
signDesc := c.commitResolution.SelfOutputSignDesc
|
signDesc := c.commitResolution.SelfOutputSignDesc
|
||||||
pkScript := signDesc.Output.PkScript
|
pkScript := signDesc.Output.PkScript
|
||||||
|
|
||||||
const confDepth = 1
|
const confDepth = 1
|
||||||
|
|
||||||
confChan, err := c.Notifier.RegisterConfirmationsNtfn(
|
confChan, err := c.Notifier.RegisterConfirmationsNtfn(
|
||||||
&txID, pkScript, confDepth, c.broadcastHeight,
|
&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
|
// The output is on our local commitment if the script starts with
|
||||||
// OP_IF for the revocation clause. On the remote commitment it will
|
// 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.
|
// 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
|
isDelayedOutput := c.commitResolution.MaturityDelay != 0
|
||||||
|
|
||||||
c.log.Debugf("isDelayedOutput=%v, isLocalCommitTx=%v", isDelayedOutput,
|
c.log.Debugf("isDelayedOutput=%v, isLocalCommitTx=%v", isDelayedOutput,
|
||||||
isLocalCommitTx)
|
isLocalCommitTx)
|
||||||
|
|
||||||
// There're three types of commitments, those that have tweaks
|
// There're three types of commitments, those that have tweaks for the
|
||||||
// for the remote key (us in this case), those that don't, and a third
|
// remote key (us in this case), those that don't, and a third where
|
||||||
// where there is no tweak and the output is delayed. On the local
|
// there is no tweak and the output is delayed. On the local commitment
|
||||||
// commitment our output will always be delayed. We'll rely on the
|
// our output will always be delayed. We'll rely on the presence of the
|
||||||
// presence of the commitment tweak to to discern which type of
|
// commitment tweak to to discern which type of commitment this is.
|
||||||
// commitment this is.
|
|
||||||
var witnessType input.WitnessType
|
var witnessType input.WitnessType
|
||||||
switch {
|
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
|
// Delayed output to us on our local commitment for a channel lease in
|
||||||
// which we are the initiator.
|
// which we are the initiator.
|
||||||
case isLocalCommitTx && c.hasCLTV():
|
case isLocalCommitTx && c.hasCLTV():
|
||||||
|
@ -293,9 +325,9 @@ func (c *commitSweepResolver) Resolve() (ContractResolver, error) {
|
||||||
|
|
||||||
c.log.Infof("Sweeping with witness type: %v", witnessType)
|
c.log.Infof("Sweeping with witness type: %v", witnessType)
|
||||||
|
|
||||||
// We'll craft an input with all the information required for
|
// We'll craft an input with all the information required for the
|
||||||
// the sweeper to create a fully valid sweeping transaction to
|
// sweeper to create a fully valid sweeping transaction to recover
|
||||||
// recover these coins.
|
// these coins.
|
||||||
var inp *input.BaseInput
|
var inp *input.BaseInput
|
||||||
if c.hasCLTV() {
|
if c.hasCLTV() {
|
||||||
inp = input.NewCsvInputWithCltv(
|
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
|
// With our input constructed, we'll now offer it to the
|
||||||
// sweeper.
|
// sweeper.
|
||||||
c.log.Infof("sweeping commit output")
|
c.log.Infof("sweeping commit output")
|
||||||
|
@ -326,28 +361,28 @@ func (c *commitSweepResolver) Resolve() (ContractResolver, error) {
|
||||||
|
|
||||||
var sweepTxID chainhash.Hash
|
var sweepTxID chainhash.Hash
|
||||||
|
|
||||||
// Sweeper is going to join this input with other inputs if
|
// Sweeper is going to join this input with other inputs if possible
|
||||||
// possible and publish the sweep tx. When the sweep tx
|
// and publish the sweep tx. When the sweep tx confirms, it signals us
|
||||||
// confirms, it signals us through the result channel with the
|
// through the result channel with the outcome. Wait for this to
|
||||||
// outcome. Wait for this to happen.
|
// happen.
|
||||||
outcome := channeldb.ResolverOutcomeClaimed
|
outcome := channeldb.ResolverOutcomeClaimed
|
||||||
select {
|
select {
|
||||||
case sweepResult := <-resultChan:
|
case sweepResult := <-resultChan:
|
||||||
switch sweepResult.Err {
|
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:
|
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 "+
|
c.log.Warnf("local commitment output was swept by "+
|
||||||
"remote party via %v", sweepResult.Tx.TxHash())
|
"remote party via %v", sweepResult.Tx.TxHash())
|
||||||
outcome = channeldb.ResolverOutcomeUnclaimed
|
outcome = channeldb.ResolverOutcomeUnclaimed
|
||||||
|
|
||||||
|
// No errors, therefore continue processing.
|
||||||
case nil:
|
case nil:
|
||||||
// No errors, therefore continue processing.
|
|
||||||
c.log.Infof("local commitment output fully resolved by "+
|
c.log.Infof("local commitment output fully resolved by "+
|
||||||
"sweep tx: %v", sweepResult.Tx.TxHash())
|
"sweep tx: %v", sweepResult.Tx.TxHash())
|
||||||
|
// Unknown errors.
|
||||||
default:
|
default:
|
||||||
// Unknown errors.
|
|
||||||
c.log.Errorf("unable to sweep input: %v",
|
c.log.Errorf("unable to sweep input: %v",
|
||||||
sweepResult.Err)
|
sweepResult.Err)
|
||||||
|
|
||||||
|
@ -404,6 +439,7 @@ func (c *commitSweepResolver) SupplementState(state *channeldb.OpenChannel) {
|
||||||
c.leaseExpiry = state.ThawHeight
|
c.leaseExpiry = state.ThawHeight
|
||||||
}
|
}
|
||||||
c.channelInitiator = state.IsInitiator
|
c.channelInitiator = state.IsInitiator
|
||||||
|
c.chanType = state.ChanType
|
||||||
}
|
}
|
||||||
|
|
||||||
// hasCLTV denotes whether the resolver must wait for an additional CLTV to
|
// hasCLTV denotes whether the resolver must wait for an additional CLTV to
|
||||||
|
|
Loading…
Add table
Reference in a new issue