Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(engine): Optional Serde #1283

Merged
merged 5 commits into from
Sep 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/eip7547/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ workspace = true

[dependencies]
alloy-primitives = { workspace = true, features = ["rlp", "serde"] }
alloy-rpc-types-engine = { workspace = true }
alloy-rpc-types-engine = { workspace = true, features = ["serde"] }
alloy-serde = { workspace = true }

# serde
Expand Down
2 changes: 1 addition & 1 deletion crates/provider/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ alloy-rpc-types-anvil = { workspace = true, optional = true }
alloy-rpc-types-eth.workspace = true
alloy-rpc-types-trace = { workspace = true, optional = true }
alloy-rpc-types-txpool = { workspace = true, optional = true }
alloy-rpc-types-engine = { workspace = true, optional = true }
alloy-rpc-types-engine = { workspace = true, optional = true, features = ["serde"] }
alloy-rpc-types = { workspace = true, optional = true }
alloy-transport-http = { workspace = true, optional = true }
alloy-transport-ipc = { workspace = true, optional = true }
Expand Down
2 changes: 1 addition & 1 deletion crates/rpc-types-beacon/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ workspace = true
[dependencies]
# ethereum
alloy-eips = { workspace = true, features = ["serde"] }
alloy-rpc-types-engine.workspace = true
alloy-rpc-types-engine = { workspace = true, features = ["serde"] }
alloy-primitives.workspace = true

# ssz
Expand Down
9 changes: 6 additions & 3 deletions crates/rpc-types-engine/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,18 @@ workspace = true

[dependencies]
# ethereum
alloy-serde.workspace = true
alloy-rlp = { workspace = true, features = ["arrayvec", "derive"] }
alloy-primitives = { workspace = true, features = ["rlp", "serde"] }
alloy-consensus = { workspace = true, features = ["serde"] }
alloy-eips = { workspace = true, features = ["serde"] }

# misc
serde = { workspace = true, features = ["derive"] }
derive_more = { workspace = true, features = ["display"] }

# serde
alloy-serde = { workspace = true, optional = true }
serde = { workspace = true, features = ["derive"], optional = true }

# ssz
ethereum_ssz_derive = { workspace = true, optional = true }
ethereum_ssz = { workspace = true, optional = true }
Expand All @@ -42,8 +44,9 @@ rand = { workspace = true, optional = true }
jsonwebtoken = { version = "9.3.0", optional = true }

