diff --git a/spartan/aztec-network/files/config/deploy-l1-contracts.sh b/spartan/aztec-network/files/config/deploy-l1-contracts.sh index 3ff6801d009..bf99ebff494 100755 --- a/spartan/aztec-network/files/config/deploy-l1-contracts.sh +++ b/spartan/aztec-network/files/config/deploy-l1-contracts.sh @@ -16,6 +16,17 @@ SALT=${1:-$RANDOM} CHAIN_ID=$2 VALIDATOR_ADDRESSES=$3 +# If the chain ID is 11155111 or 1, we are deploying to a public network, make sure that we do not use accelerated test deployments +PUBLIC_CHAIN_ID=false +if [ "$CHAIN_ID" = "11155111" -o "$CHAIN_ID" = "1" ]; then + PUBLIC_CHAIN_ID=true +fi + +# Overwrite the value of ACCELERATED_TEST_DEPLOYMENTS env variable if we are deploying to a public network +if [ "$PUBLIC_CHAIN_ID" = "true" ]; then + ACCELERATED_TEST_DEPLOYMENTS=false +fi + # Run the deploy-l1-contracts command and capture the output output="" MAX_RETRIES=5 @@ -26,9 +37,14 @@ if [ "$TEST_ACCOUNTS" = "true" ]; then TEST_ACCOUNTS_ARG="--test-accounts" fi +ACCELERATED_TEST_DEPLOYMENTS_ARG="" +if [ "$ACCELERATED_TEST_DEPLOYMENTS" = "true" ]; then + ACCELERATED_TEST_DEPLOYMENTS_ARG="--accelerated-test-deployments" +fi + for attempt in $(seq 1 $MAX_RETRIES); do # Construct base command - base_cmd="LOG_LEVEL=debug node --no-warnings /usr/src/yarn-project/aztec/dest/bin/index.js deploy-l1-contracts $TEST_ACCOUNTS_ARG" + base_cmd="LOG_LEVEL=debug node --no-warnings /usr/src/yarn-project/aztec/dest/bin/index.js deploy-l1-contracts $TEST_ACCOUNTS_ARG $ACCELERATED_TEST_DEPLOYMENTS_ARG" # Add account - use private key if set, otherwise use mnemonic if [ -n "${L1_DEPLOYMENT_PRIVATE_KEY:-}" ]; then @@ -39,11 +55,11 @@ for attempt in $(seq 1 $MAX_RETRIES); do # Add validators if INIT_VALIDATORS is true if [ "${INIT_VALIDATORS:-false}" = "true" ]; then - output=$(eval $base_cmd --validators $VALIDATOR_ADDRESSES --l1-chain-id $CHAIN_ID --salt $SALT) && break - else - output=$(eval $base_cmd --l1-chain-id $CHAIN_ID --salt $SALT) && break + base_cmd="$base_cmd --validators $VALIDATOR_ADDRESSES" fi + output=$(eval $base_cmd --l1-chain-id $CHAIN_ID --salt $SALT) && break + echo "Attempt $attempt failed. Retrying in $RETRY_DELAY seconds..." sleep "$RETRY_DELAY" done || { diff --git a/spartan/aztec-network/files/config/setup-p2p-addresses.sh b/spartan/aztec-network/files/config/setup-p2p-addresses.sh index f4b2afce6f2..9a50a091304 100644 --- a/spartan/aztec-network/files/config/setup-p2p-addresses.sh +++ b/spartan/aztec-network/files/config/setup-p2p-addresses.sh @@ -30,10 +30,10 @@ else fi # Write addresses to file for sourcing -echo "export P2P_TCP_ANNOUNCE_ADDR=${TCP_ADDR}" > /shared/p2p/p2p-addresses -echo "export P2P_TCP_LISTEN_ADDR=0.0.0.0:${P2P_TCP_PORT}" >> /shared/p2p/p2p-addresses -echo "export P2P_UDP_ANNOUNCE_ADDR=${UDP_ADDR}" >> /shared/p2p/p2p-addresses -echo "export P2P_UDP_LISTEN_ADDR=0.0.0.0:${P2P_UDP_PORT}" >> /shared/p2p/p2p-addresses +echo "export P2P_TCP_ANNOUNCE_ADDR=${TCP_ADDR}" > /shared/config/p2p-addresses +echo "export P2P_TCP_LISTEN_ADDR=0.0.0.0:${P2P_TCP_PORT}" >> /shared/config/p2p-addresses +echo "export P2P_UDP_ANNOUNCE_ADDR=${UDP_ADDR}" >> /shared/config/p2p-addresses +echo "export P2P_UDP_LISTEN_ADDR=0.0.0.0:${P2P_UDP_PORT}" >> /shared/config/p2p-addresses echo "P2P addresses configured:" -cat /shared/p2p/p2p-addresses \ No newline at end of file +cat /shared/config/p2p-addresses diff --git a/spartan/aztec-network/templates/_helpers.tpl b/spartan/aztec-network/templates/_helpers.tpl index 70d9da62638..3a0fb55da3c 100644 --- a/spartan/aztec-network/templates/_helpers.tpl +++ b/spartan/aztec-network/templates/_helpers.tpl @@ -65,7 +65,7 @@ http://{{ include "aztec-network.fullname" . }}-pxe.{{ .Release.Namespace }}:{{ {{- end -}} {{- define "aztec-network.bootNodeUrl" -}} -http://{{ include "aztec-network.fullname" . }}-boot-node-0.{{ include "aztec-network.fullname" . }}-boot-node.{{ .Release.Namespace }}.svc.cluster.local:{{ .Values.bootNode.service.nodePort }} +http://{{ include "aztec-network.fullname" . }}-boot-node.{{ .Release.Namespace }}.svc.cluster.local:{{ .Values.bootNode.service.nodePort }} {{- end -}} {{- define "aztec-network.validatorUrl" -}} @@ -94,34 +94,6 @@ http://{{ include "aztec-network.fullname" . }}-metrics.{{ .Release.Namespace }} {{- end -}} {{- end -}} -{{/* -P2P Setup Container -*/}} -{{- define "aztec-network.p2pSetupContainer" -}} -- name: setup-p2p-addresses - image: bitnami/kubectl - command: - - /bin/sh - - -c - - | - cp /scripts/setup-p2p-addresses.sh /tmp/setup-p2p-addresses.sh && \ - chmod +x /tmp/setup-p2p-addresses.sh && \ - /tmp/setup-p2p-addresses.sh - env: - - name: NETWORK_PUBLIC - value: "{{ .Values.network.public }}" - - name: NAMESPACE - value: {{ .Release.Namespace }} - - name: P2P_TCP_PORT - value: "{{ .Values.validator.service.p2pTcpPort }}" - - name: P2P_UDP_PORT - value: "{{ .Values.validator.service.p2pUdpPort }}" - volumeMounts: - - name: scripts - mountPath: /scripts - - name: p2p-addresses - mountPath: /shared/p2p -{{- end -}} {{/* Service Address Setup Container @@ -133,9 +105,7 @@ Service Address Setup Container - /bin/bash - -c - | - cp /scripts/setup-service-addresses.sh /tmp/setup-service-addresses.sh && \ - chmod +x /tmp/setup-service-addresses.sh && \ - /tmp/setup-service-addresses.sh + /scripts/setup-service-addresses.sh env: - name: NETWORK_PUBLIC value: "{{ .Values.network.public }}" @@ -189,9 +159,7 @@ Sets up the OpenTelemetry resource attributes for a service - /bin/bash - -c - | - cp /scripts/setup-otel-resource.sh /tmp/setup-otel-resource.sh && \ - chmod +x /tmp/setup-otel-resource.sh && \ - /tmp/setup-otel-resource.sh + /scripts/setup-otel-resource.sh env: - name: POD_IP valueFrom: @@ -263,3 +231,142 @@ while true; do sleep 5 done {{- end -}} + +{{/* +Combined wait-for-services and configure-env container for full nodes +*/}} +{{- define "aztec-network.combinedWaitAndConfigureContainer" -}} +- name: wait-and-configure + {{- include "aztec-network.image" . | nindent 2 }} + command: + - /bin/bash + - -c + - | + # If we already have a registry address, and the bootstrap nodes are set, then we don't need to wait for the services + if [ -n "{{ .Values.aztec.contracts.registryAddress }}" ] && [ -n "{{ .Values.aztec.bootstrapENRs }}" ]; then + echo "Registry address and bootstrap nodes already set, skipping wait for services" + echo "{{ include "aztec-network.pxeUrl" . }}" > /shared/pxe/pxe_url + else + source /shared/config/service-addresses + cat /shared/config/service-addresses + {{- include "aztec-network.waitForEthereum" . | nindent 8 }} + + if [ "{{ .Values.validator.dynamicBootNode }}" = "true" ]; then + echo "{{ include "aztec-network.pxeUrl" . }}" > /shared/pxe/pxe_url + else + until curl --silent --head --fail "${BOOT_NODE_HOST}/status" > /dev/null; do + echo "Waiting for boot node..." + sleep 5 + done + echo "Boot node is ready!" + echo "${BOOT_NODE_HOST}" > /shared/pxe/pxe_url + fi + fi + + # Configure environment + source /shared/config/service-addresses + /scripts/configure-full-node-env.sh "$(cat /shared/pxe/pxe_url)" + volumeMounts: + - name: pxe-url + mountPath: /shared/pxe + - name: scripts + mountPath: /scripts + - name: config + mountPath: /shared/config + - name: contracts-env + mountPath: /shared/contracts + env: + - name: P2P_ENABLED + value: "{{ .Values.fullNode.p2p.enabled }}" + - name: BOOTSTRAP_NODES + value: "{{ .Values.aztec.bootstrapENRs }}" + - name: REGISTRY_CONTRACT_ADDRESS + value: "{{ .Values.aztec.contracts.registryAddress }}" + - name: SLASH_FACTORY_CONTRACT_ADDRESS + value: "{{ .Values.aztec.contracts.slashFactoryAddress }}" +{{- end -}} + +{{/* +Combined P2P, Service Address, and OpenTelemetry Setup Container +*/}} +{{- define "aztec-network.combinedAllSetupContainer" -}} +{{- $serviceName := base $.Template.Name | trimSuffix ".yaml" -}} +- name: setup-all + {{- include "aztec-network.image" . | nindent 2 }} + command: + - /bin/bash + - -c + - | + # Setup P2P addresses + /scripts/setup-p2p-addresses.sh + + # Setup service addresses + /scripts/setup-service-addresses.sh + + # Setup OpenTelemetry resource + /scripts/setup-otel-resource.sh + env: + - name: NETWORK_PUBLIC + value: "{{ .Values.network.public }}" + - name: NAMESPACE + value: {{ .Release.Namespace }} + - name: P2P_TCP_PORT + value: "{{ .Values.validator.service.p2pTcpPort }}" + - name: P2P_UDP_PORT + value: "{{ .Values.validator.service.p2pUdpPort }}" + - name: TELEMETRY + value: "{{ .Values.telemetry.enabled }}" + - name: OTEL_COLLECTOR_ENDPOINT + value: "{{ .Values.telemetry.otelCollectorEndpoint }}" + - name: EXTERNAL_ETHEREUM_HOSTS + value: "{{ .Values.ethereum.execution.externalHosts }}" + - name: ETHEREUM_PORT + value: "{{ .Values.ethereum.execution.service.port }}" + - name: EXTERNAL_ETHEREUM_CONSENSUS_HOST + value: "{{ .Values.ethereum.beacon.externalHost }}" + - name: EXTERNAL_ETHEREUM_CONSENSUS_HOST_API_KEY + value: "{{ .Values.ethereum.beacon.apiKey }}" + - name: EXTERNAL_ETHEREUM_CONSENSUS_HOST_API_KEY_HEADER + value: "{{ .Values.ethereum.beacon.apiKeyHeader }}" + - name: ETHEREUM_CONSENSUS_PORT + value: "{{ .Values.ethereum.beacon.service.port }}" + - name: EXTERNAL_BOOT_NODE_HOST + value: "{{ .Values.bootNode.externalHost }}" + - name: BOOT_NODE_PORT + value: "{{ .Values.bootNode.service.nodePort }}" + - name: EXTERNAL_PROVER_NODE_HOST + value: "{{ .Values.proverNode.externalHost }}" + - name: PROVER_NODE_PORT + value: "{{ .Values.proverNode.service.nodePort }}" + - name: PROVER_BROKER_PORT + value: "{{ .Values.proverBroker.service.nodePort }}" + - name: USE_GCLOUD_LOGGING + value: "{{ .Values.telemetry.useGcloudLogging }}" + - name: SERVICE_NAME + value: {{ include "aztec-network.fullname" . }} + - name: POD_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + - name: K8S_POD_UID + valueFrom: + fieldRef: + fieldPath: metadata.uid + - name: K8S_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: K8S_NAMESPACE_NAME + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: OTEL_SERVICE_NAME + value: "{{ $serviceName }}" + - name: OTEL_RESOURCE_ATTRIBUTES + value: 'service.namespace={{ .Release.Namespace }},environment={{ .Values.environment | default "production" }}' + volumeMounts: + - name: scripts + mountPath: /scripts + - name: config + mountPath: /shared/config +{{- end -}} diff --git a/spartan/aztec-network/templates/boot-node.yaml b/spartan/aztec-network/templates/boot-node.yaml index 2823afaf72b..b0897148e2c 100644 --- a/spartan/aztec-network/templates/boot-node.yaml +++ b/spartan/aztec-network/templates/boot-node.yaml @@ -39,10 +39,9 @@ spec: serviceAccountName: {{ include "aztec-network.fullname" . }}-node {{- include "aztec-network.publicAntiAffinity" . | nindent 6 }} {{- end }} + terminationGracePeriodSeconds: 5 # default is 30 - speed up initcontainer termination initContainers: - {{- include "aztec-network.p2pSetupContainer" . | nindent 8 }} - {{- include "aztec-network.serviceAddressSetupContainer" . | nindent 8 }} - {{- include "aztec-network.otelResourceSetupContainer" . | nindent 8 }} + {{- include "aztec-network.combinedAllSetupContainer" . | nindent 8 }} # Generate the validator addresses; used in the deploy-l1-contracts step - name: generate-validator-addresses @@ -66,32 +65,18 @@ spec: - name: NUMBER_OF_VALIDATORS value: {{ .Values.validator.replicas | quote }} - - name: wait-for-ethereum - {{- include "aztec-network.image" . | nindent 10 }} - command: - - /bin/bash - - -c - - | - source /shared/config/service-addresses - cat /shared/config/service-addresses - {{- include "aztec-network.waitForEthereum" . | nindent 14 }} - volumeMounts: - - name: config - mountPath: /shared/config - name: deploy-l1-contracts {{- include "aztec-network.image" . | nindent 10 }} command: - /bin/bash - -c - | - cp /scripts/deploy-l1-contracts.sh /tmp/deploy-l1-contracts.sh - chmod +x /tmp/deploy-l1-contracts.sh source /shared/config/service-addresses source /shared/config/validator-addresses {{- include "aztec-network.waitForEthereum" . | nindent 14 }} - /tmp/deploy-l1-contracts.sh "{{ .Values.aztec.l1Salt }}" "{{ .Values.ethereum.chainId }}" "$VALIDATOR_ADDRESSES" + /scripts/deploy-l1-contracts.sh "{{ .Values.aztec.l1Salt }}" "{{ .Values.ethereum.chainId }}" "$VALIDATOR_ADDRESSES" volumeMounts: - name: scripts-output mountPath: /shared/contracts @@ -100,6 +85,8 @@ spec: - name: scripts mountPath: /scripts env: + - name: ACCELERATED_TEST_DEPLOYMENTS + value: "{{ .Values.ethereum.acceleratedTestDeployments }}" - name: TEST_ACCOUNTS value: "{{ .Values.aztec.testAccounts }}" - name: REGISTRY_CONTRACT_ADDRESS @@ -145,9 +132,8 @@ spec: - /bin/bash - -c - | - sleep 30 && \ source /shared/contracts/contracts.env && \ - source /shared/p2p/p2p-addresses && \ + source /shared/config/p2p-addresses && \ source /shared/config/service-addresses && \ source /shared/config/otel-resource && \ env && \ @@ -167,8 +153,6 @@ spec: timeoutSeconds: 30 failureThreshold: 3 volumeMounts: - - name: p2p-addresses - mountPath: /shared/p2p - name: config mountPath: /shared/config - name: boot-node-data @@ -256,8 +240,6 @@ spec: resources: {{- toYaml .Values.bootNode.resources | nindent 12 }} volumes: - - name: p2p-addresses - emptyDir: {} - name: config emptyDir: {} {{- if .Values.storage.localSsd }} @@ -271,6 +253,7 @@ spec: - name: scripts configMap: name: {{ include "aztec-network.fullname" . }}-scripts + defaultMode: 0755 - name: scripts-output emptyDir: {} --- @@ -300,7 +283,7 @@ spec: # External load balancers cannot handle mixed TCP/UDP ports, so we only expose the node port {{- if not .Values.network.public }} - port: {{ .Values.bootNode.service.p2pTcpPort }} - name: p2p-tpc + name: p2p-tcp - port: {{ .Values.bootNode.service.p2pUdpPort }} name: p2p-udp protocol: UDP diff --git a/spartan/aztec-network/templates/consolidate-balances.yaml b/spartan/aztec-network/templates/consolidate-balances.yaml index 8a925ab3421..68a34886e31 100644 --- a/spartan/aztec-network/templates/consolidate-balances.yaml +++ b/spartan/aztec-network/templates/consolidate-balances.yaml @@ -26,6 +26,7 @@ spec: - name: scripts configMap: name: {{ include "aztec-network.fullname" . }}-scripts + defaultMode: 0755 containers: - name: consolidate-balances {{- include "aztec-network.image" . | nindent 10 }} @@ -38,9 +39,7 @@ spec: - /bin/bash - -c - | - cp /scripts/consolidate-sepolia-balances.sh /tmp/consolidate-sepolia-balances.sh - chmod +x /tmp/consolidate-sepolia-balances.sh - /tmp/consolidate-sepolia-balances.sh "{{ .Values.aztec.l1DeploymentMnemonic }}" {{ add .Values.validator.replicas .Values.proverNode.replicas }} + /scripts/consolidate-sepolia-balances.sh "{{ .Values.aztec.l1DeploymentMnemonic }}" {{ add .Values.validator.replicas .Values.proverNode.replicas }} env: - name: ETHEREUM_HOSTS value: "{{ .Values.ethereum.execution.externalHosts }}" diff --git a/spartan/aztec-network/templates/deploy-l1-verifier.yaml b/spartan/aztec-network/templates/deploy-l1-verifier.yaml index 7cbe04bf828..d83633e9705 100644 --- a/spartan/aztec-network/templates/deploy-l1-verifier.yaml +++ b/spartan/aztec-network/templates/deploy-l1-verifier.yaml @@ -27,6 +27,7 @@ spec: - name: scripts configMap: name: {{ include "aztec-network.fullname" . }}-scripts + defaultMode: 0755 containers: - name: deploy-l1-verifier {{- include "aztec-network.image" . | nindent 10 }} @@ -47,9 +48,7 @@ spec: kubectl config set-context default --cluster=default --user=default kubectl config use-context default - cp /scripts/setup-service-addresses.sh /tmp/setup-service-addresses.sh - chmod +x /tmp/setup-service-addresses.sh - /tmp/setup-service-addresses.sh + /scripts/setup-service-addresses.sh source /shared/config/service-addresses cat /shared/config/service-addresses diff --git a/spartan/aztec-network/templates/faucet.yaml b/spartan/aztec-network/templates/faucet.yaml index c455ec213c7..6215b8ef02e 100644 --- a/spartan/aztec-network/templates/faucet.yaml +++ b/spartan/aztec-network/templates/faucet.yaml @@ -32,8 +32,10 @@ spec: - name: scripts configMap: name: {{ include "aztec-network.fullname" . }}-scripts + defaultMode: 0755 - name: scripts-output emptyDir: {} + terminationGracePeriodSeconds: 5 # default is 30 - speed up initcontainer termination initContainers: {{- include "aztec-network.serviceAddressSetupContainer" . | nindent 8 }} - name: wait-for-dependencies diff --git a/spartan/aztec-network/templates/full-node.yaml b/spartan/aztec-network/templates/full-node.yaml index 7e1683c0b86..d983766777b 100644 --- a/spartan/aztec-network/templates/full-node.yaml +++ b/spartan/aztec-network/templates/full-node.yaml @@ -40,86 +40,9 @@ spec: {{- include "aztec-network.publicAntiAffinity" . | nindent 6 }} {{- end }} initContainers: - {{- include "aztec-network.p2pSetupContainer" . | nindent 8 }} - {{- include "aztec-network.serviceAddressSetupContainer" . | nindent 8 }} + {{- include "aztec-network.combinedAllSetupContainer" . | nindent 8 }} + {{- include "aztec-network.combinedWaitAndConfigureContainer" . | nindent 8 }} - - - name: wait-for-services - {{- include "aztec-network.image" . | nindent 10 }} - command: - - /bin/bash - - -c - - | - # If we already have a registry address, and the bootstrap nodes are set, then we don't need to wait for the services - if [ -n "{{ .Values.aztec.contracts.registryAddress }}" ] && [ -n "{{ .Values.aztec.bootstrapENRs }}" ]; then - echo "Registry address and bootstrap nodes already set, skipping wait for services" - exit 0 - fi - - source /shared/config/service-addresses - cat /shared/config/service-addresses - {{- include "aztec-network.waitForEthereum" . | nindent 14 }} - - - if [ "{{ .Values.validator.dynamicBootNode }}" = "true" ]; then - echo "{{ include "aztec-network.pxeUrl" . }}" > /shared/pxe/pxe_url - else - until curl --silent --head --fail "${BOOT_NODE_HOST}/status" > /dev/null; do - echo "Waiting for boot node..." - sleep 5 - done - echo "Boot node is ready!" - echo "${BOOT_NODE_HOST}" > /shared/pxe/pxe_url - fi - volumeMounts: - - name: pxe-url - mountPath: /shared/pxe - - name: scripts - mountPath: /scripts - - name: config - mountPath: /shared/config - - - name: configure-full-node-env - {{- include "aztec-network.image" . | nindent 10 }} - command: - - "/bin/bash" - - "-c" - - | - source /shared/config/service-addresses && \ - cp /scripts/configure-full-node-env.sh /tmp/configure-full-node-env.sh && \ - chmod +x /tmp/configure-full-node-env.sh && \ - /tmp/configure-full-node-env.sh "$(cat /shared/pxe/pxe_url)" - volumeMounts: - - name: contracts-env - mountPath: /shared/contracts - - name: pxe-url - mountPath: /shared/pxe - - name: scripts - mountPath: /scripts - - name: config - mountPath: /shared/config - env: - - name: P2P_ENABLED - value: "{{ .Values.fullNode.p2p.enabled }}" - - name: BOOTSTRAP_NODES - value: "{{ .Values.aztec.bootstrapENRs }}" - - name: REGISTRY_CONTRACT_ADDRESS - value: "{{ .Values.aztec.contracts.registryAddress }}" - - name: SLASH_FACTORY_CONTRACT_ADDRESS - value: "{{ .Values.aztec.contracts.slashFactoryAddress }}" - - - name: wait-for-ethereum - {{- include "aztec-network.image" . | nindent 10 }} - command: - - /bin/bash - - -c - - | - source /shared/config/service-addresses - cat /shared/config/service-addresses - {{- include "aztec-network.waitForEthereum" . | nindent 14 }} - volumeMounts: - - name: config - mountPath: /shared/config containers: - name: full-node {{- include "aztec-network.image" . | nindent 10 }} @@ -127,11 +50,11 @@ spec: - /bin/bash - -c - | - sleep 30 && \ - source /shared/contracts/contracts.env && \ - source /shared/p2p/p2p-addresses && \ - source /shared/config/service-addresses && \ - env && \ + source /shared/contracts/contracts.env + source /shared/config/p2p-addresses + source /shared/config/service-addresses + env + node --no-warnings /usr/src/yarn-project/aztec/dest/bin/index.js start --node --archiver --pxe startupProbe: httpGet: @@ -148,8 +71,6 @@ spec: timeoutSeconds: 30 failureThreshold: 3 volumeMounts: - - name: p2p-addresses - mountPath: /shared/p2p - name: config mountPath: /shared/config - name: full-node-data @@ -244,8 +165,6 @@ spec: resources: {{- toYaml .Values.fullNode.resources | nindent 12 }} volumes: - - name: p2p-addresses - emptyDir: {} - name: config emptyDir: {} {{- if .Values.storage.localSsd }} @@ -259,6 +178,7 @@ spec: - name: scripts configMap: name: {{ include "aztec-network.fullname" . }}-scripts + defaultMode: 0755 - name: scripts-output emptyDir: {} - name: contracts-env diff --git a/spartan/aztec-network/templates/prover-agent.yaml b/spartan/aztec-network/templates/prover-agent.yaml index 751689482ba..51b76161119 100644 --- a/spartan/aztec-network/templates/prover-agent.yaml +++ b/spartan/aztec-network/templates/prover-agent.yaml @@ -43,9 +43,9 @@ spec: - name: scripts configMap: name: {{ include "aztec-network.fullname" . }}-scripts + defaultMode: 0755 initContainers: - {{- include "aztec-network.serviceAddressSetupContainer" . | nindent 8 }} - {{- include "aztec-network.otelResourceSetupContainer" . | nindent 8 }} + {{- include "aztec-network.combinedAllSetupContainer" . | nindent 8 }} - name: wait-for-prover-node {{- include "aztec-network.image" . | nindent 10 }} command: diff --git a/spartan/aztec-network/templates/prover-broker.yaml b/spartan/aztec-network/templates/prover-broker.yaml index 8736fd5b827..5eeff959ddd 100644 --- a/spartan/aztec-network/templates/prover-broker.yaml +++ b/spartan/aztec-network/templates/prover-broker.yaml @@ -46,9 +46,10 @@ spec: - name: scripts configMap: name: {{ include "aztec-network.fullname" . }}-scripts + defaultMode: 0755 initContainers: - {{- include "aztec-network.serviceAddressSetupContainer" . | nindent 8 }} - {{- include "aztec-network.otelResourceSetupContainer" . | nindent 8 }} + {{- include "aztec-network.combinedAllSetupContainer" . | nindent 8 }} + - name: wait-for-dependencies {{- include "aztec-network.image" . | nindent 10 }} command: @@ -81,10 +82,9 @@ spec: command: - "/bin/bash" - "-c" - - "cp /scripts/configure-prover-env.sh /tmp/configure-prover-env.sh && \ - chmod +x /tmp/configure-prover-env.sh && \ - source /shared/config/service-addresses && \ - /tmp/configure-prover-env.sh ${BOOT_NODE_HOST}" + - | + source /shared/config/service-addresses + /scripts/configure-prover-env.sh ${BOOT_NODE_HOST} volumeMounts: - name: contracts-env mountPath: /shared/contracts @@ -162,6 +162,7 @@ spec: - name: scripts configMap: name: {{ include "aztec-network.fullname" . }}-scripts + defaultMode: 0755 - name: config emptyDir: {} - name: contracts-env diff --git a/spartan/aztec-network/templates/prover-node.yaml b/spartan/aztec-network/templates/prover-node.yaml index f906e415c6c..efeeb50ccad 100644 --- a/spartan/aztec-network/templates/prover-node.yaml +++ b/spartan/aztec-network/templates/prover-node.yaml @@ -38,10 +38,9 @@ spec: dnsPolicy: ClusterFirstWithHostNet {{- include "aztec-network.publicAntiAffinity" . | nindent 6 }} {{- end }} + terminationGracePeriodSeconds: 5 # default is 30 - speed up initcontainer termination initContainers: - {{- include "aztec-network.serviceAddressSetupContainer" . | nindent 8 }} - {{- include "aztec-network.p2pSetupContainer" . | nindent 8 }} - {{- include "aztec-network.otelResourceSetupContainer" . | nindent 8 }} + {{- include "aztec-network.combinedAllSetupContainer" . | nindent 8 }} - name: get-private-key image: {{ .Values.images.foundry.image }} @@ -111,10 +110,8 @@ spec: command: - "/bin/bash" - "-c" - - "cp /scripts/configure-prover-env.sh /tmp/configure-prover-env.sh && \ - chmod +x /tmp/configure-prover-env.sh && \ - source /shared/config/service-addresses && \ - /tmp/configure-prover-env.sh ${BOOT_NODE_HOST}" + - "source /shared/config/service-addresses && \ + /scripts/configure-prover-env.sh ${BOOT_NODE_HOST}" volumeMounts: - name: contracts-env mountPath: /shared/contracts @@ -134,12 +131,12 @@ spec: - name: prover-node {{- include "aztec-network.image" . | nindent 10 }} command: - - "/bin/bash" - - "-c" + - /bin/bash + - -c - | source /shared/config/keys.env && \ source /shared/contracts/contracts.env && \ - source /shared/p2p/p2p-addresses && \ + source /shared/config/p2p-addresses && \ source /shared/config/service-addresses && \ source /shared/config/otel-resource && \ env && \ @@ -147,8 +144,6 @@ spec: volumeMounts: - name: contracts-env mountPath: /shared/contracts - - name: p2p-addresses - mountPath: /shared/p2p - name: config mountPath: /shared/config - name: prover-node-data @@ -257,10 +252,9 @@ spec: - name: scripts configMap: name: {{ include "aztec-network.fullname" . }}-scripts + defaultMode: 0755 - name: contracts-env emptyDir: {} - - name: p2p-addresses - emptyDir: {} - name: config emptyDir: {} {{- if .Values.storage.localSsd }} diff --git a/spartan/aztec-network/templates/pxe.yaml b/spartan/aztec-network/templates/pxe.yaml index 170ea13980f..d611ffc86a7 100644 --- a/spartan/aztec-network/templates/pxe.yaml +++ b/spartan/aztec-network/templates/pxe.yaml @@ -35,11 +35,14 @@ spec: - name: scripts configMap: name: {{ include "aztec-network.fullname" . }}-scripts + defaultMode: 0755 - name: scripts-output emptyDir: {} + terminationGracePeriodSeconds: 5 # default is 30 - speed up initcontainer termination initContainers: {{- include "aztec-network.serviceAddressSetupContainer" . | nindent 8 }} - - name: wait-for-boot-node + + - name: wait-for-host image: {{ .Values.images.curl.image }} command: - /bin/sh @@ -47,26 +50,23 @@ spec: - | source /shared/config/service-addresses cat /shared/config/service-addresses - until curl --head --silent ${BOOT_NODE_HOST}/status; do + + {{- if .Values.network.public }} + # If the network is public, we need to use the boot node URL + export AZTEC_NODE_URL=${BOOT_NODE_HOST} + {{- else }} + # If the network is not public, we can use the validator URL + export AZTEC_NODE_URL={{ include "aztec-network.validatorUrl" . }} + {{- end }} + + until curl --head --silent ${AZTEC_NODE_URL}/status; do echo "Waiting for boot node..." sleep 5 done volumeMounts: - name: config mountPath: /shared/config - {{- if not .Values.network.public }} - # We only need to wait for the validator service if the network is not public - - name: wait-for-validator-service - image: {{ .Values.images.curl.image }} - command: - - /bin/sh - - -c - - | - until curl --head --silent {{ include "aztec-network.validatorUrl" . }}/status; do - echo "Waiting for validator service..." - sleep 5 - done - {{- end }} + containers: - name: pxe {{- include "aztec-network.image" . | nindent 10 }} diff --git a/spartan/aztec-network/templates/transaction-bot.yaml b/spartan/aztec-network/templates/transaction-bot.yaml index f162040ae58..0f0217ca7ec 100644 --- a/spartan/aztec-network/templates/transaction-bot.yaml +++ b/spartan/aztec-network/templates/transaction-bot.yaml @@ -44,11 +44,13 @@ spec: - name: scripts configMap: name: {{ include "aztec-network.fullname" . }}-scripts + defaultMode: 0755 - name: scripts-output emptyDir: {} + terminationGracePeriodSeconds: 5 # default is 30 - speed up initcontainer termination initContainers: - {{- include "aztec-network.serviceAddressSetupContainer" . | nindent 8 }} - {{- include "aztec-network.otelResourceSetupContainer" . | nindent 8 }} + {{- include "aztec-network.combinedAllSetupContainer" . | nindent 8 }} + - name: get-private-key image: {{ .Values.images.foundry.image }} imagePullPolicy: {{ .Values.images.foundry.pullPolicy }} diff --git a/spartan/aztec-network/templates/validator.yaml b/spartan/aztec-network/templates/validator.yaml index 0c7f82d5d23..e6f7edc209f 100644 --- a/spartan/aztec-network/templates/validator.yaml +++ b/spartan/aztec-network/templates/validator.yaml @@ -40,10 +40,9 @@ spec: dnsPolicy: ClusterFirstWithHostNet {{- include "aztec-network.publicAntiAffinity" . | nindent 6 }} {{- end }} + terminationGracePeriodSeconds: 5 # default is 30 - speed up initcontainer termination initContainers: - {{- include "aztec-network.p2pSetupContainer" . | nindent 8 }} - {{- include "aztec-network.serviceAddressSetupContainer" . | nindent 8 }} - {{- include "aztec-network.otelResourceSetupContainer" . | nindent 8 }} + {{- include "aztec-network.combinedAllSetupContainer" . | nindent 8 }} # Get the private key from the mnemonic - based on the pod replica index - name: get-private-key @@ -69,71 +68,8 @@ spec: fieldRef: fieldPath: metadata.name + {{- include "aztec-network.combinedWaitAndConfigureContainer" . | nindent 8 }} - - name: wait-for-services - {{- include "aztec-network.image" . | nindent 10 }} - command: - - /bin/bash - - -c - - | - # If we already have a registry address, and the bootstrap nodes are set, then we don't need to wait for the services - if [ -n "{{ .Values.aztec.contracts.registryAddress }}" ] && [ -n "{{ .Values.aztec.bootstrapENRs }}" ]; then - echo "Registry address and bootstrap nodes already set, skipping wait for services" - echo "{{ include "aztec-network.pxeUrl" . }}" > /shared/pxe/pxe_url - exit 0 - fi - - source /shared/config/service-addresses - cat /shared/config/service-addresses - {{- include "aztec-network.waitForEthereum" . | nindent 14 }} - - if [ "{{ .Values.validator.dynamicBootNode }}" = "true" ]; then - echo "{{ include "aztec-network.pxeUrl" . }}" > /shared/pxe/pxe_url - else - until curl --silent --head --fail "${BOOT_NODE_HOST}/status" > /dev/null; do - echo "Waiting for boot node..." - sleep 5 - done - echo "Boot node is ready!" - echo "${BOOT_NODE_HOST}" > /shared/pxe/pxe_url - fi - volumeMounts: - - name: pxe-url - mountPath: /shared/pxe - - name: scripts - mountPath: /scripts - - name: config - mountPath: /shared/config - - - - name: configure-validator-env - {{- include "aztec-network.image" . | nindent 10 }} - command: - - "/bin/bash" - - "-c" - - | - source /shared/config/service-addresses && \ - cp /scripts/configure-full-node-env.sh /tmp/configure-full-node-env.sh && \ - chmod +x /tmp/configure-full-node-env.sh && \ - /tmp/configure-full-node-env.sh "$(cat /shared/pxe/pxe_url)" - volumeMounts: - - name: contracts-env - mountPath: /shared/contracts - - name: pxe-url - mountPath: /shared/pxe - - name: scripts - mountPath: /scripts - - name: config - mountPath: /shared/config - env: - - name: P2P_ENABLED - value: "{{ .Values.validator.p2p.enabled }}" - - name: BOOTSTRAP_NODES - value: "{{ .Values.aztec.bootstrapENRs }}" - - name: REGISTRY_CONTRACT_ADDRESS - value: "{{ .Values.aztec.contracts.registryAddress }}" - - name: SLASH_FACTORY_CONTRACT_ADDRESS - value: "{{ .Values.aztec.contracts.slashFactoryAddress }}" containers: - name: validator {{- include "aztec-network.image" . | nindent 10 }} @@ -141,9 +77,8 @@ spec: - "/bin/bash" - "-c" - | - sleep 10 && \ source /shared/contracts/contracts.env && \ - source /shared/p2p/p2p-addresses && \ + source /shared/config/p2p-addresses && \ source /shared/config/service-addresses && \ source /shared/config/keys.env && \ source /shared/config/otel-resource && \ @@ -168,8 +103,6 @@ spec: volumeMounts: - name: contracts-env mountPath: /shared/contracts - - name: p2p-addresses - mountPath: /shared/p2p - name: config mountPath: /shared/config - name: validator-data @@ -270,10 +203,9 @@ spec: - name: scripts configMap: name: {{ include "aztec-network.fullname" . }}-scripts + defaultMode: 0755 - name: contracts-env emptyDir: {} - - name: p2p-addresses - emptyDir: {} - name: pxe-url emptyDir: {} - name: config diff --git a/spartan/aztec-network/values.yaml b/spartan/aztec-network/values.yaml index ed10c2a503e..fba758d4c75 100644 --- a/spartan/aztec-network/values.yaml +++ b/spartan/aztec-network/values.yaml @@ -272,6 +272,7 @@ bot: maxOldSpaceSize: "4608" ethereum: + acceleratedTestDeployments: false replicas: 1 chainId: 1337 blockTime: 12 diff --git a/spartan/aztec-network/values/ci-smoke.yaml b/spartan/aztec-network/values/ci-smoke.yaml index 7d682a91150..eb2d749639d 100644 --- a/spartan/aztec-network/values/ci-smoke.yaml +++ b/spartan/aztec-network/values/ci-smoke.yaml @@ -37,6 +37,7 @@ bot: enabled: false ethereum: + acceleratedTestDeployments: true execution: resources: requests: diff --git a/spartan/aztec-network/values/ci.yaml b/spartan/aztec-network/values/ci.yaml index ae1e157c126..4c4860a5c2b 100644 --- a/spartan/aztec-network/values/ci.yaml +++ b/spartan/aztec-network/values/ci.yaml @@ -4,6 +4,7 @@ aztec: proofSubmissionWindow: 8 ethereum: + acceleratedTestDeployments: true blockTime: 8 execution: resources: diff --git a/yarn-project/cli/src/cmds/l1/deploy_l1_contracts.ts b/yarn-project/cli/src/cmds/l1/deploy_l1_contracts.ts index 6ffd0fa1a0d..23d006155fd 100644 --- a/yarn-project/cli/src/cmds/l1/deploy_l1_contracts.ts +++ b/yarn-project/cli/src/cmds/l1/deploy_l1_contracts.ts @@ -14,6 +14,7 @@ export async function deployL1Contracts( mnemonicIndex: number, salt: number | undefined, testAccounts: boolean, + acceleratedTestDeployments: boolean, json: boolean, initialValidators: EthAddress[], log: LogFn, @@ -34,6 +35,7 @@ export async function deployL1Contracts( initialValidators, genesisArchiveRoot, genesisBlockHash, + acceleratedTestDeployments, config, debugLogger, ); diff --git a/yarn-project/cli/src/cmds/l1/index.ts b/yarn-project/cli/src/cmds/l1/index.ts index 1b8cd88c41c..0e291874633 100644 --- a/yarn-project/cli/src/cmds/l1/index.ts +++ b/yarn-project/cli/src/cmds/l1/index.ts @@ -42,6 +42,7 @@ export function injectCommands(program: Command, log: LogFn, debugLogger: Logger .option('--salt ', 'The optional salt to use in deployment', arg => parseInt(arg)) .option('--json', 'Output the contract addresses in JSON format') .option('--test-accounts', 'Populate genesis state with initial fee juice for test accounts') + .option('--accelerated-test-deployments', 'Fire and forget deployment transactions, use in testing only', false) .action(async options => { const { deployL1Contracts } = await import('./deploy_l1_contracts.js'); @@ -55,6 +56,7 @@ export function injectCommands(program: Command, log: LogFn, debugLogger: Logger options.mnemonicIndex, options.salt, options.testAccounts, + options.acceleratedTestDeployments, options.json, initialValidators, log, diff --git a/yarn-project/cli/src/utils/aztec.ts b/yarn-project/cli/src/utils/aztec.ts index 620e7db7814..bae192a3a7c 100644 --- a/yarn-project/cli/src/utils/aztec.ts +++ b/yarn-project/cli/src/utils/aztec.ts @@ -44,6 +44,7 @@ export async function deployAztecContracts( initialValidators: EthAddress[], genesisArchiveRoot: Fr, genesisBlockHash: Fr, + acceleratedTestDeployments: boolean, config: L1ContractsConfig, debugLogger: Logger, ): Promise { @@ -70,6 +71,7 @@ export async function deployAztecContracts( genesisBlockHash, salt, initialValidators, + acceleratedTestDeployments, ...config, }, config, diff --git a/yarn-project/ethereum/src/deploy_l1_contracts.ts b/yarn-project/ethereum/src/deploy_l1_contracts.ts index 9c36418cfaa..dc37f112757 100644 --- a/yarn-project/ethereum/src/deploy_l1_contracts.ts +++ b/yarn-project/ethereum/src/deploy_l1_contracts.ts @@ -1,6 +1,6 @@ import { EthAddress } from '@aztec/foundation/eth-address'; import type { Fr } from '@aztec/foundation/fields'; -import type { Logger } from '@aztec/foundation/log'; +import { type Logger, createLogger } from '@aztec/foundation/log'; import { CoinIssuerAbi, CoinIssuerBytecode, @@ -43,6 +43,7 @@ import { createPublicClient, createWalletClient, encodeDeployData, + encodeFunctionData, fallback, getAddress, getContract, @@ -60,7 +61,13 @@ import type { L1ContractsConfig } from './config.js'; import { RegistryContract } from './contracts/registry.js'; import { RollupContract } from './contracts/rollup.js'; import type { L1ContractAddresses } from './l1_contract_addresses.js'; -import { L1TxUtils, type L1TxUtilsConfig, defaultL1TxUtilsConfig } from './l1_tx_utils.js'; +import { + type GasPrice, + type L1TxRequest, + L1TxUtils, + type L1TxUtilsConfig, + defaultL1TxUtilsConfig, +} from './l1_tx_utils.js'; import type { L1Clients, ViemPublicClient, ViemWalletClient } from './types.js'; export const DEPLOYER_ADDRESS: Hex = '0x4e59b44847b379578588920cA78FbF26c0B4956C'; @@ -204,6 +211,8 @@ export interface DeployL1ContractsArgs extends L1ContractsConfig { initialValidators?: EthAddress[]; /** Configuration for the L1 tx utils module. */ l1TxConfig?: Partial; + /** Enable fast mode for deployments (fire and forget transactions) */ + acceleratedTestDeployments?: boolean; } /** @@ -255,7 +264,14 @@ export const deployRollupAndPeriphery = async ( logger: Logger, txUtilsConfig: L1TxUtilsConfig, ) => { - const deployer = new L1Deployer(clients.walletClient, clients.publicClient, args.salt, logger, txUtilsConfig); + const deployer = new L1Deployer( + clients.walletClient, + clients.publicClient, + args.salt, + args.acceleratedTestDeployments, + logger, + txUtilsConfig, + ); const addresses = await RegistryContract.collectAddresses(clients.publicClient, registryAddress, 'canonical'); @@ -337,31 +353,48 @@ export const deployRollup = async ( if (args.initialValidators && args.initialValidators.length > 0) { // Check if some of the initial validators are already registered, so we support idempotent deployments - const validatorsInfo = await Promise.all( - args.initialValidators.map(async address => ({ address, ...(await rollup.read.getInfo([address.toString()])) })), - ); - const existingValidators = validatorsInfo.filter(v => v.status !== 0); - if (existingValidators.length > 0) { - logger.warn( - `Validators ${existingValidators.map(v => v.address).join(', ')} already exist. Skipping from initialization.`, + let newValidatorsAddresses = args.initialValidators.map(v => v.toString()); + if (!args.acceleratedTestDeployments) { + const validatorsInfo = await Promise.all( + args.initialValidators.map(async address => ({ + address, + ...(await rollup.read.getInfo([address.toString()])), + })), ); - } + const existingValidators = validatorsInfo.filter(v => v.status !== 0); + if (existingValidators.length > 0) { + logger.warn( + `Validators ${existingValidators + .map(v => v.address) + .join(', ')} already exist. Skipping from initialization.`, + ); + } - const newValidatorsAddresses = validatorsInfo.filter(v => v.status === 0).map(v => v.address.toString()); + newValidatorsAddresses = validatorsInfo.filter(v => v.status === 0).map(v => v.address.toString()); + } if (newValidatorsAddresses.length > 0) { - const stakingAsset = getContract({ - address: addresses.stakingAssetAddress.toString(), - abi: l1Artifacts.stakingAsset.contractAbi, - client: clients.walletClient, - }); // Mint tokens, approve them, use cheat code to initialise validator set without setting up the epoch. const stakeNeeded = args.minimumStake * BigInt(newValidatorsAddresses.length); await Promise.all( [ - await stakingAsset.write.mint([clients.walletClient.account.address, stakeNeeded], {} as any), - await stakingAsset.write.approve([rollupAddress.toString(), stakeNeeded], {} as any), - ].map(txHash => clients.publicClient.waitForTransactionReceipt({ hash: txHash })), + await deployer.sendTransaction({ + to: addresses.stakingAssetAddress.toString(), + data: encodeFunctionData({ + abi: l1Artifacts.stakingAsset.contractAbi, + functionName: 'mint', + args: [clients.walletClient.account.address, stakeNeeded], + }), + }), + await deployer.sendTransaction({ + to: addresses.stakingAssetAddress.toString(), + data: encodeFunctionData({ + abi: l1Artifacts.stakingAsset.contractAbi, + functionName: 'approve', + args: [rollupAddress.toString(), stakeNeeded], + }), + }), + ].map(tx => clients.publicClient.waitForTransactionReceipt({ hash: tx.txHash })), ); const validators = newValidatorsAddresses.map(v => ({ @@ -370,7 +403,13 @@ export const deployRollup = async ( withdrawer: v, amount: args.minimumStake, })); - const initiateValidatorSetTxHash = await rollup.write.cheat__InitialiseValidatorSet([validators]); + // const initiateValidatorSetTxHash = await rollup.write.cheat__InitialiseValidatorSet([validators]); + const initiateValidatorSetTxHash = await deployer.walletClient.writeContract({ + address: rollupAddress.toString(), + abi: l1Artifacts.rollup.contractAbi, + functionName: 'cheat__InitialiseValidatorSet', + args: [validators], + }); txHashes.push(initiateValidatorSetTxHash); logger.info(`Initialized validator set`, { validators, @@ -401,9 +440,11 @@ export const deployL1Contracts = async ( args: DeployL1ContractsArgs, txUtilsConfig: L1TxUtilsConfig = defaultL1TxUtilsConfig, ): Promise => { + const clients = createL1Clients(rpcUrls, account, chain); + const { walletClient, publicClient } = clients; + // We are assuming that you are running this on a local anvil node which have 1s block times // To align better with actual deployment, we update the block interval to 12s - const { walletClient, publicClient } = createL1Clients(rpcUrls, account, chain); const rpcCall = async (method: string, params: any[]) => { logger.info(`Calling ${method} with params: ${JSON.stringify(params)}`); @@ -425,7 +466,14 @@ export const deployL1Contracts = async ( logger.verbose(`Deploying contracts from ${account.address.toString()}`); // Governance stuff - const deployer = new L1Deployer(walletClient, publicClient, args.salt, logger, txUtilsConfig); + const deployer = new L1Deployer( + walletClient, + publicClient, + args.salt, + args.acceleratedTestDeployments, + logger, + txUtilsConfig, + ); const registryAddress = await deployer.deploy(l1Artifacts.registry, [account.address.toString()]); logger.verbose(`Deployed Registry at ${registryAddress}`); @@ -494,14 +542,28 @@ export const deployL1Contracts = async ( // Transaction hashes to await const txHashes: Hex[] = []; - if (!(await feeAsset.read.freeForAll())) { - const txHash = await feeAsset.write.setFreeForAll([true], {} as any); + if (args.acceleratedTestDeployments || !(await feeAsset.read.freeForAll())) { + const { txHash } = await deployer.sendTransaction({ + to: feeAssetAddress.toString(), + data: encodeFunctionData({ + abi: l1Artifacts.feeAsset.contractAbi, + functionName: 'setFreeForAll', + args: [true], + }), + }); logger.verbose(`Fee asset set to free for all in ${txHash}`); txHashes.push(txHash); } - if ((await feeAsset.read.owner()) !== getAddress(coinIssuerAddress.toString())) { - const txHash = await feeAsset.write.transferOwnership([coinIssuerAddress.toString()], { account }); + if (args.acceleratedTestDeployments || (await feeAsset.read.owner()) !== getAddress(coinIssuerAddress.toString())) { + const { txHash } = await deployer.sendTransaction({ + to: feeAssetAddress.toString(), + data: encodeFunctionData({ + abi: l1Artifacts.feeAsset.contractAbi, + functionName: 'transferOwnership', + args: [coinIssuerAddress.toString()], + }), + }); logger.verbose(`Fee asset transferred ownership to coin issuer in ${txHash}`); txHashes.push(txHash); } @@ -511,21 +573,47 @@ export const deployL1Contracts = async ( // @todo #8084 // fund the portal contract with Fee Juice const FEE_JUICE_INITIAL_MINT = 200000000000000000000000n; - const mintTxHash = await feeAsset.write.mint([feeJuicePortalAddress.toString(), FEE_JUICE_INITIAL_MINT], {} as any); + + // In fast mode, use the L1TxUtils to send transactions with nonce management + const { txHash: mintTxHash } = await deployer.sendTransaction({ + to: feeAssetAddress.toString(), + data: encodeFunctionData({ + abi: l1Artifacts.feeAsset.contractAbi, + functionName: 'mint', + args: [feeJuicePortalAddress.toString(), FEE_JUICE_INITIAL_MINT], + }), + }); + logger.verbose(`Funding fee juice portal contract with fee juice in ${mintTxHash} (accelerated test deployments)`); + txHashes.push(mintTxHash); // @note This is used to ensure we fully wait for the transaction when running against a real chain // otherwise we execute subsequent transactions too soon - await publicClient.waitForTransactionReceipt({ hash: mintTxHash }); - logger.verbose(`Funding fee juice portal contract with fee juice in ${mintTxHash}`); + if (!args.acceleratedTestDeployments) { + await publicClient.waitForTransactionReceipt({ hash: mintTxHash }); + logger.verbose(`Funding fee juice portal contract with fee juice in ${mintTxHash}`); + } + + // Check if portal needs initialization + let needsInitialization = args.acceleratedTestDeployments; + if (!args.acceleratedTestDeployments) { + // Only check if not in fast mode and not already known to need initialization + needsInitialization = !(await feeJuicePortal.read.initialized()); + } + if (needsInitialization) { + const { txHash: initPortalTxHash } = await deployer.sendTransaction({ + to: feeJuicePortalAddress.toString(), + data: encodeFunctionData({ + abi: l1Artifacts.feeJuicePortal.contractAbi, + functionName: 'initialize', + args: [], + }), + }); - if (!(await feeJuicePortal.read.initialized())) { - const initPortalTxHash = await feeJuicePortal.write.initialize(); txHashes.push(initPortalTxHash); logger.verbose(`Fee juice portal initializing in tx ${initPortalTxHash}`); } else { logger.verbose(`Fee juice portal is already initialized`); } - logger.verbose( `Initialized Fee Juice Portal at ${feeJuicePortalAddress} to bridge between L1 ${feeAssetAddress} to L2 ${args.l2FeeJuiceAddress}`, ); @@ -553,8 +641,18 @@ export const deployL1Contracts = async ( client: walletClient, }); - if (!(await registryContract.read.isRollupRegistered([getAddress(rollup.address.toString())]))) { - const upgradeTxHash = await registryContract.write.upgrade([getAddress(rollup.address.toString())], { account }); + if ( + args.acceleratedTestDeployments || + !(await registryContract.read.isRollupRegistered([getAddress(rollup.address.toString())])) + ) { + const { txHash: upgradeTxHash } = await deployer.sendTransaction({ + to: registryAddress.toString(), + data: encodeFunctionData({ + abi: l1Artifacts.registry.contractAbi, + functionName: 'upgrade', + args: [getAddress(rollup.address.toString())], + }), + }); logger.verbose( `Upgrading registry contract at ${registryAddress} to rollup ${rollup.address} in tx ${upgradeTxHash}`, ); @@ -564,13 +662,19 @@ export const deployL1Contracts = async ( } // If the owner is not the Governance contract, transfer ownership to the Governance contract - if ((await registryContract.read.owner()) !== getAddress(governanceAddress.toString())) { - const transferOwnershipTxHash = await registryContract.write.transferOwnership( - [getAddress(governanceAddress.toString())], - { - account, - }, - ); + if ( + args.acceleratedTestDeployments || + (await registryContract.read.owner()) !== getAddress(governanceAddress.toString()) + ) { + // TODO(md): add send transaction to the deployer such that we do not need to manage tx hashes here + const { txHash: transferOwnershipTxHash } = await deployer.sendTransaction({ + to: registryAddress.toString(), + data: encodeFunctionData({ + abi: l1Artifacts.registry.contractAbi, + functionName: 'transferOwnership', + args: [getAddress(governanceAddress.toString())], + }), + }); logger.verbose( `Transferring the ownership of the registry contract at ${registryAddress} to the Governance ${governanceAddress} in tx ${transferOwnershipTxHash}`, ); @@ -620,16 +724,24 @@ export const deployL1Contracts = async ( class L1Deployer { private salt: Hex | undefined; private txHashes: Hex[] = []; - private l1TxUtils: L1TxUtils; + public readonly l1TxUtils: L1TxUtils; + constructor( - private walletClient: ViemWalletClient, + public readonly walletClient: ViemWalletClient, private publicClient: ViemPublicClient, maybeSalt: number | undefined, - private logger: Logger, + private acceleratedTestDeployments: boolean = false, + private logger: Logger = createLogger('L1Deployer'), private txUtilsConfig?: L1TxUtilsConfig, ) { this.salt = maybeSalt ? padHex(numberToHex(maybeSalt), { size: 32 }) : undefined; - this.l1TxUtils = new L1TxUtils(this.publicClient, this.walletClient, this.logger, this.txUtilsConfig); + this.l1TxUtils = new L1TxUtils( + this.publicClient, + this.walletClient, + this.logger, + this.txUtilsConfig, + this.acceleratedTestDeployments, + ); } async deploy(params: ContractArtifacts, args: readonly unknown[] = []): Promise { @@ -643,6 +755,7 @@ class L1Deployer { params.libraries, this.logger, this.l1TxUtils, + this.acceleratedTestDeployments, ); if (txHash) { this.txHashes.push(txHash); @@ -651,7 +764,21 @@ class L1Deployer { } async waitForDeployments(): Promise { + if (this.acceleratedTestDeployments) { + this.logger.info('Accelerated test deployments - skipping waiting for deployments'); + return; + } + if (this.txHashes.length === 0) { + return; + } + + this.logger.info(`Waiting for ${this.txHashes.length} transactions to be mined...`); await Promise.all(this.txHashes.map(txHash => this.publicClient.waitForTransactionReceipt({ hash: txHash }))); + this.logger.info('All transactions mined successfully'); + } + + sendTransaction(tx: L1TxRequest): Promise<{ txHash: Hex; gasLimit: bigint; gasPrice: GasPrice }> { + return this.l1TxUtils.sendTransaction(tx); } } @@ -675,14 +802,14 @@ export async function deployL1Contract( maybeSalt?: Hex, libraries?: Libraries, logger?: Logger, - _l1TxUtils?: L1TxUtils, + l1TxUtils?: L1TxUtils, + acceleratedTestDeployments: boolean = false, ): Promise<{ address: EthAddress; txHash: Hex | undefined }> { let txHash: Hex | undefined = undefined; let resultingAddress: Hex | null | undefined = undefined; - let l1TxUtils: L1TxUtils | undefined = _l1TxUtils; if (!l1TxUtils) { - l1TxUtils = new L1TxUtils(publicClient, walletClient, logger); + l1TxUtils = new L1TxUtils(publicClient, walletClient, logger, undefined, acceleratedTestDeployments); } if (libraries) { @@ -712,6 +839,7 @@ export async function deployL1Contract( undefined, logger, l1TxUtils, + acceleratedTestDeployments, ); if (txHash) { @@ -746,9 +874,16 @@ export async function deployL1Contract( // Reth fails gas estimation if the deployed contract attempts to call a library that is not yet deployed, // so we wait for all library deployments to be mined before deploying the contract. - if (libraryTxs.length > 0) { + // However, if we are in fast mode or using debugMaxGasLimit, we will skip simulation, so we can skip waiting. + if (libraryTxs.length > 0 && !acceleratedTestDeployments) { logger?.verbose(`Awaiting for linked libraries to be deployed`); await Promise.all(libraryTxs.map(txHash => publicClient.waitForTransactionReceipt({ hash: txHash }))); + } else { + logger?.verbose( + `Skipping waiting for linked libraries to be deployed ${ + acceleratedTestDeployments ? '(accelerated test deployments)' : '' + }`, + ); } } diff --git a/yarn-project/ethereum/src/l1_tx_utils.ts b/yarn-project/ethereum/src/l1_tx_utils.ts index a050ef34ade..1b75f3f28a5 100644 --- a/yarn-project/ethereum/src/l1_tx_utils.ts +++ b/yarn-project/ethereum/src/l1_tx_utils.ts @@ -5,7 +5,7 @@ import { getDefaultConfig, numberConfigHelper, } from '@aztec/foundation/config'; -import type { Logger } from '@aztec/foundation/log'; +import { type Logger, createLogger } from '@aztec/foundation/log'; import { makeBackoff, retry } from '@aztec/foundation/retry'; import { sleep } from '@aztec/foundation/sleep'; @@ -190,14 +190,15 @@ export type TransactionStats = { }; export class L1TxUtils { - protected readonly config: L1TxUtilsConfig; + public readonly config: L1TxUtilsConfig; private interrupted = false; constructor( public publicClient: ViemPublicClient, public walletClient: ViemWalletClient, - protected readonly logger?: Logger, + protected logger: Logger = createLogger('L1TxUtils'), config?: Partial, + private debugMaxGasLimit: boolean = false, ) { this.config = { ...defaultL1TxUtilsConfig, @@ -248,7 +249,9 @@ export class L1TxUtils { const account = this.walletClient.account; let gasLimit: bigint; - if (gasConfig.gasLimit) { + if (this.debugMaxGasLimit) { + gasLimit = LARGE_GAS_LIMIT; + } else if (gasConfig.gasLimit) { gasLimit = gasConfig.gasLimit; } else { gasLimit = await this.estimateGas(account, request); @@ -288,7 +291,9 @@ export class L1TxUtils { return { txHash, gasLimit, gasPrice }; } catch (err: any) { const viemError = formatViemError(err); - this.logger?.error(`Failed to send L1 transaction`, viemError.message, { metaMessages: viemError.metaMessages }); + this.logger?.error(`Failed to send L1 transaction`, viemError.message, { + metaMessages: viemError.metaMessages, + }); throw viemError; } }