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

fix(op): fix payload id calculation #11730

Merged
merged 3 commits into from
Oct 28, 2024
Merged
Changes from 1 commit
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
65 changes: 60 additions & 5 deletions crates/optimism/payload/src/payload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//! Optimism builder support

use alloy_eips::eip2718::Decodable2718;
use alloy_primitives::{Address, B256, U256};
use alloy_primitives::{keccak256, Address, B256, U256};
use alloy_rlp::Encodable;
use alloy_rpc_types_engine::{ExecutionPayloadEnvelopeV2, ExecutionPayloadV1, PayloadId};
/// Re-export for use in downstream arguments.
Expand Down Expand Up @@ -286,16 +286,71 @@ pub(crate) fn payload_id_optimism(parent: &B256, attributes: &OpPayloadAttribute
hasher.update(parent_beacon_block);
}

let no_tx_pool = attributes.no_tx_pool.unwrap_or_default();
hasher.update([no_tx_pool as u8]);
if let Some(txs) = &attributes.transactions {
txs.iter().for_each(|tx| hasher.update(tx));
if attributes.no_tx_pool.unwrap_or_default() ||
attributes.transactions.as_ref().map(|txs| !txs.is_empty()).unwrap_or_default()
{
let no_tx_pool = attributes.no_tx_pool.unwrap_or_default();
hasher.update([no_tx_pool as u8]);
let txs_len = attributes.transactions.as_ref().map(|txs| txs.len()).unwrap_or_default();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we now have multiple calls to unwrap_or_default.

can we do this just once

hasher.update(&txs_len.to_be_bytes()[..]);
if let Some(txs) = &attributes.transactions {
txs.iter().for_each(|tx| {
// we have to just hash the bytes here because otherwise we would need to decode
// the transactions here which really isn't ideal
let tx_hash = keccak256(tx);
// maybe we can try just taking the hash and not decoding
hasher.update(tx_hash)
});
}
}

if let Some(gas_limit) = attributes.gas_limit {
hasher.update(gas_limit.to_be_bytes());
}

if let Some(eip_1559_params) = attributes.eip_1559_params {
hasher.update(eip_1559_params.as_slice());
}

let out = hasher.finalize();
PayloadId::new(out.as_slice()[..8].try_into().expect("sufficient length"))
}

#[cfg(test)]
mod tests {
use super::*;
use crate::OpPayloadAttributes;
use alloy_primitives::{address, b256, bytes, FixedBytes};
use alloy_rpc_types_engine::PayloadAttributes;
use std::str::FromStr;

#[test]
fn test_payload_id_parity_op_geth() {
// INFO rollup_boost::server:received fork_choice_updated_v3 from builder and l2_client
// payload_id_builder="0x6ef26ca02318dcf9" payload_id_l2="0x03d2dae446d2a86a"
let expected =
PayloadId::new(FixedBytes::<8>::from_str("0x03d2dae446d2a86a").unwrap().into());
let attrs = OpPayloadAttributes {
payload_attributes: PayloadAttributes {
timestamp: 1728933301,
prev_randao: b256!("9158595abbdab2c90635087619aa7042bbebe47642dfab3c9bfb934f6b082765").into(),
suggested_fee_recipient: address!("4200000000000000000000000000000000000011"),
withdrawals: Some([].into()),
parent_beacon_block_root: b256!("8fe0193b9bf83cb7e5a08538e494fecc23046aab9a497af3704f4afdae3250ff").into()
},
transactions: Some([bytes!("7ef8f8a0dc19cfa777d90980e4875d0a548a881baaa3f83f14d1bc0d3038bc329350e54194deaddeaddeaddeaddeaddeaddeaddeaddead00019442000000000000000000000000000000000000158080830f424080b8a4440a5e20000f424000000000000000000000000300000000670d6d890000000000000125000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000014bf9181db6e381d4384bbf69c48b0ee0eed23c6ca26143c6d2544f9d39997a590000000000000000000000007f83d659683caf2767fd3c720981d51f5bc365bc")].into()),
no_tx_pool: None,
gas_limit: Some(30000000),
eip_1559_params: None,
};

// Reth's `PayloadId` should match op-geth's `PayloadId`. This fails
assert_eq!(
expected,
payload_id_optimism(
&b256!("3533bf30edaf9505d0810bf475cbe4e5f4b9889904b9845e83efdeab4e92eb1e"),
&attrs
) // := "0x6ef26ca02318dcf9"
);
}
}
Loading