Skip to content

Commit fe3d17b

Browse files
committed
multi: add the aggregate internal pubkey to the v3 htlc
1 parent 55fa5d2 commit fe3d17b

File tree

7 files changed

+44
-68
lines changed

7 files changed

+44
-68
lines changed

client.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ func (s *Client) FetchSwaps() ([]*SwapInfo, error) {
195195
htlc, err := swap.NewHtlc(
196196
GetHtlcScriptVersion(swp.Contract.ProtocolVersion),
197197
swp.Contract.CltvExpiry, swp.Contract.SenderKey,
198-
swp.Contract.ReceiverKey, nil, swp.Hash, swap.HtlcP2WSH,
198+
swp.Contract.ReceiverKey, swp.Hash, swap.HtlcP2WSH,
199199
s.lndServices.ChainParams,
200200
)
201201
if err != nil {
@@ -216,7 +216,7 @@ func (s *Client) FetchSwaps() ([]*SwapInfo, error) {
216216
htlcNP2WSH, err := swap.NewHtlc(
217217
GetHtlcScriptVersion(swp.Contract.ProtocolVersion),
218218
swp.Contract.CltvExpiry, swp.Contract.SenderKey,
219-
swp.Contract.ReceiverKey, nil, swp.Hash, swap.HtlcNP2WSH,
219+
swp.Contract.ReceiverKey, swp.Hash, swap.HtlcNP2WSH,
220220
s.lndServices.ChainParams,
221221
)
222222
if err != nil {
@@ -226,7 +226,7 @@ func (s *Client) FetchSwaps() ([]*SwapInfo, error) {
226226
htlcP2WSH, err := swap.NewHtlc(
227227
GetHtlcScriptVersion(swp.Contract.ProtocolVersion),
228228
swp.Contract.CltvExpiry, swp.Contract.SenderKey,
229-
swp.Contract.ReceiverKey, nil, swp.Hash, swap.HtlcP2WSH,
229+
swp.Contract.ReceiverKey, swp.Hash, swap.HtlcP2WSH,
230230
s.lndServices.ChainParams,
231231
)
232232
if err != nil {

client_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ func testResume(t *testing.T, confs uint32, expired, preimageRevealed,
284284
scriptVersion := GetHtlcScriptVersion(protocolVersion)
285285
htlc, err := swap.NewHtlc(
286286
scriptVersion, pendingSwap.Contract.CltvExpiry, senderKey,
287-
receiverKey, nil, hash, swap.HtlcP2WSH, &chaincfg.TestNet3Params,
287+
receiverKey, hash, swap.HtlcP2WSH, &chaincfg.TestNet3Params,
288288
)
289289
require.NoError(t, err)
290290
require.Equal(t, htlc.PkScript, confIntent.PkScript)

loopd/view.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ func viewOut(swapClient *loop.Client, chainParams *chaincfg.Params) error {
5454
s.Contract.CltvExpiry,
5555
s.Contract.SenderKey,
5656
s.Contract.ReceiverKey,
57-
nil, s.Hash, swap.HtlcP2WSH, chainParams,
57+
s.Hash, swap.HtlcP2WSH, chainParams,
5858
)
5959
if err != nil {
6060
return err
@@ -106,7 +106,7 @@ func viewIn(swapClient *loop.Client, chainParams *chaincfg.Params) error {
106106
s.Contract.CltvExpiry,
107107
s.Contract.SenderKey,
108108
s.Contract.ReceiverKey,
109-
nil, s.Hash, swap.HtlcNP2WSH, chainParams,
109+
s.Hash, swap.HtlcNP2WSH, chainParams,
110110
)
111111
if err != nil {
112112
return err

loopin_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,7 @@ func testLoopInResume(t *testing.T, state loopdb.SwapState, expired bool,
387387

388388
htlc, err := swap.NewHtlc(
389389
scriptVersion, contract.CltvExpiry, contract.SenderKey,
390-
contract.ReceiverKey, nil, testPreimage.Hash(), swap.HtlcNP2WSH,
390+
contract.ReceiverKey, testPreimage.Hash(), swap.HtlcNP2WSH,
391391
cfg.lnd.ChainParams,
392392
)
393393
if err != nil {

swap.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ func (s *swapKit) getHtlc(outputType swap.HtlcOutputType) (*swap.Htlc, error) {
7272
return swap.NewHtlc(
7373
GetHtlcScriptVersion(s.contract.ProtocolVersion),
7474
s.contract.CltvExpiry, s.contract.SenderKey,
75-
s.contract.ReceiverKey, nil, s.hash, outputType,
75+
s.contract.ReceiverKey, s.hash, outputType,
7676
s.swapConfig.lnd.ChainParams,
7777
)
7878
}

swap/htlc.go

Lines changed: 32 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@ import (
66
"errors"
77
"fmt"
88

9-
btcec "github.com/btcsuite/btcd/btcec/v2"
9+
"github.com/btcsuite/btcd/btcec/v2"
1010
"github.com/btcsuite/btcd/btcec/v2/schnorr"
11+
"github.com/btcsuite/btcd/btcec/v2/schnorr/musig2"
1112
"github.com/btcsuite/btcd/btcutil"
1213
"github.com/btcsuite/btcd/chaincfg"
14+
"github.com/btcsuite/btcd/chaincfg/chainhash"
1315
"github.com/btcsuite/btcd/txscript"
1416
"github.com/btcsuite/btcd/wire"
1517
secp "github.com/decred/dcrd/dcrec/secp256k1/v4"
@@ -106,7 +108,7 @@ var (
106108
// script size.
107109
QuoteHtlc, _ = NewHtlc(
108110
HtlcV2,
109-
^int32(0), quoteKey, quoteKey, nil, quoteHash, HtlcP2WSH,
111+
^int32(0), quoteKey, quoteKey, quoteHash, HtlcP2WSH,
110112
&chaincfg.MainNetParams,
111113
)
112114

@@ -119,17 +121,6 @@ var (
119121
// selected for a v1 or v2 script.
120122
ErrInvalidOutputSelected = fmt.Errorf("taproot output selected for " +
121123
"non taproot htlc")
122-
123-
// ErrSharedKeyNotNeeded is returned when a shared key is provided for
124-
// either the v1 or v2 script. Shared key is only necessary for the v3
125-
// script.
126-
ErrSharedKeyNotNeeded = fmt.Errorf("shared key not supported for " +
127-
"script version")
128-
129-
// ErrSharedKeyRequired is returned when a script version requires a
130-
// shared key.
131-
ErrSharedKeyRequired = fmt.Errorf("shared key required for script " +
132-
"version")
133124
)
134125

135126
// String returns the string value of HtlcOutputType.
@@ -152,9 +143,8 @@ func (h HtlcOutputType) String() string {
152143
// NewHtlc returns a new instance. For v3 scripts, an internal pubkey generated
153144
// by both participants must be provided.
154145
func NewHtlc(version ScriptVersion, cltvExpiry int32,
155-
senderKey, receiverKey [33]byte, sharedKey *btcec.PublicKey,
156-
hash lntypes.Hash, outputType HtlcOutputType,
157-
chainParams *chaincfg.Params) (*Htlc, error) {
146+
senderKey, receiverKey [33]byte, hash lntypes.Hash,
147+
outputType HtlcOutputType, chainParams *chaincfg.Params) (*Htlc, error) {
158148

159149
var (
160150
err error
@@ -163,28 +153,18 @@ func NewHtlc(version ScriptVersion, cltvExpiry int32,
163153

164154
switch version {
165155
case HtlcV1:
166-
if sharedKey != nil {
167-
return nil, ErrSharedKeyNotNeeded
168-
}
169156
htlc, err = newHTLCScriptV1(
170157
cltvExpiry, senderKey, receiverKey, hash,
171158
)
172159

173160
case HtlcV2:
174-
if sharedKey != nil {
175-
return nil, ErrSharedKeyNotNeeded
176-
}
177161
htlc, err = newHTLCScriptV2(
178162
cltvExpiry, senderKey, receiverKey, hash,
179163
)
180164

181165
case HtlcV3:
182-
if sharedKey == nil {
183-
return nil, ErrSharedKeyRequired
184-
}
185166
htlc, err = newHTLCScriptV3(
186-
cltvExpiry, senderKey, receiverKey,
187-
sharedKey, hash,
167+
cltvExpiry, senderKey, receiverKey, hash,
188168
)
189169

190170
default:
@@ -650,44 +630,50 @@ func (h *HtlcScriptV2) lockingConditions(htlcOutputType HtlcOutputType,
650630

651631
// HtlcScriptV3 encapsulates the htlc v3 script.
652632
type HtlcScriptV3 struct {
653-
// The final locking script for the timeout path which is available to
654-
// the sender after the set blockheight.
633+
// TimeoutScript is the final locking script for the timeout path which
634+
// is available to the sender after the set blockheight.
655635
TimeoutScript []byte
656636

657-
// The final locking script for the success path in which the receiver
658-
// reveals the preimage.
637+
// SuccessScript is the final locking script for the success path in
638+
// which the receiver reveals the preimage.
659639
SuccessScript []byte
660640

661-
// The public key for the keyspend path which bypasses the above two
662-
// locking scripts.
641+
// InternalPubKey is the public key for the keyspend path which bypasses
642+
// the above two locking scripts.
663643
InternalPubKey *btcec.PublicKey
664644

665-
// The taproot public key which is created with the above 3 inputs.
645+
// TaprootKey is the taproot public key which is created with the above
646+
// 3 inputs.
666647
TaprootKey *btcec.PublicKey
648+
649+
// RootHash is the root hash of the taptree.
650+
RootHash chainhash.Hash
667651
}
668652

669653
// newHTLCScriptV3 constructs a HtlcScipt with the HTLC V3 taproot script.
670-
func newHTLCScriptV3(cltvExpiry int32, senderHtlcKey,
671-
receiverHtlcKey [33]byte, sharedKey *btcec.PublicKey,
654+
func newHTLCScriptV3(cltvExpiry int32, senderHtlcKey, receiverHtlcKey [33]byte,
672655
swapHash lntypes.Hash) (*HtlcScriptV3, error) {
673656

674-
receiverPubKey, err := btcec.ParsePubKey(
675-
receiverHtlcKey[:],
676-
)
657+
senderPubKey, err := schnorr.ParsePubKey(senderHtlcKey[1:])
658+
if err != nil {
659+
return nil, err
660+
}
661+
662+
receiverPubKey, err := schnorr.ParsePubKey(receiverHtlcKey[1:])
677663
if err != nil {
678664
return nil, err
679665
}
680666

681-
senderPubKey, err := btcec.ParsePubKey(
682-
senderHtlcKey[:],
667+
aggregateKey, _, _, err := musig2.AggregateKeys(
668+
[]*btcec.PublicKey{senderPubKey, receiverPubKey}, true,
683669
)
684670
if err != nil {
685671
return nil, err
686672
}
687673

688674
var schnorrSenderKey, schnorrReceiverKey [32]byte
689-
copy(schnorrSenderKey[:], schnorr.SerializePubKey(senderPubKey))
690-
copy(schnorrReceiverKey[:], schnorr.SerializePubKey(receiverPubKey))
675+
copy(schnorrSenderKey[:], senderHtlcKey[1:])
676+
copy(schnorrReceiverKey[:], receiverHtlcKey[1:])
691677

692678
// Create our success path script, we'll use this separately
693679
// to generate the success path leaf.
@@ -717,14 +703,15 @@ func newHTLCScriptV3(cltvExpiry int32, senderHtlcKey,
717703

718704
// Calculate top level taproot key.
719705
taprootKey := txscript.ComputeTaprootOutputKey(
720-
sharedKey, rootHash[:],
706+
aggregateKey.PreTweakedKey, rootHash[:],
721707
)
722708

723709
return &HtlcScriptV3{
724710
TimeoutScript: timeoutPathScript,
725711
SuccessScript: successPathScript,
726-
InternalPubKey: sharedKey,
712+
InternalPubKey: aggregateKey.PreTweakedKey,
727713
TaprootKey: taprootKey,
714+
RootHash: rootHash,
728715
}, nil
729716
}
730717

swap/htlc_test.go

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package swap
33
import (
44
"bytes"
55
"crypto/sha256"
6-
"encoding/hex"
76
"fmt"
87
"testing"
98

@@ -137,7 +136,7 @@ func TestHtlcV2(t *testing.T) {
137136

138137
// Create the htlc.
139138
htlc, err := NewHtlc(
140-
HtlcV2, testCltvExpiry, senderKey, receiverKey, nil, hash,
139+
HtlcV2, testCltvExpiry, senderKey, receiverKey, hash,
141140
HtlcP2WSH, &chaincfg.MainNetParams,
142141
)
143142
require.NoError(t, err)
@@ -286,7 +285,7 @@ func TestHtlcV2(t *testing.T) {
286285
// Create the htlc with the bogus key.
287286
htlc, err = NewHtlc(
288287
HtlcV2, testCltvExpiry,
289-
bogusKey, receiverKey, nil, hash,
288+
bogusKey, receiverKey, hash,
290289
HtlcP2WSH, &chaincfg.MainNetParams,
291290
)
292291
require.NoError(t, err)
@@ -353,17 +352,8 @@ func TestHtlcV3(t *testing.T) {
353352
copy(receiverKey[:], receiverPubKey.SerializeCompressed())
354353
copy(senderKey[:], senderPubKey.SerializeCompressed())
355354

356-
randomSharedKey, err := hex.DecodeString(
357-
"03fcb7d1b502bd59f4dbc6cf503e5c280189e0e6dd2d10c4c14d97ed8611" +
358-
"a99178",
359-
)
360-
require.NoError(t, err)
361-
362-
randomSharedPubKey, err := btcec.ParsePubKey(randomSharedKey)
363-
require.NoError(t, err)
364-
365355
htlc, err := NewHtlc(
366-
HtlcV3, cltvExpiry, senderKey, receiverKey, randomSharedPubKey,
356+
HtlcV3, cltvExpiry, senderKey, receiverKey,
367357
hashedPreimage, HtlcP2TR, &chaincfg.MainNetParams,
368358
)
369359
require.NoError(t, err)
@@ -555,8 +545,7 @@ func TestHtlcV3(t *testing.T) {
555545

556546
htlc, err := NewHtlc(
557547
HtlcV3, cltvExpiry, bogusKeyBytes,
558-
receiverKey, randomSharedPubKey,
559-
hashedPreimage, HtlcP2TR,
548+
receiverKey, hashedPreimage, HtlcP2TR,
560549
&chaincfg.MainNetParams,
561550
)
562551
require.NoError(t, err)

0 commit comments

Comments
 (0)