From e8feae11347d98e661326deff15002e1cfcf1386 Mon Sep 17 00:00:00 2001 From: Gary Malouf <982483+gmalouf@users.noreply.github.com> Date: Wed, 10 Jul 2024 13:31:44 -0400 Subject: [PATCH 1/9] Introduce profiles for hybridRelay, hybridArchival, and hybridClient. --- cmd/algocfg/profileCommand.go | 72 ++++++++++++++++++++++++++---- cmd/algocfg/profileCommand_test.go | 61 +++++++++++++++++++++++++ 2 files changed, 125 insertions(+), 8 deletions(-) diff --git a/cmd/algocfg/profileCommand.go b/cmd/algocfg/profileCommand.go index 4cd9bf5c9e..b669030845 100644 --- a/cmd/algocfg/profileCommand.go +++ b/cmd/algocfg/profileCommand.go @@ -66,8 +66,8 @@ var ( }, } - relay = configUpdater{ - description: "Relay consensus messages across the network and support catchup.", + wsRelay = configUpdater{ + description: "Relay consensus messages across the ws network and support recent catchup.", updateFunc: func(cfg config.Local) config.Local { cfg.MaxBlockHistoryLookback = 22000 // Enough to support 2 catchpoints with some wiggle room for nodes to catch up from the older one cfg.CatchpointFileHistoryLength = 3 @@ -80,7 +80,7 @@ var ( } archival = configUpdater{ - description: "Store the full chain history and support catchup.", + description: "Store the full chain history and support full catchup.", updateFunc: func(cfg config.Local) config.Local { cfg.Archival = true cfg.EnableLedgerService = true @@ -91,13 +91,69 @@ var ( }, } + hybridRelay = configUpdater{ + description: "Relay consensus messages across both ws and p2p networks, also support recent catchup.", + updateFunc: func(cfg config.Local) config.Local { + // WS relay config defaults + cfg.MaxBlockHistoryLookback = 22000 // Enough to support 2 catchpoints with some wiggle room for nodes to catch up from the older one + cfg.CatchpointFileHistoryLength = 3 + cfg.CatchpointTracking = 2 + cfg.EnableLedgerService = true + cfg.EnableBlockService = true + cfg.NetAddress = ":4160" + // This should be set to the public address of the node if public access is desired + cfg.PublicAddress = "PLEASE_SET_ME" + + // P2P config defaults + cfg.EnableP2PHybridMode = true + cfg.P2PNetAddress = ":4190" + cfg.EnableDHTProviders = true + return cfg + }, + } + + hybridArchival = configUpdater{ + description: "Store the full chain history, support full catchup, P2P enabled, discoverable via DHT.", + updateFunc: func(cfg config.Local) config.Local { + cfg.Archival = true + cfg.EnableLedgerService = true + cfg.EnableBlockService = true + cfg.NetAddress = ":4160" + cfg.EnableGossipService = false + // This should be set to the public address of the node if public access is desired + cfg.PublicAddress = "PLEASE_SET_ME" + + // P2P config defaults + cfg.EnableP2PHybridMode = true + cfg.P2PNetAddress = ":4190" + cfg.EnableDHTProviders = true + return cfg + }, + } + + hybridClient = configUpdater{ + description: "Participate in consensus or simply ensure chain health by validating blocks and supporting P2P traffic propagation.", + updateFunc: func(cfg config.Local) config.Local { + + // P2P config defaults + cfg.EnableP2PHybridMode = true + cfg.P2PNetAddress = ":4190" + cfg.EnableDHTProviders = true + + return cfg + }, + } + // profileNames are the supported pre-configurations of config values profileNames = map[string]configUpdater{ - "participation": participation, - "conduit": conduit, - "relay": relay, - "archival": archival, - "development": development, + "participation": participation, + "conduit": conduit, + "wsRelay": wsRelay, + "archival": archival, + "development": development, + "hybridRelay": hybridRelay, + "hybridArchival": hybridArchival, + "hybridClient": hybridClient, } forceUpdate bool diff --git a/cmd/algocfg/profileCommand_test.go b/cmd/algocfg/profileCommand_test.go index d8bf715534..eb5264a2d5 100644 --- a/cmd/algocfg/profileCommand_test.go +++ b/cmd/algocfg/profileCommand_test.go @@ -62,4 +62,65 @@ func Test_getConfigForArg(t *testing.T) { require.Equal(t, ":4160", cfg.NetAddress) require.False(t, cfg.EnableGossipService) }) + + t.Run("valid config test hybrid relay", func(t *testing.T) { + t.Parallel() + cfg, err := getConfigForArg("hybridRelay") + require.NoError(t, err) + + require.False(t, cfg.Archival) + require.Equal(t, uint64(22000), cfg.MaxBlockHistoryLookback) + require.Equal(t, 3, cfg.CatchpointFileHistoryLength) + require.Equal(t, int64(2), cfg.CatchpointTracking) + require.True(t, cfg.EnableLedgerService) + require.True(t, cfg.EnableBlockService) + require.Equal(t, ":4160", cfg.NetAddress) + require.True(t, cfg.EnableGossipService) + require.Equal(t, "PLEASE_SET_ME", cfg.PublicAddress) + + require.True(t, cfg.EnableP2PHybridMode) + require.Equal(t, ":4190", cfg.P2PNetAddress) + require.True(t, cfg.EnableDHTProviders) + }) + + t.Run("valid config test hybrid archival", func(t *testing.T) { + t.Parallel() + cfg, err := getConfigForArg("hybridArchival") + require.NoError(t, err) + + require.True(t, cfg.Archival) + require.Equal(t, uint64(0), cfg.MaxBlockHistoryLookback) + require.Equal(t, 365, cfg.CatchpointFileHistoryLength) + require.Equal(t, int64(0), cfg.CatchpointTracking) + require.True(t, cfg.EnableLedgerService) + require.True(t, cfg.EnableBlockService) + require.Equal(t, ":4160", cfg.NetAddress) + require.False(t, cfg.EnableGossipService) + require.Equal(t, "PLEASE_SET_ME", cfg.PublicAddress) + + require.True(t, cfg.EnableP2PHybridMode) + require.Equal(t, ":4190", cfg.P2PNetAddress) + require.True(t, cfg.EnableDHTProviders) + }) + + t.Run("valid config test hybrid client", func(t *testing.T) { + t.Parallel() + cfg, err := getConfigForArg("hybridClient") + require.NoError(t, err) + + require.False(t, cfg.Archival) + require.Equal(t, uint64(0), cfg.MaxBlockHistoryLookback) + require.Equal(t, 365, cfg.CatchpointFileHistoryLength) + require.Equal(t, int64(0), cfg.CatchpointTracking) + require.False(t, cfg.EnableLedgerService) + require.False(t, cfg.EnableBlockService) + require.Empty(t, cfg.NetAddress) + // True because it is the default value, net address is blank so has no effect in practice + require.True(t, cfg.EnableGossipService) + require.Equal(t, "", cfg.PublicAddress) + + require.True(t, cfg.EnableP2PHybridMode) + require.Equal(t, ":4190", cfg.P2PNetAddress) + require.True(t, cfg.EnableDHTProviders) + }) } From a9c883dd35e74986fe0f39aa2a944b9f8d3cc814 Mon Sep 17 00:00:00 2001 From: chris erway Date: Wed, 17 Jul 2024 10:31:10 -0400 Subject: [PATCH 2/9] no listening if NetAddress not set --- network/p2p/p2p.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/network/p2p/p2p.go b/network/p2p/p2p.go index 2877c6b2f3..f67f79f427 100644 --- a/network/p2p/p2p.go +++ b/network/p2p/p2p.go @@ -112,7 +112,8 @@ func MakeHost(cfg config.Local, datadir string, pstore *pstore.PeerStore) (host. listenAddr = parsedListenAddr } } else { - listenAddr = "/ip4/0.0.0.0/tcp/0" + // don't listen if NetAddress is not set. + listenAddr = "" } var disableMetrics = func(cfg *libp2p.Config) error { return nil } @@ -163,6 +164,11 @@ func MakeService(ctx context.Context, log logging.Logger, cfg config.Local, h ho // Start starts the P2P service func (s *serviceImpl) Start() error { + if s.listenAddr == "" { + // don't listen if no listen address configured + return nil + } + listenAddr, err := multiaddr.NewMultiaddr(s.listenAddr) if err != nil { s.log.Errorf("failed to create multiaddress: %s", err) From ab10873ebc7c66296c921429ee7fc4445b7a3ba6 Mon Sep 17 00:00:00 2001 From: chris erway Date: Wed, 17 Jul 2024 12:32:58 -0400 Subject: [PATCH 3/9] fix test by not listening in httpThread --- network/p2pNetwork.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/network/p2pNetwork.go b/network/p2pNetwork.go index 1ad49bd045..c0e1a8c922 100644 --- a/network/p2pNetwork.go +++ b/network/p2pNetwork.go @@ -471,6 +471,10 @@ func (n *P2PNetwork) meshThread() { func (n *P2PNetwork) httpdThread() { defer n.wg.Done() + if n.config.NetAddress == "" { + // don't start HTTP server if not configured to listen + return + } err := n.httpServer.Serve() if err != nil { n.log.Errorf("Error serving libp2phttp: %v", err) From f18f899911b158c1f857bf361622907ce9b907fa Mon Sep 17 00:00:00 2001 From: Gary Malouf <982483+gmalouf@users.noreply.github.com> Date: Wed, 17 Jul 2024 12:37:24 -0400 Subject: [PATCH 4/9] Abstract out placeholder constant to variable, remove desetting P2P listen port for hybridClient profile. --- cmd/algocfg/profileCommand.go | 5 ++--- cmd/algocfg/profileCommand_test.go | 7 ++++--- config/config.go | 3 +++ 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/cmd/algocfg/profileCommand.go b/cmd/algocfg/profileCommand.go index b669030845..3d5105be55 100644 --- a/cmd/algocfg/profileCommand.go +++ b/cmd/algocfg/profileCommand.go @@ -120,8 +120,8 @@ var ( cfg.EnableBlockService = true cfg.NetAddress = ":4160" cfg.EnableGossipService = false - // This should be set to the public address of the node if public access is desired - cfg.PublicAddress = "PLEASE_SET_ME" + // This should be set to the public address of the node + cfg.PublicAddress = config.PlaceholderPublicAddress // P2P config defaults cfg.EnableP2PHybridMode = true @@ -137,7 +137,6 @@ var ( // P2P config defaults cfg.EnableP2PHybridMode = true - cfg.P2PNetAddress = ":4190" cfg.EnableDHTProviders = true return cfg diff --git a/cmd/algocfg/profileCommand_test.go b/cmd/algocfg/profileCommand_test.go index eb5264a2d5..8d7d95a26e 100644 --- a/cmd/algocfg/profileCommand_test.go +++ b/cmd/algocfg/profileCommand_test.go @@ -17,6 +17,7 @@ package main import ( + "github.com/algorand/go-algorand/config" "testing" "github.com/stretchr/testify/require" @@ -76,7 +77,7 @@ func Test_getConfigForArg(t *testing.T) { require.True(t, cfg.EnableBlockService) require.Equal(t, ":4160", cfg.NetAddress) require.True(t, cfg.EnableGossipService) - require.Equal(t, "PLEASE_SET_ME", cfg.PublicAddress) + require.Equal(t, config.PlaceholderPublicAddress, cfg.PublicAddress) require.True(t, cfg.EnableP2PHybridMode) require.Equal(t, ":4190", cfg.P2PNetAddress) @@ -96,7 +97,7 @@ func Test_getConfigForArg(t *testing.T) { require.True(t, cfg.EnableBlockService) require.Equal(t, ":4160", cfg.NetAddress) require.False(t, cfg.EnableGossipService) - require.Equal(t, "PLEASE_SET_ME", cfg.PublicAddress) + require.Equal(t, config.PlaceholderPublicAddress, cfg.PublicAddress) require.True(t, cfg.EnableP2PHybridMode) require.Equal(t, ":4190", cfg.P2PNetAddress) @@ -120,7 +121,7 @@ func Test_getConfigForArg(t *testing.T) { require.Equal(t, "", cfg.PublicAddress) require.True(t, cfg.EnableP2PHybridMode) - require.Equal(t, ":4190", cfg.P2PNetAddress) + require.Equal(t, "", cfg.P2PNetAddress) require.True(t, cfg.EnableDHTProviders) }) } diff --git a/config/config.go b/config/config.go index 2d5d0bdbfe..10b90475fe 100644 --- a/config/config.go +++ b/config/config.go @@ -104,6 +104,9 @@ const CatchpointTrackingModeTracked = 1 // as long as CatchpointInterval > 0 const CatchpointTrackingModeStored = 2 +// PlaceholderPublicAddress is a placeholder for the public address generated in certain profiles +const PlaceholderPublicAddress = "PLEASE_SET_ME" + // LoadConfigFromDisk returns a Local config structure based on merging the defaults // with settings loaded from the config file from the custom dir. If the custom file // cannot be loaded, the default config is returned (with the error from loading the From e70d2258f6699f07dbfeabd7d66bd40403763e42 Mon Sep 17 00:00:00 2001 From: Gary Malouf <982483+gmalouf@users.noreply.github.com> Date: Wed, 17 Jul 2024 15:09:25 -0400 Subject: [PATCH 5/9] Update p2pnetwork tests to handle not setting a randomly selected listen port when NetAddress is not set in p2p mode. --- network/p2pNetwork_test.go | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/network/p2pNetwork_test.go b/network/p2pNetwork_test.go index 5b3470689f..f94783dd29 100644 --- a/network/p2pNetwork_test.go +++ b/network/p2pNetwork_test.go @@ -67,6 +67,7 @@ func TestP2PSubmitTX(t *testing.T) { cfg := config.GetDefaultLocal() cfg.ForceFetchTransactions = true + cfg.NetAddress = "127.0.0.1:0" log := logging.TestingLog(t) netA, err := NewP2PNetwork(log, cfg, "", nil, genesisID, config.Devtestnet, &nopeNodeInfo{}) require.NoError(t, err) @@ -159,6 +160,7 @@ func TestP2PSubmitTXNoGossip(t *testing.T) { cfg := config.GetDefaultLocal() cfg.ForceFetchTransactions = true + cfg.NetAddress = "127.0.0.1:0" log := logging.TestingLog(t) netA, err := NewP2PNetwork(log, cfg, "", nil, genesisID, config.Devtestnet, &nopeNodeInfo{}) require.NoError(t, err) @@ -189,6 +191,8 @@ func TestP2PSubmitTXNoGossip(t *testing.T) { // run netC in NPN mode (no relay => no gossip sup => no TX receiving) cfg.ForceFetchTransactions = false + // Have to unset NetAddress to get IsGossipServer to return false + cfg.NetAddress = "" netC, err := NewP2PNetwork(log, cfg, "", phoneBookAddresses, genesisID, config.Devtestnet, &nopeNodeInfo{}) require.NoError(t, err) netC.Start() @@ -253,6 +257,7 @@ func TestP2PSubmitWS(t *testing.T) { partitiontest.PartitionTest(t) cfg := config.GetDefaultLocal() + cfg.NetAddress = "127.0.0.1:0" log := logging.TestingLog(t) netA, err := NewP2PNetwork(log, cfg, "", nil, genesisID, config.Devtestnet, &nopeNodeInfo{}) require.NoError(t, err) @@ -584,6 +589,7 @@ func TestP2PNetworkDHTCapabilities(t *testing.T) { partitiontest.PartitionTest(t) cfg := config.GetDefaultLocal() + cfg.NetAddress = "127.0.0.1:0" cfg.EnableDHTProviders = true log := logging.TestingLog(t) @@ -744,6 +750,7 @@ func TestP2PHTTPHandler(t *testing.T) { cfg := config.GetDefaultLocal() cfg.EnableDHTProviders = true cfg.GossipFanout = 1 + cfg.NetAddress = "127.0.0.1:0" log := logging.TestingLog(t) netA, err := NewP2PNetwork(log, cfg, "", nil, genesisID, config.Devtestnet, &nopeNodeInfo{}) @@ -812,6 +819,7 @@ func TestP2PRelay(t *testing.T) { cfg.DNSBootstrapID = "" // disable DNS lookups since the test uses phonebook addresses cfg.ForceFetchTransactions = true cfg.BaseLoggerDebugLevel = 5 + cfg.NetAddress = "127.0.0.1:0" log := logging.TestingLog(t) log.Debugln("Starting netA") netA, err := NewP2PNetwork(log.With("net", "netA"), cfg, "", nil, genesisID, config.Devtestnet, &nopeNodeInfo{}) @@ -829,6 +837,8 @@ func TestP2PRelay(t *testing.T) { multiAddrStr := addrsA[0].String() phoneBookAddresses := []string{multiAddrStr} + // Explicitly unset NetAddress for netB + cfg.NetAddress = "" log.Debugf("Starting netB with phonebook addresses %v", phoneBookAddresses) netB, err := NewP2PNetwork(log.With("net", "netB"), cfg, "", phoneBookAddresses, genesisID, config.Devtestnet, &nopeNodeInfo{}) require.NoError(t, err) @@ -880,8 +890,8 @@ func TestP2PRelay(t *testing.T) { counterHandler, counterDone := makeCounterHandler(1, &counter, nil) netA.RegisterProcessors(counterHandler) - // send 5 messages from both netB to netA - // since there is no node with listening address set => no messages should be received + // send 5 messages from netB to netA + // since relaying is disabled on net B => no messages should be received by net A for i := 0; i < 5; i++ { err := netB.Relay(context.Background(), protocol.TxnTag, []byte{1, 2, 3, byte(i)}, true, nil) require.NoError(t, err) @@ -1031,6 +1041,7 @@ func TestP2PWantTXGossip(t *testing.T) { net.wantTXGossip.Store(true) net.nodeInfo = &nopeNodeInfo{} net.config.ForceFetchTransactions = false + net.config.NetAddress = "" net.relayMessages = false net.OnNetworkAdvance() require.Eventually(t, func() bool { net.wg.Wait(); return true }, 1*time.Second, 50*time.Millisecond) @@ -1040,6 +1051,7 @@ func TestP2PWantTXGossip(t *testing.T) { net.wantTXGossip.Store(false) net.nodeInfo = &nopeNodeInfo{} net.config.ForceFetchTransactions = true + net.config.NetAddress = "127.0.0.1:0" net.relayMessages = false net.OnNetworkAdvance() require.Eventually(t, func() bool { return mockService.count.Load() == 2 }, 1*time.Second, 50*time.Millisecond) @@ -1048,6 +1060,7 @@ func TestP2PWantTXGossip(t *testing.T) { net.wantTXGossip.Store(false) net.nodeInfo = &nopeNodeInfo{} net.config.ForceFetchTransactions = false + net.config.NetAddress = "" net.relayMessages = true net.OnNetworkAdvance() require.Eventually(t, func() bool { return mockService.count.Load() == 3 }, 1*time.Second, 50*time.Millisecond) From 1191e2335808c8e80b54bf69ffff04a96c024a99 Mon Sep 17 00:00:00 2001 From: Gary Malouf <982483+gmalouf@users.noreply.github.com> Date: Thu, 18 Jul 2024 10:34:08 -0400 Subject: [PATCH 6/9] Update cmd/algocfg/profileCommand.go Co-authored-by: Pavel Zbitskiy <65323360+algorandskiy@users.noreply.github.com> --- cmd/algocfg/profileCommand.go | 1 - 1 file changed, 1 deletion(-) diff --git a/cmd/algocfg/profileCommand.go b/cmd/algocfg/profileCommand.go index 3d5105be55..60c25244db 100644 --- a/cmd/algocfg/profileCommand.go +++ b/cmd/algocfg/profileCommand.go @@ -138,7 +138,6 @@ var ( // P2P config defaults cfg.EnableP2PHybridMode = true cfg.EnableDHTProviders = true - return cfg }, } From a8b89ff3f9b5b5f0d0a42dec252ad5906301b82b Mon Sep 17 00:00:00 2001 From: Gary Malouf <982483+gmalouf@users.noreply.github.com> Date: Thu, 18 Jul 2024 10:37:09 -0400 Subject: [PATCH 7/9] Remove unneeded NetAddress in p2p test. --- network/p2pNetwork_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/network/p2pNetwork_test.go b/network/p2pNetwork_test.go index f94783dd29..ff1f40a63c 100644 --- a/network/p2pNetwork_test.go +++ b/network/p2pNetwork_test.go @@ -1051,7 +1051,6 @@ func TestP2PWantTXGossip(t *testing.T) { net.wantTXGossip.Store(false) net.nodeInfo = &nopeNodeInfo{} net.config.ForceFetchTransactions = true - net.config.NetAddress = "127.0.0.1:0" net.relayMessages = false net.OnNetworkAdvance() require.Eventually(t, func() bool { return mockService.count.Load() == 2 }, 1*time.Second, 50*time.Millisecond) From 9e0fce5fe5906496b2286ed341e1dc45ffe713a0 Mon Sep 17 00:00:00 2001 From: Gary Malouf <982483+gmalouf@users.noreply.github.com> Date: Thu, 18 Jul 2024 12:59:08 -0400 Subject: [PATCH 8/9] Only start p2p http thread if NetAddress is set. Treat PublicAddress with 'placeholder' set as if it was empty. --- config/config.go | 5 +++++ network/p2pNetwork.go | 12 ++++++------ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/config/config.go b/config/config.go index 10b90475fe..87440cc58a 100644 --- a/config/config.go +++ b/config/config.go @@ -148,6 +148,11 @@ func mergeConfigFromFile(configpath string, source Local) (Local, error) { err = loadConfig(f, &source) + // If the PublicAddress in config file has the PlaceholderPublicAddress, treat it as if it were empty + if source.PublicAddress == PlaceholderPublicAddress { + source.PublicAddress = "" + } + if source.NetAddress != "" { source.EnableLedgerService = true source.EnableBlockService = true diff --git a/network/p2pNetwork.go b/network/p2pNetwork.go index c0e1a8c922..4d6efdac83 100644 --- a/network/p2pNetwork.go +++ b/network/p2pNetwork.go @@ -346,8 +346,11 @@ func (n *P2PNetwork) Start() error { go n.handler.messageHandlerThread(&n.wg, n.wsPeersConnectivityCheckTicker.C, n, "network", "P2PNetwork") } - n.wg.Add(1) - go n.httpdThread() + // start the HTTP server if configured to listen + if n.config.NetAddress != "" { + n.wg.Add(1) + go n.httpdThread() + } n.wg.Add(1) go n.broadcaster.broadcastThread(&n.wg, n, "network", "P2PNetwork") @@ -471,10 +474,7 @@ func (n *P2PNetwork) meshThread() { func (n *P2PNetwork) httpdThread() { defer n.wg.Done() - if n.config.NetAddress == "" { - // don't start HTTP server if not configured to listen - return - } + err := n.httpServer.Serve() if err != nil { n.log.Errorf("Error serving libp2phttp: %v", err) From 02a4f93927b1767447f047a7e46d36662bb90700 Mon Sep 17 00:00:00 2001 From: Gary Malouf <982483+gmalouf@users.noreply.github.com> Date: Thu, 18 Jul 2024 14:06:19 -0400 Subject: [PATCH 9/9] Update cmd/algocfg/profileCommand.go Co-authored-by: Pavel Zbitskiy <65323360+algorandskiy@users.noreply.github.com> --- cmd/algocfg/profileCommand.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/algocfg/profileCommand.go b/cmd/algocfg/profileCommand.go index 60c25244db..076cb65a64 100644 --- a/cmd/algocfg/profileCommand.go +++ b/cmd/algocfg/profileCommand.go @@ -102,7 +102,7 @@ var ( cfg.EnableBlockService = true cfg.NetAddress = ":4160" // This should be set to the public address of the node if public access is desired - cfg.PublicAddress = "PLEASE_SET_ME" + cfg.PublicAddress = config.PlaceholderPublicAddress // P2P config defaults cfg.EnableP2PHybridMode = true