diff --git a/loopd/config.go b/loopd/config.go index b3460e3..43cb003 100644 --- a/loopd/config.go +++ b/loopd/config.go @@ -149,6 +149,8 @@ type Config struct { TotalPaymentTimeout time.Duration `long:"totalpaymenttimeout" description:"The timeout to use for off-chain payments."` MaxPaymentRetries int `long:"maxpaymentretries" description:"The maximum number of times an off-chain payment may be retried."` + EnableExperimental bool `long:"experimental" description:"Enable experimental features: taproot HTLCs and MuSig2 loop out sweeps."` + Lnd *lndConfig `group:"lnd" namespace:"lnd"` Server *loopServerConfig `group:"server" namespace:"server"` @@ -185,6 +187,7 @@ func DefaultConfig() Config { LoopOutMaxParts: defaultLoopOutMaxParts, TotalPaymentTimeout: defaultTotalPaymentTimeout, MaxPaymentRetries: defaultMaxPaymentRetries, + EnableExperimental: false, Lnd: &lndConfig{ Host: "localhost:10009", MacaroonPath: DefaultLndMacaroonPath, diff --git a/loopd/daemon.go b/loopd/daemon.go index 71f1a6b..b8eff04 100644 --- a/loopd/daemon.go +++ b/loopd/daemon.go @@ -348,6 +348,12 @@ func (d *Daemon) startWebServers() error { // this method fails with an error then no goroutine was started yet and no // cleanup is necessary. If it succeeds, then goroutines have been spawned. func (d *Daemon) initialize(withMacaroonService bool) error { + if d.cfg.EnableExperimental { + loopdb.EnableExperimentalProtocol() + } + + log.Infof("Protocol version: %v", loopdb.CurrentProtocolVersion()) + // If no swap server is specified, use the default addresses for mainnet // and testnet. if d.cfg.Server.Host == "" { diff --git a/loopdb/protocol_version.go b/loopdb/protocol_version.go index 0d93266..06e0e32 100644 --- a/loopdb/protocol_version.go +++ b/loopdb/protocol_version.go @@ -59,18 +59,50 @@ const ( // started saving protocol version with swaps. ProtocolVersionUnrecorded ProtocolVersion = math.MaxUint32 - // CurrentRPCProtocolVersion defines the version of the RPC protocol - // that is currently supported by the loop client. - CurrentRPCProtocolVersion = looprpc.ProtocolVersion_HTLC_V3 + // stableRPCProtocolVersion defines the current stable RPC protocol + // version. + stableRPCProtocolVersion = looprpc.ProtocolVersion_ROUTING_PLUGIN - // CurrentInternalProtocolVersion defines the RPC current protocol in - // the internal representation. - CurrentInternalProtocolVersion = ProtocolVersion(CurrentRPCProtocolVersion) + // experimentalRPCProtocolVersion defines the RPC protocol version that + // includes all currently experimentally released features. + experimentalRPCProtocolVersion = looprpc.ProtocolVersion_HTLC_V3 ) +var ( + // currentRPCProtocolVersion holds the version of the RPC protocol + // that the client selected to use for new swaps. Shouldn't be lower + // than the previous protocol version. + currentRPCProtocolVersion = stableRPCProtocolVersion +) + +// CurrentRPCProtocolVersion returns the RPC protocol version selected to be +// used for new swaps. +func CurrentRPCProtocolVersion() looprpc.ProtocolVersion { + return currentRPCProtocolVersion +} + +// CurrentProtocolVersion returns the internal protocol version selected to be +// used for new swaps. +func CurrentProtocolVersion() ProtocolVersion { + return ProtocolVersion(currentRPCProtocolVersion) +} + +// EnableExperimentalProtocol sets the current protocol version to include all +// experimental features. Do not call this function directly: used in loopd and +// unit tests only. +func EnableExperimentalProtocol() { + currentRPCProtocolVersion = experimentalRPCProtocolVersion +} + +// ResetCurrentProtocolVersion resets the current protocol version to the stable +// protocol. Note: used in integration tests only! +func ResetCurrentProtocolVersion() { + currentRPCProtocolVersion = stableRPCProtocolVersion +} + // Valid returns true if the value of the ProtocolVersion is valid. func (p ProtocolVersion) Valid() bool { - return p <= CurrentInternalProtocolVersion + return p <= ProtocolVersion(experimentalRPCProtocolVersion) } // String returns the string representation of a protocol version. diff --git a/loopdb/protocol_version_test.go b/loopdb/protocol_version_test.go index cb7d3b2..2e7f7f5 100644 --- a/loopdb/protocol_version_test.go +++ b/loopdb/protocol_version_test.go @@ -48,12 +48,19 @@ func TestProtocolVersionSanity(t *testing.T) { // Finally test that the current version contants are up to date require.Equal(t, - CurrentInternalProtocolVersion, - versions[len(versions)-1], + CurrentProtocolVersion(), + versions[len(versions)-2], ) require.Equal(t, - uint32(CurrentInternalProtocolVersion), - uint32(CurrentRPCProtocolVersion), + uint32(CurrentProtocolVersion()), + uint32(CurrentRPCProtocolVersion()), + ) + + EnableExperimentalProtocol() + + require.Equal(t, + CurrentProtocolVersion(), + ProtocolVersion(experimentalRPCProtocolVersion), ) } diff --git a/loopin.go b/loopin.go index d4e7e57..9d88a93 100644 --- a/loopin.go +++ b/loopin.go @@ -244,7 +244,7 @@ func newLoopInSwap(globalCtx context.Context, cfg *swapConfig, MaxMinerFee: request.MaxMinerFee, MaxSwapFee: request.MaxSwapFee, Label: request.Label, - ProtocolVersion: loopdb.CurrentInternalProtocolVersion, + ProtocolVersion: loopdb.CurrentProtocolVersion(), }, } diff --git a/loopout.go b/loopout.go index ecfcac1..10d01de 100644 --- a/loopout.go +++ b/loopout.go @@ -177,7 +177,7 @@ func newLoopOutSwap(globalCtx context.Context, cfg *swapConfig, MaxMinerFee: request.MaxMinerFee, MaxSwapFee: request.MaxSwapFee, Label: request.Label, - ProtocolVersion: loopdb.CurrentInternalProtocolVersion, + ProtocolVersion: loopdb.CurrentProtocolVersion(), }, OutgoingChanSet: chanSet, } diff --git a/swap_server_client.go b/swap_server_client.go index 799ac87..10f0709 100644 --- a/swap_server_client.go +++ b/swap_server_client.go @@ -174,7 +174,7 @@ func (s *grpcSwapServerClient) GetLoopOutTerms(ctx context.Context) ( defer rpcCancel() terms, err := s.server.LoopOutTerms(rpcCtx, &looprpc.ServerLoopOutTermsRequest{ - ProtocolVersion: loopdb.CurrentRPCProtocolVersion, + ProtocolVersion: loopdb.CurrentRPCProtocolVersion(), }, ) if err != nil { @@ -199,7 +199,7 @@ func (s *grpcSwapServerClient) GetLoopOutQuote(ctx context.Context, &looprpc.ServerLoopOutQuoteRequest{ Amt: uint64(amt), SwapPublicationDeadline: swapPublicationDeadline.Unix(), - ProtocolVersion: loopdb.CurrentRPCProtocolVersion, + ProtocolVersion: loopdb.CurrentRPCProtocolVersion(), Expiry: expiry, }, ) @@ -231,7 +231,7 @@ func (s *grpcSwapServerClient) GetLoopInTerms(ctx context.Context) ( defer rpcCancel() terms, err := s.server.LoopInTerms(rpcCtx, &looprpc.ServerLoopInTermsRequest{ - ProtocolVersion: loopdb.CurrentRPCProtocolVersion, + ProtocolVersion: loopdb.CurrentRPCProtocolVersion(), }, ) if err != nil { @@ -258,7 +258,7 @@ func (s *grpcSwapServerClient) GetLoopInQuote(ctx context.Context, req := &looprpc.ServerLoopInQuoteRequest{ Amt: uint64(amt), - ProtocolVersion: loopdb.CurrentRPCProtocolVersion, + ProtocolVersion: loopdb.CurrentRPCProtocolVersion(), Pubkey: pubKey[:], } @@ -343,7 +343,7 @@ func (s *grpcSwapServerClient) Probe(ctx context.Context, amt btcutil.Amount, req := &looprpc.ServerProbeRequest{ Amt: uint64(amt), Target: target[:], - ProtocolVersion: loopdb.CurrentRPCProtocolVersion, + ProtocolVersion: loopdb.CurrentRPCProtocolVersion(), RouteHints: rpcRouteHints, } @@ -368,7 +368,7 @@ func (s *grpcSwapServerClient) NewLoopOutSwap(ctx context.Context, Amt: uint64(amount), ReceiverKey: receiverKey[:], SwapPublicationDeadline: swapPublicationDeadline.Unix(), - ProtocolVersion: loopdb.CurrentRPCProtocolVersion, + ProtocolVersion: loopdb.CurrentRPCProtocolVersion(), Expiry: expiry, UserAgent: UserAgent(initiator), }, @@ -403,7 +403,7 @@ func (s *grpcSwapServerClient) PushLoopOutPreimage(ctx context.Context, _, err := s.server.LoopOutPushPreimage(rpcCtx, &looprpc.ServerLoopOutPushPreimageRequest{ - ProtocolVersion: loopdb.CurrentRPCProtocolVersion, + ProtocolVersion: loopdb.CurrentRPCProtocolVersion(), Preimage: preimage[:], }, ) @@ -424,7 +424,7 @@ func (s *grpcSwapServerClient) NewLoopInSwap(ctx context.Context, Amt: uint64(amount), SenderKey: senderKey[:], SwapInvoice: swapInvoice, - ProtocolVersion: loopdb.CurrentRPCProtocolVersion, + ProtocolVersion: loopdb.CurrentRPCProtocolVersion(), ProbeInvoice: probeInvoice, UserAgent: UserAgent(initiator), } @@ -469,7 +469,7 @@ func (s *grpcSwapServerClient) SubscribeLoopInUpdates(ctx context.Context, resp, err := s.server.SubscribeLoopInUpdates( ctx, &looprpc.SubscribeUpdatesRequest{ - ProtocolVersion: loopdb.CurrentRPCProtocolVersion, + ProtocolVersion: loopdb.CurrentRPCProtocolVersion(), SwapHash: hash[:], }, ) @@ -500,7 +500,7 @@ func (s *grpcSwapServerClient) SubscribeLoopOutUpdates(ctx context.Context, resp, err := s.server.SubscribeLoopOutUpdates( ctx, &looprpc.SubscribeUpdatesRequest{ - ProtocolVersion: loopdb.CurrentRPCProtocolVersion, + ProtocolVersion: loopdb.CurrentRPCProtocolVersion(), SwapHash: hash[:], }, ) @@ -639,7 +639,7 @@ func (s *grpcSwapServerClient) CancelLoopOutSwap(ctx context.Context, details *outCancelDetails) error { req := &looprpc.CancelLoopOutSwapRequest{ - ProtocolVersion: loopdb.CurrentRPCProtocolVersion, + ProtocolVersion: loopdb.CurrentRPCProtocolVersion(), SwapHash: details.hash[:], PaymentAddress: details.paymentAddr[:], } @@ -660,7 +660,7 @@ func (s *grpcSwapServerClient) RecommendRoutingPlugin(ctx context.Context, swapHash lntypes.Hash, paymentAddr [32]byte) (RoutingPluginType, error) { req := &looprpc.RecommendRoutingPluginReq{ - ProtocolVersion: loopdb.CurrentRPCProtocolVersion, + ProtocolVersion: loopdb.CurrentRPCProtocolVersion(), SwapHash: swapHash[:], PaymentAddress: paymentAddr[:], } @@ -704,7 +704,7 @@ func (s *grpcSwapServerClient) ReportRoutingResult(ctx context.Context, } req := &looprpc.ReportRoutingResultReq{ - ProtocolVersion: loopdb.CurrentRPCProtocolVersion, + ProtocolVersion: loopdb.CurrentRPCProtocolVersion(), SwapHash: swapHash[:], PaymentAddress: paymentAddr[:], Plugin: rpcRoutingPlugin,