mirror of
https://github.com/lightninglabs/loop.git
synced 2026-08-13 12:33:03 +02:00
loopin: generate and send internal key for MuSig2 swaps
This commit changes how we create loopin swaps if the client activates the experimental MuSig2 features. When creating a new loopin swap the client will create (and store) a new key that will be used as the sender's internal key when constructing the HTLC. The client will send the public part to the server and will also receive (and store) the server's (receiver) internal public key.
This commit is contained in:
parent
da4bcbea10
commit
90ae922adf
3 changed files with 76 additions and 21 deletions
45
loopin.go
45
loopin.go
|
|
@ -9,6 +9,7 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/mempool"
|
||||
|
|
@ -19,6 +20,7 @@ import (
|
|||
"github.com/lightninglabs/loop/swap"
|
||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||
invpkg "github.com/lightningnetwork/lnd/invoices"
|
||||
"github.com/lightningnetwork/lnd/keychain"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
|
|
@ -189,6 +191,23 @@ func newLoopInSwap(globalCtx context.Context, cfg *swapConfig,
|
|||
return nil, err
|
||||
}
|
||||
|
||||
// Default the HTLC internal key to our sender key.
|
||||
senderInternalPubKey := senderKey
|
||||
|
||||
// If this is a MuSig2 swap then we'll generate a brand new key pair
|
||||
// and will use that as the internal key for the HTLC.
|
||||
if loopdb.CurrentProtocolVersion() >= loopdb.ProtocolVersionMuSig2 {
|
||||
secret, err := sharedSecretFromHash(
|
||||
globalCtx, cfg.lnd.Signer, swapHash,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, pubKey := btcec.PrivKeyFromBytes(secret[:])
|
||||
copy(senderInternalPubKey[:], pubKey.SerializeCompressed())
|
||||
}
|
||||
|
||||
// Create a cancellable context that is used for monitoring the probe.
|
||||
probeWaitCtx, probeWaitCancel := context.WithCancel(globalCtx)
|
||||
|
||||
|
|
@ -204,8 +223,8 @@ func newLoopInSwap(globalCtx context.Context, cfg *swapConfig,
|
|||
// htlc.
|
||||
log.Infof("Initiating swap request at height %v", currentHeight)
|
||||
swapResp, err := cfg.server.NewLoopInSwap(globalCtx, swapHash,
|
||||
request.Amount, senderKey, swapInvoice, probeInvoice,
|
||||
request.LastHop, request.Initiator,
|
||||
request.Amount, senderKey, senderInternalPubKey, swapInvoice,
|
||||
probeInvoice, request.LastHop, request.Initiator,
|
||||
)
|
||||
probeWaitCancel()
|
||||
if err != nil {
|
||||
|
|
@ -254,6 +273,13 @@ func newLoopInSwap(globalCtx context.Context, cfg *swapConfig,
|
|||
},
|
||||
}
|
||||
|
||||
// For MuSig2 swaps we store the proper internal keys that we generated
|
||||
// and received from the server.
|
||||
if loopdb.CurrentProtocolVersion() >= loopdb.ProtocolVersionMuSig2 {
|
||||
contract.HtlcKeys.SenderInternalPubKey = senderInternalPubKey
|
||||
contract.HtlcKeys.ReceiverInternalPubKey = swapResp.receiverInternalKey
|
||||
}
|
||||
|
||||
swapKit := newSwapKit(
|
||||
swapHash, swap.TypeIn,
|
||||
cfg, &contract.SwapContract,
|
||||
|
|
@ -1031,3 +1057,18 @@ func (s *loopInSwap) setState(state loopdb.SwapState) {
|
|||
s.lastUpdateTime = time.Now()
|
||||
s.state = state
|
||||
}
|
||||
|
||||
// sharedSecretFromHash derives the shared secret from the swap hash using the
|
||||
// swap.KeyFamily family and zero as index.
|
||||
func sharedSecretFromHash(ctx context.Context, signer lndclient.SignerClient,
|
||||
hash lntypes.Hash) ([32]byte, error) {
|
||||
|
||||
_, hashPubKey := btcec.PrivKeyFromBytes(hash[:])
|
||||
|
||||
return signer.DeriveSharedKey(
|
||||
ctx, hashPubKey, &keychain.KeyLocator{
|
||||
Family: keychain.KeyFamily(swap.KeyFamily),
|
||||
Index: 0,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -151,17 +151,22 @@ func getInvoice(hash lntypes.Hash, amt btcutil.Amount, memo string) (string, err
|
|||
}
|
||||
|
||||
func (s *serverMock) NewLoopInSwap(_ context.Context, swapHash lntypes.Hash,
|
||||
amount btcutil.Amount, _ [33]byte, swapInvoice, _ string,
|
||||
amount btcutil.Amount, _, _ [33]byte, swapInvoice, _ string,
|
||||
_ *route.Vertex, _ string) (*newLoopInResponse, error) {
|
||||
|
||||
_, receiverKey := test.CreateKey(101)
|
||||
_, receiverInternalKey := test.CreateKey(102)
|
||||
|
||||
if amount != s.expectedSwapAmt {
|
||||
return nil, errors.New("unexpected test swap amount")
|
||||
}
|
||||
|
||||
var receiverKeyArray [33]byte
|
||||
var receiverKeyArray, receiverInternalKeyArray [33]byte
|
||||
copy(receiverKeyArray[:], receiverKey.SerializeCompressed())
|
||||
copy(
|
||||
receiverInternalKeyArray[:],
|
||||
receiverInternalKey.SerializeCompressed(),
|
||||
)
|
||||
|
||||
s.swapInvoice = swapInvoice
|
||||
s.swapHash = swapHash
|
||||
|
|
@ -175,8 +180,9 @@ func (s *serverMock) NewLoopInSwap(_ context.Context, swapHash lntypes.Hash,
|
|||
<-s.lnd.FailInvoiceChannel
|
||||
|
||||
resp := &newLoopInResponse{
|
||||
expiry: s.height + testChargeOnChainCltvDelta,
|
||||
receiverKey: receiverKeyArray,
|
||||
expiry: s.height + testChargeOnChainCltvDelta,
|
||||
receiverKey: receiverKeyArray,
|
||||
receiverInternalKey: receiverInternalKeyArray,
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
|
|
|
|||
|
|
@ -94,10 +94,10 @@ type swapServerClient interface {
|
|||
preimage lntypes.Preimage) error
|
||||
|
||||
NewLoopInSwap(ctx context.Context,
|
||||
swapHash lntypes.Hash, amount btcutil.Amount,
|
||||
senderKey [33]byte, swapInvoice, probeInvoice string,
|
||||
lastHop *route.Vertex, initiator string) (*newLoopInResponse,
|
||||
error)
|
||||
swapHash lntypes.Hash, amount btcutil.Amount, senderScriptKey,
|
||||
senderInternalKey [33]byte, swapInvoice, probeInvoice string,
|
||||
lastHop *route.Vertex, initiator string) (
|
||||
*newLoopInResponse, error)
|
||||
|
||||
// SubscribeLoopOutUpdates subscribes to loop out server state.
|
||||
SubscribeLoopOutUpdates(ctx context.Context,
|
||||
|
|
@ -419,9 +419,9 @@ func (s *grpcSwapServerClient) PushLoopOutPreimage(ctx context.Context,
|
|||
}
|
||||
|
||||
func (s *grpcSwapServerClient) NewLoopInSwap(ctx context.Context,
|
||||
swapHash lntypes.Hash, amount btcutil.Amount, senderKey [33]byte,
|
||||
swapInvoice, probeInvoice string, lastHop *route.Vertex,
|
||||
initiator string) (*newLoopInResponse, error) {
|
||||
swapHash lntypes.Hash, amount btcutil.Amount, senderScriptKey,
|
||||
senderInternalKey [33]byte, swapInvoice, probeInvoice string,
|
||||
lastHop *route.Vertex, initiator string) (*newLoopInResponse, error) {
|
||||
|
||||
rpcCtx, rpcCancel := context.WithTimeout(ctx, globalCallTimeout)
|
||||
defer rpcCancel()
|
||||
|
|
@ -429,7 +429,7 @@ func (s *grpcSwapServerClient) NewLoopInSwap(ctx context.Context,
|
|||
req := &looprpc.ServerLoopInRequest{
|
||||
SwapHash: swapHash[:],
|
||||
Amt: uint64(amount),
|
||||
SenderKey: senderKey[:],
|
||||
SenderKey: senderScriptKey[:],
|
||||
SwapInvoice: swapInvoice,
|
||||
ProtocolVersion: loopdb.CurrentRPCProtocolVersion(),
|
||||
ProbeInvoice: probeInvoice,
|
||||
|
|
@ -439,13 +439,19 @@ func (s *grpcSwapServerClient) NewLoopInSwap(ctx context.Context,
|
|||
req.LastHop = lastHop[:]
|
||||
}
|
||||
|
||||
// Set the client's internal key if this is a MuSig2 swap.
|
||||
if loopdb.CurrentProtocolVersion() >= loopdb.ProtocolVersionMuSig2 {
|
||||
req.SenderInternalPubkey = senderInternalKey[:]
|
||||
}
|
||||
|
||||
swapResp, err := s.server.NewLoopInSwap(rpcCtx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var receiverKey [33]byte
|
||||
var receiverKey, receiverInternalKey [33]byte
|
||||
copy(receiverKey[:], swapResp.ReceiverKey)
|
||||
copy(receiverInternalKey[:], swapResp.ReceiverInternalPubkey)
|
||||
|
||||
// Validate receiver key.
|
||||
_, err = btcec.ParsePubKey(receiverKey[:])
|
||||
|
|
@ -454,9 +460,10 @@ func (s *grpcSwapServerClient) NewLoopInSwap(ctx context.Context,
|
|||
}
|
||||
|
||||
return &newLoopInResponse{
|
||||
receiverKey: receiverKey,
|
||||
expiry: swapResp.Expiry,
|
||||
serverMessage: swapResp.ServerMessage,
|
||||
receiverKey: receiverKey,
|
||||
receiverInternalKey: receiverInternalKey,
|
||||
expiry: swapResp.Expiry,
|
||||
serverMessage: swapResp.ServerMessage,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
@ -873,7 +880,8 @@ type newLoopOutResponse struct {
|
|||
}
|
||||
|
||||
type newLoopInResponse struct {
|
||||
receiverKey [33]byte
|
||||
expiry int32
|
||||
serverMessage string
|
||||
receiverKey [33]byte
|
||||
receiverInternalKey [33]byte
|
||||
expiry int32
|
||||
serverMessage string
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue