diff --git a/infrastructure/nomad/playbooks/templates/jobs/contracts-deployer-pos.nomad.j2 b/infrastructure/nomad/playbooks/templates/jobs/contracts-deployer-pos.nomad.j2 new file mode 100644 index 000000000..a1e36d991 --- /dev/null +++ b/infrastructure/nomad/playbooks/templates/jobs/contracts-deployer-pos.nomad.j2 @@ -0,0 +1,272 @@ +#jinja2: trim_blocks:True, lstrip_blocks:True +job "{{ job.name }}" { + datacenters = ["{{ datacenter }}"] + + group "{{ job.name }}-group" { + count = {{ job.count }} + + # This is a special case for CI because the runner machine is not very + # powerful and compiling and deploying contracts can take a long time. + {% if env == 'devenv' and profile == 'ci' %} + update { + healthy_deadline = "20m" + progress_deadline = "30m" + } + {% else %} + update { + healthy_deadline = "10m" + progress_deadline = "15m" + } + {% endif %} + + {% if env == 'devenv' %} + restart { + attempts = 0 + mode = "fail" + } + + reschedule { + attempts = 0 + unlimited = false + } + {% endif %} + + network { + dns { + servers = {{ (ansible_facts['dns']['nameservers'] + ['1.1.1.1']) | tojson }} + } + + {% for port_name, port_details in job.ports[0].items() %} + port "{{ port_name }}" { + {% if port_details.get('static') %} + static = {{ port_details['static'] }} + {% endif %} + {% if port_details.get('to') %} + to = {{ port_details['to'] }} + {% endif %} + } + {% endfor %} + } + + task "contracts" { + driver = "exec" + + {% if profile == 'testnet' %} + resources { + cpu = 4000 + memory = 2048 + } + {% elif profile == 'stressnet' or profile == 'stressnet-wl1' %} + resources { + cpu = 2000 + memory = 1024 + } + {% endif %} + + {% for port_name in job.ports[0] %} + service { + name = "{{ job.name }}" + port = "{{ port_name }}" + tags = ["{{ port_name }}"] + provider = "nomad" + + check { + type = "http" + path = "/" + port = "{{ port_name }}" + interval = "10s" + timeout = "5s" + } + } + {% endfor %} + + artifact { + source = "https://nodejs.org/dist/v18.20.4/node-v18.20.4-linux-{{ 'x64' if target_system_architecture == 'x86_64' else 'arm64' }}.tar.xz" + options { + archive = false + } + } + + artifact { + source = "https://foundry.paradigm.xyz" + destination = "local/foundry.sh" + } + + {% if env != 'devenv' %} + artifact { + source = "https://primev-infrastructure-artifacts.s3.us-west-2.amazonaws.com/contracts_{{ version }}.tar.gz" + } + {% else %} + artifact { + source = "http://{{ ansible_facts['default_ipv4']['address'] }}:1111/contracts_{{ version }}.tar.gz" + } + {% endif %} + + template { + data = <<-EOH + L1_FINALIZATION_FEE="5000000000000000" + SETTLEMENT_FINALIZATION_FEE="1" + XDG_CONFIG_HOME="local/.config" + {% raw %} + KEYSTORE_DIR="/local/data-{{ env "NOMAD_ALLOC_INDEX" }}/keystore" + KEYSTORE_FILENAME="{{ with secret "secret/data/mev-commit" }}{{ .Data.data.{% endraw %}{{ job.artifacts | selectattr('keystores', 'defined') | map(attribute='keystores') | first | list | first }}{% raw %}_filename }}{{ end }}" + KEYSTORE_PASSWORD="{{ with secret "secret/data/mev-commit" }}{{ .Data.data.{% endraw %}{{ job.artifacts | selectattr('keystores', 'defined') | map(attribute='keystores') | first | list | first }}{% raw %}_password }}{{ end }}" + {% endraw %} + CHAIN_ID="{{ job.env['chain-id'] }}" + SCRIPT_PATH_PREFIX="local/contracts/scripts" + CONTRACT_REPO_ROOT_PATH="local/contracts" + EOH + destination = "secrets/.env" + env = true + } + + template { + data = <<-EOH + #!/usr/bin/env bash + + {%- raw %} + {{- range nomadService "datadog-agent-logs-collector" }} + {{ if contains "tcp" .Tags }} + exec > >(nc {{ .Address }} {{ .Port }}) 2>&1 + {{ end }} + {{- end }} + {% endraw %} + + {%- if job.artifacts | selectattr('keystores', 'defined') | list | length > 0 %} + mkdir -p "${KEYSTORE_DIR}" > /dev/null 2>&1 + {%- raw %} + {{- with secret "secret/data/mev-commit" }} + echo '{{ .Data.data.{% endraw %}{{ job.artifacts | selectattr('keystores', 'defined') | map(attribute='keystores') | first | list | first }}{% raw %} }}' > "${KEYSTORE_DIR}/${KEYSTORE_FILENAME}" + export SENDER=$(cat "${KEYSTORE_DIR}/${KEYSTORE_FILENAME}" | jq -r '.address') + {{ end }} + {% endraw %} + {% endif %} + + tar \ + --extract \ + --file local/node-v18.20.4-linux-{{ 'x64' if target_system_architecture == 'x86_64' else 'arm64' }}.tar.xz \ + --directory /usr/local \ + --strip-components=1 + + chmod +x local/foundry.sh && local/foundry.sh + chmod +x ${XDG_CONFIG_HOME}/.foundry/bin/foundryup && ${XDG_CONFIG_HOME}/.foundry/bin/foundryup -v nightly-e649e62f125244a3ef116be25dfdc81a2afbaf2a + export PATH="${XDG_CONFIG_HOME}/.foundry/bin:$PATH" + chmod +x ${CONTRACT_REPO_ROOT_PATH}/entrypoint.sh + echo "" + + {%- raw %} + {{- range nomadService "mev-commit-geth-pos-signer-node1" }} + {{- if contains "http" .Tags }} + export RPC_URL="http://{{ .Address }}:{{ .Port }}" + {{- end }} + {{- end }} + {% endraw %} + + start_time=$(date +%s) + export DEPLOY_TYPE="core" + echo "Deploying ${DEPLOY_TYPE} contracts..." + {% raw %} + {{ with secret "secret/data/mev-commit" }} + echo '{{ .Data.data.oracle_keystore }}' > local/oracle_keystore + {{ end }} + {% endraw %} + export ORACLE_KEYSTORE_ADDRESS=$(jq -r '.address' local/oracle_keystore) + LOGS="$(${CONTRACT_REPO_ROOT_PATH}/entrypoint.sh)" + if [ $? -ne 0 ]; then + echo "Failed to deploy contracts!" + echo "${LOGS}" + exit 1 + fi + end_time=$(date +%s) + echo "Contracts deployed successfully in: $(date -ud @$((end_time - start_time)) +'%H:%M:%S')." + echo "${LOGS}" \ + | sed -n '/{.*}/p' \ + | jq -c 'reduce .logs[] as $item ({}; . + {($item | split(": ")[0]): ($item | split(": ")[1])})' \ + | jq -c 'with_entries(select(.key | startswith("_") | not))' \ + > local/${DEPLOY_TYPE}_addresses.json + + forge clean --root "${CONTRACT_REPO_ROOT_PATH}" + + {%- if profile != 'stressnet-wl1' %} + + start_time=$(date +%s) + export DEPLOY_TYPE="settlement-gateway" + echo "Deploying ${DEPLOY_TYPE} contracts..." + {% raw %} + {{ with secret "secret/data/mev-commit" }} + echo '{{ .Data.data.bridge_relayer_keystore }}' > local/bridge_relayer_keystore + {{ end }} + {% endraw %} + export RELAYER_ADDRESS=$(jq -r '.address' local/bridge_relayer_keystore) + LOGS="$(${CONTRACT_REPO_ROOT_PATH}/entrypoint.sh)" + if [ $? -ne 0 ]; then + echo "Failed to deploy contracts!" + echo "${LOGS}" + exit 1 + fi + end_time=$(date +%s) + echo "Contracts deployed successfully in: $(date -ud @$((end_time - start_time)) +'%H:%M:%S')." + echo "${LOGS}" \ + | sed -n '/{.*}/p' \ + | jq -c 'reduce .logs[] as $item ({}; . + {($item | split(": ")[0]): ($item | split(": ")[1])})' \ + | jq -c 'with_entries(select(.key | startswith("_") | not))' \ + > local/${DEPLOY_TYPE}_addresses.json + + forge clean --root "${CONTRACT_REPO_ROOT_PATH}" + + {% if profile == 'testnet' %} + export RPC_URL="{{ job.env['l1_rpc_url'] }}" + export CHAIN_ID="17000" + {% endif %} + + {%- raw %} + {{- range nomadService "mock-l1" }} + {{- if contains "http" .Tags }} + export RPC_URL="http://{{ .Address }}:{{ .Port }}" + {{- end }} + {{- end }} + {% endraw %} + + start_time=$(date +%s) + export DEPLOY_TYPE="l1-gateway" + echo "Deploying ${DEPLOY_TYPE} contracts..." + {% raw %} + {{ with secret "secret/data/mev-commit" }} + echo '{{ .Data.data.bridge_relayer_keystore }}' > local/bridge_relayer_keystore + {{ end }} + {% endraw %} + export L1_OWNER_ADDRESS=${SENDER} #TODO: this should be a multisig address on mainnet. + LOGS="$(${CONTRACT_REPO_ROOT_PATH}/entrypoint.sh)" + if [ $? -ne 0 ]; then + echo "Failed to deploy contracts!" + echo "${LOGS}" + exit 1 + fi + end_time=$(date +%s) + echo "Contracts deployed successfully in: $(date -ud @$((end_time - start_time)) +'%H:%M:%S')." + echo "${LOGS}" \ + | sed -n '/{.*}/p' \ + | jq -c 'reduce .logs[] as $item ({}; . + {($item | split(": ")[0]): ($item | split(": ")[1])})' \ + | jq -c 'with_entries(select(.key | startswith("_") | not))' \ + > local/${DEPLOY_TYPE}_addresses.json + + {%- endif %} + + mkdir -p /local/www > /dev/null 2>&1 + jq -s 'add' local/*_addresses.json > local/www/contracts.json + + exec python3 -m http.server {{ job.ports[0]['http']['static'] }} --directory /local/www + # endtodo + EOH + destination = "local/run.sh" + change_mode = "noop" + perms = "0755" + } + + config { + command = "bash" + args = ["-c", "exec local/run.sh"] + } + } + } +} diff --git a/infrastructure/nomad/playbooks/templates/jobs/contracts-deployer.nomad.j2 b/infrastructure/nomad/playbooks/templates/jobs/contracts-deployer.nomad.j2 index e9298cd56..ce9d9c334 100644 --- a/infrastructure/nomad/playbooks/templates/jobs/contracts-deployer.nomad.j2 +++ b/infrastructure/nomad/playbooks/templates/jobs/contracts-deployer.nomad.j2 @@ -162,14 +162,6 @@ job "{{ job.name }}" { {{- end }} {% endraw %} - {%- raw %} - {{- range nomadService "mev-commit-geth-pos-signer-node1" }} - {{- if contains "http" .Tags }} - export RPC_URL="http://{{ .Address }}:{{ .Port }}" - {{- end }} - {{- end }} - {% endraw %} - start_time=$(date +%s) export DEPLOY_TYPE="core" echo "Deploying ${DEPLOY_TYPE} contracts..." diff --git a/infrastructure/nomad/playbooks/variables/profiles.yml b/infrastructure/nomad/playbooks/variables/profiles.yml index e1a7d76f5..de1f0a46a 100644 --- a/infrastructure/nomad/playbooks/variables/profiles.yml +++ b/infrastructure/nomad/playbooks/variables/profiles.yml @@ -240,6 +240,24 @@ jobs: chain-id: "{{ environments[env].chain_id }}" l1_rpc_url: "{{ resolved_l1_rpc_urls.split(',')[0] }}" + contracts_deployer: &contracts_deployer_pos_job + name: contracts-deployer-pos + template: contracts-deployer-pos.nomad.j2 + artifacts: + - *contracts_artifact + - keystores: + contract_deployer_keystore: + allocation: true + bridge_relayer_keystore: + count: 1 + ports: + - http: + static: 1010 + to: 8080 + env: + chain-id: "{{ environments[env].chain_id }}" + l1_rpc_url: "{{ resolved_l1_rpc_urls.split(',')[0] }}" + mev_commit_dashboard: &mev_commit_dashboard_job name: mev-commit-dashboard template: mev-commit-dashboard.nomad.j2 @@ -802,7 +820,7 @@ profiles: - *mock_l1_job - *l1_transactor_job - *relay_emulator_job - - *contracts_deployer_job + - *contracts_deployer_pos_job - *mev_commit_bridge_job - *bridge_emulator_job - *mev_commit_dashboard_job