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(relay): ExecutionRequestsV4 with eip7685::Requests conversion #1787

Merged
Merged
Show file tree
Hide file tree
Changes from 9 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
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ serde_with = { version = "3", default-features = false, features = ["macros"] }
auto_impl = "1.2"
base64 = "0.22"
bimap = "0.6"
cfg_eval = "0.1.2"
ryanschneider marked this conversation as resolved.
Show resolved Hide resolved
cfg-if = "1"
derive_more = { version = "1.0.0", default-features = false }
home = "0.5"
Expand Down
1 change: 0 additions & 1 deletion crates/eips/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ ethereum_ssz = { workspace = true, optional = true }
# arbitrary
arbitrary = { workspace = true, features = ["derive"], optional = true }


[dev-dependencies]
alloy-primitives = { workspace = true, features = [
"rand",
Expand Down
66 changes: 64 additions & 2 deletions crates/eips/src/eip6110.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,74 @@
//! Contains Deposit request constants, first introduced in the [Prague hardfork](https://github.com/ethereum/execution-apis/blob/main/src/engine/prague.md).
//! Contains Deposit request 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

use alloy_primitives::{address, Address};
use alloy_primitives::{address, Address, FixedBytes, B256};

/// Mainnet deposit contract address.
pub const MAINNET_DEPOSIT_CONTRACT_ADDRESS: Address =
address!("00000000219ab540356cbb839cbe05303d7705fa");

/// The [EIP-7685](https://eips.ethereum.org/EIPS/eip-7685) request type for deposit requests.
pub const DEPOSIT_REQUEST_TYPE: u8 = 0x00;

/// The [EIP-6110 Consensus Specs](https://github.com/ethereum/consensus-specs/blob/2660af05390aa61f06142e1c6311a3a3c633f720/specs/_features/eip6110/beacon-chain.md#constants) defined maximum payload size.
pub const MAX_DEPOSIT_RECEIPTS_PER_PAYLOAD: usize = 8192;

/// This structure maps onto the deposit object from [EIP-6110](https://eips.ethereum.org/EIPS/eip-6110).
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "ssz", derive(ssz_derive::Encode, ssz_derive::Decode))]
#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
pub struct DepositRequest {
/// Validator public key
pub pubkey: FixedBytes<48>,
/// Withdrawal credentials
pub withdrawal_credentials: B256,
/// Amount of ether deposited in gwei
#[cfg_attr(feature = "serde", serde(with = "alloy_serde::ssz::json::uint"))]
pub amount: u64,
/// Deposit signature
pub signature: FixedBytes<96>,
/// Deposit index
#[cfg_attr(feature = "serde", serde(with = "alloy_serde::ssz::json::uint"))]
pub index: u64,
}

#[cfg(test)]
mod tests {
use super::*;
use alloy_primitives::hex;

#[test]
#[cfg(feature = "serde")]
fn test_serde_deposit_request() {
// Sample JSON input representing a deposit request
let json_data = r#"{"pubkey":"0x8e01a8f21bdc38991ada53ca86d6c78d874675a450a38431cc6aa0f12d5661e344784c56c8a211f7025224d1303ee801","withdrawal_credentials":"0x010000000000000000000000af6df504f08ddf582d604d2f0a593bc153c25dbd","amount":"18112749083033600","signature":"0xb65f3db79405544528d6d92040282f29171f4ff6e5abb2d59f9ee1f1254aced2a7000f87bc2684f543e913a7cc1007ea0e97289b349c553eecdf253cd3ef5814088ba3d4ac286f2634dac3d026d9a01e4c166dc75e249d626a0f1c180dab75ce","index":"13343631333247680512"}"#;

// Deserialize the JSON into a DepositRequest struct
let deposit_request: DepositRequest =
serde_json::from_str(json_data).expect("Failed to deserialize");

// Verify the deserialized content
assert_eq!(
deposit_request.pubkey,
FixedBytes::<48>::from(hex!("8E01A8F21BDC38991ADA53CA86D6C78D874675A450A38431CC6AA0F12D5661E344784C56C8A211F7025224D1303EE801"))
);
assert_eq!(
deposit_request.withdrawal_credentials,
B256::from(hex!("010000000000000000000000AF6DF504F08DDF582D604D2F0A593BC153C25DBD"))
);
assert_eq!(deposit_request.amount, 0x0040597307000000u64);
assert_eq!(
deposit_request.signature,
FixedBytes::<96>::from(hex!("B65F3DB79405544528D6D92040282F29171F4FF6E5ABB2D59F9EE1F1254ACED2A7000F87BC2684F543E913A7CC1007EA0E97289B349C553EECDF253CD3EF5814088BA3D4AC286F2634DAC3D026D9A01E4C166DC75E249D626A0F1C180DAB75CE"))
);
assert_eq!(deposit_request.index, 0xB92E1A0000000000u64);

// Serialize the struct back into JSON
let serialized_json = serde_json::to_string(&deposit_request).expect("Failed to serialize");

// Check if the serialized JSON matches the expected JSON structure
assert_eq!(serialized_json, json_data);
}
}
64 changes: 62 additions & 2 deletions crates/eips/src/eip7002.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
//! Contains the system contract, first introduced in the [Prague hardfork](https://github.com/ethereum/execution-apis/blob/main/src/engine/prague.md).
//! Contains the system contract and [WithdrawalRequest] types, first introduced in the [Prague hardfork](https://github.com/ethereum/execution-apis/blob/main/src/engine/prague.md).
//!
//! See also [EIP-7002](https://eips.ethereum.org/EIPS/eip-7002): Execution layer triggerable withdrawals

