@aztec/sequencer-client 0.7.9 → 0.8.6
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/README.md +1 -1
- package/dest/client/sequencer-client.d.ts +3 -3
- package/dest/client/sequencer-client.d.ts.map +1 -1
- package/dest/client/sequencer-client.js +6 -6
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +14 -7
- package/dest/global_variable_builder/config.d.ts +5 -5
- package/dest/global_variable_builder/config.d.ts.map +1 -1
- package/dest/global_variable_builder/viem-reader.js +3 -3
- package/dest/publisher/config.d.ts +6 -2
- package/dest/publisher/config.d.ts.map +1 -1
- package/dest/publisher/index.d.ts +27 -0
- package/dest/publisher/index.d.ts.map +1 -1
- package/dest/publisher/index.js +1 -1
- package/dest/publisher/l1-publisher.d.ts +26 -11
- package/dest/publisher/l1-publisher.d.ts.map +1 -1
- package/dest/publisher/l1-publisher.js +18 -4
- package/dest/publisher/viem-tx-sender.d.ts +2 -1
- package/dest/publisher/viem-tx-sender.d.ts.map +1 -1
- package/dest/publisher/viem-tx-sender.js +27 -7
- package/dest/sequencer/public_processor.d.ts +4 -2
- package/dest/sequencer/public_processor.d.ts.map +1 -1
- package/dest/sequencer/public_processor.js +11 -5
- package/dest/sequencer/sequencer.d.ts +13 -9
- package/dest/sequencer/sequencer.d.ts.map +1 -1
- package/dest/sequencer/sequencer.js +53 -34
- package/dest/simulator/index.d.ts +0 -1
- package/dest/simulator/index.d.ts.map +1 -1
- package/dest/simulator/index.js +2 -2
- package/dest/simulator/public_executor.d.ts +28 -4
- package/dest/simulator/public_executor.d.ts.map +1 -1
- package/dest/simulator/public_executor.js +46 -7
- package/dest/simulator/public_kernel.d.ts +1 -0
- package/dest/simulator/public_kernel.d.ts.map +1 -1
- package/dest/simulator/public_kernel.js +26 -5
- package/dest/simulator/rollup.d.ts +2 -8
- package/dest/simulator/rollup.d.ts.map +1 -1
- package/dest/simulator/rollup.js +37 -18
- package/package.json +70 -11
- package/src/client/sequencer-client.ts +7 -6
- package/src/config.ts +14 -5
- package/src/global_variable_builder/config.ts +6 -5
- package/src/global_variable_builder/viem-reader.ts +2 -2
- package/src/publisher/config.ts +7 -2
- package/src/publisher/index.ts +28 -0
- package/src/publisher/l1-publisher.ts +46 -13
- package/src/publisher/viem-tx-sender.ts +33 -13
- package/src/sequencer/public_processor.ts +13 -4
- package/src/sequencer/sequencer.ts +59 -45
- package/src/simulator/index.ts +0 -2
- package/src/simulator/public_executor.ts +53 -7
- package/src/simulator/public_kernel.ts +24 -4
- package/src/simulator/rollup.ts +38 -21
- package/.eslintrc.cjs +0 -1
- package/.tsbuildinfo +0 -1
- package/dest/block_builder/solo_block_builder.test.d.ts +0 -3
- package/dest/block_builder/solo_block_builder.test.d.ts.map +0 -1
- package/dest/block_builder/solo_block_builder.test.js +0 -277
- package/dest/publisher/l1-publisher.test.d.ts +0 -2
- package/dest/publisher/l1-publisher.test.d.ts.map +0 -1
- package/dest/publisher/l1-publisher.test.js +0 -58
- package/dest/sequencer/public_processor.test.d.ts +0 -2
- package/dest/sequencer/public_processor.test.d.ts.map +0 -1
- package/dest/sequencer/public_processor.test.js +0 -164
- package/dest/sequencer/sequencer.test.d.ts +0 -2
- package/dest/sequencer/sequencer.test.d.ts.map +0 -1
- package/dest/sequencer/sequencer.test.js +0 -99
- package/jest.integration.config.json +0 -13
- package/src/block_builder/solo_block_builder.test.ts +0 -425
- package/src/publisher/l1-publisher.test.ts +0 -79
- package/src/sequencer/public_processor.test.ts +0 -265
- package/src/sequencer/sequencer.test.ts +0 -160
- package/tsconfig.json +0 -38
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
import { Fr, GlobalVariables, HistoricBlockData, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, makeEmptyProof, } from '@aztec/circuits.js';
|
|
2
|
-
import { P2PClientState } from '@aztec/p2p';
|
|
3
|
-
import { L2Block, MerkleTreeId, Tx, TxHash, mockTx } from '@aztec/types';
|
|
4
|
-
import { WorldStateRunningState } from '@aztec/world-state';
|
|
5
|
-
import { mock } from 'jest-mock-extended';
|
|
6
|
-
import times from 'lodash.times';
|
|
7
|
-
import { makeEmptyProcessedTx, makeProcessedTx } from './processed_tx.js';
|
|
8
|
-
import { Sequencer } from './sequencer.js';
|
|
9
|
-
describe('sequencer', () => {
|
|
10
|
-
let publisher;
|
|
11
|
-
let globalVariableBuilder;
|
|
12
|
-
let p2p;
|
|
13
|
-
let worldState;
|
|
14
|
-
let blockBuilder;
|
|
15
|
-
let merkleTreeOps;
|
|
16
|
-
let publicProcessor;
|
|
17
|
-
let l2BlockSource;
|
|
18
|
-
let l1ToL2MessageSource;
|
|
19
|
-
let publicProcessorFactory;
|
|
20
|
-
let lastBlockNumber;
|
|
21
|
-
let sequencer;
|
|
22
|
-
const chainId = Fr.ZERO;
|
|
23
|
-
const version = Fr.ZERO;
|
|
24
|
-
beforeEach(() => {
|
|
25
|
-
lastBlockNumber = 0;
|
|
26
|
-
publisher = mock();
|
|
27
|
-
globalVariableBuilder = mock();
|
|
28
|
-
merkleTreeOps = mock();
|
|
29
|
-
blockBuilder = mock();
|
|
30
|
-
p2p = mock({
|
|
31
|
-
getStatus: () => Promise.resolve({ state: P2PClientState.IDLE, syncedToL2Block: lastBlockNumber }),
|
|
32
|
-
});
|
|
33
|
-
worldState = mock({
|
|
34
|
-
getLatest: () => merkleTreeOps,
|
|
35
|
-
status: () => Promise.resolve({ state: WorldStateRunningState.IDLE, syncedToL2Block: lastBlockNumber }),
|
|
36
|
-
});
|
|
37
|
-
publicProcessor = mock({
|
|
38
|
-
process: async (txs) => [await Promise.all(txs.map(tx => makeProcessedTx(tx))), []],
|
|
39
|
-
makeEmptyProcessedTx: () => makeEmptyProcessedTx(HistoricBlockData.empty(), chainId, version),
|
|
40
|
-
});
|
|
41
|
-
publicProcessorFactory = mock({
|
|
42
|
-
create: (_, __) => Promise.resolve(publicProcessor),
|
|
43
|
-
});
|
|
44
|
-
l2BlockSource = mock({
|
|
45
|
-
getBlockNumber: () => Promise.resolve(lastBlockNumber),
|
|
46
|
-
});
|
|
47
|
-
l1ToL2MessageSource = mock({
|
|
48
|
-
getPendingL1ToL2Messages: () => Promise.resolve(Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(Fr.ZERO)),
|
|
49
|
-
});
|
|
50
|
-
sequencer = new TestSubject(publisher, globalVariableBuilder, p2p, worldState, blockBuilder, l2BlockSource, l1ToL2MessageSource, publicProcessorFactory, {
|
|
51
|
-
chainId: Number(chainId.value),
|
|
52
|
-
version: Number(version.value),
|
|
53
|
-
});
|
|
54
|
-
});
|
|
55
|
-
it('builds a block out of a single tx', async () => {
|
|
56
|
-
const tx = mockTx();
|
|
57
|
-
const block = L2Block.random(lastBlockNumber + 1);
|
|
58
|
-
const proof = makeEmptyProof();
|
|
59
|
-
p2p.getTxs.mockResolvedValueOnce([tx]);
|
|
60
|
-
blockBuilder.buildL2Block.mockResolvedValueOnce([block, proof]);
|
|
61
|
-
publisher.processL2Block.mockResolvedValueOnce(true);
|
|
62
|
-
globalVariableBuilder.buildGlobalVariables.mockResolvedValueOnce(new GlobalVariables(chainId, version, new Fr(lastBlockNumber + 1), Fr.ZERO));
|
|
63
|
-
await sequencer.initialSync();
|
|
64
|
-
await sequencer.work();
|
|
65
|
-
const expectedTxHashes = [...(await Tx.getHashes([tx])), ...times(3, () => TxHash.ZERO)];
|
|
66
|
-
expect(blockBuilder.buildL2Block).toHaveBeenCalledWith(new GlobalVariables(chainId, version, new Fr(lastBlockNumber + 1), Fr.ZERO), expectedTxHashes.map(hash => expect.objectContaining({ hash })), Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(new Fr(0n)));
|
|
67
|
-
expect(publisher.processL2Block).toHaveBeenCalledWith(block);
|
|
68
|
-
});
|
|
69
|
-
it('builds a block out of several txs rejecting double spends', async () => {
|
|
70
|
-
const txs = [mockTx(0x10000), mockTx(0x20000), mockTx(0x30000)];
|
|
71
|
-
const doubleSpendTx = txs[1];
|
|
72
|
-
const block = L2Block.random(lastBlockNumber + 1);
|
|
73
|
-
const proof = makeEmptyProof();
|
|
74
|
-
p2p.getTxs.mockResolvedValueOnce(txs);
|
|
75
|
-
blockBuilder.buildL2Block.mockResolvedValueOnce([block, proof]);
|
|
76
|
-
publisher.processL2Block.mockResolvedValueOnce(true);
|
|
77
|
-
globalVariableBuilder.buildGlobalVariables.mockResolvedValueOnce(new GlobalVariables(chainId, version, new Fr(lastBlockNumber + 1), Fr.ZERO));
|
|
78
|
-
// We make a nullifier from tx1 a part of the nullifier tree, so it gets rejected as double spend
|
|
79
|
-
const doubleSpendNullifier = doubleSpendTx.data.end.newNullifiers[0].toBuffer();
|
|
80
|
-
merkleTreeOps.findLeafIndex.mockImplementation((treeId, value) => {
|
|
81
|
-
return Promise.resolve(treeId === MerkleTreeId.NULLIFIER_TREE && value.equals(doubleSpendNullifier) ? 1n : undefined);
|
|
82
|
-
});
|
|
83
|
-
await sequencer.initialSync();
|
|
84
|
-
await sequencer.work();
|
|
85
|
-
const expectedTxHashes = [...(await Tx.getHashes([txs[0], txs[2]])), TxHash.ZERO, TxHash.ZERO];
|
|
86
|
-
expect(blockBuilder.buildL2Block).toHaveBeenCalledWith(new GlobalVariables(chainId, version, new Fr(lastBlockNumber + 1), Fr.ZERO), expectedTxHashes.map(hash => expect.objectContaining({ hash })), Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(new Fr(0n)));
|
|
87
|
-
expect(publisher.processL2Block).toHaveBeenCalledWith(block);
|
|
88
|
-
expect(p2p.deleteTxs).toHaveBeenCalledWith([await doubleSpendTx.getTxHash()]);
|
|
89
|
-
});
|
|
90
|
-
});
|
|
91
|
-
class TestSubject extends Sequencer {
|
|
92
|
-
work() {
|
|
93
|
-
return super.work();
|
|
94
|
-
}
|
|
95
|
-
initialSync() {
|
|
96
|
-
return super.initialSync();
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VxdWVuY2VyLnRlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc2VxdWVuY2VyL3NlcXVlbmNlci50ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxFQUFFLEVBQ0YsZUFBZSxFQUNmLGlCQUFpQixFQUNqQixtQ0FBbUMsRUFDbkMsY0FBYyxHQUNmLE1BQU0sb0JBQW9CLENBQUM7QUFDNUIsT0FBTyxFQUFPLGNBQWMsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUNqRCxPQUFPLEVBQXVCLE9BQU8sRUFBaUIsWUFBWSxFQUFFLEVBQUUsRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQzdHLE9BQU8sRUFBd0Isc0JBQXNCLEVBQTBCLE1BQU0sb0JBQW9CLENBQUM7QUFFMUcsT0FBTyxFQUFhLElBQUksRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ3JELE9BQU8sS0FBSyxNQUFNLGNBQWMsQ0FBQztBQUtqQyxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsZUFBZSxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFFMUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRTNDLFFBQVEsQ0FBQyxXQUFXLEVBQUUsR0FBRyxFQUFFO0lBQ3pCLElBQUksU0FBaUMsQ0FBQztJQUN0QyxJQUFJLHFCQUF1RCxDQUFDO0lBQzVELElBQUksR0FBbUIsQ0FBQztJQUN4QixJQUFJLFVBQTZDLENBQUM7SUFDbEQsSUFBSSxZQUFxQyxDQUFDO0lBQzFDLElBQUksYUFBOEMsQ0FBQztJQUNuRCxJQUFJLGVBQTJDLENBQUM7SUFDaEQsSUFBSSxhQUF1QyxDQUFDO0lBQzVDLElBQUksbUJBQW1ELENBQUM7SUFDeEQsSUFBSSxzQkFBeUQsQ0FBQztJQUU5RCxJQUFJLGVBQXVCLENBQUM7SUFFNUIsSUFBSSxTQUFzQixDQUFDO0lBRTNCLE1BQU0sT0FBTyxHQUFHLEVBQUUsQ0FBQyxJQUFJ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
|
|
@@ -1,425 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
AppendOnlyTreeSnapshot,
|
|
3
|
-
BaseOrMergeRollupPublicInputs,
|
|
4
|
-
CircuitsWasm,
|
|
5
|
-
Fr,
|
|
6
|
-
GlobalVariables,
|
|
7
|
-
KernelCircuitPublicInputs,
|
|
8
|
-
MAX_NEW_COMMITMENTS_PER_TX,
|
|
9
|
-
MAX_NEW_L2_TO_L1_MSGS_PER_TX,
|
|
10
|
-
MAX_NEW_NULLIFIERS_PER_TX,
|
|
11
|
-
MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX,
|
|
12
|
-
MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX,
|
|
13
|
-
NULLIFIER_SUBTREE_HEIGHT,
|
|
14
|
-
NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP,
|
|
15
|
-
Proof,
|
|
16
|
-
PublicDataUpdateRequest,
|
|
17
|
-
RootRollupPublicInputs,
|
|
18
|
-
makeTuple,
|
|
19
|
-
range,
|
|
20
|
-
} from '@aztec/circuits.js';
|
|
21
|
-
import { computeBlockHashWithGlobals, computeContractLeaf } from '@aztec/circuits.js/abis';
|
|
22
|
-
import {
|
|
23
|
-
fr,
|
|
24
|
-
makeBaseOrMergeRollupPublicInputs,
|
|
25
|
-
makeNewContractData,
|
|
26
|
-
makePrivateKernelPublicInputsFinal,
|
|
27
|
-
makeProof,
|
|
28
|
-
makePublicCallRequest,
|
|
29
|
-
makeRootRollupPublicInputs,
|
|
30
|
-
} from '@aztec/circuits.js/factories';
|
|
31
|
-
import { toBufferBE } from '@aztec/foundation/bigint-buffer';
|
|
32
|
-
import { to2Fields } from '@aztec/foundation/serialize';
|
|
33
|
-
import {
|
|
34
|
-
ContractData,
|
|
35
|
-
ExtendedContractData,
|
|
36
|
-
L2Block,
|
|
37
|
-
L2BlockL2Logs,
|
|
38
|
-
MerkleTreeId,
|
|
39
|
-
PublicDataWrite,
|
|
40
|
-
Tx,
|
|
41
|
-
TxL2Logs,
|
|
42
|
-
makeEmptyLogs,
|
|
43
|
-
mockTx,
|
|
44
|
-
} from '@aztec/types';
|
|
45
|
-
import { MerkleTreeOperations, MerkleTrees } from '@aztec/world-state';
|
|
46
|
-
|
|
47
|
-
import { MockProxy, mock } from 'jest-mock-extended';
|
|
48
|
-
import { default as levelup } from 'levelup';
|
|
49
|
-
import flatMap from 'lodash.flatmap';
|
|
50
|
-
import times from 'lodash.times';
|
|
51
|
-
import { type MemDown, default as memdown } from 'memdown';
|
|
52
|
-
|
|
53
|
-
import { VerificationKeys, getVerificationKeys } from '../mocks/verification_keys.js';
|
|
54
|
-
import { EmptyRollupProver } from '../prover/empty.js';
|
|
55
|
-
import { RollupProver } from '../prover/index.js';
|
|
56
|
-
import {
|
|
57
|
-
ProcessedTx,
|
|
58
|
-
makeEmptyProcessedTx as makeEmptyProcessedTxFromHistoricTreeRoots,
|
|
59
|
-
makeProcessedTx,
|
|
60
|
-
} from '../sequencer/processed_tx.js';
|
|
61
|
-
import { getHistoricBlockData } from '../sequencer/utils.js';
|
|
62
|
-
import { RollupSimulator } from '../simulator/index.js';
|
|
63
|
-
import { WasmRollupCircuitSimulator } from '../simulator/rollup.js';
|
|
64
|
-
import { SoloBlockBuilder } from './solo_block_builder.js';
|
|
65
|
-
|
|
66
|
-
export const createMemDown = () => (memdown as any)() as MemDown<any, any>;
|
|
67
|
-
|
|
68
|
-
describe('sequencer/solo_block_builder', () => {
|
|
69
|
-
let builder: SoloBlockBuilder;
|
|
70
|
-
let builderDb: MerkleTreeOperations;
|
|
71
|
-
let expectsDb: MerkleTreeOperations;
|
|
72
|
-
let vks: VerificationKeys;
|
|
73
|
-
|
|
74
|
-
let simulator: MockProxy<RollupSimulator>;
|
|
75
|
-
let prover: MockProxy<RollupProver>;
|
|
76
|
-
|
|
77
|
-
let blockNumber: number;
|
|
78
|
-
let baseRollupOutputLeft: BaseOrMergeRollupPublicInputs;
|
|
79
|
-
let baseRollupOutputRight: BaseOrMergeRollupPublicInputs;
|
|
80
|
-
let rootRollupOutput: RootRollupPublicInputs;
|
|
81
|
-
let mockL1ToL2Messages: Fr[];
|
|
82
|
-
|
|
83
|
-
let wasm: CircuitsWasm;
|
|
84
|
-
|
|
85
|
-
let globalVariables: GlobalVariables;
|
|
86
|
-
|
|
87
|
-
const emptyProof = new Proof(Buffer.alloc(32, 0));
|
|
88
|
-
|
|
89
|
-
const chainId = Fr.ZERO;
|
|
90
|
-
const version = Fr.ZERO;
|
|
91
|
-
|
|
92
|
-
beforeAll(async () => {
|
|
93
|
-
wasm = await CircuitsWasm.get();
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
beforeEach(async () => {
|
|
97
|
-
blockNumber = 3;
|
|
98
|
-
globalVariables = new GlobalVariables(chainId, version, new Fr(blockNumber), Fr.ZERO);
|
|
99
|
-
|
|
100
|
-
builderDb = await MerkleTrees.new(levelup(createMemDown())).then(t => t.asLatest());
|
|
101
|
-
expectsDb = await MerkleTrees.new(levelup(createMemDown())).then(t => t.asLatest());
|
|
102
|
-
vks = getVerificationKeys();
|
|
103
|
-
simulator = mock<RollupSimulator>();
|
|
104
|
-
prover = mock<RollupProver>();
|
|
105
|
-
builder = new SoloBlockBuilder(builderDb, vks, simulator, prover);
|
|
106
|
-
|
|
107
|
-
// Create mock l1 to L2 messages
|
|
108
|
-
mockL1ToL2Messages = new Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(new Fr(0n));
|
|
109
|
-
|
|
110
|
-
// Create mock outputs for simulator
|
|
111
|
-
baseRollupOutputLeft = makeBaseOrMergeRollupPublicInputs(0, globalVariables);
|
|
112
|
-
baseRollupOutputRight = makeBaseOrMergeRollupPublicInputs(0, globalVariables);
|
|
113
|
-
rootRollupOutput = makeRootRollupPublicInputs(0, globalVariables);
|
|
114
|
-
|
|
115
|
-
// Set up mocks
|
|
116
|
-
prover.getBaseRollupProof.mockResolvedValue(emptyProof);
|
|
117
|
-
prover.getRootRollupProof.mockResolvedValue(emptyProof);
|
|
118
|
-
simulator.baseRollupCircuit
|
|
119
|
-
.mockResolvedValueOnce(baseRollupOutputLeft)
|
|
120
|
-
.mockResolvedValueOnce(baseRollupOutputRight);
|
|
121
|
-
simulator.rootRollupCircuit.mockResolvedValue(rootRollupOutput);
|
|
122
|
-
}, 20_000);
|
|
123
|
-
|
|
124
|
-
const makeEmptyProcessedTx = async () => {
|
|
125
|
-
const historicTreeRoots = await getHistoricBlockData(builderDb);
|
|
126
|
-
return makeEmptyProcessedTxFromHistoricTreeRoots(historicTreeRoots, chainId, version);
|
|
127
|
-
};
|
|
128
|
-
|
|
129
|
-
// Updates the expectedDb trees based on the new commitments, contracts, and nullifiers from these txs
|
|
130
|
-
const updateExpectedTreesFromTxs = async (txs: ProcessedTx[]) => {
|
|
131
|
-
const newContracts = flatMap(txs, tx => tx.data.end.newContracts.map(n => computeContractLeaf(wasm, n)));
|
|
132
|
-
for (const [tree, leaves] of [
|
|
133
|
-
[MerkleTreeId.PRIVATE_DATA_TREE, flatMap(txs, tx => tx.data.end.newCommitments.map(l => l.toBuffer()))],
|
|
134
|
-
[MerkleTreeId.CONTRACT_TREE, newContracts.map(x => x.toBuffer())],
|
|
135
|
-
] as const) {
|
|
136
|
-
await expectsDb.appendLeaves(tree, leaves);
|
|
137
|
-
}
|
|
138
|
-
await expectsDb.batchInsert(
|
|
139
|
-
MerkleTreeId.NULLIFIER_TREE,
|
|
140
|
-
flatMap(txs, tx => tx.data.end.newNullifiers.map(x => x.toBuffer())),
|
|
141
|
-
NULLIFIER_SUBTREE_HEIGHT,
|
|
142
|
-
);
|
|
143
|
-
for (const write of txs.flatMap(tx => tx.data.end.publicDataUpdateRequests)) {
|
|
144
|
-
await expectsDb.updateLeaf(MerkleTreeId.PUBLIC_DATA_TREE, write.newValue.toBuffer(), write.leafIndex.value);
|
|
145
|
-
}
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
const updateL1ToL2MessagesTree = async (l1ToL2Messages: Fr[]) => {
|
|
149
|
-
const asBuffer = l1ToL2Messages.map(m => m.toBuffer());
|
|
150
|
-
await expectsDb.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGES_TREE, asBuffer);
|
|
151
|
-
};
|
|
152
|
-
|
|
153
|
-
const updateHistoricBlocksTree = async () => {
|
|
154
|
-
const blockHash = computeBlockHashWithGlobals(
|
|
155
|
-
wasm,
|
|
156
|
-
globalVariables,
|
|
157
|
-
rootRollupOutput.endPrivateDataTreeSnapshot.root,
|
|
158
|
-
rootRollupOutput.endNullifierTreeSnapshot.root,
|
|
159
|
-
rootRollupOutput.endContractTreeSnapshot.root,
|
|
160
|
-
rootRollupOutput.endL1ToL2MessagesTreeSnapshot.root,
|
|
161
|
-
rootRollupOutput.endPublicDataTreeRoot,
|
|
162
|
-
);
|
|
163
|
-
await expectsDb.appendLeaves(MerkleTreeId.BLOCKS_TREE, [blockHash.toBuffer()]);
|
|
164
|
-
};
|
|
165
|
-
|
|
166
|
-
const getTreeSnapshot = async (tree: MerkleTreeId) => {
|
|
167
|
-
const treeInfo = await expectsDb.getTreeInfo(tree);
|
|
168
|
-
return new AppendOnlyTreeSnapshot(Fr.fromBuffer(treeInfo.root), Number(treeInfo.size));
|
|
169
|
-
};
|
|
170
|
-
|
|
171
|
-
const buildMockSimulatorInputs = async () => {
|
|
172
|
-
const kernelOutput = makePrivateKernelPublicInputsFinal();
|
|
173
|
-
kernelOutput.constants.blockData = await getHistoricBlockData(expectsDb);
|
|
174
|
-
|
|
175
|
-
const tx = await makeProcessedTx(
|
|
176
|
-
new Tx(
|
|
177
|
-
kernelOutput,
|
|
178
|
-
emptyProof,
|
|
179
|
-
makeEmptyLogs(),
|
|
180
|
-
makeEmptyLogs(),
|
|
181
|
-
times(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, makePublicCallRequest),
|
|
182
|
-
[ExtendedContractData.random()],
|
|
183
|
-
),
|
|
184
|
-
);
|
|
185
|
-
|
|
186
|
-
const txsLeft = [tx, await makeEmptyProcessedTx()];
|
|
187
|
-
const txsRight = [await makeEmptyProcessedTx(), await makeEmptyProcessedTx()];
|
|
188
|
-
|
|
189
|
-
// Calculate what would be the tree roots after the txs from the first base rollup land and update mock circuit output
|
|
190
|
-
await updateExpectedTreesFromTxs(txsLeft);
|
|
191
|
-
baseRollupOutputLeft.endContractTreeSnapshot = await getTreeSnapshot(MerkleTreeId.CONTRACT_TREE);
|
|
192
|
-
baseRollupOutputLeft.endNullifierTreeSnapshot = await getTreeSnapshot(MerkleTreeId.NULLIFIER_TREE);
|
|
193
|
-
baseRollupOutputLeft.endPrivateDataTreeSnapshot = await getTreeSnapshot(MerkleTreeId.PRIVATE_DATA_TREE);
|
|
194
|
-
baseRollupOutputLeft.endPublicDataTreeRoot = (await getTreeSnapshot(MerkleTreeId.PUBLIC_DATA_TREE)).root;
|
|
195
|
-
|
|
196
|
-
// Same for the two txs on the right
|
|
197
|
-
await updateExpectedTreesFromTxs(txsRight);
|
|
198
|
-
baseRollupOutputRight.endContractTreeSnapshot = await getTreeSnapshot(MerkleTreeId.CONTRACT_TREE);
|
|
199
|
-
baseRollupOutputRight.endNullifierTreeSnapshot = await getTreeSnapshot(MerkleTreeId.NULLIFIER_TREE);
|
|
200
|
-
baseRollupOutputRight.endPrivateDataTreeSnapshot = await getTreeSnapshot(MerkleTreeId.PRIVATE_DATA_TREE);
|
|
201
|
-
baseRollupOutputRight.endPublicDataTreeRoot = (await getTreeSnapshot(MerkleTreeId.PUBLIC_DATA_TREE)).root;
|
|
202
|
-
|
|
203
|
-
// Update l1 to l2 data tree
|
|
204
|
-
// And update the root trees now to create proper output to the root rollup circuit
|
|
205
|
-
await updateL1ToL2MessagesTree(mockL1ToL2Messages);
|
|
206
|
-
rootRollupOutput.endContractTreeSnapshot = await getTreeSnapshot(MerkleTreeId.CONTRACT_TREE);
|
|
207
|
-
rootRollupOutput.endNullifierTreeSnapshot = await getTreeSnapshot(MerkleTreeId.NULLIFIER_TREE);
|
|
208
|
-
rootRollupOutput.endPrivateDataTreeSnapshot = await getTreeSnapshot(MerkleTreeId.PRIVATE_DATA_TREE);
|
|
209
|
-
rootRollupOutput.endPublicDataTreeRoot = (await getTreeSnapshot(MerkleTreeId.PUBLIC_DATA_TREE)).root;
|
|
210
|
-
|
|
211
|
-
rootRollupOutput.endL1ToL2MessagesTreeSnapshot = await getTreeSnapshot(MerkleTreeId.L1_TO_L2_MESSAGES_TREE);
|
|
212
|
-
|
|
213
|
-
// Calculate block hash
|
|
214
|
-
rootRollupOutput.globalVariables = globalVariables;
|
|
215
|
-
await updateHistoricBlocksTree();
|
|
216
|
-
rootRollupOutput.endHistoricBlocksTreeSnapshot = await getTreeSnapshot(MerkleTreeId.BLOCKS_TREE);
|
|
217
|
-
|
|
218
|
-
const txs = [...txsLeft, ...txsRight];
|
|
219
|
-
|
|
220
|
-
const newNullifiers = flatMap(txs, tx => tx.data.end.newNullifiers);
|
|
221
|
-
const newCommitments = flatMap(txs, tx => tx.data.end.newCommitments);
|
|
222
|
-
const newContracts = flatMap(txs, tx => tx.data.end.newContracts).map(cd => computeContractLeaf(wasm, cd));
|
|
223
|
-
const newContractData = flatMap(txs, tx => tx.data.end.newContracts).map(
|
|
224
|
-
n => new ContractData(n.contractAddress, n.portalContractAddress),
|
|
225
|
-
);
|
|
226
|
-
const newPublicDataWrites = flatMap(txs, tx =>
|
|
227
|
-
tx.data.end.publicDataUpdateRequests.map(t => new PublicDataWrite(t.leafIndex, t.newValue)),
|
|
228
|
-
);
|
|
229
|
-
const newL2ToL1Msgs = flatMap(txs, tx => tx.data.end.newL2ToL1Msgs);
|
|
230
|
-
const newEncryptedLogs = new L2BlockL2Logs(txs.map(tx => tx.encryptedLogs || new TxL2Logs([])));
|
|
231
|
-
const newUnencryptedLogs = new L2BlockL2Logs(txs.map(tx => tx.unencryptedLogs || new TxL2Logs([])));
|
|
232
|
-
|
|
233
|
-
const l2Block = L2Block.fromFields({
|
|
234
|
-
number: blockNumber,
|
|
235
|
-
globalVariables,
|
|
236
|
-
startPrivateDataTreeSnapshot: rootRollupOutput.startPrivateDataTreeSnapshot,
|
|
237
|
-
endPrivateDataTreeSnapshot: rootRollupOutput.endPrivateDataTreeSnapshot,
|
|
238
|
-
startNullifierTreeSnapshot: rootRollupOutput.startNullifierTreeSnapshot,
|
|
239
|
-
endNullifierTreeSnapshot: rootRollupOutput.endNullifierTreeSnapshot,
|
|
240
|
-
startContractTreeSnapshot: rootRollupOutput.startContractTreeSnapshot,
|
|
241
|
-
endContractTreeSnapshot: rootRollupOutput.endContractTreeSnapshot,
|
|
242
|
-
startPublicDataTreeRoot: rootRollupOutput.startPublicDataTreeRoot,
|
|
243
|
-
endPublicDataTreeRoot: rootRollupOutput.endPublicDataTreeRoot,
|
|
244
|
-
startL1ToL2MessagesTreeSnapshot: rootRollupOutput.startL1ToL2MessagesTreeSnapshot,
|
|
245
|
-
endL1ToL2MessagesTreeSnapshot: rootRollupOutput.endL1ToL2MessagesTreeSnapshot,
|
|
246
|
-
startHistoricBlocksTreeSnapshot: rootRollupOutput.startHistoricBlocksTreeSnapshot,
|
|
247
|
-
endHistoricBlocksTreeSnapshot: rootRollupOutput.endHistoricBlocksTreeSnapshot,
|
|
248
|
-
newCommitments,
|
|
249
|
-
newNullifiers,
|
|
250
|
-
newContracts,
|
|
251
|
-
newContractData,
|
|
252
|
-
newPublicDataWrites,
|
|
253
|
-
newL1ToL2Messages: mockL1ToL2Messages,
|
|
254
|
-
newL2ToL1Msgs,
|
|
255
|
-
newEncryptedLogs,
|
|
256
|
-
newUnencryptedLogs,
|
|
257
|
-
});
|
|
258
|
-
|
|
259
|
-
const callDataHash = l2Block.getCalldataHash();
|
|
260
|
-
const high = Fr.fromBuffer(callDataHash.slice(0, 16));
|
|
261
|
-
const low = Fr.fromBuffer(callDataHash.slice(16, 32));
|
|
262
|
-
|
|
263
|
-
rootRollupOutput.calldataHash = [high, low];
|
|
264
|
-
|
|
265
|
-
return txs;
|
|
266
|
-
};
|
|
267
|
-
|
|
268
|
-
describe('mock simulator', () => {
|
|
269
|
-
beforeEach(() => {
|
|
270
|
-
// Create instance to test
|
|
271
|
-
builder = new SoloBlockBuilder(builderDb, vks, simulator, prover);
|
|
272
|
-
});
|
|
273
|
-
|
|
274
|
-
it('builds an L2 block using mock simulator', async () => {
|
|
275
|
-
// Assemble a fake transaction
|
|
276
|
-
const txs = await buildMockSimulatorInputs();
|
|
277
|
-
|
|
278
|
-
// Actually build a block!
|
|
279
|
-
const [l2Block, proof] = await builder.buildL2Block(globalVariables, txs, mockL1ToL2Messages);
|
|
280
|
-
|
|
281
|
-
expect(l2Block.number).toEqual(blockNumber);
|
|
282
|
-
expect(proof).toEqual(emptyProof);
|
|
283
|
-
}, 20000);
|
|
284
|
-
|
|
285
|
-
it('rejects if too many l1 to l2 messages are provided', async () => {
|
|
286
|
-
// Assemble a fake transaction
|
|
287
|
-
const txs = await buildMockSimulatorInputs();
|
|
288
|
-
const l1ToL2Messages = new Array(100).fill(new Fr(0n));
|
|
289
|
-
await expect(builder.buildL2Block(globalVariables, txs, l1ToL2Messages)).rejects.toThrow();
|
|
290
|
-
});
|
|
291
|
-
});
|
|
292
|
-
|
|
293
|
-
describe('circuits simulator', () => {
|
|
294
|
-
beforeEach(async () => {
|
|
295
|
-
const simulator = await WasmRollupCircuitSimulator.new();
|
|
296
|
-
const prover = new EmptyRollupProver();
|
|
297
|
-
builder = new SoloBlockBuilder(builderDb, vks, simulator, prover);
|
|
298
|
-
});
|
|
299
|
-
|
|
300
|
-
const makeContractDeployProcessedTx = async (seed = 0x1) => {
|
|
301
|
-
const tx = await makeEmptyProcessedTx();
|
|
302
|
-
tx.data.end.newContracts = [makeNewContractData(seed + 0x1000)];
|
|
303
|
-
return tx;
|
|
304
|
-
};
|
|
305
|
-
|
|
306
|
-
const makeBloatedProcessedTx = async (seed = 0x1) => {
|
|
307
|
-
const tx = mockTx(seed);
|
|
308
|
-
const kernelOutput = KernelCircuitPublicInputs.empty();
|
|
309
|
-
kernelOutput.constants.blockData = await getHistoricBlockData(builderDb);
|
|
310
|
-
kernelOutput.end.publicDataUpdateRequests = makeTuple(
|
|
311
|
-
MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX,
|
|
312
|
-
i => new PublicDataUpdateRequest(fr(i), fr(0), fr(i + 10)),
|
|
313
|
-
seed + 0x500,
|
|
314
|
-
);
|
|
315
|
-
|
|
316
|
-
const processedTx = await makeProcessedTx(tx, kernelOutput, makeProof());
|
|
317
|
-
|
|
318
|
-
processedTx.data.end.newCommitments = makeTuple(MAX_NEW_COMMITMENTS_PER_TX, fr, seed + 0x100);
|
|
319
|
-
processedTx.data.end.newNullifiers = makeTuple(MAX_NEW_NULLIFIERS_PER_TX, fr, seed + 0x200);
|
|
320
|
-
processedTx.data.end.newNullifiers[tx.data.end.newNullifiers.length - 1] = Fr.ZERO;
|
|
321
|
-
processedTx.data.end.newL2ToL1Msgs = makeTuple(MAX_NEW_L2_TO_L1_MSGS_PER_TX, fr, seed + 0x300);
|
|
322
|
-
processedTx.data.end.newContracts = [makeNewContractData(seed + 0x1000)];
|
|
323
|
-
processedTx.data.end.encryptedLogsHash = to2Fields(L2Block.computeKernelLogsHash(processedTx.encryptedLogs));
|
|
324
|
-
processedTx.data.end.unencryptedLogsHash = to2Fields(L2Block.computeKernelLogsHash(processedTx.unencryptedLogs));
|
|
325
|
-
|
|
326
|
-
return processedTx;
|
|
327
|
-
};
|
|
328
|
-
|
|
329
|
-
it.each([
|
|
330
|
-
[0, 4],
|
|
331
|
-
[1, 4],
|
|
332
|
-
[4, 4],
|
|
333
|
-
[0, 16],
|
|
334
|
-
[16, 16],
|
|
335
|
-
] as const)(
|
|
336
|
-
'builds an L2 block with %i contract deploy txs and %i txs total',
|
|
337
|
-
async (deployCount: number, totalCount: number) => {
|
|
338
|
-
const contractTreeBefore = await builderDb.getTreeInfo(MerkleTreeId.CONTRACT_TREE);
|
|
339
|
-
|
|
340
|
-
const txs = [
|
|
341
|
-
...(await Promise.all(times(deployCount, makeContractDeployProcessedTx))),
|
|
342
|
-
...(await Promise.all(times(totalCount - deployCount, makeEmptyProcessedTx))),
|
|
343
|
-
];
|
|
344
|
-
|
|
345
|
-
const [l2Block] = await builder.buildL2Block(globalVariables, txs, mockL1ToL2Messages);
|
|
346
|
-
expect(l2Block.number).toEqual(blockNumber);
|
|
347
|
-
|
|
348
|
-
await updateExpectedTreesFromTxs(txs);
|
|
349
|
-
const contractTreeAfter = await builderDb.getTreeInfo(MerkleTreeId.CONTRACT_TREE);
|
|
350
|
-
|
|
351
|
-
if (deployCount > 0) {
|
|
352
|
-
expect(contractTreeAfter.root).not.toEqual(contractTreeBefore.root);
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
const expectedContractTreeAfter = await expectsDb.getTreeInfo(MerkleTreeId.CONTRACT_TREE).then(t => t.root);
|
|
356
|
-
expect(contractTreeAfter.root).toEqual(expectedContractTreeAfter);
|
|
357
|
-
expect(contractTreeAfter.size).toEqual(BigInt(totalCount));
|
|
358
|
-
},
|
|
359
|
-
30000,
|
|
360
|
-
);
|
|
361
|
-
|
|
362
|
-
it('builds an empty L2 block', async () => {
|
|
363
|
-
const txs = await Promise.all([
|
|
364
|
-
makeEmptyProcessedTx(),
|
|
365
|
-
makeEmptyProcessedTx(),
|
|
366
|
-
makeEmptyProcessedTx(),
|
|
367
|
-
makeEmptyProcessedTx(),
|
|
368
|
-
]);
|
|
369
|
-
|
|
370
|
-
const [l2Block] = await builder.buildL2Block(globalVariables, txs, mockL1ToL2Messages);
|
|
371
|
-
expect(l2Block.number).toEqual(blockNumber);
|
|
372
|
-
}, 10_000);
|
|
373
|
-
|
|
374
|
-
it('builds a mixed L2 block', async () => {
|
|
375
|
-
// Ensure that each transaction has unique (non-intersecting nullifier values)
|
|
376
|
-
const txs = await Promise.all([
|
|
377
|
-
makeBloatedProcessedTx(1 * MAX_NEW_NULLIFIERS_PER_TX),
|
|
378
|
-
makeBloatedProcessedTx(2 * MAX_NEW_NULLIFIERS_PER_TX),
|
|
379
|
-
makeBloatedProcessedTx(3 * MAX_NEW_NULLIFIERS_PER_TX),
|
|
380
|
-
makeBloatedProcessedTx(4 * MAX_NEW_NULLIFIERS_PER_TX),
|
|
381
|
-
]);
|
|
382
|
-
|
|
383
|
-
const l1ToL2Messages = range(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, 1 + 0x400).map(fr);
|
|
384
|
-
|
|
385
|
-
const [l2Block] = await builder.buildL2Block(globalVariables, txs, l1ToL2Messages);
|
|
386
|
-
expect(l2Block.number).toEqual(blockNumber);
|
|
387
|
-
}, 40_000);
|
|
388
|
-
|
|
389
|
-
// This test specifically tests nullifier values which previously caused e2e_private_token test to fail
|
|
390
|
-
it('e2e_private_token edge case regression test on nullifier values', async () => {
|
|
391
|
-
const simulator = await WasmRollupCircuitSimulator.new();
|
|
392
|
-
const prover = new EmptyRollupProver();
|
|
393
|
-
builder = new SoloBlockBuilder(builderDb, vks, simulator, prover);
|
|
394
|
-
// update the starting tree
|
|
395
|
-
const updateVals = Array(4 * MAX_NEW_NULLIFIERS_PER_TX).fill(0n);
|
|
396
|
-
updateVals[0] = 19777494491628650244807463906174285795660759352776418619064841306523677458742n;
|
|
397
|
-
updateVals[1] = 10246291467305176436335175657884940686778521321101740385288169037814567547848n;
|
|
398
|
-
|
|
399
|
-
// new added values
|
|
400
|
-
const tx = await makeEmptyProcessedTx();
|
|
401
|
-
tx.data.end.newNullifiers[0] = new Fr(
|
|
402
|
-
10336601644835972678500657502133589897705389664587188571002640950065546264856n,
|
|
403
|
-
);
|
|
404
|
-
tx.data.end.newNullifiers[1] = new Fr(
|
|
405
|
-
17490072961923661940560522096125238013953043065748521735636170028491723851741n,
|
|
406
|
-
);
|
|
407
|
-
|
|
408
|
-
const txs = [tx, await makeEmptyProcessedTx(), await makeEmptyProcessedTx(), await makeEmptyProcessedTx()];
|
|
409
|
-
|
|
410
|
-
// Must be built after the txs are created
|
|
411
|
-
await builderDb.batchInsert(
|
|
412
|
-
MerkleTreeId.NULLIFIER_TREE,
|
|
413
|
-
updateVals.map(v => toBufferBE(v, 32)),
|
|
414
|
-
NULLIFIER_SUBTREE_HEIGHT,
|
|
415
|
-
);
|
|
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
|
-
});
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import { L2Block } from '@aztec/types';
|
|
2
|
-
|
|
3
|
-
import { MockProxy, mock } from 'jest-mock-extended';
|
|
4
|
-
|
|
5
|
-
import { sleep } from '../utils.js';
|
|
6
|
-
import { L1Publisher, L1PublisherTxSender, MinimalTransactionReceipt } from './l1-publisher.js';
|
|
7
|
-
|
|
8
|
-
describe('L1Publisher', () => {
|
|
9
|
-
let txSender: MockProxy<L1PublisherTxSender>;
|
|
10
|
-
let txHash: string;
|
|
11
|
-
let txReceipt: MinimalTransactionReceipt;
|
|
12
|
-
let l2Block: L2Block;
|
|
13
|
-
let l2Inputs: Buffer;
|
|
14
|
-
let l2Proof: Buffer;
|
|
15
|
-
let publisher: L1Publisher;
|
|
16
|
-
|
|
17
|
-
beforeEach(() => {
|
|
18
|
-
l2Block = L2Block.random(42);
|
|
19
|
-
l2Inputs = l2Block.encode();
|
|
20
|
-
l2Proof = Buffer.alloc(0);
|
|
21
|
-
|
|
22
|
-
txSender = mock<L1PublisherTxSender>();
|
|
23
|
-
txHash = `0x${Buffer.from('txHash').toString('hex')}`; // random tx hash
|
|
24
|
-
txReceipt = { transactionHash: txHash, status: true };
|
|
25
|
-
txSender.sendProcessTx.mockResolvedValueOnce(txHash);
|
|
26
|
-
txSender.getTransactionReceipt.mockResolvedValueOnce(txReceipt);
|
|
27
|
-
|
|
28
|
-
publisher = new L1Publisher(txSender, { l1BlockPublishRetryIntervalMS: 1 });
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
it('publishes l2 block to l1', async () => {
|
|
32
|
-
const result = await publisher.processL2Block(l2Block);
|
|
33
|
-
|
|
34
|
-
expect(result).toEqual(true);
|
|
35
|
-
expect(txSender.sendProcessTx).toHaveBeenCalledWith({ proof: l2Proof, inputs: l2Inputs });
|
|
36
|
-
expect(txSender.getTransactionReceipt).toHaveBeenCalledWith(txHash);
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it('does not retry if sending a tx fails', async () => {
|
|
40
|
-
txSender.sendProcessTx.mockReset().mockRejectedValueOnce(new Error()).mockResolvedValueOnce(txHash);
|
|
41
|
-
|
|
42
|
-
const result = await publisher.processL2Block(l2Block);
|
|
43
|
-
|
|
44
|
-
expect(result).toEqual(false);
|
|
45
|
-
expect(txSender.sendProcessTx).toHaveBeenCalledTimes(1);
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
it('retries if fetching the receipt fails', async () => {
|
|
49
|
-
txSender.getTransactionReceipt.mockReset().mockRejectedValueOnce(new Error()).mockResolvedValueOnce(txReceipt);
|
|
50
|
-
|
|
51
|
-
const result = await publisher.processL2Block(l2Block);
|
|
52
|
-
|
|
53
|
-
expect(result).toEqual(true);
|
|
54
|
-
expect(txSender.getTransactionReceipt).toHaveBeenCalledTimes(2);
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
it('returns false if tx reverts', async () => {
|
|
58
|
-
txSender.getTransactionReceipt.mockReset().mockResolvedValueOnce({ ...txReceipt, status: false });
|
|
59
|
-
|
|
60
|
-
const result = await publisher.processL2Block(l2Block);
|
|
61
|
-
|
|
62
|
-
expect(result).toEqual(false);
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
it('returns false if interrupted', async () => {
|
|
66
|
-
txSender.sendProcessTx.mockReset().mockImplementationOnce(() => sleep(10, txHash));
|
|
67
|
-
|
|
68
|
-
const resultPromise = publisher.processL2Block(l2Block);
|
|
69
|
-
publisher.interrupt();
|
|
70
|
-
const result = await resultPromise;
|
|
71
|
-
|
|
72
|
-
expect(result).toEqual(false);
|
|
73
|
-
expect(txSender.getTransactionReceipt).not.toHaveBeenCalled();
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
it.skip('waits for fee distributor balance', () => {});
|
|
77
|
-
|
|
78
|
-
it.skip('fails if contract is changed underfoot', () => {});
|
|
79
|
-
});
|