Skip to content

Commit 09f5e08

Browse files
committed
contractcourt: Fix heuristic for identifying STC commit broadcaster.
This commit fixes the heuristic we use for identifying the party that broadcast a Simple Taproot Channel commitment transaction. Prior to this change we checked if the last script element was an OP_DROP. However, both the local and remote commitment outputs have an OP_DROP at the end. The new approach checks the resolver's SignDescriptor and compares that key to the keys in the channel's local ChannelConfig. If the key is the delay key, we know that it is our commitment transaction.
1 parent 31d4575 commit 09f5e08

File tree

1 file changed

+23
-9
lines changed

1 file changed

+23
-9
lines changed

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)