diff --git a/library/libwaku_conf.nim b/library/libwaku_conf.nim new file mode 100644 index 000000000..33c915cd1 --- /dev/null +++ b/library/libwaku_conf.nim @@ -0,0 +1,100 @@ +import + std/options, + results, + waku/factory/waku_conf, + waku/factory/conf_builder/conf_builder, + waku/factory/networks_config + +type ShardingMode* = enum + AutoSharding = "auto" + StaticSharding = "static" + +type AutoShardingConf* = object + numShardsInCluster*: uint16 + +type RlnConfig* = object + contractAddress*: string + chainId*: uint + epochSizeSec*: uint64 + +type MessageValidation* = object + maxMessageSizeBytes*: uint64 + rlnConfig*: Option[RlnConfig] + +type NetworkConf* = object + bootstrapNodes*: seq[string] + staticStoreNodes*: seq[string] + clusterId*: uint16 + shardingMode*: ShardingMode + autoShardingConf*: Option[AutoShardingConf] + messageValidation*: Option[MessageValidation] + +type WakuMode* = enum + Edge = "edge" + Relay = "relay" + +type LibWakuConf* = object + mode*: WakuMode + networkConf*: NetworkConf + storeConfirmation*: bool + +proc toWakuConf*(libConf: LibWakuConf): Result[WakuConf, string] = + var b = WakuConfBuilder.init() + + case libConf.mode + of Relay: + b.withRelay(true) + + b.filterServiceConf.withEnabled(true) + b.filterServiceConf.withMaxPeersToServe(20) + + b.withLightPush(true) + + b.discv5Conf.withEnabled(true) + b.withPeerExchange(true) + + b.rateLimitConf.withRateLimits(@["filter:100/1s", "lightpush:5/1s", "px:5/1s"]) + of Edge: + return err("Edge mode is not implemented") + + #TODO: store confirmation + + ## Network Conf + let networkConf = libConf.networkConf + + # Set cluster ID + b.withClusterId(networkConf.clusterId) + + # Set sharding configuration + case networkConf.shardingMode + of AutoSharding: + b.withShardingConf(ShardingConfKind.AutoSharding) + if networkConf.autoShardingConf.isSome(): + let autoConf = networkConf.autoShardingConf.get() + b.withNumShardsInCluster(autoConf.numShardsInCluster) + of StaticSharding: + b.withShardingConf(ShardingConfKind.StaticSharding) + + # Set bootstrap nodes + if networkConf.bootstrapNodes.len > 0: + b.discv5Conf.withBootstrapNodes(networkConf.bootstrapNodes) + + # TODO: verify behaviour + # Set static store nodes + if networkConf.staticStoreNodes.len > 0: + b.withStaticNodes(networkConf.staticStoreNodes) + + # Set message validation + if networkConf.messageValidation.isSome(): + let msgValidation = networkConf.messageValidation.get() + b.withMaxMessageSize(msgValidation.maxMessageSizeBytes) + + # Set RLN config if provided + if msgValidation.rlnConfig.isSome(): + let rlnConfig = msgValidation.rlnConfig.get() + b.rlnRelayConf.withEnabled(true) + b.rlnRelayConf.withEthContractAddress(rlnConfig.contractAddress) + b.rlnRelayConf.withChainId(rlnConfig.chainId) + b.rlnRelayConf.withEpochSizeSec(rlnConfig.epochSizeSec) + + return b.build() diff --git a/tests/all_tests_waku.nim b/tests/all_tests_waku.nim index aac92863a..2f9c31f39 100644 --- a/tests/all_tests_waku.nim +++ b/tests/all_tests_waku.nim @@ -96,3 +96,6 @@ import ./waku_rln_relay/test_all # Node Factory import ./factory/test_all + +# Library tests +import ./library/test_all diff --git a/tests/library/test_all.nim b/tests/library/test_all.nim new file mode 100644 index 000000000..561c2eb12 --- /dev/null +++ b/tests/library/test_all.nim @@ -0,0 +1,3 @@ +{.used.} + +import ./test_libwaku_conf diff --git a/tests/library/test_libwaku_conf.nim b/tests/library/test_libwaku_conf.nim new file mode 100644 index 000000000..6678cd295 --- /dev/null +++ b/tests/library/test_libwaku_conf.nim @@ -0,0 +1,291 @@ +{.used.} + +import std/options, results, stint, testutils/unittests +import library/libwaku_conf, waku/factory/waku_conf, waku/factory/networks_config + +suite "LibWaku Conf - toWakuConf": + test "Relay mode configuration": + ## Given + let libConf = LibWakuConf( + mode: Relay, + networkConf: libwaku_conf.NetworkConf( + bootstrapNodes: @[], + staticStoreNodes: @[], + clusterId: 1, + shardingMode: StaticSharding, + autoShardingConf: none(AutoShardingConf), + messageValidation: none(MessageValidation), + ), + storeConfirmation: false, + ) + + ## When + let wakuConfRes = toWakuConf(libConf) + + ## Then + require wakuConfRes.isOk() + let wakuConf = wakuConfRes.get() + check: + wakuConf.relay == true + wakuConf.lightPush == true + wakuConf.peerExchangeService == true + wakuConf.clusterId == 1 + wakuConf.shardingConf.kind == ShardingConfKind.StaticSharding + + test "Auto-sharding configuration": + ## Given + let libConf = LibWakuConf( + mode: Relay, + networkConf: libwaku_conf.NetworkConf( + bootstrapNodes: @[], + staticStoreNodes: @[], + clusterId: 42, + shardingMode: AutoSharding, + autoShardingConf: some(AutoShardingConf(numShardsInCluster: 16)), + messageValidation: none(MessageValidation), + ), + storeConfirmation: false, + ) + + ## When + let wakuConfRes = toWakuConf(libConf) + + ## Then + require wakuConfRes.isOk() + let wakuConf = wakuConfRes.get() + check: + wakuConf.clusterId == 42 + wakuConf.shardingConf.kind == ShardingConfKind.AutoSharding + wakuConf.shardingConf.numShardsInCluster == 16 + + test "Bootstrap nodes configuration": + ## Given + let bootstrapNodes = + @[ + "enr:-QESuEC1p_s3xJzAC_XlOuuNrhVUETmfhbm1wxRGis0f7DlqGSw2FM-p2Vn7gmfkTTnAe8Ys2cgGBN8ufJnvzKQFZqFMBgmlkgnY0iXNlY3AyNTZrMaEDS8-D878DrdbNwcuY-3p1qdDp5MOoCurhdsNPJTXZ3c5g3RjcIJ2X4N1ZHCCd2g", + "enr:-QEkuECnZ3IbVAgkOzv-QLnKC4dRKAPRY80m1-R7G8jZ7yfT3ipEfBrhKN7ARcQgQ-vg-h40AQzyvAkPYlHPaFKk6u9MBgmlkgnY0iXNlY3AyNTZrMaEDk49D8JjMSns4p1XVNBvJquOUzT4PENSJknkROspfAFGg3RjcIJ2X4N1ZHCCd2g", + ] + let libConf = LibWakuConf( + mode: Relay, + networkConf: libwaku_conf.NetworkConf( + bootstrapNodes: bootstrapNodes, + staticStoreNodes: @[], + clusterId: 1, + shardingMode: StaticSharding, + autoShardingConf: none(AutoShardingConf), + messageValidation: none(MessageValidation), + ), + storeConfirmation: false, + ) + + ## When + let wakuConfRes = toWakuConf(libConf) + + ## Then + require wakuConfRes.isOk() + let wakuConf = wakuConfRes.get() + require wakuConf.discv5Conf.isSome() + check: + wakuConf.discv5Conf.get().bootstrapNodes == bootstrapNodes + + test "Static store nodes configuration": + ## Given + let staticStoreNodes = + @[ + "/ip4/127.0.0.1/tcp/60000/p2p/16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYc", + "/ip4/192.168.1.1/tcp/60001/p2p/16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYd", + ] + let libConf = LibWakuConf( + mode: Relay, + networkConf: libwaku_conf.NetworkConf( + bootstrapNodes: @[], + staticStoreNodes: staticStoreNodes, + clusterId: 1, + shardingMode: StaticSharding, + autoShardingConf: none(AutoShardingConf), + messageValidation: none(MessageValidation), + ), + storeConfirmation: false, + ) + + ## When + let wakuConfRes = toWakuConf(libConf) + + ## Then + require wakuConfRes.isOk() + let wakuConf = wakuConfRes.get() + check: + wakuConf.staticNodes == staticStoreNodes + + test "Message validation with max message size": + ## Given + let libConf = LibWakuConf( + mode: Relay, + networkConf: libwaku_conf.NetworkConf( + bootstrapNodes: @[], + staticStoreNodes: @[], + clusterId: 1, + shardingMode: StaticSharding, + autoShardingConf: none(AutoShardingConf), + messageValidation: some( + MessageValidation( + maxMessageSizeBytes: 100'u64 * 1024'u64, # 100kB + rlnConfig: none(RlnConfig), + ) + ), + ), + storeConfirmation: false, + ) + + ## When + let wakuConfRes = toWakuConf(libConf) + + ## Then + require wakuConfRes.isOk() + let wakuConf = wakuConfRes.get() + check: + wakuConf.maxMessageSizeBytes == 100'u64 * 1024'u64 + + test "Message validation with RLN config": + ## Given + let libConf = LibWakuConf( + mode: Relay, + networkConf: libwaku_conf.NetworkConf( + bootstrapNodes: @[], + staticStoreNodes: @[], + clusterId: 1, + shardingMode: StaticSharding, + autoShardingConf: none(AutoShardingConf), + messageValidation: some( + MessageValidation( + maxMessageSizeBytes: 150'u64 * 1024'u64, # 150KB + rlnConfig: some( + RlnConfig( + contractAddress: "0x1234567890123456789012345678901234567890", + chainId: 1'u, + epochSizeSec: 600'u64, + ) + ), + ) + ), + ), + storeConfirmation: false, + ) + + ## When + let wakuConfRes = toWakuConf(libConf) + + ## Then + require wakuConfRes.isOk() + let wakuConf = wakuConfRes.get() + check: + wakuConf.maxMessageSizeBytes == 150'u64 * 1024'u64 + + require wakuConf.rlnRelayConf.isSome() + let rlnConf = wakuConf.rlnRelayConf.get() + check: + rlnConf.dynamic == true + rlnConf.ethContractAddress == "0x1234567890123456789012345678901234567890" + rlnConf.chainId == 1'u256 + rlnConf.epochSizeSec == 600'u64 + + test "Full Relay mode configuration with all fields": + ## Given + let libConf = LibWakuConf( + mode: Relay, + networkConf: libwaku_conf.NetworkConf( + bootstrapNodes: + @[ + "enr:-QESuEC1p_s3xJzAC_XlOuuNrhVUETmfhbm1wxRGis0f7DlqGSw2FM-p2Vn7gmfkTTnAe8Ys2cgGBN8ufJnvzKQFZqFMBgmlkgnY0iXNlY3AyNTZrMaEDS8-D878DrdbNwcuY-3p1qdDp5MOoCurhdsNPJTXZ3c5g3RjcIJ2X4N1ZHCCd2g" + ], + staticStoreNodes: + @[ + "/ip4/127.0.0.1/tcp/60000/p2p/16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYc" + ], + clusterId: 99, + shardingMode: AutoSharding, + autoShardingConf: some(AutoShardingConf(numShardsInCluster: 8)), + messageValidation: some( + MessageValidation( + maxMessageSizeBytes: 512'u64 * 1024'u64, # 512KB + rlnConfig: some( + RlnConfig( + contractAddress: "0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + chainId: 5'u, # Goerli + epochSizeSec: 300'u64, + ) + ), + ) + ), + ), + storeConfirmation: true, + ) + + ## When + let wakuConfRes = toWakuConf(libConf) + + ## Then + require wakuConfRes.isOk() + let wakuConf = wakuConfRes.get() + + # Check basic settings + check: + wakuConf.relay == true + wakuConf.lightPush == true + wakuConf.peerExchangeService == true + wakuConf.clusterId == 99 + + # Check sharding + check: + wakuConf.shardingConf.kind == ShardingConfKind.AutoSharding + wakuConf.shardingConf.numShardsInCluster == 8 + + # Check bootstrap nodes + require wakuConf.discv5Conf.isSome() + check: + wakuConf.discv5Conf.get().bootstrapNodes.len == 1 + + # Check static nodes + check: + wakuConf.staticNodes.len == 1 + wakuConf.staticNodes[0] == + "/ip4/127.0.0.1/tcp/60000/p2p/16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYc" + + # Check message validation + check: + wakuConf.maxMessageSizeBytes == 512'u64 * 1024'u64 + + # Check RLN config + require wakuConf.rlnRelayConf.isSome() + let rlnConf = wakuConf.rlnRelayConf.get() + check: + rlnConf.dynamic == true + rlnConf.ethContractAddress == "0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + rlnConf.chainId == 5'u256 + rlnConf.epochSizeSec == 300'u64 + + test "Minimal configuration": + ## Given + let libConf = LibWakuConf( + mode: Relay, + networkConf: libwaku_conf.NetworkConf( + bootstrapNodes: @[], + staticStoreNodes: @[], + clusterId: 0, + shardingMode: StaticSharding, + autoShardingConf: none(AutoShardingConf), + messageValidation: none(MessageValidation), + ), + storeConfirmation: false, + ) + + ## When + let wakuConfRes = toWakuConf(libConf) + + ## Then + require wakuConfRes.isOk() + let wakuConf = wakuConfRes.get() + check: + wakuConf.clusterId == 0 + wakuConf.shardingConf.kind == ShardingConfKind.StaticSharding + wakuConf.staticNodes.len == 0