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

spec: Validate required divisor fields are not 0 #7933

Merged
merged 6 commits into from
Feb 19, 2018
Merged

spec: Validate required divisor fields are not 0 #7933

merged 6 commits into from
Feb 19, 2018

Conversation

asymmetric
Copy link
Contributor

@asymmetric asymmetric commented Feb 18, 2018

This is a replacement for #7882, implementing the check at the the deserialization level with the addition of a #[serde(deserialize_with) attribute on the required Uint divisor fields.

Optional<Uint> divisor fields are not checked at the moment, since I was having trouble getting that to work.

/cc @AndreaSilva @rphmeier

Closes #7482.
Closes #7882.

It's used to validate that a Spec's uint field used as a divisor is not zero.
Prevents panics due to divide-by-zero on the gas_limit_bound_divisor
field.
Prevents panics due to divide-by-zero on the difficulty_bound_divisor
field.
@parity-cla-bot
Copy link

It looks like @asymmetric signed our Contributor License Agreement. 👍

Many thanks,

Parity Technologies CLA Bot

Copy link
Collaborator

@debris debris left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks!

"maxCodeSize": "0x1000"
}"#;

let _deserialized: Params = serde_json::from_str(s).unwrap();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how does printed error look like? Does it say describe which field is expected to have a non-zero value?

Maybe instead of using should_panic you could do:

assert_eq!(serde_json::from_str(s).unwrap_err().to_string(), "error message");

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't specify which field is failing, only it's position. The error message looks like this:
"invalid value: integer `0`, expected a non-zero value at line 3 column 39". I agree the test can be converted not to use should_panic. It would be nice to show the field name but this is the same behavior we already have for other fields.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is it better to avoid #[should_panic(expect)]? I thought that using an attribute would make more sense, since it's available.

@debris
Copy link
Collaborator

debris commented Feb 18, 2018

@paritytech/ci @General-Beck last commit - 555e0cb is not run by CI. Could you check why?

@debris debris added A6-mustntgrumble 💦 Pull request has areas for improvement. The author need not address them before merging. M4-core ⛓ Core client code / Rust. labels Feb 18, 2018
Copy link
Contributor

@andresilva andresilva left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! 👍

@andresilva
Copy link
Contributor

andresilva commented Feb 18, 2018

@asymmetric I think the following will work for Option<Uint>:

pub fn validate_opt_non_zero<'de, D>(d: D) -> Result<Option<Uint>, D::Error> where D: Deserializer<'de> {
	let value: Option<Uint> = Option::deserialize(d)?;

	if let Some(value) = value {
		if value == Uint(U256::from(0)) {
			return Err(Error::invalid_value(Unexpected::Unsigned(value.into()), &"a non-zero value"))
		}
	}

	Ok(value)
}

You then need to enable default when declaring the deserialize_with:

#[serde(rename="difficultyIncrementDivisor")]
#[serde(default, deserialize_with="uint::validate_opt_non_zero")]
pub difficulty_increment_divisor: Option<Uint>,

@asymmetric
Copy link
Contributor Author

asymmetric commented Feb 18, 2018

@andresilva Thanks, that seems to have done the trick!

I was declaring the validation function as

pub fn validate_optional_non_zero<'de, D>(d: Option<D>) -> Result<Option<Uint>, D::Error> where D: Deserializer<'de>

(i.e. the argument was an Option<D>), which caused:

error[E0308]: mismatched types
  --> json/src/spec/ethash.rs:23:35
   |
23 | #[derive(Clone, Debug, PartialEq, Deserialize)]
   |                                   ^^^^^^^^^^^
   |                                   |
   |                                   expected enum `std::option::Option`, found type parameter
   |                                   help: try using a variant of the expected type: `serde::export::Some(__deserializer)`
   |
   = note: expected type `std::option::Option<_>`
              found type `__D`

By the way, it compiles even without #[serde(default)]. What does the attribute do, e.g. what's the default deserialization for the field?

