reth_exex_types/
notification.rs1use std::sync::Arc;
2
3use reth_chain_state::CanonStateNotification;
4use reth_execution_types::Chain;
5use reth_primitives_traits::NodePrimitives;
6
7#[derive(Debug, Clone, PartialEq, Eq)]
9#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
10pub enum ExExNotification<N: NodePrimitives = reth_chain_state::EthPrimitives> {
11 ChainCommitted {
13 new: Arc<Chain<N>>,
15 },
16 ChainReorged {
18 old: Arc<Chain<N>>,
20 new: Arc<Chain<N>>,
22 },
23 ChainReverted {
25 old: Arc<Chain<N>>,
27 },
28}
29
30impl<N: NodePrimitives> ExExNotification<N> {
31 pub fn committed_chain(&self) -> Option<Arc<Chain<N>>> {
34 match self {
35 Self::ChainCommitted { new } | Self::ChainReorged { old: _, new } => Some(new.clone()),
36 Self::ChainReverted { .. } => None,
37 }
38 }
39
40 pub fn reverted_chain(&self) -> Option<Arc<Chain<N>>> {
43 match self {
44 Self::ChainReorged { old, new: _ } | Self::ChainReverted { old } => Some(old.clone()),
45 Self::ChainCommitted { .. } => None,
46 }
47 }
48
49 pub fn into_inverted(self) -> Self {
56 match self {
57 Self::ChainCommitted { new } => Self::ChainReverted { old: new },
58 Self::ChainReverted { old } => Self::ChainCommitted { new: old },
59 Self::ChainReorged { old, new } => Self::ChainReorged { old: new, new: old },
60 }
61 }
62}
63
64impl<P: NodePrimitives> From<CanonStateNotification<P>> for ExExNotification<P> {
65 fn from(notification: CanonStateNotification<P>) -> Self {
66 match notification {
67 CanonStateNotification::Commit { new } => Self::ChainCommitted { new },
68 CanonStateNotification::Reorg { old, new } => Self::ChainReorged { old, new },
69 }
70 }
71}
72
73#[cfg(all(feature = "serde", feature = "serde-bincode-compat"))]
75pub(super) mod serde_bincode_compat {
76 use reth_execution_types::serde_bincode_compat::Chain;
77 use reth_primitives::{EthPrimitives, NodePrimitives};
78 use serde::{Deserialize, Deserializer, Serialize, Serializer};
79 use serde_with::{DeserializeAs, SerializeAs};
80 use std::sync::Arc;
81
82 #[derive(Debug, Serialize, Deserialize)]
98 #[allow(missing_docs)]
99 #[serde(bound = "")]
100 pub enum ExExNotification<'a, N = EthPrimitives>
101 where
102 N: NodePrimitives,
103 {
104 ChainCommitted { new: Chain<'a, N> },
105 ChainReorged { old: Chain<'a, N>, new: Chain<'a, N> },
106 ChainReverted { old: Chain<'a, N> },
107 }
108
109 impl<'a, N> From<&'a super::ExExNotification<N>> for ExExNotification<'a, N>
110 where
111 N: NodePrimitives,
112 {
113 fn from(value: &'a super::ExExNotification<N>) -> Self {
114 match value {
115 super::ExExNotification::ChainCommitted { new } => {
116 ExExNotification::ChainCommitted { new: Chain::from(new.as_ref()) }
117 }
118 super::ExExNotification::ChainReorged { old, new } => {
119 ExExNotification::ChainReorged {
120 old: Chain::from(old.as_ref()),
121 new: Chain::from(new.as_ref()),
122 }
123 }
124 super::ExExNotification::ChainReverted { old } => {
125 ExExNotification::ChainReverted { old: Chain::from(old.as_ref()) }
126 }
127 }
128 }
129 }
130
131 impl<'a, N> From<ExExNotification<'a, N>> for super::ExExNotification<N>
132 where
133 N: NodePrimitives,
134 {
135 fn from(value: ExExNotification<'a, N>) -> Self {
136 match value {
137 ExExNotification::ChainCommitted { new } => {
138 Self::ChainCommitted { new: Arc::new(new.into()) }
139 }
140 ExExNotification::ChainReorged { old, new } => {
141 Self::ChainReorged { old: Arc::new(old.into()), new: Arc::new(new.into()) }
142 }
143 ExExNotification::ChainReverted { old } => {
144 Self::ChainReverted { old: Arc::new(old.into()) }
145 }
146 }
147 }
148 }
149
150 impl SerializeAs<super::ExExNotification> for ExExNotification<'_> {
151 fn serialize_as<S>(
152 source: &super::ExExNotification,
153 serializer: S,
154 ) -> Result<S::Ok, S::Error>
155 where
156 S: Serializer,
157 {
158 ExExNotification::from(source).serialize(serializer)
159 }
160 }
161
162 impl<'de> DeserializeAs<'de, super::ExExNotification> for ExExNotification<'de> {
163 fn deserialize_as<D>(deserializer: D) -> Result<super::ExExNotification, D::Error>
164 where
165 D: Deserializer<'de>,
166 {
167 ExExNotification::deserialize(deserializer).map(Into::into)
168 }
169 }
170
171 #[cfg(test)]
172 mod tests {
173 use super::super::{serde_bincode_compat, ExExNotification};
174 use arbitrary::Arbitrary;
175 use rand::Rng;
176 use reth_execution_types::Chain;
177 use reth_primitives::SealedBlockWithSenders;
178 use serde::{Deserialize, Serialize};
179 use serde_with::serde_as;
180 use std::sync::Arc;
181
182 #[test]
183 fn test_exex_notification_bincode_roundtrip() {
184 #[serde_as]
185 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
186 struct Data {
187 #[serde_as(as = "serde_bincode_compat::ExExNotification")]
188 notification: ExExNotification,
189 }
190
191 let mut bytes = [0u8; 1024];
192 rand::thread_rng().fill(bytes.as_mut_slice());
193 let data = Data {
194 notification: ExExNotification::ChainReorged {
195 old: Arc::new(Chain::new(
196 vec![SealedBlockWithSenders::arbitrary(&mut arbitrary::Unstructured::new(
197 &bytes,
198 ))
199 .unwrap()],
200 Default::default(),
201 None,
202 )),
203 new: Arc::new(Chain::new(
204 vec![SealedBlockWithSenders::arbitrary(&mut arbitrary::Unstructured::new(
205 &bytes,
206 ))
207 .unwrap()],
208 Default::default(),
209 None,
210 )),
211 },
212 };
213
214 let encoded = bincode::serialize(&data).unwrap();
215 let decoded: Data = bincode::deserialize(&encoded).unwrap();
216 assert_eq!(decoded, data);
217 }
218 }
219}