From 2f7d108b536fd1fdce1d2a26ec670548e8161fb1 Mon Sep 17 00:00:00 2001 From: Santiago Carmuega Date: Wed, 14 Sep 2022 15:00:53 -0300 Subject: [PATCH] feat(primitives): Preserve order of map structures (#192) --- pallas-codec/src/utils.rs | 45 ++++++++++++++++++++------ pallas-primitives/src/alonzo/model.rs | 23 +++++++------ pallas-primitives/src/babbage/model.rs | 13 ++++---- 3 files changed, 53 insertions(+), 28 deletions(-) diff --git a/pallas-codec/src/utils.rs b/pallas-codec/src/utils.rs index d75799b7..bd6d453b 100644 --- a/pallas-codec/src/utils.rs +++ b/pallas-codec/src/utils.rs @@ -37,19 +37,32 @@ impl minicbor::Encode for SkipCbor { /// canonicalization for isomorphic decoding / encoding operators, we use a Vec /// as the underlaying struct for storage of the items (as opposed to a BTreeMap /// or HashMap). -#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] -pub enum KeyValuePairs { +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +#[serde(from = "Vec::<(K, V)>", into = "Vec::<(K, V)>")] +pub enum KeyValuePairs +where + K: Clone, + V: Clone, +{ Def(Vec<(K, V)>), Indef(Vec<(K, V)>), } -impl KeyValuePairs { +impl KeyValuePairs +where + K: Clone, + V: Clone, +{ pub fn to_vec(self) -> Vec<(K, V)> { self.into() } } -impl From> for Vec<(K, V)> { +impl From> for Vec<(K, V)> +where + K: Clone, + V: Clone, +{ fn from(other: KeyValuePairs) -> Self { match other { KeyValuePairs::Def(x) => x, @@ -58,7 +71,21 @@ impl From> for Vec<(K, V)> { } } -impl Deref for KeyValuePairs { +impl From> for KeyValuePairs +where + K: Clone, + V: Clone, +{ + fn from(other: Vec<(K, V)>) -> Self { + KeyValuePairs::Def(other) + } +} + +impl Deref for KeyValuePairs +where + K: Clone, + V: Clone, +{ type Target = Vec<(K, V)>; fn deref(&self) -> &Self::Target { @@ -71,8 +98,8 @@ impl Deref for KeyValuePairs { impl<'b, C, K, V> minicbor::decode::Decode<'b, C> for KeyValuePairs where - K: Encode + Decode<'b, C>, - V: Encode + Decode<'b, C>, + K: Encode + Decode<'b, C> + Clone, + V: Encode + Decode<'b, C> + Clone, { fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result { let datatype = d.datatype()?; @@ -92,8 +119,8 @@ where impl minicbor::encode::Encode for KeyValuePairs where - K: Encode, - V: Encode, + K: Encode + Clone, + V: Encode + Clone, { fn encode( &self, diff --git a/pallas-primitives/src/alonzo/model.rs b/pallas-primitives/src/alonzo/model.rs index 0aae38af..7553fdfd 100644 --- a/pallas-primitives/src/alonzo/model.rs +++ b/pallas-primitives/src/alonzo/model.rs @@ -2,8 +2,6 @@ //! //! Handcrafted, idiomatic rust artifacts based on based on the [Alonzo CDDL](https://github.com/input-output-hk/cardano-ledger/blob/master/eras/alonzo/test-suite/cddl-files/alonzo.cddl) file in IOHK repo. -use std::collections::BTreeMap; - use serde::{Deserialize, Serialize}; use pallas_codec::minicbor::{data::Tag, Decode, Encode}; @@ -115,7 +113,7 @@ pub type PolicyId = Hash<28>; pub type AssetName = Bytes; -pub type Multiasset = BTreeMap>; +pub type Multiasset = KeyValuePairs>; pub type Mint = Multiasset; @@ -232,7 +230,7 @@ impl minicbor::encode::Encode for InstantaneousRewardSource { #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] pub enum InstantaneousRewardTarget { - StakeCredentials(BTreeMap), + StakeCredentials(KeyValuePairs), OtherAccountingPot(Coin), } @@ -284,7 +282,7 @@ pub struct MoveInstantaneousReward { pub type RewardAccount = Bytes; -pub type Withdrawals = BTreeMap; +pub type Withdrawals = KeyValuePairs; pub type RequiredSigners = Vec; @@ -642,7 +640,7 @@ pub enum Language { pub type CostModel = Vec; -pub type CostMdls = BTreeMap; +pub type CostMdls = KeyValuePairs; #[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)] #[cbor(map)] @@ -700,7 +698,7 @@ pub struct ProtocolParamUpdate { #[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)] pub struct Update { #[n(0)] - pub proposed_protocol_parameter_updates: BTreeMap, + pub proposed_protocol_parameter_updates: KeyValuePairs, #[n(1)] pub epoch: Epoch, @@ -916,7 +914,7 @@ impl minicbor::encode::Encode for BigInt { #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] pub enum PlutusData { Constr(Constr), - Map(BTreeMap), + Map(KeyValuePairs), BigInt(BigInt), BoundedBytes(Bytes), Array(Vec), @@ -1235,7 +1233,7 @@ pub enum Metadatum { Bytes(Bytes), Text(String), Array(Vec), - Map(BTreeMap), + Map(KeyValuePairs), } impl<'b, C> minicbor::Decode<'b, C> for Metadatum { @@ -1294,7 +1292,7 @@ impl minicbor::Encode for Metadatum { pub type MetadatumLabel = u64; -pub type Metadata = BTreeMap; +pub type Metadata = KeyValuePairs; #[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Clone)] pub struct ShelleyMaAuxiliaryData { @@ -1368,7 +1366,7 @@ pub struct Block { pub transaction_witness_sets: Vec, #[n(3)] - pub auxiliary_data_set: BTreeMap, + pub auxiliary_data_set: KeyValuePairs, #[n(4)] pub invalid_transactions: Option>, @@ -1419,7 +1417,8 @@ impl<'b> From> for Block { .to_vec() .into_iter() .map(|(k, v)| (k, v.unwrap())) - .collect(), + .collect::>() + .into(), invalid_transactions: x.invalid_transactions.map(|x| x.into()), } } diff --git a/pallas-primitives/src/babbage/model.rs b/pallas-primitives/src/babbage/model.rs index 5a204251..acf69cd0 100644 --- a/pallas-primitives/src/babbage/model.rs +++ b/pallas-primitives/src/babbage/model.rs @@ -2,8 +2,6 @@ //! //! Handcrafted, idiomatic rust artifacts based on based on the [Babbage CDDL](https://github.com/input-output-hk/cardano-ledger/blob/master/eras/babbage/test-suite/cddl-files/babbage.cddl) file in IOHK repo. -use std::collections::BTreeMap; - use serde::{Deserialize, Serialize}; use pallas_codec::minicbor::{Decode, Encode}; @@ -117,7 +115,7 @@ pub use crate::alonzo::MoveInstantaneousReward; pub use crate::alonzo::RewardAccount; -pub type Withdrawals = BTreeMap; +pub type Withdrawals = KeyValuePairs; pub type RequiredSigners = Vec; @@ -226,7 +224,7 @@ pub struct ProtocolParamUpdate { #[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)] pub struct Update { #[n(0)] - pub proposed_protocol_parameter_updates: BTreeMap, + pub proposed_protocol_parameter_updates: KeyValuePairs, #[n(1)] pub epoch: Epoch, @@ -251,7 +249,7 @@ pub struct TransactionBody { pub certificates: Option>, #[n(5)] - pub withdrawals: Option>, + pub withdrawals: Option>, #[n(6)] pub update: Option, @@ -565,7 +563,7 @@ pub struct Block { pub transaction_witness_sets: Vec, #[n(3)] - pub auxiliary_data_set: BTreeMap, + pub auxiliary_data_set: KeyValuePairs, #[n(4)] pub invalid_transactions: Option>, @@ -616,7 +614,8 @@ impl<'b> From> for Block { .to_vec() .into_iter() .map(|(k, v)| (k, v.unwrap())) - .collect(), + .collect::>() + .into(), invalid_transactions: x.invalid_transactions.map(|x| x.into()), } }