mirror of
https://github.com/lightninglabs/loop.git
synced 2026-08-13 12:33:03 +02:00
multi: add the aggregate internal pubkey to the v3 htlc
This commit is contained in:
parent
638973dce2
commit
9610becebd
7 changed files with 50 additions and 87 deletions
|
|
@ -195,7 +195,7 @@ func (s *Client) FetchSwaps() ([]*SwapInfo, error) {
|
|||
htlc, err := swap.NewHtlc(
|
||||
GetHtlcScriptVersion(swp.Contract.ProtocolVersion),
|
||||
swp.Contract.CltvExpiry, swp.Contract.SenderKey,
|
||||
swp.Contract.ReceiverKey, nil, swp.Hash, swap.HtlcP2WSH,
|
||||
swp.Contract.ReceiverKey, swp.Hash, swap.HtlcP2WSH,
|
||||
s.lndServices.ChainParams,
|
||||
)
|
||||
if err != nil {
|
||||
|
|
@ -216,7 +216,7 @@ func (s *Client) FetchSwaps() ([]*SwapInfo, error) {
|
|||
htlcNP2WSH, err := swap.NewHtlc(
|
||||
GetHtlcScriptVersion(swp.Contract.ProtocolVersion),
|
||||
swp.Contract.CltvExpiry, swp.Contract.SenderKey,
|
||||
swp.Contract.ReceiverKey, nil, swp.Hash, swap.HtlcNP2WSH,
|
||||
swp.Contract.ReceiverKey, swp.Hash, swap.HtlcNP2WSH,
|
||||
s.lndServices.ChainParams,
|
||||
)
|
||||
if err != nil {
|
||||
|
|
@ -226,7 +226,7 @@ func (s *Client) FetchSwaps() ([]*SwapInfo, error) {
|
|||
htlcP2WSH, err := swap.NewHtlc(
|
||||
GetHtlcScriptVersion(swp.Contract.ProtocolVersion),
|
||||
swp.Contract.CltvExpiry, swp.Contract.SenderKey,
|
||||
swp.Contract.ReceiverKey, nil, swp.Hash, swap.HtlcP2WSH,
|
||||
swp.Contract.ReceiverKey, swp.Hash, swap.HtlcP2WSH,
|
||||
s.lndServices.ChainParams,
|
||||
)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -284,7 +284,7 @@ func testResume(t *testing.T, confs uint32, expired, preimageRevealed,
|
|||
scriptVersion := GetHtlcScriptVersion(protocolVersion)
|
||||
htlc, err := swap.NewHtlc(
|
||||
scriptVersion, pendingSwap.Contract.CltvExpiry, senderKey,
|
||||
receiverKey, nil, hash, swap.HtlcP2WSH, &chaincfg.TestNet3Params,
|
||||
receiverKey, hash, swap.HtlcP2WSH, &chaincfg.TestNet3Params,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, htlc.PkScript, confIntent.PkScript)
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ func viewOut(swapClient *loop.Client, chainParams *chaincfg.Params) error {
|
|||
s.Contract.CltvExpiry,
|
||||
s.Contract.SenderKey,
|
||||
s.Contract.ReceiverKey,
|
||||
nil, s.Hash, swap.HtlcP2WSH, chainParams,
|
||||
s.Hash, swap.HtlcP2WSH, chainParams,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -106,7 +106,7 @@ func viewIn(swapClient *loop.Client, chainParams *chaincfg.Params) error {
|
|||
s.Contract.CltvExpiry,
|
||||
s.Contract.SenderKey,
|
||||
s.Contract.ReceiverKey,
|
||||
nil, s.Hash, swap.HtlcNP2WSH, chainParams,
|
||||
s.Hash, swap.HtlcNP2WSH, chainParams,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
|||
|
|
@ -399,7 +399,7 @@ func testLoopInResume(t *testing.T, state loopdb.SwapState, expired bool,
|
|||
|
||||
htlc, err := swap.NewHtlc(
|
||||
scriptVersion, contract.CltvExpiry, contract.SenderKey,
|
||||
contract.ReceiverKey, nil, testPreimage.Hash(), swap.HtlcNP2WSH,
|
||||
contract.ReceiverKey, testPreimage.Hash(), swap.HtlcNP2WSH,
|
||||
cfg.lnd.ChainParams,
|
||||
)
|
||||
if err != nil {
|
||||
|
|
|
|||
2
swap.go
2
swap.go
|
|
@ -72,7 +72,7 @@ func (s *swapKit) getHtlc(outputType swap.HtlcOutputType) (*swap.Htlc, error) {
|
|||
return swap.NewHtlc(
|
||||
GetHtlcScriptVersion(s.contract.ProtocolVersion),
|
||||
s.contract.CltvExpiry, s.contract.SenderKey,
|
||||
s.contract.ReceiverKey, nil, s.hash, outputType,
|
||||
s.contract.ReceiverKey, s.hash, outputType,
|
||||
s.swapConfig.lnd.ChainParams,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
91
swap/htlc.go
91
swap/htlc.go
|
|
@ -6,10 +6,12 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
|
||||
btcec "github.com/btcsuite/btcd/btcec/v2"
|
||||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
"github.com/btcsuite/btcd/btcec/v2/schnorr"
|
||||
"github.com/btcsuite/btcd/btcec/v2/schnorr/musig2"
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/txscript"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
secp "github.com/decred/dcrd/dcrec/secp256k1/v4"
|
||||
|
|
@ -106,7 +108,7 @@ var (
|
|||
// script size.
|
||||
QuoteHtlc, _ = NewHtlc(
|
||||
HtlcV2,
|
||||
^int32(0), quoteKey, quoteKey, nil, quoteHash, HtlcP2WSH,
|
||||
^int32(0), quoteKey, quoteKey, quoteHash, HtlcP2WSH,
|
||||
&chaincfg.MainNetParams,
|
||||
)
|
||||
|
||||
|
|
@ -119,17 +121,6 @@ var (
|
|||
// selected for a v1 or v2 script.
|
||||
ErrInvalidOutputSelected = fmt.Errorf("taproot output selected for " +
|
||||
"non taproot htlc")
|
||||
|
||||
// ErrSharedKeyNotNeeded is returned when a shared key is provided for
|
||||
// either the v1 or v2 script. Shared key is only necessary for the v3
|
||||
// script.
|
||||
ErrSharedKeyNotNeeded = fmt.Errorf("shared key not supported for " +
|
||||
"script version")
|
||||
|
||||
// ErrSharedKeyRequired is returned when a script version requires a
|
||||
// shared key.
|
||||
ErrSharedKeyRequired = fmt.Errorf("shared key required for script " +
|
||||
"version")
|
||||
)
|
||||
|
||||
// String returns the string value of HtlcOutputType.
|
||||
|
|
@ -152,9 +143,8 @@ func (h HtlcOutputType) String() string {
|
|||
// NewHtlc returns a new instance. For v3 scripts, an internal pubkey generated
|
||||
// by both participants must be provided.
|
||||
func NewHtlc(version ScriptVersion, cltvExpiry int32,
|
||||
senderKey, receiverKey [33]byte, sharedKey *btcec.PublicKey,
|
||||
hash lntypes.Hash, outputType HtlcOutputType,
|
||||
chainParams *chaincfg.Params) (*Htlc, error) {
|
||||
senderKey, receiverKey [33]byte, hash lntypes.Hash,
|
||||
outputType HtlcOutputType, chainParams *chaincfg.Params) (*Htlc, error) {
|
||||
|
||||
var (
|
||||
err error
|
||||
|
|
@ -163,28 +153,18 @@ func NewHtlc(version ScriptVersion, cltvExpiry int32,
|
|||
|
||||
switch version {
|
||||
case HtlcV1:
|
||||
if sharedKey != nil {
|
||||
return nil, ErrSharedKeyNotNeeded
|
||||
}
|
||||
htlc, err = newHTLCScriptV1(
|
||||
cltvExpiry, senderKey, receiverKey, hash,
|
||||
)
|
||||
|
||||
case HtlcV2:
|
||||
if sharedKey != nil {
|
||||
return nil, ErrSharedKeyNotNeeded
|
||||
}
|
||||
htlc, err = newHTLCScriptV2(
|
||||
cltvExpiry, senderKey, receiverKey, hash,
|
||||
)
|
||||
|
||||
case HtlcV3:
|
||||
if sharedKey == nil {
|
||||
return nil, ErrSharedKeyRequired
|
||||
}
|
||||
htlc, err = newHTLCScriptV3(
|
||||
cltvExpiry, senderKey, receiverKey,
|
||||
sharedKey, hash,
|
||||
cltvExpiry, senderKey, receiverKey, hash,
|
||||
)
|
||||
|
||||
default:
|
||||
|
|
@ -646,49 +626,51 @@ func (h *HtlcScriptV2) lockingConditions(htlcOutputType HtlcOutputType,
|
|||
|
||||
// HtlcScriptV3 encapsulates the htlc v3 script.
|
||||
type HtlcScriptV3 struct {
|
||||
// The final locking script for the timeout path which is available to
|
||||
// the sender after the set blockheight.
|
||||
// TimeoutScript is the final locking script for the timeout path which
|
||||
// is available to the sender after the set blockheight.
|
||||
TimeoutScript []byte
|
||||
|
||||
// The final locking script for the success path in which the receiver
|
||||
// reveals the preimage.
|
||||
// SuccessScript is the final locking script for the success path in
|
||||
// which the receiver reveals the preimage.
|
||||
SuccessScript []byte
|
||||
|
||||
// The public key for the keyspend path which bypasses the above two
|
||||
// locking scripts.
|
||||
// InternalPubKey is the public key for the keyspend path which bypasses
|
||||
// the above two locking scripts.
|
||||
InternalPubKey *btcec.PublicKey
|
||||
|
||||
// The taproot public key which is created with the above 3 inputs.
|
||||
// TaprootKey is the taproot public key which is created with the above
|
||||
// 3 inputs.
|
||||
TaprootKey *btcec.PublicKey
|
||||
|
||||
// RootHash is the root hash of the taptree.
|
||||
RootHash chainhash.Hash
|
||||
}
|
||||
|
||||
// newHTLCScriptV3 constructs a HtlcScipt with the HTLC V3 taproot script.
|
||||
func newHTLCScriptV3(cltvExpiry int32, senderHtlcKey,
|
||||
receiverHtlcKey [33]byte, sharedKey *btcec.PublicKey,
|
||||
func newHTLCScriptV3(cltvExpiry int32, senderHtlcKey, receiverHtlcKey [33]byte,
|
||||
swapHash lntypes.Hash) (*HtlcScriptV3, error) {
|
||||
|
||||
receiverPubKey, err := btcec.ParsePubKey(
|
||||
receiverHtlcKey[:],
|
||||
)
|
||||
senderPubKey, err := schnorr.ParsePubKey(senderHtlcKey[1:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
senderPubKey, err := btcec.ParsePubKey(
|
||||
senderHtlcKey[:],
|
||||
)
|
||||
receiverPubKey, err := schnorr.ParsePubKey(receiverHtlcKey[1:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var schnorrSenderKey, schnorrReceiverKey [32]byte
|
||||
copy(schnorrSenderKey[:], schnorr.SerializePubKey(senderPubKey))
|
||||
copy(schnorrReceiverKey[:], schnorr.SerializePubKey(receiverPubKey))
|
||||
aggregateKey, _, _, err := musig2.AggregateKeys(
|
||||
[]*btcec.PublicKey{senderPubKey, receiverPubKey}, true,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Create our success path script, we'll use this separately
|
||||
// to generate the success path leaf.
|
||||
successPathScript, err := GenSuccessPathScript(
|
||||
schnorrReceiverKey, swapHash,
|
||||
receiverPubKey, swapHash,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -697,7 +679,7 @@ func newHTLCScriptV3(cltvExpiry int32, senderHtlcKey,
|
|||
// Create our timeout path leaf, we'll use this separately
|
||||
// to generate the timeout path leaf.
|
||||
timeoutPathScript, err := GenTimeoutPathScript(
|
||||
schnorrSenderKey, int64(cltvExpiry),
|
||||
senderPubKey, int64(cltvExpiry),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -713,14 +695,15 @@ func newHTLCScriptV3(cltvExpiry int32, senderHtlcKey,
|
|||
|
||||
// Calculate top level taproot key.
|
||||
taprootKey := txscript.ComputeTaprootOutputKey(
|
||||
sharedKey, rootHash[:],
|
||||
aggregateKey.PreTweakedKey, rootHash[:],
|
||||
)
|
||||
|
||||
return &HtlcScriptV3{
|
||||
TimeoutScript: timeoutPathScript,
|
||||
SuccessScript: successPathScript,
|
||||
InternalPubKey: sharedKey,
|
||||
InternalPubKey: aggregateKey.PreTweakedKey,
|
||||
TaprootKey: taprootKey,
|
||||
RootHash: rootHash,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
@ -728,11 +711,11 @@ func newHTLCScriptV3(cltvExpiry int32, senderHtlcKey,
|
|||
// Largest possible bytesize of the script is 32 + 1 + 2 + 1 = 36.
|
||||
//
|
||||
// <senderHtlcKey> OP_CHECKSIGVERIFY <cltvExpiry> OP_CHECKLOCKTIMEVERIFY
|
||||
func GenTimeoutPathScript(
|
||||
senderHtlcKey [32]byte, cltvExpiry int64) ([]byte, error) {
|
||||
func GenTimeoutPathScript(senderHtlcKey *btcec.PublicKey, cltvExpiry int64) (
|
||||
[]byte, error) {
|
||||
|
||||
builder := txscript.NewScriptBuilder()
|
||||
builder.AddData(senderHtlcKey[:])
|
||||
builder.AddData(schnorr.SerializePubKey(senderHtlcKey))
|
||||
builder.AddOp(txscript.OP_CHECKSIGVERIFY)
|
||||
builder.AddInt64(cltvExpiry)
|
||||
builder.AddOp(txscript.OP_CHECKLOCKTIMEVERIFY)
|
||||
|
|
@ -746,12 +729,12 @@ func GenTimeoutPathScript(
|
|||
// OP_SIZE 32 OP_EQUALVERIFY
|
||||
// OP_HASH160 <ripemd160h(swapHash)> OP_EQUALVERIFY
|
||||
// 1 OP_CHECKSEQUENCEVERIFY
|
||||
func GenSuccessPathScript(receiverHtlcKey [32]byte,
|
||||
func GenSuccessPathScript(receiverHtlcKey *btcec.PublicKey,
|
||||
swapHash lntypes.Hash) ([]byte, error) {
|
||||
|
||||
builder := txscript.NewScriptBuilder()
|
||||
|
||||
builder.AddData(receiverHtlcKey[:])
|
||||
builder.AddData(schnorr.SerializePubKey(receiverHtlcKey))
|
||||
builder.AddOp(txscript.OP_CHECKSIGVERIFY)
|
||||
builder.AddOp(txscript.OP_SIZE)
|
||||
builder.AddInt64(32)
|
||||
|
|
|
|||
|
|
@ -3,12 +3,10 @@ package swap
|
|||
import (
|
||||
"bytes"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
"github.com/btcsuite/btcd/btcec/v2/schnorr"
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
|
|
@ -137,7 +135,7 @@ func TestHtlcV2(t *testing.T) {
|
|||
|
||||
// Create the htlc.
|
||||
htlc, err := NewHtlc(
|
||||
HtlcV2, testCltvExpiry, senderKey, receiverKey, nil, hash,
|
||||
HtlcV2, testCltvExpiry, senderKey, receiverKey, hash,
|
||||
HtlcP2WSH, &chaincfg.MainNetParams,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
|
@ -285,7 +283,7 @@ func TestHtlcV2(t *testing.T) {
|
|||
// Create the htlc with the bogus key.
|
||||
htlc, err = NewHtlc(
|
||||
HtlcV2, testCltvExpiry,
|
||||
bogusKey, receiverKey, nil, hash,
|
||||
bogusKey, receiverKey, hash,
|
||||
HtlcP2WSH, &chaincfg.MainNetParams,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
|
@ -352,17 +350,8 @@ func TestHtlcV3(t *testing.T) {
|
|||
copy(receiverKey[:], receiverPubKey.SerializeCompressed())
|
||||
copy(senderKey[:], senderPubKey.SerializeCompressed())
|
||||
|
||||
randomSharedKey, err := hex.DecodeString(
|
||||
"03fcb7d1b502bd59f4dbc6cf503e5c280189e0e6dd2d10c4c14d97ed8611" +
|
||||
"a99178",
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
randomSharedPubKey, err := btcec.ParsePubKey(randomSharedKey)
|
||||
require.NoError(t, err)
|
||||
|
||||
htlc, err := NewHtlc(
|
||||
HtlcV3, cltvExpiry, senderKey, receiverKey, randomSharedPubKey,
|
||||
HtlcV3, cltvExpiry, senderKey, receiverKey,
|
||||
hashedPreimage, HtlcP2TR, &chaincfg.MainNetParams,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
|
@ -544,18 +533,9 @@ func TestHtlcV3(t *testing.T) {
|
|||
bogusKey.SerializeCompressed(),
|
||||
)
|
||||
|
||||
var shnorrSenderKey [32]byte
|
||||
copy(
|
||||
shnorrSenderKey[:],
|
||||
schnorr.SerializePubKey(
|
||||
senderPubKey,
|
||||
),
|
||||
)
|
||||
|
||||
htlc, err := NewHtlc(
|
||||
HtlcV3, cltvExpiry, bogusKeyBytes,
|
||||
receiverKey, randomSharedPubKey,
|
||||
hashedPreimage, HtlcP2TR,
|
||||
receiverKey, hashedPreimage, HtlcP2TR,
|
||||
&chaincfg.MainNetParams,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
|
@ -576,7 +556,7 @@ func TestHtlcV3(t *testing.T) {
|
|||
)
|
||||
|
||||
timeoutScript, err := GenTimeoutPathScript(
|
||||
shnorrSenderKey, int64(cltvExpiry),
|
||||
senderPubKey, int64(cltvExpiry),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue