From 7c1e7672c94a6abd01c314f96ef530adbd52f573 Mon Sep 17 00:00:00 2001 From: Alex Mylonas Date: Thu, 12 Mar 2026 17:52:16 +0200 Subject: [PATCH 01/12] feat: Added resource profile cli option --- cli/config/config.go | 2 + cli/config_test.go | 1 + cli/start.go | 8 ++- client/options/node.go | 10 ++++ go.mod | 2 + go.sum | 4 +- node/node_p2p.go | 7 +++ node/resource_manager.go | 96 +++++++++++++++++++++++++++++++++++ node/resource_manager_test.go | 42 +++++++++++++++ 9 files changed, 169 insertions(+), 3 deletions(-) create mode 100644 node/resource_manager.go create mode 100644 node/resource_manager_test.go diff --git a/cli/config/config.go b/cli/config/config.go index a6d7b57c71..1143c294dd 100644 --- a/cli/config/config.go +++ b/cli/config/config.go @@ -62,6 +62,7 @@ var ConfigFlags = map[string]string{ "peers": "net.peers", "p2paddr": "net.p2paddresses", "no-p2p": "net.p2pdisabled", + "resource-profile": "net.resourceprofile", "allowed-origins": "api.allowed-origins", "pubkeypath": "api.pubkeypath", "privkeypath": "api.privkeypath", @@ -91,6 +92,7 @@ var ConfigDefaults = map[string]any{ "net.peers": []string{}, "net.pubSubEnabled": true, "net.relay": false, + "net.resourceprofile": "", "keyring.backend": "file", "keyring.disabled": false, "keyring.namespace": "defradb", diff --git a/cli/config_test.go b/cli/config_test.go index 4592cada46..44e4d06daf 100644 --- a/cli/config_test.go +++ b/cli/config_test.go @@ -57,6 +57,7 @@ func TestLoadConfigNotExist(t *testing.T) { assert.Equal(t, true, cfg.GetBool("net.pubsubenabled")) assert.Equal(t, false, cfg.GetBool("net.relay")) assert.Equal(t, []string{}, cfg.GetStringSlice("net.peers")) + assert.Equal(t, "", cfg.GetString("net.resourceprofile")) assert.Equal(t, "info", cfg.GetString("log.level")) assert.Equal(t, "stderr", cfg.GetString("log.output")) diff --git a/cli/start.go b/cli/start.go index 73ddf51213..77b0b1b847 100644 --- a/cli/start.go +++ b/cli/start.go @@ -102,7 +102,8 @@ func MakeStartCommand(ctx context.Context) *cobra.Command { SetListenAddresses(cfg.GetStringSlice("net.p2pAddresses")...). SetEnablePubSub(cfg.GetBool("net.pubSubEnabled")). SetEnableRelay(cfg.GetBool("net.relayEnabled")). - SetBootstrapPeers(cfg.GetStringSlice("net.peers")...) + SetBootstrapPeers(cfg.GetStringSlice("net.peers")...). + SetResourceProfile(cfg.GetString("net.resourceprofile")) opts.HTTP(). SetAddress(cfg.GetString("api.address")). SetAllowedOrigins(cfg.GetStringSlice("api.allowed-origins")...). @@ -284,6 +285,11 @@ func MakeStartCommand(ctx context.Context) *cobra.Command { cfg.GetBool(config.ConfigFlags["no-p2p"]), "Disable the peer-to-peer network synchronization system", ) + cmd.PersistentFlags().String( + "resource-profile", + cfg.GetString(config.ConfigFlags["resource-profile"]), + "Set the resource manager profile for the p2p network (supported: limited, server) (default \"\")", + ) cmd.PersistentFlags().StringArray( "allowed-origins", cfg.GetStringSlice(config.ConfigFlags["allowed-origins"]), diff --git a/client/options/node.go b/client/options/node.go index 43d63ee43b..9df1ce7c75 100644 --- a/client/options/node.go +++ b/client/options/node.go @@ -113,6 +113,9 @@ type NodeP2POptions struct { EnableClearBackoffOnRetry bool // PrivateKey is the private key for the P2P node. PrivateKey []byte + // ResourceProfile sets predefined resource manager limits for the P2P host. + // Valid values are "limited", "server", or "" (default autoscaling). + ResourceProfile string } // NodeHTTPOptions contains HTTP API server configuration values. @@ -508,6 +511,13 @@ func (sb *NodeP2POptionsBuilder) SetPrivateKey(key []byte) *NodeP2POptionsBuilde return sb } +// SetResourceProfile sets predefined resource manager limits for the P2P host. +// Valid values are "limited", "server", or "" (default autoscaling). +func (sb *NodeP2POptionsBuilder) SetResourceProfile(profile string) *NodeP2POptionsBuilder { + sb.append(func(opts *NodeP2POptions) { opts.ResourceProfile = profile }) + return sb +} + // SetAll sets all P2P options from a plain data struct. func (sb *NodeP2POptionsBuilder) SetAll(p2pOpts NodeP2POptions) *NodeP2POptionsBuilder { sb.append(func(opts *NodeP2POptions) { *opts = p2pOpts }) diff --git a/go.mod b/go.mod index 71c187f492..ff71e96c37 100644 --- a/go.mod +++ b/go.mod @@ -466,3 +466,5 @@ require ( ) replace github.com/wlynxg/anet => github.com/sourcenetwork/anet v0.0.0-20250417190629-7c87cba7799e + +replace github.com/sourcenetwork/go-p2p => github.com/alexmylonas/go-p2p v0.0.0-20260310235021-0e7341cfd30b diff --git a/go.sum b/go.sum index fae767a9e8..030c39abd6 100644 --- a/go.sum +++ b/go.sum @@ -745,6 +745,8 @@ github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk5 github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b h1:mimo19zliBX/vSQ6PWWSL9lK8qwHozUj03+zLoEB8O0= github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b/go.mod h1:fvzegU4vN3H1qMT+8wDmzjAcDONcgo2/SZ/TyfdUOFs= github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cvfHR56wJVlKE= +github.com/alexmylonas/go-p2p v0.0.0-20260310235021-0e7341cfd30b h1:n2+rlGPMNqNx2Mh5wC4Zr4HizhhkRS5tlMv1jhAzWho= +github.com/alexmylonas/go-p2p v0.0.0-20260310235021-0e7341cfd30b/go.mod h1:blpzi38QuKtN4Kb61OUZoJI9QSuRJ9LC1WZvhmFydwY= github.com/alingse/asasalint v0.0.10/go.mod h1:nCaoMhw7a9kSJObvQyVzNTPBDbNpdocqrSP7t/cW5+I= github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= github.com/andybalholm/brotli v1.0.3/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= @@ -2391,8 +2393,6 @@ github.com/sourcenetwork/corelog v0.0.8 h1:jCo0mFBpWrfhUCGzzN3uUtPGyQv3jnITdPO1s github.com/sourcenetwork/corelog v0.0.8/go.mod h1:cMabHgs3kARgYTQeQYSOmaGGP8XMU6sZrHd8LFrL3zA= github.com/sourcenetwork/go-libp2p-pubsub-rpc v0.0.14 h1:620zKV4rOn7U5j/WsPkk4SFj0z9/pVV4bBx0BpZQgro= github.com/sourcenetwork/go-libp2p-pubsub-rpc v0.0.14/go.mod h1:jUoQv592uUX1u7QBjAY4C+l24X9ArhPfifOqXpDHz4U= -github.com/sourcenetwork/go-p2p v0.1.9 h1:bM5FjPqBxNBQuWS4Rd7wQZqa342sD1A3M84U3Ihzee4= -github.com/sourcenetwork/go-p2p v0.1.9/go.mod h1:blpzi38QuKtN4Kb61OUZoJI9QSuRJ9LC1WZvhmFydwY= github.com/sourcenetwork/goji v0.0.9 h1:ObFC1PxstjGMoiCgJ+tqUALl0+sZFu5HHU7dCfpfgYc= github.com/sourcenetwork/goji v0.0.9/go.mod h1:A/dsoaCbLQ1a5PQfUVCA1zYMHnNAprVhZEmQHIlCfjE= github.com/sourcenetwork/goleveldb v0.0.0-20251217012629-27249d06b81b h1:DS+7xsNq0Q7AjBRMBr13CFn55eMPaGaJC8p5TMbcxmo= diff --git a/node/node_p2p.go b/node/node_p2p.go index 326cee7c7e..eccff97d3b 100644 --- a/node/node_p2p.go +++ b/node/node_p2p.go @@ -46,6 +46,13 @@ func (n *Node) startP2P(ctx context.Context, store corekv.ReaderWriter, chunkSiz if len(n.opts.P2P.PrivateKey) > 0 { p2pOpts = append(p2pOpts, p2p.WithPrivateKey(n.opts.P2P.PrivateKey)) } + if n.opts.P2P.ResourceProfile != "" { + rm, err := buildResourceManager(n.opts.P2P.ResourceProfile) + if err != nil { + return err + } + p2pOpts = append(p2pOpts, p2p.WithResourceManager(rm)) + } p2pOpts = append(p2pOpts, p2p.WithBlockstore(datastore.P2PBlockstoreFrom(store, chunkSize))) peer, err := p2p.NewPeer(ctx, p2pOpts...) diff --git a/node/resource_manager.go b/node/resource_manager.go new file mode 100644 index 0000000000..3ad6e6d73c --- /dev/null +++ b/node/resource_manager.go @@ -0,0 +1,96 @@ +// Copyright 2026 Democratized Data Foundation +// +// Use of this software is governed by the Business Source License +// included in the file licenses/BSL.txt. +// +// As of the Change Date specified in that file, in accordance with +// the Business Source License, use of this software will be governed +// by the Apache License, Version 2.0, included in the file +// licenses/APL.txt. + +// P2P networking stack does not work in JS builds. +// +//go:build !js + +package node + +import ( + "fmt" + + libp2p "github.com/libp2p/go-libp2p" + "github.com/libp2p/go-libp2p/core/network" + rcmgr "github.com/libp2p/go-libp2p/p2p/host/resource-manager" +) + +const ( + // ResourceProfileLimited applies conservative resource limits suitable for constrained hardware such as edge nodes + ResourceProfileLimited = "limited" + // ResourceProfileServer only applies limits per-peer, rest is autoscaled + ResourceProfileServer = "server" +) + +// resourceProfiles maps profile names to their PartialLimitConfig overrides. +var resourceProfiles = map[string]rcmgr.PartialLimitConfig{ + ResourceProfileLimited: { + System: rcmgr.ResourceLimits{ + ConnsInbound: 32, + ConnsOutbound: 64, + Conns: 64, + StreamsInbound: 32 * 16, + StreamsOutbound: 64 * 16, + Streams: 64 * 16, + Memory: 128 << 20, // minimal requirement + FD: 256, // minimal requirement + }, + Transient: rcmgr.ResourceLimits{ + ConnsInbound: 16, + ConnsOutbound: 32, + Conns: 32, + StreamsInbound: 64, + StreamsOutbound: 128, + Streams: 128, + Memory: 16 << 20, + FD: 32, + }, + PeerDefault: rcmgr.ResourceLimits{ + ConnsInbound: 4, + ConnsOutbound: 4, + Conns: 4, + StreamsInbound: 64, + StreamsOutbound: 128, + Streams: 128, + Memory: 64 << 20, + }, + }, + ResourceProfileServer: { + PeerDefault: rcmgr.ResourceLimits{ + ConnsInbound: 8, + ConnsOutbound: 8, + Conns: 8, + StreamsInbound: 512, + StreamsOutbound: 1024, + Streams: 1024, + Memory: 128 << 20, + }, + }, +} + +// buildResourceManager constructs a resource manager from the given profile name. +// If profile is empty, nil is returned and go-p2p will use libp2p's autoscaled defaults. +func buildResourceManager(profile string) (network.ResourceManager, error) { + if profile == "" { + return nil, nil + } + partial, ok := resourceProfiles[profile] + if !ok { + return nil, fmt.Errorf("unknown resource profile %q: valid values are %q, %q", + profile, ResourceProfileLimited, ResourceProfileServer) + } + limits := rcmgr.DefaultLimits + libp2p.SetDefaultServiceLimits(&limits) + rm, err := rcmgr.NewResourceManager(rcmgr.NewFixedLimiter(partial.Build(limits.AutoScale()))) + if err != nil { + return nil, err + } + return rm, nil +} diff --git a/node/resource_manager_test.go b/node/resource_manager_test.go new file mode 100644 index 0000000000..fda9f15579 --- /dev/null +++ b/node/resource_manager_test.go @@ -0,0 +1,42 @@ +// Copyright 2026 Democratized Data Foundation +// +// Use of this software is governed by the Business Source License +// included in the file licenses/BSL.txt. +// +// As of the Change Date specified in that file, in accordance with +// the Business Source License, use of this software will be governed +// by the Apache License, Version 2.0, included in the file +// licenses/APL.txt. + +package node + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestResourceManagerDefault(t *testing.T) { + rcmr, err := buildResourceManager("") + assert.Nil(t, rcmr) + assert.Nil(t, err) +} + +func TestResourceManagerLimited(t *testing.T) { + rcmr, err := buildResourceManager(ResourceProfileLimited) + assert.NoError(t, err) + assert.NotNil(t, rcmr) + +} + +func TestResourceManagerServer(t *testing.T) { + rcmr, err := buildResourceManager(ResourceProfileServer) + assert.NoError(t, err) + assert.NotNil(t, rcmr) +} + +func TestResourceManagerUnknown(t *testing.T) { + rcmr, err := buildResourceManager("unknown") + assert.Error(t, err) + assert.Nil(t, rcmr) +} From 3b135bdb0ce1a25bb58bcde33e04a9e4f5bbdac3 Mon Sep 17 00:00:00 2001 From: Alex Mylonas Date: Fri, 13 Mar 2026 01:07:27 +0200 Subject: [PATCH 02/12] Added unit tests for profile limits --- node/resource_manager_test.go | 94 +++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/node/resource_manager_test.go b/node/resource_manager_test.go index fda9f15579..3aeb08f3e2 100644 --- a/node/resource_manager_test.go +++ b/node/resource_manager_test.go @@ -11,9 +11,14 @@ package node import ( + "fmt" "testing" + "github.com/libp2p/go-libp2p/core/network" + "github.com/libp2p/go-libp2p/core/peer" + "github.com/multiformats/go-multiaddr" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestResourceManagerDefault(t *testing.T) { @@ -40,3 +45,92 @@ func TestResourceManagerUnknown(t *testing.T) { assert.Error(t, err) assert.Nil(t, rcmr) } + +func TestResourceManagerLimitedProfileTransientConnsInbound(t *testing.T) { + rm, err := buildResourceManager(ResourceProfileLimited) + require.NoError(t, err) + defer rm.Close() + + // limited profile sets Transient.ConnsInbound: 16 — . + conns := make([]network.ConnManagementScope, 16) + defer func() { + for _, c := range conns { + c.Done() + } + }() + for i := range conns { + // distinct IPs to avoid per IP limit + addr := multiaddr.StringCast(fmt.Sprintf("/ip4/1.2.3.%d/tcp/1234", i)) + conns[i], err = rm.OpenConnection(network.DirInbound, false, addr) + require.NoError(t, err) + } + + // 17th transient inbound connection should be rejected + addr := multiaddr.StringCast("/ip4/1.2.4.1/tcp/1234") + _, err = rm.OpenConnection(network.DirInbound, false, addr) + assert.Error(t, err, "should reject connection beyond inbound limit") +} + +func TestResourceManagerLimitedProfileSystemConnsInbound(t *testing.T) { + rm, err := buildResourceManager(ResourceProfileLimited) + require.NoError(t, err) + defer rm.Close() + + // limited profile sets ConnsInbound: 32 + conns := make([]network.ConnManagementScope, 32) + defer func() { + for _, c := range conns { + c.Done() + } + }() + + for i := range conns { + // distinct IPs to avoid per IP limit + addr := multiaddr.StringCast(fmt.Sprintf("/ip4/1.2.3.%d/tcp/1234", i)) + conns[i], err = rm.OpenConnection(network.DirInbound, false, addr) + require.NoError(t, err) + // SetPeer moves each connection out of transient scope so we can exercise the system peer limit. + err = conns[i].SetPeer(peer.ID(fmt.Sprintf("peer%d", i))) + require.NoError(t, err) + } + + // 33rd inbound connection should be rejected + addr := multiaddr.StringCast("/ip4/1.2.4.1/tcp/1234") + _, err = rm.OpenConnection(network.DirInbound, false, addr) + assert.Error(t, err, "should reject connection beyond inbound limit") +} + +func TestResourceManagerServerProfilePeerConnsInbound(t *testing.T) { + rm, err := buildResourceManager(ResourceProfileServer) + require.NoError(t, err) + defer rm.Close() + + peerID := peer.ID("peer0") + + // ServerProfile limits connections per peer to 8 + conns := make([]network.ConnManagementScope, 8) + defer func() { + for _, c := range conns { + c.Done() + } + }() + + for i := range conns { + // distinct IPs to avoid per IP limit + addr := multiaddr.StringCast(fmt.Sprintf("/ip4/1.2.3.%d/tcp/1234", i)) + conns[i], err = rm.OpenConnection(network.DirInbound, false, addr) + require.NoError(t, err) + err = conns[i].SetPeer(peerID) + require.NoError(t, err) + } + addr := multiaddr.StringCast("/ip4/1.2.4.1/tcp/1234") + c, err := rm.OpenConnection(network.DirInbound, false, addr) + require.NoError(t, err) + defer func() { + c.Done() + }() + + // Assigning connection to this peer will be rejected + err = c.SetPeer(peerID) + assert.Error(t, err, "should reject connection beyond per-peer inbound limit") +} From 84c4437065c725f7bb1164cd41a38d6e8267ece7 Mon Sep 17 00:00:00 2001 From: Alex Mylonas Date: Fri, 13 Mar 2026 01:07:45 +0200 Subject: [PATCH 03/12] Updated README --- README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.md b/README.md index c2eda53a06..861af09729 100644 --- a/README.md +++ b/README.md @@ -502,6 +502,20 @@ defradb start --allowed-origins=http://localhost:3000 The catch-all `*` is also a valid origin. +## P2P Resource Management + +By default, DefraDB autoscale the resource limits for p2p connections based on system availability. For deployments with specific resource constraints or performance requirements, the `--resource-profile` flag selects a predefined limit profile: + +``` +defradb start --resource-profile limited +``` + +| Profile | Use case | Description | +|---------|----------|-------------| +| *(unset)* | General | autoscaled defaults | +| `limited` | Edge nodes, constrained hardware | Conservative system-wide caps on connections, streams, and memory | +| `server` | High-throughput nodes | Per-peer connection and stream caps; system limits remain autoscaled | + ## Backing up and restoring It is currently not possible to do a full backup of DefraDB that includes the history of changes through the Merkle DAG. However, DefraDB currently supports a simple backup of the current data state in JSON format that can be used to seed a database or help with transitioning from one DefraDB version to another. From 4e347721d66cbec783f18a5546347cefd1a832fa Mon Sep 17 00:00:00 2001 From: Alex Mylonas Date: Mon, 16 Mar 2026 22:05:48 +0200 Subject: [PATCH 04/12] Remove empty string as valid opt for buildResourceManager --- node/resource_manager.go | 3 --- node/resource_manager_test.go | 6 ------ 2 files changed, 9 deletions(-) diff --git a/node/resource_manager.go b/node/resource_manager.go index 3ad6e6d73c..12a241514b 100644 --- a/node/resource_manager.go +++ b/node/resource_manager.go @@ -78,9 +78,6 @@ var resourceProfiles = map[string]rcmgr.PartialLimitConfig{ // buildResourceManager constructs a resource manager from the given profile name. // If profile is empty, nil is returned and go-p2p will use libp2p's autoscaled defaults. func buildResourceManager(profile string) (network.ResourceManager, error) { - if profile == "" { - return nil, nil - } partial, ok := resourceProfiles[profile] if !ok { return nil, fmt.Errorf("unknown resource profile %q: valid values are %q, %q", diff --git a/node/resource_manager_test.go b/node/resource_manager_test.go index 3aeb08f3e2..c43c176d2b 100644 --- a/node/resource_manager_test.go +++ b/node/resource_manager_test.go @@ -21,12 +21,6 @@ import ( "github.com/stretchr/testify/require" ) -func TestResourceManagerDefault(t *testing.T) { - rcmr, err := buildResourceManager("") - assert.Nil(t, rcmr) - assert.Nil(t, err) -} - func TestResourceManagerLimited(t *testing.T) { rcmr, err := buildResourceManager(ResourceProfileLimited) assert.NoError(t, err) From 616fced53ee7e52bc03c04e2a367a72790054fc4 Mon Sep 17 00:00:00 2001 From: Alex Mylonas Date: Mon, 16 Mar 2026 22:10:57 +0200 Subject: [PATCH 05/12] Updated rcmgr limits, inbound + outbound = total --- node/resource_manager.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/node/resource_manager.go b/node/resource_manager.go index 12a241514b..4ec30940fc 100644 --- a/node/resource_manager.go +++ b/node/resource_manager.go @@ -35,30 +35,30 @@ var resourceProfiles = map[string]rcmgr.PartialLimitConfig{ System: rcmgr.ResourceLimits{ ConnsInbound: 32, ConnsOutbound: 64, - Conns: 64, + Conns: 96, StreamsInbound: 32 * 16, StreamsOutbound: 64 * 16, - Streams: 64 * 16, + Streams: 96 * 16, Memory: 128 << 20, // minimal requirement FD: 256, // minimal requirement }, Transient: rcmgr.ResourceLimits{ ConnsInbound: 16, ConnsOutbound: 32, - Conns: 32, + Conns: 48, StreamsInbound: 64, StreamsOutbound: 128, - Streams: 128, + Streams: 196, Memory: 16 << 20, FD: 32, }, PeerDefault: rcmgr.ResourceLimits{ ConnsInbound: 4, ConnsOutbound: 4, - Conns: 4, + Conns: 8, StreamsInbound: 64, StreamsOutbound: 128, - Streams: 128, + Streams: 196, Memory: 64 << 20, }, }, From fccba40c3f61cf4bb7b3940a453622399c0ad14c Mon Sep 17 00:00:00 2001 From: Alex Mylonas Date: Mon, 16 Mar 2026 23:36:38 +0200 Subject: [PATCH 06/12] Addressed coderabbit feedback --- README.md | 7 ++++--- node/resource_manager.go | 5 ++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 861af09729..a5ea66284d 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,7 @@ Read the documentation on [docs.source.network](https://docs.source.network/). * [Securing the HTTP API with TLS](#securing-the-http-api-with-tls) * [Access Control System](#access-control-system) * [Supporting CORS](#supporting-cors) + * [P2P Resource Management](#p2p-resource-management) * [Backing up and restoring](#backing-up-and-restoring) * [Telemetry](#telemetry) * [Community](#community) @@ -504,9 +505,9 @@ The catch-all `*` is also a valid origin. ## P2P Resource Management -By default, DefraDB autoscale the resource limits for p2p connections based on system availability. For deployments with specific resource constraints or performance requirements, the `--resource-profile` flag selects a predefined limit profile: +By default, DefraDB autoscales the resource limits for p2p connections based on system availability. For deployments with specific resource constraints or performance requirements, the `--resource-profile` flag selects a predefined limit profile: -``` +```shell defradb start --resource-profile limited ``` @@ -514,7 +515,7 @@ defradb start --resource-profile limited |---------|----------|-------------| | *(unset)* | General | autoscaled defaults | | `limited` | Edge nodes, constrained hardware | Conservative system-wide caps on connections, streams, and memory | -| `server` | High-throughput nodes | Per-peer connection and stream caps; system limits remain autoscaled | +| `server` | High-throughput nodes | Per-peer connections, stream and memory caps; system limits remain autoscaled | ## Backing up and restoring diff --git a/node/resource_manager.go b/node/resource_manager.go index 4ec30940fc..f388142ba3 100644 --- a/node/resource_manager.go +++ b/node/resource_manager.go @@ -48,7 +48,7 @@ var resourceProfiles = map[string]rcmgr.PartialLimitConfig{ Conns: 48, StreamsInbound: 64, StreamsOutbound: 128, - Streams: 196, + Streams: 192, Memory: 16 << 20, FD: 32, }, @@ -58,7 +58,7 @@ var resourceProfiles = map[string]rcmgr.PartialLimitConfig{ Conns: 8, StreamsInbound: 64, StreamsOutbound: 128, - Streams: 196, + Streams: 192, Memory: 64 << 20, }, }, @@ -76,7 +76,6 @@ var resourceProfiles = map[string]rcmgr.PartialLimitConfig{ } // buildResourceManager constructs a resource manager from the given profile name. -// If profile is empty, nil is returned and go-p2p will use libp2p's autoscaled defaults. func buildResourceManager(profile string) (network.ResourceManager, error) { partial, ok := resourceProfiles[profile] if !ok { From 0b66ee2522f8a48cd1eee2e9267743b45aa8f32a Mon Sep 17 00:00:00 2001 From: Alex Mylonas Date: Tue, 17 Mar 2026 10:02:13 +0200 Subject: [PATCH 07/12] Updated limits for server profile --- node/resource_manager.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/node/resource_manager.go b/node/resource_manager.go index f388142ba3..ae6d2953a9 100644 --- a/node/resource_manager.go +++ b/node/resource_manager.go @@ -66,10 +66,10 @@ var resourceProfiles = map[string]rcmgr.PartialLimitConfig{ PeerDefault: rcmgr.ResourceLimits{ ConnsInbound: 8, ConnsOutbound: 8, - Conns: 8, + Conns: 16, StreamsInbound: 512, StreamsOutbound: 1024, - Streams: 1024, + Streams: 1536, Memory: 128 << 20, }, }, From 6a67dc046f160320b4c3c61292aac24c2e56ec27 Mon Sep 17 00:00:00 2001 From: Alex Mylonas Date: Fri, 20 Mar 2026 19:19:36 +0200 Subject: [PATCH 08/12] Refactor ResourceManager as ResourceProfile --- go.mod | 19 +++-- go.sum | 52 ++++++-------- node/node_p2p.go | 4 +- node/resource_manager.go | 92 ------------------------ node/resource_manager_test.go | 130 ---------------------------------- node/resource_profile.go | 54 ++++++++++++++ node/resource_profile_test.go | 39 ++++++++++ 7 files changed, 124 insertions(+), 266 deletions(-) delete mode 100644 node/resource_manager.go delete mode 100644 node/resource_manager_test.go create mode 100644 node/resource_profile.go create mode 100644 node/resource_profile_test.go diff --git a/go.mod b/go.mod index ff71e96c37..0774bed49c 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/sourcenetwork/defradb -go 1.25.5 +go 1.25.7 require ( github.com/bits-and-blooms/bitset v1.24.4 @@ -31,7 +31,7 @@ require ( github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20250821084354-a425e60cd714 github.com/joho/godotenv v1.5.1 github.com/lestrrat-go/jwx/v2 v2.1.6 - github.com/libp2p/go-libp2p v0.47.0 + github.com/libp2p/go-libp2p v0.48.0 github.com/multiformats/go-multiaddr v0.16.1 github.com/multiformats/go-multibase v0.2.0 github.com/multiformats/go-multicodec v0.10.0 @@ -102,7 +102,9 @@ require ( cosmossdk.io/x/tx v0.14.0 // indirect cosmossdk.io/x/upgrade v0.1.4 // indirect dario.cat/mergo v1.0.2 // indirect + filippo.io/bigmod v0.1.1-0.20260103110540-f8a47775ebe5 // indirect filippo.io/edwards25519 v1.1.1 // indirect + filippo.io/keygen v0.0.0-20260114151900-8e2790ea4c5b // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/99designs/keyring v1.2.2 // indirect github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect @@ -347,21 +349,18 @@ require ( github.com/perimeterx/marshmallow v1.1.5 // indirect github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pion/datachannel v1.5.10 // indirect - github.com/pion/dtls/v2 v2.2.12 // indirect - github.com/pion/dtls/v3 v3.1.1 // indirect + github.com/pion/dtls/v3 v3.1.2 // indirect github.com/pion/ice/v4 v4.0.10 // indirect github.com/pion/interceptor v0.1.41 // indirect github.com/pion/logging v0.2.4 // indirect github.com/pion/mdns/v2 v2.0.7 // indirect github.com/pion/randutil v0.1.0 // indirect - github.com/pion/rtcp v1.2.15 // indirect + github.com/pion/rtcp v1.2.16 // indirect github.com/pion/rtp v1.8.22 // indirect github.com/pion/sctp v1.8.39 // indirect - github.com/pion/sdp/v3 v3.0.16 // indirect + github.com/pion/sdp/v3 v3.0.18 // indirect github.com/pion/srtp/v3 v3.0.8 // indirect - github.com/pion/stun v0.6.1 // indirect - github.com/pion/stun/v3 v3.0.0 // indirect - github.com/pion/transport/v2 v2.2.10 // indirect + github.com/pion/stun/v3 v3.1.1 // indirect github.com/pion/transport/v3 v3.0.8 // indirect github.com/pion/transport/v4 v4.0.1 // indirect github.com/pion/turn/v4 v4.1.1 // indirect @@ -467,4 +466,4 @@ require ( replace github.com/wlynxg/anet => github.com/sourcenetwork/anet v0.0.0-20250417190629-7c87cba7799e -replace github.com/sourcenetwork/go-p2p => github.com/alexmylonas/go-p2p v0.0.0-20260310235021-0e7341cfd30b +replace github.com/sourcenetwork/go-p2p => github.com/alexmylonas/go-p2p v0.0.0-20260320165929-6c5461abc636 diff --git a/go.sum b/go.sum index 030c39abd6..f57e46948f 100644 --- a/go.sum +++ b/go.sum @@ -656,8 +656,12 @@ cosmossdk.io/x/upgrade v0.1.4/go.mod h1:9v0Aj+fs97O+Ztw+tG3/tp5JSlrmT7IcFhAebQHm dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +filippo.io/bigmod v0.1.1-0.20260103110540-f8a47775ebe5 h1:JA0fFr+kxpqTdxR9LOBiTWpGNchqmkcsgmdeJZRclZ0= +filippo.io/bigmod v0.1.1-0.20260103110540-f8a47775ebe5/go.mod h1:OjOXDNlClLblvXdwgFFOQFJEocLhhtai8vGLy0JCZlI= filippo.io/edwards25519 v1.1.1 h1:YpjwWWlNmGIDyXOn8zLzqiD+9TyIlPhGFG96P39uBpw= filippo.io/edwards25519 v1.1.1/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +filippo.io/keygen v0.0.0-20260114151900-8e2790ea4c5b h1:REI1FbdW71yO56Are4XAxD+OS/e+BQsB3gE4mZRQEXY= +filippo.io/keygen v0.0.0-20260114151900-8e2790ea4c5b/go.mod h1:9nnw1SlYHYuPSo/3wjQzNjSbeHlq2NsKo5iEtfJPWP0= gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -745,8 +749,8 @@ github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk5 github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b h1:mimo19zliBX/vSQ6PWWSL9lK8qwHozUj03+zLoEB8O0= github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b/go.mod h1:fvzegU4vN3H1qMT+8wDmzjAcDONcgo2/SZ/TyfdUOFs= github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cvfHR56wJVlKE= -github.com/alexmylonas/go-p2p v0.0.0-20260310235021-0e7341cfd30b h1:n2+rlGPMNqNx2Mh5wC4Zr4HizhhkRS5tlMv1jhAzWho= -github.com/alexmylonas/go-p2p v0.0.0-20260310235021-0e7341cfd30b/go.mod h1:blpzi38QuKtN4Kb61OUZoJI9QSuRJ9LC1WZvhmFydwY= +github.com/alexmylonas/go-p2p v0.0.0-20260320165929-6c5461abc636 h1:XV/W5ptksV6J8HDF/v0w0pfDYGrc3tb1JMqxoWExnok= +github.com/alexmylonas/go-p2p v0.0.0-20260320165929-6c5461abc636/go.mod h1:Qnzt1YBv4YnnJpyGN6RH33o6z4oIulETOh3/efpoy6I= github.com/alingse/asasalint v0.0.10/go.mod h1:nCaoMhw7a9kSJObvQyVzNTPBDbNpdocqrSP7t/cW5+I= github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= github.com/andybalholm/brotli v1.0.3/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= @@ -851,6 +855,8 @@ github.com/bytedance/sonic v1.14.2 h1:k1twIoe97C1DtYUo+fZQy865IuHia4PR5RPiuGPPII github.com/bytedance/sonic v1.14.2/go.mod h1:T80iDELeHiHKSc0C9tubFygiuXoGzrkjKzX2quAx980= github.com/bytedance/sonic/loader v0.4.0 h1:olZ7lEqcxtZygCK9EKYKADnpQoYkRQxaeY2NYzevs+o= github.com/bytedance/sonic/loader v0.4.0/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo= +github.com/canonical/go-sp800.90a-drbg v0.0.0-20210314144037-6eeb1040d6c3 h1:oe6fCvaEpkhyW3qAicT0TnGtyht/UrgvOwMcEgLb7Aw= +github.com/canonical/go-sp800.90a-drbg v0.0.0-20210314144037-6eeb1040d6c3/go.mod h1:qdP0gaj0QtgX2RUZhnlVrceJ+Qln8aSlDyJwelLLFeM= github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= github.com/casbin/casbin/v2 v2.37.0/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= @@ -1807,8 +1813,8 @@ github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38y github.com/libp2p/go-cidranger v1.1.0/go.mod h1:KWZTfSr+r9qEo9OkI9/SIEeAtw+NNoU0dXIXt15Okic= github.com/libp2p/go-flow-metrics v0.3.0 h1:q31zcHUvHnwDO0SHaukewPYgwOBSxtt830uJtUx6784= github.com/libp2p/go-flow-metrics v0.3.0/go.mod h1:nuhlreIwEguM1IvHAew3ij7A8BMlyHQJ279ao24eZZo= -github.com/libp2p/go-libp2p v0.47.0 h1:qQpBjSCWNQFF0hjBbKirMXE9RHLtSuzTDkTfr1rw0yc= -github.com/libp2p/go-libp2p v0.47.0/go.mod h1:s8HPh7mMV933OtXzONaGFseCg/BE//m1V34p3x4EUOY= +github.com/libp2p/go-libp2p v0.48.0 h1:h2BrLAgrj7X8bEN05K7qmrjpNHYA+6tnsGRdprjTnvo= +github.com/libp2p/go-libp2p v0.48.0/go.mod h1:Q1fBZNdmC2Hf82husCTfkKJVfHm2we5zk+NWmOGEmWk= github.com/libp2p/go-libp2p-asn-util v0.4.1 h1:xqL7++IKD9TBFMgnLPZR6/6iYhawHKHl950SO9L6n94= github.com/libp2p/go-libp2p-asn-util v0.4.1/go.mod h1:d/NI6XZ9qxw67b4e+NgpQexCIiFYJjErASrYW4PFDN8= github.com/libp2p/go-libp2p-kad-dht v0.38.0 h1:NToFzwvICo6ghDfSwuTmROCtl9LDXSZT1VawEbm4NUs= @@ -2150,40 +2156,30 @@ github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4 github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= github.com/pion/datachannel v1.5.10 h1:ly0Q26K1i6ZkGf42W7D4hQYR90pZwzFOjTq5AuCKk4o= github.com/pion/datachannel v1.5.10/go.mod h1:p/jJfC9arb29W7WrxyKbepTU20CFgyx5oLo8Rs4Py/M= -github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s= -github.com/pion/dtls/v2 v2.2.12 h1:KP7H5/c1EiVAAKUmXyCzPiQe5+bCJrpOeKg/L05dunk= -github.com/pion/dtls/v2 v2.2.12/go.mod h1:d9SYc9fch0CqK90mRk1dC7AkzzpwJj6u2GU3u+9pqFE= -github.com/pion/dtls/v3 v3.1.1 h1:wSLMam9Kf7DL1A74hnqRvEb9OT+aXPAsQ5VS+BdXOJ0= -github.com/pion/dtls/v3 v3.1.1/go.mod h1:7FGvVYpHsUV6+aywaFpG7aE4Vz8nBOx74odPRFue6cI= +github.com/pion/dtls/v3 v3.1.2 h1:gqEdOUXLtCGW+afsBLO0LtDD8GnuBBjEy6HRtyofZTc= +github.com/pion/dtls/v3 v3.1.2/go.mod h1:Hw/igcX4pdY69z1Hgv5x7wJFrUkdgHwAn/Q/uo7YHRo= github.com/pion/ice/v4 v4.0.10 h1:P59w1iauC/wPk9PdY8Vjl4fOFL5B+USq1+xbDcN6gT4= github.com/pion/ice/v4 v4.0.10/go.mod h1:y3M18aPhIxLlcO/4dn9X8LzLLSma84cx6emMSu14FGw= github.com/pion/interceptor v0.1.41 h1:NpvX3HgWIukTf2yTBVjVGFXtpSpWgXjqz7IIpu7NsOw= github.com/pion/interceptor v0.1.41/go.mod h1:nEt4187unvRXJFyjiw00GKo+kIuXMWQI9K89fsosDLY= -github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= github.com/pion/logging v0.2.4 h1:tTew+7cmQ+Mc1pTBLKH2puKsOvhm32dROumOZ655zB8= github.com/pion/logging v0.2.4/go.mod h1:DffhXTKYdNZU+KtJ5pyQDjvOAh/GsNSyv1lbkFbe3so= github.com/pion/mdns/v2 v2.0.7 h1:c9kM8ewCgjslaAmicYMFQIde2H9/lrZpjBkN8VwoVtM= github.com/pion/mdns/v2 v2.0.7/go.mod h1:vAdSYNAT0Jy3Ru0zl2YiW3Rm/fJCwIeM0nToenfOJKA= github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA= github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8= -github.com/pion/rtcp v1.2.15 h1:LZQi2JbdipLOj4eBjK4wlVoQWfrZbh3Q6eHtWtJBZBo= -github.com/pion/rtcp v1.2.15/go.mod h1:jlGuAjHMEXwMUHK78RgX0UmEJFV4zUKOFHR7OP+D3D0= +github.com/pion/rtcp v1.2.16 h1:fk1B1dNW4hsI78XUCljZJlC4kZOPk67mNRuQ0fcEkSo= +github.com/pion/rtcp v1.2.16/go.mod h1:/as7VKfYbs5NIb4h6muQ35kQF/J0ZVNz2Z3xKoCBYOo= github.com/pion/rtp v1.8.22 h1:8NCVDDF+uSJmMUkjLJVnIr/HX7gPesyMV1xFt5xozXc= github.com/pion/rtp v1.8.22/go.mod h1:rF5nS1GqbR7H/TCpKwylzeq6yDM+MM6k+On5EgeThEM= github.com/pion/sctp v1.8.39 h1:PJma40vRHa3UTO3C4MyeJDQ+KIobVYRZQZ0Nt7SjQnE= github.com/pion/sctp v1.8.39/go.mod h1:cNiLdchXra8fHQwmIoqw0MbLLMs+f7uQ+dGMG2gWebE= -github.com/pion/sdp/v3 v3.0.16 h1:0dKzYO6gTAvuLaAKQkC02eCPjMIi4NuAr/ibAwrGDCo= -github.com/pion/sdp/v3 v3.0.16/go.mod h1:9tyKzznud3qiweZcD86kS0ff1pGYB3VX+Bcsmkx6IXo= +github.com/pion/sdp/v3 v3.0.18 h1:l0bAXazKHpepazVdp+tPYnrsy9dfh7ZbT8DxesH5ZnI= +github.com/pion/sdp/v3 v3.0.18/go.mod h1:ZREGo6A9ZygQ9XkqAj5xYCQtQpif0i6Pa81HOiAdqQ8= github.com/pion/srtp/v3 v3.0.8 h1:RjRrjcIeQsilPzxvdaElN0CpuQZdMvcl9VZ5UY9suUM= github.com/pion/srtp/v3 v3.0.8/go.mod h1:2Sq6YnDH7/UDCvkSoHSDNDeyBcFgWL0sAVycVbAsXFg= -github.com/pion/stun v0.6.1 h1:8lp6YejULeHBF8NmV8e2787BogQhduZugh5PdhDyyN4= -github.com/pion/stun v0.6.1/go.mod h1:/hO7APkX4hZKu/D0f2lHzNyvdkTGtIy3NDmLR7kSz/8= -github.com/pion/stun/v3 v3.0.0 h1:4h1gwhWLWuZWOJIJR9s2ferRO+W3zA/b6ijOI6mKzUw= -github.com/pion/stun/v3 v3.0.0/go.mod h1:HvCN8txt8mwi4FBvS3EmDghW6aQJ24T+y+1TKjB5jyU= -github.com/pion/transport/v2 v2.2.1/go.mod h1:cXXWavvCnFF6McHTft3DWS9iic2Mftcz1Aq29pGcU5g= -github.com/pion/transport/v2 v2.2.4/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0= -github.com/pion/transport/v2 v2.2.10 h1:ucLBLE8nuxiHfvkFKnkDQRYWYfp8ejf4YBOPfaQpw6Q= -github.com/pion/transport/v2 v2.2.10/go.mod h1:sq1kSLWs+cHW9E+2fJP95QudkzbK7wscs8yYgQToO5E= +github.com/pion/stun/v3 v3.1.1 h1:CkQxveJ4xGQjulGSROXbXq94TAWu8gIX2dT+ePhUkqw= +github.com/pion/stun/v3 v3.1.1/go.mod h1:qC1DfmcCTQjl9PBaMa5wSn3x9IPmKxSdcCsxBcDBndM= github.com/pion/transport/v3 v3.0.8 h1:oI3myyYnTKUSTthu/NZZ8eu2I5sHbxbUNNFW62olaYc= github.com/pion/transport/v3 v3.0.8/go.mod h1:+c2eewC5WJQHiAA46fkMMzoYZSuGzA/7E2FPrOYHctQ= github.com/pion/transport/v4 v4.0.1 h1:sdROELU6BZ63Ab7FrOLn13M6YdJLY20wldXW2Cu2k8o= @@ -2751,10 +2747,7 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= -golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= -golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= @@ -2910,9 +2903,7 @@ golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= -golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= @@ -3112,9 +3103,7 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= @@ -3136,9 +3125,7 @@ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= -golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek= @@ -3160,7 +3147,6 @@ golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= @@ -3303,6 +3289,8 @@ golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da h1:noIWHXmPHxILtqtCOPIhSt0ABwskkZKjD3bXGnZGpNY= +golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= gonum.org/v1/gonum v0.9.3/go.mod h1:TZumC3NeyVQskjXqmyWt4S3bINhy7B4eYwW69EbyX+0= diff --git a/node/node_p2p.go b/node/node_p2p.go index eccff97d3b..2bd5fc5964 100644 --- a/node/node_p2p.go +++ b/node/node_p2p.go @@ -47,11 +47,11 @@ func (n *Node) startP2P(ctx context.Context, store corekv.ReaderWriter, chunkSiz p2pOpts = append(p2pOpts, p2p.WithPrivateKey(n.opts.P2P.PrivateKey)) } if n.opts.P2P.ResourceProfile != "" { - rm, err := buildResourceManager(n.opts.P2P.ResourceProfile) + limits, err := resourceLimitsForProfile(n.opts.P2P.ResourceProfile) if err != nil { return err } - p2pOpts = append(p2pOpts, p2p.WithResourceManager(rm)) + p2pOpts = append(p2pOpts, p2p.WithResourceLimits(limits)) } p2pOpts = append(p2pOpts, p2p.WithBlockstore(datastore.P2PBlockstoreFrom(store, chunkSize))) diff --git a/node/resource_manager.go b/node/resource_manager.go deleted file mode 100644 index ae6d2953a9..0000000000 --- a/node/resource_manager.go +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright 2026 Democratized Data Foundation -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -// P2P networking stack does not work in JS builds. -// -//go:build !js - -package node - -import ( - "fmt" - - libp2p "github.com/libp2p/go-libp2p" - "github.com/libp2p/go-libp2p/core/network" - rcmgr "github.com/libp2p/go-libp2p/p2p/host/resource-manager" -) - -const ( - // ResourceProfileLimited applies conservative resource limits suitable for constrained hardware such as edge nodes - ResourceProfileLimited = "limited" - // ResourceProfileServer only applies limits per-peer, rest is autoscaled - ResourceProfileServer = "server" -) - -// resourceProfiles maps profile names to their PartialLimitConfig overrides. -var resourceProfiles = map[string]rcmgr.PartialLimitConfig{ - ResourceProfileLimited: { - System: rcmgr.ResourceLimits{ - ConnsInbound: 32, - ConnsOutbound: 64, - Conns: 96, - StreamsInbound: 32 * 16, - StreamsOutbound: 64 * 16, - Streams: 96 * 16, - Memory: 128 << 20, // minimal requirement - FD: 256, // minimal requirement - }, - Transient: rcmgr.ResourceLimits{ - ConnsInbound: 16, - ConnsOutbound: 32, - Conns: 48, - StreamsInbound: 64, - StreamsOutbound: 128, - Streams: 192, - Memory: 16 << 20, - FD: 32, - }, - PeerDefault: rcmgr.ResourceLimits{ - ConnsInbound: 4, - ConnsOutbound: 4, - Conns: 8, - StreamsInbound: 64, - StreamsOutbound: 128, - Streams: 192, - Memory: 64 << 20, - }, - }, - ResourceProfileServer: { - PeerDefault: rcmgr.ResourceLimits{ - ConnsInbound: 8, - ConnsOutbound: 8, - Conns: 16, - StreamsInbound: 512, - StreamsOutbound: 1024, - Streams: 1536, - Memory: 128 << 20, - }, - }, -} - -// buildResourceManager constructs a resource manager from the given profile name. -func buildResourceManager(profile string) (network.ResourceManager, error) { - partial, ok := resourceProfiles[profile] - if !ok { - return nil, fmt.Errorf("unknown resource profile %q: valid values are %q, %q", - profile, ResourceProfileLimited, ResourceProfileServer) - } - limits := rcmgr.DefaultLimits - libp2p.SetDefaultServiceLimits(&limits) - rm, err := rcmgr.NewResourceManager(rcmgr.NewFixedLimiter(partial.Build(limits.AutoScale()))) - if err != nil { - return nil, err - } - return rm, nil -} diff --git a/node/resource_manager_test.go b/node/resource_manager_test.go deleted file mode 100644 index c43c176d2b..0000000000 --- a/node/resource_manager_test.go +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright 2026 Democratized Data Foundation -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -package node - -import ( - "fmt" - "testing" - - "github.com/libp2p/go-libp2p/core/network" - "github.com/libp2p/go-libp2p/core/peer" - "github.com/multiformats/go-multiaddr" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestResourceManagerLimited(t *testing.T) { - rcmr, err := buildResourceManager(ResourceProfileLimited) - assert.NoError(t, err) - assert.NotNil(t, rcmr) - -} - -func TestResourceManagerServer(t *testing.T) { - rcmr, err := buildResourceManager(ResourceProfileServer) - assert.NoError(t, err) - assert.NotNil(t, rcmr) -} - -func TestResourceManagerUnknown(t *testing.T) { - rcmr, err := buildResourceManager("unknown") - assert.Error(t, err) - assert.Nil(t, rcmr) -} - -func TestResourceManagerLimitedProfileTransientConnsInbound(t *testing.T) { - rm, err := buildResourceManager(ResourceProfileLimited) - require.NoError(t, err) - defer rm.Close() - - // limited profile sets Transient.ConnsInbound: 16 — . - conns := make([]network.ConnManagementScope, 16) - defer func() { - for _, c := range conns { - c.Done() - } - }() - for i := range conns { - // distinct IPs to avoid per IP limit - addr := multiaddr.StringCast(fmt.Sprintf("/ip4/1.2.3.%d/tcp/1234", i)) - conns[i], err = rm.OpenConnection(network.DirInbound, false, addr) - require.NoError(t, err) - } - - // 17th transient inbound connection should be rejected - addr := multiaddr.StringCast("/ip4/1.2.4.1/tcp/1234") - _, err = rm.OpenConnection(network.DirInbound, false, addr) - assert.Error(t, err, "should reject connection beyond inbound limit") -} - -func TestResourceManagerLimitedProfileSystemConnsInbound(t *testing.T) { - rm, err := buildResourceManager(ResourceProfileLimited) - require.NoError(t, err) - defer rm.Close() - - // limited profile sets ConnsInbound: 32 - conns := make([]network.ConnManagementScope, 32) - defer func() { - for _, c := range conns { - c.Done() - } - }() - - for i := range conns { - // distinct IPs to avoid per IP limit - addr := multiaddr.StringCast(fmt.Sprintf("/ip4/1.2.3.%d/tcp/1234", i)) - conns[i], err = rm.OpenConnection(network.DirInbound, false, addr) - require.NoError(t, err) - // SetPeer moves each connection out of transient scope so we can exercise the system peer limit. - err = conns[i].SetPeer(peer.ID(fmt.Sprintf("peer%d", i))) - require.NoError(t, err) - } - - // 33rd inbound connection should be rejected - addr := multiaddr.StringCast("/ip4/1.2.4.1/tcp/1234") - _, err = rm.OpenConnection(network.DirInbound, false, addr) - assert.Error(t, err, "should reject connection beyond inbound limit") -} - -func TestResourceManagerServerProfilePeerConnsInbound(t *testing.T) { - rm, err := buildResourceManager(ResourceProfileServer) - require.NoError(t, err) - defer rm.Close() - - peerID := peer.ID("peer0") - - // ServerProfile limits connections per peer to 8 - conns := make([]network.ConnManagementScope, 8) - defer func() { - for _, c := range conns { - c.Done() - } - }() - - for i := range conns { - // distinct IPs to avoid per IP limit - addr := multiaddr.StringCast(fmt.Sprintf("/ip4/1.2.3.%d/tcp/1234", i)) - conns[i], err = rm.OpenConnection(network.DirInbound, false, addr) - require.NoError(t, err) - err = conns[i].SetPeer(peerID) - require.NoError(t, err) - } - addr := multiaddr.StringCast("/ip4/1.2.4.1/tcp/1234") - c, err := rm.OpenConnection(network.DirInbound, false, addr) - require.NoError(t, err) - defer func() { - c.Done() - }() - - // Assigning connection to this peer will be rejected - err = c.SetPeer(peerID) - assert.Error(t, err, "should reject connection beyond per-peer inbound limit") -} diff --git a/node/resource_profile.go b/node/resource_profile.go new file mode 100644 index 0000000000..2ea246f342 --- /dev/null +++ b/node/resource_profile.go @@ -0,0 +1,54 @@ +// Copyright 2026 Democratized Data Foundation +// +// Use of this software is governed by the Business Source License +// included in the file licenses/BSL.txt. +// +// As of the Change Date specified in that file, in accordance with +// the Business Source License, use of this software will be governed +// by the Apache License, Version 2.0, included in the file +// licenses/APL.txt. + +// P2P networking stack does not work in JS builds. +// +//go:build !js + +package node + +import ( + "fmt" + + p2p "github.com/sourcenetwork/go-p2p" +) + +const ( + // ResourceProfileLimited applies conservative resource limits suitable for + // constrained or low-power hardware. + ResourceProfileLimited = "limited" + // ResourceProfileServer applies generous resource limits suitable for + // always-on server nodes. + ResourceProfileServer = "server" +) + +// resourceProfiles maps profile names to their resource limits. +// Connection limits are derived automatically from MaxMemory. +var resourceProfiles = map[string]p2p.ResourceLimits{ + ResourceProfileLimited: { + MaxMemory: 128 << 20, // 128 MiB + MaxFileDescriptors: 256, + }, + ResourceProfileServer: { + MaxMemory: 8 << 30, // 8 GiB + }, +} + +// resourceLimitsForProfile returns the resource limits for the given profile name. +func resourceLimitsForProfile(profile string) (p2p.ResourceLimits, error) { + limits, ok := resourceProfiles[profile] + if !ok { + return p2p.ResourceLimits{}, fmt.Errorf( + "unknown resource profile %q: valid values are %q, %q", + profile, ResourceProfileLimited, ResourceProfileServer, + ) + } + return limits, nil +} diff --git a/node/resource_profile_test.go b/node/resource_profile_test.go new file mode 100644 index 0000000000..5447d2536b --- /dev/null +++ b/node/resource_profile_test.go @@ -0,0 +1,39 @@ +// Copyright 2026 Democratized Data Foundation +// +// Use of this software is governed by the Business Source License +// included in the file licenses/BSL.txt. +// +// As of the Change Date specified in that file, in accordance with +// the Business Source License, use of this software will be governed +// by the Apache License, Version 2.0, included in the file +// licenses/APL.txt. + +// P2P networking stack does not work in JS builds. +// +//go:build !js + +package node + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestResourceLimitsForProfile_Limited(t *testing.T) { + limits, err := resourceLimitsForProfile(ResourceProfileLimited) + require.NoError(t, err) + assert.Equal(t, int64(128<<20), limits.MaxMemory) +} + +func TestResourceLimitsForProfile_Server(t *testing.T) { + limits, err := resourceLimitsForProfile(ResourceProfileServer) + require.NoError(t, err) + assert.Equal(t, int64(16<<30), limits.MaxMemory) +} + +func TestResourceLimitsForProfile_Unknown(t *testing.T) { + _, err := resourceLimitsForProfile("unknown") + assert.Error(t, err) +} From a739fbf37253f2cd65e14c1bd6779c95419b89fe Mon Sep 17 00:00:00 2001 From: Alex Mylonas Date: Fri, 20 Mar 2026 19:45:06 +0200 Subject: [PATCH 09/12] Addressed feedback --- cli/start.go | 2 +- client/options/node.go | 4 ++-- node/errors.go | 5 +++++ node/resource_profile.go | 7 +------ 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/cli/start.go b/cli/start.go index 77b0b1b847..eb2dbf92cd 100644 --- a/cli/start.go +++ b/cli/start.go @@ -288,7 +288,7 @@ func MakeStartCommand(ctx context.Context) *cobra.Command { cmd.PersistentFlags().String( "resource-profile", cfg.GetString(config.ConfigFlags["resource-profile"]), - "Set the resource manager profile for the p2p network (supported: limited, server) (default \"\")", + "Set the resource manager profile for the p2p network (supported: limited, server)", ) cmd.PersistentFlags().StringArray( "allowed-origins", diff --git a/client/options/node.go b/client/options/node.go index 9df1ce7c75..dd522845c7 100644 --- a/client/options/node.go +++ b/client/options/node.go @@ -113,8 +113,8 @@ type NodeP2POptions struct { EnableClearBackoffOnRetry bool // PrivateKey is the private key for the P2P node. PrivateKey []byte - // ResourceProfile sets predefined resource manager limits for the P2P host. - // Valid values are "limited", "server", or "" (default autoscaling). + // ResourceProfile sets predefined resource limits for the P2P host. + // Valid values are "limited" and "server". ResourceProfile string } diff --git a/node/errors.go b/node/errors.go index 168ab1ba38..c1ede772e7 100644 --- a/node/errors.go +++ b/node/errors.go @@ -19,6 +19,7 @@ const ( errStoreTypeNotSupported string = "the selected store type is not supported by this build" errACPTypeNotSupported string = "the selected acp type is not supported by this build" errNodeACPTypeNotSupported string = "the selected node acp type is not supported by this build" + errUnknownResourceProfile string = "the selected resource profile is not supported by this build" ) var ( @@ -35,3 +36,7 @@ func NewErrStoreTypeNotSupported(store options.NodeStoreType) error { func NewErrACPTypeNotSupported(acp options.NodeDocumentACPType) error { return errors.New(errACPTypeNotSupported, errors.NewKV("ACP", acp)) } + +func NewErrUnknownResourceProfile(profile string) error { + return errors.New(errUnknownResourceProfile, errors.NewKV("Profile", profile)) +} diff --git a/node/resource_profile.go b/node/resource_profile.go index 2ea246f342..4af583e716 100644 --- a/node/resource_profile.go +++ b/node/resource_profile.go @@ -15,8 +15,6 @@ package node import ( - "fmt" - p2p "github.com/sourcenetwork/go-p2p" ) @@ -45,10 +43,7 @@ var resourceProfiles = map[string]p2p.ResourceLimits{ func resourceLimitsForProfile(profile string) (p2p.ResourceLimits, error) { limits, ok := resourceProfiles[profile] if !ok { - return p2p.ResourceLimits{}, fmt.Errorf( - "unknown resource profile %q: valid values are %q, %q", - profile, ResourceProfileLimited, ResourceProfileServer, - ) + return p2p.ResourceLimits{}, NewErrUnknownResourceProfile(profile) } return limits, nil } From 975a18be5def6f9a536363fd3af5a4dae9f454e2 Mon Sep 17 00:00:00 2001 From: Alex Mylonas Date: Fri, 20 Mar 2026 19:50:28 +0200 Subject: [PATCH 10/12] updated code comment --- node/resource_profile.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/node/resource_profile.go b/node/resource_profile.go index 4af583e716..959542c5c3 100644 --- a/node/resource_profile.go +++ b/node/resource_profile.go @@ -20,10 +20,9 @@ import ( const ( // ResourceProfileLimited applies conservative resource limits suitable for - // constrained or low-power hardware. + // constrained. ResourceProfileLimited = "limited" - // ResourceProfileServer applies generous resource limits suitable for - // always-on server nodes. + // ResourceProfileServer applies a max memory of 8GiB for p2p host. ResourceProfileServer = "server" ) From 594849798bd42897a565fcf7a642c029d984d083 Mon Sep 17 00:00:00 2001 From: Alex Mylonas Date: Fri, 20 Mar 2026 19:56:25 +0200 Subject: [PATCH 11/12] Updated outdated test --- node/resource_profile_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/node/resource_profile_test.go b/node/resource_profile_test.go index 5447d2536b..71fda6de62 100644 --- a/node/resource_profile_test.go +++ b/node/resource_profile_test.go @@ -30,7 +30,7 @@ func TestResourceLimitsForProfile_Limited(t *testing.T) { func TestResourceLimitsForProfile_Server(t *testing.T) { limits, err := resourceLimitsForProfile(ResourceProfileServer) require.NoError(t, err) - assert.Equal(t, int64(16<<30), limits.MaxMemory) + assert.Equal(t, int64(8<<30), limits.MaxMemory) } func TestResourceLimitsForProfile_Unknown(t *testing.T) { From 6be8b8f3564dc197eb2e6bace5ef9b622df08400 Mon Sep 17 00:00:00 2001 From: Alex Mylonas Date: Fri, 20 Mar 2026 20:01:21 +0200 Subject: [PATCH 12/12] Updated code comment --- node/resource_profile.go | 1 - 1 file changed, 1 deletion(-) diff --git a/node/resource_profile.go b/node/resource_profile.go index 959542c5c3..94ed78723f 100644 --- a/node/resource_profile.go +++ b/node/resource_profile.go @@ -27,7 +27,6 @@ const ( ) // resourceProfiles maps profile names to their resource limits. -// Connection limits are derived automatically from MaxMemory. var resourceProfiles = map[string]p2p.ResourceLimits{ ResourceProfileLimited: { MaxMemory: 128 << 20, // 128 MiB