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(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
233pub enum Action {
234    /// Create creates new contract.
235    Create,
236    /// Calls contract at given address.
237    /// In the case of a transfer, this is the receiver's address.'
238    Call(Address),
239}
240
241impl Default for Action {
242    fn default() -> Action { Action::Create }
243}
244
245impl Decodable for Action {
246    fn decode(rlp: &Rlp) -> Result<Self, DecoderError> {
247        if rlp.is_empty() {
248            Ok(Action::Create)
249        } else {
250            Ok(Action::Call(rlp.as_val()?))
251        }
252    }
253}
254
255impl Encodable for Action {
256    fn rlp_append(&self, stream: &mut RlpStream) {
257        match *self {
258            Action::Create => stream.append_internal(&""),
259            Action::Call(ref address) => stream.append_internal(address),
260        };
261    }
262}
263
264#[derive(
265    Debug,
266    Clone,
267    PartialEq,
268    Eq,
269    Serialize,
270    Deserialize,
271    RlpEncodable,
272    RlpDecodable,
273)]
274#[serde(rename_all = "camelCase")]
275pub struct AccessListItem {
276    pub address: Address,
277    pub storage_keys: Vec<H256>,
278}
279
280pub type AccessList = Vec<AccessListItem>;
281
282#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
283pub enum Transaction {
284    Native(TypedNativeTransaction),
285    Ethereum(EthereumTransaction),
286}
287
288impl Default for Transaction {
289    fn default() -> Self {
290        Transaction::Native(TypedNativeTransaction::Cip155(Default::default()))
291    }
292}
293
294impl From<NativeTransaction> for Transaction {
295    fn from(tx: NativeTransaction) -> Self {
296        Self::Native(TypedNativeTransaction::Cip155(tx))
297    }
298}
299
300impl From<Eip155Transaction> for Transaction {
301    fn from(tx: Eip155Transaction) -> Self {
302        Self::Ethereum(EthereumTransaction::Eip155(tx))
303    }
304}
305
306macro_rules! access_common_ref {
307    ($field:ident, $ty:ty) => {
308        pub fn $field(&self) -> &$ty {
309            match self {
310                Transaction::Native(tx) => tx.$field(),
311                Transaction::Ethereum(tx) => tx.$field(),
312            }
313        }
314    };
315}
316
317macro_rules! access_common {
318    ($field:ident, $ty:ident) => {
319        pub fn $field(&self) -> $ty {
320            match self {
321                Transaction::Native(tx) => tx.$field(),
322                Transaction::Ethereum(tx) => tx.$field(),
323            }
324        }
325    };
326}
327
328impl Transaction {
329    access_common_ref!(gas, U256);
330
331    access_common_ref!(gas_price, U256);
332
333    access_common_ref!(max_priority_gas_price, U256);
334
335    access_common_ref!(data, Bytes);
336
337    access_common_ref!(nonce, U256);
338
339    access_common!(action, Action);
340
341    access_common_ref!(value, U256);
342
343    pub fn chain_id(&self) -> Option<u32> {
344        match self {
345            Transaction::Native(tx) => Some(*tx.chain_id()),
346            Transaction::Ethereum(tx) => tx.chain_id().clone(),
347        }
348    }
349
350    pub fn storage_limit(&self) -> Option<u64> {
351        match self {
352            Transaction::Native(tx) => Some(*tx.storage_limit()),
353            Transaction::Ethereum(_tx) => None,
354        }
355    }
356
357    pub fn nonce_mut(&mut self) -> &mut U256 {
358        match self {
359            Transaction::Native(tx) => tx.nonce_mut(),
360            Transaction::Ethereum(tx) => tx.nonce_mut(),
361        }
362    }
363
364    pub fn data_mut(&mut self) -> &mut Vec<u8> {
365        match self {
366            Transaction::Native(tx) => tx.data_mut(),
367            Transaction::Ethereum(tx) => tx.data_mut(),
368        }
369    }
370
371    pub fn type_id(&self) -> u8 {
372        match self {
373            Transaction::Native(TypedNativeTransaction::Cip155(_))
374            | Transaction::Ethereum(EthereumTransaction::Eip155(_)) => 0,
375
376            Transaction::Native(TypedNativeTransaction::Cip2930(_))
377            | Transaction::Ethereum(EthereumTransaction::Eip2930(_)) => 1,
378
379            Transaction::Native(TypedNativeTransaction::Cip1559(_))
380            | Transaction::Ethereum(EthereumTransaction::Eip1559(_)) => 2,
381
382            Transaction::Ethereum(EthereumTransaction::Eip7702(_)) => 4,
383        }
384    }
385
386    pub fn is_legacy(&self) -> bool {
387        matches!(
388            self,
389            Transaction::Native(TypedNativeTransaction::Cip155(_))
390                | Transaction::Ethereum(EthereumTransaction::Eip155(_))
391        )
392    }
393
394    pub fn is_2718(&self) -> bool { !self.is_legacy() }
395
396    pub fn after_1559(&self) -> bool {
397        use EthereumTransaction::*;
398        use TypedNativeTransaction::*;
399        matches!(
400            self,
401            Transaction::Native(Cip1559(_))
402                | Transaction::Ethereum(Eip1559(_) | Eip7702(_))
403        )
404    }
405
406    pub fn after_7702(&self) -> bool {
407        matches!(self, Transaction::Ethereum(EthereumTransaction::Eip7702(_)))
408    }
409
410    pub fn access_list(&self) -> Option<&AccessList> {
411        match self {
412            Transaction::Native(tx) => tx.access_list(),
413            Transaction::Ethereum(tx) => tx.access_list(),
414        }
415    }
416
417    pub fn authorization_list(&self) -> Option<&AuthorizationList> {
418        match self {
419            Transaction::Native(_tx) => None,
420            Transaction::Ethereum(tx) => tx.authorization_list(),
421        }
422    }
423
424    pub fn authorization_len(&self) -> usize {
425        self.authorization_list().map_or(0, Vec::len)
426    }
427}
428
429impl Transaction {
430    pub fn priority_gas_price(&self, base_price: &U256) -> U256 {
431        std::cmp::min(
432            *self.max_priority_gas_price(),
433            self.gas_price() - base_price,
434        )
435    }
436
437    pub fn effective_gas_price(&self, base_price: &U256) -> U256 {
438        base_price + self.priority_gas_price(base_price)
439    }
440
441    // This function returns the hash value used in calculating the transaction
442    // signature. It is different from transaction hash. The transaction
443    // hash also contains signatures.
444    pub fn hash_for_compute_signature(&self) -> H256 {
445        let mut s = RlpStream::new();
446        let mut type_prefix = vec![];
447        match self {
448            Transaction::Native(TypedNativeTransaction::Cip155(tx)) => {
449                s.append(tx);
450            }
451            Transaction::Native(TypedNativeTransaction::Cip1559(tx)) => {
452                s.append(tx);
453                type_prefix.extend_from_slice(TYPED_NATIVE_TX_PREFIX);
454                type_prefix.push(CIP1559_TYPE);
455            }
456            Transaction::Native(TypedNativeTransaction::Cip2930(tx)) => {
457                s.append(tx);
458                type_prefix.extend_from_slice(TYPED_NATIVE_TX_PREFIX);
459                type_prefix.push(CIP2930_TYPE);
460            }
461            Transaction::Ethereum(EthereumTransaction::Eip155(tx)) => {
462                s.append(tx);
463            }
464            Transaction::Ethereum(EthereumTransaction::Eip1559(tx)) => {
465                s.append(tx);
466                type_prefix.push(EIP1559_TYPE);
467            }
468            Transaction::Ethereum(EthereumTransaction::Eip2930(tx)) => {
469                s.append(tx);
470                type_prefix.push(EIP2930_TYPE);
471            }
472            Transaction::Ethereum(EthereumTransaction::Eip7702(tx)) => {
473                s.append(tx);
474                type_prefix.push(EIP7702_TYPE);
475            }
476        };
477        let encoded = s.as_raw();
478        let mut out = vec![0; type_prefix.len() + encoded.len()];
479        out[0..type_prefix.len()].copy_from_slice(&type_prefix);
480        out[type_prefix.len()..].copy_from_slice(&encoded);
481        keccak(&out)
482    }
483
484    pub fn space(&self) -> Space {
485        match self {
486            Transaction::Native(_) => Space::Native,
487            Transaction::Ethereum(_) => Space::Ethereum,
488        }
489    }
490
491    pub fn sign(self, secret: &Secret) -> SignedTransaction {
492        let sig =
493            crate::keylib::sign(secret, &self.hash_for_compute_signature())
494                .expect(
495                    "data is valid and context has signing capabilities; qed",
496                );
497        let tx_with_sig = self.with_signature(sig);
498        let public = tx_with_sig
499            .recover_public()
500            .expect("secret is valid so it's recoverable");
501        SignedTransaction::new(public, tx_with_sig)
502    }
503
504    /// Signs the transaction with signature.
505    pub fn with_signature(self, sig: Signature) -> TransactionWithSignature {
506        TransactionWithSignature {
507            transaction: TransactionWithSignatureSerializePart {
508                unsigned: self,
509                r: sig.r().into(),
510                s: sig.s().into(),
511                v: sig.v(),
512            },
513            hash: H256::zero(),
514            rlp_size: None,
515        }
516        .compute_hash()
517    }
518}
519
520impl MallocSizeOf for Transaction {
521    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
522        self.data().size_of(ops)
523    }
524}
525
526/// Signed transaction information without verified signature.
527#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
528pub struct TransactionWithSignatureSerializePart {
529    /// Plain Transaction.
530    pub unsigned: Transaction,
531    /// The V field of the signature; helps describe which half of the curve
532    /// our point falls in.
533    pub v: u8,
534    /// The R field of the signature; helps describe the point on the curve.
535    pub r: U256,
536    /// The S field of the signature; helps describe the point on the curve.
537    pub s: U256,
538}
539
540impl Encodable for TransactionWithSignatureSerializePart {
541    fn rlp_append(&self, s: &mut RlpStream) {
542        match self.unsigned {
543            Transaction::Native(TypedNativeTransaction::Cip155(ref tx)) => {
544                s.begin_list(4);
545                s.append(tx);
546                s.append(&self.v);
547                s.append(&self.r);
548                s.append(&self.s);
549            }
550            Transaction::Ethereum(EthereumTransaction::Eip155(ref tx)) => {
551                let Eip155Transaction {
552                    nonce,
553                    gas_price,
554                    gas,
555                    action,
556                    value,
557                    data,
558                    chain_id,
559                } = tx;
560                let legacy_v = eip155_signature::add_chain_replay_protection(
561                    self.v,
562                    chain_id.map(|x| x as u64),
563                );
564                s.begin_list(9);
565                s.append(nonce);
566                s.append(gas_price);
567                s.append(gas);
568                s.append(action);
569                s.append(value);
570                s.append(data);
571                s.append(&legacy_v);
572                s.append(&self.r);
573                s.append(&self.s);
574            }
575            Transaction::Ethereum(EthereumTransaction::Eip2930(ref tx)) => {
576                s.append_raw(&[EIP2930_TYPE], 0);
577                s.begin_list(11);
578                s.append(&tx.chain_id);
579                s.append(&tx.nonce);
580                s.append(&tx.gas_price);
581                s.append(&tx.gas);
582                s.append(&tx.action);
583                s.append(&tx.value);
584                s.append(&tx.data);
585                s.append_list(&tx.access_list);
586                s.append(&self.v);
587                s.append(&self.r);
588                s.append(&self.s);
589            }
590            Transaction::Ethereum(EthereumTransaction::Eip1559(ref tx)) => {
591                s.append_raw(&[EIP1559_TYPE], 0);
592                s.begin_list(12);
593                s.append(&tx.chain_id);
594                s.append(&tx.nonce);
595                s.append(&tx.max_priority_fee_per_gas);
596                s.append(&tx.max_fee_per_gas);
597                s.append(&tx.gas);
598                s.append(&tx.action);
599                s.append(&tx.value);
600                s.append(&tx.data);
601                s.append_list(&tx.access_list);
602                s.append(&self.v);
603                s.append(&self.r);
604                s.append(&self.s);
605            }
606            Transaction::Ethereum(EthereumTransaction::Eip7702(ref tx)) => {
607                s.append_raw(&[EIP7702_TYPE], 0);
608                s.begin_list(13);
609                s.append(&tx.chain_id);
610                s.append(&tx.nonce);
611                s.append(&tx.max_priority_fee_per_gas);
612                s.append(&tx.max_fee_per_gas);
613                s.append(&tx.gas);
614                s.append(&tx.destination);
615                s.append(&tx.value);
616                s.append(&tx.data);
617                s.append_list(&tx.access_list);
618                s.append_list(&tx.authorization_list);
619                s.append(&self.v);
620                s.append(&self.r);
621                s.append(&self.s);
622            }
623            Transaction::Native(TypedNativeTransaction::Cip2930(ref tx)) => {
624                s.append_raw(TYPED_NATIVE_TX_PREFIX, 0);
625                s.append_raw(&[CIP2930_TYPE], 0);
626                s.begin_list(4);
627                s.append(tx);
628                s.append(&self.v);
629                s.append(&self.r);
630                s.append(&self.s);
631            }
632            Transaction::Native(TypedNativeTransaction::Cip1559(ref tx)) => {
633                s.append_raw(TYPED_NATIVE_TX_PREFIX, 0);
634                s.append_raw(&[CIP1559_TYPE], 0);
635                s.begin_list(4);
636                s.append(tx);
637                s.append(&self.v);
638                s.append(&self.r);
639                s.append(&self.s);
640            } /* Transaction::Native(TypedNativeTransaction::Cip7702(ref tx))
641               * => {     s.append_raw(TYPED_NATIVE_TX_PREFIX,
642               * 0);     s.append_raw(&[CIP7702_TYPE], 0);
643               *     s.begin_list(4);
644               *     s.append(tx);
645               *     s.append(&self.v);
646               *     s.append(&self.r);
647               *     s.append(&self.s);
648               * } */
649        }
650    }
651}
652
653// TODO(7702): refactor this implementation.
654impl Decodable for TransactionWithSignatureSerializePart {
655    fn decode(rlp: &Rlp) -> Result<Self, DecoderError> {
656        if rlp.as_raw().len() == 0 {
657            return Err(DecoderError::RlpInvalidLength);
658        }
659        if rlp.is_list() {
660            match rlp.item_count()? {
661                4 => {
662                    let unsigned: NativeTransaction = rlp.val_at(0)?;
663                    let v: u8 = rlp.val_at(1)?;
664                    let r: U256 = rlp.val_at(2)?;
665                    let s: U256 = rlp.val_at(3)?;
666                    Ok(TransactionWithSignatureSerializePart {
667                        unsigned: Transaction::Native(
668                            TypedNativeTransaction::Cip155(unsigned),
669                        ),
670                        v,
671                        r,
672                        s,
673                    })
674                }
675                9 => {
676                    let nonce: U256 = rlp.val_at(0)?;
677                    let gas_price: U256 = rlp.val_at(1)?;
678                    let gas: U256 = rlp.val_at(2)?;
679                    let action: Action = rlp.val_at(3)?;
680                    let value: U256 = rlp.val_at(4)?;
681                    let data: Vec<u8> = rlp.val_at(5)?;
682                    let legacy_v: u64 = rlp.val_at(6)?;
683                    let r: U256 = rlp.val_at(7)?;
684                    let s: U256 = rlp.val_at(8)?;
685
686                    let v = eip155_signature::extract_standard_v(legacy_v);
687                    let chain_id =
688                        match eip155_signature::extract_chain_id_from_legacy_v(
689                            legacy_v,
690                        ) {
691                            Some(chain_id) if chain_id > (u32::MAX as u64) => {
692                                return Err(DecoderError::Custom(
693                                    "Does not support chain_id >= 2^32",
694                                ));
695                            }
696                            chain_id => chain_id.map(|x| x as u32),
697                        };
698
699                    Ok(TransactionWithSignatureSerializePart {
700                        unsigned: Transaction::Ethereum(
701                            EthereumTransaction::Eip155(Eip155Transaction {
702                                nonce,
703                                gas_price,
704                                gas,
705                                action,
706                                value,
707                                chain_id,
708                                data,
709                            }),
710                        ),
711                        v,
712                        r,
713                        s,
714                    })
715                }
716                _ => Err(DecoderError::RlpInvalidLength),
717            }
718        } else {
719            match rlp.as_raw()[0] {
720                TYPED_NATIVE_TX_PREFIX_BYTE => {
721                    if rlp.as_raw().len() <= 4
722                        || rlp.as_raw()[0..3] != *TYPED_NATIVE_TX_PREFIX
723                    {
724                        return Err(DecoderError::RlpInvalidLength);
725                    }
726                    match rlp.as_raw()[3] {
727                        CIP2930_TYPE => {
728                            let rlp = Rlp::new(&rlp.as_raw()[4..]);
729                            if rlp.item_count()? != 4 {
730                                return Err(DecoderError::RlpIncorrectListLen);
731                            }
732
733                            let tx = rlp.val_at(0)?;
734                            let v = rlp.val_at(1)?;
735                            let r = rlp.val_at(2)?;
736                            let s = rlp.val_at(3)?;
737                            Ok(TransactionWithSignatureSerializePart {
738                                unsigned: Transaction::Native(
739                                    TypedNativeTransaction::Cip2930(tx),
740                                ),
741                                v,
742                                r,
743                                s,
744                            })
745                        }
746                        CIP1559_TYPE => {
747                            let rlp = Rlp::new(&rlp.as_raw()[4..]);
748                            if rlp.item_count()? != 4 {
749                                return Err(DecoderError::RlpIncorrectListLen);
750                            }
751
752                            let tx = rlp.val_at(0)?;
753                            let v = rlp.val_at(1)?;
754                            let r = rlp.val_at(2)?;
755                            let s = rlp.val_at(3)?;
756                            Ok(TransactionWithSignatureSerializePart {
757                                unsigned: Transaction::Native(
758                                    TypedNativeTransaction::Cip1559(tx),
759                                ),
760                                v,
761                                r,
762                                s,
763                            })
764                        }
765                        _ => Err(DecoderError::RlpInvalidLength),
766                    }
767                }
768                EIP2930_TYPE => {
769                    let rlp = Rlp::new(&rlp.as_raw()[1..]);
770                    if rlp.item_count()? != 11 {
771                        return Err(DecoderError::RlpIncorrectListLen);
772                    }
773
774                    let tx = Eip2930Transaction {
775                        chain_id: rlp.val_at(0)?,
776                        nonce: rlp.val_at(1)?,
777                        gas_price: rlp.val_at(2)?,
778                        gas: rlp.val_at(3)?,
779                        action: rlp.val_at(4)?,
780                        value: rlp.val_at(5)?,
781                        data: rlp.val_at(6)?,
782                        access_list: rlp.list_at(7)?,
783                    };
784                    let v = rlp.val_at(8)?;
785                    let r = rlp.val_at(9)?;
786                    let s = rlp.val_at(10)?;
787                    Ok(TransactionWithSignatureSerializePart {
788                        unsigned: Transaction::Ethereum(
789                            EthereumTransaction::Eip2930(tx),
790                        ),
791                        v,
792                        r,
793                        s,
794                    })
795                }
796                EIP1559_TYPE => {
797                    let rlp = Rlp::new(&rlp.as_raw()[1..]);
798                    if rlp.item_count()? != 12 {
799                        return Err(DecoderError::RlpIncorrectListLen);
800                    }
801
802                    let tx = Eip1559Transaction {
803                        chain_id: rlp.val_at(0)?,
804                        nonce: rlp.val_at(1)?,
805                        max_priority_fee_per_gas: rlp.val_at(2)?,
806                        max_fee_per_gas: rlp.val_at(3)?,
807                        gas: rlp.val_at(4)?,
808                        action: rlp.val_at(5)?,
809                        value: rlp.val_at(6)?,
810                        data: rlp.val_at(7)?,
811                        access_list: rlp.list_at(8)?,
812                    };
813                    let v = rlp.val_at(9)?;
814                    let r = rlp.val_at(10)?;
815                    let s = rlp.val_at(11)?;
816                    Ok(TransactionWithSignatureSerializePart {
817                        unsigned: Transaction::Ethereum(
818                            EthereumTransaction::Eip1559(tx),
819                        ),
820                        v,
821                        r,
822                        s,
823                    })
824                }
825                EIP7702_TYPE => {
826                    let rlp = Rlp::new(&rlp.as_raw()[1..]);
827                    if rlp.item_count()? != 13 {
828                        return Err(DecoderError::RlpIncorrectListLen);
829                    }
830
831                    let tx = Eip7702Transaction {
832                        chain_id: rlp.val_at(0)?,
833                        nonce: rlp.val_at(1)?,
834                        max_priority_fee_per_gas: rlp.val_at(2)?,
835                        max_fee_per_gas: rlp.val_at(3)?,
836                        gas: rlp.val_at(4)?,
837                        destination: rlp.val_at(5)?,
838                        value: rlp.val_at(6)?,
839                        data: rlp.val_at(7)?,
840                        access_list: rlp.list_at(8)?,
841                        authorization_list: rlp.list_at(9)?,
842                    };
843                    let v = rlp.val_at(10)?;
844                    let r = rlp.val_at(11)?;
845                    let s = rlp.val_at(12)?;
846                    Ok(TransactionWithSignatureSerializePart {
847                        unsigned: Transaction::Ethereum(
848                            EthereumTransaction::Eip7702(tx),
849                        ),
850                        v,
851                        r,
852                        s,
853                    })
854                }
855                _ => Err(DecoderError::RlpInvalidLength),
856            }
857        }
858    }
859}
860
861impl Deref for TransactionWithSignatureSerializePart {
862    type Target = Transaction;
863
864    fn deref(&self) -> &Self::Target { &self.unsigned }
865}
866
867impl DerefMut for TransactionWithSignatureSerializePart {
868    fn deref_mut(&mut self) -> &mut Self::Target { &mut self.unsigned }
869}
870
871/// Signed transaction information without verified signature.
872#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
873pub struct TransactionWithSignature {
874    /// Serialize part.
875    pub transaction: TransactionWithSignatureSerializePart,
876    /// Hash of the transaction
877    #[serde(skip)]
878    pub hash: H256,
879    /// The transaction size when serialized in rlp
880    #[serde(skip)]
881    pub rlp_size: Option<usize>,
882}
883
884impl Deref for TransactionWithSignature {
885    type Target = TransactionWithSignatureSerializePart;
886
887    fn deref(&self) -> &Self::Target { &self.transaction }
888}
889
890impl DerefMut for TransactionWithSignature {
891    fn deref_mut(&mut self) -> &mut Self::Target { &mut self.transaction }
892}
893
894impl Decodable for TransactionWithSignature {
895    fn decode(tx_rlp: &Rlp) -> Result<Self, DecoderError> {
896        let rlp_size = Some(tx_rlp.as_raw().len());
897        // The item count of TransactionWithSignatureSerializePart is checked in
898        // its decoding.
899        let hash;
900        let transaction;
901        if tx_rlp.is_list() {
902            hash = keccak(tx_rlp.as_raw());
903            // Vanilla tx encoding.
904            transaction = tx_rlp.as_val()?;
905        } else {
906            // Typed tx encoding is wrapped as an RLP string.
907            let b: Vec<u8> = tx_rlp.as_val()?;
908            hash = keccak(&b);
909            transaction = rlp::decode(&b)?;
910        };
911        Ok(TransactionWithSignature {
912            transaction,
913            hash,
914            rlp_size,
915        })
916    }
917}
918
919impl Encodable for TransactionWithSignature {
920    fn rlp_append(&self, s: &mut RlpStream) {
921        match &self.transaction.unsigned {
922            Transaction::Native(TypedNativeTransaction::Cip155(_))
923            | Transaction::Ethereum(EthereumTransaction::Eip155(_)) => {
924                s.append_internal(&self.transaction);
925            }
926            _ => {
927                // Typed tx encoding is wrapped as an RLP string.
928                s.append_internal(&rlp::encode(&self.transaction));
929            }
930        }
931    }
932}
933
934impl TransactionWithSignature {
935    pub fn new_unsigned(tx: Transaction) -> Self {
936        TransactionWithSignature {
937            transaction: TransactionWithSignatureSerializePart {
938                unsigned: tx,
939                s: 0.into(),
940                r: 0.into(),
941                v: 0,
942            },
943            hash: Default::default(),
944            rlp_size: None,
945        }
946    }
947
948    /// Used to compute hash of created transactions
949    fn compute_hash(mut self) -> TransactionWithSignature {
950        let hash = keccak(&*self.transaction.rlp_bytes());
951        self.hash = hash;
952        self
953    }
954
955    /// Checks whether signature is empty.
956    pub fn is_unsigned(&self) -> bool { self.r.is_zero() && self.s.is_zero() }
957
958    /// Construct a signature object from the sig.
959    pub fn signature(&self) -> Signature {
960        let r: H256 = BigEndianHash::from_uint(&self.r);
961        let s: H256 = BigEndianHash::from_uint(&self.s);
962        Signature::from_rsv(&r, &s, self.v)
963    }
964
965    /// Checks whether the signature has a low 's' value.
966    pub fn check_low_s(&self) -> Result<(), keylib::Error> {
967        if !self.signature().is_low_s() {
968            Err(keylib::Error::InvalidSignature)
969        } else {
970            Ok(())
971        }
972    }
973
974    pub fn check_y_parity(&self) -> Result<(), keylib::Error> {
975        if self.is_2718() && self.v > 1 {
976            // In Typed transactions (EIP-2718), v means y_parity, which must be
977            // 0 or 1
978            Err(keylib::Error::InvalidYParity)
979        } else {
980            Ok(())
981        }
982    }
983
984    pub fn hash(&self) -> H256 { self.hash }
985
986    /// Recovers the public key of the sender.
987    pub fn recover_public(&self) -> Result<Public, keylib::Error> {
988        Ok(recover(
989            &self.signature(),
990            &self.unsigned.hash_for_compute_signature(),
991        )?)
992    }
993
994    pub fn rlp_size(&self) -> usize {
995        self.rlp_size.unwrap_or_else(|| self.rlp_bytes().len())
996    }
997
998    pub fn from_raw(raw: &[u8]) -> Result<Self, DecoderError> {
999        Ok(TransactionWithSignature {
1000            transaction: Rlp::new(raw).as_val()?,
1001            hash: keccak(raw),
1002            rlp_size: Some(raw.len()),
1003        })
1004    }
1005}
1006
1007impl MallocSizeOf for TransactionWithSignature {
1008    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1009        self.unsigned.size_of(ops)
1010    }
1011}
1012
1013/// A signed transaction with successfully recovered `sender`.
1014#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1015pub struct SignedTransaction {
1016    pub transaction: TransactionWithSignature,
1017    pub sender: Address,
1018    pub public: Option<Public>,
1019}
1020
1021// The default encoder for local storage.
1022impl Encodable for SignedTransaction {
1023    fn rlp_append(&self, s: &mut RlpStream) {
1024        s.begin_list(3);
1025        s.append(&self.transaction);
1026        s.append(&self.sender);
1027        s.append(&self.public);
1028    }
1029}
1030
1031impl Decodable for SignedTransaction {
1032    fn decode(rlp: &Rlp) -> Result<Self, DecoderError> {
1033        Ok(SignedTransaction {
1034            transaction: rlp.val_at(0)?,
1035            sender: rlp.val_at(1)?,
1036            public: rlp.val_at(2)?,
1037        })
1038    }
1039}
1040
1041impl Deref for SignedTransaction {
1042    type Target = TransactionWithSignature;
1043
1044    fn deref(&self) -> &Self::Target { &self.transaction }
1045}
1046
1047impl DerefMut for SignedTransaction {
1048    fn deref_mut(&mut self) -> &mut Self::Target { &mut self.transaction }
1049}
1050
1051impl From<SignedTransaction> for TransactionWithSignature {
1052    fn from(tx: SignedTransaction) -> Self { tx.transaction }
1053}
1054
1055impl SignedTransaction {
1056    /// Try to verify transaction and recover sender.
1057    pub fn new(public: Public, transaction: TransactionWithSignature) -> Self {
1058        if transaction.is_unsigned() {
1059            SignedTransaction {
1060                transaction,
1061                sender: UNSIGNED_SENDER,
1062                public: None,
1063            }
1064        } else {
1065            let sender = public_to_address(
1066                &public,
1067                transaction.space() == Space::Native,
1068            );
1069            SignedTransaction {
1070                transaction,
1071                sender,
1072                public: Some(public),
1073            }
1074        }
1075    }
1076
1077    pub fn new_unsigned(transaction: TransactionWithSignature) -> Self {
1078        SignedTransaction {
1079            transaction,
1080            sender: UNSIGNED_SENDER,
1081            public: None,
1082        }
1083    }
1084
1085    pub fn set_public(&mut self, public: Public) {
1086        let type_nibble = self.unsigned.space() == Space::Native;
1087        self.sender = public_to_address(&public, type_nibble);
1088        self.public = Some(public);
1089    }
1090
1091    /// Returns transaction sender.
1092    pub fn sender(&self) -> AddressWithSpace {
1093        self.sender.with_space(self.space())
1094    }
1095
1096    pub fn nonce(&self) -> &U256 { self.transaction.nonce() }
1097
1098    /// Checks if signature is empty.
1099    pub fn is_unsigned(&self) -> bool { self.transaction.is_unsigned() }
1100
1101    pub fn hash(&self) -> H256 { self.transaction.hash() }
1102
1103    pub fn gas(&self) -> &U256 { &self.transaction.gas() }
1104
1105    pub fn gas_price(&self) -> &U256 { &self.transaction.gas_price() }
1106
1107    pub fn gas_limit(&self) -> &U256 { &self.transaction.gas() }
1108
1109    pub fn storage_limit(&self) -> Option<u64> {
1110        self.transaction.storage_limit()
1111    }
1112
1113    pub fn rlp_size(&self) -> usize { self.transaction.rlp_size() }
1114
1115    pub fn public(&self) -> &Option<Public> { &self.public }
1116
1117    pub fn verify_public(&self, skip: bool) -> Result<bool, keylib::Error> {
1118        if self.public.is_none() {
1119            return Ok(false);
1120        }
1121
1122        if !skip {
1123            let public = self.public.unwrap();
1124            Ok(verify_public(
1125                &public,
1126                &self.signature(),
1127                &self.unsigned.hash_for_compute_signature(),
1128            )?)
1129        } else {
1130            Ok(true)
1131        }
1132    }
1133
1134    // Calculates the created contract address if the transaction is a contract
1135    // creation.
1136    pub fn cal_created_address(&self) -> Option<AddressWithSpace> {
1137        if let Action::Create = self.action() {
1138            let from = self.sender();
1139            let nonce = self.nonce();
1140            let space = self.space();
1141            let create_type = match space {
1142                Space::Native => {
1143                    CreateContractAddressType::FromSenderNonceAndCodeHash
1144                }
1145                Space::Ethereum => CreateContractAddressType::FromSenderNonce,
1146            };
1147            let code = self.data().as_slice();
1148            let (created_address, _) = cal_contract_address_with_space(
1149                create_type,
1150                &from,
1151                &nonce,
1152                code,
1153            );
1154            Some(created_address)
1155        } else {
1156            None
1157        }
1158    }
1159}
1160
1161impl MallocSizeOf for SignedTransaction {
1162    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1163        self.transaction.size_of(ops)
1164    }
1165}