diff --git a/crates/rbuilder-operator/src/blocks_processor.rs b/crates/rbuilder-operator/src/blocks_processor.rs index b6b9b0cf0..4c2804464 100644 --- a/crates/rbuilder-operator/src/blocks_processor.rs +++ b/crates/rbuilder-operator/src/blocks_processor.rs @@ -168,7 +168,7 @@ impl BlocksProcessorClient { eth_send_to_coinbase: U256::ZERO, total_gas_used: res.inplace_sim.gas_used(), original_bundle: encode_bundle_for_blocks_processor(bundle.clone()), - bundle_hash: bundle.hash, + bundle_hash: bundle.external_hash.unwrap_or(bundle.hash), }) } else { None @@ -457,6 +457,7 @@ mod tests { refund_recipient: None, refund_tx_hashes: None, delayed_refund: None, + bundle_hash: None, }, txs: Vec::new(), }, diff --git a/crates/rbuilder-primitives/src/lib.rs b/crates/rbuilder-primitives/src/lib.rs index ebd098352..929f4c27e 100644 --- a/crates/rbuilder-primitives/src/lib.rs +++ b/crates/rbuilder-primitives/src/lib.rs @@ -208,6 +208,9 @@ pub struct Bundle { /// Bundle refund data. pub refund: Option, + + /// Unique identifier for a bundle that was set by the sender of the bundle + pub external_hash: Option, } impl Bundle { diff --git a/crates/rbuilder-primitives/src/order_builder.rs b/crates/rbuilder-primitives/src/order_builder.rs index 9e45c820b..d43f20e99 100644 --- a/crates/rbuilder-primitives/src/order_builder.rs +++ b/crates/rbuilder-primitives/src/order_builder.rs @@ -219,6 +219,7 @@ impl BundleBuilder { dropping_tx_hashes, refund: self.refund, version: LAST_BUNDLE_VERSION, + external_hash: None, }; bundle.hash_slow(); bundle diff --git a/crates/rbuilder-primitives/src/serialize.rs b/crates/rbuilder-primitives/src/serialize.rs index acdfc02c1..474e2a5bc 100644 --- a/crates/rbuilder-primitives/src/serialize.rs +++ b/crates/rbuilder-primitives/src/serialize.rs @@ -153,6 +153,9 @@ pub struct RawBundleMetadata { /// delayedRefund (Optional) `Boolean`, A flag indicating whether the refund should be delayed. #[serde(skip_serializing_if = "Option::is_none")] pub delayed_refund: Option, + /// bundleHash, externally set unique identifier for the bundle + #[serde(skip_serializing_if = "Option::is_none")] + pub bundle_hash: Option, } impl RawBundleMetadata { @@ -381,6 +384,7 @@ impl RawBundle { dropping_tx_hashes: metadata.dropping_tx_hashes, refund, version, + external_hash: metadata.bundle_hash, }; bundle.hash_slow(); Ok(RawBundleDecodeResult::NewBundle(bundle)) @@ -418,6 +422,7 @@ impl RawBundle { refund_tx_hashes: value.refund.as_ref().map(|br| vec![br.tx_hash]), delayed_refund: value.refund.as_ref().map(|br| br.delayed), version: Some(Self::encode_version(value.version)), + bundle_hash: value.external_hash, }, } } diff --git a/crates/rbuilder-primitives/src/test_data_generator.rs b/crates/rbuilder-primitives/src/test_data_generator.rs index 4f0a2ea0a..e2a885108 100644 --- a/crates/rbuilder-primitives/src/test_data_generator.rs +++ b/crates/rbuilder-primitives/src/test_data_generator.rs @@ -101,6 +101,7 @@ impl TestDataGenerator { dropping_tx_hashes: vec![], refund: None, version: LAST_BUNDLE_VERSION, + external_hash: None, }; res.hash_slow(); res @@ -166,6 +167,7 @@ impl TestDataGenerator { dropping_tx_hashes: Default::default(), refund: None, version: LAST_BUNDLE_VERSION, + external_hash: None, }; bundle.hash_slow(); bundle diff --git a/crates/rbuilder/src/backtest/build_block/synthetic_orders.rs b/crates/rbuilder/src/backtest/build_block/synthetic_orders.rs index e76ea4968..355171691 100644 --- a/crates/rbuilder/src/backtest/build_block/synthetic_orders.rs +++ b/crates/rbuilder/src/backtest/build_block/synthetic_orders.rs @@ -101,6 +101,7 @@ impl SyntheticOrdersSource { dropping_tx_hashes: Default::default(), refund: None, version: LAST_BUNDLE_VERSION, + external_hash: None, }; bundle.hash_slow(); orders.push(OrdersWithTimestamp { diff --git a/crates/rbuilder/src/backtest/redistribute/mod.rs b/crates/rbuilder/src/backtest/redistribute/mod.rs index 69ad349af..d2cbd73b1 100644 --- a/crates/rbuilder/src/backtest/redistribute/mod.rs +++ b/crates/rbuilder/src/backtest/redistribute/mod.rs @@ -557,7 +557,7 @@ fn split_orders_by_identities( for order in &block_data.available_orders { let id = order.order.id(); if let Order::Bundle(bundle) = &order.order { - bundle_hash_by_id.insert(id, bundle.hash); + bundle_hash_by_id.insert(id, bundle.external_hash.unwrap_or(bundle.hash)); }; order_sender_by_id.insert(id, order_sender(&order.order)); let address = match order_redistribution_address(&order.order, protect_signers) { diff --git a/crates/rbuilder/src/backtest/restore_landed_orders/find_landed_orders.rs b/crates/rbuilder/src/backtest/restore_landed_orders/find_landed_orders.rs index 29b416575..7ddd21a9d 100644 --- a/crates/rbuilder/src/backtest/restore_landed_orders/find_landed_orders.rs +++ b/crates/rbuilder/src/backtest/restore_landed_orders/find_landed_orders.rs @@ -969,6 +969,7 @@ mod tests { refund: Default::default(), refund_identity: None, version: LAST_BUNDLE_VERSION, + external_hash: None, }); let expected = SimplifiedOrder::new( OrderId::Bundle(uuid::uuid!("00000000-0000-0000-0000-ffff00000002")), @@ -1004,6 +1005,7 @@ mod tests { }), refund_identity: None, version: LAST_BUNDLE_VERSION, + external_hash: None, }); let expected = SimplifiedOrder::new( OrderId::Bundle(uuid::uuid!("00000000-0000-0000-0000-ffff00000002")), diff --git a/crates/rbuilder/src/backtest/store.rs b/crates/rbuilder/src/backtest/store.rs index b7a4ce999..90c4cca32 100644 --- a/crates/rbuilder/src/backtest/store.rs +++ b/crates/rbuilder/src/backtest/store.rs @@ -752,6 +752,7 @@ mod test { delayed_refund: None, refund_identity: None, version: Some(RawBundle::encode_version(LAST_BUNDLE_VERSION)), + bundle_hash: None, }, })), } diff --git a/crates/rbuilder/src/building/builders/parallel_builder/conflict_resolvers.rs b/crates/rbuilder/src/building/builders/parallel_builder/conflict_resolvers.rs index 0991e0375..8e06e596b 100644 --- a/crates/rbuilder/src/building/builders/parallel_builder/conflict_resolvers.rs +++ b/crates/rbuilder/src/building/builders/parallel_builder/conflict_resolvers.rs @@ -526,6 +526,7 @@ mod tests { refund: None, refund_identity: None, version: LAST_BUNDLE_VERSION, + external_hash: None, }; Arc::new(SimulatedOrder { diff --git a/crates/rbuilder/src/live_builder/order_input/rpc_server.rs b/crates/rbuilder/src/live_builder/order_input/rpc_server.rs index 8bfc4ea08..b58e0aeaa 100644 --- a/crates/rbuilder/src/live_builder/order_input/rpc_server.rs +++ b/crates/rbuilder/src/live_builder/order_input/rpc_server.rs @@ -182,6 +182,10 @@ async fn handle_eth_send_bundle( } }; + if raw_bundle.metadata.bundle_hash.is_none() { + warn!("Bundle hash is not set"); + } + let bundle_res = match raw_bundle.decode(TxEncoding::WithBlobData) { Ok(bundle_res) => bundle_res, Err(err) => {