diff --git a/stack_orchestrator/data/compose/docker-compose-mobymask-app-v3-demo.yml b/stack_orchestrator/data/compose/docker-compose-mobymask-app-v3-demo.yml new file mode 100644 index 00000000..3925cb5b --- /dev/null +++ b/stack_orchestrator/data/compose/docker-compose-mobymask-app-v3-demo.yml @@ -0,0 +1,32 @@ +version: '3.2' + +services: + # Builds and serves the MobyMask v3 react-app + mobymask-v3-app: + restart: unless-stopped + image: cerc/mobymask-ui:local + environment: + CERC_SCRIPT_DEBUG: ${CERC_SCRIPT_DEBUG} + CERC_APP_WATCHER_URL: ${CERC_APP_WATCHER_URL} + CERC_SNAP_URL: ${CERC_SNAP_URL} + working_dir: /app + command: ["bash", "/scripts/mobymask-app-start.sh"] + volumes: + - ../config/watcher-mobymask-v3-demo/mobymask-app-start.sh:/scripts/mobymask-app-start.sh + - ../config/watcher-mobymask-v3-demo/local/keys:/server/keys + - mobymask_deployment:/server + - nitro_deployment:/nitro + 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" + +volumes: + mobymask_deployment: + nitro_deployment: diff --git a/stack_orchestrator/data/compose/docker-compose-watcher-mobymask-v3-demo.yml b/stack_orchestrator/data/compose/docker-compose-watcher-mobymask-v3-demo.yml new file mode 100644 index 00000000..738f02cb --- /dev/null +++ b/stack_orchestrator/data/compose/docker-compose-watcher-mobymask-v3-demo.yml @@ -0,0 +1,162 @@ +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-1,mobymask-watcher-1-job-queue,mobymask-watcher-2,mobymask-watcher-2-job-queue,mobymask-watcher-3,mobymask-watcher-3-job-queue + - POSTGRES_EXTENSION=mobymask-watcher-1-job-queue:pgcrypto,mobymask-watcher-2-job-queue:pgcrypto,mobymask-watcher-3-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: + - "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 + environment: + CERC_SCRIPT_DEBUG: ${CERC_SCRIPT_DEBUG} + # ENV: "PROD" # Check if required + CERC_ETH_RPC_ENDPOINT: ${CERC_ETH_RPC_ENDPOINT} + CERC_PRIVATE_KEY_DEPLOYER: ${CERC_PRIVATE_KEY_DEPLOYER} + CERC_MOBYMASK_APP_BASE_URI: ${CERC_MOBYMASK_APP_BASE_URI} + CERC_DEPLOYED_CONTRACT: ${CERC_DEPLOYED_CONTRACT} + command: ["bash", "-c", "./deploy-and-generate-invite.sh"] + volumes: + - ../config/watcher-mobymask-v3-demo/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" + + # Starts a MobyMask v3 watcher server #1 + mobymask-watcher-1-server: + image: cerc/watcher-mobymask-v3:local + restart: unless-stopped + depends_on: + mobymask-watcher-db: + condition: service_healthy + mobymask: + condition: service_completed_successfully + nitro-contracts: + condition: service_completed_successfully + environment: + CERC_SCRIPT_DEBUG: ${CERC_SCRIPT_DEBUG} + CERC_WATCHER_INDEX: 1 + CERC_ETH_RPC_QUERY_ENDPOINT: ${CERC_ETH_RPC_QUERY_ENDPOINT} + CERC_ETH_RPC_MUTATION_ENDPOINT: ${CERC_ETH_RPC_MUTATION_ENDPOINT} + CERC_NITRO_CHAIN_URL: ${CERC_NITRO_CHAIN_URL} + command: ["bash", "./start-server.sh"] + volumes: + - ../config/watcher-mobymask-v3-demo/watcher-config-template.toml:/app/environments/watcher-config-template.toml + - ../config/watcher-mobymask-v3-demo/watcher-config-rates.toml:/app/environments/rates.toml + - ../config/watcher-mobymask-v3-demo/local/keys:/app/keys + - ../config/watcher-mobymask-v3-demo/start-server.sh:/app/start-server.sh + - watcher_nitro_data:/app/out/nitro-db + - nitro_deployment:/nitro + - mobymask_deployment:/server + # Expose GQL, metrics and relay node ports + ports: + - "0.0.0.0:3001:3001" + - "9001" + - "0.0.0.0: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" + + # Starts a MobyMask v3 watcher server #2 + mobymask-watcher-2-server: + image: cerc/watcher-mobymask-v3:local + restart: unless-stopped + depends_on: + mobymask-watcher-1-server: + condition: service_healthy + environment: + CERC_SCRIPT_DEBUG: ${CERC_SCRIPT_DEBUG} + CERC_WATCHER_INDEX: 2 + CERC_ETH_RPC_QUERY_ENDPOINT: ${CERC_ETH_RPC_QUERY_ENDPOINT} + CERC_ETH_RPC_MUTATION_ENDPOINT: ${CERC_ETH_RPC_MUTATION_ENDPOINT} + CERC_NITRO_CHAIN_URL: ${CERC_NITRO_CHAIN_URL} + command: ["bash", "./start-server.sh"] + volumes: + - ../config/watcher-mobymask-v3-demo/watcher-config-template.toml:/app/environments/watcher-config-template.toml + - ../config/watcher-mobymask-v3-demo/watcher-config-rates.toml:/app/environments/rates.toml + - ../config/watcher-mobymask-v3-demo/local/keys:/app/keys + - ../config/watcher-mobymask-v3-demo/start-server.sh:/app/start-server.sh + - watcher_nitro_data:/app/out/nitro-db + - nitro_deployment:/nitro + - mobymask_deployment:/server + # Expose GQL, metrics and relay node ports + ports: + - "3001" + - "9001" + - "0.0.0.0:9091:9090" + healthcheck: + test: ["CMD", "busybox", "nc", "localhost", "9090"] + interval: 20s + timeout: 5s + retries: 15 + start_period: 5s + extra_hosts: + - "host.docker.internal:host-gateway" + + # Starts a MobyMask v3 watcher server #3 + mobymask-watcher-3-server: + image: cerc/watcher-mobymask-v3:local + restart: unless-stopped + depends_on: + mobymask-watcher-1-server: + condition: service_healthy + mobymask-watcher-2-server: + condition: service_healthy + environment: + CERC_SCRIPT_DEBUG: ${CERC_SCRIPT_DEBUG} + CERC_WATCHER_INDEX: 3 + CERC_ETH_RPC_QUERY_ENDPOINT: ${CERC_ETH_RPC_QUERY_ENDPOINT} + CERC_ETH_RPC_MUTATION_ENDPOINT: ${CERC_ETH_RPC_MUTATION_ENDPOINT} + CERC_NITRO_CHAIN_URL: ${CERC_NITRO_CHAIN_URL} + command: ["bash", "./start-server.sh"] + volumes: + - ../config/watcher-mobymask-v3-demo/watcher-config-template.toml:/app/environments/watcher-config-template.toml + - ../config/watcher-mobymask-v3-demo/watcher-config-rates.toml:/app/environments/rates.toml + - ../config/watcher-mobymask-v3-demo/local/keys:/app/keys + - ../config/watcher-mobymask-v3-demo/start-server.sh:/app/start-server.sh + - watcher_nitro_data:/app/out/nitro-db + - nitro_deployment:/nitro + - mobymask_deployment:/server + # Expose GQL, metrics and relay node ports + ports: + - "3001" + - "9001" + - "0.0.0.0:9092: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: + mobymask_deployment: + nitro_deployment: + watcher_nitro_data: diff --git a/stack_orchestrator/data/config/fixturenet-optimism/optimism-contracts/deploy-contracts.sh b/stack_orchestrator/data/config/fixturenet-optimism/optimism-contracts/deploy-contracts.sh index 23a2bc30..1eb0c8b6 100755 --- a/stack_orchestrator/data/config/fixturenet-optimism/optimism-contracts/deploy-contracts.sh +++ b/stack_orchestrator/data/config/fixturenet-optimism/optimism-contracts/deploy-contracts.sh @@ -65,7 +65,7 @@ if [ -n "$CERC_L1_ADDRESS" ] && [ -n "$CERC_L1_PRIV_KEY" ]; then # Sequencer SEQ=$(echo "$wallet3" | awk '/Address:/{print $2}') SEQ_KEY=$(echo "$wallet3" | awk '/Private key:/{print $3}') - + echo "Funding accounts." wait_for_block 1 300 cast send --from $ADMIN --rpc-url $CERC_L1_RPC --value 5ether $PROPOSER --private-key $ADMIN_KEY @@ -169,4 +169,4 @@ cp -a /app/packages/contracts-bedrock/deployments/$DEPLOYMENT_CONTEXT /l1-deploy cp /app/packages/contracts-bedrock/deploy-config/$DEPLOYMENT_CONTEXT.json /l2-config openssl rand -hex 32 > /l2-config/l2-jwt.txt -echo "Deployment successful. Exiting" +echo "Deployment successful. Exiting." diff --git a/stack_orchestrator/data/config/watcher-mobymask-v3-demo/deploy-and-generate-invite.sh b/stack_orchestrator/data/config/watcher-mobymask-v3-demo/deploy-and-generate-invite.sh new file mode 100755 index 00000000..b325d21d --- /dev/null +++ b/stack_orchestrator/data/config/watcher-mobymask-v3-demo/deploy-and-generate-invite.sh @@ -0,0 +1,80 @@ +#!/bin/bash + +set -e +if [ -n "$CERC_SCRIPT_DEBUG" ]; then + set -x +fi + +# From env: +# CERC_ETH_RPC_ENDPOINT +# CERC_MOBYMASK_APP_BASE_URI +# CERC_DEPLOYED_CONTRACT +# CERC_PRIVATE_KEY_DEPLOYER + +# Check if CERC_DEPLOYED_CONTRACT environment variable set to skip contract deployment +if [ -n "$CERC_DEPLOYED_CONTRACT" ]; then + echo "CERC_DEPLOYED_CONTRACT is set to '$CERC_DEPLOYED_CONTRACT'" + echo "Skipping contract deployment" + exit 0 +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" + +# Create the required JSON and write it to a file +secrets_file="secrets.json" +secrets_json=$(jq -n \ + --arg privateKey "$CERC_PRIVATE_KEY_DEPLOYER" \ + --arg rpcUrl "$CERC_ETH_RPC_ENDPOINT" \ + --arg baseURI "$CERC_MOBYMASK_APP_BASE_URI" \ + '.privateKey = $privateKey | .rpcUrl = $rpcUrl | .baseURI = $baseURI') +echo "$secrets_json" > "${secrets_file}" + +export RPC_URL="${CERC_ETH_RPC_ENDPOINT}" + +# Check and exit if a deployment already exists (on restarts) +if [ -f ./config.json ]; then + echo "config.json already exists, checking the contract deployment" + + # Read JSON file + deployment_details=$(cat config.json) + deployed_contract=$(echo "$deployment_details" | jq -r '.address') + + cd ../hardhat + if yarn verifyDeployment --network optimism --contract "${deployed_contract}"; then + echo "Deployment verfication successful" + cd ../server + else + echo "Deployment verfication failed, please clear MobyMask deployment volume before starting" + exit 1 + fi +fi + +npm run deployAndGenerateInvite diff --git a/stack_orchestrator/data/config/watcher-mobymask-v3-demo/local/config.env b/stack_orchestrator/data/config/watcher-mobymask-v3-demo/local/config.env new file mode 100644 index 00000000..f3e518ae --- /dev/null +++ b/stack_orchestrator/data/config/watcher-mobymask-v3-demo/local/config.env @@ -0,0 +1,16 @@ +# Watchers + +CERC_ETH_RPC_ENDPOINT="http://op-geth:8545" + +# L1 pre-funded account #4, funded on L2 as well +CERC_PRIVATE_KEY_DEPLOYER="0xbe4aa664815ea3bc3d63118649a733f6c96b243744310806ecb6d96359ab62cf" +CERC_MOBYMASK_APP_BASE_URI="http://127.0.0.1:3004/#" + +CERC_ETH_RPC_QUERY_ENDPOINT="http://op-geth:8545" +CERC_ETH_RPC_MUTATION_ENDPOINT="http://op-geth:8545" +CERC_NITRO_CHAIN_URL="http://op-geth:8546" + +# App + +CERC_APP_WATCHER_URL="http://localhost:3001" +CERC_SNAP_URL=http://localhost:8080 diff --git a/stack_orchestrator/data/config/watcher-mobymask-v3-demo/local/fund-accounts-on-l2.sh b/stack_orchestrator/data/config/watcher-mobymask-v3-demo/local/fund-accounts-on-l2.sh new file mode 100755 index 00000000..6635c93d --- /dev/null +++ b/stack_orchestrator/data/config/watcher-mobymask-v3-demo/local/fund-accounts-on-l2.sh @@ -0,0 +1,72 @@ +#!/bin/bash +set -e +if [ -n "$CERC_SCRIPT_DEBUG" ]; then + set -x +fi + +echo "*************************************" + +CERC_L1_RPC="${CERC_L1_RPC:-${DEFAULT_CERC_L1_RPC}}" +CERC_L1_CHAIN_ID="${CERC_L1_CHAIN_ID:-${DEFAULT_CERC_L1_CHAIN_ID}}" +CERC_L1_ACCOUNTS_CSV_URL="${CERC_L1_ACCOUNTS_CSV_URL:-${DEFAULT_CERC_L1_ACCOUNTS_CSV_URL}}" + +# Fixture accounts +WATCHER_1_ACCOUNT=0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 +WATCHER_2_ACCOUNT=0x70997970C51812dc3A010C7d01b50e0d17dc79C8 +WATCHER_3_ACCOUNT=0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65 +NITRO_APP_ACCOUNT=0xbDA5747bFD65F08deb54cb465eB87D40e51B197E + +WATCHER_1_ACCOUNT_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 +WATCHER_2_ACCOUNT_KEY=0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d +WATCHER_3_ACCOUNT_KEY=0x47e179ec197488593b187f80a00eb0da91f1b9d0b13f8733639f19c30a34926a +NITRO_APP_ACCOUNT_KEY=0x689af8efa8c651a91ad287602527f3af2fe9f6501a7ac4b061667b5a93e037fd + +# Check if watcher 1 account already funded +WATCHER_1_ACCOUNT_BALANCE=$(cast balance ${WATCHER_1_ACCOUNT} --rpc-url $CERC_L1_RPC) +echo "WATCHER_1_ACCOUNT_BALANCE ${WATCHER_1_ACCOUNT_BALANCE}" +if [ "$WATCHER_1_ACCOUNT_BALANCE" != "0" ]; then + echo "Watcher account already funded, exiting." + exit 0 +fi + +echo "Funding accounts on L2" + +# Fetch the L1 funded accounts +curl -o accounts.csv $CERC_L1_ACCOUNTS_CSV_URL + +# Use the accounts other than the ones used for Optimism deployment +ACCOUNT_1=$(awk -F ',' 'NR == 5 {print $2}' accounts.csv) +ACCOUNT_1_KEY=$(awk -F ',' 'NR == 5 {print $3}' accounts.csv) + +ACCOUNT_2=$(awk -F ',' 'NR == 6 {print $2}' accounts.csv) +ACCOUNT_2_KEY=$(awk -F ',' 'NR == 6 {print $3}' accounts.csv) + +# Get the bridge contract address +DEPLOYMENT_CONTEXT="$CERC_L1_CHAIN_ID" +BRIDGE=$(cat /l1-deployment/$DEPLOYMENT_CONTEXT/L1StandardBridgeProxy.json | jq -r .address) + +# Send balance to bridge contract on L1 +cast send --rpc-url $CERC_L1_RPC --from $ACCOUNT_1 --value 10000ether $BRIDGE --private-key $ACCOUNT_1_KEY +cast send --rpc-url $CERC_L1_RPC --from $ACCOUNT_2 --value 10000ether $BRIDGE --private-key $ACCOUNT_2_KEY + +echo "Following accounts have been funded; use them for transactions on L2:" +echo "${ACCOUNT_1}" +echo "${ACCOUNT_2}" + +echo "*************************************" +echo "Funding the watcher and app Nitro accounts on L2" + +cast send --rpc-url $CERC_L1_RPC --from $ACCOUNT_1 --value 200ether $WATCHER_1_ACCOUNT --private-key $ACCOUNT_1_KEY +cast send --rpc-url $CERC_L1_RPC --from $ACCOUNT_1 --value 200ether $WATCHER_2_ACCOUNT --private-key $ACCOUNT_1_KEY +cast send --rpc-url $CERC_L1_RPC --from $ACCOUNT_1 --value 200ether $WATCHER_3_ACCOUNT --private-key $ACCOUNT_1_KEY +cast send --rpc-url $CERC_L1_RPC --from $ACCOUNT_1 --value 200ether $NITRO_APP_ACCOUNT --private-key $ACCOUNT_1_KEY + +cast send --rpc-url $CERC_L1_RPC --from $WATCHER_1_ACCOUNT --value 100ether $BRIDGE --private-key $WATCHER_1_ACCOUNT_KEY +sleep 5 +cast send --rpc-url $CERC_L1_RPC --from $WATCHER_2_ACCOUNT --value 100ether $BRIDGE --private-key $WATCHER_2_ACCOUNT_KEY +sleep 5 +cast send --rpc-url $CERC_L1_RPC --from $WATCHER_3_ACCOUNT --value 100ether $BRIDGE --private-key $WATCHER_3_ACCOUNT_KEY +sleep 5 +cast send --rpc-url $CERC_L1_RPC --from $NITRO_APP_ACCOUNT --value 100ether $BRIDGE --private-key $NITRO_APP_ACCOUNT_KEY + +echo "Done, exiting." diff --git a/stack_orchestrator/data/config/watcher-mobymask-v3-demo/local/keys/watcher-1.json b/stack_orchestrator/data/config/watcher-mobymask-v3-demo/local/keys/watcher-1.json new file mode 100644 index 00000000..23c8254e --- /dev/null +++ b/stack_orchestrator/data/config/watcher-mobymask-v3-demo/local/keys/watcher-1.json @@ -0,0 +1,21 @@ +{ + "peerId": { + "id": "12D3KooWAMjBkFCT9DtCnSDcxftxJzSuTBvzVojabv64cnEvX4AZ", + "privKey": "CAESQAKCrnY0QKTky1I18fqn+VPydXGUv1NYiV+nVKqBFkw/CAjE9sKKIDGnYAo8mivnI6dngFenERY+0Q8AJrPTaXY=", + "pubKey": "CAESIAgIxPbCiiAxp2AKPJor5yOnZ4BXpxEWPtEPACaz02l2" + }, + "relayPeerId": { + "id": "12D3KooWNQJDGtH3YAZk2qG1ZbcoQvw6HaD814pfd9HHQthgX63K", + "privKey": "CAESQGc996T2OuyV3aY+hnna+GIexKBEcE6jDNX/RaofHr58uv2EYxXm4kcL2tO2tKgnPgtkegHFdjqy6h/xOA+YMZo=", + "pubKey": "CAESILr9hGMV5uJHC9rTtrSoJz4LZHoBxXY6suof8TgPmDGa" + }, + "peer": { + "privateKey": "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", + "nitroAddress": "0xAAA6628Ec44A8a742987EF3A114dDFE2D4F7aDCE", + "nitroPrivateKey": "2d999770f7b5d49b694080f987b82bbc9fc9ac2b4dcc10b0f8aba7d700f69c6d" + }, + "consensus": { + "publicKey": "02cd17b05ca998955be5ca7bf4fd4531243d438f1aae7ce8a0ed5159f53cee5b40", + "privateKey": "67d80505614bdf61fca11cbad31d93acb2c7df1c653dc25975d77d05f05f154f" + } +} diff --git a/stack_orchestrator/data/config/watcher-mobymask-v3-demo/local/keys/watcher-2.json b/stack_orchestrator/data/config/watcher-mobymask-v3-demo/local/keys/watcher-2.json new file mode 100644 index 00000000..8bac1eec --- /dev/null +++ b/stack_orchestrator/data/config/watcher-mobymask-v3-demo/local/keys/watcher-2.json @@ -0,0 +1,21 @@ +{ + "peerId": { + "id": "12D3KooWBNEbY3QS4y23ngupDw9PDc4bvNvRJGVRejjV9EZLjux5", + "privKey": "CAESQGSTw0ymvn8+wX9Dbvyr4/Gib1q2voe0CC0VyeClMQP6FwW14x0fpRbBIx0XhLdxWHkRndphVg3gVAHyC+7ZI8o=", + "pubKey": "CAESIBcFteMdH6UWwSMdF4S3cVh5EZ3aYVYN4FQB8gvu2SPK" + }, + "relayPeerId": { + "id": "12D3KooWPpBt2coC5BKEsewogHSkdgdyY9guUHJBgJFZoh66R4UL", + "privKey": "CAESQBdoGZzpiHsE8GlIhGGP+tl6A13sIPxOhgSwsWZR4cwmz/f7627X5GQRLD41ikH6oZ7ZeSbiiPsBtelL1+t3M80=", + "pubKey": "CAESIM/3++tu1+RkESw+NYpB+qGe2Xkm4oj7AbXpS9frdzPN" + }, + "peer": { + "privateKey": "59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d", + "nitroAddress": "0xBBB676f9cFF8D242e9eaC39D063848807d3D1D94", + "nitroPrivateKey": "0279651921cd800ac560c21ceea27aab0107b67daf436cdd25ce84cad30159b4" + }, + "consensus": { + "publicKey": "029c8035b3e9401b8f178f7c37285b5cb22501e017340e2058b3b842f2a1f0ae45", + "privateKey": "0261008e8e3ec808168e99333599da38ca59a056a2ae4510a6ad3d8b5cb0918c" + } +} diff --git a/stack_orchestrator/data/config/watcher-mobymask-v3-demo/local/keys/watcher-3.json b/stack_orchestrator/data/config/watcher-mobymask-v3-demo/local/keys/watcher-3.json new file mode 100644 index 00000000..2a0b22bf --- /dev/null +++ b/stack_orchestrator/data/config/watcher-mobymask-v3-demo/local/keys/watcher-3.json @@ -0,0 +1,21 @@ +{ + "peerId": { + "id": "12D3KooWSRH6ftgkAZsKZK7UX1Zr6Hx6YAsEepHqzopFszqfTxxi", + "privKey": "CAESQHBjlHxfVhZ2gXsBItrIEEgSGKcjMkFiGs3PPz9E3ace9qyWEkvR4oit5ve9SAROVoh20hoa42IC91NIafMaqws=", + "pubKey": "CAESIPaslhJL0eKIreb3vUgETlaIdtIaGuNiAvdTSGnzGqsL" + }, + "relayPeerId": { + "id": "12D3KooWLudDC3NnS8k9xLiqTZcS9xbFNrGSttu5GPynQgNgenPW", + "privKey": "CAESQHuEXPB1hTQATlZaNRQnAfSvnfYUeLF9PjSNKp9L33K2pMl37tTBYghnfQ0yluse0zHOIXRJM+9+ARn9+jIr0gU=", + "pubKey": "CAESIKTJd+7UwWIIZ30NMpbrHtMxziF0STPvfgEZ/foyK9IF" + }, + "peer": { + "privateKey": "47e179ec197488593b187f80a00eb0da91f1b9d0b13f8733639f19c30a34926a", + "nitroAddress": "0x67D5b55604d1aF90074FcB69b8C51838FFF84f8d", + "nitroPrivateKey": "58368d20ff12f17669c06158c21d885897aa56f9be430edc789614bf9851d53f" + }, + "consensus": { + "publicKey": "039160c244a7ad8be16a64bdb69e6dbacdcfe20b37076792a0d06032a8097468ca", + "privateKey": "8894685fe81001d75662b079905472699373967451d1255ee5fc669d0a09a9ca" + } +} diff --git a/stack_orchestrator/data/config/watcher-mobymask-v3-demo/mobymask-app-start.sh b/stack_orchestrator/data/config/watcher-mobymask-v3-demo/mobymask-app-start.sh new file mode 100644 index 00000000..d063f6de --- /dev/null +++ b/stack_orchestrator/data/config/watcher-mobymask-v3-demo/mobymask-app-start.sh @@ -0,0 +1,68 @@ +#!/bin/bash + +set -e +if [ -n "$CERC_SCRIPT_DEBUG" ]; then + set -x +fi + +watcher_keys_dir="/server/keys" + +# Configure relay nodes to connect to +# Note: Assuming host ports for watchers (1-3) relay nodes +RELAY_NODES="[\"/ip4/127.0.0.1/tcp/9090/ws/p2p/$(jq -r '.relayPeerId.id' ${watcher_keys_dir}/watcher-1.json)\", \"/ip4/127.0.0.1/tcp/9091/ws/p2p/$(jq -r '.relayPeerId.id' ${watcher_keys_dir}/watcher-2.json)\", \"/ip4/127.0.0.1/tcp/9092/ws/p2p/$(jq -r '.relayPeerId.id' ${watcher_keys_dir}/watcher-3.json)\"]" + +# Configure watcher (1) Nitro account to make payments to +PAYMENT_NITRO_ADDRESS=$(jq -r '.peer.nitroAddress' ${watcher_keys_dir}/watcher-1.json) + +echo "Using RELAY_NODES $RELAY_NODES" +echo "Using PAYMENT_NITRO_ADDRESS $PAYMENT_NITRO_ADDRESS" + +# Use config from mounted volume +echo "Taking config for deployed contracts from mounted volume" +while [ ! -f /server/config.json ]; do + echo "Config not found, retrying in 5 seconds..." + sleep 5 +done + +# Get deployed contract address and chain id +DEPLOYED_CONTRACT=$(jq -r '.address' /server/config.json | tr -d '"') +CHAIN_ID=$(jq -r '.chainId' /server/config.json) + +echo "Using DEPLOYED_CONTRACT $DEPLOYED_CONTRACT" +echo "Using CHAIN_ID $CHAIN_ID" + +nitro_addresses_file="/nitro/nitro-addresses.json" +nitro_addresses_destination_file="/app/src/utils/nitro-addresses.json" +if [ -f ${nitro_addresses_file} ]; then + echo "Using Nitro addresses from ${nitro_addresses_file}:" + cat "$nitro_addresses_file" + cat "$nitro_addresses_file" > "$nitro_addresses_destination_file" +else + echo "Nitro addresses not available" + exit 1 +fi + +# Export config values in a json file +app_config_file="/app/src/utils/config.json" +app_config_json=$(jq -n \ + --arg name "MobyMask" \ + --argjson enableDebugInfo true \ + --arg address "$DEPLOYED_CONTRACT" \ + --argjson chainId "$CHAIN_ID" \ + --argjson relayNodes "$RELAY_NODES" \ + --argjson denyMultiaddrs "[]" \ + --arg pubsub "" \ + --argjson directPeers "[]" \ + '.name = $name | .address = $address | .chainId = $chainId | .relayNodes = $relayNodes | .peer.enableDebugInfo = $enableDebugInfo | .peer.denyMultiaddrs = $denyMultiaddrs | .peer.pubsub = $pubsub | .peer.directPeers = $directPeers') +echo "$app_config_json" > "${app_config_file}" + +echo "Using CERC_APP_WATCHER_URL $CERC_APP_WATCHER_URL" +echo "Using CERC_SNAP_URL $CERC_SNAP_URL" + +REACT_APP_DEBUG_PEER=true \ +REACT_APP_WATCHER_URI="$CERC_APP_WATCHER_URL/graphql" \ +REACT_APP_PAY_TO_NITRO_ADDRESS="$PAYMENT_NITRO_ADDRESS" \ +REACT_APP_SNAP_ORIGIN="local:$CERC_SNAP_URL" \ +yarn build + +http-server -p 80 /app/build diff --git a/stack_orchestrator/data/config/watcher-mobymask-v3-demo/start-server.sh b/stack_orchestrator/data/config/watcher-mobymask-v3-demo/start-server.sh new file mode 100755 index 00000000..978911c0 --- /dev/null +++ b/stack_orchestrator/data/config/watcher-mobymask-v3-demo/start-server.sh @@ -0,0 +1,119 @@ +#!/bin/bash + +set -e +if [ -n "$CERC_SCRIPT_DEBUG" ]; then + set -x +fi + +watcher_keys_dir="./keys" + +echo "Watcher index: ${CERC_WATCHER_INDEX}" +echo "Using RPC query endpoint ${CERC_ETH_RPC_QUERY_ENDPOINT}" +echo "Using RPC mutation endpoint ${CERC_ETH_RPC_MUTATION_ENDPOINT}" +echo "Using Nitro chain URL ${CERC_NITRO_CHAIN_URL}" + +WATCHER_DB="mobymask-watcher-${CERC_WATCHER_INDEX}" + +# Use the docker container's host IP for relay multiaddr in peer config +CERC_RELAY_MULTIADDR="/dns4/mobymask-watcher-${CERC_WATCHER_INDEX}-server/tcp/9090/ws/p2p/$(jq -r '.relayPeerId.id' ${watcher_keys_dir}/watcher-${CERC_WATCHER_INDEX}.json)" + +# Assign deployed contract address from server config (created by mobymask container after deploying contract) +CONTRACT_ADDRESS=$(jq -r '.address' /server/config.json | tr -d '"') + +nitro_addresses_file="/nitro/nitro-addresses.json" +nitro_addresses_destination_file="./src/nitro-addresses.json" +if [ -f ${nitro_addresses_file} ]; then + echo "Using Nitro addresses from ${nitro_addresses_file}:" + cat "$nitro_addresses_file" + cat "$nitro_addresses_file" > "$nitro_addresses_destination_file" +else + echo "Nitro addresses not available" + exit 1 +fi + +# Build after setting the Nitro addresses +yarn build + +PEER_ID_FILE='./peer-id.json' +RELAY_PEER_ID_FILE='./relay-id.json' + +# Create watcher party array +watcher_parties=() + +# Iterate over each fixture JSON file +for watcher_keys_file in "$watcher_keys_dir"/*.json; do + # Extract the filename without the path and extension + filename=$(basename "$watcher_keys_file" .json) + + # Read the consensus keys + peer_id=$(jq -r '.peerId.id' "$watcher_keys_file") + + # Read the consensus keys + consensus_public_key=$(jq -r '.consensus.publicKey' "$watcher_keys_file") + consensus_private_key=$(jq -r '.consensus.privateKey' "$watcher_keys_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 [ "$filename" = "watcher-${CERC_WATCHER_INDEX}" ]; then + # Export watcher peer and relay ids + peer_id_data=$(jq '.peerId' "$watcher_keys_file") + relay_peer_id_data=$(jq '.relayPeerId' "$watcher_keys_file") + echo "$peer_id_data" > "${PEER_ID_FILE}" + echo "$relay_peer_id_data" > "${RELAY_PEER_ID_FILE}" + + # Set peer and nitro account keys + CERC_PRIVATE_KEY_PEER=$(jq -r '.peer.privateKey' "$watcher_keys_file") + CERC_WATCHER_NITRO_PK=$(jq -r '.peer.nitroPrivateKey' "$watcher_keys_file") + + # Set consensus keys for this peer + CONSENSUS_PUBLIC_KEY=${consensus_public_key} + CONSENSUS_PRIVATE_KEY=${consensus_private_key} + fi +done + +echo "Consensus module enabled" +CONSENSUS_ENABLED=true +WATCHER_PARTY_PEERS_FILE='./watcher-party-peers.json' + +# 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}" + +# Configure relay peers for watcher 2 and 3 +CERC_RELAY_PEERS=[] +if [ "${CERC_WATCHER_INDEX}" = "2" ]; then + # 2 -> 1 + CERC_RELAY_PEERS="['/dns4/mobymask-watcher-1-server/tcp/9090/ws/p2p/$(jq -r '.relayPeerId.id' ${watcher_keys_dir}/watcher-1.json)']" +elif [ "${CERC_WATCHER_INDEX}" = "3" ]; then + # 3 -> 1, 2 + CERC_RELAY_PEERS="['/dns4/mobymask-watcher-1-server/tcp/9090/ws/p2p/$(jq -r '.relayPeerId.id' ${watcher_keys_dir}/watcher-1.json)', '/dns4/mobymask-watcher-2-server/tcp/9090/ws/p2p/$(jq -r '.relayPeerId.id' ${watcher_keys_dir}/watcher-2.json)']" +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_RELAY_MULTIADDR|${CERC_RELAY_MULTIADDR}|g; \ + s/REPLACE_WITH_CERC_PRIVATE_KEY_PEER/${CERC_PRIVATE_KEY_PEER}/g; \ + s/REPLACE_WITH_CERC_WATCHER_NITRO_PK/${CERC_WATCHER_NITRO_PK}/g; \ + s/REPLACE_WITH_CONTRACT_ADDRESS/${CONTRACT_ADDRESS}/g; \ + s|REPLACE_WITH_CERC_NITRO_CHAIN_URL|${CERC_NITRO_CHAIN_URL}|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_ETH_RPC_QUERY_ENDPOINT|${CERC_ETH_RPC_QUERY_ENDPOINT}|g; \ + s|REPLACE_WITH_CERC_ETH_RPC_MUTATION_ENDPOINT|${CERC_ETH_RPC_MUTATION_ENDPOINT}|g; \ + s|REPLACE_WITH_WATCHER_DB|${WATCHER_DB}| ") + +# Write the modified content to a new file +echo "$WATCHER_CONFIG" > environments/local.toml + +echo 'Running watcher server' +yarn server diff --git a/stack_orchestrator/data/config/watcher-mobymask-v3-demo/watcher-config-rates.toml b/stack_orchestrator/data/config/watcher-mobymask-v3-demo/watcher-config-rates.toml new file mode 100644 index 00000000..ebb8f8a1 --- /dev/null +++ b/stack_orchestrator/data/config/watcher-mobymask-v3-demo/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/stack_orchestrator/data/config/watcher-mobymask-v3-demo/watcher-config-template.toml b/stack_orchestrator/data/config/watcher-mobymask-v3-demo/watcher-config-template.toml new file mode 100644 index 00000000..f2ec9eed --- /dev/null +++ b/stack_orchestrator/data/config/watcher-mobymask-v3-demo/watcher-config-template.toml @@ -0,0 +1,111 @@ +[server] + host = "0.0.0.0" + port = 3001 + kind = "lazy" + + # Checkpointing state. + checkpointing = false + + # Checkpoint interval in number of blocks. + checkpointInterval = 2000 + + # Enable state creation + enableState = false + + # 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 + + # Flag to specify whether RPC endpoint supports block hash as block tag parameter + rpcSupportsBlockHashParam = true + + [server.p2p] + enableRelay = true + enablePeer = true + + [server.p2p.relay] + host = "0.0.0.0" + port = 9090 + relayPeers = REPLACE_WITH_CERC_RELAY_PEERS + denyMultiaddrs = [] + peerIdFile = './relay-id.json' + announce = '' + pubsub = '' + enableDebugInfo = true + + [server.p2p.peer] + relayMultiaddr = 'REPLACE_WITH_CERC_RELAY_MULTIADDR' + pubSubTopic = 'mobymask' + denyMultiaddrs = [] + peerIdFile = './peer-id.json' + pubsub = '' + enableDebugInfo = true + enableL2Txs = true + pingInterval = 4000 + pingTimeout = 1500 + maxRelayConnections = 10 + + [server.p2p.peer.l2TxsConfig] + privateKey = 'REPLACE_WITH_CERC_PRIVATE_KEY_PEER' + contractAddress = 'REPLACE_WITH_CONTRACT_ADDRESS' + + [server.p2p.nitro] + chainUrl = 'REPLACE_WITH_CERC_NITRO_CHAIN_URL' + store = './out/nitro-db' + privateKey = 'REPLACE_WITH_CERC_WATCHER_NITRO_PK' + 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' + watcherPartyPeersFile = '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 = "REPLACE_WITH_WATCHER_DB" + username = "vdbm" + password = "password" + synchronize = true + logging = false + +[upstream] + [upstream.ethServer] + gqlApiEndpoint = "http://ipld-eth-server:8083/graphql" + rpcProviderEndpoint = 'REPLACE_WITH_CERC_ETH_RPC_QUERY_ENDPOINT' + rpcProviderMutationEndpoint = 'REPLACE_WITH_CERC_ETH_RPC_MUTATION_ENDPOINT' + + [upstream.cache] + name = "requests" + enabled = false + deleteOnStart = false + +[jobQueue] + dbConnectionString = "postgres://vdbm:password@mobymask-watcher-db/REPLACE_WITH_WATCHER_DB-job-queue" + maxCompletionLagInSecs = 300 + jobDelayInMilliSecs = 100 + eventsInBatch = 50 + blockDelayInMilliSecs = 60000 diff --git a/stack_orchestrator/data/container-build/cerc-optimism-contracts/Dockerfile b/stack_orchestrator/data/container-build/cerc-optimism-contracts/Dockerfile index 2499df0a..b6dd90e9 100644 --- a/stack_orchestrator/data/container-build/cerc-optimism-contracts/Dockerfile +++ b/stack_orchestrator/data/container-build/cerc-optimism-contracts/Dockerfile @@ -3,12 +3,17 @@ FROM cerc/foundry:local # Install node (local foundry is a debian based image) RUN apt-get update \ && apt-get install -y curl wget \ - && curl --silent --location https://deb.nodesource.com/setup_16.x | bash - \ - && apt-get update \ - && apt-get install -y nodejs git busybox jq \ + && apt-get install -y git busybox jq python3 make gcc g++ + +RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash \ + && export NVM_DIR="$HOME/.nvm" \ + && [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" \ + && nvm install 16.16.0 \ && node -v -RUN corepack enable \ +SHELL ["/bin/bash", "-c"] +RUN source $HOME/.bashrc \ + && corepack enable \ && yarn --version WORKDIR /app @@ -16,7 +21,10 @@ WORKDIR /app # Copy optimism repo contents COPY . . -RUN echo "Building optimism" && \ - pnpm install && pnpm build +SHELL ["/bin/bash", "-c"] +RUN source $HOME/.bashrc \ + && echo "Building optimism" \ + && pnpm i -g pnpm@8.15.3 \ + && pnpm install && pnpm build WORKDIR /app/packages/contracts-bedrock diff --git a/stack_orchestrator/data/stacks/mobymask-v3-demo/README.md b/stack_orchestrator/data/stacks/mobymask-v3-demo/README.md new file mode 100644 index 00000000..11623d02 --- /dev/null +++ b/stack_orchestrator/data/stacks/mobymask-v3-demo/README.md @@ -0,0 +1,95 @@ +# MobyMask v3 Demo + +Instructions to setup and deploy an end-to-end MobyMask v3 stack (fixturenet-optimism + watchers + web-app) locally using [laconic-stack-orchestrator](/README.md#install) + +## Setup + +* Clone required repositories: + + ```bash + laconic-so --stack mobymask-v3-demo setup-repositories --pull + ``` + +* Build the container images: + + ```bash + laconic-so --stack mobymask-v3-demo build-containers + ``` + +* Install MetaMask Flask extension in a chromium browser from chrome web store and follow the setup instructions + +## Deploy + +* Create a spec file for the deployment: + + ```bash + laconic-so --stack mobymask-v3-demo deploy init --output mobymask-v3-demo-spec.yml + ``` + +* Create a deployment from the generated spec file: + + ```bash + laconic-so --stack mobymask-v3-demo deploy create --spec-file mobymask-v3-demo-spec.yml --deployment-dir mobymask-v3-demo-deployment + ``` + +* Copy over the demo config to place it at an appropriate path: + + ```bash + cp mobymask-v3-demo-deployment/config/watcher-mobymask-v3-demo/local/config.env mobymask-v3-demo-deployment/ + ``` + +### Start the stack + +* Start the deployment: + + ```bash + laconic-so deployment --dir mobymask-v3-demo-deployment start + + # Useful ports exposed on host + # 3001: MobyMask v3 watcher 1 GQL endpoint + # 9090: MobyMask v3 watcher 1 relay node endpoint + # 9091: MobyMask v3 watcher 2 relay node endpoint + # 9092: MobyMask v3 watcher 3 relay node endpoint + # 8080: MobyMask snap + # 3004: MobyMask v3 app + ``` + + Note: This may take several minutes as it configures and runs the L1, L2 chains and the watchers; you can follow the progress from containers' logs + +* To list and monitor the running containers: + + ```bash + laconic-so deployment --dir mobymask-v3-demo-deployment ps + + # With status + docker ps + + # Check logs for a container + docker logs -f + ``` + +## Demo + +Follow [demo](./demo.md) to try out the MobyMask app + +## Clean up + +To stop all services running in the background, while preserving data: + + ```bash + laconic-so deployment --dir mobymask-v3-demo-deployment stop + ``` + +To stop all services and also delete data: + + ```bash + laconic-so deployment --dir mobymask-v3-demo-deployment stop --delete-volumes + + # Also remove the deployment directory + rm -rf mobymask-v3-demo-deployment + ``` + +## Known Issues + +* Resource requirements (memory + time) for building the `cerc/foundry` image are on the higher side + * `cerc/optimism-contracts` image is currently based on `cerc/foundry` (Optimism requires foundry installation) diff --git a/stack_orchestrator/data/stacks/mobymask-v3-demo/demo.md b/stack_orchestrator/data/stacks/mobymask-v3-demo/demo.md new file mode 100644 index 00000000..297de9f1 --- /dev/null +++ b/stack_orchestrator/data/stacks/mobymask-v3-demo/demo.md @@ -0,0 +1,195 @@ +# Demo + +## Setup + +* Follow logs and check that all 3 watchers are running in consensus: + + ```bash + # Follow the logs in three different terminals and keep them running + docker logs -f $(docker ps --filter "name=mobymask-watcher-1" -q) + docker logs -f $(docker ps --filter "name=mobymask-watcher-2" -q) + docker logs -f $(docker ps --filter "name=mobymask-watcher-3" -q) + + # Expected output when all three are running in consensus: + # ... + # 2024-02-21T10:42:23.932Z laconic:consensus State changed to 3 (FOLLOWER) with term 286 + # 2024-02-21T10:42:23.932Z laconic:consensus State changed to 2 (CANDIDATE) with term 287 + # 2024-02-21T10:42:24.406Z laconic:consensus State changed to 1 (LEADER) with term 287 + # ... + + # At any moment, only one of watchers is the 'LEADER' + ``` + +* In MetaMask, go to settings add a custom network with the following settings: + + ```bash + # Network name + Local Optimism + + # New RPC URL + http://127.0.0.1:8545 + + # Chain ID + 42069 + + # Currency symbol + ETH + ``` + + Switch to the newly added network + +* Import a pre-funded account (using it's private key) for Nitro client in the MobyMask app: + + ```bash + # PK: 689af8efa8c651a91ad287602527f3af2fe9f6501a7ac4b061667b5a93e037fd + # Address: 0xbDA5747bFD65F08deb54cb465eB87D40e51B197E + ``` + +## Run + +### Open MobyMask app + +* Copy the generated invite link from MobyMask deployment container logs: + + ```bash + docker logs -f $(docker ps -a --filter "name=mobymask-1" -q) + + # A SIGNED DELEGATION/INVITE LINK: + # ... + # http://127.0.0.1:3004/#/members?invitation= + ``` + +* Open the invite link in browser where MetaMask was setup + +* In the app’s debug panel (bottom-right), check from `PEERS` and `GRAPH` tabs that the peer gets connected to relay nodes and watcher peers + +* Perform phisher status checks from the app + * First 10 queries are served for free; repeat until the free quota is exhausted + * Same can be seen in the watcher-1's logs (the app makes all the GQL queries to watcher-1): + + ```bash + # ... + # 2024-02-21T11:01:20.084Z laconic:payments Query rate not configured for "latestBlock", serving free query + # 2024-02-21T11:01:20.084Z vulcanize:resolver latestBlock + # 2024-02-21T11:01:20.108Z laconic:payments Serving a free query to 0x3c9B491ACA5cf17B6C11E39bbFddCA603F387d41 + # 2024-02-21T11:01:20.109Z vulcanize:resolver isPhisher 0xf8995f83bbab2bc13fb9a43c6fea4a605616e6f59503f36cbe2ad3abffd0efd3 0xAFA36c47E130d89bcE4470a9030d99f3CEcaD146 TWT:dummyPhisher + # 2024-02-21T11:01:20.113Z vulcanize:indexer isPhisher: db miss, fetching from upstream server + # ... + + # After free quota has been exhausted: + # 2024-02-21T11:06:49.311Z laconic:payments Query rate not configured for "latestBlock", serving free query + # 2024-02-21T11:06:49.312Z vulcanize:resolver latestBlock + # 2024-02-21T11:06:49.337Z laconic:payments Rejecting query from 0x3c9B491ACA5cf17B6C11E39bbFddCA603F387d41: Free quota exhausted + ``` + +### Setup app's Nitro node + +* Open the `NITRO` tab in debug panel + +* Click on `Connect Wallet` button to connect to MetaMask (use the imported account with funds) + +* Click on `Connect Snap` to install / connect snap; the watcher Nitro clients should show up in the `NITRO` tab + +* Click on `DIRECT FUND` button against watcher-1's Nitro account (`0xAAA6628Ec44A8a742987EF3A114dDFE2D4F7aDCE`) to create a ledger channel with the pre-set amount + * Confirm the tx in MetaMask popup; wait some time for the tx to be confirmed and ledger channel to be created + * The progress can be followed from watcher-1's logs + * The created ledger channel should now be visible in the `NITRO` tab; click on `REFRESH` button otherwise + +* Change amount to `10000` and click on `VIRTUAL FUND` button to create a virtual payment channel + * This results in a payment channel between the app and watcher-1 + * The payment channel's details should now be visible along with a `PAY` and `VIRTUAL DEFUND` buttons + +* Close the debug panel + +### Paid queries and mutations + +* Perform phisher status checks now that a payment channel has been created + * Amount set in the debug panel's `NITRO` tab is sent along with each request to the watcher + * Check the watcher-1 logs for the received payments: + + ```bash + # ... + # 2024-02-21T11:35:25.538Z ts-nitro:engine {"msg":"Received message","_msg":{"to":"0xAAA662","from":"0x5D12ac","payloadSummaries":[],"proposalSummaries":[],"payments":[{"amount":50,"channelId":"0x654a85725442828f89b497e3973640613c03b5f5ec47302bfa4402d42c07de30"}],"rejectedObjectives":[]}} + # 2024-02-21T11:35:25.552Z laconic:payments Query rate not configured for "latestBlock", serving free query + # 2024-02-21T11:35:25.553Z vulcanize:resolver latestBlock + # 2024-02-21T11:35:25.557Z laconic:payments Received a payment voucher of 50 from 0x5D12acfbBB1caD65fD61983003a50E0CB6900Fd3 + # 2024-02-21T11:35:25.570Z laconic:payments Serving a paid query for 0x5D12acfbBB1caD65fD61983003a50E0CB6900Fd3 + # 2024-02-21T11:35:25.570Z vulcanize:resolver isPhisher 0x6a1f0dce967aefd4adf7762c523cde358960236f05734f616ebe69c0abfcb0cc 0xAFA36c47E130d89bcE4470a9030d99f3CEcaD146 TWT:dummyPhisher + # 2024-02-21T11:35:25.580Z vulcanize:indexer isPhisher: db miss, fetching from upstream server + # ... + ``` + +* Rate for mutations is set to `100` in the watcher; go back to the `NITRO` tab in the debug panel and change amount value besides `PAY` button to >=100 + +* Perform a phisher report + * Enter a new record(s) and click on `Submit batch to p2p network` button + * Among all three watchers running in consensus, whoever is the `LEADER` at time of reporting sends a tx to the chain + * Check all the watchers' logs: + + If the payment receiving watcher (1) is leader at that moment: + + ```bash + # On watcher-1 (payment received + tx sent) + # ... + # 2024-02-21T11:42:55.088Z vulcanize:libp2p-utils [11:42:55] Received a message on mobymask P2P network from peer: 12D3KooWGXxcwevUY7KCfw8fcGhxqxPaiFMGSU4tgJDjE54QGKzf + # 2024-02-21T11:42:55.102Z ts-nitro:engine {"msg":"Received message","_msg":{"to":"0xAAA662","from":"0x5D12ac","payloadSummaries":[],"proposalSummaries":[],"payments":[{"amount":150,"channelId":"0x654a85725442828f89b497e3973640613c03b5f5ec47302bfa4402d42c07de30"}],"rejectedObjectives":[]}} + # 2024-02-21T11:42:55.115Z laconic:payments Received a payment voucher of 100 from 0x5D12acfbBB1caD65fD61983003a50E0CB6900Fd3 + # 2024-02-21T11:42:55.115Z vulcanize:libp2p-utils Payment received for a mutation request from 0x5D12acfbBB1caD65fD61983003a50E0CB6900Fd3 + # 2024-02-21T11:42:59.115Z vulcanize:libp2p-utils Transaction receipt for invoke message { + # to: '0xAFA36c47E130d89bcE4470a9030d99f3CEcaD146', + # blockNumber: 4638, + # blockHash: '0x23a42bc2ae43771c62b0d59cc48b5858e6e2e488953527ba6a9f5119ae72b42a', + # transactionHash: '0xb61cfdfd0ffe937a191a230e1355b9bc5cdd32507f7b4f24a8e6356adf089b64', + # effectiveGasPrice: '1500000050', + # gasUsed: '136450' + # } + # ... + + # On other watchers (payment not received + tx not sent) + ... + # 2024-02-21T11:42:50.329Z laconic:consensus State changed to 3 (FOLLOWER) with term 478 + # 2024-02-21T11:42:55.089Z vulcanize:libp2p-utils [11:42:55] Received a message on mobymask P2P network from peer: 12D3KooWGXxcwevUY7KCfw8fcGhxqxPaiFMGSU4tgJDjE54QGKzf + # 2024-02-21T11:42:55.096Z vulcanize:libp2p-utils Not a leader, skipped sending L2 tx + # 2024-02-21T11:43:05.095Z vulcanize:libp2p-utils Payment not received + # ... + ``` + + If the payment receiving watcher (1) is NOT leader at that moment: + + ```bash + # On watcher 1 (payment received + tx not sent) + # ... + # 2024-02-21T11:46:52.049Z vulcanize:libp2p-utils [11:46:52] Received a message on mobymask P2P network from peer: 12D3KooWGXxcwevUY7KCfw8fcGhxqxPaiFMGSU4tgJDjE54QGKzf + # 2024-02-21T11:46:52.051Z vulcanize:libp2p-utils Not a leader, skipped sending L2 tx + # 2024-02-21T11:46:52.074Z ts-nitro:engine {"msg":"Received message","_msg":{"to":"0xAAA662","from":"0x5D12ac","payloadSummaries":[],"proposalSummaries":[],"payments":[{"amount":450,"channelId":"0x654a85725442828f89b497e3973640613c03b5f5ec47302bfa4402d42c07de30"}],"rejectedObjectives":[]}} + # 2024-02-21T11:46:52.097Z laconic:payments Received a payment voucher of 100 from 0x5D12acfbBB1caD65fD61983003a50E0CB6900Fd3 + # 2024-02-21T11:46:52.097Z vulcanize:libp2p-utils Payment received for a mutation request from 0x5D12acfbBB1caD65fD61983003a50E0CB6900Fd3 + # ... + + # On the leader watcher (payment not received + tx sent) + # ... + # 2024-02-21T11:46:40.111Z vulcanize:libp2p-utils Payment not received + # 2024-02-21T11:46:52.048Z vulcanize:libp2p-utils [11:46:52] Received a message on mobymask P2P network from peer: 12D3KooWGXxcwevUY7KCfw8fcGhxqxPaiFMGSU4tgJDjE54QGKzf + # 2024-02-21T11:46:56.048Z vulcanize:libp2p-utils Transaction receipt for invoke message { + # to: '0xAFA36c47E130d89bcE4470a9030d99f3CEcaD146', + # blockNumber: 4757, + # blockHash: '0x859aa54cb02e8a3f910a01b85c2a7bf9bff7540e83018e7e846f87ca1770e55e', + # transactionHash: '0x92f087e4b6ac5604c9d4ecd823d526ca5f8f1bf5c2a92861d6b0f69bd899ba83', + # effectiveGasPrice: '1500000050', + # gasUsed: '136438' + # } + ``` + +* Check phisher status for the reported phishers to confirm state update + +## Clean up + +* From the `NITRO` tab in debug panel, perform `VIRTUAL DEFUND` and `DIRECT DEFUND` (in order) for any payment channels created + +* In the browser's console, delete all indexedDBs: + + ```bash + await clearNodeStorage() + ``` + +* Remove the snap from MetaMask flask extension diff --git a/stack_orchestrator/data/stacks/mobymask-v3-demo/deploy/commands.py b/stack_orchestrator/data/stacks/mobymask-v3-demo/deploy/commands.py new file mode 100644 index 00000000..135091b7 --- /dev/null +++ b/stack_orchestrator/data/stacks/mobymask-v3-demo/deploy/commands.py @@ -0,0 +1,68 @@ +# Copyright © 2023 Vulcanize + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. + +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +from stack_orchestrator.deploy.deployment_context import DeploymentContext +from ruamel.yaml import YAML + + +def create(context: DeploymentContext, extra_args): + fixturenet_eth_compose_file = context.deployment_dir.joinpath('compose', 'docker-compose-fixturenet-eth.yml') + + with open(fixturenet_eth_compose_file, 'r') as yaml_file: + yaml = YAML() + yaml_data = yaml.load(yaml_file) + + new_script = '../config/fixturenet-optimism/run-geth.sh:/opt/testnet/run.sh' + if new_script not in yaml_data['services']['fixturenet-eth-geth-1']['volumes']: + yaml_data['services']['fixturenet-eth-geth-1']['volumes'].append(new_script) + + with open(fixturenet_eth_compose_file, 'w') as yaml_file: + yaml = YAML() + yaml.dump(yaml_data, yaml_file) + + # load fixturenet-optimism compose file + fixturenet_optimism_compose_file = context.deployment_dir.joinpath( + "compose", + "docker-compose-fixturenet-optimism.yml" + ) + + with open(fixturenet_optimism_compose_file, 'r') as yaml_file: + yaml = YAML() + yaml_data = yaml.load(yaml_file) + + # mount the funding script to volumes + fund_accounts_script = ( + '../config/watcher-mobymask-v3-demo/local/fund-accounts-on-l2.sh' + ':/app/packages/contracts-bedrock/fund-accounts-on-l2.sh' + ) + yaml_data['services']['fixturenet-optimism-contracts']['volumes'].append(fund_accounts_script) + + # update command to run the script + yaml_data['services']['fixturenet-optimism-contracts']['command'] = ( + '"./wait-for-it.sh -h ${CERC_L1_HOST:-$${DEFAULT_CERC_L1_HOST}}' + ' -p ${CERC_L1_PORT:-$${DEFAULT_CERC_L1_PORT}} -s -t 60' + ' -- ./deploy-contracts.sh && ./fund-accounts-on-l2.sh"' + ) + + # update port mapping for op-geth: 0.0.0.0:8545:8545 + existing_ports = yaml_data['services']['op-geth']['ports'] + new_ports = ["0.0.0.0:8545:8545" if "8545" in s else s for s in existing_ports] + yaml_data['services']['op-geth']['ports'] = new_ports + + with open(fixturenet_optimism_compose_file, 'w') as yaml_file: + yaml = YAML() + yaml.dump(yaml_data, yaml_file) + + return None diff --git a/stack_orchestrator/data/stacks/mobymask-v3-demo/stack.yml b/stack_orchestrator/data/stacks/mobymask-v3-demo/stack.yml new file mode 100644 index 00000000..68788478 --- /dev/null +++ b/stack_orchestrator/data/stacks/mobymask-v3-demo/stack.yml @@ -0,0 +1,47 @@ +version: "1.0" +description: "MobyMask v3 demo stack" +name: mobymask-v3-demo +repos: + # fixturenet repos + - git.vdb.to/cerc-io/go-ethereum@v1.11.6-statediff-v5 + - git.vdb.to/cerc-io/lighthouse + - github.com/dboreham/foundry + - github.com/ethereum-optimism/optimism@op-node/v1.3.0 + - github.com/ethereum-optimism/op-geth@v1.101304.0 + # nitro repo + - github.com/cerc-io/ts-nitro@v0.1.15 + # mobymask watcher repos + - github.com/cerc-io/mobymask-v2-watcher-ts@v0.2.4 + - github.com/cerc-io/MobyMask@v0.1.3 + # mobymask app repos + - github.com/cerc-io/mobymask-snap + - github.com/cerc-io/mobymask-ui@v0.2.2 +containers: + # fixturenet images + - cerc/go-ethereum + - cerc/lighthouse + - cerc/lighthouse-cli + - cerc/fixturenet-eth-genesis + - cerc/fixturenet-eth-geth + - cerc/fixturenet-eth-lighthouse + - cerc/foundry + - cerc/optimism-contracts + - cerc/optimism-op-node + - cerc/optimism-l2geth + - cerc/optimism-op-batcher + - cerc/optimism-op-proposer + # nitro contract deployment image + - cerc/nitro-contracts + # mobymask watcher images + - cerc/watcher-mobymask-v3 + - cerc/mobymask + # mobymask app images + - cerc/mobymask-snap + - cerc/mobymask-ui +pods: + - fixturenet-eth + - fixturenet-optimism + - nitro-contracts + - watcher-mobymask-v3-demo + - mobymask-snap + - mobymask-app-v3-demo diff --git a/stack_orchestrator/data/stacks/mobymask-v3/watcher.md b/stack_orchestrator/data/stacks/mobymask-v3/watcher.md index c21fbab3..9b417703 100644 --- a/stack_orchestrator/data/stacks/mobymask-v3/watcher.md +++ b/stack_orchestrator/data/stacks/mobymask-v3/watcher.md @@ -75,7 +75,7 @@ Create and update an env file to be used in the next step ([defaults](../../conf # Uses a generated peer id if not set (disables consensus) CERC_PEER_ID= - # Disable payments to upstream ETH server + # Enable payments to upstream ETH server CERC_ENABLE_UPSTREAM_PAYMENTS=false ``` diff --git a/stack_orchestrator/data/stacks/monitoring/monitoring-watchers.md b/stack_orchestrator/data/stacks/monitoring/monitoring-watchers.md index bce2d84b..9c2449fc 100644 --- a/stack_orchestrator/data/stacks/monitoring/monitoring-watchers.md +++ b/stack_orchestrator/data/stacks/monitoring/monitoring-watchers.md @@ -112,7 +112,7 @@ Place the pre-configured watcher alerts rules in Grafana provisioning directory: Update the alerting contact points config (`monitoring-watchers-deployment/config/monitoring/grafana/provisioning/alerting/contactpoints.yml`) with desired contact points -Add corresponding routes to the notification policies config (`monitoring-watchers-deployment/monitoring/grafana/provisioning/alerting/policies.yaml`) with appropriate object-matchers: +Add corresponding routes to the notification policies config (`monitoring-watchers-deployment/config/monitoring/grafana/provisioning/alerting/policies.yml`) with appropriate object-matchers: ```yml ...