From 9740dc05608930bdb032ad27853ea77e29bcf6f0 Mon Sep 17 00:00:00 2001 From: Santiago Carmuega Date: Sat, 11 Mar 2023 18:12:31 +0100 Subject: [PATCH] refactor(traverse): Unify mint and output asset artifacts (#231) --- pallas-traverse/src/assets.rs | 139 +++++++++++----------------------- pallas-traverse/src/block.rs | 2 +- pallas-traverse/src/lib.rs | 14 +--- pallas-traverse/src/mint.rs | 32 -------- pallas-traverse/src/output.rs | 70 ++++++++++++++++- pallas-traverse/src/tx.rs | 10 +-- 6 files changed, 124 insertions(+), 143 deletions(-) delete mode 100644 pallas-traverse/src/mint.rs diff --git a/pallas-traverse/src/assets.rs b/pallas-traverse/src/assets.rs index 9c99727..28a29c1 100644 --- a/pallas-traverse/src/assets.rs +++ b/pallas-traverse/src/assets.rs @@ -1,110 +1,63 @@ -use std::ops::Deref; - -use pallas_codec::utils::{Bytes, KeyValuePairs}; use pallas_crypto::hash::Hash; -use pallas_primitives::{alonzo, babbage}; +use pallas_primitives::alonzo; -use crate::{Asset, MultiEraOutput}; +use crate::MultiEraAsset; -fn iter_policy_assets<'b>( - policy: &'b Hash<28>, - assets: &'b KeyValuePairs, -) -> impl Iterator + 'b { - assets - .iter() - .map(|(name, amount)| Asset::NativeAsset(*policy, Vec::::clone(name), *amount)) -} +impl<'b> MultiEraAsset<'b> { + pub fn collect_alonzo_compatible_output(source: &'b alonzo::Multiasset) -> Vec { + source + .iter() + .flat_map(|(policy, assets)| { + assets.iter().map(|(name, amount)| { + MultiEraAsset::AlonzoCompatible(policy, name, *amount as i64) + }) + }) + .collect::>() + } -fn collect_multiassets(multiassets: &alonzo::Multiasset) -> Vec { - multiassets - .iter() - .flat_map(|(p, a)| iter_policy_assets(p, a)) - .collect::>() -} + pub fn collect_alonzo_compatible_mint(source: &'b alonzo::Multiasset) -> Vec { + source + .iter() + .flat_map(|(policy, assets)| { + assets + .iter() + .map(|(name, amount)| MultiEraAsset::AlonzoCompatible(policy, name, *amount)) + }) + .collect::>() + } -impl Asset { - pub fn subject(&self) -> String { + pub fn policy_id(&self) -> Option<&Hash<28>> { match self { - Self::Ada(_) => String::from("ada"), - Self::NativeAsset(p, n, _) => format!("{p}.{}", hex::encode(n)), + Self::AlonzoCompatible(x, ..) => Some(*x), + Self::Lovelace(_) => None, } } - pub fn ascii_name(&self) -> Option { + pub fn coin(&self) -> i64 { match self { - Self::Ada(_) => None, - Self::NativeAsset(_, n, _) => String::from_utf8(n.clone()).ok(), + Self::AlonzoCompatible(_, _, x) => *x, + Self::Lovelace(x) => *x as i64, } } - pub fn policy_hex(&self) -> Option { + pub fn as_alonzo(&self) -> Option<(&alonzo::PolicyId, &alonzo::AssetName, i64)> { match self { - Asset::Ada(_) => None, - Asset::NativeAsset(p, _, _) => Some(p.to_string()), + Self::AlonzoCompatible(a, b, c) => Some((*a, *b, *c)), + _ => None, + } + } + + pub fn to_subject(&self) -> Option { + match self { + Self::AlonzoCompatible(p, n, _) => Some(format!("{p}.{}", hex::encode(n.to_vec()))), + _ => None, + } + } + + pub fn to_ascii_name(&self) -> Option { + match self { + Self::AlonzoCompatible(_, n, _) => String::from_utf8(n.to_vec()).ok(), + _ => None, } } } - -impl<'b> MultiEraOutput<'b> { - /// The amount of ADA asset expressed in Lovelace unit - /// - /// The value returned provides the amount of the ADA in a particular - /// output. The value is expressed in 'lovelace' (1 ADA = 1,000,000 - /// lovelace). - pub fn lovelace_amount(&self) -> u64 { - match self { - MultiEraOutput::Byron(x) => x.amount, - MultiEraOutput::Babbage(x) => match x.deref().deref() { - babbage::MintedTransactionOutput::Legacy(x) => match x.amount { - babbage::Value::Coin(c) => c, - babbage::Value::Multiasset(c, _) => c, - }, - babbage::MintedTransactionOutput::PostAlonzo(x) => match x.value { - babbage::Value::Coin(c) => c, - babbage::Value::Multiasset(c, _) => c, - }, - }, - MultiEraOutput::AlonzoCompatible(x) => match x.amount { - alonzo::Value::Coin(c) => c, - alonzo::Value::Multiasset(c, _) => c, - }, - } - } - - /// List of native assets in the output - /// - /// Returns a list of Asset structs where each one represent a native asset - /// present in the output of the tx. ADA assets are not included in this - /// list. - pub fn non_ada_assets(&self) -> Vec { - match self { - MultiEraOutput::Byron(_) => vec![], - MultiEraOutput::Babbage(x) => match x.deref().deref() { - babbage::MintedTransactionOutput::Legacy(x) => match &x.amount { - babbage::Value::Coin(_) => vec![], - babbage::Value::Multiasset(_, x) => collect_multiassets(x), - }, - babbage::MintedTransactionOutput::PostAlonzo(x) => match &x.value { - babbage::Value::Coin(_) => vec![], - babbage::Value::Multiasset(_, x) => collect_multiassets(x), - }, - }, - MultiEraOutput::AlonzoCompatible(x) => match &x.amount { - alonzo::Value::Coin(_) => vec![], - alonzo::Value::Multiasset(_, x) => collect_multiassets(x), - }, - } - } - - /// List of all assets in the output - /// - /// Returns a list of Asset structs where each one represent either ADA or a - /// native asset present in the output of the tx. - pub fn assets(&self) -> Vec { - [ - vec![Asset::Ada(self.lovelace_amount())], - self.non_ada_assets(), - ] - .concat() - } -} diff --git a/pallas-traverse/src/block.rs b/pallas-traverse/src/block.rs index f65e0c0..73affaa 100644 --- a/pallas-traverse/src/block.rs +++ b/pallas-traverse/src/block.rs @@ -1,4 +1,4 @@ -use std::borrow::Cow; +use std::{borrow::Cow, ops::Deref}; use pallas_codec::minicbor; use pallas_crypto::hash::Hash; diff --git a/pallas-traverse/src/lib.rs b/pallas-traverse/src/lib.rs index d077a36..ce2f900 100644 --- a/pallas-traverse/src/lib.rs +++ b/pallas-traverse/src/lib.rs @@ -18,7 +18,6 @@ pub mod hashes; pub mod header; pub mod input; pub mod meta; -pub mod mint; pub mod output; pub mod probe; pub mod signers; @@ -108,10 +107,9 @@ pub enum MultiEraMeta<'b> { #[derive(Debug, Clone)] #[non_exhaustive] -pub enum MultiEraMint<'b> { - NotApplicable, - Empty, - AlonzoCompatible(&'b alonzo::Mint), +pub enum MultiEraAsset<'b> { + Lovelace(u64), + AlonzoCompatible(&'b alonzo::PolicyId, &'b alonzo::AssetName, i64), } #[derive(Debug, Clone)] @@ -133,12 +131,6 @@ pub enum MultiEraSigners<'b> { #[derive(Debug, Clone)] pub struct OutputRef(Hash<32>, u64); -#[derive(Debug, Clone)] -pub enum Asset { - Ada(u64), - NativeAsset(Hash<28>, Vec, u64), -} - #[derive(Debug, Error)] pub enum Error { #[error("Invalid CBOR structure: {0}")] diff --git a/pallas-traverse/src/mint.rs b/pallas-traverse/src/mint.rs deleted file mode 100644 index 233e8e9..0000000 --- a/pallas-traverse/src/mint.rs +++ /dev/null @@ -1,32 +0,0 @@ -use pallas_primitives::alonzo; - -use crate::MultiEraMint; - -impl Default for MultiEraMint<'_> { - fn default() -> Self { - MultiEraMint::Empty - } -} - -impl<'b> MultiEraMint<'b> { - pub fn len(&self) -> usize { - match self { - MultiEraMint::AlonzoCompatible(x) => x.len(), - _ => 0, - } - } - - pub fn is_empty(&self) -> bool { - match self { - MultiEraMint::AlonzoCompatible(x) => x.is_empty(), - _ => true, - } - } - - pub fn as_alonzo(&self) -> Option<&alonzo::Mint> { - match self { - Self::AlonzoCompatible(x) => Some(x), - _ => None, - } - } -} diff --git a/pallas-traverse/src/output.rs b/pallas-traverse/src/output.rs index a0cbbbb..66553fa 100644 --- a/pallas-traverse/src/output.rs +++ b/pallas-traverse/src/output.rs @@ -4,7 +4,7 @@ use pallas_addresses::{Address, ByronAddress, Error as AddressError}; use pallas_codec::minicbor; use pallas_primitives::{alonzo, babbage, byron}; -use crate::{Era, MultiEraOutput}; +use crate::{Era, MultiEraAsset, MultiEraOutput}; impl<'b> MultiEraOutput<'b> { pub fn from_byron(output: &'b byron::TxOut) -> Self { @@ -109,4 +109,72 @@ impl<'b> MultiEraOutput<'b> { } } } + + /// The amount of ADA asset expressed in Lovelace unit + /// + /// The value returned provides the amount of the ADA in a particular + /// output. The value is expressed in 'lovelace' (1 ADA = 1,000,000 + /// lovelace). + pub fn lovelace_amount(&self) -> u64 { + match self { + MultiEraOutput::Byron(x) => x.amount, + MultiEraOutput::Babbage(x) => match x.deref().deref() { + babbage::MintedTransactionOutput::Legacy(x) => match x.amount { + babbage::Value::Coin(c) => c, + babbage::Value::Multiasset(c, _) => c, + }, + babbage::MintedTransactionOutput::PostAlonzo(x) => match x.value { + babbage::Value::Coin(c) => c, + babbage::Value::Multiasset(c, _) => c, + }, + }, + MultiEraOutput::AlonzoCompatible(x) => match x.amount { + alonzo::Value::Coin(c) => c, + alonzo::Value::Multiasset(c, _) => c, + }, + } + } + + /// List of native assets in the output + /// + /// Returns a list of Asset structs where each one represent a native asset + /// present in the output of the tx. ADA assets are not included in this + /// list. + pub fn non_ada_assets(&self) -> Vec { + match self { + MultiEraOutput::Byron(_) => vec![], + MultiEraOutput::Babbage(x) => match x.deref().deref() { + babbage::MintedTransactionOutput::Legacy(x) => match &x.amount { + babbage::Value::Coin(_) => vec![], + babbage::Value::Multiasset(_, x) => { + MultiEraAsset::collect_alonzo_compatible_output(x) + } + }, + babbage::MintedTransactionOutput::PostAlonzo(x) => match &x.value { + babbage::Value::Coin(_) => vec![], + babbage::Value::Multiasset(_, x) => { + MultiEraAsset::collect_alonzo_compatible_output(x) + } + }, + }, + MultiEraOutput::AlonzoCompatible(x) => match &x.amount { + alonzo::Value::Coin(_) => vec![], + alonzo::Value::Multiasset(_, x) => { + MultiEraAsset::collect_alonzo_compatible_output(x) + } + }, + } + } + + /// List of all assets in the output + /// + /// Returns a list of Asset structs where each one represent either ADA or a + /// native asset present in the output of the tx. + pub fn assets(&self) -> Vec { + [ + vec![MultiEraAsset::Lovelace(self.lovelace_amount())], + self.non_ada_assets(), + ] + .concat() + } } diff --git a/pallas-traverse/src/tx.rs b/pallas-traverse/src/tx.rs index 05022f2..8e6224f 100644 --- a/pallas-traverse/src/tx.rs +++ b/pallas-traverse/src/tx.rs @@ -5,7 +5,7 @@ use pallas_crypto::hash::Hash; use pallas_primitives::{alonzo, babbage, byron}; use crate::{ - Era, MultiEraCert, MultiEraInput, MultiEraMeta, MultiEraMint, MultiEraOutput, MultiEraSigners, + Era, MultiEraAsset, MultiEraCert, MultiEraInput, MultiEraMeta, MultiEraOutput, MultiEraSigners, MultiEraTx, MultiEraWithdrawals, OriginalHash, }; @@ -170,21 +170,21 @@ impl<'b> MultiEraTx<'b> { } } - pub fn mint(&self) -> MultiEraMint { + pub fn mints(&self) -> Vec { match self { MultiEraTx::AlonzoCompatible(x, _) => x .transaction_body .mint .as_ref() - .map(MultiEraMint::AlonzoCompatible) + .map(MultiEraAsset::collect_alonzo_compatible_mint) .unwrap_or_default(), MultiEraTx::Babbage(x) => x .transaction_body .mint .as_ref() - .map(MultiEraMint::AlonzoCompatible) + .map(MultiEraAsset::collect_alonzo_compatible_mint) .unwrap_or_default(), - MultiEraTx::Byron(_) => MultiEraMint::NotApplicable, + MultiEraTx::Byron(_) => vec![], } }