Skip to content
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
bc4bfff
fix(cardano-chain-follower): use Network, MultiEraBlock, Point from c…
bkioshn Dec 19, 2024
1d37012
fix(cardano-chain-follower): comments
bkioshn Dec 19, 2024
e645601
fix(cardano-chain-follower): comments
bkioshn Dec 19, 2024
4d1aea0
fix(cardano-chain-follower): fix type
bkioshn Dec 23, 2024
489a289
fix(cardano-chain-follower): fix type stat
bkioshn Dec 23, 2024
d8542d1
fix(cardano-chain-follower): fix type
bkioshn Dec 24, 2024
1ce3a20
fix(cardano-chain-follower): remove raw_aux_data
bkioshn Dec 25, 2024
9f48bd0
fix(cardano-chain-follower): remove decoded_transaction
bkioshn Dec 25, 2024
b0b68f9
fix(cardano-chain-follower): update cip509
bkioshn Dec 25, 2024
980b1b3
fix(cardano-chain-follower): update cip36
bkioshn Dec 26, 2024
944a112
fix(cardano-chain-follower): update metadata
bkioshn Dec 26, 2024
fa0bcd5
fix(cardano-chain-follower): update cip509
bkioshn Dec 26, 2024
194b327
fix(cardano-chain-follower): nonce
bkioshn Dec 26, 2024
81bc839
fix(cardano-chain-follower): update get metadata by label
bkioshn Dec 26, 2024
5e110f0
fix(cardano-chain-follower): slot
bkioshn Dec 26, 2024
d568da1
fix(cardano-blockchain-types): follow_chains.rs
bkioshn Dec 31, 2024
69f000f
fix(cardano-blockchain-types): decodedmetadata
bkioshn Dec 31, 2024
70debef
fix(cardano-blockchain-types): cleanup cip36
bkioshn Dec 31, 2024
06fbfa1
fix(cardano-blockchain-types): follow_chains.rs
bkioshn Dec 31, 2024
8b9f82c
fix(cardano-blockchain-types): cleanup
bkioshn Dec 31, 2024
f809624
fix(cardano-chain-follower): remove blake2b hash
bkioshn Dec 31, 2024
31abce8
fix(cardano-chain-follower): usecip36 contructor
bkioshn Dec 31, 2024
017b69e
fix(cardano-chain-follower): naming chain -> network
bkioshn Dec 31, 2024
1d095c5
fix(cardano-chain-follower): remove unnecessary file
bkioshn Jan 7, 2025
a99a7e7
Merge branch 'main' into fix/refactor-chain-follower
bkioshn Jan 8, 2025
244c3b1
fix(cardano-chain-follower): use function from catalyst-types
bkioshn Jan 8, 2025
5628663
fix(cardano-chain-follower): minor fixes
bkioshn Jan 8, 2025
595dd5d
test(cardano-chain-follower): recheck test in follow.rs
bkioshn Jan 8, 2025
41363e2
fix(cardano-chain-follower): add blockchain-types and cat-types lib
bkioshn Jan 8, 2025
589ac48
fix(cardano-chain-follower): try out new cip36
bkioshn Jan 9, 2025
99f9b1a
fix(cardano-chain-follower): remove redundant file data
bkioshn Jan 9, 2025
e96216a
fix(cardano-chain-follower): break down stats
bkioshn Jan 9, 2025
e74e3b5
fix(cardano-chain-follower): example log cip36
bkioshn Jan 9, 2025
7ab857c
fix(cardano-chain-follower): remove unused dependencies
bkioshn Jan 9, 2025
59b9fcf
Merge branch 'main' into fix/refactor-chain-follower
stevenj Jan 9, 2025
60c7237
fix(cardano-chain-follower): modify logging metadata example
bkioshn Jan 9, 2025
f4717e7
Merge branch 'main' into fix/refactor-chain-follower
bkioshn Jan 9, 2025
d970fdb
Merge branch 'main' into fix/refactor-chain-follower
stevenj Jan 9, 2025
cbe8f86
fix(cardano-chain-follower): revert changes
bkioshn Jan 10, 2025
00e5cf7
Update rust/cardano-chain-follower/Cargo.toml
bkioshn Jan 10, 2025
557e20c
fix(cardano-chain-follower): revert changes
bkioshn Jan 10, 2025
9302156
fix(cardano-chain-follower): new fork
bkioshn Jan 10, 2025
2fbbe61
fix(cardano-chain-follower): add more function
bkioshn Jan 13, 2025
2283d97
fix(cardano-chain-follower): tag cardano-blockchain-types
bkioshn Jan 14, 2025
19b06b8
Merge branch 'main' into fix/refactor-chain-follower
bkioshn Jan 14, 2025
d63192f
fix(cardano-chain-follower): magic number
bkioshn Jan 14, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions rust/cardano-chain-follower/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ mithril-client = { version = "0.10.4", default-features = false, features = [
] }

