From 13a3485fbffb964510f08622bb8242ed6b64778b Mon Sep 17 00:00:00 2001 From: iAmMichaelConnor Date: Sat, 20 Dec 2025 19:39:50 +0000 Subject: [PATCH 1/2] refactor: move overflow check --- .github/workflows/ci3.yml | 3 +- Makefile | 12 +- aztec-up/.gitignore | 4 +- aztec-up/Dockerfile | 14 +- aztec-up/README.md | 6 + aztec-up/bin/.aztec-run | 161 ----- aztec-up/bin/aztec | 570 ------------------ aztec-up/bin/aztec-install | 272 ++++++--- aztec-up/bin/aztec-wallet | 16 - aztec-up/bootstrap.sh | 100 ++- aztec-up/scripts/run_isolated_test.sh | 71 +++ aztec-up/scripts/run_test.sh | 58 +- aztec-up/test/amm_flow.sh | 32 +- aztec-up/test/basic_install.sh | 50 +- aztec-up/test/bridge_and_claim.sh | 32 +- aztec-up/test/counter_contract.sh | 36 +- bootstrap.sh | 18 +- boxes/.gitignore | 2 - boxes/bin.js | 124 ---- boxes/bin.test.js | 91 --- boxes/bootstrap.sh | 29 +- boxes/boxes/react/.gitignore | 1 + boxes/boxes/react/package.json | 11 +- boxes/boxes/react/playwright.config.ts | 30 +- boxes/boxes/vanilla/.gitignore | 2 +- boxes/boxes/vanilla/.prettierrc.json | 6 + boxes/boxes/vanilla/package.json | 16 +- boxes/boxes/vanilla/playwright.config.ts | 34 +- boxes/boxes/vite/.gitignore | 3 +- boxes/boxes/vite/.prettierrc.json | 6 + boxes/boxes/vite/package.json | 12 +- boxes/boxes/vite/playwright.config.ts | 35 +- boxes/docker-compose.yml | 60 -- boxes/package.json | 7 +- boxes/scripts/config.js | 14 - boxes/scripts/init.js | 19 - boxes/scripts/run_test.sh | 24 + boxes/scripts/steps/chooseBox.js | 127 ---- boxes/scripts/utils.js | 264 -------- ci3/docker_isolate | 2 +- ci3/parallelize | 2 +- ci3/run_compose_test | 10 +- ci3/source_bootstrap | 2 +- .../noir-contracts/scripts/flamegraph.sh | 100 --- noir/bootstrap.sh | 25 +- release-image/Dockerfile | 17 +- release-image/Dockerfile.base | 2 +- release-image/Dockerfile.dockerignore | 48 +- release-image/bootstrap.sh | 5 + yarn-project/aztec/package.json | 3 +- yarn-project/aztec/scripts/aztec.sh | 56 ++ yarn-project/aztec/scripts/compile.sh | 44 ++ .../aztec/scripts/extract_function.js | 26 +- yarn-project/aztec/scripts/flamegraph.sh | 59 ++ yarn-project/aztec/scripts/init.sh | 35 ++ yarn-project/aztec/scripts/new.sh | 59 ++ yarn-project/aztec/scripts/setup_project.sh | 31 + yarn-project/aztec/src/cli/cli.ts | 24 +- yarn-project/bootstrap.sh | 6 +- yarn-project/cli-wallet/src/bin/index.ts | 1 + yarn-project/cli-wallet/wallet-entrypoint.sh | 17 - .../ethereum/src/deploy_aztec_l1_contracts.ts | 73 ++- yarn-project/l1-artifacts/.gitignore | 1 + yarn-project/l1-artifacts/package.json | 6 +- .../scripts/copy-foundry-artifacts.sh | 29 + yarn-project/yarn.lock | 2 +- 66 files changed, 927 insertions(+), 2130 deletions(-) delete mode 100755 aztec-up/bin/.aztec-run delete mode 100755 aztec-up/bin/aztec delete mode 100755 aztec-up/bin/aztec-wallet create mode 100755 aztec-up/scripts/run_isolated_test.sh delete mode 100755 boxes/bin.js delete mode 100644 boxes/bin.test.js create mode 100644 boxes/boxes/vanilla/.prettierrc.json create mode 100644 boxes/boxes/vite/.prettierrc.json delete mode 100644 boxes/docker-compose.yml delete mode 100644 boxes/scripts/config.js delete mode 100644 boxes/scripts/init.js create mode 100755 boxes/scripts/run_test.sh delete mode 100644 boxes/scripts/steps/chooseBox.js delete mode 100644 boxes/scripts/utils.js delete mode 100755 noir-projects/noir-contracts/scripts/flamegraph.sh create mode 100755 yarn-project/aztec/scripts/aztec.sh create mode 100755 yarn-project/aztec/scripts/compile.sh rename noir-projects/noir-contracts/scripts/extractFunctionAsNoirArtifact.js => yarn-project/aztec/scripts/extract_function.js (61%) create mode 100755 yarn-project/aztec/scripts/flamegraph.sh create mode 100755 yarn-project/aztec/scripts/init.sh create mode 100755 yarn-project/aztec/scripts/new.sh create mode 100755 yarn-project/aztec/scripts/setup_project.sh delete mode 100755 yarn-project/cli-wallet/wallet-entrypoint.sh create mode 100755 yarn-project/l1-artifacts/scripts/copy-foundry-artifacts.sh diff --git a/.github/workflows/ci3.yml b/.github/workflows/ci3.yml index ca0cdcc67e13..55b422aab5ab 100644 --- a/.github/workflows/ci3.yml +++ b/.github/workflows/ci3.yml @@ -175,8 +175,7 @@ jobs: GCP_SA_KEY: ${{ secrets.GCP_SA_KEY }} GCP_PROJECT_ID: ${{ secrets.GCP_PROJECT_ID }} NO_SPOT: 1 - run: - ./.github/ci3.sh network-teardown next-scenario "$NAMESPACE" + run: ./.github/ci3.sh network-teardown next-scenario "$NAMESPACE" ############# # Benchmarks diff --git a/Makefile b/Makefile index 1ad179293118..ac873fd5e9b2 100644 --- a/Makefile +++ b/Makefile @@ -54,12 +54,12 @@ endef # Fast bootstrap all: release-image barretenberg boxes playground docs aztec-up \ - bb-tests l1-contracts-tests yarn-project-tests boxes-tests playground-tests aztec-up-tests docs-tests noir-protocol-circuits-tests + bb-tests l1-contracts-tests yarn-project-tests boxes-tests playground-tests aztec-up-tests docs-tests noir-protocol-circuits-tests release-image-tests # Full bootstrap full: release-image barretenberg boxes playground docs aztec-up \ bb-cpp-full yarn-project-benches \ - bb-full-tests l1-contracts-tests yarn-project-tests boxes-tests playground-tests aztec-up-tests docs-tests noir-protocol-circuits-tests + bb-full-tests l1-contracts-tests yarn-project-tests boxes-tests playground-tests aztec-up-tests docs-tests noir-protocol-circuits-tests release-image-tests # Release. Everything plus copy bb cross compiles to ts projects. release: all bb-cpp-release-dir bb-ts-cross-copy @@ -293,7 +293,10 @@ yarn-project-benches: yarn-project release-image: yarn-project $(call build,$@,release-image) -boxes: release-image +release-image-tests: release-image + $(call test,$@,release-image) + +boxes: yarn-project $(call build,$@,boxes) boxes-tests: boxes @@ -305,7 +308,6 @@ playground: yarn-project playground-tests: playground $(call test,$@,playground) -# Docs - Project documentation docs: yarn-project $(call build,$@,docs) @@ -315,5 +317,5 @@ docs-tests: docs aztec-up: yarn-project $(call build,$@,aztec-up) -aztec-up-tests: aztec-up release-image +aztec-up-tests: aztec-up $(call test,$@,aztec-up) diff --git a/aztec-up/.gitignore b/aztec-up/.gitignore index 5fd438ece3e8..cd60a81034c5 100644 --- a/aztec-up/.gitignore +++ b/aztec-up/.gitignore @@ -1,3 +1,5 @@ .terraform .terraform* -.DS_Store \ No newline at end of file +.DS_Store +bin/versions +verdaccio-storage diff --git a/aztec-up/Dockerfile b/aztec-up/Dockerfile index fa8a1263ae90..9a4cef2010dd 100644 --- a/aztec-up/Dockerfile +++ b/aztec-up/Dockerfile @@ -1,6 +1,14 @@ ######################################################################################################################## -# A pure ubuntu + docker install. Used for testing releases. +# A minimal ubuntu setup. Used for testing releases. FROM ubuntu:noble AS dind -RUN apt-get update && apt-get install -y curl -RUN curl -fsSL https://raw.githubusercontent.com/devcontainers/features/refs/heads/main/src/docker-in-docker/install.sh | bash +RUN apt update && apt install -y \ + curl \ + git \ + build-essential \ + python3 \ + netcat-openbsd \ + parallel \ + jq \ + && rm -rf /var/lib/apt/lists/* +COPY --chown=1000:1000 verdaccio-storage /home/ubuntu/verdaccio-storage RUN touch /aztec_release_test_container diff --git a/aztec-up/README.md b/aztec-up/README.md index 2c6a18c6d7b6..73742039b95c 100644 --- a/aztec-up/README.md +++ b/aztec-up/README.md @@ -26,3 +26,9 @@ VERSION=1.2.3 aztec-up ``` This will install the tagged release version 1.2.3. + +## Testing + +``` +INSTALL_URI=file://$(git rev-parse --show-toplevel)/aztec-up/bin $(git rev-parse --show-toplevel)/aztec-up/bin/aztec-install +``` diff --git a/aztec-up/bin/.aztec-run b/aztec-up/bin/.aztec-run deleted file mode 100755 index 008906c31f1e..000000000000 --- a/aztec-up/bin/.aztec-run +++ /dev/null @@ -1,161 +0,0 @@ -#!/usr/bin/env bash -# -# STOP! BEFORE YOU MODIFY THIS SCRIPT: -# -# The script starts the aztec mono-container. -# It handles mounting paths into the container. -# It handles networking and comms back to the host. -# It handles uid/gid adjustments. -# It handles environment variable forwarding. -# It's called with a multitude of entrypoints. -# -# DO NOT ADD CALLER SPECIFIC SHENANIGANS. -# Such stuff belongs in higher level e.g. `aztec` or `aztec-wallet` scripts. -set -euo pipefail - -# Can be overriden by env var CONTAINER_NAME, e.g. to start two local networks. -CONTAINER_NAME=${CONTAINER_NAME:-$1} -shift - -VERSION=${VERSION:-"latest"} - -# We default to colored logs. -FORCE_COLOR=${FORCE_COLOR:-1} - -DOCKER_REPO=${DOCKER_REPO:-"aztecprotocol/aztec"} - -function warn { - y="\033[33m" - r="\033[0m" - echo -e "${y}$1${r}" -} - -if ! command -v docker &>/dev/null; then - warn "No docker found." - exit 1 -fi - -if [[ $PWD != ${HOME}* ]]; then - warn "Due to how we containerize our applications, we require your working directory to be somewhere within $HOME." - exit 1 -fi - -uname=$(uname -s) -if [ "$uname" == "Linux" ] && docker info 2>/dev/null | grep -q rootless; then - ROOTLESS=1 -fi - -# If running in rootless docker, don't set uid/gid in container, as it breaks the write perms to the home mount. -# Otherwise we set the uid/gid to be that of user running the container to ensure write perms to the home mount. -if [ -z "${ROOTLESS:-}" ]; then - arg_user="--user $(id -u):$(id -g)" -fi - -# Set up host.docker.internal alias on Linux, just like it is on mac. -if [[ -z "${SKIP_NET:-}" && "$uname" == "Linux" ]]; then - if [ -n "${ROOTLESS:-}" ]; then - # We're in rootless docker. Probe for the host ip and use that. - ip=$(hostname -I | head | tr -d ' ') - warn "WARNING: Running within rootless docker. Using $ip as host ip. Ensure listening services are listening on this interface." - arg_host_binds="--add-host host.docker.internal:$ip" - else - arg_host_binds="--add-host host.docker.internal:host-gateway" - fi -fi - -# Substitute any references to localhost with our host gateway. -# TODO: In node, we can hook the resolve override for localhost with host.docker.internal. -# Consider if we should just do that, but that wouldn't help e.g. nargo. -args=("$@") -for i in "${!args[@]}"; do - args[$i]=${args[$i]//localhost/host.docker.internal} -done - -# Check if it's either a filename or a directory that exists outside the HOME. -# If so, warn and exit. -for i in "${!args[@]}"; do - arg=${args[$i]} - if [[ -f "$arg" || -d "$arg" ]] && [[ $(realpath $arg) != ${HOME}* ]]; then - warn "Due to how we containerize our applications, paths outside of $HOME cannot be referenced." - exit 1 - fi -done - -# Volume mounts. We always mount in users home dir and cache volume. -arg_volume_mounts="-v $HOME:$HOME -v cache:/cache" - -# If we have an ssh agent running, mount it into container, or if on mac, forward it with socat. -if [[ "${FORWARD_SSH_AGENT:-0}" == 1 && -n "${SSH_AUTH_SOCK:-}" ]]; then - # warn "SSH_AUTH_SOCK is set to ${SSH_AUTH_SOCK:-}. Attempting to enable SSH agent forwarding..." - - if [ "$uname" == "Darwin" ]; then - if ! command -v socat &> /dev/null; then - warn "Socat is not installed. To make SSH agent forwarding work in MacOS, please run:\nbrew install socat" - else - socat TCP-LISTEN:${SSH_AUTH_SOCK_SOCAT_PORT:-12345},reuseaddr,fork UNIX-CLIENT:$SSH_AUTH_SOCK & - socat_pid=$! - trap 'kill -9 $socat_pid &>/dev/null' EXIT - ENV_VARS_TO_INJECT+=" SSH_AUTH_SOCK_SOCAT_PORT" - fi - else - ENV_VARS_TO_INJECT+=" SSH_AUTH_SOCK" - arg_volume_mounts+=" -v $SSH_AUTH_SOCK:$SSH_AUTH_SOCK" - fi -fi - -# Forward all requested environment variables into the container. -# Substitute any reference to localhost with our host gateway. -arg_env_vars=("-e" "HOME=$HOME") -for env in ${ENV_VARS_TO_INJECT:-}; do - if [ -n "${!env:-}" ]; then - env=${env//localhost/host.docker.internal} - arg_env_vars+=("-e" "$env=${!env}") - fi -done - -arg_port_assignment="" - -# Dynamic port assignment. -if [ -n "${PORTS_TO_EXPOSE:-}" ]; then - for port in ${PORTS_TO_EXPOSE}; do - arg_port_assignment+=" -p $port " - done -fi - -# For debugging the aztec-up scripts, can be useful to mount local code into container. -if [ "${MOUNT_LOCAL_CODE:-0}" -eq 1 ]; then - arg_volume_mounts=" -v $PWD/..:/usr/src:ro" -fi - -# Container name. -if [ -n "$CONTAINER_NAME" ]; then - arg_container_name="--name $CONTAINER_NAME" -fi - -function run { - docker run \ - ${arg_container_name:-} \ - --rm \ - --workdir "$PWD" \ - --restart "${DOCKER_RESTART_POLICY:-no}" \ - --pull "${DOCKER_PULL_POLICY:-missing}" \ - ${arg_interactive:-} \ - ${arg_volume_mounts:-} \ - ${arg_port_assignment:-} \ - "${arg_env_vars[@]}" \ - ${arg_host_binds:-} \ - ${arg_user:-} \ - --entrypoint "" \ - $DOCKER_REPO:$VERSION "${args[@]}" -} - -if [ -t 0 ]; then - # We're in a terminal. Docker will receive e.g. SIGINT directly. - arg_interactive=-ti - run -else - # Not connected to a terminal. We need to ensure we can propagate kill signals. - trap 'echo "Sending kill to $CONTAINER_NAME"; docker kill $CONTAINER_NAME &>/dev/null; exit 0' SIGINT SIGTERM - run & - wait $! -fi diff --git a/aztec-up/bin/aztec b/aztec-up/bin/aztec deleted file mode 100755 index 1032d34d61f5..000000000000 --- a/aztec-up/bin/aztec +++ /dev/null @@ -1,570 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -export AZTEC_PATH="${AZTEC_PATH:-$HOME/.aztec}" -DEFAULT_VERSION=$(cat "$AZTEC_PATH/default_version" 2> /dev/null || echo latest) -export VERSION="${VERSION:-$DEFAULT_VERSION}" -export DOCKER_REPO="${DOCKER_REPO:-"aztecprotocol/aztec"}" - -# Take copy of command-line arguments, so we can mutate to parse. -if [ $# -eq 0 ]; then - args=("--help") -else - args=("$@") -fi - -while [ "$#" -gt 0 ]; do - case $1 in - -p | --port) - # Override default port exposed on container. - AZTEC_PORT="$2" - shift 2 - ;; - --p2p.p2pPort) - P2P_PORT="$2" - shift 2 - ;; - --p2p.p2pBroadcastPort) - P2P_BROADCAST_PORT="$2" - shift 2 - ;; - -a | --anvil-port) - # Override default port exposed on container. - ANVIL_PORT="$2" - shift 2 - ;; - --admin-port) - ADMIN_PORT="$2" - shift 2 - ;; - --help) - NO_PORT_FORWARDING=1 - shift 1 - ;; - *) - shift - ;; - esac -done -# Reset positional args. -set -- "${args[@]}" - -function get_env_vars { - docker run --rm --entrypoint /bin/bash $DOCKER_REPO:$VERSION -c "cat /usr/src/yarn-project/foundation/src/config/env_var.ts" | - awk -F"'" '{for(i=2;i<=NF;i+=2) printf $i " "}' -} - -function validate_working_directory { - # Validate working directory is under $HOME for Docker containerization - if [[ $PWD != ${HOME}* ]]; then - >&2 echo "Due to how we containerize our applications, we require your working directory to be somewhere within $HOME." - exit 1 - fi -} - -function run_nargo { - # Helper function to run nargo commands with proper Docker setup - # Usage: run_nargo [args...] - - # Determine if we need interactive/tty flags - if [ -t 0 ]; then - if [ -t 1 ]; then - TTY_FLAGS="-ti" - else - TTY_FLAGS="-i" - fi - fi - - # Run nargo via docker - docker run ${TTY_FLAGS:-} \ - --user $(id -u):$(id -g) \ - -v $HOME:$HOME \ - -e HOME=$HOME \ - --workdir="$PWD" \ - --entrypoint=/usr/src/noir/noir-repo/target/release/nargo \ - $DOCKER_REPO:$VERSION "$@" -} - -function setup_aztec_contract_project { - # Setup an Aztec contract project by adding dependencies and creating the main.nr template - # Usage: setup_aztec_contract_project - # If project_path is ".", operates in current directory - local PROJECT_DIR="$1" - - # Get the actual aztec version for the git tag - AZTEC_VERSION=$(docker run --rm --entrypoint=node $DOCKER_REPO:$VERSION --no-warnings /usr/src/yarn-project/aztec/dest/bin/index.js --version 2>/dev/null | tr -d '\n\r') - - # Determine file paths based on whether we're in current dir or a subdirectory - if [ "$PROJECT_DIR" = "." ]; then - NARGO_TOML_PATH="Nargo.toml" - MAIN_NR_PATH="src/main.nr" - else - NARGO_TOML_PATH="$PROJECT_DIR/Nargo.toml" - MAIN_NR_PATH="$PROJECT_DIR/src/main.nr" - fi - - # Add aztec dependency to Nargo.toml - if [ -f "$NARGO_TOML_PATH" ]; then - echo "" >> "$NARGO_TOML_PATH" - echo "aztec = { git=\"https://github.com/AztecProtocol/aztec-nr\", tag=\"v${AZTEC_VERSION}\", directory=\"aztec\" }" >> "$NARGO_TOML_PATH" - echo "Added aztec dependency (v${AZTEC_VERSION}) to Nargo.toml" - else - >&2 echo "Warning: Could not find Nargo.toml at $NARGO_TOML_PATH to add aztec dependency" - fi - - # Replace the contents of main.nr with the Aztec contract template - if [ -f "$MAIN_NR_PATH" ]; then - cat > "$MAIN_NR_PATH" << 'EOF' -use aztec::macros::aztec; - -#[aztec] -contract Main {} -EOF - echo "Created main.nr with Aztec contract template" - else - >&2 echo "Warning: Could not find main.nr at $MAIN_NR_PATH" - fi -} - -function parse_project_flags_and_build_nargo_args { - # Parse project type flags and build nargo arguments - # Usage: Call this function and it will populate NARGO_ARGS, HAS_TYPE_FLAG, IS_CONTRACT - # For 'new' command: pass "new" as first arg and handle PATH specially - # For 'init' command: pass "init" as first arg - local COMMAND="$1" - shift - - NARGO_ARGS=("$COMMAND") - HAS_TYPE_FLAG=false - IS_CONTRACT=false - PROJECT_PATH="" - - while [ "$#" -gt 0 ]; do - case $1 in - --name) - NARGO_ARGS+=("--name" "$2") - shift 2 - ;; - --lib) - NARGO_ARGS+=("--lib") - HAS_TYPE_FLAG=true - shift - ;; - --bin) - NARGO_ARGS+=("--bin") - HAS_TYPE_FLAG=true - shift - ;; - --contract) - NARGO_ARGS+=("--contract") - HAS_TYPE_FLAG=true - IS_CONTRACT=true - shift - ;; - --help|-h) - return 2 # Special return code to indicate help was requested - ;; - -*) - echo "Unknown option: $1" - echo "Run 'aztec $COMMAND --help' for usage information" - exit 1 - ;; - *) - # For 'new' command, this is the PATH argument - if [ "$COMMAND" = "new" ]; then - PROJECT_PATH="$1" - fi - NARGO_ARGS+=("$1") - shift - ;; - esac - done - - # Default to --contract if no type flag was provided - if [ "$HAS_TYPE_FLAG" = false ]; then - NARGO_ARGS+=("--contract") - IS_CONTRACT=true - fi - - return 0 -} - -case ${1:-} in - compile) - shift - - # If help is requested, show Aztec-specific info then run nargo compile help and then exit in order to not trigger - # transpilation - for arg in "$@"; do - if [ "$arg" == "--help" ] || [ "$arg" == "-h" ]; then - cat << 'EOF' -Aztec Compile - Compile Aztec Noir contracts - -This command compiles Aztec Noir contracts using nargo and then automatically -postprocesses them to generate Aztec-specific artifacts including: - - Transpiled contract artifacts - - Verification keys - -The compiled contracts will be placed in the target/ directory by default. - -AZTEC-SPECIFIC NOTES: - - Working directory must be under $HOME due to Docker containerization - - Compilation automatically includes contract postprocessing - - Use standard nargo compile options (see below) - -ENVIRONMENT VARIABLES: - AZTEC_PATH Path to Aztec installation (default: $HOME/.aztec) - VERSION Aztec version to use (default: from $AZTEC_PATH/default_version) - DOCKER_REPO Docker repository (default: aztecprotocol/aztec) - ---- -Underlying nargo compile options: - -EOF - # Run nargo compile help - run_nargo compile $arg - exit 0 - fi - done - - # We didn't need to perform this check for help because there we don't need to access any files. - validate_working_directory - - # Run nargo compile - run_nargo compile "$@" - - # Check if nargo compile succeeded - if [ $? -ne 0 ]; then - >&2 echo "Compilation failed!" - exit 1 - fi - - echo "Postprocessing contract..." - - docker run ${TTY_FLAGS:-} \ - --user $(id -u):$(id -g) \ - -v $HOME:$HOME \ - -e HOME=$HOME \ - --workdir="$PWD" \ - --entrypoint=/usr/src/barretenberg/cpp/build/bin/bb-avm \ - $DOCKER_REPO:$VERSION aztec_process - - # Strip internal prefixes from all compiled contract JSONs in target directory - docker run ${TTY_FLAGS:-} \ - --user $(id -u):$(id -g) \ - -v $HOME:$HOME \ - -e HOME=$HOME \ - --workdir="$PWD" \ - --entrypoint=/bin/bash \ - $DOCKER_REPO:$VERSION -c 'for json in target/*.json; do [ -f "$json" ] && /usr/src/noir-projects/noir-contracts/scripts/strip_aztec_nr_prefix.sh "$json"; done' - - echo "Compilation complete!" - ;; - test) - shift - - export ENV_VARS_TO_INJECT="LOG_LEVEL" - export LOG_LEVEL="${LOG_LEVEL:-info}" - - # Properly escape all arguments - args_str=$(printf '%q ' "$@") - - # TODO: Need to force ipv4 here with 127.0.0.1 for some reason. TXE's not on ipv6? - exec $(dirname $0)/.aztec-run "" bash -c " - node --no-warnings /usr/src/yarn-project/aztec/dest/bin/index.js start --txe --port 8081 & - while ! nc -z 127.0.0.1 8081 &>/dev/null; do sleep 0.2; done - export NARGO_FOREIGN_CALL_TIMEOUT=300000 - /usr/src/noir/noir-repo/target/release/nargo test --silence-warnings --pedantic-solving --oracle-resolver http://127.0.0.1:8081 $args_str - " - ;; - start|supervised-start) - SUPERVISED=0 - if [ "$1" == "supervised-start" ]; then - SUPERVISED=1 - fi - - shift - - export ENV_VARS_TO_INJECT="$(get_env_vars)" - - # Dynamic port assignments, .aztec-run will expose the array PORTS_TO_EXPOSE as a space-separated string. - AZTEC_PORT=${AZTEC_PORT:-8080} - export PORTS_TO_EXPOSE="$AZTEC_PORT:$AZTEC_PORT" - - # Appends 8 char hex to avoid container name clashes - export CONTAINER_NAME=aztec-start-$(printf "%08x" $((RANDOM * RANDOM))) - - if [ "${1:-}" == "--local-network" ]; then - if [ "$SUPERVISED" == "1" ]; then - echo "supervised-start is not compatible with --local-network. Please use regular start command" - exit 1 - fi - - # TODO: This entire special case should go away. - # Local network mode should start it's own anvil. - # We should not have to provide a binary path and working dir. - # Why is this not just determined and chosen at runtime? - # In fact almost none of these should not have to be set if we have sensible defaults. - export ARCHIVER_POLLING_INTERVAL_MS=500 - export P2P_BLOCK_CHECK_INTERVAL_MS=500 - export SEQ_TX_POLLING_INTERVAL_MS=500 - export WS_BLOCK_CHECK_INTERVAL_MS=500 - export ARCHIVER_VIEM_POLLING_INTERVAL_MS=500 - export TEST_ACCOUNTS=${TEST_ACCOUNTS:-true} - export LOG_LEVEL=${LOG_LEVEL:-info;silent:sequencer;verbose:debug_log} - export DEPLOY_AZTEC_CONTRACTS_SALT=${DEPLOY_AZTEC_CONTRACTS_SALT:-$RANDOM} - - ANVIL_PORT=${ANVIL_PORT:-8545} - anvil_port_assignment="$ANVIL_PORT:8545" - - export L1_CHAIN_ID=${L1_CHAIN_ID:-31337} - export ETHEREUM_HOSTS=${ETHEREUM_HOSTS:-"http://127.0.0.1:${ANVIL_PORT}"} - - PORTS_TO_EXPOSE="${PORTS_TO_EXPOSE:-} $anvil_port_assignment" - - exec $(dirname $0)/.aztec-run aztec-sandbox bash -c " - anvil --version - anvil --host 0.0.0.0 --silent & - node --no-warnings /usr/src/yarn-project/aztec/dest/bin/index.js start \"\$@\" - " bash "$@" - else - export P2P_PORT="${P2P_PORT:-40400}" - # If the p2p broadcast port if provided, then map it to the p2p port on the container. - if [ -n "${P2P_BROADCAST_PORT:-}" ]; then - export P2P_BROADCAST_PORT - P2P_TCP_BROADCAST_MAPPING="$P2P_BROADCAST_PORT:$P2P_PORT" - P2P_UDP_BROADCAST_MAPPING="${P2P_TCP_BROADCAST_MAPPING}/udp" - - PORTS_TO_EXPOSE="${PORTS_TO_EXPOSE:-} $P2P_TCP_BROADCAST_MAPPING $P2P_UDP_BROADCAST_MAPPING" - else - P2P_TCP_LISTEN_MAPPING="$P2P_PORT:$P2P_PORT" - P2P_UDP_LISTEN_MAPPING="${P2P_TCP_LISTEN_MAPPING}/udp" - - PORTS_TO_EXPOSE="${PORTS_TO_EXPOSE:-} $P2P_TCP_LISTEN_MAPPING $P2P_UDP_LISTEN_MAPPING" - fi - - if [ -n "${ADMIN_PORT:-}" ]; then - export ADMIN_PORT - ADMIN_MAPPING="$ADMIN_PORT:$ADMIN_PORT" - PORTS_TO_EXPOSE="${PORTS_TO_EXPOSE:-} $ADMIN_MAPPING" - fi - - # unset PORTS_TO_EXPOSE if we're just running --help - if [ ! -z "${NO_PORT_FORWARDING:-}" ]; then - export PORTS_TO_EXPOSE="" - fi - - export DOCKER_RESTART_POLICY="${DOCKER_RESTART_POLICY:-no}" - export DOCKER_PULL_POLICY="${DOCKER_PULL_POLICY:-always}" - - - SLEEP=1 - MAX_SLEEP=60 - EXP_BACKOFF=2 - - RESTART_CODES="1 78 79" # ERROR, ROLLUP_UPGRADE, VERSION_UPGRADE - - if [ "$SUPERVISED" == "1" ]; then - echo "Starting supervised Aztec application..." - fi - set +e - while true; do - $(dirname $0)/.aztec-run aztec-start \ - node --no-warnings /usr/src/yarn-project/aztec/dest/bin/index.js start "$@" - - EXIT_CODE=$? - - if [ "$SUPERVISED" == "0" ]; then - exit $EXIT_CODE - fi - - SHOULD_RESTART=false - for code in $RESTART_CODES; do - if [ "$EXIT_CODE" -eq "$code" ]; then - SHOULD_RESTART=true - break - fi - done - - if [ "$SHOULD_RESTART" == "true" ]; then - echo "Exit code $EXIT_CODE requires restart" - SLEEP=$((SLEEP * EXP_BACKOFF)) - - if [ "$SLEEP" -ge "$MAX_SLEEP" ]; then - SLEEP="$MAX_SLEEP" - fi - - echo "Restarting in $SLEEP seconds..." - sleep $SLEEP - - else - exit $EXIT_CODE - fi - done - fi - ;; - flamegraph) - docker run -it \ - --entrypoint /usr/src/noir-projects/noir-contracts/scripts/flamegraph.sh \ - --env SERVE=${SERVE:-0} \ - $([ "${SERVE:-0}" == "1" ] && echo "-p 8000:8000" || echo "") \ - -v $(realpath $(dirname $2))/:/tmp \ - $DOCKER_REPO:$VERSION /tmp/$(basename $2) $3 - ;; - new) - shift - - # Parse arguments - parse_project_flags_and_build_nargo_args "new" "$@" - PARSE_RESULT=$? - - # Handle help request - if [ $PARSE_RESULT -eq 2 ]; then - cat << 'EOF' -Aztec New - Create a new Aztec Noir project in a new directory - -Usage: aztec new [OPTIONS] - -Arguments: - The path to save the new project - -Options: - --name Name of the package [default: package directory name] - --lib Use a library template - --bin Use a binary template - --contract Use a contract template [default] - -h, --help Print help - -This command creates a new Aztec Noir project using nargo and automatically -adds the Aztec.nr dependency to your Nargo.toml file. - -ENVIRONMENT VARIABLES: - AZTEC_PATH Path to Aztec installation (default: $HOME/.aztec) - VERSION Aztec version to use (default: from $AZTEC_PATH/default_version) - DOCKER_REPO Docker repository (default: aztecprotocol/aztec) - -EOF - exit 0 - fi - - # Check if PATH was provided - if [ -z "$PROJECT_PATH" ]; then - echo "Error: PATH argument is required" - echo "Usage: aztec new [OPTIONS] " - echo "Run 'aztec new --help' for more information" - exit 1 - fi - - validate_working_directory - - echo "Creating new Noir project at $PROJECT_PATH..." - - # Run nargo new via docker - run_nargo "${NARGO_ARGS[@]}" - - # Check if nargo new succeeded - if [ $? -ne 0 ]; then - >&2 echo "Project creation failed!" - exit 1 - fi - - # Setup Aztec contract project (add dependency and create template) - if [ "$IS_CONTRACT" = true ]; then - setup_aztec_contract_project "$PROJECT_PATH" - fi - ;; - init) - shift - - # Parse arguments - parse_project_flags_and_build_nargo_args "init" "$@" - PARSE_RESULT=$? - - # Handle help request - if [ $PARSE_RESULT -eq 2 ]; then - cat << 'EOF' -Aztec Init - Create a new Aztec Noir project in the current directory - -Usage: aztec init [OPTIONS] - -Options: - --name Name of the package [default: current directory name] - --lib Use a library template - --bin Use a binary template - --contract Use a contract template [default] - -h, --help Print help - -This command creates a new Aztec Noir project in the current directory using nargo -and automatically adds the Aztec.nr dependency to your Nargo.toml file. - -ENVIRONMENT VARIABLES: - AZTEC_PATH Path to Aztec installation (default: $HOME/.aztec) - VERSION Aztec version to use (default: from $AZTEC_PATH/default_version) - DOCKER_REPO Docker repository (default: aztecprotocol/aztec) - -EOF - exit 0 - fi - - validate_working_directory - - echo "Initializing Noir project..." - - # Run nargo init via docker - run_nargo "${NARGO_ARGS[@]}" - - # Check if nargo init succeeded - if [ $? -ne 0 ]; then - >&2 echo "Initialization failed!" - exit 1 - fi - - # Setup Aztec contract project (add dependency and create template) - if [ "$IS_CONTRACT" = true ]; then - setup_aztec_contract_project "." - fi - ;; - fmt) - shift - - validate_working_directory - - # Run nargo fmt - run_nargo fmt "$@" - ;; - check) - shift - - validate_working_directory - - # Run nargo check - run_nargo check "$@" - ;; - lsp) - # TODO: Drop this (and the corresponding docs in cli.ts) in case `nargo` is to be used natively (not containerized). - - # Special-case nargo's LSP command: - # 1. include --rm for cleanup - # 2. don't specify a user (run as root) - # 3. don't specify a workdir - validate_working_directory - - docker run --rm -i \ - --name aztec-nargo-lsp \ - -v $HOME:$HOME \ - -e HOME=$HOME \ - --entrypoint=/usr/src/noir/noir-repo/target/release/nargo \ - $DOCKER_REPO:$VERSION lsp - ;; - valkeys|valKeys|validator-keys) - # Special case for validator keys command to inject LEGACY_BLS_CLI environment variable - export ENV_VARS_TO_INJECT="LEGACY_BLS_CLI" - exec $(dirname $0)/.aztec-run aztec \ - node --no-warnings /usr/src/yarn-project/aztec/dest/bin/index.js "$@" - ;; - *) - export ENV_VARS_TO_INJECT="SECRET_KEY" - exec $(dirname $0)/.aztec-run aztec \ - node --no-warnings /usr/src/yarn-project/aztec/dest/bin/index.js "$@" - ;; -esac diff --git a/aztec-up/bin/aztec-install b/aztec-up/bin/aztec-install index b1227609c35f..9e21ec60d84a 100755 --- a/aztec-up/bin/aztec-install +++ b/aztec-up/bin/aztec-install @@ -9,22 +9,21 @@ p="\033[35m" # Purple r="\033[0m" # Reset bold="\033[1m" -export DOCKER_CLI_HINTS=false - if [ ! -t 0 ]; then NON_INTERACTIVE=1 else NON_INTERACTIVE=${NON_INTERACTIVE:-0} fi -AZTEC_PATH="${AZTEC_PATH:-$HOME/.aztec}" -BIN_PATH=${BIN_PATH:-$AZTEC_PATH/bin} +aztec_path=$HOME/.aztec +bin_path=$aztec_path/bin -# Define version if specified, otherwise set to "latest". -VERSION=${VERSION:-"latest"} -INSTALL_URI=${INSTALL_URI:-https://install.aztec.network} -if [ "$VERSION" != "latest" ]; then - INSTALL_URI+="/$VERSION" +# For testing you can override the INSTALL_URI to point to a file uri e.g. file:///home/user/aztec-packages/aztec-up/bin +if [ -z "${INSTALL_URI:-}" ]; then + INSTALL_URI=https://install.aztec.network + if [ -n "${VERSION:-}" ]; then + INSTALL_URI+="/$VERSION" + fi fi # Add color to the AZTEC ascii art. @@ -36,6 +35,7 @@ function print_colored() { } function title() { + clear echo print_colored " █████╗ ███████╗████████╗███████╗ ██████╗" print_colored "██╔══██╗╚══███╔╝╚══██╔══╝██╔════╝██╔════╝" @@ -45,43 +45,78 @@ function title() { print_colored "╚═╝ ╚═╝╚══════╝ ╚═╝ ╚══════╝ ╚═════╝" echo -e "${r}" echo -e "Welcome to the ${bold}${b}Aztec${r} installer! Your journey into blockchain privacy begins... ${bold}${p}now${r}." - echo -e "We provide a docker image that works on any modern system (specifically: x64 or ARM64)." - echo -e "Please ensure docker is installed for your platform: https://docs.docker.com/engine/install" echo - if [ "$(uname -s)" == "Darwin" ]; then - echo -e "${y}WARNING: For best performance we recommend adjusting your default docker settings:" - echo -e " - Under general, enable VirtioFS." - echo -e " - Under resources, set CPUs to ~80% your maximum." - echo -e " - Under resources, set Memory to ~80% your maximum." - echo -e "You may receive a warning about your home directory being mounted into a container." - echo -e "This is requested so we can read and write project files, that is all." - echo -e "${r}" - fi - echo -e "This will install the following scripts and update your PATH if necessary:" - echo -e " ${bold}${g}aztec${r} - a collection of tools to compile and test contracts, to launch subsystems and interact with the aztec network." - echo -e " ${bold}${g}aztec-up${r} - a tool to upgrade the aztec toolchain to the latest, or specific versions." - echo -e " ${bold}${g}aztec-wallet${r} - our minimalistic CLI wallet" + echo -e "This install script will install the following and update your PATH if necessary:" + echo -e " ${bold}${g}nargo${r} - the version of the noir programming language compatible with this version of aztec." + echo -e " ${bold}${g}bb${r} - the version of the barretenberg proving backend compatible with this version of aztec." + echo -e " ${bold}${g}aztec${r} - a collection of tools to compile and test contracts, to launch subsystems and interact with the aztec network." + echo -e " ${bold}${g}aztec-up${r} - a tool to upgrade the aztec toolchain to the latest, or specific versions." + echo -e " ${bold}${g}aztec-wallet${r} - our minimalistic CLI wallet" + echo + read -p "Do you wish to continue? (y/n) " -n 1 -r echo - read -p "Do you wish to continue? (y/n)" -n 1 -r echo if [[ ! $REPLY =~ ^[Yy]$ ]]; then - exit 0 + exit 1 fi } -# Print text in green. -function info { +function echo_green { echo -e "${g}$1${r}" } -# Print text in yellow. -function warn { +function echo_yellow { echo -e "${y}$1${r}" } +function echo_purple { + echo -e "${p}$1${r}" +} + +function dump_fail { + output=$(mktemp) + + set +e + ($1) &>$output + status=$? + set -e + + # 0 or SIGTERM considered a success. + if [ "$status" -ne 0 ] && [ "$status" -ne 143 ]; then + { + echo + echo -e "${y}command failed${r}: $1 (exit: $status)" + echo -e "${b}--- output ---${r}" + cat $output + } >&2 + fi + + rm $output + + return $status +} + +function check_toolchains { + # Check Node.js version. + local versions=$(curl -fsSL "$INSTALL_URI/versions") + local node_min_version=$(echo "$versions" | grep node | cut -d' ' -f2) + local node_installed_version=$(node --version | cut -d 'v' -f 2 || echo "none") + if [[ "$(printf '%s\n' "$node_min_version" "$node_installed_version" | sort -V | head -n1)" != "$node_min_version" ]]; then + echo "Minimum Node.js version $node_min_version not found (got $node_installed_version)." + echo "Installation: nvm install --lts && nvm alias default lts/*" + exit 1 + fi +} + +function install_file { + local dest="$aztec_path/$1" + curl -fsSL "$INSTALL_URI/$1" -o "$dest" + echo "Installed: $dest" +} + # Copy a file from the install source path to the bin path and make it executable. function install_bin { - local dest="$BIN_PATH/$1" + local dest="$bin_path/$1" curl -fsSL "$INSTALL_URI/$1" -o "$dest" chmod +x "$dest" echo "Installed: $dest" @@ -89,79 +124,128 @@ function install_bin { # Updates appropriate shell script to ensure the bin path is in the PATH. function update_path_env_var { - TARGET_DIR="${1}" + local target_dir=$bin_path # Check if the target directory is in the user's PATH. - if [[ ":$PATH:" != *":$TARGET_DIR:"* ]]; then - # Determine the user's shell. - SHELL_PROFILE="" - case $SHELL in - */bash) - SHELL_PROFILE="$HOME/.bash_profile" + if [[ ":$PATH:" == *":$target_dir:"* ]]; then + return + fi + + # Determine the user's shell. + local shell_profile="" + case $SHELL in + */bash) + shell_profile="$HOME/.bashrc" + ;; + */zsh) + shell_profile="$HOME/.zshrc" + ;; + *) + echo "Unsupported shell: $SHELL" + return + ;; + esac + + # Add the target directory to the user's PATH in their profile. + echo "export PATH=\"\$PATH:$target_dir\"" >>"$shell_profile" +} + +function install_jq { + set -euo pipefail + url_base="https://github.com/jqlang/jq/releases/download/jq-1.8.1" + arch="$(uname -m)" + os="$(uname -s)" + + case "$os" in + Linux) + case "$arch" in + x86_64|amd64) bin="jq-linux-amd64" ;; + aarch64|arm64) bin="jq-linux-arm64" ;; + *) echo "unsupported arch"; return 1 ;; + esac ;; - */zsh) - SHELL_PROFILE="$HOME/.zshrc" + Darwin) + case "$arch" in + x86_64|amd64) bin="jq-macos-amd64" ;; + aarch64|arm64) bin="jq-macos-arm64" ;; + *) echo "unsupported arch"; return 1 ;; + esac ;; - # Add other shells as needed *) - echo "Unsupported shell: $SHELL" - return + echo "unsupported OS" + return 1 ;; - esac + esac - if [ "$NON_INTERACTIVE" -eq 0 ]; then - # Inform the user about the change and ask for confirmation - warn "The directory $TARGET_DIR is not in your PATH." - read -p "Add it to $SHELL_PROFILE to make the aztec binaries accessible? (y/n)" -n 1 -r - echo - if [[ ! $REPLY =~ ^[Yy]$ ]]; then - warn "Skipped updating PATH. You might need to add $TARGET_DIR to your PATH manually to use the binary." - return - fi - fi - - # Add the target directory to the user's PATH in their profile. - echo "export PATH=\"\$PATH:$TARGET_DIR\"" >>"$SHELL_PROFILE" - - if [ "$NON_INTERACTIVE" -eq 0 ] && [ "${NO_NEW_SHELL:-0}" -eq 0 ]; then - info "Done! Starting fresh shell..." - exec $SHELL - fi - fi + curl -Ls "$url_base/$bin" -o $bin_path/jq || return 1 + chmod +x $bin_path/jq } -# Show title if we're in a terminal. -[ "$NON_INTERACTIVE" -eq 0 ] && title - -# Check if Docker is available. -if ! command -v docker &>/dev/null; then - warn "Docker is not installed. Please install Docker and try again." - exit 1 -fi - -# Check if Docker is running. -if ! docker info &>/dev/null; then - warn "Docker is not running. Please start Docker and try again." - exit 1 -fi +function install_aztec_up { + set -euo pipefail + mkdir -p $bin_path + rm -f $bin_path/* + install_bin aztec-up + install_file versions + update_path_env_var +} -mkdir -p "$AZTEC_PATH" -TMP_VERSION_FILE="$(mktemp)" -echo "$VERSION" > "$TMP_VERSION_FILE" +function install_noir { + set -euo pipefail + curl -Ls https://raw.githubusercontent.com/noir-lang/noirup/refs/heads/main/install | bash + $HOME/.nargo/bin/noirup -v $(cat $aztec_path/versions | grep noir | cut -d' ' -f2) +} -# Pull the aztec container. -if [ -z "${SKIP_PULL:-}" ]; then - info "Pulling aztec version $VERSION..." - docker pull aztecprotocol/aztec:$VERSION -fi +function install_foundry { + set -euo pipefail + curl -L https://foundry.paradigm.xyz | bash + $HOME/.foundry/bin/foundryup -i $(cat $aztec_path/versions | grep foundry | cut -d' ' -f2) +} -info "Installing scripts in $BIN_PATH..." -rm -rf $BIN_PATH && mkdir -p $BIN_PATH -install_bin .aztec-run -install_bin aztec -install_bin aztec-up -install_bin aztec-wallet -mv "$TMP_VERSION_FILE" "$AZTEC_PATH/default_version" +function install_aztec_packages { + set -euo pipefail + local version=$(cat $aztec_path/versions | grep aztec | cut -d' ' -f2) + npm i -g @aztec/aztec@$version @aztec/cli-wallet@$version @aztec/bb.js@$version +} -update_path_env_var $BIN_PATH +function main { + # Show title if we're in a terminal. + [ "$NON_INTERACTIVE" -eq 0 ] && title + + check_toolchains + + # Install aztec-up + echo -n "Installing aztec-up... " + dump_fail install_aztec_up + echo_green "done." + + # Install jq + echo -n "Installing jq... " + dump_fail install_jq + echo_green "done." + + # Install noir + echo -n "Installing nargo... " + dump_fail install_noir + echo_green "done." + + # Install foundry + echo -n "Installing foundry... " + dump_fail install_foundry + echo_green "done." + + # Install aztec + echo -n "Installing aztec packages... " + dump_fail install_aztec_packages + echo_green "done." + + if [ "$NON_INTERACTIVE" -eq 0 ] && [ "${NO_NEW_SHELL:-0}" -eq 0 ]; then + echo_green "Done! Starting fresh shell..." + exec $SHELL + else + echo + echo -e "${g}Done!${r} You'll need to start a fresh shell to see PATH updates." + fi +} -info "Done!" +cmd="${1:-main}"; +$cmd diff --git a/aztec-up/bin/aztec-wallet b/aztec-up/bin/aztec-wallet deleted file mode 100755 index f66b6121a8ec..000000000000 --- a/aztec-up/bin/aztec-wallet +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -export AZTEC_PATH="${AZTEC_PATH:-$HOME/.aztec}" -DEFAULT_VERSION=$(cat "$AZTEC_PATH/default_version" 2> /dev/null || echo latest) -export VERSION="${VERSION:-$DEFAULT_VERSION}" -export DOCKER_REPO="${DOCKER_REPO:-"aztecprotocol/aztec"}" - -export ENV_VARS_TO_INJECT="SSH_AUTH_SOCK PXE_PROVER LOG_LEVEL" - -# Appends 8 char hex to avoid container name clashes -export CONTAINER_NAME=aztec-wallet-$(printf "%08x" $((RANDOM * RANDOM))) - -export FORWARD_SSH_AGENT=1 - -exec $(dirname $0)/.aztec-run aztec-wallet /usr/src/yarn-project/cli-wallet/wallet-entrypoint.sh "$@" diff --git a/aztec-up/bootstrap.sh b/aztec-up/bootstrap.sh index fdc5542dbe8f..3388da771e31 100755 --- a/aztec-up/bootstrap.sh +++ b/aztec-up/bootstrap.sh @@ -3,28 +3,84 @@ source $(git rev-parse --show-toplevel)/ci3/source_bootstrap hash=$(hash_str $(cache_content_hash ^aztec-up/) $(../yarn-project/bootstrap.sh hash)) -function build_dind_image { - echo_header "aztec-up build test image" - denoise "docker build -t aztecprotocol/dind ." -} +function build { + # Create versions.json so we know what to install. + ../bootstrap.sh versions > ./bin/versions + echo "Versions:" + cat ./bin/versions + echo + + # Create Verdaccio config. + cat > /tmp/verdaccio-config.yaml < /tmp/htpasswd + + if ! command -v verdaccio &>/dev/null; then + npm i -g verdaccio + fi + + rm -rf verdaccio-storage + verdaccio --config /tmp/verdaccio-config.yaml --listen 4873 &>/dev/null & + verdaccio_pid=$! + trap 'kill $verdaccio_pid &>/dev/null || true' EXIT + while ! nc -z localhost 4873 &>/dev/null; do sleep 1; done + + # Configure local npm registry. + export npm_config_registry="http://localhost:4873" + export npm_config_userconfig=$(mktemp) + cat > "$npm_config_userconfig" <<'EOF' +max_body_size=1000mb +registry=http://localhost:4873/ +//localhost:4873/:username=testuser +//localhost:4873/:_password=dGVzdHBhc3M= +//localhost:4873/:email=test@example.com +//localhost:4873/:always-auth=true +EOF + + # Deploy all npm packages to local registry. + version=$(cat ./bin/versions | grep aztec | cut -d' ' -f2) + echo "Deploying packages to local npm registry (version: $version)..." + { + echo $root/barretenberg/ts + $root/noir/bootstrap.sh get_projects + $root/yarn-project/bootstrap.sh get_projects + } | parallel --tag -k --line-buffer --halt now,fail=1 "dump_fail 'cd {} && deploy_npm latest $version' >/dev/null" + + # Prime the verdaccio cache by installing the packages we'll use in tests. + # This fetches all transitive dependencies from npmjs and caches them locally. + # Use --prefix to avoid modifying the host system's global npm packages. + echo "Priming verdaccio cache with all dependencies..." + npm i -g --prefix /tmp/npm-prime @aztec/aztec@$version @aztec/cli-wallet@$version @aztec/bb.js@$version + rm -rf /tmp/npm-prime -function update_manifest { - # We update the manifest to point to the latest arch specific images, pushed above. - local image=aztecprotocol/dind:latest - # Remove any old local manifest if present. - docker manifest rm $image || true - # Create new manifest and push. - docker manifest create $image \ - --amend aztecprotocol/dind:latest-amd64 \ - --amend aztecprotocol/dind:latest-arm64 - docker manifest push $image + docker build -t aztecprotocol/aztec-release-test . } function test_cmds { - echo "$hash aztec-up/scripts/run_test.sh amm_flow" - echo "$hash aztec-up/scripts/run_test.sh bridge_and_claim" - echo "$hash aztec-up/scripts/run_test.sh basic_install" - echo "$hash aztec-up/scripts/run_test.sh counter_contract" + for test in amm_flow bridge_and_claim basic_install counter_contract; do + echo "$hash:TIMEOUT=15m aztec-up/scripts/run_test.sh $test" + done } function test { @@ -35,21 +91,23 @@ function test { function release { echo_header "aztec-up release" local version=${REF_NAME#v} + local source_dir=./bin # Always create a version directory and upload files there. - do_or_dryrun aws s3 sync ./bin "s3://install.aztec.network/$version/" + do_or_dryrun aws s3 sync $source_dir "s3://install.aztec.network/$version/" if [[ $(dist_tag) != "latest" ]]; then # Also upload to a $dist_tag directory, if not latest. - do_or_dryrun aws s3 sync ./bin "s3://install.aztec.network/$(dist_tag)/" + do_or_dryrun aws s3 sync $source_dir "s3://install.aztec.network/$(dist_tag)/" else # Upload new version to root. - do_or_dryrun aws s3 sync ./bin s3://install.aztec.network/ + do_or_dryrun aws s3 sync $source_dir s3://install.aztec.network/ fi } case "$cmd" in "") + build ;; *) default_cmd_handler "$@" diff --git a/aztec-up/scripts/run_isolated_test.sh b/aztec-up/scripts/run_isolated_test.sh new file mode 100755 index 000000000000..85635f319c03 --- /dev/null +++ b/aztec-up/scripts/run_isolated_test.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Check we're in the test container. +if [ ! -f /aztec_release_test_container ]; then + echo "Not running inside the aztec release test container. Exiting." + exit 1 +fi + +if [ "$(whoami)" != "ubuntu" ]; then + echo "Not running as ubuntu. Exiting." + exit 1 +fi + +# Install required node version. +curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash +source ~/.nvm/nvm.sh +node_version=$(grep node aztec-packages/aztec-up/bin/versions | cut -d' ' -f2) +echo $node_version +nvm install $node_version +nvm alias default $node_version + +# Create Verdaccio config (offline mode - all packages pre-cached, no proxy to npmjs). +cat > /tmp/verdaccio-config.yaml < /tmp/htpasswd + +# Start verdaccio local npm registry. +npm i -g verdaccio +verdaccio --config /tmp/verdaccio-config.yaml --listen 0.0.0.0:4873 &>/dev/null & +while ! nc -z localhost 4873 &>/dev/null; do sleep 1; done + +# Configure npm client to use local registry. +export npm_config_registry="http://localhost:4873" +export npm_config_userconfig=$(mktemp) +cat > "$npm_config_userconfig" <<'EOF' +max_body_size=1000mb +registry=http://localhost:4873/ +//localhost:4873/:username=testuser +//localhost:4873/:_password=dGVzdHBhc3M= +//localhost:4873/:email=test@example.com +//localhost:4873/:always-auth=true +EOF + +# Install aztec. +export NO_NEW_SHELL=1 +export INSTALL_URI=file:///home/ubuntu/aztec-packages/aztec-up/bin +if [ -t 0 ]; then + bash_args="-i" +else + export NON_INTERACTIVE=1 +fi +bash ${bash_args:-} <(curl -s $INSTALL_URI/aztec-install) + +# Run test. Force interactive to parse .bashrc. +bash -i aztec-packages/aztec-up/test/$1.sh diff --git a/aztec-up/scripts/run_test.sh b/aztec-up/scripts/run_test.sh index c4625e9d0a6b..601eeff6b621 100755 --- a/aztec-up/scripts/run_test.sh +++ b/aztec-up/scripts/run_test.sh @@ -1,33 +1,14 @@ #!/usr/bin/env bash -set -euo pipefail +source $(git rev-parse --show-toplevel)/ci3/source -trap 'docker rm -f $1 &>/dev/null' SIGINT SIGTERM EXIT -docker rm -f $1 &>/dev/null || true -docker pull aztecprotocol/dind -docker run --rm \ - -d \ - --privileged \ - --name $1 \ - -v$(git rev-parse --show-toplevel):/home/ubuntu/aztec-packages:ro \ - -v$HOME/.bb-crs:/home/ubuntu/.bb-crs \ - --mount type=tmpfs,target=/var/lib/docker,tmpfs-size=4g \ - aztecprotocol/dind \ - bash -c " - tail -f /dev/null - " >/dev/null +name=$1 -docker save aztecprotocol/aztec:latest | docker exec -i $1 \ - bash -c " - echo 'Starting docker...' - while ! docker info &>/dev/null; do - /usr/local/share/docker-init.sh &>/dev/null - sleep 3 - cat /tmp/dockerd.log - done - chmod 777 /var/run/docker.sock - echo 'Loading image...' - docker load - " +function cleanup { + docker rm -f $name &>/dev/null || true +} + +trap 'cleanup' SIGINT SIGTERM EXIT +cleanup # If we're running in a terminal, run the container interactively. # Drop into a shell if the test fails. @@ -36,13 +17,18 @@ if [ -t 0 ]; then fail_shell="|| exec bash" fi -docker exec ${args:-} -w/home/ubuntu --user ubuntu:ubuntu $1 \ +echo "Running test $name..." +docker run --rm ${args:-} \ + -e FORCE_COLOR=1 \ + --name $name \ + --tmpfs /home/ubuntu/.nvm:exec,size=4g \ + --tmpfs /home/ubuntu/.npm:exec,size=2g \ + -v$(git rev-parse --show-toplevel):/home/ubuntu/aztec-packages:ro \ + -v$HOME/.bb-crs:/home/ubuntu/.bb-crs \ + -w/home/ubuntu \ + --user ubuntu:ubuntu \ + aztecprotocol/aztec-release-test \ bash -c " - ./aztec-packages/aztec-up/test/$1.sh ${fail_shell:-} - code=\${PIPESTATUS[0]} - if [ \$code -ne 0 ]; then - echo 'Dumping docker logs...' - cat /tmp/dockerd.log - fi - exit \$code - " + aztec-packages/aztec-up/scripts/run_isolated_test.sh $name ${fail_shell:-} + " & +wait $! diff --git a/aztec-up/test/amm_flow.sh b/aztec-up/test/amm_flow.sh index 02c1f999a5e1..d58b05276f70 100755 --- a/aztec-up/test/amm_flow.sh +++ b/aztec-up/test/amm_flow.sh @@ -1,36 +1,10 @@ #!/usr/bin/env bash -set -eu - -# Check we're in the test container. -if [ ! -f /aztec_release_test_container ]; then - echo "Not running inside the aztec release test container. Exiting." - exit 1 -fi - -if [ "$(whoami)" != "ubuntu" ]; then - echo "Not running as ubuntu. Exiting." - exit 1 -fi - -export SKIP_PULL=1 -export NO_NEW_SHELL=1 -export INSTALL_URI=file:///home/ubuntu/aztec-packages/aztec-up/bin - -if [ -t 0 ]; then - bash_args="-i" -else - export NON_INTERACTIVE=1 -fi - -bash ${bash_args:-} <(curl -s $INSTALL_URI/aztec-install) - -# We can't create a new shell for this test, so just re-source our modified .bashrc to get updated PATH. -PS1=" " source ~/.bash_profile +set -euo pipefail # Start local network and wait for port to open. aztec start --local-network & -local_network=$! -trap 'echo "Sending kill to pid $local_network"; kill $local_network &>/dev/null; wait $local_network' EXIT +local_network_pid=$! +trap 'set +e; kill $local_network_pid &>/dev/null; wait $local_network_pid' EXIT while ! curl -fs localhost:8080/status &>/dev/null; do sleep 1; done canonical_sponsored_fpc_address=$(aztec \ diff --git a/aztec-up/test/basic_install.sh b/aztec-up/test/basic_install.sh index 25126a602aaa..b7973431f612 100755 --- a/aztec-up/test/basic_install.sh +++ b/aztec-up/test/basic_install.sh @@ -1,46 +1,12 @@ #!/usr/bin/env bash -set -eu +set -euo pipefail -# Check we're in the test container. -if [ ! -f /aztec_release_test_container ]; then - echo "Not running inside the aztec release test container. Exiting." - exit 1 -fi - -if [ "$(whoami)" != "ubuntu" ]; then - echo "Not running as ubuntu. Exiting." - exit 1 -fi - -export SKIP_PULL=1 -export NO_NEW_SHELL=1 -export INSTALL_URI=file:///home/ubuntu/aztec-packages/aztec-up/bin - -if [ -t 0 ]; then - bash_args="-i" -else - export NON_INTERACTIVE=1 -fi - -bash ${bash_args:-} <(curl -s $INSTALL_URI/aztec-install) - -# We can't create a new shell for this test, so just re-source our modified .bashrc to get updated PATH. -PS1=" " source ~/.bash_profile - -# Sanity check lsp. -echo "Checking LSP..." -echo -ne 'Content-Length: 100\r\n\r\n{"jsonrpc": "2.0", "id": 1, "method": "initialize", "params": {"rootUri": null, "capabilities": {}}}' \ - | aztec lsp \ - | grep -q '"jsonrpc":"2.0"' -echo "LSP check passed." - -# aztec -V -# aztec-wallet -V - -# aztec-up - -# aztec -V -# aztec-wallet -V +echo +echo "nargo version: $(nargo --version | head -1 | cut -d' ' -f4)" +echo "bb version: $(bb --version)" +echo "aztec version: $(aztec --version)" +echo "aztec-wallet version: $(aztec-wallet --version)" +echo export LOG_LEVEL=silent export PXE_PROVER=none @@ -48,7 +14,7 @@ export PXE_PROVER=none # Start local network and wait for port to open. aztec start --local-network & local_network_pid=$! -trap 'echo "Sending kill to pid $local_network_pid"; kill $local_network_pid &>/dev/null; wait $local_network_pid' EXIT +trap 'set +e; kill $local_network_pid &>/dev/null; wait $local_network_pid' EXIT while ! curl -fs localhost:8080/status &>/dev/null; do sleep 1; done # Execute wallet commands as per: https://docs.aztec.network/guides/getting_started diff --git a/aztec-up/test/bridge_and_claim.sh b/aztec-up/test/bridge_and_claim.sh index 15aa7326bad9..b073daadb3c8 100755 --- a/aztec-up/test/bridge_and_claim.sh +++ b/aztec-up/test/bridge_and_claim.sh @@ -1,36 +1,10 @@ #!/usr/bin/env bash -set -eu - -# Check we're in the test container. -if [ ! -f /aztec_release_test_container ]; then - echo "Not running inside the aztec release test container. Exiting." - exit 1 -fi - -if [ "$(whoami)" != "ubuntu" ]; then - echo "Not running as ubuntu. Exiting." - exit 1 -fi - -export SKIP_PULL=1 -export NO_NEW_SHELL=1 -export INSTALL_URI=file:///home/ubuntu/aztec-packages/aztec-up/bin - -if [ -t 0 ]; then - bash_args="-i" -else - export NON_INTERACTIVE=1 -fi - -bash ${bash_args:-} <(curl -s $INSTALL_URI/aztec-install) - -# We can't create a new shell for this test, so just re-source our modified .bashrc to get updated PATH. -PS1=" " source ~/.bash_profile +set -euo pipefail # Start local network and wait for port to open. aztec start --local-network & -local_network=$! -trap 'echo "Sending kill to pid $local_network"; kill $local_network &>/dev/null; wait $local_network' EXIT +local_network_pid=$! +trap 'set +e; kill $local_network_pid &>/dev/null; wait $local_network_pid' EXIT while ! curl -fs localhost:8080/status &>/dev/null; do sleep 1; done # Execute wallet commands as per: https://docs.aztec.network/guides/getting_started diff --git a/aztec-up/test/counter_contract.sh b/aztec-up/test/counter_contract.sh index f0cd6282d494..28f337ec3256 100755 --- a/aztec-up/test/counter_contract.sh +++ b/aztec-up/test/counter_contract.sh @@ -1,44 +1,10 @@ #!/usr/bin/env bash set -euo pipefail -# Check we're in the test container. -if [ ! -f /aztec_release_test_container ]; then - echo "Not running inside the aztec release test container. Exiting." - exit 1 -fi - -if [ "$(whoami)" != "ubuntu" ]; then - echo "Not running as ubuntu. Exiting." - exit 1 -fi - -export SKIP_PULL=1 -export NO_NEW_SHELL=1 -export INSTALL_URI=file:///home/ubuntu/aztec-packages/aztec-up/bin - -if [ -t 0 ]; then - bash_args="-i" -else - export NON_INTERACTIVE=1 -fi - -bash ${bash_args:-} <(curl -s $INSTALL_URI/aztec-install) - -# We can't create a new shell for this test, so just re-source our modified .bashrc to get updated PATH. -set +eu -PS1=" " source ~/.bash_profile -set -eu - export LOG_LEVEL=silent -# Start local network and wait for port to open. -# aztec start --local-network & -# local_network_pid=$! -# trap 'echo "Sending kill to pid $local_network_pid"; kill $local_network_pid &>/dev/null; wait $local_network_pid' EXIT -# while ! curl -fs host.docker.internal:8080/status &>/dev/null; do sleep 1; done - # Execute commands as per: https://docs.aztec.network/tutorials/codealong/contract_tutorials/counter_contract -aztec new --contract counter_contract +aztec new counter_contract if [ ! -f counter_contract/Nargo.toml ] || [ ! -f counter_contract/src/main.nr ]; then echo "Failed to create contract." exit 1 diff --git a/bootstrap.sh b/bootstrap.sh index 9b2275b9de6e..a477a61638c9 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -149,6 +149,22 @@ function check_toolchains { done } +function versions { + if semver check $REF_NAME; then + echo "aztec: ${REF_NAME#v}" + else + echo "aztec: $(jq -r '."."' .release-please-manifest.json | tr -d v)" + fi + echo "noir: $(git -C noir/noir-repo describe --tags --exact-match HEAD)" + echo "foundry: $(anvil --version | head -n1 | sed -E 's/anvil Version: ([0-9.]+).*/\1/')" + echo "node: $(node --version | cut -d 'v' -f 2)" + echo "cmake: $(cmake --version | head -n1 | cut -d' ' -f3)" + echo "clang: $(clang++-20 --version | head -n1 | cut -d' ' -f4)" + echo "zig: $(zig version)" + echo "rustc: $(rustc --version | cut -d' ' -f2)" + echo "wasi-sdk: $(cat /opt/wasi-sdk/VERSION 2> /dev/null | head -n1)" +} + # Install pre-commit git hooks. function install_hooks { hooks_dir=$(git rev-parse --git-path hooks) @@ -195,7 +211,7 @@ function sort_by_cpus { function test_cmds { if [ "$#" -eq 0 ]; then # Ordered with longest running first, to ensure they get scheduled earliest. - set -- yarn-project/end-to-end aztec-up yarn-project noir-projects boxes playground barretenberg l1-contracts docs ci3 + set -- yarn-project/end-to-end aztec-up yarn-project noir-projects boxes playground barretenberg l1-contracts docs ci3 release-image fi parallel -k --line-buffer './{}/bootstrap.sh test_cmds' ::: $@ | filter_test_cmds | sort_by_cpus } diff --git a/boxes/.gitignore b/boxes/.gitignore index c5cccc475bc7..441566161bc8 100644 --- a/boxes/.gitignore +++ b/boxes/.gitignore @@ -2,5 +2,3 @@ !.yarn/releases node_modules -dest -boxes/**/contracts/target diff --git a/boxes/bin.js b/boxes/bin.js deleted file mode 100755 index 22196dbfbd0c..000000000000 --- a/boxes/bin.js +++ /dev/null @@ -1,124 +0,0 @@ -#!/usr/bin/env node -import { Command } from "commander"; -const program = new Command(); -import { chooseProject } from "./scripts/steps/chooseBox.js"; -import axios from "axios"; -import pino from "pino"; -import pretty from "pino-pretty"; -import ora from "ora"; -import { AZTEC_REPO } from "./scripts/config.js"; -import { init } from "./scripts/init.js"; - -const getLatestStable = async () => { - const { data } = await axios.get( - `https://api.github.com/repos/AztecProtocol/aztec-packages/releases`, - ); - return data[0].tag_name.replace(/^v/, "").replace(/-.*$/, ""); -}; - -program - .option("-v, --version ", "a version number or master tag") - .option("-d, --debug", "output extra debugging") - .option("-gh, --github_token ", "a github token") - .hook("preSubcommand", async (thisCommand) => { - const { debug, github_token, version } = thisCommand.opts(); - const axiosOpts = { - timeout: 5000, - headers: github_token ? { Authorization: `token ${github_token}` } : {}, - }; - - const prettyOpts = { - sync: true, - colorize: true, - include: debug ? "time" : "", - customLevels: "success:80", - customColors: "success:bgGreen", - }; - - const prettyStream = pretty(prettyOpts); - const logger = pino( - { - customLevels: { - success: 80, - }, - level: debug ? "debug" : "info", - }, - prettyStream, - ); - - global.debug = (msg) => logger.debug(msg); - global.info = (msg) => logger.info(msg); - global.success = (msg) => logger.success(msg); - - global.warn = (msg) => logger.warn(msg); - global.error = (msg) => logger.error(msg); - - global.github = async ({ path, raw = false }) => { - try { - const url = raw - ? `https://raw.githubusercontent.com/${AZTEC_REPO}/${path}` - : `https://api.github.com/repos/${AZTEC_REPO}/contents/${path}`; - const { data } = await axios.get(url, axiosOpts); - global.debug(data); - return data; - } catch (e) { - global.error(e); - } - }; - - // versioning is confusing here because "latest" and "master" point to the same thing at times - // so let's clarify a bit: - // - // if the user has set a version (ex. "master" or "0.23.0"), use that - // otherwise use the stable release (ex. 0.24.0) - global.latestStable = await getLatestStable(); - global.version = version || global.latestStable; - - // if the user has set a semver version (matches the regex), fetch that tag (i.e. v0.23.0) - // otherwise use the version as the tag - global.tag = global.version.match(/^\d+\.\d+\.\d+$/) - ? `v${global.version}` - : global.version; - - global.debug(`Version: ${global.version}`); - global.debug(`Tag: ${global.tag}`); - global.debug(`LatestStable: ${global.latestStable}`); - - global.spinner = ora({ color: "blue" }); - }); - -program - .command("init") - .description("Bootstrap an empty Aztec contract") - .argument("[folder]", "optional folder to init your project into", ".") - .action(async (folder) => { - await init(folder); - }); - -program - .command("new", { isDefault: true }) - .description("An Aztec project with a built-in development network") - .option( - "-t, --project-type ", - "the type of the project to clone ('app' or 'contract')", - ) - .option( - "-n, --project-name ", - "the name of the project to clone", - ) - .action(async (options) => { - // this is some bad code, but it's def fun - // I'm matching all keys started with project and - // then using modulo to say "if one is defined, two must be defined" - const optsKeys = Object.keys(options).filter((e) => /project*/g.test(e)); - if (optsKeys.length % 2) { - throw Error("You must define both the project type and the project name"); - } - - const { projectType, projectName } = options; - - // // STEP 1: Choose the boilerplate - await chooseProject({ projectType, projectName }); - }); - -program.parse(); diff --git a/boxes/bin.test.js b/boxes/bin.test.js deleted file mode 100644 index 09d717ef8d2d..000000000000 --- a/boxes/bin.test.js +++ /dev/null @@ -1,91 +0,0 @@ -import { parse } from "@iarna/toml"; -import axios from "axios"; -import { execSync } from "child_process"; -import fs from "fs/promises"; -import path from "path"; -import { describe, test, expect, beforeAll } from "vitest"; - -const getLatestStable = async () => { - try { - const { data } = await axios.get( - `https://api.github.com/repos/AztecProtocol/aztec-packages/releases`, - ); - return data[0].tag_name.split("-v")[1]; - } catch (error) { - console.error("Error fetching latest stable version:", error); - return; - } -}; - -const version = await getLatestStable(); -const tag = version.match(/^\d+\.\d+\.\d+$/) - ? `v${version}` - : version; - -describe("Token contract", () => { - beforeAll(() => { - try { - execSync("npx . new -d -t contract -n token_contract", { - stdio: "inherit", - }); - } catch (error) { - console.error("Error executing command:", error); - } - }); - - test("Paths were updated correctly", async () => { - const replaces = []; - const findAndReplace = async (dir, prefix) => { - const files = await fs.readdir(dir, { - withFileTypes: true, - }); - files.forEach(async (file) => { - const filePath = path.join(dir, file.name); - if (file.isDirectory()) { - findAndReplace(filePath, prefix); // Recursively search subdirectories - } else if (file.name === "Nargo.toml") { - replaces.push( - new Promise(async (resolve, reject) => { - let content = parse(await fs.readFile(filePath, "utf8")); - if (!content.dependencies) return; - resolve( - Object.keys(content.dependencies) - .filter((dep) => dep.match("@aztec")) - .every( - (dep) => - content.dependencies[dep] === - JSON.stringify({ - git: `https://github.com/${AZTEC_REPO}/`, - tag, - directory: `${prefix}${directory}`, - }), - ), - ); - }), - ); - } else if (file.name === "package.json") { - replaces.push( - new Promise(async (resolve, reject) => { - let content = JSON.parse(await fs.readFile(filePath, "utf8")); - if (!content.dependencies) return; - resolve( - Object.keys(content.dependencies) - .filter((deps) => deps.match("@aztec")) - // "master" actually means "latest" for the npm release - .every( - (dep) => - content.dependencies[dep] === - `${version === "master" ? "latest" : `^${version}`}`, - ), - ); - }), - ); - } - }); - }; - - await findAndReplace(path.resolve("./token_contract"), ""); - const res = await Promise.all(replaces); - expect(res).toEqual([true, true]); - }); -}); diff --git a/boxes/bootstrap.sh b/boxes/bootstrap.sh index a2d8ba23ebf8..3a873f47ddbd 100755 --- a/boxes/bootstrap.sh +++ b/boxes/bootstrap.sh @@ -1,9 +1,9 @@ #!/usr/bin/env bash source $(git rev-parse --show-toplevel)/ci3/source_bootstrap -# We set container name to "" to avoid container name collisions when building boxes -export CONTAINER_NAME="" -export AZTEC=$PWD/../aztec-up/bin/aztec +export AZTEC=$(realpath ../yarn-project/aztec/scripts/aztec.sh) +export BB=$(realpath ../barretenberg/cpp/build/bin/bb) +export NARGO=$(realpath ../noir/noir-repo/target/release/nargo) hash=$(hash_str \ $(../noir/bootstrap.sh hash) \ @@ -12,6 +12,15 @@ hash=$(hash_str \ ../{avm-transpiler,noir-projects,l1-contracts,yarn-project}/.rebuild_patterns \ ../barretenberg/*/.rebuild_patterns)) +function build_box { + cd boxes/$1 + yarn build +} + +function test_box { + CPUS=4 docker_isolate "./scripts/run_test.sh ${1:-vanilla} ${2:-chromium}" +} + function build { echo_header "boxes build" npm_install_deps @@ -28,21 +37,9 @@ function test { } function test_cmds { - # Until we get these boxes stable again - just testing on chromium. - local browser=chromium for box in react vite vanilla; do - echo "$hash:ONLY_TERM_PARENT=1 BOX=$box BROWSER=$browser run_compose_test $box-$browser box boxes" + echo "$hash:ISOLATE=1:NET=1:CPUS=4 ./boxes/scripts/run_test.sh $box chromium" done - - # for browser in chromium webkit firefox; do - # for box in react vite; do - # echo "$hash:ONLY_TERM_PARENT=1 BOX=$box BROWSER=$browser run_compose_test $box-$browser box boxes" - # done - # done - - # # The vanilla app works with deployed contracts configured during the build. - # # To avoid building the app three times, we test it with one sandbox and multiple browsers. - # echo "$hash:ONLY_TERM_PARENT=1 BOX=vanilla BROWSER=* run_compose_test vanilla-all-browsers box boxes" } # First argument is a branch name (e.g. master, or the latest version e.g. 1.2.3) to push to the head of. diff --git a/boxes/boxes/react/.gitignore b/boxes/boxes/react/.gitignore index 1d346fb05302..352250a3dba1 100644 --- a/boxes/boxes/react/.gitignore +++ b/boxes/boxes/react/.gitignore @@ -11,3 +11,4 @@ boxes/src/contracts/log /blob-report/ /playwright/.cache/ codegenCache.json +src/contracts/target diff --git a/boxes/boxes/react/package.json b/boxes/boxes/react/package.json index e75a7e367ab7..691fb2ec9621 100644 --- a/boxes/boxes/react/package.json +++ b/boxes/boxes/react/package.json @@ -6,15 +6,12 @@ "type": "module", "main": "./dist/index.js", "scripts": { - "compile": "cd src/contracts && CONTAINER_NAME=\"aztec-react-box\" ${AZTEC:-aztec} compile --silence-warnings", - "codegen": "CONTAINER_NAME=\"aztec-react-box\" ${AZTEC:-aztec} codegen src/contracts/target -o artifacts", + "build": "yarn clean && yarn compile && yarn codegen && webpack --mode production", "clean": "rm -rf ./dist .tsbuildinfo ./codegenCache.json ./artifacts ./src/contracts/target", - "prep": "yarn clean && yarn compile && yarn codegen", - "dev": "yarn prep && webpack serve --mode development", - "build": "yarn prep && webpack", + "compile": "cd src/contracts && ${AZTEC:-aztec} compile --silence-warnings", + "codegen": "${AZTEC:-aztec} codegen src/contracts/target -o artifacts", "serve": "webpack serve --no-open --mode development --watch-files ./src/*", - "formatting": "prettier --check ./src && eslint ./src", - "formatting:fix": "prettier -w ./src", + "lint": "prettier --check ./src && eslint ./src", "test": "playwright test" }, "jest": { diff --git a/boxes/boxes/react/playwright.config.ts b/boxes/boxes/react/playwright.config.ts index 77983540a10e..d1aaa40f93d2 100644 --- a/boxes/boxes/react/playwright.config.ts +++ b/boxes/boxes/react/playwright.config.ts @@ -1,33 +1,11 @@ import { defineConfig, devices } from '@playwright/test'; export default defineConfig({ - testDir: './tests', - testMatch: '**.spec.ts', - fullyParallel: true, - workers: process.env.CI ? 1 : 3, - reporter: 'list', - use: { - baseURL: 'http://127.0.0.1:5173', - trace: 'on-first-retry', - screenshot: 'only-on-failure', - video: 'on-first-retry', - }, - expect: { - timeout: 90000, - }, + expect: { timeout: 90000 }, projects: [ - { - name: 'chromium', - use: { ...devices['Desktop Chrome'] }, - }, - { - name: 'firefox', - use: { ...devices['Desktop Firefox'] }, - }, - { - name: 'webkit', - use: { ...devices['Desktop Safari'] }, - }, + { name: 'chromium', use: { ...devices['Desktop Chrome'] } }, + { name: 'firefox', use: { ...devices['Desktop Firefox'] } }, + { name: 'webkit', use: { ...devices['Desktop Safari'] } }, ], webServer: { command: 'yarn serve', diff --git a/boxes/boxes/vanilla/.gitignore b/boxes/boxes/vanilla/.gitignore index ee1f6c9c26b3..be24b8bd711e 100644 --- a/boxes/boxes/vanilla/.gitignore +++ b/boxes/boxes/vanilla/.gitignore @@ -36,7 +36,7 @@ test-results/ playwright-report/ blob-report/ playwright/.cache/ -artifacts/* +artifacts .env diff --git a/boxes/boxes/vanilla/.prettierrc.json b/boxes/boxes/vanilla/.prettierrc.json new file mode 100644 index 000000000000..7c3bbec68481 --- /dev/null +++ b/boxes/boxes/vanilla/.prettierrc.json @@ -0,0 +1,6 @@ +{ + "singleQuote": true, + "trailingComma": "all", + "printWidth": 120, + "arrowParens": "avoid" +} diff --git a/boxes/boxes/vanilla/package.json b/boxes/boxes/vanilla/package.json index 66e4c71cf729..d73e3b6ba372 100644 --- a/boxes/boxes/vanilla/package.json +++ b/boxes/boxes/vanilla/package.json @@ -7,18 +7,12 @@ "node": ">=22.0.0" }, "scripts": { - "clean": "rm -rf app/dist contracts/target contracts/codegenCache.json", - "compile-contracts": "cd contracts && CONTAINER_NAME=\"aztec-vanilla-box\" ${AZTEC:-aztec} compile", - "codegen-contracts": "cd contracts && CONTAINER_NAME=\"aztec-vanilla-box\" ${AZTEC:-aztec} codegen ./target -o ./target", - "copy-artifacts": "mkdir -p artifacts && cp contracts/target/*.json contracts/target/*.ts ./artifacts", - "build-contracts": "yarn clean && yarn compile-contracts && yarn codegen-contracts && yarn copy-artifacts", - "deploy-contracts": "node --experimental-transform-types scripts/deploy.ts", - "dev": "webpack serve --mode development", - "build-app": "webpack --mode production", - "build": "yarn build-contracts && yarn build-app", + "build": "yarn clean && yarn compile && yarn codegen && webpack --mode production", + "clean": "rm -rf artifacts dist contracts/target contracts/codegenCache.json && mkdir -p artifacts", + "compile": "cd contracts && ${AZTEC:-aztec} compile && cp target/*.json ../artifacts", + "codegen": "cd contracts && ${AZTEC:-aztec} codegen ./target -o ./target && cp target/*.ts ../artifacts", "serve": "webpack serve --mode production --port ${PORT:-3000}", - "prep-test": "PROVER_ENABLED=false yarn deploy-contracts && yarn build-app", - "test": "yarn prep-test && yarn playwright test", + "test": "PROVER_ENABLED=false node --experimental-transform-types scripts/deploy.ts && yarn playwright test", "lint": "prettier --check ./src" }, "dependencies": { diff --git a/boxes/boxes/vanilla/playwright.config.ts b/boxes/boxes/vanilla/playwright.config.ts index 39b96c5ac894..84f070d84add 100644 --- a/boxes/boxes/vanilla/playwright.config.ts +++ b/boxes/boxes/vanilla/playwright.config.ts @@ -1,39 +1,13 @@ import { defineConfig, devices } from '@playwright/test'; -/** - * See https://playwright.dev/docs/test-configuration. - */ export default defineConfig({ - testDir: './tests', - fullyParallel: true, - forbidOnly: !!process.env.CI, - workers: process.env.PLAYWRIGHT_NUM_WORKERS - ? Number(process.env.PLAYWRIGHT_NUM_WORKERS) - : 1, - reporter: 'list', - use: { - baseURL: 'http://127.0.0.1:3000', - }, - expect: { - timeout: 50_000, - }, + expect: { timeout: 50_000 }, timeout: 400_000, projects: [ - { - name: 'webkit', - use: { ...devices['Desktop Safari'] }, - }, - { - name: 'chromium', - use: { ...devices['Desktop Chrome'] }, - }, - // Firefox is too slow in playwright during proof generation. - // { - // name: 'firefox', - // use: { ...devices['Desktop Firefox'] }, - // }, + { name: 'webkit', use: { ...devices['Desktop Safari'] } }, + { name: 'chromium', use: { ...devices['Desktop Chrome'] } }, + { name: 'firefox', use: { ...devices['Desktop Firefox'] } }, ], - webServer: { command: 'PORT=3000 yarn serve', port: 3000, diff --git a/boxes/boxes/vite/.gitignore b/boxes/boxes/vite/.gitignore index 560d0337d678..11f2e93597ec 100644 --- a/boxes/boxes/vite/.gitignore +++ b/boxes/boxes/vite/.gitignore @@ -25,4 +25,5 @@ dist-ssr artifacts/* codegenCache.json -test-results/ \ No newline at end of file +test-results/ +src/contracts/target diff --git a/boxes/boxes/vite/.prettierrc.json b/boxes/boxes/vite/.prettierrc.json new file mode 100644 index 000000000000..7c3bbec68481 --- /dev/null +++ b/boxes/boxes/vite/.prettierrc.json @@ -0,0 +1,6 @@ +{ + "singleQuote": true, + "trailingComma": "all", + "printWidth": 120, + "arrowParens": "avoid" +} diff --git a/boxes/boxes/vite/package.json b/boxes/boxes/vite/package.json index c079372ff1c7..3c88afd2a9b9 100644 --- a/boxes/boxes/vite/package.json +++ b/boxes/boxes/vite/package.json @@ -4,15 +4,13 @@ "version": "0.0.0", "type": "module", "scripts": { - "compile": "cd src/contracts && CONTAINER_NAME=\"aztec-vite-box\" ${AZTEC:-aztec} compile --silence-warnings", - "codegen": "CONTAINER_NAME=\"aztec-vite-box\" ${AZTEC:-aztec} codegen src/contracts/target -o artifacts", - "clean": "rm -rf ./dist .tsbuildinfo ./codegenCache.json ./artifacts ./src/contracts/target", - "prep": "yarn clean && yarn compile && yarn codegen", - "build": "yarn prep && yarn tsgo -b && vite build", + "build": "yarn clean && yarn compile && yarn codegen && tsc -b && vite build", + "clean": "rm -rf ./dist .tsbuildinfo ./codegenCache.json ./artifacts ./src/contracts/target ./test-results", + "compile": "cd src/contracts && ${AZTEC:-aztec} compile --silence-warnings", + "codegen": "${AZTEC:-aztec} codegen src/contracts/target -o artifacts", "serve": "vite", "test": "playwright test", - "formatting": "prettier --check ./src && eslint ./src", - "formatting:fix": "prettier -w ./src", + "lint": "prettier --check ./src && eslint ./src", "preview": "vite preview" }, "dependencies": { diff --git a/boxes/boxes/vite/playwright.config.ts b/boxes/boxes/vite/playwright.config.ts index e6ee606db1e8..fdefb920c2b9 100644 --- a/boxes/boxes/vite/playwright.config.ts +++ b/boxes/boxes/vite/playwright.config.ts @@ -1,37 +1,14 @@ -import { defineConfig, devices } from "@playwright/test"; +import { defineConfig, devices } from '@playwright/test'; export default defineConfig({ - testDir: "./tests", - testMatch: "**.spec.ts", - fullyParallel: true, - retries: 3, - workers: 1, - reporter: "list", - use: { - baseURL: "http://127.0.0.1:5173", - trace: "on-first-retry", - screenshot: "only-on-failure", - video: "on-first-retry", - }, - expect: { - timeout: 90000, - }, + expect: { timeout: 90000 }, projects: [ - { - name: "chromium", - use: { ...devices["Desktop Chrome"] }, - }, - { - name: "firefox", - use: { ...devices["Desktop Firefox"] }, - }, - { - name: "webkit", - use: { ...devices["Desktop Safari"] }, - }, + { name: 'chromium', use: { ...devices['Desktop Chrome'] } }, + { name: 'firefox', use: { ...devices['Desktop Firefox'] } }, + { name: 'webkit', use: { ...devices['Desktop Safari'] } }, ], webServer: { - command: "yarn serve --host", + command: 'yarn serve --host', port: 5173, }, }); diff --git a/boxes/docker-compose.yml b/boxes/docker-compose.yml deleted file mode 100644 index aff2987e6c0c..000000000000 --- a/boxes/docker-compose.yml +++ /dev/null @@ -1,60 +0,0 @@ -services: - ethereum: - image: aztecprotocol/build:3.0 - cpus: 1 - cpuset: ${CPU_LIST:-} - mem_limit: 2G - entrypoint: "anvil --silent -p 8545 --host 0.0.0.0 --chain-id 31337" - - aztec: - image: aztecprotocol/build:3.0 - cpus: 4 - cpuset: ${CPU_LIST:-} - mem_limit: 8G - tty: true - volumes: - - ../:/root/aztec-packages - working_dir: /root/aztec-packages/yarn-project/aztec - command: "node ./dest/bin start --local-network" - environment: - ETHEREUM_HOSTS: http://ethereum:8545 - HARDWARE_CONCURRENCY: 4 - L1_CHAIN_ID: 31337 - FORCE_COLOR: ${FORCE_COLOR:-1} - ARCHIVER_POLLING_INTERVAL_MS: 50 - P2P_BLOCK_CHECK_INTERVAL_MS: 50 - SEQ_TX_POLLING_INTERVAL_MS: 50 - WS_BLOCK_CHECK_INTERVAL_MS: 50 - ARCHIVER_VIEM_POLLING_INTERVAL_MS: 500 - healthcheck: - test: ["CMD", "curl", "-fSs", "http://127.0.0.1:8080/status"] - interval: 3s - timeout: 30s - start_period: 120s - depends_on: - - ethereum - - box: - image: aztecprotocol/build:3.0 - cpus: 4 - cpuset: ${CPU_LIST:-} - mem_limit: 8G - tty: true - volumes: - - ../:/root/aztec-packages - working_dir: /root/aztec-packages/boxes - command: "yarn workspace aztec-example-$BOX test --project=$BROWSER" - environment: - HARDWARE_CONCURRENCY: 4 - DEBUG: "aztec:*" - DEBUG_COLORS: "true" - ETHEREUM_HOSTS: http://ethereum:8545 - L1_CHAIN_ID: 31337 - FORCE_COLOR: ${FORCE_COLOR:-1} - PXE_URL: http://aztec:8080 - AZTEC_NODE_URL: http://aztec:8080 - BOX: ${BOX:-vanilla} - BROWSER: ${BROWSER:-chromium} - depends_on: - aztec: - condition: service_healthy diff --git a/boxes/package.json b/boxes/package.json index 9017ff45bf30..a86ab895194e 100644 --- a/boxes/package.json +++ b/boxes/package.json @@ -4,12 +4,7 @@ "version": "0.5.0", "type": "module", "scripts": { - "compile": "yarn workspaces foreach -A -p -v run compile", - "build": "yarn workspaces foreach -A -p -v run build", - "install-browsers": "playwright install --with-deps", - "publish": "yarn npm publish", - "test": "vitest bin.test.js", - "test:ci": "vitest run bin.test.js" + "build": "yarn workspaces foreach -A -p -v run build" }, "workspaces": [ "boxes/*" diff --git a/boxes/scripts/config.js b/boxes/scripts/config.js deleted file mode 100644 index 21940d4404fc..000000000000 --- a/boxes/scripts/config.js +++ /dev/null @@ -1,14 +0,0 @@ -export const AZTEC_REPO = "AztecProtocol/aztec-packages"; -export const CONTRACTS_TO_SHOW = ["token_contract"]; -export const getPlaceholders = (contract) => { - return [ - { - key: "%%contract_name%%", - value: contract, - }, - { - key: "%%e2e_test_url%%", - value: `https://github.com/${AZTEC_REPO}/tree/master/yarn-project/end-to-end/src/e2e_${contract}.test.ts`, - }, - ]; -}; diff --git a/boxes/scripts/init.js b/boxes/scripts/init.js deleted file mode 100644 index ad122b90a272..000000000000 --- a/boxes/scripts/init.js +++ /dev/null @@ -1,19 +0,0 @@ -import { replacePaths } from "./utils.js"; -import { AZTEC_REPO } from "./config.js"; -import tiged from "tiged"; - -export async function init(folder) { - const emitter = tiged(`${AZTEC_REPO}/boxes/init${tag && `#${tag}`}`, { - verbose: true, - }); - emitter.on("info", ({ message }) => debug(message)); - emitter.on("warn", ({ message }) => error(message)); - await emitter.clone(`${folder}`); - - await replacePaths({ - rootDir: `${folder}`, - tag, - version, - prefix: "", - }); -} diff --git a/boxes/scripts/run_test.sh b/boxes/scripts/run_test.sh new file mode 100755 index 000000000000..c4cb720695dc --- /dev/null +++ b/boxes/scripts/run_test.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash +source $(git rev-parse --show-toplevel)/ci3/source + +BOX=$1 +BROWSER=$2 + +export AZTEC=$(realpath ../../yarn-project/aztec/scripts/aztec.sh) +export BB=$(realpath ../../barretenberg/cpp/build/bin/bb) +export NARGO=$(realpath ../../noir/noir-repo/target/release/nargo) + +function cleanup { + set +e + if [ -n "${sandbox_pid:-}" ]; then + kill $sandbox_pid &>/dev/null + fi +} +trap 'cleanup' EXIT + +../../yarn-project/aztec/scripts/aztec.sh start --local-network & +sandbox_pid=$! + +while ! nc -z 127.0.0.1 8080 &>/dev/null; do sleep 1; done + +yarn workspace aztec-example-$BOX test --project=$BROWSER || bash diff --git a/boxes/scripts/steps/chooseBox.js b/boxes/scripts/steps/chooseBox.js deleted file mode 100644 index fa2ef54346df..000000000000 --- a/boxes/scripts/steps/chooseBox.js +++ /dev/null @@ -1,127 +0,0 @@ -import select from "@inquirer/select"; -import { - getAvailableBoxes, - getAvailableContracts, - processProject, - replacePaths, - clone, -} from "../utils.js"; -import { execSync } from "child_process"; -import { getPlaceholders } from "../config.js"; - -async function initGit({ dir }) { - execSync(`yes | git -C ${dir} init`); -} - -async function chooseAndCloneBox({ projectName }) { - // if the user has already chosen a project name, we should skip the input - // and use the one they've chosen - const skipName = projectName || undefined; - - const availableBoxes = await getAvailableBoxes(); - if (!projectName) { - projectName = await select({ - message: `Please choose your Aztec boilerplate:`, - choices: [ - ...availableBoxes.map((box) => { - return { value: box.name, name: box.description }; - }), - { value: "skip", name: "Skip this step" }, - ], - }); - } else { - if (!availableBoxes.find((box) => box.name === projectName)) { - throw new Error(`Box ${projectName} not found`); - } - } - - const rootDir = await clone({ - path: "boxes/boxes", - choice: projectName, - type: "box", - tag, - version, - name: skipName, - }); - - await initGit({ dir: rootDir }); - - await replacePaths({ - rootDir, - tag, - version, - prefix: "", - }); - success("Your code is ready!"); -} - -async function chooseAndCloneContract({ projectName }) { - const availableContracts = await getAvailableContracts(); - - // if the user has already chosen a project name, we should skip the input - // and use the one they've chosen - const skipName = projectName || undefined; - - if (!projectName) { - projectName = await select({ - message: `Please choose your Aztec boilerplate:`, - choices: [ - ...availableContracts.map((contract) => { - return { value: contract.name, name: contract.name }; - }), - { value: "skip", name: "Skip this step" }, - ], - }); - } else { - if (!availableContracts.find((contract) => contract.name === projectName)) { - throw new Error(`Contract ${projectName} not found`); - } - } - - const rootDir = await clone({ - path: "noir-projects/noir-contracts/contracts", - choice: projectName, - type: "contract", - tag, - version, - name: skipName, - }); - - await initGit({ dir: rootDir }); - - await replacePaths({ - rootDir, - tag, - version, - prefix: "noir-projects/", - }); - - await processProject({ - rootDir, - placeholders: getPlaceholders(projectName), - }); - success("Your code is ready!"); - - // get the e2e test for that contract from yarn-project/end-to-end -} - -export async function chooseProject({ projectType, projectName }) { - if (!projectType) { - projectType = await select({ - message: `Please choose your type of project:`, - choices: [ - { value: "app", name: "Boilerplate project with frontend" }, - { value: "contract", name: "Just a contract example" }, - { value: "skip", name: "Skip this step" }, - ], - }); - } - - if (projectType === "skip") { - return; - } else if (projectType === "contract") { - await chooseAndCloneContract({ projectName: projectName }); - } else if (projectType === "app") { - await chooseAndCloneBox({ projectName: projectName }); - } -} diff --git a/boxes/scripts/utils.js b/boxes/scripts/utils.js deleted file mode 100644 index 8183b352ed59..000000000000 --- a/boxes/scripts/utils.js +++ /dev/null @@ -1,264 +0,0 @@ -import path from "path"; -import os from "os"; -import fs from "fs/promises"; -import { parse, stringify } from "@iarna/toml"; -import { CONTRACTS_TO_SHOW, AZTEC_REPO } from "./config.js"; - -import input from "@inquirer/input"; -import tiged from "tiged"; - -const targetDir = path.join(os.homedir(), ".aztec/bin"); // Use os.homedir() to get $HOME - -export async function getAvailableBoxes() { - try { - const data = await github({ - path: `boxes/boxes${tag == "master" ? "" : `?ref=${tag}`}`, - }); - - let availableBoxes = data - .filter( - (content) => content.type === "dir" && !content.name.startsWith("."), - ) - .map(async ({ path, name }) => { - const { description } = await github({ - path: `${tag == "master" ? "master" : tag}/${path}/package.json`, - raw: true, - }); - - return { - name, - description: description || name, - }; - }); - - return await Promise.all(availableBoxes); - } catch (e) { - error(e); - } -} - -export async function getAvailableContracts() { - try { - const data = await github({ - path: `noir-projects/noir-contracts/contracts${tag == "master" ? "" : `?ref=${tag}`}`, - }); - let availableContracts = data.filter((content) => - CONTRACTS_TO_SHOW.includes(content.name), - ); - - return await Promise.all(availableContracts); - } catch (e) { - error(e); - } -} - -export async function clone({ path, choice, type, name }) { - if (!name) { - name = await input({ - message: `Your ${type} name:`, - default: `my-aztec-${type}`, - }); - } - - spinner.text = `Cloning the ${type} code...`; - try { - spinner.start(); - - const emitter = tiged( - `${AZTEC_REPO}/${path}/${choice}${tag && `#${tag}`}`, - { verbose: true }, - ); - emitter.on("info", ({ message }) => debug(message)); - emitter.on("warn", ({ message }) => error(message)); - await emitter.clone(`./${name}`); - - if (type === "contract") { - spinner.text = `Cloning default contract project...`; - const baseEmitter = tiged( - `${AZTEC_REPO}/boxes/contract-only${tag && `#${tag}`}`, - { verbose: true }, - ); - baseEmitter.on("info", debug); - baseEmitter.on("warn", error); - await baseEmitter.clone(`./${name}/base`); - await fs.cp(`./${name}/base`, `./${name}`, { - recursive: true, - force: true, - }); - try { - await fs.rm(`./${name}/base`, { - recursive: true, - force: true, - maxRetries: 3, - }); - } catch { - log( - "Could not delete temporary directory. Try deleting it manually: " + - `./${name}/base`, - ); - } - } - spinner.succeed(); - return `./${name}`; - } catch (e) { - spinner.fail(); - error(e); - process.exit(1); - } -} - -export async function processProject({ rootDir, placeholders }) { - spinner.text = `Processing the code...`; - try { - spinner.start(); - const processes = []; - const findAndReplace = async (dir, placeholders) => { - const files = await fs.readdir(dir, { - withFileTypes: true, - }); - files.forEach(async (file) => { - const filePath = path.join(dir, file.name); - if (file.isDirectory()) { - findAndReplace(filePath, placeholders); - } else { - processes.push( - new Promise(async (resolve, reject) => { - let content = await fs.readFile(filePath, "utf8"); - placeholders.forEach(({ key, value }) => { - content = content.replace(new RegExp(key, "g"), value); - }); - await fs.writeFile(filePath, content, "utf8"); - - resolve(); - }), - ); - } - }); - }; - - await findAndReplace(path.resolve(rootDir), placeholders); - await Promise.all(processes); - spinner.succeed(); - } catch (e) { - spinner.fail(); - error(e); - process.exit(1); - } -} - -export function prettyPrintNargoToml(config) { - const withoutDependencies = Object.fromEntries( - Object.entries(config).filter(([key]) => key !== "dependencies"), - ); - - const partialToml = stringify(withoutDependencies); - const dependenciesToml = Object.entries(config.dependencies).map( - ([name, dep]) => { - const depToml = stringify.value(dep); - return `${name} = ${depToml}`; - }, - ); - - return ( - partialToml + "\n[dependencies]\n" + dependenciesToml.join("\n") + "\n" - ); -} - -export async function updatePathEnvVar() { - // Detect the user's shell profile file based on common shells and environment variables - const homeDir = os.homedir(); - let shellProfile; - if (process.env.SHELL?.includes("bash")) { - shellProfile = path.join(homeDir, ".bashrc"); - } else if (process.env.SHELL?.includes("zsh")) { - shellProfile = path.join(homeDir, ".zshrc"); - } else { - // Extend with more conditions for other shells if necessary - warn("Unsupported shell or shell not detected."); - return; - } - - // Read the current content of the shell profile to check if the path is already included - const profileContent = await fs.readFile(shellProfile, "utf8"); - if (profileContent.includes(targetDir)) { - info(`${targetDir} is already in PATH.`); - return; - } - - // Append the export command to the shell profile file - const exportCmd = `\nexport PATH="$PATH:${targetDir}" # Added by Node.js script\n`; - await fs.appendFile(shellProfile, exportCmd); - - info(`Added ${targetDir} to PATH in ${shellProfile}.`); -} - -export async function replacePaths({ rootDir, prefix = "" }) { - spinner.text = `Replacing paths...`; - - try { - spinner.start(); - const replaces = []; - const findAndReplace = async (dir, prefix) => { - const files = await fs.readdir(dir, { - withFileTypes: true, - }); - files.forEach(async (file) => { - const filePath = path.join(dir, file.name); - if (file.isDirectory()) { - findAndReplace(filePath, prefix); // Recursively search subdirectories - } else if (file.name === "Nargo.toml") { - replaces.push( - new Promise(async (resolve, reject) => { - let content = parse(await fs.readFile(filePath, "utf8")); - if (!content.dependencies) return; - Object.keys(content.dependencies).forEach((dep) => { - const directory = content.dependencies[dep].path.replace( - /^(..\/)+/, - "", - ); - content.dependencies[dep] = { - git: `https://github.com/${AZTEC_REPO}/`, - tag, - directory: `${prefix}${directory}`, - }; - }); - - await fs.writeFile( - filePath, - prettyPrintNargoToml(content), - "utf8", - ); - resolve(); - }), - ); - } else if (file.name === "package.json") { - replaces.push( - new Promise(async (resolve, reject) => { - let content = JSON.parse(await fs.readFile(filePath, "utf8")); - if (!content.dependencies) return; - Object.keys(content.dependencies) - .filter((deps) => deps.match("@aztec")) - // "master" actually means "latest" for the npm release - .map( - (dep) => - (content.dependencies[dep] = - `${version === "master" ? "latest" : `^${version}`}`), - ); - await fs.writeFile(filePath, JSON.stringify(content), "utf8"); - resolve(); - }), - ); - } - }); - }; - - await findAndReplace(path.resolve(rootDir), prefix); - await Promise.all(replaces); - spinner.succeed(); - return; - } catch (e) { - spinner.fail(); - error(e); - process.exit(1); - } -} diff --git a/ci3/docker_isolate b/ci3/docker_isolate index fc2d5b395aa2..0a7c8a881d33 100755 --- a/ci3/docker_isolate +++ b/ci3/docker_isolate @@ -49,7 +49,7 @@ if [ "${USE_HOME_TMP}" -eq 1 ]; then tmp_mount="-v$HOME/tmp:/tmp:z" else # Default: use tmpfs with specified size - tmp_mount="--mount type=tmpfs,target=/tmp,tmpfs-size=$TMPFS_SIZE" + tmp_mount="--tmpfs /tmp:exec,size=$TMPFS_SIZE" fi # Launch the container in the background. diff --git a/ci3/parallelize b/ci3/parallelize index e8e952efcd09..8fc7db08092e 100755 --- a/ci3/parallelize +++ b/ci3/parallelize @@ -30,7 +30,7 @@ echo "" > "$FLAKES_FILE" # Create/clear from previous run # Otherwise use denoise to display dots and save output to redis. if [ -t 1 ]; then set +e - output=$(parallel $parallel_args --bar 'DUMP_FAIL=1 run_test_cmd {}' > >(DUP=1 cache_log "Test run")) + output=$(parallel $parallel_args --bar 'DUMP_FAIL=1 run_test_cmd {}' > >(DUP=1 stdbuf -oL cache_log "Test run")) code=$? if [ "$code" -ne 0 ]; then echo -e "$output" diff --git a/ci3/run_compose_test b/ci3/run_compose_test index 1f61e6bdf96a..f51b1ed3fdf3 100755 --- a/ci3/run_compose_test +++ b/ci3/run_compose_test @@ -15,6 +15,7 @@ cd "$compose_file_path" docker compose $name_arg down --timeout 0 &> /dev/null function cleanup { + set +e # echo compose cleanup: $name_arg >/dev/tty # If the container hasn't completed, wait up to 15 seconds for it to start. # Bit of kludge, but otherwise the "down" could happen before the "up" has started. @@ -29,13 +30,6 @@ function cleanup { } trap cleanup EXIT -# Prevent ansi codes from overwriting log headers. -echo -echo - -started=1 -setsid docker compose --ansi always $name_arg up --exit-code-from=$exit_container --abort-on-container-exit --force-recreate | cat & +setsid docker compose $name_arg up --exit-code-from=$exit_container --abort-on-container-exit --force-recreate & pid=$! wait $pid -code=$? -exit $code diff --git a/ci3/source_bootstrap b/ci3/source_bootstrap index 5a2b2eeb17e7..1e9fd282b49d 100644 --- a/ci3/source_bootstrap +++ b/ci3/source_bootstrap @@ -14,7 +14,7 @@ case "$cmd" in exit 0 fi # Until releases are 100% stable, print a debug log. - set -x + # set -x ;; esac diff --git a/noir-projects/noir-contracts/scripts/flamegraph.sh b/noir-projects/noir-contracts/scripts/flamegraph.sh deleted file mode 100755 index afbc814cb829..000000000000 --- a/noir-projects/noir-contracts/scripts/flamegraph.sh +++ /dev/null @@ -1,100 +0,0 @@ -#!/usr/bin/env bash -set -eu - -# Function to clean up and exit -cleanup_and_exit() { - echo "Cleaning up..." - rm -f "$FUNCTION_ARTIFACT" - exit 0 -} - -# Trap SIGINT (Ctrl+C) and call cleanup_and_exit -trap cleanup_and_exit SIGINT - -# If first arg is -h or --help, print usage -if [ "$1" == "-h" ] || [ "$1" == "--help" ]; then - echo "Generates a flamegraph for the given contract and function" - echo "Usage: $0 " - echo "e.g.: $0 ./target/voting_contract_Voting.json vote" - echo "e.g.: $0 Token transfer" - exit 0 -fi - -# Get the directory of the script -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" - -PROFILER=${PROFILER_PATH:-"$SCRIPT_DIR/../../../noir/noir-repo/target/release/noir-profiler"} -BACKEND_PATH=${BACKEND_PATH:-"$SCRIPT_DIR/../../../barretenberg/cpp/build/bin/bb"} -SERVE=${SERVE:-"1"} - -if [ ! -f $PROFILER ]; then - echo "Profiler not found, building profiler" - cd "$SCRIPT_DIR/../../../noir/noir-repo/tooling/profiler" - cargo build --release - cd "$SCRIPT_DIR" -fi - -# first console arg is contract name in camel case or path to contract artifact -CONTRACT=$1 - -# second console arg is the contract function -FUNCTION=$2 - -function sed_wrapper() { - if sed --version >/dev/null 2>&1; then - sed "$@" - elif gsed --version >/dev/null 2>&1; then - gsed "$@" - else - echo "No suitable sed found" - echo "You can install gsed with 'brew install gnu-sed'" - exit 1 - fi -} - -if [[ "$CONTRACT" == *.json ]]; then - if [ ! -f "$CONTRACT" ]; then - echo "Error: Contract artifact not found at $CONTRACT" - exit 1 - fi - ARTIFACT_PATH=$CONTRACT - FUNCTION_ARTIFACT="${ARTIFACT_PATH%%.json}-${FUNCTION}.json" -else - # convert contract name to following format: token_bridge_contract-TokenBridge.json - ARTIFACT=$(echo "$CONTRACT" | sed_wrapper -r 's/^([A-Z])/\L\1/; s/([a-z0-9])([A-Z])/\1_\L\2/g') - ARTIFACT=$(echo "$ARTIFACT" | tr '[:upper:]' '[:lower:]') - ARTIFACT_NAME="${ARTIFACT}_contract-${CONTRACT}" - ARTIFACT_PATH="$SCRIPT_DIR/../target/${ARTIFACT_NAME}.json" - FUNCTION_ARTIFACT="$SCRIPT_DIR/../target/${ARTIFACT_NAME}-${FUNCTION}.json" -fi - -# Extract artifact for the specific function (will save to $FUNCTION_ARTIFACT) -node "$SCRIPT_DIR/extractFunctionAsNoirArtifact.js" "$ARTIFACT_PATH" $FUNCTION - -if [ "$SERVE" == "1" ]; then - # We create dest directory and use it as an output for the generated main.svg file - OUTPUT_DIR="$SCRIPT_DIR/../dest" - mkdir -p "$OUTPUT_DIR" -else - # Save the flamegraph to the same directory as the artifact - OUTPUT_DIR=$(dirname "$ARTIFACT_PATH") -fi - -# At last, generate the flamegraph -$PROFILER gates --artifact-path "$FUNCTION_ARTIFACT" --backend-path "$BACKEND_PATH" --backend-gates-command "gates" --output "$OUTPUT_DIR" --scheme chonk --include_gates_per_opcode - -echo "Flamegraph generated for contract: $CONTRACT" -# save as $ARTIFACT_NAME-${FUNCTION}-flamegraph.svg -OUTPUT_FILE="${OUTPUT_DIR}/$(basename ${ARTIFACT_PATH%%.json})-${FUNCTION}-flamegraph.svg" -mv "$OUTPUT_DIR/${FUNCTION}_gates.svg" "$OUTPUT_FILE" - -if [ "$SERVE" == "1" ]; then - # serve the file over http - echo -e "\nServing flamegraph at http://0.0.0.0:8000/$(basename $OUTPUT_FILE)\n" - npx -y http-server --silent -p 8000 "$OUTPUT_DIR" -else - echo -e "\nFlamegraph $(basename $OUTPUT_FILE) saved to artifacts directory. You can open it in your browser.\n" -fi - -# Clean up before exiting -cleanup_and_exit diff --git a/noir/bootstrap.sh b/noir/bootstrap.sh index c8c238fbbc57..b2ddf0d2a2c5 100755 --- a/noir/bootstrap.sh +++ b/noir/bootstrap.sh @@ -8,13 +8,13 @@ export hash=$(hash_str $noir_commit $(cache_content_hash .rebuild_patterns)) # Must be in dependency order for releasing. export js_projects=" - @noir-lang/types - @noir-lang/noir_js - @noir-lang/noir_codegen - @noir-lang/noirc_abi - @noir-lang/acvm_js + types + noir_js + noir_codegen + noirc_abi + acvm_js " -export js_include=$(printf " --include %s" $js_projects) +export js_include=$(printf " --include @noir-lang/%s" $js_projects) export GIT_COMMIT=$noir_commit export SOURCE_DATE_EPOCH=0 @@ -57,9 +57,9 @@ function build_packages { cd .. rm -rf packages && mkdir -p packages for project in $js_projects; do - p=$(cd noir-repo && yarn workspaces list --json | jq -r "select(.name==\"$project\").location") + p=$(cd noir-repo && yarn workspaces list --json | jq -r "select(.name==\"@noir-lang/$project\").location") tar zxfv noir-repo/$p/package.tgz -C packages - mv packages/package packages/${project#*/} + mv packages/package packages/$project done # Find all files in packages dir and use sed to in-place replace @noir-lang with @aztec/noir- @@ -106,13 +106,18 @@ function build { parallel --tag --line-buffer --halt now,fail=1 denoise ::: build_native build_packages } +function get_projects { + for dir in $js_projects; do + realpath packages/$dir + done +} + function release { local dist_tag=$(dist_tag) local version=${REF_NAME#v} cd packages - for package in $js_projects; do - local dir=${package#*/} + for dir in $js_projects; do [ ! -d "$dir" ] && echo "Project path not found: $dir" && exit 1 cd $dir diff --git a/release-image/Dockerfile b/release-image/Dockerfile index a73555af27a0..d422ccf0a5ed 100644 --- a/release-image/Dockerfile +++ b/release-image/Dockerfile @@ -3,19 +3,10 @@ FROM aztecprotocol/release-image-base # Copy in project files. COPY . /usr/src -# We do a short (~3 second) forge build of 3 stubborn files to make sure the cache has all entries. -# This saves time when users make a local network. -# This is impossibly finicky to get right from outside the container, due to having a different set of files. -RUN cd /usr/src/l1-contracts && \ - forge build && \ - # Remove test files from the cache that cause warnings. - cache="cache/solidity-files-cache.json" && \ - jq '.files |= with_entries(select(.key | endswith(".t.sol") | not))' "$cache" > "$cache.tmp" && mv "$cache.tmp" "$cache" - -# Even after that, we want to make sure that forge COULD force a rebuild for FOUNDRY_PROFILE=production. -# This is used in the prod deploy. As well, --broadcast writes to l1-contracts/broadcast. -RUN mkdir -p /usr/src/l1-contracts/broadcast && \ - chmod -R a+rwX /usr/src/l1-contracts/out /usr/src/l1-contracts/cache /usr/src/l1-contracts/broadcast +# L1 contracts artifacts are pre-built in yarn-project/l1-artifacts/foundry-artifacts. +# Ensure directories are writable for forge --broadcast at runtime. +RUN mkdir -p /usr/src/yarn-project/l1-artifacts/foundry-artifacts/broadcast && \ + chmod -R a+rwX /usr/src/yarn-project/l1-artifacts/foundry-artifacts ARG BUILD_METADATA="" ENV BUILD_METADATA=$BUILD_METADATA diff --git a/release-image/Dockerfile.base b/release-image/Dockerfile.base index 2d844f0a022d..f7c86d807c0e 100644 --- a/release-image/Dockerfile.base +++ b/release-image/Dockerfile.base @@ -6,7 +6,7 @@ COPY . /usr/src # Install yarn-project production dependencies. # Explicitly specify projects that we use to keep as slim as possible. WORKDIR /usr/src/yarn-project -RUN yarn workspaces focus @aztec/aztec @aztec/cli-wallet --production +RUN yarn workspaces focus @aztec/aztec --production # Create base of our final slim image. # This can be cached and will only update if dependencies change. diff --git a/release-image/Dockerfile.dockerignore b/release-image/Dockerfile.dockerignore index 48d6d770c167..abf209ea8d60 100644 --- a/release-image/Dockerfile.dockerignore +++ b/release-image/Dockerfile.dockerignore @@ -1,61 +1,23 @@ +# We include just what's needed to run the aztec cli (none of the aztec.sh extensions). * !/.release-please-manifest.json -!/avm-transpiler/target/release/avm-transpiler !/barretenberg/cpp/build/bin/bb-avm !/barretenberg/ts/dest/ !/barretenberg/ts/build/ !/barretenberg/ts/package.json !/noir/noir-repo/target/release/nargo !/noir/noir-repo/target/release/acvm -!/noir/noir-repo/target/release/noir-profiler -!/noir-projects/noir-contracts/scripts/flamegraph.sh -!/noir-projects/noir-contracts/scripts/extractFunctionAsNoirArtifact.js -!/noir-projects/noir-contracts/scripts/strip_aztec_nr_prefix.sh !/noir/packages/ !/yarn-project/package.json !/yarn-project/yarn.lock !/yarn-project/*/package.json !/yarn-project/*/dest/ -!/yarn-project/cli-wallet/wallet-entrypoint.sh -!/yarn-project/accounts/artifacts/ !/yarn-project/cli/public_include_metric_prefixes.json +!/yarn-project/accounts/artifacts/ !/yarn-project/bb-prover/artifacts/ !/yarn-project/noir-protocol-circuits-types/artifacts/ !/yarn-project/protocol-contracts/artifacts/ !/yarn-project/noir-contracts.js/artifacts/ -!/yarn-project/native/build/ - -### Start foundry / l1-contracts files - -# There's a bunch of complexity here because foundry is very particular. -# We want to take our full build from the repo, copy it over, and avoid any -# recompilation or warnings from forge inside the docker container. - -# We need to to run l1-contracts deploy scripts (script/deploy/*) -# All source/test files needed so forge cache entries match and avoid recompilation -!/l1-contracts/foundry.toml -# We have to include the solc binary annoyingly, even if we aim to fully have a cached build. -!/l1-contracts/solc-* -!/l1-contracts/script/deploy -!/l1-contracts/src/ - -# Needed to prevent rebuilds. -!/l1-contracts/cache/ -!/l1-contracts/out/ - -# Remove test files, except for shouting.t.sol that for an undiagnosed reason causes a warning if not present. -/l1-contracts/out/**/*.t.sol -!/l1-contracts/test/shouting.t.sol - -# Honk verifier. -!/l1-contracts/generated/ - -# The minimum needed to run our solidity dependencies. -!/l1-contracts/lib/**/remappings.txt -!/l1-contracts/lib/**/foundry.toml -!/l1-contracts/lib/**/*.sol -### End foundry / l1-contracts files - - -# Needed to generate list of env vars to know what to be able to inject into the container. -!/yarn-project/foundation/src/config/env_var.ts +!/yarn-project/simulator/artifacts/ +# This includes all files needed for l1-contracts deployment via forge script. +!/yarn-project/l1-artifacts/l1-contracts/ diff --git a/release-image/bootstrap.sh b/release-image/bootstrap.sh index d2322546663b..1ec58c3f9a96 100755 --- a/release-image/bootstrap.sh +++ b/release-image/bootstrap.sh @@ -40,6 +40,11 @@ function build { denoise "build_image" } +function test_cmds { + # Very simple sanity test. + echo "$hash docker run --rm aztecprotocol/aztec --version" +} + function release { echo_header "release-image release" diff --git a/yarn-project/aztec/package.json b/yarn-project/aztec/package.json index f6051dd13144..6f6b4ebcd0dc 100644 --- a/yarn-project/aztec/package.json +++ b/yarn-project/aztec/package.json @@ -6,7 +6,7 @@ ".": "./dest/index.js", "./testing": "./dest/testing/index.js" }, - "bin": "./dest/bin/index.js", + "bin": "./scripts/aztec.sh", "typedocOptions": { "entryPoints": [ "./src/index.ts" @@ -70,6 +70,7 @@ }, "files": [ "dest", + "scripts", "src", "!*.test.*" ], diff --git a/yarn-project/aztec/scripts/aztec.sh b/yarn-project/aztec/scripts/aztec.sh new file mode 100755 index 000000000000..cec7ec83686e --- /dev/null +++ b/yarn-project/aztec/scripts/aztec.sh @@ -0,0 +1,56 @@ +#!/usr/bin/env bash +set -euo pipefail + +script_dir="$(dirname "$(realpath "$0")")" + +function aztec { + exec node --no-warnings $script_dir/../dest/bin/index.js "$@" +} + +cmd=${1:-} +[ -n "$cmd" ] && shift + +export AZTEC_SHELL_WRAPPER=1 + +case $cmd in + test) + export LOG_LEVEL="${LOG_LEVEL:-info}" + aztec start --txe --port 8081 & + server_pid=$! + trap 'kill $server_pid &>/dev/null || true' EXIT + while ! nc -z 127.0.0.1 8081 &>/dev/null; do sleep 0.2; done + export NARGO_FOREIGN_CALL_TIMEOUT=300000 + nargo test --silence-warnings --pedantic-solving --oracle-resolver http://127.0.0.1:8081 "$@" + ;; + start) + if [ "${1:-}" == "--local-network" ]; then + # TODO: Can these just be set in TS? + export ARCHIVER_POLLING_INTERVAL_MS=500 + export P2P_BLOCK_CHECK_INTERVAL_MS=500 + export SEQ_TX_POLLING_INTERVAL_MS=500 + export WS_BLOCK_CHECK_INTERVAL_MS=500 + export ARCHIVER_VIEM_POLLING_INTERVAL_MS=500 + export TEST_ACCOUNTS=${TEST_ACCOUNTS:-true} + export LOG_LEVEL=${LOG_LEVEL:-info;silent:sequencer;verbose:debug_log} + export DEPLOY_AZTEC_CONTRACTS_SALT=${DEPLOY_AZTEC_CONTRACTS_SALT:-$RANDOM} + + ANVIL_PORT=${ANVIL_PORT:-8545} + + export L1_CHAIN_ID=${L1_CHAIN_ID:-31337} + export ETHEREUM_HOSTS=${ETHEREUM_HOSTS:-"http://127.0.0.1:${ANVIL_PORT}"} + + anvil --version + anvil --silent & + anvil_pid=$! + trap 'kill $anvil_pid &>/dev/null' EXIT + fi + + aztec start "$@" + ;; + compile|new|init|flamegraph) + $script_dir/${cmd}.sh "$@" + ;; + *) + aztec $cmd "$@" + ;; +esac diff --git a/yarn-project/aztec/scripts/compile.sh b/yarn-project/aztec/scripts/compile.sh new file mode 100755 index 000000000000..7bec1e29d17f --- /dev/null +++ b/yarn-project/aztec/scripts/compile.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash +set -euo pipefail + +NARGO=${NARGO:-nargo} +BB=${BB:-bb} + +# If help is requested, show Aztec-specific info then run nargo compile help and then exit in order to not trigger +# transpilation +for arg in "$@"; do + if [ "$arg" == "--help" ] || [ "$arg" == "-h" ]; then + cat << 'EOF' +Aztec Compile - Compile Aztec Noir contracts + +This command compiles Aztec Noir contracts using nargo and then automatically +postprocesses them to generate Aztec specific artifacts including: +- Transpiled contract artifacts +- Verification keys + +The compiled contracts will be placed in the target/ directory by default. + +--- +Underlying nargo compile options: + +EOF + nargo compile --help + exit 0 + fi +done + +# Run nargo compile. +$NARGO compile "$@" + +echo "Postprocessing contract..." +$BB aztec_process + +# Strip internal prefixes from all compiled contract JSONs in target directory +# TODO: This should be part of bb aztec_process! +for json in target/*.json; do + temp_file="${json}.tmp" + jq '.functions |= map(.name |= sub("^__aztec_nr_internals__"; ""))' "$json" > "$temp_file" + mv "$temp_file" "$json" +done + +echo "Compilation complete!" diff --git a/noir-projects/noir-contracts/scripts/extractFunctionAsNoirArtifact.js b/yarn-project/aztec/scripts/extract_function.js similarity index 61% rename from noir-projects/noir-contracts/scripts/extractFunctionAsNoirArtifact.js rename to yarn-project/aztec/scripts/extract_function.js index 560f0fa94a58..c73c8ba9aa58 100644 --- a/noir-projects/noir-contracts/scripts/extractFunctionAsNoirArtifact.js +++ b/yarn-project/aztec/scripts/extract_function.js @@ -1,5 +1,6 @@ -const path = require("path"); -const fs = require("fs").promises; +#!/usr/bin/env node +import fs from 'fs/promises'; +import path from 'path'; // Simple script to extract a contract function as a separate Noir artifact. // We need to use this since the transpiling that we do on public functions make the contract artifacts @@ -7,20 +8,14 @@ const fs = require("fs").promises; async function main() { let [contractArtifactPath, functionName] = process.argv.slice(2); if (!contractArtifactPath || !functionName) { - console.log( - "Usage: node extractFunctionAsNoirArtifact.js " - ); + console.log('Usage: node extractFunctionAsNoirArtifact.js '); return; } - const contractArtifact = JSON.parse( - await fs.readFile(contractArtifactPath, "utf8") - ); - const func = contractArtifact.functions.find((f) => f.name === functionName); + const contractArtifact = JSON.parse(await fs.readFile(contractArtifactPath, 'utf8')); + const func = contractArtifact.functions.find(f => f.name === functionName); if (!func) { - console.error( - `Function ${functionName} not found in ${contractArtifactPath}` - ); + console.error(`Function ${functionName} not found in ${contractArtifactPath}`); return; } @@ -39,17 +34,14 @@ async function main() { }; const outputDir = path.dirname(contractArtifactPath); - const outputName = - path.basename(contractArtifactPath, ".json") + `-${functionName}.json`; + const outputName = path.basename(contractArtifactPath, '.json') + `-${functionName}.json`; const outPath = path.join(outputDir, outputName); - console.log(`Writing to ${outPath}`); - await fs.writeFile(outPath, JSON.stringify(artifact, null, 2)); } -main().catch((err) => { +main().catch(err => { console.error(err); process.exit(1); }); diff --git a/yarn-project/aztec/scripts/flamegraph.sh b/yarn-project/aztec/scripts/flamegraph.sh new file mode 100755 index 000000000000..48763ef0d793 --- /dev/null +++ b/yarn-project/aztec/scripts/flamegraph.sh @@ -0,0 +1,59 @@ +#!/usr/bin/env bash +set -eu + +# If first arg is -h or --help, print usage. +if [ $# -lt 2 ] || [ "$1" == "-h" ] || [ "$1" == "--help" ]; then + cat << 'EOF' +Aztec Flamegraph - Generate a gate count flamegraph for an aztec contract function. + +Usage: aztec flamegraph + +Options: + -h, --help Print help + +Will output an svg at /--flamegraph.svg. +You can open it in your browser to view it. + +EOF + exit 0 +fi + +cleanup() { + set +e + if [ -f "$function_artifact" ]; then + rm -f "$function_artifact" + fi +} + +trap cleanup EXIT + +# Get the directory of the script +script_dir=$(realpath $(dirname $0)) + +PROFILER=${PROFILER_PATH:-noir-profiler} +BB=${BB:-bb} + +# first console arg is contract name in camel case or path to contract artifact +contract=$1 + +# second console arg is the contract function +function=$2 + +if [ ! -f "$contract" ]; then + echo "Error: Contract artifact not found at: $contract" + exit 1 +fi +artifact_path=$contract +function_artifact="${artifact_path%%.json}-${function}.json" +output_dir=$(dirname "$artifact_path") + +# Extract artifact for the specific function. +node $script_dir/extract_function.js "$artifact_path" $function + +# Generate the flamegraph +$PROFILER gates --artifact-path "$function_artifact" --backend-path "$BB" --backend-gates-command "gates" --output "$output_dir" --scheme chonk --include_gates_per_opcode + +# Save as $artifact_name-$function-flamegraph.svg +output_file="${function_artifact%%.json}-flamegraph.svg" +mv "$output_dir/__aztec_nr_internals__${function}_gates.svg" "$output_file" +echo "Flamegraph generated at: $output_file" diff --git a/yarn-project/aztec/scripts/init.sh b/yarn-project/aztec/scripts/init.sh new file mode 100755 index 000000000000..fa66617ff6ed --- /dev/null +++ b/yarn-project/aztec/scripts/init.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash +set -euo pipefail + +NARGO=${NARGO:-nargo} +script_path=$(realpath $(dirname "$0")) + +for arg in "$@"; do + if [ "$arg" == "--help" ] || [ "$arg" == "-h" ]; then + cat << 'EOF' +Aztec Init - Create a new Aztec Noir project in the current directory + +Usage: aztec init [OPTIONS] + +Options: + --name Name of the package [default: current directory name] + --lib Use a library template + -h, --help Print help + +This command creates a new Aztec Noir project in the current directory using nargo +and automatically adds the Aztec.nr dependency to your Nargo.toml file. + +EOF + exit 0 + fi + if [ "$arg" == "--lib" ]; then + is_contract=0 + fi +done + +echo "Initializing Noir project..." +$NARGO init "$@" + +if [ "${is_contract:-1}" -eq 1 ]; then + $script_path/setup_project.sh +fi diff --git a/yarn-project/aztec/scripts/new.sh b/yarn-project/aztec/scripts/new.sh new file mode 100755 index 000000000000..6901a235bfe8 --- /dev/null +++ b/yarn-project/aztec/scripts/new.sh @@ -0,0 +1,59 @@ +#!/usr/bin/env bash +set -euo pipefail + +NARGO=${NARGO:-nargo} +script_path=$(realpath $(dirname "$0")) + +type_arg="--contract" + +while [[ $# -gt 0 ]]; do + case $1 in + --help|-h) + cat << 'EOF' +Aztec New - Create a new Aztec Noir project in a new directory + +Usage: aztec new [OPTIONS] + +Arguments: + The path to save the new project + +Options: + --name Name of the package [default: package directory name] + --lib Create a library template instead of a contract + -h, --help Print help + +This command creates a new Aztec Noir project using nargo and automatically +adds the Aztec.nr dependency to your Nargo.toml file. +EOF + exit 0 + ;; + --lib) + type_arg="--lib" + shift + ;; + --name) + name_arg="--name $2" + shift 2 + ;; + *) + project_path=$1 + shift + break + ;; + esac +done + +if [ -z "$project_path" ]; then + echo "Error: PATH argument is required" + echo "Usage: aztec new [OPTIONS] " + echo "Run 'aztec new --help' for more information" + exit 1 +fi + +echo "Creating new Noir project at $project_path..." +$NARGO new $type_arg ${name_arg:-} $project_path + +if [ "$type_arg" == "--contract" ]; then + cd $project_path + $script_path/setup_project.sh +fi diff --git a/yarn-project/aztec/scripts/setup_project.sh b/yarn-project/aztec/scripts/setup_project.sh new file mode 100755 index 000000000000..1797a5625491 --- /dev/null +++ b/yarn-project/aztec/scripts/setup_project.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Get the actual aztec version for the git tag. +AZTEC_VERSION=$(jq -r '.version' $(dirname $0)/../package.json) +NARGO_TOML_PATH="Nargo.toml" +MAIN_NR_PATH="src/main.nr" + +if [ ! -f "$NARGO_TOML_PATH" ]; then + >&2 echo "Warning: Could not find Nargo.toml at $NARGO_TOML_PATH to add aztec dependency" + exit 1 +fi + +if [ ! -f "$MAIN_NR_PATH" ]; then + >&2 echo "Warning: Could not find main.nr at $MAIN_NR_PATH" + exit 1 +fi + +# Add aztec dependency to Nargo.toml +echo "" >> "$NARGO_TOML_PATH" +echo "aztec = { git=\"https://github.com/AztecProtocol/aztec-nr\", tag=\"v${AZTEC_VERSION}\", directory=\"aztec\" }" >> "$NARGO_TOML_PATH" +echo "Added aztec dependency (v${AZTEC_VERSION}) to Nargo.toml" + +# Replace the contents of main.nr with the Aztec contract template +cat > "$MAIN_NR_PATH" << 'EOF' +use aztec::macros::aztec; + +#[aztec] +contract Main {} +EOF +echo "Created main.nr with Aztec contract template" diff --git a/yarn-project/aztec/src/cli/cli.ts b/yarn-project/aztec/src/cli/cli.ts index 5b898cd72214..16bd7a8d109d 100644 --- a/yarn-project/aztec/src/cli/cli.ts +++ b/yarn-project/aztec/src/cli/cli.ts @@ -31,9 +31,10 @@ export function injectAztecCommands(program: Command, userLog: LogFn, debugLogge program.configureHelp({ sortSubcommands: true }); - program.addHelpText( - 'after', - ` + if (process.env.AZTEC_SHELL_WRAPPER) { + program.addHelpText( + 'after', + ` Additional commands: @@ -64,30 +65,17 @@ export function injectAztecCommands(program: Command, userLog: LogFn, debugLogge The compiled contracts will be placed in the target/ directory by default. Supports standard nargo compile options. - fmt [options]: formats Noir code using nargo fmt - Example: - $ aztec fmt # formats all Noir files in the project - - check [options]: type-checks Noir code without compiling using nargo check - Example: - $ aztec check # checks all Noir files in the project - test [options]: starts a dockerized TXE node via $ aztec start --txe then runs $ aztec test --silence-warnings --oracle-resolver= [options] - lsp: starts the Nargo Language Server Protocol server - Runs nargo lsp in a Docker container for IDE integration with Noir. - This command is typically used by IDE extensions and not called directly by users. - Example: - $ aztec lsp # starts the LSP server - preload-crs: Downloads and caches the Common Reference String (CRS) data required for zero-knowledge proofs. Example: $ aztec preload-crs # preloads CRS data `, - ); + ); + } program .command('preload-crs') diff --git a/yarn-project/bootstrap.sh b/yarn-project/bootstrap.sh index 95ba5a4eb5e0..5a7dc50d92b0 100755 --- a/yarn-project/bootstrap.sh +++ b/yarn-project/bootstrap.sh @@ -13,16 +13,16 @@ function compile_project { parallel -j16 --line-buffered --tag 'cd {} && ../node_modules/.bin/swc src -d dest --config-file=../.swcrc --strip-leading-paths' "$@" } -# Returns a list of projects to compile/lint/publish. +# Returns a list of project paths to compile/lint/publish. # Ensure exclusions are matching in both cases. function get_projects { if [ "${1:-}" == 'topological' ]; then yarn workspaces foreach --topological-dev -A \ --exclude @aztec/aztec3-packages \ --exclude @aztec/scripts \ - exec 'basename $(pwd)' | cat | grep -v "Done" + exec 'echo $(pwd)' | cat | grep -v "Done" else - dirname */src l1-artifacts/generated + dirname */src | xargs realpath fi } diff --git a/yarn-project/cli-wallet/src/bin/index.ts b/yarn-project/cli-wallet/src/bin/index.ts index 61e30ccc9c7b..1334ad2e1c72 100644 --- a/yarn-project/cli-wallet/src/bin/index.ts +++ b/yarn-project/cli-wallet/src/bin/index.ts @@ -1,3 +1,4 @@ +#!/usr/bin/env node import { computeSecretHash } from '@aztec/aztec.js/crypto'; import { Fr } from '@aztec/aztec.js/fields'; import { createAztecNodeClient } from '@aztec/aztec.js/node'; diff --git a/yarn-project/cli-wallet/wallet-entrypoint.sh b/yarn-project/cli-wallet/wallet-entrypoint.sh deleted file mode 100755 index 7099edca1cfb..000000000000 --- a/yarn-project/cli-wallet/wallet-entrypoint.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -if [[ -n "${SSH_AUTH_SOCK_SOCAT_PORT:-}" ]]; then - cleanup() { - kill -9 $SOCAT_PID - rm -rf $SOCKET - } - - SOCKET="$HOME/.aztec/aztec-wallet-$RANDOM.sock" - socat UNIX-LISTEN:$SOCKET,fork TCP:host.docker.internal:${SSH_AUTH_SOCK_SOCAT_PORT} & - SOCAT_PID=$! - trap cleanup EXIT SIGKILL SIGTERM - export SSH_AUTH_SOCK="${SOCKET:-}" -fi - -node --no-warnings /usr/src/yarn-project/cli-wallet/dest/bin/index.js $@ diff --git a/yarn-project/ethereum/src/deploy_aztec_l1_contracts.ts b/yarn-project/ethereum/src/deploy_aztec_l1_contracts.ts index f346244c8cd2..41b1596862a8 100644 --- a/yarn-project/ethereum/src/deploy_aztec_l1_contracts.ts +++ b/yarn-project/ethereum/src/deploy_aztec_l1_contracts.ts @@ -10,7 +10,8 @@ import { fileURLToPath } from '@aztec/foundation/url'; import { bn254 } from '@noble/curves/bn254'; import type { Abi, Narrow } from 'abitype'; import { spawn } from 'child_process'; -import { dirname, resolve } from 'path'; +import { cpSync, existsSync, mkdirSync, mkdtempSync, readdirSync, rmSync } from 'fs'; +import { dirname, join, resolve } from 'path'; import readline from 'readline'; import type { Hex } from 'viem'; import { foundry, mainnet, sepolia } from 'viem/chains'; @@ -107,17 +108,66 @@ export interface ValidatorJson { } /** - * Gets the path to the l1-contracts directory. + * Gets the path to the l1-contracts foundry artifacts directory. + * These are copied from l1-contracts to yarn-project/l1-artifacts/l1-contracts + * during build to make yarn-project self-contained. */ export function getL1ContractsPath(): string { - // Try to find l1-contracts relative to this file const currentDir = dirname(fileURLToPath(import.meta.url)); - - // Go up from yarn-project/ethereum/src to yarn-project, then to repo root, then to l1-contracts - const l1ContractsPath = resolve(currentDir, '..', '..', '..', 'l1-contracts'); + // Go up from yarn-project/ethereum/dest to yarn-project, then to l1-artifacts/l1-contracts + const l1ContractsPath = resolve(currentDir, '..', '..', 'l1-artifacts', 'l1-contracts'); return l1ContractsPath; } +// Cached deployment directory +let preparedDeployDir: string | undefined; + +function cleanupDeployDir() { + if (preparedDeployDir) { + try { + rmSync(preparedDeployDir, { recursive: true, force: true }); + } catch { + // ignore cleanup errors + } + preparedDeployDir = undefined; + } +} + +/** + * Prepares a temp directory for forge deployment. + * Copies all artifacts with preserved timestamps (required for forge cache validity). + * A fresh broadcast/ directory is created for deployment outputs. + */ +export function prepareL1ContractsForDeployment(): string { + if (preparedDeployDir && existsSync(preparedDeployDir)) { + return preparedDeployDir; + } + + const basePath = getL1ContractsPath(); + const tempDir = mkdtempSync(join(dirname(basePath), '.foundry-deploy-')); + preparedDeployDir = tempDir; + process.on('exit', cleanupDeployDir); + + // Copy all dirs with preserved timestamps (required for forge cache validity) + const copyOpts = { recursive: true, preserveTimestamps: true }; + cpSync(join(basePath, 'out'), join(tempDir, 'out'), copyOpts); + cpSync(join(basePath, 'lib'), join(tempDir, 'lib'), copyOpts); + cpSync(join(basePath, 'cache'), join(tempDir, 'cache'), copyOpts); + cpSync(join(basePath, 'src'), join(tempDir, 'src'), copyOpts); + cpSync(join(basePath, 'script'), join(tempDir, 'script'), copyOpts); + cpSync(join(basePath, 'generated'), join(tempDir, 'generated'), copyOpts); + cpSync(join(basePath, 'foundry.toml'), join(tempDir, 'foundry.toml')); + cpSync(join(basePath, 'foundry.lock'), join(tempDir, 'foundry.lock')); + for (const file of readdirSync(basePath)) { + if (file.startsWith('solc-')) { + cpSync(join(basePath, file), join(tempDir, file)); + } + } + + mkdirSync(join(tempDir, 'broadcast')); + return tempDir; +} + /** * Computes the validator data for passing to Solidity. * Only computes the G2 public key (which requires scalar multiplication on G2, not available in EVM). @@ -211,7 +261,6 @@ export async function deployAztecL1Contracts( 'Initial validator funding requires minting tokens, which is not possible with an external token.', ); } - const currentDir = dirname(fileURLToPath(import.meta.url)); const chain = createEthereumChain([rpcUrl], chainId); const l1Client = createExtendedL1Client([rpcUrl], privateKey, chain.chainInfo); @@ -240,8 +289,8 @@ export async function deployAztecL1Contracts( } } - // Relative location of l1-contracts in monorepo or docker image. - const l1ContractsPath = resolve(currentDir, '..', '..', '..', 'l1-contracts'); + // Use foundry-artifacts from l1-artifacts package + const l1ContractsPath = prepareL1ContractsForDeployment(); const FORGE_SCRIPT = 'script/deploy/DeployAztecL1Contracts.s.sol'; await maybeForgeForceProductionBuild(l1ContractsPath, FORGE_SCRIPT, chainId); @@ -513,10 +562,8 @@ export const deployRollupForUpgrade = async ( | 'zkPassportArgs' >, ) => { - const currentDir = dirname(fileURLToPath(import.meta.url)); - - // Relative location of l1-contracts in monorepo or docker image. - const l1ContractsPath = resolve(currentDir, '..', '..', '..', 'l1-contracts'); + // Use foundry-artifacts from l1-artifacts package + const l1ContractsPath = prepareL1ContractsForDeployment(); const FORGE_SCRIPT = 'script/deploy/DeployRollupForUpgrade.s.sol'; await maybeForgeForceProductionBuild(l1ContractsPath, FORGE_SCRIPT, chainId); diff --git a/yarn-project/l1-artifacts/.gitignore b/yarn-project/l1-artifacts/.gitignore index 85de9cf93344..918cd544d5f1 100644 --- a/yarn-project/l1-artifacts/.gitignore +++ b/yarn-project/l1-artifacts/.gitignore @@ -1 +1,2 @@ src +l1-contracts diff --git a/yarn-project/l1-artifacts/package.json b/yarn-project/l1-artifacts/package.json index 2ebf2418040d..b37e4cef8d98 100644 --- a/yarn-project/l1-artifacts/package.json +++ b/yarn-project/l1-artifacts/package.json @@ -16,7 +16,8 @@ "clean": "rm -rf ./dest ./generated .tsbuildinfo", "formatting": "run -T prettier --check ./generated && run -T eslint ./generated", "formatting:fix": "run -T prettier -w ./generated", - "generate": "yarn generate:l1-contracts", + "copy-artifacts": "bash scripts/copy-foundry-artifacts.sh", + "generate": "yarn copy-artifacts && yarn generate:l1-contracts", "generate:l1-contracts": "bash scripts/generate-artifacts.sh" }, "dependencies": { @@ -30,7 +31,8 @@ }, "files": [ "dest", - "generated" + "generated", + "l1-contracts" ], "types": "./dest/index.d.ts" } diff --git a/yarn-project/l1-artifacts/scripts/copy-foundry-artifacts.sh b/yarn-project/l1-artifacts/scripts/copy-foundry-artifacts.sh new file mode 100755 index 000000000000..f9f909e805f1 --- /dev/null +++ b/yarn-project/l1-artifacts/scripts/copy-foundry-artifacts.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Copies select Foundry artifacts from l1-contracts to yarn-project/l1-artifacts/l1-contracts. +# This makes yarn-project self-contained for runtime contract deployment. +# +# We use cp -p to preserve timestamps - forge cache uses timestamps to detect changes. +# See release-image/Dockerfile.dockerignore for the canonical list of what's needed. + +cd $(git rev-parse --show-toplevel)/yarn-project/l1-artifacts + +src="../../l1-contracts" + +[ -d "$src/out" ] || { echo "Error: l1-contracts/out not found. Build l1-contracts first."; exit 1; } + +rm -rf "l1-contracts" +mkdir -p "l1-contracts/script" "l1-contracts/lib" "l1-contracts/broadcast" + +# Copy build artifacts, cache, sources, and config (preserving timestamps for cache validity) +cp -rp "$src"/{out,cache,src,generated} "l1-contracts/" +cp -rp "$src/script/deploy" "l1-contracts/script/" # only deploy/, other scripts depend on test files +cp -p "$src"/{foundry.toml,foundry.lock,solc-*} "l1-contracts/" +abs_dest=$(pwd)/l1-contracts +# Keep only the foundry relevant files from lib +(cd "$src" && find lib \( -name "*.sol" -o -name "remappings.txt" -o -name "foundry.toml" \) -exec cp --parents -t "$abs_dest" {} +) + +# Foundry is very finicky about copying out subsets. +# Patch over what foundry feels needs to be rebuild (~3 seconds on mainframe) +(cd "l1-contracts" && forge build) diff --git a/yarn-project/yarn.lock b/yarn-project/yarn.lock index fac87c3e79fc..e0c025445479 100644 --- a/yarn-project/yarn.lock +++ b/yarn-project/yarn.lock @@ -947,7 +947,7 @@ __metadata: typescript: "npm:^5.3.3" viem: "npm:@aztec/viem@2.38.2" bin: - aztec: ./dest/bin/index.js + aztec: ./scripts/aztec.sh languageName: unknown linkType: soft From 5615c416e2d2b5ac0e4ef60709ba756411e68ee7 Mon Sep 17 00:00:00 2001 From: ludamad Date: Tue, 6 Jan 2026 12:50:11 -0500 Subject: [PATCH 2/2] Clean up Dockerfile by removing unused comments Removed commented-out lines for L1 contracts artifacts and directory permissions. --- release-image/Dockerfile | 5 ----- 1 file changed, 5 deletions(-) diff --git a/release-image/Dockerfile b/release-image/Dockerfile index d422ccf0a5ed..48c6c06a9572 100644 --- a/release-image/Dockerfile +++ b/release-image/Dockerfile @@ -3,11 +3,6 @@ FROM aztecprotocol/release-image-base # Copy in project files. COPY . /usr/src -# L1 contracts artifacts are pre-built in yarn-project/l1-artifacts/foundry-artifacts. -# Ensure directories are writable for forge --broadcast at runtime. -RUN mkdir -p /usr/src/yarn-project/l1-artifacts/foundry-artifacts/broadcast && \ - chmod -R a+rwX /usr/src/yarn-project/l1-artifacts/foundry-artifacts - ARG BUILD_METADATA="" ENV BUILD_METADATA=$BUILD_METADATA