From 8211239b7d1e91c7401a8077d6cf19655c4229ab Mon Sep 17 00:00:00 2001 From: tesseract <146037313+DoTheBestToGetTheBest@users.noreply.github.com> Date: Wed, 19 Jun 2024 15:52:06 -0700 Subject: [PATCH 01/61] feat: add trace_filter method (#946) * Update trait.rs * Update trait.rs * Update trace.rs * Update trace.rs * use ref --------- Co-authored-by: Matthias Seitz --- crates/provider/src/ext/trace.rs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/crates/provider/src/ext/trace.rs b/crates/provider/src/ext/trace.rs index 4f9f11e1b5c..90b7598457a 100644 --- a/crates/provider/src/ext/trace.rs +++ b/crates/provider/src/ext/trace.rs @@ -3,8 +3,9 @@ use crate::{Provider, RpcWithBlock}; use alloy_eips::BlockNumberOrTag; use alloy_network::Network; use alloy_primitives::TxHash; -use alloy_rpc_types_trace::parity::{ - LocalizedTransactionTrace, TraceResults, TraceResultsWithTransactionHash, TraceType, +use alloy_rpc_types_trace::{ + filter::TraceFilter, + parity::{LocalizedTransactionTrace, TraceResults, TraceResultsWithTransactionHash, TraceType}, }; use alloy_transport::{Transport, TransportResult}; @@ -56,6 +57,12 @@ where trace_type: &[TraceType], ) -> TransportResult; + /// Traces matching given filter. + async fn trace_filter( + &self, + tracer: &TraceFilter, + ) -> TransportResult>; + /// Trace all transactions in the given block. /// /// # Note @@ -120,6 +127,13 @@ where self.client().request("trace_rawTransaction", (data, trace_type)).await } + async fn trace_filter( + &self, + tracer: &TraceFilter, + ) -> TransportResult> { + self.client().request("trace_filter", (tracer,)).await + } + async fn trace_block( &self, block: BlockNumberOrTag, From 1ee31cfabbb6af9fc46034f5a61f6b93e8e157d5 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Thu, 20 Jun 2024 11:52:35 +0200 Subject: [PATCH 02/61] chore: nightly clippy (#947) --- Cargo.toml | 17 ++++++++------- crates/eip7547/src/summary.rs | 2 +- crates/provider/src/fillers/gas.rs | 21 +++++++++---------- crates/provider/src/fillers/mod.rs | 15 +++++++------ crates/provider/src/fillers/nonce.rs | 9 ++++---- crates/provider/src/provider/root.rs | 2 +- crates/provider/src/provider/with_block.rs | 16 +++++++------- crates/pubsub/src/sub.rs | 2 +- crates/rpc-types-engine/src/payload.rs | 10 ++++----- crates/rpc-types-eth/src/filter.rs | 7 +++---- .../rpc-types-eth/src/transaction/request.rs | 6 ++---- crates/serde/src/other/mod.rs | 4 ++-- crates/serde/src/storage.rs | 5 +++-- 13 files changed, 56 insertions(+), 60 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 245c4345b6e..b278a953e2e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,18 +13,19 @@ repository = "https://github.com/alloy-rs/alloy" exclude = ["benches/", "tests/"] [workspace.lints] -rust.missing_debug_implementations = "warn" -rust.missing_docs = "warn" -rust.unreachable_pub = "warn" -rust.unused_must_use = "deny" -rust.rust_2018_idioms = "deny" +rust.missing-debug-implementations = "warn" +rust.missing-docs = "warn" +rust.unreachable-pub = "warn" +rust.unused-must-use = "deny" +rust.rust-2018-idioms = "deny" rustdoc.all = "warn" [workspace.lints.clippy] all = "warn" -missing_const_for_fn = "warn" -use_self = "warn" -option_if_let_else = "warn" +missing-const-for-fn = "warn" +use-self = "warn" +option-if-let-else = "warn" +redundant-clone = "warn" [workspace.metadata.docs.rs] all-features = true diff --git a/crates/eip7547/src/summary.rs b/crates/eip7547/src/summary.rs index dd6c900362c..c4a90027861 100644 --- a/crates/eip7547/src/summary.rs +++ b/crates/eip7547/src/summary.rs @@ -16,7 +16,7 @@ use std::fmt; /// follows: /// - `status`: `enum` - `"VALID" | "INVALID" | "SYNCING" | "ACCEPTED"` /// - `validationError`: `String|null` - a message providing additional details on the validation -/// error if the payload is classified as `INVALID`. +/// error if the payload is classified as `INVALID`. #[derive(Clone, Debug, PartialEq, Eq, Deserialize)] #[serde(rename_all = "camelCase")] pub struct InclusionListStatusV1 { diff --git a/crates/provider/src/fillers/gas.rs b/crates/provider/src/fillers/gas.rs index 890c935d8cf..756e54d59be 100644 --- a/crates/provider/src/fillers/gas.rs +++ b/crates/provider/src/fillers/gas.rs @@ -34,17 +34,16 @@ pub enum GasFillable { /// ## Note: /// /// The layer will populate gas fields based on the following logic: -/// - if `gas_price` is set, it will process as a legacy tx and populate the -/// `gas_limit` field if unset. -/// - if `access_list` is set, it will process as a 2930 tx and populate the -/// `gas_limit` and `gas_price` field if unset. -/// - if `blob_sidecar` is set, it will process as a 4844 tx and populate the -/// `gas_limit`, `max_fee_per_gas`, `max_priority_fee_per_gas` and -/// `max_fee_per_blob_gas` fields if unset. -/// - Otherwise, it will process as a EIP-1559 tx and populate the `gas_limit`, -/// `max_fee_per_gas` and `max_priority_fee_per_gas` fields if unset. -/// - If the network does not support EIP-1559, it will fallback to the legacy -/// tx and populate the `gas_limit` and `gas_price` fields if unset. +/// - if `gas_price` is set, it will process as a legacy tx and populate the `gas_limit` field if +/// unset. +/// - if `access_list` is set, it will process as a 2930 tx and populate the `gas_limit` and +/// `gas_price` field if unset. +/// - if `blob_sidecar` is set, it will process as a 4844 tx and populate the `gas_limit`, +/// `max_fee_per_gas`, `max_priority_fee_per_gas` and `max_fee_per_blob_gas` fields if unset. +/// - Otherwise, it will process as a EIP-1559 tx and populate the `gas_limit`, `max_fee_per_gas` +/// and `max_priority_fee_per_gas` fields if unset. +/// - If the network does not support EIP-1559, it will fallback to the legacy tx and populate the +/// `gas_limit` and `gas_price` fields if unset. /// /// # Example /// diff --git a/crates/provider/src/fillers/mod.rs b/crates/provider/src/fillers/mod.rs index fdbb6d22c0d..0d0026e21cc 100644 --- a/crates/provider/src/fillers/mod.rs +++ b/crates/provider/src/fillers/mod.rs @@ -120,14 +120,13 @@ impl FillerControlFlow { /// /// The [`FillerControlFlow`] determines the lifecycle of a filler. Fillers /// may be in one of three states: -/// - **Missing**: The filler is missing a required property to fill in the -/// transaction request. [`TxFiller::status`] should return -/// [`FillerControlFlow::Missing`]. -/// with a list of the missing properties. -/// - **Ready**: The filler is ready to fill in the transaction request. -/// [`TxFiller::status`] should return [`FillerControlFlow::Ready`]. -/// - **Finished**: The filler has filled in all properties that it can fill. -/// [`TxFiller::status`] should return [`FillerControlFlow::Finished`]. +/// - **Missing**: The filler is missing a required property to fill in the transaction request. +/// [`TxFiller::status`] should return [`FillerControlFlow::Missing`]. with a list of the missing +/// properties. +/// - **Ready**: The filler is ready to fill in the transaction request. [`TxFiller::status`] should +/// return [`FillerControlFlow::Ready`]. +/// - **Finished**: The filler has filled in all properties that it can fill. [`TxFiller::status`] +/// should return [`FillerControlFlow::Finished`]. #[doc(alias = "TransactionFiller")] pub trait TxFiller: Clone + Send + Sync + std::fmt::Debug { /// The properties that this filler retrieves from the RPC. to fill in the diff --git a/crates/provider/src/fillers/nonce.rs b/crates/provider/src/fillers/nonce.rs index 35d4124fd6b..237cb7d9583 100644 --- a/crates/provider/src/fillers/nonce.rs +++ b/crates/provider/src/fillers/nonce.rs @@ -18,11 +18,10 @@ use tokio::sync::Mutex; /// /// # Note /// -/// - If the transaction request does not have a sender set, this layer will -/// not fill nonces. -/// - Using two providers with their own nonce layer can potentially fill -/// invalid nonces if transactions are sent from the same address, as the next -/// nonce to be used is cached internally in the layer. +/// - If the transaction request does not have a sender set, this layer will not fill nonces. +/// - Using two providers with their own nonce layer can potentially fill invalid nonces if +/// transactions are sent from the same address, as the next nonce to be used is cached internally +/// in the layer. /// /// # Example /// diff --git a/crates/provider/src/provider/root.rs b/crates/provider/src/provider/root.rs index 29883aacdfa..e9bcdfddda8 100644 --- a/crates/provider/src/provider/root.rs +++ b/crates/provider/src/provider/root.rs @@ -139,7 +139,7 @@ impl Clone for RootProviderInner { } impl RootProviderInner { - pub(crate) fn new(client: RpcClient) -> Self { + pub(crate) const fn new(client: RpcClient) -> Self { Self { client, heart: OnceLock::new(), _network: PhantomData } } diff --git a/crates/provider/src/provider/with_block.rs b/crates/provider/src/provider/with_block.rs index f8453535d11..57e9c419059 100644 --- a/crates/provider/src/provider/with_block.rs +++ b/crates/provider/src/provider/with_block.rs @@ -231,44 +231,44 @@ where } /// Set the block id to "pending". - pub fn pending(self) -> Self { + pub const fn pending(self) -> Self { self.block_id(BlockId::pending()) } /// Set the block id to "latest". - pub fn latest(self) -> Self { + pub const fn latest(self) -> Self { self.block_id(BlockId::latest()) } /// Set the block id to "earliest". - pub fn earliest(self) -> Self { + pub const fn earliest(self) -> Self { self.block_id(BlockId::earliest()) } /// Set the block id to "finalized". - pub fn finalized(self) -> Self { + pub const fn finalized(self) -> Self { self.block_id(BlockId::finalized()) } /// Set the block id to "safe". - pub fn safe(self) -> Self { + pub const fn safe(self) -> Self { self.block_id(BlockId::safe()) } /// Set the block id to a specific height. - pub fn number(self, number: u64) -> Self { + pub const fn number(self, number: u64) -> Self { self.block_id(BlockId::number(number)) } /// Set the block id to a specific hash, without requiring the hash be part /// of the canonical chain. - pub fn hash(self, hash: B256) -> Self { + pub const fn hash(self, hash: B256) -> Self { self.block_id(BlockId::hash(hash)) } /// Set the block id to a specific hash and require the hash be part of the /// canonical chain. - pub fn hash_canonical(self, hash: B256) -> Self { + pub const fn hash_canonical(self, hash: B256) -> Self { self.block_id(BlockId::hash_canonical(hash)) } } diff --git a/crates/pubsub/src/sub.rs b/crates/pubsub/src/sub.rs index 2a53fd5d79f..342bbb5fbd3 100644 --- a/crates/pubsub/src/sub.rs +++ b/crates/pubsub/src/sub.rs @@ -113,7 +113,7 @@ impl From> for SubscriptionItem { /// - The [`Subscription::recv_any`] and its variants will yield unexpected types as /// [`SubscriptionItem::Other`]. /// - The [`Subscription::recv_result`] and its variants will attempt to deserialize the -/// notifications and yield the `serde_json::Result` of the deserialization. +/// notifications and yield the `serde_json::Result` of the deserialization. #[derive(Debug)] #[must_use] pub struct Subscription { diff --git a/crates/rpc-types-engine/src/payload.rs b/crates/rpc-types-engine/src/payload.rs index 7cd8a3d3426..6c7858c1158 100644 --- a/crates/rpc-types-engine/src/payload.rs +++ b/crates/rpc-types-engine/src/payload.rs @@ -31,11 +31,11 @@ impl fmt::Display for PayloadId { /// This represents the `executionPayload` field in the return value of `engine_getPayloadV2`, /// specified as: /// -/// - `executionPayload`: `ExecutionPayloadV1` | `ExecutionPayloadV2` where: -/// - `ExecutionPayloadV1` **MUST** be returned if the payload `timestamp` is lower than the -/// Shanghai timestamp -/// - `ExecutionPayloadV2` **MUST** be returned if the payload `timestamp` is greater or equal -/// to the Shanghai timestamp +/// - `executionPayload`: `ExecutionPayloadV1` | `ExecutionPayloadV2` where: +/// - `ExecutionPayloadV1` **MUST** be returned if the payload `timestamp` is lower than the +/// Shanghai timestamp +/// - `ExecutionPayloadV2` **MUST** be returned if the payload `timestamp` is greater or equal to +/// the Shanghai timestamp /// /// See: /// diff --git a/crates/rpc-types-eth/src/filter.rs b/crates/rpc-types-eth/src/filter.rs index 96e2af0f3a8..59d3c90ec11 100644 --- a/crates/rpc-types-eth/src/filter.rs +++ b/crates/rpc-types-eth/src/filter.rs @@ -130,10 +130,9 @@ impl + Eq + Hash> FilterSet { impl FilterSet { /// Returns a ValueOrArray inside an Option, so that: - /// - If the filter is empty, it returns None - /// - If the filter has only 1 value, it returns the single value - /// - Otherwise it returns an array of values - /// This should be useful for serialization + /// - If the filter is empty, it returns None + /// - If the filter has only 1 value, it returns the single value + /// - Otherwise it returns an array of values pub fn to_value_or_array(&self) -> Option> { let mut values = self.0.iter().cloned().collect::>(); match values.len() { diff --git a/crates/rpc-types-eth/src/transaction/request.rs b/crates/rpc-types-eth/src/transaction/request.rs index c3cb409e47c..c5ffd89d78e 100644 --- a/crates/rpc-types-eth/src/transaction/request.rs +++ b/crates/rpc-types-eth/src/transaction/request.rs @@ -364,10 +364,8 @@ impl TransactionRequest { /// /// # Returns /// - /// - Ok(type) if all necessary keys are present to build the preferred - /// type. - /// - Err((type, missing)) if some keys are missing to build the preferred - /// type. + /// - Ok(type) if all necessary keys are present to build the preferred type. + /// - Err((type, missing)) if some keys are missing to build the preferred type. pub fn missing_keys(&self) -> Result)> { let pref = self.preferred_type(); if let Err(missing) = match pref { diff --git a/crates/serde/src/other/mod.rs b/crates/serde/src/other/mod.rs index 0f0758683eb..33d62fbc98c 100644 --- a/crates/serde/src/other/mod.rs +++ b/crates/serde/src/other/mod.rs @@ -35,8 +35,8 @@ pub struct OtherFields { } impl OtherFields { - /// Creates a new instance - pub fn new(inner: BTreeMap) -> Self { + /// Creates a new [`OtherFields`] instance. + pub const fn new(inner: BTreeMap) -> Self { Self { inner } } diff --git a/crates/serde/src/storage.rs b/crates/serde/src/storage.rs index 838e02bd2a7..1ab46a6c693 100644 --- a/crates/serde/src/storage.rs +++ b/crates/serde/src/storage.rs @@ -19,8 +19,9 @@ use serde::{Deserialize, Deserializer, Serialize}; /// `eth_getProof` also takes storage keys up to 32 bytes as input, so the `keys` field is /// similarly deserialized. However, geth populates the storage proof `key` fields in the response /// by mirroring the `key` field used in the input. -/// * See how `storageKey`s (the input) are populated in the `StorageResult` (the output): -/// +/// +/// See how `storageKey`s (the input) are populated in the `StorageResult` (the output): +/// /// /// The contained [B256] and From implementation for String are used to preserve the input and /// implement this behavior from geth. From 7b28acf41560bf7cfeaccfbd9e7ee89d5fbf4129 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Thu, 20 Jun 2024 15:04:59 +0200 Subject: [PATCH 03/61] chore(eips): make `alloy-serde` optional under `serde` (#948) * chore: make `alloy-serde` optional `alloy-eips` * chore: unused crate deps --- crates/eips/Cargo.toml | 9 +++++++-- crates/eips/src/lib.rs | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/crates/eips/Cargo.toml b/crates/eips/Cargo.toml index 78a485f858f..139b461016a 100644 --- a/crates/eips/Cargo.toml +++ b/crates/eips/Cargo.toml @@ -21,11 +21,11 @@ workspace = true [dependencies] alloy-primitives = { workspace = true, features = ["rlp"] } alloy-rlp = { workspace = true, features = ["derive"] } -alloy-serde.workspace = true sha2.workspace = true # serde +alloy-serde = { workspace = true, optional = true } serde = { workspace = true, optional = true } # kzg @@ -62,7 +62,12 @@ std = [ "c-kzg?/std", "once_cell?/std", ] -serde = ["dep:serde", "alloy-primitives/serde", "c-kzg?/serde"] +serde = [ + "dep:alloy-serde", + "dep:serde", + "alloy-primitives/serde", + "c-kzg?/serde", +] kzg = ["dep:derive_more", "dep:c-kzg", "dep:once_cell"] ssz = [ "std", diff --git a/crates/eips/src/lib.rs b/crates/eips/src/lib.rs index 7cdc74eb0c9..0ad80222275 100644 --- a/crates/eips/src/lib.rs +++ b/crates/eips/src/lib.rs @@ -3,6 +3,7 @@ html_logo_url = "https://raw.githubusercontent.com/alloy-rs/core/main/assets/alloy.jpg", html_favicon_url = "https://raw.githubusercontent.com/alloy-rs/core/main/assets/favicon.ico" )] +#![cfg_attr(not(test), warn(unused_crate_dependencies))] #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] #![cfg_attr(not(feature = "std"), no_std)] From b3b582803acac6fbfa3c043fb9e00689c6634dca Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Thu, 20 Jun 2024 15:57:14 +0200 Subject: [PATCH 04/61] chore(eips): make `sha2` optional, add `kzg-sidecar` feature (#949) --- crates/consensus/Cargo.toml | 2 +- crates/eips/Cargo.toml | 14 ++++++++------ crates/eips/src/eip4844/mod.rs | 5 ++++- crates/eips/src/eip4844/utils.rs | 1 + 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/crates/consensus/Cargo.toml b/crates/consensus/Cargo.toml index 1d333decad8..beeb8adfa9b 100644 --- a/crates/consensus/Cargo.toml +++ b/crates/consensus/Cargo.toml @@ -21,7 +21,7 @@ workspace = true [dependencies] alloy-primitives = { workspace = true, features = ["rlp"] } alloy-rlp.workspace = true -alloy-eips.workspace = true +alloy-eips = { workspace = true, features = ["kzg-sidecar"] } alloy-serde = { workspace = true, optional = true } # kzg diff --git a/crates/eips/Cargo.toml b/crates/eips/Cargo.toml index 139b461016a..08c9a303233 100644 --- a/crates/eips/Cargo.toml +++ b/crates/eips/Cargo.toml @@ -22,16 +22,15 @@ workspace = true alloy-primitives = { workspace = true, features = ["rlp"] } alloy-rlp = { workspace = true, features = ["derive"] } -sha2.workspace = true - # serde alloy-serde = { workspace = true, optional = true } serde = { workspace = true, optional = true } # kzg -derive_more = { workspace = true, optional = true } c-kzg = { workspace = true, optional = true } +derive_more = { workspace = true, optional = true } once_cell = { workspace = true, features = ["race", "alloc"], optional = true } +sha2 = { workspace = true, optional = true } # ssz ethereum_ssz_derive = { workspace = true, optional = true } @@ -54,7 +53,7 @@ proptest-derive.workspace = true serde_json.workspace = true [features] -default = ["std"] +default = ["std", "kzg-sidecar"] std = [ "alloy-primitives/std", "alloy-rlp/std", @@ -68,7 +67,9 @@ serde = [ "alloy-primitives/serde", "c-kzg?/serde", ] -kzg = ["dep:derive_more", "dep:c-kzg", "dep:once_cell"] +kzg = ["kzg-sidecar", "sha2", "dep:derive_more", "dep:c-kzg", "dep:once_cell"] +kzg-sidecar = ["sha2"] +sha2 = ["dep:sha2"] ssz = [ "std", "dep:ethereum_ssz", @@ -77,9 +78,10 @@ ssz = [ ] arbitrary = [ "std", + "kzg-sidecar", "dep:arbitrary", "dep:proptest-derive", "dep:proptest", "alloy-primitives/arbitrary", - "alloy-serde/arbitrary", + "alloy-serde?/arbitrary", ] diff --git a/crates/eips/src/eip4844/mod.rs b/crates/eips/src/eip4844/mod.rs index 4a344151a75..dbba4352d44 100644 --- a/crates/eips/src/eip4844/mod.rs +++ b/crates/eips/src/eip4844/mod.rs @@ -14,14 +14,16 @@ pub mod builder; pub mod utils; /// Contains sidecar related types +#[cfg(feature = "kzg-sidecar")] mod sidecar; +#[cfg(feature = "kzg-sidecar")] pub use sidecar::*; use alloy_primitives::{b256, FixedBytes, B256, U256}; /// The modulus of the BLS group used in the KZG commitment scheme. All field /// elements contained in a blob MUST be STRICTLY LESS than this value. -pub const BLS_MODULUS_BYTES: FixedBytes<32> = +pub const BLS_MODULUS_BYTES: B256 = b256!("73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001"); /// The modulus of the BLS group used in the KZG commitment scheme. All field @@ -90,6 +92,7 @@ pub type Bytes48 = FixedBytes<48>; /// # Panics /// /// If the given commitment is not 48 bytes long. +#[cfg(feature = "sha2")] pub fn kzg_to_versioned_hash(commitment: &[u8]) -> B256 { use sha2::Digest; diff --git a/crates/eips/src/eip4844/utils.rs b/crates/eips/src/eip4844/utils.rs index cf5a5ed5ca2..6f4e6acb561 100644 --- a/crates/eips/src/eip4844/utils.rs +++ b/crates/eips/src/eip4844/utils.rs @@ -2,6 +2,7 @@ //! [`SidecarCoder`]. //! //! [`SidecarCoder`]: crate::eip4844::builder::SidecarCoder + use crate::eip4844::USABLE_BITS_PER_FIELD_ELEMENT; /// Determine whether a slice of bytes can be contained in a field element. From f44f35c4988de8df54de49be3c250e58e6f191de Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Thu, 20 Jun 2024 20:28:10 +0200 Subject: [PATCH 05/61] fix: enable tls12 in rustls (#952) * fix: enable tls12 in rustls * tmp: test ci * Revert "tmp: test ci" This reverts commit 78e301d859c8ee748b42c8227931c429029f407e. --- Cargo.toml | 5 ++++- crates/provider/src/provider/trait.rs | 13 +++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b278a953e2e..0a84729864a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -97,7 +97,10 @@ http-body-util = "0.1" tokio = "1" tokio-util = "0.7" tokio-stream = "0.1" -rustls = { version = "0.23", default-features = false, features = ["std"] } +rustls = { version = "0.23", default-features = false, features = [ + "std", + "tls12", +] } tokio-test = "0.4" tokio-tungstenite = "0.23" tower = { version = "0.4", features = ["util"] } diff --git a/crates/provider/src/provider/trait.rs b/crates/provider/src/provider/trait.rs index d7f641b5b46..c3eefcadd9d 100644 --- a/crates/provider/src/provider/trait.rs +++ b/crates/provider/src/provider/trait.rs @@ -1044,15 +1044,16 @@ mod tests { }; } + // Ensures we can connect to a websocket using `wss`. #[cfg(feature = "ws")] #[tokio::test] async fn websocket_tls_setup() { - let url = "wss://eth-mainnet.ws.alchemyapi.io/v2/MdZcimFJ2yz2z6pw21UYL-KNA0zmgX-F"; - // we don't care about the response, only that it doesn't panic on the TLS setup - let _provider = ProviderBuilder::<_, _, Ethereum>::default() - .with_recommended_fillers() - .on_builtin(url) - .await; + for url in [ + "wss://eth-mainnet.ws.alchemyapi.io/v2/MdZcimFJ2yz2z6pw21UYL-KNA0zmgX-F", + "wss://mainnet.infura.io/ws/v3/b0f825787ba840af81e46c6a64d20754", + ] { + let _ = ProviderBuilder::<_, _, Ethereum>::default().on_builtin(url).await.unwrap(); + } } #[cfg(feature = "ws")] From 8aa54828c025a99bbe7e2d4fc9768605d172cc6d Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Thu, 20 Jun 2024 21:09:38 +0200 Subject: [PATCH 06/61] chore: add more features to meta crate (#953) --- crates/alloy/Cargo.toml | 49 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/crates/alloy/Cargo.toml b/crates/alloy/Cargo.toml index d2da45e5c4a..1fc09ba7270 100644 --- a/crates/alloy/Cargo.toml +++ b/crates/alloy/Cargo.toml @@ -111,18 +111,63 @@ wasm-bindgen = ["alloy-transport?/wasm-bindgen"] # general consensus = ["dep:alloy-consensus"] -contract = ["dep:alloy-contract", "dyn-abi", "json-abi", "json", "sol-types"] +contract = [ + "dep:alloy-contract", + "providers", + "dyn-abi", + "json-abi", + "json", + "sol-types", +] eips = ["dep:alloy-eips"] genesis = ["dep:alloy-genesis"] network = ["dep:alloy-network"] node-bindings = ["dep:alloy-node-bindings", "alloy-provider?/anvil-node"] # providers -providers = ["dep:alloy-provider"] +providers = ["dep:alloy-provider", "rpc-client", "eips"] provider-http = ["providers", "transport-http"] provider-ws = ["providers", "alloy-provider?/ws", "transport-ws"] provider-ipc = ["providers", "alloy-provider?/ipc", "transport-ipc"] +provider-admin-api = [ + "providers", + "alloy-provider?/admin-api", + "rpc-types-admin", +] +provider-anvil-api = [ + "providers", + "alloy-provider?/anvil-api", + "rpc-types-anvil", +] +provider-debug-api = [ + "providers", + "alloy-provider?/debug-api", + "rpc-types-trace", +] +provider-engine-api = [ + "providers", + "alloy-provider?/engine-api", + "rpc-types-engine", +] +provider-trace-api = [ + "providers", + "alloy-provider?/trace-api", + "rpc-types-trace", +] +provider-txpool-api = [ + "providers", + "alloy-provider?/txpool-api", + "rpc-types-txpool", +] + +provider-anvil-node = [ + "providers", + "provider-anvil-api", + "alloy-provider?/anvil-node", + "node-bindings", +] + # pubsub pubsub = [ "dep:alloy-pubsub", From 194f266fae46c1214004d04d4606010c3807b534 Mon Sep 17 00:00:00 2001 From: Wodann Date: Fri, 21 Jun 2024 16:46:12 -0500 Subject: [PATCH 07/61] fix: deserialization of null storage keys in AccessListItem (#955) * fix: deserialization of null storage keys in AccessListItem * test: add test * misc: apply review suggestions * Update crates/eips/src/eip2930.rs Co-authored-by: Matthias Seitz * misc: apply review suggestion --------- Co-authored-by: Matthias Seitz --- crates/eips/src/eip2930.rs | 18 ++++++++++++++++++ crates/serde/src/lib.rs | 3 +++ crates/serde/src/optional.rs | 13 +++++++++++++ 3 files changed, 34 insertions(+) create mode 100644 crates/serde/src/optional.rs diff --git a/crates/eips/src/eip2930.rs b/crates/eips/src/eip2930.rs index a53715a963a..2dd78fc3ecc 100644 --- a/crates/eips/src/eip2930.rs +++ b/crates/eips/src/eip2930.rs @@ -30,6 +30,8 @@ pub struct AccessListItem { strategy = "proptest::collection::vec(proptest::arbitrary::any::(), 0..=20)" ) )] + // In JSON, we have to accept `null` for storage key, which is interpreted as an empty array. + #[cfg_attr(feature = "serde", serde(deserialize_with = "alloy_serde::null_as_default"))] pub storage_keys: Vec, } @@ -166,8 +168,24 @@ pub struct AccessListWithGasUsed { #[cfg(all(test, feature = "serde"))] mod tests { + use serde_json::json; + use super::*; + #[test] + fn access_list_null_storage_keys() { + let json = json!([ + { + "address": "0x81b7bdd5b89c90b63f604fc7cdd17035cb939707", + "storageKeys": null, + } + ]); + + let access_list = serde_json::from_value::(json).unwrap(); + assert_eq!(access_list.len(), 1); + assert_eq!(access_list[0].storage_keys, Vec::::default()); + } + #[test] fn access_list_serde() { let list = AccessList(vec![ diff --git a/crates/serde/src/lib.rs b/crates/serde/src/lib.rs index ee8bb06fd15..633216fc8b8 100644 --- a/crates/serde/src/lib.rs +++ b/crates/serde/src/lib.rs @@ -18,6 +18,9 @@ use serde::Serializer; mod bool; pub use self::bool::*; +mod optional; +pub use self::optional::*; + #[cfg_attr(not(test), deprecated = "use `quantity::{self, opt, vec}` instead")] pub mod num; #[allow(deprecated)] diff --git a/crates/serde/src/optional.rs b/crates/serde/src/optional.rs new file mode 100644 index 00000000000..5ef3288461c --- /dev/null +++ b/crates/serde/src/optional.rs @@ -0,0 +1,13 @@ +//! Serde functions for encoding optional values. +use serde::{Deserialize, Deserializer}; + +/// For use with serde's `deserialize_with` on a sequence that must be +/// deserialized as a single but optional (i.e. possibly `null`) value. +pub fn null_as_default<'de, T, D>(deserializer: D) -> Result +where + T: Deserialize<'de> + Default, + D: Deserializer<'de>, +{ + let s: Option = Deserialize::deserialize(deserializer)?; + Ok(s.unwrap_or_default()) +} From 5eadbf18c468d6b77aa0f3210b80245aa431f3f4 Mon Sep 17 00:00:00 2001 From: Oliver Date: Sat, 22 Jun 2024 00:10:53 +0200 Subject: [PATCH 08/61] feat: add eip-7251 system contract address/code (#956) * feat: add eip-7251 system contract address/code * chore: typo Co-authored-by: DaniPopes <57450786+DaniPopes@users.noreply.github.com> * chore: nit Co-authored-by: Matthias Seitz * chore: fmt --------- Co-authored-by: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Co-authored-by: Matthias Seitz --- crates/eips/src/eip7251.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/crates/eips/src/eip7251.rs b/crates/eips/src/eip7251.rs index 27c51210345..b135f89bdb6 100644 --- a/crates/eips/src/eip7251.rs +++ b/crates/eips/src/eip7251.rs @@ -4,9 +4,20 @@ #![allow(unknown_lints, non_local_definitions)] // TODO: remove when proptest-derive updates -use alloy_primitives::{Address, FixedBytes}; +use alloy_primitives::{address, bytes, Address, Bytes, FixedBytes}; use alloy_rlp::{RlpDecodable, RlpEncodable}; +/// The address for the EIP-7251 consolidation requests contract: +/// `0x00b42dbF2194e931E80326D950320f7d9Dbeac02` +pub const CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS: Address = + address!("00b42dbF2194e931E80326D950320f7d9Dbeac02"); + +/// The code for the EIP-7251 consolidation requests contract. +pub static CONSOLIDATION_REQUEST_PREDEPLOY_CODE: Bytes = bytes!("0f5f395ff33373fffffffffffffffffffffffffffffffffffffffe146098573615156028575f545f5260205ff35b36606014156101445760115f54600182026001905f5b5f82111560595781019083028483029004916001019190603e565b90939004341061014457600154600101600155600354806004026004013381556001015f35815560010160203581556001016040359055600101600355005b6003546002548082038060011160ac575060015b5f5b81811460f15780607402838201600402600401805490600101805490600101805490600101549260601b84529083601401528260340152906054015260010160ae565b9101809214610103579060025561010e565b90505f6002555f6003555b5f548061049d141561011d57505f5b6001546001828201116101325750505f610138565b01600190035b5f555f6001556074025ff35b5f5ffd"); + +/// The [EIP-7685](https://eips.ethereum.org/EIPS/eip-7685) request type for consolidation requests. +pub const CONSOLIDATION_REQUEST_TYPE: u8 = 0x02; + /// This structure maps onto the consolidation request object from [EIP-7251](https://eips.ethereum.org/EIPS/eip-7251). #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, RlpEncodable, RlpDecodable, Default)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] From 61921bccf676843823164bc7acc31cc9df5d3079 Mon Sep 17 00:00:00 2001 From: publicqi <56060664+publicqi@users.noreply.github.com> Date: Fri, 21 Jun 2024 23:00:40 -0700 Subject: [PATCH 09/61] fix: continue reading ipc on large data (#958) --- crates/transport-ipc/src/lib.rs | 38 +++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/crates/transport-ipc/src/lib.rs b/crates/transport-ipc/src/lib.rs index ff227958684..9e26a0f4668 100644 --- a/crates/transport-ipc/src/lib.rs +++ b/crates/transport-ipc/src/lib.rs @@ -155,12 +155,6 @@ impl futures::stream::Stream for ReadJsonStream { "IPC buffer contains invalid JSON data", ); - if this.buf.len() > CAPACITY { - // buffer is full, we can't decode any more - error!("IPC response too large to decode"); - return Ready(None); - } - // this happens if the deserializer is unable to decode a partial object *this.drained = true; } else if err.is_eof() { @@ -254,4 +248,36 @@ mod tests { let obj = reader.next().await; assert!(obj.is_none()); } + + #[tokio::test] + async fn test_large_valid() { + let header = b"{\"jsonrpc\":\"2.0\",\"id\":1,\"result\":\"0x"; + let filling_zeros = header + .iter() + .chain(vec![b'0'; CAPACITY - header.len()].iter()) + .copied() + .collect::>(); + + let first_page = filling_zeros.as_ref(); + let second_page = b"\"}"; + + let mock = tokio_test::io::Builder::new() + // partial object + .read(first_page) + // trigger pending read + .wait(std::time::Duration::from_millis(1)) + // complete object + .read(second_page) + .build(); + + let mut reader = ReadJsonStream::new(mock); + poll_fn(|cx| { + let res = reader.poll_next_unpin(cx); + assert!(res.is_pending()); + Ready(()) + }) + .await; + let obj = reader.next().await; + assert!(obj.is_some()); + } } From 9b8437e6aca7cc62e59330389d9079e8d6c91ae2 Mon Sep 17 00:00:00 2001 From: Delweng Date: Mon, 24 Jun 2024 17:41:39 +0800 Subject: [PATCH 10/61] docs: copy/paste error of eip-7251 link (#961) Signed-off-by: jsvisa --- crates/consensus/src/request.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/consensus/src/request.rs b/crates/consensus/src/request.rs index 1584862a84c..eca98ef6153 100644 --- a/crates/consensus/src/request.rs +++ b/crates/consensus/src/request.rs @@ -30,7 +30,7 @@ pub enum Request { WithdrawalRequest(WithdrawalRequest), /// An [EIP-7251] consolidation request. /// - /// [EIP-7251]: https://eips.ethereum.org/EIPS/eip-7002 + /// [EIP-7251]: https://eips.ethereum.org/EIPS/eip-7251 ConsolidationRequest(ConsolidationRequest), } From ea0cffc6d0ea119c997877afff1412c4517ecb89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Gonz=C3=A1lez?= Date: Mon, 24 Jun 2024 13:51:30 +0200 Subject: [PATCH 11/61] feat(contract): implement Filter's builder methods on Event (#960) * feat(contract): implement Filter's builder methods on Event * lint: appease clippy --- crates/contract/src/event.rs | 185 ++++++++++++++++++++++++++++- crates/rpc-types-eth/src/filter.rs | 5 +- 2 files changed, 185 insertions(+), 5 deletions(-) diff --git a/crates/contract/src/event.rs b/crates/contract/src/event.rs index 4112a24e375..21aa7be4284 100644 --- a/crates/contract/src/event.rs +++ b/crates/contract/src/event.rs @@ -1,8 +1,8 @@ use crate::Error; use alloy_network::Ethereum; -use alloy_primitives::{Address, LogData}; +use alloy_primitives::{Address, LogData, B256}; use alloy_provider::{FilterPollerBuilder, Network, Provider}; -use alloy_rpc_types_eth::{Filter, Log}; +use alloy_rpc_types_eth::{BlockNumberOrTag, Filter, FilterBlockOption, Log, Topic, ValueOrArray}; use alloy_sol_types::SolEvent; use alloy_transport::{Transport, TransportResult}; use futures::Stream; @@ -80,6 +80,85 @@ impl, E: SolEvent, N: Network> Event) -> Self { + self.filter.block_option = filter.into(); + self + } + + /// Sets the from block number + pub fn from_block>(mut self, block: B) -> Self { + self.filter.block_option = self.filter.block_option.with_from_block(block.into()); + self + } + + /// Sets the to block number + pub fn to_block>(mut self, block: B) -> Self { + self.filter.block_option = self.filter.block_option.with_to_block(block.into()); + self + } + + /// Return `true` if filter configured to match pending block. + /// + /// This means that both `from_block` and `to_block` are set to the pending + /// tag. + pub fn is_pending_block_filter(&self) -> bool { + self.filter.block_option.get_from_block().map_or(false, BlockNumberOrTag::is_pending) + && self.filter.block_option.get_to_block().map_or(false, BlockNumberOrTag::is_pending) + } + + /// Pins the block hash for the filter + pub fn at_block_hash>(mut self, hash: A) -> Self { + self.filter.block_option = self.filter.block_option.with_block_hash(hash.into()); + self + } + + /// Sets the address to query with this filter. + /// + /// See [`Filter::address`]. + pub fn address>>(mut self, address: A) -> Self { + self.filter.address = address.into().into(); + self + } + + /// Given the event signature in string form, it hashes it and adds it to the topics to monitor + pub fn event(mut self, event_name: &str) -> Self { + self.filter = self.filter.event(event_name); + self + } + + /// Hashes all event signatures and sets them as array to event_signature(topic0) + pub fn events(mut self, events: impl IntoIterator>) -> Self { + self.filter = self.filter.events(events); + self + } + + /// Sets event_signature(topic0) (the event name for non-anonymous events) + pub fn event_signature>(mut self, topic: TO) -> Self { + self.filter.topics[0] = topic.into(); + self + } + + /// Sets the 1st indexed topic + pub fn topic1>(mut self, topic: TO) -> Self { + self.filter.topics[1] = topic.into(); + self + } + + /// Sets the 2nd indexed topic + pub fn topic2>(mut self, topic: TO) -> Self { + self.filter.topics[2] = topic.into(); + self + } + + /// Sets the 3rd indexed topic + pub fn topic3>(mut self, topic: TO) -> Self { + self.filter.topics[3] = topic.into(); + self + } } impl Event { @@ -322,4 +401,106 @@ mod tests { assert_eq!(all.len(), 0); } } + + /// Same test as above, but using builder methods. + #[tokio::test] + async fn event_builder_filters() { + let _ = tracing_subscriber::fmt::try_init(); + + let anvil = alloy_node_bindings::Anvil::new().spawn(); + let provider = alloy_provider::ProviderBuilder::new().on_http(anvil.endpoint_url()); + + let contract = MyContract::deploy(&provider).await.unwrap(); + + let event: Event<_, _, MyContract::MyEvent, _> = Event::new(&provider, Filter::new()) + .address(*contract.address()) + .event_signature(MyContract::MyEvent::SIGNATURE_HASH); + let all = event.query().await.unwrap(); + assert_eq!(all.len(), 0); + + let poller = event.watch().await.unwrap(); + + let _receipt = + contract.doEmit().send().await.unwrap().get_receipt().await.expect("no receipt"); + + let expected_event = MyContract::MyEvent { + _0: 42, + _1: "hello".to_string(), + _2: true, + _3: U256::from(0xdeadbeefu64).into(), + }; + + let mut stream = poller.into_stream(); + let (stream_event, stream_log) = stream.next().await.unwrap().unwrap(); + assert_eq!(MyContract::MyEvent::SIGNATURE_HASH.0, stream_log.topics().first().unwrap().0); // add check that the received event signature is the same as the one we expect + assert_eq!(stream_event, expected_event); + assert_eq!(stream_log.inner.address, *contract.address()); + assert_eq!(stream_log.block_number, Some(2)); + + // This is not going to return `None` + // assert!(stream.next().await.is_none()); + + let all = event.query().await.unwrap(); + assert_eq!(all.len(), 1); + assert_eq!(all[0].0, expected_event); + assert_eq!(all[0].1, stream_log); + + // send the wrong event and make sure it is NOT picked up by the event filter + let _wrong_receipt = contract + .doEmitWrongEvent() + .send() + .await + .unwrap() + .get_receipt() + .await + .expect("no receipt"); + + // we sent the wrong event + // so no events should be returned when querying event.query() (MyEvent) + let all = event.query().await.unwrap(); + assert_eq!(all.len(), 0); + + #[cfg(feature = "pubsub")] + { + let provider = alloy_provider::ProviderBuilder::new() + .on_builtin(&anvil.ws_endpoint()) + .await + .unwrap(); + + let contract = MyContract::new(*contract.address(), &provider); + let event: Event<_, _, MyContract::MyEvent, _> = Event::new(&provider, Filter::new()) + .address(*contract.address()) + .event_signature(MyContract::MyEvent::SIGNATURE_HASH); + + let sub = event.subscribe().await.unwrap(); + + contract.doEmit().send().await.unwrap().get_receipt().await.expect("no receipt"); + + let mut stream = sub.into_stream(); + + let (stream_event, stream_log) = stream.next().await.unwrap().unwrap(); + assert_eq!( + MyContract::MyEvent::SIGNATURE_HASH.0, + stream_log.topics().first().unwrap().0 + ); + assert_eq!(stream_event, expected_event); + assert_eq!(stream_log.address(), *contract.address()); + assert_eq!(stream_log.block_number, Some(4)); + + // send the request to emit the wrong event + contract + .doEmitWrongEvent() + .send() + .await + .unwrap() + .get_receipt() + .await + .expect("no receipt"); + + // we sent the wrong event + // so no events should be returned when querying event.query() (MyEvent) + let all = event.query().await.unwrap(); + assert_eq!(all.len(), 0); + } + } } diff --git a/crates/rpc-types-eth/src/filter.rs b/crates/rpc-types-eth/src/filter.rs index 59d3c90ec11..7b0a3b8bc0d 100644 --- a/crates/rpc-types-eth/src/filter.rs +++ b/crates/rpc-types-eth/src/filter.rs @@ -397,9 +397,8 @@ impl Filter { self.block_option = self.block_option.with_block_hash(hash.into()); self } - /// Sets the inner filter object - /// - /// *NOTE:* ranges are always inclusive + + /// Sets the address to query with this filter. /// /// # Examples /// From 2d26b057c64cbcc77654f4691141c308d63b286f Mon Sep 17 00:00:00 2001 From: Oliver Date: Mon, 24 Jun 2024 13:52:04 +0200 Subject: [PATCH 12/61] feat: add eip-7702 helpers (#950) * feat: add eip-7702 auth list types * chore: fmt * chore: no_std * feat: add k256 feature to alloy-eips * chore: const fns * chore: lint * chore: rm vec type alias * feat: split into signed/unsigned types * fix: use `signature_prehash` * chore: fmt * chore: const fn * docs: fix doc link * chore: fmt -.- * chore: make pub * chore: cleanup * fix: error on list longer than 1 for nonce * chore: const fn -.- * feat: default derive * chore: manual decode impl for `OptionalNonce` * docs: small driveby link nits * test: add small rt ser/de tests * feat: add `RecoveredAuthorization` * fix: partial move --- crates/alloy/Cargo.toml | 9 +- crates/consensus/Cargo.toml | 2 +- crates/eips/Cargo.toml | 1 + crates/eips/README.md | 1 + crates/eips/src/eip6110.rs | 2 +- crates/eips/src/eip7251.rs | 2 +- crates/eips/src/eip7702/auth_list.rs | 237 +++++++++++++++++++++++++++ crates/eips/src/eip7702/constants.rs | 18 ++ crates/eips/src/eip7702/mod.rs | 8 + crates/eips/src/lib.rs | 6 +- crates/rpc-types-eth/Cargo.toml | 2 +- 11 files changed, 278 insertions(+), 10 deletions(-) create mode 100644 crates/eips/src/eip7702/auth_list.rs create mode 100644 crates/eips/src/eip7702/constants.rs create mode 100644 crates/eips/src/eip7702/mod.rs diff --git a/crates/alloy/Cargo.toml b/crates/alloy/Cargo.toml index 1fc09ba7270..dfe76bed89e 100644 --- a/crates/alloy/Cargo.toml +++ b/crates/alloy/Cargo.toml @@ -85,10 +85,10 @@ full = [ "kzg", "network", "provider-http", # includes `providers` - "provider-ws", # includes `providers` - "provider-ipc", # includes `providers` - "rpc-types", # includes `rpc-types-eth` - "signer-local", # includes `signers` + "provider-ws", # includes `providers` + "provider-ipc", # includes `providers` + "rpc-types", # includes `rpc-types-eth` + "signer-local", # includes `signers` ] # configuration @@ -263,6 +263,7 @@ arbitrary = [ k256 = [ "alloy-core/k256", "alloy-consensus?/k256", + "alloy-eips?/k256", "alloy-network?/k256", "alloy-rpc-types?/k256", ] diff --git a/crates/consensus/Cargo.toml b/crates/consensus/Cargo.toml index beeb8adfa9b..1bc962c4911 100644 --- a/crates/consensus/Cargo.toml +++ b/crates/consensus/Cargo.toml @@ -50,7 +50,7 @@ serde_json.workspace = true [features] default = ["std"] std = ["alloy-eips/std", "c-kzg?/std"] -k256 = ["alloy-primitives/k256"] +k256 = ["alloy-primitives/k256", "alloy-eips/k256"] kzg = ["dep:c-kzg", "alloy-eips/kzg", "std"] arbitrary = [ "std", diff --git a/crates/eips/Cargo.toml b/crates/eips/Cargo.toml index 08c9a303233..26f1c293264 100644 --- a/crates/eips/Cargo.toml +++ b/crates/eips/Cargo.toml @@ -70,6 +70,7 @@ serde = [ kzg = ["kzg-sidecar", "sha2", "dep:derive_more", "dep:c-kzg", "dep:once_cell"] kzg-sidecar = ["sha2"] sha2 = ["dep:sha2"] +k256 = ["alloy-primitives/k256"] ssz = [ "std", "dep:ethereum_ssz", diff --git a/crates/eips/README.md b/crates/eips/README.md index f516218b417..4956250ee6c 100644 --- a/crates/eips/README.md +++ b/crates/eips/README.md @@ -18,3 +18,4 @@ Contains constants, helpers, and basic data structures for consensus EIPs. - [EIP-7002](https://eips.ethereum.org/EIPS/eip-7002) - [EIP-7251](https://eips.ethereum.org/EIPS/eip-7251) - [EIP-7685](https://eips.ethereum.org/EIPS/eip-7685) +- [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702) diff --git a/crates/eips/src/eip6110.rs b/crates/eips/src/eip6110.rs index 0f39db8ad10..f04c02d1897 100644 --- a/crates/eips/src/eip6110.rs +++ b/crates/eips/src/eip6110.rs @@ -1,4 +1,4 @@ -//! Contains Deposit types, first introduced in the Prague hardfork: +//! Contains Deposit types, first introduced in the [Prague hardfork](https://github.com/ethereum/execution-apis/blob/main/src/engine/prague.md). //! //! See also [EIP-6110](https://eips.ethereum.org/EIPS/eip-6110): Supply validator deposits on chain //! diff --git a/crates/eips/src/eip7251.rs b/crates/eips/src/eip7251.rs index b135f89bdb6..b62a808f7e6 100644 --- a/crates/eips/src/eip7251.rs +++ b/crates/eips/src/eip7251.rs @@ -1,4 +1,4 @@ -//! Contains consolidtion types, first introduced in the Prague hardfork: +//! Contains consolidtion types, first introduced in the [Prague hardfork](https://github.com/ethereum/execution-apis/blob/main/src/engine/prague.md). //! //! See also [EIP-7251](https://eips.ethereum.org/EIPS/eip-7251): Increase the MAX_EFFECTIVE_BALANCE diff --git a/crates/eips/src/eip7702/auth_list.rs b/crates/eips/src/eip7702/auth_list.rs new file mode 100644 index 00000000000..c6c05ce81d0 --- /dev/null +++ b/crates/eips/src/eip7702/auth_list.rs @@ -0,0 +1,237 @@ +use core::ops::Deref; + +#[cfg(not(feature = "std"))] +use alloc::vec::Vec; +use alloy_primitives::{keccak256, Address, ChainId, B256}; +use alloy_rlp::{BufMut, Decodable, Encodable, Header, RlpDecodable, RlpEncodable}; + +/// An unsigned EIP-7702 authorization. +#[derive(Debug, Clone, RlpEncodable, RlpDecodable, Eq, PartialEq)] +pub struct Authorization { + /// The chain ID of the authorization. + pub chain_id: ChainId, + /// The address of the authorization. + pub address: Address, + /// The nonce for the authorization. + pub nonce: OptionalNonce, +} + +impl Authorization { + /// Get the `chain_id` for the authorization. + /// + /// # Note + /// + /// Implementers should check that this matches the current `chain_id` *or* is 0. + pub const fn chain_id(&self) -> ChainId { + self.chain_id + } + + /// Get the `address` for the authorization. + pub const fn address(&self) -> &Address { + &self.address + } + + /// Get the `nonce` for the authorization. + /// + /// # Note + /// + /// If this is `Some`, implementers should check that the nonce of the authority is equal to + /// this nonce. + pub fn nonce(&self) -> Option { + *self.nonce + } + + /// Computes the signature hash used to sign the authorization, or recover the authority from a + /// signed authorization list item. + /// + /// The signature hash is `keccak(MAGIC || rlp([chain_id, [nonce], address]))` + #[inline] + pub fn signature_hash(&self) -> B256 { + use super::constants::MAGIC; + + #[derive(RlpEncodable)] + struct Auth { + chain_id: ChainId, + nonce: OptionalNonce, + address: Address, + } + + let mut buf = Vec::new(); + buf.put_u8(MAGIC); + + Auth { chain_id: self.chain_id, nonce: self.nonce, address: self.address }.encode(&mut buf); + + keccak256(buf) + } + + /// Convert to a signed authorization by adding a signature. + pub const fn into_signed(self, signature: S) -> SignedAuthorization { + SignedAuthorization { inner: self, signature } + } +} + +/// A signed EIP-7702 authorization. +#[derive(Debug, Clone, RlpEncodable, RlpDecodable)] +pub struct SignedAuthorization { + inner: Authorization, + signature: S, +} + +impl SignedAuthorization { + /// Get the `signature` for the authorization. + pub const fn signature(&self) -> &S { + &self.signature + } +} + +#[cfg(feature = "k256")] +impl SignedAuthorization { + /// Recover the authority for the authorization. + /// + /// # Note + /// + /// Implementers should check that the authority has no code. + pub fn recover_authority(&self) -> Result { + self.signature.recover_address_from_prehash(&self.inner.signature_hash()) + } + + /// Recover the authority and transform the signed authorization into a + /// [`RecoveredAuthorization`]. + pub fn into_recovered(self) -> RecoveredAuthorization { + let authority = self.recover_authority().ok(); + RecoveredAuthorization { inner: self.inner, authority } + } +} + +impl Deref for SignedAuthorization { + type Target = Authorization; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +/// A recovered authorization. +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct RecoveredAuthorization { + inner: Authorization, + authority: Option
, +} + +impl RecoveredAuthorization { + /// Get the `authority` for the authorization. + /// + /// If this is `None`, then the authority could not be recovered. + pub const fn authority(&self) -> Option
{ + self.authority + } +} + +impl Deref for RecoveredAuthorization { + type Target = Authorization; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +/// An internal wrapper around an `Option` for optional nonces. +/// +/// In EIP-7702 the nonce is encoded as a list of either 0 or 1 items, where 0 items means that no +/// nonce was specified (i.e. `None`). If there is 1 item, this is the same as `Some`. +/// +/// The wrapper type is used for RLP encoding and decoding. +#[derive(Default, Debug, Copy, Clone, Eq, PartialEq)] +pub struct OptionalNonce(Option); + +impl OptionalNonce { + /// Create a new [`OptionalNonce`] + pub const fn new(nonce: Option) -> Self { + Self(nonce) + } +} + +impl From> for OptionalNonce { + fn from(value: Option) -> Self { + Self::new(value) + } +} + +impl Encodable for OptionalNonce { + fn encode(&self, out: &mut dyn BufMut) { + match self.0 { + Some(nonce) => { + Header { list: true, payload_length: nonce.length() }.encode(out); + nonce.encode(out); + } + None => Header { list: true, payload_length: 0 }.encode(out), + } + } +} + +impl Decodable for OptionalNonce { + fn decode(buf: &mut &[u8]) -> alloy_rlp::Result { + let mut bytes = Header::decode_bytes(buf, true)?; + if bytes.is_empty() { + return Ok(Self(None)); + } + + let payload_view = &mut bytes; + let nonce = u64::decode(payload_view)?; + if !payload_view.is_empty() { + // if there's more than 1 item in the nonce list we error + Err(alloy_rlp::Error::UnexpectedLength) + } else { + Ok(Self(Some(nonce))) + } + } +} + +impl Deref for OptionalNonce { + type Target = Option; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn test_encode_decode_roundtrip(auth: Authorization) { + let mut buf = Vec::new(); + auth.encode(&mut buf); + let decoded = Authorization::decode(&mut buf.as_ref()).unwrap(); + assert_eq!(buf.len(), auth.length()); + assert_eq!(decoded, auth); + } + + #[test] + fn test_encode_decode_auth() { + // fully filled + test_encode_decode_roundtrip(Authorization { + chain_id: 1u64, + address: Address::left_padding_from(&[6]), + nonce: Some(1u64).into(), + }); + + // no nonce + test_encode_decode_roundtrip(Authorization { + chain_id: 1u64, + address: Address::left_padding_from(&[6]), + nonce: None.into(), + }); + } + + #[test] + fn opt_nonce_too_many_elements() { + let mut buf = Vec::new(); + vec![1u64, 2u64].encode(&mut buf); + + assert_eq!( + OptionalNonce::decode(&mut buf.as_ref()), + Err(alloy_rlp::Error::UnexpectedLength) + ) + } +} diff --git a/crates/eips/src/eip7702/constants.rs b/crates/eips/src/eip7702/constants.rs new file mode 100644 index 00000000000..18b0453f514 --- /dev/null +++ b/crates/eips/src/eip7702/constants.rs @@ -0,0 +1,18 @@ +//! [EIP-7702] constants. +//! +//! [EIP-7702]: https://eips.ethereum.org/EIPS/eip-7702 + +/// Identifier for EIP7702's set code transaction. +/// +/// See also [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702). +pub const EIP7702_TX_TYPE_ID: u8 = 4; + +/// Magic number used to calculate an EIP7702 authority. +/// +/// See also [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702). +pub const MAGIC: u8 = 0x05; + +/// An additional gas cost per EIP7702 authorization list item. +/// +/// See also [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702). +pub const PER_AUTH_BASE_COST: u64 = 2500; diff --git a/crates/eips/src/eip7702/mod.rs b/crates/eips/src/eip7702/mod.rs new file mode 100644 index 00000000000..26ad27a883c --- /dev/null +++ b/crates/eips/src/eip7702/mod.rs @@ -0,0 +1,8 @@ +//! [EIP-7702] constants, helpers, and types. +//! +//! [EIP-7702]: https://eips.ethereum.org/EIPS/eip-7702 + +mod auth_list; +pub use auth_list::*; + +pub mod constants; diff --git a/crates/eips/src/lib.rs b/crates/eips/src/lib.rs index 0ad80222275..393ba4f343e 100644 --- a/crates/eips/src/lib.rs +++ b/crates/eips/src/lib.rs @@ -27,11 +27,11 @@ pub mod eip2935; pub mod eip4788; -pub mod eip4895; - pub mod eip4844; pub use eip4844::{calc_blob_gasprice, calc_excess_blob_gas}; +pub mod eip4895; + pub mod eip6110; pub mod merge; @@ -40,3 +40,5 @@ pub mod eip7002; pub mod eip7251; pub mod eip7685; + +pub mod eip7702; diff --git a/crates/rpc-types-eth/Cargo.toml b/crates/rpc-types-eth/Cargo.toml index 63bf186f99d..2e2b9a759e6 100644 --- a/crates/rpc-types-eth/Cargo.toml +++ b/crates/rpc-types-eth/Cargo.toml @@ -66,4 +66,4 @@ arbitrary = [ ] jsonrpsee-types = ["dep:jsonrpsee-types"] ssz = ["alloy-primitives/ssz", "alloy-eips/ssz"] -k256 = ["alloy-consensus/k256"] +k256 = ["alloy-consensus/k256", "alloy-eips/k256"] From a1c9f8af873398f290d2e458ab4435b43367198a Mon Sep 17 00:00:00 2001 From: rakita Date: Mon, 24 Jun 2024 23:00:41 +0200 Subject: [PATCH 13/61] chore(eips): Add serde to Authorization types (#964) * chore(eips): Add serde to Authorization types * Add Eq and PartialEq * added nits --- crates/eips/src/eip7702/auth_list.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/crates/eips/src/eip7702/auth_list.rs b/crates/eips/src/eip7702/auth_list.rs index c6c05ce81d0..faa2c160ada 100644 --- a/crates/eips/src/eip7702/auth_list.rs +++ b/crates/eips/src/eip7702/auth_list.rs @@ -7,6 +7,8 @@ use alloy_rlp::{BufMut, Decodable, Encodable, Header, RlpDecodable, RlpEncodable /// An unsigned EIP-7702 authorization. #[derive(Debug, Clone, RlpEncodable, RlpDecodable, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] pub struct Authorization { /// The chain ID of the authorization. pub chain_id: ChainId, @@ -71,8 +73,10 @@ impl Authorization { } /// A signed EIP-7702 authorization. -#[derive(Debug, Clone, RlpEncodable, RlpDecodable)] +#[derive(Debug, Clone, RlpEncodable, RlpDecodable, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct SignedAuthorization { + #[cfg_attr(feature = "serde", serde(flatten))] inner: Authorization, signature: S, } @@ -113,7 +117,9 @@ impl Deref for SignedAuthorization { /// A recovered authorization. #[derive(Debug, Clone, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct RecoveredAuthorization { + #[cfg_attr(feature = "serde", serde(flatten))] inner: Authorization, authority: Option
, } @@ -142,6 +148,7 @@ impl Deref for RecoveredAuthorization { /// /// The wrapper type is used for RLP encoding and decoding. #[derive(Default, Debug, Copy, Clone, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct OptionalNonce(Option); impl OptionalNonce { From b69b5a336a86676d27562a2c3b11f8ae05fda83d Mon Sep 17 00:00:00 2001 From: Stephen Hankinson Date: Tue, 25 Jun 2024 06:11:04 -0300 Subject: [PATCH 14/61] hotfix(contract): support state overrides for gas estimation (#967) --- crates/contract/src/call.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/crates/contract/src/call.rs b/crates/contract/src/call.rs index 7341273cc7c..8ea9ce6c358 100644 --- a/crates/contract/src/call.rs +++ b/crates/contract/src/call.rs @@ -417,8 +417,13 @@ impl, D: CallDecoder, N: Network> CallBu } /// Returns the estimated gas cost for the underlying transaction to be executed + /// If [`state overrides`](Self::state) are set, they will be applied to the gas estimation. pub async fn estimate_gas(&self) -> Result { - self.provider.estimate_gas(&self.request).block(self.block).await.map_err(Into::into) + let mut estimate = self.provider.estimate_gas(&self.request); + if let Some(state) = &self.state { + estimate = estimate.overrides(state); + } + estimate.block(self.block).await.map_err(Into::into) } /// Queries the blockchain via an `eth_call` without submitting a transaction to the network. From 4b5541e231297d055187d2955892673a8ad2eddf Mon Sep 17 00:00:00 2001 From: zerosnacks <95942363+zerosnacks@users.noreply.github.com> Date: Tue, 25 Jun 2024 17:28:20 +0200 Subject: [PATCH 15/61] feat(alloy): forward `rustls` & `native` reqwest TLS configuration to Alloy's metacrate (#969) * add reqwest feature flags to metacrate * enable reqwest when enabling sub-flag for consistency * remove redundant reqwest entry * avoid breaking changes --- crates/alloy/Cargo.toml | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/crates/alloy/Cargo.toml b/crates/alloy/Cargo.toml index dfe76bed89e..e6c2ba9e3f9 100644 --- a/crates/alloy/Cargo.toml +++ b/crates/alloy/Cargo.toml @@ -99,6 +99,20 @@ reqwest = [ "alloy-transport-http?/reqwest", "alloy-transport-http?/reqwest-default-tls", ] +reqwest-rustls-tls = [ + "dep:reqwest", + "alloy-rpc-client?/reqwest", + "alloy-provider?/reqwest", + "alloy-transport-http?/reqwest", + "alloy-transport-http?/reqwest-rustls-tls", +] +reqwest-native-tls = [ + "dep:reqwest", + "alloy-rpc-client?/reqwest", + "alloy-provider?/reqwest", + "alloy-transport-http?/reqwest", + "alloy-transport-http?/reqwest-native-tls", +] hyper = [ "dep:hyper", "alloy-rpc-client?/hyper", @@ -129,7 +143,6 @@ providers = ["dep:alloy-provider", "rpc-client", "eips"] provider-http = ["providers", "transport-http"] provider-ws = ["providers", "alloy-provider?/ws", "transport-ws"] provider-ipc = ["providers", "alloy-provider?/ipc", "transport-ipc"] - provider-admin-api = [ "providers", "alloy-provider?/admin-api", @@ -160,7 +173,6 @@ provider-txpool-api = [ "alloy-provider?/txpool-api", "rpc-types-txpool", ] - provider-anvil-node = [ "providers", "provider-anvil-api", From 46d93cdd772a3353ce860a1dbe7a43bea07df54b Mon Sep 17 00:00:00 2001 From: jn Date: Tue, 25 Jun 2024 09:30:20 -0700 Subject: [PATCH 16/61] feat: move mev.rs from reth to rpc-types-mev (#970) * feat: move mev.rs from alloy to rpc-types-mev * fmt * doc: update README * feature rpc-types-mev * dev: use alloy_serde directly * dev: split to bundle_stats and u256_numeric_string * dev(refactor): split to multiple files based on endpoint * dev: add mev as features and re export in lib * fmt * dev: simplify * dev: merge to eth_calls, mev_calls and stats --- Cargo.toml | 1 + crates/rpc-types-mev/Cargo.toml | 27 ++ crates/rpc-types-mev/README.md | 3 + crates/rpc-types-mev/src/common.rs | 244 +++++++++++++ crates/rpc-types-mev/src/eth_calls.rs | 221 ++++++++++++ crates/rpc-types-mev/src/lib.rs | 23 ++ crates/rpc-types-mev/src/mev_calls.rs | 330 ++++++++++++++++++ crates/rpc-types-mev/src/stats.rs | 209 +++++++++++ .../rpc-types-mev/src/u256_numeric_string.rs | 30 ++ crates/rpc-types/Cargo.toml | 2 + crates/rpc-types/src/lib.rs | 3 + 11 files changed, 1093 insertions(+) create mode 100644 crates/rpc-types-mev/Cargo.toml create mode 100644 crates/rpc-types-mev/README.md create mode 100644 crates/rpc-types-mev/src/common.rs create mode 100644 crates/rpc-types-mev/src/eth_calls.rs create mode 100644 crates/rpc-types-mev/src/lib.rs create mode 100644 crates/rpc-types-mev/src/mev_calls.rs create mode 100644 crates/rpc-types-mev/src/stats.rs create mode 100644 crates/rpc-types-mev/src/u256_numeric_string.rs diff --git a/Cargo.toml b/Cargo.toml index 0a84729864a..dcb5682d85b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,6 +48,7 @@ alloy-rpc-types-anvil = { version = "0.1", path = "crates/rpc-types-anvil", defa alloy-rpc-types-beacon = { version = "0.1", path = "crates/rpc-types-beacon", default-features = false } alloy-rpc-types-engine = { version = "0.1", path = "crates/rpc-types-engine", default-features = false } alloy-rpc-types-eth = { version = "0.1", path = "crates/rpc-types-eth", default-features = false } +alloy-rpc-types-mev = { version = "0.1", path = "crates/rpc-types-mev", default-features = false } alloy-rpc-types-trace = { version = "0.1", path = "crates/rpc-types-trace", default-features = false } alloy-rpc-types-txpool = { version = "0.1", path = "crates/rpc-types-txpool", default-features = false } alloy-rpc-types = { version = "0.1", path = "crates/rpc-types", default-features = false } diff --git a/crates/rpc-types-mev/Cargo.toml b/crates/rpc-types-mev/Cargo.toml new file mode 100644 index 00000000000..58fb3e4dd3e --- /dev/null +++ b/crates/rpc-types-mev/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "alloy-rpc-types-mev" +description = "Types for the MEV JSON-RPC namespace" + +version.workspace = true +edition.workspace = true +rust-version.workspace = true +authors.workspace = true +license.workspace = true +homepage.workspace = true +repository.workspace = true +exclude.workspace = true + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] + +[dependencies] +alloy-eips = { workspace = true, features = ["serde"] } +alloy-primitives.workspace = true +alloy-serde.workspace = true + +serde.workspace = true +serde_json.workspace = true + +[lints] +workspace = true diff --git a/crates/rpc-types-mev/README.md b/crates/rpc-types-mev/README.md new file mode 100644 index 00000000000..42ef4fc27c1 --- /dev/null +++ b/crates/rpc-types-mev/README.md @@ -0,0 +1,3 @@ +# alloy-rpc-types-mev + +Types for the MEV bundle JSON-RPC namespace. diff --git a/crates/rpc-types-mev/src/common.rs b/crates/rpc-types-mev/src/common.rs new file mode 100644 index 00000000000..8c138137eff --- /dev/null +++ b/crates/rpc-types-mev/src/common.rs @@ -0,0 +1,244 @@ +use alloy_primitives::Address; +use serde::{ser::SerializeSeq, Deserialize, Deserializer, Serialize, Serializer}; + +/// The version of the MEV-share API to use. +#[derive(Deserialize, Debug, Serialize, Clone, Default, PartialEq, Eq)] +pub enum ProtocolVersion { + #[default] + #[serde(rename = "beta-1")] + /// The beta-1 version of the API. + Beta1, + /// The 0.1 version of the API. + #[serde(rename = "v0.1")] + V0_1, +} + +/// Represents information about when a bundle was considered by a builder. +#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ConsideredByBuildersAt { + /// The public key of the builder. + pub pubkey: String, + /// The timestamp indicating when the bundle was considered by the builder. + pub timestamp: String, +} + +/// Represents information about when a bundle was sealed by a builder. +#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SealedByBuildersAt { + /// The public key of the builder. + pub pubkey: String, + /// The timestamp indicating when the bundle was sealed by the builder. + pub timestamp: String, +} + +/// Requirements for the bundle to be included in the block. +#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct Validity { + /// Specifies the minimum percent of a given bundle's earnings to redistribute + /// for it to be included in a builder's block. + #[serde(skip_serializing_if = "Option::is_none")] + pub refund: Option>, + /// Specifies what addresses should receive what percent of the overall refund for this bundle, + /// if it is enveloped by another bundle (eg. a searcher backrun). + #[serde(skip_serializing_if = "Option::is_none")] + pub refund_config: Option>, +} + +/// Preferences on what data should be shared about the bundle and its transactions +#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct Privacy { + /// Hints on what data should be shared about the bundle and its transactions + #[serde(skip_serializing_if = "Option::is_none")] + pub hints: Option, + /// The addresses of the builders that should be allowed to see the bundle/transaction. + #[serde(skip_serializing_if = "Option::is_none")] + pub builders: Option>, +} + +/// Hints on what data should be shared about the bundle and its transactions +#[derive(Clone, Debug, Default, PartialEq, Eq)] +pub struct PrivacyHint { + /// The calldata of the bundle's transactions should be shared. + pub calldata: bool, + /// The address of the bundle's transactions should be shared. + pub contract_address: bool, + /// The logs of the bundle's transactions should be shared. + pub logs: bool, + /// The function selector of the bundle's transactions should be shared. + pub function_selector: bool, + /// The hash of the bundle's transactions should be shared. + pub hash: bool, + /// The hash of the bundle should be shared. + pub tx_hash: bool, +} + +impl PrivacyHint { + /// Sets the flag indicating inclusion of calldata and returns the modified `PrivacyHint` + /// instance. + pub const fn with_calldata(mut self) -> Self { + self.calldata = true; + self + } + + /// Sets the flag indicating inclusion of contract address and returns the modified + /// `PrivacyHint` instance. + pub const fn with_contract_address(mut self) -> Self { + self.contract_address = true; + self + } + + /// Sets the flag indicating inclusion of logs and returns the modified `PrivacyHint` instance. + pub const fn with_logs(mut self) -> Self { + self.logs = true; + self + } + + /// Sets the flag indicating inclusion of function selector and returns the modified + /// `PrivacyHint` instance. + pub const fn with_function_selector(mut self) -> Self { + self.function_selector = true; + self + } + + /// Sets the flag indicating inclusion of hash and returns the modified `PrivacyHint` instance. + pub const fn with_hash(mut self) -> Self { + self.hash = true; + self + } + + /// Sets the flag indicating inclusion of transaction hash and returns the modified + /// `PrivacyHint` instance. + pub const fn with_tx_hash(mut self) -> Self { + self.tx_hash = true; + self + } + + /// Checks if calldata inclusion flag is set. + pub const fn has_calldata(&self) -> bool { + self.calldata + } + + /// Checks if contract address inclusion flag is set. + pub const fn has_contract_address(&self) -> bool { + self.contract_address + } + + /// Checks if logs inclusion flag is set. + pub const fn has_logs(&self) -> bool { + self.logs + } + + /// Checks if function selector inclusion flag is set. + pub const fn has_function_selector(&self) -> bool { + self.function_selector + } + + /// Checks if hash inclusion flag is set. + pub const fn has_hash(&self) -> bool { + self.hash + } + + /// Checks if transaction hash inclusion flag is set. + pub const fn has_tx_hash(&self) -> bool { + self.tx_hash + } + + /// Calculates the number of hints set within the `PrivacyHint` instance. + const fn num_hints(&self) -> usize { + let mut num_hints = 0; + if self.calldata { + num_hints += 1; + } + if self.contract_address { + num_hints += 1; + } + if self.logs { + num_hints += 1; + } + if self.function_selector { + num_hints += 1; + } + if self.hash { + num_hints += 1; + } + if self.tx_hash { + num_hints += 1; + } + num_hints + } +} + +impl Serialize for PrivacyHint { + fn serialize(&self, serializer: S) -> Result { + let mut seq = serializer.serialize_seq(Some(self.num_hints()))?; + if self.calldata { + seq.serialize_element("calldata")?; + } + if self.contract_address { + seq.serialize_element("contract_address")?; + } + if self.logs { + seq.serialize_element("logs")?; + } + if self.function_selector { + seq.serialize_element("function_selector")?; + } + if self.hash { + seq.serialize_element("hash")?; + } + if self.tx_hash { + seq.serialize_element("tx_hash")?; + } + seq.end() + } +} + +impl<'de> Deserialize<'de> for PrivacyHint { + fn deserialize>(deserializer: D) -> Result { + let hints = Vec::::deserialize(deserializer)?; + let mut privacy_hint = Self::default(); + for hint in hints { + match hint.as_str() { + "calldata" => privacy_hint.calldata = true, + "contract_address" => privacy_hint.contract_address = true, + "logs" => privacy_hint.logs = true, + "function_selector" => privacy_hint.function_selector = true, + "hash" => privacy_hint.hash = true, + "tx_hash" => privacy_hint.tx_hash = true, + _ => return Err(serde::de::Error::custom("invalid privacy hint")), + } + } + Ok(privacy_hint) + } +} + +/// Specifies the minimum percent of a given bundle's earnings to redistribute +/// for it to be included in a builder's block. +/// Related endpoint: `mev_sendBundle`, `mev_simBundle`, `eth_sendPrivateTransaction`, +/// `eth_sendPrivateRawTransaction` +#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct Refund { + /// The index of the transaction in the bundle. + #[serde(with = "alloy_serde::quantity")] + pub body_idx: u64, + /// The minimum percent of the bundle's earnings to redistribute. + #[serde(with = "alloy_serde::quantity")] + pub percent: u64, +} + +/// Specifies what addresses should receive what percent of the overall refund for this bundle, +/// if it is enveloped by another bundle (eg. a searcher backrun). +#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct RefundConfig { + /// The address to refund. + pub address: Address, + /// The minimum percent of the bundle's earnings to redistribute. + #[serde(with = "alloy_serde::quantity")] + pub percent: u64, +} diff --git a/crates/rpc-types-mev/src/eth_calls.rs b/crates/rpc-types-mev/src/eth_calls.rs new file mode 100644 index 00000000000..cfdc3cb19b1 --- /dev/null +++ b/crates/rpc-types-mev/src/eth_calls.rs @@ -0,0 +1,221 @@ +use crate::{u256_numeric_string, Privacy, Validity}; + +use alloy_eips::BlockNumberOrTag; +use alloy_primitives::{Address, Bytes, B256, U256}; +use serde::{Deserialize, Serialize}; + +/// Bundle of transactions for `eth_callBundle` +/// +/// +#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct EthCallBundle { + /// A list of hex-encoded signed transactions + pub txs: Vec, + /// hex encoded block number for which this bundle is valid on + #[serde(with = "alloy_serde::quantity")] + pub block_number: u64, + /// Either a hex encoded number or a block tag for which state to base this simulation on + pub state_block_number: BlockNumberOrTag, + /// the timestamp to use for this bundle simulation, in seconds since the unix epoch + #[serde(default, with = "alloy_serde::quantity::opt", skip_serializing_if = "Option::is_none")] + pub timestamp: Option, +} + +/// Response for `eth_callBundle` +#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct EthCallBundleResponse { + /// The hash of the bundle bodies. + pub bundle_hash: B256, + /// The gas price of the entire bundle + #[serde(with = "u256_numeric_string")] + pub bundle_gas_price: U256, + /// The difference in Ether sent to the coinbase after all transactions in the bundle + #[serde(with = "u256_numeric_string")] + pub coinbase_diff: U256, + /// The total amount of Ether sent to the coinbase after all transactions in the bundle + #[serde(with = "u256_numeric_string")] + pub eth_sent_to_coinbase: U256, + /// The total gas fees paid for all transactions in the bundle + #[serde(with = "u256_numeric_string")] + pub gas_fees: U256, + /// Results of individual transactions within the bundle + pub results: Vec, + /// The block number used as a base for this simulation + #[serde(with = "alloy_serde::quantity")] + pub state_block_number: u64, + /// The total gas used by all transactions in the bundle + #[serde(with = "alloy_serde::quantity")] + pub total_gas_used: u64, +} + +/// Result of a single transaction in a bundle for `eth_callBundle` +#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct EthCallBundleTransactionResult { + /// The difference in Ether sent to the coinbase after the transaction + #[serde(with = "u256_numeric_string")] + pub coinbase_diff: U256, + /// The amount of Ether sent to the coinbase after the transaction + #[serde(with = "u256_numeric_string")] + pub eth_sent_to_coinbase: U256, + /// The address from which the transaction originated + pub from_address: Address, + /// The gas fees paid for the transaction + #[serde(with = "u256_numeric_string")] + pub gas_fees: U256, + /// The gas price used for the transaction + #[serde(with = "u256_numeric_string")] + pub gas_price: U256, + /// The amount of gas used by the transaction + #[serde(with = "alloy_serde::quantity")] + pub gas_used: u64, + /// The address to which the transaction is sent (optional) + pub to_address: Option
, + /// The transaction hash + pub tx_hash: B256, + /// Contains the return data if the transaction succeeded + /// + /// Note: this is mutually exclusive with `revert` + #[serde(skip_serializing_if = "Option::is_none")] + pub value: Option, + /// Contains the return data if the transaction reverted + #[serde(skip_serializing_if = "Option::is_none")] + pub revert: Option, +} + +/// Request for `eth_cancelBundle` +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct CancelBundleRequest { + /// Bundle hash of the bundle to be canceled + pub bundle_hash: String, +} + +/// Request for `eth_cancelPrivateTransaction` +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct CancelPrivateTransactionRequest { + /// Transaction hash of the transaction to be canceled + pub tx_hash: B256, +} + +/// Bundle of transactions for `eth_sendBundle` +/// +/// Note: this is for `eth_sendBundle` and not `mev_sendBundle` +/// +/// +#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub(crate) struct EthSendBundle { + /// A list of hex-encoded signed transactions + pub(crate) txs: Vec, + /// hex-encoded block number for which this bundle is valid + #[serde(with = "alloy_serde::quantity")] + pub(crate) block_number: u64, + /// unix timestamp when this bundle becomes active + #[serde(default, with = "alloy_serde::quantity::opt", skip_serializing_if = "Option::is_none")] + pub(crate) min_timestamp: Option, + /// unix timestamp how long this bundle stays valid + #[serde(default, with = "alloy_serde::quantity::opt", skip_serializing_if = "Option::is_none")] + pub(crate) max_timestamp: Option, + /// list of hashes of possibly reverting txs + #[serde(default, skip_serializing_if = "Vec::is_empty")] + pub(crate) reverting_tx_hashes: Vec, + /// UUID that can be used to cancel/replace this bundle + #[serde(default, rename = "replacementUuid", skip_serializing_if = "Option::is_none")] + pub(crate) replacement_uuid: Option, +} + +/// Response from the matchmaker after sending a bundle. +#[derive(Deserialize, Debug, Serialize, Clone, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub(crate) struct EthBundleHash { + /// Hash of the bundle bodies. + pub(crate) bundle_hash: B256, +} + +/// Response from the matchmaker after sending a bundle. +#[derive(Deserialize, Debug, Serialize, Clone, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct SendBundleResponse { + /// Hash of the bundle bodies. + pub bundle_hash: B256, +} + +/// Request for `eth_sendPrivateTransaction` +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct PrivateTransactionRequest { + /// raw signed transaction + pub tx: Bytes, + /// Hex-encoded number string, optional. Highest block number in which the transaction should + /// be included. + #[serde(default, with = "alloy_serde::quantity::opt", skip_serializing_if = "Option::is_none")] + pub max_block_number: Option, + /// Preferences for private transaction. + #[serde(default, skip_serializing_if = "PrivateTransactionPreferences::is_empty")] + pub preferences: PrivateTransactionPreferences, +} + +/// Additional preferences for `eth_sendPrivateTransaction` +#[derive(Serialize, Deserialize, Default, Debug, Clone, PartialEq, Eq)] +pub struct PrivateTransactionPreferences { + /// Requirements for the bundle to be included in the block. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub validity: Option, + /// Preferences on what data should be shared about the bundle and its transactions + #[serde(default, skip_serializing_if = "Option::is_none")] + pub privacy: Option, +} + +impl PrivateTransactionPreferences { + /// Returns true if the preferences are empty. + pub const fn is_empty(&self) -> bool { + self.validity.is_none() && self.privacy.is_none() + } +} + +#[cfg(test)] +mod tests { + use super::EthCallBundleResponse; + + #[test] + fn can_deserialize_eth_call_resp() { + let s = r#"{ "bundleGasPrice": "476190476193", +"bundleHash": "0x73b1e258c7a42fd0230b2fd05529c5d4b6fcb66c227783f8bece8aeacdd1db2e", +"coinbaseDiff": "20000000000126000", +"ethSentToCoinbase": "20000000000000000", +"gasFees": "126000", +"results": [ + { + "coinbaseDiff": "10000000000063000", + "ethSentToCoinbase": "10000000000000000", + "fromAddress": "0x02A727155aeF8609c9f7F2179b2a1f560B39F5A0", + "gasFees": "63000", + "gasPrice": "476190476193", + "gasUsed": 21000, + "toAddress": "0x73625f59CAdc5009Cb458B751b3E7b6b48C06f2C", + "txHash": "0x669b4704a7d993a946cdd6e2f95233f308ce0c4649d2e04944e8299efcaa098a", + "value": "0x" + }, + { + "coinbaseDiff": "10000000000063000", + "ethSentToCoinbase": "10000000000000000", + "fromAddress": "0x02A727155aeF8609c9f7F2179b2a1f560B39F5A0", + "gasFees": "63000", + "gasPrice": "476190476193", + "gasUsed": 21000, + "toAddress": "0x73625f59CAdc5009Cb458B751b3E7b6b48C06f2C", + "txHash": "0xa839ee83465657cac01adc1d50d96c1b586ed498120a84a64749c0034b4f19fa", + "value": "0x" + } +], +"stateBlockNumber": 5221585, +"totalGasUsed": 42000 +}"#; + + let _call = serde_json::from_str::(s).unwrap(); + } +} diff --git a/crates/rpc-types-mev/src/lib.rs b/crates/rpc-types-mev/src/lib.rs new file mode 100644 index 00000000000..d2ae96a69a3 --- /dev/null +++ b/crates/rpc-types-mev/src/lib.rs @@ -0,0 +1,23 @@ +#![doc = include_str!("../README.md")] +#![doc( + html_logo_url = "https://raw.githubusercontent.com/alloy-rs/core/main/assets/alloy.jpg", + html_favicon_url = "https://raw.githubusercontent.com/alloy-rs/core/main/assets/favicon.ico" +)] +#![cfg_attr(not(test), warn(unused_crate_dependencies))] +#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] + +mod eth_calls; +pub use eth_calls::*; + +mod mev_calls; +pub use mev_calls::*; + +// types for stats endpoint like flashbots_getUserStats and flashbots_getBundleStats +mod stats; +pub use stats::*; + +mod common; +pub use common::*; + +// serde helper to serialize/deserialize u256 as numeric string +mod u256_numeric_string; diff --git a/crates/rpc-types-mev/src/mev_calls.rs b/crates/rpc-types-mev/src/mev_calls.rs new file mode 100644 index 00000000000..f85ecfa294a --- /dev/null +++ b/crates/rpc-types-mev/src/mev_calls.rs @@ -0,0 +1,330 @@ +use crate::common::{Privacy, ProtocolVersion, Validity}; + +use alloy_eips::BlockId; +use alloy_primitives::{Address, Bytes, Log, TxHash}; +use serde::{Deserialize, Serialize}; + +/// A bundle of transactions to send to the matchmaker. +/// +/// Note: this is for `mev_sendBundle` and not `eth_sendBundle`. +#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct SendBundleRequest { + /// The version of the MEV-share API to use. + #[serde(rename = "version")] + pub protocol_version: ProtocolVersion, + /// Data used by block builders to check if the bundle should be considered for inclusion. + #[serde(rename = "inclusion")] + pub inclusion: Inclusion, + /// The transactions to include in the bundle. + #[serde(rename = "body")] + pub bundle_body: Vec, + /// Requirements for the bundle to be included in the block. + #[serde(rename = "validity", skip_serializing_if = "Option::is_none")] + pub validity: Option, + /// Preferences on what data should be shared about the bundle and its transactions + #[serde(rename = "privacy", skip_serializing_if = "Option::is_none")] + pub privacy: Option, +} + +impl SendBundleRequest { + /// Create a new bundle request. + pub const fn new( + block_num: u64, + max_block: Option, + protocol_version: ProtocolVersion, + bundle_body: Vec, + ) -> Self { + Self { + protocol_version, + inclusion: Inclusion { block: block_num, max_block }, + bundle_body, + validity: None, + privacy: None, + } + } +} + +/// Data used by block builders to check if the bundle should be considered for inclusion. +#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct Inclusion { + /// The first block the bundle is valid for. + #[serde(with = "alloy_serde::quantity")] + pub block: u64, + /// The last block the bundle is valid for. + #[serde(default, with = "alloy_serde::quantity::opt", skip_serializing_if = "Option::is_none")] + pub max_block: Option, +} + +impl Inclusion { + /// Creates a new inclusion with the given min block.. + pub const fn at_block(block: u64) -> Self { + Self { block, max_block: None } + } + + /// Returns the block number of the first block the bundle is valid for. + #[inline] + pub const fn block_number(&self) -> u64 { + self.block + } + + /// Returns the block number of the last block the bundle is valid for. + #[inline] + pub fn max_block_number(&self) -> Option { + self.max_block.as_ref().map(|b| *b) + } +} + +/// A bundle tx, which can either be a transaction hash, or a full tx. +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +#[serde(untagged)] +#[serde(rename_all = "camelCase")] +pub enum BundleItem { + /// The hash of either a transaction or bundle we are trying to backrun. + Hash { + /// Tx hash. + hash: TxHash, + }, + /// A new signed transaction. + #[serde(rename_all = "camelCase")] + Tx { + /// Bytes of the signed transaction. + tx: Bytes, + /// If true, the transaction can revert without the bundle being considered invalid. + can_revert: bool, + }, +} + +/// Optional fields to override simulation state. +#[derive(Deserialize, Debug, Serialize, Clone, Default, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct SimBundleOverrides { + /// Block used for simulation state. Defaults to latest block. + /// Block header data will be derived from parent block by default. + /// Specify other params to override the default values. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub parent_block: Option, + /// Block number used for simulation, defaults to parentBlock.number + 1 + #[serde(default, with = "alloy_serde::quantity::opt")] + pub block_number: Option, + /// Coinbase used for simulation, defaults to parentBlock.coinbase + #[serde(default, skip_serializing_if = "Option::is_none")] + pub coinbase: Option
, + /// Timestamp used for simulation, defaults to parentBlock.timestamp + 12 + #[serde(default, with = "alloy_serde::quantity::opt", skip_serializing_if = "Option::is_none")] + pub timestamp: Option, + /// Gas limit used for simulation, defaults to parentBlock.gasLimit + #[serde(default, with = "alloy_serde::quantity::opt", skip_serializing_if = "Option::is_none")] + pub gas_limit: Option, + /// Base fee used for simulation, defaults to parentBlock.baseFeePerGas + #[serde(default, with = "alloy_serde::quantity::opt", skip_serializing_if = "Option::is_none")] + pub base_fee: Option, + /// Timeout in seconds, defaults to 5 + #[serde(default, with = "alloy_serde::quantity::opt", skip_serializing_if = "Option::is_none")] + pub timeout: Option, +} + +/// Response from the matchmaker after sending a simulation request. +#[derive(Deserialize, Debug, Serialize, Clone, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct SimBundleResponse { + /// Whether the simulation was successful. + pub success: bool, + /// Error message if the simulation failed. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub error: Option, + /// The block number of the simulated block. + #[serde(with = "alloy_serde::quantity")] + pub state_block: u64, + /// The gas price of the simulated block. + #[serde(with = "alloy_serde::quantity")] + pub mev_gas_price: u64, + /// The profit of the simulated block. + #[serde(with = "alloy_serde::quantity")] + pub profit: u64, + /// The refundable value of the simulated block. + #[serde(with = "alloy_serde::quantity")] + pub refundable_value: u64, + /// The gas used by the simulated block. + #[serde(with = "alloy_serde::quantity")] + pub gas_used: u64, + /// Logs returned by `mev_simBundle`. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub logs: Option>, +} + +/// Logs returned by `mev_simBundle`. +#[derive(Deserialize, Debug, Serialize, Clone, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct SimBundleLogs { + /// Logs for transactions in bundle. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub tx_logs: Option>, + /// Logs for bundles in bundle. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub bundle_logs: Option>, +} + +#[cfg(test)] +mod tests { + use std::str::FromStr; + + use crate::{common::PrivacyHint, RefundConfig}; + use alloy_primitives::Bytes; + + use super::*; + + #[test] + fn can_deserialize_simple() { + let str = r#" + [{ + "version": "v0.1", + "inclusion": { + "block": "0x1" + }, + "body": [{ + "tx": "0x02f86b0180843b9aca00852ecc889a0082520894c87037874aed04e51c29f582394217a0a2b89d808080c080a0a463985c616dd8ee17d7ef9112af4e6e06a27b071525b42182fe7b0b5c8b4925a00af5ca177ffef2ff28449292505d41be578bebb77110dfc09361d2fb56998260", + "canRevert": false + }] + }] + "#; + let res: Result, _> = serde_json::from_str(str); + assert!(res.is_ok()); + } + + #[test] + fn can_deserialize_complex() { + let str = r#" + [{ + "version": "v0.1", + "inclusion": { + "block": "0x1" + }, + "body": [{ + "tx": "0x02f86b0180843b9aca00852ecc889a0082520894c87037874aed04e51c29f582394217a0a2b89d808080c080a0a463985c616dd8ee17d7ef9112af4e6e06a27b071525b42182fe7b0b5c8b4925a00af5ca177ffef2ff28449292505d41be578bebb77110dfc09361d2fb56998260", + "canRevert": false + }], + "privacy": { + "hints": [ + "calldata" + ] + }, + "validity": { + "refundConfig": [ + { + "address": "0x8EC1237b1E80A6adf191F40D4b7D095E21cdb18f", + "percent": 100 + } + ] + } + }] + "#; + let res: Result, _> = serde_json::from_str(str); + assert!(res.is_ok()); + } + + #[test] + fn can_serialize_complex() { + let str = r#" + [{ + "version": "v0.1", + "inclusion": { + "block": "0x1" + }, + "body": [{ + "tx": "0x02f86b0180843b9aca00852ecc889a0082520894c87037874aed04e51c29f582394217a0a2b89d808080c080a0a463985c616dd8ee17d7ef9112af4e6e06a27b071525b42182fe7b0b5c8b4925a00af5ca177ffef2ff28449292505d41be578bebb77110dfc09361d2fb56998260", + "canRevert": false + }], + "privacy": { + "hints": [ + "calldata" + ] + }, + "validity": { + "refundConfig": [ + { + "address": "0x8EC1237b1E80A6adf191F40D4b7D095E21cdb18f", + "percent": 100 + } + ] + } + }] + "#; + let bundle_body = vec![BundleItem::Tx { + tx: Bytes::from_str("0x02f86b0180843b9aca00852ecc889a0082520894c87037874aed04e51c29f582394217a0a2b89d808080c080a0a463985c616dd8ee17d7ef9112af4e6e06a27b071525b42182fe7b0b5c8b4925a00af5ca177ffef2ff28449292505d41be578bebb77110dfc09361d2fb56998260").unwrap(), + can_revert: false, + }]; + + let validity = Some(Validity { + refund_config: Some(vec![RefundConfig { + address: "0x8EC1237b1E80A6adf191F40D4b7D095E21cdb18f".parse().unwrap(), + percent: 100, + }]), + ..Default::default() + }); + + let privacy = Some(Privacy { + hints: Some(PrivacyHint { calldata: true, ..Default::default() }), + ..Default::default() + }); + + let bundle = SendBundleRequest { + protocol_version: ProtocolVersion::V0_1, + inclusion: Inclusion { block: 1, max_block: None }, + bundle_body, + validity, + privacy, + }; + let expected = serde_json::from_str::>(str).unwrap(); + assert_eq!(bundle, expected[0]); + } + + #[test] + fn can_serialize_privacy_hint() { + let hint = PrivacyHint { + calldata: true, + contract_address: true, + logs: true, + function_selector: true, + hash: true, + tx_hash: true, + }; + let expected = + r#"["calldata","contract_address","logs","function_selector","hash","tx_hash"]"#; + let actual = serde_json::to_string(&hint).unwrap(); + assert_eq!(actual, expected); + } + + #[test] + fn can_deserialize_privacy_hint() { + let hint = PrivacyHint { + calldata: true, + contract_address: false, + logs: true, + function_selector: false, + hash: true, + tx_hash: false, + }; + let expected = r#"["calldata","logs","hash"]"#; + let actual: PrivacyHint = serde_json::from_str(expected).unwrap(); + assert_eq!(actual, hint); + } + + #[test] + fn can_dererialize_sim_response() { + let expected = r#" + { + "success": true, + "stateBlock": "0x8b8da8", + "mevGasPrice": "0x74c7906005", + "profit": "0x4bc800904fc000", + "refundableValue": "0x4bc800904fc000", + "gasUsed": "0xa620", + "logs": [{},{}] + } + "#; + let actual: SimBundleResponse = serde_json::from_str(expected).unwrap(); + assert!(actual.success); + } +} diff --git a/crates/rpc-types-mev/src/stats.rs b/crates/rpc-types-mev/src/stats.rs new file mode 100644 index 00000000000..74529d46543 --- /dev/null +++ b/crates/rpc-types-mev/src/stats.rs @@ -0,0 +1,209 @@ +use crate::{u256_numeric_string, ConsideredByBuildersAt, SealedByBuildersAt}; + +use alloy_primitives::U256; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + +// TODO(@optimiz-r): Revisit after is closed. +/// Response for `flashbots_getBundleStatsV2` represents stats for a single bundle +/// +/// Note: this is V2: +/// +/// Timestamp format: "2022-10-06T21:36:06.322Z" +#[derive(Default, Debug, Clone, PartialEq, Eq)] +pub enum BundleStats { + /// The relayer has not yet seen the bundle. + #[default] + Unknown, + /// The relayer has seen the bundle, but has not simulated it yet. + Seen(StatsSeen), + /// The relayer has seen the bundle and has simulated it. + Simulated(StatsSimulated), +} + +impl Serialize for BundleStats { + fn serialize(&self, serializer: S) -> Result { + match self { + Self::Unknown => serde_json::json!({"isSimulated": false}).serialize(serializer), + Self::Seen(stats) => stats.serialize(serializer), + Self::Simulated(stats) => stats.serialize(serializer), + } + } +} + +impl<'de> Deserialize<'de> for BundleStats { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let map = serde_json::Map::deserialize(deserializer)?; + + if map.get("receivedAt").is_none() { + Ok(Self::Unknown) + } else if map["isSimulated"] == false { + StatsSeen::deserialize(serde_json::Value::Object(map)) + .map(BundleStats::Seen) + .map_err(serde::de::Error::custom) + } else { + StatsSimulated::deserialize(serde_json::Value::Object(map)) + .map(BundleStats::Simulated) + .map_err(serde::de::Error::custom) + } + } +} + +/// Response for `flashbots_getBundleStatsV2` represents stats for a single bundle +/// +/// Note: this is V2: +/// +/// Timestamp format: "2022-10-06T21:36:06.322Z +#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct StatsSeen { + /// boolean representing if this searcher has a high enough reputation to be in the high + /// priority queue + pub is_high_priority: bool, + /// representing whether the bundle gets simulated. All other fields will be omitted except + /// simulated field if API didn't receive bundle + pub is_simulated: bool, + /// time at which the bundle API received the bundle + pub received_at: String, +} + +/// Response for `flashbots_getBundleStatsV2` represents stats for a single bundle +/// +/// Note: this is V2: +/// +/// Timestamp format: "2022-10-06T21:36:06.322Z +#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct StatsSimulated { + /// boolean representing if this searcher has a high enough reputation to be in the high + /// priority queue + pub is_high_priority: bool, + /// representing whether the bundle gets simulated. All other fields will be omitted except + /// simulated field if API didn't receive bundle + pub is_simulated: bool, + /// time at which the bundle gets simulated + pub simulated_at: String, + /// time at which the bundle API received the bundle + pub received_at: String, + /// indicates time at which each builder selected the bundle to be included in the target + /// block + #[serde(default = "Vec::new")] + pub considered_by_builders_at: Vec, + /// indicates time at which each builder sealed a block containing the bundle + #[serde(default = "Vec::new")] + pub sealed_by_builders_at: Vec, +} + +/// Response for `flashbots_getUserStatsV2` represents stats for a searcher. +/// +/// Note: this is V2: +#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct UserStats { + /// Represents whether this searcher has a high enough reputation to be in the high priority + /// queue. + pub is_high_priority: bool, + /// The total amount paid to validators over all time. + #[serde(with = "u256_numeric_string")] + pub all_time_validator_payments: U256, + /// The total amount of gas simulated across all bundles submitted to Flashbots. + /// This is the actual gas used in simulations, not gas limit. + #[serde(with = "u256_numeric_string")] + pub all_time_gas_simulated: U256, + /// The total amount paid to validators the last 7 days. + #[serde(with = "u256_numeric_string")] + pub last_7d_validator_payments: U256, + /// The total amount of gas simulated across all bundles submitted to Flashbots in the last 7 + /// days. This is the actual gas used in simulations, not gas limit. + #[serde(with = "u256_numeric_string")] + pub last_7d_gas_simulated: U256, + /// The total amount paid to validators the last day. + #[serde(with = "u256_numeric_string")] + pub last_1d_validator_payments: U256, + /// The total amount of gas simulated across all bundles submitted to Flashbots in the last + /// day. This is the actual gas used in simulations, not gas limit. + #[serde(with = "u256_numeric_string")] + pub last_1d_gas_simulated: U256, +} + +#[cfg(test)] +mod tests { + use super::*; + + use crate::SealedByBuildersAt; + + #[test] + fn can_serialize_deserialize_bundle_stats() { + let fixtures = [ + ( + r#"{ + "isSimulated": false + }"#, + BundleStats::Unknown, + ), + ( + r#"{ + "isHighPriority": false, + "isSimulated": false, + "receivedAt": "476190476193" + }"#, + BundleStats::Seen(StatsSeen { + is_high_priority: false, + is_simulated: false, + received_at: "476190476193".to_string(), + }), + ), + ( + r#"{ + "isHighPriority": true, + "isSimulated": true, + "simulatedAt": "111", + "receivedAt": "222", + "consideredByBuildersAt":[], + "sealedByBuildersAt": [ + { + "pubkey": "333", + "timestamp": "444" + }, + { + "pubkey": "555", + "timestamp": "666" + } + ] + }"#, + BundleStats::Simulated(StatsSimulated { + is_high_priority: true, + is_simulated: true, + simulated_at: String::from("111"), + received_at: String::from("222"), + considered_by_builders_at: vec![], + sealed_by_builders_at: vec![ + SealedByBuildersAt { + pubkey: String::from("333"), + timestamp: String::from("444"), + }, + SealedByBuildersAt { + pubkey: String::from("555"), + timestamp: String::from("666"), + }, + ], + }), + ), + ]; + + let strip_whitespaces = + |input: &str| input.chars().filter(|&c| !c.is_whitespace()).collect::(); + + for (serialized, deserialized) in fixtures { + // Check de-serialization + let deserialized_expected = serde_json::from_str::(serialized).unwrap(); + assert_eq!(deserialized, deserialized_expected); + + // Check serialization + let serialized_expected = &serde_json::to_string(&deserialized).unwrap(); + assert_eq!(strip_whitespaces(serialized), strip_whitespaces(serialized_expected)); + } + } +} diff --git a/crates/rpc-types-mev/src/u256_numeric_string.rs b/crates/rpc-types-mev/src/u256_numeric_string.rs new file mode 100644 index 00000000000..cb3b1fc6066 --- /dev/null +++ b/crates/rpc-types-mev/src/u256_numeric_string.rs @@ -0,0 +1,30 @@ +use alloy_primitives::U256; +use serde::{de, Deserialize, Serializer}; +use std::str::FromStr; + +pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result +where + D: de::Deserializer<'de>, +{ + let val = serde_json::Value::deserialize(deserializer)?; + match val { + serde_json::Value::String(s) => { + if let Ok(val) = s.parse::() { + return Ok(U256::from(val)); + } + U256::from_str(&s).map_err(de::Error::custom) + } + serde_json::Value::Number(num) => { + num.as_u64().map(U256::from).ok_or_else(|| de::Error::custom("invalid u256")) + } + _ => Err(de::Error::custom("invalid u256")), + } +} + +pub(crate) fn serialize(val: &U256, serializer: S) -> Result +where + S: Serializer, +{ + let val: u128 = (*val).try_into().map_err(serde::ser::Error::custom)?; + serializer.serialize_str(&val.to_string()) +} diff --git a/crates/rpc-types/Cargo.toml b/crates/rpc-types/Cargo.toml index 93b30c8b37c..fedb641cde3 100644 --- a/crates/rpc-types/Cargo.toml +++ b/crates/rpc-types/Cargo.toml @@ -25,6 +25,7 @@ alloy-rpc-types-anvil = { workspace = true, optional = true } alloy-rpc-types-beacon = { workspace = true, optional = true } alloy-rpc-types-engine = { workspace = true, optional = true } alloy-rpc-types-eth = { workspace = true, optional = true } +alloy-rpc-types-mev = { workspace = true, optional = true } alloy-rpc-types-trace = { workspace = true, optional = true } alloy-rpc-types-txpool = { workspace = true, optional = true } @@ -35,6 +36,7 @@ anvil = ["dep:alloy-rpc-types-anvil"] beacon = ["dep:alloy-rpc-types-beacon"] engine = ["dep:alloy-rpc-types-engine"] eth = ["dep:alloy-rpc-types-eth"] +mev = ["dep:alloy-rpc-types-mev"] trace = ["dep:alloy-rpc-types-trace"] txpool = ["dep:alloy-rpc-types-txpool"] diff --git a/crates/rpc-types/src/lib.rs b/crates/rpc-types/src/lib.rs index 00891214f24..003a3797db7 100644 --- a/crates/rpc-types/src/lib.rs +++ b/crates/rpc-types/src/lib.rs @@ -25,6 +25,9 @@ pub use alloy_rpc_types_eth as eth; #[cfg(feature = "eth")] pub use eth::*; +#[cfg(feature = "mev")] +pub use alloy_rpc_types_mev as mev; + #[cfg(feature = "trace")] pub use alloy_rpc_types_trace as trace; From 6ac263579752188c0e2cbf5fecc6690c486cad34 Mon Sep 17 00:00:00 2001 From: morito Date: Wed, 26 Jun 2024 02:24:19 +0900 Subject: [PATCH 17/61] feat(network): Add `input` method to `TransactionResponse` (#959) * feat(network): Implement `input` method to `TransactionResponse` * add a doc alias to the `input` method * chore: use &Bytes --------- Co-authored-by: Matthias Seitz --- crates/network/src/any/mod.rs | 5 +++++ crates/network/src/ethereum/mod.rs | 5 +++++ crates/network/src/lib.rs | 6 +++++- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/crates/network/src/any/mod.rs b/crates/network/src/any/mod.rs index 820766f5001..1885e5835a9 100644 --- a/crates/network/src/any/mod.rs +++ b/crates/network/src/any/mod.rs @@ -1,6 +1,7 @@ use crate::{Network, ReceiptResponse, TransactionResponse}; use alloy_consensus::TxType; use alloy_eips::eip2718::Eip2718Error; +use alloy_primitives::Bytes; use alloy_rpc_types_eth::{AnyTransactionReceipt, Header, Transaction, TransactionRequest}; use alloy_serde::WithOtherFields; use core::fmt; @@ -106,4 +107,8 @@ impl TransactionResponse for WithOtherFields { fn gas(&self) -> u128 { self.gas } + + fn input(&self) -> &Bytes { + &self.input + } } diff --git a/crates/network/src/ethereum/mod.rs b/crates/network/src/ethereum/mod.rs index a6a532d492c..9bfe362c578 100644 --- a/crates/network/src/ethereum/mod.rs +++ b/crates/network/src/ethereum/mod.rs @@ -1,4 +1,5 @@ use crate::{Network, ReceiptResponse, TransactionResponse}; +use alloy_primitives::Bytes; mod builder; @@ -62,4 +63,8 @@ impl TransactionResponse for alloy_rpc_types_eth::Transaction { fn gas(&self) -> u128 { self.gas } + + fn input(&self) -> &Bytes { + &self.input + } } diff --git a/crates/network/src/lib.rs b/crates/network/src/lib.rs index 652b7c82834..0afa1f7f093 100644 --- a/crates/network/src/lib.rs +++ b/crates/network/src/lib.rs @@ -9,7 +9,7 @@ use alloy_consensus::TxReceipt; use alloy_eips::eip2718::{Eip2718Envelope, Eip2718Error}; use alloy_json_rpc::RpcObject; -use alloy_primitives::{Address, TxHash, U256}; +use alloy_primitives::{Address, Bytes, TxHash, U256}; use core::fmt::{Debug, Display}; mod transaction; @@ -72,6 +72,10 @@ pub trait TransactionResponse { /// Gas limit fn gas(&self) -> u128; + + /// Input data + #[doc(alias = "calldata")] + fn input(&self) -> &Bytes; } /// Captures type info for network-specific RPC requests/responses. From 109423678a77a14fc0b31ff68daac50d250c2ae5 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Tue, 25 Jun 2024 21:19:47 +0200 Subject: [PATCH 18/61] chore: release 0.1.3 --- CHANGELOG.md | 38 ++++++++++++++ Cargo.toml | 2 +- crates/consensus/CHANGELOG.md | 15 ++++++ crates/contract/CHANGELOG.md | 11 ++++ crates/eip7547/CHANGELOG.md | 7 +++ crates/eips/CHANGELOG.md | 21 ++++++++ crates/genesis/CHANGELOG.md | 1 + crates/json-rpc/CHANGELOG.md | 1 + crates/network/CHANGELOG.md | 7 +++ crates/node-bindings/CHANGELOG.md | 1 + crates/provider/CHANGELOG.md | 15 ++++++ crates/pubsub/CHANGELOG.md | 7 +++ crates/rpc-client/CHANGELOG.md | 1 + crates/rpc-types-admin/CHANGELOG.md | 1 + crates/rpc-types-anvil/CHANGELOG.md | 1 + crates/rpc-types-beacon/CHANGELOG.md | 1 + crates/rpc-types-engine/CHANGELOG.md | 7 +++ crates/rpc-types-eth/CHANGELOG.md | 12 +++++ crates/rpc-types-mev/CHANGELOG.md | 75 ++++++++++++++++++++++++++++ crates/rpc-types-trace/CHANGELOG.md | 1 + crates/rpc-types-txpool/CHANGELOG.md | 1 + crates/rpc-types/CHANGELOG.md | 7 +++ crates/serde/CHANGELOG.md | 11 ++++ crates/signer-aws/CHANGELOG.md | 1 + crates/signer-gcp/CHANGELOG.md | 1 + crates/signer-ledger/CHANGELOG.md | 1 + crates/signer-local/CHANGELOG.md | 1 + crates/signer-trezor/CHANGELOG.md | 1 + crates/signer/CHANGELOG.md | 1 + crates/transport-http/CHANGELOG.md | 1 + crates/transport-ipc/CHANGELOG.md | 7 +++ crates/transport-ws/CHANGELOG.md | 1 + crates/transport/CHANGELOG.md | 1 + 33 files changed, 259 insertions(+), 1 deletion(-) create mode 100644 crates/rpc-types-mev/CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 5fb9a287533..6773cbf84fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,43 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.3](https://github.com/alloy-rs/alloy/releases/tag/v0.1.3) - 2024-06-25 + +### Bug Fixes + +- Continue reading ipc on large data ([#958](https://github.com/alloy-rs/alloy/issues/958)) +- Deserialization of null storage keys in AccessListItem ([#955](https://github.com/alloy-rs/alloy/issues/955)) +- Enable tls12 in rustls ([#952](https://github.com/alloy-rs/alloy/issues/952)) + +### Dependencies + +- [eips] Make `alloy-serde` optional under `serde` ([#948](https://github.com/alloy-rs/alloy/issues/948)) + +### Documentation + +- Copy/paste error of eip-7251 link ([#961](https://github.com/alloy-rs/alloy/issues/961)) + +### Features + +- [network] Add `input` method to `TransactionResponse` ([#959](https://github.com/alloy-rs/alloy/issues/959)) +- Move mev.rs from reth to rpc-types-mev ([#970](https://github.com/alloy-rs/alloy/issues/970)) +- [alloy] Forward `rustls` & `native` reqwest TLS configuration to Alloy's metacrate ([#969](https://github.com/alloy-rs/alloy/issues/969)) +- Add eip-7702 helpers ([#950](https://github.com/alloy-rs/alloy/issues/950)) +- [contract] Implement Filter's builder methods on Event ([#960](https://github.com/alloy-rs/alloy/issues/960)) +- Add eip-7251 system contract address/code ([#956](https://github.com/alloy-rs/alloy/issues/956)) +- Add trace_filter method ([#946](https://github.com/alloy-rs/alloy/issues/946)) + +### Miscellaneous Tasks + +- [eips] Add serde to Authorization types ([#964](https://github.com/alloy-rs/alloy/issues/964)) +- Add more features to meta crate ([#953](https://github.com/alloy-rs/alloy/issues/953)) +- [eips] Make `sha2` optional, add `kzg-sidecar` feature ([#949](https://github.com/alloy-rs/alloy/issues/949)) +- Nightly clippy ([#947](https://github.com/alloy-rs/alloy/issues/947)) + +### Other + +- [contract] Support state overrides for gas estimation ([#967](https://github.com/alloy-rs/alloy/issues/967)) + ## [0.1.2](https://github.com/alloy-rs/alloy/releases/tag/v0.1.2) - 2024-06-19 ### Dependencies @@ -33,6 +70,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Tasks +- Release 0.1.2 - [rpc-types] Remove duplicate `Index` definition in `rpc-types-anvil` in favor of the one in `rpc-types-eth` ([#943](https://github.com/alloy-rs/alloy/issues/943)) - Update eip-2935 bytecode and address ([#934](https://github.com/alloy-rs/alloy/issues/934)) - Don't self-host documentation anymore ([#920](https://github.com/alloy-rs/alloy/issues/920)) diff --git a/Cargo.toml b/Cargo.toml index dcb5682d85b..c2065b23e38 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ members = ["crates/*"] resolver = "2" [workspace.package] -version = "0.1.2" +version = "0.1.3" edition = "2021" rust-version = "1.76" authors = ["Alloy Contributors"] diff --git a/crates/consensus/CHANGELOG.md b/crates/consensus/CHANGELOG.md index 7e7690be36e..6ff3c0f3e17 100644 --- a/crates/consensus/CHANGELOG.md +++ b/crates/consensus/CHANGELOG.md @@ -5,6 +5,20 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.3](https://github.com/alloy-rs/alloy/releases/tag/v0.1.3) - 2024-06-25 + +### Documentation + +- Copy/paste error of eip-7251 link ([#961](https://github.com/alloy-rs/alloy/issues/961)) + +### Features + +- Add eip-7702 helpers ([#950](https://github.com/alloy-rs/alloy/issues/950)) + +### Miscellaneous Tasks + +- [eips] Make `sha2` optional, add `kzg-sidecar` feature ([#949](https://github.com/alloy-rs/alloy/issues/949)) + ## [0.1.2](https://github.com/alloy-rs/alloy/releases/tag/v0.1.2) - 2024-06-19 ### Documentation @@ -17,6 +31,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Tasks +- Release 0.1.2 - Update changelogs for v0.1.1 ([#922](https://github.com/alloy-rs/alloy/issues/922)) - Add docs.rs metadata to all manifests ([#917](https://github.com/alloy-rs/alloy/issues/917)) diff --git a/crates/contract/CHANGELOG.md b/crates/contract/CHANGELOG.md index 0ef7a0d1b3e..f7cc0f084f9 100644 --- a/crates/contract/CHANGELOG.md +++ b/crates/contract/CHANGELOG.md @@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.3](https://github.com/alloy-rs/alloy/releases/tag/v0.1.3) - 2024-06-25 + +### Features + +- [contract] Implement Filter's builder methods on Event ([#960](https://github.com/alloy-rs/alloy/issues/960)) + +### Other + +- [contract] Support state overrides for gas estimation ([#967](https://github.com/alloy-rs/alloy/issues/967)) + ## [0.1.2](https://github.com/alloy-rs/alloy/releases/tag/v0.1.2) - 2024-06-19 ### Documentation @@ -13,6 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Tasks +- Release 0.1.2 - Update changelogs for v0.1.1 ([#922](https://github.com/alloy-rs/alloy/issues/922)) - Add docs.rs metadata to all manifests ([#917](https://github.com/alloy-rs/alloy/issues/917)) diff --git a/crates/eip7547/CHANGELOG.md b/crates/eip7547/CHANGELOG.md index 7ef813f4485..c588af71a9d 100644 --- a/crates/eip7547/CHANGELOG.md +++ b/crates/eip7547/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.3](https://github.com/alloy-rs/alloy/releases/tag/v0.1.3) - 2024-06-25 + +### Miscellaneous Tasks + +- Nightly clippy ([#947](https://github.com/alloy-rs/alloy/issues/947)) + ## [0.1.2](https://github.com/alloy-rs/alloy/releases/tag/v0.1.2) - 2024-06-19 ### Documentation @@ -13,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Tasks +- Release 0.1.2 - Update changelogs for v0.1.1 ([#922](https://github.com/alloy-rs/alloy/issues/922)) - Add docs.rs metadata to all manifests ([#917](https://github.com/alloy-rs/alloy/issues/917)) diff --git a/crates/eips/CHANGELOG.md b/crates/eips/CHANGELOG.md index 93c6ff64a44..ab2773a8647 100644 --- a/crates/eips/CHANGELOG.md +++ b/crates/eips/CHANGELOG.md @@ -5,6 +5,26 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.3](https://github.com/alloy-rs/alloy/releases/tag/v0.1.3) - 2024-06-25 + +### Bug Fixes + +- Deserialization of null storage keys in AccessListItem ([#955](https://github.com/alloy-rs/alloy/issues/955)) + +### Dependencies + +- [eips] Make `alloy-serde` optional under `serde` ([#948](https://github.com/alloy-rs/alloy/issues/948)) + +### Features + +- Add eip-7702 helpers ([#950](https://github.com/alloy-rs/alloy/issues/950)) +- Add eip-7251 system contract address/code ([#956](https://github.com/alloy-rs/alloy/issues/956)) + +### Miscellaneous Tasks + +- [eips] Add serde to Authorization types ([#964](https://github.com/alloy-rs/alloy/issues/964)) +- [eips] Make `sha2` optional, add `kzg-sidecar` feature ([#949](https://github.com/alloy-rs/alloy/issues/949)) + ## [0.1.2](https://github.com/alloy-rs/alloy/releases/tag/v0.1.2) - 2024-06-19 ### Documentation @@ -20,6 +40,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Tasks +- Release 0.1.2 - Update eip-2935 bytecode and address ([#934](https://github.com/alloy-rs/alloy/issues/934)) - Update changelogs for v0.1.1 ([#922](https://github.com/alloy-rs/alloy/issues/922)) - Add docs.rs metadata to all manifests ([#917](https://github.com/alloy-rs/alloy/issues/917)) diff --git a/crates/genesis/CHANGELOG.md b/crates/genesis/CHANGELOG.md index 0a81a051bde..89cc88ace21 100644 --- a/crates/genesis/CHANGELOG.md +++ b/crates/genesis/CHANGELOG.md @@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Tasks +- Release 0.1.2 - Update changelogs for v0.1.1 ([#922](https://github.com/alloy-rs/alloy/issues/922)) - Add docs.rs metadata to all manifests ([#917](https://github.com/alloy-rs/alloy/issues/917)) diff --git a/crates/json-rpc/CHANGELOG.md b/crates/json-rpc/CHANGELOG.md index bcb892f1eea..8c206309a43 100644 --- a/crates/json-rpc/CHANGELOG.md +++ b/crates/json-rpc/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Tasks +- Release 0.1.2 - Update changelogs for v0.1.1 ([#922](https://github.com/alloy-rs/alloy/issues/922)) - Add docs.rs metadata to all manifests ([#917](https://github.com/alloy-rs/alloy/issues/917)) diff --git a/crates/network/CHANGELOG.md b/crates/network/CHANGELOG.md index 4aac8c5e284..3a6121e3bd1 100644 --- a/crates/network/CHANGELOG.md +++ b/crates/network/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.3](https://github.com/alloy-rs/alloy/releases/tag/v0.1.3) - 2024-06-25 + +### Features + +- [network] Add `input` method to `TransactionResponse` ([#959](https://github.com/alloy-rs/alloy/issues/959)) + ## [0.1.2](https://github.com/alloy-rs/alloy/releases/tag/v0.1.2) - 2024-06-19 ### Documentation @@ -13,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Tasks +- Release 0.1.2 - Update changelogs for v0.1.1 ([#922](https://github.com/alloy-rs/alloy/issues/922)) - Add docs.rs metadata to all manifests ([#917](https://github.com/alloy-rs/alloy/issues/917)) diff --git a/crates/node-bindings/CHANGELOG.md b/crates/node-bindings/CHANGELOG.md index ec8e600ddd0..8b11d2d5e0a 100644 --- a/crates/node-bindings/CHANGELOG.md +++ b/crates/node-bindings/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Tasks +- Release 0.1.2 - Update changelogs for v0.1.1 ([#922](https://github.com/alloy-rs/alloy/issues/922)) - Add docs.rs metadata to all manifests ([#917](https://github.com/alloy-rs/alloy/issues/917)) diff --git a/crates/provider/CHANGELOG.md b/crates/provider/CHANGELOG.md index c4e2cd656c0..b3c708486ca 100644 --- a/crates/provider/CHANGELOG.md +++ b/crates/provider/CHANGELOG.md @@ -5,6 +5,20 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.3](https://github.com/alloy-rs/alloy/releases/tag/v0.1.3) - 2024-06-25 + +### Bug Fixes + +- Enable tls12 in rustls ([#952](https://github.com/alloy-rs/alloy/issues/952)) + +### Features + +- Add trace_filter method ([#946](https://github.com/alloy-rs/alloy/issues/946)) + +### Miscellaneous Tasks + +- Nightly clippy ([#947](https://github.com/alloy-rs/alloy/issues/947)) + ## [0.1.2](https://github.com/alloy-rs/alloy/releases/tag/v0.1.2) - 2024-06-19 ### Documentation @@ -20,6 +34,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Tasks +- Release 0.1.2 - Update changelogs for v0.1.1 ([#922](https://github.com/alloy-rs/alloy/issues/922)) - Add docs.rs metadata to all manifests ([#917](https://github.com/alloy-rs/alloy/issues/917)) diff --git a/crates/pubsub/CHANGELOG.md b/crates/pubsub/CHANGELOG.md index c1b9924859c..fbd967975cd 100644 --- a/crates/pubsub/CHANGELOG.md +++ b/crates/pubsub/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.3](https://github.com/alloy-rs/alloy/releases/tag/v0.1.3) - 2024-06-25 + +### Miscellaneous Tasks + +- Nightly clippy ([#947](https://github.com/alloy-rs/alloy/issues/947)) + ## [0.1.2](https://github.com/alloy-rs/alloy/releases/tag/v0.1.2) - 2024-06-19 ### Documentation @@ -13,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Tasks +- Release 0.1.2 - Update changelogs for v0.1.1 ([#922](https://github.com/alloy-rs/alloy/issues/922)) - Add docs.rs metadata to all manifests ([#917](https://github.com/alloy-rs/alloy/issues/917)) diff --git a/crates/rpc-client/CHANGELOG.md b/crates/rpc-client/CHANGELOG.md index ffbf41e1405..a46735095c8 100644 --- a/crates/rpc-client/CHANGELOG.md +++ b/crates/rpc-client/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Tasks +- Release 0.1.2 - Update changelogs for v0.1.1 ([#922](https://github.com/alloy-rs/alloy/issues/922)) - Add docs.rs metadata to all manifests ([#917](https://github.com/alloy-rs/alloy/issues/917)) diff --git a/crates/rpc-types-admin/CHANGELOG.md b/crates/rpc-types-admin/CHANGELOG.md index 46ff37cd71e..6aec957f3be 100644 --- a/crates/rpc-types-admin/CHANGELOG.md +++ b/crates/rpc-types-admin/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Tasks +- Release 0.1.2 - Update changelogs for v0.1.1 ([#922](https://github.com/alloy-rs/alloy/issues/922)) - Add docs.rs metadata to all manifests ([#917](https://github.com/alloy-rs/alloy/issues/917)) diff --git a/crates/rpc-types-anvil/CHANGELOG.md b/crates/rpc-types-anvil/CHANGELOG.md index f4d64f84424..1975790bc3b 100644 --- a/crates/rpc-types-anvil/CHANGELOG.md +++ b/crates/rpc-types-anvil/CHANGELOG.md @@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Tasks +- Release 0.1.2 - [rpc-types] Remove duplicate `Index` definition in `rpc-types-anvil` in favor of the one in `rpc-types-eth` ([#943](https://github.com/alloy-rs/alloy/issues/943)) - Update changelogs for v0.1.1 ([#922](https://github.com/alloy-rs/alloy/issues/922)) - Add docs.rs metadata to all manifests ([#917](https://github.com/alloy-rs/alloy/issues/917)) diff --git a/crates/rpc-types-beacon/CHANGELOG.md b/crates/rpc-types-beacon/CHANGELOG.md index 259a17b469e..c94997316e2 100644 --- a/crates/rpc-types-beacon/CHANGELOG.md +++ b/crates/rpc-types-beacon/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Tasks +- Release 0.1.2 - Update changelogs for v0.1.1 ([#922](https://github.com/alloy-rs/alloy/issues/922)) - Add docs.rs metadata to all manifests ([#917](https://github.com/alloy-rs/alloy/issues/917)) diff --git a/crates/rpc-types-engine/CHANGELOG.md b/crates/rpc-types-engine/CHANGELOG.md index dd7c29032ea..1bbd56d567a 100644 --- a/crates/rpc-types-engine/CHANGELOG.md +++ b/crates/rpc-types-engine/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.3](https://github.com/alloy-rs/alloy/releases/tag/v0.1.3) - 2024-06-25 + +### Miscellaneous Tasks + +- Nightly clippy ([#947](https://github.com/alloy-rs/alloy/issues/947)) + ## [0.1.2](https://github.com/alloy-rs/alloy/releases/tag/v0.1.2) - 2024-06-19 ### Documentation @@ -14,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Tasks +- Release 0.1.2 - Update changelogs for v0.1.1 ([#922](https://github.com/alloy-rs/alloy/issues/922)) - Add docs.rs metadata to all manifests ([#917](https://github.com/alloy-rs/alloy/issues/917)) diff --git a/crates/rpc-types-eth/CHANGELOG.md b/crates/rpc-types-eth/CHANGELOG.md index aa589422d9c..fd746b8cca5 100644 --- a/crates/rpc-types-eth/CHANGELOG.md +++ b/crates/rpc-types-eth/CHANGELOG.md @@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.3](https://github.com/alloy-rs/alloy/releases/tag/v0.1.3) - 2024-06-25 + +### Features + +- Add eip-7702 helpers ([#950](https://github.com/alloy-rs/alloy/issues/950)) +- [contract] Implement Filter's builder methods on Event ([#960](https://github.com/alloy-rs/alloy/issues/960)) + +### Miscellaneous Tasks + +- Nightly clippy ([#947](https://github.com/alloy-rs/alloy/issues/947)) + ## [0.1.2](https://github.com/alloy-rs/alloy/releases/tag/v0.1.2) - 2024-06-19 ### Documentation @@ -20,6 +31,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Tasks +- Release 0.1.2 - [rpc-types] Remove duplicate `Index` definition in `rpc-types-anvil` in favor of the one in `rpc-types-eth` ([#943](https://github.com/alloy-rs/alloy/issues/943)) - Update changelogs for v0.1.1 ([#922](https://github.com/alloy-rs/alloy/issues/922)) - Add docs.rs metadata to all manifests ([#917](https://github.com/alloy-rs/alloy/issues/917)) diff --git a/crates/rpc-types-mev/CHANGELOG.md b/crates/rpc-types-mev/CHANGELOG.md new file mode 100644 index 00000000000..ec900be7c2c --- /dev/null +++ b/crates/rpc-types-mev/CHANGELOG.md @@ -0,0 +1,75 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [0.1.3](https://github.com/alloy-rs/alloy/releases/tag/v0.1.3) - 2024-06-25 + +### Features + +- Move mev.rs from reth to rpc-types-mev ([#970](https://github.com/alloy-rs/alloy/issues/970)) + +[`alloy`]: https://crates.io/crates/alloy +[alloy]: https://crates.io/crates/alloy +[`alloy-core`]: https://crates.io/crates/alloy-core +[alloy-core]: https://crates.io/crates/alloy-core +[`alloy-consensus`]: https://crates.io/crates/alloy-consensus +[alloy-consensus]: https://crates.io/crates/alloy-consensus +[`alloy-contract`]: https://crates.io/crates/alloy-contract +[alloy-contract]: https://crates.io/crates/alloy-contract +[`alloy-eips`]: https://crates.io/crates/alloy-eips +[alloy-eips]: https://crates.io/crates/alloy-eips +[`alloy-genesis`]: https://crates.io/crates/alloy-genesis +[alloy-genesis]: https://crates.io/crates/alloy-genesis +[`alloy-json-rpc`]: https://crates.io/crates/alloy-json-rpc +[alloy-json-rpc]: https://crates.io/crates/alloy-json-rpc +[`alloy-network`]: https://crates.io/crates/alloy-network +[alloy-network]: https://crates.io/crates/alloy-network +[`alloy-node-bindings`]: https://crates.io/crates/alloy-node-bindings +[alloy-node-bindings]: https://crates.io/crates/alloy-node-bindings +[`alloy-provider`]: https://crates.io/crates/alloy-provider +[alloy-provider]: https://crates.io/crates/alloy-provider +[`alloy-pubsub`]: https://crates.io/crates/alloy-pubsub +[alloy-pubsub]: https://crates.io/crates/alloy-pubsub +[`alloy-rpc-client`]: https://crates.io/crates/alloy-rpc-client +[alloy-rpc-client]: https://crates.io/crates/alloy-rpc-client +[`alloy-rpc-types`]: https://crates.io/crates/alloy-rpc-types +[alloy-rpc-types]: https://crates.io/crates/alloy-rpc-types +[`alloy-rpc-types-anvil`]: https://crates.io/crates/alloy-rpc-types-anvil +[alloy-rpc-types-anvil]: https://crates.io/crates/alloy-rpc-types-anvil +[`alloy-rpc-types-beacon`]: https://crates.io/crates/alloy-rpc-types-beacon +[alloy-rpc-types-beacon]: https://crates.io/crates/alloy-rpc-types-beacon +[`alloy-rpc-types-engine`]: https://crates.io/crates/alloy-rpc-types-engine +[alloy-rpc-types-engine]: https://crates.io/crates/alloy-rpc-types-engine +[`alloy-rpc-types-eth`]: https://crates.io/crates/alloy-rpc-types-eth +[alloy-rpc-types-eth]: https://crates.io/crates/alloy-rpc-types-eth +[`alloy-rpc-types-trace`]: https://crates.io/crates/alloy-rpc-types-trace +[alloy-rpc-types-trace]: https://crates.io/crates/alloy-rpc-types-trace +[`alloy-serde`]: https://crates.io/crates/alloy-serde +[alloy-serde]: https://crates.io/crates/alloy-serde +[`alloy-signer`]: https://crates.io/crates/alloy-signer +[alloy-signer]: https://crates.io/crates/alloy-signer +[`alloy-signer-aws`]: https://crates.io/crates/alloy-signer-aws +[alloy-signer-aws]: https://crates.io/crates/alloy-signer-aws +[`alloy-signer-gcp`]: https://crates.io/crates/alloy-signer-gcp +[alloy-signer-gcp]: https://crates.io/crates/alloy-signer-gcp +[`alloy-signer-ledger`]: https://crates.io/crates/alloy-signer-ledger +[alloy-signer-ledger]: https://crates.io/crates/alloy-signer-ledger +[`alloy-signer-local`]: https://crates.io/crates/alloy-signer-local +[alloy-signer-local]: https://crates.io/crates/alloy-signer-local +[`alloy-signer-trezor`]: https://crates.io/crates/alloy-signer-trezor +[alloy-signer-trezor]: https://crates.io/crates/alloy-signer-trezor +[`alloy-signer-wallet`]: https://crates.io/crates/alloy-signer-wallet +[alloy-signer-wallet]: https://crates.io/crates/alloy-signer-wallet +[`alloy-transport`]: https://crates.io/crates/alloy-transport +[alloy-transport]: https://crates.io/crates/alloy-transport +[`alloy-transport-http`]: https://crates.io/crates/alloy-transport-http +[alloy-transport-http]: https://crates.io/crates/alloy-transport-http +[`alloy-transport-ipc`]: https://crates.io/crates/alloy-transport-ipc +[alloy-transport-ipc]: https://crates.io/crates/alloy-transport-ipc +[`alloy-transport-ws`]: https://crates.io/crates/alloy-transport-ws +[alloy-transport-ws]: https://crates.io/crates/alloy-transport-ws + + diff --git a/crates/rpc-types-trace/CHANGELOG.md b/crates/rpc-types-trace/CHANGELOG.md index ffc72e07c5d..26aafd6bec3 100644 --- a/crates/rpc-types-trace/CHANGELOG.md +++ b/crates/rpc-types-trace/CHANGELOG.md @@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Tasks +- Release 0.1.2 - Update changelogs for v0.1.1 ([#922](https://github.com/alloy-rs/alloy/issues/922)) - Add docs.rs metadata to all manifests ([#917](https://github.com/alloy-rs/alloy/issues/917)) diff --git a/crates/rpc-types-txpool/CHANGELOG.md b/crates/rpc-types-txpool/CHANGELOG.md index 46ff37cd71e..6aec957f3be 100644 --- a/crates/rpc-types-txpool/CHANGELOG.md +++ b/crates/rpc-types-txpool/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Tasks +- Release 0.1.2 - Update changelogs for v0.1.1 ([#922](https://github.com/alloy-rs/alloy/issues/922)) - Add docs.rs metadata to all manifests ([#917](https://github.com/alloy-rs/alloy/issues/917)) diff --git a/crates/rpc-types/CHANGELOG.md b/crates/rpc-types/CHANGELOG.md index 1a27539b74d..73e4b793392 100644 --- a/crates/rpc-types/CHANGELOG.md +++ b/crates/rpc-types/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.3](https://github.com/alloy-rs/alloy/releases/tag/v0.1.3) - 2024-06-25 + +### Features + +- Move mev.rs from reth to rpc-types-mev ([#970](https://github.com/alloy-rs/alloy/issues/970)) + ## [0.1.2](https://github.com/alloy-rs/alloy/releases/tag/v0.1.2) - 2024-06-19 ### Documentation @@ -14,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Tasks +- Release 0.1.2 - Update changelogs for v0.1.1 ([#922](https://github.com/alloy-rs/alloy/issues/922)) - Use 'dep:' syntax in rpc-types ([#921](https://github.com/alloy-rs/alloy/issues/921)) - Add docs.rs metadata to all manifests ([#917](https://github.com/alloy-rs/alloy/issues/917)) diff --git a/crates/serde/CHANGELOG.md b/crates/serde/CHANGELOG.md index eebc8ee1237..cc33d5b7dc1 100644 --- a/crates/serde/CHANGELOG.md +++ b/crates/serde/CHANGELOG.md @@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.3](https://github.com/alloy-rs/alloy/releases/tag/v0.1.3) - 2024-06-25 + +### Bug Fixes + +- Deserialization of null storage keys in AccessListItem ([#955](https://github.com/alloy-rs/alloy/issues/955)) + +### Miscellaneous Tasks + +- Nightly clippy ([#947](https://github.com/alloy-rs/alloy/issues/947)) + ## [0.1.2](https://github.com/alloy-rs/alloy/releases/tag/v0.1.2) - 2024-06-19 ### Documentation @@ -13,6 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Tasks +- Release 0.1.2 - Update changelogs for v0.1.1 ([#922](https://github.com/alloy-rs/alloy/issues/922)) - Add docs.rs metadata to all manifests ([#917](https://github.com/alloy-rs/alloy/issues/917)) diff --git a/crates/signer-aws/CHANGELOG.md b/crates/signer-aws/CHANGELOG.md index 6f039df14ff..ea54ba6d9fd 100644 --- a/crates/signer-aws/CHANGELOG.md +++ b/crates/signer-aws/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Tasks +- Release 0.1.2 - Update changelogs for v0.1.1 ([#922](https://github.com/alloy-rs/alloy/issues/922)) - Add docs.rs metadata to all manifests ([#917](https://github.com/alloy-rs/alloy/issues/917)) diff --git a/crates/signer-gcp/CHANGELOG.md b/crates/signer-gcp/CHANGELOG.md index 239a3cf9203..f46e35e59a2 100644 --- a/crates/signer-gcp/CHANGELOG.md +++ b/crates/signer-gcp/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Tasks +- Release 0.1.2 - Update changelogs for v0.1.1 ([#922](https://github.com/alloy-rs/alloy/issues/922)) - Add docs.rs metadata to all manifests ([#917](https://github.com/alloy-rs/alloy/issues/917)) diff --git a/crates/signer-ledger/CHANGELOG.md b/crates/signer-ledger/CHANGELOG.md index 811d206b949..426a78b7c50 100644 --- a/crates/signer-ledger/CHANGELOG.md +++ b/crates/signer-ledger/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Tasks +- Release 0.1.2 - Update changelogs for v0.1.1 ([#922](https://github.com/alloy-rs/alloy/issues/922)) - Add docs.rs metadata to all manifests ([#917](https://github.com/alloy-rs/alloy/issues/917)) diff --git a/crates/signer-local/CHANGELOG.md b/crates/signer-local/CHANGELOG.md index 34a8450f92e..3fc93245d5e 100644 --- a/crates/signer-local/CHANGELOG.md +++ b/crates/signer-local/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Tasks +- Release 0.1.2 - Update changelogs for v0.1.1 ([#922](https://github.com/alloy-rs/alloy/issues/922)) - Add docs.rs metadata to all manifests ([#917](https://github.com/alloy-rs/alloy/issues/917)) diff --git a/crates/signer-trezor/CHANGELOG.md b/crates/signer-trezor/CHANGELOG.md index 7acf50dc245..9cb0a703cc0 100644 --- a/crates/signer-trezor/CHANGELOG.md +++ b/crates/signer-trezor/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Tasks +- Release 0.1.2 - Update changelogs for v0.1.1 ([#922](https://github.com/alloy-rs/alloy/issues/922)) - Add docs.rs metadata to all manifests ([#917](https://github.com/alloy-rs/alloy/issues/917)) diff --git a/crates/signer/CHANGELOG.md b/crates/signer/CHANGELOG.md index 8292b2ea790..b5935eba53b 100644 --- a/crates/signer/CHANGELOG.md +++ b/crates/signer/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Tasks +- Release 0.1.2 - Update changelogs for v0.1.1 ([#922](https://github.com/alloy-rs/alloy/issues/922)) - Add docs.rs metadata to all manifests ([#917](https://github.com/alloy-rs/alloy/issues/917)) diff --git a/crates/transport-http/CHANGELOG.md b/crates/transport-http/CHANGELOG.md index a338cafcf72..91abd52d575 100644 --- a/crates/transport-http/CHANGELOG.md +++ b/crates/transport-http/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Tasks +- Release 0.1.2 - Update changelogs for v0.1.1 ([#922](https://github.com/alloy-rs/alloy/issues/922)) - Add docs.rs metadata to all manifests ([#917](https://github.com/alloy-rs/alloy/issues/917)) diff --git a/crates/transport-ipc/CHANGELOG.md b/crates/transport-ipc/CHANGELOG.md index 097967fc2e5..fb906b5131b 100644 --- a/crates/transport-ipc/CHANGELOG.md +++ b/crates/transport-ipc/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.3](https://github.com/alloy-rs/alloy/releases/tag/v0.1.3) - 2024-06-25 + +### Bug Fixes + +- Continue reading ipc on large data ([#958](https://github.com/alloy-rs/alloy/issues/958)) + ## [0.1.2](https://github.com/alloy-rs/alloy/releases/tag/v0.1.2) - 2024-06-19 ### Documentation @@ -13,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Tasks +- Release 0.1.2 - Update changelogs for v0.1.1 ([#922](https://github.com/alloy-rs/alloy/issues/922)) - Add docs.rs metadata to all manifests ([#917](https://github.com/alloy-rs/alloy/issues/917)) diff --git a/crates/transport-ws/CHANGELOG.md b/crates/transport-ws/CHANGELOG.md index 526f40e688c..3e8ed01c54f 100644 --- a/crates/transport-ws/CHANGELOG.md +++ b/crates/transport-ws/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Tasks +- Release 0.1.2 - Update changelogs for v0.1.1 ([#922](https://github.com/alloy-rs/alloy/issues/922)) - Add docs.rs metadata to all manifests ([#917](https://github.com/alloy-rs/alloy/issues/917)) diff --git a/crates/transport/CHANGELOG.md b/crates/transport/CHANGELOG.md index 74b4aee043e..f8c97d57177 100644 --- a/crates/transport/CHANGELOG.md +++ b/crates/transport/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Tasks +- Release 0.1.2 - Update changelogs for v0.1.1 ([#922](https://github.com/alloy-rs/alloy/issues/922)) - Add docs.rs metadata to all manifests ([#917](https://github.com/alloy-rs/alloy/issues/917)) From 02f375edb3537643498872ece7ee7084319f9835 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Tue, 25 Jun 2024 21:25:09 +0200 Subject: [PATCH 19/61] chore: release 0.1.3 --- CHANGELOG.md | 1 + crates/eip7547/CHANGELOG.md | 1 + crates/rpc-types-mev/CHANGELOG.md | 4 ++++ crates/rpc-types/CHANGELOG.md | 4 ++++ crates/signer-aws/CHANGELOG.md | 6 ++++++ crates/signer-gcp/CHANGELOG.md | 6 ++++++ crates/signer-ledger/CHANGELOG.md | 6 ++++++ crates/signer-trezor/CHANGELOG.md | 6 ++++++ 8 files changed, 34 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6773cbf84fa..d735220189d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Tasks +- Release 0.1.3 - [eips] Add serde to Authorization types ([#964](https://github.com/alloy-rs/alloy/issues/964)) - Add more features to meta crate ([#953](https://github.com/alloy-rs/alloy/issues/953)) - [eips] Make `sha2` optional, add `kzg-sidecar` feature ([#949](https://github.com/alloy-rs/alloy/issues/949)) diff --git a/crates/eip7547/CHANGELOG.md b/crates/eip7547/CHANGELOG.md index c588af71a9d..0e3ac20f9db 100644 --- a/crates/eip7547/CHANGELOG.md +++ b/crates/eip7547/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Tasks +- Release 0.1.3 - Nightly clippy ([#947](https://github.com/alloy-rs/alloy/issues/947)) ## [0.1.2](https://github.com/alloy-rs/alloy/releases/tag/v0.1.2) - 2024-06-19 diff --git a/crates/rpc-types-mev/CHANGELOG.md b/crates/rpc-types-mev/CHANGELOG.md index ec900be7c2c..73eda090361 100644 --- a/crates/rpc-types-mev/CHANGELOG.md +++ b/crates/rpc-types-mev/CHANGELOG.md @@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Move mev.rs from reth to rpc-types-mev ([#970](https://github.com/alloy-rs/alloy/issues/970)) +### Miscellaneous Tasks + +- Release 0.1.3 + [`alloy`]: https://crates.io/crates/alloy [alloy]: https://crates.io/crates/alloy [`alloy-core`]: https://crates.io/crates/alloy-core diff --git a/crates/rpc-types/CHANGELOG.md b/crates/rpc-types/CHANGELOG.md index 73e4b793392..8b3a6ae4b31 100644 --- a/crates/rpc-types/CHANGELOG.md +++ b/crates/rpc-types/CHANGELOG.md @@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Move mev.rs from reth to rpc-types-mev ([#970](https://github.com/alloy-rs/alloy/issues/970)) +### Miscellaneous Tasks + +- Release 0.1.3 + ## [0.1.2](https://github.com/alloy-rs/alloy/releases/tag/v0.1.2) - 2024-06-19 ### Documentation diff --git a/crates/signer-aws/CHANGELOG.md b/crates/signer-aws/CHANGELOG.md index ea54ba6d9fd..32b9089896d 100644 --- a/crates/signer-aws/CHANGELOG.md +++ b/crates/signer-aws/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.3](https://github.com/alloy-rs/alloy/releases/tag/v0.1.3) - 2024-06-25 + +### Miscellaneous Tasks + +- Release 0.1.3 + ## [0.1.2](https://github.com/alloy-rs/alloy/releases/tag/v0.1.2) - 2024-06-19 ### Documentation diff --git a/crates/signer-gcp/CHANGELOG.md b/crates/signer-gcp/CHANGELOG.md index f46e35e59a2..84358b96dd9 100644 --- a/crates/signer-gcp/CHANGELOG.md +++ b/crates/signer-gcp/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.3](https://github.com/alloy-rs/alloy/releases/tag/v0.1.3) - 2024-06-25 + +### Miscellaneous Tasks + +- Release 0.1.3 + ## [0.1.2](https://github.com/alloy-rs/alloy/releases/tag/v0.1.2) - 2024-06-19 ### Documentation diff --git a/crates/signer-ledger/CHANGELOG.md b/crates/signer-ledger/CHANGELOG.md index 426a78b7c50..6eb4709c0c5 100644 --- a/crates/signer-ledger/CHANGELOG.md +++ b/crates/signer-ledger/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.3](https://github.com/alloy-rs/alloy/releases/tag/v0.1.3) - 2024-06-25 + +### Miscellaneous Tasks + +- Release 0.1.3 + ## [0.1.2](https://github.com/alloy-rs/alloy/releases/tag/v0.1.2) - 2024-06-19 ### Documentation diff --git a/crates/signer-trezor/CHANGELOG.md b/crates/signer-trezor/CHANGELOG.md index 9cb0a703cc0..693fec3842e 100644 --- a/crates/signer-trezor/CHANGELOG.md +++ b/crates/signer-trezor/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.3](https://github.com/alloy-rs/alloy/releases/tag/v0.1.3) - 2024-06-25 + +### Miscellaneous Tasks + +- Release 0.1.3 + ## [0.1.2](https://github.com/alloy-rs/alloy/releases/tag/v0.1.2) - 2024-06-19 ### Documentation From 38ace64a1b7c18ff05dc2288f33acbf4798b1e8b Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Tue, 25 Jun 2024 21:31:50 +0200 Subject: [PATCH 20/61] chore: release 0.1.3 (-p alloy) --- CHANGELOG.md | 1 + crates/alloy/CHANGELOG.md | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d735220189d..aa616268db1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Tasks +- Release 0.1.3 - Release 0.1.3 - [eips] Add serde to Authorization types ([#964](https://github.com/alloy-rs/alloy/issues/964)) - Add more features to meta crate ([#953](https://github.com/alloy-rs/alloy/issues/953)) diff --git a/crates/alloy/CHANGELOG.md b/crates/alloy/CHANGELOG.md index 9b648e63be1..3ba912ad7f0 100644 --- a/crates/alloy/CHANGELOG.md +++ b/crates/alloy/CHANGELOG.md @@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.3](https://github.com/alloy-rs/alloy/releases/tag/v0.1.3) - 2024-06-25 + +### Features + +- [alloy] Forward `rustls` & `native` reqwest TLS configuration to Alloy's metacrate ([#969](https://github.com/alloy-rs/alloy/issues/969)) +- Add eip-7702 helpers ([#950](https://github.com/alloy-rs/alloy/issues/950)) + +### Miscellaneous Tasks + +- Add more features to meta crate ([#953](https://github.com/alloy-rs/alloy/issues/953)) + ## [0.1.2](https://github.com/alloy-rs/alloy/releases/tag/v0.1.2) - 2024-06-19 ### Documentation @@ -13,6 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Tasks +- Release 0.1.2 - Update changelogs for v0.1.1 ([#922](https://github.com/alloy-rs/alloy/issues/922)) - Add docs.rs metadata to all manifests ([#917](https://github.com/alloy-rs/alloy/issues/917)) From 67881cbc3502472da5befe707f50560002c50d99 Mon Sep 17 00:00:00 2001 From: Thomas Coratger <60488569+tcoratger@users.noreply.github.com> Date: Tue, 25 Jun 2024 22:08:20 +0200 Subject: [PATCH 21/61] add range test in `FilterBlockOption` (#939) * add range test in FilterBlockOption * fix comments * fix comments * fix comments --- crates/rpc-types-eth/src/filter.rs | 53 ++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/crates/rpc-types-eth/src/filter.rs b/crates/rpc-types-eth/src/filter.rs index 7b0a3b8bc0d..19f92f91411 100644 --- a/crates/rpc-types-eth/src/filter.rs +++ b/crates/rpc-types-eth/src/filter.rs @@ -14,6 +14,7 @@ use std::{ hash::Hash, ops::{Range, RangeFrom, RangeTo}, }; +use thiserror::Error; /// Helper type to represent a bloom filter used for matching logs. #[derive(Debug, Default)] @@ -152,6 +153,19 @@ impl From for Topic { } } +/// Represents errors that can occur when setting block filters in `FilterBlockOption`. +#[derive(Debug, PartialEq, Eq, Error)] +pub enum FilterBlockError { + /// Error indicating that the `from_block` is greater than the `to_block`. + #[error("`from_block` ({from}) is greater than `to_block` ({to})")] + FromBlockGreaterThanToBlock { + /// The starting block number, which is greater than `to`. + from: u64, + /// The ending block number, which is less than `from`. + to: u64, + }, +} + /// Represents the target range of blocks for the filter #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub enum FilterBlockOption { @@ -211,6 +225,20 @@ impl FilterBlockOption { matches!(self, Self::AtBlockHash(_)) } + /// Ensure block range validity + pub fn ensure_valid_block_range(&self) -> Result<(), FilterBlockError> { + // Check if from_block is greater than to_block + if let (Some(from), Some(to)) = ( + self.get_from_block().as_ref().and_then(|from| from.as_number()), + self.get_to_block().as_ref().and_then(|to| to.as_number()), + ) { + if from > to { + return Err(FilterBlockError::FromBlockGreaterThanToBlock { from, to }); + } + } + Ok(()) + } + /// Sets the block number this range filter should start at. #[must_use] pub fn with_from_block(&self, block: BlockNumberOrTag) -> Self { @@ -1152,6 +1180,31 @@ mod tests { ); } + #[test] + fn test_with_from_block_correct_range() { + // Test scenario where from_block is less than to_block + let original = FilterBlockOption::Range { + from_block: Some(BlockNumberOrTag::Number(1)), + to_block: Some(BlockNumberOrTag::Number(10)), + }; + let updated = original.with_from_block(BlockNumberOrTag::Number(5)); + assert!(updated.ensure_valid_block_range().is_ok()); + } + + #[test] + fn test_with_from_block_failure() { + // Test scenario where from_block is greater than to_block + let original = FilterBlockOption::Range { + from_block: Some(BlockNumberOrTag::Number(10)), + to_block: Some(BlockNumberOrTag::Number(5)), + }; + + assert!(matches!( + original.ensure_valid_block_range(), + Err(FilterBlockError::FromBlockGreaterThanToBlock { .. }) + )); + } + #[test] fn test_block_hash() { let s = From 5be0002f935a6a3f43515be111c23586ceb95477 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Wed, 26 Jun 2024 00:32:14 +0200 Subject: [PATCH 22/61] docs: add release checklist (#972) --- RELEASE_CHECKLIST.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 RELEASE_CHECKLIST.md diff --git a/RELEASE_CHECKLIST.md b/RELEASE_CHECKLIST.md new file mode 100644 index 00000000000..c87a139fa76 --- /dev/null +++ b/RELEASE_CHECKLIST.md @@ -0,0 +1,26 @@ +# Release checklist + +This checklist is meant to be used as a guide for the `crates.io` release process. + +Releases are always made in lockstep, meaning that all crates in the repository +are released with the same version number, regardless of whether they have +changed or not. + +## Requirements + +- [cargo-release](https://github.com/crate-ci/cargo-release): `cargo install cargo-release` +- [git-cliff](https://github.com/orhun/git-cliff) (patched with [orhun/git-cliff#711](https://github.com/orhun/git-cliff/pull/711)): `cargo install --git https://github.com/DaniPopes/git-cliff.git --branch fix-include-paths git-cliff` + +## Steps + +- [ ] Make sure you're on the `main` branch. +- [ ] (optional) Dry run `cargo-release`: `cargo release ` +- [ ] Run `cargo-release`: `PUBLISH_GRACE_SLEEP=10 cargo release --rate-limit.existing-packages 50 [--no-verify]` + - Ignore these warnings: + - `warning: updating to despite no changes made since...` + - `git-cliff` warning `there is already a tag () for ...` + - [ ] If a failure happened: + - [ ] You should have an unpushed commit. After the issue is fixed, retry the release process with `--no-push` and squash the commits together. + - [ ] If some crates were published before the error, AFAICT you must manually `--exclude ` each already-published crate. + - [ ] Verify that the commit is correct, and push to the repository with `git push --tags`. +- [ ] Create a new GitHub release with the automatically generated changelog and with the name set to ` v` From 1936907a444ab510911411daaec852ce52f33aa2 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Wed, 26 Jun 2024 00:57:48 +0200 Subject: [PATCH 23/61] chore(deps): remove reqwest and hyper from meta crate (#974) --- crates/alloy/Cargo.toml | 16 ++++------------ crates/alloy/src/lib.rs | 6 ------ 2 files changed, 4 insertions(+), 18 deletions(-) diff --git a/crates/alloy/Cargo.toml b/crates/alloy/Cargo.toml index e6c2ba9e3f9..2add14fb29b 100644 --- a/crates/alloy/Cargo.toml +++ b/crates/alloy/Cargo.toml @@ -58,10 +58,6 @@ alloy-transport-http = { workspace = true, optional = true } alloy-transport-ipc = { workspace = true, optional = true } alloy-transport-ws = { workspace = true, optional = true } -# optional -reqwest = { workspace = true, optional = true } -hyper = { workspace = true, optional = true } - # ----------------------------------------- Configuration ---------------------------------------- # [features] @@ -85,36 +81,32 @@ full = [ "kzg", "network", "provider-http", # includes `providers` - "provider-ws", # includes `providers` - "provider-ipc", # includes `providers` - "rpc-types", # includes `rpc-types-eth` - "signer-local", # includes `signers` + "provider-ws", # includes `providers` + "provider-ipc", # includes `providers` + "rpc-types", # includes `rpc-types-eth` + "signer-local", # includes `signers` ] # configuration reqwest = [ - "dep:reqwest", "alloy-rpc-client?/reqwest", "alloy-provider?/reqwest", "alloy-transport-http?/reqwest", "alloy-transport-http?/reqwest-default-tls", ] reqwest-rustls-tls = [ - "dep:reqwest", "alloy-rpc-client?/reqwest", "alloy-provider?/reqwest", "alloy-transport-http?/reqwest", "alloy-transport-http?/reqwest-rustls-tls", ] reqwest-native-tls = [ - "dep:reqwest", "alloy-rpc-client?/reqwest", "alloy-provider?/reqwest", "alloy-transport-http?/reqwest", "alloy-transport-http?/reqwest-native-tls", ] hyper = [ - "dep:hyper", "alloy-rpc-client?/hyper", "alloy-provider?/hyper", "alloy-transport-http?/hyper", diff --git a/crates/alloy/src/lib.rs b/crates/alloy/src/lib.rs index c72ef783f22..be4a3114ca5 100644 --- a/crates/alloy/src/lib.rs +++ b/crates/alloy/src/lib.rs @@ -56,12 +56,6 @@ macro_rules! sol { /* --------------------------------------- Main re-exports -------------------------------------- */ -#[cfg(feature = "reqwest")] -use reqwest as _; - -#[cfg(feature = "hyper")] -use hyper as _; - #[cfg(feature = "contract")] #[doc(inline)] pub use alloy_contract as contract; From a48e71a18b48d60942e7d7fc84489f9ddc29a608 Mon Sep 17 00:00:00 2001 From: jn Date: Wed, 26 Jun 2024 01:26:04 -0700 Subject: [PATCH 24/61] dev(hotfix): typo change pub(crate) to pub (#979) --- crates/rpc-types-mev/src/eth_calls.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/crates/rpc-types-mev/src/eth_calls.rs b/crates/rpc-types-mev/src/eth_calls.rs index cfdc3cb19b1..1b832bb4a98 100644 --- a/crates/rpc-types-mev/src/eth_calls.rs +++ b/crates/rpc-types-mev/src/eth_calls.rs @@ -108,32 +108,32 @@ pub struct CancelPrivateTransactionRequest { /// #[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub(crate) struct EthSendBundle { +pub struct EthSendBundle { /// A list of hex-encoded signed transactions - pub(crate) txs: Vec, + pub txs: Vec, /// hex-encoded block number for which this bundle is valid #[serde(with = "alloy_serde::quantity")] - pub(crate) block_number: u64, + pub block_number: u64, /// unix timestamp when this bundle becomes active #[serde(default, with = "alloy_serde::quantity::opt", skip_serializing_if = "Option::is_none")] - pub(crate) min_timestamp: Option, + pub min_timestamp: Option, /// unix timestamp how long this bundle stays valid #[serde(default, with = "alloy_serde::quantity::opt", skip_serializing_if = "Option::is_none")] - pub(crate) max_timestamp: Option, + pub max_timestamp: Option, /// list of hashes of possibly reverting txs #[serde(default, skip_serializing_if = "Vec::is_empty")] - pub(crate) reverting_tx_hashes: Vec, + pub reverting_tx_hashes: Vec, /// UUID that can be used to cancel/replace this bundle #[serde(default, rename = "replacementUuid", skip_serializing_if = "Option::is_none")] - pub(crate) replacement_uuid: Option, + pub replacement_uuid: Option, } /// Response from the matchmaker after sending a bundle. #[derive(Deserialize, Debug, Serialize, Clone, PartialEq, Eq)] #[serde(rename_all = "camelCase")] -pub(crate) struct EthBundleHash { +pub struct EthBundleHash { /// Hash of the bundle bodies. - pub(crate) bundle_hash: B256, + pub bundle_hash: B256, } /// Response from the matchmaker after sending a bundle. From 8748f9b5f3faa05d7ea56a5ad9e49c97ce495d5b Mon Sep 17 00:00:00 2001 From: "tu-do.ron" Date: Wed, 26 Jun 2024 16:31:45 +0700 Subject: [PATCH 25/61] fix(signer-trezor): fix zero gas price when sending legacy tx with trezor (#977) fix(signer-trezor): fix zero gas price for legacy tx --- crates/signer-trezor/src/signer.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/signer-trezor/src/signer.rs b/crates/signer-trezor/src/signer.rs index d2fd1d79de8..f20305fc1e7 100644 --- a/crates/signer-trezor/src/signer.rs +++ b/crates/signer-trezor/src/signer.rs @@ -170,7 +170,7 @@ impl TrezorSigner { let nonce = tx.nonce(); let nonce = u64_to_trezor(nonce); - let gas_price = 0_u128; + let gas_price = tx.gas_price().unwrap_or(0); let gas_price = u128_to_trezor(gas_price); let gas_limit = tx.gas_limit(); From 761909b7cab8cc131ac22a6095f70686b113e2fa Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Wed, 26 Jun 2024 13:45:14 +0200 Subject: [PATCH 26/61] feat: add missing eth bundle args (#978) --- crates/rpc-types-mev/src/eth_calls.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/crates/rpc-types-mev/src/eth_calls.rs b/crates/rpc-types-mev/src/eth_calls.rs index 1b832bb4a98..b7f6dc66984 100644 --- a/crates/rpc-types-mev/src/eth_calls.rs +++ b/crates/rpc-types-mev/src/eth_calls.rs @@ -7,6 +7,7 @@ use serde::{Deserialize, Serialize}; /// Bundle of transactions for `eth_callBundle` /// /// +/// #[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct EthCallBundle { @@ -20,6 +21,15 @@ pub struct EthCallBundle { /// the timestamp to use for this bundle simulation, in seconds since the unix epoch #[serde(default, with = "alloy_serde::quantity::opt", skip_serializing_if = "Option::is_none")] pub timestamp: Option, + /// gas limit of the block to use for this simulation + #[serde(default, with = "alloy_serde::quantity::opt", skip_serializing_if = "Option::is_none")] + pub gas_limit: Option, + /// difficulty of the block to use for this simulation + #[serde(default, skip_serializing_if = "Option::is_none")] + pub difficulty: Option, + /// basefee of the block to use for this simulation + #[serde(default, with = "alloy_serde::quantity::opt", skip_serializing_if = "Option::is_none")] + pub base_fee: Option, } /// Response for `eth_callBundle` From b17baf30e359df41e8b074a66c31b31454fae710 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Wed, 26 Jun 2024 14:15:52 +0200 Subject: [PATCH 27/61] chore(provider): simplify nonce filler (#976) --- crates/provider/src/fillers/nonce.rs | 94 ++++++++++++++++++++++------ 1 file changed, 74 insertions(+), 20 deletions(-) diff --git a/crates/provider/src/fillers/nonce.rs b/crates/provider/src/fillers/nonce.rs index 237cb7d9583..ad9f0aa60f8 100644 --- a/crates/provider/src/fillers/nonce.rs +++ b/crates/provider/src/fillers/nonce.rs @@ -7,8 +7,8 @@ use alloy_network::{Network, TransactionBuilder}; use alloy_primitives::Address; use alloy_transport::{Transport, TransportResult}; use dashmap::DashMap; +use futures::lock::Mutex; use std::sync::Arc; -use tokio::sync::Mutex; /// A [`TxFiller`] that fills nonces on transactions. /// @@ -41,7 +41,7 @@ use tokio::sync::Mutex; /// ``` #[derive(Clone, Debug, Default)] pub struct NonceFiller { - nonces: DashMap>>>, + nonces: DashMap>>, } impl TxFiller for NonceFiller { @@ -86,29 +86,31 @@ impl TxFiller for NonceFiller { impl NonceFiller { /// Get the next nonce for the given account. - async fn get_next_nonce(&self, provider: &P, from: Address) -> TransportResult + async fn get_next_nonce(&self, provider: &P, address: Address) -> TransportResult where P: Provider, N: Network, T: Transport + Clone, { - // locks dashmap internally for a short duration to clone the `Arc` - let mutex = Arc::clone(self.nonces.entry(from).or_default().value()); - - // locks the value (does not lock dashmap) - let mut nonce = mutex.lock().await; - match *nonce { - Some(ref mut nonce) => { - *nonce += 1; - Ok(*nonce) - } - None => { - // initialize the nonce if we haven't seen this account before - let initial_nonce = provider.get_transaction_count(from).await?; - *nonce = Some(initial_nonce); - Ok(initial_nonce) - } - } + // Use `u64::MAX` as a sentinel value to indicate that the nonce has not been fetched yet. + const NONE: u64 = u64::MAX; + + // Locks dashmap internally for a short duration to clone the `Arc`. + // We also don't want to hold the dashmap lock through the await point below. + let nonce = { + let rm = self.nonces.entry(address).or_insert_with(|| Arc::new(Mutex::new(NONE))); + Arc::clone(rm.value()) + }; + + let mut nonce = nonce.lock().await; + let new_nonce = if *nonce == NONE { + // Initialize the nonce if we haven't seen this account before. + provider.get_transaction_count(address).await? + } else { + *nonce + 1 + }; + *nonce = new_nonce; + Ok(new_nonce) } } @@ -119,6 +121,58 @@ mod tests { use alloy_primitives::{address, U256}; use alloy_rpc_types_eth::TransactionRequest; + async fn check_nonces(filler: &NonceFiller, provider: &P, address: Address, start: u64) + where + P: Provider, + N: Network, + T: Transport + Clone, + { + for i in start..start + 5 { + let nonce = filler.get_next_nonce(&provider, address).await.unwrap(); + assert_eq!(nonce, i); + } + } + + #[tokio::test] + async fn smoke_test() { + let filler = NonceFiller::default(); + let provider = ProviderBuilder::new().on_anvil(); + let address = Address::ZERO; + check_nonces(&filler, &provider, address, 0).await; + + #[cfg(feature = "anvil-api")] + { + use crate::ext::AnvilApi; + filler.nonces.clear(); + provider.anvil_set_nonce(address, U256::from(69)).await.unwrap(); + check_nonces(&filler, &provider, address, 69).await; + } + } + + #[tokio::test] + async fn concurrency() { + let filler = Arc::new(NonceFiller::default()); + let provider = Arc::new(ProviderBuilder::new().on_anvil()); + let address = Address::ZERO; + let tasks = (0..5) + .map(|_| { + let filler = Arc::clone(&filler); + let provider = Arc::clone(&provider); + tokio::spawn(async move { filler.get_next_nonce(&provider, address).await }) + }) + .collect::>(); + + let mut ns = Vec::new(); + for task in tasks { + ns.push(task.await.unwrap().unwrap()); + } + ns.sort_unstable(); + assert_eq!(ns, (0..5).collect::>()); + + assert_eq!(filler.nonces.len(), 1); + assert_eq!(*filler.nonces.get(&address).unwrap().value().lock().await, 4); + } + #[tokio::test] async fn no_nonce_if_sender_unset() { let provider = ProviderBuilder::new().with_nonce_management().on_anvil(); From 13766837d4b366675fe400232f9408b3c67c807b Mon Sep 17 00:00:00 2001 From: Thomas Coratger <60488569+tcoratger@users.noreply.github.com> Date: Wed, 26 Jun 2024 15:52:47 +0200 Subject: [PATCH 28/61] feat: impl `From` for `BlockHashOrNumber` (#980) feat: impl From for BlockHashOrNumber --- crates/eips/src/eip1898.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crates/eips/src/eip1898.rs b/crates/eips/src/eip1898.rs index e73a66138cc..1ff070f2ff3 100644 --- a/crates/eips/src/eip1898.rs +++ b/crates/eips/src/eip1898.rs @@ -658,6 +658,12 @@ impl From for BlockHashOrNumber { } } +impl From for BlockHashOrNumber { + fn from(value: RpcBlockHash) -> Self { + Self::Hash(value.into()) + } +} + /// Allows for RLP encoding of either a block hash or block number impl Encodable for BlockHashOrNumber { fn encode(&self, out: &mut dyn bytes::BufMut) { From 60cd429bd036c16f1e1f23ec7950689ad9819c76 Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Wed, 26 Jun 2024 22:36:21 +0200 Subject: [PATCH 29/61] feat: add helpers for trace action (#982) --- crates/rpc-types-trace/src/parity.rs | 35 +++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/crates/rpc-types-trace/src/parity.rs b/crates/rpc-types-trace/src/parity.rs index 55feda41208..caadcd18cc9 100644 --- a/crates/rpc-types-trace/src/parity.rs +++ b/crates/rpc-types-trace/src/parity.rs @@ -10,10 +10,11 @@ use std::{ }; /// Different Trace diagnostic targets. -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub enum TraceType { /// Default trace + #[default] Trace, /// Provides a full trace of the VM’s state throughout the execution of the transaction, /// including for any subcalls. @@ -199,6 +200,38 @@ impl Action { matches!(self, Self::Reward(_)) } + /// Returns the [`CallAction`] if it is [`Action::Call`] + pub const fn as_call(&self) -> Option<&CallAction> { + match self { + Self::Call(action) => Some(action), + _ => None, + } + } + + /// Returns the [`CreateAction`] if it is [`Action::Create`] + pub const fn as_create(&self) -> Option<&CreateAction> { + match self { + Self::Create(action) => Some(action), + _ => None, + } + } + + /// Returns the [`SelfdestructAction`] if it is [`Action::Selfdestruct`] + pub const fn as_selfdestruct(&self) -> Option<&SelfdestructAction> { + match self { + Self::Selfdestruct(action) => Some(action), + _ => None, + } + } + + /// Returns the [`RewardAction`] if it is [`Action::Reward`] + pub const fn as_reward(&self) -> Option<&RewardAction> { + match self { + Self::Reward(action) => Some(action), + _ => None, + } + } + /// Returns what kind of action this is pub const fn kind(&self) -> ActionType { match self { From 097e21a607395fc9a496d620c14934a736989e14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien?= <3535019+leruaa@users.noreply.github.com> Date: Thu, 27 Jun 2024 12:52:56 +0200 Subject: [PATCH 30/61] Allow to convert CallBuilderTo TransactionRequest (#981) feat: allow to convert CallBuilderTo TransactionRequest --- crates/contract/src/call.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/crates/contract/src/call.rs b/crates/contract/src/call.rs index 8ea9ce6c358..77ba97815a2 100644 --- a/crates/contract/src/call.rs +++ b/crates/contract/src/call.rs @@ -131,6 +131,13 @@ pub struct CallBuilder { transport: PhantomData, } +impl CallBuilder { + /// Converts the call builder to the inner transaction request + pub fn into_transaction_request(self) -> N::TransactionRequest { + self.request + } +} + impl AsRef for CallBuilder { fn as_ref(&self) -> &N::TransactionRequest { &self.request From 3cc55dea1c13188d3d734eede908b969cb956da0 Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Fri, 28 Jun 2024 13:11:18 +0200 Subject: [PATCH 31/61] feat: add into transactions iterator (#984) --- crates/rpc-types-eth/src/block.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/crates/rpc-types-eth/src/block.rs b/crates/rpc-types-eth/src/block.rs index 1ebf0332bad..c69b1d45084 100644 --- a/crates/rpc-types-eth/src/block.rs +++ b/crates/rpc-types-eth/src/block.rs @@ -190,6 +190,8 @@ impl BlockTransactions { } /// Fallibly cast to a slice of transactions. + /// + /// Returns `None` if the enum variant is not `Full`. pub fn as_transactions(&self) -> Option<&[T]> { match self { Self::Full(txs) => Some(txs), @@ -211,6 +213,15 @@ impl BlockTransactions { self.as_transactions().map(|txs| txs.iter()).unwrap_or_else(|| [].iter()) } + /// Returns an iterator over the transactions (if any). This will be empty if the block is not + /// full. + pub fn into_transactions(self) -> std::vec::IntoIter { + match self { + Self::Full(txs) => txs.into_iter(), + _ => std::vec::IntoIter::default(), + } + } + /// Returns an instance of BlockTransactions with the Uncle special case. #[inline] pub const fn uncle() -> Self { From a2182f4986ba55b4a5771200e688e3f0aebc9c57 Mon Sep 17 00:00:00 2001 From: Igor Line Date: Fri, 28 Jun 2024 17:03:15 +0200 Subject: [PATCH 32/61] Update builders to vector of strings in privacy struct (#983) fix(mev): builders as vector of strings in privacy struct according to mev-share specification builders are specified by their names which you can find on this page https://github.com/flashbots/dowg/blob/main/builder-registrations.json --- crates/rpc-types-mev/src/common.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/rpc-types-mev/src/common.rs b/crates/rpc-types-mev/src/common.rs index 8c138137eff..74a27835b7c 100644 --- a/crates/rpc-types-mev/src/common.rs +++ b/crates/rpc-types-mev/src/common.rs @@ -54,9 +54,10 @@ pub struct Privacy { /// Hints on what data should be shared about the bundle and its transactions #[serde(skip_serializing_if = "Option::is_none")] pub hints: Option, - /// The addresses of the builders that should be allowed to see the bundle/transaction. + /// Names of the builders that should be allowed to see the bundle/transaction. + /// #[serde(skip_serializing_if = "Option::is_none")] - pub builders: Option>, + pub builders: Option>, } /// Hints on what data should be shared about the bundle and its transactions From 91e5628dea290d38e1a30881f8321c0e0d196aed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Gonz=C3=A1lez?= Date: Fri, 28 Jun 2024 18:47:13 +0200 Subject: [PATCH 33/61] feat: add missing debug_* rpc methods (#986) * feat: add debug_getRawHeader * feat: add debug_getRawBlock * feat: add debug_getRawTransaction * feat: add debug_getRawReceipts * feat: add debug_getBadBlocks * feat: add debug_traceChain * feat: add debug_traceBlock * lint(fmt): fix formatting * fix: hex encode rlp_block bytes --- crates/provider/src/ext/debug.rs | 129 ++++++++++++++++++++++++++++++- 1 file changed, 126 insertions(+), 3 deletions(-) diff --git a/crates/provider/src/ext/debug.rs b/crates/provider/src/ext/debug.rs index c80cde9a5b7..f8933bff221 100644 --- a/crates/provider/src/ext/debug.rs +++ b/crates/provider/src/ext/debug.rs @@ -1,10 +1,10 @@ //! This module extends the Ethereum JSON-RPC provider with the Debug namespace's RPC methods. use crate::Provider; use alloy_network::Network; -use alloy_primitives::{TxHash, B256}; -use alloy_rpc_types_eth::{BlockNumberOrTag, TransactionRequest}; +use alloy_primitives::{hex, Bytes, TxHash, B256}; +use alloy_rpc_types_eth::{Block, BlockNumberOrTag, TransactionRequest}; use alloy_rpc_types_trace::geth::{ - GethDebugTracingCallOptions, GethDebugTracingOptions, GethTrace, TraceResult, + BlockTraceResult, GethDebugTracingCallOptions, GethDebugTracingOptions, GethTrace, TraceResult, }; use alloy_transport::{Transport, TransportResult}; @@ -12,6 +12,43 @@ use alloy_transport::{Transport, TransportResult}; #[cfg_attr(target_arch = "wasm32", async_trait::async_trait(?Send))] #[cfg_attr(not(target_arch = "wasm32"), async_trait::async_trait)] pub trait DebugApi: Send + Sync { + /// Returns an RLP-encoded header. + async fn debug_get_raw_header(&self, block: BlockNumberOrTag) -> TransportResult; + + /// Retrieves and returns the RLP encoded block by number, hash or tag. + async fn debug_get_raw_block(&self, block: BlockNumberOrTag) -> TransportResult; + + /// Returns an EIP-2718 binary-encoded transaction. + async fn debug_get_raw_transaction(&self, hash: TxHash) -> TransportResult; + + /// Returns an array of EIP-2718 binary-encoded receipts. + async fn debug_get_raw_receipts(&self, block: BlockNumberOrTag) -> TransportResult>; + + /// Returns an array of recent bad blocks that the client has seen on the network. + async fn debug_get_bad_blocks(&self) -> TransportResult>; + + /// Returns the structured logs created during the execution of EVM between two blocks + /// (excluding start) as a JSON object. + async fn debug_trace_chain( + &self, + start_exclusive: BlockNumberOrTag, + end_inclusive: BlockNumberOrTag, + ) -> TransportResult>; + + /// The debug_traceBlock method will return a full stack trace of all invoked opcodes of all + /// transaction that were included in this block. + /// + /// This expects an RLP-encoded block. + /// + /// # Note + /// + /// The parent of this block must be present, or it will fail. + async fn debug_trace_block( + &self, + rlp_block: &[u8], + trace_options: GethDebugTracingOptions, + ) -> TransportResult>; + /// Reruns the transaction specified by the hash and returns the trace. /// /// It will replay any prior transactions to achieve the same state the transaction was executed @@ -99,6 +136,43 @@ where T: Transport + Clone, P: Provider, { + async fn debug_get_raw_header(&self, block: BlockNumberOrTag) -> TransportResult { + self.client().request("debug_getRawHeader", (block,)).await + } + + async fn debug_get_raw_block(&self, block: BlockNumberOrTag) -> TransportResult { + self.client().request("debug_getRawBlock", (block,)).await + } + + async fn debug_get_raw_transaction(&self, hash: TxHash) -> TransportResult { + self.client().request("debug_getRawTransaction", (hash,)).await + } + + async fn debug_get_raw_receipts(&self, block: BlockNumberOrTag) -> TransportResult> { + self.client().request("debug_getRawReceipts", (block,)).await + } + + async fn debug_get_bad_blocks(&self) -> TransportResult> { + self.client().request("debug_getBadBlocks", ()).await + } + + async fn debug_trace_chain( + &self, + start_exclusive: BlockNumberOrTag, + end_inclusive: BlockNumberOrTag, + ) -> TransportResult> { + self.client().request("debug_traceChain", (start_exclusive, end_inclusive)).await + } + + async fn debug_trace_block( + &self, + rlp_block: &[u8], + trace_options: GethDebugTracingOptions, + ) -> TransportResult> { + let rlp_block = hex::encode_prefixed(rlp_block); + self.client().request("debug_traceBlock", (rlp_block, trace_options)).await + } + async fn debug_trace_transaction( &self, hash: TxHash, @@ -148,6 +222,7 @@ mod test { use super::*; use alloy_network::TransactionBuilder; + use alloy_node_bindings::Geth; use alloy_primitives::{address, U256}; fn init_tracing() { @@ -201,4 +276,52 @@ mod test { assert!(!trace.struct_logs.is_empty()); } } + + #[tokio::test] + async fn call_debug_get_raw_header() { + let temp_dir = tempfile::TempDir::with_prefix("geth-test-").unwrap(); + let geth = Geth::new().disable_discovery().data_dir(temp_dir.path()).spawn(); + let provider = ProviderBuilder::new().on_http(geth.endpoint_url()); + + let rlp_header = provider + .debug_get_raw_header(BlockNumberOrTag::default()) + .await + .expect("debug_getRawHeader call should succeed"); + + assert!(!rlp_header.is_empty()); + } + + #[tokio::test] + async fn call_debug_get_raw_block() { + let temp_dir = tempfile::TempDir::with_prefix("geth-test-").unwrap(); + let geth = Geth::new().disable_discovery().data_dir(temp_dir.path()).spawn(); + let provider = ProviderBuilder::new().on_http(geth.endpoint_url()); + + let rlp_block = provider + .debug_get_raw_block(BlockNumberOrTag::default()) + .await + .expect("debug_getRawBlock call should succeed"); + + assert!(!rlp_block.is_empty()); + } + + #[tokio::test] + async fn call_debug_get_raw_receipts() { + let temp_dir = tempfile::TempDir::with_prefix("geth-test-").unwrap(); + let geth = Geth::new().disable_discovery().data_dir(temp_dir.path()).spawn(); + let provider = ProviderBuilder::new().on_http(geth.endpoint_url()); + + let result = provider.debug_get_raw_receipts(BlockNumberOrTag::default()).await; + assert!(result.is_ok()); + } + + #[tokio::test] + async fn call_debug_get_bad_blocks() { + let temp_dir = tempfile::TempDir::with_prefix("geth-test-").unwrap(); + let geth = Geth::new().disable_discovery().data_dir(temp_dir.path()).spawn(); + let provider = ProviderBuilder::new().on_http(geth.endpoint_url()); + + let result = provider.debug_get_bad_blocks().await; + assert!(result.is_ok()); + } } From bd5700b4e1ffb37da2e664afa6c9add72933951d Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Sat, 29 Jun 2024 01:21:29 +0200 Subject: [PATCH 34/61] chore: make wrapped index value pub (#988) --- crates/rpc-types-eth/src/index.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/rpc-types-eth/src/index.rs b/crates/rpc-types-eth/src/index.rs index 50aac8a519e..b1183c9dc15 100644 --- a/crates/rpc-types-eth/src/index.rs +++ b/crates/rpc-types-eth/src/index.rs @@ -8,7 +8,7 @@ use std::fmt; /// A hex encoded or decimal index that's intended to be used as a rust index, hence it's /// deserialized into a `usize`. #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)] -pub struct Index(usize); +pub struct Index(pub usize); impl From for usize { fn from(idx: Index) -> Self { From 1807965627d29a3e6d9cab7774da1d92be971df5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Gonz=C3=A1lez?= Date: Sat, 29 Jun 2024 08:56:52 +0200 Subject: [PATCH 35/61] feat: add net rpc namespace (#989) * feat: add net rpc namespace * lint: appease clippy --- crates/alloy/Cargo.toml | 9 ++-- crates/provider/Cargo.toml | 1 + crates/provider/src/ext/mod.rs | 5 +++ crates/provider/src/ext/net.rs | 75 ++++++++++++++++++++++++++++++++++ 4 files changed, 86 insertions(+), 4 deletions(-) create mode 100644 crates/provider/src/ext/net.rs diff --git a/crates/alloy/Cargo.toml b/crates/alloy/Cargo.toml index 2add14fb29b..e920d78fb8d 100644 --- a/crates/alloy/Cargo.toml +++ b/crates/alloy/Cargo.toml @@ -81,10 +81,10 @@ full = [ "kzg", "network", "provider-http", # includes `providers` - "provider-ws", # includes `providers` - "provider-ipc", # includes `providers` - "rpc-types", # includes `rpc-types-eth` - "signer-local", # includes `signers` + "provider-ws", # includes `providers` + "provider-ipc", # includes `providers` + "rpc-types", # includes `rpc-types-eth` + "signer-local", # includes `signers` ] # configuration @@ -155,6 +155,7 @@ provider-engine-api = [ "alloy-provider?/engine-api", "rpc-types-engine", ] +provider-net-api = ["providers", "alloy-provider?/net-api"] provider-trace-api = [ "providers", "alloy-provider?/trace-api", diff --git a/crates/provider/Cargo.toml b/crates/provider/Cargo.toml index 7b9c02fe077..fb51899fb39 100644 --- a/crates/provider/Cargo.toml +++ b/crates/provider/Cargo.toml @@ -96,5 +96,6 @@ anvil-node = [ ] debug-api = ["dep:alloy-rpc-types-trace"] engine-api = ["dep:alloy-rpc-types-engine"] +net-api = [] trace-api = ["dep:alloy-rpc-types-trace"] txpool-api = ["dep:alloy-rpc-types-txpool"] diff --git a/crates/provider/src/ext/mod.rs b/crates/provider/src/ext/mod.rs index 9364c8d3b8b..8e06ca3042e 100644 --- a/crates/provider/src/ext/mod.rs +++ b/crates/provider/src/ext/mod.rs @@ -20,6 +20,11 @@ mod debug; #[cfg(feature = "debug-api")] pub use debug::DebugApi; +#[cfg(feature = "net-api")] +mod net; +#[cfg(feature = "net-api")] +pub use net::NetApi; + #[cfg(feature = "trace-api")] mod trace; #[cfg(feature = "trace-api")] diff --git a/crates/provider/src/ext/net.rs b/crates/provider/src/ext/net.rs new file mode 100644 index 00000000000..241dd58ac16 --- /dev/null +++ b/crates/provider/src/ext/net.rs @@ -0,0 +1,75 @@ +//! This module extends the Ethereum JSON-RPC provider with the Net namespace's RPC methods. +use crate::Provider; +use alloy_network::Network; +use alloy_transport::{Transport, TransportResult}; + +/// Net namespace rpc interface that provides access to network information of the node. +#[cfg_attr(target_arch = "wasm32", async_trait::async_trait(?Send))] +#[cfg_attr(not(target_arch = "wasm32"), async_trait::async_trait)] +pub trait NetApi: Send + Sync { + /// Returns a `bool` indicating whether or not the node is listening for network connections. + async fn net_listening(&self) -> TransportResult; + /// Returns the number of peers connected to the node. + async fn net_peer_count(&self) -> TransportResult; + /// Returns the network ID (e.g. 1 for mainnet). + async fn net_version(&self) -> TransportResult; +} + +#[cfg_attr(target_arch = "wasm32", async_trait::async_trait(?Send))] +#[cfg_attr(not(target_arch = "wasm32"), async_trait::async_trait)] +impl NetApi for P +where + N: Network, + T: Transport + Clone, + P: Provider, +{ + async fn net_listening(&self) -> TransportResult { + self.client().request("net_listening", ()).await + } + + async fn net_peer_count(&self) -> TransportResult { + self.client().request("net_peerCount", ()).map_resp(crate::utils::convert_u64).await + } + + async fn net_version(&self) -> TransportResult { + self.client().request("net_version", ()).map_resp(crate::utils::convert_u64).await + } +} + +#[cfg(test)] +mod test { + use crate::ProviderBuilder; + + use super::*; + use alloy_node_bindings::Geth; + + #[tokio::test] + async fn call_net_version() { + let temp_dir = tempfile::TempDir::with_prefix("geth-test-").unwrap(); + let geth = Geth::new().disable_discovery().data_dir(temp_dir.path()).spawn(); + let provider = ProviderBuilder::new().on_http(geth.endpoint_url()); + + let version = provider.net_version().await.expect("net_version call should succeed"); + assert_eq!(version, 1); + } + + #[tokio::test] + async fn call_net_peer_count() { + let temp_dir = tempfile::TempDir::with_prefix("geth-test-").unwrap(); + let geth = Geth::new().disable_discovery().data_dir(temp_dir.path()).spawn(); + let provider = ProviderBuilder::new().on_http(geth.endpoint_url()); + + let count = provider.net_peer_count().await.expect("net_peerCount call should succeed"); + assert_eq!(count, 0); + } + + #[tokio::test] + async fn call_net_listening() { + let temp_dir = tempfile::TempDir::with_prefix("geth-test-").unwrap(); + let geth = Geth::new().disable_discovery().data_dir(temp_dir.path()).spawn(); + let provider = ProviderBuilder::new().on_http(geth.endpoint_url()); + + let listening = provider.net_listening().await.expect("net_listening call should succeed"); + assert!(listening); + } +} From 0b8ad51b8b2168c4f33c2410fb68b4ec3e8d46da Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Sat, 29 Jun 2024 14:14:48 +0200 Subject: [PATCH 36/61] test: fix flaky anvil test (#992) --- crates/provider/src/ext/anvil.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/provider/src/ext/anvil.rs b/crates/provider/src/ext/anvil.rs index 22100f956c3..e3719e64ab1 100644 --- a/crates/provider/src/ext/anvil.rs +++ b/crates/provider/src/ext/anvil.rs @@ -431,11 +431,11 @@ mod tests { let start_num = provider.get_block_number().await.unwrap(); - tokio::time::sleep(tokio::time::Duration::from_secs(2)).await; + tokio::time::sleep(tokio::time::Duration::from_millis(1500)).await; let num = provider.get_block_number().await.unwrap(); - assert_eq!(num, start_num + 2); + assert_eq!(num, start_num + 1); } #[tokio::test] From b15bb6a681048564ccbaceb2c0b7530910b3a46b Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Sat, 29 Jun 2024 14:34:18 +0200 Subject: [PATCH 37/61] ci: fix wasi job (#993) * ci: fix wasi job * ci: pin cc --- .github/workflows/ci.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 64293dedb1a..f70cadc95e1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -107,21 +107,23 @@ jobs: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable with: - target: wasm32-wasi + target: wasm32-wasip1 - uses: taiki-e/install-action@cargo-hack - uses: Swatinem/rust-cache@v2 with: cache-on-failure: true + - name: pin cc # https://github.com/rust-lang/cc-rs/issues/1109 + run: cargo update cc --precise 1.0.99 - name: cargo hack run: | - cargo hack build --workspace --target wasm32-wasi \ + cargo hack build --workspace --target wasm32-wasip1 \ --exclude alloy-signer-gcp \ --exclude alloy-signer-ledger \ --exclude alloy-signer-trezor \ --exclude alloy-transport-ipc # Ledger signer requires one of `browser` or `node` features. - name: build ledger - run: cargo build -p alloy-signer-ledger --features browser --target wasm32-wasi + run: cargo build -p alloy-signer-ledger --features browser --target wasm32-wasip1 no-std: runs-on: ubuntu-latest From 7b475291f6e8af9ce6e35c26209f031efbf9851d Mon Sep 17 00:00:00 2001 From: Misha Date: Sat, 29 Jun 2024 19:47:44 +0700 Subject: [PATCH 38/61] feat: Add trace_get (#987) * trace_get implementation * Review * Update crates/provider/src/ext/trace.rs docs Co-authored-by: Matthias Seitz * Cargo fmt --------- Co-authored-by: Matthias Seitz --- crates/provider/src/ext/trace.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/crates/provider/src/ext/trace.rs b/crates/provider/src/ext/trace.rs index 90b7598457a..334ef2a883a 100644 --- a/crates/provider/src/ext/trace.rs +++ b/crates/provider/src/ext/trace.rs @@ -3,6 +3,7 @@ use crate::{Provider, RpcWithBlock}; use alloy_eips::BlockNumberOrTag; use alloy_network::Network; use alloy_primitives::TxHash; +use alloy_rpc_types_eth::Index; use alloy_rpc_types_trace::{ filter::TraceFilter, parity::{LocalizedTransactionTrace, TraceResults, TraceResultsWithTransactionHash, TraceType}, @@ -50,6 +51,18 @@ where hash: TxHash, ) -> TransportResult>; + /// Traces of the transaction on the given positions + /// + /// # Note + /// + /// This function accepts single index and build list with it under the hood because + /// trace_get method accepts list of indices but limits this list to len == 1. + async fn trace_get( + &self, + hash: TxHash, + index: usize, + ) -> TransportResult; + /// Trace the given raw transaction. async fn trace_raw_transaction( &self, @@ -119,6 +132,15 @@ where self.client().request("trace_transaction", (hash,)).await } + async fn trace_get( + &self, + hash: TxHash, + index: usize, + ) -> TransportResult { + // We are using `[index]` because API accepts a list, but only supports a single index + self.client().request("trace_get", (hash, (Index::from(index),))).await + } + async fn trace_raw_transaction( &self, data: &[u8], From b036bc9ed40cd12c7c73e503ea5d6a5a59aaa867 Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Sun, 30 Jun 2024 12:53:04 +0200 Subject: [PATCH 39/61] feat: add submit block request query (#995) --- crates/rpc-types-beacon/src/relay.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/crates/rpc-types-beacon/src/relay.rs b/crates/rpc-types-beacon/src/relay.rs index 209eeca337a..dba211b29ee 100644 --- a/crates/rpc-types-beacon/src/relay.rs +++ b/crates/rpc-types-beacon/src/relay.rs @@ -38,7 +38,6 @@ pub struct ValidatorRegistration { #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct ValidatorRegistrationMessage { /// The fee recipient's address. - #[serde(rename = "fee_recipient")] pub fee_recipient: Address, /// The gas limit for the registration. @@ -150,6 +149,23 @@ pub struct SubmitBlockRequest { pub signature: BlsSignature, } +/// Query for the `/relay/v1/builder/blocks` endpoint +#[serde_as] +#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct SubmitBlockRequestQuery { + /// If set to 1, opt into bid cancellations. + #[serde(skip_serializing_if = "Option::is_none")] + #[serde_as(as = "Option")] + pub cancellations: Option, +} + +impl SubmitBlockRequestQuery { + /// Opt into bid cancellations. + pub const fn cancellations() -> Self { + Self { cancellations: Some(true) } + } +} + /// A Request to validate a [SubmitBlockRequest] #[serde_as] #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] From c98a175da1ce18c4ddaec4aacb997a7769c3f6d7 Mon Sep 17 00:00:00 2001 From: Delweng Date: Mon, 1 Jul 2024 17:38:04 +0800 Subject: [PATCH 40/61] fix: ots_getContractCreater has field hash instead of tx (#999) * fix: ots_ContractCreater has hash instead of tx field Signed-off-by: jsvisa * clippy Signed-off-by: jsvisa --------- Signed-off-by: jsvisa --- crates/rpc-types-trace/src/otterscan.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/crates/rpc-types-trace/src/otterscan.rs b/crates/rpc-types-trace/src/otterscan.rs index 8ddb704ee86..3fad4d8197b 100644 --- a/crates/rpc-types-trace/src/otterscan.rs +++ b/crates/rpc-types-trace/src/otterscan.rs @@ -3,7 +3,7 @@ //! //! -use alloy_primitives::{Address, Bloom, Bytes, U256}; +use alloy_primitives::{Address, Bloom, Bytes, TxHash, U256}; use alloy_rpc_types_eth::{Block, Rich, Transaction, TransactionReceipt}; use serde::{Deserialize, Serialize}; @@ -169,11 +169,10 @@ pub struct TransactionsWithReceipts { } /// Custom struct for otterscan `getContractCreator` RPC responses -#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct ContractCreator { /// The transaction used to create the contract. - #[doc(alias = "transaction")] - pub tx: Transaction, + pub hash: TxHash, /// The address of the contract creator. pub creator: Address, } From 984ee1bb25ebc5061c0c973f9130d8a5c701dddd Mon Sep 17 00:00:00 2001 From: Oliver Date: Mon, 1 Jul 2024 11:51:45 +0200 Subject: [PATCH 41/61] chore: clean up 7702 encoding (#1000) Ref https://github.com/ethereum/EIPs/pull/8679 --- crates/eips/src/eip7702/auth_list.rs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/crates/eips/src/eip7702/auth_list.rs b/crates/eips/src/eip7702/auth_list.rs index faa2c160ada..132981aaef1 100644 --- a/crates/eips/src/eip7702/auth_list.rs +++ b/crates/eips/src/eip7702/auth_list.rs @@ -51,17 +51,9 @@ impl Authorization { pub fn signature_hash(&self) -> B256 { use super::constants::MAGIC; - #[derive(RlpEncodable)] - struct Auth { - chain_id: ChainId, - nonce: OptionalNonce, - address: Address, - } - let mut buf = Vec::new(); buf.put_u8(MAGIC); - - Auth { chain_id: self.chain_id, nonce: self.nonce, address: self.address }.encode(&mut buf); + self.encode(&mut buf); keccak256(buf) } From 490b841674c18230f59e3cbf8203132f47d56d32 Mon Sep 17 00:00:00 2001 From: Panagiotis Ganelis <50522617+PanGan21@users.noreply.github.com> Date: Mon, 1 Jul 2024 14:48:09 +0300 Subject: [PATCH 42/61] feat: support web3_sha3 provider function (#996) * feat: add web3 client version method for web3 namespace * feat: add web3_sha3 method * feat: add unit tests * fix: use anvil instead of geth for tests * fix: use bytes slice in web3_sha3 * refactor: move sha3 to main trait and remove separate web3 api namespace * fix: format * fmt * fix: remove log * chore: nits --------- Co-authored-by: DaniPopes <57450786+DaniPopes@users.noreply.github.com> --- crates/provider/src/provider/trait.rs | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/crates/provider/src/provider/trait.rs b/crates/provider/src/provider/trait.rs index c3eefcadd9d..c9543249e61 100644 --- a/crates/provider/src/provider/trait.rs +++ b/crates/provider/src/provider/trait.rs @@ -851,11 +851,18 @@ pub trait Provider: self.client().request("eth_syncing", ()).await } - /// Gets the client version of the chain client(). + /// Gets the client version. + #[doc(alias = "web3_client_version")] async fn get_client_version(&self) -> TransportResult { self.client().request("web3_clientVersion", ()).await } + /// Gets the `Keccak-256` hash of the given data. + #[doc(alias = "web3_sha3")] + async fn get_sha3(&self, data: &[u8]) -> TransportResult { + self.client().request("web3_sha3", (hex::encode_prefixed(data),)).await + } + /// Gets the network ID. Same as `eth_chainId`. fn get_net_version(&self) -> RpcCall { self.client().request("net_version", ()).map_resp(crate::utils::convert_u64) @@ -961,7 +968,7 @@ mod tests { use crate::{builder, ProviderBuilder, WalletProvider}; use alloy_network::AnyNetwork; use alloy_node_bindings::Anvil; - use alloy_primitives::{address, b256, bytes}; + use alloy_primitives::{address, b256, bytes, keccak256}; use alloy_rpc_types_eth::request::TransactionRequest; fn init_tracing() { @@ -1221,7 +1228,16 @@ mod tests { init_tracing(); let provider = ProviderBuilder::new().on_anvil(); let version = provider.get_client_version().await.unwrap(); - assert!(version.contains("anvil")); + assert!(version.contains("anvil"), "{version}"); + } + + #[tokio::test] + async fn gets_sha3() { + init_tracing(); + let provider = ProviderBuilder::new().on_anvil(); + let data = b"alloy"; + let hash = provider.get_sha3(data).await.unwrap(); + assert_eq!(hash, keccak256(data)); } #[tokio::test] From 735c73af1c1fe3000318f22f7e3dea474e2496bf Mon Sep 17 00:00:00 2001 From: Delweng Date: Tue, 2 Jul 2024 19:31:53 +0800 Subject: [PATCH 43/61] feat(otterscan): add output for TraceEntry (#1001) Signed-off-by: jsvisa --- crates/rpc-types-trace/src/otterscan.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/rpc-types-trace/src/otterscan.rs b/crates/rpc-types-trace/src/otterscan.rs index 3fad4d8197b..85114451c9f 100644 --- a/crates/rpc-types-trace/src/otterscan.rs +++ b/crates/rpc-types-trace/src/otterscan.rs @@ -36,7 +36,7 @@ pub struct InternalOperation { /// Custom struct for otterscan `traceTransaction` RPC response #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct TraceEntry { - /// The type of trace entry. + /// The type of the trace entry. pub r#type: String, /// The depth of the trace entry. pub depth: u32, @@ -48,6 +48,8 @@ pub struct TraceEntry { pub value: U256, /// The input data for the trace. pub input: Bytes, + /// The output data for the trace. + pub output: Bytes, } /// Internal issuance struct for `BlockDetails` struct From 3cbefdddbddc723922fe2b42386e56535670c635 Mon Sep 17 00:00:00 2001 From: Yash Atreya <44857776+yash-atreya@users.noreply.github.com> Date: Tue, 2 Jul 2024 20:44:55 +0530 Subject: [PATCH 44/61] feat(network): block context in ReceiptResponse (#1003) --- crates/network/src/any/mod.rs | 8 ++++++++ crates/network/src/ethereum/mod.rs | 8 ++++++++ crates/network/src/lib.rs | 8 +++++++- 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/crates/network/src/any/mod.rs b/crates/network/src/any/mod.rs index 1885e5835a9..8cc7bf2bbe1 100644 --- a/crates/network/src/any/mod.rs +++ b/crates/network/src/any/mod.rs @@ -84,6 +84,14 @@ impl ReceiptResponse for AnyTransactionReceipt { fn status(&self) -> bool { self.inner.inner.status() } + + fn block_hash(&self) -> Option { + self.inner.block_hash + } + + fn block_number(&self) -> Option { + self.inner.block_number + } } impl TransactionResponse for WithOtherFields { diff --git a/crates/network/src/ethereum/mod.rs b/crates/network/src/ethereum/mod.rs index 9bfe362c578..68729e3f0f9 100644 --- a/crates/network/src/ethereum/mod.rs +++ b/crates/network/src/ethereum/mod.rs @@ -40,6 +40,14 @@ impl ReceiptResponse for alloy_rpc_types_eth::TransactionReceipt { fn status(&self) -> bool { self.inner.status() } + + fn block_hash(&self) -> Option { + self.block_hash + } + + fn block_number(&self) -> Option { + self.block_number + } } impl TransactionResponse for alloy_rpc_types_eth::Transaction { diff --git a/crates/network/src/lib.rs b/crates/network/src/lib.rs index 0afa1f7f093..e0a63d2a233 100644 --- a/crates/network/src/lib.rs +++ b/crates/network/src/lib.rs @@ -9,7 +9,7 @@ use alloy_consensus::TxReceipt; use alloy_eips::eip2718::{Eip2718Envelope, Eip2718Error}; use alloy_json_rpc::RpcObject; -use alloy_primitives::{Address, Bytes, TxHash, U256}; +use alloy_primitives::{Address, BlockHash, Bytes, TxHash, U256}; use core::fmt::{Debug, Display}; mod transaction; @@ -49,6 +49,12 @@ pub trait ReceiptResponse { /// [EIP-658]: https://eips.ethereum.org/EIPS/eip-658 /// [`TxReceipt::status_or_post_state`]: alloy_consensus::TxReceipt::status_or_post_state fn status(&self) -> bool; + + /// Hash of the block this transaction was included within. + fn block_hash(&self) -> Option; + + /// Number of the block this transaction was included within. + fn block_number(&self) -> Option; } /// Transaction Response From ec9e13e6336717b988b6ec2908bb4ceec6e874a5 Mon Sep 17 00:00:00 2001 From: alexfertel Date: Wed, 3 Jul 2024 19:51:02 +0200 Subject: [PATCH 45/61] feat: add missing admin_* methods (#991) * feat: add missing admin_* methods * fix: add 0x prefix to subscription ids * fix: u16 -> U128 * fix: remork to match other subscriptions * lint(fmt): fix formatting * fix: use alloy_pubsub when pubsub is enabled * fix: add missing type path * fix(docs): remove outdated comment * doc: nit --------- Co-authored-by: DaniPopes <57450786+DaniPopes@users.noreply.github.com> --- crates/provider/src/ext/admin.rs | 17 +++++++++++ crates/rpc-types-admin/src/admin.rs | 45 +++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/crates/provider/src/ext/admin.rs b/crates/provider/src/ext/admin.rs index 2165481cc34..158f9598d37 100644 --- a/crates/provider/src/ext/admin.rs +++ b/crates/provider/src/ext/admin.rs @@ -31,6 +31,12 @@ pub trait AdminApi: Send + Sync { /// Returns general information about the node as well as information about the running p2p /// protocols (e.g. `eth`, `snap`). async fn node_info(&self) -> TransportResult; + + /// Subscribe to events received by peers over the network. + #[cfg(feature = "pubsub")] + async fn subscribe_peer_events( + &self, + ) -> TransportResult>; } #[cfg_attr(target_arch = "wasm32", async_trait::async_trait(?Send))] @@ -64,6 +70,17 @@ where async fn node_info(&self) -> TransportResult { self.client().request("admin_nodeInfo", ()).await } + + #[cfg(feature = "pubsub")] + async fn subscribe_peer_events( + &self, + ) -> TransportResult> { + self.root().pubsub_frontend()?; + let mut call = self.client().request("admin_peerEvents_subscribe", ()); + call.set_is_subscription(); + let id = call.await?; + self.root().get_subscription(id).await + } } #[cfg(test)] diff --git a/crates/rpc-types-admin/src/admin.rs b/crates/rpc-types-admin/src/admin.rs index 4ef48287bc0..2814f16160e 100644 --- a/crates/rpc-types-admin/src/admin.rs +++ b/crates/rpc-types-admin/src/admin.rs @@ -185,6 +185,51 @@ pub struct PeerNetworkInfo { pub static_node: bool, } +/// The type of a peer event. +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "lowercase")] +pub enum PeerEventType { + /// A peer was added to the server. + Add, + /// A peer was dropped from the server. + Drop, + /// A message was successfully sent to the peer. + MsgSend, + /// A message was successfully received by the peer. + MsgRecv, +} + +/// An event emitted when peers are either added or dropped from a p2p server or when a message is +/// sent or received on a peer connection. +/// +/// See [geth's `PeerEvent` struct](https://github.com/ethereum/go-ethereum/blob/94579932b18931115f28aa7f87f02450bda084c9/p2p/peer.go#L94-L103) for the source of each field. +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct PeerEvent { + /// The type of the event. + #[serde(rename = "type")] + pub kind: PeerEventType, + /// The peer's enode ID. + pub peer: String, + /// An error ocurred on the peer. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub error: Option, + /// The protocol of the peer. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub protocol: Option, + /// The message code. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub msg_code: Option, + /// The message size. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub msg_size: Option, + /// The local endpoint of the TCP connection. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub local_address: Option, + /// The remote endpoint of the TCP connection. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub remote_address: Option, +} + mod handshake { use super::*; From 78807cbd0e659873c32d373af963031f71bde8a2 Mon Sep 17 00:00:00 2001 From: Thomas Coratger <60488569+tcoratger@users.noreply.github.com> Date: Wed, 3 Jul 2024 21:37:42 +0200 Subject: [PATCH 46/61] test: add missing unit test for op `calc_next_block_base_fee` (#1008) * test: add missing unit test for op calc_next_block_base_fee * complete test suite * add base test --- crates/eips/src/eip1559/basefee.rs | 33 +++++++++- crates/eips/src/eip1559/constants.rs | 20 ++++++ crates/eips/src/eip1559/helpers.rs | 96 ++++++++++++++++++++++++++++ 3 files changed, 148 insertions(+), 1 deletion(-) diff --git a/crates/eips/src/eip1559/basefee.rs b/crates/eips/src/eip1559/basefee.rs index 3590b4e1a56..2ae88191f27 100644 --- a/crates/eips/src/eip1559/basefee.rs +++ b/crates/eips/src/eip1559/basefee.rs @@ -1,6 +1,13 @@ use crate::{ calc_next_block_base_fee, - eip1559::constants::{DEFAULT_BASE_FEE_MAX_CHANGE_DENOMINATOR, DEFAULT_ELASTICITY_MULTIPLIER}, + eip1559::constants::{ + BASE_SEPOLIA_EIP1559_DEFAULT_ELASTICITY_MULTIPLIER, + DEFAULT_BASE_FEE_MAX_CHANGE_DENOMINATOR, DEFAULT_ELASTICITY_MULTIPLIER, + OP_MAINNET_EIP1559_DEFAULT_BASE_FEE_MAX_CHANGE_DENOMINATOR, + OP_MAINNET_EIP1559_DEFAULT_ELASTICITY_MULTIPLIER, + OP_SEPOLIA_EIP1559_DEFAULT_BASE_FEE_MAX_CHANGE_DENOMINATOR, + OP_SEPOLIA_EIP1559_DEFAULT_ELASTICITY_MULTIPLIER, + }, }; /// BaseFeeParams contains the config parameters that control block base fee computation @@ -29,6 +36,30 @@ impl BaseFeeParams { } } + /// Get the base fee parameters for Optimism Mainnet + pub const fn optimism() -> Self { + Self { + max_change_denominator: OP_MAINNET_EIP1559_DEFAULT_BASE_FEE_MAX_CHANGE_DENOMINATOR, + elasticity_multiplier: OP_MAINNET_EIP1559_DEFAULT_ELASTICITY_MULTIPLIER, + } + } + + /// Get the base fee parameters for Optimism Sepolia + pub const fn optimism_sepolia() -> Self { + Self { + max_change_denominator: OP_SEPOLIA_EIP1559_DEFAULT_BASE_FEE_MAX_CHANGE_DENOMINATOR, + elasticity_multiplier: OP_SEPOLIA_EIP1559_DEFAULT_ELASTICITY_MULTIPLIER, + } + } + + /// Get the base fee parameters for Base Sepolia + pub const fn base_sepolia() -> Self { + Self { + max_change_denominator: OP_SEPOLIA_EIP1559_DEFAULT_BASE_FEE_MAX_CHANGE_DENOMINATOR, + elasticity_multiplier: BASE_SEPOLIA_EIP1559_DEFAULT_ELASTICITY_MULTIPLIER, + } + } + /// Calculate the base fee for the next block based on the EIP-1559 specification. /// /// See also [calc_next_block_base_fee] diff --git a/crates/eips/src/eip1559/constants.rs b/crates/eips/src/eip1559/constants.rs index 356761c7e20..1b6cb0b804c 100644 --- a/crates/eips/src/eip1559/constants.rs +++ b/crates/eips/src/eip1559/constants.rs @@ -25,3 +25,23 @@ pub const DEFAULT_BASE_FEE_MAX_CHANGE_DENOMINATOR: u64 = 8; /// Elasticity multiplier as defined in [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559) pub const DEFAULT_ELASTICITY_MULTIPLIER: u64 = 2; + +/// Base fee max change denominator for Optimism Sepolia as defined in the Optimism +/// [transaction costs](https://community.optimism.io/docs/developers/build/differences/#transaction-costs) doc. +pub(crate) const OP_SEPOLIA_EIP1559_DEFAULT_BASE_FEE_MAX_CHANGE_DENOMINATOR: u128 = 50; + +/// Base fee max change denominator for Optimism Sepolia as defined in the Optimism +/// [transaction costs](https://community.optimism.io/docs/developers/build/differences/#transaction-costs) doc. +pub(crate) const OP_SEPOLIA_EIP1559_DEFAULT_ELASTICITY_MULTIPLIER: u128 = 6; + +/// Base fee max change denominator for Optimism Mainnet as defined in the Optimism +/// [transaction costs](https://community.optimism.io/docs/developers/build/differences/#transaction-costs) doc. +pub(crate) const OP_MAINNET_EIP1559_DEFAULT_BASE_FEE_MAX_CHANGE_DENOMINATOR: u128 = 50; + +/// Base fee max change denominator for Optimism Mainnet as defined in the Optimism +/// [transaction costs](https://community.optimism.io/docs/developers/build/differences/#transaction-costs) doc. +pub(crate) const OP_MAINNET_EIP1559_DEFAULT_ELASTICITY_MULTIPLIER: u128 = 6; + +/// Base fee max change denominator for Base Sepolia as defined in the Optimism +/// [transaction costs](https://community.optimism.io/docs/developers/build/differences/#transaction-costs) doc. +pub(crate) const BASE_SEPOLIA_EIP1559_DEFAULT_ELASTICITY_MULTIPLIER: u128 = 10; diff --git a/crates/eips/src/eip1559/helpers.rs b/crates/eips/src/eip1559/helpers.rs index e22a3be8746..c68e3b9a8c2 100644 --- a/crates/eips/src/eip1559/helpers.rs +++ b/crates/eips/src/eip1559/helpers.rs @@ -101,4 +101,100 @@ mod tests { ); } } + + #[test] + fn calculate_optimism_sepolia_base_fee_success() { + let base_fee = [ + 1000000000, 1000000000, 1000000000, 1072671875, 1059263476, 1049238967, 1049238967, 0, + 1, 2, + ]; + let gas_used = [ + 10000000, 10000000, 10000000, 9000000, 10001000, 0, 10000000, 10000000, 10000000, + 10000000, + ]; + let gas_limit = [ + 10000000, 12000000, 14000000, 10000000, 14000000, 2000000, 18000000, 18000000, + 18000000, 18000000, + ]; + let next_base_fee = [ + 1100000048, 1080000000, 1065714297, 1167067046, 1128881311, 1028254188, 1098203452, 1, + 2, 3, + ]; + + for i in 0..base_fee.len() { + assert_eq!( + next_base_fee[i], + calc_next_block_base_fee( + gas_used[i] as u128, + gas_limit[i] as u128, + base_fee[i] as u128, + BaseFeeParams::optimism_sepolia(), + ) as u64 + ); + } + } + + #[test] + fn calculate_optimism_base_fee_success() { + let base_fee = [ + 1000000000, 1000000000, 1000000000, 1072671875, 1059263476, 1049238967, 1049238967, 0, + 1, 2, + ]; + let gas_used = [ + 10000000, 10000000, 10000000, 9000000, 10001000, 0, 10000000, 10000000, 10000000, + 10000000, + ]; + let gas_limit = [ + 10000000, 12000000, 14000000, 10000000, 14000000, 2000000, 18000000, 18000000, + 18000000, 18000000, + ]; + let next_base_fee = [ + 1100000048, 1080000000, 1065714297, 1167067046, 1128881311, 1028254188, 1098203452, 1, + 2, 3, + ]; + + for i in 0..base_fee.len() { + assert_eq!( + next_base_fee[i], + calc_next_block_base_fee( + gas_used[i] as u128, + gas_limit[i] as u128, + base_fee[i] as u128, + BaseFeeParams::optimism(), + ) as u64 + ); + } + } + + #[test] + fn calculate_base_sepolia_base_fee_success() { + let base_fee = [ + 1000000000, 1000000000, 1000000000, 1072671875, 1059263476, 1049238967, 1049238967, 0, + 1, 2, + ]; + let gas_used = [ + 10000000, 10000000, 10000000, 9000000, 10001000, 0, 10000000, 10000000, 10000000, + 10000000, + ]; + let gas_limit = [ + 10000000, 12000000, 14000000, 10000000, 14000000, 2000000, 18000000, 18000000, + 18000000, 18000000, + ]; + let next_base_fee = [ + 1180000000, 1146666666, 1122857142, 1244299375, 1189416692, 1028254188, 1144836295, 1, + 2, 3, + ]; + + for i in 0..base_fee.len() { + assert_eq!( + next_base_fee[i], + calc_next_block_base_fee( + gas_used[i] as u128, + gas_limit[i] as u128, + base_fee[i] as u128, + BaseFeeParams::base_sepolia(), + ) as u64 + ); + } + } } From 629b496e8106dc92af1cc2eddbac7bb479705453 Mon Sep 17 00:00:00 2001 From: morito Date: Thu, 4 Jul 2024 15:24:19 +0900 Subject: [PATCH 47/61] feat(eip1559): Support Optimism Canyon hardfork (#1010) * feat(eip1559): Support Optimism Canyon harfork * fix --- crates/eips/src/eip1559/basefee.rs | 26 ++++++++++++++++++++++ crates/eips/src/eip1559/constants.rs | 6 ++++++ crates/eips/src/eip1559/helpers.rs | 32 ++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+) diff --git a/crates/eips/src/eip1559/basefee.rs b/crates/eips/src/eip1559/basefee.rs index 2ae88191f27..ebb673f9b8e 100644 --- a/crates/eips/src/eip1559/basefee.rs +++ b/crates/eips/src/eip1559/basefee.rs @@ -3,8 +3,10 @@ use crate::{ eip1559::constants::{ BASE_SEPOLIA_EIP1559_DEFAULT_ELASTICITY_MULTIPLIER, DEFAULT_BASE_FEE_MAX_CHANGE_DENOMINATOR, DEFAULT_ELASTICITY_MULTIPLIER, + OP_MAINNET_EIP1559_BASE_FEE_MAX_CHANGE_DENOMINATOR_CANYON, OP_MAINNET_EIP1559_DEFAULT_BASE_FEE_MAX_CHANGE_DENOMINATOR, OP_MAINNET_EIP1559_DEFAULT_ELASTICITY_MULTIPLIER, + OP_SEPOLIA_EIP1559_BASE_FEE_MAX_CHANGE_DENOMINATOR_CANYON, OP_SEPOLIA_EIP1559_DEFAULT_BASE_FEE_MAX_CHANGE_DENOMINATOR, OP_SEPOLIA_EIP1559_DEFAULT_ELASTICITY_MULTIPLIER, }, @@ -44,6 +46,14 @@ impl BaseFeeParams { } } + /// Get the base fee parameters for Optimism Mainnet (post Canyon) + pub const fn optimism_canyon() -> Self { + Self { + max_change_denominator: OP_MAINNET_EIP1559_BASE_FEE_MAX_CHANGE_DENOMINATOR_CANYON, + elasticity_multiplier: OP_MAINNET_EIP1559_DEFAULT_ELASTICITY_MULTIPLIER, + } + } + /// Get the base fee parameters for Optimism Sepolia pub const fn optimism_sepolia() -> Self { Self { @@ -52,6 +62,14 @@ impl BaseFeeParams { } } + /// Get the base fee parameters for Optimism Sepolia (post Canyon) + pub const fn optimism_sepolia_canyon() -> Self { + Self { + max_change_denominator: OP_SEPOLIA_EIP1559_BASE_FEE_MAX_CHANGE_DENOMINATOR_CANYON, + elasticity_multiplier: OP_SEPOLIA_EIP1559_DEFAULT_ELASTICITY_MULTIPLIER, + } + } + /// Get the base fee parameters for Base Sepolia pub const fn base_sepolia() -> Self { Self { @@ -60,6 +78,14 @@ impl BaseFeeParams { } } + /// Get the base fee parameters for Base Sepolia (post Canyon) + pub const fn base_sepolia_canyon() -> Self { + Self { + max_change_denominator: OP_SEPOLIA_EIP1559_BASE_FEE_MAX_CHANGE_DENOMINATOR_CANYON, + elasticity_multiplier: BASE_SEPOLIA_EIP1559_DEFAULT_ELASTICITY_MULTIPLIER, + } + } + /// Calculate the base fee for the next block based on the EIP-1559 specification. /// /// See also [calc_next_block_base_fee] diff --git a/crates/eips/src/eip1559/constants.rs b/crates/eips/src/eip1559/constants.rs index 1b6cb0b804c..80837888668 100644 --- a/crates/eips/src/eip1559/constants.rs +++ b/crates/eips/src/eip1559/constants.rs @@ -30,6 +30,9 @@ pub const DEFAULT_ELASTICITY_MULTIPLIER: u64 = 2; /// [transaction costs](https://community.optimism.io/docs/developers/build/differences/#transaction-costs) doc. pub(crate) const OP_SEPOLIA_EIP1559_DEFAULT_BASE_FEE_MAX_CHANGE_DENOMINATOR: u128 = 50; +/// Base fee max change denominator for Optimism Sepolia as defined in the Optimism Canyon hardfork. +pub(crate) const OP_SEPOLIA_EIP1559_BASE_FEE_MAX_CHANGE_DENOMINATOR_CANYON: u128 = 250; + /// Base fee max change denominator for Optimism Sepolia as defined in the Optimism /// [transaction costs](https://community.optimism.io/docs/developers/build/differences/#transaction-costs) doc. pub(crate) const OP_SEPOLIA_EIP1559_DEFAULT_ELASTICITY_MULTIPLIER: u128 = 6; @@ -38,6 +41,9 @@ pub(crate) const OP_SEPOLIA_EIP1559_DEFAULT_ELASTICITY_MULTIPLIER: u128 = 6; /// [transaction costs](https://community.optimism.io/docs/developers/build/differences/#transaction-costs) doc. pub(crate) const OP_MAINNET_EIP1559_DEFAULT_BASE_FEE_MAX_CHANGE_DENOMINATOR: u128 = 50; +/// Base fee max change denominator for Optimism Mainnet as defined in the Optimism Canyon hardfork. +pub(crate) const OP_MAINNET_EIP1559_BASE_FEE_MAX_CHANGE_DENOMINATOR_CANYON: u128 = 250; + /// Base fee max change denominator for Optimism Mainnet as defined in the Optimism /// [transaction costs](https://community.optimism.io/docs/developers/build/differences/#transaction-costs) doc. pub(crate) const OP_MAINNET_EIP1559_DEFAULT_ELASTICITY_MULTIPLIER: u128 = 6; diff --git a/crates/eips/src/eip1559/helpers.rs b/crates/eips/src/eip1559/helpers.rs index c68e3b9a8c2..5bea1fa2314 100644 --- a/crates/eips/src/eip1559/helpers.rs +++ b/crates/eips/src/eip1559/helpers.rs @@ -166,6 +166,38 @@ mod tests { } } + #[test] + fn calculate_optimism_canyon_base_fee_success() { + let base_fee = [ + 1000000000, 1000000000, 1000000000, 1072671875, 1059263476, 1049238967, 1049238967, 0, + 1, 2, + ]; + let gas_used = [ + 10000000, 10000000, 10000000, 9000000, 10001000, 0, 10000000, 10000000, 10000000, + 10000000, + ]; + let gas_limit = [ + 10000000, 12000000, 14000000, 10000000, 14000000, 2000000, 18000000, 18000000, + 18000000, 18000000, + ]; + let next_base_fee = [ + 1020000009, 1016000000, 1013142859, 1091550909, 1073187043, 1045042012, 1059031864, 1, + 2, 3, + ]; + + for i in 0..base_fee.len() { + assert_eq!( + next_base_fee[i], + calc_next_block_base_fee( + gas_used[i] as u128, + gas_limit[i] as u128, + base_fee[i] as u128, + BaseFeeParams::optimism_canyon(), + ) as u64 + ); + } + } + #[test] fn calculate_base_sepolia_base_fee_success() { let base_fee = [ From aa01a154dedc2bcad6f59acbd74755df74212997 Mon Sep 17 00:00:00 2001 From: morito Date: Thu, 4 Jul 2024 16:12:34 +0900 Subject: [PATCH 48/61] chore(docs): Add the missing crate `rpc-types-mev` (#1011) * chore(docs): Add the missing crate `rpc-types-mev` * fix --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 84a60b93079..7f618a9823e 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,7 @@ This repository contains the following crates: - [`alloy-rpc-types-beacon`] - Types for the [Ethereum Beacon Node API][beacon-apis] - [`alloy-rpc-types-engine`] - Types for the `engine` Ethereum JSON-RPC namespace - [`alloy-rpc-types-eth`] - Types for the `eth` Ethereum JSON-RPC namespace + - [`alloy-rpc-types-mev`] - Types for the MEV bundle JSON-RPC namespace - [`alloy-rpc-types-trace`] - Types for the `trace` Ethereum JSON-RPC namespace - [`alloy-rpc-types-txpool`] - Types for the `txpool` Ethereum JSON-RPC namespace - [`alloy-serde`] - [Serde]-related utilities @@ -86,6 +87,7 @@ This repository contains the following crates: [`alloy-rpc-types-beacon`]: https://github.com/alloy-rs/alloy/tree/main/crates/rpc-types-beacon [`alloy-rpc-types-engine`]: https://github.com/alloy-rs/alloy/tree/main/crates/rpc-types-engine [`alloy-rpc-types-eth`]: https://github.com/alloy-rs/alloy/tree/main/crates/rpc-types-eth +[`alloy-rpc-types-mev`]: https://github.com/alloy-rs/alloy/tree/main/crates/rpc-types-mev [`alloy-rpc-types-trace`]: https://github.com/alloy-rs/alloy/tree/main/crates/rpc-types-trace [`alloy-rpc-types-txpool`]: https://github.com/alloy-rs/alloy/tree/main/crates/rpc-types-txpool [`alloy-serde`]: https://github.com/alloy-rs/alloy/tree/main/crates/serde From 83e5aa96b1750987a952dd3fc929b0396326cc15 Mon Sep 17 00:00:00 2001 From: Arsenii Kulikov Date: Thu, 4 Jul 2024 10:33:59 +0300 Subject: [PATCH 49/61] feat: impl Transaction for TxEnvelope (#1006) --- crates/consensus/src/transaction/envelope.rs | 69 +++++++++++++++++++- 1 file changed, 67 insertions(+), 2 deletions(-) diff --git a/crates/consensus/src/transaction/envelope.rs b/crates/consensus/src/transaction/envelope.rs index b586efffcb3..e8fdd71c79c 100644 --- a/crates/consensus/src/transaction/envelope.rs +++ b/crates/consensus/src/transaction/envelope.rs @@ -1,8 +1,8 @@ use core::fmt; -use crate::{Signed, TxEip1559, TxEip2930, TxLegacy}; +use crate::{Signed, Transaction, TxEip1559, TxEip2930, TxLegacy}; use alloy_eips::eip2718::{Decodable2718, Eip2718Error, Eip2718Result, Encodable2718}; -use alloy_primitives::B256; +use alloy_primitives::{TxKind, B256}; use alloy_rlp::{Decodable, Encodable, Header}; use crate::transaction::eip4844::{TxEip4844, TxEip4844Variant, TxEip4844WithSidecar}; @@ -361,6 +361,71 @@ impl Encodable2718 for TxEnvelope { } } +impl Transaction for TxEnvelope { + fn chain_id(&self) -> Option { + match self { + Self::Legacy(tx) => tx.tx().chain_id(), + Self::Eip2930(tx) => tx.tx().chain_id(), + Self::Eip1559(tx) => tx.tx().chain_id(), + Self::Eip4844(tx) => tx.tx().chain_id(), + } + } + + fn gas_limit(&self) -> u128 { + match self { + Self::Legacy(tx) => tx.tx().gas_limit(), + Self::Eip2930(tx) => tx.tx().gas_limit(), + Self::Eip1559(tx) => tx.tx().gas_limit(), + Self::Eip4844(tx) => tx.tx().gas_limit(), + } + } + + fn gas_price(&self) -> Option { + match self { + Self::Legacy(tx) => tx.tx().gas_price(), + Self::Eip2930(tx) => tx.tx().gas_price(), + Self::Eip1559(tx) => tx.tx().gas_price(), + Self::Eip4844(tx) => tx.tx().gas_price(), + } + } + + fn input(&self) -> &[u8] { + match self { + Self::Legacy(tx) => tx.tx().input(), + Self::Eip2930(tx) => tx.tx().input(), + Self::Eip1559(tx) => tx.tx().input(), + Self::Eip4844(tx) => tx.tx().input(), + } + } + + fn nonce(&self) -> u64 { + match self { + Self::Legacy(tx) => tx.tx().nonce(), + Self::Eip2930(tx) => tx.tx().nonce(), + Self::Eip1559(tx) => tx.tx().nonce(), + Self::Eip4844(tx) => tx.tx().nonce(), + } + } + + fn to(&self) -> TxKind { + match self { + Self::Legacy(tx) => tx.tx().to(), + Self::Eip2930(tx) => tx.tx().to(), + Self::Eip1559(tx) => tx.tx().to(), + Self::Eip4844(tx) => tx.tx().to(), + } + } + + fn value(&self) -> alloy_primitives::U256 { + match self { + Self::Legacy(tx) => tx.tx().value(), + Self::Eip2930(tx) => tx.tx().value(), + Self::Eip1559(tx) => tx.tx().value(), + Self::Eip4844(tx) => tx.tx().value(), + } + } +} + #[cfg(test)] mod tests { use super::*; From ca1f1f00dc98c975ab81ea095ecd6de627974e82 Mon Sep 17 00:00:00 2001 From: Thomas Coratger <60488569+tcoratger@users.noreply.github.com> Date: Thu, 4 Jul 2024 09:34:52 +0200 Subject: [PATCH 50/61] feat(rpc-types-eth): add more utils to `TransactionIndex` (#1007) feat(rpc-types-eth): add more utils to TransactionIndex --- crates/rpc-types-eth/src/call.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/crates/rpc-types-eth/src/call.rs b/crates/rpc-types-eth/src/call.rs index 1aee6c1beea..934b637e1eb 100644 --- a/crates/rpc-types-eth/src/call.rs +++ b/crates/rpc-types-eth/src/call.rs @@ -63,6 +63,11 @@ impl TransactionIndex { matches!(self, Self::All) } + /// Returns true if this is the index variant + pub const fn is_index(&self) -> bool { + matches!(self, Self::Index(_)) + } + /// Returns the index if this is the index variant pub const fn index(&self) -> Option { match self { @@ -72,6 +77,12 @@ impl TransactionIndex { } } +impl From for TransactionIndex { + fn from(index: usize) -> Self { + Self::Index(index) + } +} + impl Serialize for TransactionIndex { fn serialize(&self, serializer: S) -> Result where From a24e30b5b4035ea15827f8d0b6ddc1144ab17375 Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Thu, 4 Jul 2024 13:46:16 +0200 Subject: [PATCH 51/61] feat: add consolidation requests to v4 payload (#1013) --- crates/eips/src/eip7251.rs | 2 +- crates/rpc-types-beacon/src/payload.rs | 29 +++++++++++++++++++++----- crates/rpc-types-engine/src/payload.rs | 8 ++++++- 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/crates/eips/src/eip7251.rs b/crates/eips/src/eip7251.rs index b62a808f7e6..cb72a0c5352 100644 --- a/crates/eips/src/eip7251.rs +++ b/crates/eips/src/eip7251.rs @@ -1,4 +1,4 @@ -//! Contains consolidtion types, first introduced in the [Prague hardfork](https://github.com/ethereum/execution-apis/blob/main/src/engine/prague.md). +//! Contains consolidation types, first introduced in the [Prague hardfork](https://github.com/ethereum/execution-apis/blob/main/src/engine/prague.md). //! //! See also [EIP-7251](https://eips.ethereum.org/EIPS/eip-7251): Increase the MAX_EFFECTIVE_BALANCE diff --git a/crates/rpc-types-beacon/src/payload.rs b/crates/rpc-types-beacon/src/payload.rs index 05cbd37db75..dab8c7aa8fe 100644 --- a/crates/rpc-types-beacon/src/payload.rs +++ b/crates/rpc-types-beacon/src/payload.rs @@ -9,7 +9,10 @@ //! See also use crate::{withdrawals::BeaconWithdrawal, BlsPublicKey}; -use alloy_eips::{eip4895::Withdrawal, eip6110::DepositRequest, eip7002::WithdrawalRequest}; +use alloy_eips::{ + eip4895::Withdrawal, eip6110::DepositRequest, eip7002::WithdrawalRequest, + eip7251::ConsolidationRequest, +}; use alloy_primitives::{Address, Bloom, Bytes, B256, U256}; use alloy_rpc_types_engine::{ ExecutionPayload, ExecutionPayloadV1, ExecutionPayloadV2, ExecutionPayloadV3, @@ -473,23 +476,39 @@ struct BeaconExecutionPayloadV4<'a> { payload_inner: BeaconExecutionPayloadV3<'a>, deposit_requests: Vec, withdrawal_requests: Vec, + consolidation_requests: Vec, } impl<'a> From> for ExecutionPayloadV4 { fn from(payload: BeaconExecutionPayloadV4<'a>) -> Self { - let BeaconExecutionPayloadV4 { payload_inner, deposit_requests, withdrawal_requests } = - payload; - Self { payload_inner: payload_inner.into(), deposit_requests, withdrawal_requests } + let BeaconExecutionPayloadV4 { + payload_inner, + deposit_requests, + withdrawal_requests, + consolidation_requests, + } = payload; + Self { + payload_inner: payload_inner.into(), + deposit_requests, + withdrawal_requests, + consolidation_requests, + } } } impl<'a> From<&'a ExecutionPayloadV4> for BeaconExecutionPayloadV4<'a> { fn from(value: &'a ExecutionPayloadV4) -> Self { - let ExecutionPayloadV4 { payload_inner, deposit_requests, withdrawal_requests } = value; + let ExecutionPayloadV4 { + payload_inner, + deposit_requests, + withdrawal_requests, + consolidation_requests, + } = value; BeaconExecutionPayloadV4 { payload_inner: payload_inner.into(), deposit_requests: deposit_requests.clone(), withdrawal_requests: withdrawal_requests.clone(), + consolidation_requests: consolidation_requests.clone(), } } } diff --git a/crates/rpc-types-engine/src/payload.rs b/crates/rpc-types-engine/src/payload.rs index 6c7858c1158..0cb2b27a738 100644 --- a/crates/rpc-types-engine/src/payload.rs +++ b/crates/rpc-types-engine/src/payload.rs @@ -1,6 +1,8 @@ //! Payload types. use alloy_consensus::{Blob, Bytes48}; -use alloy_eips::{eip6110::DepositRequest, eip7002::WithdrawalRequest}; +use alloy_eips::{ + eip6110::DepositRequest, eip7002::WithdrawalRequest, eip7251::ConsolidationRequest, +}; use alloy_primitives::{Address, Bloom, Bytes, B256, B64, U256}; use alloy_rpc_types_eth::{transaction::BlobTransactionSidecar, Withdrawal}; use serde::{ser::SerializeMap, Deserialize, Deserializer, Serialize, Serializer}; @@ -439,6 +441,10 @@ pub struct ExecutionPayloadV4 { /// /// See [EIP-7002](https://eips.ethereum.org/EIPS/eip-7002). pub withdrawal_requests: Vec, + /// Array of consolidation requests. + /// + /// See [EIP-7251](https://eips.ethereum.org/EIPS/eip-7251). + pub consolidation_requests: Vec, } impl ExecutionPayloadV4 { From 2133aadd5f6b2ce1ee946b2d72d2fddb82379ca3 Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Thu, 4 Jul 2024 13:57:43 +0200 Subject: [PATCH 52/61] feat: add execution payloadbodyv2 (#1012) --- crates/rpc-types-engine/src/payload.rs | 30 ++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/crates/rpc-types-engine/src/payload.rs b/crates/rpc-types-engine/src/payload.rs index 0cb2b27a738..82269f3a378 100644 --- a/crates/rpc-types-engine/src/payload.rs +++ b/crates/rpc-types-engine/src/payload.rs @@ -11,6 +11,9 @@ use std::fmt; /// The execution payload body response that allows for `null` values. pub type ExecutionPayloadBodiesV1 = Vec>; +/// The execution payload body response that allows for `null` values. +pub type ExecutionPayloadBodiesV2 = Vec>; + /// And 8-byte identifier for an execution payload. #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct PayloadId(pub B64); @@ -854,6 +857,33 @@ pub struct ExecutionPayloadBodyV1 { pub withdrawals: Option>, } +/// This structure has the syntax of [`ExecutionPayloadBodyV1`] and appends the new fields: +/// depositRequests and withdrawalRequests. +/// +/// See also: +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ExecutionPayloadBodyV2 { + /// Enveloped encoded transactions. + pub transactions: Vec, + /// All withdrawals in the block. + /// + /// Will always be `None` if pre shanghai. + pub withdrawals: Option>, + /// Array of deposits requests. + /// + /// Will always be `None` if pre prague. + pub deposit_requests: Option>, + /// Array of withdrawal requests. + /// + /// Will always be `None` if pre prague. + pub withdrawal_requests: Option>, + /// Array of consolidation requests. + /// + /// Will always be `None` if pre prague. + pub consolidation_requests: Option>, +} + /// This structure contains the attributes required to initiate a payload build process in the /// context of an `engine_forkchoiceUpdated` call. #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] From 40e6860cdae981807ead6a828b5f4c9f568cd9fc Mon Sep 17 00:00:00 2001 From: teddav Date: Fri, 5 Jul 2024 12:05:20 +0200 Subject: [PATCH 53/61] chore: convert rcp-types-eth block Header to consensus Header (#1014) * chore: convert rcp-types-eth block Header to consensus Header * clippy * custom conversion error --- crates/rpc-types-eth/src/block.rs | 125 +++++++++++++++++++++++++++++- 1 file changed, 124 insertions(+), 1 deletion(-) diff --git a/crates/rpc-types-eth/src/block.rs b/crates/rpc-types-eth/src/block.rs index c69b1d45084..c2ff60ade05 100644 --- a/crates/rpc-types-eth/src/block.rs +++ b/crates/rpc-types-eth/src/block.rs @@ -1,6 +1,6 @@ //! Block RPC types. -use crate::{Transaction, Withdrawal}; +use crate::{ConversionError, Transaction, Withdrawal}; use alloy_primitives::{Address, BlockHash, Bloom, Bytes, B256, B64, U256, U64}; use alloy_serde::OtherFields; use serde::{ser::Error, Deserialize, Serialize, Serializer}; @@ -149,6 +149,61 @@ impl Header { } } +impl TryFrom
for alloy_consensus::Header { + type Error = ConversionError; + fn try_from(value: Header) -> Result { + let Header { + parent_hash, + uncles_hash, + miner, + state_root, + transactions_root, + receipts_root, + logs_bloom, + difficulty, + number, + gas_limit, + gas_used, + timestamp, + extra_data, + mix_hash, + nonce, + base_fee_per_gas, + withdrawals_root, + blob_gas_used, + excess_blob_gas, + parent_beacon_block_root, + requests_root, + // not included in the consensus header + hash: _hash, + total_difficulty: _total_difficulty, + } = value; + Ok(Self { + parent_hash, + ommers_hash: uncles_hash, + beneficiary: miner, + state_root, + transactions_root, + receipts_root, + withdrawals_root, + logs_bloom, + difficulty, + number: number.ok_or(ConversionError::MissingBlockNumber)?, + gas_limit, + gas_used, + timestamp, + mix_hash: mix_hash.ok_or(ConversionError::Custom("missing block mix_hash".into()))?, + nonce: nonce.ok_or(ConversionError::Custom("missing block nonce".into()))?, + base_fee_per_gas, + blob_gas_used, + excess_blob_gas, + parent_beacon_block_root, + requests_root, + extra_data, + }) + } +} + /// Block Transactions depending on the boolean attribute of `eth_getBlockBy*`, /// or if used by `eth_getUncle*` #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] @@ -575,6 +630,7 @@ pub struct BlockOverrides { #[cfg(test)] mod tests { + use alloy_primitives::keccak256; use arbitrary::Arbitrary; use rand::Rng; @@ -888,4 +944,71 @@ mod tests { assert!(block.transactions.is_empty()); assert!(block.transactions.as_transactions().is_some()); } + + #[test] + fn recompute_block_hash() { + let s = r#"{ + "hash": "0xb25d0e54ca0104e3ebfb5a1dcdf9528140854d609886a300946fd6750dcb19f4", + "parentHash": "0x9400ec9ef59689c157ac89eeed906f15ddd768f94e1575e0e27d37c241439a5d", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "miner": "0x829bd824b016326a401d083b33d092293333a830", + "stateRoot": "0x546e330050c66d02923e7f1f3e925efaf64e4384eeecf2288f40088714a77a84", + "transactionsRoot": "0xd5eb3ad6d7c7a4798cc5fb14a6820073f44a941107c5d79dac60bd16325631fe", + "receiptsRoot": "0xb21c41cbb3439c5af25304e1405524c885e733b16203221900cb7f4b387b62f0", + "logsBloom": "0x1f304e641097eafae088627298685d20202004a4a59e4d8900914724e2402b028c9d596660581f361240816e82d00fa14250c9ca89840887a381efa600288283d170010ab0b2a0694c81842c2482457e0eb77c2c02554614007f42aaf3b4dc15d006a83522c86a240c06d241013258d90540c3008888d576a02c10120808520a2221110f4805200302624d22092b2c0e94e849b1e1aa80bc4cc3206f00b249d0a603ee4310216850e47c8997a20aa81fe95040a49ca5a420464600e008351d161dc00d620970b6a801535c218d0b4116099292000c08001943a225d6485528828110645b8244625a182c1a88a41087e6d039b000a180d04300d0680700a15794", + "difficulty": "0xc40faff9c737d", + "number": "0xa9a230", + "gasLimit": "0xbe5a66", + "gasUsed": "0xbe0fcc", + "timestamp": "0x5f93b749", + "totalDifficulty": "0x3dc957fd8167fb2684a", + "extraData": "0x7070796520e4b883e5bda9e7a59ee4bb99e9b1bc0103", + "mixHash": "0xd5e2b7b71fbe4ddfe552fb2377bf7cddb16bbb7e185806036cee86994c6e97fc", + "nonce": "0x4722f2acd35abe0f", + "uncles": [], + "transactions": [], + "size": "0xaeb6" +}"#; + let block = serde_json::from_str::(s).unwrap(); + let header: alloy_consensus::Header = block.clone().header.try_into().unwrap(); + let recomputed_hash = keccak256(alloy_rlp::encode(&header)); + assert_eq!(recomputed_hash, block.header.hash.unwrap()); + + let s2 = r#"{ + "baseFeePerGas":"0x886b221ad", + "blobGasUsed":"0x0", + "difficulty":"0x0", + "excessBlobGas":"0x0", + "extraData":"0x6265617665726275696c642e6f7267", + "gasLimit":"0x1c9c380", + "gasUsed":"0xb0033c", + "hash":"0x85cdcbe36217fd57bf2c33731d8460657a7ce512401f49c9f6392c82a7ccf7ac", + "logsBloom":"0xc36919406572730518285284f2293101104140c0d42c4a786c892467868a8806f40159d29988002870403902413a1d04321320308da2e845438429e0012a00b419d8ccc8584a1c28f82a415d04eab8a5ae75c00d07761acf233414c08b6d9b571c06156086c70ea5186e9b989b0c2d55c0213c936805cd2ab331589c90194d070c00867549b1e1be14cb24500b0386cd901197c1ef5a00da453234fa48f3003dcaa894e3111c22b80e17f7d4388385a10720cda1140c0400f9e084ca34fc4870fb16b472340a2a6a63115a82522f506c06c2675080508834828c63defd06bc2331b4aa708906a06a560457b114248041e40179ebc05c6846c1e922125982f427", + "miner":"0x95222290dd7278aa3ddd389cc1e1d165cc4bafe5", + "mixHash":"0x4c068e902990f21f92a2456fc75c59bec8be03b7f13682b6ebd27da56269beb5", + "nonce":"0x0000000000000000", + "number":"0x128c6df", + "parentBeaconBlockRoot":"0x2843cb9f7d001bd58816a915e685ed96a555c9aeec1217736bd83a96ebd409cc", + "parentHash":"0x90926e0298d418181bd20c23b332451e35fd7d696b5dcdc5a3a0a6b715f4c717", + "receiptsRoot":"0xd43aa19ecb03571d1b86d89d9bb980139d32f2f2ba59646cd5c1de9e80c68c90", + "sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "size":"0xdcc3", + "stateRoot":"0x707875120a7103621fb4131df59904cda39de948dfda9084a1e3da44594d5404", + "timestamp":"0x65f5f4c3", + "transactionsRoot":"0x889a1c26dc42ba829dab552b779620feac231cde8a6c79af022bdc605c23a780", + "withdrawals":[ + { + "index":"0x24d80e6", + "validatorIndex":"0x8b2b6", + "address":"0x7cd1122e8e118b12ece8d25480dfeef230da17ff", + "amount":"0x1161f10" + } + ], + "withdrawalsRoot":"0x360c33f20eeed5efbc7d08be46e58f8440af5db503e40908ef3d1eb314856ef7" + }"#; + let block2 = serde_json::from_str::(s2).unwrap(); + let header: alloy_consensus::Header = block2.clone().header.try_into().unwrap(); + let recomputed_hash = keccak256(alloy_rlp::encode(&header)); + assert_eq!(recomputed_hash, block2.header.hash.unwrap()); + } } From 96e3a846347ce715351344c12a6d8a3e31f3aff8 Mon Sep 17 00:00:00 2001 From: Yash Atreya <44857776+yash-atreya@users.noreply.github.com> Date: Fri, 5 Jul 2024 16:49:05 +0530 Subject: [PATCH 54/61] feat(transport): retry layer (#849) --- crates/json-rpc/src/response/error.rs | 47 ++++++ crates/transport/Cargo.toml | 6 +- crates/transport/src/error.rs | 65 +++++++- crates/transport/src/layers/mod.rs | 6 + crates/transport/src/layers/retry.rs | 228 ++++++++++++++++++++++++++ crates/transport/src/lib.rs | 2 + 6 files changed, 350 insertions(+), 4 deletions(-) create mode 100644 crates/transport/src/layers/mod.rs create mode 100644 crates/transport/src/layers/retry.rs diff --git a/crates/json-rpc/src/response/error.rs b/crates/json-rpc/src/response/error.rs index 371fe4e97c9..c6de4dba544 100644 --- a/crates/json-rpc/src/response/error.rs +++ b/crates/json-rpc/src/response/error.rs @@ -20,6 +20,53 @@ pub struct ErrorPayload> { pub data: Option, } +impl ErrorPayload { + /// Analyzes the [ErrorPayload] and decides if the request should be retried based on the + /// error code or the message. + pub fn is_retry_err(&self) -> bool { + // alchemy throws it this way + if self.code == 429 { + return true; + } + + // This is an infura error code for `exceeded project rate limit` + if self.code == -32005 { + return true; + } + + // alternative alchemy error for specific IPs + if self.code == -32016 && self.message.contains("rate limit") { + return true; + } + + // quick node error `"credits limited to 6000/sec"` + // + if self.code == -32012 && self.message.contains("credits") { + return true; + } + + // quick node rate limit error: `100/second request limit reached - reduce calls per second + // or upgrade your account at quicknode.com` + if self.code == -32007 && self.message.contains("request limit reached") { + return true; + } + + match self.message.as_str() { + // this is commonly thrown by infura and is apparently a load balancer issue, see also + "header not found" => true, + // also thrown by infura if out of budget for the day and ratelimited + "daily request count exceeded, request rate limited" => true, + msg => { + msg.contains("rate limit") + || msg.contains("rate exceeded") + || msg.contains("too many requests") + || msg.contains("credits limited") + || msg.contains("request limit") + } + } + } +} + impl fmt::Display for ErrorPayload { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "error code {}: {}", self.code, self.message) diff --git a/crates/transport/Cargo.toml b/crates/transport/Cargo.toml index 59e3c3c5c3f..89c3cca99d3 100644 --- a/crates/transport/Cargo.toml +++ b/crates/transport/Cargo.toml @@ -29,12 +29,12 @@ serde.workspace = true thiserror.workspace = true tower.workspace = true url.workspace = true +tracing.workspace = true +tokio = { workspace = true, features = ["rt", "time"] } [target.'cfg(target_arch = "wasm32")'.dependencies] wasm-bindgen-futures = { version = "0.4", optional = true } -[target.'cfg(not(target_arch = "wasm32"))'.dependencies] -tokio = { workspace = true, features = ["rt"] } - [features] + wasm-bindgen = ["dep:wasm-bindgen-futures"] diff --git a/crates/transport/src/error.rs b/crates/transport/src/error.rs index 04b76f0c896..55b55f1bc1c 100644 --- a/crates/transport/src/error.rs +++ b/crates/transport/src/error.rs @@ -1,4 +1,5 @@ -use alloy_json_rpc::{Id, RpcError, RpcResult}; +use alloy_json_rpc::{ErrorPayload, Id, RpcError, RpcResult}; +use serde::Deserialize; use serde_json::value::RawValue; use std::{error::Error as StdError, fmt::Debug}; use thiserror::Error; @@ -110,3 +111,65 @@ impl HttpError { false } } + +/// Extension trait to implement methods for [`RpcError`]. +pub(crate) trait RpcErrorExt { + /// Analyzes whether to retry the request depending on the error. + fn is_retryable(&self) -> bool; + + /// Fetches the backoff hint from the error message if present + fn backoff_hint(&self) -> Option; +} + +impl RpcErrorExt for RpcError { + fn is_retryable(&self) -> bool { + match self { + // There was a transport-level error. This is either a non-retryable error, + // or a server error that should be retried. + Self::Transport(err) => err.is_retry_err(), + // The transport could not serialize the error itself. The request was malformed from + // the start. + Self::SerError(_) => false, + Self::DeserError { text, .. } => { + if let Ok(resp) = serde_json::from_str::(text) { + return resp.is_retry_err(); + } + + // some providers send invalid JSON RPC in the error case (no `id:u64`), but the + // text should be a `JsonRpcError` + #[derive(Deserialize)] + struct Resp { + error: ErrorPayload, + } + + if let Ok(resp) = serde_json::from_str::(text) { + return resp.error.is_retry_err(); + } + + false + } + Self::ErrorResp(err) => err.is_retry_err(), + Self::NullResp => true, + _ => false, + } + } + + fn backoff_hint(&self) -> Option { + if let Self::ErrorResp(resp) = self { + let data = resp.try_data_as::(); + if let Some(Ok(data)) = data { + // if daily rate limit exceeded, infura returns the requested backoff in the error + // response + let backoff_seconds = &data["rate"]["backoff_seconds"]; + // infura rate limit error + if let Some(seconds) = backoff_seconds.as_u64() { + return Some(std::time::Duration::from_secs(seconds)); + } + if let Some(seconds) = backoff_seconds.as_f64() { + return Some(std::time::Duration::from_secs(seconds as u64 + 1)); + } + } + } + None + } +} diff --git a/crates/transport/src/layers/mod.rs b/crates/transport/src/layers/mod.rs new file mode 100644 index 00000000000..a6a1ccbf7b4 --- /dev/null +++ b/crates/transport/src/layers/mod.rs @@ -0,0 +1,6 @@ +//! Module for housing transport layers. + +mod retry; + +/// RetryBackoffLayer +pub use retry::{RateLimitRetryPolicy, RetryBackoffLayer, RetryBackoffService, RetryPolicy}; diff --git a/crates/transport/src/layers/retry.rs b/crates/transport/src/layers/retry.rs new file mode 100644 index 00000000000..ce66cc0fc6c --- /dev/null +++ b/crates/transport/src/layers/retry.rs @@ -0,0 +1,228 @@ +use crate::{ + error::{RpcErrorExt, TransportError, TransportErrorKind}, + TransportFut, +}; +use alloy_json_rpc::{RequestPacket, ResponsePacket}; +use std::{ + sync::{ + atomic::{AtomicU32, Ordering}, + Arc, + }, + task::{Context, Poll}, + time::Duration, +}; +use tower::{Layer, Service}; +use tracing::trace; + +/// A Transport Layer that is responsible for retrying requests based on the +/// error type. See [`TransportError`]. +/// +/// TransportError: crate::error::TransportError +#[derive(Debug, Clone)] +pub struct RetryBackoffLayer { + /// The maximum number of retries for rate limit errors + max_rate_limit_retries: u32, + /// The initial backoff in milliseconds + initial_backoff: u64, + /// The number of compute units per second for this provider + compute_units_per_second: u64, +} + +impl RetryBackoffLayer { + /// Creates a new retry layer with the given parameters. + pub const fn new( + max_rate_limit_retries: u32, + initial_backoff: u64, + compute_units_per_second: u64, + ) -> Self { + Self { max_rate_limit_retries, initial_backoff, compute_units_per_second } + } +} + +/// [RateLimitRetryPolicy] implements [RetryPolicy] to determine whether to retry depending on the +/// err. +#[derive(Debug, Copy, Clone, Default)] +#[non_exhaustive] +pub struct RateLimitRetryPolicy; + +/// [RetryPolicy] defines logic for which [TransportError] instances should +/// the client retry the request and try to recover from. +pub trait RetryPolicy: Send + Sync + std::fmt::Debug { + /// Whether to retry the request based on the given `error` + fn should_retry(&self, error: &TransportError) -> bool; + + /// Providers may include the `backoff` in the error response directly + fn backoff_hint(&self, error: &TransportError) -> Option; +} + +impl RetryPolicy for RateLimitRetryPolicy { + fn should_retry(&self, error: &TransportError) -> bool { + error.is_retryable() + } + + /// Provides a backoff hint if the error response contains it + fn backoff_hint(&self, error: &TransportError) -> Option { + error.backoff_hint() + } +} + +impl Layer for RetryBackoffLayer { + type Service = RetryBackoffService; + + fn layer(&self, inner: S) -> Self::Service { + RetryBackoffService { + inner, + policy: RateLimitRetryPolicy, + max_rate_limit_retries: self.max_rate_limit_retries, + initial_backoff: self.initial_backoff, + compute_units_per_second: self.compute_units_per_second, + requests_enqueued: Arc::new(AtomicU32::new(0)), + } + } +} + +/// A Tower Service used by the RetryBackoffLayer that is responsible for retrying requests based +/// on the error type. See [TransportError] and [RateLimitRetryPolicy]. +#[derive(Debug, Clone)] +pub struct RetryBackoffService { + /// The inner service + inner: S, + /// The retry policy + policy: RateLimitRetryPolicy, + /// The maximum number of retries for rate limit errors + max_rate_limit_retries: u32, + /// The initial backoff in milliseconds + initial_backoff: u64, + /// The number of compute units per second for this service + compute_units_per_second: u64, + /// The number of requests currently enqueued + requests_enqueued: Arc, +} + +impl RetryBackoffService { + const fn initial_backoff(&self) -> Duration { + Duration::from_millis(self.initial_backoff) + } +} + +impl Service for RetryBackoffService +where + S: Service + + Send + + 'static + + Clone, + S::Future: Send + 'static, +{ + type Response = ResponsePacket; + type Error = TransportError; + type Future = TransportFut<'static>; + + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { + // Our middleware doesn't care about backpressure, so it's ready as long + // as the inner service is ready. + self.inner.poll_ready(cx) + } + + fn call(&mut self, request: RequestPacket) -> Self::Future { + let inner = self.inner.clone(); + let this = self.clone(); + let mut inner = std::mem::replace(&mut self.inner, inner); + Box::pin(async move { + let ahead_in_queue = this.requests_enqueued.fetch_add(1, Ordering::SeqCst) as u64; + let mut rate_limit_retry_number: u32 = 0; + loop { + let err; + let res = inner.call(request.clone()).await; + + match res { + Ok(res) => { + if let Some(e) = res.as_error() { + err = TransportError::ErrorResp(e.clone()) + } else { + this.requests_enqueued.fetch_sub(1, Ordering::SeqCst); + return Ok(res); + } + } + Err(e) => err = e, + } + + let should_retry = this.policy.should_retry(&err); + if should_retry { + rate_limit_retry_number += 1; + if rate_limit_retry_number > this.max_rate_limit_retries { + return Err(TransportErrorKind::custom_str(&format!( + "Max retries exceeded {}", + err + ))); + } + trace!(%err, "retrying request"); + + let current_queued_reqs = this.requests_enqueued.load(Ordering::SeqCst) as u64; + + // try to extract the requested backoff from the error or compute the next + // backoff based on retry count + let backoff_hint = this.policy.backoff_hint(&err); + let next_backoff = backoff_hint.unwrap_or_else(|| this.initial_backoff()); + + // requests are usually weighted and can vary from 10 CU to several 100 CU, + // cheaper requests are more common some example alchemy + // weights: + // - `eth_getStorageAt`: 17 + // - `eth_getBlockByNumber`: 16 + // - `eth_newFilter`: 20 + // + // (coming from forking mode) assuming here that storage request will be the + // driver for Rate limits we choose `17` as the average cost + // of any request + const AVG_COST: u64 = 17u64; + let seconds_to_wait_for_compute_budget = compute_unit_offset_in_secs( + AVG_COST, + this.compute_units_per_second, + current_queued_reqs, + ahead_in_queue, + ); + let total_backoff = next_backoff + + std::time::Duration::from_secs(seconds_to_wait_for_compute_budget); + + trace!( + total_backoff_millis = total_backoff.as_millis(), + budget_backoff_millis = seconds_to_wait_for_compute_budget * 1000, + default_backoff_millis = next_backoff.as_millis(), + backoff_hint_millis = backoff_hint.map(|d| d.as_millis()), + "(all in ms) backing off due to rate limit" + ); + + tokio::time::sleep(total_backoff).await; + } else { + this.requests_enqueued.fetch_sub(1, Ordering::SeqCst); + return Err(err); + } + } + }) + } +} + +/// Calculates an offset in seconds by taking into account the number of currently queued requests, +/// number of requests that were ahead in the queue when the request was first issued, the average +/// cost a weighted request (heuristic), and the number of available compute units per seconds. +/// +/// Returns the number of seconds (the unit the remote endpoint measures compute budget) a request +/// is supposed to wait to not get rate limited. The budget per second is +/// `compute_units_per_second`, assuming an average cost of `avg_cost` this allows (in theory) +/// `compute_units_per_second / avg_cost` requests per seconds without getting rate limited. +/// By taking into account the number of concurrent request and the position in queue when the +/// request was first issued and determine the number of seconds a request is supposed to wait, if +/// at all +fn compute_unit_offset_in_secs( + avg_cost: u64, + compute_units_per_second: u64, + current_queued_requests: u64, + ahead_in_queue: u64, +) -> u64 { + let request_capacity_per_second = compute_units_per_second.saturating_div(avg_cost); + if current_queued_requests > request_capacity_per_second { + current_queued_requests.min(ahead_in_queue).saturating_div(request_capacity_per_second) + } else { + 0 + } +} diff --git a/crates/transport/src/lib.rs b/crates/transport/src/lib.rs index 8506fa61a2d..eed8a694221 100644 --- a/crates/transport/src/lib.rs +++ b/crates/transport/src/lib.rs @@ -26,6 +26,8 @@ pub use r#trait::Transport; pub use alloy_json_rpc::{RpcError, RpcResult}; pub use futures_utils_wasm::{impl_future, BoxFuture}; +pub mod layers; + /// Misc. utilities for building transports. pub mod utils; From 07d1de5bae01797eaecff489daa30fafdc583d07 Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Sat, 6 Jul 2024 09:16:38 +0200 Subject: [PATCH 55/61] feat: add helper to set both input and data fields (#1019) --- crates/rpc-types-eth/src/transaction/request.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/crates/rpc-types-eth/src/transaction/request.rs b/crates/rpc-types-eth/src/transaction/request.rs index c5ffd89d78e..ed27bae7ea4 100644 --- a/crates/rpc-types-eth/src/transaction/request.rs +++ b/crates/rpc-types-eth/src/transaction/request.rs @@ -503,11 +503,23 @@ impl TransactionInput { Self::maybe_input(Some(data)) } + /// Creates a new instance with the given input data and sets both `input` and `data` fields to + /// the same value. + pub fn both(data: Bytes) -> Self { + Self::maybe_both(Some(data)) + } + /// Creates a new instance with the given input data. pub const fn maybe_input(input: Option) -> Self { Self { input, data: None } } + /// Creates a new instance with the given input data and sets both `input` and `data` fields to + /// the same value. + pub fn maybe_both(input: Option) -> Self { + Self { data: input.clone(), input } + } + /// Consumes the type and returns the optional input data. #[inline] pub fn into_input(self) -> Option { From 75ef6a49e7e550d91825913d64358d3e8167045c Mon Sep 17 00:00:00 2001 From: Roman Date: Mon, 8 Jul 2024 13:58:35 +0400 Subject: [PATCH 56/61] Remove signature.v parity before calculating tx hash (#893) * Remove signature.v parity before calculating tx hash * Fix tx_hash parity for eip4844 * Fix review notes * Add signature chainid guard for a legacy tx * Revert "Add signature chainid guard for a legacy tx" This reverts commit a3fa3f8057c1aa2c5a9ccb6c798df8c5b33c831b. --- crates/consensus/src/transaction/eip1559.rs | 10 +- crates/consensus/src/transaction/eip2930.rs | 10 +- crates/consensus/src/transaction/eip4844.rs | 30 +++-- crates/consensus/src/transaction/envelope.rs | 125 +++++++++++++++++-- 4 files changed, 148 insertions(+), 27 deletions(-) diff --git a/crates/consensus/src/transaction/eip1559.rs b/crates/consensus/src/transaction/eip1559.rs index 585f14bfa2b..d195edb9444 100644 --- a/crates/consensus/src/transaction/eip1559.rs +++ b/crates/consensus/src/transaction/eip1559.rs @@ -305,14 +305,16 @@ impl SignableTransaction for TxEip1559 { } fn into_signed(self, signature: Signature) -> Signed { + // Drop any v chain id value to ensure the signature format is correct at the time of + // combination for an EIP-1559 transaction. V should indicate the y-parity of the + // signature. + let signature = signature.with_parity_bool(); + let mut buf = Vec::with_capacity(self.encoded_len_with_signature(&signature, false)); self.encode_with_signature(&signature, &mut buf, false); let hash = keccak256(&buf); - // Drop any v chain id value to ensure the signature format is correct at the time of - // combination for an EIP-1559 transaction. V should indicate the y-parity of the - // signature. - Signed::new_unchecked(self, signature.with_parity_bool(), hash) + Signed::new_unchecked(self, signature, hash) } } diff --git a/crates/consensus/src/transaction/eip2930.rs b/crates/consensus/src/transaction/eip2930.rs index 8ae2a111098..85bb370c178 100644 --- a/crates/consensus/src/transaction/eip2930.rs +++ b/crates/consensus/src/transaction/eip2930.rs @@ -272,14 +272,16 @@ impl SignableTransaction for TxEip2930 { } fn into_signed(self, signature: Signature) -> Signed { + // Drop any v chain id value to ensure the signature format is correct at the time of + // combination for an EIP-2930 transaction. V should indicate the y-parity of the + // signature. + let signature = signature.with_parity_bool(); + let mut buf = Vec::with_capacity(self.encoded_len_with_signature(&signature, false)); self.encode_with_signature(&signature, &mut buf, false); let hash = keccak256(&buf); - // Drop any v chain id value to ensure the signature format is correct at the time of - // combination for an EIP-2930 transaction. V should indicate the y-parity of the - // signature. - Signed::new_unchecked(self, signature.with_parity_bool(), hash) + Signed::new_unchecked(self, signature, hash) } } diff --git a/crates/consensus/src/transaction/eip4844.rs b/crates/consensus/src/transaction/eip4844.rs index ba4bbdcbab4..f7ed416959f 100644 --- a/crates/consensus/src/transaction/eip4844.rs +++ b/crates/consensus/src/transaction/eip4844.rs @@ -268,16 +268,18 @@ impl SignableTransaction for TxEip4844Variant { } fn into_signed(self, signature: Signature) -> Signed { + // Drop any v chain id value to ensure the signature format is correct at the time of + // combination for an EIP-4844 transaction. V should indicate the y-parity of the + // signature. + let signature = signature.with_parity_bool(); + let payload_length = 1 + self.fields_len() + signature.rlp_vrs_len(); let mut buf = Vec::with_capacity(payload_length); // we use the inner tx to encode the fields self.tx().encode_with_signature(&signature, &mut buf, false); let hash = keccak256(&buf); - // Drop any v chain id value to ensure the signature format is correct at the time of - // combination for an EIP-4844 transaction. V should indicate the y-parity of the - // signature. - Signed::new_unchecked(self, signature.with_parity_bool(), hash) + Signed::new_unchecked(self, signature, hash) } } @@ -617,14 +619,16 @@ impl SignableTransaction for TxEip4844 { } fn into_signed(self, signature: Signature) -> Signed { + // Drop any v chain id value to ensure the signature format is correct at the time of + // combination for an EIP-4844 transaction. V should indicate the y-parity of the + // signature. + let signature = signature.with_parity_bool(); + let mut buf = Vec::with_capacity(self.encoded_len_with_signature(&signature, false)); self.encode_with_signature(&signature, &mut buf, false); let hash = keccak256(&buf); - // Drop any v chain id value to ensure the signature format is correct at the time of - // combination for an EIP-4844 transaction. V should indicate the y-parity of the - // signature. - Signed::new_unchecked(self, signature.with_parity_bool(), hash) + Signed::new_unchecked(self, signature, hash) } } @@ -847,6 +851,11 @@ impl SignableTransaction for TxEip4844WithSidecar { } fn into_signed(self, signature: Signature) -> Signed { + // Drop any v chain id value to ensure the signature format is correct at the time of + // combination for an EIP-4844 transaction. V should indicate the y-parity of the + // signature. + let signature = signature.with_parity_bool(); + let mut buf = Vec::with_capacity(self.tx.encoded_len_with_signature(&signature, false)); // The sidecar is NOT included in the signed payload, only the transaction fields and the // type byte. Include the type byte. @@ -856,10 +865,7 @@ impl SignableTransaction for TxEip4844WithSidecar { self.tx.encode_with_signature(&signature, &mut buf, false); let hash = keccak256(&buf); - // Drop any v chain id value to ensure the signature format is correct at the time of - // combination for an EIP-4844 transaction. V should indicate the y-parity of the - // signature. - Signed::new_unchecked(self, signature.with_parity_bool(), hash) + Signed::new_unchecked(self, signature, hash) } } diff --git a/crates/consensus/src/transaction/envelope.rs b/crates/consensus/src/transaction/envelope.rs index e8fdd71c79c..a5e7e90c7f0 100644 --- a/crates/consensus/src/transaction/envelope.rs +++ b/crates/consensus/src/transaction/envelope.rs @@ -430,8 +430,11 @@ impl Transaction for TxEnvelope { mod tests { use super::*; use crate::transaction::SignableTransaction; - use alloy_eips::eip2930::{AccessList, AccessListItem}; - use alloy_primitives::{hex, Address, Signature, U256}; + use alloy_eips::{ + eip2930::{AccessList, AccessListItem}, + eip4844::BlobTransactionSidecar, + }; + use alloy_primitives::{hex, Address, Parity, Signature, U256}; #[allow(unused_imports)] use alloy_primitives::{Bytes, TxKind}; use std::{fs, path::PathBuf, vec}; @@ -525,11 +528,13 @@ mod tests { assert_eq!(from, address!("A83C816D4f9b2783761a22BA6FADB0eB0606D7B2")); } - fn test_encode_decode_roundtrip>(tx: T) - where + fn test_encode_decode_roundtrip>( + tx: T, + signature: Option, + ) where Signed: Into, { - let signature = Signature::test_signature(); + let signature = signature.unwrap_or_else(Signature::test_signature); let tx_signed = tx.into_signed(signature); let tx_envelope: TxEnvelope = tx_signed.into(); let encoded = tx_envelope.encoded_2718(); @@ -551,7 +556,113 @@ mod tests { input: vec![8].into(), access_list: Default::default(), }; - test_encode_decode_roundtrip(tx); + test_encode_decode_roundtrip(tx, None); + } + + #[test] + fn test_encode_decode_eip1559_parity_eip155() { + let tx = TxEip1559 { + chain_id: 1u64, + nonce: 2, + max_fee_per_gas: 3, + max_priority_fee_per_gas: 4, + gas_limit: 5, + to: Address::left_padding_from(&[6]).into(), + value: U256::from(7_u64), + input: vec![8].into(), + access_list: Default::default(), + }; + let signature = Signature::test_signature().with_parity(Parity::Eip155(42)); + test_encode_decode_roundtrip(tx, Some(signature)); + } + + #[test] + fn test_encode_decode_eip2930_parity_eip155() { + let tx = TxEip2930 { + chain_id: 1u64, + nonce: 2, + gas_price: 3, + gas_limit: 4, + to: Address::left_padding_from(&[5]).into(), + value: U256::from(6_u64), + input: vec![7].into(), + access_list: Default::default(), + }; + let signature = Signature::test_signature().with_parity(Parity::Eip155(42)); + test_encode_decode_roundtrip(tx, Some(signature)); + } + + #[test] + fn test_encode_decode_eip4844_parity_eip155() { + let tx = TxEip4844 { + chain_id: 1, + nonce: 100, + max_fee_per_gas: 50_000_000_000, + max_priority_fee_per_gas: 1_000_000_000_000, + gas_limit: 1_000_000, + to: Address::random(), + value: U256::from(10e18), + input: Bytes::new(), + access_list: AccessList(vec![AccessListItem { + address: Address::random(), + storage_keys: vec![B256::random()], + }]), + blob_versioned_hashes: vec![B256::random()], + max_fee_per_blob_gas: 0, + }; + let signature = Signature::test_signature().with_parity(Parity::Eip155(42)); + test_encode_decode_roundtrip(tx, Some(signature)); + } + + #[test] + fn test_encode_decode_eip4844_sidecar_parity_eip155() { + let tx = TxEip4844 { + chain_id: 1, + nonce: 100, + max_fee_per_gas: 50_000_000_000, + max_priority_fee_per_gas: 1_000_000_000_000, + gas_limit: 1_000_000, + to: Address::random(), + value: U256::from(10e18), + input: Bytes::new(), + access_list: AccessList(vec![AccessListItem { + address: Address::random(), + storage_keys: vec![B256::random()], + }]), + blob_versioned_hashes: vec![B256::random()], + max_fee_per_blob_gas: 0, + }; + let sidecar = BlobTransactionSidecar { + blobs: vec![[2; 131072].into()], + commitments: vec![[3; 48].into()], + proofs: vec![[4; 48].into()], + }; + let tx = TxEip4844WithSidecar { tx, sidecar }; + let signature = Signature::test_signature().with_parity(Parity::Eip155(42)); + test_encode_decode_roundtrip(tx, Some(signature)); + } + + #[test] + fn test_encode_decode_eip4844_variant_parity_eip155() { + let tx = TxEip4844 { + chain_id: 1, + nonce: 100, + max_fee_per_gas: 50_000_000_000, + max_priority_fee_per_gas: 1_000_000_000_000, + gas_limit: 1_000_000, + to: Address::random(), + value: U256::from(10e18), + input: Bytes::new(), + access_list: AccessList(vec![AccessListItem { + address: Address::random(), + storage_keys: vec![B256::random()], + }]), + blob_versioned_hashes: vec![B256::random()], + max_fee_per_blob_gas: 0, + }; + let tx = TxEip4844Variant::TxEip4844(tx); + let signature = Signature::test_signature().with_parity(Parity::Eip155(42)); + test_encode_decode_roundtrip(tx, Some(signature)); } #[test] @@ -569,7 +680,7 @@ mod tests { storage_keys: vec![B256::left_padding_from(&[9])], }]), }; - test_encode_decode_roundtrip(tx); + test_encode_decode_roundtrip(tx, None); } #[test] From e6b3edda708be217e3fbc97dbc2256421c201ae2 Mon Sep 17 00:00:00 2001 From: Igor Aleksanov Date: Mon, 8 Jul 2024 16:19:03 +0400 Subject: [PATCH 57/61] fix: Fix watching already mined transactions (#997) * fix: Fix watching already mined transactions * fix: Account for reorgs in Heart --- crates/provider/src/chain.rs | 5 +- crates/provider/src/heart.rs | 116 ++++++++++++++++++++++++-- crates/provider/src/provider/root.rs | 7 +- crates/provider/src/provider/trait.rs | 74 +++++++++++++++- 4 files changed, 186 insertions(+), 16 deletions(-) diff --git a/crates/provider/src/chain.rs b/crates/provider/src/chain.rs index 75593351051..5ffb436e1c1 100644 --- a/crates/provider/src/chain.rs +++ b/crates/provider/src/chain.rs @@ -1,4 +1,3 @@ -use crate::{Provider, RootProvider}; use alloy_network::{Ethereum, Network}; use alloy_primitives::{BlockNumber, U64}; use alloy_rpc_client::{PollerBuilder, WeakClient}; @@ -27,8 +26,8 @@ pub(crate) struct ChainStreamPoller { } impl ChainStreamPoller { - pub(crate) fn from_root(p: &RootProvider) -> Self { - Self::new(p.weak_client()) + pub(crate) fn from_weak_client(w: WeakClient) -> Self { + Self::new(w) } pub(crate) fn new(client: WeakClient) -> Self { diff --git a/crates/provider/src/heart.rs b/crates/provider/src/heart.rs index efac2512f43..db7d4b7af0c 100644 --- a/crates/provider/src/heart.rs +++ b/crates/provider/src/heart.rs @@ -8,7 +8,7 @@ use alloy_rpc_types_eth::Block; use alloy_transport::{utils::Spawnable, Transport, TransportErrorKind, TransportResult}; use futures::{stream::StreamExt, FutureExt, Stream}; use std::{ - collections::{BTreeMap, HashMap}, + collections::{BTreeMap, HashMap, HashSet, VecDeque}, fmt, future::Future, time::{Duration, Instant}, @@ -306,6 +306,9 @@ impl PendingTransactionConfig { #[doc(alias = "TransactionWatcher")] struct TxWatcher { config: PendingTransactionConfig, + /// The block at which the transaction was received. To be filled once known. + /// Invariant: any confirmed transaction in `Heart` has this value set. + received_at_block: Option, tx: oneshot::Sender<()>, } @@ -339,6 +342,13 @@ impl fmt::Debug for PendingTransaction { } impl PendingTransaction { + /// Creates a ready pending transaction. + pub fn ready(tx_hash: TxHash) -> Self { + let (tx, rx) = oneshot::channel(); + tx.send(()).ok(); // Make sure that the receiver is notified already. + Self { tx_hash, rx } + } + /// Returns this transaction's hash. #[doc(alias = "transaction_hash")] pub const fn tx_hash(&self) -> &TxHash { @@ -372,10 +382,11 @@ impl HeartbeatHandle { pub(crate) async fn watch_tx( &self, config: PendingTransactionConfig, + received_at_block: Option, ) -> Result { let (tx, rx) = oneshot::channel(); let tx_hash = config.tx_hash; - match self.tx.send(TxWatcher { config, tx }).await { + match self.tx.send(TxWatcher { config, received_at_block, tx }).await { Ok(()) => Ok(PendingTransaction { tx_hash, rx }), Err(e) => Err(e.0.config), } @@ -394,6 +405,9 @@ pub(crate) struct Heartbeat { /// The stream of incoming blocks to watch. stream: futures::stream::Fuse, + /// Lookbehind blocks in form of mapping block number -> vector of transaction hashes. + past_blocks: VecDeque<(u64, HashSet)>, + /// Transactions to watch for. unconfirmed: HashMap, @@ -409,6 +423,7 @@ impl + Unpin + 'static> Heartbeat { pub(crate) fn new(stream: S) -> Self { Self { stream: stream.fuse(), + past_blocks: Default::default(), unconfirmed: Default::default(), waiting_confs: Default::default(), reap_at: Default::default(), @@ -448,18 +463,71 @@ impl Heartbeat { } } + /// Reap transactions overridden by the reorg. + /// Accepts new chain height as an argument, and drops any subscriptions + /// that were received in blocks affected by the reorg (e.g. >= new_height). + fn move_reorg_to_unconfirmed(&mut self, new_height: u64) { + for waiters in self.waiting_confs.values_mut() { + *waiters = std::mem::take(waiters).into_iter().filter_map(|watcher| { + if let Some(received_at_block) = watcher.received_at_block { + // All blocks after and _including_ the new height are reaped. + if received_at_block >= new_height { + let hash = watcher.config.tx_hash; + debug!(tx=%hash, %received_at_block, %new_height, "return to unconfirmed due to reorg"); + self.unconfirmed.insert(hash, watcher); + return None; + } + } + Some(watcher) + }).collect(); + } + } + /// Handle a watch instruction by adding it to the watch list, and /// potentially adding it to our `reap_at` list. fn handle_watch_ix(&mut self, to_watch: TxWatcher) { // Start watching for the transaction. debug!(tx=%to_watch.config.tx_hash, "watching"); - trace!(?to_watch.config); + trace!(?to_watch.config, ?to_watch.received_at_block); + if let Some(received_at_block) = to_watch.received_at_block { + // Transaction is already confirmed, we just need to wait for the required + // confirmations. + let current_block = + self.past_blocks.back().map(|(h, _)| *h).unwrap_or(received_at_block); + self.add_to_waiting_list(to_watch, current_block); + return; + } + if let Some(timeout) = to_watch.config.timeout { self.reap_at.insert(Instant::now() + timeout, to_watch.config.tx_hash); } + // Transaction may be confirmed already, check the lookbehind history first. + // If so, insert it into the waiting list. + for (block_height, txs) in self.past_blocks.iter().rev() { + if txs.contains(&to_watch.config.tx_hash) { + let confirmations = to_watch.config.required_confirmations; + let confirmed_at = *block_height + confirmations - 1; + let current_height = self.past_blocks.back().map(|(h, _)| *h).unwrap(); + + if confirmed_at <= current_height { + to_watch.notify(); + } else { + debug!(tx=%to_watch.config.tx_hash, %block_height, confirmations, "adding to waiting list"); + self.waiting_confs.entry(confirmed_at).or_default().push(to_watch); + } + return; + } + } + self.unconfirmed.insert(to_watch.config.tx_hash, to_watch); } + fn add_to_waiting_list(&mut self, watcher: TxWatcher, block_height: u64) { + let confirmations = watcher.config.required_confirmations; + debug!(tx=%watcher.config.tx_hash, %block_height, confirmations, "adding to waiting list"); + self.waiting_confs.entry(block_height + confirmations - 1).or_default().push(watcher); + } + /// Handle a new block by checking if any of the transactions we're /// watching are in it, and if so, notifying the watcher. Also updates /// the latest block. @@ -467,10 +535,35 @@ impl Heartbeat { // Blocks without numbers are ignored, as they're not part of the chain. let Some(block_height) = &block.header.number else { return }; + // Add the block the lookbehind. + // The value is chosen arbitrarily to not have a huge memory footprint but still + // catch most cases where user subscribes for an already mined transaction. + // Note that we expect provider to check whether transaction is already mined + // before subscribing, so here we only need to consider time before sending a notification + // and processing it. + const MAX_BLOCKS_TO_RETAIN: usize = 10; + if self.past_blocks.len() >= MAX_BLOCKS_TO_RETAIN { + self.past_blocks.pop_front(); + } + if let Some((last_height, _)) = self.past_blocks.back().as_ref() { + // Check that the chain is continuous. + if *last_height + 1 != *block_height { + // Move all the transactions that were reset by the reorg to the unconfirmed list. + warn!(%block_height, last_height, "reorg detected"); + self.move_reorg_to_unconfirmed(*block_height); + // Remove past blocks that are now invalid. + self.past_blocks.retain(|(h, _)| h < block_height); + } + } + self.past_blocks.push_back((*block_height, block.transactions.hashes().copied().collect())); + // Check if we are watching for any of the transactions in this block. - let to_check = - block.transactions.hashes().filter_map(|tx_hash| self.unconfirmed.remove(tx_hash)); - for watcher in to_check { + let to_check: Vec<_> = block + .transactions + .hashes() + .filter_map(|tx_hash| self.unconfirmed.remove(tx_hash)) + .collect(); + for mut watcher in to_check { // If `confirmations` is not more than 1 we can notify the watcher immediately. let confirmations = watcher.config.required_confirmations; if confirmations <= 1 { @@ -478,8 +571,15 @@ impl Heartbeat { continue; } // Otherwise add it to the waiting list. - debug!(tx=%watcher.config.tx_hash, %block_height, confirmations, "adding to waiting list"); - self.waiting_confs.entry(*block_height + confirmations - 1).or_default().push(watcher); + + // Set the block at which the transaction was received. + if let Some(set_block) = watcher.received_at_block { + warn!(tx=%watcher.config.tx_hash, set_block=%set_block, new_block=%block_height, "received_at_block already set"); + // We don't override the set value. + } else { + watcher.received_at_block = Some(*block_height); + } + self.add_to_waiting_list(watcher, *block_height); } self.check_confirmations(*block_height); diff --git a/crates/provider/src/provider/root.rs b/crates/provider/src/provider/root.rs index e9bcdfddda8..1b3f524cc5e 100644 --- a/crates/provider/src/provider/root.rs +++ b/crates/provider/src/provider/root.rs @@ -51,7 +51,7 @@ impl RootProvider, N> { } } -impl RootProvider { +impl RootProvider { /// Creates a new root provider from the given RPC client. pub fn new(client: RpcClient) -> Self { Self { inner: Arc::new(RootProviderInner::new(client)) } @@ -117,7 +117,8 @@ impl RootProvider { #[inline] pub(crate) fn get_heart(&self) -> &HeartbeatHandle { self.inner.heart.get_or_init(|| { - let poller = ChainStreamPoller::from_root(self); + let poller: ChainStreamPoller = + ChainStreamPoller::from_weak_client(self.inner.weak_client()); // TODO: Can we avoid `Box::pin` here? Heartbeat::new(Box::pin(poller.into_stream())).spawn() }) @@ -138,7 +139,7 @@ impl Clone for RootProviderInner { } } -impl RootProviderInner { +impl RootProviderInner { pub(crate) const fn new(client: RpcClient) -> Self { Self { client, heart: OnceLock::new(), _network: PhantomData } } diff --git a/crates/provider/src/provider/trait.rs b/crates/provider/src/provider/trait.rs index c9543249e61..9ccd9c93f27 100644 --- a/crates/provider/src/provider/trait.rs +++ b/crates/provider/src/provider/trait.rs @@ -7,7 +7,7 @@ use crate::{ }; use alloy_eips::eip2718::Encodable2718; use alloy_json_rpc::{RpcError, RpcParam, RpcReturn}; -use alloy_network::{Ethereum, Network}; +use alloy_network::{Ethereum, Network, ReceiptResponse as _}; use alloy_primitives::{ hex, Address, BlockHash, BlockNumber, Bytes, StorageKey, StorageValue, TxHash, B256, U128, U256, U64, @@ -667,6 +667,10 @@ pub trait Provider: &self, tx: SendableTx, ) -> TransportResult> { + // Make sure to initialize heartbeat before we submit transaction, so that + // we don't miss it if user will subscriber to it immediately after sending. + let _handle = self.root().get_heart(); + match tx { SendableTx::Builder(mut tx) => { alloy_network::TransactionBuilder::prep_for_submission(&mut tx); @@ -958,12 +962,30 @@ impl Provider for RootProvider { &self, config: PendingTransactionConfig, ) -> TransportResult { - self.get_heart().watch_tx(config).await.map_err(|_| TransportErrorKind::backend_gone()) + let block_number = + if let Some(receipt) = self.get_transaction_receipt(*config.tx_hash()).await? { + // The transaction is already confirmed. + if config.required_confirmations() <= 1 { + return Ok(PendingTransaction::ready(*config.tx_hash())); + } + // Transaction has custom confirmations, so let the heart know about its block + // number and let it handle the situation. + receipt.block_number() + } else { + None + }; + + self.get_heart() + .watch_tx(config, block_number) + .await + .map_err(|_| TransportErrorKind::backend_gone()) } } #[cfg(test)] mod tests { + use std::time::Duration; + use super::*; use crate::{builder, ProviderBuilder, WalletProvider}; use alloy_network::AnyNetwork; @@ -1148,6 +1170,54 @@ mod tests { assert_eq!(hash1, hash2); } + #[tokio::test] + async fn test_watch_confirmed_tx() { + init_tracing(); + let provider = ProviderBuilder::new().on_anvil(); + let tx = TransactionRequest { + value: Some(U256::from(100)), + to: Some(address!("d8dA6BF26964aF9D7eEd9e03E53415D37aA96045").into()), + gas_price: Some(20e9 as u128), + gas: Some(21000), + ..Default::default() + }; + + let builder = provider.send_transaction(tx.clone()).await.expect("failed to send tx"); + let hash1 = *builder.tx_hash(); + + // Wait until tx is confirmed. + loop { + if provider + .get_transaction_receipt(hash1) + .await + .expect("failed to await pending tx") + .is_some() + { + break; + } + } + + // Submit another tx. + let tx2 = TransactionRequest { + value: Some(U256::from(100)), + to: Some(address!("d8dA6BF26964aF9D7eEd9e03E53415D37aA96045").into()), + gas_price: Some(20e9 as u128), + gas: Some(21000), + ..Default::default() + }; + provider.send_transaction(tx2).await.expect("failed to send tx").watch().await.unwrap(); + + // Only subscribe for watching _after_ tx was confirmed and we submitted a new one. + let watch = builder.watch(); + // Wrap watch future in timeout to prevent it from hanging. + let watch_with_timeout = tokio::time::timeout(Duration::from_secs(1), watch); + let hash2 = watch_with_timeout + .await + .expect("Watching tx timed out") + .expect("failed to await pending tx"); + assert_eq!(hash1, hash2); + } + #[tokio::test] async fn gets_block_number() { init_tracing(); From e849732d68f6cc55128440c2a9d317f13a1d8783 Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Mon, 8 Jul 2024 14:32:44 +0200 Subject: [PATCH 58/61] chore: add helper functions for destructuring auth types (#1022) chore: add helper functions for destructing auth types --- crates/eips/src/eip7702/auth_list.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/crates/eips/src/eip7702/auth_list.rs b/crates/eips/src/eip7702/auth_list.rs index 132981aaef1..11a241efae1 100644 --- a/crates/eips/src/eip7702/auth_list.rs +++ b/crates/eips/src/eip7702/auth_list.rs @@ -78,6 +78,11 @@ impl SignedAuthorization { pub const fn signature(&self) -> &S { &self.signature } + + /// Splits the authorization into parts. + pub fn into_parts(self) -> (Authorization, S) { + (self.inner, self.signature) + } } #[cfg(feature = "k256")] @@ -123,6 +128,11 @@ impl RecoveredAuthorization { pub const fn authority(&self) -> Option
{ self.authority } + + /// Splits the authorization into parts. + pub const fn into_parts(self) -> (Authorization, Option
) { + (self.inner, self.authority) + } } impl Deref for RecoveredAuthorization { From b9a9625b9f4de0748da685c1f55add4eb7d77f61 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Mon, 8 Jul 2024 15:08:14 +0200 Subject: [PATCH 59/61] chore: update release config --- RELEASE_CHECKLIST.md | 2 +- release.toml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/RELEASE_CHECKLIST.md b/RELEASE_CHECKLIST.md index c87a139fa76..359e6069f60 100644 --- a/RELEASE_CHECKLIST.md +++ b/RELEASE_CHECKLIST.md @@ -15,7 +15,7 @@ changed or not. - [ ] Make sure you're on the `main` branch. - [ ] (optional) Dry run `cargo-release`: `cargo release ` -- [ ] Run `cargo-release`: `PUBLISH_GRACE_SLEEP=10 cargo release --rate-limit.existing-packages 50 [--no-verify]` +- [ ] Run `cargo-release`: `PUBLISH_GRACE_SLEEP=10 cargo release --execute [--no-verify] ` - Ignore these warnings: - `warning: updating to despite no changes made since...` - `git-cliff` warning `there is already a tag () for ...` diff --git a/release.toml b/release.toml index 04d7bdf5974..738fe9fa3fd 100644 --- a/release.toml +++ b/release.toml @@ -7,6 +7,7 @@ sign-tag = true shared-version = true pre-release-commit-message = "chore: release {{version}}" tag-prefix = "" # tag only once instead of per every crate +rate-limit.existing-packages = 50 pre-release-hook = [ "bash", "-c", From 83343b172585fe4e040fb104b4d1421f58cbf9a2 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Mon, 8 Jul 2024 15:12:00 +0200 Subject: [PATCH 60/61] chore: release 0.1.4 --- CHANGELOG.md | 63 ++++++++++++++++++++++++++++ Cargo.toml | 2 +- crates/alloy/CHANGELOG.md | 14 +++++++ crates/consensus/CHANGELOG.md | 11 +++++ crates/contract/CHANGELOG.md | 10 +++++ crates/eip7547/CHANGELOG.md | 1 + crates/eips/CHANGELOG.md | 18 ++++++++ crates/genesis/CHANGELOG.md | 6 +++ crates/json-rpc/CHANGELOG.md | 12 ++++++ crates/network/CHANGELOG.md | 10 +++++ crates/node-bindings/CHANGELOG.md | 6 +++ crates/provider/CHANGELOG.md | 23 ++++++++++ crates/pubsub/CHANGELOG.md | 3 +- crates/rpc-client/CHANGELOG.md | 6 +++ crates/rpc-types-admin/CHANGELOG.md | 12 ++++++ crates/rpc-types-anvil/CHANGELOG.md | 6 +++ crates/rpc-types-beacon/CHANGELOG.md | 13 ++++++ crates/rpc-types-engine/CHANGELOG.md | 8 ++++ crates/rpc-types-eth/CHANGELOG.md | 18 ++++++++ crates/rpc-types-mev/CHANGELOG.md | 12 ++++++ crates/rpc-types-trace/CHANGELOG.md | 17 ++++++++ crates/rpc-types-txpool/CHANGELOG.md | 6 +++ crates/rpc-types/CHANGELOG.md | 1 + crates/serde/CHANGELOG.md | 3 +- crates/signer-aws/CHANGELOG.md | 1 + crates/signer-gcp/CHANGELOG.md | 1 + crates/signer-ledger/CHANGELOG.md | 1 + crates/signer-local/CHANGELOG.md | 6 +++ crates/signer-trezor/CHANGELOG.md | 7 ++++ crates/signer/CHANGELOG.md | 6 +++ crates/transport-http/CHANGELOG.md | 6 +++ crates/transport-ipc/CHANGELOG.md | 6 ++- crates/transport-ws/CHANGELOG.md | 6 +++ crates/transport/CHANGELOG.md | 12 ++++++ 34 files changed, 329 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aa616268db1..ad37f0c03b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,69 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.4](https://github.com/alloy-rs/alloy/releases/tag/v0.1.4) - 2024-07-08 + +### Bug Fixes + +- Fix watching already mined transactions ([#997](https://github.com/alloy-rs/alloy/issues/997)) +- Ots_getContractCreater has field hash instead of tx ([#999](https://github.com/alloy-rs/alloy/issues/999)) +- [signer-trezor] Fix zero gas price when sending legacy tx with trezor ([#977](https://github.com/alloy-rs/alloy/issues/977)) + +### Dependencies + +- [deps] Remove reqwest and hyper from meta crate ([#974](https://github.com/alloy-rs/alloy/issues/974)) + +### Documentation + +- Add release checklist ([#972](https://github.com/alloy-rs/alloy/issues/972)) + +### Features + +- Add helper to set both input and data fields ([#1019](https://github.com/alloy-rs/alloy/issues/1019)) +- [transport] Retry layer ([#849](https://github.com/alloy-rs/alloy/issues/849)) +- Add execution payloadbodyv2 ([#1012](https://github.com/alloy-rs/alloy/issues/1012)) +- Add consolidation requests to v4 payload ([#1013](https://github.com/alloy-rs/alloy/issues/1013)) +- [rpc-types-eth] Add more utils to `TransactionIndex` ([#1007](https://github.com/alloy-rs/alloy/issues/1007)) +- Impl Transaction for TxEnvelope ([#1006](https://github.com/alloy-rs/alloy/issues/1006)) +- [eip1559] Support Optimism Canyon hardfork ([#1010](https://github.com/alloy-rs/alloy/issues/1010)) +- Add missing admin_* methods ([#991](https://github.com/alloy-rs/alloy/issues/991)) +- [network] Block context in ReceiptResponse ([#1003](https://github.com/alloy-rs/alloy/issues/1003)) +- [otterscan] Add output for TraceEntry ([#1001](https://github.com/alloy-rs/alloy/issues/1001)) +- Support web3_sha3 provider function ([#996](https://github.com/alloy-rs/alloy/issues/996)) +- Add submit block request query ([#995](https://github.com/alloy-rs/alloy/issues/995)) +- Add trace_get ([#987](https://github.com/alloy-rs/alloy/issues/987)) +- Add net rpc namespace ([#989](https://github.com/alloy-rs/alloy/issues/989)) +- Add missing debug_* rpc methods ([#986](https://github.com/alloy-rs/alloy/issues/986)) +- Add into transactions iterator ([#984](https://github.com/alloy-rs/alloy/issues/984)) +- Add helpers for trace action ([#982](https://github.com/alloy-rs/alloy/issues/982)) +- Impl `From` for `BlockHashOrNumber` ([#980](https://github.com/alloy-rs/alloy/issues/980)) +- Add missing eth bundle args ([#978](https://github.com/alloy-rs/alloy/issues/978)) + +### Miscellaneous Tasks + +- Update release config +- Add helper functions for destructuring auth types ([#1022](https://github.com/alloy-rs/alloy/issues/1022)) +- Convert rcp-types-eth block Header to consensus Header ([#1014](https://github.com/alloy-rs/alloy/issues/1014)) +- [docs] Add the missing crate `rpc-types-mev` ([#1011](https://github.com/alloy-rs/alloy/issues/1011)) +- Clean up 7702 encoding ([#1000](https://github.com/alloy-rs/alloy/issues/1000)) +- Make wrapped index value pub ([#988](https://github.com/alloy-rs/alloy/issues/988)) +- [provider] Simplify nonce filler ([#976](https://github.com/alloy-rs/alloy/issues/976)) +- Release 0.1.3 (-p alloy) + +### Other + +- Remove signature.v parity before calculating tx hash ([#893](https://github.com/alloy-rs/alloy/issues/893)) +- Fix wasi job ([#993](https://github.com/alloy-rs/alloy/issues/993)) +- Update builders to vector of strings in privacy struct ([#983](https://github.com/alloy-rs/alloy/issues/983)) +- Allow to convert CallBuilderTo TransactionRequest ([#981](https://github.com/alloy-rs/alloy/issues/981)) +- [hotfix] Typo change pub(crate) to pub ([#979](https://github.com/alloy-rs/alloy/issues/979)) +- Add range test in `FilterBlockOption` ([#939](https://github.com/alloy-rs/alloy/issues/939)) + +### Testing + +- Add missing unit test for op `calc_next_block_base_fee` ([#1008](https://github.com/alloy-rs/alloy/issues/1008)) +- Fix flaky anvil test ([#992](https://github.com/alloy-rs/alloy/issues/992)) + ## [0.1.3](https://github.com/alloy-rs/alloy/releases/tag/v0.1.3) - 2024-06-25 ### Bug Fixes diff --git a/Cargo.toml b/Cargo.toml index c2065b23e38..0831013b862 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ members = ["crates/*"] resolver = "2" [workspace.package] -version = "0.1.3" +version = "0.1.4" edition = "2021" rust-version = "1.76" authors = ["Alloy Contributors"] diff --git a/crates/alloy/CHANGELOG.md b/crates/alloy/CHANGELOG.md index 3ba912ad7f0..0054e2d5f9d 100644 --- a/crates/alloy/CHANGELOG.md +++ b/crates/alloy/CHANGELOG.md @@ -5,6 +5,20 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.4](https://github.com/alloy-rs/alloy/releases/tag/v0.1.4) - 2024-07-08 + +### Dependencies + +- [deps] Remove reqwest and hyper from meta crate ([#974](https://github.com/alloy-rs/alloy/issues/974)) + +### Features + +- Add net rpc namespace ([#989](https://github.com/alloy-rs/alloy/issues/989)) + +### Miscellaneous Tasks + +- Release 0.1.3 (-p alloy) + ## [0.1.3](https://github.com/alloy-rs/alloy/releases/tag/v0.1.3) - 2024-06-25 ### Features diff --git a/crates/consensus/CHANGELOG.md b/crates/consensus/CHANGELOG.md index 6ff3c0f3e17..9dd423660f7 100644 --- a/crates/consensus/CHANGELOG.md +++ b/crates/consensus/CHANGELOG.md @@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.4](https://github.com/alloy-rs/alloy/releases/tag/v0.1.4) - 2024-07-08 + +### Features + +- Impl Transaction for TxEnvelope ([#1006](https://github.com/alloy-rs/alloy/issues/1006)) + +### Other + +- Remove signature.v parity before calculating tx hash ([#893](https://github.com/alloy-rs/alloy/issues/893)) + ## [0.1.3](https://github.com/alloy-rs/alloy/releases/tag/v0.1.3) - 2024-06-25 ### Documentation @@ -17,6 +27,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Tasks +- Release 0.1.3 - [eips] Make `sha2` optional, add `kzg-sidecar` feature ([#949](https://github.com/alloy-rs/alloy/issues/949)) ## [0.1.2](https://github.com/alloy-rs/alloy/releases/tag/v0.1.2) - 2024-06-19 diff --git a/crates/contract/CHANGELOG.md b/crates/contract/CHANGELOG.md index f7cc0f084f9..269bef1c998 100644 --- a/crates/contract/CHANGELOG.md +++ b/crates/contract/CHANGELOG.md @@ -5,12 +5,22 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.4](https://github.com/alloy-rs/alloy/releases/tag/v0.1.4) - 2024-07-08 + +### Other + +- Allow to convert CallBuilderTo TransactionRequest ([#981](https://github.com/alloy-rs/alloy/issues/981)) + ## [0.1.3](https://github.com/alloy-rs/alloy/releases/tag/v0.1.3) - 2024-06-25 ### Features - [contract] Implement Filter's builder methods on Event ([#960](https://github.com/alloy-rs/alloy/issues/960)) +### Miscellaneous Tasks + +- Release 0.1.3 + ### Other - [contract] Support state overrides for gas estimation ([#967](https://github.com/alloy-rs/alloy/issues/967)) diff --git a/crates/eip7547/CHANGELOG.md b/crates/eip7547/CHANGELOG.md index 0e3ac20f9db..63de946cb56 100644 --- a/crates/eip7547/CHANGELOG.md +++ b/crates/eip7547/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Tasks +- Release 0.1.3 - Release 0.1.3 - Nightly clippy ([#947](https://github.com/alloy-rs/alloy/issues/947)) diff --git a/crates/eips/CHANGELOG.md b/crates/eips/CHANGELOG.md index ab2773a8647..2b5e4180ef9 100644 --- a/crates/eips/CHANGELOG.md +++ b/crates/eips/CHANGELOG.md @@ -5,6 +5,23 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.4](https://github.com/alloy-rs/alloy/releases/tag/v0.1.4) - 2024-07-08 + +### Features + +- Add consolidation requests to v4 payload ([#1013](https://github.com/alloy-rs/alloy/issues/1013)) +- [eip1559] Support Optimism Canyon hardfork ([#1010](https://github.com/alloy-rs/alloy/issues/1010)) +- Impl `From` for `BlockHashOrNumber` ([#980](https://github.com/alloy-rs/alloy/issues/980)) + +### Miscellaneous Tasks + +- Add helper functions for destructuring auth types ([#1022](https://github.com/alloy-rs/alloy/issues/1022)) +- Clean up 7702 encoding ([#1000](https://github.com/alloy-rs/alloy/issues/1000)) + +### Testing + +- Add missing unit test for op `calc_next_block_base_fee` ([#1008](https://github.com/alloy-rs/alloy/issues/1008)) + ## [0.1.3](https://github.com/alloy-rs/alloy/releases/tag/v0.1.3) - 2024-06-25 ### Bug Fixes @@ -22,6 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Tasks +- Release 0.1.3 - [eips] Add serde to Authorization types ([#964](https://github.com/alloy-rs/alloy/issues/964)) - [eips] Make `sha2` optional, add `kzg-sidecar` feature ([#949](https://github.com/alloy-rs/alloy/issues/949)) diff --git a/crates/genesis/CHANGELOG.md b/crates/genesis/CHANGELOG.md index 89cc88ace21..e2606021b06 100644 --- a/crates/genesis/CHANGELOG.md +++ b/crates/genesis/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.4](https://github.com/alloy-rs/alloy/releases/tag/v0.1.4) - 2024-07-08 + +### Miscellaneous Tasks + +- Release 0.1.3 + ## [0.1.2](https://github.com/alloy-rs/alloy/releases/tag/v0.1.2) - 2024-06-19 ### Documentation diff --git a/crates/json-rpc/CHANGELOG.md b/crates/json-rpc/CHANGELOG.md index 8c206309a43..f5542048dfa 100644 --- a/crates/json-rpc/CHANGELOG.md +++ b/crates/json-rpc/CHANGELOG.md @@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.4](https://github.com/alloy-rs/alloy/releases/tag/v0.1.4) - 2024-07-08 + +### Features + +- [transport] Retry layer ([#849](https://github.com/alloy-rs/alloy/issues/849)) + +## [0.1.3](https://github.com/alloy-rs/alloy/releases/tag/v0.1.3) - 2024-06-25 + +### Miscellaneous Tasks + +- Release 0.1.3 + ## [0.1.2](https://github.com/alloy-rs/alloy/releases/tag/v0.1.2) - 2024-06-19 ### Documentation diff --git a/crates/network/CHANGELOG.md b/crates/network/CHANGELOG.md index 3a6121e3bd1..2fd7b90e814 100644 --- a/crates/network/CHANGELOG.md +++ b/crates/network/CHANGELOG.md @@ -5,12 +5,22 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.4](https://github.com/alloy-rs/alloy/releases/tag/v0.1.4) - 2024-07-08 + +### Features + +- [network] Block context in ReceiptResponse ([#1003](https://github.com/alloy-rs/alloy/issues/1003)) + ## [0.1.3](https://github.com/alloy-rs/alloy/releases/tag/v0.1.3) - 2024-06-25 ### Features - [network] Add `input` method to `TransactionResponse` ([#959](https://github.com/alloy-rs/alloy/issues/959)) +### Miscellaneous Tasks + +- Release 0.1.3 + ## [0.1.2](https://github.com/alloy-rs/alloy/releases/tag/v0.1.2) - 2024-06-19 ### Documentation diff --git a/crates/node-bindings/CHANGELOG.md b/crates/node-bindings/CHANGELOG.md index 8b11d2d5e0a..e3e487cb7b9 100644 --- a/crates/node-bindings/CHANGELOG.md +++ b/crates/node-bindings/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.4](https://github.com/alloy-rs/alloy/releases/tag/v0.1.4) - 2024-07-08 + +### Miscellaneous Tasks + +- Release 0.1.3 + ## [0.1.2](https://github.com/alloy-rs/alloy/releases/tag/v0.1.2) - 2024-06-19 ### Documentation diff --git a/crates/provider/CHANGELOG.md b/crates/provider/CHANGELOG.md index b3c708486ca..3015bc97f3b 100644 --- a/crates/provider/CHANGELOG.md +++ b/crates/provider/CHANGELOG.md @@ -5,6 +5,28 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.4](https://github.com/alloy-rs/alloy/releases/tag/v0.1.4) - 2024-07-08 + +### Bug Fixes + +- Fix watching already mined transactions ([#997](https://github.com/alloy-rs/alloy/issues/997)) + +### Features + +- Add missing admin_* methods ([#991](https://github.com/alloy-rs/alloy/issues/991)) +- Support web3_sha3 provider function ([#996](https://github.com/alloy-rs/alloy/issues/996)) +- Add trace_get ([#987](https://github.com/alloy-rs/alloy/issues/987)) +- Add net rpc namespace ([#989](https://github.com/alloy-rs/alloy/issues/989)) +- Add missing debug_* rpc methods ([#986](https://github.com/alloy-rs/alloy/issues/986)) + +### Miscellaneous Tasks + +- [provider] Simplify nonce filler ([#976](https://github.com/alloy-rs/alloy/issues/976)) + +### Testing + +- Fix flaky anvil test ([#992](https://github.com/alloy-rs/alloy/issues/992)) + ## [0.1.3](https://github.com/alloy-rs/alloy/releases/tag/v0.1.3) - 2024-06-25 ### Bug Fixes @@ -17,6 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Tasks +- Release 0.1.3 - Nightly clippy ([#947](https://github.com/alloy-rs/alloy/issues/947)) ## [0.1.2](https://github.com/alloy-rs/alloy/releases/tag/v0.1.2) - 2024-06-19 diff --git a/crates/pubsub/CHANGELOG.md b/crates/pubsub/CHANGELOG.md index fbd967975cd..3636086dc32 100644 --- a/crates/pubsub/CHANGELOG.md +++ b/crates/pubsub/CHANGELOG.md @@ -5,10 +5,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [0.1.3](https://github.com/alloy-rs/alloy/releases/tag/v0.1.3) - 2024-06-25 +## [0.1.4](https://github.com/alloy-rs/alloy/releases/tag/v0.1.4) - 2024-07-08 ### Miscellaneous Tasks +- Release 0.1.3 - Nightly clippy ([#947](https://github.com/alloy-rs/alloy/issues/947)) ## [0.1.2](https://github.com/alloy-rs/alloy/releases/tag/v0.1.2) - 2024-06-19 diff --git a/crates/rpc-client/CHANGELOG.md b/crates/rpc-client/CHANGELOG.md index a46735095c8..b45e3e3b480 100644 --- a/crates/rpc-client/CHANGELOG.md +++ b/crates/rpc-client/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.4](https://github.com/alloy-rs/alloy/releases/tag/v0.1.4) - 2024-07-08 + +### Miscellaneous Tasks + +- Release 0.1.3 + ## [0.1.2](https://github.com/alloy-rs/alloy/releases/tag/v0.1.2) - 2024-06-19 ### Documentation diff --git a/crates/rpc-types-admin/CHANGELOG.md b/crates/rpc-types-admin/CHANGELOG.md index 6aec957f3be..e9617aa23af 100644 --- a/crates/rpc-types-admin/CHANGELOG.md +++ b/crates/rpc-types-admin/CHANGELOG.md @@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.4](https://github.com/alloy-rs/alloy/releases/tag/v0.1.4) - 2024-07-08 + +### Features + +- Add missing admin_* methods ([#991](https://github.com/alloy-rs/alloy/issues/991)) + +## [0.1.3](https://github.com/alloy-rs/alloy/releases/tag/v0.1.3) - 2024-06-25 + +### Miscellaneous Tasks + +- Release 0.1.3 + ## [0.1.2](https://github.com/alloy-rs/alloy/releases/tag/v0.1.2) - 2024-06-19 ### Documentation diff --git a/crates/rpc-types-anvil/CHANGELOG.md b/crates/rpc-types-anvil/CHANGELOG.md index 1975790bc3b..02c88540f34 100644 --- a/crates/rpc-types-anvil/CHANGELOG.md +++ b/crates/rpc-types-anvil/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.4](https://github.com/alloy-rs/alloy/releases/tag/v0.1.4) - 2024-07-08 + +### Miscellaneous Tasks + +- Release 0.1.3 + ## [0.1.2](https://github.com/alloy-rs/alloy/releases/tag/v0.1.2) - 2024-06-19 ### Documentation diff --git a/crates/rpc-types-beacon/CHANGELOG.md b/crates/rpc-types-beacon/CHANGELOG.md index c94997316e2..0c6c1b5b1a1 100644 --- a/crates/rpc-types-beacon/CHANGELOG.md +++ b/crates/rpc-types-beacon/CHANGELOG.md @@ -5,6 +5,19 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.4](https://github.com/alloy-rs/alloy/releases/tag/v0.1.4) - 2024-07-08 + +### Features + +- Add consolidation requests to v4 payload ([#1013](https://github.com/alloy-rs/alloy/issues/1013)) +- Add submit block request query ([#995](https://github.com/alloy-rs/alloy/issues/995)) + +## [0.1.3](https://github.com/alloy-rs/alloy/releases/tag/v0.1.3) - 2024-06-25 + +### Miscellaneous Tasks + +- Release 0.1.3 + ## [0.1.2](https://github.com/alloy-rs/alloy/releases/tag/v0.1.2) - 2024-06-19 ### Documentation diff --git a/crates/rpc-types-engine/CHANGELOG.md b/crates/rpc-types-engine/CHANGELOG.md index 1bbd56d567a..48a39ea180a 100644 --- a/crates/rpc-types-engine/CHANGELOG.md +++ b/crates/rpc-types-engine/CHANGELOG.md @@ -5,10 +5,18 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.4](https://github.com/alloy-rs/alloy/releases/tag/v0.1.4) - 2024-07-08 + +### Features + +- Add execution payloadbodyv2 ([#1012](https://github.com/alloy-rs/alloy/issues/1012)) +- Add consolidation requests to v4 payload ([#1013](https://github.com/alloy-rs/alloy/issues/1013)) + ## [0.1.3](https://github.com/alloy-rs/alloy/releases/tag/v0.1.3) - 2024-06-25 ### Miscellaneous Tasks +- Release 0.1.3 - Nightly clippy ([#947](https://github.com/alloy-rs/alloy/issues/947)) ## [0.1.2](https://github.com/alloy-rs/alloy/releases/tag/v0.1.2) - 2024-06-19 diff --git a/crates/rpc-types-eth/CHANGELOG.md b/crates/rpc-types-eth/CHANGELOG.md index fd746b8cca5..02b76489156 100644 --- a/crates/rpc-types-eth/CHANGELOG.md +++ b/crates/rpc-types-eth/CHANGELOG.md @@ -5,6 +5,23 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.4](https://github.com/alloy-rs/alloy/releases/tag/v0.1.4) - 2024-07-08 + +### Features + +- Add helper to set both input and data fields ([#1019](https://github.com/alloy-rs/alloy/issues/1019)) +- [rpc-types-eth] Add more utils to `TransactionIndex` ([#1007](https://github.com/alloy-rs/alloy/issues/1007)) +- Add into transactions iterator ([#984](https://github.com/alloy-rs/alloy/issues/984)) + +### Miscellaneous Tasks + +- Convert rcp-types-eth block Header to consensus Header ([#1014](https://github.com/alloy-rs/alloy/issues/1014)) +- Make wrapped index value pub ([#988](https://github.com/alloy-rs/alloy/issues/988)) + +### Other + +- Add range test in `FilterBlockOption` ([#939](https://github.com/alloy-rs/alloy/issues/939)) + ## [0.1.3](https://github.com/alloy-rs/alloy/releases/tag/v0.1.3) - 2024-06-25 ### Features @@ -14,6 +31,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Tasks +- Release 0.1.3 - Nightly clippy ([#947](https://github.com/alloy-rs/alloy/issues/947)) ## [0.1.2](https://github.com/alloy-rs/alloy/releases/tag/v0.1.2) - 2024-06-19 diff --git a/crates/rpc-types-mev/CHANGELOG.md b/crates/rpc-types-mev/CHANGELOG.md index 73eda090361..ff00b47b972 100644 --- a/crates/rpc-types-mev/CHANGELOG.md +++ b/crates/rpc-types-mev/CHANGELOG.md @@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.4](https://github.com/alloy-rs/alloy/releases/tag/v0.1.4) - 2024-07-08 + +### Features + +- Add missing eth bundle args ([#978](https://github.com/alloy-rs/alloy/issues/978)) + +### Other + +- Update builders to vector of strings in privacy struct ([#983](https://github.com/alloy-rs/alloy/issues/983)) +- [hotfix] Typo change pub(crate) to pub ([#979](https://github.com/alloy-rs/alloy/issues/979)) + ## [0.1.3](https://github.com/alloy-rs/alloy/releases/tag/v0.1.3) - 2024-06-25 ### Features @@ -13,6 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Tasks +- Release 0.1.3 - Release 0.1.3 [`alloy`]: https://crates.io/crates/alloy diff --git a/crates/rpc-types-trace/CHANGELOG.md b/crates/rpc-types-trace/CHANGELOG.md index 26aafd6bec3..446969cb8fa 100644 --- a/crates/rpc-types-trace/CHANGELOG.md +++ b/crates/rpc-types-trace/CHANGELOG.md @@ -5,6 +5,23 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.4](https://github.com/alloy-rs/alloy/releases/tag/v0.1.4) - 2024-07-08 + +### Bug Fixes + +- Ots_getContractCreater has field hash instead of tx ([#999](https://github.com/alloy-rs/alloy/issues/999)) + +### Features + +- [otterscan] Add output for TraceEntry ([#1001](https://github.com/alloy-rs/alloy/issues/1001)) +- Add helpers for trace action ([#982](https://github.com/alloy-rs/alloy/issues/982)) + +## [0.1.3](https://github.com/alloy-rs/alloy/releases/tag/v0.1.3) - 2024-06-25 + +### Miscellaneous Tasks + +- Release 0.1.3 + ## [0.1.2](https://github.com/alloy-rs/alloy/releases/tag/v0.1.2) - 2024-06-19 ### Documentation diff --git a/crates/rpc-types-txpool/CHANGELOG.md b/crates/rpc-types-txpool/CHANGELOG.md index 6aec957f3be..bcffcbc0bdd 100644 --- a/crates/rpc-types-txpool/CHANGELOG.md +++ b/crates/rpc-types-txpool/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.4](https://github.com/alloy-rs/alloy/releases/tag/v0.1.4) - 2024-07-08 + +### Miscellaneous Tasks + +- Release 0.1.3 + ## [0.1.2](https://github.com/alloy-rs/alloy/releases/tag/v0.1.2) - 2024-06-19 ### Documentation diff --git a/crates/rpc-types/CHANGELOG.md b/crates/rpc-types/CHANGELOG.md index 8b3a6ae4b31..0f921bbc142 100644 --- a/crates/rpc-types/CHANGELOG.md +++ b/crates/rpc-types/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Tasks +- Release 0.1.3 - Release 0.1.3 ## [0.1.2](https://github.com/alloy-rs/alloy/releases/tag/v0.1.2) - 2024-06-19 diff --git a/crates/serde/CHANGELOG.md b/crates/serde/CHANGELOG.md index cc33d5b7dc1..9054ea1042b 100644 --- a/crates/serde/CHANGELOG.md +++ b/crates/serde/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [0.1.3](https://github.com/alloy-rs/alloy/releases/tag/v0.1.3) - 2024-06-25 +## [0.1.4](https://github.com/alloy-rs/alloy/releases/tag/v0.1.4) - 2024-07-08 ### Bug Fixes @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Tasks +- Release 0.1.3 - Nightly clippy ([#947](https://github.com/alloy-rs/alloy/issues/947)) ## [0.1.2](https://github.com/alloy-rs/alloy/releases/tag/v0.1.2) - 2024-06-19 diff --git a/crates/signer-aws/CHANGELOG.md b/crates/signer-aws/CHANGELOG.md index 32b9089896d..7b986cd7348 100644 --- a/crates/signer-aws/CHANGELOG.md +++ b/crates/signer-aws/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Tasks +- Release 0.1.3 - Release 0.1.3 ## [0.1.2](https://github.com/alloy-rs/alloy/releases/tag/v0.1.2) - 2024-06-19 diff --git a/crates/signer-gcp/CHANGELOG.md b/crates/signer-gcp/CHANGELOG.md index 84358b96dd9..843a7766f71 100644 --- a/crates/signer-gcp/CHANGELOG.md +++ b/crates/signer-gcp/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Tasks +- Release 0.1.3 - Release 0.1.3 ## [0.1.2](https://github.com/alloy-rs/alloy/releases/tag/v0.1.2) - 2024-06-19 diff --git a/crates/signer-ledger/CHANGELOG.md b/crates/signer-ledger/CHANGELOG.md index 6eb4709c0c5..2b2d0644f6e 100644 --- a/crates/signer-ledger/CHANGELOG.md +++ b/crates/signer-ledger/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Tasks +- Release 0.1.3 - Release 0.1.3 ## [0.1.2](https://github.com/alloy-rs/alloy/releases/tag/v0.1.2) - 2024-06-19 diff --git a/crates/signer-local/CHANGELOG.md b/crates/signer-local/CHANGELOG.md index 3fc93245d5e..d8fae0e572a 100644 --- a/crates/signer-local/CHANGELOG.md +++ b/crates/signer-local/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.4](https://github.com/alloy-rs/alloy/releases/tag/v0.1.4) - 2024-07-08 + +### Miscellaneous Tasks + +- Release 0.1.3 + ## [0.1.2](https://github.com/alloy-rs/alloy/releases/tag/v0.1.2) - 2024-06-19 ### Documentation diff --git a/crates/signer-trezor/CHANGELOG.md b/crates/signer-trezor/CHANGELOG.md index 693fec3842e..9a792659f9f 100644 --- a/crates/signer-trezor/CHANGELOG.md +++ b/crates/signer-trezor/CHANGELOG.md @@ -5,10 +5,17 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.4](https://github.com/alloy-rs/alloy/releases/tag/v0.1.4) - 2024-07-08 + +### Bug Fixes + +- [signer-trezor] Fix zero gas price when sending legacy tx with trezor ([#977](https://github.com/alloy-rs/alloy/issues/977)) + ## [0.1.3](https://github.com/alloy-rs/alloy/releases/tag/v0.1.3) - 2024-06-25 ### Miscellaneous Tasks +- Release 0.1.3 - Release 0.1.3 ## [0.1.2](https://github.com/alloy-rs/alloy/releases/tag/v0.1.2) - 2024-06-19 diff --git a/crates/signer/CHANGELOG.md b/crates/signer/CHANGELOG.md index b5935eba53b..af99be8213a 100644 --- a/crates/signer/CHANGELOG.md +++ b/crates/signer/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.4](https://github.com/alloy-rs/alloy/releases/tag/v0.1.4) - 2024-07-08 + +### Miscellaneous Tasks + +- Release 0.1.3 + ## [0.1.2](https://github.com/alloy-rs/alloy/releases/tag/v0.1.2) - 2024-06-19 ### Documentation diff --git a/crates/transport-http/CHANGELOG.md b/crates/transport-http/CHANGELOG.md index 91abd52d575..22e62e313d8 100644 --- a/crates/transport-http/CHANGELOG.md +++ b/crates/transport-http/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.4](https://github.com/alloy-rs/alloy/releases/tag/v0.1.4) - 2024-07-08 + +### Miscellaneous Tasks + +- Release 0.1.3 + ## [0.1.2](https://github.com/alloy-rs/alloy/releases/tag/v0.1.2) - 2024-06-19 ### Documentation diff --git a/crates/transport-ipc/CHANGELOG.md b/crates/transport-ipc/CHANGELOG.md index fb906b5131b..2cf8f7f6a2d 100644 --- a/crates/transport-ipc/CHANGELOG.md +++ b/crates/transport-ipc/CHANGELOG.md @@ -5,12 +5,16 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [0.1.3](https://github.com/alloy-rs/alloy/releases/tag/v0.1.3) - 2024-06-25 +## [0.1.4](https://github.com/alloy-rs/alloy/releases/tag/v0.1.4) - 2024-07-08 ### Bug Fixes - Continue reading ipc on large data ([#958](https://github.com/alloy-rs/alloy/issues/958)) +### Miscellaneous Tasks + +- Release 0.1.3 + ## [0.1.2](https://github.com/alloy-rs/alloy/releases/tag/v0.1.2) - 2024-06-19 ### Documentation diff --git a/crates/transport-ws/CHANGELOG.md b/crates/transport-ws/CHANGELOG.md index 3e8ed01c54f..26a45ac7cf6 100644 --- a/crates/transport-ws/CHANGELOG.md +++ b/crates/transport-ws/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.4](https://github.com/alloy-rs/alloy/releases/tag/v0.1.4) - 2024-07-08 + +### Miscellaneous Tasks + +- Release 0.1.3 + ## [0.1.2](https://github.com/alloy-rs/alloy/releases/tag/v0.1.2) - 2024-06-19 ### Documentation diff --git a/crates/transport/CHANGELOG.md b/crates/transport/CHANGELOG.md index f8c97d57177..c23edc0ab1e 100644 --- a/crates/transport/CHANGELOG.md +++ b/crates/transport/CHANGELOG.md @@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.4](https://github.com/alloy-rs/alloy/releases/tag/v0.1.4) - 2024-07-08 + +### Features + +- [transport] Retry layer ([#849](https://github.com/alloy-rs/alloy/issues/849)) + +## [0.1.3](https://github.com/alloy-rs/alloy/releases/tag/v0.1.3) - 2024-06-25 + +### Miscellaneous Tasks + +- Release 0.1.3 + ## [0.1.2](https://github.com/alloy-rs/alloy/releases/tag/v0.1.2) - 2024-06-19 ### Documentation From 10549bc64d8ddd149ac1ae38b5e9add00ee9d569 Mon Sep 17 00:00:00 2001 From: Roshan Date: Wed, 10 Jul 2024 15:41:40 +0800 Subject: [PATCH 61/61] chore: resolve merge conflicts --- crates/rpc-types-eth/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/rpc-types-eth/Cargo.toml b/crates/rpc-types-eth/Cargo.toml index 2e2b9a759e6..7b937833416 100644 --- a/crates/rpc-types-eth/Cargo.toml +++ b/crates/rpc-types-eth/Cargo.toml @@ -67,3 +67,4 @@ arbitrary = [ jsonrpsee-types = ["dep:jsonrpsee-types"] ssz = ["alloy-primitives/ssz", "alloy-eips/ssz"] k256 = ["alloy-consensus/k256", "alloy-eips/k256"] +sidecar = ["alloy-eips/kzg-sidecar"] \ No newline at end of file