contractcourt: update commitSweepResolver for taproot chans

This commit is contained in:
Olaoluwa Osuntokun 2023-03-01 22:15:17 -08:00
parent 2010239b63
commit 47f70dae3a
No known key found for this signature in database
GPG key ID: 3BBD59E99B280306

View file

@ -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