mirror of
https://github.com/waku-org/nwaku.git
synced 2025-01-27 07:06:42 +00:00
feat: adding json string support to bindings config (#2685)
This commit is contained in:
parent
026d804a0d
commit
be5471c6f3
@ -269,13 +269,13 @@ int main(int argc, char** argv) {
|
||||
|
||||
char jsonConfig[2048];
|
||||
snprintf(jsonConfig, 2048, "{ \
|
||||
\"host\": \"%s\", \
|
||||
\"port\": %d, \
|
||||
\"key\": \"%s\", \
|
||||
\"listenAddress\": \"%s\", \
|
||||
\"tcpPort\": %d, \
|
||||
\"nodekey\": \"%s\", \
|
||||
\"relay\": %s, \
|
||||
\"store\": %s, \
|
||||
\"storeDbUrl\": \"%s\", \
|
||||
\"storeRetentionPolicy\": \"%s\", \
|
||||
\"storeMessageDbUrl\": \"%s\", \
|
||||
\"storeMessageRetentionPolicy\": \"%s\", \
|
||||
\"storeMaxNumDbConnections\": %d \
|
||||
}", cfgNode.host,
|
||||
cfgNode.port,
|
||||
|
@ -1,272 +0,0 @@
|
||||
import std/[json, strformat, options]
|
||||
import std/sequtils
|
||||
import
|
||||
libp2p/crypto/crypto,
|
||||
libp2p/crypto/secp,
|
||||
stew/shims/net,
|
||||
../../waku/waku_enr/capabilities,
|
||||
../../waku/common/utils/nat,
|
||||
../../waku/factory/external_config,
|
||||
../../waku/waku_core/message/default_values,
|
||||
../../waku/node/waku_node,
|
||||
../../waku/node/config,
|
||||
../events/json_base_event
|
||||
|
||||
proc parsePrivateKey(
|
||||
jsonNode: JsonNode, conf: var WakuNodeConf, errorResp: var string
|
||||
): bool =
|
||||
if not jsonNode.contains("key") or jsonNode["key"].kind == JsonNodeKind.JNull:
|
||||
conf.nodekey = some(PrivateKey.random(Secp256k1, newRng()[]).tryGet())
|
||||
return true
|
||||
|
||||
if jsonNode["key"].kind != JsonNodeKind.JString:
|
||||
errorResp = "The node key should be a string."
|
||||
return false
|
||||
|
||||
let key = jsonNode["key"].getStr()
|
||||
|
||||
try:
|
||||
let skPrivKey = SkPrivateKey.init(crypto.fromHex(key)).tryGet()
|
||||
conf.nodekey = some(crypto.PrivateKey(scheme: Secp256k1, skkey: skPrivKey))
|
||||
except CatchableError:
|
||||
let msg = "Invalid node key: " & getCurrentExceptionMsg()
|
||||
errorResp = msg
|
||||
return false
|
||||
|
||||
return true
|
||||
|
||||
proc parseListenAddr(
|
||||
jsonNode: JsonNode, conf: var WakuNodeConf, errorResp: var string
|
||||
): bool =
|
||||
var listenAddr: IpAddress
|
||||
if not jsonNode.contains("host"):
|
||||
conf.listenAddress = defaultListenAddress()
|
||||
return true
|
||||
|
||||
if jsonNode["host"].kind != JsonNodeKind.JString:
|
||||
errorResp = "The node host should be a string."
|
||||
return false
|
||||
|
||||
let host = jsonNode["host"].getStr()
|
||||
|
||||
try:
|
||||
listenAddr = parseIpAddress(host)
|
||||
except CatchableError:
|
||||
let msg = "Invalid host IP address: " & getCurrentExceptionMsg()
|
||||
errorResp = msg
|
||||
return false
|
||||
|
||||
return true
|
||||
|
||||
proc parsePort(jsonNode: JsonNode, conf: var WakuNodeConf, errorResp: var string): bool =
|
||||
if not jsonNode.contains("port"):
|
||||
conf.tcpPort = Port(60000)
|
||||
return true
|
||||
|
||||
if jsonNode["port"].kind != JsonNodeKind.JInt:
|
||||
errorResp = "The node port should be an integer."
|
||||
return false
|
||||
|
||||
conf.tcpPort = Port(jsonNode["port"].getInt())
|
||||
|
||||
return true
|
||||
|
||||
proc parseRelay(jsonNode: JsonNode, conf: var WakuNodeConf, errorResp: var string): bool =
|
||||
if not jsonNode.contains("relay"):
|
||||
errorResp = "relay attribute is required"
|
||||
return false
|
||||
|
||||
if jsonNode["relay"].kind != JsonNodeKind.JBool:
|
||||
errorResp = "The relay config param should be a boolean"
|
||||
return false
|
||||
|
||||
conf.relay = jsonNode["relay"].getBool()
|
||||
|
||||
return true
|
||||
|
||||
proc parseClusterId(jsonNode: JsonNode, conf: var WakuNodeConf, errorResp: var string): bool =
|
||||
if not jsonNode.contains("relay"):
|
||||
errorResp = "relay attribute is required"
|
||||
return false
|
||||
|
||||
if jsonNode.contains("clusterId"):
|
||||
if jsonNode["clusterId"].kind != JsonNodeKind.JInt:
|
||||
errorResp = "The clusterId config param should be an int"
|
||||
return false
|
||||
else:
|
||||
conf.clusterId = uint32(jsonNode["clusterId"].getInt())
|
||||
|
||||
return true
|
||||
|
||||
proc parseStore(
|
||||
jsonNode: JsonNode,
|
||||
conf: var WakuNodeConf,
|
||||
errorResp: var string,
|
||||
): bool =
|
||||
if not jsonNode.contains("store"):
|
||||
## the store parameter is not required. By default is is disabled
|
||||
conf.store = false
|
||||
return true
|
||||
|
||||
if jsonNode["store"].kind != JsonNodeKind.JBool:
|
||||
errorResp = "The store config param should be a boolean"
|
||||
return false
|
||||
|
||||
conf.store = jsonNode["store"].getBool()
|
||||
|
||||
if jsonNode.contains("storeNode"):
|
||||
if jsonNode["storeNode"].kind != JsonNodeKind.JString:
|
||||
errorResp = "The storeNode config param should be a string"
|
||||
return false
|
||||
|
||||
conf.storeNode = jsonNode["storeNode"].getStr()
|
||||
|
||||
if jsonNode.contains("storeRetentionPolicy"):
|
||||
if jsonNode["storeRetentionPolicy"].kind != JsonNodeKind.JString:
|
||||
errorResp = "The storeRetentionPolicy config param should be a string"
|
||||
return false
|
||||
|
||||
conf.storeMessageRetentionPolicy = jsonNode["storeRetentionPolicy"].getStr()
|
||||
|
||||
if jsonNode.contains("storeDbUrl"):
|
||||
if jsonNode["storeDbUrl"].kind != JsonNodeKind.JString:
|
||||
errorResp = "The storeDbUrl config param should be a string"
|
||||
return false
|
||||
|
||||
conf.storeMessageDbUrl = jsonNode["storeDbUrl"].getStr()
|
||||
|
||||
if jsonNode.contains("storeVacuum"):
|
||||
if jsonNode["storeVacuum"].kind != JsonNodeKind.JBool:
|
||||
errorResp = "The storeVacuum config param should be a bool"
|
||||
return false
|
||||
|
||||
conf.storeMessageDbVacuum = jsonNode["storeVacuum"].getBool()
|
||||
|
||||
if jsonNode.contains("storeDbMigration"):
|
||||
if jsonNode["storeDbMigration"].kind != JsonNodeKind.JBool:
|
||||
errorResp = "The storeDbMigration config param should be a bool"
|
||||
return false
|
||||
|
||||
conf.storeMessageDbMigration = jsonNode["storeDbMigration"].getBool()
|
||||
|
||||
if jsonNode.contains("storeMaxNumDbConnections"):
|
||||
if jsonNode["storeMaxNumDbConnections"].kind != JsonNodeKind.JInt:
|
||||
errorResp = "The storeMaxNumDbConnections config param should be an int"
|
||||
return false
|
||||
|
||||
conf.storeMaxNumDbConnections = jsonNode["storeMaxNumDbConnections"].getInt()
|
||||
|
||||
return true
|
||||
|
||||
proc parseTopics(jsonNode: JsonNode, conf: var WakuNodeConf) =
|
||||
if jsonNode.contains("pubsubTopics"):
|
||||
for topic in jsonNode["pubsubTopics"].items:
|
||||
conf.pubsubTopics.add(topic.getStr())
|
||||
else:
|
||||
conf.pubsubTopics = @["/waku/2/default-waku/proto"]
|
||||
|
||||
proc parseRLNRelay(jsonNode: JsonNode, conf: var WakuNodeConf, errorResp: var string): bool =
|
||||
if not jsonNode.contains("rln-relay"):
|
||||
return true
|
||||
|
||||
let jsonNode = jsonNode["rln-relay"]
|
||||
if not jsonNode.contains("enabled"):
|
||||
errorResp = "rlnRelay.enabled attribute is required"
|
||||
return false
|
||||
|
||||
conf.rlnRelay = jsonNode["enabled"].getBool()
|
||||
conf.rlnRelayCredPath = jsonNode{"cred-path"}.getStr()
|
||||
conf.rlnRelayEthClientAddress = EthRpcUrl.parseCmdArg(jsonNode{"eth-client-address"}.getStr("http://localhost:8540"))
|
||||
conf.rlnRelayEthContractAddress = jsonNode{"eth-contract-address"}.getStr()
|
||||
conf.rlnRelayCredPassword = jsonNode{"cred-password"}.getStr()
|
||||
conf.rlnRelayUserMessageLimit = uint64(jsonNode{"user-message-limit"}.getInt(1))
|
||||
conf.rlnEpochSizeSec = uint64(jsonNode{"epoch-sec"}.getInt(1))
|
||||
conf.rlnRelayCredIndex = some(uint(jsonNode{"membership-index"}.getInt()))
|
||||
conf.rlnRelayDynamic = jsonNode{"dynamic"}.getBool()
|
||||
conf.rlnRelayTreePath = jsonNode{"tree-path"}.getStr()
|
||||
conf.rlnRelayBandwidthThreshold = jsonNode{"bandwidth-threshold"}.getInt()
|
||||
|
||||
return true
|
||||
|
||||
proc parseConfig*(
|
||||
configNodeJson: string,
|
||||
conf: var WakuNodeConf,
|
||||
errorResp: var string,
|
||||
): bool {.raises: [].} =
|
||||
if configNodeJson.len == 0:
|
||||
errorResp = "The configNodeJson is empty"
|
||||
return false
|
||||
|
||||
var jsonNode: JsonNode
|
||||
try:
|
||||
jsonNode = parseJson(configNodeJson)
|
||||
except Exception, IOError, JsonParsingError:
|
||||
errorResp = "Exception: " & getCurrentExceptionMsg()
|
||||
return false
|
||||
|
||||
# key
|
||||
try:
|
||||
if not parsePrivateKey(jsonNode, conf, errorResp):
|
||||
return false
|
||||
except Exception, KeyError:
|
||||
errorResp = "Exception calling parsePrivateKey: " & getCurrentExceptionMsg()
|
||||
return false
|
||||
|
||||
# listenAddr
|
||||
var listenAddr: IpAddress
|
||||
try:
|
||||
listenAddr = parseIpAddress("127.0.0.1")
|
||||
if not parseListenAddr(jsonNode, conf, errorResp):
|
||||
return false
|
||||
except Exception, ValueError:
|
||||
errorResp = "Exception calling parseIpAddress: " & getCurrentExceptionMsg()
|
||||
return false
|
||||
|
||||
# port
|
||||
try:
|
||||
if not parsePort(jsonNode, conf, errorResp):
|
||||
return false
|
||||
except Exception, ValueError:
|
||||
errorResp = "Exception calling parsePort: " & getCurrentExceptionMsg()
|
||||
return false
|
||||
|
||||
# relay
|
||||
try:
|
||||
if not parseRelay(jsonNode, conf, errorResp):
|
||||
return false
|
||||
except Exception, KeyError:
|
||||
errorResp = "Exception calling parseRelay: " & getCurrentExceptionMsg()
|
||||
return false
|
||||
|
||||
# clusterId
|
||||
try:
|
||||
if not parseClusterId(jsonNode, conf, errorResp):
|
||||
return false
|
||||
except Exception, KeyError:
|
||||
errorResp = "Exception calling parseClusterId: " & getCurrentExceptionMsg()
|
||||
return false
|
||||
|
||||
# topics
|
||||
try:
|
||||
parseTopics(jsonNode, conf)
|
||||
except Exception, KeyError:
|
||||
errorResp = "Exception calling parseTopics: " & getCurrentExceptionMsg()
|
||||
return false
|
||||
|
||||
# store
|
||||
try:
|
||||
if not parseStore(jsonNode, conf, errorResp):
|
||||
return false
|
||||
except Exception, KeyError:
|
||||
errorResp = "Exception calling parseStore: " & getCurrentExceptionMsg()
|
||||
return false
|
||||
|
||||
# rln
|
||||
try:
|
||||
if not parseRLNRelay(jsonNode, conf, errorResp):
|
||||
return false
|
||||
except Exception, KeyError:
|
||||
errorResp = "Exception calling parseRLNRelay: " & getCurrentExceptionMsg()
|
||||
return false
|
||||
|
||||
return true
|
@ -1,6 +1,6 @@
|
||||
import std/options
|
||||
import std/sequtils
|
||||
import chronos, chronicles, stew/results, stew/shims/net
|
||||
import std/[options, sequtils, json, strutils]
|
||||
import chronos, chronicles, stew/results, stew/shims/net, confutils, confutils/std/net
|
||||
|
||||
import
|
||||
../../../../waku/common/enr/builder,
|
||||
../../../../waku/waku_enr/capabilities,
|
||||
@ -24,8 +24,7 @@ import
|
||||
../../../../waku/factory/node_factory,
|
||||
../../../../waku/factory/networks_config,
|
||||
../../../events/[json_message_event, json_base_event],
|
||||
../../../alloc,
|
||||
../../config
|
||||
../../../alloc
|
||||
|
||||
type NodeLifecycleMsgType* = enum
|
||||
CREATE_NODE
|
||||
@ -49,19 +48,22 @@ proc destroyShared(self: ptr NodeLifecycleRequest) =
|
||||
deallocShared(self)
|
||||
|
||||
proc createWaku(configJson: cstring): Future[Result[Waku, string]] {.async.} =
|
||||
var conf: WakuNodeConf
|
||||
var conf = defaultWakuNodeConf().valueOr:
|
||||
return err("Failed creating node: " & error)
|
||||
|
||||
var errorResp: string
|
||||
|
||||
try:
|
||||
if not parseConfig($configJson, conf, errorResp):
|
||||
return err(errorResp)
|
||||
except Exception:
|
||||
return err("exception calling parseConfig: " & getCurrentExceptionMsg())
|
||||
let jsonNode = parseJson($configJson)
|
||||
|
||||
# TODO: figure out how to extract default values from the config pragma
|
||||
conf.nat = "any"
|
||||
conf.maxConnections = 50.uint16
|
||||
conf.maxMessageSize = default_values.DefaultMaxWakuMessageSizeStr
|
||||
for confField, confValue in fieldPairs(conf):
|
||||
if jsonNode.contains(confField):
|
||||
# Make sure string doesn't contain the leading or trailing " character
|
||||
let formattedString = ($jsonNode[confField]).strip(chars = {'\"'})
|
||||
# Override conf field with the value set in the json-string
|
||||
confValue = parseCmdArg(typeof(confValue), formattedString)
|
||||
except Exception:
|
||||
return err("exception parsing configuration: " & getCurrentExceptionMsg())
|
||||
|
||||
# The Waku Network config (cluster-id=1)
|
||||
if conf.clusterId == 1:
|
||||
|
@ -1,5 +1,5 @@
|
||||
import
|
||||
std/strutils,
|
||||
std/[strutils, strformat],
|
||||
stew/results,
|
||||
chronos,
|
||||
regex,
|
||||
@ -12,7 +12,8 @@ import
|
||||
libp2p/crypto/secp,
|
||||
libp2p/multiaddress,
|
||||
nimcrypto/utils,
|
||||
secp256k1
|
||||
secp256k1,
|
||||
json
|
||||
import
|
||||
../common/confutils/envvar/defs as confEnvvarDefs,
|
||||
../common/confutils/envvar/std/net as confEnvvarNet,
|
||||
@ -613,6 +614,22 @@ proc parseCmdArg*(T: type crypto.PrivateKey, p: string): T =
|
||||
except CatchableError:
|
||||
raise newException(ValueError, "Invalid private key")
|
||||
|
||||
proc parseCmdArg*[T](_: type seq[T], s: string): seq[T] {.raises: [ValueError].} =
|
||||
var
|
||||
inputSeq: JsonNode
|
||||
res: seq[T] = @[]
|
||||
|
||||
try:
|
||||
inputSeq = s.parseJson()
|
||||
except Exception:
|
||||
raise newException(ValueError, fmt"Could not parse sequence: {s}")
|
||||
|
||||
for entry in inputSeq:
|
||||
let formattedString = ($entry).strip(chars = {'\"'})
|
||||
res.add(parseCmdArg(T, formattedString))
|
||||
|
||||
return res
|
||||
|
||||
proc completeCmdArg*(T: type crypto.PrivateKey, val: string): seq[string] =
|
||||
return @[]
|
||||
|
||||
@ -632,12 +649,6 @@ proc parseCmdArg*(T: type ProtectedTopic, p: string): T =
|
||||
proc completeCmdArg*(T: type ProtectedTopic, val: string): seq[string] =
|
||||
return @[]
|
||||
|
||||
proc parseCmdArg*(T: type IpAddress, p: string): T =
|
||||
try:
|
||||
parseIpAddress(p)
|
||||
except CatchableError:
|
||||
raise newException(ValueError, "Invalid IP address")
|
||||
|
||||
proc completeCmdArg*(T: type IpAddress, val: string): seq[string] =
|
||||
return @[]
|
||||
|
||||
@ -649,21 +660,9 @@ proc defaultListenAddress*(): IpAddress =
|
||||
proc defaultColocationLimit*(): int =
|
||||
return DefaultColocationLimit
|
||||
|
||||
proc parseCmdArg*(T: type Port, p: string): T =
|
||||
try:
|
||||
Port(parseInt(p))
|
||||
except CatchableError:
|
||||
raise newException(ValueError, "Invalid Port number")
|
||||
|
||||
proc completeCmdArg*(T: type Port, val: string): seq[string] =
|
||||
return @[]
|
||||
|
||||
proc parseCmdArg*(T: type Option[int], p: string): T =
|
||||
try:
|
||||
some(parseInt(p))
|
||||
except CatchableError:
|
||||
raise newException(ValueError, "Invalid number")
|
||||
|
||||
proc completeCmdArg*(T: type ShardIdx, val: string): seq[ShardIdx] =
|
||||
return @[]
|
||||
|
||||
@ -673,12 +672,6 @@ proc parseCmdArg*(T: type ShardIdx, p: string): T =
|
||||
except CatchableError:
|
||||
raise newException(ValueError, "Invalid shard index")
|
||||
|
||||
proc parseCmdArg*(T: type Option[uint], p: string): T =
|
||||
try:
|
||||
some(parseUint(p))
|
||||
except CatchableError:
|
||||
raise newException(ValueError, "Invalid unsigned integer")
|
||||
|
||||
proc completeCmdArg*(T: type EthRpcUrl, val: string): seq[string] =
|
||||
return @[]
|
||||
|
||||
@ -790,4 +783,11 @@ proc load*(T: type WakuNodeConf, version = ""): ConfResult[T] =
|
||||
except CatchableError:
|
||||
err(getCurrentExceptionMsg())
|
||||
|
||||
proc defaultWakuNodeConf*(): ConfResult[WakuNodeConf] =
|
||||
try:
|
||||
let conf = WakuNodeConf.load(version = "", cmdLine = @[])
|
||||
return ok(conf)
|
||||
except CatchableError:
|
||||
return err("exception in defaultWakuNodeConf: " & getCurrentExceptionMsg())
|
||||
|
||||
{.pop.}
|
||||
|
Loading…
x
Reference in New Issue
Block a user