diff --git a/json/src/spec/account.rs b/json/src/spec/account.rs index 046592a71..2c98fd3f1 100644 --- a/json/src/spec/account.rs +++ b/json/src/spec/account.rs @@ -39,7 +39,7 @@ pub struct Account { } impl Account { - /// Returns true if account does not have nonce and balance. + /// Returns true if account does not have nonce, balance, code and storage. pub fn is_empty(&self) -> bool { self.balance.is_none() && self.nonce.is_none() && self.code.is_none() && self.storage.is_none() } @@ -54,6 +54,59 @@ mod tests { use uint::Uint; use bytes::Bytes; + #[test] + fn account_balance_missing_not_empty() { + let s = r#"{ + "nonce": "0", + "code": "1234", + "storage": { "0x7fffffffffffffff7fffffffffffffff": "0x1" } + }"#; + let deserialized: Account = serde_json::from_str(s).unwrap(); + assert!(!deserialized.is_empty()); + } + + #[test] + fn account_nonce_missing_not_empty() { + let s = r#"{ + "balance": "1", + "code": "1234", + "storage": { "0x7fffffffffffffff7fffffffffffffff": "0x1" } + }"#; + let deserialized: Account = serde_json::from_str(s).unwrap(); + assert!(!deserialized.is_empty()); + } + + #[test] + fn account_code_missing_not_empty() { + let s = r#"{ + "balance": "1", + "nonce": "0", + "storage": { "0x7fffffffffffffff7fffffffffffffff": "0x1" } + }"#; + let deserialized: Account = serde_json::from_str(s).unwrap(); + assert!(!deserialized.is_empty()); + } + + #[test] + fn account_storage_missing_not_empty() { + let s = r#"{ + "balance": "1", + "nonce": "0", + "code": "1234" + }"#; + let deserialized: Account = serde_json::from_str(s).unwrap(); + assert!(!deserialized.is_empty()); + } + + #[test] + fn account_empty() { + let s = r#"{ + "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } + }"#; + let deserialized: Account = serde_json::from_str(s).unwrap(); + assert!(deserialized.is_empty()); + } + #[test] fn account_deserialization() { let s = r#"{ @@ -63,6 +116,7 @@ mod tests { "code": "1234" }"#; let deserialized: Account = serde_json::from_str(s).unwrap(); + assert!(!deserialized.is_empty()); assert_eq!(deserialized.balance.unwrap(), Uint(U256::from(1))); assert_eq!(deserialized.nonce.unwrap(), Uint(U256::from(0))); assert_eq!(deserialized.code.unwrap(), Bytes::new(vec![0x12, 0x34])); @@ -78,6 +132,7 @@ mod tests { "storage": { "0x7fffffffffffffff7fffffffffffffff": "0x1" } }"#; let deserialized: Account = serde_json::from_str(s).unwrap(); + assert!(!deserialized.is_empty()); assert_eq!(deserialized.balance.unwrap(), Uint(U256::from(1))); assert_eq!(deserialized.nonce.unwrap(), Uint(U256::from(0))); assert_eq!(deserialized.code.unwrap(), Bytes::new(vec![0x12, 0x34])); diff --git a/json/src/spec/authority_round.rs b/json/src/spec/authority_round.rs index 99d138d00..ae518eebc 100644 --- a/json/src/spec/authority_round.rs +++ b/json/src/spec/authority_round.rs @@ -60,7 +60,12 @@ pub struct AuthorityRound { #[cfg(test)] mod tests { + use uint::Uint; + use util::U256; + use util::H160; use serde_json; + use hash::Address; + use spec::validator_set::ValidatorSet; use spec::authority_round::AuthorityRound; #[test] @@ -79,6 +84,13 @@ mod tests { } }"#; - let _deserialized: AuthorityRound = serde_json::from_str(s).unwrap(); + let deserialized: AuthorityRound = serde_json::from_str(s).unwrap(); + assert_eq!(deserialized.params.gas_limit_bound_divisor, Uint(U256::from(0x0400))); + assert_eq!(deserialized.params.step_duration, Uint(U256::from(0x02))); + assert_eq!(deserialized.params.validators, ValidatorSet::List(vec![Address(H160::from("0xc6d9d2cd449a754c494264e1809c50e34d64562b"))])); + assert_eq!(deserialized.params.block_reward, Some(Uint(U256::from(0x50)))); + assert!(deserialized.params.registrar.is_none()); + assert_eq!(deserialized.params.start_step, Some(Uint(U256::from(24)))); + assert_eq!(deserialized.params.eip155_transition, Some(Uint(U256::from(0x42)))); } } diff --git a/json/src/spec/basic_authority.rs b/json/src/spec/basic_authority.rs index 06f50268e..01fe8f088 100644 --- a/json/src/spec/basic_authority.rs +++ b/json/src/spec/basic_authority.rs @@ -42,7 +42,12 @@ pub struct BasicAuthority { #[cfg(test)] mod tests { use serde_json; + use uint::Uint; + use util::U256; + use hash::Address; + use util::hash::H160; use spec::basic_authority::BasicAuthority; + use spec::validator_set::ValidatorSet; #[test] fn basic_authority_deserialization() { @@ -56,6 +61,11 @@ mod tests { } }"#; - let _deserialized: BasicAuthority = serde_json::from_str(s).unwrap(); + let deserialized: BasicAuthority = serde_json::from_str(s).unwrap(); + + assert_eq!(deserialized.params.gas_limit_bound_divisor, Uint(U256::from(0x0400))); + assert_eq!(deserialized.params.duration_limit, Uint(U256::from(0x0d))); + let vs = ValidatorSet::List(vec![Address(H160::from("0xc6d9d2cd449a754c494264e1809c50e34d64562b"))]); + assert_eq!(deserialized.params.validators, vs); } } diff --git a/json/src/spec/engine.rs b/json/src/spec/engine.rs index ef54c4ab1..5706b0680 100644 --- a/json/src/spec/engine.rs +++ b/json/src/spec/engine.rs @@ -58,7 +58,11 @@ mod tests { "instantSeal": { "params": {} } }"#; - let _deserialized: Engine = serde_json::from_str(s).unwrap(); + let deserialized: Engine = serde_json::from_str(s).unwrap(); + match deserialized { + Engine::InstantSeal(_) => {}, // instant seal is unit tested in its own file. + _ => assert!(false), + }; let s = r#"{ "Ethash": { @@ -77,7 +81,66 @@ mod tests { } }"#; - let _deserialized: Engine = serde_json::from_str(s).unwrap(); + let deserialized: Engine = serde_json::from_str(s).unwrap(); + match deserialized { + Engine::Ethash(_) => {}, // ethash is unit tested in its own file. + _ => assert!(false), + }; + + let s = r#"{ + "basicAuthority": { + "params": { + "gasLimitBoundDivisor": "0x0400", + "durationLimit": "0x0d", + "validators" : { + "list": ["0xc6d9d2cd449a754c494264e1809c50e34d64562b"] + } + } + } + }"#; + let deserialized: Engine = serde_json::from_str(s).unwrap(); + match deserialized { + Engine::BasicAuthority(_) => {}, // basicAuthority is unit tested in its own file. + _ => assert!(false), + }; + + let s = r#"{ + "authorityRound": { + "params": { + "gasLimitBoundDivisor": "0x0400", + "stepDuration": "0x02", + "validators": { + "list" : ["0xc6d9d2cd449a754c494264e1809c50e34d64562b"] + }, + "blockReward": "0x50", + "startStep" : 24, + "eip155Transition": "0x42", + "validateStepTransition": 150 + } + } + }"#; + let deserialized: Engine = serde_json::from_str(s).unwrap(); + match deserialized { + Engine::AuthorityRound(_) => {}, // AuthorityRound is unit tested in its own file. + _ => assert!(false), + }; + + let s = r#"{ + "tendermint": { + "params": { + "gasLimitBoundDivisor": "0x0400", + "validators": { + "list": ["0xc6d9d2cd449a754c494264e1809c50e34d64562b"] + }, + "blockReward": "0x50" + } + } + }"#; + let deserialized: Engine = serde_json::from_str(s).unwrap(); + match deserialized { + Engine::Tendermint(_) => {}, // Tendermint is unit tested in its own file. + _ => assert!(false), + }; } } diff --git a/json/src/spec/ethash.rs b/json/src/spec/ethash.rs index 16d05a18f..926dcacee 100644 --- a/json/src/spec/ethash.rs +++ b/json/src/spec/ethash.rs @@ -131,7 +131,11 @@ pub struct Ethash { #[cfg(test)] mod tests { use serde_json; - use spec::ethash::Ethash; + use uint::Uint; + use util::U256; + use hash::Address; + use util::hash::H160; + use spec::ethash::{Ethash, EthashParams}; #[test] fn ethash_deserialization() { @@ -170,17 +174,71 @@ mod tests { ], "difficultyHardforkTransition": "0x59d9", "difficultyHardforkBoundDivisor": "0x0200", - "bombDefuseTransition": "0x42", + "bombDefuseTransition": "0x41", "eip100bTransition": "0x42", - "eip150Transition": "0x42", - "eip155Transition": "0x42", - "eip160Transition": "0x42", - "eip161abcTransition": "0x42", - "eip161dTransition": "0x42" + "eip150Transition": "0x43", + "eip155Transition": "0x44", + "eip160Transition": "0x45", + "eip161abcTransition": "0x46", + "eip161dTransition": "0x47" } }"#; - let _deserialized: Ethash = serde_json::from_str(s).unwrap(); + let deserialized: Ethash = serde_json::from_str(s).unwrap(); + + assert_eq!(deserialized, Ethash{ + params: EthashParams{ + gas_limit_bound_divisor: Uint(U256::from(0x0400)), + minimum_difficulty: Uint(U256::from(0x020000)), + difficulty_bound_divisor: Uint(U256::from(0x0800)), + difficulty_increment_divisor: None, + metropolis_difficulty_increment_divisor: None, + duration_limit: Uint(U256::from(0x0d)), + block_reward: Uint(U256::from(0x4563918244F40000u64)), + registrar: Some(Address(H160::from("0xc6d9d2cd449a754c494264e1809c50e34d64562b"))), + homestead_transition: Some(Uint(U256::from(0x42))), + dao_hardfork_transition: Some(Uint(U256::from(0x08))), + dao_hardfork_beneficiary: Some(Address(H160::from("0xabcabcabcabcabcabcabcabcabcabcabcabcabca"))), + dao_hardfork_accounts: Some(vec![ + Address(H160::from("0x304a554a310c7e546dfe434669c62820b7d83490")), + Address(H160::from("0x914d1b8b43e92723e64fd0a06f5bdb8dd9b10c79")), + Address(H160::from("0xfe24cdd8648121a43a7c86d289be4dd2951ed49f")), + Address(H160::from("0x17802f43a0137c506ba92291391a8a8f207f487d")), + Address(H160::from("0xb136707642a4ea12fb4bae820f03d2562ebff487")), + Address(H160::from("0xdbe9b615a3ae8709af8b93336ce9b477e4ac0940")), + Address(H160::from("0xf14c14075d6c4ed84b86798af0956deef67365b5")), + Address(H160::from("0xca544e5c4687d109611d0f8f928b53a25af72448")), + Address(H160::from("0xaeeb8ff27288bdabc0fa5ebb731b6f409507516c")), + Address(H160::from("0xcbb9d3703e651b0d496cdefb8b92c25aeb2171f7")), + Address(H160::from("0xaccc230e8a6e5be9160b8cdf2864dd2a001c28b6")), + Address(H160::from("0x2b3455ec7fedf16e646268bf88846bd7a2319bb2")), + Address(H160::from("0x4613f3bca5c44ea06337a9e439fbc6d42e501d0a")), + Address(H160::from("0xd343b217de44030afaa275f54d31a9317c7f441e")), + Address(H160::from("0x84ef4b2357079cd7a7c69fd7a37cd0609a679106")), + Address(H160::from("0xda2fef9e4a3230988ff17df2165440f37e8b1708")), + Address(H160::from("0xf4c64518ea10f995918a454158c6b61407ea345c")), + Address(H160::from("0x7602b46df5390e432ef1c307d4f2c9ff6d65cc97")), + Address(H160::from("0xbb9bc244d798123fde783fcc1c72d3bb8c189413")), + Address(H160::from("0x807640a13483f8ac783c557fcdf27be11ea4ac7a")), + ]), + difficulty_hardfork_transition: Some(Uint(U256::from(0x59d9))), + difficulty_hardfork_bound_divisor: Some(Uint(U256::from(0x0200))), + bomb_defuse_transition: Some(Uint(U256::from(0x41))), + eip100b_transition: Some(Uint(U256::from(0x42))), + eip150_transition: Some(Uint(U256::from(0x43))), + eip155_transition: Some(Uint(U256::from(0x44))), + eip160_transition: Some(Uint(U256::from(0x45))), + eip161abc_transition: Some(Uint(U256::from(0x46))), + eip161d_transition: Some(Uint(U256::from(0x47))), + ecip1010_pause_transition: None, + ecip1010_continue_transition: None, + max_code_size: None, + max_gas_limit_transition: None, + max_gas_limit: None, + min_gas_price_transition: None, + min_gas_price: None, + } + }); } #[test] @@ -195,6 +253,38 @@ mod tests { } }"#; - let _deserialized: Ethash = serde_json::from_str(s).unwrap(); + let deserialized: Ethash = serde_json::from_str(s).unwrap(); + assert_eq!(deserialized, Ethash{ + params: EthashParams{ + gas_limit_bound_divisor: Uint(U256::from(0x0400)), + minimum_difficulty: Uint(U256::from(0x020000)), + difficulty_bound_divisor: Uint(U256::from(0x0800)), + difficulty_increment_divisor: None, + metropolis_difficulty_increment_divisor: None, + duration_limit: Uint(U256::from(0x0d)), + block_reward: Uint(U256::from(0x4563918244F40000u64)), + registrar: None, + homestead_transition: None, + dao_hardfork_transition: None, + dao_hardfork_beneficiary: None, + dao_hardfork_accounts: None, + difficulty_hardfork_transition: None, + difficulty_hardfork_bound_divisor: None, + bomb_defuse_transition: None, + eip100b_transition: None, + eip150_transition: None, + eip155_transition: None, + eip160_transition: None, + eip161abc_transition: None, + eip161d_transition: None, + ecip1010_pause_transition: None, + ecip1010_continue_transition: None, + max_code_size: None, + max_gas_limit_transition: None, + max_gas_limit: None, + min_gas_price_transition: None, + min_gas_price: None, + } + }); } } diff --git a/json/src/spec/genesis.rs b/json/src/spec/genesis.rs index 6f69f8c14..120df4fc1 100644 --- a/json/src/spec/genesis.rs +++ b/json/src/spec/genesis.rs @@ -58,7 +58,15 @@ pub struct Genesis { #[cfg(test)] mod tests { use serde_json; + use bytes::Bytes; + use uint::Uint; + use util::U256; + use hash::{H64, H256, Address}; + use util::hash::H160; + use util::{H64 as Eth64, H256 as Eth256}; use spec::genesis::Genesis; + use spec::{Ethereum, Seal}; + use std::str::FromStr; #[test] fn genesis_deserialization() { @@ -71,14 +79,29 @@ mod tests { "nonce": "0x00006d6f7264656e" } }, - "author": "0x0000000000000000000000000000000000000000", - "timestamp": "0x00", - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "author": "0x1000000000000000000000000000000000000001", + "timestamp": "0x07", + "parentHash": "0x9000000000000000000000000000000000000000000000000000000000000000", "extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa", "gasLimit": "0x1388", "stateRoot": "0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544" }"#; - let _deserialized: Genesis = serde_json::from_str(s).unwrap(); - // TODO: validate all fields + let deserialized: Genesis = serde_json::from_str(s).unwrap(); + assert_eq!(deserialized, Genesis { + seal: Seal::Ethereum(Ethereum { + nonce: H64(Eth64::from("0x00006d6f7264656e")), + mix_hash: H256(Eth256::from("0x0000000000000000000000000000000000000000000000000000000000000000")) + }), + difficulty: Uint(U256::from(0x400000000u64)), + author: Some(Address(H160::from("0x1000000000000000000000000000000000000001"))), + timestamp: Some(Uint(U256::from(0x07))), + parent_hash: Some(H256(Eth256::from("0x9000000000000000000000000000000000000000000000000000000000000000"))), + gas_limit: Uint(U256::from(0x1388)), + transactions_root: None, + receipts_root: None, + state_root: Some(H256(Eth256::from("0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544"))), + gas_used: None, + extra_data: Some(Bytes::from_str("0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa").unwrap()), + }); } } diff --git a/json/src/spec/instant_seal.rs b/json/src/spec/instant_seal.rs index 168b51c68..ebf167d28 100644 --- a/json/src/spec/instant_seal.rs +++ b/json/src/spec/instant_seal.rs @@ -35,6 +35,8 @@ pub struct InstantSeal { #[cfg(test)] mod tests { use serde_json; + use hash::Address; + use util::hash::H160; use spec::instant_seal::InstantSeal; #[test] @@ -45,6 +47,7 @@ mod tests { } }"#; - let _deserialized: InstantSeal = serde_json::from_str(s).unwrap(); + let deserialized: InstantSeal = serde_json::from_str(s).unwrap(); + assert_eq!(deserialized.params.registrar, Some(Address(H160::from("0xc6d9d2cd449a754c494264e1809c50e34d64562b")))); } } diff --git a/json/src/spec/params.rs b/json/src/spec/params.rs index 31b5cf68a..d546ad86b 100644 --- a/json/src/spec/params.rs +++ b/json/src/spec/params.rs @@ -64,21 +64,27 @@ pub struct Params { #[cfg(test)] mod tests { use serde_json; + use uint::Uint; + use util::U256; use spec::params::Params; #[test] fn params_deserialization() { let s = r#"{ - "homesteadTransition": "0x118c30", "maximumExtraDataSize": "0x20", "networkID" : "0x1", "chainID" : "0x15", "subprotocolName" : "exp", "minGasLimit": "0x1388", - "accountStartNonce": "0x00" + "accountStartNonce": "0x01" }"#; - let _deserialized: Params = serde_json::from_str(s).unwrap(); - // TODO: validate all fields + let deserialized: Params = serde_json::from_str(s).unwrap(); + assert_eq!(deserialized.maximum_extra_data_size, Uint(U256::from(0x20))); + assert_eq!(deserialized.network_id, Uint(U256::from(0x1))); + assert_eq!(deserialized.chain_id, Some(Uint(U256::from(0x15)))); + assert_eq!(deserialized.subprotocol_name, Some("exp".to_owned())); + assert_eq!(deserialized.min_gas_limit, Uint(U256::from(0x1388))); + assert_eq!(deserialized.account_start_nonce, Some(Uint(U256::from(0x01)))); } } diff --git a/json/src/spec/seal.rs b/json/src/spec/seal.rs index 247bceb22..7345a623d 100644 --- a/json/src/spec/seal.rs +++ b/json/src/spec/seal.rs @@ -70,32 +70,62 @@ pub enum Seal { #[cfg(test)] mod tests { use serde_json; - use spec::Seal; + use hash::*; + use bytes::Bytes; + use uint::Uint; + use util::U256; + use util::{H64 as Eth64, H256 as Eth256, H520 as Eth520}; + use spec::{Ethereum, AuthorityRoundSeal, TendermintSeal, Seal}; #[test] fn seal_deserialization() { let s = r#"[{ "ethereum": { "nonce": "0x0000000000000042", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000" + "mixHash": "0x1000000000000000000000000000000000000000000000000000000000000001" } },{ "generic": "0xe011bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa" },{ "authorityRound": { "step": "0x0", - "signature": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + "signature": "0x2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002" } },{ "tendermint": { - "round": "0x0", - "proposal": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "round": "0x3", + "proposal": "0x3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003", "precommits": [ - "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + "0x4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004" ] } }]"#; - let _deserialized: Vec = serde_json::from_str(s).unwrap(); - // TODO: validate all fields + + let deserialized: Vec = serde_json::from_str(s).unwrap(); + assert_eq!(deserialized.len(), 4); + + // [0] + assert_eq!(deserialized[0], Seal::Ethereum(Ethereum { + nonce: H64(Eth64::from("0x0000000000000042")), + mix_hash: H256(Eth256::from("0x1000000000000000000000000000000000000000000000000000000000000001")) + })); + + // [1] + assert_eq!(deserialized[1], Seal::Generic(Bytes::new(vec![ + 0xe0, 0x11, 0xbb, 0xe8, 0xdb, 0x4e, 0x34, 0x7b, 0x4e, 0x8c, 0x93, 0x7c, 0x1c, 0x83, 0x70, 0xe4, + 0xb5, 0xed, 0x33, 0xad, 0xb3, 0xdb, 0x69, 0xcb, 0xdb, 0x7a, 0x38, 0xe1, 0xe5, 0x0b, 0x1b, 0x82, 0xfa]))); + + // [2] + assert_eq!(deserialized[2], Seal::AuthorityRound(AuthorityRoundSeal { + step: Uint(U256::from(0x0)), + signature: H520(Eth520::from("0x2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002")) + })); + + // [3] + assert_eq!(deserialized[3], Seal::Tendermint(TendermintSeal { + round: Uint(U256::from(0x3)), + proposal: H520(Eth520::from("0x3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003")), + precommits: vec![H520(Eth520::from("0x4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004"))] + })); } } diff --git a/json/src/spec/tendermint.rs b/json/src/spec/tendermint.rs index 16c2d7255..5a15a0841 100644 --- a/json/src/spec/tendermint.rs +++ b/json/src/spec/tendermint.rs @@ -57,7 +57,12 @@ pub struct Tendermint { #[cfg(test)] mod tests { use serde_json; + use uint::Uint; + use util::U256; + use hash::Address; + use util::hash::H160; use spec::tendermint::Tendermint; + use spec::validator_set::ValidatorSet; #[test] fn tendermint_deserialization() { @@ -71,6 +76,10 @@ mod tests { } }"#; - let _deserialized: Tendermint = serde_json::from_str(s).unwrap(); + let deserialized: Tendermint = serde_json::from_str(s).unwrap(); + assert_eq!(deserialized.params.gas_limit_bound_divisor, Uint(U256::from(0x0400))); + let vs = ValidatorSet::List(vec![Address(H160::from("0xc6d9d2cd449a754c494264e1809c50e34d64562b"))]); + assert_eq!(deserialized.params.validators, vs); + assert_eq!(deserialized.params.block_reward, Some(Uint(U256::from(0x50)))); } } diff --git a/json/src/spec/validator_set.rs b/json/src/spec/validator_set.rs index f433caa03..abcb35848 100644 --- a/json/src/spec/validator_set.rs +++ b/json/src/spec/validator_set.rs @@ -40,6 +40,10 @@ pub enum ValidatorSet { #[cfg(test)] mod tests { use serde_json; + use uint::Uint; + use util::U256; + use hash::Address; + use util::hash::H160; use spec::validator_set::ValidatorSet; #[test] @@ -58,6 +62,20 @@ mod tests { } }]"#; - let _deserialized: Vec = serde_json::from_str(s).unwrap(); + let deserialized: Vec = serde_json::from_str(s).unwrap(); + assert_eq!(deserialized.len(), 4); + + assert_eq!(deserialized[0], ValidatorSet::List(vec![Address(H160::from("0xc6d9d2cd449a754c494264e1809c50e34d64562b"))])); + assert_eq!(deserialized[1], ValidatorSet::SafeContract(Address(H160::from("0xc6d9d2cd449a754c494264e1809c50e34d64562b")))); + assert_eq!(deserialized[2], ValidatorSet::Contract(Address(H160::from("0xc6d9d2cd449a754c494264e1809c50e34d64562b")))); + match deserialized[3] { + ValidatorSet::Multi(ref map) => { + assert_eq!(map.len(), 3); + assert!(map.contains_key(&Uint(U256::from(0)))); + assert!(map.contains_key(&Uint(U256::from(10)))); + assert!(map.contains_key(&Uint(U256::from(20)))); + }, + _ => assert!(false), + } } }