@aztec/aztec-node 0.16.0 → 0.16.2
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/aztec-node/db.d.ts +3 -1
- package/dest/aztec-node/db.d.ts.map +1 -1
- package/dest/aztec-node/db.js +34 -24
- package/dest/aztec-node/http_rpc_server.js +3 -3
- package/dest/aztec-node/server.d.ts +64 -17
- package/dest/aztec-node/server.d.ts.map +1 -1
- package/dest/aztec-node/server.js +137 -36
- package/package.json +12 -11
- package/src/aztec-node/db.ts +44 -24
- package/src/aztec-node/http_rpc_server.ts +2 -2
- package/src/aztec-node/server.ts +196 -37
- package/src/declaration.d.ts +16 -0
package/dest/aztec-node/db.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { LogFn } from '@aztec/foundation/log';
|
|
1
2
|
import { LevelDown } from 'leveldown';
|
|
2
3
|
import { LevelUp } from 'levelup';
|
|
4
|
+
import { RootDatabase } from 'lmdb';
|
|
3
5
|
import { MemDown } from 'memdown';
|
|
4
6
|
import { AztecNodeConfig } from './config.js';
|
|
5
7
|
export declare const createMemDown: () => MemDown<any, any>;
|
|
@@ -10,5 +12,5 @@ export declare const createLevelDown: (path: string) => LevelDown;
|
|
|
10
12
|
* @throws If `config.dataDirectory` is set and the directory cannot be created.
|
|
11
13
|
* @returns The database for the aztec node.
|
|
12
14
|
*/
|
|
13
|
-
export declare function openDb(config: AztecNodeConfig): Promise<LevelUp>;
|
|
15
|
+
export declare function openDb(config: AztecNodeConfig, log: LogFn): Promise<[nodeDb: RootDatabase, worldStateDb: LevelUp]>;
|
|
14
16
|
//# sourceMappingURL=db.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/aztec-node/db.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAwB,MAAM,WAAW,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAsB,MAAM,SAAS,CAAC;AACtD,OAAO,EAAE,OAAO,EAAsB,MAAM,SAAS,CAAC;AAItD,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,eAAO,MAAM,aAAa,yBAAgD,CAAC;AAC3E,eAAO,MAAM,eAAe,SAAU,MAAM,cAA0C,CAAC;
|
|
1
|
+
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/aztec-node/db.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAE9C,OAAO,EAAE,SAAS,EAAwB,MAAM,WAAW,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAsB,MAAM,SAAS,CAAC;AACtD,OAAO,EAAE,YAAY,EAAQ,MAAM,MAAM,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAsB,MAAM,SAAS,CAAC;AAItD,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,eAAO,MAAM,aAAa,yBAAgD,CAAC;AAC3E,eAAO,MAAM,eAAe,SAAU,MAAM,cAA0C,CAAC;AAgBvF;;;;;GAKG;AACH,wBAAsB,MAAM,CAC1B,MAAM,EAAE,eAAe,EACvB,GAAG,EAAE,KAAK,GACT,OAAO,CAAC,CAAC,MAAM,EAAE,YAAY,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC,CA6BxD"}
|
package/dest/aztec-node/db.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { default as leveldown } from 'leveldown';
|
|
2
2
|
import { default as levelup } from 'levelup';
|
|
3
|
+
import { open } from 'lmdb';
|
|
3
4
|
import { default as memdown } from 'memdown';
|
|
4
5
|
import { mkdir } from 'node:fs/promises';
|
|
5
6
|
import { join } from 'node:path';
|
|
6
7
|
export const createMemDown = () => memdown();
|
|
7
8
|
export const createLevelDown = (path) => leveldown(path);
|
|
8
9
|
const DB_SUBDIR = 'aztec-node';
|
|
10
|
+
const WORLD_STATE_SUBDIR = 'aztec-world-state';
|
|
9
11
|
const NODE_METADATA_KEY = '@@aztec_node_metadata';
|
|
10
12
|
/**
|
|
11
13
|
* Opens the database for the aztec node. If a data directory is specified, then this attempts to create it.
|
|
@@ -13,42 +15,50 @@ const NODE_METADATA_KEY = '@@aztec_node_metadata';
|
|
|
13
15
|
* @throws If `config.dataDirectory` is set and the directory cannot be created.
|
|
14
16
|
* @returns The database for the aztec node.
|
|
15
17
|
*/
|
|
16
|
-
export async function openDb(config) {
|
|
18
|
+
export async function openDb(config, log) {
|
|
17
19
|
const nodeMetadata = {
|
|
18
20
|
rollupContractAddress: config.l1Contracts.rollupAddress.toString(),
|
|
19
21
|
};
|
|
20
|
-
let
|
|
22
|
+
let nodeDb;
|
|
23
|
+
let worldStateDb;
|
|
21
24
|
if (config.dataDirectory) {
|
|
22
|
-
const
|
|
25
|
+
const nodeDir = join(config.dataDirectory, DB_SUBDIR);
|
|
26
|
+
const worldStateDir = join(config.dataDirectory, WORLD_STATE_SUBDIR);
|
|
23
27
|
// this throws if we don't have permissions to create the directory
|
|
24
|
-
await mkdir(
|
|
25
|
-
|
|
28
|
+
await mkdir(nodeDir, { recursive: true });
|
|
29
|
+
await mkdir(worldStateDir, { recursive: true });
|
|
30
|
+
log(`Opening aztec-node database at ${nodeDir}`);
|
|
31
|
+
nodeDb = open(nodeDir, {});
|
|
32
|
+
log(`Opening world-state database at ${worldStateDir}`);
|
|
33
|
+
worldStateDb = levelup(createLevelDown(worldStateDir));
|
|
26
34
|
}
|
|
27
35
|
else {
|
|
28
|
-
|
|
36
|
+
log('Opening temporary databases');
|
|
37
|
+
// not passing a path will use a temp file that gets deleted when the process exits
|
|
38
|
+
nodeDb = open({});
|
|
39
|
+
worldStateDb = levelup(createMemDown());
|
|
29
40
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
if (nodeMetadata.rollupContractAddress !== prevNodeMetadata.rollupContractAddress) {
|
|
33
|
-
await db.clear();
|
|
34
|
-
}
|
|
35
|
-
await db.put(NODE_METADATA_KEY, JSON.stringify(nodeMetadata));
|
|
36
|
-
return db;
|
|
41
|
+
await checkNodeMetadataAndClear(nodeDb, worldStateDb, nodeMetadata, log);
|
|
42
|
+
return [nodeDb, worldStateDb];
|
|
37
43
|
}
|
|
38
44
|
/**
|
|
39
|
-
*
|
|
40
|
-
* @param
|
|
41
|
-
* @
|
|
45
|
+
* Checks the node metadata and clears the database if the rollup contract address has changed.
|
|
46
|
+
* @param nodeDb - The database for the aztec node.
|
|
47
|
+
* @param nodeMetadata - The metadata for the aztec node.
|
|
42
48
|
*/
|
|
43
|
-
async function
|
|
49
|
+
async function checkNodeMetadataAndClear(nodeDb, worldStateDb, nodeMetadata, log) {
|
|
50
|
+
const metadataDB = nodeDb.openDB('metadata', {});
|
|
44
51
|
try {
|
|
45
|
-
const
|
|
46
|
-
|
|
52
|
+
const existing = metadataDB.get(NODE_METADATA_KEY);
|
|
53
|
+
// if the rollup addresses are different, wipe the local database and start over
|
|
54
|
+
if (!existing || existing.rollupContractAddress !== nodeMetadata.rollupContractAddress) {
|
|
55
|
+
log('Rollup contract address has changed, clearing databases');
|
|
56
|
+
await Promise.all([nodeDb.clearAsync(), worldStateDb.clear()]);
|
|
57
|
+
}
|
|
58
|
+
await metadataDB.put(NODE_METADATA_KEY, nodeMetadata);
|
|
47
59
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
rollupContractAddress: '',
|
|
51
|
-
};
|
|
60
|
+
finally {
|
|
61
|
+
await metadataDB.close();
|
|
52
62
|
}
|
|
53
63
|
}
|
|
54
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
64
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYXp0ZWMtbm9kZS9kYi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQSxPQUFPLEVBQWEsT0FBTyxJQUFJLFNBQVMsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUM1RCxPQUFPLEVBQVcsT0FBTyxJQUFJLE9BQU8sRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUN0RCxPQUFPLEVBQWdCLElBQUksRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUMxQyxPQUFPLEVBQVcsT0FBTyxJQUFJLE9BQU8sRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUN0RCxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDekMsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUlqQyxNQUFNLENBQUMsTUFBTSxhQUFhLEdBQUcsR0FBRyxFQUFFLENBQUUsT0FBZSxFQUF1QixDQUFDO0FBQzNFLE1BQU0sQ0FBQyxNQUFNLGVBQWUsR0FBRyxDQUFDLElBQVksRUFBRSxFQUFFLENBQUUsU0FBaUIsQ0FBQyxJQUFJLENBQWMsQ0FBQztBQUV2RixNQUFNLFNBQVMsR0FBRyxZQUFZLENBQUM7QUFDL0IsTUFBTSxrQkFBa0IsR0FBRyxtQkFBbUIsQ0FBQztBQUMvQyxNQUFNLGlCQUFpQixHQUFHLHVCQUF1QixDQUFDO0FBWWxEOzs7OztHQUtHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSxNQUFNLENBQzFCLE1BQXVCLEVBQ3ZCLEdBQVU7SUFFVixNQUFNLFlBQVksR0FBaUI7UUFDakMscUJBQXFCLEVBQUUsTUFBTSxDQUFDLFdBQVcsQ0FBQyxhQUFhLENBQUMsUUFBUSxFQUFFO0tBQ25FLENBQUM7SUFFRixJQUFJLE1BQW9CLENBQUM7SUFDekIsSUFBSSxZQUFxQixDQUFDO0lBRTFCLElBQUksTUFBTSxDQUFDLGFBQWEsRUFBRTtRQUN4QixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsRUFBRSxTQUFTLENBQUMsQ0FBQztRQUN0RCxNQUFNLGFBQWEsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsRUFBRSxrQkFBa0IsQ0FBQyxDQUFDO1FBQ3JFLG1FQUFtRTtRQUNuRSxNQUFNLEtBQUssQ0FBQyxPQUFPLEVBQUUsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUMxQyxNQUFNLEtBQUssQ0FBQyxhQUFhLEVBQUUsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUVoRCxHQUFHLENBQUMsa0NBQWtDLE9BQU8sRUFBRSxDQUFDLENBQUM7UUFDakQsTUFBTSxHQUFHLElBQUksQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFM0IsR0FBRyxDQUFDLG1DQUFtQyxhQUFhLEVBQUUsQ0FBQyxDQUFDO1FBQ3hELFlBQVksR0FBRyxPQUFPLENBQUMsZUFBZSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUM7S0FDeEQ7U0FBTTtRQUNMLEdBQUcsQ0FBQyw2QkFBNkIsQ0FBQyxDQUFDO1FBQ25DLG1GQUFtRjtRQUNuRixNQUFNLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQ2xCLFlBQVksR0FBRyxPQUFPLENBQUMsYUFBYSxFQUFFLENBQUMsQ0FBQztLQUN6QztJQUVELE1BQU0seUJBQXlCLENBQUMsTUFBTSxFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFDekUsT0FBTyxDQUFDLE1BQU0sRUFBRSxZQUFZLENBQUMsQ0FBQztBQUNoQyxDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILEtBQUssVUFBVSx5QkFBeUIsQ0FDdEMsTUFBb0IsRUFDcEIsWUFBcUIsRUFDckIsWUFBMEIsRUFDMUIsR0FBVTtJQUVWLE1BQU0sVUFBVSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQXVCLFVBQVUsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUN2RSxJQUFJO1FBQ0YsTUFBTSxRQUFRLEdBQUcsVUFBVSxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO1FBQ25ELGdGQUFnRjtRQUNoRixJQUFJLENBQUMsUUFBUSxJQUFJLFFBQVEsQ0FBQyxxQkFBcUIsS0FBSyxZQUFZLENBQUMscUJBQXFCLEVBQUU7WUFDdEYsR0FBRyxDQUFDLHlEQUF5RCxDQUFDLENBQUM7WUFDL0QsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxDQUFDLFVBQVUsRUFBRSxFQUFFLFlBQVksQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUM7U0FDaEU7UUFDRCxNQUFNLFVBQVUsQ0FBQyxHQUFHLENBQUMsaUJBQWlCLEVBQUUsWUFBWSxDQUFDLENBQUM7S0FDdkQ7WUFBUztRQUNSLE1BQU0sVUFBVSxDQUFDLEtBQUssRUFBRSxDQUFDO0tBQzFCO0FBQ0gsQ0FBQyJ9
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BlockHeader, FunctionSelector } from '@aztec/circuits.js';
|
|
2
2
|
import { AztecAddress } from '@aztec/foundation/aztec-address';
|
|
3
3
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
4
4
|
import { Fr } from '@aztec/foundation/fields';
|
|
@@ -18,7 +18,7 @@ export function createAztecNodeRpcServer(node) {
|
|
|
18
18
|
ContractData,
|
|
19
19
|
Fr,
|
|
20
20
|
FunctionSelector,
|
|
21
|
-
|
|
21
|
+
BlockHeader,
|
|
22
22
|
L2Block,
|
|
23
23
|
L2Tx,
|
|
24
24
|
LogId,
|
|
@@ -30,4 +30,4 @@ export function createAztecNodeRpcServer(node) {
|
|
|
30
30
|
['start', 'stop']);
|
|
31
31
|
return rpc;
|
|
32
32
|
}
|
|
33
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
33
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaHR0cF9ycGNfc2VydmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2F6dGVjLW5vZGUvaHR0cF9ycGNfc2VydmVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxXQUFXLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUNuRSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDL0QsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQzNELE9BQU8sRUFBRSxFQUFFLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUM5QyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sbUNBQW1DLENBQUM7QUFDbEUsT0FBTyxFQUVMLFlBQVksRUFDWixvQkFBb0IsRUFDcEIsd0JBQXdCLEVBQ3hCLHFCQUFxQixFQUNyQixPQUFPLEVBQ1AsYUFBYSxFQUNiLElBQUksRUFDSixLQUFLLEVBQ0wsV0FBVyxFQUNYLEVBQUUsRUFDRixNQUFNLEdBQ1AsTUFBTSxjQUFjLENBQUM7QUFFdEI7Ozs7R0FJRztBQUNILE1BQU0sVUFBVSx3QkFBd0IsQ0FBQyxJQUFlO0lBQ3RELE1BQU0sR0FBRyxHQUFHLElBQUksYUFBYSxDQUMzQixJQUFJLEVBQ0o7UUFDRSxZQUFZO1FBQ1osVUFBVTtRQUNWLG9CQUFvQjtRQUNwQix3QkFBd0I7UUFDeEIsWUFBWTtRQUNaLEVBQUU7UUFDRixnQkFBZ0I7UUFDaEIsV0FBVztRQUNYLE9BQU87UUFDUCxJQUFJO1FBQ0osS0FBSztRQUNMLE1BQU07UUFDTixXQUFXO1FBQ1gscUJBQXFCO0tBQ3RCLEVBQ0QsRUFBRSxFQUFFLEVBQUUsYUFBYSxFQUFFLEVBQ3JCLEtBQUs7SUFDTCxzREFBc0Q7SUFDdEQsQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLENBQ2xCLENBQUM7SUFDRixPQUFPLEdBQUcsQ0FBQztBQUNiLENBQUMifQ==
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { CONTRACT_TREE_HEIGHT, Fr,
|
|
1
|
+
import { BLOCKS_TREE_HEIGHT, BlockHeader, CONTRACT_TREE_HEIGHT, Fr, L1_TO_L2_MSG_TREE_HEIGHT, NOTE_HASH_TREE_HEIGHT, NULLIFIER_TREE_HEIGHT, PUBLIC_DATA_TREE_HEIGHT } from '@aztec/circuits.js';
|
|
2
2
|
import { L1ContractAddresses } from '@aztec/ethereum';
|
|
3
3
|
import { AztecAddress } from '@aztec/foundation/aztec-address';
|
|
4
4
|
import { P2P } from '@aztec/p2p';
|
|
5
5
|
import { GlobalVariableBuilder, SequencerClient } from '@aztec/sequencer-client';
|
|
6
|
-
import { AztecNode, ContractData, ContractDataSource, ExtendedContractData, GetUnencryptedLogsResponse, L1ToL2MessageAndIndex, L1ToL2MessageSource, L2Block, L2BlockL2Logs, L2BlockSource, L2LogsSource, L2Tx, LogFilter, LogType, MerkleTreeId, SequencerConfig, SiblingPath, Tx, TxHash } from '@aztec/types';
|
|
6
|
+
import { AztecNode, ContractData, ContractDataSource, ExtendedContractData, GetUnencryptedLogsResponse, L1ToL2MessageAndIndex, L1ToL2MessageSource, L2Block, L2BlockL2Logs, L2BlockSource, L2LogsSource, L2Tx, LogFilter, LogType, MerkleTreeId, NullifierMembershipWitness, SequencerConfig, SiblingPath, Tx, TxHash } from '@aztec/types';
|
|
7
7
|
import { WorldStateSynchronizer } from '@aztec/world-state';
|
|
8
|
-
import
|
|
8
|
+
import { LevelUp } from 'levelup';
|
|
9
9
|
import { AztecNodeConfig } from './config.js';
|
|
10
10
|
/**
|
|
11
11
|
* The aztec node.
|
|
@@ -24,9 +24,9 @@ export declare class AztecNodeService implements AztecNode {
|
|
|
24
24
|
protected readonly chainId: number;
|
|
25
25
|
protected readonly version: number;
|
|
26
26
|
protected readonly globalVariableBuilder: GlobalVariableBuilder;
|
|
27
|
-
protected readonly merkleTreesDb:
|
|
27
|
+
protected readonly merkleTreesDb: LevelUp;
|
|
28
28
|
private log;
|
|
29
|
-
constructor(config: AztecNodeConfig, p2pClient: P2P, blockSource: L2BlockSource, encryptedLogsSource: L2LogsSource, unencryptedLogsSource: L2LogsSource, contractDataSource: ContractDataSource, l1ToL2MessageSource: L1ToL2MessageSource, worldStateSynchronizer: WorldStateSynchronizer, sequencer: SequencerClient | undefined, chainId: number, version: number, globalVariableBuilder: GlobalVariableBuilder, merkleTreesDb:
|
|
29
|
+
constructor(config: AztecNodeConfig, p2pClient: P2P, blockSource: L2BlockSource, encryptedLogsSource: L2LogsSource, unencryptedLogsSource: L2LogsSource, contractDataSource: ContractDataSource, l1ToL2MessageSource: L1ToL2MessageSource, worldStateSynchronizer: WorldStateSynchronizer, sequencer: SequencerClient | undefined, chainId: number, version: number, globalVariableBuilder: GlobalVariableBuilder, merkleTreesDb: LevelUp, log?: import("@aztec/foundation/log").DebugLogger);
|
|
30
30
|
/**
|
|
31
31
|
* initializes the Aztec Node, wait for component to sync.
|
|
32
32
|
* @param config - The configuration to be used by the aztec node.
|
|
@@ -49,9 +49,9 @@ export declare class AztecNodeService implements AztecNode {
|
|
|
49
49
|
*/
|
|
50
50
|
isReady(): Promise<boolean>;
|
|
51
51
|
/**
|
|
52
|
-
* Get
|
|
52
|
+
* Get a block specified by its number.
|
|
53
53
|
* @param number - The block number being requested.
|
|
54
|
-
* @returns The
|
|
54
|
+
* @returns The requested block.
|
|
55
55
|
*/
|
|
56
56
|
getBlock(number: number): Promise<L2Block | undefined>;
|
|
57
57
|
/**
|
|
@@ -126,23 +126,33 @@ export declare class AztecNodeService implements AztecNode {
|
|
|
126
126
|
getPendingTxByHash(txHash: TxHash): Promise<Tx | undefined>;
|
|
127
127
|
/**
|
|
128
128
|
* Find the index of the given leaf in the given tree.
|
|
129
|
+
* @param blockNumber - The block number at which to get the data
|
|
129
130
|
* @param treeId - The tree to search in.
|
|
130
131
|
* @param leafValue - The value to search for
|
|
131
132
|
* @returns The index of the given leaf in the given tree or undefined if not found.
|
|
132
133
|
*/
|
|
133
|
-
findLeafIndex(treeId: MerkleTreeId, leafValue: Fr): Promise<bigint | undefined>;
|
|
134
|
+
findLeafIndex(blockNumber: number | 'latest', treeId: MerkleTreeId, leafValue: Fr): Promise<bigint | undefined>;
|
|
135
|
+
/**
|
|
136
|
+
* Returns a sibling path for the given index in the contract tree.
|
|
137
|
+
* @param blockNumber - The block number at which to get the data.
|
|
138
|
+
* @param leafIndex - The index of the leaf for which the sibling path is required.
|
|
139
|
+
* @returns The sibling path for the leaf index.
|
|
140
|
+
*/
|
|
141
|
+
getContractSiblingPath(blockNumber: number | 'latest', leafIndex: bigint): Promise<SiblingPath<typeof CONTRACT_TREE_HEIGHT>>;
|
|
134
142
|
/**
|
|
135
|
-
* Returns
|
|
143
|
+
* Returns a sibling path for the given index in the nullifier tree.
|
|
144
|
+
* @param blockNumber - The block number at which to get the data.
|
|
136
145
|
* @param leafIndex - The index of the leaf for which the sibling path is required.
|
|
137
146
|
* @returns The sibling path for the leaf index.
|
|
138
147
|
*/
|
|
139
|
-
|
|
148
|
+
getNullifierTreeSiblingPath(blockNumber: number | 'latest', leafIndex: bigint): Promise<SiblingPath<typeof NULLIFIER_TREE_HEIGHT>>;
|
|
140
149
|
/**
|
|
141
|
-
* Returns
|
|
150
|
+
* Returns a sibling path for the given index in the data tree.
|
|
151
|
+
* @param blockNumber - The block number at which to get the data.
|
|
142
152
|
* @param leafIndex - The index of the leaf for which the sibling path is required.
|
|
143
153
|
* @returns The sibling path for the leaf index.
|
|
144
154
|
*/
|
|
145
|
-
getNoteHashSiblingPath(leafIndex: bigint): Promise<SiblingPath<typeof NOTE_HASH_TREE_HEIGHT>>;
|
|
155
|
+
getNoteHashSiblingPath(blockNumber: number | 'latest', leafIndex: bigint): Promise<SiblingPath<typeof NOTE_HASH_TREE_HEIGHT>>;
|
|
146
156
|
/**
|
|
147
157
|
* Gets a confirmed/consumed L1 to L2 message for the given message key
|
|
148
158
|
* and its index in the merkle tree.
|
|
@@ -151,11 +161,48 @@ export declare class AztecNodeService implements AztecNode {
|
|
|
151
161
|
*/
|
|
152
162
|
getL1ToL2MessageAndIndex(messageKey: Fr): Promise<L1ToL2MessageAndIndex>;
|
|
153
163
|
/**
|
|
154
|
-
* Returns
|
|
164
|
+
* Returns a sibling path for a leaf in the committed l1 to l2 data tree.
|
|
165
|
+
* @param blockNumber - The block number at which to get the data.
|
|
166
|
+
* @param leafIndex - Index of the leaf in the tree.
|
|
167
|
+
* @returns The sibling path.
|
|
168
|
+
*/
|
|
169
|
+
getL1ToL2MessageSiblingPath(blockNumber: number | 'latest', leafIndex: bigint): Promise<SiblingPath<typeof L1_TO_L2_MSG_TREE_HEIGHT>>;
|
|
170
|
+
/**
|
|
171
|
+
* Returns a sibling path for a leaf in the committed blocks tree.
|
|
172
|
+
* @param blockNumber - The block number at which to get the data.
|
|
155
173
|
* @param leafIndex - Index of the leaf in the tree.
|
|
156
174
|
* @returns The sibling path.
|
|
157
175
|
*/
|
|
158
|
-
|
|
176
|
+
getBlocksTreeSiblingPath(blockNumber: number | 'latest', leafIndex: bigint): Promise<SiblingPath<typeof BLOCKS_TREE_HEIGHT>>;
|
|
177
|
+
/**
|
|
178
|
+
* Returns a sibling path for a leaf in the committed public data tree.
|
|
179
|
+
* @param blockNumber - The block number at which to get the data.
|
|
180
|
+
* @param leafIndex - Index of the leaf in the tree.
|
|
181
|
+
* @returns The sibling path.
|
|
182
|
+
*/
|
|
183
|
+
getPublicDataTreeSiblingPath(blockNumber: number | 'latest', leafIndex: bigint): Promise<SiblingPath<typeof PUBLIC_DATA_TREE_HEIGHT>>;
|
|
184
|
+
/**
|
|
185
|
+
* Returns a nullifier membership witness for a given nullifier at a given block.
|
|
186
|
+
* @param blockNumber - The block number at which to get the index.
|
|
187
|
+
* @param nullifier - Nullifier we try to find witness for.
|
|
188
|
+
* @returns The nullifier membership witness (if found).
|
|
189
|
+
*/
|
|
190
|
+
getNullifierMembershipWitness(blockNumber: number | 'latest', nullifier: Fr): Promise<NullifierMembershipWitness | undefined>;
|
|
191
|
+
/**
|
|
192
|
+
* Returns a low nullifier membership witness for a given nullifier at a given block.
|
|
193
|
+
* @param blockNumber - The block number at which to get the index.
|
|
194
|
+
* @param nullifier - Nullifier we try to find the low nullifier witness for.
|
|
195
|
+
* @returns The low nullifier membership witness (if found).
|
|
196
|
+
* @remarks Low nullifier witness can be used to perform a nullifier non-inclusion proof by leveraging the "linked
|
|
197
|
+
* list structure" of leaves and proving that a lower nullifier is pointing to a bigger next value than the nullifier
|
|
198
|
+
* we are trying to prove non-inclusion for.
|
|
199
|
+
*
|
|
200
|
+
* Note: This function returns the membership witness of the nullifier itself and not the low nullifier when
|
|
201
|
+
* the nullifier already exists in the tree. This is because the `getPreviousValueIndex` function returns the
|
|
202
|
+
* index of the nullifier itself when it already exists in the tree.
|
|
203
|
+
* TODO: This is a confusing behavior and we should eventually address that.
|
|
204
|
+
*/
|
|
205
|
+
getLowNullifierMembershipWitness(blockNumber: number | 'latest', nullifier: Fr): Promise<NullifierMembershipWitness | undefined>;
|
|
159
206
|
/**
|
|
160
207
|
* Gets the storage value at the given contract storage slot.
|
|
161
208
|
*
|
|
@@ -173,10 +220,10 @@ export declare class AztecNodeService implements AztecNode {
|
|
|
173
220
|
*/
|
|
174
221
|
getTreeRoots(): Promise<Record<MerkleTreeId, Fr>>;
|
|
175
222
|
/**
|
|
176
|
-
* Returns the currently committed
|
|
177
|
-
* @returns The current committed block
|
|
223
|
+
* Returns the currently committed block header.
|
|
224
|
+
* @returns The current committed block header.
|
|
178
225
|
*/
|
|
179
|
-
|
|
226
|
+
getBlockHeader(): Promise<BlockHeader>;
|
|
180
227
|
/**
|
|
181
228
|
* Simulates the public part of a transaction with the current state.
|
|
182
229
|
* @param tx - The transaction to simulate.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/aztec-node/server.ts"],"names":[],"mappings":"AACA,OAAO,EACL,oBAAoB,EACpB,EAAE,EAEF,
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/aztec-node/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
var _AztecNodeService_instances, _AztecNodeService_getWorldState, _AztecNodeService_syncWorldState;
|
|
2
2
|
import { __classPrivateFieldGet } from "tslib";
|
|
3
|
-
import { Archiver } from '@aztec/archiver';
|
|
4
|
-
import { Fr, GlobalVariables,
|
|
5
|
-
import { computePublicDataTreeIndex } from '@aztec/circuits.js/abis';
|
|
3
|
+
import { Archiver, LMDBArchiverStore } from '@aztec/archiver';
|
|
4
|
+
import { BlockHeader, Fr, GlobalVariables, } from '@aztec/circuits.js';
|
|
5
|
+
import { computeGlobalsHash, computePublicDataTreeIndex } from '@aztec/circuits.js/abis';
|
|
6
6
|
import { createEthereumChain } from '@aztec/ethereum';
|
|
7
7
|
import { createDebugLogger } from '@aztec/foundation/log';
|
|
8
8
|
import { InMemoryTxPool, createP2PClient } from '@aztec/p2p';
|
|
9
9
|
import { PublicProcessorFactory, SequencerClient, getGlobalVariableBuilder, } from '@aztec/sequencer-client';
|
|
10
|
-
import { L1ToL2MessageAndIndex, LogType, MerkleTreeId, } from '@aztec/types';
|
|
10
|
+
import { INITIAL_L2_BLOCK_NUM, L1ToL2MessageAndIndex, LogType, MerkleTreeId, NullifierMembershipWitness, } from '@aztec/types';
|
|
11
11
|
import { MerkleTrees, ServerWorldStateSynchronizer, getConfigEnvVars as getWorldStateConfig, } from '@aztec/world-state';
|
|
12
12
|
import { openDb } from './db.js';
|
|
13
13
|
/**
|
|
@@ -49,25 +49,27 @@ export class AztecNodeService {
|
|
|
49
49
|
if (config.chainId !== ethereumChain.chainInfo.id) {
|
|
50
50
|
throw new Error(`RPC URL configured for chain id ${ethereumChain.chainInfo.id} but expected id ${config.chainId}`);
|
|
51
51
|
}
|
|
52
|
+
const log = createDebugLogger('aztec:node');
|
|
53
|
+
const [nodeDb, worldStateDb] = await openDb(config, log);
|
|
52
54
|
// first create and sync the archiver
|
|
53
|
-
const
|
|
55
|
+
const archiverStore = new LMDBArchiverStore(nodeDb, config.maxLogs);
|
|
56
|
+
const archiver = await Archiver.createAndSync(config, archiverStore, true);
|
|
54
57
|
// we identify the P2P transaction protocol by using the rollup contract address.
|
|
55
58
|
// this may well change in future
|
|
56
59
|
config.transactionProtocol = `/aztec/tx/${config.l1Contracts.rollupAddress.toString()}`;
|
|
57
60
|
// create the tx pool and the p2p client, which will need the l2 block source
|
|
58
61
|
const p2pClient = await createP2PClient(config, new InMemoryTxPool(), archiver);
|
|
59
62
|
// now create the merkle trees and the world state synchronizer
|
|
60
|
-
const
|
|
61
|
-
const merkleTrees = await MerkleTrees.new(db);
|
|
63
|
+
const merkleTrees = await MerkleTrees.new(worldStateDb);
|
|
62
64
|
const worldStateConfig = getWorldStateConfig();
|
|
63
|
-
const worldStateSynchronizer = await ServerWorldStateSynchronizer.new(
|
|
65
|
+
const worldStateSynchronizer = await ServerWorldStateSynchronizer.new(worldStateDb, merkleTrees, archiver, worldStateConfig);
|
|
64
66
|
// start both and wait for them to sync from the block source
|
|
65
67
|
await Promise.all([p2pClient.start(), worldStateSynchronizer.start()]);
|
|
66
68
|
// now create the sequencer
|
|
67
69
|
const sequencer = config.disableSequencer
|
|
68
70
|
? undefined
|
|
69
71
|
: await SequencerClient.new(config, p2pClient, worldStateSynchronizer, archiver, archiver, archiver);
|
|
70
|
-
return new AztecNodeService(config, p2pClient, archiver, archiver, archiver, archiver, archiver, worldStateSynchronizer, sequencer, ethereumChain.chainInfo.id, config.version, getGlobalVariableBuilder(config),
|
|
72
|
+
return new AztecNodeService(config, p2pClient, archiver, archiver, archiver, archiver, archiver, worldStateSynchronizer, sequencer, ethereumChain.chainInfo.id, config.version, getGlobalVariableBuilder(config), worldStateDb, log);
|
|
71
73
|
}
|
|
72
74
|
/**
|
|
73
75
|
* Returns the sequencer client instance.
|
|
@@ -91,9 +93,9 @@ export class AztecNodeService {
|
|
|
91
93
|
return (await this.p2pClient.isReady()) ?? false;
|
|
92
94
|
}
|
|
93
95
|
/**
|
|
94
|
-
* Get
|
|
96
|
+
* Get a block specified by its number.
|
|
95
97
|
* @param number - The block number being requested.
|
|
96
|
-
* @returns The
|
|
98
|
+
* @returns The requested block.
|
|
97
99
|
*/
|
|
98
100
|
async getBlock(number) {
|
|
99
101
|
return await this.blockSource.getBlock(number);
|
|
@@ -203,30 +205,43 @@ export class AztecNodeService {
|
|
|
203
205
|
}
|
|
204
206
|
/**
|
|
205
207
|
* Find the index of the given leaf in the given tree.
|
|
208
|
+
* @param blockNumber - The block number at which to get the data
|
|
206
209
|
* @param treeId - The tree to search in.
|
|
207
210
|
* @param leafValue - The value to search for
|
|
208
211
|
* @returns The index of the given leaf in the given tree or undefined if not found.
|
|
209
212
|
*/
|
|
210
|
-
async findLeafIndex(treeId, leafValue) {
|
|
211
|
-
const committedDb = await __classPrivateFieldGet(this, _AztecNodeService_instances, "m", _AztecNodeService_getWorldState).call(this);
|
|
213
|
+
async findLeafIndex(blockNumber, treeId, leafValue) {
|
|
214
|
+
const committedDb = await __classPrivateFieldGet(this, _AztecNodeService_instances, "m", _AztecNodeService_getWorldState).call(this, blockNumber);
|
|
212
215
|
return committedDb.findLeafIndex(treeId, leafValue.toBuffer());
|
|
213
216
|
}
|
|
214
217
|
/**
|
|
215
|
-
* Returns
|
|
218
|
+
* Returns a sibling path for the given index in the contract tree.
|
|
219
|
+
* @param blockNumber - The block number at which to get the data.
|
|
216
220
|
* @param leafIndex - The index of the leaf for which the sibling path is required.
|
|
217
221
|
* @returns The sibling path for the leaf index.
|
|
218
222
|
*/
|
|
219
|
-
async getContractSiblingPath(leafIndex) {
|
|
220
|
-
const committedDb = await __classPrivateFieldGet(this, _AztecNodeService_instances, "m", _AztecNodeService_getWorldState).call(this);
|
|
223
|
+
async getContractSiblingPath(blockNumber, leafIndex) {
|
|
224
|
+
const committedDb = await __classPrivateFieldGet(this, _AztecNodeService_instances, "m", _AztecNodeService_getWorldState).call(this, blockNumber);
|
|
221
225
|
return committedDb.getSiblingPath(MerkleTreeId.CONTRACT_TREE, leafIndex);
|
|
222
226
|
}
|
|
223
227
|
/**
|
|
224
|
-
* Returns
|
|
228
|
+
* Returns a sibling path for the given index in the nullifier tree.
|
|
229
|
+
* @param blockNumber - The block number at which to get the data.
|
|
230
|
+
* @param leafIndex - The index of the leaf for which the sibling path is required.
|
|
231
|
+
* @returns The sibling path for the leaf index.
|
|
232
|
+
*/
|
|
233
|
+
async getNullifierTreeSiblingPath(blockNumber, leafIndex) {
|
|
234
|
+
const committedDb = await __classPrivateFieldGet(this, _AztecNodeService_instances, "m", _AztecNodeService_getWorldState).call(this, blockNumber);
|
|
235
|
+
return committedDb.getSiblingPath(MerkleTreeId.NULLIFIER_TREE, leafIndex);
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Returns a sibling path for the given index in the data tree.
|
|
239
|
+
* @param blockNumber - The block number at which to get the data.
|
|
225
240
|
* @param leafIndex - The index of the leaf for which the sibling path is required.
|
|
226
241
|
* @returns The sibling path for the leaf index.
|
|
227
242
|
*/
|
|
228
|
-
async getNoteHashSiblingPath(leafIndex) {
|
|
229
|
-
const committedDb = await __classPrivateFieldGet(this, _AztecNodeService_instances, "m", _AztecNodeService_getWorldState).call(this);
|
|
243
|
+
async getNoteHashSiblingPath(blockNumber, leafIndex) {
|
|
244
|
+
const committedDb = await __classPrivateFieldGet(this, _AztecNodeService_instances, "m", _AztecNodeService_getWorldState).call(this, blockNumber);
|
|
230
245
|
return committedDb.getSiblingPath(MerkleTreeId.NOTE_HASH_TREE, leafIndex);
|
|
231
246
|
}
|
|
232
247
|
/**
|
|
@@ -237,19 +252,88 @@ export class AztecNodeService {
|
|
|
237
252
|
*/
|
|
238
253
|
async getL1ToL2MessageAndIndex(messageKey) {
|
|
239
254
|
// todo: #697 - make this one lookup.
|
|
240
|
-
const index = (await this.findLeafIndex(MerkleTreeId.L1_TO_L2_MESSAGES_TREE, messageKey));
|
|
255
|
+
const index = (await this.findLeafIndex('latest', MerkleTreeId.L1_TO_L2_MESSAGES_TREE, messageKey));
|
|
241
256
|
const message = await this.l1ToL2MessageSource.getConfirmedL1ToL2Message(messageKey);
|
|
242
257
|
return Promise.resolve(new L1ToL2MessageAndIndex(index, message));
|
|
243
258
|
}
|
|
244
259
|
/**
|
|
245
|
-
* Returns
|
|
260
|
+
* Returns a sibling path for a leaf in the committed l1 to l2 data tree.
|
|
261
|
+
* @param blockNumber - The block number at which to get the data.
|
|
246
262
|
* @param leafIndex - Index of the leaf in the tree.
|
|
247
263
|
* @returns The sibling path.
|
|
248
264
|
*/
|
|
249
|
-
async getL1ToL2MessageSiblingPath(leafIndex) {
|
|
250
|
-
const committedDb = await __classPrivateFieldGet(this, _AztecNodeService_instances, "m", _AztecNodeService_getWorldState).call(this);
|
|
265
|
+
async getL1ToL2MessageSiblingPath(blockNumber, leafIndex) {
|
|
266
|
+
const committedDb = await __classPrivateFieldGet(this, _AztecNodeService_instances, "m", _AztecNodeService_getWorldState).call(this, blockNumber);
|
|
251
267
|
return committedDb.getSiblingPath(MerkleTreeId.L1_TO_L2_MESSAGES_TREE, leafIndex);
|
|
252
268
|
}
|
|
269
|
+
/**
|
|
270
|
+
* Returns a sibling path for a leaf in the committed blocks tree.
|
|
271
|
+
* @param blockNumber - The block number at which to get the data.
|
|
272
|
+
* @param leafIndex - Index of the leaf in the tree.
|
|
273
|
+
* @returns The sibling path.
|
|
274
|
+
*/
|
|
275
|
+
async getBlocksTreeSiblingPath(blockNumber, leafIndex) {
|
|
276
|
+
const committedDb = await __classPrivateFieldGet(this, _AztecNodeService_instances, "m", _AztecNodeService_getWorldState).call(this, blockNumber);
|
|
277
|
+
return committedDb.getSiblingPath(MerkleTreeId.BLOCKS_TREE, leafIndex);
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Returns a sibling path for a leaf in the committed public data tree.
|
|
281
|
+
* @param blockNumber - The block number at which to get the data.
|
|
282
|
+
* @param leafIndex - Index of the leaf in the tree.
|
|
283
|
+
* @returns The sibling path.
|
|
284
|
+
*/
|
|
285
|
+
async getPublicDataTreeSiblingPath(blockNumber, leafIndex) {
|
|
286
|
+
const committedDb = await __classPrivateFieldGet(this, _AztecNodeService_instances, "m", _AztecNodeService_getWorldState).call(this, blockNumber);
|
|
287
|
+
return committedDb.getSiblingPath(MerkleTreeId.PUBLIC_DATA_TREE, leafIndex);
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Returns a nullifier membership witness for a given nullifier at a given block.
|
|
291
|
+
* @param blockNumber - The block number at which to get the index.
|
|
292
|
+
* @param nullifier - Nullifier we try to find witness for.
|
|
293
|
+
* @returns The nullifier membership witness (if found).
|
|
294
|
+
*/
|
|
295
|
+
async getNullifierMembershipWitness(blockNumber, nullifier) {
|
|
296
|
+
const db = await __classPrivateFieldGet(this, _AztecNodeService_instances, "m", _AztecNodeService_getWorldState).call(this, blockNumber);
|
|
297
|
+
const index = await db.findLeafIndex(MerkleTreeId.NULLIFIER_TREE, nullifier.toBuffer());
|
|
298
|
+
if (!index) {
|
|
299
|
+
return undefined;
|
|
300
|
+
}
|
|
301
|
+
const leafPreimagePromise = db.getLeafPreimage(MerkleTreeId.NULLIFIER_TREE, index);
|
|
302
|
+
const siblingPathPromise = db.getSiblingPath(MerkleTreeId.NULLIFIER_TREE, BigInt(index));
|
|
303
|
+
const [leafPreimage, siblingPath] = await Promise.all([leafPreimagePromise, siblingPathPromise]);
|
|
304
|
+
if (!leafPreimage) {
|
|
305
|
+
return undefined;
|
|
306
|
+
}
|
|
307
|
+
return new NullifierMembershipWitness(BigInt(index), leafPreimage, siblingPath);
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Returns a low nullifier membership witness for a given nullifier at a given block.
|
|
311
|
+
* @param blockNumber - The block number at which to get the index.
|
|
312
|
+
* @param nullifier - Nullifier we try to find the low nullifier witness for.
|
|
313
|
+
* @returns The low nullifier membership witness (if found).
|
|
314
|
+
* @remarks Low nullifier witness can be used to perform a nullifier non-inclusion proof by leveraging the "linked
|
|
315
|
+
* list structure" of leaves and proving that a lower nullifier is pointing to a bigger next value than the nullifier
|
|
316
|
+
* we are trying to prove non-inclusion for.
|
|
317
|
+
*
|
|
318
|
+
* Note: This function returns the membership witness of the nullifier itself and not the low nullifier when
|
|
319
|
+
* the nullifier already exists in the tree. This is because the `getPreviousValueIndex` function returns the
|
|
320
|
+
* index of the nullifier itself when it already exists in the tree.
|
|
321
|
+
* TODO: This is a confusing behavior and we should eventually address that.
|
|
322
|
+
*/
|
|
323
|
+
async getLowNullifierMembershipWitness(blockNumber, nullifier) {
|
|
324
|
+
const committedDb = await __classPrivateFieldGet(this, _AztecNodeService_instances, "m", _AztecNodeService_getWorldState).call(this, blockNumber);
|
|
325
|
+
const findResult = await committedDb.getPreviousValueIndex(MerkleTreeId.NULLIFIER_TREE, nullifier.toBigInt());
|
|
326
|
+
if (!findResult) {
|
|
327
|
+
return undefined;
|
|
328
|
+
}
|
|
329
|
+
const { index, alreadyPresent } = findResult;
|
|
330
|
+
if (alreadyPresent) {
|
|
331
|
+
this.log.warn(`Nullifier ${nullifier.toBigInt()} already exists in the tree`);
|
|
332
|
+
}
|
|
333
|
+
const preimageData = (await committedDb.getLeafPreimage(MerkleTreeId.NULLIFIER_TREE, index));
|
|
334
|
+
const siblingPath = await committedDb.getSiblingPath(MerkleTreeId.NULLIFIER_TREE, BigInt(index));
|
|
335
|
+
return new NullifierMembershipWitness(BigInt(index), preimageData, siblingPath);
|
|
336
|
+
}
|
|
253
337
|
/**
|
|
254
338
|
* Gets the storage value at the given contract storage slot.
|
|
255
339
|
*
|
|
@@ -261,7 +345,7 @@ export class AztecNodeService {
|
|
|
261
345
|
* @returns Storage value at the given contract slot (or undefined if not found).
|
|
262
346
|
*/
|
|
263
347
|
async getPublicStorageAt(contract, slot) {
|
|
264
|
-
const committedDb = await __classPrivateFieldGet(this, _AztecNodeService_instances, "m", _AztecNodeService_getWorldState).call(this);
|
|
348
|
+
const committedDb = await __classPrivateFieldGet(this, _AztecNodeService_instances, "m", _AztecNodeService_getWorldState).call(this, 'latest');
|
|
265
349
|
const leafIndex = computePublicDataTreeIndex(contract, slot);
|
|
266
350
|
const value = await committedDb.getLeafValue(MerkleTreeId.PUBLIC_DATA_TREE, leafIndex.value);
|
|
267
351
|
return value ? Fr.fromBuffer(value) : undefined;
|
|
@@ -271,7 +355,7 @@ export class AztecNodeService {
|
|
|
271
355
|
* @returns The current committed roots for the data trees.
|
|
272
356
|
*/
|
|
273
357
|
async getTreeRoots() {
|
|
274
|
-
const committedDb = await __classPrivateFieldGet(this, _AztecNodeService_instances, "m", _AztecNodeService_getWorldState).call(this);
|
|
358
|
+
const committedDb = await __classPrivateFieldGet(this, _AztecNodeService_instances, "m", _AztecNodeService_getWorldState).call(this, 'latest');
|
|
275
359
|
const getTreeRoot = async (id) => Fr.fromBuffer((await committedDb.getTreeInfo(id)).root);
|
|
276
360
|
const [noteHashTree, nullifierTree, contractTree, l1ToL2MessagesTree, blocksTree, publicDataTree] = await Promise.all([
|
|
277
361
|
getTreeRoot(MerkleTreeId.NOTE_HASH_TREE),
|
|
@@ -291,13 +375,13 @@ export class AztecNodeService {
|
|
|
291
375
|
};
|
|
292
376
|
}
|
|
293
377
|
/**
|
|
294
|
-
* Returns the currently committed
|
|
295
|
-
* @returns The current committed block
|
|
378
|
+
* Returns the currently committed block header.
|
|
379
|
+
* @returns The current committed block header.
|
|
296
380
|
*/
|
|
297
|
-
async
|
|
298
|
-
const committedDb = await __classPrivateFieldGet(this, _AztecNodeService_instances, "m", _AztecNodeService_getWorldState).call(this);
|
|
381
|
+
async getBlockHeader() {
|
|
382
|
+
const committedDb = await __classPrivateFieldGet(this, _AztecNodeService_instances, "m", _AztecNodeService_getWorldState).call(this, 'latest');
|
|
299
383
|
const [roots, globalsHash] = await Promise.all([this.getTreeRoots(), committedDb.getLatestGlobalVariablesHash()]);
|
|
300
|
-
return new
|
|
384
|
+
return new BlockHeader(roots[MerkleTreeId.NOTE_HASH_TREE], roots[MerkleTreeId.NULLIFIER_TREE], roots[MerkleTreeId.CONTRACT_TREE], roots[MerkleTreeId.L1_TO_L2_MESSAGES_TREE], roots[MerkleTreeId.BLOCKS_TREE], Fr.ZERO, roots[MerkleTreeId.PUBLIC_DATA_TREE], globalsHash);
|
|
301
385
|
}
|
|
302
386
|
/**
|
|
303
387
|
* Simulates the public part of a transaction with the current state.
|
|
@@ -312,8 +396,9 @@ export class AztecNodeService {
|
|
|
312
396
|
// TODO we should be able to remove this after https://github.com/AztecProtocol/aztec-packages/issues/1869
|
|
313
397
|
// So simulation of public functions doesn't affect the merkle trees.
|
|
314
398
|
const merkleTrees = new MerkleTrees(this.merkleTreesDb, this.log);
|
|
399
|
+
const globalVariablesHash = computeGlobalsHash(prevGlobalVariables);
|
|
315
400
|
await merkleTrees.init({
|
|
316
|
-
|
|
401
|
+
globalVariablesHash,
|
|
317
402
|
});
|
|
318
403
|
const publicProcessorFactory = new PublicProcessorFactory(merkleTrees.asLatest(), this.contractDataSource, this.l1ToL2MessageSource);
|
|
319
404
|
const processor = await publicProcessorFactory.create(prevGlobalVariables, newGlobalVariables);
|
|
@@ -331,17 +416,33 @@ export class AztecNodeService {
|
|
|
331
416
|
_AztecNodeService_instances = new WeakSet(), _AztecNodeService_getWorldState =
|
|
332
417
|
/**
|
|
333
418
|
* Returns an instance of MerkleTreeOperations having first ensured the world state is fully synched
|
|
419
|
+
* @param blockNumber - The block number at which to get the data.
|
|
334
420
|
* @returns An instance of a committed MerkleTreeOperations
|
|
335
421
|
*/
|
|
336
|
-
async function _AztecNodeService_getWorldState() {
|
|
422
|
+
async function _AztecNodeService_getWorldState(blockNumber) {
|
|
423
|
+
if (typeof blockNumber === 'number' && blockNumber < INITIAL_L2_BLOCK_NUM) {
|
|
424
|
+
throw new Error('Invalid block number to get world state for: ' + blockNumber);
|
|
425
|
+
}
|
|
426
|
+
let blockSyncedTo = 0;
|
|
337
427
|
try {
|
|
338
428
|
// Attempt to sync the world state if necessary
|
|
339
|
-
await __classPrivateFieldGet(this, _AztecNodeService_instances, "m", _AztecNodeService_syncWorldState).call(this);
|
|
429
|
+
blockSyncedTo = await __classPrivateFieldGet(this, _AztecNodeService_instances, "m", _AztecNodeService_syncWorldState).call(this);
|
|
340
430
|
}
|
|
341
431
|
catch (err) {
|
|
342
432
|
this.log.error(`Error getting world state: ${err}`);
|
|
343
433
|
}
|
|
344
|
-
|
|
434
|
+
// using a snapshot could be less efficient than using the committed db
|
|
435
|
+
if (blockNumber === 'latest' || blockNumber === blockSyncedTo) {
|
|
436
|
+
this.log(`Using committed db for block ${blockNumber}, world state synced upto ${blockSyncedTo}`);
|
|
437
|
+
return this.worldStateSynchronizer.getCommitted();
|
|
438
|
+
}
|
|
439
|
+
else if (blockNumber < blockSyncedTo) {
|
|
440
|
+
this.log(`Using snapshot for block ${blockNumber}, world state synced upto ${blockSyncedTo}`);
|
|
441
|
+
return this.worldStateSynchronizer.getSnapshot(blockNumber);
|
|
442
|
+
}
|
|
443
|
+
else {
|
|
444
|
+
throw new Error(`Block ${blockNumber} not yet synced`);
|
|
445
|
+
}
|
|
345
446
|
}, _AztecNodeService_syncWorldState =
|
|
346
447
|
/**
|
|
347
448
|
* Ensure we fully sync the world state
|
|
@@ -349,6 +450,6 @@ async function _AztecNodeService_getWorldState() {
|
|
|
349
450
|
*/
|
|
350
451
|
async function _AztecNodeService_syncWorldState() {
|
|
351
452
|
const blockSourceHeight = await this.blockSource.getBlockNumber();
|
|
352
|
-
|
|
453
|
+
return this.worldStateSynchronizer.syncImmediate(blockSourceHeight);
|
|
353
454
|
};
|
|
354
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2F6dGVjLW5vZGUvc2VydmVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQzNDLE9BQU8sRUFFTCxFQUFFLEVBQ0YsZUFBZSxFQUNmLGlCQUFpQixHQUdsQixNQUFNLG9CQUFvQixDQUFDO0FBQzVCLE9BQU8sRUFBRSwwQkFBMEIsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ3JFLE9BQU8sRUFBdUIsbUJBQW1CLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUUzRSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUMxRCxPQUFPLEVBQUUsY0FBYyxFQUFPLGVBQWUsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUNsRSxPQUFPLEVBRUwsc0JBQXNCLEVBQ3RCLGVBQWUsRUFDZix3QkFBd0IsR0FDekIsTUFBTSx5QkFBeUIsQ0FBQztBQUNqQyxPQUFPLEVBTUwscUJBQXFCLEVBUXJCLE9BQU8sRUFDUCxZQUFZLEdBS2IsTUFBTSxjQUFjLENBQUM7QUFDdEIsT0FBTyxFQUNMLFdBQVcsRUFDWCw0QkFBNEIsRUFHNUIsZ0JBQWdCLElBQUksbUJBQW1CLEdBQ3hDLE1BQU0sb0JBQW9CLENBQUM7QUFLNUIsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUVqQzs7R0FFRztBQUNILE1BQU0sT0FBTyxnQkFBZ0I7SUFDM0IsWUFDcUIsTUFBdUIsRUFDdkIsU0FBYyxFQUNkLFdBQTBCLEVBQzFCLG1CQUFpQyxFQUNqQyxxQkFBbUMsRUFDbkMsa0JBQXNDLEVBQ3RDLG1CQUF3QyxFQUN4QyxzQkFBOEMsRUFDOUMsU0FBc0MsRUFDdEMsT0FBZSxFQUNmLE9BQWUsRUFDZixxQkFBNEMsRUFDNUMsYUFBOEIsRUFDekMsTUFBTSxpQkFBaUIsQ0FBQyxZQUFZLENBQUM7O1FB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
|
|
455
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2F6dGVjLW5vZGUvc2VydmVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsT0FBTyxFQUFFLFFBQVEsRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQzlELE9BQU8sRUFFTCxXQUFXLEVBRVgsRUFBRSxFQUNGLGVBQWUsR0FNaEIsTUFBTSxvQkFBb0IsQ0FBQztBQUM1QixPQUFPLEVBQUUsa0JBQWtCLEVBQUUsMEJBQTBCLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUN6RixPQUFPLEVBQXVCLG1CQUFtQixFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFFM0UsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDMUQsT0FBTyxFQUFFLGNBQWMsRUFBTyxlQUFlLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFDbEUsT0FBTyxFQUVMLHNCQUFzQixFQUN0QixlQUFlLEVBQ2Ysd0JBQXdCLEdBQ3pCLE1BQU0seUJBQXlCLENBQUM7QUFDakMsT0FBTyxFQU1MLG9CQUFvQixFQUNwQixxQkFBcUIsRUFRckIsT0FBTyxFQUNQLFlBQVksRUFDWiwwQkFBMEIsR0FLM0IsTUFBTSxjQUFjLENBQUM7QUFDdEIsT0FBTyxFQUNMLFdBQVcsRUFDWCw0QkFBNEIsRUFHNUIsZ0JBQWdCLElBQUksbUJBQW1CLEdBQ3hDLE1BQU0sb0JBQW9CLENBQUM7QUFLNUIsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUVqQzs7R0FFRztBQUNILE1BQU0sT0FBTyxnQkFBZ0I7SUFDM0IsWUFDcUIsTUFBdUIsRUFDdkIsU0FBYyxFQUNkLFdBQTBCLEVBQzFCLG1CQUFpQyxFQUNqQyxxQkFBbUMsRUFDbkMsa0JBQXNDLEVBQ3RDLG1CQUF3QyxFQUN4QyxzQkFBOEMsRUFDOUMsU0FBc0MsRUFDdEMsT0FBZSxFQUNmLE9BQWUsRUFDZixxQkFBNEMs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
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aztec/aztec-node",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.2",
|
|
4
4
|
"main": "dest/index.js",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": "./dest/index.js",
|
|
@@ -33,19 +33,20 @@
|
|
|
33
33
|
"rootDir": "./src"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@aztec/archiver": "0.16.
|
|
37
|
-
"@aztec/circuits.js": "0.16.
|
|
38
|
-
"@aztec/ethereum": "0.16.
|
|
39
|
-
"@aztec/foundation": "0.16.
|
|
40
|
-
"@aztec/l1-artifacts": "0.16.
|
|
41
|
-
"@aztec/merkle-tree": "0.16.
|
|
42
|
-
"@aztec/p2p": "0.16.
|
|
43
|
-
"@aztec/sequencer-client": "0.16.
|
|
44
|
-
"@aztec/types": "0.16.
|
|
45
|
-
"@aztec/world-state": "0.16.
|
|
36
|
+
"@aztec/archiver": "0.16.2",
|
|
37
|
+
"@aztec/circuits.js": "0.16.2",
|
|
38
|
+
"@aztec/ethereum": "0.16.2",
|
|
39
|
+
"@aztec/foundation": "0.16.2",
|
|
40
|
+
"@aztec/l1-artifacts": "0.16.2",
|
|
41
|
+
"@aztec/merkle-tree": "0.16.2",
|
|
42
|
+
"@aztec/p2p": "0.16.2",
|
|
43
|
+
"@aztec/sequencer-client": "0.16.2",
|
|
44
|
+
"@aztec/types": "0.16.2",
|
|
45
|
+
"@aztec/world-state": "0.16.2",
|
|
46
46
|
"koa": "^2.14.2",
|
|
47
47
|
"koa-router": "^12.0.0",
|
|
48
48
|
"levelup": "^5.1.1",
|
|
49
|
+
"lmdb": "^2.9.1",
|
|
49
50
|
"memdown": "^6.1.1",
|
|
50
51
|
"tslib": "^2.4.0"
|
|
51
52
|
},
|
package/src/aztec-node/db.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import { LogFn } from '@aztec/foundation/log';
|
|
2
|
+
|
|
1
3
|
import { LevelDown, default as leveldown } from 'leveldown';
|
|
2
4
|
import { LevelUp, default as levelup } from 'levelup';
|
|
5
|
+
import { RootDatabase, open } from 'lmdb';
|
|
3
6
|
import { MemDown, default as memdown } from 'memdown';
|
|
4
7
|
import { mkdir } from 'node:fs/promises';
|
|
5
8
|
import { join } from 'node:path';
|
|
@@ -10,6 +13,7 @@ export const createMemDown = () => (memdown as any)() as MemDown<any, any>;
|
|
|
10
13
|
export const createLevelDown = (path: string) => (leveldown as any)(path) as LevelDown;
|
|
11
14
|
|
|
12
15
|
const DB_SUBDIR = 'aztec-node';
|
|
16
|
+
const WORLD_STATE_SUBDIR = 'aztec-world-state';
|
|
13
17
|
const NODE_METADATA_KEY = '@@aztec_node_metadata';
|
|
14
18
|
|
|
15
19
|
/**
|
|
@@ -28,45 +32,61 @@ type NodeMetadata = {
|
|
|
28
32
|
* @throws If `config.dataDirectory` is set and the directory cannot be created.
|
|
29
33
|
* @returns The database for the aztec node.
|
|
30
34
|
*/
|
|
31
|
-
export async function openDb(
|
|
35
|
+
export async function openDb(
|
|
36
|
+
config: AztecNodeConfig,
|
|
37
|
+
log: LogFn,
|
|
38
|
+
): Promise<[nodeDb: RootDatabase, worldStateDb: LevelUp]> {
|
|
32
39
|
const nodeMetadata: NodeMetadata = {
|
|
33
40
|
rollupContractAddress: config.l1Contracts.rollupAddress.toString(),
|
|
34
41
|
};
|
|
35
42
|
|
|
36
|
-
let
|
|
43
|
+
let nodeDb: RootDatabase;
|
|
44
|
+
let worldStateDb: LevelUp;
|
|
37
45
|
|
|
38
46
|
if (config.dataDirectory) {
|
|
39
|
-
const
|
|
47
|
+
const nodeDir = join(config.dataDirectory, DB_SUBDIR);
|
|
48
|
+
const worldStateDir = join(config.dataDirectory, WORLD_STATE_SUBDIR);
|
|
40
49
|
// this throws if we don't have permissions to create the directory
|
|
41
|
-
await mkdir(
|
|
42
|
-
|
|
43
|
-
} else {
|
|
44
|
-
db = levelup(createMemDown());
|
|
45
|
-
}
|
|
50
|
+
await mkdir(nodeDir, { recursive: true });
|
|
51
|
+
await mkdir(worldStateDir, { recursive: true });
|
|
46
52
|
|
|
47
|
-
|
|
53
|
+
log(`Opening aztec-node database at ${nodeDir}`);
|
|
54
|
+
nodeDb = open(nodeDir, {});
|
|
48
55
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
56
|
+
log(`Opening world-state database at ${worldStateDir}`);
|
|
57
|
+
worldStateDb = levelup(createLevelDown(worldStateDir));
|
|
58
|
+
} else {
|
|
59
|
+
log('Opening temporary databases');
|
|
60
|
+
// not passing a path will use a temp file that gets deleted when the process exits
|
|
61
|
+
nodeDb = open({});
|
|
62
|
+
worldStateDb = levelup(createMemDown());
|
|
52
63
|
}
|
|
53
64
|
|
|
54
|
-
await
|
|
55
|
-
return
|
|
65
|
+
await checkNodeMetadataAndClear(nodeDb, worldStateDb, nodeMetadata, log);
|
|
66
|
+
return [nodeDb, worldStateDb];
|
|
56
67
|
}
|
|
57
68
|
|
|
58
69
|
/**
|
|
59
|
-
*
|
|
60
|
-
* @param
|
|
61
|
-
* @
|
|
70
|
+
* Checks the node metadata and clears the database if the rollup contract address has changed.
|
|
71
|
+
* @param nodeDb - The database for the aztec node.
|
|
72
|
+
* @param nodeMetadata - The metadata for the aztec node.
|
|
62
73
|
*/
|
|
63
|
-
async function
|
|
74
|
+
async function checkNodeMetadataAndClear(
|
|
75
|
+
nodeDb: RootDatabase,
|
|
76
|
+
worldStateDb: LevelUp,
|
|
77
|
+
nodeMetadata: NodeMetadata,
|
|
78
|
+
log: LogFn,
|
|
79
|
+
): Promise<void> {
|
|
80
|
+
const metadataDB = nodeDb.openDB<NodeMetadata, string>('metadata', {});
|
|
64
81
|
try {
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
82
|
+
const existing = metadataDB.get(NODE_METADATA_KEY);
|
|
83
|
+
// if the rollup addresses are different, wipe the local database and start over
|
|
84
|
+
if (!existing || existing.rollupContractAddress !== nodeMetadata.rollupContractAddress) {
|
|
85
|
+
log('Rollup contract address has changed, clearing databases');
|
|
86
|
+
await Promise.all([nodeDb.clearAsync(), worldStateDb.clear()]);
|
|
87
|
+
}
|
|
88
|
+
await metadataDB.put(NODE_METADATA_KEY, nodeMetadata);
|
|
89
|
+
} finally {
|
|
90
|
+
await metadataDB.close();
|
|
71
91
|
}
|
|
72
92
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BlockHeader, FunctionSelector } from '@aztec/circuits.js';
|
|
2
2
|
import { AztecAddress } from '@aztec/foundation/aztec-address';
|
|
3
3
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
4
4
|
import { Fr } from '@aztec/foundation/fields';
|
|
@@ -34,7 +34,7 @@ export function createAztecNodeRpcServer(node: AztecNode) {
|
|
|
34
34
|
ContractData,
|
|
35
35
|
Fr,
|
|
36
36
|
FunctionSelector,
|
|
37
|
-
|
|
37
|
+
BlockHeader,
|
|
38
38
|
L2Block,
|
|
39
39
|
L2Tx,
|
|
40
40
|
LogId,
|
package/src/aztec-node/server.ts
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
|
-
import { Archiver } from '@aztec/archiver';
|
|
1
|
+
import { Archiver, LMDBArchiverStore } from '@aztec/archiver';
|
|
2
2
|
import {
|
|
3
|
+
BLOCKS_TREE_HEIGHT,
|
|
4
|
+
BlockHeader,
|
|
3
5
|
CONTRACT_TREE_HEIGHT,
|
|
4
6
|
Fr,
|
|
5
7
|
GlobalVariables,
|
|
6
|
-
HistoricBlockData,
|
|
7
8
|
L1_TO_L2_MSG_TREE_HEIGHT,
|
|
8
9
|
NOTE_HASH_TREE_HEIGHT,
|
|
10
|
+
NULLIFIER_TREE_HEIGHT,
|
|
11
|
+
NullifierLeafPreimage,
|
|
12
|
+
PUBLIC_DATA_TREE_HEIGHT,
|
|
9
13
|
} from '@aztec/circuits.js';
|
|
10
|
-
import { computePublicDataTreeIndex } from '@aztec/circuits.js/abis';
|
|
14
|
+
import { computeGlobalsHash, computePublicDataTreeIndex } from '@aztec/circuits.js/abis';
|
|
11
15
|
import { L1ContractAddresses, createEthereumChain } from '@aztec/ethereum';
|
|
12
16
|
import { AztecAddress } from '@aztec/foundation/aztec-address';
|
|
13
17
|
import { createDebugLogger } from '@aztec/foundation/log';
|
|
@@ -24,6 +28,7 @@ import {
|
|
|
24
28
|
ContractDataSource,
|
|
25
29
|
ExtendedContractData,
|
|
26
30
|
GetUnencryptedLogsResponse,
|
|
31
|
+
INITIAL_L2_BLOCK_NUM,
|
|
27
32
|
L1ToL2MessageAndIndex,
|
|
28
33
|
L1ToL2MessageSource,
|
|
29
34
|
L2Block,
|
|
@@ -34,6 +39,7 @@ import {
|
|
|
34
39
|
LogFilter,
|
|
35
40
|
LogType,
|
|
36
41
|
MerkleTreeId,
|
|
42
|
+
NullifierMembershipWitness,
|
|
37
43
|
SequencerConfig,
|
|
38
44
|
SiblingPath,
|
|
39
45
|
Tx,
|
|
@@ -47,7 +53,7 @@ import {
|
|
|
47
53
|
getConfigEnvVars as getWorldStateConfig,
|
|
48
54
|
} from '@aztec/world-state';
|
|
49
55
|
|
|
50
|
-
import
|
|
56
|
+
import { LevelUp } from 'levelup';
|
|
51
57
|
|
|
52
58
|
import { AztecNodeConfig } from './config.js';
|
|
53
59
|
import { openDb } from './db.js';
|
|
@@ -69,7 +75,7 @@ export class AztecNodeService implements AztecNode {
|
|
|
69
75
|
protected readonly chainId: number,
|
|
70
76
|
protected readonly version: number,
|
|
71
77
|
protected readonly globalVariableBuilder: GlobalVariableBuilder,
|
|
72
|
-
protected readonly merkleTreesDb:
|
|
78
|
+
protected readonly merkleTreesDb: LevelUp,
|
|
73
79
|
private log = createDebugLogger('aztec:node'),
|
|
74
80
|
) {
|
|
75
81
|
const message =
|
|
@@ -95,8 +101,13 @@ export class AztecNodeService implements AztecNode {
|
|
|
95
101
|
`RPC URL configured for chain id ${ethereumChain.chainInfo.id} but expected id ${config.chainId}`,
|
|
96
102
|
);
|
|
97
103
|
}
|
|
104
|
+
|
|
105
|
+
const log = createDebugLogger('aztec:node');
|
|
106
|
+
const [nodeDb, worldStateDb] = await openDb(config, log);
|
|
107
|
+
|
|
98
108
|
// first create and sync the archiver
|
|
99
|
-
const
|
|
109
|
+
const archiverStore = new LMDBArchiverStore(nodeDb, config.maxLogs);
|
|
110
|
+
const archiver = await Archiver.createAndSync(config, archiverStore, true);
|
|
100
111
|
|
|
101
112
|
// we identify the P2P transaction protocol by using the rollup contract address.
|
|
102
113
|
// this may well change in future
|
|
@@ -106,10 +117,14 @@ export class AztecNodeService implements AztecNode {
|
|
|
106
117
|
const p2pClient = await createP2PClient(config, new InMemoryTxPool(), archiver);
|
|
107
118
|
|
|
108
119
|
// now create the merkle trees and the world state synchronizer
|
|
109
|
-
const
|
|
110
|
-
const merkleTrees = await MerkleTrees.new(db);
|
|
120
|
+
const merkleTrees = await MerkleTrees.new(worldStateDb);
|
|
111
121
|
const worldStateConfig: WorldStateConfig = getWorldStateConfig();
|
|
112
|
-
const worldStateSynchronizer = await ServerWorldStateSynchronizer.new(
|
|
122
|
+
const worldStateSynchronizer = await ServerWorldStateSynchronizer.new(
|
|
123
|
+
worldStateDb,
|
|
124
|
+
merkleTrees,
|
|
125
|
+
archiver,
|
|
126
|
+
worldStateConfig,
|
|
127
|
+
);
|
|
113
128
|
|
|
114
129
|
// start both and wait for them to sync from the block source
|
|
115
130
|
await Promise.all([p2pClient.start(), worldStateSynchronizer.start()]);
|
|
@@ -132,7 +147,8 @@ export class AztecNodeService implements AztecNode {
|
|
|
132
147
|
ethereumChain.chainInfo.id,
|
|
133
148
|
config.version,
|
|
134
149
|
getGlobalVariableBuilder(config),
|
|
135
|
-
|
|
150
|
+
worldStateDb,
|
|
151
|
+
log,
|
|
136
152
|
);
|
|
137
153
|
}
|
|
138
154
|
|
|
@@ -161,9 +177,9 @@ export class AztecNodeService implements AztecNode {
|
|
|
161
177
|
}
|
|
162
178
|
|
|
163
179
|
/**
|
|
164
|
-
* Get
|
|
180
|
+
* Get a block specified by its number.
|
|
165
181
|
* @param number - The block number being requested.
|
|
166
|
-
* @returns The
|
|
182
|
+
* @returns The requested block.
|
|
167
183
|
*/
|
|
168
184
|
public async getBlock(number: number): Promise<L2Block | undefined> {
|
|
169
185
|
return await this.blockSource.getBlock(number);
|
|
@@ -287,32 +303,59 @@ export class AztecNodeService implements AztecNode {
|
|
|
287
303
|
|
|
288
304
|
/**
|
|
289
305
|
* Find the index of the given leaf in the given tree.
|
|
306
|
+
* @param blockNumber - The block number at which to get the data
|
|
290
307
|
* @param treeId - The tree to search in.
|
|
291
308
|
* @param leafValue - The value to search for
|
|
292
309
|
* @returns The index of the given leaf in the given tree or undefined if not found.
|
|
293
310
|
*/
|
|
294
|
-
public async findLeafIndex(
|
|
295
|
-
|
|
311
|
+
public async findLeafIndex(
|
|
312
|
+
blockNumber: number | 'latest',
|
|
313
|
+
treeId: MerkleTreeId,
|
|
314
|
+
leafValue: Fr,
|
|
315
|
+
): Promise<bigint | undefined> {
|
|
316
|
+
const committedDb = await this.#getWorldState(blockNumber);
|
|
296
317
|
return committedDb.findLeafIndex(treeId, leafValue.toBuffer());
|
|
297
318
|
}
|
|
298
319
|
|
|
299
320
|
/**
|
|
300
|
-
* Returns
|
|
321
|
+
* Returns a sibling path for the given index in the contract tree.
|
|
322
|
+
* @param blockNumber - The block number at which to get the data.
|
|
301
323
|
* @param leafIndex - The index of the leaf for which the sibling path is required.
|
|
302
324
|
* @returns The sibling path for the leaf index.
|
|
303
325
|
*/
|
|
304
|
-
public async getContractSiblingPath(
|
|
305
|
-
|
|
326
|
+
public async getContractSiblingPath(
|
|
327
|
+
blockNumber: number | 'latest',
|
|
328
|
+
leafIndex: bigint,
|
|
329
|
+
): Promise<SiblingPath<typeof CONTRACT_TREE_HEIGHT>> {
|
|
330
|
+
const committedDb = await this.#getWorldState(blockNumber);
|
|
306
331
|
return committedDb.getSiblingPath(MerkleTreeId.CONTRACT_TREE, leafIndex);
|
|
307
332
|
}
|
|
308
333
|
|
|
309
334
|
/**
|
|
310
|
-
* Returns
|
|
335
|
+
* Returns a sibling path for the given index in the nullifier tree.
|
|
336
|
+
* @param blockNumber - The block number at which to get the data.
|
|
337
|
+
* @param leafIndex - The index of the leaf for which the sibling path is required.
|
|
338
|
+
* @returns The sibling path for the leaf index.
|
|
339
|
+
*/
|
|
340
|
+
public async getNullifierTreeSiblingPath(
|
|
341
|
+
blockNumber: number | 'latest',
|
|
342
|
+
leafIndex: bigint,
|
|
343
|
+
): Promise<SiblingPath<typeof NULLIFIER_TREE_HEIGHT>> {
|
|
344
|
+
const committedDb = await this.#getWorldState(blockNumber);
|
|
345
|
+
return committedDb.getSiblingPath(MerkleTreeId.NULLIFIER_TREE, leafIndex);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Returns a sibling path for the given index in the data tree.
|
|
350
|
+
* @param blockNumber - The block number at which to get the data.
|
|
311
351
|
* @param leafIndex - The index of the leaf for which the sibling path is required.
|
|
312
352
|
* @returns The sibling path for the leaf index.
|
|
313
353
|
*/
|
|
314
|
-
public async getNoteHashSiblingPath(
|
|
315
|
-
|
|
354
|
+
public async getNoteHashSiblingPath(
|
|
355
|
+
blockNumber: number | 'latest',
|
|
356
|
+
leafIndex: bigint,
|
|
357
|
+
): Promise<SiblingPath<typeof NOTE_HASH_TREE_HEIGHT>> {
|
|
358
|
+
const committedDb = await this.#getWorldState(blockNumber);
|
|
316
359
|
return committedDb.getSiblingPath(MerkleTreeId.NOTE_HASH_TREE, leafIndex);
|
|
317
360
|
}
|
|
318
361
|
|
|
@@ -324,21 +367,120 @@ export class AztecNodeService implements AztecNode {
|
|
|
324
367
|
*/
|
|
325
368
|
public async getL1ToL2MessageAndIndex(messageKey: Fr): Promise<L1ToL2MessageAndIndex> {
|
|
326
369
|
// todo: #697 - make this one lookup.
|
|
327
|
-
const index = (await this.findLeafIndex(MerkleTreeId.L1_TO_L2_MESSAGES_TREE, messageKey))!;
|
|
370
|
+
const index = (await this.findLeafIndex('latest', MerkleTreeId.L1_TO_L2_MESSAGES_TREE, messageKey))!;
|
|
328
371
|
const message = await this.l1ToL2MessageSource.getConfirmedL1ToL2Message(messageKey);
|
|
329
372
|
return Promise.resolve(new L1ToL2MessageAndIndex(index, message));
|
|
330
373
|
}
|
|
331
374
|
|
|
332
375
|
/**
|
|
333
|
-
* Returns
|
|
376
|
+
* Returns a sibling path for a leaf in the committed l1 to l2 data tree.
|
|
377
|
+
* @param blockNumber - The block number at which to get the data.
|
|
334
378
|
* @param leafIndex - Index of the leaf in the tree.
|
|
335
379
|
* @returns The sibling path.
|
|
336
380
|
*/
|
|
337
|
-
public async getL1ToL2MessageSiblingPath(
|
|
338
|
-
|
|
381
|
+
public async getL1ToL2MessageSiblingPath(
|
|
382
|
+
blockNumber: number | 'latest',
|
|
383
|
+
leafIndex: bigint,
|
|
384
|
+
): Promise<SiblingPath<typeof L1_TO_L2_MSG_TREE_HEIGHT>> {
|
|
385
|
+
const committedDb = await this.#getWorldState(blockNumber);
|
|
339
386
|
return committedDb.getSiblingPath(MerkleTreeId.L1_TO_L2_MESSAGES_TREE, leafIndex);
|
|
340
387
|
}
|
|
341
388
|
|
|
389
|
+
/**
|
|
390
|
+
* Returns a sibling path for a leaf in the committed blocks tree.
|
|
391
|
+
* @param blockNumber - The block number at which to get the data.
|
|
392
|
+
* @param leafIndex - Index of the leaf in the tree.
|
|
393
|
+
* @returns The sibling path.
|
|
394
|
+
*/
|
|
395
|
+
public async getBlocksTreeSiblingPath(
|
|
396
|
+
blockNumber: number | 'latest',
|
|
397
|
+
leafIndex: bigint,
|
|
398
|
+
): Promise<SiblingPath<typeof BLOCKS_TREE_HEIGHT>> {
|
|
399
|
+
const committedDb = await this.#getWorldState(blockNumber);
|
|
400
|
+
return committedDb.getSiblingPath(MerkleTreeId.BLOCKS_TREE, leafIndex);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Returns a sibling path for a leaf in the committed public data tree.
|
|
405
|
+
* @param blockNumber - The block number at which to get the data.
|
|
406
|
+
* @param leafIndex - Index of the leaf in the tree.
|
|
407
|
+
* @returns The sibling path.
|
|
408
|
+
*/
|
|
409
|
+
public async getPublicDataTreeSiblingPath(
|
|
410
|
+
blockNumber: number | 'latest',
|
|
411
|
+
leafIndex: bigint,
|
|
412
|
+
): Promise<SiblingPath<typeof PUBLIC_DATA_TREE_HEIGHT>> {
|
|
413
|
+
const committedDb = await this.#getWorldState(blockNumber);
|
|
414
|
+
return committedDb.getSiblingPath(MerkleTreeId.PUBLIC_DATA_TREE, leafIndex);
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* Returns a nullifier membership witness for a given nullifier at a given block.
|
|
419
|
+
* @param blockNumber - The block number at which to get the index.
|
|
420
|
+
* @param nullifier - Nullifier we try to find witness for.
|
|
421
|
+
* @returns The nullifier membership witness (if found).
|
|
422
|
+
*/
|
|
423
|
+
public async getNullifierMembershipWitness(
|
|
424
|
+
blockNumber: number | 'latest',
|
|
425
|
+
nullifier: Fr,
|
|
426
|
+
): Promise<NullifierMembershipWitness | undefined> {
|
|
427
|
+
const db = await this.#getWorldState(blockNumber);
|
|
428
|
+
const index = await db.findLeafIndex(MerkleTreeId.NULLIFIER_TREE, nullifier.toBuffer());
|
|
429
|
+
if (!index) {
|
|
430
|
+
return undefined;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
const leafPreimagePromise = db.getLeafPreimage(MerkleTreeId.NULLIFIER_TREE, index);
|
|
434
|
+
const siblingPathPromise = db.getSiblingPath<typeof NULLIFIER_TREE_HEIGHT>(
|
|
435
|
+
MerkleTreeId.NULLIFIER_TREE,
|
|
436
|
+
BigInt(index),
|
|
437
|
+
);
|
|
438
|
+
|
|
439
|
+
const [leafPreimage, siblingPath] = await Promise.all([leafPreimagePromise, siblingPathPromise]);
|
|
440
|
+
|
|
441
|
+
if (!leafPreimage) {
|
|
442
|
+
return undefined;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
return new NullifierMembershipWitness(BigInt(index), leafPreimage as NullifierLeafPreimage, siblingPath);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
/**
|
|
449
|
+
* Returns a low nullifier membership witness for a given nullifier at a given block.
|
|
450
|
+
* @param blockNumber - The block number at which to get the index.
|
|
451
|
+
* @param nullifier - Nullifier we try to find the low nullifier witness for.
|
|
452
|
+
* @returns The low nullifier membership witness (if found).
|
|
453
|
+
* @remarks Low nullifier witness can be used to perform a nullifier non-inclusion proof by leveraging the "linked
|
|
454
|
+
* list structure" of leaves and proving that a lower nullifier is pointing to a bigger next value than the nullifier
|
|
455
|
+
* we are trying to prove non-inclusion for.
|
|
456
|
+
*
|
|
457
|
+
* Note: This function returns the membership witness of the nullifier itself and not the low nullifier when
|
|
458
|
+
* the nullifier already exists in the tree. This is because the `getPreviousValueIndex` function returns the
|
|
459
|
+
* index of the nullifier itself when it already exists in the tree.
|
|
460
|
+
* TODO: This is a confusing behavior and we should eventually address that.
|
|
461
|
+
*/
|
|
462
|
+
public async getLowNullifierMembershipWitness(
|
|
463
|
+
blockNumber: number | 'latest',
|
|
464
|
+
nullifier: Fr,
|
|
465
|
+
): Promise<NullifierMembershipWitness | undefined> {
|
|
466
|
+
const committedDb = await this.#getWorldState(blockNumber);
|
|
467
|
+
const findResult = await committedDb.getPreviousValueIndex(MerkleTreeId.NULLIFIER_TREE, nullifier.toBigInt());
|
|
468
|
+
if (!findResult) {
|
|
469
|
+
return undefined;
|
|
470
|
+
}
|
|
471
|
+
const { index, alreadyPresent } = findResult;
|
|
472
|
+
if (alreadyPresent) {
|
|
473
|
+
this.log.warn(`Nullifier ${nullifier.toBigInt()} already exists in the tree`);
|
|
474
|
+
}
|
|
475
|
+
const preimageData = (await committedDb.getLeafPreimage(MerkleTreeId.NULLIFIER_TREE, index))!;
|
|
476
|
+
|
|
477
|
+
const siblingPath = await committedDb.getSiblingPath<typeof NULLIFIER_TREE_HEIGHT>(
|
|
478
|
+
MerkleTreeId.NULLIFIER_TREE,
|
|
479
|
+
BigInt(index),
|
|
480
|
+
);
|
|
481
|
+
return new NullifierMembershipWitness(BigInt(index), preimageData as NullifierLeafPreimage, siblingPath);
|
|
482
|
+
}
|
|
483
|
+
|
|
342
484
|
/**
|
|
343
485
|
* Gets the storage value at the given contract storage slot.
|
|
344
486
|
*
|
|
@@ -350,7 +492,7 @@ export class AztecNodeService implements AztecNode {
|
|
|
350
492
|
* @returns Storage value at the given contract slot (or undefined if not found).
|
|
351
493
|
*/
|
|
352
494
|
public async getPublicStorageAt(contract: AztecAddress, slot: Fr): Promise<Fr | undefined> {
|
|
353
|
-
const committedDb = await this.#getWorldState();
|
|
495
|
+
const committedDb = await this.#getWorldState('latest');
|
|
354
496
|
const leafIndex = computePublicDataTreeIndex(contract, slot);
|
|
355
497
|
const value = await committedDb.getLeafValue(MerkleTreeId.PUBLIC_DATA_TREE, leafIndex.value);
|
|
356
498
|
return value ? Fr.fromBuffer(value) : undefined;
|
|
@@ -361,7 +503,7 @@ export class AztecNodeService implements AztecNode {
|
|
|
361
503
|
* @returns The current committed roots for the data trees.
|
|
362
504
|
*/
|
|
363
505
|
public async getTreeRoots(): Promise<Record<MerkleTreeId, Fr>> {
|
|
364
|
-
const committedDb = await this.#getWorldState();
|
|
506
|
+
const committedDb = await this.#getWorldState('latest');
|
|
365
507
|
const getTreeRoot = async (id: MerkleTreeId) => Fr.fromBuffer((await committedDb.getTreeInfo(id)).root);
|
|
366
508
|
|
|
367
509
|
const [noteHashTree, nullifierTree, contractTree, l1ToL2MessagesTree, blocksTree, publicDataTree] =
|
|
@@ -385,14 +527,14 @@ export class AztecNodeService implements AztecNode {
|
|
|
385
527
|
}
|
|
386
528
|
|
|
387
529
|
/**
|
|
388
|
-
* Returns the currently committed
|
|
389
|
-
* @returns The current committed block
|
|
530
|
+
* Returns the currently committed block header.
|
|
531
|
+
* @returns The current committed block header.
|
|
390
532
|
*/
|
|
391
|
-
public async
|
|
392
|
-
const committedDb = await this.#getWorldState();
|
|
533
|
+
public async getBlockHeader(): Promise<BlockHeader> {
|
|
534
|
+
const committedDb = await this.#getWorldState('latest');
|
|
393
535
|
const [roots, globalsHash] = await Promise.all([this.getTreeRoots(), committedDb.getLatestGlobalVariablesHash()]);
|
|
394
536
|
|
|
395
|
-
return new
|
|
537
|
+
return new BlockHeader(
|
|
396
538
|
roots[MerkleTreeId.NOTE_HASH_TREE],
|
|
397
539
|
roots[MerkleTreeId.NULLIFIER_TREE],
|
|
398
540
|
roots[MerkleTreeId.CONTRACT_TREE],
|
|
@@ -418,8 +560,9 @@ export class AztecNodeService implements AztecNode {
|
|
|
418
560
|
// TODO we should be able to remove this after https://github.com/AztecProtocol/aztec-packages/issues/1869
|
|
419
561
|
// So simulation of public functions doesn't affect the merkle trees.
|
|
420
562
|
const merkleTrees = new MerkleTrees(this.merkleTreesDb, this.log);
|
|
563
|
+
const globalVariablesHash = computeGlobalsHash(prevGlobalVariables);
|
|
421
564
|
await merkleTrees.init({
|
|
422
|
-
|
|
565
|
+
globalVariablesHash,
|
|
423
566
|
});
|
|
424
567
|
|
|
425
568
|
const publicProcessorFactory = new PublicProcessorFactory(
|
|
@@ -442,24 +585,40 @@ export class AztecNodeService implements AztecNode {
|
|
|
442
585
|
|
|
443
586
|
/**
|
|
444
587
|
* Returns an instance of MerkleTreeOperations having first ensured the world state is fully synched
|
|
588
|
+
* @param blockNumber - The block number at which to get the data.
|
|
445
589
|
* @returns An instance of a committed MerkleTreeOperations
|
|
446
590
|
*/
|
|
447
|
-
async #getWorldState() {
|
|
591
|
+
async #getWorldState(blockNumber: number | 'latest') {
|
|
592
|
+
if (typeof blockNumber === 'number' && blockNumber < INITIAL_L2_BLOCK_NUM) {
|
|
593
|
+
throw new Error('Invalid block number to get world state for: ' + blockNumber);
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
let blockSyncedTo: number = 0;
|
|
448
597
|
try {
|
|
449
598
|
// Attempt to sync the world state if necessary
|
|
450
|
-
await this.#syncWorldState();
|
|
599
|
+
blockSyncedTo = await this.#syncWorldState();
|
|
451
600
|
} catch (err) {
|
|
452
601
|
this.log.error(`Error getting world state: ${err}`);
|
|
453
602
|
}
|
|
454
|
-
|
|
603
|
+
|
|
604
|
+
// using a snapshot could be less efficient than using the committed db
|
|
605
|
+
if (blockNumber === 'latest' || blockNumber === blockSyncedTo) {
|
|
606
|
+
this.log(`Using committed db for block ${blockNumber}, world state synced upto ${blockSyncedTo}`);
|
|
607
|
+
return this.worldStateSynchronizer.getCommitted();
|
|
608
|
+
} else if (blockNumber < blockSyncedTo) {
|
|
609
|
+
this.log(`Using snapshot for block ${blockNumber}, world state synced upto ${blockSyncedTo}`);
|
|
610
|
+
return this.worldStateSynchronizer.getSnapshot(blockNumber);
|
|
611
|
+
} else {
|
|
612
|
+
throw new Error(`Block ${blockNumber} not yet synced`);
|
|
613
|
+
}
|
|
455
614
|
}
|
|
456
615
|
|
|
457
616
|
/**
|
|
458
617
|
* Ensure we fully sync the world state
|
|
459
618
|
* @returns A promise that fulfils once the world state is synced
|
|
460
619
|
*/
|
|
461
|
-
async #syncWorldState() {
|
|
620
|
+
async #syncWorldState(): Promise<number> {
|
|
462
621
|
const blockSourceHeight = await this.blockSource.getBlockNumber();
|
|
463
|
-
|
|
622
|
+
return this.worldStateSynchronizer.syncImmediate(blockSourceHeight);
|
|
464
623
|
}
|
|
465
624
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
2
|
+
import { RootDatabaseOptionsWithPath } from 'lmdb';
|
|
3
|
+
|
|
4
|
+
// The problem is this snippet `nodeDb = open({});` in src/aztec-node/db.ts
|
|
5
|
+
// tsc compiles this code fine, but ts-jest can't.
|
|
6
|
+
// This is a mixture for two bugs:
|
|
7
|
+
// - the first in ts-jest, it gets confused by packages with mixed CJS and ESM type exports - https://github.com/kulshekhar/ts-jest/issues/4221
|
|
8
|
+
// - the second in lmdb, it outputs different CJS and ESM types - https://github.com/kriszyp/lmdb-js/issues/243#issuecomment-1823585586
|
|
9
|
+
|
|
10
|
+
declare module 'lmdb' {
|
|
11
|
+
/* eslint-disable jsdoc/require-jsdoc */
|
|
12
|
+
interface RootDatabaseOptionsWithPath {
|
|
13
|
+
path?: string;
|
|
14
|
+
}
|
|
15
|
+
/* eslint-enable jsdoc/require-jsdoc */
|
|
16
|
+
}
|