Skip to content
Open
2,235 changes: 1,007 additions & 1,228 deletions Cargo.lock

Large diffs are not rendered by default.

11 changes: 4 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,10 @@ edition = "2024"

[workspace.dependencies]
account_utils = { path = "common/account_utils" }
alloy-consensus = { version = "0.14.0", default-features = false }
alloy-primitives = { version = "1.0", features = ["rlp", "getrandom"] }
alloy-rlp = "0.3.4"
alloy-consensus = { version = "=1.0.37", default-features = false }
alloy-primitives = { version = "=1.4.0", features = ["rlp", "getrandom"] }
alloy-rlp = "=0.3.12"
alloy-rpc-types = "=1.0.37"
anyhow = "1"
arbitrary = { version = "1", features = ["derive"] }
async-channel = "1.9.0"
Expand Down Expand Up @@ -148,10 +149,6 @@ ethereum_hashing = "0.7.0"
ethereum_serde_utils = "0.8.0"
ethereum_ssz = "0.9.0"
ethereum_ssz_derive = "0.9.0"
ethers-core = "1"
ethers-middleware = { version = "1", default-features = false }
ethers-providers = { version = "1", default-features = false }
ethers-signers = { version = "1", default-features = false }
execution_layer = { path = "beacon_node/execution_layer" }
exit-future = "0.2"
filesystem = { path = "common/filesystem" }
Expand Down
2 changes: 1 addition & 1 deletion beacon_node/execution_layer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ edition = { workspace = true }
alloy-consensus = { workspace = true }
alloy-primitives = { workspace = true }
alloy-rlp = { workspace = true }
alloy-rpc-types = { workspace = true }
arc-swap = "1.6.0"
builder_client = { path = "../builder_client" }
bytes = { workspace = true }
eth2 = { workspace = true }
ethereum_serde_utils = { workspace = true }
ethereum_ssz = { workspace = true }
ethers-core = { workspace = true }
fixed_bytes = { workspace = true }
fork_choice = { workspace = true }
hash-db = "0.15.2"
Expand Down
1 change: 0 additions & 1 deletion beacon_node/execution_layer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ use engines::{Engine, EngineError};
pub use engines::{EngineState, ForkchoiceState};
use eth2::types::{BlobsBundle, FullPayloadContents};
use eth2::types::{ForkVersionedResponse, builder_bid::SignedBuilderBid};
use ethers_core::types::Transaction as EthersTransaction;
use fixed_bytes::UintExtended;
use fork_choice::ForkchoiceUpdateParameters;
use logging::crit;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use crate::EthersTransaction;
use crate::engine_api::{
ExecutionBlock, PayloadAttributes, PayloadId, PayloadStatusV1, PayloadStatusV1Status,
json_structures::{
JsonForkchoiceUpdatedV1Response, JsonPayloadStatusV1, JsonPayloadStatusV1Status,
},
};
use crate::engines::ForkchoiceState;
use alloy_consensus::TxEnvelope;
use alloy_rpc_types::Transaction as AlloyTransaction;
use eth2::types::BlobsBundle;
use kzg::{Kzg, KzgCommitment, KzgProof};
use parking_lot::Mutex;
Expand Down Expand Up @@ -835,7 +836,7 @@ pub fn generate_blobs<E: EthSpec>(

pub fn static_valid_tx<E: EthSpec>() -> Result<Transaction<E::MaxBytesPerTransaction>, String> {
// This is a real transaction hex encoded, but we don't care about the contents of the transaction.
let transaction: EthersTransaction = serde_json::from_str(
let transaction: AlloyTransaction = serde_json::from_str(
r#"{
"blockHash":"0x1d59ff54b1eb26b013ce3cb5fc9dab3705b415a67127a003c3e61eb445bb8df2",
"blockNumber":"0x5daf3b",
Expand All @@ -854,7 +855,8 @@ pub fn static_valid_tx<E: EthSpec>() -> Result<Transaction<E::MaxBytesPerTransac
}"#,
)
.unwrap();
VariableList::new(transaction.rlp().to_vec())

VariableList::new(alloy_rlp::encode::<TxEnvelope>(transaction.into()).to_vec())
.map_err(|e| format!("Failed to convert transaction to SSZ: {:?}", e))
}

Expand Down
5 changes: 4 additions & 1 deletion common/deposit_contract/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ edition = { workspace = true }
build = "build.rs"

[dependencies]
ethabi = "16.0.0"
alloy-dyn-abi = "1.4"
alloy-json-abi = "1.4"
alloy-primitives = { workspace = true }
ethereum_ssz = { workspace = true }
serde_json = { workspace = true }
tree_hash = { workspace = true }
types = { workspace = true }

Expand Down
103 changes: 67 additions & 36 deletions common/deposit_contract/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,44 @@
use ethabi::{Contract, Token};
use alloy_dyn_abi::{DynSolValue, JsonAbiExt};
use alloy_json_abi::JsonAbi;
use alloy_primitives::FixedBytes;
use ssz::{Decode, DecodeError as SszDecodeError, Encode};
use tree_hash::TreeHash;
use types::{DepositData, Hash256, PublicKeyBytes, SignatureBytes};

pub use ethabi::Error;

#[derive(Debug)]
pub enum DecodeError {
EthabiError(ethabi::Error),
pub enum Error {
AlloyCoreError(alloy_json_abi::Error),
SerdeJsonError(serde_json::Error),
DynAbiError(alloy_dyn_abi::Error),
SszDecodeError(SszDecodeError),
FunctionNotFound,
MissingField,
UnableToGetBytes,
MissingToken,
InadequateBytes,
}

impl From<ethabi::Error> for DecodeError {
fn from(e: ethabi::Error) -> DecodeError {
DecodeError::EthabiError(e)
impl From<alloy_json_abi::Error> for Error {
fn from(e: alloy_json_abi::Error) -> Error {
Error::AlloyCoreError(e)
}
}

impl From<serde_json::Error> for Error {
fn from(e: serde_json::Error) -> Error {
Error::SerdeJsonError(e)
}
}

impl From<alloy_dyn_abi::Error> for Error {
fn from(e: alloy_dyn_abi::Error) -> Error {
Error::DynAbiError(e)
}
}

impl From<SszDecodeError> for Error {
fn from(e: SszDecodeError) -> Error {
Error::SszDecodeError(e)
}
}

Expand All @@ -36,47 +57,57 @@ pub mod testnet {

pub fn encode_eth1_tx_data(deposit_data: &DepositData) -> Result<Vec<u8>, Error> {
let params = vec![
Token::Bytes(deposit_data.pubkey.as_ssz_bytes()),
Token::Bytes(deposit_data.withdrawal_credentials.as_ssz_bytes()),
Token::Bytes(deposit_data.signature.as_ssz_bytes()),
Token::FixedBytes(deposit_data.tree_hash_root().as_ssz_bytes()),
DynSolValue::Bytes(deposit_data.pubkey.as_ssz_bytes()),
DynSolValue::Bytes(deposit_data.withdrawal_credentials.as_ssz_bytes()),
DynSolValue::Bytes(deposit_data.signature.as_ssz_bytes()),
DynSolValue::FixedBytes(
FixedBytes::<32>::from_slice(&deposit_data.tree_hash_root().as_ssz_bytes()),
32,
),
];

// Here we make an assumption that the `crate::testnet::ABI` has a superset of the features of
// the crate::ABI`.
let abi = Contract::load(ABI)?;
let function = abi.function("deposit")?;
function.encode_input(&params)
let abi: JsonAbi = serde_json::from_slice(ABI)?;
let function = abi
.function("deposit")
.and_then(|functions| functions.first())
.ok_or(Error::FunctionNotFound)?;

function
.abi_encode_input(&params)
.map_err(Error::DynAbiError)
}

pub fn decode_eth1_tx_data(
bytes: &[u8],
amount: u64,
) -> Result<(DepositData, Hash256), DecodeError> {
let abi = Contract::load(ABI)?;
let function = abi.function("deposit")?;
let mut tokens = function.decode_input(bytes.get(4..).ok_or(DecodeError::InadequateBytes)?)?;
pub fn decode_eth1_tx_data(bytes: &[u8], amount: u64) -> Result<(DepositData, Hash256), Error> {
let abi: JsonAbi = serde_json::from_slice(ABI)?;
let function = abi
.function("deposit")
.and_then(|functions| functions.first())
.ok_or(Error::FunctionNotFound)?;

let input_data = bytes.get(4..).ok_or(Error::InadequateBytes)?;
let mut tokens = function.abi_decode_input(input_data)?;

macro_rules! decode_token {
($type: ty, $to_fn: ident) => {
<$type>::from_ssz_bytes(
&tokens
.pop()
.ok_or_else(|| DecodeError::MissingToken)?
.$to_fn()
.ok_or_else(|| DecodeError::UnableToGetBytes)?,
)
.map_err(DecodeError::SszDecodeError)?
};
($type: ty) => {{
let token = tokens.pop().ok_or(Error::MissingToken)?;
let bytes_data = match token {
DynSolValue::Bytes(b) => b,
DynSolValue::FixedBytes(b, _) => b.to_vec(),
_ => return Err(Error::UnableToGetBytes),
};
<$type>::from_ssz_bytes(&bytes_data)?
}};
}

let root = decode_token!(Hash256, into_fixed_bytes);
let root = decode_token!(Hash256);

let deposit_data = DepositData {
amount,
signature: decode_token!(SignatureBytes, into_bytes),
withdrawal_credentials: decode_token!(Hash256, into_bytes),
pubkey: decode_token!(PublicKeyBytes, into_bytes),
signature: decode_token!(SignatureBytes),
withdrawal_credentials: decode_token!(Hash256),
pubkey: decode_token!(PublicKeyBytes),
};

Ok((deposit_data, root))
Expand Down
2 changes: 1 addition & 1 deletion common/validator_dir/src/validator_dir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ pub enum Error {
UnableToReadDepositAmount(io::Error),
UnableToParseDepositAmount(std::num::ParseIntError),
DepositAmountIsNotUtf8(std::string::FromUtf8Error),
UnableToParseDepositData(deposit_contract::DecodeError),
UnableToParseDepositData(deposit_contract::Error),
Eth1TxHashExists(PathBuf),
UnableToWriteEth1TxHash(io::Error),
/// The deposit root in the deposit data file does not match the one generated locally. This is
Expand Down
9 changes: 5 additions & 4 deletions testing/execution_engine_integration/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ edition = { workspace = true }
portable = ["types/portable"]

[dependencies]
alloy-network = "=1.0.37"
alloy-primitives = { workspace = true }
alloy-provider = "=1.0.37"
alloy-rpc-types = { workspace = true }
alloy-signer-local = "=1.0.37"
async-channel = { workspace = true }
deposit_contract = { workspace = true }
ethers-core = { workspace = true }
ethers-middleware = { workspace = true }
ethers-providers = { workspace = true }
ethers-signers = { workspace = true }
execution_layer = { workspace = true }
fork_choice = { workspace = true }
futures = { workspace = true }
Expand Down
10 changes: 6 additions & 4 deletions testing/execution_engine_integration/src/execution_engine.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use ethers_providers::{Http, Provider};
use alloy_provider::ProviderBuilder;
use execution_layer::DEFAULT_JWT_FILE;
use network_utils::unused_port::unused_tcp4_port;
use reqwest::Url;
use sensitive_url::SensitiveUrl;
use std::path::PathBuf;
use std::process::Child;
Expand Down Expand Up @@ -34,7 +35,7 @@ pub struct ExecutionEngine<E> {
http_port: u16,
http_auth_port: u16,
child: Child,
pub provider: Provider<Http>,
pub provider: Box<dyn alloy_provider::Provider + Send + Sync>,
}

impl<E> Drop for ExecutionEngine<E> {
Expand All @@ -53,8 +54,9 @@ impl<E: GenericExecutionEngine> ExecutionEngine<E> {
let http_port = unused_tcp4_port().unwrap();
let http_auth_port = unused_tcp4_port().unwrap();
let child = E::start_client(&datadir, http_port, http_auth_port, jwt_secret_path);
let provider = Provider::<Http>::try_from(format!("http://localhost:{}", http_port))
.expect("failed to instantiate ethers provider");
let provider = Box::new(ProviderBuilder::new().connect_http(
Url::parse(&format!("http://localhost:{}", http_port)).expect("failed to parse URL"),
));
Self {
engine,
datadir,
Expand Down
42 changes: 25 additions & 17 deletions testing/execution_engine_integration/src/test_rig.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ use crate::execution_engine::{
ACCOUNT1, ACCOUNT2, ExecutionEngine, GenericExecutionEngine, KEYSTORE_PASSWORD, PRIVATE_KEYS,
};
use crate::transactions::transactions;
use ethers_middleware::SignerMiddleware;
use ethers_providers::Middleware;
use ethers_signers::LocalWallet;
use alloy_network::{EthereumWallet, TransactionBuilder};
use alloy_primitives::Address as AlloyAddress;
use alloy_provider::{Provider, ProviderBuilder};
use alloy_signer_local::PrivateKeySigner;
use execution_layer::test_utils::DEFAULT_GAS_LIMIT;
use execution_layer::{
BlockProposalContentsType, BuilderParams, ChainHealth, ExecutionLayer, PayloadAttributes,
Expand Down Expand Up @@ -202,12 +203,13 @@ impl<Engine: GenericExecutionEngine> TestRig<Engine> {
self.wait_until_synced().await;

// Create a local signer in case we need to sign transactions locally
let wallet1: LocalWallet = PRIVATE_KEYS[0].parse().expect("Invalid private key");
let signer = SignerMiddleware::new(&self.ee_a.execution_engine.provider, wallet1);
let private_key_signer: PrivateKeySigner =
PRIVATE_KEYS[0].parse().expect("Invalid private key");
let wallet = EthereumWallet::from(private_key_signer);

// We hardcode the accounts here since some EEs start with a default unlocked account
let account1 = ethers_core::types::Address::from_slice(&hex::decode(ACCOUNT1).unwrap());
let account2 = ethers_core::types::Address::from_slice(&hex::decode(ACCOUNT2).unwrap());
let account1 = AlloyAddress::from_slice(&hex::decode(ACCOUNT1).unwrap());
let account2 = AlloyAddress::from_slice(&hex::decode(ACCOUNT2).unwrap());

/*
* Read the terminal block hash from both pairs, check it's equal.
Expand Down Expand Up @@ -237,11 +239,18 @@ impl<Engine: GenericExecutionEngine> TestRig<Engine> {

if self.use_local_signing {
// Sign locally with the Signer middleware
for (i, tx) in txs.clone().into_iter().enumerate() {
for (i, mut tx) in txs.clone().into_iter().enumerate() {
// The local signer uses eth_sendRawTransaction, so we need to manually set the nonce
let mut tx = tx.clone();
tx.set_nonce(i as u64);
let pending_tx = signer.send_transaction(tx, None).await.unwrap();
tx = tx.with_nonce(i as u64);
let wallet_provider = ProviderBuilder::new().wallet(wallet.clone()).connect_http(
self.ee_a
.execution_engine
.http_url()
.to_string()
.parse()
.unwrap(),
);
let pending_tx = wallet_provider.send_transaction(tx).await.unwrap();
pending_txs.push(pending_tx);
}
} else {
Expand All @@ -261,7 +270,7 @@ impl<Engine: GenericExecutionEngine> TestRig<Engine> {
.ee_a
.execution_engine
.provider
.send_transaction(tx, None)
.send_transaction(tx)
.await
.unwrap();
pending_txs.push(pending_tx);
Expand Down Expand Up @@ -446,11 +455,10 @@ impl<Engine: GenericExecutionEngine> TestRig<Engine> {

// Verify that all submitted txs were successful
for pending_tx in pending_txs {
let tx_receipt = pending_tx.await.unwrap().unwrap();
assert_eq!(
tx_receipt.status,
Some(1.into()),
"Tx index {} has invalid status ",
let tx_receipt = pending_tx.get_receipt().await.unwrap();
assert!(
tx_receipt.status(),
"Tx index {:?} has invalid status ",
tx_receipt.transaction_index
);
}
Expand Down
Loading
Loading