 9bdcbe0447
			
		
	
	9bdcbe0447
	
	
	
		
			
			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>
		
			
				
	
	
		
			359 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			359 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package dht
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"testing"
 | |
| 	"time"
 | |
| 
 | |
| 	dhtcfg "github.com/libp2p/go-libp2p-kad-dht/internal/config"
 | |
| 	"github.com/libp2p/go-libp2p-kad-dht/providers"
 | |
| 	"github.com/libp2p/go-libp2p-kbucket/peerdiversity"
 | |
| 	record "github.com/libp2p/go-libp2p-record"
 | |
| 	"github.com/libp2p/go-libp2p/core/peer"
 | |
| 	"github.com/libp2p/go-libp2p/core/protocol"
 | |
| 
 | |
| 	ds "github.com/ipfs/go-datastore"
 | |
| 	ma "github.com/multiformats/go-multiaddr"
 | |
| )
 | |
| 
 | |
| // ModeOpt describes what mode the dht should operate in
 | |
| type ModeOpt = dhtcfg.ModeOpt
 | |
| 
 | |
| const (
 | |
| 	// ModeAuto utilizes EvtLocalReachabilityChanged events sent over the event bus to dynamically switch the DHT
 | |
| 	// between Client and Server modes based on network conditions
 | |
| 	ModeAuto ModeOpt = iota
 | |
| 	// ModeClient operates the DHT as a client only, it cannot respond to incoming queries
 | |
| 	ModeClient
 | |
| 	// ModeServer operates the DHT as a server, it can both send and respond to queries
 | |
| 	ModeServer
 | |
| 	// ModeAutoServer operates in the same way as ModeAuto, but acts as a server when reachability is unknown
 | |
| 	ModeAutoServer
 | |
| )
 | |
| 
 | |
| // DefaultPrefix is the application specific prefix attached to all DHT protocols by default.
 | |
| const DefaultPrefix protocol.ID = "/ipfs"
 | |
| 
 | |
| type Option = dhtcfg.Option
 | |
| 
 | |
| // ProviderStore sets the provider storage manager.
 | |
