multi: add simple taproot channel type to order

This commit is contained in:
Oliver Gugger 2023-09-22 17:13:33 +02:00
parent d000a6b7b1
commit 52cdb3d5f9
No known key found for this signature in database
GPG key ID: 8E4256593F177720
11 changed files with 160 additions and 27 deletions

View file

@ -427,6 +427,8 @@ func (c *Client) SubmitOrder(ctx context.Context, o order.Order,
channelType = auctioneerrpc.OrderChannelType_ORDER_CHANNEL_TYPE_PEER_DEPENDENT
case order.ChannelTypeScriptEnforced:
channelType = auctioneerrpc.OrderChannelType_ORDER_CHANNEL_TYPE_SCRIPT_ENFORCED
case order.ChannelTypeSimpleTaproot:
channelType = auctioneerrpc.OrderChannelType_ORDER_CHANNEL_TYPE_SIMPLE_TAPROOT
default:
return fmt.Errorf("unhandled channel type %v", c)
}

View file

@ -151,7 +151,8 @@ func isSupportedBackupVersion(backup *chanbackup.Single) bool {
case chanbackup.TweaklessCommitVersion,
chanbackup.AnchorsCommitVersion,
chanbackup.AnchorsZeroFeeHtlcTxCommitVersion,
chanbackup.ScriptEnforcedLeaseVersion:
chanbackup.ScriptEnforcedLeaseVersion,
chanbackup.SimpleTaprootVersion:
return true
default:

View file

@ -155,9 +155,8 @@ func (s *ChannelAcceptor) acceptChannel(_ context.Context,
}, nil
}
switch *req.CommitmentType {
case lnwallet.CommitmentTypeScriptEnforcedLease:
default:
const expectedType = lnwallet.CommitmentTypeScriptEnforcedLease
if *req.CommitmentType != expectedType {
return &lndclient.AcceptorResponse{
Accept: false,
Error: "expected script enforced channel " +
@ -165,6 +164,22 @@ func (s *ChannelAcceptor) acceptChannel(_ context.Context,
}, nil
}
case order.ChannelTypeSimpleTaproot:
if req.CommitmentType == nil {
return &lndclient.AcceptorResponse{
Accept: false,
Error: "expected explicit channel negotiation",
}, nil
}
if *req.CommitmentType != lnwallet.CommitmentTypeSimpleTaproot {
return &lndclient.AcceptorResponse{
Accept: false,
Error: "expected simple taproot channel " +
"commitment type",
}, nil
}
default:
log.Warnf("Unhandled channel type %v for bid %v",
expectedChanBid.ChannelType, expectedChanBid.Nonce())

View file

@ -24,6 +24,7 @@ const (
channelTypePeerDependent = "legacy"
channelTypeScriptEnforced = "script-enforced"
channelTypeSimpleTaproot = "simple-taproot"
auctionTypeInboundLiquidity = "inbound"
auctionTypeOutboundLiquidity = "outbound"
@ -151,9 +152,9 @@ var sharedFlags = []cli.Flag{
cli.StringFlag{
Name: "channel_type",
Usage: fmt.Sprintf("the type of channel resulting from the "+
"order being matched (%q, %q)",
channelTypePeerDependent,
channelTypeScriptEnforced),
"order being matched (%q, %q, %q)",
channelTypePeerDependent, channelTypeScriptEnforced,
channelTypeSimpleTaproot),
},
cli.StringFlag{
Name: "auction_type",
@ -434,6 +435,9 @@ func parseCommonParams(ctx *cli.Context, blockDuration uint32) (*poolrpc.Order,
case channelTypeScriptEnforced:
params.ChannelType = auctioneerrpc.OrderChannelType_ORDER_CHANNEL_TYPE_SCRIPT_ENFORCED
case channelTypeSimpleTaproot:
params.ChannelType = auctioneerrpc.OrderChannelType_ORDER_CHANNEL_TYPE_SIMPLE_TAPROOT
default:
return nil, fmt.Errorf("unknown channel type %q", channelType)
}

View file

@ -20,6 +20,7 @@ import (
"github.com/lightninglabs/pool/chaninfo"
"github.com/lightninglabs/pool/clientdb"
"github.com/lightninglabs/pool/order"
"github.com/lightninglabs/pool/poolscript"
"github.com/lightninglabs/pool/sidecar"
"github.com/lightningnetwork/lnd/input"
"github.com/lightningnetwork/lnd/keychain"
@ -355,14 +356,19 @@ func (m *Manager) deriveFundingShim(ourOrder order.Order,
}
}
_, fundingOutput, err := input.GenFundingPkScript(
ourMultiSigKey.PubKey.SerializeCompressed(),
commitmentType, musig2 := order.DetermineCommitmentType(
ourOrder.Details(), matchedOrder.Order.Details(),
)
fundingOutput, err := poolscript.FundingOutput(
commitmentType, ourMultiSigKey.PubKey.SerializeCompressed(),
matchedOrder.MultiSigKey[:], int64(chanSize),
)
if err != nil {
return nil, [32]byte{}, err
}
log.Debugf("Funding output pkScript: %x", fundingOutput.PkScript)
// Now that we have the funding script, we'll find the output index
// within the batch execution transaction. We ignore the first
// argument, as earlier during validation, we would've rejected the
@ -378,6 +384,9 @@ func (m *Manager) deriveFundingShim(ourOrder order.Order,
OutputIndex: chanOutputIndex,
}
log.Debugf("Found funding output at index %v of batch TX %v",
chanOutputIndex, batchTxID.String())
// With all the components assembled, we'll now create the chan point
// shim, and register it so we use the proper funding key when we
// receive the marker's incoming funding request.
@ -394,6 +403,7 @@ func (m *Manager) deriveFundingShim(ourOrder order.Order,
RemoteKey: matchedOrder.MultiSigKey[:],
PendingChanId: pendingChanID[:],
ThawHeight: thawHeight,
Musig2: musig2,
}
return &lnrpc.FundingShim{
@ -654,10 +664,10 @@ func (m *Manager) BatchChannelSetup(
if err != nil {
return nil, err
}
chanPointShim := fundingShim.GetChanPointShim()
chanPoint := wire.OutPoint{
Hash: batchTxHash,
Index: fundingShim.GetChanPointShim().ChanPoint.
OutputIndex,
Hash: batchTxHash,
Index: chanPointShim.ChanPoint.OutputIndex,
}
// Some goroutines are already running from previous
@ -689,14 +699,21 @@ func (m *Manager) BatchChannelSetup(
// * also other params to set as well
chanAmt := matchedOrder.UnitsFilled.ToSatoshis()
chanAmt += matchedOrderBid.SelfChanBalance
var commitmentType lnrpc.CommitmentType
switch {
case ourOrder.Details().ChannelType == order.ChannelTypeScriptEnforced:
fallthrough
case matchedOrderBid.Details().ChannelType == order.ChannelTypeScriptEnforced:
commitmentType = lnrpc.CommitmentType_SCRIPT_ENFORCED_LEASE
}
commitmentType, _ := order.DetermineCommitmentType(
ourOrder.Details(),
matchedOrder.Order.Details(),
)
private := matchedOrderBid.UnannouncedChannel
log.Debugf("Opening channel to node=%x, private=%v, "+
"chan_point=%v, chan_amt=%v, commit_type=%v, "+
"musig2=%v, zero_conf=%v, thaw_height=%v",
matchedOrder.NodeKey[:], private, chanPoint,
chanAmt, commitmentType, chanPointShim.Musig2,
matchedOrderBid.ZeroConfChannel,
chanPointShim.ThawHeight)
fundingReq := &lnrpc.OpenChannelRequest{
NodePubkey: matchedOrder.NodeKey[:],
LocalFundingAmount: int64(chanAmt),

View file

@ -15,7 +15,6 @@ import (
"github.com/lightninglabs/pool/auctioneerrpc"
"github.com/lightninglabs/pool/poolscript"
"github.com/lightninglabs/pool/terms"
"github.com/lightningnetwork/lnd/input"
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
)
@ -363,9 +362,13 @@ func ChannelOutput(batchTx *wire.MsgTx, wallet lndclient.WalletKitClient,
}
// Gather the information we expect to find in the batch TX.
commitType, _ := DetermineCommitmentType(
ourOrder.Details(), otherOrder.Order.Details(),
)
expectedOutputSize := selfChanBalance + otherOrder.UnitsFilled.ToSatoshis()
_, expectedOut, err := input.GenFundingPkScript(
ourKey, otherOrder.MultiSigKey[:], int64(expectedOutputSize),
expectedOut, err := poolscript.FundingOutput(
commitType, ourKey, otherOrder.MultiSigKey[:],
int64(expectedOutputSize),
)
if err != nil {
return nil, 0, fmt.Errorf("could not create multisig script: "+

View file

@ -9,6 +9,7 @@ import (
"github.com/lightninglabs/lndclient"
"github.com/lightninglabs/pool/account"
"github.com/lightninglabs/pool/terms"
"github.com/lightningnetwork/lnd/lnrpc"
)
const (
@ -371,3 +372,31 @@ func (v *batchVerifier) validateChannelOutput(batch *Batch, ourOrder Order,
// A compile-time constraint to ensure batchVerifier implements BatchVerifier.
var _ BatchVerifier = (*batchVerifier)(nil)
// DetermineCommitmentType determines the type of channel to open based on our
// order and the one matched to us and also returns whether that channel type
// uses a Musig2 construction or not.
func DetermineCommitmentType(ourOrder,
theirOrder *Kit) (lnrpc.CommitmentType, bool) {
switch {
// Since everyone needs to be on lnd 0.15.5+ because of the chain sync
// issue, we can safely assume that everyone supports the new script
// enforced type. So if one side indicates they want it, we'll use it.
case ourOrder.ChannelType == ChannelTypeScriptEnforced ||
theirOrder.ChannelType == ChannelTypeScriptEnforced:
return lnrpc.CommitmentType_SCRIPT_ENFORCED_LEASE, false
// For Simple Taproot channels, both sides need to activate them, so we
// need to make sure both parties explicitly requested them (which is
// gated by the startup feature check).
case ourOrder.ChannelType == ChannelTypeSimpleTaproot &&
theirOrder.ChannelType == ChannelTypeSimpleTaproot:
return lnrpc.CommitmentType_SIMPLE_TAPROOT, true
default:
return lnrpc.CommitmentType_UNKNOWN_COMMITMENT_TYPE, false
}
}

View file

@ -134,7 +134,7 @@ const (
StateFailed State = 6
)
// String returns a human readable string representation of the order state.
// String returns a human-readable string representation of the order state.
func (s State) String() string {
switch s {
case StateSubmitted:
@ -186,7 +186,7 @@ const (
// OrderMatchPrepare message was received initially.
MatchStatePrepare MatchState = 0
// MatchStatePrepare is the state an order is in after the
// MatchStateAccepted is the state an order is in after the
// OrderMatchPrepare message was processed successfully and the batch
// was accepted.
MatchStateAccepted MatchState = 1
@ -205,7 +205,7 @@ const (
MatchStateFinalized MatchState = 4
)
// String returns a human readable string representation of the match state.
// String returns a human-readable string representation of the match state.
func (s MatchState) String() string {
switch s {
case MatchStatePrepare:
@ -244,6 +244,10 @@ const (
// leased channel in the commitment and HTLC outputs that pay directly
// to the channel initiator.
ChannelTypeScriptEnforced ChannelType = 1
// ChannelTypeSimpleTaproot represents a channel type that uses a
// Pay-To-Taproot funding output.
ChannelTypeSimpleTaproot ChannelType = 2
)
// ChannelAnnouncementConstraints is a numerical type used to denote if the

View file

@ -115,6 +115,9 @@ func ParseRPCOrder(version, leaseDuration uint32,
case auctioneerrpc.OrderChannelType_ORDER_CHANNEL_TYPE_SCRIPT_ENFORCED:
kit.ChannelType = ChannelTypeScriptEnforced
case auctioneerrpc.OrderChannelType_ORDER_CHANNEL_TYPE_SIMPLE_TAPROOT:
kit.ChannelType = ChannelTypeSimpleTaproot
default:
return nil, fmt.Errorf("unhandled channel type %v",
details.ChannelType)
@ -260,6 +263,9 @@ func ParseRPCServerOrder(version uint32, details *auctioneerrpc.ServerOrder,
case auctioneerrpc.OrderChannelType_ORDER_CHANNEL_TYPE_SCRIPT_ENFORCED:
kit.ChannelType = ChannelTypeScriptEnforced
case auctioneerrpc.OrderChannelType_ORDER_CHANNEL_TYPE_SIMPLE_TAPROOT:
kit.ChannelType = ChannelTypeSimpleTaproot
default:
return nil, nodeKey, nil, multiSigKey,
fmt.Errorf("unhandled channel type %v", details.ChannelType)

View file

@ -15,6 +15,7 @@ import (
"github.com/lightninglabs/lndclient"
"github.com/lightningnetwork/lnd/input"
"github.com/lightningnetwork/lnd/keychain"
"github.com/lightningnetwork/lnd/lnrpc"
)
// Version represents the type of Pool account script that is used for either
@ -824,3 +825,44 @@ func IncludesPreviousOutPoint(tx *wire.MsgTx, output wire.OutPoint) bool {
}
return false
}
// FundingOutput returns the channel funding output for the given commitment
// type, funding keys and channel size.
func FundingOutput(commitmentType lnrpc.CommitmentType, ourKey,
theirKey []byte, chanSize int64) (*wire.TxOut, error) {
switch commitmentType {
case lnrpc.CommitmentType_SIMPLE_TAPROOT:
ourPubKey, err := btcec.ParsePubKey(ourKey)
if err != nil {
return nil, err
}
theirPubKey, err := btcec.ParsePubKey(theirKey)
if err != nil {
return nil, err
}
log.Debugf("Creating P2TR funding script for local key %x and "+
"remote key %x", ourKey, theirKey)
_, fundingOutput, err := input.GenTaprootFundingScript(
ourPubKey, theirPubKey, chanSize,
)
if err != nil {
return nil, err
}
return fundingOutput, nil
default:
log.Debugf("Creating P2WSH funding script for local key %x "+
"and remote key %x", ourKey, theirKey)
_, fundingOutput, err := input.GenFundingPkScript(
ourKey, theirKey, chanSize,
)
if err != nil {
return nil, err
}
return fundingOutput, nil
}
}

View file

@ -30,7 +30,6 @@ import (
"github.com/lightninglabs/pool/terms"
"github.com/lightningnetwork/lnd/chanbackup"
lndFunding "github.com/lightningnetwork/lnd/funding"
"github.com/lightningnetwork/lnd/input"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
"github.com/lightningnetwork/lnd/lnwire"
@ -2318,8 +2317,14 @@ func (s *rpcServer) prepareLeasesResponse(ctx context.Context,
ourMultiSigPubKey = t.Recipient.MultiSigPubKey
}
commitType, _ := order.DetermineCommitmentType(
ourOrder.Details(),
match.Order.Details(),
)
chanAmt := match.UnitsFilled.ToSatoshis()
_, chanOutput, err := input.GenFundingPkScript(
chanOutput, err := poolscript.FundingOutput(
commitType,
ourMultiSigPubKey.SerializeCompressed(),
match.MultiSigKey[:], int64(chanAmt),
)
@ -3334,6 +3339,8 @@ func marshallChannelType(
return auctioneerrpc.OrderChannelType_ORDER_CHANNEL_TYPE_PEER_DEPENDENT
case order.ChannelTypeScriptEnforced:
return auctioneerrpc.OrderChannelType_ORDER_CHANNEL_TYPE_SCRIPT_ENFORCED
case order.ChannelTypeSimpleTaproot:
return auctioneerrpc.OrderChannelType_ORDER_CHANNEL_TYPE_SIMPLE_TAPROOT
default:
return auctioneerrpc.OrderChannelType_ORDER_CHANNEL_TYPE_UNKNOWN
}
@ -3366,6 +3373,9 @@ func marshallChannelInfo(chanInfos map[wire.OutPoint]*chaninfo.ChannelInfo) (
case chanbackup.ScriptEnforcedLeaseVersion:
channelType = auctioneerrpc.ChannelType_SCRIPT_ENFORCED_LEASE
case chanbackup.SimpleTaprootVersion:
channelType = auctioneerrpc.ChannelType_SIMPLE_TAPROOT
default:
return nil, fmt.Errorf("unknown channel type: %v",
chanInfo.Version)