@@ -26,56 +26,34 @@ extern crate itertools;
26
26
extern crate failure;
27
27
extern crate valico;
28
28
extern crate linked_hash_set;
29
- extern crate regex;
29
+ extern crate lunarity;
30
+ extern crate toolshed;
30
31
#[ macro_use]
31
32
extern crate failure_derive;
32
33
#[ macro_use]
33
34
extern crate serde_derive;
34
- #[ macro_use]
35
- extern crate lazy_static;
36
35
37
36
#[ cfg( test) ]
38
37
extern crate hex;
39
38
40
39
mod eip712;
41
40
mod error;
42
41
mod schema;
42
+ mod parser;
43
+ use parser:: * ;
43
44
pub use error:: * ;
44
45
pub use eip712:: * ;
45
46
use schema:: * ;
46
47
47
- use ethabi:: { encode, Token } ;
48
- use ethereum_types:: { Address , U256 , H256 } ;
48
+ use ethabi:: { encode, Token as EthAbiToken } ;
49
+ use ethereum_types:: { Address as EthAddress , U256 , H256 } ;
49
50
use keccak_hash:: keccak;
50
51
use serde_json:: Value ;
51
- use std:: collections:: HashSet ;
52
52
use std:: str:: FromStr ;
53
53
use itertools:: Itertools ;
54
54
use linked_hash_set:: LinkedHashSet ;
55
55
use serde_json:: to_value;
56
56
57
-
58
- lazy_static ! {
59
- static ref INT_TYPES : HashSet <& ' static str > = vec![
60
- "int8" , "int16" , "int24" , "int32" , "int40" , "int48" , "int56" , "int64" , "int72" , "int80" ,
61
- "int88" , "int96" , "int104" , "int112" , "int120" , "int128" , "int136" , "int144" , "int152" , "int160" ,
62
- "int168" , "int176" , "int184" , "int192" , "int200" , "int208" , "int216" , "int224" , "int232" , "int240" ,
63
- "int248" , "int256" , "uint8" , "uint16" , "uint24" , "uint32" , "uint40" , "uint48" , "uint56" ,
64
- "uint64" , "uint72" , "uint80" , "uint88" , "uint96" , "uint104" , "uint112" , "uint120" , "uint128" ,
65
- "uint136" , "uint144" , "uint152" , "uint160" , "uint168" , "uint176" , "uint184" , "uint192" , "uint200" ,
66
- "uint208" , "uint216" , "uint224" , "uint232" , "uint240" , "uint248" , "uint256"
67
- ] . into_iter( ) . collect( ) ;
68
-
69
- static ref BYTES_TYPES : HashSet <& ' static str > = vec![
70
- "bytes1" , "bytes2" , "bytes3" , "bytes4" , "bytes5" , "bytes6" , "bytes7" , "bytes8" ,
71
- "bytes9" , "bytes10" , "bytes11" , "bytes12" , "bytes13" , "bytes14" , "bytes15" , "bytes16" , "bytes17" ,
72
- "bytes18" , "bytes19" , "bytes20" , "bytes21" , "bytes22" , "bytes23" , "bytes24" , "bytes25" , "bytes26" ,
73
- "bytes27" , "bytes28" , "bytes29" , "bytes30" , "bytes31" , "bytes32"
74
- ] . into_iter( ) . collect( ) ;
75
-
76
- }
77
-
78
-
79
57
/// given a type and HashMap<String, Vec<FieldType>>
80
58
/// returns a HashSet of dependent types of the given type
81
59
fn build_dependencies < ' a > ( message_type : & ' a str , message_types : & ' a MessageTypes ) -> Option < ( LinkedHashSet < & ' a str > ) >
@@ -138,38 +116,43 @@ fn type_hash(message_type: &str, typed_data: &MessageTypes) -> Result<H256> {
138
116
Ok ( keccak ( encode_type ( message_type, typed_data) ?) )
139
117
}
140
118
141
- fn encode_data ( message_type : & str , message_types : & MessageTypes , message : & Value ) -> Result < Vec < u8 > > {
119
+ fn encode_data ( parser : & Parser , message_type : & str , message_types : & MessageTypes , message : & Value ) -> Result < Vec < u8 > > {
142
120
let type_hash = ( & type_hash ( message_type, & message_types) ?) . to_vec ( ) ;
143
- let mut tokens = vec ! [ Token :: FixedBytes ( type_hash) ] ;
121
+ let mut tokens = vec ! [ EthAbiToken :: FixedBytes ( type_hash) ] ;
122
+
144
123
for field in message_types. get ( message_type) . ok_or_else ( || ErrorKind :: NonExistentType ) ? {
145
124
let value = & message[ & field. name ] ;
146
- match & * field. type_ {
147
- // Array type e.g uint256[], string[]
148
- ty if ty. len ( ) > 1 && ty. rfind ( ']' ) == Some ( ty. len ( ) - 1 ) => {
149
- let array_type = ty. find ( '[' )
150
- . and_then ( |index| ty. get ( ..index) )
151
- . ok_or_else ( || ErrorKind :: ArrayParseError ( field. name . clone ( ) ) ) ?;
125
+ let type_ = parser. parse_type ( & * field. type_ ) ?;
152
126
127
+ match type_ {
128
+ Type :: Array ( array_type) => {
153
129
let mut items = vec ! [ ] ;
154
130
155
131
for item in value. as_array ( ) . ok_or_else ( || serde_error ( "array" , & field. name ) ) ? {
156
- // is the array defined in the custom types?
157
- if let Some ( _) = message_types. get ( array_type) {
158
- let encoded = encode_data ( array_type. into ( ) , & message_types, item) ?;
159
- items. push ( encoded) ;
160
- } else {
161
- // it's either a primitive or invalid
162
- let token = encode_primitive ( array_type. into ( ) , & field. name , item) ?;
163
- items. push ( encode ( & [ token] ) ) ;
164
- }
132
+ let nested_type = * array_type. clone ( ) ;
133
+ match nested_type {
134
+ Type :: Array ( nested_arr) => {
135
+ let nested_type: String = ( * nested_arr) . into ( ) ;
136
+ let encoded = encode_data ( parser, & * nested_type, & message_types, item) ?;
137
+ items. push ( encoded) ;
138
+ } ,
139
+ Type :: Custom ( ident) => {
140
+ let encoded = encode_data ( parser, & ident, & message_types, item) ?;
141
+ items. push ( encoded) ;
142
+ }
143
+ _ => {
144
+ let token = encode_primitive ( nested_type, & field. name , item) ?;
145
+ items. push ( encode ( & [ token] ) ) ;
146
+ }
147
+ } ;
165
148
}
166
- tokens. push ( Token :: FixedBytes ( keccak ( items. concat ( ) ) . 0 . to_vec ( ) ) ) ;
149
+ tokens. push ( EthAbiToken :: FixedBytes ( keccak ( items. concat ( ) ) . 0 . to_vec ( ) ) ) ;
167
150
}
168
151
// custom type defined in message types
169
- t if message_types. get ( t ) . is_some ( ) => {
170
- let encoded = encode_data ( & field . type_ , & message_types, & value) ?;
152
+ Type :: Custom ( ref ident ) if message_types. get ( & * ident ) . is_some ( ) => {
153
+ let encoded = encode_data ( parser , & ident , & message_types, & value) ?;
171
154
let hash = ( & keccak ( encoded) ) . to_vec ( ) ;
172
- tokens. push ( Token :: FixedBytes ( hash) ) ;
155
+ tokens. push ( EthAbiToken :: FixedBytes ( hash) ) ;
173
156
}
174
157
// ethabi primitive types
175
158
field_type => {
@@ -181,9 +164,9 @@ fn encode_data(message_type: &str, message_types: &MessageTypes, message: &Value
181
164
return Ok ( encode ( & tokens) ) ;
182
165
}
183
166
184
- fn encode_primitive ( field_type : & str , field_name : & str , value : & Value ) -> Result < Token > {
167
+ fn encode_primitive ( field_type : Type , field_name : & str , value : & Value ) -> Result < EthAbiToken > {
185
168
match field_type {
186
- "bytes" => {
169
+ Type :: Bytes ( size ) if size == 32 => {
187
170
let string = value. as_str ( ) . ok_or_else ( || serde_error ( "string" , field_name) ) ?;
188
171
if string. len ( ) <= 2 {
189
172
return Err ( ErrorKind :: HexParseError (
@@ -193,9 +176,9 @@ fn encode_primitive(field_type: &str, field_name: &str, value: &Value) -> Result
193
176
let string = string. get ( 2 ..) . expect ( "line 188 checks for length; qed" ) ;
194
177
let bytes = H256 :: from_str ( string) . map_err ( |err| ErrorKind :: HexParseError ( format ! ( "{}" , err) ) ) ?;
195
178
let hash = ( & keccak ( & bytes) ) . to_vec ( ) ;
196
- return Ok ( Token :: FixedBytes ( hash) ) ;
179
+ return Ok ( EthAbiToken :: FixedBytes ( hash) ) ;
197
180
}
198
- ty if BYTES_TYPES . contains ( ty ) => {
181
+ Type :: Bytes ( size ) if size < 32 => {
199
182
let string = value. as_str ( ) . ok_or_else ( || serde_error ( "string" , field_name) ) ?;
200
183
if string. len ( ) <= 2 {
201
184
return Err ( ErrorKind :: HexParseError (
@@ -204,26 +187,25 @@ fn encode_primitive(field_type: &str, field_name: &str, value: &Value) -> Result
204
187
}
205
188
let string = string. get ( 2 ..) . expect ( "line 200 checks for length; qed" ) ;
206
189
let bytes = H256 :: from_str ( string) . map_err ( |err| ErrorKind :: HexParseError ( format ! ( "{}" , err) ) ) ?;
207
- return Ok ( Token :: FixedBytes ( bytes. to_vec ( ) ) ) ;
190
+ return Ok ( EthAbiToken :: FixedBytes ( bytes. to_vec ( ) ) ) ;
208
191
}
209
- "string" => {
192
+ Type :: String => {
210
193
let value = value. as_str ( ) . ok_or_else ( || serde_error ( "string" , field_name) ) ?;
211
194
let hash = ( & keccak ( value) ) . to_vec ( ) ;
212
- return Ok ( Token :: FixedBytes ( hash) ) ;
195
+ return Ok ( EthAbiToken :: FixedBytes ( hash) ) ;
213
196
}
214
- "bool" => return Ok ( Token :: Bool ( value. as_bool ( ) . ok_or_else ( || serde_error ( "bool" , field_name) ) ?) ) ,
215
- "address" => {
197
+ Type :: Bool => return Ok ( EthAbiToken :: Bool ( value. as_bool ( ) . ok_or_else ( || serde_error ( "bool" , field_name) ) ?) ) ,
198
+ Type :: Address => {
216
199
let addr = value. as_str ( ) . ok_or_else ( || serde_error ( "string" , field_name) ) ?;
217
200
if addr. len ( ) != 42 {
218
201
return Err ( ErrorKind :: InvalidAddressLength ( addr. len ( ) ) ) ?;
219
202
}
220
203
// we've checked the address length, this is safe
221
204
let addr = addr. get ( 2 ..) . unwrap ( ) ;
222
- let address = Address :: from_str ( addr) . map_err ( |err| ErrorKind :: HexParseError ( format ! ( "{}" , err) ) ) ?;
223
- return Ok ( Token :: Address ( address) ) ;
205
+ let address = EthAddress :: from_str ( addr) . map_err ( |err| ErrorKind :: HexParseError ( format ! ( "{}" , err) ) ) ?;
206
+ return Ok ( EthAbiToken :: Address ( address) ) ;
224
207
}
225
- // (un)signed integers
226
- ty if INT_TYPES . contains ( ty) => {
208
+ Type :: Uint => {
227
209
// try to deserialize as a number first, then a string
228
210
let uint = match ( value. as_u64 ( ) , value. as_str ( ) ) {
229
211
( Some ( number) , _) => U256 :: from ( number) ,
@@ -238,10 +220,10 @@ fn encode_primitive(field_type: &str, field_name: &str, value: &Value) -> Result
238
220
}
239
221
_ => return Err ( serde_error ( "int/uint" , field_name) ) ?
240
222
} ;
241
- return Ok ( Token :: Uint ( uint) ) ;
223
+ return Ok ( EthAbiToken :: Uint ( uint) ) ;
242
224
}
243
225
// the type couldn't be encoded
244
- _ => return Err ( ErrorKind :: UnknownType ( field_name. to_owned ( ) , field_type . to_owned ( ) ) ) ?
226
+ _ => return Err ( ErrorKind :: UnknownType ( field_name. to_owned ( ) , "" . to_owned ( ) ) ) ?
245
227
}
246
228
}
247
229
@@ -252,9 +234,10 @@ pub fn hash_data(typed_data: EIP712) -> Result<Vec<u8>> {
252
234
// EIP-191 compliant
253
235
let prefix = ( b"\x19 \x01 " ) . to_vec ( ) ;
254
236
let domain = to_value ( & typed_data. domain ) . unwrap ( ) ;
237
+ let parser = Parser :: new ( ) ;
255
238
let ( domain_hash, data_hash) = (
256
- keccak ( encode_data ( "EIP712Domain" , & typed_data. types , & domain) ?) . 0 ,
257
- keccak ( encode_data ( & typed_data. primary_type , & typed_data. types , & typed_data. message ) ?) . 0
239
+ keccak ( encode_data ( & parser , "EIP712Domain" , & typed_data. types , & domain) ?) . 0 ,
240
+ keccak ( encode_data ( & parser , & typed_data. primary_type , & typed_data. types , & typed_data. message ) ?) . 0
258
241
) ;
259
242
let concat = [ & prefix[ ..] , & domain_hash[ ..] , & data_hash[ ..] ] . concat ( ) ;
260
243
Ok ( ( & keccak ( concat) ) . to_vec ( ) )
@@ -403,7 +386,8 @@ mod tests {
403
386
#[ test]
404
387
fn test_encode_data ( ) {
405
388
let typed_data = from_str :: < EIP712 > ( JSON ) . expect ( "alas error!" ) ;
406
- let encoded = encode_data ( "Mail" . into ( ) , & typed_data. types , & typed_data. message ) . expect ( "alas error!" ) ;
389
+ let encoded = encode_data ( & Parser :: new ( ) , "Mail" . into ( ) , & typed_data. types , & typed_data. message ) . expect ( "alas \
390
+ error!") ;
407
391
assert_eq ! ( hex:: encode( encoded) , "a0cedeb2dc280ba39b857546d74f5549c3a1d7bdc2dd96bf881f76108e23dac2fc71e5fa27ff56c350aa531bc129ebdf613b772b6604664f5d8dbe21b85eb0c8cd54f074a4af31b4411ff6a60c9719dbd559c221c8ac3492d9d872b041d703d1b5aadf3154a261abdd9086fc627b61efca26ae5702701d05cd2305f7c52a2fc8" )
408
392
}
409
393
0 commit comments