diff --git a/Cargo.lock b/Cargo.lock index bc21f489583af..052e7320ee283 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -136,9 +136,9 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.18" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" +checksum = "45862d1c77f2228b9e10bc609d5bc203d86ebc9b87ad8d5d5167a6c9abf739d9" [[package]] name = "ambient-authority" @@ -188,7 +188,7 @@ dependencies = [ "serde_json", "socket2 0.5.7", "tap", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-util 0.7.12", "tower 0.4.13", @@ -989,7 +989,7 @@ dependencies = [ "nom", "num-traits", "rusticata-macros", - "thiserror", + "thiserror 1.0.69", "time", ] @@ -1154,7 +1154,7 @@ dependencies = [ "serde_urlencoded", "static_assertions_next", "tempfile", - "thiserror", + "thiserror 1.0.69", "tracing", "tracing-futures", ] @@ -1191,7 +1191,7 @@ dependencies = [ "quote 1.0.37", "strum 0.25.0", "syn 2.0.87", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -2169,7 +2169,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85b6598a2f5d564fb7855dc6b06fd1c38cff5a72bd8b863a4d021938497b440a" dependencies = [ "serde", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -2208,7 +2208,7 @@ dependencies = [ "byteorder", "ff 0.13.0", "serde", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -2252,7 +2252,7 @@ checksum = "230c5f1ca6a325a32553f8640d31ac9b49f2411e901e427570154868b46da4f7" [[package]] name = "bin-version" -version = "1.37.1" +version = "1.37.3" dependencies = [ "const-str", "git-version", @@ -2633,12 +2633,12 @@ dependencies = [ [[package]] name = "bstr" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c" +checksum = "1a68f1f47cdf0ec8ee4b941b2eee2a80cb796db73118c0dd09ac63fbe405be22" dependencies = [ "memchr", - "regex-automata 0.4.8", + "regex-automata 0.4.9", "serde", ] @@ -2736,7 +2736,7 @@ dependencies = [ "instant", "lazy_static", "once_cell", - "thiserror", + "thiserror 1.0.69", "tokio", ] @@ -2865,7 +2865,7 @@ dependencies = [ "semver", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -2879,7 +2879,7 @@ dependencies = [ "semver", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -2905,9 +2905,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.37" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40545c26d092346d8a8dab71ee48e7685a7a9cba76e634790c215b41a4a7b4cf" +checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47" dependencies = [ "jobserver", "libc", @@ -3043,9 +3043,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.20" +version = "4.5.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" +checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f" dependencies = [ "clap_builder", "clap_derive", @@ -3053,9 +3053,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.20" +version = "4.5.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" +checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec" dependencies = [ "anstream", "anstyle", @@ -3078,9 +3078,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" +checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7" [[package]] name = "clipboard-win" @@ -3111,7 +3111,7 @@ checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" dependencies = [ "serde", "termcolor", - "unicode-width", + "unicode-width 0.1.14", ] [[package]] @@ -3127,7 +3127,7 @@ dependencies = [ "k256 0.13.4", "serde", "sha2 0.10.8", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -3143,7 +3143,7 @@ dependencies = [ "pbkdf2 0.12.2", "rand 0.8.5", "sha2 0.10.8", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -3163,7 +3163,7 @@ dependencies = [ "serde_derive", "sha2 0.10.8", "sha3 0.10.8", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -3234,7 +3234,7 @@ dependencies = [ "crossterm 0.26.1", "strum 0.24.1", "strum_macros 0.24.3", - "unicode-width", + "unicode-width 0.1.14", ] [[package]] @@ -3303,7 +3303,7 @@ dependencies = [ "tap", "telemetry-subscribers", "tempfile", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-rustls 0.26.0", "tokio-stream", @@ -3326,7 +3326,7 @@ dependencies = [ "encode_unicode 0.3.6", "lazy_static", "libc", - "unicode-width", + "unicode-width 0.1.14", "windows-sys 0.52.0", ] @@ -3443,7 +3443,7 @@ dependencies = [ "serde", "serde_json", "tar", - "thiserror", + "thiserror 1.0.69", "tokio", "url", ] @@ -3533,7 +3533,7 @@ dependencies = [ "serde_json", "subtle-encoding", "tendermint", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -3575,9 +3575,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" +checksum = "0ca741a962e1b0bff6d724a1a0958b686406e853bb14061f218562e1896f95e6" dependencies = [ "libc", ] @@ -3909,9 +3909,9 @@ dependencies = [ [[package]] name = "csv" -version = "1.3.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe" +checksum = "acdc4883a9c96732e4733212c01447ebd805833b7275a73ca3ee080fd77afdaf" dependencies = [ "csv-core", "itoa", @@ -3989,7 +3989,7 @@ dependencies = [ "serde", "serde_json", "static_assertions", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -4007,7 +4007,7 @@ dependencies = [ "quote 1.0.37", "strsim 0.10.0", "syn 2.0.87", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -4528,6 +4528,7 @@ dependencies = [ "proc-macro2 1.0.89", "quote 1.0.37", "syn 2.0.87", + "unicode-xid 0.2.6", ] [[package]] @@ -4791,7 +4792,7 @@ dependencies = [ "serde", "serde_json", "tar", - "thiserror", + "thiserror 1.0.69", "url", ] @@ -4815,7 +4816,7 @@ checksum = "feadfed35b96a5634e08fc503677ded669549ae2cf7f0b01d5964f09d95487fd" dependencies = [ "documented-macros", "phf", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -4879,7 +4880,7 @@ dependencies = [ "nom", "rust_decimal", "serde", - "thiserror", + "thiserror 1.0.69", "time", ] @@ -4947,7 +4948,7 @@ dependencies = [ "rand_core 0.6.4", "serde", "sha2 0.9.9", - "thiserror", + "thiserror 1.0.69", "zeroize", ] @@ -5185,7 +5186,7 @@ dependencies = [ "serde_json", "sha2 0.10.8", "sha3 0.10.8", - "thiserror", + "thiserror 1.0.69", "uuid 0.8.2", ] @@ -5202,7 +5203,7 @@ dependencies = [ "serde", "serde_json", "sha3 0.10.8", - "thiserror", + "thiserror 1.0.69", "uint", ] @@ -5281,7 +5282,7 @@ dependencies = [ "pin-project", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -5349,7 +5350,7 @@ dependencies = [ "strum 0.26.3", "syn 2.0.87", "tempfile", - "thiserror", + "thiserror 1.0.69", "tiny-keccak", "unicode-xid 0.2.6", ] @@ -5366,7 +5367,7 @@ dependencies = [ "semver", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", "tracing", ] @@ -5390,7 +5391,7 @@ dependencies = [ "reqwest 0.11.27", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", "tracing-futures", @@ -5423,7 +5424,7 @@ dependencies = [ "reqwest 0.11.27", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-tungstenite 0.20.1", "tracing", @@ -5450,7 +5451,7 @@ dependencies = [ "ethers-core", "rand 0.8.5", "sha2 0.10.8", - "thiserror", + "thiserror 1.0.69", "tracing", ] @@ -5478,7 +5479,7 @@ dependencies = [ "serde_json", "solang-parser", "svm-rs", - "thiserror", + "thiserror 1.0.69", "tiny-keccak", "tokio", "tracing", @@ -5628,7 +5629,7 @@ dependencies = [ "sha3 0.10.8", "signature 2.2.0", "static_assertions", - "thiserror", + "thiserror 1.0.69", "tokio", "typenum", "zeroize", @@ -6171,7 +6172,7 @@ dependencies = [ "reqwest 0.12.9", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", "time", "tokio", "tokio-stream", @@ -6199,7 +6200,7 @@ dependencies = [ "rustls-pemfile 2.2.0", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", "tracing-futures", @@ -6298,7 +6299,7 @@ dependencies = [ "aho-corasick", "bstr", "log", - "regex-automata 0.4.8", + "regex-automata 0.4.9", "regex-syntax 0.8.5", ] @@ -6510,7 +6511,7 @@ dependencies = [ "pest_derive", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -7277,15 +7278,15 @@ dependencies = [ [[package]] name = "indicatif" -version = "0.17.8" +version = "0.17.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "763a5a8f45087d6bcea4222e7b72c291a054edf80e4ef6efd2a4979878c7bea3" +checksum = "cbf675b85ed934d3c67b5c5469701eec7db22689d0a2139d856e0925fa28b281" dependencies = [ "console", - "instant", "number_prefix", "portable-atomic", - "unicode-width", + "unicode-width 0.2.0", + "web-time", ] [[package]] @@ -7335,9 +7336,9 @@ dependencies = [ "dyn-clone", "lazy_static", "newline-converter", - "thiserror", + "thiserror 1.0.69", "unicode-segmentation", - "unicode-width", + "unicode-width 0.1.14", ] [[package]] @@ -7609,7 +7610,7 @@ dependencies = [ "pin-project", "rustls-native-certs 0.6.3", "soketto", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-rustls 0.23.4", "tokio-util 0.7.12", @@ -7639,7 +7640,7 @@ dependencies = [ "serde", "serde_json", "soketto", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", ] @@ -7657,7 +7658,7 @@ dependencies = [ "rustc-hash 1.1.0", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", ] @@ -7704,7 +7705,7 @@ dependencies = [ "beef", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", "tracing", ] @@ -7840,7 +7841,7 @@ version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "507460a910eb7b32ee961886ff48539633b788a36b65692b95f225b844c82553" dependencies = [ - "regex-automata 0.4.8", + "regex-automata 0.4.9", ] [[package]] @@ -8199,7 +8200,7 @@ dependencies = [ "serde_json", "strum 0.24.1", "strum_macros 0.24.3", - "thiserror", + "thiserror 1.0.69", "tokio", "tonic 0.9.2", "tonic-build 0.9.2", @@ -8231,7 +8232,7 @@ dependencies = [ "semver", "serde", "serde_with 3.11.0", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", "wasi-common", @@ -8250,7 +8251,7 @@ dependencies = [ "mamoru-chain-client", "mamoru-core", "serde", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", ] @@ -8267,7 +8268,7 @@ dependencies = [ "mamoru-sui-types", "move-core-types", "sui-types", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", ] @@ -8407,8 +8408,8 @@ dependencies = [ "supports-unicode", "terminal_size 0.3.0", "textwrap", - "thiserror", - "unicode-width", + "thiserror 1.0.69", + "unicode-width 0.1.14", ] [[package]] @@ -8536,7 +8537,7 @@ dependencies = [ "rustc_version", "smallvec", "tagptr", - "thiserror", + "thiserror 1.0.69", "triomphe", "uuid 1.11.0", ] @@ -8827,7 +8828,7 @@ dependencies = [ "serde", "serde_bytes", "serde_with 3.11.0", - "thiserror", + "thiserror 1.0.69", "uint", ] @@ -9493,13 +9494,11 @@ name = "mysten-network" version = "0.2.0" dependencies = [ "anemo", - "async-stream", "bcs", "bytes", "eyre", "futures", "http 1.1.0", - "hyper-rustls 0.27.3", "hyper-util", "multiaddr", "once_cell", @@ -9507,7 +9506,6 @@ dependencies = [ "serde", "snap", "tokio", - "tokio-rustls 0.26.0", "tokio-stream", "tonic 0.12.3", "tonic-health", @@ -9575,7 +9573,7 @@ dependencies = [ "libc", "once_cell", "parking_lot 0.12.3", - "thiserror", + "thiserror 1.0.69", "widestring", "winapi", ] @@ -9595,7 +9593,7 @@ dependencies = [ "serde", "serde_json", "tempfile", - "thiserror", + "thiserror 1.0.69", "tracing", ] @@ -9642,7 +9640,7 @@ dependencies = [ "sui-protocol-config", "telemetry-subscribers", "tempfile", - "thiserror", + "thiserror 1.0.69", "tokio", "tonic 0.12.3", "tracing", @@ -9713,7 +9711,7 @@ dependencies = [ "sui-protocol-config", "sui-types", "telemetry-subscribers", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-stream", "tracing", @@ -9766,7 +9764,7 @@ dependencies = [ "tap", "telemetry-subscribers", "tempfile", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-stream", "tower 0.4.13", @@ -9864,7 +9862,7 @@ dependencies = [ "serde_test", "serde_with 3.11.0", "sui-protocol-config", - "thiserror", + "thiserror 1.0.69", "tokio", "tonic 0.12.3", "tonic-build 0.12.3", @@ -9905,7 +9903,7 @@ dependencies = [ "tap", "telemetry-subscribers", "tempfile", - "thiserror", + "thiserror 1.0.69", "tokio", "tonic 0.12.3", "tower 0.4.13", @@ -10510,7 +10508,7 @@ dependencies = [ "js-sys", "once_cell", "pin-project-lite", - "thiserror", + "thiserror 1.0.69", "urlencoding", ] @@ -10525,7 +10523,7 @@ dependencies = [ "js-sys", "once_cell", "pin-project-lite", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -10541,7 +10539,7 @@ dependencies = [ "opentelemetry-proto", "opentelemetry_sdk", "prost 0.13.3", - "thiserror", + "thiserror 1.0.69", "tokio", "tonic 0.12.3", ] @@ -10560,22 +10558,6 @@ dependencies = [ "tonic 0.12.3", ] -[[package]] -name = "opentelemetry_api" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a81f725323db1b1206ca3da8bb19874bbd3f57c3bcd59471bfb04525b265b9b" -dependencies = [ - "futures-channel", - "futures-util", - "indexmap 1.9.3", - "js-sys", - "once_cell", - "pin-project-lite", - "thiserror", - "urlencoding", -] - [[package]] name = "opentelemetry_sdk" version = "0.25.0" @@ -10592,7 +10574,7 @@ dependencies = [ "percent-encoding", "rand 0.8.5", "serde_json", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-stream", ] @@ -10725,7 +10707,7 @@ checksum = "ae7891b22598926e4398790c8fe6447930c72a67d36d983a49d6ce682ce83290" dependencies = [ "bytecount", "fnv", - "unicode-width", + "unicode-width 0.1.14", ] [[package]] @@ -11087,7 +11069,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "879952a81a83930934cbf1786752d6dedc3b1f29e8f8fb2ad1d0a36f377cf442" dependencies = [ "memchr", - "thiserror", + "thiserror 1.0.69", "ucd-trie", ] @@ -11432,7 +11414,7 @@ dependencies = [ "smallvec", "symbolic-demangle", "tempfile", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -11532,7 +11514,7 @@ dependencies = [ "is-terminal", "lazy_static", "term", - "unicode-width", + "unicode-width 0.1.14", ] [[package]] @@ -11576,7 +11558,7 @@ version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a" dependencies = [ - "thiserror", + "thiserror 1.0.69", "toml 0.5.11", ] @@ -11656,7 +11638,7 @@ dependencies = [ "memchr", "parking_lot 0.12.3", "protobuf", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -11874,9 +11856,9 @@ dependencies = [ [[package]] name = "psm" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa37f80ca58604976033fae9515a8a2989fc13797d953f7c04fb8fa36a11f205" +checksum = "200b9ff220857e53e184257720a14553b2f4aa02577d2ed9842d45d4b9654810" dependencies = [ "cc", ] @@ -11930,9 +11912,9 @@ dependencies = [ [[package]] name = "quinn" -version = "0.11.5" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c7c5fdde3cdae7203427dc4f0a68fe0ed09833edc525a03456b153b79828684" +checksum = "62e96808277ec6f97351a2380e6c25114bc9e67037775464979f3037c92d05ef" dependencies = [ "bytes", "futures-io", @@ -11942,26 +11924,29 @@ dependencies = [ "rustc-hash 2.0.0", "rustls 0.23.16", "socket2 0.5.7", - "thiserror", + "thiserror 2.0.3", "tokio", "tracing", ] [[package]] name = "quinn-proto" -version = "0.11.8" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fadfaed2cd7f389d0161bb73eeb07b7b78f8691047a6f3e73caaeae55310a4a6" +checksum = "a2fe5ef3495d7d2e377ff17b1a8ce2ee2ec2a18cde8b6ad6619d65d0701c135d" dependencies = [ "bytes", + "getrandom 0.2.15", "rand 0.8.5", "ring 0.17.8", "rustc-hash 2.0.0", "rustls 0.23.16", + "rustls-pki-types", "slab", - "thiserror", + "thiserror 2.0.3", "tinyvec", "tracing", + "web-time", ] [[package]] @@ -12204,7 +12189,7 @@ checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom 0.2.15", "libredox", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -12248,7 +12233,7 @@ checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.8", + "regex-automata 0.4.9", "regex-syntax 0.8.5", ] @@ -12263,9 +12248,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -12390,7 +12375,7 @@ dependencies = [ "http 1.1.0", "reqwest 0.12.9", "serde", - "thiserror", + "thiserror 1.0.69", "tower-service", ] @@ -12763,7 +12748,7 @@ dependencies = [ "sha1", "sha2 0.10.8", "subtle", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-util 0.7.12", ] @@ -12808,7 +12793,7 @@ dependencies = [ "russh-cryptovec", "serde", "sha2 0.10.8", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-stream", "yasna", @@ -12868,9 +12853,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.39" +version = "0.38.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "375116bee2be9ed569afe2154ea6a99dfdffd257f533f187498c2a8f5feaf4ee" +checksum = "99e4ea3e1cdc4b559b8e5650f9c8e5998e3e5c1343b4eaf034565f32318d63c0" dependencies = [ "bitflags 2.6.0", "errno", @@ -12995,6 +12980,9 @@ name = "rustls-pki-types" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" +dependencies = [ + "web-time", +] [[package]] name = "rustls-webpki" @@ -13054,7 +13042,7 @@ dependencies = [ "scopeguard", "smallvec", "unicode-segmentation", - "unicode-width", + "unicode-width 0.1.14", "utf8parse", "winapi", ] @@ -13258,9 +13246,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.12.0" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" +checksum = "fa39c7303dc58b5543c94d22c1766b0d31f2ee58306363ea622b10bbc075eaa2" dependencies = [ "core-foundation-sys", "libc", @@ -13295,9 +13283,9 @@ checksum = "a3f0bf26fd526d2a95683cd0f87bf103b8539e2ca1ef48ce002d67aad59aa0b4" [[package]] name = "serde" -version = "1.0.214" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" dependencies = [ "serde_derive", ] @@ -13319,7 +13307,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b5b14ebbcc4e4f2b3642fa99c388649da58d1dc3308c7d109f39f565d1710f0" dependencies = [ "serde", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -13330,7 +13318,7 @@ checksum = "f05a5f801ac62a51a49d378fdb3884480041b99aced450b28990673e8ff99895" dependencies = [ "once_cell", "serde", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -13344,9 +13332,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.214" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2 1.0.89", "quote 1.0.37", @@ -13395,7 +13383,7 @@ checksum = "c7715380eec75f029a4ef7de39a9200e0a63823176b759d055b613f5a87df6a6" dependencies = [ "percent-encoding", "serde", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -13733,7 +13721,7 @@ checksum = "adc4e5204eb1910f40f9cfa375f6f05b68c3abac4b6fd879c8ff5e7ae8a0a085" dependencies = [ "num-bigint 0.4.6", "num-traits", - "thiserror", + "thiserror 1.0.69", "time", ] @@ -13879,7 +13867,7 @@ dependencies = [ "serde", "serde_json", "snowflake-jwt", - "thiserror", + "thiserror 1.0.69", "tokio", "url", "uuid 1.11.0", @@ -13896,7 +13884,7 @@ dependencies = [ "rsa 0.9.6", "serde", "sha2 0.10.8", - "thiserror", + "thiserror 1.0.69", "time", ] @@ -13946,7 +13934,7 @@ dependencies = [ "lalrpop", "lalrpop-util", "phf", - "thiserror", + "thiserror 1.0.69", "unicode-xid 0.2.6", ] @@ -14210,7 +14198,7 @@ checksum = "734676eb262c623cec13c3155096e08d1f8f29adce39ba17948b18dad1e54142" [[package]] name = "sui" -version = "1.37.1" +version = "1.37.3" dependencies = [ "anemo", "anyhow", @@ -14297,7 +14285,7 @@ dependencies = [ "telemetry-subscribers", "tempfile", "test-cluster", - "thiserror", + "thiserror 1.0.69", "tokio", "toml 0.7.8", "tower 0.4.13", @@ -14428,7 +14416,7 @@ dependencies = [ [[package]] name = "sui-analytics-indexer" -version = "1.37.1" +version = "1.37.3" dependencies = [ "anyhow", "arrow 52.2.0", @@ -14470,7 +14458,7 @@ dependencies = [ "tap", "telemetry-subscribers", "tempfile", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-stream", "tracing", @@ -14480,7 +14468,7 @@ dependencies = [ [[package]] name = "sui-analytics-indexer-derive" -version = "1.37.1" +version = "1.37.3" dependencies = [ "proc-macro2 1.0.89", "quote 1.0.37", @@ -14489,7 +14477,7 @@ dependencies = [ [[package]] name = "sui-archival" -version = "1.37.1" +version = "1.37.3" dependencies = [ "anyhow", "byteorder", @@ -14558,7 +14546,7 @@ dependencies = [ "sui-swarm-config", "sui-types", "tempfile", - "thiserror", + "thiserror 1.0.69", "tokio", ] @@ -14614,7 +14602,7 @@ dependencies = [ [[package]] name = "sui-bridge" -version = "1.37.1" +version = "1.37.3" dependencies = [ "anyhow", "arc-swap", @@ -14664,7 +14652,7 @@ dependencies = [ [[package]] name = "sui-bridge-cli" -version = "1.37.1" +version = "1.37.3" dependencies = [ "anyhow", "clap", @@ -14730,12 +14718,12 @@ dependencies = [ [[package]] name = "sui-cluster-test" -version = "1.37.1" +version = "1.37.3" dependencies = [ "anyhow", "async-trait", "clap", - "derivative", + "derive_more 1.0.0", "fastcrypto", "futures", "jsonrpsee", @@ -14890,7 +14878,7 @@ dependencies = [ "telemetry-subscribers", "tempfile", "test-fuzz", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-retry", "tokio-stream", @@ -14924,7 +14912,7 @@ dependencies = [ [[package]] name = "sui-data-ingestion" -version = "1.37.1" +version = "1.37.3" dependencies = [ "anyhow", "async-trait", @@ -15021,7 +15009,7 @@ dependencies = [ [[package]] name = "sui-e2e-tests" -version = "1.37.1" +version = "1.37.3" dependencies = [ "anyhow", "assert_cmd", @@ -15133,14 +15121,14 @@ dependencies = [ "clap", "expect-test", "tempfile", - "thiserror", + "thiserror 1.0.69", "toml 0.7.8", "toml_edit 0.19.15", ] [[package]] name = "sui-faucet" -version = "1.37.1" +version = "1.37.3" dependencies = [ "anyhow", "async-recursion", @@ -15167,7 +15155,7 @@ dependencies = [ "telemetry-subscribers", "tempfile", "test-cluster", - "thiserror", + "thiserror 1.0.69", "tokio", "tonic 0.12.3", "tower 0.4.13", @@ -15180,7 +15168,7 @@ dependencies = [ [[package]] name = "sui-field-count" -version = "1.37.1" +version = "1.37.3" dependencies = [ "sui-field-count-derive", "sui-field-count-main", @@ -15188,7 +15176,7 @@ dependencies = [ [[package]] name = "sui-field-count-derive" -version = "1.37.1" +version = "1.37.3" dependencies = [ "quote 1.0.37", "syn 1.0.109", @@ -15196,7 +15184,7 @@ dependencies = [ [[package]] name = "sui-field-count-main" -version = "1.37.1" +version = "1.37.3" [[package]] name = "sui-framework" @@ -15220,7 +15208,7 @@ dependencies = [ [[package]] name = "sui-framework-snapshot" -version = "1.37.1" +version = "1.37.3" dependencies = [ "anyhow", "bcs", @@ -15284,7 +15272,7 @@ dependencies = [ [[package]] name = "sui-graphql-config" -version = "1.37.1" +version = "1.37.3" dependencies = [ "quote 1.0.37", "syn 1.0.109", @@ -15304,7 +15292,7 @@ dependencies = [ [[package]] name = "sui-graphql-rpc" -version = "1.37.1" +version = "1.37.3" dependencies = [ "anyhow", "async-graphql", @@ -15371,7 +15359,7 @@ dependencies = [ "telemetry-subscribers", "tempfile", "test-cluster", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-util 0.7.12", "toml 0.7.8", @@ -15391,7 +15379,7 @@ dependencies = [ "reqwest 0.12.9", "serde_json", "sui-graphql-rpc-headers", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -15403,7 +15391,7 @@ dependencies = [ [[package]] name = "sui-indexer" -version = "1.37.1" +version = "1.37.3" dependencies = [ "anyhow", "async-trait", @@ -15469,7 +15457,7 @@ dependencies = [ "telemetry-subscribers", "tempfile", "test-cluster", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-stream", "tokio-util 0.7.12", @@ -15480,7 +15468,7 @@ dependencies = [ [[package]] name = "sui-indexer-alt" -version = "1.37.1" +version = "1.37.3" dependencies = [ "anyhow", "async-trait", @@ -15504,7 +15492,7 @@ dependencies = [ "sui-types", "telemetry-subscribers", "tempfile", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-stream", "tokio-util 0.7.12", @@ -15599,7 +15587,7 @@ dependencies = [ "sui-types", "tap", "telemetry-subscribers", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-util 0.7.12", "tower 0.4.13", @@ -15714,7 +15702,7 @@ dependencies = [ [[package]] name = "sui-kvstore" -version = "1.37.1" +version = "1.37.3" dependencies = [ "anyhow", "async-trait", @@ -15736,7 +15724,7 @@ dependencies = [ [[package]] name = "sui-light-client" -version = "1.37.1" +version = "1.37.3" dependencies = [ "anyhow", "async-trait", @@ -15774,7 +15762,7 @@ dependencies = [ [[package]] name = "sui-metric-checker" -version = "1.37.1" +version = "1.37.3" dependencies = [ "anyhow", "backoff", @@ -15795,7 +15783,7 @@ dependencies = [ [[package]] name = "sui-move" -version = "1.37.1" +version = "1.37.3" dependencies = [ "anyhow", "assert_cmd", @@ -15837,7 +15825,7 @@ dependencies = [ [[package]] name = "sui-move-build" -version = "1.37.1" +version = "1.37.3" dependencies = [ "anyhow", "datatest-stable", @@ -15861,7 +15849,7 @@ dependencies = [ [[package]] name = "sui-move-lsp" -version = "1.37.1" +version = "1.37.3" dependencies = [ "bin-version", "clap", @@ -15953,7 +15941,7 @@ dependencies = [ [[package]] name = "sui-mvr-indexer" -version = "1.37.1" +version = "1.37.3" dependencies = [ "anyhow", "async-trait", @@ -16019,7 +16007,7 @@ dependencies = [ "telemetry-subscribers", "tempfile", "test-cluster", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-stream", "tokio-util 0.7.12", @@ -16070,7 +16058,7 @@ dependencies = [ [[package]] name = "sui-node" -version = "1.37.1" +version = "1.37.3" dependencies = [ "anemo", "anemo-tower", @@ -16122,7 +16110,7 @@ dependencies = [ [[package]] name = "sui-open-rpc" -version = "1.37.1" +version = "1.37.3" dependencies = [ "anyhow", "bcs", @@ -16158,7 +16146,7 @@ dependencies = [ [[package]] name = "sui-oracle" -version = "1.37.1" +version = "1.37.3" dependencies = [ "anyhow", "bcs", @@ -16188,7 +16176,7 @@ dependencies = [ [[package]] name = "sui-package-dump" -version = "1.37.1" +version = "1.37.3" dependencies = [ "anyhow", "bcs", @@ -16205,7 +16193,7 @@ dependencies = [ [[package]] name = "sui-package-management" -version = "1.37.1" +version = "1.37.3" dependencies = [ "anyhow", "move-core-types", @@ -16214,7 +16202,7 @@ dependencies = [ "sui-json-rpc-types", "sui-sdk", "sui-types", - "thiserror", + "thiserror 1.0.69", "tracing", ] @@ -16237,7 +16225,7 @@ dependencies = [ "sui-move-build", "sui-rest-api", "sui-types", - "thiserror", + "thiserror 1.0.69", "tokio", "tower 0.4.13", ] @@ -16364,7 +16352,7 @@ dependencies = [ "sui-types", "tabled", "tempfile", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-util 0.7.12", "tracing", @@ -16401,14 +16389,14 @@ dependencies = [ "sui-sdk-types", "sui-types", "tap", - "thiserror", + "thiserror 1.0.69", "tokio", "url", ] [[package]] name = "sui-rosetta" -version = "1.37.1" +version = "1.37.3" dependencies = [ "anyhow", "async-trait", @@ -16445,7 +16433,7 @@ dependencies = [ "telemetry-subscribers", "tempfile", "test-cluster", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", "typed-store", @@ -16453,7 +16441,7 @@ dependencies = [ [[package]] name = "sui-rpc-loadgen" -version = "1.37.1" +version = "1.37.3" dependencies = [ "anyhow", "async-trait", @@ -16482,7 +16470,7 @@ dependencies = [ [[package]] name = "sui-sdk" -version = "1.37.1" +version = "1.37.3" dependencies = [ "anyhow", "async-recursion", @@ -16511,7 +16499,7 @@ dependencies = [ "sui-transaction-builder", "sui-types", "tempfile", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", ] @@ -16538,7 +16526,7 @@ dependencies = [ [[package]] name = "sui-security-watchdog" -version = "1.37.1" +version = "1.37.3" dependencies = [ "anyhow", "arrow-array 52.2.0", @@ -16585,7 +16573,7 @@ dependencies = [ [[package]] name = "sui-single-node-benchmark" -version = "1.37.1" +version = "1.37.3" dependencies = [ "async-trait", "bcs", @@ -16648,7 +16636,7 @@ dependencies = [ [[package]] name = "sui-source-validation" -version = "1.37.1" +version = "1.37.3" dependencies = [ "anyhow", "colored", @@ -16672,7 +16660,7 @@ dependencies = [ "tar", "tempfile", "test-cluster", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", "ureq", @@ -16774,7 +16762,7 @@ dependencies = [ [[package]] name = "sui-surfer" -version = "1.37.1" +version = "1.37.3" dependencies = [ "async-trait", "bcs", @@ -16893,7 +16881,7 @@ dependencies = [ [[package]] name = "sui-test-validator" -version = "1.37.1" +version = "1.37.3" [[package]] name = "sui-tls" @@ -16919,7 +16907,7 @@ dependencies = [ [[package]] name = "sui-tool" -version = "1.37.1" +version = "1.37.3" dependencies = [ "anemo", "anemo-cli", @@ -16954,7 +16942,6 @@ dependencies = [ "sui-sdk", "sui-snapshot", "sui-storage", - "sui-tls", "sui-types", "telemetry-subscribers", "tempfile", @@ -17055,8 +17042,7 @@ dependencies = [ "consensus-config", "coset", "criterion", - "derivative", - "derive_more 0.99.18", + "derive_more 1.0.0", "enum_dispatch", "expect-test", "eyre", @@ -17110,7 +17096,7 @@ dependencies = [ "sui-protocol-config", "sui-sdk-types", "tap", - "thiserror", + "thiserror 1.0.69", "tokio", "tonic 0.12.3", "tracing", @@ -17202,7 +17188,7 @@ dependencies = [ [[package]] name = "suins-indexer" -version = "1.37.1" +version = "1.37.3" dependencies = [ "anyhow", "async-trait", @@ -17242,7 +17228,7 @@ dependencies = [ [[package]] name = "suiop-cli" -version = "1.37.1" +version = "1.37.3" dependencies = [ "anyhow", "axum 0.7.7", @@ -17275,7 +17261,7 @@ dependencies = [ "strum 0.24.1", "tabled", "tempfile", - "thiserror", + "thiserror 1.0.69", "tokio", "toml_edit 0.19.15", "tracing", @@ -17318,7 +17304,7 @@ dependencies = [ "serde", "serde_json", "sha2 0.10.8", - "thiserror", + "thiserror 1.0.69", "url", "zip", ] @@ -17477,7 +17463,7 @@ checksum = "0ce69a5028cd9576063ec1f48edb2c75339fd835e6094ef3e05b3a079bf594a6" dependencies = [ "papergrid", "tabled_derive", - "unicode-width", + "unicode-width 0.1.14", ] [[package]] @@ -17500,7 +17486,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9a2882c514780a1973df90de9d68adcd8871bacc9a6331c3f28e6d2ff91a3d1" dependencies = [ "strip-ansi-escapes", - "unicode-width", + "unicode-width 0.1.14", ] [[package]] @@ -17561,7 +17547,6 @@ dependencies = [ "opentelemetry 0.25.0", "opentelemetry-otlp", "opentelemetry-proto", - "opentelemetry_api", "opentelemetry_sdk", "prometheus", "prost 0.13.3", @@ -17782,23 +17767,43 @@ checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" dependencies = [ "smawk", "unicode-linebreak", - "unicode-width", + "unicode-width 0.1.14", ] [[package]] name = "thiserror" -version = "1.0.68" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02dd99dc800bbb97186339685293e1cc5d9df1f8fae2d0aecd9ff1c77efea892" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa" +dependencies = [ + "thiserror-impl 2.0.3", ] [[package]] name = "thiserror-impl" -version = "1.0.68" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7c61ec9a6f64d2793d8a45faba21efbe3ced62a886d44c36a009b2b519b4c7e" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2 1.0.89", + "quote 1.0.37", + "syn 2.0.87", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568" dependencies = [ "proc-macro2 1.0.89", "quote 1.0.37", @@ -17881,7 +17886,7 @@ dependencies = [ "rand 0.8.5", "rustc-hash 1.1.0", "sha2 0.10.8", - "thiserror", + "thiserror 1.0.69", "unicode-normalization", "wasm-bindgen", "zeroize", @@ -18535,7 +18540,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3566e8ce28cc0a3fe42519fc80e6b4c943cc4c8cef275620eb8dac2d3d4e06cf" dependencies = [ "crossbeam-channel", - "thiserror", + "thiserror 1.0.69", "time", "tracing-subscriber", ] @@ -18709,7 +18714,7 @@ dependencies = [ "cassowary", "crossterm 0.25.0", "unicode-segmentation", - "unicode-width", + "unicode-width 0.1.14", ] [[package]] @@ -18727,7 +18732,7 @@ dependencies = [ "rand 0.8.5", "rustls 0.21.12", "sha1", - "thiserror", + "thiserror 1.0.69", "url", "utf-8", ] @@ -18746,7 +18751,7 @@ dependencies = [ "log", "rand 0.8.5", "sha1", - "thiserror", + "thiserror 1.0.69", "utf-8", ] @@ -18787,7 +18792,7 @@ dependencies = [ "syn 1.0.109", "tap", "tempfile", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", "typed-store-derive", @@ -18811,7 +18816,7 @@ name = "typed-store-error" version = "0.4.0" dependencies = [ "serde", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -18940,6 +18945,12 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" +[[package]] +name = "unicode-width" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" + [[package]] name = "unicode-xid" version = "0.1.0" @@ -19206,7 +19217,7 @@ dependencies = [ "once_cell", "rustix", "system-interface", - "thiserror", + "thiserror 1.0.69", "tracing", "wasmtime", "wiggle", @@ -19297,12 +19308,12 @@ dependencies = [ [[package]] name = "wasm-encoder" -version = "0.219.1" +version = "0.220.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29cbbd772edcb8e7d524a82ee8cef8dd046fc14033796a754c3ad246d019fa54" +checksum = "ebf48234b389415b226a4daef6562933d38c7b28a8b8f64c5c4130dad1561ab7" dependencies = [ "leb128", - "wasmparser 0.219.1", + "wasmparser 0.220.0", ] [[package]] @@ -19346,9 +19357,9 @@ dependencies = [ [[package]] name = "wasmparser" -version = "0.219.1" +version = "0.220.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c771866898879073c53b565a6c7b49953795159836714ac56a5befb581227c5" +checksum = "e246c2772ce3ebc83f89a2d4487ac5794cad6c309b2071818a88c7db7c36d87b" dependencies = [ "bitflags 2.6.0", "indexmap 2.6.0", @@ -19476,7 +19487,7 @@ dependencies = [ "log", "object", "target-lexicon", - "thiserror", + "thiserror 1.0.69", "wasmparser 0.121.2", "wasmtime-cranelift-shared", "wasmtime-environ", @@ -19517,7 +19528,7 @@ dependencies = [ "serde", "serde_derive", "target-lexicon", - "thiserror", + "thiserror 1.0.69", "wasm-encoder 0.41.2", "wasmparser 0.121.2", "wasmprinter", @@ -19602,7 +19613,7 @@ dependencies = [ "cranelift-entity", "serde", "serde_derive", - "thiserror", + "thiserror 1.0.69", "wasmparser 0.121.2", ] @@ -19640,7 +19651,7 @@ dependencies = [ "once_cell", "rustix", "system-interface", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", "url", @@ -19696,24 +19707,24 @@ dependencies = [ [[package]] name = "wast" -version = "219.0.1" +version = "220.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f79a9d9df79986a68689a6b40bcc8d5d40d807487b235bebc2ac69a242b54a1" +checksum = "4e708c8de08751fd66e70961a32bae9d71901f14a70871e181cb8461a3bb3165" dependencies = [ "bumpalo", "leb128", "memchr", - "unicode-width", - "wasm-encoder 0.219.1", + "unicode-width 0.2.0", + "wasm-encoder 0.220.0", ] [[package]] name = "wat" -version = "1.219.1" +version = "1.220.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bc3cf014fb336883a411cd662f987abf6a1d2a27f2f0008616a0070bbf6bd0d" +checksum = "de4f1d7d59614ba690541360102b995c4eb1b9ed373701d5102cc1a968b1c5a3" dependencies = [ - "wast 219.0.1", + "wast 220.0.0", ] [[package]] @@ -19808,7 +19819,7 @@ dependencies = [ "anyhow", "async-trait", "bitflags 2.6.0", - "thiserror", + "thiserror 1.0.69", "tracing", "wasmtime", "wiggle-macro", @@ -20160,7 +20171,7 @@ checksum = "e366f27a5cabcddb2706a78296a40b8fcc451e1a6aba2fc1d94b4a01bdaaef4b" dependencies = [ "anyhow", "log", - "thiserror", + "thiserror 1.0.69", "wast 35.0.2", ] @@ -20189,7 +20200,7 @@ dependencies = [ "pharos", "rustc_version", "send_wrapper 0.6.0", - "thiserror", + "thiserror 1.0.69", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", @@ -20212,7 +20223,7 @@ dependencies = [ [[package]] name = "x" -version = "1.37.1" +version = "1.37.3" dependencies = [ "anyhow", "camino", @@ -20236,7 +20247,7 @@ dependencies = [ "ring 0.17.8", "signature 2.2.0", "spki 0.7.3", - "thiserror", + "thiserror 1.0.69", "zeroize", ] @@ -20254,7 +20265,7 @@ dependencies = [ "nom", "oid-registry", "rusticata-macros", - "thiserror", + "thiserror 1.0.69", "time", ] diff --git a/Cargo.toml b/Cargo.toml index ed066f8183cd4..18ddc620ad4cd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -209,7 +209,7 @@ members = [ [workspace.package] # This version string will be inherited by sui-core, sui-faucet, sui-node, sui-tools, sui-sdk, sui-move-build, and sui crates. -version = "1.37.1" +version = "1.37.3" [profile.release] # debug = 1 means line charts only, which is minimum needed for good stack traces @@ -262,7 +262,6 @@ async-graphql = "=7.0.1" async-graphql-axum = "=7.0.1" async-graphql-value = "=7.0.1" async-recursion = "1.0.4" -async-stream = "0.3.6" async-trait = "0.1.61" atomic_float = "0.1" aws-config = "0.56" @@ -328,10 +327,9 @@ cynic-codegen = "= 3.7.3" dashmap = "5.5.3" # datatest-stable = "0.1.2" datatest-stable = { git = "https://github.com/nextest-rs/datatest-stable.git", rev = "72db7f6d1bbe36a5407e96b9488a581f763e106f" } -derivative = "2.2.0" derive-syn-parse = "0.1.5" derive_builder = "0.12.0" -derive_more = "0.99.17" +derive_more = "1.0.0" diesel = "2.2" diesel_migrations = "2.2" diesel-async = "0.5" @@ -583,17 +581,17 @@ move-abstract-interpreter = { path = "external-crates/move/crates/move-abstract- move-abstract-stack = { path = "external-crates/move/crates/move-abstract-stack" } move-analyzer = { path = "external-crates/move/crates/move-analyzer" } -mamoru-sniffer = { git = "https://github.com/Mamoru-Foundation/mamoru-core", rev = "d0c8237f85ccedc286ffd12ec260abc384146383" } -mamoru-sui-types = { git = "https://github.com/Mamoru-Foundation/mamoru-core", rev = "d0c8237f85ccedc286ffd12ec260abc384146383" } -#mamoru-sniffer = { path = "../mamoru-core/mamoru-sniffer" } -#mamoru-sui-types = { path = "../mamoru-core/blockchain-types/mamoru-sui-types" } - fastcrypto = { git = "https://github.com/MystenLabs/fastcrypto", rev = "2f502fd8570fe4e9cff36eea5bbd6fef22002898" } fastcrypto-tbls = { git = "https://github.com/MystenLabs/fastcrypto", rev = "2f502fd8570fe4e9cff36eea5bbd6fef22002898" } fastcrypto-zkp = { git = "https://github.com/MystenLabs/fastcrypto", rev = "2f502fd8570fe4e9cff36eea5bbd6fef22002898", package = "fastcrypto-zkp" } fastcrypto-vdf = { git = "https://github.com/MystenLabs/fastcrypto", rev = "2f502fd8570fe4e9cff36eea5bbd6fef22002898", features = [ "experimental", ] } +mamoru-sniffer = { git = "https://github.com/Mamoru-Foundation/mamoru-core", rev = "d0c8237f85ccedc286ffd12ec260abc384146383" } +mamoru-sui-types = { git = "https://github.com/Mamoru-Foundation/mamoru-core", rev = "d0c8237f85ccedc286ffd12ec260abc384146383" } +#mamoru-sniffer = { path = "../mamoru-core/mamoru-sniffer" } +#mamoru-sui-types = { path = "../mamoru-core/blockchain-types/mamoru-sui-types" } + passkey-types = { version = "0.2.0" } passkey-client = { version = "0.2.0" } passkey-authenticator = { version = "0.2.0" } diff --git a/consensus/core/src/network/tonic_network.rs b/consensus/core/src/network/tonic_network.rs index 59a29a102ff90..1c07f013cecc4 100644 --- a/consensus/core/src/network/tonic_network.rs +++ b/consensus/core/src/network/tonic_network.rs @@ -24,7 +24,6 @@ use mysten_network::{ Multiaddr, }; use parking_lot::RwLock; -use sui_tls::AllowPublicKeys; use tokio::{ pin, task::JoinSet, @@ -45,6 +44,7 @@ use super::{ consensus_service_client::ConsensusServiceClient, consensus_service_server::ConsensusService, }, + tonic_tls::create_rustls_client_config, BlockStream, NetworkClient, NetworkManager, NetworkService, }; use crate::{ @@ -54,7 +54,7 @@ use crate::{ error::{ConsensusError, ConsensusResult}, network::{ tonic_gen::consensus_service_server::ConsensusServiceServer, - tonic_tls::certificate_server_name, + tonic_tls::create_rustls_server_config, }, CommitIndex, Round, }; @@ -381,16 +381,7 @@ impl ChannelPool { let address = format!("https://{address}"); let config = &self.context.parameters.tonic; let buffer_size = config.connection_buffer_size; - let client_tls_config = sui_tls::create_rustls_client_config( - self.context - .committee - .authority(peer) - .network_key - .clone() - .into_inner(), - certificate_server_name(&self.context), - Some(network_keypair.private_key().into_inner()), - ); + let client_tls_config = create_rustls_client_config(&self.context, network_keypair, peer); let endpoint = tonic_rustls::Channel::from_shared(address.clone()) .unwrap() .connect_timeout(timeout) @@ -737,17 +728,8 @@ impl NetworkManager for TonicManager { Arc::new(builder) }; - let tls_server_config = sui_tls::create_rustls_server_config( - self.network_keypair.clone().private_key().into_inner(), - certificate_server_name(&self.context), - AllowPublicKeys::new( - self.context - .committee - .authorities() - .map(|(_i, a)| a.network_key.clone().into_inner()) - .collect(), - ), - ); + let tls_server_config = + create_rustls_server_config(&self.context, self.network_keypair.clone()); let tls_acceptor = TlsAcceptor::from(Arc::new(tls_server_config)); // Create listener to incoming connections. diff --git a/consensus/core/src/network/tonic_tls.rs b/consensus/core/src/network/tonic_tls.rs index 6e7ff630115ec..13377934e3b18 100644 --- a/consensus/core/src/network/tonic_tls.rs +++ b/consensus/core/src/network/tonic_tls.rs @@ -2,7 +2,63 @@ // SPDX-License-Identifier: Apache-2.0 use crate::context::Context; +use consensus_config::{AuthorityIndex, NetworkKeyPair}; +use sui_tls::AllowPublicKeys; +use tokio_rustls::rustls::{ClientConfig, ServerConfig}; -pub(crate) fn certificate_server_name(context: &Context) -> String { +pub(crate) fn create_rustls_server_config( + context: &Context, + network_keypair: NetworkKeyPair, +) -> ServerConfig { + let allower = AllowPublicKeys::new( + context + .committee + .authorities() + .map(|(_i, a)| a.network_key.clone().into_inner()) + .collect(), + ); + let verifier = sui_tls::ClientCertVerifier::new(allower, certificate_server_name(context)); + // TODO: refactor to use key bytes + let self_signed_cert = sui_tls::SelfSignedCertificate::new( + network_keypair.private_key().into_inner(), + &certificate_server_name(context), + ); + let tls_cert = self_signed_cert.rustls_certificate(); + let tls_private_key = self_signed_cert.rustls_private_key(); + let mut tls_config = verifier + .rustls_server_config(vec![tls_cert], tls_private_key) + .unwrap_or_else(|e| panic!("Failed to create TLS server config: {:?}", e)); + tls_config.alpn_protocols = vec![b"h2".to_vec()]; + tls_config +} + +pub(crate) fn create_rustls_client_config( + context: &Context, + network_keypair: NetworkKeyPair, + target: AuthorityIndex, +) -> ClientConfig { + let target_public_key = context + .committee + .authority(target) + .network_key + .clone() + .into_inner(); + let self_signed_cert = sui_tls::SelfSignedCertificate::new( + network_keypair.private_key().into_inner(), + &certificate_server_name(context), + ); + let tls_cert = self_signed_cert.rustls_certificate(); + let tls_private_key = self_signed_cert.rustls_private_key(); + let mut tls_config = + sui_tls::ServerCertVerifier::new(target_public_key, certificate_server_name(context)) + .rustls_client_config(vec![tls_cert], tls_private_key) + .unwrap_or_else(|e| panic!("Failed to create TLS client config: {:?}", e)); + // ServerCertVerifier sets alpn for completeness, but alpn cannot be predefined when + // using HttpsConnector from hyper-rustls, as in TonicManager. + tls_config.alpn_protocols = vec![]; + tls_config +} + +fn certificate_server_name(context: &Context) -> String { format!("consensus_epoch_{}", context.committee.epoch()) } diff --git a/crates/mysten-network/Cargo.toml b/crates/mysten-network/Cargo.toml index 18426cb914806..3fb61694e170f 100644 --- a/crates/mysten-network/Cargo.toml +++ b/crates/mysten-network/Cargo.toml @@ -9,7 +9,6 @@ publish = false [dependencies] anemo.workspace = true -async-stream.workspace = true bcs.workspace = true bytes.workspace = true eyre.workspace = true @@ -19,10 +18,8 @@ multiaddr.workspace = true serde.workspace = true once_cell.workspace = true snap.workspace = true -hyper-rustls.workspace = true hyper-util.workspace = true tokio = { workspace = true, features = ["sync", "rt", "macros"] } -tokio-rustls.workspace = true tokio-stream.workspace = true tonic.workspace = true tonic-health.workspace = true diff --git a/crates/mysten-network/src/client.rs b/crates/mysten-network/src/client.rs index 8cb508c798431..f0c188f54f21c 100644 --- a/crates/mysten-network/src/client.rs +++ b/crates/mysten-network/src/client.rs @@ -21,67 +21,53 @@ use std::{ vec, }; use tokio::task::JoinHandle; -use tokio_rustls::rustls::ClientConfig; use tonic::transport::{Channel, Endpoint, Uri}; use tower::Service; use tracing::{info, trace}; -pub async fn connect(address: &Multiaddr, tls_config: Option) -> Result { - let channel = endpoint_from_multiaddr(address, tls_config)? - .connect() - .await?; +pub async fn connect(address: &Multiaddr) -> Result { + let channel = endpoint_from_multiaddr(address)?.connect().await?; Ok(channel) } -pub fn connect_lazy(address: &Multiaddr, tls_config: Option) -> Result { - let channel = endpoint_from_multiaddr(address, tls_config)?.connect_lazy(); +pub fn connect_lazy(address: &Multiaddr) -> Result { + let channel = endpoint_from_multiaddr(address)?.connect_lazy(); Ok(channel) } -pub(crate) async fn connect_with_config( - address: &Multiaddr, - tls_config: Option, - config: &Config, -) -> Result { - let channel = endpoint_from_multiaddr(address, tls_config)? +pub(crate) async fn connect_with_config(address: &Multiaddr, config: &Config) -> Result { + let channel = endpoint_from_multiaddr(address)? .apply_config(config) .connect() .await?; Ok(channel) } -pub(crate) fn connect_lazy_with_config( - address: &Multiaddr, - tls_config: Option, - config: &Config, -) -> Result { - let channel = endpoint_from_multiaddr(address, tls_config)? +pub(crate) fn connect_lazy_with_config(address: &Multiaddr, config: &Config) -> Result { + let channel = endpoint_from_multiaddr(address)? .apply_config(config) .connect_lazy(); Ok(channel) } -fn endpoint_from_multiaddr( - addr: &Multiaddr, - tls_config: Option, -) -> Result { +fn endpoint_from_multiaddr(addr: &Multiaddr) -> Result { let mut iter = addr.iter(); let channel = match iter.next().ok_or_else(|| eyre!("address is empty"))? { Protocol::Dns(_) => { let (dns_name, tcp_port, http_or_https) = parse_dns(addr)?; let uri = format!("{http_or_https}://{dns_name}:{tcp_port}"); - MyEndpoint::try_from_uri(uri, tls_config)? + MyEndpoint::try_from_uri(uri)? } Protocol::Ip4(_) => { let (socket_addr, http_or_https) = parse_ip4(addr)?; let uri = format!("{http_or_https}://{socket_addr}"); - MyEndpoint::try_from_uri(uri, tls_config)? + MyEndpoint::try_from_uri(uri)? } Protocol::Ip6(_) => { let (socket_addr, http_or_https) = parse_ip6(addr)?; let uri = format!("{http_or_https}://{socket_addr}"); - MyEndpoint::try_from_uri(uri, tls_config)? + MyEndpoint::try_from_uri(uri)? } unsupported => return Err(eyre!("unsupported protocol {unsupported}")), }; @@ -91,25 +77,21 @@ fn endpoint_from_multiaddr( struct MyEndpoint { endpoint: Endpoint, - tls_config: Option, } static DISABLE_CACHING_RESOLVER: OnceCell = OnceCell::new(); impl MyEndpoint { - fn new(endpoint: Endpoint, tls_config: Option) -> Self { - Self { - endpoint, - tls_config, - } + fn new(endpoint: Endpoint) -> Self { + Self { endpoint } } - fn try_from_uri(uri: String, tls_config: Option) -> Result { + fn try_from_uri(uri: String) -> Result { let uri: Uri = uri .parse() .with_context(|| format!("unable to create Uri from '{uri}'"))?; let endpoint = Endpoint::from(uri); - Ok(Self::new(endpoint, tls_config)) + Ok(Self::new(endpoint)) } fn apply_config(mut self, config: &Config) -> Self { @@ -125,17 +107,7 @@ impl MyEndpoint { }); if disable_caching_resolver { - if let Some(tls_config) = self.tls_config { - self.endpoint.connect_with_connector_lazy( - hyper_rustls::HttpsConnectorBuilder::new() - .with_tls_config(tls_config) - .https_only() - .enable_http2() - .build(), - ) - } else { - self.endpoint.connect_lazy() - } + self.endpoint.connect_lazy() } else { let mut http = HttpConnector::new_with_resolver(CachingResolver::new()); http.enforce_http(false); @@ -143,33 +115,12 @@ impl MyEndpoint { http.set_keepalive(None); http.set_connect_timeout(None); - if let Some(tls_config) = self.tls_config { - let https = hyper_rustls::HttpsConnectorBuilder::new() - .with_tls_config(tls_config) - .https_only() - .enable_http1() - .wrap_connector(http); - self.endpoint.connect_with_connector_lazy(https) - } else { - self.endpoint.connect_with_connector_lazy(http) - } + self.endpoint.connect_with_connector_lazy(http) } } async fn connect(self) -> Result { - if let Some(tls_config) = self.tls_config { - let https_connector = hyper_rustls::HttpsConnectorBuilder::new() - .with_tls_config(tls_config) - .https_only() - .enable_http2() - .build(); - self.endpoint - .connect_with_connector(https_connector) - .await - .map_err(Into::into) - } else { - self.endpoint.connect().await.map_err(Into::into) - } + self.endpoint.connect().await.map_err(Into::into) } } diff --git a/crates/mysten-network/src/config.rs b/crates/mysten-network/src/config.rs index eab88a024ec41..03ec4f589b96c 100644 --- a/crates/mysten-network/src/config.rs +++ b/crates/mysten-network/src/config.rs @@ -9,7 +9,6 @@ use crate::{ use eyre::Result; use serde::{Deserialize, Serialize}; use std::time::Duration; -use tokio_rustls::rustls::ClientConfig; use tonic::transport::Channel; #[derive(Debug, Default, Deserialize, Serialize)] @@ -91,19 +90,11 @@ impl Config { ServerBuilder::from_config(self, metrics_provider) } - pub async fn connect( - &self, - addr: &Multiaddr, - tls_config: Option, - ) -> Result { - connect_with_config(addr, tls_config, self).await + pub async fn connect(&self, addr: &Multiaddr) -> Result { + connect_with_config(addr, self).await } - pub fn connect_lazy( - &self, - addr: &Multiaddr, - tls_config: Option, - ) -> Result { - connect_lazy_with_config(addr, tls_config, self) + pub fn connect_lazy(&self, addr: &Multiaddr) -> Result { + connect_lazy_with_config(addr, self) } -} +} \ No newline at end of file diff --git a/crates/mysten-network/src/server.rs b/crates/mysten-network/src/server.rs index 8d3986c6fd205..4bac6fe61ae52 100644 --- a/crates/mysten-network/src/server.rs +++ b/crates/mysten-network/src/server.rs @@ -9,15 +9,11 @@ use crate::{ multiaddr::{parse_dns, parse_ip4, parse_ip6, Multiaddr, Protocol}, }; use eyre::{eyre, Result}; -use futures::{FutureExt, Stream}; -use std::pin::Pin; -use std::sync::Arc; +use futures::FutureExt; use std::task::{Context, Poll}; use std::{convert::Infallible, net::SocketAddr}; -use tokio::io::{AsyncRead, AsyncWrite}; -use tokio::net::{TcpListener, TcpStream, ToSocketAddrs}; -use tokio_rustls::rustls::ServerConfig; -use tokio_rustls::{server::TlsStream, TlsAcceptor}; +use tokio::net::{TcpListener, ToSocketAddrs}; +use tokio_stream::wrappers::TcpListenerStream; use tonic::codegen::http::HeaderValue; use tonic::{ body::BoxBody, @@ -39,7 +35,6 @@ use tower_http::classify::{GrpcErrorsAsFailures, SharedClassifier}; use tower_http::propagate_header::PropagateHeaderLayer; use tower_http::set_header::SetRequestHeaderLayer; use tower_http::trace::{DefaultMakeSpan, DefaultOnBodyChunk, DefaultOnEos, TraceLayer}; -use tracing::debug; pub struct ServerBuilder { router: Router>, @@ -160,48 +155,46 @@ impl ServerBuilder { self } - pub async fn bind(self, addr: &Multiaddr, tls_config: Option) -> Result { + pub async fn bind(self, addr: &Multiaddr) -> Result { let mut iter = addr.iter(); let (tx_cancellation, rx_cancellation) = tokio::sync::oneshot::channel(); let rx_cancellation = rx_cancellation.map(|_| ()); - let (local_addr, server): (Multiaddr, BoxFuture<(), tonic::transport::Error>) = match iter - .next() - .ok_or_else(|| eyre!("malformed addr"))? - { - Protocol::Dns(_) => { - let (dns_name, tcp_port, _http_or_https) = parse_dns(addr)?; - let (local_addr, incoming) = - listen_and_update_multiaddr(addr, (dns_name.to_string(), tcp_port), tls_config) - .await?; - let server = Box::pin( - self.router - .serve_with_incoming_shutdown(incoming, rx_cancellation), - ); - (local_addr, server) - } - Protocol::Ip4(_) => { - let (socket_addr, _http_or_https) = parse_ip4(addr)?; - let (local_addr, incoming) = - listen_and_update_multiaddr(addr, socket_addr, tls_config).await?; - let server = Box::pin( - self.router - .serve_with_incoming_shutdown(incoming, rx_cancellation), - ); - (local_addr, server) - } - Protocol::Ip6(_) => { - let (socket_addr, _http_or_https) = parse_ip6(addr)?; - let (local_addr, incoming) = - listen_and_update_multiaddr(addr, socket_addr, tls_config).await?; - let server = Box::pin( - self.router - .serve_with_incoming_shutdown(incoming, rx_cancellation), - ); - (local_addr, server) - } - unsupported => return Err(eyre!("unsupported protocol {unsupported}")), - }; + let (local_addr, server): (Multiaddr, BoxFuture<(), tonic::transport::Error>) = + match iter.next().ok_or_else(|| eyre!("malformed addr"))? { + Protocol::Dns(_) => { + let (dns_name, tcp_port, _http_or_https) = parse_dns(addr)?; + let (local_addr, incoming) = + tcp_listener_and_update_multiaddr(addr, (dns_name.as_ref(), tcp_port)) + .await?; + let server = Box::pin( + self.router + .serve_with_incoming_shutdown(incoming, rx_cancellation), + ); + (local_addr, server) + } + Protocol::Ip4(_) => { + let (socket_addr, _http_or_https) = parse_ip4(addr)?; + let (local_addr, incoming) = + tcp_listener_and_update_multiaddr(addr, socket_addr).await?; + let server = Box::pin( + self.router + .serve_with_incoming_shutdown(incoming, rx_cancellation), + ); + (local_addr, server) + } + Protocol::Ip6(_) => { + let (socket_addr, _http_or_https) = parse_ip6(addr)?; + let (local_addr, incoming) = + tcp_listener_and_update_multiaddr(addr, socket_addr).await?; + let server = Box::pin( + self.router + .serve_with_incoming_shutdown(incoming, rx_cancellation), + ); + (local_addr, server) + } + unsupported => return Err(eyre!("unsupported protocol {unsupported}")), + }; Ok(Server { server, @@ -212,134 +205,22 @@ impl ServerBuilder { } } -async fn listen_and_update_multiaddr( +async fn tcp_listener_and_update_multiaddr( address: &Multiaddr, socket_addr: T, - tls_config: Option, -) -> Result<( - Multiaddr, - impl Stream>, -)> { - let listener = TcpListener::bind(socket_addr).await?; - let local_addr = listener.local_addr()?; +) -> Result<(Multiaddr, TcpListenerStream)> { + let (local_addr, incoming) = tcp_listener(socket_addr).await?; let local_addr = update_tcp_port_in_multiaddr(address, local_addr.port()); - - let tls_acceptor = tls_config.map(|tls_config| TlsAcceptor::from(Arc::new(tls_config))); - let incoming = TcpOrTlsListener::new(listener, tls_acceptor); - let stream = async_stream::stream! { - loop { - yield incoming.accept().await; - } - }; - - Ok((local_addr, stream)) -} - -pub struct TcpOrTlsListener { - listener: TcpListener, - tls_acceptor: Option, -} - -impl TcpOrTlsListener { - fn new(listener: TcpListener, tls_acceptor: Option) -> Self { - Self { - listener, - tls_acceptor, - } - } - - async fn accept(&self) -> std::io::Result { - let (stream, addr) = self.listener.accept().await?; - if self.tls_acceptor.is_none() { - return Ok(TcpOrTlsStream::Tcp(stream, addr)); - } - - // Determine whether new connection is TLS. - let mut buf = [0; 1]; - stream.peek(&mut buf).await?; - if buf[0] == 0x16 { - // First byte of a TLS handshake is 0x16. - debug!("accepting TLS connection from {addr:?}"); - let stream = self.tls_acceptor.as_ref().unwrap().accept(stream).await?; - Ok(TcpOrTlsStream::Tls(stream, addr)) - } else { - debug!("accepting TCP connection from {addr:?}"); - Ok(TcpOrTlsStream::Tcp(stream, addr)) - } - } + Ok((local_addr, incoming)) } -pub enum TcpOrTlsStream { - Tcp(TcpStream, SocketAddr), - Tls(TlsStream, SocketAddr), -} - -impl AsyncRead for TcpOrTlsStream { - fn poll_read( - self: Pin<&mut Self>, - cx: &mut Context<'_>, - buf: &mut tokio::io::ReadBuf, - ) -> Poll> { - match self.get_mut() { - TcpOrTlsStream::Tcp(stream, _) => Pin::new(stream).poll_read(cx, buf), - TcpOrTlsStream::Tls(stream, _) => Pin::new(stream).poll_read(cx, buf), - } - } -} - -impl AsyncWrite for TcpOrTlsStream { - fn poll_write( - self: Pin<&mut Self>, - cx: &mut Context<'_>, - buf: &[u8], - ) -> Poll> { - match self.get_mut() { - TcpOrTlsStream::Tcp(stream, _) => Pin::new(stream).poll_write(cx, buf), - TcpOrTlsStream::Tls(stream, _) => Pin::new(stream).poll_write(cx, buf), - } - } - - fn poll_flush( - self: Pin<&mut Self>, - cx: &mut Context<'_>, - ) -> Poll> { - match self.get_mut() { - TcpOrTlsStream::Tcp(stream, _) => Pin::new(stream).poll_flush(cx), - TcpOrTlsStream::Tls(stream, _) => Pin::new(stream).poll_flush(cx), - } - } - - fn poll_shutdown( - self: Pin<&mut Self>, - cx: &mut Context<'_>, - ) -> Poll> { - match self.get_mut() { - TcpOrTlsStream::Tcp(stream, _) => Pin::new(stream).poll_shutdown(cx), - TcpOrTlsStream::Tls(stream, _) => Pin::new(stream).poll_shutdown(cx), - } - } -} - -impl tonic::transport::server::Connected for TcpOrTlsStream { - type ConnectInfo = tonic::transport::server::TcpConnectInfo; - - fn connect_info(&self) -> Self::ConnectInfo { - match self { - TcpOrTlsStream::Tcp(stream, addr) => Self::ConnectInfo { - local_addr: stream.local_addr().ok(), - remote_addr: Some(*addr), - }, - TcpOrTlsStream::Tls(stream, addr) => Self::ConnectInfo { - local_addr: stream.get_ref().0.local_addr().ok(), - remote_addr: Some(*addr), - }, - } - } +async fn tcp_listener(address: T) -> Result<(SocketAddr, TcpListenerStream)> { + let listener = TcpListener::bind(address).await?; + let local_addr = listener.local_addr()?; + let incoming = TcpListenerStream::new(listener); + Ok((local_addr, incoming)) } -/// TLS server name to use for the public Sui validator interface. -pub const SUI_TLS_SERVER_NAME: &str = "sui"; - pub struct Server { server: BoxFuture<(), tonic::transport::Error>, cancel_handle: Option>, @@ -437,14 +318,14 @@ mod test { let mut server = config .server_builder_with_metrics(metrics.clone()) - .bind(&address, None) + .bind(&address) .await .unwrap(); let address = server.local_addr().to_owned(); let cancel_handle = server.take_cancel_handle().unwrap(); let server_handle = tokio::spawn(server.serve()); - let channel = config.connect(&address, None).await.unwrap(); + let channel = config.connect(&address).await.unwrap(); let mut client = HealthClient::new(channel); client @@ -500,14 +381,14 @@ mod test { let mut server = config .server_builder_with_metrics(metrics.clone()) - .bind(&address, None) + .bind(&address) .await .unwrap(); let address = server.local_addr().to_owned(); let cancel_handle = server.take_cancel_handle().unwrap(); let server_handle = tokio::spawn(server.serve()); - let channel = config.connect(&address, None).await.unwrap(); + let channel = config.connect(&address).await.unwrap(); let mut client = HealthClient::new(channel); // Call the healthcheck for a service that doesn't exist @@ -527,11 +408,11 @@ mod test { async fn test_multiaddr(address: Multiaddr) { let config = Config::new(); - let mut server = config.server_builder().bind(&address, None).await.unwrap(); + let mut server = config.server_builder().bind(&address).await.unwrap(); let address = server.local_addr().to_owned(); let cancel_handle = server.take_cancel_handle().unwrap(); let server_handle = tokio::spawn(server.serve()); - let channel = config.connect(&address, None).await.unwrap(); + let channel = config.connect(&address).await.unwrap(); let mut client = HealthClient::new(channel); client diff --git a/crates/sui-cluster-test/Cargo.toml b/crates/sui-cluster-test/Cargo.toml index 93bf428007108..8482c6c4d6f48 100644 --- a/crates/sui-cluster-test/Cargo.toml +++ b/crates/sui-cluster-test/Cargo.toml @@ -22,7 +22,7 @@ uuid.workspace = true prometheus.workspace = true fastcrypto.workspace = true shared-crypto.workspace = true -derivative.workspace = true +derive_more = { workspace = true, features = ["debug"] } regex.workspace = true sui-indexer.workspace = true diff --git a/crates/sui-cluster-test/src/config.rs b/crates/sui-cluster-test/src/config.rs index 9df8facf131d3..a8a4d91e3afd2 100644 --- a/crates/sui-cluster-test/src/config.rs +++ b/crates/sui-cluster-test/src/config.rs @@ -3,7 +3,7 @@ use clap::*; use regex::Regex; -use std::{fmt, path::PathBuf}; +use std::path::PathBuf; #[derive(Parser, Clone, ValueEnum, Debug)] pub enum Env { @@ -16,8 +16,7 @@ pub enum Env { NewLocal, } -#[derive(derivative::Derivative, Parser)] -#[derivative(Debug)] +#[derive(derive_more::Debug, Parser)] #[clap(name = "", rename_all = "kebab-case")] pub struct ClusterTestOpt { #[clap(value_enum)] @@ -33,7 +32,12 @@ pub struct ClusterTestOpt { pub indexer_address: Option, /// URL for the Indexer Postgres DB #[clap(long)] - #[derivative(Debug(format_with = "obfuscated_pg_address"))] + #[debug("{}", match pg_address { + None => "None".into(), + Some(val) => Regex::new(r":.*@") + .unwrap() + .replace_all(val.as_str(), ":*****@"), + })] pub pg_address: Option, #[clap(long)] pub config_dir: Option, @@ -47,21 +51,6 @@ pub struct ClusterTestOpt { pub with_indexer_and_graphql: bool, } -fn obfuscated_pg_address(val: &Option, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match val { - None => write!(f, "None"), - Some(val) => { - write!( - f, - "{}", - Regex::new(r":.*@") - .unwrap() - .replace_all(val.as_str(), ":*****@") - ) - } - } -} - impl ClusterTestOpt { pub fn new_local() -> Self { Self { diff --git a/crates/sui-core/src/authority_client.rs b/crates/sui-core/src/authority_client.rs index 9537dec300c71..37ccd6fa1b303 100644 --- a/crates/sui-core/src/authority_client.rs +++ b/crates/sui-core/src/authority_client.rs @@ -11,7 +11,6 @@ use std::time::Duration; use sui_network::{api::ValidatorClient, tonic}; use sui_types::base_types::AuthorityName; use sui_types::committee::CommitteeWithNetworkMetadata; -use sui_types::crypto::NetworkPublicKey; use sui_types::messages_checkpoint::{ CheckpointRequest, CheckpointRequestV2, CheckpointResponse, CheckpointResponseV2, }; @@ -98,32 +97,15 @@ pub struct NetworkAuthorityClient { } impl NetworkAuthorityClient { - pub async fn connect( - address: &Multiaddr, - tls_target: Option, - ) -> anyhow::Result { - let tls_config = tls_target.map(|tls_target| { - sui_tls::create_rustls_client_config( - tls_target, - sui_tls::SUI_VALIDATOR_SERVER_NAME.to_string(), - None, - ) - }); - let channel = mysten_network::client::connect(address, tls_config) + pub async fn connect(address: &Multiaddr) -> anyhow::Result { + let channel = mysten_network::client::connect(address) .await .map_err(|err| anyhow!(err.to_string()))?; Ok(Self::new(channel)) } - pub fn connect_lazy(address: &Multiaddr, tls_target: Option) -> Self { - let tls_config = tls_target.map(|tls_target| { - sui_tls::create_rustls_client_config( - tls_target, - sui_tls::SUI_VALIDATOR_SERVER_NAME.to_string(), - None, - ) - }); - let client: SuiResult<_> = mysten_network::client::connect_lazy(address, tls_config) + pub fn connect_lazy(address: &Multiaddr) -> Self { + let client: SuiResult<_> = mysten_network::client::connect_lazy(address) .map(ValidatorClient::new) .map_err(|err| err.to_string().into()); Self { client } @@ -283,16 +265,7 @@ pub fn make_network_authority_clients_with_network_config( for (name, (_state, network_metadata)) in committee.validators() { let address = network_metadata.network_address.clone(); let address = address.rewrite_udp_to_tcp(); - // TODO: Enable TLS on this interface with below config, once support is rolled out to validators. - // let tls_config = network_metadata.network_public_key.as_ref().map(|key| { - // sui_tls::create_rustls_client_config( - // key.clone(), - // sui_tls::SUI_VALIDATOR_SERVER_NAME.to_string(), - // None, - // ) - // }); - // TODO: Change below code to generate a SuiError if no valid TLS config is available. - let maybe_channel = network_config.connect_lazy(&address, None).map_err(|e| { + let maybe_channel = network_config.connect_lazy(&address).map_err(|e| { tracing::error!( address = %address, name = %name, @@ -332,4 +305,4 @@ fn insert_metadata(request: &mut tonic::Request, client_addr: Option Result { - let tls_config = sui_tls::create_rustls_server_config( - self.state.config.network_key_pair().copy().private(), - SUI_TLS_SERVER_NAME.to_string(), - sui_tls::AllowAll, - ); let mut server = mysten_network::config::Config::new() .server_builder() .add_service(ValidatorServer::new(ValidatorService::new_for_tests( @@ -163,7 +156,7 @@ impl AuthorityServer { self.consensus_adapter, self.metrics, ))) - .bind(&address, Some(tls_config)) + .bind(&address) .await .unwrap(); let local_addr = server.local_addr().to_owned(); diff --git a/crates/sui-core/src/unit_tests/consensus_tests.rs b/crates/sui-core/src/unit_tests/consensus_tests.rs index 47f4c404c85b2..0b79fa069c830 100644 --- a/crates/sui-core/src/unit_tests/consensus_tests.rs +++ b/crates/sui-core/src/unit_tests/consensus_tests.rs @@ -9,13 +9,18 @@ use crate::checkpoints::CheckpointServiceNoop; use crate::consensus_handler::SequencedConsensusTransaction; use fastcrypto::traits::KeyPair; use move_core_types::{account_address::AccountAddress, ident_str}; +use narwhal_types::Transactions; +use narwhal_types::TransactionsServer; +use narwhal_types::{Empty, TransactionProto}; use rand::rngs::StdRng; use rand::SeedableRng; +use sui_network::tonic; use sui_types::crypto::{deterministic_random_account_key, AccountKeyPair}; use sui_types::gas::GasCostSummary; use sui_types::messages_checkpoint::{ CheckpointContents, CheckpointSignatureMessage, CheckpointSummary, SignedCheckpointSummary, }; +use sui_types::multiaddr::Multiaddr; use sui_types::transaction::TEST_ONLY_GAS_UNIT_FOR_OBJECT_BASICS; use sui_types::utils::{make_committee_key, to_sender_signed_transaction}; use sui_types::SUI_FRAMEWORK_PACKAGE_ID; @@ -24,6 +29,8 @@ use sui_types::{ object::Object, transaction::{CallArg, CertifiedTransaction, ObjectArg, TransactionData, VerifiedTransaction}, }; +use tokio::sync::mpsc::channel; +use tokio::sync::mpsc::{Receiver, Sender}; /// Fixture: a few test gas objects. pub fn test_gas_objects() -> Vec { @@ -403,3 +410,45 @@ async fn submit_checkpoint_signature_to_consensus_adapter() { .unwrap(); waiter.await.unwrap(); } + +pub struct ConsensusMockServer { + sender: Sender, +} + +impl ConsensusMockServer { + pub fn spawn(address: Multiaddr) -> Receiver { + let (sender, receiver) = channel(1); + tokio::spawn(async move { + let config = mysten_network::config::Config::new(); + let mock = Self { sender }; + config + .server_builder() + .add_service(TransactionsServer::new(mock)) + .bind(&address) + .await + .unwrap() + .serve() + .await + }); + receiver + } +} + +#[tonic::async_trait] +impl Transactions for ConsensusMockServer { + /// Submit a Transactions + async fn submit_transaction( + &self, + request: tonic::Request, + ) -> Result, tonic::Status> { + self.sender.send(request.into_inner()).await.unwrap(); + Ok(tonic::Response::new(Empty {})) + } + /// Submit a Transactions + async fn submit_transaction_stream( + &self, + _request: tonic::Request>, + ) -> Result, tonic::Status> { + unimplemented!() + } +} diff --git a/crates/sui-e2e-tests/tests/rest/execute.rs b/crates/sui-e2e-tests/tests/rest/execute.rs index 629801f4f36c5..ff408edee6549 100644 --- a/crates/sui-e2e-tests/tests/rest/execute.rs +++ b/crates/sui-e2e-tests/tests/rest/execute.rs @@ -1,22 +1,10 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -use shared_crypto::intent::Intent; -use sui_keys::keystore::AccountKeystore; use sui_macros::sim_test; -use sui_rest_api::client::reqwest::StatusCode; use sui_rest_api::client::BalanceChange; -use sui_rest_api::transactions::ResolveTransactionQueryParameters; use sui_rest_api::Client; use sui_rest_api::ExecuteTransactionQueryParameters; -use sui_sdk_types::types::Argument; -use sui_sdk_types::types::Command; -use sui_sdk_types::types::TransactionExpiration; -use sui_sdk_types::types::UnresolvedGasPayment; -use sui_sdk_types::types::UnresolvedInputArgument; -use sui_sdk_types::types::UnresolvedProgrammableTransaction; -use sui_sdk_types::types::UnresolvedTransaction; -use sui_sdk_types::types::UnresolvedValue; use sui_test_transaction_builder::make_transfer_sui_transaction; use sui_types::base_types::SuiAddress; use sui_types::effects::TransactionEffectsAPI; @@ -65,419 +53,3 @@ async fn execute_transaction_transfer() { assert_eq!(actual, expected); } - -#[sim_test] -async fn resolve_transaction_simple_transfer() { - let test_cluster = TestClusterBuilder::new().build().await; - - let client = Client::new(test_cluster.rpc_url()); - let recipient = SuiAddress::random_for_testing_only(); - - let (sender, mut gas) = test_cluster.wallet.get_one_account().await.unwrap(); - gas.sort_by_key(|object_ref| object_ref.0); - let obj_to_send = gas.first().unwrap().0; - - let unresolved_transaction = UnresolvedTransaction { - ptb: UnresolvedProgrammableTransaction { - inputs: vec![ - UnresolvedInputArgument { - object_id: Some(obj_to_send.into()), - ..Default::default() - }, - UnresolvedInputArgument { - value: Some(UnresolvedValue::String(recipient.to_string())), - ..Default::default() - }, - ], - commands: vec![Command::TransferObjects( - sui_sdk_types::types::TransferObjects { - objects: vec![Argument::Input(0)], - address: Argument::Input(1), - }, - )], - }, - sender: sender.into(), - gas_payment: None, - expiration: TransactionExpiration::None, - }; - - let resolved = client - .inner() - .resolve_transaction_with_parameters( - &unresolved_transaction, - &ResolveTransactionQueryParameters { - simulate: true, - ..Default::default() - }, - ) - .await - .unwrap() - .into_inner(); - - let signed_transaction = test_cluster - .wallet - .sign_transaction(&resolved.transaction.try_into().unwrap()); - let effects = client - .execute_transaction( - &ExecuteTransactionQueryParameters::default(), - &signed_transaction, - ) - .await - .unwrap() - .effects; - - assert!(effects.status().is_ok()); - assert_eq!( - resolved.simulation.unwrap().effects, - effects.try_into().unwrap() - ); -} - -#[sim_test] -async fn resolve_transaction_transfer_with_sponsor() { - let test_cluster = TestClusterBuilder::new().build().await; - - let client = Client::new(test_cluster.rpc_url()); - let recipient = SuiAddress::random_for_testing_only(); - - let (sender, gas) = test_cluster.wallet.get_one_account().await.unwrap(); - let obj_to_send = gas.first().unwrap().0; - let sponsor = test_cluster.wallet.get_addresses()[1]; - - let unresolved_transaction = UnresolvedTransaction { - ptb: UnresolvedProgrammableTransaction { - inputs: vec![ - UnresolvedInputArgument { - object_id: Some(obj_to_send.into()), - ..Default::default() - }, - UnresolvedInputArgument { - value: Some(UnresolvedValue::String(recipient.to_string())), - ..Default::default() - }, - ], - commands: vec![Command::TransferObjects( - sui_sdk_types::types::TransferObjects { - objects: vec![Argument::Input(0)], - address: Argument::Input(1), - }, - )], - }, - sender: sender.into(), - gas_payment: Some(UnresolvedGasPayment { - objects: vec![], - owner: sponsor.into(), - price: None, - budget: None, - }), - expiration: TransactionExpiration::None, - }; - - let resolved = client - .inner() - .resolve_transaction_with_parameters( - &unresolved_transaction, - &ResolveTransactionQueryParameters { - simulate: true, - ..Default::default() - }, - ) - .await - .unwrap() - .into_inner(); - - let transaction_data = resolved.transaction.clone().try_into().unwrap(); - let sender_sig = test_cluster - .wallet - .config - .keystore - .sign_secure(&sender, &transaction_data, Intent::sui_transaction()) - .unwrap(); - let sponsor_sig = test_cluster - .wallet - .config - .keystore - .sign_secure(&sponsor, &transaction_data, Intent::sui_transaction()) - .unwrap(); - - let signed_transaction = sui_types::transaction::Transaction::from_data( - transaction_data, - vec![sender_sig, sponsor_sig], - ); - let effects = client - .execute_transaction( - &ExecuteTransactionQueryParameters::default(), - &signed_transaction, - ) - .await - .unwrap() - .effects; - - assert!(effects.status().is_ok()); - assert_eq!( - resolved.simulation.unwrap().effects, - effects.try_into().unwrap() - ); -} - -#[sim_test] -async fn resolve_transaction_borrowed_shared_object() { - let test_cluster = TestClusterBuilder::new().build().await; - - let client = Client::new(test_cluster.rpc_url()); - - let sender = test_cluster.wallet.get_addresses()[0]; - - let unresolved_transaction = UnresolvedTransaction { - ptb: UnresolvedProgrammableTransaction { - inputs: vec![UnresolvedInputArgument { - object_id: Some("0x6".parse().unwrap()), - ..Default::default() - }], - commands: vec![Command::MoveCall(sui_sdk_types::types::MoveCall { - package: "0x2".parse().unwrap(), - module: "clock".parse().unwrap(), - function: "timestamp_ms".parse().unwrap(), - type_arguments: vec![], - arguments: vec![Argument::Input(0)], - })], - }, - sender: sender.into(), - gas_payment: None, - expiration: TransactionExpiration::None, - }; - - let resolved = client - .inner() - .resolve_transaction_with_parameters( - &unresolved_transaction, - &ResolveTransactionQueryParameters { - simulate: true, - ..Default::default() - }, - ) - .await - .unwrap() - .into_inner(); - - let signed_transaction = test_cluster - .wallet - .sign_transaction(&resolved.transaction.try_into().unwrap()); - let effects = client - .execute_transaction( - &ExecuteTransactionQueryParameters::default(), - &signed_transaction, - ) - .await - .unwrap() - .effects; - - assert!(effects.status().is_ok()); -} - -#[sim_test] -async fn resolve_transaction_mutable_shared_object() { - let test_cluster = TestClusterBuilder::new().build().await; - - let client = Client::new(test_cluster.rpc_url()); - - let (sender, mut gas) = test_cluster.wallet.get_one_account().await.unwrap(); - gas.sort_by_key(|object_ref| object_ref.0); - let obj_to_stake = gas.first().unwrap().0; - let validator_address = client - .inner() - .get_system_state_summary() - .await - .unwrap() - .inner() - .active_validators - .first() - .unwrap() - .address; - - let unresolved_transaction = UnresolvedTransaction { - ptb: UnresolvedProgrammableTransaction { - inputs: vec![ - UnresolvedInputArgument { - object_id: Some("0x5".parse().unwrap()), - ..Default::default() - }, - UnresolvedInputArgument { - object_id: Some(obj_to_stake.into()), - ..Default::default() - }, - UnresolvedInputArgument { - value: Some(UnresolvedValue::String(validator_address.to_string())), - ..Default::default() - }, - ], - commands: vec![Command::MoveCall(sui_sdk_types::types::MoveCall { - package: "0x3".parse().unwrap(), - module: "sui_system".parse().unwrap(), - function: "request_add_stake".parse().unwrap(), - type_arguments: vec![], - arguments: vec![Argument::Input(0), Argument::Input(1), Argument::Input(2)], - })], - }, - sender: sender.into(), - gas_payment: None, - expiration: TransactionExpiration::None, - }; - - let resolved = client - .inner() - .resolve_transaction_with_parameters( - &unresolved_transaction, - &ResolveTransactionQueryParameters { - simulate: true, - ..Default::default() - }, - ) - .await - .unwrap() - .into_inner(); - - let signed_transaction = test_cluster - .wallet - .sign_transaction(&resolved.transaction.try_into().unwrap()); - let effects = client - .execute_transaction( - &ExecuteTransactionQueryParameters::default(), - &signed_transaction, - ) - .await - .unwrap() - .effects; - - assert!(effects.status().is_ok()); - assert_eq!( - resolved.simulation.unwrap().effects, - effects.try_into().unwrap() - ); -} - -#[sim_test] -async fn resolve_transaction_insufficient_gas() { - let test_cluster = TestClusterBuilder::new().build().await; - let client = Client::new(test_cluster.rpc_url()); - - // Test the case where we don't have enough coins/gas for the required budget - let unresolved_transaction = UnresolvedTransaction { - ptb: UnresolvedProgrammableTransaction { - inputs: vec![UnresolvedInputArgument { - object_id: Some("0x6".parse().unwrap()), - ..Default::default() - }], - commands: vec![Command::MoveCall(sui_sdk_types::types::MoveCall { - package: "0x2".parse().unwrap(), - module: "clock".parse().unwrap(), - function: "timestamp_ms".parse().unwrap(), - type_arguments: vec![], - arguments: vec![Argument::Input(0)], - })], - }, - sender: SuiAddress::random_for_testing_only().into(), // random account with no gas - gas_payment: None, - expiration: TransactionExpiration::None, - }; - - let error = client - .inner() - .resolve_transaction(&unresolved_transaction) - .await - .unwrap_err(); - - assert_eq!(error.status(), Some(StatusCode::BAD_REQUEST)); - assert_contains( - error.message().unwrap_or_default(), - "unable to select sufficient gas", - ); -} - -fn assert_contains(haystack: &str, needle: &str) { - if !haystack.contains(needle) { - panic!("{haystack:?} does not contain {needle:?}"); - } -} - -#[sim_test] -async fn resolve_transaction_with_raw_json() { - let test_cluster = TestClusterBuilder::new().build().await; - - let client = Client::new(test_cluster.rpc_url()); - let recipient = SuiAddress::random_for_testing_only(); - - let (sender, mut gas) = test_cluster.wallet.get_one_account().await.unwrap(); - gas.sort_by_key(|object_ref| object_ref.0); - let obj_to_send = gas.first().unwrap().0; - - let unresolved_transaction = serde_json::json!({ - "inputs": [ - { - "object_id": obj_to_send - }, - { - "value": 1 - }, - { - "value": recipient - } - ], - - "commands": [ - { - "command": "split_coins", - "coin": { "input": 0 }, - "amounts": [ - { - "input": 1, - }, - { - "input": 1, - } - ] - }, - { - "command": "transfer_objects", - "objects": [ - { "result": [0, 1] }, - { "result": [0, 0] } - ], - "address": { "input": 2 } - } - ], - - "sender": sender - }); - - let resolved = client - .inner() - .resolve_transaction_with_parameters( - &serde_json::from_value(unresolved_transaction).unwrap(), - &ResolveTransactionQueryParameters { - simulate: true, - ..Default::default() - }, - ) - .await - .unwrap() - .into_inner(); - - let signed_transaction = test_cluster - .wallet - .sign_transaction(&resolved.transaction.try_into().unwrap()); - let effects = client - .execute_transaction( - &ExecuteTransactionQueryParameters::default(), - &signed_transaction, - ) - .await - .unwrap() - .effects; - - assert!(effects.status().is_ok(), "{:?}", effects.status()); - assert_eq!( - resolved.simulation.unwrap().effects, - effects.try_into().unwrap() - ); -} diff --git a/crates/sui-e2e-tests/tests/traffic_control_tests.rs b/crates/sui-e2e-tests/tests/traffic_control_tests.rs index 27985b8b1d589..85ce468fba0e7 100644 --- a/crates/sui-e2e-tests/tests/traffic_control_tests.rs +++ b/crates/sui-e2e-tests/tests/traffic_control_tests.rs @@ -665,6 +665,63 @@ async fn test_fullnode_traffic_control_error_blocked() -> Result<(), anyhow::Err panic!("Expected spam policy to trigger within {txn_count} requests"); } +#[tokio::test] +async fn test_fullnode_traffic_control_error_blocked() -> Result<(), anyhow::Error> { + let txn_count = 5; + let policy_config = PolicyConfig { + connection_blocklist_ttl_sec: 3, + error_policy_type: PolicyType::TestNConnIP(txn_count - 1), + dry_run: false, + ..Default::default() + }; + let test_cluster = TestClusterBuilder::new() + .with_fullnode_policy_config(Some(policy_config)) + .build() + .await; + + let jsonrpc_client = &test_cluster.fullnode_handle.rpc_client; + let context = test_cluster.wallet; + + let mut txns = batch_make_transfer_transactions(&context, txn_count as usize).await; + assert!( + txns.len() >= txn_count as usize, + "Expect at least {} txns. Do we generate enough gas objects during genesis?", + txn_count, + ); + + // it should take no more than 4 requests to be added to the blocklist + for _ in 0..txn_count { + let txn = txns.swap_remove(0); + let tx_digest = txn.digest(); + let (tx_bytes, _signatures) = txn.to_tx_bytes_and_signatures(); + // create invalid (empty) client signature + let signatures: Vec = vec![]; + let params = rpc_params![ + tx_bytes, + signatures, + SuiTransactionBlockResponseOptions::new(), + ExecuteTransactionRequestType::WaitForLocalExecution + ]; + let response: RpcResult = jsonrpc_client + .request("sui_executeTransactionBlock", params.clone()) + .await; + if let Err(err) = response { + if err.to_string().contains("Too many requests") { + return Ok(()); + } + } else { + let SuiTransactionBlockResponse { + digest, + confirmed_local_execution, + .. + } = response.unwrap(); + assert_eq!(&digest, tx_digest); + assert!(confirmed_local_execution.unwrap()); + } + } + panic!("Expected spam policy to trigger within {txn_count} requests"); +} + #[tokio::test] async fn test_validator_traffic_control_error_delegated() -> Result<(), anyhow::Error> { let n = 5; diff --git a/crates/sui-graphql-rpc/src/types/balance.rs b/crates/sui-graphql-rpc/src/types/balance.rs index d4744a850534d..9823db1dcca7f 100644 --- a/crates/sui-graphql-rpc/src/types/balance.rs +++ b/crates/sui-graphql-rpc/src/types/balance.rs @@ -270,7 +270,7 @@ fn balance_query( /// Applies the filtering criteria for balances to the input `RawQuery` and returns a new /// `RawQuery`. fn filter(mut query: RawQuery, owner: SuiAddress, coin_type: Option) -> RawQuery { - query = filter!(query, "coin_type IS NOT NULL"); + query = filter!(query, "coin_type IS NOT NULL AND object_status = 0"); query = filter!( query, diff --git a/crates/sui-graphql-rpc/src/types/coin.rs b/crates/sui-graphql-rpc/src/types/coin.rs index f911256f477f4..e572d8e703cc8 100644 --- a/crates/sui-graphql-rpc/src/types/coin.rs +++ b/crates/sui-graphql-rpc/src/types/coin.rs @@ -435,7 +435,7 @@ fn apply_filter(mut query: RawQuery, coin_type: &TypeTag, owner: Option= stake.activation_epoch() { + // TODO: use dev_inspect to call a move function to get the estimated reward let estimated_reward = if let Some(current_rate) = current_rate { let stake_rate = rate_table .rates @@ -431,7 +432,8 @@ async fn exchange_rates( }) .collect::, _>>()?; - rates.sort_by(|(a, _), (b, _)| a.cmp(b).reverse()); + // Rates for some epochs might be missing due to safe mode, we need to backfill them. + rates = backfill_rates(rates); exchange_rates.push(ValidatorExchangeRates { address, @@ -451,6 +453,38 @@ pub struct ValidatorExchangeRates { pub rates: Vec<(EpochId, PoolTokenExchangeRate)>, } +/// Backfill missing rates for some epochs due to safe mode. If a rate is missing for epoch e, +/// we will use the rate for epoch e-1 to fill it. +/// Rates returned are in descending order by epoch. +fn backfill_rates( + rates: Vec<(EpochId, PoolTokenExchangeRate)>, +) -> Vec<(EpochId, PoolTokenExchangeRate)> { + if rates.is_empty() { + return rates; + } + + let min_epoch = *rates.iter().map(|(e, _)| e).min().unwrap(); + let max_epoch = *rates.iter().map(|(e, _)| e).max().unwrap(); + let mut filled_rates = Vec::new(); + let mut prev_rate = None; + + for epoch in min_epoch..=max_epoch { + match rates.iter().find(|(e, _)| *e == epoch) { + Some((e, rate)) => { + prev_rate = Some(rate.clone()); + filled_rates.push((*e, rate.clone())); + } + None => { + if let Some(rate) = prev_rate.clone() { + filled_rates.push((epoch, rate)); + } + } + } + } + filled_rates.reverse(); + filled_rates +} + impl SuiRpcModule for GovernanceReadApi { fn rpc(self) -> RpcModule { self.into_rpc() @@ -460,3 +494,44 @@ impl SuiRpcModule for GovernanceReadApi { GovernanceReadApiOpenRpc::module_doc() } } + +#[cfg(test)] +mod tests { + use super::*; + use sui_types::sui_system_state::PoolTokenExchangeRate; + + #[test] + fn test_backfill_rates_empty() { + let rates = vec![]; + assert_eq!(backfill_rates(rates), vec![]); + } + + #[test] + fn test_backfill_rates_no_gaps() { + let rate1 = PoolTokenExchangeRate::new(100, 100); + let rate2 = PoolTokenExchangeRate::new(200, 220); + let rate3 = PoolTokenExchangeRate::new(300, 330); + let rates = vec![(2, rate2.clone()), (3, rate3.clone()), (1, rate1.clone())]; + + let expected: Vec<(u64, PoolTokenExchangeRate)> = + vec![(3, rate3.clone()), (2, rate2), (1, rate1)]; + assert_eq!(backfill_rates(rates), expected); + } + + #[test] + fn test_backfill_rates_with_gaps() { + let rate1 = PoolTokenExchangeRate::new(100, 100); + let rate3 = PoolTokenExchangeRate::new(300, 330); + let rate5 = PoolTokenExchangeRate::new(500, 550); + let rates = vec![(3, rate3.clone()), (1, rate1.clone()), (5, rate5.clone())]; + + let expected = vec![ + (5, rate5.clone()), + (4, rate3.clone()), + (3, rate3.clone()), + (2, rate1.clone()), + (1, rate1), + ]; + assert_eq!(backfill_rates(rates), expected); + } +} diff --git a/crates/sui-mvr-indexer/migrations/pg/2023-08-19-044020_events/down.sql b/crates/sui-mvr-indexer/migrations/pg/2023-08-19-044020_events/down.sql index 57f1de973b1d2..ddb05ac2ebe8b 100644 --- a/crates/sui-mvr-indexer/migrations/pg/2023-08-19-044020_events/down.sql +++ b/crates/sui-mvr-indexer/migrations/pg/2023-08-19-044020_events/down.sql @@ -1,2 +1,2 @@ -- This file should undo anything in `up.sql` -DROP TABLE IF EXISTS chain_identifier; +DROP TABLE IF EXISTS epochs; diff --git a/crates/sui-mvr-indexer/migrations/pg/2023-08-19-044052_epochs/down.sql b/crates/sui-mvr-indexer/migrations/pg/2023-08-19-044052_epochs/down.sql index ddb05ac2ebe8b..99e1a8b702711 100644 --- a/crates/sui-mvr-indexer/migrations/pg/2023-08-19-044052_epochs/down.sql +++ b/crates/sui-mvr-indexer/migrations/pg/2023-08-19-044052_epochs/down.sql @@ -1,2 +1,6 @@ -- This file should undo anything in `up.sql` +<<<<<<<< HEAD:crates/sui-indexer/migrations/pg/2024-07-13-003534_chain_identifier/down.sql +DROP TABLE IF EXISTS chain_identifier; +======== DROP TABLE IF EXISTS epochs; +>>>>>>>> testnet-v1.37.3:crates/sui-mvr-indexer/migrations/pg/2023-08-19-044052_epochs/down.sql diff --git a/crates/sui-node/src/lib.rs b/crates/sui-node/src/lib.rs index 9fd3db906fd60..3af860ad5d9a1 100644 --- a/crates/sui-node/src/lib.rs +++ b/crates/sui-node/src/lib.rs @@ -13,7 +13,6 @@ use arc_swap::ArcSwap; use fastcrypto_zkp::bn254::zk_login::JwkId; use fastcrypto_zkp::bn254::zk_login::OIDCProvider; use futures::TryFutureExt; -use mysten_network::server::SUI_TLS_SERVER_NAME; use prometheus::Registry; use std::collections::{BTreeSet, HashMap, HashSet}; use std::fmt; @@ -184,9 +183,9 @@ mod simulator { } type JwkInjector = dyn Fn(AuthorityName, &OIDCProvider) -> SuiResult> - + Send - + Sync - + 'static; + + Send + + Sync + + 'static; fn default_fetch_jwks( _authority: AuthorityName, @@ -198,7 +197,7 @@ mod simulator { sui_types::zk_login_util::DEFAULT_JWK_BYTES, &OIDCProvider::Twitch, ) - .map_err(|_| SuiError::JWKRetrievalError) + .map_err(|_| SuiError::JWKRetrievalError) } thread_local! { @@ -641,7 +640,7 @@ impl SuiNode { &trusted_peer_change_tx, epoch_store.epoch_start_state(), ) - .expect("Initial trusted peers must be set"); + .expect("Initial trusted peers must be set"); info!("start state archival"); // Start archiving local state to remote store @@ -702,7 +701,7 @@ impl SuiNode { archive_readers, validator_tx_finalizer, ) - .await; + .await; // ensure genesis txn was executed if epoch_store.epoch() == 0 { let txn = &genesis.transaction(); @@ -737,7 +736,7 @@ impl SuiNode { state.get_accumulator_store().as_ref(), indexes, ) - .expect("secondary indexes are inconsistent"); + .expect("secondary indexes are inconsistent"); } } @@ -767,7 +766,7 @@ impl SuiNode { custom_rpc_runtime, software_version, ) - .await?; + .await?; let accumulator = Arc::new(StateAccumulator::new( cache_traits.accumulator_store.clone(), @@ -814,7 +813,7 @@ impl SuiNode { ®istry_service, sui_node_metrics.clone(), ) - .await?; + .await?; // This is only needed during cold start. components.consensus_adapter.submit_recovered(&epoch_store); @@ -940,7 +939,7 @@ impl SuiNode { 256 * 1024 * 1024, prometheus_registry, ) - .await?; + .await?; Ok(Some(archive_writer.start(state_sync_store).await?)) } else { Ok(None) @@ -1229,7 +1228,7 @@ impl SuiNode { consensus_adapter.clone(), ®istry_service.default_registry(), ) - .await?; + .await?; // Starts an overload monitor that monitors the execution of the authority. // Don't start the overload monitor when max_load_shedding_percentage is 0. @@ -1266,7 +1265,7 @@ impl SuiNode { sui_node_metrics, sui_tx_validator_metrics, ) - .await + .await } async fn start_epoch_specific_validator_components( @@ -1311,7 +1310,7 @@ impl SuiNode { randomness_handle, config.protocol_key_pair(), ) - .await; + .await; if let Some(randomness_manager) = randomness_manager { epoch_store .set_randomness_manager(randomness_manager) @@ -1474,13 +1473,8 @@ impl SuiNode { server_builder = server_builder.add_service(ValidatorServer::new(validator_service)); - let tls_config = sui_tls::create_rustls_server_config( - config.network_key_pair().copy().private(), - SUI_TLS_SERVER_NAME.to_string(), - sui_tls::AllowAll, - ); let server = server_builder - .bind(config.network_address(), Some(tls_config)) + .bind(config.network_address()) .await .map_err(|err| anyhow!(err.to_string()))?; let local_addr = server.local_addr(); @@ -1681,15 +1675,15 @@ impl SuiNode { // in the new epoch. let new_validator_components = if let Some(ValidatorComponents { - validator_server_handle, - validator_overload_monitor_handle, - consensus_manager, - consensus_store_pruner, - consensus_adapter, - mut checkpoint_service_tasks, - checkpoint_metrics, - sui_tx_validator_metrics, - }) = self.validator_components.lock().await.take() + validator_server_handle, + validator_overload_monitor_handle, + consensus_manager, + consensus_store_pruner, + consensus_adapter, + mut checkpoint_service_tasks, + checkpoint_metrics, + sui_tx_validator_metrics, + }) = self.validator_components.lock().await.take() { info!("Reconfiguring the validator."); // Cancel the old checkpoint service tasks. @@ -1755,7 +1749,7 @@ impl SuiNode { self.metrics.clone(), sui_tx_validator_metrics, ) - .await?, + .await?, ) } else { info!("This node is no longer a validator after reconfiguration"); @@ -1802,7 +1796,7 @@ impl SuiNode { &self.registry_service, self.metrics.clone(), ) - .await?, + .await?, ) } else { None @@ -1823,11 +1817,11 @@ impl SuiNode { ) { self.state - .prune_checkpoints_for_eligible_epochs_for_testing( - self.config.clone(), - sui_core::authority::authority_store_pruner::AuthorityStorePruningMetrics::new_for_test(), - ) - .await?; + .prune_checkpoints_for_eligible_epochs_for_testing( + self.config.clone(), + sui_core::authority::authority_store_pruner::AuthorityStorePruningMetrics::new_for_test(), + ) + .await?; } info!("Reconfiguration finished"); @@ -1862,7 +1856,7 @@ impl SuiNode { state.get_object_store().as_ref(), EpochFlag::default_flags_for_new_epoch(&state.config), ) - .expect("EpochStartConfiguration construction cannot fail"); + .expect("EpochStartConfiguration construction cannot fail"); let new_epoch_store = self .state @@ -2116,8 +2110,8 @@ pub async fn build_http_server( listener, router.into_make_service_with_connect_info::(), ) - .await - .unwrap() + .await + .unwrap() }); info!(local_addr =? addr, "Sui JSON-RPC server listening on {addr}"); @@ -2178,4 +2172,4 @@ fn max_tx_per_checkpoint(protocol_config: &ProtocolConfig) -> usize { #[cfg(test)] fn max_tx_per_checkpoint(_: &ProtocolConfig) -> usize { 2 -} +} \ No newline at end of file diff --git a/crates/sui-open-rpc/spec/openrpc.json b/crates/sui-open-rpc/spec/openrpc.json index add1b298f6e2d..8fc3a8fc673e0 100644 --- a/crates/sui-open-rpc/spec/openrpc.json +++ b/crates/sui-open-rpc/spec/openrpc.json @@ -12,7 +12,7 @@ "name": "Apache-2.0", "url": "https://raw.githubusercontent.com/MystenLabs/sui/main/LICENSE" }, - "version": "1.37.1" + "version": "1.37.3" }, "methods": [ { diff --git a/crates/sui-tls/src/lib.rs b/crates/sui-tls/src/lib.rs index 7f40317d43303..69c2dca881e23 100644 --- a/crates/sui-tls/src/lib.rs +++ b/crates/sui-tls/src/lib.rs @@ -5,9 +5,10 @@ mod acceptor; mod certgen; mod verifier; +pub const SUI_VALIDATOR_SERVER_NAME: &str = "sui"; + pub use acceptor::{TlsAcceptor, TlsConnectionInfo}; pub use certgen::SelfSignedCertificate; -use rustls::ClientConfig; pub use verifier::{ public_key_from_certificate, AllowAll, AllowPublicKeys, Allower, ClientCertVerifier, ServerCertVerifier, @@ -15,46 +16,6 @@ pub use verifier::{ pub use rustls; -use fastcrypto::ed25519::{Ed25519PrivateKey, Ed25519PublicKey}; -use tokio_rustls::rustls::ServerConfig; - -pub const SUI_VALIDATOR_SERVER_NAME: &str = "sui"; - -pub fn create_rustls_server_config( - private_key: Ed25519PrivateKey, - server_name: String, - allower: A, -) -> ServerConfig { - let verifier = ClientCertVerifier::new(allower, server_name.clone()); - // TODO: refactor to use key bytes - let self_signed_cert = SelfSignedCertificate::new(private_key, server_name.as_str()); - let tls_cert = self_signed_cert.rustls_certificate(); - let tls_private_key = self_signed_cert.rustls_private_key(); - let mut tls_config = verifier - .rustls_server_config(vec![tls_cert], tls_private_key) - .unwrap_or_else(|e| panic!("Failed to create TLS server config: {:?}", e)); - tls_config.alpn_protocols = vec![b"h2".to_vec()]; - tls_config -} - -pub fn create_rustls_client_config( - target_public_key: Ed25519PublicKey, - server_name: String, - client_key: Option, // optional self-signed cert for client verification -) -> ClientConfig { - let tls_config = ServerCertVerifier::new(target_public_key, server_name.clone()); - let tls_config = if let Some(private_key) = client_key { - let self_signed_cert = SelfSignedCertificate::new(private_key, server_name.as_str()); - let tls_cert = self_signed_cert.rustls_certificate(); - let tls_private_key = self_signed_cert.rustls_private_key(); - tls_config.rustls_client_config_with_client_auth(vec![tls_cert], tls_private_key) - } else { - tls_config.rustls_client_config_with_no_client_auth() - } - .unwrap_or_else(|e| panic!("Failed to create TLS client config: {e:?}")); - tls_config -} - #[cfg(test)] mod tests { use std::collections::BTreeSet; @@ -273,4 +234,4 @@ mod tests { let body = res.text().await.unwrap(); assert_eq!(client_public_key.to_string(), body); } -} +} \ No newline at end of file diff --git a/crates/sui-tls/src/verifier.rs b/crates/sui-tls/src/verifier.rs index b1e87fbf88823..562cc34d48973 100644 --- a/crates/sui-tls/src/verifier.rs +++ b/crates/sui-tls/src/verifier.rs @@ -178,30 +178,20 @@ impl ServerCertVerifier { Self { public_key, name } } - pub fn rustls_client_config_with_client_auth( + pub fn rustls_client_config( self, certificates: Vec>, private_key: PrivateKeyDer<'static>, ) -> Result { - rustls::ClientConfig::builder_with_provider(Arc::new( + let mut config = rustls::ClientConfig::builder_with_provider(Arc::new( rustls::crypto::ring::default_provider(), )) .with_safe_default_protocol_versions()? .dangerous() .with_custom_certificate_verifier(std::sync::Arc::new(self)) - .with_client_auth_cert(certificates, private_key) - } - - pub fn rustls_client_config_with_no_client_auth( - self, - ) -> Result { - Ok(rustls::ClientConfig::builder_with_provider(Arc::new( - rustls::crypto::ring::default_provider(), - )) - .with_safe_default_protocol_versions()? - .dangerous() - .with_custom_certificate_verifier(std::sync::Arc::new(self)) - .with_no_client_auth()) + .with_client_auth_cert(certificates, private_key)?; + config.alpn_protocols = vec![b"h2".to_vec()]; + Ok(config) } } diff --git a/crates/sui-tool/Cargo.toml b/crates/sui-tool/Cargo.toml index e2d0ce18338df..cb9bff954df3e 100644 --- a/crates/sui-tool/Cargo.toml +++ b/crates/sui-tool/Cargo.toml @@ -47,5 +47,4 @@ sui-storage.workspace = true sui-types.workspace = true sui-archival.workspace = true sui-package-dump.workspace = true -sui-tls.workspace = true bin-version.workspace = true diff --git a/crates/sui-types/Cargo.toml b/crates/sui-types/Cargo.toml index fcb060ce2bd7c..4b29e276ec05e 100644 --- a/crates/sui-types/Cargo.toml +++ b/crates/sui-types/Cargo.toml @@ -42,7 +42,6 @@ roaring.workspace = true enum_dispatch.workspace = true eyre.workspace = true indexmap.workspace = true -derivative.workspace = true jsonrpsee.workspace = true move-binary-format.workspace = true move-bytecode-utils.workspace = true @@ -70,7 +69,7 @@ fastcrypto-zkp.workspace = true passkey-types.workspace = true typed-store-error.workspace = true -derive_more.workspace = true +derive_more = { workspace = true, features = ["as_ref", "debug", "display", "from"] } proptest.workspace = true proptest-derive.workspace = true better_any.workspace = true diff --git a/crates/sui-types/src/committee.rs b/crates/sui-types/src/committee.rs index fea794ffd259c..906fd6ba1c94c 100644 --- a/crates/sui-types/src/committee.rs +++ b/crates/sui-types/src/committee.rs @@ -3,9 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 use super::base_types::*; -use crate::crypto::{ - random_committee_key_pairs_of_size, AuthorityKeyPair, AuthorityPublicKey, NetworkPublicKey, -}; +use crate::crypto::{random_committee_key_pairs_of_size, AuthorityKeyPair, AuthorityPublicKey}; use crate::error::{SuiError, SuiResult}; use crate::multiaddr::Multiaddr; use fastcrypto::traits::KeyPair; @@ -355,17 +353,18 @@ pub trait CommitteeTrait { fn weight(&self, author: &K) -> StakeUnit; } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct NetworkMetadata { pub network_address: Multiaddr, pub narwhal_primary_address: Multiaddr, - pub network_public_key: Option, } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct CommitteeWithNetworkMetadata { epoch_id: EpochId, validators: BTreeMap, + + #[serde(skip)] committee: OnceCell, } diff --git a/crates/sui-types/src/move_package.rs b/crates/sui-types/src/move_package.rs index 8b12643e4ec16..06bd929471916 100644 --- a/crates/sui-types/src/move_package.rs +++ b/crates/sui-types/src/move_package.rs @@ -10,7 +10,6 @@ use crate::{ object::OBJECT_START_VERSION, SUI_FRAMEWORK_ADDRESS, }; -use derive_more::Display; use fastcrypto::hash::HashFunction; use move_binary_format::binary_config::BinaryConfig; use move_binary_format::file_format::CompiledModule; @@ -114,13 +113,13 @@ pub struct MovePackage { // associated constants before storing in any serialization setting. /// Rust representation of upgrade policy constants in `sui::package`. #[repr(u8)] -#[derive(Display, Debug, Clone, Copy)] +#[derive(derive_more::Display, Debug, Clone, Copy)] pub enum UpgradePolicy { - #[display(fmt = "COMPATIBLE")] + #[display("COMPATIBLE")] Compatible = 0, - #[display(fmt = "ADDITIVE")] + #[display("ADDITIVE")] Additive = 128, - #[display(fmt = "DEP_ONLY")] + #[display("DEP_ONLY")] DepOnly = 192, } diff --git a/crates/sui-types/src/sui_system_state/epoch_start_sui_system_state.rs b/crates/sui-types/src/sui_system_state/epoch_start_sui_system_state.rs index 118f15c89b420..648bfc1e7f995 100644 --- a/crates/sui-types/src/sui_system_state/epoch_start_sui_system_state.rs +++ b/crates/sui-types/src/sui_system_state/epoch_start_sui_system_state.rs @@ -159,7 +159,6 @@ impl EpochStartSystemStateTrait for EpochStartSystemStateV1 { NetworkMetadata { network_address: validator.sui_net_address.clone(), narwhal_primary_address: validator.narwhal_primary_address.clone(), - network_public_key: Some(validator.narwhal_network_pubkey.clone()), }, ), ) @@ -370,4 +369,4 @@ mod test { ); } } -} +} \ No newline at end of file diff --git a/crates/sui-types/src/sui_system_state/mod.rs b/crates/sui-types/src/sui_system_state/mod.rs index d647e7da495b6..7f91dbd292e98 100644 --- a/crates/sui-types/src/sui_system_state/mod.rs +++ b/crates/sui-types/src/sui_system_state/mod.rs @@ -416,6 +416,13 @@ impl PoolTokenExchangeRate { self.pool_token_amount as f64 / self.sui_amount as f64 } } + + pub fn new(sui_amount: u64, pool_token_amount: u64) -> Self { + Self { + sui_amount, + pool_token_amount, + } + } } #[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq)] diff --git a/crates/sui-types/src/sui_system_state/simtest_sui_system_state_inner.rs b/crates/sui-types/src/sui_system_state/simtest_sui_system_state_inner.rs index 380ce1708bda5..0a365fec9c972 100644 --- a/crates/sui-types/src/sui_system_state/simtest_sui_system_state_inner.rs +++ b/crates/sui-types/src/sui_system_state/simtest_sui_system_state_inner.rs @@ -175,7 +175,6 @@ impl SuiSystemStateTrait for SimTestSuiSystemStateInnerV1 { NetworkMetadata { network_address: verified_metadata.net_address.clone(), narwhal_primary_address: verified_metadata.primary_address.clone(), - network_public_key: Some(verified_metadata.network_pubkey.clone()), }, ), ) @@ -292,7 +291,6 @@ impl SuiSystemStateTrait for SimTestSuiSystemStateInnerShallowV2 { NetworkMetadata { network_address: verified_metadata.net_address.clone(), narwhal_primary_address: verified_metadata.primary_address.clone(), - network_public_key: Some(verified_metadata.network_pubkey.clone()), }, ), ) @@ -438,7 +436,6 @@ impl SuiSystemStateTrait for SimTestSuiSystemStateInnerDeepV2 { NetworkMetadata { network_address: verified_metadata.net_address.clone(), narwhal_primary_address: verified_metadata.primary_address.clone(), - network_public_key: Some(verified_metadata.network_pubkey.clone()), }, ), ) diff --git a/crates/sui-types/src/sui_system_state/sui_system_state_inner_v1.rs b/crates/sui-types/src/sui_system_state/sui_system_state_inner_v1.rs index c759b9254490e..11b8565b47e65 100644 --- a/crates/sui-types/src/sui_system_state/sui_system_state_inner_v1.rs +++ b/crates/sui-types/src/sui_system_state/sui_system_state_inner_v1.rs @@ -88,14 +88,13 @@ pub struct ValidatorMetadataV1 { pub extra_fields: Bag, } -#[derive(derivative::Derivative, Clone, Eq, PartialEq)] -#[derivative(Debug)] +#[derive(derive_more::Debug, Clone, Eq, PartialEq)] pub struct VerifiedValidatorMetadataV1 { pub sui_address: SuiAddress, pub protocol_pubkey: AuthorityPublicKey, pub network_pubkey: NetworkPublicKey, pub worker_pubkey: NetworkPublicKey, - #[derivative(Debug = "ignore")] + #[debug(ignore)] pub proof_of_possession_bytes: Vec, pub name: String, pub description: String, @@ -553,7 +552,6 @@ impl SuiSystemStateTrait for SuiSystemStateInnerV1 { NetworkMetadata { network_address: verified_metadata.net_address.clone(), narwhal_primary_address: verified_metadata.primary_address.clone(), - network_public_key: Some(verified_metadata.network_pubkey.clone()), }, ), ) diff --git a/crates/sui-types/src/sui_system_state/sui_system_state_inner_v2.rs b/crates/sui-types/src/sui_system_state/sui_system_state_inner_v2.rs index 1b8ce5f75d6b9..f0863c2119466 100644 --- a/crates/sui-types/src/sui_system_state/sui_system_state_inner_v2.rs +++ b/crates/sui-types/src/sui_system_state/sui_system_state_inner_v2.rs @@ -132,7 +132,6 @@ impl SuiSystemStateTrait for SuiSystemStateInnerV2 { NetworkMetadata { network_address: verified_metadata.net_address.clone(), narwhal_primary_address: verified_metadata.primary_address.clone(), - network_public_key: Some(verified_metadata.network_pubkey.clone()), }, ), ) diff --git a/crates/sui-types/src/sui_system_state/sui_system_state_summary.rs b/crates/sui-types/src/sui_system_state/sui_system_state_summary.rs index 525650a730157..0b76e4c344b02 100644 --- a/crates/sui-types/src/sui_system_state/sui_system_state_summary.rs +++ b/crates/sui-types/src/sui_system_state/sui_system_state_summary.rs @@ -4,7 +4,6 @@ use super::{SuiSystemState, SuiSystemStateTrait}; use crate::base_types::{AuthorityName, ObjectID, SuiAddress}; use crate::committee::{CommitteeWithNetworkMetadata, NetworkMetadata}; -use crate::crypto::NetworkPublicKey; use crate::dynamic_field::get_dynamic_field_from_store; use crate::error::SuiError; use crate::id::ID; @@ -203,10 +202,6 @@ impl SuiSystemStateSummary { validator.primary_address.clone(), ) .unwrap(), - network_public_key: NetworkPublicKey::from_bytes( - &validator.network_pubkey_bytes, - ) - .ok(), }, ), ) diff --git a/crates/telemetry-subscribers/Cargo.toml b/crates/telemetry-subscribers/Cargo.toml index 1ed249129edac..452ea1f2b7a4d 100644 --- a/crates/telemetry-subscribers/Cargo.toml +++ b/crates/telemetry-subscribers/Cargo.toml @@ -18,7 +18,6 @@ tracing.workspace = true tracing-appender.workspace = true tracing-subscriber.workspace = true opentelemetry = { version = "0.25.0", optional = true } -opentelemetry_api = { version = "0.20.0", optional = true } opentelemetry_sdk = { version = "0.25.0", features = ["rt-tokio"], optional = true } opentelemetry-otlp = { version = "0.25.0", features = ["grpc-tonic"], optional = true } tracing-opentelemetry = { version = "0.26.0", optional = true } @@ -42,7 +41,6 @@ otlp = [ "opentelemetry", "opentelemetry-otlp", "opentelemetry-proto", - "opentelemetry_api", "opentelemetry_sdk" ] diff --git a/deny.toml b/deny.toml index b396cb4eac121..6b358daff5eb3 100644 --- a/deny.toml +++ b/deny.toml @@ -39,6 +39,10 @@ ignore = [ # Temporarily allow until arrow family of crates updates `lexical-core` to 1.0 "RUSTSEC-2023-0086", + # allow unmaintained instant crate used in transitive dependencies (backoff, cached, fastrand, parking_lot_*) + "RUSTSEC-2024-0384", + # allow unmaintained derivative crate used in transitive dependencies (ark-*) + "RUSTSEC-2024-0388", ] # Threshold for security vulnerabilities, any vulnerability with a CVSS score # lower than the range specified will be ignored. Note that ignored advisories diff --git a/narwhal/primary/tests/nodes_bootstrapping_tests.rs b/narwhal/primary/tests/nodes_bootstrapping_tests.rs new file mode 100644 index 0000000000000..373676bfe7cb1 --- /dev/null +++ b/narwhal/primary/tests/nodes_bootstrapping_tests.rs @@ -0,0 +1,299 @@ +// Copyright (c) Mysten Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 +use bytes::Bytes; +use std::time::Duration; +use test_utils::cluster::{setup_tracing, Cluster}; +use types::TransactionProto; + +#[tokio::test(flavor = "current_thread", start_paused = true)] +async fn test_response_error_after_shutdown_internal_consensus() { + // Enabled debug tracing so we can easily observe the + // nodes logs. + let _guard = setup_tracing(); + + let delay = Duration::from_secs(10); // 10 seconds + + // A cluster of 4 nodes will be created, with internal consensus. + let cluster = Cluster::new(None); + + // ==== Start first authority ==== + let authority = cluster.authority(0); + authority.start(false, Some(1)).await; + + tokio::time::sleep(delay).await; + + authority.stop_all().await; + + tokio::time::sleep(delay).await; + + let worker_id = 0; + let mut client = authority.new_transactions_client(&worker_id).await; + + // Create a fake transaction + let tx_str = "test transaction".to_string(); + let tx = bcs::to_bytes(&tx_str).unwrap(); + let txn = TransactionProto { + transactions: vec![Bytes::from(tx)], + }; + + // Should fail submitting to consensus. + let Err(e) = client.submit_transaction(txn).await else { + panic!("Submitting transactions after Narwhal shutdown should fail!"); + }; + assert!(e.message().contains("tcp connect error:"), "Actual: {}", e); +} + +/// Nodes will be started in a staggered fashion. This is simulating +/// a real world scenario where nodes across validators will not start +/// in the same time. +#[ignore] +#[tokio::test] +async fn test_node_staggered_starts() { + // Enabled debug tracing so we can easily observe the + // nodes logs. + let _guard = setup_tracing(); + + let node_staggered_delay = Duration::from_secs(60 * 2); // 2 minutes + + // A cluster of 4 nodes will be created + let cluster = Cluster::new(None); + + // ==== Start first authority ==== + cluster.authority(0).start(false, Some(1)).await; + + tokio::time::sleep(node_staggered_delay).await; + + // No node should be able to commit, no reported round was expected + cluster.assert_progress(0, 0).await; + + // ==== Start second authority ==== + cluster.authority(1).start(false, Some(1)).await; + + tokio::time::sleep(node_staggered_delay).await; + + // No node should be able to commit, no reported round was expected + cluster.assert_progress(0, 0).await; + + // ==== Start third authority ==== + // Now 2f + 1 nodes are becoming available and we expect all the nodes to + // start making progress (advance in rounds). + cluster.authority(2).start(false, Some(1)).await; + + tokio::time::sleep(node_staggered_delay).await; + + // We have only (f) unavailable nodes, so all should have made progress and committed at least after the first round + cluster.assert_progress(3, 2).await; + + // ==== Start fourth authority ==== + // Now 3f + 1 nodes are becoming available (the whole network) and all the nodes + // should make progress + cluster.authority(3).start(false, Some(1)).await; + + tokio::time::sleep(node_staggered_delay).await; + + // All nodes are available so all should have made progress and committed at least after the first round + cluster.assert_progress(4, 2).await; +} + +/// All the nodes have an outage at the same time, when they recover, the rounds begin to advance. +#[ignore] +#[tokio::test] +async fn test_full_outage_and_recovery() { + let _guard = setup_tracing(); + + let stop_and_start_delay = Duration::from_secs(12); + let node_advance_delay = Duration::from_secs(60); + + // A cluster of 4 nodes will be created + let mut cluster = Cluster::new(None); + + // ===== Start the cluster ==== + cluster.start(Some(4), Some(1), None).await; + + // Let the nodes advance a bit + tokio::time::sleep(node_advance_delay).await; + + // Stop all the nodes + cluster.authority(0).stop_all().await; + tokio::time::sleep(stop_and_start_delay).await; + + cluster.authority(1).stop_all().await; + tokio::time::sleep(stop_and_start_delay).await; + + cluster.authority(2).stop_all().await; + tokio::time::sleep(stop_and_start_delay).await; + + cluster.authority(3).stop_all().await; + tokio::time::sleep(stop_and_start_delay).await; + + // Start all the nodes + cluster.authority(0).start(true, Some(1)).await; + tokio::time::sleep(stop_and_start_delay).await; + + cluster.authority(1).start(true, Some(1)).await; + tokio::time::sleep(stop_and_start_delay).await; + + cluster.authority(2).start(true, Some(1)).await; + tokio::time::sleep(stop_and_start_delay).await; + + cluster.authority(3).start(true, Some(1)).await; + + // now wait a bit to give the opportunity to recover + tokio::time::sleep(node_advance_delay).await; + + // Ensure that nodes have made progress + cluster.assert_progress(4, 2).await; +} + +#[ignore] +#[tokio::test] +async fn test_second_node_restart() { + // Enabled debug tracing so we can easily observe the + // nodes logs. + let _guard = setup_tracing(); + + let restart_delay = Duration::from_secs(120); + let node_advance_delay = Duration::from_secs(60); + + // A cluster of 4 nodes will be created + let mut cluster = Cluster::new(None); + + // ===== Start the cluster ==== + cluster.start(Some(4), Some(1), None).await; + + // Let the nodes advance a bit + tokio::time::sleep(node_advance_delay).await; + + // Now restart node 2 with some delay between + cluster.authority(2).restart(true, restart_delay).await; + + // now wait a bit to give the opportunity to recover + tokio::time::sleep(node_advance_delay).await; + + // Ensure that nodes have made progress + cluster.assert_progress(4, 2).await; + + // Now restart node 3 with some delay between + cluster.authority(3).restart(true, restart_delay).await; + + // now wait a bit to give the opportunity to recover + tokio::time::sleep(node_advance_delay).await; + + // Ensure that nodes have made progress + cluster.assert_progress(4, 2).await; +} + +#[ignore] +#[tokio::test] +/// We are testing the loss of liveness of a healthy cluster. While 3f+1 nodes run +/// we are shutting down f+1 nodes. Then we are bringing the f+1 nodes back again +/// We expect the restarted nodes to be able to make new proposals, and all the nodes +/// should be able to propose from where they left of at last round, and the rounds should +/// all advance. +async fn test_loss_of_liveness_without_recovery() { + // Enabled debug tracing so we can easily observe the + // nodes logs. + let _guard = setup_tracing(); + + let node_advance_delay = Duration::from_secs(60); + + // A cluster of 4 nodes will be created + let mut cluster = Cluster::new(None); + + // ===== Start the cluster ==== + cluster.start(Some(4), Some(1), None).await; + + // Let the nodes advance a bit + tokio::time::sleep(node_advance_delay).await; + + // Ensure that nodes have made progress + cluster.assert_progress(4, 2).await; + + // Now stop node 2 & 3 + cluster.authority(2).stop_all().await; + cluster.authority(3).stop_all().await; + + // wait and fetch the latest commit round + tokio::time::sleep(node_advance_delay).await; + let rounds_1 = cluster.assert_progress(2, 0).await; + + // wait and fetch again the rounds + tokio::time::sleep(node_advance_delay).await; + let rounds_2 = cluster.assert_progress(2, 0).await; + + // We assert that nodes haven't advanced at all + assert_eq!(rounds_1, rounds_2); + + // Now bring up nodes + cluster.authority(2).start(true, Some(1)).await; + cluster.authority(3).start(true, Some(1)).await; + + // wait and fetch the latest commit round. All of them should have advanced and we allow a small + // threshold in case some node is faster than the others + tokio::time::sleep(node_advance_delay).await; + let rounds_3 = cluster.assert_progress(4, 2).await; + + // we test that nodes 0 & 1 have actually advanced in rounds compared to before. + assert!(rounds_3.get(&0) > rounds_2.get(&0)); + assert!(rounds_3.get(&1) > rounds_2.get(&1)); +} + +#[ignore] +#[tokio::test] +/// We are testing the loss of liveness of a healthy cluster. While 3f+1 nodes run +/// we are shutting down f+1 nodes one by one with some delay between them. +/// Then we are bringing the f+1 nodes back again. We expect the cluster to +/// recover and effectively make progress. +async fn test_loss_of_liveness_with_recovery() { + // Enabled debug tracing so we can easily observe the + // nodes logs. + let _guard = setup_tracing(); + + let node_advance_delay = Duration::from_secs(60); + + // A cluster of 4 nodes will be created + let mut cluster = Cluster::new(None); + + // ===== Start the cluster ==== + cluster.start(Some(4), Some(1), None).await; + + // Let the nodes advance a bit + tokio::time::sleep(node_advance_delay).await; + + // Ensure that nodes have made progress + cluster.assert_progress(4, 2).await; + + // Now stop node 2 + cluster.authority(2).stop_all().await; + + // allow other nodes to advance + tokio::time::sleep(node_advance_delay).await; + + // Now stop node 3 + cluster.authority(3).stop_all().await; + + // wait and fetch the latest commit round + tokio::time::sleep(node_advance_delay).await; + let rounds_1 = cluster.assert_progress(2, 0).await; + + // wait and fetch again the rounds + tokio::time::sleep(node_advance_delay).await; + let rounds_2 = cluster.assert_progress(2, 0).await; + + // We assert that nodes haven't advanced at all + assert_eq!(rounds_1, rounds_2); + + // Now bring up nodes + cluster.authority(2).start(true, Some(1)).await; + cluster.authority(3).start(true, Some(1)).await; + + // wait and fetch the latest commit round + tokio::time::sleep(node_advance_delay).await; + let rounds_3 = cluster.assert_progress(4, 2).await; + + let round_2_max = rounds_2.values().max().unwrap(); + assert!( + rounds_3.values().all(|v| v > round_2_max), + "All the nodes should have advanced more from the previous round" + ); +} diff --git a/narwhal/worker/src/tests/worker_tests.rs b/narwhal/worker/src/tests/worker_tests.rs new file mode 100644 index 0000000000000..99421109124da --- /dev/null +++ b/narwhal/worker/src/tests/worker_tests.rs @@ -0,0 +1,371 @@ +// Copyright (c) 2021, Facebook, Inc. and its affiliates +// Copyright (c) Mysten Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 +use super::*; +use crate::LocalNarwhalClient; +use crate::{metrics::initialise_metrics, TrivialTransactionValidator}; +use async_trait::async_trait; +use bytes::Bytes; +use fastcrypto::hash::Hash; +use futures::stream::FuturesOrdered; +use futures::StreamExt; +use primary::{CHANNEL_CAPACITY, NUM_SHUTDOWN_RECEIVERS}; +use prometheus::Registry; +use store::rocks; +use store::rocks::MetricConf; +use store::rocks::ReadWriteOptions; +use test_utils::{ + batch, latest_protocol_version, temp_dir, test_network, transaction, CommitteeFixture, +}; +use types::{ + BatchAPI, MockWorkerToPrimary, MockWorkerToWorker, PreSubscribedBroadcastSender, + TransactionProto, TransactionsClient, WorkerBatchMessage, WorkerToWorkerClient, +}; + +// A test validator that rejects every transaction / batch +#[derive(Clone)] +struct NilTxValidator; +#[async_trait] +impl TransactionValidator for NilTxValidator { + type Error = eyre::Report; + + fn validate(&self, _tx: &[u8]) -> Result<(), Self::Error> { + eyre::bail!("Invalid transaction"); + } + fn validate_batch( + &self, + _txs: &Batch, + _protocol_config: &ProtocolConfig, + ) -> Result<(), Self::Error> { + eyre::bail!("Invalid batch"); + } +} + +#[tokio::test] +async fn reject_invalid_clients_transactions() { + let fixture = CommitteeFixture::builder().randomize_ports(true).build(); + let committee = fixture.committee(); + let worker_cache = fixture.worker_cache(); + + let worker_id = 0; + let my_primary = fixture.authorities().next().unwrap(); + let myself = my_primary.worker(worker_id); + let public_key = my_primary.public_key(); + let client = NetworkClient::new_from_keypair(&my_primary.network_keypair()); + + let parameters = Parameters { + batch_size: 200, // Two transactions. + ..Parameters::default() + }; + + // Create a new test store. + let batch_store = rocks::DBMap::::open( + temp_dir(), + MetricConf::default(), + None, + Some("batches"), + &ReadWriteOptions::default(), + ) + .unwrap(); + + let registry = Registry::new(); + let metrics = initialise_metrics(®istry); + + let mut tx_shutdown = PreSubscribedBroadcastSender::new(NUM_SHUTDOWN_RECEIVERS); + + // Spawn a `Worker` instance with a reject-all validator. + Worker::spawn( + my_primary.authority().clone(), + myself.keypair(), + worker_id, + committee.clone(), + worker_cache.clone(), + latest_protocol_version(), + parameters, + NilTxValidator, + client, + batch_store, + metrics, + &mut tx_shutdown, + ); + + // Wait till other services have been able to start up + tokio::task::yield_now().await; + // Send enough transactions to create a batch. + let address = worker_cache + .worker(&public_key, &worker_id) + .unwrap() + .transactions; + let config = mysten_network::config::Config::new(); + let channel = config.connect_lazy(&address).unwrap(); + let mut client = TransactionsClient::new(channel); + let tx = transaction(); + let txn = TransactionProto { + transactions: vec![Bytes::from(tx.clone())], + }; + + // Check invalid transactions are rejected + let res = client.submit_transaction(txn).await; + assert!(res.is_err()); + + let worker_pk = worker_cache.worker(&public_key, &worker_id).unwrap().name; + + let batch = batch(&latest_protocol_version()); + let batch_message = WorkerBatchMessage { + batch: batch.clone(), + }; + + // setup network : impersonate a send from another worker + let another_primary = fixture.authorities().nth(2).unwrap(); + let another_worker = another_primary.worker(worker_id); + let network = test_network( + another_worker.keypair(), + &another_worker.info().worker_address, + ); + // ensure that the networks are connected + network + .connect(myself.info().worker_address.to_anemo_address().unwrap()) + .await + .unwrap(); + let peer = network.peer(PeerId(worker_pk.0.to_bytes())).unwrap(); + + // Check invalid batches are rejected + let res = WorkerToWorkerClient::new(peer) + .report_batch(batch_message) + .await; + assert!(res.is_err()); +} + +/// TODO: test both RemoteNarwhalClient and LocalNarwhalClient in the same test case. +#[tokio::test] +async fn handle_remote_clients_transactions() { + let fixture = CommitteeFixture::builder().randomize_ports(true).build(); + let committee = fixture.committee(); + let worker_cache = fixture.worker_cache(); + + let worker_id = 0; + let my_primary = fixture.authorities().next().unwrap(); + let myself = my_primary.worker(worker_id); + let authority_public_key = my_primary.public_key(); + let client = NetworkClient::new_from_keypair(&my_primary.network_keypair()); + + let parameters = Parameters { + batch_size: 200, // Two transactions. + ..Parameters::default() + }; + + // Create a new test store. + let batch_store = rocks::DBMap::::open( + temp_dir(), + MetricConf::default(), + None, + Some("batches"), + &ReadWriteOptions::default(), + ) + .unwrap(); + + let registry = Registry::new(); + let metrics = initialise_metrics(®istry); + + let mut tx_shutdown = PreSubscribedBroadcastSender::new(NUM_SHUTDOWN_RECEIVERS); + + // Spawn a `Worker` instance. + Worker::spawn( + my_primary.authority().clone(), + myself.keypair(), + worker_id, + committee.clone(), + worker_cache.clone(), + latest_protocol_version(), + parameters, + TrivialTransactionValidator, + client.clone(), + batch_store, + metrics, + &mut tx_shutdown, + ); + + // Spawn a network listener to receive our batch's digest. + let mut peer_networks = Vec::new(); + + // Create batches + let batch = batch(&latest_protocol_version()); + let batch_digest = batch.digest(); + + let (tx_await_batch, mut rx_await_batch) = test_utils::test_channel!(CHANNEL_CAPACITY); + let mut mock_primary_server = MockWorkerToPrimary::new(); + mock_primary_server + .expect_report_own_batch() + .withf(move |request| { + let message = request.body(); + + message.digest == batch_digest && message.worker_id == worker_id + }) + .times(1) + .returning(move |_| { + tx_await_batch.try_send(()).unwrap(); + Ok(anemo::Response::new(())) + }); + client.set_worker_to_primary_local_handler(Arc::new(mock_primary_server)); + + // Spawn enough workers' listeners to acknowledge our batches. + for worker in fixture.authorities().skip(1).map(|a| a.worker(worker_id)) { + let mut mock_server = MockWorkerToWorker::new(); + mock_server + .expect_report_batch() + .returning(|_| Ok(anemo::Response::new(()))); + let routes = anemo::Router::new().add_rpc_service(WorkerToWorkerServer::new(mock_server)); + peer_networks.push(worker.new_network(routes)); + } + + // Wait till other services have been able to start up + tokio::task::yield_now().await; + // Send enough transactions to create a batch. + let address = worker_cache + .worker(&authority_public_key, &worker_id) + .unwrap() + .transactions; + let config = mysten_network::config::Config::new(); + let channel = config.connect_lazy(&address).unwrap(); + let client = TransactionsClient::new(channel); + + let join_handle = tokio::task::spawn(async move { + let mut fut_list = FuturesOrdered::new(); + for tx in batch.transactions() { + let txn = TransactionProto { + transactions: vec![Bytes::from(tx.clone())], + }; + + // Calls to submit_transaction are now blocking, so we need to drive them + // all at the same time, rather than sequentially. + let mut inner_client = client.clone(); + fut_list.push_back(async move { + inner_client.submit_transaction(txn).await.unwrap(); + }); + } + + // Drive all sending in parallel. + while fut_list.next().await.is_some() {} + }); + + // Ensure the primary received the batch's digest (ie. it did not panic). + rx_await_batch.recv().await.unwrap(); + + // Ensure sending ended. + assert!(join_handle.await.is_ok()); +} + +/// TODO: test both RemoteNarwhalClient and LocalNarwhalClient in the same test case. +#[tokio::test] +async fn handle_local_clients_transactions() { + let fixture = CommitteeFixture::builder().randomize_ports(true).build(); + let committee = fixture.committee(); + let worker_cache = fixture.worker_cache(); + + let worker_id = 0; + let my_primary = fixture.authorities().next().unwrap(); + let myself = my_primary.worker(worker_id); + let authority_public_key = my_primary.public_key(); + let client = NetworkClient::new_from_keypair(&my_primary.network_keypair()); + + let parameters = Parameters { + batch_size: 200, // Two transactions. + ..Parameters::default() + }; + + // Create a new test store. + let batch_store = rocks::DBMap::::open( + temp_dir(), + MetricConf::default(), + None, + Some("batches"), + &ReadWriteOptions::default(), + ) + .unwrap(); + + let registry = Registry::new(); + let metrics = initialise_metrics(®istry); + + let mut tx_shutdown = PreSubscribedBroadcastSender::new(NUM_SHUTDOWN_RECEIVERS); + + // Spawn a `Worker` instance. + Worker::spawn( + my_primary.authority().clone(), + myself.keypair(), + worker_id, + committee.clone(), + worker_cache.clone(), + latest_protocol_version(), + parameters, + TrivialTransactionValidator, + client.clone(), + batch_store, + metrics, + &mut tx_shutdown, + ); + + // Spawn a network listener to receive our batch's digest. + let mut peer_networks = Vec::new(); + + // Create batches + let batch = batch(&latest_protocol_version()); + let batch_digest = batch.digest(); + + let (tx_await_batch, mut rx_await_batch) = test_utils::test_channel!(CHANNEL_CAPACITY); + let mut mock_primary_server = MockWorkerToPrimary::new(); + mock_primary_server + .expect_report_own_batch() + .withf(move |request| { + let message = request.body(); + message.digest == batch_digest && message.worker_id == worker_id + }) + .times(1) + .returning(move |_| { + tx_await_batch.try_send(()).unwrap(); + Ok(anemo::Response::new(())) + }); + client.set_worker_to_primary_local_handler(Arc::new(mock_primary_server)); + + // Spawn enough workers' listeners to acknowledge our batches. + for worker in fixture.authorities().skip(1).map(|a| a.worker(worker_id)) { + let mut mock_server = MockWorkerToWorker::new(); + mock_server + .expect_report_batch() + .returning(|_| Ok(anemo::Response::new(()))); + let routes = anemo::Router::new().add_rpc_service(WorkerToWorkerServer::new(mock_server)); + peer_networks.push(worker.new_network(routes)); + } + + // Wait till other services have been able to start up + tokio::task::yield_now().await; + // Send enough transactions to create a batch. + let address = worker_cache + .worker(&authority_public_key, &worker_id) + .unwrap() + .transactions; + let client = LocalNarwhalClient::get_global(&address).unwrap().load(); + + let join_handle = tokio::task::spawn(async move { + let mut fut_list = FuturesOrdered::new(); + for txn in batch.transactions() { + // Calls to submit_transaction are now blocking, so we need to drive them + // all at the same time, rather than sequentially. + let inner_client = client.clone(); + fut_list.push_back(async move { + inner_client + .submit_transactions(vec![txn.clone()]) + .await + .unwrap(); + }); + } + + // Drive all sending in parallel. + while fut_list.next().await.is_some() {} + }); + + // Ensure the primary received the batch's digest (ie. it did not panic). + rx_await_batch.recv().await.unwrap(); + + // Ensure sending ended. + assert!(join_handle.await.is_ok()); +}