From 92da12424725872ea85f5ab9f1c5294fe9ad82c1 Mon Sep 17 00:00:00 2001 From: Santiago Carmuega Date: Thu, 18 Apr 2024 22:36:19 -0300 Subject: [PATCH] feat(traverse): track original era for tx outputs (#447) --- pallas-applying/src/babbage.rs | 2 +- pallas-applying/tests/alonzo.rs | 8 +++++--- pallas-applying/tests/common.rs | 6 +++--- pallas-traverse/src/lib.rs | 4 ++-- pallas-traverse/src/output.rs | 35 +++++++++++++++++++++------------ pallas-traverse/src/tx.rs | 4 ++-- 6 files changed, 35 insertions(+), 24 deletions(-) diff --git a/pallas-applying/src/babbage.rs b/pallas-applying/src/babbage.rs index 2dfa17f..a060451 100644 --- a/pallas-applying/src/babbage.rs +++ b/pallas-applying/src/babbage.rs @@ -284,7 +284,7 @@ fn check_collaterals_assets( fn val_from_multi_era_output(multi_era_output: &MultiEraOutput) -> Value { match multi_era_output { MultiEraOutput::Byron(output) => Value::Coin(output.amount), - MultiEraOutput::AlonzoCompatible(output) => output.amount.clone(), + MultiEraOutput::AlonzoCompatible(output, _) => output.amount.clone(), babbage_output => match babbage_output.as_babbage() { Some(PseudoTransactionOutput::Legacy(output)) => output.amount.clone(), Some(PseudoTransactionOutput::PostAlonzo(output)) => output.value.clone(), diff --git a/pallas-applying/tests/alonzo.rs b/pallas-applying/tests/alonzo.rs index 3cb8c97..5a40498 100644 --- a/pallas-applying/tests/alonzo.rs +++ b/pallas-applying/tests/alonzo.rs @@ -686,12 +686,14 @@ mod alonzo_tests { .unwrap(); let multi_era_in: MultiEraInput = MultiEraInput::AlonzoCompatible(Box::new(Cow::Owned(tx_in.clone()))); - let multi_era_out: MultiEraOutput = - MultiEraOutput::AlonzoCompatible(Box::new(Cow::Owned(TransactionOutput { + let multi_era_out: MultiEraOutput = MultiEraOutput::AlonzoCompatible( + Box::new(Cow::Owned(TransactionOutput { address: Bytes::try_from(altered_address.to_hex()).unwrap(), amount: Value::Coin(5000000), datum_hash: None, - }))); + })), + Era::Alonzo, + ); utxos.insert(multi_era_in, multi_era_out); let metx: MultiEraTx = MultiEraTx::from_alonzo_compatible(&mtx, Era::Alonzo); let env: Environment = Environment { diff --git a/pallas-applying/tests/common.rs b/pallas-applying/tests/common.rs index afc33cc..10cd8dd 100644 --- a/pallas-applying/tests/common.rs +++ b/pallas-applying/tests/common.rs @@ -9,7 +9,7 @@ use pallas_primitives::{ }, byron::{Address, MintedTxPayload, Tx, TxOut}, }; -use pallas_traverse::{MultiEraInput, MultiEraOutput}; +use pallas_traverse::{Era, MultiEraInput, MultiEraOutput}; use std::{borrow::Cow, iter::zip, vec::Vec}; use pallas_codec::utils::{Bytes, CborWrap}; @@ -74,7 +74,7 @@ pub fn mk_utxo_for_alonzo_compatible_tx<'a>( datum_hash: *datum_hash, }; let multi_era_out: MultiEraOutput = - MultiEraOutput::AlonzoCompatible(Box::new(Cow::Owned(tx_out))); + MultiEraOutput::AlonzoCompatible(Box::new(Cow::Owned(tx_out)), Era::Alonzo); utxos.insert(multi_era_in, multi_era_out); } utxos @@ -134,7 +134,7 @@ pub fn add_collateral_alonzo<'a>( let multi_era_in: MultiEraInput = MultiEraInput::AlonzoCompatible(Box::new(Cow::Owned(tx_in.clone()))); let multi_era_out: MultiEraOutput = - MultiEraOutput::AlonzoCompatible(Box::new(Cow::Owned(tx_out))); + MultiEraOutput::AlonzoCompatible(Box::new(Cow::Owned(tx_out)), Era::Alonzo); utxos.insert(multi_era_in, multi_era_out); } } diff --git a/pallas-traverse/src/lib.rs b/pallas-traverse/src/lib.rs index f278359..b6cddd8 100644 --- a/pallas-traverse/src/lib.rs +++ b/pallas-traverse/src/lib.rs @@ -86,10 +86,10 @@ pub enum MultiEraTx<'b> { Conway(Box>>), } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Eq)] #[non_exhaustive] pub enum MultiEraOutput<'b> { - AlonzoCompatible(Box>), + AlonzoCompatible(Box>, Era), Babbage(Box>>), Conway(Box>>), Byron(Box>), diff --git a/pallas-traverse/src/output.rs b/pallas-traverse/src/output.rs index 9749e46..1f7922e 100644 --- a/pallas-traverse/src/output.rs +++ b/pallas-traverse/src/output.rs @@ -11,8 +11,8 @@ impl<'b> MultiEraOutput<'b> { Self::Byron(Box::new(Cow::Borrowed(output))) } - pub fn from_alonzo_compatible(output: &'b alonzo::TransactionOutput) -> Self { - Self::AlonzoCompatible(Box::new(Cow::Borrowed(output))) + pub fn from_alonzo_compatible(output: &'b alonzo::TransactionOutput, era: Era) -> Self { + Self::AlonzoCompatible(Box::new(Cow::Borrowed(output)), era) } pub fn from_babbage(output: &'b babbage::MintedTransactionOutput<'b>) -> Self { @@ -25,7 +25,7 @@ impl<'b> MultiEraOutput<'b> { pub fn datum(&self) -> Option { match self { - MultiEraOutput::AlonzoCompatible(x) => { + MultiEraOutput::AlonzoCompatible(x, _) => { x.datum_hash.map(babbage::MintedDatumOption::Hash) } MultiEraOutput::Babbage(x) => match x.deref().deref() { @@ -46,7 +46,7 @@ impl<'b> MultiEraOutput<'b> { pub fn script_ref(&self) -> Option { match &self { - MultiEraOutput::AlonzoCompatible(_) => None, + MultiEraOutput::AlonzoCompatible(..) => None, MultiEraOutput::Babbage(x) => match x.deref().deref() { babbage::MintedTransactionOutput::Legacy(_) => None, babbage::MintedTransactionOutput::PostAlonzo(x) => { @@ -65,7 +65,7 @@ impl<'b> MultiEraOutput<'b> { pub fn address(&self) -> Result { match self { - MultiEraOutput::AlonzoCompatible(x) => Address::from_bytes(&x.address), + MultiEraOutput::AlonzoCompatible(x, _) => Address::from_bytes(&x.address), MultiEraOutput::Babbage(x) => match x.deref().deref() { babbage::MintedTransactionOutput::Legacy(x) => Address::from_bytes(&x.address), babbage::MintedTransactionOutput::PostAlonzo(x) => Address::from_bytes(&x.address), @@ -82,7 +82,7 @@ impl<'b> MultiEraOutput<'b> { pub fn as_alonzo(&self) -> Option<&alonzo::TransactionOutput> { match self { - MultiEraOutput::AlonzoCompatible(x) => Some(x), + MultiEraOutput::AlonzoCompatible(x, _) => Some(x), MultiEraOutput::Babbage(_) => None, MultiEraOutput::Byron(_) => None, MultiEraOutput::Conway(_) => None, @@ -91,7 +91,7 @@ impl<'b> MultiEraOutput<'b> { pub fn as_babbage(&self) -> Option<&babbage::MintedTransactionOutput> { match self { - MultiEraOutput::AlonzoCompatible(_) => None, + MultiEraOutput::AlonzoCompatible(..) => None, MultiEraOutput::Babbage(x) => Some(x), MultiEraOutput::Byron(_) => None, MultiEraOutput::Conway(_) => None, @@ -100,7 +100,7 @@ impl<'b> MultiEraOutput<'b> { pub fn as_byron(&self) -> Option<&byron::TxOut> { match self { - MultiEraOutput::AlonzoCompatible(_) => None, + MultiEraOutput::AlonzoCompatible(..) => None, MultiEraOutput::Babbage(_) => None, MultiEraOutput::Byron(x) => Some(x), MultiEraOutput::Conway(_) => None, @@ -109,17 +109,26 @@ impl<'b> MultiEraOutput<'b> { pub fn as_conway(&self) -> Option<&conway::MintedTransactionOutput> { match self { - MultiEraOutput::AlonzoCompatible(_) => None, + MultiEraOutput::AlonzoCompatible(..) => None, MultiEraOutput::Babbage(_) => None, MultiEraOutput::Byron(_) => None, MultiEraOutput::Conway(x) => Some(x), } } + pub fn era(&self) -> Era { + match self { + MultiEraOutput::AlonzoCompatible(_, x) => *x, + MultiEraOutput::Babbage(_) => Era::Babbage, + MultiEraOutput::Conway(_) => Era::Conway, + MultiEraOutput::Byron(_) => Era::Byron, + } + } + pub fn encode(&self) -> Vec { // to_vec is infallible match self { - Self::AlonzoCompatible(x) => minicbor::to_vec(x).unwrap(), + Self::AlonzoCompatible(x, _) => minicbor::to_vec(x).unwrap(), Self::Babbage(x) => minicbor::to_vec(x).unwrap(), Self::Byron(x) => minicbor::to_vec(x).unwrap(), Self::Conway(x) => minicbor::to_vec(x).unwrap(), @@ -136,7 +145,7 @@ impl<'b> MultiEraOutput<'b> { Era::Shelley | Era::Allegra | Era::Mary | Era::Alonzo => { let tx = minicbor::decode(cbor)?; let tx = Box::new(Cow::Owned(tx)); - Ok(Self::AlonzoCompatible(tx)) + Ok(Self::AlonzoCompatible(tx, era)) } Era::Babbage => { let tx = minicbor::decode(cbor)?; @@ -158,7 +167,7 @@ impl<'b> MultiEraOutput<'b> { /// lovelace). pub fn lovelace_amount(&self) -> u64 { match self { - MultiEraOutput::AlonzoCompatible(x) => match x.amount { + MultiEraOutput::AlonzoCompatible(x, _) => match x.amount { alonzo::Value::Coin(c) => c, alonzo::Value::Multiasset(c, _) => c, }, @@ -193,7 +202,7 @@ impl<'b> MultiEraOutput<'b> { /// list. pub fn non_ada_assets(&self) -> Vec { match self { - MultiEraOutput::AlonzoCompatible(x) => match &x.amount { + MultiEraOutput::AlonzoCompatible(x, _) => match &x.amount { alonzo::Value::Coin(_) => vec![], alonzo::Value::Multiasset(_, x) => x .iter() diff --git a/pallas-traverse/src/tx.rs b/pallas-traverse/src/tx.rs index 0f33e21..d5a2a8c 100644 --- a/pallas-traverse/src/tx.rs +++ b/pallas-traverse/src/tx.rs @@ -116,7 +116,7 @@ impl<'b> MultiEraTx<'b> { .transaction_body .outputs .iter() - .map(MultiEraOutput::from_alonzo_compatible) + .map(|x| MultiEraOutput::from_alonzo_compatible(x, self.era())) .collect(), MultiEraTx::Babbage(x) => x .transaction_body @@ -145,7 +145,7 @@ impl<'b> MultiEraTx<'b> { .transaction_body .outputs .get(index) - .map(MultiEraOutput::from_alonzo_compatible), + .map(|x| MultiEraOutput::from_alonzo_compatible(x, self.era())), MultiEraTx::Babbage(x) => x .transaction_body .outputs