diff --git a/Cargo.lock b/Cargo.lock index dfe37dbb4..79ca26582 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,6 +11,7 @@ dependencies = [ "ethcore-devtools 1.1.0", "ethcore-rpc 1.1.0", "ethcore-util 1.1.0", + "ethjson 0.1.0", "ethminer 1.1.0", "ethsync 1.1.0", "fdlimit 0.1.0", @@ -184,11 +185,11 @@ dependencies = [ [[package]] name = "eth-secp256k1" version = "0.5.4" -source = "git+https://github.com/ethcore/rust-secp256k1#283a0677d8327536be58a87e0494d7e0e7b1d1d8" +source = "git+https://github.com/ethcore/rust-secp256k1#b6fdd43bbcf6d46adb72a92dd1632a0fc834cbf5" dependencies = [ "arrayvec 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "gcc 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -286,6 +287,18 @@ dependencies = [ "vergen 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ethjson" +version = "0.1.0" +dependencies = [ + "ethcore-util 1.1.0", + "rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_codegen 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ethminer" version = "1.1.0" diff --git a/Cargo.toml b/Cargo.toml index 782dd1c79..fd1d16cff 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,7 @@ ethsync = { path = "sync" } ethminer = { path = "miner" } ethcore-devtools = { path = "devtools" } ethcore-rpc = { path = "rpc", optional = true } +ethjson = { path = "json" } [features] default = ["rpc"] diff --git a/ethcore/src/block.rs b/ethcore/src/block.rs index 1ef28188b..d4aa35445 100644 --- a/ethcore/src/block.rs +++ b/ethcore/src/block.rs @@ -423,6 +423,37 @@ mod tests { #[test] fn enact_block_with_uncle() { - // TODO: test for when there's an uncle. + use spec::*; + let engine = Spec::new_test().to_engine().unwrap(); + let genesis_header = engine.spec().genesis_header(); + + let mut db_result = get_temp_journal_db(); + let mut db = db_result.take(); + engine.spec().ensure_db_good(db.as_hashdb_mut()); + let mut open_block = OpenBlock::new(engine.deref(), db, &genesis_header, vec![genesis_header.hash()], Address::zero(), x!(3141562), vec![]); + let mut uncle1_header = Header::new(); + uncle1_header.extra_data = b"uncle1".to_vec(); + let mut uncle2_header = Header::new(); + uncle2_header.extra_data = b"uncle2".to_vec(); + 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(); + + let mut db_result = get_temp_journal_db(); + let mut db = db_result.take(); + engine.spec().ensure_db_good(db.as_hashdb_mut()); + let e = enact_and_seal(&orig_bytes, engine.deref(), db, &genesis_header, vec![genesis_header.hash()]).unwrap(); + + let bytes = e.rlp_bytes(); + assert_eq!(bytes, orig_bytes); + let uncles = BlockView::new(&bytes).uncles(); + assert_eq!(uncles[1].extra_data, b"uncle2"); + + let db = e.drain(); + assert_eq!(orig_db.keys(), db.keys()); + assert!(orig_db.keys().iter().filter(|k| orig_db.get(k.0) != db.get(k.0)).next() == None); } } diff --git a/install-parity.sh b/install-parity.sh index 439700306..74387ca7f 100755 --- a/install-parity.sh +++ b/install-parity.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -PARITY_DEB_URL=https://github.com/ethcore/parity/releases/download/beta-0.9/parity_linux_0.9.0-0_amd64.deb +PARITY_DEB_URL=https://github.com/ethcore/parity/releases/download/v1.0.0-rc1/parity_linux_1.0.0.rc1-0_amd64.deb function run_installer() diff --git a/json/Cargo.toml b/json/Cargo.toml new file mode 100644 index 000000000..61599c331 --- /dev/null +++ b/json/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "ethjson" +version = "0.1.0" +authors = ["debris "] +build = "build.rs" + +[dependencies] +ethcore-util = { path = "../util" } +rustc-serialize = "0.3" +serde = "0.7.0" +serde_json = "0.7.0" +serde_macros = { version = "0.7.0", optional = true } +clippy = { version = "0.0.50", optional = true } + +[build-dependencies] +serde_codegen = { version = "0.7.0", optional = true } +syntex = "0.29.0" + +[features] +default = ["serde_codegen"] +nightly = ["serde_macros"] diff --git a/json/build.rs b/json/build.rs new file mode 100644 index 000000000..a23790d86 --- /dev/null +++ b/json/build.rs @@ -0,0 +1,45 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +#[cfg(not(feature = "serde_macros"))] +mod inner { + extern crate syntex; + extern crate serde_codegen; + + use std::env; + use std::path::Path; + + pub fn main() { + let out_dir = env::var_os("OUT_DIR").unwrap(); + + let src = Path::new("src/lib.rs.in"); + let dst = Path::new(&out_dir).join("lib.rs"); + + let mut registry = syntex::Registry::new(); + + serde_codegen::register(&mut registry); + registry.expand("", &src, &dst).unwrap(); + } +} + +#[cfg(feature = "serde_macros")] +mod inner { + pub fn main() {} +} + +fn main() { + inner::main(); +} diff --git a/json/src/blockchain/account.rs b/json/src/blockchain/account.rs new file mode 100644 index 000000000..eb6f0a1dd --- /dev/null +++ b/json/src/blockchain/account.rs @@ -0,0 +1,50 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Blockchain test account deserializer. + +use std::collections::BTreeMap; +use uint::Uint; +use bytes::Bytes; + +/// Blockchain test account deserializer. +#[derive(Debug, PartialEq, Deserialize)] +pub struct Account { + balance: Uint, + code: Bytes, + nonce: Uint, + storage: BTreeMap, +} + +#[cfg(test)] +mod tests { + use serde_json; + use blockchain::account::Account; + + #[test] + fn header_deserialization() { + let s = r#"{ + "balance" : "0x09184e72a078", + "code" : "0x600140600155", + "nonce" : "0x00", + "storage" : { + "0x01" : "0x9a10c2b5bb8f3c602e674006d9b21f09167df57c87a78a5ce96d4159ecb76520" + } + }"#; + let _deserialized: Account= serde_json::from_str(s).unwrap(); + // TODO: validate all fields + } +} diff --git a/json/src/blockchain/block.rs b/json/src/blockchain/block.rs new file mode 100644 index 000000000..ed297077c --- /dev/null +++ b/json/src/blockchain/block.rs @@ -0,0 +1,68 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Blockchain test block deserializer. + +use bytes::Bytes; +use blockchain::header::Header; +use blockchain::transaction::Transaction; + +/// Blockchain test block deserializer. +#[derive(Debug, PartialEq, Deserialize)] +pub struct Block { + #[serde(rename="blockHeader")] + header: Header, + rlp: Bytes, + transactions: Vec, + #[serde(rename="uncleHeaders")] + uncles: Vec
, +} + +#[cfg(test)] +mod tests { + use serde_json; + use blockchain::block::Block; + + #[test] + fn block_deserialization() { + let s = r#"{ + "blockHeader" : { + "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "0x020000", + "extraData" : "0x", + "gasLimit" : "0x2fefba", + "gasUsed" : "0x00", + "hash" : "65ebf1b97fb89b14680267e0723d69267ec4bf9a96d4a60ffcb356ae0e81c18f", + "mixHash" : "13735ab4156c9b36327224d92e1692fab8fc362f8e0f868c94d421848ef7cd06", + "nonce" : "931dcc53e5edc514", + "number" : "0x01", + "parentHash" : "5a39ed1020c04d4d84539975b893a4e7c53eab6c2965db8bc3468093a31bc5ae", + "receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "c5c83ff43741f573a0c9b31d0e56fdd745f4e37d193c4e78544f302777aafcf3", + "timestamp" : "0x56850b7b", + "transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }, + "blocknumber" : "1", + "rlp" : "0xf901fcf901f7a05a39ed1020c04d4d84539975b893a4e7c53eab6c2965db8bc3468093a31bc5aea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0c5c83ff43741f573a0c9b31d0e56fdd745f4e37d193c4e78544f302777aafcf3a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000001832fefba808456850b7b80a013735ab4156c9b36327224d92e1692fab8fc362f8e0f868c94d421848ef7cd0688931dcc53e5edc514c0c0", + "transactions" : [], + "uncleHeaders" : [] + }"#; + let _deserialized: Block = serde_json::from_str(s).unwrap(); + // TODO: validate all fields + } +} diff --git a/json/src/blockchain/blockchain.rs b/json/src/blockchain/blockchain.rs new file mode 100644 index 000000000..f6b1259ca --- /dev/null +++ b/json/src/blockchain/blockchain.rs @@ -0,0 +1,145 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Blockchain deserialization. + +use bytes::Bytes; +use blockchain::state::State; +use blockchain::header::Header; +use blockchain::block::Block; + +/// Blockchain deserialization. +#[derive(Debug, PartialEq, Deserialize)] +pub struct BlockChain { + #[serde(rename="genesisBlockHeader")] + genesis_block: Header, + #[serde(rename="genesisRLP")] + genesis_rlp: Bytes, + blocks: Vec, + #[serde(rename="postState")] + post_state: State, + #[serde(rename="pre")] + pre_state: State, +} + +#[cfg(test)] +mod tests { + use serde_json; + use blockchain::blockchain::BlockChain; + + #[test] + fn blockchain_deserialization() { + let s = r#"{ + "blocks" : [{ + "blockHeader" : { + "bloom" : "00000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000040000000000000000000000000000000000000000000000000000000", + "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "0x020000", + "extraData" : "0x0102030405060708091011121314151617181920212223242526272829303132", + "gasLimit" : "0x2fefba", + "gasUsed" : "0x560b", + "hash" : "06b5b1742bde29468510c92641f36b719c61b3fc3e9a21c92a23978f4f7faa2a", + "mixHash" : "5266ca43e81d25925a9ba573c3e4f9180bc076d316d90e63c6f8708b272f5ce2", + "nonce" : "59ba4daed1898e21", + "number" : "0x01", + "parentHash" : "f052d217bd5275a5177a3c3b7debdfe2670f1c8394b2965ccd5c1883cc1a524d", + "receiptTrie" : "c7778a7376099ee2e5c455791c1885b5c361b95713fddcbe32d97fd01334d296", + "stateRoot" : "bac6177a79e910c98d86ec31a09ae37ac2de15b754fd7bed1ba52362c49416bf", + "timestamp" : "0x56850c2c", + "transactionsTrie" : "498785da562aa0c5dd5937cf15f22139b0b1bcf3b4fc48986e1bb1dae9292796", + "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }, + "rlp" : "0xf90285f90219a0f052d217bd5275a5177a3c3b7debdfe2670f1c8394b2965ccd5c1883cc1a524da01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0bac6177a79e910c98d86ec31a09ae37ac2de15b754fd7bed1ba52362c49416bfa0498785da562aa0c5dd5937cf15f22139b0b1bcf3b4fc48986e1bb1dae9292796a0c7778a7376099ee2e5c455791c1885b5c361b95713fddcbe32d97fd01334d296b90100000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000400000000000000000000000000000000000000000000000000000008302000001832fefba82560b8456850c2ca00102030405060708091011121314151617181920212223242526272829303132a05266ca43e81d25925a9ba573c3e4f9180bc076d316d90e63c6f8708b272f5ce28859ba4daed1898e21f866f864800a82c35094095e7baea6a6c7c4c2dfeb977efac326af552d8785012a05f200801ca0ee0b9ec878fbd4258a9473199d8ecc32996a20c323c004e79e0cda20e0418ce3a04e6bc63927d1510bab54f37e46fa036faf4b2c465d271920d9afea1fadf7bd21c0", + "transactions" : [ + { + "data" : "0x", + "gasLimit" : "0xc350", + "gasPrice" : "0x0a", + "nonce" : "0x00", + "r" : "0xee0b9ec878fbd4258a9473199d8ecc32996a20c323c004e79e0cda20e0418ce3", + "s" : "0x4e6bc63927d1510bab54f37e46fa036faf4b2c465d271920d9afea1fadf7bd21", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "v" : "0x1c", + "value" : "0x012a05f200" + } + ], + "uncleHeaders" : [ + ] + }], + "genesisBlockHeader" : { + "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "0x020000", + "extraData" : "0x42", + "gasLimit" : "0x2fefd8", + "gasUsed" : "0x00", + "hash" : "f052d217bd5275a5177a3c3b7debdfe2670f1c8394b2965ccd5c1883cc1a524d", + "mixHash" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "nonce" : "0102030405060708", + "number" : "0x00", + "parentHash" : "0000000000000000000000000000000000000000000000000000000000000000", + "receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "925002c3260b44e44c3edebad1cc442142b03020209df1ab8bb86752edbd2cd7", + "timestamp" : "0x54c98c81", + "transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }, + "genesisRLP" : "0xf901fcf901f7a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0925002c3260b44e44c3edebad1cc442142b03020209df1ab8bb86752edbd2cd7a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000080832fefd8808454c98c8142a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421880102030405060708c0c0", + "lastblockhash" : "06b5b1742bde29468510c92641f36b719c61b3fc3e9a21c92a23978f4f7faa2a", + "postState" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "0x012a05f264", + "code" : "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600052600060206000a1", + "nonce" : "0x00", + "storage" : { + } + }, + "8888f1f195afa192cfee860698584c030f4c9db1" : { + "balance" : "0x4563918244f75c6e", + "code" : "0x", + "nonce" : "0x00", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "0x012a029592", + "code" : "0x", + "nonce" : "0x01", + "storage" : { + } + } + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "0x64", + "code" : "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600052600060206000a1", + "nonce" : "0x00", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "0x02540be400", + "code" : "0x", + "nonce" : "0x00", + "storage" : { + } + } + } + }"#; + let _deserialized: BlockChain = serde_json::from_str(s).unwrap(); + // TODO: validate all fields + //} +} diff --git a/json/src/blockchain/header.rs b/json/src/blockchain/header.rs new file mode 100644 index 000000000..e97039213 --- /dev/null +++ b/json/src/blockchain/header.rs @@ -0,0 +1,81 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Blockchain test header deserializer. + +use hash::{H64, Address, H256, Bloom}; +use uint::Uint; +use bytes::Bytes; + +/// Blockchain test header deserializer. +#[derive(Debug, PartialEq, Deserialize)] +pub struct Header { + bloom: Bloom, + coinbase: Address, + difficulty: Uint, + #[serde(rename="extraData")] + extra_data: Bytes, + #[serde(rename="gasLimit")] + gas_limit: Uint, + #[serde(rename="gasUsed")] + gas_used: Uint, + hash: H256, + #[serde(rename="mixHash")] + mix_hash: H256, + nonce: H64, + number: Uint, + #[serde(rename="parentHash")] + parent_hash: H256, + #[serde(rename="receiptTrie")] + receipt_trie: H256, + #[serde(rename="stateRoot")] + state_root: H256, + timestamp: Uint, + #[serde(rename="transactionsTrie")] + transactions_trie: H256, + #[serde(rename="uncleHash")] + uncle_hash: H256, +} + +#[cfg(test)] +mod tests { + use serde_json; + use blockchain::header::Header; + + #[test] + fn header_deserialization() { + let s = r#"{ + "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "0x020000", + "extraData" : "0x", + "gasLimit" : "0x2fefba", + "gasUsed" : "0x00", + "hash" : "65ebf1b97fb89b14680267e0723d69267ec4bf9a96d4a60ffcb356ae0e81c18f", + "mixHash" : "13735ab4156c9b36327224d92e1692fab8fc362f8e0f868c94d421848ef7cd06", + "nonce" : "931dcc53e5edc514", + "number" : "0x01", + "parentHash" : "5a39ed1020c04d4d84539975b893a4e7c53eab6c2965db8bc3468093a31bc5ae", + "receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "c5c83ff43741f573a0c9b31d0e56fdd745f4e37d193c4e78544f302777aafcf3", + "timestamp" : "0x56850b7b", + "transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }"#; + let _deserialized: Header = serde_json::from_str(s).unwrap(); + // TODO: validate all fields + } +} diff --git a/json/src/blockchain/mod.rs b/json/src/blockchain/mod.rs new file mode 100644 index 000000000..046b2e534 --- /dev/null +++ b/json/src/blockchain/mod.rs @@ -0,0 +1,25 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Blockchain test deserialization. + +pub mod account; +pub mod block; +pub mod blockchain; +pub mod header; +pub mod state; +pub mod transaction; +pub mod test; diff --git a/json/src/blockchain/state.rs b/json/src/blockchain/state.rs new file mode 100644 index 000000000..2af0dbf21 --- /dev/null +++ b/json/src/blockchain/state.rs @@ -0,0 +1,34 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Blockchain test state deserializer. + +use std::collections::BTreeMap; +use std::ops::Deref; +use hash::Address; +use blockchain::account::Account; + +/// Blockchain test state deserializer. +#[derive(Debug, PartialEq, Deserialize)] +pub struct State(BTreeMap); + +impl Deref for State { + type Target = BTreeMap; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} diff --git a/json/src/blockchain/test.rs b/json/src/blockchain/test.rs new file mode 100644 index 000000000..6097a60e6 --- /dev/null +++ b/json/src/blockchain/test.rs @@ -0,0 +1,32 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Blockchain test deserializer. + +use std::collections::BTreeMap; +use std::ops::Deref; +use blockchain::blockchain::BlockChain; + +/// Blockchain test deserializer. +pub struct Test(BTreeMap); + +impl Deref for Test { + type Target = BTreeMap; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} diff --git a/json/src/blockchain/transaction.rs b/json/src/blockchain/transaction.rs new file mode 100644 index 000000000..5d04748f5 --- /dev/null +++ b/json/src/blockchain/transaction.rs @@ -0,0 +1,35 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Blockchain test transaction deserialization. + +use uint::Uint; +use bytes::Bytes; + +/// Blockchain test transaction deserialization. +#[derive(Debug, PartialEq, Deserialize)] +pub struct Transaction { + data: Bytes, + #[serde(rename="gasLimit")] + gas_limit: Uint, + #[serde(rename="gasPrice")] + gas_price: Uint, + nonce: Uint, + r: Uint, + s: Uint, + v: Uint, + value: Uint +} diff --git a/json/src/bytes.rs b/json/src/bytes.rs new file mode 100644 index 000000000..28b7636d4 --- /dev/null +++ b/json/src/bytes.rs @@ -0,0 +1,87 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Lenient bytes json deserialization for test json files. + +use rustc_serialize::hex::FromHex; +use serde::{Deserialize, Deserializer, Error}; +use serde::de::Visitor; + +/// Lenient bytes json deserialization for test json files. +#[derive(Default, Debug, PartialEq)] +pub struct Bytes(Vec); + +impl Into> for Bytes { + fn into(self) -> Vec { + self.0 + } +} + +impl Deserialize for Bytes { + fn deserialize(deserializer: &mut D) -> Result + where D: Deserializer { + deserializer.deserialize(BytesVisitor) + } +} + +struct BytesVisitor; + +impl Visitor for BytesVisitor { + type Value = Bytes; + + fn visit_str(&mut self, value: &str) -> Result where E: Error { + 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()) + })) + }; + Ok(Bytes(v)) + } + + fn visit_string(&mut self, value: String) -> Result where E: Error { + self.visit_str(value.as_ref()) + } +} + +#[cfg(test)] +mod test { + use serde_json; + use bytes::Bytes; + + #[test] + fn bytes_deserialization() { + let s = r#"["", "0x", "0x12", "1234"]"#; + let deserialized: Vec = serde_json::from_str(s).unwrap(); + assert_eq!(deserialized, vec![ + Bytes(vec![]), + Bytes(vec![]), + Bytes(vec![0x12]), + Bytes(vec![0x12, 0x34]) + ]); + } + + #[test] + fn bytes_into() { + let bytes = Bytes(vec![0xff, 0x11]); + let v: Vec = bytes.into(); + assert_eq!(vec![0xff, 0x11], v); + } +} diff --git a/json/src/hash.rs b/json/src/hash.rs new file mode 100644 index 000000000..098f2e7a8 --- /dev/null +++ b/json/src/hash.rs @@ -0,0 +1,94 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Lenient hash json deserialization for test json files. + +use std::str::FromStr; +use serde::{Deserialize, Deserializer, Error}; +use serde::de::Visitor; +use util::hash::{H64 as Hash64, Address as Hash160, H256 as Hash256, H2048 as Hash2048}; + + +macro_rules! impl_hash { + ($name: ident, $inner: ident) => { + /// Lenient hash json deserialization for test json files. + #[derive(Default, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] + pub struct $name($inner); + + impl Into<$inner> for $name { + fn into(self) -> $inner { + self.0 + } + } + + impl Deserialize for $name { + fn deserialize(deserializer: &mut D) -> Result + where D: Deserializer { + + struct HashVisitor; + + impl Visitor for HashVisitor { + type Value = $name; + + fn visit_str(&mut self, value: &str) -> Result where E: Error { + let value = match value.len() { + 0 => $inner::from(0), + _ => try!($inner::from_str(value).map_err(|_| { + Error::custom(format!("Invalid hex value {}.", value).as_ref()) + })) + }; + + Ok($name(value)) + } + + fn visit_string(&mut self, value: String) -> Result where E: Error { + self.visit_str(value.as_ref()) + } + } + + deserializer.deserialize(HashVisitor) + } + } + } +} + +impl_hash!(H64, Hash64); +impl_hash!(Address, Hash160); +impl_hash!(H256, Hash256); +impl_hash!(Bloom, Hash2048); + +#[cfg(test)] +mod test { + use std::str::FromStr; + use serde_json; + use util::hash; + use hash::H256; + + #[test] + fn hash_deserialization() { + let s = r#"["", "5a39ed1020c04d4d84539975b893a4e7c53eab6c2965db8bc3468093a31bc5ae"]"#; + let deserialized: Vec = serde_json::from_str(s).unwrap(); + assert_eq!(deserialized, vec![ + H256(hash::H256::from(0)), + H256(hash::H256::from_str("5a39ed1020c04d4d84539975b893a4e7c53eab6c2965db8bc3468093a31bc5ae").unwrap()) + ]); + } + + #[test] + fn hash_into() { + assert_eq!(hash::H256::from(0), H256(hash::H256::from(0)).into()); + } +} diff --git a/json/src/lib.rs b/json/src/lib.rs new file mode 100644 index 000000000..b94e1fa55 --- /dev/null +++ b/json/src/lib.rs @@ -0,0 +1,28 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Json deserialization module. + +#![warn(missing_docs)] +#![cfg_attr(feature="nightly", feature(custom_derive, custom_attribute, plugin))] +#![cfg_attr(feature="nightly", plugin(serde_macros, clippy))] + +#[cfg(feature = "serde_macros")] +include!("lib.rs.in"); + +#[cfg(not(feature = "serde_macros"))] +include!(concat!(env!("OUT_DIR"), "/lib.rs")); + diff --git a/json/src/lib.rs.in b/json/src/lib.rs.in new file mode 100644 index 000000000..6d3437811 --- /dev/null +++ b/json/src/lib.rs.in @@ -0,0 +1,25 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +extern crate rustc_serialize; +extern crate serde; +extern crate serde_json; +extern crate ethcore_util as util; + +pub mod hash; +pub mod uint; +pub mod bytes; +pub mod blockchain; diff --git a/json/src/uint.rs b/json/src/uint.rs new file mode 100644 index 000000000..41e717277 --- /dev/null +++ b/json/src/uint.rs @@ -0,0 +1,88 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Lenient uint json deserialization for test json files. + +use std::str::FromStr; +use serde::{Deserialize, Deserializer, Error}; +use serde::de::Visitor; +use util::numbers::{U256, Uint as U}; + +/// Lenient uint json deserialization for test json files. +#[derive(Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct Uint(U256); + +impl Into for Uint { + fn into(self) -> U256 { + self.0 + } +} + +impl Deserialize for Uint { + fn deserialize(deserializer: &mut D) -> Result + where D: Deserializer { + deserializer.deserialize(UintVisitor) + } +} + +struct UintVisitor; + +impl Visitor for UintVisitor { + type Value = Uint; + + fn visit_str(&mut self, value: &str) -> Result where E: Error { + let value = match value.len() { + 0 => U256::from(0), + 2 if value.starts_with("0x") => U256::from(0), + _ if value.starts_with("0x") => try!(U256::from_str(&value[2..]).map_err(|_| { + Error::custom(format!("Invalid hex value {}.", value).as_ref()) + })), + _ => try!(U256::from_dec_str(value).map_err(|_| { + Error::custom(format!("Invalid decimal value {}.", value).as_ref()) + })) + }; + + Ok(Uint(value)) + } + + fn visit_string(&mut self, value: String) -> Result where E: Error { + self.visit_str(value.as_ref()) + } +} + +#[cfg(test)] +mod test { + use serde_json; + use util::numbers::U256; + use uint::Uint; + + #[test] + fn uint_deserialization() { + let s = r#"["0xa", "10", "", "0x"]"#; + let deserialized: Vec = serde_json::from_str(s).unwrap(); + assert_eq!(deserialized, vec![ + Uint(U256::from(10)), + Uint(U256::from(10)), + Uint(U256::from(0)), + Uint(U256::from(0)) + ]); + } + + #[test] + fn uint_into() { + assert_eq!(U256::from(10), Uint(U256::from(10)).into()); + } +} diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 5af299b34..8697c94a7 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -404,6 +404,12 @@ impl ChainSync { debug!(target: "sync", "Mismatched block header {}", number + 1); self.remove_downloaded_blocks(number + 1); } + if self.have_common_block && number < self.current_base_block() + 1 { + // unkown header + debug!(target: "sync", "Old block header {:?} ({}) is unknown, restarting sync", hash, number); + self.restart(io); + return Ok(()); + } } let hdr = Header { data: try!(r.at(i)).as_raw().to_vec(), @@ -483,6 +489,7 @@ impl ChainSync { trace!(target: "sync", "{} -> NewBlock ({})", peer_id, h); if !self.have_common_block { trace!(target: "sync", "NewBlock ignored while seeking"); + return Ok(()); } let header: BlockHeader = try!(header_rlp.as_val()); let mut unknown = false; @@ -1520,6 +1527,7 @@ mod tests { let mut queue = VecDeque::new(); let mut sync = dummy_sync_with_peer(client.block_hash_delta_minus(5)); + sync.have_common_block = true; let mut io = TestIo::new(&mut client, &mut queue, None); let block = UntrustedRlp::new(&block_data);