use alloy_primitives::{address, bytes, Address, Bytes};
use alloy_primitives::{address, bytes, Address, Bytes, FixedBytes};

/// The caller to be used when calling the EIP-7002 withdrawal requests contract at the end of the
/// block.
Expand All @@ -17,3 +17,63 @@ pub static WITHDRAWAL_REQUEST_PREDEPLOY_CODE: Bytes = bytes!(" 3373fffffffffff

/// The [EIP-7685](https://eips.ethereum.org/EIPS/eip-7685) request type for withdrawal requests.
pub const WITHDRAWAL_REQUEST_TYPE: u8 = 0x01;

/// The [EIP-7002](https://eips.ethereum.org/EIPS/eip-7002) defined maximum withdrawal requests per block.
pub const MAX_WITHDRAWAL_REQUESTS_PER_BLOCK: usize = 16;

/// Represents an execution layer triggerable withdrawal request.
///
/// See [EIP-7002](https://eips.ethereum.org/EIPS/eip-7002).
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "ssz", derive(ssz_derive::Encode, ssz_derive::Decode))]
#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
pub struct WithdrawalRequest {
/// Address of the source of the exit.
pub source_address: Address,
/// Validator public key.
pub validator_pubkey: FixedBytes<48>,
/// Amount of withdrawn ether in gwei.
#[cfg_attr(feature = "serde", serde(with = "alloy_serde::ssz::json::uint"))]
pub amount: u64,
}

#[cfg(test)]
mod tests {
use super::*;
use alloy_primitives::hex;

#[test]
#[cfg(feature = "serde")]
fn test_serde_withdrawal_request() {
// Sample JSON input representing a withdrawal request
let json_data = r#"{
"source_address":"0xAE0E8770147AaA6828a0D6f642504663F10F7d1E",
"validator_pubkey":"0x8e8d8749f6bc79b78be7cc6e49ff640e608454840c360b344c3a4d9b7428e280e7f40d2271bad65d8cbbfdd43cb8793b",
"amount":"1"
}"#;

// Deserialize the JSON into a WithdrawalRequest struct
let withdrawal_request: WithdrawalRequest =
serde_json::from_str(json_data).expect("Failed to deserialize");

// Verify the deserialized content
assert_eq!(
withdrawal_request.source_address,
address!("AE0E8770147AaA6828a0D6f642504663F10F7d1E")
);
assert_eq!(
withdrawal_request.validator_pubkey,
FixedBytes::<48>::from(hex!("8e8d8749f6bc79b78be7cc6e49ff640e608454840c360b344c3a4d9b7428e280e7f40d2271bad65d8cbbfdd43cb8793b"))
);
assert_eq!(withdrawal_request.amount, 1);

// Serialize the struct back into JSON
let serialized_json =
serde_json::to_string(&withdrawal_request).expect("Failed to serialize");

// Check if the serialized JSON matches the expected JSON structure
let expected_json = r#"{"source_address":"0xae0e8770147aaa6828a0d6f642504663f10f7d1e","validator_pubkey":"0x8e8d8749f6bc79b78be7cc6e49ff640e608454840c360b344c3a4d9b7428e280e7f40d2271bad65d8cbbfdd43cb8793b","amount":"1"}"#;
assert_eq!(serialized_json, expected_json);
}
}
64 changes: 62 additions & 2 deletions crates/eips/src/eip7251.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
//! Contains consolidation code, 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

