use crate::{chain::Chain, specs::HostBlockSpec};
use alloy::consensus::BlobTransactionSidecar;
use signet_types::primitives::TransactionSigned;
use std::{collections::BTreeMap, sync::Arc};
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ExExNotification {
Committed {
new: Arc<Chain>,
},
Reorged {
old: Arc<Chain>,
new: Arc<Chain>,
},
Reverted {
old: Arc<Chain>,
},
}
#[derive(Debug, Default)]
pub struct NotificationSpec {
pub old: Vec<HostBlockSpec>,
pub new: Vec<HostBlockSpec>,
}
impl NotificationSpec {
pub fn commit_single_block(block: HostBlockSpec) -> Self {
Self { old: vec![], new: vec![block] }
}
pub fn revert_single_block(block: HostBlockSpec) -> Self {
Self { old: vec![block], new: vec![] }
}
pub fn commit(mut self, block: HostBlockSpec) -> Self {
self.new.push(block);
self
}
pub fn revert(mut self, block: HostBlockSpec) -> Self {
self.old.push(block);
self
}
pub fn to_exex_notification(&self) -> NotificationWithSidecars {
let mut sidecars = BTreeMap::new();
let old_chain = if !self.old.is_empty() {
let num = self.old[0].block_number();
let (mut chain, _sidecar) = self.old[0].to_chain();
for (i, block) in self.old.iter().enumerate().skip(1) {
block.set_block_number(num + i as u64);
chain.append_block(block.recovered_block(), block.execution_outcome());
}
Some(chain)
} else {
None
};
let new_chain = if !self.new.is_empty() {
let num = self.new[0].block_number();
let (mut chain, sidecar) = self.new[0].to_chain();
if let Some(sidecar) = sidecar {
let tx = self.new[0].sealed_block().body.transactions().last().unwrap().clone();
sidecars.insert(num, (sidecar, tx));
}
for (i, block) in self.new.iter().enumerate().skip(1) {
block.set_block_number(num + i as u64);
let execution_outcome = block.execution_outcome();
if let Some(sidecar) = block.sidecar.clone() {
let tx = block.sealed_block().body.transactions().last().unwrap().clone();
sidecars.insert(block.block_number(), (sidecar, tx));
}
chain.append_block(block.recovered_block(), execution_outcome)
}
Some(chain)
} else {
None
};
match (old_chain, new_chain) {
(Some(old_chain), Some(new_chain)) => NotificationWithSidecars {
notification: ExExNotification::Reorged {
old: Arc::new(old_chain),
new: Arc::new(new_chain),
},
sidecars,
},
(Some(old_chain), None) => NotificationWithSidecars {
notification: ExExNotification::Reverted { old: Arc::new(old_chain) },
sidecars,
},
(None, Some(new_chain)) => NotificationWithSidecars {
notification: ExExNotification::Committed { new: Arc::new(new_chain) },
sidecars,
},
(None, None) => panic!("missing old and new chains"),
}
}
}
#[derive(Debug, Clone)]
pub struct NotificationWithSidecars {
pub notification: ExExNotification,
pub sidecars: BTreeMap<u64, (BlobTransactionSidecar, TransactionSigned)>,
}
impl NotificationWithSidecars {
pub fn commit_single_block(block: HostBlockSpec) -> Self {
NotificationSpec::commit_single_block(block).to_exex_notification()
}
pub fn revert_single_block(block: HostBlockSpec) -> Self {
NotificationSpec::revert_single_block(block).to_exex_notification()
}
}