From e95b996309dc428a7946ecdb627ece2a82fb15c5 Mon Sep 17 00:00:00 2001 From: Seun LanLege Date: Mon, 1 Oct 2018 21:57:53 +0100 Subject: [PATCH] removed schema validation, refactored encode_data --- Cargo.lock | 113 ----------------------------- util/EIP-712/Cargo.toml | 1 - util/EIP-712/src/eip712.rs | 1 - util/EIP-712/src/error.rs | 4 +- util/EIP-712/src/lib.rs | 128 +++++++++++++-------------------- util/EIP-712/src/schema.rs | 144 ------------------------------------- 6 files changed, 52 insertions(+), 339 deletions(-) delete mode 100644 util/EIP-712/src/schema.rs diff --git a/Cargo.lock b/Cargo.lock index e13c6e18dfb..5db14b03403 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,11 +1,3 @@ -[[package]] -name = "aho-corasick" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "aho-corasick" version = "0.6.8" @@ -432,7 +424,6 @@ dependencies = [ "serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", "toolshed 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "valico 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1581,15 +1572,6 @@ dependencies = [ "ws 0.7.5 (git+https://github.com/tomusdrw/ws-rs)", ] -[[package]] -name = "jsonway" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "keccak-hash" version = "0.1.2" @@ -1790,14 +1772,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "mem" version = "0.1.0" -[[package]] -name = "memchr" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "memchr" version = "2.0.2" @@ -2803,18 +2777,6 @@ dependencies = [ "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "regex" -version = "0.1.80" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "regex" version = "0.2.11" @@ -2839,11 +2801,6 @@ dependencies = [ "utf8-ranges 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "regex-syntax" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "regex-syntax" version = "0.5.6" @@ -3304,15 +3261,6 @@ dependencies = [ "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "thread-id" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "thread-id" version = "3.3.0" @@ -3323,14 +3271,6 @@ dependencies = [ "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "thread_local" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "thread_local" version = "0.3.6" @@ -3651,11 +3591,6 @@ dependencies = [ "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "traitobject" -version = "0.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "transaction-pool" version = "1.13.2" @@ -3715,11 +3650,6 @@ name = "try-lock" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "typeable" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "ucd-util" version = "0.1.1" @@ -3811,42 +3741,11 @@ dependencies = [ name = "using_queue" version = "0.1.0" -[[package]] -name = "utf8-ranges" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "utf8-ranges" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "uuid" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "valico" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "jsonway 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "phf 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_codegen 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", - "traitobject 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "vec_map" version = "0.8.1" @@ -4062,7 +3961,6 @@ dependencies = [ ] [metadata] -"checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66" "checksum aho-corasick 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "68f56c7353e5a9547cbd76ed90f7bb5ffc3ba09d4ea9bd1d8c06c8b1142eeb5a" "checksum ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b3568b48b7cefa6b8ce125f9bb4989e52fbcc29ebea88df04cc7c5f12f70455" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" @@ -4167,7 +4065,6 @@ dependencies = [ "checksum jsonrpc-server-utils 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)" = "" "checksum jsonrpc-tcp-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)" = "" "checksum jsonrpc-ws-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)" = "" -"checksum jsonway 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "effcb749443c905fbaef49d214f8b1049c240e0adb7af9baa0e201e625e4f9de" "checksum keccak-hash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "253bbe643c32c816bf58fa5a88248fafedeebb139705ad17a62add3517854a86" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum kvdb 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "72ae89206cea31c32014b39d5a454b96135894221610dbfd19cf4d2d044fa546" @@ -4191,7 +4088,6 @@ dependencies = [ "checksum lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4d06ff7ff06f729ce5f4e227876cb88d10bc59cd4ae1e09fbb2bde15c850dc21" "checksum lunarity 0.1.0 (git+https://github.com/paritytech/lunarity)" = "" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" -"checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20" "checksum memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a3b4142ab8738a78c51896f704f83c11df047ff1bda9a92a661aa6361552d93d" "checksum memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2ffa2c986de11a9df78620c01eeaaf27d94d3ff02bf81bfcca953102dd0c6ff" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" @@ -4262,10 +4158,8 @@ dependencies = [ "checksum rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b055d1e92aba6877574d8fe604a63c8b5df60f60e5982bf7ccbb1338ea527356" "checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" -"checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f" "checksum regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9329abc99e39129fcceabd24cf5d85b4671ef7c29c50e972bc5afe32438ec384" "checksum regex 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2069749032ea3ec200ca51e4a31df41759190a88edca0d2d86ee8bedf7073341" -"checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957" "checksum regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7" "checksum regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "747ba3b235651f6e2f67dfa8bcdcd073ddb7c243cb21c442fc12395dfcac212d" "checksum relay 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1576e382688d7e9deecea24417e350d3062d97e32e45d70b1cde65994ff1489a" @@ -4320,9 +4214,7 @@ dependencies = [ "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" "checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693" -"checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03" "checksum thread-id 3.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c7fbf4c9d56b320106cd64fd024dadfa0be7cb4706725fc44a7d7ce952d820c1" -"checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865" "checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b" @@ -4351,14 +4243,12 @@ dependencies = [ "checksum toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a0263c6c02c4db6c8f7681f9fd35e90de799ebd4cfdeab77a38f4ff6b3d8c0d9" "checksum toolshed 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "450441e131c7663af72e63a33c02a6a1fbaaa8601dc652ed6757813bb55aeec7" "checksum trace-time 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe82f2f0bf1991e163e757baf044282823155dd326e70f44ce2186c3c320cc9" -"checksum traitobject 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9dc23794ff47c95882da6f9d15de9a6be14987760a28cc0aafb40b7675ef09d8" "checksum transaction-pool 1.13.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fdb8870eea404a57e2f62056ac45067a53a6207fd31866122356481d3c2e1a30" "checksum transient-hashmap 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aeb4b191d033a35edfce392a38cdcf9790b6cebcb30fa690c312c29da4dc433e" "checksum trezor-sys 1.0.0 (git+https://github.com/paritytech/trezor-sys)" = "" "checksum trie-standardmap 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e26f52976a57a0859616d6fcec87092ac35d08eabbd78dc3dabee93b480ea5f" "checksum triehash 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3da77dc2c88bac48769c53f2c7675d99d522a7fc8130da3fadf29d7c6f94c9ac" "checksum try-lock 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee2aa4715743892880f70885373966c83d73ef1b0838a664ef0c76fffd35e7c2" -"checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" "checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d" "checksum uint 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "754ba11732b9161b94c41798e5197e5e75388d012f760c42adb5000353e98646" "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" @@ -4371,10 +4261,7 @@ dependencies = [ "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" "checksum untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f392d7819dbe58833e26872f5f6f0d68b7bbbe90fc3667e98731c4a15ad9a7ae" "checksum url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2a321979c09843d272956e73700d12c4e7d3d92b2ee112b31548aef0d4efc5a6" -"checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f" "checksum utf8-ranges 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd70f467df6810094968e2fce0ee1bd0e87157aceb026a8c083bcf5e25b9efe4" -"checksum uuid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dab5c5526c5caa3d106653401a267fed923e7046f35895ffcb5ca42db64942e6" -"checksum valico 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c72e72176d261fcd815896caef8add11aad45d300da60dd5457b4b4f6d2c03df" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum vergen 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c3365f36c57e5df714a34be40902b27a992eeddb9996eca52d0584611cf885d" "checksum version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7716c242968ee87e5542f8021178248f267f295a5c4803beae8b8b7fd9bc6051" diff --git a/util/EIP-712/Cargo.toml b/util/EIP-712/Cargo.toml index aed4aaed2d7..9bcda7be213 100644 --- a/util/EIP-712/Cargo.toml +++ b/util/EIP-712/Cargo.toml @@ -15,7 +15,6 @@ failure = "0.1" itertools="0.7" failure_derive = "0.1" lazy_static = "1.1" -valico = "2.2" linked_hash_set = "0.1.3" toolshed = "0.4" lunarity = { git = "https://github.com/paritytech/lunarity" } diff --git a/util/EIP-712/src/eip712.rs b/util/EIP-712/src/eip712.rs index 30fe743d99a..3d19773d6ab 100644 --- a/util/EIP-712/src/eip712.rs +++ b/util/EIP-712/src/eip712.rs @@ -23,7 +23,6 @@ use ethereum_types::{U256, H256, Address}; pub(crate) type MessageTypes = HashMap>; - #[serde(rename_all = "camelCase")] #[serde(deny_unknown_fields)] #[derive(Deserialize, Serialize, Debug, Clone)] diff --git a/util/EIP-712/src/error.rs b/util/EIP-712/src/error.rs index 2716a393d5a..02a10c22f62 100644 --- a/util/EIP-712/src/error.rs +++ b/util/EIP-712/src/error.rs @@ -56,8 +56,8 @@ pub enum ErrorKind { UnsupportedArrayDepth } -pub(crate) fn serde_error(expected: &str, field: &str) -> ErrorKind { - ErrorKind::UnexpectedType(expected.to_owned(), field.to_owned()) +pub(crate) fn serde_error(expected: &str, field: Option<&str>) -> ErrorKind { + ErrorKind::UnexpectedType(expected.to_owned(), field.unwrap_or("").to_owned()) } diff --git a/util/EIP-712/src/lib.rs b/util/EIP-712/src/lib.rs index ce456fdd286..6a6afa6564f 100644 --- a/util/EIP-712/src/lib.rs +++ b/util/EIP-712/src/lib.rs @@ -15,7 +15,7 @@ // along with Parity. If not, see . //! EIP-712 encoding utilities -#![warn(missing_docs, unused_extern_crates)] +#![warn(missing_docs)] extern crate serde; extern crate serde_json; @@ -24,7 +24,6 @@ extern crate ethereum_types; extern crate keccak_hash; extern crate itertools; extern crate failure; -extern crate valico; extern crate linked_hash_set; extern crate lunarity; extern crate toolshed; @@ -38,13 +37,10 @@ extern crate hex; mod eip712; mod error; -mod schema; mod parser; use parser::*; pub use error::*; pub use eip712::*; -use schema::*; - use ethabi::{encode, Token as EthAbiToken}; use ethereum_types::{Address as EthAddress, U256, H256}; use keccak_hash::keccak; @@ -116,56 +112,41 @@ fn type_hash(message_type: &str, typed_data: &MessageTypes) -> Result { Ok(keccak(encode_type(message_type, typed_data)?)) } -fn encode_data(parser: &Parser, message_type: &str, message_types: &MessageTypes, message: &Value) -> Result> { - let type_hash = (&type_hash(message_type, &message_types)?).to_vec(); - let mut tokens = vec![EthAbiToken::FixedBytes(type_hash)]; - - for field in message_types.get(message_type).ok_or_else(|| ErrorKind::NonExistentType)? { - let value = &message[&field.name]; - let type_ = parser.parse_type(&*field.type_)?; - - match type_ { - Type::Array(array_type) => { - let mut items = vec![]; - - for item in value.as_array().ok_or_else(|| serde_error("array", &field.name))? { - let nested_type = *array_type.clone(); - match nested_type { - Type::Array(nested_arr) => { - let nested_type: String = (*nested_arr).into(); - let encoded = encode_data(parser, &*nested_type, &message_types, item)?; - items.push(encoded); - }, - Type::Custom(ident) => { - let encoded = encode_data(parser, &ident, &message_types, item)?; - items.push(encoded); - } - _ => { - let token = encode_primitive(nested_type, &field.name, item)?; - items.push(encode(&[token])); - } - }; - } - tokens.push(EthAbiToken::FixedBytes(keccak(items.concat()).0.to_vec())); - } - // custom type defined in message types - Type::Custom(ref ident) if message_types.get(&*ident).is_some() => { - let encoded = encode_data(parser, &ident, &message_types, &value)?; - let hash = (&keccak(encoded)).to_vec(); - tokens.push(EthAbiToken::FixedBytes(hash)); +fn encode_data( + parser: &Parser, + message_type: Type, + message_types: &MessageTypes, + value: &Value, + field_name: Option<&str> +) -> Result> +{ + let encoded = match message_type { + Type::Array(array_type) => { + let mut items = vec![]; + + for item in value.as_array().ok_or_else(|| serde_error("array", field_name))? { + let array_type = (*array_type).clone(); + let mut encoded = encode_data(parser, array_type, &message_types, item, field_name)?; + items.append(&mut encoded); } - // ethabi primitive types - field_type => { - let token = encode_primitive(field_type, &field.name, value)?; - tokens.push(token) + + keccak(items).0.to_vec() + } + + Type::Custom(ref ident) if message_types.get(&*ident).is_some() => { + let type_hash = (&type_hash(ident, &message_types)?).to_vec(); + let mut tokens = encode(&[EthAbiToken::FixedBytes(type_hash)]); + + for field in message_types.get(ident).expect("Already checked in match guard; qed") { + let value = &value[&field.name]; + let type_ = parser.parse_type(&*field.type_)?; + let mut encoded = encode_data(parser, type_, &message_types, &value, Some(&*field.name))?; + tokens.append(&mut encoded); } + + keccak(tokens).0.to_vec() } - } - return Ok(encode(&tokens)); -} -fn encode_primitive(field_type: Type, field_name: &str, value: &Value) -> Result { - match field_type { Type::Bytes(size) if size == 32 => { let string = value.as_str().ok_or_else(|| serde_error("string", field_name))?; if string.len() <= 2 { @@ -176,8 +157,9 @@ fn encode_primitive(field_type: Type, field_name: &str, value: &Value) -> Result let string = string.get(2..).expect("line 188 checks for length; qed"); let bytes = H256::from_str(string).map_err(|err| ErrorKind::HexParseError(format!("{}", err)))?; let hash = (&keccak(&bytes)).to_vec(); - return Ok(EthAbiToken::FixedBytes(hash)); + encode(&[EthAbiToken::FixedBytes(hash)]) } + Type::Bytes(size) if size < 32 => { let string = value.as_str().ok_or_else(|| serde_error("string", field_name))?; if string.len() <= 2 { @@ -187,14 +169,17 @@ fn encode_primitive(field_type: Type, field_name: &str, value: &Value) -> Result } let string = string.get(2..).expect("line 200 checks for length; qed"); let bytes = H256::from_str(string).map_err(|err| ErrorKind::HexParseError(format!("{}", err)))?; - return Ok(EthAbiToken::FixedBytes(bytes.to_vec())); + encode(&[EthAbiToken::FixedBytes(bytes.to_vec())]) } + Type::String => { let value = value.as_str().ok_or_else(|| serde_error("string", field_name))?; let hash = (&keccak(value)).to_vec(); - return Ok(EthAbiToken::FixedBytes(hash)); + encode(&[EthAbiToken::FixedBytes(hash)]) } - Type::Bool => return Ok(EthAbiToken::Bool(value.as_bool().ok_or_else(|| serde_error("bool", field_name))?)), + + Type::Bool => encode(&[EthAbiToken::Bool(value.as_bool().ok_or_else(|| serde_error("bool", field_name))?)]), + Type::Address => { let addr = value.as_str().ok_or_else(|| serde_error("string", field_name))?; if addr.len() != 42 { @@ -203,8 +188,9 @@ fn encode_primitive(field_type: Type, field_name: &str, value: &Value) -> Result // we've checked the address length, this is safe let addr = addr.get(2..).unwrap(); let address = EthAddress::from_str(addr).map_err(|err| ErrorKind::HexParseError(format!("{}", err)))?; - return Ok(EthAbiToken::Address(address)); + encode(&[EthAbiToken::Address(address)]) } + Type::Uint => { // try to deserialize as a number first, then a string let uint = match (value.as_u64(), value.as_str()) { @@ -220,24 +206,25 @@ fn encode_primitive(field_type: Type, field_name: &str, value: &Value) -> Result } _ => return Err(serde_error("int/uint", field_name))? }; - return Ok(EthAbiToken::Uint(uint)); + encode(&[EthAbiToken::Uint(uint)]) } - // the type couldn't be encoded - _ => return Err(ErrorKind::UnknownType(field_name.to_owned(), "".to_owned()))? - } + + _ => return Err(ErrorKind::UnknownType("".to_owned(), message_type.into()))? + }; + + Ok(encoded) } /// encodes and hashes the given EIP712 struct pub fn hash_data(typed_data: EIP712) -> Result> { // json schema validation - validate_data(&typed_data)?; // EIP-191 compliant let prefix = (b"\x19\x01").to_vec(); let domain = to_value(&typed_data.domain).unwrap(); let parser = Parser::new(); let (domain_hash, data_hash) = ( - keccak(encode_data(&parser, "EIP712Domain", &typed_data.types, &domain)?).0, - keccak(encode_data(&parser, &typed_data.primary_type, &typed_data.types, &typed_data.message)?).0 + encode_data(&parser, Type::Custom("EIP712Domain".into()), &typed_data.types, &domain, None)?, + encode_data(&parser, Type::Custom(typed_data.primary_type), &typed_data.types, &typed_data.message, None)? ); let concat = [&prefix[..], &domain_hash[..], &data_hash[..]].concat(); Ok((&keccak(concat)).to_vec()) @@ -248,13 +235,6 @@ mod tests { use super::*; use serde_json::from_str; - #[test] - fn test_valico() { - let typed_data = from_str::(JSON).expect("alas error!"); - - validate_data(&typed_data).unwrap(); - } - const JSON: &'static str = r#"{ "primaryType": "Mail", "domain": { @@ -383,14 +363,6 @@ mod tests { ); } - #[test] - fn test_encode_data() { - let typed_data = from_str::(JSON).expect("alas error!"); - let encoded = encode_data(&Parser::new(), "Mail".into(), &typed_data.types, &typed_data.message).expect("alas \ - error!"); - assert_eq!(hex::encode(encoded), "a0cedeb2dc280ba39b857546d74f5549c3a1d7bdc2dd96bf881f76108e23dac2fc71e5fa27ff56c350aa531bc129ebdf613b772b6604664f5d8dbe21b85eb0c8cd54f074a4af31b4411ff6a60c9719dbd559c221c8ac3492d9d872b041d703d1b5aadf3154a261abdd9086fc627b61efca26ae5702701d05cd2305f7c52a2fc8") - } - #[test] fn test_hash_data() { let typed_data = from_str::(JSON).expect("alas error!"); diff --git a/util/EIP-712/src/schema.rs b/util/EIP-712/src/schema.rs deleted file mode 100644 index fb6e7a3c19e..00000000000 --- a/util/EIP-712/src/schema.rs +++ /dev/null @@ -1,144 +0,0 @@ -use serde_json::Value; -use std::collections::HashMap; -use std::result; -use serde::ser::{Serialize, Serializer, SerializeStruct}; -use serde_json::to_value; -use valico::json_schema; -use {Result, EIP712, ErrorKind, build_dependencies}; - -type FieldName = String; - -#[derive(Clone)] -struct Schema { - required: Vec, - items: Option>, - properties: HashMap, - type_: String, -} - -impl Serialize for Schema { - fn serialize(&self, serializer: S) -> result::Result - where - S: Serializer, - { - let mut schema = serializer.serialize_struct("Schema", 4)?; - - if self.required.len() > 0 { - schema.serialize_field("required", &self.required)?; - } - - if let Some(ref items) = self.items { - schema.serialize_field("items", &*items)?; - } - - if self.properties.len() > 0 { - schema.serialize_field("properties", &self.properties)?; - } - - schema.serialize_field("type", &self.type_)?; - - schema.end() - } -} - - -fn get_json_type(field_type: &str) -> String { - match field_type { - "bool" => "boolean".into(), - _ => "string".into() - } -} - -fn build_schema(data: &EIP712) -> Result { - let dependencies = build_dependencies(&data.primary_type, &data.types) - .ok_or_else(|| ErrorKind::NonExistentType)? - .into_iter() - .collect::>(); - - let mut schemas = dependencies - .into_iter() - .rfold(HashMap::new(), |mut schemas: HashMap<&str, Schema>, current_type| { - let fields = data.types.get(current_type) - .expect("build_dependencies returns a list of type-names that exist in types ;qed"); - - let mut schema = Schema { - type_: "object".into(), - required: vec![], - properties: HashMap::new(), - items: None, - }; - - for field in fields { - let is_array = field.type_.len() > 1 && field.type_.rfind(']') == Some(field.type_.len() - 1); - - if data.types.contains_key(&*field.type_) { - if is_array { - let type_schema = schemas.get(&*field.type_) - .expect("build_dependencies returns the types in \ - the order they exist on the primary \ - type; rfold traverses the types in reverse order\ - and inserts the schema into `schemas` ;qed").clone(); - - let obj_schema = Schema { - type_: "array".into(), - required: vec![], - properties: HashMap::new(), - items: Some(Box::new(type_schema)), - }; - schema.properties.insert(field.name.clone(), obj_schema); - } else { - let type_schema = schemas.get(&*field.type_) - .expect("build_dependencies returns the types in \ - the order they exist on the primary \ - type, rfold traverses the types in reverse order\ - and inserts the schema into `schemas` ;qed").clone(); - schema.properties.insert(field.name.clone(), type_schema); - } - } else { - if is_array { - let schema_mut = schema.properties.entry(field.name.clone()).or_insert(Schema { - type_: "array".into(), - required: vec![], - properties: HashMap::new(), - items: None, - }); - - schema_mut.items = Some(Box::new(Schema { - type_: get_json_type(&field.type_), - required: vec![], - properties: HashMap::new(), - items: None, - })); - } else { - schema.properties.insert(field.name.clone(), Schema { - type_: get_json_type(&field.type_), - required: vec![], - properties: HashMap::new(), - items: None, - }); - } - } - // add field names to the required array. - schema.required.push(field.name.clone()); - } - - schemas.insert(current_type, schema); - schemas - }); - - let schema = schemas.remove(&*data.primary_type) - .expect("build_dependencies would've returned ErrorKind::NonExistentType; qed"); - return Ok(to_value(schema).expect("Serialize is implemented for Schema ;qed")); -} - -pub fn validate_data(eip712: &EIP712) -> Result<()> { - let schema = build_schema(eip712)?; - let mut scope = json_schema::Scope::new(); - let r_schema = scope.compile_and_return(schema, true).ok().unwrap(); - - let validation_state = r_schema.validate(&eip712.message); - if !validation_state.is_valid() { - return Err(ErrorKind::SchemaValidationError(format!("{:?}", validation_state.errors)))? - } - Ok(()) -}