Skip to content

Commit

Permalink
L2 block publisher (#45)
Browse files Browse the repository at this point in the history
* Update l1-contracts submodule to latest

* Port skeleton of the publisher from aztec-connect

* Create yarn-projct/l1-contracts for ts contract abstractions

* Initial version of rollup publisher with mock data using aztec/ethereum.js

* Fix tests and add missing awaits on publisher

* Integration test for rollup publisher using anvil

* Remove querying env vars (not responsibility of each lib)

* Export archiver modules and do not start unless invoked directly

* Kill PublisherDataEncoder and use the encode method from archive instead

* Add l1-contracts to yarn-project-base dockerfile

* Merge fix

---------

Co-authored-by: PhilWindle <[email protected]>
  • Loading branch information
spalladino and PhilWindle authored Mar 23, 2023
1 parent 4078589 commit 6b97f73
Show file tree
Hide file tree
Showing 28 changed files with 711 additions and 8 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ The Aztec 3 system consists of the following sub projects.
- `ethereum.js`
- `kernel-simulator`
- `key-store`
- `l1-contracts`
- `p2p`
- `prover-client`
- `aztec-node`
Expand Down
2 changes: 1 addition & 1 deletion yarn-project/archiver/src/archiver/archiver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ export class Archiver implements L2BlockSource {
* @param l2BlockNum - Block number.
* @returns Random L2Block.
*/
function mockRandomL2Block(l2BlockNum: number): L2Block {
export function mockRandomL2Block(l2BlockNum: number): L2Block {
const newNullifiers = [randomBytes(32), randomBytes(32), randomBytes(32), randomBytes(32)];
const newCommitments = [randomBytes(32), randomBytes(32), randomBytes(32), randomBytes(32)];
const newContracts: Buffer[] = [randomBytes(32)];
Expand Down
6 changes: 6 additions & 0 deletions yarn-project/l1-contracts/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
require('@rushstack/eslint-patch/modern-module-resolution');

module.exports = {
extends: ['@aztec/eslint-config'],
parserOptions: { tsconfigRootDir: __dirname },
};
14 changes: 14 additions & 0 deletions yarn-project/l1-contracts/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
FROM 278380418400.dkr.ecr.eu-west-2.amazonaws.com/yarn-project-base AS builder

COPY l1-contracts l1-contracts
WORKDIR /usr/src/yarn-project/l1-contracts
RUN yarn build && yarn formatting && yarn test

# Prune dev dependencies. See comment in base image.
RUN yarn cache clean
RUN yarn workspaces focus --production > /dev/null

FROM node:18-alpine
COPY --from=builder /usr/src/yarn-project/l1-contracts /usr/src/yarn-project/l1-contracts
WORKDIR /usr/src/yarn-project/l1-contracts
ENTRYPOINT ["yarn"]
3 changes: 3 additions & 0 deletions yarn-project/l1-contracts/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# L1 Contracts

Typed classes for the L1 contracts.
9 changes: 9 additions & 0 deletions yarn-project/l1-contracts/contracts.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"outputPath": "./src/aztec-ethereumjs-contracts",
"contracts": {
"Rollup": {
"source": "foundry",
"buildFile": "../../l1-contracts/out/Rollup.sol/Rollup.json"
}
}
}
47 changes: 47 additions & 0 deletions yarn-project/l1-contracts/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"name": "@aztec/l1-contracts",
"version": "0.0.0",
"type": "module",
"exports": "./dest/index.js",
"typedoc": {
"entryPoint": "./src/index.ts",
"displayName": "L1 Contracts",
"tsconfig": "./tsconfig.dest.json"
},
"scripts": {
"build": "yarn clean && yarn formatting && tsc -b tsconfig.dest.json",
"build:dev": "tsc -b tsconfig.dest.json --watch",
"generate": "contract_gen_def",
"clean": "rm -rf ./dest .tsbuildinfo",
"formatting": "run -T prettier --check ./src && run -T eslint --max-warnings 0 ./src",
"test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --no-cache --passWithNoTests"
},
"jest": {
"preset": "ts-jest/presets/default-esm",
"globals": {
"ts-jest": {
"useESM": true
}
},
"moduleNameMapper": {
"^(\\.{1,2}/.*)\\.js$": "$1"
},
"testRegex": "./src/.*\\.test\\.ts$",
"rootDir": "./src"
},
"dependencies": {
"tslib": "^2.4.0"
},
"devDependencies": {
"@aztec/eslint-config": "workspace:^",
"@aztec/ethereum.js": "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",
"ts-jest": "^28.0.7",
"ts-node": "^10.9.1",
"typescript": "^4.9.5"
}
}
42 changes: 42 additions & 0 deletions yarn-project/l1-contracts/src/aztec-ethereumjs-contracts/Rollup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// THIS IS GENERATED CODE, DO NOT EDIT!
/* eslint-disable */
import { EthAddress } from '@aztec/ethereum.js/eth_address';
import { EthereumRpc } from '@aztec/ethereum.js/eth_rpc';
import { Contract, ContractTxReceipt, EventLog, Options, TxCall, TxSend } from '@aztec/ethereum.js/contract';
import * as Bytes from '@aztec/ethereum.js/contract/bytes.js';
import abi from './RollupAbi.js';
export type RollupBlockProcessedEvent = {
rollupBlockNumber: bigint;
};
export interface RollupBlockProcessedEventLog extends EventLog<RollupBlockProcessedEvent, 'RollupBlockProcessed'> {}
interface RollupEvents {
RollupBlockProcessed: RollupBlockProcessedEvent;
}
interface RollupEventLogs {
RollupBlockProcessed: RollupBlockProcessedEventLog;
}
interface RollupTxEventLogs {
RollupBlockProcessed: RollupBlockProcessedEventLog[];
}
export interface RollupTransactionReceipt extends ContractTxReceipt<RollupTxEventLogs> {}
interface RollupMethods {
processRollup(_proof: Bytes.Bytes, _inputs: Bytes.Bytes): TxSend<RollupTransactionReceipt>;
rollupStateHash(): TxCall<Bytes.Bytes32>;
verifier(): TxCall<EthAddress>;
}
export interface RollupDefinition {
methods: RollupMethods;
events: RollupEvents;
eventLogs: RollupEventLogs;
}
export class Rollup extends Contract<RollupDefinition> {
constructor(eth: EthereumRpc, address?: EthAddress, options?: Options) {
super(eth, abi, address, options);
}
deploy(): TxSend<RollupTransactionReceipt> {
return super.deployBytecode(
'0x60a060405234801561001057600080fd5b5060405161001d9061004b565b604051809103906000f080158015610039573d6000803e3d6000fd5b506001600160a01b0316608052610058565b61019d80610e8883390190565b608051610e0f610079600039600081816067015261016a0152610e0f6000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80631ab9c603146100465780632b7ac3f314610062578063f81cccbe146100a1575b600080fd5b61004f60005481565b6040519081526020015b60405180910390f35b6100897f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610059565b6100b46100af366004610adf565b6100b6565b005b6000806000806100c585610235565b60005493975091955093509150158015906100e257508260005414155b1561011257600054604051632d2ef59f60e11b815260048101919091526024810184905260440160405180910390fd5b60408051600180825281830190925260009160208083019080368337019050509050818160008151811061014857610148610b43565b6020908102919091010152604051633a94343960e21b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063ea50d0e4906101a1908a908590600401610b7d565b602060405180830381865afa1580156101be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101e29190610bf7565b6101ff576040516309bde33960e01b815260040160405180910390fd5b600083815560405186917f3b8a2090d4235f22cdb27dec2d75d724354dd3c747beb2df2bd09f1f251428b391a250505050505050565b600080600080610249856020015160e01c90565b9350610261610259600186610c36565b600487610283565b925061026f8460b887610283565b915061027a85610335565b90509193509193565b6040805160b880825260e082019092526000918291906020820181803683370190505090508460181c60208201538460101c60218201538460081c602282015384602382015360b46024820160b486602001860160045afa506002816040516102ec9190610c4f565b602060405180830381855afa158015610309573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061032c9190610c6b565b95945050505050565b60008060006103468461016c61049a565b909250905060008061036e8661035d866020610c84565b61036990610170610c9b565b61049a565b90925090506000806103a0886103848689610c9b565b61038f906020610c84565b61039b90610174610c9b565b61060d565b909250905060006103dd89846103b6888b610c9b565b6103c09190610c9b565b6103cb906020610c84565b6103d790610174610c9b565b8561076e565b604080516101ec8082526102208201909252919250906000908260208201818036833701905050905081602082018360208e0160045afa5061018c81018690526101ac81018890526101cc81018490526101ec810183905260405161020c9060029061044a908490610c4f565b602060405180830381855afa158015610467573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061048a9190610c6b565b9c9b505050505050505050505050565b8181016020015160e01c60006008816104b38285610cae565b67ffffffffffffffff8111156104cb576104cb610a3c565b6040519080825280602002602001820160405280156104f4578160200160208202803683370190505b50905060005b6105048386610cae565b8110156105f5576000610518826008610c84565b610523906020610c84565b61052e886024610c9b565b6105389190610c9b565b6040805161010080825261012082019092529192506000919060208201818036833701905050905061010060208201610100848c0160045afa506002816040516105829190610c4f565b602060405180830381855afa15801561059f573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105c29190610c6b565b8484815181106105d4576105d4610b43565b602002602001018181525050505080806105ed90610cd0565b9150506104fa565b506000610601826108c4565b93505050509250929050565b8181016020015160e01c60006002816106268285610cae565b67ffffffffffffffff81111561063e5761063e610a3c565b604051908082528060200260200182016040528015610667578160200160208202803683370190505b50905060005b6106778386610cae565b81101561075657600061068b826040610c84565b610696886024610c9b565b6106a09190610c9b565b60408051818152606081018252919250600091906020820181803683370190505090506040602082016040848c0160045afa506002816040516106e39190610c4f565b602060405180830381855afa158015610700573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906107239190610c6b565b84848151811061073557610735610b43565b6020026020010181815250505050808061074e90610cd0565b91505061066d565b5083610761826108c4565b9350935050509250929050565b600060028161077d8285610cae565b67ffffffffffffffff81111561079557610795610a3c565b6040519080825280602002602001820160405280156107be578160200160208202803683370190505b50905060005b6107ce8386610cae565b8110156108b05760006107e2826068610c84565b6107ed886024610c9b565b6107f79190610c9b565b60408051606880825260a08201909252919250600091906020820181803683370190505090506068602082016068848c0160045afa5060028160405161083d9190610c4f565b602060405180830381855afa15801561085a573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061087d9190610c6b565b84848151811061088f5761088f610b43565b602002602001018181525050505080806108a890610cd0565b9150506107c4565b506108ba816108c4565b9695505050505050565b6000805b82516108d5826002610dcd565b10156108ed57806108e581610cd0565b9150506108c8565b60006108fa826002610dcd565b905080845260005b82811015610a175760005b82811015610a0457600286828151811061092957610929610b43565b60200260200101518783600161093f9190610c9b565b8151811061094f5761094f610b43565b6020026020010151604051602001610971929190918252602082015260400190565b60408051601f198184030181529082905261098b91610c4f565b602060405180830381855afa1580156109a8573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906109cb9190610c6b565b866109d7600284610cae565b815181106109e7576109e7610b43565b60209081029190910101526109fd600282610c9b565b905061090d565b5080610a0f81610cd0565b915050610902565b5083600081518110610a2b57610a2b610b43565b602002602001015192505050919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112610a6357600080fd5b813567ffffffffffffffff80821115610a7e57610a7e610a3c565b604051601f8301601f19908116603f01168101908282118183101715610aa657610aa6610a3c565b81604052838152866020858801011115610abf57600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060408385031215610af257600080fd5b823567ffffffffffffffff80821115610b0a57600080fd5b610b1686838701610a52565b93506020850135915080821115610b2c57600080fd5b50610b3985828601610a52565b9150509250929050565b634e487b7160e01b600052603260045260246000fd5b60005b83811015610b74578181015183820152602001610b5c565b50506000910152565b60408152600083518060408401526020610b9d8260608601838901610b59565b6060601f19601f93909301929092168401848103830185830152855192810183905285820192600091608001905b80831015610beb5784518252938301936001929092019190830190610bcb565b50979650505050505050565b600060208284031215610c0957600080fd5b81518015158114610c1957600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b81810381811115610c4957610c49610c20565b92915050565b60008251610c61818460208701610b59565b9190910192915050565b600060208284031215610c7d57600080fd5b5051919050565b8082028115828204841417610c4957610c49610c20565b80820180821115610c4957610c49610c20565b600082610ccb57634e487b7160e01b600052601260045260246000fd5b500490565b600060018201610ce257610ce2610c20565b5060010190565b600181815b80851115610d24578160001904821115610d0a57610d0a610c20565b80851615610d1757918102915b93841c9390800290610cee565b509250929050565b600082610d3b57506001610c49565b81610d4857506000610c49565b8160018114610d5e5760028114610d6857610d84565b6001915050610c49565b60ff841115610d7957610d79610c20565b50506001821b610c49565b5060208310610133831016604e8410600b8410161715610da7575081810a610c49565b610db18383610ce9565b8060001904821115610dc557610dc5610c20565b029392505050565b6000610c198383610d2c56fea2646970667358221220ece9d35f0dabd2ce67f2fc7b08e612bd5e3e292de94f6df90a3bb48f782fd9ef64736f6c63430008120033608060405234801561001057600080fd5b5061017d806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063937f6a101461003b578063ea50d0e41461005a575b600080fd5b60405168496d2061206d6f636b60b81b81526020015b60405180910390f35b610072610068366004610082565b6001949350505050565b6040519015158152602001610051565b6000806000806040858703121561009857600080fd5b843567ffffffffffffffff808211156100b057600080fd5b818701915087601f8301126100c457600080fd5b8135818111156100d357600080fd5b8860208285010111156100e557600080fd5b60209283019650945090860135908082111561010057600080fd5b818701915087601f83011261011457600080fd5b81358181111561012357600080fd5b8860208260051b850101111561013857600080fd5b9598949750506020019450505056fea2646970667358221220dccfdb9ed1ec020c6477c07aa6b7354d591126e95a8df81bf7a547459d30b6cb64736f6c63430008120033',
) as any;
}
}
export var RollupAbi = abi;
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { ContractAbi } from '@aztec/ethereum.js/contract';
export default new ContractAbi([
{
inputs: [],
stateMutability: 'nonpayable',
type: 'constructor',
},
{
inputs: [],
name: 'InvalidProof',
type: 'error',
},
{
inputs: [
{
internalType: 'bytes32',
name: 'expected',
type: 'bytes32',
},
{
internalType: 'bytes32',
name: 'actual',
type: 'bytes32',
},
],
name: 'InvalidStateHash',
type: 'error',
},
{
anonymous: false,
inputs: [
{
indexed: true,
internalType: 'uint256',
name: 'rollupBlockNumber',
type: 'uint256',
},
],
name: 'RollupBlockProcessed',
type: 'event',
},
{
inputs: [
{
internalType: 'bytes',
name: '_proof',
type: 'bytes',
},
{
internalType: 'bytes',
name: '_inputs',
type: 'bytes',
},
],
name: 'processRollup',
outputs: [],
stateMutability: 'nonpayable',
type: 'function',
},
{
inputs: [],
name: 'rollupStateHash',
outputs: [
{
internalType: 'bytes32',
name: '',
type: 'bytes32',
},
],
stateMutability: 'view',
type: 'function',
},
{
inputs: [],
name: 'verifier',
outputs: [
{
internalType: 'contract MockVerifier',
name: '',
type: 'address',
},
],
stateMutability: 'view',
type: 'function',
},
]);
6 changes: 6 additions & 0 deletions yarn-project/l1-contracts/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export interface L1Addresses {
rollupContract: string;
feeDistributor: string;
}

export * from './aztec-ethereumjs-contracts/Rollup.js';
4 changes: 4 additions & 0 deletions yarn-project/l1-contracts/tsconfig.dest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"extends": ".",
"exclude": ["**/*.test.*", "**/fixtures/*"]
}
9 changes: 9 additions & 0 deletions yarn-project/l1-contracts/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"extends": "..",
"compilerOptions": {
"outDir": "dest",
"rootDir": "src",
"tsBuildInfoFile": ".tsbuildinfo"
},
"include": ["src"]
}
1 change: 1 addition & 0 deletions yarn-project/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"key-store",
"merkle-tree",
"noir-contracts",
"l1-contracts",
"p2p",
"prettier-config",
"prover-client",
Expand Down
4 changes: 4 additions & 0 deletions yarn-project/sequencer-client/.eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,8 @@ require('@rushstack/eslint-patch/modern-module-resolution');
module.exports = {
extends: ['@aztec/eslint-config'],
parserOptions: { tsconfigRootDir: __dirname },
rules: {
"jsdoc/require-jsdoc": "off",
"jsdoc/require-param": "off"
}
};
13 changes: 13 additions & 0 deletions yarn-project/sequencer-client/jest.integration.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"preset": "ts-jest/presets/default-esm",
"globals": {
"ts-jest": {
"useESM": true
}
},
"moduleNameMapper": {
"^(\\.{1,2}/.*)\\.js$": "$1"
},
"testRegex": "./test/.*\\.test\\.ts$",
"rootDir": "./test"
}
10 changes: 9 additions & 1 deletion yarn-project/sequencer-client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@
"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",
"test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --no-cache --passWithNoTests"
"formatting:fix": "run -T prettier -w ./src && run -T eslint --max-warnings 0 ./src",
"test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --no-cache --passWithNoTests",
"test:integration": "concurrently -k -s first -c reset,dim -n test,anvil \"yarn test:integration:run\" \"anvil\"",
"test:integration:run": "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --no-cache --config jest.integration.config.json"
},
"jest": {
"preset": "ts-jest/presets/default-esm",
Expand All @@ -29,6 +32,9 @@
"rootDir": "./src"
},
"dependencies": {
"@aztec/archiver": "workspace:^",
"@aztec/ethereum.js": "workspace:^",
"@aztec/l1-contracts": "workspace:^",
"tslib": "^2.4.0"
},
"devDependencies": {
Expand All @@ -37,7 +43,9 @@
"@rushstack/eslint-patch": "^1.1.4",
"@types/jest": "^29.4.0",
"@types/node": "^18.7.23",
"concurrently": "^7.6.0",
"jest": "^28.1.3",
"jest-mock-extended": "^3.0.3",
"ts-jest": "^28.0.7",
"ts-node": "^10.9.1",
"typescript": "^4.9.5"
Expand Down
7 changes: 7 additions & 0 deletions yarn-project/sequencer-client/src/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { L1Addresses } from '@aztec/l1-contracts';

export interface Config extends L1Addresses {
sequencerPrivateKey: string;
ethereumHost: string;
requiredConfirmations: number;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { EthAddress } from '@aztec/ethereum.js/eth_address';
import { EthereumRpc, TxHash, waitForTxReceipt } from '@aztec/ethereum.js/eth_rpc';
import { WalletProvider } from '@aztec/ethereum.js/provider';
import { Rollup } from '@aztec/l1-contracts';
import { Config } from '../config.js';
import { hexStringToBuffer } from '../utils.js';
import { L1ProcessRollupArgs, PublisherTxSender } from './l2-block-publisher.js';

/**
* Pushes transactions to the L1 rollup contract using the custom aztec/ethereum.js library.
*/
export class AztecEthereumjsTxSender implements PublisherTxSender {
private ethRpc: EthereumRpc;
private rollupContract: Rollup;
private confirmations: number;

constructor(config: Config) {
const { ethereumHost, sequencerPrivateKey, rollupContract: rollupContractAddress, requiredConfirmations } = config;
const provider = WalletProvider.fromHost(ethereumHost);
provider.addAccount(hexStringToBuffer(sequencerPrivateKey));
this.ethRpc = new EthereumRpc(provider);
this.rollupContract = new Rollup(this.ethRpc, EthAddress.fromString(rollupContractAddress), {
from: provider.getAccount(0),
});
this.confirmations = requiredConfirmations;
}

getTransactionReceipt(txHash: string): Promise<{ status: boolean; transactionHash: string } | undefined> {
return waitForTxReceipt(TxHash.fromString(txHash), this.ethRpc, this.confirmations).then(
r => r && { ...r, transactionHash: r.transactionHash.toString() },
);
}

async sendTransaction(encodedData: L1ProcessRollupArgs): Promise<string | undefined> {
const methodCall = this.rollupContract.methods.processRollup(encodedData.proof, encodedData.inputs);
const gas = await methodCall.estimateGas();
return methodCall
.send({ gas })
.getTxHash()
.then(hash => hash.toString());
}
}
9 changes: 9 additions & 0 deletions yarn-project/sequencer-client/src/publisher/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Config } from '../config.js';
import { AztecEthereumjsTxSender } from './aztec-ethereumjs-tx-sender.js';
import { L2BlockPublisher } from './l2-block-publisher.js';

export { L2BlockPublisher } from './l2-block-publisher.js';

export function getL2BlockPublisher(config: Config): L2BlockPublisher {
return new L2BlockPublisher(new AztecEthereumjsTxSender(config));
}
Loading

0 comments on commit 6b97f73

Please sign in to comment.