mirror of
https://github.com/vacp2p/wakurtosis.git
synced 2026-01-09 06:47:58 -05:00
Nomos testing in master (#141)
* Changed gennet to generate simple nomos topology * Added nomos node to build.sh * Updated nomos yaml trait * Added nomos variables to system_variables.star * Prepared nomos_builder.star * Modify gennet to work with nomos topology and traits * Gennet currently doesn't support mixed topologies between waku and nomos nodes. * Restructured config.json to add separated testing and simulation functionalities * Added assertions.star file * Modified wakurtosis to set up integration tests * Updated kurtosis version in README.md
This commit is contained in:
@@ -8,7 +8,7 @@ More info about Kurtosis: https://docs.kurtosis.com/
|
||||
|
||||
#### Before using this repository note that:
|
||||
|
||||
- **You are using Kurtosis version 0.77.0**. This is important, as they are working on it and changes can be huge depending on different versions. You can find all Kurtosis versions [here](https://github.com/kurtosis-tech/kurtosis-cli-release-artifacts/releases).
|
||||
- **You are using Kurtosis version 0.70.2**. This is important, as they are working on it and changes can be huge depending on different versions. You can find all Kurtosis versions [here](https://github.com/kurtosis-tech/kurtosis-cli-release-artifacts/releases).
|
||||
- The topology files that will be used by default are defined in `config/topology_generated/`. This topology is created with the [gennet](gennet-module/Readme.md) module.
|
||||
- Kurtosis can set up services in a parallel manner, defined in the `config.json` file (see below).
|
||||
- Only `kurtosis` and `docker` are needed to run this.
|
||||
|
||||
4
build.sh
4
build.sh
@@ -53,3 +53,7 @@ cd ..
|
||||
#docker build -t gowaku .
|
||||
#cd ..
|
||||
#rm -rf go-waku
|
||||
|
||||
git clone git@github.com:logos-co/nomos-node.git
|
||||
docker build -t nomos-node nomos-node
|
||||
rm -rf nomos-node
|
||||
|
||||
@@ -6,19 +6,32 @@
|
||||
"enclave_name": "wakurtosis",
|
||||
"topology_path": "./config/topology_generated/",
|
||||
"jobs": 4,
|
||||
"interconnect_nodes": false,
|
||||
"interconnection_batch": 10
|
||||
"interconnect_nodes": true,
|
||||
"interconnection_batch": 10,
|
||||
"monitoring": false,
|
||||
"injection": false,
|
||||
"testing": true,
|
||||
"assertions": {
|
||||
"nomos": {
|
||||
"waiting": 60,
|
||||
"nodes_to_check": 1,
|
||||
"endpoint": "/carnot/info",
|
||||
"jq_extract": ".current_view",
|
||||
"expected_value": 10.0
|
||||
}
|
||||
}
|
||||
},
|
||||
"gennet": {
|
||||
"num_nodes": 9,
|
||||
"num_nodes": 5,
|
||||
"fanout": 3,
|
||||
"num_topics": 1,
|
||||
"num_partitions": 1,
|
||||
"num_subnets": 1,
|
||||
"container_size": "1",
|
||||
"node_type_distribution": {
|
||||
"nwaku:relay:rpc:metrics:discv5": 100,
|
||||
"gowaku:rln:dnsdisc:dns": 0
|
||||
"nwaku:relay:rpc:metrics:discv5": 0,
|
||||
"gowaku:rln:dnsdisc:dns": 0,
|
||||
"nomos": 100
|
||||
},
|
||||
"network_type": "newmanwattsstrogatz",
|
||||
"output_dir": "network_data",
|
||||
@@ -26,7 +39,7 @@
|
||||
},
|
||||
"wls": {
|
||||
"debug_level": "DEBUG",
|
||||
"simulation_time": 60,
|
||||
"simulation_time": 20,
|
||||
"message_rate": 10,
|
||||
"min_packet_size": 2,
|
||||
"max_packet_size": 1024,
|
||||
|
||||
25
config/traits/nomos.yml
Normal file
25
config/traits/nomos.yml
Normal file
@@ -0,0 +1,25 @@
|
||||
log:
|
||||
backend: "Stdout"
|
||||
format: "Json"
|
||||
level: "debug"
|
||||
consensus:
|
||||
private_key: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
fountain_settings: null
|
||||
overlay_settings:
|
||||
nodes: [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]]
|
||||
leader:
|
||||
cur: 0
|
||||
leader_super_majority_threshold: null
|
||||
network:
|
||||
backend:
|
||||
host: 0.0.0.0
|
||||
port: 3000
|
||||
log_level: "fatal"
|
||||
nodeKey: null
|
||||
discV5BootstrapNodes: []
|
||||
initial_peers: []
|
||||
relayTopics: []
|
||||
http:
|
||||
backend:
|
||||
address: 0.0.0.0:8080
|
||||
cors_origins: []
|
||||
@@ -14,9 +14,13 @@ from pathlib import Path
|
||||
import time, tracemalloc
|
||||
import string
|
||||
import typer
|
||||
import yaml
|
||||
import hashlib
|
||||
|
||||
from enum import Enum, EnumMeta
|
||||
|
||||
from blspy import PrivateKey, Util, BasicSchemeMPL, G2Element, G1Element
|
||||
|
||||
# Enums & Consts
|
||||
|
||||
class MetaEnum(EnumMeta):
|
||||
@@ -49,15 +53,19 @@ class Trait(BaseEnum):
|
||||
STORE = "store"
|
||||
SWAP = "swap"
|
||||
WEBSOCKET = "websocket"
|
||||
NOMOS = "nomos"
|
||||
|
||||
# To add a new node type, add appropriate entries to the nodeType and nodeTypeToDocker
|
||||
class nodeType(BaseEnum):
|
||||
NWAKU = "nwaku" # waku desktop config
|
||||
GOWAKU = "gowaku" # waku mobile config
|
||||
NOMOS = "nomos"
|
||||
|
||||
nodeTypeToDocker = {
|
||||
nodeType.NWAKU: "nim-waku",
|
||||
nodeType.GOWAKU: "go-waku"
|
||||
nodeType.GOWAKU: "go-waku",
|
||||
nodeType.NOMOS: "nomos"
|
||||
|
||||
}
|
||||
|
||||
# To add a new network type, add appropriate entries to the networkType and networkTypeSwitch
|
||||
@@ -332,7 +340,7 @@ def validate_traits_distribution(traits_dir, traits_distribution):
|
||||
if traits_list[0] not in nodeType:
|
||||
raise ValueError(f"{traits_distribution} : unknown node type {traits_list[0]} in {s}")
|
||||
for t in traits_list[1:]:
|
||||
if t not in Trait and not os.path.exists(f"{traits_dir}/{t}.toml"):
|
||||
if t not in Trait and not (os.path.exists(f"{traits_dir}/{t}.toml") or os.path.exists(f"{traits_dir}/{t}.yml")):
|
||||
raise ValueError(f"{traits_distribution} : unknown trait {t} in {s}")
|
||||
|
||||
|
||||
@@ -406,6 +414,63 @@ def generate_and_write_files(ctx: typer, G):
|
||||
write_json(ctx.params["output_dir"], json_dump) # network wide json
|
||||
|
||||
|
||||
def generate_and_write_files_nomos(ctx: typer, G):
|
||||
node2subnet = generate_subnets(G, ctx.params["num_subnets"])
|
||||
node2container = pack_nodes(ctx.params["container_size"], node2subnet)
|
||||
container2nodes = invert_dict_of_list(node2container, 1)
|
||||
|
||||
json_dump, json_dump[CONTAINERS_JSON], json_dump[NODES_JSON] = {}, {}, {}
|
||||
for container, nodes in container2nodes.items():
|
||||
json_dump[CONTAINERS_JSON][container] = nodes
|
||||
|
||||
# TODO Put in json_dump[PUBLIC_KEYS] all public keys
|
||||
json_dump["all_public_keys"] = []
|
||||
|
||||
for node in G.nodes:
|
||||
json_dump[NODES_JSON][node] = {}
|
||||
json_dump[NODES_JSON][node]["static_nodes"] = []
|
||||
for edge in G.edges(node):
|
||||
json_dump[NODES_JSON][node]["static_nodes"].append(edge[1])
|
||||
json_dump[NODES_JSON][node][SUBNET_PREFIX] = node2subnet[node]
|
||||
json_dump[NODES_JSON][node]["image"] = nodeTypeToDocker.get(nodeType.NOMOS)
|
||||
# the per node tomls will continue for now as they include topics
|
||||
json_dump[NODES_JSON][node]["node_config"] = f"{node}.yml"
|
||||
# logs ought to continue as they need to be unique
|
||||
json_dump[NODES_JSON][node]["node_log"] = f"{node}.log"
|
||||
port_shift, cid = node2container[node]
|
||||
json_dump[NODES_JSON][node]["container_id"] = cid
|
||||
# TODO put in json_dump[NODES_JSON]
|
||||
seed = bytes([random.randint(0, 255) for _ in range(32)])
|
||||
privatekey = BasicSchemeMPL.key_gen(seed)
|
||||
json_dump[NODES_JSON][node]["private_key"] = list(bytes(privatekey))
|
||||
#publickey = privatekey.get_g1()
|
||||
#hashed_publickey = hashlib.blake2b(bytes(publickey), digest_size=32).digest()
|
||||
#json_dump[NODES_JSON][node]["public_key"] = list(hashed_publickey)
|
||||
#json_dump["all_public_keys"].append(list(hashed_publickey))
|
||||
json_dump[NODES_JSON][node]["public_key"] = list(bytes(privatekey))
|
||||
json_dump["all_public_keys"].append(list(bytes(privatekey)))
|
||||
|
||||
write_ymls(json_dump)
|
||||
|
||||
# TODO modificar yml para cada nodo con las claves.
|
||||
write_json(ctx.params["output_dir"], json_dump) # network wide json
|
||||
# shutil.copy2("/config/traits/nomos.yml", "/gennet/network_data/nomos.yml")
|
||||
|
||||
|
||||
def write_ymls(json_dump):
|
||||
with open("/config/traits/nomos.yml", "r") as stream:
|
||||
try:
|
||||
nomos_yml_template = yaml.safe_load(stream)
|
||||
except yaml.YAMLError as exc:
|
||||
print(exc)
|
||||
|
||||
for node_name, node_info in json_dump[NODES_JSON].items():
|
||||
nomos_yml_template['consensus']['private_key'] = node_info["private_key"]
|
||||
nomos_yml_template['consensus']['overlay_settings']['nodes'] = json_dump["all_public_keys"]
|
||||
with open(f'/gennet/network_data/{node_name}.yml', 'w') as f:
|
||||
yaml.dump(nomos_yml_template, f)
|
||||
|
||||
|
||||
# sanity check : valid json with "gennet" config
|
||||
def _config_file_callback(ctx: typer.Context, param: typer.CallbackParam, cfile: str):
|
||||
if cfile:
|
||||
@@ -498,7 +563,10 @@ def main(ctx: typer.Context,
|
||||
make_empty_dir(output_dir)
|
||||
|
||||
# Generate file format specific data structs and write the files
|
||||
generate_and_write_files(ctx, G)
|
||||
if node_type_distribution["nomos"] > 0:
|
||||
generate_and_write_files_nomos(ctx, G)
|
||||
else:
|
||||
generate_and_write_files(ctx, G)
|
||||
|
||||
# Draw the graph if need be
|
||||
if draw:
|
||||
@@ -517,3 +585,5 @@ def main(ctx: typer.Context,
|
||||
|
||||
if __name__ == "__main__":
|
||||
typer.run(main)
|
||||
|
||||
|
||||
|
||||
@@ -9,3 +9,5 @@ pyparsing==3.0.9
|
||||
python-dateutil==2.8.2
|
||||
six==1.16.0
|
||||
typer==0.7.0
|
||||
blspy~=1.0.16
|
||||
pyyaml
|
||||
16
main.star
16
main.star
@@ -7,6 +7,7 @@ grafana = import_module(vars.GRAFANA_MODULE)
|
||||
args_parser = import_module(vars.ARGUMENT_PARSER_MODULE)
|
||||
wls = import_module(vars.WLS_MODULE)
|
||||
nodes = import_module(vars.NODE_BUILDERS_MODULE)
|
||||
assertions = import_module(vars.ASSERTIONS_MODULE)
|
||||
|
||||
|
||||
def run(plan, args):
|
||||
@@ -24,16 +25,21 @@ def run(plan, args):
|
||||
network_topology = json.decode(network_topology)
|
||||
|
||||
# Set up nodes
|
||||
nodes.instantiate_services(plan, network_topology, True, False)
|
||||
nodes.instantiate_services(plan, network_topology, not kurtosis_config["interconnect_nodes"], False)
|
||||
|
||||
# Set up prometheus + grafana
|
||||
prometheus_service = prometheus.set_up_prometheus(plan, network_topology)
|
||||
|
||||
grafana_service = grafana.set_up_grafana(plan, prometheus_service)
|
||||
if kurtosis_config["monitoring"]:
|
||||
prometheus_service = prometheus.set_up_prometheus(plan, network_topology)
|
||||
grafana_service = grafana.set_up_grafana(plan, prometheus_service)
|
||||
|
||||
# Interconnect nodes if needed
|
||||
if kurtosis_config[vars.INTERCONNECT_NODES]:
|
||||
nodes.interconnect_nodes(plan, network_topology, interconnection_batch)
|
||||
|
||||
# Setup WLS & Start the Simulation
|
||||
wls_service = wls.init(plan, network_topology, config_file, prometheus_service)
|
||||
if kurtosis_config["injection"]:
|
||||
wls_service = wls.init(plan, network_topology, config_file, prometheus_service)
|
||||
|
||||
# Tests
|
||||
if kurtosis_config["testing"]:
|
||||
assertions.start_test(plan, kurtosis_config, network_topology)
|
||||
|
||||
28
src/assertions.star
Normal file
28
src/assertions.star
Normal file
@@ -0,0 +1,28 @@
|
||||
# System Imports
|
||||
vars = import_module("github.com/logos-co/wakurtosis/src/system_variables.star")
|
||||
|
||||
# Module Imports
|
||||
call_protocols = import_module(vars.CALL_PROTOCOLS)
|
||||
|
||||
|
||||
def start_test(plan, kurtosis_config, network_topology):
|
||||
for name, values in kurtosis_config["assertions"].items():
|
||||
exec_recipe = ExecRecipe(
|
||||
command=["sleep", str(values["waiting"])]
|
||||
)
|
||||
|
||||
plan.exec(
|
||||
service_name=network_topology["nodes"].values()[0]["container_id"],
|
||||
recipe=exec_recipe)
|
||||
|
||||
for service_name, service_info in network_topology["nodes"].items():
|
||||
extract = {"jq_extract": values["jq_extract"]}
|
||||
|
||||
response = call_protocols.send_http_get_req(plan, service_info["container_id"],
|
||||
vars.WAKU_RPC_PORT_ID + vars.ID_STR_SEPARATOR + service_name,
|
||||
values["endpoint"], extract)
|
||||
|
||||
plan.assert(value=response["code"], assertion="==", target_value = 200)
|
||||
plan.assert(value=response["extract.jq_extract"], assertion=">",
|
||||
target_value=values["expected_value"])
|
||||
plan.remove_service(service_info["container_id"])
|
||||
@@ -54,6 +54,8 @@ def instantiate_services(plan, network_topology, discovery, testing):
|
||||
|
||||
_add_service_info_to_topology(plan, all_services_information, network_topology, discovery)
|
||||
|
||||
return all_services_information
|
||||
|
||||
|
||||
def interconnect_nodes(plan, topology_information, interconnection_batch):
|
||||
# Interconnect them
|
||||
|
||||
@@ -2,10 +2,11 @@
|
||||
vars = import_module("github.com/logos-co/wakurtosis/src/system_variables.star")
|
||||
|
||||
|
||||
def prepare_nomos_service(node_name, all_services, config_files, artifact_ids, service_id):
|
||||
prepared_ports = _prepare_nomos_ports_in_service(node_name)
|
||||
prepared_files = _prepare_nomos_config_files_in_service(node_name, artifact_ids)
|
||||
prepared_cmd = _prepare_nomos_cmd_in_service(node_name, config_files)
|
||||
def prepare_nomos_service(node_names, all_services, config_files, artifact_ids, run_artifact_id,
|
||||
service_id, network_topology, discovery):
|
||||
prepared_ports = _prepare_nomos_ports_in_service(node_names)
|
||||
prepared_files = _prepare_nomos_config_files_in_service(node_names, artifact_ids)
|
||||
prepared_cmd = _prepare_nomos_cmd_in_service(node_names, config_files)
|
||||
|
||||
add_service_config = ServiceConfig(
|
||||
image=vars.NOMOS_IMAGE,
|
||||
@@ -22,7 +23,8 @@ def _prepare_nomos_cmd_in_service(nomos_names, config_files):
|
||||
prepared_cmd = ""
|
||||
for i in range(len(nomos_names)):
|
||||
prepared_cmd += vars.NOMOS_ENTRYPOINT + " "
|
||||
prepared_cmd += vars.NOMOS_CONTAINER_CONFIG_FILE_LOCATION + " "
|
||||
# prepared_cmd += vars.NOMOS_CONTAINER_CONFIG_FILE_LOCATION + " "
|
||||
prepared_cmd += vars.CONTAINER_NODE_CONFIG_FILE_LOCATION + nomos_names[i] + "/" + config_files[i] + " "
|
||||
# prepared_cmd += vars.NOMOS_PORT_SHIFT_FLAG + str(i)
|
||||
if i != len(nomos_names) - 1:
|
||||
prepared_cmd += " & "
|
||||
@@ -37,9 +39,9 @@ def _prepare_nomos_ports_in_service(node_names):
|
||||
PortSpec(number=vars.NOMOS_RPC_PORT_NUMBER + i,
|
||||
transport_protocol=vars.NOMOS_RPC_PORT_PROTOCOL)
|
||||
|
||||
prepared_ports[vars.PROMETHEUS_PORT_ID + vars.ID_STR_SEPARATOR + node_names[i]] = \
|
||||
PortSpec(number=vars.PROMETHEUS_PORT_NUMBER + i,
|
||||
transport_protocol=vars.PROMETHEUS_PORT_PROTOCOL)
|
||||
#prepared_ports[vars.PROMETHEUS_PORT_ID + vars.ID_STR_SEPARATOR + node_names[i]] = \
|
||||
# PortSpec(number=vars.NOMOS_PROMETHEUS_PORT_NUMBER + i,
|
||||
# transport_protocol=vars.PROMETHEUS_PORT_PROTOCOL)
|
||||
|
||||
prepared_ports[vars.NOMOS_LIBP2P_PORT_ID + vars.ID_STR_SEPARATOR + node_names[i]] = \
|
||||
PortSpec(number=vars.NOMOS_LIBP2P_PORT + i,
|
||||
@@ -57,7 +59,8 @@ def _prepare_nomos_config_files_in_service(node_names, artifact_ids):
|
||||
return prepared_files
|
||||
|
||||
|
||||
def add_nomos_ports_info_to_topology(network_topology, all_services_information, node_info, node_id):
|
||||
def add_nomos_ports_info_to_topology(network_topology, all_services_information, node_info, node_id,
|
||||
discovery):
|
||||
nomos_rpc_port_id = vars.WAKU_RPC_PORT_ID + vars.ID_STR_SEPARATOR + node_id
|
||||
libp2p_port_id = vars.NOMOS_LIBP2P_PORT_ID + vars.ID_STR_SEPARATOR + node_id
|
||||
prometheus_port_id = vars.PROMETHEUS_PORT_ID + vars.ID_STR_SEPARATOR + node_id
|
||||
@@ -65,7 +68,7 @@ def add_nomos_ports_info_to_topology(network_topology, all_services_information,
|
||||
network_topology[vars.GENNET_NODES_KEY][node_id][vars.PORTS_KEY] = {}
|
||||
_add_nomos_port(network_topology, all_services_information, node_id, node_info, nomos_rpc_port_id)
|
||||
_add_nomos_port(network_topology, all_services_information, node_id, node_info, libp2p_port_id)
|
||||
_add_nomos_port(network_topology, all_services_information, node_id, node_info, prometheus_port_id)
|
||||
#_add_nomos_port(network_topology, all_services_information, node_id, node_info, prometheus_port_id)
|
||||
|
||||
|
||||
def _add_nomos_port(network_topology, all_services_information, node_id, node_info, port_id):
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Waku Configuration
|
||||
# IMAGES
|
||||
NWAKU_IMAGE = "statusteam/nim-waku:nwaku-trace3"
|
||||
GOWAKU_IMAGE = "gowaku"
|
||||
NOMOS_IMAGE = "nomos-node"
|
||||
|
||||
# If changing this, you'll likely need to change it as well in gennet
|
||||
ID_STR_SEPARATOR = "-"
|
||||
@@ -37,10 +38,9 @@ NWAKU_SCRIPT_ENTRYPOINT = "run_waku_node.sh"
|
||||
GOWAKU_ENTRYPOINT = "/usr/bin/waku --rpc-address=0.0.0.0 --metrics-server-address=0.0.0.0"
|
||||
NOMOS_ENTRYPOINT = "/usr/bin/nomos-node"
|
||||
NOMOS_PORT_SHIFT_FLAG = "--ports-shift="
|
||||
NOMOS_CONTAINER_CONFIG_FILE_LOCATION = '/etc/nomos/config.yml'
|
||||
NOMOS_CONTAINER_CONFIG_FILE_LOCATION = '/etc/nomos/config.yaml'
|
||||
|
||||
# Nomos Configuration
|
||||
NOMOS_IMAGE = "nomos"
|
||||
NOMOS_RPC_PORT_PROTOCOL = "TCP"
|
||||
NOMOS_RPC_PORT_NUMBER = 8080
|
||||
NOMOS_LIBP2P_PORT_PROTOCOL = "TCP"
|
||||
@@ -48,6 +48,8 @@ NOMOS_LIBP2P_PORT_ID = "libp2p"
|
||||
NOMOS_LIBP2P_PORT = 3000
|
||||
NOMOS_NET_INFO_URL = "/network/info"
|
||||
NOMOS_NET_CONN_URL = "/network/conn"
|
||||
NOMOS_CARNOT_INFO = "/carnot/info"
|
||||
NOMOS_PROMETHEUS_PORT_NUMBER = 8080
|
||||
|
||||
# Prometheus Configuration
|
||||
PROMETHEUS_IMAGE = "prom/prometheus:latest"
|
||||
@@ -141,6 +143,7 @@ TEMPLATES_MODULE = "github.com/logos-co/wakurtosis/src/templates.star"
|
||||
WLS_MODULE = "github.com/logos-co/wakurtosis/src/wls.star"
|
||||
CALL_PROTOCOLS = "github.com/logos-co/wakurtosis/src/call_protocols.star"
|
||||
NOMOS_MODULE = "github.com/logos-co/wakurtosis/src/nomos.star"
|
||||
ASSERTIONS_MODULE = "github.com/logos-co/wakurtosis/src/assertions.star"
|
||||
|
||||
|
||||
TEST_ARGUMENTS_MODULE = "github.com/logos-co/wakurtosis/src/tests/test_arguments_parser.star"
|
||||
|
||||
Reference in New Issue
Block a user