diff --git a/breacharbiter.go b/breacharbiter.go index fce38289..6584cc17 100644 --- a/breacharbiter.go +++ b/breacharbiter.go @@ -944,17 +944,24 @@ func newRetributionInfo(chanPoint *wire.OutPoint, // First, record the breach information for the local channel point if // it is not considered dust, which is signaled by a non-nil sign - // descriptor. Here we use CommitmentNoDelay since this output belongs - // to us and has no time-based constraints on spending. + // descriptor. Here we use CommitmentNoDelay (or + // CommitmentNoDelayTweakless for newer commitments) since this output + // belongs to us and has no time-based constraints on spending. if breachInfo.LocalOutputSignDesc != nil { + witnessType := input.CommitmentNoDelay + if breachInfo.LocalOutputSignDesc.SingleTweak == nil { + witnessType = input.CommitSpendNoDelayTweakless + } + localOutput := makeBreachedOutput( &breachInfo.LocalOutpoint, - input.CommitmentNoDelay, + witnessType, // No second level script as this is a commitment // output. nil, breachInfo.LocalOutputSignDesc, - breachInfo.BreachHeight) + breachInfo.BreachHeight, + ) breachedOutputs = append(breachedOutputs, localOutput) } @@ -972,7 +979,8 @@ func newRetributionInfo(chanPoint *wire.OutPoint, // output. nil, breachInfo.RemoteOutputSignDesc, - breachInfo.BreachHeight) + breachInfo.BreachHeight, + ) breachedOutputs = append(breachedOutputs, remoteOutput) } @@ -1048,6 +1056,8 @@ func (b *breachArbiter) createJusticeTx( // type is unrecognized, we will omit it from the transaction. var witnessWeight int switch inp.WitnessType() { + case input.CommitSpendNoDelayTweakless: + fallthrough case input.CommitmentNoDelay: witnessWeight = input.P2WKHWitnessSize diff --git a/breacharbiter_test.go b/breacharbiter_test.go index b4f1c568..7f471ea2 100644 --- a/breacharbiter_test.go +++ b/breacharbiter_test.go @@ -142,6 +142,42 @@ var ( }, secondLevelWitnessScript: breachKeys[0], }, + { + amt: btcutil.Amount(1e7), + outpoint: breachOutPoints[0], + witnessType: input.CommitSpendNoDelayTweakless, + signDesc: input.SignDescriptor{ + WitnessScript: []byte{ + 0x00, 0x14, 0xee, 0x91, 0x41, 0x7e, + 0x85, 0x6c, 0xde, 0x10, 0xa2, 0x91, + 0x1e, 0xdc, 0xbd, 0xbd, 0x69, 0xe2, + 0xef, 0xb5, 0x71, 0x48, + }, + Output: &wire.TxOut{ + Value: 5000000000, + PkScript: []byte{ + 0x41, // OP_DATA_65 + 0x04, 0xd6, 0x4b, 0xdf, 0xd0, + 0x9e, 0xb1, 0xc5, 0xfe, 0x29, + 0x5a, 0xbd, 0xeb, 0x1d, 0xca, + 0x42, 0x81, 0xbe, 0x98, 0x8e, + 0x2d, 0xa0, 0xb6, 0xc1, 0xc6, + 0xa5, 0x9d, 0xc2, 0x26, 0xc2, + 0x86, 0x24, 0xe1, 0x81, 0x75, + 0xe8, 0x51, 0xc9, 0x6b, 0x97, + 0x3d, 0x81, 0xb0, 0x1c, 0xc3, + 0x1f, 0x04, 0x78, 0x34, 0xbc, + 0x06, 0xd6, 0xd6, 0xed, 0xf6, + 0x20, 0xd1, 0x84, 0x24, 0x1a, + 0x6a, 0xed, 0x8b, 0x63, + 0xa6, // 65-byte signature + 0xac, // OP_CHECKSIG + }, + }, + HashType: txscript.SigHashAll, + }, + secondLevelWitnessScript: breachKeys[0], + }, { amt: btcutil.Amount(2e9), outpoint: breachOutPoints[1], @@ -1344,7 +1380,8 @@ func testBreachSpends(t *testing.T, test breachTest) { // Notify the breach arbiter about the breach. retribution, err := lnwallet.NewBreachRetribution( - alice.State(), height, 1) + alice.State(), height, 1, + ) if err != nil { t.Fatalf("unable to create breach retribution: %v", err) } diff --git a/lnwallet/channel.go b/lnwallet/channel.go index bf8cdadb..dbf44324 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -2066,6 +2066,12 @@ func NewBreachRetribution(chanState *channeldb.OpenChannel, stateNum uint64, }, HashType: txscript.SigHashAll, } + + // If this is a tweakless commitment, then we can safely blank + // out the SingleTweak value as it isn't needed. + if tweaklessCommit { + localSignDesc.SingleTweak = nil + } } // Similarly, if the remote balance exceeds the remote party's dust