diff --git a/.github/workflows/ci-zk-toolbox-reusable.yml b/.github/workflows/ci-zk-toolbox-reusable.yml index 78e1e485cafc..638f168de309 100644 --- a/.github/workflows/ci-zk-toolbox-reusable.yml +++ b/.github/workflows/ci-zk-toolbox-reusable.yml @@ -132,6 +132,30 @@ jobs: --prover-db-name=zksync_prover_localhost_custom_token \ --port-offset 3000 \ --chain custom_token + + - name: Create and initialize Consensus chain + run: | + ci_run zk_inception chain create \ + --chain-name consensus \ + --chain-id sequential \ + --prover-mode no-proofs \ + --wallet-creation localhost \ + --l1-batch-commit-data-generator-mode validium \ + --base-token-address ${{ env.address }} \ + --base-token-price-nominator 3 \ + --base-token-price-denominator 2 \ + --set-as-default false \ + --ignore-prerequisites + + ci_run zk_inception chain init \ + --deploy-paymaster \ + --l1-rpc-url=http://localhost:8545 \ + --server-db-url=postgres://postgres:notsecurepassword@localhost:5432 \ + --server-db-name=zksync_server_localhost_consensus \ + --prover-db-url=postgres://postgres:notsecurepassword@localhost:5432 \ + --prover-db-name=zksync_prover_localhost_consensus \ + --port-offset 4000 \ + --chain consensus - name: Build test dependencies run: | @@ -142,6 +166,10 @@ jobs: ci_run zk_inception server --ignore-prerequisites --chain era &> ${{ env.SERVER_LOGS_DIR }}/rollup.log & ci_run zk_inception server --ignore-prerequisites --chain validium &> ${{ env.SERVER_LOGS_DIR }}/validium.log & ci_run zk_inception server --ignore-prerequisites --chain custom_token &> ${{ env.SERVER_LOGS_DIR }}/custom_token.log & + ci_run zk_inception server --ignore-prerequisites --chain consensus \ + --components=api,tree,eth,state_keeper,housekeeper,commitment_generator,vm_runner_protective_reads,vm_runner_bwip,vm_playground,da_dispatcher,consensus \ + &> ${{ env.SERVER_LOGS_DIR }}/consensus.log & + ci_run sleep 5 - name: Run integration tests @@ -155,9 +183,13 @@ jobs: ci_run zk_supervisor test integration --no-deps --ignore-prerequisites --chain custom_token &> ${{ env.INTEGRATION_TESTS_LOGS_DIR }}/custom_token.log & PID3=$! + ci_run zk_supervisor test integration --no-deps --ignore-prerequisites --chain consensus &> ${{ env.INTEGRATION_TESTS_LOGS_DIR }}/consensus.log & + PID4=$! + wait $PID1 wait $PID2 wait $PID3 + wait $PID4 - name: Init external nodes run: | @@ -173,6 +205,10 @@ jobs: --db-name=zksync_en_localhost_era_custom_token --l1-rpc-url=http://localhost:8545 --chain custom_token ci_run zk_inception external-node init --ignore-prerequisites --chain custom_token + ci_run zk_inception external-node configs --db-url=postgres://postgres:notsecurepassword@localhost:5432 \ + --db-name=zksync_en_localhost_era_consensus --l1-rpc-url=http://localhost:8545 --chain consensus + ci_run zk_inception external-node init --ignore-prerequisites --chain consensus + - name: Run recovery tests (from snapshot) run: | @@ -185,9 +221,13 @@ jobs: ci_run zk_supervisor test recovery --snapshot --no-deps --ignore-prerequisites --verbose --chain custom_token &> ${{ env.SNAPSHOT_RECOVERY_LOGS_DIR }}//custom_token.log & PID3=$! + ci_run zk_supervisor test recovery --snapshot --no-deps --ignore-prerequisites --verbose --chain consensus &> ${{ env.SNAPSHOT_RECOVERY_LOGS_DIR }}//consensus.log & + PID4=$! + wait $PID1 wait $PID2 wait $PID3 + wait $PID4 - name: Run recovery tests (from genesis) run: | @@ -200,15 +240,20 @@ jobs: ci_run zk_supervisor test recovery --no-deps --no-kill --ignore-prerequisites --verbose --chain custom_token &> ${{ env.GENESIS_RECOVERY_LOGS_DIR }}/custom_token.log & PID3=$! + ci_run zk_supervisor test recovery --no-deps --no-kill --ignore-prerequisites --verbose --chain consensus &> ${{ env.GENESIS_RECOVERY_LOGS_DIR }}/consensus.log & + PID4=$! + wait $PID1 wait $PID2 wait $PID3 + wait $PID4 - name: Run external node server run: | ci_run zk_inception external-node run --ignore-prerequisites --chain era &> ${{ env.EXTERNAL_NODE_LOGS_DIR }}/rollup.log & ci_run zk_inception external-node run --ignore-prerequisites --chain validium &> ${{ env.EXTERNAL_NODE_LOGS_DIR }}/validium.log & ci_run zk_inception external-node run --ignore-prerequisites --chain custom_token &> ${{ env.EXTERNAL_NODE_LOGS_DIR }}/custom_token.log & + ci_run zk_inception external-node run --ignore-prerequisites --chain consensus --enable-consensus &> ${{ env.EXTERNAL_NODE_LOGS_DIR }}/consensus.log & ci_run sleep 5 - name: Run integration tests en @@ -222,9 +267,13 @@ jobs: ci_run zk_supervisor test integration --no-deps --ignore-prerequisites --external-node --chain custom_token &> ${{ env.INTEGRATION_TESTS_EN_LOGS_DIR }}/custom_token.log & PID3=$! + ci_run zk_supervisor test integration --no-deps --ignore-prerequisites --external-node --chain consensus &> ${{ env.INTEGRATION_TESTS_EN_LOGS_DIR }}/consensus.log & + PID4=$! + wait $PID1 wait $PID2 wait $PID3 + wait $PID4 - name: Run revert tests run: | @@ -239,10 +288,14 @@ jobs: ci_run zk_supervisor test revert --no-deps --external-node --no-kill --ignore-prerequisites --chain custom_token &> ${{ env.REVERT_LOGS_DIR }}/custom_token.log & PID3=$! + + ci_run zk_supervisor test revert --no-deps --external-node --no-kill --ignore-prerequisites --chain consensus &> ${{ env.REVERT_LOGS_DIR }}/consensus.log & + PID4=$! wait $PID1 wait $PID2 wait $PID3 + wait $PID4 # Upgrade tests should run last, because as soon as they diff --git a/core/bin/external_node/src/config/mod.rs b/core/bin/external_node/src/config/mod.rs index cd4e845b8f3e..f8241deae26c 100644 --- a/core/bin/external_node/src/config/mod.rs +++ b/core/bin/external_node/src/config/mod.rs @@ -1217,6 +1217,7 @@ pub(crate) struct ExternalNodeConfig { pub observability: ObservabilityENConfig, pub experimental: ExperimentalENConfig, pub consensus: Option, + pub consensus_secrets: Option, pub api_component: ApiComponentConfig, pub tree_component: TreeComponentConfig, pub remote: R, @@ -1240,6 +1241,8 @@ impl ExternalNodeConfig<()> { tree_component: envy::prefixed("EN_TREE_") .from_env::() .context("could not load external node config (tree component params)")?, + consensus_secrets: read_consensus_secrets() + .context("config::read_consensus_secrets()")?, remote: (), }) } @@ -1262,7 +1265,7 @@ impl ExternalNodeConfig<()> { .map(read_yaml_repr::) .transpose() .context("failed decoding consensus YAML config")?; - + let consensus_secrets = secrets_config.consensus.clone(); let required = RequiredENConfig::from_configs( &general_config, &external_node_config, @@ -1298,6 +1301,7 @@ impl ExternalNodeConfig<()> { consensus, api_component, tree_component, + consensus_secrets, remote: (), }) } @@ -1332,6 +1336,7 @@ impl ExternalNodeConfig<()> { consensus: self.consensus, tree_component: self.tree_component, api_component: self.api_component, + consensus_secrets: self.consensus_secrets, remote, }) } @@ -1348,6 +1353,7 @@ impl ExternalNodeConfig { observability: ObservabilityENConfig::default(), experimental: ExperimentalENConfig::mock(), consensus: None, + consensus_secrets: None, api_component: ApiComponentConfig { tree_api_remote_url: None, }, diff --git a/core/bin/external_node/src/node_builder.rs b/core/bin/external_node/src/node_builder.rs index 7b94ca7a0c2a..98e286c253a2 100644 --- a/core/bin/external_node/src/node_builder.rs +++ b/core/bin/external_node/src/node_builder.rs @@ -56,11 +56,7 @@ use zksync_node_framework::{ }; use zksync_state::RocksdbStorageOptions; -use crate::{ - config::{self, ExternalNodeConfig}, - metrics::framework::ExternalNodeMetricsLayer, - Component, -}; +use crate::{config::ExternalNodeConfig, metrics::framework::ExternalNodeMetricsLayer, Component}; /// Builder for the external node. #[derive(Debug)] @@ -240,8 +236,7 @@ impl ExternalNodeBuilder { fn add_consensus_layer(mut self) -> anyhow::Result { let config = self.config.consensus.clone(); - let secrets = - config::read_consensus_secrets().context("config::read_consensus_secrets()")?; + let secrets = self.config.consensus_secrets.clone(); let layer = ExternalNodeConsensusLayer { build_version: crate::metadata::SERVER_VERSION .parse() diff --git a/core/lib/config/src/configs/consensus.rs b/core/lib/config/src/configs/consensus.rs index e5e01f880feb..759e13128338 100644 --- a/core/lib/config/src/configs/consensus.rs +++ b/core/lib/config/src/configs/consensus.rs @@ -1,6 +1,7 @@ use std::collections::{BTreeMap, BTreeSet}; -use secrecy::{ExposeSecret as _, Secret}; +use secrecy::ExposeSecret as _; +pub use secrecy::Secret; use zksync_basic_types::{ethabi, L2ChainId}; use zksync_concurrency::{limiter, time}; diff --git a/zk_toolbox/Cargo.lock b/zk_toolbox/Cargo.lock index 7c53e2747daf..eb16477382c2 100644 --- a/zk_toolbox/Cargo.lock +++ b/zk_toolbox/Cargo.lock @@ -409,6 +409,18 @@ dependencies = [ "generic-array", ] +[[package]] +name = "blst" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4378725facc195f1a538864863f6de233b500a8862747e7f165078a419d5e874" +dependencies = [ + "cc", + "glob", + "threadpool", + "zeroize", +] + [[package]] name = "bs58" version = "0.5.1" @@ -631,7 +643,7 @@ dependencies = [ "hmac", "once_cell", "pbkdf2 0.12.2", - "rand", + "rand 0.8.5", "sha2", "thiserror", ] @@ -709,7 +721,7 @@ dependencies = [ "clap", "common", "ethers", - "rand", + "rand 0.8.5", "serde", "serde_json", "strum", @@ -857,7 +869,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" dependencies = [ "generic-array", - "rand_core", + "rand_core 0.6.4", "subtle", "zeroize", ] @@ -869,7 +881,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ "generic-array", - "rand_core", + "rand_core 0.6.4", "subtle", "zeroize", ] @@ -903,6 +915,33 @@ dependencies = [ "cipher", ] +[[package]] +name = "curve25519-dalek" +version = "4.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest", + "fiat-crypto", + "rustc_version", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + [[package]] name = "darling" version = "0.13.4" @@ -1120,6 +1159,31 @@ dependencies = [ "spki 0.7.3", ] +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "pkcs8 0.10.2", + "signature 2.2.0", +] + +[[package]] +name = "ed25519-dalek" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" +dependencies = [ + "curve25519-dalek", + "ed25519", + "rand_core 0.6.4", + "serde", + "sha2", + "subtle", + "zeroize", +] + [[package]] name = "either" version = "1.13.0" @@ -1143,7 +1207,7 @@ dependencies = [ "generic-array", "group 0.12.1", "pkcs8 0.9.0", - "rand_core", + "rand_core 0.6.4", "sec1 0.3.0", "subtle", "zeroize", @@ -1162,7 +1226,7 @@ dependencies = [ "generic-array", "group 0.13.0", "pkcs8 0.10.2", - "rand_core", + "rand_core 0.6.4", "sec1 0.7.3", "subtle", "zeroize", @@ -1212,7 +1276,7 @@ dependencies = [ "hex", "k256 0.13.3", "log", - "rand", + "rand 0.8.5", "rlp", "serde", "sha3", @@ -1267,7 +1331,7 @@ dependencies = [ "hex", "hmac", "pbkdf2 0.11.0", - "rand", + "rand 0.8.5", "scrypt", "serde", "serde_json", @@ -1430,7 +1494,7 @@ dependencies = [ "num_enum 0.7.2", "once_cell", "open-fastrlp", - "rand", + "rand 0.8.5", "rlp", "serde", "serde_json", @@ -1535,7 +1599,7 @@ dependencies = [ "elliptic-curve 0.13.8", "eth-keystore", "ethers-core", - "rand", + "rand 0.8.5", "sha2", "thiserror", "tracing", @@ -1606,7 +1670,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" dependencies = [ - "rand_core", + "rand_core 0.6.4", "subtle", ] @@ -1616,10 +1680,44 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" dependencies = [ - "rand_core", + "rand_core 0.6.4", "subtle", ] +[[package]] +name = "ff_ce" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b538e4231443a5b9c507caee3356f016d832cf7393d2d90f03ea3180d4e3fbc" +dependencies = [ + "byteorder", + "ff_derive_ce", + "hex", + "rand 0.4.6", + "serde", +] + +[[package]] +name = "ff_derive_ce" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b96fbccd88dbb1fac4ee4a07c2fcc4ca719a74ffbd9d2b9d41d8c8eb073d8b20" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", + "proc-macro2", + "quote", + "serde", + "syn 1.0.109", +] + +[[package]] +name = "fiat-crypto" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" + [[package]] name = "findshlibs" version = "0.10.2" @@ -1639,7 +1737,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" dependencies = [ "byteorder", - "rand", + "rand 0.8.5", "rustc-hex", "static_assertions", ] @@ -1711,6 +1809,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" + [[package]] name = "funty" version = "2.0.0" @@ -1899,7 +2003,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" dependencies = [ "ff 0.12.1", - "rand_core", + "rand_core 0.6.4", "subtle", ] @@ -1910,7 +2014,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ "ff 0.13.0", - "rand_core", + "rand_core 0.6.4", "subtle", ] @@ -2740,7 +2844,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ffa00dec017b5b1a8b7cf5e2c008bfda1aa7e0697ac1508b491fdf2622fb4d8" dependencies = [ - "rand", + "rand 0.8.5", ] [[package]] @@ -2823,7 +2927,7 @@ dependencies = [ "num-integer", "num-iter", "num-traits", - "rand", + "rand 0.8.5", "smallvec", "zeroize", ] @@ -3119,7 +3223,7 @@ dependencies = [ "once_cell", "opentelemetry", "percent-encoding", - "rand", + "rand 0.8.5", "serde_json", "thiserror", "tokio", @@ -3158,6 +3262,19 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" +[[package]] +name = "pairing_ce" +version = "0.28.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843b5b6fb63f00460f611dbc87a50bbbb745f0dfe5cbf67ca89299c79098640e" +dependencies = [ + "byteorder", + "cfg-if", + "ff_ce", + "rand 0.4.6", + "serde", +] + [[package]] name = "parity-scale-codec" version = "3.6.12" @@ -3220,7 +3337,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" dependencies = [ "base64ct", - "rand_core", + "rand_core 0.6.4", "subtle", ] @@ -3319,7 +3436,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" dependencies = [ "phf_shared 0.11.2", - "rand", + "rand 0.8.5", ] [[package]] @@ -3530,7 +3647,7 @@ dependencies = [ "bitflags 2.6.0", "lazy_static", "num-traits", - "rand", + "rand 0.8.5", "rand_chacha", "rand_xorshift", "regex-syntax 0.8.4", @@ -3680,6 +3797,19 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" +[[package]] +name = "rand" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" +dependencies = [ + "fuchsia-cprng", + "libc", + "rand_core 0.3.1", + "rdrand", + "winapi", +] + [[package]] name = "rand" version = "0.8.5" @@ -3688,7 +3818,7 @@ checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", - "rand_core", + "rand_core 0.6.4", ] [[package]] @@ -3698,9 +3828,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +dependencies = [ + "rand_core 0.4.2", ] +[[package]] +name = "rand_core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" + [[package]] name = "rand_core" version = "0.6.4" @@ -3716,7 +3861,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" dependencies = [ - "rand_core", + "rand_core 0.6.4", ] [[package]] @@ -3739,6 +3884,15 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +dependencies = [ + "rand_core 0.3.1", +] + [[package]] name = "redox_syscall" version = "0.4.1" @@ -3995,7 +4149,7 @@ dependencies = [ "num-traits", "pkcs1", "pkcs8 0.10.2", - "rand_core", + "rand_core 0.6.4", "signature 2.2.0", "spki 0.7.3", "subtle", @@ -4349,7 +4503,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "901f761681f97db3db836ef9e094acdd8756c40215326c194201941947164ef1" dependencies = [ "once_cell", - "rand", + "rand 0.8.5", "sentry-types", "serde", "serde_json", @@ -4396,7 +4550,7 @@ checksum = "da956cca56e0101998c8688bc65ce1a96f00673a0e58e663664023d4c7911e82" dependencies = [ "debugid", "hex", - "rand", + "rand 0.8.5", "serde", "serde_json", "thiserror", @@ -4586,7 +4740,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" dependencies = [ "digest", - "rand_core", + "rand_core 0.6.4", ] [[package]] @@ -4596,7 +4750,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ "digest", - "rand_core", + "rand_core 0.6.4", ] [[package]] @@ -4840,7 +4994,7 @@ dependencies = [ "memchr", "once_cell", "percent-encoding", - "rand", + "rand 0.8.5", "rsa", "serde", "sha1", @@ -4879,7 +5033,7 @@ dependencies = [ "md-5", "memchr", "once_cell", - "rand", + "rand 0.8.5", "serde", "serde_json", "sha2", @@ -5145,6 +5299,15 @@ dependencies = [ "once_cell", ] +[[package]] +name = "threadpool" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", +] + [[package]] name = "time" version = "0.3.36" @@ -5397,7 +5560,7 @@ dependencies = [ "indexmap 1.9.3", "pin-project", "pin-project-lite", - "rand", + "rand 0.8.5", "slab", "tokio", "tokio-util", @@ -5540,7 +5703,7 @@ dependencies = [ "http 0.2.12", "httparse", "log", - "rand", + "rand 0.8.5", "rustls 0.21.12", "sha1", "thiserror", @@ -6277,6 +6440,7 @@ dependencies = [ "ethers", "human-panic", "lazy_static", + "secrecy", "serde", "serde_json", "serde_yaml", @@ -6290,6 +6454,8 @@ dependencies = [ "xshell", "zksync_basic_types", "zksync_config", + "zksync_consensus_crypto", + "zksync_consensus_roles", ] [[package]] @@ -6356,7 +6522,7 @@ dependencies = [ "anyhow", "once_cell", "pin-project", - "rand", + "rand 0.8.5", "sha3", "thiserror", "time", @@ -6371,7 +6537,7 @@ name = "zksync_config" version = "0.1.0" dependencies = [ "anyhow", - "rand", + "rand 0.8.5", "secrecy", "serde", "url", @@ -6381,6 +6547,52 @@ dependencies = [ "zksync_crypto_primitives", ] +[[package]] +name = "zksync_consensus_crypto" +version = "0.1.0-rc.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace39bdf50b8421c4d546381fe1ecc5212f953ce61cf93d4fa69172078dbe4af" +dependencies = [ + "anyhow", + "blst", + "ed25519-dalek", + "elliptic-curve 0.13.8", + "ff_ce", + "hex", + "k256 0.13.3", + "num-bigint", + "num-traits", + "pairing_ce", + "rand 0.4.6", + "rand 0.8.5", + "sha3", + "thiserror", + "tracing", + "zeroize", +] + +[[package]] +name = "zksync_consensus_roles" +version = "0.1.0-rc.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06277266e31efdc1465f6a27ce96c7435392a270978a91956b8a848732df2cfa" +dependencies = [ + "anyhow", + "bit-vec", + "hex", + "num-bigint", + "prost 0.12.6", + "rand 0.8.5", + "serde", + "thiserror", + "tracing", + "zksync_concurrency", + "zksync_consensus_crypto", + "zksync_consensus_utils", + "zksync_protobuf", + "zksync_protobuf_build", +] + [[package]] name = "zksync_consensus_utils" version = "0.1.0-rc.12" @@ -6388,7 +6600,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d624f55e2449f43b2c85588b5dd2a28b3c5ea629effc89df76e3254f8d9d2fb" dependencies = [ "anyhow", - "rand", + "rand 0.8.5", "thiserror", "zksync_concurrency", ] @@ -6413,7 +6625,7 @@ dependencies = [ "anyhow", "blake2", "hex", - "rand", + "rand 0.8.5", "secp256k1", "serde", "serde_json", @@ -6444,7 +6656,7 @@ dependencies = [ "prost 0.12.6", "prost-reflect", "quick-protobuf", - "rand", + "rand 0.8.5", "serde", "serde_json", "serde_yaml", @@ -6477,7 +6689,7 @@ dependencies = [ "anyhow", "hex", "prost 0.12.6", - "rand", + "rand 0.8.5", "secrecy", "serde_json", "serde_yaml", diff --git a/zk_toolbox/Cargo.toml b/zk_toolbox/Cargo.toml index e1ad63136af1..126c44f0eaeb 100644 --- a/zk_toolbox/Cargo.toml +++ b/zk_toolbox/Cargo.toml @@ -30,6 +30,8 @@ types = { path = "crates/types" } zksync_config = { path = "../core/lib/config" } zksync_protobuf_config = { path = "../core/lib/protobuf_config" } zksync_basic_types = { path = "../core/lib/basic_types" } +zksync_consensus_roles = "=0.1.0-rc.12" +zksync_consensus_crypto = "=0.1.0-rc.12" zksync_protobuf = "=0.1.0-rc.12" # External dependencies @@ -59,3 +61,4 @@ toml = "0.8.12" url = { version = "2.5.0", features = ["serde"] } xshell = "0.2.6" clap-markdown = "0.1.4" +secrecy = "0.8.0" diff --git a/zk_toolbox/crates/common/src/external_node.rs b/zk_toolbox/crates/common/src/external_node.rs index 09115f92d5fb..8a5cbc3cd14c 100644 --- a/zk_toolbox/crates/common/src/external_node.rs +++ b/zk_toolbox/crates/common/src/external_node.rs @@ -9,6 +9,7 @@ pub fn run( config_path: &str, secrets_path: &str, en_config_path: &str, + consensus_args: Vec, additional_args: Vec, ) -> anyhow::Result<()> { let _dir = shell.push_dir(code_path); @@ -22,6 +23,7 @@ pub fn run( --external-node-config-path {en_config_path} " ) + .args(consensus_args) .args(additional_args) .env_remove("RUSTUP_TOOLCHAIN"), ) diff --git a/zk_toolbox/crates/config/src/consensus_config.rs b/zk_toolbox/crates/config/src/consensus_config.rs new file mode 100644 index 000000000000..0bb4750d1fc0 --- /dev/null +++ b/zk_toolbox/crates/config/src/consensus_config.rs @@ -0,0 +1,18 @@ +use zksync_config::configs::consensus::ConsensusConfig; +use zksync_protobuf_config::encode_yaml_repr; + +use crate::{ + traits::{FileConfigWithDefaultName, SaveConfig}, + CONSENSUS_CONFIG_FILE, +}; + +impl FileConfigWithDefaultName for ConsensusConfig { + const FILE_NAME: &'static str = CONSENSUS_CONFIG_FILE; +} + +impl SaveConfig for ConsensusConfig { + fn save(&self, shell: &xshell::Shell, path: impl AsRef) -> anyhow::Result<()> { + let bytes = encode_yaml_repr::(self)?; + Ok(shell.write_file(path.as_ref(), bytes)?) + } +} diff --git a/zk_toolbox/crates/config/src/consensus_secrets.rs b/zk_toolbox/crates/config/src/consensus_secrets.rs new file mode 100644 index 000000000000..0e5c4592d2fc --- /dev/null +++ b/zk_toolbox/crates/config/src/consensus_secrets.rs @@ -0,0 +1,14 @@ +use std::path::Path; + +use xshell::Shell; +use zksync_config::configs::consensus::ConsensusSecrets; +use zksync_protobuf_config::decode_yaml_repr; + +use crate::traits::ReadConfig; + +impl ReadConfig for ConsensusSecrets { + fn read(shell: &Shell, path: impl AsRef) -> anyhow::Result { + let path = shell.current_dir().join(path); + decode_yaml_repr::(&path, false) + } +} diff --git a/zk_toolbox/crates/config/src/consts.rs b/zk_toolbox/crates/config/src/consts.rs index 1e1c0998f00e..80b204cc6191 100644 --- a/zk_toolbox/crates/config/src/consts.rs +++ b/zk_toolbox/crates/config/src/consts.rs @@ -11,6 +11,8 @@ pub const GENESIS_FILE: &str = "genesis.yaml"; // Name of external node specific config pub const EN_CONFIG_FILE: &str = "external_node.yaml"; +// Name of consensus config +pub const CONSENSUS_CONFIG_FILE: &str = "consensus_config.yaml"; pub(crate) const ERC20_CONFIGS_FILE: &str = "erc20.yaml"; /// Name of the initial deployments config file pub(crate) const INITIAL_DEPLOYMENT_FILE: &str = "initial_deployments.yaml"; @@ -60,6 +62,8 @@ pub const DEFAULT_EXPLORER_WORKER_PORT: u16 = 3001; pub const DEFAULT_EXPLORER_API_PORT: u16 = 3002; /// Default port for the explorer data fetcher service pub const DEFAULT_EXPLORER_DATA_FETCHER_PORT: u16 = 3040; +/// Default port for consensus service +pub const DEFAULT_CONSENSUS_PORT: u16 = 3054; pub const EXPLORER_API_DOCKER_IMAGE: &str = "matterlabs/block-explorer-api"; pub const EXPLORER_DATA_FETCHER_DOCKER_IMAGE: &str = "matterlabs/block-explorer-data-fetcher"; diff --git a/zk_toolbox/crates/config/src/general.rs b/zk_toolbox/crates/config/src/general.rs index 41c2e4c33cfd..6498beb0f532 100644 --- a/zk_toolbox/crates/config/src/general.rs +++ b/zk_toolbox/crates/config/src/general.rs @@ -3,19 +3,21 @@ use std::path::{Path, PathBuf}; use anyhow::Context; use url::Url; use xshell::Shell; -use zksync_config::configs::object_store::ObjectStoreMode; pub use zksync_config::configs::GeneralConfig; +use zksync_config::configs::{consensus::Host, object_store::ObjectStoreMode}; use zksync_protobuf_config::{decode_yaml_repr, encode_yaml_repr}; use crate::{ consts::GENERAL_FILE, traits::{ConfigWithL2RpcUrl, FileConfigWithDefaultName, ReadConfig, SaveConfig}, + DEFAULT_CONSENSUS_PORT, }; pub struct RocksDbs { pub state_keeper: PathBuf, pub merkle_tree: PathBuf, pub protective_reads: PathBuf, + pub basic_witness_input_producer: PathBuf, } pub struct FileArtifacts { @@ -54,6 +56,15 @@ pub fn set_rocks_db_config(config: &mut GeneralConfig, rocks_dbs: RocksDbs) -> a .as_mut() .context("Protective reads config is not presented")? .db_path = rocks_dbs.protective_reads.to_str().unwrap().to_string(); + config + .basic_witness_input_producer_config + .as_mut() + .context("Basic witness input producer config is not presented")? + .db_path = rocks_dbs + .basic_witness_input_producer + .to_str() + .unwrap() + .to_string(); Ok(()) } @@ -104,6 +115,11 @@ pub fn set_file_artifacts(config: &mut GeneralConfig, file_artifacts: FileArtifa pub fn ports_config(config: &GeneralConfig) -> Option { let api = config.api_config.as_ref()?; let contract_verifier = config.contract_verifier.as_ref()?; + let consensus_port = if let Some(consensus_config) = config.clone().consensus_config { + consensus_config.server_addr.port() + } else { + DEFAULT_CONSENSUS_PORT + }; Some(PortsConfig { web3_json_rpc_http_port: api.web3_json_rpc.http_port, @@ -112,6 +128,7 @@ pub fn ports_config(config: &GeneralConfig) -> Option { merkle_tree_port: api.merkle_tree.port, prometheus_listener_port: api.prometheus.listener_port, contract_verifier_port: contract_verifier.port, + consensus_port, }) } @@ -128,6 +145,10 @@ pub fn update_ports(config: &mut GeneralConfig, ports_config: &PortsConfig) -> a .prometheus_config .as_mut() .context("Prometheus config is not presented")?; + if let Some(consensus) = config.consensus_config.as_mut() { + consensus.server_addr.set_port(ports_config.consensus_port); + update_port_in_host(&mut consensus.public_addr, ports_config.consensus_port)?; + } api.web3_json_rpc.http_port = ports_config.web3_json_rpc_http_port; update_port_in_url( @@ -162,6 +183,13 @@ fn update_port_in_url(http_url: &mut String, port: u16) -> anyhow::Result<()> { Ok(()) } +fn update_port_in_host(host: &mut Host, port: u16) -> anyhow::Result<()> { + let url = Url::parse(&format!("http://{}", host.0))?; + let host_str = url.host_str().context("Failed to get host")?; + host.0 = format!("{host_str}:{port}"); + Ok(()) +} + impl FileConfigWithDefaultName for GeneralConfig { const FILE_NAME: &'static str = GENERAL_FILE; } @@ -173,6 +201,7 @@ pub struct PortsConfig { pub merkle_tree_port: u16, pub prometheus_listener_port: u16, pub contract_verifier_port: u16, + pub consensus_port: u16, } impl PortsConfig { @@ -183,6 +212,7 @@ impl PortsConfig { self.merkle_tree_port += offset; self.prometheus_listener_port += offset; self.contract_verifier_port += offset; + self.consensus_port += offset; } pub fn next_empty_ports_config(&self) -> PortsConfig { @@ -193,6 +223,7 @@ impl PortsConfig { merkle_tree_port: self.merkle_tree_port + 100, prometheus_listener_port: self.prometheus_listener_port + 100, contract_verifier_port: self.contract_verifier_port + 100, + consensus_port: self.consensus_port + 100, } } } diff --git a/zk_toolbox/crates/config/src/lib.rs b/zk_toolbox/crates/config/src/lib.rs index 3c7443f24490..1a7c5bf1d7e2 100644 --- a/zk_toolbox/crates/config/src/lib.rs +++ b/zk_toolbox/crates/config/src/lib.rs @@ -25,6 +25,8 @@ mod secrets; mod wallet_creation; mod wallets; +pub mod consensus_config; +pub mod consensus_secrets; pub mod docker_compose; pub mod explorer; pub mod explorer_compose; diff --git a/zk_toolbox/crates/zk_inception/Cargo.toml b/zk_toolbox/crates/zk_inception/Cargo.toml index 01d0697d6b6c..61983d59e6e9 100644 --- a/zk_toolbox/crates/zk_inception/Cargo.toml +++ b/zk_toolbox/crates/zk_inception/Cargo.toml @@ -34,3 +34,6 @@ zksync_config.workspace = true slugify-rs.workspace = true zksync_basic_types.workspace = true clap-markdown.workspace = true +zksync_consensus_roles.workspace = true +zksync_consensus_crypto.workspace = true +secrecy.workspace = true diff --git a/zk_toolbox/crates/zk_inception/src/commands/chain/init.rs b/zk_toolbox/crates/zk_inception/src/commands/chain/init.rs index 2b7dbf73f681..734e5e54863b 100644 --- a/zk_toolbox/crates/zk_inception/src/commands/chain/init.rs +++ b/zk_toolbox/crates/zk_inception/src/commands/chain/init.rs @@ -35,11 +35,14 @@ use crate::{ messages::{ msg_initializing_chain, MSG_ACCEPTING_ADMIN_SPINNER, MSG_CHAIN_INITIALIZED, MSG_CHAIN_NOT_FOUND_ERR, MSG_DISTRIBUTING_ETH_SPINNER, MSG_GENESIS_DATABASE_ERR, - MSG_MINT_BASE_TOKEN_SPINNER, MSG_PORTAL_FAILED_TO_CREATE_CONFIG_ERR, + MSG_MINT_BASE_TOKEN_SPINNER, MSG_PORTAL_FAILED_TO_CREATE_CONFIG_ERR, MSG_PORTS_CONFIG_ERR, MSG_REGISTERING_CHAIN_SPINNER, MSG_SELECTED_CONFIG, MSG_UPDATING_TOKEN_MULTIPLIER_SETTER_SPINNER, MSG_WALLET_TOKEN_MULTIPLIER_SETTER_NOT_FOUND, }, - utils::forge::{check_the_balance, fill_forge_private_key}, + utils::{ + consensus::{generate_consensus_keys, get_consensus_config, get_consensus_secrets}, + forge::{check_the_balance, fill_forge_private_key}, + }, }; pub(crate) async fn run(args: InitArgs, shell: &Shell) -> anyhow::Result<()> { @@ -70,6 +73,12 @@ pub async fn init( let mut general_config = chain_config.get_general_config()?; apply_port_offset(init_args.port_offset, &mut general_config)?; + let ports = ports_config(&general_config).context(MSG_PORTS_CONFIG_ERR)?; + + let consensus_keys = generate_consensus_keys(); + let consensus_config = + get_consensus_config(chain_config, ports, Some(consensus_keys.clone()), None)?; + general_config.consensus_config = Some(consensus_config); general_config.save_with_base_path(shell, &chain_config.configs)?; let mut genesis_config = chain_config.get_genesis_config()?; @@ -86,6 +95,7 @@ pub async fn init( let mut secrets = chain_config.get_secrets_config()?; set_l1_rpc_url(&mut secrets, init_args.l1_rpc_url.clone())?; + secrets.consensus = Some(get_consensus_secrets(&consensus_keys)); secrets.save_with_base_path(shell, &chain_config.configs)?; let spinner = Spinner::new(MSG_REGISTERING_CHAIN_SPINNER); diff --git a/zk_toolbox/crates/zk_inception/src/commands/external_node/args/run.rs b/zk_toolbox/crates/zk_inception/src/commands/external_node/args/run.rs index 1bc0c06728d7..cd6ff4c71534 100644 --- a/zk_toolbox/crates/zk_inception/src/commands/external_node/args/run.rs +++ b/zk_toolbox/crates/zk_inception/src/commands/external_node/args/run.rs @@ -1,7 +1,9 @@ use clap::Parser; use serde::{Deserialize, Serialize}; -use crate::messages::{MSG_SERVER_ADDITIONAL_ARGS_HELP, MSG_SERVER_COMPONENTS_HELP}; +use crate::messages::{ + MSG_ENABLE_CONSENSUS_HELP, MSG_SERVER_ADDITIONAL_ARGS_HELP, MSG_SERVER_COMPONENTS_HELP, +}; #[derive(Debug, Serialize, Deserialize, Parser)] pub struct RunExternalNodeArgs { @@ -9,6 +11,8 @@ pub struct RunExternalNodeArgs { pub reinit: bool, #[clap(long, help = MSG_SERVER_COMPONENTS_HELP)] pub components: Option>, + #[clap(long, help = MSG_ENABLE_CONSENSUS_HELP, default_missing_value = "true", num_args = 0..=1)] + pub enable_consensus: Option, #[clap(long, short)] #[arg(trailing_var_arg = true, allow_hyphen_values = true, hide = false, help = MSG_SERVER_ADDITIONAL_ARGS_HELP)] pub additional_args: Vec, diff --git a/zk_toolbox/crates/zk_inception/src/commands/external_node/prepare_configs.rs b/zk_toolbox/crates/zk_inception/src/commands/external_node/prepare_configs.rs index 51101c228878..89e08418c6e5 100644 --- a/zk_toolbox/crates/zk_inception/src/commands/external_node/prepare_configs.rs +++ b/zk_toolbox/crates/zk_inception/src/commands/external_node/prepare_configs.rs @@ -1,4 +1,4 @@ -use std::{path::Path, str::FromStr}; +use std::{collections::BTreeMap, path::Path, str::FromStr}; use anyhow::Context; use common::{config::global_config, logger}; @@ -8,14 +8,24 @@ use config::{ }; use xshell::Shell; use zksync_basic_types::url::SensitiveUrl; -use zksync_config::configs::{DatabaseSecrets, L1Secrets}; +use zksync_config::configs::{ + consensus::{ConsensusSecrets, NodeSecretKey, Secret}, + DatabaseSecrets, L1Secrets, +}; +use zksync_consensus_crypto::TextFmt; +use zksync_consensus_roles as roles; use crate::{ commands::external_node::args::prepare_configs::{PrepareConfigArgs, PrepareConfigFinal}, messages::{ - msg_preparing_en_config_is_done, MSG_CHAIN_NOT_INITIALIZED, MSG_PREPARING_EN_CONFIGS, + msg_preparing_en_config_is_done, MSG_CHAIN_NOT_INITIALIZED, + MSG_CONSENSUS_CONFIG_MISSING_ERR, MSG_CONSENSUS_SECRETS_MISSING_ERR, + MSG_CONSENSUS_SECRETS_NODE_KEY_MISSING_ERR, MSG_PORTS_CONFIG_ERR, MSG_PREPARING_EN_CONFIGS, + }, + utils::{ + consensus::{get_consensus_config, node_public_key}, + rocks_db::{recreate_rocksdb_dirs, RocksDBDirOption}, }, - utils::rocks_db::{recreate_rocksdb_dirs, RocksDBDirOption}, }; pub fn run(shell: &Shell, args: PrepareConfigArgs) -> anyhow::Result<()> { @@ -64,15 +74,45 @@ fn prepare_configs( gateway_url: None, }; let mut general_en = general.clone(); + let next_empty_ports_config = ports_config(&general) + .context(MSG_PORTS_CONFIG_ERR)? + .next_empty_ports_config(); + update_ports(&mut general_en, &next_empty_ports_config)?; + + // Set consensus config + let main_node_consensus_config = general + .consensus_config + .context(MSG_CONSENSUS_CONFIG_MISSING_ERR)?; + + let mut gossip_static_outbound = BTreeMap::new(); + let main_node_public_key = node_public_key( + &config + .get_secrets_config()? + .consensus + .context(MSG_CONSENSUS_SECRETS_MISSING_ERR)?, + )? + .context(MSG_CONSENSUS_SECRETS_NODE_KEY_MISSING_ERR)?; - update_ports( - &mut general_en, - &ports_config(&general) - .context("da")? - .next_empty_ports_config(), + gossip_static_outbound.insert(main_node_public_key, main_node_consensus_config.public_addr); + + let en_consensus_config = get_consensus_config( + config, + next_empty_ports_config, + None, + Some(gossip_static_outbound), )?; + general_en.consensus_config = Some(en_consensus_config.clone()); + en_consensus_config.save_with_base_path(shell, en_configs_path)?; + + // Set secrets config + let node_key = roles::node::SecretKey::generate().encode(); + let consensus_secrets = ConsensusSecrets { + validator_key: None, + attester_key: None, + node_key: Some(NodeSecretKey(Secret::new(node_key))), + }; let secrets = SecretsConfig { - consensus: None, + consensus: Some(consensus_secrets), database: Some(DatabaseSecrets { server_url: Some(args.db.full_url().into()), prover_url: None, diff --git a/zk_toolbox/crates/zk_inception/src/commands/external_node/run.rs b/zk_toolbox/crates/zk_inception/src/commands/external_node/run.rs index 9d3da4663859..46328699e6d4 100644 --- a/zk_toolbox/crates/zk_inception/src/commands/external_node/run.rs +++ b/zk_toolbox/crates/zk_inception/src/commands/external_node/run.rs @@ -32,6 +32,7 @@ async fn run_external_node( if args.reinit { init::init(shell, chain_config).await? } + let enable_consensus = args.enable_consensus.unwrap_or(false); let server = RunExternalNode::new(args.components.clone(), chain_config)?; - server.run(shell, args.additional_args.clone()) + server.run(shell, enable_consensus, args.additional_args.clone()) } diff --git a/zk_toolbox/crates/zk_inception/src/consts.rs b/zk_toolbox/crates/zk_inception/src/consts.rs index 72c8948a65d1..22e570a5439e 100644 --- a/zk_toolbox/crates/zk_inception/src/consts.rs +++ b/zk_toolbox/crates/zk_inception/src/consts.rs @@ -1,3 +1,5 @@ +use std::net::{IpAddr, Ipv4Addr}; + pub const AMOUNT_FOR_DISTRIBUTION_TO_WALLETS: u128 = 1000000000000000000000; pub const MINIMUM_BALANCE_FOR_WALLET: u128 = 5000000000000000000; @@ -9,6 +11,27 @@ pub const DEFAULT_PROOF_STORE_DIR: &str = "artifacts"; pub const BELLMAN_CUDA_DIR: &str = "era-bellman-cuda"; pub const L2_BASE_TOKEN_ADDRESS: &str = "0x000000000000000000000000000000000000800A"; +#[allow(non_upper_case_globals)] +const kB: usize = 1024; + +/// Max payload size for consensus in bytes +pub const MAX_PAYLOAD_SIZE: usize = 2_500_000; +/// Max batch size for consensus in bytes +/// Compute a default batch size, so operators are not caught out by the missing setting +/// while we're still working on batch syncing. The batch interval is ~1 minute, +/// so there will be ~60 blocks, and an Ethereum Merkle proof is ~1kB, but under high +/// traffic there can be thousands of huge transactions that quickly fill up blocks +/// and there could be more blocks in a batch then expected. We chose a generous +/// limit so as not to prevent any legitimate batch from being transmitted. +pub const MAX_BATCH_SIZE: usize = MAX_PAYLOAD_SIZE * 5000 + kB; +/// Gossip dynamic inbound limit for consensus +pub const GOSSIP_DYNAMIC_INBOUND_LIMIT: usize = 100; + +/// Public address for consensus +pub const CONSENSUS_PUBLIC_ADDRESS_HOST: IpAddr = IpAddr::V4(Ipv4Addr::UNSPECIFIED); +/// Server address for consensus +pub const CONSENSUS_SERVER_ADDRESS_HOST: IpAddr = IpAddr::V4(Ipv4Addr::LOCALHOST); + /// Path to the JS runtime config for the block-explorer-app docker container to be mounted to pub const EXPLORER_APP_DOCKER_CONFIG_PATH: &str = "/usr/src/app/packages/app/dist/config.js"; pub const EXPLORER_APP_DOCKER_IMAGE: &str = "matterlabs/block-explorer-app"; diff --git a/zk_toolbox/crates/zk_inception/src/defaults.rs b/zk_toolbox/crates/zk_inception/src/defaults.rs index 544e28377403..6c3821eed856 100644 --- a/zk_toolbox/crates/zk_inception/src/defaults.rs +++ b/zk_toolbox/crates/zk_inception/src/defaults.rs @@ -14,6 +14,7 @@ lazy_static! { pub const ROCKS_DB_STATE_KEEPER: &str = "state_keeper"; pub const ROCKS_DB_TREE: &str = "tree"; pub const ROCKS_DB_PROTECTIVE_READS: &str = "protective_reads"; +pub const ROCKS_DB_BASIC_WITNESS_INPUT_PRODUCER: &str = "basic_witness_input_producer"; pub const EN_ROCKS_DB_PREFIX: &str = "en"; pub const MAIN_ROCKS_DB_PREFIX: &str = "main"; diff --git a/zk_toolbox/crates/zk_inception/src/external_node.rs b/zk_toolbox/crates/zk_inception/src/external_node.rs index ef62738a7d2a..5ff4ce070250 100644 --- a/zk_toolbox/crates/zk_inception/src/external_node.rs +++ b/zk_toolbox/crates/zk_inception/src/external_node.rs @@ -6,6 +6,7 @@ use config::{ SecretsConfig, }; use xshell::Shell; +use zksync_config::configs::consensus::ConsensusConfig; use crate::messages::MSG_FAILED_TO_RUN_SERVER_ERR; @@ -15,6 +16,7 @@ pub struct RunExternalNode { general_config: PathBuf, secrets: PathBuf, en_config: PathBuf, + consensus_config: PathBuf, } impl RunExternalNode { @@ -29,6 +31,7 @@ impl RunExternalNode { let general_config = GeneralConfig::get_path_with_base_path(&en_path); let secrets = SecretsConfig::get_path_with_base_path(&en_path); let enconfig = ENConfig::get_path_with_base_path(&en_path); + let consensus_config = ConsensusConfig::get_path_with_base_path(&en_path); Ok(Self { components, @@ -36,17 +39,29 @@ impl RunExternalNode { general_config, secrets, en_config: enconfig, + consensus_config, }) } - pub fn run(&self, shell: &Shell, mut additional_args: Vec) -> anyhow::Result<()> { + pub fn run( + &self, + shell: &Shell, + enable_consensus: bool, + mut additional_args: Vec, + ) -> anyhow::Result<()> { let code_path = self.code_path.to_str().unwrap(); let config_general_config = &self.general_config.to_str().unwrap(); let en_config = &self.en_config.to_str().unwrap(); let secrets = &self.secrets.to_str().unwrap(); + let consensus_config = &self.consensus_config.to_str().unwrap(); if let Some(components) = self.components() { additional_args.push(format!("--components={}", components)) } + let mut consensus_args = vec![]; + if enable_consensus { + consensus_args.push("--enable-consensus".to_string()); + consensus_args.push(format!("--consensus-path={}", consensus_config)) + } common::external_node::run( shell, @@ -54,6 +69,7 @@ impl RunExternalNode { config_general_config, secrets, en_config, + consensus_args, additional_args, ) .context(MSG_FAILED_TO_RUN_SERVER_ERR) diff --git a/zk_toolbox/crates/zk_inception/src/messages.rs b/zk_toolbox/crates/zk_inception/src/messages.rs index 6fa1e293927b..c5b77f63ebae 100644 --- a/zk_toolbox/crates/zk_inception/src/messages.rs +++ b/zk_toolbox/crates/zk_inception/src/messages.rs @@ -220,6 +220,7 @@ pub(super) const MSG_DEPLOYING_PAYMASTER: &str = "Deploying paymaster"; /// Run server related messages pub(super) const MSG_SERVER_COMPONENTS_HELP: &str = "Components of server to run"; +pub(super) const MSG_ENABLE_CONSENSUS_HELP: &str = "Enable consensus"; pub(super) const MSG_SERVER_GENESIS_HELP: &str = "Run server in genesis mode"; pub(super) const MSG_SERVER_ADDITIONAL_ARGS_HELP: &str = "Additional arguments that can be passed through the CLI"; @@ -306,6 +307,11 @@ pub(super) fn msg_preparing_en_config_is_done(path: &Path) -> String { pub(super) const MSG_EXTERNAL_NODE_CONFIG_NOT_INITIALIZED: &str = "External node is not initialized"; +pub(super) const MSG_CONSENSUS_CONFIG_MISSING_ERR: &str = "Consensus config is missing"; +pub(super) const MSG_CONSENSUS_SECRETS_MISSING_ERR: &str = "Consensus secrets config is missing"; +pub(super) const MSG_CONSENSUS_SECRETS_NODE_KEY_MISSING_ERR: &str = "Consensus node key is missing"; + +pub(super) const MSG_PORTS_CONFIG_ERR: &str = "Failed to get ports config"; pub(super) const MSG_STARTING_EN: &str = "Starting external node"; diff --git a/zk_toolbox/crates/zk_inception/src/utils/consensus.rs b/zk_toolbox/crates/zk_inception/src/utils/consensus.rs new file mode 100644 index 000000000000..06848334a6e1 --- /dev/null +++ b/zk_toolbox/crates/zk_inception/src/utils/consensus.rs @@ -0,0 +1,124 @@ +use std::{ + collections::{BTreeMap, BTreeSet}, + net::SocketAddr, +}; + +use config::{ChainConfig, PortsConfig}; +use secrecy::{ExposeSecret, Secret}; +use zksync_config::configs::consensus::{ + AttesterPublicKey, AttesterSecretKey, ConsensusConfig, ConsensusSecrets, GenesisSpec, Host, + NodePublicKey, NodeSecretKey, ProtocolVersion, ValidatorPublicKey, ValidatorSecretKey, + WeightedAttester, WeightedValidator, +}; +use zksync_consensus_crypto::{Text, TextFmt}; +use zksync_consensus_roles as roles; + +use crate::consts::{ + CONSENSUS_PUBLIC_ADDRESS_HOST, CONSENSUS_SERVER_ADDRESS_HOST, GOSSIP_DYNAMIC_INBOUND_LIMIT, + MAX_BATCH_SIZE, MAX_PAYLOAD_SIZE, +}; + +#[derive(Debug, Clone)] +pub struct ConsensusSecretKeys { + validator_key: roles::validator::SecretKey, + attester_key: roles::attester::SecretKey, + node_key: roles::node::SecretKey, +} + +pub struct ConsensusPublicKeys { + validator_key: roles::validator::PublicKey, + attester_key: roles::attester::PublicKey, +} + +pub fn get_consensus_config( + chain_config: &ChainConfig, + ports: PortsConfig, + consensus_keys: Option, + gossip_static_outbound: Option>, +) -> anyhow::Result { + let genesis_spec = + consensus_keys.map(|consensus_keys| get_genesis_specs(chain_config, &consensus_keys)); + + let public_addr = SocketAddr::new(CONSENSUS_PUBLIC_ADDRESS_HOST, ports.consensus_port); + let server_addr = SocketAddr::new(CONSENSUS_SERVER_ADDRESS_HOST, ports.consensus_port); + + Ok(ConsensusConfig { + server_addr, + public_addr: Host(public_addr.encode()), + genesis_spec, + max_payload_size: MAX_PAYLOAD_SIZE, + gossip_dynamic_inbound_limit: GOSSIP_DYNAMIC_INBOUND_LIMIT, + max_batch_size: MAX_BATCH_SIZE, + gossip_static_inbound: BTreeSet::new(), + gossip_static_outbound: gossip_static_outbound.unwrap_or_default(), + rpc: None, + }) +} + +pub fn generate_consensus_keys() -> ConsensusSecretKeys { + ConsensusSecretKeys { + validator_key: roles::validator::SecretKey::generate(), + attester_key: roles::attester::SecretKey::generate(), + node_key: roles::node::SecretKey::generate(), + } +} + +fn get_consensus_public_keys(consensus_keys: &ConsensusSecretKeys) -> ConsensusPublicKeys { + ConsensusPublicKeys { + validator_key: consensus_keys.validator_key.public(), + attester_key: consensus_keys.attester_key.public(), + } +} + +pub fn get_genesis_specs( + chain_config: &ChainConfig, + consensus_keys: &ConsensusSecretKeys, +) -> GenesisSpec { + let public_keys = get_consensus_public_keys(consensus_keys); + let validator_key = public_keys.validator_key.encode(); + let attester_key = public_keys.attester_key.encode(); + + let validator = WeightedValidator { + key: ValidatorPublicKey(validator_key.clone()), + weight: 1, + }; + let attester = WeightedAttester { + key: AttesterPublicKey(attester_key), + weight: 1, + }; + let leader = ValidatorPublicKey(validator_key); + + GenesisSpec { + chain_id: chain_config.chain_id, + protocol_version: ProtocolVersion(1), + validators: vec![validator], + attesters: vec![attester], + leader, + registry_address: None, + } +} + +pub fn get_consensus_secrets(consensus_keys: &ConsensusSecretKeys) -> ConsensusSecrets { + let validator_key = consensus_keys.validator_key.encode(); + let attester_key = consensus_keys.attester_key.encode(); + let node_key = consensus_keys.node_key.encode(); + + ConsensusSecrets { + validator_key: Some(ValidatorSecretKey(Secret::new(validator_key))), + attester_key: Some(AttesterSecretKey(Secret::new(attester_key))), + node_key: Some(NodeSecretKey(Secret::new(node_key))), + } +} + +pub fn node_public_key(secrets: &ConsensusSecrets) -> anyhow::Result> { + Ok(node_key(secrets)?.map(|node_secret_key| NodePublicKey(node_secret_key.public().encode()))) +} +fn node_key(secrets: &ConsensusSecrets) -> anyhow::Result> { + read_secret_text(secrets.node_key.as_ref().map(|x| &x.0)) +} + +fn read_secret_text(text: Option<&Secret>) -> anyhow::Result> { + text.map(|text| Text::new(text.expose_secret()).decode()) + .transpose() + .map_err(|_| anyhow::format_err!("invalid format")) +} diff --git a/zk_toolbox/crates/zk_inception/src/utils/mod.rs b/zk_toolbox/crates/zk_inception/src/utils/mod.rs index a84f0a336de5..229d3908dc3a 100644 --- a/zk_toolbox/crates/zk_inception/src/utils/mod.rs +++ b/zk_toolbox/crates/zk_inception/src/utils/mod.rs @@ -1,2 +1,3 @@ +pub mod consensus; pub mod forge; pub mod rocks_db; diff --git a/zk_toolbox/crates/zk_inception/src/utils/rocks_db.rs b/zk_toolbox/crates/zk_inception/src/utils/rocks_db.rs index 17cffa66e39d..1b7e29dd9722 100644 --- a/zk_toolbox/crates/zk_inception/src/utils/rocks_db.rs +++ b/zk_toolbox/crates/zk_inception/src/utils/rocks_db.rs @@ -4,8 +4,8 @@ use config::RocksDbs; use xshell::Shell; use crate::defaults::{ - EN_ROCKS_DB_PREFIX, MAIN_ROCKS_DB_PREFIX, ROCKS_DB_PROTECTIVE_READS, ROCKS_DB_STATE_KEEPER, - ROCKS_DB_TREE, + EN_ROCKS_DB_PREFIX, MAIN_ROCKS_DB_PREFIX, ROCKS_DB_BASIC_WITNESS_INPUT_PRODUCER, + ROCKS_DB_PROTECTIVE_READS, ROCKS_DB_STATE_KEEPER, ROCKS_DB_TREE, }; pub enum RocksDBDirOption { @@ -37,9 +37,13 @@ pub fn recreate_rocksdb_dirs( .join(option.prefix()) .join(ROCKS_DB_PROTECTIVE_READS); shell.remove_path(&protective_reads)?; + let basic_witness_input_producer = rocks_db_path + .join(option.prefix()) + .join(ROCKS_DB_BASIC_WITNESS_INPUT_PRODUCER); Ok(RocksDbs { state_keeper: shell.create_dir(state_keeper)?, merkle_tree: shell.create_dir(merkle_tree)?, protective_reads: shell.create_dir(protective_reads)?, + basic_witness_input_producer: shell.create_dir(basic_witness_input_producer)?, }) }