rbac-registration = { version = "0.0.2", git = "https://github.com/input-output-hk/catalyst-libs.git", tag = "v0.0.8" }
cardano-blockchain-types = { git = "https://github.com/input-output-hk/catalyst-libs.git", branch = "feat/cardano-blockchain-types" }

thiserror = "1.0.64"
tokio = { version = "1.40.0", features = [
Expand Down
188 changes: 106 additions & 82 deletions rust/cardano-chain-follower/examples/follow_chains.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
// Allowing since this is example code.
//#![allow(clippy::unwrap_used)]

use cardano_blockchain_types::{BlockAuxData, Fork, MetadatumLabel, Network, Point, TxnIndex};
#[cfg(feature = "mimalloc")]
use mimalloc::MiMalloc;
use rbac_registration::cardano::cip509;

/// Use Mimalloc for the global allocator.
#[cfg(feature = "mimalloc")]
Expand All @@ -17,9 +17,8 @@ static GLOBAL: MiMalloc = MiMalloc;
use std::{error::Error, time::Duration};

use cardano_chain_follower::{
ChainFollower, ChainSyncConfig, ChainUpdate, Kind,
Metadata::{self},
Network, Statistics, ORIGIN_POINT, TIP_POINT,
metadata::DecodedMetadata, ChainFollower, ChainSyncConfig, ChainUpdate, Kind, Metadata,
Statistics,
};
use clap::{arg, ArgAction, ArgMatches, Command};
use tokio::time::Instant;
Expand Down Expand Up @@ -84,7 +83,6 @@ fn process_argument() -> (Vec<Network>, ArgMatches) {
/// Start syncing a particular network
async fn start_sync_for(network: &Network, matches: ArgMatches) -> Result<(), Box<dyn Error>> {
let mut cfg = ChainSyncConfig::default_for(*network);

let mut mithril_dl_connect_timeout = "Not Set".to_string();
let mut mithril_dl_data_timeout = "Not Set".to_string();

Expand Down Expand Up @@ -122,7 +120,7 @@ async fn start_sync_for(network: &Network, matches: ArgMatches) -> Result<(), Bo
cfg.mithril_cfg = cfg.mithril_cfg.with_dl_config(dl_config);

info!(
chain = cfg.chain.to_string(),
network = cfg.network.to_string(),
mithril_sync_dl_workers = mithril_dl_workers,
mithril_sync_dl_chunk_size = mithril_dl_chunk_size,
mithril_sync_dl_queue_ahead = mithril_dl_queue_ahead,
Expand All @@ -145,27 +143,27 @@ const RUNNING_UPDATE_INTERVAL: u64 = 100_000;
/// Try and follow a chain continuously, from Genesis until Tip.
#[allow(clippy::too_many_lines)]
async fn follow_for(network: Network, matches: ArgMatches) {
info!(chain = network.to_string(), "Following");
let mut follower = ChainFollower::new(network, ORIGIN_POINT, TIP_POINT).await;

let all_tip_blocks = matches.get_flag("all-tip-blocks");
let all_live_blocks = matches.get_flag("all-live-blocks");
let stop_at_tip = matches.get_flag("stop-at-tip");
let halt_on_error = matches.get_flag("halt-on-error");
let log_bad_cip36 = matches.get_flag("log-bad-cip36");
let log_cip509 = matches.get_flag("log-cip509");
let log_raw_aux = matches.get_flag("log-raw-aux");
let largest_metadata = matches.get_flag("largest-metadata");
info!(network = network.to_string(), "Following");
let mut follower = ChainFollower::new(network, Point::ORIGIN, Point::TIP).await;

let is_all_tip_blocks = matches.get_flag("all-tip-blocks");
let is_all_live_blocks = matches.get_flag("all-live-blocks");
let is_stop_at_tip = matches.get_flag("stop-at-tip");
let is_halt_on_error = matches.get_flag("halt-on-error");
let is_log_bad_cip36 = matches.get_flag("log-bad-cip36");
let is_log_cip509 = matches.get_flag("log-cip509");
let is_log_raw_aux = matches.get_flag("log-raw-aux");
let is_largest_metadata = matches.get_flag("largest-metadata");

let mut current_era = String::new();
let mut last_update: Option<ChainUpdate> = None;
let mut last_update_shown = false;
let mut is_last_update_shown = false;
let mut prev_hash: Option<pallas_crypto::hash::Hash<32>> = None;
let mut last_immutable: bool = false;
let mut reached_tip = false; // After we reach TIP we show all block we process.
let mut is_last_immutable: bool = false;
let mut is_reached_tip = false; // After we reach TIP we show all block we process.
let mut updates: u64 = 0;
let mut last_fork = 0;
let mut follow_all = false;
let mut last_fork: Fork = 0.into();
let mut is_follow_all = false;

let mut last_metrics_time = Instant::now();

Expand All @@ -175,21 +173,21 @@ async fn follow_for(network: Network, matches: ArgMatches) {
updates += 1;

if chain_update.tip {
reached_tip = true;
is_reached_tip = true;
}

let block = chain_update.block_data().decode();
let this_era = block.era().to_string();

// When we transition between important points, show the last block as well.
if ((current_era != this_era)
|| (chain_update.immutable() != last_immutable)
|| (chain_update.is_immutable() != is_last_immutable)
|| (last_fork != chain_update.data.fork()))
&& !last_update_shown
&& !is_last_update_shown
{
if let Some(last_update) = last_update.clone() {
info!(
chain = network.to_string(),
network = network.to_string(),
"Chain Update {}:{}",
updates - 1,
last_update
Expand All @@ -198,29 +196,29 @@ async fn follow_for(network: Network, matches: ArgMatches) {
}

// If these become true, we will show all blocks from the follower.
follow_all = follow_all
|| (!chain_update.immutable() && all_live_blocks)
|| ((chain_update.data.fork() > 1) && all_tip_blocks);
is_follow_all = is_follow_all
|| (!chain_update.is_immutable() && is_all_live_blocks)
|| ((chain_update.data.fork() > 1.into()) && is_all_tip_blocks);

// Don't know if this update will show or not, so say it didn't.
last_update_shown = false;
is_last_update_shown = false;

if (current_era != this_era)
|| (chain_update.immutable() != last_immutable)
|| reached_tip
|| follow_all
|| (chain_update.is_immutable() != is_last_immutable)
|| is_reached_tip
|| is_follow_all
|| (updates % RUNNING_UPDATE_INTERVAL == 0)
|| (last_fork != chain_update.data.fork())
{
current_era = this_era;
last_immutable = chain_update.immutable();
is_last_immutable = chain_update.is_immutable();
last_fork = chain_update.data.fork();
info!(
chain = network.to_string(),
network = network.to_string(),
"Chain Update {updates}:{}", chain_update
);
// We already showed the last update, no need to show it again.
last_update_shown = true;
is_last_update_shown = true;
}

let this_prev_hash = block.header().previous_hash();
Expand All @@ -236,44 +234,65 @@ async fn follow_for(network: Network, matches: ArgMatches) {
"This Can't Happen".to_string()
};
error!(
chain = network.to_string(),
network = network.to_string(),
"Chain is broken: {chain_update} Does not follow: {display_last_update}",
);
break;
}

// Generate `BlockAuxData` from the block.
let block_aux_data = match BlockAuxData::try_from(block) {
Ok(aux_data) => aux_data,
Err(_) => continue,
};

// Inspect the transactions in the block.
for (tx_idx, _tx) in block.txs().iter().enumerate() {
if let Some(aux_data) =
update_biggest_aux_data(&chain_update, tx_idx, largest_metadata, biggest_aux_data)
{
for (txn_idx, tx) in block.txs().iter().enumerate() {
let txn_idx = TxnIndex::from_saturating(txn_idx);

// Get the auxiliary data for the transaction.
let tx_aux_data = match block_aux_data.get(txn_idx) {
Some(aux_data) => aux_data,
None => continue,
};

// Create new decoded metadata for the transaction.
let decoded_metadata = DecodedMetadata::new(network, block.slot(), tx, tx_aux_data);

if let Some(aux_data) = update_biggest_aux_data(
&chain_update,
txn_idx,
is_largest_metadata,
biggest_aux_data,
) {
biggest_aux_data = aux_data;
}

// If flag `log_bad_cip36` is set, log the bad CIP36.
if log_bad_cip36 {
log_bad_cip36_info(&chain_update, network, tx_idx);
// If flag `is_log_bad_cip36` is set, log the bad CIP36.
if is_log_bad_cip36 {
log_bad_cip36_info(&decoded_metadata, network, txn_idx, block.number());
}
// If flag `log_cip509` is set, log the CIP509 validation.
if log_cip509 {
log_cip509_info(&chain_update, block.number(), network, tx_idx);

// If flag `is_log_cip509` is set, log the CIP509 validation.
if is_log_cip509 {
log_cip509_info(&decoded_metadata, network, txn_idx, block.number());
}
}

if log_raw_aux {
if is_log_raw_aux {
if let Some(x) = block.as_alonzo() {
info!(
chain = network.to_string(),
network = network.to_string(),
"Raw Aux Data: {:02x?}", x.auxiliary_data_set
);
} else if let Some(x) = block.as_babbage() {
info!(
chain = network.to_string(),
network = network.to_string(),
"Raw Aux Data: {:02x?}", x.auxiliary_data_set
);
} else if let Some(x) = block.as_conway() {
info!(
chain = network.to_string(),
network = network.to_string(),
"Raw Aux Data: {:02x?}", x.auxiliary_data_set
);
}
Expand All @@ -282,7 +301,7 @@ async fn follow_for(network: Network, matches: ArgMatches) {
prev_hash = Some(block.hash());
last_update = Some(chain_update);

if reached_tip && stop_at_tip {
if is_reached_tip && is_stop_at_tip {
break;
}

Expand All @@ -294,7 +313,7 @@ async fn follow_for(network: Network, matches: ArgMatches) {

info!("Json Metrics: {}", stats.as_json(true));

if halt_on_error
if is_halt_on_error
&& (stats.mithril.download_or_validation_failed > 0
|| stats.mithril.failed_to_get_tip > 0
|| stats.mithril.tip_did_not_advance > 0
Expand All @@ -306,32 +325,40 @@ async fn follow_for(network: Network, matches: ArgMatches) {
}
}

if !last_update_shown {
if !is_last_update_shown {
if let Some(last_update) = last_update.clone() {
info!(chain = network.to_string(), "Last Update: {}", last_update);
info!(
network = network.to_string(),
"Last Update: {}", last_update
);
}
}

let stats = Statistics::new(network);
info!("Json Metrics: {}", stats.as_json(true));

info!(chain = network.to_string(), "Following Completed.");
info!(network = network.to_string(), "Following Completed.");
}

// FIXME: Why do we need this? Should it be finding the largest aux data?
/// Helper function for updating the biggest aux data.
/// Comparing between CIP36 and CIP509.
fn update_biggest_aux_data(
chain_update: &ChainUpdate, tx_idx: usize, largest_metadata: bool, biggest_aux_data: usize,
chain_update: &ChainUpdate, txn_idx: TxnIndex, largest_metadata: bool, biggest_aux_data: usize,
) -> Option<usize> {
let raw_size_cip36 = match chain_update
.data
.txn_raw_metadata(tx_idx, Metadata::cip36::LABEL)
.txn_metadata(txn_idx, MetadatumLabel::CIP036_REGISTRATION)
{
Some(raw) => raw.len(),
Some(raw) => raw.as_ref().len(),
None => 0,
};

let raw_size_cip509 = match chain_update.data.txn_raw_metadata(tx_idx, cip509::LABEL) {
Some(raw) => raw.len(),
let raw_size_cip509 = match chain_update
.data
.txn_metadata(txn_idx, MetadatumLabel::CIP509_RBAC)
{
Some(raw) => raw.as_ref().len(),
None => 0,
};

Expand All @@ -346,41 +373,38 @@ fn update_biggest_aux_data(
}

/// Helper function for logging bad CIP36.
fn log_bad_cip36_info(chain_update: &ChainUpdate, network: Network, tx_idx: usize) {
if let Some(decoded_metadata) = chain_update
.data
.txn_metadata(tx_idx, Metadata::cip36::LABEL)
{
if let Metadata::DecodedMetadataValues::Cip36(cip36) = &decoded_metadata.value {
if (!cip36.signed || !decoded_metadata.report.is_empty())
&& !decoded_metadata.report.is_empty()
{
fn log_bad_cip36_info(
decoded_metadata: &DecodedMetadata, network: Network, txn_idx: TxnIndex, block: u64,
) {
if let Some(m) = decoded_metadata.get(MetadatumLabel::CIP036_REGISTRATION) {
if let Metadata::DecodedMetadataValues::Cip36(cip36) = &m.value {
if !cip36.validation.is_valid_signature && !m.report.is_empty() {
info!(
chain = network.to_string(),
"CIP36 {tx_idx}: {:?}", decoded_metadata
network = network.to_string(),
block, "CIP36 {txn_idx:?}: {:?}", &cip36
);
}
}
}
}

/// Helper function for logging CIP509 validation.
fn log_cip509_info(chain_update: &ChainUpdate, block_num: u64, network: Network, tx_idx: usize) {
if let Some(decoded_metadata) = chain_update.data.txn_metadata(tx_idx, cip509::LABEL) {
info!("Block Number {}", block_num);

if let Metadata::DecodedMetadataValues::Cip509(cip509) = &decoded_metadata.value {
fn log_cip509_info(
decoded_metadata: &DecodedMetadata, network: Network, txn_idx: TxnIndex, block: u64,
) {
if let Some(m) = decoded_metadata.get(MetadatumLabel::CIP509_RBAC) {
if let Metadata::DecodedMetadataValues::Cip509(cip509) = &m.value {
info!(
chain = network.to_string(),
"CIP509 {tx_idx}: {:?}", cip509.validation
network = network.to_string(),
block, "CIP509 {txn_idx:?}: {:?}", &cip509
);
}

// If report is not empty, log it, log it as a warning.
if !decoded_metadata.report.is_empty() {
if !m.report.is_empty() {
warn!(
chain = network.to_string(),
"CIP509 {tx_idx}: {:?}", decoded_metadata.report
network = network.to_string(),
block, "CIP509 {txn_idx:?}: {:?}", decoded_metadata
);
}
}
Expand Down
Loading
Loading