Skip to content

Commit

Permalink
Merge pull request #547 from bhandras/musig-keyreveal
Browse files Browse the repository at this point in the history
loop: Loop In MuSig2 support
  • Loading branch information
bhandras authored Mar 23, 2023
2 parents dbf6fe0 + cd91f90 commit 7f19c43
Show file tree
Hide file tree
Showing 16 changed files with 1,071 additions and 570 deletions.
40 changes: 13 additions & 27 deletions client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import (
"github.com/lightninglabs/loop/loopdb"
"github.com/lightninglabs/loop/swap"
"github.com/lightninglabs/loop/test"
"github.com/lightningnetwork/lnd/input"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -240,8 +239,12 @@ func testLoopOutResume(t *testing.T, confs uint32, expired, preimageRevealed,
Preimage: preimage,
AmountRequested: amt,
CltvExpiry: 744,
ReceiverKey: receiverKey,
SenderKey: senderKey,
HtlcKeys: loopdb.HtlcKeys{
SenderScriptKey: senderKey,
SenderInternalPubKey: senderKey,
ReceiverScriptKey: receiverKey,
ReceiverInternalPubKey: receiverKey,
},
MaxSwapFee: 60000,
MaxMinerFee: 50000,
ProtocolVersion: protocolVersion,
Expand Down Expand Up @@ -273,30 +276,13 @@ func testLoopOutResume(t *testing.T, confs uint32, expired, preimageRevealed,
// Expect client to register for our expected number of confirmations.
confIntent := ctx.AssertRegisterConf(preimageRevealed, int32(confs))

// Assert that the loopout htlc equals to the expected one.
scriptVersion := GetHtlcScriptVersion(protocolVersion)
var htlc *swap.Htlc

switch scriptVersion {
case swap.HtlcV2:
htlc, err = swap.NewHtlcV2(
pendingSwap.Contract.CltvExpiry, senderKey,
receiverKey, hash, &chaincfg.TestNet3Params,
)

case swap.HtlcV3:
htlc, err = swap.NewHtlcV3(
input.MuSig2Version040,
pendingSwap.Contract.CltvExpiry, senderKey,
receiverKey, senderKey, receiverKey, hash,
&chaincfg.TestNet3Params,
)

default:
t.Fatalf(swap.ErrInvalidScriptVersion.Error())
}

htlc, err := GetHtlc(
hash, &pendingSwap.Contract.SwapContract,
&chaincfg.TestNet3Params,
)
require.NoError(t, err)

// Assert that the loopout htlc equals to the expected one.
require.Equal(t, htlc.PkScript, confIntent.PkScript)

signalSwapPaymentResult(nil)
Expand All @@ -315,7 +301,7 @@ func testLoopOutResume(t *testing.T, confs uint32, expired, preimageRevealed,
func(r error) {},
func(r error) {},
preimageRevealed,
confIntent, scriptVersion,
confIntent, GetHtlcScriptVersion(protocolVersion),
)
}

Expand Down
39 changes: 27 additions & 12 deletions loopdb/loop.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,31 @@ import (
"github.com/lightningnetwork/lnd/lntypes"
)

// HtlcKeys is a holder of all keys used when constructing the swap HTLC. Since
// it's used for both loop in and loop out swaps it may hold partial information
// about the sender or receiver depending on the swap type.
type HtlcKeys struct {
// SenderScriptKey is the sender's public key that is used in the HTLC,
// specifically when constructing the script spend scripts.
SenderScriptKey [33]byte

// SenderInternalPubKey is the sender's internal pubkey that is used in
// taproot HTLCs as part of the aggregate internal key.
SenderInternalPubKey [33]byte

// ReceiverScriptKey is the receiver's public key that is used in the
// HTLC, specifically when constructing the script spend scripts.
ReceiverScriptKey [33]byte

// ReceiverInternalPubKey is the sender's internal pubkey that is used
// in taproot HTLCs as part of the aggregate internal key.
ReceiverInternalPubKey [33]byte

// ClientScriptKeyLocator is the client's key locator for the key used
// in the HTLC script spend scripts.
ClientScriptKeyLocator keychain.KeyLocator
}

// SwapContract contains the base data that is serialized to persistent storage
// for pending swaps.
type SwapContract struct {
Expand All @@ -19,18 +44,8 @@ type SwapContract struct {
// AmountRequested is the total amount of the swap.
AmountRequested btcutil.Amount

// SenderKey is the key of the sender that will be used in the on-chain
// HTLC.
SenderKey [33]byte

// ReceiverKey is the of the receiver that will be used in the on-chain
// HTLC.
ReceiverKey [33]byte

// ClientKeyLocator is the key locator (family and index) for the client
// key. It is for the receiver key if this is a loop out contract, or
// the sender key if this is a loop in contract.
ClientKeyLocator keychain.KeyLocator
// HtlcKeys holds all keys used in the swap HTLC construction.
HtlcKeys HtlcKeys

// CltvExpiry is the total absolute CLTV expiry of the swap.
CltvExpiry int32
Expand Down
8 changes: 4 additions & 4 deletions loopdb/loopin.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,15 @@ func serializeLoopInContract(swap *LoopInContract) (
return nil, err
}

n, err := b.Write(swap.SenderKey[:])
n, err := b.Write(swap.HtlcKeys.SenderScriptKey[:])
if err != nil {
return nil, err
}
if n != keyLength {
return nil, fmt.Errorf("sender key has invalid length")
}

n, err = b.Write(swap.ReceiverKey[:])
n, err = b.Write(swap.HtlcKeys.ReceiverScriptKey[:])
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -161,15 +161,15 @@ func deserializeLoopInContract(value []byte) (*LoopInContract, error) {
return nil, err
}

n, err := r.Read(contract.SenderKey[:])
n, err := r.Read(contract.HtlcKeys.SenderScriptKey[:])
if err != nil {
return nil, err
}
if n != keyLength {
return nil, fmt.Errorf("sender key has invalid length")
}

n, err = r.Read(contract.ReceiverKey[:])
n, err = r.Read(contract.HtlcKeys.ReceiverScriptKey[:])
if err != nil {
return nil, err
}
Expand Down
8 changes: 4 additions & 4 deletions loopdb/loopout.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,15 +134,15 @@ func deserializeLoopOutContract(value []byte, chainParams *chaincfg.Params) (
return nil, err
}

n, err := r.Read(contract.SenderKey[:])
n, err := r.Read(contract.HtlcKeys.SenderScriptKey[:])
if err != nil {
return nil, err
}
if n != keyLength {
return nil, fmt.Errorf("sender key has invalid length")
}

n, err = r.Read(contract.ReceiverKey[:])
n, err = r.Read(contract.HtlcKeys.ReceiverScriptKey[:])
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -229,15 +229,15 @@ func serializeLoopOutContract(swap *LoopOutContract) (
return nil, err
}

n, err := b.Write(swap.SenderKey[:])
n, err := b.Write(swap.HtlcKeys.SenderScriptKey[:])
if err != nil {
return nil, err
}
if n != keyLength {
return nil, fmt.Errorf("sender key has invalid length")
}

n, err = b.Write(swap.ReceiverKey[:])
n, err = b.Write(swap.HtlcKeys.ReceiverScriptKey[:])
if err != nil {
return nil, err
}
Expand Down
8 changes: 7 additions & 1 deletion loopdb/protocol_version.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ const (
// HTLC v3 (P2TR) script for swaps.
ProtocolVersionHtlcV3 = 10

// ProtocolVersionMuSig2 will enable MuSig2 signature scheme for loops.
ProtocolVersionMuSig2 ProtocolVersion = 11

// ProtocolVersionUnrecorded is set for swaps were created before we
// started saving protocol version with swaps.
ProtocolVersionUnrecorded ProtocolVersion = math.MaxUint32
Expand All @@ -65,7 +68,7 @@ const (

// experimentalRPCProtocolVersion defines the RPC protocol version that
// includes all currently experimentally released features.
experimentalRPCProtocolVersion = looprpc.ProtocolVersion_HTLC_V3
experimentalRPCProtocolVersion = looprpc.ProtocolVersion_MUSIG2
)

var (
Expand Down Expand Up @@ -141,6 +144,9 @@ func (p ProtocolVersion) String() string {
case ProtocolVersionHtlcV3:
return "HTLC V3"

case ProtocolVersionMuSig2:
return "MuSig2"

default:
return "Unknown"
}
Expand Down
Loading

0 comments on commit 7f19c43

Please sign in to comment.