| func ProviderStore(ps providers.ProviderStore) Option {
 | |
| 	return func(c *dhtcfg.Config) error {
 | |
| 		c.ProviderStore = ps
 | |
| 		return nil
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // RoutingTableLatencyTolerance sets the maximum acceptable latency for peers
 | |
| // in the routing table's cluster.
 | |
| func RoutingTableLatencyTolerance(latency time.Duration) Option {
 | |
| 	return func(c *dhtcfg.Config) error {
 | |
| 		c.RoutingTable.LatencyTolerance = latency
 | |
| 		return nil
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // RoutingTableRefreshQueryTimeout sets the timeout for routing table refresh
 | |
| // queries.
 | |
| func RoutingTableRefreshQueryTimeout(timeout time.Duration) Option {
 | |
| 	return func(c *dhtcfg.Config) error {
 | |
| 		c.RoutingTable.RefreshQueryTimeout = timeout
 | |
| 		return nil
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // RoutingTableRefreshPeriod sets the period for refreshing buckets in the
 | |
| // routing table. The DHT will refresh buckets every period by:
 | |
| //
 | |
| //  1. First searching for nearby peers to figure out how many buckets we should try to fill.
 | |
| //  1. Then searching for a random key in each bucket that hasn't been queried in
 | |
| //     the last refresh period.
 | |
| func RoutingTableRefreshPeriod(period time.Duration) Option {
 | |
| 	return func(c *dhtcfg.Config) error {
 | |
| 		c.RoutingTable.RefreshInterval = period
 | |
| 		return nil
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // Datastore configures the DHT to use the specified datastore.
 | |
| //
 | |
| // Defaults to an in-memory (temporary) map.
 | |
| func Datastore(ds ds.Batching) Option {
 | |
| 	return func(c *dhtcfg.Config) error {
 | |
| 		c.Datastore = ds
 | |
| 		return nil
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // Mode configures which mode the DHT operates in (Client, Server, Auto).
 | |
| //
 | |
| // Defaults to ModeAuto.
 | |
| func Mode(m ModeOpt) Option {
 | |
| 	return func(c *dhtcfg.Config) error {
 | |
| 		c.Mode = m
 | |
| 		return nil
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // Validator configures the DHT to use the specified validator.
 | |
| //
 | |
| // Defaults to a namespaced validator that can validate both public key (under the "pk"
 | |
| // namespace) and IPNS records (under the "ipns" namespace). Setting the validator
 | |
| // implies that the user wants to control the validators and therefore the default
 | |
| // public key and IPNS validators will not be added.
 | |
| func Validator(v record.Validator) Option {
 | |
| 	return func(c *dhtcfg.Config) error {
 | |
| 		c.Validator = v
 | |
| 		c.ValidatorChanged = true
 | |
| 		return nil
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // NamespacedValidator adds a validator namespaced under `ns`. This option fails
 | |
| // if the DHT is not using a `record.NamespacedValidator` as its validator (it
 | |
| // uses one by default but this can be overridden with the `Validator` option).
 | |
| // Adding a namespaced validator without changing the `Validator` will result in
 | |
| // adding a new validator in addition to the default public key and IPNS validators.
 | |
| // The "pk" and "ipns" namespaces cannot be overridden here unless a new `Validator`
 | |
| // has been set first.
 | |
| //
 | |
| // Example: Given a validator registered as `NamespacedValidator("ipns",
 | |
| // myValidator)`, all records with keys starting with `/ipns/` will be validated
 | |
| // with `myValidator`.
 | |
| func NamespacedValidator(ns string, v record.Validator) Option {
 | |
| 	return func(c *dhtcfg.Config) error {
 | |
| 		nsval, ok := c.Validator.(record.NamespacedValidator)
 | |
| 		if !ok {
 | |
| 			return fmt.Errorf("can only add namespaced validators to a NamespacedValidator")
 | |
| 		}
 | |
| 		nsval[ns] = v
 | |
| 		return nil
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // ProtocolPrefix sets an application specific prefix to be attached to all DHT protocols. For example,
 | |
| // /myapp/kad/1.0.0 instead of /ipfs/kad/1.0.0. Prefix should be of the form /myapp.
 | |
| //
 | |
| // Defaults to dht.DefaultPrefix
 | |
| func ProtocolPrefix(prefix protocol.ID) Option {
 | |
| 	return func(c *dhtcfg.Config) error {
 | |
| 		c.ProtocolPrefix = prefix
 | |
| 		return nil
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // ProtocolExtension adds an application specific protocol to the DHT protocol. For example,
 | |
| // /ipfs/lan/kad/1.0.0 instead of /ipfs/kad/1.0.0. extension should be of the form /lan.
 | |
| func ProtocolExtension(ext protocol.ID) Option {
 | |
| 	return func(c *dhtcfg.Config) error {
 | |
| 		c.ProtocolPrefix += ext
 | |
| 		return nil
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // V1ProtocolOverride overrides the protocolID used for /kad/1.0.0 with another. This is an
 | |
| // advanced feature, and should only be used to handle legacy networks that have not been
 | |
| // using protocolIDs of the form /app/kad/1.0.0.
 | |
| //
 | |
| // This option will override and ignore the ProtocolPrefix and ProtocolExtension options
 | |
| func V1ProtocolOverride(proto protocol.ID) Option {
 | |
| 	return func(c *dhtcfg.Config) error {
 | |
| 		c.V1ProtocolOverride = proto
 | |
| 		return nil
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // BucketSize configures the bucket size (k in the Kademlia paper) of the routing table.
 | |
| //
 | |
| // The default value is 20.
 | |
| func BucketSize(bucketSize int) Option {
 | |
| 	return func(c *dhtcfg.Config) error {
 | |
| 		c.BucketSize = bucketSize
 | |
| 		return nil
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // Concurrency configures the number of concurrent requests (alpha in the Kademlia paper) for a given query path.
 | |
| //
 | |
| // The default value is 10.
 | |
| func Concurrency(alpha int) Option {
 | |
| 	return func(c *dhtcfg.Config) error {
 | |
| 		c.Concurrency = alpha
 | |
| 		return nil
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // Resiliency configures the number of peers closest to a target that must have responded in order for a given query
 | |
| // path to complete.
 | |
| //
 | |
| // The default value is 3.
 | |
| func Resiliency(beta int) Option {
 | |
| 	return func(c *dhtcfg.Config) error {
 | |
| 		c.Resiliency = beta
 | |
| 		return nil
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // LookupInterval configures maximal number of go routines that can be used to
 | |
| // perform a lookup check operation, before adding a new node to the routing table.
 | |
| func LookupCheckConcurrency(n int) Option {
 | |
| 	return func(c *dhtcfg.Config) error {
 | |
| 		c.LookupCheckConcurrency = n
 | |
| 		return nil
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // MaxRecordAge specifies the maximum time that any node will hold onto a record ("PutValue record")
 | |
| // from the time its received. This does not apply to any other forms of validity that
 | |
| // the record may contain.
 | |
| // For example, a record may contain an ipns entry with an EOL saying its valid
 | |
| // until the year 2020 (a great time in the future). For that record to stick around
 | |
| // it must be rebroadcasted more frequently than once every 'MaxRecordAge'
 | |
| func MaxRecordAge(maxAge time.Duration) Option {
 | |
| 	return func(c *dhtcfg.Config) error {
 | |
| 		c.MaxRecordAge = maxAge
 | |
| 		return nil
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // DisableAutoRefresh completely disables 'auto-refresh' on the DHT routing
 | |
| // table. This means that we will neither refresh the routing table periodically
 | |
| // nor when the routing table size goes below the minimum threshold.
 | |
| func DisableAutoRefresh() Option {
 | |
| 	return func(c *dhtcfg.Config) error {
 | |
| 		c.RoutingTable.AutoRefresh = false
 | |
| 		return nil
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // DisableProviders disables storing and retrieving provider records.
 | |
| //
 | |
| // Defaults to enabled.
 | |
| //
 | |
| // WARNING: do not change this unless you're using a forked DHT (i.e., a private
 | |
| // network and/or distinct DHT protocols with the `Protocols` option).
 | |
| func DisableProviders() Option {
 | |
| 	return func(c *dhtcfg.Config) error {
 | |
| 		c.EnableProviders = false
 | |
| 		return nil
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // DisableValues disables storing and retrieving value records (including
 | |
| // public keys).
 | |
| //
 | |
| // Defaults to enabled.
 | |
| //
 | |
| // WARNING: do not change this unless you're using a forked DHT (i.e., a private
 | |
| // network and/or distinct DHT protocols with the `Protocols` option).
 | |
| func DisableValues() Option {
 | |
| 	return func(c *dhtcfg.Config) error {
 | |
| 		c.EnableValues = false
 | |
| 		return nil
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // QueryFilter sets a function that approves which peers may be dialed in a query
 | |
| func QueryFilter(filter QueryFilterFunc) Option {
 | |
| 	return func(c *dhtcfg.Config) error {
 | |
| 		c.QueryPeerFilter = filter
 | |
| 		return nil
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // RoutingTableFilter sets a function that approves which peers may be added to the routing table. The host should
 | |
| // already have at least one connection to the peer under consideration.
 | |
| func RoutingTableFilter(filter RouteTableFilterFunc) Option {
 | |
| 	return func(c *dhtcfg.Config) error {
 | |
| 		c.RoutingTable.PeerFilter = filter
 | |
| 		return nil
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // BootstrapPeers configures the bootstrapping nodes that we will connect to to seed
 | |
| // and refresh our Routing Table if it becomes empty.
 | |
| func BootstrapPeers(bootstrappers ...peer.AddrInfo) Option {
 | |
| 	return func(c *dhtcfg.Config) error {
 | |
| 		c.BootstrapPeers = func() []peer.AddrInfo {
 | |
| 			return bootstrappers
 | |
| 		}
 | |
| 		return nil
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // BootstrapPeersFunc configures the function that returns the bootstrapping nodes that we will
 | |
| // connect to to seed and refresh our Routing Table if it becomes empty.
 | |
| func BootstrapPeersFunc(getBootstrapPeers func() []peer.AddrInfo) Option {
 | |
| 	return func(c *dhtcfg.Config) error {
 | |
| 		c.BootstrapPeers = getBootstrapPeers
 | |
| 		return nil
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // RoutingTablePeerDiversityFilter configures the implementation of the `PeerIPGroupFilter` that will be used
 | |
| // to construct the diversity filter for the Routing Table.
 | |
| // Please see the docs for `peerdiversity.PeerIPGroupFilter` AND `peerdiversity.Filter` for more details.
 | |
| func RoutingTablePeerDiversityFilter(pg peerdiversity.PeerIPGroupFilter) Option {
 | |
| 	return func(c *dhtcfg.Config) error {
 | |
| 		c.RoutingTable.DiversityFilter = pg
 | |
| 		return nil
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // disableFixLowPeersRoutine disables the "fixLowPeers" routine in the DHT.
 | |
| // This is ONLY for tests.
 | |
| func disableFixLowPeersRoutine(t *testing.T) Option {
 | |
| 	return func(c *dhtcfg.Config) error {
 | |
| 		c.DisableFixLowPeers = true
 | |
| 		return nil
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // forceAddressUpdateProcessing forces the DHT to handle changes to the hosts addresses.
 | |
| // This occurs even when AutoRefresh has been disabled.
 | |
| // This is ONLY for tests.
 | |
| func forceAddressUpdateProcessing(t *testing.T) Option {
 | |
| 	return func(c *dhtcfg.Config) error {
 | |
| 		c.TestAddressUpdateProcessing = true
 | |
| 		return nil
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // EnableOptimisticProvide enables an optimization that skips the last hops of the provide process.
 | |
| // This works by using the network size estimator (which uses the keyspace density of queries)
 | |
| // to optimistically send ADD_PROVIDER requests when we most likely have found the last hop.
 | |
| // It will also run some ADD_PROVIDER requests asynchronously in the background after returning,
 | |
| // this allows to optimistically return earlier if some threshold number of RPCs have succeeded.
 | |
| // The number of background/in-flight queries can be configured with the OptimisticProvideJobsPoolSize
 | |
| // option.
 | |
| //
 | |
| // EXPERIMENTAL: This is an experimental option and might be removed in the future. Use at your own risk.
 | |
| func EnableOptimisticProvide() Option {
 | |
| 	return func(c *dhtcfg.Config) error {
 | |
| 		c.EnableOptimisticProvide = true
 | |
| 		return nil
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // OptimisticProvideJobsPoolSize allows to configure the asynchronicity limit for in-flight ADD_PROVIDER RPCs.
 | |
| // It makes sense to set it to a multiple of optProvReturnRatio * BucketSize. Check the description of
 | |
| // EnableOptimisticProvide for more details.
 | |
| //
 | |
| // EXPERIMENTAL: This is an experimental option and might be removed in the future. Use at your own risk.
 | |
| func OptimisticProvideJobsPoolSize(size int) Option {
 | |
| 	return func(c *dhtcfg.Config) error {
 | |
| 		c.OptimisticProvideJobsPoolSize = size
 | |
| 		return nil
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // AddressFilter allows to configure the address filtering function.
 | |
| // This function is run before addresses are added to the peerstore.
 | |
| // It is most useful to avoid adding localhost / local addresses.
 | |
| func AddressFilter(f func([]ma.Multiaddr) []ma.Multiaddr) Option {
 | |
| 	return func(c *dhtcfg.Config) error {
 | |
| 		c.AddressFilter = f
 | |
| 		return nil
 | |
| 	}
 | |
| }
 |