Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Block cheat codes in anvil #8277

Merged
merged 3 commits into from
Aug 29, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 13 additions & 7 deletions iac/mainnet-fork/Earthfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,30 @@ build:
FROM ubuntu:focal

# Install nginx
RUN echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections
RUN apt-get update && apt install -y git curl nginx

# Copy nginx config
COPY . .
COPY nginx/gateway.conf /etc/nginx/gateway.conf
COPY nginx/nginx.conf /etc/nginx/nginx.conf
COPY ./scripts/install_nginx.sh ./scripts/install_nginx.sh
RUN ./scripts/install_nginx.sh

# Install foundry
COPY ./scripts/install_foundry.sh ./scripts/install_foundry.sh
RUN ./scripts/install_foundry.sh
ENV PATH="./foundry/bin:${PATH}"

# Copy nginx config
COPY ./scripts ./scripts
COPY ./redeploy ./redeploy
COPY ./nginx/ /etc/nginx/
COPY --chmod 640 ./etc/anvil.logrotate.conf /etc/logrotate.d/anvil

# Expose port 80
EXPOSE 80

# Set entrypoint.
ENTRYPOINT ["sh", "-c", "./scripts/run_nginx_anvil.sh"]

export-local:
FROM +build
SAVE IMAGE aztecprotocol/mainnet-fork

