@aztec/aztec 5.0.0-rc.1 → 5.0.0-rc.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/bin/index.js +2 -0
- package/dest/cli/aztec_start_options.js +1 -1
- package/dest/cli/cmds/compile.d.ts +1 -1
- package/dest/cli/cmds/compile.d.ts.map +1 -1
- package/dest/cli/cmds/compile.js +25 -17
- package/dest/cli/cmds/prover.d.ts +4 -0
- package/dest/cli/cmds/prover.d.ts.map +1 -0
- package/dest/cli/cmds/prover.js +24 -0
- package/dest/cli/cmds/standby.d.ts +28 -2
- package/dest/cli/cmds/standby.d.ts.map +1 -1
- package/dest/cli/cmds/standby.js +45 -2
- package/dest/cli/cmds/start_node.d.ts +1 -1
- package/dest/cli/cmds/start_node.d.ts.map +1 -1
- package/dest/cli/cmds/start_node.js +9 -7
- package/dest/cli/cmds/utils/artifacts.d.ts +6 -1
- package/dest/cli/cmds/utils/artifacts.d.ts.map +1 -1
- package/dest/cli/util.d.ts +10 -5
- package/dest/cli/util.d.ts.map +1 -1
- package/dest/cli/util.js +19 -48
- package/dest/local-network/local-network.d.ts +3 -4
- package/dest/local-network/local-network.d.ts.map +1 -1
- package/dest/local-network/local-network.js +3 -3
- package/dest/testing/cheat_codes.d.ts +16 -23
- package/dest/testing/cheat_codes.d.ts.map +1 -1
- package/dest/testing/cheat_codes.js +20 -80
- package/dest/testing/token_allowed_setup.d.ts +9 -4
- package/dest/testing/token_allowed_setup.d.ts.map +1 -1
- package/dest/testing/token_allowed_setup.js +12 -8
- package/package.json +34 -34
- package/scripts/templates/counter/contract/src/main.nr +3 -3
- package/src/bin/index.ts +2 -0
- package/src/cli/aztec_start_options.ts +1 -1
- package/src/cli/cmds/compile.ts +29 -16
- package/src/cli/cmds/prover.ts +42 -0
- package/src/cli/cmds/standby.ts +55 -3
- package/src/cli/cmds/start_node.ts +9 -16
- package/src/cli/cmds/utils/artifacts.ts +5 -0
- package/src/cli/util.ts +20 -61
- package/src/local-network/local-network.ts +3 -3
- package/src/testing/cheat_codes.ts +19 -100
- package/src/testing/token_allowed_setup.ts +15 -8
|
@@ -1,44 +1,37 @@
|
|
|
1
1
|
import { EthCheatCodes, RollupCheatCodes } from '@aztec/ethereum/test';
|
|
2
2
|
import type { DateProvider } from '@aztec/foundation/timer';
|
|
3
|
-
import type { AutomineSequencer } from '@aztec/sequencer-client/automine';
|
|
4
3
|
import type { AztecNode, AztecNodeDebug } from '@aztec/stdlib/interfaces/client';
|
|
5
4
|
/**
|
|
6
|
-
*
|
|
7
|
-
* @deprecated
|
|
8
|
-
* they became unused (we now have better testing tools). If you are introducing a new functionality to the cheat
|
|
9
|
-
* codes, please consider whether it makes sense to just introduce new utils in your tests instead.
|
|
5
|
+
* Wrapper for Aztec Debug API.
|
|
6
|
+
* @deprecated use the AztecNode debug API directly.
|
|
10
7
|
*/
|
|
11
8
|
export declare class CheatCodes {
|
|
12
9
|
/** Cheat codes for L1.*/
|
|
13
10
|
eth: EthCheatCodes;
|
|
14
11
|
/** Cheat codes for the Aztec Rollup contract on L1. */
|
|
15
12
|
rollup: RollupCheatCodes;
|
|
16
|
-
/** When wired, redirects time-warps through the AutomineSequencer queue (test-only). */
|
|
17
|
-
private automine?;
|
|
18
|
-
private logger;
|
|
19
13
|
constructor(
|
|
20
14
|
/** Cheat codes for L1.*/
|
|
21
15
|
eth: EthCheatCodes,
|
|
22
16
|
/** Cheat codes for the Aztec Rollup contract on L1. */
|
|
23
|
-
rollup: RollupCheatCodes
|
|
24
|
-
|
|
25
|
-
automine?: AutomineSequencer | undefined);
|
|
26
|
-
static create(rpcUrls: string[], node: AztecNode, dateProvider: DateProvider, automine?: AutomineSequencer): Promise<CheatCodes>;
|
|
17
|
+
rollup: RollupCheatCodes);
|
|
18
|
+
static create(rpcUrls: string[], node: AztecNode, dateProvider: DateProvider): Promise<CheatCodes>;
|
|
27
19
|
/**
|
|
28
|
-
* Warps the L1 timestamp to
|
|
29
|
-
* the target
|
|
30
|
-
*
|
|
31
|
-
* @param
|
|
32
|
-
* @
|
|
20
|
+
* Warps the L1 timestamp to at least `targetTimestamp` and mines an L2 block advancing the L2 timestamp to at least
|
|
21
|
+
* the target. Forwards to the node's debug API, which serializes the warp through the automine sequencer queue.
|
|
22
|
+
* @param node - The Aztec node whose debug API performs the warp. Must run an automine sequencer.
|
|
23
|
+
* @param targetTimestamp - The target timestamp to warp to (in seconds).
|
|
24
|
+
* @deprecated Call `node.warpL2TimeAtLeastTo(targetTimestamp)` on the node debug API directly.
|
|
33
25
|
*/
|
|
34
26
|
warpL2TimeAtLeastTo(node: AztecNode & AztecNodeDebug, targetTimestamp: bigint | number): Promise<void>;
|
|
35
27
|
/**
|
|
36
|
-
* Warps the L1 timestamp forward by
|
|
37
|
-
* least by the duration.
|
|
38
|
-
*
|
|
39
|
-
* @param node - The Aztec node
|
|
40
|
-
* @param duration - The duration to advance time by (in seconds)
|
|
28
|
+
* Warps the L1 timestamp forward by at least `duration` seconds and mines an L2 block advancing the L2 timestamp at
|
|
29
|
+
* least by the duration. Forwards to the node's debug API, which serializes the warp through the automine sequencer
|
|
30
|
+
* queue.
|
|
31
|
+
* @param node - The Aztec node whose debug API performs the warp. Must run an automine sequencer.
|
|
32
|
+
* @param duration - The duration to advance time by (in seconds).
|
|
33
|
+
* @deprecated Call `node.warpL2TimeAtLeastBy(duration)` on the node debug API directly.
|
|
41
34
|
*/
|
|
42
35
|
warpL2TimeAtLeastBy(node: AztecNode & AztecNodeDebug, duration: bigint | number): Promise<void>;
|
|
43
36
|
}
|
|
44
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
37
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hlYXRfY29kZXMuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90ZXN0aW5nL2NoZWF0X2NvZGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxhQUFhLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUN2RSxPQUFPLEtBQUssRUFBRSxZQUFZLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUM1RCxPQUFPLEtBQUssRUFBRSxTQUFTLEVBQUUsY0FBYyxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFFakY7OztHQUdHO0FBQ0gscUJBQWEsVUFBVTtJQUVuQix5QkFBeUI7SUFDbEIsR0FBRyxFQUFFLGFBQWE7SUFDekIsdURBQXVEO0lBQ2hELE1BQU0sRUFBRSxnQkFBZ0I7SUFKakM7SUFDRSx5QkFBeUI7SUFDbEIsR0FBRyxFQUFFLGFBQWE7SUFDekIsdURBQXVEO0lBQ2hELE1BQU0sRUFBRSxnQkFBZ0IsRUFDN0I7SUFFSixPQUFhLE1BQU0sQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxZQUFZLEVBQUUsWUFBWSxHQUFHLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FPdkc7SUFFRDs7Ozs7O09BTUc7SUFDSCxtQkFBbUIsQ0FBQyxJQUFJLEVBQUUsU0FBUyxHQUFHLGNBQWMsRUFBRSxlQUFlLEVBQUUsTUFBTSxHQUFHLE1BQU0sR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLENBRXJHO0lBRUQ7Ozs7Ozs7T0FPRztJQUNILG1CQUFtQixDQUFDLElBQUksRUFBRSxTQUFTLEdBQUcsY0FBYyxFQUFFLFFBQVEsRUFBRSxNQUFNLEdBQUcsTUFBTSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FFOUY7Q0FDRiJ9
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cheat_codes.d.ts","sourceRoot":"","sources":["../../src/testing/cheat_codes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"cheat_codes.d.ts","sourceRoot":"","sources":["../../src/testing/cheat_codes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACvE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAEjF;;;GAGG;AACH,qBAAa,UAAU;IAEnB,yBAAyB;IAClB,GAAG,EAAE,aAAa;IACzB,uDAAuD;IAChD,MAAM,EAAE,gBAAgB;IAJjC;IACE,yBAAyB;IAClB,GAAG,EAAE,aAAa;IACzB,uDAAuD;IAChD,MAAM,EAAE,gBAAgB,EAC7B;IAEJ,OAAa,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,YAAY,EAAE,YAAY,GAAG,OAAO,CAAC,UAAU,CAAC,CAOvG;IAED;;;;;;OAMG;IACH,mBAAmB,CAAC,IAAI,EAAE,SAAS,GAAG,cAAc,EAAE,eAAe,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAErG;IAED;;;;;;;OAOG;IACH,mBAAmB,CAAC,IAAI,EAAE,SAAS,GAAG,cAAc,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE9F;CACF"}
|
|
@@ -1,96 +1,36 @@
|
|
|
1
1
|
import { EthCheatCodes, RollupCheatCodes } from '@aztec/ethereum/test';
|
|
2
|
-
import { SlotNumber } from '@aztec/foundation/branded-types';
|
|
3
|
-
import { createLogger } from '@aztec/foundation/log';
|
|
4
2
|
/**
|
|
5
|
-
*
|
|
6
|
-
* @deprecated
|
|
7
|
-
* they became unused (we now have better testing tools). If you are introducing a new functionality to the cheat
|
|
8
|
-
* codes, please consider whether it makes sense to just introduce new utils in your tests instead.
|
|
3
|
+
* Wrapper for Aztec Debug API.
|
|
4
|
+
* @deprecated use the AztecNode debug API directly.
|
|
9
5
|
*/ export class CheatCodes {
|
|
10
6
|
eth;
|
|
11
7
|
rollup;
|
|
12
|
-
|
|
13
|
-
logger;
|
|
14
|
-
constructor(/** Cheat codes for L1.*/ eth, /** Cheat codes for the Aztec Rollup contract on L1. */ rollup, /** When wired, redirects time-warps through the AutomineSequencer queue (test-only). */ automine){
|
|
8
|
+
constructor(/** Cheat codes for L1.*/ eth, /** Cheat codes for the Aztec Rollup contract on L1. */ rollup){
|
|
15
9
|
this.eth = eth;
|
|
16
10
|
this.rollup = rollup;
|
|
17
|
-
this.automine = automine;
|
|
18
|
-
this.logger = createLogger('aztecjs:cheat_codes');
|
|
19
11
|
}
|
|
20
|
-
static async create(rpcUrls, node, dateProvider
|
|
12
|
+
static async create(rpcUrls, node, dateProvider) {
|
|
21
13
|
const ethCheatCodes = new EthCheatCodes(rpcUrls, dateProvider);
|
|
22
14
|
const rollupCheatCodes = new RollupCheatCodes(ethCheatCodes, await node.getNodeInfo().then((n)=>n.l1ContractAddresses));
|
|
23
|
-
return new CheatCodes(ethCheatCodes, rollupCheatCodes
|
|
15
|
+
return new CheatCodes(ethCheatCodes, rollupCheatCodes);
|
|
24
16
|
}
|
|
25
17
|
/**
|
|
26
|
-
* Warps the L1 timestamp to
|
|
27
|
-
* the target
|
|
28
|
-
*
|
|
29
|
-
* @param
|
|
30
|
-
* @
|
|
31
|
-
*/
|
|
32
|
-
|
|
33
|
-
const currentTimestamp = BigInt(await this.eth.lastBlockTimestamp());
|
|
34
|
-
if (targetBigInt <= currentTimestamp) {
|
|
35
|
-
throw new Error(`warpL2TimeAtLeastTo: target timestamp ${targetBigInt} is not in the future (current L1 timestamp is ${currentTimestamp}).`);
|
|
36
|
-
}
|
|
37
|
-
// AutomineSequencer owns time control through its serial queue — delegate to keep warps atomic
|
|
38
|
-
// with respect to any in-flight build, and avoid the mineBlock-loop hack below.
|
|
39
|
-
// `warpTo` internally builds an empty L2 checkpoint, which auto-mines exactly one L1 block at
|
|
40
|
-
// the target slot boundary, so no separate `node.mineBlock()` is needed here.
|
|
41
|
-
if (this.automine) {
|
|
42
|
-
await this.automine.warpTo(Number(targetBigInt));
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
const currentSlot = await this.rollup.getSlot();
|
|
46
|
-
let effectiveTargetSlot = await this.rollup.getSlotAt(targetBigInt);
|
|
47
|
-
let effectiveTimestamp = await this.rollup.getTimestampForSlot(effectiveTargetSlot);
|
|
48
|
-
if (effectiveTimestamp < targetBigInt || effectiveTargetSlot <= currentSlot) {
|
|
49
|
-
const adjustedSlot = SlotNumber(Math.max(effectiveTargetSlot + 1, currentSlot + 1));
|
|
50
|
-
const adjustedTimestamp = await this.rollup.getTimestampForSlot(adjustedSlot);
|
|
51
|
-
this.logger.warn(`warpL2TimeAtLeastTo: target timestamp ${targetBigInt} does not align with a future L2 slot boundary. ` + `Auto-adjusting to start of slot ${adjustedSlot} at timestamp ${adjustedTimestamp}.`);
|
|
52
|
-
effectiveTimestamp = adjustedTimestamp;
|
|
53
|
-
effectiveTargetSlot = adjustedSlot;
|
|
54
|
-
}
|
|
55
|
-
await this.eth.warp(effectiveTimestamp, {
|
|
56
|
-
resetBlockInterval: true
|
|
57
|
-
});
|
|
58
|
-
// The sequencer's polling loop may have a `work()` cycle in flight that captured pre-warp slot/timestamp values
|
|
59
|
-
// just before our warp landed. That cycle would mine an L2 block at the stale slot — the L1 sync prunes such a
|
|
60
|
-
// block from the canonical chain, but it lingers in local world state and the PXE will use it as the anchor for
|
|
61
|
-
// subsequent txs, leading to `expiration_timestamp` values that are already in the past relative to L1. Mine
|
|
62
|
-
// until we observe an L2 block at (or past) the post-warp slot, ensuring the next tx anchors to a fresh block.
|
|
63
|
-
const maxAttempts = 5;
|
|
64
|
-
for(let attempt = 1; attempt <= maxAttempts; attempt++){
|
|
65
|
-
await node.mineBlock();
|
|
66
|
-
const blockData = await node.getBlockData('latest');
|
|
67
|
-
const blockSlot = blockData?.header.globalVariables.slotNumber;
|
|
68
|
-
if (blockSlot !== undefined && BigInt(blockSlot) >= BigInt(effectiveTargetSlot)) {
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
this.logger.warn(`warpL2TimeAtLeastTo: mined L2 block at slot ${blockSlot}, expected at least ${effectiveTargetSlot}. ` + `Retrying mineBlock (attempt ${attempt}/${maxAttempts}).`);
|
|
72
|
-
}
|
|
73
|
-
throw new Error(`warpL2TimeAtLeastTo: failed to mine an L2 block at or past slot ${effectiveTargetSlot} after ${maxAttempts} attempts.`);
|
|
18
|
+
* Warps the L1 timestamp to at least `targetTimestamp` and mines an L2 block advancing the L2 timestamp to at least
|
|
19
|
+
* the target. Forwards to the node's debug API, which serializes the warp through the automine sequencer queue.
|
|
20
|
+
* @param node - The Aztec node whose debug API performs the warp. Must run an automine sequencer.
|
|
21
|
+
* @param targetTimestamp - The target timestamp to warp to (in seconds).
|
|
22
|
+
* @deprecated Call `node.warpL2TimeAtLeastTo(targetTimestamp)` on the node debug API directly.
|
|
23
|
+
*/ warpL2TimeAtLeastTo(node, targetTimestamp) {
|
|
24
|
+
return node.warpL2TimeAtLeastTo(Number(targetTimestamp));
|
|
74
25
|
}
|
|
75
26
|
/**
|
|
76
|
-
* Warps the L1 timestamp forward by
|
|
77
|
-
* least by the duration.
|
|
78
|
-
*
|
|
79
|
-
* @param node - The Aztec node
|
|
80
|
-
* @param duration - The duration to advance time by (in seconds)
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
// Advance relative to whichever clock leads. A live sequencer mines L2 blocks at slot boundaries that can run
|
|
86
|
-
// ahead of anvil's L1 timestamp, so basing the target on L1 alone would advance the L2 timestamp by less than
|
|
87
|
-
// `duration`. Anchoring to the latest L2 block timestamp when it leads guarantees the post-warp L2 block is at
|
|
88
|
-
// least `duration` ahead of the current one.
|
|
89
|
-
const currentL1Timestamp = BigInt(await this.eth.lastBlockTimestamp());
|
|
90
|
-
const latestBlockData = await node.getBlockData('latest');
|
|
91
|
-
const latestL2Timestamp = latestBlockData ? BigInt(latestBlockData.header.globalVariables.timestamp) : 0n;
|
|
92
|
-
const baseTimestamp = latestL2Timestamp > currentL1Timestamp ? latestL2Timestamp : currentL1Timestamp;
|
|
93
|
-
const targetTimestamp = baseTimestamp + BigInt(duration);
|
|
94
|
-
await this.warpL2TimeAtLeastTo(node, targetTimestamp);
|
|
27
|
+
* Warps the L1 timestamp forward by at least `duration` seconds and mines an L2 block advancing the L2 timestamp at
|
|
28
|
+
* least by the duration. Forwards to the node's debug API, which serializes the warp through the automine sequencer
|
|
29
|
+
* queue.
|
|
30
|
+
* @param node - The Aztec node whose debug API performs the warp. Must run an automine sequencer.
|
|
31
|
+
* @param duration - The duration to advance time by (in seconds).
|
|
32
|
+
* @deprecated Call `node.warpL2TimeAtLeastBy(duration)` on the node debug API directly.
|
|
33
|
+
*/ warpL2TimeAtLeastBy(node, duration) {
|
|
34
|
+
return node.warpL2TimeAtLeastBy(Number(duration));
|
|
95
35
|
}
|
|
96
36
|
}
|
|
@@ -1,7 +1,12 @@
|
|
|
1
|
+
import type { ContractArtifact } from '@aztec/stdlib/abi';
|
|
1
2
|
import type { AllowedElement } from '@aztec/stdlib/interfaces/server';
|
|
2
3
|
/**
|
|
3
|
-
* Returns
|
|
4
|
-
*
|
|
4
|
+
* Returns the allowlist entries needed for FPC-based fee payments, keyed by the contract class of
|
|
5
|
+
* the `artifact` actually deployed as the fee token (defaults to canonical Token). The setup-phase
|
|
6
|
+
* validator matches these entries by class id, so a test deploying the codegen'd TestToken as its
|
|
7
|
+
* fee vehicle must pass `TestTokenContract.artifact` here -- otherwise the FPC fee calls are matched
|
|
8
|
+
* against the wrong class and rejected. Test-only: FPC fee payment with custom tokens won't work on
|
|
9
|
+
* mainnet alpha.
|
|
5
10
|
*/
|
|
6
|
-
export declare function getTokenAllowedSetupFunctions(): Promise<AllowedElement[]>;
|
|
7
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
11
|
+
export declare function getTokenAllowedSetupFunctions(artifact?: ContractArtifact): Promise<AllowedElement[]>;
|
|
12
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9rZW5fYWxsb3dlZF9zZXR1cC5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3Rlc3RpbmcvdG9rZW5fYWxsb3dlZF9zZXR1cC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQSxPQUFPLEtBQUssRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBRTFELE9BQU8sS0FBSyxFQUFFLGNBQWMsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBRXRFOzs7Ozs7O0dBT0c7QUFDSCx3QkFBc0IsNkJBQTZCLENBQ2pELFFBQVEsR0FBRSxnQkFBd0MsR0FDakQsT0FBTyxDQUFDLGNBQWMsRUFBRSxDQUFDLENBUzNCIn0=
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token_allowed_setup.d.ts","sourceRoot":"","sources":["../../src/testing/token_allowed_setup.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"token_allowed_setup.d.ts","sourceRoot":"","sources":["../../src/testing/token_allowed_setup.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAE1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAEtE;;;;;;;GAOG;AACH,wBAAsB,6BAA6B,CACjD,QAAQ,GAAE,gBAAwC,GACjD,OAAO,CAAC,cAAc,EAAE,CAAC,CAS3B"}
|
|
@@ -2,19 +2,23 @@ import { TokenContractArtifact } from '@aztec/noir-contracts.js/Token';
|
|
|
2
2
|
import { buildAllowedElement } from '@aztec/p2p/msg_validators';
|
|
3
3
|
import { getContractClassFromArtifact } from '@aztec/stdlib/contract';
|
|
4
4
|
/**
|
|
5
|
-
* Returns
|
|
6
|
-
*
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
* Returns the allowlist entries needed for FPC-based fee payments, keyed by the contract class of
|
|
6
|
+
* the `artifact` actually deployed as the fee token (defaults to canonical Token). The setup-phase
|
|
7
|
+
* validator matches these entries by class id, so a test deploying the codegen'd TestToken as its
|
|
8
|
+
* fee vehicle must pass `TestTokenContract.artifact` here -- otherwise the FPC fee calls are matched
|
|
9
|
+
* against the wrong class and rejected. Test-only: FPC fee payment with custom tokens won't work on
|
|
10
|
+
* mainnet alpha.
|
|
11
|
+
*/ export async function getTokenAllowedSetupFunctions(artifact = TokenContractArtifact) {
|
|
12
|
+
const tokenClassId = (await getContractClassFromArtifact(artifact)).id;
|
|
9
13
|
const target = {
|
|
10
14
|
classId: tokenClassId
|
|
11
15
|
};
|
|
12
16
|
return Promise.all([
|
|
13
|
-
//
|
|
14
|
-
buildAllowedElement(
|
|
17
|
+
// needed for private transfers via FPC (transfer_to_public enqueues this)
|
|
18
|
+
buildAllowedElement(artifact, target, '_increase_public_balance', {
|
|
15
19
|
onlySelf: true
|
|
16
20
|
}),
|
|
17
|
-
//
|
|
18
|
-
buildAllowedElement(
|
|
21
|
+
// needed for public transfers via FPC (fee_entrypoint_public enqueues this)
|
|
22
|
+
buildAllowedElement(artifact, target, 'transfer_in_public')
|
|
19
23
|
]);
|
|
20
24
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aztec/aztec",
|
|
3
|
-
"version": "5.0.0-rc.
|
|
3
|
+
"version": "5.0.0-rc.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./dest/index.js",
|
|
@@ -28,39 +28,39 @@
|
|
|
28
28
|
"../package.common.json"
|
|
29
29
|
],
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@aztec/accounts": "5.0.0-rc.
|
|
32
|
-
"@aztec/archiver": "5.0.0-rc.
|
|
33
|
-
"@aztec/aztec-node": "5.0.0-rc.
|
|
34
|
-
"@aztec/aztec.js": "5.0.0-rc.
|
|
35
|
-
"@aztec/bb-prover": "5.0.0-rc.
|
|
36
|
-
"@aztec/bb.js": "5.0.0-rc.
|
|
37
|
-
"@aztec/blob-client": "5.0.0-rc.
|
|
38
|
-
"@aztec/bot": "5.0.0-rc.
|
|
39
|
-
"@aztec/builder": "5.0.0-rc.
|
|
40
|
-
"@aztec/cli": "5.0.0-rc.
|
|
41
|
-
"@aztec/constants": "5.0.0-rc.
|
|
42
|
-
"@aztec/entrypoints": "5.0.0-rc.
|
|
43
|
-
"@aztec/ethereum": "5.0.0-rc.
|
|
44
|
-
"@aztec/foundation": "5.0.0-rc.
|
|
45
|
-
"@aztec/kv-store": "5.0.0-rc.
|
|
46
|
-
"@aztec/l1-artifacts": "5.0.0-rc.
|
|
47
|
-
"@aztec/node-lib": "5.0.0-rc.
|
|
48
|
-
"@aztec/noir-contracts.js": "5.0.0-rc.
|
|
49
|
-
"@aztec/noir-protocol-circuits-types": "5.0.0-rc.
|
|
50
|
-
"@aztec/p2p": "5.0.0-rc.
|
|
51
|
-
"@aztec/p2p-bootstrap": "5.0.0-rc.
|
|
52
|
-
"@aztec/protocol-contracts": "5.0.0-rc.
|
|
53
|
-
"@aztec/prover-client": "5.0.0-rc.
|
|
54
|
-
"@aztec/prover-node": "5.0.0-rc.
|
|
55
|
-
"@aztec/pxe": "5.0.0-rc.
|
|
56
|
-
"@aztec/sequencer-client": "5.0.0-rc.
|
|
57
|
-
"@aztec/standard-contracts": "5.0.0-rc.
|
|
58
|
-
"@aztec/stdlib": "5.0.0-rc.
|
|
59
|
-
"@aztec/telemetry-client": "5.0.0-rc.
|
|
60
|
-
"@aztec/txe": "5.0.0-rc.
|
|
61
|
-
"@aztec/validator-ha-signer": "5.0.0-rc.
|
|
62
|
-
"@aztec/wallets": "5.0.0-rc.
|
|
63
|
-
"@aztec/world-state": "5.0.0-rc.
|
|
31
|
+
"@aztec/accounts": "5.0.0-rc.2",
|
|
32
|
+
"@aztec/archiver": "5.0.0-rc.2",
|
|
33
|
+
"@aztec/aztec-node": "5.0.0-rc.2",
|
|
34
|
+
"@aztec/aztec.js": "5.0.0-rc.2",
|
|
35
|
+
"@aztec/bb-prover": "5.0.0-rc.2",
|
|
36
|
+
"@aztec/bb.js": "5.0.0-rc.2",
|
|
37
|
+
"@aztec/blob-client": "5.0.0-rc.2",
|
|
38
|
+
"@aztec/bot": "5.0.0-rc.2",
|
|
39
|
+
"@aztec/builder": "5.0.0-rc.2",
|
|
40
|
+
"@aztec/cli": "5.0.0-rc.2",
|
|
41
|
+
"@aztec/constants": "5.0.0-rc.2",
|
|
42
|
+
"@aztec/entrypoints": "5.0.0-rc.2",
|
|
43
|
+
"@aztec/ethereum": "5.0.0-rc.2",
|
|
44
|
+
"@aztec/foundation": "5.0.0-rc.2",
|
|
45
|
+
"@aztec/kv-store": "5.0.0-rc.2",
|
|
46
|
+
"@aztec/l1-artifacts": "5.0.0-rc.2",
|
|
47
|
+
"@aztec/node-lib": "5.0.0-rc.2",
|
|
48
|
+
"@aztec/noir-contracts.js": "5.0.0-rc.2",
|
|
49
|
+
"@aztec/noir-protocol-circuits-types": "5.0.0-rc.2",
|
|
50
|
+
"@aztec/p2p": "5.0.0-rc.2",
|
|
51
|
+
"@aztec/p2p-bootstrap": "5.0.0-rc.2",
|
|
52
|
+
"@aztec/protocol-contracts": "5.0.0-rc.2",
|
|
53
|
+
"@aztec/prover-client": "5.0.0-rc.2",
|
|
54
|
+
"@aztec/prover-node": "5.0.0-rc.2",
|
|
55
|
+
"@aztec/pxe": "5.0.0-rc.2",
|
|
56
|
+
"@aztec/sequencer-client": "5.0.0-rc.2",
|
|
57
|
+
"@aztec/standard-contracts": "5.0.0-rc.2",
|
|
58
|
+
"@aztec/stdlib": "5.0.0-rc.2",
|
|
59
|
+
"@aztec/telemetry-client": "5.0.0-rc.2",
|
|
60
|
+
"@aztec/txe": "5.0.0-rc.2",
|
|
61
|
+
"@aztec/validator-ha-signer": "5.0.0-rc.2",
|
|
62
|
+
"@aztec/wallets": "5.0.0-rc.2",
|
|
63
|
+
"@aztec/world-state": "5.0.0-rc.2",
|
|
64
64
|
"@iarna/toml": "^2.2.5",
|
|
65
65
|
"@types/chalk": "^2.2.0",
|
|
66
66
|
"abitype": "^0.8.11",
|
|
@@ -24,17 +24,17 @@ pub contract Counter {
|
|
|
24
24
|
#[initializer]
|
|
25
25
|
#[external("private")]
|
|
26
26
|
fn constructor(initial_value: u128, owner: AztecAddress) {
|
|
27
|
-
// Delivers the note to the recipient onchain
|
|
27
|
+
// Delivers the note to the recipient onchain.
|
|
28
28
|
// Without delivery, the recipient can't find or decrypt the note.
|
|
29
29
|
self.storage.counters.at(owner).add(initial_value).deliver(
|
|
30
|
-
MessageDelivery::
|
|
30
|
+
MessageDelivery::onchain_unconstrained(),
|
|
31
31
|
);
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
// Adds 1 to the owner's counter.
|
|
35
35
|
#[external("private")]
|
|
36
36
|
fn increment(owner: AztecAddress) {
|
|
37
|
-
self.storage.counters.at(owner).add(1).deliver(MessageDelivery::
|
|
37
|
+
self.storage.counters.at(owner).add(1).deliver(MessageDelivery::onchain_unconstrained());
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
// Returns the current value of the owner's counter.
|
package/src/bin/index.ts
CHANGED
|
@@ -18,6 +18,7 @@ import { Command } from 'commander';
|
|
|
18
18
|
import { injectCompileCommand } from '../cli/cmds/compile.js';
|
|
19
19
|
import { injectMigrateCommand } from '../cli/cmds/migrate_ha_db.js';
|
|
20
20
|
import { injectProfileCommand } from '../cli/cmds/profile.js';
|
|
21
|
+
import { injectProverCommand } from '../cli/cmds/prover.js';
|
|
21
22
|
import { injectAztecCommands } from '../cli/index.js';
|
|
22
23
|
|
|
23
24
|
const NETWORK_FLAG = 'network';
|
|
@@ -61,6 +62,7 @@ async function main() {
|
|
|
61
62
|
program = injectCompileCommand(program, userLog);
|
|
62
63
|
program = injectProfileCommand(program, userLog);
|
|
63
64
|
program = injectMigrateCommand(program, userLog);
|
|
65
|
+
program = injectProverCommand(program, userLog);
|
|
64
66
|
|
|
65
67
|
await program.parseAsync(process.argv);
|
|
66
68
|
}
|
|
@@ -109,7 +109,7 @@ export const aztecStartOptions: { [key: string]: AztecStartOption[] } = {
|
|
|
109
109
|
env: 'NETWORK',
|
|
110
110
|
},
|
|
111
111
|
|
|
112
|
-
configToFlag('--enable-
|
|
112
|
+
configToFlag('--enable-auto-shutdown', sharedNodeConfigMappings.enableAutoShutdown),
|
|
113
113
|
|
|
114
114
|
configToFlag('--sync-mode', sharedNodeConfigMappings.syncMode),
|
|
115
115
|
configToFlag('--snapshots-urls', sharedNodeConfigMappings.snapshotsUrls),
|
package/src/cli/cmds/compile.ts
CHANGED
|
@@ -12,8 +12,8 @@ import { needsRecompile } from './utils/needs_recompile.js';
|
|
|
12
12
|
import { run } from './utils/spawn.js';
|
|
13
13
|
import { warnIfAztecVersionMismatch } from './utils/warn_if_aztec_version_mismatch.js';
|
|
14
14
|
|
|
15
|
-
/** Returns
|
|
16
|
-
async function collectContractArtifacts(): Promise<
|
|
15
|
+
/** Returns contract artifacts in the target directory along with whether each has already been postprocessed. */
|
|
16
|
+
async function collectContractArtifacts(): Promise<ContractArtifactInfo[]> {
|
|
17
17
|
let files;
|
|
18
18
|
try {
|
|
19
19
|
files = await readArtifactFiles('target');
|
|
@@ -23,7 +23,9 @@ async function collectContractArtifacts(): Promise<string[]> {
|
|
|
23
23
|
}
|
|
24
24
|
throw err;
|
|
25
25
|
}
|
|
26
|
-
return files
|
|
26
|
+
return files
|
|
27
|
+
.filter(f => Array.isArray(f.content.functions))
|
|
28
|
+
.map(f => ({ filePath: f.filePath, transpiled: f.content.transpiled === true }));
|
|
27
29
|
}
|
|
28
30
|
|
|
29
31
|
/** Stamps the Aztec stack version into the contract artifacts. */
|
|
@@ -141,30 +143,34 @@ async function checkNoTestsInContracts(nargo: string, log: LogFn): Promise<void>
|
|
|
141
143
|
async function compileAztecContract(nargoArgs: string[], log: LogFn): Promise<void> {
|
|
142
144
|
await warnIfAztecVersionMismatch(log);
|
|
143
145
|
|
|
144
|
-
if (!(await needsRecompile())) {
|
|
145
|
-
log('No source changes detected, skipping compilation.');
|
|
146
|
-
return;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
146
|
const nargo = process.env.NARGO ?? 'nargo';
|
|
150
147
|
const bb = process.env.BB ?? findBbBinary() ?? 'bb';
|
|
151
148
|
|
|
152
|
-
await
|
|
149
|
+
const shouldRecompile = await needsRecompile();
|
|
150
|
+
if (shouldRecompile) {
|
|
151
|
+
await run(nargo, ['compile', ...nargoArgs]);
|
|
153
152
|
|
|
154
|
-
|
|
155
|
-
|
|
153
|
+
// Ensure contract crates contain no tests (tests belong in the test crate).
|
|
154
|
+
await checkNoTestsInContracts(nargo, log);
|
|
155
|
+
}
|
|
156
156
|
|
|
157
|
-
|
|
157
|
+
// Postprocess any untranspiled artifacts: those just produced by nargo above, and any left behind by a bare
|
|
158
|
+
// `nargo compile` run outside `aztec compile`.
|
|
159
|
+
const unprocessed = (await collectContractArtifacts()).filter(a => !a.transpiled).map(a => a.filePath);
|
|
158
160
|
|
|
159
|
-
if (
|
|
161
|
+
if (unprocessed.length > 0) {
|
|
160
162
|
log('Postprocessing contracts...');
|
|
161
|
-
const bbArgs =
|
|
163
|
+
const bbArgs = unprocessed.flatMap(a => ['-i', a]);
|
|
162
164
|
await run(bb, ['aztec_process', ...bbArgs]);
|
|
163
165
|
|
|
164
|
-
await stampAztecVersion(
|
|
166
|
+
await stampAztecVersion(unprocessed);
|
|
165
167
|
}
|
|
166
168
|
|
|
167
|
-
|
|
169
|
+
if (shouldRecompile || unprocessed.length > 0) {
|
|
170
|
+
log('Compilation complete!');
|
|
171
|
+
} else {
|
|
172
|
+
log('No source changes detected, skipping compilation.');
|
|
173
|
+
}
|
|
168
174
|
}
|
|
169
175
|
|
|
170
176
|
export function injectCompileCommand(program: Command, log: LogFn): Command {
|
|
@@ -190,3 +196,10 @@ export function injectCompileCommand(program: Command, log: LogFn): Command {
|
|
|
190
196
|
|
|
191
197
|
return program;
|
|
192
198
|
}
|
|
199
|
+
|
|
200
|
+
interface ContractArtifactInfo {
|
|
201
|
+
/** Path to the artifact JSON in the target directory. */
|
|
202
|
+
filePath: string;
|
|
203
|
+
/** Whether the artifact has already been transpiled and had its verification keys generated. */
|
|
204
|
+
transpiled: boolean;
|
|
205
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { jsonStringify } from '@aztec/foundation/json-rpc';
|
|
2
|
+
import type { LogFn } from '@aztec/foundation/log';
|
|
3
|
+
import { createProverNodeAdminClient } from '@aztec/stdlib/interfaces/server';
|
|
4
|
+
|
|
5
|
+
import { type Command, InvalidArgumentError } from 'commander';
|
|
6
|
+
|
|
7
|
+
function parseEpoch(value: string): number {
|
|
8
|
+
const parsed = Number(value);
|
|
9
|
+
if (!Number.isInteger(parsed) || parsed < 0) {
|
|
10
|
+
throw new InvalidArgumentError('Epoch must be a non-negative integer.');
|
|
11
|
+
}
|
|
12
|
+
return parsed;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function injectProverCommand(program: Command, log: LogFn): Command {
|
|
16
|
+
const proverCommand = program.command('prover').description('Operate a prover node via its admin JSON-RPC endpoint');
|
|
17
|
+
|
|
18
|
+
proverCommand
|
|
19
|
+
.command('start-proof')
|
|
20
|
+
.description('Schedules proving for the given epoch')
|
|
21
|
+
.requiredOption('--epoch <n>', 'Epoch number to prove', parseEpoch)
|
|
22
|
+
.requiredOption('--admin-url <url>', 'URL of the prover node admin JSON-RPC endpoint')
|
|
23
|
+
.option('--api-key <key>', 'Admin API key', process.env.AZTEC_ADMIN_API_KEY)
|
|
24
|
+
.action(async options => {
|
|
25
|
+
const client = createProverNodeAdminClient(options.adminUrl, {}, undefined, options.apiKey);
|
|
26
|
+
const jobId = await client.startProof(options.epoch);
|
|
27
|
+
log(`Started proving job ${jobId} for epoch ${options.epoch}`);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
proverCommand
|
|
31
|
+
.command('get-jobs')
|
|
32
|
+
.description('Lists the prover node proving jobs')
|
|
33
|
+
.requiredOption('--admin-url <url>', 'URL of the prover node admin JSON-RPC endpoint')
|
|
34
|
+
.option('--api-key <key>', 'Admin API key', process.env.AZTEC_ADMIN_API_KEY)
|
|
35
|
+
.action(async options => {
|
|
36
|
+
const client = createProverNodeAdminClient(options.adminUrl, {}, undefined, options.apiKey);
|
|
37
|
+
const jobs = await client.getJobs();
|
|
38
|
+
log(jsonStringify(jobs, true));
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
return program;
|
|
42
|
+
}
|
package/src/cli/cmds/standby.ts
CHANGED
|
@@ -6,13 +6,16 @@ import type { GenesisStateConfig } from '@aztec/ethereum/config';
|
|
|
6
6
|
import { RegistryContract, RollupContract } from '@aztec/ethereum/contracts';
|
|
7
7
|
import type { EthAddress } from '@aztec/foundation/eth-address';
|
|
8
8
|
import { startHttpRpcServer } from '@aztec/foundation/json-rpc/server';
|
|
9
|
-
import type
|
|
9
|
+
import { type LogFn, createLogger } from '@aztec/foundation/log';
|
|
10
10
|
import { retryUntil } from '@aztec/foundation/retry';
|
|
11
11
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
12
|
+
import type { VersionCheck } from '@aztec/stdlib/update-checker';
|
|
12
13
|
import { getGenesisValues } from '@aztec/world-state/testing';
|
|
13
14
|
|
|
14
15
|
import Koa from 'koa';
|
|
15
16
|
|
|
17
|
+
import { isShuttingDown, softShutdown } from '../util.js';
|
|
18
|
+
|
|
16
19
|
const ROLLUP_POLL_INTERVAL_S = 60;
|
|
17
20
|
|
|
18
21
|
/**
|
|
@@ -23,7 +26,7 @@ const ROLLUP_POLL_INTERVAL_S = 60;
|
|
|
23
26
|
export async function computeExpectedGenesisRoot(config: GenesisStateConfig, userLog: LogFn) {
|
|
24
27
|
const testAccounts = config.testAccounts ? (await getInitialTestAccountsData()).map(a => a.address) : [];
|
|
25
28
|
const sponsoredFPCAccounts = config.sponsoredFPC ? [await getSponsoredFPCAddress()] : [];
|
|
26
|
-
const prefundAddresses = (config.prefundAddresses ?? []).map(a => AztecAddress.
|
|
29
|
+
const prefundAddresses = (config.prefundAddresses ?? []).map(a => AztecAddress.fromStringUnsafe(a));
|
|
27
30
|
const initialFundedAccounts = testAccounts.concat(sponsoredFPCAccounts).concat(prefundAddresses);
|
|
28
31
|
|
|
29
32
|
userLog(`Initial funded accounts: ${initialFundedAccounts.map(a => a.toString()).join(', ')}`);
|
|
@@ -35,7 +38,12 @@ export async function computeExpectedGenesisRoot(config: GenesisStateConfig, use
|
|
|
35
38
|
return { genesisArchiveRoot, genesis };
|
|
36
39
|
}
|
|
37
40
|
|
|
38
|
-
|
|
41
|
+
/**
|
|
42
|
+
* Compares the rollup's on-chain protocol constants (genesis archive root, VK tree root, protocol
|
|
43
|
+
* contracts hash) against the node's expected local values. Returns a list of human-readable mismatch
|
|
44
|
+
* descriptions, empty if the rollup is compatible.
|
|
45
|
+
*/
|
|
46
|
+
export async function checkRollupCompatibility(
|
|
39
47
|
rollup: RollupContract,
|
|
40
48
|
expected: { genesisArchiveRoot: Fr; vkTreeRoot: Fr; protocolContractsHash: Fr },
|
|
41
49
|
): Promise<string[]> {
|
|
@@ -130,3 +138,47 @@ export async function waitForCompatibleRollup(
|
|
|
130
138
|
await new Promise<void>((resolve, reject) => standbyServer.close(err => (err ? reject(err) : resolve())));
|
|
131
139
|
}
|
|
132
140
|
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Polls the canonical rollup's protocol constants every 10 minutes and soft-shuts-down the node once they
|
|
144
|
+
* diverge from the node's expected local values (i.e. an incompatible rollup has become canonical on L1).
|
|
145
|
+
* The HTTP health server is left running so K8s probes keep passing on the wound-down pod. This is the
|
|
146
|
+
* inverse of {@link waitForCompatibleRollup}; it should only be set up for nodes following the canonical
|
|
147
|
+
* rollup. Reuses the {@link checkRollupCompatibility} diff and the generic VersionChecker poll primitive.
|
|
148
|
+
*/
|
|
149
|
+
export async function setupAutoShutdown(
|
|
150
|
+
config: { l1RpcUrls: string[]; l1ChainId: number },
|
|
151
|
+
registryAddress: EthAddress,
|
|
152
|
+
rollupVersion: number | 'canonical',
|
|
153
|
+
expected: { genesisArchiveRoot: Fr; vkTreeRoot: Fr; protocolContractsHash: Fr },
|
|
154
|
+
signalHandlers: Array<() => Promise<void>>,
|
|
155
|
+
): Promise<void> {
|
|
156
|
+
const { VersionChecker } = await import('@aztec/stdlib/update-checker');
|
|
157
|
+
|
|
158
|
+
const logger = createLogger('auto_shutdown');
|
|
159
|
+
const publicClient = getPublicClient(config);
|
|
160
|
+
const registry = new RegistryContract(publicClient, registryAddress);
|
|
161
|
+
|
|
162
|
+
const check: VersionCheck = {
|
|
163
|
+
name: 'rollup',
|
|
164
|
+
currentVersion: 'compatible',
|
|
165
|
+
getLatestVersion: async () => {
|
|
166
|
+
const rollupAddress = await registry.getRollupAddress(rollupVersion);
|
|
167
|
+
const rollup = new RollupContract(publicClient, rollupAddress.toString());
|
|
168
|
+
const mismatches = await checkRollupCompatibility(rollup, expected);
|
|
169
|
+
return mismatches.length === 0 ? 'compatible' : `incompatible: ${mismatches.join('; ')}`;
|
|
170
|
+
},
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
const checker = new VersionChecker([check], 600_000, logger);
|
|
174
|
+
checker.on('newVersion', ({ latestVersion }) => {
|
|
175
|
+
if (isShuttingDown()) {
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
logger.warn('Canonical rollup is no longer compatible; auto-shutting down node', { latestVersion });
|
|
179
|
+
// softShutdown never rejects (it awaits handlers via allSettled); fire-and-forget from the listener.
|
|
180
|
+
void softShutdown(logger.info.bind(logger), signalHandlers);
|
|
181
|
+
});
|
|
182
|
+
checker.start();
|
|
183
|
+
signalHandlers.push(() => checker.stop());
|
|
184
|
+
}
|