github.com/MetalBlockchain/metalgo@v1.11.9/network/test_network.go (about) 1 // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package network 5 6 import ( 7 "crypto" 8 "errors" 9 "math" 10 "net" 11 "net/netip" 12 "runtime" 13 "sync" 14 15 "github.com/prometheus/client_golang/prometheus" 16 17 "github.com/MetalBlockchain/metalgo/ids" 18 "github.com/MetalBlockchain/metalgo/message" 19 "github.com/MetalBlockchain/metalgo/network/dialer" 20 "github.com/MetalBlockchain/metalgo/network/peer" 21 "github.com/MetalBlockchain/metalgo/network/throttling" 22 "github.com/MetalBlockchain/metalgo/snow/networking/router" 23 "github.com/MetalBlockchain/metalgo/snow/networking/tracker" 24 "github.com/MetalBlockchain/metalgo/snow/uptime" 25 "github.com/MetalBlockchain/metalgo/snow/validators" 26 "github.com/MetalBlockchain/metalgo/staking" 27 "github.com/MetalBlockchain/metalgo/subnets" 28 "github.com/MetalBlockchain/metalgo/utils" 29 "github.com/MetalBlockchain/metalgo/utils/constants" 30 "github.com/MetalBlockchain/metalgo/utils/crypto/bls" 31 "github.com/MetalBlockchain/metalgo/utils/logging" 32 "github.com/MetalBlockchain/metalgo/utils/math/meter" 33 "github.com/MetalBlockchain/metalgo/utils/resource" 34 "github.com/MetalBlockchain/metalgo/utils/set" 35 "github.com/MetalBlockchain/metalgo/utils/units" 36 ) 37 38 var ( 39 errClosed = errors.New("closed") 40 41 _ net.Listener = (*noopListener)(nil) 42 _ subnets.Allower = (*nodeIDConnector)(nil) 43 ) 44 45 type noopListener struct { 46 once sync.Once 47 closed chan struct{} 48 } 49 50 func newNoopListener() net.Listener { 51 return &noopListener{ 52 closed: make(chan struct{}), 53 } 54 } 55 56 func (l *noopListener) Accept() (net.Conn, error) { 57 <-l.closed 58 return nil, errClosed 59 } 60 61 func (l *noopListener) Close() error { 62 l.once.Do(func() { 63 close(l.closed) 64 }) 65 return nil 66 } 67 68 func (*noopListener) Addr() net.Addr { 69 return &net.TCPAddr{ 70 IP: net.IPv4zero, 71 Port: 1, 72 } 73 } 74 75 func NewTestNetwork( 76 log logging.Logger, 77 networkID uint32, 78 currentValidators validators.Manager, 79 trackedSubnets set.Set[ids.ID], 80 router router.ExternalHandler, 81 ) (Network, error) { 82 metrics := prometheus.NewRegistry() 83 msgCreator, err := message.NewCreator( 84 logging.NoLog{}, 85 metrics, 86 constants.DefaultNetworkCompressionType, 87 constants.DefaultNetworkMaximumInboundTimeout, 88 ) 89 if err != nil { 90 return nil, err 91 } 92 93 tlsCert, err := staking.NewTLSCert() 94 if err != nil { 95 return nil, err 96 } 97 98 blsKey, err := bls.NewSecretKey() 99 if err != nil { 100 return nil, err 101 } 102 103 // TODO actually monitor usage 104 // TestNetwork doesn't use disk so we don't need to track it, but we should 105 // still have guardrails around cpu/memory usage. 106 resourceTracker, err := tracker.NewResourceTracker( 107 metrics, 108 resource.NoUsage, 109 &meter.ContinuousFactory{}, 110 constants.DefaultHealthCheckAveragerHalflife, 111 ) 112 if err != nil { 113 return nil, err 114 } 115 116 return NewNetwork( 117 &Config{ 118 HealthConfig: HealthConfig{ 119 Enabled: true, 120 MinConnectedPeers: constants.DefaultNetworkHealthMinPeers, 121 MaxTimeSinceMsgReceived: constants.DefaultNetworkHealthMaxTimeSinceMsgReceived, 122 MaxTimeSinceMsgSent: constants.DefaultNetworkHealthMaxTimeSinceMsgSent, 123 MaxPortionSendQueueBytesFull: constants.DefaultNetworkHealthMaxPortionSendQueueFill, 124 MaxSendFailRate: constants.DefaultNetworkHealthMaxSendFailRate, 125 SendFailRateHalflife: constants.DefaultHealthCheckAveragerHalflife, 126 }, 127 PeerListGossipConfig: PeerListGossipConfig{ 128 PeerListNumValidatorIPs: constants.DefaultNetworkPeerListNumValidatorIPs, 129 PeerListPullGossipFreq: constants.DefaultNetworkPeerListPullGossipFreq, 130 PeerListBloomResetFreq: constants.DefaultNetworkPeerListBloomResetFreq, 131 }, 132 TimeoutConfig: TimeoutConfig{ 133 PingPongTimeout: constants.DefaultPingPongTimeout, 134 ReadHandshakeTimeout: constants.DefaultNetworkReadHandshakeTimeout, 135 }, 136 DelayConfig: DelayConfig{ 137 InitialReconnectDelay: constants.DefaultNetworkInitialReconnectDelay, 138 MaxReconnectDelay: constants.DefaultNetworkMaxReconnectDelay, 139 }, 140 ThrottlerConfig: ThrottlerConfig{ 141 InboundConnUpgradeThrottlerConfig: throttling.InboundConnUpgradeThrottlerConfig{ 142 UpgradeCooldown: constants.DefaultInboundConnUpgradeThrottlerCooldown, 143 MaxRecentConnsUpgraded: int(math.Ceil(constants.DefaultInboundThrottlerMaxConnsPerSec * constants.DefaultInboundConnUpgradeThrottlerCooldown.Seconds())), 144 }, 145 InboundMsgThrottlerConfig: throttling.InboundMsgThrottlerConfig{ 146 MsgByteThrottlerConfig: throttling.MsgByteThrottlerConfig{ 147 VdrAllocSize: constants.DefaultInboundThrottlerVdrAllocSize, 148 AtLargeAllocSize: constants.DefaultInboundThrottlerAtLargeAllocSize, 149 NodeMaxAtLargeBytes: constants.DefaultInboundThrottlerNodeMaxAtLargeBytes, 150 }, 151 BandwidthThrottlerConfig: throttling.BandwidthThrottlerConfig{ 152 RefillRate: constants.DefaultInboundThrottlerBandwidthRefillRate, 153 MaxBurstSize: constants.DefaultInboundThrottlerBandwidthMaxBurstSize, 154 }, 155 CPUThrottlerConfig: throttling.SystemThrottlerConfig{ 156 MaxRecheckDelay: constants.DefaultInboundThrottlerCPUMaxRecheckDelay, 157 }, 158 DiskThrottlerConfig: throttling.SystemThrottlerConfig{ 159 MaxRecheckDelay: constants.DefaultInboundThrottlerDiskMaxRecheckDelay, 160 }, 161 MaxProcessingMsgsPerNode: constants.DefaultInboundThrottlerMaxProcessingMsgsPerNode, 162 }, 163 OutboundMsgThrottlerConfig: throttling.MsgByteThrottlerConfig{ 164 VdrAllocSize: constants.DefaultOutboundThrottlerVdrAllocSize, 165 AtLargeAllocSize: constants.DefaultOutboundThrottlerAtLargeAllocSize, 166 NodeMaxAtLargeBytes: constants.DefaultOutboundThrottlerNodeMaxAtLargeBytes, 167 }, 168 MaxInboundConnsPerSec: constants.DefaultInboundThrottlerMaxConnsPerSec, 169 }, 170 ProxyEnabled: constants.DefaultNetworkTCPProxyEnabled, 171 ProxyReadHeaderTimeout: constants.DefaultNetworkTCPProxyReadTimeout, 172 DialerConfig: dialer.Config{ 173 ThrottleRps: constants.DefaultOutboundConnectionThrottlingRps, 174 ConnectionTimeout: constants.DefaultOutboundConnectionTimeout, 175 }, 176 TLSConfig: peer.TLSConfig(*tlsCert, nil), 177 MyIPPort: utils.NewAtomic(netip.AddrPortFrom( 178 netip.IPv4Unspecified(), 179 1, 180 )), 181 NetworkID: networkID, 182 MaxClockDifference: constants.DefaultNetworkMaxClockDifference, 183 PingFrequency: constants.DefaultPingFrequency, 184 AllowPrivateIPs: !constants.ProductionNetworkIDs.Contains(networkID), 185 CompressionType: constants.DefaultNetworkCompressionType, 186 TLSKey: tlsCert.PrivateKey.(crypto.Signer), 187 BLSKey: blsKey, 188 TrackedSubnets: trackedSubnets, 189 Beacons: validators.NewManager(), 190 Validators: currentValidators, 191 UptimeCalculator: uptime.NoOpCalculator, 192 UptimeMetricFreq: constants.DefaultUptimeMetricFreq, 193 RequireValidatorToConnect: constants.DefaultNetworkRequireValidatorToConnect, 194 MaximumInboundMessageTimeout: constants.DefaultNetworkMaximumInboundTimeout, 195 PeerReadBufferSize: constants.DefaultNetworkPeerReadBufferSize, 196 PeerWriteBufferSize: constants.DefaultNetworkPeerWriteBufferSize, 197 ResourceTracker: resourceTracker, 198 CPUTargeter: tracker.NewTargeter( 199 logging.NoLog{}, 200 &tracker.TargeterConfig{ 201 VdrAlloc: float64(runtime.NumCPU()), 202 MaxNonVdrUsage: .8 * float64(runtime.NumCPU()), 203 MaxNonVdrNodeUsage: float64(runtime.NumCPU()) / 8, 204 }, 205 currentValidators, 206 resourceTracker.CPUTracker(), 207 ), 208 DiskTargeter: tracker.NewTargeter( 209 logging.NoLog{}, 210 &tracker.TargeterConfig{ 211 VdrAlloc: 1000 * units.GiB, 212 MaxNonVdrUsage: 1000 * units.GiB, 213 MaxNonVdrNodeUsage: 1000 * units.GiB, 214 }, 215 currentValidators, 216 resourceTracker.DiskTracker(), 217 ), 218 }, 219 msgCreator, 220 metrics, 221 log, 222 newNoopListener(), 223 dialer.NewDialer( 224 constants.NetworkType, 225 dialer.Config{ 226 ThrottleRps: constants.DefaultOutboundConnectionThrottlingRps, 227 ConnectionTimeout: constants.DefaultOutboundConnectionTimeout, 228 }, 229 log, 230 ), 231 router, 232 ) 233 } 234 235 type nodeIDConnector struct { 236 nodeID ids.NodeID 237 } 238 239 func newNodeIDConnector(nodeID ids.NodeID) *nodeIDConnector { 240 return &nodeIDConnector{nodeID: nodeID} 241 } 242 243 func (f *nodeIDConnector) IsAllowed(nodeID ids.NodeID, _ bool) bool { 244 return nodeID == f.nodeID 245 }