{.push raises: [].} import std/[options, net], results, chronicles, libp2p/crypto/crypto, libp2p/builders, libp2p/nameresolving/nameresolver, libp2p/transports/wstransport, libp2p/protocols/connectivity/relay/client, libp2p/protocols/connectivity/relay/relay import ../waku_enr, ../discovery/waku_discv5, ../waku_node, ../node/peer_manager, ../common/rate_limit/setting type WakuNodeBuilder* = object # General nodeRng: Option[ref crypto.HmacDrbgContext] nodeKey: Option[crypto.PrivateKey] netConfig: Option[NetConfig] record: Option[enr.Record] # Peer storage and peer manager peerStorage: Option[PeerStorage] peerStorageCapacity: Option[int] # Peer manager config maxRelayPeers: Option[int] colocationLimit: int shardAware: bool # Libp2p switch switchMaxConnections: Option[int] switchNameResolver: Option[NameResolver] switchAgentString: Option[string] switchSslSecureKey: Option[string] switchSslSecureCert: Option[string] switchSendSignedPeerRecord: Option[bool] circuitRelay: Relay #Rate limit configs for non-relay req-resp protocols rateLimitSettings: Option[seq[string]] WakuNodeBuilderResult* = Result[void, string] ## Init proc init*(T: type WakuNodeBuilder): WakuNodeBuilder = WakuNodeBuilder() ## General proc withRng*(builder: var WakuNodeBuilder, rng: ref crypto.HmacDrbgContext) = builder.nodeRng = some(rng) proc withNodeKey*(builder: var WakuNodeBuilder, nodeKey: crypto.PrivateKey) = builder.nodeKey = some(nodeKey) proc withRecord*(builder: var WakuNodeBuilder, record: enr.Record) = builder.record = some(record) proc withNetworkConfiguration*(builder: var WakuNodeBuilder, config: NetConfig) = builder.netConfig = some(config) proc withNetworkConfigurationDetails*( builder: var WakuNodeBuilder, bindIp: IpAddress, bindPort: Port, extIp = none(IpAddress), extPort = none(Port), extMultiAddrs = newSeq[MultiAddress](), wsBindPort: Port = Port(8000), wsEnabled: bool = false, wssEnabled: bool = false, wakuFlags = none(CapabilitiesBitfield), dns4DomainName = none(string), ): WakuNodeBuilderResult {. deprecated: "use 'builder.withNetworkConfiguration()' instead" .} = let netConfig = ?NetConfig.init( bindIp = bindIp, bindPort = bindPort, extIp = extIp, extPort = extPort, extMultiAddrs = extMultiAddrs, wsBindPort = wsBindPort, wsEnabled = wsEnabled, wssEnabled = wssEnabled, wakuFlags = wakuFlags, dns4DomainName = dns4DomainName, ) builder.withNetworkConfiguration(netConfig) ok() ## Peer storage and peer manager proc withPeerStorage*( builder: var WakuNodeBuilder, peerStorage: PeerStorage, capacity = none(int) ) = if not peerStorage.isNil(): builder.peerStorage = some(peerStorage) builder.peerStorageCapacity = capacity proc withPeerManagerConfig*( builder: var WakuNodeBuilder, maxRelayPeers = none(int), shardAware = false ) = builder.maxRelayPeers = maxRelayPeers builder.shardAware = shardAware proc withColocationLimit*(builder: var WakuNodeBuilder, colocationLimit: int) = builder.colocationLimit = colocationLimit proc withRateLimit*(builder: var WakuNodeBuilder, limits: seq[string]) = builder.rateLimitSettings = some(limits) proc withCircuitRelay*(builder: var WakuNodeBuilder, circuitRelay: Relay) = builder.circuitRelay = circuitRelay ## Waku switch proc withSwitchConfiguration*( builder: var WakuNodeBuilder, maxConnections = none(int), nameResolver: NameResolver = nil, sendSignedPeerRecord = false, secureKey = none(string), secureCert = none(string), agentString = none(string), ) = builder.switchMaxConnections = maxConnections builder.switchSendSignedPeerRecord = some(sendSignedPeerRecord) builder.switchSslSecureKey = secureKey builder.switchSslSecureCert = secureCert builder.switchAgentString = agentString if not nameResolver.isNil(): builder.switchNameResolver = some(nameResolver) ## Build proc build*(builder: WakuNodeBuilder): Result[WakuNode, string] = var rng: ref crypto.HmacDrbgContext if builder.nodeRng.isNone(): rng = crypto.newRng() else: rng = builder.nodeRng.get() if builder.nodeKey.isNone(): return err("node key is required") if builder.netConfig.isNone(): return err("network configuration is required") if builder.record.isNone(): return err("node record is required") let circuitRelay = if builder.circuitRelay.isNil(): Relay.new() else: builder.circuitRelay var switch: Switch try: switch = newWakuSwitch( privKey = builder.nodekey, address = builder.netConfig.get().hostAddress, wsAddress = builder.netConfig.get().wsHostAddress, transportFlags = {ServerFlags.ReuseAddr, ServerFlags.TcpNoDelay}, rng = rng, maxConnections = builder.switchMaxConnections.get(builders.MaxConnections), wssEnabled = builder.netConfig.get().wssEnabled, secureKeyPath = builder.switchSslSecureKey.get(""), secureCertPath = builder.switchSslSecureCert.get(""), nameResolver = builder.switchNameResolver.get(nil), sendSignedPeerRecord = builder.switchSendSignedPeerRecord.get(false), agentString = builder.switchAgentString, peerStoreCapacity = builder.peerStorageCapacity, circuitRelay = circuitRelay, ) except CatchableError: return err("failed to create switch: " & getCurrentExceptionMsg()) let peerManager = PeerManager.new( switch = switch, storage = builder.peerStorage.get(nil), maxRelayPeers = builder.maxRelayPeers, colocationLimit = builder.colocationLimit, shardedPeerManagement = builder.shardAware, ) var node: WakuNode try: node = WakuNode.new( netConfig = builder.netConfig.get(), enr = builder.record.get(), switch = switch, peerManager = peerManager, rng = rng, ) except Exception: return err("failed to build WakuNode instance: " & getCurrentExceptionMsg()) if builder.rateLimitSettings.isSome(): ?node.setRateLimits(builder.rateLimitSettings.get()) ok(node)