From d517c4b63bebf78e225b8e5a665fcbb2c87bc0a9 Mon Sep 17 00:00:00 2001 From: Mathis Date: Wed, 5 Mar 2025 23:01:38 +0100 Subject: [PATCH 1/5] CI: switch away from buildjet runners temporarily (#2717) * CI: switch away from buildjet runners temporarily * bump todo_by! by one month * debug: trigger CI * update arm --------- Co-authored-by: Rob --- .github/workflows/benchmark-build.yaml | 3 ++- .github/workflows/build.yml | 5 +++-- .github/workflows/cargo-features.yml | 2 +- .github/workflows/test.yml | 6 +++--- README.md | 1 + sequencer/src/network/cdn.rs | 4 ++-- 6 files changed, 12 insertions(+), 9 deletions(-) diff --git a/.github/workflows/benchmark-build.yaml b/.github/workflows/benchmark-build.yaml index d6113acbcc..701614ec6e 100644 --- a/.github/workflows/benchmark-build.yaml +++ b/.github/workflows/benchmark-build.yaml @@ -65,7 +65,8 @@ jobs: target/release/espresso-bridge build-arm: - runs-on: buildjet-16vcpu-ubuntu-2204-arm + runs-on: + group: BigArmRunners steps: - name: Checkout Repository uses: actions/checkout@v4 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 60e36265d7..a17437d5f0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -24,7 +24,7 @@ env: jobs: build: - runs-on: buildjet-8vcpu-ubuntu-2204 + runs-on: ubuntu-latest steps: - uses: rui314/setup-mold@v1 @@ -86,7 +86,8 @@ jobs: build-arm: if: github.event_name != 'pull_request' - runs-on: buildjet-8vcpu-ubuntu-2204-arm + runs-on: + group: BigArmRunners env: CARGO_BUILD_JOBS: '6' steps: diff --git a/.github/workflows/cargo-features.yml b/.github/workflows/cargo-features.yml index 0561d93bea..2d6902cc83 100644 --- a/.github/workflows/cargo-features.yml +++ b/.github/workflows/cargo-features.yml @@ -19,7 +19,7 @@ concurrency: jobs: cargo-features: - runs-on: buildjet-8vcpu-ubuntu-2204 + runs-on: ubuntu-latest steps: - uses: taiki-e/install-action@cargo-hack diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 394b9fcc43..2ca6f34442 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -27,7 +27,7 @@ env: jobs: build-test-artifacts-postgres: name: Build test artifacts (postgres) - runs-on: buildjet-8vcpu-ubuntu-2204 + runs-on: ubuntu-latest steps: - uses: rui314/setup-mold@v1 @@ -61,7 +61,7 @@ jobs: build-test-artifacts-sqlite: name: Build test artifacts (sqlite) - runs-on: buildjet-8vcpu-ubuntu-2204 + runs-on: ubuntu-latest steps: - uses: rui314/setup-mold@v1 @@ -96,7 +96,7 @@ jobs: build-test-bins: name: Build test binaries - runs-on: buildjet-8vcpu-ubuntu-2204 + runs-on: ubuntu-latest steps: - uses: rui314/setup-mold@v1 diff --git a/README.md b/README.md index 4dbe498290..dc9f154e84 100644 --- a/README.md +++ b/README.md @@ -203,3 +203,4 @@ risk. **DISCLAIMER:** The Rust library crates provided in this repository are intended primarily for use by the binary targets in this repository. We make no guarantees of public API stability. If you are building on these crates, reach out by opening an issue to discuss the APIs you need. + diff --git a/sequencer/src/network/cdn.rs b/sequencer/src/network/cdn.rs index adce13a758..9a72df4af0 100644 --- a/sequencer/src/network/cdn.rs +++ b/sequencer/src/network/cdn.rs @@ -80,7 +80,7 @@ impl SignatureScheme for WrappedSignatureKey { }; todo_by!( - "2025-3-4", + "2025-4-4", "Only accept the namespaced message once everyone has upgraded" ); public_key.0.validate(&signature, message) @@ -112,7 +112,7 @@ impl RunDef for ProductionDef { } todo_by!( - "2025-3-4", + "2025-4-4", "Remove this, switching to TCP+TLS singularly when everyone has updated" ); /// The user definition for the Push CDN. From 5d6c9669d816988b96cd113894118447fbc09a37 Mon Sep 17 00:00:00 2001 From: Phil <184445976+pls148@users.noreply.github.com> Date: Thu, 6 Mar 2025 06:36:38 -0800 Subject: [PATCH 2/5] re-enable buildjet runners (#2721) * re-enable buildjet runners * CI: debug, trigger build again --------- Co-authored-by: sveitser --- .github/workflows/benchmark-build.yaml | 3 +-- .github/workflows/build.yml | 5 ++--- .github/workflows/cargo-features.yml | 2 +- .github/workflows/test.yml | 6 +++--- README.md | 1 - 5 files changed, 7 insertions(+), 10 deletions(-) diff --git a/.github/workflows/benchmark-build.yaml b/.github/workflows/benchmark-build.yaml index 701614ec6e..d6113acbcc 100644 --- a/.github/workflows/benchmark-build.yaml +++ b/.github/workflows/benchmark-build.yaml @@ -65,8 +65,7 @@ jobs: target/release/espresso-bridge build-arm: - runs-on: - group: BigArmRunners + runs-on: buildjet-16vcpu-ubuntu-2204-arm steps: - name: Checkout Repository uses: actions/checkout@v4 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a17437d5f0..60e36265d7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -24,7 +24,7 @@ env: jobs: build: - runs-on: ubuntu-latest + runs-on: buildjet-8vcpu-ubuntu-2204 steps: - uses: rui314/setup-mold@v1 @@ -86,8 +86,7 @@ jobs: build-arm: if: github.event_name != 'pull_request' - runs-on: - group: BigArmRunners + runs-on: buildjet-8vcpu-ubuntu-2204-arm env: CARGO_BUILD_JOBS: '6' steps: diff --git a/.github/workflows/cargo-features.yml b/.github/workflows/cargo-features.yml index 2d6902cc83..0561d93bea 100644 --- a/.github/workflows/cargo-features.yml +++ b/.github/workflows/cargo-features.yml @@ -19,7 +19,7 @@ concurrency: jobs: cargo-features: - runs-on: ubuntu-latest + runs-on: buildjet-8vcpu-ubuntu-2204 steps: - uses: taiki-e/install-action@cargo-hack diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2ca6f34442..394b9fcc43 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -27,7 +27,7 @@ env: jobs: build-test-artifacts-postgres: name: Build test artifacts (postgres) - runs-on: ubuntu-latest + runs-on: buildjet-8vcpu-ubuntu-2204 steps: - uses: rui314/setup-mold@v1 @@ -61,7 +61,7 @@ jobs: build-test-artifacts-sqlite: name: Build test artifacts (sqlite) - runs-on: ubuntu-latest + runs-on: buildjet-8vcpu-ubuntu-2204 steps: - uses: rui314/setup-mold@v1 @@ -96,7 +96,7 @@ jobs: build-test-bins: name: Build test binaries - runs-on: ubuntu-latest + runs-on: buildjet-8vcpu-ubuntu-2204 steps: - uses: rui314/setup-mold@v1 diff --git a/README.md b/README.md index dc9f154e84..4dbe498290 100644 --- a/README.md +++ b/README.md @@ -203,4 +203,3 @@ risk. **DISCLAIMER:** The Rust library crates provided in this repository are intended primarily for use by the binary targets in this repository. We make no guarantees of public API stability. If you are building on these crates, reach out by opening an issue to discuss the APIs you need. - From 1ed39cc0a835d34653ccbc36993e00548bbdf72f Mon Sep 17 00:00:00 2001 From: lukaszrzasik Date: Thu, 6 Mar 2025 15:36:52 +0100 Subject: [PATCH 3/5] Split eQC formed handling to unblock Consensus task (#2712) * Move Qc2Formed handling to QuorumProposalRecvTaskState to unblock ConsensusTaskState processing * Revert "Move Qc2Formed handling to QuorumProposalRecvTaskState to unblock ConsensusTaskState processing" This reverts commit 92aa3f330d7031927377645290a8e6af4baf43a7. * Split eQC formed handling to unblock Consensus task * Handle eQC formed after shared consensus state has been updated * Temporarily disable test_all_restart_epochs --------- Co-authored-by: Brendon Fish --- hotshot-task-impls/src/consensus/mod.rs | 40 ++------ hotshot-task-impls/src/events.rs | 6 ++ .../src/quorum_proposal/handlers.rs | 65 +++++++++++-- hotshot-task-impls/src/quorum_proposal/mod.rs | 13 +++ hotshot-testing/tests/tests_6/test_epochs.rs | 96 +++++++++---------- 5 files changed, 132 insertions(+), 88 deletions(-) diff --git a/hotshot-task-impls/src/consensus/mod.rs b/hotshot-task-impls/src/consensus/mod.rs index 484039f1b0..202e174152 100644 --- a/hotshot-task-impls/src/consensus/mod.rs +++ b/hotshot-task-impls/src/consensus/mod.rs @@ -7,7 +7,6 @@ use async_broadcast::{Receiver, Sender}; use async_lock::RwLock; use async_trait::async_trait; -use either::Either; use hotshot_task::task::TaskState; use hotshot_types::{ consensus::OuterConsensus, @@ -30,8 +29,11 @@ use tracing::instrument; use self::handlers::{ handle_quorum_vote_recv, handle_timeout, handle_timeout_vote_recv, handle_view_change, }; -use crate::helpers::{validate_qc_and_next_epoch_qc, wait_for_next_epoch_qc}; -use crate::{events::HotShotEvent, helpers::broadcast_event, vote_collection::VoteCollectorsMap}; +use crate::{ + events::HotShotEvent, + helpers::{broadcast_event, validate_qc_and_next_epoch_qc}, + vote_collection::VoteCollectorsMap, +}; /// Event handlers for use in the `handle` method. mod handlers; @@ -140,40 +142,14 @@ impl, V: Versions> ConsensusTaskSt tracing::debug!("Failed to handle Timeout event; error = {e}"); } } - HotShotEvent::Qc2Formed(Either::Left(quorum_cert)) => { - let cert_view = quorum_cert.view_number(); - if !self.upgrade_lock.epochs_enabled(cert_view).await { - tracing::debug!("QC2 formed but epochs not enabled. Do nothing"); - return Ok(()); - } - if !self - .consensus - .read() - .await - .is_leaf_extended(quorum_cert.data.leaf_commit) - { - tracing::debug!("We formed QC but not eQC. Do nothing"); - return Ok(()); - } - if wait_for_next_epoch_qc( - quorum_cert, - &self.consensus, - self.timeout, - self.view_start_time, - &receiver, - ) - .await - .is_none() - { - tracing::warn!("We formed eQC but we don't have corresponding next epoch eQC."); - return Ok(()); - } + HotShotEvent::ExtendedQc2Formed(eqc) => { + let cert_view = eqc.view_number(); let cert_block_number = self .consensus .read() .await .saved_leaves() - .get(&quorum_cert.data.leaf_commit) + .get(&eqc.data.leaf_commit) .context(error!( "Could not find the leaf for the eQC. It shouldn't happen." ))? diff --git a/hotshot-task-impls/src/events.rs b/hotshot-task-impls/src/events.rs index e34f856476..a1e828f27a 100644 --- a/hotshot-task-impls/src/events.rs +++ b/hotshot-task-impls/src/events.rs @@ -135,6 +135,8 @@ pub enum HotShotEvent { Qc2Formed(Either, TimeoutCertificate2>), /// The next leader has collected enough votes from the next epoch nodes to form a QC; emitted by the next leader in the consensus task; an internal event only NextEpochQc2Formed(Either, TimeoutCertificate>), + /// A validator formed both a current epoch eQC and a next epoch eQC + ExtendedQc2Formed(QuorumCertificate2), /// The DA leader has collected enough votes to form a DAC; emitted by the DA leader in the DA task; sent to the entire network via the networking task DacSend(DaCertificate2, TYPES::SignatureKey), /// The current view has changed; emitted by the replica in the consensus task or replica in the view sync task; received by almost all other tasks @@ -312,6 +314,7 @@ impl HotShotEvent { either::Left(qc) => Some(qc.view_number()), either::Right(tc) => Some(tc.view_number()), }, + HotShotEvent::ExtendedQc2Formed(cert) => Some(cert.view_number()), HotShotEvent::ViewSyncCommitVoteSend(vote) | HotShotEvent::ViewSyncCommitVoteRecv(vote) => Some(vote.view_number()), HotShotEvent::ViewSyncPreCommitVoteRecv(vote) @@ -447,6 +450,9 @@ impl Display for HotShotEvent { write!(f, "NextEpochQc2Formed(view_number={:?})", tc.view_number()) } }, + HotShotEvent::ExtendedQc2Formed(cert) => { + write!(f, "ExtendedQc2Formed(view_number={:?})", cert.view_number()) + } HotShotEvent::DacSend(cert, _) => { write!(f, "DacSend(view_number={:?})", cert.view_number()) } diff --git a/hotshot-task-impls/src/quorum_proposal/handlers.rs b/hotshot-task-impls/src/quorum_proposal/handlers.rs index c0796c26e0..fc5577c912 100644 --- a/hotshot-task-impls/src/quorum_proposal/handlers.rs +++ b/hotshot-task-impls/src/quorum_proposal/handlers.rs @@ -13,10 +13,15 @@ use std::{ time::{Duration, Instant}, }; +use crate::{ + events::HotShotEvent, + helpers::{broadcast_event, parent_leaf_and_state, wait_for_next_epoch_qc}, + quorum_proposal::{QuorumProposalTaskState, UpgradeLock, Versions}, +}; use anyhow::{ensure, Context, Result}; use async_broadcast::{Receiver, Sender}; use async_lock::RwLock; -use committable::Committable; +use committable::{Commitment, Committable}; use hotshot_task::dependency_task::HandleDepOutput; use hotshot_types::{ consensus::{CommitmentAndMetadata, OuterConsensus}, @@ -24,7 +29,9 @@ use hotshot_types::{ message::Proposal, simple_certificate::{QuorumCertificate2, UpgradeCertificate}, traits::{ - block_contents::BlockHeader, election::Membership, node_implementation::NodeType, + block_contents::BlockHeader, + election::Membership, + node_implementation::{NodeImplementation, NodeType}, signature_key::SignatureKey, }, utils::{is_last_block_in_epoch, option_epoch_from_block_number}, @@ -35,12 +42,6 @@ use hotshot_utils::anytrace::*; use tracing::instrument; use vbs::version::StaticVersionType; -use crate::{ - events::HotShotEvent, - helpers::{broadcast_event, parent_leaf_and_state, wait_for_next_epoch_qc}, - quorum_proposal::{UpgradeLock, Versions}, -}; - /// Proposal dependency types. These types represent events that precipitate a proposal. #[derive(PartialEq, Debug)] pub(crate) enum ProposalDependency { @@ -500,3 +501,51 @@ impl HandleDepOutput for ProposalDependencyHandle< } } } + +pub(super) async fn handle_eqc_formed< + TYPES: NodeType, + I: NodeImplementation, + V: Versions, +>( + cert_view: TYPES::View, + leaf_commit: Commitment>, + task_state: &QuorumProposalTaskState, + event_sender: &Sender>>, +) { + if !task_state.upgrade_lock.epochs_enabled(cert_view).await { + tracing::debug!("QC2 formed but epochs not enabled. Do nothing"); + return; + } + if !task_state + .consensus + .read() + .await + .is_leaf_extended(leaf_commit) + { + tracing::debug!("We formed QC but not eQC. Do nothing"); + return; + } + + let consensus_reader = task_state.consensus.read().await; + let current_epoch_qc = consensus_reader.high_qc(); + let Some(next_epoch_qc) = consensus_reader.next_epoch_high_qc() else { + tracing::debug!("We formed the eQC but we don't have the next epoch eQC at all."); + return; + }; + if current_epoch_qc.view_number() != next_epoch_qc.view_number() + || current_epoch_qc.data != *next_epoch_qc.data + { + tracing::debug!( + "We formed the eQC but the current and next epoch QCs do not correspond to each other." + ); + return; + } + let current_epoch_qc_clone = current_epoch_qc.clone(); + drop(consensus_reader); + + broadcast_event( + Arc::new(HotShotEvent::ExtendedQc2Formed(current_epoch_qc_clone)), + event_sender, + ) + .await; +} diff --git a/hotshot-task-impls/src/quorum_proposal/mod.rs b/hotshot-task-impls/src/quorum_proposal/mod.rs index c5bcc1bc00..bfbebe5a57 100644 --- a/hotshot-task-impls/src/quorum_proposal/mod.rs +++ b/hotshot-task-impls/src/quorum_proposal/mod.rs @@ -35,6 +35,7 @@ use tracing::instrument; use self::handlers::{ProposalDependency, ProposalDependencyHandle}; use crate::events::HotShotEvent; +use crate::quorum_proposal::handlers::handle_eqc_formed; mod handlers; @@ -437,6 +438,10 @@ impl, V: Versions> .await .wrap() .context(error!("Failed to update high QC in storage!"))?; + + handle_eqc_formed(qc.view_number(), qc.data.leaf_commit, self, &event_sender) + .await; + let view_number = qc.view_number() + 1; self.create_dependency_task_if_new( view_number, @@ -598,6 +603,14 @@ impl, V: Versions> .await .wrap() .context(error!("Failed to update next epoch high QC in storage!"))?; + + handle_eqc_formed( + next_epoch_qc.view_number(), + next_epoch_qc.data.leaf_commit, + self, + &event_sender, + ) + .await; } _ => {} } diff --git a/hotshot-testing/tests/tests_6/test_epochs.rs b/hotshot-testing/tests/tests_6/test_epochs.rs index 686ea8f6ab..718ab21310 100644 --- a/hotshot-testing/tests/tests_6/test_epochs.rs +++ b/hotshot-testing/tests/tests_6/test_epochs.rs @@ -491,54 +491,54 @@ cross_tests!( } ); -cross_tests!( - TestName: test_all_restart_epochs, - Impls: [CombinedImpl, PushCdnImpl], - Types: [TestTypes, TestTypesRandomizedLeader, TestTwoStakeTablesTypes], - Versions: [EpochsTestVersions], - Ignore: false, - Metadata: { - let timing_data = TimingData { - next_view_timeout: 2000, - ..Default::default() - }; - let mut metadata = TestDescription::default().set_num_nodes(20,20); - let mut catchup_nodes = vec![]; - - for i in 0..20 { - catchup_nodes.push(ChangeNode { - idx: i, - updown: NodeAction::RestartDown(0), - }) - } - - metadata.timing_data = timing_data; - - metadata.spinning_properties = SpinningTaskDescription { - // Restart all the nodes in view 10 - node_changes: vec![(10, catchup_nodes)], - }; - metadata.view_sync_properties = - hotshot_testing::view_sync_task::ViewSyncTaskDescription::Threshold(0, 20); - - metadata.completion_task_description = - CompletionTaskDescription::TimeBasedCompletionTaskBuilder( - TimeBasedCompletionTaskDescription { - duration: Duration::from_secs(60), - }, - ); - metadata.overall_safety_properties = OverallSafetyPropertiesDescription { - // Make sure we keep committing rounds after the catchup, but not the full 50. - num_successful_views: 22, - expected_view_failures: vec![10], - possible_view_failures: vec![9, 11], - decide_timeout: Duration::from_secs(20), - ..Default::default() - }; - - metadata - }, -); +// cross_tests!( +// TestName: test_all_restart_epochs, +// Impls: [CombinedImpl, PushCdnImpl], +// Types: [TestTypes, TestTypesRandomizedLeader, TestTwoStakeTablesTypes], +// Versions: [EpochsTestVersions], +// Ignore: false, +// Metadata: { +// let timing_data = TimingData { +// next_view_timeout: 2000, +// ..Default::default() +// }; +// let mut metadata = TestDescription::default().set_num_nodes(20,20); +// let mut catchup_nodes = vec![]; +// +// for i in 0..20 { +// catchup_nodes.push(ChangeNode { +// idx: i, +// updown: NodeAction::RestartDown(0), +// }) +// } +// +// metadata.timing_data = timing_data; +// +// metadata.spinning_properties = SpinningTaskDescription { +// // Restart all the nodes in view 10 +// node_changes: vec![(10, catchup_nodes)], +// }; +// metadata.view_sync_properties = +// hotshot_testing::view_sync_task::ViewSyncTaskDescription::Threshold(0, 20); +// +// metadata.completion_task_description = +// CompletionTaskDescription::TimeBasedCompletionTaskBuilder( +// TimeBasedCompletionTaskDescription { +// duration: Duration::from_secs(60), +// }, +// ); +// metadata.overall_safety_properties = OverallSafetyPropertiesDescription { +// // Make sure we keep committing rounds after the catchup, but not the full 50. +// num_successful_views: 22, +// expected_view_failures: vec![10], +// possible_view_failures: vec![9, 11], +// decide_timeout: Duration::from_secs(20), +// ..Default::default() +// }; +// +// metadata +// }, +// ); cross_tests!( TestName: test_all_restart_one_da_with_epochs, From a2f0fc7742170f0e9c88dd9d76b472bb3394ac3a Mon Sep 17 00:00:00 2001 From: rob-maron <132852777+rob-maron@users.noreply.github.com> Date: Thu, 6 Mar 2025 09:37:18 -0500 Subject: [PATCH 4/5] Implement request/response protocol (#2688) * implement r/r protocol * cargo sort * cargo sort _again_ * update lock, finish merge * Update sequencer/src/external_event_handler.rs Co-authored-by: Mathis * PR comments * PR comments pt2 * lints --------- Co-authored-by: Mathis --- Cargo.lock | 456 +++++++++--------- request-response/Cargo.toml | 1 - request-response/src/lib.rs | 85 ++-- request-response/src/recipient_source.rs | 4 +- request-response/src/request.rs | 12 + sequencer-sqlite/Cargo.lock | 22 + sequencer/Cargo.toml | 2 + sequencer/src/context.rs | 80 ++- sequencer/src/external_event_handler.rs | 167 +++---- sequencer/src/lib.rs | 3 +- sequencer/src/request_response/data_source.rs | 21 + sequencer/src/request_response/mod.rs | 4 + sequencer/src/request_response/network.rs | 41 ++ .../src/request_response/recipient_source.rs | 44 ++ sequencer/src/request_response/request.rs | 94 ++++ 15 files changed, 666 insertions(+), 370 deletions(-) create mode 100644 sequencer/src/request_response/data_source.rs create mode 100644 sequencer/src/request_response/mod.rs create mode 100644 sequencer/src/request_response/network.rs create mode 100644 sequencer/src/request_response/recipient_source.rs create mode 100644 sequencer/src/request_response/request.rs diff --git a/Cargo.lock b/Cargo.lock index 1964edd963..f026ffb8d4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -214,14 +214,14 @@ dependencies = [ "alloy-transport", "futures", "futures-util", - "thiserror 2.0.11", + "thiserror 2.0.12", ] [[package]] name = "alloy-core" -version = "0.8.21" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "482f377cebceed4bb1fb5e7970f0805e2ab123d06701be9351b67ed6341e74aa" +checksum = "45ef3546f382c07c7c2e1d24844ed593e1c9b272236aedf635e4a295fb3fc9d0" dependencies = [ "alloy-dyn-abi", "alloy-json-abi", @@ -231,9 +231,9 @@ dependencies = [ [[package]] name = "alloy-dyn-abi" -version = "0.8.21" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "555896f0b8578adb522b1453b6e6cc6704c3027bd0af20058befdde992cee8e9" +checksum = "00e08c581811006021970bf07f2ecf3213f6237c125f7fd99607004b23627b61" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -259,14 +259,14 @@ dependencies = [ [[package]] name = "alloy-eip7702" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cabf647eb4650c91a9d38cb6f972bb320009e7e9d61765fb688a86f1563b33e8" +checksum = "9b15b13d38b366d01e818fe8e710d4d702ef7499eacd44926a06171dd9585d0c" dependencies = [ "alloy-primitives", "alloy-rlp", - "derive_more 1.0.0", "serde", + "thiserror 2.0.12", ] [[package]] @@ -289,9 +289,9 @@ dependencies = [ [[package]] name = "alloy-json-abi" -version = "0.8.21" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4012581681b186ba0882007ed873987cc37f86b1b488fe6b91d5efd0b585dc41" +checksum = "125601804507fef5ae7debcbf800906b12741f19800c1c05b953d0f1b990131a" dependencies = [ "alloy-primitives", "alloy-sol-type-parser", @@ -309,7 +309,7 @@ dependencies = [ "alloy-sol-types", "serde", "serde_json", - "thiserror 2.0.11", + "thiserror 2.0.12", "tracing", ] @@ -335,7 +335,7 @@ dependencies = [ "futures-utils-wasm", "serde", "serde_json", - "thiserror 2.0.11", + "thiserror 2.0.12", ] [[package]] @@ -353,15 +353,15 @@ dependencies = [ [[package]] name = "alloy-primitives" -version = "0.8.21" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "478bedf4d24e71ea48428d1bc278553bd7c6ae07c30ca063beb0b09fe58a9e74" +checksum = "8c66bb6715b7499ea755bde4c96223ae8eb74e05c014ab38b9db602879ffb825" dependencies = [ "alloy-rlp", "bytes 1.10.0", "cfg-if", "const-hex", - "derive_more 1.0.0", + "derive_more 2.0.1", "foldhash", "hashbrown 0.15.2", "indexmap 2.7.1", @@ -410,7 +410,7 @@ dependencies = [ "schnellru", "serde", "serde_json", - "thiserror 2.0.11", + "thiserror 2.0.12", "tokio", "tracing", "url", @@ -455,7 +455,7 @@ checksum = "a40e1ef334153322fd878d07e86af7a529bcb86b2439525920a88eba87bcf943" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -523,7 +523,7 @@ dependencies = [ "itertools 0.13.0", "serde", "serde_json", - "thiserror 2.0.11", + "thiserror 2.0.12", ] [[package]] @@ -548,7 +548,7 @@ dependencies = [ "auto_impl", "elliptic-curve", "k256", - "thiserror 2.0.11", + "thiserror 2.0.12", ] [[package]] @@ -566,28 +566,28 @@ dependencies = [ "coins-bip39 0.12.0", "k256", "rand 0.8.5", - "thiserror 2.0.11", + "thiserror 2.0.12", ] [[package]] name = "alloy-sol-macro" -version = "0.8.21" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2708e27f58d747423ae21d31b7a6625159bd8d867470ddd0256f396a68efa11" +checksum = "c7f9c3c7bc1f4e334e5c5fc59ec8dac894973a71b11da09065affc6094025049" dependencies = [ "alloy-sol-macro-expander", "alloy-sol-macro-input", "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] name = "alloy-sol-macro-expander" -version = "0.8.21" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6b7984d7e085dec382d2c5ef022b533fcdb1fe6129200af30ebf5afddb6a361" +checksum = "46ff7aa715eb2404cb87fa94390d2c5d5addd70d9617e20b2398ee6f48cb21f0" dependencies = [ "alloy-json-abi", "alloy-sol-macro-input", @@ -597,16 +597,16 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", "syn-solidity", "tiny-keccak", ] [[package]] name = "alloy-sol-macro-input" -version = "0.8.21" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d6a9fc4ed1a3c70bdb2357bec3924551c1a59f24e5a04a74472c755b37f87d" +checksum = "6f105fa700140c0cc6e2c3377adef650c389ac57b8ead8318a2e6bd52f1ae841" dependencies = [ "alloy-json-abi", "const-hex", @@ -615,15 +615,15 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.98", + "syn 2.0.99", "syn-solidity", ] [[package]] name = "alloy-sol-type-parser" -version = "0.8.21" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1b3e9a48a6dd7bb052a111c8d93b5afc7956ed5e2cb4177793dc63bb1d2a36" +checksum = "c649acc6c9d3893e392c737faeadce30b4a1751eed148ae43bc2f27f29c4480c" dependencies = [ "serde", "winnow 0.7.3", @@ -631,9 +631,9 @@ dependencies = [ [[package]] name = "alloy-sol-types" -version = "0.8.21" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6044800da35c38118fd4b98e18306bd3b91af5dedeb54c1b768cf1b4fb68f549" +checksum = "5f819635439ebb06aa13c96beac9b2e7360c259e90f5160a6848ae0d94d10452" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -654,7 +654,7 @@ dependencies = [ "futures-utils-wasm", "serde", "serde_json", - "thiserror 2.0.11", + "thiserror 2.0.12", "tokio", "tower 0.5.2", "tracing", @@ -793,9 +793,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.96" +version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b964d184e89d9b6b67dd2715bc8e74cf3107fb2b529990c90cf517326150bf4" +checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" [[package]] name = "arbitrary" @@ -1201,7 +1201,7 @@ checksum = "965c2d33e53cb6b267e148a4cb0760bc01f4904c1cd4bb4002a085bb016d1490" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", "synstructure", ] @@ -1213,7 +1213,7 @@ checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -1498,7 +1498,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -1522,13 +1522,13 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.86" +version = "0.1.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "644dd749086bf3771a2fbc5f256fdb982d53f011c7d5d560304eafeecebce79d" +checksum = "d556ec1359574147ec0c4fc5eb525f3f23263a592b1a9c07e0a75b427de55c97" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -1627,7 +1627,7 @@ checksum = "e12882f59de5360c748c4cbf569a042d5fb0eb515f7bea9c1f470b47f6ffbd73" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -1638,13 +1638,13 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "automod" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edf3ee19dbc0a46d740f6f0926bde8c50f02bdbc7b536842da28f6ac56513a8b" +checksum = "ebb4bd301db2e2ca1f5be131c24eb8ebf2d9559bc3744419e93baf8ddea7e670" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -1811,7 +1811,7 @@ version = "0.69.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "cexpr", "clang-sys", "itertools 0.12.1", @@ -1822,7 +1822,7 @@ dependencies = [ "regex", "rustc-hash 1.1.0", "shlex", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -1831,7 +1831,7 @@ version = "0.71.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f58bf3d7db68cfbac37cfc485a8d711e87e064c3d0fe0435b92f7a407f9d6b3" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "cexpr", "clang-sys", "itertools 0.13.0", @@ -1842,7 +1842,7 @@ dependencies = [ "regex", "rustc-hash 2.1.1", "shlex", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -1883,9 +1883,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" +checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" dependencies = [ "serde", ] @@ -1914,16 +1914,15 @@ dependencies = [ [[package]] name = "blake3" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1230237285e3e10cde447185e8975408ae24deaa67205ce684805c25bc0c7937" +checksum = "675f87afced0413c9bb02843499dbbd3882a237645883f71a2b59644a6d2f753" dependencies = [ "arrayref", "arrayvec", "cc", "cfg-if", "constant_time_eq 0.3.1", - "memmap2", ] [[package]] @@ -2021,9 +2020,9 @@ checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" [[package]] name = "byte-slice-cast" -version = "1.2.2" +version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" +checksum = "7575182f7272186991736b70173b0ea045398f984bf5ebbb3804736ce1330c9d" [[package]] name = "bytecheck" @@ -2049,9 +2048,9 @@ dependencies = [ [[package]] name = "bytemuck" -version = "1.21.0" +version = "1.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3" +checksum = "b6b1fc10dbac614ebc03540c9dbd60e83887fda27794998c6528f1782047d540" dependencies = [ "bytemuck_derive", ] @@ -2064,7 +2063,7 @@ checksum = "3fa76293b4f7bb636ab88fd78228235b5248b4d05cc589aed610f954af5d7c7a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -2106,12 +2105,11 @@ dependencies = [ [[package]] name = "bzip2-sys" -version = "0.1.12+1.0.8" +version = "0.1.13+1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72ebc2f1a417f01e1da30ef264ee86ae31d2dcd2d603ea283d3c244a883ca2a9" +checksum = "225bff33b2141874fe80d71e07d6eec4f85c5c216453dd96388240f96e1acc14" dependencies = [ "cc", - "libc", "pkg-config", ] @@ -2141,9 +2139,9 @@ dependencies = [ [[package]] name = "capnp" -version = "0.20.3" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bce4e2d41c16cf9188f47ca4d59fdcdca1f33705af211bdb41f0afbd3442f8b5" +checksum = "0d1e413320159773070317b6678b180f7ebdcb4f8825d2bdec5b56e7ecc8d0dd" dependencies = [ "embedded-io", ] @@ -2216,9 +2214,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.15" +version = "1.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c736e259eea577f443d5c86c304f9f4ae0295c43f3ba05c21f1d66b5f06001af" +checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c" dependencies = [ "jobserver", "libc", @@ -2341,7 +2339,7 @@ dependencies = [ "sqlx", "thiserror 1.0.69", "tokio", - "tokio-rustls 0.26.1", + "tokio-rustls 0.26.2", "tracing", "url", "warp", @@ -2376,7 +2374,7 @@ dependencies = [ "sqlx", "thiserror 1.0.69", "tokio", - "tokio-rustls 0.26.1", + "tokio-rustls 0.26.2", "tracing", "url", "warp", @@ -2405,9 +2403,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chrono" -version = "0.4.39" +version = "0.4.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" +checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c" dependencies = [ "android-tzdata", "iana-time-zone", @@ -2415,7 +2413,7 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-targets 0.52.6", + "windows-link", ] [[package]] @@ -2512,7 +2510,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -3195,7 +3193,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -3216,7 +3214,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", "synstructure", ] @@ -3241,7 +3239,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -3252,7 +3250,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -3292,7 +3290,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "18e4fdb82bd54a12e42fb58a800dcae6b9e13982238ce2296dc3570b92148e1f" dependencies = [ "data-encoding", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -3303,7 +3301,7 @@ checksum = "297806318ef30ad066b15792a8372858020ae3ca2e414ee6c2133b1eb9e9e945" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -3360,7 +3358,7 @@ checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -3381,7 +3379,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -3391,7 +3389,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -3404,7 +3402,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version 0.4.1", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -3413,7 +3411,16 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" dependencies = [ - "derive_more-impl", + "derive_more-impl 1.0.0", +] + +[[package]] +name = "derive_more" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" +dependencies = [ + "derive_more-impl 2.0.1", ] [[package]] @@ -3425,7 +3432,19 @@ dependencies = [ "convert_case 0.6.0", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", + "unicode-xid", +] + +[[package]] +name = "derive_more-impl" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.99", "unicode-xid", ] @@ -3556,7 +3575,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -3728,7 +3747,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -3988,7 +4007,7 @@ dependencies = [ "reqwest 0.11.27", "serde", "serde_json", - "syn 2.0.98", + "syn 2.0.99", "toml 0.8.20", "walkdir", ] @@ -4006,7 +4025,7 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -4040,7 +4059,7 @@ dependencies = [ "serde", "serde_json", "strum 0.26.3", - "syn 2.0.98", + "syn 2.0.99", "tempfile", "thiserror 1.0.69", "tiny-keccak", @@ -4504,7 +4523,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -5327,7 +5346,7 @@ dependencies = [ "derive_builder", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", "workspace-hack", ] @@ -5721,9 +5740,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.10.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2d708df4e7140240a16cd6ab0ab65c972d7433ab77819ea693fde9c43811e2a" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" [[package]] name = "httpdate" @@ -5808,7 +5827,7 @@ dependencies = [ "rustls 0.23.23", "rustls-pki-types", "tokio", - "tokio-rustls 0.26.1", + "tokio-rustls 0.26.2", "tower-service", ] @@ -6030,7 +6049,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -6147,7 +6166,7 @@ checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -7202,7 +7221,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -7263,7 +7282,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "libc", ] @@ -7359,9 +7378,9 @@ checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "litemap" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" +checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856" [[package]] name = "local-ip-address" @@ -7631,7 +7650,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -7650,15 +7669,6 @@ version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" -[[package]] -name = "memmap2" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f" -dependencies = [ - "libc", -] - [[package]] name = "memoffset" version = "0.6.5" @@ -7896,7 +7906,7 @@ dependencies = [ "log", "netlink-packet-core", "netlink-sys", - "thiserror 2.0.11", + "thiserror 2.0.12", ] [[package]] @@ -8142,7 +8152,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -8232,7 +8242,7 @@ version = "0.10.71" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e14130c6a98cd258fdcb0fb6d744152343ff729cbfcb28c656a9d12b999fbcd" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "cfg-if", "foreign-types", "libc", @@ -8249,7 +8259,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -8326,7 +8336,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -8450,7 +8460,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b7cafe60d6cf8e62e1b9b2ea516a089c008945bb5a275416789e7db0bc199dc" dependencies = [ "memchr", - "thiserror 2.0.11", + "thiserror 2.0.12", "ucd-trie", ] @@ -8474,7 +8484,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -8538,7 +8548,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -8552,22 +8562,22 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.9" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfe2e71e1471fe07709406bf725f710b02927c9c54b2b5b2ec0e8087d97c327d" +checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.9" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6e859e6e5bd50440ab63c47e3ebabc90f26251f7c73c3d3e837b74a1cc3fa67" +checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -8628,9 +8638,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" [[package]] name = "plotters" @@ -8778,7 +8788,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6924ced06e1f7dfe3fa48d57b9f74f55d8915f5036121bef647ef4b204895fac" dependencies = [ "proc-macro2", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -8857,7 +8867,7 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -8868,9 +8878,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.93" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" +checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" dependencies = [ "unicode-ident", ] @@ -8910,7 +8920,7 @@ checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -8933,7 +8943,7 @@ checksum = "14cae93065090804185d3b75f0bf93b8eeda30c7a9b4a33d3bdb3988d6229e50" dependencies = [ "bit-set 0.8.0", "bit-vec 0.8.0", - "bitflags 2.8.0", + "bitflags 2.9.0", "lazy_static", "num-traits", "rand 0.8.5", @@ -8965,7 +8975,7 @@ dependencies = [ "itertools 0.12.1", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -9033,13 +9043,13 @@ dependencies = [ [[package]] name = "quick_cache" -version = "0.6.10" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f67cfc9c723c39f3615eb0840b00c4cb9e2b068d2fa761a30d845ec91730a59" +checksum = "0af25b4e960ffdf0dead61cf0cec0c2e44c76927bf933ab4f02e2858fb449397" dependencies = [ "ahash 0.8.11", "equivalent", - "hashbrown 0.14.5", + "hashbrown 0.15.2", "parking_lot", ] @@ -9057,7 +9067,7 @@ dependencies = [ "rustc-hash 2.1.1", "rustls 0.23.23", "socket2 0.5.8", - "thiserror 2.0.11", + "thiserror 2.0.12", "tokio", "tracing", ] @@ -9076,7 +9086,7 @@ dependencies = [ "rustls 0.23.23", "rustls-pki-types", "slab", - "thiserror 2.0.11", + "thiserror 2.0.12", "tinyvec", "tracing", "web-time", @@ -9098,9 +9108,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.38" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" +checksum = "c1f1914ce909e1658d9907913b4b91947430c7d9be598b15a1912935b8c04801" dependencies = [ "proc-macro2", ] @@ -9143,8 +9153,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" dependencies = [ "rand_chacha 0.9.0", - "rand_core 0.9.2", - "zerocopy 0.8.20", + "rand_core 0.9.3", + "zerocopy 0.8.21", ] [[package]] @@ -9174,7 +9184,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core 0.9.2", + "rand_core 0.9.3", ] [[package]] @@ -9197,12 +9207,11 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a509b1a2ffbe92afab0e55c8fd99dea1c280e8171bd2d88682bb20bc41cbc2c" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ "getrandom 0.3.1", - "zerocopy 0.8.20", ] [[package]] @@ -9305,11 +9314,11 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.9" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82b568323e98e49e2a0899dcee453dd679fae22d69adf9b11dd508d1549b7e2f" +checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", ] [[package]] @@ -9365,7 +9374,7 @@ dependencies = [ "quote", "refinery-core", "regex", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -9431,7 +9440,6 @@ dependencies = [ "bincode", "blake3", "byteorder", - "derive_builder", "derive_more 1.0.0", "hotshot-types", "parking_lot", @@ -9601,7 +9609,7 @@ dependencies = [ "rkyv_derive", "seahash", "tinyvec", - "uuid 1.14.0", + "uuid 1.15.1", ] [[package]] @@ -9644,7 +9652,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" dependencies = [ "base64 0.21.7", - "bitflags 2.8.0", + "bitflags 2.9.0", "serde", "serde_derive", ] @@ -9825,7 +9833,7 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "errno", "libc", "linux-raw-sys 0.4.15", @@ -9994,7 +10002,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -10087,7 +10095,7 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "core-foundation", "core-foundation-sys", "libc", @@ -10170,6 +10178,7 @@ dependencies = [ "async-once-cell", "async-trait", "bincode", + "byteorder", "cdn-broker 0.4.0 (git+https://github.com/EspressoSystems/Push-CDN?tag=0.5.1-upgrade)", "cdn-marshal 0.4.0 (git+https://github.com/EspressoSystems/Push-CDN?tag=0.5.1-upgrade)", "clap", @@ -10215,6 +10224,7 @@ dependencies = [ "rand 0.8.5", "rand_chacha 0.3.1", "rand_distr", + "request-response", "reqwest 0.12.12", "sequencer", "sequencer-utils", @@ -10291,14 +10301,14 @@ checksum = "59fb1bedd774187d304179493b0d3c41fbe97b04b14305363f68d2bdf5e47cb9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] name = "serde_bytes" -version = "0.11.15" +version = "0.11.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" +checksum = "364fec0df39c49a083c9a8a18a23a6bcfd9af130fe9fe321d18520a0d113e09e" dependencies = [ "serde", ] @@ -10311,7 +10321,7 @@ checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -10325,9 +10335,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.139" +version = "1.0.140" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44f86c3acccc9c65b153fe1b85a3be07fe5515274ec9f0653b4a0875731c72a6" +checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" dependencies = [ "itoa", "memchr", @@ -10394,7 +10404,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -10559,7 +10569,7 @@ checksum = "297f631f50729c8c99b84667867963997ec0b50f32b2a7dbcab828ef0541e8bb" dependencies = [ "num-bigint", "num-traits", - "thiserror 2.0.11", + "thiserror 2.0.12", "time 0.3.37", ] @@ -10659,7 +10669,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -10771,7 +10781,7 @@ dependencies = [ "serde_json", "sha2 0.10.8", "smallvec", - "thiserror 2.0.11", + "thiserror 2.0.12", "time 0.3.37", "tokio", "tokio-stream", @@ -10789,7 +10799,7 @@ dependencies = [ "quote", "sqlx-core", "sqlx-macros-core", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -10812,7 +10822,7 @@ dependencies = [ "sqlx-mysql", "sqlx-postgres", "sqlx-sqlite", - "syn 2.0.98", + "syn 2.0.99", "tempfile", "tokio", "url", @@ -10826,7 +10836,7 @@ checksum = "4560278f0e00ce64938540546f59f590d60beee33fffbd3b9cd47851e5fff233" dependencies = [ "atoi", "base64 0.22.1", - "bitflags 2.8.0", + "bitflags 2.9.0", "byteorder", "bytes 1.10.0", "crc", @@ -10855,7 +10865,7 @@ dependencies = [ "smallvec", "sqlx-core", "stringprep", - "thiserror 2.0.11", + "thiserror 2.0.12", "time 0.3.37", "tracing", "whoami", @@ -10870,7 +10880,7 @@ dependencies = [ "atoi", "base64 0.22.1", "bit-vec 0.6.3", - "bitflags 2.8.0", + "bitflags 2.9.0", "byteorder", "crc", "dotenvy", @@ -10894,7 +10904,7 @@ dependencies = [ "smallvec", "sqlx-core", "stringprep", - "thiserror 2.0.11", + "thiserror 2.0.12", "time 0.3.37", "tracing", "whoami", @@ -11051,7 +11061,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -11064,7 +11074,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -11226,9 +11236,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.98" +version = "2.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" +checksum = "e02e925281e18ffd9d640e234264753c43edc62d64b2d4cf898f1bc5e75f3fc2" dependencies = [ "proc-macro2", "quote", @@ -11237,14 +11247,14 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "0.8.21" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c2de690018098e367beeb793991c7d4dc7270f42c9d2ac4ccc876c1368ca430" +checksum = "ac9f9798a84bca5cd4d1760db691075fda8f2c3a5d9647e8bfd29eb9b3fabb87" dependencies = [ "paste", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -11270,7 +11280,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -11290,7 +11300,7 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "core-foundation", "system-configuration-sys 0.6.0", ] @@ -11399,11 +11409,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.11" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" dependencies = [ - "thiserror-impl 2.0.11", + "thiserror-impl 2.0.12", ] [[package]] @@ -11414,18 +11424,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] name = "thiserror-impl" -version = "2.0.11" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -11643,9 +11653,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "022db8904dfa342efe721985167e9fcd16c29b226db4397ed752a761cfce81e8" +checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" dependencies = [ "tinyvec_macros", ] @@ -11667,7 +11677,7 @@ dependencies = [ "proc-macro2", "quote", "semver 1.0.25", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -11706,7 +11716,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -11757,9 +11767,9 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.26.1" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37" +checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" dependencies = [ "rustls 0.23.23", "tokio", @@ -11803,7 +11813,7 @@ dependencies = [ "rustls 0.23.23", "rustls-pki-types", "tokio", - "tokio-rustls 0.26.1", + "tokio-rustls 0.26.2", "tungstenite 0.24.0", "webpki-roots 0.26.8", ] @@ -11976,7 +11986,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -12137,7 +12147,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04659ddb06c87d233c566112c1c9c5b9e98256d9af50ec3bc9c8327f873a7568" dependencies = [ "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -12148,7 +12158,7 @@ checksum = "70977707304198400eb4835a78f6a9f928bf41bba420deb8fdb175cd965d77a7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -12397,9 +12407,9 @@ dependencies = [ [[package]] name = "uuid" -version = "1.14.0" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93d59ca99a559661b96bf898d8fce28ed87935fd2bea9f05983c1464dd6c71b1" +checksum = "e0f540e3240398cce6128b64ba83fdbdd86129c16a3aa1a3a252efd66eb3d587" [[package]] name = "valuable" @@ -12640,7 +12650,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", "wasm-bindgen-shared", ] @@ -12675,7 +12685,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -12834,6 +12844,12 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-link" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dccfd733ce2b1753b03b6d3c65edf020262ea35e20ccdf3e288043e6dd620e3" + [[package]] name = "windows-registry" version = "0.2.0" @@ -13055,7 +13071,7 @@ version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", ] [[package]] @@ -13083,7 +13099,7 @@ dependencies = [ "crypto-common", "data-encoding", "derive_more 1.0.0", - "derive_more-impl", + "derive_more-impl 1.0.0", "digest 0.10.7", "digest 0.9.0", "displaydoc", @@ -13130,7 +13146,7 @@ dependencies = [ "smallvec", "standback", "subtle", - "syn 2.0.98", + "syn 2.0.99", "time 0.3.37", "tokio", "tokio-util", @@ -13271,7 +13287,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", "synstructure", ] @@ -13287,11 +13303,11 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.20" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dde3bb8c68a8f3f1ed4ac9221aad6b10cece3e60a8e2ea54a6a2dec806d0084c" +checksum = "dcf01143b2dd5d134f11f545cf9f1431b13b749695cb33bcce051e7568f99478" dependencies = [ - "zerocopy-derive 0.8.20", + "zerocopy-derive 0.8.21", ] [[package]] @@ -13302,38 +13318,38 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] name = "zerocopy-derive" -version = "0.8.20" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eea57037071898bf96a6da35fd626f4f27e9cee3ead2a6c703cf09d472b2e700" +checksum = "712c8386f4f4299382c9abee219bee7084f78fb939d88b6840fcc1320d5f6da2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] name = "zerofrom" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", "synstructure", ] @@ -13354,7 +13370,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -13376,7 +13392,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] diff --git a/request-response/Cargo.toml b/request-response/Cargo.toml index 4760053dff..3c45aec7e3 100644 --- a/request-response/Cargo.toml +++ b/request-response/Cargo.toml @@ -14,7 +14,6 @@ async-trait = { workspace = true } bincode = { workspace = true } blake3 = { workspace = true } byteorder = { version = "1", default-features = false } -derive_builder = { workspace = true } derive_more = { workspace = true } hotshot-types = { workspace = true } parking_lot = { workspace = true } diff --git a/request-response/src/lib.rs b/request-response/src/lib.rs index d643547ba6..d2cd58221b 100644 --- a/request-response/src/lib.rs +++ b/request-response/src/lib.rs @@ -10,7 +10,6 @@ use std::{ use anyhow::{anyhow, Context, Result}; use data_source::DataSource; -use derive_builder::Builder; use derive_more::derive::Deref; use hotshot_types::traits::signature_key::SignatureKey; use message::{Message, RequestMessage, ResponseMessage}; @@ -87,39 +86,39 @@ pub trait Serializable: Sized { } /// The underlying configuration for the request-response protocol -#[derive(Clone, Builder)] +#[derive(Clone)] pub struct RequestResponseConfig { /// The timeout for incoming requests. Do not respond to a request after this threshold /// has passed. - incoming_request_ttl: Duration, + pub incoming_request_ttl: Duration, /// The maximum amount of time we will spend trying to both derive a response for a request and /// send the response over the wire. - response_send_timeout: Duration, + pub response_send_timeout: Duration, /// The maximum amount of time we will spend trying to validate a response. This is used to prevent /// an attack where a malicious participant sends us a bunch of requests that take a long time to /// validate. - response_validate_timeout: Duration, + pub response_validate_timeout: Duration, /// The batch size for outgoing requests. This is the number of request messages that we will /// send out at a time for a single request before waiting for the [`request_batch_interval`]. - request_batch_size: usize, + pub request_batch_size: usize, /// The time to wait (per request) between sending out batches of request messages - request_batch_interval: Duration, + pub request_batch_interval: Duration, /// The maximum (global) number of outgoing responses that can be in flight at any given time - max_outgoing_responses: usize, + pub max_outgoing_responses: usize, /// The maximum (global) number of incoming responses that can be processed at any given time. /// We need this because responses coming in need to be validated [asynchronously] that they /// satisfy the request they are responding to - max_incoming_responses: usize, + pub max_incoming_responses: usize, } /// A protocol that allows for request-response communication. Is cheaply cloneable, so there is no /// need to wrap it in an `Arc` -#[derive(Clone, Deref)] +#[derive(Deref)] pub struct RequestResponse< S: Sender, R: Receiver, Req: Request, - RS: RecipientSource, + RS: RecipientSource, DS: DataSource, K: SignatureKey + 'static, > { @@ -130,11 +129,30 @@ pub struct RequestResponse< _receiving_task_handle: Arc>, } +/// We need to manually implement the `Clone` trait for this type because deriving +/// `Deref` will cause an issue where it tries to clone the inner field instead +impl< + S: Sender, + R: Receiver, + Req: Request, + RS: RecipientSource, + DS: DataSource, + K: SignatureKey + 'static, + > Clone for RequestResponse +{ + fn clone(&self) -> Self { + Self { + inner: Arc::clone(&self.inner), + _receiving_task_handle: Arc::clone(&self._receiving_task_handle), + } + } +} + impl< S: Sender, R: Receiver, Req: Request, - RS: RecipientSource, + RS: RecipientSource, DS: DataSource, K: SignatureKey + 'static, > RequestResponse @@ -186,14 +204,14 @@ pub struct RequestResponseInner< S: Sender, R: Receiver, Req: Request, - RS: RecipientSource, + RS: RecipientSource, DS: DataSource, K: SignatureKey + 'static, > { /// The configuration of the protocol config: RequestResponseConfig, /// The sender to use for the protocol - sender: S, + pub sender: S, /// The recipient source to use for the protocol recipient_source: RS, /// The data source to use for the protocol @@ -207,7 +225,7 @@ impl< S: Sender, R: Receiver, Req: Request, - RS: RecipientSource, + RS: RecipientSource, DS: DataSource, K: SignatureKey + 'static, > RequestResponseInner @@ -303,7 +321,7 @@ impl< // that we don't always send to the same recipients in the same order let mut recipients = self .recipient_source - .get_recipients_for(&request_message.request) + .get_expected_responders(&request_message.request) .await; recipients.shuffle(&mut rand::thread_rng()); @@ -617,8 +635,8 @@ mod tests { // Implement the [`RecipientSource`] trait for the [`TestSender`] type #[async_trait] - impl RecipientSource for TestSender { - async fn get_recipients_for(&self, _request: &R) -> Vec { + impl RecipientSource for TestSender { + async fn get_expected_responders(&self, _request: &TestRequest) -> Vec { // Get all the participants in the network self.network.keys().copied().collect() } @@ -671,14 +689,14 @@ mod tests { } #[async_trait] - impl DataSource> for TestDataSource { - async fn derive_response_for(&self, request: &Vec) -> Result> { + impl DataSource for TestDataSource { + async fn derive_response_for(&self, request: &TestRequest) -> Result> { // Return a response if we hit the hit rate if self.has_data && Instant::now() >= self.data_available_time { if self.take_data && !self.taken.swap(true, std::sync::atomic::Ordering::Relaxed) { return Err(anyhow::anyhow!("data already taken")); } - Ok(blake3::hash(request).as_bytes().to_vec()) + Ok(blake3::hash(&request.0).as_bytes().to_vec()) } else { Err(anyhow::anyhow!("did not have the data")) } @@ -687,16 +705,15 @@ mod tests { /// Create and return a default protocol configuration fn default_protocol_config() -> RequestResponseConfig { - RequestResponseConfigBuilder::create_empty() - .incoming_request_ttl(Duration::from_secs(40)) - .response_send_timeout(Duration::from_secs(40)) - .request_batch_size(10) - .request_batch_interval(Duration::from_millis(100)) - .max_outgoing_responses(10) - .response_validate_timeout(Duration::from_secs(1)) - .max_incoming_responses(5) - .build() - .expect("failed to build config") + RequestResponseConfig { + incoming_request_ttl: Duration::from_secs(40), + response_send_timeout: Duration::from_secs(40), + request_batch_size: 10, + request_batch_interval: Duration::from_millis(100), + max_outgoing_responses: 10, + response_validate_timeout: Duration::from_secs(1), + max_incoming_responses: 5, + } } /// Create fully connected test networks with `num_participants` participants @@ -805,10 +822,10 @@ mod tests { .push(Arc::clone(&protocol._receiving_task_handle)); // Create a random request - let request = vec![rand::thread_rng().gen(); 100]; + let request = TestRequest(vec![rand::thread_rng().gen(); 100]); // Get the hash of the request - let request_hash = blake3::hash(&request).as_bytes().to_vec(); + let request_hash = blake3::hash(&request.0).as_bytes().to_vec(); // Create a new request message let request = RequestMessage::new_signed(&public_key, &private_key, &request) @@ -924,7 +941,7 @@ mod tests { let one = Arc::new(participants.remove(0)); // Create the request that they should all be able to join on - let request = vec![rand::thread_rng().gen(); 100]; + let request = TestRequest(vec![rand::thread_rng().gen(); 100]); // Create a join set to wait for all the tasks to finish let mut join_set = JoinSet::new(); diff --git a/request-response/src/recipient_source.rs b/request-response/src/recipient_source.rs index 49da07a2a2..bfc65d1348 100644 --- a/request-response/src/recipient_source.rs +++ b/request-response/src/recipient_source.rs @@ -7,7 +7,7 @@ use super::request::Request; /// expect responses from. In `HotShot` this would go on top of the [`Membership`] trait and determine /// which nodes are able (quorum/DA) to respond to which requests #[async_trait] -pub trait RecipientSource: Send + Sync + 'static { +pub trait RecipientSource: Send + Sync + 'static { /// Get all the recipients that the specific request should expect responses from - async fn get_recipients_for(&self, request: &R) -> Vec; + async fn get_expected_responders(&self, request: &R) -> Vec; } diff --git a/request-response/src/request.rs b/request-response/src/request.rs index 87bc466452..5d7589e8d5 100644 --- a/request-response/src/request.rs +++ b/request-response/src/request.rs @@ -24,6 +24,18 @@ pub trait Request: Send + Sync + Serializable + 'static + Clone + Debug { /// A trait that a response needs to implement #[async_trait] +#[cfg(not(test))] +pub trait Response: Send + Sync + Serializable + Clone + Debug { + /// Validate the response, making sure it is valid for the given request + /// + /// # Errors + /// If the response is not valid for the given request + async fn validate(&self, request: &R) -> Result<()>; +} + +/// A trait that a response needs to implement +#[async_trait] +#[cfg(test)] pub trait Response: Send + Sync + Serializable + Clone + Debug + PartialEq + Eq { diff --git a/sequencer-sqlite/Cargo.lock b/sequencer-sqlite/Cargo.lock index c0707fca30..1d9cb79e6d 100644 --- a/sequencer-sqlite/Cargo.lock +++ b/sequencer-sqlite/Cargo.lock @@ -8726,6 +8726,26 @@ dependencies = [ "bytecheck", ] +[[package]] +name = "request-response" +version = "0.1.0" +dependencies = [ + "anyhow", + "async-broadcast", + "async-trait", + "bincode", + "blake3", + "byteorder", + "derive_more 1.0.0", + "hotshot-types", + "parking_lot", + "rand 0.8.5", + "thiserror 1.0.69", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "reqwest" version = "0.11.27" @@ -9453,6 +9473,7 @@ dependencies = [ "async-once-cell", "async-trait", "bincode", + "byteorder", "cdn-broker 0.4.0 (git+https://github.com/EspressoSystems/Push-CDN?tag=0.5.1-upgrade)", "cdn-marshal 0.4.0 (git+https://github.com/EspressoSystems/Push-CDN?tag=0.5.1-upgrade)", "clap", @@ -9492,6 +9513,7 @@ dependencies = [ "rand 0.8.5", "rand_chacha 0.3.1", "rand_distr", + "request-response", "sequencer-utils", "serde", "serde_json", diff --git a/sequencer/Cargo.toml b/sequencer/Cargo.toml index 0bca424833..1c5d9b5347 100644 --- a/sequencer/Cargo.toml +++ b/sequencer/Cargo.toml @@ -52,6 +52,7 @@ async-lock = { workspace = true } async-once-cell = { workspace = true } async-trait = { workspace = true } bincode = { workspace = true } +byteorder = "1" # CDN imports cdn-broker = { git = "https://github.com/EspressoSystems/Push-CDN", tag = "0.5.1-upgrade", package = "cdn-broker", features = ["global-permits"] } @@ -101,6 +102,7 @@ priority-queue = { workspace = true } rand = { workspace = true } rand_chacha = { workspace = true } rand_distr = { workspace = true } +request-response = { path = "../request-response" } sequencer-utils = { path = "../utils" } serde = { workspace = true } serde_json = { workspace = true } diff --git a/sequencer/src/context.rs b/sequencer/src/context.rs index b56c0b6eb0..9b69947f73 100644 --- a/sequencer/src/context.rs +++ b/sequencer/src/context.rs @@ -27,15 +27,24 @@ use hotshot_types::{ PeerConfig, ValidatorConfig, }; use parking_lot::Mutex; -use std::fmt::Debug; +use request_response::{network::Bytes, RequestResponse, RequestResponseConfig}; +use std::{fmt::Debug, time::Duration}; use std::{fmt::Display, sync::Arc}; -use tokio::{spawn, task::JoinHandle}; +use tokio::{ + spawn, + sync::mpsc::{channel, Receiver}, + task::JoinHandle, +}; use tracing::{Instrument, Level}; use url::Url; use crate::{ - external_event_handler::{self, ExternalEventHandler}, + external_event_handler::ExternalEventHandler, proposal_fetcher::ProposalFetcherConfig, + request_response::{ + data_source::DataSource, network::Sender as RequestResponseSender, + recipient_source::RecipientSource, request::Request, + }, state_signature::StateSigner, static_stake_table_commitment, Node, SeqTypes, SequencerApiVersion, }; @@ -51,6 +60,18 @@ pub struct SequencerContext, P: SequencerPersistence #[derivative(Debug = "ignore")] handle: Arc>>, + /// The request-response protocol + #[derivative(Debug = "ignore")] + #[allow(dead_code)] + request_response_protocol: RequestResponse< + RequestResponseSender, + Receiver, + Request, + RecipientSource, + DataSource, + PubKey, + >, + /// Context for generating state signatures. state_signer: Arc>, @@ -87,7 +108,6 @@ impl, P: SequencerPersistence, V: Versions> Sequence state_relay_server: Option, metrics: &dyn Metrics, stake_table_capacity: u64, - public_api_url: Option, event_consumer: impl PersistenceEventConsumer + 'static, _: V, marketplace_config: MarketplaceConfig>, @@ -124,13 +144,14 @@ impl, P: SequencerPersistence, V: Versions> Sequence ))); let persistence = Arc::new(persistence); + let memberships = Arc::new(async_lock::RwLock::new(membership)); let handle = SystemContext::init( validator_config.public_key, validator_config.private_key.clone(), instance_state.node_id, config.clone(), - Arc::new(async_lock::RwLock::new(membership)), + memberships.clone(), network.clone(), initializer, ConsensusMetricsValue::new(metrics), @@ -145,21 +166,49 @@ impl, P: SequencerPersistence, V: Versions> Sequence state_signer = state_signer.with_relay_server(url); } - // Create the roll call info we will be using - let roll_call_info = external_event_handler::RollCallInfo { public_api_url }; + // Create the channel for sending outbound messages from the external event handler + let (outbound_message_sender, outbound_message_receiver) = channel(10); + let (request_response_sender, request_response_receiver) = channel(10); + + // Configure the request-response protocol + let request_response_config = RequestResponseConfig { + incoming_request_ttl: Duration::from_secs(40), + response_send_timeout: Duration::from_secs(5), + request_batch_size: 10, + request_batch_interval: Duration::from_secs(3), + max_outgoing_responses: 10, + response_validate_timeout: Duration::from_secs(1), + max_incoming_responses: 5, + }; + + // Create the request-response protocol + let request_response_protocol = RequestResponse::new( + request_response_config, + RequestResponseSender::new(outbound_message_sender), + request_response_receiver, + RecipientSource { memberships }, + DataSource {}, + ); // Create the external event handler let mut tasks = TaskList::default(); - let external_event_handler = - ExternalEventHandler::new(&mut tasks, network, roll_call_info, pub_key) - .await - .with_context(|| "Failed to create external event handler")?; + let external_event_handler = ExternalEventHandler::::new( + &mut tasks, + request_response_sender, + outbound_message_receiver, + network, + pub_key, + handle.hotshot.upgrade_lock.clone(), + ) + .await + .with_context(|| "Failed to create external event handler")?; Ok(Self::new( handle, persistence, state_signer, external_event_handler, + request_response_protocol, event_streamer, instance_state, network_config, @@ -179,6 +228,14 @@ impl, P: SequencerPersistence, V: Versions> Sequence persistence: Arc

, state_signer: StateSigner, external_event_handler: ExternalEventHandler, + request_response_protocol: RequestResponse< + RequestResponseSender, + Receiver, + Request, + RecipientSource, + DataSource, + PubKey, + >, event_streamer: Arc>>, node_state: NodeState, network_config: NetworkConfig, @@ -194,6 +251,7 @@ impl, P: SequencerPersistence, V: Versions> Sequence let mut ctx = Self { handle: Arc::new(RwLock::new(handle)), state_signer: Arc::new(state_signer), + request_response_protocol, tasks: Default::default(), detached: false, wait_for_orchestrator: None, diff --git a/sequencer/src/external_event_handler.rs b/sequencer/src/external_event_handler.rs index bcf5f9e23d..86659f946f 100644 --- a/sequencer/src/external_event_handler.rs +++ b/sequencer/src/external_event_handler.rs @@ -3,94 +3,67 @@ use crate::context::TaskList; use anyhow::{Context, Result}; use espresso_types::{PubKey, SeqTypes}; -use hotshot::types::{BLSPubKey, Message}; +use hotshot::types::Message; use hotshot_types::{ - message::MessageKind, + message::{MessageKind, UpgradeLock}, traits::{ network::{BroadcastDelay, ConnectedNetwork, Topic}, node_implementation::Versions, }, }; +use request_response::network::Bytes; use serde::{Deserialize, Serialize}; use std::{marker::PhantomData, sync::Arc}; -use tokio::sync::mpsc::channel; use tokio::sync::mpsc::{Receiver, Sender}; -use url::Url; /// An external message that can be sent to or received from a node #[derive(Debug, Serialize, Deserialize, Clone)] pub enum ExternalMessage { - /// A request for a node to respond with its identifier - /// Contains the public key of the node that is requesting the roll call - RollCallRequest(BLSPubKey), - - /// A response to a roll call request - /// Contains the identifier of the node - RollCallResponse(RollCallInfo), -} - -/// Information about a node that is used in a roll call response -#[derive(Debug, Serialize, Deserialize, Clone)] -pub struct RollCallInfo { - // The public API URL of the node - pub public_api_url: Option, + RequestResponse(Vec), } -/// The external event handler state +/// The external event handler +#[derive(Clone)] pub struct ExternalEventHandler { - // The `RollCallInfo` of the node (used in the roll call response) - pub roll_call_info: RollCallInfo, + /// The sender to the request-response protocol + request_response_sender: Sender, - // The public key of the node - pub public_key: BLSPubKey, - - // The outbound message queue - pub outbound_message_sender: Sender, - - _pd: PhantomData, + /// The type phantom + phantom: PhantomData, } // The different types of outbound messages (broadcast or direct) #[derive(Debug)] +#[allow(dead_code)] pub enum OutboundMessage { - Direct(Vec, PubKey), - Broadcast(Vec), + Direct(MessageKind, PubKey), + Broadcast(MessageKind), } impl ExternalEventHandler { - /// Creates a new `ExternalEventHandler` with the given network and roll call info + /// Creates a new `ExternalEventHandler` with the given network pub async fn new>( tasks: &mut TaskList, + request_response_sender: Sender, + outbound_message_receiver: Receiver, network: Arc, - roll_call_info: RollCallInfo, - public_key: BLSPubKey, + public_key: PubKey, + hotshot_upgrade_lock: UpgradeLock, ) -> Result { - // Create the outbound message queue - let (outbound_message_sender, outbound_message_receiver) = channel(10); - // Spawn the outbound message handling loop tasks.spawn( - "ExternalEventHandler (RollCall)", - Self::outbound_message_loop(outbound_message_receiver, network), + "ExternalEventHandler", + Self::outbound_message_loop( + outbound_message_receiver, + network, + public_key, + hotshot_upgrade_lock, + ), ); - // We just started, so queue an outbound RollCall message (if we have a public API URL) - if roll_call_info.public_api_url.is_some() { - let roll_call_message_bytes = - Self::create_roll_call_response(&public_key, &roll_call_info) - .await - .with_context(|| "Failed to create roll call response for initial broadcast")?; - - outbound_message_sender - .try_send(OutboundMessage::Broadcast(roll_call_message_bytes)) - .with_context(|| "External outbound message queue is somehow full")?; - } - Ok(Self { - roll_call_info, - public_key, - outbound_message_sender, - _pd: Default::default(), + request_response_sender, + phantom: PhantomData, }) } @@ -105,73 +78,67 @@ impl ExternalEventHandler { // Match the type match external_message { - ExternalMessage::RollCallRequest(pub_key) => { - if self.roll_call_info.public_api_url.is_none() { - // We don't have a public API URL, so we can't respond to the roll call - return Ok(()); - } - - let response_bytes = - Self::create_roll_call_response(&self.public_key, &self.roll_call_info) - .await - .with_context(|| { - "Failed to serialize roll call response for RollCallRequest" - })?; - - // Send the response - self.outbound_message_sender - .try_send(OutboundMessage::Direct(response_bytes, pub_key)) - .with_context(|| "External outbound message queue is full")?; - } - - _ => { - return Err(anyhow::anyhow!("Unknown external message type")); + ExternalMessage::RequestResponse(request_response) => { + // Send the inner message to the request-response protocol + self.request_response_sender + .send(request_response.into()) + .await?; } } Ok(()) } - /// Creates a roll call response message - async fn create_roll_call_response( - public_key: &BLSPubKey, - roll_call_info: &RollCallInfo, - ) -> Result> { - let response = ExternalMessage::RollCallResponse(roll_call_info.clone()); - - // Serialize the response - let response_bytes = bincode::serialize(&response) - .with_context(|| "Failed to serialize roll call response")?; - - let message = Message:: { - sender: *public_key, - kind: MessageKind::::External(response_bytes), - }; - - let response_bytes = bincode::serialize(&message) - .with_context(|| "Failed to serialize roll call response")?; - - Ok(response_bytes) - } - /// The main loop for sending outbound messages. async fn outbound_message_loop>( mut receiver: Receiver, network: Arc, + public_key: PubKey, + hotshot_upgrade_lock: UpgradeLock, ) { while let Some(message) = receiver.recv().await { // Match the message type match message { OutboundMessage::Direct(message, recipient) => { - // Send the message directly to the recipient - if let Err(err) = network.direct_message(message, recipient).await { + // Wrap it in the real message type + let message_inner = Message { + sender: public_key, + kind: message, + }; + + // Serialize it + let message_bytes = match hotshot_upgrade_lock.serialize(&message_inner).await { + Ok(message_bytes) => message_bytes, + Err(err) => { + tracing::warn!("Failed to serialize direct message: {}", err); + continue; + } + }; + + // Send the message to the recipient + if let Err(err) = network.direct_message(message_bytes, recipient).await { tracing::error!("Failed to send message: {:?}", err); }; } OutboundMessage::Broadcast(message) => { + // Wrap it in the real message type + let message_inner = Message { + sender: public_key, + kind: message, + }; + + // Serialize it + let message_bytes = match hotshot_upgrade_lock.serialize(&message_inner).await { + Ok(message_bytes) => message_bytes, + Err(err) => { + tracing::warn!("Failed to serialize broadcast message: {}", err); + continue; + } + }; + // Broadcast the message to the global topic if let Err(err) = network - .broadcast_message(message, Topic::Global, BroadcastDelay::None) + .broadcast_message(message_bytes, Topic::Global, BroadcastDelay::None) .await { tracing::error!("Failed to broadcast message: {:?}", err); diff --git a/sequencer/src/lib.rs b/sequencer/src/lib.rs index 72f6566bc3..8f165ec825 100644 --- a/sequencer/src/lib.rs +++ b/sequencer/src/lib.rs @@ -3,6 +3,7 @@ pub mod catchup; pub mod context; pub mod genesis; mod proposal_fetcher; +mod request_response; mod external_event_handler; pub mod options; @@ -542,7 +543,6 @@ pub async fn init_node( Some(network_params.state_relay_server_url), metrics, genesis.stake_table.capacity, - network_params.public_api_url, event_consumer, seq_versions, marketplace_config, @@ -1006,7 +1006,6 @@ pub mod testing { self.state_relay_url.clone(), metrics, stake_table_capacity, - None, // The public API URL event_consumer, bind_version, MarketplaceConfig::> { diff --git a/sequencer/src/request_response/data_source.rs b/sequencer/src/request_response/data_source.rs new file mode 100644 index 0000000000..df7476677e --- /dev/null +++ b/sequencer/src/request_response/data_source.rs @@ -0,0 +1,21 @@ +//! This file contains the [`DataSource`] trait. This trait allows the [`RequestResponseProtocol`] +//! to calculate/derive a response for a specific request. In the confirmation layer the implementer +//! would be something like a [`FeeMerkleTree`] for fee catchup + +use super::request::{Request, Response}; +use anyhow::Result; +use async_trait::async_trait; +use request_response::data_source::DataSource as DataSourceTrait; + +#[derive(Clone, Debug)] +pub struct DataSource {} + +/// Implement the trait that allows the [`RequestResponseProtocol`] to calculate/derive a response for a specific request +#[async_trait] +impl DataSourceTrait for DataSource { + async fn derive_response_for(&self, request: &Request) -> Result { + match request { + Request::Example => Ok(Response::Example), + } + } +} diff --git a/sequencer/src/request_response/mod.rs b/sequencer/src/request_response/mod.rs new file mode 100644 index 0000000000..fb75070a97 --- /dev/null +++ b/sequencer/src/request_response/mod.rs @@ -0,0 +1,4 @@ +pub mod data_source; +pub mod network; +pub mod recipient_source; +pub mod request; diff --git a/sequencer/src/request_response/network.rs b/sequencer/src/request_response/network.rs new file mode 100644 index 0000000000..38a80b2621 --- /dev/null +++ b/sequencer/src/request_response/network.rs @@ -0,0 +1,41 @@ +use crate::external_event_handler::ExternalMessage; +use crate::external_event_handler::OutboundMessage; +use anyhow::{Context, Result}; +use async_trait::async_trait; +use espresso_types::PubKey; +use espresso_types::SeqTypes; +use hotshot_types::message::MessageKind; +use request_response::network::Bytes; +use request_response::network::Sender as SenderTrait; +use tokio::sync::mpsc; + +/// A wrapper type that we will implement the `Sender` trait for +#[derive(Clone)] +pub struct Sender(mpsc::Sender); + +impl Sender { + pub fn new(sender: mpsc::Sender) -> Self { + Self(sender) + } +} + +/// Implement the `Sender` trait for the `RequestResponseSender` type. This tells +/// the request response protocol how to send messages to other nodes. +#[async_trait] +impl SenderTrait for Sender { + async fn send_message(&self, message: &Bytes, recipient: PubKey) -> Result<()> { + // Serialize the inner message + let message_bytes = bincode::serialize(&ExternalMessage::RequestResponse(message.to_vec())) + .with_context(|| "failed to serialize message")?; + + // Send the message + self.0 + .send(OutboundMessage::Direct( + MessageKind::External::(message_bytes), + recipient, + )) + .await + .with_context(|| "failed to send message over channel")?; + Ok(()) + } +} diff --git a/sequencer/src/request_response/recipient_source.rs b/sequencer/src/request_response/recipient_source.rs new file mode 100644 index 0000000000..a0dcbbd69d --- /dev/null +++ b/sequencer/src/request_response/recipient_source.rs @@ -0,0 +1,44 @@ +use std::sync::Arc; + +use async_lock::RwLock; +use async_trait::async_trait; +use espresso_types::{PubKey, SeqTypes}; +use hotshot_types::{ + data::EpochNumber, + traits::{ + election::Membership, + node_implementation::{ConsensusTime, NodeType}, + }, +}; +use request_response::recipient_source::RecipientSource as RecipientSourceTrait; + +use super::request::Request; + +#[derive(Clone, Debug)] +pub struct RecipientSource { + pub memberships: Arc::Membership>>, +} + +/// Implement the RecipientSourceTrait, which allows the request-response protocol to derive the +/// intended recipients for a given request +#[async_trait] +impl RecipientSourceTrait for RecipientSource { + async fn get_expected_responders(&self, request: &Request) -> Vec { + match request { + Request::Example => { + // Get the memberships + let memberships = self.memberships.read().await; + + // Get everyone in the stake table + + // NOTE: This is just an example request, therefore this is hardcoded to get members of epoch 0. + // When doing a real request, please choose the appropriate epoch to get members from. + memberships + .stake_table(Some(EpochNumber::new(0))) + .iter() + .map(|entry| entry.stake_table_entry.stake_key) + .collect() + } + } + } +} diff --git a/sequencer/src/request_response/request.rs b/sequencer/src/request_response/request.rs new file mode 100644 index 0000000000..ebb463a8ce --- /dev/null +++ b/sequencer/src/request_response/request.rs @@ -0,0 +1,94 @@ +use std::io::Cursor; + +use anyhow::{Context, Result}; +use async_trait::async_trait; +use byteorder::ReadBytesExt; +use request_response::{ + request::{Request as RequestTrait, Response as ResponseTrait}, + Serializable, +}; + +/// The outermost request type. This an enum that contains all the possible requests that the +/// sequencer can make. +#[derive(Debug, Clone)] +pub enum Request { + Example, +} + +/// Implement the `RequestTrait` trait for the `Request` type. This tells the request response +/// protocol how to validate the request and what the response type is. +#[async_trait] +impl RequestTrait for Request { + type Response = Response; + + async fn validate(&self) -> Result<()> { + Ok(()) + } +} + +/// The outermost response type. This an enum that contains all the possible responses that the +/// sequencer can make. +#[derive(Debug, Clone)] +pub enum Response { + Example, +} + +/// Implement the `ResponseTrait` trait for the `Response` type. This tells the request response +/// protocol how to validate the response and what the request type is. +#[async_trait] +impl ResponseTrait for Response { + async fn validate(&self, request: &Request) -> Result<()> { + // Match the type of the response and request + match (self, request) { + (Response::Example, Request::Example) => Ok(()), + } + } +} + +/// Implement the `Serializable` trait for the `Request` type. This tells the request response +/// protocol how to serialize and deserialize the request +impl Serializable for Request { + fn to_bytes(&self) -> Result> { + match self { + Request::Example => Ok(vec![0]), + } + } + + fn from_bytes(bytes: &[u8]) -> Result { + // Create a cursor so we can read the bytes in order + let mut cursor = Cursor::new(bytes); + + // Read the first byte, the request type + let request_type = cursor.read_u8().with_context(|| "invalid request type")?; + + // Deserialize the request based on the type + match request_type { + 0 => Ok(Request::Example), + _ => Err(anyhow::anyhow!("invalid request type")), + } + } +} + +/// Implement the `Serializable` trait for the `Response` type. This tells the request response +/// protocol how to serialize and deserialize the response. +impl Serializable for Response { + fn to_bytes(&self) -> Result> { + match self { + Response::Example => Ok(vec![0]), + } + } + + fn from_bytes(bytes: &[u8]) -> Result { + // Create a cursor so we can read the bytes in order + let mut cursor = Cursor::new(bytes); + + // Read the first byte, the response type + let response_type = cursor.read_u8().with_context(|| "invalid response type")?; + + // Deserialize the response based on the type + match response_type { + 0 => Ok(Response::Example), + _ => Err(anyhow::anyhow!("invalid response type")), + } + } +} From 1d535dab996bf08bb6c464560d9b904f2295752c Mon Sep 17 00:00:00 2001 From: Abdul Basit <45506001+imabdulbasit@users.noreply.github.com> Date: Thu, 6 Mar 2025 20:00:37 +0500 Subject: [PATCH 5/5] Prevent overwriting existing payload with empty Payload (#2716) * do not overwrite existing payload with empty payload * lint * add comments --- .../src/data_source/storage/sql/transaction.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/hotshot-query-service/src/data_source/storage/sql/transaction.rs b/hotshot-query-service/src/data_source/storage/sql/transaction.rs index efeea128e6..105df2586a 100644 --- a/hotshot-query-service/src/data_source/storage/sql/transaction.rs +++ b/hotshot-query-service/src/data_source/storage/sql/transaction.rs @@ -496,8 +496,13 @@ where // Similarly, we can initialize the payload table with a null payload, which can help us // distinguish between blocks that haven't been produced yet and blocks we haven't received // yet when answering queries. - self.upsert("payload", ["height"], ["height"], [(height as i64,)]) - .await?; + // We don't overwrite the payload if it already exists. + // During epoch transition in PoS, the same height block is sent multiple times. + // The first block may have the payload, but subsequent blocks might be missing it. + // Overwriting would cause the payload to be lost since the block height is the same + let query = query("INSERT INTO payload (height) VALUES ($1) ON CONFLICT DO NOTHING") + .bind(height as i64); + query.execute(self.as_mut()).await?; // Finally, we insert the leaf itself, which references the header row we created. // Serialize the full leaf and QC to JSON for easy storage.