From be26949ab91c6c793feb761e0ad813b5564d2f7f Mon Sep 17 00:00:00 2001 From: rooooooooob Date: Wed, 1 May 2024 00:58:14 +0900 Subject: [PATCH 01/16] Babbage Mint handle duplicate format (#327) Babbage Mint handle duplicate format Fixes #326 --- multi-era/rust/src/babbage/cbor_encodings.rs | 6 +- multi-era/rust/src/babbage/mod.rs | 6 +- multi-era/rust/src/babbage/serialization.rs | 159 +------------- multi-era/rust/src/babbage/utils.rs | 216 ++++++++++++++++++- multi-era/rust/src/utils.rs | 12 +- multi-era/wasm/src/babbage/mod.rs | 11 +- multi-era/wasm/src/utils.rs | 2 +- specs/multiera/babbage/mod.cddl | 7 +- 8 files changed, 244 insertions(+), 175 deletions(-) diff --git a/multi-era/rust/src/babbage/cbor_encodings.rs b/multi-era/rust/src/babbage/cbor_encodings.rs index 54977a38..f2f9dfac 100644 --- a/multi-era/rust/src/babbage/cbor_encodings.rs +++ b/multi-era/rust/src/babbage/cbor_encodings.rs @@ -1,7 +1,7 @@ // This file was code-generated using an experimental CDDL to rust tool: // https://github.com/dcSpark/cddl-codegen -use cml_chain::{address::RewardAccount, assets::AssetName, PolicyId}; +use cml_chain::address::RewardAccount; use cml_core::serialization::{LenEncoding, StringEncoding}; use cml_crypto::GenesisHash; use std::collections::BTreeMap; @@ -117,10 +117,6 @@ pub struct BabbageTransactionBodyEncoding { pub auxiliary_data_hash_key_encoding: Option, pub validity_interval_start_encoding: Option, pub validity_interval_start_key_encoding: Option, - pub mint_encoding: LenEncoding, - pub mint_key_encodings: BTreeMap, - pub mint_value_encodings: - BTreeMap>)>, pub mint_key_encoding: Option, pub script_data_hash_encoding: StringEncoding, pub script_data_hash_key_encoding: Option, diff --git a/multi-era/rust/src/babbage/mod.rs b/multi-era/rust/src/babbage/mod.rs index 9e193d50..b8e0cab4 100644 --- a/multi-era/rust/src/babbage/mod.rs +++ b/multi-era/rust/src/babbage/mod.rs @@ -13,7 +13,7 @@ use cbor_encodings::{ BabbageTransactionEncoding, BabbageTransactionWitnessSetEncoding, BabbageUpdateEncoding, }; use cml_chain::address::Address; -use cml_chain::assets::{Coin, Mint, Value}; +use cml_chain::assets::{Coin, Value}; use cml_chain::auxdata::{Metadata, ShelleyFormatAuxData, ShelleyMaFormatAuxData}; use cml_chain::block::Header; use cml_chain::crypto::{ @@ -33,6 +33,8 @@ use cml_core::{Int, TransactionIndex}; use std::collections::BTreeMap; +use self::utils::BabbageMint; + #[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] pub enum BabbageAuxiliaryData { Shelley(ShelleyFormatAuxData), @@ -316,7 +318,7 @@ pub struct BabbageTransactionBody { pub update: Option, pub auxiliary_data_hash: Option, pub validity_interval_start: Option, - pub mint: Option, + pub mint: Option, pub script_data_hash: Option, pub collateral_inputs: Option>, pub required_signers: Option, diff --git a/multi-era/rust/src/babbage/serialization.rs b/multi-era/rust/src/babbage/serialization.rs index 51156c91..338cde8c 100644 --- a/multi-era/rust/src/babbage/serialization.rs +++ b/multi-era/rust/src/babbage/serialization.rs @@ -6,8 +6,6 @@ use super::*; use cbor_event::de::Deserializer; use cbor_event::se::Serializer; use cml_chain::address::RewardAccount; -use cml_chain::assets::AssetName; -use cml_chain::PolicyId; use cml_core::error::*; use cml_core::serialization::*; use cml_crypto::Ed25519KeyHash; @@ -3011,104 +3009,7 @@ impl Serialize for BabbageTransactionBody { force_canonical, ), )?; - serializer.write_map_sz( - self.encodings - .as_ref() - .map(|encs| encs.mint_encoding) - .unwrap_or_default() - .to_len_sz(field.len() as u64, force_canonical), - )?; - let mut key_order = field - .iter() - .map(|(k, v)| { - let mut buf = cbor_event::se::Serializer::new_vec(); - let mint_key_encoding = self - .encodings - .as_ref() - .and_then(|encs| encs.mint_key_encodings.get(k)) - .cloned() - .unwrap_or_default(); - buf.write_bytes_sz( - k.to_raw_bytes(), - mint_key_encoding.to_str_len_sz( - k.to_raw_bytes().len() as u64, - 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 (mint_value_encoding, mint_value_value_encodings) = self - .encodings - .as_ref() - .and_then(|encs| encs.mint_value_encodings.get(key)) - .cloned() - .unwrap_or_else(|| (LenEncoding::default(), BTreeMap::new())); - serializer.write_map_sz( - mint_value_encoding.to_len_sz(value.len() as u64, force_canonical), - )?; - let mut key_order = value - .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 mint_value_value_encoding = mint_value_value_encodings - .get(key) - .cloned() - .unwrap_or_default(); - if *value >= 0 { - serializer.write_unsigned_integer_sz( - *value as u64, - fit_sz( - *value as u64, - mint_value_value_encoding, - force_canonical, - ), - )?; - } else { - serializer.write_negative_integer_sz( - *value as i128, - fit_sz( - (*value + 1).unsigned_abs(), - mint_value_value_encoding, - force_canonical, - ), - )?; - } - } - mint_value_encoding.end(serializer, force_canonical)?; - } - self.encodings - .as_ref() - .map(|encs| encs.mint_encoding) - .unwrap_or_default() - .end(serializer, force_canonical)?; + field.serialize(serializer, force_canonical)?; } } 10 => { @@ -3340,9 +3241,6 @@ impl Deserialize for BabbageTransactionBody { let mut validity_interval_start_encoding = None; let mut validity_interval_start_key_encoding = None; let mut validity_interval_start = None; - let mut mint_encoding = LenEncoding::default(); - let mut mint_key_encodings = BTreeMap::new(); - let mut mint_value_encodings = BTreeMap::new(); let mut mint_key_encoding = None; let mut mint = None; let mut script_data_hash_encoding = StringEncoding::default(); @@ -3531,57 +3429,11 @@ impl Deserialize for BabbageTransactionBody { if mint.is_some() { return Err(DeserializeFailure::DuplicateKey(Key::Uint(9)).into()); } - let (tmp_mint, tmp_mint_encoding, tmp_mint_key_encodings, tmp_mint_value_encodings) = (|| -> Result<_, DeserializeError> { + let tmp_mint = (|| -> Result<_, DeserializeError> { read_len.read_elems(1)?; - let mut mint_table = OrderedHashMap::new(); - let mint_len = raw.map_sz()?; - let mint_encoding = mint_len.into(); - let mut mint_key_encodings = BTreeMap::new(); - let mut mint_value_encodings = BTreeMap::new(); - while match mint_len { cbor_event::LenSz::Len(n, _) => (mint_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 (mint_key, mint_key_encoding) = raw.bytes_sz().map_err(Into::::into).and_then(|(bytes, enc)| PolicyId::from_raw_bytes(&bytes).map(|bytes| (bytes, StringEncoding::from(enc))).map_err(|e| DeserializeFailure::InvalidStructure(Box::new(e)).into()))?; - let mut mint_value_table = OrderedHashMap::new(); - let mint_value_len = raw.map_sz()?; - let mint_value_encoding = mint_value_len.into(); - let mut mint_value_value_encodings = BTreeMap::new(); - while match mint_value_len { cbor_event::LenSz::Len(n, _) => (mint_value_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 mint_value_key = AssetName::deserialize(raw)?; - let (mint_value_value, mint_value_value_encoding) = match raw.cbor_type()? { - cbor_event::Type::UnsignedInteger => { - let (x, enc) = raw.unsigned_integer_sz()?; - (x as i64, Some(enc)) - }, - _ => { - let (x, enc) = raw.negative_integer_sz()?; - (x as i64, Some(enc)) - }, - }; - if mint_value_table.insert(mint_value_key.clone(), mint_value_value).is_some() { - return Err(DeserializeFailure::DuplicateKey(Key::Str(String::from("some complicated/unsupported type"))).into()); - } - mint_value_value_encodings.insert(mint_value_key, mint_value_value_encoding); - } - let (mint_value, mint_value_encoding, mint_value_value_encodings) = (mint_value_table, mint_value_encoding, mint_value_value_encodings); - if mint_table.insert(mint_key, mint_value).is_some() { - return Err(DeserializeFailure::DuplicateKey(Key::Str(String::from("some complicated/unsupported type"))).into()); - } - mint_key_encodings.insert(mint_key, mint_key_encoding); - mint_value_encodings.insert(mint_key, (mint_value_encoding, mint_value_value_encodings)); - } - Ok((mint_table, mint_encoding, mint_key_encodings, mint_value_encodings)) + BabbageMint::deserialize(raw) })().map_err(|e| e.annotate("mint"))?; mint = Some(tmp_mint); - mint_encoding = tmp_mint_encoding; - mint_key_encodings = tmp_mint_key_encodings; - mint_value_encodings = tmp_mint_value_encodings; mint_key_encoding = Some(key_enc); orig_deser_order.push(9); }, @@ -3745,7 +3597,7 @@ impl Deserialize for BabbageTransactionBody { update, auxiliary_data_hash, validity_interval_start, - mint: mint.map(Into::into), + mint, script_data_hash, collateral_inputs, required_signers, @@ -3775,9 +3627,6 @@ impl Deserialize for BabbageTransactionBody { validity_interval_start_key_encoding, validity_interval_start_encoding, mint_key_encoding, - mint_encoding, - mint_key_encodings, - mint_value_encodings, script_data_hash_key_encoding, script_data_hash_encoding, collateral_inputs_key_encoding, diff --git a/multi-era/rust/src/babbage/utils.rs b/multi-era/rust/src/babbage/utils.rs index b7cc38ff..14ce5a8a 100644 --- a/multi-era/rust/src/babbage/utils.rs +++ b/multi-era/rust/src/babbage/utils.rs @@ -1,15 +1,22 @@ +use std::io::{BufRead, Seek, Write}; + +use cbor_event::{de::Deserializer, se::Serializer}; use cml_chain::{ + assets::{AssetName, Mint, NonZeroInt64}, auxdata::{AuxiliaryData, ConwayFormatAuxData}, transaction::TransactionWitnessSet, - Script, + LenEncoding, PolicyId, Script, StringEncoding, }; use super::{ BabbageAuxiliaryData, BabbageScript, BabbageTransactionBody, BabbageTransactionWitnessSet, }; -use cml_core::serialization::Serialize; -use cml_crypto::{blake2b256, TransactionHash}; +use cml_core::{ + serialization::{fit_sz, Deserialize, Serialize}, + DeserializeError, DeserializeFailure, +}; +use cml_crypto::{blake2b256, RawBytesEncoding, TransactionHash}; impl BabbageTransactionBody { pub fn hash(&self) -> TransactionHash { @@ -81,3 +88,206 @@ impl From for TransactionWitnessSet { new_wits } } + +/// Babbage mints can have multiple maps resulting in different encodings so this works around it +#[derive(Clone, Debug, Default, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] +pub struct BabbageMint { + pub assets: Vec<(PolicyId, Vec<(AssetName, NonZeroInt64)>)>, + #[serde(skip)] + pub encodings: Option, +} + +impl BabbageMint { + pub fn to_mint(&self) -> Mint { + // the only on-chain values found here are well within i64's limits + let mut mint = Mint::new(); + for (policy_id, assets) in self.assets.iter() { + for (asset_name, coin) in assets { + let new_coin = *coin + mint.get(policy_id, asset_name).unwrap_or(0); + mint.set(*policy_id, asset_name.clone(), new_coin); + } + } + mint + } +} + +impl From for BabbageMint { + fn from(mint: Mint) -> Self { + let mut assets = Vec::new(); + for (policy_id, policy_assets) in mint.iter() { + assets.push(( + *policy_id, + policy_assets + .iter() + .map(|(asset_name, coin)| (asset_name.clone(), *coin)) + .collect(), + )); + } + Self { + assets, + encodings: None, + } + } +} + +#[derive(Clone, Debug, Default)] +pub struct BabbageMintEncoding { + pub len_encoding: LenEncoding, + pub assets_encodings: Vec<(StringEncoding, LenEncoding, Vec)>, +} + +impl Serialize for BabbageMint { + 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(self.assets.len() as u64, force_canonical), + )?; + // all keys same length so this is okay (will all use 1-byte byte len for canonical) + let mut key_order = self + .assets + .iter() + .enumerate() + .map(|(i, _)| i) + .collect::>(); + if force_canonical { + key_order.sort_by(|i, j| { + self.assets[*i] + .0 + .to_raw_bytes() + .cmp(self.assets[*j].0.to_raw_bytes()) + }); + } + for (i, (policy_id, assets)) in key_order.into_iter().zip(self.assets.iter()) { + let i_encs = self + .encodings + .as_ref() + .and_then(|encs| encs.assets_encodings.get(i)) + .cloned(); + let policy_id_encoding = i_encs + .as_ref() + .map(|(e, _, _)| e.clone()) + .unwrap_or_default() + .to_str_len_sz(policy_id.to_raw_bytes().len() as u64, force_canonical); + serializer.write_bytes_sz(policy_id.to_raw_bytes(), policy_id_encoding)?; + + serializer.write_map_sz( + i_encs + .as_ref() + .map(|(_, e, _)| *e) + .unwrap_or_default() + .to_len_sz(assets.len() as u64, force_canonical), + )?; + + let mut inner_key_order = self + .assets + .iter() + .enumerate() + .map(|(i, _)| i) + .collect::>(); + if force_canonical { + inner_key_order.sort_by(|i, j| assets[*i].0.get().cmp(assets[*j].0.get())); + } + + for (j, (asset_name, coin)) in inner_key_order.into_iter().zip(assets.iter()) { + let coin_encoding = i_encs + .as_ref() + .and_then(|(_, _, encs)| encs.get(j)) + .cloned(); + asset_name.serialize(serializer, force_canonical)?; + if *coin >= 0 { + serializer.write_unsigned_integer_sz( + *coin as u64, + fit_sz(*coin as u64, coin_encoding, force_canonical), + )?; + } else { + serializer.write_negative_integer_sz( + *coin as i128, + fit_sz((*coin + 1).unsigned_abs(), coin_encoding, force_canonical), + )?; + } + } + } + Ok(serializer) + } +} + +impl Deserialize for BabbageMint { + fn deserialize(raw: &mut Deserializer) -> Result { + let outer_len = raw.map_sz()?; + let mut assets = Vec::new(); + let mut encodings = Vec::new(); + while match outer_len { + cbor_event::LenSz::Len(n, _) => (assets.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 (policy_id, policy_id_encoding) = raw + .bytes_sz() + .map_err(Into::::into) + .and_then(|(bytes, enc)| { + PolicyId::from_raw_bytes(&bytes) + .map(|bytes| (bytes, StringEncoding::from(enc))) + .map_err(|e| DeserializeFailure::InvalidStructure(Box::new(e)).into()) + })?; + let inner_len = raw.map_sz()?; + let mut policy_assets = Vec::new(); + let mut inner_encodings = Vec::new(); + while match inner_len { + cbor_event::LenSz::Len(n, _) => (policy_assets.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 asset_name = AssetName::deserialize(raw)?; + let (coin, coin_encoding) = match raw.cbor_type()? { + cbor_event::Type::UnsignedInteger => { + let (x, enc) = raw.unsigned_integer_sz()?; + (x as i64, enc) + } + _ => { + let (x, enc) = raw.negative_integer_sz()?; + (x as i64, enc) + } + }; + policy_assets.push((asset_name, coin)); + inner_encodings.push(coin_encoding); + } + assets.push((policy_id, policy_assets)); + encodings.push((policy_id_encoding, inner_len.into(), inner_encodings)); + } + Ok(Self { + assets, + encodings: Some(BabbageMintEncoding { + len_encoding: outer_len.into(), + assets_encodings: encodings, + }), + }) + } +} + +#[cfg(test)] +mod tests { + use cml_chain::{Deserialize, Serialize}; + + use crate::babbage::BabbageBlock; + + #[test] + fn babbage_mint_duplicate() { + // See: https://github.com/dcSpark/cardano-multiplatform-lib/issues/326 + let bytes = hex::decode("85828a1a0018ba521a02ae24895820413ca2266bac4f438bb66be88bc805ca5d1f4d2a8c3bdeb583c42df7474e14b958200339649fecc4224156494435a46d783d72c8b47fe54e411e6b8fdadda3a7585058203997f8cde4ebadc8993fb0e73c88a7058ec089a6311cc1f930388b9114fc3c99825840180f8b92442933ddb1d6e7a51c2e446fec230c72ff2924df1211cd698212534b488c2b1af6d12109fd2880aa43bbdd92cd0c12f08e50826abb80de13d44b075d5850da506b142cc8d33ae6d2aecfdb327622e9721e49417679f1f05f5229a0924577b80bb0b457fd99fbabd117e758bb49edf17a9a0a52b3a40b923e0faa369e687125787b70361442be3d7b91cebb53da0c19093c58200e3d4834a4dd7a556937b6c1b36a9d766cfff56b9ca28431fe4c7271008fa473845820d35f6405c9d73869b4a9ee42ac578af5d32faa1d79b4013bc620b97a61a8b7da0419014358405c6face300da458ca9453363480a961522daa402e852ba808f2ca9360ffe81e16bc4a8619e0872aeb2b6108b0809c6a0c7b3333162a0c33ffcbde8db6dad440f8208005901c0db84609ce526a38235eea695e2ed42aa2dafc739b23d395edc8e65c33553f987386182dc2a02d8a098e0e688ed9361c036704d16781489e6adca39989b436a035f17db62b490762330be236cf92e5a1bf20a9b671d062b4b38f2581498cd75fbfc4f24e21239468edbea69397a03ce91c1682c08975fc92a4873370722d6fe50876ffb1bf5c2b541cee23ac6e716788630c00d94335589dfd6161efaaa67e56dbe773acbe8c8c8e63f3ad4490342670aac252efed07b51fd082d80c78c4acf07bcc60377ae9ec07b705131841c99e5eb297355b9196d9b63aa1737dd9fdbf7a9282251a6f2e8e157aa141640fd347e18194788e13496abe4b7b2339bdad4ce5c12c25effc103e9ea2b91adf81ef9b6efd23dfe1a86f9b8d594ec536c277876365cd43984ac6ebb89df693036fc01b70cec8f3d64ca49577dc924ab08c71ef3869916e8e934b81b95c427a9d04733707887064620f05869a556d043658324654684d6e8a3a439b5e50a9cac1684ca857fe73cc12fb9ab5ac91a4b12345152344cb5edf6d226a581bb29fea7947ee7b5f1639b2a3bd5032ba2a15308c10d3d3fd75516f7b3f3ed4e24a1c9985c934984cbf867f1c3787accd5034ffec5b26f3abf83aa008282582055ba023aaccefe6888628a8513805ddad2a65f8278ca5c3397a80da6c7890b66018258208d9181649b3671475686851153eadbb8c0b90103d0c10c2ac6a9b1973d4abf49000d818258207aa9cd4999a21c3951de9e330e0ce1fba5943d79ef5bfd90628c2d41e982becd001281825820c59678b6892ba0fbeeaaec22d4cbde17026ff614ed47cea02c47752e5853ebc8010182a200581d600a11b0c7e25dc5d9c63171bdf39d9741b901dc903e12b4e162348e07011a018d55b0a2005839007ea04a6b4942fc0db5f81a86847d2545c3810717ca95f546901cd08cfffa1d082a6132fd1789d48fd348fae9e88d5521c20fb8e1045b0048011a001e848010a200581d600a11b0c7e25dc5d9c63171bdf39d9741b901dc903e12b4e162348e07011a0054cc87111a000a6361021a0006eceb031a02b574ff081a02ae246b0b58204e15e4b830f4f5f029a4779f51735b5dd8462c23a85319166ada33c56ea2ab5aa600818258201d3ae3ffec2d9228c7d5bb9870f5cff032d0f31c83c22c4bd7c5e3ffead4470c0001818258390079467c69a9ac66280174d09d62575ba955748b21dec3b483a9469a65cc339a35f9e0fe039cf510c761d4dd29040c48e9657fdac7e9c01d94821b0000000253e00ccca1581cf923673e7bc027eba929a9086b7b04a126a18ef524b41db6fb014a26a24a414c414c415f54455354024c4741474147415f544553543202021a0002c20e09a2581cf923673e7bc027eba929a9086b7b04a126a18ef524b41db6fb014a26a14a414c414c415f5445535401581cf923673e7bc027eba929a9086b7b04a126a18ef524b41db6fb014a26a14c4741474147415f5445535432010b5820e4af6dc836dada8e84d698b26252f8586f4261ddc6090fc22eac4a059bfe6b040d8382582078869651d619a1832d90b7c843f6d674707fc4c1c2a24e205145656aba7533f600825820c111c9d57fb9ee06f54f0f8bc035f9762db24eada643509afbdbbae98b3ae8f800825820ceff84520384d2f4cdf2017bab6b86a7b46b81ef8e40c3d4f08b699a8a27bade00ab00838258201388fc6611c1aea7ddb4071ce03ee041c7ae2a3b809f730c99ea5d737cb9836b03825820a4d5f23d70af6e494237da29ebd3d0c13f8fde2c3c3b169980a4b63417753a7700825820fd12b648ce816a3aee8f0f0235303958b57bccf3929c88b1f99d6605f1c648ca020183a300581d70f5542fa9d9c61b4dbccd71654cc5a72a9fddc9d563f503682e772ec901821a001e8480a1581c5e4a2431a465a00dc5d8181aaff63959bb235d97013e7acb50b55bc4a1484e6f64654665656401028201d818583cd87a9fd8799f581c4ad1571e7df63d4d6c49240c8372eb639f57c0ef669338c0d752f29bd8799fd8799f1a0025ebd11b0000018bf6a73cbdffffffff82581d604ad1571e7df63d4d6c49240c8372eb639f57c0ef669338c0d752f29b1a0089544082581d604ad1571e7df63d4d6c49240c8372eb639f57c0ef669338c0d752f29b1a005ed7c4021a00044e78031a02ae24e3081a02ae246b0b58205f658fa6994cd9157a48835760a4421da6fec59400f666b343e114283f454eea0d81825820a4d5f23d70af6e494237da29ebd3d0c13f8fde2c3c3b169980a4b63417753a77020e81581c4ad1571e7df63d4d6c49240c8372eb639f57c0ef669338c0d752f29b1082581d604ad1571e7df63d4d6c49240c8372eb639f57c0ef669338c0d752f29b1a004df682111a00370c3f12818258204b61acedca6426ec989ef78a85ed97a8b4ffd47d9c40d4155e453d7e6b25ae580083a30081825820669ed15b1bc5e97ec45af8951e9cbcbd33a3b5878943704d054a1a3ec46be28258407861d1a46731116eb7b140c1a9efbd19e2727f472d4e3503ff96d3125fcc3e11982320322e99fafb61d7016443ac815d909e573bd721efbbeba0cd7a78a11f020481d8799fd8799f40ffd8799fa1d8799fd8799fd87980d8799fd8799f581c7ea04a6b4942fc0db5f81a86847d2545c3810717ca95f546901cd08cffd8799fd8799fd8799f581cfffa1d082a6132fd1789d48fd348fae9e88d5521c20fb8e1045b0048ffffffffffd8799f4040ffff1a001e8480a0a000ffd87c9f9fd8799fd87a9fd8799f5545766572797468696e6720697320616c7269676874d8799fd87980d8799fd8799f581c7ea04a6b4942fc0db5f81a86847d2545c3810717ca95f546901cd08cffd8799fd8799fd8799f581cfffa1d082a6132fd1789d48fd348fae9e88d5521c20fb8e1045b0048ffffffffffff9fd8799f0000ffffffd87980ffd8799fd87a9fd8799f4e5265706f72742070726f626c656dd8799fd87980d8799fd8799f581c7ea04a6b4942fc0db5f81a86847d2545c3810717ca95f546901cd08cffd8799fd8799fd8799f581cfffa1d082a6132fd1789d48fd348fae9e88d5521c20fb8e1045b0048ffffffffffff9fd8799f0101ffffffd87980ffd8799fd87a9fd8799f5243686f696365206265747765656e20312d33d8799fd87980d8799fd8799f581c7ea04a6b4942fc0db5f81a86847d2545c3810717ca95f546901cd08cffd8799fd8799fd8799f581cfffa1d082a6132fd1789d48fd348fae9e88d5521c20fb8e1045b0048ffffffffffff9fd8799f0103ffffffd87980ffd8799fd87a9fd8799f5243686f696365206265747765656e20312d34d8799fd87980d8799fd8799f581c7ea04a6b4942fc0db5f81a86847d2545c3810717ca95f546901cd08cffd8799fd8799fd8799f581cfffa1d082a6132fd1789d48fd348fae9e88d5521c20fb8e1045b0048ffffffffffff9fd8799f0104ffffffd87980ffff1b0000018bf65a9496d87980ffff058184000080821a002f80a61a339742d1a30081825820489ef28ea97f719ee7768645fc74b811c271e5d7ef06c2310854db30158e945d584023dcbaf18dff2ed33a436cbc9036c70deacb573d810df73c41c72c0ebc6183f3d5b44d24d9689db9d3254f3a6720f71175bc1ac32607758276c2cf64ca7dbb0403815251010000322253330034a229309b2b2b9a0105828401000182190bb91a000c79f88401000282190bb91a000c79f8a200818258204b5d869e21e1d1d6f84fdc1e5811eda837ca9fdf2068c69255cd43f62e2711f25840888846f463da49f6f4fbbe4fbfc056901521852d203f1b8bf1a54af2c4efd1cf292ef983a8dbfd3b9266194025028ea59ce34453ddc6a4e0861ddc5db6ee01050581840001d87980821a0012c2f41a15f4bff0a080").unwrap(); + let babbage_block = BabbageBlock::from_cbor_bytes(&bytes).unwrap(); + assert_eq!(bytes, babbage_block.to_cbor_bytes()); + } +} diff --git a/multi-era/rust/src/utils.rs b/multi-era/rust/src/utils.rs index 17a750d8..142437e3 100644 --- a/multi-era/rust/src/utils.rs +++ b/multi-era/rust/src/utils.rs @@ -1,3 +1,5 @@ +use std::borrow::Cow; + use crate::allegra::{ AllegraCertificate, MIRAction, MoveInstantaneousReward, MoveInstantaneousRewardsCert, }; @@ -646,15 +648,15 @@ impl MultiEraTransactionBody { } } - pub fn mint(&self) -> Option<&Mint> { + pub fn mint(&self) -> Option> { match self { Self::Byron(_tx) => None, Self::Shelley(_tx) => None, Self::Allegra(_tx) => None, - Self::Mary(tx) => tx.mint.as_ref(), - Self::Alonzo(tx) => tx.mint.as_ref(), - Self::Babbage(tx) => tx.mint.as_ref(), - Self::Conway(tx) => tx.mint.as_ref(), + Self::Mary(tx) => tx.mint.as_ref().map(Cow::Borrowed), + Self::Alonzo(tx) => tx.mint.as_ref().map(Cow::Borrowed), + Self::Babbage(tx) => tx.mint.as_ref().map(|m| Cow::Owned(m.to_mint())), + Self::Conway(tx) => tx.mint.as_ref().map(Cow::Borrowed), } } diff --git a/multi-era/wasm/src/babbage/mod.rs b/multi-era/wasm/src/babbage/mod.rs index 924c835e..607fd8f3 100644 --- a/multi-era/wasm/src/babbage/mod.rs +++ b/multi-era/wasm/src/babbage/mod.rs @@ -731,11 +731,18 @@ impl BabbageTransactionBody { } pub fn set_mint(&mut self, mint: &Mint) { - self.0.mint = Some(mint.clone().into()) + self.0.mint = Some(cml_multi_era::babbage::utils::BabbageMint::from(Into::< + cml_chain::assets::Mint, + >::into( + mint.clone(), + ))) } pub fn mint(&self) -> Option { - self.0.mint.clone().map(std::convert::Into::into) + self.0 + .mint + .as_ref() + .map(|mint| mint.to_mint().to_owned().into()) } pub fn set_script_data_hash(&mut self, script_data_hash: &ScriptDataHash) { diff --git a/multi-era/wasm/src/utils.rs b/multi-era/wasm/src/utils.rs index 7cc6841b..e117e8c2 100644 --- a/multi-era/wasm/src/utils.rs +++ b/multi-era/wasm/src/utils.rs @@ -610,7 +610,7 @@ impl MultiEraTransactionBody { } pub fn mint(&self) -> Option { - self.0.mint().map(|m| m.clone().into()) + self.0.mint().map(|m| m.into_owned().into()) } pub fn script_data_hash(&self) -> Option { diff --git a/specs/multiera/babbage/mod.cddl b/specs/multiera/babbage/mod.cddl index d5cc8140..29044835 100644 --- a/specs/multiera/babbage/mod.cddl +++ b/specs/multiera/babbage/mod.cddl @@ -57,7 +57,7 @@ babbage_transaction_body = { ? 6 : babbage_update, ; @name update ? 7 : auxiliary_data_hash, ; @name auxiliary_data_hash ? 8 : uint, ; @name validity_interval_start - ? 9 : mint, ; @name mint + ? 9 : babbage_mint, ; @name mint ? 11 : script_data_hash, ; @name script_data_hash ? 13 : [* transaction_input], ; @name collateral_inputs ? 14 : required_signers, ; @name required_signers @@ -115,4 +115,7 @@ babbage_format_aux_data = #6.259({ babbage_auxiliary_data = shelley_format_aux_data ; @name shelley / shelley_ma_format_aux_data ; @name shelley_m_a - / babbage_format_aux_data ; @name babbage \ No newline at end of file + / babbage_format_aux_data ; @name babbage + +; babbage mint has duplicate keys so it needs its own special hand-written struct +babbage_mint = _CDDL_CODEGEN_EXTERN_TYPE_ \ No newline at end of file From e34780fd39397750dd973fd0f856ce044a4240c5 Mon Sep 17 00:00:00 2001 From: rooooooooob Date: Thu, 2 May 2024 03:56:32 +0900 Subject: [PATCH 02/16] New Conway.cddl updates (#324) * 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 * conway multi-era update + various fixes * resolve merge conflict * use conway costmodels for all eras (babbage costmdls found in alonzo on sancho testnet) * IntoIter for NonemptySet --- Cargo.toml | 4 +- chain/rust/src/block/serialization.rs | 14 +- .../rust/src/builders/certificate_builder.rs | 6 +- chain/rust/src/builders/input_builder.rs | 5 +- chain/rust/src/builders/mint_builder.rs | 2 +- chain/rust/src/builders/redeemer_builder.rs | 31 +- chain/rust/src/builders/tx_builder.rs | 87 +- chain/rust/src/builders/withdrawal_builder.rs | 2 +- chain/rust/src/builders/witness_builder.rs | 59 +- chain/rust/src/cbor_encodings.rs | 1 + chain/rust/src/certs/cbor_encodings.rs | 2 - chain/rust/src/certs/mod.rs | 24 +- chain/rust/src/certs/serialization.rs | 115 +-- chain/rust/src/crypto/hash.rs | 68 +- chain/rust/src/crypto/serialization.rs | 136 +-- chain/rust/src/deposit.rs | 8 +- chain/rust/src/fees.rs | 2 +- chain/rust/src/governance/cbor_encodings.rs | 24 +- chain/rust/src/governance/mod.rs | 113 ++- chain/rust/src/governance/serialization.rs | 572 ++++++------ chain/rust/src/lib.rs | 52 +- chain/rust/src/plutus/cbor_encodings.rs | 14 +- chain/rust/src/plutus/mod.rs | 131 ++- chain/rust/src/plutus/serialization.rs | 525 ++++++++++- chain/rust/src/plutus/utils.rs | 77 +- chain/rust/src/serialization.rs | 95 +- chain/rust/src/transaction/cbor_encodings.rs | 15 - chain/rust/src/transaction/mod.rs | 47 +- chain/rust/src/transaction/serialization.rs | 601 ++---------- chain/rust/src/transaction/utils.rs | 14 +- chain/rust/src/utils.rs | 357 +++++++- chain/wasm/json-gen/src/lib.rs | 59 +- .../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/certs/mod.rs | 18 +- chain/wasm/src/crypto/hash.rs | 15 +- chain/wasm/src/governance/mod.rs | 153 ++-- 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 | 67 ++ 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 | 15 +- multi-era/rust/src/alonzo/mod.rs | 78 +- multi-era/rust/src/alonzo/serialization.rs | 356 ++++---- multi-era/rust/src/alonzo/utils.rs | 37 +- multi-era/rust/src/babbage/cbor_encodings.rs | 10 - multi-era/rust/src/babbage/mod.rs | 43 +- multi-era/rust/src/babbage/serialization.rs | 237 +---- 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 | 129 +-- multi-era/wasm/json-gen/src/lib.rs | 35 +- multi-era/wasm/src/allegra/mod.rs | 26 +- multi-era/wasm/src/alonzo/mod.rs | 76 +- multi-era/wasm/src/babbage/mod.rs | 48 +- 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 | 8 +- specs/conway/crypto.cddl | 2 +- specs/conway/governance.cddl | 24 +- specs/conway/lib.cddl | 15 +- specs/conway/plutus.cddl | 20 +- specs/conway/transaction.cddl | 60 +- specs/multiera/allegra/mod.cddl | 18 +- specs/multiera/alonzo/mod.cddl | 25 +- specs/multiera/babbage/mod.cddl | 11 +- specs/multiera/cml_chain/certs.cddl | 24 +- specs/multiera/cml_chain/mod.cddl | 1 + specs/multiera/cml_chain/plutus.cddl | 4 +- specs/multiera/shelley/mod.cddl | 46 +- 83 files changed, 4524 insertions(+), 2890 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/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..f20701e1 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}; @@ -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 930fdbd5..5687f097 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..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, transaction::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 d743fdad..d83e15ad 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,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") + } } } @@ -211,10 +217,7 @@ impl RedeemerSetBuilder { } } - pub fn build( - &self, - default_to_dummy_exunits: bool, - ) -> Result, RedeemerBuilderError> { + 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( @@ -242,12 +245,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 +283,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(), @@ -334,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(); @@ -371,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 b561e246..7a6dd4bd 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::{CostModels, ExUnits, Language}; +use crate::plutus::{PlutusData, Redeemers}; 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,11 @@ 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,31 +1227,38 @@ 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, mint: self.mint.clone(), script_data_hash, - collateral_inputs: self - .collateral - .as_ref() - .map(|collateral| collateral.iter().map(|c| c.input.clone()).collect()), + collateral_inputs: self.collateral.as_ref().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()), + 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, @@ -1384,7 +1398,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) } @@ -4075,14 +4089,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(); @@ -5119,7 +5138,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(); } @@ -5267,7 +5286,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(); } @@ -5445,7 +5464,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(); } @@ -5703,7 +5722,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/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..3baebe67 100644 --- a/chain/rust/src/builders/witness_builder.rs +++ b/chain/rust/src/builders/witness_builder.rs @@ -8,9 +8,9 @@ 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, + plutus::{LegacyRedeemer, PlutusData, PlutusScript, PlutusV1Script, PlutusV2Script, Redeemers}, + transaction::TransactionWitnessSet, + NativeScript, RequiredSigners, Script, }; use cml_crypto::{ DatumHash, Ed25519KeyHash, Ed25519Signature, PublicKey, RawBytesEncoding, ScriptHash, @@ -24,7 +24,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 +160,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 +241,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 +329,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 +349,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 +412,34 @@ 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 @@ -629,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); @@ -653,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/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/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 a278ba16..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( @@ -344,13 +348,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), }, )); } @@ -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 f42a7f10..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); @@ -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), }, )); } @@ -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() @@ -1456,52 +1432,20 @@ 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"))?; 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, }), }) @@ -1763,8 +1705,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 +1820,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 +1938,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 { @@ -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, @@ -2835,8 +2794,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 +3145,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 +3262,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 +3376,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, @@ -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 bd5f462c..d07f6e03 100644 --- a/chain/rust/src/crypto/hash.rs +++ b/chain/rust/src/crypto/hash.rs @@ -6,10 +6,11 @@ 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 +31,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 +47,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 +58,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 +81,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/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 c0ce313a..3e40b394 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,9 @@ 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..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, @@ -61,6 +47,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 +62,15 @@ 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)] +pub struct UpdateCommitteeEncoding { + pub len_encoding: LenEncoding, + pub tag_encoding: Option, + pub credentials_encoding: LenEncoding, + pub credentials_value_encodings: BTreeMap>, } #[derive(Clone, Debug, Default)] diff --git a/chain/rust/src/governance/mod.rs b/chain/rust/src/governance/mod.rs index f0d4b551..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)] @@ -99,10 +78,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,20 +96,27 @@ 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 { 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( @@ -191,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, @@ -253,6 +217,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 +226,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 +267,46 @@ 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, + } + } +} + +#[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, } } diff --git a/chain/rust/src/governance/serialization.rs b/chain/rust/src/governance/serialization.rs index 0ceec6fa..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) @@ -352,7 +221,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 +276,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, @@ -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, @@ -1124,7 +846,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 +875,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 +898,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 +946,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 +1071,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 +1136,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 +1159,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 +1229,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, }), }) })() @@ -1474,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 bb2381c0..e3009374 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, CommitteeColdCredential}; +use cml_crypto::Ed25519KeyHash; +use crypto::{BootstrapWitness, Vkeywitness}; +use utils::NonemptySetRawBytes; +pub use utils::{NetworkId, NonemptySet, Set}; //pub mod legacy_address; @@ -53,9 +57,11 @@ 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 { @@ -105,16 +111,39 @@ impl DRepVotingThresholds { pub type DeltaCoin = Int; +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, } @@ -125,12 +154,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, } } @@ -140,8 +171,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, @@ -164,11 +195,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, } @@ -205,6 +237,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, } } @@ -313,6 +346,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/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 e95df256..79978f1e 100644 --- a/chain/rust/src/plutus/mod.rs +++ b/chain/rust/src/plutus/mod.rs @@ -5,15 +5,18 @@ 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 +108,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, derivative::Derivative)] #[derivative( Eq, @@ -172,10 +197,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, } @@ -240,10 +270,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, } @@ -308,10 +343,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, } @@ -375,23 +415,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, } } @@ -416,4 +461,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 3cf405d8..86a43d06 100644 --- a/chain/rust/src/plutus/utils.rs +++ b/chain/rust/src/plutus/utils.rs @@ -1,4 +1,4 @@ -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 crate::json::plutus_datums::{ @@ -7,9 +7,11 @@ use crate::json::plutus_datums::{ }; 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}; @@ -479,7 +481,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)?; @@ -604,6 +606,77 @@ 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..7590dce4 100644 --- a/chain/rust/src/transaction/mod.rs +++ b/chain/rust/src/transaction/mod.rs @@ -5,18 +5,21 @@ 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,8 +173,6 @@ impl NativeScript { } } -pub type RequiredSigners = Vec; - #[derive( Clone, Debug, derivative::Derivative, serde::Deserialize, serde::Serialize, schemars::JsonSchema, )] @@ -325,24 +326,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 +351,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 +425,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..ab3b184c 100644 --- a/chain/rust/src/utils.rs +++ b/chain/rust/src/utils.rs @@ -1,12 +1,13 @@ -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}; +use std::iter::IntoIterator; use crate::{ crypto::hash::{hash_script, ScriptHashNamespace}, @@ -569,6 +570,356 @@ 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 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; + + 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 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; + + 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/json-gen/src/lib.rs b/chain/wasm/json-gen/src/lib.rs index 46dcab63..8062b4c6 100644 --- a/chain/wasm/json-gen/src/lib.rs +++ b/chain/wasm/json-gen/src/lib.rs @@ -67,7 +67,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); @@ -76,18 +79,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); @@ -104,12 +119,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); @@ -118,16 +163,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/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/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/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..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); @@ -110,11 +80,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 +103,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), ), ) } @@ -145,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(), )) } @@ -183,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, } @@ -225,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, } @@ -276,7 +254,7 @@ pub enum GovActionKind { HardForkInitiationAction, TreasuryWithdrawalsAction, NoConfidence, - NewCommittee, + UpdateCommittee, NewConstitution, InfoAction, } @@ -310,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); @@ -413,13 +356,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 +431,55 @@ 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), + )) + } +} + +#[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(), )) } } diff --git a/chain/wasm/src/lib.rs b/chain/wasm/src/lib.rs index f77a451d..8c3f7e96 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,29 @@ 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_list!( + cml_chain::crypto::Ed25519KeyHash, + Ed25519KeyHash, + Ed25519KeyHashList +); -impl_wasm_conversions!(Vec, IntList); +pub type SetCommitteeColdCredential = CommitteeColdCredentialList; -#[wasm_bindgen] -impl IntList { - pub fn new() -> Self { - Self(Vec::new()) - } +pub type SetEd25519KeyHash = 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 +361,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 +537,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 +593,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 +635,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 +849,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 +892,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 +935,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 +1019,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 +1076,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 33502902..e2ca0103 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_api, 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..ce9c6751 100644 --- a/chain/wasm/src/utils.rs +++ b/chain/wasm/src/utils.rs @@ -85,3 +85,70 @@ impl NetworkId { self.0.network } } + +// 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 { + 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 +); + +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..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, @@ -80,6 +72,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..cceb8c31 100644 --- a/multi-era/rust/src/alonzo/mod.rs +++ b/multi-era/rust/src/alonzo/mod.rs @@ -5,27 +5,27 @@ 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, Redeemer}; -use cml_chain::transaction::{AlonzoFormatTxOut, NativeScript, RequiredSigners, TransactionInput}; +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, 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), @@ -77,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 { @@ -141,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, @@ -190,6 +176,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 +294,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..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 = @@ -1997,6 +1847,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 +3098,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 +3598,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/cbor_encodings.rs b/multi-era/rust/src/babbage/cbor_encodings.rs index f2f9dfac..65605137 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 b8e0cab4..9a8e0f17 100644 --- a/multi-era/rust/src/babbage/mod.rs +++ b/multi-era/rust/src/babbage/mod.rs @@ -6,11 +6,12 @@ pub mod serialization; pub mod utils; 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, Value}; @@ -20,16 +21,14 @@ use cml_chain::crypto::{ AuxiliaryDataHash, BootstrapWitness, GenesisHash, ScriptDataHash, Vkeywitness, }; use cml_chain::plutus::{ - ExUnitPrices, ExUnits, PlutusData, PlutusV1Script, PlutusV2Script, Redeemer, + CostModels, ExUnitPrices, ExUnits, PlutusData, PlutusV1Script, PlutusV2Script, }; -use cml_chain::transaction::{ - AlonzoFormatTxOut, DatumOption, NativeScript, RequiredSigners, TransactionInput, -}; -use cml_chain::{Epoch, NetworkId, Rational, UnitInterval, Withdrawals}; +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; @@ -86,29 +85,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 { @@ -382,7 +359,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 338cde8c..b4f611bb 100644 --- a/multi-era/rust/src/babbage/serialization.rs +++ b/multi-era/rust/src/babbage/serialization.rs @@ -296,239 +296,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, @@ -3600,7 +3367,7 @@ impl Deserialize for BabbageTransactionBody { mint, script_data_hash, collateral_inputs, - required_signers, + required_signers: required_signers.map(Into::into), network_id, collateral_return, total_collateral, @@ -4199,7 +3966,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 14ce5a8a..bf9eee89 100644 --- a/multi-era/rust/src/babbage/utils.rs +++ b/multi-era/rust/src/babbage/utils.rs @@ -4,6 +4,7 @@ use cbor_event::{de::Deserializer, se::Serializer}; use cml_chain::{ assets::{AssetName, Mint, NonZeroInt64}, auxdata::{AuxiliaryData, ConwayFormatAuxData}, + plutus::Redeemers, transaction::TransactionWitnessSet, LenEncoding, PolicyId, Script, StringEncoding, }; @@ -78,13 +79,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 142437e3..679d2e64 100644 --- a/multi-era/rust/src/utils.rs +++ b/multi-era/rust/src/utils.rs @@ -3,8 +3,8 @@ use std::borrow::Cow; 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; @@ -32,21 +32,20 @@ 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, RequiredSigners, TransactionInput, TransactionOutput, TransactionWitnessSet, + 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}; 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 { @@ -672,27 +671,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()), } } @@ -732,15 +731,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()), } } @@ -756,7 +755,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, @@ -764,7 +763,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()), } } @@ -835,27 +834,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(), + ), ), - ), - )), + )) + } } } } @@ -866,7 +863,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) => { @@ -1326,46 +1325,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 @@ -1428,4 +1387,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 65ce603f..c84629a4 100644 --- a/multi-era/wasm/json-gen/src/lib.rs +++ b/multi-era/wasm/json-gen/src/lib.rs @@ -18,22 +18,43 @@ 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::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 +120,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 +135,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..3ccffc41 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::{CostModels, 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, + BootstrapWitnessList, NativeScriptList, PlutusDataList, PlutusV1ScriptList, + 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)] @@ -149,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] @@ -418,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() @@ -487,6 +469,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 +733,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 607fd8f3..479818c5 100644 --- a/multi-era/wasm/src/babbage/mod.rs +++ b/multi-era/wasm/src/babbage/mod.rs @@ -3,20 +3,21 @@ 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}; 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::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, - PlutusV2ScriptList, RedeemerList, TransactionInputList, VkeywitnessList, + BootstrapWitnessList, NativeScriptList, NetworkId, PlutusDataList, PlutusV1ScriptList, + PlutusV2ScriptList, RequiredSigners, TransactionInputList, VkeywitnessList, }; use cml_core::ordered_hash_map::OrderedHashMap; use cml_core::TransactionIndex; @@ -152,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] @@ -950,11 +922,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 bd000d47..e3e7434d 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 e117e8c2..1e695394 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 20f2b9ec..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,14 +97,14 @@ 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 ) 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 @@ -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 2da0c7c3..16353f60 100644 --- a/specs/conway/governance.cddl +++ b/specs/conway/governance.cddl @@ -18,13 +18,18 @@ gov_action = [ hard_fork_initiation_action // treasury_withdrawals_action // no_confidence // - new_committee // + update_committee // new_constitution // ; @name info_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 = ( @@ -42,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 = ( @@ -55,11 +62,6 @@ new_constitution = ( constitution ) -committee = [ - credentials: { $committee_cold_credential => epoch }, - unit_interval -] - constitution = [ anchor, script_hash / null, 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..f43a42a5 100644 --- a/specs/multiera/allegra/mod.cddl +++ b/specs/multiera/allegra/mod.cddl @@ -22,15 +22,15 @@ 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 = [ + stake_registration // + stake_deregistration // + stake_delegation // + shelley_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..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 @@ -75,16 +75,17 @@ 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. ; 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 @@ -95,4 +96,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 29044835..99d887d7 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 } @@ -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/certs.cddl b/specs/multiera/cml_chain/certs.cddl index e37c4aad..2976be9a 100644 --- a/specs/multiera/cml_chain/certs.cddl +++ b/specs/multiera/cml_chain/certs.cddl @@ -1,10 +1,14 @@ 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_ ; 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) @@ -13,20 +17,8 @@ stake_delegation = ( 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/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/cml_chain/plutus.cddl b/specs/multiera/cml_chain/plutus.cddl index 7327c624..cf38d785 100644 --- a/specs/multiera/cml_chain/plutus.cddl +++ b/specs/multiera/cml_chain/plutus.cddl @@ -1,6 +1,6 @@ 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_ -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 diff --git a/specs/multiera/shelley/mod.cddl b/specs/multiera/shelley/mod.cddl index 42cbfab0..8eb0fb51 100644 --- a/specs/multiera/shelley/mod.cddl +++ b/specs/multiera/shelley/mod.cddl @@ -37,18 +37,48 @@ 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 // + shelley_single_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 + stake_registration // + stake_deregistration // + stake_delegation // + 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 b0283a8bd5bc809ded76d9b68abfc1cf183d9cd2 Mon Sep 17 00:00:00 2001 From: Sebastien Guillemot Date: Thu, 2 May 2024 07:53:45 +0900 Subject: [PATCH 03/16] 5.3.0 --- build-and-test.sh | 1 + chain/rust/Cargo.toml | 6 +++--- chain/wasm/Cargo.toml | 12 ++++++------ chain/wasm/json-gen/Cargo.toml | 2 +- cip25/rust/Cargo.toml | 8 ++++---- cip25/wasm/Cargo.toml | 12 ++++++------ cip25/wasm/json-gen/Cargo.toml | 4 ++-- cip36/rust/Cargo.toml | 8 ++++---- cip36/wasm/Cargo.toml | 16 ++++++++-------- cip36/wasm/json-gen/Cargo.toml | 2 +- cml/wasm/Cargo.toml | 12 ++++++------ cml/wasm/package.json | 2 +- core/rust/Cargo.toml | 2 +- core/wasm/Cargo.toml | 4 ++-- crypto/rust/Cargo.toml | 4 ++-- crypto/wasm/Cargo.toml | 4 ++-- multi-era/rust/Cargo.toml | 8 ++++---- multi-era/wasm/Cargo.toml | 20 ++++++++++---------- multi-era/wasm/json-gen/Cargo.toml | 2 +- multi-era/wasm/package.json | 2 +- package.json | 2 +- test.sh | 1 + tools/metadata-cddl-checker/Cargo.toml | 2 +- 23 files changed, 69 insertions(+), 67 deletions(-) mode change 100644 => 100755 build-and-test.sh mode change 100644 => 100755 test.sh diff --git a/build-and-test.sh b/build-and-test.sh old mode 100644 new mode 100755 index ecd5f31a..f7e6a856 --- a/build-and-test.sh +++ b/build-and-test.sh @@ -1 +1,2 @@ +set -eu . test.sh && npm run rust:build-nodejs \ No newline at end of file diff --git a/chain/rust/Cargo.toml b/chain/rust/Cargo.toml index dbd6a128..03d77514 100644 --- a/chain/rust/Cargo.toml +++ b/chain/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cml-chain" -version = "5.2.0" +version = "5.3.0" edition = "2018" authors = ["dcSpark"] license = "MIT" @@ -14,8 +14,8 @@ keywords = ["cardano"] crate-type = ["cdylib", "rlib"] [dependencies] -cml-core = { "path" = "../../core/rust", version = "5.2.0" } -cml-crypto = { "path" = "../../crypto/rust", version = "5.2.0" } +cml-core = { "path" = "../../core/rust", version = "5.3.0" } +cml-crypto = { "path" = "../../crypto/rust", version = "5.3.0" } cbor_event = "2.2.0" linked-hash-map = "0.5.3" derivative = "2.2.0" diff --git a/chain/wasm/Cargo.toml b/chain/wasm/Cargo.toml index 2a71767c..8db093c8 100644 --- a/chain/wasm/Cargo.toml +++ b/chain/wasm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cml-chain-wasm" -version = "5.2.0" +version = "5.3.0" edition = "2018" authors = ["dcSpark"] license = "MIT" @@ -14,12 +14,12 @@ keywords = ["cardano"] crate-type = ["cdylib", "rlib"] [dependencies] -cml-chain = { path = "../rust", version = "5.2.0" } -cml-core = { path = "../../core/rust", version = "5.2.0" } -cml-core-wasm = { path = "../../core/wasm", version = "5.2.0" } +cml-chain = { path = "../rust", version = "5.3.0" } +cml-core = { path = "../../core/rust", version = "5.3.0" } +cml-core-wasm = { path = "../../core/wasm", version = "5.3.0" } # TODO: remove this dependency if possible to reduce confusion? maybe pub export necessary things in crypto-wasm? -cml-crypto = { path = "../../crypto/rust", version = "5.2.0" } -cml-crypto-wasm = { path = "../../crypto/wasm", version = "5.2.0" } +cml-crypto = { path = "../../crypto/rust", version = "5.3.0" } +cml-crypto-wasm = { path = "../../crypto/wasm", version = "5.3.0" } cbor_event = "2.4.0" hex = "0.4.0" wasm-bindgen = { version = "=0.2.83", features = ["serde-serialize"] } diff --git a/chain/wasm/json-gen/Cargo.toml b/chain/wasm/json-gen/Cargo.toml index 13a4e01d..b4452354 100644 --- a/chain/wasm/json-gen/Cargo.toml +++ b/chain/wasm/json-gen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cml-chain-json-schema-gen" -version = "5.2.0" +version = "5.3.0" edition = "2018" keywords = ["cardano"] diff --git a/cip25/rust/Cargo.toml b/cip25/rust/Cargo.toml index a7c938d5..9221f3d0 100644 --- a/cip25/rust/Cargo.toml +++ b/cip25/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cml-cip25" -version = "5.2.0" +version = "5.3.0" edition = "2018" authors = ["dcSpark"] license = "MIT" @@ -14,9 +14,9 @@ keywords = ["cardano", "cip25"] crate-type = ["cdylib", "rlib"] [dependencies] -cml-chain = { "path" = "../../chain/rust", version = "5.2.0" } -cml-core = { "path" = "../../core/rust", version = "5.2.0" } -cml-crypto = { "path" = "../../crypto/rust", version = "5.2.0" } +cml-chain = { "path" = "../../chain/rust", version = "5.3.0" } +cml-core = { "path" = "../../core/rust", version = "5.3.0" } +cml-crypto = { "path" = "../../crypto/rust", version = "5.3.0" } cbor_event = "2.2.0" hex = "0.4.0" schemars = "0.8.8" diff --git a/cip25/wasm/Cargo.toml b/cip25/wasm/Cargo.toml index d9143241..44a7d099 100644 --- a/cip25/wasm/Cargo.toml +++ b/cip25/wasm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cml-cip25-wasm" -version = "5.2.0" +version = "5.3.0" edition = "2018" authors = ["dcSpark"] license = "MIT" @@ -15,11 +15,11 @@ crate-type = ["cdylib", "rlib"] [dependencies] cbor_event = "2.2.0" -cml-chain = { path = "../../chain/rust", version = "5.2.0" } -cml-chain-wasm = { path = "../../chain/wasm", version = "5.2.0" } -cml-core = { path = "../../core/rust", version = "5.2.0" } -cml-core-wasm = { path = "../../core/wasm", version = "5.2.0" } -cml-cip25 = { path = "../rust", version = "5.2.0" } +cml-chain = { path = "../../chain/rust", version = "5.3.0" } +cml-chain-wasm = { path = "../../chain/wasm", version = "5.3.0" } +cml-core = { path = "../../core/rust", version = "5.3.0" } +cml-core-wasm = { path = "../../core/wasm", version = "5.3.0" } +cml-cip25 = { path = "../rust", version = "5.3.0" } hex = "0.4.0" linked-hash-map = "0.5.3" serde_json = "1.0.57" diff --git a/cip25/wasm/json-gen/Cargo.toml b/cip25/wasm/json-gen/Cargo.toml index 45c8c98b..a877a183 100644 --- a/cip25/wasm/json-gen/Cargo.toml +++ b/cip25/wasm/json-gen/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "cml-cip25-json-schema-gen" -version = "5.2.0" +version = "5.3.0" edition = "2018" keywords = ["cardano"] [dependencies] serde_json = "1.0.57" schemars = "0.8.8" -cml-cip25 = { path = "../../rust", version = "5.2.0" } +cml-cip25 = { path = "../../rust", version = "5.3.0" } diff --git a/cip36/rust/Cargo.toml b/cip36/rust/Cargo.toml index 967f8b89..c8675b88 100644 --- a/cip36/rust/Cargo.toml +++ b/cip36/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cml-cip36" -version = "5.2.0" +version = "5.3.0" edition = "2018" authors = ["dcSpark"] license = "MIT" @@ -14,9 +14,9 @@ keywords = ["cardano", "cip36"] crate-type = ["cdylib", "rlib"] [dependencies] -cml-core = { "path" = "../../core/rust", version = "5.2.0" } -cml-crypto = { "path" = "../../crypto/rust", version = "5.2.0" } -cml-chain = { "path" = "../../chain/rust", version = "5.2.0" } +cml-core = { "path" = "../../core/rust", version = "5.3.0" } +cml-crypto = { "path" = "../../crypto/rust", version = "5.3.0" } +cml-chain = { "path" = "../../chain/rust", version = "5.3.0" } cbor_event = "2.2.0" linked-hash-map = "0.5.3" derivative = "2.2.0" diff --git a/cip36/wasm/Cargo.toml b/cip36/wasm/Cargo.toml index 6afac58f..89dd4ee8 100644 --- a/cip36/wasm/Cargo.toml +++ b/cip36/wasm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cml-cip36-wasm" -version = "5.2.0" +version = "5.3.0" edition = "2018" authors = ["dcSpark"] license = "MIT" @@ -14,13 +14,13 @@ keywords = ["cardano", "cip36"] crate-type = ["cdylib", "rlib"] [dependencies] -cml-cip36 = { path = "../rust", version = "5.2.0" } -cml-crypto = { path = "../../crypto/rust", version = "5.2.0" } -cml-crypto-wasm = { path = "../../crypto/wasm", version = "5.2.0" } -cml-chain = { path = "../../chain/rust", version = "5.2.0" } -cml-chain-wasm = { path = "../../chain/wasm", version = "5.2.0" } -cml-core = { path = "../../core/rust", version = "5.2.0" } -cml-core-wasm = { path = "../../core/wasm", version = "5.2.0" } +cml-cip36 = { path = "../rust", version = "5.3.0" } +cml-crypto = { path = "../../crypto/rust", version = "5.3.0" } +cml-crypto-wasm = { path = "../../crypto/wasm", version = "5.3.0" } +cml-chain = { path = "../../chain/rust", version = "5.3.0" } +cml-chain-wasm = { path = "../../chain/wasm", version = "5.3.0" } +cml-core = { path = "../../core/rust", version = "5.3.0" } +cml-core-wasm = { path = "../../core/wasm", version = "5.3.0" } cbor_event = "2.2.0" hex = "0.4.0" wasm-bindgen = { version = "=0.2.83", features = ["serde-serialize"] } diff --git a/cip36/wasm/json-gen/Cargo.toml b/cip36/wasm/json-gen/Cargo.toml index 97fa78a5..785a78b7 100644 --- a/cip36/wasm/json-gen/Cargo.toml +++ b/cip36/wasm/json-gen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cml-cip36-json-schema-gen" -version = "5.2.0" +version = "5.3.0" edition = "2018" diff --git a/cml/wasm/Cargo.toml b/cml/wasm/Cargo.toml index 2d4c8015..9dd60600 100644 --- a/cml/wasm/Cargo.toml +++ b/cml/wasm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cardano-multiplatform-lib" -version = "5.2.0" +version = "5.3.0" edition = "2018" keywords = ["cardano"] license = "MIT" @@ -13,11 +13,11 @@ readme = "../../README.md" crate-type = ["cdylib", "rlib"] [dependencies] -cml-chain-wasm = { path = "../../chain/wasm", version = "5.2.0" } -cml-cip25-wasm = { path = "../../cip25/wasm", version = "5.2.0" } -cml-cip36-wasm = { path = "../../cip36/wasm", version = "5.2.0" } -cml-crypto-wasm = { path = "../../crypto/wasm", version = "5.2.0" } -cml-core-wasm = { path = "../../core/wasm", version = "5.2.0" } +cml-chain-wasm = { path = "../../chain/wasm", version = "5.3.0" } +cml-cip25-wasm = { path = "../../cip25/wasm", version = "5.3.0" } +cml-cip36-wasm = { path = "../../cip36/wasm", version = "5.3.0" } +cml-crypto-wasm = { path = "../../crypto/wasm", version = "5.3.0" } +cml-core-wasm = { path = "../../core/wasm", version = "5.3.0" } cbor_event = "2.4.0" hex = "0.4.0" linked-hash-map = "0.5.3" diff --git a/cml/wasm/package.json b/cml/wasm/package.json index 997a384f..0eae7a58 100644 --- a/cml/wasm/package.json +++ b/cml/wasm/package.json @@ -1,6 +1,6 @@ { "name": "cardano-multiplatform-lib", - "version": "5.2.0", + "version": "5.3.0", "description": "Cardano Multiplatform SDK for core Cardano blockchain functionality", "keywords": [ "cardano" diff --git a/core/rust/Cargo.toml b/core/rust/Cargo.toml index e8e922b1..9a66ba4f 100644 --- a/core/rust/Cargo.toml +++ b/core/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cml-core" -version = "5.2.0" +version = "5.3.0" edition = "2018" authors = ["dcSpark"] license = "MIT" diff --git a/core/wasm/Cargo.toml b/core/wasm/Cargo.toml index cf524fa8..0e47c184 100644 --- a/core/wasm/Cargo.toml +++ b/core/wasm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cml-core-wasm" -version = "5.2.0" +version = "5.3.0" edition = "2018" keywords = ["cardano"] license = "MIT" @@ -13,7 +13,7 @@ readme = "../../README.md" crate-type = ["cdylib", "rlib"] [dependencies] -cml-core = { path = "../rust", version = "5.2.0" } +cml-core = { path = "../rust", version = "5.3.0" } cbor_event = "2.2.0" hex = "0.4.0" wasm-bindgen = { version = "=0.2.83", features = ["serde-serialize"] } diff --git a/crypto/rust/Cargo.toml b/crypto/rust/Cargo.toml index 2b36a818..af58d4aa 100644 --- a/crypto/rust/Cargo.toml +++ b/crypto/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cml-crypto" -version = "5.2.0" +version = "5.3.0" edition = "2018" authors = ["dcSpark"] license = "MIT" @@ -14,7 +14,7 @@ keywords = ["cardano"] crate-type = ["cdylib", "rlib"] [dependencies] -cml-core = { "path" = "../../core/rust", version = "5.2.0" } +cml-core = { "path" = "../../core/rust", version = "5.3.0" } base64 = "0.21.5" cbor_event = "2.2.0" cryptoxide = "0.4.2" diff --git a/crypto/wasm/Cargo.toml b/crypto/wasm/Cargo.toml index f7c67774..9d1c0147 100644 --- a/crypto/wasm/Cargo.toml +++ b/crypto/wasm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cml-crypto-wasm" -version = "5.2.0" +version = "5.3.0" edition = "2018" authors = ["dcSpark"] license = "MIT" @@ -14,7 +14,7 @@ keywords = ["cardano"] crate-type = ["cdylib", "rlib"] [dependencies] -cml-crypto = { path = "../rust", version = "5.2.0" } +cml-crypto = { path = "../rust", version = "5.3.0" } cbor_event = "2.2.0" wasm-bindgen = { version = "=0.2.83", features = ["serde-serialize"] } linked-hash-map = "0.5.3" diff --git a/multi-era/rust/Cargo.toml b/multi-era/rust/Cargo.toml index 42a60466..f7ade7a6 100644 --- a/multi-era/rust/Cargo.toml +++ b/multi-era/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cml-multi-era" -version = "5.2.0" +version = "5.3.0" edition = "2018" authors = ["dcSpark"] license = "MIT" @@ -14,9 +14,9 @@ keywords = ["cardano"] crate-type = ["cdylib", "rlib"] [dependencies] -cml-core = { path = "../../core/rust", version = "5.2.0" } -cml-crypto = { path = "../../crypto/rust", version = "5.2.0" } -cml-chain = { path = "../../chain/rust", version = "5.2.0" } +cml-core = { path = "../../core/rust", version = "5.3.0" } +cml-crypto = { path = "../../crypto/rust", version = "5.3.0" } +cml-chain = { path = "../../chain/rust", version = "5.3.0" } cbor_event = "2.4.0" linked-hash-map = "0.5.3" derivative = "2.2.0" diff --git a/multi-era/wasm/Cargo.toml b/multi-era/wasm/Cargo.toml index f79fa07b..5945b87c 100644 --- a/multi-era/wasm/Cargo.toml +++ b/multi-era/wasm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cml-multi-era-wasm" -version = "5.2.0" +version = "5.3.0" edition = "2018" authors = ["dcSpark"] license = "MIT" @@ -14,13 +14,13 @@ keywords = ["cardano"] crate-type = ["cdylib", "rlib"] [dependencies] -cml-chain = { path = "../../chain/rust", version = "5.2.0" } -cml-chain-wasm = { path = "../../chain/wasm", version = "5.2.0" } -cml-crypto = { path = "../../crypto/rust", version = "5.2.0" } -cml-crypto-wasm = { path = "../../crypto/wasm", version = "5.2.0" } -cml-core = { path = "../../core/rust", version = "5.2.0" } -cml-core-wasm = { path = "../../core/wasm", version = "5.2.0" } -cml-multi-era = { path = "../rust", version = "5.2.0" } +cml-chain = { path = "../../chain/rust", version = "5.3.0" } +cml-chain-wasm = { path = "../../chain/wasm", version = "5.3.0" } +cml-crypto = { path = "../../crypto/rust", version = "5.3.0" } +cml-crypto-wasm = { path = "../../crypto/wasm", version = "5.3.0" } +cml-core = { path = "../../core/rust", version = "5.3.0" } +cml-core-wasm = { path = "../../core/wasm", version = "5.3.0" } +cml-multi-era = { path = "../rust", version = "5.3.0" } cbor_event = "2.4.0" hex = "0.4.0" linked-hash-map = "0.5.3" @@ -28,5 +28,5 @@ serde_json = "1.0.57" serde-wasm-bindgen = "0.4.5" wasm-bindgen = { version = "0.2", features=["serde-serialize"] } # not actual multi-era dependencies but we re-export these for the wasm builds -cml-cip25-wasm = { path = "../../cip25/wasm", version = "5.2.0" } -cml-cip36-wasm = { path = "../../cip36/wasm", version = "5.2.0" } \ No newline at end of file +cml-cip25-wasm = { path = "../../cip25/wasm", version = "5.3.0" } +cml-cip36-wasm = { path = "../../cip36/wasm", version = "5.3.0" } \ No newline at end of file diff --git a/multi-era/wasm/json-gen/Cargo.toml b/multi-era/wasm/json-gen/Cargo.toml index 49b86eac..c376078a 100644 --- a/multi-era/wasm/json-gen/Cargo.toml +++ b/multi-era/wasm/json-gen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cml-multi-era-json-schema-gen" -version = "5.2.0" +version = "5.3.0" edition = "2018" diff --git a/multi-era/wasm/package.json b/multi-era/wasm/package.json index 70cb0447..818a9beb 100644 --- a/multi-era/wasm/package.json +++ b/multi-era/wasm/package.json @@ -1,6 +1,6 @@ { "name": "cardano-multiplatform-multiera-lib", - "version": "5.2.0", + "version": "5.3.0", "description": "Multiplatform SDK for on-chain Cardano blochain types of all eras (Byron, Shelley, etc)", "keywords": [ "cardano" diff --git a/package.json b/package.json index 45efef13..ccf8a3b4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cardano-multiplatform-lib", - "version": "5.2.0", + "version": "5.3.0", "description": "Cardano Multiplatform SDK for core Cardano blockchain functionality", "keywords": [ "cardano" diff --git a/test.sh b/test.sh old mode 100644 new mode 100755 index 58a154b9..ee869532 --- a/test.sh +++ b/test.sh @@ -1 +1,2 @@ +set -eu nvm i && npm i && npm run rust:test \ No newline at end of file diff --git a/tools/metadata-cddl-checker/Cargo.toml b/tools/metadata-cddl-checker/Cargo.toml index 9d90eac7..2dd9a34e 100644 --- a/tools/metadata-cddl-checker/Cargo.toml +++ b/tools/metadata-cddl-checker/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "metadata-cddl-checker" -version = "5.2.0" +version = "5.3.0" edition = "2018" [dependencies] From 2bae32f01fc54bd5d287956d8459a68405f229aa Mon Sep 17 00:00:00 2001 From: rooooooooob Date: Mon, 6 May 2024 12:42:39 +0900 Subject: [PATCH 04/16] Fix for Babbage Mint for preprod (#329) Fixes an issue introduced in #327 Fixes: Improper support for indefinite encoded mints + typo causing problem with multiple mints inside one policy id (not present in the test case) --- multi-era/rust/src/babbage/utils.rs | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/multi-era/rust/src/babbage/utils.rs b/multi-era/rust/src/babbage/utils.rs index bf9eee89..9d060ecd 100644 --- a/multi-era/rust/src/babbage/utils.rs +++ b/multi-era/rust/src/babbage/utils.rs @@ -188,8 +188,7 @@ impl Serialize for BabbageMint { .to_len_sz(assets.len() as u64, force_canonical), )?; - let mut inner_key_order = self - .assets + let mut inner_key_order = assets .iter() .enumerate() .map(|(i, _)| i) @@ -216,7 +215,17 @@ impl Serialize for BabbageMint { )?; } } + i_encs + .as_ref() + .map(|(_, e, _)| *e) + .unwrap_or_default() + .end(serializer, force_canonical)?; } + self.encodings + .as_ref() + .map(|encs| encs.len_encoding) + .unwrap_or_default() + .end(serializer, force_canonical)?; Ok(serializer) } } @@ -293,4 +302,11 @@ mod tests { let babbage_block = BabbageBlock::from_cbor_bytes(&bytes).unwrap(); assert_eq!(bytes, babbage_block.to_cbor_bytes()); } + + #[test] + fn babbage_tx_hash_mismatch_duplicate_mint() { + let bytes = hex::decode("85828a1a0002b9921a00a322425820581063827053ccc7d81dbac8141d9c2c509516bafd5599d9c15daa9b2eb15ce65820f270c16659735ec4b65d15d1cbef937e50e608585ac3b71a4cd117fdb761624e5820ebb507d7e0b0399ffced1a35297203134f8a2a85b616c3591c452cbefa61b88a825840199fd347919a2befa7995d869744808df54d5f9608a1de89d25e0b2837386861ea57394e0c13d858ae9e1b3bc5ffb952399fb258d2d670748ff0533a9547f03858503721a2acd37fc0e328f3749b7b4b797d37deb9c778d33b3058ee2fb631531f137d3320449dfedb74259269a1c5da254efe3afaf4626e86c470684353b7a9b7381d978a5a7d66abca9adad56b79bd6d02190bf458203648f02334769911ab0d9422311675c125cd9bd3871746b17c88ef7b0c3afe13845820e947674a4b27747fbdb5512190d79643e013cbb2ffc9346b49bd65e093cadd7301183c5840926b676216ae9db730e2d2ae9fe0308152dc5468acb3d573d7ddd0fedda8ed760f0058110a41c3db2b526e2365062f6f78f8397b5d76d5dacf07d3304d3bf7058207005901c0c3f9dcb6e03112878798fc303808f7c3ee12b6351674514d0ef0343ce9ed5011712431fc59b1c86a637e40c13191b29bdb29ece2ca14d44d21a5556528af640fb0b308ded9d94eca36532dea9fcb00f7f64792216090422ce127021da8a6fd3577d545c8cd4b7e7dcf219bbcda733e709ca8acf7f45990076820cfa8777776708422e34683c07b4f0e25689d990cc40626a44b7f6eddbcda58423416461648efb319189d242ee580efc4c89ec46de3a715ccd57c68d5e59b54759cee2d5be64b862eee54f19f06fc0e5388a7e1abbf7716cb7ef3bf8d4fad009a77de8233ba187cc0a4712c28b90b80885649eda709180911d23b71e1d494b80f4d6bb1aa5d6511dfdc7de150eed972facf595801eba808adb730ec5111bd36175a29c08e8643e2da2fcbe41a97049abd814bfbb12c895f1e55f6c9b8c81b3e3e1e276fc74ae1d1b5b7e8c26d763835c10880b6996d64aeb443e64c13c8cc1518ba9befce9660334d061489404e282ef00967f097cc64f9ef802193cecb31c04b1779a2605a5132ee4c168c60f152bda320a4c82c348559cb3600321930f5c9cbcbcddf64582ada49fc04c5a4f4ccdf58a47d4a025270e45dedf923f87baee972b0e3549b75d082a600838258207fc36e487fc641ad98963b7ec45d94ef6729acb15d993c67b564c1f845eb837e008258207fc36e487fc641ad98963b7ec45d94ef6729acb15d993c67b564c1f845eb837e028258207fc36e487fc641ad98963b7ec45d94ef6729acb15d993c67b564c1f845eb837e030184825839005ecffdc54a493a3f11b149c922ddb6c0f2622efc5e1651ccc4d4bfaf0298b4b8579f55b767c32f8137067d7f8a83879802317b10ce954e911a140cacd882583900377c5ff6ad6ab6814e108a9f7c298d467ab071d94fe02a8d0ce1f1812cf859673b01e57891f55a55ca600c7428f47e9b94a94ccbbfdb8c771a00839b68825839005ecffdc54a493a3f11b149c922ddb6c0f2622efc5e1651ccc4d4bfaf0298b4b8579f55b767c32f8137067d7f8a83879802317b10ce954e91821a001a4ec4a1581c99027c7af372116f0716ee02008739ec51224bcfdd54398ec16217efa5484d6565726b61743401484d6565726b61743601494d6565726b6174313501494d6565726b6174323201494d6565726b6174333501825839005ecffdc54a493a3f11b149c922ddb6c0f2622efc5e1651ccc4d4bfaf0298b4b8579f55b767c32f8137067d7f8a83879802317b10ce954e91821b000000023eeaf5a2a1581c99027c7af372116f0716ee02008739ec51224bcfdd54398ec16217efa3484d6565726b61743201494d6565726b6174313801494d6565726b6174333201021a00044271031a00a32588075820e17f14914a4c11738d1a391ac645b8a8c077acf8ef3b06e7be52d3007058002f09a1581c99027c7af372116f0716ee02008739ec51224bcfdd54398ec16217efa5484d6565726b61743401484d6565726b61743601494d6565726b6174313501494d6565726b6174323201494d6565726b6174333501a40081825820ad0b622e745b250833b2d9b5ba097f1eda98af919df7f79bf06db0200530df16000182a200581d609e5614893238cf85e284c61ec56d5efd9f9cdc4863ba7e1bf00c2c7d011b0067d5c8983f93cca2005839009e5614893238cf85e284c61ec56d5efd9f9cdc4863ba7e1bf00c2c7dd12d53af25a20a84981b873d3117cc21324ba035366a466c330ff790011b000000e8d4a51000021a00029309048182008200581cd12d53af25a20a84981b873d3117cc21324ba035366a466c330ff79082a2008282582033846103a1478022104669a9653dcca4c8b93ceb1ddc1045027df1a871ddabca584059e5b2c5032d044d522f7b15d5bbc957ac6d28f2f26b13ff294366a31da52dde6a3ce42b3c57719b5f98ff9e57c776e8bd3285f02ecfc69d4d1eaf2f98d27a0d825820ddc1c2e930eda0c6df23fd811b9ff40059b88338582611b966a3bd156a49cfff58401cd7f2e92a465f21981b74b253ceed7a7d48147f49de21dd9cfb99caf320a0e84a14e0b18e21fd83909c68a41d558eb3ab396dcd7a3bdc87cc4efcb2759d920001818201828200581c2b354356304a1ccb513a8bc12b278e3c4f421c692c89cf7855a2739e82051a056557faa1008182582069a14b724409e0ceef671c76ec4f8bce7509b5919bb971b3855bf92ca56532225840c180d20a83b5879609fa35c2a423b4bd08642add58e5782102e79e40f833fcb96f5546c3bd776da14717aa41360bb748bffc868a9303c7672814e9a503ccbd07a10082a11902d1a178383939303237633761663337323131366630373136656530323030383733396563353132323462636664643534333938656331363231376566a5684d6565726b617434ad63486174764469616d6f6e642048616e647320536e61706261636b64457965736b4e6f726d616c20426c7565644d61736b644e6f6e6564536b696e66446573657274646e616d656a4d6565726b6174202334654d6f757468724d6f7573746163686520416e6420506970656566696c657381a3637372637835697066733a2f2f516d614c6d566176334577427567657968425a357363387533746b61434a6851647575436b534c35654559647a35646e616d656a4d6565726b6174202334696d656469615479706569696d6167652f706e6765696d6167657835697066733a2f2f516d614c6d566176334577427567657968425a357363387533746b61434a6851647575436b534c35654559647a3566546174746f6f644e6f6e6568436c6f7468696e676a41726d79205368697274696d656469615479706569696d6167652f706e676a4261636b67726f756e646659656c6c6f776d456172204163636573736f7279644e6f6e65684d6565726b617436ad63486174644e6f6e6564457965736b4e6f726d616c20426c7565644d61736b644e6f6e6564536b696e6753747269706564646e616d656a4d6565726b6174202336654d6f757468644772696e6566696c657381a3637372637835697066733a2f2f516d59736d53564d75766245636d473545387873385466445065546f374b5634715346704d5932504a6974487852646e616d656a4d6565726b6174202336696d656469615479706569696d6167652f706e6765696d6167657835697066733a2f2f516d59736d53564d75766245636d473545387873385466445065546f374b5634715346704d5932504a697448785266546174746f6f66447261676f6e68436c6f7468696e676c426c61636b2054757865646f696d656469615479706569696d6167652f706e676a4261636b67726f756e646450696e6b6d456172204163636573736f7279644e6f6e65694d6565726b61743135ad6348617468526963652048617464457965736b4e6f726d616c20426c7565644d61736b644e6f6e6564536b696e6443616d6f646e616d656b4d6565726b617420233135654d6f75746865536e616b656566696c657381a3637372637835697066733a2f2f516d59364c5065766d714d4d3373716334374364637341353241784b4e626f3247527274354a66584b39484d4c33646e616d656b4d6565726b617420233135696d656469615479706569696d6167652f706e6765696d6167657835697066733a2f2f516d59364c5065766d714d4d3373716334374364637341353241784b4e626f3247527274354a66584b39484d4c3366546174746f6f644e6f6e6568436c6f7468696e676e486177616969616e205368697274696d656469615479706569696d6167652f706e676a4261636b67726f756e64694772617665796172646d456172204163636573736f7279644e6f6e65694d6565726b61743232ad63486174644e6f6e6564457965736c4e6f726d616c2042726f776e644d61736b644e6f6e6564536b696e6753747269706564646e616d656b4d6565726b617420233232654d6f7574686853747261696768746566696c657381a3637372637835697066733a2f2f516d665334707a7653466a76687a537a38356b44326547435453525252514e704d736e4b63436f66636f77325a74646e616d656b4d6565726b617420233232696d656469615479706569696d6167652f706e6765696d6167657835697066733a2f2f516d665334707a7653466a76687a537a38356b44326547435453525252514e704d736e4b63436f66636f77325a7466546174746f6f644e6f6e6568436c6f7468696e6766507269657374696d656469615479706569696d6167652f706e676a4261636b67726f756e64644c696d656d456172204163636573736f7279644e6f6e65694d6565726b61743335ad63486174764469616d6f6e642048616e647320536e61706261636b64457965736c4e6f726d616c2042726f776e644d61736b644e6f6e6564536b696e6a476f6c6420416c706861646e616d656b4d6565726b617420233335654d6f757468644772696e6566696c657381a3637372637835697066733a2f2f516d534766323873446f62765178727443453673364b323152776f5143756f7969574c544774436e7a76374e4337646e616d656b4d6565726b617420233335696d656469615479706569696d6167652f706e6765696d6167657835697066733a2f2f516d534766323873446f62765178727443453673364b323152776f5143756f7969574c544774436e7a76374e433766546174746f6f644e6f6e6568436c6f7468696e67694e6176792053756974696d656469615479706569696d6167652f706e676a4261636b67726f756e64694772617665796172646d456172204163636573736f72796d476f6c642045617272696e67738080").unwrap(); + let babbage_block = BabbageBlock::from_cbor_bytes(&bytes).unwrap(); + assert_eq!(bytes, babbage_block.to_cbor_bytes()); + } } From 255500b3c683618849fb38107896170ea09c95dc Mon Sep 17 00:00:00 2001 From: Sebastien Guillemot Date: Mon, 6 May 2024 12:58:44 +0900 Subject: [PATCH 05/16] 5.3.1 --- chain/rust/Cargo.toml | 6 +++--- chain/wasm/Cargo.toml | 12 ++++++------ chain/wasm/json-gen/Cargo.toml | 2 +- cip25/rust/Cargo.toml | 8 ++++---- cip25/wasm/Cargo.toml | 12 ++++++------ cip25/wasm/json-gen/Cargo.toml | 4 ++-- cip36/rust/Cargo.toml | 8 ++++---- cip36/wasm/Cargo.toml | 16 ++++++++-------- cip36/wasm/json-gen/Cargo.toml | 2 +- cml/wasm/Cargo.toml | 12 ++++++------ cml/wasm/package.json | 2 +- core/rust/Cargo.toml | 2 +- core/wasm/Cargo.toml | 4 ++-- crypto/rust/Cargo.toml | 4 ++-- crypto/wasm/Cargo.toml | 4 ++-- examples/wasm-browser/package-lock.json | 8 ++++---- multi-era/rust/Cargo.toml | 8 ++++---- multi-era/wasm/Cargo.toml | 20 ++++++++++---------- multi-era/wasm/json-gen/Cargo.toml | 2 +- multi-era/wasm/package.json | 2 +- package.json | 2 +- tools/metadata-cddl-checker/Cargo.toml | 2 +- 22 files changed, 71 insertions(+), 71 deletions(-) diff --git a/chain/rust/Cargo.toml b/chain/rust/Cargo.toml index 03d77514..d12cb741 100644 --- a/chain/rust/Cargo.toml +++ b/chain/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cml-chain" -version = "5.3.0" +version = "5.3.1" edition = "2018" authors = ["dcSpark"] license = "MIT" @@ -14,8 +14,8 @@ keywords = ["cardano"] crate-type = ["cdylib", "rlib"] [dependencies] -cml-core = { "path" = "../../core/rust", version = "5.3.0" } -cml-crypto = { "path" = "../../crypto/rust", version = "5.3.0" } +cml-core = { "path" = "../../core/rust", version = "5.3.1" } +cml-crypto = { "path" = "../../crypto/rust", version = "5.3.1" } cbor_event = "2.2.0" linked-hash-map = "0.5.3" derivative = "2.2.0" diff --git a/chain/wasm/Cargo.toml b/chain/wasm/Cargo.toml index 8db093c8..3183820f 100644 --- a/chain/wasm/Cargo.toml +++ b/chain/wasm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cml-chain-wasm" -version = "5.3.0" +version = "5.3.1" edition = "2018" authors = ["dcSpark"] license = "MIT" @@ -14,12 +14,12 @@ keywords = ["cardano"] crate-type = ["cdylib", "rlib"] [dependencies] -cml-chain = { path = "../rust", version = "5.3.0" } -cml-core = { path = "../../core/rust", version = "5.3.0" } -cml-core-wasm = { path = "../../core/wasm", version = "5.3.0" } +cml-chain = { path = "../rust", version = "5.3.1" } +cml-core = { path = "../../core/rust", version = "5.3.1" } +cml-core-wasm = { path = "../../core/wasm", version = "5.3.1" } # TODO: remove this dependency if possible to reduce confusion? maybe pub export necessary things in crypto-wasm? -cml-crypto = { path = "../../crypto/rust", version = "5.3.0" } -cml-crypto-wasm = { path = "../../crypto/wasm", version = "5.3.0" } +cml-crypto = { path = "../../crypto/rust", version = "5.3.1" } +cml-crypto-wasm = { path = "../../crypto/wasm", version = "5.3.1" } cbor_event = "2.4.0" hex = "0.4.0" wasm-bindgen = { version = "=0.2.83", features = ["serde-serialize"] } diff --git a/chain/wasm/json-gen/Cargo.toml b/chain/wasm/json-gen/Cargo.toml index b4452354..403ce862 100644 --- a/chain/wasm/json-gen/Cargo.toml +++ b/chain/wasm/json-gen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cml-chain-json-schema-gen" -version = "5.3.0" +version = "5.3.1" edition = "2018" keywords = ["cardano"] diff --git a/cip25/rust/Cargo.toml b/cip25/rust/Cargo.toml index 9221f3d0..6277b682 100644 --- a/cip25/rust/Cargo.toml +++ b/cip25/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cml-cip25" -version = "5.3.0" +version = "5.3.1" edition = "2018" authors = ["dcSpark"] license = "MIT" @@ -14,9 +14,9 @@ keywords = ["cardano", "cip25"] crate-type = ["cdylib", "rlib"] [dependencies] -cml-chain = { "path" = "../../chain/rust", version = "5.3.0" } -cml-core = { "path" = "../../core/rust", version = "5.3.0" } -cml-crypto = { "path" = "../../crypto/rust", version = "5.3.0" } +cml-chain = { "path" = "../../chain/rust", version = "5.3.1" } +cml-core = { "path" = "../../core/rust", version = "5.3.1" } +cml-crypto = { "path" = "../../crypto/rust", version = "5.3.1" } cbor_event = "2.2.0" hex = "0.4.0" schemars = "0.8.8" diff --git a/cip25/wasm/Cargo.toml b/cip25/wasm/Cargo.toml index 44a7d099..db03c318 100644 --- a/cip25/wasm/Cargo.toml +++ b/cip25/wasm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cml-cip25-wasm" -version = "5.3.0" +version = "5.3.1" edition = "2018" authors = ["dcSpark"] license = "MIT" @@ -15,11 +15,11 @@ crate-type = ["cdylib", "rlib"] [dependencies] cbor_event = "2.2.0" -cml-chain = { path = "../../chain/rust", version = "5.3.0" } -cml-chain-wasm = { path = "../../chain/wasm", version = "5.3.0" } -cml-core = { path = "../../core/rust", version = "5.3.0" } -cml-core-wasm = { path = "../../core/wasm", version = "5.3.0" } -cml-cip25 = { path = "../rust", version = "5.3.0" } +cml-chain = { path = "../../chain/rust", version = "5.3.1" } +cml-chain-wasm = { path = "../../chain/wasm", version = "5.3.1" } +cml-core = { path = "../../core/rust", version = "5.3.1" } +cml-core-wasm = { path = "../../core/wasm", version = "5.3.1" } +cml-cip25 = { path = "../rust", version = "5.3.1" } hex = "0.4.0" linked-hash-map = "0.5.3" serde_json = "1.0.57" diff --git a/cip25/wasm/json-gen/Cargo.toml b/cip25/wasm/json-gen/Cargo.toml index a877a183..09933ff8 100644 --- a/cip25/wasm/json-gen/Cargo.toml +++ b/cip25/wasm/json-gen/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "cml-cip25-json-schema-gen" -version = "5.3.0" +version = "5.3.1" edition = "2018" keywords = ["cardano"] [dependencies] serde_json = "1.0.57" schemars = "0.8.8" -cml-cip25 = { path = "../../rust", version = "5.3.0" } +cml-cip25 = { path = "../../rust", version = "5.3.1" } diff --git a/cip36/rust/Cargo.toml b/cip36/rust/Cargo.toml index c8675b88..c4c58b28 100644 --- a/cip36/rust/Cargo.toml +++ b/cip36/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cml-cip36" -version = "5.3.0" +version = "5.3.1" edition = "2018" authors = ["dcSpark"] license = "MIT" @@ -14,9 +14,9 @@ keywords = ["cardano", "cip36"] crate-type = ["cdylib", "rlib"] [dependencies] -cml-core = { "path" = "../../core/rust", version = "5.3.0" } -cml-crypto = { "path" = "../../crypto/rust", version = "5.3.0" } -cml-chain = { "path" = "../../chain/rust", version = "5.3.0" } +cml-core = { "path" = "../../core/rust", version = "5.3.1" } +cml-crypto = { "path" = "../../crypto/rust", version = "5.3.1" } +cml-chain = { "path" = "../../chain/rust", version = "5.3.1" } cbor_event = "2.2.0" linked-hash-map = "0.5.3" derivative = "2.2.0" diff --git a/cip36/wasm/Cargo.toml b/cip36/wasm/Cargo.toml index 89dd4ee8..6de5fcea 100644 --- a/cip36/wasm/Cargo.toml +++ b/cip36/wasm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cml-cip36-wasm" -version = "5.3.0" +version = "5.3.1" edition = "2018" authors = ["dcSpark"] license = "MIT" @@ -14,13 +14,13 @@ keywords = ["cardano", "cip36"] crate-type = ["cdylib", "rlib"] [dependencies] -cml-cip36 = { path = "../rust", version = "5.3.0" } -cml-crypto = { path = "../../crypto/rust", version = "5.3.0" } -cml-crypto-wasm = { path = "../../crypto/wasm", version = "5.3.0" } -cml-chain = { path = "../../chain/rust", version = "5.3.0" } -cml-chain-wasm = { path = "../../chain/wasm", version = "5.3.0" } -cml-core = { path = "../../core/rust", version = "5.3.0" } -cml-core-wasm = { path = "../../core/wasm", version = "5.3.0" } +cml-cip36 = { path = "../rust", version = "5.3.1" } +cml-crypto = { path = "../../crypto/rust", version = "5.3.1" } +cml-crypto-wasm = { path = "../../crypto/wasm", version = "5.3.1" } +cml-chain = { path = "../../chain/rust", version = "5.3.1" } +cml-chain-wasm = { path = "../../chain/wasm", version = "5.3.1" } +cml-core = { path = "../../core/rust", version = "5.3.1" } +cml-core-wasm = { path = "../../core/wasm", version = "5.3.1" } cbor_event = "2.2.0" hex = "0.4.0" wasm-bindgen = { version = "=0.2.83", features = ["serde-serialize"] } diff --git a/cip36/wasm/json-gen/Cargo.toml b/cip36/wasm/json-gen/Cargo.toml index 785a78b7..5c2595de 100644 --- a/cip36/wasm/json-gen/Cargo.toml +++ b/cip36/wasm/json-gen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cml-cip36-json-schema-gen" -version = "5.3.0" +version = "5.3.1" edition = "2018" diff --git a/cml/wasm/Cargo.toml b/cml/wasm/Cargo.toml index 9dd60600..15d595ad 100644 --- a/cml/wasm/Cargo.toml +++ b/cml/wasm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cardano-multiplatform-lib" -version = "5.3.0" +version = "5.3.1" edition = "2018" keywords = ["cardano"] license = "MIT" @@ -13,11 +13,11 @@ readme = "../../README.md" crate-type = ["cdylib", "rlib"] [dependencies] -cml-chain-wasm = { path = "../../chain/wasm", version = "5.3.0" } -cml-cip25-wasm = { path = "../../cip25/wasm", version = "5.3.0" } -cml-cip36-wasm = { path = "../../cip36/wasm", version = "5.3.0" } -cml-crypto-wasm = { path = "../../crypto/wasm", version = "5.3.0" } -cml-core-wasm = { path = "../../core/wasm", version = "5.3.0" } +cml-chain-wasm = { path = "../../chain/wasm", version = "5.3.1" } +cml-cip25-wasm = { path = "../../cip25/wasm", version = "5.3.1" } +cml-cip36-wasm = { path = "../../cip36/wasm", version = "5.3.1" } +cml-crypto-wasm = { path = "../../crypto/wasm", version = "5.3.1" } +cml-core-wasm = { path = "../../core/wasm", version = "5.3.1" } cbor_event = "2.4.0" hex = "0.4.0" linked-hash-map = "0.5.3" diff --git a/cml/wasm/package.json b/cml/wasm/package.json index 0eae7a58..66ca30cb 100644 --- a/cml/wasm/package.json +++ b/cml/wasm/package.json @@ -1,6 +1,6 @@ { "name": "cardano-multiplatform-lib", - "version": "5.3.0", + "version": "5.3.1", "description": "Cardano Multiplatform SDK for core Cardano blockchain functionality", "keywords": [ "cardano" diff --git a/core/rust/Cargo.toml b/core/rust/Cargo.toml index 9a66ba4f..d50ea7ac 100644 --- a/core/rust/Cargo.toml +++ b/core/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cml-core" -version = "5.3.0" +version = "5.3.1" edition = "2018" authors = ["dcSpark"] license = "MIT" diff --git a/core/wasm/Cargo.toml b/core/wasm/Cargo.toml index 0e47c184..605216ed 100644 --- a/core/wasm/Cargo.toml +++ b/core/wasm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cml-core-wasm" -version = "5.3.0" +version = "5.3.1" edition = "2018" keywords = ["cardano"] license = "MIT" @@ -13,7 +13,7 @@ readme = "../../README.md" crate-type = ["cdylib", "rlib"] [dependencies] -cml-core = { path = "../rust", version = "5.3.0" } +cml-core = { path = "../rust", version = "5.3.1" } cbor_event = "2.2.0" hex = "0.4.0" wasm-bindgen = { version = "=0.2.83", features = ["serde-serialize"] } diff --git a/crypto/rust/Cargo.toml b/crypto/rust/Cargo.toml index af58d4aa..d9c348ce 100644 --- a/crypto/rust/Cargo.toml +++ b/crypto/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cml-crypto" -version = "5.3.0" +version = "5.3.1" edition = "2018" authors = ["dcSpark"] license = "MIT" @@ -14,7 +14,7 @@ keywords = ["cardano"] crate-type = ["cdylib", "rlib"] [dependencies] -cml-core = { "path" = "../../core/rust", version = "5.3.0" } +cml-core = { "path" = "../../core/rust", version = "5.3.1" } base64 = "0.21.5" cbor_event = "2.2.0" cryptoxide = "0.4.2" diff --git a/crypto/wasm/Cargo.toml b/crypto/wasm/Cargo.toml index 9d1c0147..39eb864c 100644 --- a/crypto/wasm/Cargo.toml +++ b/crypto/wasm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cml-crypto-wasm" -version = "5.3.0" +version = "5.3.1" edition = "2018" authors = ["dcSpark"] license = "MIT" @@ -14,7 +14,7 @@ keywords = ["cardano"] crate-type = ["cdylib", "rlib"] [dependencies] -cml-crypto = { path = "../rust", version = "5.3.0" } +cml-crypto = { path = "../rust", version = "5.3.1" } cbor_event = "2.2.0" wasm-bindgen = { version = "=0.2.83", features = ["serde-serialize"] } linked-hash-map = "0.5.3" diff --git a/examples/wasm-browser/package-lock.json b/examples/wasm-browser/package-lock.json index a628f8e8..0b3c4171 100644 --- a/examples/wasm-browser/package-lock.json +++ b/examples/wasm-browser/package-lock.json @@ -1,12 +1,12 @@ { "name": "test-cml-dapp", - "version": "5.1.0", + "version": "5.3.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "test-cml-dapp", - "version": "5.1.0", + "version": "5.3.1", "dependencies": { "cml-chain-wasm": "file:../../chain/wasm/pkg", "cml-cip25-wasm": "file:../../cip25/wasm/pkg", @@ -21,11 +21,11 @@ }, "../../chain/wasm/pkg": { "name": "cml-chain-wasm", - "version": "5.1.0" + "version": "5.3.1" }, "../../cip25/wasm/pkg": { "name": "cml-cip25-wasm", - "version": "5.1.0" + "version": "5.3.1" }, "node_modules/@discoveryjs/json-ext": { "version": "0.5.7", diff --git a/multi-era/rust/Cargo.toml b/multi-era/rust/Cargo.toml index f7ade7a6..bb5c5e66 100644 --- a/multi-era/rust/Cargo.toml +++ b/multi-era/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cml-multi-era" -version = "5.3.0" +version = "5.3.1" edition = "2018" authors = ["dcSpark"] license = "MIT" @@ -14,9 +14,9 @@ keywords = ["cardano"] crate-type = ["cdylib", "rlib"] [dependencies] -cml-core = { path = "../../core/rust", version = "5.3.0" } -cml-crypto = { path = "../../crypto/rust", version = "5.3.0" } -cml-chain = { path = "../../chain/rust", version = "5.3.0" } +cml-core = { path = "../../core/rust", version = "5.3.1" } +cml-crypto = { path = "../../crypto/rust", version = "5.3.1" } +cml-chain = { path = "../../chain/rust", version = "5.3.1" } cbor_event = "2.4.0" linked-hash-map = "0.5.3" derivative = "2.2.0" diff --git a/multi-era/wasm/Cargo.toml b/multi-era/wasm/Cargo.toml index 5945b87c..e4c5bedc 100644 --- a/multi-era/wasm/Cargo.toml +++ b/multi-era/wasm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cml-multi-era-wasm" -version = "5.3.0" +version = "5.3.1" edition = "2018" authors = ["dcSpark"] license = "MIT" @@ -14,13 +14,13 @@ keywords = ["cardano"] crate-type = ["cdylib", "rlib"] [dependencies] -cml-chain = { path = "../../chain/rust", version = "5.3.0" } -cml-chain-wasm = { path = "../../chain/wasm", version = "5.3.0" } -cml-crypto = { path = "../../crypto/rust", version = "5.3.0" } -cml-crypto-wasm = { path = "../../crypto/wasm", version = "5.3.0" } -cml-core = { path = "../../core/rust", version = "5.3.0" } -cml-core-wasm = { path = "../../core/wasm", version = "5.3.0" } -cml-multi-era = { path = "../rust", version = "5.3.0" } +cml-chain = { path = "../../chain/rust", version = "5.3.1" } +cml-chain-wasm = { path = "../../chain/wasm", version = "5.3.1" } +cml-crypto = { path = "../../crypto/rust", version = "5.3.1" } +cml-crypto-wasm = { path = "../../crypto/wasm", version = "5.3.1" } +cml-core = { path = "../../core/rust", version = "5.3.1" } +cml-core-wasm = { path = "../../core/wasm", version = "5.3.1" } +cml-multi-era = { path = "../rust", version = "5.3.1" } cbor_event = "2.4.0" hex = "0.4.0" linked-hash-map = "0.5.3" @@ -28,5 +28,5 @@ serde_json = "1.0.57" serde-wasm-bindgen = "0.4.5" wasm-bindgen = { version = "0.2", features=["serde-serialize"] } # not actual multi-era dependencies but we re-export these for the wasm builds -cml-cip25-wasm = { path = "../../cip25/wasm", version = "5.3.0" } -cml-cip36-wasm = { path = "../../cip36/wasm", version = "5.3.0" } \ No newline at end of file +cml-cip25-wasm = { path = "../../cip25/wasm", version = "5.3.1" } +cml-cip36-wasm = { path = "../../cip36/wasm", version = "5.3.1" } \ No newline at end of file diff --git a/multi-era/wasm/json-gen/Cargo.toml b/multi-era/wasm/json-gen/Cargo.toml index c376078a..ff0fdf42 100644 --- a/multi-era/wasm/json-gen/Cargo.toml +++ b/multi-era/wasm/json-gen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cml-multi-era-json-schema-gen" -version = "5.3.0" +version = "5.3.1" edition = "2018" diff --git a/multi-era/wasm/package.json b/multi-era/wasm/package.json index 818a9beb..72763a08 100644 --- a/multi-era/wasm/package.json +++ b/multi-era/wasm/package.json @@ -1,6 +1,6 @@ { "name": "cardano-multiplatform-multiera-lib", - "version": "5.3.0", + "version": "5.3.1", "description": "Multiplatform SDK for on-chain Cardano blochain types of all eras (Byron, Shelley, etc)", "keywords": [ "cardano" diff --git a/package.json b/package.json index ccf8a3b4..db51eae0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cardano-multiplatform-lib", - "version": "5.3.0", + "version": "5.3.1", "description": "Cardano Multiplatform SDK for core Cardano blockchain functionality", "keywords": [ "cardano" diff --git a/tools/metadata-cddl-checker/Cargo.toml b/tools/metadata-cddl-checker/Cargo.toml index 2dd9a34e..0d7553b2 100644 --- a/tools/metadata-cddl-checker/Cargo.toml +++ b/tools/metadata-cddl-checker/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "metadata-cddl-checker" -version = "5.3.0" +version = "5.3.1" edition = "2018" [dependencies] From 4299c233be185eeb79b82e335a81f84f3602e1a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C5=A9=20Ho=C3=A0ng?= <127402781+hadelive@users.noreply.github.com> Date: Wed, 12 Jun 2024 02:42:04 +0700 Subject: [PATCH 06/16] feat: add native-script verify function (#332) * feat: add native-script verify function --- chain/rust/src/builders/tx_builder.rs | 5 +- chain/rust/src/builders/witness_builder.rs | 6 +-- chain/rust/src/utils.rs | 55 +++++++++++++++++++++- chain/wasm/src/transaction/mod.rs | 1 - chain/wasm/src/transaction/utils.rs | 10 ++++ multi-era/rust/src/alonzo/utils.rs | 6 +-- multi-era/rust/src/babbage/utils.rs | 8 ++-- 7 files changed, 75 insertions(+), 16 deletions(-) diff --git a/chain/rust/src/builders/tx_builder.rs b/chain/rust/src/builders/tx_builder.rs index 7a6dd4bd..a5eeb9f4 100644 --- a/chain/rust/src/builders/tx_builder.rs +++ b/chain/rust/src/builders/tx_builder.rs @@ -720,13 +720,12 @@ impl TransactionBuilder { match &script_witness.script { PlutusScriptWitness::Ref(ref_script) => { - if self + if !self .witness_builders .witness_set_builder .required_wits .script_refs - .get(ref_script) - .is_none() + .contains(ref_script) { Err(TxBuilderError::RefScriptNotFound( *ref_script, diff --git a/chain/rust/src/builders/witness_builder.rs b/chain/rust/src/builders/witness_builder.rs index 3baebe67..299f9955 100644 --- a/chain/rust/src/builders/witness_builder.rs +++ b/chain/rust/src/builders/witness_builder.rs @@ -275,7 +275,7 @@ impl TransactionWitnessSetBuilder { pub fn get_native_script(&self) -> Vec { self.scripts .iter() - .filter(|entry| self.required_wits.script_refs.get(entry.0).is_none()) + .filter(|entry| !self.required_wits.script_refs.contains(entry.0)) .fold( Vec::::new(), |mut acc, script| match &script.1 { @@ -291,7 +291,7 @@ impl TransactionWitnessSetBuilder { pub fn get_plutus_v1_script(&self) -> Vec { self.scripts .iter() - .filter(|entry| self.required_wits.script_refs.get(entry.0).is_none()) + .filter(|entry| !self.required_wits.script_refs.contains(entry.0)) .fold( Vec::::new(), |mut acc, script| match &script.1 { @@ -307,7 +307,7 @@ impl TransactionWitnessSetBuilder { pub fn get_plutus_v2_script(&self) -> Vec { self.scripts .iter() - .filter(|entry| self.required_wits.script_refs.get(entry.0).is_none()) + .filter(|entry| !self.required_wits.script_refs.contains(entry.0)) .fold( Vec::::new(), |mut acc, script| match &script.1 { diff --git a/chain/rust/src/utils.rs b/chain/rust/src/utils.rs index ab3b184c..41914ecd 100644 --- a/chain/rust/src/utils.rs +++ b/chain/rust/src/utils.rs @@ -2,9 +2,9 @@ use cbor_event::{de::Deserializer, se::Serializer, Sz}; use cml_core::{ error::{DeserializeError, DeserializeFailure}, serialization::{fit_sz, sz_max, Deserialize, LenEncoding, Serialize}, - Int, + Int, Slot, }; -use cml_crypto::{RawBytesEncoding, ScriptHash}; +use cml_crypto::{Ed25519KeyHash, RawBytesEncoding, ScriptHash}; use derivative::Derivative; use std::io::{BufRead, Seek, Write}; use std::iter::IntoIterator; @@ -41,6 +41,57 @@ impl NativeScript { pub fn hash(&self) -> ScriptHash { hash_script(ScriptHashNamespace::NativeScript, &self.to_cbor_bytes()) } + + pub fn verify( + &self, + lower_bound: Option, + upper_bound: Option, + key_hashes: &Vec, + ) -> bool { + fn verify_helper( + script: &NativeScript, + lower_bound: Option, + upper_bound: Option, + key_hashes: &Vec, + ) -> bool { + match &script { + NativeScript::ScriptPubkey(pub_key) => { + key_hashes.contains(&pub_key.ed25519_key_hash) + } + NativeScript::ScriptAll(script_all) => { + script_all.native_scripts.iter().all(|sub_script| { + verify_helper(sub_script, lower_bound, upper_bound, key_hashes) + }) + } + NativeScript::ScriptAny(script_any) => { + script_any.native_scripts.iter().any(|sub_script| { + verify_helper(sub_script, lower_bound, upper_bound, key_hashes) + }) + } + NativeScript::ScriptNOfK(script_atleast) => { + script_atleast + .native_scripts + .iter() + .map(|sub_script| { + verify_helper(sub_script, lower_bound, upper_bound, key_hashes) + }) + .filter(|r| *r) + .count() + >= script_atleast.n as usize + } + NativeScript::ScriptInvalidBefore(timelock_start) => match lower_bound { + Some(tx_slot) => tx_slot >= timelock_start.before, + _ => false, + }, + NativeScript::ScriptInvalidHereafter(timelock_expiry) => match upper_bound { + Some(tx_slot) => tx_slot < timelock_expiry.after, + _ => false, + }, + } + } + + verify_helper(self, lower_bound, upper_bound, key_hashes) + } } impl From for Script { diff --git a/chain/wasm/src/transaction/mod.rs b/chain/wasm/src/transaction/mod.rs index e4fb2a94..f8aca0f6 100644 --- a/chain/wasm/src/transaction/mod.rs +++ b/chain/wasm/src/transaction/mod.rs @@ -18,7 +18,6 @@ use cml_crypto_wasm::{ AuxiliaryDataHash, DatumHash, Ed25519KeyHash, ScriptDataHash, TransactionHash, }; use wasm_bindgen::prelude::{wasm_bindgen, JsError, JsValue}; - pub mod utils; #[derive(Clone, Debug)] diff --git a/chain/wasm/src/transaction/utils.rs b/chain/wasm/src/transaction/utils.rs index 67932bf5..5d2ddffc 100644 --- a/chain/wasm/src/transaction/utils.rs +++ b/chain/wasm/src/transaction/utils.rs @@ -4,6 +4,7 @@ use crate::{ utils::LanguageList, Ed25519KeyHashList, NativeScript, Value, }; +use cml_core::Slot; use cml_crypto_wasm::{DatumHash, ScriptHash}; use wasm_bindgen::prelude::wasm_bindgen; @@ -68,6 +69,15 @@ impl NativeScript { pub fn hash(&self) -> ScriptHash { self.0.hash().into() } + + pub fn verify( + &self, + lower_bound: Option, + upper_bound: Option, + key_hashes: &Ed25519KeyHashList, + ) -> bool { + self.0.verify(lower_bound, upper_bound, key_hashes.as_ref()) + } } #[wasm_bindgen] diff --git a/multi-era/rust/src/alonzo/utils.rs b/multi-era/rust/src/alonzo/utils.rs index 802d8207..43a6ea18 100644 --- a/multi-era/rust/src/alonzo/utils.rs +++ b/multi-era/rust/src/alonzo/utils.rs @@ -25,9 +25,9 @@ impl From for AuxiliaryData { AlonzoAuxiliaryData::ShelleyMA(md) => AuxiliaryData::new_shelley_m_a(md.clone()), AlonzoAuxiliaryData::Alonzo(md) => AuxiliaryData::new_conway({ let mut conway = ConwayFormatAuxData::new(); - conway.metadata = md.metadata.clone(); - conway.native_scripts = md.native_scripts.clone(); - conway.plutus_v1_scripts = md.plutus_v1_scripts.clone(); + conway.metadata.clone_from(&md.metadata); + conway.native_scripts.clone_from(&md.native_scripts); + conway.plutus_v1_scripts.clone_from(&md.plutus_v1_scripts); conway }), } diff --git a/multi-era/rust/src/babbage/utils.rs b/multi-era/rust/src/babbage/utils.rs index 9d060ecd..050a97d2 100644 --- a/multi-era/rust/src/babbage/utils.rs +++ b/multi-era/rust/src/babbage/utils.rs @@ -66,10 +66,10 @@ impl From for AuxiliaryData { BabbageAuxiliaryData::ShelleyMA(md) => AuxiliaryData::new_shelley_m_a(md.clone()), BabbageAuxiliaryData::Babbage(md) => AuxiliaryData::new_conway({ let mut conway = ConwayFormatAuxData::new(); - conway.metadata = md.metadata.clone(); - conway.native_scripts = md.native_scripts.clone(); - conway.plutus_v1_scripts = md.plutus_v1_scripts.clone(); - conway.plutus_v2_scripts = md.plutus_v2_scripts.clone(); + conway.metadata.clone_from(&md.metadata); + conway.native_scripts.clone_from(&md.native_scripts); + conway.plutus_v1_scripts.clone_from(&md.plutus_v1_scripts); + conway.plutus_v2_scripts.clone_from(&md.plutus_v2_scripts); conway }), } From 29c48aa202567eae1366cd59e31a40bed590ce3e Mon Sep 17 00:00:00 2001 From: rooooooooob Date: Tue, 18 Jun 2024 14:05:40 +0900 Subject: [PATCH 07/16] Cost models update conway (#336) Due to changes here: IntersectMBO/cardano-ledger#4284 Clarification here: IntersectMBO/cardano-ledger#4383 Allows non-Plutus languages according to the spec and changes to an indexable map type. --- chain/rust/src/builders/tx_builder.rs | 2 +- chain/rust/src/crypto/hash.rs | 39 +-- chain/rust/src/genesis/network_info.rs | 20 +- chain/rust/src/plutus/cbor_encodings.rs | 12 +- chain/rust/src/plutus/mod.rs | 60 +++- chain/rust/src/plutus/serialization.rs | 391 ++++++++---------------- chain/rust/src/plutus/utils.rs | 149 +++++---- chain/wasm/src/plutus/mod.rs | 45 ++- specs/conway/plutus.cddl | 11 +- 9 files changed, 304 insertions(+), 425 deletions(-) diff --git a/chain/rust/src/builders/tx_builder.rs b/chain/rust/src/builders/tx_builder.rs index a5eeb9f4..d91b1981 100644 --- a/chain/rust/src/builders/tx_builder.rs +++ b/chain/rust/src/builders/tx_builder.rs @@ -363,7 +363,7 @@ impl TransactionBuilderConfigBuilder { cost_models: if self.cost_models.is_some() { self.cost_models.unwrap() } else { - CostModels::new() + CostModels::default() }, _collateral_percentage: self.collateral_percentage.ok_or( TxBuilderError::UninitializedField(TxBuilderConfigField::CollateralPercentage), diff --git a/chain/rust/src/crypto/hash.rs b/chain/rust/src/crypto/hash.rs index d07f6e03..c8fbe5f0 100644 --- a/chain/rust/src/crypto/hash.rs +++ b/chain/rust/src/crypto/hash.rs @@ -88,37 +88,16 @@ pub fn calc_script_data_hash( encoding: Option<&TransactionWitnessSetEncoding>, ) -> Result, ScriptDataHashError> { if !redeemers.is_empty() || !datums.is_empty() { - let mut required_costmdls = CostModels::new(); + let mut required_costmdls = CostModels::default(); for lang in used_langs { - match lang { - Language::PlutusV1 => { - required_costmdls.plutus_v1 = Some( - cost_models - .plutus_v1 - .as_ref() - .ok_or(ScriptDataHashError::MissingCostModel(*lang))? - .clone(), - ); - } - Language::PlutusV2 => { - required_costmdls.plutus_v2 = Some( - cost_models - .plutus_v2 - .as_ref() - .ok_or(ScriptDataHashError::MissingCostModel(*lang))? - .clone(), - ); - } - Language::PlutusV3 => { - required_costmdls.plutus_v3 = Some( - cost_models - .plutus_v3 - .as_ref() - .ok_or(ScriptDataHashError::MissingCostModel(*lang))? - .clone(), - ); - } - } + required_costmdls.inner.insert( + *lang as u64, + cost_models + .inner + .get(&(*lang).into()) + .ok_or(ScriptDataHashError::MissingCostModel(*lang))? + .clone(), + ); } Ok(Some(hash_script_data( diff --git a/chain/rust/src/genesis/network_info.rs b/chain/rust/src/genesis/network_info.rs index eb9aef0d..6e942d91 100644 --- a/chain/rust/src/genesis/network_info.rs +++ b/chain/rust/src/genesis/network_info.rs @@ -1,10 +1,10 @@ -use crate::{byron::ProtocolMagic, plutus::CostModels}; -use cml_core::{ - network::{ - BYRON_MAINNET_NETWORK_MAGIC, BYRON_TESTNET_NETWORK_MAGIC, PREPROD_NETWORK_MAGIC, - PREVIEW_NETWORK_MAGIC, SANCHO_TESTNET_NETWORK_MAGIC, - }, - Int, +use crate::{ + byron::ProtocolMagic, + plutus::{CostModels, Language}, +}; +use cml_core::network::{ + BYRON_MAINNET_NETWORK_MAGIC, BYRON_TESTNET_NETWORK_MAGIC, PREPROD_NETWORK_MAGIC, + PREVIEW_NETWORK_MAGIC, SANCHO_TESTNET_NETWORK_MAGIC, }; #[derive(Debug, Clone, Eq, Hash, Ord, PartialEq, PartialOrd)] @@ -67,7 +67,7 @@ impl NetworkInfo { // TODO: https://github.com/dcSpark/cardano-multiplatform-lib/issues/92 pub fn plutus_alonzo_cost_models() -> CostModels { - let ops: [u64; 166] = [ + let ops = vec![ 197209, 0, 1, 1, 396231, 621, 0, 1, 150000, 1000, 0, 1, 150000, 32, 2477736, 29175, 4, 29773, 100, 29773, 100, 29773, 100, 29773, 100, 29773, 100, 29773, 100, 100, 100, 29773, 100, 150000, 32, 150000, 32, 150000, 32, 150000, 1000, 0, 1, 150000, 32, 150000, 1000, 0, @@ -81,7 +81,7 @@ pub fn plutus_alonzo_cost_models() -> CostModels { 3345831, 1, 1, ]; - let mut res = CostModels::new(); - res.plutus_v1 = Some(ops.iter().map(|&i| Int::from(i)).collect()); + let mut res = CostModels::default(); + res.inner.insert(Language::PlutusV1 as u64, ops); res } diff --git a/chain/rust/src/plutus/cbor_encodings.rs b/chain/rust/src/plutus/cbor_encodings.rs index 2ae27ca4..5e894c0a 100644 --- a/chain/rust/src/plutus/cbor_encodings.rs +++ b/chain/rust/src/plutus/cbor_encodings.rs @@ -2,17 +2,13 @@ // https://github.com/dcSpark/cddl-codegen use cml_core::serialization::{LenEncoding, StringEncoding}; +use std::collections::BTreeMap; #[derive(Clone, Debug, Default)] pub struct CostModelsEncoding { - 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, - pub plutus_v3_encoding: LenEncoding, - pub plutus_v3_key_encoding: Option, + pub inner_encoding: LenEncoding, + pub inner_key_encodings: BTreeMap>, + pub inner_value_encodings: BTreeMap>)>, } #[derive(Clone, Debug, Default)] diff --git a/chain/rust/src/plutus/mod.rs b/chain/rust/src/plutus/mod.rs index 79978f1e..e1941b42 100644 --- a/chain/rust/src/plutus/mod.rs +++ b/chain/rust/src/plutus/mod.rs @@ -18,34 +18,68 @@ use cbor_encodings::{ use cml_core::ordered_hash_map::OrderedHashMap; use cml_core::serialization::{LenEncoding, Serialize, StringEncoding}; -use cml_core::Int; use cml_crypto::{blake2b256, DatumHash}; pub use utils::{ConstrPlutusData, PlutusMap, PlutusScript}; -#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] +#[derive(Clone, Debug, Default)] pub struct CostModels { - pub plutus_v1: Option>, - pub plutus_v2: Option>, - pub plutus_v3: Option>, - #[serde(skip)] + pub inner: OrderedHashMap>, pub encodings: Option, } impl CostModels { - pub fn new() -> Self { + pub fn new(inner: OrderedHashMap>) -> Self { Self { - plutus_v1: None, - plutus_v2: None, - plutus_v3: None, + inner, encodings: None, } } } -impl Default for CostModels { - fn default() -> Self { - Self::new() +impl From>> for CostModels { + fn from(inner: OrderedHashMap>) -> Self { + CostModels::new(inner.clone()) + } +} + +impl From for OrderedHashMap> { + fn from(wrapper: CostModels) -> Self { + wrapper.inner + } +} + +impl serde::Serialize for CostModels { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + self.inner.serialize(serializer) + } +} + +impl<'de> serde::de::Deserialize<'de> for CostModels { + fn deserialize(deserializer: D) -> Result + where + D: serde::de::Deserializer<'de>, + { + let inner = + > as serde::de::Deserialize>::deserialize(deserializer)?; + Ok(Self::new(inner)) + } +} + +impl schemars::JsonSchema for CostModels { + fn schema_name() -> String { + String::from("CostModels") + } + + fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema { + OrderedHashMap::>::json_schema(gen) + } + + fn is_referenceable() -> bool { + OrderedHashMap::>::is_referenceable() } } diff --git a/chain/rust/src/plutus/serialization.rs b/chain/rust/src/plutus/serialization.rs index 8e187e26..c7fecb5c 100644 --- a/chain/rust/src/plutus/serialization.rs +++ b/chain/rust/src/plutus/serialization.rs @@ -7,6 +7,7 @@ use cbor_event::de::Deserializer; use cbor_event::se::Serializer; use cml_core::error::*; use cml_core::serialization::*; +use std::collections::BTreeMap; use std::io::{BufRead, Seek, SeekFrom, Write}; // PlutusData::Bytes uses this specific encoding: @@ -21,139 +22,70 @@ impl Serialize for CostModels { serializer.write_map_sz( self.encodings .as_ref() - .map(|encs| encs.len_encoding) + .map(|encs| encs.inner_encoding) .unwrap_or_default() - .to_len_sz( - match &self.plutus_v1 { - Some(_) => 1, - None => 0, - } + match &self.plutus_v2 { - Some(_) => 1, - None => 0, - } + match &self.plutus_v3 { - Some(_) => 1, - None => 0, - }, - force_canonical, - ), + .to_len_sz(self.inner.len() as u64, 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, - } + match &self.plutus_v3 { - Some(_) => 1, - None => 0, - } + let mut key_order = self + .inner + .iter() + .map(|(k, v)| { + let mut buf = cbor_event::se::Serializer::new_vec(); + let inner_key_encoding = self + .encodings + .as_ref() + .and_then(|encs| encs.inner_key_encodings.get(k)) + .cloned() + .unwrap_or_default(); + buf.write_unsigned_integer_sz(*k, fit_sz(*k, inner_key_encoding, force_canonical))?; + Ok((buf.finalize(), k, v)) }) - .map(|encs| encs.orig_deser_order.clone()) - .unwrap_or_else(|| vec![0, 1, 2]); - 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)?; - } + .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, } - 2 => { - if let Some(field) = &self.plutus_v3 { - serializer.write_unsigned_integer_sz( - 2u64, - fit_sz( - 2u64, - self.encodings - .as_ref() - .map(|encs| encs.plutus_v3_key_encoding) - .unwrap_or_default(), - force_canonical, - ), - )?; - serializer.write_array_sz( - self.encodings - .as_ref() - .map(|encs| encs.plutus_v3_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_encoding) - .unwrap_or_default() - .end(serializer, force_canonical)?; - } + }); + } + for (key_bytes, key, value) in key_order { + serializer.write_raw_bytes(&key_bytes)?; + let (inner_value_encoding, inner_value_elem_encodings) = self + .encodings + .as_ref() + .and_then(|encs| encs.inner_value_encodings.get(key)) + .cloned() + .unwrap_or_else(|| (LenEncoding::default(), Vec::new())); + serializer.write_array_sz( + inner_value_encoding.to_len_sz(value.len() as u64, force_canonical), + )?; + for (i, element) in value.iter().enumerate() { + let inner_value_elem_encoding = inner_value_elem_encodings + .get(i) + .cloned() + .unwrap_or_default(); + if *element >= 0 { + serializer.write_unsigned_integer_sz( + *element as u64, + fit_sz(*element as u64, inner_value_elem_encoding, force_canonical), + )?; + } else { + serializer.write_negative_integer_sz( + *element as i128, + fit_sz( + (*element + 1).unsigned_abs(), + inner_value_elem_encoding, + force_canonical, + ), + )?; } - _ => unreachable!(), - }; + } + inner_value_encoding.end(serializer, force_canonical)?; } self.encodings .as_ref() - .map(|encs| encs.len_encoding) + .map(|encs| encs.inner_encoding) .unwrap_or_default() .end(serializer, force_canonical) } @@ -161,159 +93,74 @@ impl Serialize for CostModels { impl Deserialize for CostModels { 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 plutus_v3_encoding = LenEncoding::default(); - let mut plutus_v3_key_encoding = None; - let mut plutus_v3 = None; - let mut read = 0; + let mut inner_table = OrderedHashMap::new(); + let inner_len = raw.map_sz()?; + let inner_encoding = inner_len.into(); + let mut inner_key_encodings = BTreeMap::new(); + let mut inner_value_encodings = BTreeMap::new(); + while match inner_len { + cbor_event::LenSz::Len(n, _) => (inner_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 (inner_key, inner_key_encoding) = + raw.unsigned_integer_sz().map(|(x, enc)| (x, Some(enc)))?; + let mut inner_value_arr = Vec::new(); + let len = raw.array_sz()?; + let inner_value_encoding = len.into(); + let mut inner_value_elem_encodings = Vec::new(); while match len { - cbor_event::LenSz::Len(n, _) => read < n, + cbor_event::LenSz::Len(n, _) => (inner_value_arr.len() as u64) < 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); - } - (2, key_enc) => { - if plutus_v3.is_some() { - return Err(DeserializeFailure::DuplicateKey(Key::Uint(2)).into()); - } - let (tmp_plutus_v3, tmp_plutus_v3_encoding) = - (|| -> Result<_, DeserializeError> { - read_len.read_elems(1)?; - let mut plutus_v3_arr = Vec::new(); - let len = raw.array_sz()?; - let plutus_v3_encoding = len.into(); - while match len { - cbor_event::LenSz::Len(n, _) => { - (plutus_v3_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_arr.push(Int::deserialize(raw)?); - } - Ok((plutus_v3_arr, plutus_v3_encoding)) - })() - .map_err(|e| e.annotate("plutus_v3"))?; - plutus_v3 = Some(tmp_plutus_v3); - plutus_v3_encoding = tmp_plutus_v3_encoding; - plutus_v3_key_encoding = Some(key_enc); - orig_deser_order.push(2); - } - (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()) + if raw.cbor_type()? == cbor_event::Type::Special { + assert_eq!(raw.special()?, cbor_event::Special::Break); + break; + } + let (inner_value_elem, inner_value_elem_encoding) = match raw.cbor_type()? { + cbor_event::Type::UnsignedInteger => { + let (x, enc) = raw.unsigned_integer_sz()?; + (x as i64, Some(enc)) } - 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()) + _ => { + let (x, enc) = raw.negative_integer_sz()?; + (x as i64, Some(enc)) } - } - read += 1; + }; + inner_value_arr.push(inner_value_elem); + inner_value_elem_encodings.push(inner_value_elem_encoding); } - read_len.finish()?; - Ok(Self { - plutus_v1, - plutus_v2, - plutus_v3, - encodings: Some(CostModelsEncoding { - len_encoding, - orig_deser_order, - plutus_v1_key_encoding, - plutus_v1_encoding, - plutus_v2_key_encoding, - plutus_v2_encoding, - plutus_v3_key_encoding, - plutus_v3_encoding, - }), - }) - })() - .map_err(|e| e.annotate("CostModels")) + let (inner_value, inner_value_encoding, inner_value_elem_encodings) = ( + inner_value_arr, + inner_value_encoding, + inner_value_elem_encodings, + ); + if inner_table.insert(inner_key, inner_value).is_some() { + return Err(DeserializeFailure::DuplicateKey(Key::Uint(inner_key)).into()); + } + inner_key_encodings.insert(inner_key, inner_key_encoding); + inner_value_encodings.insert( + inner_key, + (inner_value_encoding, inner_value_elem_encodings), + ); + } + let (inner, inner_encoding, inner_key_encodings, inner_value_encodings) = ( + inner_table, + inner_encoding, + inner_key_encodings, + inner_value_encodings, + ); + Ok(Self { + inner, + encodings: Some(CostModelsEncoding { + inner_encoding, + inner_key_encodings, + inner_value_encodings, + }), + }) } } diff --git a/chain/rust/src/plutus/utils.rs b/chain/rust/src/plutus/utils.rs index 86a43d06..ae228c23 100644 --- a/chain/rust/src/plutus/utils.rs +++ b/chain/rust/src/plutus/utils.rs @@ -7,12 +7,12 @@ use crate::json::plutus_datums::{ }; use cbor_event::de::Deserializer; use cbor_event::se::Serializer; +use cml_core::error::*; 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::convert::{TryFrom, TryInto}; use std::io::{BufRead, Seek, Write}; impl serde::Serialize for PlutusData { @@ -326,17 +326,6 @@ impl Deserialize for ConstrPlutusData { } impl CostModels { - pub fn as_map(&self) -> BTreeMap { - let mut map = BTreeMap::new(); - if let Some(v1_costs) = &self.plutus_v1 { - map.insert(Language::PlutusV1, &v1_costs[..]); - } - if let Some(v2_costs) = &self.plutus_v2 { - map.insert(Language::PlutusV1, &v2_costs[..]); - } - map - } - pub(crate) fn language_views_encoding(&self) -> Result, cbor_event::Error> { // ; language views CDDL: // ; { * language => script_integrity_data } @@ -354,52 +343,69 @@ impl CostModels { let mut serializer = Serializer::new_vec(); // as canonical encodings are used, we odn't need to check the keys' bytes encodings // and can order this statically. - serializer.write_map(cbor_event::Len::Len( - if self.plutus_v1.is_some() { 1 } else { 0 } - + if self.plutus_v2.is_some() { 1 } else { 0 }, - ))?; - if let Some(v1_costs) = &self.plutus_v1 { - // For PlutusV1 (language id 0), the language view is the following: - // * the value of costmdls map at key 0 is encoded as an indefinite length - // list and the result is encoded as a bytestring. (our apologies) - // * the language ID tag is also encoded twice. first as a uint then as - // a bytestring. (our apologies) - let v1_key_canonical_bytes = [0]; - serializer.write_bytes(v1_key_canonical_bytes)?; - // Due to a bug in the cardano-node input-output-hk/cardano-ledger-specs/issues/2512 - // we must use indefinite length serialization in this inner bytestring to match it - let mut cost_model_serializer = Serializer::new_vec(); - cost_model_serializer.write_array(cbor_event::Len::Indefinite)?; - for cost in v1_costs { - cost.serialize(&mut cost_model_serializer, true)?; - } - cost_model_serializer.write_special(cbor_event::Special::Break)?; - serializer.write_bytes(cost_model_serializer.finalize())?; - } - if let Some(v2_costs) = &self.plutus_v2 { - // For PlutusV2 (language id 1), the language view is the following: - // * the value of costmdls map at key 1 is encoded as an definite length list. - let v2_key = 1; - serializer.write_unsigned_integer(v2_key)?; - serializer.write_array(cbor_event::Len::Len(v2_costs.len() as u64))?; - for cost in v2_costs { - cost.serialize(&mut serializer, true)?; - } - } - if let Some(v3_costs) = &self.plutus_v3 { - // For PlutusV3 (language id 2), the language view is the following: - // * the value of costmdls map at key 2 is encoded as a definite length list. - let v3_key = 2; - serializer.write_unsigned_integer(v3_key)?; - serializer.write_array(cbor_event::Len::Len(v3_costs.len() as u64))?; - for cost in v3_costs { - cost.serialize(&mut serializer, true)?; + // Due to PlutusV1 bug we can't re-use the generated serialization code + // as it requires it to be encoded as CBOR bytes in CBOR + serializer.write_map(cbor_event::Len::Len(self.inner.len() as u64))?; + for (language, costs) in self.inner.iter() { + match (*language).try_into() { + Ok(Language::PlutusV1) => { + // For PlutusV1 (language id 0), the language view is the following: + // * the value of costmdls map at key 0 is encoded as an indefinite length + // list and the result is encoded as a bytestring. (our apologies) + // * the language ID tag is also encoded twice. first as a uint then as + // a bytestring. (our apologies) + let v1_key_canonical_bytes = [0]; + serializer.write_bytes(v1_key_canonical_bytes)?; + // Due to a bug in the cardano-node input-output-hk/cardano-ledger-specs/issues/2512 + // we must use indefinite length serialization in this inner bytestring to match it + let mut cost_model_serializer = Serializer::new_vec(); + cost_model_serializer.write_array(cbor_event::Len::Indefinite)?; + for cost in costs { + if *cost >= 0 { + cost_model_serializer.write_unsigned_integer(cost.unsigned_abs())?; + } else { + cost_model_serializer.write_negative_integer(*cost)?; + } + } + cost_model_serializer.write_special(cbor_event::Special::Break)?; + serializer.write_bytes(cost_model_serializer.finalize())?; + } + _ => { + // For PlutusV2 (language id 1), the language view is the following: + // * the value of costmdls map at key 1 is encoded as an definite length list. + // For PlutusV3 (language id 2), the language view is the following: + // * the value of costmdls map at key 2 is encoded as a definite length list. + // + // We will assume all other languages also follow this and that the non-canonical + // encoding is just a bug pertaining to Plutus V1 + serializer.write_unsigned_integer(*language)?; + serializer.write_array(cbor_event::Len::Len(costs.len() as u64))?; + for cost in costs { + if *cost >= 0 { + serializer.write_unsigned_integer(cost.unsigned_abs())?; + } else { + serializer.write_negative_integer(*cost)?; + } + } + } } } Ok(serializer.finalize()) } } +impl AsRef>> for CostModels { + fn as_ref(&self) -> &OrderedHashMap> { + &self.inner + } +} + +impl AsMut>> for CostModels { + fn as_mut(&mut self) -> &mut OrderedHashMap> { + &mut self.inner + } +} + /// Version-agnostic Plutus script #[derive(Clone, Debug)] pub enum PlutusScript { @@ -489,6 +495,34 @@ pub fn compute_total_ex_units(redeemers: &[LegacyRedeemer]) -> Result for Language { + type Error = DeserializeError; + + fn try_from(language: u64) -> Result { + match language { + 0 => Ok(Language::PlutusV1), + 1 => Ok(Language::PlutusV2), + 2 => Ok(Language::PlutusV3), + _ => Err(DeserializeFailure::OutOfRange { + found: language as usize, + min: 0, + max: 2, + } + .into()), + } + } +} + +impl From for u64 { + fn from(language: Language) -> u64 { + match language { + Language::PlutusV1 => 0, + Language::PlutusV2 => 1, + Language::PlutusV3 => 2, + } + } +} + #[derive(Clone, Debug, Default, derivative::Derivative)] #[derivative(Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct PlutusMap { @@ -679,12 +713,11 @@ impl Redeemers { #[cfg(test)] mod tests { - use crate::plutus::CostModels; - use cml_core::Int; + use crate::plutus::{CostModels, Language}; #[test] pub fn test_cost_model() { - let arr = vec![ + let v1_costs = vec![ 197209, 0, 1, 1, 396231, 621, 0, 1, 150000, 1000, 0, 1, 150000, 32, 2477736, 29175, 4, 29773, 100, 29773, 100, 29773, 100, 29773, 100, 29773, 100, 29773, 100, 100, 100, 29773, 100, 150000, 32, 150000, 32, 150000, 32, 150000, 1000, 0, 1, 150000, 32, 150000, @@ -697,8 +730,8 @@ mod tests { 1, 150000, 32, 197209, 0, 1, 1, 150000, 32, 150000, 32, 150000, 32, 150000, 32, 150000, 32, 150000, 32, 150000, 32, 3345831, 1, 1, ]; - let mut cms = CostModels::new(); - cms.plutus_v1 = Some(arr.iter().map(|&i| Int::new_uint(i)).collect()); + let mut cms = CostModels::default(); + cms.inner.insert(Language::PlutusV1.into(), v1_costs); assert_eq!( hex::encode(cms.language_views_encoding().unwrap()), "a141005901d59f1a000302590001011a00060bc719026d00011a000249f01903e800011a000249f018201a0025cea81971f70419744d186419744d186419744d186419744d186419744d186419744d18641864186419744d18641a000249f018201a000249f018201a000249f018201a000249f01903e800011a000249f018201a000249f01903e800081a000242201a00067e2318760001011a000249f01903e800081a000249f01a0001b79818f7011a000249f0192710011a0002155e19052e011903e81a000249f01903e8011a000249f018201a000249f018201a000249f0182001011a000249f0011a000249f0041a000194af18f8011a000194af18f8011a0002377c190556011a0002bdea1901f1011a000249f018201a000249f018201a000249f018201a000249f018201a000249f018201a000249f018201a000242201a00067e23187600010119f04c192bd200011a000249f018201a000242201a00067e2318760001011a000242201a00067e2318760001011a0025cea81971f704001a000141bb041a000249f019138800011a000249f018201a000302590001011a000249f018201a000249f018201a000249f018201a000249f018201a000249f018201a000249f018201a000249f018201a00330da70101ff" diff --git a/chain/wasm/src/plutus/mod.rs b/chain/wasm/src/plutus/mod.rs index ccf194fd..33df2ea2 100644 --- a/chain/wasm/src/plutus/mod.rs +++ b/chain/wasm/src/plutus/mod.rs @@ -5,13 +5,26 @@ pub mod utils; use crate::utils::BigInteger; -use super::{IntList, PlutusDataList, SubCoin}; +use super::{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}; +use cml_core_wasm::{impl_wasm_cbor_json_api, impl_wasm_conversions, impl_wasm_map}; pub use utils::{ConstrPlutusData, PlutusMap}; use wasm_bindgen::prelude::{wasm_bindgen, JsError, JsValue}; +impl_wasm_map!( + u64, + Vec, + u64, + Vec, + Vec, + MapU64ToArrI64, + true, + true, + true, + false +); + #[derive(Clone, Debug)] #[wasm_bindgen] pub struct CostModels(cml_chain::plutus::CostModels); @@ -22,32 +35,8 @@ impl_wasm_conversions!(cml_chain::plutus::CostModels, CostModels); #[wasm_bindgen] impl CostModels { - 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 set_plutus_v3(&mut self, plutus_v3: &IntList) { - self.0.plutus_v3 = Some(plutus_v3.clone().into()) - } - - pub fn plutus_v3(&self) -> Option { - self.0.plutus_v3.clone().map(std::convert::Into::into) - } - - pub fn new() -> Self { - Self(cml_chain::plutus::CostModels::new()) + pub fn inner(&self) -> MapU64ToArrI64 { + self.0.inner.clone().into() } } diff --git a/specs/conway/plutus.cddl b/specs/conway/plutus.cddl index f045cfbe..a0b85994 100644 --- a/specs/conway/plutus.cddl +++ b/specs/conway/plutus.cddl @@ -67,8 +67,9 @@ language = 0 ; @name plutus_v1 / 1 ; @name plutus_v2 / 2 ; @name plutus_v3 -cost_models = { - ? 0 : [ 166*166 int ], ; @name plutus_v1 - ? 1 : [ 175*175 int ], ; @name plutus_v2 - ? 2 : [ 233*233 int ], ; @name plutus_v3 -} +cost_models = { * uint => [* int64] } ; @newtype +;cost_models = { +; ? 0 : [ 166*166 int ], ; @name plutus_v1 +; ? 1 : [ 175*175 int ], ; @name plutus_v2 +; ? 2 : [ 233*233 int ], ; @name plutus_v3 +;} From 8999325933c131af8ac474fe8556e585ca39659c Mon Sep 17 00:00:00 2001 From: Enzo Cioppettini <48031343+ecioppettini@users.noreply.github.com> Date: Tue, 25 Jun 2024 13:55:35 -0300 Subject: [PATCH 08/16] wasm-bindgen: upgrade to 0.2.87 and remove serde-deserialize feature (#335) --- chain/rust/Cargo.toml | 2 +- chain/wasm/Cargo.toml | 2 +- cip25/rust/Cargo.toml | 2 +- cip25/wasm/Cargo.toml | 2 +- cip36/wasm/Cargo.toml | 2 +- cml/wasm/Cargo.toml | 2 +- core/rust/Cargo.toml | 2 +- core/wasm/Cargo.toml | 4 ++-- crypto/wasm/Cargo.toml | 2 +- multi-era/rust/Cargo.toml | 4 ++-- multi-era/wasm/Cargo.toml | 4 ++-- 11 files changed, 14 insertions(+), 14 deletions(-) diff --git a/chain/rust/Cargo.toml b/chain/rust/Cargo.toml index d12cb741..981a7d9a 100644 --- a/chain/rust/Cargo.toml +++ b/chain/rust/Cargo.toml @@ -52,7 +52,7 @@ unicode-segmentation = "1.10.1" # wasm #[target.'cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))'.dependencies] -wasm-bindgen = { version = "=0.2.83", features = ["serde-serialize"] } +wasm-bindgen = { version = "0.2.87" } #rand_os = { version = "0.1", features = ["wasm-bindgen"] } #js-sys = "=0.3.59" diff --git a/chain/wasm/Cargo.toml b/chain/wasm/Cargo.toml index 3183820f..beff9882 100644 --- a/chain/wasm/Cargo.toml +++ b/chain/wasm/Cargo.toml @@ -22,7 +22,7 @@ cml-crypto = { path = "../../crypto/rust", version = "5.3.1" } cml-crypto-wasm = { path = "../../crypto/wasm", version = "5.3.1" } cbor_event = "2.4.0" hex = "0.4.0" -wasm-bindgen = { version = "=0.2.83", features = ["serde-serialize"] } +wasm-bindgen = { version = "0.2.87" } linked-hash-map = "0.5.3" serde_json = "1.0.57" serde-wasm-bindgen = "0.4.5" diff --git a/cip25/rust/Cargo.toml b/cip25/rust/Cargo.toml index 6277b682..99b7e507 100644 --- a/cip25/rust/Cargo.toml +++ b/cip25/rust/Cargo.toml @@ -24,4 +24,4 @@ serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.57" thiserror = "1.0.37" # for enums -wasm-bindgen = { version = "=0.2.83", features = ["serde-serialize"] } \ No newline at end of file +wasm-bindgen = { version = "0.2.87" } diff --git a/cip25/wasm/Cargo.toml b/cip25/wasm/Cargo.toml index db03c318..cc62917b 100644 --- a/cip25/wasm/Cargo.toml +++ b/cip25/wasm/Cargo.toml @@ -24,4 +24,4 @@ hex = "0.4.0" linked-hash-map = "0.5.3" serde_json = "1.0.57" serde-wasm-bindgen = "0.4.5" -wasm-bindgen = { version = "=0.2.83", features = ["serde-serialize"] } \ No newline at end of file +wasm-bindgen = { version = "0.2.87" } diff --git a/cip36/wasm/Cargo.toml b/cip36/wasm/Cargo.toml index 6de5fcea..0a83fc26 100644 --- a/cip36/wasm/Cargo.toml +++ b/cip36/wasm/Cargo.toml @@ -23,7 +23,7 @@ cml-core = { path = "../../core/rust", version = "5.3.1" } cml-core-wasm = { path = "../../core/wasm", version = "5.3.1" } cbor_event = "2.2.0" hex = "0.4.0" -wasm-bindgen = { version = "=0.2.83", features = ["serde-serialize"] } +wasm-bindgen = { version = "0.2.87" } linked-hash-map = "0.5.3" serde_json = "1.0.57" serde-wasm-bindgen = "0.4.5" diff --git a/cml/wasm/Cargo.toml b/cml/wasm/Cargo.toml index 15d595ad..42ae2dc2 100644 --- a/cml/wasm/Cargo.toml +++ b/cml/wasm/Cargo.toml @@ -23,4 +23,4 @@ hex = "0.4.0" linked-hash-map = "0.5.3" serde_json = "1.0.57" serde-wasm-bindgen = "0.4.5" -wasm-bindgen = { version = "0.2", features=["serde-serialize"] } \ No newline at end of file +wasm-bindgen = { version = "0.2.87" } diff --git a/core/rust/Cargo.toml b/core/rust/Cargo.toml index d50ea7ac..1954ac5e 100644 --- a/core/rust/Cargo.toml +++ b/core/rust/Cargo.toml @@ -50,7 +50,7 @@ cfg-if = "1" # wasm #[target.'cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))'.dependencies] -wasm-bindgen = { version = "=0.2.83", features = ["serde-serialize"] } +wasm-bindgen = { version = "0.2.87" } #rand_os = { version = "0.1", features = ["wasm-bindgen"] } #js-sys = "=0.3.59" diff --git a/core/wasm/Cargo.toml b/core/wasm/Cargo.toml index 605216ed..58eac743 100644 --- a/core/wasm/Cargo.toml +++ b/core/wasm/Cargo.toml @@ -16,7 +16,7 @@ crate-type = ["cdylib", "rlib"] cml-core = { path = "../rust", version = "5.3.1" } cbor_event = "2.2.0" hex = "0.4.0" -wasm-bindgen = { version = "=0.2.83", features = ["serde-serialize"] } +wasm-bindgen = { version = "0.2.87" } linked-hash-map = "0.5.3" serde_json = "1.0.57" -serde-wasm-bindgen = "0.4.5" \ No newline at end of file +serde-wasm-bindgen = "0.4.5" diff --git a/crypto/wasm/Cargo.toml b/crypto/wasm/Cargo.toml index 39eb864c..9cc87314 100644 --- a/crypto/wasm/Cargo.toml +++ b/crypto/wasm/Cargo.toml @@ -16,6 +16,6 @@ crate-type = ["cdylib", "rlib"] [dependencies] cml-crypto = { path = "../rust", version = "5.3.1" } cbor_event = "2.2.0" -wasm-bindgen = { version = "=0.2.83", features = ["serde-serialize"] } +wasm-bindgen = { version = "0.2.87" } linked-hash-map = "0.5.3" serde_json = "1.0.57" diff --git a/multi-era/rust/Cargo.toml b/multi-era/rust/Cargo.toml index bb5c5e66..3457cc9b 100644 --- a/multi-era/rust/Cargo.toml +++ b/multi-era/rust/Cargo.toml @@ -23,8 +23,8 @@ derivative = "2.2.0" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.57" schemars = "0.8.8" -wasm-bindgen = { version = "0.2", features=["serde-serialize"] } +wasm-bindgen = { version = "0.2.87" } # only for declaring hash types bech32 = "0.7.2" -hex = "0.4.0" \ No newline at end of file +hex = "0.4.0" diff --git a/multi-era/wasm/Cargo.toml b/multi-era/wasm/Cargo.toml index e4c5bedc..7f296d81 100644 --- a/multi-era/wasm/Cargo.toml +++ b/multi-era/wasm/Cargo.toml @@ -26,7 +26,7 @@ hex = "0.4.0" linked-hash-map = "0.5.3" serde_json = "1.0.57" serde-wasm-bindgen = "0.4.5" -wasm-bindgen = { version = "0.2", features=["serde-serialize"] } +wasm-bindgen = { version = "0.2.87" } # not actual multi-era dependencies but we re-export these for the wasm builds cml-cip25-wasm = { path = "../../cip25/wasm", version = "5.3.1" } -cml-cip36-wasm = { path = "../../cip36/wasm", version = "5.3.1" } \ No newline at end of file +cml-cip36-wasm = { path = "../../cip36/wasm", version = "5.3.1" } From 429c8ecfdfe1aca250853acd6cb4521b7fe3a7a5 Mon Sep 17 00:00:00 2001 From: rooooooooob Date: Wed, 10 Jul 2024 15:15:15 +0900 Subject: [PATCH 09/16] Add WASM getters to TransactionUnspentOutput (#341) Fixes #338 --- chain/wasm/src/builders/tx_builder.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/chain/wasm/src/builders/tx_builder.rs b/chain/wasm/src/builders/tx_builder.rs index 1d084053..1d0e73f4 100644 --- a/chain/wasm/src/builders/tx_builder.rs +++ b/chain/wasm/src/builders/tx_builder.rs @@ -40,6 +40,14 @@ impl TransactionUnspentOutput { ) .into() } + + pub fn input(&self) -> TransactionInput { + self.0.input.clone().into() + } + + pub fn output(&self) -> TransactionOutput { + self.0.output.clone().into() + } } #[wasm_bindgen] From 8429a73e51e99e740fb6c35ec03a9618e06c89da Mon Sep 17 00:00:00 2001 From: rooooooooob Date: Wed, 10 Jul 2024 15:17:35 +0900 Subject: [PATCH 10/16] Add documentation + fix acronym names (#339) * Add documentation + fix acronym names Using dcSpark/cddl-codegen#218 and dcSpark/cddl-codegen#238 Also renames some cert fields to be clear as `coin` was not very helpful. * update multi-era crates too * clippy fix --- chain/rust/src/auxdata/cbor_encodings.rs | 2 +- chain/rust/src/auxdata/mod.rs | 14 +- chain/rust/src/auxdata/serialization.rs | 18 +- chain/rust/src/auxdata/utils.rs | 4 +- chain/rust/src/certs/cbor_encodings.rs | 16 +- chain/rust/src/certs/mod.rs | 256 ++++++++++-------- chain/rust/src/certs/serialization.rs | 180 ++++++------ chain/rust/src/governance/mod.rs | 22 +- chain/rust/src/governance/serialization.rs | 17 +- chain/rust/src/transaction/mod.rs | 4 + chain/wasm/json-gen/src/lib.rs | 2 +- chain/wasm/src/auxdata/mod.rs | 24 +- chain/wasm/src/certs/mod.rs | 138 +++++----- chain/wasm/src/governance/mod.rs | 24 +- chain/wasm/src/transaction/mod.rs | 2 + core/rust/Cargo.toml | 6 +- multi-era/rust/src/allegra/mod.rs | 12 +- multi-era/rust/src/allegra/serialization.rs | 10 +- multi-era/rust/src/allegra/utils.rs | 2 +- multi-era/rust/src/alonzo/mod.rs | 8 +- multi-era/rust/src/alonzo/serialization.rs | 2 +- multi-era/rust/src/alonzo/utils.rs | 2 +- multi-era/rust/src/babbage/mod.rs | 8 +- multi-era/rust/src/babbage/serialization.rs | 6 +- multi-era/rust/src/babbage/utils.rs | 2 +- multi-era/rust/src/shelley/cbor_encodings.rs | 6 +- multi-era/rust/src/shelley/mod.rs | 60 ++-- multi-era/rust/src/shelley/serialization.rs | 42 +-- multi-era/rust/src/shelley/utils.rs | 6 +- multi-era/rust/src/utils.rs | 2 +- multi-era/wasm/json-gen/src/lib.rs | 2 +- multi-era/wasm/src/allegra/mod.rs | 18 +- multi-era/wasm/src/alonzo/mod.rs | 14 +- multi-era/wasm/src/babbage/mod.rs | 16 +- multi-era/wasm/src/shelley/mod.rs | 42 +-- specs/conway/auxdata.cddl | 4 +- specs/conway/certs.cddl | 68 +++-- specs/conway/governance.cddl | 4 +- specs/conway/plutus.cddl | 11 +- specs/conway/transaction.cddl | 22 +- .../cml_chain/address.cddl | 0 .../cml_chain/assets.cddl | 0 .../cml_chain/auxdata.cddl | 2 +- .../cml_chain/block.cddl | 0 .../cml_chain/byron.cddl | 0 .../cml_chain/certs.cddl | 0 .../cml_chain/crypto.cddl | 0 .../cml_chain/mod.cddl | 0 .../cml_chain/plutus.cddl | 0 .../cml_chain/transaction.cddl | 0 specs/multiera/allegra/mod.cddl | 2 +- specs/multiera/alonzo/mod.cddl | 2 +- specs/multiera/babbage/mod.cddl | 2 +- specs/multiera/shelley/mod.cddl | 6 +- 54 files changed, 583 insertions(+), 529 deletions(-) rename specs/multiera/{ => _CDDL_CODEGEN_EXTERN_DEPS_DIR_}/cml_chain/address.cddl (100%) rename specs/multiera/{ => _CDDL_CODEGEN_EXTERN_DEPS_DIR_}/cml_chain/assets.cddl (100%) rename specs/multiera/{ => _CDDL_CODEGEN_EXTERN_DEPS_DIR_}/cml_chain/auxdata.cddl (62%) rename specs/multiera/{ => _CDDL_CODEGEN_EXTERN_DEPS_DIR_}/cml_chain/block.cddl (100%) rename specs/multiera/{ => _CDDL_CODEGEN_EXTERN_DEPS_DIR_}/cml_chain/byron.cddl (100%) rename specs/multiera/{ => _CDDL_CODEGEN_EXTERN_DEPS_DIR_}/cml_chain/certs.cddl (100%) rename specs/multiera/{ => _CDDL_CODEGEN_EXTERN_DEPS_DIR_}/cml_chain/crypto.cddl (100%) rename specs/multiera/{ => _CDDL_CODEGEN_EXTERN_DEPS_DIR_}/cml_chain/mod.cddl (100%) rename specs/multiera/{ => _CDDL_CODEGEN_EXTERN_DEPS_DIR_}/cml_chain/plutus.cddl (100%) rename specs/multiera/{ => _CDDL_CODEGEN_EXTERN_DEPS_DIR_}/cml_chain/transaction.cddl (100%) diff --git a/chain/rust/src/auxdata/cbor_encodings.rs b/chain/rust/src/auxdata/cbor_encodings.rs index 1dd5616c..d0775878 100644 --- a/chain/rust/src/auxdata/cbor_encodings.rs +++ b/chain/rust/src/auxdata/cbor_encodings.rs @@ -20,7 +20,7 @@ pub struct ConwayFormatAuxDataEncoding { } #[derive(Clone, Debug, Default)] -pub struct ShelleyMaFormatAuxDataEncoding { +pub struct ShelleyMAFormatAuxDataEncoding { pub len_encoding: LenEncoding, pub auxiliary_scripts_encoding: LenEncoding, } diff --git a/chain/rust/src/auxdata/mod.rs b/chain/rust/src/auxdata/mod.rs index ace3e65b..fc024711 100644 --- a/chain/rust/src/auxdata/mod.rs +++ b/chain/rust/src/auxdata/mod.rs @@ -8,14 +8,14 @@ pub mod utils; use crate::plutus::{PlutusV1Script, PlutusV2Script, PlutusV3Script}; use crate::transaction::NativeScript; -use cbor_encodings::{ConwayFormatAuxDataEncoding, ShelleyMaFormatAuxDataEncoding}; +use cbor_encodings::{ConwayFormatAuxDataEncoding, ShelleyMAFormatAuxDataEncoding}; pub use metadata::*; #[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] pub enum AuxiliaryData { Shelley(ShelleyFormatAuxData), - ShelleyMA(ShelleyMaFormatAuxData), + ShelleyMA(ShelleyMAFormatAuxData), Conway(ConwayFormatAuxData), } @@ -24,8 +24,8 @@ impl AuxiliaryData { Self::Shelley(shelley) } - pub fn new_shelley_m_a(shelley_m_a: ShelleyMaFormatAuxData) -> Self { - Self::ShelleyMA(shelley_m_a) + pub fn new_shelley_ma(shelley_ma: ShelleyMAFormatAuxData) -> Self { + Self::ShelleyMA(shelley_ma) } pub fn new_conway(conway: ConwayFormatAuxData) -> Self { @@ -66,14 +66,14 @@ impl Default for ConwayFormatAuxData { pub type ShelleyFormatAuxData = Metadata; #[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] -pub struct ShelleyMaFormatAuxData { +pub struct ShelleyMAFormatAuxData { pub transaction_metadata: Metadata, pub auxiliary_scripts: Vec, #[serde(skip)] - pub encodings: Option, + pub encodings: Option, } -impl ShelleyMaFormatAuxData { +impl ShelleyMAFormatAuxData { pub fn new(transaction_metadata: Metadata, auxiliary_scripts: Vec) -> Self { Self { transaction_metadata, diff --git a/chain/rust/src/auxdata/serialization.rs b/chain/rust/src/auxdata/serialization.rs index a54ee397..8ec38f50 100644 --- a/chain/rust/src/auxdata/serialization.rs +++ b/chain/rust/src/auxdata/serialization.rs @@ -19,8 +19,8 @@ impl Serialize for AuxiliaryData { ) -> cbor_event::Result<&'se mut Serializer> { match self { AuxiliaryData::Shelley(shelley) => shelley.serialize(serializer, force_canonical), - AuxiliaryData::ShelleyMA(shelley_m_a) => { - shelley_m_a.serialize(serializer, force_canonical) + AuxiliaryData::ShelleyMA(shelley_ma) => { + shelley_ma.serialize(serializer, force_canonical) } AuxiliaryData::Conway(conway) => conway.serialize(serializer, force_canonical), } @@ -43,9 +43,9 @@ impl Deserialize for AuxiliaryData { } }; let deser_variant: Result<_, DeserializeError> = - ShelleyMaFormatAuxData::deserialize(raw); + ShelleyMAFormatAuxData::deserialize(raw); match deser_variant { - Ok(shelley_m_a) => return Ok(Self::ShelleyMA(shelley_m_a)), + Ok(shelley_ma) => return Ok(Self::ShelleyMA(shelley_ma)), Err(e) => { errs.push(e.annotate("ShelleyMA")); raw.as_mut_ref() @@ -513,7 +513,7 @@ impl Deserialize for ConwayFormatAuxData { } } -impl Serialize for ShelleyMaFormatAuxData { +impl Serialize for ShelleyMAFormatAuxData { fn serialize<'se, W: Write>( &self, serializer: &'se mut Serializer, @@ -551,7 +551,7 @@ impl Serialize for ShelleyMaFormatAuxData { } } -impl Deserialize for ShelleyMaFormatAuxData { +impl Deserialize for ShelleyMAFormatAuxData { fn deserialize(raw: &mut Deserializer) -> Result { let len = raw.array_sz()?; let len_encoding: LenEncoding = len.into(); @@ -586,15 +586,15 @@ impl Deserialize for ShelleyMaFormatAuxData { _ => return Err(DeserializeFailure::EndingBreakMissing.into()), }, } - Ok(ShelleyMaFormatAuxData { + Ok(ShelleyMAFormatAuxData { transaction_metadata, auxiliary_scripts, - encodings: Some(ShelleyMaFormatAuxDataEncoding { + encodings: Some(ShelleyMAFormatAuxDataEncoding { len_encoding, auxiliary_scripts_encoding, }), }) })() - .map_err(|e| e.annotate("ShelleyMaFormatAuxData")) + .map_err(|e| e.annotate("ShelleyMAFormatAuxData")) } } diff --git a/chain/rust/src/auxdata/utils.rs b/chain/rust/src/auxdata/utils.rs index ffaae856..b31d8925 100644 --- a/chain/rust/src/auxdata/utils.rs +++ b/chain/rust/src/auxdata/utils.rs @@ -5,7 +5,7 @@ use crate::{ transaction::NativeScript, }; -use super::{AuxiliaryData, ConwayFormatAuxData, ShelleyMaFormatAuxData}; +use super::{AuxiliaryData, ConwayFormatAuxData, ShelleyMAFormatAuxData}; impl AuxiliaryData { pub fn new() -> Self { @@ -81,7 +81,7 @@ impl AuxiliaryData { pub fn add_native_scripts(&mut self, scripts: Vec) { match self { Self::Shelley(shelley) => { - *self = Self::ShelleyMA(ShelleyMaFormatAuxData::new(shelley.clone(), scripts)); + *self = Self::ShelleyMA(ShelleyMAFormatAuxData::new(shelley.clone(), scripts)); } Self::ShelleyMA(shelley_ma) => { shelley_ma.auxiliary_scripts.extend(scripts); diff --git a/chain/rust/src/certs/cbor_encodings.rs b/chain/rust/src/certs/cbor_encodings.rs index f902ce73..bc1b27e9 100644 --- a/chain/rust/src/certs/cbor_encodings.rs +++ b/chain/rust/src/certs/cbor_encodings.rs @@ -10,7 +10,7 @@ pub struct AuthCommitteeHotCertEncoding { } #[derive(Clone, Debug, Default)] -pub struct DnsNameEncoding { +pub struct DNSNameEncoding { pub inner_encoding: StringEncoding, } @@ -64,14 +64,14 @@ pub struct PoolRetirementEncoding { pub struct RegCertEncoding { pub len_encoding: LenEncoding, pub tag_encoding: Option, - pub coin_encoding: Option, + pub deposit_encoding: Option, } #[derive(Clone, Debug, Default)] pub struct RegDrepCertEncoding { pub len_encoding: LenEncoding, pub index_0_encoding: Option, - pub coin_encoding: Option, + pub deposit_encoding: Option, } #[derive(Clone, Debug, Default)] @@ -112,7 +112,7 @@ pub struct StakeRegDelegCertEncoding { pub len_encoding: LenEncoding, pub tag_encoding: Option, pub pool_encoding: StringEncoding, - pub coin_encoding: Option, + pub deposit_encoding: Option, } #[derive(Clone, Debug, Default)] @@ -133,21 +133,21 @@ pub struct StakeVoteRegDelegCertEncoding { pub len_encoding: LenEncoding, pub tag_encoding: Option, pub pool_encoding: StringEncoding, - pub coin_encoding: Option, + pub deposit_encoding: Option, } #[derive(Clone, Debug, Default)] pub struct UnregCertEncoding { pub len_encoding: LenEncoding, pub tag_encoding: Option, - pub coin_encoding: Option, + pub deposit_encoding: Option, } #[derive(Clone, Debug, Default)] pub struct UnregDrepCertEncoding { pub len_encoding: LenEncoding, pub index_0_encoding: Option, - pub coin_encoding: Option, + pub deposit_encoding: Option, } #[derive(Clone, Debug, Default)] @@ -171,5 +171,5 @@ pub struct VoteDelegCertEncoding { pub struct VoteRegDelegCertEncoding { pub len_encoding: LenEncoding, pub tag_encoding: Option, - pub coin_encoding: Option, + pub deposit_encoding: Option, } diff --git a/chain/rust/src/certs/mod.rs b/chain/rust/src/certs/mod.rs index e81693e5..28fc69c9 100644 --- a/chain/rust/src/certs/mod.rs +++ b/chain/rust/src/certs/mod.rs @@ -10,7 +10,7 @@ use crate::address::RewardAccount; use crate::crypto::{Ed25519KeyHash, PoolMetadataHash, ScriptHash, VRFKeyHash}; use crate::governance::Anchor; use cbor_encodings::{ - AuthCommitteeHotCertEncoding, DnsNameEncoding, Ipv4Encoding, Ipv6Encoding, + AuthCommitteeHotCertEncoding, DNSNameEncoding, Ipv4Encoding, Ipv6Encoding, MultiHostNameEncoding, PoolMetadataEncoding, PoolParamsEncoding, PoolRegistrationEncoding, PoolRetirementEncoding, RegCertEncoding, RegDrepCertEncoding, ResignCommitteeColdCertEncoding, SingleHostAddrEncoding, SingleHostNameEncoding, StakeDelegationEncoding, @@ -50,17 +50,27 @@ impl AuthCommitteeHotCert { #[allow(clippy::large_enum_variant)] #[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] pub enum Certificate { + /// Will be deprecated in the next era. Use RegCert instead which takes an explicit deposit amount, as that can change. StakeRegistration(StakeRegistration), + /// Will be deprecated in the next era. Use UnregCert instead which takes an explicit deposit amount, as that can change. StakeDeregistration(StakeDeregistration), + /// Delegate to a take pool only StakeDelegation(StakeDelegation), PoolRegistration(PoolRegistration), PoolRetirement(PoolRetirement), + /// Registers a stake credential. RegCert(RegCert), + /// Unregisters a stake credential. UnregCert(UnregCert), + /// Delegate to a DRep for voting only VoteDelegCert(VoteDelegCert), + /// Delegate to a stake pool and a DRep StakeVoteDelegCert(StakeVoteDelegCert), + /// Register a stake credential and delegate to a pool in a single cert StakeRegDelegCert(StakeRegDelegCert), + /// Register a stake credential and delegate to a DRep in a single cert VoteRegDelegCert(VoteRegDelegCert), + /// Register a stake credential and delegate to a pool and a DRep in a single cert StakeVoteRegDelegCert(StakeVoteRegDelegCert), AuthCommitteeHotCert(AuthCommitteeHotCert), ResignCommitteeColdCert(ResignCommitteeColdCert), @@ -70,14 +80,17 @@ pub enum Certificate { } impl Certificate { + /// Will be deprecated in the next era. Use RegCert instead which takes an explicit deposit amount, as that can change. pub fn new_stake_registration(stake_credential: StakeCredential) -> Self { Self::StakeRegistration(StakeRegistration::new(stake_credential)) } + /// Will be deprecated in the next era. Use UnregCert instead which takes an explicit deposit amount, as that can change. pub fn new_stake_deregistration(stake_credential: StakeCredential) -> Self { Self::StakeDeregistration(StakeDeregistration::new(stake_credential)) } + /// Delegate to a take pool only pub fn new_stake_delegation(stake_credential: StakeCredential, pool: Ed25519KeyHash) -> Self { Self::StakeDelegation(StakeDelegation::new(stake_credential, pool)) } @@ -90,18 +103,22 @@ impl Certificate { Self::PoolRetirement(PoolRetirement::new(pool, epoch)) } - pub fn new_reg_cert(stake_credential: StakeCredential, coin: Coin) -> Self { - Self::RegCert(RegCert::new(stake_credential, coin)) + /// Registers a stake credential. + pub fn new_reg_cert(stake_credential: StakeCredential, deposit: Coin) -> Self { + Self::RegCert(RegCert::new(stake_credential, deposit)) } - pub fn new_unreg_cert(stake_credential: StakeCredential, coin: Coin) -> Self { - Self::UnregCert(UnregCert::new(stake_credential, coin)) + /// Unregisters a stake credential. + pub fn new_unreg_cert(stake_credential: StakeCredential, deposit: Coin) -> Self { + Self::UnregCert(UnregCert::new(stake_credential, deposit)) } + /// Delegate to a DRep for voting only pub fn new_vote_deleg_cert(stake_credential: StakeCredential, d_rep: DRep) -> Self { Self::VoteDelegCert(VoteDelegCert::new(stake_credential, d_rep)) } + /// Delegate to a stake pool and a DRep pub fn new_stake_vote_deleg_cert( stake_credential: StakeCredential, pool: Ed25519KeyHash, @@ -110,33 +127,36 @@ impl Certificate { Self::StakeVoteDelegCert(StakeVoteDelegCert::new(stake_credential, pool, d_rep)) } + /// Register a stake credential and delegate to a pool in a single cert pub fn new_stake_reg_deleg_cert( stake_credential: StakeCredential, pool: Ed25519KeyHash, - coin: Coin, + deposit: Coin, ) -> Self { - Self::StakeRegDelegCert(StakeRegDelegCert::new(stake_credential, pool, coin)) + Self::StakeRegDelegCert(StakeRegDelegCert::new(stake_credential, pool, deposit)) } + /// Register a stake credential and delegate to a DRep in a single cert pub fn new_vote_reg_deleg_cert( stake_credential: StakeCredential, d_rep: DRep, - coin: Coin, + deposit: Coin, ) -> Self { - Self::VoteRegDelegCert(VoteRegDelegCert::new(stake_credential, d_rep, coin)) + Self::VoteRegDelegCert(VoteRegDelegCert::new(stake_credential, d_rep, deposit)) } + /// Register a stake credential and delegate to a pool and a DRep in a single cert pub fn new_stake_vote_reg_deleg_cert( stake_credential: StakeCredential, pool: Ed25519KeyHash, d_rep: DRep, - coin: Coin, + deposit: Coin, ) -> Self { Self::StakeVoteRegDelegCert(StakeVoteRegDelegCert::new( stake_credential, pool, d_rep, - coin, + deposit, )) } @@ -162,14 +182,14 @@ impl Certificate { pub fn new_reg_drep_cert( drep_credential: DrepCredential, - coin: Coin, + deposit: Coin, anchor: Option, ) -> Self { - Self::RegDrepCert(RegDrepCert::new(drep_credential, coin, anchor)) + Self::RegDrepCert(RegDrepCert::new(drep_credential, deposit, anchor)) } - pub fn new_unreg_drep_cert(drep_credential: DrepCredential, coin: Coin) -> Self { - Self::UnregDrepCert(UnregDrepCert::new(drep_credential, coin)) + pub fn new_unreg_drep_cert(drep_credential: DrepCredential, deposit: Coin) -> Self { + Self::UnregDrepCert(UnregDrepCert::new(drep_credential, deposit)) } pub fn new_update_drep_cert(drep_credential: DrepCredential, anchor: Option) -> Self { @@ -268,6 +288,78 @@ impl Credential { } } +#[derive(Clone, Debug)] +pub struct DNSName { + pub inner: String, + pub encodings: Option, +} + +impl DNSName { + pub fn get(&self) -> &String { + &self.inner + } + + pub fn new(inner: String) -> Result { + if inner.len() > 128 { + return Err(DeserializeError::new( + "DNSName", + DeserializeFailure::RangeCheck { + found: inner.len() as isize, + min: Some(0), + max: Some(128), + }, + )); + } + Ok(Self { + inner, + encodings: None, + }) + } +} + +impl TryFrom for DNSName { + type Error = DeserializeError; + + fn try_from(inner: String) -> Result { + DNSName::new(inner) + } +} + +impl serde::Serialize for DNSName { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + self.inner.serialize(serializer) + } +} + +impl<'de> serde::de::Deserialize<'de> for DNSName { + 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 DNSName") + }) + } +} + +impl schemars::JsonSchema for DNSName { + fn schema_name() -> String { + String::from("DNSName") + } + + fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema { + String::json_schema(gen) + } + + fn is_referenceable() -> bool { + String::is_referenceable() + } +} + #[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] pub enum DRep { Key { @@ -336,78 +428,6 @@ impl DRep { } } -#[derive(Clone, Debug)] -pub struct DnsName { - pub inner: String, - pub encodings: Option, -} - -impl DnsName { - pub fn get(&self) -> &String { - &self.inner - } - - pub fn new(inner: String) -> Result { - if inner.len() > 128 { - return Err(DeserializeError::new( - "DnsName", - DeserializeFailure::RangeCheck { - found: inner.len() as isize, - min: Some(0), - max: Some(128), - }, - )); - } - Ok(Self { - inner, - encodings: None, - }) - } -} - -impl TryFrom for DnsName { - type Error = DeserializeError; - - fn try_from(inner: String) -> Result { - DnsName::new(inner) - } -} - -impl serde::Serialize for DnsName { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - self.inner.serialize(serializer) - } -} - -impl<'de> serde::de::Deserialize<'de> for DnsName { - 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 DnsName") - }) - } -} - -impl schemars::JsonSchema for DnsName { - fn schema_name() -> String { - String::from("DnsName") - } - - fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema { - String::json_schema(gen) - } - - fn is_referenceable() -> bool { - String::is_referenceable() - } -} - pub type DrepCredential = Credential; #[derive(Clone, Debug)] @@ -498,13 +518,15 @@ impl From for Vec { #[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] pub struct MultiHostName { - pub dns_name: DnsName, + /// A SRV DNS record + pub dns_name: DNSName, #[serde(skip)] pub encodings: Option, } impl MultiHostName { - pub fn new(dns_name: DnsName) -> Self { + /// * `dns_name` - A SRV DNS record + pub fn new(dns_name: DNSName) -> Self { Self { dns_name, encodings: None, @@ -610,16 +632,16 @@ impl PoolRetirement { #[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] pub struct RegCert { pub stake_credential: StakeCredential, - pub coin: Coin, + pub deposit: Coin, #[serde(skip)] pub encodings: Option, } impl RegCert { - pub fn new(stake_credential: StakeCredential, coin: Coin) -> Self { + pub fn new(stake_credential: StakeCredential, deposit: Coin) -> Self { Self { stake_credential, - coin, + deposit, encodings: None, } } @@ -628,17 +650,17 @@ impl RegCert { #[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] pub struct RegDrepCert { pub drep_credential: DrepCredential, - pub coin: Coin, + pub deposit: Coin, pub anchor: Option, #[serde(skip)] pub encodings: Option, } impl RegDrepCert { - pub fn new(drep_credential: DrepCredential, coin: Coin, anchor: Option) -> Self { + pub fn new(drep_credential: DrepCredential, deposit: Coin, anchor: Option) -> Self { Self { drep_credential, - coin, + deposit, anchor, encodings: None, } @@ -661,11 +683,11 @@ impl Relay { Self::SingleHostAddr(SingleHostAddr::new(port, ipv4, ipv6)) } - pub fn new_single_host_name(port: Option, dns_name: DnsName) -> Self { + pub fn new_single_host_name(port: Option, dns_name: DNSName) -> Self { Self::SingleHostName(SingleHostName::new(port, dns_name)) } - pub fn new_multi_host_name(dns_name: DnsName) -> Self { + pub fn new_multi_host_name(dns_name: DNSName) -> Self { Self::MultiHostName(MultiHostName::new(dns_name)) } } @@ -711,13 +733,15 @@ impl SingleHostAddr { #[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] pub struct SingleHostName { pub port: Option, - pub dns_name: DnsName, + /// An A or AAAA DNS record + pub dns_name: DNSName, #[serde(skip)] pub encodings: Option, } impl SingleHostName { - pub fn new(port: Option, dns_name: DnsName) -> Self { + /// * `dns_name` - An A or AAAA DNS record + pub fn new(port: Option, dns_name: DNSName) -> Self { Self { port, dns_name, @@ -766,17 +790,17 @@ impl StakeDeregistration { pub struct StakeRegDelegCert { pub stake_credential: StakeCredential, pub pool: Ed25519KeyHash, - pub coin: Coin, + pub deposit: Coin, #[serde(skip)] pub encodings: Option, } impl StakeRegDelegCert { - pub fn new(stake_credential: StakeCredential, pool: Ed25519KeyHash, coin: Coin) -> Self { + pub fn new(stake_credential: StakeCredential, pool: Ed25519KeyHash, deposit: Coin) -> Self { Self { stake_credential, pool, - coin, + deposit, encodings: None, } } @@ -823,7 +847,7 @@ pub struct StakeVoteRegDelegCert { pub stake_credential: StakeCredential, pub pool: Ed25519KeyHash, pub d_rep: DRep, - pub coin: Coin, + pub deposit: Coin, #[serde(skip)] pub encodings: Option, } @@ -833,20 +857,20 @@ impl StakeVoteRegDelegCert { stake_credential: StakeCredential, pool: Ed25519KeyHash, d_rep: DRep, - coin: Coin, + deposit: Coin, ) -> Self { Self { stake_credential, pool, d_rep, - coin, + deposit, encodings: None, } } } -impl From for String { - fn from(wrapper: DnsName) -> Self { +impl From for String { + fn from(wrapper: DNSName) -> Self { wrapper.inner } } @@ -860,16 +884,16 @@ impl From for String { #[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] pub struct UnregCert { pub stake_credential: StakeCredential, - pub coin: Coin, + pub deposit: Coin, #[serde(skip)] pub encodings: Option, } impl UnregCert { - pub fn new(stake_credential: StakeCredential, coin: Coin) -> Self { + pub fn new(stake_credential: StakeCredential, deposit: Coin) -> Self { Self { stake_credential, - coin, + deposit, encodings: None, } } @@ -878,16 +902,16 @@ impl UnregCert { #[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] pub struct UnregDrepCert { pub drep_credential: DrepCredential, - pub coin: Coin, + pub deposit: Coin, #[serde(skip)] pub encodings: Option, } impl UnregDrepCert { - pub fn new(drep_credential: DrepCredential, coin: Coin) -> Self { + pub fn new(drep_credential: DrepCredential, deposit: Coin) -> Self { Self { drep_credential, - coin, + deposit, encodings: None, } } @@ -1005,17 +1029,17 @@ impl VoteDelegCert { pub struct VoteRegDelegCert { pub stake_credential: StakeCredential, pub d_rep: DRep, - pub coin: Coin, + pub deposit: Coin, #[serde(skip)] pub encodings: Option, } impl VoteRegDelegCert { - pub fn new(stake_credential: StakeCredential, d_rep: DRep, coin: Coin) -> Self { + pub fn new(stake_credential: StakeCredential, d_rep: DRep, deposit: Coin) -> Self { Self { stake_credential, d_rep, - coin, + deposit, encodings: None, } } diff --git a/chain/rust/src/certs/serialization.rs b/chain/rust/src/certs/serialization.rs index 17cb8f13..754b1f58 100644 --- a/chain/rust/src/certs/serialization.rs +++ b/chain/rust/src/certs/serialization.rs @@ -752,6 +752,45 @@ impl Deserialize for Credential { } } +impl Serialize for DNSName { + 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 DNSName { + fn deserialize(raw: &mut Deserializer) -> Result { + let (inner, inner_encoding) = raw + .text_sz() + .map(|(s, enc)| (s, StringEncoding::from(enc)))?; + if inner.len() > 128 { + return Err(DeserializeError::new( + "DNSName", + DeserializeFailure::RangeCheck { + found: inner.len() as isize, + min: Some(0), + max: Some(128), + }, + )); + } + Ok(Self { + inner, + encodings: Some(DNSNameEncoding { inner_encoding }), + }) + } +} + impl Serialize for DRep { fn serialize<'se, W: Write>( &self, @@ -1009,45 +1048,6 @@ impl Deserialize for DRep { } } -impl Serialize for DnsName { - 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 DnsName { - fn deserialize(raw: &mut Deserializer) -> Result { - let (inner, inner_encoding) = raw - .text_sz() - .map(|(s, enc)| (s, StringEncoding::from(enc)))?; - if inner.len() > 128 { - return Err(DeserializeError::new( - "DnsName", - DeserializeFailure::RangeCheck { - found: inner.len() as isize, - min: Some(0), - max: Some(128), - }, - )); - } - Ok(Self { - inner, - encodings: Some(DnsNameEncoding { inner_encoding }), - }) - } -} - impl Serialize for Ipv4 { fn serialize<'se, W: Write>( &self, @@ -1208,7 +1208,7 @@ impl DeserializeEmbeddedGroup for MultiHostName { })() .map_err(|e| e.annotate("tag"))?; let dns_name = - DnsName::deserialize(raw).map_err(|e: DeserializeError| e.annotate("dns_name"))?; + DNSName::deserialize(raw).map_err(|e: DeserializeError| e.annotate("dns_name"))?; Ok(MultiHostName { dns_name, encodings: Some(MultiHostNameEncoding { @@ -1760,12 +1760,12 @@ impl SerializeEmbeddedGroup for RegCert { self.stake_credential .serialize(serializer, force_canonical)?; serializer.write_unsigned_integer_sz( - self.coin, + self.deposit, fit_sz( - self.coin, + self.deposit, self.encodings .as_ref() - .map(|encs| encs.coin_encoding) + .map(|encs| encs.deposit_encoding) .unwrap_or_default(), force_canonical, ), @@ -1818,18 +1818,18 @@ impl DeserializeEmbeddedGroup for RegCert { .map_err(|e| e.annotate("tag"))?; let stake_credential = Credential::deserialize(raw) .map_err(|e: DeserializeError| e.annotate("stake_credential"))?; - let (coin, coin_encoding) = raw + let (deposit, deposit_encoding) = raw .unsigned_integer_sz() .map_err(Into::::into) .map(|(x, enc)| (x, Some(enc))) - .map_err(|e: DeserializeError| e.annotate("coin"))?; + .map_err(|e: DeserializeError| e.annotate("deposit"))?; Ok(RegCert { stake_credential, - coin, + deposit, encodings: Some(RegCertEncoding { len_encoding, tag_encoding, - coin_encoding, + deposit_encoding, }), }) })() @@ -1874,12 +1874,12 @@ impl SerializeEmbeddedGroup for RegDrepCert { self.drep_credential .serialize(serializer, force_canonical)?; serializer.write_unsigned_integer_sz( - self.coin, + self.deposit, fit_sz( - self.coin, + self.deposit, self.encodings .as_ref() - .map(|encs| encs.coin_encoding) + .map(|encs| encs.deposit_encoding) .unwrap_or_default(), force_canonical, ), @@ -1936,11 +1936,11 @@ impl DeserializeEmbeddedGroup for RegDrepCert { .map_err(|e| e.annotate("index_0"))?; let drep_credential = Credential::deserialize(raw) .map_err(|e: DeserializeError| e.annotate("drep_credential"))?; - let (coin, coin_encoding) = raw + let (deposit, deposit_encoding) = raw .unsigned_integer_sz() .map_err(Into::::into) .map(|(x, enc)| (x, Some(enc))) - .map_err(|e: DeserializeError| e.annotate("coin"))?; + .map_err(|e: DeserializeError| e.annotate("deposit"))?; let anchor = (|| -> Result<_, DeserializeError> { Ok(match raw.cbor_type()? != cbor_event::Type::Special { true => Some(Anchor::deserialize(raw)?), @@ -1955,12 +1955,12 @@ impl DeserializeEmbeddedGroup for RegDrepCert { .map_err(|e| e.annotate("anchor"))?; Ok(RegDrepCert { drep_credential, - coin, + deposit, anchor, encodings: Some(RegDrepCertEncoding { len_encoding, index_0_encoding, - coin_encoding, + deposit_encoding, }), }) })() @@ -2454,7 +2454,7 @@ impl DeserializeEmbeddedGroup for SingleHostName { })() .map_err(|e| e.annotate("port"))?; let dns_name = - DnsName::deserialize(raw).map_err(|e: DeserializeError| e.annotate("dns_name"))?; + DNSName::deserialize(raw).map_err(|e: DeserializeError| e.annotate("dns_name"))?; Ok(SingleHostName { port, dns_name, @@ -2725,12 +2725,12 @@ impl SerializeEmbeddedGroup for StakeRegDelegCert { .to_str_len_sz(self.pool.to_raw_bytes().len() as u64, force_canonical), )?; serializer.write_unsigned_integer_sz( - self.coin, + self.deposit, fit_sz( - self.coin, + self.deposit, self.encodings .as_ref() - .map(|encs| encs.coin_encoding) + .map(|encs| encs.deposit_encoding) .unwrap_or_default(), force_canonical, ), @@ -2792,20 +2792,20 @@ impl DeserializeEmbeddedGroup for StakeRegDelegCert { .map_err(|e| DeserializeFailure::InvalidStructure(Box::new(e)).into()) }) .map_err(|e: DeserializeError| e.annotate("pool"))?; - let (coin, coin_encoding) = raw + let (deposit, deposit_encoding) = raw .unsigned_integer_sz() .map_err(Into::::into) .map(|(x, enc)| (x, Some(enc))) - .map_err(|e: DeserializeError| e.annotate("coin"))?; + .map_err(|e: DeserializeError| e.annotate("deposit"))?; Ok(StakeRegDelegCert { stake_credential, pool, - coin, + deposit, encodings: Some(StakeRegDelegCertEncoding { len_encoding, tag_encoding, pool_encoding, - coin_encoding, + deposit_encoding, }), }) })() @@ -3074,12 +3074,12 @@ impl SerializeEmbeddedGroup for StakeVoteRegDelegCert { )?; self.d_rep.serialize(serializer, force_canonical)?; serializer.write_unsigned_integer_sz( - self.coin, + self.deposit, fit_sz( - self.coin, + self.deposit, self.encodings .as_ref() - .map(|encs| encs.coin_encoding) + .map(|encs| encs.deposit_encoding) .unwrap_or_default(), force_canonical, ), @@ -3143,21 +3143,21 @@ impl DeserializeEmbeddedGroup for StakeVoteRegDelegCert { .map_err(|e: DeserializeError| e.annotate("pool"))?; let d_rep = DRep::deserialize(raw).map_err(|e: DeserializeError| e.annotate("d_rep"))?; - let (coin, coin_encoding) = raw + let (deposit, deposit_encoding) = raw .unsigned_integer_sz() .map_err(Into::::into) .map(|(x, enc)| (x, Some(enc))) - .map_err(|e: DeserializeError| e.annotate("coin"))?; + .map_err(|e: DeserializeError| e.annotate("deposit"))?; Ok(StakeVoteRegDelegCert { stake_credential, pool, d_rep, - coin, + deposit, encodings: Some(StakeVoteRegDelegCertEncoding { len_encoding, tag_encoding, pool_encoding, - coin_encoding, + deposit_encoding, }), }) })() @@ -3202,12 +3202,12 @@ impl SerializeEmbeddedGroup for UnregCert { self.stake_credential .serialize(serializer, force_canonical)?; serializer.write_unsigned_integer_sz( - self.coin, + self.deposit, fit_sz( - self.coin, + self.deposit, self.encodings .as_ref() - .map(|encs| encs.coin_encoding) + .map(|encs| encs.deposit_encoding) .unwrap_or_default(), force_canonical, ), @@ -3260,18 +3260,18 @@ impl DeserializeEmbeddedGroup for UnregCert { .map_err(|e| e.annotate("tag"))?; let stake_credential = Credential::deserialize(raw) .map_err(|e: DeserializeError| e.annotate("stake_credential"))?; - let (coin, coin_encoding) = raw + let (deposit, deposit_encoding) = raw .unsigned_integer_sz() .map_err(Into::::into) .map(|(x, enc)| (x, Some(enc))) - .map_err(|e: DeserializeError| e.annotate("coin"))?; + .map_err(|e: DeserializeError| e.annotate("deposit"))?; Ok(UnregCert { stake_credential, - coin, + deposit, encodings: Some(UnregCertEncoding { len_encoding, tag_encoding, - coin_encoding, + deposit_encoding, }), }) })() @@ -3316,12 +3316,12 @@ impl SerializeEmbeddedGroup for UnregDrepCert { self.drep_credential .serialize(serializer, force_canonical)?; serializer.write_unsigned_integer_sz( - self.coin, + self.deposit, fit_sz( - self.coin, + self.deposit, self.encodings .as_ref() - .map(|encs| encs.coin_encoding) + .map(|encs| encs.deposit_encoding) .unwrap_or_default(), force_canonical, ), @@ -3374,18 +3374,18 @@ impl DeserializeEmbeddedGroup for UnregDrepCert { .map_err(|e| e.annotate("index_0"))?; let drep_credential = Credential::deserialize(raw) .map_err(|e: DeserializeError| e.annotate("drep_credential"))?; - let (coin, coin_encoding) = raw + let (deposit, deposit_encoding) = raw .unsigned_integer_sz() .map_err(Into::::into) .map(|(x, enc)| (x, Some(enc))) - .map_err(|e: DeserializeError| e.annotate("coin"))?; + .map_err(|e: DeserializeError| e.annotate("deposit"))?; Ok(UnregDrepCert { drep_credential, - coin, + deposit, encodings: Some(UnregDrepCertEncoding { len_encoding, index_0_encoding, - coin_encoding, + deposit_encoding, }), }) })() @@ -3683,12 +3683,12 @@ impl SerializeEmbeddedGroup for VoteRegDelegCert { .serialize(serializer, force_canonical)?; self.d_rep.serialize(serializer, force_canonical)?; serializer.write_unsigned_integer_sz( - self.coin, + self.deposit, fit_sz( - self.coin, + self.deposit, self.encodings .as_ref() - .map(|encs| encs.coin_encoding) + .map(|encs| encs.deposit_encoding) .unwrap_or_default(), force_canonical, ), @@ -3743,19 +3743,19 @@ impl DeserializeEmbeddedGroup for VoteRegDelegCert { .map_err(|e: DeserializeError| e.annotate("stake_credential"))?; let d_rep = DRep::deserialize(raw).map_err(|e: DeserializeError| e.annotate("d_rep"))?; - let (coin, coin_encoding) = raw + let (deposit, deposit_encoding) = raw .unsigned_integer_sz() .map_err(Into::::into) .map(|(x, enc)| (x, Some(enc))) - .map_err(|e: DeserializeError| e.annotate("coin"))?; + .map_err(|e: DeserializeError| e.annotate("deposit"))?; Ok(VoteRegDelegCert { stake_credential, d_rep, - coin, + deposit, encodings: Some(VoteRegDelegCertEncoding { len_encoding, tag_encoding, - coin_encoding, + deposit_encoding, }), }) })() diff --git a/chain/rust/src/governance/mod.rs b/chain/rust/src/governance/mod.rs index 62417925..6a997590 100644 --- a/chain/rust/src/governance/mod.rs +++ b/chain/rust/src/governance/mod.rs @@ -76,15 +76,11 @@ pub enum GovAction { impl GovAction { pub fn new_parameter_change_action( - gov_action_id: Option, - protocol_param_update: ProtocolParamUpdate, + action_id: Option, + update: ProtocolParamUpdate, policy_hash: Option, ) -> Self { - Self::ParameterChangeAction(ParameterChangeAction::new( - gov_action_id, - protocol_param_update, - policy_hash, - )) + Self::ParameterChangeAction(ParameterChangeAction::new(action_id, update, policy_hash)) } pub fn new_hard_fork_initiation_action( @@ -215,8 +211,8 @@ impl NoConfidence { #[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] pub struct ParameterChangeAction { - pub gov_action_id: Option, - pub protocol_param_update: ProtocolParamUpdate, + pub action_id: Option, + pub update: ProtocolParamUpdate, pub policy_hash: Option, #[serde(skip)] pub encodings: Option, @@ -224,13 +220,13 @@ pub struct ParameterChangeAction { impl ParameterChangeAction { pub fn new( - gov_action_id: Option, - protocol_param_update: ProtocolParamUpdate, + action_id: Option, + update: ProtocolParamUpdate, policy_hash: Option, ) -> Self { Self { - gov_action_id, - protocol_param_update, + action_id, + update, policy_hash, encodings: None, } diff --git a/chain/rust/src/governance/serialization.rs b/chain/rust/src/governance/serialization.rs index dddc9f01..806a1d98 100644 --- a/chain/rust/src/governance/serialization.rs +++ b/chain/rust/src/governance/serialization.rs @@ -869,12 +869,11 @@ impl SerializeEmbeddedGroup for ParameterChangeAction { force_canonical, ), )?; - match &self.gov_action_id { + match &self.action_id { Some(x) => x.serialize(serializer, force_canonical), None => serializer.write_special(cbor_event::Special::Null), }?; - self.protocol_param_update - .serialize(serializer, force_canonical)?; + self.update.serialize(serializer, force_canonical)?; match &self.policy_hash { Some(x) => serializer.write_bytes_sz( x.to_raw_bytes(), @@ -932,7 +931,7 @@ impl DeserializeEmbeddedGroup for ParameterChangeAction { Ok(Some(tag_encoding)) })() .map_err(|e| e.annotate("tag"))?; - let gov_action_id = (|| -> Result<_, DeserializeError> { + let action_id = (|| -> Result<_, DeserializeError> { Ok(match raw.cbor_type()? != cbor_event::Type::Special { true => Some(GovActionId::deserialize(raw)?), false => { @@ -943,9 +942,9 @@ 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"))?; + .map_err(|e| e.annotate("action_id"))?; + let update = ProtocolParamUpdate::deserialize(raw) + .map_err(|e: DeserializeError| e.annotate("update"))?; let (policy_hash, policy_hash_encoding) = (|| -> Result<_, DeserializeError> { Ok(match raw.cbor_type()? != cbor_event::Type::Special { true => Result::<_, DeserializeError>::Ok( @@ -970,8 +969,8 @@ impl DeserializeEmbeddedGroup for ParameterChangeAction { })() .map_err(|e| e.annotate("policy_hash"))?; Ok(ParameterChangeAction { - gov_action_id, - protocol_param_update, + action_id, + update, policy_hash, encodings: Some(ParameterChangeActionEncoding { len_encoding, diff --git a/chain/rust/src/transaction/mod.rs b/chain/rust/src/transaction/mod.rs index 7590dce4..9994be7d 100644 --- a/chain/rust/src/transaction/mod.rs +++ b/chain/rust/src/transaction/mod.rs @@ -143,7 +143,9 @@ pub enum NativeScript { ScriptAll(ScriptAll), ScriptAny(ScriptAny), ScriptNOfK(ScriptNOfK), + /// Timelock validity intervals are half-open intervals [a, b). This field specifies the left (included) endpoint a. ScriptInvalidBefore(ScriptInvalidBefore), + /// Timelock validity intervals are half-open intervals [a, b). This field specifies the right (excluded) endpoint b. ScriptInvalidHereafter(ScriptInvalidHereafter), } @@ -164,10 +166,12 @@ impl NativeScript { Self::ScriptNOfK(ScriptNOfK::new(n, native_scripts)) } + /// Timelock validity intervals are half-open intervals [a, b). This field specifies the left (included) endpoint a. pub fn new_script_invalid_before(before: Slot) -> Self { Self::ScriptInvalidBefore(ScriptInvalidBefore::new(before)) } + /// Timelock validity intervals are half-open intervals [a, b). This field specifies the right (excluded) endpoint b. pub fn new_script_invalid_hereafter(after: Slot) -> Self { Self::ScriptInvalidHereafter(ScriptInvalidHereafter::new(after)) } diff --git a/chain/wasm/json-gen/src/lib.rs b/chain/wasm/json-gen/src/lib.rs index 8062b4c6..0fe20163 100644 --- a/chain/wasm/json-gen/src/lib.rs +++ b/chain/wasm/json-gen/src/lib.rs @@ -70,8 +70,8 @@ pub fn export_schemas() { 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::DNSName); 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); gen_json_schema!(cml_chain::certs::MultiHostName); diff --git a/chain/wasm/src/auxdata/mod.rs b/chain/wasm/src/auxdata/mod.rs index 1f3a6e33..83d19ab2 100644 --- a/chain/wasm/src/auxdata/mod.rs +++ b/chain/wasm/src/auxdata/mod.rs @@ -26,9 +26,9 @@ impl AuxiliaryData { )) } - pub fn new_shelley_m_a(shelley_m_a: &ShelleyMaFormatAuxData) -> Self { - Self(cml_chain::auxdata::AuxiliaryData::new_shelley_m_a( - shelley_m_a.clone().into(), + pub fn new_shelley_ma(shelley_ma: &ShelleyMAFormatAuxData) -> Self { + Self(cml_chain::auxdata::AuxiliaryData::new_shelley_ma( + shelley_ma.clone().into(), )) } @@ -53,10 +53,10 @@ impl AuxiliaryData { } } - pub fn as_shelley_m_a(&self) -> Option { + pub fn as_shelley_ma(&self) -> Option { match &self.0 { - cml_chain::auxdata::AuxiliaryData::ShelleyMA(shelley_m_a) => { - Some(shelley_m_a.clone().into()) + cml_chain::auxdata::AuxiliaryData::ShelleyMA(shelley_ma) => { + Some(shelley_ma.clone().into()) } _ => None, } @@ -145,17 +145,17 @@ pub type ShelleyFormatAuxData = Metadata; #[derive(Clone, Debug)] #[wasm_bindgen] -pub struct ShelleyMaFormatAuxData(cml_chain::auxdata::ShelleyMaFormatAuxData); +pub struct ShelleyMAFormatAuxData(cml_chain::auxdata::ShelleyMAFormatAuxData); -impl_wasm_cbor_json_api!(ShelleyMaFormatAuxData); +impl_wasm_cbor_json_api!(ShelleyMAFormatAuxData); impl_wasm_conversions!( - cml_chain::auxdata::ShelleyMaFormatAuxData, - ShelleyMaFormatAuxData + cml_chain::auxdata::ShelleyMAFormatAuxData, + ShelleyMAFormatAuxData ); #[wasm_bindgen] -impl ShelleyMaFormatAuxData { +impl ShelleyMAFormatAuxData { pub fn transaction_metadata(&self) -> Metadata { self.0.transaction_metadata.clone().into() } @@ -165,7 +165,7 @@ impl ShelleyMaFormatAuxData { } pub fn new(transaction_metadata: &Metadata, auxiliary_scripts: &NativeScriptList) -> Self { - Self(cml_chain::auxdata::ShelleyMaFormatAuxData::new( + Self(cml_chain::auxdata::ShelleyMAFormatAuxData::new( transaction_metadata.clone().into(), auxiliary_scripts.clone().into(), )) diff --git a/chain/wasm/src/certs/mod.rs b/chain/wasm/src/certs/mod.rs index 16fb9470..cc0eb2bd 100644 --- a/chain/wasm/src/certs/mod.rs +++ b/chain/wasm/src/certs/mod.rs @@ -48,18 +48,21 @@ impl_wasm_conversions!(cml_chain::certs::Certificate, Certificate); #[wasm_bindgen] impl Certificate { + /// Will be deprecated in the next era. Use RegCert instead which takes an explicit deposit amount, as that can change. pub fn new_stake_registration(stake_credential: &StakeCredential) -> Self { Self(cml_chain::certs::Certificate::new_stake_registration( stake_credential.clone().into(), )) } + /// Will be deprecated in the next era. Use UnregCert instead which takes an explicit deposit amount, as that can change. pub fn new_stake_deregistration(stake_credential: &StakeCredential) -> Self { Self(cml_chain::certs::Certificate::new_stake_deregistration( stake_credential.clone().into(), )) } + /// Delegate to a take pool only pub fn new_stake_delegation(stake_credential: &StakeCredential, pool: &Ed25519KeyHash) -> Self { Self(cml_chain::certs::Certificate::new_stake_delegation( stake_credential.clone().into(), @@ -80,20 +83,23 @@ impl Certificate { )) } - pub fn new_reg_cert(stake_credential: &StakeCredential, coin: Coin) -> Self { + /// Registers a stake credential. + pub fn new_reg_cert(stake_credential: &StakeCredential, deposit: Coin) -> Self { Self(cml_chain::certs::Certificate::new_reg_cert( stake_credential.clone().into(), - coin, + deposit, )) } - pub fn new_unreg_cert(stake_credential: &StakeCredential, coin: Coin) -> Self { + /// Unregisters a stake credential. + pub fn new_unreg_cert(stake_credential: &StakeCredential, deposit: Coin) -> Self { Self(cml_chain::certs::Certificate::new_unreg_cert( stake_credential.clone().into(), - coin, + deposit, )) } + /// Delegate to a DRep for voting only pub fn new_vote_deleg_cert(stake_credential: &StakeCredential, d_rep: &DRep) -> Self { Self(cml_chain::certs::Certificate::new_vote_deleg_cert( stake_credential.clone().into(), @@ -101,6 +107,7 @@ impl Certificate { )) } + /// Delegate to a stake pool and a DRep pub fn new_stake_vote_deleg_cert( stake_credential: &StakeCredential, pool: &Ed25519KeyHash, @@ -113,42 +120,45 @@ impl Certificate { )) } + /// Register a stake credential and delegate to a pool in a single cert pub fn new_stake_reg_deleg_cert( stake_credential: &StakeCredential, pool: &Ed25519KeyHash, - coin: Coin, + deposit: Coin, ) -> Self { Self(cml_chain::certs::Certificate::new_stake_reg_deleg_cert( stake_credential.clone().into(), pool.clone().into(), - coin, + deposit, )) } + /// Register a stake credential and delegate to a DRep in a single cert pub fn new_vote_reg_deleg_cert( stake_credential: &StakeCredential, d_rep: &DRep, - coin: Coin, + deposit: Coin, ) -> Self { Self(cml_chain::certs::Certificate::new_vote_reg_deleg_cert( stake_credential.clone().into(), d_rep.clone().into(), - coin, + deposit, )) } + /// Register a stake credential and delegate to a pool and a DRep in a single cert pub fn new_stake_vote_reg_deleg_cert( stake_credential: &StakeCredential, pool: &Ed25519KeyHash, d_rep: &DRep, - coin: Coin, + deposit: Coin, ) -> Self { Self( cml_chain::certs::Certificate::new_stake_vote_reg_deleg_cert( stake_credential.clone().into(), pool.clone().into(), d_rep.clone().into(), - coin, + deposit, ), ) } @@ -177,20 +187,20 @@ impl Certificate { pub fn new_reg_drep_cert( drep_credential: &DrepCredential, - coin: Coin, + deposit: Coin, anchor: Option, ) -> Self { Self(cml_chain::certs::Certificate::new_reg_drep_cert( drep_credential.clone().into(), - coin, + deposit, anchor.map(Into::into), )) } - pub fn new_unreg_drep_cert(drep_credential: &DrepCredential, coin: Coin) -> Self { + pub fn new_unreg_drep_cert(drep_credential: &DrepCredential, deposit: Coin) -> Self { Self(cml_chain::certs::Certificate::new_unreg_drep_cert( drep_credential.clone().into(), - coin, + deposit, )) } @@ -462,6 +472,21 @@ pub enum CredentialKind { Script, } +#[derive(Clone, Debug)] +#[wasm_bindgen] +pub struct DNSName(cml_chain::certs::DNSName); + +impl_wasm_cbor_json_api!(DNSName); + +impl_wasm_conversions!(cml_chain::certs::DNSName, DNSName); + +#[wasm_bindgen] +impl DNSName { + pub fn get(&self) -> String { + self.0.get().clone() + } +} + #[derive(Clone, Debug)] #[wasm_bindgen] pub struct DRep(cml_chain::certs::DRep); @@ -522,21 +547,6 @@ pub enum DRepKind { AlwaysNoConfidence, } -#[derive(Clone, Debug)] -#[wasm_bindgen] -pub struct DnsName(cml_chain::certs::DnsName); - -impl_wasm_cbor_json_api!(DnsName); - -impl_wasm_conversions!(cml_chain::certs::DnsName, DnsName); - -#[wasm_bindgen] -impl DnsName { - pub fn get(&self) -> String { - self.0.get().clone() - } -} - pub type DrepCredential = Credential; #[derive(Clone, Debug)] @@ -579,11 +589,12 @@ impl_wasm_conversions!(cml_chain::certs::MultiHostName, MultiHostName); #[wasm_bindgen] impl MultiHostName { - pub fn dns_name(&self) -> DnsName { + pub fn dns_name(&self) -> DNSName { self.0.dns_name.clone().into() } - pub fn new(dns_name: &DnsName) -> Self { + /// * `dns_name` - A SRV DNS record + pub fn new(dns_name: &DNSName) -> Self { Self(cml_chain::certs::MultiHostName::new( dns_name.clone().into(), )) @@ -748,14 +759,14 @@ impl RegCert { self.0.stake_credential.clone().into() } - pub fn coin(&self) -> Coin { - self.0.coin + pub fn deposit(&self) -> Coin { + self.0.deposit } - pub fn new(stake_credential: &StakeCredential, coin: Coin) -> Self { + pub fn new(stake_credential: &StakeCredential, deposit: Coin) -> Self { Self(cml_chain::certs::RegCert::new( stake_credential.clone().into(), - coin, + deposit, )) } } @@ -774,18 +785,18 @@ impl RegDrepCert { self.0.drep_credential.clone().into() } - pub fn coin(&self) -> Coin { - self.0.coin + pub fn deposit(&self) -> Coin { + self.0.deposit } pub fn anchor(&self) -> Option { self.0.anchor.clone().map(std::convert::Into::into) } - pub fn new(drep_credential: &DrepCredential, coin: Coin, anchor: Option) -> Self { + pub fn new(drep_credential: &DrepCredential, deposit: Coin, anchor: Option) -> Self { Self(cml_chain::certs::RegDrepCert::new( drep_credential.clone().into(), - coin, + deposit, anchor.map(Into::into), )) } @@ -813,14 +824,14 @@ impl Relay { )) } - pub fn new_single_host_name(port: Option, dns_name: &DnsName) -> Self { + pub fn new_single_host_name(port: Option, dns_name: &DNSName) -> Self { Self(cml_chain::certs::Relay::new_single_host_name( port, dns_name.clone().into(), )) } - pub fn new_multi_host_name(dns_name: &DnsName) -> Self { + pub fn new_multi_host_name(dns_name: &DNSName) -> Self { Self(cml_chain::certs::Relay::new_multi_host_name( dns_name.clone().into(), )) @@ -946,11 +957,12 @@ impl SingleHostName { self.0.port } - pub fn dns_name(&self) -> DnsName { + pub fn dns_name(&self) -> DNSName { self.0.dns_name.clone().into() } - pub fn new(port: Option, dns_name: &DnsName) -> Self { + /// * `dns_name` - An A or AAAA DNS record + pub fn new(port: Option, dns_name: &DNSName) -> Self { Self(cml_chain::certs::SingleHostName::new( port, dns_name.clone().into(), @@ -1025,15 +1037,15 @@ impl StakeRegDelegCert { self.0.pool.into() } - pub fn coin(&self) -> Coin { - self.0.coin + pub fn deposit(&self) -> Coin { + self.0.deposit } - pub fn new(stake_credential: &StakeCredential, pool: &Ed25519KeyHash, coin: Coin) -> Self { + pub fn new(stake_credential: &StakeCredential, pool: &Ed25519KeyHash, deposit: Coin) -> Self { Self(cml_chain::certs::StakeRegDelegCert::new( stake_credential.clone().into(), pool.clone().into(), - coin, + deposit, )) } } @@ -1115,21 +1127,21 @@ impl StakeVoteRegDelegCert { self.0.d_rep.clone().into() } - pub fn coin(&self) -> Coin { - self.0.coin + pub fn deposit(&self) -> Coin { + self.0.deposit } pub fn new( stake_credential: &StakeCredential, pool: &Ed25519KeyHash, d_rep: &DRep, - coin: Coin, + deposit: Coin, ) -> Self { Self(cml_chain::certs::StakeVoteRegDelegCert::new( stake_credential.clone().into(), pool.clone().into(), d_rep.clone().into(), - coin, + deposit, )) } } @@ -1148,14 +1160,14 @@ impl UnregCert { self.0.stake_credential.clone().into() } - pub fn coin(&self) -> Coin { - self.0.coin + pub fn deposit(&self) -> Coin { + self.0.deposit } - pub fn new(stake_credential: &StakeCredential, coin: Coin) -> Self { + pub fn new(stake_credential: &StakeCredential, deposit: Coin) -> Self { Self(cml_chain::certs::UnregCert::new( stake_credential.clone().into(), - coin, + deposit, )) } } @@ -1174,14 +1186,14 @@ impl UnregDrepCert { self.0.drep_credential.clone().into() } - pub fn coin(&self) -> Coin { - self.0.coin + pub fn deposit(&self) -> Coin { + self.0.deposit } - pub fn new(drep_credential: &DrepCredential, coin: Coin) -> Self { + pub fn new(drep_credential: &DrepCredential, deposit: Coin) -> Self { Self(cml_chain::certs::UnregDrepCert::new( drep_credential.clone().into(), - coin, + deposit, )) } } @@ -1271,15 +1283,15 @@ impl VoteRegDelegCert { self.0.d_rep.clone().into() } - pub fn coin(&self) -> Coin { - self.0.coin + pub fn deposit(&self) -> Coin { + self.0.deposit } - pub fn new(stake_credential: &StakeCredential, d_rep: &DRep, coin: Coin) -> Self { + pub fn new(stake_credential: &StakeCredential, d_rep: &DRep, deposit: Coin) -> Self { Self(cml_chain::certs::VoteRegDelegCert::new( stake_credential.clone().into(), d_rep.clone().into(), - coin, + deposit, )) } } diff --git a/chain/wasm/src/governance/mod.rs b/chain/wasm/src/governance/mod.rs index a184942c..a21870d8 100644 --- a/chain/wasm/src/governance/mod.rs +++ b/chain/wasm/src/governance/mod.rs @@ -78,14 +78,14 @@ impl_wasm_conversions!(cml_chain::governance::GovAction, GovAction); #[wasm_bindgen] impl GovAction { pub fn new_parameter_change_action( - gov_action_id: Option, - protocol_param_update: &ProtocolParamUpdate, + action_id: Option, + 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(), + action_id.map(Into::into), + update.clone().into(), policy_hash.map(Into::into), ), ) @@ -348,12 +348,12 @@ impl_wasm_conversions!( #[wasm_bindgen] impl ParameterChangeAction { - pub fn gov_action_id(&self) -> Option { - self.0.gov_action_id.clone().map(std::convert::Into::into) + pub fn action_id(&self) -> Option { + self.0.action_id.clone().map(std::convert::Into::into) } - pub fn protocol_param_update(&self) -> ProtocolParamUpdate { - self.0.protocol_param_update.clone().into() + pub fn update(&self) -> ProtocolParamUpdate { + self.0.update.clone().into() } pub fn policy_hash(&self) -> Option { @@ -361,13 +361,13 @@ impl ParameterChangeAction { } pub fn new( - gov_action_id: Option, - protocol_param_update: &ProtocolParamUpdate, + action_id: Option, + update: &ProtocolParamUpdate, policy_hash: Option, ) -> Self { Self(cml_chain::governance::ParameterChangeAction::new( - gov_action_id.map(Into::into), - protocol_param_update.clone().into(), + action_id.map(Into::into), + update.clone().into(), policy_hash.map(Into::into), )) } diff --git a/chain/wasm/src/transaction/mod.rs b/chain/wasm/src/transaction/mod.rs index f8aca0f6..26ba128c 100644 --- a/chain/wasm/src/transaction/mod.rs +++ b/chain/wasm/src/transaction/mod.rs @@ -186,10 +186,12 @@ impl NativeScript { )) } + /// Timelock validity intervals are half-open intervals [a, b). This field specifies the left (included) endpoint a. pub fn new_script_invalid_before(before: Slot) -> Self { Self(cml_chain::transaction::NativeScript::new_script_invalid_before(before)) } + /// Timelock validity intervals are half-open intervals [a, b). This field specifies the right (excluded) endpoint b. pub fn new_script_invalid_hereafter(after: Slot) -> Self { Self(cml_chain::transaction::NativeScript::new_script_invalid_hereafter(after)) } diff --git a/core/rust/Cargo.toml b/core/rust/Cargo.toml index 1954ac5e..712b2e1e 100644 --- a/core/rust/Cargo.toml +++ b/core/rust/Cargo.toml @@ -44,12 +44,12 @@ cfg-if = "1" # This could possibly be resolved with macros but maybe not. # non-wasm -#[target.'cfg(not(all(target_arch = "wasm32", not(target_os = "emscripten"))))'.dependencies] +[target.'cfg(not(all(target_arch = "wasm32", not(target_os = "emscripten"))))'.dependencies] #rand_os = "0.1" -#noop_proc_macro = "0.3.0" +noop_proc_macro = "0.3.0" # wasm -#[target.'cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))'.dependencies] +[target.'cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))'.dependencies] wasm-bindgen = { version = "0.2.87" } #rand_os = { version = "0.1", features = ["wasm-bindgen"] } #js-sys = "=0.3.59" diff --git a/multi-era/rust/src/allegra/mod.rs b/multi-era/rust/src/allegra/mod.rs index c9be16f4..93a4fe0d 100644 --- a/multi-era/rust/src/allegra/mod.rs +++ b/multi-era/rust/src/allegra/mod.rs @@ -14,7 +14,7 @@ use cbor_encodings::{ AllegraTransactionWitnessSetEncoding, }; use cml_chain::assets::Coin; -use cml_chain::auxdata::{ShelleyFormatAuxData, ShelleyMaFormatAuxData}; +use cml_chain::auxdata::{ShelleyFormatAuxData, ShelleyMAFormatAuxData}; use cml_chain::certs::{ PoolRetirement, StakeCredential, StakeDelegation, StakeDeregistration, StakeRegistration, }; @@ -32,7 +32,7 @@ use self::cbor_encodings::{MoveInstantaneousRewardEncoding, MoveInstantaneousRew #[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] pub enum AllegraAuxiliaryData { Shelley(ShelleyFormatAuxData), - ShelleyMA(ShelleyMaFormatAuxData), + ShelleyMA(ShelleyMAFormatAuxData), } impl AllegraAuxiliaryData { @@ -40,8 +40,8 @@ impl AllegraAuxiliaryData { Self::Shelley(shelley) } - pub fn new_shelley_m_a(shelley_m_a: ShelleyMaFormatAuxData) -> Self { - Self::ShelleyMA(shelley_m_a) + pub fn new_shelley_ma(shelley_ma: ShelleyMAFormatAuxData) -> Self { + Self::ShelleyMA(shelley_ma) } } @@ -111,12 +111,12 @@ impl AllegraCertificate { pub fn new_genesis_key_delegation( genesis_hash: GenesisHash, genesis_delegate_hash: GenesisDelegateHash, - v_r_f_key_hash: VRFKeyHash, + vrf_key_hash: VRFKeyHash, ) -> Self { Self::GenesisKeyDelegation(GenesisKeyDelegation::new( genesis_hash, genesis_delegate_hash, - v_r_f_key_hash, + vrf_key_hash, )) } diff --git a/multi-era/rust/src/allegra/serialization.rs b/multi-era/rust/src/allegra/serialization.rs index 0e997cba..3ffbda9f 100644 --- a/multi-era/rust/src/allegra/serialization.rs +++ b/multi-era/rust/src/allegra/serialization.rs @@ -10,7 +10,7 @@ use cbor_event::de::Deserializer; use cbor_event::se::Serializer; use cml_chain::address::RewardAccount; use cml_chain::auxdata::ShelleyFormatAuxData; -use cml_chain::auxdata::ShelleyMaFormatAuxData; +use cml_chain::auxdata::ShelleyMAFormatAuxData; use cml_core::error::*; use cml_core::serialization::*; use cml_crypto::RawBytesEncoding; @@ -26,8 +26,8 @@ impl Serialize for AllegraAuxiliaryData { AllegraAuxiliaryData::Shelley(shelley) => { shelley.serialize(serializer, force_canonical) } - AllegraAuxiliaryData::ShelleyMA(shelley_m_a) => { - shelley_m_a.serialize(serializer, force_canonical) + AllegraAuxiliaryData::ShelleyMA(shelley_ma) => { + shelley_ma.serialize(serializer, force_canonical) } } } @@ -49,9 +49,9 @@ impl Deserialize for AllegraAuxiliaryData { } }; let deser_variant: Result<_, DeserializeError> = - ShelleyMaFormatAuxData::deserialize(raw); + ShelleyMAFormatAuxData::deserialize(raw); match deser_variant { - Ok(shelley_m_a) => return Ok(Self::ShelleyMA(shelley_m_a)), + Ok(shelley_ma) => return Ok(Self::ShelleyMA(shelley_ma)), Err(e) => { errs.push(e.annotate("ShelleyMA")); raw.as_mut_ref() diff --git a/multi-era/rust/src/allegra/utils.rs b/multi-era/rust/src/allegra/utils.rs index 86eedd25..53ea8922 100644 --- a/multi-era/rust/src/allegra/utils.rs +++ b/multi-era/rust/src/allegra/utils.rs @@ -15,7 +15,7 @@ impl From for AuxiliaryData { fn from(aux: AllegraAuxiliaryData) -> Self { match aux { AllegraAuxiliaryData::Shelley(md) => AuxiliaryData::new_shelley(md), - AllegraAuxiliaryData::ShelleyMA(md) => AuxiliaryData::new_shelley_m_a(md), + AllegraAuxiliaryData::ShelleyMA(md) => AuxiliaryData::new_shelley_ma(md), } } } diff --git a/multi-era/rust/src/alonzo/mod.rs b/multi-era/rust/src/alonzo/mod.rs index cceb8c31..ea51bb90 100644 --- a/multi-era/rust/src/alonzo/mod.rs +++ b/multi-era/rust/src/alonzo/mod.rs @@ -13,7 +13,7 @@ use cbor_encodings::{ AlonzoUpdateEncoding, }; use cml_chain::assets::{Coin, Mint}; -use cml_chain::auxdata::{Metadata, ShelleyFormatAuxData, ShelleyMaFormatAuxData}; +use cml_chain::auxdata::{Metadata, ShelleyFormatAuxData, ShelleyMAFormatAuxData}; use cml_chain::crypto::{ AuxiliaryDataHash, BootstrapWitness, GenesisHash, Nonce, ScriptDataHash, Vkeywitness, }; @@ -29,7 +29,7 @@ use self::cbor_encodings::AlonzoRedeemerEncoding; #[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] pub enum AlonzoAuxiliaryData { Shelley(ShelleyFormatAuxData), - ShelleyMA(ShelleyMaFormatAuxData), + ShelleyMA(ShelleyMAFormatAuxData), Alonzo(AlonzoFormatAuxData), } @@ -38,8 +38,8 @@ impl AlonzoAuxiliaryData { Self::Shelley(shelley) } - pub fn new_shelley_m_a(shelley_m_a: ShelleyMaFormatAuxData) -> Self { - Self::ShelleyMA(shelley_m_a) + pub fn new_shelley_ma(shelley_ma: ShelleyMAFormatAuxData) -> Self { + Self::ShelleyMA(shelley_ma) } pub fn new_alonzo(alonzo: AlonzoFormatAuxData) -> Self { diff --git a/multi-era/rust/src/alonzo/serialization.rs b/multi-era/rust/src/alonzo/serialization.rs index 8cbeeae6..03259bc7 100644 --- a/multi-era/rust/src/alonzo/serialization.rs +++ b/multi-era/rust/src/alonzo/serialization.rs @@ -47,7 +47,7 @@ impl Deserialize for AlonzoAuxiliaryData { } }; let deser_variant: Result<_, DeserializeError> = - ShelleyMaFormatAuxData::deserialize(raw); + ShelleyMAFormatAuxData::deserialize(raw); match deser_variant { Ok(shelley_m_a) => return Ok(Self::ShelleyMA(shelley_m_a)), Err(e) => { diff --git a/multi-era/rust/src/alonzo/utils.rs b/multi-era/rust/src/alonzo/utils.rs index 43a6ea18..e371153a 100644 --- a/multi-era/rust/src/alonzo/utils.rs +++ b/multi-era/rust/src/alonzo/utils.rs @@ -22,7 +22,7 @@ impl From for AuxiliaryData { fn from(aux: AlonzoAuxiliaryData) -> Self { match aux { AlonzoAuxiliaryData::Shelley(md) => AuxiliaryData::new_shelley(md.clone()), - AlonzoAuxiliaryData::ShelleyMA(md) => AuxiliaryData::new_shelley_m_a(md.clone()), + AlonzoAuxiliaryData::ShelleyMA(md) => AuxiliaryData::new_shelley_ma(md.clone()), AlonzoAuxiliaryData::Alonzo(md) => AuxiliaryData::new_conway({ let mut conway = ConwayFormatAuxData::new(); conway.metadata.clone_from(&md.metadata); diff --git a/multi-era/rust/src/babbage/mod.rs b/multi-era/rust/src/babbage/mod.rs index 9a8e0f17..b42abc16 100644 --- a/multi-era/rust/src/babbage/mod.rs +++ b/multi-era/rust/src/babbage/mod.rs @@ -15,7 +15,7 @@ use cbor_encodings::{ }; use cml_chain::address::Address; use cml_chain::assets::{Coin, Value}; -use cml_chain::auxdata::{Metadata, ShelleyFormatAuxData, ShelleyMaFormatAuxData}; +use cml_chain::auxdata::{Metadata, ShelleyFormatAuxData, ShelleyMAFormatAuxData}; use cml_chain::block::Header; use cml_chain::crypto::{ AuxiliaryDataHash, BootstrapWitness, GenesisHash, ScriptDataHash, Vkeywitness, @@ -37,7 +37,7 @@ use self::utils::BabbageMint; #[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] pub enum BabbageAuxiliaryData { Shelley(ShelleyFormatAuxData), - ShelleyMA(ShelleyMaFormatAuxData), + ShelleyMA(ShelleyMAFormatAuxData), Babbage(BabbageFormatAuxData), } @@ -46,8 +46,8 @@ impl BabbageAuxiliaryData { Self::Shelley(shelley) } - pub fn new_shelley_m_a(shelley_m_a: ShelleyMaFormatAuxData) -> Self { - Self::ShelleyMA(shelley_m_a) + pub fn new_shelley_ma(shelley_ma: ShelleyMAFormatAuxData) -> Self { + Self::ShelleyMA(shelley_ma) } pub fn new_babbage(babbage: BabbageFormatAuxData) -> Self { diff --git a/multi-era/rust/src/babbage/serialization.rs b/multi-era/rust/src/babbage/serialization.rs index b4f611bb..03dc76cb 100644 --- a/multi-era/rust/src/babbage/serialization.rs +++ b/multi-era/rust/src/babbage/serialization.rs @@ -22,8 +22,8 @@ impl Serialize for BabbageAuxiliaryData { BabbageAuxiliaryData::Shelley(shelley) => { shelley.serialize(serializer, force_canonical) } - BabbageAuxiliaryData::ShelleyMA(shelley_m_a) => { - shelley_m_a.serialize(serializer, force_canonical) + BabbageAuxiliaryData::ShelleyMA(shelley_ma) => { + shelley_ma.serialize(serializer, force_canonical) } BabbageAuxiliaryData::Babbage(babbage) => { babbage.serialize(serializer, force_canonical) @@ -48,7 +48,7 @@ impl Deserialize for BabbageAuxiliaryData { } }; let deser_variant: Result<_, DeserializeError> = - ShelleyMaFormatAuxData::deserialize(raw); + ShelleyMAFormatAuxData::deserialize(raw); match deser_variant { Ok(shelley_m_a) => return Ok(Self::ShelleyMA(shelley_m_a)), Err(e) => { diff --git a/multi-era/rust/src/babbage/utils.rs b/multi-era/rust/src/babbage/utils.rs index 050a97d2..9461402e 100644 --- a/multi-era/rust/src/babbage/utils.rs +++ b/multi-era/rust/src/babbage/utils.rs @@ -63,7 +63,7 @@ impl From for AuxiliaryData { fn from(aux: BabbageAuxiliaryData) -> Self { match aux { BabbageAuxiliaryData::Shelley(md) => AuxiliaryData::new_shelley(md.clone()), - BabbageAuxiliaryData::ShelleyMA(md) => AuxiliaryData::new_shelley_m_a(md.clone()), + BabbageAuxiliaryData::ShelleyMA(md) => AuxiliaryData::new_shelley_ma(md.clone()), BabbageAuxiliaryData::Babbage(md) => AuxiliaryData::new_conway({ let mut conway = ConwayFormatAuxData::new(); conway.metadata.clone_from(&md.metadata); diff --git a/multi-era/rust/src/shelley/cbor_encodings.rs b/multi-era/rust/src/shelley/cbor_encodings.rs index 247d79b0..dda4684e 100644 --- a/multi-era/rust/src/shelley/cbor_encodings.rs +++ b/multi-era/rust/src/shelley/cbor_encodings.rs @@ -11,7 +11,7 @@ pub struct GenesisKeyDelegationEncoding { pub tag_encoding: Option, pub genesis_hash_encoding: StringEncoding, pub genesis_delegate_hash_encoding: StringEncoding, - pub v_r_f_key_hash_encoding: StringEncoding, + pub vrf_key_hash_encoding: StringEncoding, } #[derive(Clone, Debug, Default)] @@ -58,7 +58,7 @@ pub struct ShelleyBlockEncoding { } #[derive(Clone, Debug, Default)] -pub struct ShelleyDnsNameEncoding { +pub struct ShelleyDNSNameEncoding { pub inner_encoding: StringEncoding, } @@ -69,7 +69,7 @@ pub struct ShelleyHeaderBodyEncoding { pub slot_encoding: Option, pub prev_hash_encoding: StringEncoding, pub issuer_vkey_encoding: StringEncoding, - pub v_r_f_vkey_encoding: StringEncoding, + pub vrf_vkey_encoding: StringEncoding, pub block_body_size_encoding: Option, pub block_body_hash_encoding: StringEncoding, } diff --git a/multi-era/rust/src/shelley/mod.rs b/multi-era/rust/src/shelley/mod.rs index d42a3c90..fdbb4183 100644 --- a/multi-era/rust/src/shelley/mod.rs +++ b/multi-era/rust/src/shelley/mod.rs @@ -36,7 +36,7 @@ use std::convert::TryFrom; use crate::allegra::MIRPot; use self::cbor_encodings::{ - GenesisKeyDelegationEncoding, ProtocolVersionStructEncoding, ShelleyDnsNameEncoding, + GenesisKeyDelegationEncoding, ProtocolVersionStructEncoding, ShelleyDNSNameEncoding, ShelleyMoveInstantaneousRewardEncoding, ShelleyMoveInstantaneousRewardsCertEncoding, ShelleyPoolParamsEncoding, }; @@ -44,7 +44,7 @@ use self::cbor_encodings::{ pub struct GenesisKeyDelegation { pub genesis_hash: GenesisHash, pub genesis_delegate_hash: GenesisDelegateHash, - pub v_r_f_key_hash: VRFKeyHash, + pub vrf_key_hash: VRFKeyHash, #[serde(skip)] pub encodings: Option, } @@ -53,12 +53,12 @@ impl GenesisKeyDelegation { pub fn new( genesis_hash: GenesisHash, genesis_delegate_hash: GenesisDelegateHash, - v_r_f_key_hash: VRFKeyHash, + vrf_key_hash: VRFKeyHash, ) -> Self { Self { genesis_hash, genesis_delegate_hash, - v_r_f_key_hash, + vrf_key_hash, encodings: None, } } @@ -238,12 +238,12 @@ impl ShelleyCertificate { pub fn new_genesis_key_delegation( genesis_hash: GenesisHash, genesis_delegate_hash: GenesisDelegateHash, - v_r_f_key_hash: VRFKeyHash, + vrf_key_hash: VRFKeyHash, ) -> Self { Self::GenesisKeyDelegation(GenesisKeyDelegation::new( genesis_hash, genesis_delegate_hash, - v_r_f_key_hash, + vrf_key_hash, )) } @@ -257,12 +257,12 @@ impl ShelleyCertificate { } #[derive(Clone, Debug)] -pub struct ShelleyDnsName { +pub struct ShelleyDNSName { pub inner: String, - pub encodings: Option, + pub encodings: Option, } -impl ShelleyDnsName { +impl ShelleyDNSName { pub fn get(&self) -> &String { &self.inner } @@ -270,7 +270,7 @@ impl ShelleyDnsName { pub fn new(inner: String) -> Result { if inner.len() > 64 { return Err(DeserializeError::new( - "ShelleyDnsName", + "ShelleyDNSName", DeserializeFailure::RangeCheck { found: inner.len() as isize, min: Some(0), @@ -285,15 +285,15 @@ impl ShelleyDnsName { } } -impl TryFrom for ShelleyDnsName { +impl TryFrom for ShelleyDNSName { type Error = DeserializeError; fn try_from(inner: String) -> Result { - ShelleyDnsName::new(inner) + ShelleyDNSName::new(inner) } } -impl serde::Serialize for ShelleyDnsName { +impl serde::Serialize for ShelleyDNSName { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, @@ -302,7 +302,7 @@ impl serde::Serialize for ShelleyDnsName { } } -impl<'de> serde::de::Deserialize<'de> for ShelleyDnsName { +impl<'de> serde::de::Deserialize<'de> for ShelleyDNSName { fn deserialize(deserializer: D) -> Result where D: serde::de::Deserializer<'de>, @@ -311,15 +311,15 @@ impl<'de> serde::de::Deserialize<'de> for ShelleyDnsName { Self::new(inner.clone()).map_err(|_e| { serde::de::Error::invalid_value( serde::de::Unexpected::Str(&inner), - &"invalid ShelleyDnsName", + &"invalid ShelleyDNSName", ) }) } } -impl schemars::JsonSchema for ShelleyDnsName { +impl schemars::JsonSchema for ShelleyDNSName { fn schema_name() -> String { - String::from("ShelleyDnsName") + String::from("ShelleyDNSName") } fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema { @@ -355,7 +355,7 @@ pub struct ShelleyHeaderBody { pub slot: u64, pub prev_hash: Option, pub issuer_vkey: Vkey, - pub v_r_f_vkey: VRFVkey, + pub vrf_vkey: VRFVkey, pub nonce_vrf: VRFCert, pub leader_vrf: VRFCert, pub block_body_size: u64, @@ -372,7 +372,7 @@ impl ShelleyHeaderBody { slot: u64, prev_hash: Option, issuer_vkey: Vkey, - v_r_f_vkey: VRFVkey, + vrf_vkey: VRFVkey, nonce_vrf: VRFCert, leader_vrf: VRFCert, block_body_size: u64, @@ -385,7 +385,7 @@ impl ShelleyHeaderBody { slot, prev_hash, issuer_vkey, - v_r_f_vkey, + vrf_vkey, nonce_vrf, leader_vrf, block_body_size, @@ -433,13 +433,15 @@ impl ShelleyMoveInstantaneousRewardsCert { #[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] pub struct ShelleyMultiHostName { - pub shelley_dns_name: ShelleyDnsName, + /// A SRV DNS record + pub shelley_dns_name: ShelleyDNSName, #[serde(skip)] pub encodings: Option, } impl ShelleyMultiHostName { - pub fn new(shelley_dns_name: ShelleyDnsName) -> Self { + /// * `shelley_dns_name` - A SRV DNS record + pub fn new(shelley_dns_name: ShelleyDNSName) -> Self { Self { shelley_dns_name, encodings: None, @@ -578,12 +580,12 @@ impl ShelleyRelay { pub fn new_shelley_single_host_name( port: Option, - shelley_dns_name: ShelleyDnsName, + 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 { + pub fn new_shelley_multi_host_name(shelley_dns_name: ShelleyDNSName) -> Self { Self::ShelleyMultiHostName(ShelleyMultiHostName::new(shelley_dns_name)) } } @@ -591,13 +593,15 @@ impl ShelleyRelay { #[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)] pub struct ShelleySingleHostName { pub port: Option, - pub shelley_dns_name: ShelleyDnsName, + /// An A or AAAA DNS record + pub shelley_dns_name: ShelleyDNSName, #[serde(skip)] pub encodings: Option, } impl ShelleySingleHostName { - pub fn new(port: Option, shelley_dns_name: ShelleyDnsName) -> Self { + /// * `shelley_dns_name` - An A or AAAA DNS record + pub fn new(port: Option, shelley_dns_name: ShelleyDNSName) -> Self { Self { port, shelley_dns_name, @@ -732,8 +736,8 @@ impl ShelleyUpdate { } } -impl From for String { - fn from(wrapper: ShelleyDnsName) -> Self { +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 a69361b7..6fbc30a3 100644 --- a/multi-era/rust/src/shelley/serialization.rs +++ b/multi-era/rust/src/shelley/serialization.rs @@ -72,13 +72,13 @@ impl SerializeEmbeddedGroup for GenesisKeyDelegation { ), )?; serializer.write_bytes_sz( - self.v_r_f_key_hash.to_raw_bytes(), + self.vrf_key_hash.to_raw_bytes(), self.encodings .as_ref() - .map(|encs| encs.v_r_f_key_hash_encoding.clone()) + .map(|encs| encs.vrf_key_hash_encoding.clone()) .unwrap_or_default() .to_str_len_sz( - self.v_r_f_key_hash.to_raw_bytes().len() as u64, + self.vrf_key_hash.to_raw_bytes().len() as u64, force_canonical, ), )?; @@ -146,7 +146,7 @@ impl DeserializeEmbeddedGroup for GenesisKeyDelegation { .map_err(|e| DeserializeFailure::InvalidStructure(Box::new(e)).into()) }) .map_err(|e: DeserializeError| e.annotate("genesis_delegate_hash"))?; - let (v_r_f_key_hash, v_r_f_key_hash_encoding) = raw + let (vrf_key_hash, vrf_key_hash_encoding) = raw .bytes_sz() .map_err(Into::::into) .and_then(|(bytes, enc)| { @@ -154,17 +154,17 @@ impl DeserializeEmbeddedGroup for GenesisKeyDelegation { .map(|bytes| (bytes, StringEncoding::from(enc))) .map_err(|e| DeserializeFailure::InvalidStructure(Box::new(e)).into()) }) - .map_err(|e: DeserializeError| e.annotate("v_r_f_key_hash"))?; + .map_err(|e: DeserializeError| e.annotate("vrf_key_hash"))?; Ok(GenesisKeyDelegation { genesis_hash, genesis_delegate_hash, - v_r_f_key_hash, + vrf_key_hash, encodings: Some(GenesisKeyDelegationEncoding { len_encoding, tag_encoding, genesis_hash_encoding, genesis_delegate_hash_encoding, - v_r_f_key_hash_encoding, + vrf_key_hash_encoding, }), }) })() @@ -1305,7 +1305,7 @@ impl Deserialize for ShelleyCertificate { } } -impl Serialize for ShelleyDnsName { +impl Serialize for ShelleyDNSName { fn serialize<'se, W: Write>( &self, serializer: &'se mut Serializer, @@ -1322,14 +1322,14 @@ impl Serialize for ShelleyDnsName { } } -impl Deserialize for ShelleyDnsName { +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", + "ShelleyDNSName", DeserializeFailure::RangeCheck { found: inner.len() as isize, min: Some(0), @@ -1339,7 +1339,7 @@ impl Deserialize for ShelleyDnsName { } Ok(Self { inner, - encodings: Some(ShelleyDnsNameEncoding { inner_encoding }), + encodings: Some(ShelleyDNSNameEncoding { inner_encoding }), }) } } @@ -1454,12 +1454,12 @@ impl Serialize for ShelleyHeaderBody { ), )?; serializer.write_bytes_sz( - self.v_r_f_vkey.to_raw_bytes(), + self.vrf_vkey.to_raw_bytes(), self.encodings .as_ref() - .map(|encs| encs.v_r_f_vkey_encoding.clone()) + .map(|encs| encs.vrf_vkey_encoding.clone()) .unwrap_or_default() - .to_str_len_sz(self.v_r_f_vkey.to_raw_bytes().len() as u64, force_canonical), + .to_str_len_sz(self.vrf_vkey.to_raw_bytes().len() as u64, force_canonical), )?; self.nonce_vrf.serialize(serializer, force_canonical)?; self.leader_vrf.serialize(serializer, force_canonical)?; @@ -1547,7 +1547,7 @@ impl Deserialize for ShelleyHeaderBody { .map_err(|e| DeserializeFailure::InvalidStructure(Box::new(e)).into()) }) .map_err(|e: DeserializeError| e.annotate("issuer_vkey"))?; - let (v_r_f_vkey, v_r_f_vkey_encoding) = raw + let (vrf_vkey, vrf_vkey_encoding) = raw .bytes_sz() .map_err(Into::::into) .and_then(|(bytes, enc)| { @@ -1555,7 +1555,7 @@ impl Deserialize for ShelleyHeaderBody { .map(|bytes| (bytes, StringEncoding::from(enc))) .map_err(|e| DeserializeFailure::InvalidStructure(Box::new(e)).into()) }) - .map_err(|e: DeserializeError| e.annotate("v_r_f_vkey"))?; + .map_err(|e: DeserializeError| e.annotate("vrf_vkey"))?; let nonce_vrf = VRFCert::deserialize(raw).map_err(|e: DeserializeError| e.annotate("nonce_vrf"))?; let leader_vrf = VRFCert::deserialize(raw) @@ -1592,7 +1592,7 @@ impl Deserialize for ShelleyHeaderBody { slot, prev_hash, issuer_vkey, - v_r_f_vkey, + vrf_vkey, nonce_vrf, leader_vrf, block_body_size, @@ -1605,7 +1605,7 @@ impl Deserialize for ShelleyHeaderBody { slot_encoding, prev_hash_encoding, issuer_vkey_encoding, - v_r_f_vkey_encoding, + vrf_vkey_encoding, block_body_size_encoding, block_body_hash_encoding, }), @@ -1997,7 +1997,7 @@ impl DeserializeEmbeddedGroup for ShelleyMultiHostName { Ok(Some(tag_encoding)) })() .map_err(|e| e.annotate("tag"))?; - let shelley_dns_name = ShelleyDnsName::deserialize(raw) + let shelley_dns_name = ShelleyDNSName::deserialize(raw) .map_err(|e: DeserializeError| e.annotate("shelley_dns_name"))?; Ok(ShelleyMultiHostName { shelley_dns_name, @@ -3468,8 +3468,8 @@ impl DeserializeEmbeddedGroup for ShelleySingleHostName { }) })() .map_err(|e| e.annotate("port"))?; - let shelley_dns_name = ShelleyDnsName::deserialize(raw) - .map_err(|e: DeserializeError| e.annotate("shelley_dns_name"))?; + let shelley_dns_name = ShelleyDNSName::deserialize(raw) + .map_err(|e: DeserializeError| e.annotate("shelley__dns_name"))?; Ok(ShelleySingleHostName { port, shelley_dns_name, diff --git a/multi-era/rust/src/shelley/utils.rs b/multi-era/rust/src/shelley/utils.rs index 13749094..e92ec241 100644 --- a/multi-era/rust/src/shelley/utils.rs +++ b/multi-era/rust/src/shelley/utils.rs @@ -1,5 +1,5 @@ use cml_chain::{ - certs::{DnsName, PoolParams, PoolRegistration, Relay}, + certs::{DNSName, PoolParams, PoolRegistration, Relay}, transaction::{NativeScript, TransactionWitnessSet}, }; @@ -91,10 +91,10 @@ impl From for Relay { } ShelleyRelay::ShelleySingleHostName(host) => Self::new_single_host_name( host.port, - DnsName::new(host.shelley_dns_name.inner).unwrap(), + DNSName::new(host.shelley_dns_name.inner).unwrap(), ), ShelleyRelay::ShelleyMultiHostName(host) => { - Self::new_multi_host_name(DnsName::new(host.shelley_dns_name.inner).unwrap()) + 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 679d2e64..f526afe3 100644 --- a/multi-era/rust/src/utils.rs +++ b/multi-era/rust/src/utils.rs @@ -343,7 +343,7 @@ impl MultiEraBlockHeader { match self { Self::ByronEB(_) => None, Self::Byron(_) => None, - Self::Shelley(header) => Some(&header.body.v_r_f_vkey), + Self::Shelley(header) => Some(&header.body.vrf_vkey), Self::Babbage(header) => Some(&header.header_body.vrf_vkey), } } diff --git a/multi-era/wasm/json-gen/src/lib.rs b/multi-era/wasm/json-gen/src/lib.rs index c84629a4..7a1c6896 100644 --- a/multi-era/wasm/json-gen/src/lib.rs +++ b/multi-era/wasm/json-gen/src/lib.rs @@ -135,7 +135,7 @@ 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::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); diff --git a/multi-era/wasm/src/allegra/mod.rs b/multi-era/wasm/src/allegra/mod.rs index 223a9488..9465a22f 100644 --- a/multi-era/wasm/src/allegra/mod.rs +++ b/multi-era/wasm/src/allegra/mod.rs @@ -9,7 +9,7 @@ use crate::{ MapTransactionIndexToAllegraAuxiliaryData, ShelleyTransactionOutputList, }; use cml_chain_wasm::assets::Coin; -use cml_chain_wasm::auxdata::{ShelleyFormatAuxData, ShelleyMaFormatAuxData}; +use cml_chain_wasm::auxdata::{ShelleyFormatAuxData, ShelleyMAFormatAuxData}; use cml_chain_wasm::certs::StakeCredential; use cml_chain_wasm::certs::{ PoolRetirement, StakeDelegation, StakeDeregistration, StakeRegistration, @@ -44,11 +44,9 @@ impl AllegraAuxiliaryData { )) } - pub fn new_shelley_m_a(shelley_m_a: &ShelleyMaFormatAuxData) -> Self { + pub fn new_shelley_ma(shelley_ma: &ShelleyMAFormatAuxData) -> Self { Self( - cml_multi_era::allegra::AllegraAuxiliaryData::new_shelley_m_a( - shelley_m_a.clone().into(), - ), + cml_multi_era::allegra::AllegraAuxiliaryData::new_shelley_ma(shelley_ma.clone().into()), ) } @@ -72,10 +70,10 @@ impl AllegraAuxiliaryData { } } - pub fn as_shelley_m_a(&self) -> Option { + pub fn as_shelley_ma(&self) -> Option { match &self.0 { - cml_multi_era::allegra::AllegraAuxiliaryData::ShelleyMA(shelley_m_a) => { - Some(shelley_m_a.clone().into()) + cml_multi_era::allegra::AllegraAuxiliaryData::ShelleyMA(shelley_ma) => { + Some(shelley_ma.clone().into()) } _ => None, } @@ -190,13 +188,13 @@ impl AllegraCertificate { pub fn new_genesis_key_delegation( genesis_hash: &GenesisHash, genesis_delegate_hash: &GenesisDelegateHash, - v_r_f_key_hash: &VRFKeyHash, + vrf_key_hash: &VRFKeyHash, ) -> Self { Self( cml_multi_era::allegra::AllegraCertificate::new_genesis_key_delegation( genesis_hash.clone().into(), genesis_delegate_hash.clone().into(), - v_r_f_key_hash.clone().into(), + vrf_key_hash.clone().into(), ), ) } diff --git a/multi-era/wasm/src/alonzo/mod.rs b/multi-era/wasm/src/alonzo/mod.rs index 3ccffc41..887c4dc8 100644 --- a/multi-era/wasm/src/alonzo/mod.rs +++ b/multi-era/wasm/src/alonzo/mod.rs @@ -7,7 +7,7 @@ use crate::{ AlonzoTransactionWitnessSetList, GenesisHashList, MapTransactionIndexToAlonzoAuxiliaryData, }; use cml_chain_wasm::assets::{Coin, Mint}; -use cml_chain_wasm::auxdata::{Metadata, ShelleyFormatAuxData, ShelleyMaFormatAuxData}; +use cml_chain_wasm::auxdata::{Metadata, ShelleyFormatAuxData, ShelleyMAFormatAuxData}; use cml_chain_wasm::crypto::Nonce; use cml_chain_wasm::plutus::{CostModels, ExUnitPrices, ExUnits, PlutusData}; use cml_chain_wasm::RequiredSigners; @@ -42,9 +42,9 @@ impl AlonzoAuxiliaryData { )) } - pub fn new_shelley_m_a(shelley_m_a: &ShelleyMaFormatAuxData) -> Self { - Self(cml_multi_era::alonzo::AlonzoAuxiliaryData::new_shelley_m_a( - shelley_m_a.clone().into(), + pub fn new_shelley_ma(shelley_ma: &ShelleyMAFormatAuxData) -> Self { + Self(cml_multi_era::alonzo::AlonzoAuxiliaryData::new_shelley_ma( + shelley_ma.clone().into(), )) } @@ -77,10 +77,10 @@ impl AlonzoAuxiliaryData { } } - pub fn as_shelley_m_a(&self) -> Option { + pub fn as_shelley_ma(&self) -> Option { match &self.0 { - cml_multi_era::alonzo::AlonzoAuxiliaryData::ShelleyMA(shelley_m_a) => { - Some(shelley_m_a.clone().into()) + cml_multi_era::alonzo::AlonzoAuxiliaryData::ShelleyMA(shelley_ma) => { + Some(shelley_ma.clone().into()) } _ => None, } diff --git a/multi-era/wasm/src/babbage/mod.rs b/multi-era/wasm/src/babbage/mod.rs index 479818c5..fcaa77be 100644 --- a/multi-era/wasm/src/babbage/mod.rs +++ b/multi-era/wasm/src/babbage/mod.rs @@ -9,7 +9,7 @@ use crate::{ }; use cml_chain_wasm::address::Address; use cml_chain_wasm::assets::{Coin, Mint, Value}; -use cml_chain_wasm::auxdata::{ShelleyFormatAuxData, ShelleyMaFormatAuxData}; +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::{CostModels, ExUnitPrices, ExUnits, PlutusV1Script, PlutusV2Script}; @@ -43,11 +43,9 @@ impl BabbageAuxiliaryData { )) } - pub fn new_shelley_m_a(shelley_m_a: &ShelleyMaFormatAuxData) -> Self { + pub fn new_shelley_ma(shelley_ma: &ShelleyMAFormatAuxData) -> Self { Self( - cml_multi_era::babbage::BabbageAuxiliaryData::new_shelley_m_a( - shelley_m_a.clone().into(), - ), + cml_multi_era::babbage::BabbageAuxiliaryData::new_shelley_ma(shelley_ma.clone().into()), ) } @@ -80,10 +78,10 @@ impl BabbageAuxiliaryData { } } - pub fn as_shelley_m_a(&self) -> Option { + pub fn as_shelley_ma(&self) -> Option { match &self.0 { - cml_multi_era::babbage::BabbageAuxiliaryData::ShelleyMA(shelley_m_a) => { - Some(shelley_m_a.clone().into()) + cml_multi_era::babbage::BabbageAuxiliaryData::ShelleyMA(shelley_ma) => { + Some(shelley_ma.clone().into()) } _ => None, } @@ -703,6 +701,7 @@ impl BabbageTransactionBody { } pub fn set_mint(&mut self, mint: &Mint) { + // hand-edit self.0.mint = Some(cml_multi_era::babbage::utils::BabbageMint::from(Into::< cml_chain::assets::Mint, >::into( @@ -711,6 +710,7 @@ impl BabbageTransactionBody { } pub fn mint(&self) -> Option { + // hand-edit self.0 .mint .as_ref() diff --git a/multi-era/wasm/src/shelley/mod.rs b/multi-era/wasm/src/shelley/mod.rs index 76004a6c..f4ee6d3c 100644 --- a/multi-era/wasm/src/shelley/mod.rs +++ b/multi-era/wasm/src/shelley/mod.rs @@ -49,19 +49,19 @@ impl GenesisKeyDelegation { self.0.genesis_delegate_hash.into() } - pub fn v_r_f_key_hash(&self) -> VRFKeyHash { - self.0.v_r_f_key_hash.into() + pub fn vrf_key_hash(&self) -> VRFKeyHash { + self.0.vrf_key_hash.into() } pub fn new( genesis_hash: &GenesisHash, genesis_delegate_hash: &GenesisDelegateHash, - v_r_f_key_hash: &VRFKeyHash, + vrf_key_hash: &VRFKeyHash, ) -> Self { Self(cml_multi_era::shelley::GenesisKeyDelegation::new( genesis_hash.clone().into(), genesis_delegate_hash.clone().into(), - v_r_f_key_hash.clone().into(), + vrf_key_hash.clone().into(), )) } } @@ -378,13 +378,13 @@ impl ShelleyCertificate { pub fn new_genesis_key_delegation( genesis_hash: &GenesisHash, genesis_delegate_hash: &GenesisDelegateHash, - v_r_f_key_hash: &VRFKeyHash, + vrf_key_hash: &VRFKeyHash, ) -> Self { Self( cml_multi_era::shelley::ShelleyCertificate::new_genesis_key_delegation( genesis_hash.clone().into(), genesis_delegate_hash.clone().into(), - v_r_f_key_hash.clone().into(), + vrf_key_hash.clone().into(), ), ) } @@ -504,14 +504,14 @@ pub enum ShelleyCertificateKind { #[derive(Clone, Debug)] #[wasm_bindgen] -pub struct ShelleyDnsName(cml_multi_era::shelley::ShelleyDnsName); +pub struct ShelleyDNSName(cml_multi_era::shelley::ShelleyDNSName); -impl_wasm_cbor_json_api!(ShelleyDnsName); +impl_wasm_cbor_json_api!(ShelleyDNSName); -impl_wasm_conversions!(cml_multi_era::shelley::ShelleyDnsName, ShelleyDnsName); +impl_wasm_conversions!(cml_multi_era::shelley::ShelleyDNSName, ShelleyDNSName); #[wasm_bindgen] -impl ShelleyDnsName { +impl ShelleyDNSName { pub fn get(&self) -> String { self.0.get().clone() } @@ -569,8 +569,8 @@ impl ShelleyHeaderBody { self.0.issuer_vkey.clone().into() } - pub fn v_r_f_vkey(&self) -> VRFVkey { - self.0.v_r_f_vkey.into() + pub fn vrf_vkey(&self) -> VRFVkey { + self.0.vrf_vkey.into() } pub fn nonce_vrf(&self) -> VRFCert { @@ -602,7 +602,7 @@ impl ShelleyHeaderBody { slot: u64, prev_hash: Option, issuer_vkey: &Vkey, - v_r_f_vkey: &VRFVkey, + vrf_vkey: &VRFVkey, nonce_vrf: &VRFCert, leader_vrf: &VRFCert, block_body_size: u64, @@ -615,7 +615,7 @@ impl ShelleyHeaderBody { slot, prev_hash.map(Into::into), issuer_vkey.clone().into(), - v_r_f_vkey.clone().into(), + vrf_vkey.clone().into(), nonce_vrf.clone().into(), leader_vrf.clone().into(), block_body_size, @@ -696,11 +696,12 @@ impl_wasm_conversions!( #[wasm_bindgen] impl ShelleyMultiHostName { - pub fn shelley_dns_name(&self) -> ShelleyDnsName { + pub fn shelley_dns_name(&self) -> ShelleyDNSName { self.0.shelley_dns_name.clone().into() } - pub fn new(shelley_dns_name: &ShelleyDnsName) -> Self { + /// * `shelley_dns_name` - A SRV DNS record + pub fn new(shelley_dns_name: &ShelleyDNSName) -> Self { Self(cml_multi_era::shelley::ShelleyMultiHostName::new( shelley_dns_name.clone().into(), )) @@ -1024,7 +1025,7 @@ impl ShelleyRelay { pub fn new_shelley_single_host_name( port: Option, - shelley_dns_name: &ShelleyDnsName, + shelley_dns_name: &ShelleyDNSName, ) -> Self { Self( cml_multi_era::shelley::ShelleyRelay::new_shelley_single_host_name( @@ -1034,7 +1035,7 @@ impl ShelleyRelay { ) } - pub fn new_shelley_multi_host_name(shelley_dns_name: &ShelleyDnsName) -> Self { + 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(), @@ -1108,11 +1109,12 @@ impl ShelleySingleHostName { self.0.port } - pub fn shelley_dns_name(&self) -> ShelleyDnsName { + pub fn shelley_dns_name(&self) -> ShelleyDNSName { self.0.shelley_dns_name.clone().into() } - pub fn new(port: Option, shelley_dns_name: &ShelleyDnsName) -> Self { + /// * `shelley_dns_name` - An A or AAAA DNS record + pub fn new(port: Option, shelley_dns_name: &ShelleyDNSName) -> Self { Self(cml_multi_era::shelley::ShelleySingleHostName::new( port, shelley_dns_name.clone().into(), diff --git a/specs/conway/auxdata.cddl b/specs/conway/auxdata.cddl index 5e801638..d9a08dda 100644 --- a/specs/conway/auxdata.cddl +++ b/specs/conway/auxdata.cddl @@ -12,7 +12,7 @@ metadata = _CDDL_CODEGEN_EXTERN_TYPE_ shelley_format_aux_data = metadata -shelley_ma_format_aux_data = [ transaction_metadata: metadata ; Shelley-ma +shelley_MA_format_aux_data = [ transaction_metadata: metadata ; Shelley-ma , auxiliary_scripts: [ * native_script ] ] @@ -26,5 +26,5 @@ conway_format_aux_data = #6.259({ auxiliary_data = shelley_format_aux_data ; @name shelley - / shelley_ma_format_aux_data ; @name shelley_m_a + / shelley_MA_format_aux_data ; @name shelley_MA / conway_format_aux_data ; @name conway diff --git a/specs/conway/certs.cddl b/specs/conway/certs.cddl index e104e593..3f01d3fe 100644 --- a/specs/conway/certs.cddl +++ b/specs/conway/certs.cddl @@ -1,22 +1,32 @@ -certificate = - [ stake_registration - // stake_deregistration - // stake_delegation - // pool_registration - // pool_retirement - // reg_cert - // unreg_cert - // vote_deleg_cert - // stake_vote_deleg_cert - // stake_reg_deleg_cert - // vote_reg_deleg_cert - // stake_vote_reg_deleg_cert - // auth_committee_hot_cert - // resign_committee_cold_cert - // reg_drep_cert - // unreg_drep_cert - // update_drep_cert - ] +certificate = [ + ; @doc Will be deprecated in the next era. Use RegCert instead which takes an explicit deposit amount, as that can change. + stake_registration // + ; @doc Will be deprecated in the next era. Use UnregCert instead which takes an explicit deposit amount, as that can change. + stake_deregistration // + ; @doc Delegate to a take pool only + stake_delegation // + pool_registration // + pool_retirement // + ; @doc Registers a stake credential. + reg_cert // + ; @doc Unregisters a stake credential. + unreg_cert // + ; @doc Delegate to a DRep for voting only + vote_deleg_cert // + ; @doc Delegate to a stake pool and a DRep + stake_vote_deleg_cert // + ; @doc Register a stake credential and delegate to a pool in a single cert + stake_reg_deleg_cert // + ; @doc Register a stake credential and delegate to a DRep in a single cert + vote_reg_deleg_cert // + ; @doc Register a stake credential and delegate to a pool and a DRep in a single cert + stake_vote_reg_deleg_cert // + auth_committee_hot_cert // + resign_committee_cold_cert // + reg_drep_cert // + unreg_drep_cert // + update_drep_cert +] stake_registration = (tag: 0, stake_credential) stake_deregistration = (tag: 1, stake_credential) @@ -39,8 +49,8 @@ pool_retirement = ( ; move_instantaneous_rewards_cert = (tag: 6, move_instantaneous_reward) ; DELEG -reg_cert = (tag: 7, stake_credential, coin) -unreg_cert = (tag: 8, stake_credential, coin) +reg_cert = (tag: 7, stake_credential, deposit: coin) +unreg_cert = (tag: 8, stake_credential, deposit: coin) vote_deleg_cert = (tag: 9, stake_credential, d_rep) stake_vote_deleg_cert = ( tag: 10, @@ -52,22 +62,22 @@ stake_reg_deleg_cert = ( tag: 11, stake_credential, pool: ed25519_key_hash, - coin + deposit: coin ) -vote_reg_deleg_cert = (tag: 12, stake_credential, d_rep, coin) +vote_reg_deleg_cert = (tag: 12, stake_credential, d_rep, deposit: coin) stake_vote_reg_deleg_cert = ( tag: 13, stake_credential, pool: ed25519_key_hash, d_rep, - coin + deposit: coin ) ; GOVCERT auth_committee_hot_cert = (14, committee_cold_credential, committee_hot_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) +reg_drep_cert = (16, drep_credential, deposit: coin, anchor / null) +unreg_drep_cert = (17, drep_credential, deposit: coin) update_drep_cert = (18, drep_credential, anchor / null) d_rep = [ @@ -104,7 +114,7 @@ pool_params = ( operator: ed25519_key_hash ipv4 = bytes .size 4 ; @custom_json ipv6 = bytes .size 16 ; @custom_json -dns_name = tstr .size (0..128) +DNS_name = tstr .size (0..128) single_host_addr = ( tag: 0 , port / null @@ -113,10 +123,10 @@ single_host_addr = ( tag: 0 ) single_host_name = ( tag: 1 , port / null - , dns_name ; An A or AAAA DNS record + , DNS_name ; @doc An A or AAAA DNS record ) multi_host_name = ( tag: 2 - , dns_name ; A SRV DNS record + , DNS_name ; @doc A SRV DNS record ) relay = [ single_host_addr diff --git a/specs/conway/governance.cddl b/specs/conway/governance.cddl index 16353f60..67037a2c 100644 --- a/specs/conway/governance.cddl +++ b/specs/conway/governance.cddl @@ -26,8 +26,8 @@ gov_action = [ parameter_change_action = ( tag: 0, - gov_action_id / null, - protocol_param_update, + action_id: gov_action_id / null, + update: protocol_param_update, policy_hash: script_hash / null, ) diff --git a/specs/conway/plutus.cddl b/specs/conway/plutus.cddl index a0b85994..8e9bbaf9 100644 --- a/specs/conway/plutus.cddl +++ b/specs/conway/plutus.cddl @@ -14,9 +14,14 @@ plutus_v1_script = bytes ; @newtype plutus_v2_script = bytes ; @newtype plutus_v3_script = bytes ; @newtype +; original def: +; { * plutus_data => plutus_data } +; we hand-code it to handle duplicates +plutus_map = _CDDL_CODEGEN_EXTERN_TYPE_ + plutus_data = constr_plutus_data - / { * plutus_data => plutus_data } ; @name map + / plutus_map ; @name map / [ * plutus_data ] ; @name list / big_integer ; @name integer / bounded_bytes ; @name bytes @@ -45,9 +50,9 @@ legacy_redeemer = [ tag: redeemer_tag, index: uint, data: plutus_data, 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 + ; @name LegacyFlatFormat @doc This format will be deprecated in the next era [ + legacy_redeemer ] / - ; @name MapFormat + ; @name MapFormat @doc New map format. Use this when possibe. { + redeemer_key => redeemer_val } redeemer_tag = diff --git a/specs/conway/transaction.cddl b/specs/conway/transaction.cddl index 1351f567..d7b151ad 100644 --- a/specs/conway/transaction.cddl +++ b/specs/conway/transaction.cddl @@ -149,18 +149,16 @@ transaction_witness_set = { ? 7: nonempty_set, ; @name plutus_v3_scripts } -native_script = - [ script_pubkey - // script_all - // script_any - // script_n_of_k - // script_invalid_before - ; Timelock validity intervals are half-open intervals [a, b). - ; This field specifies the left (included) endpoint a. - // script_invalid_hereafter - ; Timelock validity intervals are half-open intervals [a, b). - ; This field specifies the right (excluded) endpoint b. - ] +native_script = [ + script_pubkey // + script_all // + script_any // + script_n_of_k // + ; @doc Timelock validity intervals are half-open intervals [a, b). This field specifies the left (included) endpoint a. + script_invalid_before // + ; @doc Timelock validity intervals are half-open intervals [a, b). This field specifies the right (excluded) endpoint b. + script_invalid_hereafter +] script_pubkey = (tag: 0, ed25519_key_hash) script_all = (tag: 1, [ * native_script ]) diff --git a/specs/multiera/cml_chain/address.cddl b/specs/multiera/_CDDL_CODEGEN_EXTERN_DEPS_DIR_/cml_chain/address.cddl similarity index 100% rename from specs/multiera/cml_chain/address.cddl rename to specs/multiera/_CDDL_CODEGEN_EXTERN_DEPS_DIR_/cml_chain/address.cddl diff --git a/specs/multiera/cml_chain/assets.cddl b/specs/multiera/_CDDL_CODEGEN_EXTERN_DEPS_DIR_/cml_chain/assets.cddl similarity index 100% rename from specs/multiera/cml_chain/assets.cddl rename to specs/multiera/_CDDL_CODEGEN_EXTERN_DEPS_DIR_/cml_chain/assets.cddl diff --git a/specs/multiera/cml_chain/auxdata.cddl b/specs/multiera/_CDDL_CODEGEN_EXTERN_DEPS_DIR_/cml_chain/auxdata.cddl similarity index 62% rename from specs/multiera/cml_chain/auxdata.cddl rename to specs/multiera/_CDDL_CODEGEN_EXTERN_DEPS_DIR_/cml_chain/auxdata.cddl index 2df63764..99ef11eb 100644 --- a/specs/multiera/cml_chain/auxdata.cddl +++ b/specs/multiera/_CDDL_CODEGEN_EXTERN_DEPS_DIR_/cml_chain/auxdata.cddl @@ -1,3 +1,3 @@ metadata = _CDDL_CODEGEN_EXTERN_TYPE_ shelley_format_aux_data = _CDDL_CODEGEN_EXTERN_TYPE_ -shelley_ma_format_aux_data = _CDDL_CODEGEN_EXTERN_TYPE_ \ No newline at end of file +shelley_MA_format_aux_data = _CDDL_CODEGEN_EXTERN_TYPE_ \ No newline at end of file diff --git a/specs/multiera/cml_chain/block.cddl b/specs/multiera/_CDDL_CODEGEN_EXTERN_DEPS_DIR_/cml_chain/block.cddl similarity index 100% rename from specs/multiera/cml_chain/block.cddl rename to specs/multiera/_CDDL_CODEGEN_EXTERN_DEPS_DIR_/cml_chain/block.cddl diff --git a/specs/multiera/cml_chain/byron.cddl b/specs/multiera/_CDDL_CODEGEN_EXTERN_DEPS_DIR_/cml_chain/byron.cddl similarity index 100% rename from specs/multiera/cml_chain/byron.cddl rename to specs/multiera/_CDDL_CODEGEN_EXTERN_DEPS_DIR_/cml_chain/byron.cddl diff --git a/specs/multiera/cml_chain/certs.cddl b/specs/multiera/_CDDL_CODEGEN_EXTERN_DEPS_DIR_/cml_chain/certs.cddl similarity index 100% rename from specs/multiera/cml_chain/certs.cddl rename to specs/multiera/_CDDL_CODEGEN_EXTERN_DEPS_DIR_/cml_chain/certs.cddl diff --git a/specs/multiera/cml_chain/crypto.cddl b/specs/multiera/_CDDL_CODEGEN_EXTERN_DEPS_DIR_/cml_chain/crypto.cddl similarity index 100% rename from specs/multiera/cml_chain/crypto.cddl rename to specs/multiera/_CDDL_CODEGEN_EXTERN_DEPS_DIR_/cml_chain/crypto.cddl diff --git a/specs/multiera/cml_chain/mod.cddl b/specs/multiera/_CDDL_CODEGEN_EXTERN_DEPS_DIR_/cml_chain/mod.cddl similarity index 100% rename from specs/multiera/cml_chain/mod.cddl rename to specs/multiera/_CDDL_CODEGEN_EXTERN_DEPS_DIR_/cml_chain/mod.cddl diff --git a/specs/multiera/cml_chain/plutus.cddl b/specs/multiera/_CDDL_CODEGEN_EXTERN_DEPS_DIR_/cml_chain/plutus.cddl similarity index 100% rename from specs/multiera/cml_chain/plutus.cddl rename to specs/multiera/_CDDL_CODEGEN_EXTERN_DEPS_DIR_/cml_chain/plutus.cddl diff --git a/specs/multiera/cml_chain/transaction.cddl b/specs/multiera/_CDDL_CODEGEN_EXTERN_DEPS_DIR_/cml_chain/transaction.cddl similarity index 100% rename from specs/multiera/cml_chain/transaction.cddl rename to specs/multiera/_CDDL_CODEGEN_EXTERN_DEPS_DIR_/cml_chain/transaction.cddl diff --git a/specs/multiera/allegra/mod.cddl b/specs/multiera/allegra/mod.cddl index f43a42a5..267cfbd8 100644 --- a/specs/multiera/allegra/mod.cddl +++ b/specs/multiera/allegra/mod.cddl @@ -51,7 +51,7 @@ allegra_transaction_witness_set = { allegra_auxiliary_data = shelley_format_aux_data ; @name shelley - / shelley_ma_format_aux_data ; @name shelley_m_a + / shelley_MA_format_aux_data ; @name shelley_MA ; allegra differences allegra_transaction_body = { diff --git a/specs/multiera/alonzo/mod.cddl b/specs/multiera/alonzo/mod.cddl index 15ae7642..9b738d13 100644 --- a/specs/multiera/alonzo/mod.cddl +++ b/specs/multiera/alonzo/mod.cddl @@ -95,7 +95,7 @@ alonzo_format_aux_data = #6.259({ alonzo_auxiliary_data = shelley_format_aux_data ; @name shelley - / shelley_ma_format_aux_data ; @name shelley_m_a + / shelley_MA_format_aux_data ; @name shelley_MA / alonzo_format_aux_data ; @name alonzo alonzo_redeemer = [ diff --git a/specs/multiera/babbage/mod.cddl b/specs/multiera/babbage/mod.cddl index 99d887d7..bb6db753 100644 --- a/specs/multiera/babbage/mod.cddl +++ b/specs/multiera/babbage/mod.cddl @@ -115,7 +115,7 @@ babbage_format_aux_data = #6.259({ babbage_auxiliary_data = shelley_format_aux_data ; @name shelley - / shelley_ma_format_aux_data ; @name shelley_m_a + / shelley_MA_format_aux_data ; @name shelley_MA / babbage_format_aux_data ; @name babbage ; babbage mint has duplicate keys so it needs its own special hand-written struct diff --git a/specs/multiera/shelley/mod.cddl b/specs/multiera/shelley/mod.cddl index 8eb0fb51..1e6791ba 100644 --- a/specs/multiera/shelley/mod.cddl +++ b/specs/multiera/shelley/mod.cddl @@ -49,16 +49,16 @@ shelley_pool_params = ( operator: ed25519_key_hash , pool_metadata: pool_metadata / null ) -shelley_dns_name = tstr .size (0..64) +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_DNS_name, ; @doc 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_DNS_name, ; @doc A SRV DNS record @name dns_name ) shelley_relay = [ From 653fd14dfb25ab1d25107ca9579a831633c73ae5 Mon Sep 17 00:00:00 2001 From: rooooooooob Date: Wed, 10 Jul 2024 15:18:09 +0900 Subject: [PATCH 11/16] Move RawBytesEncoding and standardize use (#340) Fixes #334 Moves RawBytesEncoding to cml_core::serialization as there is nothing specific about crypto with it, and it can be used in many other places (Asset names, plutus scripts, etc). Add wasm macros for declaring the RawBytesEncoding API automatically using the rust type's trait impl Add missing hash() to PlutusV3Script Document AssetName on how to convert to/from using utf8 traits in rust Use dcSpark/cddl-codegen#240 to remove confusing `get()` (what is it getting?) functions on some wrapper types. These are replaced with `RawBytesEncoding` to standardize use with the rest of CML --- chain/rust/src/assets/mod.rs | 5 +-- chain/rust/src/assets/utils.rs | 14 +++++- chain/rust/src/genesis/byron/parse.rs | 3 ++ chain/rust/src/plutus/mod.rs | 12 ------ chain/rust/src/plutus/utils.rs | 36 ++++++++++++++-- chain/wasm/src/assets/mod.rs | 7 --- chain/wasm/src/assets/utils.rs | 15 +++---- chain/wasm/src/plutus/mod.rs | 21 --------- chain/wasm/src/plutus/utils.rs | 17 +++++++- cip25/rust/src/utils.rs | 8 ++-- core/rust/src/serialization.rs | 21 +++++++++ core/wasm/src/lib.rs | 3 ++ core/wasm/src/wasm_wrappers.rs | 43 +++++++++++++++++++ crypto/rust/src/lib.rs | 61 ++++++++++----------------- crypto/wasm/Cargo.toml | 1 + crypto/wasm/src/lib.rs | 53 +++-------------------- multi-era/rust/src/babbage/utils.rs | 3 +- specs/conway/assets.cddl | 2 +- 18 files changed, 172 insertions(+), 153 deletions(-) diff --git a/chain/rust/src/assets/mod.rs b/chain/rust/src/assets/mod.rs index adc3911b..1a6aee2f 100644 --- a/chain/rust/src/assets/mod.rs +++ b/chain/rust/src/assets/mod.rs @@ -12,6 +12,7 @@ use cml_core::error::*; use std::convert::TryFrom; +/// Use TryFrom<&str> / TryInto<&str> for utf8 text conversion and RawBytesEncoding for direct bytes access #[derive(Clone, Debug, derivative::Derivative)] #[derivative(Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct AssetName { @@ -26,10 +27,6 @@ pub struct AssetName { } impl AssetName { - pub fn get(&self) -> &Vec { - &self.inner - } - pub fn new(inner: Vec) -> Result { if inner.len() > 32 { return Err(DeserializeError::new( diff --git a/chain/rust/src/assets/utils.rs b/chain/rust/src/assets/utils.rs index c3d6a56f..39d83b19 100644 --- a/chain/rust/src/assets/utils.rs +++ b/chain/rust/src/assets/utils.rs @@ -51,7 +51,17 @@ impl<'a> TryInto<&'a str> for &'a AssetName { type Error = std::str::Utf8Error; fn try_into(self) -> Result<&'a str, Self::Error> { - std::str::from_utf8(self.get()) + std::str::from_utf8(self.to_raw_bytes()) + } +} + +impl RawBytesEncoding for AssetName { + fn to_raw_bytes(&self) -> &[u8] { + self.inner.as_ref() + } + + fn from_raw_bytes(bytes: &[u8]) -> Result { + Self::new(bytes.to_vec()) } } @@ -71,7 +81,7 @@ impl std::fmt::Debug for AssetBundle { for (pid, assets) in self.0.iter() { let pid_hex = hex::encode(pid.to_raw_bytes()); for (an, val) in assets.iter() { - let an_hex = hex::encode(an.get()); + let an_hex = hex::encode(an.to_raw_bytes()); let an_name = if an_hex.len() > 8 { format!( "{}..{}", diff --git a/chain/rust/src/genesis/byron/parse.rs b/chain/rust/src/genesis/byron/parse.rs index 1ace4de7..ddbedc88 100644 --- a/chain/rust/src/genesis/byron/parse.rs +++ b/chain/rust/src/genesis/byron/parse.rs @@ -3,6 +3,7 @@ use base64::{ Engine, }; use cbor_event::cbor; +use cml_core::DeserializeError; use cml_crypto::{CryptoError, RawBytesEncoding}; use serde_json; use std::collections::BTreeMap; @@ -29,6 +30,8 @@ pub enum GenesisJSONError { Serde(#[from] serde_json::Error), #[error("Crypto: {0:?}")] CryptoError(#[from] CryptoError), + #[error("Deserialize: {0:?}")] + DeserializeError(#[from] DeserializeError), #[error("Base64: {0:?}")] Base64(#[from] base64::DecodeError), #[error("ParseInt: {0:?}")] diff --git a/chain/rust/src/plutus/mod.rs b/chain/rust/src/plutus/mod.rs index e1941b42..b815ed90 100644 --- a/chain/rust/src/plutus/mod.rs +++ b/chain/rust/src/plutus/mod.rs @@ -244,10 +244,6 @@ pub struct PlutusV1Script { } impl PlutusV1Script { - pub fn get(&self) -> &Vec { - &self.inner - } - pub fn new(inner: Vec) -> Self { Self { inner, @@ -317,10 +313,6 @@ pub struct PlutusV2Script { } impl PlutusV2Script { - pub fn get(&self) -> &Vec { - &self.inner - } - pub fn new(inner: Vec) -> Self { Self { inner, @@ -390,10 +382,6 @@ pub struct PlutusV3Script { } impl PlutusV3Script { - pub fn get(&self) -> &Vec { - &self.inner - } - pub fn new(inner: Vec) -> Self { Self { inner, diff --git a/chain/rust/src/plutus/utils.rs b/chain/rust/src/plutus/utils.rs index ae228c23..300d4e63 100644 --- a/chain/rust/src/plutus/utils.rs +++ b/chain/rust/src/plutus/utils.rs @@ -452,19 +452,49 @@ impl From for PlutusScript { impl PlutusV1Script { pub fn hash(&self) -> ScriptHash { - hash_script(ScriptHashNamespace::PlutusV1, self.get()) + hash_script(ScriptHashNamespace::PlutusV1, self.to_raw_bytes()) } } impl PlutusV2Script { pub fn hash(&self) -> ScriptHash { - hash_script(ScriptHashNamespace::PlutusV2, self.get()) + hash_script(ScriptHashNamespace::PlutusV2, self.to_raw_bytes()) } } impl PlutusV3Script { pub fn hash(&self) -> ScriptHash { - hash_script(ScriptHashNamespace::PlutusV3, self.get()) + hash_script(ScriptHashNamespace::PlutusV3, self.to_raw_bytes()) + } +} + +impl RawBytesEncoding for PlutusV1Script { + fn to_raw_bytes(&self) -> &[u8] { + self.inner.as_ref() + } + + fn from_raw_bytes(bytes: &[u8]) -> Result { + Ok(Self::new(bytes.to_vec())) + } +} + +impl RawBytesEncoding for PlutusV2Script { + fn to_raw_bytes(&self) -> &[u8] { + self.inner.as_ref() + } + + fn from_raw_bytes(bytes: &[u8]) -> Result { + Ok(Self::new(bytes.to_vec())) + } +} + +impl RawBytesEncoding for PlutusV3Script { + fn to_raw_bytes(&self) -> &[u8] { + self.inner.as_ref() + } + + fn from_raw_bytes(bytes: &[u8]) -> Result { + Ok(Self::new(bytes.to_vec())) } } diff --git a/chain/wasm/src/assets/mod.rs b/chain/wasm/src/assets/mod.rs index 62966512..b946a230 100644 --- a/chain/wasm/src/assets/mod.rs +++ b/chain/wasm/src/assets/mod.rs @@ -18,10 +18,3 @@ pub struct AssetName(cml_chain::assets::AssetName); impl_wasm_cbor_json_api!(AssetName); impl_wasm_conversions!(cml_chain::assets::AssetName, AssetName); - -#[wasm_bindgen] -impl AssetName { - pub fn get(&self) -> Vec { - self.0.get().clone() - } -} diff --git a/chain/wasm/src/assets/utils.rs b/chain/wasm/src/assets/utils.rs index b5393091..8fb40e6b 100644 --- a/chain/wasm/src/assets/utils.rs +++ b/chain/wasm/src/assets/utils.rs @@ -6,7 +6,9 @@ use std::{ use crate::{assets::AssetName, AssetNameList, MapAssetNameToNonZeroInt64, PolicyId, PolicyIdList}; use wasm_bindgen::{prelude::wasm_bindgen, JsError, JsValue}; -use cml_core_wasm::{impl_wasm_cbor_json_api, impl_wasm_conversions, impl_wasm_map}; +use cml_core_wasm::{ + impl_raw_bytes_api, impl_wasm_cbor_json_api, impl_wasm_conversions, impl_wasm_map, +}; use super::Coin; @@ -25,15 +27,6 @@ impl_wasm_map!( #[wasm_bindgen] impl AssetName { - /** - * Create an AssetName from raw bytes. 64 byte maximum. - */ - pub fn from_bytes(bytes: Vec) -> Result { - cml_chain::assets::AssetName::try_from(bytes) - .map(Into::into) - .map_err(Into::into) - } - /** * Create an AssetName from utf8 string. 64 byte (not char!) maximum. */ @@ -55,6 +48,8 @@ impl AssetName { } } +impl_raw_bytes_api!(cml_chain::assets::AssetName, AssetName); + #[derive(Clone, Debug)] #[wasm_bindgen] pub struct MultiAsset(cml_chain::assets::MultiAsset); diff --git a/chain/wasm/src/plutus/mod.rs b/chain/wasm/src/plutus/mod.rs index 33df2ea2..58d3db19 100644 --- a/chain/wasm/src/plutus/mod.rs +++ b/chain/wasm/src/plutus/mod.rs @@ -224,13 +224,6 @@ impl_wasm_cbor_json_api!(PlutusV1Script); impl_wasm_conversions!(cml_chain::plutus::PlutusV1Script, PlutusV1Script); -#[wasm_bindgen] -impl PlutusV1Script { - pub fn get(&self) -> Vec { - self.0.get().clone() - } -} - #[derive(Clone, Debug)] #[wasm_bindgen] pub struct PlutusV2Script(cml_chain::plutus::PlutusV2Script); @@ -239,13 +232,6 @@ impl_wasm_cbor_json_api!(PlutusV2Script); impl_wasm_conversions!(cml_chain::plutus::PlutusV2Script, PlutusV2Script); -#[wasm_bindgen] -impl PlutusV2Script { - pub fn get(&self) -> Vec { - self.0.get().clone() - } -} - #[derive(Clone, Debug)] #[wasm_bindgen] pub struct PlutusV3Script(cml_chain::plutus::PlutusV3Script); @@ -254,13 +240,6 @@ impl_wasm_cbor_json_api!(PlutusV3Script); impl_wasm_conversions!(cml_chain::plutus::PlutusV3Script, PlutusV3Script); -#[wasm_bindgen] -impl PlutusV3Script { - pub fn get(&self) -> Vec { - self.0.get().clone() - } -} - #[derive(Clone, Debug)] #[wasm_bindgen] pub struct RedeemerKey(cml_chain::plutus::RedeemerKey); diff --git a/chain/wasm/src/plutus/utils.rs b/chain/wasm/src/plutus/utils.rs index e2ca0103..2b458235 100644 --- a/chain/wasm/src/plutus/utils.rs +++ b/chain/wasm/src/plutus/utils.rs @@ -3,7 +3,9 @@ use crate::{ LegacyRedeemerList, PlutusDataList, }; use cml_chain::plutus::Language; -use cml_core_wasm::{impl_wasm_cbor_api, impl_wasm_cbor_json_api, impl_wasm_conversions}; +use cml_core_wasm::{ + impl_raw_bytes_api, impl_wasm_cbor_api, impl_wasm_cbor_json_api, impl_wasm_conversions, +}; use cml_crypto_wasm::ScriptHash; use wasm_bindgen::prelude::{wasm_bindgen, JsError, JsValue}; @@ -152,6 +154,19 @@ impl PlutusV2Script { } } +#[wasm_bindgen] +impl PlutusV3Script { + pub fn hash(&self) -> ScriptHash { + self.0.hash().into() + } +} + +impl_raw_bytes_api!(cml_chain::plutus::PlutusV1Script, PlutusV1Script); + +impl_raw_bytes_api!(cml_chain::plutus::PlutusV2Script, PlutusV2Script); + +impl_raw_bytes_api!(cml_chain::plutus::PlutusV3Script, PlutusV3Script); + #[wasm_bindgen] impl Redeemers { pub fn to_flat_format(&self) -> LegacyRedeemerList { diff --git a/cip25/rust/src/utils.rs b/cip25/rust/src/utils.rs index 2b61f379..1df70073 100644 --- a/cip25/rust/src/utils.rs +++ b/cip25/rust/src/utils.rs @@ -7,7 +7,6 @@ pub use cml_chain::{ PolicyId, }; pub use cml_core::{error::*, serialization::*}; -use cml_crypto::RawBytesEncoding; use std::io::{BufRead, Seek, SeekFrom, Write}; use crate::{CIP25ChunkableString, CIP25Metadata, CIP25MetadataDetails, CIP25String64}; @@ -251,7 +250,7 @@ impl CIP25LabelMetadata { details: CIP25MetadataDetails, ) -> Result, CIP25Error> { if self.version == CIP25Version::V1 { - if let Err(e) = String::from_utf8(asset_name.get().clone()) { + if let Err(e) = String::from_utf8(asset_name.to_raw_bytes().to_vec()) { return Err(CIP25Error::Version1NonStringAsset(asset_name, e)); } } @@ -296,7 +295,8 @@ impl cbor_event::se::Serialize for CIP25LabelMetadata { for (asset_name, details) in assets.iter() { // hand-edit: write as string // note: this invariant is checked during setting and data is private - let asset_name_str = String::from_utf8(asset_name.get().clone()).unwrap(); + let asset_name_str = + String::from_utf8(asset_name.to_raw_bytes().to_vec()).unwrap(); serializer.write_text(asset_name_str)?; details.serialize(serializer)?; } @@ -313,7 +313,7 @@ impl cbor_event::se::Serialize for CIP25LabelMetadata { serializer.write_map(cbor_event::Len::Len(assets.len() as u64))?; for (asset_name, details) in assets.iter() { // hand-edit: write bytes - serializer.write_bytes(asset_name.get())?; + serializer.write_bytes(asset_name.to_raw_bytes())?; details.serialize(serializer)?; } diff --git a/core/rust/src/serialization.rs b/core/rust/src/serialization.rs index 18f92a2c..0249c440 100644 --- a/core/rust/src/serialization.rs +++ b/core/rust/src/serialization.rs @@ -288,3 +288,24 @@ impl FromBytes for T { Self::deserialize(&mut raw).map_err(Into::into) } } +pub trait RawBytesEncoding { + fn to_raw_bytes(&self) -> &[u8]; + + fn from_raw_bytes(bytes: &[u8]) -> Result + where + Self: Sized; + + fn to_raw_hex(&self) -> String { + hex::encode(self.to_raw_bytes()) + } + + fn from_raw_hex(hex_str: &str) -> Result + where + Self: Sized, + { + let bytes = hex::decode(hex_str).map_err(|e| { + DeserializeError::from(DeserializeFailure::InvalidStructure(Box::new(e))) + })?; + Self::from_raw_bytes(bytes.as_ref()) + } +} diff --git a/core/wasm/src/lib.rs b/core/wasm/src/lib.rs index c3295315..aaabee57 100644 --- a/core/wasm/src/lib.rs +++ b/core/wasm/src/lib.rs @@ -2,6 +2,9 @@ use wasm_bindgen::prelude::{wasm_bindgen, JsValue}; use cml_core::serialization::{Deserialize, Serialize}; +// re-export to make macros easier to use +pub use cml_core::serialization::RawBytesEncoding; + #[macro_use] pub mod wasm_wrappers; diff --git a/core/wasm/src/wasm_wrappers.rs b/core/wasm/src/wasm_wrappers.rs index aa0ae9f1..2840bcb2 100644 --- a/core/wasm/src/wasm_wrappers.rs +++ b/core/wasm/src/wasm_wrappers.rs @@ -550,3 +550,46 @@ macro_rules! impl_wasm_json_api { } }; } + +#[macro_export] +macro_rules! impl_raw_bytes_api { + ($rust:ty, $wasm:ident) => { + #[wasm_bindgen] + impl $wasm { + /** + * Direct raw bytes without any CBOR structure + */ + pub fn to_raw_bytes(&self) -> Vec { + use cml_core_wasm::RawBytesEncoding; + self.0.to_raw_bytes().to_vec() + } + + /** + * Parse from the direct raw bytes, without any CBOR structure + */ + pub fn from_raw_bytes(bytes: &[u8]) -> Result<$wasm, wasm_bindgen::JsError> { + use cml_core_wasm::RawBytesEncoding; + <$rust>::from_raw_bytes(bytes).map(Self).map_err(Into::into) + } + + /** + * Direct raw bytes without any CBOR structure, as a hex-encoded string + */ + pub fn to_hex(&self) -> String { + use cml_core_wasm::RawBytesEncoding; + self.0.to_raw_hex() + } + + /** + * Parse from a hex string of the direct raw bytes, without any CBOR structure + */ + pub fn from_hex(input: &str) -> Result<$wasm, wasm_bindgen::JsError> { + use cml_core_wasm::RawBytesEncoding; + <$rust>::from_raw_hex(input) + .map(Into::into) + .map(Self) + .map_err(Into::into) + } + } + }; +} diff --git a/crypto/rust/src/lib.rs b/crypto/rust/src/lib.rs index cea53404..bda9bfd7 100644 --- a/crypto/rust/src/lib.rs +++ b/crypto/rust/src/lib.rs @@ -2,7 +2,7 @@ use crate::chain_crypto::bech32::Bech32; pub use cml_core::{ error::{DeserializeError, DeserializeFailure}, - serialization::{Deserialize, Serialize, StringEncoding}, + serialization::{Deserialize, RawBytesEncoding, Serialize, StringEncoding}, }; use cryptoxide::blake2b::Blake2b; pub use derivative::Derivative; @@ -22,26 +22,6 @@ pub mod typed_bytes; #[macro_use] extern crate cfg_if; -pub trait RawBytesEncoding { - fn to_raw_bytes(&self) -> &[u8]; - - fn from_raw_bytes(bytes: &[u8]) -> Result - where - Self: Sized; - - fn to_raw_hex(&self) -> String { - hex::encode(self.to_raw_bytes()) - } - - fn from_raw_hex(hex_str: &str) -> Result - where - Self: Sized, - { - let bytes = hex::decode(hex_str)?; - Self::from_raw_bytes(bytes.as_ref()) - } -} - #[derive(Debug, thiserror::Error)] pub enum CryptoError { #[error("Bech32: {0}")] @@ -124,7 +104,7 @@ impl Bip32PrivateKey { buf[0..64].clone_from_slice(&bytes[0..64]); buf[64..96].clone_from_slice(&bytes[96..128]); - Bip32PrivateKey::from_raw_bytes(&buf) + Bip32PrivateKey::from_raw_bytes(&buf).map_err(Into::into) } /// see from_128_xprv pub fn to_128_xprv(&self) -> Vec { @@ -181,9 +161,9 @@ impl RawBytesEncoding for Bip32PrivateKey { self.0.as_ref() } - fn from_raw_bytes(bytes: &[u8]) -> Result { + fn from_raw_bytes(bytes: &[u8]) -> Result { chain_crypto::SecretKey::::from_binary(bytes) - .map_err(Into::into) + .map_err(|e| DeserializeFailure::InvalidStructure(Box::new(e)).into()) .map(Bip32PrivateKey) } } @@ -248,9 +228,9 @@ impl RawBytesEncoding for Bip32PublicKey { self.0.as_ref() } - fn from_raw_bytes(bytes: &[u8]) -> Result { + fn from_raw_bytes(bytes: &[u8]) -> Result { chain_crypto::PublicKey::::from_binary(bytes) - .map_err(Into::into) + .map_err(|e| DeserializeFailure::InvalidStructure(Box::new(e)).into()) .map(Bip32PublicKey) } } @@ -339,8 +319,10 @@ impl RawBytesEncoding for PrivateKey { } } - fn from_raw_bytes(bytes: &[u8]) -> Result { - Self::from_normal_bytes(bytes).or_else(|_| Self::from_extended_bytes(bytes)) + fn from_raw_bytes(bytes: &[u8]) -> Result { + Self::from_normal_bytes(bytes) + .or_else(|_| Self::from_extended_bytes(bytes)) + .map_err(|e| DeserializeFailure::InvalidStructure(Box::new(e)).into()) } } @@ -387,9 +369,9 @@ impl RawBytesEncoding for PublicKey { self.0.as_ref() } - fn from_raw_bytes(bytes: &[u8]) -> Result { + fn from_raw_bytes(bytes: &[u8]) -> Result { chain_crypto::PublicKey::from_binary(bytes) - .map_err(Into::into) + .map_err(|e| DeserializeFailure::InvalidStructure(Box::new(e)).into()) .map(PublicKey) } } @@ -429,10 +411,10 @@ macro_rules! impl_signature { self.0.as_ref() } - fn from_raw_bytes(bytes: &[u8]) -> Result { + fn from_raw_bytes(bytes: &[u8]) -> Result { chain_crypto::Signature::from_binary(bytes.as_ref()) .map(Self) - .map_err(Into::into) + .map_err(|e| DeserializeFailure::InvalidStructure(Box::new(e)).into()) } } @@ -528,8 +510,10 @@ macro_rules! impl_hash_type { hex::encode(&self.0.as_ref()) } - pub fn from_hex(input: &str) -> Result { - let hex_bytes = hex::decode(input)?; + pub fn from_hex(input: &str) -> Result { + let hex_bytes = hex::decode(input).map_err(|e| { + DeserializeError::from(DeserializeFailure::InvalidStructure(Box::new(e))) + })?; Self::from_raw_bytes(&hex_bytes) } } @@ -557,7 +541,7 @@ macro_rules! impl_hash_type { self.0.as_ref() } - fn from_raw_bytes(bytes: &[u8]) -> Result { + fn from_raw_bytes(bytes: &[u8]) -> Result { use std::convert::TryInto; match bytes.len() { $byte_count => Ok($name(bytes[..$byte_count].try_into().unwrap())), @@ -570,8 +554,7 @@ macro_rules! impl_hash_type { Err(DeserializeError::new( stringify!($name), DeserializeFailure::CBOR(cbor_error), - ) - .into()) + )) } } } @@ -652,10 +635,10 @@ impl RawBytesEncoding for LegacyDaedalusPrivateKey { self.0.as_ref() } - fn from_raw_bytes(bytes: &[u8]) -> Result { + fn from_raw_bytes(bytes: &[u8]) -> Result { chain_crypto::SecretKey::::from_binary(bytes) .map(LegacyDaedalusPrivateKey) - .map_err(|e| e.into()) + .map_err(|e| DeserializeFailure::InvalidStructure(Box::new(e)).into()) } } diff --git a/crypto/wasm/Cargo.toml b/crypto/wasm/Cargo.toml index 9cc87314..f6b14588 100644 --- a/crypto/wasm/Cargo.toml +++ b/crypto/wasm/Cargo.toml @@ -14,6 +14,7 @@ keywords = ["cardano"] crate-type = ["cdylib", "rlib"] [dependencies] +cml-core-wasm = { path = "../../core/wasm", version = "5.3.1" } cml-crypto = { path = "../rust", version = "5.3.1" } cbor_event = "2.2.0" wasm-bindgen = { version = "0.2.87" } diff --git a/crypto/wasm/src/lib.rs b/crypto/wasm/src/lib.rs index 358c7848..4f017bba 100644 --- a/crypto/wasm/src/lib.rs +++ b/crypto/wasm/src/lib.rs @@ -333,39 +333,20 @@ macro_rules! impl_signature { #[wasm_bindgen] impl $name { - pub fn to_raw_bytes(&self) -> Vec { - self.0.to_raw_bytes().to_vec() - } - pub fn to_bech32(&self) -> String { self.0.to_bech32() } - pub fn to_hex(&self) -> String { - self.0.to_raw_hex() - } - - pub fn from_bech32(bech32_str: &str) -> Result<$name, JsError> { + pub fn from_bech32(bech32_str: &str) -> Result<$name, wasm_bindgen::JsError> { cml_crypto::$name::from_bech32(bech32_str) .map(Into::into) .map(Self) .map_err(Into::into) } - - pub fn from_hex(input: &str) -> Result<$name, JsError> { - cml_crypto::$name::from_raw_hex(input) - .map(Into::into) - .map(Self) - .map_err(Into::into) - } - - pub fn from_raw_bytes(bytes: &[u8]) -> Result<$name, JsError> { - cml_crypto::$name::from_raw_bytes(bytes) - .map(Self) - .map_err(Into::into) - } } + cml_core_wasm::impl_raw_bytes_api!(cml_crypto::$name, $name); + impl From for $name { fn from(inner: cml_crypto::$name) -> Self { Self(inner) @@ -397,11 +378,6 @@ macro_rules! impl_hash_type_ext { #[wasm_bindgen::prelude::wasm_bindgen] impl $wasm_name { - pub fn to_raw_bytes(&self) -> Vec { - use cml_crypto::RawBytesEncoding; - self.0.to_raw_bytes().to_vec() - } - pub fn to_bech32( &self, prefix: &str, @@ -409,11 +385,6 @@ macro_rules! impl_hash_type_ext { self.0.to_bech32(prefix).map_err(Into::into) } - pub fn to_hex(&self) -> String { - use cml_crypto::RawBytesEncoding; - self.0.to_raw_hex() - } - pub fn from_bech32( bech32_str: &str, ) -> Result<$wasm_name, wasm_bindgen::prelude::JsError> { @@ -422,22 +393,6 @@ macro_rules! impl_hash_type_ext { .map(Self) .map_err(Into::into) } - - pub fn from_hex(input: &str) -> Result<$wasm_name, wasm_bindgen::prelude::JsError> { - use cml_crypto::RawBytesEncoding; - <$rust_name>::from_raw_hex(input) - .map(Self) - .map_err(Into::into) - } - - pub fn from_raw_bytes( - bytes: &[u8], - ) -> Result<$wasm_name, wasm_bindgen::prelude::JsError> { - use cml_crypto::RawBytesEncoding; - <$rust_name>::from_raw_bytes(bytes) - .map(Self) - .map_err(Into::into) - } } impl From<$rust_name> for $wasm_name { @@ -457,6 +412,8 @@ macro_rules! impl_hash_type_ext { &self.0 } } + + cml_core_wasm::impl_raw_bytes_api!($rust_name, $wasm_name); }; } diff --git a/multi-era/rust/src/babbage/utils.rs b/multi-era/rust/src/babbage/utils.rs index 9461402e..cd45180c 100644 --- a/multi-era/rust/src/babbage/utils.rs +++ b/multi-era/rust/src/babbage/utils.rs @@ -194,7 +194,8 @@ impl Serialize for BabbageMint { .map(|(i, _)| i) .collect::>(); if force_canonical { - inner_key_order.sort_by(|i, j| assets[*i].0.get().cmp(assets[*j].0.get())); + inner_key_order + .sort_by(|i, j| assets[*i].0.to_raw_bytes().cmp(assets[*j].0.to_raw_bytes())); } for (j, (asset_name, coin)) in inner_key_order.into_iter().zip(assets.iter()) { diff --git a/specs/conway/assets.cddl b/specs/conway/assets.cddl index 1fcef9bd..a1b86709 100644 --- a/specs/conway/assets.cddl +++ b/specs/conway/assets.cddl @@ -4,7 +4,7 @@ coin = uint ; but possibly it could be its own type with bounds checking (!=0) positive_coin = coin -asset_name = bytes .size (0..32) +asset_name = bytes .size (0..32) ; @doc Use TryFrom<&str> / TryInto<&str> for utf8 text conversion and RawBytesEncoding for direct bytes access ; these two are technically hand-written but we keep them here so that other code can ; continue thinking they're maps and handle them like so (encoding details, etc) From 508f31bae94b5489bb7d4f1b5a0527b3132c456e Mon Sep 17 00:00:00 2001 From: rooooooooob Date: Sun, 14 Jul 2024 15:00:26 -0700 Subject: [PATCH 12/16] add serde::Serialize/Deserialize to NetworkInfo (#342) --- chain/rust/src/genesis/network_info.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/chain/rust/src/genesis/network_info.rs b/chain/rust/src/genesis/network_info.rs index 6e942d91..7893ae67 100644 --- a/chain/rust/src/genesis/network_info.rs +++ b/chain/rust/src/genesis/network_info.rs @@ -7,7 +7,9 @@ use cml_core::network::{ PREVIEW_NETWORK_MAGIC, SANCHO_TESTNET_NETWORK_MAGIC, }; -#[derive(Debug, Clone, Eq, Hash, Ord, PartialEq, PartialOrd)] +#[derive( + Debug, Clone, Eq, Hash, Ord, PartialEq, PartialOrd, serde::Serialize, serde::Deserialize, +)] pub struct NetworkInfo { network_id: u8, protocol_magic: ProtocolMagic, From 4cb843271a21aef507465c5e327a320f56801d26 Mon Sep 17 00:00:00 2001 From: rooooooooob Date: Tue, 16 Jul 2024 08:51:52 -0700 Subject: [PATCH 13/16] Governance Builders (#333) * Governance Builders Adds `VoteBuilder` and `ProposalBuilder` to facilitate creation of votes and voting proposals to transactions. * Hook Vote/Proposal Builders into TxBuilder/RedeemerBuilder * Fix deposit/required certs * Fix proposal deposits --- .../rust/src/builders/certificate_builder.rs | 11 +- chain/rust/src/builders/input_builder.rs | 7 +- chain/rust/src/builders/mod.rs | 3 + chain/rust/src/builders/proposal_builder.rs | 165 +++++++++++++ chain/rust/src/builders/redeemer_builder.rs | 53 ++++- chain/rust/src/builders/tx_builder.rs | 69 +++++- chain/rust/src/builders/utils.rs | 14 ++ chain/rust/src/builders/vote_builder.rs | 221 ++++++++++++++++++ chain/rust/src/deposit.rs | 33 ++- chain/rust/src/governance/mod.rs | 1 + chain/rust/src/governance/utils.rs | 48 ++++ chain/wasm/src/builders/mod.rs | 2 + chain/wasm/src/builders/proposal_builder.rs | 99 ++++++++ chain/wasm/src/builders/redeemer_builder.rs | 11 +- chain/wasm/src/builders/tx_builder.rs | 11 +- chain/wasm/src/builders/vote_builder.rs | 120 ++++++++++ chain/wasm/src/governance/mod.rs | 2 + chain/wasm/src/governance/utils.rs | 23 ++ 18 files changed, 873 insertions(+), 20 deletions(-) create mode 100644 chain/rust/src/builders/proposal_builder.rs create mode 100644 chain/rust/src/builders/utils.rs create mode 100644 chain/rust/src/builders/vote_builder.rs create mode 100644 chain/rust/src/governance/utils.rs create mode 100644 chain/wasm/src/builders/proposal_builder.rs create mode 100644 chain/wasm/src/builders/vote_builder.rs create mode 100644 chain/wasm/src/governance/utils.rs diff --git a/chain/rust/src/builders/certificate_builder.rs b/chain/rust/src/builders/certificate_builder.rs index f20701e1..677ccd3d 100644 --- a/chain/rust/src/builders/certificate_builder.rs +++ b/chain/rust/src/builders/certificate_builder.rs @@ -183,9 +183,14 @@ pub fn add_cert_vkeys( vkeys.insert(*hash); } }, - Certificate::RegDrepCert(_cert) => { - // does not need a witness - } + Certificate::RegDrepCert(cert) => match &cert.drep_credential { + StakeCredential::Script { hash, .. } => { + return Err(CertBuilderError::ExpectedKeyHash(*hash)) + } + StakeCredential::PubKey { hash, .. } => { + vkeys.insert(*hash); + } + }, Certificate::UnregDrepCert(cert) => match &cert.drep_credential { StakeCredential::Script { hash, .. } => { return Err(CertBuilderError::ExpectedKeyHash(*hash)) diff --git a/chain/rust/src/builders/input_builder.rs b/chain/rust/src/builders/input_builder.rs index 5687f097..b17f7d03 100644 --- a/chain/rust/src/builders/input_builder.rs +++ b/chain/rust/src/builders/input_builder.rs @@ -2,6 +2,7 @@ use crate::builders::witness_builder::{InputAggregateWitnessData, PartialPlutusW use super::{ tx_builder::TransactionUnspentOutput, + utils::required_wits_from_required_signers, witness_builder::{NativeScriptWitnessInfo, RequiredWitnessSet}, }; @@ -138,11 +139,7 @@ impl SingleInputBuilder { required_signers: RequiredSigners, datum: Option, ) -> Result { - let mut required_wits = RequiredWitnessSet::default(); - required_signers - .as_ref() - .iter() - .for_each(|required_signer| required_wits.add_vkey_key_hash(*required_signer)); + let mut required_wits = required_wits_from_required_signers(&required_signers); input_required_wits(&self.utxo_info, &mut required_wits); let mut required_wits_left = required_wits.clone(); diff --git a/chain/rust/src/builders/mod.rs b/chain/rust/src/builders/mod.rs index 30911f48..13f63202 100644 --- a/chain/rust/src/builders/mod.rs +++ b/chain/rust/src/builders/mod.rs @@ -2,7 +2,10 @@ pub mod certificate_builder; pub mod input_builder; pub mod mint_builder; pub mod output_builder; +pub mod proposal_builder; pub mod redeemer_builder; pub mod tx_builder; +mod utils; +pub mod vote_builder; pub mod withdrawal_builder; pub mod witness_builder; diff --git a/chain/rust/src/builders/proposal_builder.rs b/chain/rust/src/builders/proposal_builder.rs new file mode 100644 index 00000000..93f7739c --- /dev/null +++ b/chain/rust/src/builders/proposal_builder.rs @@ -0,0 +1,165 @@ +use crate::{ + crypto::hash::hash_plutus_data, governance::ProposalProcedure, plutus::PlutusData, + transaction::NativeScript, RequiredSigners, +}; + +use super::{ + utils::required_wits_from_required_signers, + witness_builder::{ + InputAggregateWitnessData, NativeScriptWitnessInfo, PartialPlutusWitness, + RequiredWitnessSet, + }, +}; + +#[derive(Debug, thiserror::Error)] +pub enum ProposalBuilderError { + #[error("Proposal uses script. Call with_plutus_proposal() instead.")] + ProposalIsScript, + #[error("Proposal uses key hash. Call with_proposal() instead.")] + ProposalIsKeyHash, + #[error("Missing the following witnesses for the input: {0:?}")] + MissingWitnesses(Box), +} + +#[derive(Clone, Debug, Default)] +pub struct ProposalBuilderResult { + pub proposals: Vec, + pub required_wits: RequiredWitnessSet, + pub aggregate_witnesses: Vec, +} + +#[derive(Clone, Debug)] +pub struct ProposalBuilder { + result: ProposalBuilderResult, +} + +impl Default for ProposalBuilder { + fn default() -> Self { + Self::new() + } +} + +impl ProposalBuilder { + pub fn new() -> Self { + Self { + result: ProposalBuilderResult::default(), + } + } + + pub fn with_proposal( + mut self, + proposal: ProposalProcedure, + ) -> Result { + if proposal.gov_action.script_hash().is_some() { + return Err(ProposalBuilderError::ProposalIsScript); + } + + self.result.proposals.push(proposal.clone()); + + Ok(self) + } + + pub fn with_native_script_proposal( + mut self, + proposal: ProposalProcedure, + native_script: NativeScript, + witness_info: NativeScriptWitnessInfo, + ) -> Result { + if let Some(script_hash) = proposal.gov_action.script_hash() { + if *script_hash != native_script.hash() { + let mut err_req_wits = RequiredWitnessSet::new(); + err_req_wits.add_script_hash(*script_hash); + return Err(ProposalBuilderError::MissingWitnesses(Box::new( + err_req_wits, + ))); + } + self.result.required_wits.add_script_hash(*script_hash); + } else { + return Err(ProposalBuilderError::ProposalIsKeyHash); + } + + self.result.proposals.push(proposal); + + self.result + .aggregate_witnesses + .push(InputAggregateWitnessData::NativeScript( + native_script, + witness_info, + )); + + Ok(self) + } + + pub fn with_plutus_proposal( + self, + proposal: ProposalProcedure, + partial_witness: PartialPlutusWitness, + required_signers: RequiredSigners, + datum: PlutusData, + ) -> Result { + self.with_plutus_proposal_impl(proposal, partial_witness, required_signers, Some(datum)) + } + + pub fn with_plutus_proposal_inline_datum( + self, + proposal: ProposalProcedure, + partial_witness: PartialPlutusWitness, + required_signers: RequiredSigners, + ) -> Result { + self.with_plutus_proposal_impl(proposal, partial_witness, required_signers, None) + } + + fn with_plutus_proposal_impl( + mut self, + proposal: ProposalProcedure, + partial_witness: PartialPlutusWitness, + required_signers: RequiredSigners, + datum: Option, + ) -> Result { + let mut required_wits = required_wits_from_required_signers(&required_signers); + if let Some(script_hash) = proposal.gov_action.script_hash() { + required_wits.add_script_hash(*script_hash); + } else { + return Err(ProposalBuilderError::ProposalIsKeyHash); + } + + let mut required_wits_left = required_wits.clone(); + + // no way to know these at this time + required_wits_left.vkeys.clear(); + + let script_hash = partial_witness.script.hash(); + + // check the user provided all the required witnesses + required_wits_left.scripts.remove(&script_hash); + if let Some(datum) = &datum { + required_wits_left + .plutus_data + .remove(&hash_plutus_data(datum)); + } + + if required_wits_left.len() > 0 { + return Err(ProposalBuilderError::MissingWitnesses(Box::new( + required_wits_left, + ))); + } + + self.result.proposals.push(proposal); + + self.result.required_wits.add_all(required_wits); + + self.result + .aggregate_witnesses + .push(InputAggregateWitnessData::PlutusScript( + partial_witness, + required_signers, + datum, + )); + + Ok(self) + } + + pub fn build(self) -> ProposalBuilderResult { + self.result + } +} diff --git a/chain/rust/src/builders/redeemer_builder.rs b/chain/rust/src/builders/redeemer_builder.rs index d83e15ad..89e62138 100644 --- a/chain/rust/src/builders/redeemer_builder.rs +++ b/chain/rust/src/builders/redeemer_builder.rs @@ -1,6 +1,7 @@ use super::{ certificate_builder::CertificateBuilderResult, input_builder::InputBuilderResult, - mint_builder::MintBuilderResult, withdrawal_builder::WithdrawalBuilderResult, + mint_builder::MintBuilderResult, proposal_builder::ProposalBuilderResult, + vote_builder::VoteBuilderResult, withdrawal_builder::WithdrawalBuilderResult, }; use crate::{ address::RewardAddress, @@ -97,6 +98,10 @@ pub struct RedeemerSetBuilder { // certificates in the DCert list are indexed in the order in which they arranged in the (full, unfiltered) // list of certificates inside the transaction cert: Vec>, + + proposals: Vec>, + + votes: Vec>, } impl RedeemerSetBuilder { @@ -143,10 +148,18 @@ impl RedeemerSetBuilder { ))); } RedeemerTag::Proposing => { - todo!("https://github.com/dcSpark/cardano-multiplatform-lib/issues/323") + let entry = self.proposals.get_mut(key.index as usize).unwrap(); + *entry = Some(UntaggedRedeemerPlaceholder::Full(UntaggedRedeemer::new( + entry.as_ref().unwrap().data().clone(), + ex_units, + ))); } RedeemerTag::Voting => { - todo!("https://github.com/dcSpark/cardano-multiplatform-lib/issues/323") + let entry = self.votes.get_mut(key.index as usize).unwrap(); + *entry = Some(UntaggedRedeemerPlaceholder::Full(UntaggedRedeemer::new( + entry.as_ref().unwrap().data().clone(), + ex_units, + ))); } } } @@ -217,6 +230,28 @@ impl RedeemerSetBuilder { } } + pub fn add_proposal(&mut self, result: &ProposalBuilderResult) { + for aggregate_witness in &result.aggregate_witnesses { + if let Some(data) = aggregate_witness.redeemer_plutus_data() { + self.proposals + .push(Some(UntaggedRedeemerPlaceholder::JustData(data.clone()))); + } else { + self.proposals.push(None); + } + } + } + + pub fn add_vote(&mut self, result: &VoteBuilderResult) { + for aggregate_witness in &result.aggregate_witnesses { + if let Some(data) = aggregate_witness.redeemer_plutus_data() { + self.votes + .push(Some(UntaggedRedeemerPlaceholder::JustData(data.clone()))); + } else { + self.votes.push(None); + } + } + } + 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 @@ -244,6 +279,18 @@ impl RedeemerSetBuilder { &mut self.cert.iter().map(|entry| (&(), entry)), default_to_dummy_exunits, )?; + self.remove_placeholders_and_tag( + &mut redeemers, + RedeemerTag::Proposing, + &mut self.proposals.iter().map(|entry| (&(), entry)), + default_to_dummy_exunits, + )?; + self.remove_placeholders_and_tag( + &mut redeemers, + RedeemerTag::Voting, + &mut self.votes.iter().map(|entry| (&(), entry)), + default_to_dummy_exunits, + )?; Ok(Redeemers::new_arr_legacy_redeemer(redeemers)) } diff --git a/chain/rust/src/builders/tx_builder.rs b/chain/rust/src/builders/tx_builder.rs index d91b1981..a324846f 100644 --- a/chain/rust/src/builders/tx_builder.rs +++ b/chain/rust/src/builders/tx_builder.rs @@ -2,9 +2,11 @@ use super::certificate_builder::*; use super::input_builder::InputBuilderResult; use super::mint_builder::MintBuilderResult; use super::output_builder::{OutputBuilderError, SingleOutputBuilderResult}; +use super::proposal_builder::ProposalBuilderResult; use super::redeemer_builder::RedeemerBuilderError; use super::redeemer_builder::RedeemerSetBuilder; use super::redeemer_builder::RedeemerWitnessKey; +use super::vote_builder::VoteBuilderResult; use super::withdrawal_builder::WithdrawalBuilderResult; use super::witness_builder::merge_fake_witness; use super::witness_builder::PlutusScriptWitness; @@ -21,6 +23,7 @@ use crate::crypto::hash::{calc_script_data_hash, hash_auxiliary_data, ScriptData use crate::crypto::{BootstrapWitness, Vkeywitness}; use crate::deposit::{internal_get_deposit, internal_get_implicit_input}; use crate::fees::LinearFee; +use crate::governance::{ProposalProcedure, VotingProcedures}; use crate::min_ada::min_ada_required; use crate::plutus::{CostModels, ExUnits, Language}; use crate::plutus::{PlutusData, Redeemers}; @@ -385,6 +388,8 @@ pub struct TransactionBuilder { ttl: Option, // absolute slot number certs: Option>, withdrawals: Option, + proposals: Option>, + votes: Option, auxiliary_data: Option, validity_start_interval: Option, mint: Option, @@ -876,6 +881,60 @@ impl TransactionBuilder { .add_required_wits(result.required_wits); } + pub fn add_proposal(&mut self, mut result: ProposalBuilderResult) { + self.witness_builders + .redeemer_set_builder + .add_proposal(&result); + if self.proposals.is_none() { + self.proposals = Some(Vec::new()); + } + self.proposals + .as_mut() + .unwrap() + .append(&mut result.proposals); + for data in result.aggregate_witnesses { + self.witness_builders + .witness_set_builder + .add_input_aggregate_real_witness_data(&data); + self.witness_builders + .fake_required_witnesses + .add_input_aggregate_fake_witness_data(&data); + if let InputAggregateWitnessData::PlutusScript(_, required_signers, _) = data { + required_signers + .iter() + .for_each(|signer| self.add_required_signer(*signer)); + } + } + self.witness_builders + .witness_set_builder + .add_required_wits(result.required_wits); + } + + pub fn add_vote(&mut self, result: VoteBuilderResult) { + self.witness_builders.redeemer_set_builder.add_vote(&result); + if let Some(votes) = self.votes.as_mut() { + votes.extend(result.votes.take()); + } else { + self.votes = Some(result.votes); + } + for data in result.aggregate_witnesses { + self.witness_builders + .witness_set_builder + .add_input_aggregate_real_witness_data(&data); + self.witness_builders + .fake_required_witnesses + .add_input_aggregate_fake_witness_data(&data); + if let InputAggregateWitnessData::PlutusScript(_, required_signers, _) = data { + required_signers + .iter() + .for_each(|signer| self.add_required_signer(*signer)); + } + } + self.witness_builders + .witness_set_builder + .add_required_wits(result.required_wits); + } + pub fn get_withdrawals(&self) -> Option { self.withdrawals.clone() } @@ -977,6 +1036,8 @@ impl TransactionBuilder { ttl: None, certs: None, withdrawals: None, + proposals: None, + votes: None, auxiliary_data: None, validity_start_interval: None, mint: None, @@ -1124,6 +1185,7 @@ impl TransactionBuilder { pub fn get_deposit(&self) -> Result { internal_get_deposit( self.certs.as_deref(), + self.proposals.as_deref(), self.config.pool_deposit, self.config.key_deposit, ) @@ -1258,8 +1320,11 @@ impl TransactionBuilder { .collect::>() .into() }), - voting_procedures: None, - proposal_procedures: None, + voting_procedures: self.votes.clone(), + proposal_procedures: self + .proposals + .as_ref() + .map(|proposals| proposals.clone().into()), current_treasury_value: None, donation: None, encodings: None, diff --git a/chain/rust/src/builders/utils.rs b/chain/rust/src/builders/utils.rs new file mode 100644 index 00000000..f5be4b53 --- /dev/null +++ b/chain/rust/src/builders/utils.rs @@ -0,0 +1,14 @@ +use crate::RequiredSigners; + +use super::witness_builder::RequiredWitnessSet; + +pub(crate) fn required_wits_from_required_signers( + required_signers: &RequiredSigners, +) -> RequiredWitnessSet { + let mut required_wits = RequiredWitnessSet::default(); + required_signers + .as_ref() + .iter() + .for_each(|required_signer| required_wits.add_vkey_key_hash(*required_signer)); + required_wits +} diff --git a/chain/rust/src/builders/vote_builder.rs b/chain/rust/src/builders/vote_builder.rs new file mode 100644 index 00000000..4aef9c99 --- /dev/null +++ b/chain/rust/src/builders/vote_builder.rs @@ -0,0 +1,221 @@ +use crate::{ + crypto::hash::hash_plutus_data, + governance::{GovActionId, Voter, VotingProcedure, VotingProcedures}, + plutus::PlutusData, + transaction::NativeScript, + RequiredSigners, +}; + +use super::{ + utils::required_wits_from_required_signers, + witness_builder::{ + InputAggregateWitnessData, NativeScriptWitnessInfo, PartialPlutusWitness, + RequiredWitnessSet, + }, +}; + +#[derive(Debug, thiserror::Error)] +pub enum VoteBuilderError { + #[error("Voter is script. Call with_plutus_vote() instead.")] + VoterIsScript, + #[error("Voter is key hash. Call with_vote() instead.")] + VoterIsKeyHash, + #[error("Vote already exists")] + VoteAlreayExists, + #[error("Missing the following witnesses for the input: {0:?}")] + MissingWitnesses(Box), +} + +#[derive(Clone, Debug, Default)] +pub struct VoteBuilderResult { + pub votes: VotingProcedures, + pub required_wits: RequiredWitnessSet, + pub aggregate_witnesses: Vec, +} + +#[derive(Clone, Debug)] +pub struct VoteBuilder { + result: VoteBuilderResult, +} + +impl Default for VoteBuilder { + fn default() -> Self { + Self::new() + } +} + +impl VoteBuilder { + pub fn new() -> Self { + Self { + result: VoteBuilderResult::default(), + } + } + + /// Add a vote using a voter with a key hash + /// Will throw an error if the voter is script-hash based + pub fn with_vote( + mut self, + voter: Voter, + gov_action_id: GovActionId, + procedure: VotingProcedure, + ) -> Result { + if let Some(key_hash) = voter.key_hash() { + self.result.required_wits.add_vkey_key_hash(*key_hash); + } else { + return Err(VoteBuilderError::VoterIsScript); + } + if self + .result + .votes + .entry(voter) + .or_default() + .insert(gov_action_id, procedure) + .is_some() + { + return Err(VoteBuilderError::VoteAlreayExists); + } + Ok(self) + } + + pub fn with_native_script_vote( + mut self, + voter: Voter, + gov_action_id: GovActionId, + procedure: VotingProcedure, + native_script: NativeScript, + witness_info: NativeScriptWitnessInfo, + ) -> Result { + if let Some(script_hash) = voter.script_hash() { + if *script_hash != native_script.hash() { + let mut err_req_wits = RequiredWitnessSet::new(); + err_req_wits.add_script_hash(*script_hash); + return Err(VoteBuilderError::MissingWitnesses(Box::new(err_req_wits))); + } + self.result.required_wits.add_script_hash(*script_hash); + } else { + return Err(VoteBuilderError::VoterIsKeyHash); + } + + if self + .result + .votes + .entry(voter) + .or_default() + .insert(gov_action_id, procedure) + .is_some() + { + return Err(VoteBuilderError::VoteAlreayExists); + } + + self.result + .aggregate_witnesses + .push(InputAggregateWitnessData::NativeScript( + native_script, + witness_info, + )); + + Ok(self) + } + + pub fn with_plutus_vote( + self, + voter: Voter, + gov_action_id: GovActionId, + procedure: VotingProcedure, + partial_witness: PartialPlutusWitness, + required_signers: RequiredSigners, + datum: PlutusData, + ) -> Result { + self.with_plutus_vote_impl( + voter, + gov_action_id, + procedure, + partial_witness, + required_signers, + Some(datum), + ) + } + + pub fn with_plutus_vote_inline_datum( + self, + voter: Voter, + gov_action_id: GovActionId, + procedure: VotingProcedure, + partial_witness: PartialPlutusWitness, + required_signers: RequiredSigners, + ) -> Result { + self.with_plutus_vote_impl( + voter, + gov_action_id, + procedure, + partial_witness, + required_signers, + None, + ) + } + + fn with_plutus_vote_impl( + mut self, + voter: Voter, + gov_action_id: GovActionId, + procedure: VotingProcedure, + partial_witness: PartialPlutusWitness, + required_signers: RequiredSigners, + datum: Option, + ) -> Result { + let mut required_wits = required_wits_from_required_signers(&required_signers); + if let Some(script_hash) = voter.script_hash() { + required_wits.add_script_hash(*script_hash); + } else { + return Err(VoteBuilderError::VoterIsKeyHash); + } + + let mut required_wits_left = required_wits.clone(); + + // no way to know these at this time + required_wits_left.vkeys.clear(); + + let script_hash = partial_witness.script.hash(); + + // check the user provided all the required witnesses + required_wits_left.scripts.remove(&script_hash); + if let Some(datum) = &datum { + required_wits_left + .plutus_data + .remove(&hash_plutus_data(datum)); + } + + if required_wits_left.len() > 0 { + return Err(VoteBuilderError::MissingWitnesses(Box::new( + required_wits_left, + ))); + } + + if self + .result + .votes + .entry(voter) + .or_default() + .insert(gov_action_id, procedure) + .is_some() + { + return Err(VoteBuilderError::VoteAlreayExists); + } + + self.result.required_wits.add_all(required_wits); + + self.result + .aggregate_witnesses + .push(InputAggregateWitnessData::PlutusScript( + partial_witness, + required_signers, + datum, + )); + + Ok(self) + } + + pub fn build(self) -> VoteBuilderResult { + self.result + } +} diff --git a/chain/rust/src/deposit.rs b/chain/rust/src/deposit.rs index 3e40b394..211fc6dd 100644 --- a/chain/rust/src/deposit.rs +++ b/chain/rust/src/deposit.rs @@ -1,6 +1,9 @@ use cml_core::ArithmeticError; -use crate::{certs::Certificate, transaction::TransactionBody, Coin, Value, Withdrawals}; +use crate::{ + certs::Certificate, governance::ProposalProcedure, transaction::TransactionBody, Coin, Value, + Withdrawals, +}; pub fn internal_get_implicit_input( withdrawals: Option<&Withdrawals>, @@ -22,7 +25,10 @@ pub fn internal_get_implicit_input( .try_fold(0u64, |acc, cert| match cert { Certificate::PoolRetirement(_cert) => acc.checked_add(pool_deposit), Certificate::StakeDeregistration(_cert) => acc.checked_add(key_deposit), - Certificate::UnregCert(_cert) => acc.checked_add(key_deposit), + Certificate::UnregCert(cert) => acc.checked_add(cert.coin), + Certificate::UnregDrepCert(cert) => acc.checked_add(cert.coin), + // TODO: is this the case? + Certificate::ResignCommitteeColdCert(_cert) => acc.checked_add(key_deposit), _ => Some(acc), }) .ok_or(ArithmeticError::IntegerOverflow)?, @@ -36,6 +42,7 @@ pub fn internal_get_implicit_input( pub fn internal_get_deposit( certs: Option<&[Certificate]>, + proposals: Option<&[ProposalProcedure]>, pool_deposit: Coin, // // protocol parameter key_deposit: Coin, // protocol parameter ) -> Result { @@ -46,13 +53,25 @@ pub fn internal_get_deposit( .try_fold(0u64, |acc, cert| match cert { Certificate::PoolRegistration(_cert) => acc.checked_add(pool_deposit), Certificate::StakeRegistration(_cert) => acc.checked_add(key_deposit), - Certificate::RegCert(_cert) => acc.checked_add(key_deposit), - Certificate::StakeRegDelegCert(_cert) => acc.checked_add(key_deposit), + Certificate::RegCert(cert) => acc.checked_add(cert.coin), + Certificate::StakeRegDelegCert(cert) => acc.checked_add(cert.coin), + Certificate::RegDrepCert(cert) => acc.checked_add(cert.coin), + Certificate::VoteRegDelegCert(cert) => acc.checked_add(cert.coin), + Certificate::StakeVoteRegDelegCert(cert) => acc.checked_add(cert.coin), _ => Some(acc), }) .ok_or(ArithmeticError::IntegerOverflow)?, }; - Ok(certificate_refund) + let proposal_refund = match proposals { + None => 0, + Some(proposals) => proposals + .iter() + .try_fold(0u64, |acc, proposal| acc.checked_add(proposal.deposit)) + .ok_or(ArithmeticError::IntegerOverflow)?, + }; + certificate_refund + .checked_add(proposal_refund) + .ok_or(ArithmeticError::IntegerOverflow) } pub fn get_implicit_input( @@ -75,6 +94,10 @@ pub fn get_deposit( ) -> Result { internal_get_deposit( txbody.certs.as_ref().map(|certs| certs.as_ref()), + txbody + .proposal_procedures + .as_ref() + .map(|proposals| proposals.as_ref()), pool_deposit, key_deposit, ) diff --git a/chain/rust/src/governance/mod.rs b/chain/rust/src/governance/mod.rs index 6a997590..d0b24400 100644 --- a/chain/rust/src/governance/mod.rs +++ b/chain/rust/src/governance/mod.rs @@ -3,6 +3,7 @@ pub mod cbor_encodings; pub mod serialization; +pub mod utils; use crate::address::RewardAccount; use crate::assets::Coin; diff --git a/chain/rust/src/governance/utils.rs b/chain/rust/src/governance/utils.rs new file mode 100644 index 00000000..12391008 --- /dev/null +++ b/chain/rust/src/governance/utils.rs @@ -0,0 +1,48 @@ +use cml_crypto::{Ed25519KeyHash, ScriptHash}; + +use super::{GovAction, Voter}; + +impl GovAction { + pub fn script_hash(&self) -> Option<&ScriptHash> { + match self { + Self::ParameterChangeAction(action) => action.policy_hash.as_ref(), + Self::HardForkInitiationAction(_action) => None, + Self::TreasuryWithdrawalsAction(action) => action.policy_hash.as_ref(), + Self::NoConfidence(_action) => None, + // TODO: unsure if these count? they can be credentials but maybe it's not needed to sign + Self::UpdateCommittee(_action) => None, + // TODO: unsure if this counts? + //Self::NewConstitution(action) => action.constitution.script_hash, + Self::NewConstitution(_action) => None, + Self::InfoAction { .. } => None, + } + } +} + +impl Voter { + pub fn key_hash(&self) -> Option<&Ed25519KeyHash> { + match self { + Self::ConstitutionalCommitteeHotKeyHash { + ed25519_key_hash, .. + } => Some(ed25519_key_hash), + Self::ConstitutionalCommitteeHotScriptHash { .. } => None, + Self::DRepKeyHash { + ed25519_key_hash, .. + } => Some(ed25519_key_hash), + Self::DRepScriptHash { .. } => None, + Self::StakingPoolKeyHash { + ed25519_key_hash, .. + } => Some(ed25519_key_hash), + } + } + + pub fn script_hash(&self) -> Option<&ScriptHash> { + match self { + Self::ConstitutionalCommitteeHotKeyHash { .. } => None, + Self::ConstitutionalCommitteeHotScriptHash { script_hash, .. } => Some(script_hash), + Self::DRepKeyHash { .. } => None, + Self::DRepScriptHash { script_hash, .. } => Some(script_hash), + Self::StakingPoolKeyHash { .. } => None, + } + } +} diff --git a/chain/wasm/src/builders/mod.rs b/chain/wasm/src/builders/mod.rs index 30911f48..960df211 100644 --- a/chain/wasm/src/builders/mod.rs +++ b/chain/wasm/src/builders/mod.rs @@ -2,7 +2,9 @@ pub mod certificate_builder; pub mod input_builder; pub mod mint_builder; pub mod output_builder; +pub mod proposal_builder; pub mod redeemer_builder; pub mod tx_builder; +pub mod vote_builder; pub mod withdrawal_builder; pub mod witness_builder; diff --git a/chain/wasm/src/builders/proposal_builder.rs b/chain/wasm/src/builders/proposal_builder.rs new file mode 100644 index 00000000..abf6d23d --- /dev/null +++ b/chain/wasm/src/builders/proposal_builder.rs @@ -0,0 +1,99 @@ +use wasm_bindgen::{prelude::wasm_bindgen, JsError}; + +use cml_core_wasm::impl_wasm_conversions; + +use crate::{ + governance::ProposalProcedure, plutus::PlutusData, transaction::NativeScript, RequiredSigners, +}; + +use super::witness_builder::{NativeScriptWitnessInfo, PartialPlutusWitness}; + +#[wasm_bindgen] +#[derive(Clone, Debug)] +pub struct ProposalBuilderResult(cml_chain::builders::proposal_builder::ProposalBuilderResult); + +impl_wasm_conversions!( + cml_chain::builders::proposal_builder::ProposalBuilderResult, + ProposalBuilderResult +); + +#[wasm_bindgen] +#[derive(Clone, Debug)] +pub struct ProposalBuilder(cml_chain::builders::proposal_builder::ProposalBuilder); + +impl_wasm_conversions!( + cml_chain::builders::proposal_builder::ProposalBuilder, + ProposalBuilder +); + +#[wasm_bindgen] +impl ProposalBuilder { + pub fn new() -> Self { + Self(cml_chain::builders::proposal_builder::ProposalBuilder::new()) + } + + pub fn with_proposal(&self, proposal: ProposalProcedure) -> Result { + self.0 + .clone() + .with_proposal(proposal.clone().into()) + .map(Into::into) + .map_err(Into::into) + } + + pub fn with_native_script_proposal( + &self, + proposal: ProposalProcedure, + native_script: NativeScript, + witness_info: NativeScriptWitnessInfo, + ) -> Result { + self.0 + .clone() + .with_native_script_proposal( + proposal.clone().into(), + native_script.clone().into(), + witness_info.clone().into(), + ) + .map(Into::into) + .map_err(Into::into) + } + + pub fn with_plutus_proposal( + &self, + proposal: &ProposalProcedure, + partial_witness: &PartialPlutusWitness, + required_signers: &RequiredSigners, + datum: &PlutusData, + ) -> Result { + self.0 + .clone() + .with_plutus_proposal( + proposal.clone().into(), + partial_witness.clone().into(), + required_signers.clone().into(), + datum.clone().into(), + ) + .map(Into::into) + .map_err(Into::into) + } + + pub fn with_plutus_proposal_inline_datum( + &self, + proposal: ProposalProcedure, + partial_witness: PartialPlutusWitness, + required_signers: RequiredSigners, + ) -> Result { + self.0 + .clone() + .with_plutus_proposal_inline_datum( + proposal.clone().into(), + partial_witness.clone().into(), + required_signers.clone().into(), + ) + .map(Into::into) + .map_err(Into::into) + } + + pub fn build(&self) -> ProposalBuilderResult { + self.0.clone().build().into() + } +} diff --git a/chain/wasm/src/builders/redeemer_builder.rs b/chain/wasm/src/builders/redeemer_builder.rs index 7c6be9b1..26e673a4 100644 --- a/chain/wasm/src/builders/redeemer_builder.rs +++ b/chain/wasm/src/builders/redeemer_builder.rs @@ -1,6 +1,7 @@ use super::{ certificate_builder::CertificateBuilderResult, input_builder::InputBuilderResult, - mint_builder::MintBuilderResult, withdrawal_builder::WithdrawalBuilderResult, + mint_builder::MintBuilderResult, proposal_builder::ProposalBuilderResult, + vote_builder::VoteBuilderResult, withdrawal_builder::WithdrawalBuilderResult, }; use crate::plutus::{ExUnits, LegacyRedeemer, PlutusData, RedeemerTag, Redeemers}; use cml_core_wasm::impl_wasm_conversions; @@ -92,6 +93,14 @@ impl RedeemerSetBuilder { self.0.add_cert(result.as_ref()); } + pub fn add_proposal(&mut self, result: &ProposalBuilderResult) { + self.0.add_proposal(result.as_ref()); + } + + pub fn add_vote(&mut self, result: &VoteBuilderResult) { + self.0.add_vote(result.as_ref()); + } + pub fn build(&self, default_to_dummy_exunits: bool) -> Result { self.0 .build(default_to_dummy_exunits) diff --git a/chain/wasm/src/builders/tx_builder.rs b/chain/wasm/src/builders/tx_builder.rs index 1d0e73f4..b6091e33 100644 --- a/chain/wasm/src/builders/tx_builder.rs +++ b/chain/wasm/src/builders/tx_builder.rs @@ -10,7 +10,8 @@ use crate::{ builders::{ certificate_builder::CertificateBuilderResult, input_builder::InputBuilderResult, mint_builder::MintBuilderResult, output_builder::SingleOutputBuilderResult, - redeemer_builder::RedeemerWitnessKey, withdrawal_builder::WithdrawalBuilderResult, + proposal_builder::ProposalBuilderResult, redeemer_builder::RedeemerWitnessKey, + vote_builder::VoteBuilderResult, withdrawal_builder::WithdrawalBuilderResult, witness_builder::TransactionWitnessSetBuilder, }, crypto::{BootstrapWitness, Vkeywitness}, @@ -211,6 +212,14 @@ impl TransactionBuilder { self.0.add_cert(result.clone().into()) } + pub fn add_proposal(&mut self, result: ProposalBuilderResult) { + self.0.add_proposal(result.clone().into()) + } + + pub fn add_vote(&mut self, result: VoteBuilderResult) { + self.0.add_vote(result.clone().into()) + } + pub fn get_withdrawals(&self) -> Option { self.0.get_withdrawals().map(|wd| wd.into()) } diff --git a/chain/wasm/src/builders/vote_builder.rs b/chain/wasm/src/builders/vote_builder.rs new file mode 100644 index 00000000..88774f97 --- /dev/null +++ b/chain/wasm/src/builders/vote_builder.rs @@ -0,0 +1,120 @@ +use wasm_bindgen::{prelude::wasm_bindgen, JsError}; + +use cml_core_wasm::impl_wasm_conversions; + +use crate::{ + governance::{GovActionId, Voter, VotingProcedure}, + plutus::PlutusData, + transaction::NativeScript, + RequiredSigners, +}; + +use super::witness_builder::{NativeScriptWitnessInfo, PartialPlutusWitness}; + +#[wasm_bindgen] +#[derive(Clone, Debug)] +pub struct VoteBuilderResult(cml_chain::builders::vote_builder::VoteBuilderResult); + +impl_wasm_conversions!( + cml_chain::builders::vote_builder::VoteBuilderResult, + VoteBuilderResult +); + +#[wasm_bindgen] +#[derive(Clone, Debug)] +pub struct VoteBuilder(cml_chain::builders::vote_builder::VoteBuilder); + +impl_wasm_conversions!(cml_chain::builders::vote_builder::VoteBuilder, VoteBuilder); + +#[wasm_bindgen] +impl VoteBuilder { + pub fn new() -> Self { + Self(cml_chain::builders::vote_builder::VoteBuilder::new()) + } + + pub fn with_vote( + &self, + voter: &Voter, + gov_action_id: &GovActionId, + procedure: &VotingProcedure, + ) -> Result { + self.0 + .clone() + .with_vote( + voter.clone().into(), + gov_action_id.clone().into(), + procedure.clone().into(), + ) + .map(Into::into) + .map_err(Into::into) + } + + pub fn with_native_script_vote( + &self, + voter: &Voter, + gov_action_id: &GovActionId, + procedure: &VotingProcedure, + native_script: NativeScript, + witness_info: NativeScriptWitnessInfo, + ) -> Result { + self.0 + .clone() + .with_native_script_vote( + voter.clone().into(), + gov_action_id.clone().into(), + procedure.clone().into(), + native_script.clone().into(), + witness_info.clone().into(), + ) + .map(Into::into) + .map_err(Into::into) + } + + pub fn with_plutus_vote( + &self, + voter: &Voter, + gov_action_id: &GovActionId, + procedure: &VotingProcedure, + partial_witness: &PartialPlutusWitness, + required_signers: &RequiredSigners, + datum: &PlutusData, + ) -> Result { + self.0 + .clone() + .with_plutus_vote( + voter.clone().into(), + gov_action_id.clone().into(), + procedure.clone().into(), + partial_witness.clone().into(), + required_signers.clone().into(), + datum.clone().into(), + ) + .map(Into::into) + .map_err(Into::into) + } + + pub fn with_plutus_vote_inline_datum( + &self, + voter: &Voter, + gov_action_id: &GovActionId, + procedure: &VotingProcedure, + partial_witness: PartialPlutusWitness, + required_signers: RequiredSigners, + ) -> Result { + self.0 + .clone() + .with_plutus_vote_inline_datum( + voter.clone().into(), + gov_action_id.clone().into(), + procedure.clone().into(), + partial_witness.clone().into(), + required_signers.clone().into(), + ) + .map(Into::into) + .map_err(Into::into) + } + + pub fn build(&self) -> VoteBuilderResult { + self.0.clone().build().into() + } +} diff --git a/chain/wasm/src/governance/mod.rs b/chain/wasm/src/governance/mod.rs index a21870d8..99595b4e 100644 --- a/chain/wasm/src/governance/mod.rs +++ b/chain/wasm/src/governance/mod.rs @@ -15,6 +15,8 @@ use cml_core::ordered_hash_map::OrderedHashMap; use cml_core_wasm::{impl_wasm_cbor_json_api, impl_wasm_conversions}; use wasm_bindgen::prelude::{wasm_bindgen, JsError, JsValue}; +pub mod utils; + #[derive(Clone, Debug)] #[wasm_bindgen] pub struct Anchor(cml_chain::governance::Anchor); diff --git a/chain/wasm/src/governance/utils.rs b/chain/wasm/src/governance/utils.rs new file mode 100644 index 00000000..ec905d7e --- /dev/null +++ b/chain/wasm/src/governance/utils.rs @@ -0,0 +1,23 @@ +use wasm_bindgen::prelude::wasm_bindgen; + +use cml_crypto_wasm::{Ed25519KeyHash, ScriptHash}; + +use super::{GovAction, Voter}; + +#[wasm_bindgen] +impl GovAction { + pub fn script_hash(&self) -> Option { + self.0.script_hash().map(|hash| (*hash).into()) + } +} + +#[wasm_bindgen] +impl Voter { + pub fn key_hash(&self) -> Option { + self.0.key_hash().map(|hash| (*hash).into()) + } + + pub fn script_hash(&self) -> Option { + self.0.script_hash().map(|hash| (*hash).into()) + } +} From cf10721ac05c9dc9a26a5ca5f005bfc01d09eafa Mon Sep 17 00:00:00 2001 From: rooooooooob Date: Tue, 16 Jul 2024 15:01:38 -0700 Subject: [PATCH 14/16] Fix for coin/deposit merge issue (#344) Somehow `coin` ended up here still after #333 despite being changed to `deposit`. --- chain/rust/src/deposit.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/chain/rust/src/deposit.rs b/chain/rust/src/deposit.rs index 211fc6dd..a498e203 100644 --- a/chain/rust/src/deposit.rs +++ b/chain/rust/src/deposit.rs @@ -25,8 +25,8 @@ pub fn internal_get_implicit_input( .try_fold(0u64, |acc, cert| match cert { Certificate::PoolRetirement(_cert) => acc.checked_add(pool_deposit), Certificate::StakeDeregistration(_cert) => acc.checked_add(key_deposit), - Certificate::UnregCert(cert) => acc.checked_add(cert.coin), - Certificate::UnregDrepCert(cert) => acc.checked_add(cert.coin), + Certificate::UnregCert(cert) => acc.checked_add(cert.deposit), + Certificate::UnregDrepCert(cert) => acc.checked_add(cert.deposit), // TODO: is this the case? Certificate::ResignCommitteeColdCert(_cert) => acc.checked_add(key_deposit), _ => Some(acc), @@ -53,11 +53,11 @@ pub fn internal_get_deposit( .try_fold(0u64, |acc, cert| match cert { Certificate::PoolRegistration(_cert) => acc.checked_add(pool_deposit), Certificate::StakeRegistration(_cert) => acc.checked_add(key_deposit), - Certificate::RegCert(cert) => acc.checked_add(cert.coin), - Certificate::StakeRegDelegCert(cert) => acc.checked_add(cert.coin), - Certificate::RegDrepCert(cert) => acc.checked_add(cert.coin), - Certificate::VoteRegDelegCert(cert) => acc.checked_add(cert.coin), - Certificate::StakeVoteRegDelegCert(cert) => acc.checked_add(cert.coin), + Certificate::RegCert(cert) => acc.checked_add(cert.deposit), + Certificate::StakeRegDelegCert(cert) => acc.checked_add(cert.deposit), + Certificate::RegDrepCert(cert) => acc.checked_add(cert.deposit), + Certificate::VoteRegDelegCert(cert) => acc.checked_add(cert.deposit), + Certificate::StakeVoteRegDelegCert(cert) => acc.checked_add(cert.deposit), _ => Some(acc), }) .ok_or(ArithmeticError::IntegerOverflow)?, From 6a28e88bfebcc8160ce7f888951e9a302eb643ee Mon Sep 17 00:00:00 2001 From: rooooooooob Date: Tue, 16 Jul 2024 15:14:39 -0700 Subject: [PATCH 15/16] Remove wasm-bindgen deps from rust (#343) Rust CML crates must use wasm-bindgen for enums as these are used from the WASM CML crates. Using noop_proc_macro we can replace the wasm_bindgen proc macro with a no-op that does nothing when consumed directly from rust. This is now locked behind a feature (used_from_wasm) as we can't just use cfg target checks as compiling the wasm crate (not using web-pack) would use the rust target and break. Crates using cml-chain and cml-multi-era from a wasm crate must specify this feature to activate the wasm_bindgen dependancy instead of the no-op macro. --- chain/rust/Cargo.toml | 21 +++++---------------- chain/rust/src/address.rs | 4 +++- chain/rust/src/builders/tx_builder.rs | 4 +++- chain/rust/src/byron/mod.rs | 8 +++++--- chain/rust/src/governance/mod.rs | 7 ++++++- chain/rust/src/json/metadatums.rs | 3 +++ chain/rust/src/json/plutus_datums.rs | 3 +++ chain/rust/src/plutus/mod.rs | 9 +++++++-- chain/wasm/Cargo.toml | 2 +- cip25/wasm/Cargo.toml | 2 +- core/rust/Cargo.toml | 20 -------------------- multi-era/rust/Cargo.toml | 10 +++++++++- multi-era/rust/src/allegra/mod.rs | 7 ++++++- multi-era/rust/src/alonzo/mod.rs | 7 ++++++- multi-era/wasm/Cargo.toml | 4 ++-- 15 files changed, 60 insertions(+), 51 deletions(-) diff --git a/chain/rust/Cargo.toml b/chain/rust/Cargo.toml index 981a7d9a..5bdb22ad 100644 --- a/chain/rust/Cargo.toml +++ b/chain/rust/Cargo.toml @@ -13,6 +13,9 @@ keywords = ["cardano"] [lib] crate-type = ["cdylib", "rlib"] +[features] +used_from_wasm = ["wasm-bindgen"] + [dependencies] cml-core = { "path" = "../../core/rust", version = "5.3.1" } cml-crypto = { "path" = "../../crypto/rust", version = "5.3.1" } @@ -32,29 +35,15 @@ fraction = "0.10.0" base64 = "0.21.5" num-bigint = "0.4.0" num-integer = "0.1.45" -#rand_os = "0.1" thiserror = "1.0.37" num = "0.4" unicode-segmentation = "1.10.1" -# These can be removed if we make wasm bindings for ALL functionality here. -# This was not done right now as there is a lot of existing legacy code e.g. -# for Byron that might need to be used from WASM and might not. -# We can remove this dependency when that is decided. -# -# The other use-case here is enums. Without this two enums would need to be defined -# despite wasm_bindgen supporting C-style enums (with non-negative values) 100% -# This could possibly be resolved with macros but maybe not. # non-wasm -#[target.'cfg(not(all(target_arch = "wasm32", not(target_os = "emscripten"))))'.dependencies] -#rand_os = "0.1" -#noop_proc_macro = "0.3.0" +noop_proc_macro = { version = "0.3.0", optional = false } # wasm -#[target.'cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))'.dependencies] -wasm-bindgen = { version = "0.2.87" } -#rand_os = { version = "0.1", features = ["wasm-bindgen"] } -#js-sys = "=0.3.59" +wasm-bindgen = { version = "0.2.87", optional = true } [dev-dependencies] diff --git a/chain/rust/src/address.rs b/chain/rust/src/address.rs index cf26c16b..8f9a6253 100644 --- a/chain/rust/src/address.rs +++ b/chain/rust/src/address.rs @@ -7,7 +7,9 @@ use schemars::JsonSchema; use std::convert::{TryFrom, TryInto}; use std::io::{BufRead, Write}; -// for enums +#[cfg(not(feature = "used_from_wasm"))] +use noop_proc_macro::wasm_bindgen; +#[cfg(feature = "used_from_wasm")] use wasm_bindgen::prelude::wasm_bindgen; use cml_crypto::{Ed25519KeyHash, ScriptHash}; diff --git a/chain/rust/src/builders/tx_builder.rs b/chain/rust/src/builders/tx_builder.rs index a324846f..b6223a32 100644 --- a/chain/rust/src/builders/tx_builder.rs +++ b/chain/rust/src/builders/tx_builder.rs @@ -44,7 +44,9 @@ use std::convert::TryInto; use std::io::{BufRead, Seek, Write}; use std::ops::DerefMut; -// for enums: +#[cfg(not(feature = "used_from_wasm"))] +use noop_proc_macro::wasm_bindgen; +#[cfg(feature = "used_from_wasm")] use wasm_bindgen::prelude::wasm_bindgen; /** diff --git a/chain/rust/src/byron/mod.rs b/chain/rust/src/byron/mod.rs index 4701c158..1c455eea 100644 --- a/chain/rust/src/byron/mod.rs +++ b/chain/rust/src/byron/mod.rs @@ -1,5 +1,7 @@ -//#[cfg(not(all(target_arch = "wasm32", not(target_os = "emscripten"))))] -//use noop_proc_macro::wasm_bindgen; +#[cfg(not(feature = "used_from_wasm"))] +use noop_proc_macro::wasm_bindgen; +#[cfg(feature = "used_from_wasm")] +use wasm_bindgen::prelude::wasm_bindgen; use std::io::{BufRead, Write}; @@ -76,7 +78,7 @@ impl Default for AddrAttributes { serde::Serialize, schemars::JsonSchema, )] -#[wasm_bindgen::prelude::wasm_bindgen] +#[wasm_bindgen] pub enum ByronAddrType { PublicKey = 0, Script = 1, diff --git a/chain/rust/src/governance/mod.rs b/chain/rust/src/governance/mod.rs index d0b24400..e0e6b2af 100644 --- a/chain/rust/src/governance/mod.rs +++ b/chain/rust/src/governance/mod.rs @@ -5,6 +5,11 @@ pub mod cbor_encodings; pub mod serialization; pub mod utils; +#[cfg(not(feature = "used_from_wasm"))] +use noop_proc_macro::wasm_bindgen; +#[cfg(feature = "used_from_wasm")] +use wasm_bindgen::prelude::wasm_bindgen; + use crate::address::RewardAccount; use crate::assets::Coin; use crate::block::ProtocolVersion; @@ -321,7 +326,7 @@ impl UpdateCommittee { serde::Serialize, schemars::JsonSchema, )] -#[wasm_bindgen::prelude::wasm_bindgen] +#[wasm_bindgen] pub enum Vote { No, Yes, diff --git a/chain/rust/src/json/metadatums.rs b/chain/rust/src/json/metadatums.rs index 06cadcf6..6f5b1980 100644 --- a/chain/rust/src/json/metadatums.rs +++ b/chain/rust/src/json/metadatums.rs @@ -1,3 +1,6 @@ +#[cfg(not(feature = "used_from_wasm"))] +use noop_proc_macro::wasm_bindgen; +#[cfg(feature = "used_from_wasm")] use wasm_bindgen::prelude::wasm_bindgen; use crate::{ diff --git a/chain/rust/src/json/plutus_datums.rs b/chain/rust/src/json/plutus_datums.rs index eb222229..af2f8ba9 100644 --- a/chain/rust/src/json/plutus_datums.rs +++ b/chain/rust/src/json/plutus_datums.rs @@ -6,6 +6,9 @@ use crate::{ use std::collections::BTreeMap; use std::str::FromStr; +#[cfg(not(feature = "used_from_wasm"))] +use noop_proc_macro::wasm_bindgen; +#[cfg(feature = "used_from_wasm")] use wasm_bindgen::prelude::wasm_bindgen; /// JSON <-> PlutusData conversion schemas. diff --git a/chain/rust/src/plutus/mod.rs b/chain/rust/src/plutus/mod.rs index b815ed90..ae4850f2 100644 --- a/chain/rust/src/plutus/mod.rs +++ b/chain/rust/src/plutus/mod.rs @@ -5,6 +5,11 @@ pub mod cbor_encodings; pub mod serialization; pub mod utils; +#[cfg(not(feature = "used_from_wasm"))] +use noop_proc_macro::wasm_bindgen; +#[cfg(feature = "used_from_wasm")] +use wasm_bindgen::prelude::wasm_bindgen; + use self::cbor_encodings::{ LegacyRedeemerEncoding, PlutusV3ScriptEncoding, RedeemerKeyEncoding, RedeemerValEncoding, }; @@ -135,7 +140,7 @@ impl ExUnits { serde::Serialize, schemars::JsonSchema, )] -#[wasm_bindgen::prelude::wasm_bindgen] +#[wasm_bindgen] pub enum Language { PlutusV1, PlutusV2, @@ -477,7 +482,7 @@ impl RedeemerKey { serde::Serialize, schemars::JsonSchema, )] -#[wasm_bindgen::prelude::wasm_bindgen] +#[wasm_bindgen] pub enum RedeemerTag { Spend, Mint, diff --git a/chain/wasm/Cargo.toml b/chain/wasm/Cargo.toml index beff9882..3dce0a78 100644 --- a/chain/wasm/Cargo.toml +++ b/chain/wasm/Cargo.toml @@ -14,7 +14,7 @@ keywords = ["cardano"] crate-type = ["cdylib", "rlib"] [dependencies] -cml-chain = { path = "../rust", version = "5.3.1" } +cml-chain = { path = "../rust", version = "5.3.1", features = ["used_from_wasm"] } cml-core = { path = "../../core/rust", version = "5.3.1" } cml-core-wasm = { path = "../../core/wasm", version = "5.3.1" } # TODO: remove this dependency if possible to reduce confusion? maybe pub export necessary things in crypto-wasm? diff --git a/cip25/wasm/Cargo.toml b/cip25/wasm/Cargo.toml index cc62917b..31b0a22f 100644 --- a/cip25/wasm/Cargo.toml +++ b/cip25/wasm/Cargo.toml @@ -15,7 +15,7 @@ crate-type = ["cdylib", "rlib"] [dependencies] cbor_event = "2.2.0" -cml-chain = { path = "../../chain/rust", version = "5.3.1" } +cml-chain = { path = "../../chain/rust", version = "5.3.1", features = ["used_from_wasm"] } cml-chain-wasm = { path = "../../chain/wasm", version = "5.3.1" } cml-core = { path = "../../core/rust", version = "5.3.1" } cml-core-wasm = { path = "../../core/wasm", version = "5.3.1" } diff --git a/core/rust/Cargo.toml b/core/rust/Cargo.toml index 712b2e1e..6b30f23a 100644 --- a/core/rust/Cargo.toml +++ b/core/rust/Cargo.toml @@ -34,26 +34,6 @@ num-integer = "0.1.45" thiserror = "1.0.37" cfg-if = "1" -# These can be removed if we make wasm bindings for ALL functionality here. -# This was not done right now as there is a lot of existing legacy code e.g. -# for Byron that might need to be used from WASM and might not. -# We can remove this dependency when that is decided. -# -# The other use-case here is enums. Without this two enums would need to be defined -# despite wasm_bindgen supporting C-style enums (with non-negative values) 100% -# This could possibly be resolved with macros but maybe not. - -# non-wasm -[target.'cfg(not(all(target_arch = "wasm32", not(target_os = "emscripten"))))'.dependencies] -#rand_os = "0.1" -noop_proc_macro = "0.3.0" - -# wasm -[target.'cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))'.dependencies] -wasm-bindgen = { version = "0.2.87" } -#rand_os = { version = "0.1", features = ["wasm-bindgen"] } -#js-sys = "=0.3.59" - [dev-dependencies] quickcheck = "0.9.2" diff --git a/multi-era/rust/Cargo.toml b/multi-era/rust/Cargo.toml index 3457cc9b..37d29a25 100644 --- a/multi-era/rust/Cargo.toml +++ b/multi-era/rust/Cargo.toml @@ -13,6 +13,9 @@ keywords = ["cardano"] [lib] crate-type = ["cdylib", "rlib"] +[features] +used_from_wasm = ["wasm-bindgen"] + [dependencies] cml-core = { path = "../../core/rust", version = "5.3.1" } cml-crypto = { path = "../../crypto/rust", version = "5.3.1" } @@ -23,8 +26,13 @@ derivative = "2.2.0" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.57" schemars = "0.8.8" -wasm-bindgen = { version = "0.2.87" } # only for declaring hash types bech32 = "0.7.2" hex = "0.4.0" + +# non-wasm +noop_proc_macro = { version = "0.3.0" } + +# wasm +wasm-bindgen = { version = "0.2.87", optional = true } \ No newline at end of file diff --git a/multi-era/rust/src/allegra/mod.rs b/multi-era/rust/src/allegra/mod.rs index 93a4fe0d..38de508b 100644 --- a/multi-era/rust/src/allegra/mod.rs +++ b/multi-era/rust/src/allegra/mod.rs @@ -5,6 +5,11 @@ pub mod cbor_encodings; pub mod serialization; pub mod utils; +#[cfg(not(feature = "used_from_wasm"))] +use noop_proc_macro::wasm_bindgen; +#[cfg(feature = "used_from_wasm")] +use wasm_bindgen::prelude::wasm_bindgen; + use crate::shelley::{ GenesisKeyDelegation, ShelleyHeader, ShelleyPoolParams, ShelleyPoolRegistration, ShelleyTransactionOutput, ShelleyUpdate, @@ -259,7 +264,7 @@ impl MIRAction { serde::Serialize, schemars::JsonSchema, )] -#[wasm_bindgen::prelude::wasm_bindgen] +#[wasm_bindgen] pub enum MIRPot { Reserve, Treasury, diff --git a/multi-era/rust/src/alonzo/mod.rs b/multi-era/rust/src/alonzo/mod.rs index ea51bb90..7ba47fb4 100644 --- a/multi-era/rust/src/alonzo/mod.rs +++ b/multi-era/rust/src/alonzo/mod.rs @@ -5,6 +5,11 @@ pub mod cbor_encodings; pub mod serialization; pub mod utils; +#[cfg(not(feature = "used_from_wasm"))] +use noop_proc_macro::wasm_bindgen; +#[cfg(feature = "used_from_wasm")] +use wasm_bindgen::prelude::wasm_bindgen; + use crate::allegra::AllegraCertificate; use crate::shelley::{ProtocolVersionStruct, ShelleyHeader}; use cbor_encodings::{ @@ -210,7 +215,7 @@ impl AlonzoRedeemer { serde::Serialize, schemars::JsonSchema, )] -#[wasm_bindgen::prelude::wasm_bindgen] +#[wasm_bindgen] pub enum AlonzoRedeemerTag { Spend, Mint, diff --git a/multi-era/wasm/Cargo.toml b/multi-era/wasm/Cargo.toml index 7f296d81..51d6d997 100644 --- a/multi-era/wasm/Cargo.toml +++ b/multi-era/wasm/Cargo.toml @@ -14,13 +14,13 @@ keywords = ["cardano"] crate-type = ["cdylib", "rlib"] [dependencies] -cml-chain = { path = "../../chain/rust", version = "5.3.1" } +cml-chain = { path = "../../chain/rust", version = "5.3.1", features = ["used_from_wasm"] } cml-chain-wasm = { path = "../../chain/wasm", version = "5.3.1" } cml-crypto = { path = "../../crypto/rust", version = "5.3.1" } cml-crypto-wasm = { path = "../../crypto/wasm", version = "5.3.1" } cml-core = { path = "../../core/rust", version = "5.3.1" } cml-core-wasm = { path = "../../core/wasm", version = "5.3.1" } -cml-multi-era = { path = "../rust", version = "5.3.1" } +cml-multi-era = { path = "../rust", version = "5.3.1", features = ["used_from_wasm"] } cbor_event = "2.4.0" hex = "0.4.0" linked-hash-map = "0.5.3" From bf34fe436288952e24a2c996b710ac0ba26a980c Mon Sep 17 00:00:00 2001 From: Sebastien Guillemot Date: Wed, 17 Jul 2024 02:11:24 +0200 Subject: [PATCH 16/16] Add support for parsing Shelley genesis blocks (#331) * Add support for parsing Shelley genesis blocks * Genesis keyHash alias + minor fixes * Add alias for `ShelleyGenesisCredential::keyHash` to account for cardano-node json format * Remove unnecessary clone() * Change `u64` to `Coin` when appropriate in Genesis types * ran cargo fmt * Update Genesis parsing for changes in #340 --------- Co-authored-by: rooooooooob Co-authored-by: rooooooooob --- chain/rust/Cargo.toml | 2 + chain/rust/src/genesis/mod.rs | 1 + chain/rust/src/genesis/shelley/config.rs | 65 +++++ chain/rust/src/genesis/shelley/mod.rs | 3 + chain/rust/src/genesis/shelley/parse.rs | 226 ++++++++++++++++++ chain/rust/src/genesis/shelley/raw.rs | 139 +++++++++++ .../src/genesis/shelley/test_data/test.json | 135 +++++++++++ 7 files changed, 571 insertions(+) create mode 100644 chain/rust/src/genesis/shelley/config.rs create mode 100644 chain/rust/src/genesis/shelley/mod.rs create mode 100644 chain/rust/src/genesis/shelley/parse.rs create mode 100644 chain/rust/src/genesis/shelley/raw.rs create mode 100644 chain/rust/src/genesis/shelley/test_data/test.json diff --git a/chain/rust/Cargo.toml b/chain/rust/Cargo.toml index 5bdb22ad..5b7f5f73 100644 --- a/chain/rust/Cargo.toml +++ b/chain/rust/Cargo.toml @@ -38,6 +38,8 @@ num-integer = "0.1.45" thiserror = "1.0.37" num = "0.4" unicode-segmentation = "1.10.1" +serde-aux = "4.5.0" +chrono = "0.4.38" # non-wasm noop_proc_macro = { version = "0.3.0", optional = false } diff --git a/chain/rust/src/genesis/mod.rs b/chain/rust/src/genesis/mod.rs index f5f3e848..e485153e 100644 --- a/chain/rust/src/genesis/mod.rs +++ b/chain/rust/src/genesis/mod.rs @@ -1,2 +1,3 @@ pub mod byron; pub mod network_info; +pub mod shelley; diff --git a/chain/rust/src/genesis/shelley/config.rs b/chain/rust/src/genesis/shelley/config.rs new file mode 100644 index 00000000..45eade5a --- /dev/null +++ b/chain/rust/src/genesis/shelley/config.rs @@ -0,0 +1,65 @@ +use cml_crypto::{Ed25519KeyHash, VRFKeyHash}; +use fraction::Fraction; +use std::collections::BTreeMap; + +use crate::{address::Address, block::ProtocolVersion, Coin}; + +/// A subset of the Shelley genesis data. The genesis data is a JSON file +/// is something completely different from a epoch genesis block and the Byron genesis block +#[derive(Debug, Clone)] +pub struct ShelleyGenesisData { + pub active_slots_coeff: Fraction, + pub epoch_length: u64, + pub gen_delegs: BTreeMap, + pub initial_funds: BTreeMap, + pub max_kes_evolutions: u64, + pub max_lovelace_supply: Coin, + pub network_id: u64, + pub network_magic: u64, + pub protocol_params: ShelleyGenesisProtocolParameters, + pub security_param: u64, + pub slot_length: u64, + pub slots_per_kes_period: u64, + pub staking: Option, + pub system_start: chrono::DateTime, + pub update_quorum: u64, +} + +#[derive(Debug, Clone)] +pub struct ShelleyGenesisDelegations { + pub delegate: Ed25519KeyHash, + pub vrf: VRFKeyHash, +} + +#[derive(Debug, Clone)] +pub struct ShelleyGenesisStaking { + pub pools: BTreeMap, + // initial delegations of staking key -> pool id + pub stake: BTreeMap, +} + +#[derive(Debug, Clone)] +pub struct ShelleyGenesisProtocolParameters { + pub a0: Fraction, + pub decentralisation_param: Fraction, + pub e_max: u64, + pub extra_entropy: ShelleyGenesisExtraEntropy, + pub key_deposit: Coin, + pub max_block_body_size: u64, + pub max_block_header_size: u64, + pub max_tx_size: u64, + pub min_fee_a: Coin, + pub min_fee_b: Coin, + pub min_pool_cost: Coin, + pub min_utxo_value: Coin, + pub n_opt: u64, + pub pool_deposit: Coin, + pub protocol_version: ProtocolVersion, + pub rho: Fraction, + pub tau: Fraction, +} + +#[derive(Debug, Clone)] +pub struct ShelleyGenesisExtraEntropy { + pub tag: String, +} diff --git a/chain/rust/src/genesis/shelley/mod.rs b/chain/rust/src/genesis/shelley/mod.rs new file mode 100644 index 00000000..9fdecf58 --- /dev/null +++ b/chain/rust/src/genesis/shelley/mod.rs @@ -0,0 +1,3 @@ +pub mod config; +pub mod parse; +pub mod raw; diff --git a/chain/rust/src/genesis/shelley/parse.rs b/chain/rust/src/genesis/shelley/parse.rs new file mode 100644 index 00000000..0dfa4415 --- /dev/null +++ b/chain/rust/src/genesis/shelley/parse.rs @@ -0,0 +1,226 @@ +use cml_core::DeserializeError; +use cml_crypto::{ + chain_crypto::Blake2b256, Ed25519KeyHash, PoolMetadataHash, TransactionHash, VRFKeyHash, +}; +use serde_json; +use std::collections::BTreeMap; +use std::io::Read; +use std::str::FromStr; + +use crate::{ + address::{Address, RewardAccount}, + block::ProtocolVersion, + certs::{Ipv4, Ipv6, PoolMetadata, PoolParams, Relay, StakeCredential, Url}, + UnitInterval, +}; + +use super::{ + config, + raw::{self}, +}; + +#[derive(Debug, thiserror::Error)] +pub enum GenesisJSONError { + #[error("JSON: {0:?}")] + Serde(#[from] serde_json::Error), + #[error("Deserialize: {0:?}")] + Deserialize(#[from] DeserializeError), + #[error("ParseInt: {0:?}")] + ParseInt(#[from] std::num::ParseIntError), + #[error("ParseIP: {0:?}")] + ParseIP(#[from] crate::certs::utils::IPStringParsingError), + #[error("Unexpected network type: {0:?}")] + ParseNetwork(String), +} + +pub fn parse_genesis_data( + json: R, +) -> Result { + let data_value: serde_json::Value = serde_json::from_reader(json)?; + let data: raw::ShelleyGenesisData = serde_json::from_value(data_value)?; + + let mut initial_funds = BTreeMap::new(); + for (addr_hex, balance) in &data.initialFunds { + initial_funds.insert(Address::from_hex(addr_hex)?, *balance); + } + + let network_id = match data.networkId.as_str() { + "Mainnet" => crate::NetworkId::mainnet().network, + "Testnet" => crate::NetworkId::testnet().network, + val => return Err(GenesisJSONError::ParseNetwork(val.to_string())), + }; + + let staking = match data.staking.as_ref() { + Some(raw) => { + // 1) Get stake pools + let mut pools: BTreeMap = BTreeMap::new(); + for (pool_id, params) in &raw.pools { + let ration = fraction::Fraction::from_str(¶ms.margin).unwrap(); + let mut owners = Vec::::new(); + for owner in ¶ms.owners { + owners.push(Ed25519KeyHash::from_hex(owner)?); + } + let mut relays = Vec::::new(); + for relay in ¶ms.relays { + if let Some((key, value)) = relay.iter().next() { + match key.as_str() { + "single host address" => { + let ipv4 = match value.IPv4.as_ref() { + Some(s) => Some(Ipv4::from_str(s)?), + _ => None + }; + let ipv6 = match value.IPv6.as_ref() { + Some(s) => Some(Ipv6::from_str(s)?), + _ => None + }; + relays.push(Relay::new_single_host_addr( + value.port, + ipv4, + ipv6 + )); + }, + _ => panic!("Only single host address relays are supported in cardano-node Relay JSON parsing") + } + } + } + let pool_metadata = match params.metadata.as_ref() { + Some(metadata) => Some(PoolMetadata::new( + Url::new(metadata.url.clone()).unwrap(), + PoolMetadataHash::from_hex(&metadata.hash)?, + )), + _ => None, + }; + let parsed_params = PoolParams::new( + Ed25519KeyHash::from_hex(¶ms.publicKey)?, + VRFKeyHash::from_hex(¶ms.vrf)?, + params.pledge, + params.cost, + UnitInterval::new(*ration.numer().unwrap(), *ration.denom().unwrap()), + RewardAccount::new( + match data.networkId.as_str() { + "Mainnet" => crate::NetworkId::mainnet().network as u8, + "Testnet" => crate::NetworkId::testnet().network as u8, + val => return Err(GenesisJSONError::ParseNetwork(val.to_string())), + }, + StakeCredential::new_pub_key(Ed25519KeyHash::from_hex( + ¶ms.rewardAccount.credential.keyHash, + )?), + ), + owners.into(), + relays, + pool_metadata, + ); + pools.insert(Ed25519KeyHash::from_hex(pool_id)?, parsed_params); + } + // 2) Get initial delegations + let mut stake: BTreeMap = BTreeMap::new(); + for (staking_key, pool_id) in &raw.stake { + stake.insert( + Ed25519KeyHash::from_hex(staking_key)?, + Ed25519KeyHash::from_hex(pool_id)?, + ); + } + Some(config::ShelleyGenesisStaking { stake, pools }) + } + _ => None, + }; + + let mut gen_delegs = BTreeMap::new(); + for (key, val) in data.genDelegs.iter() { + gen_delegs.insert( + Ed25519KeyHash::from_hex(key)?, + config::ShelleyGenesisDelegations { + delegate: Ed25519KeyHash::from_hex(&val.delegate)?, + vrf: VRFKeyHash::from_hex(&val.vrf)?, + }, + ); + } + Ok(config::ShelleyGenesisData { + active_slots_coeff: fraction::Fraction::from_str(&data.activeSlotsCoeff).unwrap(), + epoch_length: data.epochLength, + gen_delegs, + initial_funds, + max_kes_evolutions: data.maxKESEvolutions, + max_lovelace_supply: data.maxLovelaceSupply, + network_id, + network_magic: data.networkMagic, + protocol_params: config::ShelleyGenesisProtocolParameters { + a0: fraction::Fraction::from_str(&data.protocolParams.a0).unwrap(), + decentralisation_param: fraction::Fraction::from_str( + &data.protocolParams.decentralisationParam, + ) + .unwrap(), + e_max: data.protocolParams.eMax, + extra_entropy: config::ShelleyGenesisExtraEntropy { + tag: data.protocolParams.extraEntropy.tag, + }, + key_deposit: data.protocolParams.keyDeposit, + max_block_body_size: data.protocolParams.maxBlockBodySize, + max_block_header_size: data.protocolParams.maxBlockHeaderSize, + max_tx_size: data.protocolParams.maxTxSize, + min_fee_a: data.protocolParams.minFeeA, + min_fee_b: data.protocolParams.minFeeB, + min_pool_cost: data.protocolParams.minPoolCost, + min_utxo_value: data.protocolParams.minUTxOValue, + n_opt: data.protocolParams.nOpt, + pool_deposit: data.protocolParams.poolDeposit, + protocol_version: ProtocolVersion::new( + data.protocolParams.protocolVersion.major, + data.protocolParams.protocolVersion.minor, + ), + rho: fraction::Fraction::from_str(&data.protocolParams.rho).unwrap(), + tau: fraction::Fraction::from_str(&data.protocolParams.tau).unwrap(), + }, + security_param: data.securityParam, + slot_length: data.slotLength, + slots_per_kes_period: data.slotsPerKESPeriod, + staking, + system_start: data.systemStart.parse().expect("Failed to parse date"), + update_quorum: data.updateQuorum, + }) +} + +pub fn redeem_address_to_txid(pubkey: &Address) -> TransactionHash { + let txid = Blake2b256::new(&pubkey.to_raw_bytes()); + TransactionHash::from(*txid.as_hash_bytes()) +} + +#[cfg(test)] +mod test { + use super::*; + + fn get_test_genesis_data() -> &'static str { + include_str!("./test_data/test.json") + } + + #[test] + fn calc_address_txid() { + let hash = redeem_address_to_txid( + &Address::from_bech32("addr_test1qpefp65049pncyz95nyyww2e44sgumqr5kx8mcemm0fuumeftwv8zdtpqct0836wz8y56aakem2uejf604cee7cn2p3qp9p8te").unwrap(), + ); + assert_eq!( + hash.to_hex(), + "66dc6b2e628bf1fb6204797f1a07f8e949d9520a70e859ecbf3ea3076029871e" + ); + } + + #[test] + fn parse_test_genesis_files() { + let genesis_data = super::parse_genesis_data(get_test_genesis_data().as_bytes()).unwrap(); + + assert_eq!(genesis_data.epoch_length, 432000u64); + assert_eq!(genesis_data.network_id, 0); + assert_eq!(genesis_data.network_magic, 764824073u64); + + assert_eq!( + *genesis_data + .initial_funds + .iter() + .find(|(n, _)| n.to_hex() + == "605276322ac7882434173dcc6441905f6737689bd309b68ad8b3614fd8") + .unwrap() + .1, + 3000000000000000u64 + ); + } +} diff --git a/chain/rust/src/genesis/shelley/raw.rs b/chain/rust/src/genesis/shelley/raw.rs new file mode 100644 index 00000000..c89fd6d4 --- /dev/null +++ b/chain/rust/src/genesis/shelley/raw.rs @@ -0,0 +1,139 @@ +use crate::assets::Coin; +use serde::{Deserialize, Serialize}; +use serde_aux::prelude::*; +use std::collections::HashMap; + +/// Parsing of the JSON representation of the Shelley genesis block +/// Note: for a lot of these fields, I didn't check what the max valid size is in the Haskell code +/// so I just used u64 everywhere + +#[allow(non_snake_case)] +#[derive(Serialize, Deserialize, Debug)] +pub struct ShelleyGenesisData { + // convert lossless JSON floats to string to avoid lossy Rust f64 + #[serde(deserialize_with = "deserialize_string_from_number")] + pub activeSlotsCoeff: String, + pub epochLength: u64, + pub genDelegs: HashMap, + pub initialFunds: HashMap, + pub maxKESEvolutions: u64, + pub maxLovelaceSupply: Coin, + pub networkId: String, + pub networkMagic: u64, + pub protocolParams: ShelleyGenesisProtocolParameters, + pub securityParam: u64, + pub slotLength: u64, + pub slotsPerKESPeriod: u64, + pub staking: Option, + pub systemStart: String, + pub updateQuorum: u64, +} + +#[allow(non_snake_case)] +#[derive(Serialize, Deserialize, Debug)] +pub struct ShelleyGenesisDelegations { + pub delegate: String, + pub vrf: String, +} + +#[allow(non_snake_case)] +#[derive(Serialize, Deserialize, Debug)] +pub struct ShelleyGenesisProtocolParameters { + // convert lossless JSON floats to string to avoid lossy Rust f64 + #[serde(deserialize_with = "deserialize_string_from_number")] + pub a0: String, + // convert lossless JSON floats to string to avoid lossy Rust f64 + #[serde(deserialize_with = "deserialize_string_from_number")] + pub decentralisationParam: String, + pub eMax: u64, + pub extraEntropy: ShelleyGenesisExtraEntropy, + pub keyDeposit: Coin, + pub maxBlockBodySize: u64, + pub maxBlockHeaderSize: u64, + pub maxTxSize: u64, + pub minFeeA: Coin, + pub minFeeB: Coin, + pub minPoolCost: Coin, + pub minUTxOValue: Coin, + pub nOpt: u64, + pub poolDeposit: Coin, + pub protocolVersion: ShelleyGenesisProtocolVersion, + // convert lossless JSON floats to string to avoid lossy Rust f64 + #[serde(deserialize_with = "deserialize_string_from_number")] + pub rho: String, + // convert lossless JSON floats to string to avoid lossy Rust f64 + #[serde(deserialize_with = "deserialize_string_from_number")] + pub tau: String, +} + +#[allow(non_snake_case)] +#[derive(Serialize, Deserialize, Debug)] +pub struct ShelleyGenesisExtraEntropy { + pub tag: String, +} + +#[allow(non_snake_case)] +#[derive(Serialize, Deserialize, Debug)] +pub struct ShelleyGenesisProtocolVersion { + pub major: u64, + pub minor: u64, +} + +#[allow(non_snake_case)] +#[derive(Serialize, Deserialize, Debug)] +pub struct ShelleyGenesisStaking { + pub pools: HashMap, + pub stake: HashMap, +} + +#[allow(non_snake_case)] +#[derive(Serialize, Deserialize, Debug)] +pub struct ShelleyGenesisPool { + pub cost: Coin, + // convert lossless JSON floats to string to avoid lossy Rust f64 + #[serde(deserialize_with = "deserialize_string_from_number")] + pub margin: String, + pub metadata: Option, + pub owners: Vec, + pub pledge: Coin, + pub publicKey: String, + pub relays: Vec, + pub rewardAccount: ShelleyGenesisRewardAccount, + pub vrf: String, +} + +// TODO: there are other relay types, but I can't find the JSON type for them +// and I can't find any usage of them in the wild anyway +// The key here defines the relay type +// ex: +// - single host address +type RelayTypeMap = HashMap; + +#[allow(non_snake_case)] +#[derive(Serialize, Deserialize, Debug)] +pub struct ShelleyGenesisPoolSingleHotsRelay { + pub IPv6: Option, + pub port: Option, + pub IPv4: Option, +} + +#[allow(non_snake_case)] +#[derive(Serialize, Deserialize, Debug)] +pub struct ShelleyGenesisPoolMetadata { + pub hash: String, + pub url: String, +} +#[allow(non_snake_case)] +#[derive(Serialize, Deserialize, Debug)] +pub struct ShelleyGenesisRewardAccount { + pub network: String, + pub credential: ShelleyGenesisCredential, +} +#[allow(non_snake_case)] +#[derive(Serialize, Deserialize, Debug)] +pub struct ShelleyGenesisCredential { + // for some reason there actually is a space in the JSON key emitted by the Haskell node + // both key hash and keyHash are accepted + #[serde(alias = "key hash")] + pub keyHash: String, +} diff --git a/chain/rust/src/genesis/shelley/test_data/test.json b/chain/rust/src/genesis/shelley/test_data/test.json new file mode 100644 index 00000000..09f234ef --- /dev/null +++ b/chain/rust/src/genesis/shelley/test_data/test.json @@ -0,0 +1,135 @@ +{ + "activeSlotsCoeff": 0.05, + "epochLength": 432000, + "genDelegs": { + "337bc5ef0f1abf205624555c13a37258c42b46b1259a6b1a6d82574e": { + "delegate": "41fd6bb31f34469320aa47cf6ccc3918e58a06d60ea1f2361efe2458", + "vrf": "7053e3ecd2b19db13e5338aa75fb518fc08b6c218f56ad65760d3eb074be95d4" + }, + "b5c3fed76c54bfdcda7993e4171eff2fb853f8ab920ab80047278a91": { + "delegate": "fcb677a90948d1d5b358912f54f6baaf762ecf5cd6579c93bcb49cef", + "vrf": "c7715f726e8e4f7745ccc646f4350758460de71de5694b244a47761fb106ec6e" + }, + "e34a75849b978bb20c366f531f978b3111b91aae0e469108dca8e433": { + "delegate": "81babf3c139646f0f0268abed36d2a54757492a3a68cda2438a37f7e", + "vrf": "ca336185cd781a6543b6c1e62ee1eee53e237d5d1fb065f08412d40d61b6ca06" + } + }, + "initialFunds": { + "007290ea8fa9433c1045a4c8473959ad608e6c03a58c7de33bdbd3ce6f295b987135610616f3c74e11c94d77b6ced5ccc93a7d719cfb135062": 300000000000, + "605276322ac7882434173dcc6441905f6737689bd309b68ad8b3614fd8": 3000000000000000, + "60a0f1aa7dca95017c11e7e373aebcf0c4568cf47ec12b94f8eb5bba8b": 3000000000000000, + "60ba957a0fff6816021b2afa7900beea68fd10f2d78fb5b64de0d2379c": 3000000000000000, + "00c8c47610a36034aac6fc58848bdae5c278d994ff502c05455e3b3ee8f8ed3a0eea0ef835ffa7bbfcde55f7fe9d2cc5d55ea62cecb42bab3c": 10000000000, + "004048ff89ca4f88e66598e620aa0c7128c2145d9a181ae9a4a81ca8e3e849af38840c5562dd382be37c9e76545c8191f9d8f6df1d20cfcee0": 10000000000, + "00ca6e1b1f320d543a24adeabc0aa4627635c7349b639f86f74bdfdd78d31b28c9619a58b3792a7394ab85deb36889c4d7b0632c8167b855d2": 10000000000, + "0007d781fe8e33883e371f9550c2f1087321fc32e06e80b65e349ccb027702d6880e86e77a0520efa37ede45002a1de43b68692e175b742e67": 10000000000, + "00627b2598dd71129167825160c564067d1d245e79cc237094815c5cb2b125e30ec2f4ce4059a069e08c3cd82cdfc9451bfb22487f8a25ceef": 10000000000, + "00c6cf7bd50f37f7e4cc161fc00f07e9b2226ba5552ccaf30d315fa0135bbc8cbd9ab5379f368fc8d3500c37a9d14074cc6ddad89e3686f0e0": 10000000000, + "005164ab186715c86378020956d892cf72f67636b78967d67cfe7360479130dc89cf7a9bc89109f939956b66f93293ade4c3920b72fd40beea": 10000000000, + "003dd38742e9848c6f12c13ddb1f9464fc0ce0bb92102768087975317e5a9f869fcd913562c9b0e0f01f77e5359ea780d37f9355f9702eff8b": 10000000000, + "0088e7e670b45cab2322b518ef7b6f66d30aec0d923dc463e467091a790f67796b9fa71224f2846cebbcf4950c11e040ee124d30f6e164bcd5": 10000000000, + "00c70b8421617802d3f23956cab1957e1d306cd4808589b41760e97927ebfd6053ba12b38288b2b6d5d4c4618d6a8ce59d50580e9c6f704af5": 10000000000, + "00c0933b8238f6f3332e48c34cf1a8e0555943b33cd4abc53aefb7d6124b7ce40dd496bdc02b34602f3a773ff7cccee873991e4c8866f3a70b": 10000000000, + "0069f7d7289de2f01cd1e0265ac5be943b41775abae0ce6b3eac0edee0ce9cadb7cdec2bded3ef8a7bbe3352869bfc1387754c9ee6b1782d9c": 10000000000, + "00709a7070005c652c27df73dbbde3319a90b127bea96aded1c5fb87a59c51dbcf90fa890174497f3f66a0dad06eb7f131e06567995e9c50a5": 10000000000, + "00fc576df3a279885a7a4d0fc500372daa1d96f26c6763542ecd2ad8551753024adea37c134edebb68dc0cfaed5a7009e8305fe1fed8d0ccd1": 10000000000, + "003346a630e6972bf38cce87219db1d63061e7cd324cad88c18e504f2990cac68e973f51256ca938683fa4ea12173d7d047d940fbb883bd0e8": 10000000000, + "0028b862d001e6a64a02b3560cbc532eab4557593477c39cc523e0b9fc527100898c11e731194171b908aad463770d6cbf7ec8871c4cb1e518": 10000000000, + "005e0e57040b06e9d71e0f28f126262838a68db0b52b4fd1b3877dda2203d5d7d4f19c5ee3a1ed51bb670779de19d40aaff2e5e9468cc05c5e": 10000000000, + "00367f65ab69b1e6715c8d5a14964214c9505ed17032266b3209a2c40dcbae9a2a881e603ff39d36e987bacfb87ee98051f222c5fe3efd350c": 10000000000, + "00c5c4ca287f3b53948b5468e5e23b1c87fe61ce52c0d9afd65d070795038751a619d463e91eaed0a774ebdb2f8e12a01a378a153bc3627323": 10000000000, + "00ef198fb7c35e1968308a0b75cfee54a46e13e86dd3354283300831d624165c357b5a0413906a0bfea8ba57587331f0836a186d632ed041b8": 10000000000 + }, + "maxKESEvolutions": 60, + "maxLovelaceSupply": 45000000000000000, + "networkId": "Testnet", + "networkMagic": 764824073, + "protocolParams": { + "a0": 0, + "decentralisationParam": 0, + "eMax": 18, + "extraEntropy": { + "tag": "NeutralNonce" + }, + "keyDeposit": 2000000, + "maxBlockBodySize": 65536, + "maxBlockHeaderSize": 1100, + "maxTxSize": 16384, + "minFeeA": 44, + "minFeeB": 155381, + "minPoolCost": 340000000, + "minUTxOValue": 1000000, + "nOpt": 100, + "poolDeposit": 500000000, + "protocolVersion": { + "major": 8, + "minor": 0 + }, + "rho": 0.003, + "tau": 0.20 + }, + "securityParam": 12, + "slotLength": 1, + "slotsPerKESPeriod": 129600, + "staking": { + "pools": { + "7301761068762f5900bde9eb7c1c15b09840285130f5b0f53606cc57": { + "cost": 340000000, + "margin": 3.0e-2, + "metadata": { + "hash": "b150b12a1301c4b1510ac8b9f53f7571cabb43455f6fd244cd8fd97504b1c869", + "url": "https://adalite.io/ADLT4-metadata.json" + }, + "owners": [ + "463a9695c9222183ee6e1523478722bebcb332fa3769f1d8ef40c7d0", + "5049c1dac0e597ee902f27a74a167cf135ae7c1717b0d3a417cd6c67" + ], + "pledge": 0, + "publicKey": "7301761068762f5900bde9eb7c1c15b09840285130f5b0f53606cc57", + "relays": [ + { + "single host address": { + "IPv6": null, + "port": 3003, + "IPv4": "54.228.75.154" + } + }, + { + "single host address": { + "IPv6": null, + "port": 3001, + "IPv4": "54.228.75.154" + } + }, + { + "single host address": { + "IPv6": null, + "port": 3003, + "IPv4": "34.249.11.89" + } + }, + { + "single host address": { + "IPv6": null, + "port": 3001, + "IPv4": "34.249.11.89" + } + } + ], + "rewardAccount": { + "credential": { + "key hash": "11a14edf73b08a0a27cb98b2c57eb37c780df18fcfcf6785ed5df84a" + }, + "network": "Testnet" + }, + "vrf": "c2b62ffa92ad18ffc117ea3abeb161a68885000a466f9c71db5e4731d6630061" + } + }, + "stake": { + "295b987135610616f3c74e11c94d77b6ced5ccc93a7d719cfb135062": "7301761068762f5900bde9eb7c1c15b09840285130f5b0f53606cc57" + } + }, + "systemStart": "2022-09-15T04:09:11.577484Z", + "updateQuorum": 2 +} \ No newline at end of file