Skip to content

Commit

Permalink
chore(engine): alloy type port
Browse files Browse the repository at this point in the history
  • Loading branch information
refcell committed May 1, 2024
1 parent e338fd3 commit ea600a2
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 123 deletions.
8 changes: 4 additions & 4 deletions src/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,10 @@ impl From<&ExecutionPayload> for BlockInfo {
/// Converts an [ExecutionPayload] to [BlockInfo]
fn from(value: &ExecutionPayload) -> Self {
Self {
number: value.block_number.as_u64(),
hash: B256::from_slice(value.block_hash.as_bytes()),
parent_hash: B256::from_slice(value.parent_hash.as_bytes()),
timestamp: value.timestamp.as_u64(),
number: value.block_number.try_into().unwrap_or_default(),
hash: value.block_hash,
parent_hash: value.parent_hash,
timestamp: value.timestamp.try_into().unwrap_or_default(),
}
}
}
Expand Down
11 changes: 5 additions & 6 deletions src/derive/stages/attributes.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::sync::{Arc, RwLock};

use ethers::abi::{decode, encode, ParamType, Token};
use ethers::types::{Address, Log, H256, U256, U64};
use ethers::types::{Address, Log, H256, U256};
use ethers::utils::{keccak256, rlp::Encodable, rlp::RlpStream};

use eyre::Result;
Expand Down Expand Up @@ -89,7 +89,6 @@ impl Attributes {
None
};

