From 368aeea5d222f3097d129e2e5ab10dea7f66b23d Mon Sep 17 00:00:00 2001 From: Marcin M <128217157+mm-zk@users.noreply.github.com> Date: Wed, 8 May 2024 22:39:49 +0200 Subject: [PATCH] feat(local-node): Added support for hyperchains (#1870) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## What ❔ * Added support for hyperchains working with local node. * Modified the entrypoint, so that it either creates a bridgehub, or connects to one depending on the environment variables. ## Why ❔ * This will allow a lot easier testing of the hyperchains and shared bridges. --- checks-config/era.dic | 1 + docker/local-node/Dockerfile | 1 + docker/local-node/entrypoint.sh | 41 ++++++--- .../local-setup-preparation/package.json | 3 +- .../src/join_hyperchain.ts | 86 +++++++++++++++++++ 5 files changed, 121 insertions(+), 11 deletions(-) create mode 100644 infrastructure/local-setup-preparation/src/join_hyperchain.ts diff --git a/checks-config/era.dic b/checks-config/era.dic index 55b78766d25..28b326ce281 100644 --- a/checks-config/era.dic +++ b/checks-config/era.dic @@ -673,6 +673,7 @@ crypto callee Subcalls Vec +vec vecs L1Messenger SystemL2ToL1Log diff --git a/docker/local-node/Dockerfile b/docker/local-node/Dockerfile index be74002a29b..c0592f89d56 100644 --- a/docker/local-node/Dockerfile +++ b/docker/local-node/Dockerfile @@ -70,4 +70,5 @@ RUN mkdir /etc/env/l1-inits && mkdir /etc/env/l2-inits # setup entrypoint script COPY ./docker/local-node/entrypoint.sh /usr/bin/ + ENTRYPOINT ["entrypoint.sh"] diff --git a/docker/local-node/entrypoint.sh b/docker/local-node/entrypoint.sh index 00784e6855f..381bde189bb 100755 --- a/docker/local-node/entrypoint.sh +++ b/docker/local-node/entrypoint.sh @@ -44,6 +44,16 @@ until psql ${DATABASE_URL%/*} -c '\q'; do sleep 5 done +if [ -z "$MASTER_URL" ]; then + echo "Running as zksync master" +else + # If running in slave mode - wait for the master to be up and running. + echo "Waiting for zksync master to init hyperchain" + until curl --fail ${MASTER_HEALTH_URL}; do + >&2 echo "Master zksync not ready yet, sleeping" + sleep 5 + done +fi # Normally, the /etc/env and /var/lib/zksync/data should be mapped to volumes # so that they are persisted between docker restarts - which would allow even faster starts. @@ -66,19 +76,28 @@ else update_config "/etc/env/base/database.toml" "state_keeper_db_path" "/var/lib/zksync/data/state_keeper" update_config "/etc/env/base/database.toml" "backup_path" "/var/lib/zksync/data/backups" + + if [ -z "$MASTER_URL" ]; then + echo "Starting with hyperchain" + else + # Updates all the stuff (from the '/etc/master_env') - it assumes that it is mapped via docker compose. + zk f yarn --cwd /infrastructure/local-setup-preparation join + fi + zk config compile zk db reset - # Perform initialization - - zk contract deploy-verifier - zk run deploy-erc20 dev # (created etc/tokens/localhost) - - ## init bridgehub state transition - zk contract deploy # (deploy L1) - zk contract initialize-governance - zk contract initialize-validator + # Perform initialization (things needed to be done only if you're running in the master mode) + if [ -z "$MASTER_URL" ]; then + zk contract deploy-verifier + zk run deploy-erc20 dev # (created etc/tokens/localhost) + + ## init bridgehub state transition + zk contract deploy # (deploy L1) + zk contract initialize-governance + zk contract initialize-validator + fi ## init hyperchain zk contract register-hyperchain @@ -87,7 +106,9 @@ else zk contract deploy-l2-through-l1 - zk f yarn --cwd /infrastructure/local-setup-preparation start + if [ -z "$MASTER_URL" ]; then + zk f yarn --cwd /infrastructure/local-setup-preparation start + fi # Create init file. echo "System initialized. Please remove this file if you want to reset the system" > $INIT_FILE diff --git a/infrastructure/local-setup-preparation/package.json b/infrastructure/local-setup-preparation/package.json index c319532d19d..1dc00029b12 100644 --- a/infrastructure/local-setup-preparation/package.json +++ b/infrastructure/local-setup-preparation/package.json @@ -13,6 +13,7 @@ "@types/node": "^18.19.15" }, "scripts": { - "start": "ts-node ./src/index.ts" + "start": "ts-node ./src/index.ts", + "join": "ts-node ./src/join_hyperchain.ts" } } \ No newline at end of file diff --git a/infrastructure/local-setup-preparation/src/join_hyperchain.ts b/infrastructure/local-setup-preparation/src/join_hyperchain.ts new file mode 100644 index 00000000000..1600dba5abb --- /dev/null +++ b/infrastructure/local-setup-preparation/src/join_hyperchain.ts @@ -0,0 +1,86 @@ +import fs from 'fs'; +import path from 'path'; +import { ethers } from 'ethers'; +import { getEthersProvider, getWalletKeys } from './utils'; +import assert from 'assert'; + +async function joinHyperchain() { + const chainId = process.env.CHAIN_ETH_ZKSYNC_NETWORK_ID!; + assert(chainId != '270', `Your chain id is set to 270 - are you sure`); + + const ethProvider = getEthersProvider(); + const operatorWallet = ethers.Wallet.createRandom(); + console.log(`Operator: ${operatorWallet.address}`); + const blobOperatorWallet = ethers.Wallet.createRandom(); + console.log(`Blob Operator: ${blobOperatorWallet.address}`); + + const allWalletKeys = getWalletKeys(); + + const richWalletKey = allWalletKeys[allWalletKeys.length - 1]; + + const richAccount = new ethers.Wallet(richWalletKey.privateKey, ethProvider); + + for (const addr of [operatorWallet.address, blobOperatorWallet.address]) { + const tx = { + to: addr, + // Convert Ether to Wei + value: ethers.utils.parseEther('100') + }; + await richAccount.sendTransaction(tx); + } + console.log(`Eth sent to operator accounts`); + + const inputFilePath = process.env.MASTER_ENV_FILE!; + const outputFilePath = path.resolve('/etc/env/l1-inits', '.init.env'); + const varsToKeep = [ + 'CONTRACTS_BRIDGEHUB_PROXY_ADDR', + 'CONTRACTS_STATE_TRANSITION_PROXY_ADDR', + 'CONTRACTS_ADMIN_FACET_ADDR', + 'CONTRACTS_MAILBOX_FACET_ADDR', + 'CONTRACTS_EXECUTOR_FACET_ADDR', + 'CONTRACTS_GETTERS_FACET_ADDR', + 'CONTRACTS_DIAMOND_INIT_ADDR', + 'CONTRACTS_BLOB_VERSIONED_HASH_RETRIEVER_ADDR', + 'CONTRACTS_VERIFIER_ADDR', + 'CONTRACTS_L1_MULTICALL3_ADDR', + 'CONTRACTS_VALIDATOR_TIMELOCK_ADDR', + 'CONTRACTS_GOVERNANCE_ADDR' + ]; + + try { + const data = fs.readFileSync(inputFilePath, 'utf8'); + + const lines = data.split(/\r?\n/); + // Filter and map lines to keep only specified variables + const filteredEnvVars = lines.filter((line) => { + const key = line.split('=')[0]; + return varsToKeep.includes(key); + }); + + filteredEnvVars.push(`ETH_SENDER_SENDER_OPERATOR_PRIVATE_KEY=${operatorWallet.privateKey}`); + filteredEnvVars.push(`ETH_SENDER_SENDER_OPERATOR_COMMIT_ETH_ADDR=${operatorWallet.address}`); + filteredEnvVars.push(`ETH_SENDER_SENDER_OPERATOR_BLOBS_PRIVATE_KEY=${blobOperatorWallet.privateKey}`); + filteredEnvVars.push(`ETH_SENDER_SENDER_OPERATOR_BLOBS_ETH_ADDR=${blobOperatorWallet.address}`); + + // Prepare the content to write to the output file + const outputContent = filteredEnvVars.join('\n'); + + // Write the filtered environment variables to the output file + fs.writeFileSync(outputFilePath, outputContent, 'utf8'); + console.log('Filtered environment variables have been written to the output file.'); + } catch (error) { + console.error('Failed to process environment variables:', error); + } +} + +async function main() { + await joinHyperchain(); +} + +main() + .then(() => { + console.log('Successfully joined hyperchain!'); + }) + .catch((e) => { + console.log(`Execution failed with error ${e}`); + });