Skip to content
This repository was archived by the owner on Nov 6, 2020. It is now read-only.

Commit 14c9cbd

Browse files
authored
Deny unknown fields for chainspec (#9972)
* Add deny_unknown_fields to chainspec * Add tests and fix existing one * Remove serde_ignored dependency for chainspec * Fix rpc test eth chain spec * Fix starting_nonce_test spec
1 parent c446687 commit 14c9cbd

20 files changed

+102
-36
lines changed

Cargo.lock

+2-12
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

chainspec/Cargo.toml

-1
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,3 @@ authors = ["Marek Kotewicz <marek@parity.io>"]
66
[dependencies]
77
ethjson = { path = "../json" }
88
serde_json = "1.0"
9-
serde_ignored = "0.0.4"

chainspec/src/main.rs

+1-16
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,8 @@
1515
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
1616

1717
extern crate serde_json;
18-
extern crate serde_ignored;
1918
extern crate ethjson;
2019

21-
use std::collections::BTreeSet;
2220
use std::{fs, env, process};
2321
use ethjson::spec::Spec;
2422

@@ -41,24 +39,11 @@ fn main() {
4139
Err(_) => quit(&format!("{} could not be opened", path)),
4240
};
4341

44-
let mut unused = BTreeSet::new();
45-
let mut deserializer = serde_json::Deserializer::from_reader(file);
46-
47-
let spec: Result<Spec, _> = serde_ignored::deserialize(&mut deserializer, |field| {
48-
unused.insert(field.to_string());
49-
});
42+
let spec: Result<Spec, _> = serde_json::from_reader(file);
5043

5144
if let Err(err) = spec {
5245
quit(&format!("{} {}", path, err.to_string()));
5346
}
5447

55-
if !unused.is_empty() {
56-
let err = unused.into_iter()
57-
.map(|field| format!("{} unexpected field `{}`", path, field))
58-
.collect::<Vec<_>>()
59-
.join("\n");
60-
quit(&err);
61-
}
62-
6348
println!("{} is valid", path);
6449
}

json/src/spec/account.rs

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use spec::builtin::Builtin;
2323

2424
/// Spec account.
2525
#[derive(Debug, PartialEq, Deserialize)]
26+
#[serde(deny_unknown_fields)]
2627
pub struct Account {
2728
/// Builtin contract.
2829
pub builtin: Option<Builtin>,

json/src/spec/authority_round.rs

+2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use super::ValidatorSet;
2323

2424
/// Authority params deserialization.
2525
#[derive(Debug, PartialEq, Deserialize)]
26+
#[serde(deny_unknown_fields)]
2627
#[serde(rename_all = "camelCase")]
2728
pub struct AuthorityRoundParams {
2829
/// Block duration, in seconds.
@@ -59,6 +60,7 @@ pub struct AuthorityRoundParams {
5960

6061
/// Authority engine deserialization.
6162
#[derive(Debug, PartialEq, Deserialize)]
63+
#[serde(deny_unknown_fields)]
6264
pub struct AuthorityRound {
6365
/// Ethash params.
6466
pub params: AuthorityRoundParams,

json/src/spec/basic_authority.rs

+2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use super::ValidatorSet;
2121

2222
/// Authority params deserialization.
2323
#[derive(Debug, PartialEq, Deserialize)]
24+
#[serde(deny_unknown_fields)]
2425
#[serde(rename_all = "camelCase")]
2526
pub struct BasicAuthorityParams {
2627
/// Block duration.
@@ -31,6 +32,7 @@ pub struct BasicAuthorityParams {
3132

3233
/// Authority engine deserialization.
3334
#[derive(Debug, PartialEq, Deserialize)]
35+
#[serde(deny_unknown_fields)]
3436
pub struct BasicAuthority {
3537
/// Ethash params.
3638
pub params: BasicAuthorityParams,

json/src/spec/builtin.rs

+5
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use uint::Uint;
2020

2121
/// Linear pricing.
2222
#[derive(Debug, PartialEq, Deserialize, Clone)]
23+
#[serde(deny_unknown_fields)]
2324
pub struct Linear {
2425
/// Base price.
2526
pub base: usize,
@@ -29,13 +30,15 @@ pub struct Linear {
2930

3031
/// Pricing for modular exponentiation.
3132
#[derive(Debug, PartialEq, Deserialize, Clone)]
33+
#[serde(deny_unknown_fields)]
3234
pub struct Modexp {
3335
/// Price divisor.
3436
pub divisor: usize,
3537
}
3638

3739
/// Pricing for alt_bn128_pairing.
3840
#[derive(Debug, PartialEq, Deserialize, Clone)]
41+
#[serde(deny_unknown_fields)]
3942
pub struct AltBn128Pairing {
4043
/// Base price.
4144
pub base: usize,
@@ -45,6 +48,7 @@ pub struct AltBn128Pairing {
4548

4649
/// Pricing variants.
4750
#[derive(Debug, PartialEq, Deserialize, Clone)]
51+
#[serde(deny_unknown_fields)]
4852
#[serde(rename_all = "snake_case")]
4953
pub enum Pricing {
5054
/// Linear pricing.
@@ -57,6 +61,7 @@ pub enum Pricing {
5761

5862
/// Spec builtin.
5963
#[derive(Debug, PartialEq, Deserialize, Clone)]
64+
#[serde(deny_unknown_fields)]
6065
pub struct Builtin {
6166
/// Builtin name.
6267
pub name: String,

json/src/spec/engine.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use super::{Ethash, BasicAuthority, AuthorityRound, Tendermint, NullEngine, Inst
2020

2121
/// Engine deserialization.
2222
#[derive(Debug, PartialEq, Deserialize)]
23+
#[serde(deny_unknown_fields)]
2324
#[serde(rename_all = "camelCase")]
2425
pub enum Engine {
2526
/// Null engine.
@@ -85,7 +86,6 @@ mod tests {
8586
"minimumDifficulty": "0x020000",
8687
"difficultyBoundDivisor": "0x0800",
8788
"durationLimit": "0x0d",
88-
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
8989
"homesteadTransition" : "0x",
9090
"daoHardforkTransition": "0xffffffffffffffff",
9191
"daoHardforkBeneficiary": "0x0000000000000000000000000000000000000000",

json/src/spec/ethash.rs

+3
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use hash::Address;
2323

2424
/// Deserializable doppelganger of block rewards for EthashParams
2525
#[derive(Clone, Debug, PartialEq, Deserialize)]
26+
#[serde(deny_unknown_fields)]
2627
#[serde(untagged)]
2728
pub enum BlockReward {
2829
Single(Uint),
@@ -31,6 +32,7 @@ pub enum BlockReward {
3132

3233
/// Deserializable doppelganger of EthashParams.
3334
#[derive(Clone, Debug, PartialEq, Deserialize)]
35+
#[serde(deny_unknown_fields)]
3436
#[serde(rename_all = "camelCase")]
3537
pub struct EthashParams {
3638
/// See main EthashParams docs.
@@ -97,6 +99,7 @@ pub struct EthashParams {
9799

98100
/// Ethash engine deserialization.
99101
#[derive(Debug, PartialEq, Deserialize)]
102+
#[serde(deny_unknown_fields)]
100103
pub struct Ethash {
101104
/// Ethash params.
102105
pub params: EthashParams,

json/src/spec/genesis.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use spec::Seal;
2323

2424
/// Spec genesis.
2525
#[derive(Debug, PartialEq, Deserialize)]
26+
#[serde(deny_unknown_fields)]
2627
#[serde(rename_all = "camelCase")]
2728
pub struct Genesis {
2829
/// Seal.
@@ -64,7 +65,6 @@ mod tests {
6465
#[test]
6566
fn genesis_deserialization() {
6667
let s = r#"{
67-
"nonce": "0x0000000000000042",
6868
"difficulty": "0x400000000",
6969
"seal": {
7070
"ethereum": {

json/src/spec/hardcoded_sync.rs

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use uint::Uint;
2121

2222
/// Spec hardcoded sync.
2323
#[derive(Debug, PartialEq, Serialize, Deserialize)]
24+
#[serde(deny_unknown_fields)]
2425
#[serde(rename_all = "camelCase")]
2526
pub struct HardcodedSync {
2627
/// Hexadecimal of the RLP encoding of the header of the block to start synchronization from.

json/src/spec/instant_seal.rs

+2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
1919
/// Instant seal engine params deserialization.
2020
#[derive(Debug, PartialEq, Deserialize)]
21+
#[serde(deny_unknown_fields)]
2122
#[serde(rename_all = "camelCase")]
2223
pub struct InstantSealParams {
2324
/// Whether to enable millisecond timestamp.
@@ -27,6 +28,7 @@ pub struct InstantSealParams {
2728

2829
/// Instant seal engine descriptor.
2930
#[derive(Debug, PartialEq, Deserialize)]
31+
#[serde(deny_unknown_fields)]
3032
pub struct InstantSeal {
3133
/// Instant seal parameters.
3234
pub params: InstantSealParams,

json/src/spec/null_engine.rs

+2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use uint::Uint;
2020

2121
/// Authority params deserialization.
2222
#[derive(Debug, PartialEq, Deserialize)]
23+
#[serde(deny_unknown_fields)]
2324
#[serde(rename_all = "camelCase")]
2425
pub struct NullEngineParams {
2526
/// Block reward.
@@ -28,6 +29,7 @@ pub struct NullEngineParams {
2829

2930
/// Null engine descriptor
3031
#[derive(Debug, PartialEq, Deserialize)]
32+
#[serde(deny_unknown_fields)]
3133
pub struct NullEngine {
3234
/// Ethash params.
3335
pub params: NullEngineParams,

json/src/spec/params.rs

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use bytes::Bytes;
2222

2323
/// Spec params.
2424
#[derive(Debug, PartialEq, Deserialize)]
25+
#[serde(deny_unknown_fields)]
2526
#[serde(rename_all = "camelCase")]
2627
pub struct Params {
2728
/// Account start nonce, defaults to 0.

json/src/spec/seal.rs

+4
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use bytes::Bytes;
2222

2323
/// Ethereum seal.
2424
#[derive(Debug, PartialEq, Deserialize)]
25+
#[serde(deny_unknown_fields)]
2526
#[serde(rename_all = "camelCase")]
2627
pub struct Ethereum {
2728
/// Seal nonce.
@@ -32,6 +33,7 @@ pub struct Ethereum {
3233

3334
/// AuthorityRound seal.
3435
#[derive(Debug, PartialEq, Deserialize)]
36+
#[serde(deny_unknown_fields)]
3537
pub struct AuthorityRoundSeal {
3638
/// Seal step.
3739
pub step: Uint,
@@ -41,6 +43,7 @@ pub struct AuthorityRoundSeal {
4143

4244
/// Tendermint seal.
4345
#[derive(Debug, PartialEq, Deserialize)]
46+
#[serde(deny_unknown_fields)]
4447
pub struct TendermintSeal {
4548
/// Seal round.
4649
pub round: Uint,
@@ -52,6 +55,7 @@ pub struct TendermintSeal {
5255

5356
/// Seal variants.
5457
#[derive(Debug, PartialEq, Deserialize)]
58+
#[serde(deny_unknown_fields)]
5559
#[serde(rename_all = "camelCase")]
5660
pub enum Seal {
5761
/// Ethereum seal.

json/src/spec/spec.rs

+66-1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ pub enum ForkSpec {
3838

3939
/// Spec deserialization.
4040
#[derive(Debug, PartialEq, Deserialize)]
41+
#[serde(deny_unknown_fields)]
4142
#[serde(rename_all = "camelCase")]
4243
pub struct Spec {
4344
/// Spec name.
@@ -70,6 +71,71 @@ mod tests {
7071
use serde_json;
7172
use spec::spec::Spec;
7273

74+
#[test]
75+
fn should_error_on_unknown_fields() {
76+
let s = r#"{
77+
"name": "Morden",
78+
"dataDir": "morden",
79+
"engine": {
80+
"Ethash": {
81+
"params": {
82+
"minimumDifficulty": "0x020000",
83+
"difficultyBoundDivisor": "0x0800",
84+
"durationLimit": "0x0d",
85+
"homesteadTransition" : "0x",
86+
"daoHardforkTransition": "0xffffffffffffffff",
87+
"daoHardforkBeneficiary": "0x0000000000000000000000000000000000000000",
88+
"daoHardforkAccounts": []
89+
}
90+
}
91+
},
92+
"params": {
93+
"accountStartNonce": "0x0100000",
94+
"maximumExtraDataSize": "0x20",
95+
"minGasLimit": "0x1388",
96+
"networkID" : "0x2",
97+
"forkBlock": "0xffffffffffffffff",
98+
"forkCanonHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
99+
"gasLimitBoundDivisor": "0x20",
100+
"unknownField": "0x0"
101+
},
102+
"genesis": {
103+
"seal": {
104+
"ethereum": {
105+
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
106+
"nonce": "0x00006d6f7264656e"
107+
}
108+
},
109+
"difficulty": "0x20000",
110+
"author": "0x0000000000000000000000000000000000000000",
111+
"timestamp": "0x00",
112+
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
113+
"extraData": "0x",
114+
"gasLimit": "0x2fefd8"
115+
},
116+
"nodes": [
117+
"enode://b1217cbaa440e35ed471157123fe468e19e8b5ad5bedb4b1fdbcbdab6fb2f5ed3e95dd9c24a22a79fdb2352204cea207df27d92bfd21bfd41545e8b16f637499@104.44.138.37:30303"
118+
],
119+
"accounts": {
120+
"0000000000000000000000000000000000000001": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
121+
"0000000000000000000000000000000000000002": { "balance": "1", "nonce": "1048576", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } },
122+
"0000000000000000000000000000000000000003": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } },
123+
"0000000000000000000000000000000000000004": { "balance": "1", "nonce": "1048576", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } },
124+
"102e61f5d8f9bc71d0ad4a084df4e65e05ce0e1c": { "balance": "1606938044258990275541962092341162602522202993782792835301376", "nonce": "1048576" }
125+
},
126+
"hardcodedSync": {
127+
"header": "f901f9a0d405da4e66f1445d455195229624e133f5baafe72b5cf7b3c36c12c8146e98b7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a05fb2b4bfdef7b314451cb138a534d225c922fc0e5fbe25e451142732c3e25c25a088d2ec6b9860aae1a2c3b299f72b6a5d70d7f7ba4722c78f2c49ba96273c2158a007c6fdfa8eea7e86b81f5b0fc0f78f90cc19f4aa60d323151e0cac660199e9a1b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302008003832fefba82524d84568e932a80a0a0349d8c3df71f1a48a9df7d03fd5f14aeee7d91332c009ecaff0a71ead405bd88ab4e252a7e8c2a23",
128+
"totalDifficulty": "0x400000000",
129+
"CHTs": [
130+
"0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa",
131+
"0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544"
132+
]
133+
}
134+
}"#;
135+
let result: Result<Spec, _> = serde_json::from_str(s);
136+
assert!(result.is_err());
137+
}
138+
73139
#[test]
74140
fn spec_deserialization() {
75141
let s = r#"{
@@ -90,7 +156,6 @@ mod tests {
90156
},
91157
"params": {
92158
"accountStartNonce": "0x0100000",
93-
"homesteadTransition": "0x789b0",
94159
"maximumExtraDataSize": "0x20",
95160
"minGasLimit": "0x1388",
96161
"networkID" : "0x2",

json/src/spec/state.rs

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use spec::{Account, Builtin};
2323

2424
/// Blockchain test state deserializer.
2525
#[derive(Debug, PartialEq, Deserialize)]
26+
#[serde(deny_unknown_fields)]
2627
pub struct State(BTreeMap<Address, Account>);
2728

2829
impl State {

0 commit comments

Comments
 (0)