diff --git a/pallas-traverse/src/witnesses.rs b/pallas-traverse/src/witnesses.rs index 9c8cf3e7..81a7e1ce 100644 --- a/pallas-traverse/src/witnesses.rs +++ b/pallas-traverse/src/witnesses.rs @@ -1,10 +1,10 @@ use pallas_codec::utils::KeepRaw; use pallas_primitives::{ alonzo::{self, BootstrapWitness, NativeScript, VKeyWitness}, - conway, PlutusData, PlutusScript, + conway, Hash, PlutusData, PlutusScript, }; -use crate::{MultiEraRedeemer, MultiEraTx}; +use crate::{MultiEraRedeemer, MultiEraTx, OriginalHash as _}; impl<'b> MultiEraTx<'b> { pub fn vkey_witnesses(&self) -> &[VKeyWitness] { @@ -127,6 +127,12 @@ impl<'b> MultiEraTx<'b> { } } + pub fn find_plutus_data(&self, hash: &Hash<32>) -> Option<&KeepRaw<'b, PlutusData>> { + self.plutus_data() + .iter() + .find(|x| x.original_hash() == *hash) + } + pub fn redeemers(&self) -> Vec { match self { Self::Byron(_) => vec![], diff --git a/pallas-utxorpc/src/lib.rs b/pallas-utxorpc/src/lib.rs index 0b4b070a..7b1c2ce0 100644 --- a/pallas-utxorpc/src/lib.rs +++ b/pallas-utxorpc/src/lib.rs @@ -22,6 +22,7 @@ pub type Cbor = Vec; pub type EraCbor = (trv::Era, Cbor); pub type UtxoMap = HashMap; pub type DatumMap = HashMap, alonzo::PlutusData>; + pub trait LedgerContext: Clone { fn get_utxos(&self, refs: &[TxoRef]) -> Option; } @@ -78,7 +79,7 @@ impl Mapper { &self, resolved: &Option, input: &trv::MultiEraInput, - datum_map: &Option, + tx: &trv::MultiEraTx, ) -> Option { let as_txref = (*input.hash(), input.index() as u32); @@ -87,7 +88,7 @@ impl Mapper { .and_then(|x| x.get(&as_txref)) .and_then(|(era, cbor)| { let o = trv::MultiEraOutput::decode(*era, cbor.as_slice()).ok()?; - Some(self.map_tx_output(&o, datum_map)) + Some(self.map_tx_output(&o, tx)) }) } @@ -98,12 +99,11 @@ impl Mapper { // lexicographical order of the input we're mapping order: u32, resolved: &Option, - datum_map: &Option, ) -> u5c::TxInput { u5c::TxInput { tx_hash: input.hash().to_vec().into(), output_index: input.index() as u32, - as_output: self.decode_resolved_utxo(resolved, input, datum_map), + as_output: self.decode_resolved_utxo(resolved, input, tx), redeemer: tx.find_spend_redeemer(order).map(|x| self.map_redeemer(&x)), } } @@ -112,11 +112,12 @@ impl Mapper { &self, input: &trv::MultiEraInput, resolved: &Option, + tx: &trv::MultiEraTx, ) -> u5c::TxInput { u5c::TxInput { tx_hash: input.hash().to_vec().into(), output_index: input.index() as u32, - as_output: self.decode_resolved_utxo(resolved, input, &None), + as_output: self.decode_resolved_utxo(resolved, input, tx), redeemer: None, } } @@ -125,20 +126,17 @@ impl Mapper { &self, input: &trv::MultiEraInput, resolved: &Option, + tx: &trv::MultiEraTx, ) -> u5c::TxInput { u5c::TxInput { tx_hash: input.hash().to_vec().into(), output_index: input.index() as u32, - as_output: self.decode_resolved_utxo(resolved, input, &None), + as_output: self.decode_resolved_utxo(resolved, input, tx), redeemer: None, } } - pub fn map_tx_datum( - &self, - x: &trv::MultiEraOutput, - datum_map: &Option, - ) -> u5c::Datum { + pub fn map_tx_datum(&self, x: &trv::MultiEraOutput, tx: &trv::MultiEraTx) -> u5c::Datum { u5c::Datum { hash: match x.datum() { Some(babbage::PseudoDatumOption::Data(x)) => x.original_hash().to_vec().into(), @@ -147,9 +145,8 @@ impl Mapper { }, payload: match x.datum() { Some(babbage::PseudoDatumOption::Data(x)) => self.map_plutus_datum(&x.0).into(), - Some(babbage::PseudoDatumOption::Hash(x)) => datum_map - .as_ref() - .and_then(|m| m.get(&x)) + Some(babbage::PseudoDatumOption::Hash(x)) => tx + .find_plutus_data(&x) .map(|d| self.map_plutus_datum(d)) .into(), _ => None, @@ -161,11 +158,7 @@ impl Mapper { } } - pub fn map_tx_output( - &self, - x: &trv::MultiEraOutput, - datum_map: &Option, - ) -> u5c::TxOutput { + pub fn map_tx_output(&self, x: &trv::MultiEraOutput, tx: &trv::MultiEraTx) -> u5c::TxOutput { u5c::TxOutput { address: x.address().map(|a| a.to_vec()).unwrap_or_default().into(), coin: x.value().coin(), @@ -178,7 +171,7 @@ impl Mapper { .iter() .map(|x| self.map_policy_assets(x)) .collect(), - datum: self.map_tx_datum(x, datum_map).into(), + datum: self.map_tx_datum(x, tx).into(), script: match x.script_ref() { Some(conway::PseudoScript::NativeScript(x)) => u5c::Script { script: u5c::script::Script::Native(Self::map_native_script(&x)).into(), /* */ @@ -489,26 +482,18 @@ impl Mapper { ctx.get_utxos(to_resolve.as_slice()) }); - let mut datum_map: DatumMap = HashMap::new(); - for datum in tx.plutus_data().iter() { - let hash = datum.original_hash(); - datum_map.insert(hash, datum.clone().unwrap()); - } - u5c::Tx { hash: tx.hash().to_vec().into(), inputs: tx .inputs_sorted_set() .iter() .enumerate() - .map(|(order, i)| { - self.map_tx_input(i, tx, order as u32, &resolved, &Some(datum_map.clone())) - }) + .map(|(order, i)| self.map_tx_input(i, tx, order as u32, &resolved)) .collect(), outputs: tx .outputs() .iter() - .map(|x| self.map_tx_output(x, &Some(datum_map.clone()))) + .map(|x| self.map_tx_output(x, tx)) .collect(), certificates: tx .certs() @@ -539,7 +524,7 @@ impl Mapper { reference_inputs: tx .reference_inputs() .iter() - .map(|x| self.map_tx_reference_input(x, &resolved)) + .map(|x| self.map_tx_reference_input(x, &resolved, tx)) .collect(), witnesses: u5c::WitnessSet { vkeywitness: tx @@ -559,11 +544,9 @@ impl Mapper { collateral: tx .collateral() .iter() - .map(|x| self.map_tx_collateral(x, &resolved)) + .map(|x| self.map_tx_collateral(x, &resolved, tx)) .collect(), - collateral_return: tx - .collateral_return() - .map(|x| self.map_tx_output(&x, &None)), + collateral_return: tx.collateral_return().map(|x| self.map_tx_output(&x, tx)), total_collateral: tx.total_collateral().unwrap_or_default(), } .into(),