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

chore!: enable multiple L1 nodes to be used #11945

Merged
merged 43 commits into from
Feb 26, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
1140b31
fix: support multiple L1 node URLs
spypsy Feb 12, 2025
b2faca5
leftovers
spypsy Feb 12, 2025
16146ca
more fixes
spypsy Feb 12, 2025
4f79daf
Merge branch 'master' into spy/multi-rpc-urls
spypsy Feb 12, 2025
286954a
fix --rpc-url usage
spypsy Feb 12, 2025
f0e23a1
Merge branch 'master' into spy/multi-rpc-urls
spypsy Feb 12, 2025
0fad63b
fix imports + tests
spypsy Feb 12, 2025
09ea2b1
undo test change
spypsy Feb 12, 2025
d6334bb
update --l1-rpc-urls
spypsy Feb 12, 2025
dd1e0ef
fix imports
spypsy Feb 13, 2025
6d45015
another import
spypsy Feb 13, 2025
4fb917e
externalHosts
spypsy Feb 13, 2025
d129c99
Merge branch 'master' into spy/multi-rpc-urls
spypsy Feb 20, 2025
4836dd9
post-merge fixes
spypsy Feb 20, 2025
bbacaaf
more post-merge fixes
spypsy Feb 20, 2025
4a91b45
fix e2e test
spypsy Feb 20, 2025
8714406
Merge branch 'master' into spy/multi-rpc-urls
spypsy Feb 21, 2025
29a1311
Merge branch 'master' into spy/multi-rpc-urls
spypsy Feb 24, 2025
24ccc68
Merge branch 'master' into spy/multi-rpc-urls
spypsy Feb 24, 2025
da0e3cb
PR Fixes
spypsy Feb 24, 2025
842ae5d
update docs
spypsy Feb 24, 2025
685d0c5
update docs
spypsy Feb 24, 2025
12cc436
Merge branch 'master' into spy/multi-rpc-urls
spypsy Feb 24, 2025
688014a
fix typings
spypsy Feb 25, 2025
aa5fa6c
Merge branch 'master' into spy/multi-rpc-urls
spypsy Feb 25, 2025
8e79c39
fix wallet client types
spypsy Feb 25, 2025
e438592
Merge branch 'master' into spy/multi-rpc-urls
spypsy Feb 25, 2025
eca0f24
use multi-urls in cheatcode
spypsy Feb 25, 2025
889caad
Merge branch 'master' into spy/multi-rpc-urls
spypsy Feb 25, 2025
fe3d7d3
fix helper spartan script
spypsy Feb 25, 2025
c489937
fix e2e cheat_codes
spypsy Feb 25, 2025
85c007f
Merge branch 'master' into spy/multi-rpc-urls
spypsy Feb 25, 2025
1547a62
rm unused import
spypsy Feb 25, 2025
67c81a9
PR Fixes
spypsy Feb 26, 2025
d58918e
Merge branch 'master' into spy/multi-rpc-urls
spypsy Feb 26, 2025
fc382de
deploy l1 contracts fixes
spypsy Feb 26, 2025
bb6975c
fix type imports
spypsy Feb 26, 2025
9405407
update gh secret names
spypsy Feb 26, 2025
36c9e22
break, don't return
spypsy Feb 26, 2025
b111170
no need to retry get-chain-id
spypsy Feb 26, 2025
da839b8
Merge branch 'master' into spy/multi-rpc-urls
spypsy Feb 26, 2025
4be11a4
Merge branch 'master' into spy/multi-rpc-urls
spypsy Feb 26, 2025
3bd421e
merge fix
spypsy Feb 26, 2025
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
6 changes: 3 additions & 3 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,11 @@ services:
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT: ${OTEL_EXPORTER_OTLP_METRICS_ENDPOINT:-http://otel-collector:4318/v1/metrics}
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT: ${OTEL_EXPORTER_OTLP_TRACES_ENDPOINT:-http://otel-collector:4318/v1/traces}
secrets:
- ethereum-host
- ethereum-hosts
- p2p-boot-node
entrypoint: |
/bin/sh -c '
export ETHEREUM_HOSTS=$$(cat /var/run/secrets/ethereum-host)
export ETHEREUM_HOSTS=$$(cat /var/run/secrets/ethereum-hosts)
export BOOTSTRAP_NODES=$$(cat /var/run/secrets/p2p-boot-node)

test -z "$$PEER_ID_PRIVATE_KEY" -a ! -f /var/lib/aztec/p2p-private-key && node /usr/src/yarn-project/cli/dest/bin/index.js generate-p2p-private-key | head -1 | cut -d" " -f 3 | tee /var/lib/aztec/p2p-private-key || echo "Re-using existing P2P private key"
Expand Down Expand Up @@ -121,7 +121,7 @@ services:
secrets:
aztec-node-url:
environment: AZTEC_NODE_URL
ethereum-host:
ethereum-hosts:
environment: ETHEREUM_HOSTS
p2p-boot-node:
environment: BOOTSTRAP_NODES
18 changes: 12 additions & 6 deletions spartan/aztec-network/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -209,12 +209,18 @@ nodeSelector:
if [ -n "${EXTERNAL_ETHEREUM_HOSTS}" ]; then
export ETHEREUM_HOSTS="${EXTERNAL_ETHEREUM_HOSTS}"
fi
echo "Awaiting ethereum node at ${ETHEREUM_HOSTS}"
until curl -s -X POST -H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":67}' \
${ETHEREUM_HOSTS} | grep 0x; do
echo "Waiting for Ethereum node ${ETHEREUM_HOSTS}..."
echo "Awaiting any ethereum node from: ${ETHEREUM_HOSTS}"
IFS=',' read -ra HOSTS <<< "${ETHEREUM_HOSTS}"
while true; do
for HOST in "${HOSTS[@]}"; do
if curl -s -X POST -H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":67}' \
${HOST} | grep -q 0x; then
echo "Ethereum node ${HOST} is ready!"
exit 0
Copy link
Contributor

Choose a reason for hiding this comment

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

What's the scope of this exit 0? IIUC this template gets pasted as-is where it is included, so any operations after this helper would not run due to the early exit. This would affect eg deploy-l1-contracts:

- name: deploy-l1-contracts
          {{- include "aztec-network.image" . | nindent 10 }}
          command:
            - /bin/bash
            - -c
            - |
              cp /scripts/deploy-l1-contracts.sh /tmp/deploy-l1-contracts.sh
              chmod +x /tmp/deploy-l1-contracts.sh
              source /shared/config/service-addresses
              source /shared/config/validator-addresses
              {{- include "aztec-network.waitForEthereum" . | nindent 14 }}
           /tmp/deploy-l1-contracts.sh "{{ .Values.aztec.l1Salt }}" "{{ .Values.ethereum.chainId }}" "$VALIDATOR_ADDRESSES"

Copy link
Contributor

Choose a reason for hiding this comment

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

Sorry, reviewed this in an outdated commit and it was already fixed.

Copy link
Contributor

Choose a reason for hiding this comment

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

Still, I think the new version doesn't do what we expect. I understand it loops over every host, waiting for 5s inbetween them, and exits once the first one replies. But it doesn't go back to the first one to retry if all failed, it just goes through, right?

fi
echo "Waiting for Ethereum node ${HOST}..."
done
sleep 5
done
echo "Ethereum node is ready!"
{{- end -}}
4 changes: 2 additions & 2 deletions spartan/releases/testnet/Earthfile
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ test-p2p-key:
echo "✅ P2P private key test passed" || \
(echo "❌ P2P private key test failed" && exit 1)

test-ethereum-host:
test-ethereum-hosts:
FROM +test-setup
RUN echo -e "\n\n" | ./aztec-spartan.sh config \
-n "troll-turtle" \
Expand Down Expand Up @@ -160,4 +160,4 @@ test-all:
BUILD +test-update
BUILD +test-data-dir
BUILD +test-p2p-key
BUILD +test-ethereum-host
BUILD +test-ethereum-hosts
2 changes: 1 addition & 1 deletion spartan/releases/testnet/aztec-spartan.sh
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ parse_args() {
IMAGE="$2"
shift 2
;;
-e | --ethereum-host)
-e | --ethereum-hosts)
ETHEREUM_HOSTS="$2"
shift 2
;;
Expand Down
6 changes: 3 additions & 3 deletions yarn-project/aztec-faucet/src/faucet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ import {
type GetContractReturnType,
type HttpTransport,
type LocalAccount,
http as ViemHttp,
type WalletClient,
createPublicClient,
createWalletClient,
fallback,
getContract,
parseEther,
http as viemHttp,
} from 'viem';
import { mnemonicToAccount } from 'viem/accounts';

Expand Down Expand Up @@ -44,12 +44,12 @@ export class Faucet {
this.walletClient = createWalletClient({
account: this.account,
chain: chain.chainInfo,
transport: fallback([ViemHttp(chain.rpcUrls[0])]),
transport: fallback(chain.rpcUrls.map(url => viemHttp(url))),
});

this.publicClient = createPublicClient({
chain: chain.chainInfo,
transport: fallback([ViemHttp(chain.rpcUrls[0])]),
transport: fallback(chain.rpcUrls.map(url => viemHttp(url))),
});
}

Expand Down
5 changes: 4 additions & 1 deletion yarn-project/aztec/src/sandbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,10 @@ export async function createSandbox(config: Partial<SandboxConfig> = {}, userLog
// sandbox is meant for test envs. We should only need one l1RpcUrl
const l1RpcUrl = config.l1RpcUrls?.[0];
if (!l1RpcUrl) {
throw new Error('At least one L1 RPC URL is required');
throw new Error('An L1 RPC URL is required');
}
if ((config.l1RpcUrls?.length || 0) > 1) {
logger.warn(`Multiple L1 RPC URLs provided. Sandbox will only use the first one: ${l1RpcUrl}`);
}
const aztecNodeConfig: AztecNodeConfig = { ...getConfigEnvVars(), ...config };
const hdAccount = mnemonicToAccount(config.l1Mnemonic || DefaultMnemonic);
Expand Down
6 changes: 3 additions & 3 deletions yarn-project/end-to-end/scripts/docker-compose-devnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ services:
end-to-end:
image: aztecprotocol/end-to-end:${AZTEC_DOCKER_TAG:-latest}
secrets:
- ethereum-host
- ethereum-hosts
- aztec-node-url
- faucet-url
environment:
Expand All @@ -12,7 +12,7 @@ services:
JOB_NAME: ${JOB_NAME:-''}
PXE_PROVER_ENABLED: ${PXE_PROVER_ENABLED:-1}
command: |
export ETHEREUM_HOSTS=$$(cat /var/run/secrets/ethereum-host)
export ETHEREUM_HOSTS=$$(cat /var/run/secrets/ethereum-hosts)
export FAUCET_URL=$$(cat /var/run/secrets/faucet-url)
export AZTEC_NODE_URL=$$(cat /var/run/secrets/aztec-node-url)
${TEST:-./src/devnet/e2e_smoke.test.ts}
Expand All @@ -22,7 +22,7 @@ services:
secrets:
aztec-node-url:
environment: AZTEC_NODE_URL
ethereum-host:
ethereum-hosts:
environment: ETHEREUM_HOSTS
faucet-url:
environment: FAUCET_URL
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,29 @@ export PRIVATE_KEY=${PRIVATE_KEY:-""}
export SALT=${SALT:-"1337"}

echo "Waiting for Ethereum node to be up..."
until curl -s -X POST -H 'Content-Type: application/json' \
--data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' \
$ETHEREUM_HOSTS 2>/dev/null | grep -q 'result'; do
found_node=0
for HOST in $(echo "${ETHEREUM_HOSTS}" | tr ',' '\n'); do
if curl -s -X POST -H 'Content-Type: application/json' \
--data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' \
"$HOST" 2>/dev/null | grep -q 'result'; then
echo "Node $HOST is ready"
found_node=1
break
fi
sleep 1
done
Copy link
Contributor

Choose a reason for hiding this comment

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

Heads up this is not equivalent to the previous one: the new one will exit if the node is not immediately available, while the previous one will retry. Given this is called simultaneously to ETHEREUM_SCRIPT in scripts/run_native_testnet.sh, we should keep the behaviour of waiting for the node to be up.


if [ $found_node -eq 0 ]; then
echo "No Ethereum nodes available"
exit 1
fi
echo "Done waiting."

# Fetch chain ID from the Ethereum node
source "$REPO"/yarn-project/end-to-end/scripts/native-network/utils/get-chain-id.sh

echo "L1_CHAIN_ID: $L1_CHAIN_ID"

# Construct base command
COMMAND="node --no-warnings $(git rev-parse --show-toplevel)/yarn-project/aztec/dest/bin/index.js \
deploy-l1-contracts \
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
export L1_CHAIN_ID=$(curl -s -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}' \
$ETHEREUM_HOSTS | grep -o '"result":"0x[^"]*"' | cut -d'"' -f4 | xargs printf "%d\n")
#!/bin/sh

echo "Using L1 chain ID: $L1_CHAIN_ID"
# Split on commas and try each host
for HOST in $(echo "${ETHEREUM_HOSTS}" | tr ',' '\n'); do
RESULT=$(curl -s -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}' \
"$HOST")
if echo "$RESULT" | grep -q '"result":"0x'; then
export L1_CHAIN_ID=$(echo "$RESULT" | grep -o '"result":"0x[^"]*"' | cut -d'"' -f4 | xargs printf "%d\n")
echo "Using L1 chain ID: $L1_CHAIN_ID from $HOST"
return 0
fi
done

echo "Error: Could not get chain ID from any host in: $ETHEREUM_HOSTS"
exit 1
8 changes: 0 additions & 8 deletions yarn-project/end-to-end/scripts/native-network/validator.sh
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,6 @@ export SEQ_PUBLISHER_PRIVATE_KEY=$VALIDATOR_PRIVATE_KEY
export DEBUG=${DEBUG:-""}
export LOG_LEVEL=${LOG_LEVEL:-"verbose"}
export L1_CONSENSUS_HOST_URL=${L1_CONSENSUS_HOST_URL:-}

# Automatically detect if we're using Anvil
if curl -s -H "Content-Type: application/json" -X POST --data '{"method":"web3_clientVersion","params":[],"id":49,"jsonrpc":"2.0"}' $ETHEREUM_HOSTS | jq .result | grep -q anvil; then
IS_ANVIL="true"
else
IS_ANVIL="false"
fi

export P2P_ENABLED="true"
export VALIDATOR_DISABLED="false"
export SEQ_MAX_SECONDS_BETWEEN_BLOCKS="0"
Expand Down
4 changes: 2 additions & 2 deletions yarn-project/end-to-end/src/devnet/e2e_smoke.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ describe('End-to-end tests for devnet', () => {
claimSecret: { value: string };
messageLeafIndex: string;
}>('bridge-fee-juice', [amount, l2Account.getAddress()], {
'l1-rpc-url': ETHEREUM_HOSTS!,
'l1-rpc-urls': ETHEREUM_HOSTS!,
'l1-chain-id': l1ChainId.toString(),
'l1-private-key': l1Account.privateKey,
'rpc-url': pxeUrl,
Expand Down Expand Up @@ -279,7 +279,7 @@ describe('End-to-end tests for devnet', () => {

async function getL1Balance(address: string, token?: EthAddress): Promise<bigint> {
const { balance } = await cli<{ balance: string }>('get-l1-balance', [address], {
'l1-rpc-url': ETHEREUM_HOSTS!,
'l1-rpc-urls': ETHEREUM_HOSTS!,
'l1-chain-id': l1ChainId.toString(),
token,
});
Expand Down
10 changes: 3 additions & 7 deletions yarn-project/ethereum/src/l1_tx_utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,19 @@ import {
type Address,
type BaseError,
type BlockOverrides,
type Chain,
type ContractFunctionExecutionError,
type FallbackTransport,
type GetTransactionReturnType,
type Hex,
type HttpTransport,
MethodNotFoundRpcError,
MethodNotSupportedRpcError,
type PublicClient,
type StateOverride,
type TransactionReceipt,
type WalletClient,
formatGwei,
getContractError,
hexToBytes,
} from 'viem';

import type { ExtendedViemWalletClient, ViemPublicClient } from './types.js';
import { formatViemError } from './utils.js';

// 1_000_000_000 Gwei = 1 ETH
Expand Down Expand Up @@ -207,8 +203,8 @@ export class L1TxUtils {
private interrupted = false;

constructor(
public publicClient: PublicClient<FallbackTransport<HttpTransport[]>, Chain>,
public walletClient: WalletClient<FallbackTransport<HttpTransport[]>, Chain, Account>,
public publicClient: ViemPublicClient,
public walletClient: ExtendedViemWalletClient,
protected readonly logger?: Logger,
config?: Partial<L1TxUtilsConfig>,
) {
Expand Down
41 changes: 9 additions & 32 deletions yarn-project/ethereum/src/test/tx_delayer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,44 +2,20 @@ import { type Logger, createLogger } from '@aztec/foundation/log';
import { TestERC20Abi, TestERC20Bytecode } from '@aztec/l1-artifacts';

import { type Anvil } from '@viem/anvil';
import {
type Chain,
type Client,
type HttpTransport,
type PrivateKeyAccount,
type PublicActions,
type PublicRpcSchema,
type WalletActions,
type WalletRpcSchema,
createWalletClient,
getContract,
http,
publicActions,
} from 'viem';
import { type PrivateKeyAccount, createWalletClient, fallback, getContract, http, publicActions } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { foundry } from 'viem/chains';

import type { ExtendedViemWalletClient } from '../types.js';
import { startAnvil } from './start_anvil.js';
import { type Delayer, withDelayer } from './tx_delayer.js';

/**
* Type for a viem wallet and public client using a local private key.
* Created as: `createWalletClient({ account: privateKeyToAccount(key), transport: http(url), chain }).extend(publicActions)`
*/
export type ViemClient = Client<
HttpTransport,
Chain,
PrivateKeyAccount,
[...PublicRpcSchema, ...WalletRpcSchema],
PublicActions<HttpTransport, Chain> & WalletActions<Chain, PrivateKeyAccount>
>;

describe('tx_delayer', () => {
let anvil: Anvil;
let rpcUrl: string;
let logger: Logger;
let account: PrivateKeyAccount;
let client: ViemClient;
let client: ExtendedViemWalletClient;
let delayer: Delayer;

const ETHEREUM_SLOT_DURATION = 2;
Expand All @@ -50,12 +26,13 @@ describe('tx_delayer', () => {
});

beforeEach(() => {
const transport = http(rpcUrl);
account = privateKeyToAccount('0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80');
({ client, delayer } = withDelayer(
createWalletClient({ transport, chain: foundry, account }).extend(publicActions),
{ ethereumSlotDuration: ETHEREUM_SLOT_DURATION },
));
const _client = createWalletClient({
transport: fallback([http(rpcUrl)]),
chain: foundry,
account,
}).extend(publicActions);
({ client, delayer } = withDelayer(_client, { ethereumSlotDuration: ETHEREUM_SLOT_DURATION }));
});

const receiptNotFound = expect.objectContaining({ name: 'TransactionReceiptNotFoundError' });
Expand Down
5 changes: 3 additions & 2 deletions yarn-project/ethereum/src/test/tx_delayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ import {
type Client,
type Hex,
type PublicClient,
type WalletClient,
keccak256,
parseTransaction,
publicActions,
walletActions,
} from 'viem';

import type { ExtendedViemWalletClient } from '../types.js';

export function waitUntilBlock<T extends Client>(client: T, blockNumber: number | bigint, logger?: Logger) {
const publicClient =
'getBlockNumber' in client && typeof client.getBlockNumber === 'function'
Expand Down Expand Up @@ -93,7 +94,7 @@ class DelayerImpl implements Delayer {
* The delayer can be used to hold off the next tx to be sent until a given block number.
* TODO(#10824): This doesn't play along well with blob txs for some reason.
*/
export function withDelayer<T extends WalletClient>(
export function withDelayer<T extends ExtendedViemWalletClient>(
client: T,
opts: { ethereumSlotDuration: bigint | number },
): { client: T; delayer: Delayer } {
Expand Down
9 changes: 4 additions & 5 deletions yarn-project/ethereum/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ import type {
Chain,
Client,
FallbackTransport,
HttpTransport,
PrivateKeyAccount,
HttpTransport, // PrivateKeyAccount,
PublicActions,
PublicClient,
PublicRpcSchema,
Expand All @@ -19,11 +18,11 @@ export type ViemPublicClient = PublicClient<FallbackTransport<HttpTransport[]>,
export type ViemWalletClient = WalletClient<FallbackTransport<HttpTransport[]>, Chain, Account>;

export type ExtendedViemWalletClient = Client<
FallbackTransport<HttpTransport[]>,
FallbackTransport<readonly HttpTransport[]>,
Chain,
PrivateKeyAccount,
Account,
[...PublicRpcSchema, ...WalletRpcSchema],
PublicActions<FallbackTransport<HttpTransport[]>, Chain> & WalletActions<Chain, PrivateKeyAccount>
PublicActions<FallbackTransport<readonly HttpTransport[]>, Chain> & WalletActions<Chain, Account>
>;

export type L1Clients = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ describe('ProvingBrokerPersistedDatabase', () => {
batchSize = 5;

config = {
dataStoreMapSizeKB: 1024 * 1024 * 1024, // 1GB
dataStoreMapSizeKB: 1024 * 1024, // 1GB
dataDirectory: directory,
proverBrokerJobMaxRetries: 1,
proverBrokerJobTimeoutMs: 1000,
Expand Down