From 4a5238e7e0e016248fe96f876d55859bb9cc9fe8 Mon Sep 17 00:00:00 2001 From: Leila Wang Date: Sun, 26 Mar 2023 10:49:58 +0100 Subject: [PATCH] Aztec.js and AztecRPCServer. (#80) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update e2e test. * Aztec.js and AztecRPCServer. (#67) * Add ContractDeployer. * Add aztec-rpc, remove wallet. * Initial Aztec RPC Server. * Use pre-generated abi in e2e. * Update yarn.lock. * Use aztec-node in aztec-rpc. * Update dockerfiles. * Fix dependencies. * Update dockerfile. * Update build manifest. * Cleanup. * Interface changes. * Fix. * Fix. * Update eslintrc source. * feat(sim): added skeleton of simulators to the aztec rpc server (#73) * feat(acir): added skeleton for acir sim * feat(sim): use callstackitem * feat(sim): kernel prover skeleton * merge milestone/1_1 into arv/simulators * feat(sim): integrate sim skeleton with rpc * refactor: remove unused comments * chore: global skipLibCheck * Revert "chore: global skipLibCheck" This reverts commit fe274275b6f868ec749545b7ee2bc11d65f9c976. * chore: renamed kernel-simulator to kernel-prover * feat(rpc): fetch acir and portal from DB * fix(prover): pass signature to kernel * chore: added build of deps * chore: fixed dockerfile * chore: master => milestone1-1 (#78) * Working Aztec Node (#76) * Init sequencer client * Update circuits to "TS structs for merge and root rollups structs" See https://github.com/AztecProtocol/aztec3-circuits/pull/81 * Symlink circuits/ts into yarn-project * Fix archiver main * Expose p2p client state and fix typo * Rename aztec-ethereumjs-tx-sender * Sequencer client wip * Include full output of private kernel circuit in p2p pool txs * Remove hardcoded deps and block builder (wip) * Update circuits to palla/aztec3-packages branch * Update l1-contracts * Update sequencer to use new method names * Update archiver to use current l1 contract abi * Add archiver integration test * Update circuits package * Update yarn.lock * Lose lastBlock view method in rollup contract and remove syncStatus from archiver in favor of latestBlockNum * Archiver TODOs for when we move to mainnet * Update rollup contract to latest * Fix archiver test * WIP * Use components and serialization from circuits package for L2Block * WIP * WIP * Format archiver * Check consistency of block number in block parsed from calldata * Make linter happy * Format * WIP * Add missing reference * WIP * WIP * Move references in archiver to base tsconfig * Add formatting:fix tasks here and there * Fix build issues * WIP * WIP * WIP * Fix build issues on integration test and move to separate folder * WIP * WIP * Update rollup contract to handle blocks with id 0 * Fix settled block num in integration test * Use aztec debug logger and add inspect method for L2block * Fix bug in block builder due to bad ordering of ctor args * Stop sequencer when aztec node stops * Add integration test for processing 3 txs * Apply changes to all trees on world state synchroniser * Formatting * Working Aztec Node * Minor refactor * Lint fix * Yarn lockfile * Merge fixes * Project references * Build order * Docker file * Test rename * Test logging * fix: build (attempt) * fix: build (attempt) * fix: build (attempt) * fix: build (attempt) * fix: build (attempt) * fix: build (attempt) * fix: build (attempt) * fix: build (attempt) * fix: build (attempt) * fix: build by refactoring .yalc usage * fix: build by refactoring .yalc usage * Revert l1-contracts * Update Dockerfile * Update circuits * Update circuits * fix: circuits.js ref * fix: misc build --------- Co-authored-by: Santiago Palladino Co-authored-by: Adam Domurad Co-authored-by: ludamad Co-authored-by: ludamad * post-merge * post-merge * post-merge * post-merge --------- Co-authored-by: PhilWindle <60546371+PhilWindle@users.noreply.github.com> Co-authored-by: Santiago Palladino Co-authored-by: Adam Domurad * Fix merge. * Remove formatting from build script. * Mark contract as deployed when block is settled. * Update ts ref. * Revert test. * Update build manifest. * Fix. * Fix. * Empty test. --------- Co-authored-by: Álvaro Rodríguez Co-authored-by: ludamad Co-authored-by: PhilWindle <60546371+PhilWindle@users.noreply.github.com> Co-authored-by: Santiago Palladino Co-authored-by: Adam Domurad --- README.md | 4 +- bootstrap.sh | 17 +- build_manifest.json | 45 ++-- build_manifest.sh | 4 +- l1-contracts | 2 +- yarn-project/acir-simulator/package.json | 2 +- yarn-project/acir-simulator/src/acvm.ts | 31 +++ yarn-project/acir-simulator/src/circuits.ts | 229 ++++++++++++++++++ yarn-project/acir-simulator/src/db_oracle.ts | 16 ++ yarn-project/acir-simulator/src/index.ts | 7 +- yarn-project/acir-simulator/src/simulator.ts | 69 ++++++ yarn-project/archiver/package.json | 2 +- yarn-project/aztec-cli/package.json | 2 +- yarn-project/aztec-node/package.json | 2 +- .../.eslintrc.cjs | 0 yarn-project/{wallet => aztec-rpc}/Dockerfile | 10 +- yarn-project/aztec-rpc/README.md | 1 + .../{wallet => aztec-rpc}/package.json | 12 +- yarn-project/aztec-rpc/src/abi_coder/index.ts | 11 + .../src/account_state/account_state.ts | 11 + .../aztec-rpc/src/account_state/index.ts | 1 + .../src/aztec_rpc_client/aztec_rpc_client.ts | 23 ++ .../aztec-rpc/src/aztec_rpc_client/index.ts | 1 + .../src/aztec_rpc_server/aztec_rpc_server.ts | 175 +++++++++++++ .../create_aztec_rpc_server.ts | 32 +++ .../aztec-rpc/src/aztec_rpc_server/index.ts | 2 + yarn-project/aztec-rpc/src/circuits.ts | 167 +++++++++++++ .../src/contract_data_source/contract_dao.ts | 36 +++ .../contract_data_source.ts | 10 + .../src/contract_data_source/index.ts | 3 + .../memory_contract_data_source.ts | 36 +++ .../aztec-rpc/src/database/database.ts | 7 + yarn-project/aztec-rpc/src/database/index.ts | 3 + .../aztec-rpc/src/database/memory_db.ts | 12 + yarn-project/aztec-rpc/src/database/tx_dao.ts | 14 ++ yarn-project/aztec-rpc/src/foundation.ts | 12 + yarn-project/aztec-rpc/src/index.ts | 9 + yarn-project/aztec-rpc/src/key_store/index.ts | 3 + .../aztec-rpc/src/key_store/key_pair.ts | 34 +++ .../aztec-rpc/src/key_store/key_store.ts | 8 + .../aztec-rpc/src/key_store/test_key_store.ts | 34 +++ yarn-project/aztec-rpc/src/noir.ts | 123 ++++++++++ .../aztec-rpc/src/synchroniser/index.ts | 1 + .../src/synchroniser/synchroniser.ts | 96 ++++++++ yarn-project/aztec-rpc/src/tx/index.ts | 2 + yarn-project/aztec-rpc/src/tx/tx_hash.ts | 9 + yarn-project/aztec-rpc/src/tx/tx_receipt.ts | 14 ++ yarn-project/aztec-rpc/tsconfig.dest.json | 21 ++ yarn-project/aztec-rpc/tsconfig.json | 26 ++ yarn-project/aztec.js/Dockerfile | 5 +- yarn-project/aztec.js/package.json | 6 +- .../aztec.js/src/abi_coder/hex_string.ts | 3 + yarn-project/aztec.js/src/abi_coder/index.ts | 15 ++ .../src/contract/contract_function.ts | 14 ++ yarn-project/aztec.js/src/contract/index.ts | 3 + .../aztec.js/src/contract/send_method.ts | 73 ++++++ yarn-project/aztec.js/src/contract/sent_tx.ts | 22 ++ .../contract_deployer/constructor_method.ts | 50 ++++ .../contract_deployer.test.ts | 114 +++++++++ .../contract_deployer/contract_deployer.ts | 13 + .../aztec.js/src/contract_deployer/index.ts | 1 + yarn-project/aztec.js/src/foundation.ts | 63 +++++ yarn-project/aztec.js/src/index.test.ts | 7 - yarn-project/aztec.js/src/index.ts | 9 +- yarn-project/aztec.js/tsconfig.dest.json | 8 + yarn-project/aztec.js/tsconfig.json | 8 + yarn-project/end-to-end/Dockerfile | 8 +- yarn-project/end-to-end/package.json | 4 +- .../end-to-end/src/create_aztec_node.ts | 20 ++ .../end-to-end/src/create_aztec_rpc_client.ts | 14 ++ .../src/e2e_deploy_contract.test.ts | 4 +- .../{wallet => kernel-prover}/.eslintrc.cjs | 0 .../Dockerfile | 8 +- .../README.md | 0 .../package.json | 6 +- yarn-project/kernel-prover/src/circuits.ts | 26 ++ yarn-project/kernel-prover/src/index.ts | 53 ++++ yarn-project/kernel-prover/tsconfig.dest.json | 12 + .../tsconfig.json | 8 + yarn-project/kernel-simulator/src/index.ts | 4 - .../kernel-simulator/tsconfig.dest.json | 4 - yarn-project/key-store/package.json | 2 +- yarn-project/l1-contracts/package.json | 2 +- yarn-project/merkle-tree/package.json | 2 +- yarn-project/noir-contracts/package.json | 2 +- yarn-project/p2p/package.json | 2 +- yarn-project/package.json | 4 +- yarn-project/prover-client/package.json | 2 +- yarn-project/sequencer-client/package.json | 2 +- yarn-project/typedoc.json | 4 +- yarn-project/wallet/README.md | 1 - yarn-project/wallet/src/index.ts | 4 - yarn-project/wallet/tsconfig.dest.json | 4 - yarn-project/wallet/tsconfig.json | 9 - yarn-project/world-state/package.json | 2 +- yarn-project/yarn-project-base/Dockerfile | 4 +- yarn-project/yarn.lock | 53 ++-- 97 files changed, 1928 insertions(+), 147 deletions(-) create mode 100644 yarn-project/acir-simulator/src/acvm.ts create mode 100644 yarn-project/acir-simulator/src/circuits.ts create mode 100644 yarn-project/acir-simulator/src/db_oracle.ts create mode 100644 yarn-project/acir-simulator/src/simulator.ts rename yarn-project/{kernel-simulator => aztec-rpc}/.eslintrc.cjs (100%) rename yarn-project/{wallet => aztec-rpc}/Dockerfile (58%) create mode 100644 yarn-project/aztec-rpc/README.md rename yarn-project/{wallet => aztec-rpc}/package.json (76%) create mode 100644 yarn-project/aztec-rpc/src/abi_coder/index.ts create mode 100644 yarn-project/aztec-rpc/src/account_state/account_state.ts create mode 100644 yarn-project/aztec-rpc/src/account_state/index.ts create mode 100644 yarn-project/aztec-rpc/src/aztec_rpc_client/aztec_rpc_client.ts create mode 100644 yarn-project/aztec-rpc/src/aztec_rpc_client/index.ts create mode 100644 yarn-project/aztec-rpc/src/aztec_rpc_server/aztec_rpc_server.ts create mode 100644 yarn-project/aztec-rpc/src/aztec_rpc_server/create_aztec_rpc_server.ts create mode 100644 yarn-project/aztec-rpc/src/aztec_rpc_server/index.ts create mode 100644 yarn-project/aztec-rpc/src/circuits.ts create mode 100644 yarn-project/aztec-rpc/src/contract_data_source/contract_dao.ts create mode 100644 yarn-project/aztec-rpc/src/contract_data_source/contract_data_source.ts create mode 100644 yarn-project/aztec-rpc/src/contract_data_source/index.ts create mode 100644 yarn-project/aztec-rpc/src/contract_data_source/memory_contract_data_source.ts create mode 100644 yarn-project/aztec-rpc/src/database/database.ts create mode 100644 yarn-project/aztec-rpc/src/database/index.ts create mode 100644 yarn-project/aztec-rpc/src/database/memory_db.ts create mode 100644 yarn-project/aztec-rpc/src/database/tx_dao.ts create mode 100644 yarn-project/aztec-rpc/src/foundation.ts create mode 100644 yarn-project/aztec-rpc/src/index.ts create mode 100644 yarn-project/aztec-rpc/src/key_store/index.ts create mode 100644 yarn-project/aztec-rpc/src/key_store/key_pair.ts create mode 100644 yarn-project/aztec-rpc/src/key_store/key_store.ts create mode 100644 yarn-project/aztec-rpc/src/key_store/test_key_store.ts create mode 100644 yarn-project/aztec-rpc/src/noir.ts create mode 100644 yarn-project/aztec-rpc/src/synchroniser/index.ts create mode 100644 yarn-project/aztec-rpc/src/synchroniser/synchroniser.ts create mode 100644 yarn-project/aztec-rpc/src/tx/index.ts create mode 100644 yarn-project/aztec-rpc/src/tx/tx_hash.ts create mode 100644 yarn-project/aztec-rpc/src/tx/tx_receipt.ts create mode 100644 yarn-project/aztec-rpc/tsconfig.dest.json create mode 100644 yarn-project/aztec-rpc/tsconfig.json create mode 100644 yarn-project/aztec.js/src/abi_coder/hex_string.ts create mode 100644 yarn-project/aztec.js/src/abi_coder/index.ts create mode 100644 yarn-project/aztec.js/src/contract/contract_function.ts create mode 100644 yarn-project/aztec.js/src/contract/index.ts create mode 100644 yarn-project/aztec.js/src/contract/send_method.ts create mode 100644 yarn-project/aztec.js/src/contract/sent_tx.ts create mode 100644 yarn-project/aztec.js/src/contract_deployer/constructor_method.ts create mode 100644 yarn-project/aztec.js/src/contract_deployer/contract_deployer.test.ts create mode 100644 yarn-project/aztec.js/src/contract_deployer/contract_deployer.ts create mode 100644 yarn-project/aztec.js/src/contract_deployer/index.ts create mode 100644 yarn-project/aztec.js/src/foundation.ts delete mode 100644 yarn-project/aztec.js/src/index.test.ts create mode 100644 yarn-project/end-to-end/src/create_aztec_node.ts create mode 100644 yarn-project/end-to-end/src/create_aztec_rpc_client.ts rename yarn-project/{wallet => kernel-prover}/.eslintrc.cjs (100%) rename yarn-project/{kernel-simulator => kernel-prover}/Dockerfile (55%) rename yarn-project/{kernel-simulator => kernel-prover}/README.md (100%) rename yarn-project/{kernel-simulator => kernel-prover}/package.json (86%) create mode 100644 yarn-project/kernel-prover/src/circuits.ts create mode 100644 yarn-project/kernel-prover/src/index.ts create mode 100644 yarn-project/kernel-prover/tsconfig.dest.json rename yarn-project/{kernel-simulator => kernel-prover}/tsconfig.json (50%) delete mode 100644 yarn-project/kernel-simulator/src/index.ts delete mode 100644 yarn-project/kernel-simulator/tsconfig.dest.json delete mode 100644 yarn-project/wallet/README.md delete mode 100644 yarn-project/wallet/src/index.ts delete mode 100644 yarn-project/wallet/tsconfig.dest.json delete mode 100644 yarn-project/wallet/tsconfig.json diff --git a/README.md b/README.md index 0089c0f3f07..6d127df72c7 100644 --- a/README.md +++ b/README.md @@ -5,13 +5,13 @@ The Aztec 3 system consists of the following sub projects. - `acir-simulator` - `archiver` - `aztec-cli` +- `aztec-rpc` - `aztec.js` - `ethereum.js` -- `kernel-simulator` +- `kernel-prover` - `key-store` - `l1-contracts` - `p2p` - `prover-client` - `aztec-node` - `sequencer-client` -- `wallet` diff --git a/bootstrap.sh b/bootstrap.sh index f6c88db6b58..e6d05b76c2c 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -47,23 +47,20 @@ cd ../.. # We only bootstrap projects that produce artefacts needed for running end-to-end tests. PROJECTS=( - # "circuits:./bootstrap.sh db_cli rollup_cli" - # "yarn-project/acir-simulator:yarn build" - # "yarn-project/aztec-cli:yarn build" "yarn-project/foundation:yarn build" "yarn-project/l1-contracts:yarn build" - "yarn-project/aztec.js:yarn build" "yarn-project/ethereum.js:yarn build" - "yarn-project/archiver:yarn build" - # "yarn-project/kernel-simulator:yarn build" - "yarn-project/key-store:yarn build" "yarn-project/merkle-tree:yarn build" - "yarn-project/p2p:yarn build" - # "yarn-project/prover-client:yarn build" - # "yarn-project/wallet:yarn build" + "yarn-project/archiver:yarn build" "yarn-project/world-state:yarn build" + "yarn-project/p2p:yarn build" "yarn-project/sequencer-client:yarn build" "yarn-project/aztec-node:yarn build" + "yarn-project/key-store:yarn build" + "yarn-project/acir-simulator:yarn build" + "yarn-project/kernel-prover:yarn build" + "yarn-project/aztec-rpc:yarn build" + "yarn-project/aztec.js:yarn build" ) for E in "${PROJECTS[@]}"; do diff --git a/build_manifest.json b/build_manifest.json index d9b83b14df2..0fca6b15f52 100644 --- a/build_manifest.json +++ b/build_manifest.json @@ -57,21 +57,28 @@ "projectDir": "yarn-project/aztec-cli", "dockerfile": "aztec-cli/Dockerfile", "rebuildPatterns": ["^yarn-project/aztec-cli/"], - "dependencies": ["yarn-project-base"] + "dependencies": ["aztec.js"] + }, + "aztec-rpc": { + "buildDir": "yarn-project", + "projectDir": "yarn-project/aztec-rpc", + "dockerfile": "aztec-rpc/Dockerfile", + "rebuildPatterns": ["^yarn-project/aztec-rpc/"], + "dependencies": ["aztec-node"] }, "aztec.js": { "buildDir": "yarn-project", "projectDir": "yarn-project/aztec.js", "dockerfile": "aztec.js/Dockerfile", "rebuildPatterns": ["^yarn-project/aztec.js/"], - "dependencies": ["yarn-project-base", "foundation"] + "dependencies": ["aztec-rpc"] }, "end-to-end": { "buildDir": "yarn-project", "projectDir": "yarn-project/end-to-end", "dockerfile": "end-to-end/Dockerfile", "rebuildPatterns": ["^yarn-project/end-to-end/"], - "dependencies": ["yarn-project-base", "foundation"] + "dependencies": ["aztec.js"] }, "ethereum.js": { "buildDir": "yarn-project", @@ -80,11 +87,18 @@ "rebuildPatterns": ["^yarn-project/ethereum.js/"], "dependencies": ["yarn-project-base", "foundation"] }, - "kernel-simulator": { + "foundation": { + "buildDir": "yarn-project", + "projectDir": "yarn-project/foundation", + "dockerfile": "foundation/Dockerfile", + "rebuildPatterns": ["^yarn-project/foundation/"], + "dependencies": [] + }, + "kernel-prover": { "buildDir": "yarn-project", - "projectDir": "yarn-project/kernel-simulator", - "dockerfile": "kernel-simulator/Dockerfile", - "rebuildPatterns": ["^yarn-project/kernel-simulator/"], + "projectDir": "yarn-project/kernel-prover", + "dockerfile": "kernel-prover/Dockerfile", + "rebuildPatterns": ["^yarn-project/kernel-prover/"], "dependencies": ["yarn-project-base"] }, "key-store": { @@ -94,13 +108,6 @@ "rebuildPatterns": ["^yarn-project/key-store/"], "dependencies": ["yarn-project-base"] }, - "foundation": { - "buildDir": "yarn-project", - "projectDir": "yarn-project/foundation", - "dockerfile": "foundation/Dockerfile", - "rebuildPatterns": ["^yarn-project/foundation/"], - "dependencies": ["yarn-project-base"] - }, "merkle-tree": { "buildDir": "yarn-project", "projectDir": "yarn-project/merkle-tree", @@ -140,8 +147,7 @@ "world-state", "p2p", "sequencer-client", - "ethereum.js", - "circuits.js" + "ethereum.js" ] }, "sequencer-client": { @@ -157,13 +163,6 @@ "archiver" ] }, - "wallet": { - "buildDir": "yarn-project", - "projectDir": "yarn-project/wallet", - "dockerfile": "wallet/Dockerfile", - "rebuildPatterns": ["^yarn-project/wallet/"], - "dependencies": ["yarn-project-base"] - }, "world-state": { "buildDir": "yarn-project", "projectDir": "yarn-project/world-state", diff --git a/build_manifest.sh b/build_manifest.sh index ebe59c4e914..7857d7653f3 100755 --- a/build_manifest.sh +++ b/build_manifest.sh @@ -14,16 +14,16 @@ PROJECTS=( # acir-simulator:yarn-project # archiver:yarn-project # aztec-cli:yarn-project + # aztec-rpc:yarn-project # aztec.js:yarn-project # end-to-end:yarn-project # ethereum.js:yarn-project - # kernel-simulator:yarn-project + # kernel-prover:yarn-project # key-store:yarn-project # merkle-tree:yarn-project # p2p:yarn-project # prover-client:yarn-project # aztec-node:yarn-project # sequencer-client:yarn-project - # wallet:yarn-project # world-state:yarn-project ) diff --git a/l1-contracts b/l1-contracts index 7f01e8875c1..daacc374bb9 160000 --- a/l1-contracts +++ b/l1-contracts @@ -1 +1 @@ -Subproject commit 7f01e8875c187e56feda3e3a7bf6d8d1ce638b62 +Subproject commit daacc374bb9b1c59bfc90b50e6bc97114ed4fbd6 diff --git a/yarn-project/acir-simulator/package.json b/yarn-project/acir-simulator/package.json index beca27e246b..f16e4039145 100644 --- a/yarn-project/acir-simulator/package.json +++ b/yarn-project/acir-simulator/package.json @@ -9,7 +9,7 @@ "tsconfig": "./tsconfig.dest.json" }, "scripts": { - "build": "yarn clean && yarn formatting && tsc -b tsconfig.dest.json", + "build": "yarn clean && tsc -b tsconfig.dest.json", "build:dev": "tsc -b tsconfig.dest.json --watch", "clean": "rm -rf ./dest .tsbuildinfo", "formatting": "run -T prettier --check ./src && run -T eslint --max-warnings 0 ./src", diff --git a/yarn-project/acir-simulator/src/acvm.ts b/yarn-project/acir-simulator/src/acvm.ts new file mode 100644 index 00000000000..2c2f5daabe2 --- /dev/null +++ b/yarn-project/acir-simulator/src/acvm.ts @@ -0,0 +1,31 @@ +import { AztecAddress, CallContext, ContractDeploymentData } from './circuits.js'; +import { NoteLoadOracleInputs } from './db_oracle.js'; + +export interface ACIRCallback { + getSecretKey(keyId: Buffer): Promise; + getNotes(storageSlot: Buffer): Promise; + getRandomField(): Promise; + privateFunctionCall( + contractAddress: AztecAddress, + functionSelector: string, + args: Array, + ): Promise>; +} + +export interface ExecutionPreimages { + newNotes: Buffer[]; + nullifiedNotes: Buffer[]; +} + +export interface ACIRExecutionResult { + preimages: ExecutionPreimages; + partialWitness: Buffer; +} + +export type execute = ( + acir: Buffer, + args: Array, + callContext: CallContext, + contractDeploymentData: ContractDeploymentData, + oracle: ACIRCallback, +) => Promise; diff --git a/yarn-project/acir-simulator/src/circuits.ts b/yarn-project/acir-simulator/src/circuits.ts new file mode 100644 index 00000000000..917b55cc08a --- /dev/null +++ b/yarn-project/acir-simulator/src/circuits.ts @@ -0,0 +1,229 @@ +// See aztec3/constants.hpp +// Copied here for prototyping purposes +// In future: structured serialization? +export const ARGS_LENGTH = 8; +export const RETURN_VALUES_LENGTH = 4; +export const EMITTED_EVENTS_LENGTH = 4; + +export const NEW_COMMITMENTS_LENGTH = 4; +export const NEW_NULLIFIERS_LENGTH = 4; + +export const STATE_TRANSITIONS_LENGTH = 4; +export const STATE_READS_LENGTH = 4; + +export const PRIVATE_CALL_STACK_LENGTH = 4; +export const PUBLIC_CALL_STACK_LENGTH = 4; +export const L1_MSG_STACK_LENGTH = 2; + +export const KERNEL_NEW_COMMITMENTS_LENGTH = 16; +export const KERNEL_NEW_NULLIFIERS_LENGTH = 16; +export const KERNEL_NEW_CONTRACTS_LENGTH = 8; +export const KERNEL_PRIVATE_CALL_STACK_LENGTH = 8; +export const KERNEL_PUBLIC_CALL_STACK_LENGTH = 8; +export const KERNEL_L1_MSG_STACK_LENGTH = 4; +export const KERNEL_OPTIONALLY_REVEALED_DATA_LENGTH = 4; + +export const VK_TREE_HEIGHT = 3; +export const CONTRACT_TREE_HEIGHT = 4; +export const PRIVATE_DATA_TREE_HEIGHT = 8; +export const NULLIFIER_TREE_HEIGHT = 8; + +export const PRIVATE_DATA_TREE_ROOTS_TREE_HEIGHT = 8; +export const CONTRACT_TREE_ROOTS_TREE_HEIGHT = 8; + +export const FUNCTION_SELECTOR_NUM_BYTES = 31; + +/** + * Assert a member is a certain length. + * @param obj - An object. + * @param member - A member string. + * @param length - The length. + */ +export function assertLength( + obj: T, + member: F, + length: number, +) { + if (obj[member].length !== length) { + throw new Error(`Expected ${member} to have length ${length}! Was: ${obj[member].length}`); + } +} + +export class Fr { + public static ZERO = new Fr(Buffer.alloc(32)); + + constructor(public readonly buffer: Buffer) {} +} + +export class AztecAddress { + public static SIZE = 64; + + public static ZERO = new AztecAddress(Buffer.alloc(AztecAddress.SIZE)); + + constructor(public readonly buffer: Buffer) {} + + public equals(rhs: AztecAddress) { + return this.buffer.equals(rhs.buffer); + } +} + +export class EthAddress { + public static ZERO = new EthAddress(Buffer.alloc(20)); + + constructor(public readonly buffer: Buffer) {} +} + +/** + * Call context. + * @see abis/call_context.hpp + */ +export class CallContext { + constructor( + public msgSender: AztecAddress, + public storageContractAddress: AztecAddress, + public portalContractAddress: EthAddress, + public isDelegateCall: boolean, + public isStaticCall: boolean, + public isContractDeployment: boolean, + ) {} +} + +/** + * Contract deployment data in a @TxContext. + * cpp/src/aztec3/circuits/abis/contract_deployment_data.hpp + */ +export class ContractDeploymentData { + constructor( + public constructorVkHash: Fr, + public functionTreeRoot: Fr, + public contractAddressSalt: Fr, + public portalContractAddress: EthAddress, + ) {} +} + +/** + * Public inputs to a private circuit. + * @see abis/private_circuit_public_inputs.hpp. + */ +export class PrivateCircuitPublicInputs { + constructor( + // NOTE: Must have same order as CPP. + public callContext: CallContext, + public args: Fr[], + public returnValues: Fr[], + public emittedEvents: Fr[], + public newCommitments: Fr[], + public newNullifiers: Fr[], + public privateCallStack: Fr[], + public publicCallStack: Fr[], + public l1MsgStack: Fr[], + public historicPrivateDataTreeRoot: Fr, + public historicPrivateNullifierTreeRoot: Fr, + public historicContractTreeRoot: Fr, + public contractDeploymentData: ContractDeploymentData, + ) { + assertLength(this, 'args', ARGS_LENGTH); + assertLength(this, 'returnValues', RETURN_VALUES_LENGTH); + assertLength(this, 'emittedEvents', EMITTED_EVENTS_LENGTH); + assertLength(this, 'newCommitments', NEW_COMMITMENTS_LENGTH); + assertLength(this, 'newNullifiers', NEW_NULLIFIERS_LENGTH); + assertLength(this, 'privateCallStack', PRIVATE_CALL_STACK_LENGTH); + assertLength(this, 'publicCallStack', PUBLIC_CALL_STACK_LENGTH); + assertLength(this, 'l1MsgStack', L1_MSG_STACK_LENGTH); + } +} + +export class TxContext { + constructor( + public readonly isFeePaymentTx: boolean, + public readonly isRebatePaymentTx: boolean, + public readonly isContractDeploymentTx: boolean, + public readonly contractDeploymentData: ContractDeploymentData, + ) {} +} + +export interface FunctionData { + functionSelector: Buffer; + isSecret: boolean; + isContructor: boolean; +} + +export class TxRequest { + constructor( + public readonly from: AztecAddress, + public readonly to: AztecAddress, + public readonly functionData: FunctionData, + public readonly args: Fr[], + public readonly txContext: TxContext, + public readonly nonce: Fr, + public readonly chainId: Fr, + ) {} + + toBuffer() { + return Buffer.alloc(0); + } +} + +export class PrivateCallStackItem { + constructor( + public readonly contractAddress: AztecAddress, + public readonly functionSelector: Buffer, + public readonly publicInputs: PrivateCircuitPublicInputs, + ) {} +} + +export class OldTreeRoots { + constructor( + public privateDataTreeRoot: Fr, + public nullifierTreeRoot: Fr, + public contractTreeRoot: Fr, + public privateKernelVkTreeRoot: Fr, // future enhancement + ) {} +} + +export class ConstantData { + constructor(public oldTreeRoots: OldTreeRoots, public txContext: TxContext) {} +} + +export class AggregationObject {} + +export class NewContractData { + constructor( + public readonly contractAddress: AztecAddress, + public readonly portalContractAddress: EthAddress, + public readonly functionTreeRoot: Fr, + ) {} +} + +export class OptionallyRevealedData {} + +export class AccumulatedTxData { + constructor( + public aggregationObject: AggregationObject, // Contains the aggregated proof of all previous kernel iterations + + public privateCallCount: Fr, + + public newCommitments: Fr[], + public newNullifiers: Fr[], + + public privateCallStack: Fr[], + public publicCallStack: Fr[], + public l1MsgStack: Fr[], + + public newContracts: NewContractData[], + + public optionallyRevealedData: OptionallyRevealedData[], + ) { + assertLength(this, 'newCommitments', KERNEL_NEW_COMMITMENTS_LENGTH); + assertLength(this, 'newNullifiers', KERNEL_NEW_NULLIFIERS_LENGTH); + assertLength(this, 'privateCallStack', KERNEL_PRIVATE_CALL_STACK_LENGTH); + assertLength(this, 'publicCallStack', KERNEL_PUBLIC_CALL_STACK_LENGTH); + assertLength(this, 'l1MsgStack', KERNEL_L1_MSG_STACK_LENGTH); + assertLength(this, 'newContracts', KERNEL_NEW_CONTRACTS_LENGTH); + assertLength(this, 'optionallyRevealedData', KERNEL_OPTIONALLY_REVEALED_DATA_LENGTH); + } +} + +export class PrivateKernelPublicInputs { + constructor(public end: AccumulatedTxData, public constants: ConstantData, public isPrivateKernel: true) {} +} diff --git a/yarn-project/acir-simulator/src/db_oracle.ts b/yarn-project/acir-simulator/src/db_oracle.ts new file mode 100644 index 00000000000..ae006a01f95 --- /dev/null +++ b/yarn-project/acir-simulator/src/db_oracle.ts @@ -0,0 +1,16 @@ +import { AztecAddress, EthAddress } from './circuits.js'; + +export interface NoteLoadOracleInputs { + note: Buffer; + siblingPath: Buffer; + leafIndex: number; + root: Buffer; +} + +export interface DBOracle { + getSecretKey(contractAddress: AztecAddress, keyId: Buffer): Promise; + getNotes(contractAddress: AztecAddress, storageSlot: Buffer): Promise; + getBytecode(contractAddress: AztecAddress, functionSelector: string): Promise; + getProvingKey(contractAddress: AztecAddress, functionSelector: string): Promise; + getPortalContractAddress(contractAddress: AztecAddress): Promise; +} diff --git a/yarn-project/acir-simulator/src/index.ts b/yarn-project/acir-simulator/src/index.ts index e517e3e3ac0..330c9900b13 100644 --- a/yarn-project/acir-simulator/src/index.ts +++ b/yarn-project/acir-simulator/src/index.ts @@ -1,4 +1,3 @@ -/** - * A placeholder for the Acir Simulator. - */ -export class AcirSimulator {} +export * from './simulator.js'; +export * from './db_oracle.js'; +export * from './acvm.js'; diff --git a/yarn-project/acir-simulator/src/simulator.ts b/yarn-project/acir-simulator/src/simulator.ts new file mode 100644 index 00000000000..0716d462c69 --- /dev/null +++ b/yarn-project/acir-simulator/src/simulator.ts @@ -0,0 +1,69 @@ +import { ExecutionPreimages } from './acvm.js'; +import { + CallContext, + PrivateCircuitPublicInputs, + TxRequest, + EthAddress, + PrivateCallStackItem, + OldTreeRoots, +} from './circuits.js'; + +export interface ExecutionResult { + // Needed for prover + acir: Buffer; + partialWitness: Buffer; + // Needed for the verifier (kernel) + callStackItem: PrivateCallStackItem; + // Needed for the user + preimages: ExecutionPreimages; + // Nested executions + nestedExecutions: this[]; +} + +/** + * A placeholder for the Acir Simulator. + */ +export class AcirSimulator { + run( + request: TxRequest, + entryPointACIR: Buffer, + portalContractAddress: EthAddress, + oldRoots: OldTreeRoots, + ): Promise { + const callContext = new CallContext( + request.from, + request.to, + portalContractAddress, + false, + false, + request.functionData.isContructor, + ); + + const publicInputs = new PrivateCircuitPublicInputs( + callContext, + request.args, + [], // returnValues, + [], // emittedEvents, + [], // newCommitments, + [], // newNullifiers, + [], // privateCallStack, + [], // publicCallStack, + [], // l1MsgStack, + oldRoots.privateDataTreeRoot, + oldRoots.nullifierTreeRoot, + oldRoots.contractTreeRoot, + request.txContext.contractDeploymentData, + ); + + return Promise.resolve({ + acir: entryPointACIR, + partialWitness: Buffer.alloc(0), + callStackItem: new PrivateCallStackItem(request.to, request.functionData.functionSelector, publicInputs), + preimages: { + newNotes: [], + nullifiedNotes: [], + }, + nestedExecutions: [], + }); + } +} diff --git a/yarn-project/archiver/package.json b/yarn-project/archiver/package.json index 95ab3f35d22..8d65eee4494 100644 --- a/yarn-project/archiver/package.json +++ b/yarn-project/archiver/package.json @@ -9,7 +9,7 @@ "tsconfig": "./tsconfig.dest.json" }, "scripts": { - "build": "yarn clean && yarn formatting && tsc -b tsconfig.dest.json", + "build": "yarn clean && tsc -b tsconfig.dest.json", "build:dev": "tsc -b tsconfig.dest.json --watch", "start": "node ./dest", "start:dev": "tsc-watch -p tsconfig.dest.json --onSuccess 'yarn start'", diff --git a/yarn-project/aztec-cli/package.json b/yarn-project/aztec-cli/package.json index 9d6da2973d6..1343af35a4b 100644 --- a/yarn-project/aztec-cli/package.json +++ b/yarn-project/aztec-cli/package.json @@ -12,7 +12,7 @@ "aztec_cli": "index.js" }, "scripts": { - "build": "yarn clean && yarn formatting && tsc -b tsconfig.dest.json", + "build": "yarn clean && tsc -b tsconfig.dest.json", "build:dev": "tsc -p tsconfig.dest.json --watch", "clean": "rm -rf ./dest .tsbuildinfo", "formatting": "run -T prettier --check ./src && run -T eslint --max-warnings 0 ./src", diff --git a/yarn-project/aztec-node/package.json b/yarn-project/aztec-node/package.json index 11be37960c1..5337b382793 100644 --- a/yarn-project/aztec-node/package.json +++ b/yarn-project/aztec-node/package.json @@ -10,7 +10,7 @@ "tsconfig": "./tsconfig.dest.json" }, "scripts": { - "build": "yarn clean && yarn formatting && tsc -b tsconfig.dest.json", + "build": "yarn clean && tsc -b tsconfig.dest.json", "build:dev": "tsc -b tsconfig.dest.json --watch", "clean": "rm -rf ./dest .tsbuildinfo", "formatting": "run -T prettier --check ./src && run -T eslint --max-warnings 0 ./src", diff --git a/yarn-project/kernel-simulator/.eslintrc.cjs b/yarn-project/aztec-rpc/.eslintrc.cjs similarity index 100% rename from yarn-project/kernel-simulator/.eslintrc.cjs rename to yarn-project/aztec-rpc/.eslintrc.cjs diff --git a/yarn-project/wallet/Dockerfile b/yarn-project/aztec-rpc/Dockerfile similarity index 58% rename from yarn-project/wallet/Dockerfile rename to yarn-project/aztec-rpc/Dockerfile index 11131ce6756..b92f7b7ff4c 100644 --- a/yarn-project/wallet/Dockerfile +++ b/yarn-project/aztec-rpc/Dockerfile @@ -1,7 +1,7 @@ FROM 278380418400.dkr.ecr.eu-west-2.amazonaws.com/yarn-project-base AS builder - -COPY wallet wallet -WORKDIR /usr/src/yarn-project/wallet +COPY . . +RUN cd aztec-node && yarn build +WORKDIR /usr/src/yarn-project/aztec-rpc RUN yarn build && yarn formatting && yarn test # Prune dev dependencies. See comment in base image. @@ -9,6 +9,6 @@ RUN yarn cache clean RUN yarn workspaces focus --production > /dev/null FROM node:18-alpine -COPY --from=builder /usr/src/yarn-project/wallet /usr/src/yarn-project/wallet -WORKDIR /usr/src/yarn-project/wallet +COPY --from=builder /usr/src/yarn-project/aztec-rpc /usr/src/yarn-project/aztec-rpc +WORKDIR /usr/src/yarn-project/aztec-rpc ENTRYPOINT ["yarn"] \ No newline at end of file diff --git a/yarn-project/aztec-rpc/README.md b/yarn-project/aztec-rpc/README.md new file mode 100644 index 00000000000..b1e338ba694 --- /dev/null +++ b/yarn-project/aztec-rpc/README.md @@ -0,0 +1 @@ +# Aztec RPC Server & Client diff --git a/yarn-project/wallet/package.json b/yarn-project/aztec-rpc/package.json similarity index 76% rename from yarn-project/wallet/package.json rename to yarn-project/aztec-rpc/package.json index ee9b0749a6d..d359e6d3730 100644 --- a/yarn-project/wallet/package.json +++ b/yarn-project/aztec-rpc/package.json @@ -1,5 +1,5 @@ { - "name": "@aztec/wallet", + "name": "@aztec/aztec-rpc", "version": "0.0.0", "type": "module", "exports": "./dest/index.js", @@ -9,10 +9,10 @@ "tsconfig": "./tsconfig.dest.json" }, "scripts": { - "build": "yarn clean && yarn formatting && tsc -b tsconfig.dest.json", + "build": "yarn clean && tsc -b tsconfig.dest.json", "build:dev": "tsc -b tsconfig.dest.json --watch", "clean": "rm -rf ./dest .tsbuildinfo", - "formatting": "run -T prettier --check ./src && run -T eslint --max-warnings 0 ./src", + "formatting": "run -T prettier --check ./src && run -T eslint --max-warnings 10 ./src", "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --no-cache --passWithNoTests" }, "jest": { @@ -29,6 +29,12 @@ "rootDir": "./src" }, "dependencies": { + "@aztec/acir-simulator": "workspace:^", + "@aztec/aztec-node": "workspace:^", + "@aztec/foundation": "workspace:^", + "@aztec/kernel-prover": "workspace:^", + "@aztec/p2p": "workspace:^", + "sha3": "^2.1.4", "tslib": "^2.4.0" }, "devDependencies": { diff --git a/yarn-project/aztec-rpc/src/abi_coder/index.ts b/yarn-project/aztec-rpc/src/abi_coder/index.ts new file mode 100644 index 00000000000..0a37a288f75 --- /dev/null +++ b/yarn-project/aztec-rpc/src/abi_coder/index.ts @@ -0,0 +1,11 @@ +import { keccak256 } from '../foundation.js'; +import { ABIParameter } from '../noir.js'; + +export function generateFunctionSignature(name: string, parameters: ABIParameter[]) { + return name === 'constructor' ? name : `${name}(${parameters.map(p => p.type.kind).join(',')})`; +} + +export function generateFunctionSelector(name: string, parameters: ABIParameter[]) { + const signature = generateFunctionSignature(name, parameters); + return keccak256(Buffer.from(signature)).slice(0, 4); +} diff --git a/yarn-project/aztec-rpc/src/account_state/account_state.ts b/yarn-project/aztec-rpc/src/account_state/account_state.ts new file mode 100644 index 00000000000..8e5e97e27f9 --- /dev/null +++ b/yarn-project/aztec-rpc/src/account_state/account_state.ts @@ -0,0 +1,11 @@ +import { AztecAddress } from '../circuits.js'; +import { Database } from '../database/index.js'; +import { TxHash } from '../tx/index.js'; + +export class AccountState { + constructor(public readonly publicKey: AztecAddress, private db: Database) {} + + getTx(txHash: TxHash) { + return this.db.getTx(txHash); + } +} diff --git a/yarn-project/aztec-rpc/src/account_state/index.ts b/yarn-project/aztec-rpc/src/account_state/index.ts new file mode 100644 index 00000000000..fa1fec1b824 --- /dev/null +++ b/yarn-project/aztec-rpc/src/account_state/index.ts @@ -0,0 +1 @@ +export * from './account_state.js'; diff --git a/yarn-project/aztec-rpc/src/aztec_rpc_client/aztec_rpc_client.ts b/yarn-project/aztec-rpc/src/aztec_rpc_client/aztec_rpc_client.ts new file mode 100644 index 00000000000..94531725e8f --- /dev/null +++ b/yarn-project/aztec-rpc/src/aztec_rpc_client/aztec_rpc_client.ts @@ -0,0 +1,23 @@ +import { Tx } from '@aztec/p2p'; +import { AztecAddress, EthAddress, Fr, Signature, TxRequest } from '../circuits.js'; +import { ContractAbi } from '../noir.js'; +import { TxHash, TxReceipt } from '../tx/index.js'; + +export interface AztecRPCClient { + addAccount(): Promise; + getAccounts(): Promise; + getCode(contract: AztecAddress, functionSelector?: Buffer): Promise; + createDeploymentTxRequest( + abi: ContractAbi, + args: Fr[], + portalContract: EthAddress, + contractAddressSalt: Fr, + from: AztecAddress, + ): Promise; + createTxRequest(functionSelector: Buffer, args: Fr[], to: AztecAddress, from: AztecAddress): Promise; + signTxRequest(txRequest: TxRequest): Promise; + createTx(txRequest: TxRequest, signature: Signature): Promise; + sendTx(tx: Tx): Promise; + // callTx(functionSelector: Buffer, args: Fr[], to: AztecAddress, from: AztecAddress): Promise; + getTxReceipt(txHash: TxHash): Promise; +} diff --git a/yarn-project/aztec-rpc/src/aztec_rpc_client/index.ts b/yarn-project/aztec-rpc/src/aztec_rpc_client/index.ts new file mode 100644 index 00000000000..d70b35ea79b --- /dev/null +++ b/yarn-project/aztec-rpc/src/aztec_rpc_client/index.ts @@ -0,0 +1 @@ +export * from './aztec_rpc_client.js'; diff --git a/yarn-project/aztec-rpc/src/aztec_rpc_server/aztec_rpc_server.ts b/yarn-project/aztec-rpc/src/aztec_rpc_server/aztec_rpc_server.ts new file mode 100644 index 00000000000..dd704707bc7 --- /dev/null +++ b/yarn-project/aztec-rpc/src/aztec_rpc_server/aztec_rpc_server.ts @@ -0,0 +1,175 @@ +import { AcirSimulator } from '@aztec/acir-simulator'; +import { AztecNode } from '@aztec/aztec-node'; +import { KernelProver } from '@aztec/kernel-prover'; +import { Tx } from '@aztec/p2p'; +import { generateFunctionSelector } from '../abi_coder/index.js'; +import { AztecRPCClient } from '../aztec_rpc_client/index.js'; +import { + AztecAddress, + ContractDeploymentData, + EthAddress, + Fr, + generateContractAddress, + OldTreeRoots, + Signature, + TxContext, + TxRequest, +} from '../circuits.js'; +import { ContractDao, ContractDataSource } from '../contract_data_source/index.js'; +import { KeyStore } from '../key_store/index.js'; +import { ContractAbi } from '../noir.js'; +import { Synchroniser } from '../synchroniser/index.js'; +import { TxHash } from '../tx/index.js'; + +export class AztecRPCServer implements AztecRPCClient { + constructor( + private keyStore: KeyStore, + private synchroniser: Synchroniser, + private acirSimulator: AcirSimulator, + private kernelProver: KernelProver, + private node: AztecNode, + private db: ContractDataSource, + ) {} + + public async addAccount() { + const accountPublicKey = await this.keyStore.addAccount(); + await this.synchroniser.addAccount(accountPublicKey); + return accountPublicKey; + } + + public getAccounts() { + return Promise.resolve(this.synchroniser.getAccounts().map(a => a.publicKey)); + } + + public getCode(contract: AztecAddress, functionSelector?: Buffer) { + return this.db.getCode(contract, functionSelector || generateFunctionSelector('constructor', [])); + } + + public async createDeploymentTxRequest( + abi: ContractAbi, + args: Fr[], + portalContract: EthAddress, + contractAddressSalt: Fr, + from: AztecAddress, + ) { + const constructorAbi = abi.functions.find(f => f.name === 'constructor'); + if (!constructorAbi) { + throw new Error('Cannot find constructor in the ABI.'); + } + + const functionData = { + functionSelector: generateFunctionSelector(constructorAbi.name, constructorAbi.parameters), + isSecret: true, + isContructor: true, + }; + + const constructorVkHash = Fr.ZERO; + const functionTreeRoot = Fr.ZERO; + const contractDeploymentData = new ContractDeploymentData( + constructorVkHash, + functionTreeRoot, + contractAddressSalt, + portalContract, + ); + const txContext = new TxContext(false, false, false, contractDeploymentData); + + const contractAddress = generateContractAddress(from, contractAddressSalt, args); + await this.db.addContract(contractAddress, portalContract, abi, false); + + return new TxRequest( + from, + AztecAddress.ZERO, // to + functionData, + args, + txContext, + Fr.random(), // nonce + Fr.ZERO, // chainId + ); + } + + public async createTxRequest(functionSelector: Buffer, args: Fr[], to: AztecAddress, from: AztecAddress) { + const contract = await this.db.getContract(to); + if (!contract) { + throw new Error('Unknown contract.'); + } + + const functionDao = this.findFunction(contract, functionSelector); + + const functionData = { + functionSelector, + isSecret: functionDao.isSecret, + isContructor: false, + }; + + const txContext = new TxContext(false, false, false, ContractDeploymentData.EMPTY); + + return new TxRequest( + from, + to, + functionData, + args, + txContext, + Fr.random(), // nonce + Fr.ZERO, // chainId + ); + } + + public signTxRequest(txRequest: TxRequest) { + return this.keyStore.signTxRequest(txRequest); + } + + public async createTx(txRequest: TxRequest, signature: Signature) { + let contractAddress; + + if (txRequest.to.equals(AztecAddress.ZERO)) { + contractAddress = generateContractAddress( + txRequest.from, + txRequest.txContext.contractDeploymentData.contractAddressSalt, + txRequest.args, + ); + } else { + contractAddress = txRequest.to; + } + + const contract = await this.db.getContract(contractAddress); + + if (!contract) { + throw new Error('Unknown contract.'); + } + + const functionDao = this.findFunction(contract, txRequest.functionData.functionSelector); + + const oldRoots = new OldTreeRoots(Fr.ZERO, Fr.ZERO, Fr.ZERO, Fr.ZERO); // TODO - get old roots from the database/node + const executionResult = await this.acirSimulator.run( + txRequest, + Buffer.from(functionDao.bytecode, 'base64'), + contract.portalAddress, + oldRoots, + ); + const { publicInputs } = await this.kernelProver.prove( + txRequest as any, // TODO - remove `as any` + signature, + executionResult, + oldRoots as any, // TODO - remove `as any` + ); + // TODO I think the TX should include all the data from the publicInputs + proof + return new Tx(publicInputs); + } + + public async sendTx(tx: Tx) { + await this.node.sendTx(tx); + return new TxHash(tx.txId); + } + + public getTxReceipt(txHash: TxHash) { + return this.synchroniser.getTxReceipt(txHash); + } + + private findFunction(contract: ContractDao, functionSelector: Buffer) { + const functionDao = contract.functions.find(f => f.selector.equals(functionSelector)); + if (!functionDao) { + throw new Error('Unknown function.'); + } + return functionDao; + } +} diff --git a/yarn-project/aztec-rpc/src/aztec_rpc_server/create_aztec_rpc_server.ts b/yarn-project/aztec-rpc/src/aztec_rpc_server/create_aztec_rpc_server.ts new file mode 100644 index 00000000000..06c0ea90008 --- /dev/null +++ b/yarn-project/aztec-rpc/src/aztec_rpc_server/create_aztec_rpc_server.ts @@ -0,0 +1,32 @@ +import { AcirSimulator } from '@aztec/acir-simulator'; +import { AztecNode } from '@aztec/aztec-node'; +import { KernelProver } from '@aztec/kernel-prover'; +import { MemoryDB } from '../database/index.js'; +import { KeyStore, TestKeyStore } from '../key_store/index.js'; +import { Synchroniser } from '../synchroniser/index.js'; +import { AztecRPCServer } from './aztec_rpc_server.js'; + +export async function createAztecRPCServer( + aztecNode: AztecNode, + { + keyStore, + db, + synchroniser, + acirSimulator, + kernelProver, + }: { + keyStore?: KeyStore; + db?: MemoryDB; + synchroniser?: Synchroniser; + acirSimulator?: AcirSimulator; + kernelProver?: KernelProver; + } = {}, +) { + keyStore = keyStore || new TestKeyStore(); + db = db || new MemoryDB(); + synchroniser = synchroniser || new Synchroniser(aztecNode, db); + acirSimulator = acirSimulator || new AcirSimulator(); + kernelProver = kernelProver || new KernelProver(); + + return await Promise.resolve(new AztecRPCServer(keyStore, synchroniser, acirSimulator, kernelProver, aztecNode, db)); +} diff --git a/yarn-project/aztec-rpc/src/aztec_rpc_server/index.ts b/yarn-project/aztec-rpc/src/aztec_rpc_server/index.ts new file mode 100644 index 00000000000..3af43b1a499 --- /dev/null +++ b/yarn-project/aztec-rpc/src/aztec_rpc_server/index.ts @@ -0,0 +1,2 @@ +export * from './aztec_rpc_server.js'; +export * from './create_aztec_rpc_server.js'; diff --git a/yarn-project/aztec-rpc/src/circuits.ts b/yarn-project/aztec-rpc/src/circuits.ts new file mode 100644 index 00000000000..7360897095f --- /dev/null +++ b/yarn-project/aztec-rpc/src/circuits.ts @@ -0,0 +1,167 @@ +import { randomBytes } from './foundation.js'; + +export class Fr { + public static ZERO = new Fr(Buffer.alloc(32)); + + public static random() { + return new Fr(randomBytes(32)); + } + + constructor(public readonly buffer: Buffer) {} +} + +export class EthAddress { + public static ZERO = new EthAddress(Buffer.alloc(20)); + + public static random() { + return new EthAddress(randomBytes(20)); + } + + public static fromString(address: string) { + return new EthAddress(Buffer.from(address.replace(/^0x/i, ''), 'hex')); + } + + constructor(public readonly buffer: Buffer) {} +} + +export class AztecAddress { + public static SIZE = 64; + + public static ZERO = new AztecAddress(Buffer.alloc(AztecAddress.SIZE)); + + public static random() { + return new AztecAddress(randomBytes(AztecAddress.SIZE)); + } + + constructor(public readonly buffer: Buffer) {} + + public equals(rhs: AztecAddress) { + return this.buffer.equals(rhs.buffer); + } +} + +export class Signature { + public static SIZE = 64; + + public static random() { + return new EthAddress(randomBytes(Signature.SIZE)); + } + + constructor(public readonly buffer: Buffer) {} +} + +export interface FunctionData { + functionSelector: Buffer; + isSecret: boolean; + isContructor: boolean; +} + +/** + * Contract deployment data in a TxContext + * cpp/src/aztec3/circuits/abis/contract_deployment_data.hpp + */ +export class ContractDeploymentData { + public static EMPTY = new ContractDeploymentData(Fr.ZERO, Fr.ZERO, Fr.ZERO, Fr.ZERO); + + constructor( + public constructorVkHash: Fr, + public functionTreeRoot: Fr, + public contractAddressSalt: Fr, + public portalContractAddress: EthAddress, + ) {} +} + +export class TxContext { + constructor( + public readonly isFeePaymentTx: boolean, + public readonly isRebatePaymentTx: boolean, + public readonly isContractDeploymentTx: boolean, + public readonly contractDeploymentData: ContractDeploymentData, + ) {} +} + +export class TxRequest { + constructor( + public readonly from: AztecAddress, + public readonly to: AztecAddress, + public readonly functionData: FunctionData, + public readonly args: Fr[], + public readonly txContext: TxContext, + public readonly nonce: Fr, + public readonly chainId: Fr, + ) {} + + toBuffer() { + return Buffer.alloc(0); + } +} + +export class PreviousKernelData {} + +export class PrivateCallData {} + +export class KernelPrivateInputs { + constructor( + public readonly txRequest: TxRequest, + public readonly signature: Signature, + public readonly previousKernelData: PreviousKernelData, + public readonly privateCallData: PrivateCallData, + ) {} +} + +export function generateContractAddress( + deployerAddress: AztecAddress, + salt: Fr, + args: Fr[], + // functionLeaves: Fr[], +) { + return AztecAddress.random(); +} + +export class OldTreeRoots { + constructor( + public privateDataTreeRoot: Fr, + public nullifierTreeRoot: Fr, + public contractTreeRoot: Fr, + public privateKernelVkTreeRoot: Fr, // future enhancement + ) {} +} + +export class ConstantData { + constructor(public oldTreeRoots: OldTreeRoots, public txContext: TxContext) {} +} + +export class AggregationObject {} + +export class NewContractData { + constructor( + public readonly contractAddress: AztecAddress, + public readonly portalContractAddress: EthAddress, + public readonly functionTreeRoot: Fr, + ) {} +} + +export class OptionallyRevealedData {} + +export class AccumulatedTxData { + constructor( + public aggregationObject: AggregationObject, // Contains the aggregated proof of all previous kernel iterations + + public privateCallCount: Fr, + + public newCommitments: Fr[], + public newNullifiers: Fr[], + + public privateCallStack: Fr[], + public publicCallStack: Fr[], + public l1MsgStack: Fr[], + + public newContracts: NewContractData[], + + public optionallyRevealedData: OptionallyRevealedData[], + ) {} +} + +export class PrivateKernelPublicInputs { + constructor(public end: AccumulatedTxData, public constants: ConstantData, public isPrivateKernel: true) {} +} diff --git a/yarn-project/aztec-rpc/src/contract_data_source/contract_dao.ts b/yarn-project/aztec-rpc/src/contract_data_source/contract_dao.ts new file mode 100644 index 00000000000..ae3f167c398 --- /dev/null +++ b/yarn-project/aztec-rpc/src/contract_data_source/contract_dao.ts @@ -0,0 +1,36 @@ +import { generateFunctionSelector } from '../abi_coder/index.js'; +import { AztecAddress, EthAddress } from '../circuits.js'; +import { ContractAbi, FunctionAbi } from '../noir.js'; + +export interface ContractFunctionDao extends FunctionAbi { + selector: Buffer; +} + +export interface ContractDao extends ContractAbi { + address: AztecAddress; + portalAddress: EthAddress; + functions: ContractFunctionDao[]; + deployed: boolean; +} + +export function functionAbiToFunctionDao(abi: FunctionAbi) { + const selector = generateFunctionSelector(abi.name, abi.parameters); + return { + ...abi, + selector, + }; +} + +export function contractAbiToContractDao( + address: AztecAddress, + portalAddress: EthAddress, + abi: ContractAbi, + deployed: boolean, +): ContractDao { + return { + address, + portalAddress, + functions: abi.functions.map(functionAbiToFunctionDao), + deployed, + }; +} diff --git a/yarn-project/aztec-rpc/src/contract_data_source/contract_data_source.ts b/yarn-project/aztec-rpc/src/contract_data_source/contract_data_source.ts new file mode 100644 index 00000000000..917884b8dd0 --- /dev/null +++ b/yarn-project/aztec-rpc/src/contract_data_source/contract_data_source.ts @@ -0,0 +1,10 @@ +import { AztecAddress, EthAddress } from '../circuits.js'; +import { ContractAbi } from '../noir.js'; +import { ContractDao } from './contract_dao.js'; + +export interface ContractDataSource { + addContract(address: AztecAddress, portalAddress: EthAddress, abi: ContractAbi, deployed?: boolean): Promise; + confirmContractsDeployed(addresses: AztecAddress[]): Promise; + getContract(address: AztecAddress): Promise; + getCode(contractAddress: AztecAddress, functionSelector: Buffer): Promise; +} diff --git a/yarn-project/aztec-rpc/src/contract_data_source/index.ts b/yarn-project/aztec-rpc/src/contract_data_source/index.ts new file mode 100644 index 00000000000..c1fad74451a --- /dev/null +++ b/yarn-project/aztec-rpc/src/contract_data_source/index.ts @@ -0,0 +1,3 @@ +export * from './contract_dao.js'; +export * from './contract_data_source.js'; +export * from './memory_contract_data_source.js'; diff --git a/yarn-project/aztec-rpc/src/contract_data_source/memory_contract_data_source.ts b/yarn-project/aztec-rpc/src/contract_data_source/memory_contract_data_source.ts new file mode 100644 index 00000000000..e342908b14b --- /dev/null +++ b/yarn-project/aztec-rpc/src/contract_data_source/memory_contract_data_source.ts @@ -0,0 +1,36 @@ +import { AztecAddress, EthAddress } from '../circuits.js'; +import { ContractAbi } from '../noir.js'; +import { contractAbiToContractDao, ContractDao } from './contract_dao.js'; +import { ContractDataSource } from './contract_data_source.js'; + +export class MemoryContractDataSource implements ContractDataSource { + private contracts: ContractDao[] = []; + + public addContract(address: AztecAddress, portalAddress: EthAddress, abi: ContractAbi, deployed = false) { + this.contracts.push(contractAbiToContractDao(address, portalAddress, abi, deployed)); + return Promise.resolve(); + } + + public confirmContractsDeployed(addresses: AztecAddress[]) { + const contractIndices: Map = new Map(); + this.contracts.forEach((c, i) => { + contractIndices.set(c.address.toString(), i); + }); + addresses.forEach(a => { + const index = contractIndices.get(a.toString()); + if (index !== undefined) { + this.contracts[index] = { ...this.contracts[index], deployed: true }; + } + }); + return Promise.resolve(); + } + + public getContract(address: AztecAddress) { + return Promise.resolve(this.contracts.find(c => c.address.equals(address))); + } + + public async getCode(contractAddress: AztecAddress, functionSelector: Buffer) { + const contract = await this.getContract(contractAddress); + return contract?.functions.find(f => f.selector.equals(functionSelector))?.bytecode; + } +} diff --git a/yarn-project/aztec-rpc/src/database/database.ts b/yarn-project/aztec-rpc/src/database/database.ts new file mode 100644 index 00000000000..3e74a51a55f --- /dev/null +++ b/yarn-project/aztec-rpc/src/database/database.ts @@ -0,0 +1,7 @@ +import { ContractDataSource } from '../contract_data_source/index.js'; +import { TxHash } from '../tx/index.js'; +import { TxDao } from './tx_dao.js'; + +export interface Database extends ContractDataSource { + getTx(txHash: TxHash): Promise; +} diff --git a/yarn-project/aztec-rpc/src/database/index.ts b/yarn-project/aztec-rpc/src/database/index.ts new file mode 100644 index 00000000000..695723d1a2e --- /dev/null +++ b/yarn-project/aztec-rpc/src/database/index.ts @@ -0,0 +1,3 @@ +export * from './database.js'; +export * from './memory_db.js'; +export * from './tx_dao.js'; diff --git a/yarn-project/aztec-rpc/src/database/memory_db.ts b/yarn-project/aztec-rpc/src/database/memory_db.ts new file mode 100644 index 00000000000..cc2215964d0 --- /dev/null +++ b/yarn-project/aztec-rpc/src/database/memory_db.ts @@ -0,0 +1,12 @@ +import { MemoryContractDataSource } from '../contract_data_source/index.js'; +import { TxHash } from '../tx/index.js'; +import { Database } from './database.js'; +import { TxDao } from './tx_dao.js'; + +export class MemoryDB extends MemoryContractDataSource implements Database { + private txs: TxDao[] = []; + + public getTx(txHash: TxHash) { + return Promise.resolve(this.txs.find(tx => tx.txHash.equals(txHash))); + } +} diff --git a/yarn-project/aztec-rpc/src/database/tx_dao.ts b/yarn-project/aztec-rpc/src/database/tx_dao.ts new file mode 100644 index 00000000000..30d0b77b562 --- /dev/null +++ b/yarn-project/aztec-rpc/src/database/tx_dao.ts @@ -0,0 +1,14 @@ +import { AztecAddress } from '../circuits.js'; +import { TxHash } from '../tx/index.js'; + +export class TxDao { + constructor( + public readonly txHash: TxHash, + public readonly blockHash: Buffer, + public readonly blockNumber: number, + public readonly from: AztecAddress, + public readonly to: AztecAddress | undefined, + public readonly contractAddress: AztecAddress | undefined, + public readonly error: string, + ) {} +} diff --git a/yarn-project/aztec-rpc/src/foundation.ts b/yarn-project/aztec-rpc/src/foundation.ts new file mode 100644 index 00000000000..aa664f0d46f --- /dev/null +++ b/yarn-project/aztec-rpc/src/foundation.ts @@ -0,0 +1,12 @@ +import nodeCrypto from 'crypto'; +import { Keccak } from 'sha3'; + +export const randomBytes = (len: number) => { + return nodeCrypto.randomBytes(len) as Buffer; +}; + +export function keccak256(input: Buffer | string) { + const inputBuf = typeof input === 'string' ? Buffer.from(input) : input; + const hash = new Keccak(256); + return hash.update(inputBuf).digest(); +} diff --git a/yarn-project/aztec-rpc/src/index.ts b/yarn-project/aztec-rpc/src/index.ts new file mode 100644 index 00000000000..74f07348677 --- /dev/null +++ b/yarn-project/aztec-rpc/src/index.ts @@ -0,0 +1,9 @@ +export * from './abi_coder/index.js'; +export * from './aztec_rpc_client/index.js'; +export * from './aztec_rpc_server/index.js'; +export * from './tx/index.js'; + +export { Tx } from '@aztec/p2p'; +// TODO - only export necessary stuffs +export * from './circuits.js'; +export * from './noir.js'; diff --git a/yarn-project/aztec-rpc/src/key_store/index.ts b/yarn-project/aztec-rpc/src/key_store/index.ts new file mode 100644 index 00000000000..6cf083f0a03 --- /dev/null +++ b/yarn-project/aztec-rpc/src/key_store/index.ts @@ -0,0 +1,3 @@ +// TODO - move to yarn-project/key-store +export * from './key_store.js'; +export * from './test_key_store.js'; diff --git a/yarn-project/aztec-rpc/src/key_store/key_pair.ts b/yarn-project/aztec-rpc/src/key_store/key_pair.ts new file mode 100644 index 00000000000..c0c7c9077a3 --- /dev/null +++ b/yarn-project/aztec-rpc/src/key_store/key_pair.ts @@ -0,0 +1,34 @@ +import { AztecAddress, Signature } from '../circuits.js'; +import { randomBytes } from '../foundation.js'; + +export interface KeyPair { + getPublicKey(): AztecAddress; + getPrivateKey(): Promise; + signMessage(message: Buffer): Promise; +} + +export class ConstantKeyPair implements KeyPair { + public static random() { + const privateKey = randomBytes(32); + const publicKey = AztecAddress.random(); + return new ConstantKeyPair(publicKey, privateKey); + } + + constructor(private publicKey: AztecAddress, private privateKey: Buffer) {} + + public getPublicKey() { + return this.publicKey; + } + + public getPrivateKey() { + return Promise.resolve(this.privateKey); + } + + public signMessage(message: Buffer) { + if (!message.length) { + throw new Error('Cannot sign over empty message.'); + } + + return Promise.resolve(Signature.random()); + } +} diff --git a/yarn-project/aztec-rpc/src/key_store/key_store.ts b/yarn-project/aztec-rpc/src/key_store/key_store.ts new file mode 100644 index 00000000000..e9fd0a68431 --- /dev/null +++ b/yarn-project/aztec-rpc/src/key_store/key_store.ts @@ -0,0 +1,8 @@ +import { AztecAddress, Signature, TxRequest } from '../circuits.js'; + +export interface KeyStore { + addAccount(): Promise; + getAccounts(): Promise; + getSigningPublicKeys(): Promise; + signTxRequest(txRequest: TxRequest): Promise; +} diff --git a/yarn-project/aztec-rpc/src/key_store/test_key_store.ts b/yarn-project/aztec-rpc/src/key_store/test_key_store.ts new file mode 100644 index 00000000000..a95423a7013 --- /dev/null +++ b/yarn-project/aztec-rpc/src/key_store/test_key_store.ts @@ -0,0 +1,34 @@ +import { TxRequest } from '../circuits.js'; +import { ConstantKeyPair, KeyPair } from './key_pair.js'; +import { KeyStore } from './key_store.js'; + +export class TestKeyStore implements KeyStore { + private accounts: KeyPair[] = []; + + constructor() { + this.accounts.push(ConstantKeyPair.random()); + } + + public addAccount() { + const keyPair = ConstantKeyPair.random(); + this.accounts.push(keyPair); + return Promise.resolve(keyPair.getPublicKey()); + } + + getAccounts() { + return Promise.resolve(this.accounts.map(a => a.getPublicKey())); + } + + getSigningPublicKeys() { + return this.getAccounts(); + } + + signTxRequest(txRequest: TxRequest) { + const account = this.accounts.find(a => a.getPublicKey().equals(txRequest.from)); + if (!account) { + throw new Error('Unknown account.'); + } + + return account.signMessage(txRequest.toBuffer()); + } +} diff --git a/yarn-project/aztec-rpc/src/noir.ts b/yarn-project/aztec-rpc/src/noir.ts new file mode 100644 index 00000000000..bb91ea35b56 --- /dev/null +++ b/yarn-project/aztec-rpc/src/noir.ts @@ -0,0 +1,123 @@ +/** + * A named type. + */ +export interface ABIVariable { + /** + * The name of the variable. + */ + name: string; + /** + * The type of the variable. + */ + type: ABIType; +} + +/** + * A function parameter. + */ +export interface ABIParameter extends ABIVariable { + /** + * Whether the parameter is unpacked. + */ + unpacked: boolean; +} + +/** + * A basic type. + */ +export interface BasicType { + /** + * The kind of the type. + */ + kind: T; +} + +/** + * A variable type. + */ +export type ABIType = BasicType<'field'> | BasicType<'boolean'> | IntegerType | ArrayType | StringType | StructType; + +/** + * An integer type. + */ +export interface IntegerType extends BasicType<'integer'> { + /** + * The sign of the integer. + */ + sign: string; + /** + * The width of the integer in bits. + */ + width: number; +} + +/** + * An array type. + */ +export interface ArrayType extends BasicType<'array'> { + /** + * The length of the array. + */ + length: number; + /** + * The type of the array elements. + */ + type: ABIType; +} + +/** + * A string type. + */ +export interface StringType extends BasicType<'string'> { + /** + * The length of the string. + */ + length: number; +} + +/** + * A struct type. + */ +export interface StructType extends BasicType<'struct'> { + /** + * The fields of the struct. + */ + fields: ABIVariable[]; +} + +/** + * The ABI entry of a function. + */ +export interface FunctionAbi { + /** + * The name of the function. + */ + name: string; + /** + * Whether the function is secret. + */ + isSecret: boolean; + /** + * Function parameters. + */ + parameters: ABIParameter[]; + /** + * The types of the return values. + */ + returnTypes: ABIType[]; + /** + * The ACIR bytecode of the function. + */ + bytecode: string; + /** + * The verification key of the function. + */ + verificationKey: string; +} + +export interface ContractAbi { + /** + * The functions of the contract. + */ + functions: FunctionAbi[]; +} diff --git a/yarn-project/aztec-rpc/src/synchroniser/index.ts b/yarn-project/aztec-rpc/src/synchroniser/index.ts new file mode 100644 index 00000000000..bf023056508 --- /dev/null +++ b/yarn-project/aztec-rpc/src/synchroniser/index.ts @@ -0,0 +1 @@ +export * from './synchroniser.js'; diff --git a/yarn-project/aztec-rpc/src/synchroniser/synchroniser.ts b/yarn-project/aztec-rpc/src/synchroniser/synchroniser.ts new file mode 100644 index 00000000000..4976a8fa203 --- /dev/null +++ b/yarn-project/aztec-rpc/src/synchroniser/synchroniser.ts @@ -0,0 +1,96 @@ +import { AztecNode } from '@aztec/aztec-node'; +import { InterruptableSleep } from '@aztec/foundation'; +import { AccountState } from '../account_state/index.js'; +import { AztecAddress, EthAddress } from '../circuits.js'; +import { Database } from '../database/index.js'; +import { ContractAbi } from '../noir.js'; +import { TxHash } from '../tx/index.js'; + +export class Synchroniser { + private runningPromise?: Promise; + private accountStates: AccountState[] = []; + private interruptableSleep = new InterruptableSleep(); + private running = false; + + constructor(private node: AztecNode, private db: Database) {} + + public start(from = 0, take = 1, retryInterval = 10000) { + if (this.running) { + return; + } + + this.running = true; + + const run = async () => { + while (this.running) { + try { + const blocks = await this.node.getBlocks(from, take); + + if (!blocks.length) { + await this.interruptableSleep.sleep(retryInterval); + continue; + } + + const contractAddresses = blocks + .map(b => b.newContractData.map(d => d.aztecAddress)) + .flat() + .map(fr => new AztecAddress(fr.toBuffer())); + await this.db.confirmContractsDeployed(contractAddresses); + + from += blocks.length; + } catch (err) { + console.log(err); + await this.interruptableSleep.sleep(retryInterval); + } + } + }; + + this.runningPromise = run(); + } + + public async stop() { + this.running = false; + this.interruptableSleep.interrupt(); + await this.runningPromise; + } + + public async addAccount(account: AztecAddress) { + this.accountStates.push(new AccountState(account, this.db)); + await Promise.resolve(); + } + + public getAccount(account: AztecAddress) { + return this.accountStates.find(as => as.publicKey.equals(account)); + } + + public getAccounts() { + return [...this.accountStates]; + } + + public async addPendingContractAbi(contractAddress: AztecAddress, portalContract: EthAddress, abi: ContractAbi) { + await this.db.addContract(contractAddress, portalContract, abi, false); + } + + public async getTxReceipt(txHash: TxHash) { + const tx = await this.db.getTx(txHash); + if (!tx) { + return; + } + + const account = this.getAccount(tx.from); + if (!account) { + throw new Error('Unauthorised account.'); + } + + return { + txHash: tx.txHash, + blockHash: tx.blockHash, + blockNumber: tx.blockNumber, + from: tx.from, + to: tx.to, + contractAddress: tx.contractAddress, + error: tx.error, + status: !tx.error, + }; + } +} diff --git a/yarn-project/aztec-rpc/src/tx/index.ts b/yarn-project/aztec-rpc/src/tx/index.ts new file mode 100644 index 00000000000..342a3450227 --- /dev/null +++ b/yarn-project/aztec-rpc/src/tx/index.ts @@ -0,0 +1,2 @@ +export * from './tx_hash.js'; +export * from './tx_receipt.js'; diff --git a/yarn-project/aztec-rpc/src/tx/tx_hash.ts b/yarn-project/aztec-rpc/src/tx/tx_hash.ts new file mode 100644 index 00000000000..c6a819b82cb --- /dev/null +++ b/yarn-project/aztec-rpc/src/tx/tx_hash.ts @@ -0,0 +1,9 @@ +export class TxHash { + public static SIZE = 32; + + constructor(public readonly buffer: Buffer) {} + + public equals(rhs: TxHash) { + return this.buffer.equals(rhs.buffer); + } +} diff --git a/yarn-project/aztec-rpc/src/tx/tx_receipt.ts b/yarn-project/aztec-rpc/src/tx/tx_receipt.ts new file mode 100644 index 00000000000..fb0fe8fb1ce --- /dev/null +++ b/yarn-project/aztec-rpc/src/tx/tx_receipt.ts @@ -0,0 +1,14 @@ +import { AztecAddress } from '../circuits.js'; +import { TxHash } from './tx_hash.js'; + +export interface TxReceipt { + txHash: TxHash; + // txIndex: number; + blockHash: Buffer; + blockNumber: number; + from: AztecAddress; + to?: AztecAddress; + contractAddress?: AztecAddress; + status: boolean; + error: string; +} diff --git a/yarn-project/aztec-rpc/tsconfig.dest.json b/yarn-project/aztec-rpc/tsconfig.dest.json new file mode 100644 index 00000000000..95f0c3168cd --- /dev/null +++ b/yarn-project/aztec-rpc/tsconfig.dest.json @@ -0,0 +1,21 @@ +{ + "extends": ".", + "references": [ + { + "path": "../acir-simulator/tsconfig.dest.json" + }, + { + "path": "../aztec-node/tsconfig.dest.json" + }, + { + "path": "../foundation/tsconfig.dest.json" + }, + { + "path": "../kernel-prover/tsconfig.dest.json" + }, + { + "path": "../p2p/tsconfig.dest.json" + } + ], + "exclude": ["**/*.test.*", "**/fixtures/*"] +} diff --git a/yarn-project/aztec-rpc/tsconfig.json b/yarn-project/aztec-rpc/tsconfig.json new file mode 100644 index 00000000000..88bc72ae571 --- /dev/null +++ b/yarn-project/aztec-rpc/tsconfig.json @@ -0,0 +1,26 @@ +{ + "extends": "..", + "compilerOptions": { + "outDir": "dest", + "rootDir": "src", + "tsBuildInfoFile": ".tsbuildinfo" + }, + "references": [ + { + "path": "../acir-simulator/tsconfig.dest.json" + }, + { + "path": "../aztec-node/tsconfig.dest.json" + }, + { + "path": "../foundation/tsconfig.dest.json" + }, + { + "path": "../kernel-prover/tsconfig.dest.json" + }, + { + "path": "../p2p/tsconfig.dest.json" + } + ], + "include": ["src"] +} diff --git a/yarn-project/aztec.js/Dockerfile b/yarn-project/aztec.js/Dockerfile index d29bdc77510..614f06b1799 100644 --- a/yarn-project/aztec.js/Dockerfile +++ b/yarn-project/aztec.js/Dockerfile @@ -1,7 +1,6 @@ FROM 278380418400.dkr.ecr.eu-west-2.amazonaws.com/yarn-project-base AS builder - -COPY foundation foundation -COPY aztec.js aztec.js +COPY . . +RUN cd aztec-rpc && yarn build WORKDIR /usr/src/yarn-project/aztec.js RUN yarn build && yarn formatting && yarn test diff --git a/yarn-project/aztec.js/package.json b/yarn-project/aztec.js/package.json index 61a6e560442..53c836fa0e3 100644 --- a/yarn-project/aztec.js/package.json +++ b/yarn-project/aztec.js/package.json @@ -9,10 +9,10 @@ "tsconfig": "./tsconfig.dest.json" }, "scripts": { - "build": "yarn clean && yarn formatting && tsc -b tsconfig.dest.json", + "build": "yarn clean && tsc -b tsconfig.dest.json", "build:dev": "tsc -b tsconfig.dest.json --watch", "clean": "rm -rf ./dest .tsbuildinfo", - "formatting": "run -T prettier --check ./src && run -T eslint --max-warnings 0 ./src", + "formatting": "run -T prettier --check ./src && run -T eslint --max-warnings 10 ./src", "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --no-cache --passWithNoTests" }, "jest": { @@ -29,6 +29,7 @@ "rootDir": "./src" }, "dependencies": { + "@aztec/aztec-rpc": "workspace:^", "@aztec/foundation": "workspace:^", "tslib": "^2.4.0" }, @@ -38,6 +39,7 @@ "@types/jest": "^29.4.0", "@types/node": "^18.7.23", "jest": "^28.1.3", + "jest-mock-extended": "^3.0.3", "ts-jest": "^28.0.7", "ts-node": "^10.9.1", "typescript": "^4.9.5" diff --git a/yarn-project/aztec.js/src/abi_coder/hex_string.ts b/yarn-project/aztec.js/src/abi_coder/hex_string.ts new file mode 100644 index 00000000000..fd6eb9ebe38 --- /dev/null +++ b/yarn-project/aztec.js/src/abi_coder/hex_string.ts @@ -0,0 +1,3 @@ +export function hexToBuffer(h: string) { + return Buffer.from((h.length % 2 ? '0' : '') + h.replace(/^0x/, ''), 'hex'); +} diff --git a/yarn-project/aztec.js/src/abi_coder/index.ts b/yarn-project/aztec.js/src/abi_coder/index.ts new file mode 100644 index 00000000000..8a6dacd1fa5 --- /dev/null +++ b/yarn-project/aztec.js/src/abi_coder/index.ts @@ -0,0 +1,15 @@ +import { ABIParameter } from '@aztec/aztec-rpc'; + +export * from './hex_string.js'; + +function pack(parameter: ABIParameter, value: any) { + return Buffer.alloc(32); +} + +export function encodeParameters(parameters: ABIParameter[], args: any[]) { + if (parameters.length !== args.length) { + throw new Error(`Incorrect number of args. Expect ${parameters.length}. Got ${args.length}.`); + } + + return parameters.map((p, i) => pack(p, args[i])); +} diff --git a/yarn-project/aztec.js/src/contract/contract_function.ts b/yarn-project/aztec.js/src/contract/contract_function.ts new file mode 100644 index 00000000000..6305c3e3a73 --- /dev/null +++ b/yarn-project/aztec.js/src/contract/contract_function.ts @@ -0,0 +1,14 @@ +import { FunctionAbi, generateFunctionSelector } from '@aztec/aztec-rpc'; +import { encodeParameters } from '../abi_coder/index.js'; + +export class ContractFunction { + constructor(private abi: FunctionAbi) {} + + public encodeABI() { + return generateFunctionSelector(this.abi.name, this.abi.parameters); + } + + public encodeParameters(args: any[]) { + return encodeParameters(this.abi.parameters, args); + } +} diff --git a/yarn-project/aztec.js/src/contract/index.ts b/yarn-project/aztec.js/src/contract/index.ts new file mode 100644 index 00000000000..c434ae96257 --- /dev/null +++ b/yarn-project/aztec.js/src/contract/index.ts @@ -0,0 +1,3 @@ +export * from './contract_function.js'; +export * from './send_method.js'; +export * from './sent_tx.js'; diff --git a/yarn-project/aztec.js/src/contract/send_method.ts b/yarn-project/aztec.js/src/contract/send_method.ts new file mode 100644 index 00000000000..c3e094552de --- /dev/null +++ b/yarn-project/aztec.js/src/contract/send_method.ts @@ -0,0 +1,73 @@ +import { AztecAddress, AztecRPCClient, Fr, Signature, Tx, TxHash, TxRequest } from '@aztec/aztec-rpc'; +import { ContractFunction } from './contract_function.js'; +import { SentTx } from './sent_tx.js'; + +export interface SendMethodOptions { + from?: AztecAddress; + nonce?: Fr; +} + +/** + * This is the class that is returned when calling e.g. `contract.methods.myMethod(arg0, arg1)`. + * It contains available interactions one can call on a `send` method. + */ +export class SendMethod { + protected txRequest?: TxRequest; + private signature?: Signature; + private tx?: Tx; + + constructor( + protected arc: AztecRPCClient, + protected contractAddress: AztecAddress, + protected entry: ContractFunction, + protected args: any[], + protected defaultOptions: SendMethodOptions = {}, + ) {} + + public async request(options: SendMethodOptions = {}) { + const { from } = { ...this.defaultOptions, ...options }; + this.txRequest = await this.arc.createTxRequest( + this.entry.encodeABI(), + this.entry.encodeParameters(this.args).map(p => new Fr(p)), + this.contractAddress, + from || AztecAddress.ZERO, + ); + return this.txRequest; + } + + public async sign(options: SendMethodOptions = {}) { + if (!this.txRequest) { + await this.request(options); + } + + this.signature = await this.arc.signTxRequest(this.txRequest!); + return this.signature; + } + + public async create(options: SendMethodOptions = {}) { + if (!this.signature) { + await this.sign(options); + } + + this.tx = await this.arc.createTx(this.txRequest!, this.signature!); + return this.tx; + } + + public send(options: SendMethodOptions = {}) { + let promise: Promise; + if (this.tx) { + promise = this.arc.sendTx(this.tx); + } else { + promise = (async () => { + await this.create(options); + return this.arc.sendTx(this.tx!); + })(); + } + + return new SentTx(this.arc, promise); + } + + public encodeABI() { + return this.entry.encodeABI(); + } +} diff --git a/yarn-project/aztec.js/src/contract/sent_tx.ts b/yarn-project/aztec.js/src/contract/sent_tx.ts new file mode 100644 index 00000000000..ad1dbce0bea --- /dev/null +++ b/yarn-project/aztec.js/src/contract/sent_tx.ts @@ -0,0 +1,22 @@ +import { AztecRPCClient, TxHash, TxReceipt } from '@aztec/aztec-rpc'; +import { retryUntil } from '../foundation.js'; + +export class SentTx { + private receipt?: TxReceipt; + + constructor(private arc: AztecRPCClient, private txHashPromise: Promise) {} + + public async getTxHash() { + return await this.txHashPromise; + } + + public async getReceipt(timeout = 0, interval = 1) { + if (this.receipt) { + return this.receipt; + } + + const txHash = await this.getTxHash(); + this.receipt = await retryUntil(() => this.arc.getTxReceipt(txHash), 'getReceipt', timeout, interval); + return this.receipt; + } +} diff --git a/yarn-project/aztec.js/src/contract_deployer/constructor_method.ts b/yarn-project/aztec.js/src/contract_deployer/constructor_method.ts new file mode 100644 index 00000000000..033c148c67c --- /dev/null +++ b/yarn-project/aztec.js/src/contract_deployer/constructor_method.ts @@ -0,0 +1,50 @@ +import { AztecAddress, AztecRPCClient, ContractAbi, EthAddress, Fr } from '@aztec/aztec-rpc'; +import { ContractFunction, SendMethod, SendMethodOptions } from '../contract/index.js'; + +export interface ConstructorOptions extends SendMethodOptions { + portalContract?: EthAddress; + contractAddressSalt?: Fr; +} + +/** + * Extends the SendMethodInteraction to create TxRequest for constructors (deployments). + */ +export class ConstructorMethod extends SendMethod { + constructor( + arc: AztecRPCClient, + private abi: ContractAbi, + args: any[] = [], + defaultOptions: ConstructorOptions = {}, + ) { + const constructorAbi = abi.functions.find(f => f.name === 'constructor'); + if (!constructorAbi) { + throw new Error('Cannot find constructor in the ABI.'); + } + + super(arc, AztecAddress.ZERO, new ContractFunction(constructorAbi), args, defaultOptions); + } + + public async request(options: ConstructorOptions = {}) { + const { portalContract, contractAddressSalt, from } = { ...this.defaultOptions, ...options }; + this.txRequest = await this.arc.createDeploymentTxRequest( + this.abi, + this.entry.encodeParameters(this.args).map(p => new Fr(p)), + portalContract || EthAddress.ZERO, + contractAddressSalt || Fr.random(), + from || AztecAddress.ZERO, + ); + return this.txRequest; + } + + public sign(options: ConstructorOptions = {}) { + return super.sign(options); + } + + public create(options: ConstructorOptions = {}) { + return super.create(options); + } + + public send(options: ConstructorOptions = {}) { + return super.send(options); + } +} diff --git a/yarn-project/aztec.js/src/contract_deployer/contract_deployer.test.ts b/yarn-project/aztec.js/src/contract_deployer/contract_deployer.test.ts new file mode 100644 index 00000000000..d744dd4fbe7 --- /dev/null +++ b/yarn-project/aztec.js/src/contract_deployer/contract_deployer.test.ts @@ -0,0 +1,114 @@ +import { mock } from 'jest-mock-extended'; +import { + AztecAddress, + AztecRPCClient, + ContractAbi, + EthAddress, + Fr, + Signature, + Tx, + TxHash, + TxReceipt, + TxRequest, +} from '@aztec/aztec-rpc'; +import { ContractDeployer } from './contract_deployer.js'; + +describe('Contract Deployer', () => { + let arc: ReturnType>; + + const abi: ContractAbi = { + functions: [ + { + name: 'constructor', + isSecret: true, + parameters: [], + returnTypes: [], + bytecode: '0x01234567', + verificationKey: '0x98765432', + }, + ], + }; + + const portalContract = EthAddress.random(); + const contractAddressSalt = Fr.random(); + const account = AztecAddress.random(); + + const mockTxRequest = { type: 'TxRequest' } as any as TxRequest; + const mockSignature = { type: 'Signature' } as any as Signature; + const mockTx = { type: 'Tx' } as any as Tx; + const mockTxHash = { type: 'TxHash' } as any as TxHash; + const mockTxReceipt = { type: 'TxReceipt' } as any as TxReceipt; + + beforeEach(() => { + arc = mock(); + arc.createDeploymentTxRequest.mockResolvedValue(mockTxRequest); + arc.createTxRequest.mockResolvedValue(mockTxRequest); + arc.signTxRequest.mockResolvedValue(mockSignature); + arc.createTx.mockResolvedValue(mockTx); + arc.sendTx.mockResolvedValue(mockTxHash); + arc.getTxReceipt.mockResolvedValue(mockTxReceipt); + }); + + it('should request, sign, craete and send a contract deployment tx', async () => { + const deployer = new ContractDeployer(abi, arc); + const sentTx = deployer.deploy().send({ + portalContract, + contractAddressSalt, + from: account, + }); + const txHash = await sentTx.getTxHash(); + const receipt = await sentTx.getReceipt(); + + expect(txHash).toBe(mockTxHash); + expect(receipt).toBe(mockTxReceipt); + expect(arc.createDeploymentTxRequest).toHaveBeenCalledTimes(1); + expect(arc.createDeploymentTxRequest).toHaveBeenCalledWith(abi, [], portalContract, contractAddressSalt, account); + expect(arc.createTxRequest).toHaveBeenCalledTimes(0); + expect(arc.signTxRequest).toHaveBeenCalledTimes(1); + expect(arc.signTxRequest).toHaveBeenCalledWith(mockTxRequest); + expect(arc.createTx).toHaveBeenCalledTimes(1); + expect(arc.createTx).toHaveBeenCalledWith(mockTxRequest, mockSignature); + expect(arc.sendTx).toHaveBeenCalledTimes(1); + expect(arc.sendTx).toHaveBeenCalledWith(mockTx); + }); + + it('should be able to deploy a contract step by step', async () => { + const deployer = new ContractDeployer(abi, arc); + const deployment = deployer.deploy(); + const txRequest = await deployment.request({ + portalContract, + contractAddressSalt, + from: account, + }); + const signature = await deployment.sign(); + const tx = await deployment.create(); + const receipt = await deployment.send().getReceipt(); + + expect(txRequest).toBe(mockTxRequest); + expect(signature).toBe(mockSignature); + expect(tx).toBe(mockTx); + expect(receipt).toBe(mockTxReceipt); + expect(arc.createDeploymentTxRequest).toHaveBeenCalledTimes(1); + expect(arc.createDeploymentTxRequest).toHaveBeenCalledWith(abi, [], portalContract, contractAddressSalt, account); + expect(arc.createTxRequest).toHaveBeenCalledTimes(0); + expect(arc.signTxRequest).toHaveBeenCalledTimes(1); + expect(arc.createTx).toHaveBeenCalledTimes(1); + expect(arc.sendTx).toHaveBeenCalledTimes(1); + }); + + it('should assign zeros or generate random values for undefined options', async () => { + const deployer = new ContractDeployer(abi, arc); + const deployment = deployer.deploy(); + await deployment.request(); + expect(arc.createDeploymentTxRequest).toHaveBeenCalledWith( + abi, + [], + EthAddress.ZERO, // portalContract + expect.anything(), // contractAddressSalt + AztecAddress.ZERO, // account + ); + const defaultContractAddressSalt = arc.createDeploymentTxRequest.mock.calls[0][3]; + expect(defaultContractAddressSalt).not.toEqual(contractAddressSalt); + expect(defaultContractAddressSalt).not.toEqual(Fr.ZERO); + }); +}); diff --git a/yarn-project/aztec.js/src/contract_deployer/contract_deployer.ts b/yarn-project/aztec.js/src/contract_deployer/contract_deployer.ts new file mode 100644 index 00000000000..f4be732d3c0 --- /dev/null +++ b/yarn-project/aztec.js/src/contract_deployer/contract_deployer.ts @@ -0,0 +1,13 @@ +import { AztecRPCClient, ContractAbi } from '@aztec/aztec-rpc'; +import { ConstructorMethod, ConstructorOptions } from './constructor_method.js'; + +/** + * A class for deploying contract. + */ +export class ContractDeployer { + constructor(private abi: ContractAbi, private arc: AztecRPCClient, private defaultOptions: ConstructorOptions = {}) {} + + public deploy(...args: any[]) { + return new ConstructorMethod(this.arc, this.abi, args, this.defaultOptions); + } +} diff --git a/yarn-project/aztec.js/src/contract_deployer/index.ts b/yarn-project/aztec.js/src/contract_deployer/index.ts new file mode 100644 index 00000000000..587eeb108ce --- /dev/null +++ b/yarn-project/aztec.js/src/contract_deployer/index.ts @@ -0,0 +1 @@ +export * from './contract_deployer.js'; diff --git a/yarn-project/aztec.js/src/foundation.ts b/yarn-project/aztec.js/src/foundation.ts new file mode 100644 index 00000000000..b9b48b88eeb --- /dev/null +++ b/yarn-project/aztec.js/src/foundation.ts @@ -0,0 +1,63 @@ +export function sleep(ms: number) { + return new Promise(resolve => setTimeout(resolve, ms)); +} + +export class Timer { + private start: number; + + constructor() { + this.start = new Date().getTime(); + } + + public ms() { + return new Date().getTime() - this.start; + } + + public s() { + return (new Date().getTime() - this.start) / 1000; + } +} + +export function* backoffGenerator() { + const v = [1, 1, 1, 2, 4, 8, 16, 32, 64]; + let i = 0; + while (true) { + yield v[Math.min(i++, v.length - 1)]; + } +} + +export async function retry(fn: () => Promise, name = 'Operation', backoff = backoffGenerator()) { + while (true) { + try { + return await fn(); + } catch (err: any) { + const s = backoff.next().value; + if (s === undefined) { + throw err; + } + console.log(`${name} failed. Will retry in ${s}s...`); + console.log(err); + await sleep(s * 1000); + continue; + } + } +} + +// Call `fn` repeatedly until it returns true or timeout. +// Both `interval` and `timeout` are seconds. +// Will never timeout if the value is 0. +export async function retryUntil(fn: () => Promise, name = '', timeout = 0, interval = 1) { + const timer = new Timer(); + while (true) { + const result = await fn(); + if (result) { + return result; + } + + await sleep(interval * 1000); + + if (timeout && timer.s() > timeout) { + throw new Error(name ? `Timeout awaiting ${name}` : 'Timeout'); + } + } +} diff --git a/yarn-project/aztec.js/src/index.test.ts b/yarn-project/aztec.js/src/index.test.ts deleted file mode 100644 index ce33cfbe10c..00000000000 --- a/yarn-project/aztec.js/src/index.test.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { Aztec } from './index.js'; - -describe('Aztec', () => { - it('Initialise Aztec', () => { - expect(() => new Aztec()).not.toThrow(); - }); -}); diff --git a/yarn-project/aztec.js/src/index.ts b/yarn-project/aztec.js/src/index.ts index dec50f231ab..64f67ec0e27 100644 --- a/yarn-project/aztec.js/src/index.ts +++ b/yarn-project/aztec.js/src/index.ts @@ -1,4 +1,5 @@ -/** - * A placeholder for Aztec js. - */ -export class Aztec {} +export * from './contract/index.js'; +export * from './contract_deployer/index.js'; + +// TODO - only export necessary stuffs +export * from '@aztec/aztec-rpc'; diff --git a/yarn-project/aztec.js/tsconfig.dest.json b/yarn-project/aztec.js/tsconfig.dest.json index 965aaa1c433..427378e2cb4 100644 --- a/yarn-project/aztec.js/tsconfig.dest.json +++ b/yarn-project/aztec.js/tsconfig.dest.json @@ -1,4 +1,12 @@ { "extends": ".", + "references": [ + { + "path": "../aztec-rpc/tsconfig.dest.json" + }, + { + "path": "../foundation/tsconfig.dest.json" + } + ], "exclude": ["**/*.test.*", "**/fixtures/*"] } diff --git a/yarn-project/aztec.js/tsconfig.json b/yarn-project/aztec.js/tsconfig.json index f67ddec9fd6..8df00c9048d 100644 --- a/yarn-project/aztec.js/tsconfig.json +++ b/yarn-project/aztec.js/tsconfig.json @@ -5,5 +5,13 @@ "rootDir": "src", "tsBuildInfoFile": ".tsbuildinfo" }, + "references": [ + { + "path": "../aztec-rpc/tsconfig.dest.json" + }, + { + "path": "../foundation/tsconfig.dest.json" + } + ], "include": ["src"] } diff --git a/yarn-project/end-to-end/Dockerfile b/yarn-project/end-to-end/Dockerfile index 08cc86cf78e..c2203a13d02 100644 --- a/yarn-project/end-to-end/Dockerfile +++ b/yarn-project/end-to-end/Dockerfile @@ -1,12 +1,8 @@ FROM 278380418400.dkr.ecr.eu-west-2.amazonaws.com/yarn-project-base AS builder - -COPY foundation foundation -COPY aztec.js aztec.js +COPY . . RUN cd aztec.js && yarn build - -COPY end-to-end end-to-end WORKDIR /usr/src/yarn-project/end-to-end -RUN yarn build && yarn formatting +RUN yarn formatting # Prune dev dependencies. See comment in base image. RUN yarn cache clean diff --git a/yarn-project/end-to-end/package.json b/yarn-project/end-to-end/package.json index 4fb7355f20d..7c24091a7b6 100644 --- a/yarn-project/end-to-end/package.json +++ b/yarn-project/end-to-end/package.json @@ -4,7 +4,7 @@ "type": "module", "exports": "./dest/index.js", "scripts": { - "build": "yarn clean && yarn formatting && tsc -b tsconfig.json", + "build": "yarn clean && tsc -b tsconfig.json", "clean": "rm -rf ./dest .tsbuildinfo", "formatting": "run -T prettier --check ./src && run -T eslint --max-warnings 0 ./src", "test": "./scripts/start_e2e.sh" @@ -23,8 +23,10 @@ "rootDir": "./src" }, "dependencies": { + "@aztec/aztec-node": "workspace:^", "@aztec/aztec.js": "workspace:^", "@aztec/foundation": "workspace:^", + "@aztec/noir-contracts": "workspace:^", "@types/jest": "^29.4.0", "jest": "^28.1.3", "ts-jest": "^28.0.7", diff --git a/yarn-project/end-to-end/src/create_aztec_node.ts b/yarn-project/end-to-end/src/create_aztec_node.ts new file mode 100644 index 00000000000..4444d3a667a --- /dev/null +++ b/yarn-project/end-to-end/src/create_aztec_node.ts @@ -0,0 +1,20 @@ +import { AztecNode } from '@aztec/aztec-node'; +import { EthAddress } from '@aztec/aztec.js'; + +const { + ETHEREUM_HOST = 'http://localhost:8545', + ROLLUP_ADDRESS = '0x5FbDB2315678afecb367f032d93F642f64180aa3', + YEETER_ADDRESS = '0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512', +} = process.env; + +export async function createAztecNode() { + return await AztecNode.createAndSync({ + rpcUrl: ETHEREUM_HOST, + rollupContract: EthAddress.fromString(ROLLUP_ADDRESS) as any, + yeeterContract: EthAddress.fromString(YEETER_ADDRESS) as any, + retryIntervalMs: 10000, + publisherPrivateKey: Buffer.alloc(64), + requiredConfirmations: 1, + transactionPollingInterval: 1000, + }); +} diff --git a/yarn-project/end-to-end/src/create_aztec_rpc_client.ts b/yarn-project/end-to-end/src/create_aztec_rpc_client.ts new file mode 100644 index 00000000000..2d3936b2e60 --- /dev/null +++ b/yarn-project/end-to-end/src/create_aztec_rpc_client.ts @@ -0,0 +1,14 @@ +import { AztecNode } from '@aztec/aztec-node'; +import { createAztecRPCServer } from '@aztec/aztec.js'; +import { createAztecNode } from './create_aztec_node.js'; + +export async function createTestAztecRPCClient(numberOfAccounts = 1, aztecNode?: AztecNode) { + const node = aztecNode || (await createAztecNode()); + const arc = await createAztecRPCServer(node); + + for (let i = 0; i < numberOfAccounts; ++i) { + await arc.addAccount(); + } + + return arc; +} diff --git a/yarn-project/end-to-end/src/e2e_deploy_contract.test.ts b/yarn-project/end-to-end/src/e2e_deploy_contract.test.ts index 1586d67858a..3571e82c26d 100644 --- a/yarn-project/end-to-end/src/e2e_deploy_contract.test.ts +++ b/yarn-project/end-to-end/src/e2e_deploy_contract.test.ts @@ -1,7 +1,5 @@ -import { Aztec } from '@aztec/aztec.js'; - describe('e2e_deploy_contract', () => { it('should deploy a contract', () => { - expect(() => new Aztec()).not.toThrow(); + // TODO }); }); diff --git a/yarn-project/wallet/.eslintrc.cjs b/yarn-project/kernel-prover/.eslintrc.cjs similarity index 100% rename from yarn-project/wallet/.eslintrc.cjs rename to yarn-project/kernel-prover/.eslintrc.cjs diff --git a/yarn-project/kernel-simulator/Dockerfile b/yarn-project/kernel-prover/Dockerfile similarity index 55% rename from yarn-project/kernel-simulator/Dockerfile rename to yarn-project/kernel-prover/Dockerfile index 60c31d5c269..0738898f443 100644 --- a/yarn-project/kernel-simulator/Dockerfile +++ b/yarn-project/kernel-prover/Dockerfile @@ -1,7 +1,7 @@ FROM 278380418400.dkr.ecr.eu-west-2.amazonaws.com/yarn-project-base AS builder -COPY kernel-simulator kernel-simulator -WORKDIR /usr/src/yarn-project/kernel-simulator +COPY kernel-prover kernel-prover +WORKDIR /usr/src/yarn-project/kernel-prover RUN yarn build && yarn formatting && yarn test # Prune dev dependencies. See comment in base image. @@ -9,6 +9,6 @@ RUN yarn cache clean RUN yarn workspaces focus --production > /dev/null FROM node:18-alpine -COPY --from=builder /usr/src/yarn-project/kernel-simulator /usr/src/yarn-project/kernel-simulator -WORKDIR /usr/src/yarn-project/kernel-simulator +COPY --from=builder /usr/src/yarn-project/kernel-prover /usr/src/yarn-project/kernel-prover +WORKDIR /usr/src/yarn-project/kernel-prover ENTRYPOINT ["yarn"] \ No newline at end of file diff --git a/yarn-project/kernel-simulator/README.md b/yarn-project/kernel-prover/README.md similarity index 100% rename from yarn-project/kernel-simulator/README.md rename to yarn-project/kernel-prover/README.md diff --git a/yarn-project/kernel-simulator/package.json b/yarn-project/kernel-prover/package.json similarity index 86% rename from yarn-project/kernel-simulator/package.json rename to yarn-project/kernel-prover/package.json index d102f897747..d5a11bba87e 100644 --- a/yarn-project/kernel-simulator/package.json +++ b/yarn-project/kernel-prover/package.json @@ -1,5 +1,5 @@ { - "name": "@aztec/kernel-simulator", + "name": "@aztec/kernel-prover", "version": "0.0.0", "type": "module", "exports": "./dest/index.js", @@ -9,7 +9,7 @@ "tsconfig": "./tsconfig.dest.json" }, "scripts": { - "build": "yarn clean && yarn formatting && tsc -b tsconfig.dest.json", + "build": "yarn clean && tsc -b tsconfig.dest.json", "build:dev": "tsc -b tsconfig.dest.json --watch", "clean": "rm -rf ./dest .tsbuildinfo", "formatting": "run -T prettier --check ./src && run -T eslint --max-warnings 0 ./src", @@ -29,6 +29,8 @@ "rootDir": "./src" }, "dependencies": { + "@aztec/acir-simulator": "workspace:^", + "@aztec/circuits.js": "workspace:^", "tslib": "^2.4.0" }, "devDependencies": { diff --git a/yarn-project/kernel-prover/src/circuits.ts b/yarn-project/kernel-prover/src/circuits.ts new file mode 100644 index 00000000000..5bbd42b113f --- /dev/null +++ b/yarn-project/kernel-prover/src/circuits.ts @@ -0,0 +1,26 @@ +// See aztec3/constants.hpp +// Copied here for prototyping purposes + +import { AztecAddress, Fr, FunctionData, TxContext } from '@aztec/circuits.js'; + +export class TxRequest { + constructor( + public readonly from: AztecAddress, + public readonly to: AztecAddress, + public readonly functionData: FunctionData, + public readonly args: Fr[], + public readonly txContext: TxContext, + public readonly nonce: Fr, + public readonly chainId: Fr, + ) {} + + toBuffer() { + return Buffer.alloc(0); + } +} + +export class Signature { + public static SIZE = 64; + + constructor(public readonly buffer: Buffer) {} +} diff --git a/yarn-project/kernel-prover/src/index.ts b/yarn-project/kernel-prover/src/index.ts new file mode 100644 index 00000000000..79318c291e6 --- /dev/null +++ b/yarn-project/kernel-prover/src/index.ts @@ -0,0 +1,53 @@ +import { ExecutionResult } from '@aztec/acir-simulator'; +import { + AccumulatedData, + AggregationObject, + ConstantData, + Fr, + NewContractData, + OldTreeRoots, + PrivateKernelPublicInputs, +} from '@aztec/circuits.js'; +import { Signature, TxRequest } from './circuits.js'; +export class KernelProver { + prove( + txRequest: TxRequest, + txSignature: Signature, + executionResult: ExecutionResult, + oldRoots: OldTreeRoots, + ): Promise<{ publicInputs: PrivateKernelPublicInputs; proof: Buffer }> { + // TODO: implement this + const newContracts = []; + if (txRequest.functionData.isConstructor) { + newContracts.push( + new NewContractData( + txRequest.to, + txRequest.txContext.contractDeploymentData.portalContractAddress, + txRequest.txContext.contractDeploymentData.functionTreeRoot, + ), + ); + } + const accumulatedTxData = new AccumulatedData( + AggregationObject.fromBuffer(Buffer.alloc(0)), // TODO - Fix this. + new Fr(Buffer.from([1])), + [], // newCommitments + [], // newNullifiers + [], // privateCallStack + [], // publicCallStack + [], // l1MsgStack + newContracts, + [], // optionallyRevealedData + ); + + const publicInputs = new PrivateKernelPublicInputs( + accumulatedTxData, + new ConstantData(oldRoots, txRequest.txContext), + true, + ); + + return Promise.resolve({ + publicInputs, + proof: Buffer.alloc(0), + }); + } +} diff --git a/yarn-project/kernel-prover/tsconfig.dest.json b/yarn-project/kernel-prover/tsconfig.dest.json new file mode 100644 index 00000000000..972422b99ee --- /dev/null +++ b/yarn-project/kernel-prover/tsconfig.dest.json @@ -0,0 +1,12 @@ +{ + "extends": ".", + "references": [ + { + "path": "../acir-simulator/tsconfig.dest.json" + }, + { + "path": "../circuits.js/tsconfig.dest.json" + } + ], + "exclude": ["**/*.test.*", "**/fixtures/*"] +} diff --git a/yarn-project/kernel-simulator/tsconfig.json b/yarn-project/kernel-prover/tsconfig.json similarity index 50% rename from yarn-project/kernel-simulator/tsconfig.json rename to yarn-project/kernel-prover/tsconfig.json index f67ddec9fd6..b3e4c475ad0 100644 --- a/yarn-project/kernel-simulator/tsconfig.json +++ b/yarn-project/kernel-prover/tsconfig.json @@ -5,5 +5,13 @@ "rootDir": "src", "tsBuildInfoFile": ".tsbuildinfo" }, + "references": [ + { + "path": "../acir-simulator/tsconfig.dest.json" + }, + { + "path": "../circuits.js/tsconfig.dest.json" + } + ], "include": ["src"] } diff --git a/yarn-project/kernel-simulator/src/index.ts b/yarn-project/kernel-simulator/src/index.ts deleted file mode 100644 index d63aa680f38..00000000000 --- a/yarn-project/kernel-simulator/src/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -/** - * A placeholder for the Kernel Simulator. - */ -export class KernelSimulator {} diff --git a/yarn-project/kernel-simulator/tsconfig.dest.json b/yarn-project/kernel-simulator/tsconfig.dest.json deleted file mode 100644 index 965aaa1c433..00000000000 --- a/yarn-project/kernel-simulator/tsconfig.dest.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "extends": ".", - "exclude": ["**/*.test.*", "**/fixtures/*"] -} diff --git a/yarn-project/key-store/package.json b/yarn-project/key-store/package.json index 472205b4916..490b1ec2cbd 100644 --- a/yarn-project/key-store/package.json +++ b/yarn-project/key-store/package.json @@ -9,7 +9,7 @@ "tsconfig": "./tsconfig.dest.json" }, "scripts": { - "build": "yarn clean && yarn formatting && tsc -b tsconfig.dest.json", + "build": "yarn clean && tsc -b tsconfig.dest.json", "build:dev": "tsc -b tsconfig.dest.json --watch", "clean": "rm -rf ./dest .tsbuildinfo", "formatting": "run -T prettier --check ./src && run -T eslint --max-warnings 0 ./src", diff --git a/yarn-project/l1-contracts/package.json b/yarn-project/l1-contracts/package.json index 3e125611119..b0899bc566e 100644 --- a/yarn-project/l1-contracts/package.json +++ b/yarn-project/l1-contracts/package.json @@ -12,7 +12,7 @@ "tsconfig": "./tsconfig.dest.json" }, "scripts": { - "build": "yarn clean && yarn formatting && tsc -b tsconfig.dest.json", + "build": "yarn clean && tsc -b tsconfig.dest.json", "build:dev": "tsc -b tsconfig.dest.json --watch", "generate": "contract_gen_def && bash scripts/update-viem-abis.sh && yarn formatting:fix", "clean": "rm -rf ./dest .tsbuildinfo", diff --git a/yarn-project/merkle-tree/package.json b/yarn-project/merkle-tree/package.json index 1e657e352eb..e7f50d91a51 100644 --- a/yarn-project/merkle-tree/package.json +++ b/yarn-project/merkle-tree/package.json @@ -4,7 +4,7 @@ "type": "module", "exports": "./dest/index.js", "scripts": { - "build": "yarn clean && yarn formatting && tsc -b tsconfig.dest.json", + "build": "yarn clean && tsc -b tsconfig.dest.json", "build:dev": "tsc -b tsconfig.dest.json --watch", "clean": "rm -rf ./dest .tsbuildinfo", "formatting": "run -T prettier --check ./src && run -T eslint --max-warnings 0 ./src", diff --git a/yarn-project/noir-contracts/package.json b/yarn-project/noir-contracts/package.json index c64c7be5535..09dc42d036d 100644 --- a/yarn-project/noir-contracts/package.json +++ b/yarn-project/noir-contracts/package.json @@ -12,7 +12,7 @@ "tsconfig": "./tsconfig.dest.json" }, "scripts": { - "build": "yarn clean && yarn formatting && tsc -b tsconfig.dest.json", + "build": "yarn clean && tsc -b tsconfig.dest.json", "build:dev": "tsc -p tsconfig.dest.json --watch", "clean": "rm -rf ./dest .tsbuildinfo", "formatting": "run -T prettier --check ./src && run -T eslint --max-warnings 0 ./src", diff --git a/yarn-project/p2p/package.json b/yarn-project/p2p/package.json index dba27766ad4..5e7a4bb2550 100644 --- a/yarn-project/p2p/package.json +++ b/yarn-project/p2p/package.json @@ -9,7 +9,7 @@ "tsconfig": "./tsconfig.dest.json" }, "scripts": { - "build": "yarn clean && yarn formatting && tsc -b tsconfig.dest.json", + "build": "yarn clean && tsc -b tsconfig.dest.json", "build:dev": "tsc -b tsconfig.dest.json --watch", "start": "node ./dest", "start:dev": "tsc-watch -p tsconfig.dest.json --onSuccess 'yarn start'", diff --git a/yarn-project/package.json b/yarn-project/package.json index 37ac5b93927..2a75807ed9a 100644 --- a/yarn-project/package.json +++ b/yarn-project/package.json @@ -11,6 +11,7 @@ "acir-simulator", "archiver", "aztec-cli", + "aztec-rpc", "aztec.js", "circuits.js", "docs", @@ -18,7 +19,7 @@ "ethereum.js", "ethereum.js/example", "foundation", - "kernel-simulator", + "kernel-prover", "key-store", "merkle-tree", "noir-contracts", @@ -27,7 +28,6 @@ "prover-client", "aztec-node", "sequencer-client", - "wallet", "world-state", ".yalc/*/*" ], diff --git a/yarn-project/prover-client/package.json b/yarn-project/prover-client/package.json index 709986a5594..511ab85227f 100644 --- a/yarn-project/prover-client/package.json +++ b/yarn-project/prover-client/package.json @@ -9,7 +9,7 @@ "tsconfig": "./tsconfig.dest.json" }, "scripts": { - "build": "yarn clean && yarn formatting && tsc -b tsconfig.dest.json", + "build": "yarn clean && tsc -b tsconfig.dest.json", "build:dev": "tsc -b tsconfig.dest.json --watch", "clean": "rm -rf ./dest .tsbuildinfo", "formatting": "run -T prettier --check ./src && run -T eslint --max-warnings 0 ./src", diff --git a/yarn-project/sequencer-client/package.json b/yarn-project/sequencer-client/package.json index 9b608a93e3b..e16ef1f30d6 100644 --- a/yarn-project/sequencer-client/package.json +++ b/yarn-project/sequencer-client/package.json @@ -9,7 +9,7 @@ "tsconfig": "./tsconfig.dest.json" }, "scripts": { - "build": "yarn clean && yarn formatting && tsc -b tsconfig.dest.json", + "build": "yarn clean && tsc -b tsconfig.dest.json", "build:dev": "tsc -b tsconfig.dest.json --watch", "clean": "rm -rf ./dest .tsbuildinfo", "formatting": "run -T prettier --check ./src && run -T eslint --max-warnings 0 ./src", diff --git a/yarn-project/typedoc.json b/yarn-project/typedoc.json index e332f8cf72d..475584d6a5d 100644 --- a/yarn-project/typedoc.json +++ b/yarn-project/typedoc.json @@ -5,16 +5,16 @@ "acir-simulator", "archiver", "aztec-cli", + "aztec-rpc", "aztec.js", "ethereum.js", - "kernel-simulator", + "kernel-prover", "key-store", "noir-contracts", "p2p", "prover-client", "aztec-node", "sequencer-client", - "wallet", "world-state", "merkle-tree" ] diff --git a/yarn-project/wallet/README.md b/yarn-project/wallet/README.md deleted file mode 100644 index 456644fc556..00000000000 --- a/yarn-project/wallet/README.md +++ /dev/null @@ -1 +0,0 @@ -# Wallet diff --git a/yarn-project/wallet/src/index.ts b/yarn-project/wallet/src/index.ts deleted file mode 100644 index 95d6e81d27f..00000000000 --- a/yarn-project/wallet/src/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -/** - * A placeholder for the Wallet. - */ -export class Wallet {} diff --git a/yarn-project/wallet/tsconfig.dest.json b/yarn-project/wallet/tsconfig.dest.json deleted file mode 100644 index 965aaa1c433..00000000000 --- a/yarn-project/wallet/tsconfig.dest.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "extends": ".", - "exclude": ["**/*.test.*", "**/fixtures/*"] -} diff --git a/yarn-project/wallet/tsconfig.json b/yarn-project/wallet/tsconfig.json deleted file mode 100644 index f67ddec9fd6..00000000000 --- a/yarn-project/wallet/tsconfig.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "..", - "compilerOptions": { - "outDir": "dest", - "rootDir": "src", - "tsBuildInfoFile": ".tsbuildinfo" - }, - "include": ["src"] -} diff --git a/yarn-project/world-state/package.json b/yarn-project/world-state/package.json index 59f29ab73e3..3cc0082d51b 100644 --- a/yarn-project/world-state/package.json +++ b/yarn-project/world-state/package.json @@ -4,7 +4,7 @@ "type": "module", "exports": "./dest/index.js", "scripts": { - "build": "yarn clean && yarn formatting && tsc -b tsconfig.dest.json", + "build": "yarn clean && tsc -b tsconfig.dest.json", "build:dev": "tsc -b tsconfig.dest.json --watch", "clean": "rm -rf ./dest .tsbuildinfo", "formatting": "run -T prettier --check ./src && run -T eslint --max-warnings 0 ./src", diff --git a/yarn-project/yarn-project-base/Dockerfile b/yarn-project/yarn-project-base/Dockerfile index 8fb6dcf19b7..7fa07b4c116 100644 --- a/yarn-project/yarn-project-base/Dockerfile +++ b/yarn-project/yarn-project-base/Dockerfile @@ -15,6 +15,7 @@ WORKDIR /usr/src/yarn-project COPY acir-simulator/package.json acir-simulator/package.json COPY archiver/package.json archiver/package.json COPY aztec-cli/package.json aztec-cli/package.json +COPY aztec-rpc/package.json aztec-rpc/package.json COPY aztec-node/package.json aztec-node/package.json COPY aztec.js/package.json aztec.js/package.json COPY docs/package.json docs/package.json @@ -24,7 +25,7 @@ COPY ethereum.js/package.json ethereum.js/package.json # Note: foundation has its own lock file, we need to copy it and build COPY foundation/package.json foundation/package.json COPY foundation/yarn.lock foundation/yarn.lock -COPY kernel-simulator/package.json kernel-simulator/package.json +COPY kernel-prover/package.json kernel-prover/package.json COPY key-store/package.json key-store/package.json COPY merkle-tree/package.json merkle-tree/package.json COPY noir-contracts/package.json noir-contracts/package.json @@ -33,7 +34,6 @@ COPY circuits.js/package.json circuits.js/package.json COPY p2p/package.json p2p/package.json COPY prover-client/package.json prover-client/package.json COPY sequencer-client/package.json sequencer-client/package.json -COPY wallet/package.json wallet/package.json COPY world-state/package.json world-state/package.json COPY package.json tsconfig.json yarn.lock .yarnrc.yml ./ COPY .yarn .yarn diff --git a/yarn-project/yarn.lock b/yarn-project/yarn.lock index 51d13a5f100..065579f9207 100644 --- a/yarn-project/yarn.lock +++ b/yarn-project/yarn.lock @@ -15,7 +15,7 @@ __metadata: languageName: node linkType: hard -"@aztec/acir-simulator@workspace:acir-simulator": +"@aztec/acir-simulator@workspace:^, @aztec/acir-simulator@workspace:acir-simulator": version: 0.0.0-use.local resolution: "@aztec/acir-simulator@workspace:acir-simulator" dependencies: @@ -81,7 +81,7 @@ __metadata: languageName: unknown linkType: soft -"@aztec/aztec-node@workspace:aztec-node": +"@aztec/aztec-node@workspace:^, @aztec/aztec-node@workspace:aztec-node": version: 0.0.0-use.local resolution: "@aztec/aztec-node@workspace:aztec-node" dependencies: @@ -105,16 +105,39 @@ __metadata: languageName: unknown linkType: soft +"@aztec/aztec-rpc@workspace:^, @aztec/aztec-rpc@workspace:aztec-rpc": + version: 0.0.0-use.local + resolution: "@aztec/aztec-rpc@workspace:aztec-rpc" + dependencies: + "@aztec/acir-simulator": "workspace:^" + "@aztec/aztec-node": "workspace:^" + "@aztec/kernel-prover": "workspace:^" + "@aztec/p2p": "workspace:^" + "@jest/globals": ^29.4.3 + "@rushstack/eslint-patch": ^1.1.4 + "@types/jest": ^29.4.0 + "@types/node": ^18.7.23 + jest: ^28.1.3 + sha3: ^2.1.4 + ts-jest: ^28.0.7 + ts-node: ^10.9.1 + tslib: ^2.4.0 + typescript: ^4.9.5 + languageName: unknown + linkType: soft + "@aztec/aztec.js@workspace:^, @aztec/aztec.js@workspace:aztec.js": version: 0.0.0-use.local resolution: "@aztec/aztec.js@workspace:aztec.js" dependencies: + "@aztec/aztec-rpc": "workspace:^" "@aztec/foundation": "workspace:^" "@jest/globals": ^29.4.3 "@rushstack/eslint-patch": ^1.1.4 "@types/jest": ^29.4.0 "@types/node": ^18.7.23 jest: ^28.1.3 + jest-mock-extended: ^3.0.3 ts-jest: ^28.0.7 ts-node: ^10.9.1 tslib: ^2.4.0 @@ -170,8 +193,10 @@ __metadata: version: 0.0.0-use.local resolution: "@aztec/end-to-end@workspace:end-to-end" dependencies: + "@aztec/aztec-node": "workspace:^" "@aztec/aztec.js": "workspace:^" "@aztec/foundation": "workspace:^" + "@aztec/noir-contracts": "workspace:^" "@jest/globals": ^29.4.3 "@rushstack/eslint-patch": ^1.1.4 "@types/jest": ^29.4.0 @@ -254,10 +279,12 @@ __metadata: languageName: unknown linkType: soft -"@aztec/kernel-simulator@workspace:kernel-simulator": +"@aztec/kernel-prover@workspace:^, @aztec/kernel-prover@workspace:kernel-prover": version: 0.0.0-use.local - resolution: "@aztec/kernel-simulator@workspace:kernel-simulator" + resolution: "@aztec/kernel-prover@workspace:kernel-prover" dependencies: + "@aztec/acir-simulator": "workspace:^" + "@aztec/circuits.js": "workspace:^" "@jest/globals": ^29.4.3 "@rushstack/eslint-patch": ^1.1.4 "@types/jest": ^29.4.0 @@ -327,7 +354,7 @@ __metadata: languageName: unknown linkType: soft -"@aztec/noir-contracts@workspace:noir-contracts": +"@aztec/noir-contracts@workspace:^, @aztec/noir-contracts@workspace:noir-contracts": version: 0.0.0-use.local resolution: "@aztec/noir-contracts@workspace:noir-contracts" dependencies: @@ -408,22 +435,6 @@ __metadata: languageName: unknown linkType: soft -"@aztec/wallet@workspace:wallet": - version: 0.0.0-use.local - resolution: "@aztec/wallet@workspace:wallet" - dependencies: - "@jest/globals": ^29.4.3 - "@rushstack/eslint-patch": ^1.1.4 - "@types/jest": ^29.4.0 - "@types/node": ^18.7.23 - jest: ^28.1.3 - ts-jest: ^28.0.7 - ts-node: ^10.9.1 - tslib: ^2.4.0 - typescript: ^4.9.5 - languageName: unknown - linkType: soft - "@aztec/wasm@workspace:.yalc/@aztec/wasm, @aztec/wasm@workspace:^": version: 0.0.0-use.local resolution: "@aztec/wasm@workspace:.yalc/@aztec/wasm"