Skip to content

Commit

Permalink
feat: Deterministic deployments for L1 (#8031)
Browse files Browse the repository at this point in the history
This PR does multiple things. In retrospective, should've broken it into
multiple ones, but here we are.

## L1 contracts

This PR updates L1 contracts that depended on `msg.sender` during
deployment to instead accept the owner as an argument.

This allows us to use the [deterministic deployment
proxy](https://github.com/Arachnid/deterministic-deployment-proxy)
(already deployed to mainnet and to anvil by default) for deploying our
contracts using a salt (otherwise the factory contract would be
appointed as owner), so we can get different deployment addresses based
on the salt we use.

With the current setup we'd always get the same deployment addresses on
a fresh anvil instance, since contract addresses on ethereum are derived
from the sender address and an incremental nonce, and we are
consistently using the same deployer address.

## Creating data stores

Refactors calls to creating new stores to ensure they always go through
`initStoreForRollup`, which means that the lmdb store is cleared if we
detect that it was created for a different rollup address contract (we
should be using an Aztec Chain ID, though maybe we should make the
rollup contract address **be** the chain id? anyway, that's another
discussion).

This, combined with a rollup contract address that can be different on
each deployment, means that our components should automatically clean
their db if connected to a different L1 rollup.

## Creating dirs

Adds mkdir (recursive) calls wherever they were missing, so we no longer
need to manually create data or working dirs in an init container in our
ECS tasks.

## Deployments

Removes the forced EFS replacement for each task, so they can reuse the
same filesystem, which should greatly improve deployment times (from 2
min to 10 seconds). Given the above tasks, we can now rely on the
changing rollup contract address for our components to init a new db as
needed.

To ensure we get a fresh rollup address on each deployment, we bind the
deployment salt to the github run id, which should be unique.
  • Loading branch information
spalladino authored Aug 16, 2024
1 parent 0dc7a50 commit abc6b19
Show file tree
Hide file tree
Showing 28 changed files with 188 additions and 171 deletions.
5 changes: 3 additions & 2 deletions .github/workflows/devnet-deploys.yml
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,7 @@ jobs:
--private-key ${{ env.CONTRACT_PUBLISHER_PRIVATE_KEY }} \
--rpc-url https://${{ env.DEPLOY_TAG }}-mainnet-fork.aztec.network:8545/${{ env.API_KEY }} \
--l1-chain-id ${{ env.L1_CHAIN_ID }} \
--salt ${{ github.run_id }} \
--json | tee ./l1_contracts.json
# upload contract addresses to S3
Expand Down Expand Up @@ -436,7 +437,7 @@ jobs:
working-directory: ./yarn-project/aztec/terraform/node
run: |
terraform init -input=false -backend-config="key=${{ env.DEPLOY_TAG }}/aztec-node"
terraform apply -input=false -auto-approve -replace="aws_efs_file_system.node_data_store" -var="NODE_P2P_TCP_PORT=${{ needs.set-network.outputs.node_tcp_range_start }}" -var="NODE_P2P_UDP_PORT=${{ needs.set-network.outputs.node_udp_range_start }}"
terraform apply -input=false -auto-approve -var="NODE_P2P_TCP_PORT=${{ needs.set-network.outputs.node_tcp_range_start }}" -var="NODE_P2P_UDP_PORT=${{ needs.set-network.outputs.node_udp_range_start }}"
- name: Deploy Aztec Prover Nodes
working-directory: ./yarn-project/aztec/terraform/prover-node
Expand All @@ -454,7 +455,7 @@ jobs:
working-directory: ./yarn-project/aztec/terraform/pxe
run: |
terraform init -input=false -backend-config="key=${{ env.DEPLOY_TAG }}/pxe"
terraform apply -input=false -auto-approve -replace="aws_efs_file_system.pxe_data_store"
terraform apply -input=false -auto-approve
bootstrap:
runs-on: ubuntu-latest
Expand Down
5 changes: 3 additions & 2 deletions l1-contracts/src/core/Rollup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,9 @@ contract Rollup is Leonidas, IRollup, ITestRollup {
IRegistry _registry,
IAvailabilityOracle _availabilityOracle,
IERC20 _fpcJuice,
bytes32 _vkTreeRoot
) Leonidas(msg.sender) {
bytes32 _vkTreeRoot,
address _ares
) Leonidas(_ares) {
verifier = new MockVerifier();
REGISTRY = _registry;
AVAILABILITY_ORACLE = _availabilityOracle;
Expand Down
2 changes: 2 additions & 0 deletions l1-contracts/src/core/interfaces/messagebridge/IRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,6 @@ interface IRegistry {
// docs:start:registry_number_of_versions
function numberOfVersions() external view returns (uint256);
// docs:end:registry_number_of_versions

function isRollupRegistered(address _rollup) external view returns (bool);
}
18 changes: 16 additions & 2 deletions l1-contracts/src/core/messagebridge/Registry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ contract Registry is IRegistry, Ownable {
mapping(uint256 version => DataStructures.RegistrySnapshot snapshot) internal snapshots;
mapping(address rollup => uint256 version) internal rollupToVersion;

constructor() Ownable(msg.sender) {
constructor(address _owner) Ownable(_owner) {
// Inserts a "dead" rollup at version 0
// This is simply done to make first version 1, which fits better with the rest of the system
upgrade(address(0xdead));
_upgrade(address(0xdead));
}

/**
Expand All @@ -49,6 +49,16 @@ contract Registry is IRegistry, Ownable {
return version;
}

/**
* @notice Returns whther the rollup is registered
* @param _rollup - The address of the rollup contract
* @return Whether the rollup is registered
*/
function isRollupRegistered(address _rollup) external view override(IRegistry) returns (bool) {
(, bool exists) = _getVersionFor(_rollup);
return exists;
}

/**
* @notice Fetches a snapshot of the registry indicated by `version`
* @dev the version is 0 indexed, so the first snapshot is version 0.
Expand Down Expand Up @@ -87,6 +97,10 @@ contract Registry is IRegistry, Ownable {
* @return The version of the new snapshot
*/
function upgrade(address _rollup) public override(IRegistry) onlyOwner returns (uint256) {
return _upgrade(_rollup);
}

function _upgrade(address _rollup) internal returns (uint256) {
(, bool exists) = _getVersionFor(_rollup);
if (exists) revert Errors.Registry__RollupAlreadyRegistered(_rollup);

Expand Down
2 changes: 1 addition & 1 deletion l1-contracts/test/Registry.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ contract RegistryTest is Test {
Registry internal registry;

function setUp() public {
registry = new Registry();
registry = new Registry(address(this));
}

function testConstructorSetup() public {
Expand Down
6 changes: 4 additions & 2 deletions l1-contracts/test/Rollup.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,12 @@ contract RollupTest is DecoderBase {
vm.warp(initialTime);
}

registry = new Registry();
registry = new Registry(address(this));
availabilityOracle = new AvailabilityOracle();
portalERC20 = new PortalERC20();
rollup = new Rollup(registry, availabilityOracle, IERC20(address(portalERC20)), bytes32(0));
rollup = new Rollup(
registry, availabilityOracle, IERC20(address(portalERC20)), bytes32(0), address(this)
);
inbox = Inbox(address(rollup.INBOX()));
outbox = Outbox(address(rollup.OUTBOX()));

Expand Down
7 changes: 4 additions & 3 deletions l1-contracts/test/portals/TokenPortal.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,11 @@ contract TokenPortalTest is Test {
uint256 internal l2BlockNumber = 69;

function setUp() public {
registry = new Registry();
registry = new Registry(address(this));
portalERC20 = new PortalERC20();
rollup =
new Rollup(registry, new AvailabilityOracle(), IERC20(address(portalERC20)), bytes32(0));
rollup = new Rollup(
registry, new AvailabilityOracle(), IERC20(address(portalERC20)), bytes32(0), address(this)
);
inbox = rollup.INBOX();
outbox = rollup.OUTBOX();

Expand Down
7 changes: 4 additions & 3 deletions l1-contracts/test/portals/UniswapPortal.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,11 @@ contract UniswapPortalTest is Test {
uint256 forkId = vm.createFork(vm.rpcUrl("mainnet_fork"));
vm.selectFork(forkId);

registry = new Registry();
registry = new Registry(address(this));
PortalERC20 portalERC20 = new PortalERC20();
rollup =
new Rollup(registry, new AvailabilityOracle(), IERC20(address(portalERC20)), bytes32(0));
rollup = new Rollup(
registry, new AvailabilityOracle(), IERC20(address(portalERC20)), bytes32(0), address(this)
);
registry.upgrade(address(rollup));
portalERC20.mint(address(rollup), 1000000);

Expand Down
6 changes: 4 additions & 2 deletions l1-contracts/test/sparta/DevNet.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,12 @@ contract DevNetTest is DecoderBase {
vm.warp(initialTime);
}

registry = new Registry();
registry = new Registry(address(this));
availabilityOracle = new AvailabilityOracle();
portalERC20 = new PortalERC20();
rollup = new Rollup(registry, availabilityOracle, IERC20(address(portalERC20)), bytes32(0));
rollup = new Rollup(
registry, availabilityOracle, IERC20(address(portalERC20)), bytes32(0), address(this)
);
inbox = Inbox(address(rollup.INBOX()));
outbox = Outbox(address(rollup.OUTBOX()));

Expand Down
6 changes: 4 additions & 2 deletions l1-contracts/test/sparta/Sparta.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,12 @@ contract SpartaTest is DecoderBase {
vm.warp(initialTime);
}

registry = new Registry();
registry = new Registry(address(this));
availabilityOracle = new AvailabilityOracle();
portalERC20 = new PortalERC20();
rollup = new Rollup(registry, availabilityOracle, IERC20(address(portalERC20)), bytes32(0));
rollup = new Rollup(
registry, availabilityOracle, IERC20(address(portalERC20)), bytes32(0), address(this)
);
inbox = Inbox(address(rollup.INBOX()));
outbox = Outbox(address(rollup.OUTBOX()));

Expand Down
1 change: 1 addition & 0 deletions yarn-project/aztec/src/cli/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ export function injectAztecCommands(program: Command, userLog: LogFn, debugLogge
process.exit(1);
}
}

installSignalHandlers(debugLogger.info, signalHandlers);

if (services.length) {
Expand Down
10 changes: 3 additions & 7 deletions yarn-project/aztec/src/cli/cmds/start_archiver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ import {
} from '@aztec/archiver';
import { createDebugLogger } from '@aztec/aztec.js';
import { type ServerList } from '@aztec/foundation/json-rpc/server';
import { AztecLmdbStore } from '@aztec/kv-store/lmdb';
import { initStoreForRollup } from '@aztec/kv-store/utils';
import { createStore } from '@aztec/kv-store/utils';
import {
createAndStartTelemetryClient,
getConfigEnvVars as getTelemetryClientConfig,
Expand All @@ -22,11 +21,8 @@ export const startArchiver = async (options: any, signalHandlers: (() => Promise
const archiverConfig = extractRelevantOptions<ArchiverConfig>(options, archiverConfigMappings);

const storeLog = createDebugLogger('aztec:archiver:lmdb');
const store = await initStoreForRollup(
AztecLmdbStore.open(archiverConfig.dataDirectory, false),
archiverConfig.l1Contracts.rollupAddress,
storeLog,
);
const rollupAddress = archiverConfig.l1Contracts.rollupAddress;
const store = await createStore(archiverConfig, rollupAddress, storeLog);
const archiverStore = new KVArchiverDataStore(store, archiverConfig.maxLogs);

const telemetry = createAndStartTelemetryClient(getTelemetryClientConfig());
Expand Down
1 change: 1 addition & 0 deletions yarn-project/aztec/src/sandbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ export async function deployContractsToL1(
l2FeeJuiceAddress: FeeJuiceAddress,
vkTreeRoot: getVKTreeRoot(),
assumeProvenUntil: opts.assumeProvenUntilBlockNumber,
salt: undefined,
}),
);

Expand Down
16 changes: 0 additions & 16 deletions yarn-project/aztec/terraform/node/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -148,18 +148,6 @@ resource "aws_ecs_task_definition" "aztec-node" {
}

container_definitions = jsonencode([
{
name = "init-container"
image = "amazonlinux:latest"
essential = false
command = ["sh", "-c", "mkdir -p ${local.data_dir}/node_${count.index + 1}/data ${local.data_dir}/node_${count.index + 1}/temp"]
mountPoints = [
{
containerPath = local.data_dir
sourceVolume = "efs-data-store"
}
]
},
{
name = "${var.DEPLOY_TAG}-aztec-node-${count.index + 1}"
image = "${var.DOCKERHUB_ACCOUNT}/aztec:${var.IMAGE_TAG}"
Expand Down Expand Up @@ -380,10 +368,6 @@ resource "aws_ecs_task_definition" "aztec-node" {
}
]
dependsOn = [
{
containerName = "init-container"
condition = "COMPLETE"
}
]
logConfiguration = {
logDriver = "awslogs"
Expand Down
16 changes: 0 additions & 16 deletions yarn-project/aztec/terraform/prover-node/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -148,18 +148,6 @@ resource "aws_ecs_task_definition" "aztec-prover-node" {
}

container_definitions = jsonencode([
{
name = "init-container"
image = "amazonlinux:latest"
essential = false
command = ["sh", "-c", "mkdir -p ${local.data_dir}/prover_node_${count.index + 1}/data ${local.data_dir}/prover_node_${count.index + 1}/temp"]
mountPoints = [
{
containerPath = local.data_dir
sourceVolume = "efs-data-store"
}
]
},
{
name = "${var.DEPLOY_TAG}-aztec-prover-node-${count.index + 1}"
image = "${var.DOCKERHUB_ACCOUNT}/aztec:${var.IMAGE_TAG}"
Expand Down Expand Up @@ -246,10 +234,6 @@ resource "aws_ecs_task_definition" "aztec-prover-node" {
}
]
dependsOn = [
{
containerName = "init-container"
condition = "COMPLETE"
}
]
logConfiguration = {
logDriver = "awslogs"
Expand Down
10 changes: 8 additions & 2 deletions yarn-project/bb-prover/src/prover/bb_private_kernel_prover.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import {
} from '@aztec/circuits.js';
import { siloNoteHash } from '@aztec/circuits.js/hash';
import { runInDirectory } from '@aztec/foundation/fs';
import { createDebugLogger } from '@aztec/foundation/log';
import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log';
import { Timer } from '@aztec/foundation/timer';
import {
ClientCircuitArtifacts,
Expand Down Expand Up @@ -57,6 +57,7 @@ import {
executeBbClientIvcProof,
verifyProof,
} from '../bb/execute.js';
import { type BBConfig } from '../config.js';
import { mapProtocolArtifactNameToCircuitName } from '../stats.js';
import { extractVkData } from '../verification_key/verification_key_data.js';

Expand All @@ -73,13 +74,18 @@ export class BBNativePrivateKernelProver implements PrivateKernelProver {
Promise<VerificationKeyData>
>();

constructor(
private constructor(
private bbBinaryPath: string,
private bbWorkingDirectory: string,
private skipCleanup: boolean,
private log = createDebugLogger('aztec:bb-native-prover'),
) {}

public static async new(config: BBConfig, log?: DebugLogger) {
await fs.mkdir(config.bbWorkingDirectory, { recursive: true });
return new BBNativePrivateKernelProver(config.bbBinaryPath, config.bbWorkingDirectory, !!config.bbSkipCleanup, log);
}

private async _createClientIvcProof(
directory: string,
acirs: Buffer[],
Expand Down
1 change: 1 addition & 0 deletions yarn-project/bb-prover/src/verifier/bb_verifier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export class BBCircuitVerifier implements ClientProtocolCircuitVerifier {
initialCircuits: ProtocolArtifact[] = [],
logger = createDebugLogger('aztec:bb-verifier'),
) {
await fs.mkdir(config.bbWorkingDirectory, { recursive: true });
const keys = new Map<ProtocolArtifact, Promise<VerificationKeyData>>();
for (const circuit of initialCircuits) {
const vkData = await this.generateVerificationKey(
Expand Down
16 changes: 2 additions & 14 deletions yarn-project/cli/src/cmds/devnet/bootstrap_network.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,20 +112,8 @@ async function deployERC20({ walletClient, publicClient }: L1Clients) {
contractBytecode: TokenPortalBytecode,
};

const erc20Address = await deployL1Contract(
walletClient,
publicClient,
erc20.contractAbi,
erc20.contractBytecode,
[],
);
const portalAddress = await deployL1Contract(
walletClient,
publicClient,
portal.contractAbi,
portal.contractBytecode,
[],
);
const erc20Address = await deployL1Contract(walletClient, publicClient, erc20.contractAbi, erc20.contractBytecode);
const portalAddress = await deployL1Contract(walletClient, publicClient, portal.contractAbi, portal.contractBytecode);

return {
erc20Address,
Expand Down
3 changes: 2 additions & 1 deletion yarn-project/cli/src/cmds/l1/deploy_l1_contracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ export async function deployL1Contracts(
chainId: number,
privateKey: string | undefined,
mnemonic: string,
salt: number | undefined,
json: boolean,
log: LogFn,
debugLogger: DebugLogger,
) {
const { l1ContractAddresses } = await deployAztecContracts(rpcUrl, chainId, privateKey, mnemonic, debugLogger);
const { l1ContractAddresses } = await deployAztecContracts(rpcUrl, chainId, privateKey, mnemonic, salt, debugLogger);

if (json) {
log(
Expand Down
2 changes: 2 additions & 0 deletions yarn-project/cli/src/cmds/l1/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export function injectCommands(program: Command, log: LogFn, debugLogger: DebugL
'test test test test test test test test test test test junk',
)
.addOption(l1ChainIdOption)
.option('--salt <number>', 'The optional salt to use in deployment', arg => parseInt(arg))
.option('--json', 'Output the contract addresses in JSON format')
.action(async options => {
const { deployL1Contracts } = await import('./deploy_l1_contracts.js');
Expand All @@ -38,6 +39,7 @@ export function injectCommands(program: Command, log: LogFn, debugLogger: DebugL
options.l1ChainId,
options.privateKey,
options.mnemonic,
options.salt,
options.json,
log,
debugLogger,
Expand Down
2 changes: 2 additions & 0 deletions yarn-project/cli/src/utils/aztec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ export async function deployAztecContracts(
chainId: number,
privateKey: string | undefined,
mnemonic: string,
salt: number | undefined,
debugLogger: DebugLogger,
): Promise<DeployL1Contracts> {
const {
Expand Down Expand Up @@ -116,6 +117,7 @@ export async function deployAztecContracts(
return await deployL1Contracts(chain.rpcUrl, account, chain.chainInfo, debugLogger, l1Artifacts, {
l2FeeJuiceAddress: FeeJuiceAddress,
vkTreeRoot: getVKTreeRoot(),
salt,
});
}

Expand Down
1 change: 1 addition & 0 deletions yarn-project/end-to-end/src/fixtures/setup_l1_contracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ export const setupL1Contracts = async (
const l1Data = await deployL1Contracts(l1RpcUrl, account, foundry, logger, l1Artifacts, {
l2FeeJuiceAddress: FeeJuiceAddress,
vkTreeRoot: getVKTreeRoot(),
salt: undefined,
});

return l1Data;
Expand Down
1 change: 1 addition & 0 deletions yarn-project/end-to-end/src/fixtures/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ export const setupL1Contracts = async (
const l1Data = await deployL1Contracts(l1RpcUrl, account, foundry, logger, l1Artifacts, {
l2FeeJuiceAddress: FeeJuiceAddress,
vkTreeRoot: getVKTreeRoot(),
salt: undefined,
});

return l1Data;
Expand Down
Loading

0 comments on commit abc6b19

Please sign in to comment.