@@ -4,7 +4,117 @@ use ethereum_types::{Address, H256, U256};
4
4
use rlp:: { DecoderError , Rlp , RlpStream } ;
5
5
use sha3:: { Digest , Keccak256 } ;
6
6
7
- use crate :: { transaction:: TransactionAction , Bytes } ;
7
+ use crate :: Bytes ;
8
+
9
+ pub use super :: legacy:: TransactionAction ;
10
+
11
+ #[ derive( Clone , Debug , PartialEq , Eq ) ]
12
+ #[ cfg_attr(
13
+ feature = "with-scale" ,
14
+ derive(
15
+ scale_info:: TypeInfo ,
16
+ scale_codec:: Encode ,
17
+ scale_codec:: Decode ,
18
+ scale_codec:: DecodeWithMemTracking
19
+ )
20
+ ) ]
21
+ #[ cfg_attr( feature = "with-serde" , derive( serde:: Serialize , serde:: Deserialize ) ) ]
22
+ pub struct MalleableTransactionSignature {
23
+ pub odd_y_parity : bool ,
24
+ pub r : H256 ,
25
+ pub s : H256 ,
26
+ }
27
+
28
+ #[ derive( Clone , Debug , PartialEq , Eq ) ]
29
+ #[ cfg_attr(
30
+ feature = "with-scale" ,
31
+ derive(
32
+ scale_info:: TypeInfo ,
33
+ scale_codec:: Encode ,
34
+ scale_codec:: DecodeWithMemTracking
35
+ )
36
+ ) ]
37
+ #[ cfg_attr( feature = "with-serde" , derive( serde:: Serialize ) ) ]
38
+ pub struct TransactionSignature {
39
+ odd_y_parity : bool ,
40
+ r : H256 ,
41
+ s : H256 ,
42
+ }
43
+
44
+ impl TransactionSignature {
45
+ #[ must_use]
46
+ pub fn new ( odd_y_parity : bool , r : H256 , s : H256 ) -> Option < Self > {
47
+ const LOWER : H256 = H256 ( [
48
+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
49
+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
50
+ 0x00 , 0x00 , 0x00 , 0x01 ,
51
+ ] ) ;
52
+ const UPPER : H256 = H256 ( [
53
+ 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff ,
54
+ 0xff , 0xfe , 0xba , 0xae , 0xdc , 0xe6 , 0xaf , 0x48 , 0xa0 , 0x3b , 0xbf , 0xd2 , 0x5e , 0x8c ,
55
+ 0xd0 , 0x36 , 0x41 , 0x41 ,
56
+ ] ) ;
57
+
58
+ let is_valid = r < UPPER && r >= LOWER && s < UPPER && s >= LOWER ;
59
+
60
+ if is_valid {
61
+ Some ( Self { odd_y_parity, r, s } )
62
+ } else {
63
+ None
64
+ }
65
+ }
66
+
67
+ #[ must_use]
68
+ pub fn odd_y_parity ( & self ) -> bool {
69
+ self . odd_y_parity
70
+ }
71
+
72
+ #[ must_use]
73
+ pub fn r ( & self ) -> & H256 {
74
+ & self . r
75
+ }
76
+
77
+ #[ must_use]
78
+ pub fn s ( & self ) -> & H256 {
79
+ & self . s
80
+ }
81
+
82
+ #[ must_use]
83
+ pub fn is_low_s ( & self ) -> bool {
84
+ const LOWER : H256 = H256 ( [
85
+ 0x7f , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff ,
86
+ 0xff , 0xff , 0x5d , 0x57 , 0x6e , 0x73 , 0x57 , 0xa4 , 0x50 , 0x1d , 0xdf , 0xe9 , 0x2f , 0x46 ,
87
+ 0x68 , 0x1b , 0x20 , 0xa0 ,
88
+ ] ) ;
89
+
90
+ self . s <= LOWER
91
+ }
92
+ }
93
+
94
+ #[ cfg( feature = "with-scale" ) ]
95
+ impl scale_codec:: Decode for TransactionSignature {
96
+ fn decode < I : scale_codec:: Input > ( value : & mut I ) -> Result < Self , scale_codec:: Error > {
97
+ let unchecked = MalleableTransactionSignature :: decode ( value) ?;
98
+ match Self :: new ( unchecked. odd_y_parity , unchecked. r , unchecked. s ) {
99
+ Some ( signature) => Ok ( signature) ,
100
+ None => Err ( scale_codec:: Error :: from ( "Invalid signature" ) ) ,
101
+ }
102
+ }
103
+ }
104
+
105
+ #[ cfg( feature = "with-serde" ) ]
106
+ impl < ' de > serde:: Deserialize < ' de > for TransactionSignature {
107
+ fn deserialize < D > ( deserializer : D ) -> Result < Self , D :: Error >
108
+ where
109
+ D : serde:: de:: Deserializer < ' de > ,
110
+ {
111
+ let unchecked = MalleableTransactionSignature :: deserialize ( deserializer) ?;
112
+ Ok (
113
+ TransactionSignature :: new ( unchecked. odd_y_parity , unchecked. r , unchecked. s )
114
+ . ok_or ( serde:: de:: Error :: custom ( "invalid signature" ) ) ?,
115
+ )
116
+ }
117
+ }
8
118
9
119
#[ derive( Clone , Debug , PartialEq , Eq ) ]
10
120
#[ cfg_attr(
@@ -61,9 +171,7 @@ pub struct EIP2930Transaction {
61
171
pub value : U256 ,
62
172
pub input : Bytes ,
63
173
pub access_list : AccessList ,
64
- pub odd_y_parity : bool ,
65
- pub r : H256 ,
66
- pub s : H256 ,
174
+ pub signature : TransactionSignature ,
67
175
}
68
176
69
177
impl EIP2930Transaction {
@@ -100,9 +208,9 @@ impl rlp::Encodable for EIP2930Transaction {
100
208
s. append ( & self . value ) ;
101
209
s. append ( & self . input ) ;
102
210
s. append_list ( & self . access_list ) ;
103
- s. append ( & self . odd_y_parity ) ;
104
- s. append ( & U256 :: from_big_endian ( & self . r [ ..] ) ) ;
105
- s. append ( & U256 :: from_big_endian ( & self . s [ ..] ) ) ;
211
+ s. append ( & self . signature . odd_y_parity ( ) ) ;
212
+ s. append ( & U256 :: from_big_endian ( & self . signature . r ( ) [ ..] ) ) ;
213
+ s. append ( & U256 :: from_big_endian ( & self . signature . s ( ) [ ..] ) ) ;
106
214
}
107
215
}
108
216
@@ -121,9 +229,13 @@ impl rlp::Decodable for EIP2930Transaction {
121
229
value : rlp. val_at ( 5 ) ?,
122
230
input : rlp. val_at ( 6 ) ?,
123
231
access_list : rlp. list_at ( 7 ) ?,
124
- odd_y_parity : rlp. val_at ( 8 ) ?,
125
- r : H256 :: from ( rlp. val_at :: < U256 > ( 9 ) ?. to_big_endian ( ) ) ,
126
- s : H256 :: from ( rlp. val_at :: < U256 > ( 10 ) ?. to_big_endian ( ) ) ,
232
+ signature : {
233
+ let odd_y_parity = rlp. val_at ( 8 ) ?;
234
+ let r = H256 :: from ( rlp. val_at :: < U256 > ( 9 ) ?. to_big_endian ( ) ) ;
235
+ let s = H256 :: from ( rlp. val_at :: < U256 > ( 10 ) ?. to_big_endian ( ) ) ;
236
+ TransactionSignature :: new ( odd_y_parity, r, s)
237
+ . ok_or ( DecoderError :: Custom ( "Invalid transaction signature format" ) ) ?
238
+ } ,
127
239
} )
128
240
}
129
241
}
0 commit comments