@aztec/archiver 0.0.1-commit.993d240 → 0.0.1-commit.9a89641
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/archiver.d.ts +44 -8
- package/dest/archiver.d.ts.map +1 -1
- package/dest/archiver.js +103 -35
- package/dest/config.d.ts +5 -4
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +28 -7
- package/dest/factory.d.ts +8 -1
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +41 -5
- package/dest/l1/calldata_retriever.d.ts +8 -1
- package/dest/l1/calldata_retriever.d.ts.map +1 -1
- package/dest/l1/calldata_retriever.js +7 -6
- package/dest/l1/data_retrieval.d.ts +7 -2
- package/dest/l1/data_retrieval.d.ts.map +1 -1
- package/dest/modules/contract_data_source_adapter.d.ts +2 -2
- package/dest/modules/contract_data_source_adapter.d.ts.map +1 -1
- package/dest/modules/contract_data_source_adapter.js +1 -9
- package/dest/modules/data_source_base.d.ts +5 -6
- package/dest/modules/data_source_base.d.ts.map +1 -1
- package/dest/modules/data_source_base.js +9 -38
- package/dest/modules/data_store_updater.d.ts +1 -1
- package/dest/modules/data_store_updater.d.ts.map +1 -1
- package/dest/modules/data_store_updater.js +4 -3
- package/dest/modules/instrumentation.d.ts +9 -1
- package/dest/modules/instrumentation.d.ts.map +1 -1
- package/dest/modules/instrumentation.js +23 -2
- package/dest/modules/l1_synchronizer.d.ts +3 -3
- package/dest/modules/l1_synchronizer.d.ts.map +1 -1
- package/dest/modules/l1_synchronizer.js +78 -41
- package/dest/modules/outbox_trees_resolver.d.ts +64 -0
- package/dest/modules/outbox_trees_resolver.d.ts.map +1 -0
- package/dest/modules/outbox_trees_resolver.js +184 -0
- package/dest/modules/validation.d.ts +29 -7
- package/dest/modules/validation.d.ts.map +1 -1
- package/dest/modules/validation.js +31 -13
- package/dest/store/block_store.d.ts +26 -22
- package/dest/store/block_store.d.ts.map +1 -1
- package/dest/store/block_store.js +105 -78
- package/dest/store/contract_class_store.d.ts +1 -1
- package/dest/store/contract_class_store.d.ts.map +1 -1
- package/dest/store/contract_class_store.js +19 -1
- package/dest/store/contract_instance_store.d.ts +1 -1
- package/dest/store/contract_instance_store.d.ts.map +1 -1
- package/dest/store/contract_instance_store.js +18 -1
- package/dest/store/log_store.d.ts +1 -1
- package/dest/store/log_store.d.ts.map +1 -1
- package/dest/store/log_store.js +3 -3
- package/dest/store/log_store_codec.d.ts +9 -1
- package/dest/store/log_store_codec.d.ts.map +1 -1
- package/dest/store/log_store_codec.js +9 -0
- package/dest/test/fake_l1_state.js +3 -3
- package/dest/test/mock_l1_to_l2_message_source.d.ts +1 -1
- package/dest/test/mock_l1_to_l2_message_source.d.ts.map +1 -1
- package/dest/test/mock_l1_to_l2_message_source.js +1 -2
- package/dest/test/mock_l2_block_source.d.ts +4 -11
- package/dest/test/mock_l2_block_source.d.ts.map +1 -1
- package/dest/test/mock_l2_block_source.js +15 -39
- package/dest/test/mock_structs.d.ts +1 -1
- package/dest/test/mock_structs.d.ts.map +1 -1
- package/dest/test/mock_structs.js +2 -2
- package/dest/test/noop_l1_archiver.d.ts +8 -3
- package/dest/test/noop_l1_archiver.d.ts.map +1 -1
- package/dest/test/noop_l1_archiver.js +12 -9
- package/package.json +13 -13
- package/src/archiver.ts +147 -42
- package/src/config.ts +34 -16
- package/src/factory.ts +48 -4
- package/src/l1/calldata_retriever.ts +13 -6
- package/src/l1/data_retrieval.ts +8 -1
- package/src/modules/contract_data_source_adapter.ts +1 -10
- package/src/modules/data_source_base.ts +17 -44
- package/src/modules/data_store_updater.ts +4 -3
- package/src/modules/instrumentation.ts +15 -2
- package/src/modules/l1_synchronizer.ts +120 -57
- package/src/modules/outbox_trees_resolver.ts +220 -0
- package/src/modules/validation.ts +71 -15
- package/src/store/block_store.ts +108 -101
- package/src/store/contract_class_store.ts +19 -1
- package/src/store/contract_instance_store.ts +18 -1
- package/src/store/log_store.ts +3 -2
- package/src/store/log_store_codec.ts +11 -0
- package/src/test/fake_l1_state.ts +3 -3
- package/src/test/mock_l1_to_l2_message_source.ts +0 -1
- package/src/test/mock_l2_block_source.ts +14 -53
- package/src/test/mock_structs.ts +5 -2
- package/src/test/noop_l1_archiver.ts +30 -11
package/src/factory.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { EpochCache } from '@aztec/epoch-cache';
|
|
2
2
|
import { createEthereumChain } from '@aztec/ethereum/chain';
|
|
3
3
|
import { makeL1HttpTransport } from '@aztec/ethereum/client';
|
|
4
|
-
import { InboxContract, RollupContract } from '@aztec/ethereum/contracts';
|
|
4
|
+
import { InboxContract, OutboxContract, RollupContract } from '@aztec/ethereum/contracts';
|
|
5
5
|
import { pickL1ContractAddresses } from '@aztec/ethereum/l1-contract-addresses';
|
|
6
6
|
import type { ViemPublicDebugClient } from '@aztec/ethereum/types';
|
|
7
7
|
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
@@ -12,11 +12,16 @@ import { DateProvider } from '@aztec/foundation/timer';
|
|
|
12
12
|
import { createStore } from '@aztec/kv-store/lmdb-v2';
|
|
13
13
|
import { protocolContractNames } from '@aztec/protocol-contracts';
|
|
14
14
|
import { BundledProtocolContractsProvider } from '@aztec/protocol-contracts/providers/bundle';
|
|
15
|
+
import { getPublishableStandardContracts } from '@aztec/standard-contracts';
|
|
15
16
|
import { FunctionType, decodeFunctionSignature } from '@aztec/stdlib/abi';
|
|
16
17
|
import type { ArchiverEmitter, BlockHash } from '@aztec/stdlib/block';
|
|
18
|
+
import { DEFAULT_BLOCK_DURATION_MS } from '@aztec/stdlib/config';
|
|
17
19
|
import { type ContractClassPublicWithCommitment, computePublicBytecodeCommitment } from '@aztec/stdlib/contract';
|
|
18
20
|
import type { DataStoreConfig } from '@aztec/stdlib/kv-store';
|
|
19
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
DEFAULT_ORPHAN_PRUNE_NO_PROPOSAL_TOLERANCE,
|
|
23
|
+
getDefaultCheckpointProposalSyncGrace,
|
|
24
|
+
} from '@aztec/stdlib/timetable';
|
|
20
25
|
import type { BlockHeader } from '@aztec/stdlib/tx';
|
|
21
26
|
import { getTelemetryClient } from '@aztec/telemetry-client';
|
|
22
27
|
|
|
@@ -64,6 +69,9 @@ export async function createArchiver(
|
|
|
64
69
|
): Promise<Archiver> {
|
|
65
70
|
const archiverStore = await createArchiverStore(config, initialBlockHash);
|
|
66
71
|
await registerProtocolContracts(archiverStore);
|
|
72
|
+
if (config.testPreloadStandardContracts) {
|
|
73
|
+
await registerStandardContracts(archiverStore);
|
|
74
|
+
}
|
|
67
75
|
|
|
68
76
|
// Create Ethereum clients
|
|
69
77
|
const chain = createEthereumChain(config.l1RpcUrls, config.l1ChainId);
|
|
@@ -85,6 +93,7 @@ export async function createArchiver(
|
|
|
85
93
|
// Create L1 contract instances
|
|
86
94
|
const rollup = new RollupContract(publicClient, config.rollupAddress);
|
|
87
95
|
const inbox = new InboxContract(publicClient, config.inboxAddress);
|
|
96
|
+
const outbox = new OutboxContract(publicClient, config.outboxAddress);
|
|
88
97
|
|
|
89
98
|
// Fetch L1 constants from rollup contract
|
|
90
99
|
const [
|
|
@@ -131,7 +140,12 @@ export async function createArchiver(
|
|
|
131
140
|
maxAllowedEthClientDriftSeconds: 300,
|
|
132
141
|
ethereumAllowNoDebugHosts: false,
|
|
133
142
|
skipHistoricalLogsCheck: false,
|
|
134
|
-
|
|
143
|
+
checkpointProposalSyncGrace:
|
|
144
|
+
config.checkpointProposalSyncGraceSeconds ??
|
|
145
|
+
getDefaultCheckpointProposalSyncGrace((config.blockDurationMs ?? DEFAULT_BLOCK_DURATION_MS) / 1000),
|
|
146
|
+
orphanPruneNoProposalTolerance: DEFAULT_ORPHAN_PRUNE_NO_PROPOSAL_TOLERANCE,
|
|
147
|
+
skipOrphanProposedBlockPruning: false,
|
|
148
|
+
blockDuration: (config.blockDurationMs ?? DEFAULT_BLOCK_DURATION_MS) / 1000,
|
|
135
149
|
},
|
|
136
150
|
mapArchiverConfig(config),
|
|
137
151
|
);
|
|
@@ -171,6 +185,7 @@ export async function createArchiver(
|
|
|
171
185
|
publicClient,
|
|
172
186
|
debugClient,
|
|
173
187
|
rollup,
|
|
188
|
+
outbox,
|
|
174
189
|
{ ...pickL1ContractAddresses(config), slashingProposerAddress },
|
|
175
190
|
archiverStore,
|
|
176
191
|
archiverConfig,
|
|
@@ -182,7 +197,6 @@ export async function createArchiver(
|
|
|
182
197
|
initialHeader,
|
|
183
198
|
initialBlockHash,
|
|
184
199
|
l2TipsCache,
|
|
185
|
-
epochCache,
|
|
186
200
|
deps.dateProvider ?? new DateProvider(),
|
|
187
201
|
);
|
|
188
202
|
|
|
@@ -217,3 +231,33 @@ export async function registerProtocolContracts(stores: ArchiverDataStores) {
|
|
|
217
231
|
await stores.contractInstances.addContractInstances([contract.instance], BlockNumber(blockNumber));
|
|
218
232
|
}
|
|
219
233
|
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Preloads the standard contracts (AuthRegistry, PublicChecks, HandshakeRegistry) into the archiver store at block 0,
|
|
237
|
+
* mirroring {@link registerProtocolContracts}. Only invoked for test environments (via `testPreloadStandardContracts`),
|
|
238
|
+
* which also seed the matching registration/deployment nullifiers into the genesis nullifier tree so the store and tree
|
|
239
|
+
* stay consistent. Idempotent — skips contracts that already exist (e.g. on node restart).
|
|
240
|
+
*/
|
|
241
|
+
export async function registerStandardContracts(stores: ArchiverDataStores) {
|
|
242
|
+
const blockNumber = 0;
|
|
243
|
+
for (const contract of await getPublishableStandardContracts()) {
|
|
244
|
+
// Skip if already registered (happens on node restart with a persisted store).
|
|
245
|
+
if (await stores.contractClasses.getContractClass(contract.contractClass.id)) {
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
const publicBytecodeCommitment = await computePublicBytecodeCommitment(contract.contractClass.packedBytecode);
|
|
250
|
+
const contractClassPublic: ContractClassPublicWithCommitment = {
|
|
251
|
+
...contract.contractClass,
|
|
252
|
+
publicBytecodeCommitment,
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
const publicFunctionSignatures = contract.artifact.functions
|
|
256
|
+
.filter(fn => fn.functionType === FunctionType.PUBLIC)
|
|
257
|
+
.map(fn => decodeFunctionSignature(fn.name, fn.parameters));
|
|
258
|
+
|
|
259
|
+
await stores.functionNames.register(publicFunctionSignatures);
|
|
260
|
+
await stores.contractClasses.addContractClasses([contractClassPublic], BlockNumber(blockNumber));
|
|
261
|
+
await stores.contractInstances.addContractInstances([contract.instance], BlockNumber(blockNumber));
|
|
262
|
+
}
|
|
263
|
+
}
|
|
@@ -34,6 +34,12 @@ type CheckpointData = {
|
|
|
34
34
|
archiveRoot: Fr;
|
|
35
35
|
header: CheckpointHeader;
|
|
36
36
|
attestations: CommitteeAttestation[];
|
|
37
|
+
/**
|
|
38
|
+
* The exact packed `CommitteeAttestations` tuple as it appears in the propose calldata, preserved
|
|
39
|
+
* verbatim (never re-derived from {@link attestations}) so invalidation evidence stays byte-faithful to
|
|
40
|
+
* the on-chain `attestationsHash`.
|
|
41
|
+
*/
|
|
42
|
+
verbatimAttestations: ViemCommitteeAttestations;
|
|
37
43
|
blockHash: string;
|
|
38
44
|
feeAssetPriceModifier: bigint;
|
|
39
45
|
};
|
|
@@ -406,14 +412,14 @@ export class CalldataRetriever {
|
|
|
406
412
|
return undefined;
|
|
407
413
|
}
|
|
408
414
|
|
|
409
|
-
const [decodedArgs,
|
|
415
|
+
const [decodedArgs, verbatimAttestations] = args! as readonly [
|
|
410
416
|
{ archive: Hex; oracleInput: { feeAssetPriceModifier: bigint }; header: ViemHeader },
|
|
411
417
|
ViemCommitteeAttestations,
|
|
412
418
|
...unknown[],
|
|
413
419
|
];
|
|
414
420
|
|
|
415
421
|
// Verify attestationsHash
|
|
416
|
-
const computedAttestationsHash = this.computeAttestationsHash(
|
|
422
|
+
const computedAttestationsHash = this.computeAttestationsHash(verbatimAttestations);
|
|
417
423
|
if (
|
|
418
424
|
!Buffer.from(hexToBytes(computedAttestationsHash)).equals(
|
|
419
425
|
Buffer.from(hexToBytes(expectedHashes.attestationsHash)),
|
|
@@ -441,7 +447,7 @@ export class CalldataRetriever {
|
|
|
441
447
|
return undefined;
|
|
442
448
|
}
|
|
443
449
|
|
|
444
|
-
const attestations = CommitteeAttestation.fromPacked(
|
|
450
|
+
const attestations = CommitteeAttestation.fromPacked(verbatimAttestations, this.targetCommitteeSize);
|
|
445
451
|
|
|
446
452
|
this.logger.trace(`Validated and decoded propose calldata for checkpoint ${checkpointNumber}`, {
|
|
447
453
|
checkpointNumber,
|
|
@@ -449,7 +455,7 @@ export class CalldataRetriever {
|
|
|
449
455
|
header: decodedArgs.header,
|
|
450
456
|
l1BlockHash: blockHash,
|
|
451
457
|
attestations,
|
|
452
|
-
|
|
458
|
+
verbatimAttestations,
|
|
453
459
|
targetCommitteeSize: this.targetCommitteeSize,
|
|
454
460
|
});
|
|
455
461
|
|
|
@@ -458,6 +464,7 @@ export class CalldataRetriever {
|
|
|
458
464
|
archiveRoot,
|
|
459
465
|
header,
|
|
460
466
|
attestations,
|
|
467
|
+
verbatimAttestations,
|
|
461
468
|
blockHash,
|
|
462
469
|
feeAssetPriceModifier,
|
|
463
470
|
};
|
|
@@ -467,8 +474,8 @@ export class CalldataRetriever {
|
|
|
467
474
|
}
|
|
468
475
|
|
|
469
476
|
/** Computes the keccak256 hash of ABI-encoded CommitteeAttestations. */
|
|
470
|
-
private computeAttestationsHash(
|
|
471
|
-
return keccak256(encodeAbiParameters([this.getCommitteeAttestationsStructDef()], [
|
|
477
|
+
private computeAttestationsHash(verbatimAttestations: ViemCommitteeAttestations): Hex {
|
|
478
|
+
return keccak256(encodeAbiParameters([this.getCommitteeAttestationsStructDef()], [verbatimAttestations]));
|
|
472
479
|
}
|
|
473
480
|
|
|
474
481
|
/** Computes the keccak256 payload digest from the checkpoint header, archive root, and fee asset price modifier. */
|
package/src/l1/data_retrieval.ts
CHANGED
|
@@ -12,6 +12,8 @@ import type {
|
|
|
12
12
|
InboxContract,
|
|
13
13
|
MessageSentLog,
|
|
14
14
|
RollupContract,
|
|
15
|
+
ViemCommitteeAttestations,
|
|
16
|
+
ViemHeader,
|
|
15
17
|
} from '@aztec/ethereum/contracts';
|
|
16
18
|
import type { ViemPublicClient, ViemPublicDebugClient } from '@aztec/ethereum/types';
|
|
17
19
|
import { asyncPool } from '@aztec/foundation/async-pool';
|
|
@@ -55,6 +57,11 @@ export type RetrievedCheckpointFromCalldata = RetrievedCheckpointBase & {
|
|
|
55
57
|
blobHashes: Buffer[];
|
|
56
58
|
/** Parent beacon block root from the L1 block, used for blob fetching. */
|
|
57
59
|
parentBeaconBlockRoot: string | undefined;
|
|
60
|
+
/**
|
|
61
|
+
* The exact packed `CommitteeAttestations` tuple from the propose calldata, carried verbatim so that
|
|
62
|
+
* attestation validation can attach byte-faithful invalidation evidence to a negative result.
|
|
63
|
+
*/
|
|
64
|
+
verbatimAttestations: ViemCommitteeAttestations;
|
|
58
65
|
};
|
|
59
66
|
|
|
60
67
|
export async function retrievedToPublishedCheckpoint({
|
|
@@ -460,7 +467,7 @@ export async function getProofFromSubmitProofTx(
|
|
|
460
467
|
start: bigint;
|
|
461
468
|
end: bigint;
|
|
462
469
|
args: EpochProofPublicInputArgs;
|
|
463
|
-
|
|
470
|
+
headers: readonly ViemHeader[];
|
|
464
471
|
proof: Hex;
|
|
465
472
|
},
|
|
466
473
|
];
|
|
@@ -28,16 +28,7 @@ export class ArchiverContractDataSourceAdapter implements ContractDataSource {
|
|
|
28
28
|
return this.stores.contractClasses.getBytecodeCommitment(id);
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
public
|
|
32
|
-
address: AztecAddress,
|
|
33
|
-
maybeTimestamp?: UInt64,
|
|
34
|
-
): Promise<ContractInstanceWithAddress | undefined> {
|
|
35
|
-
let timestamp = maybeTimestamp;
|
|
36
|
-
if (timestamp === undefined) {
|
|
37
|
-
const latest = await this.stores.blocks.getLatestL2BlockNumber();
|
|
38
|
-
const blockData = latest > 0 ? await this.stores.blocks.getBlockData({ number: latest }) : undefined;
|
|
39
|
-
timestamp = blockData ? blockData.header.globalVariables.timestamp : 0n;
|
|
40
|
-
}
|
|
31
|
+
public getContract(address: AztecAddress, timestamp: UInt64): Promise<ContractInstanceWithAddress | undefined> {
|
|
41
32
|
return this.stores.contractInstances.getContractInstance(address, timestamp);
|
|
42
33
|
}
|
|
43
34
|
|
|
@@ -40,9 +40,9 @@ import {
|
|
|
40
40
|
} from '@aztec/stdlib/epoch-helpers';
|
|
41
41
|
import type { L2LogsSource } from '@aztec/stdlib/interfaces/server';
|
|
42
42
|
import type { LogResult, PrivateLogsQuery, PublicLogsQuery } from '@aztec/stdlib/logs';
|
|
43
|
-
import type { L1ToL2MessageSource } from '@aztec/stdlib/messaging';
|
|
43
|
+
import type { L1ToL2MessageSource, L2ToL1MembershipWitness } from '@aztec/stdlib/messaging';
|
|
44
44
|
import { AppendOnlyTreeSnapshot } from '@aztec/stdlib/trees';
|
|
45
|
-
import type { BlockHeader, IndexedTxEffect, TxHash
|
|
45
|
+
import type { BlockHeader, IndexedTxEffect, TxHash } from '@aztec/stdlib/tx';
|
|
46
46
|
import type { UInt64 } from '@aztec/stdlib/types';
|
|
47
47
|
|
|
48
48
|
import type { ArchiverDataSource } from '../interfaces.js';
|
|
@@ -149,6 +149,12 @@ export abstract class ArchiverDataSourceBase
|
|
|
149
149
|
|
|
150
150
|
abstract syncImmediate(): Promise<void>;
|
|
151
151
|
|
|
152
|
+
abstract getL2ToL1MembershipWitness(
|
|
153
|
+
txHash: TxHash,
|
|
154
|
+
message: Fr,
|
|
155
|
+
messageIndexInTx?: number,
|
|
156
|
+
): Promise<L2ToL1MembershipWitness | undefined>;
|
|
157
|
+
|
|
152
158
|
public async isPruneDueAtSlot(slot: SlotNumber): Promise<boolean> {
|
|
153
159
|
if (!this.l1Constants) {
|
|
154
160
|
throw new Error('isPruneDueAtSlot requires l1Constants');
|
|
@@ -218,23 +224,6 @@ export abstract class ArchiverDataSourceBase
|
|
|
218
224
|
}
|
|
219
225
|
}
|
|
220
226
|
|
|
221
|
-
/**
|
|
222
|
-
* Resolves a {@link CheckpointsQuery} to a concrete `{from, limit}` pair used by BlockStore,
|
|
223
|
-
* or undefined when the epoch has no checkpoints.
|
|
224
|
-
*/
|
|
225
|
-
private async resolveCheckpointsQuery(
|
|
226
|
-
query: CheckpointsQuery,
|
|
227
|
-
): Promise<{ from: CheckpointNumber; limit: number } | undefined> {
|
|
228
|
-
if ('from' in query) {
|
|
229
|
-
return query;
|
|
230
|
-
}
|
|
231
|
-
const numbers = await this.getCheckpointNumbersForEpoch(query.epoch);
|
|
232
|
-
if (numbers.length === 0) {
|
|
233
|
-
return undefined;
|
|
234
|
-
}
|
|
235
|
-
return { from: numbers[0], limit: numbers.length };
|
|
236
|
-
}
|
|
237
|
-
|
|
238
227
|
public async getCheckpoint(query: CheckpointQuery): Promise<PublishedCheckpoint | undefined> {
|
|
239
228
|
const number = await this.resolveCheckpointQuery(query);
|
|
240
229
|
if (number === undefined || number === 0) {
|
|
@@ -248,11 +237,7 @@ export abstract class ArchiverDataSourceBase
|
|
|
248
237
|
}
|
|
249
238
|
|
|
250
239
|
public async getCheckpoints(query: CheckpointsQuery): Promise<PublishedCheckpoint[]> {
|
|
251
|
-
const
|
|
252
|
-
if (!resolved) {
|
|
253
|
-
return [];
|
|
254
|
-
}
|
|
255
|
-
const checkpoints = await this.stores.blocks.getRangeOfCheckpoints(resolved.from, resolved.limit);
|
|
240
|
+
const checkpoints = await this.getCheckpointsData(query);
|
|
256
241
|
return Promise.all(checkpoints.map(ch => this.getPublishedCheckpointFromCheckpointData(ch)));
|
|
257
242
|
}
|
|
258
243
|
|
|
@@ -265,11 +250,14 @@ export abstract class ArchiverDataSourceBase
|
|
|
265
250
|
}
|
|
266
251
|
|
|
267
252
|
public async getCheckpointsData(query: CheckpointsQuery): Promise<CheckpointData[]> {
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
return [];
|
|
253
|
+
if ('fromSlot' in query) {
|
|
254
|
+
return this.stores.blocks.getCheckpointsBySlot(query.fromSlot, query.limit, query.reverse ?? false);
|
|
271
255
|
}
|
|
272
|
-
|
|
256
|
+
if ('from' in query) {
|
|
257
|
+
return this.stores.blocks.getRangeOfCheckpoints(query.from, query.limit);
|
|
258
|
+
}
|
|
259
|
+
const numbers = await this.getCheckpointNumbersForEpoch(query.epoch);
|
|
260
|
+
return numbers.length > 0 ? this.stores.blocks.getRangeOfCheckpoints(numbers[0], numbers.length) : [];
|
|
273
261
|
}
|
|
274
262
|
|
|
275
263
|
public getProposedCheckpointData(query?: ProposedCheckpointQuery): Promise<ProposedCheckpointData | undefined> {
|
|
@@ -286,10 +274,6 @@ export abstract class ArchiverDataSourceBase
|
|
|
286
274
|
return this.stores.blocks.getTxEffect(txHash);
|
|
287
275
|
}
|
|
288
276
|
|
|
289
|
-
public getSettledTxReceipt(txHash: TxHash): Promise<TxReceipt | undefined> {
|
|
290
|
-
return this.stores.blocks.getSettledTxReceipt(txHash, this.l1Constants);
|
|
291
|
-
}
|
|
292
|
-
|
|
293
277
|
public isPendingChainInvalid(): Promise<boolean> {
|
|
294
278
|
return this.getPendingChainValidationStatus().then(status => !status.valid);
|
|
295
279
|
}
|
|
@@ -314,18 +298,7 @@ export abstract class ArchiverDataSourceBase
|
|
|
314
298
|
return this.stores.contractClasses.getBytecodeCommitment(id);
|
|
315
299
|
}
|
|
316
300
|
|
|
317
|
-
public
|
|
318
|
-
address: AztecAddress,
|
|
319
|
-
maybeTimestamp?: UInt64,
|
|
320
|
-
): Promise<ContractInstanceWithAddress | undefined> {
|
|
321
|
-
let timestamp;
|
|
322
|
-
if (maybeTimestamp === undefined) {
|
|
323
|
-
const latestBlockData = await this.getBlockData({ tag: 'proposed' });
|
|
324
|
-
timestamp = latestBlockData ? latestBlockData.header.globalVariables.timestamp : 0n;
|
|
325
|
-
} else {
|
|
326
|
-
timestamp = maybeTimestamp;
|
|
327
|
-
}
|
|
328
|
-
|
|
301
|
+
public getContract(address: AztecAddress, timestamp: UInt64): Promise<ContractInstanceWithAddress | undefined> {
|
|
329
302
|
return this.stores.contractInstances.getContractInstance(address, timestamp);
|
|
330
303
|
}
|
|
331
304
|
|
|
@@ -114,10 +114,11 @@ export class ArchiverDataStoreUpdater {
|
|
|
114
114
|
// Before adding checkpoints, check for conflicts with local blocks if any
|
|
115
115
|
const { prunedBlocks, lastAlreadyInsertedBlockNumber } = await this.pruneMismatchingLocalBlocks(checkpoints);
|
|
116
116
|
|
|
117
|
-
await this.stores.blocks.addCheckpoints(checkpoints);
|
|
117
|
+
const insertedCheckpoints = await this.stores.blocks.addCheckpoints(checkpoints);
|
|
118
118
|
|
|
119
|
-
//
|
|
120
|
-
|
|
119
|
+
// Skip blocks already inserted via addProposedBlock() and blocks of already-stored checkpoints
|
|
120
|
+
// re-included by an L1 reorg: their logs/contract data were extracted when first inserted.
|
|
121
|
+
const newBlocks = insertedCheckpoints
|
|
121
122
|
.flatMap((ch: PublishedCheckpoint) => ch.checkpoint.blocks)
|
|
122
123
|
.filter(b => lastAlreadyInsertedBlockNumber === undefined || b.number > lastAlreadyInsertedBlockNumber);
|
|
123
124
|
|
|
@@ -84,7 +84,9 @@ export class ArchiverInstrumentation {
|
|
|
84
84
|
|
|
85
85
|
this.pruneDuration = meter.createHistogram(Metrics.ARCHIVER_PRUNE_DURATION);
|
|
86
86
|
|
|
87
|
-
this.pruneCount = createUpDownCounterWithDefault(meter, Metrics.ARCHIVER_PRUNE_COUNT
|
|
87
|
+
this.pruneCount = createUpDownCounterWithDefault(meter, Metrics.ARCHIVER_PRUNE_COUNT, {
|
|
88
|
+
[Attributes.PRUNE_TYPE]: ['unproven', 'uncheckpointed', 'l1_conflict', 'orphan', 'l1_mismatch'],
|
|
89
|
+
});
|
|
88
90
|
|
|
89
91
|
this.blockProposalTxTargetCount = createUpDownCounterWithDefault(
|
|
90
92
|
meter,
|
|
@@ -150,10 +152,21 @@ export class ArchiverInstrumentation {
|
|
|
150
152
|
}
|
|
151
153
|
|
|
152
154
|
public processPrune(duration: number) {
|
|
153
|
-
this.pruneCount.add(1);
|
|
155
|
+
this.pruneCount.add(1, { [Attributes.PRUNE_TYPE]: 'unproven' });
|
|
154
156
|
this.pruneDuration.record(Math.ceil(duration));
|
|
155
157
|
}
|
|
156
158
|
|
|
159
|
+
/**
|
|
160
|
+
* Records a pending-chain reorg, where the archiver dropped proposed blocks (and world-state follows by pruning). The
|
|
161
|
+
* type distinguishes the cause: 'uncheckpointed' (slot ended without a checkpoint), 'l1_conflict' (proposed blocks
|
|
162
|
+
* conflicting with an L1 checkpoint), 'orphan' (no matching proposed checkpoint arrived before the deadline), or
|
|
163
|
+
* 'l1_mismatch' (the local checkpointed tip diverged from L1 — an L1 reorg or a pruned/missed-proof checkpoint — so
|
|
164
|
+
* already-checkpointed blocks were rewound).
|
|
165
|
+
*/
|
|
166
|
+
public recordPrune(pruneType: 'uncheckpointed' | 'l1_conflict' | 'orphan' | 'l1_mismatch') {
|
|
167
|
+
this.pruneCount.add(1, { [Attributes.PRUNE_TYPE]: pruneType });
|
|
168
|
+
}
|
|
169
|
+
|
|
157
170
|
public updateLastProvenCheckpoint(checkpoint: CheckpointData) {
|
|
158
171
|
const lastBlockNumberInCheckpoint = checkpoint.startBlock + checkpoint.blockCount - 1;
|
|
159
172
|
this.blockHeight.record(lastBlockNumberInCheckpoint, { [Attributes.STATUS]: 'proven' });
|