diff --git a/src/filters/fingerprint.rs b/src/filters/fingerprint.rs index 4f785a49..d4f6ff19 100644 --- a/src/filters/fingerprint.rs +++ b/src/filters/fingerprint.rs @@ -9,7 +9,10 @@ use log::{debug, warn}; use serde::Deserialize; use crate::{ - model::{CIP25AssetRecord, Event, EventData, MetadataRecord, MintRecord, OutputAssetRecord}, + model::{ + CIP25AssetRecord, EpochBoundaryRecord, Event, EventData, MetadataRecord, MintRecord, + OutputAssetRecord, + }, pipelining::{new_inter_stage_channel, FilterProvider, PartialBootstrapResult, StageReceiver}, Error, }; @@ -100,6 +103,10 @@ fn build_fingerprint(event: &Event, seed: u32) -> Result { .with_slot(&event.context.slot) .with_prefix("blckend") .append_optional(&event.context.block_hash)?, + EventData::EpochBoundary(EpochBoundaryRecord { hash, .. }) => b + .with_slot(&event.context.slot) + .with_prefix("ebb") + .append_to_string(hash)?, EventData::Transaction { .. } => b .with_slot(&event.context.slot) .with_prefix("tx") diff --git a/src/mapper/byron.rs b/src/mapper/byron.rs index c5c686d6..b56394d0 100644 --- a/src/mapper/byron.rs +++ b/src/mapper/byron.rs @@ -2,7 +2,10 @@ use std::ops::Deref; use super::map::ToHex; use super::EventWriter; -use crate::model::{BlockRecord, Era, EventData, TransactionRecord, TxInputRecord, TxOutputRecord}; +use crate::model::{ + BlockRecord, EpochBoundaryRecord, Era, EventData, TransactionRecord, TxInputRecord, + TxOutputRecord, +}; use crate::{model::EventContext, Error}; use pallas::crypto::hash::Hash; @@ -68,7 +71,7 @@ impl EventWriter { let mut record = TransactionRecord { hash: tx_hash.to_owned(), - // TODO: we have a problem with here. AFAIK, there's no reference to the tx fee in the + // TODO: we have a problem here. AFAIK, there's no reference to the tx fee in the // block contents. This leaves us with the two alternative: a) compute the value, b) // omit the value. // @@ -187,25 +190,74 @@ impl EventWriter { Ok(()) } + pub fn to_byron_epoch_boundary_record( + &self, + source: &byron::EbBlock, + hash: &Hash<32>, + cbor: &[u8], + ) -> Result { + Ok(EpochBoundaryRecord { + era: Era::Byron, + body_size: cbor.len() as usize, + hash: hash.to_hex(), + number: source.header.consensus_data.difficulty[0], + previous_hash: source.header.prev_block.to_hex(), + cbor_hex: match self.config.include_block_cbor { + true => hex::encode(cbor).into(), + false => None, + }, + epoch: source.header.consensus_data.epoch_id, + }) + } + + fn crawl_byron_ebb_block( + &self, + block: &byron::EbBlock, + hash: &Hash<32>, + cbor: &[u8], + ) -> Result<(), Error> { + let record = self.to_byron_epoch_boundary_record(block, hash, cbor)?; + self.append_from(record)?; + Ok(()) + } + /// Mapper entry-point for decoded Byron blocks /// /// Entry-point to start crawling a blocks for events. Meant to be used when /// we already have a decoded block (for example, N2C). The raw CBOR is also /// passed through in case we need to attach it to outbound events. pub fn crawl_byron_with_cbor(&self, block: &byron::Block, cbor: &[u8]) -> Result<(), Error> { - if let byron::Block::MainBlock(block) = block { - let hash = block.header.to_hash(); - let abs_slot = block.header.consensus_data.0.to_abs_slot(); - - let child = self.child_writer(EventContext { - block_hash: Some(hex::encode(&hash)), - block_number: Some(block.header.consensus_data.2[0]), - slot: Some(abs_slot), - timestamp: self.compute_timestamp(abs_slot), - ..EventContext::default() - }); - - child.crawl_byron_main_block(block, &hash, cbor)?; + match block { + byron::Block::MainBlock(block) => { + let hash = block.header.to_hash(); + let abs_slot = block.header.consensus_data.0.to_abs_slot(); + + let child = self.child_writer(EventContext { + block_hash: Some(hex::encode(&hash)), + block_number: Some(block.header.consensus_data.2[0]), + slot: Some(abs_slot), + timestamp: self.compute_timestamp(abs_slot), + ..EventContext::default() + }); + + child.crawl_byron_main_block(block, &hash, cbor)?; + } + byron::Block::EbBlock(block) => { + if self.config.include_byron_ebb { + let hash = block.header.to_hash(); + let abs_slot = block.header.to_abs_slot(); + + let child = self.child_writer(EventContext { + block_hash: Some(hex::encode(&hash)), + block_number: Some(block.header.consensus_data.difficulty[0]), + slot: Some(abs_slot), + timestamp: self.compute_timestamp(abs_slot), + ..EventContext::default() + }); + + child.crawl_byron_ebb_block(block, &hash, cbor)?; + } + } } Ok(()) diff --git a/src/mapper/prelude.rs b/src/mapper/prelude.rs index c7e83a71..21f0a44d 100644 --- a/src/mapper/prelude.rs +++ b/src/mapper/prelude.rs @@ -27,6 +27,9 @@ pub struct Config { #[serde(default)] pub include_block_cbor: bool, + + #[serde(default)] + pub include_byron_ebb: bool, } #[derive(Clone)] diff --git a/src/model.rs b/src/model.rs index 411f9b41..51e5a533 100644 --- a/src/model.rs +++ b/src/model.rs @@ -185,6 +185,23 @@ pub struct BlockRecord { pub cbor_hex: Option, } +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] +pub struct EpochBoundaryRecord { + pub era: Era, + pub body_size: usize, + pub epoch: u64, + pub hash: String, + pub number: u64, + pub previous_hash: String, + pub cbor_hex: Option, +} + +impl From for EventData { + fn from(x: EpochBoundaryRecord) -> Self { + EventData::EpochBoundary(x) + } +} + #[derive(Serialize, Deserialize, Display, Debug, Clone)] #[serde(rename_all = "snake_case")] pub enum EventData { @@ -245,6 +262,7 @@ pub enum EventData { block_slot: u64, block_hash: String, }, + EpochBoundary(EpochBoundaryRecord), } #[derive(Debug, Serialize, Deserialize)] diff --git a/src/sinks/terminal/format.rs b/src/sinks/terminal/format.rs index a8c77535..99c856ea 100644 --- a/src/sinks/terminal/format.rs +++ b/src/sinks/terminal/format.rs @@ -3,8 +3,8 @@ use std::fmt::{Display, Write}; use crossterm::style::{Attribute, Color, Stylize}; use crate::model::{ - BlockRecord, CIP25AssetRecord, Event, EventData, MetadataRecord, MintRecord, OutputAssetRecord, - TransactionRecord, TxInputRecord, TxOutputRecord, + BlockRecord, CIP25AssetRecord, EpochBoundaryRecord, Event, EventData, MetadataRecord, + MintRecord, OutputAssetRecord, TransactionRecord, TxInputRecord, TxOutputRecord, }; pub struct LogLine { @@ -65,6 +65,25 @@ impl LogLine { max_width, } } + EventData::EpochBoundary(EpochBoundaryRecord { + epoch, + hash, + number, + .. + }) => { + LogLine { + prefix: "EBB", + color: Color::DarkMagenta, + content: format!( + "{{ epoch: {}, hash: {}, number: {} }}", + epoch, + hash, + number, + ), + source, + max_width, + } + } EventData::Transaction(TransactionRecord { total_output, fee,