diff --git a/stack-orchestrator/compose/docker-compose-go-nitro.yml b/stack-orchestrator/compose/docker-compose-go-nitro.yml new file mode 100644 index 0000000..6f79653 --- /dev/null +++ b/stack-orchestrator/compose/docker-compose-go-nitro.yml @@ -0,0 +1,42 @@ +name: go-nitro + +services: + go-nitro: + image: cerc/go-nitro:local + hostname: go-nitro + restart: on-failure + depends_on: + # Wait for Nitro contracts to be deployed + nitro-contracts: + condition: service_completed_successfully + environment: + CERC_NITRO_CHAIN_URL: ${CERC_NITRO_CHAIN_URL} + CERC_NITRO_PK: ${CERC_NITRO_PK} + CERC_NITRO_CHAIN_PK: ${CERC_NITRO_CHAIN_PK} + CERC_NITRO_USE_DURABLE_STORE: ${CERC_NITRO_USE_DURABLE_STORE} + CERC_NITRO_DURABLE_STORE_FOLDER: ${CERC_NITRO_DURABLE_STORE_FOLDER} + CERC_NITRO_MSG_PORT: ${CERC_NITRO_MSG_PORT} + CERC_NITRO_WS_MSG_PORT: ${CERC_NITRO_WS_MSG_PORT} + CERC_NITRO_RPC_PORT: ${CERC_NITRO_RPC_PORT} + CERC_NA_ADDRESS: ${CERC_NA_ADDRESS} + CERC_VPA_ADDRESS: ${CERC_VPA_ADDRESS} + CERC_CA_ADDRESS: ${CERC_CA_ADDRESS} + entrypoint: ["bash", "-c", "/app/run-nitro-node.sh"] + volumes: + - go_nitro_data:/app/data + - nitro_deployment:/app/deployment + - ../config/go-nitro/run-nitro-node.sh:/app/run-nitro-node.sh + healthcheck: + test: ["CMD", "nc", "-vz", "localhost", "4006"] + interval: 30s + timeout: 5s + retries: 10 + start_period: 10s + ports: + - "3006:3006" + - "4006:4006" + - "5006:5006" + +volumes: + go_nitro_data: + nitro_deployment: diff --git a/stack-orchestrator/compose/docker-compose-nitro-contracts.yml b/stack-orchestrator/compose/docker-compose-nitro-contracts.yml new file mode 100644 index 0000000..af1a66b --- /dev/null +++ b/stack-orchestrator/compose/docker-compose-nitro-contracts.yml @@ -0,0 +1,25 @@ +name: nitro-contracts + +services: + # Optionally deploys the Nitro contracts + # TODO: Rename to nitro-protocol + nitro-contracts: + image: cerc/nitro-contracts:local + restart: on-failure + environment: + CERC_SCRIPT_DEBUG: ${CERC_SCRIPT_DEBUG} + CERC_ETH_RPC_ENDPOINT: ${CERC_ETH_RPC_ENDPOINT} + CERC_PRIVATE_KEY_DEPLOYER: ${CERC_PRIVATE_KEY_DEPLOYER} + CERC_NA_ADDRESS: ${CERC_NA_ADDRESS} + CERC_VPA_ADDRESS: ${CERC_VPA_ADDRESS} + CERC_CA_ADDRESS: ${CERC_CA_ADDRESS} + # TODO: Add bridge contract address + volumes: + - ../config/nitro-contracts/deploy.sh:/app/deploy.sh + - nitro_deployment:/app/deployment + command: ["bash", "-c", "/app/deploy.sh"] + extra_hosts: + - "host.docker.internal:host-gateway" + +volumes: + nitro_deployment: diff --git a/stack-orchestrator/compose/docker-compose-nitro-rpc-client.yml b/stack-orchestrator/compose/docker-compose-nitro-rpc-client.yml new file mode 100644 index 0000000..f05895e --- /dev/null +++ b/stack-orchestrator/compose/docker-compose-nitro-rpc-client.yml @@ -0,0 +1,8 @@ +name: nitro-rpc-client + +services: + nitro-rpc-client: + image: cerc/nitro-rpc-client:local + hostname: nitro-rpc-client + restart: on-failure + command: ["bash", "-c", "tail -f /dev/null"] diff --git a/stack-orchestrator/config/go-nitro/run-nitro-node.sh b/stack-orchestrator/config/go-nitro/run-nitro-node.sh new file mode 100644 index 0000000..e43e139 --- /dev/null +++ b/stack-orchestrator/config/go-nitro/run-nitro-node.sh @@ -0,0 +1,52 @@ +#!/bin/bash + +# TODO: Support running node on L2 +if [ -n "$CERC_SCRIPT_DEBUG" ]; then + set -x +fi + +nitro_addresses_file="/app/deployment/nitro-addresses.json" + +# Check if CERC_NA_ADDRESS environment variable is set +if [ -n "$CERC_NA_ADDRESS" ]; then + echo "CERC_NA_ADDRESS is set to '$CERC_NA_ADDRESS'" + echo "CERC_VPA_ADDRESS is set to '$CERC_VPA_ADDRESS'" + echo "CERC_CA_ADDRESS is set to '$CERC_CA_ADDRESS'" + echo "Using the above Nitro addresses" + + NA_ADDRESS=${CERC_NA_ADDRESS} + VPA_ADDRESS=${CERC_VPA_ADDRESS} + CA_ADDRESS=${CERC_CA_ADDRESS} +elif [ -f ${nitro_addresses_file} ]; then + echo "Reading Nitro addresses from ${nitro_addresses_file}" + +# TODO: Use Bridge address instead of NA address while running node on L2 + NA_ADDRESS=$(jq -r '.nitroAdjudicatorAddress' ${nitro_addresses_file}) + VPA_ADDRESS=$(jq -r '.virtualPaymentAppAddress' ${nitro_addresses_file}) + CA_ADDRESS=$(jq -r '.consensusAppAddress' ${nitro_addresses_file}) +else + echo "File ${nitro_addresses_file} not found" + exit 1 +fi + +echo "Running Nitro node" + +# Assuming CERC_NITRO_CHAIN_URL is of format ://host:port +ws_host=$(echo "$CERC_NITRO_CHAIN_URL" | awk -F '://' '{print $2}' | cut -d ':' -f 1) +ws_port=$(echo "$CERC_NITRO_CHAIN_URL" | awk -F '://' '{print $2}' | cut -d ':' -f 2) + +# Wait till chain endpoint is available +retry_interval=5 +while true; do + nc -z -w 1 "$ws_host" "$ws_port" + + if [ $? -eq 0 ]; then + echo "Chain endpoint is available" + break + fi + + echo "Chain endpoint not yet available, retrying in $retry_interval seconds..." + sleep $retry_interval +done + +./nitro -chainurl ${CERC_NITRO_CHAIN_URL} -msgport ${CERC_NITRO_MSG_PORT} -rpcport ${CERC_NITRO_RPC_PORT} -wsmsgport ${CERC_NITRO_WS_MSG_PORT} -publicip "0.0.0.0" -pk ${CERC_NITRO_PK} -chainpk ${CERC_NITRO_CHAIN_PK} -naaddress ${NA_ADDRESS} -vpaaddress ${VPA_ADDRESS} -caaddress ${CA_ADDRESS} -usedurablestore ${CERC_NITRO_USE_DURABLE_STORE} -durablestorefolder ${CERC_NITRO_DURABLE_STORE_FOLDER} -tlscertfilepath "" -tlsKeyFilepath "" diff --git a/stack-orchestrator/config/nitro-contracts/deploy.sh b/stack-orchestrator/config/nitro-contracts/deploy.sh new file mode 100644 index 0000000..7c6e0c1 --- /dev/null +++ b/stack-orchestrator/config/nitro-contracts/deploy.sh @@ -0,0 +1,59 @@ +#!/bin/bash + +# TODO: Make sure contracts are not deployed on L2 +set -e +if [ -n "$CERC_SCRIPT_DEBUG" ]; then + set -x +fi + +nitro_addresses_file="/app/deployment/nitro-addresses.json" + +# Check if CERC_NA_ADDRESS environment variable set to skip contract deployment +if [ -n "$CERC_NA_ADDRESS" ]; then + echo "CERC_NA_ADDRESS is set to '$CERC_NA_ADDRESS'" + echo "CERC_VPA_ADDRESS is set to '$CERC_VPA_ADDRESS'" + echo "CERC_CA_ADDRESS is set to '$CERC_CA_ADDRESS'" + echo "Skipping Nitro contracts deployment" + exit +fi + +# Check and exit if a deployment already exists (on restarts) +if [ -f ${nitro_addresses_file} ]; then + echo "${nitro_addresses_file} already exists, skipping Nitro contracts deployment" + cat ${nitro_addresses_file} + exit +fi + +echo "Using ETH RPC endpoint ${CERC_ETH_RPC_ENDPOINT}" + +# Wait till ETH RPC endpoint is available with block number > 1 +retry_interval=5 +while true; do + block_number_hex=$(curl -s -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' ${CERC_ETH_RPC_ENDPOINT} | jq -r '.result') + + # Check if the request call was successful + if [ $? -ne 0 ]; then + echo "RPC endpoint not yet available, retrying in $retry_interval seconds..." + sleep $retry_interval + continue + fi + + # Convert hex to decimal + block_number_dec=$(printf %u ${block_number_hex}) + + # Check if block number is > 1 to avoid failures in the deployment + if [ "$block_number_dec" -ge 1 ]; then + echo "RPC endpoint is up" + break + else + echo "RPC endpoint not yet available, retrying in $retry_interval seconds..." + sleep $retry_interval + continue + fi +done + +echo "Using CERC_PRIVATE_KEY_DEPLOYER from env" + +# Use yarn contracts:deploy to deploy contracts +yarn test:deploy-contracts --chainUrl ${CERC_ETH_RPC_ENDPOINT} --key ${CERC_PRIVATE_KEY_DEPLOYER} --addressesFilePath ${nitro_addresses_file} +cat ${nitro_addresses_file} diff --git a/stack-orchestrator/container-build/cerc-go-nitro/Dockerfile b/stack-orchestrator/container-build/cerc-go-nitro/Dockerfile new file mode 100644 index 0000000..696c1fe --- /dev/null +++ b/stack-orchestrator/container-build/cerc-go-nitro/Dockerfile @@ -0,0 +1,17 @@ +FROM golang:1.21-bullseye AS builder + +# Copy files into image +WORKDIR /app +COPY . . + +# Build the binary +RUN go build -v -o nitro . + +# TODO: Update steps to build go-nitro image +# Reduce image size +FROM debian:bullseye-slim +RUN apt-get update +RUN apt-get install -y ca-certificates jq netcat +RUN rm -rf /var/lib/apt/lists/* +WORKDIR /app +COPY --from=builder /app/nitro . diff --git a/stack-orchestrator/container-build/cerc-go-nitro/build.sh b/stack-orchestrator/container-build/cerc-go-nitro/build.sh new file mode 100644 index 0000000..28bdde4 --- /dev/null +++ b/stack-orchestrator/container-build/cerc-go-nitro/build.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +# Build cerc/go-nitro + +source ${CERC_CONTAINER_BASE_DIR}/build-base.sh + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) + +docker build -t cerc/go-nitro:local -f ${SCRIPT_DIR}/Dockerfile ${build_command_args} ${CERC_REPO_BASE_DIR}/go-nitro diff --git a/stack-orchestrator/container-build/cerc-nitro-contracts/Dockerfile b/stack-orchestrator/container-build/cerc-nitro-contracts/Dockerfile new file mode 100644 index 0000000..ac183ca --- /dev/null +++ b/stack-orchestrator/container-build/cerc-nitro-contracts/Dockerfile @@ -0,0 +1,12 @@ +FROM node:18.17.1-alpine3.18 + +RUN apk --update --no-cache add python3 alpine-sdk bash curl jq + +WORKDIR /app + +COPY . . + +RUN echo "Installing dependencies" && \ + yarn && yarn build + +WORKDIR /app/packages/nitro-protocol diff --git a/stack-orchestrator/container-build/cerc-nitro-contracts/build.sh b/stack-orchestrator/container-build/cerc-nitro-contracts/build.sh new file mode 100755 index 0000000..e70c7d0 --- /dev/null +++ b/stack-orchestrator/container-build/cerc-nitro-contracts/build.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +# Build cerc/nitro-contracts + +source ${CERC_CONTAINER_BASE_DIR}/build-base.sh + +# See: https://stackoverflow.com/a/246128/1701505 +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) + +docker build -t cerc/nitro-contracts:local -f ${SCRIPT_DIR}/Dockerfile ${build_command_args} ${CERC_REPO_BASE_DIR}/go-nitro diff --git a/stack-orchestrator/container-build/cerc-nitro-rpc-client/Dockerfile b/stack-orchestrator/container-build/cerc-nitro-rpc-client/Dockerfile new file mode 100644 index 0000000..887673b --- /dev/null +++ b/stack-orchestrator/container-build/cerc-nitro-rpc-client/Dockerfile @@ -0,0 +1,13 @@ +FROM node:18.17.1-alpine3.18 + +RUN apk --update --no-cache add python3 alpine-sdk bash curl jq + +WORKDIR /app + +COPY . . + +RUN echo "Installing dependencies" && \ + yarn & yarn build + +WORKDIR /app/packages/nitro-rpc-client +ENV NODE_EXTRA_CA_CERTS="$(mkcert -CAROOT)/rootCA.pem" diff --git a/stack-orchestrator/container-build/cerc-nitro-rpc-client/build.sh b/stack-orchestrator/container-build/cerc-nitro-rpc-client/build.sh new file mode 100755 index 0000000..1a80583 --- /dev/null +++ b/stack-orchestrator/container-build/cerc-nitro-rpc-client/build.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +# Build cerc/nitro-rpc-client + +source ${CERC_CONTAINER_BASE_DIR}/build-base.sh + +# See: https://stackoverflow.com/a/246128/1701505 +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) + +docker build -t cerc/nitro-rpc-client:local -f ${SCRIPT_DIR}/Dockerfile ${build_command_args} ${CERC_REPO_BASE_DIR}/go-nitro diff --git a/stack-orchestrator/stack/go-nitro/README.md b/stack-orchestrator/stack/go-nitro/README.md new file mode 100644 index 0000000..ad40743 --- /dev/null +++ b/stack-orchestrator/stack/go-nitro/README.md @@ -0,0 +1,19 @@ +# Go-nitro + +## Clone the stack repo + + +## Clone required repositories + + +```bash +laconic-so --stack //nitro-stack/stack-orchestrator/stack/go-nitro setup-repositories +``` +Note: Replace path to nitro stack with actual path + +## Build the container image + + +```bash +laconic-so --stack //nitro-stack/stack-orchestrator/stack/go-nitro build-containers +``` \ No newline at end of file diff --git a/stack-orchestrator/stack/go-nitro/stack.yml b/stack-orchestrator/stack/go-nitro/stack.yml new file mode 100644 index 0000000..51649bd --- /dev/null +++ b/stack-orchestrator/stack/go-nitro/stack.yml @@ -0,0 +1,14 @@ +version: "1.0" +name: go-nitro +description: "Stack to demonstrate payments between various services" +repos: + - github.com/cerc-io/go-nitro +containers: + - cerc/nitro-contracts + - cerc/nitro-rpc-client + # TODO: Uncomment after building container image + # - cerc/go-nitro +pods: + - nitro-contracts + - go-nitro + - nitro-rpc-client