Integrate BACKBEAT SDK and resolve KACHING license validation
Major integrations and fixes: - Added BACKBEAT SDK integration for P2P operation timing - Implemented beat-aware status tracking for distributed operations - Added Docker secrets support for secure license management - Resolved KACHING license validation via HTTPS/TLS - Updated docker-compose configuration for clean stack deployment - Disabled rollback policies to prevent deployment failures - Added license credential storage (CHORUS-DEV-MULTI-001) Technical improvements: - BACKBEAT P2P operation tracking with phase management - Enhanced configuration system with file-based secrets - Improved error handling for license validation - Clean separation of KACHING and CHORUS deployment stacks 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
498
vendor/github.com/libp2p/go-libp2p/config/config.go
generated
vendored
Normal file
498
vendor/github.com/libp2p/go-libp2p/config/config.go
generated
vendored
Normal file
@@ -0,0 +1,498 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/libp2p/go-libp2p/core/connmgr"
|
||||
"github.com/libp2p/go-libp2p/core/crypto"
|
||||
"github.com/libp2p/go-libp2p/core/event"
|
||||
"github.com/libp2p/go-libp2p/core/host"
|
||||
"github.com/libp2p/go-libp2p/core/metrics"
|
||||
"github.com/libp2p/go-libp2p/core/network"
|
||||
"github.com/libp2p/go-libp2p/core/peer"
|
||||
"github.com/libp2p/go-libp2p/core/peerstore"
|
||||
"github.com/libp2p/go-libp2p/core/pnet"
|
||||
"github.com/libp2p/go-libp2p/core/protocol"
|
||||
"github.com/libp2p/go-libp2p/core/routing"
|
||||
"github.com/libp2p/go-libp2p/core/sec"
|
||||
"github.com/libp2p/go-libp2p/core/sec/insecure"
|
||||
"github.com/libp2p/go-libp2p/core/transport"
|
||||
"github.com/libp2p/go-libp2p/p2p/host/autonat"
|
||||
"github.com/libp2p/go-libp2p/p2p/host/autorelay"
|
||||
bhost "github.com/libp2p/go-libp2p/p2p/host/basic"
|
||||
blankhost "github.com/libp2p/go-libp2p/p2p/host/blank"
|
||||
"github.com/libp2p/go-libp2p/p2p/host/eventbus"
|
||||
"github.com/libp2p/go-libp2p/p2p/host/peerstore/pstoremem"
|
||||
rcmgr "github.com/libp2p/go-libp2p/p2p/host/resource-manager"
|
||||
routed "github.com/libp2p/go-libp2p/p2p/host/routed"
|
||||
"github.com/libp2p/go-libp2p/p2p/net/swarm"
|
||||
tptu "github.com/libp2p/go-libp2p/p2p/net/upgrader"
|
||||
circuitv2 "github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/client"
|
||||
relayv2 "github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/relay"
|
||||
"github.com/libp2p/go-libp2p/p2p/protocol/holepunch"
|
||||
"github.com/libp2p/go-libp2p/p2p/transport/quicreuse"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
|
||||
ma "github.com/multiformats/go-multiaddr"
|
||||
madns "github.com/multiformats/go-multiaddr-dns"
|
||||
"go.uber.org/fx"
|
||||
"go.uber.org/fx/fxevent"
|
||||
)
|
||||
|
||||
// AddrsFactory is a function that takes a set of multiaddrs we're listening on and
|
||||
// returns the set of multiaddrs we should advertise to the network.
|
||||
type AddrsFactory = bhost.AddrsFactory
|
||||
|
||||
// NATManagerC is a NATManager constructor.
|
||||
type NATManagerC func(network.Network) bhost.NATManager
|
||||
|
||||
type RoutingC func(host.Host) (routing.PeerRouting, error)
|
||||
|
||||
// AutoNATConfig defines the AutoNAT behavior for the libp2p host.
|
||||
type AutoNATConfig struct {
|
||||
ForceReachability *network.Reachability
|
||||
EnableService bool
|
||||
ThrottleGlobalLimit int
|
||||
ThrottlePeerLimit int
|
||||
ThrottleInterval time.Duration
|
||||
}
|
||||
|
||||
type Security struct {
|
||||
ID protocol.ID
|
||||
Constructor interface{}
|
||||
}
|
||||
|
||||
// Config describes a set of settings for a libp2p node
|
||||
//
|
||||
// This is *not* a stable interface. Use the options defined in the root
|
||||
// package.
|
||||
type Config struct {
|
||||
// UserAgent is the identifier this node will send to other peers when
|
||||
// identifying itself, e.g. via the identify protocol.
|
||||
//
|
||||
// Set it via the UserAgent option function.
|
||||
UserAgent string
|
||||
|
||||
// ProtocolVersion is the protocol version that identifies the family
|
||||
// of protocols used by the peer in the Identify protocol. It is set
|
||||
// using the [ProtocolVersion] option.
|
||||
ProtocolVersion string
|
||||
|
||||
PeerKey crypto.PrivKey
|
||||
|
||||
QUICReuse []fx.Option
|
||||
Transports []fx.Option
|
||||
Muxers []tptu.StreamMuxer
|
||||
SecurityTransports []Security
|
||||
Insecure bool
|
||||
PSK pnet.PSK
|
||||
|
||||
DialTimeout time.Duration
|
||||
|
||||
RelayCustom bool
|
||||
Relay bool // should the relay transport be used
|
||||
|
||||
EnableRelayService bool // should we run a circuitv2 relay (if publicly reachable)
|
||||
RelayServiceOpts []relayv2.Option
|
||||
|
||||
ListenAddrs []ma.Multiaddr
|
||||
AddrsFactory bhost.AddrsFactory
|
||||
ConnectionGater connmgr.ConnectionGater
|
||||
|
||||
ConnManager connmgr.ConnManager
|
||||
ResourceManager network.ResourceManager
|
||||
|
||||
NATManager NATManagerC
|
||||
Peerstore peerstore.Peerstore
|
||||
Reporter metrics.Reporter
|
||||
|
||||
MultiaddrResolver *madns.Resolver
|
||||
|
||||
DisablePing bool
|
||||
|
||||
Routing RoutingC
|
||||
|
||||
EnableAutoRelay bool
|
||||
AutoRelayOpts []autorelay.Option
|
||||
AutoNATConfig
|
||||
|
||||
EnableHolePunching bool
|
||||
HolePunchingOptions []holepunch.Option
|
||||
|
||||
DisableMetrics bool
|
||||
PrometheusRegisterer prometheus.Registerer
|
||||
|
||||
DialRanker network.DialRanker
|
||||
|
||||
SwarmOpts []swarm.Option
|
||||
}
|
||||
|
||||
func (cfg *Config) makeSwarm(eventBus event.Bus, enableMetrics bool) (*swarm.Swarm, error) {
|
||||
if cfg.Peerstore == nil {
|
||||
return nil, fmt.Errorf("no peerstore specified")
|
||||
}
|
||||
|
||||
// Check this early. Prevents us from even *starting* without verifying this.
|
||||
if pnet.ForcePrivateNetwork && len(cfg.PSK) == 0 {
|
||||
log.Error("tried to create a libp2p node with no Private" +
|
||||
" Network Protector but usage of Private Networks" +
|
||||
" is forced by the environment")
|
||||
// Note: This is *also* checked the upgrader itself, so it'll be
|
||||
// enforced even *if* you don't use the libp2p constructor.
|
||||
return nil, pnet.ErrNotInPrivateNetwork
|
||||
}
|
||||
|
||||
if cfg.PeerKey == nil {
|
||||
return nil, fmt.Errorf("no peer key specified")
|
||||
}
|
||||
|
||||
// Obtain Peer ID from public key
|
||||
pid, err := peer.IDFromPublicKey(cfg.PeerKey.GetPublic())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := cfg.Peerstore.AddPrivKey(pid, cfg.PeerKey); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := cfg.Peerstore.AddPubKey(pid, cfg.PeerKey.GetPublic()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
opts := cfg.SwarmOpts
|
||||
if cfg.Reporter != nil {
|
||||
opts = append(opts, swarm.WithMetrics(cfg.Reporter))
|
||||
}
|
||||
if cfg.ConnectionGater != nil {
|
||||
opts = append(opts, swarm.WithConnectionGater(cfg.ConnectionGater))
|
||||
}
|
||||
if cfg.DialTimeout != 0 {
|
||||
opts = append(opts, swarm.WithDialTimeout(cfg.DialTimeout))
|
||||
}
|
||||
if cfg.ResourceManager != nil {
|
||||
opts = append(opts, swarm.WithResourceManager(cfg.ResourceManager))
|
||||
}
|
||||
if cfg.MultiaddrResolver != nil {
|
||||
opts = append(opts, swarm.WithMultiaddrResolver(cfg.MultiaddrResolver))
|
||||
}
|
||||
if cfg.DialRanker != nil {
|
||||
opts = append(opts, swarm.WithDialRanker(cfg.DialRanker))
|
||||
}
|
||||
|
||||
if enableMetrics {
|
||||
opts = append(opts,
|
||||
swarm.WithMetricsTracer(swarm.NewMetricsTracer(swarm.WithRegisterer(cfg.PrometheusRegisterer))))
|
||||
}
|
||||
// TODO: Make the swarm implementation configurable.
|
||||
return swarm.NewSwarm(pid, cfg.Peerstore, eventBus, opts...)
|
||||
}
|
||||
|
||||
func (cfg *Config) addTransports(h host.Host) error {
|
||||
swrm, ok := h.Network().(transport.TransportNetwork)
|
||||
if !ok {
|
||||
// Should probably skip this if no transports.
|
||||
return fmt.Errorf("swarm does not support transports")
|
||||
}
|
||||
|
||||
fxopts := []fx.Option{
|
||||
fx.WithLogger(func() fxevent.Logger { return getFXLogger() }),
|
||||
fx.Provide(fx.Annotate(tptu.New, fx.ParamTags(`name:"security"`))),
|
||||
fx.Supply(cfg.Muxers),
|
||||
fx.Supply(h.ID()),
|
||||
fx.Provide(func() host.Host { return h }),
|
||||
fx.Provide(func() crypto.PrivKey { return h.Peerstore().PrivKey(h.ID()) }),
|
||||
fx.Provide(func() connmgr.ConnectionGater { return cfg.ConnectionGater }),
|
||||
fx.Provide(func() pnet.PSK { return cfg.PSK }),
|
||||
fx.Provide(func() network.ResourceManager { return cfg.ResourceManager }),
|
||||
fx.Provide(func() *madns.Resolver { return cfg.MultiaddrResolver }),
|
||||
}
|
||||
fxopts = append(fxopts, cfg.Transports...)
|
||||
if cfg.Insecure {
|
||||
fxopts = append(fxopts,
|
||||
fx.Provide(
|
||||
fx.Annotate(
|
||||
func(id peer.ID, priv crypto.PrivKey) []sec.SecureTransport {
|
||||
return []sec.SecureTransport{insecure.NewWithIdentity(insecure.ID, id, priv)}
|
||||
},
|
||||
fx.ResultTags(`name:"security"`),
|
||||
),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
// fx groups are unordered, but we need to preserve the order of the security transports
|
||||
// First of all, we construct the security transports that are needed,
|
||||
// and save them to a group call security_unordered.
|
||||
for _, s := range cfg.SecurityTransports {
|
||||
fxName := fmt.Sprintf(`name:"security_%s"`, s.ID)
|
||||
fxopts = append(fxopts, fx.Supply(fx.Annotate(s.ID, fx.ResultTags(fxName))))
|
||||
fxopts = append(fxopts,
|
||||
fx.Provide(fx.Annotate(
|
||||
s.Constructor,
|
||||
fx.ParamTags(fxName),
|
||||
fx.As(new(sec.SecureTransport)),
|
||||
fx.ResultTags(`group:"security_unordered"`),
|
||||
)),
|
||||
)
|
||||
}
|
||||
// Then we consume the group security_unordered, and order them by the user's preference.
|
||||
fxopts = append(fxopts, fx.Provide(
|
||||
fx.Annotate(
|
||||
func(secs []sec.SecureTransport) ([]sec.SecureTransport, error) {
|
||||
if len(secs) != len(cfg.SecurityTransports) {
|
||||
return nil, errors.New("inconsistent length for security transports")
|
||||
}
|
||||
t := make([]sec.SecureTransport, 0, len(secs))
|
||||
for _, s := range cfg.SecurityTransports {
|
||||
for _, st := range secs {
|
||||
if s.ID != st.ID() {
|
||||
continue
|
||||
}
|
||||
t = append(t, st)
|
||||
}
|
||||
}
|
||||
return t, nil
|
||||
},
|
||||
fx.ParamTags(`group:"security_unordered"`),
|
||||
fx.ResultTags(`name:"security"`),
|
||||
)))
|
||||
}
|
||||
|
||||
fxopts = append(fxopts, fx.Provide(PrivKeyToStatelessResetKey))
|
||||
fxopts = append(fxopts, fx.Provide(PrivKeyToTokenGeneratorKey))
|
||||
if cfg.QUICReuse != nil {
|
||||
fxopts = append(fxopts, cfg.QUICReuse...)
|
||||
} else {
|
||||
fxopts = append(fxopts, fx.Provide(quicreuse.NewConnManager)) // TODO: close the ConnManager when shutting down the node
|
||||
}
|
||||
|
||||
fxopts = append(fxopts, fx.Invoke(
|
||||
fx.Annotate(
|
||||
func(tpts []transport.Transport) error {
|
||||
for _, t := range tpts {
|
||||
if err := swrm.AddTransport(t); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
fx.ParamTags(`group:"transport"`),
|
||||
)),
|
||||
)
|
||||
if cfg.Relay {
|
||||
fxopts = append(fxopts, fx.Invoke(circuitv2.AddTransport))
|
||||
}
|
||||
app := fx.New(fxopts...)
|
||||
if err := app.Err(); err != nil {
|
||||
h.Close()
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewNode constructs a new libp2p Host from the Config.
|
||||
//
|
||||
// This function consumes the config. Do not reuse it (really!).
|
||||
func (cfg *Config) NewNode() (host.Host, error) {
|
||||
// If possible check that the resource manager conn limit is higher than the
|
||||
// limit set in the conn manager.
|
||||
if l, ok := cfg.ResourceManager.(connmgr.GetConnLimiter); ok {
|
||||
err := cfg.ConnManager.CheckLimit(l)
|
||||
if err != nil {
|
||||
log.Warn(fmt.Sprintf("rcmgr limit conflicts with connmgr limit: %v", err))
|
||||
}
|
||||
}
|
||||
|
||||
eventBus := eventbus.NewBus(eventbus.WithMetricsTracer(eventbus.NewMetricsTracer(eventbus.WithRegisterer(cfg.PrometheusRegisterer))))
|
||||
swrm, err := cfg.makeSwarm(eventBus, !cfg.DisableMetrics)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !cfg.DisableMetrics {
|
||||
rcmgr.MustRegisterWith(cfg.PrometheusRegisterer)
|
||||
}
|
||||
|
||||
h, err := bhost.NewHost(swrm, &bhost.HostOpts{
|
||||
EventBus: eventBus,
|
||||
ConnManager: cfg.ConnManager,
|
||||
AddrsFactory: cfg.AddrsFactory,
|
||||
NATManager: cfg.NATManager,
|
||||
EnablePing: !cfg.DisablePing,
|
||||
UserAgent: cfg.UserAgent,
|
||||
ProtocolVersion: cfg.ProtocolVersion,
|
||||
EnableHolePunching: cfg.EnableHolePunching,
|
||||
HolePunchingOptions: cfg.HolePunchingOptions,
|
||||
EnableRelayService: cfg.EnableRelayService,
|
||||
RelayServiceOpts: cfg.RelayServiceOpts,
|
||||
EnableMetrics: !cfg.DisableMetrics,
|
||||
PrometheusRegisterer: cfg.PrometheusRegisterer,
|
||||
})
|
||||
if err != nil {
|
||||
swrm.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if cfg.Relay {
|
||||
// If we've enabled the relay, we should filter out relay
|
||||
// addresses by default.
|
||||
//
|
||||
// TODO: We shouldn't be doing this here.
|
||||
oldFactory := h.AddrsFactory
|
||||
h.AddrsFactory = func(addrs []ma.Multiaddr) []ma.Multiaddr {
|
||||
return oldFactory(autorelay.Filter(addrs))
|
||||
}
|
||||
}
|
||||
|
||||
if err := cfg.addTransports(h); err != nil {
|
||||
h.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// TODO: This method succeeds if listening on one address succeeds. We
|
||||
// should probably fail if listening on *any* addr fails.
|
||||
if err := h.Network().Listen(cfg.ListenAddrs...); err != nil {
|
||||
h.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Configure routing and autorelay
|
||||
var router routing.PeerRouting
|
||||
if cfg.Routing != nil {
|
||||
router, err = cfg.Routing(h)
|
||||
if err != nil {
|
||||
h.Close()
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Note: h.AddrsFactory may be changed by relayFinder, but non-relay version is
|
||||
// used by AutoNAT below.
|
||||
var ar *autorelay.AutoRelay
|
||||
addrF := h.AddrsFactory
|
||||
if cfg.EnableAutoRelay {
|
||||
if !cfg.Relay {
|
||||
h.Close()
|
||||
return nil, fmt.Errorf("cannot enable autorelay; relay is not enabled")
|
||||
}
|
||||
if !cfg.DisableMetrics {
|
||||
mt := autorelay.WithMetricsTracer(
|
||||
autorelay.NewMetricsTracer(autorelay.WithRegisterer(cfg.PrometheusRegisterer)))
|
||||
mtOpts := []autorelay.Option{mt}
|
||||
cfg.AutoRelayOpts = append(mtOpts, cfg.AutoRelayOpts...)
|
||||
}
|
||||
|
||||
ar, err = autorelay.NewAutoRelay(h, cfg.AutoRelayOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
autonatOpts := []autonat.Option{
|
||||
autonat.UsingAddresses(func() []ma.Multiaddr {
|
||||
return addrF(h.AllAddrs())
|
||||
}),
|
||||
}
|
||||
if !cfg.DisableMetrics {
|
||||
autonatOpts = append(autonatOpts,
|
||||
autonat.WithMetricsTracer(
|
||||
autonat.NewMetricsTracer(autonat.WithRegisterer(cfg.PrometheusRegisterer))))
|
||||
}
|
||||
if cfg.AutoNATConfig.ThrottleInterval != 0 {
|
||||
autonatOpts = append(autonatOpts,
|
||||
autonat.WithThrottling(cfg.AutoNATConfig.ThrottleGlobalLimit, cfg.AutoNATConfig.ThrottleInterval),
|
||||
autonat.WithPeerThrottling(cfg.AutoNATConfig.ThrottlePeerLimit))
|
||||
}
|
||||
if cfg.AutoNATConfig.EnableService {
|
||||
autonatPrivKey, _, err := crypto.GenerateEd25519Key(rand.Reader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ps, err := pstoremem.NewPeerstore()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Pull out the pieces of the config that we _actually_ care about.
|
||||
// Specifically, don't set up things like autorelay, listeners,
|
||||
// identify, etc.
|
||||
autoNatCfg := Config{
|
||||
Transports: cfg.Transports,
|
||||
Muxers: cfg.Muxers,
|
||||
SecurityTransports: cfg.SecurityTransports,
|
||||
Insecure: cfg.Insecure,
|
||||
PSK: cfg.PSK,
|
||||
ConnectionGater: cfg.ConnectionGater,
|
||||
Reporter: cfg.Reporter,
|
||||
PeerKey: autonatPrivKey,
|
||||
Peerstore: ps,
|
||||
DialRanker: swarm.NoDelayDialRanker,
|
||||
SwarmOpts: []swarm.Option{
|
||||
// It is better to disable black hole detection and just attempt a dial for autonat
|
||||
swarm.WithUDPBlackHoleConfig(false, 0, 0),
|
||||
swarm.WithIPv6BlackHoleConfig(false, 0, 0),
|
||||
},
|
||||
}
|
||||
|
||||
dialer, err := autoNatCfg.makeSwarm(eventbus.NewBus(), false)
|
||||
if err != nil {
|
||||
h.Close()
|
||||
return nil, err
|
||||
}
|
||||
dialerHost := blankhost.NewBlankHost(dialer)
|
||||
if err := autoNatCfg.addTransports(dialerHost); err != nil {
|
||||
dialerHost.Close()
|
||||
h.Close()
|
||||
return nil, err
|
||||
}
|
||||
// NOTE: We're dropping the blank host here but that's fine. It
|
||||
// doesn't really _do_ anything and doesn't even need to be
|
||||
// closed (as long as we close the underlying network).
|
||||
autonatOpts = append(autonatOpts, autonat.EnableService(dialerHost.Network()))
|
||||
}
|
||||
if cfg.AutoNATConfig.ForceReachability != nil {
|
||||
autonatOpts = append(autonatOpts, autonat.WithReachability(*cfg.AutoNATConfig.ForceReachability))
|
||||
}
|
||||
|
||||
autonat, err := autonat.New(h, autonatOpts...)
|
||||
if err != nil {
|
||||
h.Close()
|
||||
return nil, fmt.Errorf("cannot enable autorelay; autonat failed to start: %v", err)
|
||||
}
|
||||
h.SetAutoNat(autonat)
|
||||
|
||||
// start the host background tasks
|
||||
h.Start()
|
||||
|
||||
var ho host.Host
|
||||
ho = h
|
||||
if router != nil {
|
||||
ho = routed.Wrap(h, router)
|
||||
}
|
||||
if ar != nil {
|
||||
arh := autorelay.NewAutoRelayHost(ho, ar)
|
||||
arh.Start()
|
||||
ho = arh
|
||||
}
|
||||
return ho, nil
|
||||
}
|
||||
|
||||
// Option is a libp2p config option that can be given to the libp2p constructor
|
||||
// (`libp2p.New`).
|
||||
type Option func(cfg *Config) error
|
||||
|
||||
// Apply applies the given options to the config, returning the first error
|
||||
// encountered (if any).
|
||||
func (cfg *Config) Apply(opts ...Option) error {
|
||||
for _, opt := range opts {
|
||||
if opt == nil {
|
||||
continue
|
||||
}
|
||||
if err := opt(cfg); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user