From 81a15942f92c5975af503e2a7499219b03925055 Mon Sep 17 00:00:00 2001 From: Nina Date: Fri, 13 Feb 2026 16:55:14 +0000 Subject: [PATCH 01/12] tcp tile / squashed commits --- Cargo.lock | 1571 +++++++++-------- Cargo.toml | 2 + crates/common/src/config.rs | 8 + crates/common/src/local_cache.rs | 22 +- crates/relay/Cargo.toml | 2 + crates/relay/src/api/admin_service.rs | 4 +- crates/relay/src/api/builder/submit_block.rs | 28 +- crates/relay/src/api/builder/top_bid.rs | 6 +- crates/relay/src/auctioneer/context.rs | 2 +- crates/relay/src/auctioneer/decoder.rs | 189 +- crates/relay/src/auctioneer/handle.rs | 23 +- crates/relay/src/auctioneer/mod.rs | 52 +- .../relay/src/auctioneer/simulator/manager.rs | 2 + crates/relay/src/auctioneer/simulator/mod.rs | 23 +- crates/relay/src/auctioneer/submit_block.rs | 15 +- crates/relay/src/auctioneer/types.rs | 20 +- crates/relay/src/auctioneer/worker.rs | 136 +- crates/relay/src/lib.rs | 4 +- crates/relay/src/main.rs | 29 +- crates/relay/src/tcp_bid_recv/mod.rs | 193 ++ crates/relay/src/tcp_bid_recv/types.rs | 189 ++ crates/relay/src/website/website_service.rs | 2 +- crates/types/Cargo.toml | 1 + crates/types/src/block_merging.rs | 1 + 24 files changed, 1603 insertions(+), 921 deletions(-) create mode 100644 crates/relay/src/tcp_bid_recv/mod.rs create mode 100644 crates/relay/src/tcp_bid_recv/types.rs diff --git a/Cargo.lock b/Cargo.lock index f1359fa99..d582afe9a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -120,9 +120,9 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "alloy-chains" -version = "0.2.23" +version = "0.2.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35d744058a9daa51a8cf22a3009607498fcf82d3cf4c5444dd8056cdf651f471" +checksum = "90f374d3c6d729268bbe2d0e0ff992bb97898b2df756691a62ee1d5f0506bc39" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -133,9 +133,9 @@ dependencies = [ [[package]] name = "alloy-consensus" -version = "1.1.3" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e318e25fb719e747a7e8db1654170fc185024f3ed5b10f86c08d448a912f6e2" +checksum = "86debde32d8dbb0ab29e7cc75ae1a98688ac7a4c9da54b3a9b14593b9b3c46d3" dependencies = [ "alloy-eips", "alloy-primitives", @@ -146,7 +146,7 @@ dependencies = [ "auto_impl", "borsh", "c-kzg", - "derive_more 2.1.0", + "derive_more 2.1.1", "either", "k256", "once_cell", @@ -155,14 +155,14 @@ dependencies = [ "serde", "serde_json", "serde_with 3.16.1", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] name = "alloy-consensus-any" -version = "1.1.3" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "364380a845193a317bcb7a5398fc86cdb66c47ebe010771dde05f6869bf9e64a" +checksum = "8d6cb2e7efd385b333f5a77b71baaa2605f7e22f1d583f2879543b54cbce777c" dependencies = [ "alloy-consensus", "alloy-eips", @@ -174,15 +174,15 @@ dependencies = [ [[package]] name = "alloy-dyn-abi" -version = "1.4.1" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdff496dd4e98a81f4861e66f7eaf5f2488971848bb42d9c892f871730245c8" +checksum = "14ff5ee5f27aa305bda825c735f686ad71bb65508158f059f513895abe69b8c3" dependencies = [ "alloy-json-abi", "alloy-primitives", "alloy-sol-type-parser", "alloy-sol-types", - "derive_more 2.1.0", + "derive_more 2.1.1", "itoa", "serde", "serde_json", @@ -199,7 +199,7 @@ dependencies = [ "alloy-rlp", "crc", "serde", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -226,32 +226,45 @@ dependencies = [ "k256", "serde", "serde_with 3.16.1", - "thiserror 2.0.17", + "thiserror 2.0.18", +] + +[[package]] +name = "alloy-eip7928" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3231de68d5d6e75332b7489cfcc7f4dfabeba94d990a10e4b923af0e6623540" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "borsh", + "serde", ] [[package]] name = "alloy-eips" -version = "1.1.3" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4c4d7c5839d9f3a467900c625416b24328450c65702eb3d8caff8813e4d1d33" +checksum = "be47bf1b91674a5f394b9ed3c691d764fb58ba43937f1371550ff4bc8e59c295" dependencies = [ "alloy-eip2124", "alloy-eip2930", "alloy-eip7702", + "alloy-eip7928", "alloy-primitives", "alloy-rlp", "alloy-serde", "auto_impl", "borsh", "c-kzg", - "derive_more 2.1.0", + "derive_more 2.1.1", "either", "ethereum_ssz", "ethereum_ssz_derive", "serde", "serde_with 3.16.1", "sha2 0.10.9", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -268,19 +281,19 @@ dependencies = [ "alloy-rpc-types-eth", "alloy-sol-types", "auto_impl", - "derive_more 2.1.0", + "derive_more 2.1.1", "op-alloy-consensus", "op-alloy-rpc-types-engine", "op-revm", "revm", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] name = "alloy-genesis" -version = "1.1.3" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ba4b1be0988c11f0095a2380aa596e35533276b8fa6c9e06961bbfe0aebcac5" +checksum = "a59f6f520c323111650d319451de1edb1e32760029a468105b9d7b0f7c11bdf2" dependencies = [ "alloy-eips", "alloy-primitives", @@ -293,9 +306,9 @@ dependencies = [ [[package]] name = "alloy-hardforks" -version = "0.4.5" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d9a33550fc21fd77a3f8b63e99969d17660eec8dcc50a95a80f7c9964f7680b" +checksum = "83ba208044232d14d4adbfa77e57d6329f51bc1acc21f5667bb7db72d88a0831" dependencies = [ "alloy-chains", "alloy-eip2124", @@ -307,9 +320,9 @@ dependencies = [ [[package]] name = "alloy-json-abi" -version = "1.4.1" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5513d5e6bd1cba6bdcf5373470f559f320c05c8c59493b6e98912fbe6733943f" +checksum = "8708475665cc00e081c085886e68eada2f64cfa08fc668213a9231655093d4de" dependencies = [ "alloy-primitives", "alloy-sol-type-parser", @@ -319,24 +332,24 @@ dependencies = [ [[package]] name = "alloy-json-rpc" -version = "1.1.3" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f72cf87cda808e593381fb9f005ffa4d2475552b7a6c5ac33d087bf77d82abd0" +checksum = "5a24c81a56d684f525cd1c012619815ad3a1dd13b0238f069356795d84647d3c" dependencies = [ "alloy-primitives", "alloy-sol-types", "http 1.4.0", "serde", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", "tracing", ] [[package]] name = "alloy-network" -version = "1.1.3" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12aeb37b6f2e61b93b1c3d34d01ee720207c76fe447e2a2c217e433ac75b17f5" +checksum = "786c5b3ad530eaf43cda450f973fe7fb1c127b4c8990adf66709dafca25e3f6f" dependencies = [ "alloy-consensus", "alloy-consensus-any", @@ -351,18 +364,18 @@ dependencies = [ "alloy-sol-types", "async-trait", "auto_impl", - "derive_more 2.1.0", + "derive_more 2.1.1", "futures-utils-wasm", "serde", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] name = "alloy-network-primitives" -version = "1.1.3" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abd29ace62872083e30929cd9b282d82723196d196db589f3ceda67edcc05552" +checksum = "c1ed40adf21ae4be786ef5eb62db9c692f6a30f86d34452ca3f849d6390ce319" dependencies = [ "alloy-consensus", "alloy-eips", @@ -373,37 +386,37 @@ dependencies = [ [[package]] name = "alloy-primitives" -version = "1.4.1" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "355bf68a433e0fd7f7d33d5a9fc2583fde70bf5c530f63b80845f8da5505cf28" +checksum = "3b88cf92ed20685979ed1d8472422f0c6c2d010cec77caf63aaa7669cc1a7bc2" dependencies = [ "alloy-rlp", "bytes", "cfg-if", "const-hex", - "derive_more 2.1.0", + "derive_more 2.1.1", "foldhash 0.2.0", "getrandom 0.3.4", "hashbrown 0.16.1", - "indexmap 2.12.1", + "indexmap 2.13.0", "itoa", "k256", "keccak-asm", "paste", "proptest", "rand 0.9.2", + "rapidhash", "ruint", "rustc-hash", "serde", "sha3", - "tiny-keccak", ] [[package]] name = "alloy-provider" -version = "1.1.3" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b710636d7126e08003b8217e24c09f0cca0b46d62f650a841736891b1ed1fc1" +checksum = "a3ca4c15818be7ac86208aff3a91b951d14c24e1426e66624e75f2215ba5e2cc" dependencies = [ "alloy-chains", "alloy-consensus", @@ -428,13 +441,13 @@ dependencies = [ "either", "futures", "futures-utils-wasm", - "lru 0.13.0", + "lru 0.16.3", "parking_lot", "pin-project", - "reqwest 0.12.26", + "reqwest 0.12.28", "serde", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tracing", "url", @@ -443,9 +456,9 @@ dependencies = [ [[package]] name = "alloy-pubsub" -version = "1.1.3" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdd4c64eb250a18101d22ae622357c6b505e158e9165d4c7974d59082a600c5e" +checksum = "e9eb9c9371738ac47f589e40aae6e418cb5f7436ad25b87575a7f94a60ccf43b" dependencies = [ "alloy-json-rpc", "alloy-primitives", @@ -458,16 +471,16 @@ dependencies = [ "serde_json", "tokio", "tokio-stream", - "tower 0.5.2", + "tower 0.5.3", "tracing", "wasmtimer", ] [[package]] name = "alloy-rlp" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f70d83b765fdc080dbcd4f4db70d8d23fe4761f2f02ebfa9146b833900634b4" +checksum = "e93e50f64a77ad9c5470bf2ad0ca02f228da70c792a8f06634801e202579f35e" dependencies = [ "alloy-rlp-derive", "arrayvec", @@ -476,20 +489,20 @@ dependencies = [ [[package]] name = "alloy-rlp-derive" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64b728d511962dda67c1bc7ea7c03736ec275ed2cf4c35d9585298ac9ccf3b73" +checksum = "ce8849c74c9ca0f5a03da1c865e3eb6f768df816e67dd3721a398a8a7e398011" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] name = "alloy-rpc-client" -version = "1.1.3" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0882e72d2c1c0c79dcf4ab60a67472d3f009a949f774d4c17d0bdb669cfde05" +checksum = "abe0addad5b8197e851062b49dc47157444bced173b601d91e3f9b561a060a50" dependencies = [ "alloy-json-rpc", "alloy-primitives", @@ -500,12 +513,12 @@ dependencies = [ "alloy-transport-ws", "futures", "pin-project", - "reqwest 0.12.26", + "reqwest 0.12.28", "serde", "serde_json", "tokio", "tokio-stream", - "tower 0.5.2", + "tower 0.5.3", "tracing", "url", "wasmtimer", @@ -513,9 +526,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types" -version = "1.1.3" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39cf1398cb33aacb139a960fa3d8cf8b1202079f320e77e952a0b95967bf7a9f" +checksum = "74d17d4645a717f0527e491f44f6f7a75c221b9c00ccf79ddba2d26c8e0df4c3" dependencies = [ "alloy-primitives", "alloy-rpc-types-beacon", @@ -527,9 +540,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-admin" -version = "1.1.3" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65a583d2029b171301f5dcf122aa2ef443a65a373778ec76540d999691ae867d" +checksum = "ded79e60d8fd0d7c851044f8b2f2dd7fa8dfa467c577d620595d4de3c31eff7e" dependencies = [ "alloy-genesis", "alloy-primitives", @@ -539,9 +552,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-anvil" -version = "1.1.3" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3ce4c24e416bd0f17fceeb2f26cd8668df08fe19e1dc02f9d41c3b8ed1e93e0" +checksum = "2593ce5e1fd416e3b094e7671ef361f22e6944545e0e62ee309b6dfbd702225d" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", @@ -551,9 +564,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-any" -version = "1.1.3" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a63fb40ed24e4c92505f488f9dd256e2afaed17faa1b7a221086ebba74f4122" +checksum = "d0e98aabb013a71a4b67b52825f7b503e5bb6057fb3b7b2290d514b0b0574b57" dependencies = [ "alloy-consensus-any", "alloy-rpc-types-eth", @@ -562,48 +575,48 @@ dependencies = [ [[package]] name = "alloy-rpc-types-beacon" -version = "1.1.3" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16633087e23d8d75161c3a59aa183203637b817a5a8d2f662f612ccb6d129af0" +checksum = "3a647a4e3acf49182135c2333d6f9b11ab8684559ff43ef1958ed762cfe9fe0e" dependencies = [ "alloy-eips", "alloy-primitives", "alloy-rpc-types-engine", - "derive_more 2.1.0", + "derive_more 2.1.1", "ethereum_ssz", "ethereum_ssz_derive", "serde", "serde_json", "serde_with 3.16.1", - "thiserror 2.0.17", + "thiserror 2.0.18", "tree_hash", "tree_hash_derive", ] [[package]] name = "alloy-rpc-types-debug" -version = "1.1.3" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4936f579d9d10eae01772b2ab3497f9d568684f05f26f8175e12f9a1a2babc33" +checksum = "2a1dd760b6a798ee045ab6a7bbd1a02ad8bd6a64d8e18d6e41732f4fc4a4fe5c" dependencies = [ "alloy-primitives", - "derive_more 2.1.0", + "derive_more 2.1.1", "serde", "serde_with 3.16.1", ] [[package]] name = "alloy-rpc-types-engine" -version = "1.1.3" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c60bdce3be295924122732b7ecd0b2495ce4790bedc5370ca7019c08ad3f26e" +checksum = "ddc871ae69688e358cf242a6a7ee6b6e0476a03fd0256434c68daedaec086ec4" dependencies = [ "alloy-consensus", "alloy-eips", "alloy-primitives", "alloy-rlp", "alloy-serde", - "derive_more 2.1.0", + "derive_more 2.1.1", "ethereum_ssz", "ethereum_ssz_derive", "jsonwebtoken 9.3.1", @@ -614,9 +627,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-eth" -version = "1.1.3" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9eae0c7c40da20684548cbc8577b6b7447f7bf4ddbac363df95e3da220e41e72" +checksum = "5899af8417dcf89f40f88fa3bdb2f3f172605d8e167234311ee34811bbfdb0bf" dependencies = [ "alloy-consensus", "alloy-consensus-any", @@ -630,14 +643,14 @@ dependencies = [ "serde", "serde_json", "serde_with 3.16.1", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] name = "alloy-rpc-types-mev" -version = "1.1.3" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81c0dd81c24944cfbf45b5df7cd149d9cd3e354db81ccf08aa47e0e05be8ab97" +checksum = "4d4c9229424e77bd97e629fba44dbfdadebe5bfadbb1e53ad4acbc955610b6c7" dependencies = [ "alloy-consensus", "alloy-eips", @@ -650,23 +663,23 @@ dependencies = [ [[package]] name = "alloy-rpc-types-trace" -version = "1.1.3" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef206a4b8d436fbb7cf2e6a61c692d11df78f9382becc3c9a283bd58e64f0583" +checksum = "410a80e9ac786a2d885adfd7da3568e8f392da106cb5432f00eb4787689d281a" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", "alloy-serde", "serde", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] name = "alloy-rpc-types-txpool" -version = "1.1.3" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecb5a795264a02222f9534435b8f40dcbd88de8e9d586647884aae24f389ebf2" +checksum = "3a8074654c0292783d504bfa1f2691a69f420154ee9a7883f9212eaf611e60cd" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", @@ -676,9 +689,9 @@ dependencies = [ [[package]] name = "alloy-serde" -version = "1.1.3" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0df1987ed0ff2d0159d76b52e7ddfc4e4fbddacc54d2fbee765e0d14d7c01b5" +checksum = "feb73325ee881e42972a5a7bc85250f6af89f92c6ad1222285f74384a203abeb" dependencies = [ "alloy-primitives", "serde", @@ -687,9 +700,9 @@ dependencies = [ [[package]] name = "alloy-signer" -version = "1.1.3" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff69deedee7232d7ce5330259025b868c5e6a52fa8dffda2c861fb3a5889b24" +checksum = "1bea4c8f30eddb11d7ab56e83e49c814655daa78ca708df26c300c10d0189cbc" dependencies = [ "alloy-primitives", "async-trait", @@ -697,14 +710,14 @@ dependencies = [ "either", "elliptic-curve", "k256", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] name = "alloy-signer-local" -version = "1.1.3" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72cfe0be3ec5a8c1a46b2e5a7047ed41121d360d97f4405bb7c1c784880c86cb" +checksum = "c28bd71507db58477151a6fe6988fa62a4b778df0f166c3e3e1ef11d059fe5fa" dependencies = [ "alloy-consensus", "alloy-network", @@ -715,47 +728,47 @@ dependencies = [ "coins-bip39 0.12.0", "k256", "rand 0.8.5", - "thiserror 2.0.17", + "thiserror 2.0.18", "zeroize", ] [[package]] name = "alloy-sol-macro" -version = "1.4.1" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3ce480400051b5217f19d6e9a82d9010cdde20f1ae9c00d53591e4a1afbb312" +checksum = "f5fa1ca7e617c634d2bd9fa71f9ec8e47c07106e248b9fcbd3eaddc13cabd625" dependencies = [ "alloy-sol-macro-expander", "alloy-sol-macro-input", "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] name = "alloy-sol-macro-expander" -version = "1.4.1" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d792e205ed3b72f795a8044c52877d2e6b6e9b1d13f431478121d8d4eaa9028" +checksum = "27c00c0c3a75150a9dc7c8c679ca21853a137888b4e1c5569f92d7e2b15b5102" dependencies = [ "alloy-sol-macro-input", "const-hex", "heck 0.5.0", - "indexmap 2.12.1", + "indexmap 2.13.0", "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.111", + "sha3", + "syn 2.0.114", "syn-solidity", - "tiny-keccak", ] [[package]] name = "alloy-sol-macro-input" -version = "1.4.1" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bd1247a8f90b465ef3f1207627547ec16940c35597875cdc09c49d58b19693c" +checksum = "297db260eb4d67c105f68d6ba11b8874eec681caec5505eab8fbebee97f790bc" dependencies = [ "const-hex", "dunce", @@ -763,15 +776,15 @@ dependencies = [ "macro-string", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", "syn-solidity", ] [[package]] name = "alloy-sol-type-parser" -version = "1.4.1" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "954d1b2533b9b2c7959652df3076954ecb1122a28cc740aa84e7b0a49f6ac0a9" +checksum = "94b91b13181d3bcd23680fd29d7bc861d1f33fbe90fdd0af67162434aeba902d" dependencies = [ "serde", "winnow", @@ -779,9 +792,9 @@ dependencies = [ [[package]] name = "alloy-sol-types" -version = "1.4.1" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70319350969a3af119da6fb3e9bddb1bce66c9ea933600cb297c8b1850ad2a3c" +checksum = "fc442cc2a75207b708d481314098a0f8b6f7b58e3148dd8d8cc7407b0d6f9385" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -791,22 +804,22 @@ dependencies = [ [[package]] name = "alloy-transport" -version = "1.1.3" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be98b07210d24acf5b793c99b759e9a696e4a2e67593aec0487ae3b3e1a2478c" +checksum = "b321f506bd67a434aae8e8a7dfe5373bf66137c149a5f09c9e7dfb0ca43d7c91" dependencies = [ "alloy-json-rpc", "auto_impl", "base64 0.22.1", - "derive_more 2.1.0", + "derive_more 2.1.1", "futures", "futures-utils-wasm", "parking_lot", "serde", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", - "tower 0.5.2", + "tower 0.5.3", "tracing", "url", "wasmtimer", @@ -814,24 +827,24 @@ dependencies = [ [[package]] name = "alloy-transport-http" -version = "1.1.3" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4198a1ee82e562cab85e7f3d5921aab725d9bd154b6ad5017f82df1695877c97" +checksum = "30bf12879a20e1261cd39c3b101856f52d18886907a826e102538897f0d2b66e" dependencies = [ "alloy-json-rpc", "alloy-transport", - "reqwest 0.12.26", + "reqwest 0.12.28", "serde_json", - "tower 0.5.2", + "tower 0.5.3", "tracing", "url", ] [[package]] name = "alloy-transport-ipc" -version = "1.1.3" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8db249779ebc20dc265920c7e706ed0d31dbde8627818d1cbde60919b875bb0" +checksum = "b75f2334d400249e9672a1ec402536bab259e27a66201a94c3c9b3f1d3bae241" dependencies = [ "alloy-json-rpc", "alloy-pubsub", @@ -849,15 +862,14 @@ dependencies = [ [[package]] name = "alloy-transport-ws" -version = "1.1.3" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ad2344a12398d7105e3722c9b7a7044ea837128e11d453604dec6e3731a86e2" +checksum = "527a0d9c8bbc5c3215b03ad465d4ae8775384ff5faec7c41f033f087c851a9f9" dependencies = [ "alloy-pubsub", "alloy-transport", "futures", "http 1.4.0", - "rustls 0.23.35", "serde_json", "tokio", "tokio-tungstenite 0.26.2", @@ -867,30 +879,31 @@ dependencies = [ [[package]] name = "alloy-trie" -version = "0.9.1" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3412d52bb97c6c6cc27ccc28d4e6e8cf605469101193b50b0bd5813b1f990b5" +checksum = "4d7fd448ab0a017de542de1dcca7a58e7019fe0e7a34ed3f9543ebddf6aceffa" dependencies = [ "alloy-primitives", "alloy-rlp", "arrayvec", - "derive_more 2.1.0", + "derive_more 2.1.1", "nybbles", "serde", "smallvec", + "thiserror 2.0.18", "tracing", ] [[package]] name = "alloy-tx-macros" -version = "1.1.3" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "333544408503f42d7d3792bfc0f7218b643d968a03d2c0ed383ae558fb4a76d0" +checksum = "6a91d6b4c2f6574fdbcb1611e460455c326667cf5b805c6bd1640dad8e8ee4d2" dependencies = [ "darling 0.21.3", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -944,7 +957,7 @@ version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -955,14 +968,14 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] name = "anyhow" -version = "1.0.100" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" +checksum = "5f0e0fee31ef5ed1ba1316088939cea399010ed7731dba877ed44aeb407a75ea" [[package]] name = "aquamarine" @@ -975,7 +988,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -989,7 +1002,7 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -1140,7 +1153,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62945a2f7e6de02a31fe400aa489f0e0f5b2502e69f95f853adb82a96c7a6b60" dependencies = [ "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -1178,7 +1191,7 @@ dependencies = [ "num-traits", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -1267,7 +1280,7 @@ checksum = "213888f660fddcca0d257e88e54ac05bca01885f258ccdf695bafd77031bb69d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -1350,7 +1363,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -1419,13 +1432,12 @@ dependencies = [ [[package]] name = "async-compression" -version = "0.4.36" +version = "0.4.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98ec5f6c2f8bc326c994cb9e241cc257ddaba9afa8555a43cffbb5dd86efaa37" +checksum = "68650b7df54f0293fd061972a0fb05aaf4fc0879d3b3d21a638a182c5c543b9f" dependencies = [ "compression-codecs", "compression-core", - "futures-core", "pin-project-lite", "tokio", ] @@ -1472,16 +1484,16 @@ dependencies = [ "futures-lite", "parking", "polling", - "rustix 1.1.2", + "rustix 1.1.3", "slab", "windows-sys 0.61.2", ] [[package]] name = "async-lock" -version = "3.4.1" +version = "3.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd03604047cee9b6ce9de9f70c6cd540a0520c813cbd49bae61f33ab80ed1dc" +checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" dependencies = [ "event-listener 5.4.1", "event-listener-strategy", @@ -1512,7 +1524,7 @@ dependencies = [ "cfg-if", "event-listener 5.4.1", "futures-lite", - "rustix 1.1.2", + "rustix 1.1.3", ] [[package]] @@ -1527,7 +1539,7 @@ dependencies = [ "cfg-if", "futures-core", "futures-io", - "rustix 1.1.2", + "rustix 1.1.3", "signal-hook-registry", "slab", "windows-sys 0.61.2", @@ -1580,7 +1592,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -1597,7 +1609,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -1635,7 +1647,7 @@ checksum = "ffdcb70bdbc4d478427380519163274ac86e52916e10f0a8889adf0f96d3fee7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -1674,11 +1686,11 @@ dependencies = [ [[package]] name = "axum" -version = "0.8.7" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b098575ebe77cb6d14fc7f32749631a6e44edbef6b796f89b020e99ba20d425" +checksum = "8b52af3cb4058c895d37317bb27508dccc8e5f2d39454016b297bf4a400597b8" dependencies = [ - "axum-core 0.5.5", + "axum-core 0.5.6", "base64 0.22.1", "bytes", "form_urlencoded", @@ -1702,7 +1714,7 @@ dependencies = [ "sync_wrapper 1.0.2", "tokio", "tokio-tungstenite 0.28.0", - "tower 0.5.2", + "tower 0.5.3", "tower-layer", "tower-service", "tracing", @@ -1727,9 +1739,9 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.5.5" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59446ce19cd142f8833f856eb31f3eb097812d1479ab224f54d72428ca21ea22" +checksum = "08c78f31d7b1291f7ee735c1c6780ccde7785daae9a9206026862dab7d8792d1" dependencies = [ "bytes", "futures-core", @@ -1746,9 +1758,9 @@ dependencies = [ [[package]] name = "az" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973" +checksum = "be5eb007b7cacc6c660343e96f650fedf4b5a77512399eb952ca6642cf8d13f7" [[package]] name = "backon" @@ -1817,9 +1829,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "base64ct" -version = "1.8.1" +version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e050f626429857a27ddccb31e0aca21356bfa709c04041aefddac081a8f068a" +checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" [[package]] name = "basic-cookies" @@ -1877,7 +1889,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -1895,7 +1907,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -1949,7 +1961,7 @@ checksum = "238b90427dfad9da4a9abd60f3ec1cdee6b80454bde49ed37f1781dd8e9dc7f9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -2104,7 +2116,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -2149,9 +2161,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.19.0" +version = "3.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" +checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" [[package]] name = "byte-slice-cast" @@ -2167,9 +2179,9 @@ checksum = "175812e0be2bccb6abe50bb8d566126198344f707e304f45c648fd8f2cc0365e" [[package]] name = "bytemuck" -version = "1.24.0" +version = "1.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" +checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" [[package]] name = "byteorder" @@ -2179,9 +2191,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" dependencies = [ "serde", ] @@ -2239,6 +2251,16 @@ dependencies = [ "serde", ] +[[package]] +name = "cargo-platform" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87a0c0e6148f11f01f32650a2ea02d532b2ad4e81d8bd41e6e565b5adc5e6082" +dependencies = [ + "serde", + "serde_core", +] + [[package]] name = "cargo_metadata" version = "0.14.2" @@ -2246,7 +2268,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa" dependencies = [ "camino", - "cargo-platform", + "cargo-platform 0.1.9", "semver 1.0.27", "serde", "serde_json", @@ -2259,7 +2281,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" dependencies = [ "camino", - "cargo-platform", + "cargo-platform 0.1.9", "semver 1.0.27", "serde", "serde_json", @@ -2268,16 +2290,16 @@ dependencies = [ [[package]] name = "cargo_metadata" -version = "0.19.2" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd5eb614ed4c27c5d706420e4320fbe3216ab31fa1c33cd8246ac36dae4479ba" +checksum = "ef987d17b0a113becdd19d3d0022d04d7ef41f9efe4f3fb63ac44ba61df3ade9" dependencies = [ "camino", - "cargo-platform", + "cargo-platform 0.3.2", "semver 1.0.27", "serde", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -2341,9 +2363,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chrono" -version = "0.4.42" +version = "0.4.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" +checksum = "fac4744fb15ae8337dc853fee7fb3f4e48c0fbaa23d0afe49c447b4fab126118" dependencies = [ "iana-time-zone", "js-sys", @@ -2412,9 +2434,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.53" +version = "4.5.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e340e012a1bf4935f5282ed1436d1489548e8f72308207ea5df0e23d2d03f8" +checksum = "6899ea499e3fb9305a65d5ebf6e3d2248c5fab291f300ad0a704fbe142eae31a" dependencies = [ "clap_builder", "clap_derive", @@ -2422,9 +2444,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.53" +version = "4.5.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d76b5d13eaa18c901fd2f7fca939fefe3a0727a953561fefdf3b2922b8569d00" +checksum = "7b12c8b680195a62a8364d16b8447b01b6c2c8f9aaf68bee653be34d4245e238" dependencies = [ "anstream", "anstyle", @@ -2434,21 +2456,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.49" +version = "4.5.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" +checksum = "a92793da1a46a5f2a02a6f4c46c6496b28c43638adea8306fcb0caa1634f24e5" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] name = "clap_lex" -version = "0.7.6" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" +checksum = "c3e64b0cc0439b12df2fa678eae89a1c56a529fd067a9115f7827f1fffd22b32" [[package]] name = "coins-bip32" @@ -2561,11 +2583,11 @@ checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" [[package]] name = "colored" -version = "3.0.0" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fde0e0ec90c9dfb3b4b1a0891a7dcd0e2bffde2f7efed5fe7c9bb00e5bfb915e" +checksum = "faf9468729b8cbcea668e36183cb69d317348c2e08e994829fb56ebfdfbaac34" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -2580,9 +2602,9 @@ dependencies = [ [[package]] name = "comfy-table" -version = "7.2.1" +version = "7.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b03b7db8e0b4b2fdad6c551e634134e99ec000e5c8c3b6856c65e8bbaded7a3b" +checksum = "958c5d6ecf1f214b4c2bbbbf6ab9523a864bd136dcf71a7e8904799acfe1ad47" dependencies = [ "crossterm 0.29.0", "unicode-segmentation", @@ -2622,9 +2644,9 @@ dependencies = [ [[package]] name = "compression-codecs" -version = "0.4.35" +version = "0.4.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0f7ac3e5b97fdce45e8922fb05cae2c37f7bbd63d30dd94821dacfd8f3f2bf2" +checksum = "00828ba6fd27b45a448e57dbfe84f1029d4c9f26b368157e9a448a5f49a2ec2a" dependencies = [ "brotli", "compression-core", @@ -2921,7 +2943,7 @@ dependencies = [ "crossterm_winapi", "document-features", "parking_lot", - "rustix 1.1.2", + "rustix 1.1.3", "winapi", ] @@ -3015,7 +3037,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -3048,6 +3070,16 @@ dependencies = [ "darling_macro 0.21.3", ] +[[package]] +name = "darling" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" +dependencies = [ + "darling_core 0.23.0", + "darling_macro 0.23.0", +] + [[package]] name = "darling_core" version = "0.13.4" @@ -3073,7 +3105,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.11.1", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -3088,7 +3120,20 @@ dependencies = [ "quote", "serde", "strsim 0.11.1", - "syn 2.0.111", + "syn 2.0.114", +] + +[[package]] +name = "darling_core" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0" +dependencies = [ + "ident_case", + "proc-macro2", + "quote", + "strsim 0.11.1", + "syn 2.0.114", ] [[package]] @@ -3110,7 +3155,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core 0.20.11", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -3121,7 +3166,18 @@ checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ "darling_core 0.21.3", "quote", - "syn 2.0.111", + "syn 2.0.114", +] + +[[package]] +name = "darling_macro" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" +dependencies = [ + "darling_core 0.23.0", + "quote", + "syn 2.0.114", ] [[package]] @@ -3153,15 +3209,15 @@ dependencies = [ [[package]] name = "data-encoding" -version = "2.9.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" +checksum = "d7a1e2f27636f116493b8b860f5546edb47c8d8f8ea73e1d2a20be88e28d1fea" [[package]] name = "data-encoding-macro" -version = "0.1.18" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47ce6c96ea0102f01122a185683611bd5ac8d99e62bc59dd12e6bda344ee673d" +checksum = "8142a83c17aa9461d637e649271eae18bf2edd00e91f2e105df36c3c16355bdb" dependencies = [ "data-encoding", "data-encoding-macro-internal", @@ -3169,12 +3225,12 @@ dependencies = [ [[package]] name = "data-encoding-macro-internal" -version = "0.1.16" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d162beedaa69905488a8da94f5ac3edb4dd4788b732fadb7bd120b2625c1976" +checksum = "7ab67060fc6b8ef687992d439ca0fa36e7ed17e9a0b16b25b601e8757df720de" dependencies = [ "data-encoding", - "syn 2.0.111", + "syn 1.0.109", ] [[package]] @@ -3266,7 +3322,7 @@ checksum = "ef941ded77d15ca19b40374869ac6000af1c9f2a4c0f3d4c70926287e6364a8f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -3277,7 +3333,7 @@ checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -3298,7 +3354,7 @@ dependencies = [ "darling 0.20.11", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -3308,7 +3364,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -3321,7 +3377,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version 0.4.1", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -3335,11 +3391,11 @@ dependencies = [ [[package]] name = "derive_more" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10b768e943bed7bf2cab53df09f4bc34bfd217cdb57d971e769874c9a6710618" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" dependencies = [ - "derive_more-impl 2.1.0", + "derive_more-impl 2.1.1", ] [[package]] @@ -3350,20 +3406,20 @@ checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] name = "derive_more-impl" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d286bfdaf75e988b4a78e013ecd79c581e06399ab53fbacd2d916c2f904f30b" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" dependencies = [ "convert_case 0.10.0", "proc-macro2", "quote", "rustc_version 0.4.1", - "syn 2.0.111", + "syn 2.0.114", "unicode-xid", ] @@ -3452,7 +3508,7 @@ dependencies = [ "libc", "option-ext", "redox_users 0.5.2", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -3507,7 +3563,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -3595,7 +3651,7 @@ dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -3807,7 +3863,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -3827,7 +3883,7 @@ checksum = "8ca9601fb2d62598ee17836250842873a413586e5d7ed88b356e38ddbb0ec631" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -3853,7 +3909,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -4060,7 +4116,7 @@ dependencies = [ "darling 0.20.11", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -4129,7 +4185,7 @@ dependencies = [ "reqwest 0.11.27", "serde", "serde_json", - "syn 2.0.111", + "syn 2.0.114", "toml", "walkdir", ] @@ -4147,7 +4203,7 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -4173,7 +4229,7 @@ dependencies = [ "serde", "serde_json", "strum 0.26.3", - "syn 2.0.111", + "syn 2.0.114", "tempfile", "thiserror 1.0.69", "tiny-keccak", @@ -4428,14 +4484,13 @@ checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" [[package]] name = "filetime" -version = "0.2.26" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc0505cd1b6fa6580283f6bdf70a73fcf4aba1184038c90902b92b3dd0df63ed" +checksum = "f98844151eee8917efc50bd9e8318cb963ae8b297431495d3f758616ea5c57db" dependencies = [ "cfg-if", "libc", "libredox", - "windows-sys 0.60.2", ] [[package]] @@ -4467,9 +4522,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.1.5" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" dependencies = [ "crc32fast", "miniz_oxide", @@ -4477,8 +4532,8 @@ dependencies = [ [[package]] name = "flux" -version = "0.0.36" -source = "git+https://github.com/gattaca-com/flux#16973424f7eb3eac68f80cc305a03b948486805d" +version = "0.0.37" +source = "git+https://github.com/gattaca-com/flux#6119504e55e6db4fba88bcaacc78637b7fff95be" dependencies = [ "bitcode", "core_affinity", @@ -4501,7 +4556,7 @@ dependencies = [ [[package]] name = "flux-communication" version = "0.0.26" -source = "git+https://github.com/gattaca-com/flux#16973424f7eb3eac68f80cc305a03b948486805d" +source = "git+https://github.com/gattaca-com/flux#6119504e55e6db4fba88bcaacc78637b7fff95be" dependencies = [ "directories", "flux-timing", @@ -4514,20 +4569,21 @@ dependencies = [ [[package]] name = "flux-network" -version = "0.0.7" -source = "git+https://github.com/gattaca-com/flux#16973424f7eb3eac68f80cc305a03b948486805d" +version = "0.0.8" +source = "git+https://github.com/gattaca-com/flux#6119504e55e6db4fba88bcaacc78637b7fff95be" dependencies = [ "flux-communication", "flux-timing", "flux-utils", + "libc", "mio", "tracing", ] [[package]] name = "flux-timing" -version = "0.0.14" -source = "git+https://github.com/gattaca-com/flux#16973424f7eb3eac68f80cc305a03b948486805d" +version = "0.0.15" +source = "git+https://github.com/gattaca-com/flux#6119504e55e6db4fba88bcaacc78637b7fff95be" dependencies = [ "bitcode", "chrono", @@ -4545,7 +4601,7 @@ dependencies = [ [[package]] name = "flux-utils" version = "0.0.22" -source = "git+https://github.com/gattaca-com/flux#16973424f7eb3eac68f80cc305a03b948486805d" +source = "git+https://github.com/gattaca-com/flux#6119504e55e6db4fba88bcaacc78637b7fff95be" dependencies = [ "core_affinity", "directories", @@ -4711,7 +4767,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -4782,14 +4838,14 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", "js-sys", "libc", - "wasi", + "wasi 0.11.1+wasi-snapshot-preview1", "wasm-bindgen", ] @@ -4825,9 +4881,9 @@ checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" [[package]] name = "git2" -version = "0.20.3" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e2b37e2f62729cdada11f0e6b3b6fe383c69c29fc619e391223e12856af308c" +checksum = "7b88256088d75a56f8ecfa070513a775dd9107f6530ef14919dac831af9cfe2b" dependencies = [ "bitflags 2.10.0", "libc", @@ -4984,7 +5040,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.12.1", + "indexmap 2.13.0", "slab", "tokio", "tokio-util", @@ -4993,9 +5049,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" +checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54" dependencies = [ "atomic-waker", "bytes", @@ -5003,7 +5059,7 @@ dependencies = [ "futures-core", "futures-sink", "http 1.4.0", - "indexmap 2.12.1", + "indexmap 2.13.0", "slab", "tokio", "tokio-util", @@ -5060,6 +5116,8 @@ version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" dependencies = [ + "allocator-api2", + "equivalent", "foldhash 0.2.0", "serde", "serde_core", @@ -5121,7 +5179,7 @@ dependencies = [ "alloy-consensus", "alloy-primitives", "alloy-rlp", - "axum 0.8.7", + "axum 0.8.8", "backtrace", "bytes", "chrono", @@ -5158,7 +5216,7 @@ dependencies = [ "tree_hash", "tree_hash_derive", "url", - "uuid 1.19.0", + "uuid 1.20.0", ] [[package]] @@ -5171,7 +5229,8 @@ dependencies = [ "alloy-rlp", "askama", "async-trait", - "axum 0.8.7", + "axum 0.8.8", + "bitflags 2.10.0", "bytes", "chrono", "crossbeam-channel", @@ -5184,6 +5243,7 @@ dependencies = [ "eyre", "flate2", "flux", + "flux-network", "futures", "helix-common", "helix-types", @@ -5223,7 +5283,7 @@ dependencies = [ "tree_hash", "tree_hash_derive", "url", - "uuid 1.19.0", + "uuid 1.20.0", "zstd 0.13.3", ] @@ -5243,7 +5303,7 @@ dependencies = [ "bytes", "clap", "dashmap 5.5.3", - "derive_more 2.1.0", + "derive_more 2.1.1", "futures", "helix-types", "jsonrpsee", @@ -5273,6 +5333,7 @@ dependencies = [ "alloy-eips", "alloy-primitives", "alloy-rpc-types", + "bitflags 2.10.0", "bls", "blst", "criterion", @@ -5337,7 +5398,7 @@ dependencies = [ "rand 0.9.2", "ring 0.17.14", "serde", - "thiserror 2.0.17", + "thiserror 2.0.18", "tinyvec", "tokio", "tracing", @@ -5361,7 +5422,7 @@ dependencies = [ "resolv-conf", "serde", "smallvec", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tracing", ] @@ -5569,7 +5630,7 @@ dependencies = [ "bytes", "futures-channel", "futures-core", - "h2 0.4.12", + "h2 0.4.13", "http 1.4.0", "http-body 1.0.1", "httparse", @@ -5606,13 +5667,13 @@ dependencies = [ "hyper 1.8.1", "hyper-util", "log", - "rustls 0.23.35", + "rustls 0.23.36", "rustls-native-certs", "rustls-pki-types", "tokio", "tokio-rustls 0.26.4", "tower-service", - "webpki-roots 1.0.4", + "webpki-roots 1.0.6", ] [[package]] @@ -5655,14 +5716,13 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.19" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "727805d60e7938b76b826a6ef209eb70eaa1812794f9424d4a4e2d740662df5f" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" dependencies = [ "base64 0.22.1", "bytes", "futures-channel", - "futures-core", "futures-util", "http 1.4.0", "http-body 1.0.1", @@ -5671,7 +5731,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.6.1", + "socket2 0.6.2", "tokio", "tower-service", "tracing", @@ -5679,9 +5739,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.64" +version = "0.1.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -5689,7 +5749,7 @@ dependencies = [ "js-sys", "log", "wasm-bindgen", - "windows-core 0.62.2", + "windows-core 0.57.0", ] [[package]] @@ -5854,7 +5914,7 @@ checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -5895,9 +5955,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.12.1" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2" +checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" dependencies = [ "equivalent", "hashbrown 0.16.1", @@ -5946,15 +6006,15 @@ dependencies = [ [[package]] name = "instability" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6778b0196eefee7df739db78758e5cf9b37412268bfa5650bfeed028aed20d9c" +checksum = "357b7205c6cd18dd2c86ed312d1e70add149aea98e7ef72b9fdf0270e555c11d" dependencies = [ - "darling 0.20.11", + "darling 0.23.0", "indoc", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -5976,9 +6036,9 @@ dependencies = [ [[package]] name = "interprocess" -version = "2.2.3" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d941b405bd2322993887859a8ee6ac9134945a24ec5ec763a8a962fc64dfec2d" +checksum = "53bf2b0e0785c5394a7392f66d7c4fb9c653633c29b27a932280da3cb344c66a" dependencies = [ "doctest-file", "futures-core", @@ -6009,9 +6069,9 @@ checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" [[package]] name = "iri-string" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f867b9d1d896b67beb18518eda36fdb77a32ea590de864f1325b294a6d14397" +checksum = "c91338f0783edbd6195decb37bae672fd3b165faffb89bf7b9e6942f8b1a731a" dependencies = [ "memchr", "serde", @@ -6070,9 +6130,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.15" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" [[package]] name = "jni" @@ -6108,9 +6168,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.83" +version = "0.3.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8" +checksum = "8c942ebf8e95485ca0d52d97da7c5a2c387d0e7f0ba4c35e93bfcaee045955b3" dependencies = [ "once_cell", "wasm-bindgen", @@ -6147,11 +6207,11 @@ dependencies = [ "http 1.4.0", "jsonrpsee-core", "pin-project", - "rustls 0.23.35", + "rustls 0.23.36", "rustls-pki-types", "rustls-platform-verifier", "soketto", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tokio-rustls 0.26.4", "tokio-util", @@ -6179,10 +6239,10 @@ dependencies = [ "rustc-hash", "serde", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tokio-stream", - "tower 0.5.2", + "tower 0.5.3", "tracing", "wasm-bindgen-futures", ] @@ -6200,13 +6260,13 @@ dependencies = [ "hyper-util", "jsonrpsee-core", "jsonrpsee-types", - "rustls 0.23.35", + "rustls 0.23.36", "rustls-platform-verifier", "serde", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", - "tower 0.5.2", + "tower 0.5.3", "url", ] @@ -6220,7 +6280,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -6242,11 +6302,11 @@ dependencies = [ "serde", "serde_json", "soketto", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tokio-stream", "tokio-util", - "tower 0.5.2", + "tower 0.5.3", "tracing", ] @@ -6259,7 +6319,7 @@ dependencies = [ "http 1.4.0", "serde", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -6271,7 +6331,7 @@ dependencies = [ "jsonrpsee-client-transport", "jsonrpsee-core", "jsonrpsee-types", - "tower 0.5.2", + "tower 0.5.3", ] [[package]] @@ -6284,7 +6344,7 @@ dependencies = [ "jsonrpsee-client-transport", "jsonrpsee-core", "jsonrpsee-types", - "tower 0.5.2", + "tower 0.5.3", "url", ] @@ -6343,9 +6403,9 @@ dependencies = [ [[package]] name = "keccak-asm" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "505d1856a39b200489082f90d897c3f07c455563880bc5952e38eabf731c83b6" +checksum = "b646a74e746cd25045aa0fd42f4f7f78aa6d119380182c7e63a5593c4ab8df6f" dependencies = [ "digest 0.10.7", "sha3-asm", @@ -6449,9 +6509,9 @@ checksum = "db13adb97ab515a3691f56e4dbab09283d0b86cb45abd991d8634a9d6f501760" [[package]] name = "libc" -version = "0.2.178" +version = "0.2.180" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" +checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc" [[package]] name = "libgit2-sys" @@ -6477,9 +6537,9 @@ dependencies = [ [[package]] name = "libm" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "libp2p-identity" @@ -6495,7 +6555,7 @@ dependencies = [ "multihash", "quick-protobuf", "sha2 0.10.9", - "thiserror 2.0.17", + "thiserror 2.0.18", "tracing", "zeroize", ] @@ -6513,13 +6573,13 @@ dependencies = [ [[package]] name = "libredox" -version = "0.1.10" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" +checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" dependencies = [ "bitflags 2.10.0", "libc", - "redox_syscall", + "redox_syscall 0.7.0", ] [[package]] @@ -6615,11 +6675,11 @@ dependencies = [ [[package]] name = "lru" -version = "0.13.0" +version = "0.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "227748d55f2f0ab4735d87fd623798cb6b664512fe979705f829c9f81c934465" +checksum = "a1dc47f592c06f33f8e3aea9591776ec7c9f9e4124778ff8a3c3b87159f7e593" dependencies = [ - "hashbrown 0.15.5", + "hashbrown 0.16.1", ] [[package]] @@ -6655,12 +6715,9 @@ checksum = "08ab2867e3eeeca90e844d1940eab391c9dc5228783db2ed999acbc0a9ed375a" [[package]] name = "mach2" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a1b95cd5421ec55b445b5ae102f5ea0e768de1f82bd3001e11f426c269c3aea" -dependencies = [ - "libc", -] +checksum = "dae608c151f68243f2b000364e1f7b186d9c29845f7d2d85bd31b9ad77ad552b" [[package]] name = "macro-string" @@ -6670,7 +6727,7 @@ checksum = "1b27834086c65ec3f9387b096d66e99f221cf081c2b738042aa252bcd41204e3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -6681,13 +6738,13 @@ checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" [[package]] name = "match-lookup" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1265724d8cb29dbbc2b0f06fffb8bf1a8c0cf73a78eede9ba73a4a66c52a981e" +checksum = "757aee279b8bdbb9f9e676796fd459e4207a1f986e87886700abf589f5abf771" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.114", ] [[package]] @@ -6729,9 +6786,9 @@ checksum = "33746aadcb41349ec291e7f2f0a3aa6834d1d7c58066fb4b01f68efc4c4b7631" [[package]] name = "memchr" -version = "2.7.6" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" [[package]] name = "memmap2" @@ -6764,25 +6821,25 @@ dependencies = [ [[package]] name = "metastruct" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d74f54f231f9a18d77393ecc5cc7ab96709b2a61ee326c2b2b291009b0cc5a07" +checksum = "969a1be9bd80794bdf93b23ab552c2ec6f3e83b33164824553fd996cdad513b8" dependencies = [ "metastruct_macro", ] [[package]] name = "metastruct_macro" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "985e7225f3a4dfbec47a0c6a730a874185fda840d365d7bbd6ba199dd81796d5" +checksum = "de9164f767d73a507c19205868c84da411dc7795f4bdabf497d3dd93cfef9930" dependencies = [ - "darling 0.13.4", - "itertools 0.10.5", + "darling 0.23.0", + "itertools 0.14.0", "proc-macro2", "quote", "smallvec", - "syn 1.0.109", + "syn 2.0.114", ] [[package]] @@ -6805,14 +6862,13 @@ dependencies = [ [[package]] name = "metrics-derive" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3dbdd96ed57d565ec744cba02862d707acf373c5772d152abae6ec5c4e24f6c" +checksum = "37a87f4b19620e4c561f7b48f5e6ca085b1780def671696a6a3d9d0c137360ec" dependencies = [ "proc-macro2", "quote", - "regex", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -6822,7 +6878,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd7399781913e5393588a8d8c6a2867bf85fb38eaf2502fdce465aad2dc6f034" dependencies = [ "base64 0.22.1", - "indexmap 2.12.1", + "indexmap 2.13.0", "metrics 0.24.3", "metrics-util", "quanta", @@ -6831,9 +6887,9 @@ dependencies = [ [[package]] name = "metrics-process" -version = "2.4.2" +version = "2.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f615e08e049bd14a44c4425415782efb9bcd479fc1e19ddeb971509074c060d0" +checksum = "4268d87f64a752f5a651314fc683f04da10be65701ea3e721ba4d74f79163cac" dependencies = [ "libc", "libproc", @@ -6938,15 +6994,15 @@ checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" dependencies = [ "libc", "log", - "wasi", + "wasi 0.11.1+wasi-snapshot-preview1", "windows-sys 0.61.2", ] [[package]] name = "mockito" -version = "1.7.1" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e0603425789b4a70fcc4ac4f5a46a566c116ee3e2a6b768dc623f7719c611de" +checksum = "90820618712cab19cfc46b274c6c22546a82affcb3c3bdf0f29e3db8e1bb92c0" dependencies = [ "assert-json-diff", "bytes", @@ -6990,9 +7046,9 @@ dependencies = [ [[package]] name = "moka" -version = "0.12.11" +version = "0.12.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8261cd88c312e0004c1d51baad2980c66528dfdb2bee62003e643a4d8f86b077" +checksum = "b4ac832c50ced444ef6be0767a008b02c106a909ba79d1d830501e94b96f6b7e" dependencies = [ "crossbeam-channel", "crossbeam-epoch", @@ -7000,10 +7056,9 @@ dependencies = [ "equivalent", "parking_lot", "portable-atomic", - "rustc_version 0.4.1", "smallvec", "tagptr", - "uuid 1.19.0", + "uuid 1.20.0", ] [[package]] @@ -7068,7 +7123,7 @@ dependencies = [ "libc", "log", "openssl", - "openssl-probe", + "openssl-probe 0.1.6", "openssl-sys", "schannel", "security-framework 2.11.1", @@ -7143,15 +7198,18 @@ dependencies = [ [[package]] name = "notify-types" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e0826a989adedc2a244799e823aece04662b66609d96af8dff7ac6df9a8925d" +checksum = "42b8cfee0e339a0337359f3c88165702ac6e600dc01c0cc9579a92d62b08477a" +dependencies = [ + "bitflags 2.10.0", +] [[package]] name = "ntapi" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" +checksum = "c70f219e21142367c70c0b30c6a9e3a14d55b4d12a204d897fbec83a0363f081" dependencies = [ "winapi", ] @@ -7162,7 +7220,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -7217,9 +7275,9 @@ dependencies = [ [[package]] name = "num-conv" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050" [[package]] name = "num-format" @@ -7301,7 +7359,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -7315,9 +7373,9 @@ dependencies = [ [[package]] name = "nybbles" -version = "0.4.6" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c4b5ecbd0beec843101bffe848217f770e8b8da81d8355b7d6e226f2199b3dc" +checksum = "0d49ff0c0d00d4a502b39df9af3a525e1efeb14b9dabb5bb83335284c1309210" dependencies = [ "alloy-rlp", "cfg-if", @@ -7369,10 +7427,10 @@ dependencies = [ "alloy-primitives", "alloy-rlp", "alloy-serde", - "derive_more 2.1.0", + "derive_more 2.1.1", "serde", "serde_with 3.16.1", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -7387,13 +7445,13 @@ dependencies = [ "alloy-rlp", "alloy-rpc-types-engine", "alloy-serde", - "derive_more 2.1.0", + "derive_more 2.1.1", "ethereum_ssz", "ethereum_ssz_derive", "op-alloy-consensus", "serde", "snap", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -7461,7 +7519,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -7470,11 +7528,17 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" +[[package]] +name = "openssl-probe" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" + [[package]] name = "openssl-src" -version = "300.5.4+3.5.4" +version = "300.5.5+3.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507b3792995dae9b0df8a1c1e3771e8418b7c2d9f0baeba32e6fe8b06c7cb72" +checksum = "3f1787d533e03597a7934fd0a765f0d28e94ecc5fb7789f8053b1e699a56f709" dependencies = [ "cc", ] @@ -7502,7 +7566,7 @@ dependencies = [ "futures-sink", "js-sys", "pin-project-lite", - "thiserror 2.0.17", + "thiserror 2.0.18", "tracing", ] @@ -7516,7 +7580,7 @@ dependencies = [ "futures-sink", "js-sys", "pin-project-lite", - "thiserror 2.0.17", + "thiserror 2.0.18", "tracing", ] @@ -7530,7 +7594,7 @@ dependencies = [ "bytes", "http 1.4.0", "opentelemetry 0.29.1", - "reqwest 0.12.26", + "reqwest 0.12.28", "tracing", ] @@ -7544,7 +7608,7 @@ dependencies = [ "bytes", "http 1.4.0", "opentelemetry 0.31.0", - "reqwest 0.12.26", + "reqwest 0.12.28", ] [[package]] @@ -7560,8 +7624,8 @@ dependencies = [ "opentelemetry-proto 0.29.0", "opentelemetry_sdk 0.29.0", "prost 0.13.5", - "reqwest 0.12.26", - "thiserror 2.0.17", + "reqwest 0.12.28", + "thiserror 2.0.18", "tokio", "tonic 0.12.3", "tracing", @@ -7578,11 +7642,11 @@ dependencies = [ "opentelemetry-http 0.31.0", "opentelemetry-proto 0.31.0", "opentelemetry_sdk 0.31.0", - "prost 0.14.1", - "reqwest 0.12.26", - "thiserror 2.0.17", + "prost 0.14.3", + "reqwest 0.12.28", + "thiserror 2.0.18", "tokio", - "tonic 0.14.2", + "tonic 0.14.3", "tracing", ] @@ -7606,8 +7670,8 @@ checksum = "a7175df06de5eaee9909d4805a3d07e28bb752c34cab57fa9cff549da596b30f" dependencies = [ "opentelemetry 0.31.0", "opentelemetry_sdk 0.31.0", - "prost 0.14.1", - "tonic 0.14.2", + "prost 0.14.3", + "tonic 0.14.3", "tonic-prost", ] @@ -7631,7 +7695,7 @@ dependencies = [ "percent-encoding", "rand 0.9.2", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tokio-stream", "tracing", @@ -7649,7 +7713,7 @@ dependencies = [ "opentelemetry 0.31.0", "percent-encoding", "rand 0.9.2", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -7715,7 +7779,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -7742,7 +7806,7 @@ checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.5.18", "smallvec", "windows-link", ] @@ -7828,9 +7892,9 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pest" -version = "2.8.4" +version = "2.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbcfd20a6d4eeba40179f05735784ad32bdaef05ce8e8af05f180d45bb3e7e22" +checksum = "e0848c601009d37dfa3430c4666e147e49cdcf1b92ecd3e63657d8a5f19da662" dependencies = [ "memchr", "ucd-trie", @@ -7843,7 +7907,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.12.1", + "indexmap 2.13.0", ] [[package]] @@ -7907,7 +7971,7 @@ dependencies = [ "phf_shared 0.11.3", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -7920,7 +7984,7 @@ dependencies = [ "phf_shared 0.13.1", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -7964,7 +8028,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -8044,7 +8108,7 @@ dependencies = [ "concurrent-queue", "hermit-abi", "pin-project-lite", - "rustix 1.1.2", + "rustix 1.1.3", "windows-sys 0.61.2", ] @@ -8062,15 +8126,15 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.11.1" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" [[package]] name = "postgres-protocol" -version = "0.6.9" +version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbef655056b916eb868048276cfd5d6a7dea4f81560dfd047f97c8c6fe3fcfd4" +checksum = "3ee9dd5fe15055d2b6806f4736aa0c9637217074e224bbec46d4041b91bb9491" dependencies = [ "base64 0.22.1", "byteorder", @@ -8086,9 +8150,9 @@ dependencies = [ [[package]] name = "postgres-types" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef4605b7c057056dd35baeb6ac0c0338e4975b1f2bef0f65da953285eb007095" +checksum = "54b858f82211e84682fecd373f68e1ceae642d8d751a1ebd13f33de6257b3e20" dependencies = [ "bytes", "fallible-iterator", @@ -8153,7 +8217,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -8185,7 +8249,7 @@ version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" dependencies = [ - "toml_edit 0.23.9", + "toml_edit 0.23.10+spec-1.0.0", ] [[package]] @@ -8231,14 +8295,14 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] name = "proc-macro2" -version = "1.0.103" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] @@ -8265,7 +8329,7 @@ checksum = "25485360a54d6861439d60facef26de713b1e126bf015ec8f98239467a2b82f7" dependencies = [ "bitflags 2.10.0", "procfs-core 0.18.0", - "rustix 1.1.2", + "rustix 1.1.3", ] [[package]] @@ -8306,9 +8370,9 @@ dependencies = [ [[package]] name = "proptest" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bee689443a2bd0a16ab0348b52ee43e3b2d1b1f931c8aa5c9f8de4c86fbe8c40" +checksum = "37566cb3fdacef14c0737f9546df7cfeadbfbc9fef10991038bf5015d0c80532" dependencies = [ "bit-set 0.8.0", "bit-vec 0.8.0", @@ -8345,12 +8409,12 @@ dependencies = [ [[package]] name = "prost" -version = "0.14.1" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7231bd9b3d3d33c86b58adbac74b5ec0ad9f496b19d22801d773636feaa95f3d" +checksum = "d2ea70524a2f82d518bce41317d0fae74151505651af45faf1ffbd6fd33f0568" dependencies = [ "bytes", - "prost-derive 0.14.1", + "prost-derive 0.14.3", ] [[package]] @@ -8370,7 +8434,7 @@ dependencies = [ "prost 0.12.6", "prost-types", "regex", - "syn 2.0.111", + "syn 2.0.114", "tempfile", ] @@ -8384,7 +8448,7 @@ dependencies = [ "itertools 0.12.1", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -8397,20 +8461,20 @@ dependencies = [ "itertools 0.14.0", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] name = "prost-derive" -version = "0.14.1" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9120690fafc389a67ba3803df527d0ec9cbbc9cc45e4cc20b332996dfb672425" +checksum = "27c6023962132f4b30eb4c172c91ce92d933da334c59c23cddee82358ddafb0b" dependencies = [ "anyhow", "itertools 0.14.0", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -8463,7 +8527,7 @@ dependencies = [ "libc", "once_cell", "raw-cpuid", - "wasi", + "wasi 0.11.1+wasi-snapshot-preview1", "web-sys", "winapi", ] @@ -8495,9 +8559,9 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash", - "rustls 0.23.35", - "socket2 0.6.1", - "thiserror 2.0.17", + "rustls 0.23.36", + "socket2 0.6.2", + "thiserror 2.0.18", "tokio", "tracing", "web-time", @@ -8515,10 +8579,10 @@ dependencies = [ "rand 0.9.2", "ring 0.17.14", "rustc-hash", - "rustls 0.23.35", + "rustls 0.23.36", "rustls-pki-types", "slab", - "thiserror 2.0.17", + "thiserror 2.0.18", "tinyvec", "tracing", "web-time", @@ -8533,16 +8597,16 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.6.1", + "socket2 0.6.2", "tracing", "windows-sys 0.60.2", ] [[package]] name = "quote" -version = "1.0.42" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" dependencies = [ "proc-macro2", ] @@ -8578,7 +8642,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" dependencies = [ "rand_chacha 0.9.0", - "rand_core 0.9.3", + "rand_core 0.9.5", "serde", ] @@ -8599,7 +8663,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core 0.9.3", + "rand_core 0.9.5", ] [[package]] @@ -8608,14 +8672,14 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", ] [[package]] name = "rand_core" -version = "0.9.3" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" dependencies = [ "getrandom 0.3.4", "serde", @@ -8636,7 +8700,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a" dependencies = [ - "rand_core 0.9.3", + "rand_core 0.9.5", ] [[package]] @@ -8645,7 +8709,17 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f703f4665700daf5512dcca5f43afa6af89f09db47fb56be587f80636bda2d41" dependencies = [ - "rand_core 0.9.3", + "rand_core 0.9.5", +] + +[[package]] +name = "rapidhash" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84816e4c99c467e92cf984ee6328caa976dfecd33a673544489d79ca2caaefe5" +dependencies = [ + "rand 0.9.2", + "rustversion", ] [[package]] @@ -8722,13 +8796,22 @@ dependencies = [ "bitflags 2.10.0", ] +[[package]] +name = "redox_syscall" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f3fe0889e69e2ae9e41f4d6c4c0181701d00e4697b356fb1f74173a5e0ee27" +dependencies = [ + "bitflags 2.10.0", +] + [[package]] name = "redox_users" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", "libredox", "thiserror 1.0.69", ] @@ -8739,9 +8822,9 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", "libredox", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -8761,7 +8844,7 @@ checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -8806,14 +8889,14 @@ dependencies = [ "quote", "refinery-core", "regex", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] name = "regex" -version = "1.12.2" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" dependencies = [ "aho-corasick", "memchr", @@ -8823,9 +8906,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" dependencies = [ "aho-corasick", "memchr", @@ -8834,9 +8917,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" +checksum = "a96887878f22d7bad8a3b6dc5b7440e0ada9a245242924394987b21cf2210a4c" [[package]] name = "reqwest" @@ -8887,9 +8970,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.26" +version = "0.12.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b4c14b2d9afca6a60277086b0cc6a6ae0b568f6f7916c943a8cdc79f8be240f" +checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" dependencies = [ "base64 0.22.1", "bytes", @@ -8907,7 +8990,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.35", + "rustls 0.23.36", "rustls-native-certs", "rustls-pki-types", "serde", @@ -8917,7 +9000,7 @@ dependencies = [ "tokio", "tokio-rustls 0.26.4", "tokio-util", - "tower 0.5.2", + "tower 0.5.3", "tower-http 0.6.8", "tower-service", "url", @@ -8925,7 +9008,7 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", - "webpki-roots 1.0.4", + "webpki-roots 1.0.6", ] [[package]] @@ -8982,7 +9065,7 @@ dependencies = [ "alloy-consensus", "alloy-eips", "alloy-primitives", - "derive_more 2.1.0", + "derive_more 2.1.1", "metrics 0.24.3", "parking_lot", "pin-project", @@ -9016,7 +9099,7 @@ dependencies = [ "alloy-primitives", "alloy-trie", "auto_impl", - "derive_more 2.1.0", + "derive_more 2.1.1", "reth-ethereum-forks", "reth-network-peers", "reth-primitives-traits", @@ -9059,7 +9142,7 @@ dependencies = [ "itertools 0.14.0", "lz4", "ratatui", - "reqwest 0.12.26", + "reqwest 0.12.28", "reth-chainspec", "reth-cli", "reth-cli-runner", @@ -9136,7 +9219,7 @@ dependencies = [ "reth-fs-util", "secp256k1 0.30.0", "serde", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -9164,7 +9247,7 @@ source = "git+https://github.com/paradigmxyz/reth?tag=v1.9.1#3afe69a5738459a7cb5 dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -9192,7 +9275,7 @@ dependencies = [ "auto_impl", "reth-execution-types", "reth-primitives-traits", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -9220,10 +9303,10 @@ dependencies = [ "alloy-rpc-types-engine", "alloy-transport", "auto_impl", - "derive_more 2.1.0", + "derive_more 2.1.1", "eyre", "futures", - "reqwest 0.12.26", + "reqwest 0.12.28", "reth-node-api", "reth-primitives-traits", "reth-tracing", @@ -9239,7 +9322,7 @@ version = "1.9.1" source = "git+https://github.com/paradigmxyz/reth?tag=v1.9.1#3afe69a5738459a7cb5f46c598c7f541a1510f32" dependencies = [ "alloy-primitives", - "derive_more 2.1.0", + "derive_more 2.1.1", "eyre", "metrics 0.24.3", "page_size", @@ -9254,7 +9337,7 @@ dependencies = [ "rustc-hash", "strum 0.27.2", "sysinfo", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -9266,7 +9349,7 @@ dependencies = [ "alloy-genesis", "alloy-primitives", "bytes", - "derive_more 2.1.0", + "derive_more 2.1.1", "metrics 0.24.3", "modular-bitfield", "parity-scale-codec", @@ -9308,7 +9391,7 @@ dependencies = [ "reth-trie-db", "serde", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", "tracing", ] @@ -9345,7 +9428,7 @@ dependencies = [ "schnellru", "secp256k1 0.30.0", "serde", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tokio-stream", "tracing", @@ -9358,7 +9441,7 @@ source = "git+https://github.com/paradigmxyz/reth?tag=v1.9.1#3afe69a5738459a7cb5 dependencies = [ "alloy-primitives", "alloy-rlp", - "derive_more 2.1.0", + "derive_more 2.1.1", "discv5", "enr 0.13.0", "futures", @@ -9370,7 +9453,7 @@ dependencies = [ "reth-metrics", "reth-network-peers", "secp256k1 0.30.0", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tracing", ] @@ -9393,7 +9476,7 @@ dependencies = [ "secp256k1 0.30.0", "serde", "serde_with 3.16.1", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tokio-stream", "tracing", @@ -9423,7 +9506,7 @@ dependencies = [ "reth-primitives-traits", "reth-storage-api", "reth-tasks", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tokio-stream", "tokio-util", @@ -9453,7 +9536,7 @@ dependencies = [ "secp256k1 0.30.0", "sha2 0.10.9", "sha3", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tokio-stream", "tokio-util", @@ -9504,7 +9587,7 @@ dependencies = [ "reth-primitives-traits", "reth-trie-common", "serde", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", ] @@ -9543,7 +9626,7 @@ dependencies = [ "alloy-rpc-types-engine", "crossbeam-channel", "dashmap 6.1.0", - "derive_more 2.1.0", + "derive_more 2.1.1", "futures", "metrics 0.24.3", "mini-moka", @@ -9575,7 +9658,7 @@ dependencies = [ "revm-primitives", "schnellru", "smallvec", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tracing", ] @@ -9621,7 +9704,7 @@ dependencies = [ "ethereum_ssz_derive", "reth-ethereum-primitives", "snap", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -9633,7 +9716,7 @@ dependencies = [ "bytes", "eyre", "futures-util", - "reqwest 0.12.26", + "reqwest 0.12.28", "reth-fs-util", "sha2 0.10.9", "tokio", @@ -9669,7 +9752,7 @@ dependencies = [ "reth-consensus", "reth-execution-errors", "reth-storage-errors", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -9681,7 +9764,7 @@ dependencies = [ "alloy-primitives", "alloy-rlp", "bytes", - "derive_more 2.1.0", + "derive_more 2.1.1", "futures", "pin-project", "reth-codecs", @@ -9693,7 +9776,7 @@ dependencies = [ "reth-primitives-traits", "serde", "snap", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tokio-stream", "tokio-util", @@ -9712,13 +9795,13 @@ dependencies = [ "alloy-primitives", "alloy-rlp", "bytes", - "derive_more 2.1.0", + "derive_more 2.1.1", "reth-chainspec", "reth-codecs-derive", "reth-ethereum-primitives", "reth-primitives-traits", "serde", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -9817,7 +9900,7 @@ dependencies = [ "reth-primitives-traits", "serde", "sha2 0.10.9", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -9901,7 +9984,7 @@ dependencies = [ "alloy-evm", "alloy-primitives", "auto_impl", - "derive_more 2.1.0", + "derive_more 2.1.1", "futures-util", "metrics 0.24.3", "reth-execution-errors", @@ -9924,7 +10007,7 @@ dependencies = [ "alloy-evm", "alloy-primitives", "alloy-rpc-types-engine", - "derive_more 2.1.0", + "derive_more 2.1.1", "reth-chainspec", "reth-ethereum-forks", "reth-ethereum-primitives", @@ -9945,7 +10028,7 @@ dependencies = [ "alloy-rlp", "nybbles", "reth-storage-errors", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -9957,7 +10040,7 @@ dependencies = [ "alloy-eips", "alloy-evm", "alloy-primitives", - "derive_more 2.1.0", + "derive_more 2.1.1", "reth-ethereum-primitives", "reth-primitives-traits", "reth-trie-common", @@ -9998,7 +10081,7 @@ dependencies = [ "reth-tasks", "reth-tracing", "rmp-serde", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tokio-util", "tracing", @@ -10025,7 +10108,7 @@ source = "git+https://github.com/paradigmxyz/reth?tag=v1.9.1#3afe69a5738459a7cb5 dependencies = [ "serde", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -10068,11 +10151,11 @@ dependencies = [ "jsonrpsee", "pin-project", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tokio-stream", "tokio-util", - "tower 0.5.2", + "tower 0.5.3", "tracing", ] @@ -10084,11 +10167,11 @@ dependencies = [ "bitflags 2.10.0", "byteorder", "dashmap 6.1.0", - "derive_more 2.1.0", + "derive_more 2.1.1", "parking_lot", "reth-mdbx-sys", "smallvec", - "thiserror 2.0.17", + "thiserror 2.0.18", "tracing", ] @@ -10128,9 +10211,9 @@ source = "git+https://github.com/paradigmxyz/reth?tag=v1.9.1#3afe69a5738459a7cb5 dependencies = [ "futures-util", "if-addrs", - "reqwest 0.12.26", + "reqwest 0.12.28", "serde_with 3.16.1", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tracing", ] @@ -10146,7 +10229,7 @@ dependencies = [ "alloy-rlp", "aquamarine 0.6.0", "auto_impl", - "derive_more 2.1.0", + "derive_more 2.1.1", "discv5", "enr 0.13.0", "futures", @@ -10183,7 +10266,7 @@ dependencies = [ "secp256k1 0.30.0", "serde", "smallvec", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tokio-stream", "tokio-util", @@ -10200,7 +10283,7 @@ dependencies = [ "alloy-rpc-types-admin", "alloy-rpc-types-eth", "auto_impl", - "derive_more 2.1.0", + "derive_more 2.1.1", "enr 0.13.0", "futures", "reth-eth-wire-types", @@ -10210,7 +10293,7 @@ dependencies = [ "reth-network-types", "reth-tokio-util", "serde", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tokio-stream", ] @@ -10224,7 +10307,7 @@ dependencies = [ "alloy-eips", "alloy-primitives", "auto_impl", - "derive_more 2.1.0", + "derive_more 2.1.1", "futures", "reth-consensus", "reth-eth-wire-types", @@ -10247,7 +10330,7 @@ dependencies = [ "enr 0.13.0", "secp256k1 0.30.0", "serde_with 3.16.1", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "url", ] @@ -10273,12 +10356,12 @@ source = "git+https://github.com/paradigmxyz/reth?tag=v1.9.1#3afe69a5738459a7cb5 dependencies = [ "anyhow", "bincode", - "derive_more 2.1.0", + "derive_more 2.1.1", "lz4_flex", "memmap2", "reth-fs-util", "serde", - "thiserror 2.0.17", + "thiserror 2.0.18", "tracing", "zstd 0.13.3", ] @@ -10385,7 +10468,7 @@ dependencies = [ "alloy-primitives", "alloy-rpc-types-engine", "clap", - "derive_more 2.1.0", + "derive_more 2.1.1", "dirs-next", "eyre", "futures", @@ -10481,7 +10564,7 @@ dependencies = [ "reth-transaction-pool", "serde", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tokio-stream", "tokio-tungstenite 0.26.2", @@ -10498,7 +10581,7 @@ dependencies = [ "alloy-eips", "alloy-primitives", "alloy-rpc-types-engine", - "derive_more 2.1.0", + "derive_more 2.1.1", "futures", "humantime", "pin-project", @@ -10526,11 +10609,11 @@ dependencies = [ "metrics-process", "metrics-util", "procfs 0.17.0", - "reqwest 0.12.26", + "reqwest 0.12.28", "reth-metrics", "reth-tasks", "tokio", - "tower 0.5.2", + "tower 0.5.3", "tracing", ] @@ -10595,7 +10678,7 @@ dependencies = [ "reth-errors", "reth-primitives-traits", "serde", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", ] @@ -10638,7 +10721,7 @@ dependencies = [ "auto_impl", "byteorder", "bytes", - "derive_more 2.1.0", + "derive_more 2.1.1", "modular-bitfield", "once_cell", "op-alloy-consensus", @@ -10650,7 +10733,7 @@ dependencies = [ "secp256k1 0.30.0", "serde", "serde_with 3.16.1", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -10715,7 +10798,7 @@ dependencies = [ "reth-static-file-types", "reth-tokio-util", "rustc-hash", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tracing", ] @@ -10726,12 +10809,12 @@ version = "1.9.1" source = "git+https://github.com/paradigmxyz/reth?tag=v1.9.1#3afe69a5738459a7cb5f46c598c7f541a1510f32" dependencies = [ "alloy-primitives", - "derive_more 2.1.0", + "derive_more 2.1.1", "modular-bitfield", "reth-codecs", "serde", "strum 0.27.2", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -10774,7 +10857,7 @@ dependencies = [ "alloy-signer", "alloy-signer-local", "async-trait", - "derive_more 2.1.0", + "derive_more 2.1.1", "dyn-clone", "futures", "http 1.4.0", @@ -10818,10 +10901,10 @@ dependencies = [ "serde", "serde_json", "sha2 0.10.9", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tokio-stream", - "tower 0.5.2", + "tower 0.5.3", "tracing", "tracing-futures", ] @@ -10885,10 +10968,10 @@ dependencies = [ "reth-tasks", "reth-transaction-pool", "serde", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tokio-util", - "tower 0.5.2", + "tower 0.5.3", "tower-http 0.6.8", "tracing", ] @@ -10911,7 +10994,7 @@ dependencies = [ "reth-evm", "reth-primitives-traits", "revm-context", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -10939,7 +11022,7 @@ dependencies = [ "reth-tasks", "reth-transaction-pool", "serde", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tracing", ] @@ -11002,14 +11085,14 @@ dependencies = [ "alloy-rpc-types-eth", "alloy-sol-types", "alloy-transport", - "derive_more 2.1.0", + "derive_more 2.1.1", "futures", "itertools 0.14.0", "jsonrpsee-core", "jsonrpsee-types", "metrics 0.24.3", "rand 0.9.2", - "reqwest 0.12.26", + "reqwest 0.12.28", "reth-chain-state", "reth-chainspec", "reth-errors", @@ -11029,7 +11112,7 @@ dependencies = [ "revm-inspectors", "schnellru", "serde", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tokio-stream", "tracing", @@ -11044,7 +11127,7 @@ dependencies = [ "http 1.4.0", "jsonrpsee-http-client", "pin-project", - "tower 0.5.2", + "tower 0.5.3", "tower-http 0.6.8", "tracing", ] @@ -11079,7 +11162,7 @@ dependencies = [ "itertools 0.14.0", "num-traits", "rayon", - "reqwest 0.12.26", + "reqwest 0.12.28", "reth-codecs", "reth-config", "reth-consensus", @@ -11104,7 +11187,7 @@ dependencies = [ "reth-storage-errors", "reth-trie", "reth-trie-db", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tracing", ] @@ -11131,7 +11214,7 @@ dependencies = [ "reth-static-file", "reth-static-file-types", "reth-tokio-util", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tracing", ] @@ -11176,7 +11259,7 @@ source = "git+https://github.com/paradigmxyz/reth?tag=v1.9.1#3afe69a5738459a7cb5 dependencies = [ "alloy-primitives", "clap", - "derive_more 2.1.0", + "derive_more 2.1.1", "serde", "strum 0.27.2", ] @@ -11212,12 +11295,12 @@ dependencies = [ "alloy-eips", "alloy-primitives", "alloy-rlp", - "derive_more 2.1.0", + "derive_more 2.1.1", "reth-primitives-traits", "reth-prune-types", "reth-static-file-types", "revm-database-interface", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -11232,7 +11315,7 @@ dependencies = [ "pin-project", "rayon", "reth-metrics", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tracing", "tracing-futures", @@ -11275,7 +11358,7 @@ dependencies = [ "opentelemetry-semantic-conventions", "opentelemetry_sdk 0.31.0", "tracing", - "tracing-opentelemetry 0.32.0", + "tracing-opentelemetry 0.32.1", "tracing-subscriber 0.3.22", "url", ] @@ -11314,7 +11397,7 @@ dependencies = [ "serde", "serde_json", "smallvec", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tokio-stream", "tracing", @@ -11357,7 +11440,7 @@ dependencies = [ "alloy-trie", "arrayvec", "bytes", - "derive_more 2.1.0", + "derive_more 2.1.1", "itertools 0.14.0", "nybbles", "rayon", @@ -11390,7 +11473,7 @@ dependencies = [ "alloy-rlp", "crossbeam-channel", "dashmap 6.1.0", - "derive_more 2.1.0", + "derive_more 2.1.1", "itertools 0.14.0", "metrics 0.24.3", "rayon", @@ -11401,7 +11484,7 @@ dependencies = [ "reth-trie", "reth-trie-common", "reth-trie-sparse", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tracing", ] @@ -11594,7 +11677,7 @@ dependencies = [ "revm", "serde", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -11692,7 +11775,7 @@ checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", - "getrandom 0.2.16", + "getrandom 0.2.17", "libc", "untrusted 0.9.0", "windows-sys 0.52.0", @@ -11715,9 +11798,9 @@ dependencies = [ [[package]] name = "rlimit" -version = "0.10.2" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7043b63bd0cd1aaa628e476b80e6d4023a3b50eb32789f2728908107bd0c793a" +checksum = "f35ee2729c56bb610f6dba436bf78135f728b7373bdffae2ec815b2d3eb98cc3" dependencies = [ "libc", ] @@ -11746,22 +11829,19 @@ dependencies = [ [[package]] name = "rmp" -version = "0.8.14" +version = "0.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "228ed7c16fa39782c3b3468e974aec2795e9089153cd08ee2e9aefb3613334c4" +checksum = "4ba8be72d372b2c9b35542551678538b562e7cf86c3315773cae48dfbfe7790c" dependencies = [ - "byteorder", "num-traits", - "paste", ] [[package]] name = "rmp-serde" -version = "1.3.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52e599a477cf9840e92f2cde9a7189e67b42c57532749bf90aea6ec10facd4db" +checksum = "72f81bee8c8ef9b577d1681a70ebbc962c232461e397b22c208c43c04b67a155" dependencies = [ - "byteorder", "rmp", "serde", ] @@ -11802,9 +11882,9 @@ dependencies = [ [[package]] name = "rug" -version = "1.28.0" +version = "1.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58ad2e973fe3c3214251a840a621812a4f40468da814b1a3d6947d433c2af11f" +checksum = "de190ec858987c79cad4da30e19e546139b3339331282832af004d0ea7829639" dependencies = [ "az", "gmp-mpfr-sys", @@ -11814,9 +11894,9 @@ dependencies = [ [[package]] name = "ruint" -version = "1.17.0" +version = "1.17.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a68df0380e5c9d20ce49534f292a36a7514ae21350726efe1865bdb1fa91d278" +checksum = "c141e807189ad38a07276942c6623032d3753c8859c146104ac2e4d68865945a" dependencies = [ "alloy-rlp", "ark-ff 0.3.0", @@ -11879,9 +11959,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" +checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d" [[package]] name = "rustc-hash" @@ -11931,15 +12011,15 @@ dependencies = [ [[package]] name = "rustix" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" +checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" dependencies = [ "bitflags 2.10.0", "errno", "libc", "linux-raw-sys 0.11.0", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -11956,26 +12036,26 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.35" +version = "0.23.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f" +checksum = "c665f33d38cea657d9614f766881e4d510e0eda4239891eea56b4cadcf01801b" dependencies = [ "log", "once_cell", "ring 0.17.14", "rustls-pki-types", - "rustls-webpki 0.103.8", + "rustls-webpki 0.103.9", "subtle", "zeroize", ] [[package]] name = "rustls-native-certs" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9980d917ebb0c0536119ba501e90834767bffc3d60641457fd84a1f3fd337923" +checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" dependencies = [ - "openssl-probe", + "openssl-probe 0.2.1", "rustls-pki-types", "schannel", "security-framework 3.5.1", @@ -11992,9 +12072,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.13.1" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "708c0f9d5f54ba0272468c1d306a52c495b31fa155e91bc25371e6df7996908c" +checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd" dependencies = [ "web-time", "zeroize", @@ -12011,10 +12091,10 @@ dependencies = [ "jni", "log", "once_cell", - "rustls 0.23.35", + "rustls 0.23.36", "rustls-native-certs", "rustls-platform-verifier-android", - "rustls-webpki 0.103.8", + "rustls-webpki 0.103.9", "security-framework 3.5.1", "security-framework-sys", "webpki-root-certs 0.26.11", @@ -12039,9 +12119,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.8" +version = "0.103.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52" +checksum = "d7df23109aa6c1567d1c575b9952556388da57401e4ace1d15f79eedad0d8f53" dependencies = [ "ring 0.17.14", "rustls-pki-types", @@ -12068,9 +12148,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.20" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" [[package]] name = "safe_arith" @@ -12126,7 +12206,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -12152,9 +12232,9 @@ dependencies = [ [[package]] name = "schemars" -version = "1.1.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9558e172d4e8533736ba97870c4b2cd63f84b382a3d6eb063da41b91cce17289" +checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc" dependencies = [ "dyn-clone", "ref-cast", @@ -12381,21 +12461,21 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] name = "serde_json" -version = "1.0.145" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ - "indexmap 2.12.1", + "indexmap 2.13.0", "itoa", "memchr", - "ryu", "serde", "serde_core", + "zmij", ] [[package]] @@ -12427,7 +12507,7 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -12471,9 +12551,9 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.12.1", + "indexmap 2.13.0", "schemars 0.9.0", - "schemars 1.1.0", + "schemars 1.2.1", "serde_core", "serde_json", "serde_with_macros 3.16.1", @@ -12501,7 +12581,7 @@ dependencies = [ "darling 0.21.3", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -12510,7 +12590,7 @@ version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.12.1", + "indexmap 2.13.0", "itoa", "ryu", "serde", @@ -12599,9 +12679,9 @@ dependencies = [ [[package]] name = "sha3-asm" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28efc5e327c837aa837c59eae585fc250715ef939ac32881bcc11677cd02d46" +checksum = "b31139435f327c93c6038ed350ae4588e2c70a13d50599509fee6349967ba35a" dependencies = [ "cc", "cfg-if", @@ -12667,10 +12747,11 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.7" +version = "1.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7664a098b8e616bdfcc2dc0e9ac44eb231eedf41db4e9fe95d8d32ec728dedad" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" dependencies = [ + "errno", "libc", ] @@ -12704,15 +12785,15 @@ checksum = "297f631f50729c8c99b84667867963997ec0b50f32b2a7dbcab828ef0541e8bb" dependencies = [ "num-bigint", "num-traits", - "thiserror 2.0.17", + "thiserror 2.0.18", "time", ] [[package]] name = "siphasher" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" +checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" [[package]] name = "skeptic" @@ -12737,9 +12818,9 @@ checksum = "c1e9a774a6c28142ac54bb25d25562e6bcf957493a184f15ad4eebccb23e410a" [[package]] name = "slab" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "slot_clock" @@ -12779,9 +12860,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" +checksum = "86f4aa3ad99f2088c990dfa82d367e19cb29268ed67c574d10d0a4bfe71f07e0" dependencies = [ "libc", "windows-sys 0.60.2", @@ -12831,12 +12912,12 @@ checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] name = "spine-derive" -version = "0.0.8" -source = "git+https://github.com/gattaca-com/flux#16973424f7eb3eac68f80cc305a03b948486805d" +version = "0.0.9" +source = "git+https://github.com/gattaca-com/flux#6119504e55e6db4fba88bcaacc78637b7fff95be" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -12949,7 +13030,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -12961,7 +13042,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -12972,16 +13053,16 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "superstruct" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b986e4a629907f20a2c2a639a75bc22a8b5d99b444e0d83c395f4cb309022bf" +checksum = "bae4a9ccd7882533c1f210e400763ec6ee64c390fc12248c238276281863719e" dependencies = [ - "darling 0.20.11", - "itertools 0.13.0", + "darling 0.23.0", + "itertools 0.14.0", "proc-macro2", "quote", "smallvec", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -13027,9 +13108,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.111" +version = "2.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" +checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a" dependencies = [ "proc-macro2", "quote", @@ -13038,14 +13119,14 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "1.4.1" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff790eb176cc81bb8936aed0f7b9f14fc4670069a2d371b3e3b0ecce908b2cb3" +checksum = "2379beea9476b89d0237078be761cf8e012d92d5ae4ae0c9a329f974838870fc" dependencies = [ "paste", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -13071,7 +13152,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -13196,7 +13277,7 @@ dependencies = [ "tokio", "tokio-util", "url", - "uuid 1.19.0", + "uuid 1.20.0", ] [[package]] @@ -13213,15 +13294,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.23.0" +version = "3.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" +checksum = "655da9c7eb6305c55742045d5a8d2037996d61d8de95806335c7c86ce0f82e9c" dependencies = [ "fastrand", "getrandom 0.3.4", "once_cell", - "rustix 1.1.2", - "windows-sys 0.61.2", + "rustix 1.1.3", + "windows-sys 0.52.0", ] [[package]] @@ -13255,11 +13336,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.17" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ - "thiserror-impl 2.0.17", + "thiserror-impl 2.0.18", ] [[package]] @@ -13270,18 +13351,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] name = "thiserror-impl" -version = "2.0.17" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -13324,9 +13405,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.44" +version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" dependencies = [ "deranged", "itoa", @@ -13334,22 +13415,22 @@ dependencies = [ "num-conv", "num_threads", "powerfmt", - "serde", + "serde_core", "time-core", "time-macros", ] [[package]] name = "time-core" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" [[package]] name = "time-macros" -version = "0.2.24" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" dependencies = [ "num-conv", "time-core", @@ -13401,9 +13482,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.48.0" +version = "1.49.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" +checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" dependencies = [ "bytes", "libc", @@ -13411,7 +13492,7 @@ dependencies = [ "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2 0.6.1", + "socket2 0.6.2", "tokio-macros", "windows-sys 0.61.2", ] @@ -13434,7 +13515,7 @@ checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -13449,9 +13530,9 @@ dependencies = [ [[package]] name = "tokio-postgres" -version = "0.7.15" +version = "0.7.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b40d66d9b2cfe04b628173409368e58247e8eddbbd3b0e6c6ba1d09f20f6c9e" +checksum = "dcea47c8f71744367793f16c2db1f11cb859d28f436bdb4ca9193eb1f787ee42" dependencies = [ "async-trait", "byteorder", @@ -13467,7 +13548,7 @@ dependencies = [ "postgres-protocol", "postgres-types", "rand 0.9.2", - "socket2 0.6.1", + "socket2 0.6.2", "tokio", "tokio-util", "whoami", @@ -13489,15 +13570,15 @@ version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ - "rustls 0.23.35", + "rustls 0.23.36", "tokio", ] [[package]] name = "tokio-stream" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" +checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" dependencies = [ "futures-core", "pin-project-lite", @@ -13528,7 +13609,7 @@ checksum = "7a9daff607c6d2bf6c16fd681ccb7eecc83e4e2cdc1ca067ffaadfca5de7f084" dependencies = [ "futures-util", "log", - "rustls 0.23.35", + "rustls 0.23.36", "rustls-native-certs", "rustls-pki-types", "tokio", @@ -13563,9 +13644,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.17" +version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2efa149fe76073d6e8fd97ef4f4eca7b67f599660115591483572e406e165594" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" dependencies = [ "bytes", "futures-core", @@ -13599,9 +13680,9 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.7.3" +version = "0.7.5+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533" +checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" dependencies = [ "serde_core", ] @@ -13612,7 +13693,7 @@ version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ - "indexmap 2.12.1", + "indexmap 2.13.0", "serde", "serde_spanned", "toml_datetime 0.6.11", @@ -13622,21 +13703,21 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.23.9" +version = "0.23.10+spec-1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d7cbc3b4b49633d57a0509303158ca50de80ae32c265093b24c414705807832" +checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269" dependencies = [ - "indexmap 2.12.1", - "toml_datetime 0.7.3", + "indexmap 2.13.0", + "toml_datetime 0.7.5+spec-1.1.0", "toml_parser", "winnow", ] [[package]] name = "toml_parser" -version = "1.0.4" +version = "1.0.6+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e" +checksum = "a3198b4b0a8e11f09dd03e133c0280504d0801269e9afa46362ffde1cbeebf44" dependencies = [ "winnow", ] @@ -13703,9 +13784,9 @@ dependencies = [ [[package]] name = "tonic" -version = "0.14.2" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb7613188ce9f7df5bfe185db26c5814347d110db17920415cf2fbcad85e7203" +checksum = "a286e33f82f8a1ee2df63f4fa35c0becf4a85a0cb03091a15fd7bf0b402dc94a" dependencies = [ "async-trait", "base64 0.22.1", @@ -13721,7 +13802,7 @@ dependencies = [ "sync_wrapper 1.0.2", "tokio", "tokio-stream", - "tower 0.5.2", + "tower 0.5.3", "tower-layer", "tower-service", "tracing", @@ -13737,18 +13818,18 @@ dependencies = [ "proc-macro2", "prost-build", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] name = "tonic-prost" -version = "0.14.2" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66bd50ad6ce1252d87ef024b3d64fe4c3cf54a86fb9ef4c631fdd0ded7aeaa67" +checksum = "d6c55a2d6a14174563de34409c9f92ff981d006f56da9c6ecd40d9d4a31500b0" dependencies = [ "bytes", - "prost 0.14.1", - "tonic 0.14.2", + "prost 0.14.3", + "tonic 0.14.3", ] [[package]] @@ -13774,14 +13855,14 @@ dependencies = [ [[package]] name = "tower" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" dependencies = [ "futures-core", "futures-util", "hdrhistogram", - "indexmap 2.12.1", + "indexmap 2.13.0", "pin-project-lite", "slab", "sync_wrapper 1.0.2", @@ -13820,7 +13901,7 @@ dependencies = [ "tower-layer", "tower-service", "tracing", - "uuid 1.19.0", + "uuid 1.20.0", ] [[package]] @@ -13847,11 +13928,11 @@ dependencies = [ "pin-project-lite", "tokio", "tokio-util", - "tower 0.5.2", + "tower 0.5.3", "tower-layer", "tower-service", "tracing", - "uuid 1.19.0", + "uuid 1.20.0", ] [[package]] @@ -13872,21 +13953,21 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57a2ccff6830fa835371af7541e561a90e4c07b84f72991ebac4b3cb6790dc0d" dependencies = [ - "axum 0.8.7", + "axum 0.8.8", "forwarded-header-value", "governor 0.8.1", "http 1.4.0", "pin-project", - "thiserror 2.0.17", - "tower 0.5.2", + "thiserror 2.0.18", + "tower 0.5.3", "tracing", ] [[package]] name = "tracing" -version = "0.1.43" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d15d90a0b5c19378952d479dc858407149d7bb45a14de0142f6c534b16fc647" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ "log", "pin-project-lite", @@ -13901,7 +13982,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "786d480bce6247ab75f005b14ae1624ad978d3029d9113f0a22fa1ac773faeaf" dependencies = [ "crossbeam-channel", - "thiserror 2.0.17", + "thiserror 2.0.18", "time", "tracing-subscriber 0.3.22", ] @@ -13914,14 +13995,14 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] name = "tracing-core" -version = "0.1.35" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a04e24fab5c89c6a36eb8558c9656f30d81de51dfa4d3b45f26b21d61fa0a6c" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ "once_cell", "valuable", @@ -13961,9 +14042,9 @@ dependencies = [ [[package]] name = "tracing-logfmt" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b1f47d22deb79c3f59fcf2a1f00f60cbdc05462bf17d1cd356c1fefa3f444bd" +checksum = "a250055a3518b5efba928a18ffac8d32d42ea607a9affff4532144cd5b2e378e" dependencies = [ "time", "tracing", @@ -13991,16 +14072,13 @@ dependencies = [ [[package]] name = "tracing-opentelemetry" -version = "0.32.0" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e6e5658463dd88089aba75c7791e1d3120633b1bfde22478b28f625a9bb1b8e" +checksum = "1ac28f2d093c6c477eaa76b23525478f38de514fa9aeb1285738d4b97a9552fc" dependencies = [ "js-sys", "opentelemetry 0.31.0", - "opentelemetry_sdk 0.31.0", - "rustversion", "smallvec", - "thiserror 2.0.17", "tracing", "tracing-core", "tracing-log", @@ -14070,7 +14148,7 @@ dependencies = [ "darling 0.20.11", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -14121,10 +14199,10 @@ dependencies = [ "httparse", "log", "rand 0.9.2", - "rustls 0.23.35", + "rustls 0.23.36", "rustls-pki-types", "sha1", - "thiserror 2.0.17", + "thiserror 2.0.18", "utf-8", ] @@ -14141,7 +14219,7 @@ dependencies = [ "log", "rand 0.9.2", "sha1", - "thiserror 2.0.17", + "thiserror 2.0.18", "utf-8", ] @@ -14158,24 +14236,24 @@ dependencies = [ "log", "rand 0.9.2", "sha1", - "thiserror 2.0.17", + "thiserror 2.0.18", "utf-8", ] [[package]] name = "type-hash" version = "0.0.1" -source = "git+https://github.com/gattaca-com/flux#16973424f7eb3eac68f80cc305a03b948486805d" +source = "git+https://github.com/gattaca-com/flux#6119504e55e6db4fba88bcaacc78637b7fff95be" [[package]] name = "type-hash-derive" version = "0.0.4" -source = "git+https://github.com/gattaca-com/flux#16973424f7eb3eac68f80cc305a03b948486805d" +source = "git+https://github.com/gattaca-com/flux#6119504e55e6db4fba88bcaacc78637b7fff95be" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -14270,9 +14348,9 @@ checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" [[package]] name = "unicase" -version = "2.8.1" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" +checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142" [[package]] name = "unicode-bidi" @@ -14282,9 +14360,9 @@ checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" [[package]] name = "unicode-ident" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" +checksum = "537dd038a89878be9b64dd4bd1b260315c1bb94f4d784956b81e27a088d9a09e" [[package]] name = "unicode-normalization" @@ -14372,14 +14450,15 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.7" +version = "2.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" dependencies = [ "form_urlencoded", "idna", "percent-encoding", "serde", + "serde_derive", ] [[package]] @@ -14406,15 +14485,15 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", "serde", ] [[package]] name = "uuid" -version = "1.19.0" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e054861b4bd027cd373e18e8d8d8e6548085000e41290d95ce0c373a654b4a" +checksum = "ee48d38b119b0cd71fe4141b30f5ba9c7c5d9f4e7a3a8b4a674e4b6ef789976f" dependencies = [ "getrandom 0.3.4", "js-sys", @@ -14448,17 +14527,17 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "vergen" -version = "9.0.6" +version = "9.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b2bf58be11fc9414104c6d3a2e464163db5ef74b12296bda593cac37b6e4777" +checksum = "b849a1f6d8639e8de261e81ee0fc881e3e3620db1af9f2e0da015d4382ceaf75" dependencies = [ "anyhow", - "cargo_metadata 0.19.2", + "cargo_metadata 0.23.1", "derive_builder", "regex", "rustversion", "time", - "vergen-lib", + "vergen-lib 9.1.0", ] [[package]] @@ -14473,7 +14552,7 @@ dependencies = [ "rustversion", "time", "vergen", - "vergen-lib", + "vergen-lib 0.1.6", ] [[package]] @@ -14487,6 +14566,17 @@ dependencies = [ "rustversion", ] +[[package]] +name = "vergen-lib" +version = "9.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b34a29ba7e9c59e62f229ae1932fb1b8fb8a6fdcc99215a641913f5f5a59a569" +dependencies = [ + "anyhow", + "derive_builder", + "rustversion", +] + [[package]] name = "version_check" version = "0.9.5" @@ -14527,26 +14617,38 @@ version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" +[[package]] +name = "wasi" +version = "0.14.7+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c" +dependencies = [ + "wasip2", +] + [[package]] name = "wasip2" -version = "1.0.1+wasi-0.2.4" +version = "1.0.2+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" dependencies = [ "wit-bindgen", ] [[package]] name = "wasite" -version = "0.1.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" +checksum = "66fe902b4a6b8028a753d5424909b764ccf79b7a209eac9bf97e59cda9f71a42" +dependencies = [ + "wasi 0.14.7+wasi-0.2.4", +] [[package]] name = "wasm-bindgen" -version = "0.2.106" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd" +checksum = "64024a30ec1e37399cf85a7ffefebdb72205ca1c972291c51512360d90bd8566" dependencies = [ "cfg-if", "once_cell", @@ -14557,11 +14659,12 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.56" +version = "0.4.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836d9622d604feee9e5de25ac10e3ea5f2d65b41eac0d9ce72eb5deae707ce7c" +checksum = "70a6e77fd0ae8029c9ea0063f87c46fde723e7d887703d74ad2616d792e51e6f" dependencies = [ "cfg-if", + "futures-util", "js-sys", "once_cell", "wasm-bindgen", @@ -14570,9 +14673,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.106" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3" +checksum = "008b239d9c740232e71bd39e8ef6429d27097518b6b30bdf9086833bd5b6d608" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -14580,22 +14683,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.106" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40" +checksum = "5256bae2d58f54820e6490f9839c49780dff84c65aeab9e772f15d5f0e913a55" dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.106" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4" +checksum = "1f01b580c9ac74c8d8f0c0e4afb04eeef2acf145458e52c03845ee9cd23e3d12" dependencies = [ "unicode-ident", ] @@ -14629,9 +14732,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.83" +version = "0.3.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b32828d774c412041098d182a8b38b16ea816958e07cf40eec2bc080ae137ac" +checksum = "312e32e551d92129218ea9a2452120f4aabc03529ef03e4d0d82fb2780608598" dependencies = [ "js-sys", "wasm-bindgen", @@ -14653,14 +14756,14 @@ version = "0.26.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75c7f0ef91146ebfb530314f5f1d24528d7f0767efbfd31dce919275413e393e" dependencies = [ - "webpki-root-certs 1.0.4", + "webpki-root-certs 1.0.6", ] [[package]] name = "webpki-root-certs" -version = "1.0.4" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee3e3b5f5e80bc89f30ce8d0343bf4e5f12341c51f3e26cbeecbc7c85443e85b" +checksum = "804f18a4ac2676ffb4e8b5b5fa9ae38af06df08162314f96a68d2a363e21a8ca" dependencies = [ "rustls-pki-types", ] @@ -14677,23 +14780,23 @@ version = "0.26.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" dependencies = [ - "webpki-roots 1.0.4", + "webpki-roots 1.0.6", ] [[package]] name = "webpki-roots" -version = "1.0.4" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2878ef029c47c6e8cf779119f20fcf52bde7ad42a731b2a304bc221df17571e" +checksum = "22cfaf3c063993ff62e73cb4311efde4db1efb31ab78a3e5c457939ad5cc0bed" dependencies = [ "rustls-pki-types", ] [[package]] name = "whoami" -version = "1.6.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d4a4db5077702ca3015d3d02d74974948aba2ad9e12ab7df718ee64ccd7e97d" +checksum = "8fae98cf96deed1b7572272dfc777713c249ae40aa1cf8862e091e8b745f5361" dependencies = [ "libredox", "wasite", @@ -14737,7 +14840,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -14834,7 +14937,7 @@ checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -14845,7 +14948,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -14856,7 +14959,7 @@ checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -14867,7 +14970,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -15270,9 +15373,9 @@ dependencies = [ [[package]] name = "wit-bindgen" -version = "0.46.0" +version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" [[package]] name = "writeable" @@ -15293,7 +15396,7 @@ dependencies = [ "pharos", "rustc_version 0.4.1", "send_wrapper 0.6.0", - "thiserror 2.0.17", + "thiserror 2.0.18", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", @@ -15315,7 +15418,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156" dependencies = [ "libc", - "rustix 1.1.2", + "rustix 1.1.3", ] [[package]] @@ -15349,28 +15452,28 @@ checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", "synstructure", ] [[package]] name = "zerocopy" -version = "0.8.31" +version = "0.8.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3" +checksum = "db6d35d663eadb6c932438e763b262fe1a70987f9ae936e60158176d710cae4a" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.31" +version = "0.8.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a" +checksum = "4122cd3169e94605190e77839c9a40d40ed048d305bfdc146e7df40ab0f3e517" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -15390,7 +15493,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", "synstructure", ] @@ -15406,13 +15509,13 @@ dependencies = [ [[package]] name = "zeroize_derive" -version = "1.4.2" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -15445,7 +15548,7 @@ checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -15468,6 +15571,12 @@ dependencies = [ "zstd 0.11.2+zstd.1.5.2", ] +[[package]] +name = "zmij" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4de98dfa5d5b7fef4ee834d0073d560c9ca7b6c46a71d058c48db7960f8cfaf7" + [[package]] name = "zstd" version = "0.11.2+zstd.1.5.2" diff --git a/Cargo.toml b/Cargo.toml index df7a83782..d626c1b8a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,7 @@ askama = "0.12.0" async-trait = "0.1" axum = { version = "0.8", features = ["matched-path", "ws"] } backtrace = "0.3.69" +bitflags = "2.10.0" blst = { version = "0.3.16", features = ["no-threads"] } bytes = "1.10" chrono = { features = ["serde"], version = "0.4.38" } @@ -41,6 +42,7 @@ ethers = "2.0.14" eyre = "0.6.12" flate2 = "1.0" flux = { git = "https://github.com/gattaca-com/flux" } +flux-network = { package = "flux-network", git = "https://github.com/gattaca-com/flux" } futures = "0.3" futures-util = { version = "0.3", features = ["compat"] } helix-common = { path = "crates/common" } diff --git a/crates/common/src/config.rs b/crates/common/src/config.rs index 92e0c27fd..4e777eb25 100644 --- a/crates/common/src/config.rs +++ b/crates/common/src/config.rs @@ -59,6 +59,10 @@ pub struct RelayConfig { pub gossip_payload_on_header: bool, #[serde(default = "default_u16::<4040>")] pub api_port: u16, + #[serde(default = "default_u16::<4041>")] + pub tcp_port: u16, + #[serde(default = "default_usize::<512>")] + pub tcp_max_connections: usize, } impl RelayConfig { @@ -89,9 +93,12 @@ impl RelayConfig { tokio: vec![], sub_workers: vec![], reg_workers: vec![], + tcp_bid_submissions_tile: 2, }, gossip_payload_on_header: false, api_port: 4040, + tcp_port: 4041, + tcp_max_connections: Default::default(), } } } @@ -134,6 +141,7 @@ pub struct CoresConfig { pub sub_workers: Vec, /// Registrations pub reg_workers: Vec, + pub tcp_bid_submissions_tile: usize, } impl Default for WebsiteConfig { diff --git a/crates/common/src/local_cache.rs b/crates/common/src/local_cache.rs index 7dbafeafe..54f9a0da6 100644 --- a/crates/common/src/local_cache.rs +++ b/crates/common/src/local_cache.rs @@ -10,7 +10,6 @@ use axum::{ }; use dashmap::{DashMap, DashSet}; use helix_types::{BlsPublicKeyBytes, CryptoError, MergedBlock}; -use http::HeaderValue; use parking_lot::RwLock; use tracing::error; @@ -89,7 +88,7 @@ pub struct LocalCache { pub inclusion_list: Arc>>, builder_info_cache: Arc>, /// Api key -> builder pubkey - api_key_cache: Arc>>, + pub api_key_cache: Arc>>, trusted_proposers: Arc>, primev_proposers: Arc>, kill_switch: Arc, @@ -119,16 +118,6 @@ impl LocalCache { merged_blocks, } } - - pub fn new_test() -> Self { - Self::new() - } -} - -impl Default for LocalCache { - fn default() -> Self { - Self::new() - } } impl LocalCache { @@ -136,11 +125,11 @@ impl LocalCache { Some(self.builder_info_cache.get(builder_pub_key)?.clone()) } - pub fn contains_api_key(&self, api_key: &HeaderValue) -> bool { + pub fn contains_api_key(&self, api_key: &str) -> bool { self.api_key_cache.contains_key(api_key) } - pub fn validate_api_key(&self, api_key: &HeaderValue, pubkey: &BlsPublicKeyBytes) -> bool { + pub fn validate_api_key(&self, api_key: &str, pubkey: &BlsPublicKeyBytes) -> bool { self.api_key_cache.get(api_key).is_some_and(|p| p.value().contains(pubkey)) } @@ -167,10 +156,7 @@ impl LocalCache { for builder_info in builder_infos { if let Some(api_key) = builder_info.builder_info.api_key.as_ref() { - self.api_key_cache - .entry(HeaderValue::from_str(api_key).unwrap()) - .or_default() - .push(builder_info.pub_key); + self.api_key_cache.entry(api_key.clone()).or_default().push(builder_info.pub_key); } self.builder_info_cache.insert(builder_info.pub_key, builder_info.builder_info.clone()); diff --git a/crates/relay/Cargo.toml b/crates/relay/Cargo.toml index dbca10930..c9a05dc26 100644 --- a/crates/relay/Cargo.toml +++ b/crates/relay/Cargo.toml @@ -14,6 +14,7 @@ alloy-rlp.workspace = true askama.workspace = true async-trait.workspace = true axum.workspace = true +bitflags = "2.10.0" bytes.workspace = true chrono.workspace = true crossbeam-channel.workspace = true @@ -26,6 +27,7 @@ ethers.workspace = true eyre.workspace = true flate2.workspace = true flux.workspace = true +flux-network.workspace = true futures.workspace = true helix-common.workspace = true helix-types.workspace = true diff --git a/crates/relay/src/api/admin_service.rs b/crates/relay/src/api/admin_service.rs index 826e75d6b..44a668713 100644 --- a/crates/relay/src/api/admin_service.rs +++ b/crates/relay/src/api/admin_service.rs @@ -47,7 +47,7 @@ mod test { #[tokio::test] #[serial] async fn test_admin_service() { - let auctioneer = Arc::new(LocalCache::new_test()); + let auctioneer = Arc::new(LocalCache::new()); let admin_token = "test_token".into(); tokio::spawn(run_admin_service(auctioneer.clone(), admin_token)); @@ -76,7 +76,7 @@ mod test { #[tokio::test] #[serial] async fn test_admin_service_unauthorized() { - let auctioneer = Arc::new(LocalCache::new_test()); + let auctioneer = Arc::new(LocalCache::new()); let admin_token = "test_token".into(); tokio::spawn(run_admin_service(auctioneer.clone(), admin_token)); diff --git a/crates/relay/src/api/builder/submit_block.rs b/crates/relay/src/api/builder/submit_block.rs index fb51dcf64..62de38e57 100644 --- a/crates/relay/src/api/builder/submit_block.rs +++ b/crates/relay/src/api/builder/submit_block.rs @@ -8,14 +8,17 @@ use http::HeaderMap; use tracing::{error, trace}; use super::api::BuilderApi; -use crate::api::{Api, builder::error::BuilderApiError}; +use crate::{ + api::{Api, builder::error::BuilderApiError}, + auctioneer::headers_map_to_bid_submission_header, +}; impl BuilderApi { /// Implements this API: #[tracing::instrument(skip_all, err(level = tracing::Level::TRACE), fields( - id =% extract_request_id(&headers), - slot = tracing::field::Empty, // submission slot + id = tracing::field::Empty, + slot = tracing::field::Empty, builder_pubkey = tracing::field::Empty, builder_id = tracing::field::Empty, block_hash = tracing::field::Empty, @@ -26,18 +29,33 @@ impl BuilderApi { headers: HeaderMap, body: bytes::Bytes, ) -> Result<(), BuilderApiError> { + let request_id = extract_request_id(&headers); + + tracing::Span::current().record("id", tracing::field::display(request_id)); + trace!("start handler"); let mut trace = SubmissionTrace::init_from_timings(timings); trace.metadata = api.api_provider.get_metadata(&headers); - let Ok(rx) = api.auctioneer_handle.block_submission(headers, body, trace) else { + let (header, sequence, encoding, compression, api_key) = + headers_map_to_bid_submission_header(headers); + let Ok(rx) = api.auctioneer_handle.block_submission( + header, + sequence, + encoding, + compression, + api_key, + body, + trace, + false, + ) else { error!("failed sending request to worker"); return Err(BuilderApiError::InternalError); }; let res = match rx.await { - Ok(res) => res, + Ok((_, res)) => res, Err(_) => Err(BuilderApiError::RequestTimeout), }; diff --git a/crates/relay/src/api/builder/top_bid.rs b/crates/relay/src/api/builder/top_bid.rs index 288ef73c4..977825f23 100644 --- a/crates/relay/src/api/builder/top_bid.rs +++ b/crates/relay/src/api/builder/top_bid.rs @@ -22,7 +22,11 @@ impl BuilderApi { headers: HeaderMap, ws: WebSocketUpgrade, ) -> Result { - let Some(api_key) = headers.get(HEADER_API_KEY).or_else(|| headers.get(HEADER_API_TOKEN)) + let Some(api_key) = headers + .get(HEADER_API_KEY) + .or(headers.get(HEADER_API_TOKEN)) + .map(|key| key.to_str().ok()) + .flatten() else { return Err(BuilderApiError::InvalidApiKey); }; diff --git a/crates/relay/src/auctioneer/context.rs b/crates/relay/src/auctioneer/context.rs index 8aff5b27e..cb2c6a8e6 100644 --- a/crates/relay/src/auctioneer/context.rs +++ b/crates/relay/src/auctioneer/context.rs @@ -214,7 +214,7 @@ impl Context { if let Some(res_tx) = result.res_tx { // submission was initially valid but by the time sim finished the slot already // progressed - let _ = res_tx.send(Err(BuilderApiError::SimOnNextSlot)); + let _ = res_tx.send((result.request_id, Err(BuilderApiError::SimOnNextSlot))); } } diff --git a/crates/relay/src/auctioneer/decoder.rs b/crates/relay/src/auctioneer/decoder.rs index 0e47af818..885f33965 100644 --- a/crates/relay/src/auctioneer/decoder.rs +++ b/crates/relay/src/auctioneer/decoder.rs @@ -15,7 +15,7 @@ use http::{ HeaderMap, HeaderValue, header::{CONTENT_ENCODING, CONTENT_TYPE}, }; -use serde::de::DeserializeOwned; +use serde::{Deserialize, Serialize, de::DeserializeOwned}; use ssz::Decode; use strum::{AsRefStr, EnumString}; use tracing::trace; @@ -24,9 +24,13 @@ use zstd::{ zstd_safe::{CONTENTSIZE_ERROR, CONTENTSIZE_UNKNOWN, get_frame_content_size}, }; -use crate::api::{ - HEADER_MERGE_TYPE, HEADER_SUBMISSION_TYPE, - builder::{api::MAX_PAYLOAD_LENGTH, error::BuilderApiError}, +use crate::{ + api::{ + HEADER_API_KEY, HEADER_API_TOKEN, HEADER_HYDRATE, HEADER_IS_MERGEABLE, HEADER_MERGE_TYPE, + HEADER_SEQUENCE, HEADER_SUBMISSION_TYPE, HEADER_WITH_ADJUSTMENTS, + builder::{api::MAX_PAYLOAD_LENGTH, error::BuilderApiError}, + }, + tcp_bid_recv::{BidSubmissionHeader, types::BidSubmissionFlags}, }; #[derive(Debug, Clone, Copy, PartialEq, Eq, EnumString, AsRefStr)] @@ -44,29 +48,92 @@ impl SubmissionType { } } -#[derive(Debug, Clone, Copy, PartialEq, Eq, EnumString, AsRefStr)] +#[repr(u8)] +#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, EnumString, AsRefStr)] #[strum(serialize_all = "snake_case", ascii_case_insensitive)] pub enum MergeType { - Mergeable, - AppendOnly, + #[default] + None = 0, + Mergeable = 1, + AppendOnly = 2, } impl MergeType { - pub fn from_headers(header_map: &HeaderMap) -> Option { - let merge_type = header_map.get(HEADER_MERGE_TYPE)?.to_str().ok()?; - merge_type.parse().ok() + pub fn from_headers(header_map: &HeaderMap) -> Self { + match header_map.get(HEADER_MERGE_TYPE) { + None => { + if matches!(header_map.get(HEADER_IS_MERGEABLE), Some(header) if header == HeaderValue::from_static("true")) + { + MergeType::Mergeable + } else { + MergeType::None + } + } + Some(merge_type) => { + merge_type.to_str().ok().map(|t| t.parse().ok()).flatten().unwrap_or_default() + } + } + } + + pub fn is_some(&self) -> bool { + *self != MergeType::None + } +} + +impl TryFrom for MergeType { + type Error = (); + + fn try_from(value: u8) -> Result { + match value { + 0 => Ok(Self::None), + 1 => Ok(Self::Mergeable), + 2 => Ok(Self::AppendOnly), + _ => Err(()), + } } } -#[derive(Clone, Copy, Debug, PartialEq)] -enum Compression { - None, - Gzip, - Zstd, +#[repr(u8)] +#[derive( + Debug, Eq, PartialEq, Clone, Copy, Serialize, Deserialize, Hash, PartialOrd, Ord, Default, +)] +pub enum Compression { + #[default] + None = 0, + Gzip = 1, + Zstd = 2, +} + +impl Compression { + pub fn string(&self) -> String { + match &self { + Compression::None => "none".into(), + Compression::Gzip => "gzip".into(), + Compression::Zstd => "zstd".into(), + } + } + + pub fn as_str(&self) -> &'static str { + match &self { + Compression::None => "none", + Compression::Gzip => "gzip", + Compression::Zstd => "zstd", + } + } +} + +impl std::fmt::Display for Compression { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", match self { + Compression::None => "NONE", + Compression::Gzip => "GZIP", + Compression::Zstd => "ZSTD", + }) + } } #[derive(Clone, Copy, Debug)] -enum Encoding { +pub enum Encoding { Json, Ssz, } @@ -85,23 +152,7 @@ pub struct SubmissionDecoder { } impl SubmissionDecoder { - pub fn from_headers(header_map: &HeaderMap) -> Self { - const GZIP_HEADER: HeaderValue = HeaderValue::from_static("gzip"); - const ZSTD_HEADER: HeaderValue = HeaderValue::from_static("zstd"); - - let compression = match header_map.get(CONTENT_ENCODING) { - Some(header) if header == GZIP_HEADER => Compression::Gzip, - Some(header) if header == ZSTD_HEADER => Compression::Zstd, - _ => Compression::None, - }; - - const SSZ_HEADER: HeaderValue = HeaderValue::from_static("application/octet-stream"); - - let encoding = match header_map.get(CONTENT_TYPE) { - Some(header) if header == SSZ_HEADER => Encoding::Ssz, - _ => Encoding::Json, - }; - + pub fn new(compression: Compression, encoding: Encoding) -> Self { Self { compression, encoding, @@ -233,11 +284,7 @@ impl SubmissionDecoder { } fn record_metrics(&self) { - let compression_label = match self.compression { - Compression::None => "none", - Compression::Gzip => "gzip", - Compression::Zstd => "zstd", - }; + let compression_label = self.compression.as_str(); SUBMISSION_BY_COMPRESSION.with_label_values(&[compression_label]).inc(); if self.compression != Compression::None { @@ -260,7 +307,7 @@ impl SubmissionDecoder { .observe(error) } } - // Record encoding type + let encoding_label = match self.encoding { Encoding::Json => "json", Encoding::Ssz => "ssz", @@ -299,6 +346,70 @@ fn gzip_size_hint(buf: &[u8]) -> Option { } } +pub fn headers_map_to_bid_submission_header( + headers: http::header::HeaderMap, +) -> (BidSubmissionHeader, Option, Encoding, Compression, Option) { + let mut flags = BidSubmissionFlags::default(); + + if matches!(headers.get(HEADER_WITH_ADJUSTMENTS), Some(header) if header == HeaderValue::from_static("true")) + { + flags.set(BidSubmissionFlags::WITH_ADJUSTMENTS, true); + } + if headers.get(HEADER_HYDRATE).is_some() { + flags.set(BidSubmissionFlags::IS_DEHYDRATED, true); + } + + if let Some(submission_type) = SubmissionType::from_headers(&headers) { + match submission_type { + SubmissionType::Dehydrated => { + flags.set(BidSubmissionFlags::IS_DEHYDRATED, true); + } + SubmissionType::Merge => { + // TODO @nina + // flags.set(BidSubmissionFlags::WITH_MERGEABLE_DATA, true); + } + SubmissionType::Default => {} + } + } + + let sequence_number = headers + .get(HEADER_SEQUENCE) + .and_then(|seq| seq.to_str().ok()) + .and_then(|seq| seq.parse::().ok()); + + const GZIP_HEADER: HeaderValue = HeaderValue::from_static("gzip"); + const ZSTD_HEADER: HeaderValue = HeaderValue::from_static("zstd"); + + let compression = match headers.get(CONTENT_ENCODING) { + Some(header) if header == GZIP_HEADER => Compression::Gzip, + Some(header) if header == ZSTD_HEADER => Compression::Zstd, + _ => Compression::None, + }; + + const SSZ_HEADER: HeaderValue = HeaderValue::from_static("application/octet-stream"); + + let encoding = match headers.get(CONTENT_TYPE) { + Some(header) if header == SSZ_HEADER => Encoding::Ssz, + _ => Encoding::Json, + }; + + let merge_type = MergeType::from_headers(&headers); + + let api_key = headers + .get(HEADER_API_KEY) + .or(headers.get(HEADER_API_TOKEN)) + .map(|key| key.to_str().map(|key| key.to_owned()).ok()) + .flatten(); + + let header = BidSubmissionHeader { + sequence_number: sequence_number.unwrap_or_default(), + merge_type, + flags, + }; + + (header, sequence_number, encoding, compression, api_key) +} + #[cfg(test)] mod tests { use alloy_primitives::hex::FromHex; diff --git a/crates/relay/src/auctioneer/handle.rs b/crates/relay/src/auctioneer/handle.rs index 49c5925a4..366fe7527 100644 --- a/crates/relay/src/auctioneer/handle.rs +++ b/crates/relay/src/auctioneer/handle.rs @@ -2,15 +2,18 @@ use std::{ops::Range, sync::Arc, time::Instant}; use helix_common::{GetPayloadTrace, SubmissionTrace, api::proposer_api::GetHeaderParams}; use helix_types::{BlsPublicKeyBytes, SignedBlindedBeaconBlock, SignedValidatorRegistration}; -use http::HeaderMap; use tokio::sync::oneshot; use tracing::trace; use crate::{ - auctioneer::types::{ - Event, GetHeaderResult, GetPayloadResult, RegWorkerJob, SubWorkerJob, SubmissionResult, + auctioneer::{ + decoder::{Compression, Encoding}, + types::{ + Event, GetHeaderResult, GetPayloadResult, RegWorkerJob, SubWorkerJob, SubmissionResult, + }, }, gossip::BroadcastPayloadParams, + tcp_bid_recv::BidSubmissionHeader, }; #[derive(Clone)] @@ -29,20 +32,30 @@ impl AuctioneerHandle { pub fn block_submission( &self, - headers: HeaderMap, + header: BidSubmissionHeader, + sequence: Option, + encoding: Encoding, + compression: Compression, + api_key: Option, body: bytes::Bytes, trace: SubmissionTrace, + skip_sigverify: bool, ) -> Result, ChannelFull> { let (tx, rx) = oneshot::channel(); trace!("sending to worker"); self.worker .try_send(SubWorkerJob::BlockSubmission { - headers, + header, + sequence, + encoding, + compression, + api_key, body, trace, res_tx: tx, span: tracing::Span::current(), sent_at: Instant::now(), + skip_sigverify, }) .map_err(|_| ChannelFull)?; Ok(rx) diff --git a/crates/relay/src/auctioneer/mod.rs b/crates/relay/src/auctioneer/mod.rs index 872814dfd..4d6e8c9bb 100644 --- a/crates/relay/src/auctioneer/mod.rs +++ b/crates/relay/src/auctioneer/mod.rs @@ -43,7 +43,9 @@ pub use crate::auctioneer::{ bid_adjustor::{BidAdjustor, DefaultBidAdjustor}, bid_sorter::BidSorter, context::Context, + decoder::{Compression, Encoding, MergeType, headers_map_to_bid_submission_header}, simulator::{SimulatorRequest, client::SimulatorClient, manager::SimulatorManager}, + types::SubmissionResult, // move to types? }; use crate::{ HelixSpine, PostgresDatabaseService, @@ -94,7 +96,7 @@ impl Auctioneer { impl Tile for Auctioneer { fn loop_body(&mut self, _adapter: &mut flux::spine::SpineAdapter) { for event in self.event_rx.try_iter() { - self.state.step(event, &mut self.ctx, &mut self.tel); + self.state.step(event, &mut self.ctx, &mut self.tel, _adapter); } self.tel.telemetry(&self.event_rx); @@ -138,12 +140,18 @@ impl Default for State { // TODO: tokio metrics impl State { - fn step(&mut self, event: Event, ctx: &mut Context, tel: &mut Telemetry) { + fn step( + &mut self, + event: Event, + ctx: &mut Context, + tel: &mut Telemetry, + _adapter: &mut flux::spine::SpineAdapter, + ) { let start = Instant::now(); let start_state = self.as_str(); let event_tag = event.as_str(); - self._step(event, ctx); + self._step(event, ctx, _adapter); let end_state = self.as_str(); let step_dur = start.elapsed(); @@ -157,7 +165,12 @@ impl State { .observe(step_dur.as_nanos() as f64 / 1000.); } - fn _step(&mut self, event: Event, ctx: &mut Context) { + fn _step( + &mut self, + event: Event, + ctx: &mut Context, + _adapter: &mut flux::spine::SpineAdapter, + ) { match (&self, event) { ///////////// LIFECYCLE EVENTS (ALWAYS VALID) ///////////// @@ -418,10 +431,13 @@ impl State { State::Broadcasting { slot_data: slot_ctx, .. }, Event::Submission { submission_data, res_tx, .. }, ) => { - let _ = res_tx.send(Err(BuilderApiError::DeliveringPayload { - bid_slot: submission_data.bid_slot(), - delivering: slot_ctx.bid_slot.as_u64(), - })); + let _ = res_tx.send(( + submission_data.request_id, + Err(BuilderApiError::DeliveringPayload { + bid_slot: submission_data.bid_slot(), + delivering: slot_ctx.bid_slot.as_u64(), + }), + )); } // late get_header @@ -467,14 +483,20 @@ impl State { (State::Slot { bid_slot, .. }, Event::Submission { res_tx, submission_data, .. }) => { if submission_data.bid_slot() == bid_slot.as_u64() { // either not registered or waiting for full data from housekepper - let _ = res_tx.send(Err(BuilderApiError::ProposerDutyNotFound)); + let _ = res_tx.send(( + submission_data.request_id, + Err(BuilderApiError::ProposerDutyNotFound), + )); } else { - let _ = res_tx.send(Err(BuilderApiError::BidValidation( - helix_types::BlockValidationError::SubmissionForWrongSlot { - expected: *bid_slot, - got: submission_data.bid_slot().into(), - }, - ))); + let _ = res_tx.send(( + submission_data.request_id, + Err(BuilderApiError::BidValidation( + helix_types::BlockValidationError::SubmissionForWrongSlot { + expected: *bid_slot, + got: submission_data.bid_slot().into(), + }, + )), + )); } } diff --git a/crates/relay/src/auctioneer/simulator/manager.rs b/crates/relay/src/auctioneer/simulator/manager.rs index 9dff9a114..00a978a4d 100644 --- a/crates/relay/src/auctioneer/simulator/manager.rs +++ b/crates/relay/src/auctioneer/simulator/manager.rs @@ -41,6 +41,7 @@ struct LocalTelemetry { pub type SimulationResult = (usize, Option); pub struct SimulationResultInner { pub result: Result<(), BlockSimError>, + pub request_id: u64, // Some if not optimistic pub res_tx: Option>, // TODO: move up @@ -230,6 +231,7 @@ impl SimulatorManager { let result = ( id, Some(SimulationResultInner { + request_id: req.submission_request_id, result: res, paused_until, res_tx: req.res_tx, diff --git a/crates/relay/src/auctioneer/simulator/mod.rs b/crates/relay/src/auctioneer/simulator/mod.rs index 1adfbd8dc..f59921eb3 100644 --- a/crates/relay/src/auctioneer/simulator/mod.rs +++ b/crates/relay/src/auctioneer/simulator/mod.rs @@ -12,7 +12,7 @@ use helix_types::{ }; use tokio::sync::oneshot; -use crate::{SlotData, SubmissionPayload, auctioneer::types::SubmissionResult}; +use crate::auctioneer::types::SubmissionResult; pub mod client; pub mod manager; @@ -111,6 +111,7 @@ pub struct SimulatorRequest { pub is_top_bid: bool, pub version: SubmissionVersion, pub submission: SignedBidSubmission, + pub submission_request_id: u64, /// None if optimistic pub res_tx: Option>, pub trace: SubmissionTrace, @@ -119,26 +120,6 @@ pub struct SimulatorRequest { } impl SimulatorRequest { - pub fn new(bid: &SubmissionPayload, slot_data: &SlotData) -> Self { - let request = BlockSimRequest::new( - slot_data.registration_data.entry.registration.message.gas_limit, - &bid.signed_bid_submission, - slot_data.registration_data.entry.preferences.clone(), - bid.parent_beacon_block_root, - slot_data.il.clone(), - ); - - Self { - request, - is_top_bid: true, - res_tx: None, - submission: bid.signed_bid_submission.clone(), - trace: bid.submission_trace.clone(), - tx_root: bid.tx_root, - version: bid.submission_version, - } - } - pub fn on_receive_ns(&self) -> u64 { self.trace.receive } diff --git a/crates/relay/src/auctioneer/submit_block.rs b/crates/relay/src/auctioneer/submit_block.rs index bb52ee2dc..2a6f0e206 100644 --- a/crates/relay/src/auctioneer/submit_block.rs +++ b/crates/relay/src/auctioneer/submit_block.rs @@ -32,10 +32,11 @@ impl Context { res_tx: oneshot::Sender, slot_data: &SlotData, ) { + let request_id = submission_data.request_id; match self.validate_and_sort(submission_data, slot_data) { Ok((validated, optimistic_version, merging_data)) => { let res_tx = if optimistic_version.is_optimistic() { - let _ = res_tx.send(Ok(())); + let _ = res_tx.send((request_id, Ok(()))); None } else { Some(res_tx) @@ -77,7 +78,7 @@ impl Context { } Err(err) => { - let _ = res_tx.send(Err(err)); + let _ = res_tx.send((request_id, Err(err))); } } } @@ -94,7 +95,10 @@ impl Context { Err(err) if err.is_demotable() => { self.bid_sorter.demote(*result.submission.builder_public_key()); if let Some(res_tx) = res_tx { - let _ = res_tx.send(Err(BuilderApiError::BlockSimulation(err.clone()))); + let _ = res_tx.send(( + result.request_id, + Err(BuilderApiError::BlockSimulation(err.clone())), + )); }; } @@ -111,7 +115,7 @@ impl Context { } self.request_merged_block(); - let _ = res_tx.send(Ok(())); + let _ = res_tx.send((result.request_id, Ok(()))); }; } } @@ -204,6 +208,7 @@ impl Context { }); let validated = ValidatedData { + request_id: submission_data.request_id, submission, tx_root: maybe_tx_root, payload_attributes, @@ -231,6 +236,7 @@ impl Context { ); let req = SimulatorRequest { + submission_request_id: validated.request_id, request, is_top_bid: validated.is_top_bid, res_tx, @@ -310,6 +316,7 @@ impl Context { } pub struct ValidatedData<'a> { + pub request_id: u64, pub submission: SignedBidSubmission, pub tx_root: Option, pub payload_attributes: &'a PayloadAttributesUpdate, diff --git a/crates/relay/src/auctioneer/types.rs b/crates/relay/src/auctioneer/types.rs index 4e70dc1ef..a2cca5d70 100644 --- a/crates/relay/src/auctioneer/types.rs +++ b/crates/relay/src/auctioneer/types.rs @@ -27,12 +27,17 @@ use tracing::debug; use crate::{ api::{builder::error::BuilderApiError, proposer::ProposerApiError}, - auctioneer::{BlockMergeResult, simulator::manager::SimulationResult}, + auctioneer::{ + BlockMergeResult, + decoder::{Compression, Encoding}, + simulator::manager::SimulationResult, + }, gossip::BroadcastPayloadParams, housekeeper::PayloadAttributesUpdate, + tcp_bid_recv::types::BidSubmissionHeader, }; -pub type SubmissionResult = Result<(), BuilderApiError>; +pub type SubmissionResult = (u64, Result<(), BuilderApiError>); pub type GetHeaderResult = Result; pub type GetPayloadResult = Result; @@ -44,7 +49,9 @@ pub struct GetPayloadResultData { pub bid: PayloadBidData, } +#[derive(Clone, Debug)] pub struct SubmissionData { + pub request_id: u64, pub submission: Submission, pub merging_data: Option, pub bid_adjustment_data: Option, @@ -62,7 +69,7 @@ impl Deref for SubmissionData { } #[allow(clippy::large_enum_variant)] -#[derive(Clone)] +#[derive(Clone, Debug)] pub enum Submission { // received after sigverify Full(SignedBidSubmission), @@ -297,12 +304,17 @@ impl PayloadBidDataRef<'_> { pub enum SubWorkerJob { BlockSubmission { - headers: http::HeaderMap, + header: BidSubmissionHeader, + sequence: Option, + encoding: Encoding, + api_key: Option, + compression: Compression, body: bytes::Bytes, trace: SubmissionTrace, // TODO: replace this with better tracing res_tx: oneshot::Sender, span: tracing::Span, sent_at: Instant, + skip_sigverify: bool, }, GetPayload { diff --git a/crates/relay/src/auctioneer/worker.rs b/crates/relay/src/auctioneer/worker.rs index 575d88e8e..9b18ed9d8 100644 --- a/crates/relay/src/auctioneer/worker.rs +++ b/crates/relay/src/auctioneer/worker.rs @@ -20,20 +20,17 @@ use helix_types::{ SignedBidSubmissionWithMergingData, SignedBlindedBeaconBlock, SignedValidatorRegistration, SubmissionVersion, }; -use http::HeaderValue; use tracing::{error, trace}; use crate::{ HelixSpine, - api::{ - HEADER_API_KEY, HEADER_HYDRATE, HEADER_IS_MERGEABLE, HEADER_SEQUENCE, - HEADER_WITH_ADJUSTMENTS, builder::error::BuilderApiError, proposer::ProposerApiError, - }, + api::{builder::error::BuilderApiError, proposer::ProposerApiError}, auctioneer::{ block_merger::get_mergeable_orders, - decoder::{MergeType, SubmissionDecoder, SubmissionType}, + decoder::{Compression, Encoding, MergeType, SubmissionDecoder}, types::{Event, RegWorkerJob, SubWorkerJob, Submission, SubmissionData}, }, + tcp_bid_recv::BidSubmissionHeader, }; pub struct Telemetry { @@ -118,11 +115,33 @@ impl SubWorker { fn _handle_task(&self, task: SubWorkerJob) { match task { - SubWorkerJob::BlockSubmission { headers, body, mut trace, res_tx, span, sent_at } => { + SubWorkerJob::BlockSubmission { + header, + sequence, + encoding, + compression, + api_key, + body, + mut trace, + res_tx, + span, + sent_at, + skip_sigverify, + } => { record_submission_step("worker_recv", sent_at.elapsed()); let guard = span.enter(); trace!("received by worker"); - match self.handle_block_submission(headers, body, &mut trace) { + let request_id = header.sequence_number; + match self.handle_block_submission( + header, + sequence, + api_key, + skip_sigverify, + encoding, + compression, + body, + &mut trace, + ) { Ok(( submission, withdrawals_root, @@ -166,6 +185,7 @@ impl SubWorker { }; let submission_data = SubmissionData { + request_id, submission, version, merging_data, @@ -187,7 +207,7 @@ impl SubWorker { } Err(err) => { - let _ = res_tx.send(Err(err)); + let _ = res_tx.send((request_id, Err(err))); } } } @@ -231,70 +251,56 @@ impl SubWorker { #[allow(clippy::type_complexity)] fn handle_block_submission( &self, - headers: http::HeaderMap, + header: BidSubmissionHeader, + sequence: Option, + api_key: Option, + mut skip_sigverify: bool, + encoding: Encoding, + compression: Compression, body: bytes::Bytes, trace: &mut SubmissionTrace, ) -> Result< (Submission, B256, SubmissionVersion, Option, Option), BuilderApiError, > { - let mut decoder = SubmissionDecoder::from_headers(&headers); + let mut decoder = SubmissionDecoder::new(compression, encoding); let body = decoder.decompress(body)?; - let submission_type = SubmissionType::from_headers(&headers); - let merge_type = MergeType::from_headers(&headers); - let has_mergeable_data = matches!(headers.get(HEADER_IS_MERGEABLE), Some(header) if header == HeaderValue::from_static("true")); - let builder_pubkey = decoder.extract_builder_pubkey(body.as_ref(), has_mergeable_data)?; - let with_adjustments = matches!(headers.get(HEADER_WITH_ADJUSTMENTS), Some(header) if header == HeaderValue::from_static("true")); - - let skip_sigverify = headers - .get(HEADER_API_KEY) - .is_some_and(|key| self.cache.validate_api_key(key, &builder_pubkey)); - let should_hydrate = headers.get(HEADER_HYDRATE).is_some(); - let sequence = headers - .get(HEADER_SEQUENCE) - .and_then(|seq| seq.to_str().ok()) - .and_then(|seq| seq.parse::().ok()); + + let with_mergeable_data = header.merge_type.is_some(); + let with_adjustments = header.flags.with_adjustments(); + let is_dehydrated = header.flags.is_dehydrated(); + + let builder_pubkey = decoder.extract_builder_pubkey(body.as_ref(), with_mergeable_data)?; + if !skip_sigverify { + skip_sigverify = api_key + .is_some_and(|api_key| self.cache.validate_api_key(&api_key, &builder_pubkey)); + } trace!( ?sequence, - should_hydrate, + is_dehydrated, skip_sigverify, - has_mergeable_data, + with_mergeable_data, with_adjustments, "processing payload" ); let flags = DecodeFlags { skip_sigverify, - merge_type, - with_adjustment: with_adjustments, + merge_type: header.merge_type, + with_adjustments, block_merging_dry_run: self.config.block_merging_config.is_dry_run, }; - let (submission, merging_data, bid_adjustment_data) = match submission_type { - Some(SubmissionType::Default) => { - decode_default(&mut decoder, body, trace, &self.chain_info, &flags)? - } - Some(SubmissionType::Merge) => { - decode_merge(&mut decoder, body, trace, &self.chain_info, &flags)? - } - Some(SubmissionType::Dehydrated) => { - decode_dehydrated(&mut decoder, body, trace, &self.chain_info, &flags)? - } - None => { - if should_hydrate { - decode_dehydrated(&mut decoder, body, trace, &self.chain_info, &flags)? - } else if has_mergeable_data { - decode_merge(&mut decoder, body, trace, &self.chain_info, &flags)? - } else { - decode_default(&mut decoder, body, trace, &self.chain_info, &flags)? - } - } + let (submission, merging_data, bid_adjustment_data) = if is_dehydrated { + decode_dehydrated(&mut decoder, body, trace, &self.chain_info, &flags)? + } else if with_mergeable_data { + decode_merge(&mut decoder, body, trace, &self.chain_info, &flags)? + } else { + decode_default(&mut decoder, body, trace, &self.chain_info, &flags)? }; - trace!("computing withdrawals root"); let withdrawals_root = submission.withdrawal_root(); - trace!("withdrawals root done"); let version = SubmissionVersion::new(trace.receive, sequence); Ok((submission, withdrawals_root, version, merging_data, bid_adjustment_data)) @@ -423,8 +429,8 @@ impl Tile for RegWorker { struct DecodeFlags { skip_sigverify: bool, - merge_type: Option, - with_adjustment: bool, + merge_type: MergeType, + with_adjustments: bool, block_merging_dry_run: bool, } @@ -439,7 +445,7 @@ fn decode_dehydrated( return Err(BuilderApiError::UntrustedBuilderOnDehydratedPayload); } - let (submission, bid_adjustment) = if flags.with_adjustment { + let (submission, bid_adjustment) = if flags.with_adjustments { let sub_with_adjustment: DehydratedBidSubmissionFuluWithAdjustments = decoder.decode_by_fork(body, chain_info.current_fork_name())?; let (sub, adjustment_data) = sub_with_adjustment.split(); @@ -455,15 +461,13 @@ fn decode_dehydrated( trace.decoded = utcnow_ns(); let merging_data = match flags.merge_type { - Some(MergeType::Mergeable) => { + MergeType::Mergeable => { //Should this return an error instead? error!("mergeable dehydrated submissions are not supported"); None } - Some(MergeType::AppendOnly) => { - Some(BlockMergingData::append_only(submission.fee_recipient())) - } - None => { + MergeType::AppendOnly => Some(BlockMergingData::append_only(submission.fee_recipient())), + MergeType::None => { if flags.block_merging_dry_run { Some(BlockMergingData::append_only(submission.fee_recipient())) } else { @@ -486,17 +490,17 @@ fn decode_merge( let mut upgraded = sub_with_merging.maybe_upgrade_to_fulu(chain_info.current_fork_name()); trace.decoded = utcnow_ns(); let merging_data = match flags.merge_type { - Some(MergeType::Mergeable) => Some(upgraded.merging_data), + MergeType::Mergeable => Some(upgraded.merging_data), //Handle append-only by creating empty mergeable orders //this allows builder to switch between append-only and mergeable without changing // submission alternatively we could reject or ignore append-only here if the // submission is mergeable? - Some(MergeType::AppendOnly) => Some(BlockMergingData { + MergeType::AppendOnly => Some(BlockMergingData { allow_appending: upgraded.merging_data.allow_appending, builder_address: upgraded.merging_data.builder_address, merge_orders: vec![], }), - None => Some(upgraded.merging_data), + MergeType::None => Some(upgraded.merging_data), }; verify_and_validate(&mut upgraded.submission, flags.skip_sigverify, chain_info)?; Ok((Submission::Full(upgraded.submission), merging_data, None)) @@ -509,7 +513,7 @@ fn decode_default( chain_info: &ChainInfo, flags: &DecodeFlags, ) -> Result<(Submission, Option, Option), BuilderApiError> { - let (submission, bid_adjustment) = if flags.with_adjustment { + let (submission, bid_adjustment) = if flags.with_adjustments { let sub_with_adjustment: SignedBidSubmissionFuluWithAdjustments = decoder.decode(body)?; let (sub, adjustment_data) = sub_with_adjustment.split(); @@ -523,15 +527,13 @@ fn decode_default( let mut upgraded = submission.maybe_upgrade_to_fulu(chain_info.current_fork_name()); trace.decoded = utcnow_ns(); let merging_data = match flags.merge_type { - Some(MergeType::Mergeable) => { + MergeType::Mergeable => { //Should this return an error instead? error!("mergeable dehydrated submissions are not supported"); None } - Some(MergeType::AppendOnly) => { - Some(BlockMergingData::append_only(upgraded.fee_recipient())) - } - None => { + MergeType::AppendOnly => Some(BlockMergingData::append_only(upgraded.fee_recipient())), + MergeType::None => { if flags.block_merging_dry_run { Some(BlockMergingData::allow_all(upgraded.fee_recipient(), upgraded.num_txs())) } else { diff --git a/crates/relay/src/lib.rs b/crates/relay/src/lib.rs index 9e563fcfb..edf1d9d63 100644 --- a/crates/relay/src/lib.rs +++ b/crates/relay/src/lib.rs @@ -6,6 +6,7 @@ mod gossip; mod housekeeper; mod network; mod spine; +mod tcp_bid_recv; mod website; pub use crate::{ @@ -13,12 +14,13 @@ pub use crate::{ auctioneer::{ Auctioneer, AuctioneerHandle, BidSorter, Context, PayloadEntry, RegWorker, RegWorkerHandle, SimulatorClient, SimulatorManager, SimulatorRequest, SlotData, SubWorker, - SubmissionPayload, + SubmissionPayload, SubmissionResult, }, beacon::start_beacon_client, database::{postgres::postgres_db_service::PostgresDatabaseService, start_db_service}, housekeeper::start_housekeeper, network::RelayNetworkManager, spine::HelixSpine, + tcp_bid_recv::BidSubmissionTcpListener, website::WebsiteService, }; diff --git a/crates/relay/src/main.rs b/crates/relay/src/main.rs index 39c3753f8..8dbf4978d 100644 --- a/crates/relay/src/main.rs +++ b/crates/relay/src/main.rs @@ -1,4 +1,5 @@ use std::{ + net::{Ipv4Addr, SocketAddr, SocketAddrV4}, sync::{ Arc, atomic::{AtomicBool, Ordering}, @@ -22,10 +23,10 @@ use helix_common::{ utils::{init_panic_hook, init_tracing_log}, }; use helix_relay::{ - Api, Auctioneer, AuctioneerHandle, BidSorter, DefaultBidAdjustor, HelixSpine, - PostgresDatabaseService, RegWorker, RegWorkerHandle, RelayNetworkManager, SubWorker, - WebsiteService, start_admin_service, start_api_service, start_beacon_client, start_db_service, - start_housekeeper, + Api, Auctioneer, AuctioneerHandle, BidSorter, BidSubmissionTcpListener, DefaultBidAdjustor, + HelixSpine, PostgresDatabaseService, RegWorker, RegWorkerHandle, RelayNetworkManager, + SubWorker, WebsiteService, start_admin_service, start_api_service, start_beacon_client, + start_db_service, start_housekeeper, }; use helix_types::BlsKeypair; use tikv_jemallocator::Jemalloc; @@ -121,7 +122,7 @@ async fn run(instance_id: String, config: RelayConfig, keypair: BlsKeypair) -> e let termination_grace_period = config.router_config.shutdown_delay_ms; let spine = HelixSpine::new(None); - spine.start(None, |spine| { + spine.start(None, Some(Duration::from_millis(termination_grace_period)), |spine| { start_admin_service(local_cache.clone(), expect_env_var(ADMIN_TOKEN_ENV_VAR)); let auctioneer_handle = AuctioneerHandle::new(sub_worker_tx, event_tx.clone()); @@ -142,7 +143,7 @@ async fn run(instance_id: String, config: RelayConfig, keypair: BlsKeypair) -> e terminating.clone(), top_bid_tx.clone(), relay_network_api.api(), - auctioneer_handle, + auctioneer_handle.clone(), registrations_handle, ); @@ -174,6 +175,22 @@ async fn run(instance_id: String, config: RelayConfig, keypair: BlsKeypair) -> e } let auctioneer_core = config.cores.auctioneer; + let sock_addr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::LOCALHOST, config.tcp_port)); + let block_submission_tcp_listener = BidSubmissionTcpListener::new( + sock_addr, + auctioneer_handle, + local_cache.api_key_cache.clone(), + config.tcp_max_connections, + ); + attach_tile( + block_submission_tcp_listener, + spine, + TileConfig::new( + config.cores.tcp_bid_submissions_tile, + flux::utils::ThreadPriority::High, + ), + ); + let auctioneer = Auctioneer::new( chain_info.as_ref().clone(), config, diff --git a/crates/relay/src/tcp_bid_recv/mod.rs b/crates/relay/src/tcp_bid_recv/mod.rs new file mode 100644 index 000000000..b67eacb16 --- /dev/null +++ b/crates/relay/src/tcp_bid_recv/mod.rs @@ -0,0 +1,193 @@ +use std::{ + collections::{HashMap, HashSet}, + net::SocketAddr, + sync::Arc, +}; + +use dashmap::DashMap; +use flux::{spine::FluxSpine, tile::Tile}; +use flux_network::{ + Token, + tcp::{SendBehavior, TcpConnector, TcpTelemetry}, +}; +use helix_common::SubmissionTrace; +use helix_types::BlsPublicKeyBytes; +use ssz::{Decode, Encode}; +use tokio::sync::oneshot::{Receiver, error::TryRecvError}; +use uuid::Uuid; + +use crate::{ + AuctioneerHandle, HelixSpine, SubmissionResult, + auctioneer::Encoding, + tcp_bid_recv::types::{BidSubmission, BidSubmissionResponse, RegistrationMsg}, +}; + +pub mod types; + +pub use crate::tcp_bid_recv::types::{BidSubmissionError, BidSubmissionHeader}; + +pub struct BidSubmissionTcpListener { + listener_addr: SocketAddr, + listener: TcpConnector, + listener_token: Option, + + auctioneer_handle: AuctioneerHandle, + api_key_cache: Arc>>, + + in_flight: HashMap>, + to_remove: Vec, + to_disconnect: Vec, + registered: HashSet, + submission_errors: Vec<(Token, Option, BidSubmissionError)>, +} + +impl BidSubmissionTcpListener { + pub fn new( + listener_addr: SocketAddr, + auctioneer_handle: AuctioneerHandle, + api_key_cache: Arc>>, + max_connections: usize, + ) -> Self { + let listener = TcpConnector::default() + .with_telemetry(TcpTelemetry::Enabled { app_name: HelixSpine::app_name() }) + .with_socket_buf_size(64 * 1024 * 1024); // 64MB + Self { + listener_addr, + listener, + listener_token: None, + auctioneer_handle, + api_key_cache, + in_flight: HashMap::with_capacity(max_connections), + to_remove: Vec::with_capacity(max_connections), + to_disconnect: Vec::with_capacity(max_connections), + registered: HashSet::with_capacity(max_connections), + submission_errors: Vec::with_capacity(max_connections), + } + } + + #[tracing::instrument(skip_all, + fields( + id =% bid.header.sequence_number, + slot = tracing::field::Empty, + builder_pubkey = tracing::field::Empty, + builder_id = tracing::field::Empty, + block_hash = tracing::field::Empty, + ))] + fn accept_bid_submission( + auctioneer_handle: &AuctioneerHandle, + bid: BidSubmission, + ) -> Result, BidSubmissionError> { + let compression = bid.header.compression(); + + auctioneer_handle + .block_submission( + bid.header, + Some(bid.header.sequence_number), + Encoding::Ssz, + compression, + None, + bid.data, + SubmissionTrace::default(), + true, + ) + .map_err(|_| BidSubmissionError::InternalError) + } +} + +impl Tile for BidSubmissionTcpListener { + fn try_init(&mut self, _adapter: &mut flux::spine::SpineAdapter) -> bool { + self.listener_token = self.listener.listen_at(self.listener_addr); + self.listener_token.is_some() + } + + fn loop_body(&mut self, _adapter: &mut flux::spine::SpineAdapter) { + self.listener.poll_with( + |connection| { + tracing::trace!( + "connected to new peer {:?} with token {:?}", + connection.peer_addr, + connection.incoming_stream + ); + }, + |token, msg, _| { + if !self.registered.contains(&token) { + let registration_message = + RegistrationMsg::from_ssz_bytes(msg); + match registration_message { + Ok(msg) => { + let api_key = Uuid::from_bytes(msg.api_key).to_string(); + if self + .api_key_cache + .get(&api_key) + .is_some_and(|p| p.value().contains(&msg.builder_pubkey)) + { + self.registered.insert(token); + } else { + tracing::error!( + "unknown api key and pubkey pair: {} {}, disconnecting peer", + api_key, + msg.builder_pubkey + ); + self.to_disconnect.push(token); + } + } + Err(e) => { + tracing::error!(err=?e, "invalid registration message"); + self.to_disconnect.push(token); + } + } + } else { + match BidSubmission::try_from(msg) { + Ok(bid) => { + let request_id = bid.header.sequence_number; + match Self::accept_bid_submission(&self.auctioneer_handle, bid) { + Ok(rx) => { + self.in_flight.insert(token, rx); + } + Err(e) => { + tracing::error!(err=%e, "failed to send bid submission to worker"); + self.submission_errors.push((token, Some(request_id), e)); + } + } + } + Err(e) => { + tracing::error!(err=%e, "failed to deserialize the bid"); + self.submission_errors.push((token, None, e)); + } + }; + } + }, + ); + + for token in self.to_disconnect.drain(..) { + self.listener.disconnect(token); + } + + for (token, request_id, err) in self.submission_errors.drain(..) { + self.listener.write_or_enqueue_with(SendBehavior::Single(token), |buffer| { + BidSubmissionResponse::from_bid_submission_error(&request_id, &err) + .ssz_append(buffer); + }); + } + + for (token, rx) in &mut self.in_flight { + match rx.try_recv() { + Ok((request_id, res)) => { + self.listener.write_or_enqueue_with(SendBehavior::Single(*token), |buffer| { + BidSubmissionResponse::from_builder_api_error(request_id, &res) + .ssz_append(buffer); + }); + self.to_remove.push(*token); + } + Err(err) if err == TryRecvError::Closed => { + self.to_remove.push(*token); + } + _ => {} + } + } + + for token in self.to_remove.drain(..) { + self.in_flight.remove(&token); + } + } +} diff --git a/crates/relay/src/tcp_bid_recv/types.rs b/crates/relay/src/tcp_bid_recv/types.rs new file mode 100644 index 000000000..b4f16cbd9 --- /dev/null +++ b/crates/relay/src/tcp_bid_recv/types.rs @@ -0,0 +1,189 @@ +use bytes::Bytes; +use helix_types::BlsPublicKeyBytes; +use serde::{Deserialize, Serialize}; +use ssz::{Decode, DecodeError}; +use ssz_derive::{Decode, Encode}; + +use crate::{ + api::builder::error::BuilderApiError, + auctioneer::{Compression, MergeType}, +}; + +#[repr(C)] +#[derive(Debug, Clone, Decode)] +pub struct RegistrationMsg { + pub api_key: [u8; 16], // this is a Uuid + pub builder_pubkey: BlsPublicKeyBytes, +} + +#[derive(Debug, thiserror::Error)] +pub enum BidSubmissionError { + #[error("Internal error")] + InternalError, + #[error(transparent)] + BuilderApiError(#[from] BuilderApiError), + #[error("InvalidMergeType {0}")] + InvalidMergeType(u8), + #[error("SubmissionTooShort")] + SubmissionTooShort, +} + +#[derive(Debug, Clone)] +pub struct BidSubmission { + pub header: BidSubmissionHeader, + pub data: bytes::Bytes, +} + +impl TryFrom<&[u8]> for BidSubmission { + type Error = BidSubmissionError; + + fn try_from(data: &[u8]) -> Result { + let header = BidSubmissionHeader::try_from(&data[..BID_SUB_HEADER_SIZE])?; + + tracing::trace!("{:?}", header); + + let bid_submission_data = Bytes::copy_from_slice(&data[BID_SUB_HEADER_SIZE..]); + Ok(BidSubmission { header, data: bid_submission_data }) + } +} + +#[repr(C)] +#[derive(Debug, Clone, Copy, Default)] +pub struct BidSubmissionHeader { + pub sequence_number: u64, + pub merge_type: MergeType, + pub flags: BidSubmissionFlags, +} + +const BID_SUB_HEADER_SIZE: usize = 10; + +impl TryFrom<&[u8]> for BidSubmissionHeader { + type Error = BidSubmissionError; + + fn try_from(value: &[u8]) -> Result { + if value.len() < BID_SUB_HEADER_SIZE { + return Err(BidSubmissionError::SubmissionTooShort) + } + + let sequence_number = u64::from_be_bytes(value[..8].try_into().unwrap()); + let merge_type = MergeType::try_from(value[8]) + .map_err(|_| BidSubmissionError::InvalidMergeType(value[8]))?; + let flags = BidSubmissionFlags::from_bits_retain(value[9]); + + Ok(Self { sequence_number, merge_type, flags }) + } +} + +impl BidSubmissionHeader { + pub fn compression(&self) -> Compression { + if self.flags.is_zstd_compressed() { Compression::Zstd } else { Compression::None } + } +} + +#[repr(transparent)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default, Serialize, Deserialize)] +pub struct BidSubmissionFlags(u8); + +bitflags::bitflags! { + impl BidSubmissionFlags : u8 { + const IS_DEHYDRATED = 1 << 0; + const WITH_ADJUSTMENTS = 1 << 1; + const ZSTD_COMPRESSED = 1 << 2; + } +} + +impl BidSubmissionFlags { + pub fn is_dehydrated(&self) -> bool { + self.contains(Self::IS_DEHYDRATED) + } + pub fn with_adjustments(&self) -> bool { + self.contains(Self::WITH_ADJUSTMENTS) + } + pub fn is_zstd_compressed(&self) -> bool { + self.contains(Self::ZSTD_COMPRESSED) + } +} + +impl Decode for BidSubmissionFlags { + fn from_ssz_bytes(bytes: &[u8]) -> Result { + if bytes.len() != 1 { + return Err(DecodeError::InvalidByteLength { len: bytes.len(), expected: 1 }); + } + Ok(BidSubmissionFlags(bytes[0])) + } + + fn is_ssz_fixed_len() -> bool { + true + } + + fn ssz_fixed_len() -> usize { + 1 + } +} + +#[repr(u8)] +#[derive(Debug, Clone, Copy, Encode)] +#[ssz(enum_behaviour = "tag")] +pub enum Status { + Okay = 0, + InvalidRequest = 1, + InternalError = 2, + // client-only + // ConnectionError = 255, +} + +impl From<&BuilderApiError> for Status { + fn from(e: &BuilderApiError) -> Self { + match e { + BuilderApiError::DatabaseError(_) | BuilderApiError::InternalError => { + Status::InternalError + } + _ => Status::InvalidRequest, + } + } +} + +impl From<&BidSubmissionError> for Status { + fn from(e: &BidSubmissionError) -> Self { + match e { + BidSubmissionError::InternalError => Status::InternalError, + BidSubmissionError::BuilderApiError(e) => Status::from(e), + BidSubmissionError::InvalidMergeType(_) => Status::InvalidRequest, + BidSubmissionError::SubmissionTooShort => Status::InvalidRequest, + // _ => Status::InvalidRequest, + } + } +} + +#[repr(C)] +#[derive(Debug, Clone, Encode)] +pub struct BidSubmissionResponse { + pub error_msg: Vec, + pub sequence_number: u64, + pub status: Status, +} + +impl BidSubmissionResponse { + pub fn from_builder_api_error(request_id: u64, result: &Result<(), BuilderApiError>) -> Self { + match result { + Ok(()) => Self { + sequence_number: request_id, + status: Status::Okay, + error_msg: Default::default(), + }, + Err(e) => Self { + sequence_number: request_id, + status: Status::from(e), + error_msg: e.to_string().into_bytes(), + }, + } + } + + pub fn from_bid_submission_error(request_id: &Option, e: &BidSubmissionError) -> Self { + Self { + sequence_number: request_id.unwrap_or_default(), + status: Status::from(e), + error_msg: e.to_string().into_bytes(), + } + } +} diff --git a/crates/relay/src/website/website_service.rs b/crates/relay/src/website/website_service.rs index 44a4df71b..27d37f9e2 100644 --- a/crates/relay/src/website/website_service.rs +++ b/crates/relay/src/website/website_service.rs @@ -59,7 +59,7 @@ impl WebsiteService { }); let chain_updater = ChainEventUpdater::new( - Arc::new(LocalCache::new_test()), + Arc::new(LocalCache::new()), chain_info, current_slot_info, crossbeam_channel::bounded(0).0, diff --git a/crates/types/Cargo.toml b/crates/types/Cargo.toml index 15c5a4aa7..dbb61d764 100644 --- a/crates/types/Cargo.toml +++ b/crates/types/Cargo.toml @@ -12,6 +12,7 @@ alloy-eips.workspace = true alloy-primitives.workspace = true alloy-rpc-types.workspace = true blst.workspace = true +bitflags.workspace = true ethereum_serde_utils.workspace = true ethereum_ssz.workspace = true ethereum_ssz_derive.workspace = true diff --git a/crates/types/src/block_merging.rs b/crates/types/src/block_merging.rs index 680120f7d..659f7d70f 100644 --- a/crates/types/src/block_merging.rs +++ b/crates/types/src/block_merging.rs @@ -180,6 +180,7 @@ pub struct BlobWithMetadataV2 { pub blob: Blob, } +#[derive(Clone, Debug)] pub struct MergeableOrdersWithPref { pub allow_appending: bool, pub orders: MergeableOrders, From 1f32440be4f39e2d1e284d857fe48a32632a7f5e Mon Sep 17 00:00:00 2001 From: Nina Date: Fri, 13 Feb 2026 16:55:43 +0000 Subject: [PATCH 02/12] unspecified --- crates/relay/src/main.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/relay/src/main.rs b/crates/relay/src/main.rs index 8dbf4978d..9b3e0373b 100644 --- a/crates/relay/src/main.rs +++ b/crates/relay/src/main.rs @@ -175,7 +175,8 @@ async fn run(instance_id: String, config: RelayConfig, keypair: BlsKeypair) -> e } let auctioneer_core = config.cores.auctioneer; - let sock_addr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::LOCALHOST, config.tcp_port)); + let sock_addr = + SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, config.tcp_port)); let block_submission_tcp_listener = BidSubmissionTcpListener::new( sock_addr, auctioneer_handle, From d1bd8d5b93a7ec99f1e0967a84b6eab0615a75a0 Mon Sep 17 00:00:00 2001 From: Nina Date: Mon, 16 Feb 2026 12:09:07 +0000 Subject: [PATCH 03/12] some fixes --- Cargo.lock | 16 +-- Cargo.toml | 4 +- crates/common/src/config.rs | 2 +- crates/relay/src/api/builder/error.rs | 8 +- crates/relay/src/api/builder/submit_block.rs | 30 +++-- crates/relay/src/api/builder/top_bid.rs | 3 +- crates/relay/src/auctioneer/context.rs | 2 +- crates/relay/src/auctioneer/decoder.rs | 32 ++---- crates/relay/src/auctioneer/handle.rs | 22 ++-- crates/relay/src/auctioneer/mod.rs | 27 ++--- .../relay/src/auctioneer/simulator/manager.rs | 8 +- crates/relay/src/auctioneer/simulator/mod.rs | 9 +- crates/relay/src/auctioneer/submit_block.rs | 18 +-- crates/relay/src/auctioneer/types.rs | 41 +++++-- crates/relay/src/auctioneer/worker.rs | 27 +++-- crates/relay/src/main.rs | 10 +- crates/relay/src/tcp_bid_recv/mod.rs | 107 +++++++++--------- crates/relay/src/tcp_bid_recv/types.rs | 101 +++++++++++------ crates/types/src/bid_submission.rs | 6 +- 19 files changed, 263 insertions(+), 210 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d582afe9a..fee393598 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4533,7 +4533,7 @@ dependencies = [ [[package]] name = "flux" version = "0.0.37" -source = "git+https://github.com/gattaca-com/flux#6119504e55e6db4fba88bcaacc78637b7fff95be" +source = "git+https://github.com/gattaca-com/flux?rev=7b043e20c33cf3d23a0c1a8e06fc06298c010662#7b043e20c33cf3d23a0c1a8e06fc06298c010662" dependencies = [ "bitcode", "core_affinity", @@ -4556,7 +4556,7 @@ dependencies = [ [[package]] name = "flux-communication" version = "0.0.26" -source = "git+https://github.com/gattaca-com/flux#6119504e55e6db4fba88bcaacc78637b7fff95be" +source = "git+https://github.com/gattaca-com/flux?rev=7b043e20c33cf3d23a0c1a8e06fc06298c010662#7b043e20c33cf3d23a0c1a8e06fc06298c010662" dependencies = [ "directories", "flux-timing", @@ -4570,7 +4570,7 @@ dependencies = [ [[package]] name = "flux-network" version = "0.0.8" -source = "git+https://github.com/gattaca-com/flux#6119504e55e6db4fba88bcaacc78637b7fff95be" +source = "git+https://github.com/gattaca-com/flux?rev=7b043e20c33cf3d23a0c1a8e06fc06298c010662#7b043e20c33cf3d23a0c1a8e06fc06298c010662" dependencies = [ "flux-communication", "flux-timing", @@ -4583,7 +4583,7 @@ dependencies = [ [[package]] name = "flux-timing" version = "0.0.15" -source = "git+https://github.com/gattaca-com/flux#6119504e55e6db4fba88bcaacc78637b7fff95be" +source = "git+https://github.com/gattaca-com/flux?rev=7b043e20c33cf3d23a0c1a8e06fc06298c010662#7b043e20c33cf3d23a0c1a8e06fc06298c010662" dependencies = [ "bitcode", "chrono", @@ -4601,7 +4601,7 @@ dependencies = [ [[package]] name = "flux-utils" version = "0.0.22" -source = "git+https://github.com/gattaca-com/flux#6119504e55e6db4fba88bcaacc78637b7fff95be" +source = "git+https://github.com/gattaca-com/flux?rev=7b043e20c33cf3d23a0c1a8e06fc06298c010662#7b043e20c33cf3d23a0c1a8e06fc06298c010662" dependencies = [ "core_affinity", "directories", @@ -12913,7 +12913,7 @@ checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] name = "spine-derive" version = "0.0.9" -source = "git+https://github.com/gattaca-com/flux#6119504e55e6db4fba88bcaacc78637b7fff95be" +source = "git+https://github.com/gattaca-com/flux?rev=7b043e20c33cf3d23a0c1a8e06fc06298c010662#7b043e20c33cf3d23a0c1a8e06fc06298c010662" dependencies = [ "proc-macro2", "quote", @@ -14243,12 +14243,12 @@ dependencies = [ [[package]] name = "type-hash" version = "0.0.1" -source = "git+https://github.com/gattaca-com/flux#6119504e55e6db4fba88bcaacc78637b7fff95be" +source = "git+https://github.com/gattaca-com/flux?rev=7b043e20c33cf3d23a0c1a8e06fc06298c010662#7b043e20c33cf3d23a0c1a8e06fc06298c010662" [[package]] name = "type-hash-derive" version = "0.0.4" -source = "git+https://github.com/gattaca-com/flux#6119504e55e6db4fba88bcaacc78637b7fff95be" +source = "git+https://github.com/gattaca-com/flux?rev=7b043e20c33cf3d23a0c1a8e06fc06298c010662#7b043e20c33cf3d23a0c1a8e06fc06298c010662" dependencies = [ "proc-macro-crate", "proc-macro2", diff --git a/Cargo.toml b/Cargo.toml index d626c1b8a..3342e152b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,8 +41,8 @@ ethereum_ssz_derive = "0.9" ethers = "2.0.14" eyre = "0.6.12" flate2 = "1.0" -flux = { git = "https://github.com/gattaca-com/flux" } -flux-network = { package = "flux-network", git = "https://github.com/gattaca-com/flux" } +flux = { git = "https://github.com/gattaca-com/flux", rev = "7b043e20c33cf3d23a0c1a8e06fc06298c010662"} +flux-network = { package = "flux-network", git = "https://github.com/gattaca-com/flux", rev = "7b043e20c33cf3d23a0c1a8e06fc06298c010662" } futures = "0.3" futures-util = { version = "0.3", features = ["compat"] } helix-common = { path = "crates/common" } diff --git a/crates/common/src/config.rs b/crates/common/src/config.rs index 4e777eb25..d1276b577 100644 --- a/crates/common/src/config.rs +++ b/crates/common/src/config.rs @@ -98,7 +98,7 @@ impl RelayConfig { gossip_payload_on_header: false, api_port: 4040, tcp_port: 4041, - tcp_max_connections: Default::default(), + tcp_max_connections: 512, } } } diff --git a/crates/relay/src/api/builder/error.rs b/crates/relay/src/api/builder/error.rs index d371b927f..f05dae6ee 100644 --- a/crates/relay/src/api/builder/error.rs +++ b/crates/relay/src/api/builder/error.rs @@ -1,6 +1,6 @@ use axum::response::{IntoResponse, Response}; use helix_common::{local_cache::AuctioneerError, simulator::BlockSimError}; -use helix_types::{BlockValidationError, HydrationError, SigError}; +use helix_types::{BlockValidationError, BlsPublicKeyBytes, HydrationError, SigError}; use http::StatusCode; use crate::{auctioneer::OrderValidationError, database::error::DatabaseError}; @@ -60,6 +60,11 @@ pub enum BuilderApiError { #[error("internal error")] InternalError, + + #[error( + "submission pubkey doesn't match registration message pubkey; expected: {0}, receieved: {1}" + )] + InvalidBuilderPubkey(BlsPublicKeyBytes, BlsPublicKeyBytes), } impl IntoResponse for BuilderApiError { @@ -75,6 +80,7 @@ impl IntoResponse for BuilderApiError { BuilderApiError::SigError(_) | BuilderApiError::SimOnNextSlot | BuilderApiError::MergeableOrdersNotFound(_) | + BuilderApiError::InvalidBuilderPubkey(_, _) | BuilderApiError::DeliveringPayload { .. } => StatusCode::BAD_REQUEST, BuilderApiError::InvalidApiKey | diff --git a/crates/relay/src/api/builder/submit_block.rs b/crates/relay/src/api/builder/submit_block.rs index 62de38e57..d6f3f21f6 100644 --- a/crates/relay/src/api/builder/submit_block.rs +++ b/crates/relay/src/api/builder/submit_block.rs @@ -10,7 +10,7 @@ use tracing::{error, trace}; use super::api::BuilderApi; use crate::{ api::{Api, builder::error::BuilderApiError}, - auctioneer::headers_map_to_bid_submission_header, + auctioneer::{BlockSubResultSender, headers_map_to_bid_submission_header}, }; impl BuilderApi { @@ -40,19 +40,25 @@ impl BuilderApi { let (header, sequence, encoding, compression, api_key) = headers_map_to_bid_submission_header(headers); - let Ok(rx) = api.auctioneer_handle.block_submission( - header, - sequence, - encoding, - compression, - api_key, - body, - trace, - false, - ) else { + let (tx, rx) = tokio::sync::oneshot::channel(); + if api + .auctioneer_handle + .block_submission( + header, + sequence, + encoding, + compression, + api_key, + body, + trace, + BlockSubResultSender::OneShot(tx), + None, + ) + .is_err() + { error!("failed sending request to worker"); return Err(BuilderApiError::InternalError); - }; + } let res = match rx.await { Ok((_, res)) => res, diff --git a/crates/relay/src/api/builder/top_bid.rs b/crates/relay/src/api/builder/top_bid.rs index 977825f23..6d9f6a484 100644 --- a/crates/relay/src/api/builder/top_bid.rs +++ b/crates/relay/src/api/builder/top_bid.rs @@ -25,8 +25,7 @@ impl BuilderApi { let Some(api_key) = headers .get(HEADER_API_KEY) .or(headers.get(HEADER_API_TOKEN)) - .map(|key| key.to_str().ok()) - .flatten() + .and_then(|key| key.to_str().ok()) else { return Err(BuilderApiError::InvalidApiKey); }; diff --git a/crates/relay/src/auctioneer/context.rs b/crates/relay/src/auctioneer/context.rs index cb2c6a8e6..3baf603a6 100644 --- a/crates/relay/src/auctioneer/context.rs +++ b/crates/relay/src/auctioneer/context.rs @@ -214,7 +214,7 @@ impl Context { if let Some(res_tx) = result.res_tx { // submission was initially valid but by the time sim finished the slot already // progressed - let _ = res_tx.send((result.request_id, Err(BuilderApiError::SimOnNextSlot))); + res_tx.try_send((result.request_id, Err(BuilderApiError::SimOnNextSlot))); } } diff --git a/crates/relay/src/auctioneer/decoder.rs b/crates/relay/src/auctioneer/decoder.rs index 885f33965..643c17eca 100644 --- a/crates/relay/src/auctioneer/decoder.rs +++ b/crates/relay/src/auctioneer/decoder.rs @@ -10,7 +10,7 @@ use helix_common::metrics::{ SUBMISSION_BY_COMPRESSION, SUBMISSION_BY_ENCODING, SUBMISSION_COMPRESSED_BYTES, SUBMISSION_DECOMPRESSED_BYTES, }; -use helix_types::{BlsPublicKeyBytes, ForkName, ForkVersionDecode}; +use helix_types::{BlsPublicKeyBytes, ForkName, ForkVersionDecode, SeqNum}; use http::{ HeaderMap, HeaderValue, header::{CONTENT_ENCODING, CONTENT_TYPE}, @@ -59,10 +59,11 @@ pub enum MergeType { } impl MergeType { - pub fn from_headers(header_map: &HeaderMap) -> Self { + pub fn from_headers(header_map: &HeaderMap, sub_type: Option) -> Self { match header_map.get(HEADER_MERGE_TYPE) { None => { - if matches!(header_map.get(HEADER_IS_MERGEABLE), Some(header) if header == HeaderValue::from_static("true")) + if sub_type.is_some_and(|sub_type| sub_type == SubmissionType::Merge) || + matches!(header_map.get(HEADER_IS_MERGEABLE), Some(header) if header == HeaderValue::from_static("true")) { MergeType::Mergeable } else { @@ -70,7 +71,7 @@ impl MergeType { } } Some(merge_type) => { - merge_type.to_str().ok().map(|t| t.parse().ok()).flatten().unwrap_or_default() + merge_type.to_str().ok().and_then(|t| t.parse().ok()).unwrap_or_default() } } } @@ -348,7 +349,7 @@ fn gzip_size_hint(buf: &[u8]) -> Option { pub fn headers_map_to_bid_submission_header( headers: http::header::HeaderMap, -) -> (BidSubmissionHeader, Option, Encoding, Compression, Option) { +) -> (BidSubmissionHeader, Option, Encoding, Compression, Option) { let mut flags = BidSubmissionFlags::default(); if matches!(headers.get(HEADER_WITH_ADJUSTMENTS), Some(header) if header == HeaderValue::from_static("true")) @@ -359,23 +360,15 @@ pub fn headers_map_to_bid_submission_header( flags.set(BidSubmissionFlags::IS_DEHYDRATED, true); } - if let Some(submission_type) = SubmissionType::from_headers(&headers) { - match submission_type { - SubmissionType::Dehydrated => { - flags.set(BidSubmissionFlags::IS_DEHYDRATED, true); - } - SubmissionType::Merge => { - // TODO @nina - // flags.set(BidSubmissionFlags::WITH_MERGEABLE_DATA, true); - } - SubmissionType::Default => {} - } + let submission_type = SubmissionType::from_headers(&headers); + if submission_type.is_some_and(|sub_type| sub_type == SubmissionType::Dehydrated) { + flags.set(BidSubmissionFlags::IS_DEHYDRATED, true); } let sequence_number = headers .get(HEADER_SEQUENCE) .and_then(|seq| seq.to_str().ok()) - .and_then(|seq| seq.parse::().ok()); + .and_then(|seq| seq.parse::().ok()); const GZIP_HEADER: HeaderValue = HeaderValue::from_static("gzip"); const ZSTD_HEADER: HeaderValue = HeaderValue::from_static("zstd"); @@ -393,13 +386,12 @@ pub fn headers_map_to_bid_submission_header( _ => Encoding::Json, }; - let merge_type = MergeType::from_headers(&headers); + let merge_type = MergeType::from_headers(&headers, submission_type); let api_key = headers .get(HEADER_API_KEY) .or(headers.get(HEADER_API_TOKEN)) - .map(|key| key.to_str().map(|key| key.to_owned()).ok()) - .flatten(); + .and_then(|key| key.to_str().map(|key| key.to_owned()).ok()); let header = BidSubmissionHeader { sequence_number: sequence_number.unwrap_or_default(), diff --git a/crates/relay/src/auctioneer/handle.rs b/crates/relay/src/auctioneer/handle.rs index 366fe7527..6fad59798 100644 --- a/crates/relay/src/auctioneer/handle.rs +++ b/crates/relay/src/auctioneer/handle.rs @@ -1,7 +1,9 @@ use std::{ops::Range, sync::Arc, time::Instant}; use helix_common::{GetPayloadTrace, SubmissionTrace, api::proposer_api::GetHeaderParams}; -use helix_types::{BlsPublicKeyBytes, SignedBlindedBeaconBlock, SignedValidatorRegistration}; +use helix_types::{ + BlsPublicKeyBytes, SeqNum, SignedBlindedBeaconBlock, SignedValidatorRegistration, +}; use tokio::sync::oneshot; use tracing::trace; @@ -9,7 +11,8 @@ use crate::{ auctioneer::{ decoder::{Compression, Encoding}, types::{ - Event, GetHeaderResult, GetPayloadResult, RegWorkerJob, SubWorkerJob, SubmissionResult, + BlockSubResultSender, Event, GetHeaderResult, GetPayloadResult, RegWorkerJob, + SubWorkerJob, SubmissionResult, }, }, gossip::BroadcastPayloadParams, @@ -33,15 +36,15 @@ impl AuctioneerHandle { pub fn block_submission( &self, header: BidSubmissionHeader, - sequence: Option, + sequence: Option, encoding: Encoding, compression: Compression, api_key: Option, body: bytes::Bytes, trace: SubmissionTrace, - skip_sigverify: bool, - ) -> Result, ChannelFull> { - let (tx, rx) = oneshot::channel(); + res_tx: BlockSubResultSender, + expected_pubkey: Option, + ) -> Result<(), ChannelFull> { trace!("sending to worker"); self.worker .try_send(SubWorkerJob::BlockSubmission { @@ -52,13 +55,12 @@ impl AuctioneerHandle { api_key, body, trace, - res_tx: tx, + res_tx, span: tracing::Span::current(), sent_at: Instant::now(), - skip_sigverify, + expected_pubkey, }) - .map_err(|_| ChannelFull)?; - Ok(rx) + .map_err(|_| ChannelFull) } pub fn get_header( diff --git a/crates/relay/src/auctioneer/mod.rs b/crates/relay/src/auctioneer/mod.rs index 4d6e8c9bb..6254487be 100644 --- a/crates/relay/src/auctioneer/mod.rs +++ b/crates/relay/src/auctioneer/mod.rs @@ -45,7 +45,7 @@ pub use crate::auctioneer::{ context::Context, decoder::{Compression, Encoding, MergeType, headers_map_to_bid_submission_header}, simulator::{SimulatorRequest, client::SimulatorClient, manager::SimulatorManager}, - types::SubmissionResult, // move to types? + types::{BlockSubResultSender, SubmissionResult}, // move to types? }; use crate::{ HelixSpine, PostgresDatabaseService, @@ -96,7 +96,7 @@ impl Auctioneer { impl Tile for Auctioneer { fn loop_body(&mut self, _adapter: &mut flux::spine::SpineAdapter) { for event in self.event_rx.try_iter() { - self.state.step(event, &mut self.ctx, &mut self.tel, _adapter); + self.state.step(event, &mut self.ctx, &mut self.tel); } self.tel.telemetry(&self.event_rx); @@ -140,18 +140,12 @@ impl Default for State { // TODO: tokio metrics impl State { - fn step( - &mut self, - event: Event, - ctx: &mut Context, - tel: &mut Telemetry, - _adapter: &mut flux::spine::SpineAdapter, - ) { + fn step(&mut self, event: Event, ctx: &mut Context, tel: &mut Telemetry) { let start = Instant::now(); let start_state = self.as_str(); let event_tag = event.as_str(); - self._step(event, ctx, _adapter); + self._step(event, ctx); let end_state = self.as_str(); let step_dur = start.elapsed(); @@ -165,12 +159,7 @@ impl State { .observe(step_dur.as_nanos() as f64 / 1000.); } - fn _step( - &mut self, - event: Event, - ctx: &mut Context, - _adapter: &mut flux::spine::SpineAdapter, - ) { + fn _step(&mut self, event: Event, ctx: &mut Context) { match (&self, event) { ///////////// LIFECYCLE EVENTS (ALWAYS VALID) ///////////// @@ -431,7 +420,7 @@ impl State { State::Broadcasting { slot_data: slot_ctx, .. }, Event::Submission { submission_data, res_tx, .. }, ) => { - let _ = res_tx.send(( + res_tx.try_send(( submission_data.request_id, Err(BuilderApiError::DeliveringPayload { bid_slot: submission_data.bid_slot(), @@ -483,12 +472,12 @@ impl State { (State::Slot { bid_slot, .. }, Event::Submission { res_tx, submission_data, .. }) => { if submission_data.bid_slot() == bid_slot.as_u64() { // either not registered or waiting for full data from housekepper - let _ = res_tx.send(( + res_tx.try_send(( submission_data.request_id, Err(BuilderApiError::ProposerDutyNotFound), )); } else { - let _ = res_tx.send(( + res_tx.try_send(( submission_data.request_id, Err(BuilderApiError::BidValidation( helix_types::BlockValidationError::SubmissionForWrongSlot { diff --git a/crates/relay/src/auctioneer/simulator/manager.rs b/crates/relay/src/auctioneer/simulator/manager.rs index 00a978a4d..bdead7f48 100644 --- a/crates/relay/src/auctioneer/simulator/manager.rs +++ b/crates/relay/src/auctioneer/simulator/manager.rs @@ -11,13 +11,13 @@ use helix_common::{ SimulatorConfig, SubmissionTrace, bid_submission::OptimisticVersion, is_local_dev, metrics::SimulatorMetrics, record_submission_step, simulator::BlockSimError, spawn_tracked, }; -use helix_types::{BlsPublicKeyBytes, SignedBidSubmission, SubmissionVersion}; -use tokio::sync::oneshot; +use helix_types::{BlsPublicKeyBytes, SeqNum, SignedBidSubmission, SubmissionVersion}; use tracing::{debug, error, info, warn}; use crate::{ api::service::SIMULATOR_REQUEST_TIMEOUT, auctioneer::{ + BlockSubResultSender, simulator::{BlockMergeRequest, SimulatorRequest, client::SimulatorClient}, types::{Event, SubmissionResult}, }, @@ -41,9 +41,9 @@ struct LocalTelemetry { pub type SimulationResult = (usize, Option); pub struct SimulationResultInner { pub result: Result<(), BlockSimError>, - pub request_id: u64, + pub request_id: SeqNum, // Some if not optimistic - pub res_tx: Option>, + pub res_tx: Option>, // TODO: move up pub paused_until: Option, pub submission: SignedBidSubmission, diff --git a/crates/relay/src/auctioneer/simulator/mod.rs b/crates/relay/src/auctioneer/simulator/mod.rs index f59921eb3..5508c7229 100644 --- a/crates/relay/src/auctioneer/simulator/mod.rs +++ b/crates/relay/src/auctioneer/simulator/mod.rs @@ -7,12 +7,11 @@ use helix_common::{ }; use helix_types::{ BidTrace, BlobsBundle, BlsPublicKeyBytes, BlsSignatureBytes, BuilderInclusionResult, - ExecutionPayload, ExecutionRequests, MergeableOrderWithOrigin, SignedBidSubmission, + ExecutionPayload, ExecutionRequests, MergeableOrderWithOrigin, SeqNum, SignedBidSubmission, SubmissionVersion, }; -use tokio::sync::oneshot; -use crate::auctioneer::types::SubmissionResult; +use crate::auctioneer::{BlockSubResultSender, types::SubmissionResult}; pub mod client; pub mod manager; @@ -111,9 +110,9 @@ pub struct SimulatorRequest { pub is_top_bid: bool, pub version: SubmissionVersion, pub submission: SignedBidSubmission, - pub submission_request_id: u64, + pub submission_request_id: SeqNum, /// None if optimistic - pub res_tx: Option>, + pub res_tx: Option>, pub trace: SubmissionTrace, // only Some for dehydrated submissions pub tx_root: Option, diff --git a/crates/relay/src/auctioneer/submit_block.rs b/crates/relay/src/auctioneer/submit_block.rs index 2a6f0e206..b1e07195a 100644 --- a/crates/relay/src/auctioneer/submit_block.rs +++ b/crates/relay/src/auctioneer/submit_block.rs @@ -8,15 +8,15 @@ use helix_common::{ record_submission_step, spawn_tracked, }; use helix_types::{ - BidAdjustmentData, BlockValidationError, MergeableOrdersWithPref, SignedBidSubmission, + BidAdjustmentData, BlockValidationError, MergeableOrdersWithPref, SeqNum, SignedBidSubmission, SubmissionVersion, }; -use tokio::sync::oneshot; use tracing::{error, trace}; use crate::{ api::builder::error::BuilderApiError, auctioneer::{ + BlockSubResultSender, bid_adjustor::BidAdjustor, context::Context, simulator::{BlockSimRequest, SimulatorRequest, manager::SimulationResult}, @@ -29,14 +29,14 @@ impl Context { pub(super) fn handle_submission( &mut self, submission_data: SubmissionData, - res_tx: oneshot::Sender, + res_tx: BlockSubResultSender, slot_data: &SlotData, ) { let request_id = submission_data.request_id; match self.validate_and_sort(submission_data, slot_data) { Ok((validated, optimistic_version, merging_data)) => { let res_tx = if optimistic_version.is_optimistic() { - let _ = res_tx.send((request_id, Ok(()))); + res_tx.try_send((request_id, Ok(()))); None } else { Some(res_tx) @@ -78,7 +78,7 @@ impl Context { } Err(err) => { - let _ = res_tx.send((request_id, Err(err))); + res_tx.try_send((request_id, Err(err))); } } } @@ -95,7 +95,7 @@ impl Context { Err(err) if err.is_demotable() => { self.bid_sorter.demote(*result.submission.builder_public_key()); if let Some(res_tx) = res_tx { - let _ = res_tx.send(( + res_tx.try_send(( result.request_id, Err(BuilderApiError::BlockSimulation(err.clone())), )); @@ -115,7 +115,7 @@ impl Context { } self.request_merged_block(); - let _ = res_tx.send((result.request_id, Ok(()))); + res_tx.try_send((result.request_id, Ok(()))); }; } } @@ -224,7 +224,7 @@ impl Context { fn prep_data_to_store_and_sim( &mut self, validated: ValidatedData, - res_tx: Option>, + res_tx: Option>, slot_data: &SlotData, ) -> (SimulatorRequest, PayloadEntry) { let request = BlockSimRequest::new( @@ -316,7 +316,7 @@ impl Context { } pub struct ValidatedData<'a> { - pub request_id: u64, + pub request_id: SeqNum, pub submission: SignedBidSubmission, pub tx_root: Option, pub payload_attributes: &'a PayloadAttributesUpdate, diff --git a/crates/relay/src/auctioneer/types.rs b/crates/relay/src/auctioneer/types.rs index a2cca5d70..afecb7ea3 100644 --- a/crates/relay/src/auctioneer/types.rs +++ b/crates/relay/src/auctioneer/types.rs @@ -16,7 +16,7 @@ use helix_common::{ use helix_types::{ BidAdjustmentData, BlsPublicKeyBytes, BuilderBid, DehydratedBidSubmission, ExecutionPayload, ExecutionRequests, ForkName, GetPayloadResponse, MergeableOrdersWithPref, PayloadAndBlobs, - SignedBidSubmission, SignedBlindedBeaconBlock, SignedValidatorRegistration, Slot, + SeqNum, SignedBidSubmission, SignedBlindedBeaconBlock, SignedValidatorRegistration, Slot, SubmissionVersion, VersionedSignedProposal, mock_public_key_bytes, }; use rustc_hash::FxHashMap; @@ -37,10 +37,37 @@ use crate::{ tcp_bid_recv::types::BidSubmissionHeader, }; -pub type SubmissionResult = (u64, Result<(), BuilderApiError>); +pub type SubmissionResult = (SeqNum, Result<(), BuilderApiError>); pub type GetHeaderResult = Result; pub type GetPayloadResult = Result; +pub enum BlockSubResultSender { + OneShot(oneshot::Sender), + Shared(crossbeam_channel::Sender), +} + +impl BlockSubResultSender { + pub fn try_send(self, data: T) { + match self { + Self::OneShot(tx) => { + let _ = tx.send(data); + } + Self::Shared(tx) => { + if let Err(e) = tx.try_send(data) { + tracing::error!(err=%e, "failed to send submission result to worker"); + } + } + } + } + + pub fn is_closed(&self) -> bool { + match self { + Self::OneShot(tx) => tx.is_closed(), + Self::Shared(_) => false, + } + } +} + pub struct GetPayloadResultData { pub to_proposer: GetPayloadResponse, pub to_publish: VersionedSignedProposal, @@ -51,7 +78,7 @@ pub struct GetPayloadResultData { #[derive(Clone, Debug)] pub struct SubmissionData { - pub request_id: u64, + pub request_id: SeqNum, pub submission: Submission, pub merging_data: Option, pub bid_adjustment_data: Option, @@ -305,16 +332,16 @@ impl PayloadBidDataRef<'_> { pub enum SubWorkerJob { BlockSubmission { header: BidSubmissionHeader, - sequence: Option, + sequence: Option, encoding: Encoding, api_key: Option, compression: Compression, body: bytes::Bytes, trace: SubmissionTrace, // TODO: replace this with better tracing - res_tx: oneshot::Sender, + res_tx: BlockSubResultSender, span: tracing::Span, sent_at: Instant, - skip_sigverify: bool, + expected_pubkey: Option, }, GetPayload { @@ -379,7 +406,7 @@ pub enum Event { }, Submission { submission_data: SubmissionData, - res_tx: oneshot::Sender, + res_tx: BlockSubResultSender, span: tracing::Span, sent_at: Instant, }, diff --git a/crates/relay/src/auctioneer/worker.rs b/crates/relay/src/auctioneer/worker.rs index 9b18ed9d8..62e560972 100644 --- a/crates/relay/src/auctioneer/worker.rs +++ b/crates/relay/src/auctioneer/worker.rs @@ -15,8 +15,8 @@ use helix_common::{ }; use helix_types::{ BidAdjustmentData, BlockMergingData, BlsPublicKey, BlsPublicKeyBytes, DehydratedBidSubmission, - DehydratedBidSubmissionFuluWithAdjustments, ExecPayload, MergeableOrdersWithPref, SigError, - SignedBidSubmission, SignedBidSubmissionFuluWithAdjustments, + DehydratedBidSubmissionFuluWithAdjustments, ExecPayload, MergeableOrdersWithPref, SeqNum, + SigError, SignedBidSubmission, SignedBidSubmissionFuluWithAdjustments, SignedBidSubmissionWithMergingData, SignedBlindedBeaconBlock, SignedValidatorRegistration, SubmissionVersion, }; @@ -126,7 +126,7 @@ impl SubWorker { res_tx, span, sent_at, - skip_sigverify, + expected_pubkey, } => { record_submission_step("worker_recv", sent_at.elapsed()); let guard = span.enter(); @@ -136,9 +136,9 @@ impl SubWorker { header, sequence, api_key, - skip_sigverify, encoding, compression, + expected_pubkey, body, &mut trace, ) { @@ -207,7 +207,7 @@ impl SubWorker { } Err(err) => { - let _ = res_tx.send((request_id, Err(err))); + res_tx.try_send((request_id, Err(err))); } } } @@ -252,11 +252,11 @@ impl SubWorker { fn handle_block_submission( &self, header: BidSubmissionHeader, - sequence: Option, + sequence: Option, api_key: Option, - mut skip_sigverify: bool, encoding: Encoding, compression: Compression, + expected_pubkey: Option, body: bytes::Bytes, trace: &mut SubmissionTrace, ) -> Result< @@ -271,10 +271,15 @@ impl SubWorker { let is_dehydrated = header.flags.is_dehydrated(); let builder_pubkey = decoder.extract_builder_pubkey(body.as_ref(), with_mergeable_data)?; - if !skip_sigverify { - skip_sigverify = api_key - .is_some_and(|api_key| self.cache.validate_api_key(&api_key, &builder_pubkey)); - } + let skip_sigverify = if let Some(expected_pubkey) = expected_pubkey { + if builder_pubkey != expected_pubkey { + return Err(BuilderApiError::InvalidBuilderPubkey(expected_pubkey, builder_pubkey)); + } + + true + } else { + api_key.is_some_and(|api_key| self.cache.validate_api_key(&api_key, &builder_pubkey)) + }; trace!( ?sequence, diff --git a/crates/relay/src/main.rs b/crates/relay/src/main.rs index 9b3e0373b..e6f62f21e 100644 --- a/crates/relay/src/main.rs +++ b/crates/relay/src/main.rs @@ -119,10 +119,10 @@ async fn run(instance_id: String, config: RelayConfig, keypair: BlsKeypair) -> e .map_err(|e| eyre!("housekeeper init: {e}"))?; let terminating = Arc::new(AtomicBool::default()); - let termination_grace_period = config.router_config.shutdown_delay_ms; + let termination_grace_period = Duration::from_millis(config.router_config.shutdown_delay_ms); let spine = HelixSpine::new(None); - spine.start(None, Some(Duration::from_millis(termination_grace_period)), |spine| { + spine.start(None, Some(termination_grace_period), |spine| { start_admin_service(local_cache.clone(), expect_env_var(ADMIN_TOKEN_ENV_VAR)); let auctioneer_handle = AuctioneerHandle::new(sub_worker_tx, event_tx.clone()); @@ -220,10 +220,10 @@ async fn run(instance_id: String, config: RelayConfig, keypair: BlsKeypair) -> e terminating.store(true, Ordering::Relaxed); - if termination_grace_period != 0 { - tracing::info!("Pausing for {termination_grace_period}ms before exit"); + if !termination_grace_period.is_zero() { + tracing::info!("Pausing for {}ms before exit", termination_grace_period.as_millis()); - tokio::time::sleep(Duration::from_millis(termination_grace_period)).await; + tokio::time::sleep(termination_grace_period).await; } Ok(()) diff --git a/crates/relay/src/tcp_bid_recv/mod.rs b/crates/relay/src/tcp_bid_recv/mod.rs index b67eacb16..61d658a60 100644 --- a/crates/relay/src/tcp_bid_recv/mod.rs +++ b/crates/relay/src/tcp_bid_recv/mod.rs @@ -1,9 +1,6 @@ -use std::{ - collections::{HashMap, HashSet}, - net::SocketAddr, - sync::Arc, -}; +use std::{collections::HashMap, net::SocketAddr, sync::Arc}; +use crossbeam_channel::{Receiver, Sender}; use dashmap::DashMap; use flux::{spine::FluxSpine, tile::Tile}; use flux_network::{ @@ -11,14 +8,13 @@ use flux_network::{ tcp::{SendBehavior, TcpConnector, TcpTelemetry}, }; use helix_common::SubmissionTrace; -use helix_types::BlsPublicKeyBytes; +use helix_types::{BlsPublicKeyBytes, SeqNum}; use ssz::{Decode, Encode}; -use tokio::sync::oneshot::{Receiver, error::TryRecvError}; use uuid::Uuid; use crate::{ AuctioneerHandle, HelixSpine, SubmissionResult, - auctioneer::Encoding, + auctioneer::{BlockSubResultSender, Encoding}, tcp_bid_recv::types::{BidSubmission, BidSubmissionResponse, RegistrationMsg}, }; @@ -34,11 +30,13 @@ pub struct BidSubmissionTcpListener { auctioneer_handle: AuctioneerHandle, api_key_cache: Arc>>, - in_flight: HashMap>, - to_remove: Vec, + rx: Receiver, + tx: Sender, + + in_flight: HashMap, to_disconnect: Vec, - registered: HashSet, - submission_errors: Vec<(Token, Option, BidSubmissionError)>, + registered: HashMap, + submission_errors: Vec<(Token, Option, BidSubmissionError)>, } impl BidSubmissionTcpListener { @@ -51,32 +49,38 @@ impl BidSubmissionTcpListener { let listener = TcpConnector::default() .with_telemetry(TcpTelemetry::Enabled { app_name: HelixSpine::app_name() }) .with_socket_buf_size(64 * 1024 * 1024); // 64MB + + let (tx, rx) = crossbeam_channel::bounded(10_000); + Self { listener_addr, listener, listener_token: None, auctioneer_handle, api_key_cache, + rx, + tx, in_flight: HashMap::with_capacity(max_connections), - to_remove: Vec::with_capacity(max_connections), to_disconnect: Vec::with_capacity(max_connections), - registered: HashSet::with_capacity(max_connections), + registered: HashMap::with_capacity(max_connections), submission_errors: Vec::with_capacity(max_connections), } } #[tracing::instrument(skip_all, fields( - id =% bid.header.sequence_number, + id =% Uuid::from_u128(bid.header.sequence_number), slot = tracing::field::Empty, builder_pubkey = tracing::field::Empty, builder_id = tracing::field::Empty, block_hash = tracing::field::Empty, ))] fn accept_bid_submission( + tx: Sender, auctioneer_handle: &AuctioneerHandle, bid: BidSubmission, - ) -> Result, BidSubmissionError> { + expected_pubkey: BlsPublicKeyBytes, + ) -> Result<(), BidSubmissionError> { let compression = bid.header.compression(); auctioneer_handle @@ -88,7 +92,8 @@ impl BidSubmissionTcpListener { None, bid.data, SubmissionTrace::default(), - true, + BlockSubResultSender::Shared(tx), + Some(expected_pubkey), ) .map_err(|_| BidSubmissionError::InternalError) } @@ -110,7 +115,26 @@ impl Tile for BidSubmissionTcpListener { ); }, |token, msg, _| { - if !self.registered.contains(&token) { + if let Some(expected_pubkey) = self.registered.get(&token) { + match BidSubmission::try_from(msg) { + Ok(bid) => { + let request_id = bid.header.sequence_number; + match Self::accept_bid_submission(self.tx.clone(), &self.auctioneer_handle, bid, *expected_pubkey) { + Ok(_) => { + self.in_flight.insert(request_id, token); + } + Err(e) => { + tracing::error!(err=%e, "failed to send bid submission to worker"); + self.submission_errors.push((token, Some(request_id), e)); + } + } + }, + Err(e) => { + tracing::error!(err=%e, "failed to deserialize the bid"); + self.submission_errors.push((token, None, e)); + } + }; + } else { let registration_message = RegistrationMsg::from_ssz_bytes(msg); match registration_message { @@ -121,7 +145,7 @@ impl Tile for BidSubmissionTcpListener { .get(&api_key) .is_some_and(|p| p.value().contains(&msg.builder_pubkey)) { - self.registered.insert(token); + self.registered.insert(token, msg.builder_pubkey); } else { tracing::error!( "unknown api key and pubkey pair: {} {}, disconnecting peer", @@ -136,31 +160,13 @@ impl Tile for BidSubmissionTcpListener { self.to_disconnect.push(token); } } - } else { - match BidSubmission::try_from(msg) { - Ok(bid) => { - let request_id = bid.header.sequence_number; - match Self::accept_bid_submission(&self.auctioneer_handle, bid) { - Ok(rx) => { - self.in_flight.insert(token, rx); - } - Err(e) => { - tracing::error!(err=%e, "failed to send bid submission to worker"); - self.submission_errors.push((token, Some(request_id), e)); - } - } - } - Err(e) => { - tracing::error!(err=%e, "failed to deserialize the bid"); - self.submission_errors.push((token, None, e)); - } - }; } }, ); for token in self.to_disconnect.drain(..) { self.listener.disconnect(token); + self.registered.remove(&token); } for (token, request_id, err) in self.submission_errors.drain(..) { @@ -170,24 +176,15 @@ impl Tile for BidSubmissionTcpListener { }); } - for (token, rx) in &mut self.in_flight { - match rx.try_recv() { - Ok((request_id, res)) => { - self.listener.write_or_enqueue_with(SendBehavior::Single(*token), |buffer| { - BidSubmissionResponse::from_builder_api_error(request_id, &res) - .ssz_append(buffer); - }); - self.to_remove.push(*token); - } - Err(err) if err == TryRecvError::Closed => { - self.to_remove.push(*token); - } - _ => {} + for (seq_num, result) in self.rx.try_iter() { + if let Some(token) = self.in_flight.remove(&seq_num) { + self.listener.write_or_enqueue_with(SendBehavior::Single(token), |buffer| { + BidSubmissionResponse::from_builder_api_error(seq_num, &result) + .ssz_append(buffer); + }); + } else { + tracing::error!(id=%seq_num, "connection token not found for submission result: {:?}", result); } } - - for token in self.to_remove.drain(..) { - self.in_flight.remove(&token); - } } } diff --git a/crates/relay/src/tcp_bid_recv/types.rs b/crates/relay/src/tcp_bid_recv/types.rs index b4f16cbd9..af6a89e35 100644 --- a/crates/relay/src/tcp_bid_recv/types.rs +++ b/crates/relay/src/tcp_bid_recv/types.rs @@ -1,7 +1,6 @@ use bytes::Bytes; -use helix_types::BlsPublicKeyBytes; +use helix_types::{BlsPublicKeyBytes, SeqNum}; use serde::{Deserialize, Serialize}; -use ssz::{Decode, DecodeError}; use ssz_derive::{Decode, Encode}; use crate::{ @@ -9,10 +8,13 @@ use crate::{ auctioneer::{Compression, MergeType}, }; +/// First message on a new TCP connection. SSZ-encoded. +/// Server validates the (api_key, builder_pubkey) pair against the key cache; on failure drops the +/// connection. #[repr(C)] #[derive(Debug, Clone, Decode)] pub struct RegistrationMsg { - pub api_key: [u8; 16], // this is a Uuid + pub api_key: [u8; 16], // UUID bytes pub builder_pubkey: BlsPublicKeyBytes, } @@ -38,6 +40,10 @@ impl TryFrom<&[u8]> for BidSubmission { type Error = BidSubmissionError; fn try_from(data: &[u8]) -> Result { + if data.len() < BID_SUB_HEADER_SIZE { + return Err(BidSubmissionError::SubmissionTooShort) + } + let header = BidSubmissionHeader::try_from(&data[..BID_SUB_HEADER_SIZE])?; tracing::trace!("{:?}", header); @@ -47,34 +53,40 @@ impl TryFrom<&[u8]> for BidSubmission { } } -#[repr(C)] -#[derive(Debug, Clone, Copy, Default)] +/// Wire header for bid submission. Manually encoded as +/// `[16B BE seq_number][1B merge_type][1B flags]` (18 bytes total). +/// The sequence_number is used as a unique identifier of the submission on both sides. +/// Unlike HTTP the api key is not sent, because it is validated on receipt of the registration +/// message. +#[derive(Debug, Clone, Copy, Default, PartialEq)] pub struct BidSubmissionHeader { - pub sequence_number: u64, + pub sequence_number: SeqNum, pub merge_type: MergeType, pub flags: BidSubmissionFlags, } -const BID_SUB_HEADER_SIZE: usize = 10; +const BID_SUB_HEADER_SIZE: usize = 18; impl TryFrom<&[u8]> for BidSubmissionHeader { type Error = BidSubmissionError; fn try_from(value: &[u8]) -> Result { - if value.len() < BID_SUB_HEADER_SIZE { - return Err(BidSubmissionError::SubmissionTooShort) - } - - let sequence_number = u64::from_be_bytes(value[..8].try_into().unwrap()); - let merge_type = MergeType::try_from(value[8]) - .map_err(|_| BidSubmissionError::InvalidMergeType(value[8]))?; - let flags = BidSubmissionFlags::from_bits_retain(value[9]); + let sequence_number = u128::from_be_bytes(value[..16].try_into().unwrap()); + let merge_type = MergeType::try_from(value[16]) + .map_err(|_| BidSubmissionError::InvalidMergeType(value[16]))?; + let flags = BidSubmissionFlags::from_bits_retain(value[17]); Ok(Self { sequence_number, merge_type, flags }) } } impl BidSubmissionHeader { + pub fn append_encoded(self, buffer: &mut Vec) { + buffer.extend_from_slice(&self.sequence_number.to_be_bytes()); + buffer.push(self.merge_type as u8); + buffer.push(self.flags.bits()); + } + pub fn compression(&self) -> Compression { if self.flags.is_zstd_compressed() { Compression::Zstd } else { Compression::None } } @@ -104,23 +116,6 @@ impl BidSubmissionFlags { } } -impl Decode for BidSubmissionFlags { - fn from_ssz_bytes(bytes: &[u8]) -> Result { - if bytes.len() != 1 { - return Err(DecodeError::InvalidByteLength { len: bytes.len(), expected: 1 }); - } - Ok(BidSubmissionFlags(bytes[0])) - } - - fn is_ssz_fixed_len() -> bool { - true - } - - fn ssz_fixed_len() -> usize { - 1 - } -} - #[repr(u8)] #[derive(Debug, Clone, Copy, Encode)] #[ssz(enum_behaviour = "tag")] @@ -155,16 +150,20 @@ impl From<&BidSubmissionError> for Status { } } +/// SSZ-encoded server response sent back in a single frame. #[repr(C)] #[derive(Debug, Clone, Encode)] pub struct BidSubmissionResponse { - pub error_msg: Vec, - pub sequence_number: u64, + pub sequence_number: SeqNum, pub status: Status, + pub error_msg: Vec, } impl BidSubmissionResponse { - pub fn from_builder_api_error(request_id: u64, result: &Result<(), BuilderApiError>) -> Self { + pub fn from_builder_api_error( + request_id: SeqNum, + result: &Result<(), BuilderApiError>, + ) -> Self { match result { Ok(()) => Self { sequence_number: request_id, @@ -179,7 +178,7 @@ impl BidSubmissionResponse { } } - pub fn from_bid_submission_error(request_id: &Option, e: &BidSubmissionError) -> Self { + pub fn from_bid_submission_error(request_id: &Option, e: &BidSubmissionError) -> Self { Self { sequence_number: request_id.unwrap_or_default(), status: Status::from(e), @@ -187,3 +186,33 @@ impl BidSubmissionResponse { } } } + +#[cfg(test)] +mod tests { + use crate::{ + auctioneer::MergeType, + tcp_bid_recv::{ + BidSubmissionHeader, + types::{BID_SUB_HEADER_SIZE, BidSubmissionFlags}, + }, + }; + + #[test] + fn test_bid_submission_header() { + let header = BidSubmissionHeader { + sequence_number: 1913u128, + merge_type: MergeType::Mergeable, + flags: BidSubmissionFlags::all(), + }; + + let mut buffer = Vec::new(); + header.append_encoded(&mut buffer); + + assert_eq!(buffer.len(), BID_SUB_HEADER_SIZE); + + let decoded = + BidSubmissionHeader::try_from(buffer.as_slice()).expect("failed to decode header"); + + assert_eq!(decoded, header); + } +} diff --git a/crates/types/src/bid_submission.rs b/crates/types/src/bid_submission.rs index dea19d8e8..0df3f66c5 100644 --- a/crates/types/src/bid_submission.rs +++ b/crates/types/src/bid_submission.rs @@ -14,6 +14,8 @@ use crate::{ bid_adjustment_data::BidAdjustmentData, error::SigError, fields::ExecutionRequests, }; +pub type SeqNum = u128; + #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Encode, Decode, TreeHash)] #[serde(deny_unknown_fields)] pub struct BidTrace { @@ -696,11 +698,11 @@ impl SignedBidSubmissionFuluWithAdjustments { #[derive(Clone, Copy, PartialEq, Eq)] pub struct SubmissionVersion { on_receive_ns: u64, - sequence: Option, + sequence: Option, } impl SubmissionVersion { - pub fn new(on_receive_ns: u64, sequence: Option) -> Self { + pub fn new(on_receive_ns: u64, sequence: Option) -> Self { Self { on_receive_ns, sequence } } From ca20f5b0821ac05a39d53810b21c5bf8c71ceb6c Mon Sep 17 00:00:00 2001 From: Nina Date: Mon, 16 Feb 2026 17:49:13 +0000 Subject: [PATCH 04/12] request ref + trace --- crates/relay/src/api/builder/submit_block.rs | 4 +- crates/relay/src/auctioneer/context.rs | 2 +- crates/relay/src/auctioneer/decoder.rs | 18 +++---- crates/relay/src/auctioneer/handle.rs | 10 ++-- crates/relay/src/auctioneer/mod.rs | 8 ++-- .../relay/src/auctioneer/simulator/manager.rs | 8 ++-- crates/relay/src/auctioneer/simulator/mod.rs | 9 ++-- crates/relay/src/auctioneer/submit_block.rs | 22 +++++---- crates/relay/src/auctioneer/types.rs | 13 +++-- crates/relay/src/auctioneer/worker.rs | 9 ++-- crates/relay/src/tcp_bid_recv/mod.rs | 48 +++++++++++-------- 11 files changed, 84 insertions(+), 67 deletions(-) diff --git a/crates/relay/src/api/builder/submit_block.rs b/crates/relay/src/api/builder/submit_block.rs index d6f3f21f6..45f2f3b8d 100644 --- a/crates/relay/src/api/builder/submit_block.rs +++ b/crates/relay/src/api/builder/submit_block.rs @@ -38,14 +38,14 @@ impl BuilderApi { let mut trace = SubmissionTrace::init_from_timings(timings); trace.metadata = api.api_provider.get_metadata(&headers); - let (header, sequence, encoding, compression, api_key) = + let (header, submission_ref, encoding, compression, api_key) = headers_map_to_bid_submission_header(headers); let (tx, rx) = tokio::sync::oneshot::channel(); if api .auctioneer_handle .block_submission( + submission_ref, header, - sequence, encoding, compression, api_key, diff --git a/crates/relay/src/auctioneer/context.rs b/crates/relay/src/auctioneer/context.rs index 3baf603a6..ebac3a91f 100644 --- a/crates/relay/src/auctioneer/context.rs +++ b/crates/relay/src/auctioneer/context.rs @@ -214,7 +214,7 @@ impl Context { if let Some(res_tx) = result.res_tx { // submission was initially valid but by the time sim finished the slot already // progressed - res_tx.try_send((result.request_id, Err(BuilderApiError::SimOnNextSlot))); + res_tx.try_send((result.submission_ref, Err(BuilderApiError::SimOnNextSlot))); } } diff --git a/crates/relay/src/auctioneer/decoder.rs b/crates/relay/src/auctioneer/decoder.rs index 643c17eca..a13e8efa0 100644 --- a/crates/relay/src/auctioneer/decoder.rs +++ b/crates/relay/src/auctioneer/decoder.rs @@ -10,7 +10,7 @@ use helix_common::metrics::{ SUBMISSION_BY_COMPRESSION, SUBMISSION_BY_ENCODING, SUBMISSION_COMPRESSED_BYTES, SUBMISSION_DECOMPRESSED_BYTES, }; -use helix_types::{BlsPublicKeyBytes, ForkName, ForkVersionDecode, SeqNum}; +use helix_types::{BlsPublicKeyBytes, ForkName, ForkVersionDecode}; use http::{ HeaderMap, HeaderValue, header::{CONTENT_ENCODING, CONTENT_TYPE}, @@ -30,6 +30,7 @@ use crate::{ HEADER_SEQUENCE, HEADER_SUBMISSION_TYPE, HEADER_WITH_ADJUSTMENTS, builder::{api::MAX_PAYLOAD_LENGTH, error::BuilderApiError}, }, + auctioneer::SubmissionRef, tcp_bid_recv::{BidSubmissionHeader, types::BidSubmissionFlags}, }; @@ -349,7 +350,7 @@ fn gzip_size_hint(buf: &[u8]) -> Option { pub fn headers_map_to_bid_submission_header( headers: http::header::HeaderMap, -) -> (BidSubmissionHeader, Option, Encoding, Compression, Option) { +) -> (BidSubmissionHeader, SubmissionRef, Encoding, Compression, Option) { let mut flags = BidSubmissionFlags::default(); if matches!(headers.get(HEADER_WITH_ADJUSTMENTS), Some(header) if header == HeaderValue::from_static("true")) @@ -365,7 +366,7 @@ pub fn headers_map_to_bid_submission_header( flags.set(BidSubmissionFlags::IS_DEHYDRATED, true); } - let sequence_number = headers + let seq_num = headers .get(HEADER_SEQUENCE) .and_then(|seq| seq.to_str().ok()) .and_then(|seq| seq.parse::().ok()); @@ -393,13 +394,12 @@ pub fn headers_map_to_bid_submission_header( .or(headers.get(HEADER_API_TOKEN)) .and_then(|key| key.to_str().map(|key| key.to_owned()).ok()); - let header = BidSubmissionHeader { - sequence_number: sequence_number.unwrap_or_default(), - merge_type, - flags, - }; + let header = + BidSubmissionHeader { sequence_number: seq_num.unwrap_or_default(), merge_type, flags }; + + let submission_ref = SubmissionRef { seq_num, token: None }; - (header, sequence_number, encoding, compression, api_key) + (header, submission_ref, encoding, compression, api_key) } #[cfg(test)] diff --git a/crates/relay/src/auctioneer/handle.rs b/crates/relay/src/auctioneer/handle.rs index 6fad59798..4b0d7c11e 100644 --- a/crates/relay/src/auctioneer/handle.rs +++ b/crates/relay/src/auctioneer/handle.rs @@ -1,9 +1,7 @@ use std::{ops::Range, sync::Arc, time::Instant}; use helix_common::{GetPayloadTrace, SubmissionTrace, api::proposer_api::GetHeaderParams}; -use helix_types::{ - BlsPublicKeyBytes, SeqNum, SignedBlindedBeaconBlock, SignedValidatorRegistration, -}; +use helix_types::{BlsPublicKeyBytes, SignedBlindedBeaconBlock, SignedValidatorRegistration}; use tokio::sync::oneshot; use tracing::trace; @@ -12,7 +10,7 @@ use crate::{ decoder::{Compression, Encoding}, types::{ BlockSubResultSender, Event, GetHeaderResult, GetPayloadResult, RegWorkerJob, - SubWorkerJob, SubmissionResult, + SubWorkerJob, SubmissionRef, SubmissionResult, }, }, gossip::BroadcastPayloadParams, @@ -35,8 +33,8 @@ impl AuctioneerHandle { pub fn block_submission( &self, + submission_ref: SubmissionRef, header: BidSubmissionHeader, - sequence: Option, encoding: Encoding, compression: Compression, api_key: Option, @@ -48,8 +46,8 @@ impl AuctioneerHandle { trace!("sending to worker"); self.worker .try_send(SubWorkerJob::BlockSubmission { + submission_ref, header, - sequence, encoding, compression, api_key, diff --git a/crates/relay/src/auctioneer/mod.rs b/crates/relay/src/auctioneer/mod.rs index 6254487be..d745f8143 100644 --- a/crates/relay/src/auctioneer/mod.rs +++ b/crates/relay/src/auctioneer/mod.rs @@ -45,7 +45,7 @@ pub use crate::auctioneer::{ context::Context, decoder::{Compression, Encoding, MergeType, headers_map_to_bid_submission_header}, simulator::{SimulatorRequest, client::SimulatorClient, manager::SimulatorManager}, - types::{BlockSubResultSender, SubmissionResult}, // move to types? + types::{BlockSubResultSender, SubmissionRef, SubmissionResult}, // move to types? }; use crate::{ HelixSpine, PostgresDatabaseService, @@ -421,7 +421,7 @@ impl State { Event::Submission { submission_data, res_tx, .. }, ) => { res_tx.try_send(( - submission_data.request_id, + submission_data.submission_ref, Err(BuilderApiError::DeliveringPayload { bid_slot: submission_data.bid_slot(), delivering: slot_ctx.bid_slot.as_u64(), @@ -473,12 +473,12 @@ impl State { if submission_data.bid_slot() == bid_slot.as_u64() { // either not registered or waiting for full data from housekepper res_tx.try_send(( - submission_data.request_id, + submission_data.submission_ref, Err(BuilderApiError::ProposerDutyNotFound), )); } else { res_tx.try_send(( - submission_data.request_id, + submission_data.submission_ref, Err(BuilderApiError::BidValidation( helix_types::BlockValidationError::SubmissionForWrongSlot { expected: *bid_slot, diff --git a/crates/relay/src/auctioneer/simulator/manager.rs b/crates/relay/src/auctioneer/simulator/manager.rs index bdead7f48..75614ac00 100644 --- a/crates/relay/src/auctioneer/simulator/manager.rs +++ b/crates/relay/src/auctioneer/simulator/manager.rs @@ -11,7 +11,7 @@ use helix_common::{ SimulatorConfig, SubmissionTrace, bid_submission::OptimisticVersion, is_local_dev, metrics::SimulatorMetrics, record_submission_step, simulator::BlockSimError, spawn_tracked, }; -use helix_types::{BlsPublicKeyBytes, SeqNum, SignedBidSubmission, SubmissionVersion}; +use helix_types::{BlsPublicKeyBytes, SignedBidSubmission, SubmissionVersion}; use tracing::{debug, error, info, warn}; use crate::{ @@ -19,7 +19,7 @@ use crate::{ auctioneer::{ BlockSubResultSender, simulator::{BlockMergeRequest, SimulatorRequest, client::SimulatorClient}, - types::{Event, SubmissionResult}, + types::{Event, SubmissionRef, SubmissionResult}, }, }; @@ -41,7 +41,7 @@ struct LocalTelemetry { pub type SimulationResult = (usize, Option); pub struct SimulationResultInner { pub result: Result<(), BlockSimError>, - pub request_id: SeqNum, + pub submission_ref: SubmissionRef, // Some if not optimistic pub res_tx: Option>, // TODO: move up @@ -231,7 +231,7 @@ impl SimulatorManager { let result = ( id, Some(SimulationResultInner { - request_id: req.submission_request_id, + submission_ref: req.submission_ref, result: res, paused_until, res_tx: req.res_tx, diff --git a/crates/relay/src/auctioneer/simulator/mod.rs b/crates/relay/src/auctioneer/simulator/mod.rs index 5508c7229..cb32505bb 100644 --- a/crates/relay/src/auctioneer/simulator/mod.rs +++ b/crates/relay/src/auctioneer/simulator/mod.rs @@ -7,11 +7,14 @@ use helix_common::{ }; use helix_types::{ BidTrace, BlobsBundle, BlsPublicKeyBytes, BlsSignatureBytes, BuilderInclusionResult, - ExecutionPayload, ExecutionRequests, MergeableOrderWithOrigin, SeqNum, SignedBidSubmission, + ExecutionPayload, ExecutionRequests, MergeableOrderWithOrigin, SignedBidSubmission, SubmissionVersion, }; -use crate::auctioneer::{BlockSubResultSender, types::SubmissionResult}; +use crate::auctioneer::{ + BlockSubResultSender, + types::{SubmissionRef, SubmissionResult}, +}; pub mod client; pub mod manager; @@ -110,7 +113,7 @@ pub struct SimulatorRequest { pub is_top_bid: bool, pub version: SubmissionVersion, pub submission: SignedBidSubmission, - pub submission_request_id: SeqNum, + pub submission_ref: SubmissionRef, /// None if optimistic pub res_tx: Option>, pub trace: SubmissionTrace, diff --git a/crates/relay/src/auctioneer/submit_block.rs b/crates/relay/src/auctioneer/submit_block.rs index b1e07195a..e13814d92 100644 --- a/crates/relay/src/auctioneer/submit_block.rs +++ b/crates/relay/src/auctioneer/submit_block.rs @@ -8,7 +8,7 @@ use helix_common::{ record_submission_step, spawn_tracked, }; use helix_types::{ - BidAdjustmentData, BlockValidationError, MergeableOrdersWithPref, SeqNum, SignedBidSubmission, + BidAdjustmentData, BlockValidationError, MergeableOrdersWithPref, SignedBidSubmission, SubmissionVersion, }; use tracing::{error, trace}; @@ -20,7 +20,9 @@ use crate::{ bid_adjustor::BidAdjustor, context::Context, simulator::{BlockSimRequest, SimulatorRequest, manager::SimulationResult}, - types::{PayloadEntry, SlotData, Submission, SubmissionData, SubmissionResult}, + types::{ + PayloadEntry, SlotData, Submission, SubmissionData, SubmissionRef, SubmissionResult, + }, }, housekeeper::PayloadAttributesUpdate, }; @@ -32,11 +34,11 @@ impl Context { res_tx: BlockSubResultSender, slot_data: &SlotData, ) { - let request_id = submission_data.request_id; + let submission_ref = submission_data.submission_ref; match self.validate_and_sort(submission_data, slot_data) { Ok((validated, optimistic_version, merging_data)) => { let res_tx = if optimistic_version.is_optimistic() { - res_tx.try_send((request_id, Ok(()))); + res_tx.try_send((submission_ref, Ok(()))); None } else { Some(res_tx) @@ -78,7 +80,7 @@ impl Context { } Err(err) => { - res_tx.try_send((request_id, Err(err))); + res_tx.try_send((submission_ref, Err(err))); } } } @@ -96,7 +98,7 @@ impl Context { self.bid_sorter.demote(*result.submission.builder_public_key()); if let Some(res_tx) = res_tx { res_tx.try_send(( - result.request_id, + result.submission_ref, Err(BuilderApiError::BlockSimulation(err.clone())), )); }; @@ -115,7 +117,7 @@ impl Context { } self.request_merged_block(); - res_tx.try_send((result.request_id, Ok(()))); + res_tx.try_send((result.submission_ref, Ok(()))); }; } } @@ -208,7 +210,7 @@ impl Context { }); let validated = ValidatedData { - request_id: submission_data.request_id, + submission_ref: submission_data.submission_ref, submission, tx_root: maybe_tx_root, payload_attributes, @@ -236,7 +238,7 @@ impl Context { ); let req = SimulatorRequest { - submission_request_id: validated.request_id, + submission_ref: validated.submission_ref, request, is_top_bid: validated.is_top_bid, res_tx, @@ -316,7 +318,7 @@ impl Context { } pub struct ValidatedData<'a> { - pub request_id: SeqNum, + pub submission_ref: SubmissionRef, pub submission: SignedBidSubmission, pub tx_root: Option, pub payload_attributes: &'a PayloadAttributesUpdate, diff --git a/crates/relay/src/auctioneer/types.rs b/crates/relay/src/auctioneer/types.rs index afecb7ea3..c7dadf257 100644 --- a/crates/relay/src/auctioneer/types.rs +++ b/crates/relay/src/auctioneer/types.rs @@ -5,6 +5,7 @@ use std::{ }; use alloy_primitives::{B256, U256}; +use flux_network::Token; use helix_common::{ GetPayloadTrace, SubmissionTrace, api::{ @@ -37,7 +38,13 @@ use crate::{ tcp_bid_recv::types::BidSubmissionHeader, }; -pub type SubmissionResult = (SeqNum, Result<(), BuilderApiError>); +#[derive(Clone, Copy, Debug)] +pub struct SubmissionRef { + pub seq_num: Option, + pub token: Option, +} + +pub type SubmissionResult = (SubmissionRef, Result<(), BuilderApiError>); pub type GetHeaderResult = Result; pub type GetPayloadResult = Result; @@ -78,7 +85,7 @@ pub struct GetPayloadResultData { #[derive(Clone, Debug)] pub struct SubmissionData { - pub request_id: SeqNum, + pub submission_ref: SubmissionRef, pub submission: Submission, pub merging_data: Option, pub bid_adjustment_data: Option, @@ -331,8 +338,8 @@ impl PayloadBidDataRef<'_> { pub enum SubWorkerJob { BlockSubmission { + submission_ref: SubmissionRef, header: BidSubmissionHeader, - sequence: Option, encoding: Encoding, api_key: Option, compression: Compression, diff --git a/crates/relay/src/auctioneer/worker.rs b/crates/relay/src/auctioneer/worker.rs index 62e560972..9cf2b9197 100644 --- a/crates/relay/src/auctioneer/worker.rs +++ b/crates/relay/src/auctioneer/worker.rs @@ -116,8 +116,8 @@ impl SubWorker { fn _handle_task(&self, task: SubWorkerJob) { match task { SubWorkerJob::BlockSubmission { + submission_ref, header, - sequence, encoding, compression, api_key, @@ -131,10 +131,9 @@ impl SubWorker { record_submission_step("worker_recv", sent_at.elapsed()); let guard = span.enter(); trace!("received by worker"); - let request_id = header.sequence_number; match self.handle_block_submission( header, - sequence, + submission_ref.seq_num, api_key, encoding, compression, @@ -185,7 +184,7 @@ impl SubWorker { }; let submission_data = SubmissionData { - request_id, + submission_ref, submission, version, merging_data, @@ -207,7 +206,7 @@ impl SubWorker { } Err(err) => { - res_tx.try_send((request_id, Err(err))); + res_tx.try_send((submission_ref, Err(err))); } } } diff --git a/crates/relay/src/tcp_bid_recv/mod.rs b/crates/relay/src/tcp_bid_recv/mod.rs index 61d658a60..a053b9cac 100644 --- a/crates/relay/src/tcp_bid_recv/mod.rs +++ b/crates/relay/src/tcp_bid_recv/mod.rs @@ -7,14 +7,14 @@ use flux_network::{ Token, tcp::{SendBehavior, TcpConnector, TcpTelemetry}, }; -use helix_common::SubmissionTrace; +use helix_common::{SubmissionTrace, utils::utcnow_ns}; use helix_types::{BlsPublicKeyBytes, SeqNum}; use ssz::{Decode, Encode}; use uuid::Uuid; use crate::{ AuctioneerHandle, HelixSpine, SubmissionResult, - auctioneer::{BlockSubResultSender, Encoding}, + auctioneer::{BlockSubResultSender, Encoding, SubmissionRef}, tcp_bid_recv::types::{BidSubmission, BidSubmissionResponse, RegistrationMsg}, }; @@ -33,7 +33,6 @@ pub struct BidSubmissionTcpListener { rx: Receiver, tx: Sender, - in_flight: HashMap, to_disconnect: Vec, registered: HashMap, submission_errors: Vec<(Token, Option, BidSubmissionError)>, @@ -60,7 +59,6 @@ impl BidSubmissionTcpListener { api_key_cache, rx, tx, - in_flight: HashMap::with_capacity(max_connections), to_disconnect: Vec::with_capacity(max_connections), registered: HashMap::with_capacity(max_connections), submission_errors: Vec::with_capacity(max_connections), @@ -76,6 +74,7 @@ impl BidSubmissionTcpListener { block_hash = tracing::field::Empty, ))] fn accept_bid_submission( + submission_ref: SubmissionRef, tx: Sender, auctioneer_handle: &AuctioneerHandle, bid: BidSubmission, @@ -83,15 +82,18 @@ impl BidSubmissionTcpListener { ) -> Result<(), BidSubmissionError> { let compression = bid.header.compression(); + let now = utcnow_ns(); + let trace = SubmissionTrace { receive: now, read_body: now, ..Default::default() }; + auctioneer_handle .block_submission( + submission_ref, bid.header, - Some(bid.header.sequence_number), Encoding::Ssz, compression, None, bid.data, - SubmissionTrace::default(), + trace, BlockSubResultSender::Shared(tx), Some(expected_pubkey), ) @@ -119,24 +121,26 @@ impl Tile for BidSubmissionTcpListener { match BidSubmission::try_from(msg) { Ok(bid) => { let request_id = bid.header.sequence_number; - match Self::accept_bid_submission(self.tx.clone(), &self.auctioneer_handle, bid, *expected_pubkey) { - Ok(_) => { - self.in_flight.insert(request_id, token); - } - Err(e) => { - tracing::error!(err=%e, "failed to send bid submission to worker"); - self.submission_errors.push((token, Some(request_id), e)); - } + let submission_ref = + SubmissionRef { seq_num: Some(request_id), token: Some(token) }; + if let Err(e) = Self::accept_bid_submission( + submission_ref, + self.tx.clone(), + &self.auctioneer_handle, + bid, + *expected_pubkey, + ) { + tracing::error!(err=%e, "failed to send bid submission to worker"); + self.submission_errors.push((token, Some(request_id), e)); } - }, + } Err(e) => { tracing::error!(err=%e, "failed to deserialize the bid"); self.submission_errors.push((token, None, e)); } }; } else { - let registration_message = - RegistrationMsg::from_ssz_bytes(msg); + let registration_message = RegistrationMsg::from_ssz_bytes(msg); match registration_message { Ok(msg) => { let api_key = Uuid::from_bytes(msg.api_key).to_string(); @@ -176,14 +180,18 @@ impl Tile for BidSubmissionTcpListener { }); } - for (seq_num, result) in self.rx.try_iter() { - if let Some(token) = self.in_flight.remove(&seq_num) { + for (submission_ref, result) in self.rx.try_iter() { + if let (Some(token), Some(seq_num)) = (submission_ref.token, submission_ref.seq_num) { self.listener.write_or_enqueue_with(SendBehavior::Single(token), |buffer| { BidSubmissionResponse::from_builder_api_error(seq_num, &result) .ssz_append(buffer); }); } else { - tracing::error!(id=%seq_num, "connection token not found for submission result: {:?}", result); + tracing::error!( + "submission ref {:?} not found for submission result: {:?}", + submission_ref, + result + ); } } } From 3a4eab3220c76c9719b661ea6563895f360119e0 Mon Sep 17 00:00:00 2001 From: Nina Date: Mon, 16 Feb 2026 19:12:33 +0000 Subject: [PATCH 05/12] draft --- crates/relay/src/api/builder/top_bid.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/relay/src/api/builder/top_bid.rs b/crates/relay/src/api/builder/top_bid.rs index 6d9f6a484..f79182758 100644 --- a/crates/relay/src/api/builder/top_bid.rs +++ b/crates/relay/src/api/builder/top_bid.rs @@ -24,7 +24,7 @@ impl BuilderApi { ) -> Result { let Some(api_key) = headers .get(HEADER_API_KEY) - .or(headers.get(HEADER_API_TOKEN)) + .or_else(|| headers.get(HEADER_API_TOKEN)) .and_then(|key| key.to_str().ok()) else { return Err(BuilderApiError::InvalidApiKey); From c6ac772c36fb90e414be5d71006870da2f1ea39a Mon Sep 17 00:00:00 2001 From: Nina Date: Tue, 17 Feb 2026 10:02:28 +0000 Subject: [PATCH 06/12] update flux --- Cargo.lock | 16 +++++++------- Cargo.toml | 4 ++-- crates/relay/src/tcp_bid_recv/mod.rs | 32 ++++++++++++++-------------- 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fee393598..d8dd42526 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4533,7 +4533,7 @@ dependencies = [ [[package]] name = "flux" version = "0.0.37" -source = "git+https://github.com/gattaca-com/flux?rev=7b043e20c33cf3d23a0c1a8e06fc06298c010662#7b043e20c33cf3d23a0c1a8e06fc06298c010662" +source = "git+https://github.com/gattaca-com/flux?rev=d399dcc10179f5892ffc2608f1d46ad2b449f0ac#d399dcc10179f5892ffc2608f1d46ad2b449f0ac" dependencies = [ "bitcode", "core_affinity", @@ -4556,7 +4556,7 @@ dependencies = [ [[package]] name = "flux-communication" version = "0.0.26" -source = "git+https://github.com/gattaca-com/flux?rev=7b043e20c33cf3d23a0c1a8e06fc06298c010662#7b043e20c33cf3d23a0c1a8e06fc06298c010662" +source = "git+https://github.com/gattaca-com/flux?rev=d399dcc10179f5892ffc2608f1d46ad2b449f0ac#d399dcc10179f5892ffc2608f1d46ad2b449f0ac" dependencies = [ "directories", "flux-timing", @@ -4570,7 +4570,7 @@ dependencies = [ [[package]] name = "flux-network" version = "0.0.8" -source = "git+https://github.com/gattaca-com/flux?rev=7b043e20c33cf3d23a0c1a8e06fc06298c010662#7b043e20c33cf3d23a0c1a8e06fc06298c010662" +source = "git+https://github.com/gattaca-com/flux?rev=d399dcc10179f5892ffc2608f1d46ad2b449f0ac#d399dcc10179f5892ffc2608f1d46ad2b449f0ac" dependencies = [ "flux-communication", "flux-timing", @@ -4583,7 +4583,7 @@ dependencies = [ [[package]] name = "flux-timing" version = "0.0.15" -source = "git+https://github.com/gattaca-com/flux?rev=7b043e20c33cf3d23a0c1a8e06fc06298c010662#7b043e20c33cf3d23a0c1a8e06fc06298c010662" +source = "git+https://github.com/gattaca-com/flux?rev=d399dcc10179f5892ffc2608f1d46ad2b449f0ac#d399dcc10179f5892ffc2608f1d46ad2b449f0ac" dependencies = [ "bitcode", "chrono", @@ -4601,7 +4601,7 @@ dependencies = [ [[package]] name = "flux-utils" version = "0.0.22" -source = "git+https://github.com/gattaca-com/flux?rev=7b043e20c33cf3d23a0c1a8e06fc06298c010662#7b043e20c33cf3d23a0c1a8e06fc06298c010662" +source = "git+https://github.com/gattaca-com/flux?rev=d399dcc10179f5892ffc2608f1d46ad2b449f0ac#d399dcc10179f5892ffc2608f1d46ad2b449f0ac" dependencies = [ "core_affinity", "directories", @@ -12913,7 +12913,7 @@ checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] name = "spine-derive" version = "0.0.9" -source = "git+https://github.com/gattaca-com/flux?rev=7b043e20c33cf3d23a0c1a8e06fc06298c010662#7b043e20c33cf3d23a0c1a8e06fc06298c010662" +source = "git+https://github.com/gattaca-com/flux?rev=d399dcc10179f5892ffc2608f1d46ad2b449f0ac#d399dcc10179f5892ffc2608f1d46ad2b449f0ac" dependencies = [ "proc-macro2", "quote", @@ -14243,12 +14243,12 @@ dependencies = [ [[package]] name = "type-hash" version = "0.0.1" -source = "git+https://github.com/gattaca-com/flux?rev=7b043e20c33cf3d23a0c1a8e06fc06298c010662#7b043e20c33cf3d23a0c1a8e06fc06298c010662" +source = "git+https://github.com/gattaca-com/flux?rev=d399dcc10179f5892ffc2608f1d46ad2b449f0ac#d399dcc10179f5892ffc2608f1d46ad2b449f0ac" [[package]] name = "type-hash-derive" version = "0.0.4" -source = "git+https://github.com/gattaca-com/flux?rev=7b043e20c33cf3d23a0c1a8e06fc06298c010662#7b043e20c33cf3d23a0c1a8e06fc06298c010662" +source = "git+https://github.com/gattaca-com/flux?rev=d399dcc10179f5892ffc2608f1d46ad2b449f0ac#d399dcc10179f5892ffc2608f1d46ad2b449f0ac" dependencies = [ "proc-macro-crate", "proc-macro2", diff --git a/Cargo.toml b/Cargo.toml index 3342e152b..9781926b5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,8 +41,8 @@ ethereum_ssz_derive = "0.9" ethers = "2.0.14" eyre = "0.6.12" flate2 = "1.0" -flux = { git = "https://github.com/gattaca-com/flux", rev = "7b043e20c33cf3d23a0c1a8e06fc06298c010662"} -flux-network = { package = "flux-network", git = "https://github.com/gattaca-com/flux", rev = "7b043e20c33cf3d23a0c1a8e06fc06298c010662" } +flux = { git = "https://github.com/gattaca-com/flux", rev = "d399dcc10179f5892ffc2608f1d46ad2b449f0ac"} +flux-network = { package = "flux-network", git = "https://github.com/gattaca-com/flux", rev = "d399dcc10179f5892ffc2608f1d46ad2b449f0ac" } futures = "0.3" futures-util = { version = "0.3", features = ["compat"] } helix-common = { path = "crates/common" } diff --git a/crates/relay/src/tcp_bid_recv/mod.rs b/crates/relay/src/tcp_bid_recv/mod.rs index a053b9cac..d08025595 100644 --- a/crates/relay/src/tcp_bid_recv/mod.rs +++ b/crates/relay/src/tcp_bid_recv/mod.rs @@ -5,7 +5,7 @@ use dashmap::DashMap; use flux::{spine::FluxSpine, tile::Tile}; use flux_network::{ Token, - tcp::{SendBehavior, TcpConnector, TcpTelemetry}, + tcp::{PollEvent, SendBehavior, TcpConnector, TcpTelemetry}, }; use helix_common::{SubmissionTrace, utils::utcnow_ns}; use helix_types::{BlsPublicKeyBytes, SeqNum}; @@ -108,17 +108,16 @@ impl Tile for BidSubmissionTcpListener { } fn loop_body(&mut self, _adapter: &mut flux::spine::SpineAdapter) { - self.listener.poll_with( - |connection| { - tracing::trace!( - "connected to new peer {:?} with token {:?}", - connection.peer_addr, - connection.incoming_stream - ); - }, - |token, msg, _| { + self.listener.poll_with(|event| match event { + PollEvent::Accept { listener: _, stream, peer_addr } => { + tracing::trace!("connected to new peer {:?} with token {:?}", peer_addr, stream); + } + PollEvent::Disconnect { token } => { + self.registered.remove(&token); + } + PollEvent::Message { token, payload, .. } => { if let Some(expected_pubkey) = self.registered.get(&token) { - match BidSubmission::try_from(msg) { + match BidSubmission::try_from(payload) { Ok(bid) => { let request_id = bid.header.sequence_number; let submission_ref = @@ -140,7 +139,7 @@ impl Tile for BidSubmissionTcpListener { } }; } else { - let registration_message = RegistrationMsg::from_ssz_bytes(msg); + let registration_message = RegistrationMsg::from_ssz_bytes(payload); match registration_message { Ok(msg) => { let api_key = Uuid::from_bytes(msg.api_key).to_string(); @@ -165,8 +164,8 @@ impl Tile for BidSubmissionTcpListener { } } } - }, - ); + } + }); for token in self.to_disconnect.drain(..) { self.listener.disconnect(token); @@ -182,9 +181,10 @@ impl Tile for BidSubmissionTcpListener { for (submission_ref, result) in self.rx.try_iter() { if let (Some(token), Some(seq_num)) = (submission_ref.token, submission_ref.seq_num) { + let response = BidSubmissionResponse::from_builder_api_error(seq_num, &result); + self.listener.write_or_enqueue_with(SendBehavior::Single(token), |buffer| { - BidSubmissionResponse::from_builder_api_error(seq_num, &result) - .ssz_append(buffer); + response.ssz_append(buffer); }); } else { tracing::error!( From aa33fd49b0b212e21068fadf86644e4ae73dd0c0 Mon Sep 17 00:00:00 2001 From: Nina Date: Tue, 17 Feb 2026 14:02:52 +0000 Subject: [PATCH 07/12] move types around --- Cargo.lock | 20 +- Cargo.toml | 5 +- crates/relay/Cargo.toml | 2 +- crates/relay/src/auctioneer/decoder.rs | 101 ++-------- crates/relay/src/auctioneer/handle.rs | 6 +- crates/relay/src/auctioneer/mod.rs | 2 +- crates/relay/src/auctioneer/types.rs | 17 +- crates/relay/src/auctioneer/worker.rs | 12 +- crates/relay/src/lib.rs | 5 +- crates/relay/src/tcp_bid_recv/mod.rs | 19 +- crates/relay/src/tcp_bid_recv/types.rs | 207 +++----------------- crates/tcp-types/Cargo.toml | 20 ++ crates/tcp-types/src/lib.rs | 255 +++++++++++++++++++++++++ crates/types/Cargo.toml | 1 + crates/types/src/bid_submission.rs | 6 +- crates/types/src/lib.rs | 1 + 16 files changed, 381 insertions(+), 298 deletions(-) create mode 100644 crates/tcp-types/Cargo.toml create mode 100644 crates/tcp-types/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index d8dd42526..1b4210fa3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5230,7 +5230,6 @@ dependencies = [ "askama", "async-trait", "axum 0.8.8", - "bitflags 2.10.0", "bytes", "chrono", "crossbeam-channel", @@ -5246,6 +5245,7 @@ dependencies = [ "flux-network", "futures", "helix-common", + "helix-tcp-types", "helix-types", "http 1.4.0", "http-body 1.0.1", @@ -5325,6 +5325,23 @@ dependencies = [ "tracing", ] +[[package]] +name = "helix-tcp-types" +version = "0.0.1" +dependencies = [ + "alloy-rpc-types", + "bitflags 2.10.0", + "bytes", + "ethereum_ssz", + "ethereum_ssz_derive", + "serde", + "strum 0.27.2", + "thiserror 1.0.69", + "tracing", + "type-hash", + "type-hash-derive", +] + [[package]] name = "helix-types" version = "0.0.1" @@ -5341,6 +5358,7 @@ dependencies = [ "ethereum_serde_utils", "ethereum_ssz", "ethereum_ssz_derive", + "helix-tcp-types", "kzg", "rand 0.9.2", "rustc-hash", diff --git a/Cargo.toml b/Cargo.toml index 9781926b5..46d51c716 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [workspace] default-members = ["crates/relay"] -members = ["crates/common", "crates/relay", "crates/simulator", "crates/types"] +members = ["crates/common", "crates/relay", "crates/simulator", "crates/tcp-types", "crates/types"] resolver = "2" [workspace.package] @@ -43,9 +43,12 @@ eyre = "0.6.12" flate2 = "1.0" flux = { git = "https://github.com/gattaca-com/flux", rev = "d399dcc10179f5892ffc2608f1d46ad2b449f0ac"} flux-network = { package = "flux-network", git = "https://github.com/gattaca-com/flux", rev = "d399dcc10179f5892ffc2608f1d46ad2b449f0ac" } +flux-type-hash = { package = "type-hash", git = "https://github.com/gattaca-com/flux", rev = "d399dcc10179f5892ffc2608f1d46ad2b449f0ac" } +flux-type-hash-derive = { package = "type-hash-derive", git = "https://github.com/gattaca-com/flux", rev = "d399dcc10179f5892ffc2608f1d46ad2b449f0ac" } futures = "0.3" futures-util = { version = "0.3", features = ["compat"] } helix-common = { path = "crates/common" } +helix-tcp-types = { path = "./crates/tcp-types" } helix-types = { path = "./crates/types" } http = "1.0" http-body = "1.0" diff --git a/crates/relay/Cargo.toml b/crates/relay/Cargo.toml index c9a05dc26..342c5cd1b 100644 --- a/crates/relay/Cargo.toml +++ b/crates/relay/Cargo.toml @@ -14,7 +14,6 @@ alloy-rlp.workspace = true askama.workspace = true async-trait.workspace = true axum.workspace = true -bitflags = "2.10.0" bytes.workspace = true chrono.workspace = true crossbeam-channel.workspace = true @@ -30,6 +29,7 @@ flux.workspace = true flux-network.workspace = true futures.workspace = true helix-common.workspace = true +helix-tcp-types.workspace = true helix-types.workspace = true http.workspace = true http-body.workspace = true diff --git a/crates/relay/src/auctioneer/decoder.rs b/crates/relay/src/auctioneer/decoder.rs index a13e8efa0..e4f5c6247 100644 --- a/crates/relay/src/auctioneer/decoder.rs +++ b/crates/relay/src/auctioneer/decoder.rs @@ -10,12 +10,12 @@ use helix_common::metrics::{ SUBMISSION_BY_COMPRESSION, SUBMISSION_BY_ENCODING, SUBMISSION_COMPRESSED_BYTES, SUBMISSION_DECOMPRESSED_BYTES, }; -use helix_types::{BlsPublicKeyBytes, ForkName, ForkVersionDecode}; +use helix_types::{BlsPublicKeyBytes, Compression, ForkName, ForkVersionDecode, MergeType}; use http::{ HeaderMap, HeaderValue, header::{CONTENT_ENCODING, CONTENT_TYPE}, }; -use serde::{Deserialize, Serialize, de::DeserializeOwned}; +use serde::de::DeserializeOwned; use ssz::Decode; use strum::{AsRefStr, EnumString}; use tracing::trace; @@ -31,7 +31,7 @@ use crate::{ builder::{api::MAX_PAYLOAD_LENGTH, error::BuilderApiError}, }, auctioneer::SubmissionRef, - tcp_bid_recv::{BidSubmissionHeader, types::BidSubmissionFlags}, + tcp_bid_recv::{BidSubmissionFlags, BidSubmissionHeader}, }; #[derive(Debug, Clone, Copy, PartialEq, Eq, EnumString, AsRefStr)] @@ -49,91 +49,26 @@ impl SubmissionType { } } -#[repr(u8)] -#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, EnumString, AsRefStr)] -#[strum(serialize_all = "snake_case", ascii_case_insensitive)] -pub enum MergeType { - #[default] - None = 0, - Mergeable = 1, - AppendOnly = 2, -} - -impl MergeType { - pub fn from_headers(header_map: &HeaderMap, sub_type: Option) -> Self { - match header_map.get(HEADER_MERGE_TYPE) { - None => { - if sub_type.is_some_and(|sub_type| sub_type == SubmissionType::Merge) || - matches!(header_map.get(HEADER_IS_MERGEABLE), Some(header) if header == HeaderValue::from_static("true")) - { - MergeType::Mergeable - } else { - MergeType::None - } - } - Some(merge_type) => { - merge_type.to_str().ok().and_then(|t| t.parse().ok()).unwrap_or_default() +pub fn merge_type_from_headers( + header_map: &HeaderMap, + sub_type: Option, +) -> MergeType { + match header_map.get(HEADER_MERGE_TYPE) { + None => { + if sub_type.is_some_and(|sub_type| sub_type == SubmissionType::Merge) || + matches!(header_map.get(HEADER_IS_MERGEABLE), Some(header) if header == HeaderValue::from_static("true")) + { + MergeType::Mergeable + } else { + MergeType::None } } - } - - pub fn is_some(&self) -> bool { - *self != MergeType::None - } -} - -impl TryFrom for MergeType { - type Error = (); - - fn try_from(value: u8) -> Result { - match value { - 0 => Ok(Self::None), - 1 => Ok(Self::Mergeable), - 2 => Ok(Self::AppendOnly), - _ => Err(()), - } - } -} - -#[repr(u8)] -#[derive( - Debug, Eq, PartialEq, Clone, Copy, Serialize, Deserialize, Hash, PartialOrd, Ord, Default, -)] -pub enum Compression { - #[default] - None = 0, - Gzip = 1, - Zstd = 2, -} - -impl Compression { - pub fn string(&self) -> String { - match &self { - Compression::None => "none".into(), - Compression::Gzip => "gzip".into(), - Compression::Zstd => "zstd".into(), - } - } - - pub fn as_str(&self) -> &'static str { - match &self { - Compression::None => "none", - Compression::Gzip => "gzip", - Compression::Zstd => "zstd", + Some(merge_type) => { + merge_type.to_str().ok().and_then(|t| t.parse().ok()).unwrap_or_default() } } } -impl std::fmt::Display for Compression { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", match self { - Compression::None => "NONE", - Compression::Gzip => "GZIP", - Compression::Zstd => "ZSTD", - }) - } -} - #[derive(Clone, Copy, Debug)] pub enum Encoding { Json, @@ -387,7 +322,7 @@ pub fn headers_map_to_bid_submission_header( _ => Encoding::Json, }; - let merge_type = MergeType::from_headers(&headers, submission_type); + let merge_type = merge_type_from_headers(&headers, submission_type); let api_key = headers .get(HEADER_API_KEY) diff --git a/crates/relay/src/auctioneer/handle.rs b/crates/relay/src/auctioneer/handle.rs index 4b0d7c11e..a7ba2fe15 100644 --- a/crates/relay/src/auctioneer/handle.rs +++ b/crates/relay/src/auctioneer/handle.rs @@ -1,13 +1,15 @@ use std::{ops::Range, sync::Arc, time::Instant}; use helix_common::{GetPayloadTrace, SubmissionTrace, api::proposer_api::GetHeaderParams}; -use helix_types::{BlsPublicKeyBytes, SignedBlindedBeaconBlock, SignedValidatorRegistration}; +use helix_types::{ + BlsPublicKeyBytes, Compression, SignedBlindedBeaconBlock, SignedValidatorRegistration, +}; use tokio::sync::oneshot; use tracing::trace; use crate::{ auctioneer::{ - decoder::{Compression, Encoding}, + decoder::Encoding, types::{ BlockSubResultSender, Event, GetHeaderResult, GetPayloadResult, RegWorkerJob, SubWorkerJob, SubmissionRef, SubmissionResult, diff --git a/crates/relay/src/auctioneer/mod.rs b/crates/relay/src/auctioneer/mod.rs index d745f8143..601690777 100644 --- a/crates/relay/src/auctioneer/mod.rs +++ b/crates/relay/src/auctioneer/mod.rs @@ -43,7 +43,7 @@ pub use crate::auctioneer::{ bid_adjustor::{BidAdjustor, DefaultBidAdjustor}, bid_sorter::BidSorter, context::Context, - decoder::{Compression, Encoding, MergeType, headers_map_to_bid_submission_header}, + decoder::{Encoding, headers_map_to_bid_submission_header}, simulator::{SimulatorRequest, client::SimulatorClient, manager::SimulatorManager}, types::{BlockSubResultSender, SubmissionRef, SubmissionResult}, // move to types? }; diff --git a/crates/relay/src/auctioneer/types.rs b/crates/relay/src/auctioneer/types.rs index c7dadf257..321a42f3d 100644 --- a/crates/relay/src/auctioneer/types.rs +++ b/crates/relay/src/auctioneer/types.rs @@ -15,10 +15,11 @@ use helix_common::{ metrics::BID_CREATION_LATENCY, }; use helix_types::{ - BidAdjustmentData, BlsPublicKeyBytes, BuilderBid, DehydratedBidSubmission, ExecutionPayload, - ExecutionRequests, ForkName, GetPayloadResponse, MergeableOrdersWithPref, PayloadAndBlobs, - SeqNum, SignedBidSubmission, SignedBlindedBeaconBlock, SignedValidatorRegistration, Slot, - SubmissionVersion, VersionedSignedProposal, mock_public_key_bytes, + BidAdjustmentData, BlsPublicKeyBytes, BuilderBid, Compression, DehydratedBidSubmission, + ExecutionPayload, ExecutionRequests, ForkName, GetPayloadResponse, MergeableOrdersWithPref, + PayloadAndBlobs, SeqNum, SignedBidSubmission, SignedBlindedBeaconBlock, + SignedValidatorRegistration, Slot, SubmissionVersion, VersionedSignedProposal, + mock_public_key_bytes, }; use rustc_hash::FxHashMap; use serde::Serialize; @@ -28,14 +29,10 @@ use tracing::debug; use crate::{ api::{builder::error::BuilderApiError, proposer::ProposerApiError}, - auctioneer::{ - BlockMergeResult, - decoder::{Compression, Encoding}, - simulator::manager::SimulationResult, - }, + auctioneer::{BlockMergeResult, decoder::Encoding, simulator::manager::SimulationResult}, gossip::BroadcastPayloadParams, housekeeper::PayloadAttributesUpdate, - tcp_bid_recv::types::BidSubmissionHeader, + tcp_bid_recv::BidSubmissionHeader, }; #[derive(Clone, Copy, Debug)] diff --git a/crates/relay/src/auctioneer/worker.rs b/crates/relay/src/auctioneer/worker.rs index 9cf2b9197..0d8138976 100644 --- a/crates/relay/src/auctioneer/worker.rs +++ b/crates/relay/src/auctioneer/worker.rs @@ -14,11 +14,11 @@ use helix_common::{ utils::{utcnow_ns, utcnow_sec}, }; use helix_types::{ - BidAdjustmentData, BlockMergingData, BlsPublicKey, BlsPublicKeyBytes, DehydratedBidSubmission, - DehydratedBidSubmissionFuluWithAdjustments, ExecPayload, MergeableOrdersWithPref, SeqNum, - SigError, SignedBidSubmission, SignedBidSubmissionFuluWithAdjustments, - SignedBidSubmissionWithMergingData, SignedBlindedBeaconBlock, SignedValidatorRegistration, - SubmissionVersion, + BidAdjustmentData, BlockMergingData, BlsPublicKey, BlsPublicKeyBytes, Compression, + DehydratedBidSubmission, DehydratedBidSubmissionFuluWithAdjustments, ExecPayload, MergeType, + MergeableOrdersWithPref, SeqNum, SigError, SignedBidSubmission, + SignedBidSubmissionFuluWithAdjustments, SignedBidSubmissionWithMergingData, + SignedBlindedBeaconBlock, SignedValidatorRegistration, SubmissionVersion, }; use tracing::{error, trace}; @@ -27,7 +27,7 @@ use crate::{ api::{builder::error::BuilderApiError, proposer::ProposerApiError}, auctioneer::{ block_merger::get_mergeable_orders, - decoder::{Compression, Encoding, MergeType, SubmissionDecoder}, + decoder::{Encoding, SubmissionDecoder}, types::{Event, RegWorkerJob, SubWorkerJob, Submission, SubmissionData}, }, tcp_bid_recv::BidSubmissionHeader, diff --git a/crates/relay/src/lib.rs b/crates/relay/src/lib.rs index edf1d9d63..95b19087f 100644 --- a/crates/relay/src/lib.rs +++ b/crates/relay/src/lib.rs @@ -21,6 +21,9 @@ pub use crate::{ housekeeper::start_housekeeper, network::RelayNetworkManager, spine::HelixSpine, - tcp_bid_recv::BidSubmissionTcpListener, + tcp_bid_recv::{ + BidSubmissionFlags, BidSubmissionHeader, BidSubmissionResponse, BidSubmissionTcpListener, + RegistrationMsg, + }, website::WebsiteService, }; diff --git a/crates/relay/src/tcp_bid_recv/mod.rs b/crates/relay/src/tcp_bid_recv/mod.rs index d08025595..95a72f6d2 100644 --- a/crates/relay/src/tcp_bid_recv/mod.rs +++ b/crates/relay/src/tcp_bid_recv/mod.rs @@ -8,19 +8,25 @@ use flux_network::{ tcp::{PollEvent, SendBehavior, TcpConnector, TcpTelemetry}, }; use helix_common::{SubmissionTrace, utils::utcnow_ns}; -use helix_types::{BlsPublicKeyBytes, SeqNum}; +use helix_tcp_types::{BidSubmission, SeqNum}; +use helix_types::BlsPublicKeyBytes; use ssz::{Decode, Encode}; use uuid::Uuid; use crate::{ AuctioneerHandle, HelixSpine, SubmissionResult, auctioneer::{BlockSubResultSender, Encoding, SubmissionRef}, - tcp_bid_recv::types::{BidSubmission, BidSubmissionResponse, RegistrationMsg}, }; pub mod types; -pub use crate::tcp_bid_recv::types::{BidSubmissionError, BidSubmissionHeader}; +pub use helix_tcp_types::{ + BidSubmissionFlags, BidSubmissionHeader, BidSubmissionResponse, RegistrationMsg, +}; + +pub use crate::tcp_bid_recv::types::{ + BidSubmissionError, response_from_bid_submission_error, response_from_builder_api_error, +}; pub struct BidSubmissionTcpListener { listener_addr: SocketAddr, @@ -117,7 +123,7 @@ impl Tile for BidSubmissionTcpListener { } PollEvent::Message { token, payload, .. } => { if let Some(expected_pubkey) = self.registered.get(&token) { - match BidSubmission::try_from(payload) { + match BidSubmission::try_from(payload).map_err(BidSubmissionError::from) { Ok(bid) => { let request_id = bid.header.sequence_number; let submission_ref = @@ -174,14 +180,13 @@ impl Tile for BidSubmissionTcpListener { for (token, request_id, err) in self.submission_errors.drain(..) { self.listener.write_or_enqueue_with(SendBehavior::Single(token), |buffer| { - BidSubmissionResponse::from_bid_submission_error(&request_id, &err) - .ssz_append(buffer); + response_from_bid_submission_error(&request_id, &err).ssz_append(buffer); }); } for (submission_ref, result) in self.rx.try_iter() { if let (Some(token), Some(seq_num)) = (submission_ref.token, submission_ref.seq_num) { - let response = BidSubmissionResponse::from_builder_api_error(seq_num, &result); + let response = response_from_builder_api_error(seq_num, &result); self.listener.write_or_enqueue_with(SendBehavior::Single(token), |buffer| { response.ssz_append(buffer); diff --git a/crates/relay/src/tcp_bid_recv/types.rs b/crates/relay/src/tcp_bid_recv/types.rs index af6a89e35..ebde94e27 100644 --- a/crates/relay/src/tcp_bid_recv/types.rs +++ b/crates/relay/src/tcp_bid_recv/types.rs @@ -1,22 +1,6 @@ -use bytes::Bytes; -use helix_types::{BlsPublicKeyBytes, SeqNum}; -use serde::{Deserialize, Serialize}; -use ssz_derive::{Decode, Encode}; +use helix_tcp_types::{BidSubmissionResponse, ParseError, SeqNum, Status}; -use crate::{ - api::builder::error::BuilderApiError, - auctioneer::{Compression, MergeType}, -}; - -/// First message on a new TCP connection. SSZ-encoded. -/// Server validates the (api_key, builder_pubkey) pair against the key cache; on failure drops the -/// connection. -#[repr(C)] -#[derive(Debug, Clone, Decode)] -pub struct RegistrationMsg { - pub api_key: [u8; 16], // UUID bytes - pub builder_pubkey: BlsPublicKeyBytes, -} +use crate::api::builder::error::BuilderApiError; #[derive(Debug, thiserror::Error)] pub enum BidSubmissionError { @@ -24,107 +8,8 @@ pub enum BidSubmissionError { InternalError, #[error(transparent)] BuilderApiError(#[from] BuilderApiError), - #[error("InvalidMergeType {0}")] - InvalidMergeType(u8), - #[error("SubmissionTooShort")] - SubmissionTooShort, -} - -#[derive(Debug, Clone)] -pub struct BidSubmission { - pub header: BidSubmissionHeader, - pub data: bytes::Bytes, -} - -impl TryFrom<&[u8]> for BidSubmission { - type Error = BidSubmissionError; - - fn try_from(data: &[u8]) -> Result { - if data.len() < BID_SUB_HEADER_SIZE { - return Err(BidSubmissionError::SubmissionTooShort) - } - - let header = BidSubmissionHeader::try_from(&data[..BID_SUB_HEADER_SIZE])?; - - tracing::trace!("{:?}", header); - - let bid_submission_data = Bytes::copy_from_slice(&data[BID_SUB_HEADER_SIZE..]); - Ok(BidSubmission { header, data: bid_submission_data }) - } -} - -/// Wire header for bid submission. Manually encoded as -/// `[16B BE seq_number][1B merge_type][1B flags]` (18 bytes total). -/// The sequence_number is used as a unique identifier of the submission on both sides. -/// Unlike HTTP the api key is not sent, because it is validated on receipt of the registration -/// message. -#[derive(Debug, Clone, Copy, Default, PartialEq)] -pub struct BidSubmissionHeader { - pub sequence_number: SeqNum, - pub merge_type: MergeType, - pub flags: BidSubmissionFlags, -} - -const BID_SUB_HEADER_SIZE: usize = 18; - -impl TryFrom<&[u8]> for BidSubmissionHeader { - type Error = BidSubmissionError; - - fn try_from(value: &[u8]) -> Result { - let sequence_number = u128::from_be_bytes(value[..16].try_into().unwrap()); - let merge_type = MergeType::try_from(value[16]) - .map_err(|_| BidSubmissionError::InvalidMergeType(value[16]))?; - let flags = BidSubmissionFlags::from_bits_retain(value[17]); - - Ok(Self { sequence_number, merge_type, flags }) - } -} - -impl BidSubmissionHeader { - pub fn append_encoded(self, buffer: &mut Vec) { - buffer.extend_from_slice(&self.sequence_number.to_be_bytes()); - buffer.push(self.merge_type as u8); - buffer.push(self.flags.bits()); - } - - pub fn compression(&self) -> Compression { - if self.flags.is_zstd_compressed() { Compression::Zstd } else { Compression::None } - } -} - -#[repr(transparent)] -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default, Serialize, Deserialize)] -pub struct BidSubmissionFlags(u8); - -bitflags::bitflags! { - impl BidSubmissionFlags : u8 { - const IS_DEHYDRATED = 1 << 0; - const WITH_ADJUSTMENTS = 1 << 1; - const ZSTD_COMPRESSED = 1 << 2; - } -} - -impl BidSubmissionFlags { - pub fn is_dehydrated(&self) -> bool { - self.contains(Self::IS_DEHYDRATED) - } - pub fn with_adjustments(&self) -> bool { - self.contains(Self::WITH_ADJUSTMENTS) - } - pub fn is_zstd_compressed(&self) -> bool { - self.contains(Self::ZSTD_COMPRESSED) - } -} - -#[repr(u8)] -#[derive(Debug, Clone, Copy, Encode)] -#[ssz(enum_behaviour = "tag")] -pub enum Status { - Okay = 0, - InvalidRequest = 1, - InternalError = 2, - // client-only - // ConnectionError = 255, + #[error(transparent)] + ParseError(#[from] ParseError), } impl From<&BuilderApiError> for Status { @@ -143,76 +28,36 @@ impl From<&BidSubmissionError> for Status { match e { BidSubmissionError::InternalError => Status::InternalError, BidSubmissionError::BuilderApiError(e) => Status::from(e), - BidSubmissionError::InvalidMergeType(_) => Status::InvalidRequest, - BidSubmissionError::SubmissionTooShort => Status::InvalidRequest, - // _ => Status::InvalidRequest, + BidSubmissionError::ParseError(_) => Status::InvalidRequest, } } } -/// SSZ-encoded server response sent back in a single frame. -#[repr(C)] -#[derive(Debug, Clone, Encode)] -pub struct BidSubmissionResponse { - pub sequence_number: SeqNum, - pub status: Status, - pub error_msg: Vec, -} - -impl BidSubmissionResponse { - pub fn from_builder_api_error( - request_id: SeqNum, - result: &Result<(), BuilderApiError>, - ) -> Self { - match result { - Ok(()) => Self { - sequence_number: request_id, - status: Status::Okay, - error_msg: Default::default(), - }, - Err(e) => Self { - sequence_number: request_id, - status: Status::from(e), - error_msg: e.to_string().into_bytes(), - }, - } - } - - pub fn from_bid_submission_error(request_id: &Option, e: &BidSubmissionError) -> Self { - Self { - sequence_number: request_id.unwrap_or_default(), +pub fn response_from_builder_api_error( + request_id: SeqNum, + result: &Result<(), BuilderApiError>, +) -> BidSubmissionResponse { + match result { + Ok(()) => BidSubmissionResponse { + sequence_number: request_id, + status: Status::Okay, + error_msg: Default::default(), + }, + Err(e) => BidSubmissionResponse { + sequence_number: request_id, status: Status::from(e), error_msg: e.to_string().into_bytes(), - } + }, } } -#[cfg(test)] -mod tests { - use crate::{ - auctioneer::MergeType, - tcp_bid_recv::{ - BidSubmissionHeader, - types::{BID_SUB_HEADER_SIZE, BidSubmissionFlags}, - }, - }; - - #[test] - fn test_bid_submission_header() { - let header = BidSubmissionHeader { - sequence_number: 1913u128, - merge_type: MergeType::Mergeable, - flags: BidSubmissionFlags::all(), - }; - - let mut buffer = Vec::new(); - header.append_encoded(&mut buffer); - - assert_eq!(buffer.len(), BID_SUB_HEADER_SIZE); - - let decoded = - BidSubmissionHeader::try_from(buffer.as_slice()).expect("failed to decode header"); - - assert_eq!(decoded, header); +pub fn response_from_bid_submission_error( + request_id: &Option, + e: &BidSubmissionError, +) -> BidSubmissionResponse { + BidSubmissionResponse { + sequence_number: request_id.unwrap_or_default(), + status: Status::from(e), + error_msg: e.to_string().into_bytes(), } } diff --git a/crates/tcp-types/Cargo.toml b/crates/tcp-types/Cargo.toml new file mode 100644 index 000000000..9cd85a882 --- /dev/null +++ b/crates/tcp-types/Cargo.toml @@ -0,0 +1,20 @@ +[package] +edition.workspace = true +license.workspace = true +name = "helix-tcp-types" +repository.workspace = true +rust-version.workspace = true +version.workspace = true + +[dependencies] +alloy-rpc-types.workspace = true +bitflags.workspace = true +bytes.workspace = true +ethereum_ssz.workspace = true +flux-type-hash.workspace = true +flux-type-hash-derive.workspace = true +ethereum_ssz_derive.workspace = true +serde.workspace = true +strum.workspace = true +thiserror.workspace = true +tracing.workspace = true diff --git a/crates/tcp-types/src/lib.rs b/crates/tcp-types/src/lib.rs new file mode 100644 index 000000000..3dc299553 --- /dev/null +++ b/crates/tcp-types/src/lib.rs @@ -0,0 +1,255 @@ +use std::fmt::{self, Display}; + +use bytes::Bytes; +use flux_type_hash_derive::TypeHash; +use serde::{Deserialize, Serialize}; +use strum::{AsRefStr, EnumString}; + +pub type SeqNum = u128; + +#[repr(u8)] +#[derive( + Debug, Default, Clone, Copy, PartialEq, Eq, EnumString, AsRefStr, Serialize, Deserialize, +)] +#[strum(serialize_all = "snake_case", ascii_case_insensitive)] +pub enum MergeType { + #[default] + None = 0, + Mergeable = 1, + AppendOnly = 2, +} + +impl MergeType { + pub fn is_some(&self) -> bool { + *self != Self::None + } +} + +impl TryFrom for MergeType { + type Error = (); + + fn try_from(value: u8) -> Result { + match value { + 0 => Ok(Self::None), + 1 => Ok(Self::Mergeable), + 2 => Ok(Self::AppendOnly), + _ => Err(()), + } + } +} + +#[repr(u8)] +#[derive( + Debug, Eq, PartialEq, Clone, Copy, Serialize, Deserialize, Hash, PartialOrd, Ord, Default, +)] +pub enum Compression { + #[default] + None = 0, + Gzip = 1, + Zstd = 2, +} + +impl Compression { + pub fn string(&self) -> String { + match self { + Compression::None => "none".into(), + Compression::Gzip => "gzip".into(), + Compression::Zstd => "zstd".into(), + } + } + + pub fn as_str(&self) -> &'static str { + match self { + Compression::None => "none", + Compression::Gzip => "gzip", + Compression::Zstd => "zstd", + } + } +} + +impl std::fmt::Display for Compression { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", match self { + Compression::None => "NONE", + Compression::Gzip => "GZIP", + Compression::Zstd => "ZSTD", + }) + } +} + +/// First message on a new TCP connection. SSZ-encoded. +/// Server validates the (api_key, builder_pubkey) pair against the key cache; on failure drops the +/// connection. +#[repr(C)] +#[derive(Debug, Clone, ssz_derive::Decode, ssz_derive::Encode)] +pub struct RegistrationMsg { + pub api_key: [u8; 16], // UUID bytes + pub builder_pubkey: alloy_rpc_types::beacon::BlsPublicKey, +} + +#[derive(Debug, thiserror::Error)] +pub enum ParseError { + #[error("InvalidMergeType {0}")] + InvalidMergeType(u8), + #[error("SubmissionTooShort")] + SubmissionTooShort, +} + +#[derive(Debug, Clone)] +pub struct BidSubmission { + pub header: BidSubmissionHeader, + pub data: Bytes, +} + +const BID_SUB_HEADER_SIZE: usize = 18; + +impl TryFrom<&[u8]> for BidSubmission { + type Error = ParseError; + + fn try_from(data: &[u8]) -> Result { + if data.len() < BID_SUB_HEADER_SIZE { + return Err(ParseError::SubmissionTooShort) + } + + let header = BidSubmissionHeader::try_from(&data[..BID_SUB_HEADER_SIZE])?; + + tracing::trace!("{:?}", header); + + let data = Bytes::copy_from_slice(&data[BID_SUB_HEADER_SIZE..]); + Ok(BidSubmission { header, data }) + } +} + +/// Wire header for bid submission. Manually encoded as +/// `[16B BE seq_number][1B merge_type][1B flags]` (18 bytes total). +/// The sequence_number is used as a unique identifier of the submission on both sides. +/// Unlike HTTP the api key is not sent, because it is validated on receipt of the registration +/// message. +#[derive(Debug, Clone, Copy, Default, PartialEq)] +pub struct BidSubmissionHeader { + pub sequence_number: SeqNum, + pub merge_type: MergeType, + pub flags: BidSubmissionFlags, +} + +impl TryFrom<&[u8]> for BidSubmissionHeader { + type Error = ParseError; + + fn try_from(value: &[u8]) -> Result { + let sequence_number = u128::from_be_bytes(value[..16].try_into().unwrap()); + let merge_type = + MergeType::try_from(value[16]).map_err(|_| ParseError::InvalidMergeType(value[16]))?; + let flags = BidSubmissionFlags::from_bits_retain(value[17]); + + Ok(Self { sequence_number, merge_type, flags }) + } +} + +impl BidSubmissionHeader { + pub fn append_encoded(self, buffer: &mut Vec) { + buffer.extend_from_slice(&self.sequence_number.to_be_bytes()); + buffer.push(self.merge_type as u8); + buffer.push(self.flags.bits()); + } + + pub fn compression(&self) -> Compression { + if self.flags.is_zstd_compressed() { Compression::Zstd } else { Compression::None } + } +} + +#[repr(transparent)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default, Serialize, Deserialize)] +pub struct BidSubmissionFlags(u8); + +bitflags::bitflags! { + impl BidSubmissionFlags : u8 { + const IS_DEHYDRATED = 1 << 0; + const WITH_ADJUSTMENTS = 1 << 1; + const ZSTD_COMPRESSED = 1 << 2; + } +} + +impl BidSubmissionFlags { + pub fn is_dehydrated(&self) -> bool { + self.contains(Self::IS_DEHYDRATED) + } + pub fn with_adjustments(&self) -> bool { + self.contains(Self::WITH_ADJUSTMENTS) + } + pub fn is_zstd_compressed(&self) -> bool { + self.contains(Self::ZSTD_COMPRESSED) + } +} + +#[repr(u8)] +#[derive( + Default, + Debug, + Clone, + Copy, + PartialEq, + Eq, + Deserialize, + Serialize, + Hash, + TypeHash, + ssz_derive::Encode, + ssz_derive::Decode, +)] +#[ssz(enum_behaviour = "tag")] +pub enum Status { + #[default] + Okay = 0, + InvalidRequest = 1, + InternalError = 2, + // client only + ConnectionError = 255, +} + +impl Display for Status { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + fmt::Debug::fmt(&self, f) + } +} + +impl Status { + pub fn is_okay(&self) -> bool { + *self == Status::Okay + } + pub fn is_err(&self) -> bool { + !self.is_okay() + } +} + +/// SSZ-encoded server response sent back in a single frame. +#[repr(C)] +#[derive(Debug, Clone, ssz_derive::Encode, ssz_derive::Decode)] +pub struct BidSubmissionResponse { + pub sequence_number: SeqNum, + pub status: Status, + pub error_msg: Vec, +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_bid_submission_header() { + let header = BidSubmissionHeader { + sequence_number: 1913u128, + merge_type: MergeType::Mergeable, + flags: BidSubmissionFlags::all(), + }; + + let mut buffer = Vec::new(); + header.append_encoded(&mut buffer); + + assert_eq!(buffer.len(), BID_SUB_HEADER_SIZE); + + let decoded = + BidSubmissionHeader::try_from(buffer.as_slice()).expect("failed to decode header"); + + assert_eq!(decoded, header); + } +} diff --git a/crates/types/Cargo.toml b/crates/types/Cargo.toml index dbb61d764..dc3953a65 100644 --- a/crates/types/Cargo.toml +++ b/crates/types/Cargo.toml @@ -14,6 +14,7 @@ alloy-rpc-types.workspace = true blst.workspace = true bitflags.workspace = true ethereum_serde_utils.workspace = true +helix-tcp-types.workspace = true ethereum_ssz.workspace = true ethereum_ssz_derive.workspace = true lh-bls.workspace = true diff --git a/crates/types/src/bid_submission.rs b/crates/types/src/bid_submission.rs index 0df3f66c5..28de9f4cc 100644 --- a/crates/types/src/bid_submission.rs +++ b/crates/types/src/bid_submission.rs @@ -10,12 +10,10 @@ use tree_hash_derive::TreeHash; use crate::{ BlobsBundle, BlobsBundleV1, BlobsBundleV2, BlobsError, Bloom, BlsPublicKey, BlsPublicKeyBytes, - BlsSignature, BlsSignatureBytes, ExecutionPayload, ExtraData, PayloadAndBlobs, SszError, - bid_adjustment_data::BidAdjustmentData, error::SigError, fields::ExecutionRequests, + BlsSignature, BlsSignatureBytes, ExecutionPayload, ExtraData, PayloadAndBlobs, SeqNum, + SszError, bid_adjustment_data::BidAdjustmentData, error::SigError, fields::ExecutionRequests, }; -pub type SeqNum = u128; - #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Encode, Decode, TreeHash)] #[serde(deny_unknown_fields)] pub struct BidTrace { diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs index 6560b0faa..0afc80e59 100644 --- a/crates/types/src/lib.rs +++ b/crates/types/src/lib.rs @@ -23,6 +23,7 @@ pub use clock::*; pub use error::*; pub use execution_payload::*; pub use fields::*; +pub use helix_tcp_types::{Compression, MergeType, SeqNum}; pub use hydration::*; pub use lh_kzg::{KzgCommitment, KzgProof}; pub use lh_test_random::TestRandom; From 0331edfdd7c55fc5121159d9378c17f963fbd257 Mon Sep 17 00:00:00 2001 From: Nina Date: Tue, 17 Feb 2026 17:39:11 +0000 Subject: [PATCH 08/12] bump flux --- Cargo.lock | 16 ++++++++-------- Cargo.toml | 10 ++++++---- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1b4210fa3..f2ed6e183 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4533,7 +4533,7 @@ dependencies = [ [[package]] name = "flux" version = "0.0.37" -source = "git+https://github.com/gattaca-com/flux?rev=d399dcc10179f5892ffc2608f1d46ad2b449f0ac#d399dcc10179f5892ffc2608f1d46ad2b449f0ac" +source = "git+https://github.com/gattaca-com/flux?rev=1fbb6568ee3635e3763e7dec52625b01a673837f#1fbb6568ee3635e3763e7dec52625b01a673837f" dependencies = [ "bitcode", "core_affinity", @@ -4556,7 +4556,7 @@ dependencies = [ [[package]] name = "flux-communication" version = "0.0.26" -source = "git+https://github.com/gattaca-com/flux?rev=d399dcc10179f5892ffc2608f1d46ad2b449f0ac#d399dcc10179f5892ffc2608f1d46ad2b449f0ac" +source = "git+https://github.com/gattaca-com/flux?rev=1fbb6568ee3635e3763e7dec52625b01a673837f#1fbb6568ee3635e3763e7dec52625b01a673837f" dependencies = [ "directories", "flux-timing", @@ -4570,7 +4570,7 @@ dependencies = [ [[package]] name = "flux-network" version = "0.0.8" -source = "git+https://github.com/gattaca-com/flux?rev=d399dcc10179f5892ffc2608f1d46ad2b449f0ac#d399dcc10179f5892ffc2608f1d46ad2b449f0ac" +source = "git+https://github.com/gattaca-com/flux?rev=1fbb6568ee3635e3763e7dec52625b01a673837f#1fbb6568ee3635e3763e7dec52625b01a673837f" dependencies = [ "flux-communication", "flux-timing", @@ -4583,7 +4583,7 @@ dependencies = [ [[package]] name = "flux-timing" version = "0.0.15" -source = "git+https://github.com/gattaca-com/flux?rev=d399dcc10179f5892ffc2608f1d46ad2b449f0ac#d399dcc10179f5892ffc2608f1d46ad2b449f0ac" +source = "git+https://github.com/gattaca-com/flux?rev=1fbb6568ee3635e3763e7dec52625b01a673837f#1fbb6568ee3635e3763e7dec52625b01a673837f" dependencies = [ "bitcode", "chrono", @@ -4601,7 +4601,7 @@ dependencies = [ [[package]] name = "flux-utils" version = "0.0.22" -source = "git+https://github.com/gattaca-com/flux?rev=d399dcc10179f5892ffc2608f1d46ad2b449f0ac#d399dcc10179f5892ffc2608f1d46ad2b449f0ac" +source = "git+https://github.com/gattaca-com/flux?rev=1fbb6568ee3635e3763e7dec52625b01a673837f#1fbb6568ee3635e3763e7dec52625b01a673837f" dependencies = [ "core_affinity", "directories", @@ -12931,7 +12931,7 @@ checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] name = "spine-derive" version = "0.0.9" -source = "git+https://github.com/gattaca-com/flux?rev=d399dcc10179f5892ffc2608f1d46ad2b449f0ac#d399dcc10179f5892ffc2608f1d46ad2b449f0ac" +source = "git+https://github.com/gattaca-com/flux?rev=1fbb6568ee3635e3763e7dec52625b01a673837f#1fbb6568ee3635e3763e7dec52625b01a673837f" dependencies = [ "proc-macro2", "quote", @@ -14261,12 +14261,12 @@ dependencies = [ [[package]] name = "type-hash" version = "0.0.1" -source = "git+https://github.com/gattaca-com/flux?rev=d399dcc10179f5892ffc2608f1d46ad2b449f0ac#d399dcc10179f5892ffc2608f1d46ad2b449f0ac" +source = "git+https://github.com/gattaca-com/flux?rev=1fbb6568ee3635e3763e7dec52625b01a673837f#1fbb6568ee3635e3763e7dec52625b01a673837f" [[package]] name = "type-hash-derive" version = "0.0.4" -source = "git+https://github.com/gattaca-com/flux?rev=d399dcc10179f5892ffc2608f1d46ad2b449f0ac#d399dcc10179f5892ffc2608f1d46ad2b449f0ac" +source = "git+https://github.com/gattaca-com/flux?rev=1fbb6568ee3635e3763e7dec52625b01a673837f#1fbb6568ee3635e3763e7dec52625b01a673837f" dependencies = [ "proc-macro-crate", "proc-macro2", diff --git a/Cargo.toml b/Cargo.toml index 46d51c716..0752e9a30 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,10 +41,12 @@ ethereum_ssz_derive = "0.9" ethers = "2.0.14" eyre = "0.6.12" flate2 = "1.0" -flux = { git = "https://github.com/gattaca-com/flux", rev = "d399dcc10179f5892ffc2608f1d46ad2b449f0ac"} -flux-network = { package = "flux-network", git = "https://github.com/gattaca-com/flux", rev = "d399dcc10179f5892ffc2608f1d46ad2b449f0ac" } -flux-type-hash = { package = "type-hash", git = "https://github.com/gattaca-com/flux", rev = "d399dcc10179f5892ffc2608f1d46ad2b449f0ac" } -flux-type-hash-derive = { package = "type-hash-derive", git = "https://github.com/gattaca-com/flux", rev = "d399dcc10179f5892ffc2608f1d46ad2b449f0ac" } + +flux = { git = "https://github.com/gattaca-com/flux", rev="1fbb6568ee3635e3763e7dec52625b01a673837f"} +flux-network = { package = "flux-network", git = "https://github.com/gattaca-com/flux", rev = "1fbb6568ee3635e3763e7dec52625b01a673837f"} +flux-type-hash = { package = "type-hash", git = "https://github.com/gattaca-com/flux", rev = "1fbb6568ee3635e3763e7dec52625b01a673837f"} +flux-type-hash-derive = { package = "type-hash-derive", git = "https://github.com/gattaca-com/flux", rev = "1fbb6568ee3635e3763e7dec52625b01a673837f"} + futures = "0.3" futures-util = { version = "0.3", features = ["compat"] } helix-common = { path = "crates/common" } From 7a2610e826b776d4354b7ff4ec603a191ff6ce24 Mon Sep 17 00:00:00 2001 From: Nina Date: Wed, 18 Feb 2026 13:57:58 +0000 Subject: [PATCH 09/12] request id --- crates/relay/src/api/builder/submit_block.rs | 17 +-- crates/relay/src/auctioneer/context.rs | 2 +- crates/relay/src/auctioneer/decoder.rs | 96 +----------- crates/relay/src/auctioneer/handle.rs | 26 +--- crates/relay/src/auctioneer/mod.rs | 9 +- .../relay/src/auctioneer/simulator/manager.rs | 11 +- crates/relay/src/auctioneer/simulator/mod.rs | 10 +- crates/relay/src/auctioneer/submit_block.rs | 27 ++-- crates/relay/src/auctioneer/types.rs | 138 +++++++++++++++--- crates/relay/src/auctioneer/worker.rs | 50 +++---- crates/relay/src/tcp_bid_recv/mod.rs | 80 +++++----- crates/relay/src/tcp_bid_recv/types.rs | 18 ++- crates/tcp-types/src/lib.rs | 27 ++-- crates/types/src/bid_submission.rs | 8 +- crates/types/src/lib.rs | 2 +- 15 files changed, 246 insertions(+), 275 deletions(-) diff --git a/crates/relay/src/api/builder/submit_block.rs b/crates/relay/src/api/builder/submit_block.rs index 45f2f3b8d..9ed00f301 100644 --- a/crates/relay/src/api/builder/submit_block.rs +++ b/crates/relay/src/api/builder/submit_block.rs @@ -10,7 +10,7 @@ use tracing::{error, trace}; use super::api::BuilderApi; use crate::{ api::{Api, builder::error::BuilderApiError}, - auctioneer::{BlockSubResultSender, headers_map_to_bid_submission_header}, + auctioneer::{InternalBidSubmissionHeader, SubmissionResultSender}, }; impl BuilderApi { @@ -38,22 +38,11 @@ impl BuilderApi { let mut trace = SubmissionTrace::init_from_timings(timings); trace.metadata = api.api_provider.get_metadata(&headers); - let (header, submission_ref, encoding, compression, api_key) = - headers_map_to_bid_submission_header(headers); + let header = InternalBidSubmissionHeader::from_http_headers(request_id, headers); let (tx, rx) = tokio::sync::oneshot::channel(); if api .auctioneer_handle - .block_submission( - submission_ref, - header, - encoding, - compression, - api_key, - body, - trace, - BlockSubResultSender::OneShot(tx), - None, - ) + .block_submission(header, body, trace, SubmissionResultSender::OneShot(tx), None) .is_err() { error!("failed sending request to worker"); diff --git a/crates/relay/src/auctioneer/context.rs b/crates/relay/src/auctioneer/context.rs index ebac3a91f..4cfeec7ee 100644 --- a/crates/relay/src/auctioneer/context.rs +++ b/crates/relay/src/auctioneer/context.rs @@ -214,7 +214,7 @@ impl Context { if let Some(res_tx) = result.res_tx { // submission was initially valid but by the time sim finished the slot already // progressed - res_tx.try_send((result.submission_ref, Err(BuilderApiError::SimOnNextSlot))); + res_tx.try_send((result.submission_id, Err(BuilderApiError::SimOnNextSlot))); } } diff --git a/crates/relay/src/auctioneer/decoder.rs b/crates/relay/src/auctioneer/decoder.rs index e4f5c6247..28a2ebe8e 100644 --- a/crates/relay/src/auctioneer/decoder.rs +++ b/crates/relay/src/auctioneer/decoder.rs @@ -10,11 +10,8 @@ use helix_common::metrics::{ SUBMISSION_BY_COMPRESSION, SUBMISSION_BY_ENCODING, SUBMISSION_COMPRESSED_BYTES, SUBMISSION_DECOMPRESSED_BYTES, }; -use helix_types::{BlsPublicKeyBytes, Compression, ForkName, ForkVersionDecode, MergeType}; -use http::{ - HeaderMap, HeaderValue, - header::{CONTENT_ENCODING, CONTENT_TYPE}, -}; +use helix_types::{BlsPublicKeyBytes, Compression, ForkName, ForkVersionDecode}; +use http::HeaderMap; use serde::de::DeserializeOwned; use ssz::Decode; use strum::{AsRefStr, EnumString}; @@ -24,14 +21,9 @@ use zstd::{ zstd_safe::{CONTENTSIZE_ERROR, CONTENTSIZE_UNKNOWN, get_frame_content_size}, }; -use crate::{ - api::{ - HEADER_API_KEY, HEADER_API_TOKEN, HEADER_HYDRATE, HEADER_IS_MERGEABLE, HEADER_MERGE_TYPE, - HEADER_SEQUENCE, HEADER_SUBMISSION_TYPE, HEADER_WITH_ADJUSTMENTS, - builder::{api::MAX_PAYLOAD_LENGTH, error::BuilderApiError}, - }, - auctioneer::SubmissionRef, - tcp_bid_recv::{BidSubmissionFlags, BidSubmissionHeader}, +use crate::api::{ + HEADER_SUBMISSION_TYPE, + builder::{api::MAX_PAYLOAD_LENGTH, error::BuilderApiError}, }; #[derive(Debug, Clone, Copy, PartialEq, Eq, EnumString, AsRefStr)] @@ -49,26 +41,6 @@ impl SubmissionType { } } -pub fn merge_type_from_headers( - header_map: &HeaderMap, - sub_type: Option, -) -> MergeType { - match header_map.get(HEADER_MERGE_TYPE) { - None => { - if sub_type.is_some_and(|sub_type| sub_type == SubmissionType::Merge) || - matches!(header_map.get(HEADER_IS_MERGEABLE), Some(header) if header == HeaderValue::from_static("true")) - { - MergeType::Mergeable - } else { - MergeType::None - } - } - Some(merge_type) => { - merge_type.to_str().ok().and_then(|t| t.parse().ok()).unwrap_or_default() - } - } -} - #[derive(Clone, Copy, Debug)] pub enum Encoding { Json, @@ -283,66 +255,12 @@ fn gzip_size_hint(buf: &[u8]) -> Option { } } -pub fn headers_map_to_bid_submission_header( - headers: http::header::HeaderMap, -) -> (BidSubmissionHeader, SubmissionRef, Encoding, Compression, Option) { - let mut flags = BidSubmissionFlags::default(); - - if matches!(headers.get(HEADER_WITH_ADJUSTMENTS), Some(header) if header == HeaderValue::from_static("true")) - { - flags.set(BidSubmissionFlags::WITH_ADJUSTMENTS, true); - } - if headers.get(HEADER_HYDRATE).is_some() { - flags.set(BidSubmissionFlags::IS_DEHYDRATED, true); - } - - let submission_type = SubmissionType::from_headers(&headers); - if submission_type.is_some_and(|sub_type| sub_type == SubmissionType::Dehydrated) { - flags.set(BidSubmissionFlags::IS_DEHYDRATED, true); - } - - let seq_num = headers - .get(HEADER_SEQUENCE) - .and_then(|seq| seq.to_str().ok()) - .and_then(|seq| seq.parse::().ok()); - - const GZIP_HEADER: HeaderValue = HeaderValue::from_static("gzip"); - const ZSTD_HEADER: HeaderValue = HeaderValue::from_static("zstd"); - - let compression = match headers.get(CONTENT_ENCODING) { - Some(header) if header == GZIP_HEADER => Compression::Gzip, - Some(header) if header == ZSTD_HEADER => Compression::Zstd, - _ => Compression::None, - }; - - const SSZ_HEADER: HeaderValue = HeaderValue::from_static("application/octet-stream"); - - let encoding = match headers.get(CONTENT_TYPE) { - Some(header) if header == SSZ_HEADER => Encoding::Ssz, - _ => Encoding::Json, - }; - - let merge_type = merge_type_from_headers(&headers, submission_type); - - let api_key = headers - .get(HEADER_API_KEY) - .or(headers.get(HEADER_API_TOKEN)) - .and_then(|key| key.to_str().map(|key| key.to_owned()).ok()); - - let header = - BidSubmissionHeader { sequence_number: seq_num.unwrap_or_default(), merge_type, flags }; - - let submission_ref = SubmissionRef { seq_num, token: None }; - - (header, submission_ref, encoding, compression, api_key) -} - #[cfg(test)] mod tests { use alloy_primitives::hex::FromHex; use helix_types::{ - SignedBidSubmission, SignedBidSubmissionElectra, SignedBidSubmissionWithMergingData, - TestRandomSeed, + MergeType, SignedBidSubmission, SignedBidSubmissionElectra, + SignedBidSubmissionWithMergingData, TestRandomSeed, }; use ssz::Encode; diff --git a/crates/relay/src/auctioneer/handle.rs b/crates/relay/src/auctioneer/handle.rs index a7ba2fe15..a94dfbf2e 100644 --- a/crates/relay/src/auctioneer/handle.rs +++ b/crates/relay/src/auctioneer/handle.rs @@ -1,22 +1,16 @@ use std::{ops::Range, sync::Arc, time::Instant}; use helix_common::{GetPayloadTrace, SubmissionTrace, api::proposer_api::GetHeaderParams}; -use helix_types::{ - BlsPublicKeyBytes, Compression, SignedBlindedBeaconBlock, SignedValidatorRegistration, -}; +use helix_types::{BlsPublicKeyBytes, SignedBlindedBeaconBlock, SignedValidatorRegistration}; use tokio::sync::oneshot; use tracing::trace; use crate::{ - auctioneer::{ - decoder::Encoding, - types::{ - BlockSubResultSender, Event, GetHeaderResult, GetPayloadResult, RegWorkerJob, - SubWorkerJob, SubmissionRef, SubmissionResult, - }, + auctioneer::types::{ + Event, GetHeaderResult, GetPayloadResult, InternalBidSubmissionHeader, RegWorkerJob, + SubWorkerJob, SubmissionResult, SubmissionResultSender, }, gossip::BroadcastPayloadParams, - tcp_bid_recv::BidSubmissionHeader, }; #[derive(Clone)] @@ -35,24 +29,16 @@ impl AuctioneerHandle { pub fn block_submission( &self, - submission_ref: SubmissionRef, - header: BidSubmissionHeader, - encoding: Encoding, - compression: Compression, - api_key: Option, + header: InternalBidSubmissionHeader, body: bytes::Bytes, trace: SubmissionTrace, - res_tx: BlockSubResultSender, + res_tx: SubmissionResultSender, expected_pubkey: Option, ) -> Result<(), ChannelFull> { trace!("sending to worker"); self.worker .try_send(SubWorkerJob::BlockSubmission { - submission_ref, header, - encoding, - compression, - api_key, body, trace, res_tx, diff --git a/crates/relay/src/auctioneer/mod.rs b/crates/relay/src/auctioneer/mod.rs index 601690777..e8c0279b0 100644 --- a/crates/relay/src/auctioneer/mod.rs +++ b/crates/relay/src/auctioneer/mod.rs @@ -43,9 +43,8 @@ pub use crate::auctioneer::{ bid_adjustor::{BidAdjustor, DefaultBidAdjustor}, bid_sorter::BidSorter, context::Context, - decoder::{Encoding, headers_map_to_bid_submission_header}, simulator::{SimulatorRequest, client::SimulatorClient, manager::SimulatorManager}, - types::{BlockSubResultSender, SubmissionRef, SubmissionResult}, // move to types? + types::{InternalBidSubmissionHeader, SubmissionResult, SubmissionResultSender}, /* move to types? */ }; use crate::{ HelixSpine, PostgresDatabaseService, @@ -421,7 +420,7 @@ impl State { Event::Submission { submission_data, res_tx, .. }, ) => { res_tx.try_send(( - submission_data.submission_ref, + submission_data.submission_id, Err(BuilderApiError::DeliveringPayload { bid_slot: submission_data.bid_slot(), delivering: slot_ctx.bid_slot.as_u64(), @@ -473,12 +472,12 @@ impl State { if submission_data.bid_slot() == bid_slot.as_u64() { // either not registered or waiting for full data from housekepper res_tx.try_send(( - submission_data.submission_ref, + submission_data.submission_id, Err(BuilderApiError::ProposerDutyNotFound), )); } else { res_tx.try_send(( - submission_data.submission_ref, + submission_data.submission_id, Err(BuilderApiError::BidValidation( helix_types::BlockValidationError::SubmissionForWrongSlot { expected: *bid_slot, diff --git a/crates/relay/src/auctioneer/simulator/manager.rs b/crates/relay/src/auctioneer/simulator/manager.rs index 75614ac00..ce1aeb969 100644 --- a/crates/relay/src/auctioneer/simulator/manager.rs +++ b/crates/relay/src/auctioneer/simulator/manager.rs @@ -13,13 +13,14 @@ use helix_common::{ }; use helix_types::{BlsPublicKeyBytes, SignedBidSubmission, SubmissionVersion}; use tracing::{debug, error, info, warn}; +use uuid::Uuid; use crate::{ api::service::SIMULATOR_REQUEST_TIMEOUT, auctioneer::{ - BlockSubResultSender, + SubmissionResultSender, simulator::{BlockMergeRequest, SimulatorRequest, client::SimulatorClient}, - types::{Event, SubmissionRef, SubmissionResult}, + types::{Event, SubmissionResult}, }, }; @@ -41,9 +42,9 @@ struct LocalTelemetry { pub type SimulationResult = (usize, Option); pub struct SimulationResultInner { pub result: Result<(), BlockSimError>, - pub submission_ref: SubmissionRef, + pub submission_id: Uuid, // Some if not optimistic - pub res_tx: Option>, + pub res_tx: Option>, // TODO: move up pub paused_until: Option, pub submission: SignedBidSubmission, @@ -231,7 +232,7 @@ impl SimulatorManager { let result = ( id, Some(SimulationResultInner { - submission_ref: req.submission_ref, + submission_id: req.submission_id, result: res, paused_until, res_tx: req.res_tx, diff --git a/crates/relay/src/auctioneer/simulator/mod.rs b/crates/relay/src/auctioneer/simulator/mod.rs index cb32505bb..21759e8b8 100644 --- a/crates/relay/src/auctioneer/simulator/mod.rs +++ b/crates/relay/src/auctioneer/simulator/mod.rs @@ -10,11 +10,9 @@ use helix_types::{ ExecutionPayload, ExecutionRequests, MergeableOrderWithOrigin, SignedBidSubmission, SubmissionVersion, }; +use uuid::Uuid; -use crate::auctioneer::{ - BlockSubResultSender, - types::{SubmissionRef, SubmissionResult}, -}; +use crate::auctioneer::{SubmissionResultSender, types::SubmissionResult}; pub mod client; pub mod manager; @@ -113,9 +111,9 @@ pub struct SimulatorRequest { pub is_top_bid: bool, pub version: SubmissionVersion, pub submission: SignedBidSubmission, - pub submission_ref: SubmissionRef, + pub submission_id: Uuid, /// None if optimistic - pub res_tx: Option>, + pub res_tx: Option>, pub trace: SubmissionTrace, // only Some for dehydrated submissions pub tx_root: Option, diff --git a/crates/relay/src/auctioneer/submit_block.rs b/crates/relay/src/auctioneer/submit_block.rs index e13814d92..6949bee5d 100644 --- a/crates/relay/src/auctioneer/submit_block.rs +++ b/crates/relay/src/auctioneer/submit_block.rs @@ -12,17 +12,16 @@ use helix_types::{ SubmissionVersion, }; use tracing::{error, trace}; +use uuid::Uuid; use crate::{ api::builder::error::BuilderApiError, auctioneer::{ - BlockSubResultSender, + SubmissionResultSender, bid_adjustor::BidAdjustor, context::Context, simulator::{BlockSimRequest, SimulatorRequest, manager::SimulationResult}, - types::{ - PayloadEntry, SlotData, Submission, SubmissionData, SubmissionRef, SubmissionResult, - }, + types::{PayloadEntry, SlotData, Submission, SubmissionData, SubmissionResult}, }, housekeeper::PayloadAttributesUpdate, }; @@ -31,14 +30,14 @@ impl Context { pub(super) fn handle_submission( &mut self, submission_data: SubmissionData, - res_tx: BlockSubResultSender, + res_tx: SubmissionResultSender, slot_data: &SlotData, ) { - let submission_ref = submission_data.submission_ref; + let submission_id = submission_data.submission_id; match self.validate_and_sort(submission_data, slot_data) { Ok((validated, optimistic_version, merging_data)) => { let res_tx = if optimistic_version.is_optimistic() { - res_tx.try_send((submission_ref, Ok(()))); + res_tx.try_send((submission_id, Ok(()))); None } else { Some(res_tx) @@ -80,7 +79,7 @@ impl Context { } Err(err) => { - res_tx.try_send((submission_ref, Err(err))); + res_tx.try_send((submission_id, Err(err))); } } } @@ -98,7 +97,7 @@ impl Context { self.bid_sorter.demote(*result.submission.builder_public_key()); if let Some(res_tx) = res_tx { res_tx.try_send(( - result.submission_ref, + result.submission_id, Err(BuilderApiError::BlockSimulation(err.clone())), )); }; @@ -117,7 +116,7 @@ impl Context { } self.request_merged_block(); - res_tx.try_send((result.submission_ref, Ok(()))); + res_tx.try_send((result.submission_id, Ok(()))); }; } } @@ -210,7 +209,7 @@ impl Context { }); let validated = ValidatedData { - submission_ref: submission_data.submission_ref, + submission_id: submission_data.submission_id, submission, tx_root: maybe_tx_root, payload_attributes, @@ -226,7 +225,7 @@ impl Context { fn prep_data_to_store_and_sim( &mut self, validated: ValidatedData, - res_tx: Option>, + res_tx: Option>, slot_data: &SlotData, ) -> (SimulatorRequest, PayloadEntry) { let request = BlockSimRequest::new( @@ -238,7 +237,7 @@ impl Context { ); let req = SimulatorRequest { - submission_ref: validated.submission_ref, + submission_id: validated.submission_id, request, is_top_bid: validated.is_top_bid, res_tx, @@ -318,7 +317,7 @@ impl Context { } pub struct ValidatedData<'a> { - pub submission_ref: SubmissionRef, + pub submission_id: Uuid, pub submission: SignedBidSubmission, pub tx_root: Option, pub payload_attributes: &'a PayloadAttributesUpdate, diff --git a/crates/relay/src/auctioneer/types.rs b/crates/relay/src/auctioneer/types.rs index 321a42f3d..8c37f4909 100644 --- a/crates/relay/src/auctioneer/types.rs +++ b/crates/relay/src/auctioneer/types.rs @@ -5,7 +5,6 @@ use std::{ }; use alloy_primitives::{B256, U256}; -use flux_network::Token; use helix_common::{ GetPayloadTrace, SubmissionTrace, api::{ @@ -14,43 +13,140 @@ use helix_common::{ }, metrics::BID_CREATION_LATENCY, }; +use helix_tcp_types::{BidSubmissionFlags, BidSubmissionHeader}; use helix_types::{ BidAdjustmentData, BlsPublicKeyBytes, BuilderBid, Compression, DehydratedBidSubmission, - ExecutionPayload, ExecutionRequests, ForkName, GetPayloadResponse, MergeableOrdersWithPref, - PayloadAndBlobs, SeqNum, SignedBidSubmission, SignedBlindedBeaconBlock, + ExecutionPayload, ExecutionRequests, ForkName, GetPayloadResponse, MergeType, + MergeableOrdersWithPref, PayloadAndBlobs, SignedBidSubmission, SignedBlindedBeaconBlock, SignedValidatorRegistration, Slot, SubmissionVersion, VersionedSignedProposal, mock_public_key_bytes, }; +use http::{ + HeaderMap, HeaderValue, + header::{CONTENT_ENCODING, CONTENT_TYPE}, +}; use rustc_hash::FxHashMap; use serde::Serialize; use ssz_derive::{Decode, Encode}; use tokio::sync::oneshot; use tracing::debug; +use uuid::Uuid; use crate::{ - api::{builder::error::BuilderApiError, proposer::ProposerApiError}, - auctioneer::{BlockMergeResult, decoder::Encoding, simulator::manager::SimulationResult}, + api::{ + HEADER_API_KEY, HEADER_API_TOKEN, HEADER_HYDRATE, HEADER_IS_MERGEABLE, HEADER_MERGE_TYPE, + HEADER_SEQUENCE, HEADER_WITH_ADJUSTMENTS, builder::error::BuilderApiError, + proposer::ProposerApiError, + }, + auctioneer::{ + BlockMergeResult, + decoder::{Encoding, SubmissionType}, + simulator::manager::SimulationResult, + }, gossip::BroadcastPayloadParams, housekeeper::PayloadAttributesUpdate, - tcp_bid_recv::BidSubmissionHeader, }; -#[derive(Clone, Copy, Debug)] -pub struct SubmissionRef { - pub seq_num: Option, - pub token: Option, -} - -pub type SubmissionResult = (SubmissionRef, Result<(), BuilderApiError>); +pub type SubmissionResult = (Uuid, Result<(), BuilderApiError>); pub type GetHeaderResult = Result; pub type GetPayloadResult = Result; -pub enum BlockSubResultSender { +pub struct InternalBidSubmissionHeader { + pub id: Uuid, + pub sequence_number: Option, + pub merge_type: MergeType, + pub flags: BidSubmissionFlags, + pub encoding: Encoding, + pub compression: Compression, + pub api_key: Option, +} + +impl InternalBidSubmissionHeader { + pub fn from_http_headers(request_id: Uuid, headers: http::header::HeaderMap) -> Self { + let mut flags = BidSubmissionFlags::default(); + if matches!(headers.get(HEADER_WITH_ADJUSTMENTS), Some(header) if header == HeaderValue::from_static("true")) + { + flags.set(BidSubmissionFlags::WITH_ADJUSTMENTS, true); + } + if headers.get(HEADER_HYDRATE).is_some() { + flags.set(BidSubmissionFlags::IS_DEHYDRATED, true); + } + + let submission_type = SubmissionType::from_headers(&headers); + if submission_type.is_some_and(|sub_type| sub_type == SubmissionType::Dehydrated) { + flags.set(BidSubmissionFlags::IS_DEHYDRATED, true); + } + + let sequence_number = headers + .get(HEADER_SEQUENCE) + .and_then(|seq| seq.to_str().ok()) + .and_then(|seq| seq.parse::().ok()); + + const GZIP_HEADER: HeaderValue = HeaderValue::from_static("gzip"); + const ZSTD_HEADER: HeaderValue = HeaderValue::from_static("zstd"); + + let compression = match headers.get(CONTENT_ENCODING) { + Some(header) if header == GZIP_HEADER => Compression::Gzip, + Some(header) if header == ZSTD_HEADER => Compression::Zstd, + _ => Compression::None, + }; + + const SSZ_HEADER: HeaderValue = HeaderValue::from_static("application/octet-stream"); + + let encoding = match headers.get(CONTENT_TYPE) { + Some(header) if header == SSZ_HEADER => Encoding::Ssz, + _ => Encoding::Json, + }; + + let merge_type = Self::merge_type_from_headers(&headers, submission_type); + + let api_key = headers + .get(HEADER_API_KEY) + .or(headers.get(HEADER_API_TOKEN)) + .and_then(|key| key.to_str().map(|key| key.to_owned()).ok()); + + Self { id: request_id, sequence_number, merge_type, flags, encoding, compression, api_key } + } + + fn merge_type_from_headers( + header_map: &HeaderMap, + sub_type: Option, + ) -> MergeType { + match header_map.get(HEADER_MERGE_TYPE) { + None => { + if sub_type.is_some_and(|sub_type| sub_type == SubmissionType::Merge) || + matches!(header_map.get(HEADER_IS_MERGEABLE), Some(header) if header == HeaderValue::from_static("true")) + { + MergeType::Mergeable + } else { + MergeType::None + } + } + Some(merge_type) => { + merge_type.to_str().ok().and_then(|t| t.parse().ok()).unwrap_or_default() + } + } + } + + pub fn from_tcp_header(request_id: Uuid, header: BidSubmissionHeader) -> Self { + Self { + id: request_id, + sequence_number: Some(header.sequence_number), + merge_type: header.merge_type, + flags: header.flags, + encoding: Encoding::Ssz, + compression: header.compression(), + api_key: None, + } + } +} + +pub enum SubmissionResultSender { OneShot(oneshot::Sender), Shared(crossbeam_channel::Sender), } -impl BlockSubResultSender { +impl SubmissionResultSender { pub fn try_send(self, data: T) { match self { Self::OneShot(tx) => { @@ -82,7 +178,7 @@ pub struct GetPayloadResultData { #[derive(Clone, Debug)] pub struct SubmissionData { - pub submission_ref: SubmissionRef, + pub submission_id: Uuid, pub submission: Submission, pub merging_data: Option, pub bid_adjustment_data: Option, @@ -335,14 +431,10 @@ impl PayloadBidDataRef<'_> { pub enum SubWorkerJob { BlockSubmission { - submission_ref: SubmissionRef, - header: BidSubmissionHeader, - encoding: Encoding, - api_key: Option, - compression: Compression, + header: InternalBidSubmissionHeader, body: bytes::Bytes, trace: SubmissionTrace, // TODO: replace this with better tracing - res_tx: BlockSubResultSender, + res_tx: SubmissionResultSender, span: tracing::Span, sent_at: Instant, expected_pubkey: Option, @@ -410,7 +502,7 @@ pub enum Event { }, Submission { submission_data: SubmissionData, - res_tx: BlockSubResultSender, + res_tx: SubmissionResultSender, span: tracing::Span, sent_at: Instant, }, diff --git a/crates/relay/src/auctioneer/worker.rs b/crates/relay/src/auctioneer/worker.rs index 0d8138976..eec12a867 100644 --- a/crates/relay/src/auctioneer/worker.rs +++ b/crates/relay/src/auctioneer/worker.rs @@ -14,11 +14,11 @@ use helix_common::{ utils::{utcnow_ns, utcnow_sec}, }; use helix_types::{ - BidAdjustmentData, BlockMergingData, BlsPublicKey, BlsPublicKeyBytes, Compression, - DehydratedBidSubmission, DehydratedBidSubmissionFuluWithAdjustments, ExecPayload, MergeType, - MergeableOrdersWithPref, SeqNum, SigError, SignedBidSubmission, - SignedBidSubmissionFuluWithAdjustments, SignedBidSubmissionWithMergingData, - SignedBlindedBeaconBlock, SignedValidatorRegistration, SubmissionVersion, + BidAdjustmentData, BlockMergingData, BlsPublicKey, BlsPublicKeyBytes, DehydratedBidSubmission, + DehydratedBidSubmissionFuluWithAdjustments, ExecPayload, MergeType, MergeableOrdersWithPref, + SigError, SignedBidSubmission, SignedBidSubmissionFuluWithAdjustments, + SignedBidSubmissionWithMergingData, SignedBlindedBeaconBlock, SignedValidatorRegistration, + SubmissionVersion, }; use tracing::{error, trace}; @@ -26,11 +26,11 @@ use crate::{ HelixSpine, api::{builder::error::BuilderApiError, proposer::ProposerApiError}, auctioneer::{ + InternalBidSubmissionHeader, block_merger::get_mergeable_orders, - decoder::{Encoding, SubmissionDecoder}, + decoder::SubmissionDecoder, types::{Event, RegWorkerJob, SubWorkerJob, Submission, SubmissionData}, }, - tcp_bid_recv::BidSubmissionHeader, }; pub struct Telemetry { @@ -116,11 +116,7 @@ impl SubWorker { fn _handle_task(&self, task: SubWorkerJob) { match task { SubWorkerJob::BlockSubmission { - submission_ref, header, - encoding, - compression, - api_key, body, mut trace, res_tx, @@ -128,19 +124,11 @@ impl SubWorker { sent_at, expected_pubkey, } => { + let submission_id = header.id; record_submission_step("worker_recv", sent_at.elapsed()); let guard = span.enter(); trace!("received by worker"); - match self.handle_block_submission( - header, - submission_ref.seq_num, - api_key, - encoding, - compression, - expected_pubkey, - body, - &mut trace, - ) { + match self.handle_block_submission(header, expected_pubkey, body, &mut trace) { Ok(( submission, withdrawals_root, @@ -184,7 +172,7 @@ impl SubWorker { }; let submission_data = SubmissionData { - submission_ref, + submission_id, submission, version, merging_data, @@ -206,7 +194,7 @@ impl SubWorker { } Err(err) => { - res_tx.try_send((submission_ref, Err(err))); + res_tx.try_send((submission_id, Err(err))); } } } @@ -250,11 +238,7 @@ impl SubWorker { #[allow(clippy::type_complexity)] fn handle_block_submission( &self, - header: BidSubmissionHeader, - sequence: Option, - api_key: Option, - encoding: Encoding, - compression: Compression, + header: InternalBidSubmissionHeader, expected_pubkey: Option, body: bytes::Bytes, trace: &mut SubmissionTrace, @@ -262,7 +246,7 @@ impl SubWorker { (Submission, B256, SubmissionVersion, Option, Option), BuilderApiError, > { - let mut decoder = SubmissionDecoder::new(compression, encoding); + let mut decoder = SubmissionDecoder::new(header.compression, header.encoding); let body = decoder.decompress(body)?; let with_mergeable_data = header.merge_type.is_some(); @@ -277,11 +261,13 @@ impl SubWorker { true } else { - api_key.is_some_and(|api_key| self.cache.validate_api_key(&api_key, &builder_pubkey)) + header + .api_key + .is_some_and(|api_key| self.cache.validate_api_key(&api_key, &builder_pubkey)) }; trace!( - ?sequence, + ?header.sequence_number, is_dehydrated, skip_sigverify, with_mergeable_data, @@ -306,7 +292,7 @@ impl SubWorker { let withdrawals_root = submission.withdrawal_root(); - let version = SubmissionVersion::new(trace.receive, sequence); + let version = SubmissionVersion::new(trace.receive, header.sequence_number); Ok((submission, withdrawals_root, version, merging_data, bid_adjustment_data)) } diff --git a/crates/relay/src/tcp_bid_recv/mod.rs b/crates/relay/src/tcp_bid_recv/mod.rs index 95a72f6d2..8c4bf84ed 100644 --- a/crates/relay/src/tcp_bid_recv/mod.rs +++ b/crates/relay/src/tcp_bid_recv/mod.rs @@ -8,14 +8,14 @@ use flux_network::{ tcp::{PollEvent, SendBehavior, TcpConnector, TcpTelemetry}, }; use helix_common::{SubmissionTrace, utils::utcnow_ns}; -use helix_tcp_types::{BidSubmission, SeqNum}; +use helix_tcp_types::BidSubmission; use helix_types::BlsPublicKeyBytes; use ssz::{Decode, Encode}; use uuid::Uuid; use crate::{ AuctioneerHandle, HelixSpine, SubmissionResult, - auctioneer::{BlockSubResultSender, Encoding, SubmissionRef}, + auctioneer::{InternalBidSubmissionHeader, SubmissionResultSender}, }; pub mod types; @@ -28,10 +28,12 @@ pub use crate::tcp_bid_recv::types::{ BidSubmissionError, response_from_bid_submission_error, response_from_builder_api_error, }; +const SUBMISSIONS_PER_SLOT: usize = 5000usize; + +type SubmissionError = (Token, Option, Option, BidSubmissionError); + pub struct BidSubmissionTcpListener { - listener_addr: SocketAddr, listener: TcpConnector, - listener_token: Option, auctioneer_handle: AuctioneerHandle, api_key_cache: Arc>>, @@ -41,7 +43,8 @@ pub struct BidSubmissionTcpListener { to_disconnect: Vec, registered: HashMap, - submission_errors: Vec<(Token, Option, BidSubmissionError)>, + in_flight: HashMap, + submission_errors: Vec, } impl BidSubmissionTcpListener { @@ -51,56 +54,52 @@ impl BidSubmissionTcpListener { api_key_cache: Arc>>, max_connections: usize, ) -> Self { - let listener = TcpConnector::default() + let mut listener = TcpConnector::default() .with_telemetry(TcpTelemetry::Enabled { app_name: HelixSpine::app_name() }) .with_socket_buf_size(64 * 1024 * 1024); // 64MB let (tx, rx) = crossbeam_channel::bounded(10_000); + listener.listen_at(listener_addr).expect("failed to initialise the TCP listener"); + Self { - listener_addr, listener, - listener_token: None, auctioneer_handle, api_key_cache, rx, tx, to_disconnect: Vec::with_capacity(max_connections), registered: HashMap::with_capacity(max_connections), + in_flight: HashMap::with_capacity(max_connections * SUBMISSIONS_PER_SLOT), submission_errors: Vec::with_capacity(max_connections), } } #[tracing::instrument(skip_all, fields( - id =% Uuid::from_u128(bid.header.sequence_number), + id =% request_id, slot = tracing::field::Empty, builder_pubkey = tracing::field::Empty, builder_id = tracing::field::Empty, block_hash = tracing::field::Empty, ))] fn accept_bid_submission( - submission_ref: SubmissionRef, + request_id: Uuid, tx: Sender, auctioneer_handle: &AuctioneerHandle, bid: BidSubmission, expected_pubkey: BlsPublicKeyBytes, ) -> Result<(), BidSubmissionError> { - let compression = bid.header.compression(); - let now = utcnow_ns(); let trace = SubmissionTrace { receive: now, read_body: now, ..Default::default() }; + let header = InternalBidSubmissionHeader::from_tcp_header(request_id, bid.header); auctioneer_handle .block_submission( - submission_ref, - bid.header, - Encoding::Ssz, - compression, - None, + header, bid.data, trace, - BlockSubResultSender::Shared(tx), + SubmissionResultSender::Shared(tx), Some(expected_pubkey), ) .map_err(|_| BidSubmissionError::InternalError) @@ -108,11 +107,6 @@ impl BidSubmissionTcpListener { } impl Tile for BidSubmissionTcpListener { - fn try_init(&mut self, _adapter: &mut flux::spine::SpineAdapter) -> bool { - self.listener_token = self.listener.listen_at(self.listener_addr); - self.listener_token.is_some() - } - fn loop_body(&mut self, _adapter: &mut flux::spine::SpineAdapter) { self.listener.poll_with(|event| match event { PollEvent::Accept { listener: _, stream, peer_addr } => { @@ -125,23 +119,30 @@ impl Tile for BidSubmissionTcpListener { if let Some(expected_pubkey) = self.registered.get(&token) { match BidSubmission::try_from(payload).map_err(BidSubmissionError::from) { Ok(bid) => { - let request_id = bid.header.sequence_number; - let submission_ref = - SubmissionRef { seq_num: Some(request_id), token: Some(token) }; - if let Err(e) = Self::accept_bid_submission( - submission_ref, + let request_id = Uuid::new_v4(); + let seq_num = bid.header.sequence_number; + match Self::accept_bid_submission( + request_id, self.tx.clone(), &self.auctioneer_handle, bid, *expected_pubkey, ) { - tracing::error!(err=%e, "failed to send bid submission to worker"); - self.submission_errors.push((token, Some(request_id), e)); + Ok(()) => {self.in_flight.insert(request_id, (token, seq_num));}, + Err(e) => { + tracing::error!(err=%e, id=%request_id, "failed to send bid submission to worker"); + self.submission_errors.push(( + token, + Some(seq_num), + Some(request_id), + e, + )); + } } } Err(e) => { tracing::error!(err=%e, "failed to deserialize the bid"); - self.submission_errors.push((token, None, e)); + self.submission_errors.push((token, None, None, e)); } }; } else { @@ -178,25 +179,20 @@ impl Tile for BidSubmissionTcpListener { self.registered.remove(&token); } - for (token, request_id, err) in self.submission_errors.drain(..) { + for (token, seq_num, request_id, err) in self.submission_errors.drain(..) { self.listener.write_or_enqueue_with(SendBehavior::Single(token), |buffer| { - response_from_bid_submission_error(&request_id, &err).ssz_append(buffer); + response_from_bid_submission_error(seq_num, request_id, &err).ssz_append(buffer); }); } - for (submission_ref, result) in self.rx.try_iter() { - if let (Some(token), Some(seq_num)) = (submission_ref.token, submission_ref.seq_num) { - let response = response_from_builder_api_error(seq_num, &result); - + for (request_id, result) in self.rx.try_iter() { + if let Some((token, seq_num)) = self.in_flight.remove(&request_id) { + let response = response_from_builder_api_error(seq_num, request_id, &result); self.listener.write_or_enqueue_with(SendBehavior::Single(token), |buffer| { response.ssz_append(buffer); }); } else { - tracing::error!( - "submission ref {:?} not found for submission result: {:?}", - submission_ref, - result - ); + tracing::error!("no in-flight entry for request_id on submission result"); } } } diff --git a/crates/relay/src/tcp_bid_recv/types.rs b/crates/relay/src/tcp_bid_recv/types.rs index ebde94e27..e14c64bb6 100644 --- a/crates/relay/src/tcp_bid_recv/types.rs +++ b/crates/relay/src/tcp_bid_recv/types.rs @@ -1,4 +1,5 @@ -use helix_tcp_types::{BidSubmissionResponse, ParseError, SeqNum, Status}; +use helix_tcp_types::{BidSubmissionResponse, ParseError, Status}; +use uuid::Uuid; use crate::api::builder::error::BuilderApiError; @@ -34,17 +35,20 @@ impl From<&BidSubmissionError> for Status { } pub fn response_from_builder_api_error( - request_id: SeqNum, + seq_num: u32, + request_id: Uuid, result: &Result<(), BuilderApiError>, ) -> BidSubmissionResponse { match result { Ok(()) => BidSubmissionResponse { - sequence_number: request_id, + sequence_number: seq_num, + request_id: request_id.into_bytes(), status: Status::Okay, error_msg: Default::default(), }, Err(e) => BidSubmissionResponse { - sequence_number: request_id, + sequence_number: seq_num, + request_id: request_id.into_bytes(), status: Status::from(e), error_msg: e.to_string().into_bytes(), }, @@ -52,11 +56,13 @@ pub fn response_from_builder_api_error( } pub fn response_from_bid_submission_error( - request_id: &Option, + seq_num: Option, + request_id: Option, e: &BidSubmissionError, ) -> BidSubmissionResponse { BidSubmissionResponse { - sequence_number: request_id.unwrap_or_default(), + sequence_number: seq_num.unwrap_or_default(), + request_id: request_id.map(Uuid::into_bytes).unwrap_or_default(), status: Status::from(e), error_msg: e.to_string().into_bytes(), } diff --git a/crates/tcp-types/src/lib.rs b/crates/tcp-types/src/lib.rs index 3dc299553..d3147e9b5 100644 --- a/crates/tcp-types/src/lib.rs +++ b/crates/tcp-types/src/lib.rs @@ -5,8 +5,6 @@ use flux_type_hash_derive::TypeHash; use serde::{Deserialize, Serialize}; use strum::{AsRefStr, EnumString}; -pub type SeqNum = u128; - #[repr(u8)] #[derive( Debug, Default, Clone, Copy, PartialEq, Eq, EnumString, AsRefStr, Serialize, Deserialize, @@ -93,6 +91,8 @@ pub enum ParseError { InvalidMergeType(u8), #[error("SubmissionTooShort")] SubmissionTooShort, + #[error("DuplicateSequenceNumber {0}")] + DuplicateSequenceNumber(u32), } #[derive(Debug, Clone)] @@ -101,7 +101,7 @@ pub struct BidSubmission { pub data: Bytes, } -const BID_SUB_HEADER_SIZE: usize = 18; +const BID_SUB_HEADER_SIZE: usize = 6; impl TryFrom<&[u8]> for BidSubmission { type Error = ParseError; @@ -121,13 +121,13 @@ impl TryFrom<&[u8]> for BidSubmission { } /// Wire header for bid submission. Manually encoded as -/// `[16B BE seq_number][1B merge_type][1B flags]` (18 bytes total). -/// The sequence_number is used as a unique identifier of the submission on both sides. -/// Unlike HTTP the api key is not sent, because it is validated on receipt of the registration -/// message. +/// `[4B BE seq_number][1B merge_type][1B flags]` (6 bytes total). +/// The sequence_number is used as a unique identifier of the submission on the client side per +/// slot. Unlike HTTP the api key is not sent, because it is validated on receipt of the +/// registration message. #[derive(Debug, Clone, Copy, Default, PartialEq)] pub struct BidSubmissionHeader { - pub sequence_number: SeqNum, + pub sequence_number: u32, pub merge_type: MergeType, pub flags: BidSubmissionFlags, } @@ -136,10 +136,10 @@ impl TryFrom<&[u8]> for BidSubmissionHeader { type Error = ParseError; fn try_from(value: &[u8]) -> Result { - let sequence_number = u128::from_be_bytes(value[..16].try_into().unwrap()); + let sequence_number = u32::from_be_bytes(value[..4].try_into().unwrap()); let merge_type = - MergeType::try_from(value[16]).map_err(|_| ParseError::InvalidMergeType(value[16]))?; - let flags = BidSubmissionFlags::from_bits_retain(value[17]); + MergeType::try_from(value[4]).map_err(|_| ParseError::InvalidMergeType(value[4]))?; + let flags = BidSubmissionFlags::from_bits_retain(value[5]); Ok(Self { sequence_number, merge_type, flags }) } @@ -225,7 +225,8 @@ impl Status { #[repr(C)] #[derive(Debug, Clone, ssz_derive::Encode, ssz_derive::Decode)] pub struct BidSubmissionResponse { - pub sequence_number: SeqNum, + pub sequence_number: u32, + pub request_id: [u8; 16], // UUID pub status: Status, pub error_msg: Vec, } @@ -237,7 +238,7 @@ mod tests { #[test] fn test_bid_submission_header() { let header = BidSubmissionHeader { - sequence_number: 1913u128, + sequence_number: 1913, merge_type: MergeType::Mergeable, flags: BidSubmissionFlags::all(), }; diff --git a/crates/types/src/bid_submission.rs b/crates/types/src/bid_submission.rs index 28de9f4cc..82061da78 100644 --- a/crates/types/src/bid_submission.rs +++ b/crates/types/src/bid_submission.rs @@ -10,8 +10,8 @@ use tree_hash_derive::TreeHash; use crate::{ BlobsBundle, BlobsBundleV1, BlobsBundleV2, BlobsError, Bloom, BlsPublicKey, BlsPublicKeyBytes, - BlsSignature, BlsSignatureBytes, ExecutionPayload, ExtraData, PayloadAndBlobs, SeqNum, - SszError, bid_adjustment_data::BidAdjustmentData, error::SigError, fields::ExecutionRequests, + BlsSignature, BlsSignatureBytes, ExecutionPayload, ExtraData, PayloadAndBlobs, SszError, + bid_adjustment_data::BidAdjustmentData, error::SigError, fields::ExecutionRequests, }; #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Encode, Decode, TreeHash)] @@ -696,11 +696,11 @@ impl SignedBidSubmissionFuluWithAdjustments { #[derive(Clone, Copy, PartialEq, Eq)] pub struct SubmissionVersion { on_receive_ns: u64, - sequence: Option, + sequence: Option, } impl SubmissionVersion { - pub fn new(on_receive_ns: u64, sequence: Option) -> Self { + pub fn new(on_receive_ns: u64, sequence: Option) -> Self { Self { on_receive_ns, sequence } } diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs index 0afc80e59..968fd84bf 100644 --- a/crates/types/src/lib.rs +++ b/crates/types/src/lib.rs @@ -23,7 +23,7 @@ pub use clock::*; pub use error::*; pub use execution_payload::*; pub use fields::*; -pub use helix_tcp_types::{Compression, MergeType, SeqNum}; +pub use helix_tcp_types::{Compression, MergeType}; pub use hydration::*; pub use lh_kzg::{KzgCommitment, KzgProof}; pub use lh_test_random::TestRandom; From 7c011052ce6b0537f96fe0f0ed868b37c7fea8ae Mon Sep 17 00:00:00 2001 From: Nina Date: Wed, 18 Feb 2026 14:15:02 +0000 Subject: [PATCH 10/12] submission ref --- crates/relay/src/api/builder/submit_block.rs | 2 +- crates/relay/src/auctioneer/context.rs | 2 +- crates/relay/src/auctioneer/handle.rs | 4 +- crates/relay/src/auctioneer/mod.rs | 8 +-- .../relay/src/auctioneer/simulator/manager.rs | 7 ++- crates/relay/src/auctioneer/simulator/mod.rs | 8 +-- crates/relay/src/auctioneer/submit_block.rs | 21 ++++---- crates/relay/src/auctioneer/types.rs | 13 ++++- crates/relay/src/auctioneer/worker.rs | 6 +-- crates/relay/src/tcp_bid_recv/mod.rs | 51 +++++++++---------- 10 files changed, 66 insertions(+), 56 deletions(-) diff --git a/crates/relay/src/api/builder/submit_block.rs b/crates/relay/src/api/builder/submit_block.rs index 9ed00f301..06b3f08ca 100644 --- a/crates/relay/src/api/builder/submit_block.rs +++ b/crates/relay/src/api/builder/submit_block.rs @@ -42,7 +42,7 @@ impl BuilderApi { let (tx, rx) = tokio::sync::oneshot::channel(); if api .auctioneer_handle - .block_submission(header, body, trace, SubmissionResultSender::OneShot(tx), None) + .block_submission(None, header, body, trace, SubmissionResultSender::OneShot(tx), None) .is_err() { error!("failed sending request to worker"); diff --git a/crates/relay/src/auctioneer/context.rs b/crates/relay/src/auctioneer/context.rs index 4cfeec7ee..ebac3a91f 100644 --- a/crates/relay/src/auctioneer/context.rs +++ b/crates/relay/src/auctioneer/context.rs @@ -214,7 +214,7 @@ impl Context { if let Some(res_tx) = result.res_tx { // submission was initially valid but by the time sim finished the slot already // progressed - res_tx.try_send((result.submission_id, Err(BuilderApiError::SimOnNextSlot))); + res_tx.try_send((result.submission_ref, Err(BuilderApiError::SimOnNextSlot))); } } diff --git a/crates/relay/src/auctioneer/handle.rs b/crates/relay/src/auctioneer/handle.rs index a94dfbf2e..bd732656d 100644 --- a/crates/relay/src/auctioneer/handle.rs +++ b/crates/relay/src/auctioneer/handle.rs @@ -8,7 +8,7 @@ use tracing::trace; use crate::{ auctioneer::types::{ Event, GetHeaderResult, GetPayloadResult, InternalBidSubmissionHeader, RegWorkerJob, - SubWorkerJob, SubmissionResult, SubmissionResultSender, + SubWorkerJob, SubmissionRef, SubmissionResult, SubmissionResultSender, }, gossip::BroadcastPayloadParams, }; @@ -29,6 +29,7 @@ impl AuctioneerHandle { pub fn block_submission( &self, + submission_ref: Option, header: InternalBidSubmissionHeader, body: bytes::Bytes, trace: SubmissionTrace, @@ -38,6 +39,7 @@ impl AuctioneerHandle { trace!("sending to worker"); self.worker .try_send(SubWorkerJob::BlockSubmission { + submission_ref, header, body, trace, diff --git a/crates/relay/src/auctioneer/mod.rs b/crates/relay/src/auctioneer/mod.rs index e8c0279b0..4c03d2efa 100644 --- a/crates/relay/src/auctioneer/mod.rs +++ b/crates/relay/src/auctioneer/mod.rs @@ -44,7 +44,7 @@ pub use crate::auctioneer::{ bid_sorter::BidSorter, context::Context, simulator::{SimulatorRequest, client::SimulatorClient, manager::SimulatorManager}, - types::{InternalBidSubmissionHeader, SubmissionResult, SubmissionResultSender}, /* move to types? */ + types::{InternalBidSubmissionHeader, SubmissionRef, SubmissionResult, SubmissionResultSender}, /* move to types? */ }; use crate::{ HelixSpine, PostgresDatabaseService, @@ -420,7 +420,7 @@ impl State { Event::Submission { submission_data, res_tx, .. }, ) => { res_tx.try_send(( - submission_data.submission_id, + submission_data.submission_ref, Err(BuilderApiError::DeliveringPayload { bid_slot: submission_data.bid_slot(), delivering: slot_ctx.bid_slot.as_u64(), @@ -472,12 +472,12 @@ impl State { if submission_data.bid_slot() == bid_slot.as_u64() { // either not registered or waiting for full data from housekepper res_tx.try_send(( - submission_data.submission_id, + submission_data.submission_ref, Err(BuilderApiError::ProposerDutyNotFound), )); } else { res_tx.try_send(( - submission_data.submission_id, + submission_data.submission_ref, Err(BuilderApiError::BidValidation( helix_types::BlockValidationError::SubmissionForWrongSlot { expected: *bid_slot, diff --git a/crates/relay/src/auctioneer/simulator/manager.rs b/crates/relay/src/auctioneer/simulator/manager.rs index ce1aeb969..b5890366e 100644 --- a/crates/relay/src/auctioneer/simulator/manager.rs +++ b/crates/relay/src/auctioneer/simulator/manager.rs @@ -13,14 +13,13 @@ use helix_common::{ }; use helix_types::{BlsPublicKeyBytes, SignedBidSubmission, SubmissionVersion}; use tracing::{debug, error, info, warn}; -use uuid::Uuid; use crate::{ api::service::SIMULATOR_REQUEST_TIMEOUT, auctioneer::{ SubmissionResultSender, simulator::{BlockMergeRequest, SimulatorRequest, client::SimulatorClient}, - types::{Event, SubmissionResult}, + types::{Event, SubmissionRef, SubmissionResult}, }, }; @@ -42,7 +41,7 @@ struct LocalTelemetry { pub type SimulationResult = (usize, Option); pub struct SimulationResultInner { pub result: Result<(), BlockSimError>, - pub submission_id: Uuid, + pub submission_ref: Option, // Some if not optimistic pub res_tx: Option>, // TODO: move up @@ -232,7 +231,7 @@ impl SimulatorManager { let result = ( id, Some(SimulationResultInner { - submission_id: req.submission_id, + submission_ref: req.submission_ref, result: res, paused_until, res_tx: req.res_tx, diff --git a/crates/relay/src/auctioneer/simulator/mod.rs b/crates/relay/src/auctioneer/simulator/mod.rs index 21759e8b8..3756fe456 100644 --- a/crates/relay/src/auctioneer/simulator/mod.rs +++ b/crates/relay/src/auctioneer/simulator/mod.rs @@ -10,9 +10,11 @@ use helix_types::{ ExecutionPayload, ExecutionRequests, MergeableOrderWithOrigin, SignedBidSubmission, SubmissionVersion, }; -use uuid::Uuid; -use crate::auctioneer::{SubmissionResultSender, types::SubmissionResult}; +use crate::auctioneer::{ + SubmissionResultSender, + types::{SubmissionRef, SubmissionResult}, +}; pub mod client; pub mod manager; @@ -111,7 +113,7 @@ pub struct SimulatorRequest { pub is_top_bid: bool, pub version: SubmissionVersion, pub submission: SignedBidSubmission, - pub submission_id: Uuid, + pub submission_ref: Option, /// None if optimistic pub res_tx: Option>, pub trace: SubmissionTrace, diff --git a/crates/relay/src/auctioneer/submit_block.rs b/crates/relay/src/auctioneer/submit_block.rs index 6949bee5d..bd8cf66f2 100644 --- a/crates/relay/src/auctioneer/submit_block.rs +++ b/crates/relay/src/auctioneer/submit_block.rs @@ -12,7 +12,6 @@ use helix_types::{ SubmissionVersion, }; use tracing::{error, trace}; -use uuid::Uuid; use crate::{ api::builder::error::BuilderApiError, @@ -21,7 +20,9 @@ use crate::{ bid_adjustor::BidAdjustor, context::Context, simulator::{BlockSimRequest, SimulatorRequest, manager::SimulationResult}, - types::{PayloadEntry, SlotData, Submission, SubmissionData, SubmissionResult}, + types::{ + PayloadEntry, SlotData, Submission, SubmissionData, SubmissionRef, SubmissionResult, + }, }, housekeeper::PayloadAttributesUpdate, }; @@ -33,11 +34,11 @@ impl Context { res_tx: SubmissionResultSender, slot_data: &SlotData, ) { - let submission_id = submission_data.submission_id; + let submission_ref = submission_data.submission_ref; match self.validate_and_sort(submission_data, slot_data) { Ok((validated, optimistic_version, merging_data)) => { let res_tx = if optimistic_version.is_optimistic() { - res_tx.try_send((submission_id, Ok(()))); + res_tx.try_send((submission_ref, Ok(()))); None } else { Some(res_tx) @@ -79,7 +80,7 @@ impl Context { } Err(err) => { - res_tx.try_send((submission_id, Err(err))); + res_tx.try_send((submission_ref, Err(err))); } } } @@ -97,7 +98,7 @@ impl Context { self.bid_sorter.demote(*result.submission.builder_public_key()); if let Some(res_tx) = res_tx { res_tx.try_send(( - result.submission_id, + result.submission_ref, Err(BuilderApiError::BlockSimulation(err.clone())), )); }; @@ -116,7 +117,7 @@ impl Context { } self.request_merged_block(); - res_tx.try_send((result.submission_id, Ok(()))); + res_tx.try_send((result.submission_ref, Ok(()))); }; } } @@ -209,7 +210,7 @@ impl Context { }); let validated = ValidatedData { - submission_id: submission_data.submission_id, + submission_ref: submission_data.submission_ref, submission, tx_root: maybe_tx_root, payload_attributes, @@ -237,7 +238,7 @@ impl Context { ); let req = SimulatorRequest { - submission_id: validated.submission_id, + submission_ref: validated.submission_ref, request, is_top_bid: validated.is_top_bid, res_tx, @@ -317,7 +318,7 @@ impl Context { } pub struct ValidatedData<'a> { - pub submission_id: Uuid, + pub submission_ref: Option, pub submission: SignedBidSubmission, pub tx_root: Option, pub payload_attributes: &'a PayloadAttributesUpdate, diff --git a/crates/relay/src/auctioneer/types.rs b/crates/relay/src/auctioneer/types.rs index 8c37f4909..74b193dec 100644 --- a/crates/relay/src/auctioneer/types.rs +++ b/crates/relay/src/auctioneer/types.rs @@ -5,6 +5,7 @@ use std::{ }; use alloy_primitives::{B256, U256}; +use flux_network::Token; use helix_common::{ GetPayloadTrace, SubmissionTrace, api::{ @@ -47,7 +48,14 @@ use crate::{ housekeeper::PayloadAttributesUpdate, }; -pub type SubmissionResult = (Uuid, Result<(), BuilderApiError>); +#[derive(Clone, Copy, Debug)] +pub struct SubmissionRef { + pub id: Uuid, + pub token: Token, + pub seq_num: u32, +} + +pub type SubmissionResult = (Option, Result<(), BuilderApiError>); pub type GetHeaderResult = Result; pub type GetPayloadResult = Result; @@ -178,7 +186,7 @@ pub struct GetPayloadResultData { #[derive(Clone, Debug)] pub struct SubmissionData { - pub submission_id: Uuid, + pub submission_ref: Option, pub submission: Submission, pub merging_data: Option, pub bid_adjustment_data: Option, @@ -431,6 +439,7 @@ impl PayloadBidDataRef<'_> { pub enum SubWorkerJob { BlockSubmission { + submission_ref: Option, header: InternalBidSubmissionHeader, body: bytes::Bytes, trace: SubmissionTrace, // TODO: replace this with better tracing diff --git a/crates/relay/src/auctioneer/worker.rs b/crates/relay/src/auctioneer/worker.rs index eec12a867..93674adbe 100644 --- a/crates/relay/src/auctioneer/worker.rs +++ b/crates/relay/src/auctioneer/worker.rs @@ -116,6 +116,7 @@ impl SubWorker { fn _handle_task(&self, task: SubWorkerJob) { match task { SubWorkerJob::BlockSubmission { + submission_ref, header, body, mut trace, @@ -124,7 +125,6 @@ impl SubWorker { sent_at, expected_pubkey, } => { - let submission_id = header.id; record_submission_step("worker_recv", sent_at.elapsed()); let guard = span.enter(); trace!("received by worker"); @@ -172,7 +172,7 @@ impl SubWorker { }; let submission_data = SubmissionData { - submission_id, + submission_ref, submission, version, merging_data, @@ -194,7 +194,7 @@ impl SubWorker { } Err(err) => { - res_tx.try_send((submission_id, Err(err))); + res_tx.try_send((submission_ref, Err(err))); } } } diff --git a/crates/relay/src/tcp_bid_recv/mod.rs b/crates/relay/src/tcp_bid_recv/mod.rs index 8c4bf84ed..95a17574d 100644 --- a/crates/relay/src/tcp_bid_recv/mod.rs +++ b/crates/relay/src/tcp_bid_recv/mod.rs @@ -15,7 +15,7 @@ use uuid::Uuid; use crate::{ AuctioneerHandle, HelixSpine, SubmissionResult, - auctioneer::{InternalBidSubmissionHeader, SubmissionResultSender}, + auctioneer::{InternalBidSubmissionHeader, SubmissionRef, SubmissionResultSender}, }; pub mod types; @@ -28,8 +28,6 @@ pub use crate::tcp_bid_recv::types::{ BidSubmissionError, response_from_bid_submission_error, response_from_builder_api_error, }; -const SUBMISSIONS_PER_SLOT: usize = 5000usize; - type SubmissionError = (Token, Option, Option, BidSubmissionError); pub struct BidSubmissionTcpListener { @@ -43,7 +41,6 @@ pub struct BidSubmissionTcpListener { to_disconnect: Vec, registered: HashMap, - in_flight: HashMap, submission_errors: Vec, } @@ -70,21 +67,20 @@ impl BidSubmissionTcpListener { tx, to_disconnect: Vec::with_capacity(max_connections), registered: HashMap::with_capacity(max_connections), - in_flight: HashMap::with_capacity(max_connections * SUBMISSIONS_PER_SLOT), submission_errors: Vec::with_capacity(max_connections), } } #[tracing::instrument(skip_all, fields( - id =% request_id, + id =% submission_ref.id, slot = tracing::field::Empty, builder_pubkey = tracing::field::Empty, builder_id = tracing::field::Empty, block_hash = tracing::field::Empty, ))] fn accept_bid_submission( - request_id: Uuid, + submission_ref: SubmissionRef, tx: Sender, auctioneer_handle: &AuctioneerHandle, bid: BidSubmission, @@ -92,10 +88,11 @@ impl BidSubmissionTcpListener { ) -> Result<(), BidSubmissionError> { let now = utcnow_ns(); let trace = SubmissionTrace { receive: now, read_body: now, ..Default::default() }; - let header = InternalBidSubmissionHeader::from_tcp_header(request_id, bid.header); + let header = InternalBidSubmissionHeader::from_tcp_header(submission_ref.id, bid.header); auctioneer_handle .block_submission( + Some(submission_ref), header, bid.data, trace, @@ -119,25 +116,25 @@ impl Tile for BidSubmissionTcpListener { if let Some(expected_pubkey) = self.registered.get(&token) { match BidSubmission::try_from(payload).map_err(BidSubmissionError::from) { Ok(bid) => { - let request_id = Uuid::new_v4(); - let seq_num = bid.header.sequence_number; - match Self::accept_bid_submission( - request_id, + let submission_ref = SubmissionRef { + id: Uuid::new_v4(), + token, + seq_num: bid.header.sequence_number, + }; + if let Err(e) = Self::accept_bid_submission( + submission_ref, self.tx.clone(), &self.auctioneer_handle, bid, *expected_pubkey, ) { - Ok(()) => {self.in_flight.insert(request_id, (token, seq_num));}, - Err(e) => { - tracing::error!(err=%e, id=%request_id, "failed to send bid submission to worker"); - self.submission_errors.push(( - token, - Some(seq_num), - Some(request_id), - e, - )); - } + tracing::error!(err=%e, id=%submission_ref.id, "failed to send bid submission to worker"); + self.submission_errors.push(( + submission_ref.token, + Some(submission_ref.seq_num), + Some(submission_ref.id), + e, + )); } } Err(e) => { @@ -185,14 +182,14 @@ impl Tile for BidSubmissionTcpListener { }); } - for (request_id, result) in self.rx.try_iter() { - if let Some((token, seq_num)) = self.in_flight.remove(&request_id) { - let response = response_from_builder_api_error(seq_num, request_id, &result); - self.listener.write_or_enqueue_with(SendBehavior::Single(token), |buffer| { + for (submission_ref, result) in self.rx.try_iter() { + if let Some(r) = submission_ref { + let response = response_from_builder_api_error(r.seq_num, r.id, &result); + self.listener.write_or_enqueue_with(SendBehavior::Single(r.token), |buffer| { response.ssz_append(buffer); }); } else { - tracing::error!("no in-flight entry for request_id on submission result"); + tracing::error!("submission result has no SubmissionRef"); } } } From 368cc0f30215a85b79ecc1d80e213b9b7544e423 Mon Sep 17 00:00:00 2001 From: Nina Date: Wed, 18 Feb 2026 14:20:07 +0000 Subject: [PATCH 11/12] temp flux --- Cargo.lock | 16 ++++++++-------- Cargo.toml | 8 ++++---- crates/relay/src/tcp_bid_recv/mod.rs | 6 +++++- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f2ed6e183..a3073551b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4533,7 +4533,7 @@ dependencies = [ [[package]] name = "flux" version = "0.0.37" -source = "git+https://github.com/gattaca-com/flux?rev=1fbb6568ee3635e3763e7dec52625b01a673837f#1fbb6568ee3635e3763e7dec52625b01a673837f" +source = "git+https://github.com/gattaca-com/flux?branch=ng%2Freconnect#b4c209f6ce592dcc3397a9d68921be01d56f5741" dependencies = [ "bitcode", "core_affinity", @@ -4556,7 +4556,7 @@ dependencies = [ [[package]] name = "flux-communication" version = "0.0.26" -source = "git+https://github.com/gattaca-com/flux?rev=1fbb6568ee3635e3763e7dec52625b01a673837f#1fbb6568ee3635e3763e7dec52625b01a673837f" +source = "git+https://github.com/gattaca-com/flux?branch=ng%2Freconnect#b4c209f6ce592dcc3397a9d68921be01d56f5741" dependencies = [ "directories", "flux-timing", @@ -4570,7 +4570,7 @@ dependencies = [ [[package]] name = "flux-network" version = "0.0.8" -source = "git+https://github.com/gattaca-com/flux?rev=1fbb6568ee3635e3763e7dec52625b01a673837f#1fbb6568ee3635e3763e7dec52625b01a673837f" +source = "git+https://github.com/gattaca-com/flux?branch=ng%2Freconnect#b4c209f6ce592dcc3397a9d68921be01d56f5741" dependencies = [ "flux-communication", "flux-timing", @@ -4583,7 +4583,7 @@ dependencies = [ [[package]] name = "flux-timing" version = "0.0.15" -source = "git+https://github.com/gattaca-com/flux?rev=1fbb6568ee3635e3763e7dec52625b01a673837f#1fbb6568ee3635e3763e7dec52625b01a673837f" +source = "git+https://github.com/gattaca-com/flux?branch=ng%2Freconnect#b4c209f6ce592dcc3397a9d68921be01d56f5741" dependencies = [ "bitcode", "chrono", @@ -4601,7 +4601,7 @@ dependencies = [ [[package]] name = "flux-utils" version = "0.0.22" -source = "git+https://github.com/gattaca-com/flux?rev=1fbb6568ee3635e3763e7dec52625b01a673837f#1fbb6568ee3635e3763e7dec52625b01a673837f" +source = "git+https://github.com/gattaca-com/flux?branch=ng%2Freconnect#b4c209f6ce592dcc3397a9d68921be01d56f5741" dependencies = [ "core_affinity", "directories", @@ -12931,7 +12931,7 @@ checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] name = "spine-derive" version = "0.0.9" -source = "git+https://github.com/gattaca-com/flux?rev=1fbb6568ee3635e3763e7dec52625b01a673837f#1fbb6568ee3635e3763e7dec52625b01a673837f" +source = "git+https://github.com/gattaca-com/flux?branch=ng%2Freconnect#b4c209f6ce592dcc3397a9d68921be01d56f5741" dependencies = [ "proc-macro2", "quote", @@ -14261,12 +14261,12 @@ dependencies = [ [[package]] name = "type-hash" version = "0.0.1" -source = "git+https://github.com/gattaca-com/flux?rev=1fbb6568ee3635e3763e7dec52625b01a673837f#1fbb6568ee3635e3763e7dec52625b01a673837f" +source = "git+https://github.com/gattaca-com/flux?branch=ng%2Freconnect#b4c209f6ce592dcc3397a9d68921be01d56f5741" [[package]] name = "type-hash-derive" version = "0.0.4" -source = "git+https://github.com/gattaca-com/flux?rev=1fbb6568ee3635e3763e7dec52625b01a673837f#1fbb6568ee3635e3763e7dec52625b01a673837f" +source = "git+https://github.com/gattaca-com/flux?branch=ng%2Freconnect#b4c209f6ce592dcc3397a9d68921be01d56f5741" dependencies = [ "proc-macro-crate", "proc-macro2", diff --git a/Cargo.toml b/Cargo.toml index 0752e9a30..1a8a7fe82 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,10 +42,10 @@ ethers = "2.0.14" eyre = "0.6.12" flate2 = "1.0" -flux = { git = "https://github.com/gattaca-com/flux", rev="1fbb6568ee3635e3763e7dec52625b01a673837f"} -flux-network = { package = "flux-network", git = "https://github.com/gattaca-com/flux", rev = "1fbb6568ee3635e3763e7dec52625b01a673837f"} -flux-type-hash = { package = "type-hash", git = "https://github.com/gattaca-com/flux", rev = "1fbb6568ee3635e3763e7dec52625b01a673837f"} -flux-type-hash-derive = { package = "type-hash-derive", git = "https://github.com/gattaca-com/flux", rev = "1fbb6568ee3635e3763e7dec52625b01a673837f"} +flux = { git = "https://github.com/gattaca-com/flux", branch = "ng/reconnect"} +flux-network = { package = "flux-network", git = "https://github.com/gattaca-com/flux", branch = "ng/reconnect"} +flux-type-hash = { package = "type-hash", git = "https://github.com/gattaca-com/flux",branch = "ng/reconnect"} +flux-type-hash-derive = { package = "type-hash-derive", git = "https://github.com/gattaca-com/flux",branch = "ng/reconnect"} futures = "0.3" futures-util = { version = "0.3", features = ["compat"] } diff --git a/crates/relay/src/tcp_bid_recv/mod.rs b/crates/relay/src/tcp_bid_recv/mod.rs index 95a17574d..562e3846b 100644 --- a/crates/relay/src/tcp_bid_recv/mod.rs +++ b/crates/relay/src/tcp_bid_recv/mod.rs @@ -108,8 +108,12 @@ impl Tile for BidSubmissionTcpListener { self.listener.poll_with(|event| match event { PollEvent::Accept { listener: _, stream, peer_addr } => { tracing::trace!("connected to new peer {:?} with token {:?}", peer_addr, stream); - } + }, + PollEvent::Reconnect { token } => { + tracing::trace!("reconnected to peer with token {:?}", token); + }, PollEvent::Disconnect { token } => { + tracing::trace!("disconnected from peer with token {:?}", token); self.registered.remove(&token); } PollEvent::Message { token, payload, .. } => { From e1692359f41d30b1f21d3a880ca7ac2dd37ce6dc Mon Sep 17 00:00:00 2001 From: Nina Date: Wed, 18 Feb 2026 16:09:00 +0000 Subject: [PATCH 12/12] bump flux --- Cargo.lock | 16 ++++++++-------- Cargo.toml | 8 ++++---- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a3073551b..0d4019418 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4533,7 +4533,7 @@ dependencies = [ [[package]] name = "flux" version = "0.0.37" -source = "git+https://github.com/gattaca-com/flux?branch=ng%2Freconnect#b4c209f6ce592dcc3397a9d68921be01d56f5741" +source = "git+https://github.com/gattaca-com/flux?rev=15dfc44b360c3ec55abdf8e506f2dca60ac72e13#15dfc44b360c3ec55abdf8e506f2dca60ac72e13" dependencies = [ "bitcode", "core_affinity", @@ -4556,7 +4556,7 @@ dependencies = [ [[package]] name = "flux-communication" version = "0.0.26" -source = "git+https://github.com/gattaca-com/flux?branch=ng%2Freconnect#b4c209f6ce592dcc3397a9d68921be01d56f5741" +source = "git+https://github.com/gattaca-com/flux?rev=15dfc44b360c3ec55abdf8e506f2dca60ac72e13#15dfc44b360c3ec55abdf8e506f2dca60ac72e13" dependencies = [ "directories", "flux-timing", @@ -4570,7 +4570,7 @@ dependencies = [ [[package]] name = "flux-network" version = "0.0.8" -source = "git+https://github.com/gattaca-com/flux?branch=ng%2Freconnect#b4c209f6ce592dcc3397a9d68921be01d56f5741" +source = "git+https://github.com/gattaca-com/flux?rev=15dfc44b360c3ec55abdf8e506f2dca60ac72e13#15dfc44b360c3ec55abdf8e506f2dca60ac72e13" dependencies = [ "flux-communication", "flux-timing", @@ -4583,7 +4583,7 @@ dependencies = [ [[package]] name = "flux-timing" version = "0.0.15" -source = "git+https://github.com/gattaca-com/flux?branch=ng%2Freconnect#b4c209f6ce592dcc3397a9d68921be01d56f5741" +source = "git+https://github.com/gattaca-com/flux?rev=15dfc44b360c3ec55abdf8e506f2dca60ac72e13#15dfc44b360c3ec55abdf8e506f2dca60ac72e13" dependencies = [ "bitcode", "chrono", @@ -4601,7 +4601,7 @@ dependencies = [ [[package]] name = "flux-utils" version = "0.0.22" -source = "git+https://github.com/gattaca-com/flux?branch=ng%2Freconnect#b4c209f6ce592dcc3397a9d68921be01d56f5741" +source = "git+https://github.com/gattaca-com/flux?rev=15dfc44b360c3ec55abdf8e506f2dca60ac72e13#15dfc44b360c3ec55abdf8e506f2dca60ac72e13" dependencies = [ "core_affinity", "directories", @@ -12931,7 +12931,7 @@ checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] name = "spine-derive" version = "0.0.9" -source = "git+https://github.com/gattaca-com/flux?branch=ng%2Freconnect#b4c209f6ce592dcc3397a9d68921be01d56f5741" +source = "git+https://github.com/gattaca-com/flux?rev=15dfc44b360c3ec55abdf8e506f2dca60ac72e13#15dfc44b360c3ec55abdf8e506f2dca60ac72e13" dependencies = [ "proc-macro2", "quote", @@ -14261,12 +14261,12 @@ dependencies = [ [[package]] name = "type-hash" version = "0.0.1" -source = "git+https://github.com/gattaca-com/flux?branch=ng%2Freconnect#b4c209f6ce592dcc3397a9d68921be01d56f5741" +source = "git+https://github.com/gattaca-com/flux?rev=15dfc44b360c3ec55abdf8e506f2dca60ac72e13#15dfc44b360c3ec55abdf8e506f2dca60ac72e13" [[package]] name = "type-hash-derive" version = "0.0.4" -source = "git+https://github.com/gattaca-com/flux?branch=ng%2Freconnect#b4c209f6ce592dcc3397a9d68921be01d56f5741" +source = "git+https://github.com/gattaca-com/flux?rev=15dfc44b360c3ec55abdf8e506f2dca60ac72e13#15dfc44b360c3ec55abdf8e506f2dca60ac72e13" dependencies = [ "proc-macro-crate", "proc-macro2", diff --git a/Cargo.toml b/Cargo.toml index 1a8a7fe82..c676a4fa8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,10 +42,10 @@ ethers = "2.0.14" eyre = "0.6.12" flate2 = "1.0" -flux = { git = "https://github.com/gattaca-com/flux", branch = "ng/reconnect"} -flux-network = { package = "flux-network", git = "https://github.com/gattaca-com/flux", branch = "ng/reconnect"} -flux-type-hash = { package = "type-hash", git = "https://github.com/gattaca-com/flux",branch = "ng/reconnect"} -flux-type-hash-derive = { package = "type-hash-derive", git = "https://github.com/gattaca-com/flux",branch = "ng/reconnect"} +flux = { git = "https://github.com/gattaca-com/flux", rev = "15dfc44b360c3ec55abdf8e506f2dca60ac72e13"} +flux-network = { package = "flux-network", git = "https://github.com/gattaca-com/flux", rev = "15dfc44b360c3ec55abdf8e506f2dca60ac72e13"} +flux-type-hash = { package = "type-hash", git = "https://github.com/gattaca-com/flux", rev = "15dfc44b360c3ec55abdf8e506f2dca60ac72e13"} +flux-type-hash-derive = { package = "type-hash-derive", git = "https://github.com/gattaca-com/flux", rev = "15dfc44b360c3ec55abdf8e506f2dca60ac72e13"} futures = "0.3" futures-util = { version = "0.3", features = ["compat"] }