@aztec/prover-node 3.0.0-canary.a9708bd → 3.0.0-devnet.3
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/bin/run-failed-epoch.js +1 -1
- package/dest/config.d.ts +2 -0
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +18 -13
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +15 -6
- package/dest/job/epoch-proving-job.d.ts +6 -4
- package/dest/job/epoch-proving-job.d.ts.map +1 -1
- package/dest/job/epoch-proving-job.js +41 -9
- package/dest/metrics.js +1 -1
- package/dest/monitors/epoch-monitor.d.ts +2 -0
- package/dest/monitors/epoch-monitor.d.ts.map +1 -1
- package/dest/monitors/epoch-monitor.js +8 -0
- package/dest/prover-node-publisher.d.ts +2 -5
- package/dest/prover-node-publisher.d.ts.map +1 -1
- package/dest/prover-node-publisher.js +8 -15
- package/dest/prover-node.d.ts.map +1 -1
- package/dest/prover-node.js +5 -1
- package/dest/prover-publisher-factory.d.ts +2 -0
- package/dest/prover-publisher-factory.d.ts.map +1 -1
- package/dest/prover-publisher-factory.js +6 -0
- package/package.json +23 -23
- package/src/bin/run-failed-epoch.ts +1 -1
- package/src/config.ts +29 -28
- package/src/factory.ts +15 -13
- package/src/job/epoch-proving-job.ts +62 -13
- package/src/metrics.ts +1 -1
- package/src/monitors/epoch-monitor.ts +11 -2
- package/src/prover-node-publisher.ts +13 -22
- package/src/prover-node.ts +5 -2
- package/src/prover-publisher-factory.ts +9 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aztec/prover-node",
|
|
3
|
-
"version": "3.0.0-
|
|
3
|
+
"version": "3.0.0-devnet.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./dest/index.js",
|
|
@@ -56,30 +56,30 @@
|
|
|
56
56
|
]
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
|
-
"@aztec/archiver": "3.0.0-
|
|
60
|
-
"@aztec/bb-prover": "3.0.0-
|
|
61
|
-
"@aztec/blob-lib": "3.0.0-
|
|
62
|
-
"@aztec/blob-sink": "3.0.0-
|
|
63
|
-
"@aztec/constants": "3.0.0-
|
|
64
|
-
"@aztec/epoch-cache": "3.0.0-
|
|
65
|
-
"@aztec/ethereum": "3.0.0-
|
|
66
|
-
"@aztec/foundation": "3.0.0-
|
|
67
|
-
"@aztec/kv-store": "3.0.0-
|
|
68
|
-
"@aztec/l1-artifacts": "3.0.0-
|
|
69
|
-
"@aztec/node-keystore": "3.0.0-
|
|
70
|
-
"@aztec/node-lib": "3.0.0-
|
|
71
|
-
"@aztec/noir-protocol-circuits-types": "3.0.0-
|
|
72
|
-
"@aztec/p2p": "3.0.0-
|
|
73
|
-
"@aztec/protocol-contracts": "3.0.0-
|
|
74
|
-
"@aztec/prover-client": "3.0.0-
|
|
75
|
-
"@aztec/sequencer-client": "3.0.0-
|
|
76
|
-
"@aztec/simulator": "3.0.0-
|
|
77
|
-
"@aztec/stdlib": "3.0.0-
|
|
78
|
-
"@aztec/telemetry-client": "3.0.0-
|
|
79
|
-
"@aztec/world-state": "3.0.0-
|
|
59
|
+
"@aztec/archiver": "3.0.0-devnet.3",
|
|
60
|
+
"@aztec/bb-prover": "3.0.0-devnet.3",
|
|
61
|
+
"@aztec/blob-lib": "3.0.0-devnet.3",
|
|
62
|
+
"@aztec/blob-sink": "3.0.0-devnet.3",
|
|
63
|
+
"@aztec/constants": "3.0.0-devnet.3",
|
|
64
|
+
"@aztec/epoch-cache": "3.0.0-devnet.3",
|
|
65
|
+
"@aztec/ethereum": "3.0.0-devnet.3",
|
|
66
|
+
"@aztec/foundation": "3.0.0-devnet.3",
|
|
67
|
+
"@aztec/kv-store": "3.0.0-devnet.3",
|
|
68
|
+
"@aztec/l1-artifacts": "3.0.0-devnet.3",
|
|
69
|
+
"@aztec/node-keystore": "3.0.0-devnet.3",
|
|
70
|
+
"@aztec/node-lib": "3.0.0-devnet.3",
|
|
71
|
+
"@aztec/noir-protocol-circuits-types": "3.0.0-devnet.3",
|
|
72
|
+
"@aztec/p2p": "3.0.0-devnet.3",
|
|
73
|
+
"@aztec/protocol-contracts": "3.0.0-devnet.3",
|
|
74
|
+
"@aztec/prover-client": "3.0.0-devnet.3",
|
|
75
|
+
"@aztec/sequencer-client": "3.0.0-devnet.3",
|
|
76
|
+
"@aztec/simulator": "3.0.0-devnet.3",
|
|
77
|
+
"@aztec/stdlib": "3.0.0-devnet.3",
|
|
78
|
+
"@aztec/telemetry-client": "3.0.0-devnet.3",
|
|
79
|
+
"@aztec/world-state": "3.0.0-devnet.3",
|
|
80
80
|
"source-map-support": "^0.5.21",
|
|
81
81
|
"tslib": "^2.4.0",
|
|
82
|
-
"viem": "2.
|
|
82
|
+
"viem": "npm:@spalladino/viem@2.38.2-eip7594.0"
|
|
83
83
|
},
|
|
84
84
|
"devDependencies": {
|
|
85
85
|
"@jest/globals": "^30.0.0",
|
|
@@ -25,7 +25,7 @@ async function rerunFailedEpoch(provingJobUrl: string, baseLocalDir: string) {
|
|
|
25
25
|
const config = {
|
|
26
26
|
...getProverNodeConfigFromEnv(),
|
|
27
27
|
dataDirectory: dataDir,
|
|
28
|
-
|
|
28
|
+
dataStoreMapSizeKb: env.dataStoreMapSizeKb ?? 1024 * 1024,
|
|
29
29
|
proverId: env.proverId ?? EthAddress.random(),
|
|
30
30
|
};
|
|
31
31
|
|
package/src/config.ts
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
import { type ArchiverConfig, archiverConfigMappings } from '@aztec/archiver/config';
|
|
2
2
|
import type { ACVMConfig, BBConfig } from '@aztec/bb-prover/config';
|
|
3
3
|
import { type GenesisStateConfig, genesisStateConfigMappings } from '@aztec/ethereum';
|
|
4
|
-
import { type ConfigMappingsType, getConfigFromMappings, numberConfigHelper } from '@aztec/foundation/config';
|
|
5
|
-
import { type DataStoreConfig, dataConfigMappings } from '@aztec/kv-store/config';
|
|
6
4
|
import {
|
|
7
|
-
type
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
} from '@aztec/node-keystore';
|
|
5
|
+
type ConfigMappingsType,
|
|
6
|
+
booleanConfigHelper,
|
|
7
|
+
getConfigFromMappings,
|
|
8
|
+
numberConfigHelper,
|
|
9
|
+
} from '@aztec/foundation/config';
|
|
10
|
+
import { type DataStoreConfig, dataConfigMappings } from '@aztec/kv-store/config';
|
|
11
|
+
import { type KeyStore, type KeyStoreConfig, ethPrivateKeySchema, keyStoreConfigMappings } from '@aztec/node-keystore';
|
|
14
12
|
import { type SharedNodeConfig, sharedNodeConfigMappings } from '@aztec/node-lib/config';
|
|
15
13
|
import { type P2PConfig, p2pConfigMappings } from '@aztec/p2p/config';
|
|
16
14
|
import {
|
|
@@ -45,6 +43,8 @@ export type SpecificProverNodeConfig = {
|
|
|
45
43
|
proverNodePollingIntervalMs: number;
|
|
46
44
|
proverNodeMaxParallelBlocksPerEpoch: number;
|
|
47
45
|
proverNodeFailedEpochStore: string | undefined;
|
|
46
|
+
proverNodeEpochProvingDelayMs: number | undefined;
|
|
47
|
+
proverNodeDisableProofPublish?: boolean;
|
|
48
48
|
txGatheringTimeoutMs: number;
|
|
49
49
|
txGatheringIntervalMs: number;
|
|
50
50
|
txGatheringBatchSize: number;
|
|
@@ -72,6 +72,10 @@ const specificProverNodeConfigMappings: ConfigMappingsType<SpecificProverNodeCon
|
|
|
72
72
|
description: 'File store where to upload node state when an epoch fails to be proven',
|
|
73
73
|
defaultValue: undefined,
|
|
74
74
|
},
|
|
75
|
+
proverNodeEpochProvingDelayMs: {
|
|
76
|
+
description: 'Optional delay in milliseconds to wait before proving a new epoch',
|
|
77
|
+
defaultValue: undefined,
|
|
78
|
+
},
|
|
75
79
|
txGatheringIntervalMs: {
|
|
76
80
|
env: 'PROVER_NODE_TX_GATHERING_INTERVAL_MS',
|
|
77
81
|
description: 'How often to check that tx data is available',
|
|
@@ -92,6 +96,11 @@ const specificProverNodeConfigMappings: ConfigMappingsType<SpecificProverNodeCon
|
|
|
92
96
|
description: 'How long to wait for tx data to be available before giving up',
|
|
93
97
|
...numberConfigHelper(120_000),
|
|
94
98
|
},
|
|
99
|
+
proverNodeDisableProofPublish: {
|
|
100
|
+
env: 'PROVER_NODE_DISABLE_PROOF_PUBLISH',
|
|
101
|
+
description: 'Whether the prover node skips publishing proofs to L1',
|
|
102
|
+
...booleanConfigHelper(false),
|
|
103
|
+
},
|
|
95
104
|
};
|
|
96
105
|
|
|
97
106
|
export const proverNodeConfigMappings: ConfigMappingsType<ProverNodeConfig> = {
|
|
@@ -125,19 +134,14 @@ export function getProverNodeAgentConfigFromEnv(): ProverAgentConfig & BBConfig
|
|
|
125
134
|
};
|
|
126
135
|
}
|
|
127
136
|
|
|
128
|
-
function createKeyStoreFromWeb3Signer(config: ProverNodeConfig) {
|
|
129
|
-
// See what we have been given for proverId.
|
|
130
|
-
const proverId = config.proverId ? (config.proverId.toString() as EthAddressHex) : undefined;
|
|
131
|
-
|
|
137
|
+
function createKeyStoreFromWeb3Signer(config: ProverNodeConfig): KeyStore | undefined {
|
|
132
138
|
// If we don't have a valid prover Id then we can't build a valid key store with remote signers
|
|
133
|
-
if (proverId === undefined) {
|
|
139
|
+
if (config.proverId === undefined) {
|
|
134
140
|
return undefined;
|
|
135
141
|
}
|
|
136
142
|
|
|
137
143
|
// Also, we need at least one publisher address.
|
|
138
|
-
const publishers = config.publisherAddresses
|
|
139
|
-
? config.publisherAddresses.map(k => k.toChecksumString() as EthRemoteSignerAccount)
|
|
140
|
-
: [];
|
|
144
|
+
const publishers = config.publisherAddresses ?? [];
|
|
141
145
|
|
|
142
146
|
if (publishers.length === 0) {
|
|
143
147
|
return undefined;
|
|
@@ -147,7 +151,7 @@ function createKeyStoreFromWeb3Signer(config: ProverNodeConfig) {
|
|
|
147
151
|
schemaVersion: 1,
|
|
148
152
|
slasher: undefined,
|
|
149
153
|
prover: {
|
|
150
|
-
id: proverId,
|
|
154
|
+
id: config.proverId,
|
|
151
155
|
publisher: publishers,
|
|
152
156
|
},
|
|
153
157
|
remoteSigner: config.web3SignerUrl,
|
|
@@ -156,10 +160,10 @@ function createKeyStoreFromWeb3Signer(config: ProverNodeConfig) {
|
|
|
156
160
|
return keyStore;
|
|
157
161
|
}
|
|
158
162
|
|
|
159
|
-
function createKeyStoreFromPublisherKeys(config: ProverNodeConfig) {
|
|
163
|
+
function createKeyStoreFromPublisherKeys(config: ProverNodeConfig): KeyStore | undefined {
|
|
160
164
|
// Extract the publisher keys from the provided config.
|
|
161
165
|
const publisherKeys = config.publisherPrivateKeys
|
|
162
|
-
? config.publisherPrivateKeys.map(k => k.getValue()
|
|
166
|
+
? config.publisherPrivateKeys.map(k => ethPrivateKeySchema.parse(k.getValue()))
|
|
163
167
|
: [];
|
|
164
168
|
|
|
165
169
|
// There must be at least 1.
|
|
@@ -167,9 +171,6 @@ function createKeyStoreFromPublisherKeys(config: ProverNodeConfig) {
|
|
|
167
171
|
return undefined;
|
|
168
172
|
}
|
|
169
173
|
|
|
170
|
-
// Now see what we have been given for proverId.
|
|
171
|
-
const proverId = config.proverId ? (config.proverId.toString() as EthAddressHex) : undefined;
|
|
172
|
-
|
|
173
174
|
// If we have a valid proverId then create a prover key store of the form { id, publisher: [publisherKeys] }
|
|
174
175
|
// Otherwise create one of the form ("0x12345678....." as EthAccount).
|
|
175
176
|
|
|
@@ -177,11 +178,11 @@ function createKeyStoreFromPublisherKeys(config: ProverNodeConfig) {
|
|
|
177
178
|
schemaVersion: 1,
|
|
178
179
|
slasher: undefined,
|
|
179
180
|
prover:
|
|
180
|
-
proverId === undefined
|
|
181
|
-
?
|
|
181
|
+
config.proverId === undefined
|
|
182
|
+
? publisherKeys[0]
|
|
182
183
|
: {
|
|
183
|
-
id: proverId,
|
|
184
|
-
publisher: publisherKeys
|
|
184
|
+
id: config.proverId,
|
|
185
|
+
publisher: publisherKeys,
|
|
185
186
|
},
|
|
186
187
|
remoteSigner: undefined,
|
|
187
188
|
validators: undefined,
|
|
@@ -189,7 +190,7 @@ function createKeyStoreFromPublisherKeys(config: ProverNodeConfig) {
|
|
|
189
190
|
return keyStore;
|
|
190
191
|
}
|
|
191
192
|
|
|
192
|
-
export function createKeyStoreForProver(config: ProverNodeConfig) {
|
|
193
|
+
export function createKeyStoreForProver(config: ProverNodeConfig): KeyStore | undefined {
|
|
193
194
|
if (config.web3SignerUrl !== undefined && config.web3SignerUrl.length > 0) {
|
|
194
195
|
return createKeyStoreFromWeb3Signer(config);
|
|
195
196
|
}
|
package/src/factory.ts
CHANGED
|
@@ -2,20 +2,14 @@ import { type Archiver, createArchiver } from '@aztec/archiver';
|
|
|
2
2
|
import { BBCircuitVerifier, QueuedIVCVerifier, TestCircuitVerifier } from '@aztec/bb-prover';
|
|
3
3
|
import { type BlobSinkClientInterface, createBlobSinkClient } from '@aztec/blob-sink/client';
|
|
4
4
|
import { EpochCache } from '@aztec/epoch-cache';
|
|
5
|
-
import {
|
|
6
|
-
type EthSigner,
|
|
7
|
-
L1TxUtils,
|
|
8
|
-
PublisherManager,
|
|
9
|
-
RollupContract,
|
|
10
|
-
createEthereumChain,
|
|
11
|
-
createL1TxUtilsFromEthSigner,
|
|
12
|
-
} from '@aztec/ethereum';
|
|
5
|
+
import { L1TxUtils, PublisherManager, RollupContract, createEthereumChain } from '@aztec/ethereum';
|
|
13
6
|
import { pick } from '@aztec/foundation/collection';
|
|
14
7
|
import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
15
8
|
import { DateProvider } from '@aztec/foundation/timer';
|
|
16
9
|
import type { DataStoreConfig } from '@aztec/kv-store/config';
|
|
17
10
|
import { type KeyStoreConfig, KeystoreManager, loadKeystores, mergeKeystores } from '@aztec/node-keystore';
|
|
18
11
|
import { trySnapshotSync } from '@aztec/node-lib/actions';
|
|
12
|
+
import { createL1TxUtilsFromEthSignerWithStore } from '@aztec/node-lib/factories';
|
|
19
13
|
import { NodeRpcTxSource, createP2PClient } from '@aztec/p2p';
|
|
20
14
|
import { type ProverClientConfig, createProverClient } from '@aztec/prover-client';
|
|
21
15
|
import { createAndStartProvingBroker } from '@aztec/prover-client/broker';
|
|
@@ -73,6 +67,8 @@ export async function createProverNode(
|
|
|
73
67
|
}
|
|
74
68
|
}
|
|
75
69
|
|
|
70
|
+
await keyStoreManager?.validateSigners();
|
|
71
|
+
|
|
76
72
|
// Extract the prover signers from the key store and verify that we have one.
|
|
77
73
|
const proverSigners = keyStoreManager?.createProverSigners();
|
|
78
74
|
|
|
@@ -86,6 +82,8 @@ export async function createProverNode(
|
|
|
86
82
|
);
|
|
87
83
|
}
|
|
88
84
|
|
|
85
|
+
log.info(`Creating prover with publishers ${proverSigners.signers.map(signer => signer.address.toString()).join()}`);
|
|
86
|
+
|
|
89
87
|
// Only consider user provided config if it is valid
|
|
90
88
|
const proverIdInUserConfig = config.proverId === undefined || config.proverId.isZero() ? undefined : config.proverId;
|
|
91
89
|
|
|
@@ -133,15 +131,18 @@ export async function createProverNode(
|
|
|
133
131
|
|
|
134
132
|
const l1TxUtils = deps.l1TxUtils
|
|
135
133
|
? [deps.l1TxUtils]
|
|
136
|
-
:
|
|
137
|
-
|
|
138
|
-
|
|
134
|
+
: await createL1TxUtilsFromEthSignerWithStore(
|
|
135
|
+
publicClient,
|
|
136
|
+
proverSigners.signers,
|
|
137
|
+
{ ...config, scope: 'prover' },
|
|
138
|
+
{ telemetry, logger: log.createChild('l1-tx-utils'), dateProvider },
|
|
139
|
+
);
|
|
139
140
|
|
|
140
141
|
const publisherFactory =
|
|
141
142
|
deps.publisherFactory ??
|
|
142
143
|
new ProverPublisherFactory(config, {
|
|
143
144
|
rollupContract,
|
|
144
|
-
publisherManager: new PublisherManager(l1TxUtils),
|
|
145
|
+
publisherManager: new PublisherManager(l1TxUtils, config),
|
|
145
146
|
telemetry,
|
|
146
147
|
});
|
|
147
148
|
|
|
@@ -175,6 +176,7 @@ export async function createProverNode(
|
|
|
175
176
|
'proverNodeMaxPendingJobs',
|
|
176
177
|
'proverNodeMaxParallelBlocksPerEpoch',
|
|
177
178
|
'proverNodePollingIntervalMs',
|
|
179
|
+
'proverNodeEpochProvingDelayMs',
|
|
178
180
|
'txGatheringMaxParallelRequests',
|
|
179
181
|
'txGatheringIntervalMs',
|
|
180
182
|
'txGatheringTimeoutMs',
|
|
@@ -187,7 +189,7 @@ export async function createProverNode(
|
|
|
187
189
|
|
|
188
190
|
const epochMonitor = await EpochMonitor.create(
|
|
189
191
|
archiver,
|
|
190
|
-
{ pollingIntervalMs: config.proverNodePollingIntervalMs },
|
|
192
|
+
{ pollingIntervalMs: config.proverNodePollingIntervalMs, provingDelayMs: config.proverNodeEpochProvingDelayMs },
|
|
191
193
|
telemetry,
|
|
192
194
|
);
|
|
193
195
|
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { BatchedBlob, Blob } from '@aztec/blob-lib';
|
|
2
1
|
import { NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP } from '@aztec/constants';
|
|
3
2
|
import { asyncPool } from '@aztec/foundation/async-pool';
|
|
4
3
|
import { padArrayEnd } from '@aztec/foundation/collection';
|
|
@@ -6,6 +5,9 @@ import { Fr } from '@aztec/foundation/fields';
|
|
|
6
5
|
import { createLogger } from '@aztec/foundation/log';
|
|
7
6
|
import { RunningPromise, promiseWithResolvers } from '@aztec/foundation/promise';
|
|
8
7
|
import { Timer } from '@aztec/foundation/timer';
|
|
8
|
+
import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree';
|
|
9
|
+
import { protocolContractsHash } from '@aztec/protocol-contracts';
|
|
10
|
+
import { buildFinalBlobChallenges } from '@aztec/prover-client/helpers';
|
|
9
11
|
import type { PublicProcessor, PublicProcessorFactory } from '@aztec/simulator/server';
|
|
10
12
|
import type { L2Block, L2BlockSource } from '@aztec/stdlib/block';
|
|
11
13
|
import {
|
|
@@ -14,6 +16,7 @@ import {
|
|
|
14
16
|
EpochProvingJobTerminalState,
|
|
15
17
|
type ForkMerkleTreeOperations,
|
|
16
18
|
} from '@aztec/stdlib/interfaces/server';
|
|
19
|
+
import { CheckpointConstantData } from '@aztec/stdlib/rollup';
|
|
17
20
|
import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
18
21
|
import type { ProcessedTx, Tx } from '@aztec/stdlib/tx';
|
|
19
22
|
import { Attributes, type Traceable, type Tracer, trackSpan } from '@aztec/telemetry-client';
|
|
@@ -24,6 +27,12 @@ import type { ProverNodeJobMetrics } from '../metrics.js';
|
|
|
24
27
|
import type { ProverNodePublisher } from '../prover-node-publisher.js';
|
|
25
28
|
import { type EpochProvingJobData, validateEpochProvingJobData } from './epoch-proving-job-data.js';
|
|
26
29
|
|
|
30
|
+
export type EpochProvingJobOptions = {
|
|
31
|
+
parallelBlockLimit?: number;
|
|
32
|
+
skipEpochCheck?: boolean;
|
|
33
|
+
skipSubmitProof?: boolean;
|
|
34
|
+
};
|
|
35
|
+
|
|
27
36
|
/**
|
|
28
37
|
* Job that grabs a range of blocks from the unfinalized chain from L1, gets their txs given their hashes,
|
|
29
38
|
* re-executes their public calls, generates a rollup proof, and submits it to L1. This job will update the
|
|
@@ -49,7 +58,7 @@ export class EpochProvingJob implements Traceable {
|
|
|
49
58
|
private l2BlockSource: L2BlockSource | undefined,
|
|
50
59
|
private metrics: ProverNodeJobMetrics,
|
|
51
60
|
private deadline: Date | undefined,
|
|
52
|
-
private config:
|
|
61
|
+
private config: EpochProvingJobOptions,
|
|
53
62
|
) {
|
|
54
63
|
validateEpochProvingJobData(data);
|
|
55
64
|
this.uuid = crypto.randomUUID();
|
|
@@ -123,12 +132,14 @@ export class EpochProvingJob implements Traceable {
|
|
|
123
132
|
this.runPromise = promise;
|
|
124
133
|
|
|
125
134
|
try {
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
|
|
135
|
+
const blobFieldsPerCheckpoint = this.blocks.map(block => block.getCheckpointBlobFields());
|
|
136
|
+
const finalBlobBatchingChallenges = await buildFinalBlobChallenges(blobFieldsPerCheckpoint);
|
|
137
|
+
|
|
138
|
+
// TODO(#17027): Enable multiple blocks per checkpoint.
|
|
139
|
+
// Total number of checkpoints equals number of blocks because we currently build a checkpoint with only one block.
|
|
140
|
+
const totalNumCheckpoints = epochSizeBlocks;
|
|
129
141
|
|
|
130
|
-
|
|
131
|
-
this.prover.startNewEpoch(epochNumber, fromBlock, epochSizeBlocks, finalBlobBatchingChallenges);
|
|
142
|
+
this.prover.startNewEpoch(epochNumber, totalNumCheckpoints, finalBlobBatchingChallenges);
|
|
132
143
|
await this.prover.startTubeCircuits(Array.from(this.txs.values()));
|
|
133
144
|
|
|
134
145
|
await asyncPool(this.config.parallelBlockLimit ?? 32, this.blocks, async block => {
|
|
@@ -151,12 +162,41 @@ export class EpochProvingJob implements Traceable {
|
|
|
151
162
|
...globalVariables,
|
|
152
163
|
});
|
|
153
164
|
|
|
165
|
+
const checkpointConstants = CheckpointConstantData.from({
|
|
166
|
+
chainId: globalVariables.chainId,
|
|
167
|
+
version: globalVariables.version,
|
|
168
|
+
vkTreeRoot: getVKTreeRoot(),
|
|
169
|
+
protocolContractsHash: protocolContractsHash,
|
|
170
|
+
proverId: this.prover.getProverId().toField(),
|
|
171
|
+
slotNumber: globalVariables.slotNumber,
|
|
172
|
+
coinbase: globalVariables.coinbase,
|
|
173
|
+
feeRecipient: globalVariables.feeRecipient,
|
|
174
|
+
gasFees: globalVariables.gasFees,
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
// TODO(#17027): Enable multiple blocks per checkpoint.
|
|
178
|
+
// Each checkpoint has only one block.
|
|
179
|
+
const totalNumBlocks = 1;
|
|
180
|
+
const checkpointIndex = block.number - fromBlock;
|
|
181
|
+
await this.prover.startNewCheckpoint(
|
|
182
|
+
checkpointIndex,
|
|
183
|
+
checkpointConstants,
|
|
184
|
+
l1ToL2Messages,
|
|
185
|
+
totalNumBlocks,
|
|
186
|
+
blobFieldsPerCheckpoint[checkpointIndex].length,
|
|
187
|
+
previousHeader,
|
|
188
|
+
);
|
|
189
|
+
|
|
154
190
|
// Start block proving
|
|
155
|
-
await this.prover.startNewBlock(
|
|
191
|
+
await this.prover.startNewBlock(block.number, globalVariables.timestamp, txs.length);
|
|
156
192
|
|
|
157
193
|
// Process public fns
|
|
158
194
|
const db = await this.createFork(block.number - 1, l1ToL2Messages);
|
|
159
|
-
const publicProcessor = this.publicProcessorFactory.create(db, globalVariables,
|
|
195
|
+
const publicProcessor = this.publicProcessorFactory.create(db, globalVariables, {
|
|
196
|
+
skipFeeEnforcement: true,
|
|
197
|
+
clientInitiatedSimulation: false,
|
|
198
|
+
proverId: this.prover.getProverId().toField(),
|
|
199
|
+
});
|
|
160
200
|
const processed = await this.processTxs(publicProcessor, txs);
|
|
161
201
|
await this.prover.addTxs(processed);
|
|
162
202
|
await db.close();
|
|
@@ -167,7 +207,8 @@ export class EpochProvingJob implements Traceable {
|
|
|
167
207
|
});
|
|
168
208
|
|
|
169
209
|
// Mark block as completed to pad it
|
|
170
|
-
|
|
210
|
+
const expectedBlockHeader = block.getBlockHeader();
|
|
211
|
+
await this.prover.setBlockCompleted(block.number, expectedBlockHeader);
|
|
171
212
|
});
|
|
172
213
|
|
|
173
214
|
const executionTime = timer.ms();
|
|
@@ -178,6 +219,15 @@ export class EpochProvingJob implements Traceable {
|
|
|
178
219
|
|
|
179
220
|
this.progressState('publishing-proof');
|
|
180
221
|
|
|
222
|
+
if (this.config.skipSubmitProof) {
|
|
223
|
+
this.log.info(
|
|
224
|
+
`Proof publishing is disabled. Dropping valid proof for epoch ${epochNumber} (blocks ${fromBlock} to ${toBlock})`,
|
|
225
|
+
);
|
|
226
|
+
this.state = 'completed';
|
|
227
|
+
this.metrics.recordProvingJob(executionTime, timer.ms(), epochSizeBlocks, epochSizeTxs);
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
|
|
181
231
|
const success = await this.publisher.submitEpochProof({
|
|
182
232
|
fromBlock,
|
|
183
233
|
toBlock,
|
|
@@ -224,7 +274,7 @@ export class EpochProvingJob implements Traceable {
|
|
|
224
274
|
*/
|
|
225
275
|
private async createFork(blockNumber: number, l1ToL2Messages: Fr[]) {
|
|
226
276
|
const db = await this.dbProvider.fork(blockNumber);
|
|
227
|
-
const l1ToL2MessagesPadded = padArrayEnd(
|
|
277
|
+
const l1ToL2MessagesPadded = padArrayEnd<Fr, number>(
|
|
228
278
|
l1ToL2Messages,
|
|
229
279
|
Fr.ZERO,
|
|
230
280
|
NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP,
|
|
@@ -252,7 +302,6 @@ export class EpochProvingJob implements Traceable {
|
|
|
252
302
|
public async stop(state: EpochProvingJobTerminalState = 'stopped') {
|
|
253
303
|
this.state = state;
|
|
254
304
|
this.prover.cancel();
|
|
255
|
-
// TODO(palla/prover): Stop the publisher as well
|
|
256
305
|
if (this.runPromise) {
|
|
257
306
|
await this.runPromise;
|
|
258
307
|
}
|
|
@@ -318,7 +367,7 @@ export class EpochProvingJob implements Traceable {
|
|
|
318
367
|
private getBlockHeader(blockNumber: number) {
|
|
319
368
|
const block = this.blocks.find(b => b.number === blockNumber);
|
|
320
369
|
if (block) {
|
|
321
|
-
return block.
|
|
370
|
+
return block.getBlockHeader();
|
|
322
371
|
}
|
|
323
372
|
|
|
324
373
|
if (blockNumber === Number(this.data.previousBlockHeader.getBlockNumber())) {
|
package/src/metrics.ts
CHANGED
|
@@ -91,7 +91,7 @@ export class ProverNodeRewardsMetrics {
|
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
private observe = async (observer: BatchObservableResult): Promise<void> => {
|
|
94
|
-
const epoch = await this.rollup.
|
|
94
|
+
const epoch = await this.rollup.getCurrentEpochNumber();
|
|
95
95
|
|
|
96
96
|
if (epoch > this.proofSubmissionEpochs) {
|
|
97
97
|
// look at the prev epoch so that we get an accurate value, after proof submission window has closed
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createLogger } from '@aztec/foundation/log';
|
|
2
2
|
import { RunningPromise } from '@aztec/foundation/running-promise';
|
|
3
|
+
import { sleep } from '@aztec/foundation/sleep';
|
|
3
4
|
import type { L2BlockSource } from '@aztec/stdlib/block';
|
|
4
5
|
import { type L1RollupConstants, getEpochAtSlot } from '@aztec/stdlib/epoch-helpers';
|
|
5
6
|
import {
|
|
@@ -36,16 +37,19 @@ export class EpochMonitor implements Traceable {
|
|
|
36
37
|
constructor(
|
|
37
38
|
private readonly l2BlockSource: L2BlockSource,
|
|
38
39
|
private readonly l1Constants: Pick<L1RollupConstants, 'epochDuration'>,
|
|
39
|
-
private options: { pollingIntervalMs: number },
|
|
40
|
+
private options: { pollingIntervalMs: number; provingDelayMs?: number },
|
|
40
41
|
telemetry: TelemetryClient = getTelemetryClient(),
|
|
41
42
|
) {
|
|
42
43
|
this.tracer = telemetry.getTracer('EpochMonitor');
|
|
43
44
|
this.runningPromise = new RunningPromise(this.work.bind(this), this.log, this.options.pollingIntervalMs);
|
|
45
|
+
if (this.options.provingDelayMs) {
|
|
46
|
+
this.log.warn(`Prover node epoch monitor running with delay of ${this.options.provingDelayMs}ms`);
|
|
47
|
+
}
|
|
44
48
|
}
|
|
45
49
|
|
|
46
50
|
public static async create(
|
|
47
51
|
l2BlockSource: L2BlockSource,
|
|
48
|
-
options: { pollingIntervalMs: number },
|
|
52
|
+
options: { pollingIntervalMs: number; provingDelayMs?: number },
|
|
49
53
|
telemetry: TelemetryClient = getTelemetryClient(),
|
|
50
54
|
): Promise<EpochMonitor> {
|
|
51
55
|
const l1Constants = await l2BlockSource.getL1Constants();
|
|
@@ -87,6 +91,11 @@ export class EpochMonitor implements Traceable {
|
|
|
87
91
|
return;
|
|
88
92
|
}
|
|
89
93
|
|
|
94
|
+
if (this.options.provingDelayMs) {
|
|
95
|
+
this.log.debug(`Waiting ${this.options.provingDelayMs}ms before proving epoch ${epochToProve}`);
|
|
96
|
+
await sleep(this.options.provingDelayMs);
|
|
97
|
+
}
|
|
98
|
+
|
|
90
99
|
this.log.debug(`Epoch ${epochToProve} is ready to be proven`);
|
|
91
100
|
if (await this.handler?.handleEpochReadyToProve(epochToProve)) {
|
|
92
101
|
this.latestEpochNumber = epochToProve;
|
|
@@ -1,21 +1,16 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { BatchedBlob } from '@aztec/blob-lib';
|
|
2
2
|
import { AZTEC_MAX_EPOCH_DURATION } from '@aztec/constants';
|
|
3
|
-
import {
|
|
4
|
-
type L1TxUtils,
|
|
5
|
-
type RollupContract,
|
|
6
|
-
RollupContract as RollupContractClass,
|
|
7
|
-
type ViemCommitteeAttestation,
|
|
8
|
-
} from '@aztec/ethereum';
|
|
3
|
+
import type { L1TxUtils, RollupContract, ViemCommitteeAttestation } from '@aztec/ethereum';
|
|
9
4
|
import { makeTuple } from '@aztec/foundation/array';
|
|
10
5
|
import { areArraysEqual } from '@aztec/foundation/collection';
|
|
11
6
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
12
7
|
import { Fr } from '@aztec/foundation/fields';
|
|
13
8
|
import { createLogger } from '@aztec/foundation/log';
|
|
14
9
|
import type { Tuple } from '@aztec/foundation/serialize';
|
|
15
|
-
import { InterruptibleSleep } from '@aztec/foundation/sleep';
|
|
16
10
|
import { Timer } from '@aztec/foundation/timer';
|
|
17
11
|
import { RollupAbi } from '@aztec/l1-artifacts';
|
|
18
12
|
import type { PublisherConfig, TxSenderConfig } from '@aztec/sequencer-client';
|
|
13
|
+
import { CommitteeAttestation, CommitteeAttestationsAndSigners } from '@aztec/stdlib/block';
|
|
19
14
|
import type { Proof } from '@aztec/stdlib/proofs';
|
|
20
15
|
import type { FeeRecipient, RootRollupPublicInputs } from '@aztec/stdlib/rollup';
|
|
21
16
|
import type { L1PublishProofStats } from '@aztec/stdlib/stats';
|
|
@@ -39,8 +34,6 @@ export type L1SubmitEpochProofArgs = {
|
|
|
39
34
|
};
|
|
40
35
|
|
|
41
36
|
export class ProverNodePublisher {
|
|
42
|
-
private interruptibleSleep = new InterruptibleSleep();
|
|
43
|
-
private sleepTimeMs: number;
|
|
44
37
|
private interrupted = false;
|
|
45
38
|
private metrics: ProverNodePublisherMetrics;
|
|
46
39
|
|
|
@@ -58,8 +51,6 @@ export class ProverNodePublisher {
|
|
|
58
51
|
telemetry?: TelemetryClient;
|
|
59
52
|
},
|
|
60
53
|
) {
|
|
61
|
-
this.sleepTimeMs = config?.l1PublishRetryIntervalMS ?? 60_000;
|
|
62
|
-
|
|
63
54
|
const telemetry = deps.telemetry ?? getTelemetryClient();
|
|
64
55
|
|
|
65
56
|
this.metrics = new ProverNodePublisherMetrics(telemetry, 'ProverNode');
|
|
@@ -80,12 +71,13 @@ export class ProverNodePublisher {
|
|
|
80
71
|
*/
|
|
81
72
|
public interrupt() {
|
|
82
73
|
this.interrupted = true;
|
|
83
|
-
this.
|
|
74
|
+
this.l1TxUtils.interrupt();
|
|
84
75
|
}
|
|
85
76
|
|
|
86
77
|
/** Restarts the publisher after calling `interrupt`. */
|
|
87
78
|
public restart() {
|
|
88
79
|
this.interrupted = false;
|
|
80
|
+
this.l1TxUtils.restart();
|
|
89
81
|
}
|
|
90
82
|
|
|
91
83
|
public getSenderAddress() {
|
|
@@ -103,6 +95,7 @@ export class ProverNodePublisher {
|
|
|
103
95
|
}): Promise<boolean> {
|
|
104
96
|
const { epochNumber, fromBlock, toBlock } = args;
|
|
105
97
|
const ctx = { epochNumber, fromBlock, toBlock };
|
|
98
|
+
|
|
106
99
|
if (!this.interrupted) {
|
|
107
100
|
const timer = new Timer();
|
|
108
101
|
// Validate epoch proof range and hashes are correct before submitting
|
|
@@ -143,7 +136,6 @@ export class ProverNodePublisher {
|
|
|
143
136
|
|
|
144
137
|
this.metrics.recordFailedTx();
|
|
145
138
|
this.log.error(`Rollup.submitEpochProof tx status failed ${txReceipt.transactionHash}`, undefined, ctx);
|
|
146
|
-
await this.sleepOrInterrupted();
|
|
147
139
|
}
|
|
148
140
|
|
|
149
141
|
this.log.verbose('L2 block data syncing interrupted', ctx);
|
|
@@ -188,9 +180,10 @@ export class ProverNodePublisher {
|
|
|
188
180
|
}
|
|
189
181
|
|
|
190
182
|
// Check the batched blob inputs from the root rollup against the batched blob computed in ts
|
|
191
|
-
|
|
183
|
+
const finalBlobAccumulator = batchedBlobInputs.toFinalBlobAccumulator();
|
|
184
|
+
if (!publicInputs.blobPublicInputs.equals(finalBlobAccumulator)) {
|
|
192
185
|
throw new Error(
|
|
193
|
-
`Batched blob mismatch: ${inspect(publicInputs.blobPublicInputs)} !== ${inspect(
|
|
186
|
+
`Batched blob mismatch: ${inspect(publicInputs.blobPublicInputs)} !== ${inspect(finalBlobAccumulator)}`,
|
|
194
187
|
);
|
|
195
188
|
}
|
|
196
189
|
|
|
@@ -263,7 +256,7 @@ export class ProverNodePublisher {
|
|
|
263
256
|
{
|
|
264
257
|
previousArchive: args.publicInputs.previousArchiveRoot.toString(),
|
|
265
258
|
endArchive: args.publicInputs.endArchiveRoot.toString(),
|
|
266
|
-
proverId: EthAddress.fromField(args.publicInputs.proverId).toString(),
|
|
259
|
+
proverId: EthAddress.fromField(args.publicInputs.constants.proverId).toString(),
|
|
267
260
|
} /*_args*/,
|
|
268
261
|
makeTuple(AZTEC_MAX_EPOCH_DURATION * 2, i =>
|
|
269
262
|
i % 2 === 0
|
|
@@ -290,13 +283,11 @@ export class ProverNodePublisher {
|
|
|
290
283
|
end: argsArray[1],
|
|
291
284
|
args: argsArray[2],
|
|
292
285
|
fees: argsArray[3],
|
|
293
|
-
attestations:
|
|
286
|
+
attestations: new CommitteeAttestationsAndSigners(
|
|
287
|
+
args.attestations.map(a => CommitteeAttestation.fromViem(a)),
|
|
288
|
+
).getPackedAttestations(),
|
|
294
289
|
blobInputs: argsArray[4],
|
|
295
290
|
proof: proofHex,
|
|
296
291
|
};
|
|
297
292
|
}
|
|
298
|
-
|
|
299
|
-
protected async sleepOrInterrupted() {
|
|
300
|
-
await this.interruptibleSleep.sleep(this.sleepTimeMs);
|
|
301
|
-
}
|
|
302
293
|
}
|
package/src/prover-node.ts
CHANGED
|
@@ -87,6 +87,7 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
|
|
|
87
87
|
txGatheringMaxParallelRequestsPerNode: 100,
|
|
88
88
|
txGatheringTimeoutMs: 120_000,
|
|
89
89
|
proverNodeFailedEpochStore: undefined,
|
|
90
|
+
proverNodeEpochProvingDelayMs: undefined,
|
|
90
91
|
...compact(config),
|
|
91
92
|
};
|
|
92
93
|
|
|
@@ -143,6 +144,7 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
|
|
|
143
144
|
*/
|
|
144
145
|
async start() {
|
|
145
146
|
this.epochsMonitor.start(this);
|
|
147
|
+
await this.publisherFactory.start();
|
|
146
148
|
this.publisher = await this.publisherFactory.create();
|
|
147
149
|
await this.rewardsMetrics.start();
|
|
148
150
|
this.l1Metrics.start();
|
|
@@ -158,6 +160,7 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
|
|
|
158
160
|
await this.prover.stop();
|
|
159
161
|
await tryStop(this.p2pClient);
|
|
160
162
|
await tryStop(this.l2BlockSource);
|
|
163
|
+
await tryStop(this.publisherFactory);
|
|
161
164
|
this.publisher?.interrupt();
|
|
162
165
|
await Promise.all(Array.from(this.jobs.values()).map(job => job.stop()));
|
|
163
166
|
await this.worldState.stop();
|
|
@@ -366,7 +369,7 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
|
|
|
366
369
|
publisher: ProverNodePublisher,
|
|
367
370
|
opts: { skipEpochCheck?: boolean } = {},
|
|
368
371
|
) {
|
|
369
|
-
const { proverNodeMaxParallelBlocksPerEpoch: parallelBlockLimit } = this.config;
|
|
372
|
+
const { proverNodeMaxParallelBlocksPerEpoch: parallelBlockLimit, proverNodeDisableProofPublish } = this.config;
|
|
370
373
|
return new EpochProvingJob(
|
|
371
374
|
data,
|
|
372
375
|
this.worldState,
|
|
@@ -376,7 +379,7 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
|
|
|
376
379
|
this.l2BlockSource,
|
|
377
380
|
this.jobMetrics,
|
|
378
381
|
deadline,
|
|
379
|
-
{ parallelBlockLimit, ...opts },
|
|
382
|
+
{ parallelBlockLimit, skipSubmitProof: proverNodeDisableProofPublish, ...opts },
|
|
380
383
|
);
|
|
381
384
|
}
|
|
382
385
|
|
|
@@ -13,6 +13,15 @@ export class ProverPublisherFactory {
|
|
|
13
13
|
telemetry?: TelemetryClient;
|
|
14
14
|
},
|
|
15
15
|
) {}
|
|
16
|
+
|
|
17
|
+
public async start() {
|
|
18
|
+
await this.deps.publisherManager.loadState();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
public stop() {
|
|
22
|
+
this.deps.publisherManager.interrupt();
|
|
23
|
+
}
|
|
24
|
+
|
|
16
25
|
/**
|
|
17
26
|
* Creates a new Prover Publisher instance.
|
|
18
27
|
* @returns A new ProverNodePublisher instance.
|