@aztec/prover-client 3.0.0-canary.a9708bd → 3.0.0-devnet.20251212
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/dest/block-factory/index.d.ts +1 -1
- package/dest/block-factory/light.d.ts +5 -3
- package/dest/block-factory/light.d.ts.map +1 -1
- package/dest/block-factory/light.js +32 -11
- package/dest/config.d.ts +1 -1
- package/dest/config.js +1 -1
- package/dest/index.d.ts +1 -1
- package/dest/light/lightweight_checkpoint_builder.d.ts +29 -0
- package/dest/light/lightweight_checkpoint_builder.d.ts.map +1 -0
- package/dest/light/lightweight_checkpoint_builder.js +108 -0
- package/dest/mocks/fixtures.d.ts +5 -5
- package/dest/mocks/fixtures.d.ts.map +1 -1
- package/dest/mocks/fixtures.js +33 -15
- package/dest/mocks/test_context.d.ts +37 -33
- package/dest/mocks/test_context.d.ts.map +1 -1
- package/dest/mocks/test_context.js +124 -82
- package/dest/orchestrator/block-building-helpers.d.ts +35 -35
- package/dest/orchestrator/block-building-helpers.d.ts.map +1 -1
- package/dest/orchestrator/block-building-helpers.js +151 -187
- package/dest/orchestrator/block-proving-state.d.ts +68 -55
- package/dest/orchestrator/block-proving-state.d.ts.map +1 -1
- package/dest/orchestrator/block-proving-state.js +273 -185
- package/dest/orchestrator/checkpoint-proving-state.d.ts +63 -0
- package/dest/orchestrator/checkpoint-proving-state.d.ts.map +1 -0
- package/dest/orchestrator/checkpoint-proving-state.js +210 -0
- package/dest/orchestrator/epoch-proving-state.d.ts +38 -31
- package/dest/orchestrator/epoch-proving-state.d.ts.map +1 -1
- package/dest/orchestrator/epoch-proving-state.js +128 -84
- package/dest/orchestrator/index.d.ts +1 -1
- package/dest/orchestrator/orchestrator.d.ts +33 -32
- package/dest/orchestrator/orchestrator.d.ts.map +1 -1
- package/dest/orchestrator/orchestrator.js +369 -243
- package/dest/orchestrator/orchestrator_metrics.d.ts +1 -1
- package/dest/orchestrator/orchestrator_metrics.d.ts.map +1 -1
- package/dest/orchestrator/tx-proving-state.d.ts +12 -10
- package/dest/orchestrator/tx-proving-state.d.ts.map +1 -1
- package/dest/orchestrator/tx-proving-state.js +23 -29
- package/dest/prover-client/factory.d.ts +1 -1
- package/dest/prover-client/index.d.ts +1 -1
- package/dest/prover-client/prover-client.d.ts +1 -1
- package/dest/prover-client/prover-client.d.ts.map +1 -1
- package/dest/prover-client/server-epoch-prover.d.ts +13 -11
- package/dest/prover-client/server-epoch-prover.d.ts.map +1 -1
- package/dest/prover-client/server-epoch-prover.js +9 -9
- package/dest/proving_broker/broker_prover_facade.d.ts +23 -18
- package/dest/proving_broker/broker_prover_facade.d.ts.map +1 -1
- package/dest/proving_broker/broker_prover_facade.js +41 -25
- package/dest/proving_broker/config.d.ts +18 -14
- package/dest/proving_broker/config.d.ts.map +1 -1
- package/dest/proving_broker/config.js +13 -7
- package/dest/proving_broker/factory.d.ts +1 -1
- package/dest/proving_broker/factory.js +1 -1
- package/dest/proving_broker/fixtures.d.ts +3 -2
- package/dest/proving_broker/fixtures.d.ts.map +1 -1
- package/dest/proving_broker/fixtures.js +3 -2
- package/dest/proving_broker/index.d.ts +1 -1
- package/dest/proving_broker/proof_store/factory.d.ts +2 -2
- package/dest/proving_broker/proof_store/gcs_proof_store.d.ts +1 -1
- package/dest/proving_broker/proof_store/gcs_proof_store.d.ts.map +1 -1
- package/dest/proving_broker/proof_store/index.d.ts +2 -1
- package/dest/proving_broker/proof_store/index.d.ts.map +1 -1
- package/dest/proving_broker/proof_store/index.js +1 -0
- package/dest/proving_broker/proof_store/inline_proof_store.d.ts +1 -1
- package/dest/proving_broker/proof_store/inline_proof_store.d.ts.map +1 -1
- package/dest/proving_broker/proof_store/proof_store.d.ts +1 -1
- package/dest/proving_broker/proving_agent.d.ts +1 -1
- package/dest/proving_broker/proving_agent.d.ts.map +1 -1
- package/dest/proving_broker/proving_agent_instrumentation.d.ts +1 -1
- package/dest/proving_broker/proving_agent_instrumentation.d.ts.map +1 -1
- package/dest/proving_broker/proving_broker.d.ts +2 -2
- package/dest/proving_broker/proving_broker.d.ts.map +1 -1
- package/dest/proving_broker/proving_broker.js +31 -19
- package/dest/proving_broker/proving_broker_database/memory.d.ts +3 -2
- package/dest/proving_broker/proving_broker_database/memory.d.ts.map +1 -1
- package/dest/proving_broker/proving_broker_database/persisted.d.ts +3 -2
- package/dest/proving_broker/proving_broker_database/persisted.d.ts.map +1 -1
- package/dest/proving_broker/proving_broker_database/persisted.js +8 -7
- package/dest/proving_broker/proving_broker_database.d.ts +3 -2
- package/dest/proving_broker/proving_broker_database.d.ts.map +1 -1
- package/dest/proving_broker/proving_broker_instrumentation.d.ts +1 -1
- package/dest/proving_broker/proving_broker_instrumentation.d.ts.map +1 -1
- package/dest/proving_broker/proving_job_controller.d.ts +3 -2
- package/dest/proving_broker/proving_job_controller.d.ts.map +1 -1
- package/dest/proving_broker/proving_job_controller.js +39 -19
- package/dest/proving_broker/rpc.d.ts +4 -4
- package/dest/test/mock_proof_store.d.ts +3 -3
- package/dest/test/mock_proof_store.d.ts.map +1 -1
- package/dest/test/mock_prover.d.ts +23 -19
- package/dest/test/mock_prover.d.ts.map +1 -1
- package/dest/test/mock_prover.js +35 -20
- package/package.json +19 -19
- package/src/block-factory/light.ts +40 -17
- package/src/config.ts +1 -1
- package/src/light/lightweight_checkpoint_builder.ts +144 -0
- package/src/mocks/fixtures.ts +41 -36
- package/src/mocks/test_context.ts +188 -114
- package/src/orchestrator/block-building-helpers.ts +233 -313
- package/src/orchestrator/block-proving-state.ts +315 -247
- package/src/orchestrator/checkpoint-proving-state.ts +303 -0
- package/src/orchestrator/epoch-proving-state.ts +176 -129
- package/src/orchestrator/orchestrator.ts +554 -319
- package/src/orchestrator/tx-proving-state.ts +48 -55
- package/src/prover-client/server-epoch-prover.ts +30 -21
- package/src/proving_broker/broker_prover_facade.ts +175 -103
- package/src/proving_broker/config.ts +15 -8
- package/src/proving_broker/factory.ts +1 -1
- package/src/proving_broker/fixtures.ts +8 -3
- package/src/proving_broker/proof_store/index.ts +1 -0
- package/src/proving_broker/proving_broker.ts +38 -19
- package/src/proving_broker/proving_broker_database/memory.ts +2 -1
- package/src/proving_broker/proving_broker_database/persisted.ts +10 -9
- package/src/proving_broker/proving_broker_database.ts +2 -1
- package/src/proving_broker/proving_job_controller.ts +41 -20
- package/src/test/mock_prover.ts +142 -60
- package/dest/bin/get-proof-inputs.d.ts +0 -2
- package/dest/bin/get-proof-inputs.d.ts.map +0 -1
- package/dest/bin/get-proof-inputs.js +0 -51
- package/src/bin/get-proof-inputs.ts +0 -59
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { SpongeBlob, computeBlobsHashFromBlobs, encodeCheckpointEndMarker, getBlobsPerL1Block } from '@aztec/blob-lib';
|
|
2
|
+
import { NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP } from '@aztec/constants';
|
|
3
|
+
import type { CheckpointNumber } from '@aztec/foundation/branded-types';
|
|
4
|
+
import { padArrayEnd } from '@aztec/foundation/collection';
|
|
5
|
+
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
6
|
+
import { createLogger } from '@aztec/foundation/log';
|
|
7
|
+
import { L2BlockNew } from '@aztec/stdlib/block';
|
|
8
|
+
import { Checkpoint } from '@aztec/stdlib/checkpoint';
|
|
9
|
+
import type { MerkleTreeWriteOperations } from '@aztec/stdlib/interfaces/server';
|
|
10
|
+
import { computeCheckpointOutHash, computeInHashFromL1ToL2Messages } from '@aztec/stdlib/messaging';
|
|
11
|
+
import { CheckpointConstantData, CheckpointHeader, computeBlockHeadersHash } from '@aztec/stdlib/rollup';
|
|
12
|
+
import { AppendOnlyTreeSnapshot, MerkleTreeId } from '@aztec/stdlib/trees';
|
|
13
|
+
import { ContentCommitment, type GlobalVariables, type ProcessedTx, StateReference } from '@aztec/stdlib/tx';
|
|
14
|
+
|
|
15
|
+
import {
|
|
16
|
+
buildHeaderAndBodyFromTxs,
|
|
17
|
+
getTreeSnapshot,
|
|
18
|
+
insertSideEffects,
|
|
19
|
+
} from '../orchestrator/block-building-helpers.js';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Builds a checkpoint and its header and the blocks in it from a set of processed tx without running any circuits.
|
|
23
|
+
*
|
|
24
|
+
* It updates the l1-to-l2 message tree when starting a new checkpoint, inserts the side effects to note hash,
|
|
25
|
+
* nullifier, and public data trees, then updates the archive tree when a block is added.
|
|
26
|
+
*/
|
|
27
|
+
export class LightweightCheckpointBuilder {
|
|
28
|
+
private readonly logger = createLogger('lightweight-checkpoint-builder');
|
|
29
|
+
private lastArchives: AppendOnlyTreeSnapshot[] = [];
|
|
30
|
+
private spongeBlob: SpongeBlob;
|
|
31
|
+
private blocks: L2BlockNew[] = [];
|
|
32
|
+
private blobFields: Fr[] = [];
|
|
33
|
+
|
|
34
|
+
constructor(
|
|
35
|
+
private checkpointNumber: CheckpointNumber,
|
|
36
|
+
private constants: CheckpointConstantData,
|
|
37
|
+
private l1ToL2Messages: Fr[],
|
|
38
|
+
private db: MerkleTreeWriteOperations,
|
|
39
|
+
) {
|
|
40
|
+
this.spongeBlob = SpongeBlob.init();
|
|
41
|
+
this.logger.debug('Starting new checkpoint', { constants: constants.toInspect(), l1ToL2Messages });
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
static async startNewCheckpoint(
|
|
45
|
+
checkpointNumber: CheckpointNumber,
|
|
46
|
+
constants: CheckpointConstantData,
|
|
47
|
+
l1ToL2Messages: Fr[],
|
|
48
|
+
db: MerkleTreeWriteOperations,
|
|
49
|
+
): Promise<LightweightCheckpointBuilder> {
|
|
50
|
+
// Insert l1-to-l2 messages into the tree.
|
|
51
|
+
await db.appendLeaves(
|
|
52
|
+
MerkleTreeId.L1_TO_L2_MESSAGE_TREE,
|
|
53
|
+
padArrayEnd<Fr, number>(l1ToL2Messages, Fr.ZERO, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP),
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
return new LightweightCheckpointBuilder(checkpointNumber, constants, l1ToL2Messages, db);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async addBlock(globalVariables: GlobalVariables, endState: StateReference, txs: ProcessedTx[]): Promise<L2BlockNew> {
|
|
60
|
+
const isFirstBlock = this.blocks.length === 0;
|
|
61
|
+
if (isFirstBlock) {
|
|
62
|
+
this.lastArchives.push(await getTreeSnapshot(MerkleTreeId.ARCHIVE, this.db));
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const lastArchive = this.lastArchives.at(-1)!;
|
|
66
|
+
|
|
67
|
+
for (const tx of txs) {
|
|
68
|
+
await insertSideEffects(tx, this.db);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const { header, body, blockBlobFields } = await buildHeaderAndBodyFromTxs(
|
|
72
|
+
txs,
|
|
73
|
+
lastArchive,
|
|
74
|
+
endState,
|
|
75
|
+
globalVariables,
|
|
76
|
+
this.spongeBlob,
|
|
77
|
+
isFirstBlock,
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
await this.db.updateArchive(header);
|
|
81
|
+
const newArchive = await getTreeSnapshot(MerkleTreeId.ARCHIVE, this.db);
|
|
82
|
+
this.lastArchives.push(newArchive);
|
|
83
|
+
|
|
84
|
+
const indexWithinCheckpoint = this.blocks.length;
|
|
85
|
+
const block = new L2BlockNew(newArchive, header, body, this.checkpointNumber, indexWithinCheckpoint);
|
|
86
|
+
this.blocks.push(block);
|
|
87
|
+
|
|
88
|
+
await this.spongeBlob.absorb(blockBlobFields);
|
|
89
|
+
this.blobFields.push(...blockBlobFields);
|
|
90
|
+
|
|
91
|
+
this.logger.debug(`Built block ${header.getBlockNumber()}`, {
|
|
92
|
+
globalVariables: globalVariables.toInspect(),
|
|
93
|
+
archiveRoot: newArchive.root.toString(),
|
|
94
|
+
stateReference: header.state.toInspect(),
|
|
95
|
+
blockHash: (await block.hash()).toString(),
|
|
96
|
+
txs: block.body.txEffects.map(tx => tx.txHash.toString()),
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
return block;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
async completeCheckpoint(): Promise<Checkpoint> {
|
|
103
|
+
if (!this.blocks.length) {
|
|
104
|
+
throw new Error('No blocks added to checkpoint.');
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const numBlobFields = this.blobFields.length + 1; // +1 for the checkpoint end marker.
|
|
108
|
+
const checkpointEndMarker = encodeCheckpointEndMarker({ numBlobFields });
|
|
109
|
+
this.blobFields.push(checkpointEndMarker);
|
|
110
|
+
|
|
111
|
+
const blocks = this.blocks;
|
|
112
|
+
const blockHeadersHash = await computeBlockHeadersHash(blocks.map(block => block.header));
|
|
113
|
+
|
|
114
|
+
const newArchive = this.lastArchives[this.lastArchives.length - 1];
|
|
115
|
+
|
|
116
|
+
const blobs = getBlobsPerL1Block(this.blobFields);
|
|
117
|
+
const blobsHash = computeBlobsHashFromBlobs(blobs);
|
|
118
|
+
|
|
119
|
+
const inHash = computeInHashFromL1ToL2Messages(this.l1ToL2Messages);
|
|
120
|
+
|
|
121
|
+
const outHash = computeCheckpointOutHash(blocks.map(block => block.body.txEffects.map(tx => tx.l2ToL1Msgs)));
|
|
122
|
+
|
|
123
|
+
const constants = this.constants!;
|
|
124
|
+
|
|
125
|
+
// timestamp of a checkpoint is the timestamp of the last block in the checkpoint.
|
|
126
|
+
const timestamp = blocks[blocks.length - 1].timestamp;
|
|
127
|
+
|
|
128
|
+
const totalManaUsed = blocks.reduce((acc, block) => acc.add(block.header.totalManaUsed), Fr.ZERO);
|
|
129
|
+
|
|
130
|
+
const header = CheckpointHeader.from({
|
|
131
|
+
lastArchiveRoot: this.lastArchives[0].root,
|
|
132
|
+
blockHeadersHash,
|
|
133
|
+
contentCommitment: new ContentCommitment(blobsHash, inHash, outHash),
|
|
134
|
+
slotNumber: constants.slotNumber,
|
|
135
|
+
timestamp,
|
|
136
|
+
coinbase: constants.coinbase,
|
|
137
|
+
feeRecipient: constants.feeRecipient,
|
|
138
|
+
gasFees: constants.gasFees,
|
|
139
|
+
totalManaUsed,
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
return new Checkpoint(newArchive, header, blocks, this.checkpointNumber);
|
|
143
|
+
}
|
|
144
|
+
}
|
package/src/mocks/fixtures.ts
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { BlockNumber, SlotNumber } from '@aztec/foundation/branded-types';
|
|
2
|
+
import { randomBytes } from '@aztec/foundation/crypto/random';
|
|
3
|
+
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
4
4
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
5
|
-
import { Fr } from '@aztec/foundation/fields';
|
|
6
5
|
import type { Logger } from '@aztec/foundation/log';
|
|
6
|
+
import type { FieldsOf } from '@aztec/foundation/types';
|
|
7
7
|
import { fileURLToPath } from '@aztec/foundation/url';
|
|
8
|
+
import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree';
|
|
9
|
+
import { protocolContractsHash } from '@aztec/protocol-contracts';
|
|
8
10
|
import { type CircuitSimulator, NativeACVMSimulator, WASMSimulatorWithBlobs } from '@aztec/simulator/server';
|
|
9
11
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
10
12
|
import { GasFees } from '@aztec/stdlib/gas';
|
|
11
|
-
import
|
|
12
|
-
import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
13
|
-
import type { ProcessedTx } from '@aztec/stdlib/tx';
|
|
13
|
+
import { CheckpointConstantData } from '@aztec/stdlib/rollup';
|
|
14
14
|
import { GlobalVariables } from '@aztec/stdlib/tx';
|
|
15
15
|
|
|
16
16
|
import { promises as fs } from 'fs';
|
|
@@ -32,7 +32,7 @@ export const getEnvironmentConfig = async (logger: Logger) => {
|
|
|
32
32
|
try {
|
|
33
33
|
const expectedBBPath = BB_BINARY_PATH
|
|
34
34
|
? BB_BINARY_PATH
|
|
35
|
-
: `${path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../../../../barretenberg/', BB_RELEASE_DIR)}/bb`;
|
|
35
|
+
: `${path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../../../../barretenberg/', BB_RELEASE_DIR)}/bb-avm`;
|
|
36
36
|
await fs.access(expectedBBPath, fs.constants.R_OK);
|
|
37
37
|
const tempWorkingDirectory = `${TEMP_DIR}/${randomBytes(4).toString('hex')}`;
|
|
38
38
|
const bbWorkingDirectory = BB_WORKING_DIRECTORY ? BB_WORKING_DIRECTORY : `${tempWorkingDirectory}/bb`;
|
|
@@ -84,34 +84,39 @@ export async function getSimulator(
|
|
|
84
84
|
return new WASMSimulatorWithBlobs();
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
);
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
}
|
|
87
|
+
export const makeGlobals = (
|
|
88
|
+
blockNumber: number,
|
|
89
|
+
slotNumber = blockNumber,
|
|
90
|
+
overrides: Partial<FieldsOf<GlobalVariables> & FieldsOf<CheckpointConstantData>> = {},
|
|
91
|
+
) => {
|
|
92
|
+
const checkpointConstants = makeCheckpointConstants(slotNumber, overrides);
|
|
93
|
+
return GlobalVariables.from({
|
|
94
|
+
chainId: checkpointConstants.chainId,
|
|
95
|
+
version: checkpointConstants.version,
|
|
96
|
+
blockNumber: BlockNumber(blockNumber) /** block number */,
|
|
97
|
+
slotNumber: SlotNumber(slotNumber) /** slot number */,
|
|
98
|
+
timestamp: BigInt(blockNumber * 123) /** block number * 123 as pseudo-timestamp for testing */,
|
|
99
|
+
coinbase: checkpointConstants.coinbase,
|
|
100
|
+
feeRecipient: checkpointConstants.feeRecipient,
|
|
101
|
+
gasFees: checkpointConstants.gasFees,
|
|
102
|
+
...overrides,
|
|
103
|
+
});
|
|
104
104
|
};
|
|
105
105
|
|
|
106
|
-
export const
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
106
|
+
export const makeCheckpointConstants = (
|
|
107
|
+
slotNumber: number,
|
|
108
|
+
overrides: Partial<FieldsOf<CheckpointConstantData>> = {},
|
|
109
|
+
) => {
|
|
110
|
+
return CheckpointConstantData.from({
|
|
111
|
+
chainId: Fr.ZERO,
|
|
112
|
+
version: Fr.ZERO,
|
|
113
|
+
vkTreeRoot: getVKTreeRoot(),
|
|
114
|
+
protocolContractsHash,
|
|
115
|
+
proverId: Fr.ZERO,
|
|
116
|
+
slotNumber: SlotNumber(slotNumber),
|
|
117
|
+
coinbase: EthAddress.ZERO,
|
|
118
|
+
feeRecipient: AztecAddress.ZERO,
|
|
119
|
+
gasFees: GasFees.empty(),
|
|
120
|
+
...overrides,
|
|
121
|
+
});
|
|
117
122
|
};
|
|
@@ -1,52 +1,64 @@
|
|
|
1
1
|
import type { BBProverConfig } from '@aztec/bb-prover';
|
|
2
|
+
import { TestCircuitProver } from '@aztec/bb-prover';
|
|
2
3
|
import { NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP } from '@aztec/constants';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
4
|
+
import { BlockNumber, CheckpointNumber } from '@aztec/foundation/branded-types';
|
|
5
|
+
import { padArrayEnd, times, timesAsync } from '@aztec/foundation/collection';
|
|
6
|
+
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
5
7
|
import type { Logger } from '@aztec/foundation/log';
|
|
6
|
-
import {
|
|
8
|
+
import type { FieldsOf } from '@aztec/foundation/types';
|
|
7
9
|
import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree';
|
|
8
|
-
import {
|
|
10
|
+
import { ProtocolContractsList } from '@aztec/protocol-contracts';
|
|
9
11
|
import { computeFeePayerBalanceLeafSlot } from '@aztec/protocol-contracts/fee-juice';
|
|
10
|
-
import { SimpleContractDataSource } from '@aztec/simulator/public/fixtures';
|
|
11
|
-
import { PublicProcessorFactory } from '@aztec/simulator/server';
|
|
12
12
|
import { PublicDataWrite } from '@aztec/stdlib/avm';
|
|
13
13
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
14
|
-
import { EthAddress
|
|
15
|
-
import type {
|
|
16
|
-
import {
|
|
17
|
-
import
|
|
18
|
-
import {
|
|
14
|
+
import { EthAddress } from '@aztec/stdlib/block';
|
|
15
|
+
import type { Checkpoint } from '@aztec/stdlib/checkpoint';
|
|
16
|
+
import type { MerkleTreeWriteOperations, ServerCircuitProver } from '@aztec/stdlib/interfaces/server';
|
|
17
|
+
import type { CheckpointConstantData } from '@aztec/stdlib/rollup';
|
|
18
|
+
import { mockProcessedTx } from '@aztec/stdlib/testing';
|
|
19
|
+
import { MerkleTreeId, PublicDataTreeLeaf } from '@aztec/stdlib/trees';
|
|
20
|
+
import {
|
|
21
|
+
type BlockHeader,
|
|
22
|
+
type GlobalVariables,
|
|
23
|
+
type ProcessedTx,
|
|
24
|
+
StateReference,
|
|
25
|
+
TreeSnapshots,
|
|
26
|
+
} from '@aztec/stdlib/tx';
|
|
19
27
|
import type { MerkleTreeAdminDatabase } from '@aztec/world-state';
|
|
20
28
|
import { NativeWorldStateService } from '@aztec/world-state/native';
|
|
21
29
|
|
|
22
30
|
import { promises as fs } from 'fs';
|
|
23
31
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
32
|
+
import { LightweightCheckpointBuilder } from '../light/lightweight_checkpoint_builder.js';
|
|
33
|
+
import {
|
|
34
|
+
buildFinalBlobChallenges,
|
|
35
|
+
getTreeSnapshot,
|
|
36
|
+
insertSideEffects,
|
|
37
|
+
} from '../orchestrator/block-building-helpers.js';
|
|
38
|
+
import type { BlockProvingState } from '../orchestrator/block-proving-state.js';
|
|
29
39
|
import { ProvingOrchestrator } from '../orchestrator/index.js';
|
|
30
40
|
import { BrokerCircuitProverFacade } from '../proving_broker/broker_prover_facade.js';
|
|
31
41
|
import { TestBroker } from '../test/mock_prover.js';
|
|
32
|
-
import { getEnvironmentConfig, getSimulator,
|
|
42
|
+
import { getEnvironmentConfig, getSimulator, makeCheckpointConstants, makeGlobals } from './fixtures.js';
|
|
33
43
|
|
|
34
44
|
export class TestContext {
|
|
35
45
|
private headers: Map<number, BlockHeader> = new Map();
|
|
46
|
+
private checkpoints: Checkpoint[] = [];
|
|
47
|
+
private nextCheckpointIndex = 0;
|
|
48
|
+
private nextBlockNumber = 1;
|
|
49
|
+
private epochNumber = 1;
|
|
36
50
|
private feePayerBalance: Fr;
|
|
37
51
|
|
|
38
52
|
constructor(
|
|
39
53
|
public worldState: MerkleTreeAdminDatabase,
|
|
40
|
-
public globalVariables: GlobalVariables,
|
|
41
54
|
public prover: ServerCircuitProver,
|
|
42
55
|
public broker: TestBroker,
|
|
43
56
|
public brokerProverFacade: BrokerCircuitProverFacade,
|
|
44
57
|
public orchestrator: TestProvingOrchestrator,
|
|
45
|
-
|
|
46
|
-
public feePayer: AztecAddress,
|
|
58
|
+
private feePayer: AztecAddress,
|
|
47
59
|
initialFeePayerBalance: Fr,
|
|
48
|
-
|
|
49
|
-
|
|
60
|
+
private directoriesToCleanup: string[],
|
|
61
|
+
private logger: Logger,
|
|
50
62
|
) {
|
|
51
63
|
this.feePayerBalance = initialFeePayerBalance;
|
|
52
64
|
}
|
|
@@ -60,15 +72,12 @@ export class TestContext {
|
|
|
60
72
|
{
|
|
61
73
|
proverCount = 4,
|
|
62
74
|
createProver = async (bbConfig: BBProverConfig) => new TestCircuitProver(await getSimulator(bbConfig, logger)),
|
|
63
|
-
blockNumber = 1,
|
|
64
75
|
}: {
|
|
65
76
|
proverCount?: number;
|
|
66
77
|
createProver?: (bbConfig: BBProverConfig) => Promise<ServerCircuitProver>;
|
|
67
|
-
blockNumber?: number;
|
|
68
78
|
} = {},
|
|
69
79
|
) {
|
|
70
80
|
const directoriesToCleanup: string[] = [];
|
|
71
|
-
const globalVariables = makeGlobals(blockNumber);
|
|
72
81
|
|
|
73
82
|
const feePayer = AztecAddress.fromNumber(42222);
|
|
74
83
|
const initialFeePayerBalance = new Fr(10n ** 20n);
|
|
@@ -112,12 +121,10 @@ export class TestContext {
|
|
|
112
121
|
|
|
113
122
|
return new this(
|
|
114
123
|
ws,
|
|
115
|
-
globalVariables,
|
|
116
124
|
localProver,
|
|
117
125
|
broker,
|
|
118
126
|
facade,
|
|
119
127
|
orchestrator,
|
|
120
|
-
blockNumber,
|
|
121
128
|
feePayer,
|
|
122
129
|
initialFeePayerBalance,
|
|
123
130
|
directoriesToCleanup,
|
|
@@ -129,20 +136,6 @@ export class TestContext {
|
|
|
129
136
|
return this.worldState.fork();
|
|
130
137
|
}
|
|
131
138
|
|
|
132
|
-
public getBlockHeader(blockNumber: 0): BlockHeader;
|
|
133
|
-
public getBlockHeader(blockNumber: number): BlockHeader | undefined;
|
|
134
|
-
public getBlockHeader(blockNumber = 0) {
|
|
135
|
-
return blockNumber === 0 ? this.worldState.getCommitted().getInitialHeader() : this.headers.get(blockNumber);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
public setBlockHeader(header: BlockHeader, blockNumber: number) {
|
|
139
|
-
this.headers.set(blockNumber, header);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
public getPreviousBlockHeader(currentBlockNumber = this.blockNumber): BlockHeader {
|
|
143
|
-
return this.getBlockHeader(currentBlockNumber - 1)!;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
139
|
async cleanup() {
|
|
147
140
|
await this.brokerProverFacade.stop();
|
|
148
141
|
await this.broker.stop();
|
|
@@ -155,93 +148,172 @@ export class TestContext {
|
|
|
155
148
|
}
|
|
156
149
|
}
|
|
157
150
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
header,
|
|
163
|
-
vkTreeRoot: getVKTreeRoot(),
|
|
164
|
-
protocolContractTreeRoot,
|
|
165
|
-
globalVariables: this.globalVariables,
|
|
166
|
-
feePayer: this.feePayer,
|
|
167
|
-
...opts,
|
|
168
|
-
});
|
|
169
|
-
this.feePayerBalance = new Fr(this.feePayerBalance.toBigInt() - tx.txEffect.transactionFee.toBigInt());
|
|
170
|
-
if (opts?.privateOnly) {
|
|
171
|
-
const feePayerSlot = await computeFeePayerBalanceLeafSlot(this.feePayer);
|
|
172
|
-
tx.txEffect.publicDataWrites[0] = new PublicDataWrite(feePayerSlot, this.feePayerBalance);
|
|
173
|
-
}
|
|
174
|
-
return tx;
|
|
151
|
+
public startNewEpoch() {
|
|
152
|
+
this.checkpoints = [];
|
|
153
|
+
this.nextCheckpointIndex = 0;
|
|
154
|
+
this.epochNumber++;
|
|
175
155
|
}
|
|
176
156
|
|
|
177
|
-
|
|
178
|
-
public
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
blockNumOrGlobals: GlobalVariables | number = this.globalVariables,
|
|
182
|
-
makeProcessedTxOpts: (index: number) => Partial<Parameters<typeof makeBloatedProcessedTx>[0]> = () => ({}),
|
|
183
|
-
) {
|
|
184
|
-
const globalVariables = typeof blockNumOrGlobals === 'number' ? makeGlobals(blockNumOrGlobals) : blockNumOrGlobals;
|
|
185
|
-
const blockNum = globalVariables.blockNumber;
|
|
186
|
-
const db = await this.worldState.fork();
|
|
187
|
-
const l1ToL2Messages = times(numL1ToL2Messages, i => new Fr(blockNum * 100 + i));
|
|
188
|
-
const merkleTrees = await this.worldState.fork();
|
|
189
|
-
await merkleTrees.appendLeaves(
|
|
190
|
-
MerkleTreeId.L1_TO_L2_MESSAGE_TREE,
|
|
191
|
-
padArrayEnd(l1ToL2Messages, Fr.ZERO, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP),
|
|
192
|
-
);
|
|
193
|
-
const newL1ToL2Snapshot = await getTreeSnapshot(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, merkleTrees);
|
|
194
|
-
const txs = await timesParallel(numTxs, i =>
|
|
195
|
-
this.makeProcessedTx({
|
|
196
|
-
seed: i + blockNum * 1000,
|
|
197
|
-
globalVariables,
|
|
198
|
-
newL1ToL2Snapshot,
|
|
199
|
-
...makeProcessedTxOpts(i),
|
|
200
|
-
}),
|
|
201
|
-
);
|
|
202
|
-
await this.setTreeRoots(txs);
|
|
157
|
+
// Return blob fields of all checkpoints in the epoch.
|
|
158
|
+
public getBlobFields() {
|
|
159
|
+
return this.checkpoints.map(checkpoint => checkpoint.toBlobFields());
|
|
160
|
+
}
|
|
203
161
|
|
|
204
|
-
|
|
205
|
-
this.
|
|
206
|
-
await
|
|
207
|
-
return { block, txs, l1ToL2Messages };
|
|
162
|
+
public async getFinalBlobChallenges() {
|
|
163
|
+
const blobFields = this.getBlobFields();
|
|
164
|
+
return await buildFinalBlobChallenges(blobFields);
|
|
208
165
|
}
|
|
209
166
|
|
|
210
|
-
public async
|
|
211
|
-
|
|
167
|
+
public async makeCheckpoint(
|
|
168
|
+
numBlocks: number,
|
|
212
169
|
{
|
|
213
|
-
|
|
170
|
+
numTxsPerBlock = 0,
|
|
214
171
|
numL1ToL2Messages = 0,
|
|
215
|
-
|
|
172
|
+
makeProcessedTxOpts = () => ({}),
|
|
173
|
+
...constantOpts
|
|
216
174
|
}: {
|
|
217
|
-
|
|
175
|
+
numTxsPerBlock?: number | number[];
|
|
218
176
|
numL1ToL2Messages?: number;
|
|
219
|
-
|
|
220
|
-
|
|
177
|
+
makeProcessedTxOpts?: (
|
|
178
|
+
blockGlobalVariables: GlobalVariables,
|
|
179
|
+
txIndex: number,
|
|
180
|
+
) => Partial<Parameters<typeof mockProcessedTx>[0]>;
|
|
181
|
+
} & Partial<FieldsOf<CheckpointConstantData>> = {},
|
|
221
182
|
) {
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
183
|
+
if (numBlocks === 0) {
|
|
184
|
+
throw new Error(
|
|
185
|
+
'Cannot make a checkpoint with 0 blocks. Crate an empty block (numTxsPerBlock = 0) if there are no txs.',
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const checkpointIndex = this.nextCheckpointIndex++;
|
|
190
|
+
const checkpointNumber = CheckpointNumber(checkpointIndex + 1);
|
|
191
|
+
const slotNumber = checkpointNumber * 15; // times an arbitrary number to make it different to the checkpoint number
|
|
192
|
+
|
|
193
|
+
const constants = makeCheckpointConstants(slotNumber, constantOpts);
|
|
194
|
+
|
|
195
|
+
const fork = await this.worldState.fork();
|
|
196
|
+
|
|
197
|
+
// Build l1 to l2 messages.
|
|
198
|
+
const l1ToL2Messages = times(numL1ToL2Messages, i => new Fr(slotNumber * 100 + i));
|
|
199
|
+
await fork.appendLeaves(
|
|
225
200
|
MerkleTreeId.L1_TO_L2_MESSAGE_TREE,
|
|
226
|
-
padArrayEnd(l1ToL2Messages, Fr.ZERO, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP),
|
|
201
|
+
padArrayEnd<Fr, number>(l1ToL2Messages, Fr.ZERO, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP),
|
|
227
202
|
);
|
|
203
|
+
const newL1ToL2Snapshot = await getTreeSnapshot(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, fork);
|
|
228
204
|
|
|
229
|
-
const
|
|
230
|
-
|
|
231
|
-
|
|
205
|
+
const startBlockNumber = this.nextBlockNumber;
|
|
206
|
+
const previousBlockHeader = this.getBlockHeader(BlockNumber(startBlockNumber - 1));
|
|
207
|
+
|
|
208
|
+
// Build global variables.
|
|
209
|
+
const blockGlobalVariables = times(numBlocks, i =>
|
|
210
|
+
makeGlobals(startBlockNumber + i, slotNumber, {
|
|
211
|
+
coinbase: constants.coinbase,
|
|
212
|
+
feeRecipient: constants.feeRecipient,
|
|
213
|
+
gasFees: constants.gasFees,
|
|
214
|
+
}),
|
|
232
215
|
);
|
|
233
|
-
|
|
216
|
+
this.nextBlockNumber += numBlocks;
|
|
234
217
|
|
|
235
|
-
|
|
218
|
+
// Build txs.
|
|
219
|
+
let totalTxs = 0;
|
|
220
|
+
const blockEndStates: StateReference[] = [];
|
|
221
|
+
const blockTxs = await timesAsync(numBlocks, async blockIndex => {
|
|
222
|
+
const txIndexOffset = totalTxs;
|
|
223
|
+
const numTxs = typeof numTxsPerBlock === 'number' ? numTxsPerBlock : numTxsPerBlock[blockIndex];
|
|
224
|
+
totalTxs += numTxs;
|
|
225
|
+
const txs = await timesAsync(numTxs, txIndex =>
|
|
226
|
+
this.makeProcessedTx({
|
|
227
|
+
seed: (txIndexOffset + txIndex + 1) * 321 + (checkpointIndex + 1) * 123456 + this.epochNumber * 0x99999,
|
|
228
|
+
globalVariables: blockGlobalVariables[blockIndex],
|
|
229
|
+
anchorBlockHeader: previousBlockHeader,
|
|
230
|
+
newL1ToL2Snapshot,
|
|
231
|
+
...makeProcessedTxOpts(blockGlobalVariables[blockIndex], txIndexOffset + txIndex),
|
|
232
|
+
}),
|
|
233
|
+
);
|
|
234
|
+
|
|
235
|
+
// Insert side effects into the trees.
|
|
236
|
+
const endState = await this.updateTrees(txs, fork);
|
|
237
|
+
blockEndStates.push(endState);
|
|
238
|
+
|
|
239
|
+
return txs;
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
const cleanFork = await this.worldState.fork();
|
|
243
|
+
const builder = await LightweightCheckpointBuilder.startNewCheckpoint(
|
|
244
|
+
checkpointNumber,
|
|
245
|
+
constants,
|
|
246
|
+
l1ToL2Messages,
|
|
247
|
+
cleanFork,
|
|
248
|
+
);
|
|
249
|
+
|
|
250
|
+
// Add tx effects to db and build block headers.
|
|
251
|
+
const blocks = [];
|
|
252
|
+
for (let i = 0; i < numBlocks; i++) {
|
|
253
|
+
const txs = blockTxs[i];
|
|
254
|
+
const state = blockEndStates[i];
|
|
255
|
+
|
|
256
|
+
const block = await builder.addBlock(blockGlobalVariables[i], state, txs);
|
|
257
|
+
|
|
258
|
+
const header = block.header;
|
|
259
|
+
this.headers.set(block.number, header);
|
|
260
|
+
|
|
261
|
+
const blockMsgs = block.indexWithinCheckpoint === 0 ? l1ToL2Messages : [];
|
|
262
|
+
await this.worldState.handleL2BlockAndMessages(block, blockMsgs);
|
|
263
|
+
|
|
264
|
+
blocks.push({ header, txs });
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const checkpoint = await builder.completeCheckpoint();
|
|
268
|
+
this.checkpoints.push(checkpoint);
|
|
269
|
+
|
|
270
|
+
return {
|
|
271
|
+
constants,
|
|
272
|
+
header: checkpoint.header,
|
|
273
|
+
blocks,
|
|
274
|
+
l1ToL2Messages,
|
|
275
|
+
previousBlockHeader,
|
|
276
|
+
};
|
|
236
277
|
}
|
|
237
278
|
|
|
238
|
-
private async
|
|
239
|
-
const
|
|
279
|
+
private async makeProcessedTx(opts: Parameters<typeof mockProcessedTx>[0] = {}): Promise<ProcessedTx> {
|
|
280
|
+
const tx = await mockProcessedTx({
|
|
281
|
+
vkTreeRoot: getVKTreeRoot(),
|
|
282
|
+
protocolContracts: ProtocolContractsList,
|
|
283
|
+
feePayer: this.feePayer,
|
|
284
|
+
...opts,
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
this.feePayerBalance = new Fr(this.feePayerBalance.toBigInt() - tx.txEffect.transactionFee.toBigInt());
|
|
288
|
+
|
|
289
|
+
const feePayerSlot = await computeFeePayerBalanceLeafSlot(this.feePayer);
|
|
290
|
+
const feePaymentPublicDataWrite = new PublicDataWrite(feePayerSlot, this.feePayerBalance);
|
|
291
|
+
tx.txEffect.publicDataWrites[0] = feePaymentPublicDataWrite;
|
|
292
|
+
if (tx.avmProvingRequest) {
|
|
293
|
+
tx.avmProvingRequest.inputs.publicInputs.accumulatedData.publicDataWrites[0] = feePaymentPublicDataWrite;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
return tx;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
private getBlockHeader(blockNumber: BlockNumber): BlockHeader {
|
|
300
|
+
if (Number(blockNumber) > 0 && Number(blockNumber) >= this.nextBlockNumber) {
|
|
301
|
+
throw new Error(`Block header not built for block number ${blockNumber}.`);
|
|
302
|
+
}
|
|
303
|
+
return Number(blockNumber) === 0
|
|
304
|
+
? this.worldState.getCommitted().getInitialHeader()
|
|
305
|
+
: this.headers.get(Number(blockNumber))!;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
private async updateTrees(txs: ProcessedTx[], fork: MerkleTreeWriteOperations) {
|
|
309
|
+
let startStateReference = await fork.getStateReference();
|
|
310
|
+
let endStateReference = startStateReference;
|
|
240
311
|
for (const tx of txs) {
|
|
241
|
-
|
|
242
|
-
await
|
|
243
|
-
|
|
312
|
+
await insertSideEffects(tx, fork);
|
|
313
|
+
endStateReference = await fork.getStateReference();
|
|
314
|
+
|
|
244
315
|
if (tx.avmProvingRequest) {
|
|
316
|
+
// Update the trees in the avm public inputs so that the proof won't fail.
|
|
245
317
|
const l1ToL2MessageTree = tx.avmProvingRequest.inputs.publicInputs.startTreeSnapshots.l1ToL2MessageTree;
|
|
246
318
|
tx.avmProvingRequest.inputs.publicInputs.startTreeSnapshots = new TreeSnapshots(
|
|
247
319
|
l1ToL2MessageTree,
|
|
@@ -249,6 +321,7 @@ export class TestContext {
|
|
|
249
321
|
startStateReference.partial.nullifierTree,
|
|
250
322
|
startStateReference.partial.publicDataTree,
|
|
251
323
|
);
|
|
324
|
+
|
|
252
325
|
tx.avmProvingRequest.inputs.publicInputs.endTreeSnapshots = new TreeSnapshots(
|
|
253
326
|
l1ToL2MessageTree,
|
|
254
327
|
endStateReference.partial.noteHashTree,
|
|
@@ -256,7 +329,11 @@ export class TestContext {
|
|
|
256
329
|
endStateReference.partial.publicDataTree,
|
|
257
330
|
);
|
|
258
331
|
}
|
|
332
|
+
|
|
333
|
+
startStateReference = endStateReference;
|
|
259
334
|
}
|
|
335
|
+
|
|
336
|
+
return endStateReference;
|
|
260
337
|
}
|
|
261
338
|
}
|
|
262
339
|
|
|
@@ -265,12 +342,9 @@ class TestProvingOrchestrator extends ProvingOrchestrator {
|
|
|
265
342
|
|
|
266
343
|
// Disable this check by default, since it requires seeding world state with the block being built
|
|
267
344
|
// This is only enabled in some tests with multiple blocks that populate the pending chain via makePendingBlock
|
|
268
|
-
protected override verifyBuiltBlockAgainstSyncedState(
|
|
269
|
-
l2Block: L2Block,
|
|
270
|
-
newArchive: AppendOnlyTreeSnapshot,
|
|
271
|
-
): Promise<void> {
|
|
345
|
+
protected override verifyBuiltBlockAgainstSyncedState(provingState: BlockProvingState): Promise<void> {
|
|
272
346
|
if (this.isVerifyBuiltBlockAgainstSyncedStateEnabled) {
|
|
273
|
-
return super.verifyBuiltBlockAgainstSyncedState(
|
|
347
|
+
return super.verifyBuiltBlockAgainstSyncedState(provingState);
|
|
274
348
|
}
|
|
275
349
|
return Promise.resolve();
|
|
276
350
|
}
|