Skip to content

Commit

Permalink
contractcourt: Fix heuristic for identifying STC commit broadcaster.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
ProofOfKeags committed Jul 17, 2024
1 parent 31d4575 commit 09f5e08
Showing 1 changed file with 23 additions and 9 deletions.
32 changes: 23 additions & 9 deletions contractcourt/commit_sweep_resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ import (
// version of the commitment transaction. We can sweep this output immediately,
// as it doesn't have a time-lock delay.
type commitSweepResolver struct {
// localChanCfg is used to provide the resolver with the keys required
// to identify whether the commitment transaction was broadcast by the
// local or remote party.
localChanCfg channeldb.ChannelConfig

// commitResolution contains all data required to successfully sweep
// this HTLC on-chain.
commitResolution lnwallet.CommitOutputResolution
Expand Down Expand Up @@ -252,18 +257,26 @@ func (c *commitSweepResolver) Resolve(_ bool) (ContractResolver, error) {

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)
// on the timelock value. For remote commitment transactions, the
// witness script has a timelock of 1.
case c.chanType.IsTaproot():
scriptLen := len(signDesc.WitnessScript)
isLocalCommitTx = signDesc.WitnessScript[scriptLen-1] ==
txscript.OP_DROP
delayKey := c.localChanCfg.DelayBasePoint.PubKey
nonDelayKey := c.localChanCfg.PaymentBasePoint.PubKey

signKey := c.commitResolution.SelfOutputSignDesc.KeyDesc.PubKey

// If the key in the script is neither of these, we shouldn't
// proceed. This should be impossible.
if !signKey.IsEqual(delayKey) && !signKey.IsEqual(nonDelayKey) {
return nil, fmt.Errorf("unknown sign key %v", signKey)
}

// The commitment transaction is ours iff the signing key is
// the delay key.
isLocalCommitTx = signKey.IsEqual(delayKey)

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

0 comments on commit 09f5e08

Please sign in to comment.