primitives/transaction/
native_transaction.rs

1use crate::{
2    bytes::Bytes, transaction::AccessListItem, Action, SignedTransaction,
3    Transaction, TransactionWithSignature,
4    TransactionWithSignatureSerializePart,
5};
6use cfx_types::{AddressWithSpace, H256, U256};
7use cfxkey::Address;
8use rlp_derive::{RlpDecodable, RlpEncodable};
9use serde_derive::{Deserialize, Serialize};
10
11use super::{AccessList, AuthorizationListItem};
12
13#[derive(
14    Default,
15    Debug,
16    Clone,
17    Eq,
18    PartialEq,
19    RlpEncodable,
20    RlpDecodable,
21    Serialize,
22    Deserialize,
23)]
24pub struct NativeTransaction {
25    /// Nonce.
26    pub nonce: U256,
27    /// Gas price.
28    pub gas_price: U256,
29    /// Gas paid up front for transaction execution.
30    pub gas: U256,
31    /// Action, can be either call or contract create.
32    pub action: Action,
33    /// Transferred value.
34    pub value: U256,
35    /// Maximum storage increasement in this execution.
36    pub storage_limit: u64,
37    /// The epoch height of the transaction. A transaction
38    /// can only be packed between the epochs of [epoch_height -
39    /// TRANSACTION_EPOCH_BOUND, epoch_height + TRANSACTION_EPOCH_BOUND]
40    pub epoch_height: u64,
41    /// The chain id of the transaction
42    pub chain_id: u32,
43    /// Transaction data.
44    pub data: Bytes,
45}
46
47impl NativeTransaction {
48    /// Specify the sender; this won't survive the serialize/deserialize
49    /// process, but can be cloned.
50    pub fn fake_sign(self, from: AddressWithSpace) -> SignedTransaction {
51        SignedTransaction {
52            transaction: TransactionWithSignature {
53                transaction: TransactionWithSignatureSerializePart {
54                    unsigned: Transaction::Native(
55                        TypedNativeTransaction::Cip155(self),
56                    ),
57                    r: U256::one(),
58                    s: U256::one(),
59                    v: 0,
60                },
61                hash: H256::zero(),
62                rlp_size: None,
63            }
64            .compute_hash(),
65            sender: from.address,
66            public: None,
67        }
68    }
69}
70
71#[derive(
72    Default,
73    Debug,
74    Clone,
75    Eq,
76    PartialEq,
77    RlpEncodable,
78    RlpDecodable,
79    Serialize,
80    Deserialize,
81)]
82pub struct Cip2930Transaction {
83    pub nonce: U256,
84    pub gas_price: U256,
85    pub gas: U256,
86    pub action: Action,
87    pub value: U256,
88    pub storage_limit: u64,
89    pub epoch_height: u64,
90    pub chain_id: u32,
91    pub data: Bytes,
92    pub access_list: Vec<AccessListItem>,
93}
94
95#[derive(
96    Default,
97    Debug,
98    Clone,
99    Eq,
100    PartialEq,
101    RlpEncodable,
102    RlpDecodable,
103    Serialize,
104    Deserialize,
105)]
106pub struct Cip1559Transaction {
107    pub nonce: U256,
108    pub max_priority_fee_per_gas: U256,
109    pub max_fee_per_gas: U256,
110    pub gas: U256,
111    pub action: Action,
112    pub value: U256,
113    pub storage_limit: u64,
114    pub epoch_height: u64,
115    pub chain_id: u32,
116    pub data: Bytes,
117    pub access_list: Vec<AccessListItem>,
118}
119
120#[derive(
121    Default,
122    Debug,
123    Clone,
124    Eq,
125    PartialEq,
126    RlpEncodable,
127    RlpDecodable,
128    Serialize,
129    Deserialize,
130)]
131pub struct Cip7702Transaction {
132    pub nonce: U256,
133    pub max_priority_fee_per_gas: U256,
134    pub max_fee_per_gas: U256,
135    pub gas: U256,
136    pub destination: Address,
137    pub value: U256,
138    pub storage_limit: u64,
139    pub epoch_height: u64,
140    pub chain_id: u32,
141    pub data: Bytes,
142    pub access_list: Vec<AccessListItem>,
143    pub authorization_list: Vec<AuthorizationListItem>,
144}
145
146macro_rules! access_common_ref {
147    ($field:ident, $ty:ty) => {
148        pub fn $field(&self) -> &$ty {
149            match self {
150                TypedNativeTransaction::Cip155(tx) => &tx.$field,
151                TypedNativeTransaction::Cip2930(tx) => &tx.$field,
152                TypedNativeTransaction::Cip1559(tx) => &tx.$field,
153            }
154        }
155    };
156}
157
158impl TypedNativeTransaction {
159    access_common_ref!(gas, U256);
160
161    access_common_ref!(data, Bytes);
162
163    access_common_ref!(nonce, U256);
164
165    access_common_ref!(value, U256);
166
167    access_common_ref!(chain_id, u32);
168
169    access_common_ref!(epoch_height, u64);
170
171    access_common_ref!(storage_limit, u64);
172
173    pub fn action(&self) -> Action {
174        match self {
175            TypedNativeTransaction::Cip155(tx) => tx.action,
176            TypedNativeTransaction::Cip2930(tx) => tx.action,
177            TypedNativeTransaction::Cip1559(tx) => tx.action,
178        }
179    }
180
181    pub fn gas_price(&self) -> &U256 {
182        match self {
183            Cip155(tx) => &tx.gas_price,
184            Cip2930(tx) => &tx.gas_price,
185            Cip1559(tx) => &tx.max_fee_per_gas,
186        }
187    }
188
189    pub fn max_priority_gas_price(&self) -> &U256 {
190        match self {
191            Cip155(tx) => &tx.gas_price,
192            Cip2930(tx) => &tx.gas_price,
193            Cip1559(tx) => &tx.max_priority_fee_per_gas,
194        }
195    }
196
197    pub fn nonce_mut(&mut self) -> &mut U256 {
198        match self {
199            Cip155(tx) => &mut tx.nonce,
200            Cip2930(tx) => &mut tx.nonce,
201            Cip1559(tx) => &mut tx.nonce,
202        }
203    }
204
205    pub fn data_mut(&mut self) -> &mut Vec<u8> {
206        match self {
207            Cip155(tx) => &mut tx.data,
208            Cip2930(tx) => &mut tx.data,
209            Cip1559(tx) => &mut tx.data,
210        }
211    }
212
213    pub fn access_list(&self) -> Option<&AccessList> {
214        match self {
215            Cip155(_tx) => None,
216            Cip2930(tx) => Some(&tx.access_list),
217            Cip1559(tx) => Some(&tx.access_list),
218        }
219    }
220}
221
222#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
223pub enum TypedNativeTransaction {
224    Cip155(NativeTransaction),
225    Cip2930(Cip2930Transaction),
226    Cip1559(Cip1559Transaction),
227}
228
229impl TypedNativeTransaction {
230    pub fn fake_sign_rpc(self, from: AddressWithSpace) -> SignedTransaction {
231        SignedTransaction {
232            transaction: TransactionWithSignature {
233                transaction: TransactionWithSignatureSerializePart {
234                    unsigned: Transaction::Native(self),
235                    r: U256::one(),
236                    s: U256::one(),
237                    v: 0,
238                },
239                hash: H256::zero(),
240                rlp_size: None,
241            }
242            .compute_hash(),
243            sender: from.address,
244            public: None,
245        }
246    }
247}
248
249use TypedNativeTransaction::*;