From 85cf02dec42169a66f011a3e0bd46866b1be1d41 Mon Sep 17 00:00:00 2001 From: Santiago Carmuega Date: Tue, 13 Sep 2022 07:52:35 -0300 Subject: [PATCH] feat(traverse): Provide access to original Datum hash (#189) --- pallas-primitives/src/alonzo/model.rs | 48 +++++++- pallas-primitives/src/babbage/model.rs | 54 ++++++++- pallas-traverse/src/hashes.rs | 162 +++++++++++++++---------- pallas-traverse/src/header.rs | 11 +- pallas-traverse/src/lib.rs | 16 +-- pallas-traverse/src/support.rs | 2 +- pallas-traverse/src/tx.rs | 18 +-- pallas-traverse/src/witnesses.rs | 145 +++++++++++++--------- test_data/babbage1.tx | 1 + 9 files changed, 299 insertions(+), 158 deletions(-) create mode 100644 test_data/babbage1.tx diff --git a/pallas-primitives/src/alonzo/model.rs b/pallas-primitives/src/alonzo/model.rs index 8c70f15..3fe68e6 100644 --- a/pallas-primitives/src/alonzo/model.rs +++ b/pallas-primitives/src/alonzo/model.rs @@ -1159,7 +1159,7 @@ pub struct BootstrapWitness { #[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Clone)] #[cbor(map)] -pub struct TransactionWitnessSet { +pub struct WitnessSet { #[n(0)] pub vkeywitness: Option>, @@ -1179,6 +1179,43 @@ pub struct TransactionWitnessSet { pub redeemer: Option>, } +#[derive(Encode, Decode, Debug, PartialEq, Clone)] +#[cbor(map)] +pub struct MintedWitnessSet<'b> { + #[n(0)] + pub vkeywitness: Option>, + + #[n(1)] + pub native_script: Option>, + + #[n(2)] + pub bootstrap_witness: Option>, + + #[n(3)] + pub plutus_script: Option>, + + #[b(4)] + pub plutus_data: Option>>, + + #[n(5)] + pub redeemer: Option>, +} + +impl<'b> From> for WitnessSet { + fn from(x: MintedWitnessSet<'b>) -> Self { + WitnessSet { + vkeywitness: x.vkeywitness, + native_script: x.native_script, + bootstrap_witness: x.bootstrap_witness, + plutus_script: x.plutus_script, + plutus_data: x + .plutus_data + .map(|x| x.into_iter().map(|x| x.unwrap()).collect()), + redeemer: x.redeemer, + } + } +} + #[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Clone)] #[cbor(map)] pub struct PostAlonzoAuxiliaryData { @@ -1328,7 +1365,7 @@ pub struct Block { pub transaction_bodies: Vec, #[n(2)] - pub transaction_witness_sets: Vec, + pub transaction_witness_sets: Vec, #[n(3)] pub auxiliary_data_set: BTreeMap, @@ -1351,7 +1388,7 @@ pub struct MintedBlock<'b> { pub transaction_bodies: MaybeIndefArray>, #[n(2)] - pub transaction_witness_sets: MaybeIndefArray>, + pub transaction_witness_sets: MaybeIndefArray>>, #[n(3)] pub auxiliary_data_set: KeyValuePairs>, @@ -1375,6 +1412,7 @@ impl<'b> From> for Block { .to_vec() .into_iter() .map(|x| x.unwrap()) + .map(|x| WitnessSet::from(x)) .collect(), auxiliary_data_set: x .auxiliary_data_set @@ -1393,7 +1431,7 @@ pub struct Tx { pub transaction_body: TransactionBody, #[n(1)] - pub transaction_witness_set: TransactionWitnessSet, + pub transaction_witness_set: WitnessSet, #[n(2)] pub success: bool, @@ -1408,7 +1446,7 @@ pub struct MintedTx<'b> { pub transaction_body: KeepRaw<'b, TransactionBody>, #[n(1)] - pub transaction_witness_set: KeepRaw<'b, TransactionWitnessSet>, + pub transaction_witness_set: KeepRaw<'b, MintedWitnessSet<'b>>, #[n(2)] pub success: bool, diff --git a/pallas-primitives/src/babbage/model.rs b/pallas-primitives/src/babbage/model.rs index f9eeac3..268231f 100644 --- a/pallas-primitives/src/babbage/model.rs +++ b/pallas-primitives/src/babbage/model.rs @@ -375,7 +375,7 @@ pub use crate::alonzo::BootstrapWitness; #[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Clone)] #[cbor(map)] -pub struct TransactionWitnessSet { +pub struct WitnessSet { #[n(0)] pub vkeywitness: Option>, @@ -398,6 +398,47 @@ pub struct TransactionWitnessSet { pub plutus_v2_script: Option>, } +#[derive(Encode, Decode, Debug, PartialEq, Clone)] +#[cbor(map)] +pub struct MintedWitnessSet<'b> { + #[n(0)] + pub vkeywitness: Option>, + + #[n(1)] + pub native_script: Option>, + + #[n(2)] + pub bootstrap_witness: Option>, + + #[n(3)] + pub plutus_v1_script: Option>, + + #[b(4)] + pub plutus_data: Option>>, + + #[n(5)] + pub redeemer: Option>, + + #[n(6)] + pub plutus_v2_script: Option>, +} + +impl<'b> From> for WitnessSet { + fn from(x: MintedWitnessSet<'b>) -> Self { + WitnessSet { + vkeywitness: x.vkeywitness, + native_script: x.native_script, + bootstrap_witness: x.bootstrap_witness, + plutus_v1_script: x.plutus_v1_script, + plutus_data: x + .plutus_data + .map(|x| x.into_iter().map(|x| x.unwrap()).collect()), + redeemer: x.redeemer, + plutus_v2_script: x.plutus_v2_script, + } + } +} + #[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Clone)] #[cbor(map)] pub struct PostAlonzoAuxiliaryData { @@ -521,7 +562,7 @@ pub struct Block { pub transaction_bodies: Vec, #[n(2)] - pub transaction_witness_sets: Vec, + pub transaction_witness_sets: Vec, #[n(3)] pub auxiliary_data_set: BTreeMap, @@ -544,7 +585,7 @@ pub struct MintedBlock<'b> { pub transaction_bodies: MaybeIndefArray>, #[n(2)] - pub transaction_witness_sets: MaybeIndefArray>, + pub transaction_witness_sets: MaybeIndefArray>>, #[n(3)] pub auxiliary_data_set: KeyValuePairs>, @@ -568,6 +609,7 @@ impl<'b> From> for Block { .to_vec() .into_iter() .map(|x| x.unwrap()) + .map(|x| WitnessSet::from(x)) .collect(), auxiliary_data_set: x .auxiliary_data_set @@ -586,7 +628,7 @@ pub struct Tx { pub transaction_body: TransactionBody, #[n(1)] - pub transaction_witness_set: TransactionWitnessSet, + pub transaction_witness_set: WitnessSet, #[n(2)] pub success: bool, @@ -601,7 +643,7 @@ pub struct MintedTx<'b> { pub transaction_body: KeepRaw<'b, TransactionBody>, #[n(1)] - pub transaction_witness_set: KeepRaw<'b, TransactionWitnessSet>, + pub transaction_witness_set: KeepRaw<'b, MintedWitnessSet<'b>>, #[n(2)] pub success: bool, @@ -614,7 +656,7 @@ impl<'b> From> for Tx { fn from(x: MintedTx<'b>) -> Self { Tx { transaction_body: x.transaction_body.unwrap(), - transaction_witness_set: x.transaction_witness_set.unwrap(), + transaction_witness_set: x.transaction_witness_set.unwrap().into(), success: x.success, auxiliary_data: x.auxiliary_data.map(|x| x.unwrap()), } diff --git a/pallas-traverse/src/hashes.rs b/pallas-traverse/src/hashes.rs index e608b54..ce676e2 100644 --- a/pallas-traverse/src/hashes.rs +++ b/pallas-traverse/src/hashes.rs @@ -1,137 +1,152 @@ -use crate::ToHash; +use crate::{ComputeHash, OriginalHash}; use pallas_codec::utils::KeepRaw; use pallas_crypto::hash::{Hash, Hasher}; use pallas_primitives::{alonzo, babbage, byron}; -impl ToHash<32> for byron::EbbHead { - fn to_hash(&self) -> Hash<32> { +impl ComputeHash<32> for byron::EbbHead { + fn compute_hash(&self) -> Hash<32> { // hash expects to have a prefix for the type of block Hasher::<256>::hash_cbor(&(0, self)) } } -impl ToHash<32> for KeepRaw<'_, byron::EbbHead> { - fn to_hash(&self) -> Hash<32> { +impl OriginalHash<32> for KeepRaw<'_, byron::EbbHead> { + fn original_hash(&self) -> Hash<32> { // hash expects to have a prefix for the type of block Hasher::<256>::hash_cbor(&(0, self)) } } -impl ToHash<32> for byron::BlockHead { - fn to_hash(&self) -> Hash<32> { +impl ComputeHash<32> for byron::BlockHead { + fn compute_hash(&self) -> Hash<32> { // hash expects to have a prefix for the type of block Hasher::<256>::hash_cbor(&(1, self)) } } -impl ToHash<32> for KeepRaw<'_, byron::BlockHead> { - fn to_hash(&self) -> Hash<32> { +impl OriginalHash<32> for KeepRaw<'_, byron::BlockHead> { + fn original_hash(&self) -> Hash<32> { // hash expects to have a prefix for the type of block Hasher::<256>::hash_cbor(&(1, self)) } } -impl ToHash<32> for byron::Tx { - fn to_hash(&self) -> Hash<32> { +impl ComputeHash<32> for byron::Tx { + fn compute_hash(&self) -> Hash<32> { Hasher::<256>::hash_cbor(self) } } -impl ToHash<32> for KeepRaw<'_, byron::Tx> { - fn to_hash(&self) -> Hash<32> { +impl OriginalHash<32> for KeepRaw<'_, byron::Tx> { + fn original_hash(&self) -> Hash<32> { Hasher::<256>::hash(self.raw_cbor()) } } -impl ToHash<32> for alonzo::Header { - fn to_hash(&self) -> pallas_crypto::hash::Hash<32> { +impl ComputeHash<32> for alonzo::Header { + fn compute_hash(&self) -> pallas_crypto::hash::Hash<32> { Hasher::<256>::hash_cbor(self) } } -impl ToHash<32> for alonzo::AuxiliaryData { - fn to_hash(&self) -> pallas_crypto::hash::Hash<32> { +impl OriginalHash<32> for KeepRaw<'_, alonzo::Header> { + fn original_hash(&self) -> pallas_crypto::hash::Hash<32> { + Hasher::<256>::hash(self.raw_cbor()) + } +} + +impl ComputeHash<32> for alonzo::AuxiliaryData { + fn compute_hash(&self) -> pallas_crypto::hash::Hash<32> { Hasher::<256>::hash_cbor(self) } } -impl ToHash<28> for alonzo::NativeScript { - fn to_hash(&self) -> Hash<28> { +impl ComputeHash<28> for alonzo::NativeScript { + fn compute_hash(&self) -> Hash<28> { Hasher::<224>::hash_tagged_cbor(self, 0) } } -impl ToHash<28> for alonzo::PlutusScript { - fn to_hash(&self) -> Hash<28> { +impl ComputeHash<28> for alonzo::PlutusScript { + fn compute_hash(&self) -> Hash<28> { Hasher::<224>::hash_tagged(&self.0, 1) } } -impl ToHash<32> for alonzo::PlutusData { - fn to_hash(&self) -> Hash<32> { +impl ComputeHash<32> for alonzo::PlutusData { + fn compute_hash(&self) -> Hash<32> { Hasher::<256>::hash_cbor(self) } } -impl ToHash<32> for alonzo::TransactionBody { - fn to_hash(&self) -> Hash<32> { +impl OriginalHash<32> for KeepRaw<'_, alonzo::PlutusData> { + fn original_hash(&self) -> Hash<32> { + Hasher::<256>::hash(&self.raw_cbor()) + } +} + +impl ComputeHash<32> for alonzo::TransactionBody { + fn compute_hash(&self) -> Hash<32> { Hasher::<256>::hash_cbor(self) } } -impl ToHash<32> for KeepRaw<'_, alonzo::TransactionBody> { - fn to_hash(&self) -> pallas_crypto::hash::Hash<32> { +impl OriginalHash<32> for KeepRaw<'_, alonzo::TransactionBody> { + fn original_hash(&self) -> pallas_crypto::hash::Hash<32> { Hasher::<256>::hash(self.raw_cbor()) } } -impl ToHash<32> for babbage::Header { - fn to_hash(&self) -> pallas_crypto::hash::Hash<32> { +impl ComputeHash<32> for babbage::Header { + fn compute_hash(&self) -> pallas_crypto::hash::Hash<32> { Hasher::<256>::hash_cbor(self) } } -impl ToHash<28> for babbage::PlutusV2Script { - fn to_hash(&self) -> Hash<28> { +impl OriginalHash<32> for KeepRaw<'_, babbage::Header> { + fn original_hash(&self) -> pallas_crypto::hash::Hash<32> { + Hasher::<256>::hash(self.raw_cbor()) + } +} + +impl ComputeHash<28> for babbage::PlutusV2Script { + fn compute_hash(&self) -> Hash<28> { Hasher::<224>::hash_tagged(&self.0, 2) } } -impl ToHash<32> for babbage::TransactionBody { - fn to_hash(&self) -> Hash<32> { +impl ComputeHash<32> for babbage::TransactionBody { + fn compute_hash(&self) -> Hash<32> { Hasher::<256>::hash_cbor(self) } } -impl ToHash<32> for KeepRaw<'_, babbage::TransactionBody> { - fn to_hash(&self) -> pallas_crypto::hash::Hash<32> { +impl OriginalHash<32> for KeepRaw<'_, babbage::TransactionBody> { + fn original_hash(&self) -> pallas_crypto::hash::Hash<32> { Hasher::<256>::hash(self.raw_cbor()) } } -impl ToHash<32> for babbage::DatumOption { - fn to_hash(&self) -> Hash<32> { +impl ComputeHash<32> for babbage::DatumOption { + fn compute_hash(&self) -> Hash<32> { match self { babbage::DatumOption::Hash(hash) => *hash, - babbage::DatumOption::Data(data) => data.to_hash(), + babbage::DatumOption::Data(data) => data.compute_hash(), } } } #[cfg(test)] mod tests { - use crate::{MultiEraTx, Era}; + use crate::{Era, MultiEraTx}; - use super::ToHash; - use pallas_codec::{minicbor, utils::Bytes}; + use super::{ComputeHash, OriginalHash}; use pallas_codec::utils::Int; + use pallas_codec::{minicbor, utils::Bytes}; use pallas_crypto::hash::Hash; use pallas_primitives::{alonzo, babbage, byron}; use std::str::FromStr; - const KNOWN_HASH: &'static str = - "5c196e7394ace0449ba5a51c919369699b13896e97432894b4f0354dce8670b6"; - #[test] fn byron_transaction_hash_works() { type BlockWrapper<'b> = (u16, byron::MintedBlock<'b>); @@ -144,9 +159,12 @@ mod tests { let (_, block_model): BlockWrapper = minicbor::decode(&block_bytes[..]) .expect(&format!("error decoding cbor for file {}", block_idx)); - let computed_hash = block_model.header.to_hash(); + let computed_hash = block_model.header.original_hash(); - assert_eq!(hex::encode(computed_hash), KNOWN_HASH) + assert_eq!( + hex::encode(computed_hash), + "5c196e7394ace0449ba5a51c919369699b13896e97432894b4f0354dce8670b6" + ) } #[test] @@ -170,9 +188,9 @@ mod tests { ]; for (tx_idx, tx) in block_model.transaction_bodies.iter().enumerate() { - let computed_hash = tx.to_hash(); - let known_hash = valid_hashes[tx_idx]; - assert_eq!(hex::encode(computed_hash), known_hash) + let original_hash = tx.original_hash(); + let expected_hash = valid_hashes[tx_idx]; + assert_eq!(hex::encode(original_hash), expected_hash) } } @@ -191,9 +209,9 @@ mod tests { let valid_hashes = vec!["3fad302595665b004971a6b76909854a39a0a7ecdbff3692f37b77ae37dbe882"]; for (tx_idx, tx) in block_model.transaction_bodies.iter().enumerate() { - let computed_hash = tx.to_hash(); - let known_hash = valid_hashes[tx_idx]; - assert_eq!(hex::encode(computed_hash), known_hash) + let original_hash = tx.original_hash(); + let expected_hash = valid_hashes[tx_idx]; + assert_eq!(hex::encode(original_hash), expected_hash) } } @@ -212,7 +230,7 @@ mod tests { let cardano_cli_output = "d6a8ced01ecdfbb26c90850010a06fbc20a7c23632fc92f531667f36"; assert_eq!( - ns.to_hash(), + ns.compute_hash(), Hash::<28>::from_str(cardano_cli_output).unwrap() ) } @@ -253,7 +271,7 @@ mod tests { let cardano_cli_output = "d9bc0eb6ac664286155f70d720cafd2af16277fbd9014a930997431a2ffbe554"; assert_eq!( - pd.to_hash(), + pd.compute_hash(), Hash::<32>::from_str(cardano_cli_output).unwrap() ) } @@ -264,7 +282,7 @@ mod tests { let bytecode = hex::decode(bytecode_hex).unwrap(); let script = alonzo::PlutusScript(Bytes::from(bytecode)); - let generated = script.to_hash().to_string(); + let generated = script.compute_hash().to_string(); assert_eq!( generated, @@ -280,7 +298,7 @@ mod tests { let bytecode = hex::decode(bytecode_hex).unwrap(); let script = babbage::PlutusV2Script(Bytes::from(bytecode)); - let generated = script.to_hash().to_string(); + let generated = script.compute_hash().to_string(); assert_eq!( generated, @@ -296,15 +314,37 @@ mod tests { let bytecode = hex::decode(tx_bytecode_hex).unwrap(); let tx = MultiEraTx::decode(Era::Babbage, &bytecode).unwrap(); - let wits = tx.witnesses(); - - let script = wits.plutus_v1_script().unwrap().get(0).unwrap(); - - let generated = script.to_hash().to_string(); + let generated = tx + .plutus_v1_scripts() + .get(0) + .unwrap() + .compute_hash() + .to_string(); assert_eq!( generated, "62bdc3d04d04376d516d31664944b25ce3affa76d17f8b5e1279b49d" ); } + + #[test] + fn test_datum_hash_respects_original_cbor() { + let expected = [ + "54ad3c112d58e8946480e21d6a35b2a215d1a9a8f540c13714ded86e4b0b6aea", + "831a557bc2948e1b8c9f5e8e594d62299abff4eb1a11dc19da38bfaf9f2da407", + "923918e403bf43c34b4ef6b48eb2ee04babed17320d8d1b9ff9ad086e86f44ec", + "b0ea85f16a443da7f60704a427923ae1d89a7dc2d6621d805d9dd441431ed700", + "c695868b4bfbf4c95714e707c69da1823bcf8cfc7c4b14b92c3645d4e1943be3", + "ed33125018c5cbc9ae1b242a3ff8f3db2e108e4a63866d0b5238a34502c723ed", + ]; + + let tx_hex = include_str!("../../test_data/babbage1.tx"); + let tx_bytes = hex::decode(tx_hex).unwrap(); + let tx = MultiEraTx::decode(Era::Babbage, &tx_bytes).unwrap(); + let data = tx.plutus_data(); + + for (datum, expected_hash) in data.iter().zip(expected) { + assert_eq!(datum.original_hash().to_string(), expected_hash); + } + } } diff --git a/pallas-traverse/src/header.rs b/pallas-traverse/src/header.rs index cd3bce4..9c3857d 100644 --- a/pallas-traverse/src/header.rs +++ b/pallas-traverse/src/header.rs @@ -5,8 +5,7 @@ use pallas_codec::minicbor; use pallas_crypto::hash::{Hash, Hasher}; use pallas_primitives::{alonzo, babbage, byron}; -use crate::time; -use crate::{Era, Error, MultiEraHeader, ToHash}; +use crate::{time, Era, Error, MultiEraHeader, OriginalHash}; impl<'b> MultiEraHeader<'b> { pub fn decode(tag: u8, subtag: Option, cbor: &'b [u8]) -> Result { @@ -71,10 +70,10 @@ impl<'b> MultiEraHeader<'b> { pub fn hash(&self) -> Hash<32> { match self { - MultiEraHeader::EpochBoundary(x) => x.to_hash(), - MultiEraHeader::AlonzoCompatible(x) => x.to_hash(), - MultiEraHeader::Babbage(x) => x.to_hash(), - MultiEraHeader::Byron(x) => x.to_hash(), + MultiEraHeader::EpochBoundary(x) => x.original_hash(), + MultiEraHeader::AlonzoCompatible(x) => x.original_hash(), + MultiEraHeader::Babbage(x) => x.original_hash(), + MultiEraHeader::Byron(x) => x.original_hash(), } } diff --git a/pallas-traverse/src/lib.rs b/pallas-traverse/src/lib.rs index 7c9f1e0..cc356df 100644 --- a/pallas-traverse/src/lib.rs +++ b/pallas-traverse/src/lib.rs @@ -129,14 +129,6 @@ pub enum MultiEraSigners<'b> { 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)] pub struct OutputRef(Hash<32>, u64); @@ -172,6 +164,10 @@ impl Error { } } -pub trait ToHash { - fn to_hash(&self) -> pallas_crypto::hash::Hash; +pub trait ComputeHash { + fn compute_hash(&self) -> pallas_crypto::hash::Hash; +} + +pub trait OriginalHash { + fn original_hash(&self) -> pallas_crypto::hash::Hash; } diff --git a/pallas-traverse/src/support.rs b/pallas-traverse/src/support.rs index 7907957..f2412d0 100644 --- a/pallas-traverse/src/support.rs +++ b/pallas-traverse/src/support.rs @@ -7,7 +7,7 @@ macro_rules! clone_tx_fn { fn $fn_name<'b>(block: &'b $era::MintedBlock, index: usize) -> Option<$era::MintedTx<'b>> { let transaction_body = block.transaction_bodies.get(index).cloned()?; - let transaction_witness_set = block.transaction_witness_sets.get(index).cloned()?; + let transaction_witness_set = block.transaction_witness_sets.get(index)?.clone(); let success = !block .invalid_transactions diff --git a/pallas-traverse/src/tx.rs b/pallas-traverse/src/tx.rs index 5b4a1bf..a790459 100644 --- a/pallas-traverse/src/tx.rs +++ b/pallas-traverse/src/tx.rs @@ -6,7 +6,7 @@ use pallas_primitives::{alonzo, babbage, byron}; use crate::{ Era, MultiEraCert, MultiEraInput, MultiEraMeta, MultiEraMint, MultiEraOutput, MultiEraSigners, - MultiEraTx, MultiEraWithdrawals, MultiEraWitnesses, ToHash, + MultiEraTx, MultiEraWithdrawals, OriginalHash, }; impl<'b> MultiEraTx<'b> { @@ -61,9 +61,9 @@ impl<'b> MultiEraTx<'b> { pub fn hash(&self) -> Hash<32> { match self { - MultiEraTx::AlonzoCompatible(x, _) => x.transaction_body.to_hash(), - MultiEraTx::Babbage(x) => x.transaction_body.to_hash(), - MultiEraTx::Byron(x) => x.transaction.to_hash(), + MultiEraTx::AlonzoCompatible(x, _) => x.transaction_body.original_hash(), + MultiEraTx::Babbage(x) => x.transaction_body.original_hash(), + MultiEraTx::Byron(x) => x.transaction.original_hash(), } } @@ -341,16 +341,6 @@ impl<'b> MultiEraTx<'b> { } } - 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/witnesses.rs b/pallas-traverse/src/witnesses.rs index 13da114..6f1dd1c 100644 --- a/pallas-traverse/src/witnesses.rs +++ b/pallas-traverse/src/witnesses.rs @@ -1,85 +1,120 @@ +use pallas_codec::utils::KeepRaw; use pallas_primitives::{ alonzo::{self, BootstrapWitness, NativeScript, PlutusData, Redeemer, VKeyWitness}, - babbage::{self, PlutusV2Script}, + babbage::PlutusV2Script, }; -use crate::MultiEraWitnesses; +use crate::MultiEraTx; -impl<'b> MultiEraWitnesses<'b> { - pub fn as_alonzo(&self) -> Option<&alonzo::TransactionWitnessSet> { +impl<'b> MultiEraTx<'b> { + pub fn vkey_witnesses(&self) -> Option<&[VKeyWitness]> { match self { - Self::AlonzoCompatible(x) => Some(x), + Self::AlonzoCompatible(x, _) => x + .transaction_witness_set + .vkeywitness + .as_ref() + .map(|x| x.as_ref()), + Self::Babbage(x) => x + .transaction_witness_set + .vkeywitness + .as_ref() + .map(|x| x.as_ref()), _ => None, } } - pub fn as_babbage(&self) -> Option<&babbage::TransactionWitnessSet> { + pub fn native_scripts(&self) -> Option<&[NativeScript]> { match self { - Self::Babbage(x) => Some(x), + Self::AlonzoCompatible(x, _) => x + .transaction_witness_set + .native_script + .as_ref() + .map(|x| x.as_ref()), + Self::Babbage(x) => x + .transaction_witness_set + .native_script + .as_ref() + .map(|x| x.as_ref()), _ => None, } } - pub fn vkeywitness(&self) -> Option<&[VKeyWitness]> { + pub fn bootstrap_witnesses(&self) -> Option<&[BootstrapWitness]> { match self { - Self::AlonzoCompatible(x) => x.vkeywitness.as_ref().map(|x| x.as_ref()), - Self::Babbage(x) => x.vkeywitness.as_ref().map(|x| x.as_ref()), + Self::AlonzoCompatible(x, _) => x + .transaction_witness_set + .bootstrap_witness + .as_ref() + .map(|x| x.as_ref()), + Self::Babbage(x) => x + .transaction_witness_set + .bootstrap_witness + .as_ref() + .map(|x| x.as_ref()), _ => None, } } - pub fn native_script(&self) -> Option<&[NativeScript]> { + pub fn plutus_v1_scripts(&self) -> Vec<&alonzo::PlutusScript> { match self { - Self::AlonzoCompatible(x) => x.native_script.as_ref().map(|x| x.as_ref()), - Self::Babbage(x) => x.native_script.as_ref().map(|x| x.as_ref()), + Self::AlonzoCompatible(x, _) => x + .transaction_witness_set + .plutus_script + .iter() + .flatten() + .collect(), + Self::Babbage(x) => x + .transaction_witness_set + .plutus_v1_script + .iter() + .flatten() + .collect(), + _ => vec![], + } + } + + pub fn plutus_data(&self) -> Vec<&KeepRaw<'b, PlutusData>> { + match self { + Self::AlonzoCompatible(x, _) => x + .transaction_witness_set + .plutus_data + .iter() + .flatten() + .collect(), + Self::Babbage(x) => x + .transaction_witness_set + .plutus_data + .iter() + .flatten() + .collect(), + _ => std::iter::empty().collect(), + } + } + + pub fn redeemers(&self) -> Option<&[Redeemer]> { + match self { + Self::AlonzoCompatible(x, _) => x + .transaction_witness_set + .redeemer + .as_ref() + .map(|x| x.as_ref()), + Self::Babbage(x) => x + .transaction_witness_set + .redeemer + .as_ref() + .map(|x| x.as_ref()), _ => None, } } - pub fn bootstrap_witness(&self) -> Option<&[BootstrapWitness]> { + pub fn plutus_v2_scripts(&self) -> Option<&[PlutusV2Script]> { match self { - Self::AlonzoCompatible(x) => x.bootstrap_witness.as_ref().map(|x| x.as_ref()), - Self::Babbage(x) => x.bootstrap_witness.as_ref().map(|x| x.as_ref()), + Self::Babbage(x) => x + .transaction_witness_set + .plutus_v2_script + .as_ref() + .map(|x| x.as_ref()), _ => None, } } - - pub fn plutus_v1_script(&self) -> Option<&[alonzo::PlutusScript]> { - match self { - Self::AlonzoCompatible(x) => x.plutus_script.as_ref().map(|x| x.as_ref()), - Self::Babbage(x) => x.plutus_v1_script.as_ref().map(|x| x.as_ref()), - _ => None, - } - } - - pub fn plutus_data(&self) -> Option<&[PlutusData]> { - match self { - Self::AlonzoCompatible(x) => x.plutus_data.as_ref().map(|x| x.as_ref()), - Self::Babbage(x) => x.plutus_data.as_ref().map(|x| x.as_ref()), - _ => None, - } - } - - pub fn redeemer(&self) -> Option<&[Redeemer]> { - match self { - Self::AlonzoCompatible(x) => x.redeemer.as_ref().map(|x| x.as_ref()), - Self::Babbage(x) => x.redeemer.as_ref().map(|x| x.as_ref()), - _ => None, - } - } - - pub fn plutus_v2_script(&self) -> Option<&[PlutusV2Script]> { - match self { - Self::Babbage(x) => x.plutus_v2_script.as_ref().map(|x| x.as_ref()), - _ => 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(), - } - } } diff --git a/test_data/babbage1.tx b/test_data/babbage1.tx new file mode 100644 index 0000000..03135ae --- /dev/null +++ b/test_data/babbage1.tx @@ -0,0 +1 @@ +84a400828258206c732139de33e916342707de2aebef2252c781640326ff37b86ec99d97f1ba8d0182582018f86700660fc88d0370a8f95ea58f75507e6b27a18a17925ad3b1777eb0d77600018783581d703a888d65f16790950a72daee1f63aa05add6d268434107cfa5b67712821a000f52c6a05820923918e403bf43c34b4ef6b48eb2ee04babed17320d8d1b9ff9ad086e86f44ec83581d703a888d65f16790950a72daee1f63aa05add6d268434107cfa5b67712821a000f52c6a0582054ad3c112d58e8946480e21d6a35b2a215d1a9a8f540c13714ded86e4b0b6aea83581d703a888d65f16790950a72daee1f63aa05add6d268434107cfa5b67712821a000f52c6a05820ed33125018c5cbc9ae1b242a3ff8f3db2e108e4a63866d0b5238a34502c723ed83581d703a888d65f16790950a72daee1f63aa05add6d268434107cfa5b67712821a000f52c6a05820b0ea85f16a443da7f60704a427923ae1d89a7dc2d6621d805d9dd441431ed70083581d703a888d65f16790950a72daee1f63aa05add6d268434107cfa5b67712821a000f52c6a05820831a557bc2948e1b8c9f5e8e594d62299abff4eb1a11dc19da38bfaf9f2da40783581d703a888d65f16790950a72daee1f63aa05add6d268434107cfa5b67712821a000f52c6a05820c695868b4bfbf4c95714e707c69da1823bcf8cfc7c4b14b92c3645d4e1943be382581d60b6c8794e9a7a26599440a4d0fd79cd07644d15917ff13694f1f672351b00000001af62c125021a0002dfb10b58209dc070b08ae8dbd9ced77831308173284a19ab4839ce894fca45b8e3752a8a42a2008182582031ae74f8058527afb305d7495b10a99422d9337fc199e1f28044f2c477a0f94658409d9315424385661b9c17c0c9b96eeb61645d8f18cbefd43aa87677aae8cc2282642650d41004a11d1d0b66146da9fa22c824e6c1b9e0525268e9a43078fb670c049fd8799f413101ffd905039fa101423131d8798043313131ffd87980a10142313141319f0102fffff5f6 \ No newline at end of file