Skip to content

Commit 6dea864

Browse files
authored
Merge pull request #8879 from ProofOfKeags/bugfix/taproot-coop-sequence
contractcourt: Taproot Channel Bugfixes
2 parents fdd28c8 + 09f5e08 commit 6dea864

File tree

2 files changed

+28
-10
lines changed

2 files changed

+28
-10
lines changed

contractcourt/chain_watcher.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"github.com/btcsuite/btcd/btcutil"
1313
"github.com/btcsuite/btcd/chaincfg"
1414
"github.com/btcsuite/btcd/chaincfg/chainhash"
15+
"github.com/btcsuite/btcd/mempool"
1516
"github.com/btcsuite/btcd/txscript"
1617
"github.com/btcsuite/btcd/wire"
1718
"github.com/davecgh/go-spew/spew"
@@ -689,7 +690,10 @@ func (c *chainWatcher) closeObserver(spendNtfn *chainntnfs.SpendEvent) {
689690
// sequence number that's finalized. This won't happen with
690691
// regular commitment transactions due to the state hint
691692
// encoding scheme.
692-
if commitTxBroadcast.TxIn[0].Sequence == wire.MaxTxInSequenceNum {
693+
switch commitTxBroadcast.TxIn[0].Sequence {
694+
case wire.MaxTxInSequenceNum:
695+
fallthrough
696+
case mempool.MaxRBFSequence:
693697
// TODO(roasbeef): rare but possible, need itest case
694698
// for
695699
err := c.dispatchCooperativeClose(commitSpend)

contractcourt/commit_sweep_resolver.go

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ import (
2424
// version of the commitment transaction. We can sweep this output immediately,
2525
// as it doesn't have a time-lock delay.
2626
type commitSweepResolver struct {
27+
// localChanCfg is used to provide the resolver with the keys required
28+
// to identify whether the commitment transaction was broadcast by the
29+
// local or remote party.
30+
localChanCfg channeldb.ChannelConfig
31+
2732
// commitResolution contains all data required to successfully sweep
2833
// this HTLC on-chain.
2934
commitResolution lnwallet.CommitOutputResolution
@@ -252,18 +257,26 @@ func (c *commitSweepResolver) Resolve(_ bool) (ContractResolver, error) {
252257

253258
signDesc = c.commitResolution.SelfOutputSignDesc
254259
)
260+
255261
switch {
256262
// For taproot channels, we'll know if this is the local commit based
257-
// on the witness script. For local channels, the witness script has an
258-
// OP_DROP value.
259-
//
260-
// TODO(roasbeef): revisit this after the script changes
261-
// * otherwise need to base off the key in script or the CSV value
262-
// (script num encode)
263+
// on the timelock value. For remote commitment transactions, the
264+
// witness script has a timelock of 1.
263265
case c.chanType.IsTaproot():
264-
scriptLen := len(signDesc.WitnessScript)
265-
isLocalCommitTx = signDesc.WitnessScript[scriptLen-1] ==
266-
txscript.OP_DROP
266+
delayKey := c.localChanCfg.DelayBasePoint.PubKey
267+
nonDelayKey := c.localChanCfg.PaymentBasePoint.PubKey
268+
269+
signKey := c.commitResolution.SelfOutputSignDesc.KeyDesc.PubKey
270+
271+
// If the key in the script is neither of these, we shouldn't
272+
// proceed. This should be impossible.
273+
if !signKey.IsEqual(delayKey) && !signKey.IsEqual(nonDelayKey) {
274+
return nil, fmt.Errorf("unknown sign key %v", signKey)
275+
}
276+
277+
// The commitment transaction is ours iff the signing key is
278+
// the delay key.
279+
isLocalCommitTx = signKey.IsEqual(delayKey)
267280

268281
// The output is on our local commitment if the script starts with
269282
// OP_IF for the revocation clause. On the remote commitment it will
@@ -446,6 +459,7 @@ func (c *commitSweepResolver) SupplementState(state *channeldb.OpenChannel) {
446459
if state.ChanType.HasLeaseExpiration() {
447460
c.leaseExpiry = state.ThawHeight
448461
}
462+
c.localChanCfg = state.LocalChanCfg
449463
c.channelInitiator = state.IsInitiator
450464
c.chanType = state.ChanType
451465
}

0 commit comments

Comments
 (0)