Fix serde
Motivation
Fix the bug in Block serialize and deserialize
@vicsn
In current test cases, we sample a couple of genesis blocks which's cumulative_weight is 0 to make tests on serialize and deserialize.
I don't think any adjustments are necessary, but we need to check if the types used in snarkVM are unsupported by JSON
@ghostant-1017 great find! Would it be possible to add some of the failing test cases to this PR? Also curious what are the implications in rolling out the fix? Would it break any existing code/infra/services?
@d0cd In JSON, the largest numeric type is f64, so any values in the u128 range that exceed f64 will cause test case failures. However, existing test cases do not cover this scenario.
To my knowledge, only the RPC interfaces related to /block/ have been affected by serialization.
Affect:
The json block returned after height 1203484 on mainnet can no longer be deserialized by the Block provided by snarkVM.
In current test cases, we sample a couple of genesis blocks which's cumulative_weight is 0 to make tests on serialize and deserialize.
I think a clean approach to testing could be to add a function similar to sample_genesis_block(, which uses Block::from_unchecked to construct a random invalid block to test serialization/deserialization on.
If you're not interested to add the test, just let us know and I'll close this PR, adding the test in a new one.
Nice find. Why did
test_serde_jsonbelow not catch any issues? Can any of the underlying test logic be adjusted so it would have failed earlier? And as a result, would we need to re-evaluate any othertest_serde_jsonfunctions in snarkVM?
@vicsn
serde-json by default deserializes directly to an f64 if it finds an integer that can only be represented by the u128 type.
The Number enum in serde-json without the arbitraryprecision flag can hold a u64, i64, or f64. Thus without the arbitraryprecision flag, Number isn't capable of holding a u128 directly and defaults to storing it as an f64. The arbitraryprecision flag creates an alternative Number enum that represents higher precision with two u64s, i64s, or f64s. I don't think it would be wise to rely on that flag because it would change how every single type is represented during the json Deserialization process and we're unaware the side effects that would have. It would also make everyone else using serde-json in Rust projects surrounding Aleo to use it.
The reason we didn't likely see it in testing, is because we didn't end up testing with a number above u64::MAX. If we had we might've caught the error, so test cases that use integers that require more than 8 bits should be added.
@vicsn I will make some changes according to @iamalwaysuncomfortable , and add the test case sir.
check-clippy finishes fine, in 34s. It is just CircleCI being its usual garbage.