diff --git a/.gitignore b/.gitignore index 836f3f16ce3..9115ec7782a 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,5 @@ node_modules build/ .idea cmake-build-debug -.bootstrapped \ No newline at end of file +.terraform +.bootstrapped diff --git a/yarn-project/archiver/src/archiver/archiver.ts b/yarn-project/archiver/src/archiver/archiver.ts index 217df42dab6..04531d92e48 100644 --- a/yarn-project/archiver/src/archiver/archiver.ts +++ b/yarn-project/archiver/src/archiver/archiver.ts @@ -103,10 +103,10 @@ export class Archiver implements L2BlockSource, L2LogsSource, ContractDataSource const archiverStore = new MemoryArchiverStore(); const archiver = new Archiver( publicClient, - config.rollupContract, - config.inboxContract, - config.registryContract, - config.contractDeploymentEmitterContract, + config.l1Contracts.rollupAddress!, + config.l1Contracts.inboxAddress!, + config.l1Contracts.registryAddress!, + config.l1Contracts.contractDeploymentEmitterAddress!, config.searchStartBlock, archiverStore, config.archiverPollingIntervalMS, diff --git a/yarn-project/archiver/src/archiver/config.ts b/yarn-project/archiver/src/archiver/config.ts index f6604d8c6f2..e4494a4945d 100644 --- a/yarn-project/archiver/src/archiver/config.ts +++ b/yarn-project/archiver/src/archiver/config.ts @@ -1,5 +1,5 @@ +import { L1ContractAddresses } from '@aztec/ethereum'; import { EthAddress } from '@aztec/foundation/eth-address'; -import { L1Addresses } from '@aztec/types'; /** * There are 2 polling intervals used in this configuration. The first is the archiver polling interval, archiverPollingIntervalMS. @@ -11,7 +11,7 @@ import { L1Addresses } from '@aztec/types'; /** * The archiver configuration. */ -export interface ArchiverConfig extends L1Addresses { +export interface ArchiverConfig { /** * The url of the Ethereum RPC node. */ @@ -36,6 +36,11 @@ export interface ArchiverConfig extends L1Addresses { * Eth block from which we start scanning for L2Blocks. */ searchStartBlock: number; + + /** + * The deployed L1 contract addresses + */ + l1Contracts: L1ContractAddresses; } /** @@ -55,17 +60,19 @@ export function getConfigEnvVars(): ArchiverConfig { INBOX_CONTRACT_ADDRESS, REGISTRY_CONTRACT_ADDRESS, } = process.env; + const addresses = new L1ContractAddresses( + ROLLUP_CONTRACT_ADDRESS ? EthAddress.fromString(ROLLUP_CONTRACT_ADDRESS) : EthAddress.ZERO, + REGISTRY_CONTRACT_ADDRESS ? EthAddress.fromString(REGISTRY_CONTRACT_ADDRESS) : EthAddress.ZERO, + INBOX_CONTRACT_ADDRESS ? EthAddress.fromString(INBOX_CONTRACT_ADDRESS) : EthAddress.ZERO, + undefined, + CONTRACT_DEPLOYMENT_EMITTER_ADDRESS ? EthAddress.fromString(CONTRACT_DEPLOYMENT_EMITTER_ADDRESS) : EthAddress.ZERO, + ); return { rpcUrl: ETHEREUM_HOST || 'http://127.0.0.1:8545/', archiverPollingIntervalMS: ARCHIVER_POLLING_INTERVAL_MS ? +ARCHIVER_POLLING_INTERVAL_MS : 1_000, viemPollingIntervalMS: ARCHIVER_VIEM_POLLING_INTERVAL_MS ? +ARCHIVER_VIEM_POLLING_INTERVAL_MS : 1_000, - rollupContract: ROLLUP_CONTRACT_ADDRESS ? EthAddress.fromString(ROLLUP_CONTRACT_ADDRESS) : EthAddress.ZERO, - registryContract: REGISTRY_CONTRACT_ADDRESS ? EthAddress.fromString(REGISTRY_CONTRACT_ADDRESS) : EthAddress.ZERO, - inboxContract: INBOX_CONTRACT_ADDRESS ? EthAddress.fromString(INBOX_CONTRACT_ADDRESS) : EthAddress.ZERO, - contractDeploymentEmitterContract: CONTRACT_DEPLOYMENT_EMITTER_ADDRESS - ? EthAddress.fromString(CONTRACT_DEPLOYMENT_EMITTER_ADDRESS) - : EthAddress.ZERO, searchStartBlock: SEARCH_START_BLOCK ? +SEARCH_START_BLOCK : 0, apiKey: API_KEY, + l1Contracts: addresses, }; } diff --git a/yarn-project/archiver/src/index.ts b/yarn-project/archiver/src/index.ts index d132e23af90..1edb9b488f5 100644 --- a/yarn-project/archiver/src/index.ts +++ b/yarn-project/archiver/src/index.ts @@ -17,14 +17,7 @@ const log = createDebugLogger('aztec:archiver'); // eslint-disable-next-line require-await async function main() { const config = getConfigEnvVars(); - const { - rpcUrl, - rollupContract, - inboxContract, - registryContract, - contractDeploymentEmitterContract, - searchStartBlock, - } = config; + const { rpcUrl, l1Contracts, searchStartBlock } = config; const publicClient = createPublicClient({ chain: localhost, @@ -35,10 +28,10 @@ async function main() { const archiver = new Archiver( publicClient, - rollupContract, - inboxContract, - registryContract, - contractDeploymentEmitterContract, + l1Contracts.rollupAddress!, + l1Contracts.inboxAddress!, + l1Contracts.registryAddress!, + l1Contracts.contractDeploymentEmitterAddress!, searchStartBlock, archiverStore, ); diff --git a/yarn-project/aztec-node/Dockerfile b/yarn-project/aztec-node/Dockerfile index efb5e939ea5..5608c729449 100644 --- a/yarn-project/aztec-node/Dockerfile +++ b/yarn-project/aztec-node/Dockerfile @@ -10,6 +10,6 @@ RUN yarn cache clean RUN yarn workspaces focus --production > /dev/null FROM node:18-alpine -COPY --from=builder /usr/src/yarn-project/aztec-node /usr/src/yarn-project/aztec-node +COPY --from=builder /usr/src /usr/src WORKDIR /usr/src/yarn-project/aztec-node -ENTRYPOINT ["yarn"] \ No newline at end of file +ENTRYPOINT ["yarn", "start"] \ No newline at end of file diff --git a/yarn-project/aztec-node/package.json b/yarn-project/aztec-node/package.json index 8e785e5b058..85df499f9ba 100644 --- a/yarn-project/aztec-node/package.json +++ b/yarn-project/aztec-node/package.json @@ -4,6 +4,7 @@ "main": "dest/index.js", "type": "module", "exports": "./dest/index.js", + "bin": "./dest/bin/index.js", "typedocOptions": { "entryPoints": [ "./src/index.ts" @@ -12,6 +13,7 @@ "tsconfig": "./tsconfig.json" }, "scripts": { + "start": "node --no-warnings ./dest/bin", "build": "yarn clean && tsc -b", "build:dev": "tsc -b --watch", "clean": "rm -rf ./dest .tsbuildinfo", @@ -33,6 +35,7 @@ "dependencies": { "@aztec/archiver": "workspace:^", "@aztec/circuits.js": "workspace:^", + "@aztec/ethereum": "workspace:^", "@aztec/foundation": "workspace:^", "@aztec/l1-artifacts": "workspace:^", "@aztec/merkle-tree": "workspace:^", @@ -40,6 +43,8 @@ "@aztec/sequencer-client": "workspace:^", "@aztec/types": "workspace:^", "@aztec/world-state": "workspace:^", + "koa": "^2.14.2", + "koa-router": "^12.0.0", "tslib": "^2.4.0" }, "devDependencies": { diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index 4c07e444bee..babb4be9e6f 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -2,13 +2,13 @@ import { Archiver } from '@aztec/archiver'; import { CONTRACT_TREE_HEIGHT, CircuitsWasm, - EthAddress, Fr, GlobalVariables, HistoricBlockData, L1_TO_L2_MSG_TREE_HEIGHT, PRIVATE_DATA_TREE_HEIGHT, } from '@aztec/circuits.js'; +import { L1ContractAddresses } from '@aztec/ethereum'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { createDebugLogger } from '@aztec/foundation/log'; import { InMemoryTxPool, P2P, createP2PClient } from '@aztec/p2p'; @@ -57,6 +57,7 @@ export const createMemDown = () => (memdown as any)() as MemDown; */ export class AztecNodeService implements AztecNode { constructor( + protected config: AztecNodeConfig, protected p2pClient: P2P, protected blockSource: L2BlockSource, protected encryptedLogsSource: L2LogsSource, @@ -83,7 +84,7 @@ export class AztecNodeService implements AztecNode { // we identify the P2P transaction protocol by using the rollup contract address. // this may well change in future - config.transactionProtocol = `/aztec/tx/${config.rollupContract.toString()}`; + config.transactionProtocol = `/aztec/tx/${config.l1Contracts.rollupAddress!.toString()}`; // create the tx pool and the p2p client, which will need the l2 block source const p2pClient = await createP2PClient(config, new InMemoryTxPool(), archiver); @@ -107,6 +108,7 @@ export class AztecNodeService implements AztecNode { archiver, ); return new AztecNodeService( + config, p2pClient, archiver, archiver, @@ -122,6 +124,14 @@ export class AztecNodeService implements AztecNode { ); } + /** + * Method to return the currently deployed L1 contract addresses. + * @returns - The currently deployed L1 contract addresses. + */ + public getL1ContractAddresses(): Promise { + return Promise.resolve(this.config.l1Contracts); + } + /** * Method to determine if the node is ready to accept transactions. * @returns - Flag indicating the readiness for tx submission. @@ -173,18 +183,6 @@ export class AztecNodeService implements AztecNode { return Promise.resolve(this.chainId); } - /** - * Method to fetch the rollup contract address at the base-layer. - * @returns The rollup address. - */ - public getRollupAddress(): Promise { - return this.blockSource.getRollupAddress(); - } - - public getRegistryAddress(): Promise { - return this.blockSource.getRegistryAddress(); - } - /** * Get the extended contract data for this contract. * @param contractAddress - The contract data address. diff --git a/yarn-project/aztec-node/src/bin/index.ts b/yarn-project/aztec-node/src/bin/index.ts new file mode 100644 index 00000000000..6938c9317f6 --- /dev/null +++ b/yarn-project/aztec-node/src/bin/index.ts @@ -0,0 +1,68 @@ +#!/usr/bin/env -S node --no-warnings +import { createDebugLogger } from '@aztec/foundation/log'; +import { createAztecNodeRpcServer } from '@aztec/types'; + +import http from 'http'; +import Koa from 'koa'; +import Router from 'koa-router'; + +import { AztecNodeConfig, AztecNodeService, getConfigEnvVars } from '../index.js'; + +const { SERVER_PORT = 8081, API_PREFIX = '' } = process.env; + +const logger = createDebugLogger('aztec:node'); + +/** + * Creates the node from provided config + */ +async function createAndDeployAztecNode() { + const aztecNodeConfig: AztecNodeConfig = { ...getConfigEnvVars() }; + + return await AztecNodeService.createAndSync(aztecNodeConfig); +} + +/** + * Creates a router for helper API endpoints of the Aztec RPC Server. + * @param apiPrefix - The prefix to use for all api requests + * @returns - The router for handling status requests. + */ +export function createStatusRouter(apiPrefix: string) { + const router = new Router({ prefix: `${apiPrefix}` }); + router.get('/status', (ctx: Koa.Context) => { + ctx.status = 200; + }); + return router; +} + +/** + * Create and start a new Aztec Node HTTP Server + */ +async function main() { + logger.info(`Setting up Aztec Node...`); + + const aztecNode = await createAndDeployAztecNode(); + + const shutdown = async () => { + logger.info('Shutting down...'); + await aztecNode.stop(); + process.exit(0); + }; + + process.once('SIGINT', shutdown); + process.once('SIGTERM', shutdown); + + const rpcServer = createAztecNodeRpcServer(aztecNode); + const app = rpcServer.getApp(API_PREFIX); + const apiRouter = createStatusRouter(API_PREFIX); + app.use(apiRouter.routes()); + app.use(apiRouter.allowedMethods()); + + const httpServer = http.createServer(app.callback()); + httpServer.listen(+SERVER_PORT); + logger.info(`Aztec Node JSON-RPC Server listening on port ${SERVER_PORT}`); +} + +main().catch(err => { + logger.error(err); + process.exit(1); +}); diff --git a/yarn-project/aztec-node/src/index.ts b/yarn-project/aztec-node/src/index.ts index 853db6bae96..30446306da6 100644 --- a/yarn-project/aztec-node/src/index.ts +++ b/yarn-project/aztec-node/src/index.ts @@ -1,4 +1,2 @@ export * from './aztec-node/config.js'; export * from './aztec-node/server.js'; -export * from './rpc/http_rpc_server.js'; -export * from './rpc/http_rpc_client.js'; diff --git a/yarn-project/aztec-node/terraform/main.tf b/yarn-project/aztec-node/terraform/main.tf new file mode 100644 index 00000000000..c425b64c69a --- /dev/null +++ b/yarn-project/aztec-node/terraform/main.tf @@ -0,0 +1,251 @@ +terraform { + backend "s3" { + bucket = "aztec-terraform" + region = "eu-west-2" + } + required_providers { + aws = { + source = "hashicorp/aws" + version = "3.74.2" + } + } +} + +# Define provider and region +provider "aws" { + region = "eu-west-2" +} + +data "terraform_remote_state" "setup_iac" { + backend = "s3" + config = { + bucket = "aztec-terraform" + key = "setup/setup-iac" + region = "eu-west-2" + } +} + +data "terraform_remote_state" "aztec2_iac" { + backend = "s3" + config = { + bucket = "aztec-terraform" + key = "aztec2/iac" + region = "eu-west-2" + } +} + + +resource "aws_cloudwatch_log_group" "aztec_node_log_group" { + name = "/fargate/service/${var.DEPLOY_TAG}/aztec-node" + retention_in_days = 14 +} + +resource "aws_service_discovery_service" "aztec-node" { + name = "${var.DEPLOY_TAG}-aztec-node" + + health_check_custom_config { + failure_threshold = 1 + } + + dns_config { + namespace_id = data.terraform_remote_state.setup_iac.outputs.local_service_discovery_id + + dns_records { + ttl = 60 + type = "A" + } + + dns_records { + ttl = 60 + type = "SRV" + } + + routing_policy = "MULTIVALUE" + } + + # Terraform just fails if this resource changes and you have registered instances. + provisioner "local-exec" { + when = destroy + command = "${path.module}/../servicediscovery-drain.sh ${self.id}" + } +} + +# Define task definition and service. +resource "aws_ecs_task_definition" "aztec-node-1" { + family = "${var.DEPLOY_TAG}-aztec-node" + requires_compatibilities = ["FARGATE"] + network_mode = "awsvpc" + cpu = "2048" + memory = "4096" + execution_role_arn = data.terraform_remote_state.setup_iac.outputs.ecs_task_execution_role_arn + task_role_arn = data.terraform_remote_state.aztec2_iac.outputs.cloudwatch_logging_ecs_role_arn + + container_definitions = < { - const [version, chainId, rollupAddress, registryAddress] = await Promise.all([ + const [version, chainId, contractAddresses] = await Promise.all([ this.node.getVersion(), this.node.getChainId(), - this.node.getRollupAddress(), - this.node.getRegistryAddress(), + this.node.getL1ContractAddresses(), ]); - return { - sandboxVersion: this.sandboxVersion, - compatibleNargoVersion: NoirVersion.tag, - chainId, - protocolVersion: version, - rollupAddress, - registryAddress, - }; + return new NodeInfo(this.sandboxVersion, NoirVersion.tag, chainId, version, contractAddresses); } /** diff --git a/yarn-project/aztec-rpc/src/aztec_rpc_server/test/aztec_rpc_server.test.ts b/yarn-project/aztec-rpc/src/aztec_rpc_server/test/aztec_rpc_server.test.ts index 99adad75081..dbde0945ba8 100644 --- a/yarn-project/aztec-rpc/src/aztec_rpc_server/test/aztec_rpc_server.test.ts +++ b/yarn-project/aztec-rpc/src/aztec_rpc_server/test/aztec_rpc_server.test.ts @@ -1,11 +1,13 @@ import { Grumpkin } from '@aztec/circuits.js/barretenberg'; +import { L1ContractAddresses } from '@aztec/ethereum'; +import { EthAddress } from '@aztec/foundation/eth-address'; import { TestKeyStore } from '@aztec/key-store'; import { AztecNode, AztecRPC, L2Tx, mockTx } from '@aztec/types'; import { MockProxy, mock } from 'jest-mock-extended'; import { MemoryDB } from '../../database/memory_db.js'; -import { EthAddress, RpcServerConfig } from '../../index.js'; +import { RpcServerConfig } from '../../index.js'; import { AztecRPCServer } from '../aztec_rpc_server.js'; import { aztecRpcTestSuite } from './aztec_rpc_test_suite.js'; @@ -21,7 +23,8 @@ async function createAztecRpcServer(): Promise { node.getBlockNumber.mockResolvedValue(2); node.getVersion.mockResolvedValue(1); node.getChainId.mockResolvedValue(1); - node.getRollupAddress.mockResolvedValue(EthAddress.random()); + const mockedContracts = new L1ContractAddresses(EthAddress.random()); + node.getL1ContractAddresses.mockResolvedValue(mockedContracts); return new AztecRPCServer(keyStore, node, db, config); } diff --git a/yarn-project/aztec-rpc/src/aztec_rpc_server/test/aztec_rpc_test_suite.ts b/yarn-project/aztec-rpc/src/aztec_rpc_server/test/aztec_rpc_test_suite.ts index 9698c1f08ac..f9de03b941e 100644 --- a/yarn-project/aztec-rpc/src/aztec_rpc_server/test/aztec_rpc_test_suite.ts +++ b/yarn-project/aztec-rpc/src/aztec_rpc_server/test/aztec_rpc_test_suite.ts @@ -135,7 +135,7 @@ export const aztecRpcTestSuite = (testName: string, aztecRpcSetup: () => Promise const nodeInfo = await rpc.getNodeInfo(); expect(typeof nodeInfo.protocolVersion).toEqual('number'); expect(typeof nodeInfo.chainId).toEqual('number'); - expect(nodeInfo.rollupAddress.toString()).toMatch(/0x[a-fA-F0-9]+/); + expect(nodeInfo.l1ContractAddresses.rollupAddress!.toString()).toMatch(/0x[a-fA-F0-9]+/); }); // Note: Not testing `isGlobalStateSynchronized`, `isAccountStateSynchronized` and `getSyncStatus` as these methods diff --git a/yarn-project/aztec-rpc/src/bin/index.ts b/yarn-project/aztec-rpc/src/bin/index.ts new file mode 100644 index 00000000000..80584d0a8e6 --- /dev/null +++ b/yarn-project/aztec-rpc/src/bin/index.ts @@ -0,0 +1,39 @@ +#!/usr/bin/env -S node --no-warnings +import { createDebugLogger } from '@aztec/foundation/log'; +import { createAztecNodeRpcClient } from '@aztec/types'; + +import { startHttpRpcServer } from '../aztec_rpc_http/index.js'; +import { createAztecRPCServer } from '../aztec_rpc_server/index.js'; +import { getConfigEnvVars } from '../config/index.js'; + +const { SERVER_PORT = 8080, AZTEC_NODE_RPC_URL = '' } = process.env; + +const logger = createDebugLogger('aztec:rpc_server'); + +/** + * Create and start a new Aztec RCP HTTP Server + */ +async function main() { + logger.info(`Setting up Aztec RPC Server...`); + + const rpcConfig = getConfigEnvVars(); + const nodeRpcClient = createAztecNodeRpcClient(AZTEC_NODE_RPC_URL); + const rpcServer = await createAztecRPCServer(nodeRpcClient, rpcConfig); + + const shutdown = async () => { + logger.info('Shutting down...'); + await rpcServer.stop(); + process.exit(0); + }; + + process.once('SIGINT', shutdown); + process.once('SIGTERM', shutdown); + + startHttpRpcServer(rpcServer, SERVER_PORT); + logger.info(`Aztec RPC Server listening on port ${SERVER_PORT}`); +} + +main().catch(err => { + logger.error(err); + process.exit(1); +}); diff --git a/yarn-project/aztec-rpc/tsconfig.json b/yarn-project/aztec-rpc/tsconfig.json index 8f298d5722d..1190999ce69 100644 --- a/yarn-project/aztec-rpc/tsconfig.json +++ b/yarn-project/aztec-rpc/tsconfig.json @@ -12,6 +12,9 @@ { "path": "../circuits.js" }, + { + "path": "../ethereum" + }, { "path": "../foundation" }, diff --git a/yarn-project/aztec-sandbox/Dockerfile b/yarn-project/aztec-sandbox/Dockerfile index 4bd5ddbdbaa..98c5a6191d0 100644 --- a/yarn-project/aztec-sandbox/Dockerfile +++ b/yarn-project/aztec-sandbox/Dockerfile @@ -13,7 +13,6 @@ RUN if [[ -n "${COMMIT_TAG}" ]]; then \ fi WORKDIR /usr/src/yarn-project/aztec-sandbox -RUN ls RUN if [[ -n "${COMMIT_TAG}" ]]; then \ jq --arg v ${COMMIT_TAG} '.version = $v' package.json > _temp && mv _temp package.json; \ fi diff --git a/yarn-project/aztec-sandbox/src/bin/index.ts b/yarn-project/aztec-sandbox/src/bin/index.ts index 8f906cf874d..d8358595893 100644 --- a/yarn-project/aztec-sandbox/src/bin/index.ts +++ b/yarn-project/aztec-sandbox/src/bin/index.ts @@ -1,4 +1,5 @@ #!/usr/bin/env -S node --no-warnings +import { startHttpRpcServer } from '@aztec/aztec-rpc'; import { deployInitialSandboxAccounts } from '@aztec/aztec.js'; import { createDebugLogger } from '@aztec/foundation/log'; import { fileURLToPath } from '@aztec/foundation/url'; @@ -8,14 +9,38 @@ import { readFileSync } from 'fs'; import { dirname, resolve } from 'path'; import { setupFileDebugLog } from '../logging.js'; -import { createSandbox } from '../sandbox.js'; -import { startHttpRpcServer } from '../server.js'; +import { createP2PSandbox, createSandbox } from '../sandbox.js'; import { github, splash } from '../splash.js'; const { SERVER_PORT = 8080 } = process.env; const logger = createDebugLogger('aztec:sandbox'); +/** + * Creates the sandbox from provided config and deploys any initial L1 and L2 contracts + * @param isP2PSandbox - Flag indicating if this sandbox is to connect to a P2P network + */ +async function createAndDeploySandbox(isP2PSandbox: boolean) { + if (!isP2PSandbox) { + const { l1Contracts, rpcServer, stop } = await createSandbox(); + logger.info('Setting up test accounts...'); + const accounts = await deployInitialSandboxAccounts(rpcServer); + return { + l1Contracts, + rpcServer, + stop, + accounts, + }; + } + const { l1Contracts, rpcServer, stop } = await createP2PSandbox(); + return { + l1Contracts, + rpcServer, + stop, + accounts: [], + }; +} + /** * Create and start a new Aztec RCP HTTP Server */ @@ -26,10 +51,7 @@ async function main() { logger.info(`Setting up Aztec Sandbox v${version} (nargo ${NoirVersion.tag}), please stand by...`); - const { l1Contracts, rpcServer, stop } = await createSandbox(); - - logger.info('Setting up test accounts...'); - const accounts = await deployInitialSandboxAccounts(rpcServer); + const { rpcServer, stop, accounts } = await createAndDeploySandbox(false); const shutdown = async () => { logger.info('Shutting down...'); @@ -40,7 +62,7 @@ async function main() { process.once('SIGINT', shutdown); process.once('SIGTERM', shutdown); - startHttpRpcServer(rpcServer, l1Contracts, SERVER_PORT); + startHttpRpcServer(rpcServer, SERVER_PORT); logger.info(`Aztec Sandbox JSON-RPC Server listening on port ${SERVER_PORT}`); logger.info(`Debug logs will be written to ${logPath}`); const accountStrings = [`Initial Accounts:\n\n`]; diff --git a/yarn-project/aztec-sandbox/src/routes.ts b/yarn-project/aztec-sandbox/src/routes.ts index 43967f3bd82..982fd37677d 100644 --- a/yarn-project/aztec-sandbox/src/routes.ts +++ b/yarn-project/aztec-sandbox/src/routes.ts @@ -1,5 +1,3 @@ -import { DeployL1Contracts } from '@aztec/ethereum'; - import Koa from 'koa'; import Router from 'koa-router'; @@ -8,24 +6,12 @@ import Router from 'koa-router'; * @param aztecNode - An instance of the aztec node. * @param config - The aztec node's configuration variables. */ -export function createApiRouter(l1Contracts: DeployL1Contracts) { +export function createApiRouter() { const router = new Router({ prefix: '/api' }); router.get('/status', (ctx: Koa.Context) => { // TODO: add `status` to Aztec node. ctx.status = 200; }); - router.get('/l1-contract-addresses', (ctx: Koa.Context) => { - ctx.body = { - rollup: l1Contracts.rollupAddress.toString(), - contractDeploymentEmitter: l1Contracts.contractDeploymentEmitterAddress.toString(), - inbox: l1Contracts.inboxAddress.toString(), - outbox: l1Contracts.outboxAddress.toString(), - decoderHelper: l1Contracts.decoderHelperAddress?.toString(), - registry: l1Contracts.registryAddress.toString(), - }; - ctx.status = 200; - }); - return router; } diff --git a/yarn-project/aztec-sandbox/src/sandbox.ts b/yarn-project/aztec-sandbox/src/sandbox.ts index 227cc7f6edb..270199b30d5 100644 --- a/yarn-project/aztec-sandbox/src/sandbox.ts +++ b/yarn-project/aztec-sandbox/src/sandbox.ts @@ -1,12 +1,21 @@ #!/usr/bin/env -S node --no-warnings import { AztecNodeConfig, AztecNodeService, getConfigEnvVars } from '@aztec/aztec-node'; import { createAztecRPCServer, getConfigEnvVars as getRpcConfigEnvVars } from '@aztec/aztec-rpc'; -import { deployL1Contracts } from '@aztec/ethereum'; +import { DeployL1Contracts, L1ContractAddresses, createEthereumChain, deployL1Contracts } from '@aztec/ethereum'; import { createDebugLogger } from '@aztec/foundation/log'; import { retryUntil } from '@aztec/foundation/retry'; -import { HDAccount, createPublicClient, http as httpViemTransport } from 'viem'; -import { mnemonicToAccount } from 'viem/accounts'; +import { + Account, + Chain, + HDAccount, + HttpTransport, + createPublicClient, + createWalletClient, + http, + http as httpViemTransport, +} from 'viem'; +import { mnemonicToAccount, privateKeyToAccount } from 'viem/accounts'; import { foundry } from 'viem/chains'; const { MNEMONIC = 'test test test test test test test test test test test junk' } = process.env; @@ -15,14 +24,45 @@ const logger = createDebugLogger('aztec:sandbox'); const localAnvil = foundry; +/** + * Helper function that retrieves the addresses of configured deployed contracts. + */ +function retrieveL1Contracts(config: AztecNodeConfig, account: Account): Promise { + const chain = createEthereumChain(config.rpcUrl, config.apiKey); + const walletClient = createWalletClient({ + account, + chain: chain.chainInfo, + transport: http(chain.rpcUrl), + }); + const publicClient = createPublicClient({ + chain: chain.chainInfo, + transport: http(chain.rpcUrl), + }); + const l1Contracts = new L1ContractAddresses( + config.l1Contracts.rollupAddress, + config.l1Contracts.registryAddress, + config.l1Contracts.inboxAddress, + config.l1Contracts.outboxAddress, + config.l1Contracts.contractDeploymentEmitterAddress, + undefined, + ); + const contracts: DeployL1Contracts = { + l1ContractAddresses: l1Contracts, + walletClient, + publicClient, + }; + return Promise.resolve(contracts); +} + /** * Helper function that waits for the Ethereum RPC server to respond before deploying L1 contracts. */ -async function waitThenDeploy(rpcUrl: string, hdAccount: HDAccount) { +async function waitThenDeploy(config: AztecNodeConfig, deployFunction: () => Promise) { + const chain = createEthereumChain(config.rpcUrl, config.apiKey); // wait for ETH RPC to respond to a request. const publicClient = createPublicClient({ - chain: foundry, - transport: httpViemTransport(rpcUrl), + chain: chain.chainInfo, + transport: httpViemTransport(chain.rpcUrl), }); const chainID = await retryUntil( async () => { @@ -30,7 +70,7 @@ async function waitThenDeploy(rpcUrl: string, hdAccount: HDAccount) { try { chainId = await publicClient.getChainId(); } catch (err) { - logger.warn(`Failed to connect to Ethereum node at ${rpcUrl}. Retrying...`); + logger.warn(`Failed to connect to Ethereum node at ${chain.rpcUrl}. Retrying...`); } return chainId; }, @@ -40,12 +80,11 @@ async function waitThenDeploy(rpcUrl: string, hdAccount: HDAccount) { ); if (!chainID) { - throw Error(`Ethereum node unresponsive at ${rpcUrl}.`); + throw Error(`Ethereum node unresponsive at ${chain.rpcUrl}.`); } // Deploy L1 contracts - const deployedL1Contracts = await deployL1Contracts(rpcUrl, hdAccount, localAnvil, logger); - return deployedL1Contracts; + return await deployFunction(); } /** Sandbox settings. */ @@ -65,12 +104,45 @@ export async function createSandbox(config: Partial = {}) { const hdAccount = mnemonicToAccount(config.l1Mnemonic ?? MNEMONIC); const privKey = hdAccount.getHdKey().privateKey; - const l1Contracts = await waitThenDeploy(aztecNodeConfig.rpcUrl, hdAccount); + const l1Contracts = await waitThenDeploy(aztecNodeConfig, () => + deployL1Contracts(aztecNodeConfig.rpcUrl, hdAccount, localAnvil, logger), + ); aztecNodeConfig.publisherPrivateKey = `0x${Buffer.from(privKey!).toString('hex')}`; - aztecNodeConfig.rollupContract = l1Contracts.rollupAddress; - aztecNodeConfig.contractDeploymentEmitterContract = l1Contracts.contractDeploymentEmitterAddress; - aztecNodeConfig.inboxContract = l1Contracts.inboxAddress; - aztecNodeConfig.registryContract = l1Contracts.registryAddress; + aztecNodeConfig.l1Contracts.rollupAddress = l1Contracts.l1ContractAddresses.rollupAddress; + aztecNodeConfig.l1Contracts.contractDeploymentEmitterAddress = + l1Contracts.l1ContractAddresses.contractDeploymentEmitterAddress; + aztecNodeConfig.l1Contracts.inboxAddress = l1Contracts.l1ContractAddresses.inboxAddress; + aztecNodeConfig.l1Contracts.registryAddress = l1Contracts.l1ContractAddresses.registryAddress; + + const node = await AztecNodeService.createAndSync(aztecNodeConfig); + const rpcServer = await createAztecRPCServer(node, rpcConfig); + + const stop = async () => { + await rpcServer.stop(); + await node.stop(); + }; + + return { node, rpcServer, l1Contracts, stop }; +} + +/** + * Create and start a new Aztec Node and RPC Server. Designed for interaction with a node network. + * Does not start any HTTP services nor populate any initial accounts. + * @param config - Optional Sandbox settings. + */ +export async function createP2PSandbox() { + const aztecNodeConfig: AztecNodeConfig = { ...getConfigEnvVars() }; + const rpcConfig = getRpcConfigEnvVars(); + const privateKeyAccount = privateKeyToAccount(aztecNodeConfig.publisherPrivateKey); + + const l1Contracts = await waitThenDeploy(aztecNodeConfig, () => + retrieveL1Contracts(aztecNodeConfig, privateKeyAccount), + ); + aztecNodeConfig.l1Contracts.rollupAddress = l1Contracts.l1ContractAddresses.rollupAddress; + aztecNodeConfig.l1Contracts.contractDeploymentEmitterAddress = + l1Contracts.l1ContractAddresses.contractDeploymentEmitterAddress; + aztecNodeConfig.l1Contracts.inboxAddress = l1Contracts.l1ContractAddresses.inboxAddress; + aztecNodeConfig.l1Contracts.registryAddress = l1Contracts.l1ContractAddresses.registryAddress; const node = await AztecNodeService.createAndSync(aztecNodeConfig); const rpcServer = await createAztecRPCServer(node, rpcConfig); diff --git a/yarn-project/aztec-sandbox/src/server.ts b/yarn-project/aztec-sandbox/src/server.ts index e749c4cc79c..0e37b1c91a0 100644 --- a/yarn-project/aztec-sandbox/src/server.ts +++ b/yarn-project/aztec-sandbox/src/server.ts @@ -1,5 +1,4 @@ import { getHttpRpcServer } from '@aztec/aztec-rpc'; -import { DeployL1Contracts } from '@aztec/ethereum'; import { AztecRPC } from '@aztec/types'; import http from 'http'; @@ -9,19 +8,14 @@ import { createApiRouter } from './routes.js'; /** * Creates an http server that forwards calls to the rpc server and starts it on the given port. * @param aztecRpcServer - RPC server that answers queries to the created HTTP server. - * @param deployedL1Contracts - Info on L1 deployed contracts. * @param port - Port to listen in. * @returns A running http server. */ -export function startHttpRpcServer( - aztecRpcServer: AztecRPC, - deployedL1Contracts: DeployL1Contracts, - port: string | number, -): http.Server { +export function startHttpRpcServer(aztecRpcServer: AztecRPC, port: string | number): http.Server { const rpcServer = getHttpRpcServer(aztecRpcServer); const app = rpcServer.getApp(); - const apiRouter = createApiRouter(deployedL1Contracts); + const apiRouter = createApiRouter(); app.use(apiRouter.routes()); app.use(apiRouter.allowedMethods()); diff --git a/yarn-project/aztec.js/package.json b/yarn-project/aztec.js/package.json index 12d26f8484b..b2d29580ad7 100644 --- a/yarn-project/aztec.js/package.json +++ b/yarn-project/aztec.js/package.json @@ -39,6 +39,7 @@ }, "dependencies": { "@aztec/circuits.js": "workspace:^", + "@aztec/ethereum": "workspace:^", "@aztec/foundation": "workspace:^", "@aztec/types": "workspace:^", "lodash.every": "^4.6.0", @@ -54,13 +55,17 @@ "@types/lodash.partition": "^4.6.0", "@types/lodash.zip": "^4.2.7", "@types/node": "^18.7.23", + "assert": "^2.1.0", + "browserify-zlib": "^0.2.0", "buffer": "^6.0.3", "crypto-browserify": "^3.12.0", "jest": "^29.5.0", "jest-mock-extended": "^3.0.3", "process": "^0.11.10", + "querystring-es3": "^0.2.1", "resolve-typescript-plugin": "^2.0.1", "stream-browserify": "^3.0.0", + "stream-http": "^3.2.0", "ts-jest": "^29.1.0", "ts-loader": "^9.4.4", "ts-node": "^10.9.1", diff --git a/yarn-project/aztec.js/src/aztec_rpc_client.ts b/yarn-project/aztec.js/src/aztec_rpc_client.ts index fee9e8192e1..274cc98dd84 100644 --- a/yarn-project/aztec.js/src/aztec_rpc_client.ts +++ b/yarn-project/aztec.js/src/aztec_rpc_client.ts @@ -6,6 +6,7 @@ import { ContractData, ExtendedContractData, L2BlockL2Logs, + NodeInfo, NotePreimage, Tx, TxExecutionRequest, @@ -32,7 +33,7 @@ export const createAztecRpcClient = (url: string, fetch = makeFetch([1, 2, 3], t NotePreimage, AuthWitness, }, - { Tx, TxReceipt, L2BlockL2Logs }, + { Tx, TxReceipt, L2BlockL2Logs, NodeInfo }, false, fetch, ); diff --git a/yarn-project/aztec.js/src/contract/contract.test.ts b/yarn-project/aztec.js/src/contract/contract.test.ts index a095b316b57..bcdf3fc5a51 100644 --- a/yarn-project/aztec.js/src/contract/contract.test.ts +++ b/yarn-project/aztec.js/src/contract/contract.test.ts @@ -1,4 +1,5 @@ import { AztecAddress, CompleteAddress, EthAddress } from '@aztec/circuits.js'; +import { L1ContractAddresses } from '@aztec/ethereum'; import { ABIParameterVisibility, ContractAbi, FunctionType } from '@aztec/foundation/abi'; import { DeployedContract, @@ -28,14 +29,13 @@ describe('Contract Class', () => { const mockTxHash = { type: 'TxHash' } as any as TxHash; const mockTxReceipt = { type: 'TxReceipt' } as any as TxReceipt; const mockViewResultValue = 1; - const mockNodeInfo: NodeInfo = { - sandboxVersion: 'vx.x.x', - compatibleNargoVersion: 'vx.x.x-aztec.x', - protocolVersion: 1, - chainId: 2, - rollupAddress: EthAddress.random(), - registryAddress: EthAddress.random(), - }; + const mockNodeInfo: NodeInfo = new NodeInfo( + 'vx.x.x', + 'vx.x.x-aztec.x', + 1, + 2, + new L1ContractAddresses(EthAddress.random(), EthAddress.random()), + ); const defaultAbi: ContractAbi = { name: 'FooContract', diff --git a/yarn-project/aztec.js/src/utils/cheat_codes.ts b/yarn-project/aztec.js/src/utils/cheat_codes.ts index fc3fe96c080..c1488f7c02a 100644 --- a/yarn-project/aztec.js/src/utils/cheat_codes.ts +++ b/yarn-project/aztec.js/src/utils/cheat_codes.ts @@ -257,7 +257,7 @@ export class AztecCheatCodes { * @param to - The timestamp to set the next block to (must be greater than current time) */ public async warp(to: number): Promise { - const rollupContract = (await this.aztecRpc.getNodeInfo()).rollupAddress; + const rollupContract = (await this.aztecRpc.getNodeInfo()).l1ContractAddresses.rollupAddress!; await this.eth.setNextBlockTimestamp(to); // also store this time on the rollup contract (slot 1 tracks `lastBlockTs`). // This is because when the sequencer executes public functions, it uses the timestamp stored in the rollup contract. diff --git a/yarn-project/aztec.js/tsconfig.json b/yarn-project/aztec.js/tsconfig.json index 01c876235ce..7d0bb1110ba 100644 --- a/yarn-project/aztec.js/tsconfig.json +++ b/yarn-project/aztec.js/tsconfig.json @@ -9,6 +9,9 @@ { "path": "../circuits.js" }, + { + "path": "../ethereum" + }, { "path": "../foundation" }, diff --git a/yarn-project/aztec.js/webpack.config.js b/yarn-project/aztec.js/webpack.config.js index 67005d8790a..cf722e339c2 100644 --- a/yarn-project/aztec.js/webpack.config.js +++ b/yarn-project/aztec.js/webpack.config.js @@ -62,13 +62,19 @@ export default { fs: false, path: false, url: false, + async_hooks: false, worker_threads: false, + net: false, events: require.resolve('events/'), buffer: require.resolve('buffer/'), util: require.resolve('util/'), stream: require.resolve('stream-browserify'), string_decoder: require.resolve('string_decoder/'), tty: require.resolve('tty-browserify'), + http: require.resolve('stream-http'), + zlib: require.resolve('browserify-zlib'), + assert: require.resolve('assert/'), + querystring: require.resolve('querystring-es3'), }, }, }; diff --git a/yarn-project/cli/package.json b/yarn-project/cli/package.json index 8a9dce35fdf..feb0477e29d 100644 --- a/yarn-project/cli/package.json +++ b/yarn-project/cli/package.json @@ -39,6 +39,7 @@ "@aztec/foundation": "workspace:^", "@aztec/noir-compiler": "workspace:^", "@aztec/noir-contracts": "workspace:^", + "@aztec/p2p": "workspace:^", "@aztec/types": "workspace:^", "commander": "^9.0.0", "jszip": "^3.10.1", diff --git a/yarn-project/cli/src/index.ts b/yarn-project/cli/src/index.ts index 1945cd3217b..a7e0c55d1b4 100644 --- a/yarn-project/cli/src/index.ts +++ b/yarn-project/cli/src/index.ts @@ -14,11 +14,11 @@ import { JsonStringify } from '@aztec/foundation/json-rpc'; import { DebugLogger, LogFn } from '@aztec/foundation/log'; import { fileURLToPath } from '@aztec/foundation/url'; import { compileContract, generateNoirInterface, generateTypescriptInterface } from '@aztec/noir-compiler/cli'; +import { createLibP2PPeerId } from '@aztec/p2p'; import { CompleteAddress, ContractData, L2BlockL2Logs, TxHash } from '@aztec/types'; import { Command } from 'commander'; import { readFileSync } from 'fs'; -import startCase from 'lodash.startcase'; import { dirname, resolve } from 'path'; import { mnemonicToAccount } from 'viem/accounts'; @@ -75,20 +75,19 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command { 'test test test test test test test test test test test junk', ) .action(async options => { - const { rollupAddress, registryAddress, inboxAddress, outboxAddress, contractDeploymentEmitterAddress } = - await deployAztecContracts( - options.rpcUrl, - options.apiKey ?? '', - options.privateKey, - options.mnemonic, - debugLogger, - ); + const { l1ContractAddresses } = await deployAztecContracts( + options.rpcUrl, + options.apiKey ?? '', + options.privateKey, + options.mnemonic, + debugLogger, + ); log('\n'); - log(`Rollup Address: ${rollupAddress.toString()}`); - log(`Registry Address: ${registryAddress.toString()}`); - log(`L1 -> L2 Inbox Address: ${inboxAddress.toString()}`); - log(`L2 -> L1 Outbox address: ${outboxAddress.toString()}`); - log(`Contract Deployment Emitter Address: ${contractDeploymentEmitterAddress.toString()}`); + log(`Rollup Address: ${l1ContractAddresses.rollupAddress?.toString()}`); + log(`Registry Address: ${l1ContractAddresses.registryAddress?.toString()}`); + log(`L1 -> L2 Inbox Address: ${l1ContractAddresses.inboxAddress?.toString()}`); + log(`L2 -> L1 Outbox address: ${l1ContractAddresses.outboxAddress?.toString()}`); + log(`Contract Deployment Emitter Address: ${l1ContractAddresses.contractDeploymentEmitterAddress?.toString()}`); log('\n'); }); @@ -118,6 +117,17 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command { log(`\nPrivate Key: ${privKey}\nPublic Key: ${publicKey.toString()}\n`); }); + program + .command('generate-p2p-private-key') + .summary('Generates a LibP2P peer private key.') + .description('Generates a private key that can be used for running a node on a LibP2P network.') + .action(async () => { + const peerId = await createLibP2PPeerId(); + const exportedPeerId = Buffer.from(peerId.privateKey!).toString('hex'); + log(`Private key: ${exportedPeerId}`); + log(`Peer Id: ${peerId}`); + }); + program .command('create-account') .description( @@ -500,8 +510,7 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command { .action(async options => { const client = await createCompatibleClient(options.rpcUrl, debugLogger); const info = await client.getNodeInfo(); - log(`\nNode Info:\n`); - Object.entries(info).map(([key, value]) => log(`${startCase(key)}: ${value}`)); + log(`\nNode Info:\n`, info.toReadableString()); }); program diff --git a/yarn-project/cli/tsconfig.json b/yarn-project/cli/tsconfig.json index a654a1611c8..28e130a83a3 100644 --- a/yarn-project/cli/tsconfig.json +++ b/yarn-project/cli/tsconfig.json @@ -21,6 +21,9 @@ { "path": "../noir-contracts" }, + { + "path": "../p2p" + }, { "path": "../types" } diff --git a/yarn-project/end-to-end/src/e2e_cheat_codes.test.ts b/yarn-project/end-to-end/src/e2e_cheat_codes.test.ts index f0968945e54..6b776447548 100644 --- a/yarn-project/end-to-end/src/e2e_cheat_codes.test.ts +++ b/yarn-project/end-to-end/src/e2e_cheat_codes.test.ts @@ -25,7 +25,7 @@ describe('e2e_cheat_codes', () => { walletClient = deployL1ContractsValues.walletClient; publicClient = deployL1ContractsValues.publicClient; - rollupAddress = deployL1ContractsValues.rollupAddress; + rollupAddress = deployL1ContractsValues.l1ContractAddresses.rollupAddress!; }, 100_000); afterAll(async () => { diff --git a/yarn-project/end-to-end/src/e2e_cli.test.ts b/yarn-project/end-to-end/src/e2e_cli.test.ts index 112748fe75b..19d4d44a9d1 100644 --- a/yarn-project/end-to-end/src/e2e_cli.test.ts +++ b/yarn-project/end-to-end/src/e2e_cli.test.ts @@ -17,9 +17,8 @@ let aztecRpcServer: AztecRPC; const testSetup = async () => { const context = await e2eSetup(2); debug(`Environment set up`); - const { deployL1ContractsValues } = context; ({ aztecNode, aztecRpcServer } = context); - http = startHttpRpcServer(aztecRpcServer, deployL1ContractsValues, HTTP_PORT); + http = startHttpRpcServer(aztecRpcServer, HTTP_PORT); debug(`HTTP RPC server started in port ${HTTP_PORT}`); return aztecRpcServer; }; diff --git a/yarn-project/end-to-end/src/e2e_p2p_network.test.ts b/yarn-project/end-to-end/src/e2e_p2p_network.test.ts index f28b101c754..a7ed4a8f0d9 100644 --- a/yarn-project/end-to-end/src/e2e_p2p_network.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p_network.test.ts @@ -10,7 +10,7 @@ import { AztecAddress, CompleteAddress, Fr, PublicKey, getContractDeploymentInfo import { Grumpkin } from '@aztec/circuits.js/barretenberg'; import { DebugLogger } from '@aztec/foundation/log'; import { TestContractAbi } from '@aztec/noir-contracts/artifacts'; -import { BootstrapNode, P2PConfig, createLibP2PPeerId, exportLibP2PPeerIdToString } from '@aztec/p2p'; +import { BootstrapNode, P2PConfig, createLibP2PPeerId } from '@aztec/p2p'; import { AztecRPC, TxStatus } from '@aztec/types'; import { setup } from './fixtures/utils.js'; @@ -92,8 +92,8 @@ describe('e2e_p2p_network', () => { tcpListenIp: '0.0.0.0', announceHostname: '127.0.0.1', announcePort: BOOT_NODE_TCP_PORT, - peerIdPrivateKey: exportLibP2PPeerIdToString(peerId), - serverMode: true, + peerIdPrivateKey: Buffer.from(peerId.privateKey!).toString('hex'), + serverMode: false, minPeerCount: 10, maxPeerCount: 100, diff --git a/yarn-project/end-to-end/src/e2e_sandbox_example.test.ts b/yarn-project/end-to-end/src/e2e_sandbox_example.test.ts index 7f0b77d7aa9..84f72c805ca 100644 --- a/yarn-project/end-to-end/src/e2e_sandbox_example.test.ts +++ b/yarn-project/end-to-end/src/e2e_sandbox_example.test.ts @@ -33,7 +33,7 @@ describe('e2e_sandbox_example', () => { expect(typeof nodeInfo.protocolVersion).toBe('number'); expect(typeof nodeInfo.chainId).toBe('number'); - expect(typeof nodeInfo.rollupAddress).toBe('object'); + expect(typeof nodeInfo.l1ContractAddresses.rollupAddress).toBe('object'); // For the sandbox quickstart we just want to show them preloaded accounts (since it is a quickstart) // We show creation of accounts in a later test diff --git a/yarn-project/end-to-end/src/fixtures/cross_chain_test_harness.ts b/yarn-project/end-to-end/src/fixtures/cross_chain_test_harness.ts index e34244ade3f..ac0e4938aa3 100644 --- a/yarn-project/end-to-end/src/fixtures/cross_chain_test_harness.ts +++ b/yarn-project/end-to-end/src/fixtures/cross_chain_test_harness.ts @@ -36,7 +36,7 @@ export class CrossChainTestHarness { const [owner, receiver] = accounts; const outbox = getContract({ - address: deployL1ContractsValues.outboxAddress.toString(), + address: deployL1ContractsValues.l1ContractAddresses.outboxAddress!.toString(), abi: OutboxAbi, publicClient, }); @@ -47,7 +47,7 @@ export class CrossChainTestHarness { wallet, walletClient, publicClient, - deployL1ContractsValues!.registryAddress, + deployL1ContractsValues!.l1ContractAddresses.registryAddress!, owner.address, underlyingERC20Address, ); diff --git a/yarn-project/end-to-end/src/fixtures/utils.ts b/yarn-project/end-to-end/src/fixtures/utils.ts index 4c8d570e987..ee52d114346 100644 --- a/yarn-project/end-to-end/src/fixtures/utils.ts +++ b/yarn-project/end-to-end/src/fixtures/utils.ts @@ -10,7 +10,6 @@ import { Wallet, createAccounts, createAztecRpcClient as createJsonRpcClient, - getL1ContractAddresses, getSandboxAccountsWallets, } from '@aztec/aztec.js'; import { CircuitsWasm, GeneratorIndex } from '@aztec/circuits.js'; @@ -85,30 +84,6 @@ const createRpcServer = async ( }; const setupL1Contracts = async (l1RpcUrl: string, account: HDAccount, logger: DebugLogger) => { - if (SANDBOX_URL) { - logger(`Retrieving contract addresses from ${SANDBOX_URL}`); - const l1Contracts = await getL1ContractAddresses(SANDBOX_URL); - - const walletClient = createWalletClient({ - account, - chain: localAnvil, - transport: http(l1RpcUrl), - }); - const publicClient = createPublicClient({ - chain: localAnvil, - transport: http(l1RpcUrl), - }); - return { - rollupAddress: l1Contracts.rollup, - registryAddress: l1Contracts.registry, - inboxAddress: l1Contracts.inbox, - outboxAddress: l1Contracts.outbox, - contractDeploymentEmitterAddress: l1Contracts.contractDeploymentEmitter, - decoderHelperAddress: l1Contracts.decoderHelper, - walletClient, - publicClient, - }; - } return await deployL1Contracts(l1RpcUrl, account, localAnvil, logger); }; @@ -222,15 +197,50 @@ export async function setup( const logger = getLogger(); const hdAccount = mnemonicToAccount(MNEMONIC); + if (SANDBOX_URL) { + // we are setting up against the sandbox, l1 contracts are already deployed + const { aztecRpcServer, accounts, wallets } = await setupAztecRPCServer(numberOfAccounts, undefined, logger); + logger(`Retrieving contract addresses from ${SANDBOX_URL}`); + const l1Contracts = (await aztecRpcServer.getNodeInfo()).l1ContractAddresses; + + const walletClient = createWalletClient({ + account: hdAccount, + chain: localAnvil, + transport: http(config.rpcUrl), + }); + const publicClient = createPublicClient({ + chain: localAnvil, + transport: http(config.rpcUrl), + }); + const deployL1ContractsValues: DeployL1Contracts = { + l1ContractAddresses: l1Contracts, + walletClient, + publicClient, + }; + const cheatCodes = await CheatCodes.create(config.rpcUrl, aztecRpcServer!); + return { + aztecNode: undefined, + aztecRpcServer, + deployL1ContractsValues, + accounts, + config, + wallet: wallets[0], + wallets, + logger, + cheatCodes, + }; + } + const deployL1ContractsValues = await setupL1Contracts(config.rpcUrl, hdAccount, logger); const privKeyRaw = hdAccount.getHdKey().privateKey; const publisherPrivKey = privKeyRaw === null ? null : Buffer.from(privKeyRaw); config.publisherPrivateKey = `0x${publisherPrivKey!.toString('hex')}`; - config.rollupContract = deployL1ContractsValues.rollupAddress; - config.contractDeploymentEmitterContract = deployL1ContractsValues.contractDeploymentEmitterAddress; - config.inboxContract = deployL1ContractsValues.inboxAddress; - config.registryContract = deployL1ContractsValues.registryAddress; + config.l1Contracts.rollupAddress = deployL1ContractsValues.l1ContractAddresses.rollupAddress; + config.l1Contracts.registryAddress = deployL1ContractsValues.l1ContractAddresses.registryAddress; + config.l1Contracts.contractDeploymentEmitterAddress = + deployL1ContractsValues.l1ContractAddresses.contractDeploymentEmitterAddress; + config.l1Contracts.inboxAddress = deployL1ContractsValues.l1ContractAddresses.inboxAddress; const aztecNode = await createAztecNode(config, logger); diff --git a/yarn-project/end-to-end/src/integration_archiver_l1_to_l2.test.ts b/yarn-project/end-to-end/src/integration_archiver_l1_to_l2.test.ts index 771502116e5..ff740dcdd3e 100644 --- a/yarn-project/end-to-end/src/integration_archiver_l1_to_l2.test.ts +++ b/yarn-project/end-to-end/src/integration_archiver_l1_to_l2.test.ts @@ -52,7 +52,7 @@ describe('archiver integration with l1 to l2 messages', () => { wallet, walletClient, publicClient, - deployL1ContractsValues!.registryAddress, + deployL1ContractsValues!.l1ContractAddresses.registryAddress!, initialBalance, owner, ); diff --git a/yarn-project/end-to-end/src/integration_l1_publisher.test.ts b/yarn-project/end-to-end/src/integration_l1_publisher.test.ts index 13bcd08e760..75406d8f06d 100644 --- a/yarn-project/end-to-end/src/integration_l1_publisher.test.ts +++ b/yarn-project/end-to-end/src/integration_l1_publisher.test.ts @@ -13,7 +13,7 @@ import { range, } from '@aztec/circuits.js'; import { fr, makeNewContractData, makeProof } from '@aztec/circuits.js/factories'; -import { deployL1Contracts } from '@aztec/ethereum'; +import { L1ContractAddresses, deployL1Contracts } from '@aztec/ethereum'; import { EthAddress } from '@aztec/foundation/eth-address'; import { Fr } from '@aztec/foundation/fields'; import { createDebugLogger } from '@aztec/foundation/log'; @@ -93,23 +93,18 @@ describe('L1Publisher integration', () => { beforeEach(async () => { deployerAccount = privateKeyToAccount(deployerPK); const { - rollupAddress: rollupAddress_, - inboxAddress: inboxAddress_, - outboxAddress: outboxAddress_, - registryAddress: registryAddress_, - contractDeploymentEmitterAddress: contractDeploymentEmitterAddress_, - decoderHelperAddress: decoderHelperAddress_, - publicClient: publicClient_, + l1ContractAddresses, walletClient, + publicClient: publicClient_, } = await deployL1Contracts(config.rpcUrl, deployerAccount, localAnvil, logger, true); publicClient = publicClient_; - rollupAddress = getAddress(rollupAddress_.toString()); - inboxAddress = getAddress(inboxAddress_.toString()); - outboxAddress = getAddress(outboxAddress_.toString()); - registryAddress = getAddress(registryAddress_.toString()); - contractDeploymentEmitterAddress = getAddress(contractDeploymentEmitterAddress_.toString()); - decoderHelperAddress = getAddress(decoderHelperAddress_!.toString()); + rollupAddress = getAddress(l1ContractAddresses.rollupAddress!.toString()); + inboxAddress = getAddress(l1ContractAddresses.inboxAddress!.toString()); + outboxAddress = getAddress(l1ContractAddresses.outboxAddress!.toString()); + contractDeploymentEmitterAddress = getAddress(l1ContractAddresses.contractDeploymentEmitterAddress!.toString()); + decoderHelperAddress = getAddress(l1ContractAddresses.decoderHelperAddress!.toString()); + registryAddress = getAddress(l1ContractAddresses.registryAddress!.toString()); // Set up contract instances rollup = getContract({ @@ -142,14 +137,19 @@ describe('L1Publisher integration', () => { l2Proof = Buffer.alloc(0); + const l1Contracts = new L1ContractAddresses( + EthAddress.fromString(rollupAddress), + EthAddress.fromString(registryAddress), + EthAddress.fromString(inboxAddress), + undefined, + EthAddress.fromString(contractDeploymentEmitterAddress), + ); + publisher = getL1Publisher({ rpcUrl: config.rpcUrl, apiKey: '', requiredConfirmations: 1, - rollupContract: EthAddress.fromString(rollupAddress), - inboxContract: EthAddress.fromString(inboxAddress), - registryContract: EthAddress.fromString(registryAddress), - contractDeploymentEmitterContract: EthAddress.fromString(contractDeploymentEmitterAddress), + l1Contracts, publisherPrivateKey: sequencerPK, l1BlockPublishRetryIntervalMS: 100, }); diff --git a/yarn-project/end-to-end/src/uniswap_trade_on_l1_from_l2.test.ts b/yarn-project/end-to-end/src/uniswap_trade_on_l1_from_l2.test.ts index b8482b98f7c..8b27b03fd26 100644 --- a/yarn-project/end-to-end/src/uniswap_trade_on_l1_from_l2.test.ts +++ b/yarn-project/end-to-end/src/uniswap_trade_on_l1_from_l2.test.ts @@ -111,7 +111,7 @@ describe.skip('uniswap_trade_on_l1_from_l2', () => { await uniswapL2Contract.attach(uniswapPortalAddress); await uniswapPortal.write.initialize( - [deployL1ContractsValues!.registryAddress.toString(), uniswapL2Contract.address.toString()], + [deployL1ContractsValues!.l1ContractAddresses.registryAddress!.toString(), uniswapL2Contract.address.toString()], {} as any, ); diff --git a/yarn-project/ethereum/src/deploy_l1_contracts.ts b/yarn-project/ethereum/src/deploy_l1_contracts.ts index 4a8a7998e03..744209d85f4 100644 --- a/yarn-project/ethereum/src/deploy_l1_contracts.ts +++ b/yarn-project/ethereum/src/deploy_l1_contracts.ts @@ -31,6 +31,8 @@ import { } from 'viem'; import { HDAccount, PrivateKeyAccount } from 'viem/accounts'; +import { L1ContractAddresses } from './l1_contract_addresses.js'; + /** * Return type of the deployL1Contract function. */ @@ -43,30 +45,11 @@ export type DeployL1Contracts = { * Public Client Type. */ publicClient: PublicClient; + /** - * Rollup Address. - */ - rollupAddress: EthAddress; - /** - * Registry Address. - */ - registryAddress: EthAddress; - /** - * Inbox Address. - */ - inboxAddress: EthAddress; - /** - * Outbox Address. - */ - outboxAddress: EthAddress; - /** - * Data Emitter Address. - */ - contractDeploymentEmitterAddress: EthAddress; - /** - * Decoder Helper Address. + * The currently deployed l1 contract addresses */ - decoderHelperAddress?: EthAddress; + l1ContractAddresses: L1ContractAddresses; }; /** @@ -141,15 +124,19 @@ export const deployL1Contracts = async ( logger(`Deployed DecoderHelper at ${decoderHelperAddress}`); } - return { - walletClient, - publicClient, + const l1Contracts = new L1ContractAddresses( rollupAddress, registryAddress, inboxAddress, outboxAddress, contractDeploymentEmitterAddress, decoderHelperAddress, + ); + + return { + walletClient, + publicClient, + l1ContractAddresses: l1Contracts, }; }; diff --git a/yarn-project/ethereum/src/index.ts b/yarn-project/ethereum/src/index.ts index 6279349059c..c8edddb8dde 100644 --- a/yarn-project/ethereum/src/index.ts +++ b/yarn-project/ethereum/src/index.ts @@ -5,6 +5,7 @@ import { createTestnetChain } from './testnet.js'; export * from './testnet.js'; export * from './deploy_l1_contracts.js'; +export * from './l1_contract_addresses.js'; /** * Helper function to create an instance of Aztec Chain from an rpc url and api key. diff --git a/yarn-project/ethereum/src/l1_contract_addresses.ts b/yarn-project/ethereum/src/l1_contract_addresses.ts new file mode 100644 index 00000000000..814a04ed5e8 --- /dev/null +++ b/yarn-project/ethereum/src/l1_contract_addresses.ts @@ -0,0 +1,82 @@ +import { EthAddress } from '@aztec/foundation/eth-address'; + +/** + * Provides the directory of current L1 contract addresses + */ +export class L1ContractAddresses { + constructor( + /** + * Rollup Address. + */ + public rollupAddress?: EthAddress, + /** + * Registry Address. + */ + public registryAddress?: EthAddress, + /** + * Inbox Address. + */ + public inboxAddress?: EthAddress, + /** + * Outbox Address. + */ + public outboxAddress?: EthAddress, + /** + * Data Emitter Address. + */ + public contractDeploymentEmitterAddress?: EthAddress, + /** + * Decoder Helper Address. + */ + public decoderHelperAddress?: EthAddress, + ) {} + + /** + * Serialize as JSON object. + * @returns The string. + */ + toJSON() { + const obj: { [key: string]: string } = {}; + if (this.rollupAddress) { + obj.rollupAddress = this.rollupAddress?.toString(); + } + if (this.registryAddress) { + obj.registryAddress = this.registryAddress?.toString(); + } + if (this.inboxAddress) { + obj.inboxAddress = this.inboxAddress?.toString(); + } + if (this.outboxAddress) { + obj.outboxAddress = this.outboxAddress?.toString(); + } + if (this.contractDeploymentEmitterAddress) { + obj.contractDeploymentEmitterAddress = this.contractDeploymentEmitterAddress?.toString(); + } + if (this.decoderHelperAddress) { + obj.decoderHelperAddress = this.decoderHelperAddress?.toString(); + } + return obj; + } + + /** + * Deserializes from a JSON. + * @param obj - object to read from + * @returns The deserialized L1ContractAddresses object. + */ + static fromJSON(obj: any): L1ContractAddresses { + const fromString = (key: string) => { + if (obj[key]) { + return EthAddress.fromString(obj[key]); + } + return undefined; + }; + return new L1ContractAddresses( + fromString('rollupAddress'), + fromString('registryAddress'), + fromString('inboxAddress'), + fromString('outboxAddress'), + fromString('contractDeploymentEmitterAddress'), + fromString('decoderHelperAddress'), + ); + } +} diff --git a/yarn-project/foundation/package.json b/yarn-project/foundation/package.json index 3e8e058f4be..59e7f903efb 100644 --- a/yarn-project/foundation/package.json +++ b/yarn-project/foundation/package.json @@ -58,7 +58,7 @@ "debug": "^4.3.4", "detect-node": "^2.1.0", "hash.js": "^1.1.7", - "koa": "^2.14.1", + "koa": "^2.14.2", "koa-bodyparser": "^4.4.0", "koa-compress": "^5.1.0", "koa-router": "^12.0.0", diff --git a/yarn-project/p2p/src/bootstrap/bootstrap.ts b/yarn-project/p2p/src/bootstrap/bootstrap.ts index 5c02976f1e2..e57e9596263 100644 --- a/yarn-project/p2p/src/bootstrap/bootstrap.ts +++ b/yarn-project/p2p/src/bootstrap/bootstrap.ts @@ -5,7 +5,6 @@ import { yamux } from '@chainsafe/libp2p-yamux'; import type { ServiceMap } from '@libp2p/interface-libp2p'; import { kadDHT } from '@libp2p/kad-dht'; import { mplex } from '@libp2p/mplex'; -import { createFromProtobuf } from '@libp2p/peer-id-factory'; import { tcp } from '@libp2p/tcp'; import { Libp2p, Libp2pOptions, ServiceFactoryMap, createLibp2p } from 'libp2p'; import { identifyService } from 'libp2p/identify'; @@ -29,9 +28,7 @@ export class BootstrapNode { public async start(config: P2PConfig) { const { peerIdPrivateKey, tcpListenIp, tcpListenPort, announceHostname, announcePort, minPeerCount, maxPeerCount } = config; - const peerId = peerIdPrivateKey - ? await createFromProtobuf(Buffer.from(peerIdPrivateKey, 'hex')) - : await createLibP2PPeerId(); + const peerId = await createLibP2PPeerId(peerIdPrivateKey); this.logger( `Starting bootstrap node ${peerId} on ${tcpListenIp}:${tcpListenPort} announced at ${announceHostname}:${announcePort}`, ); @@ -41,7 +38,7 @@ export class BootstrapNode { peerId, addresses: { listen: [`/ip4/${tcpListenIp}/tcp/${tcpListenPort}`], - announce: [`/ip4/${announceHostname}/tcp/${announcePort ?? tcpListenPort}`], + announce: announceHostname ? [`/ip4/${announceHostname}/tcp/${announcePort ?? tcpListenPort}`] : [], }, transports: [tcp()], streamMuxers: [yamux(), mplex()], diff --git a/yarn-project/p2p/src/service/libp2p_service.ts b/yarn-project/p2p/src/service/libp2p_service.ts index ca2e5f4de8a..83cd580e320 100644 --- a/yarn-project/p2p/src/service/libp2p_service.ts +++ b/yarn-project/p2p/src/service/libp2p_service.ts @@ -10,7 +10,7 @@ import { PeerId } from '@libp2p/interface-peer-id'; import { IncomingStreamData } from '@libp2p/interface/stream-handler'; import { DualKadDHT, kadDHT } from '@libp2p/kad-dht'; import { mplex } from '@libp2p/mplex'; -import { createEd25519PeerId, createFromProtobuf, exportToProtobuf } from '@libp2p/peer-id-factory'; +import { createFromJSON, createSecp256k1PeerId, exportToProtobuf } from '@libp2p/peer-id-factory'; import { tcp } from '@libp2p/tcp'; import { pipe } from 'it-pipe'; import { Libp2p, Libp2pOptions, ServiceFactoryMap, createLibp2p } from 'libp2p'; @@ -35,11 +35,19 @@ import { const INITIAL_PEER_REFRESH_INTERVAL = 20000; /** - * Create a libp2p peer ID. + * Create a libp2p peer ID from the private key if provided, otherwise creates a new random ID. + * @param privateKey - Optional peer ID private key as hex string * @returns The peer ID. */ -export async function createLibP2PPeerId() { - return await createEd25519PeerId(); +export async function createLibP2PPeerId(privateKey?: string) { + if (!privateKey) { + return await createSecp256k1PeerId(); + } + const base64 = Buffer.from(privateKey, 'hex').toString('base64'); + return await createFromJSON({ + id: '', + privKey: base64, + }); } /** @@ -141,10 +149,9 @@ export class LibP2PService implements P2PService { serverMode, minPeerCount, maxPeerCount, + peerIdPrivateKey, } = config; - const peerId = config.peerIdPrivateKey - ? await createFromProtobuf(Buffer.from(config.peerIdPrivateKey, 'hex')) - : await createLibP2PPeerId(); + const peerId = await createLibP2PPeerId(peerIdPrivateKey); const opts: Libp2pOptions = { start: false, diff --git a/yarn-project/sequencer-client/src/config.ts b/yarn-project/sequencer-client/src/config.ts index 3a5540f97b3..f7e74ce7d72 100644 --- a/yarn-project/sequencer-client/src/config.ts +++ b/yarn-project/sequencer-client/src/config.ts @@ -1,3 +1,4 @@ +import { L1ContractAddresses } from '@aztec/ethereum'; import { EthAddress } from '@aztec/foundation/eth-address'; import { GlobalReaderConfig } from './global_variable_builder/index.js'; @@ -36,6 +37,14 @@ export function getConfigEnvVars(): SequencerClientConfig { : '0000000000000000000000000000000000000000000000000000000000000000' }`; + const addresses = new L1ContractAddresses( + ROLLUP_CONTRACT_ADDRESS ? EthAddress.fromString(ROLLUP_CONTRACT_ADDRESS) : EthAddress.ZERO, + REGISTRY_CONTRACT_ADDRESS ? EthAddress.fromString(REGISTRY_CONTRACT_ADDRESS) : EthAddress.ZERO, + INBOX_CONTRACT_ADDRESS ? EthAddress.fromString(INBOX_CONTRACT_ADDRESS) : EthAddress.ZERO, + undefined, + CONTRACT_DEPLOYMENT_EMITTER_ADDRESS ? EthAddress.fromString(CONTRACT_DEPLOYMENT_EMITTER_ADDRESS) : EthAddress.ZERO, + ); + return { rpcUrl: ETHEREUM_HOST ? ETHEREUM_HOST : '', chainId: CHAIN_ID ? +CHAIN_ID : 31337, // 31337 is the default chain id for anvil @@ -44,12 +53,7 @@ export function getConfigEnvVars(): SequencerClientConfig { requiredConfirmations: SEQ_REQUIRED_CONFS ? +SEQ_REQUIRED_CONFS : 1, l1BlockPublishRetryIntervalMS: SEQ_PUBLISH_RETRY_INTERVAL_MS ? +SEQ_PUBLISH_RETRY_INTERVAL_MS : 1_000, transactionPollingIntervalMS: SEQ_TX_POLLING_INTERVAL_MS ? +SEQ_TX_POLLING_INTERVAL_MS : 1_000, - rollupContract: ROLLUP_CONTRACT_ADDRESS ? EthAddress.fromString(ROLLUP_CONTRACT_ADDRESS) : EthAddress.ZERO, - inboxContract: INBOX_CONTRACT_ADDRESS ? EthAddress.fromString(INBOX_CONTRACT_ADDRESS) : EthAddress.ZERO, - registryContract: REGISTRY_CONTRACT_ADDRESS ? EthAddress.fromString(REGISTRY_CONTRACT_ADDRESS) : EthAddress.ZERO, - contractDeploymentEmitterContract: CONTRACT_DEPLOYMENT_EMITTER_ADDRESS - ? EthAddress.fromString(CONTRACT_DEPLOYMENT_EMITTER_ADDRESS) - : EthAddress.ZERO, + l1Contracts: addresses, publisherPrivateKey, maxTxsPerBlock: SEQ_MAX_TX_PER_BLOCK ? +SEQ_MAX_TX_PER_BLOCK : 32, minTxsPerBlock: SEQ_MIN_TX_PER_BLOCK ? +SEQ_MIN_TX_PER_BLOCK : 1, diff --git a/yarn-project/sequencer-client/src/global_variable_builder/config.ts b/yarn-project/sequencer-client/src/global_variable_builder/config.ts index 909d3d32b05..2884374561a 100644 --- a/yarn-project/sequencer-client/src/global_variable_builder/config.ts +++ b/yarn-project/sequencer-client/src/global_variable_builder/config.ts @@ -1,13 +1,9 @@ -import { EthAddress } from '@aztec/circuits.js'; +import { L1ContractAddresses } from '@aztec/ethereum'; /** * Configuration of the L1GlobalReader. */ export interface GlobalReaderConfig { - /** - * Rollup contract address. - */ - rollupContract: EthAddress; /** * The RPC Url of the ethereum host. */ @@ -16,4 +12,9 @@ export interface GlobalReaderConfig { * The API key of the ethereum host. */ apiKey?: string; + + /** + * The deployed l1 contract addresses + */ + l1Contracts: L1ContractAddresses; } diff --git a/yarn-project/sequencer-client/src/global_variable_builder/viem-reader.ts b/yarn-project/sequencer-client/src/global_variable_builder/viem-reader.ts index e351db0c09d..6dd24c2c4b7 100644 --- a/yarn-project/sequencer-client/src/global_variable_builder/viem-reader.ts +++ b/yarn-project/sequencer-client/src/global_variable_builder/viem-reader.ts @@ -23,7 +23,7 @@ export class ViemReader implements L1GlobalReader { private publicClient: PublicClient; constructor(config: GlobalReaderConfig) { - const { rpcUrl, apiKey, rollupContract: rollupContractAddress } = config; + const { rpcUrl, apiKey, l1Contracts } = config; const chain = createEthereumChain(rpcUrl, apiKey); @@ -33,7 +33,7 @@ export class ViemReader implements L1GlobalReader { }); this.rollupContract = getContract({ - address: getAddress(rollupContractAddress.toString()), + address: getAddress(l1Contracts.rollupAddress!.toString()), abi: RollupAbi, publicClient: this.publicClient, }); diff --git a/yarn-project/sequencer-client/src/publisher/config.ts b/yarn-project/sequencer-client/src/publisher/config.ts index 5ec4cfde76c..96ad07bd6f1 100644 --- a/yarn-project/sequencer-client/src/publisher/config.ts +++ b/yarn-project/sequencer-client/src/publisher/config.ts @@ -1,9 +1,9 @@ -import { L1Addresses } from '@aztec/types'; +import { L1ContractAddresses } from '@aztec/ethereum'; /** * The configuration of the rollup transaction publisher. */ -export interface TxSenderConfig extends L1Addresses { +export interface TxSenderConfig { /** * The private key to be used by the publisher. */ @@ -23,6 +23,11 @@ export interface TxSenderConfig extends L1Addresses { * The number of confirmations required. */ requiredConfirmations: number; + + /** + * The deployed l1 contract addresses + */ + l1Contracts: L1ContractAddresses; } /** diff --git a/yarn-project/sequencer-client/src/publisher/viem-tx-sender.ts b/yarn-project/sequencer-client/src/publisher/viem-tx-sender.ts index d9e112e8d0a..106517c65fe 100644 --- a/yarn-project/sequencer-client/src/publisher/viem-tx-sender.ts +++ b/yarn-project/sequencer-client/src/publisher/viem-tx-sender.ts @@ -41,13 +41,7 @@ export class ViemTxSender implements L1PublisherTxSender { private account: PrivateKeyAccount; constructor(config: TxSenderConfig) { - const { - rpcUrl, - apiKey, - publisherPrivateKey, - rollupContract: rollupContractAddress, - contractDeploymentEmitterContract: contractDeploymentEmitterContractAddress, - } = config; + const { rpcUrl, apiKey, publisherPrivateKey, l1Contracts } = config; const chain = createEthereumChain(rpcUrl, apiKey); this.account = privateKeyToAccount(publisherPrivateKey); const walletClient = createWalletClient({ @@ -62,13 +56,13 @@ export class ViemTxSender implements L1PublisherTxSender { }); this.rollupContract = getContract({ - address: getAddress(rollupContractAddress.toString()), + address: getAddress(l1Contracts.rollupAddress!.toString()), abi: RollupAbi, publicClient: this.publicClient, walletClient, }); this.contractDeploymentEmitterContract = getContract({ - address: getAddress(contractDeploymentEmitterContractAddress.toString()), + address: getAddress(l1Contracts.contractDeploymentEmitterAddress!.toString()), abi: ContractDeploymentEmitterAbi, publicClient: this.publicClient, walletClient, diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.ts index e51a0d9595b..a04c7568907 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.ts @@ -32,8 +32,6 @@ export class Sequencer { private minTxsPerBLock = 1; private lastPublishedBlock = 0; private state = SequencerState.STOPPED; - private chainId: Fr; - private version: Fr; constructor( private publisher: L1Publisher, @@ -54,8 +52,6 @@ export class Sequencer { if (config.minTxsPerBlock) { this.minTxsPerBLock = config.minTxsPerBlock; } - this.chainId = new Fr(config.chainId); - this.version = new Fr(config.version); } /** diff --git a/yarn-project/types/package.json b/yarn-project/types/package.json index 78977f0c5f4..78fa4e4fda9 100644 --- a/yarn-project/types/package.json +++ b/yarn-project/types/package.json @@ -31,6 +31,7 @@ }, "dependencies": { "@aztec/circuits.js": "workspace:^", + "@aztec/ethereum": "workspace:^", "@aztec/foundation": "workspace:^", "browserify-cipher": "^1.0.1", "lodash.clonedeep": "^4.5.0", diff --git a/yarn-project/aztec-node/src/rpc/http_rpc_client.ts b/yarn-project/types/src/aztec_node/rpc/http_rpc_client.ts similarity index 90% rename from yarn-project/aztec-node/src/rpc/http_rpc_client.ts rename to yarn-project/types/src/aztec_node/rpc/http_rpc_client.ts index c19c787a35d..23c1216475e 100644 --- a/yarn-project/aztec-node/src/rpc/http_rpc_client.ts +++ b/yarn-project/types/src/aztec_node/rpc/http_rpc_client.ts @@ -1,4 +1,5 @@ import { HistoricBlockData } from '@aztec/circuits.js'; +import { L1ContractAddresses } from '@aztec/ethereum'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { EthAddress } from '@aztec/foundation/eth-address'; import { Fr } from '@aztec/foundation/fields'; @@ -15,7 +16,7 @@ export function createAztecNodeRpcClient(url: string, fetch = defaultFetch): Azt const rpcClient = createJsonRpcClient( url, { AztecAddress, EthAddress, ExtendedContractData, ContractData, Fr, HistoricBlockData, L2Block, L2Tx, TxHash }, - { Tx, L2BlockL2Logs }, + { Tx, L2BlockL2Logs, L1ContractAddresses }, false, fetch, ); diff --git a/yarn-project/aztec-node/src/rpc/http_rpc_server.ts b/yarn-project/types/src/aztec_node/rpc/http_rpc_server.ts similarity index 91% rename from yarn-project/aztec-node/src/rpc/http_rpc_server.ts rename to yarn-project/types/src/aztec_node/rpc/http_rpc_server.ts index e1fb672952b..25b7c2205cf 100644 --- a/yarn-project/aztec-node/src/rpc/http_rpc_server.ts +++ b/yarn-project/types/src/aztec_node/rpc/http_rpc_server.ts @@ -1,4 +1,5 @@ import { HistoricBlockData } from '@aztec/circuits.js'; +import { L1ContractAddresses } from '@aztec/ethereum'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { EthAddress } from '@aztec/foundation/eth-address'; import { Fr } from '@aztec/foundation/fields'; @@ -14,7 +15,7 @@ export function createAztecNodeRpcServer(node: AztecNode) { const rpc = new JsonRpcServer( node, { AztecAddress, EthAddress, ExtendedContractData, ContractData, Fr, HistoricBlockData, L2Block, L2Tx, TxHash }, - { Tx, L2BlockL2Logs }, + { Tx, L2BlockL2Logs, L1ContractAddresses }, false, // disable methods not part of the AztecNode interface [ diff --git a/yarn-project/types/src/aztec_node/rpc/index.ts b/yarn-project/types/src/aztec_node/rpc/index.ts new file mode 100644 index 00000000000..b182baaccf1 --- /dev/null +++ b/yarn-project/types/src/aztec_node/rpc/index.ts @@ -0,0 +1,2 @@ +export * from './http_rpc_client.js'; +export * from './http_rpc_server.js'; diff --git a/yarn-project/types/src/index.ts b/yarn-project/types/src/index.ts index c9714153628..9d41e4dcb67 100644 --- a/yarn-project/types/src/index.ts +++ b/yarn-project/types/src/index.ts @@ -4,7 +4,6 @@ export * from './contract_database.js'; export * from './contract_data.js'; export * from './function_call.js'; export * from './keys/index.js'; -export * from './l1_addresses.js'; export * from './l1_to_l2_message.js'; export * from './l2_block.js'; export * from './l2_block_context.js'; @@ -22,5 +21,6 @@ export * from './packed_arguments.js'; export * from './interfaces/index.js'; export * from './sibling_path.js'; export * from './auth_witness.js'; +export * from './aztec_node/rpc/index.js'; export * from '@aztec/circuits.js/types'; export { CompleteAddress } from '@aztec/circuits.js'; diff --git a/yarn-project/types/src/interfaces/aztec-node.ts b/yarn-project/types/src/interfaces/aztec-node.ts index bac696c3850..a3ebcf30039 100644 --- a/yarn-project/types/src/interfaces/aztec-node.ts +++ b/yarn-project/types/src/interfaces/aztec-node.ts @@ -1,4 +1,5 @@ -import { EthAddress, HistoricBlockData } from '@aztec/circuits.js'; +import { HistoricBlockData } from '@aztec/circuits.js'; +import { L1ContractAddresses } from '@aztec/ethereum'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr } from '@aztec/foundation/fields'; @@ -62,16 +63,10 @@ export interface AztecNode extends DataCommitmentProvider, L1ToL2MessageProvider getChainId(): Promise; /** - * Method to fetch the rollup contract address at the base-layer. - * @returns The rollup address. + * Method to fetch the currently deployed l1 contract addresses. + * @returns The deployed contract addresses. */ - getRollupAddress(): Promise; - - /** - * Method to fetch the registry contract address at the base-layer. - * @returns The registry address. - */ - getRegistryAddress(): Promise; + getL1ContractAddresses(): Promise; /** * Get the extended contract data for this contract. diff --git a/yarn-project/types/src/interfaces/aztec_rpc.ts b/yarn-project/types/src/interfaces/aztec_rpc.ts index 2c487329fac..ea78215dc3e 100644 --- a/yarn-project/types/src/interfaces/aztec_rpc.ts +++ b/yarn-project/types/src/interfaces/aztec_rpc.ts @@ -12,8 +12,8 @@ import { TxReceipt, } from '@aztec/types'; +import { NodeInfo } from '../node-info/node-info.js'; import { DeployedContract } from './deployed-contract.js'; -import { NodeInfo } from './node-info.js'; import { SyncStatus } from './sync-status.js'; // docs:start:rpc-interface diff --git a/yarn-project/types/src/interfaces/index.ts b/yarn-project/types/src/interfaces/index.ts index d53098ad94c..18df9e9e0ce 100644 --- a/yarn-project/types/src/interfaces/index.ts +++ b/yarn-project/types/src/interfaces/index.ts @@ -5,5 +5,5 @@ export * from './l1_l2_message_provider.js'; export * from './aztec-node.js'; export * from './aztec_rpc.js'; export * from './deployed-contract.js'; -export * from './node-info.js'; +export * from '../node-info/node-info.js'; export * from './sync-status.js'; diff --git a/yarn-project/types/src/interfaces/node-info.ts b/yarn-project/types/src/interfaces/node-info.ts deleted file mode 100644 index 6c10d6b5ef8..00000000000 --- a/yarn-project/types/src/interfaces/node-info.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { EthAddress } from '@aztec/circuits.js'; - -/** - * Provides basic information about the running node. - */ -export type NodeInfo = { - /** - * Version as tracked in the aztec-packages repository. - */ - sandboxVersion: string; - /** - * The nargo version compatible with this sandbox version - */ - compatibleNargoVersion: string; - /** - * L1 chain id. - */ - chainId: number; - /** - * Protocol version. - */ - protocolVersion: number; - /** - * The rollup contract address - */ - rollupAddress: EthAddress; - /** - * The registry contract address - */ - registryAddress: EthAddress; -}; diff --git a/yarn-project/types/src/l1_addresses.ts b/yarn-project/types/src/l1_addresses.ts deleted file mode 100644 index a85fb0f889a..00000000000 --- a/yarn-project/types/src/l1_addresses.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { EthAddress } from '@aztec/foundation/eth-address'; - -/** - * Rollup contract addresses. - */ -export interface L1Addresses { - /** - * Rollup contract address. - */ - rollupContract: EthAddress; - - /** - * Inbox contract address. - */ - inboxContract: EthAddress; - - /** - * Registry contract address. - */ - registryContract: EthAddress; - - /** - * ContractDeploymentEmitter contract address. - */ - contractDeploymentEmitterContract: EthAddress; -} diff --git a/yarn-project/types/src/node-info/index.ts b/yarn-project/types/src/node-info/index.ts new file mode 100644 index 00000000000..46da7a96f90 --- /dev/null +++ b/yarn-project/types/src/node-info/index.ts @@ -0,0 +1 @@ +export * from './node-info.js'; diff --git a/yarn-project/types/src/node-info/node-info.ts b/yarn-project/types/src/node-info/node-info.ts new file mode 100644 index 00000000000..b71b8f7374e --- /dev/null +++ b/yarn-project/types/src/node-info/node-info.ts @@ -0,0 +1,72 @@ +import { L1ContractAddresses } from '@aztec/ethereum'; + +/** + * Provides basic information about the running node. + */ +export class NodeInfo { + constructor( + /** + * Version as tracked in the aztec-packages repository. + */ + public sandboxVersion: string, + /** + * The nargo version compatible with this sandbox version + */ + public compatibleNargoVersion: string, + /** + * L1 chain id. + */ + public chainId: number, + /** + * Protocol version. + */ + public protocolVersion: number, + /** + * The deployed l1 contract addresses + */ + public l1ContractAddresses: L1ContractAddresses, + ) {} + + /** + * Converts the Node Info to a readable string. + * @returns A readable string contaiing the node info. + */ + public toReadableString() { + return ` + Sandbox Version: ${this.sandboxVersion}\n + Compatible Nargo Version: ${this.compatibleNargoVersion}\n + Chain Id: ${this.chainId}\n + Protocol Version: ${this.protocolVersion}\n + Rollup Address: ${this.l1ContractAddresses.rollupAddress?.toString()} + `; + } + + /** + * Serialize as JSON object. + * @returns The string. + */ + toJSON() { + return { + sandboxVersion: this.sandboxVersion, + compatibleNargoVersion: this.compatibleNargoVersion, + chainId: this.chainId, + protocolVersion: this.protocolVersion, + l1ContractAddresses: this.l1ContractAddresses.toJSON(), + }; + } + + /** + * Deserializes from a JSON. + * @param obj - String to read from. + * @returns The deserialized NodeInfo object. + */ + static fromJSON(obj: any): NodeInfo { + return new NodeInfo( + obj.sandboxVersion, + obj.compatibleNargoVersion, + obj.chainId, + obj.protocolVersion, + L1ContractAddresses.fromJSON(obj.l1ContractAddresses), + ); + } +} diff --git a/yarn-project/types/tsconfig.json b/yarn-project/types/tsconfig.json index 82aa8cf4ccf..e7053342b34 100644 --- a/yarn-project/types/tsconfig.json +++ b/yarn-project/types/tsconfig.json @@ -9,6 +9,9 @@ { "path": "../circuits.js" }, + { + "path": "../ethereum" + }, { "path": "../foundation" } diff --git a/yarn-project/yarn.lock b/yarn-project/yarn.lock index 9252fc38ac7..25bee29a45c 100644 --- a/yarn-project/yarn.lock +++ b/yarn-project/yarn.lock @@ -120,6 +120,7 @@ __metadata: dependencies: "@aztec/archiver": "workspace:^" "@aztec/circuits.js": "workspace:^" + "@aztec/ethereum": "workspace:^" "@aztec/foundation": "workspace:^" "@aztec/l1-artifacts": "workspace:^" "@aztec/merkle-tree": "workspace:^" @@ -134,10 +135,14 @@ __metadata: "@types/memdown": ^3.0.0 "@types/node": ^18.7.23 jest: ^29.5.0 + koa: ^2.14.2 + koa-router: ^12.0.0 ts-jest: ^29.1.0 ts-node: ^10.9.1 tslib: ^2.4.0 typescript: ^5.0.4 + bin: + aztec-node: ./dest/bin/index.js languageName: unknown linkType: soft @@ -147,6 +152,7 @@ __metadata: dependencies: "@aztec/acir-simulator": "workspace:^" "@aztec/circuits.js": "workspace:^" + "@aztec/ethereum": "workspace:^" "@aztec/foundation": "workspace:^" "@aztec/key-store": "workspace:^" "@aztec/noir-compiler": "workspace:^" @@ -160,6 +166,8 @@ __metadata: "@types/node": ^18.7.23 jest: ^29.5.0 jest-mock-extended: ^3.0.3 + koa: ^2.14.2 + koa-router: ^12.0.0 lodash.omit: ^4.5.0 lodash.partition: ^4.6.0 lodash.times: ^4.3.2 @@ -169,6 +177,8 @@ __metadata: tslib: ^2.4.0 typescript: ^5.0.4 viem: ^1.2.5 + bin: + aztec-rpc: ./dest/bin/index.js languageName: unknown linkType: soft @@ -228,6 +238,7 @@ __metadata: resolution: "@aztec/aztec.js@workspace:aztec.js" dependencies: "@aztec/circuits.js": "workspace:^" + "@aztec/ethereum": "workspace:^" "@aztec/foundation": "workspace:^" "@aztec/types": "workspace:^" "@jest/globals": ^29.5.0 @@ -237,6 +248,8 @@ __metadata: "@types/lodash.partition": ^4.6.0 "@types/lodash.zip": ^4.2.7 "@types/node": ^18.7.23 + assert: ^2.1.0 + browserify-zlib: ^0.2.0 buffer: ^6.0.3 crypto-browserify: ^3.12.0 jest: ^29.5.0 @@ -245,8 +258,10 @@ __metadata: lodash.partition: ^4.6.0 lodash.zip: ^4.2.0 process: ^0.11.10 + querystring-es3: ^0.2.1 resolve-typescript-plugin: ^2.0.1 stream-browserify: ^3.0.0 + stream-http: ^3.2.0 ts-jest: ^29.1.0 ts-loader: ^9.4.4 ts-node: ^10.9.1 @@ -341,6 +356,7 @@ __metadata: "@aztec/foundation": "workspace:^" "@aztec/noir-compiler": "workspace:^" "@aztec/noir-contracts": "workspace:^" + "@aztec/p2p": "workspace:^" "@aztec/types": "workspace:^" "@jest/globals": ^29.5.0 "@rushstack/eslint-patch": ^1.1.4 @@ -477,7 +493,7 @@ __metadata: eslint-plugin-tsdoc: ^0.2.17 hash.js: ^1.1.7 jest: ^29.5.0 - koa: ^2.14.1 + koa: ^2.14.2 koa-bodyparser: ^4.4.0 koa-compress: ^5.1.0 koa-router: ^12.0.0 @@ -730,6 +746,7 @@ __metadata: resolution: "@aztec/types@workspace:types" dependencies: "@aztec/circuits.js": "workspace:^" + "@aztec/ethereum": "workspace:^" "@aztec/foundation": "workspace:^" "@jest/globals": ^29.5.0 "@rushstack/eslint-patch": ^1.1.4 @@ -6517,6 +6534,19 @@ __metadata: languageName: node linkType: hard +"assert@npm:^2.1.0": + version: 2.1.0 + resolution: "assert@npm:2.1.0" + dependencies: + call-bind: ^1.0.2 + is-nan: ^1.3.2 + object-is: ^1.1.5 + object.assign: ^4.1.4 + util: ^0.12.5 + checksum: 1ed1cabba9abe55f4109b3f7292b4e4f3cf2953aad8dc148c0b3c3bd676675c31b1abb32ef563b7d5a19d1715bf90d1e5f09fad2a4ee655199468902da80f7c2 + languageName: node + linkType: hard + "assertion-error@npm:^1.1.0": version: 1.1.0 resolution: "assertion-error@npm:1.1.0" @@ -7098,6 +7128,15 @@ __metadata: languageName: node linkType: hard +"browserify-zlib@npm:^0.2.0": + version: 0.2.0 + resolution: "browserify-zlib@npm:0.2.0" + dependencies: + pako: ~1.0.5 + checksum: 5cd9d6a665190fedb4a97dfbad8dabc8698d8a507298a03f42c734e96d58ca35d3c7d4085e283440bbca1cd1938cff85031728079bedb3345310c58ab1ec92d6 + languageName: node + linkType: hard + "browserslist@npm:^4.14.5, browserslist@npm:^4.21.10, browserslist@npm:^4.21.9": version: 4.21.10 resolution: "browserslist@npm:4.21.10" @@ -7214,6 +7253,13 @@ __metadata: languageName: node linkType: hard +"builtin-status-codes@npm:^3.0.0": + version: 3.0.0 + resolution: "builtin-status-codes@npm:3.0.0" + checksum: 1119429cf4b0d57bf76b248ad6f529167d343156ebbcc4d4e4ad600484f6bc63002595cbb61b67ad03ce55cd1d3c4711c03bbf198bf24653b8392420482f3773 + languageName: node + linkType: hard + "bundle-name@npm:^3.0.0": version: 3.0.0 resolution: "bundle-name@npm:3.0.0" @@ -11286,6 +11332,16 @@ __metadata: languageName: node linkType: hard +"is-nan@npm:^1.3.2": + version: 1.3.2 + resolution: "is-nan@npm:1.3.2" + dependencies: + call-bind: ^1.0.0 + define-properties: ^1.1.3 + checksum: 5dfadcef6ad12d3029d43643d9800adbba21cf3ce2ec849f734b0e14ee8da4070d82b15fdb35138716d02587c6578225b9a22779cab34888a139cc43e4e3610a + languageName: node + linkType: hard + "is-negative-zero@npm:^2.0.2": version: 2.0.2 resolution: "is-negative-zero@npm:2.0.2" @@ -13076,7 +13132,7 @@ __metadata: languageName: node linkType: hard -"koa@npm:^2.14.1, koa@npm:^2.14.2": +"koa@npm:^2.14.2": version: 2.14.2 resolution: "koa@npm:2.14.2" dependencies: @@ -14989,7 +15045,7 @@ __metadata: languageName: node linkType: hard -"pako@npm:~1.0.2": +"pako@npm:~1.0.2, pako@npm:~1.0.5": version: 1.0.11 resolution: "pako@npm:1.0.11" checksum: 1be2bfa1f807608c7538afa15d6f25baa523c30ec870a3228a89579e474a4d992f4293859524e46d5d87fd30fa17c5edf34dbef0671251d9749820b488660b16 @@ -15796,6 +15852,13 @@ __metadata: languageName: node linkType: hard +"querystring-es3@npm:^0.2.1": + version: 0.2.1 + resolution: "querystring-es3@npm:0.2.1" + checksum: 691e8d6b8b157e7cd49ae8e83fcf86de39ab3ba948c25abaa94fba84c0986c641aa2f597770848c64abce290ed17a39c9df6df737dfa7e87c3b63acc7d225d61 + languageName: node + linkType: hard + "queue-microtask@npm:^1.2.2, queue-microtask@npm:^1.2.3": version: 1.2.3 resolution: "queue-microtask@npm:1.2.3" @@ -17239,6 +17302,18 @@ __metadata: languageName: node linkType: hard +"stream-http@npm:^3.2.0": + version: 3.2.0 + resolution: "stream-http@npm:3.2.0" + dependencies: + builtin-status-codes: ^3.0.0 + inherits: ^2.0.4 + readable-stream: ^3.6.0 + xtend: ^4.0.2 + checksum: c9b78453aeb0c84fcc59555518ac62bacab9fa98e323e7b7666e5f9f58af8f3155e34481078509b02929bd1268427f664d186604cdccee95abc446099b339f83 + languageName: node + linkType: hard + "stream-shift@npm:^1.0.0": version: 1.0.1 resolution: "stream-shift@npm:1.0.1" @@ -19200,7 +19275,7 @@ __metadata: languageName: node linkType: hard -"xtend@npm:^4.0.1": +"xtend@npm:^4.0.1, xtend@npm:^4.0.2": version: 4.0.2 resolution: "xtend@npm:4.0.2" checksum: ac5dfa738b21f6e7f0dd6e65e1b3155036d68104e67e5d5d1bde74892e327d7e5636a076f625599dc394330a731861e87343ff184b0047fef1360a7ec0a5a36a