@@ -112,9 +112,30 @@ var (
112112 // value: concatenation of uint32 values [family, index].
113113 keyLocatorKey = []byte ("keylocator" )
114114
115+ // senderInternalPubKeyKey is the key that stores the sender's internal
116+ // public key which used when constructing the swap HTLC.
117+ //
118+ // path: loopInBucket/loopOutBucket -> swapBucket[hash]
119+ // -> senderInternalPubKeyKey
120+ // value: serialized public key.
121+ senderInternalPubKeyKey = []byte ("sender-internal-pubkey" )
122+
123+ // receiverInternalPubKeyKey is the key that stores the receiver's
124+ // internal public key which is used when constructing the swap HTLC.
125+ //
126+ // path: loopInBucket/loopOutBucket -> swapBucket[hash]
127+ // -> receiverInternalPubKeyKey
128+ // value: serialized public key.
129+ receiverInternalPubKeyKey = []byte ("receiver-internal-pubkey" )
130+
115131 byteOrder = binary .BigEndian
116132
133+ // keyLength is the length of a serialized public key.
117134 keyLength = 33
135+
136+ // errInvalidKey is returned when a serialized key is not the expected
137+ // length.
138+ errInvalidKey = fmt .Errorf ("invalid serialized key" )
118139)
119140
120141const (
@@ -233,6 +254,95 @@ func NewBoltSwapStore(dbPath string, chainParams *chaincfg.Params) (
233254 }, nil
234255}
235256
257+ // marshalHtlcKeys marshals the HTLC keys of the swap contract into the swap
258+ // bucket.
259+ func marshalHtlcKeys (swapBucket * bbolt.Bucket , contract * SwapContract ) error {
260+ var err error
261+
262+ // Store the key locator for swaps that use taproot HTLCs.
263+ if contract .ProtocolVersion >= ProtocolVersionHtlcV3 {
264+ keyLocator , err := MarshalKeyLocator (
265+ contract .HtlcKeys .ClientScriptKeyLocator ,
266+ )
267+ if err != nil {
268+ return err
269+ }
270+
271+ err = swapBucket .Put (keyLocatorKey , keyLocator )
272+ if err != nil {
273+ return err
274+ }
275+ }
276+
277+ // Store the internal keys for MuSig2 swaps.
278+ if contract .ProtocolVersion >= ProtocolVersionMuSig2 {
279+ // Internal pubkeys are always filled.
280+ err = swapBucket .Put (
281+ senderInternalPubKeyKey ,
282+ contract .HtlcKeys .SenderInternalPubKey [:],
283+ )
284+ if err != nil {
285+ return err
286+ }
287+
288+ err = swapBucket .Put (
289+ receiverInternalPubKeyKey ,
290+ contract .HtlcKeys .ReceiverInternalPubKey [:],
291+ )
292+ if err != nil {
293+ return err
294+ }
295+ }
296+
297+ return nil
298+ }
299+
300+ // unmarshalHtlcKeys deserializes the htlc keys from the swap bucket.
301+ func unmarshalHtlcKeys (swapBucket * bbolt.Bucket , contract * SwapContract ) error {
302+ var err error
303+
304+ // HTLC V3 contracts have the client script key locator stored.
305+ if contract .ProtocolVersion >= ProtocolVersionHtlcV3 &&
306+ ProtocolVersionUnrecorded > contract .ProtocolVersion {
307+
308+ contract .HtlcKeys .ClientScriptKeyLocator , err =
309+ UnmarshalKeyLocator (
310+ swapBucket .Get (keyLocatorKey ),
311+ )
312+ if err != nil {
313+ return err
314+ }
315+
316+ // Default the internal scriptkeys to the sender and receiver
317+ // keys.
318+ contract .HtlcKeys .SenderInternalPubKey =
319+ contract .HtlcKeys .SenderScriptKey
320+ contract .HtlcKeys .ReceiverInternalPubKey =
321+ contract .HtlcKeys .ReceiverScriptKey
322+ }
323+
324+ // MuSig2 contracts have the internal keys stored too.
325+ if contract .ProtocolVersion >= ProtocolVersionMuSig2 &&
326+ ProtocolVersionUnrecorded > contract .ProtocolVersion {
327+
328+ // The pubkeys used for the joint HTLC internal key are always
329+ // present.
330+ key := swapBucket .Get (senderInternalPubKeyKey )
331+ if len (key ) != keyLength {
332+ return errInvalidKey
333+ }
334+ copy (contract .HtlcKeys .SenderInternalPubKey [:], key )
335+
336+ key = swapBucket .Get (receiverInternalPubKeyKey )
337+ if len (key ) != keyLength {
338+ return errInvalidKey
339+ }
340+ copy (contract .HtlcKeys .ReceiverInternalPubKey [:], key )
341+ }
342+
343+ return nil
344+ }
345+
236346// FetchLoopOutSwaps returns all loop out swaps currently in the store.
237347//
238348// NOTE: Part of the loopdb.SwapStore interface.
@@ -435,19 +545,10 @@ func (s *boltSwapStore) CreateLoopOut(hash lntypes.Hash,
435545 return err
436546 }
437547
438- // Store the key locator for swaps with taproot htlc.
439- if swap .ProtocolVersion >= ProtocolVersionHtlcV3 {
440- keyLocator , err := MarshalKeyLocator (
441- swap .ClientKeyLocator ,
442- )
443- if err != nil {
444- return err
445- }
446-
447- err = swapBucket .Put (keyLocatorKey , keyLocator )
448- if err != nil {
449- return err
450- }
548+ // Store the htlc keys and server key locator.
549+ err = marshalHtlcKeys (swapBucket , & swap .SwapContract )
550+ if err != nil {
551+ return err
451552 }
452553
453554 // Finally, we'll create an empty updates bucket for this swap
@@ -501,19 +602,10 @@ func (s *boltSwapStore) CreateLoopIn(hash lntypes.Hash,
501602 return err
502603 }
503604
504- // Store the key locator for swaps with taproot htlc.
505- if swap .ProtocolVersion >= ProtocolVersionHtlcV3 {
506- keyLocator , err := MarshalKeyLocator (
507- swap .ClientKeyLocator ,
508- )
509- if err != nil {
510- return err
511- }
512-
513- err = swapBucket .Put (keyLocatorKey , keyLocator )
514- if err != nil {
515- return err
516- }
605+ // Store the htlc keys and server key locator.
606+ err = marshalHtlcKeys (swapBucket , & swap .SwapContract )
607+ if err != nil {
608+ return err
517609 }
518610
519611 // Finally, we'll create an empty updates bucket for this swap
@@ -788,14 +880,12 @@ func (s *boltSwapStore) fetchLoopOutSwap(rootBucket *bbolt.Bucket,
788880 return nil , err
789881 }
790882
791- // Try to unmarshal the key locator.
792- if contract .ProtocolVersion >= ProtocolVersionHtlcV3 {
793- contract .ClientKeyLocator , err = UnmarshalKeyLocator (
794- swapBucket .Get (keyLocatorKey ),
795- )
796- if err != nil {
797- return nil , err
798- }
883+ // Unmarshal HTLC keys if the contract is recent.
884+ err = unmarshalHtlcKeys (
885+ swapBucket , & contract .SwapContract ,
886+ )
887+ if err != nil {
888+ return nil , err
799889 }
800890
801891 loop := LoopOut {
@@ -865,14 +955,12 @@ func (s *boltSwapStore) fetchLoopInSwap(rootBucket *bbolt.Bucket,
865955 return nil , err
866956 }
867957
868- // Try to unmarshal the key locator.
869- if contract .ProtocolVersion >= ProtocolVersionHtlcV3 {
870- contract .ClientKeyLocator , err = UnmarshalKeyLocator (
871- swapBucket .Get (keyLocatorKey ),
872- )
873- if err != nil {
874- return nil , err
875- }
958+ // Unmarshal HTLC keys if the contract is recent.
959+ err = unmarshalHtlcKeys (
960+ swapBucket , & contract .SwapContract ,
961+ )
962+ if err != nil {
963+ return nil , err
876964 }
877965
878966 loop := LoopIn {
0 commit comments