From a90b27b06ca95a5f5fe86b9eab3ee838b0fd3a9c Mon Sep 17 00:00:00 2001 From: Bohdan Ohorodnii <273991985+varex83agent@users.noreply.github.com> Date: Tue, 25 Aug 2026 16:51:54 +0200 Subject: [PATCH 1/3] refactor(eth2api): make ValidatorCache immutable in BeaconNodeClient The validator set is known at node construction (from the cluster validators), so the cache no longer needs to be optional, mutable, or shared behind a lock. Build a single `ValidatorCache` in `node::run` and thread it into both the scheduler and submission `BeaconNodeClient`s at construction. - `BeaconNodeClient::new` now takes the `ValidatorCache` and stores it as a plain field (the type is already `Arc`-backed, so clones share state). - Remove the `Arc>>` wrapping, the `set_validator_cache` setter, and the `NoActiveValidatorCache` error variant. - `validator_cache()` returns `&ValidatorCache`; drops the `.expect`/TODO at the scheduler read site. Closes #482 Co-Authored-By: Bohdan Ohorodnii <35969035+varex83@users.noreply.github.com> --- crates/app/src/node/mod.rs | 17 +++++++- crates/app/src/node/wire.rs | 24 +++++------ crates/app/tests/wiring.rs | 70 ++++++++++++------------------- crates/core/src/bcast/mod.rs | 26 +++++++----- crates/core/src/scheduler.rs | 24 +++++++---- crates/eth2api/src/beacon_node.rs | 37 +++++++--------- 6 files changed, 97 insertions(+), 101 deletions(-) diff --git a/crates/app/src/node/mod.rs b/crates/app/src/node/mod.rs index 9c134c84..f342b504 100644 --- a/crates/app/src/node/mod.rs +++ b/crates/app/src/node/mod.rs @@ -378,10 +378,22 @@ async fn run(config: AppConfig, ct: CancellationToken) -> Result<(), AppError> { verify_fork_schedule(ð2_cl, &lock.fork_version).await?; } - let beacon_client = pluto_eth2api::BeaconNodeClient::new(eth2_cl.clone()); + // One pubkey-scoped validator cache shared by the scheduler's beacon + // client, the submission client, and the validator API, so every consumer + // resolves the same cluster validator set. `ValidatorCache` is `Arc`-backed, + // so the clones seeded into each client (and the one wired into the + // per-epoch refresh subscriber in `wire_core_workflow`) share state, letting + // a single refresh update every consumer at once. + let eth2_pubkeys: Vec<_> = validators.iter().map(|v| v.eth2_pubkey).collect(); + let validator_cache = + pluto_eth2api::valcache::ValidatorCache::new(eth2_cl.clone(), eth2_pubkeys); + + let beacon_client = + pluto_eth2api::BeaconNodeClient::new(eth2_cl.clone(), validator_cache.clone()); // Broadcasting uses a separate client with the (distinct) submit timeout. let submission_api = build_api_client(&beacon_node_addr, config.beacon_node_submit_timeout)?; - let submission_client = pluto_eth2api::BeaconNodeClient::new(submission_api); + let submission_client = + pluto_eth2api::BeaconNodeClient::new(submission_api, validator_cache.clone()); // ---- Beacon-derived duty-workflow inputs ---- @@ -556,6 +568,7 @@ async fn run(config: AppConfig, ct: CancellationToken) -> Result<(), AppError> { beacon_client, eth2_cl, submission_client, + validator_cache, validators, consensus: consensus_controller.current_consensus(), builder_enabled: config.builder_api, diff --git a/crates/app/src/node/wire.rs b/crates/app/src/node/wire.rs index 40dab2ff..85777397 100644 --- a/crates/app/src/node/wire.rs +++ b/crates/app/src/node/wire.rs @@ -258,6 +258,11 @@ pub struct WireInputs { pub eth2_cl: EthBeaconNodeApiClient, /// Submission beacon node client used for broadcasting. pub submission_client: BeaconNodeClient, + /// Pubkey-scoped validator cache shared by the beacon/submission clients + /// and the validator API. A clone of the same `Arc`-backed cache seeded + /// into those clients, so the per-epoch trim + refresh subscriber wired + /// below refreshes every consumer at once. + pub validator_cache: ValidatorCache, /// Per-validator data for this node. pub validators: Vec, /// Current consensus implementation, from the controller. Forwards to the @@ -424,6 +429,7 @@ pub async fn wire_core_workflow( beacon_client, eth2_cl, submission_client, + validator_cache, validators, consensus, builder_enabled, @@ -442,29 +448,19 @@ pub async fn wire_core_workflow( } = inputs; // ---- Derived validator maps ---- - let mut eth2_pubkeys = Vec::with_capacity(validators.len()); // DV root pubkey -> this node's public share (validatorapi wants this flat // map already collapsed for our share index). let mut pub_share_by_pubkey: HashMap = HashMap::new(); let mut fee_recipient_by_pubkey: HashMap = HashMap::new(); for val in &validators { - eth2_pubkeys.push(val.eth2_pubkey); pub_share_by_pubkey.insert(val.eth2_pubkey, val.pubshare); fee_recipient_by_pubkey.insert(val.pubkey, val.fee_recipient); } - // One pubkey-scoped validator cache shared by the scheduler's beacon - // client, the submission client, and the validator API, so every consumer - // resolves the same cluster validator set. Without seeding, the scheduler - // would resolve duties against an empty (or unfiltered) set. `ValidatorCache` - // clones share state, so the per-epoch trim + refresh subscriber registered - // below refreshes every consumer at once. - let validator_cache = ValidatorCache::new(eth2_cl.clone(), eth2_pubkeys); - tokio::join!( - beacon_client.set_validator_cache(validator_cache.clone()), - submission_client.set_validator_cache(validator_cache.clone()), - ); - + // The pubkey-scoped validator cache is built and seeded into the + // beacon/submission clients at construction (in `node::run`), and passed in + // here so the per-epoch trim + refresh subscriber registered below (and the + // validator API) share the same `Arc`-backed state. let fee_recipient_fn: FeeRecipientFunc = { let map = fee_recipient_by_pubkey.clone(); Arc::new(move |pubkey: &PubKey| map.get(pubkey).copied().unwrap_or_default()) diff --git a/crates/app/tests/wiring.rs b/crates/app/tests/wiring.rs index 6d8aa63c..0d68ec41 100644 --- a/crates/app/tests/wiring.rs +++ b/crates/app/tests/wiring.rs @@ -49,6 +49,7 @@ use pluto_eth2api::{ BeaconNodeClient, EthBeaconNodeApiClient, GetStateValidatorsResponseResponse, GetStateValidatorsResponseResponseDatum, spec::{altair, phase0}, + valcache::ValidatorCache, versioned::{self, AttestationPayload, SignedProposalBlock, VersionedAttestation}, }; use pluto_testutil::BeaconMock; @@ -208,7 +209,6 @@ fn attester_partial(share_idx: u64, share: &pluto_crypto::types::PrivateKey) -> /// path connects, not that BLS verification works). fn wire_inputs( eth2_cl: EthBeaconNodeApiClient, - beacon_client: BeaconNodeClient, pubkey: PubKey, consensus: Arc, threshold: u64, @@ -217,14 +217,7 @@ fn wire_inputs( // eth2 verification is deliberately bypassed here. The bad-partial-signature // test injects the real verifier. let permissive_verifier: VerifyFn = Arc::new(|_pubkey, _data| Box::pin(async { Ok(()) })); - wire_inputs_with( - eth2_cl, - beacon_client, - pubkey, - consensus, - threshold, - permissive_verifier, - ) + wire_inputs_with(eth2_cl, pubkey, consensus, threshold, permissive_verifier) } /// Builds the wiring inputs for a single-validator cluster with a caller-chosen @@ -232,7 +225,6 @@ fn wire_inputs( /// verifier parses and verifies the reconstructed group signature against). fn wire_inputs_with( eth2_cl: EthBeaconNodeApiClient, - beacon_client: BeaconNodeClient, pubkey: PubKey, consensus: Arc, threshold: u64, @@ -245,9 +237,14 @@ fn wire_inputs_with( fee_recipient: [0u8; 20], }]; + // One shared, pubkey-scoped cache seeded into both clients at construction, + // mirroring production wiring (`node::run`). + let eth2_pubkeys = validators.iter().map(|v| v.eth2_pubkey).collect(); + let validator_cache = ValidatorCache::new(eth2_cl.clone(), eth2_pubkeys); + let beacon_client = BeaconNodeClient::new(eth2_cl.clone(), validator_cache.clone()); // The broadcaster's constructor performs beacon-node calls, so the // submission client must point at the mock too. - let submission_client = BeaconNodeClient::new(eth2_cl.clone()); + let submission_client = BeaconNodeClient::new(eth2_cl.clone(), validator_cache.clone()); WireInputs { threshold, @@ -255,6 +252,7 @@ fn wire_inputs_with( beacon_client, eth2_cl, submission_client, + validator_cache, validators, consensus, builder_enabled: false, @@ -329,16 +327,12 @@ async fn wiring_exercises_fetcher_back_edges() { let ct = CancellationToken::new(); let mock = BeaconMock::builder().build().await.expect("beacon mock"); let eth2_cl = mock.client().clone(); - let beacon_client = BeaconNodeClient::new(eth2_cl.clone()); let pubkey = PubKey::new([2u8; PK_LEN]); let consensus = build_consensus(&ct); let wired = tokio::time::timeout( GUARD, - wire_core_workflow( - wire_inputs(eth2_cl, beacon_client, pubkey, consensus, 1), - ct.clone(), - ), + wire_core_workflow(wire_inputs(eth2_cl, pubkey, consensus, 1), ct.clone()), ) .await .expect("wire did not deadlock") @@ -428,7 +422,6 @@ async fn wiring_connects_sign_path() { let mock = BeaconMock::builder().build().await.expect("beacon mock"); mount_attestation_submit(mock.server()).await; let eth2_cl = mock.client().clone(); - let beacon_client = BeaconNodeClient::new(eth2_cl.clone()); let pubkey = PubKey::new([5u8; PK_LEN]); let consensus = build_consensus(&ct); @@ -436,7 +429,7 @@ async fn wiring_connects_sign_path() { // partial signatures (distinct share indices) cross the threshold and are // aggregated by SigAgg. const THRESHOLD: u64 = 2; - let inputs = wire_inputs(eth2_cl, beacon_client, pubkey, consensus, THRESHOLD); + let inputs = wire_inputs(eth2_cl, pubkey, consensus, THRESHOLD); let wired = tokio::time::timeout(GUARD, wire_core_workflow(inputs, ct.clone())) .await @@ -551,12 +544,11 @@ async fn wiring_connects_sign_path_proposer() { let mock = BeaconMock::builder().build().await.expect("beacon mock"); mount_submit(mock.server(), "/eth/v2/beacon/blocks").await; let eth2_cl = mock.client().clone(); - let beacon_client = BeaconNodeClient::new(eth2_cl.clone()); let pubkey = PubKey::new([6u8; PK_LEN]); let consensus = build_consensus(&ct); const THRESHOLD: u64 = 2; - let inputs = wire_inputs(eth2_cl, beacon_client, pubkey, consensus, THRESHOLD); + let inputs = wire_inputs(eth2_cl, pubkey, consensus, THRESHOLD); let wired = tokio::time::timeout(GUARD, wire_core_workflow(inputs, ct.clone())) .await @@ -624,12 +616,11 @@ async fn wiring_connects_sign_path_sync_contribution() { let mock = BeaconMock::builder().build().await.expect("beacon mock"); mount_submit(mock.server(), "/eth/v1/validator/contribution_and_proofs").await; let eth2_cl = mock.client().clone(); - let beacon_client = BeaconNodeClient::new(eth2_cl.clone()); let pubkey = PubKey::new([8u8; PK_LEN]); let consensus = build_consensus(&ct); const THRESHOLD: u64 = 2; - let inputs = wire_inputs(eth2_cl, beacon_client, pubkey, consensus, THRESHOLD); + let inputs = wire_inputs(eth2_cl, pubkey, consensus, THRESHOLD); let wired = tokio::time::timeout(GUARD, wire_core_workflow(inputs, ct.clone())) .await @@ -712,7 +703,6 @@ async fn wiring_rejects_bad_partial_signature() { let mock = BeaconMock::builder().build().await.expect("beacon mock"); mount_attestation_submit(mock.server()).await; let eth2_cl = mock.client().clone(); - let beacon_client = BeaconNodeClient::new(eth2_cl.clone()); let consensus = build_consensus(&ct); // Real BLS group key: the verifier parses this pubkey and verifies the @@ -728,14 +718,7 @@ async fn wiring_rejects_bad_partial_signature() { let verifier: VerifyFn = pluto_core::sigagg::new_verifier(Arc::new(eth2_cl.clone())); const THRESHOLD: u64 = 2; - let inputs = wire_inputs_with( - eth2_cl, - beacon_client, - pubkey, - consensus, - THRESHOLD, - verifier, - ); + let inputs = wire_inputs_with(eth2_cl, pubkey, consensus, THRESHOLD, verifier); let wired = tokio::time::timeout(GUARD, wire_core_workflow(inputs, ct.clone())) .await @@ -824,12 +807,12 @@ async fn wiring_rejects_bad_partial_signature() { ct.cancel(); } -/// (d) `wire_core_workflow` seeds one pubkey-scoped validator cache into the -/// scheduler's beacon client and the submission client (Charon shares a single +/// (d) One pubkey-scoped validator cache is seeded into the scheduler's beacon +/// client and the submission client at construction (Charon shares a single /// cache across both; the validator API reuses the same instance). The mock's /// POST validators endpoint returns only validators whose pubkey appears in the -/// request-body `ids`, so the unseeded (empty-pubkey) default cache would -/// resolve zero validators — the regression this test guards against. +/// request-body `ids`, so an unseeded (empty-pubkey) cache would resolve zero +/// validators — the regression this test guards against. #[tokio::test] async fn wiring_seeds_shared_validator_cache() { let ct = CancellationToken::new(); @@ -839,13 +822,14 @@ async fn wiring_seeds_shared_validator_cache() { mount_filtered_post_validators(mock.server(), vec![validator_datum(V_IDX, pubkey)]).await; let eth2_cl = mock.client().clone(); - let beacon_client = BeaconNodeClient::new(eth2_cl.clone()); let consensus = build_consensus(&ct); - // `BeaconNodeClient` clones share the cache slot, so the seeding performed - // inside `wire_core_workflow` is observable through these probes. - let beacon_probe = beacon_client.clone(); - let inputs = wire_inputs(eth2_cl, beacon_client, pubkey, consensus, 1); + // The clients are constructed with the shared, pubkey-seeded cache inside + // `wire_inputs` (mirroring production `node::run`). `BeaconNodeClient` clones + // share the same `Arc`-backed cache, so the seeded pubkeys are observable + // through these probes. + let inputs = wire_inputs(eth2_cl, pubkey, consensus, 1); + let beacon_probe = inputs.beacon_client.clone(); let submission_probe = inputs.submission_client.clone(); let _wired = tokio::time::timeout(GUARD, wire_core_workflow(inputs, ct.clone())) @@ -882,7 +866,6 @@ async fn wiring_delivers_slot_ticks_to_subscriber() { .expect("beacon mock"); let pubkey = PubKey::new([9u8; PK_LEN]); let eth2_cl = mock.client().clone(); - let beacon_client = BeaconNodeClient::new(eth2_cl.clone()); let consensus = build_consensus(&ct); let (tx, mut rx) = tokio::sync::mpsc::channel::(8); @@ -895,7 +878,7 @@ async fn wiring_delivers_slot_ticks_to_subscriber() { }) }); - let mut inputs = wire_inputs(eth2_cl, beacon_client, pubkey, consensus, 1); + let mut inputs = wire_inputs(eth2_cl, pubkey, consensus, 1); inputs.slot_tick = Some(slot_tick); let _wired = tokio::time::timeout(GUARD, wire_core_workflow(inputs, ct.clone())) @@ -980,9 +963,8 @@ async fn multinode_parsig_exchange_reaches_submission() { let mut nodes = Vec::with_capacity(N); for i in 0..N { let eth2_cl = mock.client().clone(); - let beacon_client = BeaconNodeClient::new(eth2_cl.clone()); let consensus = build_consensus(&ct); - let mut inputs = wire_inputs(eth2_cl, beacon_client, pubkey, consensus, THRESHOLD); + let mut inputs = wire_inputs(eth2_cl, pubkey, consensus, THRESHOLD); inputs.parsigex = routed_parsigex_seam(i, Arc::clone(&receivers)); let wired = tokio::time::timeout(GUARD, wire_core_workflow(inputs, ct.clone())) .await diff --git a/crates/core/src/bcast/mod.rs b/crates/core/src/bcast/mod.rs index 99a3f53e..8e341359 100644 --- a/crates/core/src/bcast/mod.rs +++ b/crates/core/src/bcast/mod.rs @@ -868,11 +868,9 @@ mod tests { .mount(beacon.server()) .await; - let client = BeaconNodeClient::new(beacon.client().clone()); - client - .set_validator_cache(ValidatorCache::new(beacon.client().clone(), vec![])) - .await; - client + let api = beacon.client().clone(); + let cache = ValidatorCache::new(api.clone(), vec![]); + BeaconNodeClient::new(api, cache) } fn pubkey(byte: u8) -> PubKey { @@ -890,9 +888,12 @@ mod tests { async fn new_broadcaster() -> (BeaconMock, Broadcaster) { let beacon = BeaconMock::builder().build().await.expect("beacon mock"); mount_submit_successes(beacon.server()).await; - let broadcaster = Broadcaster::new(BeaconNodeClient::new(beacon.client().clone())) - .await - .expect("broadcaster"); + let broadcaster = Broadcaster::new(BeaconNodeClient::new( + beacon.client().clone(), + ValidatorCache::new(beacon.client().clone(), vec![]), + )) + .await + .expect("broadcaster"); (beacon, broadcaster) } @@ -1190,9 +1191,12 @@ mod tests { async fn broadcast_attester_submits_and_swallows_prior_known() { let beacon = BeaconMock::builder().build().await.expect("beacon mock"); mount_prior_attestation_known(beacon.server()).await; - let broadcaster = Broadcaster::new(BeaconNodeClient::new(beacon.client().clone())) - .await - .expect("broadcaster"); + let broadcaster = Broadcaster::new(BeaconNodeClient::new( + beacon.client().clone(), + ValidatorCache::new(beacon.client().clone(), vec![]), + )) + .await + .expect("broadcaster"); let set = signed_set( pubkey(1), VersionedAttestation::new(deneb_attestation()).expect("attestation"), diff --git a/crates/core/src/scheduler.rs b/crates/core/src/scheduler.rs index d29b5abe..ab264160 100644 --- a/crates/core/src/scheduler.rs +++ b/crates/core/src/scheduler.rs @@ -458,8 +458,8 @@ impl SchedulerActor { // During this time the Scheduler actor is blocked. // This is the same behavior as in Charon, but it might not be desirable. - let valcache = self.client.validator_cache().await; - let vals = resolve_active_validators(slot.epoch(), &valcache).await?; + let valcache = self.client.validator_cache(); + let vals = resolve_active_validators(slot.epoch(), valcache).await?; SCHEDULER_METRICS.validators_active.set(vals.len() as u64); @@ -1149,11 +1149,21 @@ mod tests { .await; } + /// Builds a [`BeaconNodeClient`] over the mock with an empty-pubkey + /// validator cache. The mock returns its mounted validator datums + /// regardless of the request's `ids` filter, so an empty pubkey set is + /// sufficient for the scheduler tests. + fn test_beacon_client(mock: &BeaconMock) -> BeaconNodeClient { + let api = mock.client().clone(); + let cache = valcache::ValidatorCache::new(api.clone(), Vec::new()); + BeaconNodeClient::new(api, cache) + } + /// Builds an initial [`SchedulerActor`] wired to the mock's client. No /// epoch resolved yet. fn test_actor(mock: &BeaconMock) -> SchedulerActor { SchedulerActor { - client: pluto_eth2api::BeaconNodeClient::new(mock.client().clone()), + client: test_beacon_client(mock), slots_per_epoch: 1, slot_broadcast: sync::broadcast::channel(CHANNEL_BUFFER_SIZE).0, duty_broadcast: sync::broadcast::channel(CHANNEL_BUFFER_SIZE).0, @@ -1221,7 +1231,7 @@ mod tests { let slot_sub = slot_broadcast.subscribe(); let duty_sub = duty_broadcast.subscribe(); - let client = pluto_eth2api::BeaconNodeClient::new(mock.client().clone()); + let client = test_beacon_client(mock); // Cache slots_per_epoch from the mock's spec, mirroring `build`, so // `get_duty_definition`'s epoch math matches the slots the test drives. let (_slot_duration, slots_per_epoch) = client @@ -1263,7 +1273,7 @@ mod tests { let err = fetch_attester_duties( &test_past_slot(0, 1), validator_set_a_mismatched(), - &BeaconNodeClient::new(mock.client().clone()), + &test_beacon_client(&mock), ) .await .expect_err("mismatched pubkey should be rejected"); @@ -1276,7 +1286,7 @@ mod tests { let err = fetch_proposer_duties( &test_past_slot(0, 1), validator_set_a_mismatched(), - &BeaconNodeClient::new(mock.client().clone()), + &test_beacon_client(&mock), ) .await .expect_err("mismatched pubkey should be rejected"); @@ -1289,7 +1299,7 @@ mod tests { let err = fetch_sync_committee_duties( &test_past_slot(0, 1), validator_set_a_mismatched(), - &BeaconNodeClient::new(mock.client().clone()), + &test_beacon_client(&mock), ) .await .expect_err("mismatched pubkey should be rejected"); diff --git a/crates/eth2api/src/beacon_node.rs b/crates/eth2api/src/beacon_node.rs index 5bef37cb..b6286433 100644 --- a/crates/eth2api/src/beacon_node.rs +++ b/crates/eth2api/src/beacon_node.rs @@ -2,8 +2,6 @@ use crate::{ EthBeaconNodeApiClient, valcache::{ActiveValidators, CompleteValidators, ValidatorCache, ValidatorCacheError}, }; -use std::sync::Arc; -use tokio::sync::RwLock; type Result = std::result::Result; @@ -20,18 +18,18 @@ pub enum BeaconNodeClientError { #[derive(Clone)] pub struct BeaconNodeClient { api: EthBeaconNodeApiClient, - // TODO: Find the concrete usages of the `validator_cache` and consider if we can make it - // immutable, that is, set it once at construction and not have to deal with the possibility of - // it being unset later. - validator_cache: Arc>, + /// Pubkey-scoped validator cache, fixed at construction. [`ValidatorCache`] + /// is `Arc`-backed, so clones (including those held by other consumers) + /// share the same underlying cache state. + validator_cache: ValidatorCache, } impl BeaconNodeClient { - /// Creates a new beacon node client. - pub fn new(api: EthBeaconNodeApiClient) -> Self { + /// Creates a new beacon node client backed by the given validator cache. + pub fn new(api: EthBeaconNodeApiClient, validator_cache: ValidatorCache) -> Self { Self { - api: api.clone(), - validator_cache: Arc::new(RwLock::new(ValidatorCache::new(api, Vec::new()))), + api, + validator_cache, } } @@ -40,26 +38,21 @@ impl BeaconNodeClient { &self.api } - /// Sets the validator cache used by cached validator methods. - pub async fn set_validator_cache(&self, validator_cache: ValidatorCache) { - *self.validator_cache.write().await = validator_cache; - } - /// Returns active validators for `head`. pub async fn active_validators(&self) -> Result { - let (active, _) = self.validator_cache().await.get_by_head().await?; + let (active, _) = self.validator_cache.get_by_head().await?; Ok(active) } /// Returns complete validators for `head`. pub async fn complete_validators(&self) -> Result { - let (_, complete) = self.validator_cache().await.get_by_head().await?; + let (_, complete) = self.validator_cache.get_by_head().await?; Ok(complete) } /// Get the validator cache. - pub async fn validator_cache(&self) -> ValidatorCache { - self.validator_cache.read().await.clone() + pub fn validator_cache(&self) -> &ValidatorCache { + &self.validator_cache } } @@ -102,10 +95,8 @@ mod tests { .mount(&mock) .await; - let client = BeaconNodeClient::new(test_client(&mock)); - client - .set_validator_cache(ValidatorCache::new(client.api().clone(), pubkeys)) - .await; + let api = test_client(&mock); + let client = BeaconNodeClient::new(api.clone(), ValidatorCache::new(api, pubkeys)); let active = client.active_validators().await.unwrap(); let complete = client.complete_validators().await.unwrap(); From 333a01ea3940371f1fc6faef0234a37f4dc209f1 Mon Sep 17 00:00:00 2001 From: "emlautarom1-agent[bot]" <292495798+emlautarom1-agent[bot]@users.noreply.github.com> Date: Tue, 1 Sep 2026 20:22:16 -0300 Subject: [PATCH 2/3] refactor(app): build the validator cache and beacon clients in wire_core_workflow WireInputs takes the two beacon API clients. Wiring derives the cache from the cluster validators once and constructs both BeaconNodeClients, the per-epoch refresher and the validator API from it. The wiring test asserts the scheduler's first validators request carries the cluster pubkeys. --- crates/app/src/node/mod.rs | 18 +----- crates/app/src/node/wire.rs | 29 ++++----- crates/app/tests/wiring.rs | 120 ++++++++++-------------------------- 3 files changed, 46 insertions(+), 121 deletions(-) diff --git a/crates/app/src/node/mod.rs b/crates/app/src/node/mod.rs index f342b504..7463dbbe 100644 --- a/crates/app/src/node/mod.rs +++ b/crates/app/src/node/mod.rs @@ -378,22 +378,8 @@ async fn run(config: AppConfig, ct: CancellationToken) -> Result<(), AppError> { verify_fork_schedule(ð2_cl, &lock.fork_version).await?; } - // One pubkey-scoped validator cache shared by the scheduler's beacon - // client, the submission client, and the validator API, so every consumer - // resolves the same cluster validator set. `ValidatorCache` is `Arc`-backed, - // so the clones seeded into each client (and the one wired into the - // per-epoch refresh subscriber in `wire_core_workflow`) share state, letting - // a single refresh update every consumer at once. - let eth2_pubkeys: Vec<_> = validators.iter().map(|v| v.eth2_pubkey).collect(); - let validator_cache = - pluto_eth2api::valcache::ValidatorCache::new(eth2_cl.clone(), eth2_pubkeys); - - let beacon_client = - pluto_eth2api::BeaconNodeClient::new(eth2_cl.clone(), validator_cache.clone()); // Broadcasting uses a separate client with the (distinct) submit timeout. let submission_api = build_api_client(&beacon_node_addr, config.beacon_node_submit_timeout)?; - let submission_client = - pluto_eth2api::BeaconNodeClient::new(submission_api, validator_cache.clone()); // ---- Beacon-derived duty-workflow inputs ---- @@ -565,10 +551,8 @@ async fn run(config: AppConfig, ct: CancellationToken) -> Result<(), AppError> { WireInputs { threshold, share_idx, - beacon_client, eth2_cl, - submission_client, - validator_cache, + submission_api, validators, consensus: consensus_controller.current_consensus(), builder_enabled: config.builder_api, diff --git a/crates/app/src/node/wire.rs b/crates/app/src/node/wire.rs index 85777397..ab38a35b 100644 --- a/crates/app/src/node/wire.rs +++ b/crates/app/src/node/wire.rs @@ -252,17 +252,10 @@ pub struct WireInputs { pub threshold: u64, /// This node's 1-indexed share index. pub share_idx: u64, - /// Beacon node client used for scheduling. - pub beacon_client: BeaconNodeClient, - /// Beacon node API client used for fetching / dutydb / validatorapi. + /// Beacon node API client for everything except broadcasting. pub eth2_cl: EthBeaconNodeApiClient, - /// Submission beacon node client used for broadcasting. - pub submission_client: BeaconNodeClient, - /// Pubkey-scoped validator cache shared by the beacon/submission clients - /// and the validator API. A clone of the same `Arc`-backed cache seeded - /// into those clients, so the per-epoch trim + refresh subscriber wired - /// below refreshes every consumer at once. - pub validator_cache: ValidatorCache, + /// Beacon node API client for broadcasting, built with the submit timeout. + pub submission_api: EthBeaconNodeApiClient, /// Per-validator data for this node. pub validators: Vec, /// Current consensus implementation, from the controller. Forwards to the @@ -426,10 +419,8 @@ pub async fn wire_core_workflow( let WireInputs { threshold, share_idx, - beacon_client, eth2_cl, - submission_client, - validator_cache, + submission_api, validators, consensus, builder_enabled, @@ -457,15 +448,19 @@ pub async fn wire_core_workflow( fee_recipient_by_pubkey.insert(val.pubkey, val.fee_recipient); } - // The pubkey-scoped validator cache is built and seeded into the - // beacon/submission clients at construction (in `node::run`), and passed in - // here so the per-epoch trim + refresh subscriber registered below (and the - // validator API) share the same `Arc`-backed state. let fee_recipient_fn: FeeRecipientFunc = { let map = fee_recipient_by_pubkey.clone(); Arc::new(move |pubkey: &PubKey| map.get(pubkey).copied().unwrap_or_default()) }; + // ---- Beacon node clients ---- + // Both clients, the per-epoch refresher and the validator API share one + // validator cache, so a single refresh serves every consumer. + let eth2_pubkeys = validators.iter().map(|v| v.eth2_pubkey).collect(); + let validator_cache = ValidatorCache::new(eth2_cl.clone(), eth2_pubkeys); + let beacon_client = BeaconNodeClient::new(eth2_cl.clone(), validator_cache.clone()); + let submission_client = BeaconNodeClient::new(submission_api, validator_cache.clone()); + // ---- Deadliners (one per component) ---- // // Each component gets its own deadliner task sharing the injected calculator diff --git a/crates/app/tests/wiring.rs b/crates/app/tests/wiring.rs index 0d68ec41..11dee700 100644 --- a/crates/app/tests/wiring.rs +++ b/crates/app/tests/wiring.rs @@ -46,18 +46,16 @@ use pluto_core::{ }; use pluto_crypto::tbls; use pluto_eth2api::{ - BeaconNodeClient, EthBeaconNodeApiClient, GetStateValidatorsResponseResponse, - GetStateValidatorsResponseResponseDatum, + EthBeaconNodeApiClient, spec::{altair, phase0}, - valcache::ValidatorCache, versioned::{self, AttestationPayload, SignedProposalBlock, VersionedAttestation}, }; use pluto_testutil::BeaconMock; use tokio::sync::Mutex; use tokio_util::sync::CancellationToken; use wiremock::{ - Mock, MockServer, Request, ResponseTemplate, - matchers::{method, path, path_regex}, + Mock, MockServer, ResponseTemplate, + matchers::{method, path}, }; const PK_LEN: usize = 48; @@ -119,46 +117,7 @@ async fn wait_for_post(server: &MockServer, submit_path: &'static str) -> usize } }) .await - .unwrap_or_else(|_| panic!("submit endpoint {submit_path} should be hit")) -} - -/// Builds a `/states/{id}/validators` datum for an active validator with the -/// given index and pubkey. -fn validator_datum(index: u64, pubkey: PubKey) -> GetStateValidatorsResponseResponseDatum { - let v = pluto_testutil::Validator::active(index, pubkey_to_eth2(pubkey)); - GetStateValidatorsResponseResponseDatum { - index: v.index.to_string(), - balance: v.balance.to_string(), - status: v.status, - validator: v.validator, - } -} - -/// Mounts POST `/eth/v1/beacon/states/{state_id}/validators` returning ONLY the -/// datums whose pubkey appears in the request-body `ids` — so an unseeded -/// (empty-pubkey) cache resolves zero validators. Cover both `head` and slot -/// state IDs because the scheduler refreshes the cache by slot immediately. -async fn mount_filtered_post_validators( - server: &MockServer, - datums: Vec, -) { - Mock::given(method("POST")) - .and(path_regex(r"^/eth/v1/beacon/states/[^/]+/validators$")) - .respond_with(move |request: &Request| { - let body = String::from_utf8_lossy(&request.body); - let data: Vec<_> = datums - .iter() - .filter(|d| body.contains(&d.validator.pubkey)) - .cloned() - .collect(); - ResponseTemplate::new(200).set_body_json(GetStateValidatorsResponseResponse { - execution_optimistic: false, - finalized: true, - data, - }) - }) - .mount(server) - .await; + .unwrap_or_else(|_| panic!("POST {submit_path} should be hit")) } /// Counts POSTs the mock has received for `submit_path`. @@ -237,22 +196,15 @@ fn wire_inputs_with( fee_recipient: [0u8; 20], }]; - // One shared, pubkey-scoped cache seeded into both clients at construction, - // mirroring production wiring (`node::run`). - let eth2_pubkeys = validators.iter().map(|v| v.eth2_pubkey).collect(); - let validator_cache = ValidatorCache::new(eth2_cl.clone(), eth2_pubkeys); - let beacon_client = BeaconNodeClient::new(eth2_cl.clone(), validator_cache.clone()); // The broadcaster's constructor performs beacon-node calls, so the - // submission client must point at the mock too. - let submission_client = BeaconNodeClient::new(eth2_cl.clone(), validator_cache.clone()); + // submission API must point at the mock too. + let submission_api = eth2_cl.clone(); WireInputs { threshold, share_idx: 1, - beacon_client, eth2_cl, - submission_client, - validator_cache, + submission_api, validators, consensus, builder_enabled: false, @@ -807,47 +759,41 @@ async fn wiring_rejects_bad_partial_signature() { ct.cancel(); } -/// (d) One pubkey-scoped validator cache is seeded into the scheduler's beacon -/// client and the submission client at construction (Charon shares a single -/// cache across both; the validator API reuses the same instance). The mock's -/// POST validators endpoint returns only validators whose pubkey appears in the -/// request-body `ids`, so an unseeded (empty-pubkey) cache would resolve zero -/// validators — the regression this test guards against. +/// (d) `wire_core_workflow` seeds the shared validator cache with the cluster +/// pubkeys. The scheduler resolves the current slot on start, so its validators +/// request must carry those pubkeys in `ids`; an unseeded cache sends an empty +/// `ids` and resolves zero validators. #[tokio::test] -async fn wiring_seeds_shared_validator_cache() { +async fn wiring_seeds_validator_cache() { let ct = CancellationToken::new(); let mock = BeaconMock::builder().build().await.expect("beacon mock"); let pubkey = PubKey::new([9u8; PK_LEN]); - const V_IDX: u64 = 7; - mount_filtered_post_validators(mock.server(), vec![validator_datum(V_IDX, pubkey)]).await; - let eth2_cl = mock.client().clone(); let consensus = build_consensus(&ct); - // The clients are constructed with the shared, pubkey-seeded cache inside - // `wire_inputs` (mirroring production `node::run`). `BeaconNodeClient` clones - // share the same `Arc`-backed cache, so the seeded pubkeys are observable - // through these probes. - let inputs = wire_inputs(eth2_cl, pubkey, consensus, 1); - let beacon_probe = inputs.beacon_client.clone(); - let submission_probe = inputs.submission_client.clone(); + let _wired = tokio::time::timeout( + GUARD, + wire_core_workflow(wire_inputs(eth2_cl, pubkey, consensus, 1), ct.clone()), + ) + .await + .expect("wire did not deadlock") + .expect("wire succeeded"); - let _wired = tokio::time::timeout(GUARD, wire_core_workflow(inputs, ct.clone())) + const VALIDATORS: &str = "/eth/v1/beacon/states/head/validators"; + wait_for_post(mock.server(), VALIDATORS).await; + let bodies: Vec<_> = mock + .server() + .received_requests() .await - .expect("wire did not deadlock") - .expect("wire succeeded"); - - for (name, probe) in [("beacon", beacon_probe), ("submission", submission_probe)] { - let active = tokio::time::timeout(GUARD, probe.active_validators()) - .await - .unwrap_or_else(|_| panic!("(d) {name} client active_validators timed out")) - .unwrap_or_else(|e| panic!("(d) {name} client active_validators failed: {e}")); - assert_eq!( - active.get(&V_IDX), - Some(&pubkey_to_eth2(pubkey)), - "(d) the {name} client's cache should be seeded with the cluster pubkeys" - ); - } + .expect("requests") + .iter() + .filter(|r| r.method.as_str() == "POST" && r.url.path() == VALIDATORS) + .map(|r| String::from_utf8_lossy(&r.body).into_owned()) + .collect(); + assert!( + bodies.iter().all(|body| body.contains(&pubkey.to_string())), + "(d) validators requests should carry the cluster pubkeys, got: {bodies:?}" + ); ct.cancel(); } From 5faf3c181eb1fbe6d203db2a2e4050a11133807d Mon Sep 17 00:00:00 2001 From: Lautaro Emanuel Date: Tue, 1 Sep 2026 20:30:58 -0300 Subject: [PATCH 3/3] Update Cargo.lock --- Cargo.lock | 375 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 217 insertions(+), 158 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a1efe2a4..9fc3b4f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -121,7 +121,7 @@ dependencies = [ "either", "k256", "once_cell", - "rand 0.8.7", + "rand 0.8.8", "secp256k1 0.30.0", "serde", "serde_json", @@ -170,9 +170,9 @@ dependencies = [ [[package]] name = "alloy-core" -version = "1.6.1" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8421a5ee9019b6d89f92935d0f8facd9f6ca088b41d7cc47244a02ccde4545f" +checksum = "e88cf3d065edfb29a13278215b8521d3ef72a41e2432e019c1f0dd8e30649a5d" dependencies = [ "alloy-dyn-abi", "alloy-json-abi", @@ -183,9 +183,9 @@ dependencies = [ [[package]] name = "alloy-dyn-abi" -version = "1.6.1" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a04eb4abc2b5074a18e687ee63918f407cc7990083cba9b999445f839796060" +checksum = "d9f1a3f2206f2ba4206fdeeddce6640eed3e26b8a13ac41444adb66b76d8e650" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -303,9 +303,9 @@ dependencies = [ [[package]] name = "alloy-json-abi" -version = "1.6.1" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cee30dd4c2f4b23f434fdf675e7bf9681b86768141277266c6f548ef25cba0a" +checksum = "208699c66c453fbb4c50d2e602f8ceff8a5f1fa48ac8b6ee3b6357fdc93da311" dependencies = [ "alloy-primitives", "alloy-sol-type-parser", @@ -369,9 +369,9 @@ dependencies = [ [[package]] name = "alloy-primitives" -version = "1.6.1" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f007e257069855bdf21d27762fd3f3705a613f805c9a08309bf353503f081d71" +checksum = "9c902f0ca3f8353c41e3e1ec3cf26be49412525bc48ab9d3c4710d7be4f01832" dependencies = [ "alloy-rlp", "bytes", @@ -381,7 +381,7 @@ dependencies = [ "fixed-cache", "foldhash 0.2.0", "hashbrown 0.17.1", - "indexmap 2.14.0", + "indexmap 2.14.1", "itoa", "k256", "keccak-asm", @@ -566,15 +566,15 @@ dependencies = [ "alloy-signer", "async-trait", "k256", - "rand 0.8.7", + "rand 0.8.8", "thiserror 2.0.20", ] [[package]] name = "alloy-sol-macro" -version = "1.6.1" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5655c38d5f84955bf727b2eeb62fddd91ebb98fd1d7ae6eb77f73ea88f9b9cf" +checksum = "fdcbd48d60e029be4a325c3a2f1312761caea4ed249f18ba9e8ed24ca1bf01e6" dependencies = [ "alloy-sol-macro-expander", "alloy-sol-macro-input", @@ -586,15 +586,15 @@ dependencies = [ [[package]] name = "alloy-sol-macro-expander" -version = "1.6.1" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6277c780e07b76951e09a59788dde230d1582612324177d11a43a61e21a6bb83" +checksum = "59c9f7c535f99a7e7b64cc520968b09ed14cec3715572fcc277cfbff602808cd" dependencies = [ "alloy-json-abi", "alloy-sol-macro-input", "const-hex", "heck", - "indexmap 2.14.0", + "indexmap 2.14.1", "proc-macro-error3", "proc-macro2", "quote", @@ -605,9 +605,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro-input" -version = "1.6.1" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9762b2ad3e5a0c09886de54fe549ab0056681df843cb082e2df7e1c0eb270d30" +checksum = "1abd404fbc12f543823005146b73fd07621bdc0baaa950d26995c543a9d73811" dependencies = [ "alloy-json-abi", "const-hex", @@ -623,9 +623,9 @@ dependencies = [ [[package]] name = "alloy-sol-type-parser" -version = "1.6.1" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da4c7130f0f01f4719678bda3db3bc7267fc2f7f9d0565e3bd964cd2bb45050d" +checksum = "40a7fd71864526bfeca8903010d5bb7fd28a0a4f5cc55818304c9cad8f0d63ab" dependencies = [ "serde", "winnow", @@ -633,9 +633,9 @@ dependencies = [ [[package]] name = "alloy-sol-types" -version = "1.6.1" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96e74d6213180f78dbdccddce8af02a639c160c94b0a543fa35c77c58b8a7fc" +checksum = "adfc2ba3fb0e865de4934bcad6d37fc51e9ffcd5294be1322eab38e4494e051b" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -704,7 +704,7 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d0626c4f3b2028f7e8db32f53c22d9ecd5939f772317b7c4b6fe5219cb0589a" dependencies = [ - "darling", + "darling 0.23.0", "proc-macro2", "quote", "syn 2.0.119", @@ -1011,7 +1011,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" dependencies = [ "num-traits", - "rand 0.8.7", + "rand 0.8.8", ] [[package]] @@ -1021,7 +1021,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" dependencies = [ "num-traits", - "rand 0.8.7", + "rand 0.8.8", ] [[package]] @@ -1031,7 +1031,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "246a225cc6131e9ee4f24619af0f19d67761fff15d7ccc22e42b80846e69449a" dependencies = [ "num-traits", - "rand 0.8.7", + "rand 0.8.8", ] [[package]] @@ -1041,7 +1041,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "367c9c827ed431bff6868b7aa926e05b16eb46603cc8b6e768e4a5553fa1d155" dependencies = [ "num-traits", - "rand 0.8.7", + "rand 0.8.8", ] [[package]] @@ -1175,7 +1175,7 @@ checksum = "82f6aeea286b8eb4dd3431a1be1b59d290ace00f5bfd8e2a159bc2a05e2c1667" dependencies = [ "proc-macro2", "quote", - "syn 3.0.3", + "syn 3.0.4", ] [[package]] @@ -1228,9 +1228,9 @@ checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" [[package]] name = "aws-lc-rs" -version = "1.18.0" +version = "1.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce2b2dcc879c3bae0d371e77c99f2238400ef24ec001394befa67b6e543add9e" +checksum = "b281d307588d634de920874890732659e2e7672f72b5e10e81badc1a8a83621e" dependencies = [ "aws-lc-sys", "zeroize", @@ -1238,9 +1238,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.44.0" +version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f09fae7be8bb3174e05c6afdb34199e6dc0c7c04ba9fa237b1967adfbde27483" +checksum = "9bff6c3b54fad79a2e60b8102caf565819711497c1f5f092f49508e2f5c31b27" dependencies = [ "cc", "cmake", @@ -1402,7 +1402,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bca4c7abb40c8817d77403c880988cfd484f23ab2365726afb2f798363e2c4a2" dependencies = [ "bitcoin-io", - "hex-conservative 0.2.2", + "hex-conservative 0.2.3", ] [[package]] @@ -1544,34 +1544,32 @@ dependencies = [ [[package]] name = "bon" -version = "3.9.3" +version = "3.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a602c73c7b0148ec6d12af6fd5cc7a46e2eacc8878271a999abac56eed12f561" +checksum = "9e3fac94a66da67200398458a25412bcc3f9b6443b5119a6cad9cf3ccfcd8cc6" dependencies = [ "bon-macros", - "rustversion", ] [[package]] name = "bon-macros" -version = "3.9.3" +version = "3.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dee98b0db6a962de883bf5d20362dee4d7ca0d12fe39a7c6c73c844e1cd7c1f" +checksum = "d4654961ad0494e4774c5c60b4cb4cd0ae9b9d92d039d901638b1dba97ebebf5" dependencies = [ - "darling", + "darling 0.24.1", "ident_case", - "prettyplease", + "prettyplease 0.3.0", "proc-macro2", "quote", - "rustversion", - "syn 2.0.119", + "syn 3.0.4", ] [[package]] name = "borsh" -version = "1.8.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a88b7ea17d208c4193f2c1e6de3c35fe71f98c96982d5ced308bdcc749ff6e1f" +checksum = "553c5d846a6ba5150c65e3b1b8ec073bcf1abc20f9b7220de384a4443ea4e20a" dependencies = [ "borsh-derive", "bytes", @@ -1580,15 +1578,15 @@ dependencies = [ [[package]] name = "borsh-derive" -version = "1.8.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8f347189c62a579b8cd5f80714efa178f52e461dc2e6d701d264f5ff22e566c" +checksum = "12cdfe656708a01f89b451a7d36466e6fe6c414de0aa18fc54f864f6f9ca9f56" dependencies = [ "once_cell", "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.119", + "syn 3.0.4", ] [[package]] @@ -1679,9 +1677,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.4.3" +version = "1.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "509591b7bcd67f4ef775afad7662703b4935daaa6ec0e5605cfb1090b32a2b6d" +checksum = "0ad534f4357a5264cce5019c989cf66a4f0dc4e0d1b1d15f8aacec0ff7360273" dependencies = [ "find-msvc-tools", "jobserver", @@ -1714,12 +1712,12 @@ dependencies = [ [[package]] name = "chacha20" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d524456ba66e72eb8b115ff89e01e497f8e6d11d78b70b1aa13c0fbd97540a81" +checksum = "65c35e4b699c7e15ccbe7ee35c005e4fc0a278d22238a2857e6ce2dadeda1b06" dependencies = [ "cfg-if", - "cpufeatures 0.3.0", + "cpufeatures 0.3.1", "rand_core 0.10.1", ] @@ -1819,7 +1817,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 3.0.3", + "syn 3.0.4", ] [[package]] @@ -1845,9 +1843,9 @@ checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" [[package]] name = "combine" -version = "4.6.7" +version = "4.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +checksum = "cfc320937d09e6de266b31b9afb480f197d7a861be86be7cb2ea7e5d1bfffc5e" dependencies = [ "bytes", "memchr", @@ -1959,9 +1957,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +checksum = "5ca28b0ae3115b884660db4118d803791fd6756b6e88f39c0f3f7859060d7566" dependencies = [ "libc", ] @@ -1983,9 +1981,9 @@ checksum = "217698eaf96b4a3f0bc4f3662aaa55bdf913cd54d7204591faa790070c6d0853" [[package]] name = "crc32fast" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +checksum = "8498c871161e1742aaa9d52551b2d6ebdd4c3d45a3be423e3728f33b955be550" dependencies = [ "cfg-if", ] @@ -2177,8 +2175,18 @@ version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.23.0", + "darling_macro 0.23.0", +] + +[[package]] +name = "darling" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed17f5901b6630b993ca003def43f2f8ef4014fc13b047b57aad617ff32bc2ec" +dependencies = [ + "darling_core 0.24.1", + "darling_macro 0.24.1", ] [[package]] @@ -2195,17 +2203,41 @@ dependencies = [ "syn 2.0.119", ] +[[package]] +name = "darling_core" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6837e2cf7485aaae18f86181d2f0e9a7ed297a025e220aeabf63fdebd3a2ddff" +dependencies = [ + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 3.0.4", +] + [[package]] name = "darling_macro" version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" dependencies = [ - "darling_core", + "darling_core 0.23.0", "quote", "syn 2.0.119", ] +[[package]] +name = "darling_macro" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ac7135c3ef02b2f7833bbeb1be5ba7f966dcde8a87c6b87f65a778d71a02785" +dependencies = [ + "darling_core 0.24.1", + "quote", + "syn 3.0.4", +] + [[package]] name = "dashmap" version = "6.2.1" @@ -2243,7 +2275,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c54e03a951783e8b327515db3f2a2fd0e3bed362a96b066f341ce66ed49b4ead" dependencies = [ "data-encoding", - "syn 3.0.3", + "syn 3.0.4", ] [[package]] @@ -2401,7 +2433,7 @@ checksum = "c6232dd377dcc64799954cbd3a9bb882e9cdc1308ccd87b1c098f1fb2eaf82a8" dependencies = [ "proc-macro2", "quote", - "syn 3.0.3", + "syn 3.0.4", ] [[package]] @@ -2566,7 +2598,7 @@ checksum = "a65863d15a4ce2888bd2f0f543cc963d3879c3a022c8ee43f6141d479a3ac815" dependencies = [ "proc-macro2", "quote", - "syn 3.0.3", + "syn 3.0.4", ] [[package]] @@ -2640,7 +2672,7 @@ version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "daf022360bdbe9456eda5f35718a50476d5b2a0d51a97ed4eae27420737a6fba" dependencies = [ - "darling", + "darling 0.23.0", "proc-macro2", "quote", "syn 2.0.119", @@ -2757,7 +2789,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" dependencies = [ "byteorder", - "rand 0.8.7", + "rand 0.8.8", "rustc-hex", "static_assertions", ] @@ -2770,12 +2802,13 @@ checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" [[package]] name = "flate2" -version = "1.1.9" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" +checksum = "6e634e2e0ebac1ee034020da1ca582e17ffe4e0f5e985823721e168928136dcb" dependencies = [ "crc32fast", "miniz_oxide", + "zlib-rs", ] [[package]] @@ -2893,7 +2926,7 @@ checksum = "9fb9654ba8355388abeb8dcb4fc62f511300867002afc858860463bdd9fe0c44" dependencies = [ "proc-macro2", "quote", - "syn 3.0.3", + "syn 3.0.4", ] [[package]] @@ -3051,9 +3084,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.18" +version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "839c0e8a181239723652be9062bb56ca5bf5f64011f73b623f6f4fc59086a228" +checksum = "ef8e5e5a340588f4452631496976cf8636d4a7ecf600239fdc27615d2530bc16" dependencies = [ "atomic-waker", "bytes", @@ -3061,7 +3094,7 @@ dependencies = [ "futures-core", "futures-sink", "http", - "indexmap 2.14.0", + "indexmap 2.14.1", "slab", "tokio", "tokio-util", @@ -3130,9 +3163,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" +checksum = "e17592d60ebacc7d5e169f4663c5f84f9161cc90328abcfe8456f41e4dfcb284" [[package]] name = "hex" @@ -3142,9 +3175,9 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "hex-conservative" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fda06d18ac606267c40c04e41b9947729bf8b9efe74bd4e82b61a5f26a510b9f" +checksum = "db3fef046dca3ca91ee1408a8c1b80ab777e80a4d308d1bf4e7adb3fcb047e08" dependencies = [ "arrayvec", ] @@ -3294,9 +3327,9 @@ dependencies = [ [[package]] name = "hyper" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d22053281f852e11534f5198498373cbb59295120a20771d90f7ed1897490a72" +checksum = "27b501faa50e7a26c3d3560ca625132f4078a17771f4810baf70475ae48cbe43" dependencies = [ "atomic-waker", "bytes", @@ -3491,9 +3524,9 @@ checksum = "e590f038c1464a96894fd6d10127e90a8be4509f56ff7ecef851b15cee0b7caa" [[package]] name = "icu_provider" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92a7ed671a6aad807a8651a2e1782a6598fda9ce5185dd8158549e95a91c6428" +checksum = "d27bbb9d3abbefac45d55f647c9de1d44aafcd1186eb91879afef17c396c3e73" dependencies = [ "displaydoc", "icu_locale_core", @@ -3618,9 +3651,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.14.0" +version = "2.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +checksum = "07aa2048142242915a31d35844fb311e0e53fcca590c3a0a40dcf1b841fa09eb" dependencies = [ "equivalent", "hashbrown 0.17.1", @@ -3844,12 +3877,12 @@ dependencies = [ [[package]] name = "keccak" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffd9697dc4a9a62e2da93389f34400b77a28f0287711263cabb203b3ccb9c0e4" +checksum = "d8f198d1db720e4940b5a493201d199d9f24f568f8f746bd13706243a2f71598" dependencies = [ "cfg-if", - "cpufeatures 0.3.0", + "cpufeatures 0.3.1", ] [[package]] @@ -3891,9 +3924,9 @@ checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" [[package]] name = "libgit2-sys" -version = "0.18.7+1.9.6" +version = "0.18.8+1.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23c7391e4b9f4ffab1a624223cc1d7385ff9a678f490768add717de7ea2f4d89" +checksum = "7f7c568b25d7489bc3fb2988ed69ab111d2944d2f5fec3d5c987fe545ea97b50" dependencies = [ "cc", "libc", @@ -3970,7 +4003,7 @@ dependencies = [ "libp2p-swarm", "quick-protobuf", "quick-protobuf-codec", - "rand 0.8.7", + "rand 0.8.8", "rand_core 0.6.4", "thiserror 2.0.20", "tracing", @@ -4005,7 +4038,7 @@ dependencies = [ "parking_lot", "pin-project", "quick-protobuf", - "rand 0.8.7", + "rand 0.8.8", "rw-stream-sink", "thiserror 2.0.20", "tracing", @@ -4063,7 +4096,7 @@ dependencies = [ "k256", "multihash", "prost 0.14.4", - "rand 0.8.7", + "rand 0.8.8", "sha2", "thiserror 2.0.20", "tracing", @@ -4082,7 +4115,7 @@ dependencies = [ "libp2p-core", "libp2p-identity", "libp2p-swarm", - "rand 0.8.7", + "rand 0.8.8", "smallvec", "socket2 0.5.10", "tokio", @@ -4121,7 +4154,7 @@ dependencies = [ "multiaddr", "multihash", "quick-protobuf", - "rand 0.8.7", + "rand 0.8.8", "snow", "static_assertions", "thiserror 2.0.20", @@ -4141,7 +4174,7 @@ dependencies = [ "libp2p-core", "libp2p-identity", "libp2p-swarm", - "rand 0.8.7", + "rand 0.8.8", "tracing", "web-time", ] @@ -4160,7 +4193,7 @@ dependencies = [ "libp2p-tls", "quinn", "quinn-proto", - "rand 0.8.7", + "rand 0.8.8", "ring", "rustls", "socket2 0.5.10", @@ -4186,7 +4219,7 @@ dependencies = [ "libp2p-swarm", "quick-protobuf", "quick-protobuf-codec", - "rand 0.8.7", + "rand 0.8.8", "static_assertions", "thiserror 2.0.20", "tracing", @@ -4205,7 +4238,7 @@ dependencies = [ "libp2p-core", "libp2p-identity", "libp2p-swarm", - "rand 0.8.7", + "rand 0.8.8", "smallvec", "tracing", ] @@ -4225,7 +4258,7 @@ dependencies = [ "libp2p-identity", "libp2p-swarm-derive", "multistream-select", - "rand 0.8.7", + "rand 0.8.8", "smallvec", "tokio", "tracing", @@ -4343,9 +4376,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.33" +version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" +checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6" [[package]] name = "loki-api" @@ -4359,9 +4392,9 @@ dependencies = [ [[package]] name = "lru" -version = "0.18.2" +version = "0.18.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d2f2f9b4ba7e6b24d95e7e899329d35be83bcded72c8540cdd5368932d1d90a" +checksum = "0d317b4b9eb398e6acce275758ec6125535505e7a146fb1a9b8bda2451b0ff4c" dependencies = [ "hashbrown 0.17.1", ] @@ -4385,9 +4418,9 @@ dependencies = [ [[package]] name = "match-lookup" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "757aee279b8bdbb9f9e676796fd459e4207a1f986e87886700abf589f5abf771" +checksum = "549e39695cc0b640f3cb378053832db3d2133422d49e8dcae5c866a2aaf1f730" dependencies = [ "proc-macro2", "quote", @@ -4439,9 +4472,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.8.9" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +checksum = "b63fbc4a50860e98e7b2aa7804ded1db5cbc3aff9193adaff57a6931bf7c4b4c" dependencies = [ "adler2", "simd-adler32", @@ -4784,11 +4817,11 @@ dependencies = [ "eventsource-stream", "futures-core", "http", - "indexmap 2.14.0", + "indexmap 2.14.1", "oas3", - "prettyplease", + "prettyplease 0.2.37", "proc-macro2", - "quick-xml", + "quick-xml 0.42.0", "quote", "regex", "reqwest 0.13.4", @@ -4998,7 +5031,7 @@ checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" dependencies = [ "fixedbitset", "hashbrown 0.15.5", - "indexmap 2.14.0", + "indexmap 2.14.1", ] [[package]] @@ -5128,7 +5161,7 @@ dependencies = [ "pluto-testutil", "prost 0.14.4", "prost-types 0.14.4", - "rand 0.8.7", + "rand 0.8.8", "regex", "reqwest 0.13.4", "serde", @@ -5181,8 +5214,8 @@ dependencies = [ "pluto-ssz", "pluto-testutil", "pluto-tracing", - "quick-xml", - "rand 0.8.7", + "quick-xml 0.41.0", + "rand 0.8.8", "reqwest 0.13.4", "serde", "serde_json", @@ -5215,7 +5248,7 @@ dependencies = [ "pluto-p2p", "pluto-ssz", "pluto-testutil", - "rand 0.8.7", + "rand 0.8.8", "reqwest 0.13.4", "serde", "serde_json", @@ -5300,7 +5333,7 @@ dependencies = [ "pluto-tracing", "prost 0.14.4", "prost-types 0.14.4", - "rand 0.8.7", + "rand 0.8.8", "regex", "reqwest 0.13.4", "serde", @@ -5324,7 +5357,7 @@ dependencies = [ "blst", "hex", "pluto-eth2api", - "rand 0.8.7", + "rand 0.8.8", "rand_core 0.6.4", "test-case", "thiserror 2.0.20", @@ -5362,7 +5395,7 @@ dependencies = [ "pluto-tracing", "prost 0.14.4", "prost-types 0.14.4", - "rand 0.8.7", + "rand 0.8.8", "serde", "serde_json", "sha2", @@ -5439,7 +5472,7 @@ dependencies = [ "pluto-k1util", "pluto-ssz", "pluto-testutil", - "rand 0.8.7", + "rand 0.8.8", "regex", "reqwest 0.13.4", "scrypt", @@ -5478,7 +5511,7 @@ version = "1.7.1" dependencies = [ "blst", "hex", - "rand 0.8.7", + "rand 0.8.8", "rand_core 0.6.4", "serde", "serde_json", @@ -5543,7 +5576,7 @@ dependencies = [ "pluto-testutil", "pluto-tracing", "prost 0.14.4", - "rand 0.8.7", + "rand 0.8.8", "reqwest 0.13.4", "serde_json", "tempfile", @@ -5637,7 +5670,7 @@ dependencies = [ "pluto-testutil", "prost 0.14.4", "prost-types 0.14.4", - "rand 0.8.7", + "rand 0.8.8", "test-case", "thiserror 2.0.20", "tokio", @@ -5658,7 +5691,7 @@ dependencies = [ "pluto-eth2util", "pluto-p2p", "pluto-tracing", - "rand 0.8.7", + "rand 0.8.8", "reqwest 0.13.4", "serde_json", "thiserror 2.0.20", @@ -5698,7 +5731,7 @@ dependencies = [ "pluto-crypto", "pluto-eth2api", "pluto-eth2util", - "rand 0.8.7", + "rand 0.8.8", "reqwest 0.13.4", "serde", "serde_json", @@ -5811,6 +5844,16 @@ dependencies = [ "syn 2.0.119", ] +[[package]] +name = "prettyplease" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bfe0f4c752e450fc2faf62654f1c134747922825d5b04ca717b8874f41a40c0" +dependencies = [ + "proc-macro2", + "syn 3.0.4", +] + [[package]] name = "primitive-types" version = "0.12.2" @@ -5931,7 +5974,7 @@ dependencies = [ "log", "multimap", "petgraph", - "prettyplease", + "prettyplease 0.2.37", "prost 0.14.4", "prost-types 0.14.4", "regex", @@ -6015,6 +6058,16 @@ dependencies = [ "serde", ] +[[package]] +name = "quick-xml" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41b1177fdf999d2321d3fb46ff47159d9c1fb9ad66a4879f8c50a0b504615e9b" +dependencies = [ + "memchr", + "serde", +] + [[package]] name = "quinn" version = "0.11.11" @@ -6103,9 +6156,9 @@ checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" [[package]] name = "rand" -version = "0.8.7" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22f6172bdec972074665ed81ed53b71da00bfc44b65a753cfde883ec4c702a1a" +checksum = "e058c7de0b26af77780c769414d6257830bb240f3c38477dbc2c16e5f54d6d4c" dependencies = [ "libc", "rand_chacha 0.3.1", @@ -6130,7 +6183,7 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80" dependencies = [ - "chacha20 0.10.1", + "chacha20 0.10.2", "getrandom 0.4.3", "rand_core 0.10.1", ] @@ -6266,7 +6319,7 @@ checksum = "92ecd8964f8453721699a1ed72037b0db49ce2f5a5138486ee89bed6f67cdf3a" dependencies = [ "proc-macro2", "quote", - "syn 3.0.3", + "syn 3.0.4", ] [[package]] @@ -6459,7 +6512,7 @@ dependencies = [ "parity-scale-codec", "primitive-types", "proptest", - "rand 0.8.7", + "rand 0.8.8", "rand 0.9.5", "rlp", "ruint-macro", @@ -6593,9 +6646,9 @@ checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" [[package]] name = "rustls-webpki" -version = "0.103.14" +version = "0.103.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0527518605e68109d875e248ea259b6758801cf165e4b2c2733ae3b51f12535a" +checksum = "f3c3cf1d8b1e7d4927e2d154c3fcb02979afb9939629c62cd9048d4f07b60ac2" dependencies = [ "aws-lc-rs", "ring", @@ -6717,7 +6770,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b50c5943d326858130af85e049f2661ba3c78b26589b8ab98e65e80ae44a1252" dependencies = [ "bitcoin_hashes", - "rand 0.8.7", + "rand 0.8.8", "secp256k1-sys 0.10.1", "serde", ] @@ -6838,7 +6891,7 @@ checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" dependencies = [ "proc-macro2", "quote", - "syn 3.0.3", + "syn 3.0.4", ] [[package]] @@ -6847,7 +6900,7 @@ version = "1.0.151" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" dependencies = [ - "indexmap 2.14.0", + "indexmap 2.14.1", "itoa", "memchr", "serde", @@ -6874,7 +6927,7 @@ checksum = "8d3b1629de253c70a0508c3899572da79ca359fdab27c7920ff00406df418906" dependencies = [ "proc-macro2", "quote", - "syn 3.0.3", + "syn 3.0.4", ] [[package]] @@ -6909,7 +6962,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.14.0", + "indexmap 2.14.1", "jiff", "schemars 0.9.0", "schemars 1.2.2", @@ -6925,7 +6978,7 @@ version = "3.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8705578779c2b6bd90d84d66eb2e206b708b1a4d7b9f17641b293545bf1c7e46" dependencies = [ - "darling", + "darling 0.23.0", "proc-macro2", "quote", "syn 2.0.119", @@ -6937,7 +6990,7 @@ version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.14.0", + "indexmap 2.14.1", "itoa", "ryu", "serde", @@ -6982,7 +7035,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be176f1a57ce4e3d31c1a166222d9768de5954f811601fb7ca06fc8203905ce1" dependencies = [ "digest 0.11.3", - "keccak 0.2.1", + "keccak 0.2.2", ] [[package]] @@ -7066,9 +7119,9 @@ checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smallvec" -version = "1.15.2" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" +checksum = "b9be42f50aa861c555654aa3a37f52f4b1074bacf4e48fe0ef7fa584e80f1f0f" dependencies = [ "serde", ] @@ -7197,9 +7250,9 @@ dependencies = [ [[package]] name = "syn" -version = "3.0.3" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3" +checksum = "e6275cddf4610d1775e6d1fe9469b2e77d0f39fd98fb7450901b821e0c53649f" dependencies = [ "proc-macro2", "quote", @@ -7208,9 +7261,9 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "1.6.1" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "083be3061e64d362cbe6ef12cfe1307ba3884326d8856448fe8a120fa2c44ebf" +checksum = "e452eb8cb83fc8b81597eb07c8d39f770d04905af9c5bffce8bea7213df29960" dependencies = [ "paste", "proc-macro2", @@ -7410,7 +7463,7 @@ checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af" dependencies = [ "proc-macro2", "quote", - "syn 3.0.3", + "syn 3.0.4", ] [[package]] @@ -7521,7 +7574,7 @@ checksum = "78773a2a397f451582ce068015985c33193cf6dea8b74d2a639fe457b2f07b0e" dependencies = [ "proc-macro2", "quote", - "syn 3.0.3", + "syn 3.0.4", ] [[package]] @@ -7567,7 +7620,7 @@ version = "1.1.4+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3aace63f4bbcdfc2c965b059de67119c89c4017a70d633be6c104910f67056f5" dependencies = [ - "indexmap 2.14.0", + "indexmap 2.14.1", "serde_core", "serde_spanned", "toml_datetime", @@ -7591,7 +7644,7 @@ version = "0.25.13+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6975367e4d2ef766d86af01ffad14b622fecc8d4357a998fbc4deb6e9bacaf9b" dependencies = [ - "indexmap 2.14.0", + "indexmap 2.14.1", "toml_datetime", "toml_parser", "winnow", @@ -7660,7 +7713,7 @@ checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" dependencies = [ "futures-core", "futures-util", - "indexmap 2.14.0", + "indexmap 2.14.1", "pin-project-lite", "slab", "sync_wrapper", @@ -7812,7 +7865,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8840ad4d852e325d3afa7fde8a50b2412f89dce47d7eb291c0cc7f87cd040f38" dependencies = [ - "darling", + "darling 0.23.0", "proc-macro2", "quote", "syn 2.0.119", @@ -7985,9 +8038,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.24.1" +version = "1.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cefc03fd367c0c6d4305de1b312cf00248c4114f4a0418ce6a6af769e3b0bd9" +checksum = "b5772d71c9be8a8a6ac2117d949c5b224c1b72241bb611d9a3012edcf8af7812" dependencies = [ "getrandom 0.4.3", "js-sys", @@ -8017,7 +8070,7 @@ version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240e4b81c20a1d6d50d1d7265c658dfbd204e8b9ac4d80f3c931f39462196335" dependencies = [ - "darling", + "darling 0.23.0", "proc-macro-error3", "proc-macro2", "quote", @@ -8644,7 +8697,7 @@ dependencies = [ "nohash-hasher", "parking_lot", "pin-project", - "rand 0.8.7", + "rand 0.8.8", "static_assertions", ] @@ -8781,15 +8834,21 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.5" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f212a141d820099d57ffafb9569be9617a6f27d3dc881fbee8fb56642f917a9" +checksum = "34df6fc39dbd26ddc9c10e6a2984476e13acce22e64e4487636ef494369225da" dependencies = [ "proc-macro2", "quote", - "syn 3.0.3", + "syn 3.0.4", ] +[[package]] +name = "zlib-rs" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34b31d188d9d685a4f9c7b46d6e36631b07058d2cfe190267adce54dc230bf12" + [[package]] name = "zmij" version = "1.0.23"