[features]
default = ["jwt", "std"]
default = ["jwt", "std", "serde"]
std = ["alloy-consensus/std", "derive_more/std"]
serde = ["dep:serde", "dep:alloy-serde"]
jwt = ["dep:jsonwebtoken", "dep:rand"]
jsonrpsee-types = ["dep:jsonrpsee-types"]
ssz = ["std", "dep:ethereum_ssz", "dep:ethereum_ssz_derive", "alloy-eips/ssz"]
Expand Down
3 changes: 2 additions & 1 deletion crates/rpc-types-engine/src/cancun.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ use alloy_primitives::B256;
///
/// See also:
/// <https://github.com/ethereum/execution-apis/blob/fe8e13c288c592ec154ce25c534e26cb7ce0530d/src/engine/cancun.md#request>
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct CancunPayloadFields {
/// The parent beacon block root.
pub parent_beacon_block_root: B256,
Expand Down
11 changes: 6 additions & 5 deletions crates/rpc-types-engine/src/forkchoice.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use super::{PayloadStatus, PayloadStatusEnum};
use crate::PayloadId;
use alloy_primitives::B256;
use serde::{Deserialize, Serialize};

/// invalid forkchoice state error code.
pub const INVALID_FORK_CHOICE_STATE_ERROR: i32 = -38002;
Expand All @@ -19,8 +18,9 @@ pub const INVALID_PAYLOAD_ATTRIBUTES_ERROR_MSG: &str = "Invalid payload attribut
pub type ForkChoiceUpdateResult = Result<ForkchoiceUpdated, ForkchoiceUpdateError>;

/// This structure encapsulates the fork choice state
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
pub struct ForkchoiceState {
/// Hash of the head block.
pub head_block_hash: B256,
Expand Down Expand Up @@ -116,8 +116,9 @@ impl From<ForkchoiceUpdateError> for jsonrpsee_types::error::ErrorObject<'static
/// Represents a successfully _processed_ forkchoice state update.
///
/// Note: this can still be INVALID if the provided payload was invalid.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
pub struct ForkchoiceUpdated {
/// Represents the outcome of the validation of the payload, independently of the payload being
/// valid or not.
Expand Down
10 changes: 6 additions & 4 deletions crates/rpc-types-engine/src/identification.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

use alloc::string::{String, ToString};
use core::str::FromStr;
use serde::{Deserialize, Serialize};

/// This enum defines a standard for specifying a client with just two letters. Clients teams which
/// have a code reserved in this list MUST use this code when identifying themselves.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum ClientCode {
/// Besu
BU,
Expand Down Expand Up @@ -101,8 +101,9 @@ impl core::fmt::Display for ClientCode {
}

/// Contains information which identifies a client implementation.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
pub struct ClientVersionV1 {
/// Client code, e.g. GE for Geth
pub code: ClientCode,
Expand All @@ -120,6 +121,7 @@ mod tests {
use super::*;

#[test]
#[cfg(feature = "serde")]
fn client_id_serde() {
let s = r#"{"code":"RH","name":"Reth","version":"v1.10.8","commit":"fa4ff922"}"#;
let v: ClientVersionV1 = serde_json::from_str(s).unwrap();
Expand Down
14 changes: 11 additions & 3 deletions crates/rpc-types-engine/src/jwt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use jsonwebtoken::{
decode, errors::ErrorKind, get_current_timestamp, Algorithm, DecodingKey, Validation,
};
use rand::Rng;
use serde::{Deserialize, Serialize};
#[cfg(feature = "std")]
use std::{
fs, io,
Expand Down Expand Up @@ -117,7 +116,8 @@ const JWT_SIGNATURE_ALGO: Algorithm = Algorithm::HS256;
///
/// The Engine API spec requires that just the `iat` (issued-at) claim is provided.
/// It ignores claims that are optional or additional for this specification.
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
#[derive(Copy, Clone, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Claims {
/// The "iat" value MUST be a number containing a NumericDate value.
/// According to the RFC A NumericDate represents the number of seconds since
Expand Down Expand Up @@ -215,6 +215,7 @@ impl JwtSecret {
/// - The JWT `exp` (expiration time) claim is validated by default if defined.
///
/// See also: [JWT Claims - Engine API specs](https://github.com/ethereum/execution-apis/blob/main/src/engine/authentication.md#jwt-claims)
#[cfg(feature = "serde")]
pub fn validate(&self, jwt: &str) -> Result<(), JwtError> {
// Create a new validation object with the required signature algorithm
// and ensure that the `iat` claim is present. The `exp` claim is validated if defined.
Expand Down Expand Up @@ -250,6 +251,7 @@ impl JwtSecret {

/// Encode the header and claims given and sign the payload using the algorithm from the header
/// and the key.
#[cfg(feature = "serde")]
pub fn encode(&self, claims: &Claims) -> Result<String, jsonwebtoken::errors::Error> {
let bytes = &self.0;
let key = jsonwebtoken::EncodingKey::from_secret(bytes);
Expand Down Expand Up @@ -331,6 +333,7 @@ mod tests {
}

#[test]
#[cfg(feature = "serde")]
fn validation_ok() {
let secret = JwtSecret::random();
let claims = Claims { iat: get_current_timestamp(), exp: Some(10000000000) };
Expand All @@ -342,6 +345,7 @@ mod tests {
}

#[test]
#[cfg(feature = "serde")]
fn validation_with_current_time_ok() {
let secret = JwtSecret::random();
let claims = Claims::default();
Expand All @@ -353,7 +357,7 @@ mod tests {
}

#[test]
#[cfg(feature = "std")]
#[cfg(all(feature = "std", feature = "serde"))]
fn validation_error_iat_out_of_window() {
let secret = JwtSecret::random();

Expand All @@ -379,6 +383,7 @@ mod tests {
}

#[test]
#[cfg(feature = "serde")]
fn validation_error_exp_expired() {
let secret = JwtSecret::random();
let claims = Claims { iat: get_current_timestamp(), exp: Some(1) };
Expand All @@ -390,6 +395,7 @@ mod tests {
}

#[test]
#[cfg(feature = "serde")]
fn validation_error_wrong_signature() {
let secret_1 = JwtSecret::random();
let claims = Claims { iat: get_current_timestamp(), exp: Some(10000000000) };
Expand All @@ -402,6 +408,7 @@ mod tests {
}

#[test]
#[cfg(feature = "serde")]
fn validation_error_unsupported_algorithm() {
let secret = JwtSecret::random();
let bytes = &secret.0;
Expand All @@ -417,6 +424,7 @@ mod tests {
}

#[test]
#[cfg(feature = "serde")]
fn valid_without_exp_claim() {
let secret = JwtSecret::random();

Expand Down
Loading