ethexe_common/
malachite.rs1use crate::injected::SignedInjectedTransaction;
19use alloc::vec::Vec;
20use derive_more::{Deref, DerefMut, IntoIterator};
21use gprimitives::H256;
22use parity_scale_codec::{Decode, Encode};
23use scale_info::TypeInfo;
24
25#[cfg(feature = "std")]
26use serde::{Deserialize, Serialize};
27
28#[derive(Clone, Debug, PartialEq, Eq, Encode, Decode, TypeInfo)]
30#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
31pub enum Transaction {
32 AdvanceTillEthereumBlock { block_hash: H256 },
34
35 ProgressTasks { limits: ProgressTasksLimits },
37
38 ProcessQueues { limits: ProcessQueuesLimits },
40
41 Injected(SignedInjectedTransaction),
43}
44
45#[derive(Clone, Debug, Default, PartialEq, Eq, Encode, Decode, TypeInfo)]
47#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
48pub struct ProgressTasksLimits {}
49
50#[derive(Clone, Debug, Default, PartialEq, Eq, Encode, Decode, TypeInfo)]
52#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
53pub struct ProcessQueuesLimits {
54 pub gas_allowance: u64,
55}
56
57impl Transaction {
58 pub fn tag(&self) -> &'static str {
60 match self {
61 Self::AdvanceTillEthereumBlock { .. } => "advance-eth-block",
62 Self::ProgressTasks { .. } => "progress-tasks",
63 Self::ProcessQueues { .. } => "process-queues",
64 Self::Injected(_) => "injected",
65 }
66 }
67}
68
69#[derive(
71 Clone, Debug, Default, PartialEq, Eq, Encode, Decode, TypeInfo, Deref, DerefMut, IntoIterator,
72)]
73#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
74pub struct Transactions(pub Vec<Transaction>);
75
76impl Transactions {
77 pub fn new(transactions: Vec<Transaction>) -> Self {
78 Self(transactions)
79 }
80
81 pub fn hash(&self) -> H256 {
83 gear_core::utils::hash(&self.encode()).into()
84 }
85}
86
87#[cfg(test)]
88mod tests {
89 use super::*;
90
91 fn empty_txs() -> Transactions {
92 Transactions::new(alloc::vec![
93 Transaction::ProgressTasks {
94 limits: ProgressTasksLimits::default(),
95 },
96 Transaction::ProcessQueues {
97 limits: ProcessQueuesLimits::default(),
98 },
99 ])
100 }
101
102 #[test]
103 fn hash_is_deterministic_for_same_content() {
104 let a = empty_txs();
105 let b = empty_txs();
106 assert_eq!(a.hash(), b.hash());
107 }
108
109 #[test]
110 fn hash_changes_when_transactions_change() {
111 let mut a = empty_txs();
112 let b = empty_txs();
113 a.push(Transaction::AdvanceTillEthereumBlock {
114 block_hash: H256::from_low_u64_be(0xEB),
115 });
116 assert_ne!(a.hash(), b.hash());
117 }
118
119 #[test]
120 fn transaction_tag_distinguishes_variants() {
121 let advance = Transaction::AdvanceTillEthereumBlock {
122 block_hash: H256::zero(),
123 };
124 let progress = Transaction::ProgressTasks {
125 limits: ProgressTasksLimits::default(),
126 };
127 let queues = Transaction::ProcessQueues {
128 limits: ProcessQueuesLimits::default(),
129 };
130 assert_eq!(advance.tag(), "advance-eth-block");
131 assert_eq!(progress.tag(), "progress-tasks");
132 assert_eq!(queues.tag(), "process-queues");
133 }
134
135 #[test]
136 fn scale_round_trip_preserves_hash() {
137 use parity_scale_codec::Decode;
142
143 let original = Transactions::new(alloc::vec![Transaction::AdvanceTillEthereumBlock {
144 block_hash: H256::from_low_u64_be(0xEB)
145 }]);
146 let encoded = original.encode();
147 let decoded = Transactions::decode(&mut encoded.as_slice()).expect("decode");
148 assert_eq!(original, decoded);
149 assert_eq!(original.hash(), decoded.hash());
150 }
151}