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