export-mainnet-fork:
FROM +build
ARG DIST_TAG="devnet"
Expand Down
9 changes: 9 additions & 0 deletions iac/mainnet-fork/etc/anvil.logrotate.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/var/log/anvil/*.log {
daily
missingok
rotate 14
size 50M
compress
notifempty
copytruncate
}
22 changes: 19 additions & 3 deletions iac/mainnet-fork/nginx/gateway.conf
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,29 @@ server {
listen 80 default_server;
listen 8545;

location = /{{API_KEY}} {
location /{{ADMIN_API_KEY}} {
proxy_pass http://0.0.0.0:8544;
rewrite ^/{{API_KEY}}(.*) /$1 break;
rewrite ^/{{ADMIN_API_KEY}}(.*) /$1 break;
}

location /public-{{PUBLIC_API_KEY}} {
client_body_buffer_size 20M;
client_body_in_single_buffer on;
js_import main from njs/anvil_validation.js;
js_content main.authorize;
}

location @anvil {
proxy_pass http://0.0.0.0:8544;
rewrite ^/({{ADMIN_API_KEY}}|public-{{PUBLIC_API_KEY}})(.*) /$2 break;
}

# Error responses
error_page 404 = @400; # Treat invalid paths as bad requests
error_page 404 = @404;
location @404 {
return 404 '{"error":"Resource not found"}';
}

proxy_intercept_errors on; # Do not send backend errors to client
default_type application/json; # If no content-type, assume JSON
}
1 change: 1 addition & 0 deletions iac/mainnet-fork/nginx/nginx.conf
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
load_module modules/ngx_http_js_module.so;

events {
worker_connections 768;
Expand Down
28 changes: 28 additions & 0 deletions iac/mainnet-fork/nginx/njs/anvil_validation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Authorizes a request based on the method of the JSON-RPC request body, blocking all cheat codes.
// See https://github.com/nginx/njs-examples?tab=readme-ov-file#authorizing-requests-based-on-request-body-content-http-authorization-request-body
function authorize(r) {
try {
if (r.requestText) {
const body = JSON.parse(r.requestText);
if (body && body.method) {
const method = body.method.replace(/\s+/g).toLowerCase();
if (
method.startsWith("evm_") ||
method.startsWith("hardhat_") ||
method.startsWith("anvil_")
) {
const error = "Restricted method " + method;
r.error(error);
r.return(401, JSON.stringify({ error }));
return;
}
}
}
r.internalRedirect("@anvil");
} catch (e) {
r.error("JSON.parse exception: " + e);
r.return(400, JSON.stringify({ error: "Error parsing request" }));
}
}

export default { authorize };
2 changes: 1 addition & 1 deletion iac/mainnet-fork/redeploy
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3
4
19 changes: 19 additions & 0 deletions iac/mainnet-fork/scripts/install_nginx.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/bin/sh
set -eu

# See https://nginx.org/en/linux_packages.html#Ubuntu
echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections

apt-get update && apt install -y curl gnupg2 ca-certificates lsb-release ubuntu-keyring

curl -sS https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
| tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null

echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
http://nginx.org/packages/ubuntu `lsb_release -cs` nginx" \
| tee /etc/apt/sources.list.d/nginx.list

echo "Package: *\nPin: origin nginx.org\nPin: release o=nginx\nPin-Priority: 900\n" \
| tee /etc/apt/preferences.d/99nginx

apt-get update && apt install -y git curl nginx nginx-module-njs
12 changes: 8 additions & 4 deletions iac/mainnet-fork/scripts/run_nginx_anvil.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@

set -eum pipefail

# Replace API_KEY in nginx config
echo "Replacing api key with $API_KEY in nginx config..."
sed -i 's/{{API_KEY}}/'$API_KEY'/' /etc/nginx/gateway.conf
# Replace API_KEYs in nginx config
echo "Replacing api keys in nginx config..."
sed -i 's/{{PUBLIC_API_KEY}}/'$PUBLIC_API_KEY'/g' /etc/nginx/gateway.conf
sed -i 's/{{ADMIN_API_KEY}}/'$API_KEY'/g' /etc/nginx/gateway.conf

# Run nginx and anvil alongside each other
trap 'kill $(jobs -p)' SIGTERM
Expand All @@ -21,8 +22,11 @@ echo "result: ${MNEMONIC_STRIPPED:0:10}..."
# Data directory for anvil state
mkdir -p /data

# Log directory for anvil
mkdir -p /var/log/anvil/

# Run anvil silently
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: It's not silent anymore :-)

.foundry/bin/anvil --silent --block-time 12 --host $HOST -p $PORT -m "$MNEMONIC_STRIPPED" -f=https://mainnet.infura.io/v3/$INFURA_API_KEY --chain-id=$L1_CHAIN_ID --fork-block-number=15918000 --block-base-fee-per-gas=10 -s=$SNAPSHOT_FREQUENCY --state=./data/state --balance=1000000000000000000 >/dev/null &
.foundry/bin/anvil --block-time 12 --host $HOST -p $PORT -m "$MNEMONIC_STRIPPED" -f=https://mainnet.infura.io/v3/$INFURA_API_KEY --chain-id=$L1_CHAIN_ID --fork-block-number=15918000 --block-base-fee-per-gas=10 -s=$SNAPSHOT_FREQUENCY --state=./data/state --balance=1000000000000000000 >>/var/log/anvil/anvil.log &

echo "Waiting for ethereum host at $ETHEREUM_HOST..."
while ! curl -s $ETHEREUM_HOST >/dev/null; do sleep 1; done
Expand Down
26 changes: 6 additions & 20 deletions iac/mainnet-fork/terraform/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -119,26 +119,12 @@ resource "aws_ecs_task_definition" "aztec_mainnet_fork" {
image = "${var.DOCKERHUB_ACCOUNT}/mainnet-fork:${var.DEPLOY_TAG}"
essential = true
environment = [
{
name = "API_KEY"
value = "${var.API_KEY}"
},
{
name = "MNEMONIC"
value = "${var.FORK_MNEMONIC}"
},
{
name = "INFURA_API_KEY"
value = "${var.INFURA_API_KEY}"
},
{
name = "L1_CHAIN_ID"
value = "${var.L1_CHAIN_ID}"
},
{
name = "SNAPSHOT_FREQUENCY"
value = "15"
}
{ name = "API_KEY", value = "${var.API_KEY}" },
{ name = "PUBLIC_API_KEY", value = "${var.PUBLIC_API_KEY}" },
{ name = "MNEMONIC", value = "${var.FORK_MNEMONIC}" },
{ name = "INFURA_API_KEY", value = "${var.INFURA_API_KEY}" },
{ name = "L1_CHAIN_ID", value = "${var.L1_CHAIN_ID}" },
{ name = "SNAPSHOT_FREQUENCY", value = "15" }
]
mountPoints = [
{
Expand Down
4 changes: 4 additions & 0 deletions iac/mainnet-fork/terraform/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ variable "API_KEY" {
type = string
}

variable "PUBLIC_API_KEY" {
type = string
}

variable "DOCKERHUB_ACCOUNT" {
type = string
}
Expand Down
Loading