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

fix: L1 deployment on reth #12060

Merged
merged 3 commits into from
Feb 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
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
1 change: 1 addition & 0 deletions spartan/aztec-network/eth-devnet/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ services:
- "${PWD}/out/jwt-secret.hex:/genesis/jwt-secret.hex"
environment:
- HTTP_PORT=8545
- WS_PORT=8546
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

run-locally was failing without this since #11922

- MAX_TX_INPUT_SIZE_BYTES=1310720

eth_beacon:
Expand Down
2 changes: 1 addition & 1 deletion spartan/aztec-network/eth-devnet/run-locally.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
REPO_ROOT=$(git rev-parse --show-toplevel)

${REPO_ROOT}/spartan/aztec-network/eth-devnet/create.sh
(cd ${REPO_ROOT}/spartan/aztec-network/eth-devnet && docker compose build && docker compose up)
(cd ${REPO_ROOT}/spartan/aztec-network/eth-devnet && docker compose down -v && docker compose build && docker compose up)
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The down -v ensures volumes are cleaned up. Otherwise the containers will use the volumes with the config from an old create.sh run and fail to start.

Copy link
Member

Choose a reason for hiding this comment

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

thanks for adding that

2 changes: 1 addition & 1 deletion yarn-project/end-to-end/src/fixtures/snapshot_manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ async function setupFromFresh(

// Start anvil. We go via a wrapper script to ensure if the parent dies, anvil dies.
logger.verbose('Starting anvil...');
const res = await startAnvil(opts.ethereumSlotDuration);
const res = await startAnvil({ l1BlockTime: opts.ethereumSlotDuration });
const anvil = res.anvil;
aztecNodeConfig.l1RpcUrl = res.rpcUrl;

Expand Down
2 changes: 1 addition & 1 deletion yarn-project/end-to-end/src/fixtures/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ export async function setup(
);
}

const res = await startAnvil(opts.ethereumSlotDuration);
const res = await startAnvil({ l1BlockTime: opts.ethereumSlotDuration });
anvil = res.anvil;
config.l1RpcUrl = res.rpcUrl;
}
Expand Down
3 changes: 2 additions & 1 deletion yarn-project/ethereum/src/contracts/forwarder.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@ import { type PrivateKeyAccount, privateKeyToAccount } from 'viem/accounts';
import { foundry } from 'viem/chains';

import { DefaultL1ContractsConfig } from '../config.js';
import { type L1Clients, createL1Clients, deployL1Contract, deployL1Contracts } from '../deploy_l1_contracts.js';
import { createL1Clients, deployL1Contract, deployL1Contracts } from '../deploy_l1_contracts.js';
import { L1TxUtils } from '../l1_tx_utils.js';
import { startAnvil } from '../test/start_anvil.js';
import { type L1Clients } from '../types.js';
import { FormattedViemError } from '../utils.js';
import { ForwarderContract } from './forwarder.js';

Expand Down
3 changes: 2 additions & 1 deletion yarn-project/ethereum/src/contracts/forwarder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ import {
getContract,
} from 'viem';

import { type L1Clients, deployL1Contract } from '../deploy_l1_contracts.js';
import { deployL1Contract } from '../deploy_l1_contracts.js';
import { type L1BlobInputs, type L1GasConfig, type L1TxRequest, type L1TxUtils } from '../l1_tx_utils.js';
import { type L1Clients } from '../types.js';
import { RollupContract } from './rollup.js';

