@aztec/prover-node 0.76.4 → 0.77.0-testnet-ignition.21
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/config.d.ts +5 -2
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +24 -30
- package/dest/factory.d.ts +6 -3
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +21 -14
- package/dest/http.d.ts +1 -1
- package/dest/http.d.ts.map +1 -1
- package/dest/http.js +2 -4
- package/dest/index.js +0 -1
- package/dest/job/epoch-proving-job.d.ts +7 -4
- package/dest/job/epoch-proving-job.d.ts.map +1 -1
- package/dest/job/epoch-proving-job.js +233 -193
- package/dest/metrics.d.ts +5 -2
- package/dest/metrics.d.ts.map +1 -1
- package/dest/metrics.js +50 -25
- package/dest/monitors/epoch-monitor.d.ts +22 -3
- package/dest/monitors/epoch-monitor.d.ts.map +1 -1
- package/dest/monitors/epoch-monitor.js +102 -48
- package/dest/monitors/index.js +0 -1
- package/dest/prover-coordination/config.js +2 -3
- package/dest/prover-coordination/factory.d.ts +5 -5
- package/dest/prover-coordination/factory.d.ts.map +1 -1
- package/dest/prover-coordination/factory.js +11 -8
- package/dest/prover-coordination/index.js +0 -1
- package/dest/prover-node-publisher.d.ts +5 -4
- package/dest/prover-node-publisher.d.ts.map +1 -1
- package/dest/prover-node-publisher.js +60 -52
- package/dest/prover-node.d.ts +12 -7
- package/dest/prover-node.d.ts.map +1 -1
- package/dest/prover-node.js +237 -224
- package/dest/test/index.d.ts +2 -2
- package/dest/test/index.d.ts.map +1 -1
- package/dest/test/index.js +2 -1
- package/package.json +21 -22
- package/src/config.ts +23 -31
- package/src/factory.ts +17 -8
- package/src/http.ts +2 -2
- package/src/job/epoch-proving-job.ts +11 -13
- package/src/metrics.ts +26 -5
- package/src/monitors/epoch-monitor.ts +57 -12
- package/src/prover-coordination/factory.ts +9 -12
- package/src/prover-node-publisher.ts +21 -14
- package/src/prover-node.ts +24 -22
- package/src/test/index.ts +2 -2
package/src/config.ts
CHANGED
|
@@ -1,35 +1,29 @@
|
|
|
1
|
-
import { type ArchiverConfig, archiverConfigMappings
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import { type ArchiverConfig, archiverConfigMappings } from '@aztec/archiver/config';
|
|
2
|
+
import type { ACVMConfig, BBConfig } from '@aztec/bb-prover/config';
|
|
3
|
+
import {
|
|
4
|
+
type ConfigMappingsType,
|
|
5
|
+
booleanConfigHelper,
|
|
6
|
+
getConfigFromMappings,
|
|
7
|
+
numberConfigHelper,
|
|
8
|
+
} from '@aztec/foundation/config';
|
|
9
|
+
import { type DataStoreConfig, dataConfigMappings } from '@aztec/kv-store/config';
|
|
10
|
+
import { type P2PConfig, p2pConfigMappings } from '@aztec/p2p/config';
|
|
6
11
|
import {
|
|
7
12
|
type ProverAgentConfig,
|
|
8
13
|
type ProverBrokerConfig,
|
|
9
14
|
proverAgentConfigMappings,
|
|
10
15
|
proverBrokerConfigMappings,
|
|
11
16
|
} from '@aztec/prover-client/broker';
|
|
12
|
-
import {
|
|
13
|
-
type ProverClientConfig,
|
|
14
|
-
bbConfigMappings,
|
|
15
|
-
getProverEnvVars,
|
|
16
|
-
proverClientConfigMappings,
|
|
17
|
-
} from '@aztec/prover-client/config';
|
|
17
|
+
import { type ProverClientConfig, bbConfigMappings, proverClientConfigMappings } from '@aztec/prover-client/config';
|
|
18
18
|
import {
|
|
19
19
|
type PublisherConfig,
|
|
20
20
|
type TxSenderConfig,
|
|
21
|
-
getPublisherConfigFromEnv,
|
|
22
21
|
getPublisherConfigMappings,
|
|
23
|
-
getTxSenderConfigFromEnv,
|
|
24
22
|
getTxSenderConfigMappings,
|
|
25
23
|
} from '@aztec/sequencer-client/config';
|
|
26
|
-
import { type WorldStateConfig,
|
|
24
|
+
import { type WorldStateConfig, worldStateConfigMappings } from '@aztec/world-state/config';
|
|
27
25
|
|
|
28
|
-
import {
|
|
29
|
-
type ProverCoordinationConfig,
|
|
30
|
-
getTxProviderConfigFromEnv,
|
|
31
|
-
proverCoordinationConfigMappings,
|
|
32
|
-
} from './prover-coordination/config.js';
|
|
26
|
+
import { type ProverCoordinationConfig, proverCoordinationConfigMappings } from './prover-coordination/config.js';
|
|
33
27
|
|
|
34
28
|
export type ProverNodeConfig = ArchiverConfig &
|
|
35
29
|
ProverClientConfig &
|
|
@@ -39,7 +33,10 @@ export type ProverNodeConfig = ArchiverConfig &
|
|
|
39
33
|
TxSenderConfig &
|
|
40
34
|
DataStoreConfig &
|
|
41
35
|
ProverCoordinationConfig &
|
|
42
|
-
SpecificProverNodeConfig
|
|
36
|
+
SpecificProverNodeConfig & {
|
|
37
|
+
/** Whether to populate the genesis state with initial fee juice for the test accounts */
|
|
38
|
+
testAccounts: boolean;
|
|
39
|
+
};
|
|
43
40
|
|
|
44
41
|
type SpecificProverNodeConfig = {
|
|
45
42
|
proverNodeMaxPendingJobs: number;
|
|
@@ -93,20 +90,15 @@ export const proverNodeConfigMappings: ConfigMappingsType<ProverNodeConfig> = {
|
|
|
93
90
|
...getTxSenderConfigMappings('PROVER'),
|
|
94
91
|
...proverCoordinationConfigMappings,
|
|
95
92
|
...specificProverNodeConfigMappings,
|
|
93
|
+
testAccounts: {
|
|
94
|
+
env: 'TEST_ACCOUNTS',
|
|
95
|
+
description: 'Whether to populate the genesis state with initial fee juice for the test accounts.',
|
|
96
|
+
...booleanConfigHelper(false),
|
|
97
|
+
},
|
|
96
98
|
};
|
|
97
99
|
|
|
98
100
|
export function getProverNodeConfigFromEnv(): ProverNodeConfig {
|
|
99
|
-
return
|
|
100
|
-
...getP2PConfigFromEnv(),
|
|
101
|
-
...getDataConfigFromEnv(),
|
|
102
|
-
...getArchiverConfigFromEnv(),
|
|
103
|
-
...getProverEnvVars(),
|
|
104
|
-
...getWorldStateConfigFromEnv(),
|
|
105
|
-
...getPublisherConfigFromEnv('PROVER'),
|
|
106
|
-
...getTxSenderConfigFromEnv('PROVER'),
|
|
107
|
-
...getTxProviderConfigFromEnv(),
|
|
108
|
-
...getConfigFromMappings(specificProverNodeConfigMappings),
|
|
109
|
-
};
|
|
101
|
+
return getConfigFromMappings(proverNodeConfigMappings);
|
|
110
102
|
}
|
|
111
103
|
|
|
112
104
|
export function getProverNodeBrokerConfigFromEnv(): ProverBrokerConfig {
|
package/src/factory.ts
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import { type Archiver, createArchiver } from '@aztec/archiver';
|
|
2
2
|
import { type BlobSinkClientInterface, createBlobSinkClient } from '@aztec/blob-sink/client';
|
|
3
|
-
import { type ProverCoordination, type ProvingJobBroker } from '@aztec/circuit-types';
|
|
4
3
|
import { EpochCache } from '@aztec/epoch-cache';
|
|
5
4
|
import { L1TxUtils, RollupContract, createEthereumChain, createL1Clients } from '@aztec/ethereum';
|
|
6
5
|
import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
7
|
-
import {
|
|
6
|
+
import type { DataStoreConfig } from '@aztec/kv-store/config';
|
|
8
7
|
import { createProverClient } from '@aztec/prover-client';
|
|
9
8
|
import { createAndStartProvingBroker } from '@aztec/prover-client/broker';
|
|
9
|
+
import type { ProverCoordination, ProvingJobBroker } from '@aztec/stdlib/interfaces/server';
|
|
10
|
+
import type { PublicDataTreeLeaf } from '@aztec/stdlib/trees';
|
|
10
11
|
import { type TelemetryClient, getTelemetryClient } from '@aztec/telemetry-client';
|
|
11
12
|
import { createWorldStateSynchronizer } from '@aztec/world-state';
|
|
12
13
|
|
|
13
|
-
import {
|
|
14
|
+
import type { ProverNodeConfig } from './config.js';
|
|
14
15
|
import { EpochMonitor } from './monitors/epoch-monitor.js';
|
|
15
16
|
import { createProverCoordination } from './prover-coordination/factory.js';
|
|
16
17
|
import { ProverNodePublisher } from './prover-node-publisher.js';
|
|
@@ -29,6 +30,9 @@ export async function createProverNode(
|
|
|
29
30
|
broker?: ProvingJobBroker;
|
|
30
31
|
l1TxUtils?: L1TxUtils;
|
|
31
32
|
} = {},
|
|
33
|
+
options: {
|
|
34
|
+
prefilledPublicData?: PublicDataTreeLeaf[];
|
|
35
|
+
} = {},
|
|
32
36
|
) {
|
|
33
37
|
const telemetry = deps.telemetry ?? getTelemetryClient();
|
|
34
38
|
const blobSinkClient = deps.blobSinkClient ?? createBlobSinkClient(config);
|
|
@@ -37,15 +41,20 @@ export async function createProverNode(
|
|
|
37
41
|
log.verbose(`Created archiver and synced to block ${await archiver.getBlockNumber()}`);
|
|
38
42
|
|
|
39
43
|
const worldStateConfig = { ...config, worldStateProvenBlocksOnly: false };
|
|
40
|
-
const worldStateSynchronizer = await createWorldStateSynchronizer(
|
|
44
|
+
const worldStateSynchronizer = await createWorldStateSynchronizer(
|
|
45
|
+
worldStateConfig,
|
|
46
|
+
archiver,
|
|
47
|
+
options.prefilledPublicData,
|
|
48
|
+
telemetry,
|
|
49
|
+
);
|
|
41
50
|
await worldStateSynchronizer.start();
|
|
42
51
|
|
|
43
52
|
const broker = deps.broker ?? (await createAndStartProvingBroker(config, telemetry));
|
|
44
53
|
const prover = await createProverClient(config, worldStateSynchronizer, broker, telemetry);
|
|
45
54
|
|
|
46
|
-
const {
|
|
47
|
-
const chain = createEthereumChain(
|
|
48
|
-
const { publicClient, walletClient } = createL1Clients(
|
|
55
|
+
const { l1RpcUrls: rpcUrls, l1ChainId: chainId, publisherPrivateKey } = config;
|
|
56
|
+
const chain = createEthereumChain(rpcUrls, chainId);
|
|
57
|
+
const { publicClient, walletClient } = createL1Clients(rpcUrls, publisherPrivateKey, chain.chainInfo);
|
|
49
58
|
|
|
50
59
|
const rollupContract = new RollupContract(publicClient, config.l1Contracts.rollupAddress.toString());
|
|
51
60
|
|
|
@@ -73,7 +82,7 @@ export async function createProverNode(
|
|
|
73
82
|
txGatheringTimeoutMs: config.txGatheringTimeoutMs,
|
|
74
83
|
};
|
|
75
84
|
|
|
76
|
-
const epochMonitor =
|
|
85
|
+
const epochMonitor = await EpochMonitor.create(archiver, proverNodeConfig, telemetry);
|
|
77
86
|
|
|
78
87
|
return new ProverNode(
|
|
79
88
|
prover,
|
package/src/http.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { ProverNodeApiSchema } from '@aztec/
|
|
1
|
+
import { ProverNodeApiSchema } from '@aztec/stdlib/interfaces/server';
|
|
2
2
|
import { createTracedJsonRpcServer } from '@aztec/telemetry-client';
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import type { ProverNode } from './prover-node.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Wrap a ProverNode instance with a JSON RPC HTTP server.
|
|
@@ -1,25 +1,23 @@
|
|
|
1
|
+
import { asyncPool } from '@aztec/foundation/async-pool';
|
|
2
|
+
import { createLogger } from '@aztec/foundation/log';
|
|
3
|
+
import { promiseWithResolvers } from '@aztec/foundation/promise';
|
|
4
|
+
import { Timer } from '@aztec/foundation/timer';
|
|
5
|
+
import type { PublicProcessor, PublicProcessorFactory } from '@aztec/simulator/server';
|
|
6
|
+
import type { L2Block, L2BlockSource } from '@aztec/stdlib/block';
|
|
1
7
|
import {
|
|
2
8
|
type EpochProver,
|
|
3
9
|
type EpochProvingJobState,
|
|
4
10
|
EpochProvingJobTerminalState,
|
|
5
11
|
type ForkMerkleTreeOperations,
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
type ProcessedTx,
|
|
10
|
-
type Tx,
|
|
11
|
-
} from '@aztec/circuit-types';
|
|
12
|
-
import { asyncPool } from '@aztec/foundation/async-pool';
|
|
13
|
-
import { createLogger } from '@aztec/foundation/log';
|
|
14
|
-
import { promiseWithResolvers } from '@aztec/foundation/promise';
|
|
15
|
-
import { Timer } from '@aztec/foundation/timer';
|
|
16
|
-
import { type PublicProcessor, type PublicProcessorFactory } from '@aztec/simulator/server';
|
|
12
|
+
} from '@aztec/stdlib/interfaces/server';
|
|
13
|
+
import type { L1ToL2MessageSource } from '@aztec/stdlib/messaging';
|
|
14
|
+
import type { ProcessedTx, Tx } from '@aztec/stdlib/tx';
|
|
17
15
|
import { Attributes, type Traceable, type Tracer, trackSpan } from '@aztec/telemetry-client';
|
|
18
16
|
|
|
19
17
|
import * as crypto from 'node:crypto';
|
|
20
18
|
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
19
|
+
import type { ProverNodeMetrics } from '../metrics.js';
|
|
20
|
+
import type { ProverNodePublisher } from '../prover-node-publisher.js';
|
|
23
21
|
|
|
24
22
|
/**
|
|
25
23
|
* Job that grabs a range of blocks from the unfinalised chain from L1, gets their txs given their hashes,
|
package/src/metrics.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createLogger } from '@aztec/foundation/log';
|
|
2
|
+
import type { L1PublishProofStats, L1PublishStats } from '@aztec/stdlib/stats';
|
|
2
3
|
import {
|
|
3
4
|
Attributes,
|
|
5
|
+
type Gauge,
|
|
4
6
|
type Histogram,
|
|
5
7
|
Metrics,
|
|
6
8
|
type TelemetryClient,
|
|
@@ -25,7 +27,13 @@ export class ProverNodeMetrics {
|
|
|
25
27
|
txBlobDataGasUsed: Histogram;
|
|
26
28
|
txBlobDataGasCost: Histogram;
|
|
27
29
|
|
|
28
|
-
|
|
30
|
+
private senderBalance: Gauge;
|
|
31
|
+
|
|
32
|
+
constructor(
|
|
33
|
+
public readonly client: TelemetryClient,
|
|
34
|
+
name = 'ProverNode',
|
|
35
|
+
private logger = createLogger('prover-node:publisher:metrics'),
|
|
36
|
+
) {
|
|
29
37
|
const meter = client.getMeter(name);
|
|
30
38
|
this.proverEpochExecutionDuration = meter.createHistogram(Metrics.PROVER_NODE_EXECUTION_DURATION, {
|
|
31
39
|
description: 'Duration of execution of an epoch by the prover',
|
|
@@ -34,8 +42,8 @@ export class ProverNodeMetrics {
|
|
|
34
42
|
});
|
|
35
43
|
this.provingJobDuration = meter.createHistogram(Metrics.PROVER_NODE_JOB_DURATION, {
|
|
36
44
|
description: 'Duration of proving job',
|
|
37
|
-
unit: '
|
|
38
|
-
valueType: ValueType.
|
|
45
|
+
unit: 's',
|
|
46
|
+
valueType: ValueType.DOUBLE,
|
|
39
47
|
});
|
|
40
48
|
this.provingJobBlocks = meter.createHistogram(Metrics.PROVER_NODE_JOB_BLOCKS, {
|
|
41
49
|
description: 'Number of blocks in a proven epoch',
|
|
@@ -91,6 +99,12 @@ export class ProverNodeMetrics {
|
|
|
91
99
|
unit: 'gwei',
|
|
92
100
|
valueType: ValueType.INT,
|
|
93
101
|
});
|
|
102
|
+
|
|
103
|
+
this.senderBalance = meter.createGauge(Metrics.L1_PUBLISHER_BALANCE, {
|
|
104
|
+
unit: 'eth',
|
|
105
|
+
description: 'The balance of the sender address',
|
|
106
|
+
valueType: ValueType.DOUBLE,
|
|
107
|
+
});
|
|
94
108
|
}
|
|
95
109
|
|
|
96
110
|
recordFailedTx() {
|
|
@@ -106,11 +120,18 @@ export class ProverNodeMetrics {
|
|
|
106
120
|
|
|
107
121
|
public recordProvingJob(executionTimeMs: number, totalTimeMs: number, numBlocks: number, numTxs: number) {
|
|
108
122
|
this.proverEpochExecutionDuration.record(Math.ceil(executionTimeMs));
|
|
109
|
-
this.provingJobDuration.record(
|
|
123
|
+
this.provingJobDuration.record(totalTimeMs / 1000);
|
|
110
124
|
this.provingJobBlocks.record(Math.floor(numBlocks));
|
|
111
125
|
this.provingJobTransactions.record(Math.floor(numTxs));
|
|
112
126
|
}
|
|
113
127
|
|
|
128
|
+
public recordSenderBalance(wei: bigint, senderAddress: string) {
|
|
129
|
+
const eth = parseFloat(formatEther(wei, 'wei'));
|
|
130
|
+
this.senderBalance.record(eth, {
|
|
131
|
+
[Attributes.SENDER_ADDRESS]: senderAddress,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
114
135
|
private recordTx(durationMs: number, stats: L1PublishStats) {
|
|
115
136
|
const attributes = {
|
|
116
137
|
[Attributes.L1_TX_TYPE]: 'submitProof',
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { type L2BlockSource } from '@aztec/circuit-types';
|
|
2
1
|
import { createLogger } from '@aztec/foundation/log';
|
|
3
2
|
import { RunningPromise } from '@aztec/foundation/running-promise';
|
|
3
|
+
import type { L2BlockSource } from '@aztec/stdlib/block';
|
|
4
|
+
import { type L1RollupConstants, getEpochAtSlot } from '@aztec/stdlib/epoch-helpers';
|
|
4
5
|
import {
|
|
5
6
|
type TelemetryClient,
|
|
6
7
|
type Traceable,
|
|
@@ -10,20 +11,31 @@ import {
|
|
|
10
11
|
} from '@aztec/telemetry-client';
|
|
11
12
|
|
|
12
13
|
export interface EpochMonitorHandler {
|
|
13
|
-
|
|
14
|
+
handleEpochReadyToProve(epochNumber: bigint): Promise<void>;
|
|
14
15
|
}
|
|
15
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Fires an event when a new epoch ready to prove is detected.
|
|
19
|
+
*
|
|
20
|
+
* We define an epoch as ready to prove when:
|
|
21
|
+
* - The epoch is complete
|
|
22
|
+
* - Its blocks have not been reorg'd out due to a missing L2 proof
|
|
23
|
+
* - Its first block is the immediate successor of the last proven block
|
|
24
|
+
*
|
|
25
|
+
* This class periodically hits the L2BlockSource.
|
|
26
|
+
* On start it will trigger the event for the last epoch ready to prove.
|
|
27
|
+
*/
|
|
16
28
|
export class EpochMonitor implements Traceable {
|
|
17
29
|
private runningPromise: RunningPromise;
|
|
18
30
|
private log = createLogger('prover-node:epoch-monitor');
|
|
19
31
|
public readonly tracer: Tracer;
|
|
20
32
|
|
|
21
33
|
private handler: EpochMonitorHandler | undefined;
|
|
22
|
-
|
|
23
34
|
private latestEpochNumber: bigint | undefined;
|
|
24
35
|
|
|
25
36
|
constructor(
|
|
26
37
|
private readonly l2BlockSource: L2BlockSource,
|
|
38
|
+
private readonly l1Constants: Pick<L1RollupConstants, 'epochDuration'>,
|
|
27
39
|
private options: { pollingIntervalMs: number },
|
|
28
40
|
telemetry: TelemetryClient = getTelemetryClient(),
|
|
29
41
|
) {
|
|
@@ -31,12 +43,26 @@ export class EpochMonitor implements Traceable {
|
|
|
31
43
|
this.runningPromise = new RunningPromise(this.work.bind(this), this.log, this.options.pollingIntervalMs);
|
|
32
44
|
}
|
|
33
45
|
|
|
46
|
+
public static async create(
|
|
47
|
+
l2BlockSource: L2BlockSource,
|
|
48
|
+
options: { pollingIntervalMs: number },
|
|
49
|
+
telemetry: TelemetryClient = getTelemetryClient(),
|
|
50
|
+
): Promise<EpochMonitor> {
|
|
51
|
+
const l1Constants = await l2BlockSource.getL1Constants();
|
|
52
|
+
return new EpochMonitor(l2BlockSource, l1Constants, options, telemetry);
|
|
53
|
+
}
|
|
54
|
+
|
|
34
55
|
public start(handler: EpochMonitorHandler) {
|
|
35
56
|
this.handler = handler;
|
|
36
57
|
this.runningPromise.start();
|
|
37
58
|
this.log.info('Started EpochMonitor', this.options);
|
|
38
59
|
}
|
|
39
60
|
|
|
61
|
+
/** Exposed for testing */
|
|
62
|
+
public setHandler(handler: EpochMonitorHandler) {
|
|
63
|
+
this.handler = handler;
|
|
64
|
+
}
|
|
65
|
+
|
|
40
66
|
public async stop() {
|
|
41
67
|
await this.runningPromise.stop();
|
|
42
68
|
this.log.info('Stopped EpochMonitor');
|
|
@@ -44,18 +70,37 @@ export class EpochMonitor implements Traceable {
|
|
|
44
70
|
|
|
45
71
|
@trackSpan('EpochMonitor.work')
|
|
46
72
|
public async work() {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
73
|
+
const { epochToProve, blockNumber, slotNumber } = await this.getEpochNumberToProve();
|
|
74
|
+
if (epochToProve === undefined) {
|
|
75
|
+
this.log.trace(`Next block to prove ${blockNumber} not yet mined`, { blockNumber });
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
if (this.latestEpochNumber !== undefined && epochToProve <= this.latestEpochNumber) {
|
|
79
|
+
this.log.trace(`Epoch ${epochToProve} already processed`, { epochToProve, blockNumber, slotNumber });
|
|
53
80
|
return;
|
|
54
81
|
}
|
|
55
82
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
this.
|
|
83
|
+
const isCompleted = await this.l2BlockSource.isEpochComplete(epochToProve);
|
|
84
|
+
if (!isCompleted) {
|
|
85
|
+
this.log.trace(`Epoch ${epochToProve} is not complete`, { epochToProve, blockNumber, slotNumber });
|
|
86
|
+
return;
|
|
59
87
|
}
|
|
88
|
+
|
|
89
|
+
this.log.debug(`Epoch ${epochToProve} is ready to be proven`);
|
|
90
|
+
await this.handler?.handleEpochReadyToProve(epochToProve);
|
|
91
|
+
this.latestEpochNumber = epochToProve;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
private async getEpochNumberToProve() {
|
|
95
|
+
const lastBlockProven = await this.l2BlockSource.getProvenBlockNumber();
|
|
96
|
+
const firstBlockToProve = lastBlockProven + 1;
|
|
97
|
+
const firstBlockHeaderToProve = await this.l2BlockSource.getBlockHeader(firstBlockToProve);
|
|
98
|
+
if (!firstBlockHeaderToProve) {
|
|
99
|
+
return { epochToProve: undefined, blockNumber: firstBlockToProve };
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const firstSlotOfEpochToProve = firstBlockHeaderToProve.getSlot();
|
|
103
|
+
const epochToProve = getEpochAtSlot(firstSlotOfEpochToProve, this.l1Constants);
|
|
104
|
+
return { epochToProve, blockNumber: firstBlockToProve, slotNumber: firstSlotOfEpochToProve };
|
|
60
105
|
}
|
|
61
106
|
}
|
|
@@ -1,21 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { ArchiveSource, Archiver } from '@aztec/archiver';
|
|
2
2
|
import { BBCircuitVerifier, TestCircuitVerifier } from '@aztec/bb-prover';
|
|
3
|
-
import {
|
|
4
|
-
P2PClientType,
|
|
5
|
-
type ProverCoordination,
|
|
6
|
-
type WorldStateSynchronizer,
|
|
7
|
-
createAztecNodeClient,
|
|
8
|
-
getComponentsVersionsFromConfig,
|
|
9
|
-
} from '@aztec/circuit-types';
|
|
10
|
-
import { type EpochCache } from '@aztec/epoch-cache';
|
|
3
|
+
import type { EpochCache } from '@aztec/epoch-cache';
|
|
11
4
|
import { createLogger } from '@aztec/foundation/log';
|
|
12
|
-
import {
|
|
13
|
-
import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/
|
|
5
|
+
import type { DataStoreConfig } from '@aztec/kv-store/config';
|
|
6
|
+
import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree';
|
|
14
7
|
import { createP2PClient } from '@aztec/p2p';
|
|
15
8
|
import { protocolContractTreeRoot } from '@aztec/protocol-contracts';
|
|
9
|
+
import { createAztecNodeClient } from '@aztec/stdlib/interfaces/client';
|
|
10
|
+
import type { ProverCoordination, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
|
|
11
|
+
import { P2PClientType } from '@aztec/stdlib/p2p';
|
|
12
|
+
import { getComponentsVersionsFromConfig } from '@aztec/stdlib/versioning';
|
|
16
13
|
import { type TelemetryClient, makeTracedFetch } from '@aztec/telemetry-client';
|
|
17
14
|
|
|
18
|
-
import {
|
|
15
|
+
import type { ProverNodeConfig } from '../config.js';
|
|
19
16
|
|
|
20
17
|
// We return a reference to the P2P client so that the prover node can stop the service when it shuts down.
|
|
21
18
|
type ProverCoordinationDeps = {
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { type FeeRecipient, type RootRollupPublicInputs } from '@aztec/circuits.js/rollup';
|
|
4
|
-
import { type L1TxUtils, type RollupContract } from '@aztec/ethereum';
|
|
1
|
+
import { AGGREGATION_OBJECT_LENGTH, AZTEC_MAX_EPOCH_DURATION } from '@aztec/constants';
|
|
2
|
+
import type { L1TxUtils, RollupContract } from '@aztec/ethereum';
|
|
5
3
|
import { makeTuple } from '@aztec/foundation/array';
|
|
6
4
|
import { areArraysEqual, times } from '@aztec/foundation/collection';
|
|
7
5
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
@@ -11,7 +9,10 @@ import { type Tuple, serializeToBuffer } from '@aztec/foundation/serialize';
|
|
|
11
9
|
import { InterruptibleSleep } from '@aztec/foundation/sleep';
|
|
12
10
|
import { Timer } from '@aztec/foundation/timer';
|
|
13
11
|
import { RollupAbi } from '@aztec/l1-artifacts';
|
|
14
|
-
import {
|
|
12
|
+
import type { PublisherConfig, TxSenderConfig } from '@aztec/sequencer-client';
|
|
13
|
+
import type { Proof } from '@aztec/stdlib/proofs';
|
|
14
|
+
import type { FeeRecipient, RootRollupPublicInputs } from '@aztec/stdlib/rollup';
|
|
15
|
+
import type { L1PublishProofStats } from '@aztec/stdlib/stats';
|
|
15
16
|
import { type TelemetryClient, getTelemetryClient } from '@aztec/telemetry-client';
|
|
16
17
|
|
|
17
18
|
import { type Hex, type TransactionReceipt, encodeFunctionData } from 'viem';
|
|
@@ -105,6 +106,12 @@ export class ProverNodePublisher {
|
|
|
105
106
|
return false;
|
|
106
107
|
}
|
|
107
108
|
|
|
109
|
+
try {
|
|
110
|
+
this.metrics.recordSenderBalance(await this.l1TxUtils.getSenderBalance(), this.l1TxUtils.getSenderAddress());
|
|
111
|
+
} catch (err) {
|
|
112
|
+
this.log.warn(`Failed to record the ETH balance of the prover node: ${err}`);
|
|
113
|
+
}
|
|
114
|
+
|
|
108
115
|
// Tx was mined successfully
|
|
109
116
|
if (txReceipt.status) {
|
|
110
117
|
const tx = await this.l1TxUtils.getTransactionStats(txReceipt.transactionHash);
|
|
@@ -251,15 +258,15 @@ export class ProverNodePublisher {
|
|
|
251
258
|
return [
|
|
252
259
|
BigInt(args.fromBlock),
|
|
253
260
|
BigInt(args.toBlock),
|
|
254
|
-
|
|
255
|
-
args.publicInputs.previousArchive.root.toString(),
|
|
256
|
-
args.publicInputs.endArchive.root.toString(),
|
|
257
|
-
args.publicInputs.previousBlockHash.toString(),
|
|
258
|
-
args.publicInputs.endBlockHash.toString(),
|
|
259
|
-
args.publicInputs.endTimestamp.
|
|
260
|
-
args.publicInputs.outHash.toString(),
|
|
261
|
-
args.publicInputs.proverId.toString(),
|
|
262
|
-
|
|
261
|
+
{
|
|
262
|
+
previousArchive: args.publicInputs.previousArchive.root.toString(),
|
|
263
|
+
endArchive: args.publicInputs.endArchive.root.toString(),
|
|
264
|
+
previousBlockHash: args.publicInputs.previousBlockHash.toString(),
|
|
265
|
+
endBlockHash: args.publicInputs.endBlockHash.toString(),
|
|
266
|
+
endTimestamp: args.publicInputs.endTimestamp.toBigInt(),
|
|
267
|
+
outHash: args.publicInputs.outHash.toString(),
|
|
268
|
+
proverId: EthAddress.fromField(args.publicInputs.proverId).toString(),
|
|
269
|
+
},
|
|
263
270
|
makeTuple(AZTEC_MAX_EPOCH_DURATION * 2, i =>
|
|
264
271
|
i % 2 === 0
|
|
265
272
|
? args.publicInputs.fees[i / 2].recipient.toField().toString()
|
package/src/prover-node.ts
CHANGED
|
@@ -1,28 +1,26 @@
|
|
|
1
|
+
import { compact } from '@aztec/foundation/collection';
|
|
2
|
+
import { memoize } from '@aztec/foundation/decorators';
|
|
3
|
+
import { createLogger } from '@aztec/foundation/log';
|
|
4
|
+
import { RunningPromise } from '@aztec/foundation/running-promise';
|
|
5
|
+
import { DateProvider } from '@aztec/foundation/timer';
|
|
6
|
+
import type { Maybe } from '@aztec/foundation/types';
|
|
7
|
+
import type { P2P } from '@aztec/p2p';
|
|
8
|
+
import { PublicProcessorFactory } from '@aztec/simulator/server';
|
|
9
|
+
import type { L2Block, L2BlockSource } from '@aztec/stdlib/block';
|
|
10
|
+
import type { ContractDataSource } from '@aztec/stdlib/contract';
|
|
11
|
+
import { getTimestampRangeForEpoch } from '@aztec/stdlib/epoch-helpers';
|
|
1
12
|
import {
|
|
2
13
|
type EpochProverManager,
|
|
3
14
|
EpochProvingJobTerminalState,
|
|
4
|
-
type L1ToL2MessageSource,
|
|
5
|
-
type L2Block,
|
|
6
|
-
type L2BlockSource,
|
|
7
|
-
type P2PClientType,
|
|
8
15
|
type ProverCoordination,
|
|
9
16
|
type ProverNodeApi,
|
|
10
17
|
type Service,
|
|
11
|
-
type Tx,
|
|
12
|
-
type TxHash,
|
|
13
18
|
type WorldStateSynchronizer,
|
|
14
|
-
getTimestampRangeForEpoch,
|
|
15
19
|
tryStop,
|
|
16
|
-
} from '@aztec/
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import { createLogger } from '@aztec/foundation/log';
|
|
21
|
-
import { RunningPromise } from '@aztec/foundation/running-promise';
|
|
22
|
-
import { DateProvider } from '@aztec/foundation/timer';
|
|
23
|
-
import { type Maybe } from '@aztec/foundation/types';
|
|
24
|
-
import { type P2P } from '@aztec/p2p';
|
|
25
|
-
import { PublicProcessorFactory } from '@aztec/simulator/server';
|
|
20
|
+
} from '@aztec/stdlib/interfaces/server';
|
|
21
|
+
import type { L1ToL2MessageSource } from '@aztec/stdlib/messaging';
|
|
22
|
+
import type { P2PClientType } from '@aztec/stdlib/p2p';
|
|
23
|
+
import type { Tx, TxHash } from '@aztec/stdlib/tx';
|
|
26
24
|
import {
|
|
27
25
|
Attributes,
|
|
28
26
|
type TelemetryClient,
|
|
@@ -34,8 +32,8 @@ import {
|
|
|
34
32
|
|
|
35
33
|
import { EpochProvingJob, type EpochProvingJobState } from './job/epoch-proving-job.js';
|
|
36
34
|
import { ProverNodeMetrics } from './metrics.js';
|
|
37
|
-
import {
|
|
38
|
-
import {
|
|
35
|
+
import type { EpochMonitor, EpochMonitorHandler } from './monitors/epoch-monitor.js';
|
|
36
|
+
import type { ProverNodePublisher } from './prover-node-publisher.js';
|
|
39
37
|
|
|
40
38
|
export type ProverNodeOptions = {
|
|
41
39
|
pollingIntervalMs: number;
|
|
@@ -94,6 +92,10 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
|
|
|
94
92
|
this.txFetcher = new RunningPromise(() => this.checkForTxs(), this.log, this.options.txGatheringIntervalMs);
|
|
95
93
|
}
|
|
96
94
|
|
|
95
|
+
public getProverId() {
|
|
96
|
+
return this.prover.getProverId();
|
|
97
|
+
}
|
|
98
|
+
|
|
97
99
|
public getP2P() {
|
|
98
100
|
const asP2PClient = this.coordination as P2P<P2PClientType.Prover>;
|
|
99
101
|
if (typeof asP2PClient.isP2PClient === 'function' && asP2PClient.isP2PClient()) {
|
|
@@ -106,7 +108,7 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
|
|
|
106
108
|
* Handles an epoch being completed by starting a proof for it if there are no active jobs for it.
|
|
107
109
|
* @param epochNumber - The epoch number that was just completed.
|
|
108
110
|
*/
|
|
109
|
-
async
|
|
111
|
+
async handleEpochReadyToProve(epochNumber: bigint): Promise<void> {
|
|
110
112
|
try {
|
|
111
113
|
this.log.debug('jobs', JSON.stringify(this.jobs, null, 2));
|
|
112
114
|
const activeJobs = await this.getActiveJobsForEpoch(epochNumber);
|
|
@@ -216,7 +218,7 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
|
|
|
216
218
|
|
|
217
219
|
// Fast forward world state to right before the target block and get a fork
|
|
218
220
|
this.log.verbose(`Creating proving job for epoch ${epochNumber} for block range ${fromBlock} to ${toBlock}`);
|
|
219
|
-
await this.worldState.syncImmediate(
|
|
221
|
+
await this.worldState.syncImmediate(toBlock);
|
|
220
222
|
|
|
221
223
|
// Create a processor using the forked world state
|
|
222
224
|
const publicProcessorFactory = new PublicProcessorFactory(
|
|
@@ -253,7 +255,7 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
|
|
|
253
255
|
return;
|
|
254
256
|
}
|
|
255
257
|
const txHashes = block.body.txEffects.map(tx => tx.txHash);
|
|
256
|
-
this.log.verbose(`Fetching ${txHashes.length} for block number ${blockNumber} from coordination`);
|
|
258
|
+
this.log.verbose(`Fetching ${txHashes.length} tx hashes for block number ${blockNumber} from coordination`);
|
|
257
259
|
await this.coordination.getTxsByHash(txHashes); // This stores the txs in the tx pool, no need to persist them here
|
|
258
260
|
this.lastBlockNumber = blockNumber;
|
|
259
261
|
}
|
package/src/test/index.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { EpochProverManager } from '@aztec/stdlib/interfaces/server';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import type { ProverNodePublisher } from '../prover-node-publisher.js';
|
|
4
4
|
import { ProverNode } from '../prover-node.js';
|
|
5
5
|
|
|
6
6
|
class TestProverNode_ extends ProverNode {
|