@5chdn 5chdn added A7-looksgoodtestsfail 🤖 Pull request is reviewed well, but cannot be merged due to tests failing. and removed A6-mustntgrumble 💦 Pull request has areas for improvement. The author need not address them before merging. labels Feb 18, 2018
@5chdn 5chdn added this to the 1.10 milestone Feb 18, 2018
@5chdn
Copy link
Contributor

5chdn commented Feb 18, 2018

Tests fail :)

@andresilva
Copy link
Contributor

andresilva commented Feb 18, 2018

@asymmetric I think when you use deserialize_with it no longer sets default to true, which means missing fields are not deserialized as None and instead you get a missing field error (this is why the tests are failing).

When using `#[serde(deserialize_with)]`, `#[serde(default)]` must be specified so that missing
fields can be deserialized with the deserializer for `None`.
@5chdn 5chdn merged commit e630f64 into openethereum:master Feb 19, 2018
@5chdn 5chdn added the B0-patch label Feb 19, 2018
@asymmetric asymmetric deleted the asymmetric/validate-uint branch February 19, 2018 11:47
andresilva pushed a commit that referenced this pull request Feb 19, 2018
* Add validate_non_zero function

It's used to validate that a Spec's uint field used as a divisor is not zero.

* Add deserialize_with to gas_limit_bound_divisor

Prevents panics due to divide-by-zero on the gas_limit_bound_divisor
field.

* Add deserialize_with to difficulty_bound_divisor

Prevents panics due to divide-by-zero on the difficulty_bound_divisor
field.

* Add validate_optional_non_zero function

Used to validate Option<Uint> divisor fields.

* Use deserialize_with on optional divisor fields.

* Add #[serde(default)] attribute to divisor fields

When using `#[serde(deserialize_with)]`, `#[serde(default)]` must be specified so that missing
fields can be deserialized with the deserializer for `None`.
@andresilva andresilva mentioned this pull request Feb 19, 2018
andresilva pushed a commit that referenced this pull request Feb 19, 2018
* Add validate_non_zero function

It's used to validate that a Spec's uint field used as a divisor is not zero.

* Add deserialize_with to gas_limit_bound_divisor

Prevents panics due to divide-by-zero on the gas_limit_bound_divisor
field.

* Add deserialize_with to difficulty_bound_divisor

Prevents panics due to divide-by-zero on the difficulty_bound_divisor
field.

* Add validate_optional_non_zero function

Used to validate Option<Uint> divisor fields.

* Use deserialize_with on optional divisor fields.

* Add #[serde(default)] attribute to divisor fields

When using `#[serde(deserialize_with)]`, `#[serde(default)]` must be specified so that missing
fields can be deserialized with the deserializer for `None`.
5chdn pushed a commit that referenced this pull request Feb 19, 2018
* ECIP 1041 - Remove Difficulty Bomb (#7905)

Enable difficulty bomb defusion at block:
 - 5900000 on Ethereum Classic mainnet,
 - 2300000 on morden testnet.

Reference:
https://github.com/ethereumproject/ECIPs/blob/master/ECIPs/ECIP-1041.md

* spec: Validate required divisor fields are not 0 (#7933)

* Add validate_non_zero function

It's used to validate that a Spec's uint field used as a divisor is not zero.

* Add deserialize_with to gas_limit_bound_divisor

Prevents panics due to divide-by-zero on the gas_limit_bound_divisor
field.

* Add deserialize_with to difficulty_bound_divisor

Prevents panics due to divide-by-zero on the difficulty_bound_divisor
field.

* Add validate_optional_non_zero function

Used to validate Option<Uint> divisor fields.

* Use deserialize_with on optional divisor fields.

* Add #[serde(default)] attribute to divisor fields

When using `#[serde(deserialize_with)]`, `#[serde(default)]` must be specified so that missing
fields can be deserialized with the deserializer for `None`.

* Kovan WASM fork code (#7849)

* kovan fork code

* introduce ethcore level vm_factory and let it fail

* fix json tests

* wasmcosts as option

* review changes

* wasm costs in parser

* fix evm tests

* review fixes

* fix test

* remove redundant json field
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
A7-looksgoodtestsfail 🤖 Pull request is reviewed well, but cannot be merged due to tests failing. M4-core ⛓ Core client code / Rust.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants