From 0c7c34e6091c2d716eddbc722c0847541f663d01 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Wed, 2 Aug 2017 12:50:36 +0200 Subject: [PATCH] Chainspec validation (#6197) * chainspec validation * better error formatting for chainspec * lint validate_chainspecs.sh * quit takes &str instead of S: AsRef * push CI * don't double check spec validity --- Cargo.lock | 18 +++++++++ Cargo.toml | 2 +- chainspec/Cargo.toml | 9 +++++ chainspec/src/main.rs | 48 ++++++++++++++++++++++++ ethcore/res/constructor.json | 1 - ethcore/res/validator_safe_contract.json | 1 - ethcore/src/ethereum/mod.rs | 19 ---------- ethcore/src/spec/spec.rs | 13 ------- scripts/validate_chainspecs.sh | 15 ++++++++ test.sh | 4 ++ 10 files changed, 95 insertions(+), 35 deletions(-) create mode 100644 chainspec/Cargo.toml create mode 100644 chainspec/src/main.rs create mode 100755 scripts/validate_chainspecs.sh diff --git a/Cargo.lock b/Cargo.lock index b0bedd6d7..cc8c7d3c7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -237,6 +237,15 @@ name = "cfg-if" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "chainspec" +version = "0.1.0" +dependencies = [ + "ethjson 0.1.0", + "serde_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "cid" version = "0.2.2" @@ -2592,6 +2601,14 @@ dependencies = [ "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "serde_ignored" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "serde_json" version = "1.0.2" @@ -3398,6 +3415,7 @@ dependencies = [ "checksum serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6a7c6b751a2e8d5df57a5ff71b5b4fc8aaee9ee28ff1341d640dd130bb5f4f7a" "checksum serde_derive 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "2f6ca58905ebd3c3b285a8a6d4f3ac92b92c0d7951d5649b1bdd212549c06639" "checksum serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37aee4e0da52d801acfbc0cc219eb1eda7142112339726e427926a6f6ee65d3a" +"checksum serde_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "190e9765dcedb56be63b6e0993a006c7e3b071a016a304736e4a315dc01fb142" "checksum serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "48b04779552e92037212c3615370f6bd57a40ebba7f20e554ff9f55e41a69a7b" "checksum serde_urlencoded 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce0fd303af908732989354c6f02e05e2e6d597152870f2c6990efb0577137480" "checksum sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc30b1e1e8c40c121ca33b86c23308a090d19974ef001b4bf6e61fd1a0fb095c" diff --git a/Cargo.toml b/Cargo.toml index 97746c082..03d9c9664 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -110,4 +110,4 @@ lto = false panic = "abort" [workspace] -members = ["ethstore/cli", "ethkey/cli", "evmbin", "whisper"] +members = ["ethstore/cli", "ethkey/cli", "evmbin", "whisper", "chainspec"] diff --git a/chainspec/Cargo.toml b/chainspec/Cargo.toml new file mode 100644 index 000000000..73daf795a --- /dev/null +++ b/chainspec/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "chainspec" +version = "0.1.0" +authors = ["debris "] + +[dependencies] +ethjson = { path = "../json" } +serde_json = "1.0" +serde_ignored = "0.0.4" diff --git a/chainspec/src/main.rs b/chainspec/src/main.rs new file mode 100644 index 000000000..bcef53f3f --- /dev/null +++ b/chainspec/src/main.rs @@ -0,0 +1,48 @@ +extern crate serde_json; +extern crate serde_ignored; +extern crate ethjson; + +use std::collections::BTreeSet; +use std::{fs, env, process}; +use ethjson::spec::Spec; + +fn quit(s: &str) -> ! { + println!("{}", s); + process::exit(1); +} + +fn main() { + let mut args = env::args(); + if args.len() != 2 { + quit("You need to specify chainspec.json\n\ + \n\ + ./chainspec "); + } + + let path = args.nth(1).expect("args.len() == 2; qed"); + let file = match fs::File::open(&path) { + Ok(file) => file, + Err(_) => quit(&format!("{} could not be opened", path)), + }; + + let mut unused = BTreeSet::new(); + let mut deserializer = serde_json::Deserializer::from_reader(file); + + let spec: Result = serde_ignored::deserialize(&mut deserializer, |field| { + unused.insert(field.to_string()); + }); + + if let Err(err) = spec { + quit(&format!("{} {}", path, err.to_string())); + } + + if !unused.is_empty() { + let err = unused.into_iter() + .map(|field| format!("{} unexpected field `{}`", path, field)) + .collect::>() + .join("\n"); + quit(&err); + } + + println!("{} is valid", path); +} diff --git a/ethcore/res/constructor.json b/ethcore/res/constructor.json index 2932ce164..9b1de7020 100644 --- a/ethcore/res/constructor.json +++ b/ethcore/res/constructor.json @@ -11,7 +11,6 @@ "networkID" : "0x2" }, "genesis": { - "gasLimitBoundDivisor": "0x0400", "seal": { "generic": "0x" }, diff --git a/ethcore/res/validator_safe_contract.json b/ethcore/res/validator_safe_contract.json index 7845c898d..63dfb948d 100644 --- a/ethcore/res/validator_safe_contract.json +++ b/ethcore/res/validator_safe_contract.json @@ -3,7 +3,6 @@ "engine": { "basicAuthority": { "params": { - "gasLimitBoundDivisor": "0x0400", "durationLimit": "0x0d", "validators": { "safeContract": "0x0000000000000000000000000000000000000005" diff --git a/ethcore/src/ethereum/mod.rs b/ethcore/src/ethereum/mod.rs index e731ef7db..dee86883b 100644 --- a/ethcore/src/ethereum/mod.rs +++ b/ethcore/src/ethereum/mod.rs @@ -134,23 +134,4 @@ mod tests { let _ = frontier.engine; } - - #[test] - fn all_spec_files_valid() { - let tmp = ::std::env::temp_dir(); - new_olympic(&tmp); - new_foundation(&tmp); - new_classic(&tmp); - new_expanse(&tmp); - new_kovan(&tmp); - new_ropsten(&tmp); - new_morden(&tmp); - new_frontier_test(); - new_homestead_test(); - new_eip150_test(); - new_eip161_test(); - new_transition_test(); - new_mainnet_like(); - new_metropolis_test(); - } } diff --git a/ethcore/src/spec/spec.rs b/ethcore/src/spec/spec.rs index 7fc00f1e4..395f8ef9c 100644 --- a/ethcore/src/spec/spec.rs +++ b/ethcore/src/spec/spec.rs @@ -529,19 +529,6 @@ mod tests { assert!(Spec::load(::std::env::temp_dir(), &[] as &[u8]).is_err()); } - #[test] - fn all_spec_files_valid() { - Spec::new_test(); - Spec::new_null(); - Spec::new_test_constructor(); - Spec::new_instant(); - Spec::new_test_round(); - Spec::new_test_tendermint(); - Spec::new_validator_safe_contract(); - Spec::new_validator_contract(); - Spec::new_validator_multi(); - } - #[test] fn test_chain() { let test_spec = Spec::new_test(); diff --git a/scripts/validate_chainspecs.sh b/scripts/validate_chainspecs.sh new file mode 100755 index 000000000..a0e2d9b17 --- /dev/null +++ b/scripts/validate_chainspecs.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +ERR=0 +cargo build --release -p chainspec + +for spec in ethcore/res/*.json; do + if ! ./target/release/chainspec "$spec"; then ERR=1; fi +done + +for spec in ethcore/res/ethereum/*.json; do + if ! ./target/release/chainspec "$spec"; then ERR=1; fi +done + +exit $ERR + diff --git a/test.sh b/test.sh index 435a1ad3f..5430b17ea 100755 --- a/test.sh +++ b/test.sh @@ -22,4 +22,8 @@ case $1 in ;; esac +set -e + +./scripts/validate_chainspecs.sh + cargo test -j 8 $OPTIONS --features "$FEATURES" --all --exclude parity-ipfs-api --exclude evmjit $1