Skip to content

Commit

Permalink
Kill PublisherDataEncoder and use the encode method from archive instead
Browse files Browse the repository at this point in the history
  • Loading branch information
spalladino committed Mar 16, 2023
1 parent 3dbb7a2 commit 32444aa
Show file tree
Hide file tree
Showing 10 changed files with 55 additions and 85 deletions.
1 change: 1 addition & 0 deletions yarn-project/sequencer-client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"rootDir": "./src"
},
"dependencies": {
"@aztec/archiver": "workspace:^",
"@aztec/ethereum.js": "workspace:^",
"@aztec/l1-contracts": "workspace:^",
"tslib": "^2.4.0"
Expand Down
2 changes: 1 addition & 1 deletion yarn-project/sequencer-client/src/config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { L1Addresses, getL1Addresses } from '@aztec/l1-contracts';
import { L1Addresses } from '@aztec/l1-contracts';

export interface Config extends L1Addresses {
sequencerPrivateKey: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { WalletProvider } from '@aztec/ethereum.js/provider';
import { Rollup } from '@aztec/l1-contracts';
import { Config } from '../config.js';
import { hexStringToBuffer } from '../utils.js';
import { EncodedL2BlockData, PublisherTxSender } from './l2-block-publisher.js';
import { L1ProcessRollupArgs, PublisherTxSender } from './l2-block-publisher.js';

/**
* Pushes transactions to the L1 rollup contract using the custom aztec/ethereum.js library.
Expand All @@ -19,7 +19,9 @@ export class AztecEthereumjsTxSender implements PublisherTxSender {
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.rollupContract = new Rollup(this.ethRpc, EthAddress.fromString(rollupContractAddress), {
from: provider.getAccount(0),
});
this.confirmations = requiredConfirmations;
}

Expand All @@ -29,9 +31,12 @@ export class AztecEthereumjsTxSender implements PublisherTxSender {
);
}

async sendTransaction(encodedData: EncodedL2BlockData): Promise<string | undefined> {
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());
return methodCall
.send({ gas })
.getTxHash()
.then(hash => hash.toString());
}
}
3 changes: 1 addition & 2 deletions yarn-project/sequencer-client/src/publisher/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { Config } from '../config.js';
import { AztecEthereumjsTxSender } from './aztec-ethereumjs-tx-sender.js';
import { L2BlockPublisher } from './l2-block-publisher.js';
import { MockL2DataEncoder } from './mock-l2-block-encoder.js';

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

export function getL2BlockPublisher(config: Config): L2BlockPublisher {
return new L2BlockPublisher(new AztecEthereumjsTxSender(config), new MockL2DataEncoder());
return new L2BlockPublisher(new AztecEthereumjsTxSender(config));
}
Original file line number Diff line number Diff line change
@@ -1,47 +1,44 @@
import { L2Block, mockRandomL2Block } from '@aztec/archiver';
import { TxHash } from '@aztec/ethereum.js/eth_rpc';
import { mock, MockProxy } from 'jest-mock-extended';
import { MockL2DataEncoder } from './mock-l2-block-encoder.js';
import { L2BlockData } from '../receiver.js';
import { EncodedL2BlockData, L2BlockPublisher, PublisherDataEncoder, PublisherTxSender } from './l2-block-publisher.js';
import { sleep } from '../utils.js';
import { L2BlockPublisher, PublisherTxSender } from './l2-block-publisher.js';

describe('L2BlockPublisher', () => {
let encoder: PublisherDataEncoder;
let txSender: MockProxy<PublisherTxSender>;
let txHash: string;
let txReceipt: { transactionHash: string; status: boolean };
let l2BlockData: L2BlockData;
let l2EncodedData: EncodedL2BlockData;

let l2Block: L2Block;
let l2Inputs: Buffer;
let l2Proof: Buffer;
let publisher: L2BlockPublisher;

beforeEach(() => {
l2BlockData = { id: 42 };
const mockEncoder = new MockL2DataEncoder();
l2EncodedData = mockEncoder.mockData;
encoder = mockEncoder;
l2Block = mockRandomL2Block(42);
l2Inputs = l2Block.encode();
l2Proof = Buffer.alloc(0);

txSender = mock<PublisherTxSender>();
txHash = TxHash.random().toString();
txReceipt = { transactionHash: txHash, status: true };
txSender.sendTransaction.mockResolvedValueOnce(txHash);
txSender.getTransactionReceipt.mockResolvedValueOnce(txReceipt);

publisher = new L2BlockPublisher(txSender, encoder, { sleepTimeMs: 1 });
publisher = new L2BlockPublisher(txSender, { sleepTimeMs: 1 });
});

it('publishes l2 block to l1', async () => {
const result = await publisher.processL2Block(l2BlockData);
const result = await publisher.processL2Block(l2Block);

expect(result).toEqual(true);
expect(txSender.sendTransaction).toHaveBeenCalledWith(l2EncodedData);
expect(txSender.sendTransaction).toHaveBeenCalledWith({ proof: l2Proof, inputs: l2Inputs });
expect(txSender.getTransactionReceipt).toHaveBeenCalledWith(txHash);
});

it('retries if sending a tx fails', async () => {
txSender.sendTransaction.mockReset().mockRejectedValueOnce(new Error()).mockResolvedValueOnce(txHash);

const result = await publisher.processL2Block(l2BlockData);
const result = await publisher.processL2Block(l2Block);

expect(result).toEqual(true);
expect(txSender.sendTransaction).toHaveBeenCalledTimes(2);
Expand All @@ -50,7 +47,7 @@ describe('L2BlockPublisher', () => {
it('retries if fetching the receipt fails', async () => {
txSender.getTransactionReceipt.mockReset().mockRejectedValueOnce(new Error()).mockResolvedValueOnce(txReceipt);

const result = await publisher.processL2Block(l2BlockData);
const result = await publisher.processL2Block(l2Block);

expect(result).toEqual(true);
expect(txSender.getTransactionReceipt).toHaveBeenCalledTimes(2);
Expand All @@ -59,15 +56,15 @@ describe('L2BlockPublisher', () => {
it('returns false if tx reverts', async () => {
txSender.getTransactionReceipt.mockReset().mockResolvedValueOnce({ ...txReceipt, status: false });

const result = await publisher.processL2Block(l2BlockData);
const result = await publisher.processL2Block(l2Block);

expect(result).toEqual(false);
});

it('returns false if interrupted', async () => {
txSender.sendTransaction.mockReset().mockImplementationOnce(() => sleep(10, txHash));

const resultPromise = publisher.processL2Block(l2BlockData);
const resultPromise = publisher.processL2Block(l2Block);
publisher.interrupt();
const result = await resultPromise;

Expand Down
31 changes: 11 additions & 20 deletions yarn-project/sequencer-client/src/publisher/l2-block-publisher.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { L2BlockData, L2BlockReceiver } from '../receiver.js';
import { L2Block } from '@aztec/archiver';
import { L2BlockReceiver } from '../receiver.js';

// eslint-disable-next-line @typescript-eslint/no-unused-vars
const MIN_FEE_DISTRIBUTOR_BALANCE = 5n * 10n ** 17n;
Expand All @@ -7,25 +8,18 @@ const MIN_FEE_DISTRIBUTOR_BALANCE = 5n * 10n ** 17n;
* Component responsible of pushing the txs to the chain and waiting for completion.
*/
export interface PublisherTxSender {
sendTransaction(encodedData: EncodedL2BlockData): Promise<string | undefined>;
sendTransaction(encodedData: L1ProcessRollupArgs): Promise<string | undefined>;
getTransactionReceipt(txHash: string): Promise<{ status: boolean; transactionHash: string } | undefined>;
}

/**
* Encoded block data ready to be pushed to the L1 contract.
* Encoded block data and proof ready to be pushed to the L1 contract.
*/
export type EncodedL2BlockData = {
export type L1ProcessRollupArgs = {
proof: Buffer;
inputs: Buffer;
};

/**
* Component responsible of encoding the data of an l2 block to be published to the l1 rollup contract.
*/
export interface PublisherDataEncoder {
encodeL2BlockDataForPublish(l2BlockData: L2BlockData): Promise<EncodedL2BlockData>;
}

/**
* Publishes L2 blocks to the L1 rollup contracts. This implementation does *not* retry a transaction in
* the event of network congestion.
Expand All @@ -40,11 +34,7 @@ export class L2BlockPublisher implements L2BlockReceiver {
private interruptResolve = () => {};
private sleepTimeMs: number;

constructor(
private txSender: PublisherTxSender,
private encoder: PublisherDataEncoder,
opts?: { sleepTimeMs?: number },
) {
constructor(private txSender: PublisherTxSender, opts?: { sleepTimeMs?: number }) {
this.interruptPromise = new Promise(resolve => (this.interruptResolve = resolve));
this.sleepTimeMs = opts?.sleepTimeMs ?? 60_000;
}
Expand All @@ -53,8 +43,9 @@ export class L2BlockPublisher implements L2BlockReceiver {
* Processes incoming L2 block data by publishing it to the L1 rollup contract.
* @returns True once the tx has been confirmed and is successful, false on revert or interrupt, blocks otherwise.
*/
public async processL2Block(l2BlockData: L2BlockData): Promise<boolean> {
const txData = await this.encoder.encodeL2BlockDataForPublish(l2BlockData);
public async processL2Block(l2BlockData: L2Block): Promise<boolean> {
const proof = Buffer.alloc(0);
const txData = { proof, inputs: l2BlockData.encode() };

while (!this.interrupted) {
if (!(await this.checkFeeDistributorBalance())) {
Expand All @@ -73,7 +64,7 @@ export class L2BlockPublisher implements L2BlockReceiver {
if (receipt.status) return true;

// Check if someone else moved the block id
if (!(await this.checkNextL2BlockId(l2BlockData.id))) {
if (!(await this.checkNextL2BlockId(l2BlockData.number))) {
console.log('Publish failed. Contract changed underfoot.');
break;
}
Expand Down Expand Up @@ -109,7 +100,7 @@ export class L2BlockPublisher implements L2BlockReceiver {
return true;
}

private async sendTransaction(encodedData: EncodedL2BlockData): Promise<string | undefined> {
private async sendTransaction(encodedData: L1ProcessRollupArgs): Promise<string | undefined> {
while (!this.interrupted) {
try {
return await this.txSender.sendTransaction(encodedData);
Expand Down

This file was deleted.

7 changes: 2 additions & 5 deletions yarn-project/sequencer-client/src/receiver.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
// TODO: Complete definition or import from another package (add txs at least!).
export interface L2BlockData {
id: number;
}
import { L2Block } from '@aztec/archiver';

/**
* Given the necessary rollup data, verifies it, and updates the underlying state accordingly to advance the state of the system.
* See https://hackmd.io/ouVCnacHQRq2o1oRc5ksNA#RollupReceiver.
*/
export interface L2BlockReceiver {
processL2Block(l2BlockData: L2BlockData): Promise<boolean>;
processL2Block(l2BlockData: L2Block): Promise<boolean>;
}
25 changes: 13 additions & 12 deletions yarn-project/sequencer-client/test/l2-block-publisher.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { L2Block, mockRandomL2Block } from '@aztec/archiver';
import { EthAddress } from '@aztec/ethereum.js/eth_address';
import { EthereumRpc } from '@aztec/ethereum.js/eth_rpc';
import { WalletProvider } from '@aztec/ethereum.js/provider';
import { Rollup } from '@aztec/l1-contracts';
import { beforeAll, describe, it, expect } from '@jest/globals';
import { beforeAll, describe, expect, it } from '@jest/globals';
import { AztecEthereumjsTxSender } from '../src/publisher/aztec-ethereumjs-tx-sender.js';
import { EncodedL2BlockData, L2BlockPublisher } from '../src/publisher/l2-block-publisher.js';
import { MockL2DataEncoder } from '../src/publisher/mock-l2-block-encoder.js';
import { L2BlockData } from '../src/receiver.js';
import { L2BlockPublisher } from '../src/publisher/l2-block-publisher.js';
import { hexStringToBuffer } from '../src/utils.js';

// Accounts 4 and 5 of Anvil default startup with mnemonic: 'test test test test test test test test test test test junk'
Expand All @@ -18,16 +17,15 @@ describe('L2BlockPublisher integration', () => {
let rollup: Rollup;
let ethRpc: EthereumRpc;
let publisher: L2BlockPublisher;
let l2BlockData: L2BlockData;
let encodedL2BlockData: EncodedL2BlockData;
let l2Block: L2Block;
let l2Proof: Buffer;

beforeAll(async () => {
let deployer: EthAddress;
({ ethRpc, rollup, deployer } = await deployRollup());

const encoder = new MockL2DataEncoder();
encodedL2BlockData = encoder.mockData;
l2BlockData = { id: 42 };
l2Block = mockRandomL2Block(42);
l2Proof = Buffer.alloc(0);

publisher = new L2BlockPublisher(
new AztecEthereumjsTxSender({
Expand All @@ -37,7 +35,6 @@ describe('L2BlockPublisher integration', () => {
rollupContract: rollup.address.toChecksumString(),
sequencerPrivateKey: sequencerPK
}),
encoder,
{
sleepTimeMs: 100
}
Expand All @@ -46,11 +43,15 @@ describe('L2BlockPublisher integration', () => {

it('publishes l2 block data to l1 rollup contract', async () => {
const blockNumber = await ethRpc.blockNumber();
await publisher.processL2Block(l2BlockData);
await publisher.processL2Block(l2Block);

const logs = await rollup.getLogs('RollupBlockProcessed', { fromBlock: blockNumber });
expect(logs).toHaveLength(1);
expect(logs[0].args.rollupBlockNumber).toEqual(1n);
expect(logs[0].args.rollupBlockNumber).toEqual(42n);

const tx = await ethRpc.getTransactionByHash(logs[0].transactionHash!);
const expectedData = rollup.methods.processRollup(l2Proof, l2Block.encode()).encodeABI();
expect(tx.input).toEqual(expectedData);
});
});

Expand Down
Loading

0 comments on commit 32444aa

Please sign in to comment.