Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
benesjan committed Jan 15, 2024
1 parent 757dc29 commit 6d4f22a
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 82 deletions.
8 changes: 5 additions & 3 deletions yarn-project/archiver/src/archiver/archiver.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ describe('Archiver', () => {
function makeL2BlockProcessedEvent(l1BlockNum: bigint, l2BlockNum: bigint) {
return {
blockNumber: l1BlockNum,
args: { blockNum: l2BlockNum },
args: { blockNumber: l2BlockNum },
transactionHash: `0x${l2BlockNum}`,
} as Log<bigint, number, undefined, true, typeof RollupAbi, 'L2BlockProcessed'>;
}
Expand Down Expand Up @@ -349,8 +349,10 @@ function makeL1ToL2MessageCancelledEvents(l1BlockNum: bigint, entryKeys: string[
* @returns A fake tx with calldata that corresponds to calling process in the Rollup contract.
*/
function makeRollupTx(l2Block: L2Block) {
const header = toHex(l2Block.header.toBuffer());
const archive = toHex(l2Block.archive.toBuffer());
const body = toHex(l2Block.bodyToBuffer());
const proof = `0x`;
const block = toHex(l2Block.toBufferWithLogs());
const input = encodeFunctionData({ abi: RollupAbi, functionName: 'process', args: [proof, block] });
const input = encodeFunctionData({ abi: RollupAbi, functionName: 'process', args: [header, archive, body, proof] });
return { input } as Transaction<bigint, number>;
}
14 changes: 10 additions & 4 deletions yarn-project/archiver/src/archiver/eth_log_handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,12 @@ export async function processBlockLogs(
): Promise<L2Block[]> {
const retrievedBlocks: L2Block[] = [];
for (const log of logs) {
const blockNum = log.args.blockNum;
const blockNum = log.args.blockNumber;
if (blockNum !== expectedL2BlockNumber) {
throw new Error('Block number mismatch. Expected: ' + expectedL2BlockNumber + ' but got: ' + blockNum + '.');
}
// TODO: Fetch blocks from calldata in parallel
const newBlock = await getBlockFromCallData(publicClient, log.transactionHash!, log.args.blockNum);
const newBlock = await getBlockFromCallData(publicClient, log.transactionHash!, log.args.blockNumber);
newBlock.setL1BlockNumber(log.blockNumber!);
retrievedBlocks.push(newBlock);
expectedL2BlockNumber++;
Expand Down Expand Up @@ -112,8 +112,14 @@ async function getBlockFromCallData(
if (functionName !== 'process') {
throw new Error(`Unexpected method called ${functionName}`);
}
const [, l2BlockHex] = args! as [Hex, Hex];
const block = L2Block.fromBufferWithLogs(Buffer.from(hexToBytes(l2BlockHex)));
// TODO(benesjan): This is brittle and should be handled inside the L2 Block.
const [headerHex, archiveHex, bodyHex] = args! as [Hex, Hex, Hex, Hex];
const blockBuffer = Buffer.concat([
Buffer.from(hexToBytes(headerHex)),
Buffer.from(hexToBytes(archiveHex)),
Buffer.from(hexToBytes(bodyHex)),
]);
const block = L2Block.fromBufferWithLogs(blockBuffer);
if (BigInt(block.number) !== l2BlockNum) {
throw new Error(`Block number mismatch: expected ${l2BlockNum} but got ${block.number}`);
}
Expand Down
52 changes: 6 additions & 46 deletions yarn-project/circuit-types/src/l2_block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -263,19 +263,7 @@ export class L2Block {
*/
toBuffer() {
return serializeToBuffer(
this.header.globalVariables,
// TODO(#3868)
AppendOnlyTreeSnapshot.empty(), // this.startNoteHashTreeSnapshot,
AppendOnlyTreeSnapshot.empty(), // this.startNullifierTreeSnapshot,
AppendOnlyTreeSnapshot.empty(), // this.startContractTreeSnapshot,
AppendOnlyTreeSnapshot.empty(), // this.startPublicDataTreeSnapshot,
AppendOnlyTreeSnapshot.empty(), // this.startL1ToL2MessageTreeSnapshot,
this.header.lastArchive,
this.header.state.partial.noteHashTree,
this.header.state.partial.nullifierTree,
this.header.state.partial.contractTree,
this.header.state.partial.publicDataTree,
this.header.state.l1ToL2MessageTree,
this.header,
this.archive,
this.newCommitments.length,
this.newCommitments,
Expand Down Expand Up @@ -308,13 +296,6 @@ export class L2Block {
return serializeToBuffer(this.toBuffer(), this.newEncryptedLogs, this.newUnencryptedLogs);
}

headerAndArchiveToBuffer() {
return serializeToBuffer(
this.header,
this.archive,
);
}

bodyToBuffer(): Buffer {
if (this.newEncryptedLogs === undefined || this.newUnencryptedLogs === undefined) {
throw new Error(
Expand All @@ -335,7 +316,7 @@ export class L2Block {
this.newContracts,
this.newContractData,
this.newL1ToL2Messages.length,
this.newL1ToL2Messages,
this.newL1ToL2Messages, this.newEncryptedLogs, this.newUnencryptedLogs
);
}

Expand All @@ -357,20 +338,8 @@ export class L2Block {
*/
static fromBuffer(buf: Buffer | BufferReader, blockHash?: Buffer) {
const reader = BufferReader.asReader(buf);
const globalVariables = reader.readObject(GlobalVariables);
// TODO(#3938): update the encoding here
reader.readObject(AppendOnlyTreeSnapshot); // startNoteHashTreeSnapshot
reader.readObject(AppendOnlyTreeSnapshot); // startNullifierTreeSnapshot
reader.readObject(AppendOnlyTreeSnapshot); // startContractTreeSnapshot
reader.readObject(AppendOnlyTreeSnapshot); // startPublicDataTreeSnapshot
reader.readObject(AppendOnlyTreeSnapshot); // startL1ToL2MessageTreeSnapshot
const startArchiveSnapshot = reader.readObject(AppendOnlyTreeSnapshot);
const endNoteHashTreeSnapshot = reader.readObject(AppendOnlyTreeSnapshot);
const endNullifierTreeSnapshot = reader.readObject(AppendOnlyTreeSnapshot);
const endContractTreeSnapshot = reader.readObject(AppendOnlyTreeSnapshot);
const endPublicDataTreeSnapshot = reader.readObject(AppendOnlyTreeSnapshot);
const endL1ToL2MessageTreeSnapshot = reader.readObject(AppendOnlyTreeSnapshot);
const endArchiveSnapshot = reader.readObject(AppendOnlyTreeSnapshot);
const header = reader.readObject(Header);
const archive = reader.readObject(AppendOnlyTreeSnapshot);
const newCommitments = reader.readVector(Fr);
const newNullifiers = reader.readVector(Fr);
const newPublicDataWrites = reader.readVector(PublicDataWrite);
Expand All @@ -380,19 +349,9 @@ export class L2Block {
// TODO(sean): could an optimization of this be that it is encoded such that zeros are assumed
const newL1ToL2Messages = reader.readVector(Fr);

const partial = new PartialStateReference(
endNoteHashTreeSnapshot,
endNullifierTreeSnapshot,
endContractTreeSnapshot,
endPublicDataTreeSnapshot,
);
const state = new StateReference(endL1ToL2MessageTreeSnapshot, partial);
// TODO(#3938): populate bodyHash
const header = new Header(startArchiveSnapshot, [Fr.ZERO, Fr.ZERO], state, globalVariables);

return L2Block.fromFields(
{
archive: endArchiveSnapshot,
archive,
header,
newCommitments,
newNullifiers,
Expand Down Expand Up @@ -565,6 +524,7 @@ export class L2Block {
* and inside the circuit, it is part of the public inputs.
* @returns The calldata hash.
*/
// TODO(benesjan): Update to getBodyHash
getCalldataHash() {
if (this.newEncryptedLogs === undefined) {
throw new Error('Encrypted logs has to be attached before calling "getCalldataHash"');
Expand Down
26 changes: 18 additions & 8 deletions yarn-project/end-to-end/src/integration_l1_publisher.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ describe('L1Publisher integration', () => {
};

it(`Build ${numberOfConsecutiveBlocks} blocks of 4 bloated txs building on each other`, async () => {
const stateInRollup_ = await rollup.read.rollupStateHash();
const stateInRollup_ = await rollup.read.archive();
expect(hexStringToBuffer(stateInRollup_.toString())).toEqual(Buffer.alloc(32, 0));

const blockNumber = await publicClient.getBlockNumber();
Expand Down Expand Up @@ -362,7 +362,7 @@ describe('L1Publisher integration', () => {
fromBlock: blockNumber + 1n,
});
expect(logs).toHaveLength(i + 1);
expect(logs[i].args.blockNum).toEqual(BigInt(i + 1));
expect(logs[i].args.blockNumber).toEqual(BigInt(i + 1));

const ethTx = await publicClient.getTransaction({
hash: logs[i].transactionHash!,
Expand All @@ -371,14 +371,19 @@ describe('L1Publisher integration', () => {
const expectedData = encodeFunctionData({
abi: RollupAbi,
functionName: 'process',
args: [`0x${l2Proof.toString('hex')}`, `0x${block.toBufferWithLogs().toString('hex')}`],
args: [
`0x${block.header.toBuffer().toString('hex')}`,
`0x${block.archive.toBuffer().toString('hex')}`,
`0x${block.bodyToBuffer().toString('hex')}`,
`0x${l2Proof.toString('hex')}`,
],
});
expect(ethTx.input).toEqual(expectedData);

const decoderArgs = [`0x${block.toBufferWithLogs().toString('hex')}`] as const;
const decodedHashes = await decoderHelper.read.computeDiffRootAndMessagesHash(decoderArgs);
const decodedRes = await decoderHelper.read.decode(decoderArgs);
const stateInRollup = await rollup.read.rollupStateHash();
const stateInRollup = await rollup.read.archive();

expect(block.number).toEqual(Number(decodedRes[0]));
expect(block.getStartStateHash()).toEqual(hexStringToBuffer(decodedRes[1].toString()));
Expand All @@ -403,7 +408,7 @@ describe('L1Publisher integration', () => {
}, 360_000);

it(`Build ${numberOfConsecutiveBlocks} blocks of 4 empty txs building on each other`, async () => {
const stateInRollup_ = await rollup.read.rollupStateHash();
const stateInRollup_ = await rollup.read.archive();
expect(hexStringToBuffer(stateInRollup_.toString())).toEqual(Buffer.alloc(32, 0));

const blockNumber = await publicClient.getBlockNumber();
Expand Down Expand Up @@ -438,7 +443,7 @@ describe('L1Publisher integration', () => {
fromBlock: blockNumber + 1n,
});
expect(logs).toHaveLength(i + 1);
expect(logs[i].args.blockNum).toEqual(BigInt(i + 1));
expect(logs[i].args.blockNumber).toEqual(BigInt(i + 1));

const ethTx = await publicClient.getTransaction({
hash: logs[i].transactionHash!,
Expand All @@ -447,14 +452,19 @@ describe('L1Publisher integration', () => {
const expectedData = encodeFunctionData({
abi: RollupAbi,
functionName: 'process',
args: [`0x${l2Proof.toString('hex')}`, `0x${block.toBufferWithLogs().toString('hex')}`],
args: [
`0x${block.header.toBuffer().toString('hex')}`,
`0x${block.archive.toBuffer().toString('hex')}`,
`0x${block.bodyToBuffer().toString('hex')}`,
`0x${l2Proof.toString('hex')}`,
],
});
expect(ethTx.input).toEqual(expectedData);

const decoderArgs = [`0x${block.toBufferWithLogs().toString('hex')}`] as const;
const decodedHashes = await decoderHelper.read.computeDiffRootAndMessagesHash(decoderArgs);
const decodedRes = await decoderHelper.read.decode(decoderArgs);
const stateInRollup = await rollup.read.rollupStateHash();
const stateInRollup = await rollup.read.archive();

expect(block.number).toEqual(Number(decodedRes[0]));
expect(block.getStartStateHash()).toEqual(hexStringToBuffer(decodedRes[1].toString()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -250,11 +250,7 @@ describe('sequencer/solo_block_builder', () => {
newUnencryptedLogs,
});

const callDataHash = l2Block.getCalldataHash();
const high = Fr.fromBuffer(callDataHash.slice(0, 16));
const low = Fr.fromBuffer(callDataHash.slice(16, 32));

rootRollupOutput.header.bodyHash = [high, low];
rootRollupOutput.header.bodyHash = l2Block.getCalldataHash();

return txs;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,11 +144,12 @@ export class SoloBlockBuilder implements BlockBuilder {
newUnencryptedLogs,
});

// TODO: update naming here
if (!l2Block.getCalldataHash().equals(circuitsOutput.header.bodyHash)) {
throw new Error(
`Calldata hash mismatch, ${l2Block.getCalldataHash().toString('hex')} == ${circuitsOutput
.sha256CalldataHash()
.toString('hex')} `,
`Calldata hash mismatch, ${l2Block
.getCalldataHash()
.toString('hex')} == ${circuitsOutput.header.bodyHash.toString('hex')} `,
);
}

Expand Down
26 changes: 15 additions & 11 deletions yarn-project/sequencer-client/src/publisher/l1-publisher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,17 +82,17 @@ export interface L1PublisherTxSender {
}

/**
* Encoded block data and proof ready to be pushed to the L1 contract.
* Encoded block and proof ready to be pushed to the L1 contract.
*/
export type L1ProcessArgs = {
/**
* Root rollup proof for an L1 block.
*/
/** The L2 block header. */
header: Buffer;
/** A snapshot (root and next available leaf index) of the archive tree after the L2 block is applied. */
archive: Buffer;
/** L2 block body. */
body: Buffer;
/** Root rollup proof of the L2 block. */
proof: Buffer;
/**
* Serialized L2Block data.
*/
inputs: Buffer;
};

/**
Expand Down Expand Up @@ -129,9 +129,12 @@ export class L1Publisher implements L2BlockReceiver {
* @returns True once the tx has been confirmed and is successful, false on revert or interrupt, blocks otherwise.
*/
public async publishL2Block(block: L2Block): Promise<boolean> {
const proof = Buffer.alloc(0);

const txData = { proof, inputs: block.toBufferWithLogs() };
const txData = {
header: block.header.toBuffer(),
archive: block.archive.toBuffer(),
body: block.bodyToBuffer(),
proof: Buffer.alloc(0),
};
const startStateHash = block.getStartStateHash();

while (!this.interrupted) {
Expand Down Expand Up @@ -243,6 +246,7 @@ export class L1Publisher implements L2BlockReceiver {
* @param startStateHash - The start state hash of the block we wish to publish.
* @returns Boolean indicating if the hashes are equal.
*/
// TODO(benesjan): rename this
private async checkStartStateHash(startStateHash: Buffer): Promise<boolean> {
const fromChain = await this.txSender.getCurrentStateHash();
const areSame = startStateHash.equals(fromChain);
Expand Down
9 changes: 7 additions & 2 deletions yarn-project/sequencer-client/src/publisher/viem-tx-sender.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ export class ViemTxSender implements L1PublisherTxSender {
}

async getCurrentStateHash(): Promise<Buffer> {
const stateHash = await this.rollupContract.read.rollupStateHash();
const stateHash = await this.rollupContract.read.archive();
return Buffer.from(stateHash.replace('0x', ''), 'hex');
}

Expand Down Expand Up @@ -122,7 +122,12 @@ export class ViemTxSender implements L1PublisherTxSender {
* @returns The hash of the mined tx.
*/
async sendProcessTx(encodedData: ProcessTxArgs): Promise<string | undefined> {
const args = [`0x${encodedData.proof.toString('hex')}`, `0x${encodedData.inputs.toString('hex')}`] as const;
const args = [
`0x${encodedData.header.toString('hex')}`,
`0x${encodedData.archive.toString('hex')}`,
`0x${encodedData.body.toString('hex')}`,
`0x${encodedData.proof.toString('hex')}`,
] as const;

const gas = await this.rollupContract.estimateGas.process(args, {
account: this.account,
Expand Down

0 comments on commit 6d4f22a

Please sign in to comment.