Skip to content
Merged
17 changes: 17 additions & 0 deletions yarn-project/aztec-node/src/aztec-node/server.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { createEthereumChain } from '@aztec/ethereum';

import { AztecNodeConfig, AztecNodeService } from '../index.js';

describe('aztec node service', () => {
it('fails to create Aztec Node if given incorrect chain id', async () => {
const config: Partial<AztecNodeConfig> = {
rpcUrl: 'testnet',
apiKey: '12345',
chainId: 12345, // not the testnet chain id
};
const ethereumChain = createEthereumChain(config.rpcUrl!, config.apiKey);
await expect(() => AztecNodeService.createAndSync(config as AztecNodeConfig)).rejects.toThrow(
`RPC URL configured for chain id ${ethereumChain.chainInfo.id} but expected id ${config.chainId}`,
);
});
});
13 changes: 10 additions & 3 deletions yarn-project/aztec-node/src/aztec-node/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
PRIVATE_DATA_TREE_HEIGHT,
} from '@aztec/circuits.js';
import { computePublicDataTreeIndex } from '@aztec/circuits.js/abis';
import { L1ContractAddresses } from '@aztec/ethereum';
import { L1ContractAddresses, createEthereumChain } from '@aztec/ethereum';
import { AztecAddress } from '@aztec/foundation/aztec-address';
import { createDebugLogger } from '@aztec/foundation/log';
import { InMemoryTxPool, P2P, createP2PClient } from '@aztec/p2p';
Expand Down Expand Up @@ -73,7 +73,7 @@ export class AztecNodeService implements AztecNode {
private log = createDebugLogger('aztec:node'),
) {
const message =
`Started Aztec Node with contracts - \n` +
`Started Aztec Node against chain 0x${chainId.toString(16)} with contracts - \n` +
`Rollup: ${config.l1Contracts.rollupAddress.toString()}\n` +
`Registry: ${config.l1Contracts.registryAddress.toString()}\n` +
`Inbox: ${config.l1Contracts.inboxAddress.toString()}\n` +
Expand All @@ -88,6 +88,13 @@ export class AztecNodeService implements AztecNode {
* @returns - A fully synced Aztec Node for use in development/testing.
*/
public static async createAndSync(config: AztecNodeConfig) {
const ethereumChain = createEthereumChain(config.rpcUrl, config.apiKey);
//validate that the actual chain id matches that specified in configuration
if (config.chainId !== ethereumChain.chainInfo.id) {
throw new Error(
`RPC URL configured for chain id ${ethereumChain.chainInfo.id} but expected id ${config.chainId}`,
);
}
// first create and sync the archiver
const archiver = await Archiver.createAndSync(config);

Expand Down Expand Up @@ -122,7 +129,7 @@ export class AztecNodeService implements AztecNode {
archiver,
worldStateSynchronizer,
sequencer,
config.chainId,
ethereumChain.chainInfo.id,
config.version,
getGlobalVariableBuilder(config),
db,
Expand Down
4 changes: 2 additions & 2 deletions yarn-project/aztec-node/terraform/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ resource "aws_ecs_task_definition" "aztec-node-1" {
[
{
"name": "${var.DEPLOY_TAG}-aztec-node-1",
"image": "${var.ECR_URL}/aztec-node:latest",
"image": "${var.ECR_URL}/aztec-node:aztec3-packages-prod",
Comment thread
PhilWindle marked this conversation as resolved.
"essential": true,
"memoryReservation": 3776,
"portMappings": [
Expand Down Expand Up @@ -388,7 +388,7 @@ resource "aws_ecs_task_definition" "aztec-node-2" {
[
{
"name": "${var.DEPLOY_TAG}-aztec-node-2",
"image": "${var.ECR_URL}/aztec-node:latest",
"image": "${var.ECR_URL}/aztec-node:aztec3-packages-prod",
"essential": true,
"memoryReservation": 3776,
"portMappings": [
Expand Down
16 changes: 13 additions & 3 deletions yarn-project/aztec-sandbox/src/bin/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,21 @@ const logger = createDebugLogger('aztec:sandbox');
* Creates the sandbox from provided config and deploys any initial L1 and L2 contracts
*/
async function createAndInitialiseSandbox() {
const { l1Contracts, node, pxe, stop } = await createSandbox();
const { aztecNodeConfig, node, pxe, stop } = await createSandbox();
if (aztecNodeConfig.p2pEnabled) {
logger.info(`Not setting up test accounts as we are connecting to a network`);
return {
aztecNodeConfig,
pxe,
node,
stop,
accounts: [],
};
}
logger.info('Setting up test accounts...');
const accounts = await deployInitialSandboxAccounts(pxe);
return {
l1Contracts,
aztecNodeConfig,
pxe,
node,
stop,
Expand Down Expand Up @@ -60,7 +70,7 @@ async function main() {
startHttpRpcServer(pxe, createPXERpcServer, PXE_PORT);
logger.info(`PXE JSON-RPC Server listening on port ${PXE_PORT}`);
logger.info(`Debug logs will be written to ${logPath}`);
const accountStrings = [`Initial Accounts:\n\n`];
const accountStrings = accounts.length ? [`Initial Accounts:\n\n`] : [];

const registeredAccounts = await pxe.getRegisteredAccounts();
for (const account of accounts) {
Expand Down
51 changes: 33 additions & 18 deletions yarn-project/aztec-sandbox/src/sandbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { AztecNodeConfig, AztecNodeService, getConfigEnvVars } from '@aztec/azte
import {
DeployL1Contracts,
L1ContractArtifactsForDeployment,
NULL_KEY,
createEthereumChain,
deployL1Contracts,
} from '@aztec/ethereum';
Expand All @@ -22,7 +23,7 @@ import {
} from '@aztec/l1-artifacts';
import { createPXEService, getPXEServiceConfig } from '@aztec/pxe';

import { createPublicClient, http as httpViemTransport } from 'viem';
import { HDAccount, createPublicClient, http as httpViemTransport } from 'viem';
import { mnemonicToAccount } from 'viem/accounts';
import { foundry } from 'viem/chains';

Expand Down Expand Up @@ -65,23 +66,12 @@ async function waitThenDeploy(config: AztecNodeConfig, deployFunction: () => Pro
return await deployFunction();
}

/** Sandbox settings. */
export type SandboxConfig = AztecNodeConfig & {
/** Mnemonic used to derive the L1 deployer private key.*/
l1Mnemonic: string;
};

/**
* Create and start a new Aztec Node and PXE. Deploys L1 contracts.
* Does not start any HTTP services nor populate any initial accounts.
* @param config - Optional Sandbox settings.
* Function to deploy our L1 contracts to the sandbox L1
* @param aztecNodeConfig - The Aztec Node Config
* @param hdAccount - Account for publishing L1 contracts
*/
export async function createSandbox(config: Partial<SandboxConfig> = {}) {
const aztecNodeConfig: AztecNodeConfig = { ...getConfigEnvVars(), ...config };
const pxeServiceConfig = getPXEServiceConfig();
const hdAccount = mnemonicToAccount(config.l1Mnemonic ?? MNEMONIC);
const privKey = hdAccount.getHdKey().privateKey;

async function deployContractsToL1(aztecNodeConfig: AztecNodeConfig, hdAccount: HDAccount) {
const l1Artifacts: L1ContractArtifactsForDeployment = {
contractDeploymentEmitter: {
contractAbi: ContractDeploymentEmitterAbi,
Expand All @@ -108,12 +98,37 @@ export async function createSandbox(config: Partial<SandboxConfig> = {}) {
const l1Contracts = await waitThenDeploy(aztecNodeConfig, () =>
deployL1Contracts(aztecNodeConfig.rpcUrl, hdAccount, localAnvil, logger, l1Artifacts),
);
aztecNodeConfig.publisherPrivateKey = `0x${Buffer.from(privKey!).toString('hex')}`;
aztecNodeConfig.l1Contracts.rollupAddress = l1Contracts.l1ContractAddresses.rollupAddress;
aztecNodeConfig.l1Contracts.contractDeploymentEmitterAddress =
l1Contracts.l1ContractAddresses.contractDeploymentEmitterAddress;
aztecNodeConfig.l1Contracts.inboxAddress = l1Contracts.l1ContractAddresses.inboxAddress;
aztecNodeConfig.l1Contracts.registryAddress = l1Contracts.l1ContractAddresses.registryAddress;
return l1Contracts;
}

/** Sandbox settings. */
export type SandboxConfig = AztecNodeConfig & {
/** Mnemonic used to derive the L1 deployer private key.*/
l1Mnemonic: string;
};

/**
* Create and start a new Aztec Node and PXE. Deploys L1 contracts.
* Does not start any HTTP services nor populate any initial accounts.
* @param config - Optional Sandbox settings.
*/
export async function createSandbox(config: Partial<SandboxConfig> = {}) {
const aztecNodeConfig: AztecNodeConfig = { ...getConfigEnvVars(), ...config };
const pxeServiceConfig = getPXEServiceConfig();
const hdAccount = mnemonicToAccount(config.l1Mnemonic ?? MNEMONIC);
if (aztecNodeConfig.publisherPrivateKey === NULL_KEY) {
const privKey = hdAccount.getHdKey().privateKey;
aztecNodeConfig.publisherPrivateKey = `0x${Buffer.from(privKey!).toString('hex')}`;
}

if (!aztecNodeConfig.p2pEnabled) {
await deployContractsToL1(aztecNodeConfig, hdAccount);
}

const node = await AztecNodeService.createAndSync(aztecNodeConfig);
const pxe = await createPXEService(node, pxeServiceConfig);
Expand All @@ -123,5 +138,5 @@ export async function createSandbox(config: Partial<SandboxConfig> = {}) {
await node.stop();
};

return { node, pxe, l1Contracts, stop };
return { node, pxe, aztecNodeConfig, stop };
}
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ export class DeployMethod<TContract extends ContractBase = Contract> extends Bas
*/
public send(options: DeployOptions = {}): DeploySentTx<TContract> {
const txHashPromise = super.send(options).getTxHash();
return new DeploySentTx(this.artifact, this.pxe, txHashPromise);
return new DeploySentTx(this.artifact, this.pxe, txHashPromise, this.completeAddress);
}

/**
Expand Down
13 changes: 11 additions & 2 deletions yarn-project/aztec.js/src/contract_deployer/deploy_sent_tx.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { FieldsOf } from '@aztec/circuits.js';
import { CompleteAddress, FieldsOf } from '@aztec/circuits.js';
import { ContractArtifact } from '@aztec/foundation/abi';
import { TxHash, TxReceipt } from '@aztec/types';

Expand All @@ -20,7 +20,16 @@ export type DeployTxReceipt<TContract extends ContractBase = Contract> = FieldsO
* A contract deployment transaction sent to the network, extending SentTx with methods to create a contract instance.
*/
export class DeploySentTx<TContract extends Contract = Contract> extends SentTx {
constructor(private artifact: ContractArtifact, wallet: PXE | Wallet, txHashPromise: Promise<TxHash>) {
constructor(
private artifact: ContractArtifact,
wallet: PXE | Wallet,
txHashPromise: Promise<TxHash>,

/**
* The complete address of the deployed contract
*/
public completeContractAddress?: CompleteAddress,
) {
super(wallet, txHashPromise);
}

Expand Down
7 changes: 4 additions & 3 deletions yarn-project/cli/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,8 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command {
const deployed = await tx.wait();
log(`\nContract deployed at ${deployed.contractAddress!.toString()}\n`);
} else {
log(`\nDeployment transaction hash: ${txHash}\n`);
log(`\nContract Address: ${tx.completeContractAddress?.address.toString() ?? 'N/A'}`);
log(`Deployment transaction hash: ${txHash}\n`);
}
});

Expand Down Expand Up @@ -458,7 +459,7 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command {
const wallet = await getSchnorrAccount(client, privateKey, privateKey, accountCreationSalt).getWallet();
const contract = await Contract.at(contractAddress, contractArtifact, wallet);
const tx = contract.methods[functionName](...functionArgs).send();
log(`Transaction hash: ${(await tx.getTxHash()).toString()}`);
log(`\nTransaction hash: ${(await tx.getTxHash()).toString()}`);
if (options.wait) {
await tx.wait();

Expand All @@ -469,7 +470,7 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command {
log(`Block number: ${receipt.blockNumber}`);
log(`Block hash: ${receipt.blockHash?.toString('hex')}`);
} else {
log('\nTransaction pending. Check status with get-tx-receipt');
log('Transaction pending. Check status with get-tx-receipt');
}
});

Expand Down
11 changes: 7 additions & 4 deletions yarn-project/end-to-end/src/integration_l1_publisher.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
range,
} from '@aztec/circuits.js';
import { fr, makeNewContractData, makeProof } from '@aztec/circuits.js/factories';
import { createEthereumChain } from '@aztec/ethereum';
import { Fr } from '@aztec/foundation/fields';
import { createDebugLogger } from '@aztec/foundation/log';
import { to2Fields } from '@aztec/foundation/serialize';
Expand Down Expand Up @@ -87,6 +88,8 @@ describe('L1Publisher integration', () => {
// The global variables of the last rollup
let prevGlobals: GlobalVariables;

const chainId = createEthereumChain(config.rpcUrl, config.apiKey).chainInfo.id;

beforeEach(async () => {
deployerAccount = privateKeyToAccount(deployerPK);
const {
Expand Down Expand Up @@ -148,7 +151,7 @@ describe('L1Publisher integration', () => {
const historicTreeRoots = await getHistoricBlockData(builderDb, prevGlobals);
const tx = await makeEmptyProcessedTxFromHistoricTreeRoots(
historicTreeRoots,
new Fr(config.chainId),
new Fr(chainId),
new Fr(config.version),
);
return tx;
Expand All @@ -157,7 +160,7 @@ describe('L1Publisher integration', () => {
const makeBloatedProcessedTx = async (seed = 0x1) => {
const tx = mockTx(seed);
const kernelOutput = KernelCircuitPublicInputs.empty();
kernelOutput.constants.txContext.chainId = fr(config.chainId);
kernelOutput.constants.txContext.chainId = fr(chainId);
kernelOutput.constants.txContext.version = fr(config.version);
kernelOutput.constants.blockData = await getHistoricBlockData(builderDb, prevGlobals);
kernelOutput.end.publicDataUpdateRequests = makeTuple(
Expand Down Expand Up @@ -267,7 +270,7 @@ describe('L1Publisher integration', () => {
await makeBloatedProcessedTx(totalNullifiersPerBlock * i + 4 * MAX_NEW_NULLIFIERS_PER_TX),
];
const globalVariables = new GlobalVariables(
new Fr(config.chainId),
new Fr(chainId),
new Fr(config.version),
new Fr(1 + i),
new Fr(await rollup.read.lastBlockTs()),
Expand Down Expand Up @@ -359,7 +362,7 @@ describe('L1Publisher integration', () => {
await makeEmptyProcessedTx(),
];
const globalVariables = new GlobalVariables(
new Fr(config.chainId),
new Fr(chainId),
new Fr(config.version),
new Fr(1 + i),
new Fr(await rollup.read.lastBlockTs()),
Expand Down
3 changes: 3 additions & 0 deletions yarn-project/ethereum/src/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { Hex } from 'viem';

export const NULL_KEY: Hex = `0x${'0000000000000000000000000000000000000000000000000000000000000000'}`;
1 change: 1 addition & 0 deletions yarn-project/ethereum/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { createTestnetChain } from './testnet.js';
export * from './testnet.js';
export * from './deploy_l1_contracts.js';
export * from './l1_contract_addresses.js';
export * from './constants.js';

/**
* Helper function to create an instance of Aztec Chain from an rpc url and api key.
Expand Down
4 changes: 2 additions & 2 deletions yarn-project/p2p-bootstrap/terraform/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ resource "aws_ecs_task_definition" "aztec-bootstrap-1" {
[
{
"name": "${var.DEPLOY_TAG}-aztec-bootstrap-1",
"image": "${var.ECR_URL}/p2p-bootstrap:latest",
"image": "${var.ECR_URL}/p2p-bootstrap:aztec3-packages-prod",
"essential": true,
"command": ["start"],
"memoryReservation": 3776,
Expand Down Expand Up @@ -273,7 +273,7 @@ resource "aws_ecs_task_definition" "aztec-bootstrap-2" {
[
{
"name": "${var.DEPLOY_TAG}-aztec-bootstrap-2",
"image": "${var.ECR_URL}/p2p-bootstrap:latest",
"image": "${var.ECR_URL}/p2p-bootstrap:aztec3-packages-prod",
"essential": true,
"command": ["start"],
"memoryReservation": 3776,
Expand Down
12 changes: 6 additions & 6 deletions yarn-project/sequencer-client/src/config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { L1ContractAddresses } from '@aztec/ethereum';
import { L1ContractAddresses, NULL_KEY } from '@aztec/ethereum';
import { EthAddress } from '@aztec/foundation/eth-address';

import { Hex } from 'viem';

import { GlobalReaderConfig } from './global_variable_builder/index.js';
import { PublisherConfig, TxSenderConfig } from './publisher/config.js';
import { SequencerConfig } from './sequencer/config.js';
Expand Down Expand Up @@ -43,11 +45,9 @@ export function getConfigEnvVars(): SequencerClientConfig {
CONTRACT_DEPLOYMENT_EMITTER_ADDRESS,
} = process.env;

const publisherPrivateKey: `0x${string}` = `0x${
SEQ_PUBLISHER_PRIVATE_KEY
? SEQ_PUBLISHER_PRIVATE_KEY.replace('0x', '')
: '0000000000000000000000000000000000000000000000000000000000000000'
}`;
const publisherPrivateKey: Hex = SEQ_PUBLISHER_PRIVATE_KEY
? `0x${SEQ_PUBLISHER_PRIVATE_KEY.replace('0x', '')}`
: NULL_KEY;
// Populate the relevant addresses for use by the sequencer
const addresses: L1ContractAddresses = {
rollupAddress: ROLLUP_CONTRACT_ADDRESS ? EthAddress.fromString(ROLLUP_CONTRACT_ADDRESS) : EthAddress.ZERO,
Expand Down
Loading