@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
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { SlotNumber } from '@aztec/foundation/branded-types';
|
|
2
2
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
3
|
+
import { DateProvider } from '@aztec/foundation/timer';
|
|
3
4
|
import type { BlockHash } from '@aztec/stdlib/block';
|
|
4
5
|
import type { L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
|
|
5
6
|
import type { BlockHeader } from '@aztec/stdlib/tx';
|
|
@@ -8,6 +9,9 @@ import { Archiver } from '../archiver.js';
|
|
|
8
9
|
import { ArchiverInstrumentation } from '../modules/instrumentation.js';
|
|
9
10
|
import type { ArchiverDataStores } from '../store/data_stores.js';
|
|
10
11
|
import { L2TipsCache } from '../store/l2_tips_cache.js';
|
|
12
|
+
type NoopL1ArchiverConfigOverrides = Partial<{
|
|
13
|
+
skipOrphanProposedBlockPruning: boolean;
|
|
14
|
+
}>;
|
|
11
15
|
/**
|
|
12
16
|
* Archiver with mocked L1 connectivity for testing.
|
|
13
17
|
* Uses mock L1 clients and a noop synchronizer, enabling tests that
|
|
@@ -16,7 +20,7 @@ import { L2TipsCache } from '../store/l2_tips_cache.js';
|
|
|
16
20
|
export declare class NoopL1Archiver extends Archiver {
|
|
17
21
|
constructor(dataStores: ArchiverDataStores, l1Constants: L1RollupConstants & {
|
|
18
22
|
genesisArchiveRoot: Fr;
|
|
19
|
-
}, instrumentation: ArchiverInstrumentation, initialHeader: BlockHeader, initialBlockHash: BlockHash, l2TipsCache: L2TipsCache);
|
|
23
|
+
}, instrumentation: ArchiverInstrumentation, initialHeader: BlockHeader, initialBlockHash: BlockHash, l2TipsCache: L2TipsCache, dateProvider?: DateProvider, configOverrides?: NoopL1ArchiverConfigOverrides);
|
|
20
24
|
/** Override start to skip L1 validation checks. */
|
|
21
25
|
start(_blockUntilSynced?: boolean): Promise<void>;
|
|
22
26
|
/** Always reports as fully synced since there is no real L1 to sync from. */
|
|
@@ -25,5 +29,6 @@ export declare class NoopL1Archiver extends Archiver {
|
|
|
25
29
|
/** Creates an archiver with mocked L1 connectivity for testing. */
|
|
26
30
|
export declare function createNoopL1Archiver(dataStores: ArchiverDataStores, l1Constants: L1RollupConstants & {
|
|
27
31
|
genesisArchiveRoot: Fr;
|
|
28
|
-
}, telemetry: TelemetryClient | undefined, initialHeader: BlockHeader): Promise<NoopL1Archiver>;
|
|
29
|
-
|
|
32
|
+
}, telemetry: TelemetryClient | undefined, initialHeader: BlockHeader, dateProvider?: DateProvider, configOverrides?: NoopL1ArchiverConfigOverrides): Promise<NoopL1Archiver>;
|
|
33
|
+
export {};
|
|
34
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm9vcF9sMV9hcmNoaXZlci5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3Rlc3Qvbm9vcF9sMV9hcmNoaXZlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFHQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFFN0QsT0FBTyxFQUFFLEVBQUUsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBRXBELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUV2RCxPQUFPLEtBQUssRUFBbUIsU0FBUyxFQUFXLE1BQU0scUJBQXFCLENBQUM7QUFDL0UsT0FBTyxLQUFLLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUNyRSxPQUFPLEtBQUssRUFBRSxXQUFXLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUNwRCxPQUFPLEVBQUUsS0FBSyxlQUFlLEVBQW1DLE1BQU0seUJBQXlCLENBQUM7QUFLaEcsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzFDLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBRXhFLE9BQU8sS0FBSyxFQUFFLGtCQUFrQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDbEUsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBRXhELEtBQUssNkJBQTZCLEdBQUcsT0FBTyxDQUFDO0lBQzNDLDhCQUE4QixFQUFFLE9BQU8sQ0FBQztDQUN6QyxDQUFDLENBQUM7QUF5Qkg7Ozs7R0FJRztBQUNILHFCQUFhLGNBQWUsU0FBUSxRQUFRO0lBQzFDLFlBQ0UsVUFBVSxFQUFFLGtCQUFrQixFQUM5QixXQUFXLEVBQUUsaUJBQWlCLEdBQUc7UUFBRSxrQkFBa0IsRUFBRSxFQUFFLENBQUE7S0FBRSxFQUMzRCxlQUFlLEVBQUUsdUJBQXVCLEVBQ3hDLGFBQWEsRUFBRSxXQUFXLEVBQzFCLGdCQUFnQixFQUFFLFNBQVMsRUFDM0IsV0FBVyxFQUFFLFdBQVcsRUFDeEIsWUFBWSxHQUFFLFlBQWlDLEVBQy9DLGVBQWUsR0FBRSw2QkFBa0MsRUFvRHBEO0lBRUQsbURBQW1EO0lBQ25DLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQyxFQUFFLE9BQU8sR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLENBSWhFO0lBRUQsNkVBQTZFO0lBQzdELHFCQUFxQixJQUFJLE9BQU8sQ0FBQyxVQUFVLEdBQUcsU0FBUyxDQUFDLENBRXZFO0NBQ0Y7QUFFRCxtRUFBbUU7QUFDbkUsd0JBQXNCLG9CQUFvQixDQUN4QyxVQUFVLEVBQUUsa0JBQWtCLEVBQzlCLFdBQVcsRUFBRSxpQkFBaUIsR0FBRztJQUFFLGtCQUFrQixFQUFFLEVBQUUsQ0FBQTtDQUFFLEVBQzNELFNBQVMsNkJBQXdDLEVBQ2pELGFBQWEsRUFBRSxXQUFXLEVBQzFCLFlBQVksQ0FBQyxFQUFFLFlBQVksRUFDM0IsZUFBZSxDQUFDLEVBQUUsNkJBQTZCLEdBQzlDLE9BQU8sQ0FBQyxjQUFjLENBQUMsQ0FrQnpCIn0=
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"noop_l1_archiver.d.ts","sourceRoot":"","sources":["../../src/test/noop_l1_archiver.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"noop_l1_archiver.d.ts","sourceRoot":"","sources":["../../src/test/noop_l1_archiver.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAE7D,OAAO,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AAEpD,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAEvD,OAAO,KAAK,EAAmB,SAAS,EAAW,MAAM,qBAAqB,CAAC;AAC/E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,KAAK,eAAe,EAAmC,MAAM,yBAAyB,CAAC;AAKhG,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AAExE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAExD,KAAK,6BAA6B,GAAG,OAAO,CAAC;IAC3C,8BAA8B,EAAE,OAAO,CAAC;CACzC,CAAC,CAAC;AAyBH;;;;GAIG;AACH,qBAAa,cAAe,SAAQ,QAAQ;IAC1C,YACE,UAAU,EAAE,kBAAkB,EAC9B,WAAW,EAAE,iBAAiB,GAAG;QAAE,kBAAkB,EAAE,EAAE,CAAA;KAAE,EAC3D,eAAe,EAAE,uBAAuB,EACxC,aAAa,EAAE,WAAW,EAC1B,gBAAgB,EAAE,SAAS,EAC3B,WAAW,EAAE,WAAW,EACxB,YAAY,GAAE,YAAiC,EAC/C,eAAe,GAAE,6BAAkC,EAoDpD;IAED,mDAAmD;IACnC,KAAK,CAAC,iBAAiB,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAIhE;IAED,6EAA6E;IAC7D,qBAAqB,IAAI,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAEvE;CACF;AAED,mEAAmE;AACnE,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,kBAAkB,EAC9B,WAAW,EAAE,iBAAiB,GAAG;IAAE,kBAAkB,EAAE,EAAE,CAAA;CAAE,EAC3D,SAAS,6BAAwC,EACjD,aAAa,EAAE,WAAW,EAC1B,YAAY,CAAC,EAAE,YAAY,EAC3B,eAAe,CAAC,EAAE,6BAA6B,GAC9C,OAAO,CAAC,cAAc,CAAC,CAkBzB"}
|
|
@@ -24,7 +24,7 @@ import { L2TipsCache } from '../store/l2_tips_cache.js';
|
|
|
24
24
|
return Promise.resolve();
|
|
25
25
|
}
|
|
26
26
|
syncFromL1(_initialSyncComplete) {
|
|
27
|
-
return Promise.resolve();
|
|
27
|
+
return Promise.resolve([]);
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
/**
|
|
@@ -32,20 +32,19 @@ import { L2TipsCache } from '../store/l2_tips_cache.js';
|
|
|
32
32
|
* Uses mock L1 clients and a noop synchronizer, enabling tests that
|
|
33
33
|
* don't require real Ethereum connectivity.
|
|
34
34
|
*/ export class NoopL1Archiver extends Archiver {
|
|
35
|
-
constructor(dataStores, l1Constants, instrumentation, initialHeader, initialBlockHash, l2TipsCache){
|
|
35
|
+
constructor(dataStores, l1Constants, instrumentation, initialHeader, initialBlockHash, l2TipsCache, dateProvider = new DateProvider(), configOverrides = {}){
|
|
36
36
|
// Create mocks for L1 clients
|
|
37
37
|
const publicClient = mock();
|
|
38
38
|
const debugClient = mock();
|
|
39
39
|
const rollup = mock();
|
|
40
|
+
const outbox = mock();
|
|
40
41
|
const blobClient = mock();
|
|
41
42
|
// Mock methods called during start()
|
|
42
43
|
blobClient.testSources.mockResolvedValue();
|
|
43
44
|
publicClient.getBlockNumber.mockResolvedValue(1n);
|
|
44
45
|
const events = new EventEmitter();
|
|
45
46
|
const synchronizer = new NoopL1Synchronizer(instrumentation.tracer);
|
|
46
|
-
|
|
47
|
-
epochCache.pipeliningOffset.mockReturnValue(0);
|
|
48
|
-
super(publicClient, debugClient, rollup, {
|
|
47
|
+
super(publicClient, debugClient, rollup, outbox, {
|
|
49
48
|
rollupAddress: EthAddress.ZERO,
|
|
50
49
|
registryAddress: EthAddress.ZERO,
|
|
51
50
|
inboxAddress: EthAddress.ZERO,
|
|
@@ -58,11 +57,15 @@ import { L2TipsCache } from '../store/l2_tips_cache.js';
|
|
|
58
57
|
maxAllowedEthClientDriftSeconds: 300,
|
|
59
58
|
ethereumAllowNoDebugHosts: true,
|
|
60
59
|
skipHistoricalLogsCheck: true,
|
|
61
|
-
|
|
60
|
+
checkpointProposalSyncGrace: 4,
|
|
61
|
+
orphanPruneNoProposalTolerance: 1,
|
|
62
|
+
skipOrphanProposedBlockPruning: true,
|
|
63
|
+
blockDuration: 2,
|
|
64
|
+
...configOverrides
|
|
62
65
|
}, blobClient, instrumentation, {
|
|
63
66
|
...l1Constants,
|
|
64
67
|
l1StartBlockHash: Buffer32.random()
|
|
65
|
-
}, synchronizer, events, initialHeader, initialBlockHash, l2TipsCache,
|
|
68
|
+
}, synchronizer, events, initialHeader, initialBlockHash, l2TipsCache, dateProvider);
|
|
66
69
|
}
|
|
67
70
|
/** Override start to skip L1 validation checks. */ start(_blockUntilSynced) {
|
|
68
71
|
// Just start the running promise without L1 checks
|
|
@@ -73,7 +76,7 @@ import { L2TipsCache } from '../store/l2_tips_cache.js';
|
|
|
73
76
|
return Promise.resolve(SlotNumber(Number.MAX_SAFE_INTEGER));
|
|
74
77
|
}
|
|
75
78
|
}
|
|
76
|
-
/** Creates an archiver with mocked L1 connectivity for testing. */ export async function createNoopL1Archiver(dataStores, l1Constants, telemetry = getTelemetryClient(), initialHeader) {
|
|
79
|
+
/** Creates an archiver with mocked L1 connectivity for testing. */ export async function createNoopL1Archiver(dataStores, l1Constants, telemetry = getTelemetryClient(), initialHeader, dateProvider, configOverrides) {
|
|
77
80
|
const instrumentation = await ArchiverInstrumentation.new(telemetry, ()=>dataStores.db.estimateSize());
|
|
78
81
|
// Mirror the production factory: precompute the dynamic genesis block hash from the injected
|
|
79
82
|
// initial header so `L2TipsCache` reports the correct tip hash at block 0. Without this, the
|
|
@@ -81,5 +84,5 @@ import { L2TipsCache } from '../store/l2_tips_cache.js';
|
|
|
81
84
|
// with default empty genesis.
|
|
82
85
|
const initialBlockHash = await initialHeader.hash();
|
|
83
86
|
const l2TipsCache = new L2TipsCache(dataStores.blocks, initialBlockHash);
|
|
84
|
-
return new NoopL1Archiver(dataStores, l1Constants, instrumentation, initialHeader, initialBlockHash, l2TipsCache);
|
|
87
|
+
return new NoopL1Archiver(dataStores, l1Constants, instrumentation, initialHeader, initialBlockHash, l2TipsCache, dateProvider, configOverrides);
|
|
85
88
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aztec/archiver",
|
|
3
|
-
"version": "0.0.1-commit.
|
|
3
|
+
"version": "0.0.1-commit.9a89641",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./dest/index.js",
|
|
@@ -65,18 +65,18 @@
|
|
|
65
65
|
]
|
|
66
66
|
},
|
|
67
67
|
"dependencies": {
|
|
68
|
-
"@aztec/blob-client": "0.0.1-commit.
|
|
69
|
-
"@aztec/blob-lib": "0.0.1-commit.
|
|
70
|
-
"@aztec/constants": "0.0.1-commit.
|
|
71
|
-
"@aztec/epoch-cache": "0.0.1-commit.
|
|
72
|
-
"@aztec/ethereum": "0.0.1-commit.
|
|
73
|
-
"@aztec/foundation": "0.0.1-commit.
|
|
74
|
-
"@aztec/kv-store": "0.0.1-commit.
|
|
75
|
-
"@aztec/l1-artifacts": "0.0
|
|
76
|
-
"@aztec/
|
|
77
|
-
"@aztec/
|
|
78
|
-
"@aztec/stdlib": "0.0.1-commit.
|
|
79
|
-
"@aztec/telemetry-client": "0.0.1-commit.
|
|
68
|
+
"@aztec/blob-client": "0.0.1-commit.9a89641",
|
|
69
|
+
"@aztec/blob-lib": "0.0.1-commit.9a89641",
|
|
70
|
+
"@aztec/constants": "0.0.1-commit.9a89641",
|
|
71
|
+
"@aztec/epoch-cache": "0.0.1-commit.9a89641",
|
|
72
|
+
"@aztec/ethereum": "0.0.1-commit.9a89641",
|
|
73
|
+
"@aztec/foundation": "0.0.1-commit.9a89641",
|
|
74
|
+
"@aztec/kv-store": "0.0.1-commit.9a89641",
|
|
75
|
+
"@aztec/l1-artifacts": "6.0.0-nightly.20260807",
|
|
76
|
+
"@aztec/protocol-contracts": "0.0.1-commit.9a89641",
|
|
77
|
+
"@aztec/standard-contracts": "0.0.1-commit.9a89641",
|
|
78
|
+
"@aztec/stdlib": "0.0.1-commit.9a89641",
|
|
79
|
+
"@aztec/telemetry-client": "0.0.1-commit.9a89641",
|
|
80
80
|
"lodash.groupby": "^4.6.0",
|
|
81
81
|
"lodash.omit": "^4.5.0",
|
|
82
82
|
"tslib": "^2.5.0",
|
package/src/archiver.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type { BlobClientInterface } from '@aztec/blob-client/client';
|
|
2
2
|
import { EpochCache } from '@aztec/epoch-cache';
|
|
3
|
-
import { BlockTagTooOldError, RollupContract } from '@aztec/ethereum/contracts';
|
|
3
|
+
import { BlockTagTooOldError, OutboxContract, RollupContract } from '@aztec/ethereum/contracts';
|
|
4
4
|
import type { L1ContractAddresses } from '@aztec/ethereum/l1-contract-addresses';
|
|
5
5
|
import type { ViemPublicClient, ViemPublicDebugClient } from '@aztec/ethereum/types';
|
|
6
6
|
import { BlockNumber, CheckpointNumber, EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
|
|
7
7
|
import { Buffer32 } from '@aztec/foundation/buffer';
|
|
8
|
-
import { merge
|
|
8
|
+
import { merge } from '@aztec/foundation/collection';
|
|
9
9
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
10
10
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
11
11
|
import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
L2BlockSourceEvents,
|
|
21
21
|
type L2Tips,
|
|
22
22
|
type ValidateCheckpointResult,
|
|
23
|
+
l2TipsEqual,
|
|
23
24
|
} from '@aztec/stdlib/block';
|
|
24
25
|
import { type ProposedCheckpointInput, PublishedCheckpoint } from '@aztec/stdlib/checkpoint';
|
|
25
26
|
import {
|
|
@@ -30,7 +31,9 @@ import {
|
|
|
30
31
|
getTimestampForSlot,
|
|
31
32
|
getTimestampRangeForEpoch,
|
|
32
33
|
} from '@aztec/stdlib/epoch-helpers';
|
|
33
|
-
import type {
|
|
34
|
+
import type { L2ToL1MembershipWitness } from '@aztec/stdlib/messaging';
|
|
35
|
+
import { ConsensusTimetable } from '@aztec/stdlib/timetable';
|
|
36
|
+
import type { BlockHeader, TxHash } from '@aztec/stdlib/tx';
|
|
34
37
|
import { type TelemetryClient, type Traceable, type Tracer, trackSpan } from '@aztec/telemetry-client';
|
|
35
38
|
|
|
36
39
|
import { type ArchiverConfig, mapArchiverConfig } from './config.js';
|
|
@@ -41,6 +44,7 @@ import { ArchiverDataSourceBase } from './modules/data_source_base.js';
|
|
|
41
44
|
import { ArchiverDataStoreUpdater } from './modules/data_store_updater.js';
|
|
42
45
|
import type { ArchiverInstrumentation } from './modules/instrumentation.js';
|
|
43
46
|
import type { ArchiverL1Synchronizer } from './modules/l1_synchronizer.js';
|
|
47
|
+
import { OutboxTreesResolver } from './modules/outbox_trees_resolver.js';
|
|
44
48
|
import { type ArchiverDataStores, backupArchiverDataStores, getArchiverSynchPoint } from './store/data_stores.js';
|
|
45
49
|
import { L2TipsCache } from './store/l2_tips_cache.js';
|
|
46
50
|
|
|
@@ -70,6 +74,16 @@ export type ArchiverDeps = {
|
|
|
70
74
|
dateProvider?: DateProvider;
|
|
71
75
|
};
|
|
72
76
|
|
|
77
|
+
/** Minimal dependency for observing whether a checkpoint proposal was received for a slot. */
|
|
78
|
+
export type CheckpointProposalPresence = {
|
|
79
|
+
/** Returns true when a checkpoint proposal for `slot` has been retained locally. */
|
|
80
|
+
hasCheckpointProposalForSlot(slot: SlotNumber): Promise<boolean>;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const noCheckpointProposalPresence: CheckpointProposalPresence = {
|
|
84
|
+
hasCheckpointProposalForSlot: () => Promise.resolve(false),
|
|
85
|
+
};
|
|
86
|
+
|
|
73
87
|
/**
|
|
74
88
|
* Pulls checkpoints in a non-blocking manner and provides interface for their retrieval.
|
|
75
89
|
* Responsible for handling robust L1 polling so that other components do not need to
|
|
@@ -85,6 +99,9 @@ export class Archiver extends ArchiverDataSourceBase implements L2BlockSink, Tra
|
|
|
85
99
|
/** L1 synchronizer that handles fetching checkpoints and messages from L1. */
|
|
86
100
|
private readonly synchronizer: ArchiverL1Synchronizer;
|
|
87
101
|
|
|
102
|
+
/** Resolver for L2-to-L1 message membership witnesses, built over this archiver's read view. */
|
|
103
|
+
private readonly outboxTreesResolver: OutboxTreesResolver;
|
|
104
|
+
|
|
88
105
|
private initialSyncComplete: boolean = false;
|
|
89
106
|
private initialSyncPromise: PromiseWithResolvers<void>;
|
|
90
107
|
|
|
@@ -97,6 +114,9 @@ export class Archiver extends ArchiverDataSourceBase implements L2BlockSink, Tra
|
|
|
97
114
|
/** In-memory cache for L2 chain tips. */
|
|
98
115
|
private readonly l2TipsCache: L2TipsCache;
|
|
99
116
|
|
|
117
|
+
/** Consensus timing model used for proposed-checkpoint arrival expectations. */
|
|
118
|
+
private readonly timetable: ConsensusTimetable;
|
|
119
|
+
|
|
100
120
|
public readonly tracer: Tracer;
|
|
101
121
|
|
|
102
122
|
private readonly instrumentation: ArchiverInstrumentation;
|
|
@@ -106,6 +126,7 @@ export class Archiver extends ArchiverDataSourceBase implements L2BlockSink, Tra
|
|
|
106
126
|
* @param publicClient - A client for interacting with the Ethereum node.
|
|
107
127
|
* @param debugClient - A client for interacting with the Ethereum node for debug/trace methods.
|
|
108
128
|
* @param rollup - Rollup contract instance.
|
|
129
|
+
* @param outbox - Outbox contract instance, used to read per-epoch L2-to-L1 message roots.
|
|
109
130
|
* @param inbox - Inbox contract instance.
|
|
110
131
|
* @param l1Addresses - L1 contract addresses (registry, governance proposer, slashing proposer).
|
|
111
132
|
* @param dataStores - Archiver substores for storage & retrieval of blocks, encrypted logs & contract data.
|
|
@@ -118,7 +139,6 @@ export class Archiver extends ArchiverDataSourceBase implements L2BlockSink, Tra
|
|
|
118
139
|
* @param initialHeader - Genesis block header.
|
|
119
140
|
* @param initialBlockHash - Precomputed hash of the genesis block header.
|
|
120
141
|
* @param l2TipsCache - In-memory cache for L2 chain tips.
|
|
121
|
-
* @param epochCache - Cache used to compute the proposer pipelining offset.
|
|
122
142
|
* @param dateProvider - Provider for current date/time, used for wall-clock orphan-block pruning.
|
|
123
143
|
* @param log - A logger.
|
|
124
144
|
*/
|
|
@@ -126,6 +146,7 @@ export class Archiver extends ArchiverDataSourceBase implements L2BlockSink, Tra
|
|
|
126
146
|
private readonly publicClient: ViemPublicClient,
|
|
127
147
|
private readonly debugClient: ViemPublicDebugClient,
|
|
128
148
|
private readonly rollup: RollupContract,
|
|
149
|
+
private readonly outbox: OutboxContract,
|
|
129
150
|
private readonly l1Addresses: Pick<
|
|
130
151
|
L1ContractAddresses,
|
|
131
152
|
'rollupAddress' | 'registryAddress' | 'inboxAddress' | 'governanceProposerAddress'
|
|
@@ -140,7 +161,10 @@ export class Archiver extends ArchiverDataSourceBase implements L2BlockSink, Tra
|
|
|
140
161
|
maxAllowedEthClientDriftSeconds: number;
|
|
141
162
|
ethereumAllowNoDebugHosts?: boolean;
|
|
142
163
|
skipHistoricalLogsCheck?: boolean;
|
|
143
|
-
|
|
164
|
+
checkpointProposalSyncGrace: number;
|
|
165
|
+
orphanPruneNoProposalTolerance: number;
|
|
166
|
+
skipOrphanProposedBlockPruning: boolean;
|
|
167
|
+
blockDuration: number;
|
|
144
168
|
},
|
|
145
169
|
private readonly blobClient: BlobClientInterface,
|
|
146
170
|
instrumentation: ArchiverInstrumentation,
|
|
@@ -153,8 +177,8 @@ export class Archiver extends ArchiverDataSourceBase implements L2BlockSink, Tra
|
|
|
153
177
|
initialHeader: BlockHeader,
|
|
154
178
|
initialBlockHash: BlockHash,
|
|
155
179
|
l2TipsCache: L2TipsCache,
|
|
156
|
-
private readonly epochCache: EpochCache,
|
|
157
180
|
private readonly dateProvider: DateProvider,
|
|
181
|
+
private checkpointProposalPresence: CheckpointProposalPresence = noCheckpointProposalPresence,
|
|
158
182
|
private readonly log: Logger = createLogger('archiver'),
|
|
159
183
|
) {
|
|
160
184
|
super(dataStores, l1Constants, initialHeader, initialBlockHash, l1Constants.genesisArchiveRoot);
|
|
@@ -165,10 +189,25 @@ export class Archiver extends ArchiverDataSourceBase implements L2BlockSink, Tra
|
|
|
165
189
|
this.synchronizer = synchronizer;
|
|
166
190
|
this.events = events;
|
|
167
191
|
this.l2TipsCache = l2TipsCache;
|
|
192
|
+
this.timetable = new ConsensusTimetable({
|
|
193
|
+
l1Constants,
|
|
194
|
+
blockDuration: this.config.blockDuration,
|
|
195
|
+
checkpointProposalSyncGrace: this.config.checkpointProposalSyncGrace,
|
|
196
|
+
});
|
|
168
197
|
this.updater = new ArchiverDataStoreUpdater(this.dataStores, this.l2TipsCache, {
|
|
169
198
|
rollupManaLimit: l1Constants.rollupManaLimit,
|
|
170
199
|
});
|
|
171
200
|
|
|
201
|
+
// The resolver reads its witness data from this archiver and pins its lazy Outbox-root fetches
|
|
202
|
+
// to the archiver's synced L1 block. No method on `this` is invoked during construction.
|
|
203
|
+
this.outboxTreesResolver = new OutboxTreesResolver(
|
|
204
|
+
this.outbox,
|
|
205
|
+
this,
|
|
206
|
+
this.dataStores.db,
|
|
207
|
+
() => Promise.resolve(this.getL1BlockNumber()),
|
|
208
|
+
l1Constants.epochDuration,
|
|
209
|
+
);
|
|
210
|
+
|
|
172
211
|
// Running promise starts with a small interval inbetween runs, so all iterations needed for the initial sync
|
|
173
212
|
// are done as fast as possible. This then gets updated once the initial sync completes.
|
|
174
213
|
this.runningPromise = new RunningPromise(
|
|
@@ -179,6 +218,27 @@ export class Archiver extends ArchiverDataSourceBase implements L2BlockSink, Tra
|
|
|
179
218
|
);
|
|
180
219
|
}
|
|
181
220
|
|
|
221
|
+
/**
|
|
222
|
+
* Returns the L2-to-L1 membership witness for `message` emitted by tx `txHash`. The node selects
|
|
223
|
+
* the smallest partial-proof root on the Outbox that covers the tx's checkpoint and builds the
|
|
224
|
+
* witness against it.
|
|
225
|
+
*
|
|
226
|
+
* The node reads the Outbox roots lazily, pinned to its synced L1 block, so the witness reflects
|
|
227
|
+
* the node's synced view. Returns `undefined` if the tx isn't yet in a block/epoch or no covering
|
|
228
|
+
* root has landed on L1 as of the synced block.
|
|
229
|
+
*
|
|
230
|
+
* Caveat: roots are cached only for the current synced L1 block and re-fetched once the node
|
|
231
|
+
* advances, so a reorg is picked up on the next synced-block advance rather than re-validated per
|
|
232
|
+
* request.
|
|
233
|
+
*/
|
|
234
|
+
public getL2ToL1MembershipWitness(
|
|
235
|
+
txHash: TxHash,
|
|
236
|
+
message: Fr,
|
|
237
|
+
messageIndexInTx?: number,
|
|
238
|
+
): Promise<L2ToL1MembershipWitness | undefined> {
|
|
239
|
+
return this.outboxTreesResolver.getL2ToL1MembershipWitness(txHash, message, messageIndexInTx);
|
|
240
|
+
}
|
|
241
|
+
|
|
182
242
|
/** Updates archiver config */
|
|
183
243
|
public updateConfig(newConfig: Partial<ArchiverConfig>) {
|
|
184
244
|
this.config = merge(this.config, mapArchiverConfig(newConfig));
|
|
@@ -235,6 +295,11 @@ export class Archiver extends ArchiverDataSourceBase implements L2BlockSink, Tra
|
|
|
235
295
|
return this.runningPromise.trigger();
|
|
236
296
|
}
|
|
237
297
|
|
|
298
|
+
/** Sets the proposal-presence provider used by orphan proposed-block pruning. */
|
|
299
|
+
public setCheckpointProposalPresence(checkpointProposalPresence: CheckpointProposalPresence): void {
|
|
300
|
+
this.checkpointProposalPresence = checkpointProposalPresence;
|
|
301
|
+
}
|
|
302
|
+
|
|
238
303
|
public trySyncImmediate() {
|
|
239
304
|
try {
|
|
240
305
|
return this.syncImmediate();
|
|
@@ -276,9 +341,10 @@ export class Archiver extends ArchiverDataSourceBase implements L2BlockSink, Tra
|
|
|
276
341
|
* Called at the beginning of each sync iteration.
|
|
277
342
|
* Items are processed in the order they were queued.
|
|
278
343
|
*/
|
|
279
|
-
private async processInboundQueue(): Promise<
|
|
344
|
+
private async processInboundQueue(): Promise<L2Block[]> {
|
|
345
|
+
const blocksAdded: L2Block[] = [];
|
|
280
346
|
if (this.inboundQueue.length === 0) {
|
|
281
|
-
return;
|
|
347
|
+
return blocksAdded;
|
|
282
348
|
}
|
|
283
349
|
|
|
284
350
|
// Take all items from the queue
|
|
@@ -315,6 +381,7 @@ export class Archiver extends ArchiverDataSourceBase implements L2BlockSink, Tra
|
|
|
315
381
|
if (type === 'block') {
|
|
316
382
|
const [durationMs] = await elapsed(() => this.updater.addProposedBlock(item.block));
|
|
317
383
|
this.instrumentation.processNewProposedBlock(durationMs, item.block);
|
|
384
|
+
blocksAdded.push(item.block);
|
|
318
385
|
} else {
|
|
319
386
|
await this.updater.addProposedCheckpoint(item.checkpoint);
|
|
320
387
|
}
|
|
@@ -323,6 +390,7 @@ export class Archiver extends ArchiverDataSourceBase implements L2BlockSink, Tra
|
|
|
323
390
|
} catch (err: any) {
|
|
324
391
|
if (err instanceof BlockAlreadyCheckpointedError) {
|
|
325
392
|
this.log.debug(`Proposed block ${itemNumber} matches already checkpointed block, ignoring late proposal`);
|
|
393
|
+
// A late proposal that matches an already-checkpointed block adds nothing new, so it is not appended.
|
|
326
394
|
resolve();
|
|
327
395
|
continue;
|
|
328
396
|
}
|
|
@@ -333,6 +401,7 @@ export class Archiver extends ArchiverDataSourceBase implements L2BlockSink, Tra
|
|
|
333
401
|
reject(err);
|
|
334
402
|
}
|
|
335
403
|
}
|
|
404
|
+
return blocksAdded;
|
|
336
405
|
}
|
|
337
406
|
|
|
338
407
|
public waitForInitialSync() {
|
|
@@ -344,12 +413,31 @@ export class Archiver extends ArchiverDataSourceBase implements L2BlockSink, Tra
|
|
|
344
413
|
*/
|
|
345
414
|
@trackSpan('Archiver.sync')
|
|
346
415
|
private async sync() {
|
|
416
|
+
// Capture the tips before any mutation so the aggregate event can report what moved this pass.
|
|
417
|
+
const fromTips = await this.getL2Tips();
|
|
418
|
+
|
|
419
|
+
// Accumulate the blocks added across the pass's sub-steps (queued proposals + L1 checkpoint payloads).
|
|
420
|
+
const blocksAdded: L2Block[] = [];
|
|
347
421
|
// Process any queued blocks first, before doing L1 sync
|
|
348
|
-
await this.processInboundQueue();
|
|
422
|
+
blocksAdded.push(...(await this.processInboundQueue()));
|
|
349
423
|
// Now perform L1 sync
|
|
350
|
-
await this.syncFromL1();
|
|
351
|
-
// Prune proposed blocks with no corresponding proposed checkpoint
|
|
424
|
+
blocksAdded.push(...(await this.syncFromL1()));
|
|
425
|
+
// Prune proposed blocks with no corresponding proposed checkpoint after the appropriate materialization deadline.
|
|
352
426
|
await this.pruneOrphanProposedBlocks();
|
|
427
|
+
|
|
428
|
+
// Emit a single aggregate update event after all pass work has committed and the tips cache has refreshed,
|
|
429
|
+
// so `toTips` and the source state observed by listeners are consistent with the event payload. The pass
|
|
430
|
+
// mutated state if the tips moved (added blocks, a prune, or a thin tier movement) or blocks were added; a
|
|
431
|
+
// fully-synced no-op pass emits nothing.
|
|
432
|
+
const toTips = await this.getL2Tips();
|
|
433
|
+
if (!l2TipsEqual(fromTips, toTips) || blocksAdded.length > 0) {
|
|
434
|
+
this.events.emit(L2BlockSourceEvents.L2BlockSourceUpdated, {
|
|
435
|
+
type: L2BlockSourceEvents.L2BlockSourceUpdated,
|
|
436
|
+
fromTips,
|
|
437
|
+
toTips,
|
|
438
|
+
blocksAdded,
|
|
439
|
+
});
|
|
440
|
+
}
|
|
353
441
|
}
|
|
354
442
|
|
|
355
443
|
/**
|
|
@@ -357,38 +445,38 @@ export class Archiver extends ArchiverDataSourceBase implements L2BlockSink, Tra
|
|
|
357
445
|
*
|
|
358
446
|
* Under pipelining, a proposer publishes the blocks for a checkpoint (block-only proposals) before
|
|
359
447
|
* assembling and publishing the enclosing proposed checkpoint at the end of the build slot. A node
|
|
360
|
-
* that received those blocks but never the proposed checkpoint is left with an orphan tip it must
|
|
361
|
-
*
|
|
362
|
-
*
|
|
363
|
-
*
|
|
448
|
+
* that received those blocks but never the proposed checkpoint is left with an orphan tip it must not build on.
|
|
449
|
+
* If no checkpoint proposal was received for the orphan slot, we prune after the receive deadline plus local
|
|
450
|
+
* tolerance. If a checkpoint proposal was received but has not materialized into proposed archiver state,
|
|
451
|
+
* we prune after the consensus materialization deadline.
|
|
364
452
|
*
|
|
365
453
|
* The uncheckpointed suffix is scanned in order. Blocks covered by proposed checkpoints are left in
|
|
366
454
|
* place; the first block not covered by a proposed checkpoint starts the orphan suffix to prune.
|
|
367
455
|
*/
|
|
368
456
|
private async pruneOrphanProposedBlocks(): Promise<void> {
|
|
457
|
+
if (this.config.skipOrphanProposedBlockPruning) {
|
|
458
|
+
return;
|
|
459
|
+
}
|
|
369
460
|
const tips = await this.getL2Tips();
|
|
370
461
|
const now = BigInt(this.dateProvider.nowInSeconds());
|
|
371
|
-
const pipeliningOffset = this.epochCache.pipeliningOffset();
|
|
372
462
|
|
|
373
|
-
//
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
return;
|
|
377
|
-
}
|
|
463
|
+
// Frontier block covered by a proposed (or, falling back, confirmed) checkpoint. Blocks beyond it
|
|
464
|
+
// have no enclosing checkpoint proposal and are the orphan-pruning candidates.
|
|
465
|
+
const proposedCheckpointBlockNumber = await this.stores.blocks.getProposedCheckpointL2BlockNumber();
|
|
378
466
|
|
|
379
467
|
// The proposed tip is a proposed-checkpointed block, so there are no orphan proposed blocks to prune
|
|
380
|
-
if (
|
|
381
|
-
this.log.trace(
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
);
|
|
468
|
+
if (proposedCheckpointBlockNumber === tips.proposed.number) {
|
|
469
|
+
this.log.trace(`No orphan proposed blocks to prune: proposed tip ${tips.proposed.number} is checkpointed`, {
|
|
470
|
+
proposed: tips.proposed,
|
|
471
|
+
proposedCheckpointBlockNumber,
|
|
472
|
+
});
|
|
385
473
|
return;
|
|
386
474
|
}
|
|
387
475
|
|
|
388
476
|
// Load the blocks that are candidates for pruning (ie blocks without a proposed checkpoint covering them)
|
|
389
477
|
const blocksWithoutProposedCheckpoint = await this.stores.blocks.getBlocksData({
|
|
390
|
-
from: BlockNumber(
|
|
391
|
-
limit: tips.proposed.number -
|
|
478
|
+
from: BlockNumber(proposedCheckpointBlockNumber + 1),
|
|
479
|
+
limit: tips.proposed.number - proposedCheckpointBlockNumber,
|
|
392
480
|
});
|
|
393
481
|
|
|
394
482
|
// Iterate through them in order, the first one with a slot that should have received a proposed checkpoint
|
|
@@ -403,15 +491,21 @@ export class Archiver extends ArchiverDataSourceBase implements L2BlockSink, Tra
|
|
|
403
491
|
}
|
|
404
492
|
lastSlotChecked = blockSlot;
|
|
405
493
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
const
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
494
|
+
const hasCheckpointProposal = await this.checkpointProposalPresence.hasCheckpointProposalForSlot(blockSlot);
|
|
495
|
+
const deadlineType = hasCheckpointProposal ? 'checkpoint-proposal-synced' : 'checkpoint-proposal-received';
|
|
496
|
+
const selectedDeadline = BigInt(
|
|
497
|
+
hasCheckpointProposal
|
|
498
|
+
? this.timetable.getCheckpointProposalSyncedDeadline(blockSlot)
|
|
499
|
+
: Math.ceil(
|
|
500
|
+
this.timetable.getCheckpointProposalReceiveDeadline(blockSlot) +
|
|
501
|
+
this.config.orphanPruneNoProposalTolerance,
|
|
502
|
+
),
|
|
503
|
+
);
|
|
412
504
|
|
|
413
|
-
// If it's not checkpointed
|
|
414
|
-
|
|
505
|
+
// If it's still not checkpointed once strictly past the selected deadline, prune it along with all blocks after
|
|
506
|
+
// it. A proposal may still legitimately arrive or materialize at exactly its deadline, so the tip is only
|
|
507
|
+
// orphaned once that instant has fully elapsed.
|
|
508
|
+
if (now > selectedDeadline) {
|
|
415
509
|
const pruneAfterBlockNumber = BlockNumber(blockNumber - 1);
|
|
416
510
|
this.log.warn(
|
|
417
511
|
`Pruning orphan blocks after block ${pruneAfterBlockNumber}: block at slot ${blockSlot} belongs to ` +
|
|
@@ -421,15 +515,16 @@ export class Archiver extends ArchiverDataSourceBase implements L2BlockSink, Tra
|
|
|
421
515
|
blockCheckpointNumber: blockData.checkpointNumber,
|
|
422
516
|
blockNumber,
|
|
423
517
|
blockSlot,
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
518
|
+
hasCheckpointProposal,
|
|
519
|
+
deadlineType,
|
|
520
|
+
selectedDeadline,
|
|
427
521
|
now,
|
|
428
522
|
},
|
|
429
523
|
);
|
|
430
524
|
|
|
431
525
|
const prunedBlocks = await this.updater.removeBlocksWithoutProposedCheckpointAfter(pruneAfterBlockNumber);
|
|
432
526
|
if (prunedBlocks.length > 0) {
|
|
527
|
+
this.instrumentation.recordPrune('orphan');
|
|
433
528
|
this.events.emit(L2BlockSourceEvents.L2PruneUncheckpointed, {
|
|
434
529
|
type: L2BlockSourceEvents.L2PruneUncheckpointed,
|
|
435
530
|
slotNumber: blockSlot,
|
|
@@ -440,14 +535,14 @@ export class Archiver extends ArchiverDataSourceBase implements L2BlockSink, Tra
|
|
|
440
535
|
}
|
|
441
536
|
}
|
|
442
537
|
|
|
443
|
-
this.log.trace('No orphan proposed blocks to prune: all uncheckpointed blocks are still within
|
|
538
|
+
this.log.trace('No orphan proposed blocks to prune: all uncheckpointed blocks are still within deadline', {
|
|
444
539
|
blocksWithoutProposedCheckpoint: blocksWithoutProposedCheckpoint.map(b => b.header.toInspect()),
|
|
445
540
|
});
|
|
446
541
|
}
|
|
447
542
|
|
|
448
|
-
private async syncFromL1() {
|
|
543
|
+
private async syncFromL1(): Promise<L2Block[]> {
|
|
449
544
|
// Delegate to the L1 synchronizer
|
|
450
|
-
await this.synchronizer.syncFromL1(this.initialSyncComplete);
|
|
545
|
+
const blocksAdded = await this.synchronizer.syncFromL1(this.initialSyncComplete);
|
|
451
546
|
|
|
452
547
|
// Check if we've completed initial sync
|
|
453
548
|
const currentL1BlockNumber = this.synchronizer.getL1BlockNumber();
|
|
@@ -464,6 +559,7 @@ export class Archiver extends ArchiverDataSourceBase implements L2BlockSink, Tra
|
|
|
464
559
|
this.initialSyncPromise.resolve();
|
|
465
560
|
}
|
|
466
561
|
}
|
|
562
|
+
return blocksAdded;
|
|
467
563
|
}
|
|
468
564
|
|
|
469
565
|
/** Resumes the archiver after a stop. */
|
|
@@ -599,6 +695,15 @@ export class Archiver extends ArchiverDataSourceBase implements L2BlockSink, Tra
|
|
|
599
695
|
return this.updater.removeCheckpointsAfter(checkpointNumber);
|
|
600
696
|
}
|
|
601
697
|
|
|
698
|
+
/**
|
|
699
|
+
* Removes all uncheckpointed blocks strictly after `blockNumber`, along with the proposed checkpoints
|
|
700
|
+
* that referenced them. Used by the AutomineSequencer to undo a local insert whose propose tx failed
|
|
701
|
+
* to land on L1 (no reorg needed — nothing reached L1). Refuses to touch checkpointed blocks.
|
|
702
|
+
*/
|
|
703
|
+
public removeUncheckpointedBlocksAfter(blockNumber: BlockNumber): Promise<L2Block[]> {
|
|
704
|
+
return this.updater.removeUncheckpointedBlocksAfter(blockNumber);
|
|
705
|
+
}
|
|
706
|
+
|
|
602
707
|
/** Used by TXE to add checkpoints directly without syncing from L1. */
|
|
603
708
|
public async addCheckpoints(
|
|
604
709
|
checkpoints: PublishedCheckpoint[],
|
package/src/config.ts
CHANGED
|
@@ -8,13 +8,9 @@ import {
|
|
|
8
8
|
numberConfigHelper,
|
|
9
9
|
optionalNumberConfigHelper,
|
|
10
10
|
} from '@aztec/foundation/config';
|
|
11
|
-
import {
|
|
12
|
-
type ChainConfig,
|
|
13
|
-
type PipelineConfig,
|
|
14
|
-
chainConfigMappings,
|
|
15
|
-
pipelineConfigMappings,
|
|
16
|
-
} from '@aztec/stdlib/config';
|
|
11
|
+
import { type ChainConfig, type SequencerConfig, chainConfigMappings } from '@aztec/stdlib/config';
|
|
17
12
|
import type { ArchiverSpecificConfig } from '@aztec/stdlib/interfaces/server';
|
|
13
|
+
import { DEFAULT_ORPHAN_PRUNE_NO_PROPOSAL_TOLERANCE } from '@aztec/stdlib/timetable';
|
|
18
14
|
|
|
19
15
|
/**
|
|
20
16
|
* The archiver configuration.
|
|
@@ -26,13 +22,12 @@ import type { ArchiverSpecificConfig } from '@aztec/stdlib/interfaces/server';
|
|
|
26
22
|
export type ArchiverConfig = ArchiverSpecificConfig &
|
|
27
23
|
L1ReaderConfig &
|
|
28
24
|
L1ContractsConfig &
|
|
29
|
-
PipelineConfig & // required to pass through to epoch cache
|
|
30
25
|
BlobClientConfig &
|
|
31
|
-
ChainConfig
|
|
26
|
+
ChainConfig &
|
|
27
|
+
Pick<SequencerConfig, 'blockDurationMs' | 'checkpointProposalSyncGraceSeconds'>;
|
|
32
28
|
|
|
33
29
|
export const archiverConfigMappings: ConfigMappingsType<ArchiverConfig> = {
|
|
34
30
|
...blobClientConfigMapping,
|
|
35
|
-
...pipelineConfigMappings,
|
|
36
31
|
archiverPollingIntervalMS: {
|
|
37
32
|
env: 'ARCHIVER_POLLING_INTERVAL_MS',
|
|
38
33
|
description: 'The polling interval in ms for retrieving new L2 blocks and encrypted logs.',
|
|
@@ -48,6 +43,18 @@ export const archiverConfigMappings: ConfigMappingsType<ArchiverConfig> = {
|
|
|
48
43
|
...optionalNumberConfigHelper(),
|
|
49
44
|
description: 'The maximum possible size of the archiver DB in KB. Overwrites the general dataStoreMapSizeKb.',
|
|
50
45
|
},
|
|
46
|
+
blockDurationMs: {
|
|
47
|
+
env: 'SEQ_BLOCK_DURATION_MS',
|
|
48
|
+
description:
|
|
49
|
+
'Duration per block in milliseconds when building multiple blocks per slot. Used to derive orphan proposed block pruning timing.',
|
|
50
|
+
...optionalNumberConfigHelper(),
|
|
51
|
+
},
|
|
52
|
+
checkpointProposalSyncGraceSeconds: {
|
|
53
|
+
env: 'CHECKPOINT_PROPOSAL_SYNC_GRACE_SECONDS',
|
|
54
|
+
description:
|
|
55
|
+
'Consensus grace in seconds for a received checkpoint proposal to materialize into local proposed state.',
|
|
56
|
+
...optionalNumberConfigHelper(),
|
|
57
|
+
},
|
|
51
58
|
skipValidateCheckpointAttestations: {
|
|
52
59
|
description: 'Skip validating checkpoint attestations (for testing purposes only)',
|
|
53
60
|
...booleanConfigHelper(false),
|
|
@@ -73,13 +80,23 @@ export const archiverConfigMappings: ConfigMappingsType<ArchiverConfig> = {
|
|
|
73
80
|
'Set to true to bypass the check when the connected RPC node is known to prune old logs.',
|
|
74
81
|
...booleanConfigHelper(false),
|
|
75
82
|
},
|
|
76
|
-
|
|
77
|
-
env: '
|
|
83
|
+
orphanPruneNoProposalTolerance: {
|
|
84
|
+
env: 'ARCHIVER_ORPHAN_PRUNE_NO_PROPOSAL_TOLERANCE',
|
|
85
|
+
description: 'Local tolerance in seconds before pruning an orphan block when no checkpoint proposal was received.',
|
|
86
|
+
...numberConfigHelper(DEFAULT_ORPHAN_PRUNE_NO_PROPOSAL_TOLERANCE),
|
|
87
|
+
},
|
|
88
|
+
skipOrphanProposedBlockPruning: {
|
|
89
|
+
env: 'ARCHIVER_SKIP_ORPHAN_PROPOSED_BLOCK_PRUNING',
|
|
90
|
+
description: 'Skip pruning orphan proposed blocks that have no matching proposed checkpoint.',
|
|
91
|
+
...booleanConfigHelper(false),
|
|
92
|
+
},
|
|
93
|
+
testPreloadStandardContracts: {
|
|
94
|
+
env: 'TEST_PRELOAD_STANDARD_CONTRACTS',
|
|
78
95
|
description:
|
|
79
|
-
'
|
|
80
|
-
'
|
|
81
|
-
'
|
|
82
|
-
...
|
|
96
|
+
'Preload the standard contracts (AuthRegistry, PublicChecks, HandshakeRegistry) into the contract store at ' +
|
|
97
|
+
'block 0. For test environments only, and only safe when genesis seeds the matching registration/deployment ' +
|
|
98
|
+
'nullifiers; otherwise a later on-chain publish would collide with the block-0 preload.',
|
|
99
|
+
...booleanConfigHelper(false),
|
|
83
100
|
},
|
|
84
101
|
...chainConfigMappings,
|
|
85
102
|
...l1ReaderConfigMappings,
|
|
@@ -110,6 +127,7 @@ export function mapArchiverConfig(config: Partial<ArchiverConfig>) {
|
|
|
110
127
|
maxAllowedEthClientDriftSeconds: config.maxAllowedEthClientDriftSeconds,
|
|
111
128
|
ethereumAllowNoDebugHosts: config.ethereumAllowNoDebugHosts,
|
|
112
129
|
skipHistoricalLogsCheck: config.archiverSkipHistoricalLogsCheck,
|
|
113
|
-
|
|
130
|
+
orphanPruneNoProposalTolerance: config.orphanPruneNoProposalTolerance,
|
|
131
|
+
skipOrphanProposedBlockPruning: config.skipOrphanProposedBlockPruning,
|
|
114
132
|
};
|
|
115
133
|
}
|