let timestamp = U64([input.timestamp]);
let l1_inclusion_block = Some(input.l1_inclusion_block);
let seq_number = Some(self.sequence_number);
let prev_randao = l1_info.block_info.mix_hash;
Expand All @@ -98,12 +97,12 @@ impl Attributes {
let suggested_fee_recipient = SystemAccounts::default().fee_vault;

PayloadAttributes {
timestamp,
prev_randao: H256::from_slice(prev_randao.as_slice()),
suggested_fee_recipient: Address::from_slice(suggested_fee_recipient.as_slice()),
timestamp: alloy_primitives::U64::from(input.timestamp),
prev_randao,
suggested_fee_recipient,
transactions,
no_tx_pool: true,
gas_limit: U64([l1_info.system_config.gas_limit.try_into().unwrap()]),
gas_limit: alloy_primitives::U64::from(l1_info.system_config.gas_limit),
withdrawals,
epoch,
l1_inclusion_block,
Expand Down
26 changes: 13 additions & 13 deletions src/driver/engine_driver.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use std::sync::Arc;

use alloy_primitives::B256;
use ethers::providers::{Http, Middleware, Provider};
use ethers::types::Transaction;
use ethers::{
Expand Down Expand Up @@ -38,7 +37,8 @@ pub struct EngineDriver<E: Engine> {
impl<E: Engine> EngineDriver<E> {
/// Initiates validation & production of a new L2 block from the given [PayloadAttributes] and updates the forkchoice
pub async fn handle_attributes(&mut self, attributes: PayloadAttributes) -> Result<()> {
let block: Option<Block<Transaction>> = self.block_at(attributes.timestamp.as_u64()).await;
let timestamp: u64 = attributes.timestamp.try_into()?;
let block: Option<Block<Transaction>> = self.block_at(timestamp).await;

if let Some(block) = block {
if should_skip(&block, &attributes)? {
Expand Down Expand Up @@ -100,10 +100,10 @@ impl<E: Engine> EngineDriver<E> {
let payload = self.build_payload(attributes).await?;

let new_head = BlockInfo {
number: payload.block_number.as_u64(),
hash: B256::from_slice(payload.block_hash.as_bytes()),
parent_hash: B256::from_slice(payload.parent_hash.as_bytes()),
timestamp: payload.timestamp.as_u64(),
number: payload.block_number.try_into().unwrap_or_default(),
hash: payload.block_hash,
parent_hash: payload.parent_hash,
timestamp: payload.timestamp.try_into().unwrap_or_default(),
};

self.push_payload(payload).await?;
Expand Down Expand Up @@ -199,9 +199,9 @@ impl<E: Engine> EngineDriver<E> {
/// - `finalized_block` = `finalized_head`
fn create_forkchoice_state(&self) -> ForkchoiceState {
ForkchoiceState {
head_block_hash: H256::from_slice(self.unsafe_head.hash.as_slice()),
safe_block_hash: H256::from_slice(self.safe_head.hash.as_slice()),
finalized_block_hash: H256::from_slice(self.finalized_head.hash.as_slice()),
head_block_hash: self.unsafe_head.hash,
safe_block_hash: self.safe_head.hash,
finalized_block_hash: self.finalized_head.hash,
}
}

Expand Down Expand Up @@ -243,10 +243,10 @@ fn should_skip(block: &Block<Transaction>, attributes: &PayloadAttributes) -> Re
tracing::debug!("block hashes: {:?}", block_hashes);

let is_same = attributes_hashes == block_hashes
&& attributes.timestamp.as_u64() == block.timestamp.as_u64()
&& attributes.prev_randao == block.mix_hash.unwrap()
&& attributes.suggested_fee_recipient == block.author.unwrap()
&& attributes.gas_limit.as_u64() == block.gas_limit.as_u64();
&& attributes.timestamp == alloy_primitives::U64::from(block.timestamp.as_u64())
&& attributes.prev_randao == alloy_primitives::B256::from_slice(block.mix_hash.unwrap().as_bytes())
&& attributes.suggested_fee_recipient == alloy_primitives::Address::from_slice(block.author.unwrap().as_bytes())
&& attributes.gas_limit == alloy_primitives::U64::from(block.gas_limit.as_u64());

Ok(is_same)
}
Expand Down
7 changes: 5 additions & 2 deletions src/driver/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,14 +230,17 @@ impl<E: Engine> Driver<E> {
}

self.future_unsafe_blocks.retain(|payload| {
let unsafe_block_num = payload.block_number.as_u64();
let unsafe_block_num: u64 = match payload.block_number.try_into() {
Ok(num) => num,
Err(_) => return false,
};
let synced_block_num = self.engine_driver.unsafe_head.number;

unsafe_block_num > synced_block_num && unsafe_block_num - synced_block_num < 1024
});

let next_unsafe_payload = self.future_unsafe_blocks.iter().find(|p| {
alloy_primitives::B256::from_slice(p.parent_hash.as_bytes())
p.parent_hash
== self.engine_driver.unsafe_head.hash
});

Expand Down
14 changes: 6 additions & 8 deletions src/engine/fork.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use alloy_primitives::B256;
use ethers::types::H256;
use serde::{Deserialize, Serialize};

use super::{PayloadId, PayloadStatus};
Expand All @@ -23,23 +22,22 @@ pub struct ForkChoiceUpdate {
#[serde(rename_all = "camelCase")]
pub struct ForkchoiceState {
/// 32 byte block hash of the head of the canonical chain
pub head_block_hash: H256,
pub head_block_hash: B256,
/// 32 byte "safe" block hash of the canonical chain under certain synchrony and honesty assumptions
/// This value MUST be either equal to or an ancestor of headBlockHash
pub safe_block_hash: H256,
pub safe_block_hash: B256,
/// 32 byte block hash of the most recent finalized block
pub finalized_block_hash: H256,
pub finalized_block_hash: B256,
}

impl ForkchoiceState {
/// Creates a new fork choice state with the given head block hash.
/// The safe and finalized block hashes are set to the head block hash.
pub fn from_single_head(head_block_hash: B256) -> Self {
let hash = H256::from_slice(head_block_hash.as_slice());
Self {
head_block_hash: hash,
safe_block_hash: hash,
finalized_block_hash: hash,
head_block_hash,
safe_block_hash: head_block_hash,
finalized_block_hash: head_block_hash,
}
}
}
131 changes: 43 additions & 88 deletions src/engine/payload.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use alloy_consensus::TxEnvelope;
use alloy_eips::eip2718::Encodable2718;
use alloy_rpc_types::Block as AlloyBlock;
use alloy_rpc_types::Block;
use alloy_rpc_types::BlockTransactions;
use ethers::types::{Block, Bytes, Transaction, H160, H256, U64};
use alloy_primitives::{Bytes, Address, B256, U64};
use eyre::Result;
use serde::{Deserialize, Serialize};

Expand All @@ -16,17 +16,17 @@ use crate::{
#[serde(rename_all = "camelCase")]
pub struct ExecutionPayload {
/// A 32 byte hash of the parent payload
pub parent_hash: H256,
/// A 20 byte hash (aka Address) for the feeRecipient field of the new payload
pub fee_recipient: H160,
pub parent_hash: B256,
/// The fee recipient of the new payload
pub fee_recipient: Address,
/// A 32 byte state root hash
pub state_root: H256,
pub state_root: B256,
/// A 32 byte receipt root hash
pub receipts_root: H256,
pub receipts_root: B256,
/// A 32 byte logs bloom filter
pub logs_bloom: Bytes,
/// A 32 byte beacon chain randomness value
pub prev_randao: H256,
pub prev_randao: B256,
/// A 64 bit number for the current block index
pub block_number: U64,
/// A 64 bit value for the gas limit
Expand All @@ -40,7 +40,7 @@ pub struct ExecutionPayload {
/// 256 bits for the base fee per gas
pub base_fee_per_gas: U64,
/// The 32 byte block hash
pub block_hash: H256,
pub block_hash: B256,
/// An array of transaction objects where each object is a byte list
pub transactions: Vec<RawTransaction>,
/// An array of beaconchain withdrawals. Always empty as this exists only for L1 compatibility
Expand All @@ -54,11 +54,11 @@ pub struct ExecutionPayload {
pub excess_blob_gas: Option<U64>,
}

impl TryFrom<AlloyBlock> for ExecutionPayload {
impl TryFrom<Block> for ExecutionPayload {
type Error = eyre::Report;

/// Converts a [Block] to an [ExecutionPayload]
fn try_from(value: AlloyBlock) -> Result<Self> {
fn try_from(value: Block) -> Result<Self> {
let txs = if let BlockTransactions::Full(txs) = value.transactions {
txs
} else {
Expand All @@ -75,62 +75,24 @@ impl TryFrom<AlloyBlock> for ExecutionPayload {
.to_vec();

Ok(ExecutionPayload {
parent_hash: H256::from_slice(value.header.parent_hash.as_slice()),
fee_recipient: H160::from_slice(SystemAccounts::default().fee_vault.as_slice()),
state_root: H256::from_slice(value.header.state_root.as_slice()),
receipts_root: H256::from_slice(value.header.receipts_root.as_slice()),
parent_hash: value.header.parent_hash,
fee_recipient: SystemAccounts::default().fee_vault,
state_root: value.header.state_root,
receipts_root: value.header.receipts_root,
logs_bloom: value.header.logs_bloom.0.to_vec().into(),
prev_randao: H256::from_slice(value.header.mix_hash.unwrap().as_slice()),
block_number: value.header.number.unwrap().into(),
gas_limit: (value.header.gas_limit as u64).into(),
gas_used: (value.header.gas_used as u64).into(),
timestamp: value.header.timestamp.into(),
prev_randao: value.header.mix_hash.ok_or_else(|| eyre::eyre!("Missing mix hash"))?,
block_number: value.header.number.ok_or_else(|| eyre::eyre!("Missing block number"))?.try_into()?,
gas_limit: (value.header.gas_limit as u64).try_into()?,
gas_used: (value.header.gas_used as u64).try_into()?,
timestamp: value.header.timestamp.try_into()?,
extra_data: Bytes::from(value.header.extra_data.0),
base_fee_per_gas: (value.header.base_fee_per_gas.unwrap_or_else(|| 0u64.into()) as u64)
.into(),
block_hash: H256::from_slice(value.header.hash.unwrap().as_slice()),
.try_into()?,
block_hash: value.header.hash.ok_or_else(|| eyre::eyre!("Missing block hash"))?,
transactions: encoded_txs,
withdrawals: Some(Vec::new()),
blob_gas_used: value.header.blob_gas_used.map(|v| (v as u64).into()),
excess_blob_gas: value.header.excess_blob_gas.map(|v| (v as u64).into()),
})
}
}

impl TryFrom<Block<Transaction>> for ExecutionPayload {
type Error = eyre::Report;

/// Converts a [Block] to an [ExecutionPayload]
fn try_from(value: Block<Transaction>) -> Result<Self> {
let encoded_txs = (*value
.transactions
.into_iter()
.map(|tx| RawTransaction(tx.rlp().to_vec()))
.collect::<Vec<_>>())
.to_vec();

Ok(ExecutionPayload {
parent_hash: value.parent_hash,
fee_recipient: H160::from_slice(SystemAccounts::default().fee_vault.as_slice()),
state_root: value.state_root,
receipts_root: value.receipts_root,
logs_bloom: value.logs_bloom.unwrap().as_bytes().to_vec().into(),
prev_randao: value.mix_hash.unwrap(),
block_number: value.number.unwrap(),
gas_limit: value.gas_limit.as_u64().into(),
gas_used: value.gas_used.as_u64().into(),
timestamp: value.timestamp.as_u64().into(),
extra_data: value.extra_data.clone(),
base_fee_per_gas: value
.base_fee_per_gas
.unwrap_or_else(|| 0u64.into())
.as_u64()
.into(),
block_hash: value.hash.unwrap(),
transactions: encoded_txs,
withdrawals: Some(Vec::new()),
blob_gas_used: value.blob_gas_used.map(|v| v.as_u64().into()),
excess_blob_gas: value.excess_blob_gas.map(|v| v.as_u64().into()),
blob_gas_used: value.header.blob_gas_used.map(|v| (v as u64).try_into()).transpose()?,
excess_blob_gas: value.header.excess_blob_gas.map(|v| (v as u64).try_into()).transpose()?,
})
}
}
Expand All @@ -145,9 +107,9 @@ pub struct PayloadAttributes {
/// 64 bit value for the timestamp field of the new payload.
pub timestamp: U64,
/// 32 byte value for the prevRandao field of the new payload.
pub prev_randao: H256,
pub prev_randao: B256,
/// 20 bytes suggested value for the feeRecipient field of the new payload.
pub suggested_fee_recipient: H160,
pub suggested_fee_recipient: Address,
/// Array of transactions to be included in the new payload.
pub transactions: Option<Vec<RawTransaction>>,
/// Boolean value indicating whether or not the payload should be built without including transactions from the txpool.
Expand Down Expand Up @@ -187,7 +149,7 @@ pub struct PayloadStatus {
/// The status of the payload.
pub status: Status,
/// 32 Bytes - the hash of the most recent valid block in the branch defined by payload and its ancestors
pub latest_valid_hash: Option<H256>,
pub latest_valid_hash: Option<B256>,
/// A message providing additional details on the validation error if the payload is classified as INVALID or INVALID_BLOCK_HASH.
#[serde(default)]
pub validation_error: Option<String>,
Expand All @@ -213,37 +175,30 @@ pub enum Status {

#[cfg(test)]
mod tests {

use ethers::{
providers::{Http, Middleware, Provider},
types::H256,
};
use eyre::Result;

use alloy_provider::{Provider, ProviderBuilder};
use alloy_primitives::{b256, uint};
use crate::engine::ExecutionPayload;

#[tokio::test]
async fn test_from_block_hash_to_execution_paylaod() -> Result<()> {
if std::env::var("L2_TEST_RPC_URL").is_ok() {
let checkpoint_hash: H256 =
"0xc2794a16acacd9f7670379ffd12b6968ff98e2a602f57d7d1f880220aa5a4973".parse()?;
let Ok(l2_rpc_url) = std::env::var("L2_TEST_RPC_URL") else {
return Ok(());
};
let checkpoint_hash = b256!("c2794a16acacd9f7670379ffd12b6968ff98e2a602f57d7d1f880220aa5a4973");
let url = reqwest::Url::parse(&l2_rpc_url)?;
let l2_provider = ProviderBuilder::new().on_http(url);

let l2_rpc = std::env::var("L2_TEST_RPC_URL")?;
let checkpoint_sync_url = Provider::<Http>::try_from(l2_rpc)?;
let checkpoint_block = checkpoint_sync_url
.get_block_with_txs(checkpoint_hash)
.await?
.unwrap();
let checkpoint_block = l2_provider
.get_block(checkpoint_hash.into(), true)
.await?
.unwrap();

let payload = ExecutionPayload::try_from(checkpoint_block)?;
let payload = ExecutionPayload::try_from(checkpoint_block)?;

assert_eq!(
payload.block_hash,
"0xc2794a16acacd9f7670379ffd12b6968ff98e2a602f57d7d1f880220aa5a4973".parse()?
);
assert_eq!(payload.block_number, 8453214u64.into());
assert_eq!(payload.base_fee_per_gas, 50u64.into());
}
assert_eq!(payload.block_hash, checkpoint_hash);
assert_eq!(payload.block_number, uint!(8453214U64));
assert_eq!(payload.base_fee_per_gas, uint!(50U64));

Ok(())
}
Expand Down
5 changes: 3 additions & 2 deletions src/network/handlers/block_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,9 @@ impl BlockHandler {
.unwrap()
.as_secs();

let is_future = envelope.payload.timestamp.as_u64() > current_timestamp + 5;
let is_past = envelope.payload.timestamp.as_u64() < current_timestamp - 60;
let timestamp: u64 = envelope.payload.timestamp.try_into().unwrap_or_default();
let is_future = timestamp > current_timestamp + 5;
let is_past = timestamp < current_timestamp - 60;
let time_valid = !(is_future || is_past);

let msg = envelope.hash.signature_message(self.chain_id);
Expand Down

0 comments on commit ea600a2

Please sign in to comment.