diff --git a/.gitignore b/.gitignore index 40ebfe8..cee3c32 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ apps/walletshield/walletshield +docker/node/.env genconfig/cmd/genconfig/genconfig pki/pki server_plugins/cbor_plugins/http_proxy/cmd/http_proxy/http_proxy diff --git a/docker/Makefile.appchain b/docker/Makefile.appchain index b2e32e8..f22313b 100644 --- a/docker/Makefile.appchain +++ b/docker/Makefile.appchain @@ -1,4 +1,7 @@ net ?= /tmp/appchain-mixnet +url_appchain_indexer ?= http://localhost:8081/graphql +url_appchain_processor ?= http://localhost:8082/graphql +url_appchain_sequencer ?= http://localhost:8080/graphql dir_base := /mixnet dir_bin := /opt/zkn docker_image ?= zkn/node:latest @@ -18,6 +21,20 @@ probe_count ?= 1 export +.PHONY: help +help: + @echo + @echo "These make targets allow you to control the test network:" + @echo " image - build node docker image" + @echo " config - generate config for test network nodes" + @echo " init - register and activate a network with local appchain" + @echo " start - start the testnet" + @echo " _start - start the testnet without re-build/config" + @echo " stop - stop the testnet" + @echo " wait - wait for testnet to have consensus" + @echo " probe - send a probe over the testnet" + @echo " clean - stop, remove docker image and config" + $(net): mkdir -vp $(net) @@ -49,8 +66,22 @@ probe: $(net)/run.stamp -config $(dir_base)/client2/client.toml \ -log_level DEBUG \ -probe \ + -probe_send_delay 1 \ -probe_count $(probe_count) +.PHONY: init +init: $(net) + $(docker_run) \ + --env URL_APPCHAIN_INDEXER=$(url_appchain_indexer) \ + --env URL_APPCHAIN_PROCESSOR=$(url_appchain_processor) \ + --env URL_APPCHAIN_SEQUENCER=$(url_appchain_sequencer) \ + --volume $(shell readlink -f ./network.yml):/tmp/network.yml \ + $(docker_image_agent) \ + bin/network-init.sh \ + dev-$(shell date +%H%M%S) \ + /tmp/network.yml \ + $(dir_base) + .PHONY: stop stop: [ -e $(net) ] && cd $(net) && $(docker_compose) down --remove-orphans @@ -58,5 +89,9 @@ stop: .PHONY: clean clean: stop - $(docker) rmi $(docker_image) rm -rfv $(net) + +.PHONY: clean-image +clean-image: + $(docker) rmi $(docker_image) + rm -fv $(net)/image.stamp diff --git a/docker/README.md b/docker/README.md index 9a3f9be..7675bdc 100644 --- a/docker/README.md +++ b/docker/README.md @@ -38,30 +38,36 @@ To run the Appchain PKI network, ensure the following components are available: ### Example Workflow ```bash -# build the appchain-agent docker image -cd appchain-agent && make image +# with appchain-agent docker image built, and local appchain running -# start local appchain instance, then: +# a lil helper to decrease verbosity +alias makea='net=/tmp/mix make -f Makefile.appchain' + +# register and activate a network with the local appchain +makea init # build the docker image, configure, start the network, wait for the epoch, then probe -net=/tmp/appchain-mixnet make -f Makefile.appchain start wait probe +makea start wait probe # stop the network and clean up -net=/tmp/appchain-mixnet make -f Makefile.appchain clean +makea clean # build the docker image and configure (without starting network) # to inspect or manually edit the configuration files before continuing -net=/tmp/appchain-mixnet make -f Makefile.appchain config +makea config # start the network without rebuilding or reconfiguring, wait for the epoch -net=/tmp/appchain-mixnet make -f Makefile.appchain _start wait +makea _start wait # test the network with a client sending 10 test probes -net=/tmp/appchain-mixnet probe_count=10 make -f Makefile.appchain probe +makea probe_count=10 probe # watch log files tail -f /tmp/appchain-mixnet/*/*.log # stop the network (without cleaning up) -net=/tmp/appchain-mixnet make -f Makefile.appchain stop +makea stop + +# clean up (remove config files) +makea clean ``` diff --git a/docker/genconfig.sh b/docker/genconfig.sh index ee819a4..6dbad65 100755 --- a/docker/genconfig.sh +++ b/docker/genconfig.sh @@ -16,6 +16,9 @@ echo " docker_image_agent: ${docker_image_agent}" echo " num_gateways: ${num_gateways}" echo " num_servicenodes: ${num_servicenodes}" echo " num_mixes: ${num_mixes}" +echo " url_appchain_indexer: ${url_appchain_indexer}" +echo " url_appchain_processor: ${url_appchain_processor}" +echo " url_appchain_sequencer: ${url_appchain_sequencer}" gencfg="${docker} run ${docker_args} --rm \ --volume $(readlink -f ./network.yml):/tmp/network.yml \ @@ -66,6 +69,7 @@ function gencfg_node () { ${gencfg} \ -type ${type} \ -identifier ${id} \ + -log-level DEBUG \ -metrics ${metrics} \ -port ${port} \ || exit 1 @@ -79,10 +83,14 @@ function gencfg_node () { ${id}-agent: <<: *common-service image: ${docker_image_agent} + environment: + - URL_APPCHAIN_INDEXER=${url_appchain_indexer} + - URL_APPCHAIN_PROCESSOR=${url_appchain_processor} + - URL_APPCHAIN_SEQUENCER=${url_appchain_sequencer} command: > pnpm run agent \ --ipfs \ - --ipfs-data ${dir_base}/ipfs-data \ + --ipfs-data ${dir_base}/ipfs \ --listen \ --key ${dir_base}/${id}-auth/appchain.key \ --socket ${dir_base}/${id}-auth/appchain.sock \ diff --git a/docker/node/Dockerfile b/docker/node/Dockerfile index ca24024..6f4af19 100644 --- a/docker/node/Dockerfile +++ b/docker/node/Dockerfile @@ -8,6 +8,7 @@ RUN \ ca-certificates \ && rm -rf /var/lib/apt/lists/* + FROM base AS builder ARG ENABLE_WARPED_EPOCH=false diff --git a/docker/node/docker-compose.yml b/docker/node/docker-compose.yml new file mode 100644 index 0000000..6d77397 --- /dev/null +++ b/docker/node/docker-compose.yml @@ -0,0 +1,37 @@ +x-common-service: &common-service + restart: "no" + image: ${IMAGE_NODE} + user: ${DOCKER_USER} + volumes: + - ${VOLUME_MIXNET}:${DIR_BASE} + network_mode: host + +services: + mix-agent: + <<: *common-service + image: ${IMAGE_AGENT} + environment: + - URL_APPCHAIN_INDEXER=${URL_APPCHAIN_INDEXER} + - URL_APPCHAIN_PROCESSOR=${URL_APPCHAIN_PROCESSOR} + - URL_APPCHAIN_SEQUENCER=${URL_APPCHAIN_SEQUENCER} + command: > + pnpm run agent + --ipfs + --ipfs-data ${DIR_BASE}/ipfs + --listen + --key ${DIR_BASE}/${NODE_ID}-auth/appchain.key + --socket ${DIR_BASE}/${NODE_ID}-auth/appchain.sock + --socket-format cbor + --debug + + mix-auth: + <<: *common-service + command: ${DIR_BIN}/pki -f ${DIR_BASE}/${NODE_ID}-auth/authority.toml + depends_on: + - mix-agent + + mix: + <<: *common-service + command: ${DIR_BIN}/server -f ${DIR_BASE}/${NODE_ID}/katzenpost.toml + depends_on: + - mix-auth diff --git a/docker/node/env.example b/docker/node/env.example new file mode 100644 index 0000000..fbe427e --- /dev/null +++ b/docker/node/env.example @@ -0,0 +1,16 @@ +NODE_ADDRESS=127.0.0.1 +NODE_ID=mix-1000 +NODE_LOG_LEVEL=INFO +NODE_METRICS=0.0.0.0:9100 +NODE_PORT=8888 +NODE_TYPE=mix +VOLUME_MIXNET=/tmp/mix + +DIR_BASE=/mixnet +DIR_BIN=/opt/zkn +IMAGE_AGENT=ghcr.io/0knowledgenetwork/appchain-agent:latest +IMAGE_NODE=ghcr.io/0knowledgenetwork/node:latest +URL_APPCHAIN_INDEXER=http://localhost:8081/graphql +URL_APPCHAIN_SEQUENCER=http://localhost:8080/graphql +URL_APPCHAIN_PROCESSOR=http://localhost:8082/graphql +USE_LOCAL_IMAGES=0 diff --git a/docker/node/node-start.sh b/docker/node/node-start.sh new file mode 100755 index 0000000..288ebf3 --- /dev/null +++ b/docker/node/node-start.sh @@ -0,0 +1,93 @@ +#!/bin/bash + +set -euo pipefail + +dir_script=$(dirname "$(readlink -f "$0")") +network_id=${1:-_} # default to active network +file_env="${2:-${dir_script}/.env}" # default to .env in this script's directory + +# Load configuration from the .env file in the same directory as the script +[ ! -f "${file_env}" ] && echo "Error: .env file not found: ${file_env}" && exit 1 +echo "Loading environment variables from ${file_env}" +export $(grep -v '^#' "${file_env}" | xargs) + +# Verify that required environment variables are set +for var in \ + DIR_BASE \ + DIR_BIN \ + IMAGE_AGENT \ + IMAGE_NODE \ + NODE_ADDRESS \ + NODE_ID \ + NODE_LOG_LEVEL \ + NODE_METRICS \ + NODE_PORT \ + NODE_TYPE \ + URL_APPCHAIN_INDEXER \ + URL_APPCHAIN_PROCESSOR \ + URL_APPCHAIN_SEQUENCER \ + USE_LOCAL_IMAGES \ + VOLUME_MIXNET \ +; do + : "${!var:?Environment variable ${var} is required}" +done + +# Configuration +file_network="${VOLUME_MIXNET}/network.yml" + +# Determine container tool and related settings +if command -v podman >/dev/null; then + docker="podman" + docker_user=$(if podman info --format '{{.Host.Security.Rootless}}' | grep -iq "true"; then echo "$(id -u):$(id -g)"; else echo "0:0"; fi) + docker_compose_env="DOCKER_USER=${docker_user} DOCKER_HOST=unix://${XDG_RUNTIME_DIR:-/run/user/$(id -u)}/podman/podman.sock" +else + docker="docker" + docker_user="${SUDO_UID:-$(id -u)}:${SUDO_GID:-$(id -g)}" + docker_compose_env="DOCKER_USER=${docker_user}" +fi +docker_compose="${docker_compose_env} docker compose --env-file ${file_env}" +docker_run="${docker} run \ + --env URL_APPCHAIN_INDEXER=${URL_APPCHAIN_INDEXER} \ + --env URL_APPCHAIN_PROCESSOR=${URL_APPCHAIN_PROCESSOR} \ + --env URL_APPCHAIN_SEQUENCER=${URL_APPCHAIN_SEQUENCER} \ + --network=host \ + --rm \ + --user ${docker_user} \ + --volume ${VOLUME_MIXNET}:${DIR_BASE}" + +# Pull required Docker images +[ ${USE_LOCAL_IMAGES} -eq "0" ] && echo -e "\nPulling required Docker images..." && eval ${docker_compose} pull + +# Fetch network info +echo -e "\nFetching active network configuration..." +eval ${docker_run} \ + ${IMAGE_AGENT} \ + pnpm run agent \ + --ipfs \ + --ipfs-data ${DIR_BASE}/ipfs \ + networks getNetwork ${network_id} ${DIR_BASE}/network.yml +[ ! -f "${file_network}" ] && echo "Error: Network configuration file not generated." && exit 1 +echo "Network configuration saved to ${file_network}" + +# Generate node configuration +echo -e "\nGenerating node configuration..." +eval ${docker_run} \ + ${IMAGE_NODE} \ + ${DIR_BIN}/genconfig \ + -input ${DIR_BASE}/network.yml \ + -binary-prefix ${DIR_BIN}/ \ + -dir-base ${DIR_BASE} \ + -dir-out ${DIR_BASE} \ + -address ${NODE_ADDRESS} \ + -identifier ${NODE_ID} \ + -log-level ${NODE_LOG_LEVEL} \ + -metrics ${NODE_METRICS} \ + -port ${NODE_PORT} \ + -type ${NODE_TYPE} +echo "Node configuration generated successfully." + +# Start services +echo -e "\nStarting services..." +eval ${docker_compose} -p ${NODE_ID} up -d + +echo -e "\nNode setup and services started successfully." diff --git a/genconfig/genconfig.go b/genconfig/genconfig.go index 38e5efc..680e4fc 100644 --- a/genconfig/genconfig.go +++ b/genconfig/genconfig.go @@ -508,7 +508,7 @@ func ParseFlags() GenconfigInput { flag.StringVar(&gi.cfgType, "type", "", "Type of config to generate: mix, gateway, servicenode, client1, client2") flag.StringVar(&gi.identifier, "identifier", "", "Node identifier; lowercase alphanumeric with 4 to 20 characters (default -type)") flag.StringVar(&gi.inputNetworkInfo, "input", "network.yml", "Path to network info file") - flag.StringVar(&gi.logLevel, "log-level", "DEBUG", "logging level could be set to: DEBUG, INFO, NOTICE, WARNING, ERROR, CRITICAL") + flag.StringVar(&gi.logLevel, "log-level", "INFO", "logging level could be set to: DEBUG, INFO, NOTICE, WARNING, ERROR, CRITICAL") flag.StringVar(&gi.metrics, "metrics", metrics, "Metrics endpoint") flag.StringVar(&gi.outDir, "dir-out", "", "Path to write files to") flag.StringVar(&gi.transport, "transport", transport, "Transport protocol: tcp, quic") diff --git a/go.mod b/go.mod index ac2a35e..bba048e 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/0KnowledgeNetwork/opt go 1.22.3 require ( - github.com/0KnowledgeNetwork/appchain-agent/clients/go v0.0.0-20241018051950-6cb4d4598933 + github.com/0KnowledgeNetwork/appchain-agent/clients/go v0.0.0-20250108045135-72cb54760c56 github.com/BurntSushi/toml v1.4.0 github.com/carlmjohnson/versioninfo v0.22.5 github.com/charmbracelet/log v0.4.0 diff --git a/go.sum b/go.sum index 0d9b6d6..246e8e7 100644 --- a/go.sum +++ b/go.sum @@ -4,8 +4,8 @@ filippo.io/edwards25519 v1.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek= filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= filippo.io/mlkem768 v0.0.0-20240221181710-5ce91625fdc1 h1:xbdqh5aDZeO0XqW896qVjKnAqRji9nkIwmsBEEbCA10= filippo.io/mlkem768 v0.0.0-20240221181710-5ce91625fdc1/go.mod h1:mIEHrcJ2xBlJRQwnRO0ujmZ+Rt6m6eNeCPq8E3Wkths= -github.com/0KnowledgeNetwork/appchain-agent/clients/go v0.0.0-20241018051950-6cb4d4598933 h1:iYk0ECvvvKPGzNg3zAr75wM91H7fh9O9+jDl+TlwBu4= -github.com/0KnowledgeNetwork/appchain-agent/clients/go v0.0.0-20241018051950-6cb4d4598933/go.mod h1:sMFBunupwopr9TDPw5bxUrs1mSYDn2QPF/vFI7gvWwU= +github.com/0KnowledgeNetwork/appchain-agent/clients/go v0.0.0-20250108045135-72cb54760c56 h1:CX9n4//lUS6bhHfUJEKPKmY/KFitHfmIn6YYFc3y8Tk= +github.com/0KnowledgeNetwork/appchain-agent/clients/go v0.0.0-20250108045135-72cb54760c56/go.mod h1:sMFBunupwopr9TDPw5bxUrs1mSYDn2QPF/vFI7gvWwU= github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=