From 995e6cd66bdd05b7076de05b2e71b30899bc4dff Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Wed, 1 Mar 2023 21:45:27 -0800 Subject: [PATCH] lnwallet: update NewBreachRetribution to handle taproot chans For our local output, we need a valid control block. To sweep the remote output, we use the taptweak so we can spend the keyspend path. --- lnwallet/channel.go | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/lnwallet/channel.go b/lnwallet/channel.go index c90a3e2c9..02462f010 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -2475,6 +2475,7 @@ func NewBreachRetribution(chanState *channeldb.OpenChannel, stateNum uint64, // If the returned *RevocationLog is non-nil, use it to derive the info // we need. + isTaproot := chanState.ChanType.IsTaproot() if revokedLog != nil { br, ourAmt, theirAmt, err = createBreachRetribution( revokedLog, spendTx, chanState, keyRing, @@ -2517,6 +2518,22 @@ func NewBreachRetribution(chanState *channeldb.OpenChannel, stateNum uint64, }, HashType: txscript.SigHashAll, } + + // For taproot channels, we'll make sure to set the script path + // spend (as our output on their revoked tx still needs the + // delay), and set the control block. + if isTaproot { + br.LocalOutputSignDesc.SignMethod = input.TaprootScriptSpendSignMethod + + ctrlBlock := input.MakeTaprootCtrlBlock( + br.LocalOutputSignDesc.WitnessScript, + &input.TaprootNUMSKey, ourScript.ScriptTree, + ) + br.LocalOutputSignDesc.ControlBlock, err = ctrlBlock.ToBytes() + if err != nil { + return nil, err + } + } } // Similarly, if their balance exceeds the remote party's dust limit, @@ -2533,6 +2550,18 @@ func NewBreachRetribution(chanState *channeldb.OpenChannel, stateNum uint64, }, HashType: txscript.SigHashAll, } + + // For taproot channels, the remote ouput (the revoked outuput) + // can be spent using a single key spend, now that we know the + // revocation key. + if isTaproot { + br.RemoteOutputSignDesc.SignMethod = input.TaprootKeySpendSignMethod + + // We'll also need to set the taptweak as we'll be + // signing with the full output key. + tapscriptRoot := theirScript.ScriptTree.RootNode.TapHash() + br.RemoteOutputSignDesc.TapTweak = tapscriptRoot[:] + } } // Finally, with all the necessary data constructed, we can pad the