diff --git a/app/data/compose/docker-compose-mobymask-app-v3.yml b/app/data/compose/docker-compose-mobymask-app-v3.yml new file mode 100644 index 00000000..bc0973c8 --- /dev/null +++ b/app/data/compose/docker-compose-mobymask-app-v3.yml @@ -0,0 +1,38 @@ +version: '3.2' + +services: + # Builds and serves the MobyMask v3 react-app + mobymask-v3-app: + restart: unless-stopped + image: cerc/mobymask-ui:local + env_file: + - ../config/watcher-mobymask-v3/mobymask-params.env + environment: + CERC_SCRIPT_DEBUG: ${CERC_SCRIPT_DEBUG} + CERC_CHAIN_ID: ${CERC_CHAIN_ID} + CERC_DEPLOYED_CONTRACT: ${CERC_DEPLOYED_CONTRACT} + CERC_RELAY_NODES: ${CERC_RELAY_NODES} + CERC_DENY_MULTIADDRS: ${CERC_DENY_MULTIADDRS} + CERC_PUBSUB: ${CERC_PUBSUB} + CERC_RELEASE: "laconic-v3" + CERC_NA_ADDRESS: ${CERC_NA_ADDRESS} + CERC_VPA_ADDRESS: ${CERC_VPA_ADDRESS} + CERC_CA_ADDRESS: ${CERC_CA_ADDRESS} + CERC_APP_WATCHER_URL: ${CERC_APP_WATCHER_URL} + CERC_PAYMENT_NITRO_ADDRESS: ${CERC_PAYMENT_NITRO_ADDRESS} + CERC_SNAP_URL: ${CERC_SNAP_URL} + working_dir: /scripts + command: ["sh", "mobymask-app-start.sh"] + volumes: + - ../config/watcher-mobymask-v3/mobymask-app-start.sh:/scripts/mobymask-app-start.sh + - ../config/watcher-mobymask-v2/mobymask-app-config.json:/app/src/mobymask-app-config.json + ports: + - "127.0.0.1:3004:80" + healthcheck: + test: ["CMD", "nc", "-vz", "localhost", "80"] + interval: 20s + timeout: 5s + retries: 15 + start_period: 10s + extra_hosts: + - "host.docker.internal:host-gateway" diff --git a/app/data/compose/docker-compose-watcher-mobymask-v3.yml b/app/data/compose/docker-compose-watcher-mobymask-v3.yml new file mode 100644 index 00000000..8c351ae7 --- /dev/null +++ b/app/data/compose/docker-compose-watcher-mobymask-v3.yml @@ -0,0 +1,128 @@ +version: '3.2' + +services: + # Starts the PostgreSQL database for watcher + mobymask-watcher-db: + restart: unless-stopped + image: postgres:14-alpine + environment: + - POSTGRES_USER=vdbm + - POSTGRES_MULTIPLE_DATABASES=mobymask-watcher,mobymask-watcher-job-queue + - POSTGRES_EXTENSION=mobymask-watcher-job-queue:pgcrypto + - POSTGRES_PASSWORD=password + volumes: + - ../config/postgresql/multiple-postgressql-databases.sh:/docker-entrypoint-initdb.d/multiple-postgressql-databases.sh + - mobymask_watcher_db_data:/var/lib/postgresql/data + ports: + - "127.0.0.1:15432:5432" + healthcheck: + test: ["CMD", "nc", "-v", "localhost", "5432"] + interval: 20s + timeout: 5s + retries: 15 + start_period: 10s + + # Deploys the MobyMask contract and generates an invite link + # Deployment is skipped if CERC_DEPLOYED_CONTRACT env is set + mobymask: + image: cerc/mobymask:local + working_dir: /app/packages/server + env_file: + - ../config/watcher-mobymask-v3/mobymask-params.env + environment: + CERC_SCRIPT_DEBUG: ${CERC_SCRIPT_DEBUG} + ENV: "PROD" + CERC_L2_GETH_RPC: ${CERC_L2_GETH_RPC} + CERC_L1_ACCOUNTS_CSV_URL: ${CERC_L1_ACCOUNTS_CSV_URL} + CERC_PRIVATE_KEY_DEPLOYER: ${CERC_PRIVATE_KEY_DEPLOYER} + CERC_MOBYMASK_APP_BASE_URI: ${CERC_MOBYMASK_APP_BASE_URI} + CERC_DEPLOYED_CONTRACT: ${CERC_DEPLOYED_CONTRACT} + CERC_L2_GETH_HOST: ${CERC_L2_GETH_HOST} + CERC_L2_GETH_PORT: ${CERC_L2_GETH_PORT} + CERC_L2_NODE_HOST: ${CERC_L2_NODE_HOST} + CERC_L2_NODE_PORT: ${CERC_L2_NODE_PORT} + command: ["sh", "deploy-and-generate-invite.sh"] + volumes: + - ../config/network/wait-for-it.sh:/app/packages/server/wait-for-it.sh + - ../config/watcher-mobymask-v2/secrets-template.json:/app/packages/server/secrets-template.json + - ../config/watcher-mobymask-v2/deploy-and-generate-invite.sh:/app/packages/server/deploy-and-generate-invite.sh + - mobymask_deployment:/app/packages/server + extra_hosts: + - "host.docker.internal:host-gateway" + + # Creates peer-id files if they don't exist + peer-ids-gen: + image: cerc/watcher-ts:local + restart: on-failure + environment: + CERC_SCRIPT_DEBUG: ${CERC_SCRIPT_DEBUG} + working_dir: /app/packages/peer + command: ["sh", "generate-peer-ids.sh"] + volumes: + - ../config/watcher-mobymask-v2/generate-peer-ids.sh:/app/packages/peer/generate-peer-ids.sh + - peers_ids:/peer-ids + + # Optionally deploys the Nitro contracts; sets them at the required path + # Starts the MobyMask v3 watcher server + mobymask-watcher-server: + image: cerc/watcher-mobymask-v3:local + restart: unless-stopped + depends_on: + mobymask-watcher-db: + condition: service_healthy + peer-ids-gen: + condition: service_completed_successfully + mobymask: + condition: service_completed_successfully + env_file: + - ../config/watcher-mobymask-v3/mobymask-params.env + environment: + CERC_SCRIPT_DEBUG: ${CERC_SCRIPT_DEBUG} + CERC_L2_GETH_RPC: ${CERC_L2_GETH_RPC} + CERC_L1_ACCOUNTS_CSV_URL: ${CERC_L1_ACCOUNTS_CSV_URL} + CERC_PRIVATE_KEY_DEPLOYER: ${CERC_PRIVATE_KEY_DEPLOYER} + CERC_RELAY_PEERS: ${CERC_RELAY_PEERS} + CERC_DENY_MULTIADDRS: ${CERC_DENY_MULTIADDRS} + CERC_PUBSUB: ${CERC_PUBSUB} + CERC_RELAY_ANNOUNCE_DOMAIN: ${CERC_RELAY_ANNOUNCE_DOMAIN} + CERC_ENABLE_PEER_L2_TXS: ${CERC_ENABLE_PEER_L2_TXS} + CERC_DEPLOYED_CONTRACT: ${CERC_DEPLOYED_CONTRACT} + CERC_NA_ADDRESS: ${CERC_NA_ADDRESS} + CERC_VPA_ADDRESS: ${CERC_VPA_ADDRESS} + CERC_CA_ADDRESS: ${CERC_CA_ADDRESS} + CERC_PRIVATE_KEY_PEER: ${CERC_PRIVATE_KEY_PEER} + CERC_PRIVATE_KEY_NITRO: ${CERC_PRIVATE_KEY_NITRO} + CERC_PEER_ID: ${CERC_PEER_ID} + entrypoint: ["bash", "-c"] + command: ["./deploy-nitro-contracts.sh && ./start-server.sh"] + volumes: + - ../config/watcher-mobymask-v3/deploy-nitro-contracts.sh:/app/deploy-nitro-contracts.sh + - ../config/watcher-mobymask-v3/deploy-nitro-contracts.ts:/app/deploy-nitro-contracts.ts + - ../config/watcher-mobymask-v3/watcher-config-template.toml:/app/environments/watcher-config-template.toml + - ../config/watcher-mobymask-v3/watcher-config-rates.toml:/app/environments/rates.toml + - ../config/watcher-mobymask-v3/keys:/app/keys + - ../config/watcher-mobymask-v3/start-server.sh:/app/start-server.sh + - nitro_data:/app/out/nitro-db + - peers_ids:/app/peers + - nitro_addresses:/nitro + - mobymask_deployment:/server + # Expose GQL, metrics and relay node ports + ports: + - "127.0.0.1:3001:3001" + - "127.0.0.1:9001:9001" + - "127.0.0.1:9090:9090" + healthcheck: + test: ["CMD", "busybox", "nc", "localhost", "9090"] + interval: 20s + timeout: 5s + retries: 15 + start_period: 5s + extra_hosts: + - "host.docker.internal:host-gateway" + +volumes: + mobymask_watcher_db_data: + peers_ids: + mobymask_deployment: + nitro_addresses: + nitro_data: diff --git a/app/data/config/watcher-mobymask-v3/deploy-nitro-contracts.sh b/app/data/config/watcher-mobymask-v3/deploy-nitro-contracts.sh new file mode 100755 index 00000000..b12e9ce2 --- /dev/null +++ b/app/data/config/watcher-mobymask-v3/deploy-nitro-contracts.sh @@ -0,0 +1,58 @@ +#!/bin/bash + +set -e +if [ -n "$CERC_SCRIPT_DEBUG" ]; then + set -x +fi + +CERC_NA_ADDRESS="${CERC_NA_ADDRESS:-${DEFAULT_CERC_NA_ADDRESS}}" +CERC_VPA_ADDRESS="${CERC_VPA_ADDRESS:-${DEFAULT_CERC_VPA_ADDRESS}}" +CERC_CA_ADDRESS="${CERC_CA_ADDRESS:-${DEFAULT_CERC_CA_ADDRESS}}" + +NITRO_ADDRESSES_FILE_PATH="/nitro/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 "Using the above addresses and skipping Nitro contracts deployment" + + # Create the required JSON and write it to a file + nitro_addresses_json=$(jq -n \ + --arg na "$CERC_NA_ADDRESS" \ + --arg vpa "$CERC_VPA_ADDRESS" \ + --arg ca "$CERC_CA_ADDRESS" \ + '.nitroAdjudicatorAddress = $na | .virtualPaymentAppAddress = $vpa | .consensusAppAddress = $ca') + echo "$nitro_addresses_json" > "${NITRO_ADDRESSES_FILE_PATH}" + + exit +fi + +# Check and exit if a deployment already exists (on restarts) +if [ -f ${NITRO_ADDRESSES_FILE_PATH} ]; then + echo "${NITRO_ADDRESSES_FILE_PATH} already exists, skipping Nitro contracts deployment" + exit +fi + +echo "Using L2 RPC endpoint ${CERC_L2_GETH_RPC}" + +if [ -n "$CERC_L1_ACCOUNTS_CSV_URL" ] && \ + l1_accounts_response=$(curl -L --write-out '%{http_code}' --silent --output /dev/null "$CERC_L1_ACCOUNTS_CSV_URL") && \ + [ "$l1_accounts_response" -eq 200 ]; +then + echo "Fetching L1 account credentials using provided URL" + mkdir -p /geth-accounts + wget -O /geth-accounts/accounts.csv "$CERC_L1_ACCOUNTS_CSV_URL" + + # Read the private key of an L1 account to deploy contract + CERC_PRIVATE_KEY_DEPLOYER=$(head -n 1 /geth-accounts/accounts.csv | cut -d ',' -f 3) +else + echo "Couldn't fetch L1 account credentials, using CERC_PRIVATE_KEY_DEPLOYER from env" +fi + +echo "RPC_URL=${CERC_L2_GETH_RPC}" > .env +echo "NITRO_ADDRESSES_FILE_PATH=${NITRO_ADDRESSES_FILE_PATH}" >> .env +echo "PRIVATE_KEY=${CERC_PRIVATE_KEY_DEPLOYER}" >> .env + +yarn ts-node --esm deploy-nitro-contracts.ts diff --git a/app/data/config/watcher-mobymask-v3/deploy-nitro-contracts.ts b/app/data/config/watcher-mobymask-v3/deploy-nitro-contracts.ts new file mode 100644 index 00000000..c738083d --- /dev/null +++ b/app/data/config/watcher-mobymask-v3/deploy-nitro-contracts.ts @@ -0,0 +1,49 @@ +import 'dotenv/config'; +import fs from 'fs'; +import { providers, Wallet } from 'ethers'; +import { deployContracts } from '@cerc-io/nitro-util'; + +async function main () { + const rpcURL = process.env.RPC_URL; + const addressesFilePath = process.env.NITRO_ADDRESSES_FILE_PATH; + const deployerKey = process.env.PRIVATE_KEY; + + if (!rpcURL) { + console.log('RPC_URL not set, skipping deployment'); + return; + } + + if (!addressesFilePath) { + console.log('NITRO_ADDRESSES_FILE_PATH not set, skipping deployment'); + return; + } + + if (!deployerKey) { + console.log('PRIVATE_KEY not set, skipping deployment'); + return; + } + + const provider = new providers.JsonRpcProvider(process.env.RPC_URL); + const signer = new Wallet(deployerKey, provider); + + const [ + nitroAdjudicatorAddress, + virtualPaymentAppAddress, + consensusAppAddress + ] = await deployContracts(signer as any); + + const output = { + nitroAdjudicatorAddress, + virtualPaymentAppAddress, + consensusAppAddress + }; + + fs.writeFileSync(addressesFilePath, JSON.stringify(output, null, 2)); + console.log('Nitro contracts deployed, addresses written to', addressesFilePath); + console.log('Result:', JSON.stringify(output, null, 2)); +} + +main() + .catch((err) => { + console.log(err); + }); diff --git a/app/data/config/watcher-mobymask-v3/keys/12D3KooWAMjBkFCT9DtCnSDcxftxJzSuTBvzVojabv64cnEvX4AZ.json b/app/data/config/watcher-mobymask-v3/keys/12D3KooWAMjBkFCT9DtCnSDcxftxJzSuTBvzVojabv64cnEvX4AZ.json new file mode 100644 index 00000000..84465346 --- /dev/null +++ b/app/data/config/watcher-mobymask-v3/keys/12D3KooWAMjBkFCT9DtCnSDcxftxJzSuTBvzVojabv64cnEvX4AZ.json @@ -0,0 +1,11 @@ +{ + "peerId": { + "id": "12D3KooWAMjBkFCT9DtCnSDcxftxJzSuTBvzVojabv64cnEvX4AZ", + "privKey": "CAESQAKCrnY0QKTky1I18fqn+VPydXGUv1NYiV+nVKqBFkw/CAjE9sKKIDGnYAo8mivnI6dngFenERY+0Q8AJrPTaXY=", + "pubKey": "CAESIAgIxPbCiiAxp2AKPJor5yOnZ4BXpxEWPtEPACaz02l2" + }, + "consensus": { + "publicKey": "02cd17b05ca998955be5ca7bf4fd4531243d438f1aae7ce8a0ed5159f53cee5b40", + "privateKey": "67d80505614bdf61fca11cbad31d93acb2c7df1c653dc25975d77d05f05f154f" + } +} diff --git a/app/data/config/watcher-mobymask-v3/keys/12D3KooWBNEbY3QS4y23ngupDw9PDc4bvNvRJGVRejjV9EZLjux5.json b/app/data/config/watcher-mobymask-v3/keys/12D3KooWBNEbY3QS4y23ngupDw9PDc4bvNvRJGVRejjV9EZLjux5.json new file mode 100644 index 00000000..8eea1872 --- /dev/null +++ b/app/data/config/watcher-mobymask-v3/keys/12D3KooWBNEbY3QS4y23ngupDw9PDc4bvNvRJGVRejjV9EZLjux5.json @@ -0,0 +1,11 @@ +{ + "peerId": { + "id": "12D3KooWBNEbY3QS4y23ngupDw9PDc4bvNvRJGVRejjV9EZLjux5", + "privKey": "CAESQGSTw0ymvn8+wX9Dbvyr4/Gib1q2voe0CC0VyeClMQP6FwW14x0fpRbBIx0XhLdxWHkRndphVg3gVAHyC+7ZI8o=", + "pubKey": "CAESIBcFteMdH6UWwSMdF4S3cVh5EZ3aYVYN4FQB8gvu2SPK" + }, + "consensus": { + "publicKey": "029c8035b3e9401b8f178f7c37285b5cb22501e017340e2058b3b842f2a1f0ae45", + "privateKey": "0261008e8e3ec808168e99333599da38ca59a056a2ae4510a6ad3d8b5cb0918c" + } +} diff --git a/app/data/config/watcher-mobymask-v3/keys/12D3KooWSRH6ftgkAZsKZK7UX1Zr6Hx6YAsEepHqzopFszqfTxxi.json b/app/data/config/watcher-mobymask-v3/keys/12D3KooWSRH6ftgkAZsKZK7UX1Zr6Hx6YAsEepHqzopFszqfTxxi.json new file mode 100644 index 00000000..80721faa --- /dev/null +++ b/app/data/config/watcher-mobymask-v3/keys/12D3KooWSRH6ftgkAZsKZK7UX1Zr6Hx6YAsEepHqzopFszqfTxxi.json @@ -0,0 +1,11 @@ +{ + "peerId": { + "id": "12D3KooWSRH6ftgkAZsKZK7UX1Zr6Hx6YAsEepHqzopFszqfTxxi", + "privKey": "CAESQHBjlHxfVhZ2gXsBItrIEEgSGKcjMkFiGs3PPz9E3ace9qyWEkvR4oit5ve9SAROVoh20hoa42IC91NIafMaqws=", + "pubKey": "CAESIPaslhJL0eKIreb3vUgETlaIdtIaGuNiAvdTSGnzGqsL" + }, + "consensus": { + "publicKey": "039160c244a7ad8be16a64bdb69e6dbacdcfe20b37076792a0d06032a8097468ca", + "privateKey": "8894685fe81001d75662b079905472699373967451d1255ee5fc669d0a09a9ca" + } +} diff --git a/app/data/config/watcher-mobymask-v3/mobymask-app-start.sh b/app/data/config/watcher-mobymask-v3/mobymask-app-start.sh new file mode 100644 index 00000000..d7f87f19 --- /dev/null +++ b/app/data/config/watcher-mobymask-v3/mobymask-app-start.sh @@ -0,0 +1,62 @@ +#!/bin/bash + +set -e +if [ -n "$CERC_SCRIPT_DEBUG" ]; then + set -x +fi + +CERC_CHAIN_ID="${CERC_CHAIN_ID:-${DEFAULT_CERC_CHAIN_ID}}" +CERC_DEPLOYED_CONTRACT="${CERC_DEPLOYED_CONTRACT:-${DEFAULT_CERC_DEPLOYED_CONTRACT}}" +CERC_RELAY_NODES="${CERC_RELAY_NODES:-${DEFAULT_CERC_RELAY_NODES}}" +CERC_DENY_MULTIADDRS="${CERC_DENY_MULTIADDRS:-${DEFAULT_CERC_DENY_MULTIADDRS}}" +CERC_PUBSUB="${CERC_PUBSUB:-${DEFAULT_CERC_PUBSUB}}" + +echo "Using CERC_RELAY_NODES $CERC_RELAY_NODES" + +if [ -z "$CERC_DEPLOYED_CONTRACT" ]; then + echo "CERC_DEPLOYED_CONTRACT not set" + exit 1 +else + echo "Using CERC_DEPLOYED_CONTRACT ${CERC_DEPLOYED_CONTRACT} from env as the MobyMask contract address" +fi + +# Checkout to the required release/branch +cd /app +git checkout $CERC_RELEASE + +# Check if CERC_NA_ADDRESS 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" + + # Create the required JSON and write it to a file + nitro_addresses_json=$(jq -n \ + --arg na "$CERC_NA_ADDRESS" \ + --arg vpa "$CERC_VPA_ADDRESS" \ + --arg ca "$CERC_CA_ADDRESS" \ + '.nitroAdjudicatorAddress = $na | .virtualPaymentAppAddress = $vpa | .consensusAppAddress = $ca') + echo "$nitro_addresses_json" > /app/src/utils/nitro-addresses.json +else + echo "Nitro addresses not provided" + exit 1 +fi + +# Export config values in a json file +jq --arg address "$CERC_DEPLOYED_CONTRACT" \ + --argjson chainId "$CERC_CHAIN_ID" \ + --argjson relayNodes "$CERC_RELAY_NODES" \ + --argjson denyMultiaddrs "$CERC_DENY_MULTIADDRS" \ + --arg pubsub "$CERC_PUBSUB" \ + '.address = $address | .chainId = $chainId | .relayNodes = $relayNodes | .peer.denyMultiaddrs = $denyMultiaddrs | .peer.pubsub = $pubsub' \ + /app/src/mobymask-app-config.json > /app/src/utils/config.json + +yarn install + +REACT_APP_WATCHER_URI="$CERC_APP_WATCHER_URL/graphql" \ +REACT_APP_PAY_TO_NITRO_ADDRESS="$CERC_PAYMENT_NITRO_ADDRESS" \ +REACT_APP_SNAP_ORIGIN="local:$CERC_SNAP_URL" \ +yarn build + +http-server -p 80 /app/build diff --git a/app/data/config/watcher-mobymask-v3/mobymask-params.env b/app/data/config/watcher-mobymask-v3/mobymask-params.env new file mode 100644 index 00000000..35a54b69 --- /dev/null +++ b/app/data/config/watcher-mobymask-v3/mobymask-params.env @@ -0,0 +1,34 @@ +# Defaults + +# Set of relay peers to connect to from the relay node +DEFAULT_CERC_RELAY_PEERS=[] + +# Domain to be used in the relay node's announce address +DEFAULT_CERC_RELAY_ANNOUNCE_DOMAIN= + +# Base URI for mobymask-app (used for generating invite) +DEFAULT_CERC_MOBYMASK_APP_BASE_URI="http://127.0.0.1:3004/#" + +# Set to false for disabling watcher peer to send txs to L2 +DEFAULT_CERC_ENABLE_PEER_L2_TXS=true + +# Set deployed MobyMask contract address to avoid deploying contract in stack +# mobymask-app will use this contract address in config if run separately +DEFAULT_CERC_DEPLOYED_CONTRACT= + +# Chain ID is used by mobymask web-app for txs +DEFAULT_CERC_CHAIN_ID=42069 + +# Set of relay nodes to be used by web-apps +DEFAULT_CERC_RELAY_NODES=[] + +# Set of multiaddrs to be avoided while dialling +DEFAULT_CERC_DENY_MULTIADDRS=[] + +# Type of pubsub to be used +DEFAULT_CERC_PUBSUB="" + +# Set deployed Nitro addresses to avoid deploying them in the stack +DEFAULT_CERC_NA_ADDRESS= +DEFAULT_CERC_VPA_ADDRESS= +DEFAULT_CERC_CA_ADDRESS= diff --git a/app/data/config/watcher-mobymask-v3/start-server.sh b/app/data/config/watcher-mobymask-v3/start-server.sh new file mode 100755 index 00000000..9ff4020f --- /dev/null +++ b/app/data/config/watcher-mobymask-v3/start-server.sh @@ -0,0 +1,133 @@ +#!/bin/bash + +set -e +if [ -n "$CERC_SCRIPT_DEBUG" ]; then + set -x +fi + +CERC_L2_GETH_RPC="${CERC_L2_GETH_RPC:-${DEFAULT_CERC_L2_GETH_RPC}}" + +CERC_RELAY_PEERS="${CERC_RELAY_PEERS:-${DEFAULT_CERC_RELAY_PEERS}}" +CERC_DENY_MULTIADDRS="${CERC_DENY_MULTIADDRS:-${DEFAULT_CERC_DENY_MULTIADDRS}}" +CERC_PUBSUB="${CERC_PUBSUB:-${DEFAULT_CERC_PUBSUB}}" +CERC_RELAY_ANNOUNCE_DOMAIN="${CERC_RELAY_ANNOUNCE_DOMAIN:-${DEFAULT_CERC_RELAY_ANNOUNCE_DOMAIN}}" +CERC_ENABLE_PEER_L2_TXS="${CERC_ENABLE_PEER_L2_TXS:-${DEFAULT_CERC_ENABLE_PEER_L2_TXS}}" +CERC_DEPLOYED_CONTRACT="${CERC_DEPLOYED_CONTRACT:-${DEFAULT_CERC_DEPLOYED_CONTRACT}}" + +nitro_addresses_file="/nitro/nitro-addresses.json" +nitro_addresses_destination_file="./src/nitro-addresses.json" + +watcher_keys_dir="./keys" + +echo "Using L2 RPC endpoint ${CERC_L2_GETH_RPC}" + +# Use public domain for relay multiaddr in peer config if specified +# Otherwise, use the docker container's host IP +if [ -n "$CERC_RELAY_ANNOUNCE_DOMAIN" ]; then + CERC_RELAY_MULTIADDR="/dns4/${CERC_RELAY_ANNOUNCE_DOMAIN}/tcp/443/wss/p2p/$(jq -r '.id' /app/peers/relay-id.json)" +else + CERC_RELAY_MULTIADDR="/dns4/mobymask-watcher-server/tcp/9090/ws/p2p/$(jq -r '.id' /app/peers/relay-id.json)" +fi + +# Use contract address from environment variable or set from config.json in mounted volume +if [ -n "$CERC_DEPLOYED_CONTRACT" ]; then + CONTRACT_ADDRESS="${CERC_DEPLOYED_CONTRACT}" +else + # Assign deployed contract address from server config (created by mobymask container after deploying contract) + CONTRACT_ADDRESS=$(jq -r '.address' /server/config.json | tr -d '"') +fi + +# Copy the deployed Nitro addresses to the required path +if [ -f "$nitro_addresses_file" ]; then + cat "$nitro_addresses_file" > "$nitro_addresses_destination_file" + echo "Nitro addresses set to ${nitro_addresses_destination_file}" + + # Build after setting the Nitro addresses + yarn build +else + echo "File ${nitro_addresses_file} does not exist" + exit 1 +fi + +echo "Using CERC_PRIVATE_KEY_PEER (account with funds) from env for sending txs to L2" +echo "Using CERC_PRIVATE_KEY_NITRO from env for Nitro account" + +if [ -n "$CERC_PEER_ID" ]; then + echo "Using CERC_PEER_ID ${CERC_PEER_ID} from env for watcher fixture" + echo "Consensus module enabled" + + # Set corresponding variables + PEER_ID_FILE='./peer-id.json' + CONSENSUS_ENABLED=true + WATCHER_PARTY_PEERS_FILE='./watcher-party-peers.json' + + # Create watcher party array + watcher_parties=() + + # Iterate over each fixture JSON file + for peer_data_file in "$watcher_keys_dir"/*.json; do + # Extract the filename without the path and extension + peer_id=$(basename "$peer_data_file" .json) + + # Read the consensus keys + consensus_public_key=$(jq -r '.consensus.publicKey' "$peer_data_file") + consensus_private_key=$(jq -r '.consensus.privateKey' "$peer_data_file") + + # Append watcher party + watcher_party=$(jq -n \ + --arg peerId "$peer_id" \ + --arg publicKey "$consensus_public_key" \ + '.peerId = $peerId | .publicKey = $publicKey') + watcher_parties+=("$watcher_party") + + if [ "$peer_id" = "$CERC_PEER_ID" ]; then + # Export peer id + peer_id_data=$(jq '.peerId' "$peer_data_file") + echo "$peer_id_data" > "${PEER_ID_FILE}" + + # Set consensus keys for this peer + CONSENSUS_PUBLIC_KEY=${consensus_public_key} + CONSENSUS_PRIVATE_KEY=${consensus_private_key} + fi + done + + # Export watcher party file + watcher_parties_json=$(printf '%s\n' "${watcher_parties[@]}" | jq -s .) + echo "$watcher_parties_json" > "${WATCHER_PARTY_PEERS_FILE}" + echo "Watcher party peers exported to ${WATCHER_PARTY_PEERS_FILE}" +else + echo "Using generated peer id" + echo "Consensus module disabled" + + # Set corresponding variables + PEER_ID_FILE='./peers/peer-id.json' + CONSENSUS_ENABLED=false + WATCHER_PARTY_PEERS_FILE='' + CONSENSUS_PUBLIC_KEY='' + CONSENSUS_PRIVATE_KEY='' +fi + +# Read in the config template TOML file and modify it +WATCHER_CONFIG_TEMPLATE=$(cat environments/watcher-config-template.toml) +WATCHER_CONFIG=$(echo "$WATCHER_CONFIG_TEMPLATE" | \ + sed -E "s|REPLACE_WITH_CERC_RELAY_PEERS|${CERC_RELAY_PEERS}|g; \ + s|REPLACE_WITH_CERC_DENY_MULTIADDRS|${CERC_DENY_MULTIADDRS}|g; \ + s/REPLACE_WITH_CERC_PUBSUB/${CERC_PUBSUB}/g; \ + s/REPLACE_WITH_CERC_RELAY_ANNOUNCE_DOMAIN/${CERC_RELAY_ANNOUNCE_DOMAIN}/g; \ + s|REPLACE_WITH_CERC_RELAY_MULTIADDR|${CERC_RELAY_MULTIADDR}|g; \ + s|REPLACE_WITH_PEER_ID_FILE|${PEER_ID_FILE}|g; \ + s/REPLACE_WITH_CERC_ENABLE_PEER_L2_TXS/${CERC_ENABLE_PEER_L2_TXS}/g; \ + s/REPLACE_WITH_CERC_PRIVATE_KEY_PEER/${CERC_PRIVATE_KEY_PEER}/g; \ + s/REPLACE_WITH_CERC_PRIVATE_KEY_NITRO/${CERC_PRIVATE_KEY_NITRO}/g; \ + s/REPLACE_WITH_CONTRACT_ADDRESS/${CONTRACT_ADDRESS}/g; \ + s/REPLACE_WITH_CONSENSUS_ENABLED/${CONSENSUS_ENABLED}/g; \ + s/REPLACE_WITH_CONSENSUS_PUBLIC_KEY/${CONSENSUS_PUBLIC_KEY}/g; \ + s/REPLACE_WITH_CONSENSUS_PRIVATE_KEY/${CONSENSUS_PRIVATE_KEY}/g; \ + s|REPLACE_WITH_WATCHER_PARTY_PEERS_FILE|${WATCHER_PARTY_PEERS_FILE}|g; \ + s|REPLACE_WITH_CERC_L2_GETH_RPC_ENDPOINT|${CERC_L2_GETH_RPC}| ") + +# Write the modified content to a new file +echo "$WATCHER_CONFIG" > environments/local.toml + +echo 'yarn server' +yarn server diff --git a/app/data/config/watcher-mobymask-v3/watcher-config-rates.toml b/app/data/config/watcher-mobymask-v3/watcher-config-rates.toml new file mode 100644 index 00000000..ebb8f8a1 --- /dev/null +++ b/app/data/config/watcher-mobymask-v3/watcher-config-rates.toml @@ -0,0 +1,14 @@ +freeQueriesLimit = 10 + +freeQueriesList = [] + +[queries] + multiNonce = '50' + _owner = '50' + isRevoked = '50' + isPhisher = '50' + isMember = '50' + +[mutations] + invoke = '100' + revoke = '100' diff --git a/app/data/config/watcher-mobymask-v3/watcher-config-template.toml b/app/data/config/watcher-mobymask-v3/watcher-config-template.toml new file mode 100644 index 00000000..dbf5b407 --- /dev/null +++ b/app/data/config/watcher-mobymask-v3/watcher-config-template.toml @@ -0,0 +1,103 @@ +[server] + host = "0.0.0.0" + port = 3001 + kind = "lazy" + + # Checkpointing state. + checkpointing = true + + # Checkpoint interval in number of blocks. + checkpointInterval = 2000 + + # Enable state creation + enableState = true + + # Boolean to filter logs by contract. + filterLogs = true + + # Max block range for which to return events in eventsInRange GQL query. + # Use -1 for skipping check on block range. + maxEventsBlockRange = -1 + + [server.p2p] + enableRelay = true + enablePeer = true + + [server.p2p.relay] + host = "0.0.0.0" + port = 9090 + relayPeers = REPLACE_WITH_CERC_RELAY_PEERS + denyMultiaddrs = REPLACE_WITH_CERC_DENY_MULTIADDRS + peerIdFile = './peers/relay-id.json' + announce = 'REPLACE_WITH_CERC_RELAY_ANNOUNCE_DOMAIN' + pubsub = 'REPLACE_WITH_CERC_PUBSUB' + enableDebugInfo = true + + [server.p2p.peer] + relayMultiaddr = 'REPLACE_WITH_CERC_RELAY_MULTIADDR' + pubSubTopic = 'mobymask' + denyMultiaddrs = REPLACE_WITH_CERC_DENY_MULTIADDRS + peerIdFile = 'REPLACE_WITH_PEER_ID_FILE' + pubsub = 'REPLACE_WITH_CERC_PUBSUB' + enableDebugInfo = true + enableL2Txs = REPLACE_WITH_CERC_ENABLE_PEER_L2_TXS + + [server.p2p.peer.l2TxsConfig] + privateKey = 'REPLACE_WITH_CERC_PRIVATE_KEY_PEER' + contractAddress = 'REPLACE_WITH_CONTRACT_ADDRESS' + + [server.p2p.nitro] + store = './out/nitro-db' + privateKey = 'REPLACE_WITH_CERC_PRIVATE_KEY_NITRO' + chainPrivateKey = 'REPLACE_WITH_CERC_PRIVATE_KEY_PEER' + + [server.p2p.nitro.payments] + ratesFile = './environments/rates.toml' + requestTimeoutInSecs = 10 + + [server.p2p.nitro.payments.cache] + maxAccounts = 1000 + accountTTLInSecs = 1800 + maxVouchersPerAccount = 1000 + voucherTTLInSecs = 300 + maxPaymentChannels = 10000 + paymentChannelTTLInSecs = 1800 + + [server.p2p.consensus] + enabled = REPLACE_WITH_CONSENSUS_ENABLED + publicKey = 'REPLACE_WITH_CONSENSUS_PUBLIC_KEY' + privateKey = 'REPLACE_WITH_CONSENSUS_PRIVATE_KEY' + watcherPartyFile = 'REPLACE_WITH_WATCHER_PARTY_PEERS_FILE' + +[metrics] + host = "0.0.0.0" + port = 9000 + [metrics.gql] + port = 9001 + +[database] + type = "postgres" + host = "mobymask-watcher-db" + port = 5432 + database = "mobymask-watcher" + username = "vdbm" + password = "password" + synchronize = true + logging = false + +[upstream] + [upstream.ethServer] + gqlApiEndpoint = "http://ipld-eth-server:8083/graphql" + rpcProviderEndpoint = "REPLACE_WITH_CERC_L2_GETH_RPC_ENDPOINT" + blockDelayInMilliSecs = 60000 + + [upstream.cache] + name = "requests" + enabled = false + deleteOnStart = false + +[jobQueue] + dbConnectionString = "postgres://vdbm:password@mobymask-watcher-db/mobymask-watcher-job-queue" + maxCompletionLagInSecs = 300 + jobDelayInMilliSecs = 100 + eventsInBatch = 50 diff --git a/app/data/container-build/cerc-mobymask-ui/Dockerfile b/app/data/container-build/cerc-mobymask-ui/Dockerfile index 56e72a7a..e00ac663 100644 --- a/app/data/container-build/cerc-mobymask-ui/Dockerfile +++ b/app/data/container-build/cerc-mobymask-ui/Dockerfile @@ -1,6 +1,6 @@ # Originally from: https://github.com/devcontainers/images/blob/main/src/javascript-node/.devcontainer/Dockerfile # [Choice] Node.js version (use -bullseye variants on local arm64/Apple Silicon): 18, 16, 14, 18-bullseye, 16-bullseye, 14-bullseye, 18-buster, 16-buster, 14-buster -ARG VARIANT=16-bullseye +ARG VARIANT=18-bullseye FROM node:${VARIANT} ARG USERNAME=node @@ -37,7 +37,7 @@ RUN yarn global add http-server WORKDIR /app COPY . . -RUN npm install +RUN yarn install # Expose port for http EXPOSE 80 diff --git a/app/data/container-build/cerc-watcher-mobymask-v3/Dockerfile b/app/data/container-build/cerc-watcher-mobymask-v3/Dockerfile new file mode 100644 index 00000000..3e07eec9 --- /dev/null +++ b/app/data/container-build/cerc-watcher-mobymask-v3/Dockerfile @@ -0,0 +1,20 @@ +FROM ubuntu:22.04 + +RUN apt-get update \ + && apt-get install -y curl wget gnupg build-essential \ + && curl --silent --location https://deb.nodesource.com/setup_18.x | bash - \ + && apt-get update \ + && apt-get install -y nodejs git busybox jq \ + && node -v + +RUN corepack enable \ + && yarn --version + +WORKDIR /app + +COPY . . + +RUN echo "Building mobymask-v2-watcher-ts" && \ + yarn && yarn build + +WORKDIR /app diff --git a/app/data/container-build/cerc-watcher-mobymask-v3/build.sh b/app/data/container-build/cerc-watcher-mobymask-v3/build.sh new file mode 100755 index 00000000..1c26a4ce --- /dev/null +++ b/app/data/container-build/cerc-watcher-mobymask-v3/build.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +# Build cerc/watcher-mobymask-v3 + +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/watcher-mobymask-v3:local -f ${SCRIPT_DIR}/Dockerfile ${build_command_args} ${CERC_REPO_BASE_DIR}/mobymask-v2-watcher-ts diff --git a/app/data/container-image-list.txt b/app/data/container-image-list.txt index 9ed473ba..ab8bc3ce 100644 --- a/app/data/container-image-list.txt +++ b/app/data/container-image-list.txt @@ -50,3 +50,4 @@ cerc/watcher-sushiswap cerc/graph-node cerc/sushiswap-subgraphs cerc/webapp-base +cerc/watcher-mobymask-v3 diff --git a/app/data/pod-list.txt b/app/data/pod-list.txt index d375fd8e..ee3fc53b 100644 --- a/app/data/pod-list.txt +++ b/app/data/pod-list.txt @@ -35,3 +35,5 @@ contract-sushiswap graph-node sushiswap-subgraph-v3 fixturenet-sushiswap-subgraph-v3 +watcher-mobymask-v3 +mobymask-app-v3 diff --git a/app/data/stacks/mobymask-v3/README.md b/app/data/stacks/mobymask-v3/README.md new file mode 100644 index 00000000..6ea57af5 --- /dev/null +++ b/app/data/stacks/mobymask-v3/README.md @@ -0,0 +1,6 @@ +# MobyMask v3 + +Instructions to setup and deploy MobyMask v3 stack (watcher + web-app) using [laconic-stack-orchestrator](/README.md#install) + +* Follow [watcher.md](./watcher.md) for deploying the watcher +* Follow [web-app.md](./web-app.md) for deploying the app diff --git a/app/data/stacks/mobymask-v3/stack.yml b/app/data/stacks/mobymask-v3/stack.yml new file mode 100644 index 00000000..85af73ac --- /dev/null +++ b/app/data/stacks/mobymask-v3/stack.yml @@ -0,0 +1,16 @@ +version: "1.0" +description: "MobyMask v3 stack" +name: mobymask-v3 +repos: + - github.com/cerc-io/watcher-ts@v0.2.57 + - github.com/cerc-io/mobymask-v2-watcher-ts@v3 + - github.com/cerc-io/MobyMask@v0.1.3 + - github.com/cerc-io/mobymask-ui +containers: + - cerc/watcher-ts + - cerc/watcher-mobymask-v3 + - cerc/mobymask + - cerc/mobymask-ui +pods: + - watcher-mobymask-v3 + - mobymask-app-v3 diff --git a/app/data/stacks/mobymask-v3/watcher.md b/app/data/stacks/mobymask-v3/watcher.md new file mode 100644 index 00000000..9063b022 --- /dev/null +++ b/app/data/stacks/mobymask-v3/watcher.md @@ -0,0 +1,135 @@ +# MobyMask v3 Watcher + +## Setup + +Prerequisite: L2 Optimism Geth and Node RPC endpoints + +Clone required repositories: + +```bash +laconic-so --stack mobymask-v3 setup-repositories --pull --exclude github.com/cerc-io/mobymask-ui +``` + +Build the container images: + +```bash +laconic-so --stack mobymask-v3 build-containers --exclude cerc/mobymask-ui +``` + +## Deploy + +### Configuration + +Create and update an env file to be used in the next step ([defaults](../../config/watcher-mobymask-v3/mobymask-params.env)): + + ```bash + # External L2 endpoints + CERC_L2_GETH_RPC= + + # Endpoints waited on before contract deployment + CERC_L2_GETH_HOST= + CERC_L2_GETH_PORT= + + CERC_L2_NODE_HOST= + CERC_L2_NODE_PORT= + + # URL (fixturenet-eth-bootnode-lighthouse) to get CSV with credentials for accounts on L1 to perform txs on L2 + CERC_L1_ACCOUNTS_CSV_URL= + + # OR + # Specify the required account credentials + CERC_PRIVATE_KEY_DEPLOYER= + + # Base URI for mobymask-app + # (used for generating a root invite link after deploying the contract) + CERC_MOBYMASK_APP_BASE_URI="http://127.0.0.1:3004/#" + + # (Optional) Domain to be used in the relay node's announce address + CERC_RELAY_ANNOUNCE_DOMAIN= + + # (Optional) Set of relay peers to connect to from the relay node + CERC_RELAY_PEERS=[] + + # (Optional) Set of multiaddrs to be avoided while dialling + CERC_DENY_MULTIADDRS=[] + + # (Optional) Type of pubsub to be used + CERC_PUBSUB="" + + # Set to false for disabling watcher peer to send txs to L2 + CERC_ENABLE_PEER_L2_TXS=true + + # (Optional) Set already deployed MobyMask contract address to avoid deploying contract in the stack + CERC_DEPLOYED_CONTRACT= + + # (Optional) Set already deployed Nitro addresses to avoid deploying them in the stack + CERC_NA_ADDRESS= + CERC_VPA_ADDRESS= + CERC_CA_ADDRESS= + + # Specify private key of a funded account for sending txs to L2 + CERC_PRIVATE_KEY_PEER= + + # Specify private key for the Nitro account + CERC_PRIVATE_KEY_NITRO= + + # (Optional) Set a pre-existing peer id to be used (enables consensus) + # Uses a generated peer id if not set (disables consensus) + CERC_PEER_ID= + ``` + +* NOTE: If Optimism is running on the host machine, use `host.docker.internal` as the hostname to access the host port + +### Deploy the stack + +```bash +laconic-so --stack mobymask-v3 deploy --cluster mobymask_v3 --include watcher-mobymask-v3 --env-file up +``` + +* To list down and monitor the running containers: + + ```bash + laconic-so --stack mobymask-v3 deploy --cluster mobymask_v3 --include watcher-mobymask-v3 ps + + # With status + docker ps -a + + # Check logs for a container + docker logs -f + ``` + +* The watcher endpoint is exposed on host port `3001` and the relay node endpoint is exposed on host port `9090` + +* Check the logs of the MobyMask contract deployment container to get the deployed contract's address and generated root invite link: + + ```bash + docker logs -f $(docker ps -aq --filter name="mobymask-1") + ``` + +* Check the logs of the watcher server container to get the deployed Nitro contracts' addresses: + +```bash +docker exec -it $(docker ps -q --filter name="mobymask-watcher-server") bash -c "cat /nitro/nitro-addresses.json" +``` + +## Clean up + +Stop all services running in the background: + +```bash +laconic-so --stack mobymask-v3 deploy --cluster mobymask_v3 --include watcher-mobymask-v3 down +``` + +Clear volumes created by this stack: + +```bash +# List all relevant volumes +docker volume ls -q --filter "name=mobymask_v3" + +# Remove all the listed volumes +docker volume rm $(docker volume ls -q --filter "name=mobymask_v3") + +# WARNING: To avoid changing peer ids for the watcher, `peers_ids` volume can be persisted +# To delete all volumes except for `peers_ids` +docker volume rm $(docker volume ls -q --filter "name=mobymask_v3" | grep -v "peers_ids$") +``` diff --git a/app/data/stacks/mobymask-v3/web-app.md b/app/data/stacks/mobymask-v3/web-app.md new file mode 100644 index 00000000..d0efee81 --- /dev/null +++ b/app/data/stacks/mobymask-v3/web-app.md @@ -0,0 +1,86 @@ +# MobyMask v3 App + +## Setup + +Prerequisite: Watcher with GQL and relay node endpoints + +Clone required repositories: + +```bash +laconic-so --stack mobymask-v3 setup-repositories --pull --include github.com/cerc-io/mobymask-ui +``` + +Build the container images: + +```bash +laconic-so --stack mobymask-v3 build-containers --include cerc/mobymask-ui +``` + +## Deploy + +### Configuration + +Create and update an env file to be used in the next step ([defaults](../../config/watcher-mobymask-v3/mobymask-params.env)): + + ```bash + # Set of relay nodes to be used by the web-app + # (use double quotes " for strings, avoid space after commas) + # Eg. CERC_RELAY_NODES=["/dns4/example.com/tcp/443/wss/p2p/12D3KooWGHmDDCc93XUWL16FMcTPCGu2zFaMkf67k8HZ4gdQbRDr"] + CERC_RELAY_NODES=[] + + # Set of multiaddrs to be avoided while dialling + CERC_DENY_MULTIADDRS=[] + + # Also add if running MobyMask app: + + # Watcher endpoint used by the app for GQL queries + CERC_APP_WATCHER_URL="http://127.0.0.1:3001" + + # Set deployed MobyMask contract address to be used in MobyMask app's config + CERC_DEPLOYED_CONTRACT= + + # L2 Chain ID used by mobymask web-app for L2 txs + CERC_CHAIN_ID=42069 + + # (Optional) Type of pubsub to be used ("floodsub" | "gossipsub") + CERC_PUBSUB="" + + # Set Nitro addresses + CERC_NA_ADDRESS= + CERC_VPA_ADDRESS= + CERC_CA_ADDRESS= + + # Nitro account address to make the query and mutation payments to + CERC_PAYMENT_NITRO_ADDRESS= + + # Endpoint for Mobymask snap installation + CERC_SNAP_URL= + ``` + +### Deploy the stack + +```bash +laconic-so --stack mobymask-v3 deploy --cluster mobymask_v3 --include mobymask-app-v3 --env-file up + +# Runs the MobyMask v3 app on host port 3004 +``` + +To list down and monitor the running containers: + +```bash +laconic-so --stack mobymask-v3 deploy --cluster mobymask_v3 --include mobymask-app-v3 ps + +# With status +docker ps -a + +# Check logs for a container +docker logs -f +``` + +## Clean up + +Stop all services running in the background: + +```bash +laconic-so --stack mobymask-v3 deploy --cluster mobymask_v3 --include mobymask-app-v3 down +```