diff --git a/src/mapper/map.rs b/src/mapper/map.rs index edcc8d43..ad88e4fa 100644 --- a/src/mapper/map.rs +++ b/src/mapper/map.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; -use pallas::codec::minicbor::bytes::ByteVec; -use pallas::crypto::hash::Hash; +use pallas::codec::minicbor::{self, bytes::ByteVec}; +use pallas::crypto::hash::{Hash, Hasher}; use pallas::ledger::primitives::alonzo::{ self as alonzo, AuxiliaryData, Block, Certificate, InstantaneousRewardSource, InstantaneousRewardTarget, Metadatum, Relay, TransactionInput, TransactionOutput, Value, @@ -12,8 +12,8 @@ use pallas::network::miniprotocols::Point; use serde_json::{json, Value as JsonValue}; use crate::model::{ - BlockRecord, Era, EventData, MetadataRecord, MetadatumRendition, MintRecord, OutputAssetRecord, - StakeCredential, TransactionRecord, TxInputRecord, TxOutputRecord, + BlockRecord, Era, EventData, MetadataRecord, MetadatumRendition, MintRecord, NativeScript, + OutputAssetRecord, StakeCredential, TransactionRecord, TxInputRecord, TxOutputRecord, }; use crate::utils::time::TimeProvider; @@ -187,8 +187,45 @@ impl EventWriter { } } - pub fn to_native_script_event(&self) -> EventData { - EventData::NativeScript {} + pub fn to_native_script_event(&self, script: &alonzo::NativeScript) -> EventData { + let mut cbor = Vec::new(); + minicbor::encode(script, &mut cbor).unwrap(); + cbor.insert(0, 0); + let digest = Hasher::<224>::hash(&cbor); + + EventData::NativeScript { + policy_id: hex::encode(digest), + script: self.to_native_script(script), + } + } + + pub fn to_native_script(&self, script: &alonzo::NativeScript) -> NativeScript { + match script { + alonzo::NativeScript::ScriptPubkey(keyhash) => NativeScript::Sig { + key_hash: keyhash.to_string(), + }, + alonzo::NativeScript::ScriptAll(scripts) => NativeScript::All { + scripts: (*scripts) + .iter() + .map(|script| self.to_native_script(script)) + .collect(), + }, + alonzo::NativeScript::ScriptAny(scripts) => NativeScript::Any { + scripts: (*scripts) + .iter() + .map(|script| self.to_native_script(script)) + .collect(), + }, + alonzo::NativeScript::ScriptNOfK(n, scripts) => NativeScript::AtLeast { + required: *n, + scripts: (*scripts) + .iter() + .map(|script| self.to_native_script(script)) + .collect(), + }, + alonzo::NativeScript::InvalidBefore(slot) => NativeScript::After { slot: *slot }, + alonzo::NativeScript::InvalidHereafter(slot) => NativeScript::Before { slot: *slot }, + } } pub fn to_plutus_script_event(&self, script: &ByteVec) -> EventData { @@ -324,26 +361,6 @@ impl EventWriter { }; } - // TODO: add witness set data to transaction - /* - if let Some(witness) = self.transaction_witness_sets.get(idx) { - let plutus_count = match &witness.plutus_script { - Some(scripts) => scripts.len(), - None => 0, - }; - - let native_count = match &witness.native_script { - Some(scripts) => scripts.len(), - None => 0, - }; - - let redeemer_count = match &witness.redeemer { - Some(redeemer) => redeemer.len(), - None => 0, - }; - } - */ - if self.config.include_transaction_details { record.metadata = match aux_data { Some(aux_data) => self.collect_metadata_records(aux_data)?.into(), diff --git a/src/mapper/shelley.rs b/src/mapper/shelley.rs index c5ec8c83..ce668976 100644 --- a/src/mapper/shelley.rs +++ b/src/mapper/shelley.rs @@ -39,8 +39,10 @@ impl EventWriter { self.crawl_metadata(metadata)?; } - for _native in data.native_scripts.iter() { - self.append(self.to_native_script_event())?; + if let Some(native) = &data.native_scripts { + for script in native.iter() { + self.append(self.to_native_script_event(script))?; + } } if let Some(plutus) = &data.plutus_scripts { @@ -58,8 +60,10 @@ impl EventWriter { } => { self.crawl_metadata(transaction_metadata)?; - for _native in auxiliary_scripts.iter() { - self.append(self.to_native_script_event())?; + if let Some(native) = &auxiliary_scripts { + for script in native.iter() { + self.append(self.to_native_script_event(script))?; + } } } } @@ -228,6 +232,19 @@ impl EventWriter { self.append(EventData::BlockEnd(record))?; } + for witness in block.transaction_witness_sets.iter() { + if let Some(native) = &witness.native_script { + for script in native.iter() { + self.append(self.to_native_script_event(script))?; + } + } + if let Some(plutus) = &witness.plutus_script { + for script in plutus.iter() { + self.append(self.to_plutus_script_event(script))?; + } + } + } + Ok(()) } diff --git a/src/model.rs b/src/model.rs index 17c2c4e7..a70c5e59 100644 --- a/src/model.rs +++ b/src/model.rs @@ -173,6 +173,32 @@ pub enum StakeCredential { Scripthash(String), } +#[derive(Serialize, Deserialize, Debug, Clone, Display)] +#[serde(rename_all = "camelCase")] +#[serde(tag = "type")] +pub enum NativeScript { + #[serde(rename_all = "camelCase")] + Sig { + key_hash: String, + }, + All { + scripts: Vec, + }, + Any { + scripts: Vec, + }, + AtLeast { + required: u32, + scripts: Vec, + }, + Before { + slot: u64, + }, + After { + slot: u64, + }, +} + #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] pub struct BlockRecord { pub era: Era, @@ -215,7 +241,10 @@ pub enum EventData { tx_id: String, index: u64, }, - NativeScript {}, + NativeScript { + policy_id: String, + script: NativeScript, + }, PlutusScript { data: String, }, diff --git a/src/sinks/terminal/format.rs b/src/sinks/terminal/format.rs index 41b73e1f..e1717c71 100644 --- a/src/sinks/terminal/format.rs +++ b/src/sinks/terminal/format.rs @@ -163,10 +163,10 @@ impl LogLine { source, max_width, }, - EventData::NativeScript {} => LogLine { + EventData::NativeScript { policy_id, script } => LogLine { prefix: "NATIVE", color: Color::White, - content: "{{ ... }}".to_string(), + content: format!("{{ policy_id: {}, script: {} }}", policy_id, script), source, max_width, },