From b1894d9b8d2c9e84b023270c1693e6657d6dbf77 Mon Sep 17 00:00:00 2001 From: ohill <145173879+ohill@users.noreply.github.com> Date: Tue, 14 Nov 2023 17:02:12 -0500 Subject: [PATCH 1/3] config: add EnableGossipService option --- config/localTemplate.go | 6 +- config/local_defaults.go | 3 +- installer/config.json.example | 3 +- network/wsNetwork.go | 9 +- test/testdata/configs/config-v33.json | 140 ++++++++++++++++++++++++++ 5 files changed, 157 insertions(+), 4 deletions(-) create mode 100644 test/testdata/configs/config-v33.json diff --git a/config/localTemplate.go b/config/localTemplate.go index 6748801209..d35bf105bf 100644 --- a/config/localTemplate.go +++ b/config/localTemplate.go @@ -42,7 +42,7 @@ type Local struct { // Version tracks the current version of the defaults so we can migrate old -> new // This is specifically important whenever we decide to change the default value // for an existing parameter. This field tag must be updated any time we add a new version. - Version uint32 `version[0]:"0" version[1]:"1" version[2]:"2" version[3]:"3" version[4]:"4" version[5]:"5" version[6]:"6" version[7]:"7" version[8]:"8" version[9]:"9" version[10]:"10" version[11]:"11" version[12]:"12" version[13]:"13" version[14]:"14" version[15]:"15" version[16]:"16" version[17]:"17" version[18]:"18" version[19]:"19" version[20]:"20" version[21]:"21" version[22]:"22" version[23]:"23" version[24]:"24" version[25]:"25" version[26]:"26" version[27]:"27" version[28]:"28" version[29]:"29" version[30]:"30" version[31]:"31" version[32]:"32"` + Version uint32 `version[0]:"0" version[1]:"1" version[2]:"2" version[3]:"3" version[4]:"4" version[5]:"5" version[6]:"6" version[7]:"7" version[8]:"8" version[9]:"9" version[10]:"10" version[11]:"11" version[12]:"12" version[13]:"13" version[14]:"14" version[15]:"15" version[16]:"16" version[17]:"17" version[18]:"18" version[19]:"19" version[20]:"20" version[21]:"21" version[22]:"22" version[23]:"23" version[24]:"24" version[25]:"25" version[26]:"26" version[27]:"27" version[28]:"28" version[29]:"29" version[30]:"30" version[31]:"31" version[32]:"32" version[33]:"33"` // Archival nodes retain a full copy of the block history. Non-Archival nodes will delete old blocks and only retain what's need to properly validate blockchain messages (the precise number of recent blocks depends on the consensus parameters. Currently the last 1321 blocks are required). This means that non-Archival nodes require significantly less storage than Archival nodes. Relays (nodes with a valid NetAddress) are always Archival, regardless of this setting. This may change in the future. If setting this to true for the first time, the existing ledger may need to be deleted to get the historical values stored as the setting only effects current blocks forward. To do this, shutdown the node and delete all .sqlite files within the data/testnet-version directory, except the crash.sqlite file. Restart the node and wait for the node to sync. Archival bool `version[0]:"false"` @@ -375,6 +375,10 @@ type Local struct { // 0 means don't store any, -1 mean unlimited and positive number suggest the maximum number of most recent catchpoint files to store. CatchpointFileHistoryLength int `version[7]:"365"` + // EnableGossipService enables the gossip network HTTP websockets endpoint. The functionality of this depends on NetAddress, which must also be provided. + // This functionality is required for serving gossip traffic. + EnableGossipService bool `version[33]:"true"` + // EnableLedgerService enables the ledger serving service. The functionality of this depends on NetAddress, which must also be provided. // This functionality is required for the catchpoint catchup. EnableLedgerService bool `version[7]:"false"` diff --git a/config/local_defaults.go b/config/local_defaults.go index 06a26f2c1c..3df773a760 100644 --- a/config/local_defaults.go +++ b/config/local_defaults.go @@ -20,7 +20,7 @@ package config var defaultLocal = Local{ - Version: 32, + Version: 33, AccountUpdatesStatsInterval: 5000000000, AccountsRebuildSynchronousMode: 1, AgreementIncomingBundlesQueueLength: 15, @@ -70,6 +70,7 @@ var defaultLocal = Local{ EnableExperimentalAPI: false, EnableFollowMode: false, EnableGossipBlockService: true, + EnableGossipService: true, EnableIncomingMessageFilter: false, EnableLedgerService: false, EnableMetricReporting: false, diff --git a/installer/config.json.example b/installer/config.json.example index ce02380331..aa1cb71712 100644 --- a/installer/config.json.example +++ b/installer/config.json.example @@ -1,5 +1,5 @@ { - "Version": 32, + "Version": 33, "AccountUpdatesStatsInterval": 5000000000, "AccountsRebuildSynchronousMode": 1, "AgreementIncomingBundlesQueueLength": 15, @@ -49,6 +49,7 @@ "EnableExperimentalAPI": false, "EnableFollowMode": false, "EnableGossipBlockService": true, + "EnableGossipService": true, "EnableIncomingMessageFilter": false, "EnableLedgerService": false, "EnableMetricReporting": false, diff --git a/network/wsNetwork.go b/network/wsNetwork.go index 05e7ba44ca..37b172df62 100644 --- a/network/wsNetwork.go +++ b/network/wsNetwork.go @@ -591,7 +591,9 @@ func (wn *WebsocketNetwork) setup() { wn.upgrader.EnableCompression = false wn.lastPeerConnectionsSent = time.Now() wn.router = mux.NewRouter() - wn.router.Handle(GossipNetworkPath, wn) + if wn.config.EnableGossipService { + wn.router.Handle(GossipNetworkPath, wn) + } wn.requestsTracker = makeRequestsTracker(wn.router, wn.log, wn.config) if wn.config.EnableRequestLogger { wn.requestsLogger = makeRequestLogger(wn.requestsTracker, wn.log) @@ -1009,6 +1011,11 @@ func (wn *WebsocketNetwork) GetHTTPRequestConnection(request *http.Request) (con // ServerHTTP handles the gossip network functions over websockets func (wn *WebsocketNetwork) ServeHTTP(response http.ResponseWriter, request *http.Request) { + if !wn.config.EnableGossipService { + response.WriteHeader(http.StatusServiceUnavailable) + return + } + trackedRequest := wn.requestsTracker.GetTrackedRequest(request) if wn.checkIncomingConnectionLimits(response, request, trackedRequest.remoteHost, trackedRequest.otherTelemetryGUID, trackedRequest.otherInstanceName) != http.StatusOK { diff --git a/test/testdata/configs/config-v33.json b/test/testdata/configs/config-v33.json new file mode 100644 index 0000000000..aa1cb71712 --- /dev/null +++ b/test/testdata/configs/config-v33.json @@ -0,0 +1,140 @@ +{ + "Version": 33, + "AccountUpdatesStatsInterval": 5000000000, + "AccountsRebuildSynchronousMode": 1, + "AgreementIncomingBundlesQueueLength": 15, + "AgreementIncomingProposalsQueueLength": 50, + "AgreementIncomingVotesQueueLength": 20000, + "AnnounceParticipationKey": true, + "Archival": false, + "BaseLoggerDebugLevel": 4, + "BlockDBDir": "", + "BlockServiceCustomFallbackEndpoints": "", + "BlockServiceMemCap": 500000000, + "BroadcastConnectionsLimit": -1, + "CadaverDirectory": "", + "CadaverSizeTarget": 0, + "CatchpointDir": "", + "CatchpointFileHistoryLength": 365, + "CatchpointInterval": 10000, + "CatchpointTracking": 0, + "CatchupBlockDownloadRetryAttempts": 1000, + "CatchupBlockValidateMode": 0, + "CatchupFailurePeerRefreshRate": 10, + "CatchupGossipBlockFetchTimeoutSec": 4, + "CatchupHTTPBlockFetchTimeoutSec": 4, + "CatchupLedgerDownloadRetryAttempts": 50, + "CatchupParallelBlocks": 16, + "ColdDataDir": "", + "ConnectionsRateLimitingCount": 60, + "ConnectionsRateLimitingWindowSeconds": 1, + "CrashDBDir": "", + "DNSBootstrapID": ".algorand.network?backup=.algorand.net&dedup=.algorand-.(network|net)", + "DNSSecurityFlags": 1, + "DeadlockDetection": 0, + "DeadlockDetectionThreshold": 30, + "DisableAPIAuth": false, + "DisableLedgerLRUCache": false, + "DisableLocalhostConnectionRateLimit": true, + "DisableNetworking": false, + "DisableOutgoingConnectionThrottling": false, + "EnableAccountUpdatesStats": false, + "EnableAgreementReporting": false, + "EnableAgreementTimeMetrics": false, + "EnableAssembleStats": false, + "EnableBlockService": false, + "EnableBlockServiceFallbackToArchiver": false, + "EnableCatchupFromArchiveServers": false, + "EnableDeveloperAPI": false, + "EnableExperimentalAPI": false, + "EnableFollowMode": false, + "EnableGossipBlockService": true, + "EnableGossipService": true, + "EnableIncomingMessageFilter": false, + "EnableLedgerService": false, + "EnableMetricReporting": false, + "EnableOutgoingNetworkMessageFiltering": true, + "EnableP2P": false, + "EnablePingHandler": true, + "EnableProcessBlockStats": false, + "EnableProfiler": false, + "EnableRequestLogger": false, + "EnableRuntimeMetrics": false, + "EnableTopAccountsReporting": false, + "EnableTxBacklogAppRateLimiting": true, + "EnableTxBacklogRateLimiting": true, + "EnableTxnEvalTracer": false, + "EnableUsageLog": false, + "EnableVerbosedTransactionSyncLogging": false, + "EndpointAddress": "127.0.0.1:0", + "FallbackDNSResolverAddress": "", + "ForceFetchTransactions": false, + "ForceRelayMessages": false, + "GossipFanout": 4, + "HeartbeatUpdateInterval": 600, + "HotDataDir": "", + "IncomingConnectionsLimit": 2400, + "IncomingMessageFilterBucketCount": 5, + "IncomingMessageFilterBucketSize": 512, + "LedgerSynchronousMode": 2, + "LogArchiveDir": "", + "LogArchiveMaxAge": "", + "LogArchiveName": "node.archive.log", + "LogFileDir": "", + "LogSizeLimit": 1073741824, + "MaxAPIBoxPerApplication": 100000, + "MaxAPIResourcesPerAccount": 100000, + "MaxAcctLookback": 4, + "MaxBlockHistoryLookback": 0, + "MaxCatchpointDownloadDuration": 43200000000000, + "MaxConnectionsPerIP": 15, + "MinCatchpointFileDownloadBytesPerSecond": 20480, + "NetAddress": "", + "NetworkMessageTraceServer": "", + "NetworkProtocolVersion": "", + "NodeExporterListenAddress": ":9100", + "NodeExporterPath": "./node_exporter", + "OptimizeAccountsDatabaseOnStartup": false, + "OutgoingMessageFilterBucketCount": 3, + "OutgoingMessageFilterBucketSize": 128, + "P2PPersistPeerID": false, + "P2PPrivateKeyLocation": "", + "ParticipationKeysRefreshInterval": 60000000000, + "PeerConnectionsUpdateInterval": 3600, + "PeerPingPeriodSeconds": 0, + "PriorityPeers": {}, + "ProposalAssemblyTime": 500000000, + "PublicAddress": "", + "ReconnectTime": 60000000000, + "ReservedFDs": 256, + "RestConnectionsHardLimit": 2048, + "RestConnectionsSoftLimit": 1024, + "RestReadTimeoutSeconds": 15, + "RestWriteTimeoutSeconds": 120, + "RunHosted": false, + "StateproofDir": "", + "StorageEngine": "sqlite", + "SuggestedFeeBlockHistory": 3, + "SuggestedFeeSlidingWindowSize": 50, + "TLSCertFile": "", + "TLSKeyFile": "", + "TelemetryToLog": true, + "TrackerDBDir": "", + "TransactionSyncDataExchangeRate": 0, + "TransactionSyncSignificantMessageThreshold": 0, + "TxBacklogAppTxPerSecondRate": 100, + "TxBacklogAppTxRateLimiterMaxSize": 1048576, + "TxBacklogRateLimitingCongestionPct": 50, + "TxBacklogReservedCapacityPerPeer": 20, + "TxBacklogServiceRateWindowSeconds": 10, + "TxBacklogSize": 26000, + "TxIncomingFilterMaxSize": 500000, + "TxIncomingFilteringFlags": 1, + "TxPoolExponentialIncreaseFactor": 2, + "TxPoolSize": 75000, + "TxSyncIntervalSeconds": 60, + "TxSyncServeResponseSize": 1000000, + "TxSyncTimeoutSeconds": 30, + "UseXForwardedForAddressField": "", + "VerifiedTranscationsCacheSize": 150000 +} From 555c4c88246512638c996ef9caa4a59cbb8cb8ee Mon Sep 17 00:00:00 2001 From: ohill <145173879+ohill@users.noreply.github.com> Date: Wed, 15 Nov 2023 11:54:14 -0500 Subject: [PATCH 2/3] add TestWebsocketNetworkNoGossipService --- network/wsNetwork.go | 2 +- network/wsNetwork_test.go | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/network/wsNetwork.go b/network/wsNetwork.go index 37b172df62..7f8b3046c9 100644 --- a/network/wsNetwork.go +++ b/network/wsNetwork.go @@ -1012,7 +1012,7 @@ func (wn *WebsocketNetwork) GetHTTPRequestConnection(request *http.Request) (con // ServerHTTP handles the gossip network functions over websockets func (wn *WebsocketNetwork) ServeHTTP(response http.ResponseWriter, request *http.Request) { if !wn.config.EnableGossipService { - response.WriteHeader(http.StatusServiceUnavailable) + response.WriteHeader(http.StatusNotFound) return } diff --git a/network/wsNetwork_test.go b/network/wsNetwork_test.go index 445ede3dc3..785fc26c48 100644 --- a/network/wsNetwork_test.go +++ b/network/wsNetwork_test.go @@ -656,6 +656,29 @@ func TestWebsocketNetworkNoAddress(t *testing.T) { } } +func TestWebsocketNetworkNoGossipService(t *testing.T) { + partitiontest.PartitionTest(t) + + config := defaultConfig + config.EnableGossipService = false + netA := makeTestWebsocketNodeWithConfig(t, config) + netA.Start() + defer netStop(t, netA, "A") + + // assert that the network was started and is listening + addrA, postListen := netA.Address() + require.True(t, postListen) + + // make HTTP request to gossip service and assert 404 + var resp *http.Response + require.Eventually(t, func() bool { + var err error + resp, err = http.Get(fmt.Sprintf("%s/v1/%s/gossip", addrA, genesisID)) + return err == nil + }, 2*time.Second, 100*time.Millisecond) + require.Equal(t, http.StatusNotFound, resp.StatusCode) +} + func lineNetwork(t *testing.T, numNodes int) (nodes []*WebsocketNetwork, counters []messageCounterHandler) { nodes = make([]*WebsocketNetwork, numNodes) counters = make([]messageCounterHandler, numNodes) From 31d9c9f25a6fbaed107156756cd9c743d3477db2 Mon Sep 17 00:00:00 2001 From: ohill <145173879+ohill@users.noreply.github.com> Date: Wed, 15 Nov 2023 17:21:52 -0500 Subject: [PATCH 3/3] update TestWebsocketNetworkNoAddress as per CR --- network/wsNetwork_test.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/network/wsNetwork_test.go b/network/wsNetwork_test.go index 785fc26c48..05e484843a 100644 --- a/network/wsNetwork_test.go +++ b/network/wsNetwork_test.go @@ -628,6 +628,10 @@ func TestWebsocketNetworkNoAddress(t *testing.T) { noAddressConfig := defaultConfig noAddressConfig.NetAddress = "" + // enable services even though NetAddress is not set (to assert they don't override NetAddress) + noAddressConfig.EnableGossipService = true + noAddressConfig.EnableBlockService = true + noAddressConfig.EnableLedgerService = true netB := makeTestWebsocketNodeWithConfig(t, noAddressConfig) netB.config.GossipFanout = 1 addrA, postListen := netA.Address() @@ -636,6 +640,12 @@ func TestWebsocketNetworkNoAddress(t *testing.T) { netB.phonebook.ReplacePeerList([]string{addrA}, "default", PhoneBookEntryRelayRole) netB.Start() defer netStop(t, netB, "B") + + // assert addrB is not listening + addrB, postListenB := netB.Address() + require.False(t, postListenB) + require.Empty(t, addrB) + counter := newMessageCounter(t, 2) counterDone := counter.done netB.RegisterHandlers([]TaggedMessageHandler{{Tag: protocol.TxnTag, MessageHandler: counter}})