namada_node/shell/
vote_extensions.rs1pub mod bridge_pool_vext;
4pub mod eth_events;
5pub mod val_set_update;
6
7use drain_filter_polyfill::DrainFilter;
8use namada_sdk::eth_bridge::protocol::transactions::bridge_pool_roots::sign_bridge_pool_root;
9use namada_sdk::eth_bridge::protocol::transactions::ethereum_events::sign_ethereum_events;
10use namada_sdk::eth_bridge::protocol::transactions::validator_set_update::sign_validator_set_update;
11pub use namada_sdk::eth_bridge::protocol::validation::VoteExtensionError;
12use namada_sdk::tx::Signed;
13use namada_vote_ext::{
14 VoteExtension, bridge_pool_roots, ethereum_events, validator_set_update,
15};
16
17use super::*;
18use crate::shims::abcipp_shim_types::shim::TxBytes;
19
20const VALIDATOR_EXPECT_MSG: &str = "Only validators receive this method call.";
22
23impl<D, H> Shell<D, H>
24where
25 D: DB + for<'iter> DBIter<'iter> + Sync + 'static,
26 H: StorageHasher + Sync + 'static,
27{
28 #[inline]
32 pub fn craft_extension(&mut self) -> VoteExtension {
33 VoteExtension {
34 ethereum_events: self.extend_vote_with_ethereum_events(),
35 bridge_pool_root: self
36 .extend_vote_with_bp_roots()
37 .map(bridge_pool_roots::SignedVext),
38 validator_set_update: self.extend_vote_with_valset_update(),
39 }
40 }
41
42 #[inline]
44 pub fn extend_vote_with_ethereum_events(
45 &mut self,
46 ) -> Option<Signed<ethereum_events::Vext>> {
47 let events = self.new_ethereum_events();
48 self.sign_ethereum_events(events)
49 }
50
51 pub fn sign_ethereum_events(
54 &self,
55 ethereum_events: Vec<EthereumEvent>,
56 ) -> Option<Signed<ethereum_events::Vext>> {
57 let validator_addr = self
58 .mode
59 .get_validator_address()
60 .expect(VALIDATOR_EXPECT_MSG);
61 let protocol_key = match &self.mode {
62 ShellMode::Validator { data, .. } => &data.keys.protocol_keypair,
63 _ => unreachable!("{VALIDATOR_EXPECT_MSG}"),
64 };
65 sign_ethereum_events(
66 &self.state,
67 validator_addr,
68 protocol_key,
69 ethereum_events,
70 )
71 .map(|ethereum_events::SignedVext(ext)| ext)
72 }
73
74 pub fn extend_vote_with_bp_roots(
76 &self,
77 ) -> Option<Signed<bridge_pool_roots::Vext>> {
78 let validator_addr = self
79 .mode
80 .get_validator_address()
81 .expect(VALIDATOR_EXPECT_MSG);
82 let eth_hot_key = self
83 .mode
84 .get_eth_bridge_keypair()
85 .expect(VALIDATOR_EXPECT_MSG);
86 let protocol_key = match &self.mode {
87 ShellMode::Validator { data, .. } => &data.keys.protocol_keypair,
88 _ => unreachable!("{VALIDATOR_EXPECT_MSG}"),
89 };
90 sign_bridge_pool_root(
91 &self.state,
92 validator_addr,
93 eth_hot_key,
94 protocol_key,
95 )
96 .map(|bridge_pool_roots::SignedVext(ext)| ext)
97 }
98
99 pub fn extend_vote_with_valset_update(
102 &self,
103 ) -> Option<validator_set_update::SignedVext> {
104 let validator_addr = self
105 .mode
106 .get_validator_address()
107 .expect(VALIDATOR_EXPECT_MSG);
108 let eth_hot_key = self
109 .mode
110 .get_eth_bridge_keypair()
111 .expect("{VALIDATOR_EXPECT_MSG}");
112 sign_validator_set_update::<_, _, governance::Store<_>>(
113 &self.state,
114 validator_addr,
115 eth_hot_key,
116 )
117 }
118
119 pub fn deserialize_vote_extensions<'shell>(
122 &'shell self,
123 txs: &'shell mut Vec<TxBytes>,
124 ) -> DrainFilter<'shell, TxBytes, impl FnMut(&mut TxBytes) -> bool + 'shell>
125 {
126 drain_filter_polyfill::VecExt::drain_filter(txs, move |tx_bytes| {
127 let tx = match Tx::try_from_bytes(tx_bytes.as_ref()) {
128 Ok(tx) => tx,
129 Err(err) => {
130 tracing::warn!(
131 ?err,
132 "Failed to deserialize tx in \
133 deserialize_vote_extensions"
134 );
135 return false;
136 }
137 };
138 match (&tx).try_into().ok() {
139 Some(EthereumTxData::BridgePoolVext(_)) => true,
140 Some(EthereumTxData::EthEventsVext(ext)) => {
141 ext.data.ethereum_events.iter().any(|event| {
144 self.state
145 .ethbridge_queries()
146 .validate_eth_event_nonce(event)
147 })
148 }
149 Some(EthereumTxData::ValSetUpdateVext(ext)) => {
150 let is_seen = self
160 .state
161 .ethbridge_queries()
162 .valset_upd_seen(ext.data.signing_epoch.next());
163 !is_seen
164 }
165 _ => false,
166 }
167 })
168 }
169}
170
171pub fn iter_protocol_txs(
174 ext: VoteExtension,
175) -> impl Iterator<Item = EthereumTxData> {
176 let VoteExtension {
177 ethereum_events,
178 bridge_pool_root,
179 validator_set_update,
180 } = ext;
181 [
182 ethereum_events.map(|e| {
183 EthereumTxData::EthEventsVext(ethereum_events::SignedVext(e))
184 }),
185 bridge_pool_root.map(EthereumTxData::BridgePoolVext),
186 validator_set_update.map(EthereumTxData::ValSetUpdateVext),
187 ]
188 .into_iter()
189 .flatten()
190}