primitives/transaction/
mod.rs

1// Copyright 2019 Conflux Foundation. All rights reserved.
2// Conflux is free software and distributed under GNU General Public License.
3// See http://www.gnu.org/licenses/
4
5// TODO(7702): refactor this file
6
7mod authorization;
8pub mod eth_transaction;
9pub mod native_transaction;
10
11pub use authorization::{
12    extract_7702_payload, AuthorizationList, AuthorizationListItem, AUTH_MAGIC,
13    CODE_PREFIX_7702,
14};
15pub use eth_transaction::{
16    Eip1559Transaction, Eip155Transaction, Eip2930Transaction,
17    Eip7702Transaction, EthereumTransaction,
18};
19pub use native_transaction::{
20    Cip1559Transaction, Cip2930Transaction, NativeTransaction,
21    TypedNativeTransaction,
22};
23use rlp_derive::{RlpDecodable, RlpEncodable};
24
25use crate::{
26    bytes::Bytes,
27    hash::keccak,
28    keylib::{
29        self, public_to_address, recover, verify_public, Public, Secret,
30        Signature,
31    },
32};
33use cfx_types::{
34    cal_contract_address_with_space, Address, AddressSpaceUtil,
35    AddressWithSpace, BigEndianHash, CreateContractAddressType, Space, H160,
36    H256, U256,
37};
38use eth_transaction::eip155_signature;
39use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
40use rlp::{self, Decodable, DecoderError, Encodable, Rlp, RlpStream};
41use serde::{Deserialize, Serialize};
42use std::{
43    error, fmt,
44    ops::{Deref, DerefMut},
45};
46use unexpected::OutOfBounds;
47
48/// Fake address for unsigned transactions.
49pub const UNSIGNED_SENDER: Address = H160([0xff; 20]);
50
51pub const TYPED_NATIVE_TX_PREFIX: &[u8; 3] = b"cfx";
52pub const TYPED_NATIVE_TX_PREFIX_BYTE: u8 = TYPED_NATIVE_TX_PREFIX[0];
53pub const LEGACY_TX_TYPE: u8 = 0x00;
54pub const EIP2930_TYPE: u8 = 0x01;
55pub const EIP1559_TYPE: u8 = 0x02;
56pub const EIP7702_TYPE: u8 = 0x04;
57pub const CIP2930_TYPE: u8 = 0x01;
58pub const CIP1559_TYPE: u8 = 0x02;
59
60/// Shorter id for transactions in compact blocks
61// TODO should be u48
62pub type TxShortId = u64;
63
64pub type TxPropagateId = u32;
65
66// FIXME: Most errors here are bounded for TransactionPool and intended for rpc,
67// FIXME: however these are unused, they are not errors for transaction itself.
68// FIXME: Transaction verification and consensus related error can be separated.
69#[derive(Debug, PartialEq, Clone, Eq)]
70/// Errors concerning transaction processing.
71pub enum TransactionError {
72    /// Transaction is already imported to the queue
73    AlreadyImported,
74    /// Chain id in the transaction doesn't match the chain id of the network.
75    ChainIdMismatch {
76        expected: u32,
77        got: u32,
78        space: Space,
79    },
80    /// Epoch height out of bound.
81    EpochHeightOutOfBound {
82        block_height: u64,
83        set: u64,
84        transaction_epoch_bound: u64,
85    },
86    /// The gas paid for transaction is lower than base gas.
87    NotEnoughBaseGas {
88        /// Absolute minimum gas required.
89        required: U256,
90        /// Gas provided.
91        got: U256,
92    },
93    /// Transaction is not valid anymore (state already has higher nonce)
94    Stale,
95    /// Transaction has too low fee
96    /// (there is already a transaction with the same sender-nonce but higher
97    /// gas price)
98    TooCheapToReplace,
99    /// Transaction was not imported to the queue because limit has been
100    /// reached.
101    LimitReached,
102    /// Transaction's gas price is below threshold.
103    InsufficientGasPrice {
104        /// Minimal expected gas price
105        minimal: U256,
106        /// Transaction gas price
107        got: U256,
108    },
109    /// Transaction's gas is below currently set minimal gas requirement.
110    InsufficientGas {
111        /// Minimal expected gas
112        minimal: U256,
113        /// Transaction gas
114        got: U256,
115    },
116    /// Sender doesn't have enough funds to pay for this transaction
117    InsufficientBalance {
118        /// Senders balance
119        balance: U256,
120        /// Transaction cost
121        cost: U256,
122    },
123    /// Transactions gas is higher then current gas limit
124    GasLimitExceeded {
125        /// Current gas limit
126        limit: U256,
127        /// Declared transaction gas
128        got: U256,
129    },
130    /// Transaction's gas limit (aka gas) is invalid.
131    InvalidGasLimit(OutOfBounds<U256>),
132    /// Signature error
133    InvalidSignature(String),
134    /// Transaction too big
135    TooBig,
136    /// Invalid RLP encoding
137    InvalidRlp(String),
138    ZeroGasPrice,
139    /// Transaction types have not been activated
140    FutureTransactionType {
141        tx_type: u8,
142        enable_height: u64,
143        current_height: u64,
144    },
145    /// Create transaction with too large init code size,
146    CreateInitCodeSizeLimit,
147    /// Receiver with invalid type bit.
148    InvalidReceiver,
149    /// Transaction nonce exceeds local limit.
150    TooLargeNonce,
151    /// Empty authorization list (EIP-7702)
152    EmptyAuthorizationList,
153    /// Max priority fee greater than max fee (EIP-1559)
154    PriortyGreaterThanMaxFee,
155}
156
157impl From<keylib::Error> for TransactionError {
158    fn from(err: keylib::Error) -> Self {
159        TransactionError::InvalidSignature(format!("{}", err))
160    }
161}
162
163impl From<rlp::DecoderError> for TransactionError {
164    fn from(err: rlp::DecoderError) -> Self {
165        TransactionError::InvalidRlp(format!("{}", err))
166    }
167}
168
169impl fmt::Display for TransactionError {
170    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
171        use self::TransactionError::*;
172        let msg = match *self {
173            AlreadyImported => "Already imported".into(),
174            ChainIdMismatch { expected, got, space } => {
175                format!("Chain id mismatch, expected {}, got {}, space {:?}", expected, got, space)
176            }
177            EpochHeightOutOfBound {
178                block_height,
179                set,
180                transaction_epoch_bound,
181            } => format!(
182                "EpochHeight out of bound:\
183                 block_height {}, transaction epoch_height {}, transaction_epoch_bound {}",
184                block_height, set, transaction_epoch_bound
185            ),
186            NotEnoughBaseGas { got, required } => format!(
187                "Transaction gas {} less than intrinsic gas {}",
188                got, required
189            ),
190            Stale => "No longer valid".into(),
191            TooCheapToReplace => "Gas price too low to replace".into(),
192            LimitReached => "Transaction limit reached".into(),
193            InsufficientGasPrice { minimal, got } => format!(
194                "Insufficient gas price. Min={}, Given={}",
195                minimal, got
196            ),
197            InsufficientGas { minimal, got } => {
198                format!("Insufficient gas. Min={}, Given={}", minimal, got)
199            }
200            InsufficientBalance { balance, cost } => format!(
201                "Insufficient balance for transaction. Balance={}, Cost={}",
202                balance, cost
203            ),
204            GasLimitExceeded { limit, got } => {
205                format!("Gas limit exceeded. Limit={}, Given={}", limit, got)
206            }
207            InvalidGasLimit(ref err) => format!("Invalid gas limit. {}", err),
208            InvalidSignature(ref err) => {
209                format!("Transaction has invalid signature: {}.", err)
210            }
211            TooBig => "Transaction too big".into(),
212            InvalidRlp(ref err) => {
213                format!("Transaction has invalid RLP structure: {}.", err)
214            }
215            ZeroGasPrice => "Zero gas price is not allowed".into(),
216            FutureTransactionType {tx_type, current_height, enable_height} => format!("Transaction type {tx_type} is not enabled, current height {current_height}, enable height {enable_height}"),
217            InvalidReceiver => "Sending transaction to invalid address. The first four bits of address must be 0x0, 0x1, or 0x8.".into(),
218            TooLargeNonce => "Transaction nonce is too large.".into(),
219            CreateInitCodeSizeLimit => "Transaction initcode is too large.".into(),
220            EmptyAuthorizationList => "Empty authorization list".into(),
221            PriortyGreaterThanMaxFee => "Max priority fee greater than max fee".into(),
222        };
223
224        f.write_fmt(format_args!("Transaction error ({})", msg))
225    }
226}
227
228impl error::Error for TransactionError {
229    fn description(&self) -> &str { "Transaction error" }
230}
231
232#[derive(
233    Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default,
234)]
235pub enum Action {
236    /// Create creates new contract.
237    #[default]
238    Create,
239    /// Calls contract at given address.
240    /// In the case of a transfer, this is the receiver's address.'
241    Call(Address),
242}
243
244impl Decodable for Action {
245    fn decode(rlp: &Rlp) -> Result<Self, DecoderError> {
246        if rlp.is_empty() {
247            Ok(Action::Create)
248        } else {
249            Ok(Action::Call(rlp.as_val()?))
250        }
251    }
252}
253
254impl Encodable for Action {
255    fn rlp_append(&self, stream: &mut RlpStream) {
256        match *self {
257            Action::Create => stream.append_internal(&""),
258            Action::Call(ref address) => stream.append_internal(address),
259        };
260    }
261}
262
263#[derive(
264    Debug,
265    Clone,
266    PartialEq,
267    Eq,
268    Serialize,
269    Deserialize,
270    RlpEncodable,
271    RlpDecodable,
272)]
273#[serde(rename_all = "camelCase")]
274pub struct AccessListItem {
275    pub address: Address,
276    pub storage_keys: Vec<H256>,
277}
278
279pub type AccessList = Vec<AccessListItem>;
280
281#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
282pub enum Transaction {
283    Native(TypedNativeTransaction),
284    Ethereum(EthereumTransaction),
285}
286
287impl Default for Transaction {
288    fn default() -> Self {
289        Transaction::Native(TypedNativeTransaction::Cip155(Default::default()))
290    }
291}
292
293impl From<NativeTransaction> for Transaction {
294    fn from(tx: NativeTransaction) -> Self {
295        Self::Native(TypedNativeTransaction::Cip155(tx))
296    }
297}
298
299impl From<Eip155Transaction> for Transaction {
300    fn from(tx: Eip155Transaction) -> Self {
301        Self::Ethereum(EthereumTransaction::Eip155(tx))
302    }
303}
304
305macro_rules! access_common_ref {
306    ($field:ident, $ty:ty) => {
307        pub fn $field(&self) -> &$ty {
308            match self {
309                Transaction::Native(tx) => tx.$field(),
310                Transaction::Ethereum(tx) => tx.$field(),
311            }
312        }
313    };
314}
315
316macro_rules! access_common {
317    ($field:ident, $ty:ident) => {
318        pub fn $field(&self) -> $ty {
319            match self {
320                Transaction::Native(tx) => tx.$field(),
321                Transaction::Ethereum(tx) => tx.$field(),
322            }
323        }
324    };
325}
326
327impl Transaction {
328    access_common_ref!(gas, U256);
329
330    access_common_ref!(gas_price, U256);
331
332    access_common_ref!(max_priority_gas_price, U256);
333
334    access_common_ref!(data, Bytes);
335
336    access_common_ref!(nonce, U256);
337
338    access_common!(action, Action);
339
340    access_common_ref!(value, U256);
341
342    pub fn chain_id(&self) -> Option<u32> {
343        match self {
344            Transaction::Native(tx) => Some(*tx.chain_id()),
345            Transaction::Ethereum(tx) => tx.chain_id(),
346        }
347    }
348
349    pub fn storage_limit(&self) -> Option<u64> {
350        match self {
351            Transaction::Native(tx) => Some(*tx.storage_limit()),
352            Transaction::Ethereum(_tx) => None,
353        }
354    }
355
356    pub fn nonce_mut(&mut self) -> &mut U256 {
357        match self {
358            Transaction::Native(tx) => tx.nonce_mut(),
359            Transaction::Ethereum(tx) => tx.nonce_mut(),
360        }
361    }
362
363    pub fn data_mut(&mut self) -> &mut Vec<u8> {
364        match self {
365            Transaction::Native(tx) => tx.data_mut(),
366            Transaction::Ethereum(tx) => tx.data_mut(),
367        }
368    }
369
370    pub fn type_id(&self) -> u8 {
371        match self {
372            Transaction::Native(TypedNativeTransaction::Cip155(_))
373            | Transaction::Ethereum(EthereumTransaction::Eip155(_)) => 0,
374
375            Transaction::Native(TypedNativeTransaction::Cip2930(_))
376            | Transaction::Ethereum(EthereumTransaction::Eip2930(_)) => 1,
377
378            Transaction::Native(TypedNativeTransaction::Cip1559(_))
379            | Transaction::Ethereum(EthereumTransaction::Eip1559(_)) => 2,
380
381            Transaction::Ethereum(EthereumTransaction::Eip7702(_)) => 4,
382        }
383    }
384
385    pub fn is_legacy(&self) -> bool {
386        matches!(
387            self,
388            Transaction::Native(TypedNativeTransaction::Cip155(_))
389                | Transaction::Ethereum(EthereumTransaction::Eip155(_))
390        )
391    }
392
393    pub fn is_2718(&self) -> bool { !self.is_legacy() }
394
395    pub fn after_1559(&self) -> bool {
396        use EthereumTransaction::*;
397        use TypedNativeTransaction::*;
398        matches!(
399            self,
400            Transaction::Native(Cip1559(_))
401                | Transaction::Ethereum(Eip1559(_) | Eip7702(_))
402        )
403    }
404
405    pub fn after_7702(&self) -> bool {
406        matches!(self, Transaction::Ethereum(EthereumTransaction::Eip7702(_)))
407    }
408
409    pub fn access_list(&self) -> Option<&AccessList> {
410        match self {
411            Transaction::Native(tx) => tx.access_list(),
412            Transaction::Ethereum(tx) => tx.access_list(),
413        }
414    }
415
416    pub fn authorization_list(&self) -> Option<&AuthorizationList> {
417        match self {
418            Transaction::Native(_tx) => None,
419            Transaction::Ethereum(tx) => tx.authorization_list(),
420        }
421    }
422
423    pub fn authorization_len(&self) -> usize {
424        self.authorization_list().map_or(0, Vec::len)
425    }
426}
427
428impl Transaction {
429    pub fn priority_gas_price(&self, base_price: &U256) -> U256 {
430        std::cmp::min(
431            *self.max_priority_gas_price(),
432            self.gas_price() - base_price,
433        )
434    }
435
436    pub fn effective_gas_price(&self, base_price: &U256) -> U256 {
437        base_price + self.priority_gas_price(base_price)
438    }
439
440    // This function returns the hash value used in calculating the transaction
441    // signature. It is different from transaction hash. The transaction
442    // hash also contains signatures.
443    pub fn hash_for_compute_signature(&self) -> H256 {
444        let mut s = RlpStream::new();
445        let mut type_prefix = vec![];
446        match self {
447            Transaction::Native(TypedNativeTransaction::Cip155(tx)) => {
448                s.append(tx);
449            }
450            Transaction::Native(TypedNativeTransaction::Cip1559(tx)) => {
451                s.append(tx);
452                type_prefix.extend_from_slice(TYPED_NATIVE_TX_PREFIX);
453                type_prefix.push(CIP1559_TYPE);
454            }
455            Transaction::Native(TypedNativeTransaction::Cip2930(tx)) => {
456                s.append(tx);
457                type_prefix.extend_from_slice(TYPED_NATIVE_TX_PREFIX);
458                type_prefix.push(CIP2930_TYPE);
459            }
460            Transaction::Ethereum(EthereumTransaction::Eip155(tx)) => {
461                s.append(tx);
462            }
463            Transaction::Ethereum(EthereumTransaction::Eip1559(tx)) => {
464                s.append(tx);
465                type_prefix.push(EIP1559_TYPE);
466            }
467            Transaction::Ethereum(EthereumTransaction::Eip2930(tx)) => {
468                s.append(tx);
469                type_prefix.push(EIP2930_TYPE);
470            }
471            Transaction::Ethereum(EthereumTransaction::Eip7702(tx)) => {
472                s.append(tx);
473                type_prefix.push(EIP7702_TYPE);
474            }
475        };
476        let encoded = s.as_raw();
477        let mut out = vec![0; type_prefix.len() + encoded.len()];
478        out[0..type_prefix.len()].copy_from_slice(&type_prefix);
479        out[type_prefix.len()..].copy_from_slice(encoded);
480        keccak(&out)
481    }
482
483    pub fn space(&self) -> Space {
484        match self {
485            Transaction::Native(_) => Space::Native,
486            Transaction::Ethereum(_) => Space::Ethereum,
487        }
488    }
489
490    pub fn sign(self, secret: &Secret) -> SignedTransaction {
491        let sig =
492            crate::keylib::sign(secret, &self.hash_for_compute_signature())
493                .expect(
494                    "data is valid and context has signing capabilities; qed",
495                );
496        let tx_with_sig = self.with_signature(sig);
497        let public = tx_with_sig
498            .recover_public()
499            .expect("secret is valid so it's recoverable");
500        SignedTransaction::new(public, tx_with_sig)
501    }
502
503    /// Signs the transaction with signature.
504    pub fn with_signature(self, sig: Signature) -> TransactionWithSignature {
505        TransactionWithSignature {
506            transaction: TransactionWithSignatureSerializePart {
507                unsigned: self,
508                r: U256::from_big_endian(sig.r()),
509                s: U256::from_big_endian(sig.s()),
510                v: sig.v(),
511            },
512            hash: H256::zero(),
513            rlp_size: None,
514        }
515        .compute_hash()
516    }
517}
518
519impl MallocSizeOf for Transaction {
520    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
521        self.data().size_of(ops)
522    }
523}
524
525/// Signed transaction information without verified signature.
526#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
527pub struct TransactionWithSignatureSerializePart {
528    /// Plain Transaction.
529    pub unsigned: Transaction,
530    /// The V field of the signature; helps describe which half of the curve
531    /// our point falls in.
532    pub v: u8,
533    /// The R field of the signature; helps describe the point on the curve.
534    pub r: U256,
535    /// The S field of the signature; helps describe the point on the curve.
536    pub s: U256,
537}
538
539impl Encodable for TransactionWithSignatureSerializePart {
540    fn rlp_append(&self, s: &mut RlpStream) {
541        match self.unsigned {
542            Transaction::Native(TypedNativeTransaction::Cip155(ref tx)) => {
543                s.begin_list(4);
544                s.append(tx);
545                s.append(&self.v);
546                s.append(&self.r);
547                s.append(&self.s);
548            }
549            Transaction::Ethereum(EthereumTransaction::Eip155(ref tx)) => {
550                let Eip155Transaction {
551                    nonce,
552                    gas_price,
553                    gas,
554                    action,
555                    value,
556                    data,
557                    chain_id,
558                } = tx;
559                let legacy_v = eip155_signature::add_chain_replay_protection(
560                    self.v,
561                    chain_id.map(|x| x as u64),
562                );
563                s.begin_list(9);
564                s.append(nonce);
565                s.append(gas_price);
566                s.append(gas);
567                s.append(action);
568                s.append(value);
569                s.append(data);
570                s.append(&legacy_v);
571                s.append(&self.r);
572                s.append(&self.s);
573            }
574            Transaction::Ethereum(EthereumTransaction::Eip2930(ref tx)) => {
575                s.append_raw(&[EIP2930_TYPE], 0);
576                s.begin_list(11);
577                s.append(&tx.chain_id);
578                s.append(&tx.nonce);
579                s.append(&tx.gas_price);
580                s.append(&tx.gas);
581                s.append(&tx.action);
582                s.append(&tx.value);
583                s.append(&tx.data);
584                s.append_list(&tx.access_list);
585                s.append(&self.v);
586                s.append(&self.r);
587                s.append(&self.s);
588            }
589            Transaction::Ethereum(EthereumTransaction::Eip1559(ref tx)) => {
590                s.append_raw(&[EIP1559_TYPE], 0);
591                s.begin_list(12);
592                s.append(&tx.chain_id);
593                s.append(&tx.nonce);
594                s.append(&tx.max_priority_fee_per_gas);
595                s.append(&tx.max_fee_per_gas);
596                s.append(&tx.gas);
597                s.append(&tx.action);
598                s.append(&tx.value);
599                s.append(&tx.data);
600                s.append_list(&tx.access_list);
601                s.append(&self.v);
602                s.append(&self.r);
603                s.append(&self.s);
604            }
605            Transaction::Ethereum(EthereumTransaction::Eip7702(ref tx)) => {
606                s.append_raw(&[EIP7702_TYPE], 0);
607                s.begin_list(13);
608                s.append(&tx.chain_id);
609                s.append(&tx.nonce);
610                s.append(&tx.max_priority_fee_per_gas);
611                s.append(&tx.max_fee_per_gas);
612                s.append(&tx.gas);
613                s.append(&tx.destination);
614                s.append(&tx.value);
615                s.append(&tx.data);
616                s.append_list(&tx.access_list);
617                s.append_list(&tx.authorization_list);
618                s.append(&self.v);
619                s.append(&self.r);
620                s.append(&self.s);
621            }
622            Transaction::Native(TypedNativeTransaction::Cip2930(ref tx)) => {
623                s.append_raw(TYPED_NATIVE_TX_PREFIX, 0);
624                s.append_raw(&[CIP2930_TYPE], 0);
625                s.begin_list(4);
626                s.append(tx);
627                s.append(&self.v);
628                s.append(&self.r);
629                s.append(&self.s);
630            }
631            Transaction::Native(TypedNativeTransaction::Cip1559(ref tx)) => {
632                s.append_raw(TYPED_NATIVE_TX_PREFIX, 0);
633                s.append_raw(&[CIP1559_TYPE], 0);
634                s.begin_list(4);
635                s.append(tx);
636                s.append(&self.v);
637                s.append(&self.r);
638                s.append(&self.s);
639            } /* Transaction::Native(TypedNativeTransaction::Cip7702(ref tx))
640               * => {     s.append_raw(TYPED_NATIVE_TX_PREFIX,
641               * 0);     s.append_raw(&[CIP7702_TYPE], 0);
642               *     s.begin_list(4);
643               *     s.append(tx);
644               *     s.append(&self.v);
645               *     s.append(&self.r);
646               *     s.append(&self.s);
647               * } */
648        }
649    }
650}
651
652// TODO(7702): refactor this implementation.
653impl Decodable for TransactionWithSignatureSerializePart {
654    fn decode(rlp: &Rlp) -> Result<Self, DecoderError> {
655        if rlp.as_raw().is_empty() {
656            return Err(DecoderError::RlpInvalidLength);
657        }
658        if rlp.is_list() {
659            match rlp.item_count()? {
660                4 => {
661                    let unsigned: NativeTransaction = rlp.val_at(0)?;
662                    let v: u8 = rlp.val_at(1)?;
663                    let r: U256 = rlp.val_at(2)?;
664                    let s: U256 = rlp.val_at(3)?;
665                    Ok(TransactionWithSignatureSerializePart {
666                        unsigned: Transaction::Native(
667                            TypedNativeTransaction::Cip155(unsigned),
668                        ),
669                        v,
670                        r,
671                        s,
672                    })
673                }
674                9 => {
675                    let nonce: U256 = rlp.val_at(0)?;
676                    let gas_price: U256 = rlp.val_at(1)?;
677                    let gas: U256 = rlp.val_at(2)?;
678                    let action: Action = rlp.val_at(3)?;
679                    let value: U256 = rlp.val_at(4)?;
680                    let data: Vec<u8> = rlp.val_at(5)?;
681                    let legacy_v: u64 = rlp.val_at(6)?;
682                    let r: U256 = rlp.val_at(7)?;
683                    let s: U256 = rlp.val_at(8)?;
684
685                    let v = eip155_signature::extract_standard_v(legacy_v);
686                    let chain_id =
687                        match eip155_signature::extract_chain_id_from_legacy_v(
688                            legacy_v,
689                        ) {
690                            Some(chain_id) if chain_id > (u32::MAX as u64) => {
691                                return Err(DecoderError::Custom(
692                                    "Does not support chain_id >= 2^32",
693                                ));
694                            }
695                            chain_id => chain_id.map(|x| x as u32),
696                        };
697
698                    Ok(TransactionWithSignatureSerializePart {
699                        unsigned: Transaction::Ethereum(
700                            EthereumTransaction::Eip155(Eip155Transaction {
701                                nonce,
702                                gas_price,
703                                gas,
704                                action,
705                                value,
706                                chain_id,
707                                data,
708                            }),
709                        ),
710                        v,
711                        r,
712                        s,
713                    })
714                }
715                _ => Err(DecoderError::RlpInvalidLength),
716            }
717        } else {
718            match rlp.as_raw()[0] {
719                TYPED_NATIVE_TX_PREFIX_BYTE => {
720                    if rlp.as_raw().len() <= 4
721                        || rlp.as_raw()[0..3] != *TYPED_NATIVE_TX_PREFIX
722                    {
723                        return Err(DecoderError::RlpInvalidLength);
724                    }
725                    match rlp.as_raw()[3] {
726                        CIP2930_TYPE => {
727                            let rlp = Rlp::new(&rlp.as_raw()[4..]);
728                            if rlp.item_count()? != 4 {
729                                return Err(DecoderError::RlpIncorrectListLen);
730                            }
731
732                            let tx = rlp.val_at(0)?;
733                            let v = rlp.val_at(1)?;
734                            let r = rlp.val_at(2)?;
735                            let s = rlp.val_at(3)?;
736                            Ok(TransactionWithSignatureSerializePart {
737                                unsigned: Transaction::Native(
738                                    TypedNativeTransaction::Cip2930(tx),
739                                ),
740                                v,
741                                r,
742                                s,
743                            })
744                        }
745                        CIP1559_TYPE => {
746                            let rlp = Rlp::new(&rlp.as_raw()[4..]);
747                            if rlp.item_count()? != 4 {
748                                return Err(DecoderError::RlpIncorrectListLen);
749                            }
750
751                            let tx = rlp.val_at(0)?;
752                            let v = rlp.val_at(1)?;
753                            let r = rlp.val_at(2)?;
754                            let s = rlp.val_at(3)?;
755                            Ok(TransactionWithSignatureSerializePart {
756                                unsigned: Transaction::Native(
757                                    TypedNativeTransaction::Cip1559(tx),
758                                ),
759                                v,
760                                r,
761                                s,
762                            })
763                        }
764                        _ => Err(DecoderError::RlpInvalidLength),
765                    }
766                }
767                EIP2930_TYPE => {
768                    let rlp = Rlp::new(&rlp.as_raw()[1..]);
769                    if rlp.item_count()? != 11 {
770                        return Err(DecoderError::RlpIncorrectListLen);
771                    }
772
773                    let tx = Eip2930Transaction {
774                        chain_id: rlp.val_at(0)?,
775                        nonce: rlp.val_at(1)?,
776                        gas_price: rlp.val_at(2)?,
777                        gas: rlp.val_at(3)?,
778                        action: rlp.val_at(4)?,
779                        value: rlp.val_at(5)?,
780                        data: rlp.val_at(6)?,
781                        access_list: rlp.list_at(7)?,
782                    };
783                    let v = rlp.val_at(8)?;
784                    let r = rlp.val_at(9)?;
785                    let s = rlp.val_at(10)?;
786                    Ok(TransactionWithSignatureSerializePart {
787                        unsigned: Transaction::Ethereum(
788                            EthereumTransaction::Eip2930(tx),
789                        ),
790                        v,
791                        r,
792                        s,
793                    })
794                }
795                EIP1559_TYPE => {
796                    let rlp = Rlp::new(&rlp.as_raw()[1..]);
797                    if rlp.item_count()? != 12 {
798                        return Err(DecoderError::RlpIncorrectListLen);
799                    }
800
801                    let tx = Eip1559Transaction {
802                        chain_id: rlp.val_at(0)?,
803                        nonce: rlp.val_at(1)?,
804                        max_priority_fee_per_gas: rlp.val_at(2)?,
805                        max_fee_per_gas: rlp.val_at(3)?,
806                        gas: rlp.val_at(4)?,
807                        action: rlp.val_at(5)?,
808                        value: rlp.val_at(6)?,
809                        data: rlp.val_at(7)?,
810                        access_list: rlp.list_at(8)?,
811                    };
812                    let v = rlp.val_at(9)?;
813                    let r = rlp.val_at(10)?;
814                    let s = rlp.val_at(11)?;
815                    Ok(TransactionWithSignatureSerializePart {
816                        unsigned: Transaction::Ethereum(
817                            EthereumTransaction::Eip1559(tx),
818                        ),
819                        v,
820                        r,
821                        s,
822                    })
823                }
824                EIP7702_TYPE => {
825                    let rlp = Rlp::new(&rlp.as_raw()[1..]);
826                    if rlp.item_count()? != 13 {
827                        return Err(DecoderError::RlpIncorrectListLen);
828                    }
829
830                    let tx = Eip7702Transaction {
831                        chain_id: rlp.val_at(0)?,
832                        nonce: rlp.val_at(1)?,
833                        max_priority_fee_per_gas: rlp.val_at(2)?,
834                        max_fee_per_gas: rlp.val_at(3)?,
835                        gas: rlp.val_at(4)?,
836                        destination: rlp.val_at(5)?,
837                        value: rlp.val_at(6)?,
838                        data: rlp.val_at(7)?,
839                        access_list: rlp.list_at(8)?,
840                        authorization_list: rlp.list_at(9)?,
841                    };
842                    let v = rlp.val_at(10)?;
843                    let r = rlp.val_at(11)?;
844                    let s = rlp.val_at(12)?;
845                    Ok(TransactionWithSignatureSerializePart {
846                        unsigned: Transaction::Ethereum(
847                            EthereumTransaction::Eip7702(tx),
848                        ),
849                        v,
850                        r,
851                        s,
852                    })
853                }
854                _ => Err(DecoderError::RlpInvalidLength),
855            }
856        }
857    }
858}
859
860impl Deref for TransactionWithSignatureSerializePart {
861    type Target = Transaction;
862
863    fn deref(&self) -> &Self::Target { &self.unsigned }
864}
865
866impl DerefMut for TransactionWithSignatureSerializePart {
867    fn deref_mut(&mut self) -> &mut Self::Target { &mut self.unsigned }
868}
869
870/// Signed transaction information without verified signature.
871#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
872pub struct TransactionWithSignature {
873    /// Serialize part.
874    pub transaction: TransactionWithSignatureSerializePart,
875    /// Hash of the transaction
876    #[serde(skip)]
877    pub hash: H256,
878    /// The transaction size when serialized in rlp
879    #[serde(skip)]
880    pub rlp_size: Option<usize>,
881}
882
883impl Deref for TransactionWithSignature {
884    type Target = TransactionWithSignatureSerializePart;
885
886    fn deref(&self) -> &Self::Target { &self.transaction }
887}
888
889impl DerefMut for TransactionWithSignature {
890    fn deref_mut(&mut self) -> &mut Self::Target { &mut self.transaction }
891}
892
893impl Decodable for TransactionWithSignature {
894    fn decode(tx_rlp: &Rlp) -> Result<Self, DecoderError> {
895        let rlp_size = Some(tx_rlp.as_raw().len());
896        // The item count of TransactionWithSignatureSerializePart is checked in
897        // its decoding.
898        let hash;
899        let transaction;
900        if tx_rlp.is_list() {
901            hash = keccak(tx_rlp.as_raw());
902            // Vanilla tx encoding.
903            transaction = tx_rlp.as_val()?;
904        } else {
905            // Typed tx encoding is wrapped as an RLP string.
906            let b: Vec<u8> = tx_rlp.as_val()?;
907            hash = keccak(&b);
908            transaction = rlp::decode(&b)?;
909        };
910        Ok(TransactionWithSignature {
911            transaction,
912            hash,
913            rlp_size,
914        })
915    }
916}
917
918impl Encodable for TransactionWithSignature {
919    fn rlp_append(&self, s: &mut RlpStream) {
920        match &self.transaction.unsigned {
921            Transaction::Native(TypedNativeTransaction::Cip155(_))
922            | Transaction::Ethereum(EthereumTransaction::Eip155(_)) => {
923                s.append_internal(&self.transaction);
924            }
925            _ => {
926                // Typed tx encoding is wrapped as an RLP string.
927                s.append_internal(&rlp::encode(&self.transaction));
928            }
929        }
930    }
931}
932
933impl TransactionWithSignature {
934    pub fn new_unsigned(tx: Transaction) -> Self {
935        TransactionWithSignature {
936            transaction: TransactionWithSignatureSerializePart {
937                unsigned: tx,
938                s: 0.into(),
939                r: 0.into(),
940                v: 0,
941            },
942            hash: Default::default(),
943            rlp_size: None,
944        }
945    }
946
947    /// Used to compute hash of created transactions
948    fn compute_hash(mut self) -> TransactionWithSignature {
949        let hash = keccak(&*self.transaction.rlp_bytes());
950        self.hash = hash;
951        self
952    }
953
954    /// Checks whether signature is empty.
955    pub fn is_unsigned(&self) -> bool { self.r.is_zero() && self.s.is_zero() }
956
957    /// Construct a signature object from the sig.
958    pub fn signature(&self) -> Signature {
959        let r: H256 = BigEndianHash::from_uint(&self.r);
960        let s: H256 = BigEndianHash::from_uint(&self.s);
961        Signature::from_rsv(&r, &s, self.v)
962    }
963
964    /// Checks whether the signature has a low 's' value.
965    pub fn check_low_s(&self) -> Result<(), keylib::Error> {
966        if !self.signature().is_low_s() {
967            Err(keylib::Error::InvalidSignature)
968        } else {
969            Ok(())
970        }
971    }
972
973    pub fn check_y_parity(&self) -> Result<(), keylib::Error> {
974        if self.is_2718() && self.v > 1 {
975            // In Typed transactions (EIP-2718), v means y_parity, which must be
976            // 0 or 1
977            Err(keylib::Error::InvalidYParity)
978        } else {
979            Ok(())
980        }
981    }
982
983    pub fn hash(&self) -> H256 { self.hash }
984
985    /// Recovers the public key of the sender.
986    pub fn recover_public(&self) -> Result<Public, keylib::Error> {
987        recover(
988            &self.signature(),
989            &self.unsigned.hash_for_compute_signature(),
990        )
991    }
992
993    pub fn rlp_size(&self) -> usize {
994        self.rlp_size.unwrap_or_else(|| self.rlp_bytes().len())
995    }
996
997    pub fn from_raw(raw: &[u8]) -> Result<Self, DecoderError> {
998        Ok(TransactionWithSignature {
999            transaction: Rlp::new(raw).as_val()?,
1000            hash: keccak(raw),
1001            rlp_size: Some(raw.len()),
1002        })
1003    }
1004}
1005
1006impl MallocSizeOf for TransactionWithSignature {
1007    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1008        self.unsigned.size_of(ops)
1009    }
1010}
1011
1012/// A signed transaction with successfully recovered `sender`.
1013#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1014pub struct SignedTransaction {
1015    pub transaction: TransactionWithSignature,
1016    pub sender: Address,
1017    pub public: Option<Public>,
1018}
1019
1020// The default encoder for local storage.
1021impl Encodable for SignedTransaction {
1022    fn rlp_append(&self, s: &mut RlpStream) {
1023        s.begin_list(3);
1024        s.append(&self.transaction);
1025        s.append(&self.sender);
1026        s.append(&self.public);
1027    }
1028}
1029
1030impl Decodable for SignedTransaction {
1031    fn decode(rlp: &Rlp) -> Result<Self, DecoderError> {
1032        Ok(SignedTransaction {
1033            transaction: rlp.val_at(0)?,
1034            sender: rlp.val_at(1)?,
1035            public: rlp.val_at(2)?,
1036        })
1037    }
1038}
1039
1040impl Deref for SignedTransaction {
1041    type Target = TransactionWithSignature;
1042
1043    fn deref(&self) -> &Self::Target { &self.transaction }
1044}
1045
1046impl DerefMut for SignedTransaction {
1047    fn deref_mut(&mut self) -> &mut Self::Target { &mut self.transaction }
1048}
1049
1050impl From<SignedTransaction> for TransactionWithSignature {
1051    fn from(tx: SignedTransaction) -> Self { tx.transaction }
1052}
1053
1054impl SignedTransaction {
1055    /// Try to verify transaction and recover sender.
1056    pub fn new(public: Public, transaction: TransactionWithSignature) -> Self {
1057        if transaction.is_unsigned() {
1058            SignedTransaction {
1059                transaction,
1060                sender: UNSIGNED_SENDER,
1061                public: None,
1062            }
1063        } else {
1064            let sender = public_to_address(
1065                &public,
1066                transaction.space() == Space::Native,
1067            );
1068            SignedTransaction {
1069                transaction,
1070                sender,
1071                public: Some(public),
1072            }
1073        }
1074    }
1075
1076    pub fn new_unsigned(transaction: TransactionWithSignature) -> Self {
1077        SignedTransaction {
1078            transaction,
1079            sender: UNSIGNED_SENDER,
1080            public: None,
1081        }
1082    }
1083
1084    pub fn set_public(&mut self, public: Public) {
1085        let type_nibble = self.unsigned.space() == Space::Native;
1086        self.sender = public_to_address(&public, type_nibble);
1087        self.public = Some(public);
1088    }
1089
1090    /// Returns transaction sender.
1091    pub fn sender(&self) -> AddressWithSpace {
1092        self.sender.with_space(self.space())
1093    }
1094
1095    pub fn nonce(&self) -> &U256 { self.transaction.nonce() }
1096
1097    /// Checks if signature is empty.
1098    pub fn is_unsigned(&self) -> bool { self.transaction.is_unsigned() }
1099
1100    pub fn hash(&self) -> H256 { self.transaction.hash() }
1101
1102    pub fn gas(&self) -> &U256 { self.transaction.gas() }
1103
1104    pub fn gas_price(&self) -> &U256 { self.transaction.gas_price() }
1105
1106    pub fn gas_limit(&self) -> &U256 { self.transaction.gas() }
1107
1108    pub fn storage_limit(&self) -> Option<u64> {
1109        self.transaction.storage_limit()
1110    }
1111
1112    pub fn rlp_size(&self) -> usize { self.transaction.rlp_size() }
1113
1114    pub fn public(&self) -> &Option<Public> { &self.public }
1115
1116    pub fn verify_public(&self, skip: bool) -> Result<bool, keylib::Error> {
1117        if self.public.is_none() {
1118            return Ok(false);
1119        }
1120
1121        if !skip {
1122            let public = self.public.unwrap();
1123            Ok(verify_public(
1124                &public,
1125                &self.signature(),
1126                &self.unsigned.hash_for_compute_signature(),
1127            )?)
1128        } else {
1129            Ok(true)
1130        }
1131    }
1132
1133    // Calculates the created contract address if the transaction is a contract
1134    // creation.
1135    pub fn cal_created_address(&self) -> Option<AddressWithSpace> {
1136        if let Action::Create = self.action() {
1137            let from = self.sender();
1138            let nonce = self.nonce();
1139            let space = self.space();
1140            let create_type = match space {
1141                Space::Native => {
1142                    CreateContractAddressType::FromSenderNonceAndCodeHash
1143                }
1144                Space::Ethereum => CreateContractAddressType::FromSenderNonce,
1145            };
1146            let code = self.data().as_slice();
1147            let (created_address, _) = cal_contract_address_with_space(
1148                create_type,
1149                &from,
1150                nonce,
1151                code,
1152            );
1153            Some(created_address)
1154        } else {
1155            None
1156        }
1157    }
1158}
1159
1160impl MallocSizeOf for SignedTransaction {
1161    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1162        self.transaction.size_of(ops)
1163    }
1164}