export class ForwarderContract {
Expand Down
2 changes: 1 addition & 1 deletion yarn-project/ethereum/src/contracts/governance_proposer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import {
getContract,
} from 'viem';

import type { L1Clients } from '../deploy_l1_contracts.js';
import type { GasPrice, L1TxRequest, L1TxUtils } from '../l1_tx_utils.js';
import { type L1Clients } from '../types.js';
import { type IEmpireBase, encodeVote } from './empire_base.js';

export class GovernanceProposerContract implements IEmpireBase {
Expand Down
2 changes: 1 addition & 1 deletion yarn-project/ethereum/src/contracts/slashing_proposer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import {
getContract,
} from 'viem';

import type { L1Clients } from '../deploy_l1_contracts.js';
import type { L1TxRequest } from '../l1_tx_utils.js';
import type { L1Clients } from '../types.js';
import { type IEmpireBase, encodeVote } from './empire_base.js';

export class SlashingProposerContract implements IEmpireBase {
Expand Down
27 changes: 20 additions & 7 deletions yarn-project/ethereum/src/deploy_l1_contracts.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,15 @@ import { Fr } from '@aztec/foundation/fields';
import { type Logger, createLogger } from '@aztec/foundation/log';
import { RollupAbi } from '@aztec/l1-artifacts/RollupAbi';

import { type Anvil } from '@viem/anvil';
import { getContract } from 'viem';
import { type PrivateKeyAccount, privateKeyToAccount } from 'viem/accounts';
import { foundry } from 'viem/chains';

import { createEthereumChain } from './chain.js';
import { DefaultL1ContractsConfig } from './config.js';
import { type DeployL1ContractsArgs, deployL1Contracts } from './deploy_l1_contracts.js';
import { startAnvil } from './test/start_anvil.js';

describe('deploy_l1_contracts', () => {
let anvil: Anvil;
let rpcUrl: string;
let privateKey: PrivateKeyAccount;
let logger: Logger;

Expand All @@ -27,6 +24,13 @@ describe('deploy_l1_contracts', () => {
let initialValidators: EthAddress[];
let l2FeeJuiceAddress: AztecAddress;

// Use these environment variables to run against a live node. Eg to test against spartan's eth-devnet:
// BLOCK_TIME=1 spartan/aztec-network/eth-devnet/run-locally.sh
// LOG_LEVEL=verbose L1_RPC_URL=http://localhost:8545 L1_CHAIN_ID=1337 yarn test deploy_l1_contracts
const chainId = process.env.L1_CHAIN_ID ? parseInt(process.env.L1_CHAIN_ID, 10) : 31337;
let rpcUrl = process.env.L1_RPC_URL;
let stop: () => Promise<void> = () => Promise.resolve();

beforeAll(async () => {
logger = createLogger('ethereum:test:deploy_l1_contracts');
privateKey = privateKeyToAccount('0x8b3a350cf5c34c9194ca85829a2df0ec3153be0318b5e2d3348e872092edffba');
Expand All @@ -37,22 +41,31 @@ describe('deploy_l1_contracts', () => {
initialValidators = times(3, EthAddress.random);
l2FeeJuiceAddress = await AztecAddress.random();

({ anvil, rpcUrl } = await startAnvil());
if (!rpcUrl) {
({ stop, rpcUrl } = await startAnvil());
}
});

afterAll(async () => {
await anvil.stop().catch(err => createLogger('cleanup').error(err));
if (stop) {
try {
await stop();
} catch (err) {
createLogger('ethereum:cleanup').error(`Error during cleanup`, err);
}
}
});

const deploy = (args: Partial<DeployL1ContractsArgs> = {}) =>
deployL1Contracts(rpcUrl, privateKey, foundry, logger, {
deployL1Contracts(rpcUrl!, privateKey, createEthereumChain(rpcUrl!, chainId).chainInfo, logger, {
...DefaultL1ContractsConfig,
salt: undefined,
vkTreeRoot,
protocolContractTreeRoot,
genesisArchiveRoot,
genesisBlockHash,
l2FeeJuiceAddress,
l1TxConfig: { checkIntervalMs: 100 },
...args,
});

Expand Down
36 changes: 17 additions & 19 deletions yarn-project/ethereum/src/deploy_l1_contracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,10 @@ import type { Abi, Narrow } from 'abitype';
import {
type Account,
type Chain,
type Client,
type Hex,
type HttpTransport,
type PublicActions,
type PublicClient,
type PublicRpcSchema,
type WalletActions,
type WalletClient,
type WalletRpcSchema,
concatHex,
createPublicClient,
createWalletClient,
Expand All @@ -68,6 +63,7 @@ import { isAnvilTestChain } from './chain.js';
import { type L1ContractsConfig } from './config.js';
import { type L1ContractAddresses } from './l1_contract_addresses.js';
import { L1TxUtils, type L1TxUtilsConfig, defaultL1TxUtilsConfig } from './l1_tx_utils.js';
import type { L1Clients } from './types.js';

export const DEPLOYER_ADDRESS: Hex = '0x4e59b44847b379578588920cA78FbF26c0B4956C';

Expand Down Expand Up @@ -206,19 +202,10 @@ export interface DeployL1ContractsArgs extends L1ContractsConfig {
salt: number | undefined;
/** The initial validators for the rollup contract. */
initialValidators?: EthAddress[];
/** Configuration for the L1 tx utils module. */
l1TxConfig?: Partial<L1TxUtilsConfig>;
}

export type L1Clients = {
publicClient: PublicClient<HttpTransport, Chain>;
walletClient: Client<
HttpTransport,
Chain,
PrivateKeyAccount,
[...WalletRpcSchema, ...PublicRpcSchema],
PublicActions<HttpTransport, Chain> & WalletActions<Chain, PrivateKeyAccount>
>;
};

/**
* Creates a wallet and a public viem client for interacting with L1.
* @param rpcUrl - RPC URL to connect to L1.
Expand Down Expand Up @@ -353,7 +340,7 @@ export const deployL1Contracts = async (
await govDeployer.waitForDeployments();
logger.verbose(`All governance contracts deployed`);

const deployer = new L1Deployer(walletClient, publicClient, args.salt, logger);
const deployer = new L1Deployer(walletClient, publicClient, args.salt, logger, args.l1TxConfig ?? {});

const feeJuicePortalAddress = await deployer.deploy(l1Artifacts.feeJuicePortal, [
registryAddress.toString(),
Expand Down Expand Up @@ -665,11 +652,11 @@ export async function deployL1Contract(
}

const replacements: Record<string, EthAddress> = {};

const libraryTxs: Hex[] = [];
for (const libraryName in libraries?.libraryCode) {
const lib = libraries.libraryCode[libraryName];

const { address } = await deployL1Contract(
const { address, txHash } = await deployL1Contract(
walletClient,
publicClient,
lib.contractAbi,
Expand All @@ -681,6 +668,10 @@ export async function deployL1Contract(
l1TxUtils,
);

if (txHash) {
libraryTxs.push(txHash);
}

for (const linkRef in libraries.linkReferences) {
for (const contractName in libraries.linkReferences[linkRef]) {
// If the library name matches the one we just deployed, we replace it.
Expand All @@ -706,6 +697,13 @@ export async function deployL1Contract(
const replacement = replacements[toReplace].toString().slice(2);
bytecode = bytecode.replace(new RegExp(escapeRegExp(toReplace), 'g'), replacement) as Hex;
}

// Reth fails gas estimation if the deployed contract attempts to call a library that is not yet deployed,
// so we wait for all library deployments to be mined before deploying the contract.
if (libraryTxs.length > 0) {
logger?.verbose(`Awaiting for linked libraries to be deployed`);
await Promise.all(libraryTxs.map(txHash => publicClient.waitForTransactionReceipt({ hash: txHash })));
}
}

if (maybeSalt) {
Expand Down
2 changes: 1 addition & 1 deletion yarn-project/ethereum/src/l1_tx_utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ describe('GasUtils', () => {
const logger = createLogger('ethereum:test:l1_gas_test');

beforeAll(async () => {
const { anvil: anvilInstance, rpcUrl } = await startAnvil(1);
const { anvil: anvilInstance, rpcUrl } = await startAnvil({ l1BlockTime: 1 });
anvil = anvilInstance;
cheatCodes = new EthCheatCodes(rpcUrl);
const hdAccount = mnemonicToAccount(MNEMONIC, { addressIndex: 0 });
Expand Down
2 changes: 1 addition & 1 deletion yarn-project/ethereum/src/l1_tx_utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import {
hexToBytes,
} from 'viem';

import { type L1Clients } from './deploy_l1_contracts.js';
import { type L1Clients } from './types.js';
import { formatViemError } from './utils.js';

// 1_000_000_000 Gwei = 1 ETH
Expand Down
10 changes: 7 additions & 3 deletions yarn-project/ethereum/src/test/start_anvil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ import { dirname, resolve } from 'path';
/**
* Ensures there's a running Anvil instance and returns the RPC URL.
*/
export async function startAnvil(l1BlockTime?: number): Promise<{ anvil: Anvil; rpcUrl: string }> {
export async function startAnvil(
opts: {
l1BlockTime?: number;
} = {},
): Promise<{ anvil: Anvil; rpcUrl: string; stop: () => Promise<void> }> {
const anvilBinary = resolve(dirname(fileURLToPath(import.meta.url)), '../../', 'scripts/anvil_kill_wrapper.sh');

let port: number | undefined;
Expand All @@ -19,7 +23,7 @@ export async function startAnvil(l1BlockTime?: number): Promise<{ anvil: Anvil;
const anvil = createAnvil({
anvilBinary,
port: 0,
blockTime: l1BlockTime,
blockTime: opts.l1BlockTime,
stopTimeout: 1000,
});

Expand All @@ -44,5 +48,5 @@ export async function startAnvil(l1BlockTime?: number): Promise<{ anvil: Anvil;

// Monkeypatch the anvil instance to include the actually assigned port
Object.defineProperty(anvil, 'port', { value: port, writable: false });
return { anvil, rpcUrl: `http://127.0.0.1:${port}` };
return { anvil, stop: () => anvil.stop(), rpcUrl: `http://127.0.0.1:${port}` };
}
2 changes: 1 addition & 1 deletion yarn-project/ethereum/src/test/tx_delayer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ describe('tx_delayer', () => {
const ETHEREUM_SLOT_DURATION = 2;

beforeAll(async () => {
({ anvil, rpcUrl } = await startAnvil(ETHEREUM_SLOT_DURATION));
({ anvil, rpcUrl } = await startAnvil({ l1BlockTime: ETHEREUM_SLOT_DURATION }));
logger = createLogger('ethereum:test:tx_delayer');
});

Expand Down
6 changes: 6 additions & 0 deletions yarn-project/ethereum/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,9 @@ export type ViemClient = Client<

/** Type for a viem public client */
export type ViemPublicClient = PublicClient<HttpTransport, Chain>;

/** Both L1 clients */
export type L1Clients = {
publicClient: ViemPublicClient;
walletClient: ViemClient;
};