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: Configure sandbox for network #2818

Merged
merged 18 commits into from
Oct 13, 2023
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",
PhilWindle marked this conversation as resolved.
Show resolved Hide 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