Skip to content

Commit c6a6d11

Browse files
authored
Shelley genesis use serde json arbitrary precision (#363)
* remove serde_aux and use arbitrary_precision feature for decimals * handle exponential notation
1 parent b7acbd3 commit c6a6d11

File tree

3 files changed

+38
-33
lines changed

3 files changed

+38
-33
lines changed

chain/rust/Cargo.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ cbor_event = "2.2.0"
2323
linked-hash-map = "0.5.3"
2424
derivative = "2.2.0"
2525
serde = { version = "1.0", features = ["derive"] }
26-
serde_json = "1.0.57"
26+
serde_json = { version = "1.0.57", features = ["arbitrary_precision"] }
2727
schemars = "0.8.8"
2828

2929
bech32 = "0.7.2"
@@ -38,7 +38,6 @@ num-integer = "0.1.45"
3838
thiserror = "1.0.37"
3939
num = "0.4"
4040
unicode-segmentation = "1.10.1"
41-
serde-aux = "4.5.0"
4241
chrono = "0.4.38"
4342

4443
# non-wasm

chain/rust/src/genesis/shelley/parse.rs

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use cml_core::DeserializeError;
22
use cml_crypto::{
33
chain_crypto::Blake2b256, Ed25519KeyHash, PoolMetadataHash, TransactionHash, VRFKeyHash,
44
};
5+
use num::traits::Pow as _;
56
use serde_json;
67
use std::collections::BTreeMap;
78
use std::io::Read;
@@ -36,8 +37,7 @@ pub enum GenesisJSONError {
3637
pub fn parse_genesis_data<R: Read>(
3738
json: R,
3839
) -> Result<config::ShelleyGenesisData, GenesisJSONError> {
39-
let data_value: serde_json::Value = serde_json::from_reader(json)?;
40-
let data: raw::ShelleyGenesisData = serde_json::from_value(data_value)?;
40+
let data: raw::ShelleyGenesisData = serde_json::from_reader(json)?;
4141

4242
let mut initial_funds = BTreeMap::new();
4343
for (addr_hex, balance) in &data.initialFunds {
@@ -55,7 +55,7 @@ pub fn parse_genesis_data<R: Read>(
5555
// 1) Get stake pools
5656
let mut pools: BTreeMap<Ed25519KeyHash, PoolParams> = BTreeMap::new();
5757
for (pool_id, params) in &raw.pools {
58-
let ration = fraction::Fraction::from_str(&params.margin).unwrap();
58+
let ration = json_number_to_fraction(&params.margin);
5959
let mut owners = Vec::<Ed25519KeyHash>::new();
6060
for owner in &params.owners {
6161
owners.push(Ed25519KeyHash::from_hex(owner)?);
@@ -136,7 +136,7 @@ pub fn parse_genesis_data<R: Read>(
136136
);
137137
}
138138
Ok(config::ShelleyGenesisData {
139-
active_slots_coeff: fraction::Fraction::from_str(&data.activeSlotsCoeff).unwrap(),
139+
active_slots_coeff: json_number_to_fraction(&data.activeSlotsCoeff),
140140
epoch_length: data.epochLength,
141141
gen_delegs,
142142
initial_funds,
@@ -145,11 +145,10 @@ pub fn parse_genesis_data<R: Read>(
145145
network_id,
146146
network_magic: data.networkMagic,
147147
protocol_params: config::ShelleyGenesisProtocolParameters {
148-
a0: fraction::Fraction::from_str(&data.protocolParams.a0).unwrap(),
149-
decentralisation_param: fraction::Fraction::from_str(
148+
a0: json_number_to_fraction(&data.protocolParams.a0),
149+
decentralisation_param: json_number_to_fraction(
150150
&data.protocolParams.decentralisationParam,
151-
)
152-
.unwrap(),
151+
),
153152
e_max: data.protocolParams.eMax,
154153
extra_entropy: config::ShelleyGenesisExtraEntropy {
155154
tag: data.protocolParams.extraEntropy.tag,
@@ -168,18 +167,33 @@ pub fn parse_genesis_data<R: Read>(
168167
data.protocolParams.protocolVersion.major,
169168
data.protocolParams.protocolVersion.minor,
170169
),
171-
rho: fraction::Fraction::from_str(&data.protocolParams.rho).unwrap(),
172-
tau: fraction::Fraction::from_str(&data.protocolParams.tau).unwrap(),
170+
rho: json_number_to_fraction(&data.protocolParams.rho),
171+
tau: json_number_to_fraction(&data.protocolParams.tau),
173172
},
174173
security_param: data.securityParam,
175-
slot_length: fraction::Fraction::from_str(&data.slotLength).unwrap(),
174+
slot_length: json_number_to_fraction(&data.slotLength),
176175
slots_per_kes_period: data.slotsPerKESPeriod,
177176
staking,
178177
system_start: data.systemStart.parse().expect("Failed to parse date"),
179178
update_quorum: data.updateQuorum,
180179
})
181180
}
182181

182+
fn json_number_to_fraction(param: &serde_json::Number) -> fraction::GenericFraction<u64> {
183+
let s = param.to_string();
184+
185+
if let Some(exp_position) = s.find('e').or_else(|| s.find('E')) {
186+
let (a, b) = s.split_at_checked(exp_position).unwrap();
187+
188+
let exp = fraction::Ratio::from(10u64).pow(i32::from_str(&b[1..]).unwrap());
189+
190+
fraction::Fraction::from_str(a).unwrap()
191+
* fraction::Fraction::new(*exp.numer(), *exp.denom())
192+
} else {
193+
fraction::Fraction::from_str(&param.to_string()).unwrap()
194+
}
195+
}
196+
183197
pub fn redeem_address_to_txid(pubkey: &Address) -> TransactionHash {
184198
let txid = Blake2b256::new(&pubkey.to_raw_bytes());
185199
TransactionHash::from(*txid.as_hash_bytes())

chain/rust/src/genesis/shelley/raw.rs

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use crate::assets::Coin;
22
use serde::{Deserialize, Serialize};
3-
use serde_aux::prelude::*;
43
use std::collections::HashMap;
54

65
/// Parsing of the JSON representation of the Shelley genesis block
@@ -11,8 +10,7 @@ use std::collections::HashMap;
1110
#[derive(Serialize, Deserialize, Debug)]
1211
pub struct ShelleyGenesisData {
1312
// convert lossless JSON floats to string to avoid lossy Rust f64
14-
#[serde(deserialize_with = "deserialize_string_from_number")]
15-
pub activeSlotsCoeff: String,
13+
pub activeSlotsCoeff: serde_json::Number,
1614
pub epochLength: u64,
1715
pub genDelegs: HashMap<String, ShelleyGenesisDelegations>,
1816
pub initialFunds: HashMap<String, Coin>,
@@ -22,8 +20,7 @@ pub struct ShelleyGenesisData {
2220
pub networkMagic: u64,
2321
pub protocolParams: ShelleyGenesisProtocolParameters,
2422
pub securityParam: u64,
25-
#[serde(deserialize_with = "deserialize_string_from_number")]
26-
pub slotLength: String,
23+
pub slotLength: serde_json::Number,
2724
pub slotsPerKESPeriod: u64,
2825
pub staking: Option<ShelleyGenesisStaking>,
2926
pub systemStart: String,
@@ -40,12 +37,10 @@ pub struct ShelleyGenesisDelegations {
4037
#[allow(non_snake_case)]
4138
#[derive(Serialize, Deserialize, Debug)]
4239
pub struct ShelleyGenesisProtocolParameters {
43-
// convert lossless JSON floats to string to avoid lossy Rust f64
44-
#[serde(deserialize_with = "deserialize_string_from_number")]
45-
pub a0: String,
46-
// convert lossless JSON floats to string to avoid lossy Rust f64
47-
#[serde(deserialize_with = "deserialize_string_from_number")]
48-
pub decentralisationParam: String,
40+
// this uses the serde_json arbitrary_precision feature to avoid lossy Rust f64
41+
pub a0: serde_json::Number,
42+
// this uses the serde_json arbitrary_precision feature to avoid lossy Rust f64
43+
pub decentralisationParam: serde_json::Number,
4944
pub eMax: u64,
5045
pub extraEntropy: ShelleyGenesisExtraEntropy,
5146
pub keyDeposit: Coin,
@@ -59,12 +54,10 @@ pub struct ShelleyGenesisProtocolParameters {
5954
pub nOpt: u64,
6055
pub poolDeposit: Coin,
6156
pub protocolVersion: ShelleyGenesisProtocolVersion,
62-
// convert lossless JSON floats to string to avoid lossy Rust f64
63-
#[serde(deserialize_with = "deserialize_string_from_number")]
64-
pub rho: String,
65-
// convert lossless JSON floats to string to avoid lossy Rust f64
66-
#[serde(deserialize_with = "deserialize_string_from_number")]
67-
pub tau: String,
57+
// this uses the serde_json arbitrary_precision feature to avoid lossy Rust f64
58+
pub rho: serde_json::Number,
59+
// this uses the serde_json arbitrary_precision feature to avoid lossy Rust f64
60+
pub tau: serde_json::Number,
6861
}
6962

7063
#[allow(non_snake_case)]
@@ -91,9 +84,8 @@ pub struct ShelleyGenesisStaking {
9184
#[derive(Serialize, Deserialize, Debug)]
9285
pub struct ShelleyGenesisPool {
9386
pub cost: Coin,
94-
// convert lossless JSON floats to string to avoid lossy Rust f64
95-
#[serde(deserialize_with = "deserialize_string_from_number")]
96-
pub margin: String,
87+
// this uses the serde_json arbitrary_precision feature to avoid lossy Rust f64
88+
pub margin: serde_json::Number,
9789
pub metadata: Option<ShelleyGenesisPoolMetadata>,
9890
pub owners: Vec<String>,
9991
pub pledge: Coin,

0 commit comments

Comments
 (0)