@aztec/sequencer-client 0.1.0-alpha11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.cjs +1 -0
- package/.tsbuildinfo +1 -0
- package/README.md +45 -0
- package/dest/block_builder/index.d.ts +19 -0
- package/dest/block_builder/index.d.ts.map +1 -0
- package/dest/block_builder/index.js +2 -0
- package/dest/block_builder/solo_block_builder.d.ts +76 -0
- package/dest/block_builder/solo_block_builder.d.ts.map +1 -0
- package/dest/block_builder/solo_block_builder.js +453 -0
- package/dest/block_builder/solo_block_builder.test.d.ts +3 -0
- package/dest/block_builder/solo_block_builder.test.d.ts.map +1 -0
- package/dest/block_builder/solo_block_builder.test.js +291 -0
- package/dest/block_builder/types.d.ts +12 -0
- package/dest/block_builder/types.d.ts.map +1 -0
- package/dest/block_builder/types.js +2 -0
- package/dest/client/index.d.ts +2 -0
- package/dest/client/index.d.ts.map +1 -0
- package/dest/client/index.js +2 -0
- package/dest/client/sequencer-client.d.ts +32 -0
- package/dest/client/sequencer-client.d.ts.map +1 -0
- package/dest/client/sequencer-client.js +47 -0
- package/dest/config.d.ts +12 -0
- package/dest/config.d.ts.map +1 -0
- package/dest/config.js +25 -0
- package/dest/global_variable_builder/config.d.ts +19 -0
- package/dest/global_variable_builder/config.d.ts.map +1 -0
- package/dest/global_variable_builder/config.js +2 -0
- package/dest/global_variable_builder/global_builder.d.ts +30 -0
- package/dest/global_variable_builder/global_builder.d.ts.map +1 -0
- package/dest/global_variable_builder/global_builder.js +24 -0
- package/dest/global_variable_builder/index.d.ts +11 -0
- package/dest/global_variable_builder/index.d.ts.map +1 -0
- package/dest/global_variable_builder/index.js +12 -0
- package/dest/global_variable_builder/viem-reader.d.ts +26 -0
- package/dest/global_variable_builder/viem-reader.d.ts.map +1 -0
- package/dest/global_variable_builder/viem-reader.js +43 -0
- package/dest/index.d.ts +11 -0
- package/dest/index.d.ts.map +1 -0
- package/dest/index.js +12 -0
- package/dest/mocks/tx.d.ts +10 -0
- package/dest/mocks/tx.d.ts.map +1 -0
- package/dest/mocks/tx.js +18 -0
- package/dest/mocks/verification_keys.d.ts +28 -0
- package/dest/mocks/verification_keys.d.ts.map +1 -0
- package/dest/mocks/verification_keys.js +14 -0
- package/dest/prover/empty.d.ts +41 -0
- package/dest/prover/empty.d.ts.map +1 -0
- package/dest/prover/empty.js +57 -0
- package/dest/prover/index.d.ts +17 -0
- package/dest/prover/index.d.ts.map +1 -0
- package/dest/prover/index.js +2 -0
- package/dest/publisher/config.d.ts +33 -0
- package/dest/publisher/config.d.ts.map +1 -0
- package/dest/publisher/config.js +2 -0
- package/dest/publisher/index.d.ts +10 -0
- package/dest/publisher/index.d.ts.map +1 -0
- package/dest/publisher/index.js +11 -0
- package/dest/publisher/l1-publisher.d.ts +99 -0
- package/dest/publisher/l1-publisher.d.ts.map +1 -0
- package/dest/publisher/l1-publisher.js +154 -0
- package/dest/publisher/l1-publisher.test.d.ts +2 -0
- package/dest/publisher/l1-publisher.test.d.ts.map +1 -0
- package/dest/publisher/l1-publisher.test.js +58 -0
- package/dest/publisher/viem-tx-sender.d.ts +42 -0
- package/dest/publisher/viem-tx-sender.d.ts.map +1 -0
- package/dest/publisher/viem-tx-sender.js +115 -0
- package/dest/receiver.d.ts +13 -0
- package/dest/receiver.d.ts.map +1 -0
- package/dest/receiver.js +2 -0
- package/dest/sequencer/config.d.ts +26 -0
- package/dest/sequencer/config.d.ts.map +1 -0
- package/dest/sequencer/config.js +2 -0
- package/dest/sequencer/index.d.ts +4 -0
- package/dest/sequencer/index.d.ts.map +1 -0
- package/dest/sequencer/index.js +4 -0
- package/dest/sequencer/processed_tx.d.ts +34 -0
- package/dest/sequencer/processed_tx.d.ts.map +1 -0
- package/dest/sequencer/processed_tx.js +39 -0
- package/dest/sequencer/public_processor.d.ts +68 -0
- package/dest/sequencer/public_processor.d.ts.map +1 -0
- package/dest/sequencer/public_processor.js +195 -0
- package/dest/sequencer/public_processor.test.d.ts +2 -0
- package/dest/sequencer/public_processor.test.d.ts.map +1 -0
- package/dest/sequencer/public_processor.test.js +159 -0
- package/dest/sequencer/sequencer.d.ts +133 -0
- package/dest/sequencer/sequencer.d.ts.map +1 -0
- package/dest/sequencer/sequencer.js +293 -0
- package/dest/sequencer/sequencer.test.d.ts +2 -0
- package/dest/sequencer/sequencer.test.d.ts.map +1 -0
- package/dest/sequencer/sequencer.test.js +100 -0
- package/dest/sequencer/utils.d.ts +7 -0
- package/dest/sequencer/utils.d.ts.map +1 -0
- package/dest/sequencer/utils.js +9 -0
- package/dest/simulator/index.d.ts +42 -0
- package/dest/simulator/index.d.ts.map +1 -0
- package/dest/simulator/index.js +2 -0
- package/dest/simulator/public_executor.d.ts +39 -0
- package/dest/simulator/public_executor.d.ts.map +1 -0
- package/dest/simulator/public_executor.js +118 -0
- package/dest/simulator/public_kernel.d.ts +20 -0
- package/dest/simulator/public_kernel.d.ts.map +1 -0
- package/dest/simulator/public_kernel.js +27 -0
- package/dest/simulator/rollup.d.ts +33 -0
- package/dest/simulator/rollup.d.ts.map +1 -0
- package/dest/simulator/rollup.js +41 -0
- package/dest/utils.d.ts +12 -0
- package/dest/utils.d.ts.map +1 -0
- package/dest/utils.js +16 -0
- package/jest.integration.config.json +13 -0
- package/package.json +23 -0
- package/src/block_builder/index.ts +23 -0
- package/src/block_builder/solo_block_builder.test.ts +425 -0
- package/src/block_builder/solo_block_builder.ts +710 -0
- package/src/block_builder/types.ts +16 -0
- package/src/client/index.ts +1 -0
- package/src/client/sequencer-client.ts +79 -0
- package/src/config.ts +48 -0
- package/src/global_variable_builder/config.ts +19 -0
- package/src/global_variable_builder/global_builder.ts +43 -0
- package/src/global_variable_builder/index.ts +15 -0
- package/src/global_variable_builder/viem-reader.ts +63 -0
- package/src/index.ts +12 -0
- package/src/mocks/tx.ts +26 -0
- package/src/mocks/verification_keys.ts +36 -0
- package/src/prover/empty.ts +73 -0
- package/src/prover/index.ts +27 -0
- package/src/publisher/config.ts +36 -0
- package/src/publisher/index.ts +14 -0
- package/src/publisher/l1-publisher.test.ts +77 -0
- package/src/publisher/l1-publisher.ts +236 -0
- package/src/publisher/viem-tx-sender.ts +166 -0
- package/src/receiver.ts +13 -0
- package/src/sequencer/config.ts +27 -0
- package/src/sequencer/index.ts +3 -0
- package/src/sequencer/processed_tx.ts +82 -0
- package/src/sequencer/public_processor.test.ts +225 -0
- package/src/sequencer/public_processor.ts +280 -0
- package/src/sequencer/sequencer.test.ts +158 -0
- package/src/sequencer/sequencer.ts +356 -0
- package/src/sequencer/utils.ts +18 -0
- package/src/simulator/index.ts +51 -0
- package/src/simulator/public_executor.ts +137 -0
- package/src/simulator/public_kernel.ts +27 -0
- package/src/simulator/rollup.ts +54 -0
- package/src/utils.ts +16 -0
- package/tsconfig.json +38 -0
|
@@ -0,0 +1,425 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AppendOnlyTreeSnapshot,
|
|
3
|
+
BaseOrMergeRollupPublicInputs,
|
|
4
|
+
BaseRollupInputs,
|
|
5
|
+
CircuitsWasm,
|
|
6
|
+
Fr,
|
|
7
|
+
GlobalVariables,
|
|
8
|
+
KERNEL_NEW_COMMITMENTS_LENGTH,
|
|
9
|
+
KERNEL_NEW_L2_TO_L1_MSGS_LENGTH,
|
|
10
|
+
KERNEL_NEW_NULLIFIERS_LENGTH,
|
|
11
|
+
KERNEL_PUBLIC_CALL_STACK_LENGTH,
|
|
12
|
+
KERNEL_PUBLIC_DATA_UPDATE_REQUESTS_LENGTH,
|
|
13
|
+
KernelCircuitPublicInputs,
|
|
14
|
+
NULLIFIER_TREE_HEIGHT,
|
|
15
|
+
NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP,
|
|
16
|
+
Proof,
|
|
17
|
+
PublicDataUpdateRequest,
|
|
18
|
+
RootRollupPublicInputs,
|
|
19
|
+
makeTuple,
|
|
20
|
+
range,
|
|
21
|
+
} from '@aztec/circuits.js';
|
|
22
|
+
import { computeContractLeaf } from '@aztec/circuits.js/abis';
|
|
23
|
+
import {
|
|
24
|
+
fr,
|
|
25
|
+
makeBaseOrMergeRollupPublicInputs,
|
|
26
|
+
makeKernelPublicInputs,
|
|
27
|
+
makeNewContractData,
|
|
28
|
+
makeProof,
|
|
29
|
+
makePublicCallRequest,
|
|
30
|
+
makeRootRollupPublicInputs,
|
|
31
|
+
} from '@aztec/circuits.js/factories';
|
|
32
|
+
import { toBufferBE } from '@aztec/foundation/bigint-buffer';
|
|
33
|
+
import { ContractData, L2Block, L2BlockL2Logs, MerkleTreeId, PublicDataWrite, Tx, TxL2Logs } from '@aztec/types';
|
|
34
|
+
import { MerkleTreeOperations, MerkleTrees } from '@aztec/world-state';
|
|
35
|
+
import { MockProxy, mock } from 'jest-mock-extended';
|
|
36
|
+
import { default as levelup } from 'levelup';
|
|
37
|
+
import flatMap from 'lodash.flatmap';
|
|
38
|
+
import times from 'lodash.times';
|
|
39
|
+
import { default as memdown, type MemDown } from 'memdown';
|
|
40
|
+
import { makeEmptyLogs, makeTx } from '../mocks/tx.js';
|
|
41
|
+
import { VerificationKeys, getVerificationKeys } from '../mocks/verification_keys.js';
|
|
42
|
+
import { EmptyRollupProver } from '../prover/empty.js';
|
|
43
|
+
import { RollupProver } from '../prover/index.js';
|
|
44
|
+
import {
|
|
45
|
+
ProcessedTx,
|
|
46
|
+
makeEmptyProcessedTx as makeEmptyProcessedTxFromHistoricTreeRoots,
|
|
47
|
+
makeProcessedTx,
|
|
48
|
+
} from '../sequencer/processed_tx.js';
|
|
49
|
+
import { getCombinedHistoricTreeRoots } from '../sequencer/utils.js';
|
|
50
|
+
import { RollupSimulator } from '../simulator/index.js';
|
|
51
|
+
import { WasmRollupCircuitSimulator } from '../simulator/rollup.js';
|
|
52
|
+
import { SoloBlockBuilder } from './solo_block_builder.js';
|
|
53
|
+
import { to2Fields } from '@aztec/foundation/serialize';
|
|
54
|
+
|
|
55
|
+
export const createMemDown = () => (memdown as any)() as MemDown<any, any>;
|
|
56
|
+
|
|
57
|
+
describe('sequencer/solo_block_builder', () => {
|
|
58
|
+
let builder: SoloBlockBuilder;
|
|
59
|
+
let builderDb: MerkleTreeOperations;
|
|
60
|
+
let expectsDb: MerkleTreeOperations;
|
|
61
|
+
let vks: VerificationKeys;
|
|
62
|
+
|
|
63
|
+
let simulator: MockProxy<RollupSimulator>;
|
|
64
|
+
let prover: MockProxy<RollupProver>;
|
|
65
|
+
|
|
66
|
+
let blockNumber: number;
|
|
67
|
+
let baseRollupOutputLeft: BaseOrMergeRollupPublicInputs;
|
|
68
|
+
let baseRollupOutputRight: BaseOrMergeRollupPublicInputs;
|
|
69
|
+
let rootRollupOutput: RootRollupPublicInputs;
|
|
70
|
+
let mockL1ToL2Messages: Fr[];
|
|
71
|
+
|
|
72
|
+
let wasm: CircuitsWasm;
|
|
73
|
+
|
|
74
|
+
let globalVariables: GlobalVariables;
|
|
75
|
+
|
|
76
|
+
const emptyProof = new Proof(Buffer.alloc(32, 0));
|
|
77
|
+
|
|
78
|
+
const chainId = Fr.ZERO;
|
|
79
|
+
const version = Fr.ZERO;
|
|
80
|
+
|
|
81
|
+
beforeAll(async () => {
|
|
82
|
+
wasm = await CircuitsWasm.get();
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
beforeEach(async () => {
|
|
86
|
+
blockNumber = 3;
|
|
87
|
+
globalVariables = new GlobalVariables(chainId, version, new Fr(blockNumber), Fr.ZERO);
|
|
88
|
+
|
|
89
|
+
builderDb = await MerkleTrees.new(levelup(createMemDown())).then(t => t.asLatest());
|
|
90
|
+
expectsDb = await MerkleTrees.new(levelup(createMemDown())).then(t => t.asLatest());
|
|
91
|
+
vks = getVerificationKeys();
|
|
92
|
+
simulator = mock<RollupSimulator>();
|
|
93
|
+
prover = mock<RollupProver>();
|
|
94
|
+
builder = new SoloBlockBuilder(builderDb, vks, simulator, prover);
|
|
95
|
+
|
|
96
|
+
// Create mock l1 to L2 messages
|
|
97
|
+
mockL1ToL2Messages = new Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(new Fr(0n));
|
|
98
|
+
|
|
99
|
+
// Create mock outputs for simulator
|
|
100
|
+
baseRollupOutputLeft = makeBaseOrMergeRollupPublicInputs();
|
|
101
|
+
baseRollupOutputRight = makeBaseOrMergeRollupPublicInputs();
|
|
102
|
+
rootRollupOutput = makeRootRollupPublicInputs();
|
|
103
|
+
|
|
104
|
+
// Set up mocks
|
|
105
|
+
prover.getBaseRollupProof.mockResolvedValue(emptyProof);
|
|
106
|
+
prover.getRootRollupProof.mockResolvedValue(emptyProof);
|
|
107
|
+
simulator.baseRollupCircuit
|
|
108
|
+
.mockResolvedValueOnce(baseRollupOutputLeft)
|
|
109
|
+
.mockResolvedValueOnce(baseRollupOutputRight);
|
|
110
|
+
simulator.rootRollupCircuit.mockResolvedValue(rootRollupOutput);
|
|
111
|
+
}, 20_000);
|
|
112
|
+
|
|
113
|
+
const makeEmptyProcessedTx = async () => {
|
|
114
|
+
const historicTreeRoots = await getCombinedHistoricTreeRoots(builderDb);
|
|
115
|
+
return makeEmptyProcessedTxFromHistoricTreeRoots(historicTreeRoots, chainId, version);
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
// Updates the expectedDb trees based on the new commitments, contracts, and nullifiers from these txs
|
|
119
|
+
const updateExpectedTreesFromTxs = async (txs: ProcessedTx[]) => {
|
|
120
|
+
const newContracts = flatMap(txs, tx => tx.data.end.newContracts.map(n => computeContractLeaf(wasm, n)));
|
|
121
|
+
for (const [tree, leaves] of [
|
|
122
|
+
[MerkleTreeId.PRIVATE_DATA_TREE, flatMap(txs, tx => tx.data.end.newCommitments.map(l => l.toBuffer()))],
|
|
123
|
+
[MerkleTreeId.CONTRACT_TREE, newContracts.map(x => x.toBuffer())],
|
|
124
|
+
[MerkleTreeId.NULLIFIER_TREE, flatMap(txs, tx => tx.data.end.newNullifiers.map(x => x.toBuffer()))],
|
|
125
|
+
] as const) {
|
|
126
|
+
await expectsDb.appendLeaves(tree, leaves);
|
|
127
|
+
}
|
|
128
|
+
for (const write of txs.flatMap(tx => tx.data.end.publicDataUpdateRequests)) {
|
|
129
|
+
await expectsDb.updateLeaf(MerkleTreeId.PUBLIC_DATA_TREE, write.newValue.toBuffer(), write.leafIndex.value);
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
const updateL1ToL2MessagesTree = async (l1ToL2Messages: Fr[]) => {
|
|
134
|
+
const asBuffer = l1ToL2Messages.map(m => m.toBuffer());
|
|
135
|
+
await expectsDb.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGES_TREE, asBuffer);
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
const getTreeSnapshot = async (tree: MerkleTreeId) => {
|
|
139
|
+
const treeInfo = await expectsDb.getTreeInfo(tree);
|
|
140
|
+
return new AppendOnlyTreeSnapshot(Fr.fromBuffer(treeInfo.root), Number(treeInfo.size));
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
const buildMockSimulatorInputs = async () => {
|
|
144
|
+
const kernelOutput = makeKernelPublicInputs();
|
|
145
|
+
kernelOutput.constants.historicTreeRoots = await getCombinedHistoricTreeRoots(expectsDb);
|
|
146
|
+
|
|
147
|
+
const tx = await makeProcessedTx(
|
|
148
|
+
new Tx(
|
|
149
|
+
kernelOutput,
|
|
150
|
+
emptyProof,
|
|
151
|
+
makeEmptyLogs(),
|
|
152
|
+
makeEmptyLogs(),
|
|
153
|
+
[],
|
|
154
|
+
times(KERNEL_PUBLIC_CALL_STACK_LENGTH, makePublicCallRequest),
|
|
155
|
+
),
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
const txsLeft = [tx, await makeEmptyProcessedTx()];
|
|
159
|
+
const txsRight = [await makeEmptyProcessedTx(), await makeEmptyProcessedTx()];
|
|
160
|
+
|
|
161
|
+
// Calculate what would be the tree roots after the txs from the first base rollup land and update mock circuit output
|
|
162
|
+
await updateExpectedTreesFromTxs(txsLeft);
|
|
163
|
+
baseRollupOutputLeft.endContractTreeSnapshot = await getTreeSnapshot(MerkleTreeId.CONTRACT_TREE);
|
|
164
|
+
baseRollupOutputLeft.endNullifierTreeSnapshot = await getTreeSnapshot(MerkleTreeId.NULLIFIER_TREE);
|
|
165
|
+
baseRollupOutputLeft.endPrivateDataTreeSnapshot = await getTreeSnapshot(MerkleTreeId.PRIVATE_DATA_TREE);
|
|
166
|
+
baseRollupOutputLeft.endPublicDataTreeRoot = (await getTreeSnapshot(MerkleTreeId.PUBLIC_DATA_TREE)).root;
|
|
167
|
+
|
|
168
|
+
// Same for the two txs on the right
|
|
169
|
+
await updateExpectedTreesFromTxs(txsRight);
|
|
170
|
+
baseRollupOutputRight.endContractTreeSnapshot = await getTreeSnapshot(MerkleTreeId.CONTRACT_TREE);
|
|
171
|
+
baseRollupOutputRight.endNullifierTreeSnapshot = await getTreeSnapshot(MerkleTreeId.NULLIFIER_TREE);
|
|
172
|
+
baseRollupOutputRight.endPrivateDataTreeSnapshot = await getTreeSnapshot(MerkleTreeId.PRIVATE_DATA_TREE);
|
|
173
|
+
baseRollupOutputRight.endPublicDataTreeRoot = (await getTreeSnapshot(MerkleTreeId.PUBLIC_DATA_TREE)).root;
|
|
174
|
+
|
|
175
|
+
// Update l1 to l2 data tree
|
|
176
|
+
// And update the root trees now to create proper output to the root rollup circuit
|
|
177
|
+
await updateL1ToL2MessagesTree(mockL1ToL2Messages);
|
|
178
|
+
await expectsDb.updateHistoricRootsTrees();
|
|
179
|
+
rootRollupOutput.endContractTreeSnapshot = await getTreeSnapshot(MerkleTreeId.CONTRACT_TREE);
|
|
180
|
+
rootRollupOutput.endNullifierTreeSnapshot = await getTreeSnapshot(MerkleTreeId.NULLIFIER_TREE);
|
|
181
|
+
rootRollupOutput.endPrivateDataTreeSnapshot = await getTreeSnapshot(MerkleTreeId.PRIVATE_DATA_TREE);
|
|
182
|
+
rootRollupOutput.endPublicDataTreeRoot = (await getTreeSnapshot(MerkleTreeId.PUBLIC_DATA_TREE)).root;
|
|
183
|
+
rootRollupOutput.endTreeOfHistoricContractTreeRootsSnapshot = await getTreeSnapshot(
|
|
184
|
+
MerkleTreeId.CONTRACT_TREE_ROOTS_TREE,
|
|
185
|
+
);
|
|
186
|
+
rootRollupOutput.endTreeOfHistoricPrivateDataTreeRootsSnapshot = await getTreeSnapshot(
|
|
187
|
+
MerkleTreeId.PRIVATE_DATA_TREE_ROOTS_TREE,
|
|
188
|
+
);
|
|
189
|
+
rootRollupOutput.endL1ToL2MessageTreeSnapshot = await getTreeSnapshot(MerkleTreeId.L1_TO_L2_MESSAGES_TREE);
|
|
190
|
+
rootRollupOutput.endTreeOfHistoricL1ToL2MessageTreeRootsSnapshot = await getTreeSnapshot(
|
|
191
|
+
MerkleTreeId.L1_TO_L2_MESSAGES_ROOTS_TREE,
|
|
192
|
+
);
|
|
193
|
+
|
|
194
|
+
const txs = [...txsLeft, ...txsRight];
|
|
195
|
+
|
|
196
|
+
const newNullifiers = flatMap(txs, tx => tx.data.end.newNullifiers);
|
|
197
|
+
const newCommitments = flatMap(txs, tx => tx.data.end.newCommitments);
|
|
198
|
+
const newContracts = flatMap(txs, tx => tx.data.end.newContracts).map(cd => computeContractLeaf(wasm, cd));
|
|
199
|
+
const newContractData = flatMap(txs, tx => tx.data.end.newContracts).map(
|
|
200
|
+
n => new ContractData(n.contractAddress, n.portalContractAddress),
|
|
201
|
+
);
|
|
202
|
+
const newPublicDataWrites = flatMap(txs, tx =>
|
|
203
|
+
tx.data.end.publicDataUpdateRequests.map(t => new PublicDataWrite(t.leafIndex, t.newValue)),
|
|
204
|
+
);
|
|
205
|
+
const newL2ToL1Msgs = flatMap(txs, tx => tx.data.end.newL2ToL1Msgs);
|
|
206
|
+
const newEncryptedLogs = new L2BlockL2Logs(txs.map(tx => tx.encryptedLogs || new TxL2Logs([])));
|
|
207
|
+
const newUnencryptedLogs = new L2BlockL2Logs(txs.map(tx => tx.unencryptedLogs || new TxL2Logs([])));
|
|
208
|
+
|
|
209
|
+
const l2Block = L2Block.fromFields({
|
|
210
|
+
number: blockNumber,
|
|
211
|
+
globalVariables: rootRollupOutput.globalVariables,
|
|
212
|
+
startPrivateDataTreeSnapshot: rootRollupOutput.startPrivateDataTreeSnapshot,
|
|
213
|
+
endPrivateDataTreeSnapshot: rootRollupOutput.endPrivateDataTreeSnapshot,
|
|
214
|
+
startNullifierTreeSnapshot: rootRollupOutput.startNullifierTreeSnapshot,
|
|
215
|
+
endNullifierTreeSnapshot: rootRollupOutput.endNullifierTreeSnapshot,
|
|
216
|
+
startContractTreeSnapshot: rootRollupOutput.startContractTreeSnapshot,
|
|
217
|
+
endContractTreeSnapshot: rootRollupOutput.endContractTreeSnapshot,
|
|
218
|
+
startPublicDataTreeRoot: rootRollupOutput.startPublicDataTreeRoot,
|
|
219
|
+
endPublicDataTreeRoot: rootRollupOutput.endPublicDataTreeRoot,
|
|
220
|
+
startTreeOfHistoricPrivateDataTreeRootsSnapshot: rootRollupOutput.startTreeOfHistoricPrivateDataTreeRootsSnapshot,
|
|
221
|
+
endTreeOfHistoricPrivateDataTreeRootsSnapshot: rootRollupOutput.endTreeOfHistoricPrivateDataTreeRootsSnapshot,
|
|
222
|
+
startTreeOfHistoricContractTreeRootsSnapshot: rootRollupOutput.startTreeOfHistoricContractTreeRootsSnapshot,
|
|
223
|
+
endTreeOfHistoricContractTreeRootsSnapshot: rootRollupOutput.endTreeOfHistoricContractTreeRootsSnapshot,
|
|
224
|
+
startL1ToL2MessageTreeSnapshot: rootRollupOutput.startL1ToL2MessageTreeSnapshot,
|
|
225
|
+
endL1ToL2MessageTreeSnapshot: rootRollupOutput.endL1ToL2MessageTreeSnapshot,
|
|
226
|
+
startTreeOfHistoricL1ToL2MessageTreeRootsSnapshot:
|
|
227
|
+
rootRollupOutput.startTreeOfHistoricL1ToL2MessageTreeRootsSnapshot,
|
|
228
|
+
endTreeOfHistoricL1ToL2MessageTreeRootsSnapshot: rootRollupOutput.endTreeOfHistoricL1ToL2MessageTreeRootsSnapshot,
|
|
229
|
+
newCommitments,
|
|
230
|
+
newNullifiers,
|
|
231
|
+
newContracts,
|
|
232
|
+
newContractData,
|
|
233
|
+
newPublicDataWrites,
|
|
234
|
+
newL1ToL2Messages: mockL1ToL2Messages,
|
|
235
|
+
newL2ToL1Msgs,
|
|
236
|
+
newEncryptedLogs,
|
|
237
|
+
newUnencryptedLogs,
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
const callDataHash = l2Block.getCalldataHash();
|
|
241
|
+
const high = Fr.fromBuffer(callDataHash.slice(0, 16));
|
|
242
|
+
const low = Fr.fromBuffer(callDataHash.slice(16, 32));
|
|
243
|
+
|
|
244
|
+
rootRollupOutput.calldataHash = [high, low];
|
|
245
|
+
|
|
246
|
+
return txs;
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
describe('mock simulator', () => {
|
|
250
|
+
beforeEach(() => {
|
|
251
|
+
// Create instance to test
|
|
252
|
+
builder = new SoloBlockBuilder(builderDb, vks, simulator, prover);
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
it('builds an L2 block using mock simulator', async () => {
|
|
256
|
+
// Assemble a fake transaction
|
|
257
|
+
const txs = await buildMockSimulatorInputs();
|
|
258
|
+
|
|
259
|
+
// Actually build a block!
|
|
260
|
+
const [l2Block, proof] = await builder.buildL2Block(globalVariables, txs, mockL1ToL2Messages);
|
|
261
|
+
|
|
262
|
+
expect(l2Block.number).toEqual(blockNumber);
|
|
263
|
+
expect(proof).toEqual(emptyProof);
|
|
264
|
+
}, 20000);
|
|
265
|
+
|
|
266
|
+
// For varying orders of insertions assert the local batch insertion generator creates the correct proofs
|
|
267
|
+
it.each([
|
|
268
|
+
// These are arbitrary but it needs to be higher than the constant `INITIAL_NULLIFIER_TREE_SIZE` and `KERNEL_NEW_NULLIFIERS_LENGTH * 2`
|
|
269
|
+
[[1003, 1002, 1001, 1000, 0, 0, 0, 0]],
|
|
270
|
+
[[1003, 1004, 1005, 1006, 0, 0, 0, 0]],
|
|
271
|
+
[[1234, 1098, 0, 0, 99999, 1096, 1054, 0]],
|
|
272
|
+
[[1970, 1980, 1040, 0, 99999, 1880, 100001, 9000000]],
|
|
273
|
+
] as const)('performs nullifier tree batch insertion correctly', async nullifiers => {
|
|
274
|
+
const leaves = nullifiers.map(i => toBufferBE(BigInt(i), 32));
|
|
275
|
+
await expectsDb.appendLeaves(MerkleTreeId.NULLIFIER_TREE, leaves);
|
|
276
|
+
|
|
277
|
+
await builderDb.batchInsert(
|
|
278
|
+
MerkleTreeId.NULLIFIER_TREE,
|
|
279
|
+
leaves,
|
|
280
|
+
NULLIFIER_TREE_HEIGHT,
|
|
281
|
+
BaseRollupInputs.NULLIFIER_SUBTREE_HEIGHT,
|
|
282
|
+
);
|
|
283
|
+
|
|
284
|
+
const expected = await expectsDb.getTreeInfo(MerkleTreeId.NULLIFIER_TREE);
|
|
285
|
+
const actual = await builderDb.getTreeInfo(MerkleTreeId.NULLIFIER_TREE);
|
|
286
|
+
expect(actual).toEqual(expected);
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
it('rejects if too many l1 to l2 messages are provided', async () => {
|
|
290
|
+
// Assemble a fake transaction
|
|
291
|
+
const txs = await buildMockSimulatorInputs();
|
|
292
|
+
const l1ToL2Messages = new Array(100).fill(new Fr(0n));
|
|
293
|
+
await expect(builder.buildL2Block(globalVariables, txs, l1ToL2Messages)).rejects.toThrow();
|
|
294
|
+
});
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
describe('circuits simulator', () => {
|
|
298
|
+
beforeEach(async () => {
|
|
299
|
+
const simulator = await WasmRollupCircuitSimulator.new();
|
|
300
|
+
const prover = new EmptyRollupProver();
|
|
301
|
+
builder = new SoloBlockBuilder(builderDb, vks, simulator, prover);
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
const makeContractDeployProcessedTx = async (seed = 0x1) => {
|
|
305
|
+
const tx = await makeEmptyProcessedTx();
|
|
306
|
+
tx.data.end.newContracts = [makeNewContractData(seed + 0x1000)];
|
|
307
|
+
return tx;
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
const makeBloatedProcessedTx = async (seed = 0x1) => {
|
|
311
|
+
const tx = makeTx(seed);
|
|
312
|
+
const kernelOutput = KernelCircuitPublicInputs.empty();
|
|
313
|
+
kernelOutput.constants.historicTreeRoots = await getCombinedHistoricTreeRoots(builderDb);
|
|
314
|
+
kernelOutput.end.publicDataUpdateRequests = makeTuple(
|
|
315
|
+
KERNEL_PUBLIC_DATA_UPDATE_REQUESTS_LENGTH,
|
|
316
|
+
i => new PublicDataUpdateRequest(fr(i), fr(0), fr(i + 10)),
|
|
317
|
+
seed + 0x500,
|
|
318
|
+
);
|
|
319
|
+
|
|
320
|
+
const processedTx = await makeProcessedTx(tx, kernelOutput, makeProof());
|
|
321
|
+
|
|
322
|
+
processedTx.data.end.newCommitments = makeTuple(KERNEL_NEW_COMMITMENTS_LENGTH, fr, seed + 0x100);
|
|
323
|
+
processedTx.data.end.newNullifiers = makeTuple(KERNEL_NEW_NULLIFIERS_LENGTH, fr, seed + 0x200);
|
|
324
|
+
processedTx.data.end.newNullifiers[tx.data.end.newNullifiers.length - 1] = Fr.ZERO;
|
|
325
|
+
processedTx.data.end.newL2ToL1Msgs = makeTuple(KERNEL_NEW_L2_TO_L1_MSGS_LENGTH, fr, seed + 0x300);
|
|
326
|
+
processedTx.data.end.newContracts = [makeNewContractData(seed + 0x1000)];
|
|
327
|
+
processedTx.data.end.encryptedLogsHash = to2Fields(L2Block.computeKernelLogsHash(processedTx.encryptedLogs));
|
|
328
|
+
processedTx.data.end.unencryptedLogsHash = to2Fields(L2Block.computeKernelLogsHash(processedTx.unencryptedLogs));
|
|
329
|
+
|
|
330
|
+
return processedTx;
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
it.each([
|
|
334
|
+
[0, 4],
|
|
335
|
+
[1, 4],
|
|
336
|
+
[4, 4],
|
|
337
|
+
[0, 16],
|
|
338
|
+
[16, 16],
|
|
339
|
+
] as const)(
|
|
340
|
+
'builds an L2 block with %i contract deploy txs and %i txs total',
|
|
341
|
+
async (deployCount: number, totalCount: number) => {
|
|
342
|
+
const contractTreeBefore = await builderDb.getTreeInfo(MerkleTreeId.CONTRACT_TREE);
|
|
343
|
+
|
|
344
|
+
const txs = [
|
|
345
|
+
...(await Promise.all(times(deployCount, makeContractDeployProcessedTx))),
|
|
346
|
+
...(await Promise.all(times(totalCount - deployCount, makeEmptyProcessedTx))),
|
|
347
|
+
];
|
|
348
|
+
|
|
349
|
+
const [l2Block] = await builder.buildL2Block(globalVariables, txs, mockL1ToL2Messages);
|
|
350
|
+
expect(l2Block.number).toEqual(blockNumber);
|
|
351
|
+
|
|
352
|
+
await updateExpectedTreesFromTxs(txs);
|
|
353
|
+
const contractTreeAfter = await builderDb.getTreeInfo(MerkleTreeId.CONTRACT_TREE);
|
|
354
|
+
|
|
355
|
+
if (deployCount > 0) {
|
|
356
|
+
expect(contractTreeAfter.root).not.toEqual(contractTreeBefore.root);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
const expectedContractTreeAfter = await expectsDb.getTreeInfo(MerkleTreeId.CONTRACT_TREE).then(t => t.root);
|
|
360
|
+
expect(contractTreeAfter.root).toEqual(expectedContractTreeAfter);
|
|
361
|
+
expect(contractTreeAfter.size).toEqual(BigInt(totalCount));
|
|
362
|
+
},
|
|
363
|
+
10000,
|
|
364
|
+
);
|
|
365
|
+
|
|
366
|
+
it('builds an empty L2 block', async () => {
|
|
367
|
+
const txs = await Promise.all([
|
|
368
|
+
makeEmptyProcessedTx(),
|
|
369
|
+
makeEmptyProcessedTx(),
|
|
370
|
+
makeEmptyProcessedTx(),
|
|
371
|
+
makeEmptyProcessedTx(),
|
|
372
|
+
]);
|
|
373
|
+
|
|
374
|
+
const [l2Block] = await builder.buildL2Block(globalVariables, txs, mockL1ToL2Messages);
|
|
375
|
+
expect(l2Block.number).toEqual(blockNumber);
|
|
376
|
+
}, 10_000);
|
|
377
|
+
|
|
378
|
+
it('builds a mixed L2 block', async () => {
|
|
379
|
+
const txs = await Promise.all([
|
|
380
|
+
makeBloatedProcessedTx(32),
|
|
381
|
+
makeBloatedProcessedTx(64),
|
|
382
|
+
makeBloatedProcessedTx(96),
|
|
383
|
+
makeBloatedProcessedTx(128),
|
|
384
|
+
]);
|
|
385
|
+
|
|
386
|
+
const l1ToL2Messages = range(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, 1 + 0x400).map(fr);
|
|
387
|
+
|
|
388
|
+
const [l2Block] = await builder.buildL2Block(globalVariables, txs, l1ToL2Messages);
|
|
389
|
+
expect(l2Block.number).toEqual(blockNumber);
|
|
390
|
+
}, 20_000);
|
|
391
|
+
|
|
392
|
+
// This test specifically tests nullifier values which previously caused e2e_zk_token test to fail
|
|
393
|
+
it('e2e_zk_token edge case regression test on nullifier values', async () => {
|
|
394
|
+
const simulator = await WasmRollupCircuitSimulator.new();
|
|
395
|
+
const prover = new EmptyRollupProver();
|
|
396
|
+
builder = new SoloBlockBuilder(builderDb, vks, simulator, prover);
|
|
397
|
+
// update the starting tree
|
|
398
|
+
const updateVals = Array(4 * KERNEL_NEW_NULLIFIERS_LENGTH).fill(0n);
|
|
399
|
+
updateVals[0] = 19777494491628650244807463906174285795660759352776418619064841306523677458742n;
|
|
400
|
+
updateVals[1] = 10246291467305176436335175657884940686778521321101740385288169037814567547848n;
|
|
401
|
+
|
|
402
|
+
await builderDb.appendLeaves(
|
|
403
|
+
MerkleTreeId.NULLIFIER_TREE,
|
|
404
|
+
updateVals.map(v => toBufferBE(v, 32)),
|
|
405
|
+
);
|
|
406
|
+
|
|
407
|
+
// new added values
|
|
408
|
+
const tx = await makeEmptyProcessedTx();
|
|
409
|
+
tx.data.end.newNullifiers[0] = new Fr(
|
|
410
|
+
10336601644835972678500657502133589897705389664587188571002640950065546264856n,
|
|
411
|
+
);
|
|
412
|
+
tx.data.end.newNullifiers[1] = new Fr(
|
|
413
|
+
17490072961923661940560522096125238013953043065748521735636170028491723851741n,
|
|
414
|
+
);
|
|
415
|
+
const txs = [tx, await makeEmptyProcessedTx(), await makeEmptyProcessedTx(), await makeEmptyProcessedTx()];
|
|
416
|
+
|
|
417
|
+
const [l2Block] = await builder.buildL2Block(globalVariables, txs, mockL1ToL2Messages);
|
|
418
|
+
|
|
419
|
+
expect(l2Block.number).toEqual(blockNumber);
|
|
420
|
+
}, 10000);
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
// describe("Input guard tests", () => {
|
|
424
|
+
// })
|
|
425
|
+
});
|