Skip to content

Commit 9b9e4aa

Browse files
committed
tapchannel: tweak HTLC second level transaction internal key
1 parent cfc459c commit 9b9e4aa

File tree

4 files changed

+30
-20
lines changed

4 files changed

+30
-20
lines changed

tapchannel/aux_leaf_creator.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ func FetchLeavesFromCommit(chainParams *address.ChainParams,
129129
leaf, err := CreateSecondLevelHtlcTx(
130130
chanState, com.CommitTx, htlc.Amt.ToSatoshis(),
131131
keys, chainParams, htlcOutputs, cltvTimeout,
132+
htlc.HtlcIndex,
132133
)
133134
if err != nil {
134135
return lfn.Err[returnType](fmt.Errorf("unable "+
@@ -169,6 +170,7 @@ func FetchLeavesFromCommit(chainParams *address.ChainParams,
169170
leaf, err := CreateSecondLevelHtlcTx(
170171
chanState, com.CommitTx, htlc.Amt.ToSatoshis(),
171172
keys, chainParams, htlcOutputs, cltvTimeout,
173+
htlc.HtlcIndex,
172174
)
173175
if err != nil {
174176
return lfn.Err[returnType](fmt.Errorf("unable "+

tapchannel/aux_leaf_signer.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ func verifyHtlcSignature(chainParams *address.ChainParams,
370370

371371
vPackets, err := htlcSecondLevelPacketsFromCommit(
372372
chainParams, chanState, commitTx, baseJob.KeyRing, htlcOutputs,
373-
baseJob, htlcTimeout,
373+
baseJob, htlcTimeout, baseJob.HTLC.HtlcIndex,
374374
)
375375
if err != nil {
376376
return fmt.Errorf("error generating second level packets: %w",
@@ -514,7 +514,7 @@ func (s *AuxLeafSigner) generateHtlcSignature(chanState lnwallet.AuxChanState,
514514

515515
vPackets, err := htlcSecondLevelPacketsFromCommit(
516516
s.cfg.ChainParams, chanState, commitTx, baseJob.KeyRing,
517-
htlcOutputs, baseJob, htlcTimeout,
517+
htlcOutputs, baseJob, htlcTimeout, baseJob.HTLC.HtlcIndex,
518518
)
519519
if err != nil {
520520
return lnwallet.AuxSigJobResp{}, fmt.Errorf("error generating "+
@@ -602,12 +602,12 @@ func (s *AuxLeafSigner) generateHtlcSignature(chanState lnwallet.AuxChanState,
602602
func htlcSecondLevelPacketsFromCommit(chainParams *address.ChainParams,
603603
chanState lnwallet.AuxChanState, commitTx *wire.MsgTx,
604604
keyRing lnwallet.CommitmentKeyRing, htlcOutputs []*cmsg.AssetOutput,
605-
baseJob lnwallet.BaseAuxJob,
606-
htlcTimeout fn.Option[uint32]) ([]*tappsbt.VPacket, error) {
605+
baseJob lnwallet.BaseAuxJob, htlcTimeout fn.Option[uint32],
606+
htlcIndex uint64) ([]*tappsbt.VPacket, error) {
607607

608608
packets, _, err := CreateSecondLevelHtlcPackets(
609609
chanState, commitTx, baseJob.HTLC.Amount.ToSatoshis(),
610-
keyRing, chainParams, htlcOutputs, htlcTimeout,
610+
keyRing, chainParams, htlcOutputs, htlcTimeout, htlcIndex,
611611
)
612612
if err != nil {
613613
return nil, fmt.Errorf("error creating second level HTLC "+

tapchannel/aux_sweeper.go

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -217,10 +217,12 @@ func (a *AuxSweeper) createSweepVpackets(sweepInputs []*cmsg.AssetOutput,
217217
cltvTimeout = fn.Some(uint32(delay))
218218
})
219219

220+
htlcIndex := resReq.HtlcID.UnwrapOr(math.MaxUint64)
220221
alloc, err := createSecondLevelHtlcAllocations(
221222
resReq.ChanType, resReq.Initiator, sweepInputs,
222223
resReq.HtlcAmt, resReq.CommitCsvDelay, *resReq.KeyRing,
223224
fn.Some(resReq.ContractPoint.Index), cltvTimeout,
225+
htlcIndex,
224226
)
225227
if err != nil {
226228
return lfn.Err[returnType](err)
@@ -364,8 +366,7 @@ func (a *AuxSweeper) signSweepVpackets(vPackets []*tappsbt.VPacket,
364366
// tweaks to generate the key we'll use to verify the
365367
// signature.
366368
signingKey, leafToSign := applySignDescToVIn(
367-
signDesc, vIn, &a.cfg.ChainParams,
368-
tapTweak,
369+
signDesc, vIn, &a.cfg.ChainParams, tapTweak,
369370
)
370371

371372
// In this case, the witness isn't special, so we'll set the
@@ -876,7 +877,7 @@ func localHtlcTimeoutSweepDesc(req lnwallet.ResolutionReq,
876877
// As this is an HTLC on our local commitment transaction, we'll also
877878
// need to generate a sweep desc for second level HTLC.
878879
secondLevelScriptTree, err := input.TaprootSecondLevelScriptTree(
879-
req.KeyRing.RevocationKey, req.KeyRing.ToLocalKey,
880+
tweakedKeyRing.RevocationKey, req.KeyRing.ToLocalKey,
880881
req.CommitCsvDelay, lfn.None[txscript.TapLeaf](),
881882
)
882883
if err != nil {
@@ -978,7 +979,7 @@ func localHtlcSuccessSweepDesc(req lnwallet.ResolutionReq,
978979
// As this is an HTLC on our local commitment transaction, we'll also
979980
// need to generate a sweep desc for second level HTLC.
980981
secondLevelScriptTree, err := input.TaprootSecondLevelScriptTree(
981-
req.KeyRing.RevocationKey, req.KeyRing.ToLocalKey,
982+
tweakedKeyRing.RevocationKey, req.KeyRing.ToLocalKey,
982983
req.CommitCsvDelay, lfn.None[txscript.TapLeaf](),
983984
)
984985
if err != nil {
@@ -2408,9 +2409,7 @@ func (a *AuxSweeper) registerAndBroadcastSweep(req *sweep.BumpRequest,
24082409
}
24092410

24102411
// Now that we have our vPkts, we'll re-create the output commitments.
2411-
outCommitments, err := tapsend.CreateOutputCommitments(
2412-
vPkts.allPkts(),
2413-
)
2412+
outCommitments, err := tapsend.CreateOutputCommitments(vPkts.allPkts())
24142413
if err != nil {
24152414
return fmt.Errorf("unable to create output "+
24162415
"commitments: %w", err)

tapchannel/commitment.go

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1263,7 +1263,7 @@ func createSecondLevelHtlcAllocations(chanType channeldb.ChannelType,
12631263
initiator bool, htlcOutputs []*cmsg.AssetOutput, htlcAmt btcutil.Amount,
12641264
commitCsvDelay uint32, keys lnwallet.CommitmentKeyRing,
12651265
outputIndex fn.Option[uint32], htlcTimeout fn.Option[uint32],
1266-
) ([]*Allocation, error) {
1266+
htlcIndex uint64) ([]*Allocation, error) {
12671267

12681268
// TODO(roasbeef): thaw height not implemented for taproot chans rn
12691269
// (lease expiry)
@@ -1284,6 +1284,13 @@ func createSecondLevelHtlcAllocations(chanType channeldb.ChannelType,
12841284
"script sibling: %w", err)
12851285
}
12861286

1287+
// To ensure uniqueness of the script key across HTLCs with the same
1288+
// payment hash and timeout (which would be equal otherwise), we tweak
1289+
// the asset level internal key of the second-level script key as well
1290+
// with the HTLC index. We'll ONLY use this for the asset level, NOT for
1291+
// the BTC level.
1292+
tweakedTree := TweakHtlcTree(htlcTree, htlcIndex)
1293+
12871294
allocations := []*Allocation{{
12881295
Type: SecondLevelHtlcAllocation,
12891296
// If we're making the second-level transaction just to sign,
@@ -1299,12 +1306,14 @@ func createSecondLevelHtlcAllocations(chanType channeldb.ChannelType,
12991306
),
13001307
InternalKey: htlcTree.InternalKey,
13011308
NonAssetLeaves: sibling,
1302-
ScriptKey: asset.NewScriptKey(htlcTree.TaprootKey),
1309+
ScriptKey: asset.NewScriptKey(tweakedTree.TaprootKey),
13031310
SortTaprootKeyBytes: schnorr.SerializePubKey(
1311+
// This _must_ remain the non-tweaked key, since this is
1312+
// used for sorting _before_ applying any TAP tweaks.
13041313
htlcTree.TaprootKey,
13051314
),
1306-
// TODO(roasbeef): don't need it here?
1307-
CLTV: htlcTimeout.UnwrapOr(0),
1315+
CLTV: htlcTimeout.UnwrapOr(0),
1316+
HtlcIndex: htlcIndex,
13081317
}}
13091318

13101319
return allocations, nil
@@ -1316,12 +1325,12 @@ func CreateSecondLevelHtlcPackets(chanState lnwallet.AuxChanState,
13161325
commitTx *wire.MsgTx, htlcAmt btcutil.Amount,
13171326
keys lnwallet.CommitmentKeyRing, chainParams *address.ChainParams,
13181327
htlcOutputs []*cmsg.AssetOutput, htlcTimeout fn.Option[uint32],
1319-
) ([]*tappsbt.VPacket, []*Allocation, error) {
1328+
htlcIndex uint64) ([]*tappsbt.VPacket, []*Allocation, error) {
13201329

13211330
allocations, err := createSecondLevelHtlcAllocations(
13221331
chanState.ChanType, chanState.IsInitiator,
13231332
htlcOutputs, htlcAmt, uint32(chanState.LocalChanCfg.CsvDelay),
1324-
keys, fn.None[uint32](), htlcTimeout,
1333+
keys, fn.None[uint32](), htlcTimeout, htlcIndex,
13251334
)
13261335
if err != nil {
13271336
return nil, nil, err
@@ -1367,13 +1376,13 @@ func CreateSecondLevelHtlcTx(chanState lnwallet.AuxChanState,
13671376
commitTx *wire.MsgTx, htlcAmt btcutil.Amount,
13681377
keys lnwallet.CommitmentKeyRing, chainParams *address.ChainParams,
13691378
htlcOutputs []*cmsg.AssetOutput, htlcTimeout fn.Option[uint32],
1370-
) (input.AuxTapLeaf, error) {
1379+
htlcIndex uint64) (input.AuxTapLeaf, error) {
13711380

13721381
none := input.NoneTapLeaf()
13731382

13741383
vPackets, allocations, err := CreateSecondLevelHtlcPackets(
13751384
chanState, commitTx, htlcAmt, keys, chainParams, htlcOutputs,
1376-
htlcTimeout,
1385+
htlcTimeout, htlcIndex,
13771386
)
13781387
if err != nil {
13791388
return none, fmt.Errorf("error creating second level HTLC "+

0 commit comments

Comments
 (0)