diff --git a/waku/factory/builder.nim b/waku/factory/builder.nim index 13c6b4ae2..2fc91c8c7 100644 --- a/waku/factory/builder.nim +++ b/waku/factory/builder.nim @@ -47,9 +47,11 @@ type rateLimitSettings: Option[seq[string]] # Eligibility enabled - # FIXME: is this the right way to propagate eligibility-related config items? eligibilityEnabled: bool + # Reputation enabled + reputationEnabled: bool + WakuNodeBuilderResult* = Result[void, string] ## Init @@ -118,6 +120,7 @@ proc withPeerManagerConfig*( relayServiceRatio: string, shardAware = false, eligibilityEnabled = false, + reputationEnabled = false, ) = let (relayRatio, serviceRatio) = parseRelayServiceRatio(relayServiceRatio).get() var relayPeers = int(ceil(float(maxConnections) * relayRatio)) @@ -127,6 +130,7 @@ proc withPeerManagerConfig*( builder.maxRelayPeers = relayPeers builder.shardAware = shardAware builder.eligibilityEnabled = eligibilityEnabled + builder.reputationEnabled = reputationEnabled proc withColocationLimit*(builder: var WakuNodeBuilder, colocationLimit: int) = builder.colocationLimit = colocationLimit @@ -212,9 +216,8 @@ proc build*(builder: WakuNodeBuilder): Result[WakuNode, string] = colocationLimit = builder.colocationLimit, shardedPeerManagement = builder.shardAware, dnsNameServers = netConfig.dnsNameServers, - # FIXME: should eligibilityEnabled be part of some eligibilityConfig within WakuNodeBuilder here? - eligibilityEnabled = builder.eligibilityEnabled - #reputationEnabled = true, # FIXME: i13n: read config or something instead + eligibilityEnabled = builder.eligibilityEnabled, + reputationEnabled = builder.reputationEnabled ) var node: WakuNode diff --git a/waku/factory/conf_builder/reputation_conf_builder.nim b/waku/factory/conf_builder/reputation_conf_builder.nim new file mode 100644 index 000000000..f01a6a083 --- /dev/null +++ b/waku/factory/conf_builder/reputation_conf_builder.nim @@ -0,0 +1,28 @@ +import chronicles, std/options, results +import ../waku_conf + +logScope: + topics = "waku conf builder reputation" + +type ReputationConfBuilder* = object + enabled*: Option[bool] + +proc init*(T: type ReputationConfBuilder): ReputationConfBuilder = + ReputationConfBuilder() + +proc withEnabled*(b: var ReputationConfBuilder, enabled: bool) = + b.enabled = some(enabled) + +proc build*(b: ReputationConfBuilder): Result[Option[ReputationConf], string] = + if not b.enabled.get(false): + debug "reputation: ReputationConf not enabled" + return ok(none(ReputationConf)) + + debug "reputation: ReputationConf created" + return ok( + some( + ReputationConf( + enabled: true + ) + ) + ) \ No newline at end of file diff --git a/waku/factory/conf_builder/waku_conf_builder.nim b/waku/factory/conf_builder/waku_conf_builder.nim index 92a51fcf1..d89e026f4 100644 --- a/waku/factory/conf_builder/waku_conf_builder.nim +++ b/waku/factory/conf_builder/waku_conf_builder.nim @@ -23,7 +23,8 @@ import ./web_socket_conf_builder, ./metrics_server_conf_builder, ./rln_relay_conf_builder, - ./eligibility_conf_builder + ./eligibility_conf_builder, + ./reputation_conf_builder logScope: topics = "waku conf builder" @@ -74,6 +75,7 @@ type WakuConfBuilder* = object storeServiceConf*: StoreServiceConfBuilder webSocketConf*: WebSocketConfBuilder eligibilityConf*: EligibilityConfBuilder + reputationConf*: ReputationConfBuilder # End conf builders relay: Option[bool] lightPush: Option[bool] @@ -138,6 +140,7 @@ proc init*(T: type WakuConfBuilder): WakuConfBuilder = storeServiceConf: StoreServiceConfBuilder.init(), webSocketConf: WebSocketConfBuilder.init(), eligibilityConf: EligibilityConfBuilder.init(), + reputationConf: ReputationConfBuilder.init(), ) proc withClusterConf*(b: var WakuConfBuilder, clusterConf: ClusterConf) = @@ -479,6 +482,9 @@ proc build*( let eligibilityConf = builder.eligibilityConf.build().valueOr: return err("Eligibility Conf building failed: " & $error) + + let reputationConf = builder.reputationConf.build().valueOr: + return err("Reputation Conf building failed: " & $error) # End - Build sub-configs let logLevel = @@ -603,6 +609,7 @@ proc build*( restServerConf: restServerConf, dnsDiscoveryConf: dnsDiscoveryConf, eligibilityConf: eligibilityConf, + reputationConf: reputationConf, # end confs nodeKey: nodeKey, clusterId: clusterId, diff --git a/waku/factory/external_config.nim b/waku/factory/external_config.nim index 7e33ffd7c..fd961bb6e 100644 --- a/waku/factory/external_config.nim +++ b/waku/factory/external_config.nim @@ -28,7 +28,8 @@ import ../waku_core/topics/pubsub_topic, ../../tools/rln_keystore_generator/rln_keystore_generator, ../../tools/rln_db_inspector/rln_db_inspector, - ./conf_builder/eligibility_conf_builder + ./conf_builder/eligibility_conf_builder, + ./conf_builder/reputation_conf_builder include ../waku_core/message/default_values @@ -484,7 +485,7 @@ type WakuNodeConf* = object reputationEnabled* {. desc: "Enable client-side reputation for light protocols: true|false", defaultValue: false, - name: "reputation" + name: "reputation-enabled" .}: bool ## Eligibility config @@ -1092,4 +1093,7 @@ proc toWakuConf*(n: WakuNodeConf): ConfResult[WakuConf] = if n.eligibilityEthRpcUrl.len > 0: b.eligibilityConf.withEthClientUrls(n.eligibilityEthRpcUrl.mapIt(string(it))) + # Setup reputation configuration + b.reputationConf.withEnabled(n.reputationEnabled) + return b.build() diff --git a/waku/factory/node_factory.nim b/waku/factory/node_factory.nim index c1f93d853..7c7c71679 100644 --- a/waku/factory/node_factory.nim +++ b/waku/factory/node_factory.nim @@ -116,6 +116,12 @@ proc initNode( else: false + let reputationEnabled = + if conf.reputationConf.isSome(): + conf.reputationConf.get().enabled + else: + false + if conf.maxRelayPeers.isSome(): let maxRelayPeers = conf.maxRelayPeers.get() @@ -130,6 +136,7 @@ proc initNode( relayServiceRatio = $relayRatio & ":" & $serviceRatio, shardAware = conf.relayShardedPeerManagement, eligibilityEnabled = eligibilityEnabled, + reputationEnabled = reputationEnabled, ) error "maxRelayPeers is deprecated. It is recommended to use relayServiceRatio instead. If relayServiceRatio is not set, it will be automatically calculated based on maxConnections and maxRelayPeers." else: @@ -138,6 +145,7 @@ proc initNode( relayServiceRatio = conf.relayServiceRatio, shardAware = conf.relayShardedPeerManagement, eligibilityEnabled = eligibilityEnabled, + reputationEnabled = reputationEnabled, ) builder.withRateLimit(conf.rateLimits) builder.withCircuitRelay(relay) diff --git a/waku/factory/waku_conf.nim b/waku/factory/waku_conf.nim index ba81a57c4..af115260e 100644 --- a/waku/factory/waku_conf.nim +++ b/waku/factory/waku_conf.nim @@ -64,6 +64,9 @@ type EligibilityConf* = object paymentAmountWei*: uint32 ethClientUrls*: seq[string] +type ReputationConf* = object + enabled*: bool + ## `WakuConf` is a valid configuration for a Waku node ## All information needed by a waku node should be contained ## In this object. A convenient `validate` method enables doing @@ -100,6 +103,7 @@ type WakuConf* {.requiresInit.} = ref object metricsServerConf*: Option[MetricsServerConf] webSocketConf*: Option[WebSocketConf] eligibilityConf*: Option[EligibilityConf] + reputationConf*: Option[ReputationConf] portsShift*: uint16 dnsAddrs*: bool diff --git a/waku/node/peer_manager/peer_manager.nim b/waku/node/peer_manager/peer_manager.nim index 4c1a9a4f9..2b8ece328 100644 --- a/waku/node/peer_manager/peer_manager.nim +++ b/waku/node/peer_manager/peer_manager.nim @@ -242,6 +242,7 @@ proc selectPeer*( # For other protocols, we select the peer that is slotted for the given protocol pm.serviceSlots.withValue(proto, serviceSlot): + # FIXME: if there is just one peer, reputation doesn't affect choice? trace "Got peer from service slots", peerId = serviceSlot[].peerId, multi = serviceSlot[].addrs[0], protocol = proto return some(serviceSlot[]) @@ -249,8 +250,10 @@ proc selectPeer*( # If not slotted, we select a random peer for the given protocol if peers.len > 0: # if reputation is enabled, filter out bad-reputation peers + debug "Total peers in peerstore:", numPeers = peers.len var preSelectedPeers = if pm.reputationManager.isSome(): + debug "Reputation enabled: consider only non-negative reputation peers" peers.filterIt: let rep = try: @@ -261,6 +264,9 @@ proc selectPeer*( else: peers let selectedPeer = preSelectedPeers[0] + if pm.reputationManager.isSome(): + debug "Non-negative reputation peers in peerstore: ", numPeers = preSelectedPeers.len + debug "Selected peer has reputation", reputation = pm.reputationManager.get().getReputation(selectedPeer.peerId) trace "Got peer from peerstore", peerId = selectedPeer.peerId, multi = selectedPeer.addrs[0], protocol = proto return some(selectedPeer) diff --git a/waku/waku_lightpush/client.nim b/waku/waku_lightpush/client.nim index 745de6dd8..61f061cc9 100644 --- a/waku/waku_lightpush/client.nim +++ b/waku/waku_lightpush/client.nim @@ -85,6 +85,7 @@ proc publish*( if message.timestamp == 0: message.timestamp = getNowInNanosecondTime() + # FIXME: make more DRY when peer is PeerId: info "publish", peerId = shortLog(peer),