use alloy_primitives::{address, bytes, Address, Bytes};
use alloy_primitives::{address, bytes, Address, Bytes, FixedBytes};

/// The address for the EIP-7251 consolidation requests contract:
/// `0x00b42dbF2194e931E80326D950320f7d9Dbeac02`
Expand All @@ -14,3 +14,63 @@ pub static CONSOLIDATION_REQUEST_PREDEPLOY_CODE: Bytes = bytes!("3373fffffffffff

/// The [EIP-7685](https://eips.ethereum.org/EIPS/eip-7685) request type for consolidation requests.
pub const CONSOLIDATION_REQUEST_TYPE: u8 = 0x02;

/// The [EIP-7251](https://eips.ethereum.org/EIPS/eip-7251) defined maximum number of consolidation requests per block.
pub const MAX_CONSOLIDATION_REQUESTS_PER_BLOCK: usize = 2;

/// 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, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "ssz", derive(ssz_derive::Encode, ssz_derive::Decode))]
#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
pub struct ConsolidationRequest {
/// Source address
pub source_address: Address,
/// Source public key
pub source_pubkey: FixedBytes<48>,
/// Target public key
pub target_pubkey: FixedBytes<48>,
}

#[cfg(test)]
mod tests {
use super::*;
use alloy_primitives::hex;
use core::str::FromStr;

#[test]
fn test_serde_consolidation_request() {
// Sample JSON input representing a consolidation request
let json_data = r#"{
"source_address":"0x007eABCA654E67103dF02f49EbdC5f6Cd9387a07",
"source_pubkey":"0xb13ff174911d0137e5f2b739fbf172b22cba35a037ef1edb03683b75c9abf5b271f8d48ad279cc89c7fae91db631c1e7",
"target_pubkey":"0xd0e5be6b709f2dc02a49f6e37e0d03b7d832b79b0db1c8bbfd5b81b8e57b79a1282fb99a671b4629a0e0bfffa7cf6d4f"
}"#;

// Deserialize the JSON into a ConsolidationRequest struct
let consolidation_request: ConsolidationRequest =
serde_json::from_str(json_data).expect("Failed to deserialize");

// Verify the deserialized content
assert_eq!(
consolidation_request.source_address,
Address::from_str("0x007eABCA654E67103dF02f49EbdC5f6Cd9387a07").unwrap()
);
assert_eq!(
consolidation_request.source_pubkey,
FixedBytes::<48>::from(hex!("b13ff174911d0137e5f2b739fbf172b22cba35a037ef1edb03683b75c9abf5b271f8d48ad279cc89c7fae91db631c1e7"))
);
assert_eq!(
consolidation_request.target_pubkey,
FixedBytes::<48>::from(hex!("d0e5be6b709f2dc02a49f6e37e0d03b7d832b79b0db1c8bbfd5b81b8e57b79a1282fb99a671b4629a0e0bfffa7cf6d4f"))
);

// Serialize the struct back into JSON
let serialized_json =
serde_json::to_string(&consolidation_request).expect("Failed to serialize");

// Check if the serialized JSON matches the expected JSON structure
let expected_json = r#"{"source_address":"0x007eabca654e67103df02f49ebdc5f6cd9387a07","source_pubkey":"0xb13ff174911d0137e5f2b739fbf172b22cba35a037ef1edb03683b75c9abf5b271f8d48ad279cc89c7fae91db631c1e7","target_pubkey":"0xd0e5be6b709f2dc02a49f6e37e0d03b7d832b79b0db1c8bbfd5b81b8e57b79a1282fb99a671b4629a0e0bfffa7cf6d4f"}"#;
assert_eq!(serialized_json, expected_json);
}
}
1 change: 0 additions & 1 deletion crates/rpc-types-beacon/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ workspace = true
alloy-eips = { workspace = true, features = ["serde"] }
alloy-rpc-types-engine = { workspace = true, features = ["serde"] }
alloy-primitives.workspace = true
alloy-serde.workspace = true

# ssz
ethereum_ssz_derive = { workspace = true, optional = true }
Expand Down
Loading
Loading