@aztec/archiver 0.0.0-test.0
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/README.md +16 -0
- package/dest/archiver/archiver.d.ts +197 -0
- package/dest/archiver/archiver.d.ts.map +1 -0
- package/dest/archiver/archiver.js +900 -0
- package/dest/archiver/archiver_store.d.ts +220 -0
- package/dest/archiver/archiver_store.d.ts.map +1 -0
- package/dest/archiver/archiver_store.js +4 -0
- package/dest/archiver/archiver_store_test_suite.d.ts +8 -0
- package/dest/archiver/archiver_store_test_suite.d.ts.map +1 -0
- package/dest/archiver/archiver_store_test_suite.js +794 -0
- package/dest/archiver/config.d.ts +37 -0
- package/dest/archiver/config.d.ts.map +1 -0
- package/dest/archiver/config.js +46 -0
- package/dest/archiver/data_retrieval.d.ts +74 -0
- package/dest/archiver/data_retrieval.d.ts.map +1 -0
- package/dest/archiver/data_retrieval.js +283 -0
- package/dest/archiver/errors.d.ts +4 -0
- package/dest/archiver/errors.d.ts.map +1 -0
- package/dest/archiver/errors.js +5 -0
- package/dest/archiver/index.d.ts +8 -0
- package/dest/archiver/index.d.ts.map +1 -0
- package/dest/archiver/index.js +5 -0
- package/dest/archiver/instrumentation.d.ts +29 -0
- package/dest/archiver/instrumentation.d.ts.map +1 -0
- package/dest/archiver/instrumentation.js +99 -0
- package/dest/archiver/kv_archiver_store/block_store.d.ts +87 -0
- package/dest/archiver/kv_archiver_store/block_store.d.ts.map +1 -0
- package/dest/archiver/kv_archiver_store/block_store.js +217 -0
- package/dest/archiver/kv_archiver_store/contract_class_store.d.ts +18 -0
- package/dest/archiver/kv_archiver_store/contract_class_store.d.ts.map +1 -0
- package/dest/archiver/kv_archiver_store/contract_class_store.js +126 -0
- package/dest/archiver/kv_archiver_store/contract_instance_store.d.ts +21 -0
- package/dest/archiver/kv_archiver_store/contract_instance_store.d.ts.map +1 -0
- package/dest/archiver/kv_archiver_store/contract_instance_store.js +63 -0
- package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts +153 -0
- package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts.map +1 -0
- package/dest/archiver/kv_archiver_store/kv_archiver_store.js +254 -0
- package/dest/archiver/kv_archiver_store/log_store.d.ts +49 -0
- package/dest/archiver/kv_archiver_store/log_store.d.ts.map +1 -0
- package/dest/archiver/kv_archiver_store/log_store.js +364 -0
- package/dest/archiver/kv_archiver_store/message_store.d.ts +33 -0
- package/dest/archiver/kv_archiver_store/message_store.d.ts.map +1 -0
- package/dest/archiver/kv_archiver_store/message_store.js +85 -0
- package/dest/archiver/kv_archiver_store/nullifier_store.d.ts +12 -0
- package/dest/archiver/kv_archiver_store/nullifier_store.d.ts.map +1 -0
- package/dest/archiver/kv_archiver_store/nullifier_store.js +73 -0
- package/dest/archiver/memory_archiver_store/l1_to_l2_message_store.d.ts +23 -0
- package/dest/archiver/memory_archiver_store/l1_to_l2_message_store.d.ts.map +1 -0
- package/dest/archiver/memory_archiver_store/l1_to_l2_message_store.js +49 -0
- package/dest/archiver/memory_archiver_store/memory_archiver_store.d.ts +175 -0
- package/dest/archiver/memory_archiver_store/memory_archiver_store.d.ts.map +1 -0
- package/dest/archiver/memory_archiver_store/memory_archiver_store.js +636 -0
- package/dest/archiver/structs/data_retrieval.d.ts +27 -0
- package/dest/archiver/structs/data_retrieval.d.ts.map +1 -0
- package/dest/archiver/structs/data_retrieval.js +5 -0
- package/dest/archiver/structs/published.d.ts +11 -0
- package/dest/archiver/structs/published.d.ts.map +1 -0
- package/dest/archiver/structs/published.js +1 -0
- package/dest/factory.d.ts +24 -0
- package/dest/factory.d.ts.map +1 -0
- package/dest/factory.js +85 -0
- package/dest/index.d.ts +5 -0
- package/dest/index.d.ts.map +1 -0
- package/dest/index.js +4 -0
- package/dest/rpc/index.d.ts +10 -0
- package/dest/rpc/index.d.ts.map +1 -0
- package/dest/rpc/index.js +18 -0
- package/dest/test/index.d.ts +4 -0
- package/dest/test/index.d.ts.map +1 -0
- package/dest/test/index.js +3 -0
- package/dest/test/mock_archiver.d.ts +23 -0
- package/dest/test/mock_archiver.d.ts.map +1 -0
- package/dest/test/mock_archiver.js +40 -0
- package/dest/test/mock_l1_to_l2_message_source.d.ts +16 -0
- package/dest/test/mock_l1_to_l2_message_source.d.ts.map +1 -0
- package/dest/test/mock_l1_to_l2_message_source.js +25 -0
- package/dest/test/mock_l2_block_source.d.ts +79 -0
- package/dest/test/mock_l2_block_source.d.ts.map +1 -0
- package/dest/test/mock_l2_block_source.js +163 -0
- package/package.json +110 -0
- package/src/archiver/archiver.ts +1181 -0
- package/src/archiver/archiver_store.ts +263 -0
- package/src/archiver/archiver_store_test_suite.ts +810 -0
- package/src/archiver/config.ts +92 -0
- package/src/archiver/data_retrieval.ts +422 -0
- package/src/archiver/errors.ts +5 -0
- package/src/archiver/index.ts +7 -0
- package/src/archiver/instrumentation.ts +132 -0
- package/src/archiver/kv_archiver_store/block_store.ts +283 -0
- package/src/archiver/kv_archiver_store/contract_class_store.ts +186 -0
- package/src/archiver/kv_archiver_store/contract_instance_store.ts +107 -0
- package/src/archiver/kv_archiver_store/kv_archiver_store.ts +358 -0
- package/src/archiver/kv_archiver_store/log_store.ts +444 -0
- package/src/archiver/kv_archiver_store/message_store.ts +102 -0
- package/src/archiver/kv_archiver_store/nullifier_store.ts +97 -0
- package/src/archiver/memory_archiver_store/l1_to_l2_message_store.ts +61 -0
- package/src/archiver/memory_archiver_store/memory_archiver_store.ts +801 -0
- package/src/archiver/structs/data_retrieval.ts +27 -0
- package/src/archiver/structs/published.ts +11 -0
- package/src/factory.ts +107 -0
- package/src/index.ts +5 -0
- package/src/rpc/index.ts +20 -0
- package/src/test/index.ts +3 -0
- package/src/test/mock_archiver.ts +57 -0
- package/src/test/mock_l1_to_l2_message_source.ts +31 -0
- package/src/test/mock_l2_block_source.ts +204 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Data retrieved from logs
|
|
3
|
+
*/
|
|
4
|
+
export type DataRetrieval<T> = {
|
|
5
|
+
/**
|
|
6
|
+
* Blocknumber of the last L1 block from which we obtained data.
|
|
7
|
+
*/
|
|
8
|
+
lastProcessedL1BlockNumber: bigint;
|
|
9
|
+
/**
|
|
10
|
+
* The data returned.
|
|
11
|
+
*/
|
|
12
|
+
retrievedData: T[];
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Data retrieved from logs
|
|
17
|
+
*/
|
|
18
|
+
export type SingletonDataRetrieval<T> = {
|
|
19
|
+
/**
|
|
20
|
+
* Blocknumber of the last L1 block from which we obtained data.
|
|
21
|
+
*/
|
|
22
|
+
lastProcessedL1BlockNumber: bigint;
|
|
23
|
+
/**
|
|
24
|
+
* The data returned.
|
|
25
|
+
*/
|
|
26
|
+
retrievedData: T;
|
|
27
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Extends a type with L1 published info (block number, hash, and timestamp) */
|
|
2
|
+
export type L1Published<T> = {
|
|
3
|
+
data: T;
|
|
4
|
+
l1: L1PublishedData;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export type L1PublishedData = {
|
|
8
|
+
blockNumber: bigint;
|
|
9
|
+
timestamp: bigint;
|
|
10
|
+
blockHash: string;
|
|
11
|
+
};
|
package/src/factory.ts
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import type { BlobSinkClientInterface } from '@aztec/blob-sink/client';
|
|
2
|
+
import { createLogger } from '@aztec/foundation/log';
|
|
3
|
+
import type { DataStoreConfig } from '@aztec/kv-store/config';
|
|
4
|
+
import { createStore } from '@aztec/kv-store/lmdb-v2';
|
|
5
|
+
import { TokenContractArtifact } from '@aztec/noir-contracts.js/Token';
|
|
6
|
+
import { TokenBridgeContractArtifact } from '@aztec/noir-contracts.js/TokenBridge';
|
|
7
|
+
import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree';
|
|
8
|
+
import { protocolContractNames, protocolContractTreeRoot } from '@aztec/protocol-contracts';
|
|
9
|
+
import { BundledProtocolContractsProvider } from '@aztec/protocol-contracts/providers/bundle';
|
|
10
|
+
import { FunctionType, decodeFunctionSignature } from '@aztec/stdlib/abi';
|
|
11
|
+
import type { L2BlockSourceEventEmitter } from '@aztec/stdlib/block';
|
|
12
|
+
import {
|
|
13
|
+
type ContractClassPublic,
|
|
14
|
+
computePublicBytecodeCommitment,
|
|
15
|
+
getContractClassFromArtifact,
|
|
16
|
+
} from '@aztec/stdlib/contract';
|
|
17
|
+
import type { ArchiverApi, Service } from '@aztec/stdlib/interfaces/server';
|
|
18
|
+
import { getComponentsVersionsFromConfig } from '@aztec/stdlib/versioning';
|
|
19
|
+
import { type TelemetryClient, getTelemetryClient } from '@aztec/telemetry-client';
|
|
20
|
+
|
|
21
|
+
import { Archiver } from './archiver/archiver.js';
|
|
22
|
+
import type { ArchiverConfig } from './archiver/config.js';
|
|
23
|
+
import { KVArchiverDataStore } from './archiver/index.js';
|
|
24
|
+
import { createArchiverClient } from './rpc/index.js';
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Creates a local archiver.
|
|
28
|
+
* @param config - The archiver configuration.
|
|
29
|
+
* @param blobSinkClient - The blob sink client.
|
|
30
|
+
* @param opts - The options.
|
|
31
|
+
* @param telemetry - The telemetry client.
|
|
32
|
+
* @returns The local archiver.
|
|
33
|
+
*/
|
|
34
|
+
export async function createArchiver(
|
|
35
|
+
config: ArchiverConfig & DataStoreConfig,
|
|
36
|
+
blobSinkClient: BlobSinkClientInterface,
|
|
37
|
+
opts: { blockUntilSync: boolean } = { blockUntilSync: true },
|
|
38
|
+
telemetry: TelemetryClient = getTelemetryClient(),
|
|
39
|
+
): Promise<ArchiverApi & Service & L2BlockSourceEventEmitter> {
|
|
40
|
+
const store = await createStore(
|
|
41
|
+
'archiver',
|
|
42
|
+
KVArchiverDataStore.SCHEMA_VERSION,
|
|
43
|
+
config,
|
|
44
|
+
createLogger('archiver:lmdb'),
|
|
45
|
+
);
|
|
46
|
+
const archiverStore = new KVArchiverDataStore(store, config.maxLogs);
|
|
47
|
+
await registerProtocolContracts(archiverStore);
|
|
48
|
+
await registerCommonContracts(archiverStore);
|
|
49
|
+
return Archiver.createAndSync(config, archiverStore, { telemetry, blobSinkClient }, opts.blockUntilSync);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Creates a remote archiver client.
|
|
54
|
+
* @param config - The archiver configuration.
|
|
55
|
+
* @returns The remote archiver client.
|
|
56
|
+
*/
|
|
57
|
+
export function createRemoteArchiver(config: ArchiverConfig): ArchiverApi {
|
|
58
|
+
if (!config.archiverUrl) {
|
|
59
|
+
throw new Error('Archiver URL is required');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return createArchiverClient(
|
|
63
|
+
config.archiverUrl,
|
|
64
|
+
getComponentsVersionsFromConfig(config, protocolContractTreeRoot, getVKTreeRoot()),
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async function registerProtocolContracts(store: KVArchiverDataStore) {
|
|
69
|
+
const blockNumber = 0;
|
|
70
|
+
for (const name of protocolContractNames) {
|
|
71
|
+
const provider = new BundledProtocolContractsProvider();
|
|
72
|
+
const contract = await provider.getProtocolContractArtifact(name);
|
|
73
|
+
const contractClassPublic: ContractClassPublic = {
|
|
74
|
+
...contract.contractClass,
|
|
75
|
+
privateFunctions: [],
|
|
76
|
+
unconstrainedFunctions: [],
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const publicFunctionSignatures = contract.artifact.functions
|
|
80
|
+
.filter(fn => fn.functionType === FunctionType.PUBLIC)
|
|
81
|
+
.map(fn => decodeFunctionSignature(fn.name, fn.parameters));
|
|
82
|
+
|
|
83
|
+
await store.registerContractFunctionSignatures(contract.address, publicFunctionSignatures);
|
|
84
|
+
const bytecodeCommitment = await computePublicBytecodeCommitment(contractClassPublic.packedBytecode);
|
|
85
|
+
await store.addContractClasses([contractClassPublic], [bytecodeCommitment], blockNumber);
|
|
86
|
+
await store.addContractInstances([contract.instance], blockNumber);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// TODO(#10007): Remove this method. We are explicitly registering these contracts
|
|
91
|
+
// here to ensure they are available to all nodes and all prover nodes, since the PXE
|
|
92
|
+
// was tweaked to automatically push contract classes to the node it is registered,
|
|
93
|
+
// but other nodes in the network may require the contract classes to be registered as well.
|
|
94
|
+
// TODO(#10007): Remove the dependency on noir-contracts.js from this package once we remove this.
|
|
95
|
+
async function registerCommonContracts(store: KVArchiverDataStore) {
|
|
96
|
+
const blockNumber = 0;
|
|
97
|
+
const artifacts = [TokenBridgeContractArtifact, TokenContractArtifact];
|
|
98
|
+
const classes = await Promise.all(
|
|
99
|
+
artifacts.map(async artifact => ({
|
|
100
|
+
...(await getContractClassFromArtifact(artifact)),
|
|
101
|
+
privateFunctions: [],
|
|
102
|
+
unconstrainedFunctions: [],
|
|
103
|
+
})),
|
|
104
|
+
);
|
|
105
|
+
const bytecodeCommitments = await Promise.all(classes.map(x => computePublicBytecodeCommitment(x.packedBytecode)));
|
|
106
|
+
await store.addContractClasses(classes, bytecodeCommitments, blockNumber);
|
|
107
|
+
}
|
package/src/index.ts
ADDED
package/src/rpc/index.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { createSafeJsonRpcClient } from '@aztec/foundation/json-rpc/client';
|
|
2
|
+
import { type ArchiverApi, ArchiverApiSchema } from '@aztec/stdlib/interfaces/server';
|
|
3
|
+
import { type ComponentsVersions, getVersioningResponseHandler } from '@aztec/stdlib/versioning';
|
|
4
|
+
import { createTracedJsonRpcServer, makeTracedFetch } from '@aztec/telemetry-client';
|
|
5
|
+
|
|
6
|
+
export function createArchiverClient(
|
|
7
|
+
url: string,
|
|
8
|
+
versions: Partial<ComponentsVersions>,
|
|
9
|
+
fetch = makeTracedFetch([1, 2, 3], true),
|
|
10
|
+
): ArchiverApi {
|
|
11
|
+
return createSafeJsonRpcClient<ArchiverApi>(url, ArchiverApiSchema, {
|
|
12
|
+
namespaceMethods: 'archiver',
|
|
13
|
+
fetch,
|
|
14
|
+
onResponse: getVersioningResponseHandler(versions),
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function createArchiverRpcServer(handler: ArchiverApi) {
|
|
19
|
+
return createTracedJsonRpcServer(handler, ArchiverApiSchema);
|
|
20
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { Fr } from '@aztec/foundation/fields';
|
|
2
|
+
import type { L2Block, L2BlockSource } from '@aztec/stdlib/block';
|
|
3
|
+
import type { L1ToL2MessageSource } from '@aztec/stdlib/messaging';
|
|
4
|
+
|
|
5
|
+
import { MockL1ToL2MessageSource } from './mock_l1_to_l2_message_source.js';
|
|
6
|
+
import { MockL2BlockSource } from './mock_l2_block_source.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* A mocked implementation of the archiver that implements L2BlockSource and L1ToL2MessageSource.
|
|
10
|
+
*/
|
|
11
|
+
export class MockArchiver extends MockL2BlockSource implements L2BlockSource, L1ToL2MessageSource {
|
|
12
|
+
private messageSource = new MockL1ToL2MessageSource(0);
|
|
13
|
+
|
|
14
|
+
public setL1ToL2Messages(blockNumber: number, msgs: Fr[]) {
|
|
15
|
+
this.messageSource.setL1ToL2Messages(blockNumber, msgs);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
getL1ToL2Messages(blockNumber: bigint): Promise<Fr[]> {
|
|
19
|
+
return this.messageSource.getL1ToL2Messages(blockNumber);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
getL1ToL2MessageIndex(_l1ToL2Message: Fr): Promise<bigint | undefined> {
|
|
23
|
+
return this.messageSource.getL1ToL2MessageIndex(_l1ToL2Message);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* A mocked implementation of the archiver with a set of precomputed blocks and messages.
|
|
29
|
+
*/
|
|
30
|
+
export class MockPrefilledArchiver extends MockArchiver {
|
|
31
|
+
private precomputed: L2Block[];
|
|
32
|
+
|
|
33
|
+
constructor(precomputed: L2Block[], messages: Fr[][]) {
|
|
34
|
+
super();
|
|
35
|
+
this.precomputed = precomputed.slice();
|
|
36
|
+
messages.forEach((msgs, i) => this.setL1ToL2Messages(i + 1, msgs));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
public setPrefilledBlocks(blocks: L2Block[], messages: Fr[][]) {
|
|
40
|
+
for (const block of blocks) {
|
|
41
|
+
this.precomputed[block.number - 1] = block;
|
|
42
|
+
}
|
|
43
|
+
messages.forEach((msgs, i) => this.setL1ToL2Messages(blocks[i].number, msgs));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
public override createBlocks(numBlocks: number) {
|
|
47
|
+
if (this.l2Blocks.length + numBlocks > this.precomputed.length) {
|
|
48
|
+
throw new Error(
|
|
49
|
+
`Not enough precomputed blocks to create ${numBlocks} more blocks (already at ${this.l2Blocks.length})`,
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const fromBlock = this.l2Blocks.length;
|
|
54
|
+
this.addBlocks(this.precomputed.slice(fromBlock, fromBlock + numBlocks));
|
|
55
|
+
return Promise.resolve();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { Fr } from '@aztec/foundation/fields';
|
|
2
|
+
import type { L1ToL2MessageSource } from '@aztec/stdlib/messaging';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* A mocked implementation of L1ToL2MessageSource to be used in tests.
|
|
6
|
+
*/
|
|
7
|
+
export class MockL1ToL2MessageSource implements L1ToL2MessageSource {
|
|
8
|
+
private messagesPerBlock = new Map<number, Fr[]>();
|
|
9
|
+
|
|
10
|
+
constructor(private blockNumber: number) {}
|
|
11
|
+
|
|
12
|
+
public setL1ToL2Messages(blockNumber: number, msgs: Fr[]) {
|
|
13
|
+
this.messagesPerBlock.set(blockNumber, msgs);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
public setBlockNumber(blockNumber: number) {
|
|
17
|
+
this.blockNumber = blockNumber;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
getL1ToL2Messages(blockNumber: bigint): Promise<Fr[]> {
|
|
21
|
+
return Promise.resolve(this.messagesPerBlock.get(Number(blockNumber)) ?? []);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
getL1ToL2MessageIndex(_l1ToL2Message: Fr): Promise<bigint | undefined> {
|
|
25
|
+
throw new Error('Method not implemented.');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
getBlockNumber(): Promise<number> {
|
|
29
|
+
return Promise.resolve(this.blockNumber);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import { DefaultL1ContractsConfig } from '@aztec/ethereum';
|
|
2
|
+
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
3
|
+
import { createLogger } from '@aztec/foundation/log';
|
|
4
|
+
import { L2Block, L2BlockHash, type L2BlockSource, type L2Tips } from '@aztec/stdlib/block';
|
|
5
|
+
import { type L1RollupConstants, getSlotRangeForEpoch } from '@aztec/stdlib/epoch-helpers';
|
|
6
|
+
import { type BlockHeader, TxHash, TxReceipt, TxStatus } from '@aztec/stdlib/tx';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* A mocked implementation of L2BlockSource to be used in tests.
|
|
10
|
+
*/
|
|
11
|
+
export class MockL2BlockSource implements L2BlockSource {
|
|
12
|
+
protected l2Blocks: L2Block[] = [];
|
|
13
|
+
|
|
14
|
+
private provenBlockNumber: number = 0;
|
|
15
|
+
|
|
16
|
+
private log = createLogger('archiver:mock_l2_block_source');
|
|
17
|
+
|
|
18
|
+
public async createBlocks(numBlocks: number) {
|
|
19
|
+
for (let i = 0; i < numBlocks; i++) {
|
|
20
|
+
const blockNum = this.l2Blocks.length + 1;
|
|
21
|
+
const block = await L2Block.random(blockNum);
|
|
22
|
+
this.l2Blocks.push(block);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
this.log.verbose(`Created ${numBlocks} blocks in the mock L2 block source`);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
public addBlocks(blocks: L2Block[]) {
|
|
29
|
+
this.l2Blocks.push(...blocks);
|
|
30
|
+
this.log.verbose(`Added ${blocks.length} blocks to the mock L2 block source`);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
public removeBlocks(numBlocks: number) {
|
|
34
|
+
this.l2Blocks = this.l2Blocks.slice(0, -numBlocks);
|
|
35
|
+
this.log.verbose(`Removed ${numBlocks} blocks from the mock L2 block source`);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
public setProvenBlockNumber(provenBlockNumber: number) {
|
|
39
|
+
this.provenBlockNumber = provenBlockNumber;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Method to fetch the rollup contract address at the base-layer.
|
|
44
|
+
* @returns The rollup address.
|
|
45
|
+
*/
|
|
46
|
+
getRollupAddress(): Promise<EthAddress> {
|
|
47
|
+
return Promise.resolve(EthAddress.random());
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Method to fetch the registry contract address at the base-layer.
|
|
52
|
+
* @returns The registry address.
|
|
53
|
+
*/
|
|
54
|
+
getRegistryAddress(): Promise<EthAddress> {
|
|
55
|
+
return Promise.resolve(EthAddress.random());
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Gets the number of the latest L2 block processed by the block source implementation.
|
|
60
|
+
* @returns In this mock instance, returns the number of L2 blocks that we've mocked.
|
|
61
|
+
*/
|
|
62
|
+
public getBlockNumber() {
|
|
63
|
+
return Promise.resolve(this.l2Blocks.length);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
public getProvenBlockNumber(): Promise<number> {
|
|
67
|
+
return Promise.resolve(this.provenBlockNumber);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Gets an l2 block.
|
|
72
|
+
* @param number - The block number to return (inclusive).
|
|
73
|
+
* @returns The requested L2 block.
|
|
74
|
+
*/
|
|
75
|
+
public getBlock(number: number) {
|
|
76
|
+
return Promise.resolve(this.l2Blocks[number - 1]);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Gets up to `limit` amount of L2 blocks starting from `from`.
|
|
81
|
+
* @param from - Number of the first block to return (inclusive).
|
|
82
|
+
* @param limit - The maximum number of blocks to return.
|
|
83
|
+
* @returns The requested mocked L2 blocks.
|
|
84
|
+
*/
|
|
85
|
+
public getBlocks(from: number, limit: number, proven?: boolean) {
|
|
86
|
+
return Promise.resolve(
|
|
87
|
+
this.l2Blocks
|
|
88
|
+
.slice(from - 1, from - 1 + limit)
|
|
89
|
+
.filter(b => !proven || this.provenBlockNumber === undefined || b.number <= this.provenBlockNumber),
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
getBlockHeader(number: number | 'latest'): Promise<BlockHeader | undefined> {
|
|
94
|
+
return Promise.resolve(this.l2Blocks.at(typeof number === 'number' ? number - 1 : -1)?.header);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
getBlocksForEpoch(epochNumber: bigint): Promise<L2Block[]> {
|
|
98
|
+
const epochDuration = DefaultL1ContractsConfig.aztecEpochDuration;
|
|
99
|
+
const [start, end] = getSlotRangeForEpoch(epochNumber, { epochDuration });
|
|
100
|
+
const blocks = this.l2Blocks.filter(b => {
|
|
101
|
+
const slot = b.header.globalVariables.slotNumber.toBigInt();
|
|
102
|
+
return slot >= start && slot <= end;
|
|
103
|
+
});
|
|
104
|
+
return Promise.resolve(blocks);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Gets a tx effect.
|
|
109
|
+
* @param txHash - The hash of a transaction which resulted in the returned tx effect.
|
|
110
|
+
* @returns The requested tx effect.
|
|
111
|
+
*/
|
|
112
|
+
public async getTxEffect(txHash: TxHash) {
|
|
113
|
+
const match = this.l2Blocks
|
|
114
|
+
.flatMap(b => b.body.txEffects.map(tx => [tx, b] as const))
|
|
115
|
+
.find(([tx]) => tx.txHash.equals(txHash));
|
|
116
|
+
if (!match) {
|
|
117
|
+
return Promise.resolve(undefined);
|
|
118
|
+
}
|
|
119
|
+
const [txEffect, block] = match;
|
|
120
|
+
return { data: txEffect, l2BlockNumber: block.number, l2BlockHash: (await block.hash()).toString() };
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Gets a receipt of a settled tx.
|
|
125
|
+
* @param txHash - The hash of a tx we try to get the receipt for.
|
|
126
|
+
* @returns The requested tx receipt (or undefined if not found).
|
|
127
|
+
*/
|
|
128
|
+
public async getSettledTxReceipt(txHash: TxHash): Promise<TxReceipt | undefined> {
|
|
129
|
+
for (const block of this.l2Blocks) {
|
|
130
|
+
for (const txEffect of block.body.txEffects) {
|
|
131
|
+
if (txEffect.txHash.equals(txHash)) {
|
|
132
|
+
return new TxReceipt(
|
|
133
|
+
txHash,
|
|
134
|
+
TxStatus.SUCCESS,
|
|
135
|
+
'',
|
|
136
|
+
txEffect.transactionFee.toBigInt(),
|
|
137
|
+
L2BlockHash.fromField(await block.hash()),
|
|
138
|
+
block.number,
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return undefined;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
async getL2Tips(): Promise<L2Tips> {
|
|
147
|
+
const [latest, proven, finalized] = [
|
|
148
|
+
await this.getBlockNumber(),
|
|
149
|
+
await this.getProvenBlockNumber(),
|
|
150
|
+
await this.getProvenBlockNumber(),
|
|
151
|
+
] as const;
|
|
152
|
+
|
|
153
|
+
const latestBlock = this.l2Blocks[latest - 1];
|
|
154
|
+
const provenBlock = this.l2Blocks[proven - 1];
|
|
155
|
+
const finalizedBlock = this.l2Blocks[finalized - 1];
|
|
156
|
+
|
|
157
|
+
return {
|
|
158
|
+
latest: {
|
|
159
|
+
number: latest,
|
|
160
|
+
hash: (await latestBlock?.hash())?.toString(),
|
|
161
|
+
},
|
|
162
|
+
proven: {
|
|
163
|
+
number: proven,
|
|
164
|
+
hash: (await provenBlock?.hash())?.toString(),
|
|
165
|
+
},
|
|
166
|
+
finalized: {
|
|
167
|
+
number: finalized,
|
|
168
|
+
hash: (await finalizedBlock?.hash())?.toString(),
|
|
169
|
+
},
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
getL2EpochNumber(): Promise<bigint> {
|
|
174
|
+
throw new Error('Method not implemented.');
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
getL2SlotNumber(): Promise<bigint> {
|
|
178
|
+
throw new Error('Method not implemented.');
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
isEpochComplete(_epochNumber: bigint): Promise<boolean> {
|
|
182
|
+
throw new Error('Method not implemented.');
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
getL1Constants(): Promise<L1RollupConstants> {
|
|
186
|
+
throw new Error('Method not implemented.');
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Starts the block source. In this mock implementation, this is a noop.
|
|
191
|
+
* @returns A promise that signals the initialization of the l2 block source on completion.
|
|
192
|
+
*/
|
|
193
|
+
public start(): Promise<void> {
|
|
194
|
+
return Promise.resolve();
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Stops the block source. In this mock implementation, this is a noop.
|
|
199
|
+
* @returns A promise that signals the l2 block source is now stopped.
|
|
200
|
+
*/
|
|
201
|
+
public stop(): Promise<void> {
|
|
202
|
+
return Promise.resolve();
|
|
203
|
+
}
|
|
204
|
+
}
|