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
12 changes: 9 additions & 3 deletions yarn-project/aztec-node/src/aztec-node/server.ts
Original file line number Diff line number Diff line change
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 @@ -91,6 +91,12 @@ export class AztecNodeService implements AztecNode {
// first create and sync the archiver
const archiver = await Archiver.createAndSync(config);

// get the chain id here
const lastBlockNumber = await archiver.getBlockNumber();
const globalVariableBuilder = getGlobalVariableBuilder(config);
// just use the next block number for this query
const globalVariables = await globalVariableBuilder.buildGlobalVariables(new Fr(lastBlockNumber + 1));

// we identify the P2P transaction protocol by using the rollup contract address.
// this may well change in future
config.transactionProtocol = `/aztec/tx/${config.l1Contracts.rollupAddress.toString()}`;
Expand Down Expand Up @@ -122,9 +128,9 @@ export class AztecNodeService implements AztecNode {
archiver,
worldStateSynchronizer,
sequencer,
config.chainId,
Number(globalVariables.chainId.value),
config.version,
getGlobalVariableBuilder(config),
globalVariableBuilder,
db,
);
}
Expand Down
12 changes: 2 additions & 10 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",
"essential": true,
"memoryReservation": 3776,
"portMappings": [
Expand Down Expand Up @@ -195,10 +195,6 @@ resource "aws_ecs_task_definition" "aztec-node-1" {
"name": "P2P_ENABLED",
"value": "true"
},
{
"name": "CHAIN_ID",
"value": "${var.CHAIN_ID}"
},
{
"name": "PEER_ID_PRIVATE_KEY",
"value": "${var.NODE_1_PRIVATE_KEY}"
Expand Down Expand Up @@ -392,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 Expand Up @@ -488,10 +484,6 @@ resource "aws_ecs_task_definition" "aztec-node-2" {
"name": "P2P_ENABLED",
"value": "true"
},
{
"name": "CHAIN_ID",
"value": "${var.CHAIN_ID}"
},
{
"name": "PEER_ID_PRIVATE_KEY",
"value": "${var.NODE_2_PRIVATE_KEY}"
Expand Down
4 changes: 0 additions & 4 deletions yarn-project/aztec-node/terraform/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,6 @@ variable "SEQ_2_PUBLISHER_PRIVATE_KEY" {
type = string
}

variable "CHAIN_ID" {
type = string
}

variable "BOOTNODE_1_LISTEN_PORT" {
type = string
}
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 };
}
10 changes: 6 additions & 4 deletions yarn-project/cli/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,14 +218,16 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command {
const args = encodeArgs(rawArgs, constructorArtifact!.parameters);
debugLogger(`Encoded arguments: ${args.join(', ')}`);

const tx = deployer.deploy(...args).send({ contractAddressSalt: salt });
const deployMethod = deployer.deploy(...args);
const tx = deployMethod.send({ contractAddressSalt: salt });
const txHash = await tx.getTxHash();
debugLogger(`Deploy tx sent with hash ${txHash}`);
if (wait) {
const deployed = await tx.wait();
log(`\nContract deployed at ${deployed.contractAddress!.toString()}\n`);
} else {
log(`\nDeployment transaction hash: ${txHash}\n`);
log(`\nContract Address: ${deployMethod.completeAddress?.address.toString() ?? 'N/A'}`);
Copy link
Contributor

Choose a reason for hiding this comment

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

This API kind of sucks, you shouldn't need to keep the deployMethod around just to get the deployment address. Maybe we should inject it into yarn-project/aztec.js/src/contract_deployer/deploy_sent_tx.ts so you can query it from the tx object directly?

(not a note for this PR, but more of a comment for something we need to change elsewhere)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yeah I thought it was a bit rubbish. I went ahead and made the change.

log(`Deployment transaction hash: ${txHash}\n`);
}
});

Expand Down Expand Up @@ -458,7 +460,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 +471,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
10 changes: 6 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 @@ -87,6 +87,8 @@ describe('L1Publisher integration', () => {
// The global variables of the last rollup
let prevGlobals: GlobalVariables;

const chainId = 1;

beforeEach(async () => {
deployerAccount = privateKeyToAccount(deployerPK);
const {
Expand Down Expand Up @@ -148,7 +150,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 +159,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 +269,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 +361,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
16 changes: 6 additions & 10 deletions yarn-project/sequencer-client/src/config.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
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';

/** Chain configuration. */
type ChainConfig = {
/** The chain id of the ethereum host. */
chainId: number;
/** The version of the rollup. */
version: number;
};
Expand All @@ -29,7 +29,6 @@ export function getConfigEnvVars(): SequencerClientConfig {
const {
SEQ_PUBLISHER_PRIVATE_KEY,
ETHEREUM_HOST,
CHAIN_ID,
VERSION,
API_KEY,
SEQ_REQUIRED_CONFIRMATIONS,
Expand All @@ -43,11 +42,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 All @@ -62,7 +59,6 @@ export function getConfigEnvVars(): SequencerClientConfig {

return {
rpcUrl: ETHEREUM_HOST ? ETHEREUM_HOST : '',
chainId: CHAIN_ID ? +CHAIN_ID : 31337, // 31337 is the default chain id for anvil
Copy link
Contributor

Choose a reason for hiding this comment

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

Why remove the chain id from the configuration? It's usually a good practice to include the chain id as a safeguard to ensure you don't accidentally connect to the wrong network by entering an incorrect RPC URL.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That's a good point. I added the chain Id configuration back in and validate it on Aztec Node creation.

version: VERSION ? +VERSION : 1, // 1 is our default version
apiKey: API_KEY,
requiredConfirmations: SEQ_REQUIRED_CONFIRMATIONS ? +SEQ_REQUIRED_CONFIRMATIONS : 1,
Expand Down
Loading