From 23a25f53b6f00b601ba613a951e4e52175c6c3fe Mon Sep 17 00:00:00 2001 From: rooooooooob Date: Thu, 28 Mar 2024 07:44:08 -0700 Subject: [PATCH 1/5] New Conway.cddl updates (cml-chain/cml-chain-wasm) Includes: * IntersectMBO/cardano-ledger#4003 * IntersectMBO/cardano-ledger#4178 * IntersectMBO/cardano-ledger#4055 * IntersectMBO/cardano-ledger#4117 * IntersectMBO/cardano-ledger#4040 TODO: [ ] need to check how this affects the script data hash and test that [ ] multi-era --- chain/rust/src/block/serialization.rs | 14 +- .../rust/src/builders/certificate_builder.rs | 2 +- chain/rust/src/builders/input_builder.rs | 5 +- chain/rust/src/builders/mint_builder.rs | 2 +- chain/rust/src/builders/redeemer_builder.rs | 20 +- chain/rust/src/builders/tx_builder.rs | 38 +- chain/rust/src/builders/withdrawal_builder.rs | 2 +- chain/rust/src/builders/witness_builder.rs | 53 +- chain/rust/src/cbor_encodings.rs | 1 + chain/rust/src/certs/mod.rs | 4 +- chain/rust/src/certs/serialization.rs | 22 +- chain/rust/src/crypto/hash.rs | 69 +- chain/rust/src/deposit.rs | 4 +- chain/rust/src/fees.rs | 2 +- chain/rust/src/governance/cbor_encodings.rs | 2 + chain/rust/src/governance/mod.rs | 15 +- chain/rust/src/governance/serialization.rs | 84 +- chain/rust/src/lib.rs | 47 +- chain/rust/src/plutus/cbor_encodings.rs | 14 +- chain/rust/src/plutus/mod.rs | 129 +++- chain/rust/src/plutus/serialization.rs | 525 ++++++++++++- chain/rust/src/plutus/utils.rs | 46 +- chain/rust/src/serialization.rs | 95 ++- chain/rust/src/transaction/cbor_encodings.rs | 15 - chain/rust/src/transaction/mod.rs | 44 +- chain/rust/src/transaction/serialization.rs | 601 ++------------- chain/rust/src/transaction/utils.rs | 14 +- chain/rust/src/utils.rs | 295 +++++++- .../wasm/src/builders/certificate_builder.rs | 2 +- chain/wasm/src/builders/input_builder.rs | 4 +- chain/wasm/src/builders/mint_builder.rs | 2 +- chain/wasm/src/builders/redeemer_builder.rs | 9 +- chain/wasm/src/builders/tx_builder.rs | 6 +- chain/wasm/src/builders/withdrawal_builder.rs | 2 +- chain/wasm/src/builders/witness_builder.rs | 10 +- chain/wasm/src/crypto/hash.rs | 15 +- chain/wasm/src/governance/mod.rs | 21 +- chain/wasm/src/lib.rs | 716 ++++-------------- chain/wasm/src/plutus/mod.rs | 130 +++- chain/wasm/src/plutus/utils.rs | 16 +- chain/wasm/src/transaction/mod.rs | 88 +-- chain/wasm/src/utils.rs | 60 ++ specs/conway/certs.cddl | 2 +- specs/conway/governance.cddl | 10 +- specs/conway/lib.cddl | 15 +- specs/conway/plutus.cddl | 20 +- specs/conway/transaction.cddl | 60 +- specs/multiera/allegra/mod.cddl | 19 +- specs/multiera/alonzo/mod.cddl | 16 +- specs/multiera/babbage/mod.cddl | 2 +- specs/multiera/cml_chain/certs.cddl | 17 +- specs/multiera/cml_chain/plutus.cddl | 1 - specs/multiera/shelley/mod.cddl | 47 +- 53 files changed, 1936 insertions(+), 1518 deletions(-) diff --git a/chain/rust/src/block/serialization.rs b/chain/rust/src/block/serialization.rs index e6cad1b1..4db61ef1 100644 --- a/chain/rust/src/block/serialization.rs +++ b/chain/rust/src/block/serialization.rs @@ -391,13 +391,13 @@ impl Deserialize for HeaderBody { (|| -> Result<_, DeserializeError> { let (block_number, block_number_encoding) = raw .unsigned_integer_sz() - .map(|(x, enc)| (x, Some(enc))) .map_err(Into::::into) + .map(|(x, enc)| (x, Some(enc))) .map_err(|e: DeserializeError| e.annotate("block_number"))?; let (slot, slot_encoding) = raw .unsigned_integer_sz() - .map(|(x, enc)| (x, Some(enc))) .map_err(Into::::into) + .map(|(x, enc)| (x, Some(enc))) .map_err(|e: DeserializeError| e.annotate("slot"))?; let (prev_hash, prev_hash_encoding) = (|| -> Result<_, DeserializeError> { Ok(match raw.cbor_type()? != cbor_event::Type::Special { @@ -444,8 +444,8 @@ impl Deserialize for HeaderBody { .map_err(|e: DeserializeError| e.annotate("vrf_result"))?; let (block_body_size, block_body_size_encoding) = raw .unsigned_integer_sz() - .map(|(x, enc)| (x, Some(enc))) .map_err(Into::::into) + .map(|(x, enc)| (x, Some(enc))) .map_err(|e: DeserializeError| e.annotate("block_body_size"))?; let (block_body_hash, block_body_hash_encoding) = raw .bytes_sz() @@ -600,13 +600,13 @@ impl DeserializeEmbeddedGroup for OperationalCert { .map_err(|e: DeserializeError| e.annotate("hot_vkey"))?; let (sequence_number, sequence_number_encoding) = raw .unsigned_integer_sz() - .map(|(x, enc)| (x, Some(enc))) .map_err(Into::::into) + .map(|(x, enc)| (x, Some(enc))) .map_err(|e: DeserializeError| e.annotate("sequence_number"))?; let (kes_period, kes_period_encoding) = raw .unsigned_integer_sz() - .map(|(x, enc)| (x, Some(enc))) .map_err(Into::::into) + .map(|(x, enc)| (x, Some(enc))) .map_err(|e: DeserializeError| e.annotate("kes_period"))?; let (sigma, sigma_encoding) = raw .bytes_sz() @@ -716,13 +716,13 @@ impl DeserializeEmbeddedGroup for ProtocolVersion { (|| -> Result<_, DeserializeError> { let (major, major_encoding) = raw .unsigned_integer_sz() - .map(|(x, enc)| (x, Some(enc))) .map_err(Into::::into) + .map(|(x, enc)| (x, Some(enc))) .map_err(|e: DeserializeError| e.annotate("major"))?; let (minor, minor_encoding) = raw .unsigned_integer_sz() - .map(|(x, enc)| (x, Some(enc))) .map_err(Into::::into) + .map(|(x, enc)| (x, Some(enc))) .map_err(|e: DeserializeError| e.annotate("minor"))?; Ok(ProtocolVersion { major, diff --git a/chain/rust/src/builders/certificate_builder.rs b/chain/rust/src/builders/certificate_builder.rs index b7a529da..2d2aadf3 100644 --- a/chain/rust/src/builders/certificate_builder.rs +++ b/chain/rust/src/builders/certificate_builder.rs @@ -6,7 +6,7 @@ use super::witness_builder::{NativeScriptWitnessInfo, RequiredWitnessSet}; use crate::{ certs::{Certificate, StakeCredential}, - transaction::RequiredSigners, + RequiredSigners, }; use cml_crypto::{Ed25519KeyHash, ScriptHash}; diff --git a/chain/rust/src/builders/input_builder.rs b/chain/rust/src/builders/input_builder.rs index 930fdbd5..b2b659a5 100644 --- a/chain/rust/src/builders/input_builder.rs +++ b/chain/rust/src/builders/input_builder.rs @@ -10,8 +10,8 @@ use crate::{ certs::StakeCredential, crypto::hash::hash_plutus_data, plutus::PlutusData, - transaction::{RequiredSigners, TransactionInput, TransactionOutput}, - NativeScript, + transaction::{TransactionInput, TransactionOutput}, + NativeScript, RequiredSigners }; #[derive(Debug, thiserror::Error)] @@ -140,6 +140,7 @@ impl SingleInputBuilder { ) -> Result { let mut required_wits = RequiredWitnessSet::default(); required_signers + .as_ref() .iter() .for_each(|required_signer| required_wits.add_vkey_key_hash(*required_signer)); input_required_wits(&self.utxo_info, &mut required_wits); diff --git a/chain/rust/src/builders/mint_builder.rs b/chain/rust/src/builders/mint_builder.rs index 2c934c3e..4446116f 100644 --- a/chain/rust/src/builders/mint_builder.rs +++ b/chain/rust/src/builders/mint_builder.rs @@ -4,7 +4,7 @@ use super::witness_builder::{NativeScriptWitnessInfo, RequiredWitnessSet}; use cml_core::ordered_hash_map::OrderedHashMap; -use crate::{assets::AssetName, transaction::RequiredSigners, NativeScript, PolicyId}; +use crate::{assets::AssetName, RequiredSigners, NativeScript, PolicyId}; #[derive(Clone)] pub struct MintBuilderResult { diff --git a/chain/rust/src/builders/redeemer_builder.rs b/chain/rust/src/builders/redeemer_builder.rs index d743fdad..335bdf58 100644 --- a/chain/rust/src/builders/redeemer_builder.rs +++ b/chain/rust/src/builders/redeemer_builder.rs @@ -4,7 +4,7 @@ use super::{ }; use crate::{ address::RewardAddress, - plutus::{ExUnits, PlutusData, Redeemer, RedeemerTag}, + plutus::{ExUnits, LegacyRedeemer, PlutusData, RedeemerTag, Redeemers}, transaction::TransactionInput, PolicyId, }; @@ -22,8 +22,8 @@ impl RedeemerWitnessKey { } } -impl From<&Redeemer> for RedeemerWitnessKey { - fn from(redeemer: &Redeemer) -> Self { +impl From<&LegacyRedeemer> for RedeemerWitnessKey { + fn from(redeemer: &LegacyRedeemer) -> Self { Self { tag: redeemer.tag, index: redeemer.index, @@ -31,7 +31,7 @@ impl From<&Redeemer> for RedeemerWitnessKey { } } -/// Redeemer without the tag of index +/// LegacyRedeemer without the tag of index /// This allows builder code to return partial redeemers /// and then later have them placed in the right context #[derive(Clone, Debug)] @@ -142,6 +142,8 @@ impl RedeemerSetBuilder { ex_units, ))); } + RedeemerTag::Proposing => todo!("https://github.com/dcSpark/cardano-multiplatform-lib/issues/323"), + RedeemerTag::Voting => todo!("https://github.com/dcSpark/cardano-multiplatform-lib/issues/323"), } } @@ -214,7 +216,7 @@ impl RedeemerSetBuilder { pub fn build( &self, default_to_dummy_exunits: bool, - ) -> Result, RedeemerBuilderError> { + ) -> Result { let mut redeemers = Vec::new(); // Calling iter on a BTreeMap returns a list of sorted keys self.remove_placeholders_and_tag( @@ -242,12 +244,12 @@ impl RedeemerSetBuilder { default_to_dummy_exunits, )?; - Ok(redeemers) + Ok(Redeemers::new_arr_legacy_redeemer(redeemers)) } fn remove_placeholders_and_tag<'a, K: Debug + Clone>( &self, - redeemers: &mut Vec, + redeemers: &mut Vec, tag: RedeemerTag, entries: &mut dyn Iterator)>, default_to_dummy_exunits: bool, @@ -280,12 +282,12 @@ impl RedeemerSetBuilder { fn tag_redeemer( tag: RedeemerTag, untagged_redeemers: &[Option], - ) -> Vec { + ) -> Vec { let mut result = Vec::new(); for (index, untagged_redeemer) in untagged_redeemers.iter().enumerate() { if let Some(untagged_redeemer) = untagged_redeemer { - result.push(Redeemer::new( + result.push(LegacyRedeemer::new( tag, index as u64, untagged_redeemer.data.clone(), diff --git a/chain/rust/src/builders/tx_builder.rs b/chain/rust/src/builders/tx_builder.rs index 7ce221ff..b2633a62 100644 --- a/chain/rust/src/builders/tx_builder.rs +++ b/chain/rust/src/builders/tx_builder.rs @@ -22,8 +22,8 @@ use crate::crypto::{BootstrapWitness, Vkeywitness}; use crate::deposit::{internal_get_deposit, internal_get_implicit_input}; use crate::fees::LinearFee; use crate::min_ada::min_ada_required; -use crate::plutus::PlutusData; -use crate::plutus::{CostModels, ExUnits, Language, Redeemer}; +use crate::plutus::{PlutusData, Redeemers}; +use crate::plutus::{CostModels, ExUnits, Language}; use crate::transaction::{ DatumOption, ScriptRef, Transaction, TransactionBody, TransactionInput, TransactionOutput, TransactionWitnessSet, @@ -113,6 +113,7 @@ impl WitnessBuilders { let redeemers = self.redeemer_set_builder.build(true)?; let mut witness_set_clone = self.witness_set_builder.clone(); redeemers + .to_flat_format() .into_iter() .for_each(|r| witness_set_clone.add_redeemer(r)); @@ -714,8 +715,8 @@ impl TransactionBuilder { data { required_signers - .into_iter() - .for_each(|signer| self.add_required_signer(signer)); + .iter() + .for_each(|signer| self.add_required_signer(*signer)); match &script_witness.script { PlutusScriptWitness::Ref(ref_script) => { @@ -867,8 +868,8 @@ impl TransactionBuilder { .add_input_aggregate_fake_witness_data(&data); if let InputAggregateWitnessData::PlutusScript(_, required_signers, _) = data { required_signers - .into_iter() - .for_each(|signer| self.add_required_signer(signer)); + .iter() + .for_each(|signer| self.add_required_signer(*signer)); } } self.witness_builders @@ -900,8 +901,8 @@ impl TransactionBuilder { .add_input_aggregate_fake_witness_data(&data); if let InputAggregateWitnessData::PlutusScript(_, required_signers, _) = data { required_signers - .into_iter() - .for_each(|signer| self.add_required_signer(signer)); + .iter() + .for_each(|signer| self.add_required_signer(*signer)); } } self.witness_builders @@ -956,8 +957,8 @@ impl TransactionBuilder { .add_input_aggregate_fake_witness_data(&data); if let InputAggregateWitnessData::PlutusScript(_, required_signers, _) = data { required_signers - .into_iter() - .for_each(|signer| self.add_required_signer(signer)); + .iter() + .for_each(|signer| self.add_required_signer(*signer)); } } Ok(()) @@ -1163,6 +1164,8 @@ impl TransactionBuilder { let redeemers = self.witness_builders.redeemer_set_builder.build(true)?; let has_dummy_exunit = redeemers + .clone() + .to_flat_format() .iter() .any(|redeemer| redeemer.ex_units == ExUnits::dummy()); @@ -1207,7 +1210,7 @@ impl TransactionBuilder { }); calc_script_data_hash( &redeemers, - &self.witness_builders.witness_set_builder.get_plutus_datum(), + &self.witness_builders.witness_set_builder.get_plutus_datum().into(), &self.config.cost_models, &languages.iter().copied().collect::>(), None, @@ -1220,11 +1223,12 @@ impl TransactionBuilder { .inputs .iter() .map(|tx_builder_input| tx_builder_input.input.clone()) - .collect(), + .collect::>() + .into(), outputs: self.outputs.clone(), fee, ttl: self.ttl, - certs: self.certs.clone(), + certs: self.certs.as_ref().map(|certs| certs.clone().into()), withdrawals: self.withdrawals.clone(), auxiliary_data_hash: self.auxiliary_data.as_ref().map(hash_auxiliary_data), validity_interval_start: self.validity_start_interval, @@ -1233,18 +1237,18 @@ impl TransactionBuilder { collateral_inputs: self .collateral .as_ref() - .map(|collateral| collateral.iter().map(|c| c.input.clone()).collect()), + .map(|collateral| collateral.iter().map(|c| c.input.clone()).collect::>().into()), required_signers: self .required_signers .as_ref() - .map(|set| set.iter().cloned().collect()), + .map(|set| set.iter().cloned().collect::>().into()), network_id: self.network_id, collateral_return: self.collateral_return.clone(), total_collateral: self.calc_collateral_total()?, reference_inputs: self .reference_inputs .as_ref() - .map(|inputs| inputs.iter().map(|utxo| utxo.input.clone()).collect()), + .map(|inputs| inputs.iter().map(|utxo| utxo.input.clone()).collect::>().into()), voting_procedures: None, proposal_procedures: None, current_treasury_value: None, @@ -1384,7 +1388,7 @@ impl TxRedeemerBuilder { /// Builds the transaction and moves to the next step where any real witness can be added /// NOTE: is_valid set to true /// Will NOT require you to have set required signers & witnesses - pub fn build(&self) -> Result, RedeemerBuilderError> { + pub fn build(&self) -> Result { self.witness_builders.redeemer_set_builder.build(true) } diff --git a/chain/rust/src/builders/withdrawal_builder.rs b/chain/rust/src/builders/withdrawal_builder.rs index a626a8a8..31cc060a 100644 --- a/chain/rust/src/builders/withdrawal_builder.rs +++ b/chain/rust/src/builders/withdrawal_builder.rs @@ -3,7 +3,7 @@ use crate::*; use super::witness_builder::{NativeScriptWitnessInfo, RequiredWitnessSet}; -use crate::{address::RewardAddress, certs::StakeCredential, transaction::RequiredSigners}; +use crate::{address::RewardAddress, certs::StakeCredential, RequiredSigners}; #[derive(Debug, thiserror::Error)] pub enum WithdrawalBuilderError { diff --git a/chain/rust/src/builders/witness_builder.rs b/chain/rust/src/builders/witness_builder.rs index 8cca74b0..e9a28950 100644 --- a/chain/rust/src/builders/witness_builder.rs +++ b/chain/rust/src/builders/witness_builder.rs @@ -5,12 +5,7 @@ use std::{ }; use crate::{ - byron::ByronAddress, - certs::Credential, - crypto::{hash::hash_plutus_data, BootstrapWitness, Vkey, Vkeywitness}, - plutus::{PlutusData, PlutusScript, PlutusV1Script, PlutusV2Script, Redeemer}, - transaction::{RequiredSigners, TransactionWitnessSet}, - NativeScript, Script, + byron::ByronAddress, certs::Credential, crypto::{hash::hash_plutus_data, BootstrapWitness, Vkey, Vkeywitness}, plutus::{LegacyRedeemer, PlutusData, PlutusScript, PlutusV1Script, PlutusV2Script, Redeemers}, transaction::TransactionWitnessSet, NativeScript, RequiredSigners, Script }; use cml_crypto::{ DatumHash, Ed25519KeyHash, Ed25519Signature, PublicKey, RawBytesEncoding, ScriptHash, @@ -24,7 +19,7 @@ pub enum WitnessBuilderError { MissingWitnesses(RequiredWitnessSet), #[error("Missing ExUnit: {0}")] MissingExUnit(#[from] MissingExunitError), - #[error("Redeemer build failed: {0}")] + #[error("LegacyRedeemer build failed: {0}")] RedeemBuildFailed(#[from] RedeemerBuilderError), } @@ -160,7 +155,7 @@ impl RequiredWitnessSet { self.plutus_data.insert(plutus_datum); } - // pub fn add_redeemer(&mut self, redeemer: &Redeemer) { + // pub fn add_redeemer(&mut self, redeemer: &LegacyRedeemer) { // self.add_redeemer_tag(&RedeemerWitnessKey::new(&redeemer.tag(), &redeemer.index())); // } pub fn add_redeemer_tag(&mut self, redeemer: RedeemerWitnessKey) { @@ -241,7 +236,7 @@ pub struct TransactionWitnessSetBuilder { pub bootstraps: HashMap, pub scripts: HashMap, pub plutus_data: LinkedHashMap, - pub redeemers: LinkedHashMap, + pub redeemers: LinkedHashMap, /// witnesses that need to be added for the build function to succeed /// this allows checking that witnesses are present at build time (instead of when submitting to a node) @@ -329,12 +324,12 @@ impl TransactionWitnessSetBuilder { self.plutus_data.values().cloned().collect() } - pub fn add_redeemer(&mut self, redeemer: Redeemer) { + pub fn add_redeemer(&mut self, redeemer: LegacyRedeemer) { self.redeemers .insert(RedeemerWitnessKey::from(&redeemer), redeemer); } - pub fn get_redeemer(&self) -> Vec { + pub fn get_redeemer(&self) -> Vec { self.redeemers.values().cloned().collect() } @@ -349,32 +344,32 @@ impl TransactionWitnessSetBuilder { pub fn add_existing(&mut self, wit_set: TransactionWitnessSet) { if let Some(vkeys) = wit_set.vkeywitnesses { - vkeys.into_iter().for_each(|vkey| { - self.add_vkey(vkey); + vkeys.iter().for_each(|vkey| { + self.add_vkey(vkey.clone()); }); } if let Some(bootstraps) = wit_set.bootstrap_witnesses { - bootstraps.into_iter().for_each(|bootstrap| { - self.add_bootstrap(bootstrap); + bootstraps.iter().for_each(|bootstrap| { + self.add_bootstrap(bootstrap.clone()); }); } if let Some(native_scripts) = wit_set.native_scripts { - native_scripts.into_iter().for_each(|native_script| { - self.add_script(native_script.into()); + native_scripts.iter().for_each(|native_script| { + self.add_script(native_script.clone().into()); }); } if let Some(plutus_scripts) = wit_set.plutus_v1_scripts { - plutus_scripts.into_iter().for_each(|plutus_script| { - self.add_script(plutus_script.into()); + plutus_scripts.iter().for_each(|plutus_script| { + self.add_script(plutus_script.clone().into()); }); } if let Some(plutus_scripts) = wit_set.plutus_v2_scripts { - plutus_scripts.into_iter().for_each(|plutus_script| { - self.add_script(plutus_script.into()); + plutus_scripts.iter().for_each(|plutus_script| { + self.add_script(plutus_script.clone().into()); }); } if let Some(redeemers) = wit_set.redeemers { - redeemers.into_iter().for_each(|redeemer| { + redeemers.to_flat_format().into_iter().for_each(|redeemer| { self.add_redeemer(redeemer); }); } @@ -412,31 +407,31 @@ impl TransactionWitnessSetBuilder { let plutus_datums = self.get_plutus_datum(); if !self.vkeys.is_empty() { - result.vkeywitnesses = Some(self.vkeys.into_values().collect()); + result.vkeywitnesses = Some(self.vkeys.into_values().collect::>().into()); } if !self.bootstraps.is_empty() { - result.bootstrap_witnesses = Some(self.bootstraps.into_values().collect()); + result.bootstrap_witnesses = Some(self.bootstraps.into_values().collect::>().into()); } if !native_scripts.is_empty() { - result.native_scripts = Some(native_scripts); + result.native_scripts = Some(native_scripts.into()); } if !plutus_v1_scripts.is_empty() { - result.plutus_v1_scripts = Some(plutus_v1_scripts); + result.plutus_v1_scripts = Some(plutus_v1_scripts.into()); } if !plutus_v2_scripts.is_empty() { - result.plutus_v2_scripts = Some(plutus_v2_scripts); + result.plutus_v2_scripts = Some(plutus_v2_scripts.into()); } if !self.plutus_data.is_empty() { - result.plutus_datums = Some(plutus_datums); + result.plutus_datums = Some(plutus_datums.into()); } if !self.redeemers.is_empty() { - result.redeemers = Some(self.redeemers.values().cloned().collect()); + result.redeemers = Some(Redeemers::new_arr_legacy_redeemer(self.redeemers.values().cloned().collect::>())); } result diff --git a/chain/rust/src/cbor_encodings.rs b/chain/rust/src/cbor_encodings.rs index 60e4c16f..8cce7e74 100644 --- a/chain/rust/src/cbor_encodings.rs +++ b/chain/rust/src/cbor_encodings.rs @@ -66,6 +66,7 @@ pub struct ProtocolParamUpdateEncoding { pub d_rep_deposit_key_encoding: Option, pub d_rep_inactivity_period_encoding: Option, pub d_rep_inactivity_period_key_encoding: Option, + pub min_fee_ref_script_cost_per_byte_key_encoding: Option, } #[derive(Clone, Debug, Default)] diff --git a/chain/rust/src/certs/mod.rs b/chain/rust/src/certs/mod.rs index a278ba16..3afe023a 100644 --- a/chain/rust/src/certs/mod.rs +++ b/chain/rust/src/certs/mod.rs @@ -344,13 +344,13 @@ impl DnsName { } pub fn new(inner: String) -> Result { - if inner.len() > 64 { + if inner.len() > 128 { return Err(DeserializeError::new( "DnsName", DeserializeFailure::RangeCheck { found: inner.len() as isize, min: Some(0), - max: Some(64), + max: Some(128), }, )); } diff --git a/chain/rust/src/certs/serialization.rs b/chain/rust/src/certs/serialization.rs index f42a7f10..4d834461 100644 --- a/chain/rust/src/certs/serialization.rs +++ b/chain/rust/src/certs/serialization.rs @@ -1031,13 +1031,13 @@ impl Deserialize for DnsName { let (inner, inner_encoding) = raw .text_sz() .map(|(s, enc)| (s, StringEncoding::from(enc)))?; - if inner.len() > 64 { + if inner.len() > 128 { return Err(DeserializeError::new( "DnsName", DeserializeFailure::RangeCheck { found: inner.len() as isize, min: Some(0), - max: Some(64), + max: Some(128), }, )); } @@ -1456,13 +1456,13 @@ impl DeserializeEmbeddedGroup for PoolParams { .map_err(|e: DeserializeError| e.annotate("vrf_keyhash"))?; let (pledge, pledge_encoding) = raw .unsigned_integer_sz() - .map(|(x, enc)| (x, Some(enc))) .map_err(Into::::into) + .map(|(x, enc)| (x, Some(enc))) .map_err(|e: DeserializeError| e.annotate("pledge"))?; let (cost, cost_encoding) = raw .unsigned_integer_sz() - .map(|(x, enc)| (x, Some(enc))) .map_err(Into::::into) + .map(|(x, enc)| (x, Some(enc))) .map_err(|e: DeserializeError| e.annotate("cost"))?; let margin = UnitInterval::deserialize(raw) .map_err(|e: DeserializeError| e.annotate("margin"))?; @@ -1763,8 +1763,8 @@ impl DeserializeEmbeddedGroup for PoolRetirement { .map_err(|e: DeserializeError| e.annotate("pool"))?; let (epoch, epoch_encoding) = raw .unsigned_integer_sz() - .map(|(x, enc)| (x, Some(enc))) .map_err(Into::::into) + .map(|(x, enc)| (x, Some(enc))) .map_err(|e: DeserializeError| e.annotate("epoch"))?; Ok(PoolRetirement { pool, @@ -1878,8 +1878,8 @@ impl DeserializeEmbeddedGroup for RegCert { .map_err(|e: DeserializeError| e.annotate("stake_credential"))?; let (coin, coin_encoding) = raw .unsigned_integer_sz() - .map(|(x, enc)| (x, Some(enc))) .map_err(Into::::into) + .map(|(x, enc)| (x, Some(enc))) .map_err(|e: DeserializeError| e.annotate("coin"))?; Ok(RegCert { stake_credential, @@ -1996,8 +1996,8 @@ impl DeserializeEmbeddedGroup for RegDrepCert { .map_err(|e: DeserializeError| e.annotate("drep_credential"))?; let (coin, coin_encoding) = raw .unsigned_integer_sz() - .map(|(x, enc)| (x, Some(enc))) .map_err(Into::::into) + .map(|(x, enc)| (x, Some(enc))) .map_err(|e: DeserializeError| e.annotate("coin"))?; let anchor = (|| -> Result<_, DeserializeError> { Ok(match raw.cbor_type()? != cbor_event::Type::Special { @@ -2835,8 +2835,8 @@ impl DeserializeEmbeddedGroup for StakeRegDelegCert { .map_err(|e: DeserializeError| e.annotate("pool"))?; let (coin, coin_encoding) = raw .unsigned_integer_sz() - .map(|(x, enc)| (x, Some(enc))) .map_err(Into::::into) + .map(|(x, enc)| (x, Some(enc))) .map_err(|e: DeserializeError| e.annotate("coin"))?; Ok(StakeRegDelegCert { stake_credential, @@ -3186,8 +3186,8 @@ impl DeserializeEmbeddedGroup for StakeVoteRegDelegCert { DRep::deserialize(raw).map_err(|e: DeserializeError| e.annotate("d_rep"))?; let (coin, coin_encoding) = raw .unsigned_integer_sz() - .map(|(x, enc)| (x, Some(enc))) .map_err(Into::::into) + .map(|(x, enc)| (x, Some(enc))) .map_err(|e: DeserializeError| e.annotate("coin"))?; Ok(StakeVoteRegDelegCert { stake_credential, @@ -3303,8 +3303,8 @@ impl DeserializeEmbeddedGroup for UnregCert { .map_err(|e: DeserializeError| e.annotate("stake_credential"))?; let (coin, coin_encoding) = raw .unsigned_integer_sz() - .map(|(x, enc)| (x, Some(enc))) .map_err(Into::::into) + .map(|(x, enc)| (x, Some(enc))) .map_err(|e: DeserializeError| e.annotate("coin"))?; Ok(UnregCert { stake_credential, @@ -3417,8 +3417,8 @@ impl DeserializeEmbeddedGroup for UnregDrepCert { .map_err(|e: DeserializeError| e.annotate("drep_credential"))?; let (coin, coin_encoding) = raw .unsigned_integer_sz() - .map(|(x, enc)| (x, Some(enc))) .map_err(Into::::into) + .map(|(x, enc)| (x, Some(enc))) .map_err(|e: DeserializeError| e.annotate("coin"))?; Ok(UnregDrepCert { drep_credential, diff --git a/chain/rust/src/crypto/hash.rs b/chain/rust/src/crypto/hash.rs index bd5f462c..f848a4f1 100644 --- a/chain/rust/src/crypto/hash.rs +++ b/chain/rust/src/crypto/hash.rs @@ -6,10 +6,10 @@ use cml_crypto::{ use crate::{ auxdata::AuxiliaryData, - plutus::{CostModels, Language, PlutusData, Redeemer}, + plutus::{CostModels, Language, PlutusData, Redeemers}, transaction::{ cbor_encodings::TransactionWitnessSetEncoding, TransactionBody, TransactionWitnessSet, - }, + }, NonemptySetPlutusData, }; pub fn hash_auxiliary_data(auxiliary_data: &AuxiliaryData) -> AuxiliaryDataHash { @@ -30,10 +30,11 @@ pub fn hash_plutus_data(plutus_data: &PlutusData) -> DatumHash { /// Most users will not directly need this as when using the builders /// it will be invoked for you. pub fn hash_script_data( - redeemers: &[Redeemer], + redeemers: &Redeemers, cost_models: &CostModels, - datums: Option<&[PlutusData]>, - encoding: Option<&TransactionWitnessSetEncoding>, + datums: Option<&NonemptySetPlutusData>, + // this will be used again after Conway so we keep it here to avoid double breaking changes + _encoding: Option<&TransactionWitnessSetEncoding>, ) -> ScriptDataHash { let mut buf = cbor_event::se::Serializer::new_vec(); match datums { @@ -45,23 +46,7 @@ pub fn hash_script_data( ; corresponding to a CBOR empty list and an empty map (our apologies). */ buf.write_raw_bytes(&[0x80]).unwrap(); - buf.write_array_sz( - encoding - .as_ref() - .map(|encs| encs.plutus_datums_encoding) - .unwrap_or_default() - .to_len_sz(datums.len() as u64, false), - ) - .unwrap(); - for datum in datums { - datum.serialize(&mut buf, false).unwrap(); - } - encoding - .as_ref() - .map(|encs| encs.plutus_datums_encoding) - .unwrap_or_default() - .end(&mut buf, false) - .unwrap(); + datums.serialize(&mut buf, false).unwrap(); buf.write_raw_bytes(&[0xA0]).unwrap(); } _ => { @@ -72,41 +57,9 @@ pub fn hash_script_data( ; Similarly for the datums, if present. If no datums are provided, the middle ; field is an empty string. */ - buf.write_array_sz( - encoding - .as_ref() - .map(|encs| encs.redeemers_encoding) - .unwrap_or_default() - .to_len_sz(redeemers.len() as u64, false), - ) - .unwrap(); - for redeemer in redeemers { - redeemer.serialize(&mut buf, false).unwrap(); - } - encoding - .as_ref() - .map(|encs| encs.redeemers_encoding) - .unwrap_or_default() - .end(&mut buf, false) - .unwrap(); + redeemers.serialize(&mut buf, false).unwrap(); if let Some(datums) = datums { - buf.write_array_sz( - encoding - .as_ref() - .map(|encs| encs.plutus_datums_encoding) - .unwrap_or_default() - .to_len_sz(datums.len() as u64, false), - ) - .unwrap(); - for datum in datums { - datum.serialize(&mut buf, false).unwrap(); - } - encoding - .as_ref() - .map(|encs| encs.plutus_datums_encoding) - .unwrap_or_default() - .end(&mut buf, false) - .unwrap(); + datums.serialize(&mut buf, false).unwrap(); } buf.write_raw_bytes(&cost_models.language_views_encoding().unwrap()) .unwrap(); @@ -127,8 +80,8 @@ pub enum ScriptDataHashError { /// Most users will not directly need this as when using the builders /// it will be invoked for you. pub fn calc_script_data_hash( - redeemers: &[Redeemer], - datums: &[PlutusData], + redeemers: &Redeemers, + datums: &NonemptySetPlutusData, cost_models: &CostModels, used_langs: &[Language], encoding: Option<&TransactionWitnessSetEncoding>, diff --git a/chain/rust/src/deposit.rs b/chain/rust/src/deposit.rs index c0ce313a..b68ada99 100644 --- a/chain/rust/src/deposit.rs +++ b/chain/rust/src/deposit.rs @@ -62,7 +62,7 @@ pub fn get_implicit_input( ) -> Result { internal_get_implicit_input( txbody.withdrawals.as_ref(), - txbody.certs.as_deref(), + txbody.certs.as_ref().map(|certs| certs.as_ref()), pool_deposit, key_deposit, ) @@ -73,5 +73,5 @@ pub fn get_deposit( pool_deposit: Coin, // // protocol parameter key_deposit: Coin, // protocol parameter ) -> Result { - internal_get_deposit(txbody.certs.as_deref(), pool_deposit, key_deposit) + internal_get_deposit(txbody.certs.as_ref().map(|certs| certs.as_ref()), pool_deposit, key_deposit) } diff --git a/chain/rust/src/fees.rs b/chain/rust/src/fees.rs index 513ead7b..800b11f0 100644 --- a/chain/rust/src/fees.rs +++ b/chain/rust/src/fees.rs @@ -30,7 +30,7 @@ pub fn min_script_fee( ex_unit_prices: &ExUnitPrices, ) -> Result { if let Some(redeemers) = &tx.witness_set.redeemers { - let total_ex_units = compute_total_ex_units(redeemers)?; + let total_ex_units = compute_total_ex_units(&redeemers.clone().to_flat_format())?; let script_fee = ((Fraction::new(total_ex_units.mem, 1u64) * Fraction::new( ex_unit_prices.mem_price.numerator, diff --git a/chain/rust/src/governance/cbor_encodings.rs b/chain/rust/src/governance/cbor_encodings.rs index ee62e7f1..189cb279 100644 --- a/chain/rust/src/governance/cbor_encodings.rs +++ b/chain/rust/src/governance/cbor_encodings.rs @@ -61,6 +61,7 @@ pub struct NoConfidenceEncoding { pub struct ParameterChangeActionEncoding { pub len_encoding: LenEncoding, pub tag_encoding: Option, + pub policy_hash_encoding: StringEncoding, } #[derive(Clone, Debug, Default)] @@ -75,6 +76,7 @@ pub struct TreasuryWithdrawalsActionEncoding { pub tag_encoding: Option, pub withdrawal_encoding: LenEncoding, pub withdrawal_value_encodings: BTreeMap>, + pub policy_hash_encoding: StringEncoding, } #[derive(Clone, Debug, Default)] diff --git a/chain/rust/src/governance/mod.rs b/chain/rust/src/governance/mod.rs index f0d4b551..d46bedb0 100644 --- a/chain/rust/src/governance/mod.rs +++ b/chain/rust/src/governance/mod.rs @@ -99,10 +99,12 @@ impl GovAction { pub fn new_parameter_change_action( gov_action_id: Option, protocol_param_update: ProtocolParamUpdate, + policy_hash: Option, ) -> Self { Self::ParameterChangeAction(ParameterChangeAction::new( gov_action_id, protocol_param_update, + policy_hash, )) } @@ -115,8 +117,9 @@ impl GovAction { pub fn new_treasury_withdrawals_action( withdrawal: OrderedHashMap, + policy_hash: Option, ) -> Self { - Self::TreasuryWithdrawalsAction(TreasuryWithdrawalsAction::new(withdrawal)) + Self::TreasuryWithdrawalsAction(TreasuryWithdrawalsAction::new(withdrawal, policy_hash)) } pub fn new_no_confidence(action_id: Option) -> Self { @@ -253,6 +256,7 @@ impl NoConfidence { pub struct ParameterChangeAction { pub gov_action_id: Option, pub protocol_param_update: ProtocolParamUpdate, + pub policy_hash: Option, #[serde(skip)] pub encodings: Option, } @@ -261,10 +265,12 @@ impl ParameterChangeAction { pub fn new( gov_action_id: Option, protocol_param_update: ProtocolParamUpdate, + policy_hash: Option, ) -> Self { Self { gov_action_id, protocol_param_update, + policy_hash, encodings: None, } } @@ -300,14 +306,19 @@ impl ProposalProcedure { #[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] pub struct TreasuryWithdrawalsAction { pub withdrawal: OrderedHashMap, + pub policy_hash: Option, #[serde(skip)] pub encodings: Option, } impl TreasuryWithdrawalsAction { - pub fn new(withdrawal: OrderedHashMap) -> Self { + pub fn new( + withdrawal: OrderedHashMap, + policy_hash: Option, + ) -> Self { Self { withdrawal, + policy_hash, encodings: None, } } diff --git a/chain/rust/src/governance/serialization.rs b/chain/rust/src/governance/serialization.rs index 0ceec6fa..cfdbed65 100644 --- a/chain/rust/src/governance/serialization.rs +++ b/chain/rust/src/governance/serialization.rs @@ -352,7 +352,7 @@ impl Deserialize for GovAction { let mut errs = Vec::new(); let deser_variant = (|raw: &mut Deserializer<_>| -> Result<_, DeserializeError> { let mut read_len = CBORReadLen::new(len); - read_len.read_elems(3)?; + read_len.read_elems(4)?; read_len.finish()?; let ret = ParameterChangeAction::deserialize_as_embedded_group(raw, &mut read_len, len); @@ -407,7 +407,7 @@ impl Deserialize for GovAction { }; let deser_variant = (|raw: &mut Deserializer<_>| -> Result<_, DeserializeError> { let mut read_len = CBORReadLen::new(len); - read_len.read_elems(2)?; + read_len.read_elems(3)?; read_len.finish()?; let ret = TreasuryWithdrawalsAction::deserialize_as_embedded_group( raw, @@ -1124,7 +1124,7 @@ impl Serialize for ParameterChangeAction { .as_ref() .map(|encs| encs.len_encoding) .unwrap_or_default() - .to_len_sz(3, force_canonical), + .to_len_sz(4, force_canonical), )?; self.serialize_as_embedded_group(serializer, force_canonical) } @@ -1153,6 +1153,17 @@ impl SerializeEmbeddedGroup for ParameterChangeAction { }?; self.protocol_param_update .serialize(serializer, force_canonical)?; + match &self.policy_hash { + Some(x) => serializer.write_bytes_sz( + x.to_raw_bytes(), + self.encodings + .as_ref() + .map(|encs| encs.policy_hash_encoding.clone()) + .unwrap_or_default() + .to_str_len_sz(x.to_raw_bytes().len() as u64, force_canonical), + ), + None => serializer.write_special(cbor_event::Special::Null), + }?; self.encodings .as_ref() .map(|encs| encs.len_encoding) @@ -1165,7 +1176,7 @@ impl Deserialize for ParameterChangeAction { fn deserialize(raw: &mut Deserializer) -> Result { let len = raw.array_sz()?; let mut read_len = CBORReadLen::new(len); - read_len.read_elems(3)?; + read_len.read_elems(4)?; read_len.finish()?; let ret = Self::deserialize_as_embedded_group(raw, &mut read_len, len); match len { @@ -1213,12 +1224,37 @@ impl DeserializeEmbeddedGroup for ParameterChangeAction { .map_err(|e| e.annotate("gov_action_id"))?; let protocol_param_update = ProtocolParamUpdate::deserialize(raw) .map_err(|e: DeserializeError| e.annotate("protocol_param_update"))?; + let (policy_hash, policy_hash_encoding) = (|| -> Result<_, DeserializeError> { + Ok(match raw.cbor_type()? != cbor_event::Type::Special { + true => Result::<_, DeserializeError>::Ok( + raw.bytes_sz() + .map_err(Into::::into) + .and_then(|(bytes, enc)| { + ScriptHash::from_raw_bytes(&bytes) + .map(|bytes| (bytes, StringEncoding::from(enc))) + .map_err(|e| { + DeserializeFailure::InvalidStructure(Box::new(e)).into() + }) + })?, + ) + .map(|(x, policy_hash_encoding)| (Some(x), policy_hash_encoding))?, + false => { + if raw.special()? != cbor_event::Special::Null { + return Err(DeserializeFailure::ExpectedNull.into()); + } + (None, StringEncoding::default()) + } + }) + })() + .map_err(|e| e.annotate("policy_hash"))?; Ok(ParameterChangeAction { gov_action_id, protocol_param_update, + policy_hash, encodings: Some(ParameterChangeActionEncoding { len_encoding, tag_encoding, + policy_hash_encoding, }), }) })() @@ -1313,7 +1349,7 @@ impl Serialize for TreasuryWithdrawalsAction { .as_ref() .map(|encs| encs.len_encoding) .unwrap_or_default() - .to_len_sz(2, force_canonical), + .to_len_sz(3, force_canonical), )?; self.serialize_as_embedded_group(serializer, force_canonical) } @@ -1378,6 +1414,17 @@ impl SerializeEmbeddedGroup for TreasuryWithdrawalsAction { .map(|encs| encs.withdrawal_encoding) .unwrap_or_default() .end(serializer, force_canonical)?; + match &self.policy_hash { + Some(x) => serializer.write_bytes_sz( + x.to_raw_bytes(), + self.encodings + .as_ref() + .map(|encs| encs.policy_hash_encoding.clone()) + .unwrap_or_default() + .to_str_len_sz(x.to_raw_bytes().len() as u64, force_canonical), + ), + None => serializer.write_special(cbor_event::Special::Null), + }?; self.encodings .as_ref() .map(|encs| encs.len_encoding) @@ -1390,7 +1437,7 @@ impl Deserialize for TreasuryWithdrawalsAction { fn deserialize(raw: &mut Deserializer) -> Result { let len = raw.array_sz()?; let mut read_len = CBORReadLen::new(len); - read_len.read_elems(2)?; + read_len.read_elems(3)?; read_len.finish()?; let ret = Self::deserialize_as_embedded_group(raw, &mut read_len, len); match len { @@ -1460,13 +1507,38 @@ impl DeserializeEmbeddedGroup for TreasuryWithdrawalsAction { )) })() .map_err(|e| e.annotate("withdrawal"))?; + let (policy_hash, policy_hash_encoding) = (|| -> Result<_, DeserializeError> { + Ok(match raw.cbor_type()? != cbor_event::Type::Special { + true => Result::<_, DeserializeError>::Ok( + raw.bytes_sz() + .map_err(Into::::into) + .and_then(|(bytes, enc)| { + ScriptHash::from_raw_bytes(&bytes) + .map(|bytes| (bytes, StringEncoding::from(enc))) + .map_err(|e| { + DeserializeFailure::InvalidStructure(Box::new(e)).into() + }) + })?, + ) + .map(|(x, policy_hash_encoding)| (Some(x), policy_hash_encoding))?, + false => { + if raw.special()? != cbor_event::Special::Null { + return Err(DeserializeFailure::ExpectedNull.into()); + } + (None, StringEncoding::default()) + } + }) + })() + .map_err(|e| e.annotate("policy_hash"))?; Ok(TreasuryWithdrawalsAction { withdrawal, + policy_hash, encodings: Some(TreasuryWithdrawalsActionEncoding { len_encoding, tag_encoding, withdrawal_encoding, withdrawal_value_encodings, + policy_hash_encoding, }), }) })() diff --git a/chain/rust/src/lib.rs b/chain/rust/src/lib.rs index d93f1d60..55959731 100644 --- a/chain/rust/src/lib.rs +++ b/chain/rust/src/lib.rs @@ -30,7 +30,11 @@ pub mod transaction; pub mod utils; pub use assets::{Coin, Value}; -pub use utils::NetworkId; +use certs::Certificate; +use cml_crypto::Ed25519KeyHash; +use crypto::{BootstrapWitness, Vkeywitness}; +use utils::NonemptySetRawBytes; +pub use utils::{NonemptySet, Set, NetworkId}; //pub mod legacy_address; @@ -54,9 +58,9 @@ use cbor_encodings::{ DRepVotingThresholdsEncoding, PoolVotingThresholdsEncoding, ProtocolParamUpdateEncoding, RationalEncoding, UnitIntervalEncoding, }; -use governance::Voter; -use plutus::{CostModels, ExUnitPrices, ExUnits, PlutusV1Script, PlutusV2Script, PlutusV3Script}; -use transaction::NativeScript; +use governance::{ProposalProcedure, Voter}; +use plutus::{CostModels, ExUnitPrices, ExUnits, PlutusData, PlutusV1Script, PlutusV2Script, PlutusV3Script}; +use transaction::{NativeScript, TransactionInput}; #[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] pub struct DRepVotingThresholds { @@ -106,16 +110,41 @@ impl DRepVotingThresholds { pub type DeltaCoin = Int; +pub type SetTransactionInput = Set; + +pub type NonemptySetBootstrapWitness = NonemptySet; + +pub type NonemptySetCertificate = NonemptySet; + +pub type NonemptySetNativeScript = NonemptySet; + +pub type NonemptySetPlutusData = NonemptySet; + +pub type NonemptySetPlutusV1Script = NonemptySet; + +pub type NonemptySetPlutusV2Script = NonemptySet; + +pub type NonemptySetPlutusV3Script = NonemptySet; + +pub type NonemptySetProposalProcedure = NonemptySet; + +pub type NonemptySetTransactionInput = NonemptySet; + +pub type NonemptySetVkeywitness = NonemptySet; + pub type PolicyId = cml_crypto::ScriptHash; pub type PolicyIdList = Vec; +pub type RequiredSigners = NonemptySetRawBytes; + #[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] pub struct PoolVotingThresholds { pub motion_no_confidence: UnitInterval, pub committee_normal: UnitInterval, pub committee_no_confidence: UnitInterval, pub hard_fork_initiation: UnitInterval, + pub security_relevant_parameter_voting_threshold: UnitInterval, #[serde(skip)] pub encodings: Option, } @@ -126,12 +155,14 @@ impl PoolVotingThresholds { committee_normal: UnitInterval, committee_no_confidence: UnitInterval, hard_fork_initiation: UnitInterval, + security_relevant_parameter_voting_threshold: UnitInterval, ) -> Self { Self { motion_no_confidence, committee_normal, committee_no_confidence, hard_fork_initiation, + security_relevant_parameter_voting_threshold, encodings: None, } } @@ -141,8 +172,8 @@ pub type Port = u16; #[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] pub struct ProtocolParamUpdate { - pub minfee_a: Option, - pub minfee_b: Option, + pub minfee_a: Option, + pub minfee_b: Option, pub max_block_body_size: Option, pub max_transaction_size: Option, pub max_block_header_size: Option, @@ -165,11 +196,12 @@ pub struct ProtocolParamUpdate { pub pool_voting_thresholds: Option, pub d_rep_voting_thresholds: Option, pub min_committee_size: Option, - pub committee_term_limit: Option, + pub committee_term_limit: Option, pub governance_action_validity_period: Option, pub governance_action_deposit: Option, pub d_rep_deposit: Option, pub d_rep_inactivity_period: Option, + pub min_fee_ref_script_cost_per_byte: Option, #[serde(skip)] pub encodings: Option, } @@ -206,6 +238,7 @@ impl ProtocolParamUpdate { governance_action_deposit: None, d_rep_deposit: None, d_rep_inactivity_period: None, + min_fee_ref_script_cost_per_byte: None, encodings: None, } } diff --git a/chain/rust/src/plutus/cbor_encodings.rs b/chain/rust/src/plutus/cbor_encodings.rs index e52e128e..2ae27ca4 100644 --- a/chain/rust/src/plutus/cbor_encodings.rs +++ b/chain/rust/src/plutus/cbor_encodings.rs @@ -27,6 +27,13 @@ pub struct ExUnitsEncoding { pub steps_encoding: Option, } +#[derive(Clone, Debug, Default)] +pub struct LegacyRedeemerEncoding { + pub len_encoding: LenEncoding, + pub tag_encoding: Option, + pub index_encoding: Option, +} + #[derive(Clone, Debug, Default)] pub struct PlutusV1ScriptEncoding { pub inner_encoding: StringEncoding, @@ -43,8 +50,13 @@ pub struct PlutusV3ScriptEncoding { } #[derive(Clone, Debug, Default)] -pub struct RedeemerEncoding { +pub struct RedeemerKeyEncoding { pub len_encoding: LenEncoding, pub tag_encoding: Option, pub index_encoding: Option, } + +#[derive(Clone, Debug, Default)] +pub struct RedeemerValEncoding { + pub len_encoding: LenEncoding, +} diff --git a/chain/rust/src/plutus/mod.rs b/chain/rust/src/plutus/mod.rs index 5db69b61..c4a167a4 100644 --- a/chain/rust/src/plutus/mod.rs +++ b/chain/rust/src/plutus/mod.rs @@ -5,15 +5,16 @@ pub mod cbor_encodings; pub mod serialization; pub mod utils; -use self::cbor_encodings::PlutusV3ScriptEncoding; +use self::cbor_encodings::{LegacyRedeemerEncoding, PlutusV3ScriptEncoding, RedeemerKeyEncoding, RedeemerValEncoding}; use super::{Rational, SubCoin}; use crate::utils::BigInteger; use cbor_encodings::{ CostModelsEncoding, ExUnitPricesEncoding, ExUnitsEncoding, PlutusV1ScriptEncoding, - PlutusV2ScriptEncoding, RedeemerEncoding, + PlutusV2ScriptEncoding, }; +use cml_core::ordered_hash_map::OrderedHashMap; use cml_core::serialization::{LenEncoding, Serialize, StringEncoding}; use cml_core::Int; use cml_crypto::{blake2b256, DatumHash}; @@ -105,6 +106,28 @@ pub enum Language { PlutusV3, } +#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] +pub struct LegacyRedeemer { + pub tag: RedeemerTag, + pub index: u64, + pub data: PlutusData, + pub ex_units: ExUnits, + #[serde(skip)] + pub encodings: Option, +} + +impl LegacyRedeemer { + pub fn new(tag: RedeemerTag, index: u64, data: PlutusData, ex_units: ExUnits) -> Self { + Self { + tag, + index, + data, + ex_units, + encodings: None, + } + } +} + #[derive( Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema, derivative::Derivative, )] @@ -176,10 +199,15 @@ impl PlutusData { } #[derive(Clone, Debug, derivative::Derivative)] -#[derivative(Hash, PartialEq, Eq)] +#[derivative(Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct PlutusV1Script { pub inner: Vec, - #[derivative(PartialEq = "ignore", Hash = "ignore")] + #[derivative( + PartialEq = "ignore", + Ord = "ignore", + PartialOrd = "ignore", + Hash = "ignore" + )] pub encodings: Option, } @@ -244,10 +272,15 @@ impl schemars::JsonSchema for PlutusV1Script { } #[derive(Clone, Debug, derivative::Derivative)] -#[derivative(Hash, PartialEq, Eq)] +#[derivative(Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct PlutusV2Script { pub inner: Vec, - #[derivative(PartialEq = "ignore", Hash = "ignore")] + #[derivative( + PartialEq = "ignore", + Ord = "ignore", + PartialOrd = "ignore", + Hash = "ignore" + )] pub encodings: Option, } @@ -312,10 +345,15 @@ impl schemars::JsonSchema for PlutusV2Script { } #[derive(Clone, Debug, derivative::Derivative)] -#[derivative(Hash, PartialEq, Eq)] +#[derivative(Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct PlutusV3Script { pub inner: Vec, - #[derivative(PartialEq = "ignore", Hash = "ignore")] + #[derivative( + PartialEq = "ignore", + Ord = "ignore", + PartialOrd = "ignore", + Hash = "ignore" + )] pub encodings: Option, } @@ -379,23 +417,28 @@ impl schemars::JsonSchema for PlutusV3Script { } } -#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] -pub struct Redeemer { +#[derive( + Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema, derivative::Derivative, +)] +#[derivative(Eq, PartialEq, Ord, PartialOrd, Hash)] +pub struct RedeemerKey { pub tag: RedeemerTag, pub index: u64, - pub data: PlutusData, - pub ex_units: ExUnits, + #[derivative( + PartialEq = "ignore", + Ord = "ignore", + PartialOrd = "ignore", + Hash = "ignore" + )] #[serde(skip)] - pub encodings: Option, + pub encodings: Option, } -impl Redeemer { - pub fn new(tag: RedeemerTag, index: u64, data: PlutusData, ex_units: ExUnits) -> Self { +impl RedeemerKey { + pub fn new(tag: RedeemerTag, index: u64) -> Self { Self { tag, index, - data, - ex_units, encodings: None, } } @@ -420,4 +463,56 @@ pub enum RedeemerTag { Mint, Cert, Reward, + Voting, + Proposing, +} + +#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] +pub struct RedeemerVal { + pub data: PlutusData, + pub ex_units: ExUnits, + #[serde(skip)] + pub encodings: Option, +} + +impl RedeemerVal { + pub fn new(data: PlutusData, ex_units: ExUnits) -> Self { + Self { + data, + ex_units, + encodings: None, + } + } +} + +#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] +pub enum Redeemers { + ArrLegacyRedeemer { + arr_legacy_redeemer: Vec, + #[serde(skip)] + arr_legacy_redeemer_encoding: LenEncoding, + }, + MapRedeemerKeyToRedeemerVal { + map_redeemer_key_to_redeemer_val: OrderedHashMap, + #[serde(skip)] + map_redeemer_key_to_redeemer_val_encoding: LenEncoding, + }, +} + +impl Redeemers { + pub fn new_arr_legacy_redeemer(arr_legacy_redeemer: Vec) -> Self { + Self::ArrLegacyRedeemer { + arr_legacy_redeemer, + arr_legacy_redeemer_encoding: LenEncoding::default(), + } + } + + pub fn new_map_redeemer_key_to_redeemer_val( + map_redeemer_key_to_redeemer_val: OrderedHashMap, + ) -> Self { + Self::MapRedeemerKeyToRedeemerVal { + map_redeemer_key_to_redeemer_val, + map_redeemer_key_to_redeemer_val_encoding: LenEncoding::default(), + } + } } diff --git a/chain/rust/src/plutus/serialization.rs b/chain/rust/src/plutus/serialization.rs index 199061a8..8e187e26 100644 --- a/chain/rust/src/plutus/serialization.rs +++ b/chain/rust/src/plutus/serialization.rs @@ -422,13 +422,13 @@ impl Deserialize for ExUnits { (|| -> Result<_, DeserializeError> { let (mem, mem_encoding) = raw .unsigned_integer_sz() - .map(|(x, enc)| (x, Some(enc))) .map_err(Into::::into) + .map(|(x, enc)| (x, Some(enc))) .map_err(|e: DeserializeError| e.annotate("mem"))?; let (steps, steps_encoding) = raw .unsigned_integer_sz() - .map(|(x, enc)| (x, Some(enc))) .map_err(Into::::into) + .map(|(x, enc)| (x, Some(enc))) .map_err(|e: DeserializeError| e.annotate("steps"))?; match len { cbor_event::LenSz::Len(_, _) => (), @@ -451,6 +451,264 @@ impl Deserialize for ExUnits { } } +impl Serialize for LegacyRedeemer { + fn serialize<'se, W: Write>( + &self, + serializer: &'se mut Serializer, + force_canonical: bool, + ) -> cbor_event::Result<&'se mut Serializer> { + serializer.write_array_sz( + self.encodings + .as_ref() + .map(|encs| encs.len_encoding) + .unwrap_or_default() + .to_len_sz(4, force_canonical), + )?; + match &self.tag { + RedeemerTag::Spend => serializer.write_unsigned_integer_sz( + 0u64, + fit_sz( + 0u64, + self.encodings + .as_ref() + .map(|encs| encs.tag_encoding) + .unwrap_or_default(), + force_canonical, + ), + ), + RedeemerTag::Mint => serializer.write_unsigned_integer_sz( + 1u64, + fit_sz( + 1u64, + self.encodings + .as_ref() + .map(|encs| encs.tag_encoding) + .unwrap_or_default(), + force_canonical, + ), + ), + RedeemerTag::Cert => serializer.write_unsigned_integer_sz( + 2u64, + fit_sz( + 2u64, + self.encodings + .as_ref() + .map(|encs| encs.tag_encoding) + .unwrap_or_default(), + force_canonical, + ), + ), + RedeemerTag::Reward => serializer.write_unsigned_integer_sz( + 3u64, + fit_sz( + 3u64, + self.encodings + .as_ref() + .map(|encs| encs.tag_encoding) + .unwrap_or_default(), + force_canonical, + ), + ), + RedeemerTag::Voting => serializer.write_unsigned_integer_sz( + 4u64, + fit_sz( + 4u64, + self.encodings + .as_ref() + .map(|encs| encs.tag_encoding) + .unwrap_or_default(), + force_canonical, + ), + ), + RedeemerTag::Proposing => serializer.write_unsigned_integer_sz( + 5u64, + fit_sz( + 5u64, + self.encodings + .as_ref() + .map(|encs| encs.tag_encoding) + .unwrap_or_default(), + force_canonical, + ), + ), + }?; + serializer.write_unsigned_integer_sz( + self.index, + fit_sz( + self.index, + self.encodings + .as_ref() + .map(|encs| encs.index_encoding) + .unwrap_or_default(), + force_canonical, + ), + )?; + self.data.serialize(serializer, force_canonical)?; + self.ex_units.serialize(serializer, force_canonical)?; + self.encodings + .as_ref() + .map(|encs| encs.len_encoding) + .unwrap_or_default() + .end(serializer, force_canonical) + } +} + +impl Deserialize for LegacyRedeemer { + fn deserialize(raw: &mut Deserializer) -> Result { + let len = raw.array_sz()?; + let len_encoding: LenEncoding = len.into(); + let mut read_len = CBORReadLen::new(len); + read_len.read_elems(4)?; + read_len.finish()?; + (|| -> Result<_, DeserializeError> { + let (tag, tag_encoding) = (|| -> Result<_, DeserializeError> { + let initial_position = raw.as_mut_ref().stream_position().unwrap(); + let deser_variant = (|raw: &mut Deserializer<_>| -> Result<_, DeserializeError> { + let (spend_value, spend_encoding) = raw.unsigned_integer_sz()?; + if spend_value != 0 { + return Err(DeserializeFailure::FixedValueMismatch { + found: Key::Uint(spend_value), + expected: Key::Uint(0), + } + .into()); + } + Ok(Some(spend_encoding)) + })(raw); + match deser_variant { + Ok(tag_encoding) => return Ok((RedeemerTag::Spend, tag_encoding)), + Err(_) => raw + .as_mut_ref() + .seek(SeekFrom::Start(initial_position)) + .unwrap(), + }; + let deser_variant = (|raw: &mut Deserializer<_>| -> Result<_, DeserializeError> { + let (mint_value, mint_encoding) = raw.unsigned_integer_sz()?; + if mint_value != 1 { + return Err(DeserializeFailure::FixedValueMismatch { + found: Key::Uint(mint_value), + expected: Key::Uint(1), + } + .into()); + } + Ok(Some(mint_encoding)) + })(raw); + match deser_variant { + Ok(tag_encoding) => return Ok((RedeemerTag::Mint, tag_encoding)), + Err(_) => raw + .as_mut_ref() + .seek(SeekFrom::Start(initial_position)) + .unwrap(), + }; + let deser_variant = (|raw: &mut Deserializer<_>| -> Result<_, DeserializeError> { + let (cert_value, cert_encoding) = raw.unsigned_integer_sz()?; + if cert_value != 2 { + return Err(DeserializeFailure::FixedValueMismatch { + found: Key::Uint(cert_value), + expected: Key::Uint(2), + } + .into()); + } + Ok(Some(cert_encoding)) + })(raw); + match deser_variant { + Ok(tag_encoding) => return Ok((RedeemerTag::Cert, tag_encoding)), + Err(_) => raw + .as_mut_ref() + .seek(SeekFrom::Start(initial_position)) + .unwrap(), + }; + let deser_variant = (|raw: &mut Deserializer<_>| -> Result<_, DeserializeError> { + let (reward_value, reward_encoding) = raw.unsigned_integer_sz()?; + if reward_value != 3 { + return Err(DeserializeFailure::FixedValueMismatch { + found: Key::Uint(reward_value), + expected: Key::Uint(3), + } + .into()); + } + Ok(Some(reward_encoding)) + })(raw); + match deser_variant { + Ok(tag_encoding) => return Ok((RedeemerTag::Reward, tag_encoding)), + Err(_) => raw + .as_mut_ref() + .seek(SeekFrom::Start(initial_position)) + .unwrap(), + }; + let deser_variant = (|raw: &mut Deserializer<_>| -> Result<_, DeserializeError> { + let (voting_value, voting_encoding) = raw.unsigned_integer_sz()?; + if voting_value != 4 { + return Err(DeserializeFailure::FixedValueMismatch { + found: Key::Uint(voting_value), + expected: Key::Uint(4), + } + .into()); + } + Ok(Some(voting_encoding)) + })(raw); + match deser_variant { + Ok(tag_encoding) => return Ok((RedeemerTag::Voting, tag_encoding)), + Err(_) => raw + .as_mut_ref() + .seek(SeekFrom::Start(initial_position)) + .unwrap(), + }; + let deser_variant = (|raw: &mut Deserializer<_>| -> Result<_, DeserializeError> { + let (proposing_value, proposing_encoding) = raw.unsigned_integer_sz()?; + if proposing_value != 5 { + return Err(DeserializeFailure::FixedValueMismatch { + found: Key::Uint(proposing_value), + expected: Key::Uint(5), + } + .into()); + } + Ok(Some(proposing_encoding)) + })(raw); + match deser_variant { + Ok(tag_encoding) => return Ok((RedeemerTag::Proposing, tag_encoding)), + Err(_) => raw + .as_mut_ref() + .seek(SeekFrom::Start(initial_position)) + .unwrap(), + }; + Err(DeserializeError::new( + "RedeemerTag", + DeserializeFailure::NoVariantMatched, + )) + })() + .map_err(|e| e.annotate("tag"))?; + let (index, index_encoding) = raw + .unsigned_integer_sz() + .map_err(Into::::into) + .map(|(x, enc)| (x, Some(enc))) + .map_err(|e: DeserializeError| e.annotate("index"))?; + let data = + PlutusData::deserialize(raw).map_err(|e: DeserializeError| e.annotate("data"))?; + let ex_units = + ExUnits::deserialize(raw).map_err(|e: DeserializeError| e.annotate("ex_units"))?; + match len { + cbor_event::LenSz::Len(_, _) => (), + cbor_event::LenSz::Indefinite => match raw.special()? { + cbor_event::Special::Break => (), + _ => return Err(DeserializeFailure::EndingBreakMissing.into()), + }, + } + Ok(LegacyRedeemer { + tag, + index, + data, + ex_units, + encodings: Some(LegacyRedeemerEncoding { + len_encoding, + tag_encoding, + index_encoding, + }), + }) + })() + .map_err(|e| e.annotate("LegacyRedeemer")) + } +} + impl Serialize for PlutusData { fn serialize<'se, W: Write>( &self, @@ -638,7 +896,7 @@ impl Deserialize for PlutusV3Script { } } -impl Serialize for Redeemer { +impl Serialize for RedeemerKey { fn serialize<'se, W: Write>( &self, serializer: &'se mut Serializer, @@ -649,7 +907,7 @@ impl Serialize for Redeemer { .as_ref() .map(|encs| encs.len_encoding) .unwrap_or_default() - .to_len_sz(4, force_canonical), + .to_len_sz(2, force_canonical), )?; match &self.tag { RedeemerTag::Spend => serializer.write_unsigned_integer_sz( @@ -696,6 +954,28 @@ impl Serialize for Redeemer { force_canonical, ), ), + RedeemerTag::Voting => serializer.write_unsigned_integer_sz( + 4u64, + fit_sz( + 4u64, + self.encodings + .as_ref() + .map(|encs| encs.tag_encoding) + .unwrap_or_default(), + force_canonical, + ), + ), + RedeemerTag::Proposing => serializer.write_unsigned_integer_sz( + 5u64, + fit_sz( + 5u64, + self.encodings + .as_ref() + .map(|encs| encs.tag_encoding) + .unwrap_or_default(), + force_canonical, + ), + ), }?; serializer.write_unsigned_integer_sz( self.index, @@ -708,8 +988,6 @@ impl Serialize for Redeemer { force_canonical, ), )?; - self.data.serialize(serializer, force_canonical)?; - self.ex_units.serialize(serializer, force_canonical)?; self.encodings .as_ref() .map(|encs| encs.len_encoding) @@ -718,12 +996,12 @@ impl Serialize for Redeemer { } } -impl Deserialize for Redeemer { +impl Deserialize for RedeemerKey { fn deserialize(raw: &mut Deserializer) -> Result { let len = raw.array_sz()?; let len_encoding: LenEncoding = len.into(); let mut read_len = CBORReadLen::new(len); - read_len.read_elems(4)?; + read_len.read_elems(2)?; read_len.finish()?; (|| -> Result<_, DeserializeError> { let (tag, tag_encoding) = (|| -> Result<_, DeserializeError> { @@ -800,6 +1078,42 @@ impl Deserialize for Redeemer { .seek(SeekFrom::Start(initial_position)) .unwrap(), }; + let deser_variant = (|raw: &mut Deserializer<_>| -> Result<_, DeserializeError> { + let (voting_value, voting_encoding) = raw.unsigned_integer_sz()?; + if voting_value != 4 { + return Err(DeserializeFailure::FixedValueMismatch { + found: Key::Uint(voting_value), + expected: Key::Uint(4), + } + .into()); + } + Ok(Some(voting_encoding)) + })(raw); + match deser_variant { + Ok(tag_encoding) => return Ok((RedeemerTag::Voting, tag_encoding)), + Err(_) => raw + .as_mut_ref() + .seek(SeekFrom::Start(initial_position)) + .unwrap(), + }; + let deser_variant = (|raw: &mut Deserializer<_>| -> Result<_, DeserializeError> { + let (proposing_value, proposing_encoding) = raw.unsigned_integer_sz()?; + if proposing_value != 5 { + return Err(DeserializeFailure::FixedValueMismatch { + found: Key::Uint(proposing_value), + expected: Key::Uint(5), + } + .into()); + } + Ok(Some(proposing_encoding)) + })(raw); + match deser_variant { + Ok(tag_encoding) => return Ok((RedeemerTag::Proposing, tag_encoding)), + Err(_) => raw + .as_mut_ref() + .seek(SeekFrom::Start(initial_position)) + .unwrap(), + }; Err(DeserializeError::new( "RedeemerTag", DeserializeFailure::NoVariantMatched, @@ -811,10 +1125,6 @@ impl Deserialize for Redeemer { .map_err(Into::::into) .map(|(x, enc)| (x, Some(enc))) .map_err(|e: DeserializeError| e.annotate("index"))?; - let data = - PlutusData::deserialize(raw).map_err(|e: DeserializeError| e.annotate("data"))?; - let ex_units = - ExUnits::deserialize(raw).map_err(|e: DeserializeError| e.annotate("ex_units"))?; match len { cbor_event::LenSz::Len(_, _) => (), cbor_event::LenSz::Indefinite => match raw.special()? { @@ -822,18 +1132,199 @@ impl Deserialize for Redeemer { _ => return Err(DeserializeFailure::EndingBreakMissing.into()), }, } - Ok(Redeemer { + Ok(RedeemerKey { tag, index, - data, - ex_units, - encodings: Some(RedeemerEncoding { + encodings: Some(RedeemerKeyEncoding { len_encoding, tag_encoding, index_encoding, }), }) })() - .map_err(|e| e.annotate("Redeemer")) + .map_err(|e| e.annotate("RedeemerKey")) + } +} + +impl Serialize for RedeemerVal { + fn serialize<'se, W: Write>( + &self, + serializer: &'se mut Serializer, + force_canonical: bool, + ) -> cbor_event::Result<&'se mut Serializer> { + serializer.write_array_sz( + self.encodings + .as_ref() + .map(|encs| encs.len_encoding) + .unwrap_or_default() + .to_len_sz(2, force_canonical), + )?; + self.data.serialize(serializer, force_canonical)?; + self.ex_units.serialize(serializer, force_canonical)?; + self.encodings + .as_ref() + .map(|encs| encs.len_encoding) + .unwrap_or_default() + .end(serializer, force_canonical) + } +} + +impl Deserialize for RedeemerVal { + fn deserialize(raw: &mut Deserializer) -> Result { + let len = raw.array_sz()?; + let len_encoding: LenEncoding = len.into(); + let mut read_len = CBORReadLen::new(len); + read_len.read_elems(2)?; + read_len.finish()?; + (|| -> Result<_, DeserializeError> { + let data = + PlutusData::deserialize(raw).map_err(|e: DeserializeError| e.annotate("data"))?; + let ex_units = + ExUnits::deserialize(raw).map_err(|e: DeserializeError| e.annotate("ex_units"))?; + match len { + cbor_event::LenSz::Len(_, _) => (), + cbor_event::LenSz::Indefinite => match raw.special()? { + cbor_event::Special::Break => (), + _ => return Err(DeserializeFailure::EndingBreakMissing.into()), + }, + } + Ok(RedeemerVal { + data, + ex_units, + encodings: Some(RedeemerValEncoding { len_encoding }), + }) + })() + .map_err(|e| e.annotate("RedeemerVal")) + } +} + +impl Serialize for Redeemers { + fn serialize<'se, W: Write>( + &self, + serializer: &'se mut Serializer, + force_canonical: bool, + ) -> cbor_event::Result<&'se mut Serializer> { + match self { + Redeemers::ArrLegacyRedeemer { + arr_legacy_redeemer, + arr_legacy_redeemer_encoding, + } => { + serializer.write_array_sz( + arr_legacy_redeemer_encoding + .to_len_sz(arr_legacy_redeemer.len() as u64, force_canonical), + )?; + for element in arr_legacy_redeemer.iter() { + element.serialize(serializer, force_canonical)?; + } + arr_legacy_redeemer_encoding.end(serializer, force_canonical) + } + Redeemers::MapRedeemerKeyToRedeemerVal { + map_redeemer_key_to_redeemer_val, + map_redeemer_key_to_redeemer_val_encoding, + } => { + serializer.write_map_sz(map_redeemer_key_to_redeemer_val_encoding.to_len_sz( + map_redeemer_key_to_redeemer_val.len() as u64, + force_canonical, + ))?; + let mut key_order = map_redeemer_key_to_redeemer_val + .iter() + .map(|(k, v)| { + let mut buf = cbor_event::se::Serializer::new_vec(); + k.serialize(&mut buf, force_canonical)?; + Ok((buf.finalize(), k, v)) + }) + .collect::, &_, &_)>, cbor_event::Error>>()?; + if force_canonical { + key_order.sort_by(|(lhs_bytes, _, _), (rhs_bytes, _, _)| { + match lhs_bytes.len().cmp(&rhs_bytes.len()) { + std::cmp::Ordering::Equal => lhs_bytes.cmp(rhs_bytes), + diff_ord => diff_ord, + } + }); + } + for (key_bytes, _key, value) in key_order { + serializer.write_raw_bytes(&key_bytes)?; + value.serialize(serializer, force_canonical)?; + } + map_redeemer_key_to_redeemer_val_encoding.end(serializer, force_canonical) + } + } + } +} + +impl Deserialize for Redeemers { + fn deserialize(raw: &mut Deserializer) -> Result { + (|| -> Result<_, DeserializeError> { + match raw.cbor_type()? { + cbor_event::Type::Array => { + let mut arr_legacy_redeemer_arr = Vec::new(); + let len = raw.array_sz()?; + let arr_legacy_redeemer_encoding = len.into(); + while match len { + cbor_event::LenSz::Len(n, _) => (arr_legacy_redeemer_arr.len() as u64) < n, + cbor_event::LenSz::Indefinite => true, + } { + if raw.cbor_type()? == cbor_event::Type::Special { + assert_eq!(raw.special()?, cbor_event::Special::Break); + break; + } + arr_legacy_redeemer_arr.push(LegacyRedeemer::deserialize(raw)?); + } + let (arr_legacy_redeemer, arr_legacy_redeemer_encoding) = + (arr_legacy_redeemer_arr, arr_legacy_redeemer_encoding); + Ok(Self::ArrLegacyRedeemer { + arr_legacy_redeemer, + arr_legacy_redeemer_encoding, + }) + } + cbor_event::Type::Map => { + let mut map_redeemer_key_to_redeemer_val_table = OrderedHashMap::new(); + let map_redeemer_key_to_redeemer_val_len = raw.map_sz()?; + let map_redeemer_key_to_redeemer_val_encoding = + map_redeemer_key_to_redeemer_val_len.into(); + while match map_redeemer_key_to_redeemer_val_len { + cbor_event::LenSz::Len(n, _) => { + (map_redeemer_key_to_redeemer_val_table.len() as u64) < n + } + cbor_event::LenSz::Indefinite => true, + } { + if raw.cbor_type()? == cbor_event::Type::Special { + assert_eq!(raw.special()?, cbor_event::Special::Break); + break; + } + let map_redeemer_key_to_redeemer_val_key = RedeemerKey::deserialize(raw)?; + let map_redeemer_key_to_redeemer_val_value = RedeemerVal::deserialize(raw)?; + if map_redeemer_key_to_redeemer_val_table + .insert( + map_redeemer_key_to_redeemer_val_key.clone(), + map_redeemer_key_to_redeemer_val_value, + ) + .is_some() + { + return Err(DeserializeFailure::DuplicateKey(Key::Str(String::from( + "some complicated/unsupported type", + ))) + .into()); + } + } + let ( + map_redeemer_key_to_redeemer_val, + map_redeemer_key_to_redeemer_val_encoding, + ) = ( + map_redeemer_key_to_redeemer_val_table, + map_redeemer_key_to_redeemer_val_encoding, + ); + Ok(Self::MapRedeemerKeyToRedeemerVal { + map_redeemer_key_to_redeemer_val, + map_redeemer_key_to_redeemer_val_encoding, + }) + } + _ => Err(DeserializeError::new( + "Redeemers", + DeserializeFailure::NoVariantMatched, + )), + } + })() + .map_err(|e| e.annotate("Redeemers")) } } diff --git a/chain/rust/src/plutus/utils.rs b/chain/rust/src/plutus/utils.rs index 66bfbdf4..b36ec259 100644 --- a/chain/rust/src/plutus/utils.rs +++ b/chain/rust/src/plutus/utils.rs @@ -1,11 +1,13 @@ -use super::{CostModels, Language, Redeemer}; +use super::{CostModels, Language, LegacyRedeemer, RedeemerKey, RedeemerVal, Redeemers}; use super::{ExUnits, PlutusData, PlutusV1Script, PlutusV2Script, PlutusV3Script}; use crate::crypto::hash::{hash_script, ScriptHashNamespace}; use cbor_event::de::Deserializer; use cbor_event::se::Serializer; +use cml_core::ordered_hash_map::OrderedHashMap; use cml_core::serialization::*; use cml_core::{error::*, Int}; use cml_crypto::ScriptHash; +use itertools::Itertools; use std::collections::BTreeMap; use std::io::{BufRead, Seek, Write}; @@ -426,7 +428,7 @@ impl ExUnits { } } -pub fn compute_total_ex_units(redeemers: &[Redeemer]) -> Result { +pub fn compute_total_ex_units(redeemers: &[LegacyRedeemer]) -> Result { let mut sum = ExUnits::new(0, 0); for redeemer in redeemers { sum = sum.checked_add(&redeemer.ex_units)?; @@ -560,6 +562,46 @@ impl Deserialize for PlutusMap { } } +impl Redeemers { + pub fn to_flat_format(self) -> Vec { + match self { + Self::ArrLegacyRedeemer { arr_legacy_redeemer, .. } => arr_legacy_redeemer, + Self::MapRedeemerKeyToRedeemerVal { map_redeemer_key_to_redeemer_val, .. } => map_redeemer_key_to_redeemer_val.iter().map(|(k, v)| LegacyRedeemer::new( + k.tag, + k.index, + v.data.clone(), + v.ex_units.clone(), + )).collect_vec(), + } + } + + pub fn to_map_format(self) -> OrderedHashMap { + match self { + Self::ArrLegacyRedeemer { arr_legacy_redeemer, .. } => arr_legacy_redeemer.into_iter().map(|r| (RedeemerKey::new(r.tag, r.index), RedeemerVal::new(r.data, r.ex_units))).collect(), + Self::MapRedeemerKeyToRedeemerVal { map_redeemer_key_to_redeemer_val, .. } => map_redeemer_key_to_redeemer_val, + } + } + + pub fn is_empty(&self) -> bool { + match self { + Self::ArrLegacyRedeemer { arr_legacy_redeemer, .. } => arr_legacy_redeemer.is_empty(), + Self::MapRedeemerKeyToRedeemerVal { map_redeemer_key_to_redeemer_val, .. } => map_redeemer_key_to_redeemer_val.is_empty(), + } + } + + pub fn extend(&mut self, other: Self) { + match self { + Self::ArrLegacyRedeemer { arr_legacy_redeemer, .. } => arr_legacy_redeemer.extend(other.to_flat_format()), + Self::MapRedeemerKeyToRedeemerVal { map_redeemer_key_to_redeemer_val, .. } => { + for (k, v) in other.to_map_format().take() { + map_redeemer_key_to_redeemer_val.insert(k, v); + } + + }, + } + } +} + #[cfg(test)] mod tests { use crate::plutus::CostModels; diff --git a/chain/rust/src/serialization.rs b/chain/rust/src/serialization.rs index 92b944c8..be889d93 100644 --- a/chain/rust/src/serialization.rs +++ b/chain/rust/src/serialization.rs @@ -123,7 +123,7 @@ impl Serialize for PoolVotingThresholds { .as_ref() .map(|encs| encs.len_encoding) .unwrap_or_default() - .to_len_sz(4, force_canonical), + .to_len_sz(5, force_canonical), )?; self.motion_no_confidence .serialize(serializer, force_canonical)?; @@ -133,6 +133,8 @@ impl Serialize for PoolVotingThresholds { .serialize(serializer, force_canonical)?; self.hard_fork_initiation .serialize(serializer, force_canonical)?; + self.security_relevant_parameter_voting_threshold + .serialize(serializer, force_canonical)?; self.encodings .as_ref() .map(|encs| encs.len_encoding) @@ -146,7 +148,7 @@ impl Deserialize for PoolVotingThresholds { let len = raw.array_sz()?; let len_encoding: LenEncoding = len.into(); let mut read_len = CBORReadLen::new(len); - read_len.read_elems(4)?; + read_len.read_elems(5)?; read_len.finish()?; (|| -> Result<_, DeserializeError> { let motion_no_confidence = UnitInterval::deserialize(raw) @@ -157,6 +159,10 @@ impl Deserialize for PoolVotingThresholds { .map_err(|e: DeserializeError| e.annotate("committee_no_confidence"))?; let hard_fork_initiation = UnitInterval::deserialize(raw) .map_err(|e: DeserializeError| e.annotate("hard_fork_initiation"))?; + let security_relevant_parameter_voting_threshold = UnitInterval::deserialize(raw) + .map_err(|e: DeserializeError| { + e.annotate("security_relevant_parameter_voting_threshold") + })?; match len { cbor_event::LenSz::Len(_, _) => (), cbor_event::LenSz::Indefinite => match raw.special()? { @@ -169,6 +175,7 @@ impl Deserialize for PoolVotingThresholds { committee_normal, committee_no_confidence, hard_fork_initiation, + security_relevant_parameter_voting_threshold, encodings: Some(PoolVotingThresholdsEncoding { len_encoding }), }) })() @@ -275,6 +282,9 @@ impl Serialize for ProtocolParamUpdate { } + match &self.d_rep_inactivity_period { Some(_) => 1, None => 0, + } + match &self.min_fee_ref_script_cost_per_byte { + Some(_) => 1, + None => 0, }, force_canonical, ), @@ -372,13 +382,16 @@ impl Serialize for ProtocolParamUpdate { } + match &self.d_rep_inactivity_period { Some(_) => 1, None => 0, + } + match &self.min_fee_ref_script_cost_per_byte { + Some(_) => 1, + None => 0, } }) .map(|encs| encs.orig_deser_order.clone()) .unwrap_or_else(|| { vec![ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, - 22, 23, 24, 25, 26, 27, 28, + 22, 23, 24, 25, 26, 27, 28, 29, ] }); for field_index in deser_order { @@ -1047,6 +1060,22 @@ impl Serialize for ProtocolParamUpdate { )?; } } + 29 => { + if let Some(field) = &self.min_fee_ref_script_cost_per_byte { + serializer.write_unsigned_integer_sz( + 33u64, + fit_sz( + 33u64, + self.encodings + .as_ref() + .map(|encs| encs.min_fee_ref_script_cost_per_byte_key_encoding) + .unwrap_or_default(), + force_canonical, + ), + )?; + field.serialize(serializer, force_canonical)?; + } + } _ => unreachable!(), }; } @@ -1143,6 +1172,8 @@ impl Deserialize for ProtocolParamUpdate { let mut d_rep_inactivity_period_encoding = None; let mut d_rep_inactivity_period_key_encoding = None; let mut d_rep_inactivity_period = None; + let mut min_fee_ref_script_cost_per_byte_key_encoding = None; + let mut min_fee_ref_script_cost_per_byte = None; let mut read = 0; while match len { cbor_event::LenSz::Len(n, _) => read < n, cbor_event::LenSz::Indefinite => true, } { match raw.cbor_type()? { @@ -1153,7 +1184,7 @@ impl Deserialize for ProtocolParamUpdate { } let (tmp_minfee_a, tmp_minfee_a_encoding) = (|| -> Result<_, DeserializeError> { read_len.read_elems(1)?; - raw.unsigned_integer_sz().map(|(x, enc)| (x, Some(enc))).map_err(Into::::into) + raw.unsigned_integer_sz().map_err(Into::::into).map(|(x, enc)| (x, Some(enc))) })().map_err(|e| e.annotate("minfee_a"))?; minfee_a = Some(tmp_minfee_a); minfee_a_encoding = tmp_minfee_a_encoding; @@ -1166,7 +1197,7 @@ impl Deserialize for ProtocolParamUpdate { } let (tmp_minfee_b, tmp_minfee_b_encoding) = (|| -> Result<_, DeserializeError> { read_len.read_elems(1)?; - raw.unsigned_integer_sz().map(|(x, enc)| (x, Some(enc))).map_err(Into::::into) + raw.unsigned_integer_sz().map_err(Into::::into).map(|(x, enc)| (x, Some(enc))) })().map_err(|e| e.annotate("minfee_b"))?; minfee_b = Some(tmp_minfee_b); minfee_b_encoding = tmp_minfee_b_encoding; @@ -1179,7 +1210,7 @@ impl Deserialize for ProtocolParamUpdate { } let (tmp_max_block_body_size, tmp_max_block_body_size_encoding) = (|| -> Result<_, DeserializeError> { read_len.read_elems(1)?; - raw.unsigned_integer_sz().map(|(x, enc)| (x, Some(enc))).map_err(Into::::into) + raw.unsigned_integer_sz().map_err(Into::::into).map(|(x, enc)| (x, Some(enc))) })().map_err(|e| e.annotate("max_block_body_size"))?; max_block_body_size = Some(tmp_max_block_body_size); max_block_body_size_encoding = tmp_max_block_body_size_encoding; @@ -1192,7 +1223,7 @@ impl Deserialize for ProtocolParamUpdate { } let (tmp_max_transaction_size, tmp_max_transaction_size_encoding) = (|| -> Result<_, DeserializeError> { read_len.read_elems(1)?; - raw.unsigned_integer_sz().map(|(x, enc)| (x, Some(enc))).map_err(Into::::into) + raw.unsigned_integer_sz().map_err(Into::::into).map(|(x, enc)| (x, Some(enc))) })().map_err(|e| e.annotate("max_transaction_size"))?; max_transaction_size = Some(tmp_max_transaction_size); max_transaction_size_encoding = tmp_max_transaction_size_encoding; @@ -1205,7 +1236,7 @@ impl Deserialize for ProtocolParamUpdate { } let (tmp_max_block_header_size, tmp_max_block_header_size_encoding) = (|| -> Result<_, DeserializeError> { read_len.read_elems(1)?; - raw.unsigned_integer_sz().map(|(x, enc)| (x, Some(enc))).map_err(Into::::into) + raw.unsigned_integer_sz().map_err(Into::::into).map(|(x, enc)| (x, Some(enc))) })().map_err(|e| e.annotate("max_block_header_size"))?; max_block_header_size = Some(tmp_max_block_header_size); max_block_header_size_encoding = tmp_max_block_header_size_encoding; @@ -1218,7 +1249,7 @@ impl Deserialize for ProtocolParamUpdate { } let (tmp_key_deposit, tmp_key_deposit_encoding) = (|| -> Result<_, DeserializeError> { read_len.read_elems(1)?; - raw.unsigned_integer_sz().map(|(x, enc)| (x, Some(enc))).map_err(Into::::into) + raw.unsigned_integer_sz().map_err(Into::::into).map(|(x, enc)| (x, Some(enc))) })().map_err(|e| e.annotate("key_deposit"))?; key_deposit = Some(tmp_key_deposit); key_deposit_encoding = tmp_key_deposit_encoding; @@ -1231,7 +1262,7 @@ impl Deserialize for ProtocolParamUpdate { } let (tmp_pool_deposit, tmp_pool_deposit_encoding) = (|| -> Result<_, DeserializeError> { read_len.read_elems(1)?; - raw.unsigned_integer_sz().map(|(x, enc)| (x, Some(enc))).map_err(Into::::into) + raw.unsigned_integer_sz().map_err(Into::::into).map(|(x, enc)| (x, Some(enc))) })().map_err(|e| e.annotate("pool_deposit"))?; pool_deposit = Some(tmp_pool_deposit); pool_deposit_encoding = tmp_pool_deposit_encoding; @@ -1244,7 +1275,7 @@ impl Deserialize for ProtocolParamUpdate { } let (tmp_maximum_epoch, tmp_maximum_epoch_encoding) = (|| -> Result<_, DeserializeError> { read_len.read_elems(1)?; - raw.unsigned_integer_sz().map(|(x, enc)| (x, Some(enc))).map_err(Into::::into) + raw.unsigned_integer_sz().map_err(Into::::into).map(|(x, enc)| (x, Some(enc))) })().map_err(|e| e.annotate("maximum_epoch"))?; maximum_epoch = Some(tmp_maximum_epoch); maximum_epoch_encoding = tmp_maximum_epoch_encoding; @@ -1257,7 +1288,7 @@ impl Deserialize for ProtocolParamUpdate { } let (tmp_n_opt, tmp_n_opt_encoding) = (|| -> Result<_, DeserializeError> { read_len.read_elems(1)?; - raw.unsigned_integer_sz().map(|(x, enc)| (x, Some(enc))).map_err(Into::::into) + raw.unsigned_integer_sz().map_err(Into::::into).map(|(x, enc)| (x, Some(enc))) })().map_err(|e| e.annotate("n_opt"))?; n_opt = Some(tmp_n_opt); n_opt_encoding = tmp_n_opt_encoding; @@ -1306,7 +1337,7 @@ impl Deserialize for ProtocolParamUpdate { } let (tmp_min_pool_cost, tmp_min_pool_cost_encoding) = (|| -> Result<_, DeserializeError> { read_len.read_elems(1)?; - raw.unsigned_integer_sz().map(|(x, enc)| (x, Some(enc))).map_err(Into::::into) + raw.unsigned_integer_sz().map_err(Into::::into).map(|(x, enc)| (x, Some(enc))) })().map_err(|e| e.annotate("min_pool_cost"))?; min_pool_cost = Some(tmp_min_pool_cost); min_pool_cost_encoding = tmp_min_pool_cost_encoding; @@ -1319,7 +1350,7 @@ impl Deserialize for ProtocolParamUpdate { } let (tmp_ada_per_utxo_byte, tmp_ada_per_utxo_byte_encoding) = (|| -> Result<_, DeserializeError> { read_len.read_elems(1)?; - raw.unsigned_integer_sz().map(|(x, enc)| (x, Some(enc))).map_err(Into::::into) + raw.unsigned_integer_sz().map_err(Into::::into).map(|(x, enc)| (x, Some(enc))) })().map_err(|e| e.annotate("ada_per_utxo_byte"))?; ada_per_utxo_byte = Some(tmp_ada_per_utxo_byte); ada_per_utxo_byte_encoding = tmp_ada_per_utxo_byte_encoding; @@ -1380,7 +1411,7 @@ impl Deserialize for ProtocolParamUpdate { } let (tmp_max_value_size, tmp_max_value_size_encoding) = (|| -> Result<_, DeserializeError> { read_len.read_elems(1)?; - raw.unsigned_integer_sz().map(|(x, enc)| (x, Some(enc))).map_err(Into::::into) + raw.unsigned_integer_sz().map_err(Into::::into).map(|(x, enc)| (x, Some(enc))) })().map_err(|e| e.annotate("max_value_size"))?; max_value_size = Some(tmp_max_value_size); max_value_size_encoding = tmp_max_value_size_encoding; @@ -1393,7 +1424,7 @@ impl Deserialize for ProtocolParamUpdate { } let (tmp_collateral_percentage, tmp_collateral_percentage_encoding) = (|| -> Result<_, DeserializeError> { read_len.read_elems(1)?; - raw.unsigned_integer_sz().map(|(x, enc)| (x, Some(enc))).map_err(Into::::into) + raw.unsigned_integer_sz().map_err(Into::::into).map(|(x, enc)| (x, Some(enc))) })().map_err(|e| e.annotate("collateral_percentage"))?; collateral_percentage = Some(tmp_collateral_percentage); collateral_percentage_encoding = tmp_collateral_percentage_encoding; @@ -1406,7 +1437,7 @@ impl Deserialize for ProtocolParamUpdate { } let (tmp_max_collateral_inputs, tmp_max_collateral_inputs_encoding) = (|| -> Result<_, DeserializeError> { read_len.read_elems(1)?; - raw.unsigned_integer_sz().map(|(x, enc)| (x, Some(enc))).map_err(Into::::into) + raw.unsigned_integer_sz().map_err(Into::::into).map(|(x, enc)| (x, Some(enc))) })().map_err(|e| e.annotate("max_collateral_inputs"))?; max_collateral_inputs = Some(tmp_max_collateral_inputs); max_collateral_inputs_encoding = tmp_max_collateral_inputs_encoding; @@ -1443,7 +1474,7 @@ impl Deserialize for ProtocolParamUpdate { } let (tmp_min_committee_size, tmp_min_committee_size_encoding) = (|| -> Result<_, DeserializeError> { read_len.read_elems(1)?; - raw.unsigned_integer_sz().map(|(x, enc)| (x, Some(enc))).map_err(Into::::into) + raw.unsigned_integer_sz().map_err(Into::::into).map(|(x, enc)| (x, Some(enc))) })().map_err(|e| e.annotate("min_committee_size"))?; min_committee_size = Some(tmp_min_committee_size); min_committee_size_encoding = tmp_min_committee_size_encoding; @@ -1456,7 +1487,7 @@ impl Deserialize for ProtocolParamUpdate { } let (tmp_committee_term_limit, tmp_committee_term_limit_encoding) = (|| -> Result<_, DeserializeError> { read_len.read_elems(1)?; - raw.unsigned_integer_sz().map(|(x, enc)| (x, Some(enc))).map_err(Into::::into) + raw.unsigned_integer_sz().map_err(Into::::into).map(|(x, enc)| (x, Some(enc))) })().map_err(|e| e.annotate("committee_term_limit"))?; committee_term_limit = Some(tmp_committee_term_limit); committee_term_limit_encoding = tmp_committee_term_limit_encoding; @@ -1469,7 +1500,7 @@ impl Deserialize for ProtocolParamUpdate { } let (tmp_governance_action_validity_period, tmp_governance_action_validity_period_encoding) = (|| -> Result<_, DeserializeError> { read_len.read_elems(1)?; - raw.unsigned_integer_sz().map(|(x, enc)| (x, Some(enc))).map_err(Into::::into) + raw.unsigned_integer_sz().map_err(Into::::into).map(|(x, enc)| (x, Some(enc))) })().map_err(|e| e.annotate("governance_action_validity_period"))?; governance_action_validity_period = Some(tmp_governance_action_validity_period); governance_action_validity_period_encoding = tmp_governance_action_validity_period_encoding; @@ -1482,7 +1513,7 @@ impl Deserialize for ProtocolParamUpdate { } let (tmp_governance_action_deposit, tmp_governance_action_deposit_encoding) = (|| -> Result<_, DeserializeError> { read_len.read_elems(1)?; - raw.unsigned_integer_sz().map(|(x, enc)| (x, Some(enc))).map_err(Into::::into) + raw.unsigned_integer_sz().map_err(Into::::into).map(|(x, enc)| (x, Some(enc))) })().map_err(|e| e.annotate("governance_action_deposit"))?; governance_action_deposit = Some(tmp_governance_action_deposit); governance_action_deposit_encoding = tmp_governance_action_deposit_encoding; @@ -1495,7 +1526,7 @@ impl Deserialize for ProtocolParamUpdate { } let (tmp_d_rep_deposit, tmp_d_rep_deposit_encoding) = (|| -> Result<_, DeserializeError> { read_len.read_elems(1)?; - raw.unsigned_integer_sz().map(|(x, enc)| (x, Some(enc))).map_err(Into::::into) + raw.unsigned_integer_sz().map_err(Into::::into).map(|(x, enc)| (x, Some(enc))) })().map_err(|e| e.annotate("d_rep_deposit"))?; d_rep_deposit = Some(tmp_d_rep_deposit); d_rep_deposit_encoding = tmp_d_rep_deposit_encoding; @@ -1508,13 +1539,25 @@ impl Deserialize for ProtocolParamUpdate { } let (tmp_d_rep_inactivity_period, tmp_d_rep_inactivity_period_encoding) = (|| -> Result<_, DeserializeError> { read_len.read_elems(1)?; - raw.unsigned_integer_sz().map(|(x, enc)| (x, Some(enc))).map_err(Into::::into) + raw.unsigned_integer_sz().map_err(Into::::into).map(|(x, enc)| (x, Some(enc))) })().map_err(|e| e.annotate("d_rep_inactivity_period"))?; d_rep_inactivity_period = Some(tmp_d_rep_inactivity_period); d_rep_inactivity_period_encoding = tmp_d_rep_inactivity_period_encoding; d_rep_inactivity_period_key_encoding = Some(key_enc); orig_deser_order.push(28); }, + (33, key_enc) => { + if min_fee_ref_script_cost_per_byte.is_some() { + return Err(DeserializeFailure::DuplicateKey(Key::Uint(33)).into()); + } + let tmp_min_fee_ref_script_cost_per_byte = (|| -> Result<_, DeserializeError> { + read_len.read_elems(1)?; + Rational::deserialize(raw) + })().map_err(|e| e.annotate("min_fee_ref_script_cost_per_byte"))?; + min_fee_ref_script_cost_per_byte = Some(tmp_min_fee_ref_script_cost_per_byte); + min_fee_ref_script_cost_per_byte_key_encoding = Some(key_enc); + orig_deser_order.push(29); + }, (unknown_key, _enc) => return Err(DeserializeFailure::UnknownKey(Key::Uint(unknown_key)).into()), }, cbor_event::Type::Text => return Err(DeserializeFailure::UnknownKey(Key::Str(raw.text()?)).into()), @@ -1560,6 +1603,7 @@ impl Deserialize for ProtocolParamUpdate { governance_action_deposit, d_rep_deposit, d_rep_inactivity_period, + min_fee_ref_script_cost_per_byte, encodings: Some(ProtocolParamUpdateEncoding { len_encoding, orig_deser_order, @@ -1612,6 +1656,7 @@ impl Deserialize for ProtocolParamUpdate { d_rep_deposit_encoding, d_rep_inactivity_period_key_encoding, d_rep_inactivity_period_encoding, + min_fee_ref_script_cost_per_byte_key_encoding, }), }) })().map_err(|e| e.annotate("ProtocolParamUpdate")) @@ -1692,13 +1737,13 @@ impl Deserialize for Rational { (|| -> Result<_, DeserializeError> { let (numerator, numerator_encoding) = raw .unsigned_integer_sz() - .map(|(x, enc)| (x, Some(enc))) .map_err(Into::::into) + .map(|(x, enc)| (x, Some(enc))) .map_err(|e: DeserializeError| e.annotate("numerator"))?; let (denominator, denominator_encoding) = raw .unsigned_integer_sz() - .map(|(x, enc)| (x, Some(enc))) .map_err(Into::::into) + .map(|(x, enc)| (x, Some(enc))) .map_err(|e: DeserializeError| e.annotate("denominator"))?; match len { cbor_event::LenSz::Len(_, _) => (), diff --git a/chain/rust/src/transaction/cbor_encodings.rs b/chain/rust/src/transaction/cbor_encodings.rs index 6796124e..73545a08 100644 --- a/chain/rust/src/transaction/cbor_encodings.rs +++ b/chain/rust/src/transaction/cbor_encodings.rs @@ -71,7 +71,6 @@ pub struct ScriptPubkeyEncoding { pub struct TransactionBodyEncoding { pub len_encoding: LenEncoding, pub orig_deser_order: Vec, - pub inputs_encoding: LenEncoding, pub inputs_key_encoding: Option, pub outputs_encoding: LenEncoding, pub outputs_key_encoding: Option, @@ -79,7 +78,6 @@ pub struct TransactionBodyEncoding { pub fee_key_encoding: Option, pub ttl_encoding: Option, pub ttl_key_encoding: Option, - pub certs_encoding: LenEncoding, pub certs_key_encoding: Option, pub withdrawals_encoding: LenEncoding, pub withdrawals_value_encodings: BTreeMap>, @@ -95,21 +93,16 @@ pub struct TransactionBodyEncoding { pub mint_key_encoding: Option, pub script_data_hash_encoding: StringEncoding, pub script_data_hash_key_encoding: Option, - pub collateral_inputs_encoding: LenEncoding, pub collateral_inputs_key_encoding: Option, - pub required_signers_encoding: LenEncoding, - pub required_signers_elem_encodings: Vec, pub required_signers_key_encoding: Option, pub network_id_key_encoding: Option, pub collateral_return_key_encoding: Option, pub total_collateral_encoding: Option, pub total_collateral_key_encoding: Option, - pub reference_inputs_encoding: LenEncoding, pub reference_inputs_key_encoding: Option, pub voting_procedures_encoding: LenEncoding, pub voting_procedures_value_encodings: BTreeMap, pub voting_procedures_key_encoding: Option, - pub proposal_procedures_encoding: LenEncoding, pub proposal_procedures_key_encoding: Option, pub current_treasury_value_encoding: Option, pub current_treasury_value_key_encoding: Option, @@ -133,20 +126,12 @@ pub struct TransactionInputEncoding { pub struct TransactionWitnessSetEncoding { pub len_encoding: LenEncoding, pub orig_deser_order: Vec, - pub vkeywitnesses_encoding: LenEncoding, pub vkeywitnesses_key_encoding: Option, - pub native_scripts_encoding: LenEncoding, pub native_scripts_key_encoding: Option, - pub bootstrap_witnesses_encoding: LenEncoding, pub bootstrap_witnesses_key_encoding: Option, - pub plutus_v1_scripts_encoding: LenEncoding, pub plutus_v1_scripts_key_encoding: Option, - pub plutus_datums_encoding: LenEncoding, pub plutus_datums_key_encoding: Option, - pub redeemers_encoding: LenEncoding, pub redeemers_key_encoding: Option, - pub plutus_v2_scripts_encoding: LenEncoding, pub plutus_v2_scripts_key_encoding: Option, - pub plutus_v3_scripts_encoding: LenEncoding, pub plutus_v3_scripts_key_encoding: Option, } diff --git a/chain/rust/src/transaction/mod.rs b/chain/rust/src/transaction/mod.rs index 1030d1c2..d53887d3 100644 --- a/chain/rust/src/transaction/mod.rs +++ b/chain/rust/src/transaction/mod.rs @@ -5,18 +5,19 @@ pub mod cbor_encodings; pub mod serialization; pub mod utils; -use super::{NetworkId, Slot, Value, Withdrawals}; +use super::{NetworkId, Value}; use crate::address::Address; use crate::assets::{Coin, Mint, PositiveCoin}; use crate::auxdata::AuxiliaryData; -use crate::certs::Certificate; use crate::crypto::{ - AuxiliaryDataHash, BootstrapWitness, DatumHash, Ed25519KeyHash, ScriptDataHash, - TransactionHash, Vkeywitness, + AuxiliaryDataHash, DatumHash, Ed25519KeyHash, ScriptDataHash, + TransactionHash, +}; +use crate::governance::VotingProcedures; +use crate::plutus::{PlutusData, Redeemers}; +use crate::{ + NonemptySetBootstrapWitness, NonemptySetCertificate, NonemptySetNativeScript, NonemptySetPlutusData, NonemptySetPlutusV1Script, NonemptySetPlutusV2Script, NonemptySetPlutusV3Script, NonemptySetProposalProcedure, NonemptySetTransactionInput, NonemptySetVkeywitness, RequiredSigners, Script, SetTransactionInput, Slot, Withdrawals }; -use crate::governance::{ProposalProcedure, VotingProcedures}; -use crate::plutus::{PlutusData, PlutusV1Script, PlutusV2Script, PlutusV3Script, Redeemer}; -use crate::Script; use cbor_encodings::{ AlonzoFormatTxOutEncoding, ConwayFormatTxOutEncoding, ScriptAllEncoding, ScriptAnyEncoding, ScriptInvalidBeforeEncoding, ScriptInvalidHereafterEncoding, ScriptNOfKEncoding, @@ -170,7 +171,6 @@ impl NativeScript { } } -pub type RequiredSigners = Vec; #[derive( Clone, Debug, derivative::Derivative, serde::Deserialize, serde::Serialize, schemars::JsonSchema, @@ -325,24 +325,24 @@ impl Transaction { #[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] pub struct TransactionBody { - pub inputs: Vec, + pub inputs: SetTransactionInput, pub outputs: Vec, pub fee: Coin, pub ttl: Option, - pub certs: Option>, + pub certs: Option, pub withdrawals: Option, pub auxiliary_data_hash: Option, pub validity_interval_start: Option, pub mint: Option, pub script_data_hash: Option, - pub collateral_inputs: Option>, + pub collateral_inputs: Option, pub required_signers: Option, pub network_id: Option, pub collateral_return: Option, pub total_collateral: Option, - pub reference_inputs: Option>, + pub reference_inputs: Option, pub voting_procedures: Option, - pub proposal_procedures: Option>, + pub proposal_procedures: Option, pub current_treasury_value: Option, pub donation: Option, #[serde(skip)] @@ -350,7 +350,7 @@ pub struct TransactionBody { } impl TransactionBody { - pub fn new(inputs: Vec, outputs: Vec, fee: Coin) -> Self { + pub fn new(inputs: SetTransactionInput, outputs: Vec, fee: Coin) -> Self { Self { inputs, outputs, @@ -424,14 +424,14 @@ impl TransactionOutput { #[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] pub struct TransactionWitnessSet { - pub vkeywitnesses: Option>, - pub native_scripts: Option>, - pub bootstrap_witnesses: Option>, - pub plutus_v1_scripts: Option>, - pub plutus_datums: Option>, - pub redeemers: Option>, - pub plutus_v2_scripts: Option>, - pub plutus_v3_scripts: Option>, + pub vkeywitnesses: Option, + pub native_scripts: Option, + pub bootstrap_witnesses: Option, + pub plutus_v1_scripts: Option, + pub plutus_datums: Option, + pub redeemers: Option, + pub plutus_v2_scripts: Option, + pub plutus_v3_scripts: Option, #[serde(skip)] pub encodings: Option, } diff --git a/chain/rust/src/transaction/serialization.rs b/chain/rust/src/transaction/serialization.rs index 6c331ecd..bfba7b2c 100644 --- a/chain/rust/src/transaction/serialization.rs +++ b/chain/rust/src/transaction/serialization.rs @@ -5,6 +5,7 @@ use super::cbor_encodings::*; use super::*; use crate::address::RewardAccount; use crate::governance::{GovActionId, Voter, VotingProcedure}; +use crate::plutus::Redeemers; use crate::{assets::AssetName, Script}; use cbor_event; use cbor_event::de::Deserializer; @@ -1104,8 +1105,8 @@ impl DeserializeEmbeddedGroup for ScriptInvalidBefore { .map_err(|e| e.annotate("tag"))?; let (before, before_encoding) = raw .unsigned_integer_sz() - .map(|(x, enc)| (x, Some(enc))) .map_err(Into::::into) + .map(|(x, enc)| (x, Some(enc))) .map_err(|e: DeserializeError| e.annotate("before"))?; Ok(ScriptInvalidBefore { before, @@ -1213,8 +1214,8 @@ impl DeserializeEmbeddedGroup for ScriptInvalidHereafter { .map_err(|e| e.annotate("tag"))?; let (after, after_encoding) = raw .unsigned_integer_sz() - .map(|(x, enc)| (x, Some(enc))) .map_err(Into::::into) + .map(|(x, enc)| (x, Some(enc))) .map_err(|e: DeserializeError| e.annotate("after"))?; Ok(ScriptInvalidHereafter { after, @@ -1337,8 +1338,8 @@ impl DeserializeEmbeddedGroup for ScriptNOfK { .map_err(|e| e.annotate("tag"))?; let (n, n_encoding) = raw .unsigned_integer_sz() - .map(|(x, enc)| (x, Some(enc))) .map_err(Into::::into) + .map(|(x, enc)| (x, Some(enc))) .map_err(|e: DeserializeError| e.annotate("n"))?; let (native_scripts, native_scripts_encoding) = (|| -> Result<_, DeserializeError> { let mut native_scripts_arr = Vec::new(); @@ -1706,21 +1707,7 @@ impl Serialize for TransactionBody { force_canonical, ), )?; - serializer.write_array_sz( - self.encodings - .as_ref() - .map(|encs| encs.inputs_encoding) - .unwrap_or_default() - .to_len_sz(self.inputs.len() as u64, force_canonical), - )?; - for element in self.inputs.iter() { - element.serialize(serializer, force_canonical)?; - } - self.encodings - .as_ref() - .map(|encs| encs.inputs_encoding) - .unwrap_or_default() - .end(serializer, force_canonical)?; + self.inputs.serialize(serializer, force_canonical)?; } 1 => { serializer.write_unsigned_integer_sz( @@ -1813,21 +1800,7 @@ impl Serialize for TransactionBody { force_canonical, ), )?; - serializer.write_array_sz( - self.encodings - .as_ref() - .map(|encs| encs.certs_encoding) - .unwrap_or_default() - .to_len_sz(field.len() as u64, force_canonical), - )?; - for element in field.iter() { - element.serialize(serializer, force_canonical)?; - } - self.encodings - .as_ref() - .map(|encs| encs.certs_encoding) - .unwrap_or_default() - .end(serializer, force_canonical)?; + field.serialize(serializer, force_canonical)?; } } 5 => { @@ -2087,21 +2060,7 @@ impl Serialize for TransactionBody { force_canonical, ), )?; - serializer.write_array_sz( - self.encodings - .as_ref() - .map(|encs| encs.collateral_inputs_encoding) - .unwrap_or_default() - .to_len_sz(field.len() as u64, force_canonical), - )?; - for element in field.iter() { - element.serialize(serializer, force_canonical)?; - } - self.encodings - .as_ref() - .map(|encs| encs.collateral_inputs_encoding) - .unwrap_or_default() - .end(serializer, force_canonical)?; + field.serialize(serializer, force_canonical)?; } } 11 => { @@ -2117,33 +2076,7 @@ impl Serialize for TransactionBody { force_canonical, ), )?; - serializer.write_array_sz( - self.encodings - .as_ref() - .map(|encs| encs.required_signers_encoding) - .unwrap_or_default() - .to_len_sz(field.len() as u64, force_canonical), - )?; - for (i, element) in field.iter().enumerate() { - let required_signers_elem_encoding = self - .encodings - .as_ref() - .and_then(|encs| encs.required_signers_elem_encodings.get(i)) - .cloned() - .unwrap_or_default(); - serializer.write_bytes_sz( - element.to_raw_bytes(), - required_signers_elem_encoding.to_str_len_sz( - element.to_raw_bytes().len() as u64, - force_canonical, - ), - )?; - } - self.encodings - .as_ref() - .map(|encs| encs.required_signers_encoding) - .unwrap_or_default() - .end(serializer, force_canonical)?; + field.serialize(serializer, force_canonical)?; } } 12 => { @@ -2217,21 +2150,7 @@ impl Serialize for TransactionBody { force_canonical, ), )?; - serializer.write_array_sz( - self.encodings - .as_ref() - .map(|encs| encs.reference_inputs_encoding) - .unwrap_or_default() - .to_len_sz(field.len() as u64, force_canonical), - )?; - for element in field.iter() { - element.serialize(serializer, force_canonical)?; - } - self.encodings - .as_ref() - .map(|encs| encs.reference_inputs_encoding) - .unwrap_or_default() - .end(serializer, force_canonical)?; + field.serialize(serializer, force_canonical)?; } } 16 => { @@ -2327,21 +2246,7 @@ impl Serialize for TransactionBody { force_canonical, ), )?; - serializer.write_array_sz( - self.encodings - .as_ref() - .map(|encs| encs.proposal_procedures_encoding) - .unwrap_or_default() - .to_len_sz(field.len() as u64, force_canonical), - )?; - for element in field.iter() { - element.serialize(serializer, force_canonical)?; - } - self.encodings - .as_ref() - .map(|encs| encs.proposal_procedures_encoding) - .unwrap_or_default() - .end(serializer, force_canonical)?; + field.serialize(serializer, force_canonical)?; } } 18 => { @@ -2415,7 +2320,6 @@ impl Deserialize for TransactionBody { read_len.read_elems(3)?; (|| -> Result<_, DeserializeError> { let mut orig_deser_order = Vec::new(); - let mut inputs_encoding = LenEncoding::default(); let mut inputs_key_encoding = None; let mut inputs = None; let mut outputs_encoding = LenEncoding::default(); @@ -2427,7 +2331,6 @@ impl Deserialize for TransactionBody { let mut ttl_encoding = None; let mut ttl_key_encoding = None; let mut ttl = None; - let mut certs_encoding = LenEncoding::default(); let mut certs_key_encoding = None; let mut certs = None; let mut withdrawals_encoding = LenEncoding::default(); @@ -2448,11 +2351,8 @@ impl Deserialize for TransactionBody { let mut script_data_hash_encoding = StringEncoding::default(); let mut script_data_hash_key_encoding = None; let mut script_data_hash = None; - let mut collateral_inputs_encoding = LenEncoding::default(); let mut collateral_inputs_key_encoding = None; let mut collateral_inputs = None; - let mut required_signers_encoding = LenEncoding::default(); - let mut required_signers_elem_encodings = Vec::new(); let mut required_signers_key_encoding = None; let mut required_signers = None; let mut network_id_key_encoding = None; @@ -2462,14 +2362,12 @@ impl Deserialize for TransactionBody { let mut total_collateral_encoding = None; let mut total_collateral_key_encoding = None; let mut total_collateral = None; - let mut reference_inputs_encoding = LenEncoding::default(); let mut reference_inputs_key_encoding = None; let mut reference_inputs = None; let mut voting_procedures_encoding = LenEncoding::default(); let mut voting_procedures_value_encodings = BTreeMap::new(); let mut voting_procedures_key_encoding = None; let mut voting_procedures = None; - let mut proposal_procedures_encoding = LenEncoding::default(); let mut proposal_procedures_key_encoding = None; let mut proposal_procedures = None; let mut current_treasury_value_encoding = None; @@ -2486,21 +2384,8 @@ impl Deserialize for TransactionBody { if inputs.is_some() { return Err(DeserializeFailure::DuplicateKey(Key::Uint(0)).into()); } - let (tmp_inputs, tmp_inputs_encoding) = (|| -> Result<_, DeserializeError> { - let mut inputs_arr = Vec::new(); - let len = raw.array_sz()?; - let inputs_encoding = len.into(); - while match len { cbor_event::LenSz::Len(n, _) => (inputs_arr.len() as u64) < n, cbor_event::LenSz::Indefinite => true, } { - if raw.cbor_type()? == cbor_event::Type::Special { - assert_eq!(raw.special()?, cbor_event::Special::Break); - break; - } - inputs_arr.push(TransactionInput::deserialize(raw)?); - } - Ok((inputs_arr, inputs_encoding)) - })().map_err(|e| e.annotate("inputs"))?; + let tmp_inputs = SetTransactionInput::deserialize(raw).map_err(|e: DeserializeError| e.annotate("inputs"))?; inputs = Some(tmp_inputs); - inputs_encoding = tmp_inputs_encoding; inputs_key_encoding = Some(key_enc); orig_deser_order.push(0); }, @@ -2530,7 +2415,7 @@ impl Deserialize for TransactionBody { if fee.is_some() { return Err(DeserializeFailure::DuplicateKey(Key::Uint(2)).into()); } - let (tmp_fee, tmp_fee_encoding) = raw.unsigned_integer_sz().map(|(x, enc)| (x, Some(enc))).map_err(Into::::into).map_err(|e: DeserializeError| e.annotate("fee"))?; + let (tmp_fee, tmp_fee_encoding) = raw.unsigned_integer_sz().map_err(Into::::into).map(|(x, enc)| (x, Some(enc))).map_err(|e: DeserializeError| e.annotate("fee"))?; fee = Some(tmp_fee); fee_encoding = tmp_fee_encoding; fee_key_encoding = Some(key_enc); @@ -2542,7 +2427,7 @@ impl Deserialize for TransactionBody { } let (tmp_ttl, tmp_ttl_encoding) = (|| -> Result<_, DeserializeError> { read_len.read_elems(1)?; - raw.unsigned_integer_sz().map(|(x, enc)| (x, Some(enc))).map_err(Into::::into) + raw.unsigned_integer_sz().map_err(Into::::into).map(|(x, enc)| (x, Some(enc))) })().map_err(|e| e.annotate("ttl"))?; ttl = Some(tmp_ttl); ttl_encoding = tmp_ttl_encoding; @@ -2553,22 +2438,11 @@ impl Deserialize for TransactionBody { if certs.is_some() { return Err(DeserializeFailure::DuplicateKey(Key::Uint(4)).into()); } - let (tmp_certs, tmp_certs_encoding) = (|| -> Result<_, DeserializeError> { + let tmp_certs = (|| -> Result<_, DeserializeError> { read_len.read_elems(1)?; - let mut certs_arr = Vec::new(); - let len = raw.array_sz()?; - let certs_encoding = len.into(); - while match len { cbor_event::LenSz::Len(n, _) => (certs_arr.len() as u64) < n, cbor_event::LenSz::Indefinite => true, } { - if raw.cbor_type()? == cbor_event::Type::Special { - assert_eq!(raw.special()?, cbor_event::Special::Break); - break; - } - certs_arr.push(Certificate::deserialize(raw)?); - } - Ok((certs_arr, certs_encoding)) + NonemptySetCertificate::deserialize(raw) })().map_err(|e| e.annotate("certs"))?; certs = Some(tmp_certs); - certs_encoding = tmp_certs_encoding; certs_key_encoding = Some(key_enc); orig_deser_order.push(4); }, @@ -2621,7 +2495,7 @@ impl Deserialize for TransactionBody { } let (tmp_validity_interval_start, tmp_validity_interval_start_encoding) = (|| -> Result<_, DeserializeError> { read_len.read_elems(1)?; - raw.unsigned_integer_sz().map(|(x, enc)| (x, Some(enc))).map_err(Into::::into) + raw.unsigned_integer_sz().map_err(Into::::into).map(|(x, enc)| (x, Some(enc))) })().map_err(|e| e.annotate("validity_interval_start"))?; validity_interval_start = Some(tmp_validity_interval_start); validity_interval_start_encoding = tmp_validity_interval_start_encoding; @@ -2703,22 +2577,11 @@ impl Deserialize for TransactionBody { if collateral_inputs.is_some() { return Err(DeserializeFailure::DuplicateKey(Key::Uint(13)).into()); } - let (tmp_collateral_inputs, tmp_collateral_inputs_encoding) = (|| -> Result<_, DeserializeError> { + let tmp_collateral_inputs = (|| -> Result<_, DeserializeError> { read_len.read_elems(1)?; - let mut collateral_inputs_arr = Vec::new(); - let len = raw.array_sz()?; - let collateral_inputs_encoding = len.into(); - while match len { cbor_event::LenSz::Len(n, _) => (collateral_inputs_arr.len() as u64) < n, cbor_event::LenSz::Indefinite => true, } { - if raw.cbor_type()? == cbor_event::Type::Special { - assert_eq!(raw.special()?, cbor_event::Special::Break); - break; - } - collateral_inputs_arr.push(TransactionInput::deserialize(raw)?); - } - Ok((collateral_inputs_arr, collateral_inputs_encoding)) + NonemptySetTransactionInput::deserialize(raw) })().map_err(|e| e.annotate("collateral_inputs"))?; collateral_inputs = Some(tmp_collateral_inputs); - collateral_inputs_encoding = tmp_collateral_inputs_encoding; collateral_inputs_key_encoding = Some(key_enc); orig_deser_order.push(10); }, @@ -2726,26 +2589,11 @@ impl Deserialize for TransactionBody { if required_signers.is_some() { return Err(DeserializeFailure::DuplicateKey(Key::Uint(14)).into()); } - let (tmp_required_signers, tmp_required_signers_encoding, tmp_required_signers_elem_encodings) = (|| -> Result<_, DeserializeError> { + let tmp_required_signers = (|| -> Result<_, DeserializeError> { read_len.read_elems(1)?; - let mut required_signers_arr = Vec::new(); - let len = raw.array_sz()?; - let required_signers_encoding = len.into(); - let mut required_signers_elem_encodings = Vec::new(); - while match len { cbor_event::LenSz::Len(n, _) => (required_signers_arr.len() as u64) < n, cbor_event::LenSz::Indefinite => true, } { - if raw.cbor_type()? == cbor_event::Type::Special { - assert_eq!(raw.special()?, cbor_event::Special::Break); - break; - } - let (required_signers_elem, required_signers_elem_encoding) = raw.bytes_sz().map_err(Into::::into).and_then(|(bytes, enc)| Ed25519KeyHash::from_raw_bytes(&bytes).map(|bytes| (bytes, StringEncoding::from(enc))).map_err(|e| DeserializeFailure::InvalidStructure(Box::new(e)).into()))?; - required_signers_arr.push(required_signers_elem); - required_signers_elem_encodings.push(required_signers_elem_encoding); - } - Ok((required_signers_arr, required_signers_encoding, required_signers_elem_encodings)) + RequiredSigners::deserialize(raw) })().map_err(|e| e.annotate("required_signers"))?; required_signers = Some(tmp_required_signers); - required_signers_encoding = tmp_required_signers_encoding; - required_signers_elem_encodings = tmp_required_signers_elem_encodings; required_signers_key_encoding = Some(key_enc); orig_deser_order.push(11); }, @@ -2779,7 +2627,7 @@ impl Deserialize for TransactionBody { } let (tmp_total_collateral, tmp_total_collateral_encoding) = (|| -> Result<_, DeserializeError> { read_len.read_elems(1)?; - raw.unsigned_integer_sz().map(|(x, enc)| (x, Some(enc))).map_err(Into::::into) + raw.unsigned_integer_sz().map_err(Into::::into).map(|(x, enc)| (x, Some(enc))) })().map_err(|e| e.annotate("total_collateral"))?; total_collateral = Some(tmp_total_collateral); total_collateral_encoding = tmp_total_collateral_encoding; @@ -2790,22 +2638,11 @@ impl Deserialize for TransactionBody { if reference_inputs.is_some() { return Err(DeserializeFailure::DuplicateKey(Key::Uint(18)).into()); } - let (tmp_reference_inputs, tmp_reference_inputs_encoding) = (|| -> Result<_, DeserializeError> { + let tmp_reference_inputs = (|| -> Result<_, DeserializeError> { read_len.read_elems(1)?; - let mut reference_inputs_arr = Vec::new(); - let len = raw.array_sz()?; - let reference_inputs_encoding = len.into(); - while match len { cbor_event::LenSz::Len(n, _) => (reference_inputs_arr.len() as u64) < n, cbor_event::LenSz::Indefinite => true, } { - if raw.cbor_type()? == cbor_event::Type::Special { - assert_eq!(raw.special()?, cbor_event::Special::Break); - break; - } - reference_inputs_arr.push(TransactionInput::deserialize(raw)?); - } - Ok((reference_inputs_arr, reference_inputs_encoding)) + NonemptySetTransactionInput::deserialize(raw) })().map_err(|e| e.annotate("reference_inputs"))?; reference_inputs = Some(tmp_reference_inputs); - reference_inputs_encoding = tmp_reference_inputs_encoding; reference_inputs_key_encoding = Some(key_enc); orig_deser_order.push(15); }, @@ -2857,22 +2694,11 @@ impl Deserialize for TransactionBody { if proposal_procedures.is_some() { return Err(DeserializeFailure::DuplicateKey(Key::Uint(20)).into()); } - let (tmp_proposal_procedures, tmp_proposal_procedures_encoding) = (|| -> Result<_, DeserializeError> { + let tmp_proposal_procedures = (|| -> Result<_, DeserializeError> { read_len.read_elems(1)?; - let mut proposal_procedures_arr = Vec::new(); - let len = raw.array_sz()?; - let proposal_procedures_encoding = len.into(); - while match len { cbor_event::LenSz::Len(n, _) => (proposal_procedures_arr.len() as u64) < n, cbor_event::LenSz::Indefinite => true, } { - if raw.cbor_type()? == cbor_event::Type::Special { - assert_eq!(raw.special()?, cbor_event::Special::Break); - break; - } - proposal_procedures_arr.push(ProposalProcedure::deserialize(raw)?); - } - Ok((proposal_procedures_arr, proposal_procedures_encoding)) + NonemptySetProposalProcedure::deserialize(raw) })().map_err(|e| e.annotate("proposal_procedures"))?; proposal_procedures = Some(tmp_proposal_procedures); - proposal_procedures_encoding = tmp_proposal_procedures_encoding; proposal_procedures_key_encoding = Some(key_enc); orig_deser_order.push(17); }, @@ -2882,7 +2708,7 @@ impl Deserialize for TransactionBody { } let (tmp_current_treasury_value, tmp_current_treasury_value_encoding) = (|| -> Result<_, DeserializeError> { read_len.read_elems(1)?; - raw.unsigned_integer_sz().map(|(x, enc)| (x, Some(enc))).map_err(Into::::into) + raw.unsigned_integer_sz().map_err(Into::::into).map(|(x, enc)| (x, Some(enc))) })().map_err(|e| e.annotate("current_treasury_value"))?; current_treasury_value = Some(tmp_current_treasury_value); current_treasury_value_encoding = tmp_current_treasury_value_encoding; @@ -2895,7 +2721,7 @@ impl Deserialize for TransactionBody { } let (tmp_donation, tmp_donation_encoding) = (|| -> Result<_, DeserializeError> { read_len.read_elems(1)?; - raw.unsigned_integer_sz().map(|(x, enc)| (x, Some(enc))).map_err(Into::::into) + raw.unsigned_integer_sz().map_err(Into::::into).map(|(x, enc)| (x, Some(enc))) })().map_err(|e| e.annotate("donation"))?; donation = Some(tmp_donation); donation_encoding = tmp_donation_encoding; @@ -2955,7 +2781,6 @@ impl Deserialize for TransactionBody { len_encoding, orig_deser_order, inputs_key_encoding, - inputs_encoding, outputs_key_encoding, outputs_encoding, fee_key_encoding, @@ -2963,7 +2788,6 @@ impl Deserialize for TransactionBody { ttl_key_encoding, ttl_encoding, certs_key_encoding, - certs_encoding, withdrawals_key_encoding, withdrawals_encoding, withdrawals_value_encodings, @@ -2978,21 +2802,16 @@ impl Deserialize for TransactionBody { script_data_hash_key_encoding, script_data_hash_encoding, collateral_inputs_key_encoding, - collateral_inputs_encoding, required_signers_key_encoding, - required_signers_encoding, - required_signers_elem_encodings, network_id_key_encoding, collateral_return_key_encoding, total_collateral_key_encoding, total_collateral_encoding, reference_inputs_key_encoding, - reference_inputs_encoding, voting_procedures_key_encoding, voting_procedures_encoding, voting_procedures_value_encodings, proposal_procedures_key_encoding, - proposal_procedures_encoding, current_treasury_value_key_encoding, current_treasury_value_encoding, donation_key_encoding, @@ -3065,8 +2884,8 @@ impl Deserialize for TransactionInput { .map_err(|e: DeserializeError| e.annotate("transaction_id"))?; let (index, index_encoding) = raw .unsigned_integer_sz() - .map(|(x, enc)| (x, Some(enc))) .map_err(Into::::into) + .map(|(x, enc)| (x, Some(enc))) .map_err(|e: DeserializeError| e.annotate("index"))?; match len { cbor_event::LenSz::Len(_, _) => (), @@ -3215,21 +3034,7 @@ impl Serialize for TransactionWitnessSet { force_canonical, ), )?; - serializer.write_array_sz( - self.encodings - .as_ref() - .map(|encs| encs.vkeywitnesses_encoding) - .unwrap_or_default() - .to_len_sz(field.len() as u64, force_canonical), - )?; - for element in field.iter() { - element.serialize(serializer, force_canonical)?; - } - self.encodings - .as_ref() - .map(|encs| encs.vkeywitnesses_encoding) - .unwrap_or_default() - .end(serializer, force_canonical)?; + field.serialize(serializer, force_canonical)?; } } 1 => { @@ -3245,21 +3050,7 @@ impl Serialize for TransactionWitnessSet { force_canonical, ), )?; - serializer.write_array_sz( - self.encodings - .as_ref() - .map(|encs| encs.native_scripts_encoding) - .unwrap_or_default() - .to_len_sz(field.len() as u64, force_canonical), - )?; - for element in field.iter() { - element.serialize(serializer, force_canonical)?; - } - self.encodings - .as_ref() - .map(|encs| encs.native_scripts_encoding) - .unwrap_or_default() - .end(serializer, force_canonical)?; + field.serialize(serializer, force_canonical)?; } } 2 => { @@ -3275,21 +3066,7 @@ impl Serialize for TransactionWitnessSet { force_canonical, ), )?; - serializer.write_array_sz( - self.encodings - .as_ref() - .map(|encs| encs.bootstrap_witnesses_encoding) - .unwrap_or_default() - .to_len_sz(field.len() as u64, force_canonical), - )?; - for element in field.iter() { - element.serialize(serializer, force_canonical)?; - } - self.encodings - .as_ref() - .map(|encs| encs.bootstrap_witnesses_encoding) - .unwrap_or_default() - .end(serializer, force_canonical)?; + field.serialize(serializer, force_canonical)?; } } 3 => { @@ -3305,21 +3082,7 @@ impl Serialize for TransactionWitnessSet { force_canonical, ), )?; - serializer.write_array_sz( - self.encodings - .as_ref() - .map(|encs| encs.plutus_v1_scripts_encoding) - .unwrap_or_default() - .to_len_sz(field.len() as u64, force_canonical), - )?; - for element in field.iter() { - element.serialize(serializer, force_canonical)?; - } - self.encodings - .as_ref() - .map(|encs| encs.plutus_v1_scripts_encoding) - .unwrap_or_default() - .end(serializer, force_canonical)?; + field.serialize(serializer, force_canonical)?; } } 4 => { @@ -3335,21 +3098,7 @@ impl Serialize for TransactionWitnessSet { force_canonical, ), )?; - serializer.write_array_sz( - self.encodings - .as_ref() - .map(|encs| encs.plutus_datums_encoding) - .unwrap_or_default() - .to_len_sz(field.len() as u64, force_canonical), - )?; - for element in field.iter() { - element.serialize(serializer, force_canonical)?; - } - self.encodings - .as_ref() - .map(|encs| encs.plutus_datums_encoding) - .unwrap_or_default() - .end(serializer, force_canonical)?; + field.serialize(serializer, force_canonical)?; } } 5 => { @@ -3365,21 +3114,7 @@ impl Serialize for TransactionWitnessSet { force_canonical, ), )?; - serializer.write_array_sz( - self.encodings - .as_ref() - .map(|encs| encs.redeemers_encoding) - .unwrap_or_default() - .to_len_sz(field.len() as u64, force_canonical), - )?; - for element in field.iter() { - element.serialize(serializer, force_canonical)?; - } - self.encodings - .as_ref() - .map(|encs| encs.redeemers_encoding) - .unwrap_or_default() - .end(serializer, force_canonical)?; + field.serialize(serializer, force_canonical)?; } } 6 => { @@ -3395,21 +3130,7 @@ impl Serialize for TransactionWitnessSet { force_canonical, ), )?; - serializer.write_array_sz( - self.encodings - .as_ref() - .map(|encs| encs.plutus_v2_scripts_encoding) - .unwrap_or_default() - .to_len_sz(field.len() as u64, force_canonical), - )?; - for element in field.iter() { - element.serialize(serializer, force_canonical)?; - } - self.encodings - .as_ref() - .map(|encs| encs.plutus_v2_scripts_encoding) - .unwrap_or_default() - .end(serializer, force_canonical)?; + field.serialize(serializer, force_canonical)?; } } 7 => { @@ -3425,21 +3146,7 @@ impl Serialize for TransactionWitnessSet { force_canonical, ), )?; - serializer.write_array_sz( - self.encodings - .as_ref() - .map(|encs| encs.plutus_v3_scripts_encoding) - .unwrap_or_default() - .to_len_sz(field.len() as u64, force_canonical), - )?; - for element in field.iter() { - element.serialize(serializer, force_canonical)?; - } - self.encodings - .as_ref() - .map(|encs| encs.plutus_v3_scripts_encoding) - .unwrap_or_default() - .end(serializer, force_canonical)?; + field.serialize(serializer, force_canonical)?; } } _ => unreachable!(), @@ -3460,28 +3167,20 @@ impl Deserialize for TransactionWitnessSet { let mut read_len = CBORReadLen::new(len); (|| -> Result<_, DeserializeError> { let mut orig_deser_order = Vec::new(); - let mut vkeywitnesses_encoding = LenEncoding::default(); let mut vkeywitnesses_key_encoding = None; let mut vkeywitnesses = None; - let mut native_scripts_encoding = LenEncoding::default(); let mut native_scripts_key_encoding = None; let mut native_scripts = None; - let mut bootstrap_witnesses_encoding = LenEncoding::default(); let mut bootstrap_witnesses_key_encoding = None; let mut bootstrap_witnesses = None; - let mut plutus_v1_scripts_encoding = LenEncoding::default(); let mut plutus_v1_scripts_key_encoding = None; let mut plutus_v1_scripts = None; - let mut plutus_datums_encoding = LenEncoding::default(); let mut plutus_datums_key_encoding = None; let mut plutus_datums = None; - let mut redeemers_encoding = LenEncoding::default(); let mut redeemers_key_encoding = None; let mut redeemers = None; - let mut plutus_v2_scripts_encoding = LenEncoding::default(); let mut plutus_v2_scripts_key_encoding = None; let mut plutus_v2_scripts = None; - let mut plutus_v3_scripts_encoding = LenEncoding::default(); let mut plutus_v3_scripts_key_encoding = None; let mut plutus_v3_scripts = None; let mut read = 0; @@ -3495,29 +3194,12 @@ impl Deserialize for TransactionWitnessSet { if vkeywitnesses.is_some() { return Err(DeserializeFailure::DuplicateKey(Key::Uint(0)).into()); } - let (tmp_vkeywitnesses, tmp_vkeywitnesses_encoding) = - (|| -> Result<_, DeserializeError> { - read_len.read_elems(1)?; - let mut vkeywitnesses_arr = Vec::new(); - let len = raw.array_sz()?; - let vkeywitnesses_encoding = len.into(); - while match len { - cbor_event::LenSz::Len(n, _) => { - (vkeywitnesses_arr.len() as u64) < n - } - cbor_event::LenSz::Indefinite => true, - } { - if raw.cbor_type()? == cbor_event::Type::Special { - assert_eq!(raw.special()?, cbor_event::Special::Break); - break; - } - vkeywitnesses_arr.push(Vkeywitness::deserialize(raw)?); - } - Ok((vkeywitnesses_arr, vkeywitnesses_encoding)) - })() - .map_err(|e| e.annotate("vkeywitnesses"))?; + let tmp_vkeywitnesses = (|| -> Result<_, DeserializeError> { + read_len.read_elems(1)?; + NonemptySetVkeywitness::deserialize(raw) + })() + .map_err(|e| e.annotate("vkeywitnesses"))?; vkeywitnesses = Some(tmp_vkeywitnesses); - vkeywitnesses_encoding = tmp_vkeywitnesses_encoding; vkeywitnesses_key_encoding = Some(key_enc); orig_deser_order.push(0); } @@ -3525,29 +3207,12 @@ impl Deserialize for TransactionWitnessSet { if native_scripts.is_some() { return Err(DeserializeFailure::DuplicateKey(Key::Uint(1)).into()); } - let (tmp_native_scripts, tmp_native_scripts_encoding) = - (|| -> Result<_, DeserializeError> { - read_len.read_elems(1)?; - let mut native_scripts_arr = Vec::new(); - let len = raw.array_sz()?; - let native_scripts_encoding = len.into(); - while match len { - cbor_event::LenSz::Len(n, _) => { - (native_scripts_arr.len() as u64) < n - } - cbor_event::LenSz::Indefinite => true, - } { - if raw.cbor_type()? == cbor_event::Type::Special { - assert_eq!(raw.special()?, cbor_event::Special::Break); - break; - } - native_scripts_arr.push(NativeScript::deserialize(raw)?); - } - Ok((native_scripts_arr, native_scripts_encoding)) - })() - .map_err(|e| e.annotate("native_scripts"))?; + let tmp_native_scripts = (|| -> Result<_, DeserializeError> { + read_len.read_elems(1)?; + NonemptySetNativeScript::deserialize(raw) + })() + .map_err(|e| e.annotate("native_scripts"))?; native_scripts = Some(tmp_native_scripts); - native_scripts_encoding = tmp_native_scripts_encoding; native_scripts_key_encoding = Some(key_enc); orig_deser_order.push(1); } @@ -3555,30 +3220,12 @@ impl Deserialize for TransactionWitnessSet { if bootstrap_witnesses.is_some() { return Err(DeserializeFailure::DuplicateKey(Key::Uint(2)).into()); } - let (tmp_bootstrap_witnesses, tmp_bootstrap_witnesses_encoding) = - (|| -> Result<_, DeserializeError> { - read_len.read_elems(1)?; - let mut bootstrap_witnesses_arr = Vec::new(); - let len = raw.array_sz()?; - let bootstrap_witnesses_encoding = len.into(); - while match len { - cbor_event::LenSz::Len(n, _) => { - (bootstrap_witnesses_arr.len() as u64) < n - } - cbor_event::LenSz::Indefinite => true, - } { - if raw.cbor_type()? == cbor_event::Type::Special { - assert_eq!(raw.special()?, cbor_event::Special::Break); - break; - } - bootstrap_witnesses_arr - .push(BootstrapWitness::deserialize(raw)?); - } - Ok((bootstrap_witnesses_arr, bootstrap_witnesses_encoding)) - })() - .map_err(|e| e.annotate("bootstrap_witnesses"))?; + let tmp_bootstrap_witnesses = (|| -> Result<_, DeserializeError> { + read_len.read_elems(1)?; + NonemptySetBootstrapWitness::deserialize(raw) + })() + .map_err(|e| e.annotate("bootstrap_witnesses"))?; bootstrap_witnesses = Some(tmp_bootstrap_witnesses); - bootstrap_witnesses_encoding = tmp_bootstrap_witnesses_encoding; bootstrap_witnesses_key_encoding = Some(key_enc); orig_deser_order.push(2); } @@ -3586,30 +3233,12 @@ impl Deserialize for TransactionWitnessSet { if plutus_v1_scripts.is_some() { return Err(DeserializeFailure::DuplicateKey(Key::Uint(3)).into()); } - let (tmp_plutus_v1_scripts, tmp_plutus_v1_scripts_encoding) = - (|| -> Result<_, DeserializeError> { - read_len.read_elems(1)?; - let mut plutus_v1_scripts_arr = Vec::new(); - let len = raw.array_sz()?; - let plutus_v1_scripts_encoding = len.into(); - while match len { - cbor_event::LenSz::Len(n, _) => { - (plutus_v1_scripts_arr.len() as u64) < n - } - cbor_event::LenSz::Indefinite => true, - } { - if raw.cbor_type()? == cbor_event::Type::Special { - assert_eq!(raw.special()?, cbor_event::Special::Break); - break; - } - plutus_v1_scripts_arr - .push(PlutusV1Script::deserialize(raw)?); - } - Ok((plutus_v1_scripts_arr, plutus_v1_scripts_encoding)) - })() - .map_err(|e| e.annotate("plutus_v1_scripts"))?; + let tmp_plutus_v1_scripts = (|| -> Result<_, DeserializeError> { + read_len.read_elems(1)?; + NonemptySetPlutusV1Script::deserialize(raw) + })() + .map_err(|e| e.annotate("plutus_v1_scripts"))?; plutus_v1_scripts = Some(tmp_plutus_v1_scripts); - plutus_v1_scripts_encoding = tmp_plutus_v1_scripts_encoding; plutus_v1_scripts_key_encoding = Some(key_enc); orig_deser_order.push(3); } @@ -3617,29 +3246,12 @@ impl Deserialize for TransactionWitnessSet { if plutus_datums.is_some() { return Err(DeserializeFailure::DuplicateKey(Key::Uint(4)).into()); } - let (tmp_plutus_datums, tmp_plutus_datums_encoding) = - (|| -> Result<_, DeserializeError> { - read_len.read_elems(1)?; - let mut plutus_datums_arr = Vec::new(); - let len = raw.array_sz()?; - let plutus_datums_encoding = len.into(); - while match len { - cbor_event::LenSz::Len(n, _) => { - (plutus_datums_arr.len() as u64) < n - } - cbor_event::LenSz::Indefinite => true, - } { - if raw.cbor_type()? == cbor_event::Type::Special { - assert_eq!(raw.special()?, cbor_event::Special::Break); - break; - } - plutus_datums_arr.push(PlutusData::deserialize(raw)?); - } - Ok((plutus_datums_arr, plutus_datums_encoding)) - })() - .map_err(|e| e.annotate("plutus_datums"))?; + let tmp_plutus_datums = (|| -> Result<_, DeserializeError> { + read_len.read_elems(1)?; + NonemptySetPlutusData::deserialize(raw) + })() + .map_err(|e| e.annotate("plutus_datums"))?; plutus_datums = Some(tmp_plutus_datums); - plutus_datums_encoding = tmp_plutus_datums_encoding; plutus_datums_key_encoding = Some(key_enc); orig_deser_order.push(4); } @@ -3647,29 +3259,12 @@ impl Deserialize for TransactionWitnessSet { if redeemers.is_some() { return Err(DeserializeFailure::DuplicateKey(Key::Uint(5)).into()); } - let (tmp_redeemers, tmp_redeemers_encoding) = - (|| -> Result<_, DeserializeError> { - read_len.read_elems(1)?; - let mut redeemers_arr = Vec::new(); - let len = raw.array_sz()?; - let redeemers_encoding = len.into(); - while match len { - cbor_event::LenSz::Len(n, _) => { - (redeemers_arr.len() as u64) < n - } - cbor_event::LenSz::Indefinite => true, - } { - if raw.cbor_type()? == cbor_event::Type::Special { - assert_eq!(raw.special()?, cbor_event::Special::Break); - break; - } - redeemers_arr.push(Redeemer::deserialize(raw)?); - } - Ok((redeemers_arr, redeemers_encoding)) - })() - .map_err(|e| e.annotate("redeemers"))?; + let tmp_redeemers = (|| -> Result<_, DeserializeError> { + read_len.read_elems(1)?; + Redeemers::deserialize(raw) + })() + .map_err(|e| e.annotate("redeemers"))?; redeemers = Some(tmp_redeemers); - redeemers_encoding = tmp_redeemers_encoding; redeemers_key_encoding = Some(key_enc); orig_deser_order.push(5); } @@ -3677,30 +3272,12 @@ impl Deserialize for TransactionWitnessSet { if plutus_v2_scripts.is_some() { return Err(DeserializeFailure::DuplicateKey(Key::Uint(6)).into()); } - let (tmp_plutus_v2_scripts, tmp_plutus_v2_scripts_encoding) = - (|| -> Result<_, DeserializeError> { - read_len.read_elems(1)?; - let mut plutus_v2_scripts_arr = Vec::new(); - let len = raw.array_sz()?; - let plutus_v2_scripts_encoding = len.into(); - while match len { - cbor_event::LenSz::Len(n, _) => { - (plutus_v2_scripts_arr.len() as u64) < n - } - cbor_event::LenSz::Indefinite => true, - } { - if raw.cbor_type()? == cbor_event::Type::Special { - assert_eq!(raw.special()?, cbor_event::Special::Break); - break; - } - plutus_v2_scripts_arr - .push(PlutusV2Script::deserialize(raw)?); - } - Ok((plutus_v2_scripts_arr, plutus_v2_scripts_encoding)) - })() - .map_err(|e| e.annotate("plutus_v2_scripts"))?; + let tmp_plutus_v2_scripts = (|| -> Result<_, DeserializeError> { + read_len.read_elems(1)?; + NonemptySetPlutusV2Script::deserialize(raw) + })() + .map_err(|e| e.annotate("plutus_v2_scripts"))?; plutus_v2_scripts = Some(tmp_plutus_v2_scripts); - plutus_v2_scripts_encoding = tmp_plutus_v2_scripts_encoding; plutus_v2_scripts_key_encoding = Some(key_enc); orig_deser_order.push(6); } @@ -3708,30 +3285,12 @@ impl Deserialize for TransactionWitnessSet { if plutus_v3_scripts.is_some() { return Err(DeserializeFailure::DuplicateKey(Key::Uint(7)).into()); } - let (tmp_plutus_v3_scripts, tmp_plutus_v3_scripts_encoding) = - (|| -> Result<_, DeserializeError> { - read_len.read_elems(1)?; - let mut plutus_v3_scripts_arr = Vec::new(); - let len = raw.array_sz()?; - let plutus_v3_scripts_encoding = len.into(); - while match len { - cbor_event::LenSz::Len(n, _) => { - (plutus_v3_scripts_arr.len() as u64) < n - } - cbor_event::LenSz::Indefinite => true, - } { - if raw.cbor_type()? == cbor_event::Type::Special { - assert_eq!(raw.special()?, cbor_event::Special::Break); - break; - } - plutus_v3_scripts_arr - .push(PlutusV3Script::deserialize(raw)?); - } - Ok((plutus_v3_scripts_arr, plutus_v3_scripts_encoding)) - })() - .map_err(|e| e.annotate("plutus_v3_scripts"))?; + let tmp_plutus_v3_scripts = (|| -> Result<_, DeserializeError> { + read_len.read_elems(1)?; + NonemptySetPlutusV3Script::deserialize(raw) + })() + .map_err(|e| e.annotate("plutus_v3_scripts"))?; plutus_v3_scripts = Some(tmp_plutus_v3_scripts); - plutus_v3_scripts_encoding = tmp_plutus_v3_scripts_encoding; plutus_v3_scripts_key_encoding = Some(key_enc); orig_deser_order.push(7); } @@ -3773,21 +3332,13 @@ impl Deserialize for TransactionWitnessSet { len_encoding, orig_deser_order, vkeywitnesses_key_encoding, - vkeywitnesses_encoding, native_scripts_key_encoding, - native_scripts_encoding, bootstrap_witnesses_key_encoding, - bootstrap_witnesses_encoding, plutus_v1_scripts_key_encoding, - plutus_v1_scripts_encoding, plutus_datums_key_encoding, - plutus_datums_encoding, redeemers_key_encoding, - redeemers_encoding, plutus_v2_scripts_key_encoding, - plutus_v2_scripts_encoding, plutus_v3_scripts_key_encoding, - plutus_v3_scripts_encoding, }), }) })() diff --git a/chain/rust/src/transaction/utils.rs b/chain/rust/src/transaction/utils.rs index 5d302de4..f0642cdf 100644 --- a/chain/rust/src/transaction/utils.rs +++ b/chain/rust/src/transaction/utils.rs @@ -145,49 +145,49 @@ impl TransactionWitnessSet { // TODO: should we do duplicate checking here? if let Some(other_vkeys) = other.vkeywitnesses { if let Some(vkeys) = &mut self.vkeywitnesses { - vkeys.extend(other_vkeys); + vkeys.extend(Vec::from(other_vkeys)); } else { self.vkeywitnesses = Some(other_vkeys); } } if let Some(other_native_scripts) = other.native_scripts { if let Some(scripts) = &mut self.native_scripts { - scripts.extend(other_native_scripts); + scripts.extend(Vec::from(other_native_scripts)); } else { self.native_scripts = Some(other_native_scripts); } } if let Some(other_bootstraps) = other.bootstrap_witnesses { if let Some(bootstraps) = &mut self.bootstrap_witnesses { - bootstraps.extend(other_bootstraps); + bootstraps.extend(Vec::from(other_bootstraps)); } else { self.bootstrap_witnesses = Some(other_bootstraps); } } if let Some(other_plutus_v1_scripts) = other.plutus_v1_scripts { if let Some(scripts) = &mut self.plutus_v1_scripts { - scripts.extend(other_plutus_v1_scripts); + scripts.extend(Vec::from(other_plutus_v1_scripts)); } else { self.plutus_v1_scripts = Some(other_plutus_v1_scripts); } } if let Some(other_plutus_v2_scripts) = other.plutus_v2_scripts { if let Some(scripts) = &mut self.plutus_v2_scripts { - scripts.extend(other_plutus_v2_scripts); + scripts.extend(Vec::from(other_plutus_v2_scripts)); } else { self.plutus_v2_scripts = Some(other_plutus_v2_scripts); } } if let Some(other_plutus_v3_scripts) = other.plutus_v3_scripts { if let Some(scripts) = &mut self.plutus_v3_scripts { - scripts.extend(other_plutus_v3_scripts); + scripts.extend(Vec::from(other_plutus_v3_scripts)); } else { self.plutus_v3_scripts = Some(other_plutus_v3_scripts); } } if let Some(other_plutus_datums) = other.plutus_datums { if let Some(datums) = &mut self.plutus_datums { - datums.extend(other_plutus_datums); + datums.extend(Vec::from(other_plutus_datums)); } else { self.plutus_datums = Some(other_plutus_datums); } diff --git a/chain/rust/src/utils.rs b/chain/rust/src/utils.rs index bd20c90d..085fba47 100644 --- a/chain/rust/src/utils.rs +++ b/chain/rust/src/utils.rs @@ -1,10 +1,10 @@ -use cbor_event::{de::Deserializer, se::Serializer}; +use cbor_event::{de::Deserializer, se::Serializer, Sz}; use cml_core::{ error::{DeserializeError, DeserializeFailure}, - serialization::{fit_sz, sz_max, Deserialize, Serialize}, + serialization::{fit_sz, sz_max, Deserialize, LenEncoding, Serialize}, Int, }; -use cml_crypto::ScriptHash; +use cml_crypto::{RawBytesEncoding, ScriptHash}; use derivative::Derivative; use std::io::{BufRead, Seek, Write}; @@ -569,6 +569,295 @@ impl Deserialize for NetworkId { } } +// Represents the cddl: #6.258([+ T]) / [* T] +// it DOES NOT and CAN NOT have any encoding detials per element! +// so you can NOT use it on any primitives so must be serializable directly +#[derive(Debug, Clone)] +pub struct NonemptySet { + elems: Vec, + len_encoding: LenEncoding, + // also controls whether to use the tag encoding (Some) or raw array (None) + tag_encoding: Option, +} + +impl serde::Serialize for NonemptySet { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + self.elems.serialize(serializer) + } +} + +impl<'de, T: serde::de::Deserialize<'de>> serde::de::Deserialize<'de> for NonemptySet { + fn deserialize(deserializer: D) -> Result + where + D: serde::de::Deserializer<'de>, + { + Vec::deserialize(deserializer) + .map(|elems| Self { + elems, + len_encoding: LenEncoding::default(), + tag_encoding: None, + }) + } +} + +impl schemars::JsonSchema for NonemptySet { + fn schema_name() -> String { + Vec::::schema_name() + } + fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema { + Vec::::json_schema(gen) + } + fn is_referenceable() -> bool { + Vec::::is_referenceable() + } +} + +impl AsRef<[T]> for NonemptySet { + fn as_ref(&self) -> &[T] { + self.elems.as_ref() + } +} + +impl std::ops::Deref for NonemptySet { + type Target = Vec; + + fn deref(&self) -> &Self::Target { + &self.elems + } +} + +impl std::ops::DerefMut for NonemptySet { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.elems + } +} + +impl From> for NonemptySet { + fn from(elems: Vec) -> Self { + Self { + elems, + len_encoding: LenEncoding::default(), + tag_encoding: None, + } + } +} + +impl From> for Vec { + fn from(set: NonemptySet) -> Self { + set.elems + } +} + +impl Serialize for NonemptySet { + fn serialize<'se, W: Write>( + &self, + serializer: &'se mut Serializer, + force_canonical: bool, + ) -> cbor_event::Result<&'se mut Serializer> { + if let Some(tag_encoding) = &self.tag_encoding { + serializer.write_tag_sz(258, *tag_encoding)?; + } + serializer.write_array_sz( + self.len_encoding + .to_len_sz(self.elems.len() as u64, force_canonical), + )?; + for elem in self.elems.iter() { + elem.serialize(serializer, force_canonical)?; + } + self.len_encoding.end(serializer, force_canonical) + } +} + +impl Deserialize for NonemptySet { + fn deserialize(raw: &mut Deserializer) -> Result { + (|| -> Result<_, DeserializeError> { + let mut elems = Vec::new(); + let (arr_len, tag_encoding) = if raw.cbor_type()? == cbor_event::Type::Tag { + let (tag, tag_encoding) = raw.tag_sz()?; + if tag != 258 { + return Err(DeserializeFailure::TagMismatch { found: tag, expected: 258 }.into()); + } + (raw.array_sz()?, Some(tag_encoding)) + } else { + (raw.array_sz()?, None) + }; + let len_encoding = arr_len.into(); + while match arr_len { + cbor_event::LenSz::Len(n, _) => (elems.len() as u64) < n, + cbor_event::LenSz::Indefinite => true, + } { + if raw.cbor_type()? == cbor_event::Type::Special { + assert_eq!(raw.special()?, cbor_event::Special::Break); + break; + } + let elem = T::deserialize(raw)?; + elems.push(elem); + } + Ok(Self { + elems, + len_encoding, + tag_encoding, + }) + })() + .map_err(|e| e.annotate("NonemptySet")) + } +} + +// for now just do this +pub type Set = NonemptySet; + +// Represents the cddl: #6.258([+ T]) / [* T] where T uses RawBytesEncoding +#[derive(Debug, Clone)] +pub struct NonemptySetRawBytes { + elems: Vec, + len_encoding: LenEncoding, + // also controls whether to use the tag encoding (Some) or raw array (None) + tag_encoding: Option, + bytes_encodings: Vec, +} + +impl serde::Serialize for NonemptySetRawBytes { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + self.elems.serialize(serializer) + } +} + +impl<'de, T: serde::de::Deserialize<'de>> serde::de::Deserialize<'de> for NonemptySetRawBytes { + fn deserialize(deserializer: D) -> Result + where + D: serde::de::Deserializer<'de>, + { + Vec::deserialize(deserializer) + .map(|elems| Self { + elems, + len_encoding: LenEncoding::default(), + tag_encoding: None, + bytes_encodings: Vec::new(), + }) + } +} + +impl schemars::JsonSchema for NonemptySetRawBytes { + fn schema_name() -> String { + Vec::::schema_name() + } + fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema { + Vec::::json_schema(gen) + } + fn is_referenceable() -> bool { + Vec::::is_referenceable() + } +} + +impl AsRef<[T]> for NonemptySetRawBytes { + fn as_ref(&self) -> &[T] { + self.elems.as_ref() + } +} + +impl std::ops::Deref for NonemptySetRawBytes { + type Target = Vec; + + fn deref(&self) -> &Self::Target { + &self.elems + } +} + +impl std::ops::DerefMut for NonemptySetRawBytes { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.elems + } +} + +impl From> for NonemptySetRawBytes { + fn from(elems: Vec) -> Self { + Self { + elems, + len_encoding: LenEncoding::default(), + tag_encoding: None, + bytes_encodings: Vec::new(), + } + } +} + +impl From> for Vec { + fn from(set: NonemptySetRawBytes) -> Self { + set.elems + } +} + +impl Serialize for NonemptySetRawBytes { + fn serialize<'se, W: Write>( + &self, + serializer: &'se mut Serializer, + force_canonical: bool, + ) -> cbor_event::Result<&'se mut Serializer> { + if let Some(tag_encoding) = &self.tag_encoding { + serializer.write_tag_sz(258, *tag_encoding)?; + } + serializer.write_array_sz( + self.len_encoding + .to_len_sz(self.elems.len() as u64, force_canonical), + )?; + for (i, elem) in self.elems.iter().enumerate() { + serializer.write_bytes_sz( + elem.to_raw_bytes(), + self.bytes_encodings.get(i) + .cloned() + .unwrap_or_default() + .to_str_len_sz(elem.to_raw_bytes().len() as u64, force_canonical), + )?; + } + self.len_encoding.end(serializer, force_canonical) + } +} + +impl Deserialize for NonemptySetRawBytes { + fn deserialize(raw: &mut Deserializer) -> Result { + (|| -> Result<_, DeserializeError> { + let mut elems = Vec::new(); + let mut bytes_encodings = Vec::new(); + let (arr_len, tag_encoding) = if raw.cbor_type()? == cbor_event::Type::Tag { + let (tag, tag_encoding) = raw.tag_sz()?; + if tag != 258 { + return Err(DeserializeFailure::TagMismatch { found: tag, expected: 258 }.into()); + } + (raw.array_sz()?, Some(tag_encoding)) + } else { + (raw.array_sz()?, None) + }; + let len_encoding = arr_len.into(); + while match arr_len { + cbor_event::LenSz::Len(n, _) => (elems.len() as u64) < n, + cbor_event::LenSz::Indefinite => true, + } { + if raw.cbor_type()? == cbor_event::Type::Special { + assert_eq!(raw.special()?, cbor_event::Special::Break); + break; + } + let (bytes, bytes_enc) = raw.bytes_sz()?; + let elem = T::from_raw_bytes(&bytes) + .map_err(|e| DeserializeFailure::InvalidStructure(Box::new(e)))?; + elems.push(elem); + bytes_encodings.push(bytes_enc.into()); + } + Ok(Self { + elems, + len_encoding, + tag_encoding, + bytes_encodings, + }) + })() + .map_err(|e| e.annotate("NonemptySetRawBytes")) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/chain/wasm/src/builders/certificate_builder.rs b/chain/wasm/src/builders/certificate_builder.rs index 6e2a8620..f97ac93d 100644 --- a/chain/wasm/src/builders/certificate_builder.rs +++ b/chain/wasm/src/builders/certificate_builder.rs @@ -5,7 +5,7 @@ use wasm_bindgen::prelude::{wasm_bindgen, JsError}; use super::witness_builder::NativeScriptWitnessInfo; -use crate::{certs::Certificate, transaction::RequiredSigners}; +use crate::{certs::Certificate, RequiredSigners}; #[wasm_bindgen] #[derive(Clone)] diff --git a/chain/wasm/src/builders/input_builder.rs b/chain/wasm/src/builders/input_builder.rs index 9c1a0e6a..0e5901de 100644 --- a/chain/wasm/src/builders/input_builder.rs +++ b/chain/wasm/src/builders/input_builder.rs @@ -4,8 +4,8 @@ use crate::builders::{ }; use crate::{ plutus::PlutusData, - transaction::{RequiredSigners, TransactionInput, TransactionOutput}, - NativeScript, + transaction::{TransactionInput, TransactionOutput}, + NativeScript, RequiredSigners, }; use cml_core_wasm::impl_wasm_conversions; use wasm_bindgen::prelude::{wasm_bindgen, JsError}; diff --git a/chain/wasm/src/builders/mint_builder.rs b/chain/wasm/src/builders/mint_builder.rs index 287030a8..c357f032 100644 --- a/chain/wasm/src/builders/mint_builder.rs +++ b/chain/wasm/src/builders/mint_builder.rs @@ -3,7 +3,7 @@ use crate::builders::witness_builder::{NativeScriptWitnessInfo, PartialPlutusWit use cml_core_wasm::impl_wasm_conversions; use wasm_bindgen::prelude::wasm_bindgen; -use crate::{transaction::RequiredSigners, AssetName, MapAssetNameToNonZeroInt64, NativeScript}; +use crate::{AssetName, MapAssetNameToNonZeroInt64, NativeScript, RequiredSigners}; #[wasm_bindgen] #[derive(Clone)] diff --git a/chain/wasm/src/builders/redeemer_builder.rs b/chain/wasm/src/builders/redeemer_builder.rs index be053a1c..7c6be9b1 100644 --- a/chain/wasm/src/builders/redeemer_builder.rs +++ b/chain/wasm/src/builders/redeemer_builder.rs @@ -2,10 +2,7 @@ use super::{ certificate_builder::CertificateBuilderResult, input_builder::InputBuilderResult, mint_builder::MintBuilderResult, withdrawal_builder::WithdrawalBuilderResult, }; -use crate::{ - plutus::{ExUnits, PlutusData, Redeemer, RedeemerTag}, - RedeemerList, -}; +use crate::plutus::{ExUnits, LegacyRedeemer, PlutusData, RedeemerTag, Redeemers}; use cml_core_wasm::impl_wasm_conversions; use wasm_bindgen::prelude::{wasm_bindgen, JsError}; @@ -24,7 +21,7 @@ impl RedeemerWitnessKey { cml_chain::builders::redeemer_builder::RedeemerWitnessKey::new(tag, index).into() } - pub fn from_redeemer(redeemer: &Redeemer) -> Self { + pub fn from_redeemer(redeemer: &LegacyRedeemer) -> Self { cml_chain::builders::redeemer_builder::RedeemerWitnessKey::from(redeemer.as_ref()).into() } } @@ -95,7 +92,7 @@ impl RedeemerSetBuilder { self.0.add_cert(result.as_ref()); } - pub fn build(&self, default_to_dummy_exunits: bool) -> Result { + pub fn build(&self, default_to_dummy_exunits: bool) -> Result { self.0 .build(default_to_dummy_exunits) .map(Into::into) diff --git a/chain/wasm/src/builders/tx_builder.rs b/chain/wasm/src/builders/tx_builder.rs index 304ba5eb..1d084053 100644 --- a/chain/wasm/src/builders/tx_builder.rs +++ b/chain/wasm/src/builders/tx_builder.rs @@ -15,9 +15,9 @@ use crate::{ }, crypto::{BootstrapWitness, Vkeywitness}, fees::LinearFee, - plutus::{CostModels, ExUnitPrices, ExUnits}, + plutus::{CostModels, ExUnitPrices, ExUnits, Redeemers}, transaction::{Transaction, TransactionBody, TransactionInput, TransactionOutput}, - Coin, NetworkId, RedeemerList, Slot, Value, Withdrawals, + Coin, NetworkId, Slot, Value, Withdrawals, }; #[wasm_bindgen] @@ -385,7 +385,7 @@ impl TxRedeemerBuilder { /// Builds the transaction and moves to the next step where any real witness can be added /// NOTE: is_valid set to true /// Will NOT require you to have set required signers & witnesses - pub fn build(&self) -> Result { + pub fn build(&self) -> Result { self.0.build().map(Into::into).map_err(Into::into) } diff --git a/chain/wasm/src/builders/withdrawal_builder.rs b/chain/wasm/src/builders/withdrawal_builder.rs index 4a88e328..36fa815d 100644 --- a/chain/wasm/src/builders/withdrawal_builder.rs +++ b/chain/wasm/src/builders/withdrawal_builder.rs @@ -5,7 +5,7 @@ use wasm_bindgen::prelude::{wasm_bindgen, JsError}; use super::witness_builder::NativeScriptWitnessInfo; -use crate::{address::RewardAddress, transaction::RequiredSigners}; +use crate::{address::RewardAddress, RequiredSigners}; #[wasm_bindgen] #[derive(Clone)] diff --git a/chain/wasm/src/builders/witness_builder.rs b/chain/wasm/src/builders/witness_builder.rs index 18537be6..38026977 100644 --- a/chain/wasm/src/builders/witness_builder.rs +++ b/chain/wasm/src/builders/witness_builder.rs @@ -2,10 +2,10 @@ use crate::{ address::RewardAddress, byron::ByronAddress, crypto::{BootstrapWitness, Vkeywitness}, - plutus::{utils::PlutusScript, PlutusData, Redeemer}, + plutus::{utils::PlutusScript, LegacyRedeemer, PlutusData}, transaction::TransactionWitnessSet, - Ed25519KeyHashList, NativeScriptList, PlutusDataList, PlutusV1ScriptList, PlutusV2ScriptList, - RedeemerList, Script, + Ed25519KeyHashList, LegacyRedeemerList, NativeScriptList, PlutusDataList, PlutusV1ScriptList, + PlutusV2ScriptList, Script, }; use cml_core_wasm::impl_wasm_conversions; use cml_crypto_wasm::{DatumHash, Ed25519KeyHash, ScriptHash}; @@ -194,11 +194,11 @@ impl TransactionWitnessSetBuilder { self.0.get_plutus_datum().into() } - pub fn add_redeemer(&mut self, redeemer: &Redeemer) { + pub fn add_redeemer(&mut self, redeemer: &LegacyRedeemer) { self.0.add_redeemer(redeemer.clone().into()); } - pub fn get_redeemer(&self) -> RedeemerList { + pub fn get_redeemer(&self) -> LegacyRedeemerList { self.0.get_redeemer().into() } diff --git a/chain/wasm/src/crypto/hash.rs b/chain/wasm/src/crypto/hash.rs index c6b2f365..1ab838a7 100644 --- a/chain/wasm/src/crypto/hash.rs +++ b/chain/wasm/src/crypto/hash.rs @@ -2,14 +2,16 @@ use wasm_bindgen::prelude::{wasm_bindgen, JsError}; use crate::{ auxdata::AuxiliaryData, - plutus::{CostModels, PlutusData}, + plutus::{CostModels, PlutusData, Redeemers}, transaction::{TransactionBody, TransactionWitnessSet}, utils::LanguageList, - PlutusDataList, RedeemerList, + PlutusDataList, }; use cml_crypto_wasm::{AuxiliaryDataHash, DatumHash, ScriptDataHash, TransactionHash}; +use cml_chain::NonemptySet; + #[wasm_bindgen] pub fn hash_auxiliary_data(auxiliary_data: &AuxiliaryData) -> AuxiliaryDataHash { cml_chain::crypto::hash::hash_auxiliary_data(auxiliary_data.as_ref()).into() @@ -37,15 +39,16 @@ pub fn hash_plutus_data(plutus_data: &PlutusData) -> DatumHash { /// please use calc_script_data_hash_from_witness() #[wasm_bindgen] pub fn hash_script_data( - redeemers: &RedeemerList, + redeemers: &Redeemers, cost_models: &CostModels, datums: Option, // encoding: Option, ) -> ScriptDataHash { + let datums = datums.map(|datums| NonemptySet::from(Into::>::into(datums))); cml_chain::crypto::hash::hash_script_data( redeemers.as_ref(), cost_models.as_ref(), - datums.as_ref().map(AsRef::as_ref), + datums.as_ref(), None, ) .into() @@ -63,7 +66,7 @@ pub fn hash_script_data( /// please use calc_script_data_hash_from_witness() #[wasm_bindgen] pub fn calc_script_data_hash( - redeemers: &RedeemerList, + redeemers: &Redeemers, datums: &PlutusDataList, cost_models: &CostModels, used_langs: &LanguageList, @@ -71,7 +74,7 @@ pub fn calc_script_data_hash( ) -> Result, JsError> { cml_chain::crypto::hash::calc_script_data_hash( redeemers.as_ref(), - datums.as_ref(), + &NonemptySet::from(Into::>::into(datums.clone())), cost_models.as_ref(), used_langs.as_ref(), None, diff --git a/chain/wasm/src/governance/mod.rs b/chain/wasm/src/governance/mod.rs index 33adb5d0..34c1e104 100644 --- a/chain/wasm/src/governance/mod.rs +++ b/chain/wasm/src/governance/mod.rs @@ -110,11 +110,13 @@ impl GovAction { pub fn new_parameter_change_action( gov_action_id: Option, protocol_param_update: &ProtocolParamUpdate, + policy_hash: Option, ) -> Self { Self( cml_chain::governance::GovAction::new_parameter_change_action( gov_action_id.map(Into::into), protocol_param_update.clone().into(), + policy_hash.map(Into::into), ), ) } @@ -131,10 +133,14 @@ impl GovAction { ) } - pub fn new_treasury_withdrawals_action(withdrawal: &MapRewardAccountToCoin) -> Self { + pub fn new_treasury_withdrawals_action( + withdrawal: &MapRewardAccountToCoin, + policy_hash: Option, + ) -> Self { Self( cml_chain::governance::GovAction::new_treasury_withdrawals_action( withdrawal.clone().into(), + policy_hash.map(Into::into), ), ) } @@ -413,13 +419,19 @@ impl ParameterChangeAction { self.0.protocol_param_update.clone().into() } + pub fn policy_hash(&self) -> Option { + self.0.policy_hash.map(std::convert::Into::into) + } + pub fn new( gov_action_id: Option, protocol_param_update: &ProtocolParamUpdate, + policy_hash: Option, ) -> Self { Self(cml_chain::governance::ParameterChangeAction::new( gov_action_id.map(Into::into), protocol_param_update.clone().into(), + policy_hash.map(Into::into), )) } } @@ -482,9 +494,14 @@ impl TreasuryWithdrawalsAction { self.0.withdrawal.clone().into() } - pub fn new(withdrawal: &MapRewardAccountToCoin) -> Self { + pub fn policy_hash(&self) -> Option { + self.0.policy_hash.map(std::convert::Into::into) + } + + pub fn new(withdrawal: &MapRewardAccountToCoin, policy_hash: Option) -> Self { Self(cml_chain::governance::TreasuryWithdrawalsAction::new( withdrawal.clone().into(), + policy_hash.map(Into::into), )) } } diff --git a/chain/wasm/src/lib.rs b/chain/wasm/src/lib.rs index 5432aef5..7a2716a5 100644 --- a/chain/wasm/src/lib.rs +++ b/chain/wasm/src/lib.rs @@ -41,8 +41,8 @@ use cml_crypto_wasm::{Ed25519KeyHash, ScriptHash}; use crypto::{BootstrapWitness, Vkeywitness}; use governance::{GovActionId, Voter}; use plutus::{ - CostModels, ExUnitPrices, ExUnits, PlutusData, PlutusV1Script, PlutusV2Script, PlutusV3Script, - Redeemer, + CostModels, ExUnitPrices, ExUnits, LegacyRedeemer, PlutusData, PlutusV1Script, PlutusV2Script, + PlutusV3Script, }; use transaction::{ NativeScript, TransactionBody, TransactionInput, TransactionOutput, TransactionWitnessSet, @@ -51,117 +51,52 @@ pub use utils::NetworkId; use crate::certs::CommitteeColdCredential; use crate::governance::{ProposalProcedure, VotingProcedure}; +use crate::plutus::{RedeemerKey, RedeemerVal}; -//extern crate serde_wasm_bindgen; -// Code below here was code-generated using an experimental CDDL to rust tool: -// https://github.com/dcSpark/cddl-codegen - -#[derive(Clone, Debug)] -#[wasm_bindgen] -pub struct AssetNameList(Vec); - -impl_wasm_conversions!(Vec, AssetNameList); - -#[wasm_bindgen] -impl AssetNameList { - pub fn new() -> Self { - Self(Vec::new()) - } - - pub fn len(&self) -> usize { - self.0.len() - } +pub type SetTransactionInput = TransactionInputList; - pub fn get(&self, index: usize) -> AssetName { - self.0[index].clone().into() - } +pub type NonemptySetBootstrapWitness = BootstrapWitnessList; - pub fn add(&mut self, elem: &AssetName) { - self.0.push(elem.clone().into()); - } -} +pub type NonemptySetCertificate = CertificateList; -#[derive(Clone, Debug)] -#[wasm_bindgen] -pub struct BootstrapWitnessList(Vec); +pub type NonemptySetNativeScript = NativeScriptList; -impl_wasm_conversions!( - Vec, - BootstrapWitnessList -); +pub type NonemptySetPlutusData = PlutusDataList; -#[wasm_bindgen] -impl BootstrapWitnessList { - pub fn new() -> Self { - Self(Vec::new()) - } +pub type NonemptySetPlutusV1Script = PlutusV1ScriptList; - pub fn len(&self) -> usize { - self.0.len() - } +pub type NonemptySetPlutusV2Script = PlutusV2ScriptList; - pub fn get(&self, index: usize) -> BootstrapWitness { - self.0[index].clone().into() - } +pub type NonemptySetPlutusV3Script = PlutusV3ScriptList; - pub fn add(&mut self, elem: &BootstrapWitness) { - self.0.push(elem.clone().into()); - } -} +pub type NonemptySetProposalProcedure = ProposalProcedureList; -#[derive(Clone, Debug)] -#[wasm_bindgen] -pub struct CertificateList(Vec); +pub type NonemptySetTransactionInput = TransactionInputList; -impl_wasm_conversions!(Vec, CertificateList); +pub type NonemptySetVkeywitness = VkeywitnessList; -#[wasm_bindgen] -impl CertificateList { - pub fn new() -> Self { - Self(Vec::new()) - } +pub type RequiredSigners = Ed25519KeyHashList; - pub fn len(&self) -> usize { - self.0.len() - } +//extern crate serde_wasm_bindgen; +// Code below here was code-generated using an experimental CDDL to rust tool: +// https://github.com/dcSpark/cddl-codegen - pub fn get(&self, index: usize) -> Certificate { - self.0[index].clone().into() - } +impl_wasm_list!(cml_chain::assets::AssetName, AssetName, AssetNameList); - pub fn add(&mut self, elem: &Certificate) { - self.0.push(elem.clone().into()); - } -} +impl_wasm_list!( + cml_chain::crypto::BootstrapWitness, + BootstrapWitness, + BootstrapWitnessList +); -#[derive(Clone, Debug)] -#[wasm_bindgen] -pub struct CommitteeColdCredentialList(Vec); +impl_wasm_list!(cml_chain::certs::Certificate, Certificate, CertificateList); -impl_wasm_conversions!( - Vec, +impl_wasm_list!( + cml_chain::certs::CommitteeColdCredential, + CommitteeColdCredential, CommitteeColdCredentialList ); -#[wasm_bindgen] -impl CommitteeColdCredentialList { - pub fn new() -> Self { - Self(Vec::new()) - } - - pub fn len(&self) -> usize { - self.0.len() - } - - pub fn get(&self, index: usize) -> CommitteeColdCredential { - self.0[index].clone().into() - } - - pub fn add(&mut self, elem: &CommitteeColdCredential) { - self.0.push(elem.clone().into()); - } -} - #[derive(Clone, Debug)] #[wasm_bindgen] pub struct DRepVotingThresholds(cml_chain::DRepVotingThresholds); @@ -241,80 +176,25 @@ impl DRepVotingThresholds { pub type DeltaCoin = Int; -#[derive(Clone, Debug)] -#[wasm_bindgen] -pub struct Ed25519KeyHashList(Vec); - -impl_wasm_conversions!(Vec, Ed25519KeyHashList); - -#[wasm_bindgen] -impl Ed25519KeyHashList { - pub fn new() -> Self { - Self(Vec::new()) - } - - pub fn len(&self) -> usize { - self.0.len() - } - - pub fn get(&self, index: usize) -> Ed25519KeyHash { - self.0[index].into() - } - - pub fn add(&mut self, elem: &Ed25519KeyHash) { - self.0.push(elem.clone().into()); - } -} - -#[derive(Clone, Debug)] -#[wasm_bindgen] -pub struct GovActionIdList(Vec); - -impl_wasm_conversions!(Vec, GovActionIdList); - -#[wasm_bindgen] -impl GovActionIdList { - pub fn new() -> Self { - Self(Vec::new()) - } - - pub fn len(&self) -> usize { - self.0.len() - } - - pub fn get(&self, index: usize) -> GovActionId { - self.0[index].clone().into() - } - - pub fn add(&mut self, elem: &GovActionId) { - self.0.push(elem.clone().into()); - } -} - -#[derive(Clone, Debug)] -#[wasm_bindgen] -pub struct IntList(Vec); - -impl_wasm_conversions!(Vec, IntList); - -#[wasm_bindgen] -impl IntList { - pub fn new() -> Self { - Self(Vec::new()) - } +impl_wasm_list!( + cml_chain::crypto::Ed25519KeyHash, + Ed25519KeyHash, + Ed25519KeyHashList +); - pub fn len(&self) -> usize { - self.0.len() - } +impl_wasm_list!( + cml_chain::governance::GovActionId, + GovActionId, + GovActionIdList +); - pub fn get(&self, index: usize) -> Int { - self.0[index].clone().into() - } +impl_wasm_list!(cml_chain::Int, Int, IntList); - pub fn add(&mut self, elem: &Int) { - self.0.push(elem.clone().into()); - } -} +impl_wasm_list!( + cml_chain::plutus::LegacyRedeemer, + LegacyRedeemer, + LegacyRedeemerList +); #[derive(Clone, Debug)] #[wasm_bindgen] @@ -477,6 +357,39 @@ impl MapPlutusDataToPlutusData { } } +#[derive(Clone, Debug)] +#[wasm_bindgen] +pub struct MapRedeemerKeyToRedeemerVal( + OrderedHashMap, +); + +impl_wasm_conversions!(OrderedHashMap, MapRedeemerKeyToRedeemerVal); + +#[wasm_bindgen] +impl MapRedeemerKeyToRedeemerVal { + pub fn new() -> Self { + Self(OrderedHashMap::new()) + } + + pub fn len(&self) -> usize { + self.0.len() + } + + pub fn insert(&mut self, key: &RedeemerKey, value: &RedeemerVal) -> Option { + self.0 + .insert(key.clone().into(), value.clone().into()) + .map(Into::into) + } + + pub fn get(&self, key: &RedeemerKey) -> Option { + self.0.get(key.as_ref()).map(|v| v.clone().into()) + } + + pub fn keys(&self) -> RedeemerKeyList { + RedeemerKeyList(self.0.iter().map(|(k, _v)| k.clone()).collect::>()) + } +} + #[derive(Clone, Debug)] #[wasm_bindgen] pub struct MapRewardAccountToCoin( @@ -620,134 +533,35 @@ impl MapTransactionMetadatumToTransactionMetadatum { } } -#[derive(Clone, Debug)] -#[wasm_bindgen] -pub struct NativeScriptList(Vec); - -impl_wasm_conversions!(Vec, NativeScriptList); - -#[wasm_bindgen] -impl NativeScriptList { - pub fn new() -> Self { - Self(Vec::new()) - } - - pub fn len(&self) -> usize { - self.0.len() - } - - pub fn get(&self, index: usize) -> NativeScript { - self.0[index].clone().into() - } - - pub fn add(&mut self, elem: &NativeScript) { - self.0.push(elem.clone().into()); - } -} +impl_wasm_list!( + cml_chain::transaction::NativeScript, + NativeScript, + NativeScriptList +); impl_wasm_list!(cml_chain::plutus::PlutusData, PlutusData, PlutusDataList); -#[derive(Clone, Debug)] -#[wasm_bindgen] -pub struct PlutusV1ScriptList(Vec); - -impl_wasm_conversions!(Vec, PlutusV1ScriptList); - -#[wasm_bindgen] -impl PlutusV1ScriptList { - pub fn new() -> Self { - Self(Vec::new()) - } - - pub fn len(&self) -> usize { - self.0.len() - } - - pub fn get(&self, index: usize) -> PlutusV1Script { - self.0[index].clone().into() - } - - pub fn add(&mut self, elem: &PlutusV1Script) { - self.0.push(elem.clone().into()); - } -} - -#[derive(Clone, Debug)] -#[wasm_bindgen] -pub struct PlutusV2ScriptList(Vec); - -impl_wasm_conversions!(Vec, PlutusV2ScriptList); - -#[wasm_bindgen] -impl PlutusV2ScriptList { - pub fn new() -> Self { - Self(Vec::new()) - } - - pub fn len(&self) -> usize { - self.0.len() - } - - pub fn get(&self, index: usize) -> PlutusV2Script { - self.0[index].clone().into() - } - - pub fn add(&mut self, elem: &PlutusV2Script) { - self.0.push(elem.clone().into()); - } -} - -#[derive(Clone, Debug)] -#[wasm_bindgen] -pub struct PlutusV3ScriptList(Vec); - -impl_wasm_conversions!(Vec, PlutusV3ScriptList); - -#[wasm_bindgen] -impl PlutusV3ScriptList { - pub fn new() -> Self { - Self(Vec::new()) - } - - pub fn len(&self) -> usize { - self.0.len() - } +impl_wasm_list!( + cml_chain::plutus::PlutusV1Script, + PlutusV1Script, + PlutusV1ScriptList +); - pub fn get(&self, index: usize) -> PlutusV3Script { - self.0[index].clone().into() - } +impl_wasm_list!( + cml_chain::plutus::PlutusV2Script, + PlutusV2Script, + PlutusV2ScriptList +); - pub fn add(&mut self, elem: &PlutusV3Script) { - self.0.push(elem.clone().into()); - } -} +impl_wasm_list!( + cml_chain::plutus::PlutusV3Script, + PlutusV3Script, + PlutusV3ScriptList +); pub type PolicyId = ScriptHash; -#[derive(Clone, Debug)] -#[wasm_bindgen] -pub struct PolicyIdList(Vec); - -impl_wasm_conversions!(Vec, PolicyIdList); - -#[wasm_bindgen] -impl PolicyIdList { - pub fn new() -> Self { - Self(Vec::new()) - } - - pub fn len(&self) -> usize { - self.0.len() - } - - pub fn get(&self, index: usize) -> PolicyId { - self.0[index].into() - } - - pub fn add(&mut self, elem: &PolicyId) { - self.0.push(elem.clone().into()); - } -} +impl_wasm_list!(cml_chain::PolicyId, PolicyId, PolicyIdList); #[derive(Clone, Debug)] #[wasm_bindgen] @@ -775,51 +589,38 @@ impl PoolVotingThresholds { self.0.hard_fork_initiation.clone().into() } + pub fn security_relevant_parameter_voting_threshold(&self) -> UnitInterval { + self.0 + .security_relevant_parameter_voting_threshold + .clone() + .into() + } + pub fn new( motion_no_confidence: &UnitInterval, committee_normal: &UnitInterval, committee_no_confidence: &UnitInterval, hard_fork_initiation: &UnitInterval, + security_relevant_parameter_voting_threshold: &UnitInterval, ) -> Self { Self(cml_chain::PoolVotingThresholds::new( motion_no_confidence.clone().into(), committee_normal.clone().into(), committee_no_confidence.clone().into(), hard_fork_initiation.clone().into(), + security_relevant_parameter_voting_threshold.clone().into(), )) } } pub type Port = u16; -#[derive(Clone, Debug)] -#[wasm_bindgen] -pub struct ProposalProcedureList(Vec); - -impl_wasm_conversions!( - Vec, +impl_wasm_list!( + cml_chain::governance::ProposalProcedure, + ProposalProcedure, ProposalProcedureList ); -#[wasm_bindgen] -impl ProposalProcedureList { - pub fn new() -> Self { - Self(Vec::new()) - } - - pub fn len(&self) -> usize { - self.0.len() - } - - pub fn get(&self, index: usize) -> ProposalProcedure { - self.0[index].clone().into() - } - - pub fn add(&mut self, elem: &ProposalProcedure) { - self.0.push(elem.clone().into()); - } -} - #[derive(Clone, Debug)] #[wasm_bindgen] pub struct ProtocolParamUpdate(cml_chain::ProtocolParamUpdate); @@ -830,19 +631,19 @@ impl_wasm_conversions!(cml_chain::ProtocolParamUpdate, ProtocolParamUpdate); #[wasm_bindgen] impl ProtocolParamUpdate { - pub fn set_minfee_a(&mut self, minfee_a: u64) { + pub fn set_minfee_a(&mut self, minfee_a: Coin) { self.0.minfee_a = Some(minfee_a) } - pub fn minfee_a(&self) -> Option { + pub fn minfee_a(&self) -> Option { self.0.minfee_a } - pub fn set_minfee_b(&mut self, minfee_b: u64) { + pub fn set_minfee_b(&mut self, minfee_b: Coin) { self.0.minfee_b = Some(minfee_b) } - pub fn minfee_b(&self) -> Option { + pub fn minfee_b(&self) -> Option { self.0.minfee_b } @@ -1044,11 +845,11 @@ impl ProtocolParamUpdate { self.0.min_committee_size } - pub fn set_committee_term_limit(&mut self, committee_term_limit: u64) { + pub fn set_committee_term_limit(&mut self, committee_term_limit: Epoch) { self.0.committee_term_limit = Some(committee_term_limit) } - pub fn committee_term_limit(&self) -> Option { + pub fn committee_term_limit(&self) -> Option { self.0.committee_term_limit } @@ -1087,6 +888,21 @@ impl ProtocolParamUpdate { self.0.d_rep_inactivity_period } + pub fn set_min_fee_ref_script_cost_per_byte( + &mut self, + min_fee_ref_script_cost_per_byte: &Rational, + ) { + self.0.min_fee_ref_script_cost_per_byte = + Some(min_fee_ref_script_cost_per_byte.clone().into()) + } + + pub fn min_fee_ref_script_cost_per_byte(&self) -> Option { + self.0 + .min_fee_ref_script_cost_per_byte + .clone() + .map(std::convert::Into::into) + } + pub fn new() -> Self { Self(cml_chain::ProtocolParamUpdate::new()) } @@ -1115,80 +931,15 @@ impl Rational { } } -#[derive(Clone, Debug)] -#[wasm_bindgen] -pub struct RedeemerList(Vec); +impl_wasm_list!(cml_chain::plutus::RedeemerKey, RedeemerKey, RedeemerKeyList); -impl_wasm_conversions!(Vec, RedeemerList); +impl_wasm_list!(cml_chain::certs::Relay, Relay, RelayList); -#[wasm_bindgen] -impl RedeemerList { - pub fn new() -> Self { - Self(Vec::new()) - } - - pub fn len(&self) -> usize { - self.0.len() - } - - pub fn get(&self, index: usize) -> Redeemer { - self.0[index].clone().into() - } - - pub fn add(&mut self, elem: &Redeemer) { - self.0.push(elem.clone().into()); - } -} - -#[derive(Clone, Debug)] -#[wasm_bindgen] -pub struct RelayList(Vec); - -impl_wasm_conversions!(Vec, RelayList); - -#[wasm_bindgen] -impl RelayList { - pub fn new() -> Self { - Self(Vec::new()) - } - - pub fn len(&self) -> usize { - self.0.len() - } - - pub fn get(&self, index: usize) -> Relay { - self.0[index].clone().into() - } - - pub fn add(&mut self, elem: &Relay) { - self.0.push(elem.clone().into()); - } -} - -#[derive(Clone, Debug)] -#[wasm_bindgen] -pub struct RewardAccountList(Vec); - -impl_wasm_conversions!(Vec, RewardAccountList); - -#[wasm_bindgen] -impl RewardAccountList { - pub fn new() -> Self { - Self(Vec::new()) - } - - pub fn len(&self) -> usize { - self.0.len() - } - - pub fn get(&self, index: usize) -> RewardAccount { - self.0[index].clone().into() - } - - pub fn add(&mut self, elem: &RewardAccount) { - self.0.push(elem.clone().into()); - } -} +impl_wasm_list!( + cml_chain::address::RewardAccount, + RewardAccount, + RewardAccountList +); #[derive(Clone, Debug)] #[wasm_bindgen] @@ -1264,147 +1015,40 @@ pub enum ScriptKind { pub type Slot = u64; -#[derive(Clone, Debug)] -#[wasm_bindgen] -pub struct StakeCredentialList(Vec); - -impl_wasm_conversions!(Vec, StakeCredentialList); - -#[wasm_bindgen] -impl StakeCredentialList { - pub fn new() -> Self { - Self(Vec::new()) - } - - pub fn len(&self) -> usize { - self.0.len() - } - - pub fn get(&self, index: usize) -> StakeCredential { - self.0[index].clone().into() - } - - pub fn add(&mut self, elem: &StakeCredential) { - self.0.push(elem.clone().into()); - } -} +impl_wasm_list!( + cml_chain::certs::StakeCredential, + StakeCredential, + StakeCredentialList +); pub type SubCoin = Rational; -#[derive(Clone, Debug)] -#[wasm_bindgen] -pub struct TransactionBodyList(Vec); - -impl_wasm_conversions!( - Vec, +impl_wasm_list!( + cml_chain::transaction::TransactionBody, + TransactionBody, TransactionBodyList ); -#[wasm_bindgen] -impl TransactionBodyList { - pub fn new() -> Self { - Self(Vec::new()) - } - - pub fn len(&self) -> usize { - self.0.len() - } - - pub fn get(&self, index: usize) -> TransactionBody { - self.0[index].clone().into() - } - - pub fn add(&mut self, elem: &TransactionBody) { - self.0.push(elem.clone().into()); - } -} - pub type TransactionIndex = u16; -#[derive(Clone, Debug)] -#[wasm_bindgen] -pub struct TransactionInputList(Vec); - -impl_wasm_conversions!( - Vec, +impl_wasm_list!( + cml_chain::transaction::TransactionInput, + TransactionInput, TransactionInputList ); -#[wasm_bindgen] -impl TransactionInputList { - pub fn new() -> Self { - Self(Vec::new()) - } - - pub fn len(&self) -> usize { - self.0.len() - } - - pub fn get(&self, index: usize) -> TransactionInput { - self.0[index].clone().into() - } - - pub fn add(&mut self, elem: &TransactionInput) { - self.0.push(elem.clone().into()); - } -} - -#[derive(Clone, Debug)] -#[wasm_bindgen] -pub struct TransactionOutputList(Vec); - -impl_wasm_conversions!( - Vec, +impl_wasm_list!( + cml_chain::transaction::TransactionOutput, + TransactionOutput, TransactionOutputList ); -#[wasm_bindgen] -impl TransactionOutputList { - pub fn new() -> Self { - Self(Vec::new()) - } - - pub fn len(&self) -> usize { - self.0.len() - } - - pub fn get(&self, index: usize) -> TransactionOutput { - self.0[index].clone().into() - } - - pub fn add(&mut self, elem: &TransactionOutput) { - self.0.push(elem.clone().into()); - } -} - -#[derive(Clone, Debug)] -#[wasm_bindgen] -pub struct TransactionWitnessSetList(Vec); - -impl_wasm_conversions!( - Vec, +impl_wasm_list!( + cml_chain::transaction::TransactionWitnessSet, + TransactionWitnessSet, TransactionWitnessSetList ); -#[wasm_bindgen] -impl TransactionWitnessSetList { - pub fn new() -> Self { - Self(Vec::new()) - } - - pub fn len(&self) -> usize { - self.0.len() - } - - pub fn get(&self, index: usize) -> TransactionWitnessSet { - self.0[index].clone().into() - } - - pub fn add(&mut self, elem: &TransactionWitnessSet) { - self.0.push(elem.clone().into()); - } -} - #[derive(Clone, Debug)] #[wasm_bindgen] pub struct UnitInterval(cml_chain::UnitInterval); @@ -1428,54 +1072,8 @@ impl UnitInterval { } } -#[derive(Clone, Debug)] -#[wasm_bindgen] -pub struct VkeywitnessList(Vec); - -impl_wasm_conversions!(Vec, VkeywitnessList); - -#[wasm_bindgen] -impl VkeywitnessList { - pub fn new() -> Self { - Self(Vec::new()) - } +impl_wasm_list!(cml_chain::crypto::Vkeywitness, Vkeywitness, VkeywitnessList); - pub fn len(&self) -> usize { - self.0.len() - } - - pub fn get(&self, index: usize) -> Vkeywitness { - self.0[index].clone().into() - } - - pub fn add(&mut self, elem: &Vkeywitness) { - self.0.push(elem.clone().into()); - } -} - -#[derive(Clone, Debug)] -#[wasm_bindgen] -pub struct VoterList(Vec); - -impl_wasm_conversions!(Vec, VoterList); - -#[wasm_bindgen] -impl VoterList { - pub fn new() -> Self { - Self(Vec::new()) - } - - pub fn len(&self) -> usize { - self.0.len() - } - - pub fn get(&self, index: usize) -> Voter { - self.0[index].clone().into() - } - - pub fn add(&mut self, elem: &Voter) { - self.0.push(elem.clone().into()); - } -} +impl_wasm_list!(cml_chain::governance::Voter, Voter, VoterList); pub type Withdrawals = MapRewardAccountToCoin; diff --git a/chain/wasm/src/plutus/mod.rs b/chain/wasm/src/plutus/mod.rs index 34603486..ccf194fd 100644 --- a/chain/wasm/src/plutus/mod.rs +++ b/chain/wasm/src/plutus/mod.rs @@ -6,6 +6,7 @@ pub mod utils; use crate::utils::BigInteger; use super::{IntList, PlutusDataList, SubCoin}; +use crate::{LegacyRedeemerList, MapRedeemerKeyToRedeemerVal}; pub use cml_chain::plutus::{Language, RedeemerTag}; use cml_core_wasm::{impl_wasm_cbor_json_api, impl_wasm_conversions}; pub use utils::{ConstrPlutusData, PlutusMap}; @@ -99,6 +100,42 @@ impl ExUnits { } } +#[derive(Clone, Debug)] +#[wasm_bindgen] +pub struct LegacyRedeemer(cml_chain::plutus::LegacyRedeemer); + +impl_wasm_cbor_json_api!(LegacyRedeemer); + +impl_wasm_conversions!(cml_chain::plutus::LegacyRedeemer, LegacyRedeemer); + +#[wasm_bindgen] +impl LegacyRedeemer { + pub fn tag(&self) -> RedeemerTag { + self.0.tag + } + + pub fn index(&self) -> u64 { + self.0.index + } + + pub fn data(&self) -> PlutusData { + self.0.data.clone().into() + } + + pub fn ex_units(&self) -> ExUnits { + self.0.ex_units.clone().into() + } + + pub fn new(tag: RedeemerTag, index: u64, data: &PlutusData, ex_units: &ExUnits) -> Self { + Self(cml_chain::plutus::LegacyRedeemer::new( + tag, + index, + data.clone().into(), + ex_units.clone().into(), + )) + } +} + #[derive(Clone, Debug)] #[wasm_bindgen] pub struct PlutusData(cml_chain::plutus::PlutusData); @@ -237,14 +274,14 @@ impl PlutusV3Script { #[derive(Clone, Debug)] #[wasm_bindgen] -pub struct Redeemer(cml_chain::plutus::Redeemer); +pub struct RedeemerKey(cml_chain::plutus::RedeemerKey); -impl_wasm_cbor_json_api!(Redeemer); +impl_wasm_cbor_json_api!(RedeemerKey); -impl_wasm_conversions!(cml_chain::plutus::Redeemer, Redeemer); +impl_wasm_conversions!(cml_chain::plutus::RedeemerKey, RedeemerKey); #[wasm_bindgen] -impl Redeemer { +impl RedeemerKey { pub fn tag(&self) -> RedeemerTag { self.0.tag } @@ -253,6 +290,21 @@ impl Redeemer { self.0.index } + pub fn new(tag: RedeemerTag, index: u64) -> Self { + Self(cml_chain::plutus::RedeemerKey::new(tag, index)) + } +} + +#[derive(Clone, Debug)] +#[wasm_bindgen] +pub struct RedeemerVal(cml_chain::plutus::RedeemerVal); + +impl_wasm_cbor_json_api!(RedeemerVal); + +impl_wasm_conversions!(cml_chain::plutus::RedeemerVal, RedeemerVal); + +#[wasm_bindgen] +impl RedeemerVal { pub fn data(&self) -> PlutusData { self.0.data.clone().into() } @@ -261,12 +313,74 @@ impl Redeemer { self.0.ex_units.clone().into() } - pub fn new(tag: RedeemerTag, index: u64, data: &PlutusData, ex_units: &ExUnits) -> Self { - Self(cml_chain::plutus::Redeemer::new( - tag, - index, + pub fn new(data: &PlutusData, ex_units: &ExUnits) -> Self { + Self(cml_chain::plutus::RedeemerVal::new( data.clone().into(), ex_units.clone().into(), )) } } + +#[derive(Clone, Debug)] +#[wasm_bindgen] +pub struct Redeemers(cml_chain::plutus::Redeemers); + +impl_wasm_cbor_json_api!(Redeemers); + +impl_wasm_conversions!(cml_chain::plutus::Redeemers, Redeemers); + +#[wasm_bindgen] +impl Redeemers { + pub fn new_arr_legacy_redeemer(arr_legacy_redeemer: &LegacyRedeemerList) -> Self { + Self(cml_chain::plutus::Redeemers::new_arr_legacy_redeemer( + arr_legacy_redeemer.clone().into(), + )) + } + + pub fn new_map_redeemer_key_to_redeemer_val( + map_redeemer_key_to_redeemer_val: &MapRedeemerKeyToRedeemerVal, + ) -> Self { + Self( + cml_chain::plutus::Redeemers::new_map_redeemer_key_to_redeemer_val( + map_redeemer_key_to_redeemer_val.clone().into(), + ), + ) + } + + pub fn kind(&self) -> RedeemersKind { + match &self.0 { + cml_chain::plutus::Redeemers::ArrLegacyRedeemer { .. } => { + RedeemersKind::ArrLegacyRedeemer + } + cml_chain::plutus::Redeemers::MapRedeemerKeyToRedeemerVal { .. } => { + RedeemersKind::MapRedeemerKeyToRedeemerVal + } + } + } + + pub fn as_arr_legacy_redeemer(&self) -> Option { + match &self.0 { + cml_chain::plutus::Redeemers::ArrLegacyRedeemer { + arr_legacy_redeemer, + .. + } => Some(arr_legacy_redeemer.clone().into()), + _ => None, + } + } + + pub fn as_map_redeemer_key_to_redeemer_val(&self) -> Option { + match &self.0 { + cml_chain::plutus::Redeemers::MapRedeemerKeyToRedeemerVal { + map_redeemer_key_to_redeemer_val, + .. + } => Some(map_redeemer_key_to_redeemer_val.clone().into()), + _ => None, + } + } +} + +#[wasm_bindgen] +pub enum RedeemersKind { + ArrLegacyRedeemer, + MapRedeemerKeyToRedeemerVal, +} diff --git a/chain/wasm/src/plutus/utils.rs b/chain/wasm/src/plutus/utils.rs index e115d28c..31a6842f 100644 --- a/chain/wasm/src/plutus/utils.rs +++ b/chain/wasm/src/plutus/utils.rs @@ -1,4 +1,7 @@ -use crate::{plutus::PlutusData, PlutusDataList, RedeemerList}; +use crate::{ + plutus::{PlutusData, Redeemers}, + LegacyRedeemerList, PlutusDataList, +}; use cml_chain::plutus::Language; use cml_core_wasm::{impl_wasm_cbor_json_api, impl_wasm_conversions}; use cml_crypto_wasm::ScriptHash; @@ -149,6 +152,13 @@ impl PlutusV2Script { } } +#[wasm_bindgen] +impl Redeemers { + pub fn to_flat_format(&self) -> LegacyRedeemerList { + self.0.clone().to_flat_format().into() + } +} + #[wasm_bindgen] impl ExUnits { pub fn checked_add(&self, other: &ExUnits) -> Result { @@ -160,8 +170,8 @@ impl ExUnits { } #[wasm_bindgen] -pub fn compute_total_ex_units(redeemers: &RedeemerList) -> Result { - cml_chain::plutus::utils::compute_total_ex_units(redeemers.as_ref()) +pub fn compute_total_ex_units(redeemers: &Redeemers) -> Result { + cml_chain::plutus::utils::compute_total_ex_units(redeemers.to_flat_format().as_ref()) .map(Into::into) .map_err(Into::into) } diff --git a/chain/wasm/src/transaction/mod.rs b/chain/wasm/src/transaction/mod.rs index ae055006..e4fb2a94 100644 --- a/chain/wasm/src/transaction/mod.rs +++ b/chain/wasm/src/transaction/mod.rs @@ -5,12 +5,13 @@ use crate::address::Address; use crate::assets::{Coin, Mint, PositiveCoin, Value}; use crate::auxdata::AuxiliaryData; use crate::governance::VotingProcedures; -use crate::plutus::PlutusData; -use crate::Script; +use crate::plutus::{PlutusData, Redeemers}; use crate::{ - BootstrapWitnessList, CertificateList, NativeScriptList, NetworkId, PlutusDataList, - PlutusV1ScriptList, PlutusV2ScriptList, PlutusV3ScriptList, ProposalProcedureList, - RedeemerList, Slot, TransactionInputList, TransactionOutputList, VkeywitnessList, Withdrawals, + NativeScriptList, NetworkId, NonemptySetBootstrapWitness, NonemptySetCertificate, + NonemptySetNativeScript, NonemptySetPlutusData, NonemptySetPlutusV1Script, + NonemptySetPlutusV2Script, NonemptySetPlutusV3Script, NonemptySetProposalProcedure, + NonemptySetTransactionInput, NonemptySetVkeywitness, RequiredSigners, Script, + SetTransactionInput, Slot, TransactionOutputList, Withdrawals, }; use cml_core_wasm::{impl_wasm_cbor_json_api, impl_wasm_conversions}; use cml_crypto_wasm::{ @@ -274,31 +275,6 @@ pub enum NativeScriptKind { ScriptInvalidHereafter, } -#[derive(Clone, Debug)] -#[wasm_bindgen] -pub struct RequiredSigners(Vec); - -impl_wasm_conversions!(Vec, RequiredSigners); - -#[wasm_bindgen] -impl RequiredSigners { - pub fn new() -> Self { - Self(Vec::new()) - } - - pub fn len(&self) -> usize { - self.0.len() - } - - pub fn get(&self, index: usize) -> Ed25519KeyHash { - self.0[index].into() - } - - pub fn add(&mut self, elem: &Ed25519KeyHash) { - self.0.push(elem.clone().into()); - } -} - #[derive(Clone, Debug)] #[wasm_bindgen] pub struct ScriptAll(cml_chain::transaction::ScriptAll); @@ -485,7 +461,7 @@ impl_wasm_conversions!(cml_chain::transaction::TransactionBody, TransactionBody) #[wasm_bindgen] impl TransactionBody { - pub fn inputs(&self) -> TransactionInputList { + pub fn inputs(&self) -> SetTransactionInput { self.0.inputs.clone().into() } @@ -505,11 +481,11 @@ impl TransactionBody { self.0.ttl } - pub fn set_certs(&mut self, certs: &CertificateList) { + pub fn set_certs(&mut self, certs: &NonemptySetCertificate) { self.0.certs = Some(certs.clone().into()) } - pub fn certs(&self) -> Option { + pub fn certs(&self) -> Option { self.0.certs.clone().map(std::convert::Into::into) } @@ -553,11 +529,11 @@ impl TransactionBody { self.0.script_data_hash.map(std::convert::Into::into) } - pub fn set_collateral_inputs(&mut self, collateral_inputs: &TransactionInputList) { + pub fn set_collateral_inputs(&mut self, collateral_inputs: &NonemptySetTransactionInput) { self.0.collateral_inputs = Some(collateral_inputs.clone().into()) } - pub fn collateral_inputs(&self) -> Option { + pub fn collateral_inputs(&self) -> Option { self.0 .collateral_inputs .clone() @@ -602,11 +578,11 @@ impl TransactionBody { self.0.total_collateral } - pub fn set_reference_inputs(&mut self, reference_inputs: &TransactionInputList) { + pub fn set_reference_inputs(&mut self, reference_inputs: &NonemptySetTransactionInput) { self.0.reference_inputs = Some(reference_inputs.clone().into()) } - pub fn reference_inputs(&self) -> Option { + pub fn reference_inputs(&self) -> Option { self.0 .reference_inputs .clone() @@ -624,11 +600,11 @@ impl TransactionBody { .map(std::convert::Into::into) } - pub fn set_proposal_procedures(&mut self, proposal_procedures: &ProposalProcedureList) { + pub fn set_proposal_procedures(&mut self, proposal_procedures: &NonemptySetProposalProcedure) { self.0.proposal_procedures = Some(proposal_procedures.clone().into()) } - pub fn proposal_procedures(&self) -> Option { + pub fn proposal_procedures(&self) -> Option { self.0 .proposal_procedures .clone() @@ -651,7 +627,7 @@ impl TransactionBody { self.0.donation } - pub fn new(inputs: &TransactionInputList, outputs: &TransactionOutputList, fee: Coin) -> Self { + pub fn new(inputs: &SetTransactionInput, outputs: &TransactionOutputList, fee: Coin) -> Self { Self(cml_chain::transaction::TransactionBody::new( inputs.clone().into(), outputs.clone().into(), @@ -761,76 +737,76 @@ impl_wasm_conversions!( #[wasm_bindgen] impl TransactionWitnessSet { - pub fn set_vkeywitnesses(&mut self, vkeywitnesses: &VkeywitnessList) { + pub fn set_vkeywitnesses(&mut self, vkeywitnesses: &NonemptySetVkeywitness) { self.0.vkeywitnesses = Some(vkeywitnesses.clone().into()) } - pub fn vkeywitnesses(&self) -> Option { + pub fn vkeywitnesses(&self) -> Option { self.0.vkeywitnesses.clone().map(std::convert::Into::into) } - pub fn set_native_scripts(&mut self, native_scripts: &NativeScriptList) { + pub fn set_native_scripts(&mut self, native_scripts: &NonemptySetNativeScript) { self.0.native_scripts = Some(native_scripts.clone().into()) } - pub fn native_scripts(&self) -> Option { + pub fn native_scripts(&self) -> Option { self.0.native_scripts.clone().map(std::convert::Into::into) } - pub fn set_bootstrap_witnesses(&mut self, bootstrap_witnesses: &BootstrapWitnessList) { + pub fn set_bootstrap_witnesses(&mut self, bootstrap_witnesses: &NonemptySetBootstrapWitness) { self.0.bootstrap_witnesses = Some(bootstrap_witnesses.clone().into()) } - pub fn bootstrap_witnesses(&self) -> Option { + pub fn bootstrap_witnesses(&self) -> Option { self.0 .bootstrap_witnesses .clone() .map(std::convert::Into::into) } - pub fn set_plutus_v1_scripts(&mut self, plutus_v1_scripts: &PlutusV1ScriptList) { + pub fn set_plutus_v1_scripts(&mut self, plutus_v1_scripts: &NonemptySetPlutusV1Script) { self.0.plutus_v1_scripts = Some(plutus_v1_scripts.clone().into()) } - pub fn plutus_v1_scripts(&self) -> Option { + pub fn plutus_v1_scripts(&self) -> Option { self.0 .plutus_v1_scripts .clone() .map(std::convert::Into::into) } - pub fn set_plutus_datums(&mut self, plutus_datums: &PlutusDataList) { + pub fn set_plutus_datums(&mut self, plutus_datums: &NonemptySetPlutusData) { self.0.plutus_datums = Some(plutus_datums.clone().into()) } - pub fn plutus_datums(&self) -> Option { + pub fn plutus_datums(&self) -> Option { self.0.plutus_datums.clone().map(std::convert::Into::into) } - pub fn set_redeemers(&mut self, redeemers: &RedeemerList) { + pub fn set_redeemers(&mut self, redeemers: &Redeemers) { self.0.redeemers = Some(redeemers.clone().into()) } - pub fn redeemers(&self) -> Option { + pub fn redeemers(&self) -> Option { self.0.redeemers.clone().map(std::convert::Into::into) } - pub fn set_plutus_v2_scripts(&mut self, plutus_v2_scripts: &PlutusV2ScriptList) { + pub fn set_plutus_v2_scripts(&mut self, plutus_v2_scripts: &NonemptySetPlutusV2Script) { self.0.plutus_v2_scripts = Some(plutus_v2_scripts.clone().into()) } - pub fn plutus_v2_scripts(&self) -> Option { + pub fn plutus_v2_scripts(&self) -> Option { self.0 .plutus_v2_scripts .clone() .map(std::convert::Into::into) } - pub fn set_plutus_v3_scripts(&mut self, plutus_v3_scripts: &PlutusV3ScriptList) { + pub fn set_plutus_v3_scripts(&mut self, plutus_v3_scripts: &NonemptySetPlutusV3Script) { self.0.plutus_v3_scripts = Some(plutus_v3_scripts.clone().into()) } - pub fn plutus_v3_scripts(&self) -> Option { + pub fn plutus_v3_scripts(&self) -> Option { self.0 .plutus_v3_scripts .clone() diff --git a/chain/wasm/src/utils.rs b/chain/wasm/src/utils.rs index be2c0811..00d0bfc8 100644 --- a/chain/wasm/src/utils.rs +++ b/chain/wasm/src/utils.rs @@ -85,3 +85,63 @@ impl NetworkId { self.0.network } } + +macro_rules! impl_wasm_conversions_into { + ($rust:ty, $wasm:ty) => { + impl From<$rust> for $wasm { + fn from(native: $rust) -> Self { + Self(native.into()) + } + } + + #[allow(clippy::from_over_into)] + impl Into<$rust> for $wasm { + fn into(self) -> $rust { + self.0.into() + } + } + }; +} + +impl_wasm_conversions_into!(cml_chain::NonemptySetCertificate, crate::CertificateList); + +impl_wasm_conversions_into!( + cml_chain::NonemptySetPlutusV1Script, + crate::PlutusV1ScriptList +); + +impl_wasm_conversions_into!( + cml_chain::NonemptySetPlutusV2Script, + crate::PlutusV2ScriptList +); + +impl_wasm_conversions_into!( + cml_chain::NonemptySetPlutusV3Script, + crate::PlutusV3ScriptList +); + +impl_wasm_conversions_into!(cml_chain::NonemptySetPlutusData, crate::PlutusDataList); + +impl_wasm_conversions_into!( + cml_chain::NonemptySetBootstrapWitness, + crate::BootstrapWitnessList +); + +impl_wasm_conversions_into!(cml_chain::NonemptySetVkeywitness, crate::VkeywitnessList); + +impl_wasm_conversions_into!( + cml_chain::NonemptySetProposalProcedure, + crate::ProposalProcedureList +); + +impl_wasm_conversions_into!( + cml_chain::NonemptySetTransactionInput, + crate::TransactionInputList +); + +impl_wasm_conversions_into!(cml_chain::NonemptySetNativeScript, crate::NativeScriptList); + +impl_wasm_conversions_into!( + cml_chain::utils::NonemptySetRawBytes, + crate::Ed25519KeyHashList +); diff --git a/specs/conway/certs.cddl b/specs/conway/certs.cddl index 20f2b9ec..d66eb727 100644 --- a/specs/conway/certs.cddl +++ b/specs/conway/certs.cddl @@ -104,7 +104,7 @@ pool_params = ( operator: ed25519_key_hash ipv4 = bytes .size 4 ; @custom_json ipv6 = bytes .size 16 ; @custom_json -dns_name = tstr .size (0..64) +dns_name = tstr .size (0..128) single_host_addr = ( tag: 0 , port / null diff --git a/specs/conway/governance.cddl b/specs/conway/governance.cddl index 2da0c7c3..d069e320 100644 --- a/specs/conway/governance.cddl +++ b/specs/conway/governance.cddl @@ -24,7 +24,12 @@ gov_action = [ 6 ] -parameter_change_action = (tag: 0, gov_action_id / null, protocol_param_update) +parameter_change_action = ( + tag: 0, + gov_action_id / null, + protocol_param_update, + policy_hash: script_hash / null, +) hard_fork_initiation_action = ( tag: 1 @@ -34,7 +39,8 @@ hard_fork_initiation_action = ( treasury_withdrawals_action = ( tag: 2, - withdrawal: { $reward_account => coin } + withdrawal: { $reward_account => coin }, + policy_hash: script_hash / null, ) no_confidence = ( diff --git a/specs/conway/lib.cddl b/specs/conway/lib.cddl index 18665081..62c12556 100644 --- a/specs/conway/lib.cddl +++ b/specs/conway/lib.cddl @@ -28,8 +28,8 @@ withdrawals = { * reward_account => coin } protocol_param_update = { - ? 0: uint, ; @name minfee_a - ? 1: uint, ; @name minfee_b + ? 0: coin, ; @name minfee_a + ? 1: coin, ; @name minfee_b ? 2: uint, ; @name max_block_body_size ? 3: uint, ; @name max_transaction_size ? 4: uint, ; @name max_block_header_size @@ -52,18 +52,20 @@ protocol_param_update = { ? 25: pool_voting_thresholds, ; @name pool_voting_thresholds ? 26: d_rep_voting_thresholds, ; @name d_rep_voting_thresholds ? 27: uint, ; @name min_committee_size - ? 28: uint, ; @name committee_term_limit + ? 28: epoch, ; @name committee_term_limit ? 29: epoch, ; @name governance_action_validity_period ? 30: coin, ; @name governance_action_deposit ? 31: coin, ; @name d_rep_deposit ? 32: epoch, ; @name d_rep_inactivity_period + ? 33: rational, ; @name min_fee_ref_script_cost_per_byte } pool_voting_thresholds = [ motion_no_confidence: unit_interval, committee_normal: unit_interval, committee_no_confidence: unit_interval, - hard_fork_initiation: unit_interval, + hard_fork_initiation: unit_interval, + security_relevant_parameter_voting_threshold: unit_interval, ] d_rep_voting_thresholds = [ @@ -90,4 +92,7 @@ policy_id = script_hash ; network_id = uint .size 1 ; @newtype ; but then hand-coded to add functionality/check bounds more network_id = uint ; @newtype -; _CDDL_CODEGEN_EXTERN_TYPE_ \ No newline at end of file +; _CDDL_CODEGEN_EXTERN_TYPE_ + +set = _CDDL_CODEGEN_EXTERN_TYPE_ +nonempty_set = _CDDL_CODEGEN_EXTERN_TYPE_ \ No newline at end of file diff --git a/specs/conway/plutus.cddl b/specs/conway/plutus.cddl index 1286d7f0..f045cfbe 100644 --- a/specs/conway/plutus.cddl +++ b/specs/conway/plutus.cddl @@ -36,12 +36,28 @@ big_integer = _CDDL_CODEGEN_EXTERN_TYPE_ ; / #6.102([alternative: uint, fields: [* a]]) constr_plutus_data = _CDDL_CODEGEN_EXTERN_TYPE_ -redeemer = [ tag: redeemer_tag, index: uint, data: plutus_data, ex_units: ex_units ] +redeemer_key = [ tag: redeemer_tag, index: uint ] + +redeemer_val = [ data: plutus_data, ex_units: ex_units ] + +legacy_redeemer = [ tag: redeemer_tag, index: uint, data: plutus_data, ex_units: ex_units ] + +; Flat Array support is included for backwards compatibility and will be removed in the next era. +; It is recommended for tools to adopt using a Map instead of Array going forward. +redeemers = + ; @name LegacyFlatFormat + [ + legacy_redeemer ] / + ; @name MapFormat + { + redeemer_key => redeemer_val } + redeemer_tag = 0 ; @name Spend / 1 ; @name Mint / 2 ; @name Cert / 3 ; @name Reward + / 4 ; @name Voting + / 5 ; @name Proposing + ex_units = [mem: uint, steps: uint] ex_unit_prices = @@ -54,5 +70,5 @@ language = 0 ; @name plutus_v1 cost_models = { ? 0 : [ 166*166 int ], ; @name plutus_v1 ? 1 : [ 175*175 int ], ; @name plutus_v2 - ? 2 : [ 179*179 int ], ; @name plutus_v3 + ? 2 : [ 233*233 int ], ; @name plutus_v3 } diff --git a/specs/conway/transaction.cddl b/specs/conway/transaction.cddl index db6e37e5..1351f567 100644 --- a/specs/conway/transaction.cddl +++ b/specs/conway/transaction.cddl @@ -8,29 +8,29 @@ transaction = ] transaction_body = { - 0 : [* transaction_input], ; @name inputs - 1 : [* transaction_output], ; @name outputs - 2 : coin, ; @name fee - ? 3 : uint, ; @name ttl - ? 4 : [* certificate], ; @name certs - ? 5 : withdrawals, ; @name withdrawals - ? 7 : auxiliary_data_hash, ; @name auxiliary_data_hash - ? 8 : uint, ; @name validity_interval_start - ? 9 : mint, ; @name mint - ? 11 : script_data_hash, ; @name script_data_hash - ? 13 : [* transaction_input], ; @name collateral_inputs - ? 14 : required_signers, ; @name required_signers - ? 15 : network_id, ; @name network_id - ? 16 : transaction_output, ; @name collateral_return - ? 17 : coin, ; @name total_collateral - ? 18 : [* transaction_input], ; @name reference_inputs - ? 19 : voting_procedures, ; @name voting_procedures - ? 20 : [* proposal_procedure], ; @name proposal_procedures - ? 21 : coin, ; @name current_treasury_value - ? 22 : positive_coin, ; @name donation + 0 : set, ; @name inputs + 1 : [* transaction_output], ; @name outputs + 2 : coin, ; @name fee + ? 3 : uint, ; @name ttl + ? 4 : nonempty_set, ; @name certs + ? 5 : withdrawals, ; @name withdrawals + ? 7 : auxiliary_data_hash, ; @name auxiliary_data_hash + ? 8 : uint, ; @name validity_interval_start + ? 9 : mint, ; @name mint + ? 11 : script_data_hash, ; @name script_data_hash + ? 13 : nonempty_set, ; @name collateral_inputs + ? 14 : required_signers, ; @name required_signers + ? 15 : network_id, ; @name network_id + ? 16 : transaction_output, ; @name collateral_return + ? 17 : coin, ; @name total_collateral + ? 18 : nonempty_set, ; @name reference_inputs + ? 19 : voting_procedures, ; @name voting_procedures + ? 20 : nonempty_set, ; @name proposal_procedures + ? 21 : coin, ; @name current_treasury_value + ? 22 : positive_coin, ; @name donation } -required_signers = [* ed25519_key_hash] +required_signers = nonempty_set transaction_input = [ transaction_id : transaction_hash , index : uint @@ -135,18 +135,18 @@ script = [ tag: 2, script: plutus_v2_script // ; @name plutus_v3 tag: 3, script: plutus_v3_script -] +] ; @used_as_key transaction_witness_set = { - ? 0: [* vkeywitness ], ; @name vkeywitnesses - ? 1: [* native_script ], ; @name native_scripts - ? 2: [* bootstrap_witness ], ; @name bootstrap_witnesses - ? 3: [* plutus_v1_script ], ; @name plutus_v1_scripts - ? 4: [* plutus_data ], ; @name plutus_datums - ? 5: [* redeemer ], ; @name redeemers - ? 6: [* plutus_v2_script ], ; @name plutus_v2_scripts - ? 7: [* plutus_v3_script ], ; @name plutus_v3_scripts + ? 0: nonempty_set, ; @name vkeywitnesses + ? 1: nonempty_set, ; @name native_scripts + ? 2: nonempty_set, ; @name bootstrap_witnesses + ? 3: nonempty_set, ; @name plutus_v1_scripts + ? 4: nonempty_set, ; @name plutus_datums + ? 5: redeemers, ; @name redeemers + ? 6: nonempty_set, ; @name plutus_v2_scripts + ? 7: nonempty_set, ; @name plutus_v3_scripts } native_script = diff --git a/specs/multiera/allegra/mod.cddl b/specs/multiera/allegra/mod.cddl index 9247c722..2bb9eb13 100644 --- a/specs/multiera/allegra/mod.cddl +++ b/specs/multiera/allegra/mod.cddl @@ -22,15 +22,16 @@ move_instantaneous_reward = [ ] move_instantaneous_rewards_cert = (tag: 6, move_instantaneous_reward) -allegra_certificate = - [ stake_registration - // stake_deregistration - // stake_delegation - // pool_registration - // pool_retirement - // genesis_key_delegation - // move_instantaneous_rewards_cert - ] +allegra_certificate = [ + ; @name stake_registration + shelley_stake_registration // + stake_deregistration // + stake_delegation // + pool_registration // + pool_retirement // + genesis_key_delegation // + move_instantaneous_rewards_cert +] allegra_transaction = [ body: allegra_transaction_body, diff --git a/specs/multiera/alonzo/mod.cddl b/specs/multiera/alonzo/mod.cddl index 9aab2f0f..7162fe89 100644 --- a/specs/multiera/alonzo/mod.cddl +++ b/specs/multiera/alonzo/mod.cddl @@ -75,7 +75,7 @@ alonzo_transaction_witness_set = { ? 2: [* bootstrap_witness ], ; @name bootstrap_witnesses ? 3: [* plutus_v1_script ], ; @name plutus_v1_scripts ? 4: [* plutus_data ], ; @name plutus_datums - ? 5: [* redeemer ], ; @name redeemers + ? 5: [* alonzo_redeemer ], ; @name redeemers } ; The keys to the cost model map are not present in the serialization. @@ -95,4 +95,16 @@ alonzo_format_aux_data = #6.259({ alonzo_auxiliary_data = shelley_format_aux_data ; @name shelley / shelley_ma_format_aux_data ; @name shelley_m_a - / alonzo_format_aux_data ; @name alonzo \ No newline at end of file + / alonzo_format_aux_data ; @name alonzo + +alonzo_redeemer = [ + tag: alonzo_redeemer_tag, + index: uint, + data: plutus_data, + ex_units: ex_units +] +alonzo_redeemer_tag = + 0 ; @name Spend + / 1 ; @name Mint + / 2 ; @name Cert + / 3 ; @name Reward \ No newline at end of file diff --git a/specs/multiera/babbage/mod.cddl b/specs/multiera/babbage/mod.cddl index d5cc8140..fb389d8d 100644 --- a/specs/multiera/babbage/mod.cddl +++ b/specs/multiera/babbage/mod.cddl @@ -16,7 +16,7 @@ babbage_transaction_witness_set = { ? 2: [* bootstrap_witness ], ; @name bootstrap_witnesses ? 3: [* plutus_v1_script ], ; @name plutus_v1_scripts ? 4: [* plutus_data ], ; @name plutus_datums - ? 5: [* redeemer ], ; @name redeemers + ? 5: [* alonzo_redeemer ], ; @name redeemers ? 6: [* plutus_v2_script ], ; @name plutus_v2_scripts } diff --git a/specs/multiera/cml_chain/certs.cddl b/specs/multiera/cml_chain/certs.cddl index e37c4aad..440b29ad 100644 --- a/specs/multiera/cml_chain/certs.cddl +++ b/specs/multiera/cml_chain/certs.cddl @@ -2,31 +2,18 @@ stake_credential = _CDDL_CODEGEN_EXTERN_TYPE_ ; also port, ipv4, single_host_addr, etc but these are only used by relay relay = _CDDL_CODEGEN_EXTERN_TYPE_ pool_metadata = _CDDL_CODEGEN_EXTERN_TYPE_ +single_host_addr = _CDDL_CODEGEN_EXTERN_TYPE_ ; THESE CANNOT BE EXTERN SINCE THEY ARE PLAIN GROUPS SO DELETE THEM AFTER - -stake_registration = (tag: 0, stake_credential) stake_deregistration = (tag: 1, stake_credential) stake_delegation = ( tag: 2, stake_credential, ed25519_key_hash ; @name pool ) -pool_registration = (tag: 3, pool_params) pool_retirement = ( tag: 4, ed25519_key_hash, ; @name pool epoch -) - -pool_params = ( operator: ed25519_key_hash - , vrf_keyhash: VRF_key_hash - , pledge: coin - , cost: coin - , margin: unit_interval - , reward_account: reward_account - , pool_owners: [* ed25519_key_hash] - , relays: [* relay] - , pool_metadata: pool_metadata / null - ) \ No newline at end of file +) \ No newline at end of file diff --git a/specs/multiera/cml_chain/plutus.cddl b/specs/multiera/cml_chain/plutus.cddl index 7327c624..34555f92 100644 --- a/specs/multiera/cml_chain/plutus.cddl +++ b/specs/multiera/cml_chain/plutus.cddl @@ -1,5 +1,4 @@ plutus_data = _CDDL_CODEGEN_EXTERN_TYPE_ -redeemer = _CDDL_CODEGEN_EXTERN_TYPE_ ex_units = _CDDL_CODEGEN_EXTERN_TYPE_ ex_unit_prices = _CDDL_CODEGEN_EXTERN_TYPE_ plutus_v1_script = _CDDL_CODEGEN_EXTERN_TYPE_ diff --git a/specs/multiera/shelley/mod.cddl b/specs/multiera/shelley/mod.cddl index 42cbfab0..d65dc593 100644 --- a/specs/multiera/shelley/mod.cddl +++ b/specs/multiera/shelley/mod.cddl @@ -37,14 +37,47 @@ shelley_header_body = [ protocol_version, ] +shelley_pool_registration = (tag: 3, pool_params: shelley_pool_params) +shelley_pool_params = ( operator: ed25519_key_hash + , vrf_keyhash: VRF_key_hash + , pledge: coin + , cost: coin + , margin: unit_interval + , reward_account: reward_account + , pool_owners: [* ed25519_key_hash] + , relays: [* shelley_relay] + , pool_metadata: pool_metadata / null + ) + +shelley_dns_name = tstr .size (0..64) + +shelley_single_host_name = ( + tag: 1, + port / null, + shelley_dns_name, ; An A or AAAA DNS record @name dns_name +) +shelley_multi_host_name = ( + tag: 2, + shelley_dns_name, ; A SRV DNS record @name dns_name +) + +shelley_relay = [ + single_host_addr // + ; @name single_host_name + shelley_single_host_name // + ; @name multi_host_name + shelley_multi_host_name +] + shelley_certificate = [ - stake_registration - // stake_deregistration - // stake_delegation - // pool_registration - // pool_retirement - // genesis_key_delegation - // shelley_move_instantaneous_rewards_cert + ; @name stake_registration + shelley_stake_registration // + stake_deregistration // + stake_delegation // + pool_registration // + pool_retirement // + genesis_key_delegation // + shelley_move_instantaneous_rewards_cert ] genesis_key_delegation = (tag: 5, genesis_hash, genesis_delegate_hash, VRF_key_hash) From c58b666d29e2ef0614ac08d13d4d1b52f09eaf0b Mon Sep 17 00:00:00 2001 From: rooooooooob Date: Wed, 3 Apr 2024 14:33:17 -0700 Subject: [PATCH 2/5] conway multi-era update + various fixes --- Cargo.toml | 4 +- .../rust/src/builders/certificate_builder.rs | 4 +- chain/rust/src/builders/input_builder.rs | 2 +- chain/rust/src/builders/mint_builder.rs | 2 +- chain/rust/src/builders/redeemer_builder.rs | 17 +- chain/rust/src/builders/tx_builder.rs | 57 +- chain/rust/src/builders/witness_builder.rs | 18 +- chain/rust/src/certs/cbor_encodings.rs | 2 - chain/rust/src/certs/mod.rs | 20 +- chain/rust/src/certs/serialization.rs | 93 +- chain/rust/src/crypto/hash.rs | 3 +- chain/rust/src/crypto/serialization.rs | 136 +-- chain/rust/src/deposit.rs | 6 +- chain/rust/src/governance/cbor_encodings.rs | 22 +- chain/rust/src/governance/mod.rs | 98 +- chain/rust/src/governance/serialization.rs | 488 +++++----- chain/rust/src/lib.rs | 15 +- chain/rust/src/plutus/mod.rs | 4 +- chain/rust/src/plutus/utils.rs | 61 +- chain/rust/src/transaction/mod.rs | 9 +- chain/rust/src/utils.rs | 39 +- chain/wasm/json-gen/src/lib.rs | 59 +- chain/wasm/src/certs/mod.rs | 18 +- chain/wasm/src/governance/mod.rs | 132 ++- chain/wasm/src/lib.rs | 4 + chain/wasm/src/utils.rs | 7 + multi-era/rust/src/allegra/mod.rs | 12 +- multi-era/rust/src/allegra/serialization.rs | 15 +- multi-era/rust/src/allegra/utils.rs | 6 +- multi-era/rust/src/alonzo/cbor_encodings.rs | 7 + multi-era/rust/src/alonzo/mod.rs | 52 +- multi-era/rust/src/alonzo/serialization.rs | 204 ++++- multi-era/rust/src/alonzo/utils.rs | 37 +- multi-era/rust/src/babbage/mod.rs | 13 +- multi-era/rust/src/babbage/serialization.rs | 4 +- multi-era/rust/src/babbage/utils.rs | 17 +- multi-era/rust/src/shelley/cbor_encodings.rs | 36 + multi-era/rust/src/shelley/mod.rs | 238 ++++- multi-era/rust/src/shelley/serialization.rs | 853 +++++++++++++++++- multi-era/rust/src/shelley/utils.rs | 62 +- multi-era/rust/src/utils.rs | 76 +- multi-era/wasm/json-gen/src/lib.rs | 35 +- multi-era/wasm/src/allegra/mod.rs | 26 +- multi-era/wasm/src/alonzo/mod.rs | 49 +- multi-era/wasm/src/babbage/mod.rs | 13 +- multi-era/wasm/src/lib.rs | 17 +- multi-era/wasm/src/shelley/mod.rs | 297 +++++- multi-era/wasm/src/utils.rs | 13 +- specs/conway/certs.cddl | 6 +- specs/conway/crypto.cddl | 2 +- specs/conway/governance.cddl | 14 +- specs/multiera/allegra/mod.cddl | 5 +- specs/multiera/cml_chain/certs.cddl | 11 +- specs/multiera/cml_chain/mod.cddl | 1 + specs/multiera/shelley/mod.cddl | 9 +- 55 files changed, 2565 insertions(+), 885 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 023a16b3..d2a4d61a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,9 @@ members = [ # exclude old crate structure to avoid error in it exclude = [ "rust", - "rust/json-gen" + "rust/json-gen", + "tools/metadata-cddl-checker", + "tools/plutus-datum-codegen" ] [profile.release] diff --git a/chain/rust/src/builders/certificate_builder.rs b/chain/rust/src/builders/certificate_builder.rs index 2d2aadf3..f20701e1 100644 --- a/chain/rust/src/builders/certificate_builder.rs +++ b/chain/rust/src/builders/certificate_builder.rs @@ -35,7 +35,7 @@ pub fn cert_required_wits(cert: &Certificate, required_witnesses: &mut RequiredW required_witnesses.add_from_credential(cert.stake_credential.clone()); } Certificate::PoolRegistration(cert) => { - for owner in &cert.pool_params.pool_owners { + for owner in cert.pool_params.pool_owners.as_ref() { required_witnesses.add_vkey_key_hash(*owner); } required_witnesses.add_vkey_key_hash(cert.pool_params.operator); @@ -108,7 +108,7 @@ pub fn add_cert_vkeys( } }, Certificate::PoolRegistration(cert) => { - for owner in &cert.pool_params.pool_owners { + for owner in cert.pool_params.pool_owners.as_ref() { vkeys.insert(*owner); } vkeys.insert(cert.pool_params.operator); diff --git a/chain/rust/src/builders/input_builder.rs b/chain/rust/src/builders/input_builder.rs index b2b659a5..5687f097 100644 --- a/chain/rust/src/builders/input_builder.rs +++ b/chain/rust/src/builders/input_builder.rs @@ -11,7 +11,7 @@ use crate::{ crypto::hash::hash_plutus_data, plutus::PlutusData, transaction::{TransactionInput, TransactionOutput}, - NativeScript, RequiredSigners + NativeScript, RequiredSigners, }; #[derive(Debug, thiserror::Error)] diff --git a/chain/rust/src/builders/mint_builder.rs b/chain/rust/src/builders/mint_builder.rs index 4446116f..53e88127 100644 --- a/chain/rust/src/builders/mint_builder.rs +++ b/chain/rust/src/builders/mint_builder.rs @@ -4,7 +4,7 @@ use super::witness_builder::{NativeScriptWitnessInfo, RequiredWitnessSet}; use cml_core::ordered_hash_map::OrderedHashMap; -use crate::{assets::AssetName, RequiredSigners, NativeScript, PolicyId}; +use crate::{assets::AssetName, NativeScript, PolicyId, RequiredSigners}; #[derive(Clone)] pub struct MintBuilderResult { diff --git a/chain/rust/src/builders/redeemer_builder.rs b/chain/rust/src/builders/redeemer_builder.rs index 335bdf58..d83e15ad 100644 --- a/chain/rust/src/builders/redeemer_builder.rs +++ b/chain/rust/src/builders/redeemer_builder.rs @@ -142,8 +142,12 @@ impl RedeemerSetBuilder { ex_units, ))); } - RedeemerTag::Proposing => todo!("https://github.com/dcSpark/cardano-multiplatform-lib/issues/323"), - RedeemerTag::Voting => todo!("https://github.com/dcSpark/cardano-multiplatform-lib/issues/323"), + RedeemerTag::Proposing => { + todo!("https://github.com/dcSpark/cardano-multiplatform-lib/issues/323") + } + RedeemerTag::Voting => { + todo!("https://github.com/dcSpark/cardano-multiplatform-lib/issues/323") + } } } @@ -213,10 +217,7 @@ impl RedeemerSetBuilder { } } - pub fn build( - &self, - default_to_dummy_exunits: bool, - ) -> Result { + pub fn build(&self, default_to_dummy_exunits: bool) -> Result { let mut redeemers = Vec::new(); // Calling iter on a BTreeMap returns a list of sorted keys self.remove_placeholders_and_tag( @@ -336,7 +337,7 @@ mod tests { } }; let missing_signers = vec![fake_raw_key_public(0).hash()]; - InputAggregateWitnessData::PlutusScript(witness, missing_signers, None) + InputAggregateWitnessData::PlutusScript(witness, missing_signers.into(), None) }; let address = Address::from_bech32("addr1qxeqxcja25k8q05evyngf4f88xn89asl54x2zg3ephgj26ndyt5qk02xmmras5pe9jz2c7tc93wu4c96rqwvg6e2v50qlpmx70").unwrap(); @@ -373,7 +374,7 @@ mod tests { ExUnits::new(10, 10), ); - let redeemers = builder.build(false).unwrap(); + let redeemers = builder.build(false).unwrap().to_flat_format(); assert_eq!(redeemers.len(), 1); diff --git a/chain/rust/src/builders/tx_builder.rs b/chain/rust/src/builders/tx_builder.rs index b2633a62..f016f8a4 100644 --- a/chain/rust/src/builders/tx_builder.rs +++ b/chain/rust/src/builders/tx_builder.rs @@ -22,8 +22,8 @@ use crate::crypto::{BootstrapWitness, Vkeywitness}; use crate::deposit::{internal_get_deposit, internal_get_implicit_input}; use crate::fees::LinearFee; use crate::min_ada::min_ada_required; -use crate::plutus::{PlutusData, Redeemers}; use crate::plutus::{CostModels, ExUnits, Language}; +use crate::plutus::{PlutusData, Redeemers}; use crate::transaction::{ DatumOption, ScriptRef, Transaction, TransactionBody, TransactionInput, TransactionOutput, TransactionWitnessSet, @@ -1210,7 +1210,11 @@ impl TransactionBuilder { }); calc_script_data_hash( &redeemers, - &self.witness_builders.witness_set_builder.get_plutus_datum().into(), + &self + .witness_builders + .witness_set_builder + .get_plutus_datum() + .into(), &self.config.cost_models, &languages.iter().copied().collect::>(), None, @@ -1234,10 +1238,13 @@ impl TransactionBuilder { validity_interval_start: self.validity_start_interval, mint: self.mint.clone(), script_data_hash, - collateral_inputs: self - .collateral - .as_ref() - .map(|collateral| collateral.iter().map(|c| c.input.clone()).collect::>().into()), + collateral_inputs: self.collateral.as_ref().map(|collateral| { + collateral + .iter() + .map(|c| c.input.clone()) + .collect::>() + .into() + }), required_signers: self .required_signers .as_ref() @@ -1245,10 +1252,13 @@ impl TransactionBuilder { network_id: self.network_id, collateral_return: self.collateral_return.clone(), total_collateral: self.calc_collateral_total()?, - reference_inputs: self - .reference_inputs - .as_ref() - .map(|inputs| inputs.iter().map(|utxo| utxo.input.clone()).collect::>().into()), + reference_inputs: self.reference_inputs.as_ref().map(|inputs| { + inputs + .iter() + .map(|utxo| utxo.input.clone()) + .collect::>() + .into() + }), voting_procedures: None, proposal_procedures: None, current_treasury_value: None, @@ -4081,14 +4091,19 @@ mod tests { let mut witness_set = TransactionWitnessSet::new(); - witness_set.vkeywitnesses = Some(vec![make_vkey_witness( - &hash_transaction(&body), - &PrivateKey::from_normal_bytes( - &hex::decode("c660e50315d76a53d80732efda7630cae8885dfb85c46378684b3c6103e1284a") + witness_set.vkeywitnesses = Some( + vec![make_vkey_witness( + &hash_transaction(&body), + &PrivateKey::from_normal_bytes( + &hex::decode( + "c660e50315d76a53d80732efda7630cae8885dfb85c46378684b3c6103e1284a", + ) .unwrap(), - ) - .unwrap(), - )]); + ) + .unwrap(), + )] + .into(), + ); let final_tx = Transaction::new(body, witness_set, true, None); let deser_t = Transaction::from_cbor_bytes(&final_tx.to_cbor_bytes()).unwrap(); @@ -5125,7 +5140,7 @@ mod tests { ), PlutusData::from_cbor_bytes(&hex::decode("D866820380").unwrap()).unwrap(), ), - required_signers, + required_signers.into(), PlutusData::from_cbor_bytes(&hex::decode("d866820181d866820083581c5627217786eb781fbfb51911a253f4d250fdbfdcf1198e70d35985a9443330353301").unwrap()).unwrap() ).unwrap()).unwrap(); } @@ -5273,7 +5288,7 @@ mod tests { ), PlutusData::from_cbor_bytes(&hex::decode("D866820380").unwrap()).unwrap(), ), - required_signers, + required_signers.into(), PlutusData::from_cbor_bytes(&hex::decode("d866820181d866820083581c5627217786eb781fbfb51911a253f4d250fdbfdcf1198e70d35985a9443330353301").unwrap()).unwrap() ).unwrap()).unwrap(); } @@ -5451,7 +5466,7 @@ mod tests { ), PlutusData::from_cbor_bytes(&hex::decode("D866820380").unwrap()).unwrap(), ), - required_signers, + required_signers.into(), PlutusData::from_cbor_bytes(&hex::decode("d866820181d866820083581c5627217786eb781fbfb51911a253f4d250fdbfdcf1198e70d35985a9443330353301").unwrap()).unwrap() ).unwrap()).unwrap(); } @@ -5709,7 +5724,7 @@ mod tests { PlutusScriptWitness::from(script_hash), PlutusData::new_bytes(vec![]), ), - vec![], + vec![].into(), PlutusData::from_cbor_bytes(&hex::decode("D866820380").unwrap()).unwrap(), ) .unwrap() diff --git a/chain/rust/src/builders/witness_builder.rs b/chain/rust/src/builders/witness_builder.rs index e9a28950..3baebe67 100644 --- a/chain/rust/src/builders/witness_builder.rs +++ b/chain/rust/src/builders/witness_builder.rs @@ -5,7 +5,12 @@ use std::{ }; use crate::{ - byron::ByronAddress, certs::Credential, crypto::{hash::hash_plutus_data, BootstrapWitness, Vkey, Vkeywitness}, plutus::{LegacyRedeemer, PlutusData, PlutusScript, PlutusV1Script, PlutusV2Script, Redeemers}, transaction::TransactionWitnessSet, NativeScript, RequiredSigners, Script + byron::ByronAddress, + certs::Credential, + crypto::{hash::hash_plutus_data, BootstrapWitness, Vkey, Vkeywitness}, + plutus::{LegacyRedeemer, PlutusData, PlutusScript, PlutusV1Script, PlutusV2Script, Redeemers}, + transaction::TransactionWitnessSet, + NativeScript, RequiredSigners, Script, }; use cml_crypto::{ DatumHash, Ed25519KeyHash, Ed25519Signature, PublicKey, RawBytesEncoding, ScriptHash, @@ -411,7 +416,8 @@ impl TransactionWitnessSetBuilder { } if !self.bootstraps.is_empty() { - result.bootstrap_witnesses = Some(self.bootstraps.into_values().collect::>().into()); + result.bootstrap_witnesses = + Some(self.bootstraps.into_values().collect::>().into()); } if !native_scripts.is_empty() { @@ -431,7 +437,9 @@ impl TransactionWitnessSetBuilder { } if !self.redeemers.is_empty() { - result.redeemers = Some(Redeemers::new_arr_legacy_redeemer(self.redeemers.values().cloned().collect::>())); + result.redeemers = Some(Redeemers::new_arr_legacy_redeemer( + self.redeemers.values().cloned().collect::>(), + )); } result @@ -624,7 +632,7 @@ mod tests { } }; let missing_signers = vec![fake_raw_key_public(0).hash()]; - InputAggregateWitnessData::PlutusScript(witness, missing_signers, None) + InputAggregateWitnessData::PlutusScript(witness, missing_signers.into(), None) }; assert_eq!(required_wits.vkeys.len(), 0); @@ -648,7 +656,7 @@ mod tests { } }; let missing_signers = vec![hash]; - InputAggregateWitnessData::PlutusScript(witness, missing_signers, None) + InputAggregateWitnessData::PlutusScript(witness, missing_signers.into(), None) }; assert_eq!(required_wits.vkeys.len(), 1); diff --git a/chain/rust/src/certs/cbor_encodings.rs b/chain/rust/src/certs/cbor_encodings.rs index fe2fcbe5..f902ce73 100644 --- a/chain/rust/src/certs/cbor_encodings.rs +++ b/chain/rust/src/certs/cbor_encodings.rs @@ -43,8 +43,6 @@ pub struct PoolParamsEncoding { pub vrf_keyhash_encoding: StringEncoding, pub pledge_encoding: Option, pub cost_encoding: Option, - pub pool_owners_encoding: LenEncoding, - pub pool_owners_elem_encodings: Vec, pub relays_encoding: LenEncoding, } diff --git a/chain/rust/src/certs/mod.rs b/chain/rust/src/certs/mod.rs index 3afe023a..e81693e5 100644 --- a/chain/rust/src/certs/mod.rs +++ b/chain/rust/src/certs/mod.rs @@ -5,7 +5,7 @@ pub mod cbor_encodings; pub mod serialization; pub mod utils; -use super::{Coin, Epoch, Port, UnitInterval}; +use super::{Coin, Epoch, Port, SetEd25519KeyHash, UnitInterval}; use crate::address::RewardAccount; use crate::crypto::{Ed25519KeyHash, PoolMetadataHash, ScriptHash, VRFKeyHash}; use crate::governance::Anchor; @@ -152,8 +152,12 @@ impl Certificate { pub fn new_resign_committee_cold_cert( committee_cold_credential: CommitteeColdCredential, + anchor: Option, ) -> Self { - Self::ResignCommitteeColdCert(ResignCommitteeColdCert::new(committee_cold_credential)) + Self::ResignCommitteeColdCert(ResignCommitteeColdCert::new( + committee_cold_credential, + anchor, + )) } pub fn new_reg_drep_cert( @@ -534,7 +538,7 @@ pub struct PoolParams { pub cost: Coin, pub margin: UnitInterval, pub reward_account: RewardAccount, - pub pool_owners: Vec, + pub pool_owners: SetEd25519KeyHash, pub relays: Vec, pub pool_metadata: Option, #[serde(skip)] @@ -550,7 +554,7 @@ impl PoolParams { cost: Coin, margin: UnitInterval, reward_account: RewardAccount, - pool_owners: Vec, + pool_owners: SetEd25519KeyHash, relays: Vec, pool_metadata: Option, ) -> Self { @@ -669,14 +673,16 @@ impl Relay { #[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] pub struct ResignCommitteeColdCert { pub committee_cold_credential: CommitteeColdCredential, + pub anchor: Option, #[serde(skip)] pub encodings: Option, } impl ResignCommitteeColdCert { - pub fn new(committee_cold_credential: CommitteeColdCredential) -> Self { + pub fn new(committee_cold_credential: CommitteeColdCredential, anchor: Option) -> Self { Self { committee_cold_credential, + anchor, encodings: None, } } @@ -917,13 +923,13 @@ impl Url { } pub fn new(inner: String) -> Result { - if inner.len() > 64 { + if inner.len() > 128 { return Err(DeserializeError::new( "Url", DeserializeFailure::RangeCheck { found: inner.len() as isize, min: Some(0), - max: Some(64), + max: Some(128), }, )); } diff --git a/chain/rust/src/certs/serialization.rs b/chain/rust/src/certs/serialization.rs index 4d834461..17cb8f13 100644 --- a/chain/rust/src/certs/serialization.rs +++ b/chain/rust/src/certs/serialization.rs @@ -491,7 +491,7 @@ impl Deserialize for Certificate { }; let deser_variant = (|raw: &mut Deserializer<_>| -> Result<_, DeserializeError> { let mut read_len = CBORReadLen::new(len); - read_len.read_elems(2)?; + read_len.read_elems(3)?; read_len.finish()?; let ret = ResignCommitteeColdCert::deserialize_as_embedded_group(raw, &mut read_len, len); @@ -1358,31 +1358,7 @@ impl SerializeEmbeddedGroup for PoolParams { )?; self.margin.serialize(serializer, force_canonical)?; self.reward_account.serialize(serializer, force_canonical)?; - serializer.write_array_sz( - self.encodings - .as_ref() - .map(|encs| encs.pool_owners_encoding) - .unwrap_or_default() - .to_len_sz(self.pool_owners.len() as u64, force_canonical), - )?; - for (i, element) in self.pool_owners.iter().enumerate() { - let pool_owners_elem_encoding = self - .encodings - .as_ref() - .and_then(|encs| encs.pool_owners_elem_encodings.get(i)) - .cloned() - .unwrap_or_default(); - serializer.write_bytes_sz( - element.to_raw_bytes(), - pool_owners_elem_encoding - .to_str_len_sz(element.to_raw_bytes().len() as u64, force_canonical), - )?; - } - self.encodings - .as_ref() - .map(|encs| encs.pool_owners_encoding) - .unwrap_or_default() - .end(serializer, force_canonical)?; + self.pool_owners.serialize(serializer, force_canonical)?; serializer.write_array_sz( self.encodings .as_ref() @@ -1468,40 +1444,8 @@ impl DeserializeEmbeddedGroup for PoolParams { .map_err(|e: DeserializeError| e.annotate("margin"))?; let reward_account = RewardAccount::deserialize(raw) .map_err(|e: DeserializeError| e.annotate("reward_account"))?; - let (pool_owners, pool_owners_encoding, pool_owners_elem_encodings) = - (|| -> Result<_, DeserializeError> { - let mut pool_owners_arr = Vec::new(); - let len = raw.array_sz()?; - let pool_owners_encoding = len.into(); - let mut pool_owners_elem_encodings = Vec::new(); - while match len { - cbor_event::LenSz::Len(n, _) => (pool_owners_arr.len() as u64) < n, - cbor_event::LenSz::Indefinite => true, - } { - if raw.cbor_type()? == cbor_event::Type::Special { - assert_eq!(raw.special()?, cbor_event::Special::Break); - break; - } - let (pool_owners_elem, pool_owners_elem_encoding) = raw - .bytes_sz() - .map_err(Into::::into) - .and_then(|(bytes, enc)| { - Ed25519KeyHash::from_raw_bytes(&bytes) - .map(|bytes| (bytes, StringEncoding::from(enc))) - .map_err(|e| { - DeserializeFailure::InvalidStructure(Box::new(e)).into() - }) - })?; - pool_owners_arr.push(pool_owners_elem); - pool_owners_elem_encodings.push(pool_owners_elem_encoding); - } - Ok(( - pool_owners_arr, - pool_owners_encoding, - pool_owners_elem_encodings, - )) - })() - .map_err(|e| e.annotate("pool_owners"))?; + let pool_owners = SetEd25519KeyHash::deserialize(raw) + .map_err(|e: DeserializeError| e.annotate("pool_owners"))?; let (relays, relays_encoding) = (|| -> Result<_, DeserializeError> { let mut relays_arr = Vec::new(); let len = raw.array_sz()?; @@ -1547,8 +1491,6 @@ impl DeserializeEmbeddedGroup for PoolParams { vrf_keyhash_encoding, pledge_encoding, cost_encoding, - pool_owners_encoding, - pool_owners_elem_encodings, relays_encoding, }), }) @@ -2141,7 +2083,7 @@ impl Serialize for ResignCommitteeColdCert { .as_ref() .map(|encs| encs.len_encoding) .unwrap_or_default() - .to_len_sz(2, force_canonical), + .to_len_sz(3, force_canonical), )?; self.serialize_as_embedded_group(serializer, force_canonical) } @@ -2166,6 +2108,10 @@ impl SerializeEmbeddedGroup for ResignCommitteeColdCert { )?; self.committee_cold_credential .serialize(serializer, force_canonical)?; + match &self.anchor { + Some(x) => x.serialize(serializer, force_canonical), + None => serializer.write_special(cbor_event::Special::Null), + }?; self.encodings .as_ref() .map(|encs| encs.len_encoding) @@ -2178,7 +2124,7 @@ impl Deserialize for ResignCommitteeColdCert { fn deserialize(raw: &mut Deserializer) -> Result { let len = raw.array_sz()?; let mut read_len = CBORReadLen::new(len); - read_len.read_elems(2)?; + read_len.read_elems(3)?; read_len.finish()?; let ret = Self::deserialize_as_embedded_group(raw, &mut read_len, len); match len { @@ -2214,8 +2160,21 @@ impl DeserializeEmbeddedGroup for ResignCommitteeColdCert { .map_err(|e| e.annotate("index_0"))?; let committee_cold_credential = Credential::deserialize(raw) .map_err(|e: DeserializeError| e.annotate("committee_cold_credential"))?; + let anchor = (|| -> Result<_, DeserializeError> { + Ok(match raw.cbor_type()? != cbor_event::Type::Special { + true => Some(Anchor::deserialize(raw)?), + false => { + if raw.special()? != cbor_event::Special::Null { + return Err(DeserializeFailure::ExpectedNull.into()); + } + None + } + }) + })() + .map_err(|e| e.annotate("anchor"))?; Ok(ResignCommitteeColdCert { committee_cold_credential, + anchor, encodings: Some(ResignCommitteeColdCertEncoding { len_encoding, index_0_encoding, @@ -3569,13 +3528,13 @@ impl Deserialize for Url { let (inner, inner_encoding) = raw .text_sz() .map(|(s, enc)| (s, StringEncoding::from(enc)))?; - if inner.len() > 64 { + if inner.len() > 128 { return Err(DeserializeError::new( "Url", DeserializeFailure::RangeCheck { found: inner.len() as isize, min: Some(0), - max: Some(64), + max: Some(128), }, )); } @@ -3786,8 +3745,8 @@ impl DeserializeEmbeddedGroup for VoteRegDelegCert { DRep::deserialize(raw).map_err(|e: DeserializeError| e.annotate("d_rep"))?; let (coin, coin_encoding) = raw .unsigned_integer_sz() - .map(|(x, enc)| (x, Some(enc))) .map_err(Into::::into) + .map(|(x, enc)| (x, Some(enc))) .map_err(|e: DeserializeError| e.annotate("coin"))?; Ok(VoteRegDelegCert { stake_credential, diff --git a/chain/rust/src/crypto/hash.rs b/chain/rust/src/crypto/hash.rs index f848a4f1..d07f6e03 100644 --- a/chain/rust/src/crypto/hash.rs +++ b/chain/rust/src/crypto/hash.rs @@ -9,7 +9,8 @@ use crate::{ plutus::{CostModels, Language, PlutusData, Redeemers}, transaction::{ cbor_encodings::TransactionWitnessSetEncoding, TransactionBody, TransactionWitnessSet, - }, NonemptySetPlutusData, + }, + NonemptySetPlutusData, }; pub fn hash_auxiliary_data(auxiliary_data: &AuxiliaryData) -> AuxiliaryDataHash { diff --git a/chain/rust/src/crypto/serialization.rs b/chain/rust/src/crypto/serialization.rs index c276f6e1..bb8229f0 100644 --- a/chain/rust/src/crypto/serialization.rs +++ b/chain/rust/src/crypto/serialization.rs @@ -9,7 +9,7 @@ use cbor_event::se::Serializer; use cml_core::error::*; use cml_core::serialization::*; use cml_crypto::RawBytesEncoding; -use std::io::{BufRead, Seek, Write}; +use std::io::{BufRead, Seek, SeekFrom, Write}; impl Serialize for BootstrapWitness { fn serialize<'se, W: Write>( @@ -230,68 +230,96 @@ impl Deserialize for Nonce { (|| -> Result<_, DeserializeError> { let len = raw.array_sz()?; let len_encoding: LenEncoding = len.into(); - match raw.cbor_type()? { - cbor_event::Type::UnsignedInteger => { - let (identity_value, identity_encoding) = raw.unsigned_integer_sz()?; - if identity_value != 0 { - return Err(DeserializeFailure::FixedValueMismatch { - found: Key::Uint(identity_value), - expected: Key::Uint(0), - } - .into()); + let initial_position = raw.as_mut_ref().stream_position().unwrap(); + let mut errs = Vec::new(); + let deser_variant = (|raw: &mut Deserializer<_>| -> Result<_, DeserializeError> { + let mut read_len = CBORReadLen::new(len); + read_len.read_elems(1)?; + read_len.finish()?; + let (identity_value, identity_encoding) = raw.unsigned_integer_sz()?; + if identity_value != 0 { + return Err(DeserializeFailure::FixedValueMismatch { + found: Key::Uint(identity_value), + expected: Key::Uint(0), } - let identity_encoding = Some(identity_encoding); - Ok(Self::Identity { + .into()); + } + let ret = Ok(Some(identity_encoding)); + match len { + cbor_event::LenSz::Len(_, _) => (), + cbor_event::LenSz::Indefinite => match raw.special()? { + cbor_event::Special::Break => (), + _ => return Err(DeserializeFailure::EndingBreakMissing.into()), + }, + } + ret + })(raw); + match deser_variant { + Ok(identity_encoding) => { + return Ok(Self::Identity { identity_encoding, len_encoding, }) } - cbor_event::Type::Array => { - let mut read_len = CBORReadLen::new(len); - read_len.read_elems(2)?; - read_len.finish()?; - let tag_encoding = (|| -> Result<_, DeserializeError> { - let (tag_value, tag_encoding) = raw.unsigned_integer_sz()?; - if tag_value != 1 { - return Err(DeserializeFailure::FixedValueMismatch { - found: Key::Uint(tag_value), - expected: Key::Uint(1), - } - .into()); + Err(e) => { + errs.push(e.annotate("Identity")); + raw.as_mut_ref() + .seek(SeekFrom::Start(initial_position)) + .unwrap(); + } + }; + let variant_deser = (|raw: &mut Deserializer<_>| -> Result<_, DeserializeError> { + let mut read_len = CBORReadLen::new(len); + read_len.read_elems(2)?; + read_len.finish()?; + let tag_encoding = (|| -> Result<_, DeserializeError> { + let (tag_value, tag_encoding) = raw.unsigned_integer_sz()?; + if tag_value != 1 { + return Err(DeserializeFailure::FixedValueMismatch { + found: Key::Uint(tag_value), + expected: Key::Uint(1), } - Ok(Some(tag_encoding)) - })() - .map_err(|e| e.annotate("tag"))?; - let (hash, hash_encoding) = raw - .bytes_sz() - .map_err(Into::::into) - .and_then(|(bytes, enc)| { - NonceHash::from_raw_bytes(&bytes) - .map(|bytes| (bytes, StringEncoding::from(enc))) - .map_err(|e| { - DeserializeFailure::InvalidStructure(Box::new(e)).into() - }) - }) - .map_err(|e: DeserializeError| e.annotate("hash"))?; - match len { - cbor_event::LenSz::Len(_, _) => (), - cbor_event::LenSz::Indefinite => match raw.special()? { - cbor_event::Special::Break => (), - _ => return Err(DeserializeFailure::EndingBreakMissing.into()), - }, + .into()); } - Ok(Self::Hash { - hash, - len_encoding, - tag_encoding, - hash_encoding, + Ok(Some(tag_encoding)) + })() + .map_err(|e| e.annotate("tag"))?; + let (hash, hash_encoding) = raw + .bytes_sz() + .map_err(Into::::into) + .and_then(|(bytes, enc)| { + NonceHash::from_raw_bytes(&bytes) + .map(|bytes| (bytes, StringEncoding::from(enc))) + .map_err(|e| DeserializeFailure::InvalidStructure(Box::new(e)).into()) }) + .map_err(|e: DeserializeError| e.annotate("hash"))?; + match len { + cbor_event::LenSz::Len(_, _) => (), + cbor_event::LenSz::Indefinite => match raw.special()? { + cbor_event::Special::Break => (), + _ => return Err(DeserializeFailure::EndingBreakMissing.into()), + }, } - _ => Err(DeserializeError::new( - "Nonce", - DeserializeFailure::NoVariantMatched, - )), - } + Ok(Self::Hash { + hash, + len_encoding, + tag_encoding, + hash_encoding, + }) + })(raw); + match variant_deser { + Ok(variant) => return Ok(variant), + Err(e) => { + errs.push(e.annotate("Hash")); + raw.as_mut_ref() + .seek(SeekFrom::Start(initial_position)) + .unwrap(); + } + }; + Err(DeserializeError::new( + "Nonce", + DeserializeFailure::NoVariantMatchedWithCauses(errs), + )) })() .map_err(|e| e.annotate("Nonce")) } diff --git a/chain/rust/src/deposit.rs b/chain/rust/src/deposit.rs index b68ada99..3e40b394 100644 --- a/chain/rust/src/deposit.rs +++ b/chain/rust/src/deposit.rs @@ -73,5 +73,9 @@ pub fn get_deposit( pool_deposit: Coin, // // protocol parameter key_deposit: Coin, // protocol parameter ) -> Result { - internal_get_deposit(txbody.certs.as_ref().map(|certs| certs.as_ref()), pool_deposit, key_deposit) + internal_get_deposit( + txbody.certs.as_ref().map(|certs| certs.as_ref()), + pool_deposit, + key_deposit, + ) } diff --git a/chain/rust/src/governance/cbor_encodings.rs b/chain/rust/src/governance/cbor_encodings.rs index 189cb279..8a7bd177 100644 --- a/chain/rust/src/governance/cbor_encodings.rs +++ b/chain/rust/src/governance/cbor_encodings.rs @@ -12,13 +12,6 @@ pub struct AnchorEncoding { pub anchor_doc_hash_encoding: StringEncoding, } -#[derive(Clone, Debug, Default)] -pub struct CommitteeEncoding { - pub len_encoding: LenEncoding, - pub credentials_encoding: LenEncoding, - pub credentials_value_encodings: BTreeMap>, -} - #[derive(Clone, Debug, Default)] pub struct ConstitutionEncoding { pub len_encoding: LenEncoding, @@ -38,13 +31,6 @@ pub struct HardForkInitiationActionEncoding { pub tag_encoding: Option, } -#[derive(Clone, Debug, Default)] -pub struct NewCommitteeEncoding { - pub len_encoding: LenEncoding, - pub tag_encoding: Option, - pub cold_credentials_encoding: LenEncoding, -} - #[derive(Clone, Debug, Default)] pub struct NewConstitutionEncoding { pub len_encoding: LenEncoding, @@ -79,6 +65,14 @@ pub struct TreasuryWithdrawalsActionEncoding { pub policy_hash_encoding: StringEncoding, } +#[derive(Clone, Debug, Default)] +pub struct UpdateCommitteeEncoding { + pub len_encoding: LenEncoding, + pub tag_encoding: Option, + pub credentials_encoding: LenEncoding, + pub credentials_value_encodings: BTreeMap>, +} + #[derive(Clone, Debug, Default)] pub struct VotingProcedureEncoding { pub len_encoding: LenEncoding, diff --git a/chain/rust/src/governance/mod.rs b/chain/rust/src/governance/mod.rs index d46bedb0..62417925 100644 --- a/chain/rust/src/governance/mod.rs +++ b/chain/rust/src/governance/mod.rs @@ -9,12 +9,12 @@ use crate::assets::Coin; use crate::block::ProtocolVersion; use crate::certs::{CommitteeColdCredential, Url}; use crate::crypto::{AnchorDocHash, Ed25519KeyHash, ScriptHash, TransactionHash}; -use crate::{Epoch, ProtocolParamUpdate, UnitInterval}; +use crate::{Epoch, ProtocolParamUpdate, SetCommitteeColdCredential, UnitInterval}; use cbor_encodings::{ - AnchorEncoding, CommitteeEncoding, ConstitutionEncoding, GovActionIdEncoding, - HardForkInitiationActionEncoding, NewCommitteeEncoding, NewConstitutionEncoding, - NoConfidenceEncoding, ParameterChangeActionEncoding, ProposalProcedureEncoding, - TreasuryWithdrawalsActionEncoding, VotingProcedureEncoding, + AnchorEncoding, ConstitutionEncoding, GovActionIdEncoding, HardForkInitiationActionEncoding, + NewConstitutionEncoding, NoConfidenceEncoding, ParameterChangeActionEncoding, + ProposalProcedureEncoding, TreasuryWithdrawalsActionEncoding, UpdateCommitteeEncoding, + VotingProcedureEncoding, }; use cml_core::ordered_hash_map::OrderedHashMap; @@ -39,27 +39,6 @@ impl Anchor { } } -#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] -pub struct Committee { - pub credentials: OrderedHashMap, - pub unit_interval: UnitInterval, - #[serde(skip)] - pub encodings: Option, -} - -impl Committee { - pub fn new( - credentials: OrderedHashMap, - unit_interval: UnitInterval, - ) -> Self { - Self { - credentials, - unit_interval, - encodings: None, - } - } -} - #[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] pub struct Constitution { pub anchor: Anchor, @@ -85,7 +64,7 @@ pub enum GovAction { HardForkInitiationAction(HardForkInitiationAction), TreasuryWithdrawalsAction(TreasuryWithdrawalsAction), NoConfidence(NoConfidence), - NewCommittee(NewCommittee), + UpdateCommittee(UpdateCommittee), NewConstitution(NewConstitution), InfoAction { #[serde(skip)] @@ -126,12 +105,18 @@ impl GovAction { Self::NoConfidence(NoConfidence::new(action_id)) } - pub fn new_new_committee( + pub fn new_update_committee( action_id: Option, - cold_credentials: Vec, - committee: Committee, + cold_credentials: SetCommitteeColdCredential, + credentials: OrderedHashMap, + unit_interval: UnitInterval, ) -> Self { - Self::NewCommittee(NewCommittee::new(action_id, cold_credentials, committee)) + Self::UpdateCommittee(UpdateCommittee::new( + action_id, + cold_credentials, + credentials, + unit_interval, + )) } pub fn new_new_constitution( @@ -194,30 +179,6 @@ impl HardForkInitiationAction { } } -#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] -pub struct NewCommittee { - pub action_id: Option, - pub cold_credentials: Vec, - pub committee: Committee, - #[serde(skip)] - pub encodings: Option, -} - -impl NewCommittee { - pub fn new( - action_id: Option, - cold_credentials: Vec, - committee: Committee, - ) -> Self { - Self { - action_id, - cold_credentials, - committee, - encodings: None, - } - } -} - #[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] pub struct NewConstitution { pub action_id: Option, @@ -324,6 +285,33 @@ impl TreasuryWithdrawalsAction { } } +#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] +pub struct UpdateCommittee { + pub action_id: Option, + pub cold_credentials: SetCommitteeColdCredential, + pub credentials: OrderedHashMap, + pub unit_interval: UnitInterval, + #[serde(skip)] + pub encodings: Option, +} + +impl UpdateCommittee { + pub fn new( + action_id: Option, + cold_credentials: SetCommitteeColdCredential, + credentials: OrderedHashMap, + unit_interval: UnitInterval, + ) -> Self { + Self { + action_id, + cold_credentials, + credentials, + unit_interval, + encodings: None, + } + } +} + #[derive( Copy, Eq, diff --git a/chain/rust/src/governance/serialization.rs b/chain/rust/src/governance/serialization.rs index cfdbed65..dddc9f01 100644 --- a/chain/rust/src/governance/serialization.rs +++ b/chain/rust/src/governance/serialization.rs @@ -85,137 +85,6 @@ impl Deserialize for Anchor { } } -impl Serialize for Committee { - fn serialize<'se, W: Write>( - &self, - serializer: &'se mut Serializer, - force_canonical: bool, - ) -> cbor_event::Result<&'se mut Serializer> { - serializer.write_array_sz( - self.encodings - .as_ref() - .map(|encs| encs.len_encoding) - .unwrap_or_default() - .to_len_sz(2, force_canonical), - )?; - serializer.write_map_sz( - self.encodings - .as_ref() - .map(|encs| encs.credentials_encoding) - .unwrap_or_default() - .to_len_sz(self.credentials.len() as u64, force_canonical), - )?; - let mut key_order = self - .credentials - .iter() - .map(|(k, v)| { - let mut buf = cbor_event::se::Serializer::new_vec(); - k.serialize(&mut buf, force_canonical)?; - Ok((buf.finalize(), k, v)) - }) - .collect::, &_, &_)>, cbor_event::Error>>()?; - if force_canonical { - key_order.sort_by(|(lhs_bytes, _, _), (rhs_bytes, _, _)| { - match lhs_bytes.len().cmp(&rhs_bytes.len()) { - std::cmp::Ordering::Equal => lhs_bytes.cmp(rhs_bytes), - diff_ord => diff_ord, - } - }); - } - for (key_bytes, key, value) in key_order { - serializer.write_raw_bytes(&key_bytes)?; - let credentials_value_encoding = self - .encodings - .as_ref() - .and_then(|encs| encs.credentials_value_encodings.get(key)) - .cloned() - .unwrap_or_default(); - serializer.write_unsigned_integer_sz( - *value, - fit_sz(*value, credentials_value_encoding, force_canonical), - )?; - } - self.encodings - .as_ref() - .map(|encs| encs.credentials_encoding) - .unwrap_or_default() - .end(serializer, force_canonical)?; - self.unit_interval.serialize(serializer, force_canonical)?; - self.encodings - .as_ref() - .map(|encs| encs.len_encoding) - .unwrap_or_default() - .end(serializer, force_canonical) - } -} - -impl Deserialize for Committee { - fn deserialize(raw: &mut Deserializer) -> Result { - let len = raw.array_sz()?; - let len_encoding: LenEncoding = len.into(); - let mut read_len = CBORReadLen::new(len); - read_len.read_elems(2)?; - read_len.finish()?; - (|| -> Result<_, DeserializeError> { - let (credentials, credentials_encoding, credentials_value_encodings) = - (|| -> Result<_, DeserializeError> { - let mut credentials_table = OrderedHashMap::new(); - let credentials_len = raw.map_sz()?; - let credentials_encoding = credentials_len.into(); - let mut credentials_value_encodings = BTreeMap::new(); - while match credentials_len { - cbor_event::LenSz::Len(n, _) => (credentials_table.len() as u64) < n, - cbor_event::LenSz::Indefinite => true, - } { - if raw.cbor_type()? == cbor_event::Type::Special { - assert_eq!(raw.special()?, cbor_event::Special::Break); - break; - } - let credentials_key = Credential::deserialize(raw)?; - let (credentials_value, credentials_value_encoding) = - raw.unsigned_integer_sz().map(|(x, enc)| (x, Some(enc)))?; - if credentials_table - .insert(credentials_key.clone(), credentials_value) - .is_some() - { - return Err(DeserializeFailure::DuplicateKey(Key::Str(String::from( - "some complicated/unsupported type", - ))) - .into()); - } - credentials_value_encodings - .insert(credentials_key, credentials_value_encoding); - } - Ok(( - credentials_table, - credentials_encoding, - credentials_value_encodings, - )) - })() - .map_err(|e| e.annotate("credentials"))?; - let unit_interval = UnitInterval::deserialize(raw) - .map_err(|e: DeserializeError| e.annotate("unit_interval"))?; - match len { - cbor_event::LenSz::Len(_, _) => (), - cbor_event::LenSz::Indefinite => match raw.special()? { - cbor_event::Special::Break => (), - _ => return Err(DeserializeFailure::EndingBreakMissing.into()), - }, - } - Ok(Committee { - credentials, - unit_interval, - encodings: Some(CommitteeEncoding { - len_encoding, - credentials_encoding, - credentials_value_encodings, - }), - }) - })() - .map_err(|e| e.annotate("Committee")) - } -} - impl Serialize for Constitution { fn serialize<'se, W: Write>( &self, @@ -321,8 +190,8 @@ impl Serialize for GovAction { GovAction::NoConfidence(no_confidence) => { no_confidence.serialize(serializer, force_canonical) } - GovAction::NewCommittee(new_committee) => { - new_committee.serialize(serializer, force_canonical) + GovAction::UpdateCommittee(update_committee) => { + update_committee.serialize(serializer, force_canonical) } GovAction::NewConstitution(new_constitution) => { new_constitution.serialize(serializer, force_canonical) @@ -459,9 +328,9 @@ impl Deserialize for GovAction { }; let deser_variant = (|raw: &mut Deserializer<_>| -> Result<_, DeserializeError> { let mut read_len = CBORReadLen::new(len); - read_len.read_elems(4)?; + read_len.read_elems(5)?; read_len.finish()?; - let ret = NewCommittee::deserialize_as_embedded_group(raw, &mut read_len, len); + let ret = UpdateCommittee::deserialize_as_embedded_group(raw, &mut read_len, len); match len { cbor_event::LenSz::Len(_, _) => (), cbor_event::LenSz::Indefinite => match raw.special()? { @@ -472,9 +341,9 @@ impl Deserialize for GovAction { ret })(raw); match deser_variant { - Ok(new_committee) => return Ok(Self::NewCommittee(new_committee)), + Ok(update_committee) => return Ok(Self::UpdateCommittee(update_committee)), Err(e) => { - errs.push(e.annotate("NewCommittee")); + errs.push(e.annotate("UpdateCommittee")); raw.as_mut_ref() .seek(SeekFrom::Start(initial_position)) .unwrap(); @@ -746,153 +615,6 @@ impl DeserializeEmbeddedGroup for HardForkInitiationAction { } } -impl Serialize for NewCommittee { - fn serialize<'se, W: Write>( - &self, - serializer: &'se mut Serializer, - force_canonical: bool, - ) -> cbor_event::Result<&'se mut Serializer> { - serializer.write_array_sz( - self.encodings - .as_ref() - .map(|encs| encs.len_encoding) - .unwrap_or_default() - .to_len_sz(4, force_canonical), - )?; - self.serialize_as_embedded_group(serializer, force_canonical) - } -} - -impl SerializeEmbeddedGroup for NewCommittee { - fn serialize_as_embedded_group<'se, W: Write>( - &self, - serializer: &'se mut Serializer, - force_canonical: bool, - ) -> cbor_event::Result<&'se mut Serializer> { - serializer.write_unsigned_integer_sz( - 4u64, - fit_sz( - 4u64, - self.encodings - .as_ref() - .map(|encs| encs.tag_encoding) - .unwrap_or_default(), - force_canonical, - ), - )?; - match &self.action_id { - Some(x) => x.serialize(serializer, force_canonical), - None => serializer.write_special(cbor_event::Special::Null), - }?; - serializer.write_array_sz( - self.encodings - .as_ref() - .map(|encs| encs.cold_credentials_encoding) - .unwrap_or_default() - .to_len_sz(self.cold_credentials.len() as u64, force_canonical), - )?; - for element in self.cold_credentials.iter() { - element.serialize(serializer, force_canonical)?; - } - self.encodings - .as_ref() - .map(|encs| encs.cold_credentials_encoding) - .unwrap_or_default() - .end(serializer, force_canonical)?; - self.committee.serialize(serializer, force_canonical)?; - self.encodings - .as_ref() - .map(|encs| encs.len_encoding) - .unwrap_or_default() - .end(serializer, force_canonical) - } -} - -impl Deserialize for NewCommittee { - fn deserialize(raw: &mut Deserializer) -> Result { - let len = raw.array_sz()?; - let mut read_len = CBORReadLen::new(len); - read_len.read_elems(4)?; - read_len.finish()?; - let ret = Self::deserialize_as_embedded_group(raw, &mut read_len, len); - match len { - cbor_event::LenSz::Len(_, _) => (), - cbor_event::LenSz::Indefinite => match raw.special()? { - cbor_event::Special::Break => (), - _ => return Err(DeserializeFailure::EndingBreakMissing.into()), - }, - } - ret - } -} - -impl DeserializeEmbeddedGroup for NewCommittee { - fn deserialize_as_embedded_group( - raw: &mut Deserializer, - _read_len: &mut CBORReadLen, - len: cbor_event::LenSz, - ) -> Result { - let len_encoding = len.into(); - (|| -> Result<_, DeserializeError> { - let tag_encoding = (|| -> Result<_, DeserializeError> { - let (tag_value, tag_encoding) = raw.unsigned_integer_sz()?; - if tag_value != 4 { - return Err(DeserializeFailure::FixedValueMismatch { - found: Key::Uint(tag_value), - expected: Key::Uint(4), - } - .into()); - } - Ok(Some(tag_encoding)) - })() - .map_err(|e| e.annotate("tag"))?; - let action_id = (|| -> Result<_, DeserializeError> { - Ok(match raw.cbor_type()? != cbor_event::Type::Special { - true => Some(GovActionId::deserialize(raw)?), - false => { - if raw.special()? != cbor_event::Special::Null { - return Err(DeserializeFailure::ExpectedNull.into()); - } - None - } - }) - })() - .map_err(|e| e.annotate("action_id"))?; - let (cold_credentials, cold_credentials_encoding) = - (|| -> Result<_, DeserializeError> { - let mut cold_credentials_arr = Vec::new(); - let len = raw.array_sz()?; - let cold_credentials_encoding = len.into(); - while match len { - cbor_event::LenSz::Len(n, _) => (cold_credentials_arr.len() as u64) < n, - cbor_event::LenSz::Indefinite => true, - } { - if raw.cbor_type()? == cbor_event::Type::Special { - assert_eq!(raw.special()?, cbor_event::Special::Break); - break; - } - cold_credentials_arr.push(Credential::deserialize(raw)?); - } - Ok((cold_credentials_arr, cold_credentials_encoding)) - })() - .map_err(|e| e.annotate("cold_credentials"))?; - let committee = Committee::deserialize(raw) - .map_err(|e: DeserializeError| e.annotate("committee"))?; - Ok(NewCommittee { - action_id, - cold_credentials, - committee, - encodings: Some(NewCommitteeEncoding { - len_encoding, - tag_encoding, - cold_credentials_encoding, - }), - }) - })() - .map_err(|e| e.annotate("NewCommittee")) - } -} - impl Serialize for NewConstitution { fn serialize<'se, W: Write>( &self, @@ -1546,6 +1268,204 @@ impl DeserializeEmbeddedGroup for TreasuryWithdrawalsAction { } } +impl Serialize for UpdateCommittee { + fn serialize<'se, W: Write>( + &self, + serializer: &'se mut Serializer, + force_canonical: bool, + ) -> cbor_event::Result<&'se mut Serializer> { + serializer.write_array_sz( + self.encodings + .as_ref() + .map(|encs| encs.len_encoding) + .unwrap_or_default() + .to_len_sz(5, force_canonical), + )?; + self.serialize_as_embedded_group(serializer, force_canonical) + } +} + +impl SerializeEmbeddedGroup for UpdateCommittee { + fn serialize_as_embedded_group<'se, W: Write>( + &self, + serializer: &'se mut Serializer, + force_canonical: bool, + ) -> cbor_event::Result<&'se mut Serializer> { + serializer.write_unsigned_integer_sz( + 4u64, + fit_sz( + 4u64, + self.encodings + .as_ref() + .map(|encs| encs.tag_encoding) + .unwrap_or_default(), + force_canonical, + ), + )?; + match &self.action_id { + Some(x) => x.serialize(serializer, force_canonical), + None => serializer.write_special(cbor_event::Special::Null), + }?; + self.cold_credentials + .serialize(serializer, force_canonical)?; + serializer.write_map_sz( + self.encodings + .as_ref() + .map(|encs| encs.credentials_encoding) + .unwrap_or_default() + .to_len_sz(self.credentials.len() as u64, force_canonical), + )?; + let mut key_order = self + .credentials + .iter() + .map(|(k, v)| { + let mut buf = cbor_event::se::Serializer::new_vec(); + k.serialize(&mut buf, force_canonical)?; + Ok((buf.finalize(), k, v)) + }) + .collect::, &_, &_)>, cbor_event::Error>>()?; + if force_canonical { + key_order.sort_by(|(lhs_bytes, _, _), (rhs_bytes, _, _)| { + match lhs_bytes.len().cmp(&rhs_bytes.len()) { + std::cmp::Ordering::Equal => lhs_bytes.cmp(rhs_bytes), + diff_ord => diff_ord, + } + }); + } + for (key_bytes, key, value) in key_order { + serializer.write_raw_bytes(&key_bytes)?; + let credentials_value_encoding = self + .encodings + .as_ref() + .and_then(|encs| encs.credentials_value_encodings.get(key)) + .cloned() + .unwrap_or_default(); + serializer.write_unsigned_integer_sz( + *value, + fit_sz(*value, credentials_value_encoding, force_canonical), + )?; + } + self.encodings + .as_ref() + .map(|encs| encs.credentials_encoding) + .unwrap_or_default() + .end(serializer, force_canonical)?; + self.unit_interval.serialize(serializer, force_canonical)?; + self.encodings + .as_ref() + .map(|encs| encs.len_encoding) + .unwrap_or_default() + .end(serializer, force_canonical) + } +} + +impl Deserialize for UpdateCommittee { + fn deserialize(raw: &mut Deserializer) -> Result { + let len = raw.array_sz()?; + let mut read_len = CBORReadLen::new(len); + read_len.read_elems(5)?; + read_len.finish()?; + let ret = Self::deserialize_as_embedded_group(raw, &mut read_len, len); + match len { + cbor_event::LenSz::Len(_, _) => (), + cbor_event::LenSz::Indefinite => match raw.special()? { + cbor_event::Special::Break => (), + _ => return Err(DeserializeFailure::EndingBreakMissing.into()), + }, + } + ret + } +} + +impl DeserializeEmbeddedGroup for UpdateCommittee { + fn deserialize_as_embedded_group( + raw: &mut Deserializer, + _read_len: &mut CBORReadLen, + len: cbor_event::LenSz, + ) -> Result { + let len_encoding = len.into(); + (|| -> Result<_, DeserializeError> { + let tag_encoding = (|| -> Result<_, DeserializeError> { + let (tag_value, tag_encoding) = raw.unsigned_integer_sz()?; + if tag_value != 4 { + return Err(DeserializeFailure::FixedValueMismatch { + found: Key::Uint(tag_value), + expected: Key::Uint(4), + } + .into()); + } + Ok(Some(tag_encoding)) + })() + .map_err(|e| e.annotate("tag"))?; + let action_id = (|| -> Result<_, DeserializeError> { + Ok(match raw.cbor_type()? != cbor_event::Type::Special { + true => Some(GovActionId::deserialize(raw)?), + false => { + if raw.special()? != cbor_event::Special::Null { + return Err(DeserializeFailure::ExpectedNull.into()); + } + None + } + }) + })() + .map_err(|e| e.annotate("action_id"))?; + let cold_credentials = SetCommitteeColdCredential::deserialize(raw) + .map_err(|e: DeserializeError| e.annotate("cold_credentials"))?; + let (credentials, credentials_encoding, credentials_value_encodings) = + (|| -> Result<_, DeserializeError> { + let mut credentials_table = OrderedHashMap::new(); + let credentials_len = raw.map_sz()?; + let credentials_encoding = credentials_len.into(); + let mut credentials_value_encodings = BTreeMap::new(); + while match credentials_len { + cbor_event::LenSz::Len(n, _) => (credentials_table.len() as u64) < n, + cbor_event::LenSz::Indefinite => true, + } { + if raw.cbor_type()? == cbor_event::Type::Special { + assert_eq!(raw.special()?, cbor_event::Special::Break); + break; + } + let credentials_key = Credential::deserialize(raw)?; + let (credentials_value, credentials_value_encoding) = + raw.unsigned_integer_sz().map(|(x, enc)| (x, Some(enc)))?; + if credentials_table + .insert(credentials_key.clone(), credentials_value) + .is_some() + { + return Err(DeserializeFailure::DuplicateKey(Key::Str(String::from( + "some complicated/unsupported type", + ))) + .into()); + } + credentials_value_encodings + .insert(credentials_key, credentials_value_encoding); + } + Ok(( + credentials_table, + credentials_encoding, + credentials_value_encodings, + )) + })() + .map_err(|e| e.annotate("credentials"))?; + let unit_interval = UnitInterval::deserialize(raw) + .map_err(|e: DeserializeError| e.annotate("unit_interval"))?; + Ok(UpdateCommittee { + action_id, + cold_credentials, + credentials, + unit_interval, + encodings: Some(UpdateCommitteeEncoding { + len_encoding, + tag_encoding, + credentials_encoding, + credentials_value_encodings, + }), + }) + })() + .map_err(|e| e.annotate("UpdateCommittee")) + } +} + impl Serialize for Voter { fn serialize<'se, W: Write>( &self, diff --git a/chain/rust/src/lib.rs b/chain/rust/src/lib.rs index 55959731..ec34be1d 100644 --- a/chain/rust/src/lib.rs +++ b/chain/rust/src/lib.rs @@ -30,11 +30,11 @@ pub mod transaction; pub mod utils; pub use assets::{Coin, Value}; -use certs::Certificate; +use certs::{Certificate, CommitteeColdCredential}; use cml_crypto::Ed25519KeyHash; use crypto::{BootstrapWitness, Vkeywitness}; use utils::NonemptySetRawBytes; -pub use utils::{NonemptySet, Set, NetworkId}; +pub use utils::{NetworkId, NonemptySet, Set}; //pub mod legacy_address; @@ -59,7 +59,9 @@ use cbor_encodings::{ RationalEncoding, UnitIntervalEncoding, }; use governance::{ProposalProcedure, Voter}; -use plutus::{CostModels, ExUnitPrices, ExUnits, PlutusData, PlutusV1Script, PlutusV2Script, PlutusV3Script}; +use plutus::{ + CostModels, ExUnitPrices, ExUnits, PlutusData, PlutusV1Script, PlutusV2Script, PlutusV3Script, +}; use transaction::{NativeScript, TransactionInput}; #[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] @@ -110,8 +112,6 @@ impl DRepVotingThresholds { pub type DeltaCoin = Int; -pub type SetTransactionInput = Set; - pub type NonemptySetBootstrapWitness = NonemptySet; pub type NonemptySetCertificate = NonemptySet; @@ -347,6 +347,11 @@ impl Script { } } +pub type SetCommitteeColdCredential = Set; +pub type SetEd25519KeyHash = NonemptySetRawBytes; + +pub type SetTransactionInput = Set; + pub type SubCoin = Rational; #[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] diff --git a/chain/rust/src/plutus/mod.rs b/chain/rust/src/plutus/mod.rs index c4a167a4..96d914f5 100644 --- a/chain/rust/src/plutus/mod.rs +++ b/chain/rust/src/plutus/mod.rs @@ -5,7 +5,9 @@ pub mod cbor_encodings; pub mod serialization; pub mod utils; -use self::cbor_encodings::{LegacyRedeemerEncoding, PlutusV3ScriptEncoding, RedeemerKeyEncoding, RedeemerValEncoding}; +use self::cbor_encodings::{ + LegacyRedeemerEncoding, PlutusV3ScriptEncoding, RedeemerKeyEncoding, RedeemerValEncoding, +}; use super::{Rational, SubCoin}; use crate::utils::BigInteger; diff --git a/chain/rust/src/plutus/utils.rs b/chain/rust/src/plutus/utils.rs index b36ec259..339c6450 100644 --- a/chain/rust/src/plutus/utils.rs +++ b/chain/rust/src/plutus/utils.rs @@ -565,39 +565,70 @@ impl Deserialize for PlutusMap { impl Redeemers { pub fn to_flat_format(self) -> Vec { match self { - Self::ArrLegacyRedeemer { arr_legacy_redeemer, .. } => arr_legacy_redeemer, - Self::MapRedeemerKeyToRedeemerVal { map_redeemer_key_to_redeemer_val, .. } => map_redeemer_key_to_redeemer_val.iter().map(|(k, v)| LegacyRedeemer::new( - k.tag, - k.index, - v.data.clone(), - v.ex_units.clone(), - )).collect_vec(), + Self::ArrLegacyRedeemer { + arr_legacy_redeemer, + .. + } => arr_legacy_redeemer, + Self::MapRedeemerKeyToRedeemerVal { + map_redeemer_key_to_redeemer_val, + .. + } => map_redeemer_key_to_redeemer_val + .iter() + .map(|(k, v)| { + LegacyRedeemer::new(k.tag, k.index, v.data.clone(), v.ex_units.clone()) + }) + .collect_vec(), } } pub fn to_map_format(self) -> OrderedHashMap { match self { - Self::ArrLegacyRedeemer { arr_legacy_redeemer, .. } => arr_legacy_redeemer.into_iter().map(|r| (RedeemerKey::new(r.tag, r.index), RedeemerVal::new(r.data, r.ex_units))).collect(), - Self::MapRedeemerKeyToRedeemerVal { map_redeemer_key_to_redeemer_val, .. } => map_redeemer_key_to_redeemer_val, + Self::ArrLegacyRedeemer { + arr_legacy_redeemer, + .. + } => arr_legacy_redeemer + .into_iter() + .map(|r| { + ( + RedeemerKey::new(r.tag, r.index), + RedeemerVal::new(r.data, r.ex_units), + ) + }) + .collect(), + Self::MapRedeemerKeyToRedeemerVal { + map_redeemer_key_to_redeemer_val, + .. + } => map_redeemer_key_to_redeemer_val, } } pub fn is_empty(&self) -> bool { match self { - Self::ArrLegacyRedeemer { arr_legacy_redeemer, .. } => arr_legacy_redeemer.is_empty(), - Self::MapRedeemerKeyToRedeemerVal { map_redeemer_key_to_redeemer_val, .. } => map_redeemer_key_to_redeemer_val.is_empty(), + Self::ArrLegacyRedeemer { + arr_legacy_redeemer, + .. + } => arr_legacy_redeemer.is_empty(), + Self::MapRedeemerKeyToRedeemerVal { + map_redeemer_key_to_redeemer_val, + .. + } => map_redeemer_key_to_redeemer_val.is_empty(), } } pub fn extend(&mut self, other: Self) { match self { - Self::ArrLegacyRedeemer { arr_legacy_redeemer, .. } => arr_legacy_redeemer.extend(other.to_flat_format()), - Self::MapRedeemerKeyToRedeemerVal { map_redeemer_key_to_redeemer_val, .. } => { + Self::ArrLegacyRedeemer { + arr_legacy_redeemer, + .. + } => arr_legacy_redeemer.extend(other.to_flat_format()), + Self::MapRedeemerKeyToRedeemerVal { + map_redeemer_key_to_redeemer_val, + .. + } => { for (k, v) in other.to_map_format().take() { map_redeemer_key_to_redeemer_val.insert(k, v); } - - }, + } } } } diff --git a/chain/rust/src/transaction/mod.rs b/chain/rust/src/transaction/mod.rs index d53887d3..7590dce4 100644 --- a/chain/rust/src/transaction/mod.rs +++ b/chain/rust/src/transaction/mod.rs @@ -10,13 +10,15 @@ use crate::address::Address; use crate::assets::{Coin, Mint, PositiveCoin}; use crate::auxdata::AuxiliaryData; use crate::crypto::{ - AuxiliaryDataHash, DatumHash, Ed25519KeyHash, ScriptDataHash, - TransactionHash, + AuxiliaryDataHash, DatumHash, Ed25519KeyHash, ScriptDataHash, TransactionHash, }; use crate::governance::VotingProcedures; use crate::plutus::{PlutusData, Redeemers}; use crate::{ - NonemptySetBootstrapWitness, NonemptySetCertificate, NonemptySetNativeScript, NonemptySetPlutusData, NonemptySetPlutusV1Script, NonemptySetPlutusV2Script, NonemptySetPlutusV3Script, NonemptySetProposalProcedure, NonemptySetTransactionInput, NonemptySetVkeywitness, RequiredSigners, Script, SetTransactionInput, Slot, Withdrawals + NonemptySetBootstrapWitness, NonemptySetCertificate, NonemptySetNativeScript, + NonemptySetPlutusData, NonemptySetPlutusV1Script, NonemptySetPlutusV2Script, + NonemptySetPlutusV3Script, NonemptySetProposalProcedure, NonemptySetTransactionInput, + NonemptySetVkeywitness, RequiredSigners, Script, SetTransactionInput, Slot, Withdrawals, }; use cbor_encodings::{ AlonzoFormatTxOutEncoding, ConwayFormatTxOutEncoding, ScriptAllEncoding, ScriptAnyEncoding, @@ -171,7 +173,6 @@ impl NativeScript { } } - #[derive( Clone, Debug, derivative::Derivative, serde::Deserialize, serde::Serialize, schemars::JsonSchema, )] diff --git a/chain/rust/src/utils.rs b/chain/rust/src/utils.rs index 085fba47..ae8e75e7 100644 --- a/chain/rust/src/utils.rs +++ b/chain/rust/src/utils.rs @@ -594,12 +594,11 @@ impl<'de, T: serde::de::Deserialize<'de>> serde::de::Deserialize<'de> for Nonemp where D: serde::de::Deserializer<'de>, { - Vec::deserialize(deserializer) - .map(|elems| Self { - elems, - len_encoding: LenEncoding::default(), - tag_encoding: None, - }) + Vec::deserialize(deserializer).map(|elems| Self { + elems, + len_encoding: LenEncoding::default(), + tag_encoding: None, + }) } } @@ -678,7 +677,11 @@ impl Deserialize for NonemptySet { let (arr_len, tag_encoding) = if raw.cbor_type()? == cbor_event::Type::Tag { let (tag, tag_encoding) = raw.tag_sz()?; if tag != 258 { - return Err(DeserializeFailure::TagMismatch { found: tag, expected: 258 }.into()); + return Err(DeserializeFailure::TagMismatch { + found: tag, + expected: 258, + } + .into()); } (raw.array_sz()?, Some(tag_encoding)) } else { @@ -733,13 +736,12 @@ impl<'de, T: serde::de::Deserialize<'de>> serde::de::Deserialize<'de> for Nonemp where D: serde::de::Deserializer<'de>, { - Vec::deserialize(deserializer) - .map(|elems| Self { - elems, - len_encoding: LenEncoding::default(), - tag_encoding: None, - bytes_encodings: Vec::new(), - }) + Vec::deserialize(deserializer).map(|elems| Self { + elems, + len_encoding: LenEncoding::default(), + tag_encoding: None, + bytes_encodings: Vec::new(), + }) } } @@ -808,7 +810,8 @@ impl Serialize for NonemptySetRawBytes { for (i, elem) in self.elems.iter().enumerate() { serializer.write_bytes_sz( elem.to_raw_bytes(), - self.bytes_encodings.get(i) + self.bytes_encodings + .get(i) .cloned() .unwrap_or_default() .to_str_len_sz(elem.to_raw_bytes().len() as u64, force_canonical), @@ -826,7 +829,11 @@ impl Deserialize for NonemptySetRawBytes { let (arr_len, tag_encoding) = if raw.cbor_type()? == cbor_event::Type::Tag { let (tag, tag_encoding) = raw.tag_sz()?; if tag != 258 { - return Err(DeserializeFailure::TagMismatch { found: tag, expected: 258 }.into()); + return Err(DeserializeFailure::TagMismatch { + found: tag, + expected: 258, + } + .into()); } (raw.array_sz()?, Some(tag_encoding)) } else { diff --git a/chain/wasm/json-gen/src/lib.rs b/chain/wasm/json-gen/src/lib.rs index 0b6b390d..03531c16 100644 --- a/chain/wasm/json-gen/src/lib.rs +++ b/chain/wasm/json-gen/src/lib.rs @@ -46,7 +46,10 @@ pub fn export_schemas() { gen_json_schema!(cml_chain::byron::StakeholderId); gen_json_schema!(cml_crypto::Bip32PublicKey); // certs + gen_json_schema!(cml_chain::certs::AuthCommitteeHotCert); gen_json_schema!(cml_chain::certs::Certificate); + gen_json_schema!(cml_chain::certs::Credential); + gen_json_schema!(cml_chain::certs::DRep); gen_json_schema!(cml_chain::certs::DnsName); gen_json_schema!(cml_chain::certs::Ipv4); gen_json_schema!(cml_chain::certs::Ipv6); @@ -55,18 +58,30 @@ pub fn export_schemas() { gen_json_schema!(cml_chain::certs::PoolParams); gen_json_schema!(cml_chain::certs::PoolRegistration); gen_json_schema!(cml_chain::certs::PoolRetirement); + gen_json_schema!(cml_chain::certs::RegCert); + gen_json_schema!(cml_chain::certs::RegDrepCert); gen_json_schema!(cml_chain::certs::Relay); + gen_json_schema!(cml_chain::certs::ResignCommitteeColdCert); gen_json_schema!(cml_chain::certs::SingleHostAddr); gen_json_schema!(cml_chain::certs::SingleHostName); - gen_json_schema!(cml_chain::certs::StakeCredential); gen_json_schema!(cml_chain::certs::StakeDelegation); gen_json_schema!(cml_chain::certs::StakeDeregistration); + gen_json_schema!(cml_chain::certs::StakeRegDelegCert); gen_json_schema!(cml_chain::certs::StakeRegistration); + gen_json_schema!(cml_chain::certs::StakeVoteDelegCert); + gen_json_schema!(cml_chain::certs::StakeVoteRegDelegCert); + gen_json_schema!(cml_chain::certs::UnregCert); + gen_json_schema!(cml_chain::certs::UnregDrepCert); + gen_json_schema!(cml_chain::certs::UpdateDrepCert); gen_json_schema!(cml_chain::certs::Url); + gen_json_schema!(cml_chain::certs::VoteDelegCert); + gen_json_schema!(cml_chain::certs::VoteRegDelegCert); // crypto + gen_json_schema!(cml_chain::crypto::AnchorDocHash); gen_json_schema!(cml_chain::crypto::AuxiliaryDataHash); gen_json_schema!(cml_chain::crypto::BlockBodyHash); gen_json_schema!(cml_chain::crypto::BlockHeaderHash); + gen_json_schema!(cml_chain::crypto::BootstrapWitness); gen_json_schema!(cml_chain::crypto::DatumHash); gen_json_schema!(cml_chain::crypto::Ed25519KeyHash); gen_json_schema!(cml_chain::crypto::Ed25519Signature); @@ -83,12 +98,42 @@ pub fn export_schemas() { gen_json_schema!(cml_chain::crypto::VRFKeyHash); gen_json_schema!(cml_chain::crypto::VRFVkey); gen_json_schema!(cml_chain::crypto::Vkey); + gen_json_schema!(cml_chain::crypto::Vkeywitness); + // governance + gen_json_schema!(cml_chain::governance::Anchor); + gen_json_schema!(cml_chain::governance::Constitution); + gen_json_schema!(cml_chain::governance::GovAction); + gen_json_schema!(cml_chain::governance::GovActionId); + gen_json_schema!(cml_chain::governance::HardForkInitiationAction); + gen_json_schema!(cml_chain::governance::NewConstitution); + gen_json_schema!(cml_chain::governance::NoConfidence); + gen_json_schema!(cml_chain::governance::ParameterChangeAction); + gen_json_schema!(cml_chain::governance::ProposalProcedure); + gen_json_schema!(cml_chain::governance::TreasuryWithdrawalsAction); + gen_json_schema!(cml_chain::governance::UpdateCommittee); + gen_json_schema!(cml_chain::governance::Vote); + gen_json_schema!(cml_chain::governance::Voter); + gen_json_schema!(cml_chain::governance::VotingProcedure); // lib - gen_json_schema!(cml_chain::crypto::BootstrapWitness); + gen_json_schema!(cml_chain::DRepVotingThresholds); gen_json_schema!(cml_chain::Int); + gen_json_schema!(cml_chain::NetworkId); + gen_json_schema!(cml_chain::NonemptySetBootstrapWitness); + gen_json_schema!(cml_chain::NonemptySetCertificate); + gen_json_schema!(cml_chain::NonemptySetNativeScript); + gen_json_schema!(cml_chain::NonemptySetPlutusData); + gen_json_schema!(cml_chain::NonemptySetPlutusV1Script); + gen_json_schema!(cml_chain::NonemptySetPlutusV2Script); + gen_json_schema!(cml_chain::NonemptySetPlutusV3Script); + gen_json_schema!(cml_chain::NonemptySetProposalProcedure); + gen_json_schema!(cml_chain::NonemptySetTransactionInput); + gen_json_schema!(cml_chain::NonemptySetVkeywitness); + gen_json_schema!(cml_chain::PoolVotingThresholds); gen_json_schema!(cml_chain::ProtocolParamUpdate); gen_json_schema!(cml_chain::Rational); gen_json_schema!(cml_chain::Script); + gen_json_schema!(cml_chain::SetEd25519KeyHash); + gen_json_schema!(cml_chain::SetTransactionInput); gen_json_schema!(cml_chain::UnitInterval); gen_json_schema!(cml_chain::Value); gen_json_schema!(cml_chain::crypto::Vkeywitness); @@ -97,16 +142,22 @@ pub fn export_schemas() { gen_json_schema!(cml_chain::plutus::CostModels); gen_json_schema!(cml_chain::plutus::ExUnitPrices); gen_json_schema!(cml_chain::plutus::ExUnits); + gen_json_schema!(cml_chain::plutus::Language); + gen_json_schema!(cml_chain::plutus::LegacyRedeemer); gen_json_schema!(cml_chain::plutus::PlutusData); gen_json_schema!(cml_chain::plutus::PlutusMap); gen_json_schema!(cml_chain::plutus::PlutusV1Script); gen_json_schema!(cml_chain::plutus::PlutusV2Script); - gen_json_schema!(cml_chain::plutus::Redeemer); + gen_json_schema!(cml_chain::plutus::PlutusV3Script); + gen_json_schema!(cml_chain::plutus::RedeemerKey); gen_json_schema!(cml_chain::plutus::RedeemerTag); + gen_json_schema!(cml_chain::plutus::RedeemerVal); + gen_json_schema!(cml_chain::plutus::Redeemers); // transaction + gen_json_schema!(cml_chain::transaction::AlonzoFormatTxOut); + gen_json_schema!(cml_chain::transaction::ConwayFormatTxOut); gen_json_schema!(cml_chain::transaction::DatumOption); gen_json_schema!(cml_chain::transaction::NativeScript); - gen_json_schema!(cml_chain::transaction::RequiredSigners); gen_json_schema!(cml_chain::transaction::ScriptAll); gen_json_schema!(cml_chain::transaction::ScriptAny); gen_json_schema!(cml_chain::transaction::ScriptInvalidBefore); diff --git a/chain/wasm/src/certs/mod.rs b/chain/wasm/src/certs/mod.rs index 01ddd59b..16fb9470 100644 --- a/chain/wasm/src/certs/mod.rs +++ b/chain/wasm/src/certs/mod.rs @@ -1,7 +1,7 @@ // This file was code-generated using an experimental CDDL to rust tool: // https://github.com/dcSpark/cddl-codegen -use super::{Coin, Ed25519KeyHashList, Epoch, Port, RelayList, UnitInterval}; +use super::{Coin, Epoch, Port, RelayList, SetEd25519KeyHash, UnitInterval}; use crate::address::RewardAccount; use crate::governance::Anchor; @@ -165,10 +165,12 @@ impl Certificate { pub fn new_resign_committee_cold_cert( committee_cold_credential: &CommitteeColdCredential, + anchor: Option, ) -> Self { Self( cml_chain::certs::Certificate::new_resign_committee_cold_cert( committee_cold_credential.clone().into(), + anchor.map(Into::into), ), ) } @@ -648,7 +650,7 @@ impl PoolParams { self.0.reward_account.clone().into() } - pub fn pool_owners(&self) -> Ed25519KeyHashList { + pub fn pool_owners(&self) -> SetEd25519KeyHash { self.0.pool_owners.clone().into() } @@ -667,7 +669,7 @@ impl PoolParams { cost: Coin, margin: &UnitInterval, reward_account: &RewardAccount, - pool_owners: &Ed25519KeyHashList, + pool_owners: &SetEd25519KeyHash, relays: &RelayList, pool_metadata: Option, ) -> Self { @@ -884,9 +886,17 @@ impl ResignCommitteeColdCert { self.0.committee_cold_credential.clone().into() } - pub fn new(committee_cold_credential: &CommitteeColdCredential) -> Self { + pub fn anchor(&self) -> Option { + self.0.anchor.clone().map(std::convert::Into::into) + } + + pub fn new( + committee_cold_credential: &CommitteeColdCredential, + anchor: Option, + ) -> Self { Self(cml_chain::certs::ResignCommitteeColdCert::new( committee_cold_credential.clone().into(), + anchor.map(Into::into), )) } } diff --git a/chain/wasm/src/governance/mod.rs b/chain/wasm/src/governance/mod.rs index 34c1e104..a184942c 100644 --- a/chain/wasm/src/governance/mod.rs +++ b/chain/wasm/src/governance/mod.rs @@ -7,9 +7,8 @@ use crate::block::ProtocolVersion; use crate::certs::Url; use crate::crypto::{AnchorDocHash, Ed25519KeyHash, ScriptHash, TransactionHash}; use crate::{ - CommitteeColdCredentialList, MapCommitteeColdCredentialToEpoch, - MapGovActionIdToVotingProcedure, MapRewardAccountToCoin, ProtocolParamUpdate, UnitInterval, - VoterList, + MapCommitteeColdCredentialToEpoch, MapGovActionIdToVotingProcedure, MapRewardAccountToCoin, + ProtocolParamUpdate, SetCommitteeColdCredential, UnitInterval, VoterList, }; pub use cml_chain::governance::Vote; use cml_core::ordered_hash_map::OrderedHashMap; @@ -42,35 +41,6 @@ impl Anchor { } } -#[derive(Clone, Debug)] -#[wasm_bindgen] -pub struct Committee(cml_chain::governance::Committee); - -impl_wasm_cbor_json_api!(Committee); - -impl_wasm_conversions!(cml_chain::governance::Committee, Committee); - -#[wasm_bindgen] -impl Committee { - pub fn credentials(&self) -> MapCommitteeColdCredentialToEpoch { - self.0.credentials.clone().into() - } - - pub fn unit_interval(&self) -> UnitInterval { - self.0.unit_interval.clone().into() - } - - pub fn new( - credentials: &MapCommitteeColdCredentialToEpoch, - unit_interval: &UnitInterval, - ) -> Self { - Self(cml_chain::governance::Committee::new( - credentials.clone().into(), - unit_interval.clone().into(), - )) - } -} - #[derive(Clone, Debug)] #[wasm_bindgen] pub struct Constitution(cml_chain::governance::Constitution); @@ -151,15 +121,17 @@ impl GovAction { )) } - pub fn new_new_committee( + pub fn new_update_committee( action_id: Option, - cold_credentials: &CommitteeColdCredentialList, - committee: &Committee, + cold_credentials: &SetCommitteeColdCredential, + credentials: &MapCommitteeColdCredentialToEpoch, + unit_interval: &UnitInterval, ) -> Self { - Self(cml_chain::governance::GovAction::new_new_committee( + Self(cml_chain::governance::GovAction::new_update_committee( action_id.map(Into::into), cold_credentials.clone().into(), - committee.clone().into(), + credentials.clone().into(), + unit_interval.clone().into(), )) } @@ -189,7 +161,7 @@ impl GovAction { GovActionKind::TreasuryWithdrawalsAction } cml_chain::governance::GovAction::NoConfidence(_) => GovActionKind::NoConfidence, - cml_chain::governance::GovAction::NewCommittee(_) => GovActionKind::NewCommittee, + cml_chain::governance::GovAction::UpdateCommittee(_) => GovActionKind::UpdateCommittee, cml_chain::governance::GovAction::NewConstitution(_) => GovActionKind::NewConstitution, cml_chain::governance::GovAction::InfoAction { .. } => GovActionKind::InfoAction, } @@ -231,10 +203,10 @@ impl GovAction { } } - pub fn as_new_committee(&self) -> Option { + pub fn as_update_committee(&self) -> Option { match &self.0 { - cml_chain::governance::GovAction::NewCommittee(new_committee) => { - Some(new_committee.clone().into()) + cml_chain::governance::GovAction::UpdateCommittee(update_committee) => { + Some(update_committee.clone().into()) } _ => None, } @@ -282,7 +254,7 @@ pub enum GovActionKind { HardForkInitiationAction, TreasuryWithdrawalsAction, NoConfidence, - NewCommittee, + UpdateCommittee, NewConstitution, InfoAction, } @@ -316,41 +288,6 @@ impl HardForkInitiationAction { } } -#[derive(Clone, Debug)] -#[wasm_bindgen] -pub struct NewCommittee(cml_chain::governance::NewCommittee); - -impl_wasm_cbor_json_api!(NewCommittee); - -impl_wasm_conversions!(cml_chain::governance::NewCommittee, NewCommittee); - -#[wasm_bindgen] -impl NewCommittee { - pub fn action_id(&self) -> Option { - self.0.action_id.clone().map(std::convert::Into::into) - } - - pub fn cold_credentials(&self) -> CommitteeColdCredentialList { - self.0.cold_credentials.clone().into() - } - - pub fn committee(&self) -> Committee { - self.0.committee.clone().into() - } - - pub fn new( - action_id: Option, - cold_credentials: &CommitteeColdCredentialList, - committee: &Committee, - ) -> Self { - Self(cml_chain::governance::NewCommittee::new( - action_id.map(Into::into), - cold_credentials.clone().into(), - committee.clone().into(), - )) - } -} - #[derive(Clone, Debug)] #[wasm_bindgen] pub struct NewConstitution(cml_chain::governance::NewConstitution); @@ -506,6 +443,47 @@ impl TreasuryWithdrawalsAction { } } +#[derive(Clone, Debug)] +#[wasm_bindgen] +pub struct UpdateCommittee(cml_chain::governance::UpdateCommittee); + +impl_wasm_cbor_json_api!(UpdateCommittee); + +impl_wasm_conversions!(cml_chain::governance::UpdateCommittee, UpdateCommittee); + +#[wasm_bindgen] +impl UpdateCommittee { + pub fn action_id(&self) -> Option { + self.0.action_id.clone().map(std::convert::Into::into) + } + + pub fn cold_credentials(&self) -> SetCommitteeColdCredential { + self.0.cold_credentials.clone().into() + } + + pub fn credentials(&self) -> MapCommitteeColdCredentialToEpoch { + self.0.credentials.clone().into() + } + + pub fn unit_interval(&self) -> UnitInterval { + self.0.unit_interval.clone().into() + } + + pub fn new( + action_id: Option, + cold_credentials: &SetCommitteeColdCredential, + credentials: &MapCommitteeColdCredentialToEpoch, + unit_interval: &UnitInterval, + ) -> Self { + Self(cml_chain::governance::UpdateCommittee::new( + action_id.map(Into::into), + cold_credentials.clone().into(), + credentials.clone().into(), + unit_interval.clone().into(), + )) + } +} + #[derive(Clone, Debug)] #[wasm_bindgen] pub struct Voter(cml_chain::governance::Voter); diff --git a/chain/wasm/src/lib.rs b/chain/wasm/src/lib.rs index 7a2716a5..a6d3a19d 100644 --- a/chain/wasm/src/lib.rs +++ b/chain/wasm/src/lib.rs @@ -182,6 +182,10 @@ impl_wasm_list!( Ed25519KeyHashList ); +pub type SetCommitteeColdCredential = CommitteeColdCredentialList; + +pub type SetEd25519KeyHash = Ed25519KeyHashList; + impl_wasm_list!( cml_chain::governance::GovActionId, GovActionId, diff --git a/chain/wasm/src/utils.rs b/chain/wasm/src/utils.rs index 00d0bfc8..ce9c6751 100644 --- a/chain/wasm/src/utils.rs +++ b/chain/wasm/src/utils.rs @@ -86,6 +86,8 @@ impl NetworkId { } } +// we provide direct From/Into conversions between NonemptySet and TList +// to allow the auto-generated code to work directly without changes macro_rules! impl_wasm_conversions_into { ($rust:ty, $wasm:ty) => { impl From<$rust> for $wasm { @@ -145,3 +147,8 @@ impl_wasm_conversions_into!( cml_chain::utils::NonemptySetRawBytes, crate::Ed25519KeyHashList ); + +impl_wasm_conversions_into!( + cml_chain::SetCommitteeColdCredential, + crate::CommitteeColdCredentialList +); diff --git a/multi-era/rust/src/allegra/mod.rs b/multi-era/rust/src/allegra/mod.rs index 0cfe0b01..c9be16f4 100644 --- a/multi-era/rust/src/allegra/mod.rs +++ b/multi-era/rust/src/allegra/mod.rs @@ -6,7 +6,8 @@ pub mod serialization; pub mod utils; use crate::shelley::{ - GenesisKeyDelegation, ShelleyHeader, ShelleyTransactionOutput, ShelleyUpdate, + GenesisKeyDelegation, ShelleyHeader, ShelleyPoolParams, ShelleyPoolRegistration, + ShelleyTransactionOutput, ShelleyUpdate, }; use cbor_encodings::{ AllegraBlockEncoding, AllegraTransactionBodyEncoding, AllegraTransactionEncoding, @@ -15,8 +16,7 @@ use cbor_encodings::{ use cml_chain::assets::Coin; use cml_chain::auxdata::{ShelleyFormatAuxData, ShelleyMaFormatAuxData}; use cml_chain::certs::{ - PoolParams, PoolRegistration, PoolRetirement, StakeCredential, StakeDelegation, - StakeDeregistration, StakeRegistration, + PoolRetirement, StakeCredential, StakeDelegation, StakeDeregistration, StakeRegistration, }; use cml_chain::crypto::{AuxiliaryDataHash, BootstrapWitness, Vkeywitness}; use cml_chain::transaction::{NativeScript, TransactionInput}; @@ -78,7 +78,7 @@ pub enum AllegraCertificate { StakeRegistration(StakeRegistration), StakeDeregistration(StakeDeregistration), StakeDelegation(StakeDelegation), - PoolRegistration(PoolRegistration), + ShelleyPoolRegistration(ShelleyPoolRegistration), PoolRetirement(PoolRetirement), GenesisKeyDelegation(GenesisKeyDelegation), MoveInstantaneousRewardsCert(MoveInstantaneousRewardsCert), @@ -100,8 +100,8 @@ impl AllegraCertificate { Self::StakeDelegation(StakeDelegation::new(stake_credential, ed25519_key_hash)) } - pub fn new_pool_registration(pool_params: PoolParams) -> Self { - Self::PoolRegistration(PoolRegistration::new(pool_params)) + pub fn new_shelley_pool_registration(pool_params: ShelleyPoolParams) -> Self { + Self::ShelleyPoolRegistration(ShelleyPoolRegistration::new(pool_params)) } pub fn new_pool_retirement(ed25519_key_hash: Ed25519KeyHash, epoch: Epoch) -> Self { diff --git a/multi-era/rust/src/allegra/serialization.rs b/multi-era/rust/src/allegra/serialization.rs index 7e51a865..0e997cba 100644 --- a/multi-era/rust/src/allegra/serialization.rs +++ b/multi-era/rust/src/allegra/serialization.rs @@ -1,6 +1,8 @@ // This file was code-generated using an experimental CDDL to rust tool: // https://github.com/dcSpark/cddl-codegen +use crate::shelley::ShelleyPoolRegistration; + use super::cbor_encodings::*; use super::*; use cbor_event; @@ -254,8 +256,8 @@ impl Serialize for AllegraCertificate { AllegraCertificate::StakeDelegation(stake_delegation) => { stake_delegation.serialize(serializer, force_canonical) } - AllegraCertificate::PoolRegistration(pool_registration) => { - pool_registration.serialize(serializer, force_canonical) + AllegraCertificate::ShelleyPoolRegistration(shelley_pool_registration) => { + shelley_pool_registration.serialize(serializer, force_canonical) } AllegraCertificate::PoolRetirement(pool_retirement) => { pool_retirement.serialize(serializer, force_canonical) @@ -352,7 +354,8 @@ impl Deserialize for AllegraCertificate { let mut read_len = CBORReadLen::new(len); read_len.read_elems(10)?; read_len.finish()?; - let ret = PoolRegistration::deserialize_as_embedded_group(raw, &mut read_len, len); + let ret = + ShelleyPoolRegistration::deserialize_as_embedded_group(raw, &mut read_len, len); match len { cbor_event::LenSz::Len(_, _) => (), cbor_event::LenSz::Indefinite => match raw.special()? { @@ -363,9 +366,11 @@ impl Deserialize for AllegraCertificate { ret })(raw); match deser_variant { - Ok(pool_registration) => return Ok(Self::PoolRegistration(pool_registration)), + Ok(shelley_pool_registration) => { + return Ok(Self::ShelleyPoolRegistration(shelley_pool_registration)) + } Err(e) => { - errs.push(e.annotate("PoolRegistration")); + errs.push(e.annotate("ShelleyPoolRegistration")); raw.as_mut_ref() .seek(SeekFrom::Start(initial_position)) .unwrap(); diff --git a/multi-era/rust/src/allegra/utils.rs b/multi-era/rust/src/allegra/utils.rs index cae7a14e..86eedd25 100644 --- a/multi-era/rust/src/allegra/utils.rs +++ b/multi-era/rust/src/allegra/utils.rs @@ -23,9 +23,9 @@ impl From for AuxiliaryData { impl From for TransactionWitnessSet { fn from(wits: AllegraTransactionWitnessSet) -> Self { let mut new_wits = TransactionWitnessSet::new(); - new_wits.vkeywitnesses = wits.vkeywitnesses; - new_wits.native_scripts = wits.native_scripts; - new_wits.bootstrap_witnesses = wits.bootstrap_witnesses; + new_wits.vkeywitnesses = wits.vkeywitnesses.map(Into::into); + new_wits.native_scripts = wits.native_scripts.map(Into::into); + new_wits.bootstrap_witnesses = wits.bootstrap_witnesses.map(Into::into); new_wits } } diff --git a/multi-era/rust/src/alonzo/cbor_encodings.rs b/multi-era/rust/src/alonzo/cbor_encodings.rs index 03958ad6..d4f9a8d0 100644 --- a/multi-era/rust/src/alonzo/cbor_encodings.rs +++ b/multi-era/rust/src/alonzo/cbor_encodings.rs @@ -80,6 +80,13 @@ pub struct AlonzoProtocolParamUpdateEncoding { pub max_collateral_inputs_key_encoding: Option, } +#[derive(Clone, Debug, Default)] +pub struct AlonzoRedeemerEncoding { + pub len_encoding: LenEncoding, + pub tag_encoding: Option, + pub index_encoding: Option, +} + #[derive(Clone, Debug, Default)] pub struct AlonzoTransactionBodyEncoding { pub len_encoding: LenEncoding, diff --git a/multi-era/rust/src/alonzo/mod.rs b/multi-era/rust/src/alonzo/mod.rs index e6315069..e5b4969c 100644 --- a/multi-era/rust/src/alonzo/mod.rs +++ b/multi-era/rust/src/alonzo/mod.rs @@ -19,13 +19,15 @@ use cml_chain::auxdata::{Metadata, ShelleyFormatAuxData, ShelleyMaFormatAuxData} use cml_chain::crypto::{ AuxiliaryDataHash, BootstrapWitness, GenesisHash, Nonce, ScriptDataHash, Vkeywitness, }; -use cml_chain::plutus::{ExUnitPrices, ExUnits, PlutusData, PlutusV1Script, Redeemer}; -use cml_chain::transaction::{AlonzoFormatTxOut, NativeScript, RequiredSigners, TransactionInput}; +use cml_chain::plutus::{ExUnitPrices, ExUnits, PlutusData, PlutusV1Script}; +use cml_chain::transaction::{AlonzoFormatTxOut, NativeScript, TransactionInput}; use cml_chain::TransactionIndex; -use cml_chain::{Epoch, NetworkId, Rational, UnitInterval, Withdrawals}; +use cml_chain::{Epoch, NetworkId, Rational, RequiredSigners, UnitInterval, Withdrawals}; use cml_core::ordered_hash_map::OrderedHashMap; use std::collections::BTreeMap; +use self::cbor_encodings::AlonzoRedeemerEncoding; + #[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] pub enum AlonzoAuxiliaryData { Shelley(ShelleyFormatAuxData), @@ -190,6 +192,48 @@ impl Default for AlonzoProtocolParamUpdate { } } +#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] +pub struct AlonzoRedeemer { + pub tag: AlonzoRedeemerTag, + pub index: u64, + pub data: PlutusData, + pub ex_units: ExUnits, + #[serde(skip)] + pub encodings: Option, +} + +impl AlonzoRedeemer { + pub fn new(tag: AlonzoRedeemerTag, index: u64, data: PlutusData, ex_units: ExUnits) -> Self { + Self { + tag, + index, + data, + ex_units, + encodings: None, + } + } +} + +#[derive( + Copy, + Eq, + PartialEq, + Ord, + PartialOrd, + Clone, + Debug, + serde::Deserialize, + serde::Serialize, + schemars::JsonSchema, +)] +#[wasm_bindgen::prelude::wasm_bindgen] +pub enum AlonzoRedeemerTag { + Spend, + Mint, + Cert, + Reward, +} + #[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] pub struct AlonzoTransaction { pub body: AlonzoTransactionBody, @@ -266,7 +310,7 @@ pub struct AlonzoTransactionWitnessSet { pub bootstrap_witnesses: Option>, pub plutus_v1_scripts: Option>, pub plutus_datums: Option>, - pub redeemers: Option>, + pub redeemers: Option>, #[serde(skip)] pub encodings: Option, } diff --git a/multi-era/rust/src/alonzo/serialization.rs b/multi-era/rust/src/alonzo/serialization.rs index 26855145..74372831 100644 --- a/multi-era/rust/src/alonzo/serialization.rs +++ b/multi-era/rust/src/alonzo/serialization.rs @@ -1997,6 +1997,206 @@ impl Deserialize for AlonzoProtocolParamUpdate { } } +impl Serialize for AlonzoRedeemer { + fn serialize<'se, W: Write>( + &self, + serializer: &'se mut Serializer, + force_canonical: bool, + ) -> cbor_event::Result<&'se mut Serializer> { + serializer.write_array_sz( + self.encodings + .as_ref() + .map(|encs| encs.len_encoding) + .unwrap_or_default() + .to_len_sz(4, force_canonical), + )?; + match &self.tag { + AlonzoRedeemerTag::Spend => serializer.write_unsigned_integer_sz( + 0u64, + fit_sz( + 0u64, + self.encodings + .as_ref() + .map(|encs| encs.tag_encoding) + .unwrap_or_default(), + force_canonical, + ), + ), + AlonzoRedeemerTag::Mint => serializer.write_unsigned_integer_sz( + 1u64, + fit_sz( + 1u64, + self.encodings + .as_ref() + .map(|encs| encs.tag_encoding) + .unwrap_or_default(), + force_canonical, + ), + ), + AlonzoRedeemerTag::Cert => serializer.write_unsigned_integer_sz( + 2u64, + fit_sz( + 2u64, + self.encodings + .as_ref() + .map(|encs| encs.tag_encoding) + .unwrap_or_default(), + force_canonical, + ), + ), + AlonzoRedeemerTag::Reward => serializer.write_unsigned_integer_sz( + 3u64, + fit_sz( + 3u64, + self.encodings + .as_ref() + .map(|encs| encs.tag_encoding) + .unwrap_or_default(), + force_canonical, + ), + ), + }?; + serializer.write_unsigned_integer_sz( + self.index, + fit_sz( + self.index, + self.encodings + .as_ref() + .map(|encs| encs.index_encoding) + .unwrap_or_default(), + force_canonical, + ), + )?; + self.data.serialize(serializer, force_canonical)?; + self.ex_units.serialize(serializer, force_canonical)?; + self.encodings + .as_ref() + .map(|encs| encs.len_encoding) + .unwrap_or_default() + .end(serializer, force_canonical) + } +} + +impl Deserialize for AlonzoRedeemer { + fn deserialize(raw: &mut Deserializer) -> Result { + let len = raw.array_sz()?; + let len_encoding: LenEncoding = len.into(); + let mut read_len = CBORReadLen::new(len); + read_len.read_elems(4)?; + read_len.finish()?; + (|| -> Result<_, DeserializeError> { + let (tag, tag_encoding) = (|| -> Result<_, DeserializeError> { + let initial_position = raw.as_mut_ref().stream_position().unwrap(); + let deser_variant = (|raw: &mut Deserializer<_>| -> Result<_, DeserializeError> { + let (spend_value, spend_encoding) = raw.unsigned_integer_sz()?; + if spend_value != 0 { + return Err(DeserializeFailure::FixedValueMismatch { + found: Key::Uint(spend_value), + expected: Key::Uint(0), + } + .into()); + } + Ok(Some(spend_encoding)) + })(raw); + match deser_variant { + Ok(tag_encoding) => return Ok((AlonzoRedeemerTag::Spend, tag_encoding)), + Err(_) => raw + .as_mut_ref() + .seek(SeekFrom::Start(initial_position)) + .unwrap(), + }; + let deser_variant = (|raw: &mut Deserializer<_>| -> Result<_, DeserializeError> { + let (mint_value, mint_encoding) = raw.unsigned_integer_sz()?; + if mint_value != 1 { + return Err(DeserializeFailure::FixedValueMismatch { + found: Key::Uint(mint_value), + expected: Key::Uint(1), + } + .into()); + } + Ok(Some(mint_encoding)) + })(raw); + match deser_variant { + Ok(tag_encoding) => return Ok((AlonzoRedeemerTag::Mint, tag_encoding)), + Err(_) => raw + .as_mut_ref() + .seek(SeekFrom::Start(initial_position)) + .unwrap(), + }; + let deser_variant = (|raw: &mut Deserializer<_>| -> Result<_, DeserializeError> { + let (cert_value, cert_encoding) = raw.unsigned_integer_sz()?; + if cert_value != 2 { + return Err(DeserializeFailure::FixedValueMismatch { + found: Key::Uint(cert_value), + expected: Key::Uint(2), + } + .into()); + } + Ok(Some(cert_encoding)) + })(raw); + match deser_variant { + Ok(tag_encoding) => return Ok((AlonzoRedeemerTag::Cert, tag_encoding)), + Err(_) => raw + .as_mut_ref() + .seek(SeekFrom::Start(initial_position)) + .unwrap(), + }; + let deser_variant = (|raw: &mut Deserializer<_>| -> Result<_, DeserializeError> { + let (reward_value, reward_encoding) = raw.unsigned_integer_sz()?; + if reward_value != 3 { + return Err(DeserializeFailure::FixedValueMismatch { + found: Key::Uint(reward_value), + expected: Key::Uint(3), + } + .into()); + } + Ok(Some(reward_encoding)) + })(raw); + match deser_variant { + Ok(tag_encoding) => return Ok((AlonzoRedeemerTag::Reward, tag_encoding)), + Err(_) => raw + .as_mut_ref() + .seek(SeekFrom::Start(initial_position)) + .unwrap(), + }; + Err(DeserializeError::new( + "AlonzoRedeemerTag", + DeserializeFailure::NoVariantMatched, + )) + })() + .map_err(|e| e.annotate("tag"))?; + let (index, index_encoding) = raw + .unsigned_integer_sz() + .map_err(Into::::into) + .map(|(x, enc)| (x, Some(enc))) + .map_err(|e: DeserializeError| e.annotate("index"))?; + let data = + PlutusData::deserialize(raw).map_err(|e: DeserializeError| e.annotate("data"))?; + let ex_units = + ExUnits::deserialize(raw).map_err(|e: DeserializeError| e.annotate("ex_units"))?; + match len { + cbor_event::LenSz::Len(_, _) => (), + cbor_event::LenSz::Indefinite => match raw.special()? { + cbor_event::Special::Break => (), + _ => return Err(DeserializeFailure::EndingBreakMissing.into()), + }, + } + Ok(AlonzoRedeemer { + tag, + index, + data, + ex_units, + encodings: Some(AlonzoRedeemerEncoding { + len_encoding, + tag_encoding, + index_encoding, + }), + }) + })() + .map_err(|e| e.annotate("AlonzoRedeemer")) + } +} + impl Serialize for AlonzoTransaction { fn serialize<'se, W: Write>( &self, @@ -3048,7 +3248,7 @@ impl Deserialize for AlonzoTransactionBody { mint: mint.map(Into::into), script_data_hash, collateral_inputs, - required_signers, + required_signers: required_signers.map(Into::into), network_id, encodings: Some(AlonzoTransactionBodyEncoding { len_encoding, @@ -3548,7 +3748,7 @@ impl Deserialize for AlonzoTransactionWitnessSet { assert_eq!(raw.special()?, cbor_event::Special::Break); break; } - redeemers_arr.push(Redeemer::deserialize(raw)?); + redeemers_arr.push(AlonzoRedeemer::deserialize(raw)?); } Ok((redeemers_arr, redeemers_encoding)) })() diff --git a/multi-era/rust/src/alonzo/utils.rs b/multi-era/rust/src/alonzo/utils.rs index 7dd8714f..802d8207 100644 --- a/multi-era/rust/src/alonzo/utils.rs +++ b/multi-era/rust/src/alonzo/utils.rs @@ -1,9 +1,13 @@ use cml_chain::{ auxdata::{AuxiliaryData, ConwayFormatAuxData}, + plutus::{LegacyRedeemer, RedeemerTag, Redeemers}, transaction::TransactionWitnessSet, }; -use super::{AlonzoAuxiliaryData, AlonzoTransactionBody, AlonzoTransactionWitnessSet}; +use super::{ + AlonzoAuxiliaryData, AlonzoRedeemer, AlonzoRedeemerTag, AlonzoTransactionBody, + AlonzoTransactionWitnessSet, +}; use cml_core::serialization::Serialize; use cml_crypto::{blake2b256, TransactionHash}; @@ -33,12 +37,31 @@ impl From for AuxiliaryData { impl From for TransactionWitnessSet { fn from(wits: AlonzoTransactionWitnessSet) -> Self { let mut new_wits = TransactionWitnessSet::new(); - new_wits.vkeywitnesses = wits.vkeywitnesses; - new_wits.native_scripts = wits.native_scripts; - new_wits.bootstrap_witnesses = wits.bootstrap_witnesses; - new_wits.redeemers = wits.redeemers; - new_wits.plutus_datums = wits.plutus_datums; - new_wits.plutus_v1_scripts = wits.plutus_v1_scripts; + new_wits.vkeywitnesses = wits.vkeywitnesses.map(Into::into); + new_wits.native_scripts = wits.native_scripts.map(Into::into); + new_wits.bootstrap_witnesses = wits.bootstrap_witnesses.map(Into::into); + new_wits.redeemers = wits + .redeemers + .map(|r| Redeemers::new_arr_legacy_redeemer(r.into_iter().map(Into::into).collect())); + new_wits.plutus_datums = wits.plutus_datums.map(Into::into); + new_wits.plutus_v1_scripts = wits.plutus_v1_scripts.map(Into::into); new_wits } } + +impl From for LegacyRedeemer { + fn from(redeemer: AlonzoRedeemer) -> Self { + Self { + tag: match redeemer.tag { + AlonzoRedeemerTag::Cert => RedeemerTag::Cert, + AlonzoRedeemerTag::Mint => RedeemerTag::Mint, + AlonzoRedeemerTag::Reward => RedeemerTag::Reward, + AlonzoRedeemerTag::Spend => RedeemerTag::Spend, + }, + index: redeemer.index, + data: redeemer.data, + ex_units: redeemer.ex_units, + encodings: None, + } + } +} diff --git a/multi-era/rust/src/babbage/mod.rs b/multi-era/rust/src/babbage/mod.rs index 9e193d50..0d9a9b54 100644 --- a/multi-era/rust/src/babbage/mod.rs +++ b/multi-era/rust/src/babbage/mod.rs @@ -6,6 +6,7 @@ pub mod serialization; pub mod utils; use crate::allegra::AllegraCertificate; +use crate::alonzo::AlonzoRedeemer; use crate::shelley::ProtocolVersionStruct; use cbor_encodings::{ BabbageBlockEncoding, BabbageCostModelsEncoding, BabbageFormatAuxDataEncoding, @@ -19,13 +20,9 @@ use cml_chain::block::Header; use cml_chain::crypto::{ AuxiliaryDataHash, BootstrapWitness, GenesisHash, ScriptDataHash, Vkeywitness, }; -use cml_chain::plutus::{ - ExUnitPrices, ExUnits, PlutusData, PlutusV1Script, PlutusV2Script, Redeemer, -}; -use cml_chain::transaction::{ - AlonzoFormatTxOut, DatumOption, NativeScript, RequiredSigners, TransactionInput, -}; -use cml_chain::{Epoch, NetworkId, Rational, UnitInterval, Withdrawals}; +use cml_chain::plutus::{ExUnitPrices, ExUnits, PlutusData, PlutusV1Script, PlutusV2Script}; +use cml_chain::transaction::{AlonzoFormatTxOut, DatumOption, NativeScript, TransactionInput}; +use cml_chain::{Epoch, NetworkId, Rational, RequiredSigners, UnitInterval, Withdrawals}; use cml_core::ordered_hash_map::OrderedHashMap; use cml_core::serialization::LenEncoding; @@ -380,7 +377,7 @@ pub struct BabbageTransactionWitnessSet { pub bootstrap_witnesses: Option>, pub plutus_v1_scripts: Option>, pub plutus_datums: Option>, - pub redeemers: Option>, + pub redeemers: Option>, pub plutus_v2_scripts: Option>, #[serde(skip)] pub encodings: Option, diff --git a/multi-era/rust/src/babbage/serialization.rs b/multi-era/rust/src/babbage/serialization.rs index 51156c91..ccc96304 100644 --- a/multi-era/rust/src/babbage/serialization.rs +++ b/multi-era/rust/src/babbage/serialization.rs @@ -3748,7 +3748,7 @@ impl Deserialize for BabbageTransactionBody { mint: mint.map(Into::into), script_data_hash, collateral_inputs, - required_signers, + required_signers: required_signers.map(Into::into), network_id, collateral_return, total_collateral, @@ -4350,7 +4350,7 @@ impl Deserialize for BabbageTransactionWitnessSet { assert_eq!(raw.special()?, cbor_event::Special::Break); break; } - redeemers_arr.push(Redeemer::deserialize(raw)?); + redeemers_arr.push(AlonzoRedeemer::deserialize(raw)?); } Ok((redeemers_arr, redeemers_encoding)) })() diff --git a/multi-era/rust/src/babbage/utils.rs b/multi-era/rust/src/babbage/utils.rs index b7cc38ff..fd005370 100644 --- a/multi-era/rust/src/babbage/utils.rs +++ b/multi-era/rust/src/babbage/utils.rs @@ -1,5 +1,6 @@ use cml_chain::{ auxdata::{AuxiliaryData, ConwayFormatAuxData}, + plutus::Redeemers, transaction::TransactionWitnessSet, Script, }; @@ -71,13 +72,15 @@ impl From for AuxiliaryData { impl From for TransactionWitnessSet { fn from(wits: BabbageTransactionWitnessSet) -> Self { let mut new_wits = TransactionWitnessSet::new(); - new_wits.vkeywitnesses = wits.vkeywitnesses; - new_wits.native_scripts = wits.native_scripts; - new_wits.bootstrap_witnesses = wits.bootstrap_witnesses; - new_wits.redeemers = wits.redeemers; - new_wits.plutus_datums = wits.plutus_datums; - new_wits.plutus_v1_scripts = wits.plutus_v1_scripts; - new_wits.plutus_v2_scripts = wits.plutus_v2_scripts; + new_wits.vkeywitnesses = wits.vkeywitnesses.map(Into::into); + new_wits.native_scripts = wits.native_scripts.map(Into::into); + new_wits.bootstrap_witnesses = wits.bootstrap_witnesses.map(Into::into); + new_wits.redeemers = wits.redeemers.map(|rs| { + Redeemers::new_arr_legacy_redeemer(rs.into_iter().map(Into::into).collect::>()) + }); + new_wits.plutus_datums = wits.plutus_datums.map(Into::into); + new_wits.plutus_v1_scripts = wits.plutus_v1_scripts.map(Into::into); + new_wits.plutus_v2_scripts = wits.plutus_v2_scripts.map(Into::into); new_wits } } diff --git a/multi-era/rust/src/shelley/cbor_encodings.rs b/multi-era/rust/src/shelley/cbor_encodings.rs index 7dc548a2..247d79b0 100644 --- a/multi-era/rust/src/shelley/cbor_encodings.rs +++ b/multi-era/rust/src/shelley/cbor_encodings.rs @@ -57,6 +57,11 @@ pub struct ShelleyBlockEncoding { pub transaction_metadata_set_key_encodings: BTreeMap>, } +#[derive(Clone, Debug, Default)] +pub struct ShelleyDnsNameEncoding { + pub inner_encoding: StringEncoding, +} + #[derive(Clone, Debug, Default)] pub struct ShelleyHeaderBodyEncoding { pub len_encoding: LenEncoding, @@ -88,6 +93,30 @@ pub struct ShelleyMoveInstantaneousRewardsCertEncoding { pub tag_encoding: Option, } +#[derive(Clone, Debug, Default)] +pub struct ShelleyMultiHostNameEncoding { + pub len_encoding: LenEncoding, + pub tag_encoding: Option, +} + +#[derive(Clone, Debug, Default)] +pub struct ShelleyPoolParamsEncoding { + pub len_encoding: LenEncoding, + pub operator_encoding: StringEncoding, + pub vrf_keyhash_encoding: StringEncoding, + pub pledge_encoding: Option, + pub cost_encoding: Option, + pub pool_owners_encoding: LenEncoding, + pub pool_owners_elem_encodings: Vec, + pub relays_encoding: LenEncoding, +} + +#[derive(Clone, Debug, Default)] +pub struct ShelleyPoolRegistrationEncoding { + pub len_encoding: LenEncoding, + pub tag_encoding: Option, +} + #[derive(Clone, Debug, Default)] pub struct ShelleyProtocolParamUpdateEncoding { pub len_encoding: LenEncoding, @@ -120,6 +149,13 @@ pub struct ShelleyProtocolParamUpdateEncoding { pub min_utxo_value_key_encoding: Option, } +#[derive(Clone, Debug, Default)] +pub struct ShelleySingleHostNameEncoding { + pub len_encoding: LenEncoding, + pub tag_encoding: Option, + pub port_encoding: Option, +} + #[derive(Clone, Debug, Default)] pub struct ShelleyTransactionBodyEncoding { pub len_encoding: LenEncoding, diff --git a/multi-era/rust/src/shelley/mod.rs b/multi-era/rust/src/shelley/mod.rs index 23985e7c..d42a3c90 100644 --- a/multi-era/rust/src/shelley/mod.rs +++ b/multi-era/rust/src/shelley/mod.rs @@ -8,15 +8,17 @@ pub mod utils; use cbor_encodings::{ MultisigAllEncoding, MultisigAnyEncoding, MultisigNOfKEncoding, MultisigPubkeyEncoding, ShelleyBlockEncoding, ShelleyHeaderBodyEncoding, ShelleyHeaderEncoding, - ShelleyProtocolParamUpdateEncoding, ShelleyTransactionBodyEncoding, ShelleyTransactionEncoding, - ShelleyTransactionOutputEncoding, ShelleyTransactionWitnessSetEncoding, ShelleyUpdateEncoding, + ShelleyMultiHostNameEncoding, ShelleyPoolRegistrationEncoding, + ShelleyProtocolParamUpdateEncoding, ShelleySingleHostNameEncoding, + ShelleyTransactionBodyEncoding, ShelleyTransactionEncoding, ShelleyTransactionOutputEncoding, + ShelleyTransactionWitnessSetEncoding, ShelleyUpdateEncoding, }; -use cml_chain::address::Address; +use cml_chain::address::{Address, RewardAccount}; use cml_chain::assets::Coin; use cml_chain::auxdata::Metadata; use cml_chain::block::{OperationalCert, ProtocolVersion}; use cml_chain::certs::{ - PoolParams, PoolRegistration, PoolRetirement, StakeCredential, StakeDelegation, + Ipv4, Ipv6, PoolMetadata, PoolRetirement, SingleHostAddr, StakeCredential, StakeDelegation, StakeDeregistration, StakeRegistration, }; use cml_chain::crypto::{ @@ -24,17 +26,19 @@ use cml_chain::crypto::{ GenesisHash, KESSignature, Nonce, VRFCert, VRFVkey, Vkey, Vkeywitness, }; use cml_chain::transaction::TransactionInput; -use cml_chain::{Epoch, LenEncoding, Rational, UnitInterval, Withdrawals}; +use cml_chain::{Epoch, Port, Rational, UnitInterval, Withdrawals}; use cml_core::ordered_hash_map::OrderedHashMap; -use cml_core::TransactionIndex; +use cml_core::{DeserializeError, DeserializeFailure, TransactionIndex}; use cml_crypto::{GenesisDelegateHash, VRFKeyHash}; use std::collections::BTreeMap; +use std::convert::TryFrom; use crate::allegra::MIRPot; use self::cbor_encodings::{ - GenesisKeyDelegationEncoding, ProtocolVersionStructEncoding, + GenesisKeyDelegationEncoding, ProtocolVersionStructEncoding, ShelleyDnsNameEncoding, ShelleyMoveInstantaneousRewardEncoding, ShelleyMoveInstantaneousRewardsCertEncoding, + ShelleyPoolParamsEncoding, }; #[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] pub struct GenesisKeyDelegation { @@ -201,14 +205,10 @@ pub enum ShelleyCertificate { StakeRegistration(StakeRegistration), StakeDeregistration(StakeDeregistration), StakeDelegation(StakeDelegation), - PoolRegistration(PoolRegistration), + ShelleyPoolRegistration(ShelleyPoolRegistration), PoolRetirement(PoolRetirement), GenesisKeyDelegation(GenesisKeyDelegation), - ShelleyMoveInstantaneousRewardsCert { - shelley_move_instantaneous_rewards_cert: ShelleyMoveInstantaneousRewardsCert, - #[serde(skip)] - len_encoding: LenEncoding, - }, + ShelleyMoveInstantaneousRewardsCert(ShelleyMoveInstantaneousRewardsCert), } impl ShelleyCertificate { @@ -227,8 +227,8 @@ impl ShelleyCertificate { Self::StakeDelegation(StakeDelegation::new(stake_credential, ed25519_key_hash)) } - pub fn new_pool_registration(pool_params: PoolParams) -> Self { - Self::PoolRegistration(PoolRegistration::new(pool_params)) + pub fn new_shelley_pool_registration(pool_params: ShelleyPoolParams) -> Self { + Self::ShelleyPoolRegistration(ShelleyPoolRegistration::new(pool_params)) } pub fn new_pool_retirement(ed25519_key_hash: Ed25519KeyHash, epoch: Epoch) -> Self { @@ -250,12 +250,84 @@ impl ShelleyCertificate { pub fn new_shelley_move_instantaneous_rewards_cert( shelley_move_instantaneous_reward: ShelleyMoveInstantaneousReward, ) -> Self { - Self::ShelleyMoveInstantaneousRewardsCert { - shelley_move_instantaneous_rewards_cert: ShelleyMoveInstantaneousRewardsCert::new( - shelley_move_instantaneous_reward, - ), - len_encoding: LenEncoding::default(), + Self::ShelleyMoveInstantaneousRewardsCert(ShelleyMoveInstantaneousRewardsCert::new( + shelley_move_instantaneous_reward, + )) + } +} + +#[derive(Clone, Debug)] +pub struct ShelleyDnsName { + pub inner: String, + pub encodings: Option, +} + +impl ShelleyDnsName { + pub fn get(&self) -> &String { + &self.inner + } + + pub fn new(inner: String) -> Result { + if inner.len() > 64 { + return Err(DeserializeError::new( + "ShelleyDnsName", + DeserializeFailure::RangeCheck { + found: inner.len() as isize, + min: Some(0), + max: Some(64), + }, + )); } + Ok(Self { + inner, + encodings: None, + }) + } +} + +impl TryFrom for ShelleyDnsName { + type Error = DeserializeError; + + fn try_from(inner: String) -> Result { + ShelleyDnsName::new(inner) + } +} + +impl serde::Serialize for ShelleyDnsName { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + self.inner.serialize(serializer) + } +} + +impl<'de> serde::de::Deserialize<'de> for ShelleyDnsName { + fn deserialize(deserializer: D) -> Result + where + D: serde::de::Deserializer<'de>, + { + let inner = ::deserialize(deserializer)?; + Self::new(inner.clone()).map_err(|_e| { + serde::de::Error::invalid_value( + serde::de::Unexpected::Str(&inner), + &"invalid ShelleyDnsName", + ) + }) + } +} + +impl schemars::JsonSchema for ShelleyDnsName { + fn schema_name() -> String { + String::from("ShelleyDnsName") + } + + fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema { + String::json_schema(gen) + } + + fn is_referenceable() -> bool { + String::is_referenceable() } } @@ -359,6 +431,80 @@ impl ShelleyMoveInstantaneousRewardsCert { } } +#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] +pub struct ShelleyMultiHostName { + pub shelley_dns_name: ShelleyDnsName, + #[serde(skip)] + pub encodings: Option, +} + +impl ShelleyMultiHostName { + pub fn new(shelley_dns_name: ShelleyDnsName) -> Self { + Self { + shelley_dns_name, + encodings: None, + } + } +} + +#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] +pub struct ShelleyPoolParams { + pub operator: Ed25519KeyHash, + pub vrf_keyhash: VRFKeyHash, + pub pledge: Coin, + pub cost: Coin, + pub margin: UnitInterval, + pub reward_account: RewardAccount, + pub pool_owners: Vec, + pub relays: Vec, + pub pool_metadata: Option, + #[serde(skip)] + pub encodings: Option, +} + +impl ShelleyPoolParams { + pub fn new( + operator: Ed25519KeyHash, + vrf_keyhash: VRFKeyHash, + pledge: Coin, + cost: Coin, + margin: UnitInterval, + reward_account: RewardAccount, + pool_owners: Vec, + relays: Vec, + pool_metadata: Option, + ) -> Self { + Self { + operator, + vrf_keyhash, + pledge, + cost, + margin, + reward_account, + pool_owners, + relays, + pool_metadata, + encodings: None, + } + } +} + +#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] +pub struct ShelleyPoolRegistration { + pub pool_params: ShelleyPoolParams, + #[serde(skip)] + pub encodings: Option, +} + +impl ShelleyPoolRegistration { + pub fn new(pool_params: ShelleyPoolParams) -> Self { + Self { + pool_params, + encodings: None, + } + } +} + pub type ShelleyProposedProtocolParameterUpdates = OrderedHashMap; @@ -414,6 +560,52 @@ impl Default for ShelleyProtocolParamUpdate { } } +#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] +pub enum ShelleyRelay { + SingleHostAddr(SingleHostAddr), + ShelleySingleHostName(ShelleySingleHostName), + ShelleyMultiHostName(ShelleyMultiHostName), +} + +impl ShelleyRelay { + pub fn new_single_host_addr( + port: Option, + ipv4: Option, + ipv6: Option, + ) -> Self { + Self::SingleHostAddr(SingleHostAddr::new(port, ipv4, ipv6)) + } + + pub fn new_shelley_single_host_name( + port: Option, + shelley_dns_name: ShelleyDnsName, + ) -> Self { + Self::ShelleySingleHostName(ShelleySingleHostName::new(port, shelley_dns_name)) + } + + pub fn new_shelley_multi_host_name(shelley_dns_name: ShelleyDnsName) -> Self { + Self::ShelleyMultiHostName(ShelleyMultiHostName::new(shelley_dns_name)) + } +} + +#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] +pub struct ShelleySingleHostName { + pub port: Option, + pub shelley_dns_name: ShelleyDnsName, + #[serde(skip)] + pub encodings: Option, +} + +impl ShelleySingleHostName { + pub fn new(port: Option, shelley_dns_name: ShelleyDnsName) -> Self { + Self { + port, + shelley_dns_name, + encodings: None, + } + } +} + #[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] pub struct ShelleyTransaction { pub body: ShelleyTransactionBody, @@ -539,3 +731,9 @@ impl ShelleyUpdate { } } } + +impl From for String { + fn from(wrapper: ShelleyDnsName) -> Self { + wrapper.inner + } +} diff --git a/multi-era/rust/src/shelley/serialization.rs b/multi-era/rust/src/shelley/serialization.rs index 2a8cbad3..a69361b7 100644 --- a/multi-era/rust/src/shelley/serialization.rs +++ b/multi-era/rust/src/shelley/serialization.rs @@ -7,6 +7,7 @@ use cbor_event; use cbor_event::de::Deserializer; use cbor_event::se::Serializer; use cml_chain::address::RewardAccount; +use cml_chain::certs::{PoolMetadata, SingleHostAddr}; use cml_core::error::*; use cml_core::serialization::*; use cml_crypto::GenesisDelegateHash; @@ -1095,8 +1096,8 @@ impl Serialize for ShelleyCertificate { ShelleyCertificate::StakeDelegation(stake_delegation) => { stake_delegation.serialize(serializer, force_canonical) } - ShelleyCertificate::PoolRegistration(pool_registration) => { - pool_registration.serialize(serializer, force_canonical) + ShelleyCertificate::ShelleyPoolRegistration(shelley_pool_registration) => { + shelley_pool_registration.serialize(serializer, force_canonical) } ShelleyCertificate::PoolRetirement(pool_retirement) => { pool_retirement.serialize(serializer, force_canonical) @@ -1104,15 +1105,9 @@ impl Serialize for ShelleyCertificate { ShelleyCertificate::GenesisKeyDelegation(genesis_key_delegation) => { genesis_key_delegation.serialize(serializer, force_canonical) } - ShelleyCertificate::ShelleyMoveInstantaneousRewardsCert { + ShelleyCertificate::ShelleyMoveInstantaneousRewardsCert( shelley_move_instantaneous_rewards_cert, - len_encoding, - } => { - serializer.write_array_sz(len_encoding.to_len_sz(1, force_canonical))?; - shelley_move_instantaneous_rewards_cert.serialize(serializer, force_canonical)?; - len_encoding.end(serializer, force_canonical)?; - Ok(serializer) - } + ) => shelley_move_instantaneous_rewards_cert.serialize(serializer, force_canonical), } } } @@ -1121,7 +1116,6 @@ impl Deserialize for ShelleyCertificate { fn deserialize(raw: &mut Deserializer) -> Result { (|| -> Result<_, DeserializeError> { let len = raw.array_sz()?; - let len_encoding: LenEncoding = len.into(); let initial_position = raw.as_mut_ref().stream_position().unwrap(); let mut errs = Vec::new(); let deser_variant = (|raw: &mut Deserializer<_>| -> Result<_, DeserializeError> { @@ -1200,7 +1194,8 @@ impl Deserialize for ShelleyCertificate { let mut read_len = CBORReadLen::new(len); read_len.read_elems(10)?; read_len.finish()?; - let ret = PoolRegistration::deserialize_as_embedded_group(raw, &mut read_len, len); + let ret = + ShelleyPoolRegistration::deserialize_as_embedded_group(raw, &mut read_len, len); match len { cbor_event::LenSz::Len(_, _) => (), cbor_event::LenSz::Indefinite => match raw.special()? { @@ -1211,9 +1206,11 @@ impl Deserialize for ShelleyCertificate { ret })(raw); match deser_variant { - Ok(pool_registration) => return Ok(Self::PoolRegistration(pool_registration)), + Ok(shelley_pool_registration) => { + return Ok(Self::ShelleyPoolRegistration(shelley_pool_registration)) + } Err(e) => { - errs.push(e.annotate("PoolRegistration")); + errs.push(e.annotate("ShelleyPoolRegistration")); raw.as_mut_ref() .seek(SeekFrom::Start(initial_position)) .unwrap(); @@ -1270,9 +1267,13 @@ impl Deserialize for ShelleyCertificate { }; let deser_variant = (|raw: &mut Deserializer<_>| -> Result<_, DeserializeError> { let mut read_len = CBORReadLen::new(len); - read_len.read_elems(1)?; + read_len.read_elems(2)?; read_len.finish()?; - let ret = ShelleyMoveInstantaneousRewardsCert::deserialize(raw); + let ret = ShelleyMoveInstantaneousRewardsCert::deserialize_as_embedded_group( + raw, + &mut read_len, + len, + ); match len { cbor_event::LenSz::Len(_, _) => (), cbor_event::LenSz::Indefinite => match raw.special()? { @@ -1284,10 +1285,9 @@ impl Deserialize for ShelleyCertificate { })(raw); match deser_variant { Ok(shelley_move_instantaneous_rewards_cert) => { - return Ok(Self::ShelleyMoveInstantaneousRewardsCert { + return Ok(Self::ShelleyMoveInstantaneousRewardsCert( shelley_move_instantaneous_rewards_cert, - len_encoding, - }) + )) } Err(e) => { errs.push(e.annotate("ShelleyMoveInstantaneousRewardsCert")); @@ -1305,6 +1305,45 @@ impl Deserialize for ShelleyCertificate { } } +impl Serialize for ShelleyDnsName { + fn serialize<'se, W: Write>( + &self, + serializer: &'se mut Serializer, + force_canonical: bool, + ) -> cbor_event::Result<&'se mut Serializer> { + serializer.write_text_sz( + &self.inner, + self.encodings + .as_ref() + .map(|encs| encs.inner_encoding.clone()) + .unwrap_or_default() + .to_str_len_sz(self.inner.len() as u64, force_canonical), + ) + } +} + +impl Deserialize for ShelleyDnsName { + fn deserialize(raw: &mut Deserializer) -> Result { + let (inner, inner_encoding) = raw + .text_sz() + .map(|(s, enc)| (s, StringEncoding::from(enc)))?; + if inner.len() > 64 { + return Err(DeserializeError::new( + "ShelleyDnsName", + DeserializeFailure::RangeCheck { + found: inner.len() as isize, + min: Some(0), + max: Some(64), + }, + )); + } + Ok(Self { + inner, + encodings: Some(ShelleyDnsNameEncoding { inner_encoding }), + }) + } +} + impl Serialize for ShelleyHeader { fn serialize<'se, W: Write>( &self, @@ -1768,17 +1807,476 @@ impl Deserialize for ShelleyMoveInstantaneousReward { to_stake_credentials, encodings: Some(ShelleyMoveInstantaneousRewardEncoding { len_encoding, - pot_encoding, - to_stake_credentials_encoding, - to_stake_credentials_value_encodings, + pot_encoding, + to_stake_credentials_encoding, + to_stake_credentials_value_encodings, + }), + }) + })() + .map_err(|e| e.annotate("ShelleyMoveInstantaneousReward")) + } +} + +impl Serialize for ShelleyMoveInstantaneousRewardsCert { + fn serialize<'se, W: Write>( + &self, + serializer: &'se mut Serializer, + force_canonical: bool, + ) -> cbor_event::Result<&'se mut Serializer> { + serializer.write_array_sz( + self.encodings + .as_ref() + .map(|encs| encs.len_encoding) + .unwrap_or_default() + .to_len_sz(2, force_canonical), + )?; + self.serialize_as_embedded_group(serializer, force_canonical) + } +} + +impl SerializeEmbeddedGroup for ShelleyMoveInstantaneousRewardsCert { + fn serialize_as_embedded_group<'se, W: Write>( + &self, + serializer: &'se mut Serializer, + force_canonical: bool, + ) -> cbor_event::Result<&'se mut Serializer> { + serializer.write_unsigned_integer_sz( + 6u64, + fit_sz( + 6u64, + self.encodings + .as_ref() + .map(|encs| encs.tag_encoding) + .unwrap_or_default(), + force_canonical, + ), + )?; + self.shelley_move_instantaneous_reward + .serialize(serializer, force_canonical)?; + self.encodings + .as_ref() + .map(|encs| encs.len_encoding) + .unwrap_or_default() + .end(serializer, force_canonical) + } +} + +impl Deserialize for ShelleyMoveInstantaneousRewardsCert { + fn deserialize(raw: &mut Deserializer) -> Result { + let len = raw.array_sz()?; + let mut read_len = CBORReadLen::new(len); + read_len.read_elems(2)?; + read_len.finish()?; + let ret = Self::deserialize_as_embedded_group(raw, &mut read_len, len); + match len { + cbor_event::LenSz::Len(_, _) => (), + cbor_event::LenSz::Indefinite => match raw.special()? { + cbor_event::Special::Break => (), + _ => return Err(DeserializeFailure::EndingBreakMissing.into()), + }, + } + ret + } +} + +impl DeserializeEmbeddedGroup for ShelleyMoveInstantaneousRewardsCert { + fn deserialize_as_embedded_group( + raw: &mut Deserializer, + _read_len: &mut CBORReadLen, + len: cbor_event::LenSz, + ) -> Result { + let len_encoding = len.into(); + (|| -> Result<_, DeserializeError> { + let tag_encoding = (|| -> Result<_, DeserializeError> { + let (tag_value, tag_encoding) = raw.unsigned_integer_sz()?; + if tag_value != 6 { + return Err(DeserializeFailure::FixedValueMismatch { + found: Key::Uint(tag_value), + expected: Key::Uint(6), + } + .into()); + } + Ok(Some(tag_encoding)) + })() + .map_err(|e| e.annotate("tag"))?; + let shelley_move_instantaneous_reward = ShelleyMoveInstantaneousReward::deserialize( + raw, + ) + .map_err(|e: DeserializeError| e.annotate("shelley_move_instantaneous_reward"))?; + Ok(ShelleyMoveInstantaneousRewardsCert { + shelley_move_instantaneous_reward, + encodings: Some(ShelleyMoveInstantaneousRewardsCertEncoding { + len_encoding, + tag_encoding, + }), + }) + })() + .map_err(|e| e.annotate("ShelleyMoveInstantaneousRewardsCert")) + } +} + +impl Serialize for ShelleyMultiHostName { + fn serialize<'se, W: Write>( + &self, + serializer: &'se mut Serializer, + force_canonical: bool, + ) -> cbor_event::Result<&'se mut Serializer> { + serializer.write_array_sz( + self.encodings + .as_ref() + .map(|encs| encs.len_encoding) + .unwrap_or_default() + .to_len_sz(2, force_canonical), + )?; + self.serialize_as_embedded_group(serializer, force_canonical) + } +} + +impl SerializeEmbeddedGroup for ShelleyMultiHostName { + fn serialize_as_embedded_group<'se, W: Write>( + &self, + serializer: &'se mut Serializer, + force_canonical: bool, + ) -> cbor_event::Result<&'se mut Serializer> { + serializer.write_unsigned_integer_sz( + 2u64, + fit_sz( + 2u64, + self.encodings + .as_ref() + .map(|encs| encs.tag_encoding) + .unwrap_or_default(), + force_canonical, + ), + )?; + self.shelley_dns_name + .serialize(serializer, force_canonical)?; + self.encodings + .as_ref() + .map(|encs| encs.len_encoding) + .unwrap_or_default() + .end(serializer, force_canonical) + } +} + +impl Deserialize for ShelleyMultiHostName { + fn deserialize(raw: &mut Deserializer) -> Result { + let len = raw.array_sz()?; + let mut read_len = CBORReadLen::new(len); + read_len.read_elems(2)?; + read_len.finish()?; + let ret = Self::deserialize_as_embedded_group(raw, &mut read_len, len); + match len { + cbor_event::LenSz::Len(_, _) => (), + cbor_event::LenSz::Indefinite => match raw.special()? { + cbor_event::Special::Break => (), + _ => return Err(DeserializeFailure::EndingBreakMissing.into()), + }, + } + ret + } +} + +impl DeserializeEmbeddedGroup for ShelleyMultiHostName { + fn deserialize_as_embedded_group( + raw: &mut Deserializer, + _read_len: &mut CBORReadLen, + len: cbor_event::LenSz, + ) -> Result { + let len_encoding = len.into(); + (|| -> Result<_, DeserializeError> { + let tag_encoding = (|| -> Result<_, DeserializeError> { + let (tag_value, tag_encoding) = raw.unsigned_integer_sz()?; + if tag_value != 2 { + return Err(DeserializeFailure::FixedValueMismatch { + found: Key::Uint(tag_value), + expected: Key::Uint(2), + } + .into()); + } + Ok(Some(tag_encoding)) + })() + .map_err(|e| e.annotate("tag"))?; + let shelley_dns_name = ShelleyDnsName::deserialize(raw) + .map_err(|e: DeserializeError| e.annotate("shelley_dns_name"))?; + Ok(ShelleyMultiHostName { + shelley_dns_name, + encodings: Some(ShelleyMultiHostNameEncoding { + len_encoding, + tag_encoding, + }), + }) + })() + .map_err(|e| e.annotate("ShelleyMultiHostName")) + } +} + +impl Serialize for ShelleyPoolParams { + fn serialize<'se, W: Write>( + &self, + serializer: &'se mut Serializer, + force_canonical: bool, + ) -> cbor_event::Result<&'se mut Serializer> { + serializer.write_array_sz( + self.encodings + .as_ref() + .map(|encs| encs.len_encoding) + .unwrap_or_default() + .to_len_sz(9, force_canonical), + )?; + self.serialize_as_embedded_group(serializer, force_canonical) + } +} + +impl SerializeEmbeddedGroup for ShelleyPoolParams { + fn serialize_as_embedded_group<'se, W: Write>( + &self, + serializer: &'se mut Serializer, + force_canonical: bool, + ) -> cbor_event::Result<&'se mut Serializer> { + serializer.write_bytes_sz( + self.operator.to_raw_bytes(), + self.encodings + .as_ref() + .map(|encs| encs.operator_encoding.clone()) + .unwrap_or_default() + .to_str_len_sz(self.operator.to_raw_bytes().len() as u64, force_canonical), + )?; + serializer.write_bytes_sz( + self.vrf_keyhash.to_raw_bytes(), + self.encodings + .as_ref() + .map(|encs| encs.vrf_keyhash_encoding.clone()) + .unwrap_or_default() + .to_str_len_sz( + self.vrf_keyhash.to_raw_bytes().len() as u64, + force_canonical, + ), + )?; + serializer.write_unsigned_integer_sz( + self.pledge, + fit_sz( + self.pledge, + self.encodings + .as_ref() + .map(|encs| encs.pledge_encoding) + .unwrap_or_default(), + force_canonical, + ), + )?; + serializer.write_unsigned_integer_sz( + self.cost, + fit_sz( + self.cost, + self.encodings + .as_ref() + .map(|encs| encs.cost_encoding) + .unwrap_or_default(), + force_canonical, + ), + )?; + self.margin.serialize(serializer, force_canonical)?; + self.reward_account.serialize(serializer, force_canonical)?; + serializer.write_array_sz( + self.encodings + .as_ref() + .map(|encs| encs.pool_owners_encoding) + .unwrap_or_default() + .to_len_sz(self.pool_owners.len() as u64, force_canonical), + )?; + for (i, element) in self.pool_owners.iter().enumerate() { + let pool_owners_elem_encoding = self + .encodings + .as_ref() + .and_then(|encs| encs.pool_owners_elem_encodings.get(i)) + .cloned() + .unwrap_or_default(); + serializer.write_bytes_sz( + element.to_raw_bytes(), + pool_owners_elem_encoding + .to_str_len_sz(element.to_raw_bytes().len() as u64, force_canonical), + )?; + } + self.encodings + .as_ref() + .map(|encs| encs.pool_owners_encoding) + .unwrap_or_default() + .end(serializer, force_canonical)?; + serializer.write_array_sz( + self.encodings + .as_ref() + .map(|encs| encs.relays_encoding) + .unwrap_or_default() + .to_len_sz(self.relays.len() as u64, force_canonical), + )?; + for element in self.relays.iter() { + element.serialize(serializer, force_canonical)?; + } + self.encodings + .as_ref() + .map(|encs| encs.relays_encoding) + .unwrap_or_default() + .end(serializer, force_canonical)?; + match &self.pool_metadata { + Some(x) => x.serialize(serializer, force_canonical), + None => serializer.write_special(cbor_event::Special::Null), + }?; + self.encodings + .as_ref() + .map(|encs| encs.len_encoding) + .unwrap_or_default() + .end(serializer, force_canonical) + } +} + +impl Deserialize for ShelleyPoolParams { + fn deserialize(raw: &mut Deserializer) -> Result { + let len = raw.array_sz()?; + let mut read_len = CBORReadLen::new(len); + read_len.read_elems(9)?; + read_len.finish()?; + let ret = Self::deserialize_as_embedded_group(raw, &mut read_len, len); + match len { + cbor_event::LenSz::Len(_, _) => (), + cbor_event::LenSz::Indefinite => match raw.special()? { + cbor_event::Special::Break => (), + _ => return Err(DeserializeFailure::EndingBreakMissing.into()), + }, + } + ret + } +} + +impl DeserializeEmbeddedGroup for ShelleyPoolParams { + fn deserialize_as_embedded_group( + raw: &mut Deserializer, + _read_len: &mut CBORReadLen, + len: cbor_event::LenSz, + ) -> Result { + let len_encoding = len.into(); + (|| -> Result<_, DeserializeError> { + let (operator, operator_encoding) = raw + .bytes_sz() + .map_err(Into::::into) + .and_then(|(bytes, enc)| { + Ed25519KeyHash::from_raw_bytes(&bytes) + .map(|bytes| (bytes, StringEncoding::from(enc))) + .map_err(|e| DeserializeFailure::InvalidStructure(Box::new(e)).into()) + }) + .map_err(|e: DeserializeError| e.annotate("operator"))?; + let (vrf_keyhash, vrf_keyhash_encoding) = raw + .bytes_sz() + .map_err(Into::::into) + .and_then(|(bytes, enc)| { + VRFKeyHash::from_raw_bytes(&bytes) + .map(|bytes| (bytes, StringEncoding::from(enc))) + .map_err(|e| DeserializeFailure::InvalidStructure(Box::new(e)).into()) + }) + .map_err(|e: DeserializeError| e.annotate("vrf_keyhash"))?; + let (pledge, pledge_encoding) = raw + .unsigned_integer_sz() + .map_err(Into::::into) + .map(|(x, enc)| (x, Some(enc))) + .map_err(|e: DeserializeError| e.annotate("pledge"))?; + let (cost, cost_encoding) = raw + .unsigned_integer_sz() + .map_err(Into::::into) + .map(|(x, enc)| (x, Some(enc))) + .map_err(|e: DeserializeError| e.annotate("cost"))?; + let margin = UnitInterval::deserialize(raw) + .map_err(|e: DeserializeError| e.annotate("margin"))?; + let reward_account = RewardAccount::deserialize(raw) + .map_err(|e: DeserializeError| e.annotate("reward_account"))?; + let (pool_owners, pool_owners_encoding, pool_owners_elem_encodings) = + (|| -> Result<_, DeserializeError> { + let mut pool_owners_arr = Vec::new(); + let len = raw.array_sz()?; + let pool_owners_encoding = len.into(); + let mut pool_owners_elem_encodings = Vec::new(); + while match len { + cbor_event::LenSz::Len(n, _) => (pool_owners_arr.len() as u64) < n, + cbor_event::LenSz::Indefinite => true, + } { + if raw.cbor_type()? == cbor_event::Type::Special { + assert_eq!(raw.special()?, cbor_event::Special::Break); + break; + } + let (pool_owners_elem, pool_owners_elem_encoding) = raw + .bytes_sz() + .map_err(Into::::into) + .and_then(|(bytes, enc)| { + Ed25519KeyHash::from_raw_bytes(&bytes) + .map(|bytes| (bytes, StringEncoding::from(enc))) + .map_err(|e| { + DeserializeFailure::InvalidStructure(Box::new(e)).into() + }) + })?; + pool_owners_arr.push(pool_owners_elem); + pool_owners_elem_encodings.push(pool_owners_elem_encoding); + } + Ok(( + pool_owners_arr, + pool_owners_encoding, + pool_owners_elem_encodings, + )) + })() + .map_err(|e| e.annotate("pool_owners"))?; + let (relays, relays_encoding) = (|| -> Result<_, DeserializeError> { + let mut relays_arr = Vec::new(); + let len = raw.array_sz()?; + let relays_encoding = len.into(); + while match len { + cbor_event::LenSz::Len(n, _) => (relays_arr.len() as u64) < n, + cbor_event::LenSz::Indefinite => true, + } { + if raw.cbor_type()? == cbor_event::Type::Special { + assert_eq!(raw.special()?, cbor_event::Special::Break); + break; + } + relays_arr.push(ShelleyRelay::deserialize(raw)?); + } + Ok((relays_arr, relays_encoding)) + })() + .map_err(|e| e.annotate("relays"))?; + let pool_metadata = (|| -> Result<_, DeserializeError> { + Ok(match raw.cbor_type()? != cbor_event::Type::Special { + true => Some(PoolMetadata::deserialize(raw)?), + false => { + if raw.special()? != cbor_event::Special::Null { + return Err(DeserializeFailure::ExpectedNull.into()); + } + None + } + }) + })() + .map_err(|e| e.annotate("pool_metadata"))?; + Ok(ShelleyPoolParams { + operator, + vrf_keyhash, + pledge, + cost, + margin, + reward_account, + pool_owners, + relays, + pool_metadata, + encodings: Some(ShelleyPoolParamsEncoding { + len_encoding, + operator_encoding, + vrf_keyhash_encoding, + pledge_encoding, + cost_encoding, + pool_owners_encoding, + pool_owners_elem_encodings, + relays_encoding, }), }) })() - .map_err(|e| e.annotate("ShelleyMoveInstantaneousReward")) + .map_err(|e| e.annotate("ShelleyPoolParams")) } } -impl Serialize for ShelleyMoveInstantaneousRewardsCert { +impl Serialize for ShelleyPoolRegistration { fn serialize<'se, W: Write>( &self, serializer: &'se mut Serializer, @@ -1789,12 +2287,22 @@ impl Serialize for ShelleyMoveInstantaneousRewardsCert { .as_ref() .map(|encs| encs.len_encoding) .unwrap_or_default() - .to_len_sz(2, force_canonical), + .to_len_sz(10, force_canonical), )?; + self.serialize_as_embedded_group(serializer, force_canonical) + } +} + +impl SerializeEmbeddedGroup for ShelleyPoolRegistration { + fn serialize_as_embedded_group<'se, W: Write>( + &self, + serializer: &'se mut Serializer, + force_canonical: bool, + ) -> cbor_event::Result<&'se mut Serializer> { serializer.write_unsigned_integer_sz( - 6u64, + 3u64, fit_sz( - 6u64, + 3u64, self.encodings .as_ref() .map(|encs| encs.tag_encoding) @@ -1802,8 +2310,8 @@ impl Serialize for ShelleyMoveInstantaneousRewardsCert { force_canonical, ), )?; - self.shelley_move_instantaneous_reward - .serialize(serializer, force_canonical)?; + self.pool_params + .serialize_as_embedded_group(serializer, force_canonical)?; self.encodings .as_ref() .map(|encs| encs.len_encoding) @@ -1812,46 +2320,55 @@ impl Serialize for ShelleyMoveInstantaneousRewardsCert { } } -impl Deserialize for ShelleyMoveInstantaneousRewardsCert { +impl Deserialize for ShelleyPoolRegistration { fn deserialize(raw: &mut Deserializer) -> Result { let len = raw.array_sz()?; - let len_encoding: LenEncoding = len.into(); let mut read_len = CBORReadLen::new(len); - read_len.read_elems(2)?; + read_len.read_elems(10)?; read_len.finish()?; + let ret = Self::deserialize_as_embedded_group(raw, &mut read_len, len); + match len { + cbor_event::LenSz::Len(_, _) => (), + cbor_event::LenSz::Indefinite => match raw.special()? { + cbor_event::Special::Break => (), + _ => return Err(DeserializeFailure::EndingBreakMissing.into()), + }, + } + ret + } +} + +impl DeserializeEmbeddedGroup for ShelleyPoolRegistration { + fn deserialize_as_embedded_group( + raw: &mut Deserializer, + read_len: &mut CBORReadLen, + len: cbor_event::LenSz, + ) -> Result { + let len_encoding = len.into(); (|| -> Result<_, DeserializeError> { let tag_encoding = (|| -> Result<_, DeserializeError> { let (tag_value, tag_encoding) = raw.unsigned_integer_sz()?; - if tag_value != 6 { + if tag_value != 3 { return Err(DeserializeFailure::FixedValueMismatch { found: Key::Uint(tag_value), - expected: Key::Uint(6), + expected: Key::Uint(3), } .into()); } Ok(Some(tag_encoding)) })() .map_err(|e| e.annotate("tag"))?; - let shelley_move_instantaneous_reward = ShelleyMoveInstantaneousReward::deserialize( - raw, - ) - .map_err(|e: DeserializeError| e.annotate("shelley_move_instantaneous_reward"))?; - match len { - cbor_event::LenSz::Len(_, _) => (), - cbor_event::LenSz::Indefinite => match raw.special()? { - cbor_event::Special::Break => (), - _ => return Err(DeserializeFailure::EndingBreakMissing.into()), - }, - } - Ok(ShelleyMoveInstantaneousRewardsCert { - shelley_move_instantaneous_reward, - encodings: Some(ShelleyMoveInstantaneousRewardsCertEncoding { + let pool_params = ShelleyPoolParams::deserialize_as_embedded_group(raw, read_len, len) + .map_err(|e: DeserializeError| e.annotate("pool_params"))?; + Ok(ShelleyPoolRegistration { + pool_params, + encodings: Some(ShelleyPoolRegistrationEncoding { len_encoding, tag_encoding, }), }) })() - .map_err(|e| e.annotate("ShelleyMoveInstantaneousRewardsCert")) + .map_err(|e| e.annotate("ShelleyPoolRegistration")) } } @@ -2729,6 +3246,244 @@ impl Deserialize for ShelleyProtocolParamUpdate { } } +impl Serialize for ShelleyRelay { + fn serialize<'se, W: Write>( + &self, + serializer: &'se mut Serializer, + force_canonical: bool, + ) -> cbor_event::Result<&'se mut Serializer> { + match self { + ShelleyRelay::SingleHostAddr(single_host_addr) => { + single_host_addr.serialize(serializer, force_canonical) + } + ShelleyRelay::ShelleySingleHostName(shelley_single_host_name) => { + shelley_single_host_name.serialize(serializer, force_canonical) + } + ShelleyRelay::ShelleyMultiHostName(shelley_multi_host_name) => { + shelley_multi_host_name.serialize(serializer, force_canonical) + } + } + } +} + +impl Deserialize for ShelleyRelay { + fn deserialize(raw: &mut Deserializer) -> Result { + (|| -> Result<_, DeserializeError> { + let len = raw.array_sz()?; + let initial_position = raw.as_mut_ref().stream_position().unwrap(); + let mut errs = Vec::new(); + let deser_variant = (|raw: &mut Deserializer<_>| -> Result<_, DeserializeError> { + let mut read_len = CBORReadLen::new(len); + read_len.read_elems(4)?; + read_len.finish()?; + let ret = SingleHostAddr::deserialize_as_embedded_group(raw, &mut read_len, len); + match len { + cbor_event::LenSz::Len(_, _) => (), + cbor_event::LenSz::Indefinite => match raw.special()? { + cbor_event::Special::Break => (), + _ => return Err(DeserializeFailure::EndingBreakMissing.into()), + }, + } + ret + })(raw); + match deser_variant { + Ok(single_host_addr) => return Ok(Self::SingleHostAddr(single_host_addr)), + Err(e) => { + errs.push(e.annotate("SingleHostAddr")); + raw.as_mut_ref() + .seek(SeekFrom::Start(initial_position)) + .unwrap(); + } + }; + let deser_variant = (|raw: &mut Deserializer<_>| -> Result<_, DeserializeError> { + let mut read_len = CBORReadLen::new(len); + read_len.read_elems(3)?; + read_len.finish()?; + let ret = + ShelleySingleHostName::deserialize_as_embedded_group(raw, &mut read_len, len); + match len { + cbor_event::LenSz::Len(_, _) => (), + cbor_event::LenSz::Indefinite => match raw.special()? { + cbor_event::Special::Break => (), + _ => return Err(DeserializeFailure::EndingBreakMissing.into()), + }, + } + ret + })(raw); + match deser_variant { + Ok(shelley_single_host_name) => { + return Ok(Self::ShelleySingleHostName(shelley_single_host_name)) + } + Err(e) => { + errs.push(e.annotate("ShelleySingleHostName")); + raw.as_mut_ref() + .seek(SeekFrom::Start(initial_position)) + .unwrap(); + } + }; + let deser_variant = (|raw: &mut Deserializer<_>| -> Result<_, DeserializeError> { + let mut read_len = CBORReadLen::new(len); + read_len.read_elems(2)?; + read_len.finish()?; + let ret = + ShelleyMultiHostName::deserialize_as_embedded_group(raw, &mut read_len, len); + match len { + cbor_event::LenSz::Len(_, _) => (), + cbor_event::LenSz::Indefinite => match raw.special()? { + cbor_event::Special::Break => (), + _ => return Err(DeserializeFailure::EndingBreakMissing.into()), + }, + } + ret + })(raw); + match deser_variant { + Ok(shelley_multi_host_name) => { + return Ok(Self::ShelleyMultiHostName(shelley_multi_host_name)) + } + Err(e) => { + errs.push(e.annotate("ShelleyMultiHostName")); + raw.as_mut_ref() + .seek(SeekFrom::Start(initial_position)) + .unwrap(); + } + }; + Err(DeserializeError::new( + "ShelleyRelay", + DeserializeFailure::NoVariantMatchedWithCauses(errs), + )) + })() + .map_err(|e| e.annotate("ShelleyRelay")) + } +} + +impl Serialize for ShelleySingleHostName { + fn serialize<'se, W: Write>( + &self, + serializer: &'se mut Serializer, + force_canonical: bool, + ) -> cbor_event::Result<&'se mut Serializer> { + serializer.write_array_sz( + self.encodings + .as_ref() + .map(|encs| encs.len_encoding) + .unwrap_or_default() + .to_len_sz(3, force_canonical), + )?; + self.serialize_as_embedded_group(serializer, force_canonical) + } +} + +impl SerializeEmbeddedGroup for ShelleySingleHostName { + fn serialize_as_embedded_group<'se, W: Write>( + &self, + serializer: &'se mut Serializer, + force_canonical: bool, + ) -> cbor_event::Result<&'se mut Serializer> { + serializer.write_unsigned_integer_sz( + 1u64, + fit_sz( + 1u64, + self.encodings + .as_ref() + .map(|encs| encs.tag_encoding) + .unwrap_or_default(), + force_canonical, + ), + )?; + match &self.port { + Some(x) => serializer.write_unsigned_integer_sz( + *x as u64, + fit_sz( + *x as u64, + self.encodings + .as_ref() + .map(|encs| encs.port_encoding) + .unwrap_or_default(), + force_canonical, + ), + ), + None => serializer.write_special(cbor_event::Special::Null), + }?; + self.shelley_dns_name + .serialize(serializer, force_canonical)?; + self.encodings + .as_ref() + .map(|encs| encs.len_encoding) + .unwrap_or_default() + .end(serializer, force_canonical) + } +} + +impl Deserialize for ShelleySingleHostName { + fn deserialize(raw: &mut Deserializer) -> Result { + let len = raw.array_sz()?; + let mut read_len = CBORReadLen::new(len); + read_len.read_elems(3)?; + read_len.finish()?; + let ret = Self::deserialize_as_embedded_group(raw, &mut read_len, len); + match len { + cbor_event::LenSz::Len(_, _) => (), + cbor_event::LenSz::Indefinite => match raw.special()? { + cbor_event::Special::Break => (), + _ => return Err(DeserializeFailure::EndingBreakMissing.into()), + }, + } + ret + } +} + +impl DeserializeEmbeddedGroup for ShelleySingleHostName { + fn deserialize_as_embedded_group( + raw: &mut Deserializer, + _read_len: &mut CBORReadLen, + len: cbor_event::LenSz, + ) -> Result { + let len_encoding = len.into(); + (|| -> Result<_, DeserializeError> { + let tag_encoding = (|| -> Result<_, DeserializeError> { + let (tag_value, tag_encoding) = raw.unsigned_integer_sz()?; + if tag_value != 1 { + return Err(DeserializeFailure::FixedValueMismatch { + found: Key::Uint(tag_value), + expected: Key::Uint(1), + } + .into()); + } + Ok(Some(tag_encoding)) + })() + .map_err(|e| e.annotate("tag"))?; + let (port, port_encoding) = (|| -> Result<_, DeserializeError> { + Ok(match raw.cbor_type()? != cbor_event::Type::Special { + true => Result::<_, DeserializeError>::Ok( + raw.unsigned_integer_sz() + .map(|(x, enc)| (x as u16, Some(enc)))?, + ) + .map(|(x, port_encoding)| (Some(x), port_encoding))?, + false => { + if raw.special()? != cbor_event::Special::Null { + return Err(DeserializeFailure::ExpectedNull.into()); + } + (None, None) + } + }) + })() + .map_err(|e| e.annotate("port"))?; + let shelley_dns_name = ShelleyDnsName::deserialize(raw) + .map_err(|e: DeserializeError| e.annotate("shelley_dns_name"))?; + Ok(ShelleySingleHostName { + port, + shelley_dns_name, + encodings: Some(ShelleySingleHostNameEncoding { + len_encoding, + tag_encoding, + port_encoding, + }), + }) + })() + .map_err(|e| e.annotate("ShelleySingleHostName")) + } +} + impl Serialize for ShelleyTransaction { fn serialize<'se, W: Write>( &self, diff --git a/multi-era/rust/src/shelley/utils.rs b/multi-era/rust/src/shelley/utils.rs index e16d0789..13749094 100644 --- a/multi-era/rust/src/shelley/utils.rs +++ b/multi-era/rust/src/shelley/utils.rs @@ -1,6 +1,12 @@ -use cml_chain::transaction::{NativeScript, TransactionWitnessSet}; +use cml_chain::{ + certs::{DnsName, PoolParams, PoolRegistration, Relay}, + transaction::{NativeScript, TransactionWitnessSet}, +}; -use super::{MultisigScript, ShelleyTransactionBody, ShelleyTransactionWitnessSet}; +use super::{ + MultisigScript, ShelleyPoolRegistration, ShelleyRelay, ShelleyTransactionBody, + ShelleyTransactionWitnessSet, +}; use cml_core::serialization::Serialize; use cml_crypto::{blake2b256, TransactionHash}; @@ -14,11 +20,15 @@ impl ShelleyTransactionBody { impl From for TransactionWitnessSet { fn from(wits: ShelleyTransactionWitnessSet) -> Self { let mut new_wits = TransactionWitnessSet::new(); - new_wits.vkeywitnesses = wits.vkeywitnesses; - new_wits.native_scripts = wits - .native_scripts - .map(|native_scripts| native_scripts.into_iter().map(NativeScript::from).collect()); - new_wits.bootstrap_witnesses = wits.bootstrap_witnesses; + new_wits.vkeywitnesses = wits.vkeywitnesses.map(Into::into); + new_wits.native_scripts = wits.native_scripts.map(|native_scripts| { + native_scripts + .into_iter() + .map(NativeScript::from) + .collect::>() + .into() + }); + new_wits.bootstrap_witnesses = wits.bootstrap_witnesses.map(Into::into); new_wits } } @@ -51,3 +61,41 @@ impl From for NativeScript { } } } + +impl From for PoolRegistration { + fn from(pool_reg: ShelleyPoolRegistration) -> Self { + Self::new(PoolParams::new( + pool_reg.pool_params.operator, + pool_reg.pool_params.vrf_keyhash, + pool_reg.pool_params.pledge, + pool_reg.pool_params.cost, + pool_reg.pool_params.margin, + pool_reg.pool_params.reward_account, + pool_reg.pool_params.pool_owners.into(), + pool_reg + .pool_params + .relays + .into_iter() + .map(Into::into) + .collect(), + pool_reg.pool_params.pool_metadata, + )) + } +} + +impl From for Relay { + fn from(relay: ShelleyRelay) -> Self { + match relay { + ShelleyRelay::SingleHostAddr(host) => { + Self::new_single_host_addr(host.port, host.ipv4, host.ipv6) + } + ShelleyRelay::ShelleySingleHostName(host) => Self::new_single_host_name( + host.port, + DnsName::new(host.shelley_dns_name.inner).unwrap(), + ), + ShelleyRelay::ShelleyMultiHostName(host) => { + Self::new_multi_host_name(DnsName::new(host.shelley_dns_name.inner).unwrap()) + } + } + } +} diff --git a/multi-era/rust/src/utils.rs b/multi-era/rust/src/utils.rs index 17a750d8..25c8e5c9 100644 --- a/multi-era/rust/src/utils.rs +++ b/multi-era/rust/src/utils.rs @@ -33,7 +33,7 @@ use cml_chain::governance::{ProposalProcedure, VotingProcedures}; use cml_chain::plutus::cbor_encodings::CostModelsEncoding; use cml_chain::plutus::{CostModels, ExUnitPrices, ExUnits}; use cml_chain::transaction::{ - AlonzoFormatTxOut, RequiredSigners, TransactionInput, TransactionOutput, TransactionWitnessSet, + AlonzoFormatTxOut, TransactionInput, TransactionOutput, TransactionWitnessSet, }; use cml_chain::{ Coin, DRepVotingThresholds, LenEncoding, NetworkId, OrderedHashMap, PoolVotingThresholds, @@ -43,8 +43,8 @@ use cml_core::error::{DeserializeError, DeserializeFailure}; use cml_core::serialization::*; use cml_core::{Epoch, Int, TransactionIndex}; use cml_crypto::{ - blake2b256, AuxiliaryDataHash, BlockBodyHash, BlockHeaderHash, GenesisHash, RawBytesEncoding, - ScriptDataHash, TransactionHash, VRFVkey, + blake2b256, AuxiliaryDataHash, BlockBodyHash, BlockHeaderHash, Ed25519KeyHash, GenesisHash, + RawBytesEncoding, ScriptDataHash, TransactionHash, VRFVkey, }; impl MultiEraBlock { @@ -670,27 +670,27 @@ impl MultiEraTransactionBody { } } - pub fn collateral_inputs(&self) -> Option<&Vec> { + pub fn collateral_inputs(&self) -> Option<&[TransactionInput]> { match self { Self::Byron(_tx) => None, Self::Shelley(_tx) => None, Self::Allegra(_tx) => None, Self::Mary(_tx) => None, - Self::Alonzo(tx) => tx.collateral_inputs.as_ref(), - Self::Babbage(tx) => tx.collateral_inputs.as_ref(), - Self::Conway(tx) => tx.collateral_inputs.as_ref(), + Self::Alonzo(tx) => tx.collateral_inputs.as_ref().map(|inputs| inputs.as_ref()), + Self::Babbage(tx) => tx.collateral_inputs.as_ref().map(|inputs| inputs.as_ref()), + Self::Conway(tx) => tx.collateral_inputs.as_ref().map(|inputs| inputs.as_ref()), } } - pub fn required_signers(&self) -> Option<&RequiredSigners> { + pub fn required_signers(&self) -> Option<&[Ed25519KeyHash]> { match self { Self::Byron(_tx) => None, Self::Shelley(_tx) => None, Self::Allegra(_tx) => None, Self::Mary(_tx) => None, - Self::Alonzo(tx) => tx.required_signers.as_ref(), - Self::Babbage(tx) => tx.required_signers.as_ref(), - Self::Conway(tx) => tx.required_signers.as_ref(), + Self::Alonzo(tx) => tx.required_signers.as_ref().map(|signers| signers.as_ref()), + Self::Babbage(tx) => tx.required_signers.as_ref().map(|signers| signers.as_ref()), + Self::Conway(tx) => tx.required_signers.as_ref().map(|signers| signers.as_ref()), } } @@ -730,15 +730,15 @@ impl MultiEraTransactionBody { } } - pub fn reference_inputs(&self) -> Option<&Vec> { + pub fn reference_inputs(&self) -> Option<&[TransactionInput]> { match self { Self::Byron(_tx) => None, Self::Shelley(_tx) => None, Self::Allegra(_tx) => None, Self::Mary(_tx) => None, Self::Alonzo(_tx) => None, - Self::Babbage(tx) => tx.reference_inputs.as_ref(), - Self::Conway(tx) => tx.reference_inputs.as_ref(), + Self::Babbage(tx) => tx.reference_inputs.as_ref().map(|inputs| inputs.as_ref()), + Self::Conway(tx) => tx.reference_inputs.as_ref().map(|inputs| inputs.as_ref()), } } @@ -754,7 +754,7 @@ impl MultiEraTransactionBody { } } - pub fn proposal_procedures(&self) -> Option<&Vec> { + pub fn proposal_procedures(&self) -> Option<&[ProposalProcedure]> { match self { Self::Byron(_tx) => None, Self::Shelley(_tx) => None, @@ -762,7 +762,7 @@ impl MultiEraTransactionBody { Self::Mary(_tx) => None, Self::Alonzo(_tx) => None, Self::Babbage(_tx) => None, - Self::Conway(tx) => tx.proposal_procedures.as_ref(), + Self::Conway(tx) => tx.proposal_procedures.as_ref().map(|pps| pps.as_ref()), } } @@ -833,27 +833,25 @@ impl From for MultiEraCertificate { ShelleyCertificate::StakeRegistration(cert) => Self::StakeRegistration(cert), ShelleyCertificate::StakeDeregistration(cert) => Self::StakeDeregistration(cert), ShelleyCertificate::StakeDelegation(cert) => Self::StakeDelegation(cert), - ShelleyCertificate::PoolRegistration(cert) => Self::PoolRegistration(cert), + ShelleyCertificate::ShelleyPoolRegistration(cert) => { + Self::PoolRegistration(cert.into()) + } ShelleyCertificate::PoolRetirement(cert) => Self::PoolRetirement(cert), ShelleyCertificate::GenesisKeyDelegation(cert) => Self::GenesisKeyDelegation(cert), - ShelleyCertificate::ShelleyMoveInstantaneousRewardsCert { - shelley_move_instantaneous_rewards_cert, - .. - } => Self::MoveInstantaneousRewardsCert(MoveInstantaneousRewardsCert::new( - MoveInstantaneousReward::new( - shelley_move_instantaneous_rewards_cert - .shelley_move_instantaneous_reward - .pot, - MIRAction::new_to_stake_credentials( - shelley_move_instantaneous_rewards_cert - .shelley_move_instantaneous_reward - .to_stake_credentials - .iter() - .map(|(k, v)| (k.clone(), Int::from(*v))) - .collect(), + ShelleyCertificate::ShelleyMoveInstantaneousRewardsCert(cert) => { + Self::MoveInstantaneousRewardsCert(MoveInstantaneousRewardsCert::new( + MoveInstantaneousReward::new( + cert.shelley_move_instantaneous_reward.pot, + MIRAction::new_to_stake_credentials( + cert.shelley_move_instantaneous_reward + .to_stake_credentials + .iter() + .map(|(k, v)| (k.clone(), Int::from(*v))) + .collect(), + ), ), - ), - )), + )) + } } } } @@ -864,7 +862,9 @@ impl From for MultiEraCertificate { AllegraCertificate::StakeRegistration(cert) => Self::StakeRegistration(cert), AllegraCertificate::StakeDeregistration(cert) => Self::StakeDeregistration(cert), AllegraCertificate::StakeDelegation(cert) => Self::StakeDelegation(cert), - AllegraCertificate::PoolRegistration(cert) => Self::PoolRegistration(cert), + AllegraCertificate::ShelleyPoolRegistration(cert) => { + Self::PoolRegistration(cert.into()) + } AllegraCertificate::PoolRetirement(cert) => Self::PoolRetirement(cert), AllegraCertificate::GenesisKeyDelegation(cert) => Self::GenesisKeyDelegation(cert), AllegraCertificate::MoveInstantaneousRewardsCert(cert) => { @@ -1375,6 +1375,12 @@ fn byron_epoch_slot_to_absolute(epoch: u64, sub_epoch_slot: u64) -> u64 { mod test { use super::*; + #[test] + fn mary_block_nonce() { + let bytes = hex::decode("84828f1a0054dca41a01908b2f582008ecdb54a80c81073ddee790f3cf4f8d4ff4422eb369b41cd5e0e18c13de6bbe5820d498647f2b7a481e6207ee3dfe02f6292ae85224621c5aabf9c0bf84d097390f58203492992128b6388ed9b56ab0329e42c57df5d1ead48436ea26908195f33daf90825840a38e20ecfa89e9804837f88fe8f8cd13b6a9b4eafca581fdceebf545eea0ea7e4caf36af4d7549a36d15598f67dfbed9840b02b4469d37552a9212669a79096458509370fce20873730ca9fdce508a3a9b0d3350a153c0942f6c8bf5dccd4c699aa80a635ceccb965c6327d6ca25ca32727de977c81f9143438e963df7db2d0165423809360fc744a34a099f1f59f01603008258400005b23bdc51c75f8eeb21f83eacac3d0605891801471c6d61515b27810a1bb8094f4c0ae560ba418ef35bba28e09ed64ca671bdea2139087822455f83ac451258504d90ab3807ad8c84b48460ae154e460826c6af5f3f18d05abdb05ea2c478248428c7d4cb9e9a6d82d94df170c1cabead6fa6b7774e0017dbc5ede4d1cd7cbe34cb08a7af450ff449ff9f68b1cf14e8091924c858203d4f6c99d53160a58c879c9ca04a2bde019377456384aa90b92cc00bcdb3671958206c1a25de95c89fe2df4af81e8440ac621b723fcc06c0ddfc0f2c7dd900067c1f0418ad5840d21ef35d27287c1172ae7d7f593f9f84ea925260e8ca9dd913746085cbd2843d10926b87044bedbdaed4f923e543898e3f7f97f6c780ff01270fdf1e604c4a0a04005901c01bb9f5e7ee8f37a4b499ed7abe8114e76c3d6d453c228004103840798ec2c0b85fbc8de65cf68bf154834679cd9bdd90a849afaf9c950c43a30cac0b4eb504077d34b1c4bbdff197ba64266affc385d9a2bcedc6f08559fe93f2cb61d6c70af41f7582c74cbb7866a6c881b139832e250325bbe15674165a2b06e158ba91341427033f9ce3b813a2bff5451bdc3cc9b3ab7952920383d8f2aba9772251db7d6e8135c58df613036c908e405c9277193a36b1d9a4d40bb263696a3de374ab695ce2fd4401bf30e707ee43de4c05d7839f2bb1e8bed4d4e6b0d9cf0906807b4a6b0520b992825d0643add63168848f3fea1fe2ae147a174d5e7939161ba46a293838ab8cda64dc5a6989aea414b4e502d1edb8dd0c5d1421ab7fa92d4581d0b669d1114a5f340568d67c68ed1b07bb3beea0acedbd7ddb9c79478f6adcda27ff31d704c5a998839750d5ac084ce81e05766c4ae18f4f783063b6f3b76be050be55896ed7202695427b3e9c333319150e0dd993f3ba314ef89f53a8689939425c648060a58a5310efb311c6b3f7835e0f1a662f9f2e867a389e3394c7a1cc2f74de2c0330ebf40aab2cf4efbacaac3fed373b4d64d9c56d3cfcec7f28c9bf18926894a500818258209ea2ac72bc4e082b1a47c6914d9d953d73aff9792174cc1f08cf7215544dd1b901018182583901d42900731c039a877000445f88be659e574632707b056fd2960994c5b652ad81db60f5d8605dcec6e73d1ed932009651d9f3e8580ee07d221a1e1b9461021a0002b06d031a0190a6cb0758209a19f90d9ef5545280368b5503eeaa52c1da650f68fb2209255313a34c19a1d6a400818258200682aeb19e9a31ea5f7f5d4078c91ec94831b1498fcebcd30bc37b6800c17f7001018282582b82d818582183581ce03866945a566d9e8e32f27273877d026385a8e7d54d9494906ed530a0001ab897305f1a1fb8358082581d61d91ef01b73f3010bb173945cf5417257c00c002715a13052015ab54f1a26908966021a00029cd5031a01908ee6a4008182582048926e334cd6b9469a3540cfca974230f9fa25d0e90fa043566abef18d2049aa01018282584c82d818584283581c76ddc0051984f84c6be230066710c1aead629f632e718bb3f9c2c145a101581e581c73a2075d4789f0d61873b4c2d309310949ca41e434d97c21388727c8001a37285aec1a08b11eea82581d6179e67550b2ff311da1883ad0ccc6fb2bb7c75e5489acff735fcc68781ad17d4c43021a00029cd5031a01908ee6a40082825820df07e64b7151d6c6c4c15ae3b2b1944d501df2cf54ee5ae98feaf97e49e0067e00825820df07e64b7151d6c6c4c15ae3b2b1944d501df2cf54ee5ae98feaf97e49e0067e01018182581d614926b3e631270b5d5310b5481e0fc82b1a1c706ad278c4bc091e29211a2aab95ba021a0002d644031a05f5e100a40081825820c0cf68370b852bfed85b0a39ce4644c8195511149ab70620a9158206d08e05ce01018282581d61483f3120cfe28f4220f4b96228f8d110e5f2100285b914218e927c251b000000012a70c1c08258390111e921395d6c4ad0c7004ef928d9d0dcf5b33983749a14b59a0e6ee22aeb420cce4b576d6833d513fbb1aaf4b2396a427c9d96aee6d608df1b00000001b8a9ec0b021a00028de1031a0190a71ca400818258200b5dd952875af5c7ff5a251febd31e607ee1ff3be911e93d27a35f94c9e96cbd01018282584c82d818584283581c2be129a2509494c81b8fced13d9eb21529b6c1ef88f5ea3b578c27c7a101581e581c633c7e9a7d0419aaf93a78e0cf2fc2bcbc54a2a12371fd9d00645c8d001a6429c6be1a195edd7082584c82d818584283581c7cd9baffad4c847dce58c53bfaa0ae4d6f19ed9c0182585d3ca54bb9a101581e581cd4688480c96f8332739757b76b843a8c681328ec34c9b5b38d6898fb001a6ebfa4dc1b0000005286323835021a0002a8b1031a0190a72ba50081825820b2bdbe07d5cd4da8b8dbef9eee67ff6fb1877055d0b8309fbd4718591389eac5000181825839016445bb08465c26cf435a4274b8dadff753b3b9a87f4aa8f88479431d4eb646b86f18f6f4266684f37fbcf4027c650747dc45278ab0bf8c8e1a0048f96f021a000351d1031a01909ccd0682a7581c162f94554ac8c225383a2248c245659eda870eaa82d0ef25fc7dcd82a10d82015820d982e06fd33e7440b43cefad529b7ecafbaa255e38178ad4189a37e4ce9bf1fa581c2075a095b3c844a29c24317a94a643ab8e22d54a3a3a72a420260af6a10d82015820d982e06fd33e7440b43cefad529b7ecafbaa255e38178ad4189a37e4ce9bf1fa581c268cfc0b89e910ead22e0ade91493d8212f53f3e2164b2e4bef0819ba10d82015820d982e06fd33e7440b43cefad529b7ecafbaa255e38178ad4189a37e4ce9bf1fa581c60baee25cbc90047e83fd01e1e57dc0b06d3d0cb150d0ab40bbfead1a10d82015820d982e06fd33e7440b43cefad529b7ecafbaa255e38178ad4189a37e4ce9bf1fa581cad5463153dc3d24b9ff133e46136028bdc1edbb897f5a7cf1b37950ca10d82015820d982e06fd33e7440b43cefad529b7ecafbaa255e38178ad4189a37e4ce9bf1fa581cb9547b8a57656539a8d9bc42c008e38d9c8bd9c8adbb1e73ad529497a10d82015820d982e06fd33e7440b43cefad529b7ecafbaa255e38178ad4189a37e4ce9bf1fa581cf7b341c14cd58fca4195a9b278cce1ef402dc0e06deb77e543cd1757a10d82015820d982e06fd33e7440b43cefad529b7ecafbaa255e38178ad4189a37e4ce9bf1fa190102a40081825820a3d07b77d09868b01d07b4c53e40b71200639266b1776512e0981cd66f48eb5d0101828258390134d388e0c5251d087232b3dcc67caa6cce2937c97a270fb4f4a2499999b8e6a0a8c8e173ddd63478e982846ffbbcd165028a1cef78ae9ee71a078ca24982581d616904e8b2c26f3dda6c4a5db4b3ec9e31d581c9960977cfe9c6917a431a2d0faa34021a00029cd5031a01908ee6a40081825820ac9ceff2de86d2387950ed7d1197a517e772c5ddfecb5b94767fae888820b3d801018282584c82d818584283581c15c97f0866ba4f390e283a268b53e180cfdb5e34bcc464a357e36710a101581e581c83d3e2df30edf951c5ba0b8582a1a303432081a4295f18ba44e9a548001a6b9405c71a1392fc8082584c82d818584283581cde349abef27bb239d4ae5e7629c1400d32165097f684148808da3c97a101581e581c2b0b011ba3683d776e9d872a85987bd6e6942a6b8c30d6d7dc3dfb14001a18ff53f01b0000000107647432021a0002a8b1031a0190a729a40082825820bb6baeb11c7472779c3b3acc35db7897f2d36d11846909ba6dd5979239fd067000825820bb6baeb11c7472779c3b3acc35db7897f2d36d11846909ba6dd5979239fd067001018182584c82d818584283581c9c9490179ae2288142fcc6fc0f6aa8ff8c49531ed384740d5c73622ea101581e581c5981b261ab5ccd7bf7f2c1225ad7eefe385edcc839ba55113b3e95db001a0122212c1a0aba8850021a0002d644031a05f5e100a40082825820d4b800d689d733f523fa78361ffb5fade29d9bb13fcfbc344aa458bd0b0b976b018258203b7bfa5f182b349e13c0e1c56c6c81ca8c5cf40d7b72b416a3563783fc0ff134010182825839012d8b354447efe987387f329b63a3c86b6007371699ed5db4ac5cd88e2d8b354447efe987387f329b63a3c86b6007371699ed5db4ac5cd88e1a584abd6e82581d610237be10f5ec0ccb6cbd226b112f0940fed44ae0466d9b53962ba8b11a184eefca021a0002bf35031a01908ee6a400818258201cc75901ee9df32dbc50ce820052038faba13b465b25fe64f887d940c9f9458e0101828258390117c7c19c81dbf1187a5bdf387a320f46bf80246e30d5b97efd59ab9fdd7986e3b08ab70333fa1e4183b8735cf3474a31108fa0943de6b8cb1a034f468282584c82d818584283581c776eb96b96e2cbce528a47278a736ab725dd13ce98c027ccb548ed70a101581e581c1afbc57540db1561adeaccd7f4894065965cd230f6bdc70722aecd8b001a6a14bf9a1b0000000f31da326b021a0004623d031a0190a71ea400818258202c6cca35e5e4458cc35ebd173a6471b3ae29668fd06bd4ba5114955339f219e501018282584c82d818584283581cad8f02b7134781a28997cb23f2a78215322f6c1d8a58e9e47c9f445ea101581e581cc9a4c68c63646852d93de951824def94b774fd58431f7a5618115a19001a389631ac1a060871738258390181bfa0e759547ebf226bbd51a844095d56890ba05aea3a73665cbe881cdeaf2c1028e67b5b360171975136b41c9a58d9220bdd65fd6ac0791b00000003218293c1021a0005f9b0031a0190a71ea40081825820c306f318e9721757d3252cdc5dd31eac6bd6aee236beeb9601a772fa681e554301018282583901a6c024231f3bf4de746511675994db25b664aecc25789de65462eff4739f0761691131d31bd714501d8a6f9f44ac9b5b3a74932753c29efc821a00160a5ba1581c59960c8ca8871af59f70474cbb2c11e3d782614a4c4be7f25e6c783ea148616c666f6e7a6f731913888258390170a84cf34da92bfe2c4da8689f358caeb4d1715c73710aed235be3d71537f3dbdcfedc8079eb6e8c1af93563a6cc2a7ecfbe5b4ba92750ab821a9c11edf0a2581c36e8f59542d444e3afca00cecca881cbdf8257c1b07a2fd84ed25730a1574570737465696e4469646e744b696c6c48696d73656c661a000f4240581c59960c8ca8871af59f70474cbb2c11e3d782614a4c4be7f25e6c783ea148616c666f6e7a6f731984d0021a0002b041031a0190a73ba40081825820e71f446e150a646a1982fce26c0239395dfc52bf029d3b653e06232925148aa10101828258390126141bac8f8fde24eec91011bcffd28b7f221b52aaaddcb24b3b421f265b2a3a895d6d9ebf67b1d1f1b06927caf752d13e40bf4ea11c622a1a004c4b4082584c82d818584283581cfafa1e6485be8a43275f37446d9ec9268682dff27678956c1a01dffca101581e581cd8d97175289f3a7dd17a4b6107633ed785ce2d33a1ee00f20ef4d7fa001a9e288d2c1a3eff155d021a0002a56d031a0190a73ca4008182582020a32c2967acf50e42efa21bc6f2582f26def86152f15b66a0fffc61b1397d0100018282583901a0c0fed7b1d4288835dc2334aba0240d27e10dedb73badb27457ba91ec17628c4600f1d941b206a557581d904584da48ba972d554d3aa4891a03d8312082584c82d818584283581c505f6f99e8b2a44bc02753d04e1745910a28205187e4b743b6be8904a101581e581cd8d97175289f3a326c6a29619d56eb6e22830bd40ee474aea3ea120d001aa030fe341a02048ce2021a0002a56d031a0190a73da40083825820150ae07532b9e62de190ac6955cde4c33ec42ee86c7d8415c7f820d6561f280d08825820293f1fb4adaeded6aa8f3230d6075df6e8ea657fe3f36e3c78bfb71524d3a712098258204dbaa5d17d37aadddce5409a0aa4c299c9468f0cda7f672b3d9553713216e8290b018c82584c82d818584283581c0fea43d9bfa899adfbbf88e57e6798e53466219143130576b4122a44a101581e581c9b55b8bf594b59974d9edc197b6a68a1d5d10327348c8f5c20278339001a2c181f7a1a3b9aca0082584c82d818584283581c7d1d116c1bd0b92d8f307dcfdde3282316105c6249c995c5b4c96f48a101581e581c8f802fa39db6a972b8e0b1c4f7f9649c381f6af5dd53cc3658668cf1001aca1390591a01c52fa082584c82d818584283581c0fea43d9bfa899adfbbf88e57e6798e53466219143130576b4122a44a101581e581c9b55b8bf594b59974d9edc197b6a68a1d5d10327348c8f5c20278339001a2c181f7a1a01c9c38082584c82d818584283581cc5f21c78dba1146cb869e7c243165ea5841970045d4dd3cbec118f01a101581e581c4c119dd2b2270328df974203bca1f8e6d3bb601baebda45374871f21001ae0b305381b000000022ee0828082584c82d818584283581c90438a11280f3692dc611cb03d8d7cb1c3688ad8519b2c52b4acd791a101581e581c4c119dd2b2270357d09868034a444ba63688d21110f3a142d428c203001ae70673711a96d76ae082584c82d818584283581c23cf87cf3f4008fc1f26fd7667e3340325df267dfdb86b22234a11dfa101581e581c633c7e9a7d04199e20a1cae0b6a1c282c0310dba20b93265e8d2dbb9001a00cc23491a6e5404c082584c82d818584283581c7899f9c5244e1b64109325ae19e7f7920eb19f118fcc4cb525400b82a101581e581c84b2ff88d08bc4143a01f5c9795a72f04f627169d47c46873e86096b001a7919a0ea1a1a848ac882584c82d818584283581c700af7d911f9383b9a3011b68fb725dc43ff6b1884627c3e1007a20ba101581e581c84b2ff88d08bc4254f49a9c959dde14cccd5a314ef5d04631b2fc5e6001a1bfa4f131a00d86ce182584c82d818584283581cbe60727988fa9476b309f78e41f74035cfeb53c2c1ae16b3f5562b01a101581e581c84b2ff88d08bc477eb6000c9b770b219910c269ff575e1d78b74a975001aef4865821a00da751182584c82d818584283581cfc8a85f9862b26e153aae414ced247a0767a7e6003cec68d257833f8a101581e581c84b2ff88d08bc45186803ac9607c3c0743e23a1c18866c40919dd748001a58de0f8b1af82445c682584c82d818584283581c8449e1e8e805543715cc807d922f5fedf6c0437e5f410e7eb8e28055a101581e581c84b2ff88d08bc479e9e19dc90ee5e975b064ddf7bfacc41424d8ad82001ae306c9341a4304682b82584c82d818584283581c77970d82501e8dbbe906fdf9f208fbcce238fa93ee6331328d64bd8ca101581e581c84b2ff88d08bc4359d75e8c9aea1d751cd013be81d1b54cc374ed3c5001a4c8fcc631a31089b31021a0003908d031a0190a73fa400818258207c072edb52db7aefc6881f6ced60b7aad9b8fabf590dae34db09b5a4db81702105018282583901ad915af56530a5d452bcd4a88b87b0e1ca375feaab4fe399a1105312ad915af56530a5d452bcd4a88b87b0e1ca375feaab4fe399a11053121a02ec88cf82582b82d818582183581cbc14e6b9754d7eef691230ae09e4c52b03d1d824c80e22b65432d7a8a0001afaf343d61b0000000185309742021a0003656f031a3b9aca00a4008282582069572bee1b68d01c50b619de76461edbb90dd25c66e862c79fa9fa124efa92300082582069572bee1b68d01c50b619de76461edbb90dd25c66e862c79fa9fa124efa923001018282584c82d818584283581cfbfbb9e7f7844a40b2a6465af5ec17b8da45974c738d60d1cb21ba8fa101581e581ce378ee30d568143c4b061b6dfd1875fe5b27cd41917b30ce0107790b001a31db91811a832156008258390114ef538b66f44052ae6dc8c545250eebedf65c491327a9b8c7102e0c14ef538b66f44052ae6dc8c545250eebedf65c491327a9b8c7102e0c1a036cd490021a0002e4db031a05f5e100a4008182582089be624b89aa349ccd11c415695e0421d00fd3106b6334e877961437e51191c00101818258390119690bdc2289666c814de06b1095ca10ecf2092ed237669df9e3ee0619690bdc2289666c814de06b1095ca10ecf2092ed237669df9e3ee061a110c0380021a000add40031a0190a74d94a100818258202669028f7c59934d13efa39435215fc2486e389e35ba6c6b05dda7c65213257e5840b3cd2e84cae259105b7330bf4c871ff8796d42935ef822e3028f4e3128d660d04619443006f87971c3ec2fdd3f0ad9a63070e2d8037b88682c7c91b327c55b0ba100818258200d197b7eeef1b961962a2911d4b553f0d9c3114b8d3e61de3beb4f39dc348eb058407d6f5b2c1cce03a45c5f6d754da293936d7d3a013ef5822e9a36954b635fc0ed148da41a7ad85438d6fe7e32ff6e3a7c2e611a96ea891d08e3d570b14386a906a100818258206687a36f0a4b8abf2671f8affb7febeb8940e9ee83548d2a2924dbc74679c4665840289d23202301208dce8e594b84de249e4e6a77153ef66c7171431df21645f336ed1b37e5786c8e2e8c41b790b1deffa093ddd0cd6937121809abc327b45cc904a10082825820276601a019b13a328b7306c0faac593c064476af30beed0380aa035d4bc1fe315840331b8f8dd2c470f1318a87fb51fc1ab030448166aa61bcfea8052420658836e59036c52befdabb2cf4acb8637bc63f0bd822f21646b35ce1e167269c233bf800825820276601a019b13a328b7306c0faac593c064476af30beed0380aa035d4bc1fe315840331b8f8dd2c470f1318a87fb51fc1ab030448166aa61bcfea8052420658836e59036c52befdabb2cf4acb8637bc63f0bd822f21646b35ce1e167269c233bf800a10081825820783b5406ddd311ad3640afd90eb5bc45f85ff0b57fc5937ee365c8313636239f584070f587d9c080c8a76c5b26059bf3ec4b8dec9a98c955710303038636187aa76c01b386f87192cb2b2e4bb768b6c4a10cef33a631c9236799f034849c1508590aa1028184582063e3a4107a043aa1c7253612aa6e12e3c6231fa11f454aa06046f184cbf49fd758405d946178128a00dd003121c481a5d8f729e9b96b7dbf0bddbe57c94adcf000a83b68d7fc9f64a88d96fa87e1fc6c9cc1af2e1b86719b0d45febb7518459c970a58205bd2b0767d1f7de98f74403718cab3262e11105be4883947ed06785a3b3626825822a101581e581cd4688480c96f83055933ffb71bd2a85ea5ec4f45c5ccc0c98e8ee2bba1008882582061261a95b7613ee6bf2067dad77b70349729b0c50d57bc1cf30de0db4a1e73a85840375bfc568d815bc5d6778d3e2ec6287529a88602dee06e5c694ff8d727d8dc8d325e9c8967ebf992d8df9fd862f7b03a57c9c721a563c783a9847296484135028258209180d818e69cd997e34663c418a648c076f2e19cd4194e486e159d8580bc6cda5840c9664b3f484faa30ebed8308bc009ba2261b4826a6306b1a943cced6f0e00aa2fcbc8da3156db5d7d644196c74d44f81dfe477658ca20733272e4b1a9490fd0f82582089c29f8c4af27b7accbe589747820134ebbaa1caf3ce949270a3d0c7dcfd541b5840e46527dea5301bcb69d943dc3f0d7e97798b4b93addd28907cb08b0fd9741b285069476500407020249b28db467b16a782510e4bac318c1780f562a5a95ccd0e825820f14f712dc600d793052d4842d50cefa4e65884ea6cf83707079eb8ce302efc8558406bd6d8e0538963107baac0977e2b3ec8e3baab8dacf77851d8a7433412d0f3ac2a631cb4b1819e4d735e04ed4fc2ff89843d05de2847fc1a7a6756e19940910c8258208b53207629f9a30e4b2015044f337c01735abe67243c19470c9dae8c7b732798584059854e89e94fb2d6a363884aaf22d117e5fa22f77948d5a15f0aa551c4f97189d3a039467a046c8ead26612619c4ecc48ec88144ff077910891b1d95dd89a20c8258205fddeedade2714d6db2f9e1104743d2d8d818ecddc306e176108db14caadd4415840620c64cdf8d662028fb1ae1da2e9ccaaa81b79f40fae2ac8e425d174f8b6dc72383c61eb4a9ec1c5d10ecc1d643968e2fc00ad9e3d8e317faf3f3c261033f60a825820cbc6b506e94fbefe442eecee376f3b3ebaf89415ef5cd2efb666e06ddae483935840b74f2b37390269a78d45685d3197b4640c5cc9cf82b1c1c53d3f88e2117ce33bc7c6da056a9701818a37b8d657f4c4f25d39573a33fd8f57ceb6e228dd3e0f07825820e8c03a03c0b2ddbea4195caf39f41e669f7d251ecf221fbb2f275c0a5d7e05d158402d8fefb1305c16245613adeee72004c31840267dd01dbfaaa177dbe0da5f542ce52252b3d3da24adc17587443be4d8715d772ca0d9b4af8c97d38678b0eb440da10081825820393b3d3cab6be0897cbc87143cc3a24825dc1d8249df4d37969502931cf856ff584072e1e68e093e0511cd74666cbd04dc085f51824ecd699ccec34b65f67cd455172320e5dff108b5698a90599e95ac97ce29223e8eeb0341c93fc73cb01757ac06a10281845820d1f77134edfa56f240847ead978ca98e8bb5f43f476b6b71ef3e50ceb852b2135840df7a4a2e50bac5285264b9174f51d3f93ad0c309141737d3eef6a884db658ae63ad3e770cab31c93c11f873071fcfbdf0989081cc5a878fa11516e9325f271015820abbd19a5be197b7f66196c02a7a5fd714c3f95e2b280fd85dad81683b995b6cb5822a101581e581c2b0b011ba3683d58dd9d722a2f2cb9679b356ada972029c6b5f2ae61a10082825820ea5dd58ee48288c53c2ab95776da5e35357db5833f8ab3c420baa88dd920e11d58405bd3d606ca8810f5e50aabc09bbb69bd460bd90e6b68e016dd553b32da20ee1ec20ea79826ead8b52b7ca73b673ae5a59b132bb64fe565fcc462187b53f0a807825820ea5dd58ee48288c53c2ab95776da5e35357db5833f8ab3c420baa88dd920e11d58405bd3d606ca8810f5e50aabc09bbb69bd460bd90e6b68e016dd553b32da20ee1ec20ea79826ead8b52b7ca73b673ae5a59b132bb64fe565fcc462187b53f0a807a100818258206c0180db688a9e477b10a7792e3c4efd749cddbe0e05068b6cb586dee54056975840e4f95636842e596b03aaf3379907a96b48e4545ad591246df8ccb7c6c254c30e514f9135e7178d3a7badb521cc583ae458e137195c41ce4f0b2fe19920955000a102818458208b66d7f3bf0629a3cf791984bf0fa4568b83106c9257818e63edf63142e9bf2a58400a13b559254d21194e8fcf77662d0b73b778dc91f0f12aeb639becbcbcc2322df45bd9b2cdc85a6d3b842056191c2903dd9afcdfb234a62a9e0a8eff2f3fd10d582022cc1a6495cb1639e562a07c9aa86a4cf54e3dbb6839aa4ee6f0b6a20dc349ad5822a101581e581c1afbc57540db1561adeaccd7f4894065965cd230f6bdc70722aecd8ba100828258204db5d63d4561edc2b565f50c9be435ffb0bd606030aefba4fe0cd9ff86cbf473584082a9975d71dfd55cf3be8b1fa9da9b07737143e0a2f36aa8e43f793844c4448ed9a07a500e914a0e629dcaede71df676218143a324186c2a1b5e2224e114620f825820e68a43be6ae384bc3d33b2921c89914f5dd99bf088a45c5a31d17734e408d78e584076e9eb5c4a18bc8a5aad2ef4e4db2810fda3b76a6b8639cf82b2ad0141b80a97c0f568f3292fdc67bb378c91301fb06cd8ee4c543509cdb4dda4d1aef9d31a02a10081825820c9ed44b3f86f0beaa05d2e8e611488f3f369ecafbcf2754cfea82c84e248528b5840f7b52620cff9f200274014fca350d74a84d17b819e9cc6d23eb54a51078b7a59750a6c01e3f2b5a05bebe8520d0a80f14f78a32854ce889f99e7eae9c886540ba10281845820d02732f50b7c1c1b7a4e946d8d280195c2c96577f1ba2b90474ad509e35812055840a856245cd143457faabef30d675d0c45d2b63f16cf97c62d50f53d03e221d8e20869caf8f61982d29af7b3082f2e62d47484598495e95ac70a8c1b442aed97015820c227781775746f69bf6644f59dcfa6ac64864e307193ba95c2ea4514babd32d05822a101581e581cd8d97175289f3a7a3431a461b982088fca713f245b33843eeba6ace1a10281845820a0e38b160bd1292273c027fc08fca940abf54ecf3331dca01a5f195dc6b0ea1e5840617a03af56821787ae7a5e9ef0f28455157ee825a7913e1c0f27f35261e05d9916573fdce741d4ff419326c34aed1c02f0c998fbe33c247e1e800c5288e6d7015820937737a634d6ea5a0a2ef0f7658bb5337a21467e5ec565216a56bad4bd602a415822a101581e581cd8d97175289f3a14d655b2617089ce27d2df668f2901bc633cf7fcf4a102838458204a8e7f58407fdd312c4b093fbd30a69e1f6977b741d232e83e0fb99aed0e4cbd5840707b40421b8aa92605e34084d54e30643c253171bca2f5c2d3c56816a0295c025c870d9d0e3fa8df5c21764e33fbbd29d52bcdd77d7e6464f2948baa4e550d0a58203f043217f97312094c938259e57e9fb4d62b5ea373d00db3964b34ff898ac38f5822a101581e581c84b2ff88d08bc4408857d0c933f73033a3c62ced32e46b133ccbabef845820f80b356bd8105ebf65a3ca11b8ec2f8a179ac969b3bd6e9dcabf0e98bcb95a405840ff6e845dedeb967a24b042d839b52fadd4ba9855f13a76540b4de6818b016427b6e8a5512242142d732a5bc3d9df60d6e892293fdf5d33adde9bd22f69d1f6025820e7f9e3a251b0465dd169e2af1eac21512411370c42d5901670c9b6fb31658dc05822a101581e581c84b2ff88d08bc45e1dfb07c906b614497ca6cfe4ef27fdd314676c708458202ed3b6973c6f7fb567a9fefc01b351cbb06998c758c827fd34ff3d4512c55465584082351b0b888fd4854317304dc9e9865d75ab207a2c2bad439ca694a76e49a0224461f5291ee84db1a2377c2258ef8339ae9671e596218e1fd4383fe6ab984f0a5820dde71e8188d0e60442a9241ca91a5026c784677ed7b550d2ee49f12478076a365822a101581e581c84b2ff88d08bc4638430e8c9c992b98178c9a3a86159f877ff48e1f2a1028184582087fe94fa4925fcaa0948ac6b3a4ea590d11710fc999bfb3939864be95a30da8f584022093273e4658d71cf5cb737d1869247e39782e985e236c5b732996c1c6660528df5507fd272f5f15bdbf3578782d2dab8ab74d5b3b0fd48b0d8b8a26589bf005820250cd474ce3d2459197ee7ce25265f41eefc7b0fc37da633d10e4b02e87ad4ad41a0a1008282582086e3337f52290bc4f455da7e83a055c93e2a96b63fb3b7233f20f1a9c46e80a4584039db8d78698986021fc4cbfbe84665e1056dfaf91563a42841520ef5f03f573731bf6afb2ece1c85d8e2808cccc6d2b3a5587bfc72c9d88033d325bd7b6fb90282582086e3337f52290bc4f455da7e83a055c93e2a96b63fb3b7233f20f1a9c46e80a4584039db8d78698986021fc4cbfbe84665e1056dfaf91563a42841520ef5f03f573731bf6afb2ece1c85d8e2808cccc6d2b3a5587bfc72c9d88033d325bd7b6fb902a10281845820f0cd529bf77540b1211aa75a233601e0627951ccd4270d812c3add3c444bb0985840d9ed324cb3e74aec5baa40f3913856a015f78ab4b746b808268020bf2d293beb599eb390165c8299ce4e1a6ab0deece23c4401dc63fc6ad5a7f3c808a72f6f025820a7c5165bf99697dab666d48be507bbc475e282ae9743e72715f6e6b084234e835822a101581e581cba5f3d73c6d17e2e7d13dd396f0a74bf5cd02fd63ec68d0f09d9898fa100a219ef64a4015820ac05963babda59adb08a6ce3ab590199c0baaabd2763484f0bf5a7e72335ef25025820d1a756633fe50049d7cac880d793289e2b16ac4ef31abd411f730770d63c29e903583901d42900731c039a877000445f88be659e574632707b056fd2960994c5b652ad81db60f5d8605dcec6e73d1ed932009651d9f3e8580ee07d22041a01908adb19ef65a1015840787a36aa14eed279069272dd3ade19ea4e304a67da4524098619195e974b3be409fa6aee63a784c9fe9fac77b4718c84c3523c756b0701d10fa2171bec93db01").unwrap(); + let _block = MaryBlock::from_cbor_bytes(&bytes).unwrap(); + } + #[test] fn byron_network_block_parse() { let bytes = hex::decode("82018385015820f3e188a0adb6e8bc840286be2241bdf8d72efa8078d84534f4ac5e51189f537284830058200e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a85820afc0da64183bf2664f3d4eec7238d524ba607faeeab24fc100eb861dba69971b82035820d36a2619a672494604e11bb447cbcf5231e9f2ba25c2169177edc941bd50ad6c5820afc0da64183bf2664f3d4eec7238d524ba607faeeab24fc100eb861dba69971b58204e66280cd94d591072349bec0a3090a53aa945562efb6d08d56e53654b0e409884820119087158405eba3a05b57a84c877453667b2de00061b50dafafcdd83d7a0b7d0f0959eba7bef72eb9d18142f2deab055f197ac15a830e38aae8155e3cca07d212adb185110810c820282840058405eba3a05b57a84c877453667b2de00061b50dafafcdd83d7a0b7d0f0959eba7bef72eb9d18142f2deab055f197ac15a830e38aae8155e3cca07d212adb18511058409aae625d4d15bcb3733d420e064f1cd338f386e0af049fcd42b455a69d28ad366483d177ba2b801b4136e0d6662e5e9e0a24f2c80a0e78d4c235b4c08f201f4c5840939dcfe5555ee661b9db5d817a70d5c3fa9d1d97c2ae5849696d915606b530f7e9edda5d02a01e61524a766f9c356084616ba058a3de70ea51bf29cd187a5f0758402deb50bb6bb566cc688abe0548612b72e92e16a4b20542d2488eb479b31f6646457bdf8575e3bd9f168d278bb4cc7f91a27efaa7ec4e6e7ab24afafef84f7f0b8483010000826a63617264616e6f2d736c01a058204ba92aa320c60acc9ad7b9a64f2eda55c4d2ec28e604faf186708b4f0c4e8edf849fff8203d90102809fff82809fff81a0").unwrap(); diff --git a/multi-era/wasm/json-gen/src/lib.rs b/multi-era/wasm/json-gen/src/lib.rs index 65ce603f..5b359616 100644 --- a/multi-era/wasm/json-gen/src/lib.rs +++ b/multi-era/wasm/json-gen/src/lib.rs @@ -18,22 +18,45 @@ pub fn export_schemas() { // allegra gen_json_schema!(cml_multi_era::allegra::AllegraAuxiliaryData); gen_json_schema!(cml_multi_era::allegra::AllegraBlock); + gen_json_schema!(cml_multi_era::allegra::AllegraCertificate); + gen_json_schema!(cml_multi_era::allegra::AllegraTransaction); gen_json_schema!(cml_multi_era::allegra::AllegraTransactionBody); gen_json_schema!(cml_multi_era::allegra::AllegraTransactionWitnessSet); + gen_json_schema!(cml_multi_era::allegra::MIRAction); + gen_json_schema!(cml_multi_era::allegra::MIRPot); + gen_json_schema!(cml_multi_era::allegra::MoveInstantaneousReward); + gen_json_schema!(cml_multi_era::allegra::MoveInstantaneousRewardsCert); // alonzo gen_json_schema!(cml_multi_era::alonzo::AlonzoAuxiliaryData); gen_json_schema!(cml_multi_era::alonzo::AlonzoBlock); gen_json_schema!(cml_multi_era::alonzo::AlonzoCostmdls); gen_json_schema!(cml_multi_era::alonzo::AlonzoFormatAuxData); gen_json_schema!(cml_multi_era::alonzo::AlonzoProtocolParamUpdate); + gen_json_schema!(cml_multi_era::alonzo::AlonzoRedeemer); + gen_json_schema!(cml_multi_era::alonzo::AlonzoRedeemerTag); + gen_json_schema!(cml_multi_era::alonzo::AlonzoTransaction); gen_json_schema!(cml_multi_era::alonzo::AlonzoTransactionBody); gen_json_schema!(cml_multi_era::alonzo::AlonzoTransactionWitnessSet); gen_json_schema!(cml_multi_era::alonzo::AlonzoUpdate); + // babbage + gen_json_schema!(cml_multi_era::babbage::BabbageAuxiliaryData); + gen_json_schema!(cml_multi_era::babbage::BabbageBlock); + gen_json_schema!(cml_multi_era::babbage::BabbageCostModels); + gen_json_schema!(cml_multi_era::babbage::BabbageFormatAuxData); + gen_json_schema!(cml_multi_era::babbage::BabbageFormatTxOut); + gen_json_schema!(cml_multi_era::babbage::BabbageProtocolParamUpdate); + gen_json_schema!(cml_multi_era::babbage::BabbageScript); + gen_json_schema!(cml_multi_era::babbage::BabbageTransaction); + gen_json_schema!(cml_multi_era::babbage::BabbageTransactionBody); + gen_json_schema!(cml_multi_era::babbage::BabbageTransactionOutput); + gen_json_schema!(cml_multi_era::babbage::BabbageTransactionWitnessSet); + gen_json_schema!(cml_multi_era::babbage::BabbageUpdate); // byron gen_json_schema!(cml_multi_era::byron::Blake2b256); gen_json_schema!(cml_multi_era::byron::ByronSlotId); // byron::block gen_json_schema!(cml_multi_era::byron::block::BlockHeaderExtraData); + gen_json_schema!(cml_multi_era::byron::block::ByronBlock); gen_json_schema!(cml_multi_era::byron::block::ByronBlockBody); gen_json_schema!(cml_multi_era::byron::block::ByronBlockConsensusData); gen_json_schema!(cml_multi_era::byron::block::ByronBlockHeader); @@ -99,10 +122,13 @@ pub fn export_schemas() { gen_json_schema!(cml_multi_era::byron::update::SoftForkRule); gen_json_schema!(cml_multi_era::byron::update::StdFeePolicy); // lib - gen_json_schema!(cml_multi_era::byron::block::ByronBlock); + gen_json_schema!(cml_multi_era::MultiEraBlock); + gen_json_schema!(cml_multi_era::MultiEraTransactionBody); // mary gen_json_schema!(cml_multi_era::mary::MaryBlock); + gen_json_schema!(cml_multi_era::mary::MaryTransaction); gen_json_schema!(cml_multi_era::mary::MaryTransactionBody); + gen_json_schema!(cml_multi_era::mary::MaryTransactionOutput); // shelley gen_json_schema!(cml_multi_era::shelley::MultisigAll); gen_json_schema!(cml_multi_era::shelley::MultisigAny); @@ -111,11 +137,18 @@ pub fn export_schemas() { gen_json_schema!(cml_multi_era::shelley::MultisigScript); gen_json_schema!(cml_multi_era::shelley::ShelleyBlock); gen_json_schema!(cml_multi_era::shelley::ShelleyCertificate); + gen_json_schema!(cml_multi_era::shelley::ShelleyDnsName); gen_json_schema!(cml_multi_era::shelley::ShelleyHeader); gen_json_schema!(cml_multi_era::shelley::ShelleyHeaderBody); gen_json_schema!(cml_multi_era::shelley::ShelleyMoveInstantaneousReward); gen_json_schema!(cml_multi_era::shelley::ShelleyMoveInstantaneousRewardsCert); + gen_json_schema!(cml_multi_era::shelley::ShelleyMultiHostName); + gen_json_schema!(cml_multi_era::shelley::ShelleyPoolParams); + gen_json_schema!(cml_multi_era::shelley::ShelleyPoolRegistration); gen_json_schema!(cml_multi_era::shelley::ShelleyProtocolParamUpdate); + gen_json_schema!(cml_multi_era::shelley::ShelleyRelay); + gen_json_schema!(cml_multi_era::shelley::ShelleySingleHostName); + gen_json_schema!(cml_multi_era::shelley::ShelleyTransaction); gen_json_schema!(cml_multi_era::shelley::ShelleyTransactionBody); gen_json_schema!(cml_multi_era::shelley::ShelleyTransactionOutput); gen_json_schema!(cml_multi_era::shelley::ShelleyTransactionWitnessSet); diff --git a/multi-era/wasm/src/allegra/mod.rs b/multi-era/wasm/src/allegra/mod.rs index c25deac9..223a9488 100644 --- a/multi-era/wasm/src/allegra/mod.rs +++ b/multi-era/wasm/src/allegra/mod.rs @@ -1,16 +1,18 @@ // This file was code-generated using an experimental CDDL to rust tool: // https://github.com/dcSpark/cddl-codegen -use crate::shelley::{GenesisKeyDelegation, ShelleyHeader, ShelleyUpdate}; +use crate::shelley::{ + GenesisKeyDelegation, ShelleyHeader, ShelleyPoolParams, ShelleyPoolRegistration, ShelleyUpdate, +}; use crate::{ AllegraCertificateList, AllegraTransactionBodyList, AllegraTransactionWitnessSetList, MapTransactionIndexToAllegraAuxiliaryData, ShelleyTransactionOutputList, }; use cml_chain_wasm::assets::Coin; use cml_chain_wasm::auxdata::{ShelleyFormatAuxData, ShelleyMaFormatAuxData}; -use cml_chain_wasm::certs::{PoolParams, StakeCredential}; +use cml_chain_wasm::certs::StakeCredential; use cml_chain_wasm::certs::{ - PoolRegistration, PoolRetirement, StakeDelegation, StakeDeregistration, StakeRegistration, + PoolRetirement, StakeDelegation, StakeDeregistration, StakeRegistration, }; use cml_chain_wasm::Epoch; use cml_chain_wasm::{ @@ -168,9 +170,9 @@ impl AllegraCertificate { ) } - pub fn new_pool_registration(pool_params: &PoolParams) -> Self { + pub fn new_shelley_pool_registration(pool_params: &ShelleyPoolParams) -> Self { Self( - cml_multi_era::allegra::AllegraCertificate::new_pool_registration( + cml_multi_era::allegra::AllegraCertificate::new_shelley_pool_registration( pool_params.clone().into(), ), ) @@ -220,8 +222,8 @@ impl AllegraCertificate { cml_multi_era::allegra::AllegraCertificate::StakeDelegation(_) => { AllegraCertificateKind::StakeDelegation } - cml_multi_era::allegra::AllegraCertificate::PoolRegistration(_) => { - AllegraCertificateKind::PoolRegistration + cml_multi_era::allegra::AllegraCertificate::ShelleyPoolRegistration(_) => { + AllegraCertificateKind::ShelleyPoolRegistration } cml_multi_era::allegra::AllegraCertificate::PoolRetirement(_) => { AllegraCertificateKind::PoolRetirement @@ -262,11 +264,11 @@ impl AllegraCertificate { } } - pub fn as_pool_registration(&self) -> Option { + pub fn as_shelley_pool_registration(&self) -> Option { match &self.0 { - cml_multi_era::allegra::AllegraCertificate::PoolRegistration(pool_registration) => { - Some(pool_registration.clone().into()) - } + cml_multi_era::allegra::AllegraCertificate::ShelleyPoolRegistration( + shelley_pool_registration, + ) => Some(shelley_pool_registration.clone().into()), _ => None, } } @@ -304,7 +306,7 @@ pub enum AllegraCertificateKind { StakeRegistration, StakeDeregistration, StakeDelegation, - PoolRegistration, + ShelleyPoolRegistration, PoolRetirement, GenesisKeyDelegation, MoveInstantaneousRewardsCert, diff --git a/multi-era/wasm/src/alonzo/mod.rs b/multi-era/wasm/src/alonzo/mod.rs index 4fdf347f..9a592625 100644 --- a/multi-era/wasm/src/alonzo/mod.rs +++ b/multi-era/wasm/src/alonzo/mod.rs @@ -3,23 +3,24 @@ use crate::shelley::{ProtocolVersionStruct, ShelleyHeader}; use crate::{ - AllegraCertificateList, AlonzoFormatTxOutList, AlonzoTransactionBodyList, + AllegraCertificateList, AlonzoFormatTxOutList, AlonzoRedeemerList, AlonzoTransactionBodyList, AlonzoTransactionWitnessSetList, GenesisHashList, MapTransactionIndexToAlonzoAuxiliaryData, }; use cml_chain_wasm::assets::{Coin, Mint}; use cml_chain_wasm::auxdata::{Metadata, ShelleyFormatAuxData, ShelleyMaFormatAuxData}; use cml_chain_wasm::crypto::Nonce; -use cml_chain_wasm::plutus::{ExUnitPrices, ExUnits}; -use cml_chain_wasm::transaction::RequiredSigners; +use cml_chain_wasm::plutus::{ExUnitPrices, ExUnits, PlutusData}; +use cml_chain_wasm::RequiredSigners; use cml_chain_wasm::TransactionIndex; use cml_chain_wasm::{ BootstrapWitnessList, IntList, NativeScriptList, PlutusDataList, PlutusV1ScriptList, - RedeemerList, TransactionInputList, VkeywitnessList, + TransactionInputList, VkeywitnessList, }; use cml_chain_wasm::{Epoch, NetworkId, Rational, UnitInterval, Withdrawals}; use cml_core::ordered_hash_map::OrderedHashMap; use cml_core_wasm::{impl_wasm_cbor_json_api, impl_wasm_conversions}; use cml_crypto_wasm::{AuxiliaryDataHash, GenesisHash, ScriptDataHash}; +use cml_multi_era::alonzo::AlonzoRedeemerTag; use wasm_bindgen::prelude::{wasm_bindgen, JsError, JsValue}; #[derive(Clone, Debug)] @@ -487,6 +488,42 @@ impl AlonzoProtocolParamUpdate { } } +#[derive(Clone, Debug)] +#[wasm_bindgen] +pub struct AlonzoRedeemer(cml_multi_era::alonzo::AlonzoRedeemer); + +impl_wasm_cbor_json_api!(AlonzoRedeemer); + +impl_wasm_conversions!(cml_multi_era::alonzo::AlonzoRedeemer, AlonzoRedeemer); + +#[wasm_bindgen] +impl AlonzoRedeemer { + pub fn tag(&self) -> AlonzoRedeemerTag { + self.0.tag + } + + pub fn index(&self) -> u64 { + self.0.index + } + + pub fn data(&self) -> PlutusData { + self.0.data.clone().into() + } + + pub fn ex_units(&self) -> ExUnits { + self.0.ex_units.clone().into() + } + + pub fn new(tag: AlonzoRedeemerTag, index: u64, data: &PlutusData, ex_units: &ExUnits) -> Self { + Self(cml_multi_era::alonzo::AlonzoRedeemer::new( + tag, + index, + data.clone().into(), + ex_units.clone().into(), + )) + } +} + #[derive(Clone, Debug)] #[wasm_bindgen] pub struct AlonzoTransaction(cml_multi_era::alonzo::AlonzoTransaction); @@ -715,11 +752,11 @@ impl AlonzoTransactionWitnessSet { self.0.plutus_datums.clone().map(std::convert::Into::into) } - pub fn set_redeemers(&mut self, redeemers: &RedeemerList) { + pub fn set_redeemers(&mut self, redeemers: &AlonzoRedeemerList) { self.0.redeemers = Some(redeemers.clone().into()) } - pub fn redeemers(&self) -> Option { + pub fn redeemers(&self) -> Option { self.0.redeemers.clone().map(std::convert::Into::into) } diff --git a/multi-era/wasm/src/babbage/mod.rs b/multi-era/wasm/src/babbage/mod.rs index c1f3826b..e57b5061 100644 --- a/multi-era/wasm/src/babbage/mod.rs +++ b/multi-era/wasm/src/babbage/mod.rs @@ -3,8 +3,9 @@ use crate::shelley::ProtocolVersionStruct; use crate::{ - AllegraCertificateList, BabbageTransactionBodyList, BabbageTransactionOutputList, - BabbageTransactionWitnessSetList, GenesisHashList, MapTransactionIndexToBabbageAuxiliaryData, + AllegraCertificateList, AlonzoRedeemerList, BabbageTransactionBodyList, + BabbageTransactionOutputList, BabbageTransactionWitnessSetList, GenesisHashList, + MapTransactionIndexToBabbageAuxiliaryData, }; use cml_chain_wasm::address::Address; use cml_chain_wasm::assets::{Coin, Mint, Value}; @@ -12,10 +13,10 @@ use cml_chain_wasm::auxdata::{ShelleyFormatAuxData, ShelleyMaFormatAuxData}; use cml_chain_wasm::block::Header; use cml_chain_wasm::crypto::{AuxiliaryDataHash, GenesisHash, ScriptDataHash}; use cml_chain_wasm::plutus::{ExUnitPrices, ExUnits, PlutusV1Script, PlutusV2Script}; -use cml_chain_wasm::transaction::{AlonzoFormatTxOut, DatumOption, NativeScript, RequiredSigners}; +use cml_chain_wasm::transaction::{AlonzoFormatTxOut, DatumOption, NativeScript}; use cml_chain_wasm::{ BootstrapWitnessList, IntList, NativeScriptList, NetworkId, PlutusDataList, PlutusV1ScriptList, - PlutusV2ScriptList, RedeemerList, TransactionInputList, VkeywitnessList, + PlutusV2ScriptList, RequiredSigners, TransactionInputList, VkeywitnessList, }; use cml_chain_wasm::{Epoch, Rational, UnitInterval, Withdrawals}; use cml_core::ordered_hash_map::OrderedHashMap; @@ -943,11 +944,11 @@ impl BabbageTransactionWitnessSet { self.0.plutus_datums.clone().map(std::convert::Into::into) } - pub fn set_redeemers(&mut self, redeemers: &RedeemerList) { + pub fn set_redeemers(&mut self, redeemers: &AlonzoRedeemerList) { self.0.redeemers = Some(redeemers.clone().into()) } - pub fn redeemers(&self) -> Option { + pub fn redeemers(&self) -> Option { self.0.redeemers.clone().map(std::convert::Into::into) } diff --git a/multi-era/wasm/src/lib.rs b/multi-era/wasm/src/lib.rs index b7efb9ad..2bca3aa9 100644 --- a/multi-era/wasm/src/lib.rs +++ b/multi-era/wasm/src/lib.rs @@ -26,7 +26,8 @@ use crate::{ AllegraTransactionWitnessSet, }, alonzo::{ - AlonzoAuxiliaryData, AlonzoBlock, AlonzoTransactionBody, AlonzoTransactionWitnessSet, + AlonzoAuxiliaryData, AlonzoBlock, AlonzoRedeemer, AlonzoTransactionBody, + AlonzoTransactionWitnessSet, }, babbage::{ BabbageAuxiliaryData, BabbageBlock, BabbageTransactionBody, BabbageTransactionOutput, @@ -35,7 +36,7 @@ use crate::{ byron::{block::ByronBlock, transaction::ByronTx}, mary::{MaryBlock, MaryTransactionBody, MaryTransactionOutput}, shelley::{ - MultisigScript, ShelleyBlock, ShelleyCertificate, ShelleyTransactionBody, + MultisigScript, ShelleyBlock, ShelleyCertificate, ShelleyRelay, ShelleyTransactionBody, ShelleyTransactionOutput, ShelleyTransactionWitnessSet, }, }; @@ -69,6 +70,12 @@ impl_wasm_list!( AllegraTransactionWitnessSetList ); +impl_wasm_list!( + cml_multi_era::alonzo::AlonzoRedeemer, + AlonzoRedeemer, + AlonzoRedeemerList +); + impl_wasm_list!( cml_multi_era::alonzo::AlonzoTransactionBody, AlonzoTransactionBody, @@ -463,6 +470,12 @@ impl_wasm_list!( ShelleyCertificateList ); +impl_wasm_list!( + cml_multi_era::shelley::ShelleyRelay, + ShelleyRelay, + ShelleyRelayList +); + impl_wasm_list!( cml_multi_era::shelley::ShelleyTransactionBody, ShelleyTransactionBody, diff --git a/multi-era/wasm/src/shelley/mod.rs b/multi-era/wasm/src/shelley/mod.rs index d009d81f..76004a6c 100644 --- a/multi-era/wasm/src/shelley/mod.rs +++ b/multi-era/wasm/src/shelley/mod.rs @@ -3,20 +3,22 @@ use crate::{ GenesisHashList, MapStakeCredentialToCoin, MapTransactionIndexToMetadata, MultisigScriptList, - ShelleyCertificateList, ShelleyTransactionBodyList, ShelleyTransactionOutputList, - ShelleyTransactionWitnessSetList, + ShelleyCertificateList, ShelleyRelayList, ShelleyTransactionBodyList, + ShelleyTransactionOutputList, ShelleyTransactionWitnessSetList, }; -use cml_chain_wasm::address::Address; +use cml_chain_wasm::address::{Address, RewardAccount}; use cml_chain_wasm::assets::Coin; use cml_chain_wasm::auxdata::Metadata; use cml_chain_wasm::block::{OperationalCert, ProtocolVersion}; use cml_chain_wasm::certs::{ - PoolParams, PoolRegistration, PoolRetirement, StakeCredential, StakeDelegation, + Ipv4, Ipv6, PoolMetadata, PoolRetirement, SingleHostAddr, StakeCredential, StakeDelegation, StakeDeregistration, StakeRegistration, }; use cml_chain_wasm::crypto::{KESSignature, Nonce, VRFCert, Vkey}; -use cml_chain_wasm::{BootstrapWitnessList, TransactionInputList, VkeywitnessList}; -use cml_chain_wasm::{Epoch, Rational, UnitInterval, Withdrawals}; +use cml_chain_wasm::{ + BootstrapWitnessList, Ed25519KeyHashList, TransactionInputList, VkeywitnessList, +}; +use cml_chain_wasm::{Epoch, Port, Rational, UnitInterval, Withdrawals}; use cml_core::ordered_hash_map::OrderedHashMap; use cml_core_wasm::{impl_wasm_cbor_json_api, impl_wasm_conversions}; use cml_crypto_wasm::{ @@ -356,9 +358,9 @@ impl ShelleyCertificate { ) } - pub fn new_pool_registration(pool_params: &PoolParams) -> Self { + pub fn new_shelley_pool_registration(pool_params: &ShelleyPoolParams) -> Self { Self( - cml_multi_era::shelley::ShelleyCertificate::new_pool_registration( + cml_multi_era::shelley::ShelleyCertificate::new_shelley_pool_registration( pool_params.clone().into(), ), ) @@ -408,8 +410,8 @@ impl ShelleyCertificate { cml_multi_era::shelley::ShelleyCertificate::StakeDelegation(_) => { ShelleyCertificateKind::StakeDelegation } - cml_multi_era::shelley::ShelleyCertificate::PoolRegistration(_) => { - ShelleyCertificateKind::PoolRegistration + cml_multi_era::shelley::ShelleyCertificate::ShelleyPoolRegistration(_) => { + ShelleyCertificateKind::ShelleyPoolRegistration } cml_multi_era::shelley::ShelleyCertificate::PoolRetirement(_) => { ShelleyCertificateKind::PoolRetirement @@ -417,9 +419,9 @@ impl ShelleyCertificate { cml_multi_era::shelley::ShelleyCertificate::GenesisKeyDelegation(_) => { ShelleyCertificateKind::GenesisKeyDelegation } - cml_multi_era::shelley::ShelleyCertificate::ShelleyMoveInstantaneousRewardsCert { - .. - } => ShelleyCertificateKind::ShelleyMoveInstantaneousRewardsCert, + cml_multi_era::shelley::ShelleyCertificate::ShelleyMoveInstantaneousRewardsCert(_) => { + ShelleyCertificateKind::ShelleyMoveInstantaneousRewardsCert + } } } @@ -450,11 +452,11 @@ impl ShelleyCertificate { } } - pub fn as_pool_registration(&self) -> Option { + pub fn as_shelley_pool_registration(&self) -> Option { match &self.0 { - cml_multi_era::shelley::ShelleyCertificate::PoolRegistration(pool_registration) => { - Some(pool_registration.clone().into()) - } + cml_multi_era::shelley::ShelleyCertificate::ShelleyPoolRegistration( + shelley_pool_registration, + ) => Some(shelley_pool_registration.clone().into()), _ => None, } } @@ -481,10 +483,9 @@ impl ShelleyCertificate { &self, ) -> Option { match &self.0 { - cml_multi_era::shelley::ShelleyCertificate::ShelleyMoveInstantaneousRewardsCert { + cml_multi_era::shelley::ShelleyCertificate::ShelleyMoveInstantaneousRewardsCert( shelley_move_instantaneous_rewards_cert, - .. - } => Some(shelley_move_instantaneous_rewards_cert.clone().into()), + ) => Some(shelley_move_instantaneous_rewards_cert.clone().into()), _ => None, } } @@ -495,12 +496,27 @@ pub enum ShelleyCertificateKind { StakeRegistration, StakeDeregistration, StakeDelegation, - PoolRegistration, + ShelleyPoolRegistration, PoolRetirement, GenesisKeyDelegation, ShelleyMoveInstantaneousRewardsCert, } +#[derive(Clone, Debug)] +#[wasm_bindgen] +pub struct ShelleyDnsName(cml_multi_era::shelley::ShelleyDnsName); + +impl_wasm_cbor_json_api!(ShelleyDnsName); + +impl_wasm_conversions!(cml_multi_era::shelley::ShelleyDnsName, ShelleyDnsName); + +#[wasm_bindgen] +impl ShelleyDnsName { + pub fn get(&self) -> String { + self.0.get().clone() + } +} + #[derive(Clone, Debug)] #[wasm_bindgen] pub struct ShelleyHeader(cml_multi_era::shelley::ShelleyHeader); @@ -667,6 +683,125 @@ impl ShelleyMoveInstantaneousRewardsCert { } } +#[derive(Clone, Debug)] +#[wasm_bindgen] +pub struct ShelleyMultiHostName(cml_multi_era::shelley::ShelleyMultiHostName); + +impl_wasm_cbor_json_api!(ShelleyMultiHostName); + +impl_wasm_conversions!( + cml_multi_era::shelley::ShelleyMultiHostName, + ShelleyMultiHostName +); + +#[wasm_bindgen] +impl ShelleyMultiHostName { + pub fn shelley_dns_name(&self) -> ShelleyDnsName { + self.0.shelley_dns_name.clone().into() + } + + pub fn new(shelley_dns_name: &ShelleyDnsName) -> Self { + Self(cml_multi_era::shelley::ShelleyMultiHostName::new( + shelley_dns_name.clone().into(), + )) + } +} + +#[derive(Clone, Debug)] +#[wasm_bindgen] +pub struct ShelleyPoolParams(cml_multi_era::shelley::ShelleyPoolParams); + +impl_wasm_cbor_json_api!(ShelleyPoolParams); + +impl_wasm_conversions!(cml_multi_era::shelley::ShelleyPoolParams, ShelleyPoolParams); + +#[wasm_bindgen] +impl ShelleyPoolParams { + pub fn operator(&self) -> Ed25519KeyHash { + self.0.operator.into() + } + + pub fn vrf_keyhash(&self) -> VRFKeyHash { + self.0.vrf_keyhash.into() + } + + pub fn pledge(&self) -> Coin { + self.0.pledge + } + + pub fn cost(&self) -> Coin { + self.0.cost + } + + pub fn margin(&self) -> UnitInterval { + self.0.margin.clone().into() + } + + pub fn reward_account(&self) -> RewardAccount { + self.0.reward_account.clone().into() + } + + pub fn pool_owners(&self) -> Ed25519KeyHashList { + self.0.pool_owners.clone().into() + } + + pub fn relays(&self) -> ShelleyRelayList { + self.0.relays.clone().into() + } + + pub fn pool_metadata(&self) -> Option { + self.0.pool_metadata.clone().map(std::convert::Into::into) + } + + pub fn new( + operator: &Ed25519KeyHash, + vrf_keyhash: &VRFKeyHash, + pledge: Coin, + cost: Coin, + margin: &UnitInterval, + reward_account: &RewardAccount, + pool_owners: &Ed25519KeyHashList, + relays: &ShelleyRelayList, + pool_metadata: Option, + ) -> Self { + Self(cml_multi_era::shelley::ShelleyPoolParams::new( + operator.clone().into(), + vrf_keyhash.clone().into(), + pledge, + cost, + margin.clone().into(), + reward_account.clone().into(), + pool_owners.clone().into(), + relays.clone().into(), + pool_metadata.map(Into::into), + )) + } +} + +#[derive(Clone, Debug)] +#[wasm_bindgen] +pub struct ShelleyPoolRegistration(cml_multi_era::shelley::ShelleyPoolRegistration); + +impl_wasm_cbor_json_api!(ShelleyPoolRegistration); + +impl_wasm_conversions!( + cml_multi_era::shelley::ShelleyPoolRegistration, + ShelleyPoolRegistration +); + +#[wasm_bindgen] +impl ShelleyPoolRegistration { + pub fn pool_params(&self) -> ShelleyPoolParams { + self.0.pool_params.clone().into() + } + + pub fn new(pool_params: &ShelleyPoolParams) -> Self { + Self(cml_multi_era::shelley::ShelleyPoolRegistration::new( + pool_params.clone().into(), + )) + } +} + #[derive(Clone, Debug)] #[wasm_bindgen] pub struct ShelleyProposedProtocolParameterUpdates( @@ -865,6 +1000,126 @@ impl ShelleyProtocolParamUpdate { } } +#[derive(Clone, Debug)] +#[wasm_bindgen] +pub struct ShelleyRelay(cml_multi_era::shelley::ShelleyRelay); + +impl_wasm_cbor_json_api!(ShelleyRelay); + +impl_wasm_conversions!(cml_multi_era::shelley::ShelleyRelay, ShelleyRelay); + +#[wasm_bindgen] +impl ShelleyRelay { + pub fn new_single_host_addr( + port: Option, + ipv4: Option, + ipv6: Option, + ) -> Self { + Self(cml_multi_era::shelley::ShelleyRelay::new_single_host_addr( + port, + ipv4.map(Into::into), + ipv6.map(Into::into), + )) + } + + pub fn new_shelley_single_host_name( + port: Option, + shelley_dns_name: &ShelleyDnsName, + ) -> Self { + Self( + cml_multi_era::shelley::ShelleyRelay::new_shelley_single_host_name( + port, + shelley_dns_name.clone().into(), + ), + ) + } + + pub fn new_shelley_multi_host_name(shelley_dns_name: &ShelleyDnsName) -> Self { + Self( + cml_multi_era::shelley::ShelleyRelay::new_shelley_multi_host_name( + shelley_dns_name.clone().into(), + ), + ) + } + + pub fn kind(&self) -> ShelleyRelayKind { + match &self.0 { + cml_multi_era::shelley::ShelleyRelay::SingleHostAddr(_) => { + ShelleyRelayKind::SingleHostAddr + } + cml_multi_era::shelley::ShelleyRelay::ShelleySingleHostName(_) => { + ShelleyRelayKind::ShelleySingleHostName + } + cml_multi_era::shelley::ShelleyRelay::ShelleyMultiHostName(_) => { + ShelleyRelayKind::ShelleyMultiHostName + } + } + } + + pub fn as_single_host_addr(&self) -> Option { + match &self.0 { + cml_multi_era::shelley::ShelleyRelay::SingleHostAddr(single_host_addr) => { + Some(single_host_addr.clone().into()) + } + _ => None, + } + } + + pub fn as_shelley_single_host_name(&self) -> Option { + match &self.0 { + cml_multi_era::shelley::ShelleyRelay::ShelleySingleHostName( + shelley_single_host_name, + ) => Some(shelley_single_host_name.clone().into()), + _ => None, + } + } + + pub fn as_shelley_multi_host_name(&self) -> Option { + match &self.0 { + cml_multi_era::shelley::ShelleyRelay::ShelleyMultiHostName(shelley_multi_host_name) => { + Some(shelley_multi_host_name.clone().into()) + } + _ => None, + } + } +} + +#[wasm_bindgen] +pub enum ShelleyRelayKind { + SingleHostAddr, + ShelleySingleHostName, + ShelleyMultiHostName, +} + +#[derive(Clone, Debug)] +#[wasm_bindgen] +pub struct ShelleySingleHostName(cml_multi_era::shelley::ShelleySingleHostName); + +impl_wasm_cbor_json_api!(ShelleySingleHostName); + +impl_wasm_conversions!( + cml_multi_era::shelley::ShelleySingleHostName, + ShelleySingleHostName +); + +#[wasm_bindgen] +impl ShelleySingleHostName { + pub fn port(&self) -> Option { + self.0.port + } + + pub fn shelley_dns_name(&self) -> ShelleyDnsName { + self.0.shelley_dns_name.clone().into() + } + + pub fn new(port: Option, shelley_dns_name: &ShelleyDnsName) -> Self { + Self(cml_multi_era::shelley::ShelleySingleHostName::new( + port, + shelley_dns_name.clone().into(), + )) + } +} + #[derive(Clone, Debug)] #[wasm_bindgen] pub struct ShelleyTransaction(cml_multi_era::shelley::ShelleyTransaction); diff --git a/multi-era/wasm/src/utils.rs b/multi-era/wasm/src/utils.rs index 7cc6841b..c7127384 100644 --- a/multi-era/wasm/src/utils.rs +++ b/multi-era/wasm/src/utils.rs @@ -12,10 +12,9 @@ use cml_chain_wasm::{ crypto::{GenesisHash, Nonce, VRFCert, Vkey}, governance::VotingProcedures, plutus::{CostModels, ExUnitPrices, ExUnits}, - transaction::RequiredSigners, DRepVotingThresholds, MapTransactionIndexToAuxiliaryData, NetworkId, PoolVotingThresholds, - ProposalProcedureList, Rational, TransactionInputList, TransactionWitnessSetList, UnitInterval, - Withdrawals, + ProposalProcedureList, Rational, RequiredSigners, TransactionInputList, + TransactionWitnessSetList, UnitInterval, Withdrawals, }; use cml_core::{Epoch, TransactionIndex}; use cml_core_wasm::{impl_wasm_conversions, impl_wasm_json_api, impl_wasm_list, impl_wasm_map}; @@ -620,13 +619,13 @@ impl MultiEraTransactionBody { pub fn collateral_inputs(&self) -> Option { self.0 .collateral_inputs() - .map(|inputs| inputs.clone().into()) + .map(|inputs| inputs.to_vec().into()) } pub fn required_signers(&self) -> Option { self.0 .required_signers() - .map(|signers| signers.clone().into()) + .map(|signers| signers.to_vec().into()) } pub fn network_id(&self) -> Option { @@ -644,7 +643,7 @@ impl MultiEraTransactionBody { pub fn reference_inputs(&self) -> Option { self.0 .reference_inputs() - .map(|inputs| inputs.clone().into()) + .map(|inputs| inputs.to_vec().into()) } pub fn voting_procedures(&self) -> Option { @@ -652,7 +651,7 @@ impl MultiEraTransactionBody { } pub fn proposal_procedures(&self) -> Option { - self.0.proposal_procedures().map(|pps| pps.clone().into()) + self.0.proposal_procedures().map(|pps| pps.to_vec().into()) } pub fn current_treasury_value(&self) -> Option { diff --git a/specs/conway/certs.cddl b/specs/conway/certs.cddl index d66eb727..e104e593 100644 --- a/specs/conway/certs.cddl +++ b/specs/conway/certs.cddl @@ -65,7 +65,7 @@ stake_vote_reg_deleg_cert = ( ; GOVCERT auth_committee_hot_cert = (14, committee_cold_credential, committee_hot_credential) -resign_committee_cold_cert = (15, committee_cold_credential) +resign_committee_cold_cert = (15, committee_cold_credential, anchor / null) reg_drep_cert = (16, drep_credential, coin, anchor / null) unreg_drep_cert = (17, drep_credential, coin) update_drep_cert = (18, drep_credential, anchor / null) @@ -97,7 +97,7 @@ pool_params = ( operator: ed25519_key_hash , cost: coin , margin: unit_interval , reward_account: reward_account - , pool_owners: [* ed25519_key_hash] + , pool_owners: set , relays: [* relay] , pool_metadata: pool_metadata / null ) @@ -125,7 +125,7 @@ relay = ] pool_metadata = [url, pool_metadata_hash] -url = tstr .size (0..64) +url = tstr .size (0..128) credential = [ diff --git a/specs/conway/crypto.cddl b/specs/conway/crypto.cddl index 0ad2ffa9..adbaa7cf 100644 --- a/specs/conway/crypto.cddl +++ b/specs/conway/crypto.cddl @@ -44,7 +44,7 @@ nonce_hash = _CDDL_CODEGEN_RAW_BYTES_TYPE_ nonce = [ ; @name identity - identity: 0 // + tag: 0 // ; @name hash tag: 1, hash: nonce_hash ] diff --git a/specs/conway/governance.cddl b/specs/conway/governance.cddl index d069e320..16353f60 100644 --- a/specs/conway/governance.cddl +++ b/specs/conway/governance.cddl @@ -18,7 +18,7 @@ gov_action = [ hard_fork_initiation_action // treasury_withdrawals_action // no_confidence // - new_committee // + update_committee // new_constitution // ; @name info_action 6 @@ -48,11 +48,12 @@ no_confidence = ( action_id: gov_action_id / null ) -new_committee = ( +update_committee = ( tag: 4, action_id: gov_action_id / null, - cold_credentials: [* committee_cold_credential], - committee + cold_credentials: set, + credentials: { * committee_cold_credential => epoch }, + unit_interval ) new_constitution = ( @@ -61,11 +62,6 @@ new_constitution = ( constitution ) -committee = [ - credentials: { $committee_cold_credential => epoch }, - unit_interval -] - constitution = [ anchor, script_hash / null, diff --git a/specs/multiera/allegra/mod.cddl b/specs/multiera/allegra/mod.cddl index 2bb9eb13..f43a42a5 100644 --- a/specs/multiera/allegra/mod.cddl +++ b/specs/multiera/allegra/mod.cddl @@ -23,11 +23,10 @@ move_instantaneous_reward = [ move_instantaneous_rewards_cert = (tag: 6, move_instantaneous_reward) allegra_certificate = [ - ; @name stake_registration - shelley_stake_registration // + stake_registration // stake_deregistration // stake_delegation // - pool_registration // + shelley_pool_registration // pool_retirement // genesis_key_delegation // move_instantaneous_rewards_cert diff --git a/specs/multiera/cml_chain/certs.cddl b/specs/multiera/cml_chain/certs.cddl index 440b29ad..2976be9a 100644 --- a/specs/multiera/cml_chain/certs.cddl +++ b/specs/multiera/cml_chain/certs.cddl @@ -1,11 +1,16 @@ stake_credential = _CDDL_CODEGEN_EXTERN_TYPE_ -; also port, ipv4, single_host_addr, etc but these are only used by relay -relay = _CDDL_CODEGEN_EXTERN_TYPE_ pool_metadata = _CDDL_CODEGEN_EXTERN_TYPE_ -single_host_addr = _CDDL_CODEGEN_EXTERN_TYPE_ ; THESE CANNOT BE EXTERN SINCE THEY ARE PLAIN GROUPS SO DELETE THEM AFTER +ipv4 = bytes .size 4 ; @custom_json +ipv6 = bytes .size 16 ; @custom_json +single_host_addr = ( tag: 0 + , port / null + , ipv4 / null + , ipv6 / null + ) +stake_registration = (tag: 0, stake_credential) stake_deregistration = (tag: 1, stake_credential) stake_delegation = ( tag: 2, diff --git a/specs/multiera/cml_chain/mod.cddl b/specs/multiera/cml_chain/mod.cddl index 92632c35..32b8eb1f 100644 --- a/specs/multiera/cml_chain/mod.cddl +++ b/specs/multiera/cml_chain/mod.cddl @@ -18,4 +18,5 @@ delta_coin = _CDDL_CODEGEN_EXTERN_TYPE_ network_id = _CDDL_CODEGEN_EXTERN_TYPE_ epoch = uint +port = uint .le 65535 withdrawals = { * reward_account => coin } diff --git a/specs/multiera/shelley/mod.cddl b/specs/multiera/shelley/mod.cddl index d65dc593..8eb0fb51 100644 --- a/specs/multiera/shelley/mod.cddl +++ b/specs/multiera/shelley/mod.cddl @@ -63,25 +63,22 @@ shelley_multi_host_name = ( shelley_relay = [ single_host_addr // - ; @name single_host_name shelley_single_host_name // - ; @name multi_host_name shelley_multi_host_name ] shelley_certificate = [ - ; @name stake_registration - shelley_stake_registration // + stake_registration // stake_deregistration // stake_delegation // - pool_registration // + shelley_pool_registration // pool_retirement // genesis_key_delegation // shelley_move_instantaneous_rewards_cert ] genesis_key_delegation = (tag: 5, genesis_hash, genesis_delegate_hash, VRF_key_hash) -shelley_move_instantaneous_rewards_cert = [tag: 6, shelley_move_instantaneous_reward] +shelley_move_instantaneous_rewards_cert = (tag: 6, shelley_move_instantaneous_reward) shelley_transaction_body = { 0 : [* transaction_input], ; @name inputs From 386e91dbd41179fa6b975d6cb324a52f76d0f160 Mon Sep 17 00:00:00 2001 From: rooooooooob Date: Wed, 3 Apr 2024 14:53:44 -0700 Subject: [PATCH 3/5] resolve merge conflict --- chain/rust/src/plutus/mod.rs | 4 +--- chain/wasm/json-gen/src/lib.rs | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/chain/rust/src/plutus/mod.rs b/chain/rust/src/plutus/mod.rs index 1b75972b..79978f1e 100644 --- a/chain/rust/src/plutus/mod.rs +++ b/chain/rust/src/plutus/mod.rs @@ -130,9 +130,7 @@ impl LegacyRedeemer { } } -#[derive( - Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema, derivative::Derivative, -)] +#[derive(Clone, Debug, derivative::Derivative)] #[derivative( Eq, PartialEq, diff --git a/chain/wasm/json-gen/src/lib.rs b/chain/wasm/json-gen/src/lib.rs index fb6a2f86..8062b4c6 100644 --- a/chain/wasm/json-gen/src/lib.rs +++ b/chain/wasm/json-gen/src/lib.rs @@ -165,8 +165,8 @@ pub fn export_schemas() { gen_json_schema!(cml_chain::plutus::ExUnits); gen_json_schema!(cml_chain::plutus::Language); gen_json_schema!(cml_chain::plutus::LegacyRedeemer); - gen_json_schema!(cml_chain::plutus::PlutusData); - gen_json_schema!(cml_chain::plutus::PlutusMap); + //gen_json_schema!(cml_chain::plutus::PlutusData); + //gen_json_schema!(cml_chain::plutus::PlutusMap); gen_json_schema!(cml_chain::plutus::PlutusV1Script); gen_json_schema!(cml_chain::plutus::PlutusV2Script); gen_json_schema!(cml_chain::plutus::PlutusV3Script); From fcb731461d7436a8493239e6d845e94dfe4c21d7 Mon Sep 17 00:00:00 2001 From: rooooooooob Date: Thu, 4 Apr 2024 07:20:36 -0700 Subject: [PATCH 4/5] use conway costmodels for all eras (babbage costmdls found in alonzo on sancho testnet) --- multi-era/rust/src/alonzo/cbor_encodings.rs | 8 - multi-era/rust/src/alonzo/mod.rs | 28 +-- multi-era/rust/src/alonzo/serialization.rs | 152 +----------- multi-era/rust/src/babbage/cbor_encodings.rs | 10 - multi-era/rust/src/babbage/mod.rs | 36 +-- multi-era/rust/src/babbage/serialization.rs | 233 ------------------- multi-era/rust/src/utils.rs | 65 ++---- multi-era/wasm/json-gen/src/lib.rs | 2 - multi-era/wasm/src/alonzo/mod.rs | 29 +-- multi-era/wasm/src/babbage/mod.rs | 35 +-- specs/multiera/alonzo/mod.cddl | 9 +- specs/multiera/babbage/mod.cddl | 9 +- specs/multiera/cml_chain/plutus.cddl | 3 +- 13 files changed, 50 insertions(+), 569 deletions(-) diff --git a/multi-era/rust/src/alonzo/cbor_encodings.rs b/multi-era/rust/src/alonzo/cbor_encodings.rs index d4f9a8d0..19882f12 100644 --- a/multi-era/rust/src/alonzo/cbor_encodings.rs +++ b/multi-era/rust/src/alonzo/cbor_encodings.rs @@ -16,14 +16,6 @@ pub struct AlonzoBlockEncoding { pub invalid_transactions_elem_encodings: Vec>, } -#[derive(Clone, Debug, Default)] -pub struct AlonzoCostmdlsEncoding { - pub len_encoding: LenEncoding, - pub orig_deser_order: Vec, - pub plutus_v1_encoding: LenEncoding, - pub plutus_v1_key_encoding: Option, -} - #[derive(Clone, Debug, Default)] pub struct AlonzoFormatAuxDataEncoding { pub len_encoding: LenEncoding, diff --git a/multi-era/rust/src/alonzo/mod.rs b/multi-era/rust/src/alonzo/mod.rs index e5b4969c..cceb8c31 100644 --- a/multi-era/rust/src/alonzo/mod.rs +++ b/multi-era/rust/src/alonzo/mod.rs @@ -5,21 +5,19 @@ pub mod cbor_encodings; pub mod serialization; pub mod utils; -use cml_core::Int; - use crate::allegra::AllegraCertificate; use crate::shelley::{ProtocolVersionStruct, ShelleyHeader}; use cbor_encodings::{ - AlonzoBlockEncoding, AlonzoCostmdlsEncoding, AlonzoFormatAuxDataEncoding, - AlonzoProtocolParamUpdateEncoding, AlonzoTransactionBodyEncoding, AlonzoTransactionEncoding, - AlonzoTransactionWitnessSetEncoding, AlonzoUpdateEncoding, + AlonzoBlockEncoding, AlonzoFormatAuxDataEncoding, AlonzoProtocolParamUpdateEncoding, + AlonzoTransactionBodyEncoding, AlonzoTransactionEncoding, AlonzoTransactionWitnessSetEncoding, + AlonzoUpdateEncoding, }; use cml_chain::assets::{Coin, Mint}; use cml_chain::auxdata::{Metadata, ShelleyFormatAuxData, ShelleyMaFormatAuxData}; use cml_chain::crypto::{ AuxiliaryDataHash, BootstrapWitness, GenesisHash, Nonce, ScriptDataHash, Vkeywitness, }; -use cml_chain::plutus::{ExUnitPrices, ExUnits, PlutusData, PlutusV1Script}; +use cml_chain::plutus::{CostModels, ExUnitPrices, ExUnits, PlutusData, PlutusV1Script}; use cml_chain::transaction::{AlonzoFormatTxOut, NativeScript, TransactionInput}; use cml_chain::TransactionIndex; use cml_chain::{Epoch, NetworkId, Rational, RequiredSigners, UnitInterval, Withdrawals}; @@ -79,21 +77,7 @@ impl AlonzoBlock { } } -#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] -pub struct AlonzoCostmdls { - pub plutus_v1: Vec, - #[serde(skip)] - pub encodings: Option, -} - -impl AlonzoCostmdls { - pub fn new(plutus_v1: Vec) -> Self { - Self { - plutus_v1, - encodings: None, - } - } -} +pub type AlonzoCostModels = CostModels; #[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] pub struct AlonzoFormatAuxData { @@ -143,7 +127,7 @@ pub struct AlonzoProtocolParamUpdate { pub protocol_version: Option, pub min_pool_cost: Option, pub ada_per_utxo_byte: Option, - pub cost_models_for_script_languages: Option, + pub cost_models_for_script_languages: Option, pub execution_costs: Option, pub max_tx_ex_units: Option, pub max_block_ex_units: Option, diff --git a/multi-era/rust/src/alonzo/serialization.rs b/multi-era/rust/src/alonzo/serialization.rs index 74372831..8cbeeae6 100644 --- a/multi-era/rust/src/alonzo/serialization.rs +++ b/multi-era/rust/src/alonzo/serialization.rs @@ -295,156 +295,6 @@ impl Deserialize for AlonzoBlock { } } -impl Serialize for AlonzoCostmdls { - fn serialize<'se, W: Write>( - &self, - serializer: &'se mut Serializer, - force_canonical: bool, - ) -> cbor_event::Result<&'se mut Serializer> { - serializer.write_map_sz( - self.encodings - .as_ref() - .map(|encs| encs.len_encoding) - .unwrap_or_default() - .to_len_sz(1, force_canonical), - )?; - let deser_order = self - .encodings - .as_ref() - .filter(|encs| !force_canonical && encs.orig_deser_order.len() == 1) - .map(|encs| encs.orig_deser_order.clone()) - .unwrap_or_else(|| vec![0]); - for field_index in deser_order { - match field_index { - 0 => { - serializer.write_unsigned_integer_sz( - 0u64, - fit_sz( - 0u64, - self.encodings - .as_ref() - .map(|encs| encs.plutus_v1_key_encoding) - .unwrap_or_default(), - force_canonical, - ), - )?; - serializer.write_array_sz( - self.encodings - .as_ref() - .map(|encs| encs.plutus_v1_encoding) - .unwrap_or_default() - .to_len_sz(self.plutus_v1.len() as u64, force_canonical), - )?; - for element in self.plutus_v1.iter() { - element.serialize(serializer, force_canonical)?; - } - self.encodings - .as_ref() - .map(|encs| encs.plutus_v1_encoding) - .unwrap_or_default() - .end(serializer, force_canonical)?; - } - _ => unreachable!(), - }; - } - self.encodings - .as_ref() - .map(|encs| encs.len_encoding) - .unwrap_or_default() - .end(serializer, force_canonical) - } -} - -impl Deserialize for AlonzoCostmdls { - fn deserialize(raw: &mut Deserializer) -> Result { - let len = raw.map_sz()?; - let len_encoding: LenEncoding = len.into(); - let mut read_len = CBORReadLen::new(len); - read_len.read_elems(1)?; - read_len.finish()?; - (|| -> Result<_, DeserializeError> { - let mut orig_deser_order = Vec::new(); - let mut plutus_v1_encoding = LenEncoding::default(); - let mut plutus_v1_key_encoding = None; - let mut plutus_v1 = None; - let mut read = 0; - while match len { - cbor_event::LenSz::Len(n, _) => read < n, - cbor_event::LenSz::Indefinite => true, - } { - match raw.cbor_type()? { - cbor_event::Type::UnsignedInteger => match raw.unsigned_integer_sz()? { - (0, key_enc) => { - if plutus_v1.is_some() { - return Err(DeserializeFailure::DuplicateKey(Key::Uint(0)).into()); - } - let (tmp_plutus_v1, tmp_plutus_v1_encoding) = - (|| -> Result<_, DeserializeError> { - let mut plutus_v1_arr = Vec::new(); - let len = raw.array_sz()?; - let plutus_v1_encoding = len.into(); - while match len { - cbor_event::LenSz::Len(n, _) => { - (plutus_v1_arr.len() as u64) < n - } - cbor_event::LenSz::Indefinite => true, - } { - if raw.cbor_type()? == cbor_event::Type::Special { - assert_eq!(raw.special()?, cbor_event::Special::Break); - break; - } - plutus_v1_arr.push(Int::deserialize(raw)?); - } - Ok((plutus_v1_arr, plutus_v1_encoding)) - })() - .map_err(|e| e.annotate("plutus_v1"))?; - plutus_v1 = Some(tmp_plutus_v1); - plutus_v1_encoding = tmp_plutus_v1_encoding; - plutus_v1_key_encoding = Some(key_enc); - orig_deser_order.push(0); - } - (unknown_key, _enc) => { - return Err( - DeserializeFailure::UnknownKey(Key::Uint(unknown_key)).into() - ) - } - }, - cbor_event::Type::Text => { - return Err(DeserializeFailure::UnknownKey(Key::Str(raw.text()?)).into()) - } - cbor_event::Type::Special => match len { - cbor_event::LenSz::Len(_, _) => { - return Err(DeserializeFailure::BreakInDefiniteLen.into()) - } - cbor_event::LenSz::Indefinite => match raw.special()? { - cbor_event::Special::Break => break, - _ => return Err(DeserializeFailure::EndingBreakMissing.into()), - }, - }, - other_type => { - return Err(DeserializeFailure::UnexpectedKeyType(other_type).into()) - } - } - read += 1; - } - let plutus_v1 = match plutus_v1 { - Some(x) => x, - None => return Err(DeserializeFailure::MandatoryFieldMissing(Key::Uint(0)).into()), - }; - Ok(Self { - plutus_v1, - encodings: Some(AlonzoCostmdlsEncoding { - len_encoding, - orig_deser_order, - plutus_v1_key_encoding, - plutus_v1_encoding, - }), - }) - })() - .map_err(|e| e.annotate("AlonzoCostmdls")) - } -} - impl Serialize for AlonzoFormatAuxData { fn serialize<'se, W: Write>( &self, @@ -1801,7 +1651,7 @@ impl Deserialize for AlonzoProtocolParamUpdate { let tmp_cost_models_for_script_languages = (|| -> Result<_, DeserializeError> { read_len.read_elems(1)?; - AlonzoCostmdls::deserialize(raw) + CostModels::deserialize(raw) })() .map_err(|e| e.annotate("cost_models_for_script_languages"))?; cost_models_for_script_languages = diff --git a/multi-era/rust/src/babbage/cbor_encodings.rs b/multi-era/rust/src/babbage/cbor_encodings.rs index 54977a38..a5077d7d 100644 --- a/multi-era/rust/src/babbage/cbor_encodings.rs +++ b/multi-era/rust/src/babbage/cbor_encodings.rs @@ -17,16 +17,6 @@ pub struct BabbageBlockEncoding { pub invalid_transactions_elem_encodings: Vec>, } -#[derive(Clone, Debug, Default)] -pub struct BabbageCostModelsEncoding { - pub len_encoding: LenEncoding, - pub orig_deser_order: Vec, - pub plutus_v1_encoding: LenEncoding, - pub plutus_v1_key_encoding: Option, - pub plutus_v2_encoding: LenEncoding, - pub plutus_v2_key_encoding: Option, -} - #[derive(Clone, Debug, Default)] pub struct BabbageFormatAuxDataEncoding { pub len_encoding: LenEncoding, diff --git a/multi-era/rust/src/babbage/mod.rs b/multi-era/rust/src/babbage/mod.rs index 0d9a9b54..3ff914f3 100644 --- a/multi-era/rust/src/babbage/mod.rs +++ b/multi-era/rust/src/babbage/mod.rs @@ -9,9 +9,9 @@ use crate::allegra::AllegraCertificate; use crate::alonzo::AlonzoRedeemer; use crate::shelley::ProtocolVersionStruct; use cbor_encodings::{ - BabbageBlockEncoding, BabbageCostModelsEncoding, BabbageFormatAuxDataEncoding, - BabbageFormatTxOutEncoding, BabbageProtocolParamUpdateEncoding, BabbageTransactionBodyEncoding, - BabbageTransactionEncoding, BabbageTransactionWitnessSetEncoding, BabbageUpdateEncoding, + BabbageBlockEncoding, BabbageFormatAuxDataEncoding, BabbageFormatTxOutEncoding, + BabbageProtocolParamUpdateEncoding, BabbageTransactionBodyEncoding, BabbageTransactionEncoding, + BabbageTransactionWitnessSetEncoding, BabbageUpdateEncoding, }; use cml_chain::address::Address; use cml_chain::assets::{Coin, Mint, Value}; @@ -20,13 +20,15 @@ use cml_chain::block::Header; use cml_chain::crypto::{ AuxiliaryDataHash, BootstrapWitness, GenesisHash, ScriptDataHash, Vkeywitness, }; -use cml_chain::plutus::{ExUnitPrices, ExUnits, PlutusData, PlutusV1Script, PlutusV2Script}; +use cml_chain::plutus::{ + CostModels, ExUnitPrices, ExUnits, PlutusData, PlutusV1Script, PlutusV2Script, +}; use cml_chain::transaction::{AlonzoFormatTxOut, DatumOption, NativeScript, TransactionInput}; use cml_chain::{Epoch, NetworkId, Rational, RequiredSigners, UnitInterval, Withdrawals}; use cml_core::ordered_hash_map::OrderedHashMap; use cml_core::serialization::LenEncoding; -use cml_core::{Int, TransactionIndex}; +use cml_core::TransactionIndex; use std::collections::BTreeMap; @@ -81,29 +83,7 @@ impl BabbageBlock { } } -#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] -pub struct BabbageCostModels { - pub plutus_v1: Option>, - pub plutus_v2: Option>, - #[serde(skip)] - pub encodings: Option, -} - -impl BabbageCostModels { - pub fn new() -> Self { - Self { - plutus_v1: None, - plutus_v2: None, - encodings: None, - } - } -} - -impl Default for BabbageCostModels { - fn default() -> Self { - Self::new() - } -} +pub type BabbageCostModels = CostModels; #[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] pub struct BabbageFormatAuxData { diff --git a/multi-era/rust/src/babbage/serialization.rs b/multi-era/rust/src/babbage/serialization.rs index ccc96304..812fb4e1 100644 --- a/multi-era/rust/src/babbage/serialization.rs +++ b/multi-era/rust/src/babbage/serialization.rs @@ -298,239 +298,6 @@ impl Deserialize for BabbageBlock { } } -impl Serialize for BabbageCostModels { - fn serialize<'se, W: Write>( - &self, - serializer: &'se mut Serializer, - force_canonical: bool, - ) -> cbor_event::Result<&'se mut Serializer> { - serializer.write_map_sz( - self.encodings - .as_ref() - .map(|encs| encs.len_encoding) - .unwrap_or_default() - .to_len_sz( - match &self.plutus_v1 { - Some(_) => 1, - None => 0, - } + match &self.plutus_v2 { - Some(_) => 1, - None => 0, - }, - force_canonical, - ), - )?; - let deser_order = self - .encodings - .as_ref() - .filter(|encs| { - !force_canonical - && encs.orig_deser_order.len() - == match &self.plutus_v1 { - Some(_) => 1, - None => 0, - } + match &self.plutus_v2 { - Some(_) => 1, - None => 0, - } - }) - .map(|encs| encs.orig_deser_order.clone()) - .unwrap_or_else(|| vec![0, 1]); - for field_index in deser_order { - match field_index { - 0 => { - if let Some(field) = &self.plutus_v1 { - serializer.write_unsigned_integer_sz( - 0u64, - fit_sz( - 0u64, - self.encodings - .as_ref() - .map(|encs| encs.plutus_v1_key_encoding) - .unwrap_or_default(), - force_canonical, - ), - )?; - serializer.write_array_sz( - self.encodings - .as_ref() - .map(|encs| encs.plutus_v1_encoding) - .unwrap_or_default() - .to_len_sz(field.len() as u64, force_canonical), - )?; - for element in field.iter() { - element.serialize(serializer, force_canonical)?; - } - self.encodings - .as_ref() - .map(|encs| encs.plutus_v1_encoding) - .unwrap_or_default() - .end(serializer, force_canonical)?; - } - } - 1 => { - if let Some(field) = &self.plutus_v2 { - serializer.write_unsigned_integer_sz( - 1u64, - fit_sz( - 1u64, - self.encodings - .as_ref() - .map(|encs| encs.plutus_v2_key_encoding) - .unwrap_or_default(), - force_canonical, - ), - )?; - serializer.write_array_sz( - self.encodings - .as_ref() - .map(|encs| encs.plutus_v2_encoding) - .unwrap_or_default() - .to_len_sz(field.len() as u64, force_canonical), - )?; - for element in field.iter() { - element.serialize(serializer, force_canonical)?; - } - self.encodings - .as_ref() - .map(|encs| encs.plutus_v2_encoding) - .unwrap_or_default() - .end(serializer, force_canonical)?; - } - } - _ => unreachable!(), - }; - } - self.encodings - .as_ref() - .map(|encs| encs.len_encoding) - .unwrap_or_default() - .end(serializer, force_canonical) - } -} - -impl Deserialize for BabbageCostModels { - fn deserialize(raw: &mut Deserializer) -> Result { - let len = raw.map_sz()?; - let len_encoding: LenEncoding = len.into(); - let mut read_len = CBORReadLen::new(len); - (|| -> Result<_, DeserializeError> { - let mut orig_deser_order = Vec::new(); - let mut plutus_v1_encoding = LenEncoding::default(); - let mut plutus_v1_key_encoding = None; - let mut plutus_v1 = None; - let mut plutus_v2_encoding = LenEncoding::default(); - let mut plutus_v2_key_encoding = None; - let mut plutus_v2 = None; - let mut read = 0; - while match len { - cbor_event::LenSz::Len(n, _) => read < n, - cbor_event::LenSz::Indefinite => true, - } { - match raw.cbor_type()? { - cbor_event::Type::UnsignedInteger => match raw.unsigned_integer_sz()? { - (0, key_enc) => { - if plutus_v1.is_some() { - return Err(DeserializeFailure::DuplicateKey(Key::Uint(0)).into()); - } - let (tmp_plutus_v1, tmp_plutus_v1_encoding) = - (|| -> Result<_, DeserializeError> { - read_len.read_elems(1)?; - let mut plutus_v1_arr = Vec::new(); - let len = raw.array_sz()?; - let plutus_v1_encoding = len.into(); - while match len { - cbor_event::LenSz::Len(n, _) => { - (plutus_v1_arr.len() as u64) < n - } - cbor_event::LenSz::Indefinite => true, - } { - if raw.cbor_type()? == cbor_event::Type::Special { - assert_eq!(raw.special()?, cbor_event::Special::Break); - break; - } - plutus_v1_arr.push(Int::deserialize(raw)?); - } - Ok((plutus_v1_arr, plutus_v1_encoding)) - })() - .map_err(|e| e.annotate("plutus_v1"))?; - plutus_v1 = Some(tmp_plutus_v1); - plutus_v1_encoding = tmp_plutus_v1_encoding; - plutus_v1_key_encoding = Some(key_enc); - orig_deser_order.push(0); - } - (1, key_enc) => { - if plutus_v2.is_some() { - return Err(DeserializeFailure::DuplicateKey(Key::Uint(1)).into()); - } - let (tmp_plutus_v2, tmp_plutus_v2_encoding) = - (|| -> Result<_, DeserializeError> { - read_len.read_elems(1)?; - let mut plutus_v2_arr = Vec::new(); - let len = raw.array_sz()?; - let plutus_v2_encoding = len.into(); - while match len { - cbor_event::LenSz::Len(n, _) => { - (plutus_v2_arr.len() as u64) < n - } - cbor_event::LenSz::Indefinite => true, - } { - if raw.cbor_type()? == cbor_event::Type::Special { - assert_eq!(raw.special()?, cbor_event::Special::Break); - break; - } - plutus_v2_arr.push(Int::deserialize(raw)?); - } - Ok((plutus_v2_arr, plutus_v2_encoding)) - })() - .map_err(|e| e.annotate("plutus_v2"))?; - plutus_v2 = Some(tmp_plutus_v2); - plutus_v2_encoding = tmp_plutus_v2_encoding; - plutus_v2_key_encoding = Some(key_enc); - orig_deser_order.push(1); - } - (unknown_key, _enc) => { - return Err( - DeserializeFailure::UnknownKey(Key::Uint(unknown_key)).into() - ) - } - }, - cbor_event::Type::Text => { - return Err(DeserializeFailure::UnknownKey(Key::Str(raw.text()?)).into()) - } - cbor_event::Type::Special => match len { - cbor_event::LenSz::Len(_, _) => { - return Err(DeserializeFailure::BreakInDefiniteLen.into()) - } - cbor_event::LenSz::Indefinite => match raw.special()? { - cbor_event::Special::Break => break, - _ => return Err(DeserializeFailure::EndingBreakMissing.into()), - }, - }, - other_type => { - return Err(DeserializeFailure::UnexpectedKeyType(other_type).into()) - } - } - read += 1; - } - read_len.finish()?; - Ok(Self { - plutus_v1, - plutus_v2, - encodings: Some(BabbageCostModelsEncoding { - len_encoding, - orig_deser_order, - plutus_v1_key_encoding, - plutus_v1_encoding, - plutus_v2_key_encoding, - plutus_v2_encoding, - }), - }) - })() - .map_err(|e| e.annotate("BabbageCostModels")) - } -} - impl Serialize for BabbageFormatAuxData { fn serialize<'se, W: Write>( &self, diff --git a/multi-era/rust/src/utils.rs b/multi-era/rust/src/utils.rs index 25c8e5c9..59170799 100644 --- a/multi-era/rust/src/utils.rs +++ b/multi-era/rust/src/utils.rs @@ -1,8 +1,8 @@ use crate::allegra::{ AllegraCertificate, MIRAction, MoveInstantaneousReward, MoveInstantaneousRewardsCert, }; -use crate::alonzo::{AlonzoCostmdls, AlonzoProtocolParamUpdate}; -use crate::babbage::{BabbageCostModels, BabbageProtocolParamUpdate, BabbageTransactionOutput}; +use crate::alonzo::AlonzoProtocolParamUpdate; +use crate::babbage::{BabbageProtocolParamUpdate, BabbageTransactionOutput}; use crate::byron::block::{ByronBlockHeader, ByronEbBlock, ByronMainBlock, EbbHead}; use crate::byron::transaction::ByronTxIn; use crate::mary::MaryTransactionOutput; @@ -30,13 +30,12 @@ use cml_chain::certs::{ }; use cml_chain::crypto::{Nonce, VRFCert, Vkey}; use cml_chain::governance::{ProposalProcedure, VotingProcedures}; -use cml_chain::plutus::cbor_encodings::CostModelsEncoding; use cml_chain::plutus::{CostModels, ExUnitPrices, ExUnits}; use cml_chain::transaction::{ AlonzoFormatTxOut, TransactionInput, TransactionOutput, TransactionWitnessSet, }; use cml_chain::{ - Coin, DRepVotingThresholds, LenEncoding, NetworkId, OrderedHashMap, PoolVotingThresholds, + Coin, DRepVotingThresholds, NetworkId, OrderedHashMap, PoolVotingThresholds, ProtocolParamUpdate, Rational, UnitInterval, Value, Withdrawals, }; use cml_core::error::{DeserializeError, DeserializeFailure}; @@ -1324,46 +1323,6 @@ impl From for MultiEraTransactionOutput { } } -impl From for CostModels { - fn from(cost_models: AlonzoCostmdls) -> Self { - Self { - plutus_v1: Some(cost_models.plutus_v1), - plutus_v2: None, - plutus_v3: None, - encodings: cost_models.encodings.map(|encs| CostModelsEncoding { - len_encoding: encs.len_encoding, - orig_deser_order: encs.orig_deser_order, - plutus_v1_encoding: encs.plutus_v1_encoding, - plutus_v1_key_encoding: encs.plutus_v1_key_encoding, - plutus_v2_encoding: LenEncoding::default(), - plutus_v2_key_encoding: None, - plutus_v3_encoding: LenEncoding::default(), - plutus_v3_key_encoding: None, - }), - } - } -} - -impl From for CostModels { - fn from(cost_models: BabbageCostModels) -> Self { - Self { - plutus_v1: cost_models.plutus_v1, - plutus_v2: cost_models.plutus_v2, - plutus_v3: None, - encodings: cost_models.encodings.map(|encs| CostModelsEncoding { - len_encoding: encs.len_encoding, - orig_deser_order: encs.orig_deser_order, - plutus_v1_encoding: encs.plutus_v1_encoding, - plutus_v1_key_encoding: encs.plutus_v1_key_encoding, - plutus_v2_encoding: encs.plutus_v2_encoding, - plutus_v2_key_encoding: encs.plutus_v2_key_encoding, - plutus_v3_encoding: LenEncoding::default(), - plutus_v3_key_encoding: None, - }), - } - } -} - const KNOWN_SLOT_LENGTH_SECS: u64 = 20; // 20 secs const KNOWN_EPOCH_LENGTH_SECS: u64 = 5 * 24 * 60 * 60; // 5 days @@ -1375,12 +1334,6 @@ fn byron_epoch_slot_to_absolute(epoch: u64, sub_epoch_slot: u64) -> u64 { mod test { use super::*; - #[test] - fn mary_block_nonce() { - let bytes = hex::decode("84828f1a0054dca41a01908b2f582008ecdb54a80c81073ddee790f3cf4f8d4ff4422eb369b41cd5e0e18c13de6bbe5820d498647f2b7a481e6207ee3dfe02f6292ae85224621c5aabf9c0bf84d097390f58203492992128b6388ed9b56ab0329e42c57df5d1ead48436ea26908195f33daf90825840a38e20ecfa89e9804837f88fe8f8cd13b6a9b4eafca581fdceebf545eea0ea7e4caf36af4d7549a36d15598f67dfbed9840b02b4469d37552a9212669a79096458509370fce20873730ca9fdce508a3a9b0d3350a153c0942f6c8bf5dccd4c699aa80a635ceccb965c6327d6ca25ca32727de977c81f9143438e963df7db2d0165423809360fc744a34a099f1f59f01603008258400005b23bdc51c75f8eeb21f83eacac3d0605891801471c6d61515b27810a1bb8094f4c0ae560ba418ef35bba28e09ed64ca671bdea2139087822455f83ac451258504d90ab3807ad8c84b48460ae154e460826c6af5f3f18d05abdb05ea2c478248428c7d4cb9e9a6d82d94df170c1cabead6fa6b7774e0017dbc5ede4d1cd7cbe34cb08a7af450ff449ff9f68b1cf14e8091924c858203d4f6c99d53160a58c879c9ca04a2bde019377456384aa90b92cc00bcdb3671958206c1a25de95c89fe2df4af81e8440ac621b723fcc06c0ddfc0f2c7dd900067c1f0418ad5840d21ef35d27287c1172ae7d7f593f9f84ea925260e8ca9dd913746085cbd2843d10926b87044bedbdaed4f923e543898e3f7f97f6c780ff01270fdf1e604c4a0a04005901c01bb9f5e7ee8f37a4b499ed7abe8114e76c3d6d453c228004103840798ec2c0b85fbc8de65cf68bf154834679cd9bdd90a849afaf9c950c43a30cac0b4eb504077d34b1c4bbdff197ba64266affc385d9a2bcedc6f08559fe93f2cb61d6c70af41f7582c74cbb7866a6c881b139832e250325bbe15674165a2b06e158ba91341427033f9ce3b813a2bff5451bdc3cc9b3ab7952920383d8f2aba9772251db7d6e8135c58df613036c908e405c9277193a36b1d9a4d40bb263696a3de374ab695ce2fd4401bf30e707ee43de4c05d7839f2bb1e8bed4d4e6b0d9cf0906807b4a6b0520b992825d0643add63168848f3fea1fe2ae147a174d5e7939161ba46a293838ab8cda64dc5a6989aea414b4e502d1edb8dd0c5d1421ab7fa92d4581d0b669d1114a5f340568d67c68ed1b07bb3beea0acedbd7ddb9c79478f6adcda27ff31d704c5a998839750d5ac084ce81e05766c4ae18f4f783063b6f3b76be050be55896ed7202695427b3e9c333319150e0dd993f3ba314ef89f53a8689939425c648060a58a5310efb311c6b3f7835e0f1a662f9f2e867a389e3394c7a1cc2f74de2c0330ebf40aab2cf4efbacaac3fed373b4d64d9c56d3cfcec7f28c9bf18926894a500818258209ea2ac72bc4e082b1a47c6914d9d953d73aff9792174cc1f08cf7215544dd1b901018182583901d42900731c039a877000445f88be659e574632707b056fd2960994c5b652ad81db60f5d8605dcec6e73d1ed932009651d9f3e8580ee07d221a1e1b9461021a0002b06d031a0190a6cb0758209a19f90d9ef5545280368b5503eeaa52c1da650f68fb2209255313a34c19a1d6a400818258200682aeb19e9a31ea5f7f5d4078c91ec94831b1498fcebcd30bc37b6800c17f7001018282582b82d818582183581ce03866945a566d9e8e32f27273877d026385a8e7d54d9494906ed530a0001ab897305f1a1fb8358082581d61d91ef01b73f3010bb173945cf5417257c00c002715a13052015ab54f1a26908966021a00029cd5031a01908ee6a4008182582048926e334cd6b9469a3540cfca974230f9fa25d0e90fa043566abef18d2049aa01018282584c82d818584283581c76ddc0051984f84c6be230066710c1aead629f632e718bb3f9c2c145a101581e581c73a2075d4789f0d61873b4c2d309310949ca41e434d97c21388727c8001a37285aec1a08b11eea82581d6179e67550b2ff311da1883ad0ccc6fb2bb7c75e5489acff735fcc68781ad17d4c43021a00029cd5031a01908ee6a40082825820df07e64b7151d6c6c4c15ae3b2b1944d501df2cf54ee5ae98feaf97e49e0067e00825820df07e64b7151d6c6c4c15ae3b2b1944d501df2cf54ee5ae98feaf97e49e0067e01018182581d614926b3e631270b5d5310b5481e0fc82b1a1c706ad278c4bc091e29211a2aab95ba021a0002d644031a05f5e100a40081825820c0cf68370b852bfed85b0a39ce4644c8195511149ab70620a9158206d08e05ce01018282581d61483f3120cfe28f4220f4b96228f8d110e5f2100285b914218e927c251b000000012a70c1c08258390111e921395d6c4ad0c7004ef928d9d0dcf5b33983749a14b59a0e6ee22aeb420cce4b576d6833d513fbb1aaf4b2396a427c9d96aee6d608df1b00000001b8a9ec0b021a00028de1031a0190a71ca400818258200b5dd952875af5c7ff5a251febd31e607ee1ff3be911e93d27a35f94c9e96cbd01018282584c82d818584283581c2be129a2509494c81b8fced13d9eb21529b6c1ef88f5ea3b578c27c7a101581e581c633c7e9a7d0419aaf93a78e0cf2fc2bcbc54a2a12371fd9d00645c8d001a6429c6be1a195edd7082584c82d818584283581c7cd9baffad4c847dce58c53bfaa0ae4d6f19ed9c0182585d3ca54bb9a101581e581cd4688480c96f8332739757b76b843a8c681328ec34c9b5b38d6898fb001a6ebfa4dc1b0000005286323835021a0002a8b1031a0190a72ba50081825820b2bdbe07d5cd4da8b8dbef9eee67ff6fb1877055d0b8309fbd4718591389eac5000181825839016445bb08465c26cf435a4274b8dadff753b3b9a87f4aa8f88479431d4eb646b86f18f6f4266684f37fbcf4027c650747dc45278ab0bf8c8e1a0048f96f021a000351d1031a01909ccd0682a7581c162f94554ac8c225383a2248c245659eda870eaa82d0ef25fc7dcd82a10d82015820d982e06fd33e7440b43cefad529b7ecafbaa255e38178ad4189a37e4ce9bf1fa581c2075a095b3c844a29c24317a94a643ab8e22d54a3a3a72a420260af6a10d82015820d982e06fd33e7440b43cefad529b7ecafbaa255e38178ad4189a37e4ce9bf1fa581c268cfc0b89e910ead22e0ade91493d8212f53f3e2164b2e4bef0819ba10d82015820d982e06fd33e7440b43cefad529b7ecafbaa255e38178ad4189a37e4ce9bf1fa581c60baee25cbc90047e83fd01e1e57dc0b06d3d0cb150d0ab40bbfead1a10d82015820d982e06fd33e7440b43cefad529b7ecafbaa255e38178ad4189a37e4ce9bf1fa581cad5463153dc3d24b9ff133e46136028bdc1edbb897f5a7cf1b37950ca10d82015820d982e06fd33e7440b43cefad529b7ecafbaa255e38178ad4189a37e4ce9bf1fa581cb9547b8a57656539a8d9bc42c008e38d9c8bd9c8adbb1e73ad529497a10d82015820d982e06fd33e7440b43cefad529b7ecafbaa255e38178ad4189a37e4ce9bf1fa581cf7b341c14cd58fca4195a9b278cce1ef402dc0e06deb77e543cd1757a10d82015820d982e06fd33e7440b43cefad529b7ecafbaa255e38178ad4189a37e4ce9bf1fa190102a40081825820a3d07b77d09868b01d07b4c53e40b71200639266b1776512e0981cd66f48eb5d0101828258390134d388e0c5251d087232b3dcc67caa6cce2937c97a270fb4f4a2499999b8e6a0a8c8e173ddd63478e982846ffbbcd165028a1cef78ae9ee71a078ca24982581d616904e8b2c26f3dda6c4a5db4b3ec9e31d581c9960977cfe9c6917a431a2d0faa34021a00029cd5031a01908ee6a40081825820ac9ceff2de86d2387950ed7d1197a517e772c5ddfecb5b94767fae888820b3d801018282584c82d818584283581c15c97f0866ba4f390e283a268b53e180cfdb5e34bcc464a357e36710a101581e581c83d3e2df30edf951c5ba0b8582a1a303432081a4295f18ba44e9a548001a6b9405c71a1392fc8082584c82d818584283581cde349abef27bb239d4ae5e7629c1400d32165097f684148808da3c97a101581e581c2b0b011ba3683d776e9d872a85987bd6e6942a6b8c30d6d7dc3dfb14001a18ff53f01b0000000107647432021a0002a8b1031a0190a729a40082825820bb6baeb11c7472779c3b3acc35db7897f2d36d11846909ba6dd5979239fd067000825820bb6baeb11c7472779c3b3acc35db7897f2d36d11846909ba6dd5979239fd067001018182584c82d818584283581c9c9490179ae2288142fcc6fc0f6aa8ff8c49531ed384740d5c73622ea101581e581c5981b261ab5ccd7bf7f2c1225ad7eefe385edcc839ba55113b3e95db001a0122212c1a0aba8850021a0002d644031a05f5e100a40082825820d4b800d689d733f523fa78361ffb5fade29d9bb13fcfbc344aa458bd0b0b976b018258203b7bfa5f182b349e13c0e1c56c6c81ca8c5cf40d7b72b416a3563783fc0ff134010182825839012d8b354447efe987387f329b63a3c86b6007371699ed5db4ac5cd88e2d8b354447efe987387f329b63a3c86b6007371699ed5db4ac5cd88e1a584abd6e82581d610237be10f5ec0ccb6cbd226b112f0940fed44ae0466d9b53962ba8b11a184eefca021a0002bf35031a01908ee6a400818258201cc75901ee9df32dbc50ce820052038faba13b465b25fe64f887d940c9f9458e0101828258390117c7c19c81dbf1187a5bdf387a320f46bf80246e30d5b97efd59ab9fdd7986e3b08ab70333fa1e4183b8735cf3474a31108fa0943de6b8cb1a034f468282584c82d818584283581c776eb96b96e2cbce528a47278a736ab725dd13ce98c027ccb548ed70a101581e581c1afbc57540db1561adeaccd7f4894065965cd230f6bdc70722aecd8b001a6a14bf9a1b0000000f31da326b021a0004623d031a0190a71ea400818258202c6cca35e5e4458cc35ebd173a6471b3ae29668fd06bd4ba5114955339f219e501018282584c82d818584283581cad8f02b7134781a28997cb23f2a78215322f6c1d8a58e9e47c9f445ea101581e581cc9a4c68c63646852d93de951824def94b774fd58431f7a5618115a19001a389631ac1a060871738258390181bfa0e759547ebf226bbd51a844095d56890ba05aea3a73665cbe881cdeaf2c1028e67b5b360171975136b41c9a58d9220bdd65fd6ac0791b00000003218293c1021a0005f9b0031a0190a71ea40081825820c306f318e9721757d3252cdc5dd31eac6bd6aee236beeb9601a772fa681e554301018282583901a6c024231f3bf4de746511675994db25b664aecc25789de65462eff4739f0761691131d31bd714501d8a6f9f44ac9b5b3a74932753c29efc821a00160a5ba1581c59960c8ca8871af59f70474cbb2c11e3d782614a4c4be7f25e6c783ea148616c666f6e7a6f731913888258390170a84cf34da92bfe2c4da8689f358caeb4d1715c73710aed235be3d71537f3dbdcfedc8079eb6e8c1af93563a6cc2a7ecfbe5b4ba92750ab821a9c11edf0a2581c36e8f59542d444e3afca00cecca881cbdf8257c1b07a2fd84ed25730a1574570737465696e4469646e744b696c6c48696d73656c661a000f4240581c59960c8ca8871af59f70474cbb2c11e3d782614a4c4be7f25e6c783ea148616c666f6e7a6f731984d0021a0002b041031a0190a73ba40081825820e71f446e150a646a1982fce26c0239395dfc52bf029d3b653e06232925148aa10101828258390126141bac8f8fde24eec91011bcffd28b7f221b52aaaddcb24b3b421f265b2a3a895d6d9ebf67b1d1f1b06927caf752d13e40bf4ea11c622a1a004c4b4082584c82d818584283581cfafa1e6485be8a43275f37446d9ec9268682dff27678956c1a01dffca101581e581cd8d97175289f3a7dd17a4b6107633ed785ce2d33a1ee00f20ef4d7fa001a9e288d2c1a3eff155d021a0002a56d031a0190a73ca4008182582020a32c2967acf50e42efa21bc6f2582f26def86152f15b66a0fffc61b1397d0100018282583901a0c0fed7b1d4288835dc2334aba0240d27e10dedb73badb27457ba91ec17628c4600f1d941b206a557581d904584da48ba972d554d3aa4891a03d8312082584c82d818584283581c505f6f99e8b2a44bc02753d04e1745910a28205187e4b743b6be8904a101581e581cd8d97175289f3a326c6a29619d56eb6e22830bd40ee474aea3ea120d001aa030fe341a02048ce2021a0002a56d031a0190a73da40083825820150ae07532b9e62de190ac6955cde4c33ec42ee86c7d8415c7f820d6561f280d08825820293f1fb4adaeded6aa8f3230d6075df6e8ea657fe3f36e3c78bfb71524d3a712098258204dbaa5d17d37aadddce5409a0aa4c299c9468f0cda7f672b3d9553713216e8290b018c82584c82d818584283581c0fea43d9bfa899adfbbf88e57e6798e53466219143130576b4122a44a101581e581c9b55b8bf594b59974d9edc197b6a68a1d5d10327348c8f5c20278339001a2c181f7a1a3b9aca0082584c82d818584283581c7d1d116c1bd0b92d8f307dcfdde3282316105c6249c995c5b4c96f48a101581e581c8f802fa39db6a972b8e0b1c4f7f9649c381f6af5dd53cc3658668cf1001aca1390591a01c52fa082584c82d818584283581c0fea43d9bfa899adfbbf88e57e6798e53466219143130576b4122a44a101581e581c9b55b8bf594b59974d9edc197b6a68a1d5d10327348c8f5c20278339001a2c181f7a1a01c9c38082584c82d818584283581cc5f21c78dba1146cb869e7c243165ea5841970045d4dd3cbec118f01a101581e581c4c119dd2b2270328df974203bca1f8e6d3bb601baebda45374871f21001ae0b305381b000000022ee0828082584c82d818584283581c90438a11280f3692dc611cb03d8d7cb1c3688ad8519b2c52b4acd791a101581e581c4c119dd2b2270357d09868034a444ba63688d21110f3a142d428c203001ae70673711a96d76ae082584c82d818584283581c23cf87cf3f4008fc1f26fd7667e3340325df267dfdb86b22234a11dfa101581e581c633c7e9a7d04199e20a1cae0b6a1c282c0310dba20b93265e8d2dbb9001a00cc23491a6e5404c082584c82d818584283581c7899f9c5244e1b64109325ae19e7f7920eb19f118fcc4cb525400b82a101581e581c84b2ff88d08bc4143a01f5c9795a72f04f627169d47c46873e86096b001a7919a0ea1a1a848ac882584c82d818584283581c700af7d911f9383b9a3011b68fb725dc43ff6b1884627c3e1007a20ba101581e581c84b2ff88d08bc4254f49a9c959dde14cccd5a314ef5d04631b2fc5e6001a1bfa4f131a00d86ce182584c82d818584283581cbe60727988fa9476b309f78e41f74035cfeb53c2c1ae16b3f5562b01a101581e581c84b2ff88d08bc477eb6000c9b770b219910c269ff575e1d78b74a975001aef4865821a00da751182584c82d818584283581cfc8a85f9862b26e153aae414ced247a0767a7e6003cec68d257833f8a101581e581c84b2ff88d08bc45186803ac9607c3c0743e23a1c18866c40919dd748001a58de0f8b1af82445c682584c82d818584283581c8449e1e8e805543715cc807d922f5fedf6c0437e5f410e7eb8e28055a101581e581c84b2ff88d08bc479e9e19dc90ee5e975b064ddf7bfacc41424d8ad82001ae306c9341a4304682b82584c82d818584283581c77970d82501e8dbbe906fdf9f208fbcce238fa93ee6331328d64bd8ca101581e581c84b2ff88d08bc4359d75e8c9aea1d751cd013be81d1b54cc374ed3c5001a4c8fcc631a31089b31021a0003908d031a0190a73fa400818258207c072edb52db7aefc6881f6ced60b7aad9b8fabf590dae34db09b5a4db81702105018282583901ad915af56530a5d452bcd4a88b87b0e1ca375feaab4fe399a1105312ad915af56530a5d452bcd4a88b87b0e1ca375feaab4fe399a11053121a02ec88cf82582b82d818582183581cbc14e6b9754d7eef691230ae09e4c52b03d1d824c80e22b65432d7a8a0001afaf343d61b0000000185309742021a0003656f031a3b9aca00a4008282582069572bee1b68d01c50b619de76461edbb90dd25c66e862c79fa9fa124efa92300082582069572bee1b68d01c50b619de76461edbb90dd25c66e862c79fa9fa124efa923001018282584c82d818584283581cfbfbb9e7f7844a40b2a6465af5ec17b8da45974c738d60d1cb21ba8fa101581e581ce378ee30d568143c4b061b6dfd1875fe5b27cd41917b30ce0107790b001a31db91811a832156008258390114ef538b66f44052ae6dc8c545250eebedf65c491327a9b8c7102e0c14ef538b66f44052ae6dc8c545250eebedf65c491327a9b8c7102e0c1a036cd490021a0002e4db031a05f5e100a4008182582089be624b89aa349ccd11c415695e0421d00fd3106b6334e877961437e51191c00101818258390119690bdc2289666c814de06b1095ca10ecf2092ed237669df9e3ee0619690bdc2289666c814de06b1095ca10ecf2092ed237669df9e3ee061a110c0380021a000add40031a0190a74d94a100818258202669028f7c59934d13efa39435215fc2486e389e35ba6c6b05dda7c65213257e5840b3cd2e84cae259105b7330bf4c871ff8796d42935ef822e3028f4e3128d660d04619443006f87971c3ec2fdd3f0ad9a63070e2d8037b88682c7c91b327c55b0ba100818258200d197b7eeef1b961962a2911d4b553f0d9c3114b8d3e61de3beb4f39dc348eb058407d6f5b2c1cce03a45c5f6d754da293936d7d3a013ef5822e9a36954b635fc0ed148da41a7ad85438d6fe7e32ff6e3a7c2e611a96ea891d08e3d570b14386a906a100818258206687a36f0a4b8abf2671f8affb7febeb8940e9ee83548d2a2924dbc74679c4665840289d23202301208dce8e594b84de249e4e6a77153ef66c7171431df21645f336ed1b37e5786c8e2e8c41b790b1deffa093ddd0cd6937121809abc327b45cc904a10082825820276601a019b13a328b7306c0faac593c064476af30beed0380aa035d4bc1fe315840331b8f8dd2c470f1318a87fb51fc1ab030448166aa61bcfea8052420658836e59036c52befdabb2cf4acb8637bc63f0bd822f21646b35ce1e167269c233bf800825820276601a019b13a328b7306c0faac593c064476af30beed0380aa035d4bc1fe315840331b8f8dd2c470f1318a87fb51fc1ab030448166aa61bcfea8052420658836e59036c52befdabb2cf4acb8637bc63f0bd822f21646b35ce1e167269c233bf800a10081825820783b5406ddd311ad3640afd90eb5bc45f85ff0b57fc5937ee365c8313636239f584070f587d9c080c8a76c5b26059bf3ec4b8dec9a98c955710303038636187aa76c01b386f87192cb2b2e4bb768b6c4a10cef33a631c9236799f034849c1508590aa1028184582063e3a4107a043aa1c7253612aa6e12e3c6231fa11f454aa06046f184cbf49fd758405d946178128a00dd003121c481a5d8f729e9b96b7dbf0bddbe57c94adcf000a83b68d7fc9f64a88d96fa87e1fc6c9cc1af2e1b86719b0d45febb7518459c970a58205bd2b0767d1f7de98f74403718cab3262e11105be4883947ed06785a3b3626825822a101581e581cd4688480c96f83055933ffb71bd2a85ea5ec4f45c5ccc0c98e8ee2bba1008882582061261a95b7613ee6bf2067dad77b70349729b0c50d57bc1cf30de0db4a1e73a85840375bfc568d815bc5d6778d3e2ec6287529a88602dee06e5c694ff8d727d8dc8d325e9c8967ebf992d8df9fd862f7b03a57c9c721a563c783a9847296484135028258209180d818e69cd997e34663c418a648c076f2e19cd4194e486e159d8580bc6cda5840c9664b3f484faa30ebed8308bc009ba2261b4826a6306b1a943cced6f0e00aa2fcbc8da3156db5d7d644196c74d44f81dfe477658ca20733272e4b1a9490fd0f82582089c29f8c4af27b7accbe589747820134ebbaa1caf3ce949270a3d0c7dcfd541b5840e46527dea5301bcb69d943dc3f0d7e97798b4b93addd28907cb08b0fd9741b285069476500407020249b28db467b16a782510e4bac318c1780f562a5a95ccd0e825820f14f712dc600d793052d4842d50cefa4e65884ea6cf83707079eb8ce302efc8558406bd6d8e0538963107baac0977e2b3ec8e3baab8dacf77851d8a7433412d0f3ac2a631cb4b1819e4d735e04ed4fc2ff89843d05de2847fc1a7a6756e19940910c8258208b53207629f9a30e4b2015044f337c01735abe67243c19470c9dae8c7b732798584059854e89e94fb2d6a363884aaf22d117e5fa22f77948d5a15f0aa551c4f97189d3a039467a046c8ead26612619c4ecc48ec88144ff077910891b1d95dd89a20c8258205fddeedade2714d6db2f9e1104743d2d8d818ecddc306e176108db14caadd4415840620c64cdf8d662028fb1ae1da2e9ccaaa81b79f40fae2ac8e425d174f8b6dc72383c61eb4a9ec1c5d10ecc1d643968e2fc00ad9e3d8e317faf3f3c261033f60a825820cbc6b506e94fbefe442eecee376f3b3ebaf89415ef5cd2efb666e06ddae483935840b74f2b37390269a78d45685d3197b4640c5cc9cf82b1c1c53d3f88e2117ce33bc7c6da056a9701818a37b8d657f4c4f25d39573a33fd8f57ceb6e228dd3e0f07825820e8c03a03c0b2ddbea4195caf39f41e669f7d251ecf221fbb2f275c0a5d7e05d158402d8fefb1305c16245613adeee72004c31840267dd01dbfaaa177dbe0da5f542ce52252b3d3da24adc17587443be4d8715d772ca0d9b4af8c97d38678b0eb440da10081825820393b3d3cab6be0897cbc87143cc3a24825dc1d8249df4d37969502931cf856ff584072e1e68e093e0511cd74666cbd04dc085f51824ecd699ccec34b65f67cd455172320e5dff108b5698a90599e95ac97ce29223e8eeb0341c93fc73cb01757ac06a10281845820d1f77134edfa56f240847ead978ca98e8bb5f43f476b6b71ef3e50ceb852b2135840df7a4a2e50bac5285264b9174f51d3f93ad0c309141737d3eef6a884db658ae63ad3e770cab31c93c11f873071fcfbdf0989081cc5a878fa11516e9325f271015820abbd19a5be197b7f66196c02a7a5fd714c3f95e2b280fd85dad81683b995b6cb5822a101581e581c2b0b011ba3683d58dd9d722a2f2cb9679b356ada972029c6b5f2ae61a10082825820ea5dd58ee48288c53c2ab95776da5e35357db5833f8ab3c420baa88dd920e11d58405bd3d606ca8810f5e50aabc09bbb69bd460bd90e6b68e016dd553b32da20ee1ec20ea79826ead8b52b7ca73b673ae5a59b132bb64fe565fcc462187b53f0a807825820ea5dd58ee48288c53c2ab95776da5e35357db5833f8ab3c420baa88dd920e11d58405bd3d606ca8810f5e50aabc09bbb69bd460bd90e6b68e016dd553b32da20ee1ec20ea79826ead8b52b7ca73b673ae5a59b132bb64fe565fcc462187b53f0a807a100818258206c0180db688a9e477b10a7792e3c4efd749cddbe0e05068b6cb586dee54056975840e4f95636842e596b03aaf3379907a96b48e4545ad591246df8ccb7c6c254c30e514f9135e7178d3a7badb521cc583ae458e137195c41ce4f0b2fe19920955000a102818458208b66d7f3bf0629a3cf791984bf0fa4568b83106c9257818e63edf63142e9bf2a58400a13b559254d21194e8fcf77662d0b73b778dc91f0f12aeb639becbcbcc2322df45bd9b2cdc85a6d3b842056191c2903dd9afcdfb234a62a9e0a8eff2f3fd10d582022cc1a6495cb1639e562a07c9aa86a4cf54e3dbb6839aa4ee6f0b6a20dc349ad5822a101581e581c1afbc57540db1561adeaccd7f4894065965cd230f6bdc70722aecd8ba100828258204db5d63d4561edc2b565f50c9be435ffb0bd606030aefba4fe0cd9ff86cbf473584082a9975d71dfd55cf3be8b1fa9da9b07737143e0a2f36aa8e43f793844c4448ed9a07a500e914a0e629dcaede71df676218143a324186c2a1b5e2224e114620f825820e68a43be6ae384bc3d33b2921c89914f5dd99bf088a45c5a31d17734e408d78e584076e9eb5c4a18bc8a5aad2ef4e4db2810fda3b76a6b8639cf82b2ad0141b80a97c0f568f3292fdc67bb378c91301fb06cd8ee4c543509cdb4dda4d1aef9d31a02a10081825820c9ed44b3f86f0beaa05d2e8e611488f3f369ecafbcf2754cfea82c84e248528b5840f7b52620cff9f200274014fca350d74a84d17b819e9cc6d23eb54a51078b7a59750a6c01e3f2b5a05bebe8520d0a80f14f78a32854ce889f99e7eae9c886540ba10281845820d02732f50b7c1c1b7a4e946d8d280195c2c96577f1ba2b90474ad509e35812055840a856245cd143457faabef30d675d0c45d2b63f16cf97c62d50f53d03e221d8e20869caf8f61982d29af7b3082f2e62d47484598495e95ac70a8c1b442aed97015820c227781775746f69bf6644f59dcfa6ac64864e307193ba95c2ea4514babd32d05822a101581e581cd8d97175289f3a7a3431a461b982088fca713f245b33843eeba6ace1a10281845820a0e38b160bd1292273c027fc08fca940abf54ecf3331dca01a5f195dc6b0ea1e5840617a03af56821787ae7a5e9ef0f28455157ee825a7913e1c0f27f35261e05d9916573fdce741d4ff419326c34aed1c02f0c998fbe33c247e1e800c5288e6d7015820937737a634d6ea5a0a2ef0f7658bb5337a21467e5ec565216a56bad4bd602a415822a101581e581cd8d97175289f3a14d655b2617089ce27d2df668f2901bc633cf7fcf4a102838458204a8e7f58407fdd312c4b093fbd30a69e1f6977b741d232e83e0fb99aed0e4cbd5840707b40421b8aa92605e34084d54e30643c253171bca2f5c2d3c56816a0295c025c870d9d0e3fa8df5c21764e33fbbd29d52bcdd77d7e6464f2948baa4e550d0a58203f043217f97312094c938259e57e9fb4d62b5ea373d00db3964b34ff898ac38f5822a101581e581c84b2ff88d08bc4408857d0c933f73033a3c62ced32e46b133ccbabef845820f80b356bd8105ebf65a3ca11b8ec2f8a179ac969b3bd6e9dcabf0e98bcb95a405840ff6e845dedeb967a24b042d839b52fadd4ba9855f13a76540b4de6818b016427b6e8a5512242142d732a5bc3d9df60d6e892293fdf5d33adde9bd22f69d1f6025820e7f9e3a251b0465dd169e2af1eac21512411370c42d5901670c9b6fb31658dc05822a101581e581c84b2ff88d08bc45e1dfb07c906b614497ca6cfe4ef27fdd314676c708458202ed3b6973c6f7fb567a9fefc01b351cbb06998c758c827fd34ff3d4512c55465584082351b0b888fd4854317304dc9e9865d75ab207a2c2bad439ca694a76e49a0224461f5291ee84db1a2377c2258ef8339ae9671e596218e1fd4383fe6ab984f0a5820dde71e8188d0e60442a9241ca91a5026c784677ed7b550d2ee49f12478076a365822a101581e581c84b2ff88d08bc4638430e8c9c992b98178c9a3a86159f877ff48e1f2a1028184582087fe94fa4925fcaa0948ac6b3a4ea590d11710fc999bfb3939864be95a30da8f584022093273e4658d71cf5cb737d1869247e39782e985e236c5b732996c1c6660528df5507fd272f5f15bdbf3578782d2dab8ab74d5b3b0fd48b0d8b8a26589bf005820250cd474ce3d2459197ee7ce25265f41eefc7b0fc37da633d10e4b02e87ad4ad41a0a1008282582086e3337f52290bc4f455da7e83a055c93e2a96b63fb3b7233f20f1a9c46e80a4584039db8d78698986021fc4cbfbe84665e1056dfaf91563a42841520ef5f03f573731bf6afb2ece1c85d8e2808cccc6d2b3a5587bfc72c9d88033d325bd7b6fb90282582086e3337f52290bc4f455da7e83a055c93e2a96b63fb3b7233f20f1a9c46e80a4584039db8d78698986021fc4cbfbe84665e1056dfaf91563a42841520ef5f03f573731bf6afb2ece1c85d8e2808cccc6d2b3a5587bfc72c9d88033d325bd7b6fb902a10281845820f0cd529bf77540b1211aa75a233601e0627951ccd4270d812c3add3c444bb0985840d9ed324cb3e74aec5baa40f3913856a015f78ab4b746b808268020bf2d293beb599eb390165c8299ce4e1a6ab0deece23c4401dc63fc6ad5a7f3c808a72f6f025820a7c5165bf99697dab666d48be507bbc475e282ae9743e72715f6e6b084234e835822a101581e581cba5f3d73c6d17e2e7d13dd396f0a74bf5cd02fd63ec68d0f09d9898fa100a219ef64a4015820ac05963babda59adb08a6ce3ab590199c0baaabd2763484f0bf5a7e72335ef25025820d1a756633fe50049d7cac880d793289e2b16ac4ef31abd411f730770d63c29e903583901d42900731c039a877000445f88be659e574632707b056fd2960994c5b652ad81db60f5d8605dcec6e73d1ed932009651d9f3e8580ee07d22041a01908adb19ef65a1015840787a36aa14eed279069272dd3ade19ea4e304a67da4524098619195e974b3be409fa6aee63a784c9fe9fac77b4718c84c3523c756b0701d10fa2171bec93db01").unwrap(); - let _block = MaryBlock::from_cbor_bytes(&bytes).unwrap(); - } - #[test] fn byron_network_block_parse() { let bytes = hex::decode("82018385015820f3e188a0adb6e8bc840286be2241bdf8d72efa8078d84534f4ac5e51189f537284830058200e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a85820afc0da64183bf2664f3d4eec7238d524ba607faeeab24fc100eb861dba69971b82035820d36a2619a672494604e11bb447cbcf5231e9f2ba25c2169177edc941bd50ad6c5820afc0da64183bf2664f3d4eec7238d524ba607faeeab24fc100eb861dba69971b58204e66280cd94d591072349bec0a3090a53aa945562efb6d08d56e53654b0e409884820119087158405eba3a05b57a84c877453667b2de00061b50dafafcdd83d7a0b7d0f0959eba7bef72eb9d18142f2deab055f197ac15a830e38aae8155e3cca07d212adb185110810c820282840058405eba3a05b57a84c877453667b2de00061b50dafafcdd83d7a0b7d0f0959eba7bef72eb9d18142f2deab055f197ac15a830e38aae8155e3cca07d212adb18511058409aae625d4d15bcb3733d420e064f1cd338f386e0af049fcd42b455a69d28ad366483d177ba2b801b4136e0d6662e5e9e0a24f2c80a0e78d4c235b4c08f201f4c5840939dcfe5555ee661b9db5d817a70d5c3fa9d1d97c2ae5849696d915606b530f7e9edda5d02a01e61524a766f9c356084616ba058a3de70ea51bf29cd187a5f0758402deb50bb6bb566cc688abe0548612b72e92e16a4b20542d2488eb479b31f6646457bdf8575e3bd9f168d278bb4cc7f91a27efaa7ec4e6e7ab24afafef84f7f0b8483010000826a63617264616e6f2d736c01a058204ba92aa320c60acc9ad7b9a64f2eda55c4d2ec28e604faf186708b4f0c4e8edf849fff8203d90102809fff82809fff81a0").unwrap(); @@ -1432,4 +1385,16 @@ mod test { "42f01b7eb6e7a822427057b5f7578a8f8048fb599642e562f38aa65da1aba0d5" ); } + + #[test] + fn sancho_testnet_alonzo_block_with_babbage_costmodels() { + let bytes = hex::decode("820585828f1910e21a000151bc5820ab3a121e39d38cd844ed40988b435d5776d2be3e1a3ff15ee8b6f6099b6eefbc58201aba5fea24ea77d696737416bdfb6136fda5f0fa745f6b4aa682283e7d3e0f2d58200bd8f3ceb4057507f67c7c5730a62d691359983cae18d02f94ca80a020c9a6e682584014bc82eb1ada0c58bf1458140a81d569e9889dc303b9ef71afaa27615bd6b1ef5583ed74a14203b195404977edf201ce92f72bbb915ae5e1a187b74adf1e009f5850bb6a6709fe6fecf871c1f2dd3a657d3d2a8afc1f76f60d7d4d64706396f7b15ed9a628bc9a15a5dd444b316872a9d8bcbe90c01a826ad15f4c8b7f647aaed832d18efa5607b27a17ad432773fbc8430a8258409428e60adabd462ceba6c7ad8a68e8c444b1e66c31ec3e498baddf7f58a7a57b663db391f9b181457148d3704d6fc62ab71615ebf3acf89e90336f2974e72bc8585011bdede95b5b188d5649467ad62ff4df95068ae5d9462f54211d4522dc812cddba98bc7f9e0187e550e4c424d31651a63c1692b6ef335d7346d7e3f499f496beb7f402356510c4b00ab3ed932069ee03190d9158201d39330aaf40049b703f7c1a9b2eb6c9f84f11cc8d8f456aafb6266f757d685a58201dc1cddf59c04f8744d412c5490f6b87367fa109a22140b4a2987edd1433f75f00005840556655ab6e794c101e840475c9fba24c75ee06c7b6932ca0b596e05ea973d7c77d0bb0af98ed08717fec6d365b6462817567dbbe484c1623cdee61c27e5dcd0107025901c04fbcd1a7d282498822e5ce754b2cf976551678ab7984b02d1a6c66556329667b4ac9a702c44e17dd68e678825afb2696d8c56cb94a1619edde2b5b570f818008060b62df089138b25a9130eaf11ce9467830b9194e4cd0fc50a61c190e50011297fdefb16849ab3c53191a8d254eee51109417c3be4605ffe795b6ff96aa0778a949a342a53e93ba4143be6b10df056eb80b60911490a48c54710081f9f2d21d6a93b21952ee892bd3a70954ecc7d3f733321a572df04c1b163b74c7d4280e00e4784b35077b8bac624644de3d4fe3dbf82fb4ff22a8e5ee9f30ac67caef4b8cef2021206c6f2395109fa34d164c926380fd88385a8d166ea7d0de46e179bdfcbf6c201aa8de5a44f211900909910b8add25494f26994ccde53b4812a9ec329e682507a3e272dcb6ebc3973ccb4a23e9dd0eedf3a5d3b713568c4ae02dbeaa9e5b4637ca5c1a03ae030c2b504cfa932476383a790c91e79ee05321113e01447a0783deedd9b6d0a14ea781719f7c2a90f09f400d52621234c40803a3c30ed3c4c0acedd89180822a9fdf6147faee7458f8feb3334878c569f2503925f147948066f34f1b7cd783bec633a5df03bd11f4d5a99b21450b5bfbc13cd29339fc1bbe81a4008182582064ed7c9676c3b2954c188b60def3950bd750f8af90a233b077b6ff434539530803018182581d604da890918cb29f4446d07602a7c3877887326eb9e98394b8d6ce57b31b006983fdc40520ce021a0004b3890682a3581cc1ad22cabb342cbb83ce3859708232f4945ccb669e9b5f932cffc0eda7021a00016000081901f40cd81e8200010e82070012a2009f1a0003236119032c01011903e819023b00011903e8195e7104011903e818201a0001ca761928eb041959d818641959d818641959d818641959d818641959d818641959d81864186418641959d81864194c5118201a0002acfa182019b551041a000363151901ff00011a00015c3518201a000797751936f404021a0002ff941a0006ea7818dc0001011903e8196ff604021a0003bd081a00034ec5183e011a00102e0f19312a011a00032e801901a5011a0002da781903e819cf06011a00013a34182019a8f118201903e818201a00013aac0119e143041903e80a1a00030219189c011a00030219189c011a0003207c1901d9011a000330001901ff0119ccf3182019fd40182019ffd5182019581e18201940b318201a00012adf18201a0002ff941a0006ea7818dc0001011a00010f92192da7000119eabb18201a0002ff941a0006ea7818dc0001011a0002ff941a0006ea7818dc0001011a000c504e197712041a001d6af61a0001425b041a00040c660004001a00014fab18201a0003236119032c010119a0de18201a00033d7618201979f41820197fb8182019a95d1820197df718201995aa18201a0374f693194a1f0aff019f1a0003236119032c01011903e819023b00011903e8195e7104011903e818201a0001ca761928eb041959d818641959d818641959d818641959d818641959d818641959d81864186418641959d81864194c5118201a0002acfa182019b551041a000363151901ff00011a00015c3518201a000797751936f404021a0002ff941a0006ea7818dc0001011903e8196ff604021a0003bd081a00034ec5183e011a00102e0f19312a011a00032e801901a5011a0002da781903e819cf06011a00013a34182019a8f118201903e818201a00013aac0119e143041903e80a1a00030219189c011a00030219189c011a0003207c1901d9011a000330001901ff0119ccf3182019fd40182019ffd5182019581e18201940b318201a00012adf18201a0002ff941a0006ea7818dc0001011a00010f92192da7000119eabb18201a0002ff941a0006ea7818dc0001011a0002ff941a0006ea7818dc0001011a0011b22c1a0005fdde00021a000c504e197712041a001d6af61a0001425b041a00040c660004001a00014fab18201a0003236119032c010119a0de18201a00033d7618201979f41820197fb8182019a95d1820197df718201995aa18201a0223accc0a1a0374f693194a1f0a1a02515e841980b30aff14821a00d59f801b00000002540be40015821a03b20b801b00000004a817c800581cc264bca994a3a5deee5a1d9b92a3d7e9d6cbdb81f2f6989bb7f7b437a7021a00016000081901f40cd81e8200010e82070012a2009f1a0003236119032c01011903e819023b00011903e8195e7104011903e818201a0001ca761928eb041959d818641959d818641959d818641959d818641959d818641959d81864186418641959d81864194c5118201a0002acfa182019b551041a000363151901ff00011a00015c3518201a000797751936f404021a0002ff941a0006ea7818dc0001011903e8196ff604021a0003bd081a00034ec5183e011a00102e0f19312a011a00032e801901a5011a0002da781903e819cf06011a00013a34182019a8f118201903e818201a00013aac0119e143041903e80a1a00030219189c011a00030219189c011a0003207c1901d9011a000330001901ff0119ccf3182019fd40182019ffd5182019581e18201940b318201a00012adf18201a0002ff941a0006ea7818dc0001011a00010f92192da7000119eabb18201a0002ff941a0006ea7818dc0001011a0002ff941a0006ea7818dc0001011a000c504e197712041a001d6af61a0001425b041a00040c660004001a00014fab18201a0003236119032c010119a0de18201a00033d7618201979f41820197fb8182019a95d1820197df718201995aa18201a0374f693194a1f0aff019f1a0003236119032c01011903e819023b00011903e8195e7104011903e818201a0001ca761928eb041959d818641959d818641959d818641959d818641959d818641959d81864186418641959d81864194c5118201a0002acfa182019b551041a000363151901ff00011a00015c3518201a000797751936f404021a0002ff941a0006ea7818dc0001011903e8196ff604021a0003bd081a00034ec5183e011a00102e0f19312a011a00032e801901a5011a0002da781903e819cf06011a00013a34182019a8f118201903e818201a00013aac0119e143041903e80a1a00030219189c011a00030219189c011a0003207c1901d9011a000330001901ff0119ccf3182019fd40182019ffd5182019581e18201940b318201a00012adf18201a0002ff941a0006ea7818dc0001011a00010f92192da7000119eabb18201a0002ff941a0006ea7818dc0001011a0002ff941a0006ea7818dc0001011a0011b22c1a0005fdde00021a000c504e197712041a001d6af61a0001425b041a00040c660004001a00014fab18201a0003236119032c010119a0de18201a00033d7618201979f41820197fb8182019a95d1820197df718201995aa18201a0223accc0a1a0374f693194a1f0a1a02515e841980b30aff14821a00d59f801b00000002540be40015821a03b20b801b00000004a817c800581cd4bf7eb45b72dffa5ac33d5c902fe409e4e611f2e9a52fb0d09784c3a7021a00016000081901f40cd81e8200010e82070012a2009f1a0003236119032c01011903e819023b00011903e8195e7104011903e818201a0001ca761928eb041959d818641959d818641959d818641959d818641959d818641959d81864186418641959d81864194c5118201a0002acfa182019b551041a000363151901ff00011a00015c3518201a000797751936f404021a0002ff941a0006ea7818dc0001011903e8196ff604021a0003bd081a00034ec5183e011a00102e0f19312a011a00032e801901a5011a0002da781903e819cf06011a00013a34182019a8f118201903e818201a00013aac0119e143041903e80a1a00030219189c011a00030219189c011a0003207c1901d9011a000330001901ff0119ccf3182019fd40182019ffd5182019581e18201940b318201a00012adf18201a0002ff941a0006ea7818dc0001011a00010f92192da7000119eabb18201a0002ff941a0006ea7818dc0001011a0002ff941a0006ea7818dc0001011a000c504e197712041a001d6af61a0001425b041a00040c660004001a00014fab18201a0003236119032c010119a0de18201a00033d7618201979f41820197fb8182019a95d1820197df718201995aa18201a0374f693194a1f0aff019f1a0003236119032c01011903e819023b00011903e8195e7104011903e818201a0001ca761928eb041959d818641959d818641959d818641959d818641959d818641959d81864186418641959d81864194c5118201a0002acfa182019b551041a000363151901ff00011a00015c3518201a000797751936f404021a0002ff941a0006ea7818dc0001011903e8196ff604021a0003bd081a00034ec5183e011a00102e0f19312a011a00032e801901a5011a0002da781903e819cf06011a00013a34182019a8f118201903e818201a00013aac0119e143041903e80a1a00030219189c011a00030219189c011a0003207c1901d9011a000330001901ff0119ccf3182019fd40182019ffd5182019581e18201940b318201a00012adf18201a0002ff941a0006ea7818dc0001011a00010f92192da7000119eabb18201a0002ff941a0006ea7818dc0001011a0002ff941a0006ea7818dc0001011a0011b22c1a0005fdde00021a000c504e197712041a001d6af61a0001425b041a00040c660004001a00014fab18201a0003236119032c010119a0de18201a00033d7618201979f41820197fb8182019a95d1820197df718201995aa18201a0223accc0a1a0374f693194a1f0a1a02515e841980b30aff14821a00d59f801b00000002540be40015821a03b20b801b00000004a817c8000181a100848258201aba5fea24ea77d696737416bdfb6136fda5f0fa745f6b4aa682283e7d3e0f2d5840545819f889b346c17b95aafb6a6f81cf63d1149e8571727c3b682e21ce0308562176a2f2d628a6b4680c6d4da80a91631f5028533cf2fb2519bb739ee04e3f0b825820b33fb2984d0a104491afeecdcc327dc1fb0d72fd8bcb2a819999a3a6ec1f38395840e531d044d7c36361ded8e8fb90ce0cb590d2fbe67eb8a581d26e8064a87fde7e720329594f541df0734ca85f18ec3b44bf1731dad406fa7cc73171940215dc09825820d7361dba245e89a9f1e87247810aad8ab6bb5d8e8cfce978b458ff3bb4f34cb75840b0ad3e36ae6d04218cdb44f0849210fb9b52ca4208dd1fa97f5a7970021179faf86959661390afc2c2d70ee7517d6fa22ab0e21c00f2752ab252ea9e883dde0e825820f442e8c87378195b57ac5cc02590290158eb8707eda84155a035e5f5e6ed4f0a58408b8a4fffc01fa067f0d3c9afc2223499528e0f1e6e6f50ff28ba731c3923be96f7c8e4a15419b5abec02a45c96c195d8077d7340a2c1d59e5cf05c22219da508a080").unwrap(); + let _block = MultiEraBlock::from_explicit_network_cbor_bytes(&bytes).unwrap(); + } + + #[test] + fn mary_block_nonce() { + let bytes = hex::decode("84828f1a0054dca41a01908b2f582008ecdb54a80c81073ddee790f3cf4f8d4ff4422eb369b41cd5e0e18c13de6bbe5820d498647f2b7a481e6207ee3dfe02f6292ae85224621c5aabf9c0bf84d097390f58203492992128b6388ed9b56ab0329e42c57df5d1ead48436ea26908195f33daf90825840a38e20ecfa89e9804837f88fe8f8cd13b6a9b4eafca581fdceebf545eea0ea7e4caf36af4d7549a36d15598f67dfbed9840b02b4469d37552a9212669a79096458509370fce20873730ca9fdce508a3a9b0d3350a153c0942f6c8bf5dccd4c699aa80a635ceccb965c6327d6ca25ca32727de977c81f9143438e963df7db2d0165423809360fc744a34a099f1f59f01603008258400005b23bdc51c75f8eeb21f83eacac3d0605891801471c6d61515b27810a1bb8094f4c0ae560ba418ef35bba28e09ed64ca671bdea2139087822455f83ac451258504d90ab3807ad8c84b48460ae154e460826c6af5f3f18d05abdb05ea2c478248428c7d4cb9e9a6d82d94df170c1cabead6fa6b7774e0017dbc5ede4d1cd7cbe34cb08a7af450ff449ff9f68b1cf14e8091924c858203d4f6c99d53160a58c879c9ca04a2bde019377456384aa90b92cc00bcdb3671958206c1a25de95c89fe2df4af81e8440ac621b723fcc06c0ddfc0f2c7dd900067c1f0418ad5840d21ef35d27287c1172ae7d7f593f9f84ea925260e8ca9dd913746085cbd2843d10926b87044bedbdaed4f923e543898e3f7f97f6c780ff01270fdf1e604c4a0a04005901c01bb9f5e7ee8f37a4b499ed7abe8114e76c3d6d453c228004103840798ec2c0b85fbc8de65cf68bf154834679cd9bdd90a849afaf9c950c43a30cac0b4eb504077d34b1c4bbdff197ba64266affc385d9a2bcedc6f08559fe93f2cb61d6c70af41f7582c74cbb7866a6c881b139832e250325bbe15674165a2b06e158ba91341427033f9ce3b813a2bff5451bdc3cc9b3ab7952920383d8f2aba9772251db7d6e8135c58df613036c908e405c9277193a36b1d9a4d40bb263696a3de374ab695ce2fd4401bf30e707ee43de4c05d7839f2bb1e8bed4d4e6b0d9cf0906807b4a6b0520b992825d0643add63168848f3fea1fe2ae147a174d5e7939161ba46a293838ab8cda64dc5a6989aea414b4e502d1edb8dd0c5d1421ab7fa92d4581d0b669d1114a5f340568d67c68ed1b07bb3beea0acedbd7ddb9c79478f6adcda27ff31d704c5a998839750d5ac084ce81e05766c4ae18f4f783063b6f3b76be050be55896ed7202695427b3e9c333319150e0dd993f3ba314ef89f53a8689939425c648060a58a5310efb311c6b3f7835e0f1a662f9f2e867a389e3394c7a1cc2f74de2c0330ebf40aab2cf4efbacaac3fed373b4d64d9c56d3cfcec7f28c9bf18926894a500818258209ea2ac72bc4e082b1a47c6914d9d953d73aff9792174cc1f08cf7215544dd1b901018182583901d42900731c039a877000445f88be659e574632707b056fd2960994c5b652ad81db60f5d8605dcec6e73d1ed932009651d9f3e8580ee07d221a1e1b9461021a0002b06d031a0190a6cb0758209a19f90d9ef5545280368b5503eeaa52c1da650f68fb2209255313a34c19a1d6a400818258200682aeb19e9a31ea5f7f5d4078c91ec94831b1498fcebcd30bc37b6800c17f7001018282582b82d818582183581ce03866945a566d9e8e32f27273877d026385a8e7d54d9494906ed530a0001ab897305f1a1fb8358082581d61d91ef01b73f3010bb173945cf5417257c00c002715a13052015ab54f1a26908966021a00029cd5031a01908ee6a4008182582048926e334cd6b9469a3540cfca974230f9fa25d0e90fa043566abef18d2049aa01018282584c82d818584283581c76ddc0051984f84c6be230066710c1aead629f632e718bb3f9c2c145a101581e581c73a2075d4789f0d61873b4c2d309310949ca41e434d97c21388727c8001a37285aec1a08b11eea82581d6179e67550b2ff311da1883ad0ccc6fb2bb7c75e5489acff735fcc68781ad17d4c43021a00029cd5031a01908ee6a40082825820df07e64b7151d6c6c4c15ae3b2b1944d501df2cf54ee5ae98feaf97e49e0067e00825820df07e64b7151d6c6c4c15ae3b2b1944d501df2cf54ee5ae98feaf97e49e0067e01018182581d614926b3e631270b5d5310b5481e0fc82b1a1c706ad278c4bc091e29211a2aab95ba021a0002d644031a05f5e100a40081825820c0cf68370b852bfed85b0a39ce4644c8195511149ab70620a9158206d08e05ce01018282581d61483f3120cfe28f4220f4b96228f8d110e5f2100285b914218e927c251b000000012a70c1c08258390111e921395d6c4ad0c7004ef928d9d0dcf5b33983749a14b59a0e6ee22aeb420cce4b576d6833d513fbb1aaf4b2396a427c9d96aee6d608df1b00000001b8a9ec0b021a00028de1031a0190a71ca400818258200b5dd952875af5c7ff5a251febd31e607ee1ff3be911e93d27a35f94c9e96cbd01018282584c82d818584283581c2be129a2509494c81b8fced13d9eb21529b6c1ef88f5ea3b578c27c7a101581e581c633c7e9a7d0419aaf93a78e0cf2fc2bcbc54a2a12371fd9d00645c8d001a6429c6be1a195edd7082584c82d818584283581c7cd9baffad4c847dce58c53bfaa0ae4d6f19ed9c0182585d3ca54bb9a101581e581cd4688480c96f8332739757b76b843a8c681328ec34c9b5b38d6898fb001a6ebfa4dc1b0000005286323835021a0002a8b1031a0190a72ba50081825820b2bdbe07d5cd4da8b8dbef9eee67ff6fb1877055d0b8309fbd4718591389eac5000181825839016445bb08465c26cf435a4274b8dadff753b3b9a87f4aa8f88479431d4eb646b86f18f6f4266684f37fbcf4027c650747dc45278ab0bf8c8e1a0048f96f021a000351d1031a01909ccd0682a7581c162f94554ac8c225383a2248c245659eda870eaa82d0ef25fc7dcd82a10d82015820d982e06fd33e7440b43cefad529b7ecafbaa255e38178ad4189a37e4ce9bf1fa581c2075a095b3c844a29c24317a94a643ab8e22d54a3a3a72a420260af6a10d82015820d982e06fd33e7440b43cefad529b7ecafbaa255e38178ad4189a37e4ce9bf1fa581c268cfc0b89e910ead22e0ade91493d8212f53f3e2164b2e4bef0819ba10d82015820d982e06fd33e7440b43cefad529b7ecafbaa255e38178ad4189a37e4ce9bf1fa581c60baee25cbc90047e83fd01e1e57dc0b06d3d0cb150d0ab40bbfead1a10d82015820d982e06fd33e7440b43cefad529b7ecafbaa255e38178ad4189a37e4ce9bf1fa581cad5463153dc3d24b9ff133e46136028bdc1edbb897f5a7cf1b37950ca10d82015820d982e06fd33e7440b43cefad529b7ecafbaa255e38178ad4189a37e4ce9bf1fa581cb9547b8a57656539a8d9bc42c008e38d9c8bd9c8adbb1e73ad529497a10d82015820d982e06fd33e7440b43cefad529b7ecafbaa255e38178ad4189a37e4ce9bf1fa581cf7b341c14cd58fca4195a9b278cce1ef402dc0e06deb77e543cd1757a10d82015820d982e06fd33e7440b43cefad529b7ecafbaa255e38178ad4189a37e4ce9bf1fa190102a40081825820a3d07b77d09868b01d07b4c53e40b71200639266b1776512e0981cd66f48eb5d0101828258390134d388e0c5251d087232b3dcc67caa6cce2937c97a270fb4f4a2499999b8e6a0a8c8e173ddd63478e982846ffbbcd165028a1cef78ae9ee71a078ca24982581d616904e8b2c26f3dda6c4a5db4b3ec9e31d581c9960977cfe9c6917a431a2d0faa34021a00029cd5031a01908ee6a40081825820ac9ceff2de86d2387950ed7d1197a517e772c5ddfecb5b94767fae888820b3d801018282584c82d818584283581c15c97f0866ba4f390e283a268b53e180cfdb5e34bcc464a357e36710a101581e581c83d3e2df30edf951c5ba0b8582a1a303432081a4295f18ba44e9a548001a6b9405c71a1392fc8082584c82d818584283581cde349abef27bb239d4ae5e7629c1400d32165097f684148808da3c97a101581e581c2b0b011ba3683d776e9d872a85987bd6e6942a6b8c30d6d7dc3dfb14001a18ff53f01b0000000107647432021a0002a8b1031a0190a729a40082825820bb6baeb11c7472779c3b3acc35db7897f2d36d11846909ba6dd5979239fd067000825820bb6baeb11c7472779c3b3acc35db7897f2d36d11846909ba6dd5979239fd067001018182584c82d818584283581c9c9490179ae2288142fcc6fc0f6aa8ff8c49531ed384740d5c73622ea101581e581c5981b261ab5ccd7bf7f2c1225ad7eefe385edcc839ba55113b3e95db001a0122212c1a0aba8850021a0002d644031a05f5e100a40082825820d4b800d689d733f523fa78361ffb5fade29d9bb13fcfbc344aa458bd0b0b976b018258203b7bfa5f182b349e13c0e1c56c6c81ca8c5cf40d7b72b416a3563783fc0ff134010182825839012d8b354447efe987387f329b63a3c86b6007371699ed5db4ac5cd88e2d8b354447efe987387f329b63a3c86b6007371699ed5db4ac5cd88e1a584abd6e82581d610237be10f5ec0ccb6cbd226b112f0940fed44ae0466d9b53962ba8b11a184eefca021a0002bf35031a01908ee6a400818258201cc75901ee9df32dbc50ce820052038faba13b465b25fe64f887d940c9f9458e0101828258390117c7c19c81dbf1187a5bdf387a320f46bf80246e30d5b97efd59ab9fdd7986e3b08ab70333fa1e4183b8735cf3474a31108fa0943de6b8cb1a034f468282584c82d818584283581c776eb96b96e2cbce528a47278a736ab725dd13ce98c027ccb548ed70a101581e581c1afbc57540db1561adeaccd7f4894065965cd230f6bdc70722aecd8b001a6a14bf9a1b0000000f31da326b021a0004623d031a0190a71ea400818258202c6cca35e5e4458cc35ebd173a6471b3ae29668fd06bd4ba5114955339f219e501018282584c82d818584283581cad8f02b7134781a28997cb23f2a78215322f6c1d8a58e9e47c9f445ea101581e581cc9a4c68c63646852d93de951824def94b774fd58431f7a5618115a19001a389631ac1a060871738258390181bfa0e759547ebf226bbd51a844095d56890ba05aea3a73665cbe881cdeaf2c1028e67b5b360171975136b41c9a58d9220bdd65fd6ac0791b00000003218293c1021a0005f9b0031a0190a71ea40081825820c306f318e9721757d3252cdc5dd31eac6bd6aee236beeb9601a772fa681e554301018282583901a6c024231f3bf4de746511675994db25b664aecc25789de65462eff4739f0761691131d31bd714501d8a6f9f44ac9b5b3a74932753c29efc821a00160a5ba1581c59960c8ca8871af59f70474cbb2c11e3d782614a4c4be7f25e6c783ea148616c666f6e7a6f731913888258390170a84cf34da92bfe2c4da8689f358caeb4d1715c73710aed235be3d71537f3dbdcfedc8079eb6e8c1af93563a6cc2a7ecfbe5b4ba92750ab821a9c11edf0a2581c36e8f59542d444e3afca00cecca881cbdf8257c1b07a2fd84ed25730a1574570737465696e4469646e744b696c6c48696d73656c661a000f4240581c59960c8ca8871af59f70474cbb2c11e3d782614a4c4be7f25e6c783ea148616c666f6e7a6f731984d0021a0002b041031a0190a73ba40081825820e71f446e150a646a1982fce26c0239395dfc52bf029d3b653e06232925148aa10101828258390126141bac8f8fde24eec91011bcffd28b7f221b52aaaddcb24b3b421f265b2a3a895d6d9ebf67b1d1f1b06927caf752d13e40bf4ea11c622a1a004c4b4082584c82d818584283581cfafa1e6485be8a43275f37446d9ec9268682dff27678956c1a01dffca101581e581cd8d97175289f3a7dd17a4b6107633ed785ce2d33a1ee00f20ef4d7fa001a9e288d2c1a3eff155d021a0002a56d031a0190a73ca4008182582020a32c2967acf50e42efa21bc6f2582f26def86152f15b66a0fffc61b1397d0100018282583901a0c0fed7b1d4288835dc2334aba0240d27e10dedb73badb27457ba91ec17628c4600f1d941b206a557581d904584da48ba972d554d3aa4891a03d8312082584c82d818584283581c505f6f99e8b2a44bc02753d04e1745910a28205187e4b743b6be8904a101581e581cd8d97175289f3a326c6a29619d56eb6e22830bd40ee474aea3ea120d001aa030fe341a02048ce2021a0002a56d031a0190a73da40083825820150ae07532b9e62de190ac6955cde4c33ec42ee86c7d8415c7f820d6561f280d08825820293f1fb4adaeded6aa8f3230d6075df6e8ea657fe3f36e3c78bfb71524d3a712098258204dbaa5d17d37aadddce5409a0aa4c299c9468f0cda7f672b3d9553713216e8290b018c82584c82d818584283581c0fea43d9bfa899adfbbf88e57e6798e53466219143130576b4122a44a101581e581c9b55b8bf594b59974d9edc197b6a68a1d5d10327348c8f5c20278339001a2c181f7a1a3b9aca0082584c82d818584283581c7d1d116c1bd0b92d8f307dcfdde3282316105c6249c995c5b4c96f48a101581e581c8f802fa39db6a972b8e0b1c4f7f9649c381f6af5dd53cc3658668cf1001aca1390591a01c52fa082584c82d818584283581c0fea43d9bfa899adfbbf88e57e6798e53466219143130576b4122a44a101581e581c9b55b8bf594b59974d9edc197b6a68a1d5d10327348c8f5c20278339001a2c181f7a1a01c9c38082584c82d818584283581cc5f21c78dba1146cb869e7c243165ea5841970045d4dd3cbec118f01a101581e581c4c119dd2b2270328df974203bca1f8e6d3bb601baebda45374871f21001ae0b305381b000000022ee0828082584c82d818584283581c90438a11280f3692dc611cb03d8d7cb1c3688ad8519b2c52b4acd791a101581e581c4c119dd2b2270357d09868034a444ba63688d21110f3a142d428c203001ae70673711a96d76ae082584c82d818584283581c23cf87cf3f4008fc1f26fd7667e3340325df267dfdb86b22234a11dfa101581e581c633c7e9a7d04199e20a1cae0b6a1c282c0310dba20b93265e8d2dbb9001a00cc23491a6e5404c082584c82d818584283581c7899f9c5244e1b64109325ae19e7f7920eb19f118fcc4cb525400b82a101581e581c84b2ff88d08bc4143a01f5c9795a72f04f627169d47c46873e86096b001a7919a0ea1a1a848ac882584c82d818584283581c700af7d911f9383b9a3011b68fb725dc43ff6b1884627c3e1007a20ba101581e581c84b2ff88d08bc4254f49a9c959dde14cccd5a314ef5d04631b2fc5e6001a1bfa4f131a00d86ce182584c82d818584283581cbe60727988fa9476b309f78e41f74035cfeb53c2c1ae16b3f5562b01a101581e581c84b2ff88d08bc477eb6000c9b770b219910c269ff575e1d78b74a975001aef4865821a00da751182584c82d818584283581cfc8a85f9862b26e153aae414ced247a0767a7e6003cec68d257833f8a101581e581c84b2ff88d08bc45186803ac9607c3c0743e23a1c18866c40919dd748001a58de0f8b1af82445c682584c82d818584283581c8449e1e8e805543715cc807d922f5fedf6c0437e5f410e7eb8e28055a101581e581c84b2ff88d08bc479e9e19dc90ee5e975b064ddf7bfacc41424d8ad82001ae306c9341a4304682b82584c82d818584283581c77970d82501e8dbbe906fdf9f208fbcce238fa93ee6331328d64bd8ca101581e581c84b2ff88d08bc4359d75e8c9aea1d751cd013be81d1b54cc374ed3c5001a4c8fcc631a31089b31021a0003908d031a0190a73fa400818258207c072edb52db7aefc6881f6ced60b7aad9b8fabf590dae34db09b5a4db81702105018282583901ad915af56530a5d452bcd4a88b87b0e1ca375feaab4fe399a1105312ad915af56530a5d452bcd4a88b87b0e1ca375feaab4fe399a11053121a02ec88cf82582b82d818582183581cbc14e6b9754d7eef691230ae09e4c52b03d1d824c80e22b65432d7a8a0001afaf343d61b0000000185309742021a0003656f031a3b9aca00a4008282582069572bee1b68d01c50b619de76461edbb90dd25c66e862c79fa9fa124efa92300082582069572bee1b68d01c50b619de76461edbb90dd25c66e862c79fa9fa124efa923001018282584c82d818584283581cfbfbb9e7f7844a40b2a6465af5ec17b8da45974c738d60d1cb21ba8fa101581e581ce378ee30d568143c4b061b6dfd1875fe5b27cd41917b30ce0107790b001a31db91811a832156008258390114ef538b66f44052ae6dc8c545250eebedf65c491327a9b8c7102e0c14ef538b66f44052ae6dc8c545250eebedf65c491327a9b8c7102e0c1a036cd490021a0002e4db031a05f5e100a4008182582089be624b89aa349ccd11c415695e0421d00fd3106b6334e877961437e51191c00101818258390119690bdc2289666c814de06b1095ca10ecf2092ed237669df9e3ee0619690bdc2289666c814de06b1095ca10ecf2092ed237669df9e3ee061a110c0380021a000add40031a0190a74d94a100818258202669028f7c59934d13efa39435215fc2486e389e35ba6c6b05dda7c65213257e5840b3cd2e84cae259105b7330bf4c871ff8796d42935ef822e3028f4e3128d660d04619443006f87971c3ec2fdd3f0ad9a63070e2d8037b88682c7c91b327c55b0ba100818258200d197b7eeef1b961962a2911d4b553f0d9c3114b8d3e61de3beb4f39dc348eb058407d6f5b2c1cce03a45c5f6d754da293936d7d3a013ef5822e9a36954b635fc0ed148da41a7ad85438d6fe7e32ff6e3a7c2e611a96ea891d08e3d570b14386a906a100818258206687a36f0a4b8abf2671f8affb7febeb8940e9ee83548d2a2924dbc74679c4665840289d23202301208dce8e594b84de249e4e6a77153ef66c7171431df21645f336ed1b37e5786c8e2e8c41b790b1deffa093ddd0cd6937121809abc327b45cc904a10082825820276601a019b13a328b7306c0faac593c064476af30beed0380aa035d4bc1fe315840331b8f8dd2c470f1318a87fb51fc1ab030448166aa61bcfea8052420658836e59036c52befdabb2cf4acb8637bc63f0bd822f21646b35ce1e167269c233bf800825820276601a019b13a328b7306c0faac593c064476af30beed0380aa035d4bc1fe315840331b8f8dd2c470f1318a87fb51fc1ab030448166aa61bcfea8052420658836e59036c52befdabb2cf4acb8637bc63f0bd822f21646b35ce1e167269c233bf800a10081825820783b5406ddd311ad3640afd90eb5bc45f85ff0b57fc5937ee365c8313636239f584070f587d9c080c8a76c5b26059bf3ec4b8dec9a98c955710303038636187aa76c01b386f87192cb2b2e4bb768b6c4a10cef33a631c9236799f034849c1508590aa1028184582063e3a4107a043aa1c7253612aa6e12e3c6231fa11f454aa06046f184cbf49fd758405d946178128a00dd003121c481a5d8f729e9b96b7dbf0bddbe57c94adcf000a83b68d7fc9f64a88d96fa87e1fc6c9cc1af2e1b86719b0d45febb7518459c970a58205bd2b0767d1f7de98f74403718cab3262e11105be4883947ed06785a3b3626825822a101581e581cd4688480c96f83055933ffb71bd2a85ea5ec4f45c5ccc0c98e8ee2bba1008882582061261a95b7613ee6bf2067dad77b70349729b0c50d57bc1cf30de0db4a1e73a85840375bfc568d815bc5d6778d3e2ec6287529a88602dee06e5c694ff8d727d8dc8d325e9c8967ebf992d8df9fd862f7b03a57c9c721a563c783a9847296484135028258209180d818e69cd997e34663c418a648c076f2e19cd4194e486e159d8580bc6cda5840c9664b3f484faa30ebed8308bc009ba2261b4826a6306b1a943cced6f0e00aa2fcbc8da3156db5d7d644196c74d44f81dfe477658ca20733272e4b1a9490fd0f82582089c29f8c4af27b7accbe589747820134ebbaa1caf3ce949270a3d0c7dcfd541b5840e46527dea5301bcb69d943dc3f0d7e97798b4b93addd28907cb08b0fd9741b285069476500407020249b28db467b16a782510e4bac318c1780f562a5a95ccd0e825820f14f712dc600d793052d4842d50cefa4e65884ea6cf83707079eb8ce302efc8558406bd6d8e0538963107baac0977e2b3ec8e3baab8dacf77851d8a7433412d0f3ac2a631cb4b1819e4d735e04ed4fc2ff89843d05de2847fc1a7a6756e19940910c8258208b53207629f9a30e4b2015044f337c01735abe67243c19470c9dae8c7b732798584059854e89e94fb2d6a363884aaf22d117e5fa22f77948d5a15f0aa551c4f97189d3a039467a046c8ead26612619c4ecc48ec88144ff077910891b1d95dd89a20c8258205fddeedade2714d6db2f9e1104743d2d8d818ecddc306e176108db14caadd4415840620c64cdf8d662028fb1ae1da2e9ccaaa81b79f40fae2ac8e425d174f8b6dc72383c61eb4a9ec1c5d10ecc1d643968e2fc00ad9e3d8e317faf3f3c261033f60a825820cbc6b506e94fbefe442eecee376f3b3ebaf89415ef5cd2efb666e06ddae483935840b74f2b37390269a78d45685d3197b4640c5cc9cf82b1c1c53d3f88e2117ce33bc7c6da056a9701818a37b8d657f4c4f25d39573a33fd8f57ceb6e228dd3e0f07825820e8c03a03c0b2ddbea4195caf39f41e669f7d251ecf221fbb2f275c0a5d7e05d158402d8fefb1305c16245613adeee72004c31840267dd01dbfaaa177dbe0da5f542ce52252b3d3da24adc17587443be4d8715d772ca0d9b4af8c97d38678b0eb440da10081825820393b3d3cab6be0897cbc87143cc3a24825dc1d8249df4d37969502931cf856ff584072e1e68e093e0511cd74666cbd04dc085f51824ecd699ccec34b65f67cd455172320e5dff108b5698a90599e95ac97ce29223e8eeb0341c93fc73cb01757ac06a10281845820d1f77134edfa56f240847ead978ca98e8bb5f43f476b6b71ef3e50ceb852b2135840df7a4a2e50bac5285264b9174f51d3f93ad0c309141737d3eef6a884db658ae63ad3e770cab31c93c11f873071fcfbdf0989081cc5a878fa11516e9325f271015820abbd19a5be197b7f66196c02a7a5fd714c3f95e2b280fd85dad81683b995b6cb5822a101581e581c2b0b011ba3683d58dd9d722a2f2cb9679b356ada972029c6b5f2ae61a10082825820ea5dd58ee48288c53c2ab95776da5e35357db5833f8ab3c420baa88dd920e11d58405bd3d606ca8810f5e50aabc09bbb69bd460bd90e6b68e016dd553b32da20ee1ec20ea79826ead8b52b7ca73b673ae5a59b132bb64fe565fcc462187b53f0a807825820ea5dd58ee48288c53c2ab95776da5e35357db5833f8ab3c420baa88dd920e11d58405bd3d606ca8810f5e50aabc09bbb69bd460bd90e6b68e016dd553b32da20ee1ec20ea79826ead8b52b7ca73b673ae5a59b132bb64fe565fcc462187b53f0a807a100818258206c0180db688a9e477b10a7792e3c4efd749cddbe0e05068b6cb586dee54056975840e4f95636842e596b03aaf3379907a96b48e4545ad591246df8ccb7c6c254c30e514f9135e7178d3a7badb521cc583ae458e137195c41ce4f0b2fe19920955000a102818458208b66d7f3bf0629a3cf791984bf0fa4568b83106c9257818e63edf63142e9bf2a58400a13b559254d21194e8fcf77662d0b73b778dc91f0f12aeb639becbcbcc2322df45bd9b2cdc85a6d3b842056191c2903dd9afcdfb234a62a9e0a8eff2f3fd10d582022cc1a6495cb1639e562a07c9aa86a4cf54e3dbb6839aa4ee6f0b6a20dc349ad5822a101581e581c1afbc57540db1561adeaccd7f4894065965cd230f6bdc70722aecd8ba100828258204db5d63d4561edc2b565f50c9be435ffb0bd606030aefba4fe0cd9ff86cbf473584082a9975d71dfd55cf3be8b1fa9da9b07737143e0a2f36aa8e43f793844c4448ed9a07a500e914a0e629dcaede71df676218143a324186c2a1b5e2224e114620f825820e68a43be6ae384bc3d33b2921c89914f5dd99bf088a45c5a31d17734e408d78e584076e9eb5c4a18bc8a5aad2ef4e4db2810fda3b76a6b8639cf82b2ad0141b80a97c0f568f3292fdc67bb378c91301fb06cd8ee4c543509cdb4dda4d1aef9d31a02a10081825820c9ed44b3f86f0beaa05d2e8e611488f3f369ecafbcf2754cfea82c84e248528b5840f7b52620cff9f200274014fca350d74a84d17b819e9cc6d23eb54a51078b7a59750a6c01e3f2b5a05bebe8520d0a80f14f78a32854ce889f99e7eae9c886540ba10281845820d02732f50b7c1c1b7a4e946d8d280195c2c96577f1ba2b90474ad509e35812055840a856245cd143457faabef30d675d0c45d2b63f16cf97c62d50f53d03e221d8e20869caf8f61982d29af7b3082f2e62d47484598495e95ac70a8c1b442aed97015820c227781775746f69bf6644f59dcfa6ac64864e307193ba95c2ea4514babd32d05822a101581e581cd8d97175289f3a7a3431a461b982088fca713f245b33843eeba6ace1a10281845820a0e38b160bd1292273c027fc08fca940abf54ecf3331dca01a5f195dc6b0ea1e5840617a03af56821787ae7a5e9ef0f28455157ee825a7913e1c0f27f35261e05d9916573fdce741d4ff419326c34aed1c02f0c998fbe33c247e1e800c5288e6d7015820937737a634d6ea5a0a2ef0f7658bb5337a21467e5ec565216a56bad4bd602a415822a101581e581cd8d97175289f3a14d655b2617089ce27d2df668f2901bc633cf7fcf4a102838458204a8e7f58407fdd312c4b093fbd30a69e1f6977b741d232e83e0fb99aed0e4cbd5840707b40421b8aa92605e34084d54e30643c253171bca2f5c2d3c56816a0295c025c870d9d0e3fa8df5c21764e33fbbd29d52bcdd77d7e6464f2948baa4e550d0a58203f043217f97312094c938259e57e9fb4d62b5ea373d00db3964b34ff898ac38f5822a101581e581c84b2ff88d08bc4408857d0c933f73033a3c62ced32e46b133ccbabef845820f80b356bd8105ebf65a3ca11b8ec2f8a179ac969b3bd6e9dcabf0e98bcb95a405840ff6e845dedeb967a24b042d839b52fadd4ba9855f13a76540b4de6818b016427b6e8a5512242142d732a5bc3d9df60d6e892293fdf5d33adde9bd22f69d1f6025820e7f9e3a251b0465dd169e2af1eac21512411370c42d5901670c9b6fb31658dc05822a101581e581c84b2ff88d08bc45e1dfb07c906b614497ca6cfe4ef27fdd314676c708458202ed3b6973c6f7fb567a9fefc01b351cbb06998c758c827fd34ff3d4512c55465584082351b0b888fd4854317304dc9e9865d75ab207a2c2bad439ca694a76e49a0224461f5291ee84db1a2377c2258ef8339ae9671e596218e1fd4383fe6ab984f0a5820dde71e8188d0e60442a9241ca91a5026c784677ed7b550d2ee49f12478076a365822a101581e581c84b2ff88d08bc4638430e8c9c992b98178c9a3a86159f877ff48e1f2a1028184582087fe94fa4925fcaa0948ac6b3a4ea590d11710fc999bfb3939864be95a30da8f584022093273e4658d71cf5cb737d1869247e39782e985e236c5b732996c1c6660528df5507fd272f5f15bdbf3578782d2dab8ab74d5b3b0fd48b0d8b8a26589bf005820250cd474ce3d2459197ee7ce25265f41eefc7b0fc37da633d10e4b02e87ad4ad41a0a1008282582086e3337f52290bc4f455da7e83a055c93e2a96b63fb3b7233f20f1a9c46e80a4584039db8d78698986021fc4cbfbe84665e1056dfaf91563a42841520ef5f03f573731bf6afb2ece1c85d8e2808cccc6d2b3a5587bfc72c9d88033d325bd7b6fb90282582086e3337f52290bc4f455da7e83a055c93e2a96b63fb3b7233f20f1a9c46e80a4584039db8d78698986021fc4cbfbe84665e1056dfaf91563a42841520ef5f03f573731bf6afb2ece1c85d8e2808cccc6d2b3a5587bfc72c9d88033d325bd7b6fb902a10281845820f0cd529bf77540b1211aa75a233601e0627951ccd4270d812c3add3c444bb0985840d9ed324cb3e74aec5baa40f3913856a015f78ab4b746b808268020bf2d293beb599eb390165c8299ce4e1a6ab0deece23c4401dc63fc6ad5a7f3c808a72f6f025820a7c5165bf99697dab666d48be507bbc475e282ae9743e72715f6e6b084234e835822a101581e581cba5f3d73c6d17e2e7d13dd396f0a74bf5cd02fd63ec68d0f09d9898fa100a219ef64a4015820ac05963babda59adb08a6ce3ab590199c0baaabd2763484f0bf5a7e72335ef25025820d1a756633fe50049d7cac880d793289e2b16ac4ef31abd411f730770d63c29e903583901d42900731c039a877000445f88be659e574632707b056fd2960994c5b652ad81db60f5d8605dcec6e73d1ed932009651d9f3e8580ee07d22041a01908adb19ef65a1015840787a36aa14eed279069272dd3ade19ea4e304a67da4524098619195e974b3be409fa6aee63a784c9fe9fac77b4718c84c3523c756b0701d10fa2171bec93db01").unwrap(); + let _block = MaryBlock::from_cbor_bytes(&bytes).unwrap(); + } } diff --git a/multi-era/wasm/json-gen/src/lib.rs b/multi-era/wasm/json-gen/src/lib.rs index 5b359616..c84629a4 100644 --- a/multi-era/wasm/json-gen/src/lib.rs +++ b/multi-era/wasm/json-gen/src/lib.rs @@ -29,7 +29,6 @@ pub fn export_schemas() { // alonzo gen_json_schema!(cml_multi_era::alonzo::AlonzoAuxiliaryData); gen_json_schema!(cml_multi_era::alonzo::AlonzoBlock); - gen_json_schema!(cml_multi_era::alonzo::AlonzoCostmdls); gen_json_schema!(cml_multi_era::alonzo::AlonzoFormatAuxData); gen_json_schema!(cml_multi_era::alonzo::AlonzoProtocolParamUpdate); gen_json_schema!(cml_multi_era::alonzo::AlonzoRedeemer); @@ -41,7 +40,6 @@ pub fn export_schemas() { // babbage gen_json_schema!(cml_multi_era::babbage::BabbageAuxiliaryData); gen_json_schema!(cml_multi_era::babbage::BabbageBlock); - gen_json_schema!(cml_multi_era::babbage::BabbageCostModels); gen_json_schema!(cml_multi_era::babbage::BabbageFormatAuxData); gen_json_schema!(cml_multi_era::babbage::BabbageFormatTxOut); gen_json_schema!(cml_multi_era::babbage::BabbageProtocolParamUpdate); diff --git a/multi-era/wasm/src/alonzo/mod.rs b/multi-era/wasm/src/alonzo/mod.rs index 9a592625..3ccffc41 100644 --- a/multi-era/wasm/src/alonzo/mod.rs +++ b/multi-era/wasm/src/alonzo/mod.rs @@ -9,11 +9,11 @@ use crate::{ use cml_chain_wasm::assets::{Coin, Mint}; use cml_chain_wasm::auxdata::{Metadata, ShelleyFormatAuxData, ShelleyMaFormatAuxData}; use cml_chain_wasm::crypto::Nonce; -use cml_chain_wasm::plutus::{ExUnitPrices, ExUnits, PlutusData}; +use cml_chain_wasm::plutus::{CostModels, ExUnitPrices, ExUnits, PlutusData}; use cml_chain_wasm::RequiredSigners; use cml_chain_wasm::TransactionIndex; use cml_chain_wasm::{ - BootstrapWitnessList, IntList, NativeScriptList, PlutusDataList, PlutusV1ScriptList, + BootstrapWitnessList, NativeScriptList, PlutusDataList, PlutusV1ScriptList, TransactionInputList, VkeywitnessList, }; use cml_chain_wasm::{Epoch, NetworkId, Rational, UnitInterval, Withdrawals}; @@ -150,26 +150,7 @@ impl AlonzoBlock { } } -#[derive(Clone, Debug)] -#[wasm_bindgen] -pub struct AlonzoCostmdls(cml_multi_era::alonzo::AlonzoCostmdls); - -impl_wasm_cbor_json_api!(AlonzoCostmdls); - -impl_wasm_conversions!(cml_multi_era::alonzo::AlonzoCostmdls, AlonzoCostmdls); - -#[wasm_bindgen] -impl AlonzoCostmdls { - pub fn plutus_v1(&self) -> IntList { - self.0.plutus_v1.clone().into() - } - - pub fn new(plutus_v1: &IntList) -> Self { - Self(cml_multi_era::alonzo::AlonzoCostmdls::new( - plutus_v1.clone().into(), - )) - } -} +pub type AlonzoCostModels = CostModels; #[derive(Clone, Debug)] #[wasm_bindgen] @@ -419,13 +400,13 @@ impl AlonzoProtocolParamUpdate { pub fn set_cost_models_for_script_languages( &mut self, - cost_models_for_script_languages: &AlonzoCostmdls, + cost_models_for_script_languages: &AlonzoCostModels, ) { self.0.cost_models_for_script_languages = Some(cost_models_for_script_languages.clone().into()) } - pub fn cost_models_for_script_languages(&self) -> Option { + pub fn cost_models_for_script_languages(&self) -> Option { self.0 .cost_models_for_script_languages .clone() diff --git a/multi-era/wasm/src/babbage/mod.rs b/multi-era/wasm/src/babbage/mod.rs index d0aa2071..52d63deb 100644 --- a/multi-era/wasm/src/babbage/mod.rs +++ b/multi-era/wasm/src/babbage/mod.rs @@ -12,11 +12,11 @@ use cml_chain_wasm::assets::{Coin, Mint, Value}; use cml_chain_wasm::auxdata::{ShelleyFormatAuxData, ShelleyMaFormatAuxData}; use cml_chain_wasm::block::Header; use cml_chain_wasm::crypto::{AuxiliaryDataHash, GenesisHash, ScriptDataHash}; -use cml_chain_wasm::plutus::{ExUnitPrices, ExUnits, PlutusV1Script, PlutusV2Script}; +use cml_chain_wasm::plutus::{CostModels, ExUnitPrices, ExUnits, PlutusV1Script, PlutusV2Script}; use cml_chain_wasm::transaction::{AlonzoFormatTxOut, DatumOption, NativeScript}; use cml_chain_wasm::{auxdata::Metadata, Epoch, Rational, UnitInterval, Withdrawals}; use cml_chain_wasm::{ - BootstrapWitnessList, IntList, NativeScriptList, NetworkId, PlutusDataList, PlutusV1ScriptList, + BootstrapWitnessList, NativeScriptList, NetworkId, PlutusDataList, PlutusV1ScriptList, PlutusV2ScriptList, RequiredSigners, TransactionInputList, VkeywitnessList, }; use cml_core::ordered_hash_map::OrderedHashMap; @@ -153,36 +153,7 @@ impl BabbageBlock { } } -#[derive(Clone, Debug)] -#[wasm_bindgen] -pub struct BabbageCostModels(cml_multi_era::babbage::BabbageCostModels); - -impl_wasm_cbor_json_api!(BabbageCostModels); - -impl_wasm_conversions!(cml_multi_era::babbage::BabbageCostModels, BabbageCostModels); - -#[wasm_bindgen] -impl BabbageCostModels { - pub fn set_plutus_v1(&mut self, plutus_v1: &IntList) { - self.0.plutus_v1 = Some(plutus_v1.clone().into()) - } - - pub fn plutus_v1(&self) -> Option { - self.0.plutus_v1.clone().map(std::convert::Into::into) - } - - pub fn set_plutus_v2(&mut self, plutus_v2: &IntList) { - self.0.plutus_v2 = Some(plutus_v2.clone().into()) - } - - pub fn plutus_v2(&self) -> Option { - self.0.plutus_v2.clone().map(std::convert::Into::into) - } - - pub fn new() -> Self { - Self(cml_multi_era::babbage::BabbageCostModels::new()) - } -} +pub type BabbageCostModels = CostModels; #[derive(Clone, Debug)] #[wasm_bindgen] diff --git a/specs/multiera/alonzo/mod.cddl b/specs/multiera/alonzo/mod.cddl index 7162fe89..15ae7642 100644 --- a/specs/multiera/alonzo/mod.cddl +++ b/specs/multiera/alonzo/mod.cddl @@ -60,7 +60,7 @@ alonzo_protocol_param_update = { ? 14: protocol_version_struct, ; @name protocol_version ? 16: coin, ; @name min_pool_cost ? 17: coin, ; @name ada_per_utxo_byte - ? 18: alonzo_costmdls, ; @name cost_models_for_script_languages + ? 18: alonzo_cost_models, ; @name cost_models_for_script_languages ? 19: ex_unit_prices, ; @name execution_costs ? 20: ex_units, ; @name max_tx_ex_units ? 21: ex_units, ; @name max_block_ex_units @@ -82,9 +82,10 @@ alonzo_transaction_witness_set = { ; The values in the serialization are assumed to be ordered ; lexicographically by their correpsonding key value. ; The key values are listed in sorted_cost_model_keys.txt. -alonzo_costmdls = { - 0 : [ 166*166 int ], ; @name plutus_v1 -} +;alonzo_costmdls = { +; 0 : [ 166*166 int ], ; @name plutus_v1 +;} +alonzo_cost_models = cost_models alonzo_format_aux_data = #6.259({ ? 0 => metadata, ; @name metadata diff --git a/specs/multiera/babbage/mod.cddl b/specs/multiera/babbage/mod.cddl index fb389d8d..6bc9916f 100644 --- a/specs/multiera/babbage/mod.cddl +++ b/specs/multiera/babbage/mod.cddl @@ -75,10 +75,11 @@ babbage_update = [ babbage_proposed_protocol_parameter_updates = { * genesis_hash => babbage_protocol_param_update } -babbage_cost_models = { - ? 0 : [ 166*166 int ], ; @name plutus_v1 - ? 1 : [ 175*175 int ], ; @name plutus_v2 -} +;babbage_cost_models = { +; ? 0 : [ 166*166 int ], ; @name plutus_v1 +; ? 1 : [ 175*175 int ], ; @name plutus_v2 +;} +babbage_cost_models = cost_models babbage_protocol_param_update = { ? 0: uint, ; @name minfee_a diff --git a/specs/multiera/cml_chain/plutus.cddl b/specs/multiera/cml_chain/plutus.cddl index 34555f92..cf38d785 100644 --- a/specs/multiera/cml_chain/plutus.cddl +++ b/specs/multiera/cml_chain/plutus.cddl @@ -2,4 +2,5 @@ plutus_data = _CDDL_CODEGEN_EXTERN_TYPE_ ex_units = _CDDL_CODEGEN_EXTERN_TYPE_ ex_unit_prices = _CDDL_CODEGEN_EXTERN_TYPE_ plutus_v1_script = _CDDL_CODEGEN_EXTERN_TYPE_ -plutus_v2_script = _CDDL_CODEGEN_EXTERN_TYPE_ \ No newline at end of file +plutus_v2_script = _CDDL_CODEGEN_EXTERN_TYPE_ +cost_models = _CDDL_CODEGEN_EXTERN_TYPE_ \ No newline at end of file From 6f8be2ea32d9156c3c18ccb3daa05de11aa5ef65 Mon Sep 17 00:00:00 2001 From: rooooooooob Date: Thu, 4 Apr 2024 07:52:42 -0700 Subject: [PATCH 5/5] IntoIter for NonemptySet --- chain/rust/src/utils.rs | 55 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/chain/rust/src/utils.rs b/chain/rust/src/utils.rs index ae8e75e7..ab3b184c 100644 --- a/chain/rust/src/utils.rs +++ b/chain/rust/src/utils.rs @@ -7,6 +7,7 @@ use cml_core::{ use cml_crypto::{RawBytesEncoding, ScriptHash}; use derivative::Derivative; use std::io::{BufRead, Seek, Write}; +use std::iter::IntoIterator; use crate::{ crypto::hash::{hash_script, ScriptHashNamespace}, @@ -620,6 +621,33 @@ impl AsRef<[T]> for NonemptySet { } } +impl IntoIterator for NonemptySet { + type Item = T; + type IntoIter = as IntoIterator>::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.elems.into_iter() + } +} + +impl<'a, T> IntoIterator for &'a NonemptySet { + type Item = &'a T; + type IntoIter = std::slice::Iter<'a, T>; + + fn into_iter(self) -> Self::IntoIter { + self.elems.iter() + } +} + +impl<'a, T> IntoIterator for &'a mut NonemptySet { + type Item = &'a mut T; + type IntoIter = std::slice::IterMut<'a, T>; + + fn into_iter(self) -> Self::IntoIter { + self.elems.iter_mut() + } +} + impl std::ops::Deref for NonemptySet { type Target = Vec; @@ -763,6 +791,33 @@ impl AsRef<[T]> for NonemptySetRawBytes { } } +impl IntoIterator for NonemptySetRawBytes { + type Item = T; + type IntoIter = as IntoIterator>::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.elems.into_iter() + } +} + +impl<'a, T> IntoIterator for &'a NonemptySetRawBytes { + type Item = &'a T; + type IntoIter = std::slice::Iter<'a, T>; + + fn into_iter(self) -> Self::IntoIter { + self.elems.iter() + } +} + +impl<'a, T> IntoIterator for &'a mut NonemptySetRawBytes { + type Item = &'a mut T; + type IntoIter = std::slice::IterMut<'a, T>; + + fn into_iter(self) -> Self::IntoIter { + self.elems.iter_mut() + } +} + impl std::ops::Deref for NonemptySetRawBytes { type Target = Vec;