From 11e5c0c22352f2f21487521a3ba88ac7818201cc Mon Sep 17 00:00:00 2001 From: nikola-bozin-txfusion Date: Thu, 12 Sep 2024 10:29:41 +0200 Subject: [PATCH 1/5] feat: add node task --- packages/hardhat-zksync-node/src/index.ts | 16 ++++++++++++++ packages/hardhat-zksync-node/src/utils.ts | 26 +++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/packages/hardhat-zksync-node/src/index.ts b/packages/hardhat-zksync-node/src/index.ts index fc91d2fb7..633796934 100644 --- a/packages/hardhat-zksync-node/src/index.ts +++ b/packages/hardhat-zksync-node/src/index.ts @@ -2,6 +2,7 @@ import { spawn } from 'child_process'; import { task, subtask, types } from 'hardhat/config'; import { TASK_COMPILE, + TASK_NODE, TASK_TEST, TASK_TEST_GET_TEST_FILES, TASK_TEST_RUN_MOCHA_TESTS, @@ -24,6 +25,7 @@ import { getAvailablePort, getPlatform, getRPCServerBinariesDir, + startServer, waitForNodeToBeReady, } from './utils'; import { RPCServerDownloader } from './downloader'; @@ -75,6 +77,20 @@ subtask(TASK_NODE_ZKSYNC_CREATE_SERVER, 'Creates a JSON-RPC server for ZKsync no }, ); +task(TASK_NODE, 'Start a ZKSync Node') + .addOptionalParam('tag', 'Version tag', undefined, types.string) + .addOptionalParam('force', 'Force download', undefined, types.boolean) + .setAction(async ({ tag, force }, { network }, runSuper) => { + if (network.zksync !== true || network.name !== HARDHAT_NETWORK_NAME) { + return await runSuper(); + } + + const { port, server, commandArgs } = await startServer(tag, force); + const _ = server.listen(commandArgs); + await waitForNodeToBeReady(port); + await server.stop(); + }); + // Main task of the plugin. It starts the server and listens for requests. task(TASK_NODE_ZKSYNC, 'Starts a JSON-RPC server for ZKsync node') .addOptionalParam('port', 'Port to listen on - default: 8011', undefined, types.int) diff --git a/packages/hardhat-zksync-node/src/utils.ts b/packages/hardhat-zksync-node/src/utils.ts index e2aa8b59d..43a6aba63 100644 --- a/packages/hardhat-zksync-node/src/utils.ts +++ b/packages/hardhat-zksync-node/src/utils.ts @@ -19,16 +19,20 @@ import { ALLOWED_SHOW_STORAGE_LOGS_VALUES, ALLOWED_SHOW_VM_DETAILS_VALUES, BASE_URL, + MAX_PORT_ATTEMPTS, NETWORK_ACCOUNTS, NETWORK_ETH, NETWORK_GAS, NETWORK_GAS_PRICE, PLATFORM_MAP, + START_PORT, TEMP_FILE_PREFIX, ZKSYNC_ERA_TEST_NODE_NETWORK_NAME, } from './constants'; import { ZkSyncNodePluginError } from './errors'; import { CommandArguments } from './types'; +import { RPCServerDownloader } from './downloader'; +import { JsonRpcServer } from './server'; // Generates command arguments for running the era-test-node binary export function constructCommandArgs(args: CommandArguments): string[] { @@ -406,3 +410,25 @@ export async function configureNetwork(config: HardhatConfig, network: any, port config.networks[network.name] = network.config; network.provider = await createProvider(config, network.name); } + +export const startServer = async (tag?: string, force: boolean = false) => { + const platform = getPlatform(); + if (platform === 'windows' || platform === '') { + throw new ZkSyncNodePluginError(`Unsupported platform: ${platform}`); + } + const rpcServerBinaryDir = await getRPCServerBinariesDir(); + + const downloader: RPCServerDownloader = new RPCServerDownloader(rpcServerBinaryDir, tag || 'latest'); + + await downloader.downloadIfNeeded(force); + const binaryPath = await downloader.getBinaryPath(); + + const currentPort = await getAvailablePort(START_PORT, MAX_PORT_ATTEMPTS); + const commandArgs = constructCommandArgs({ port: currentPort }); + + return { + commandArgs, + server: new JsonRpcServer(binaryPath), + port: currentPort, + }; +}; From 5b48a114ba16fce3348a5aed2b23ef9c07e5df45 Mon Sep 17 00:00:00 2001 From: nikola-bozin-txfusion Date: Thu, 12 Sep 2024 21:06:03 +0200 Subject: [PATCH 2/5] feat: refactor task node --- packages/hardhat-zksync-node/src/index.ts | 128 ++++++++++++++++++++-- 1 file changed, 118 insertions(+), 10 deletions(-) diff --git a/packages/hardhat-zksync-node/src/index.ts b/packages/hardhat-zksync-node/src/index.ts index 633796934..310210430 100644 --- a/packages/hardhat-zksync-node/src/index.ts +++ b/packages/hardhat-zksync-node/src/index.ts @@ -78,18 +78,126 @@ subtask(TASK_NODE_ZKSYNC_CREATE_SERVER, 'Creates a JSON-RPC server for ZKsync no ); task(TASK_NODE, 'Start a ZKSync Node') - .addOptionalParam('tag', 'Version tag', undefined, types.string) + .addOptionalParam('log', 'Log filter level (error, warn, info, debug) - default: info', undefined, types.string) + .addOptionalParam( + 'logFilePath', + 'Path to the file where logs should be written - default: `era_test_node.log`', + undefined, + types.string, + ) + .addOptionalParam('cache', 'Cache type (none, disk, memory) - default: disk', undefined, types.string) + .addOptionalParam( + 'cacheDir', + 'Cache directory location for `disk` cache - default: `.cache`', + undefined, + types.string, + ) + .addFlag('resetCache', 'Reset the local `disk` cache') + .addOptionalParam( + 'showCalls', + 'Show call debug information (none, user, system, all) - default: none', + undefined, + types.string, + ) + .addOptionalParam( + 'showStorageLogs', + 'Show storage log information (none, read, write, all) - default: none', + undefined, + types.string, + ) + .addOptionalParam( + 'showVmDetails', + 'Show VM details information (none, all) - default: none', + undefined, + types.string, + ) + .addOptionalParam( + 'showGasDetails', + 'Show Gas details information (none, all) - default: none', + undefined, + types.string, + ) + .addFlag( + 'resolveHashes', + 'Try to contact openchain to resolve the ABI & topic names. It enabled, it makes debug log more readable, but will decrease the performance', + ) + .addFlag( + 'devUseLocalContracts', + 'Loads the locally compiled system contracts (useful when doing changes to system contracts or bootloader)', + ) + .addOptionalParam('replayTx', 'Transaction hash to replay', undefined, types.string) + .addOptionalParam('tag', 'Specified node release for use', undefined) .addOptionalParam('force', 'Force download', undefined, types.boolean) - .setAction(async ({ tag, force }, { network }, runSuper) => { - if (network.zksync !== true || network.name !== HARDHAT_NETWORK_NAME) { - return await runSuper(); - } + .setAction( + async ( + { + port, + log, + logFilePath, + cache, + cacheDir, + resetCache, + showCalls, + showStorageLogs, + showVmDetails, + showGasDetails, + resolveHashes, + devUseLocalContracts, + fork, + forkBlockNumber, + replayTx, + tag, + force, + }: { + port: number; + log: string; + logFilePath: string; + cache: string; + cacheDir: string; + resetCache: boolean; + showCalls: string; + showStorageLogs: string; + showVmDetails: string; + showGasDetails: string; + resolveHashes: boolean; + devUseLocalContracts: boolean; + fork: string; + forkBlockNumber: number; + replayTx: string; + tag: string; + binaryTag: string; + force: boolean; + }, + { network }, + runSuper, + ) => { + if (network.zksync !== true || network.name !== HARDHAT_NETWORK_NAME) { + return await runSuper(); + } - const { port, server, commandArgs } = await startServer(tag, force); - const _ = server.listen(commandArgs); - await waitForNodeToBeReady(port); - await server.stop(); - }); + const commandArgs = constructCommandArgs({ + port, + log, + logFilePath, + cache, + cacheDir, + resetCache, + showCalls, + showStorageLogs, + showVmDetails, + showGasDetails, + resolveHashes, + devUseLocalContracts, + fork, + forkBlockNumber, + replayTx, + }); + + const { server } = await startServer(tag, force); + const _ = server.listen(commandArgs); + await waitForNodeToBeReady(port); + }, + ); // Main task of the plugin. It starts the server and listens for requests. task(TASK_NODE_ZKSYNC, 'Starts a JSON-RPC server for ZKsync node') From c0512733a8bc938d0bbf27e9478e68883f76e453 Mon Sep 17 00:00:00 2001 From: nikola-bozin-txfusion Date: Mon, 16 Sep 2024 11:09:02 +0200 Subject: [PATCH 3/5] feat: update task node --- packages/hardhat-zksync-node/src/index.ts | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/packages/hardhat-zksync-node/src/index.ts b/packages/hardhat-zksync-node/src/index.ts index 310210430..3e84ed703 100644 --- a/packages/hardhat-zksync-node/src/index.ts +++ b/packages/hardhat-zksync-node/src/index.ts @@ -25,7 +25,6 @@ import { getAvailablePort, getPlatform, getRPCServerBinariesDir, - startServer, waitForNodeToBeReady, } from './utils'; import { RPCServerDownloader } from './downloader'; @@ -168,13 +167,15 @@ task(TASK_NODE, 'Start a ZKSync Node') binaryTag: string; force: boolean; }, - { network }, + { network, run }, runSuper, ) => { if (network.zksync !== true || network.name !== HARDHAT_NETWORK_NAME) { return await runSuper(); } + port = START_PORT; + const commandArgs = constructCommandArgs({ port, log, @@ -193,9 +194,17 @@ task(TASK_NODE, 'Start a ZKSync Node') replayTx, }); - const { server } = await startServer(tag, force); - const _ = server.listen(commandArgs); - await waitForNodeToBeReady(port); + // Download the binary + const binaryPath: string = await run(TASK_NODE_ZKSYNC_DOWNLOAD_BINARY, { force: false, tag }); + + // Create the server + const server: JsonRpcServer = await run(TASK_NODE_ZKSYNC_CREATE_SERVER, { binaryPath }); + + try { + await server.listen(commandArgs); + } catch (error: any) { + throw new ZkSyncNodePluginError(`Failed when running node: ${error.message}`); + } }, ); From da71962f0890e43bd246bf12d4c9319cbd2ba233 Mon Sep 17 00:00:00 2001 From: Marko Arambasic Date: Tue, 17 Sep 2024 13:17:07 +0200 Subject: [PATCH 4/5] fix: call subtask for era test node start --- packages/hardhat-zksync-node/src/index.ts | 96 ++++------------------ packages/hardhat-zksync-node/src/server.ts | 7 +- 2 files changed, 20 insertions(+), 83 deletions(-) diff --git a/packages/hardhat-zksync-node/src/index.ts b/packages/hardhat-zksync-node/src/index.ts index 3e84ed703..abf9a645c 100644 --- a/packages/hardhat-zksync-node/src/index.ts +++ b/packages/hardhat-zksync-node/src/index.ts @@ -9,6 +9,7 @@ import { } from 'hardhat/builtin-tasks/task-names'; import { HARDHAT_NETWORK_NAME } from 'hardhat/plugins'; +import { TaskArguments } from 'hardhat/types'; import { MAX_PORT_ATTEMPTS, START_PORT, @@ -17,7 +18,7 @@ import { TASK_NODE_ZKSYNC_DOWNLOAD_BINARY, TASK_RUN_NODE_ZKSYNC_IN_SEPARATE_PROCESS, } from './constants'; -import { JsonRpcServer } from './server'; +import { JsonRpcServer, RpcServer } from './server'; import { adjustTaskArgsForPort, configureNetwork, @@ -126,87 +127,18 @@ task(TASK_NODE, 'Start a ZKSync Node') ) .addOptionalParam('replayTx', 'Transaction hash to replay', undefined, types.string) .addOptionalParam('tag', 'Specified node release for use', undefined) - .addOptionalParam('force', 'Force download', undefined, types.boolean) - .setAction( - async ( - { - port, - log, - logFilePath, - cache, - cacheDir, - resetCache, - showCalls, - showStorageLogs, - showVmDetails, - showGasDetails, - resolveHashes, - devUseLocalContracts, - fork, - forkBlockNumber, - replayTx, - tag, - force, - }: { - port: number; - log: string; - logFilePath: string; - cache: string; - cacheDir: string; - resetCache: boolean; - showCalls: string; - showStorageLogs: string; - showVmDetails: string; - showGasDetails: string; - resolveHashes: boolean; - devUseLocalContracts: boolean; - fork: string; - forkBlockNumber: number; - replayTx: string; - tag: string; - binaryTag: string; - force: boolean; - }, - { network, run }, - runSuper, - ) => { - if (network.zksync !== true || network.name !== HARDHAT_NETWORK_NAME) { - return await runSuper(); - } - - port = START_PORT; - - const commandArgs = constructCommandArgs({ - port, - log, - logFilePath, - cache, - cacheDir, - resetCache, - showCalls, - showStorageLogs, - showVmDetails, - showGasDetails, - resolveHashes, - devUseLocalContracts, - fork, - forkBlockNumber, - replayTx, - }); - - // Download the binary - const binaryPath: string = await run(TASK_NODE_ZKSYNC_DOWNLOAD_BINARY, { force: false, tag }); - - // Create the server - const server: JsonRpcServer = await run(TASK_NODE_ZKSYNC_CREATE_SERVER, { binaryPath }); + // .addOptionalParam('force', 'Force download', undefined, types.boolean) + .setAction(async (args: TaskArguments, { network, run }, runSuper) => { + if (network.zksync !== true || network.name !== HARDHAT_NETWORK_NAME) { + return await runSuper(); + } + // Hardhat doesn't allow to override the port value, so we need to do it manually. With this approach we don't allow 8545 for the user. + if (args.port === 8545) { + delete args.port; + } - try { - await server.listen(commandArgs); - } catch (error: any) { - throw new ZkSyncNodePluginError(`Failed when running node: ${error.message}`); - } - }, - ); + await run(TASK_NODE_ZKSYNC, args); + }); // Main task of the plugin. It starts the server and listens for requests. task(TASK_NODE_ZKSYNC, 'Starts a JSON-RPC server for ZKsync node') @@ -329,7 +261,7 @@ task(TASK_NODE_ZKSYNC, 'Starts a JSON-RPC server for ZKsync node') const binaryPath: string = await run(TASK_NODE_ZKSYNC_DOWNLOAD_BINARY, { force: false, tag }); // Create the server - const server: JsonRpcServer = await run(TASK_NODE_ZKSYNC_CREATE_SERVER, { binaryPath }); + const server: RpcServer = await run(TASK_NODE_ZKSYNC_CREATE_SERVER, { binaryPath }); try { await server.listen(commandArgs); diff --git a/packages/hardhat-zksync-node/src/server.ts b/packages/hardhat-zksync-node/src/server.ts index 620a853fe..c9bf7e76f 100644 --- a/packages/hardhat-zksync-node/src/server.ts +++ b/packages/hardhat-zksync-node/src/server.ts @@ -3,7 +3,12 @@ import chalk from 'chalk'; import { PROCESS_TERMINATION_SIGNALS } from './constants'; -export class JsonRpcServer { +export interface RpcServer { + listen(args?: string[], blockProcess?: boolean): Promise; + stop(): Promise; +} + +export class JsonRpcServer implements RpcServer { private serverProcess: ChildProcess | null = null; // eslint-disable-next-line @typescript-eslint/naming-convention From 64f96174a941bc64eb9cf73da20f7a6e24dd12f4 Mon Sep 17 00:00:00 2001 From: Marko Arambasic Date: Tue, 17 Sep 2024 14:23:13 +0200 Subject: [PATCH 5/5] fix: set default port at 8545 for both node tasks --- packages/hardhat-zksync-node/src/index.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/hardhat-zksync-node/src/index.ts b/packages/hardhat-zksync-node/src/index.ts index abf9a645c..43f48011c 100644 --- a/packages/hardhat-zksync-node/src/index.ts +++ b/packages/hardhat-zksync-node/src/index.ts @@ -132,17 +132,13 @@ task(TASK_NODE, 'Start a ZKSync Node') if (network.zksync !== true || network.name !== HARDHAT_NETWORK_NAME) { return await runSuper(); } - // Hardhat doesn't allow to override the port value, so we need to do it manually. With this approach we don't allow 8545 for the user. - if (args.port === 8545) { - delete args.port; - } await run(TASK_NODE_ZKSYNC, args); }); // Main task of the plugin. It starts the server and listens for requests. task(TASK_NODE_ZKSYNC, 'Starts a JSON-RPC server for ZKsync node') - .addOptionalParam('port', 'Port to listen on - default: 8011', undefined, types.int) + .addOptionalParam('port', 'Port to listen on - default: 8545', 8545, types.int) .addOptionalParam('log', 'Log filter level (error, warn, info, debug) - default: info', undefined, types.string) .addOptionalParam( 'logFilePath',