From a58cfa65ffb65b946c35563a562ba8126c1dcb2c Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Wed, 7 Aug 2019 20:29:15 -0700 Subject: [PATCH] lnwallet+breacharbiter: update breach logic to be aware of new commitment format In this commit, we update the brar logic in the channel state machine, and also the brar itself to be aware of the new commitment format. Similar to the unilateral close summary, we'll now blank out the SingleTweak field in `NewBreachRetribution` if it's a tweakless commitment. The brar will then use this to properly identify the commitment type, to ensure we use the proper witness generation function when we're handling our own breach. --- breacharbiter.go | 20 +++++++++++++++----- breacharbiter_test.go | 39 ++++++++++++++++++++++++++++++++++++++- lnwallet/channel.go | 6 ++++++ 3 files changed, 59 insertions(+), 6 deletions(-) diff --git a/breacharbiter.go b/breacharbiter.go index fce38289d..6584cc17b 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 b4f1c5683..7f471ea2e 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 bf8cdadb4..dbf443240 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