diff --git a/ethcore/src/block.rs b/ethcore/src/block.rs index d4aa35445..e53cbfd61 100644 --- a/ethcore/src/block.rs +++ b/ethcore/src/block.rs @@ -438,7 +438,7 @@ mod tests { open_block.push_uncle(uncle1_header).unwrap(); open_block.push_uncle(uncle2_header).unwrap(); let b = open_block.close().seal(engine.deref(), vec![]).unwrap(); - + let orig_bytes = b.rlp_bytes(); let orig_db = b.drain(); diff --git a/ethcore/src/json_tests/chain.rs b/ethcore/src/json_tests/chain.rs index 89bd5da2b..a2e6a5659 100644 --- a/ethcore/src/json_tests/chain.rs +++ b/ethcore/src/json_tests/chain.rs @@ -16,18 +16,19 @@ use super::test_common::*; use client::{BlockChainClient, Client, ClientConfig}; -use pod_state::*; use block::Block; use ethereum; use tests::helpers::*; use devtools::*; +use spec::Genesis; +use ethjson; pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec { init_log(); - let json = Json::from_str(::std::str::from_utf8(json_data).unwrap()).expect("Json is invalid"); + let tests = ethjson::blockchain::Test::load(json_data).unwrap(); let mut failed = Vec::new(); - for (name, test) in json.as_object().unwrap() { + for (name, blockchain) in tests.deref() { let mut fail = false; { let mut fail_unless = |cond: bool| if !cond && !fail { @@ -39,37 +40,36 @@ pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec { flush!(" - {}...", name); - let blocks: Vec<(Bytes, bool)> = test["blocks"].as_array().unwrap().iter().map(|e| (xjson!(&e["rlp"]), e.find("blockHeader").is_some())).collect(); let mut spec = match era { ChainEra::Frontier => ethereum::new_frontier_test(), ChainEra::Homestead => ethereum::new_homestead_test(), }; - let s = PodState::from_json(test.find("pre").unwrap()); - spec.set_genesis_state(s); - spec.overwrite_genesis(test.find("genesisBlockHeader").unwrap()); + + let genesis = Genesis::from(blockchain.genesis()); + let state = From::from(blockchain.pre_state.clone()); + spec.set_genesis_state(state); + spec.overwrite_genesis_params(genesis); assert!(spec.is_state_root_valid()); - let genesis_hash = spec.genesis_header().hash(); - assert_eq!(genesis_hash, H256::from_json(&test.find("genesisBlockHeader").unwrap()["hash"])); let temp = RandomTempPath::new(); { let client = Client::new(ClientConfig::default(), spec, temp.as_path(), IoChannel::disconnected()).unwrap(); - assert_eq!(client.chain_info().best_block_hash, genesis_hash); - for (b, is_valid) in blocks.into_iter() { + for b in &blockchain.blocks_rlp() { if Block::is_good(&b) { let _ = client.import_block(b.clone()); + client.flush_queue(); + client.import_verified_blocks(&IoChannel::disconnected()); } - client.flush_queue(); - let imported_ok = client.import_verified_blocks(&IoChannel::disconnected()) > 0; - assert_eq!(imported_ok, is_valid); } - fail_unless(client.chain_info().best_block_hash == H256::from_json(&test["lastblockhash"])); + fail_unless(client.chain_info().best_block_hash == blockchain.best_block.clone().into()); } } + if !fail { flushln!("ok"); } } + println!("!!! {:?} tests from failed.", failed.len()); failed } diff --git a/ethcore/src/pod_account.rs b/ethcore/src/pod_account.rs index 8f38326ca..387679da9 100644 --- a/ethcore/src/pod_account.rs +++ b/ethcore/src/pod_account.rs @@ -82,7 +82,8 @@ impl From for PodAccount { code: a.code.into(), storage: a.storage.into_iter().fold(BTreeMap::new(), |mut acc, (key, value)| { let key: U256 = key.into(); - acc.insert(H256::from(key), value.into()); + let value: U256 = value.into(); + acc.insert(H256::from(key), H256::from(value)); acc }) } diff --git a/ethcore/src/pod_state.rs b/ethcore/src/pod_state.rs index 5782803ef..7ebfed78b 100644 --- a/ethcore/src/pod_state.rs +++ b/ethcore/src/pod_state.rs @@ -21,7 +21,7 @@ use pod_account::*; use ethjson; /// State of all accounts in the system expressed in Plain Old Data. -#[derive(Debug,Clone,PartialEq,Eq,Default)] +#[derive(Debug, Clone, PartialEq, Eq, Default)] pub struct PodState (BTreeMap); impl PodState { diff --git a/json/src/blockchain/account.rs b/json/src/blockchain/account.rs index 990c024c7..ca69409fc 100644 --- a/json/src/blockchain/account.rs +++ b/json/src/blockchain/account.rs @@ -19,7 +19,6 @@ use std::collections::BTreeMap; use uint::Uint; use bytes::Bytes; -use hash::H256; /// Blockchain test account deserializer. #[derive(Debug, PartialEq, Deserialize, Clone)] @@ -31,7 +30,7 @@ pub struct Account { /// Nonce. pub nonce: Uint, /// Storage. - pub storage: BTreeMap, + pub storage: BTreeMap, } #[cfg(test)] diff --git a/json/src/blockchain/block.rs b/json/src/blockchain/block.rs index 190102ae5..03522a2c9 100644 --- a/json/src/blockchain/block.rs +++ b/json/src/blockchain/block.rs @@ -24,11 +24,11 @@ use blockchain::transaction::Transaction; #[derive(Debug, PartialEq, Deserialize)] pub struct Block { #[serde(rename="blockHeader")] - header: Header, + header: Option
, rlp: Bytes, - transactions: Vec, + transactions: Option>, #[serde(rename="uncleHeaders")] - uncles: Vec
, + uncles: Option>, } impl Block { diff --git a/json/src/blockchain/blockchain.rs b/json/src/blockchain/blockchain.rs index 4783819e5..98392b983 100644 --- a/json/src/blockchain/blockchain.rs +++ b/json/src/blockchain/blockchain.rs @@ -17,6 +17,7 @@ //! Blockchain deserialization. use bytes::Bytes; +use hash::H256; use blockchain::state::State; use blockchain::header::Header; use blockchain::block::Block; @@ -30,7 +31,7 @@ pub struct BlockChain { pub genesis_block: Header, /// Genesis block rlp. #[serde(rename="genesisRLP")] - pub genesis_rlp: Bytes, + pub genesis_rlp: Option, /// Blocks. pub blocks: Vec, /// Post state. @@ -39,14 +40,12 @@ pub struct BlockChain { /// Pre state. #[serde(rename="pre")] pub pre_state: State, + /// Hash of best block. + #[serde(rename="lastblockhash")] + pub best_block: H256 } impl BlockChain { - /// Returns genesis block rlp. - pub fn genesis_rlp(&self) -> Vec { - self.genesis_rlp.clone().into() - } - /// Returns blocks rlp. pub fn blocks_rlp(&self) -> Vec> { self.blocks.iter().map(|block| block.rlp()).collect() diff --git a/json/src/blockchain/test.rs b/json/src/blockchain/test.rs index 6f48a8bc6..1a6a63a71 100644 --- a/json/src/blockchain/test.rs +++ b/json/src/blockchain/test.rs @@ -18,6 +18,9 @@ use std::collections::BTreeMap; use std::ops::Deref; +use std::io::Read; +use serde_json; +use serde_json::Error; use blockchain::blockchain::BlockChain; /// Blockchain test deserializer. @@ -31,3 +34,10 @@ impl Deref for Test { &self.0 } } + +impl Test { + /// Loads test from json. + pub fn load(reader: R) -> Result where R: Read { + serde_json::from_reader(reader) + } +} diff --git a/json/src/bytes.rs b/json/src/bytes.rs index 061795b40..6ccae51d7 100644 --- a/json/src/bytes.rs +++ b/json/src/bytes.rs @@ -46,12 +46,8 @@ impl Visitor for BytesVisitor { let v = match value.len() { 0 => vec![], 2 if value.starts_with("0x") => vec![], - _ if value.starts_with("0x") => try!(FromHex::from_hex(&value[2..]).map_err(|_| { - Error::custom(format!("Invalid hex value {}.", value).as_ref()) - })), - _ => try!(FromHex::from_hex(value).map_err(|_| { - Error::custom(format!("Invalid hex value {}.", value).as_ref()) - })) + _ if value.starts_with("0x") => FromHex::from_hex(&value[2..]).unwrap_or(vec![]), + _ => FromHex::from_hex(value).unwrap_or(vec![]), }; Ok(Bytes(v)) } diff --git a/parity/rpctest.rs b/parity/rpctest.rs index 4fd31b134..6cc747959 100644 --- a/parity/rpctest.rs +++ b/parity/rpctest.rs @@ -37,9 +37,10 @@ use ethcore::ethereum; use ethcore::client::{BlockChainClient, Client, ClientConfig}; use devtools::RandomTempPath; use util::IoChannel; -use rpc::v1::tests::helpers::{TestSyncProvider, Config as SyncConfig, TestMinerService, TestAccountProvider}; -use rpc::v1::{Eth, EthClient}; +use rpc::v1::tests::helpers::{TestSyncProvider, Config as SyncConfig, TestMinerService, TestAccountProvider, TestAccount}; +use rpc::v1::{Eth, EthClient, EthFilter, EthFilterClient}; use util::panics::MayPanic; +use util::hash::Address; const USAGE: &'static str = r#" Parity rpctest client. @@ -86,8 +87,9 @@ impl Configuration { process::exit(1); }); - let tests: ethjson::blockchain::Test = serde_json::from_reader(file).unwrap_or_else(|_| { + let tests: ethjson::blockchain::Test = serde_json::from_reader(file).unwrap_or_else(|err| { println!("Invalid json file."); + println!("{:?}", err); process::exit(2); }); @@ -117,9 +119,12 @@ impl Configuration { })); let miner = Arc::new(TestMinerService::default()); - let accounts = Arc::new(TestAccountProvider::new(HashMap::new())); + let mut accs = HashMap::new(); + accs.insert(Address::from(1), TestAccount::new("test")); + let accounts = Arc::new(TestAccountProvider::new(accs)); let server = rpc::RpcServer::new(); server.add_delegate(EthClient::new(&client, &sync, &accounts, &miner).to_delegate()); + server.add_delegate(EthFilterClient::new(&client, &miner).to_delegate()); let url = format!("{}:{}", self.args.flag_jsonrpc_addr, self.args.flag_jsonrpc_port); let panic_handler = server.start_http(url.as_ref(), "*", 1); diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 7fa12295d..3daa6275c 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -103,7 +103,8 @@ impl EthClient timestamp: U256::from(view.timestamp()), difficulty: view.difficulty(), total_difficulty: total_difficulty, - uncles: vec![], + nonce: view.seal().get(1).map_or_else(H64::zero, |r| H64::from_slice(r)), + uncles: block_view.uncle_hashes(), transactions: { if include_txs { BlockTransactions::Full(block_view.localized_transactions().into_iter().map(From::from).collect()) @@ -111,7 +112,7 @@ impl EthClient BlockTransactions::Hashes(block_view.transaction_hashes()) } }, - extra_data: Bytes::default() + extra_data: Bytes::new(view.extra_data()) }; to_value(&block) }, @@ -229,8 +230,8 @@ impl Eth for EthClient fn block_transaction_count_by_hash(&self, params: Params) -> Result { from_params::<(H256,)>(params) .and_then(|(hash,)| // match - to_value(&take_weak!(self.client).block(BlockId::Hash(hash)) - .map_or_else(U256::zero, |bytes| U256::from(BlockView::new(&bytes).transactions_count())))) + take_weak!(self.client).block(BlockId::Hash(hash)) + .map_or(Ok(Value::Null), |bytes| to_value(&U256::from(BlockView::new(&bytes).transactions_count())))) } fn block_transaction_count_by_number(&self, params: Params) -> Result { @@ -239,24 +240,24 @@ impl Eth for EthClient BlockNumber::Pending => to_value( &U256::from(take_weak!(self.miner).status().transactions_in_pending_block) ), - _ => to_value(&take_weak!(self.client).block(block_number.into()) - .map_or_else(U256::zero, |bytes| U256::from(BlockView::new(&bytes).transactions_count()))) + _ => take_weak!(self.client).block(block_number.into()) + .map_or(Ok(Value::Null), |bytes| to_value(&U256::from(BlockView::new(&bytes).transactions_count()))) }) } fn block_uncles_count_by_hash(&self, params: Params) -> Result { from_params::<(H256,)>(params) .and_then(|(hash,)| - to_value(&take_weak!(self.client).block(BlockId::Hash(hash)) - .map_or_else(U256::zero, |bytes| U256::from(BlockView::new(&bytes).uncles_count())))) + take_weak!(self.client).block(BlockId::Hash(hash)) + .map_or(Ok(Value::Null), |bytes| to_value(&U256::from(BlockView::new(&bytes).uncles_count())))) } fn block_uncles_count_by_number(&self, params: Params) -> Result { from_params::<(BlockNumber,)>(params) .and_then(|(block_number,)| match block_number { BlockNumber::Pending => to_value(&U256::from(0)), - _ => to_value(&take_weak!(self.client).block(block_number.into()) - .map_or_else(U256::zero, |bytes| U256::from(BlockView::new(&bytes).uncles_count()))) + _ => take_weak!(self.client).block(block_number.into()) + .map_or(Ok(Value::Null), |bytes| to_value(&U256::from(BlockView::new(&bytes).uncles_count()))) }) } diff --git a/rpc/src/v1/tests/eth.rs b/rpc/src/v1/tests/eth.rs index 389de103b..a5f318350 100644 --- a/rpc/src/v1/tests/eth.rs +++ b/rpc/src/v1/tests/eth.rs @@ -224,7 +224,7 @@ fn rpc_eth_block_transaction_count_by_hash() { "params": ["0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"], "id": 1 }"#; - let response = r#"{"jsonrpc":"2.0","result":"0x00","id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":null,"id":1}"#; assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned())); } @@ -264,7 +264,7 @@ fn rpc_eth_uncle_count_by_block_hash() { "params": ["0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"], "id": 1 }"#; - let response = r#"{"jsonrpc":"2.0","result":"0x00","id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":null,"id":1}"#; assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned())); } diff --git a/rpc/src/v1/tests/helpers/miner_service.rs b/rpc/src/v1/tests/helpers/miner_service.rs index 22e210392..7f07341bf 100644 --- a/rpc/src/v1/tests/helpers/miner_service.rs +++ b/rpc/src/v1/tests/helpers/miner_service.rs @@ -57,7 +57,7 @@ impl MinerService for TestMinerService { where T: Fn(&Address) -> AccountDetails { unimplemented!(); } /// Returns hashes of transactions currently in pending - fn pending_transactions_hashes(&self) -> Vec { unimplemented!(); } + fn pending_transactions_hashes(&self) -> Vec { vec![] } /// Removes all transactions from the queue and restart mining operation. fn clear_and_reset(&self, _chain: &BlockChainClient) { unimplemented!(); } diff --git a/rpc/src/v1/types/block.rs b/rpc/src/v1/types/block.rs index 2457efcf8..ac334dd2b 100644 --- a/rpc/src/v1/types/block.rs +++ b/rpc/src/v1/types/block.rs @@ -63,7 +63,8 @@ pub struct Block { pub difficulty: U256, #[serde(rename="totalDifficulty")] pub total_difficulty: U256, - pub uncles: Vec, + pub nonce: H64, + pub uncles: Vec, pub transactions: BlockTransactions } @@ -78,7 +79,7 @@ mod tests { fn test_serialize_block_transactions() { let t = BlockTransactions::Full(vec![Transaction::default()]); let serialized = serde_json::to_string(&t).unwrap(); - assert_eq!(serialized, r#"[{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x00","blockHash":null,"blockNumber":null,"transactionIndex":null,"from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x00","gasPrice":"0x00","gas":"0x00","input":"0x00"}]"#); + assert_eq!(serialized, r#"[{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x00","blockHash":null,"blockNumber":null,"transactionIndex":null,"from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x00","gasPrice":"0x00","gas":"0x00","input":"0x"}]"#); let t = BlockTransactions::Hashes(vec![H256::default()]); let serialized = serde_json::to_string(&t).unwrap(); @@ -104,11 +105,12 @@ mod tests { timestamp: U256::default(), difficulty: U256::default(), total_difficulty: U256::default(), + nonce: H64::default(), uncles: vec![], transactions: BlockTransactions::Hashes(vec![]) }; let serialized = serde_json::to_string(&block).unwrap(); - assert_eq!(serialized, r#"{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000","sha3Uncles":"0x0000000000000000000000000000000000000000000000000000000000000000","author":"0x0000000000000000000000000000000000000000","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionsRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","receiptsRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","number":"0x00","gasUsed":"0x00","gasLimit":"0x00","extraData":"0x00","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","timestamp":"0x00","difficulty":"0x00","totalDifficulty":"0x00","uncles":[],"transactions":[]}"#); + assert_eq!(serialized, r#"{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000","sha3Uncles":"0x0000000000000000000000000000000000000000000000000000000000000000","author":"0x0000000000000000000000000000000000000000","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionsRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","receiptsRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","number":"0x00","gasUsed":"0x00","gasLimit":"0x00","extraData":"0x","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","timestamp":"0x00","difficulty":"0x00","totalDifficulty":"0x00","nonce":"0x0000000000000000","uncles":[],"transactions":[]}"#); } } diff --git a/rpc/src/v1/types/bytes.rs b/rpc/src/v1/types/bytes.rs index 0b14c30e8..8c47806f8 100644 --- a/rpc/src/v1/types/bytes.rs +++ b/rpc/src/v1/types/bytes.rs @@ -20,7 +20,7 @@ use serde::de::Visitor; use util::common::FromHex; /// Wrapper structure around vector of bytes. -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Default)] pub struct Bytes(Vec); impl Bytes { @@ -31,13 +31,6 @@ impl Bytes { pub fn to_vec(self) -> Vec { let Bytes(x) = self; x } } -impl Default for Bytes { - fn default() -> Self { - // default serialized value is 0x00 - Bytes(vec![0]) - } -} - impl Serialize for Bytes { fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer { diff --git a/rpc/src/v1/types/transaction.rs b/rpc/src/v1/types/transaction.rs index 232cf0bf3..d809d19b4 100644 --- a/rpc/src/v1/types/transaction.rs +++ b/rpc/src/v1/types/transaction.rs @@ -67,7 +67,7 @@ mod tests { fn test_transaction_serialize() { let t = Transaction::default(); let serialized = serde_json::to_string(&t).unwrap(); - assert_eq!(serialized, r#"{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x00","blockHash":null,"blockNumber":null,"transactionIndex":null,"from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x00","gasPrice":"0x00","gas":"0x00","input":"0x00"}"#); + assert_eq!(serialized, r#"{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x00","blockHash":null,"blockNumber":null,"transactionIndex":null,"from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x00","gasPrice":"0x00","gas":"0x00","input":"0x"}"#); } }