1mod 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
48pub 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
60pub type TxShortId = u64;
63
64pub type TxPropagateId = u32;
65
66#[derive(Debug, PartialEq, Clone, Eq)]
70pub enum TransactionError {
72 AlreadyImported,
74 ChainIdMismatch {
76 expected: u32,
77 got: u32,
78 space: Space,
79 },
80 EpochHeightOutOfBound {
82 block_height: u64,
83 set: u64,
84 transaction_epoch_bound: u64,
85 },
86 NotEnoughBaseGas {
88 required: U256,
90 got: U256,
92 },
93 Stale,
95 TooCheapToReplace,
99 LimitReached,
102 InsufficientGasPrice {
104 minimal: U256,
106 got: U256,
108 },
109 InsufficientGas {
111 minimal: U256,
113 got: U256,
115 },
116 InsufficientBalance {
118 balance: U256,
120 cost: U256,
122 },
123 GasLimitExceeded {
125 limit: U256,
127 got: U256,
129 },
130 InvalidGasLimit(OutOfBounds<U256>),
132 InvalidSignature(String),
134 TooBig,
136 InvalidRlp(String),
138 ZeroGasPrice,
139 FutureTransactionType {
141 tx_type: u8,
142 enable_height: u64,
143 current_height: u64,
144 },
145 CreateInitCodeSizeLimit,
147 InvalidReceiver,
149 TooLargeNonce,
151 EmptyAuthorizationList,
153 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,
236 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 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 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#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
528pub struct TransactionWithSignatureSerializePart {
529 pub unsigned: Transaction,
531 pub v: u8,
534 pub r: U256,
536 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 } }
650 }
651}
652
653impl 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#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
873pub struct TransactionWithSignature {
874 pub transaction: TransactionWithSignatureSerializePart,
876 #[serde(skip)]
878 pub hash: H256,
879 #[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 let hash;
900 let transaction;
901 if tx_rlp.is_list() {
902 hash = keccak(tx_rlp.as_raw());
903 transaction = tx_rlp.as_val()?;
905 } else {
906 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 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 fn compute_hash(mut self) -> TransactionWithSignature {
950 let hash = keccak(&*self.transaction.rlp_bytes());
951 self.hash = hash;
952 self
953 }
954
955 pub fn is_unsigned(&self) -> bool { self.r.is_zero() && self.s.is_zero() }
957
958 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 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 Err(keylib::Error::InvalidYParity)
979 } else {
980 Ok(())
981 }
982 }
983
984 pub fn hash(&self) -> H256 { self.hash }
985
986 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#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1015pub struct SignedTransaction {
1016 pub transaction: TransactionWithSignature,
1017 pub sender: Address,
1018 pub public: Option<Public>,
1019}
1020
1021impl 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 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 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 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 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}