diff --git a/pallas-primitives/src/alonzo/model.rs b/pallas-primitives/src/alonzo/model.rs index 3a0eab0..4062af0 100644 --- a/pallas-primitives/src/alonzo/model.rs +++ b/pallas-primitives/src/alonzo/model.rs @@ -282,6 +282,8 @@ pub type RewardAccount = ByteVec; pub type Withdrawals = KeyValuePairs; +pub type RequiredSigners = MaybeIndefArray; + pub type Port = u32; pub type IPv4 = ByteVec; pub type IPv6 = ByteVec; @@ -742,7 +744,7 @@ pub struct TransactionBody { pub collateral: Option>, #[n(14)] - pub required_signers: Option>, + pub required_signers: Option, #[n(15)] pub network_id: Option, diff --git a/pallas-primitives/src/babbage/model.rs b/pallas-primitives/src/babbage/model.rs index 91aba68..32cbb9f 100644 --- a/pallas-primitives/src/babbage/model.rs +++ b/pallas-primitives/src/babbage/model.rs @@ -113,6 +113,10 @@ pub use crate::alonzo::MoveInstantaneousReward; pub use crate::alonzo::RewardAccount; +pub type Withdrawals = KeyValuePairs; + +pub type RequiredSigners = MaybeIndefArray; + pub use crate::alonzo::Port; pub use crate::alonzo::IPv4; diff --git a/pallas-primitives/src/byron/model.rs b/pallas-primitives/src/byron/model.rs index 3e201e6..3253207 100644 --- a/pallas-primitives/src/byron/model.rs +++ b/pallas-primitives/src/byron/model.rs @@ -693,13 +693,15 @@ pub struct BlockHead { pub extra_data: BlockHeadEx, } +pub type Witnesses = MaybeIndefArray; + #[derive(Debug, Encode, Decode)] pub struct TxPayload { #[n(0)] pub transaction: Tx, #[n(1)] - pub witness: MaybeIndefArray, + pub witness: Witnesses, } #[derive(Debug, Encode, Decode, Clone)] @@ -708,7 +710,7 @@ pub struct MintedTxPayload<'b> { pub transaction: KeepRaw<'b, Tx>, #[n(1)] - pub witness: MaybeIndefArray, + pub witness: KeepRaw<'b, Witnesses>, } #[derive(Encode, Decode, Debug)] diff --git a/pallas-traverse/src/block.rs b/pallas-traverse/src/block.rs index bf89c94..f65e0c0 100644 --- a/pallas-traverse/src/block.rs +++ b/pallas-traverse/src/block.rs @@ -13,61 +13,49 @@ impl<'b> MultiEraBlock<'b> { let (_, block): BlockWrapper = minicbor::decode(cbor).map_err(Error::invalid_cbor)?; - Ok(Self::EpochBoundary(Box::new(Cow::Owned(block)))) + Ok(Self::EpochBoundary(Box::new(block))) } pub fn decode_byron(cbor: &'b [u8]) -> Result { let (_, block): BlockWrapper = minicbor::decode(cbor).map_err(Error::invalid_cbor)?; - Ok(Self::Byron(Box::new(Cow::Owned(block)))) + Ok(Self::Byron(Box::new(block))) } pub fn decode_shelley(cbor: &'b [u8]) -> Result { let (_, block): BlockWrapper = minicbor::decode(cbor).map_err(Error::invalid_cbor)?; - Ok(Self::AlonzoCompatible( - Box::new(Cow::Owned(block)), - Era::Shelley, - )) + Ok(Self::AlonzoCompatible(Box::new(block), Era::Shelley)) } pub fn decode_allegra(cbor: &'b [u8]) -> Result { let (_, block): BlockWrapper = minicbor::decode(cbor).map_err(Error::invalid_cbor)?; - Ok(Self::AlonzoCompatible( - Box::new(Cow::Owned(block)), - Era::Allegra, - )) + Ok(Self::AlonzoCompatible(Box::new(block), Era::Allegra)) } pub fn decode_mary(cbor: &'b [u8]) -> Result { let (_, block): BlockWrapper = minicbor::decode(cbor).map_err(Error::invalid_cbor)?; - Ok(Self::AlonzoCompatible( - Box::new(Cow::Owned(block)), - Era::Mary, - )) + Ok(Self::AlonzoCompatible(Box::new(block), Era::Mary)) } pub fn decode_alonzo(cbor: &'b [u8]) -> Result { let (_, block): BlockWrapper = minicbor::decode(cbor).map_err(Error::invalid_cbor)?; - Ok(Self::AlonzoCompatible( - Box::new(Cow::Owned(block)), - Era::Alonzo, - )) + Ok(Self::AlonzoCompatible(Box::new(block), Era::Alonzo)) } pub fn decode_babbage(cbor: &'b [u8]) -> Result { let (_, block): BlockWrapper = minicbor::decode(cbor).map_err(Error::invalid_cbor)?; - Ok(Self::Babbage(Box::new(Cow::Owned(block)))) + Ok(Self::Babbage(Box::new(block))) } pub fn decode(cbor: &'b [u8]) -> Result, Error> { diff --git a/pallas-traverse/src/header.rs b/pallas-traverse/src/header.rs index 85b85de..a64c62b 100644 --- a/pallas-traverse/src/header.rs +++ b/pallas-traverse/src/header.rs @@ -1,8 +1,9 @@ use std::borrow::Cow; +use std::ops::Deref; use pallas_codec::minicbor; use pallas_crypto::hash::{Hash, Hasher}; -use pallas_primitives::ToHash; +use pallas_primitives::{alonzo, babbage, byron, ToHash}; use crate::Era::Byron; use crate::{Error, MultiEraHeader}; @@ -97,4 +98,32 @@ impl<'b> MultiEraHeader<'b> { MultiEraHeader::Byron(_) => Err(Error::InvalidEra(Byron)), } } + + pub fn as_eb(&self) -> Option<&byron::EbbHead> { + match self { + MultiEraHeader::EpochBoundary(x) => Some(x.deref().deref()), + _ => None, + } + } + + pub fn as_byron(&self) -> Option<&byron::BlockHead> { + match self { + MultiEraHeader::Byron(x) => Some(x.deref().deref()), + _ => None, + } + } + + pub fn as_alonzo(&self) -> Option<&alonzo::Header> { + match self { + MultiEraHeader::AlonzoCompatible(x) => Some(x.deref().deref()), + _ => None, + } + } + + pub fn as_babbage(&self) -> Option<&babbage::Header> { + match self { + MultiEraHeader::Babbage(x) => Some(x.deref().deref()), + _ => None, + } + } } diff --git a/pallas-traverse/src/lib.rs b/pallas-traverse/src/lib.rs index 33fab3f..fa213ee 100644 --- a/pallas-traverse/src/lib.rs +++ b/pallas-traverse/src/lib.rs @@ -18,9 +18,11 @@ pub mod meta; pub mod mint; pub mod output; pub mod probe; +pub mod signers; mod support; pub mod tx; pub mod withdrawals; +pub mod witnesses; #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] #[non_exhaustive] @@ -56,10 +58,10 @@ pub enum MultiEraHeader<'b> { #[derive(Debug, Clone)] #[non_exhaustive] pub enum MultiEraBlock<'b> { - EpochBoundary(Box>>), - AlonzoCompatible(Box>>, Era), - Babbage(Box>>), - Byron(Box>>), + EpochBoundary(Box>), + AlonzoCompatible(Box>, Era), + Babbage(Box>), + Byron(Box>), } #[derive(Debug, Clone)] @@ -97,7 +99,7 @@ pub enum MultiEraCert<'b> { pub enum MultiEraMeta<'b> { NotApplicable, Empty, - AlonzoCompatible(Cow<'b, alonzo::Metadata>), + AlonzoCompatible(&'b alonzo::Metadata), } #[derive(Debug, Clone)] @@ -105,7 +107,7 @@ pub enum MultiEraMeta<'b> { pub enum MultiEraMint<'b> { NotApplicable, Empty, - AlonzoCompatible(Cow<'b, alonzo::Mint>), + AlonzoCompatible(&'b alonzo::Mint), } #[derive(Debug, Clone)] @@ -113,7 +115,23 @@ pub enum MultiEraMint<'b> { pub enum MultiEraWithdrawals<'b> { NotApplicable, Empty, - AlonzoCompatible(Cow<'b, alonzo::Withdrawals>), + AlonzoCompatible(&'b alonzo::Withdrawals), +} + +#[derive(Debug, Clone)] +#[non_exhaustive] +pub enum MultiEraSigners<'b> { + NotApplicable, + Empty, + AlonzoCompatible(&'b alonzo::RequiredSigners), +} + +#[derive(Debug, Clone)] +#[non_exhaustive] +pub enum MultiEraWitnesses<'b> { + Byron(&'b KeepRaw<'b, byron::Witnesses>), + AlonzoCompatible(&'b KeepRaw<'b, alonzo::TransactionWitnessSet>), + Babbage(&'b KeepRaw<'b, babbage::TransactionWitnessSet>), } #[derive(Debug, Clone)] diff --git a/pallas-traverse/src/meta.rs b/pallas-traverse/src/meta.rs index e87a423..6537e1c 100644 --- a/pallas-traverse/src/meta.rs +++ b/pallas-traverse/src/meta.rs @@ -34,12 +34,9 @@ impl<'b> MultiEraMeta<'b> { T: FromIterator<(&'a alonzo::MetadatumLabel, &'a alonzo::Metadatum)>, { match self { - MultiEraMeta::NotApplicable => T::from_iter(std::iter::empty()), - MultiEraMeta::Empty => T::from_iter(std::iter::empty()), - MultiEraMeta::AlonzoCompatible(x) => { - let iter = x.iter().map(|(k, v)| (k, v)); - T::from_iter(iter) - } + MultiEraMeta::NotApplicable => std::iter::empty().collect(), + MultiEraMeta::Empty => std::iter::empty().collect(), + MultiEraMeta::AlonzoCompatible(x) => x.iter().map(|(k, v)| (k, v)).collect(), } } } diff --git a/pallas-traverse/src/signers.rs b/pallas-traverse/src/signers.rs new file mode 100644 index 0000000..c691d4a --- /dev/null +++ b/pallas-traverse/src/signers.rs @@ -0,0 +1,37 @@ +use pallas_crypto::hash::Hash; +use pallas_primitives::alonzo; + +use crate::MultiEraSigners; + +impl Default for MultiEraSigners<'_> { + fn default() -> Self { + Self::Empty + } +} + +impl<'b> MultiEraSigners<'b> { + pub fn as_alonzo(&self) -> Option<&alonzo::RequiredSigners> { + match self { + Self::AlonzoCompatible(x) => Some(x), + _ => None, + } + } + + pub fn is_empty(&self) -> bool { + match self { + Self::AlonzoCompatible(x) => x.is_empty(), + _ => true, + } + } + + pub fn collect<'a, T>(&'a self) -> T + where + T: FromIterator<&'a Hash<28>>, + { + match self { + Self::NotApplicable => std::iter::empty().collect(), + Self::Empty => std::iter::empty().collect(), + Self::AlonzoCompatible(x) => x.iter().collect(), + } + } +} diff --git a/pallas-traverse/src/tx.rs b/pallas-traverse/src/tx.rs index 20e4dc0..422ed20 100644 --- a/pallas-traverse/src/tx.rs +++ b/pallas-traverse/src/tx.rs @@ -7,8 +7,8 @@ use pallas_primitives::{ use std::{borrow::Cow, ops::Deref}; use crate::{ - Era, MultiEraCert, MultiEraInput, MultiEraMeta, MultiEraMint, MultiEraOutput, MultiEraTx, - MultiEraWithdrawals, + Era, MultiEraCert, MultiEraInput, MultiEraMeta, MultiEraMint, MultiEraOutput, MultiEraSigners, + MultiEraTx, MultiEraWithdrawals, MultiEraWitnesses, }; impl<'b> MultiEraTx<'b> { @@ -160,13 +160,13 @@ impl<'b> MultiEraTx<'b> { .transaction_body .mint .as_ref() - .map(|c| MultiEraMint::AlonzoCompatible(Cow::Borrowed(c))) + .map(MultiEraMint::AlonzoCompatible) .unwrap_or_default(), MultiEraTx::Babbage(x) => x .transaction_body .mint .as_ref() - .map(|c| MultiEraMint::AlonzoCompatible(Cow::Borrowed(c))) + .map(MultiEraMint::AlonzoCompatible) .unwrap_or_default(), MultiEraTx::Byron(_) => MultiEraMint::NotApplicable, } @@ -192,14 +192,14 @@ impl<'b> MultiEraTx<'b> { } } - pub fn withdrawals(&'b self) -> MultiEraWithdrawals<'b> { + pub fn withdrawals(&self) -> MultiEraWithdrawals { match self { MultiEraTx::AlonzoCompatible(x, _) => match &x.transaction_body.withdrawals { - Some(x) => MultiEraWithdrawals::AlonzoCompatible(Cow::Borrowed(x)), + Some(x) => MultiEraWithdrawals::AlonzoCompatible(x), None => MultiEraWithdrawals::Empty, }, MultiEraTx::Babbage(x) => match &x.transaction_body.withdrawals { - Some(x) => MultiEraWithdrawals::AlonzoCompatible(Cow::Borrowed(x)), + Some(x) => MultiEraWithdrawals::AlonzoCompatible(x), None => MultiEraWithdrawals::Empty, }, MultiEraTx::Byron(_) => MultiEraWithdrawals::NotApplicable, @@ -214,23 +214,51 @@ impl<'b> MultiEraTx<'b> { } } - pub fn metadata(&'b self) -> MultiEraMeta<'b> { + pub fn metadata(&self) -> MultiEraMeta { match self.aux_data() { Some(x) => match x.deref() { - AuxiliaryData::Shelley(x) => MultiEraMeta::AlonzoCompatible(Cow::Borrowed(x)), + AuxiliaryData::Shelley(x) => MultiEraMeta::AlonzoCompatible(x), AuxiliaryData::ShelleyMa(x) => { - MultiEraMeta::AlonzoCompatible(Cow::Borrowed(&x.transaction_metadata)) + MultiEraMeta::AlonzoCompatible(&x.transaction_metadata) } AuxiliaryData::PostAlonzo(x) => x .metadata .as_ref() - .map(|x| MultiEraMeta::AlonzoCompatible(Cow::Borrowed(x))) + .map(MultiEraMeta::AlonzoCompatible) .unwrap_or_default(), }, None => MultiEraMeta::Empty, } } + pub fn required_signers(&self) -> MultiEraSigners { + match self { + MultiEraTx::AlonzoCompatible(x, _) => x + .transaction_body + .required_signers + .as_ref() + .map(MultiEraSigners::AlonzoCompatible) + .unwrap_or_default(), + MultiEraTx::Babbage(x) => x + .transaction_body + .required_signers + .as_ref() + .map(MultiEraSigners::AlonzoCompatible) + .unwrap_or_default(), + MultiEraTx::Byron(_) => MultiEraSigners::NotApplicable, + } + } + + pub fn witnesses(&self) -> MultiEraWitnesses { + match self { + MultiEraTx::AlonzoCompatible(x, _) => { + MultiEraWitnesses::AlonzoCompatible(&x.transaction_witness_set) + } + MultiEraTx::Babbage(x) => MultiEraWitnesses::Babbage(&x.transaction_witness_set), + MultiEraTx::Byron(x) => MultiEraWitnesses::Byron(&x.witness), + } + } + pub fn is_valid(&self) -> bool { match self { MultiEraTx::AlonzoCompatible(x, _) => x.success, diff --git a/pallas-traverse/src/withdrawals.rs b/pallas-traverse/src/withdrawals.rs index 4afbee1..289ece3 100644 --- a/pallas-traverse/src/withdrawals.rs +++ b/pallas-traverse/src/withdrawals.rs @@ -22,11 +22,10 @@ impl<'b> MultiEraWithdrawals<'b> { T: FromIterator<(&'a [u8], u64)>, { match self { - MultiEraWithdrawals::NotApplicable => T::from_iter(std::iter::empty()), - MultiEraWithdrawals::Empty => T::from_iter(std::iter::empty()), + MultiEraWithdrawals::NotApplicable => std::iter::empty().collect(), + MultiEraWithdrawals::Empty => std::iter::empty().collect(), MultiEraWithdrawals::AlonzoCompatible(x) => { - let iter = x.iter().map(|(k, v)| (k.as_slice(), v.into())); - T::from_iter(iter) + x.iter().map(|(k, v)| (k.as_slice(), v.into())).collect() } } } diff --git a/pallas-traverse/src/witnesses.rs b/pallas-traverse/src/witnesses.rs new file mode 100644 index 0000000..dbc0da7 --- /dev/null +++ b/pallas-traverse/src/witnesses.rs @@ -0,0 +1,27 @@ +use pallas_primitives::{alonzo, babbage}; + +use crate::MultiEraWitnesses; + +impl<'b> MultiEraWitnesses<'b> { + pub fn as_alonzo(&self) -> Option<&alonzo::TransactionWitnessSet> { + match self { + Self::AlonzoCompatible(x) => Some(x), + _ => None, + } + } + + pub fn as_babbage(&self) -> Option<&babbage::TransactionWitnessSet> { + match self { + Self::Babbage(x) => Some(x), + _ => None, + } + } + + pub fn cbor(&self) -> &[u8] { + match self { + MultiEraWitnesses::AlonzoCompatible(x) => x.raw_cbor(), + MultiEraWitnesses::Babbage(x) => x.raw_cbor(), + MultiEraWitnesses::Byron(x) => x.raw_cbor(), + } + } +}