feat: wakuv2 connectivity and peer management (#17)
* wakuv2 connectivity and peer management * feat: wakuv2 light client (#15) Co-authored-by: Richard Ramos <info@richardramos.me>
This commit is contained in:
parent
e29ba9c9fa
commit
2bb5df3c5f
|
@ -1,10 +1,11 @@
|
||||||
import chronicles
|
import chronicles
|
||||||
import ../eventemitter
|
import ../eventemitter
|
||||||
import statusgo_backend/settings
|
import statusgo_backend/settings
|
||||||
|
import statusgo_backend/core
|
||||||
import json
|
import json
|
||||||
import uuids
|
import uuids, strutils
|
||||||
import json_serialization
|
import json_serialization
|
||||||
import ./types/[setting]
|
import ./types/[setting, fleet]
|
||||||
|
|
||||||
logScope:
|
logScope:
|
||||||
topics = "network-model"
|
topics = "network-model"
|
||||||
|
@ -21,6 +22,16 @@ proc newNetworkModel*(events: EventEmitter): NetworkModel =
|
||||||
result.peers = @[]
|
result.peers = @[]
|
||||||
result.connected = false
|
result.connected = false
|
||||||
|
|
||||||
|
proc fetchPeers*(self: NetworkModel): seq[string] =
|
||||||
|
var fleetStr = getSetting[string](Setting.Fleet)
|
||||||
|
if fleetStr == "": fleetStr = "eth.prod"
|
||||||
|
let fleet = parseEnum[Fleet](fleetStr)
|
||||||
|
let isWakuV2 = if fleet == WakuV2Prod or fleet == WakuV2Test: true else: false
|
||||||
|
if isWakuV2:
|
||||||
|
return wakuV2Peers()
|
||||||
|
else:
|
||||||
|
return adminPeers()
|
||||||
|
|
||||||
proc peerSummaryChange*(self: NetworkModel, peers: seq[string]) =
|
proc peerSummaryChange*(self: NetworkModel, peers: seq[string]) =
|
||||||
if peers.len == 0 and self.connected:
|
if peers.len == 0 and self.connected:
|
||||||
self.connected = false
|
self.connected = false
|
||||||
|
|
|
@ -45,12 +45,18 @@ proc getCurrentNetwork*(self: SettingsModel): NetworkType =
|
||||||
proc setWakuVersion*(self: SettingsModel, newVersion: int) =
|
proc setWakuVersion*(self: SettingsModel, newVersion: int) =
|
||||||
statusgo_backend_settings.setWakuVersion(newVersion)
|
statusgo_backend_settings.setWakuVersion(newVersion)
|
||||||
|
|
||||||
|
proc getWakuVersion*(self: SettingsModel): int =
|
||||||
|
statusgo_backend_settings.getWakuVersion()
|
||||||
|
|
||||||
proc setBloomFilterMode*(self: SettingsModel, bloomFilterMode: bool): StatusGoError =
|
proc setBloomFilterMode*(self: SettingsModel, bloomFilterMode: bool): StatusGoError =
|
||||||
statusgo_backend_settings.setBloomFilterMode(bloomFilterMode)
|
statusgo_backend_settings.setBloomFilterMode(bloomFilterMode)
|
||||||
|
|
||||||
proc setFleet*(self: SettingsModel, fleetConfig: FleetConfig, fleet: Fleet): StatusGoError =
|
proc setFleet*(self: SettingsModel, fleetConfig: FleetConfig, fleet: Fleet): StatusGoError =
|
||||||
statusgo_backend_settings.setFleet(fleetConfig, fleet)
|
statusgo_backend_settings.setFleet(fleetConfig, fleet)
|
||||||
|
|
||||||
|
proc setV2LightMode*(self: SettingsModel, enabled: bool): StatusGoError =
|
||||||
|
statusgo_backend_settings.setV2LightMode(enabled)
|
||||||
|
|
||||||
proc getNodeConfig*(self: SettingsModel): JsonNode =
|
proc getNodeConfig*(self: SettingsModel): JsonNode =
|
||||||
statusgo_backend_settings.getNodeConfig()
|
statusgo_backend_settings.getNodeConfig()
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import json, json_serialization, strutils
|
import json, json_serialization, strutils
|
||||||
import signals/[base, chronicles_logs, community, discovery_summary, envelope, expired, mailserver, messages, signal_type, stats, wallet, whisper_filter]
|
import signals/[base, chronicles_logs, community, discovery_summary, envelope, expired, mailserver, messages, peerstats, signal_type, stats, wallet, whisper_filter]
|
||||||
|
|
||||||
export base, chronicles_logs, community, discovery_summary, envelope, expired, mailserver, messages, signal_type, stats, wallet, whisper_filter
|
export base, chronicles_logs, community, discovery_summary, envelope, expired, mailserver, messages, peerstats, signal_type, stats, wallet, whisper_filter
|
||||||
|
|
||||||
proc decode*(jsonSignal: JsonNode): Signal =
|
proc decode*(jsonSignal: JsonNode): Signal =
|
||||||
let signalString = jsonSignal{"type"}.getStr
|
let signalString = jsonSignal{"type"}.getStr
|
||||||
|
@ -18,6 +18,7 @@ proc decode*(jsonSignal: JsonNode): Signal =
|
||||||
of SignalType.WhisperFilterAdded: WhisperFilterSignal.fromEvent(jsonSignal)
|
of SignalType.WhisperFilterAdded: WhisperFilterSignal.fromEvent(jsonSignal)
|
||||||
of SignalType.Wallet: WalletSignal.fromEvent(jsonSignal)
|
of SignalType.Wallet: WalletSignal.fromEvent(jsonSignal)
|
||||||
of SignalType.NodeLogin: Json.decode($jsonSignal, NodeSignal)
|
of SignalType.NodeLogin: Json.decode($jsonSignal, NodeSignal)
|
||||||
|
of SignalType.PeerStats: PeerStatsSignal.fromEvent(jsonSignal)
|
||||||
of SignalType.DiscoverySummary: DiscoverySummarySignal.fromEvent(jsonSignal)
|
of SignalType.DiscoverySummary: DiscoverySummarySignal.fromEvent(jsonSignal)
|
||||||
of SignalType.MailserverRequestCompleted: MailserverRequestCompletedSignal.fromEvent(jsonSignal)
|
of SignalType.MailserverRequestCompleted: MailserverRequestCompletedSignal.fromEvent(jsonSignal)
|
||||||
of SignalType.MailserverRequestExpired: MailserverRequestExpiredSignal.fromEvent(jsonSignal)
|
of SignalType.MailserverRequestExpired: MailserverRequestExpiredSignal.fromEvent(jsonSignal)
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
import json
|
||||||
|
import base
|
||||||
|
import signal_type
|
||||||
|
|
||||||
|
type PeerStatsSignal* = ref object of Signal
|
||||||
|
peers*: seq[string]
|
||||||
|
|
||||||
|
proc fromEvent*(T: type PeerStatsSignal, jsonSignal: JsonNode): PeerStatsSignal =
|
||||||
|
result = PeerStatsSignal()
|
||||||
|
result.signalType = SignalType.PeerStats
|
||||||
|
if jsonSignal["event"].kind != JNull:
|
||||||
|
for (node, protocols) in jsonSignal["event"]["peers"].pairs():
|
||||||
|
if protocols.getElems.len != 0:
|
||||||
|
result.peers.add(node)
|
|
@ -19,6 +19,7 @@ type SignalType* {.pure.} = enum
|
||||||
SubscriptionsError = "subscriptions.error"
|
SubscriptionsError = "subscriptions.error"
|
||||||
WhisperFilterAdded = "whisper.filter.added"
|
WhisperFilterAdded = "whisper.filter.added"
|
||||||
CommunityFound = "community.found"
|
CommunityFound = "community.found"
|
||||||
|
PeerStats = "wakuv2.peerstats"
|
||||||
Stats = "stats"
|
Stats = "stats"
|
||||||
ChroniclesLogs = "chronicles-log"
|
ChroniclesLogs = "chronicles-log"
|
||||||
HistoryRequestStarted = "history.request.started"
|
HistoryRequestStarted = "history.request.started"
|
||||||
|
|
|
@ -23,14 +23,19 @@ proc getDefaultNodeConfig*(fleetConfig: FleetConfig, installationId: string): Js
|
||||||
result["ClusterConfig"]["TrustedMailServers"] = %* fleetConfig.getNodes(fleet, FleetNodes.Mailservers)
|
result["ClusterConfig"]["TrustedMailServers"] = %* fleetConfig.getNodes(fleet, FleetNodes.Mailservers)
|
||||||
result["ClusterConfig"]["StaticNodes"] = %* fleetConfig.getNodes(fleet, FleetNodes.Whisper)
|
result["ClusterConfig"]["StaticNodes"] = %* fleetConfig.getNodes(fleet, FleetNodes.Whisper)
|
||||||
result["ClusterConfig"]["RendezvousNodes"] = %* fleetConfig.getNodes(fleet, FleetNodes.Rendezvous)
|
result["ClusterConfig"]["RendezvousNodes"] = %* fleetConfig.getNodes(fleet, FleetNodes.Rendezvous)
|
||||||
result["ClusterConfig"]["WakuNodes"] = %* fleetConfig.getNodes(fleet, FleetNodes.Waku)
|
|
||||||
result["ClusterConfig"]["WakuStoreNodes"] = %* fleetConfig.getNodes(fleet, FleetNodes.Waku)
|
|
||||||
result["NetworkId"] = networkConfig["config"]["NetworkId"]
|
result["NetworkId"] = networkConfig["config"]["NetworkId"]
|
||||||
result["DataDir"] = newDataDir.newJString()
|
result["DataDir"] = newDataDir.newJString()
|
||||||
result["UpstreamConfig"]["Enabled"] = networkConfig["config"]["UpstreamConfig"]["Enabled"]
|
result["UpstreamConfig"]["Enabled"] = networkConfig["config"]["UpstreamConfig"]["Enabled"]
|
||||||
result["UpstreamConfig"]["URL"] = upstreamUrl
|
result["UpstreamConfig"]["URL"] = upstreamUrl
|
||||||
result["ShhextConfig"]["InstallationID"] = newJString(installationId)
|
result["ShhextConfig"]["InstallationID"] = newJString(installationId)
|
||||||
|
|
||||||
|
# TODO: fleet.status.im should have different sections depending on the node type
|
||||||
|
# or maybe it's not necessary because a node has the identify protocol
|
||||||
|
result["ClusterConfig"]["RelayNodes"] = %* fleetConfig.getNodes(fleet, FleetNodes.Waku)
|
||||||
|
result["ClusterConfig"]["StoreNodes"] = %* fleetConfig.getNodes(fleet, FleetNodes.Waku)
|
||||||
|
result["ClusterConfig"]["FilterNodes"] = %* fleetConfig.getNodes(fleet, FleetNodes.Waku)
|
||||||
|
result["ClusterConfig"]["LightpushNodes"] = %* fleetConfig.getNodes(fleet, FleetNodes.Waku)
|
||||||
|
|
||||||
# TODO: commented since it's not necessary (we do the connections thru C bindings). Enable it thru an option once status-nodes are able to be configured in desktop
|
# TODO: commented since it's not necessary (we do the connections thru C bindings). Enable it thru an option once status-nodes are able to be configured in desktop
|
||||||
# result["ListenAddr"] = if existsEnv("STATUS_PORT"): newJString("0.0.0.0:" & $getEnv("STATUS_PORT")) else: newJString("0.0.0.0:30305")
|
# result["ListenAddr"] = if existsEnv("STATUS_PORT"): newJString("0.0.0.0:" & $getEnv("STATUS_PORT")) else: newJString("0.0.0.0:30305")
|
||||||
|
|
||||||
|
|
|
@ -167,7 +167,8 @@ var NODE_CONFIG* = %* {
|
||||||
"WakuV2Config": {
|
"WakuV2Config": {
|
||||||
"Enabled": false,
|
"Enabled": false,
|
||||||
"Host": "0.0.0.0",
|
"Host": "0.0.0.0",
|
||||||
"Port": 0
|
"Port": 0,
|
||||||
|
"LightClient": false
|
||||||
},
|
},
|
||||||
"WalletConfig": {
|
"WalletConfig": {
|
||||||
"Enabled": true
|
"Enabled": true
|
||||||
|
|
|
@ -61,3 +61,24 @@ proc signTypedData*(data: string, address: string, password: string): string =
|
||||||
|
|
||||||
proc getBloomFilter*(): string =
|
proc getBloomFilter*(): string =
|
||||||
return $callPrivateRPC("bloomFilter".prefix, %* []).parseJSON()["result"].getStr
|
return $callPrivateRPC("bloomFilter".prefix, %* []).parseJSON()["result"].getStr
|
||||||
|
|
||||||
|
proc adminPeers*(): seq[string] =
|
||||||
|
let response = callPrivateRPC("admin_peers", %* []).parseJSON()["result"]
|
||||||
|
for jsonPeer in response:
|
||||||
|
result.add(jsonPeer["enode"].getStr)
|
||||||
|
|
||||||
|
proc wakuV2Peers*(): seq[string] =
|
||||||
|
let response = callPrivateRPC("peers".prefix, %* []).parseJSON()["result"]
|
||||||
|
for (id, proto) in response.pairs:
|
||||||
|
if proto.len != 0:
|
||||||
|
result.add(id)
|
||||||
|
|
||||||
|
proc dialPeer*(address: string):bool =
|
||||||
|
let response = callPrivateRPC("dialPeer".prefix, %* [address]).parseJSON()
|
||||||
|
if response.hasKey("error"):
|
||||||
|
error "waku peer could not be dialed", response
|
||||||
|
return false
|
||||||
|
return true
|
||||||
|
|
||||||
|
proc dropPeerByID*(peerID: string) =
|
||||||
|
echo callPrivateRPC("dropPeer".prefix, %* [peerID])
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
import json, times, chronicles
|
import json, times, chronicles
|
||||||
import core, ../utils
|
import core, ../utils
|
||||||
|
|
||||||
proc ping*(mailservers: seq[string], timeoutMs: int): string =
|
proc ping*(mailservers: seq[string], timeoutMs: int, isWakuV2: bool = false): string =
|
||||||
var addresses: seq[string] = @[]
|
var addresses: seq[string] = @[]
|
||||||
for mailserver in mailservers:
|
for mailserver in mailservers:
|
||||||
addresses.add(mailserver)
|
addresses.add(mailserver)
|
||||||
result = callPrivateRPC("mailservers_ping", %* [
|
var rpcMethod = if isWakuV2: "mailservers_multiAddressPing" else: "mailservers_ping"
|
||||||
|
result = callPrivateRPC(rpcMethod, %* [
|
||||||
{ "addresses": addresses, "timeoutMs": timeoutMs }
|
{ "addresses": addresses, "timeoutMs": timeoutMs }
|
||||||
])
|
])
|
||||||
info "ping", topics="mailserver-interaction", rpc_method="mailservers_ping", addresses, timeoutMs, result
|
info "ping", topics="mailserver-interaction", rpc_method="mailservers_ping", addresses, timeoutMs, result
|
||||||
|
|
|
@ -212,8 +212,13 @@ proc setFleet*(fleetConfig: FleetConfig, fleet: Fleet): StatusGoError =
|
||||||
nodeConfig["ClusterConfig"]["TrustedMailServers"] = %* fleetConfig.getNodes(fleet, FleetNodes.Mailservers)
|
nodeConfig["ClusterConfig"]["TrustedMailServers"] = %* fleetConfig.getNodes(fleet, FleetNodes.Mailservers)
|
||||||
nodeConfig["ClusterConfig"]["StaticNodes"] = %* fleetConfig.getNodes(fleet, FleetNodes.Whisper)
|
nodeConfig["ClusterConfig"]["StaticNodes"] = %* fleetConfig.getNodes(fleet, FleetNodes.Whisper)
|
||||||
nodeConfig["ClusterConfig"]["RendezvousNodes"] = %* fleetConfig.getNodes(fleet, FleetNodes.Rendezvous)
|
nodeConfig["ClusterConfig"]["RendezvousNodes"] = %* fleetConfig.getNodes(fleet, FleetNodes.Rendezvous)
|
||||||
nodeConfig["ClusterConfig"]["WakuNodes"] = %* fleetConfig.getNodes(fleet, FleetNodes.Waku)
|
nodeConfig["ClusterConfig"]["RelayNodes"] = %* fleetConfig.getNodes(fleet, FleetNodes.Waku)
|
||||||
nodeConfig["ClusterConfig"]["WakuStoreNodes"] = %* fleetConfig.getNodes(fleet, FleetNodes.Waku)
|
nodeConfig["ClusterConfig"]["StoreNodes"] = %* fleetConfig.getNodes(fleet, FleetNodes.Waku)
|
||||||
|
nodeConfig["ClusterConfig"]["FilterNodes"] = %* fleetConfig.getNodes(fleet, FleetNodes.Waku)
|
||||||
|
nodeConfig["ClusterConfig"]["LightpushNodes"] = %* fleetConfig.getNodes(fleet, FleetNodes.Waku)
|
||||||
return saveSetting(Setting.NodeConfig, nodeConfig)
|
return saveSetting(Setting.NodeConfig, nodeConfig)
|
||||||
|
|
||||||
|
proc setV2LightMode*(enabled: bool): StatusGoError =
|
||||||
|
var nodeConfig = getNodeConfig()
|
||||||
|
nodeConfig["WakuV2Config"]["LightClient"] = newJBool(enabled)
|
||||||
|
return saveSetting(Setting.NodeConfig, nodeConfig)
|
||||||
|
|
|
@ -44,9 +44,13 @@ proc getNodes*(self: FleetConfig, fleet: Fleet, nodeType: FleetNodes = FleetNode
|
||||||
if not self.fleet[$fleet].hasKey($nodeType): return
|
if not self.fleet[$fleet].hasKey($nodeType): return
|
||||||
result = toSeq(self.fleet[$fleet][$nodeType].values)
|
result = toSeq(self.fleet[$fleet][$nodeType].values)
|
||||||
|
|
||||||
proc getMailservers*(self: FleetConfig, fleet: Fleet): Table[string, string] =
|
proc getMailservers*(self: FleetConfig, fleet: Fleet, isWakuV2: bool): Table[string, string] =
|
||||||
if not self.fleet[$fleet].hasKey($FleetNodes.Mailservers):
|
# TODO: If using wakuV2, this assumes that Waku nodes in fleet.status.json are also store nodes.
|
||||||
|
# Maybe it make senses to add a "waku-store" section in case we want to have separate node types?
|
||||||
|
# Discuss with @iurimatias, @cammellos and Vac team
|
||||||
|
let fleetKey = if isWakuV2: $FleetNodes.Waku else: $FleetNodes.Mailservers
|
||||||
|
if not self.fleet[$fleet].hasKey(fleetKey) :
|
||||||
result = initTable[string,string]()
|
result = initTable[string,string]()
|
||||||
return
|
return
|
||||||
result = self.fleet[$fleet][$FleetNodes.Mailservers]
|
result = self.fleet[$fleet][fleetKey]
|
||||||
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit cee18efd710756c662c19ea9b167a47112847388
|
Subproject commit 51493d61bdb71cbac06acbd120d23f434082cfa4
|
Loading…
Reference in New Issue