Skip to content
Merged
Show file tree
Hide file tree
Changes from 41 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
13 changes: 3 additions & 10 deletions rust/cardano-chain-follower/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,12 @@ pallas = { version = "0.30.1", git = "https://github.com/input-output-hk/catalys
pallas-hardano = { version = "0.30.1", git = "https://github.com/input-output-hk/catalyst-pallas.git", rev = "9b5183c8b90b90fe2cc319d986e933e9518957b3" }
pallas-crypto = { version = "0.30.1", git = "https://github.com/input-output-hk/catalyst-pallas.git", rev = "9b5183c8b90b90fe2cc319d986e933e9518957b3" }

# mithril-client = { version = "0.10.4", git = "https://github.com/input-output-hk/mithril", rev = "c6c7ebafae0158b2c1672eb96f6ef832fd542f93", default-features = false, features = [
mithril-client = { version = "0.10.4", default-features = false, features = [
"full",
"num-integer-backend",
] }

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

thiserror = "1.0.69"
tokio = { version = "1.42.0", features = [
Expand All @@ -37,26 +36,20 @@ url = "2.5.4"
anyhow = "1.0.95"
chrono = "0.4.39"
async-trait = "0.1.83"
dirs = "5.0.1"
futures = "0.3.31"
humantime = "2.1.0"
crossbeam-skiplist = "0.1.3"
crossbeam-channel = "0.5.14"
crossbeam-epoch = "0.9.18"
strum = "0.26.3"
ouroboros = "0.18.4"
hex = "0.4.3"
rayon = "1.10.0"
serde = "1.0.217"
serde_json = "1.0.134"
mimalloc = { version = "0.1.43", optional = true }
memx = "0.1.32"
fmmap = { version = "0.3.3", features = ["sync", "tokio-async"] }
minicbor = { version = "0.25.1", features = ["alloc", "derive", "half"] }
zstd = "0.13.2"
ed25519-dalek = "2.1.1"
blake2b_simd = "1.0.2"
num-traits = "0.2.19"
logcall = "0.1.11"
tar = "0.4.43"
ureq = { version = "2.12.1", features = ["native-certs"] }
Expand All @@ -65,12 +58,12 @@ hickory-resolver = { version = "0.24.2", features = ["dns-over-rustls"] }
moka = { version = "0.12.9", features = ["sync"] }

[dev-dependencies]
hex = "0.4.3"
tracing-subscriber = { version = "0.3.19", features = ["env-filter"] }
test-log = { version = "0.2.16", default-features = false, features = [
"trace",
] }
clap = "4.5.23"
# rbac-registration = { version = "0.0.2", git = "https://github.com/input-output-hk/catalyst-libs.git", tag = "v0.0.8" }

# Note, these features are for support of features exposed by dependencies.
[features]
Expand Down
140 changes: 38 additions & 102 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::{Cip36, Fork, MultiEraBlock, Network, Point};
#[cfg(feature = "mimalloc")]
use mimalloc::MiMalloc;
use rbac_registration::cardano::cip509;

/// Use Mimalloc for the global allocator.
#[cfg(feature = "mimalloc")]
Expand All @@ -16,11 +16,7 @@ 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,
};
use cardano_chain_follower::{ChainFollower, ChainSyncConfig, ChainUpdate, Kind, Statistics};
use clap::{arg, ArgAction, ArgMatches, Command};
use tokio::time::Instant;
use tracing::{error, info, level_filters::LevelFilter, warn};
Expand All @@ -41,14 +37,8 @@ fn process_argument() -> (Vec<Network>, ArgMatches) {
.action(ArgAction::SetTrue),
arg!(--"halt-on-error" "Stop the process when an error occurs without retrying.")
.action(ArgAction::SetTrue),
arg!(--"log-bad-cip36" "Dump Bad CIP36 registrations detected.")
.action(ArgAction::SetTrue),
arg!(--"log-cip509" "Dump CIP509 validation.")
.action(ArgAction::SetTrue),
arg!(--"log-raw-aux" "Dump raw auxiliary data.")
.action(ArgAction::SetTrue),
arg!(--"largest-metadata" "Dump The largest transaction metadata we find (as we find it).")
.action(ArgAction::SetTrue),
arg!(--"mithril-sync-workers" <WORKERS> "The number of workers to use when downloading the blockchain snapshot.")
.value_parser(clap::value_parser!(u16).range(1..))
.action(ArgAction::Set),
Expand All @@ -64,6 +54,9 @@ fn process_argument() -> (Vec<Network>, ArgMatches) {
arg!(--"mithril-sync-data-read-timeout" <SECS> "The HTTP Data Read Timeout for mithril downloads, in seconds.")
.value_parser(clap::value_parser!(u64).range(1..))
.action(ArgAction::Set),
// Metadata
arg!(--"log-bad-cip36" "Dump Bad CIP36 registrations detected.")
.action(ArgAction::SetTrue),
])
.get_matches();

Expand All @@ -84,7 +77,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 @@ -146,16 +138,16 @@ const RUNNING_UPDATE_INTERVAL: u64 = 100_000;
#[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 mut follower = ChainFollower::new(network, Point::ORIGIN, Point::TIP).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");

// Metadata
let log_bad_cip36 = matches.get_flag("log-bad-cip36");

let mut current_era = String::new();
let mut last_update: Option<ChainUpdate> = None;
Expand All @@ -164,13 +156,11 @@ async fn follow_for(network: Network, matches: ArgMatches) {
let mut last_immutable: bool = false;
let mut 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 last_fork: Fork = 0.into();
let mut follow_all = false;

let mut last_metrics_time = Instant::now();

let mut biggest_aux_data: usize = 0;

while let Some(chain_update) = follower.next().await {
updates += 1;

Expand Down Expand Up @@ -200,7 +190,7 @@ 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);
|| ((chain_update.data.fork() > 1.into()) && all_tip_blocks);

// Don't know if this update will show or not, so say it didn't.
last_update_shown = false;
Expand Down Expand Up @@ -242,24 +232,6 @@ async fn follow_for(network: Network, matches: ArgMatches) {
break;
}

// 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)
{
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 `log_cip509` is set, log the CIP509 validation.
if log_cip509 {
log_cip509_info(&chain_update, block.number(), network, tx_idx);
}
}

if log_raw_aux {
if let Some(x) = block.as_alonzo() {
info!(
Expand All @@ -279,6 +251,13 @@ async fn follow_for(network: Network, matches: ArgMatches) {
}
}

// Illustrate how the chain-follower works with metadata.
// Log bad CIP36.
if log_bad_cip36 {
log_bad_cip36_info(chain_update.block_data(), network);
}
// TODO - Add CIP509 example.

prev_hash = Some(block.hash());
last_update = Some(chain_update);

Expand Down Expand Up @@ -318,74 +297,31 @@ async fn follow_for(network: Network, matches: ArgMatches) {
info!(chain = network.to_string(), "Following Completed.");
}

/// Helper function for updating the biggest aux data.
fn update_biggest_aux_data(
chain_update: &ChainUpdate, tx_idx: usize, 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)
{
Some(raw) => raw.len(),
None => 0,
};

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

// Get the maximum raw size from both cip36 and cip509
let raw_size = raw_size_cip36.max(raw_size_cip509);

if largest_metadata && raw_size > biggest_aux_data {
return Some(raw_size);
}

None
}

/// 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()
{
info!(
chain = network.to_string(),
"CIP36 {tx_idx}: {:?}", decoded_metadata
);
/// Function for logging bad CIP36.
/// Bad CIP36 includes:
/// - CIP36 that is valid decoded, but have problem.
/// - CIP36 that is invalid decoded.
fn log_bad_cip36_info(block: &MultiEraBlock, network: Network) {
if let Some(map) = Cip36::cip36_from_block(block, true) {
for (key, value) in &map {
match value {
Ok(value) => {
// Logging the problematic CIP36.
if value.err_report().is_problematic() {
info!(
network = network.to_string(),
"CIP36 valid decoded, but have problem: index {:?}, {}", key, value
);
}
},
Err(e) => {
warn!("CIP36 decode err {}: ", e);
},
}
}
}
}

/// 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 {
info!(
chain = network.to_string(),
"CIP509 {tx_idx}: {:?}", cip509.validation
);
}

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

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
tracing_subscriber::fmt()
Expand Down
Loading
Loading