From 2d3aef1725ab4f3da5ad088b0135dee9c2760456 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Tue, 31 Jan 2023 20:41:23 +0100 Subject: [PATCH] order+server: add flag based batch version --- order/batch.go | 47 ++++++++++++++++++++++---- order/batch_test.go | 81 +++++++++++++++++++++++++++++++++++++++++++++ server.go | 23 +++++++++++-- 3 files changed, 142 insertions(+), 9 deletions(-) diff --git a/order/batch.go b/order/batch.go index 87c9612..5823cd3 100644 --- a/order/batch.go +++ b/order/batch.go @@ -56,7 +56,7 @@ const ( // // NOTE: This feature requires the runtime support: // - The asker needs to open the channel with the right `private` value - // - The bidder needs to be able set the channel acceptor for the + // - The bidder needs to be able to set the channel acceptor for the // channel with the right `private` value. // For that reason this needs to be a batch version and not only an // order one. @@ -65,7 +65,9 @@ const ( // UpgradeAccountTaprootBatchVersion is the batch version where accounts // are automatically upgraded to Taproot accounts. We leave a gap up to // 10 on purpose to allow for in-between versions (that aren't dependent - // on a lnd version) to be added. + // on a lnd version) to be added. This version is used as the base + // version when using a flag based versioning scheme, as this is now the + // feature set that every lnd node supports. UpgradeAccountTaprootBatchVersion BatchVersion = 10 // ZeroConfChannelsBatchVersion is the first version where orders can @@ -76,37 +78,68 @@ const ( // - The bidder needs to be able to set the channel acceptor for the // channel with the right `Zeroconf` bool value && `MinDepth=0`. // The LND node should be running version v0.15.1-beta or newer. + // Because this version already existed (in a deployed state) as a + // config dependent version before we switched to a flag based version + // scheme, this still has a linear version number. But the features + // expressed by this version can also be expressed as + // UpgradeAccountTaprootBatchVersion | ZeroConfChannelsFlag ZeroConfChannelsBatchVersion BatchVersion = 11 ) +const ( + // LinearVersionEnd is the end of the linear version space. This is used + // to determine whether a version is one of the old, linear ones or one + // of the new, flag based ones. + LinearVersionEnd BatchVersion = 0x0000_000F + + // ZeroConfChannelsFlag is the flag in the batch version that indicates + // that orders can set the flags to only match with confirmed/zeroconf + // channels. + ZeroConfChannelsFlag BatchVersion = 0x0000_0010 + + // UpgradeAccountTaprootV2Flag is the flag in the batch version that + // indicates accounts can automatically be upgraded to Taproot v2 (using + // the MuSig2 v1.0.0-rc2 spec). + UpgradeAccountTaprootV2Flag BatchVersion = 0x0000_0020 +) + // SupportsAccountExtension is a helper function to easily check if a version // supports account extension after participating in a batch or not. func (bv BatchVersion) SupportsAccountExtension() bool { - return bv >= ExtendAccountBatchVersion + return (bv & LinearVersionEnd) >= ExtendAccountBatchVersion } // SupportsUnannouncedChannels is a helper function to easily check if a version // supports orders with unannounced channels or not. func (bv BatchVersion) SupportsUnannouncedChannels() bool { - return bv >= UnannouncedChannelsBatchVersion + return (bv & LinearVersionEnd) >= UnannouncedChannelsBatchVersion } // SupportsAccountTaprootUpgrade is a helper function to easily check if a // version supports upgrading SegWit v0 (p2wsh) accounts to Taproot (p2tr) or // not. func (bv BatchVersion) SupportsAccountTaprootUpgrade() bool { - return bv >= UpgradeAccountTaprootBatchVersion + return (bv & LinearVersionEnd) >= UpgradeAccountTaprootBatchVersion +} + +// SupportsAccountTaprootV2Upgrade is a helper function to easily check if a +// version supports upgrading SegWit v0 (p2wsh) or Taproot v2 (p2tr) to +// Taproot v2 (p2tr) or not. +func (bv BatchVersion) SupportsAccountTaprootV2Upgrade() bool { + return (bv & UpgradeAccountTaprootV2Flag) == UpgradeAccountTaprootV2Flag } // SupportsZeroConfChannels is the helper function to easily check if a version // supports orders with zeroconf channels or not. func (bv BatchVersion) SupportsZeroConfChannels() bool { - return bv >= ZeroConfChannelsBatchVersion + return (bv&LinearVersionEnd) >= ZeroConfChannelsBatchVersion || + bv&ZeroConfChannelsFlag == ZeroConfChannelsFlag } const ( // LatestBatchVersion points to the most recent batch version. - LatestBatchVersion = ZeroConfChannelsBatchVersion + LatestBatchVersion = UpgradeAccountTaprootBatchVersion | + ZeroConfChannelsFlag | UpgradeAccountTaprootV2Flag // LegacyLeaseDurationBucket is the single static duration bucket that // was used for orders before dynamic duration buckets were added. diff --git a/order/batch_test.go b/order/batch_test.go index 0cd455e..702e449 100644 --- a/order/batch_test.go +++ b/order/batch_test.go @@ -2,6 +2,7 @@ package order import ( "encoding/hex" + "fmt" "testing" "github.com/btcsuite/btcd/btcec/v2" @@ -126,3 +127,83 @@ func TestChannelOutput(t *testing.T) { require.Equal(t, uint32(0), idx) require.Equal(t, batchTx.TxOut[0], out) } + +// TestBatchVersionFlags tests the various batch versions and their supported +// features. +func TestBatchVersionFlags(t *testing.T) { + testCases := []struct { + version BatchVersion + supportExtension bool + supportUnannounced bool + supportTaproot bool + supportTaprootV2 bool + supportZeroConf bool + }{{ + version: DefaultBatchVersion, + }, { + version: ExtendAccountBatchVersion, + supportExtension: true, + }, { + version: UnannouncedChannelsBatchVersion, + supportExtension: true, + supportUnannounced: true, + }, { + version: UpgradeAccountTaprootBatchVersion, + supportExtension: true, + supportUnannounced: true, + supportTaproot: true, + }, { + version: ZeroConfChannelsBatchVersion, + supportExtension: true, + supportUnannounced: true, + supportTaproot: true, + supportZeroConf: true, + }, { + version: UpgradeAccountTaprootBatchVersion | + ZeroConfChannelsFlag, + supportExtension: true, + supportUnannounced: true, + supportTaproot: true, + supportZeroConf: true, + }, { + version: UpgradeAccountTaprootBatchVersion | + UpgradeAccountTaprootV2Flag, + supportExtension: true, + supportUnannounced: true, + supportTaproot: true, + supportTaprootV2: true, + }, { + version: UpgradeAccountTaprootBatchVersion | + ZeroConfChannelsFlag | UpgradeAccountTaprootV2Flag, + supportExtension: true, + supportUnannounced: true, + supportTaproot: true, + supportTaprootV2: true, + supportZeroConf: true, + }} + + for _, tc := range testCases { + t.Run(fmt.Sprintf("%d", tc.version), func(tt *testing.T) { + require.Equal( + tt, tc.supportExtension, + tc.version.SupportsAccountExtension(), + ) + require.Equal( + tt, tc.supportUnannounced, + tc.version.SupportsUnannouncedChannels(), + ) + require.Equal( + tt, tc.supportTaproot, + tc.version.SupportsAccountTaprootUpgrade(), + ) + require.Equal( + tt, tc.supportTaprootV2, + tc.version.SupportsAccountTaprootV2Upgrade(), + ) + require.Equal( + tt, tc.supportZeroConf, + tc.version.SupportsZeroConfChannels(), + ) + }) + } +} diff --git a/server.go b/server.go index 660effd..68c8860 100644 --- a/server.go +++ b/server.go @@ -883,6 +883,9 @@ func (s *Server) determineBatchVersion() (order.BatchVersion, error) { // We set the default value of the config flag to -1, so we can // differentiate between no value set and the first version (0). if configVersion >= 0 { + log.Infof("Using configured batch version %d for connecting "+ + "to auctioneer", configVersion) + return order.BatchVersion(configVersion), nil } @@ -898,6 +901,8 @@ func (s *Server) determineBatchVersion() (order.BatchVersion, error) { return 0, err } + baseVersion := order.UpgradeAccountTaprootBatchVersion + // If the node supports ZeroConfChannels use that batch version. _, zeroConfOpt := info.Features[uint32(lnwire.ZeroConfOptional)] _, zeroConfReq := info.Features[uint32(lnwire.ZeroConfRequired)] @@ -908,8 +913,22 @@ func (s *Server) determineBatchVersion() (order.BatchVersion, error) { supportsSCIDAlias := SCIDAliasOpt || SCIDAliasReq if supportsZeroConf && supportsSCIDAlias { - return order.ZeroConfChannelsBatchVersion, nil + baseVersion |= order.ZeroConfChannelsFlag } - return order.UpgradeAccountTaprootBatchVersion, nil + // We can only use the new version of the MuSig2 protocol if we have a + // recent lnd version that added support for specifying the MuSig2 + // version in the RPC. + currentLndVersion := s.lndServices.Version + verErr := lndclient.AssertVersionCompatible( + currentLndVersion, muSig2V100RC2Version, + ) + if verErr == nil { + baseVersion |= order.UpgradeAccountTaprootV2Flag + } + + log.Infof("Using batch version %d for connecting to auctioneer", + baseVersion) + + return baseVersion, nil }