From c79e5b7efe5449121dbe3e8f3d158795a6937eea Mon Sep 17 00:00:00 2001 From: JayT106 Date: Thu, 5 Sep 2024 21:52:58 -0400 Subject: [PATCH] feat: missing GKMSSigner feature (#78) Co-authored-by: Calvin Lau <38898718+calvinaco@users.noreply.github.com> --- Cargo.lock | 614 +++++++++++++++++- core/bin/zksync_server/src/node_builder.rs | 27 +- core/lib/config/src/configs/eth_sender.rs | 11 + core/lib/config/src/testonly.rs | 5 +- core/lib/env_config/src/eth_sender.rs | 5 +- core/lib/eth_client/src/clients/http/mod.rs | 2 +- .../eth_client/src/clients/http/signing.rs | 35 +- core/lib/eth_client/src/clients/mod.rs | 2 +- core/lib/eth_signer/Cargo.toml | 5 + core/lib/eth_signer/src/g_kms_signer.rs | 161 +++++ core/lib/eth_signer/src/lib.rs | 1 + core/lib/eth_signer/src/raw_ethereum_tx.rs | 4 + core/lib/protobuf_config/src/eth.rs | 23 + .../src/proto/config/eth_sender.proto | 6 + .../layers/pk_signing_eth_client.rs | 122 +++- etc/env/base/eth_sender.toml | 2 + 16 files changed, 957 insertions(+), 68 deletions(-) create mode 100644 core/lib/eth_signer/src/g_kms_signer.rs diff --git a/Cargo.lock b/Cargo.lock index fecd7dd76..108043446 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -298,6 +298,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "auto_impl" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.36", + "syn 2.0.72", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -331,6 +342,34 @@ dependencies = [ "paste", ] +[[package]] +name = "axum" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" +dependencies = [ + "async-trait", + "axum-core 0.3.4", + "bitflags 1.3.2", + "bytes", + "futures-util", + "http 0.2.9", + "http-body 0.4.6", + "hyper 0.14.29", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "sync_wrapper 0.1.2", + "tower", + "tower-layer", + "tower-service", +] + [[package]] name = "axum" version = "0.7.5" @@ -338,7 +377,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf" dependencies = [ "async-trait", - "axum-core", + "axum-core 0.4.3", "bytes", "futures-util", "http 1.1.0", @@ -366,6 +405,23 @@ dependencies = [ "tracing", ] +[[package]] +name = "axum-core" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http 0.2.9", + "http-body 0.4.6", + "mime", + "rustversion", + "tower-layer", + "tower-service", +] + [[package]] name = "axum-core" version = "0.4.3" @@ -459,6 +515,12 @@ dependencies = [ "serde", ] +[[package]] +name = "bech32" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" + [[package]] name = "beef" version = "0.5.2" @@ -776,6 +838,16 @@ dependencies = [ "syn_derive", ] +[[package]] +name = "bs58" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" +dependencies = [ + "sha2 0.10.8", + "tinyvec", +] + [[package]] name = "build_html" version = "2.4.0" @@ -833,6 +905,9 @@ name = "bytes" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +dependencies = [ + "serde", +] [[package]] name = "bytesize" @@ -1230,6 +1305,58 @@ dependencies = [ "indexmap 1.9.3", ] +[[package]] +name = "coins-bip32" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b6be4a5df2098cd811f3194f64ddb96c267606bffd9689ac7b0160097b01ad3" +dependencies = [ + "bs58", + "coins-core", + "digest 0.10.7", + "hmac", + "k256 0.13.3", + "serde", + "sha2 0.10.8", + "thiserror", +] + +[[package]] +name = "coins-bip39" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3db8fba409ce3dc04f7d804074039eb68b960b0829161f8e06c95fea3f122528" +dependencies = [ + "bitvec", + "coins-bip32", + "hmac", + "once_cell", + "pbkdf2 0.12.2", + "rand 0.8.5", + "sha2 0.10.8", + "thiserror", +] + +[[package]] +name = "coins-core" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5286a0843c21f8367f7be734f89df9b822e0321d8bcce8d6e735aadff7d74979" +dependencies = [ + "base64 0.21.5", + "bech32", + "bs58", + "digest 0.10.7", + "generic-array", + "hex", + "ripemd", + "serde", + "serde_derive", + "sha2 0.10.8", + "sha3 0.10.8", + "thiserror", +] + [[package]] name = "colorchoice" version = "1.0.0" @@ -1273,6 +1400,19 @@ dependencies = [ "windows-sys 0.45.0", ] +[[package]] +name = "const-hex" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94fb8a24a26d37e1ffd45343323dc9fe6654ceea44c12f2fcb3d7ac29e610bc6" +dependencies = [ + "cfg-if 1.0.0", + "cpufeatures", + "hex", + "proptest", + "serde", +] + [[package]] name = "const-oid" version = "0.9.5" @@ -1701,7 +1841,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d" dependencies = [ "serde", - "uuid", + "uuid 1.5.0", ] [[package]] @@ -1746,6 +1886,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "derive_more" +version = "0.99.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.36", + "syn 2.0.72", +] + [[package]] name = "derive_more" version = "1.0.0-beta.6" @@ -2011,6 +2162,28 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "eth-keystore" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fda3bf123be441da5260717e0661c25a2fd9cb2b2c1d20bf2e05580047158ab" +dependencies = [ + "aes", + "ctr", + "digest 0.10.7", + "hex", + "hmac", + "pbkdf2 0.11.0", + "rand 0.8.5", + "scrypt", + "serde", + "serde_json", + "sha2 0.10.8", + "sha3 0.10.8", + "thiserror", + "uuid 0.8.2", +] + [[package]] name = "ethabi" version = "18.0.0" @@ -2036,8 +2209,10 @@ checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60" dependencies = [ "crunchy", "fixed-hash", + "impl-codec", "impl-rlp", "impl-serde", + "scale-info", "tiny-keccak 2.0.2", ] @@ -2049,12 +2224,60 @@ checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" dependencies = [ "ethbloom", "fixed-hash", + "impl-codec", "impl-rlp", "impl-serde", "primitive-types", + "scale-info", "uint", ] +[[package]] +name = "ethers-core" +version = "2.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82d80cc6ad30b14a48ab786523af33b37f28a8623fc06afd55324816ef18fb1f" +dependencies = [ + "arrayvec 0.7.4", + "bytes", + "chrono", + "const-hex", + "elliptic-curve 0.13.8", + "ethabi", + "generic-array", + "k256 0.13.3", + "num_enum 0.7.2", + "open-fastrlp", + "rand 0.8.5", + "rlp", + "serde", + "serde_json", + "strum", + "tempfile", + "thiserror", + "tiny-keccak 2.0.2", + "unicode-xid 0.2.4", +] + +[[package]] +name = "ethers-signers" +version = "2.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "228875491c782ad851773b652dd8ecac62cda8571d3bc32a5853644dd26766c2" +dependencies = [ + "async-trait", + "coins-bip32", + "coins-bip39", + "const-hex", + "elliptic-curve 0.13.8", + "eth-keystore", + "ethers-core", + "rand 0.8.5", + "sha2 0.10.8", + "thiserror", + "tracing", +] + [[package]] name = "event-listener" version = "5.3.1" @@ -2520,8 +2743,8 @@ checksum = "1112c453c2e155b3e683204ffff52bcc6d6495d04b68d9e90cd24161270c5058" dependencies = [ "async-trait", "base64 0.21.5", - "google-cloud-metadata", - "google-cloud-token", + "google-cloud-metadata 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "google-cloud-token 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "home", "jsonwebtoken", "reqwest 0.12.5", @@ -2534,6 +2757,72 @@ dependencies = [ "urlencoding", ] +[[package]] +name = "google-cloud-auth" +version = "0.16.0" +source = "git+https://github.com/yoshidan/google-cloud-rust.git?tag=v20240627#8f387a13309707c493d2e581961ee5b0f20631fc" +dependencies = [ + "async-trait", + "base64 0.21.5", + "google-cloud-metadata 0.5.0 (git+https://github.com/yoshidan/google-cloud-rust.git?tag=v20240627)", + "google-cloud-token 0.1.2 (git+https://github.com/yoshidan/google-cloud-rust.git?tag=v20240627)", + "home", + "jsonwebtoken", + "reqwest 0.12.5", + "serde", + "serde_json", + "thiserror", + "time", + "tokio", + "tracing", + "urlencoding", +] + +[[package]] +name = "google-cloud-gax" +version = "0.18.0" +source = "git+https://github.com/yoshidan/google-cloud-rust.git?tag=v20240627#8f387a13309707c493d2e581961ee5b0f20631fc" +dependencies = [ + "google-cloud-token 0.1.2 (git+https://github.com/yoshidan/google-cloud-rust.git?tag=v20240627)", + "http 0.2.9", + "thiserror", + "tokio", + "tokio-retry", + "tonic 0.11.0", + "tower", + "tracing", +] + +[[package]] +name = "google-cloud-googleapis" +version = "0.14.0" +source = "git+https://github.com/yoshidan/google-cloud-rust.git?tag=v20240627#8f387a13309707c493d2e581961ee5b0f20631fc" +dependencies = [ + "prost 0.12.1", + "prost-types", + "tonic 0.11.0", +] + +[[package]] +name = "google-cloud-kms" +version = "0.3.0" +source = "git+https://github.com/yoshidan/google-cloud-rust.git?tag=v20240627#8f387a13309707c493d2e581961ee5b0f20631fc" +dependencies = [ + "async-trait", + "ethers-core", + "ethers-signers", + "google-cloud-auth 0.16.0 (git+https://github.com/yoshidan/google-cloud-rust.git?tag=v20240627)", + "google-cloud-gax", + "google-cloud-googleapis", + "google-cloud-token 0.1.2 (git+https://github.com/yoshidan/google-cloud-rust.git?tag=v20240627)", + "k256 0.13.3", + "prost-types", + "serde", + "serde_json", + "thiserror", + "tracing", +] + [[package]] name = "google-cloud-metadata" version = "0.5.0" @@ -2545,6 +2834,16 @@ dependencies = [ "tokio", ] +[[package]] +name = "google-cloud-metadata" +version = "0.5.0" +source = "git+https://github.com/yoshidan/google-cloud-rust.git?tag=v20240627#8f387a13309707c493d2e581961ee5b0f20631fc" +dependencies = [ + "reqwest 0.12.5", + "thiserror", + "tokio", +] + [[package]] name = "google-cloud-storage" version = "0.20.0" @@ -2557,9 +2856,9 @@ dependencies = [ "base64 0.21.5", "bytes", "futures-util", - "google-cloud-auth", - "google-cloud-metadata", - "google-cloud-token", + "google-cloud-auth 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", + "google-cloud-metadata 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "google-cloud-token 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "hex", "once_cell", "percent-encoding", @@ -2587,6 +2886,14 @@ dependencies = [ "async-trait", ] +[[package]] +name = "google-cloud-token" +version = "0.1.2" +source = "git+https://github.com/yoshidan/google-cloud-rust.git?tag=v20240627#8f387a13309707c493d2e581961ee5b0f20631fc" +dependencies = [ + "async-trait", +] + [[package]] name = "governor" version = "0.4.2" @@ -2916,13 +3223,25 @@ dependencies = [ "hyper 1.3.1", "hyper-util", "log", - "rustls", + "rustls 0.23.10", "rustls-pki-types", "tokio", - "tokio-rustls", + "tokio-rustls 0.26.0", "tower-service", ] +[[package]] +name = "hyper-timeout" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" +dependencies = [ + "hyper 0.14.29", + "pin-project-lite", + "tokio", + "tokio-io-timeout", +] + [[package]] name = "hyper-timeout" version = "0.5.1" @@ -3233,13 +3552,13 @@ dependencies = [ "http 1.1.0", "jsonrpsee-core", "pin-project", - "rustls", + "rustls 0.23.10", "rustls-pki-types", "rustls-platform-verifier", "soketto", "thiserror", "tokio", - "tokio-rustls", + "tokio-rustls 0.26.0", "tokio-util", "tracing", "url", @@ -3288,7 +3607,7 @@ dependencies = [ "hyper-util", "jsonrpsee-core", "jsonrpsee-types", - "rustls", + "rustls 0.23.10", "rustls-platform-verifier", "serde", "serde_json", @@ -4080,6 +4399,31 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +[[package]] +name = "open-fastrlp" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "786393f80485445794f6043fd3138854dd109cc6c4bd1a6383db304c9ce9b9ce" +dependencies = [ + "arrayvec 0.7.4", + "auto_impl", + "bytes", + "ethereum-types", + "open-fastrlp-derive", +] + +[[package]] +name = "open-fastrlp-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "003b2be5c6c53c1cfeb0a238b8a1c3915cd410feb684457a36c10038f764bb1c" +dependencies = [ + "bytes", + "proc-macro2 1.0.86", + "quote 1.0.36", + "syn 1.0.109", +] + [[package]] name = "openssl" version = "0.10.66" @@ -4180,7 +4524,7 @@ dependencies = [ "reqwest 0.12.5", "thiserror", "tokio", - "tonic", + "tonic 0.12.1", ] [[package]] @@ -4192,7 +4536,7 @@ dependencies = [ "opentelemetry", "opentelemetry_sdk", "prost 0.13.1", - "tonic", + "tonic 0.12.1", ] [[package]] @@ -4340,6 +4684,25 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +[[package]] +name = "pbkdf2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "pbkdf2" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" +dependencies = [ + "digest 0.10.7", + "hmac", +] + [[package]] name = "peeking_take_while" version = "0.1.2" @@ -4597,6 +4960,7 @@ dependencies = [ "impl-codec", "impl-rlp", "impl-serde", + "scale-info", "uint", ] @@ -4699,6 +5063,22 @@ dependencies = [ "syn 2.0.72", ] +[[package]] +name = "proptest" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c2511913b88df1637da85cc8d96ec8e43a3f8bb8ccb71ee1ac240d6f3df58d" +dependencies = [ + "bitflags 2.6.0", + "lazy_static", + "num-traits", + "rand 0.8.5", + "rand_chacha", + "rand_xorshift", + "regex-syntax 0.8.2", + "unarray", +] + [[package]] name = "prost" version = "0.12.1" @@ -4963,6 +5343,15 @@ dependencies = [ "getrandom", ] +[[package]] +name = "rand_xorshift" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" +dependencies = [ + "rand_core 0.6.4", +] + [[package]] name = "rand_xoshiro" version = "0.6.0" @@ -5228,6 +5617,15 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "ripemd" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" +dependencies = [ + "digest 0.10.7", +] + [[package]] name = "rkyv" version = "0.7.43" @@ -5243,7 +5641,7 @@ dependencies = [ "rkyv_derive", "seahash", "tinyvec", - "uuid", + "uuid 1.5.0", ] [[package]] @@ -5264,9 +5662,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" dependencies = [ "bytes", + "rlp-derive", "rustc-hex", ] +[[package]] +name = "rlp-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e33d7b2abe0c340d8797fe2907d3f20d3b5ea5908683618bfe80df7f621f672a" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.36", + "syn 1.0.109", +] + [[package]] name = "rocksdb" version = "0.21.0" @@ -5359,6 +5769,20 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rustls" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" +dependencies = [ + "log", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + [[package]] name = "rustls" version = "0.23.10" @@ -5415,7 +5839,7 @@ dependencies = [ "jni", "log", "once_cell", - "rustls", + "rustls 0.23.10", "rustls-native-certs", "rustls-platform-verifier-android", "rustls-webpki", @@ -5455,6 +5879,15 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +[[package]] +name = "salsa20" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" +dependencies = [ + "cipher", +] + [[package]] name = "same-file" version = "1.0.6" @@ -5464,6 +5897,30 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scale-info" +version = "2.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eca070c12893629e2cc820a9761bedf6ce1dcddc9852984d1dc734b8bd9bd024" +dependencies = [ + "cfg-if 1.0.0", + "derive_more 0.99.18", + "parity-scale-codec", + "scale-info-derive", +] + +[[package]] +name = "scale-info-derive" +version = "2.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d35494501194174bda522a32605929eefc9ecf7e0a326c26db1fdd85881eb62" +dependencies = [ + "proc-macro-crate 3.1.0", + "proc-macro2 1.0.86", + "quote 1.0.36", + "syn 1.0.109", +] + [[package]] name = "schannel" version = "0.1.22" @@ -5479,6 +5936,18 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "scrypt" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f9e24d2b632954ded8ab2ef9fea0a0c769ea56ea98bddbafbad22caeeadf45d" +dependencies = [ + "hmac", + "pbkdf2 0.11.0", + "salsa20", + "sha2 0.10.8", +] + [[package]] name = "seahash" version = "4.1.0" @@ -5684,7 +6153,7 @@ dependencies = [ "thiserror", "time", "url", - "uuid", + "uuid 1.5.0", ] [[package]] @@ -6709,7 +7178,7 @@ dependencies = [ "pin-project-lite", "thiserror", "tokio", - "tokio-rustls", + "tokio-rustls 0.26.0", ] [[package]] @@ -6730,6 +7199,16 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "tokio-io-timeout" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" +dependencies = [ + "pin-project-lite", + "tokio", +] + [[package]] name = "tokio-macros" version = "2.4.0" @@ -6751,13 +7230,35 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-retry" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f57eb36ecbe0fc510036adff84824dd3c24bb781e21bfa67b69d556aa85214f" +dependencies = [ + "pin-project", + "rand 0.8.5", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" +dependencies = [ + "rustls 0.22.4", + "rustls-pki-types", + "tokio", +] + [[package]] name = "tokio-rustls" version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "rustls", + "rustls 0.23.10", "rustls-pki-types", "tokio", ] @@ -6828,6 +7329,38 @@ dependencies = [ "winnow", ] +[[package]] +name = "tonic" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76c4eb7a4e9ef9d4763600161f12f5070b92a578e1b634db88a6887844c91a13" +dependencies = [ + "async-stream", + "async-trait", + "axum 0.6.20", + "base64 0.21.5", + "bytes", + "flate2", + "h2 0.3.26", + "http 0.2.9", + "http-body 0.4.6", + "hyper 0.14.29", + "hyper-timeout 0.4.1", + "percent-encoding", + "pin-project", + "prost 0.12.1", + "rustls-pemfile", + "rustls-pki-types", + "tokio", + "tokio-rustls 0.25.0", + "tokio-stream", + "tower", + "tower-layer", + "tower-service", + "tracing", + "webpki-roots", +] + [[package]] name = "tonic" version = "0.12.1" @@ -6836,7 +7369,7 @@ checksum = "38659f4a91aba8598d27821589f5db7dddd94601e7a01b1e485a50e5484c7401" dependencies = [ "async-stream", "async-trait", - "axum", + "axum 0.7.5", "base64 0.22.1", "bytes", "h2 0.4.5", @@ -6844,7 +7377,7 @@ dependencies = [ "http-body 1.0.0", "http-body-util", "hyper 1.3.1", - "hyper-timeout", + "hyper-timeout 0.5.1", "hyper-util", "percent-encoding", "pin-project", @@ -7072,6 +7605,12 @@ dependencies = [ "libc", ] +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + [[package]] name = "unicase" version = "2.7.0" @@ -7201,6 +7740,16 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +[[package]] +name = "uuid" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" +dependencies = [ + "getrandom", + "serde", +] + [[package]] name = "uuid" version = "1.5.0" @@ -8301,7 +8850,7 @@ dependencies = [ "thiserror", "tls-listener", "tokio", - "tokio-rustls", + "tokio-rustls 0.26.0", "tracing", "vise", "zksync_concurrency", @@ -8398,7 +8947,7 @@ name = "zksync_contract_verification_server" version = "0.1.0" dependencies = [ "anyhow", - "axum", + "axum 0.7.5", "serde", "serde_json", "tokio", @@ -8671,9 +9220,14 @@ name = "zksync_eth_signer" version = "0.1.0" dependencies = [ "async-trait", + "ethers-signers", + "google-cloud-gax", + "google-cloud-kms", + "hex", "rlp", "thiserror", "tokio", + "tracing", "zksync_types", ] @@ -8776,7 +9330,7 @@ name = "zksync_external_proof_integration_api" version = "0.1.0" dependencies = [ "anyhow", - "axum", + "axum 0.7.5", "bincode", "tokio", "tracing", @@ -8910,7 +9464,7 @@ dependencies = [ "anyhow", "assert_matches", "async-trait", - "axum", + "axum 0.7.5", "futures 0.3.28", "itertools 0.10.5", "once_cell", @@ -8990,7 +9544,7 @@ dependencies = [ "anyhow", "assert_matches", "async-trait", - "axum", + "axum 0.7.5", "chrono", "futures 0.3.28", "governor", @@ -9287,7 +9841,7 @@ dependencies = [ "async-trait", "bincode", "flate2", - "google-cloud-auth", + "google-cloud-auth 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "google-cloud-storage", "http 1.1.0", "prost 0.12.1", @@ -9308,7 +9862,7 @@ name = "zksync_proof_data_handler" version = "0.1.0" dependencies = [ "anyhow", - "axum", + "axum 0.7.5", "chrono", "hyper 1.3.1", "serde_json", @@ -9700,7 +10254,7 @@ dependencies = [ "bincode", "blake2 0.10.6", "chrono", - "derive_more", + "derive_more 1.0.0-beta.6", "hex", "itertools 0.10.5", "num", @@ -9848,7 +10402,7 @@ dependencies = [ "pin-project-lite", "rand 0.8.5", "rlp", - "rustls", + "rustls 0.23.10", "serde", "serde_json", "test-casing", diff --git a/core/bin/zksync_server/src/node_builder.rs b/core/bin/zksync_server/src/node_builder.rs index 6b0315200..70afca4d8 100644 --- a/core/bin/zksync_server/src/node_builder.rs +++ b/core/bin/zksync_server/src/node_builder.rs @@ -3,7 +3,11 @@ use anyhow::Context; use zksync_config::{ - configs::{eth_sender::PubdataSendingMode, wallets::Wallets, GeneralConfig, Secrets}, + configs::{ + eth_sender::{PubdataSendingMode, SigningMode}, + wallets::Wallets, + GeneralConfig, Secrets, + }, ContractsConfig, GenesisConfig, }; use zksync_core_leftovers::Component; @@ -43,7 +47,7 @@ use zksync_node_framework::{ main_node_strategy::MainNodeInitStrategyLayer, NodeStorageInitializerLayer, }, object_store::ObjectStoreLayer, - pk_signing_eth_client::PKSigningEthClientLayer, + pk_signing_eth_client::{PKSigningEthClientLayer, SigningEthClientType}, pools_layer::PoolsLayerBuilder, postgres_metrics::PostgresMetricsLayer, prometheus_exporter::PrometheusExporterLayer, @@ -71,7 +75,6 @@ use zksync_node_framework::{ }; use zksync_types::{settlement::SettlementMode, SHARED_BRIDGE_ETHER_TOKEN_ADDRESS}; use zksync_vlog::prometheus::PrometheusExporterConfig; - /// Macro that looks into a path to fetch an optional config, /// and clones it into a variable. macro_rules! try_load_config { @@ -143,11 +146,29 @@ impl MainNodeBuilder { fn add_pk_signing_client_layer(mut self) -> anyhow::Result { let eth_config = try_load_config!(self.configs.eth); let wallets = try_load_config!(self.wallets.eth_sender); + + let eth_sender = self + .configs + .eth + .clone() + .context("eth_config")? + .sender + .context("sender")?; + + let signing_mode = eth_sender.signing_mode.clone(); + tracing::info!("Using signing mode: {:?}", signing_mode); + + let client_type = match signing_mode { + SigningMode::GcloudKms => SigningEthClientType::GKMSSigningEthClient, + SigningMode::PrivateKey => SigningEthClientType::PKSigningEthClient, + }; + self.node.add_layer(PKSigningEthClientLayer::new( eth_config, self.contracts_config.clone(), self.genesis_config.settlement_layer_id(), wallets, + client_type, )); Ok(self) } diff --git a/core/lib/config/src/configs/eth_sender.rs b/core/lib/config/src/configs/eth_sender.rs index 7e6ef2244..714a77294 100644 --- a/core/lib/config/src/configs/eth_sender.rs +++ b/core/lib/config/src/configs/eth_sender.rs @@ -42,6 +42,7 @@ impl EthConfig { pubdata_sending_mode: PubdataSendingMode::Calldata, tx_aggregation_paused: false, tx_aggregation_only_prove_and_execute: false, + signing_mode: SigningMode::PrivateKey, }), gas_adjuster: Some(GasAdjusterConfig { default_priority_fee_per_gas: 1000000000, @@ -88,6 +89,13 @@ pub enum PubdataSendingMode { RelayedL2Calldata, } +#[derive(Debug, Deserialize, Clone, Copy, PartialEq, Default)] +pub enum SigningMode { + #[default] + PrivateKey, + GcloudKms, +} + #[derive(Debug, Deserialize, Clone, PartialEq)] pub struct SenderConfig { pub aggregated_proof_sizes: Vec, @@ -127,6 +135,9 @@ pub struct SenderConfig { /// special mode specifically for gateway migration to decrease number of non-executed batches #[serde(default = "SenderConfig::default_tx_aggregation_only_prove_and_execute")] pub tx_aggregation_only_prove_and_execute: bool, + + /// Type of signing client for Ethereum transactions. + pub signing_mode: SigningMode, } impl SenderConfig { diff --git a/core/lib/config/src/testonly.rs b/core/lib/config/src/testonly.rs index 2ec91f5be..3318e9bb6 100644 --- a/core/lib/config/src/testonly.rs +++ b/core/lib/config/src/testonly.rs @@ -13,7 +13,9 @@ use zksync_consensus_utils::EncodeDist; use zksync_crypto_primitives::K256PrivateKey; use crate::configs::{ - self, eth_sender::PubdataSendingMode, external_price_api_client::ForcedPriceClientConfig, + self, + eth_sender::{PubdataSendingMode, SigningMode}, + external_price_api_client::ForcedPriceClientConfig, }; trait Sample { @@ -412,6 +414,7 @@ impl Distribution for EncodeDist { pubdata_sending_mode: PubdataSendingMode::Calldata, tx_aggregation_paused: false, tx_aggregation_only_prove_and_execute: false, + signing_mode: SigningMode::PrivateKey, } } } diff --git a/core/lib/env_config/src/eth_sender.rs b/core/lib/env_config/src/eth_sender.rs index 64e0a89d5..07d44648e 100644 --- a/core/lib/env_config/src/eth_sender.rs +++ b/core/lib/env_config/src/eth_sender.rs @@ -41,7 +41,7 @@ impl FromEnv for GasAdjusterConfig { #[cfg(test)] mod tests { - use zksync_config::configs::eth_sender::{ProofSendingMode, PubdataSendingMode}; + use zksync_config::configs::eth_sender::{ProofSendingMode, PubdataSendingMode, SigningMode}; use super::*; use crate::test_utils::{hash, EnvMutex}; @@ -58,7 +58,6 @@ mod tests { aggregated_block_execute_deadline: 4_000, max_aggregated_tx_gas: 4_000_000, max_eth_tx_data_size: 120_000, - timestamp_criteria_max_allowed_lag: 30, max_aggregated_blocks_to_commit: 3, max_aggregated_blocks_to_execute: 4, @@ -72,6 +71,7 @@ mod tests { pubdata_sending_mode: PubdataSendingMode::Calldata, tx_aggregation_only_prove_and_execute: false, tx_aggregation_paused: false, + signing_mode: SigningMode::PrivateKey, }), gas_adjuster: Some(GasAdjusterConfig { default_priority_fee_per_gas: 20000000000, @@ -136,6 +136,7 @@ mod tests { ETH_SENDER_SENDER_PUBDATA_SENDING_MODE="Calldata" ETH_WATCH_CONFIRMATIONS_FOR_ETH_EVENT="0" ETH_WATCH_ETH_NODE_POLL_INTERVAL="300" + ETH_SENDER_SENDER_SIGNING_MODE="PrivateKey" ETH_CLIENT_WEB3_URL="http://127.0.0.1:8545" "#; diff --git a/core/lib/eth_client/src/clients/http/mod.rs b/core/lib/eth_client/src/clients/http/mod.rs index 111507c65..830b2a9ec 100644 --- a/core/lib/eth_client/src/clients/http/mod.rs +++ b/core/lib/eth_client/src/clients/http/mod.rs @@ -4,7 +4,7 @@ use vise::{ Buckets, Counter, EncodeLabelSet, EncodeLabelValue, Family, Histogram, LabeledFamily, Metrics, }; -pub use self::signing::{PKSigningClient, SigningClient}; +pub use self::signing::{GKMSSigningClient, PKSigningClient, SigningClient}; mod decl; mod query; diff --git a/core/lib/eth_client/src/clients/http/signing.rs b/core/lib/eth_client/src/clients/http/signing.rs index e602f98a3..e827a411a 100644 --- a/core/lib/eth_client/src/clients/http/signing.rs +++ b/core/lib/eth_client/src/clients/http/signing.rs @@ -2,7 +2,9 @@ use std::{fmt, sync::Arc}; use async_trait::async_trait; use zksync_contracts::hyperchain_contract; -use zksync_eth_signer::{EthereumSigner, PrivateKeySigner, TransactionParameters}; +use zksync_eth_signer::{ + g_kms_signer::GKMSSigner, EthereumSigner, PrivateKeySigner, TransactionParameters, +}; use zksync_types::{ ethabi, web3, Address, K256PrivateKey, SLChainId, EIP_4844_TX_TYPE, H160, U256, }; @@ -40,6 +42,37 @@ impl PKSigningClient { } } +pub type GKMSSigningClient = SigningClient; + +impl GKMSSigningClient { + pub async fn new_raw( + diamond_proxy_addr: Address, + default_priority_fee_per_gas: u64, + chain_id: SLChainId, + query_client: Box>, + key_name: String, + ) -> Self { + let signer = match GKMSSigner::new(key_name, chain_id.0).await { + Ok(s) => s, + Err(e) => panic!("Failed to create GKMSSigner: {:?}", e), + }; + + SigningClient::new( + query_client, + hyperchain_contract(), + signer.get_address().await.unwrap(), + signer, + diamond_proxy_addr, + default_priority_fee_per_gas.into(), + chain_id, + ) + } + + pub fn get_address(&self) -> Address { + self.inner.sender_account + } +} + /// Gas limit value to be used in transaction if for some reason /// gas limit was not set for it. /// diff --git a/core/lib/eth_client/src/clients/mod.rs b/core/lib/eth_client/src/clients/mod.rs index b08f92115..42398fd78 100644 --- a/core/lib/eth_client/src/clients/mod.rs +++ b/core/lib/eth_client/src/clients/mod.rs @@ -6,6 +6,6 @@ mod mock; pub use zksync_web3_decl::client::{Client, DynClient, L1}; pub use self::{ - http::{PKSigningClient, SigningClient}, + http::{GKMSSigningClient, PKSigningClient, SigningClient}, mock::{MockSettlementLayer, MockSettlementLayerBuilder}, }; diff --git a/core/lib/eth_signer/Cargo.toml b/core/lib/eth_signer/Cargo.toml index f760134e0..690a231fa 100644 --- a/core/lib/eth_signer/Cargo.toml +++ b/core/lib/eth_signer/Cargo.toml @@ -15,6 +15,11 @@ zksync_types.workspace = true rlp.workspace = true thiserror.workspace = true async-trait.workspace = true +google-cloud-kms = { git="https://github.com/yoshidan/google-cloud-rust.git", tag="v20240627", features=["eth"]} +google-cloud-gax = { git="https://github.com/yoshidan/google-cloud-rust.git", tag="v20240627"} +hex = "0.4.3" +tracing = "0.1" +ethers-signers = "2.0" [dev-dependencies] tokio = { workspace = true, features = ["full"] } diff --git a/core/lib/eth_signer/src/g_kms_signer.rs b/core/lib/eth_signer/src/g_kms_signer.rs new file mode 100644 index 000000000..bff35b8db --- /dev/null +++ b/core/lib/eth_signer/src/g_kms_signer.rs @@ -0,0 +1,161 @@ +use std::result::Result; + +use ethers_signers::Signer as EthSigner; +use google_cloud_gax::retry::RetrySetting; +use google_cloud_kms::{ + client::{Client, ClientConfig}, + signer::ethereum::Signer, +}; +use hex; +use tracing::{self}; +use zksync_types::{ + web3::{keccak256, Signature}, + Address, EIP712TypedStructure, Eip712Domain, PackedEthSignature, H256, U256, +}; + +use crate::{ + raw_ethereum_tx::{Transaction, TransactionParameters}, + EthereumSigner, SignerError, +}; + +pub const GOOGLE_KMS_OP_KEY_NAME: &str = "GOOGLE_KMS_OP_KEY_NAME"; +pub const GOOGLE_KMS_OP_BLOB_KEY_NAME: &str = "GOOGLE_KMS_OP_BLOB_KEY_NAME"; + +#[derive(Clone)] +pub struct GKMSSigner { + signer: Signer, +} + +impl GKMSSigner { + pub async fn new(key_name: String, _chain_id: u64) -> Result { + let config = ClientConfig::default() + .with_auth() + .await + .map_err(|e| SignerError::SigningFailed(e.to_string()))?; + + let client = Client::new(config) + .await + .map_err(|e| SignerError::SigningFailed(e.to_string()))?; + + let signer = Signer::new(client, &key_name, _chain_id, Some(RetrySetting::default())) + .await + .map_err(|e| SignerError::SigningFailed(e.to_string()))?; + + tracing::info!("KMS signer address: {:?}", hex::encode(signer.address())); + + Ok(GKMSSigner { signer }) + } + + fn u256_to_h256(u: U256) -> H256 { + let mut bytes = [0u8; 32]; + u.to_big_endian(&mut bytes); + H256::from(bytes) + } +} + +#[async_trait::async_trait] +impl EthereumSigner for GKMSSigner { + /// Get Ethereum address that matches the private key. + async fn get_address(&self) -> Result { + Ok(self.signer.address()) + } + + /// Signs typed struct using Ethereum private key by EIP-712 signature standard. + /// Result of this function is the equivalent of RPC calling `eth_signTypedData`. + async fn sign_typed_data( + &self, + domain: &Eip712Domain, + typed_struct: &S, + ) -> Result { + let digest = + H256::from(PackedEthSignature::typed_data_to_signed_bytes(domain, typed_struct).0); + + let signature = self + .signer + .sign_digest(digest.as_bytes()) + .await + .map_err(|e| SignerError::SigningFailed(e.to_string()))?; + + // Convert the signature components to the appropriate format. + let r_h256 = GKMSSigner::u256_to_h256(signature.r); + let s_h256 = GKMSSigner::u256_to_h256(signature.s); + + // Ensure the `v` component is in the correct byte format. + let v_byte = match signature.v.try_into() { + Ok(v) => v, + Err(_) => { + return Err(SignerError::SigningFailed( + "V value conversion failed".to_string(), + )) + } + }; + + // Construct the Ethereum signature from the R, S, and V components. + let eth_sig = PackedEthSignature::from_rsv(&r_h256, &s_h256, v_byte); + + Ok(eth_sig) + } + + /// Signs and returns the RLP-encoded transaction. + async fn sign_transaction( + &self, + raw_tx: TransactionParameters, + ) -> Result, SignerError> { + // According to the code in web3 + // We should use `max_fee_per_gas` as `gas_price` if we use EIP1559 + let gas_price = raw_tx.max_fee_per_gas; + let max_priority_fee_per_gas = raw_tx.max_priority_fee_per_gas; + + let tx = Transaction { + to: raw_tx.to, + nonce: raw_tx.nonce, + gas: raw_tx.gas, + gas_price, + value: raw_tx.value, + data: raw_tx.data, + transaction_type: raw_tx.transaction_type, + access_list: raw_tx.access_list.unwrap_or_default(), + max_priority_fee_per_gas, + max_fee_per_blob_gas: raw_tx.max_fee_per_blob_gas, + blob_versioned_hashes: raw_tx.blob_versioned_hashes, + }; + + let encoded = tx.encode_pub(raw_tx.chain_id, None); + let digest = H256(keccak256(encoded.as_ref())); + + let signature = self + .signer + .sign_digest(digest.as_bytes()) + .await + .map_err(|e| SignerError::SigningFailed(e.to_string()))?; + + let adjusted_v = if let Some(transaction_type) = tx.transaction_type.map(|t| t.as_u64()) { + match transaction_type { + 0 => signature.v + raw_tx.chain_id * 2 + 35, // EIP-155 + _ => signature.v, // EIP-2930 and others + } + } else { + signature.v + raw_tx.chain_id * 2 + 35 // EIP-155 + }; + + let r_h256 = GKMSSigner::u256_to_h256(signature.r); + let s_h256 = GKMSSigner::u256_to_h256(signature.s); + + tracing::debug!( + "KMS sign_transaction signature: v: {}, r: {}, s: {}", + adjusted_v, + hex::encode(r_h256), + hex::encode(s_h256), + ); + + let web3_sig = Signature { + v: adjusted_v, + r: r_h256, + s: s_h256, + }; + + let signed = tx.encode_pub(raw_tx.chain_id, Some(&web3_sig)); + + return Ok(signed); + } +} diff --git a/core/lib/eth_signer/src/lib.rs b/core/lib/eth_signer/src/lib.rs index 3a92d47b0..9053ed794 100644 --- a/core/lib/eth_signer/src/lib.rs +++ b/core/lib/eth_signer/src/lib.rs @@ -3,6 +3,7 @@ use zksync_types::{Address, EIP712TypedStructure, Eip712Domain, PackedEthSignatu pub use crate::{pk_signer::PrivateKeySigner, raw_ethereum_tx::TransactionParameters}; +pub mod g_kms_signer; mod pk_signer; mod raw_ethereum_tx; diff --git a/core/lib/eth_signer/src/raw_ethereum_tx.rs b/core/lib/eth_signer/src/raw_ethereum_tx.rs index 9479b5bd9..dbaffd597 100644 --- a/core/lib/eth_signer/src/raw_ethereum_tx.rs +++ b/core/lib/eth_signer/src/raw_ethereum_tx.rs @@ -268,4 +268,8 @@ impl Transaction { transaction_hash, } } + + pub fn encode_pub(&self, chain_id: u64, signature: Option<&Signature>) -> Vec { + self.encode(chain_id, signature) + } } diff --git a/core/lib/protobuf_config/src/eth.rs b/core/lib/protobuf_config/src/eth.rs index 273b7f4e3..7eede7f7f 100644 --- a/core/lib/protobuf_config/src/eth.rs +++ b/core/lib/protobuf_config/src/eth.rs @@ -46,6 +46,24 @@ impl proto::PubdataSendingMode { } } +impl proto::SigningMode { + fn new(x: &configs::eth_sender::SigningMode) -> Self { + use configs::eth_sender::SigningMode as From; + match x { + From::PrivateKey => Self::PrivateKey, + From::GcloudKms => Self::GcloudKms, + } + } + + fn parse(&self) -> configs::eth_sender::SigningMode { + use configs::eth_sender::SigningMode as To; + match self { + Self::PrivateKey => To::PrivateKey, + Self::GcloudKms => To::GcloudKms, + } + } +} + impl ProtoRepr for proto::Eth { type Type = configs::eth_sender::EthConfig; @@ -115,6 +133,10 @@ impl ProtoRepr for proto::Sender { .parse(), tx_aggregation_only_prove_and_execute: self.tx_aggregation_paused.unwrap_or(false), tx_aggregation_paused: self.tx_aggregation_only_prove_and_execute.unwrap_or(false), + signing_mode: required(&self.signing_mode) + .and_then(|x| Ok(proto::SigningMode::try_from(*x)?)) + .context("signing_mode")? + .parse(), }) } @@ -147,6 +169,7 @@ impl ProtoRepr for proto::Sender { ), tx_aggregation_only_prove_and_execute: Some(this.tx_aggregation_only_prove_and_execute), tx_aggregation_paused: Some(this.tx_aggregation_paused), + signing_mode: Some(proto::SigningMode::new(&this.signing_mode).into()), } } } diff --git a/core/lib/protobuf_config/src/proto/config/eth_sender.proto b/core/lib/protobuf_config/src/proto/config/eth_sender.proto index b102a08be..aa3d1da8a 100644 --- a/core/lib/protobuf_config/src/proto/config/eth_sender.proto +++ b/core/lib/protobuf_config/src/proto/config/eth_sender.proto @@ -27,6 +27,11 @@ enum PubdataSendingMode { RELAYED_L2_CALLDATA = 3; } +enum SigningMode { + PRIVATE_KEY = 0; + GCLOUD_KMS = 1; +} + message Sender { repeated uint64 aggregated_proof_sizes = 1; // ? optional uint64 wait_confirmations = 2; // optional @@ -48,6 +53,7 @@ message Sender { reserved 19; reserved "proof_loading_mode"; optional bool tx_aggregation_paused = 20; // required optional bool tx_aggregation_only_prove_and_execute = 21; // required + optional SigningMode signing_mode = 99; // required } message GasAdjuster { diff --git a/core/node/node_framework/src/implementations/layers/pk_signing_eth_client.rs b/core/node/node_framework/src/implementations/layers/pk_signing_eth_client.rs index fdef23a40..4f072cb97 100644 --- a/core/node/node_framework/src/implementations/layers/pk_signing_eth_client.rs +++ b/core/node/node_framework/src/implementations/layers/pk_signing_eth_client.rs @@ -3,7 +3,7 @@ use zksync_config::{ configs::{wallets, ContractsConfig}, EthConfig, }; -use zksync_eth_client::clients::PKSigningClient; +use zksync_eth_client::clients::{GKMSSigningClient, PKSigningClient}; use zksync_types::SLChainId; use crate::{ @@ -15,12 +15,20 @@ use crate::{ }; /// Wiring layer for [`PKSigningClient`]. +#[derive(Debug)] +#[non_exhaustive] +pub enum SigningEthClientType { + PKSigningEthClient, + GKMSSigningEthClient, +} + #[derive(Debug)] pub struct PKSigningEthClientLayer { eth_sender_config: EthConfig, contracts_config: ContractsConfig, sl_chain_id: SLChainId, wallets: wallets::EthSender, + client_type: SigningEthClientType, } #[derive(Debug, FromContext)] @@ -43,12 +51,14 @@ impl PKSigningEthClientLayer { contracts_config: ContractsConfig, sl_chain_id: SLChainId, wallets: wallets::EthSender, + client_type: SigningEthClientType, ) -> Self { Self { eth_sender_config, contracts_config, sl_chain_id, wallets, + client_type, } } } @@ -63,34 +73,88 @@ impl WiringLayer for PKSigningEthClientLayer { } async fn wire(self, input: Self::Input) -> Result { - let private_key = self.wallets.operator.private_key(); - let gas_adjuster_config = self - .eth_sender_config - .gas_adjuster - .as_ref() - .context("gas_adjuster config is missing")?; - let EthInterfaceResource(query_client) = input.eth_client; - - let signing_client = PKSigningClient::new_raw( - private_key.clone(), - self.contracts_config.diamond_proxy_addr, - gas_adjuster_config.default_priority_fee_per_gas, - self.sl_chain_id, - query_client.clone(), - ); - let signing_client = BoundEthInterfaceResource(Box::new(signing_client)); - - let signing_client_for_blobs = self.wallets.blob_operator.map(|blob_operator| { - let private_key = blob_operator.private_key(); - let signing_client_for_blobs = PKSigningClient::new_raw( - private_key.clone(), - self.contracts_config.diamond_proxy_addr, - gas_adjuster_config.default_priority_fee_per_gas, - self.sl_chain_id, - query_client, - ); - BoundEthInterfaceForBlobsResource(Box::new(signing_client_for_blobs)) - }); + let signing_client; + let mut signing_client_for_blobs = None; + + match self.client_type { + SigningEthClientType::PKSigningEthClient => { + let private_key = self.wallets.operator.private_key(); + let gas_adjuster_config = self + .eth_sender_config + .gas_adjuster + .as_ref() + .context("gas_adjuster config is missing")?; + let EthInterfaceResource(query_client) = input.eth_client; + + let sc = PKSigningClient::new_raw( + private_key.clone(), + self.contracts_config.diamond_proxy_addr, + gas_adjuster_config.default_priority_fee_per_gas, + self.sl_chain_id, + query_client.clone(), + ); + signing_client = BoundEthInterfaceResource(Box::new(sc)); + + signing_client_for_blobs = self.wallets.blob_operator.map(|blob_operator| { + let private_key = blob_operator.private_key(); + let signing_client_for_blobs = PKSigningClient::new_raw( + private_key.clone(), + self.contracts_config.diamond_proxy_addr, + gas_adjuster_config.default_priority_fee_per_gas, + self.sl_chain_id, + query_client, + ); + BoundEthInterfaceForBlobsResource(Box::new(signing_client_for_blobs)) + }); + } + SigningEthClientType::GKMSSigningEthClient => { + let gas_adjuster_config = self + .eth_sender_config + .gas_adjuster + .as_ref() + .context("gas_adjuster config is missing")?; + + let gkms_op_key_name = std::env::var("GOOGLE_KMS_OP_KEY_NAME").ok(); + tracing::info!( + "KMS op key name: {:?}", + std::env::var("GOOGLE_KMS_OP_KEY_NAME") + ); + + let EthInterfaceResource(query_client) = input.eth_client; + + let sc = GKMSSigningClient::new_raw( + self.contracts_config.diamond_proxy_addr, + gas_adjuster_config.default_priority_fee_per_gas, + self.sl_chain_id, + query_client.clone(), + gkms_op_key_name + .expect("gkms_op_key_name is required but was None") + .to_string(), + ) + .await; + + signing_client = BoundEthInterfaceResource(Box::new(sc)); + + let gkms_op_blob_key_name = std::env::var("GOOGLE_KMS_OP_BLOB_KEY_NAME").ok(); + tracing::info!( + "KMS op blob key name: {:?}", + std::env::var("GOOGLE_KMS_OP_BLOB_KEY_NAME") + ); + + if let Some(key_name) = gkms_op_blob_key_name { + let blobs_resources = GKMSSigningClient::new_raw( + self.contracts_config.diamond_proxy_addr, + gas_adjuster_config.default_priority_fee_per_gas, + self.sl_chain_id, + query_client, + key_name.to_string(), + ) + .await; + signing_client_for_blobs = + Some(BoundEthInterfaceForBlobsResource(Box::new(blobs_resources))); + }; + } + }; Ok(Output { signing_client, diff --git a/etc/env/base/eth_sender.toml b/etc/env/base/eth_sender.toml index 31fe626c8..0cead97cf 100644 --- a/etc/env/base/eth_sender.toml +++ b/etc/env/base/eth_sender.toml @@ -48,6 +48,8 @@ max_acceptable_priority_fee_in_gwei = 100000000000 pubdata_sending_mode = "Blobs" +signing_mode = "PrivateKey" + [eth_sender.gas_adjuster] # Priority fee to be used by GasAdjuster (in wei). default_priority_fee_per_gas = 1_000_000_000