From 9171546a6fda223d54bdb76ab1e2c9ed309b1f32 Mon Sep 17 00:00:00 2001 From: James Prestwich Date: Thu, 19 Sep 2024 08:22:12 -0400 Subject: [PATCH] feat: bundle hash on ethsendbundle (#1308) * feat: bundle hash on ethsendbundle * nit: unfinished NB --- crates/rpc-types-mev/src/eth_calls.rs | 33 ++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/crates/rpc-types-mev/src/eth_calls.rs b/crates/rpc-types-mev/src/eth_calls.rs index b7f6dc66984..8e38811c8f9 100644 --- a/crates/rpc-types-mev/src/eth_calls.rs +++ b/crates/rpc-types-mev/src/eth_calls.rs @@ -1,7 +1,7 @@ use crate::{u256_numeric_string, Privacy, Validity}; use alloy_eips::BlockNumberOrTag; -use alloy_primitives::{Address, Bytes, B256, U256}; +use alloy_primitives::{keccak256, Address, Bytes, Keccak256, B256, U256}; use serde::{Deserialize, Serialize}; /// Bundle of transactions for `eth_callBundle` @@ -138,6 +138,37 @@ pub struct EthSendBundle { pub replacement_uuid: Option, } +impl EthSendBundle { + /// Returns the bundle hash. + /// + /// This is the keccak256 hash of the transaction hashes of the + /// transactions in the bundle. + /// + /// ## Note + /// + /// Logic for calculating the bundle hash is as follows: + /// - Calculate the hash of each transaction in the bundle + /// - Concatenate the hashes, in bundle order + /// - Calculate the keccak256 hash of the concatenated hashes + /// + /// See the [flashbots impl]. + /// + /// This function will not verify transaction correctness. If the bundle + /// `txs` contains invalid transactions, the bundle hash will still be + /// calculated. + /// + /// [flashbots impl]: https://github.com/flashbots/mev-geth/blob/fddf97beec5877483f879a77b7dea2e58a58d653/internal/ethapi/api.go#L2067 + pub fn bundle_hash(&self) -> B256 { + let mut hasher = Keccak256::default(); + for tx in &self.txs { + // NB: the txs must contain envelopes, so the tx_hash is just the + // keccak256 hash of the envelope. no need to deserialize the tx + hasher.update(keccak256(tx)); + } + hasher.finalize() + } +} + /// Response from the matchmaker after sending a bundle. #[derive(Deserialize, Debug, Serialize, Clone, PartialEq, Eq)] #[serde(rename_all = "camelCase")]