Skip to content

Commit 1c2b570

Browse files
bkioshnstevenj
andauthored
feat(rust/cardano-chain-follower): RBAC CIP509 validation (#16)
* feat: move rbac validate from hermes * fix: change tx index to u16 * fix: rust ci branch pointing * fix: update rust ci version * fix(rust/cardano-chain-follower): move chain follower commands to itss on justfile * fix(rust/c509-certificate): only extract stake key for pubkey validation * fix(rust/c509-certificate): spelling * fix(rust/c509-certificate): stake public key validation + test cases * fix(rust/c509-certificate): ignore format for cspell addresses * fix(rust/c509-certificate): disable cspell check for addresses * fix(rust/cardano-chain-follower): payment key ref index * fix(rust/cardano-chain-follower): payment key ref index type to i16 * test(rust/cardano-chain-follower): CIP509 RBAC validation (#25) * test(rust/cardano-chain-follower): add test data * test(rust/cardano-chain-follower): add test for x509_chunk decompression * fix(rust/cardano-chain-follower): payment key should accept negative number * test(rust/cardano-chain-follower): add test for cip509 validation * chore(rust/cardano-chain-follower): typo * fix(rust/cardano-chain-follower): update test data --------- Co-authored-by: Steven Johnson <[email protected]>
1 parent 86abb82 commit 1c2b570

File tree

22 files changed

+2069
-502
lines changed

22 files changed

+2069
-502
lines changed

.config/dictionaries/project.dic

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ aarch
22
abcz
33
ABNF
44
addrr
5+
addrs
56
adminer
67
anypolicy
78
apskhem
@@ -10,6 +11,7 @@ asyncio
1011
Attributes
1112
auditability
1213
backpressure
14+
bech
1315
bimap
1416
bindgen
1517
bkioshn
@@ -59,6 +61,7 @@ encryptor
5961
Errno
6062
Eternl
6163
excalidraw
64+
extn
6265
fadvise
6366
fcntl
6467
fdatasync
@@ -85,6 +88,7 @@ happ
8588
hardano
8689
Hardlink
8790
hasher
91+
heaptrack
8892
hexdigit
8993
highwater
9094
hmod

rust/cardano-chain-follower/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ ureq = { version = "2.10.1", features = ["native-certs"] }
6565
http = "1.1.0"
6666
hickory-resolver = { version = "0.24.1", features = ["dns-over-rustls"] }
6767
moka = { version = "0.12.8", features = ["sync"] }
68+
der-parser = "9.0.0"
69+
regex = "1.10.6"
70+
bech32 = "0.11.0"
6871

6972
[dev-dependencies]
7073
hex = "0.4.3"
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# use with https://github.com/casey/just
2+
#
3+
# Cardano chain follower developer convenience functions
4+
5+
# Format the rust code
6+
code-format:
7+
cargo +nightly fmtfix
8+
cargo +nightly fmtchk
9+
10+
# Run long running developer test for mithril downloading.
11+
run-mithril-download-example-preprod: code-format
12+
cargo build -r --package cardano-chain-follower --example follow_chains --features mimalloc
13+
RUST_LOG="error,follow_chains=debug,cardano_chain_follower=debug,mithril-client=debug" \
14+
../target/release/examples/follow_chains --preprod
15+
16+
run-mithril-download-example-preprod-high-dl-bandwidth: code-format
17+
cargo build -r --package cardano-chain-follower --example follow_chains --features mimalloc
18+
RUST_LOG="error,follow_chains=debug,cardano_chain_follower=debug,mithril-client=debug" \
19+
../target/release/examples/follow_chains --preprod --mithril-sync-workers 64 --mithril-sync-chunk-size 16 --mithril-sync-queue-ahead=6
20+
21+
run-mithril-download-example-preprod-conservative-dl-bandwidth: code-format
22+
cargo build -r --package cardano-chain-follower --example follow_chains --features mimalloc
23+
RUST_LOG="error,follow_chains=debug,cardano_chain_follower=debug,mithril-client=debug" \
24+
../target/release/examples/follow_chains --preprod --mithril-sync-workers 8 --mithril-sync-chunk-size 1 --mithril-sync-queue-ahead=2
25+
26+
run-mithril-download-example-preview: code-format
27+
cargo build -r --package cardano-chain-follower --example follow_chains --features mimalloc
28+
RUST_LOG="error,follow_chains=debug,cardano_chain_follower=debug,mithril-client=debug" \
29+
../target/release/examples/follow_chains --preview
30+
31+
# Run long running developer test for mithril downloading.
32+
run-mithril-download-example-mainnet: code-format
33+
cargo build -r --package cardano-chain-follower --example follow_chains --features mimalloc
34+
RUST_LOG="error,follow_chains=debug,cardano_chain_follower=debug,mithril-client=debug" \
35+
../target/release/examples/follow_chains --mainnet
36+
37+
# Run long running developer test for mithril downloading.
38+
debug-heap-mithril-download-example:
39+
cargo build --package cardano-chain-follower --example follow_chains
40+
RUST_LOG="error,follow_chains=debug,cardano_chain_follower=debug,mithril-client=debug" \
41+
heaptrack ../target/debug/examples/follow_chains --preprod

rust/cardano-chain-follower/examples/follow_chains.rs

Lines changed: 99 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,13 @@ static GLOBAL: MiMalloc = MiMalloc;
1616
use std::{error::Error, time::Duration};
1717

1818
use cardano_chain_follower::{
19-
ChainFollower, ChainSyncConfig, ChainUpdate, Kind, Metadata, Network, Statistics, ORIGIN_POINT,
20-
TIP_POINT,
19+
ChainFollower, ChainSyncConfig, ChainUpdate, Kind,
20+
Metadata::{self},
21+
Network, Statistics, ORIGIN_POINT, TIP_POINT,
2122
};
2223
use clap::{arg, ArgAction, ArgMatches, Command};
2324
use tokio::time::Instant;
24-
use tracing::{error, info, level_filters::LevelFilter};
25+
use tracing::{error, info, level_filters::LevelFilter, warn};
2526
use tracing_subscriber::EnvFilter;
2627

2728
/// Process our CLI Arguments
@@ -39,7 +40,11 @@ fn process_argument() -> (Vec<Network>, ArgMatches) {
3940
.action(ArgAction::SetTrue),
4041
arg!(--"halt-on-error" "Stop the process when an error occurs without retrying.")
4142
.action(ArgAction::SetTrue),
42-
arg!(--"bad-cip36" "Dump Bad Cip36 registrations detected.")
43+
arg!(--"log-bad-cip36" "Dump Bad CIP36 registrations detected.")
44+
.action(ArgAction::SetTrue),
45+
arg!(--"log-cip509" "Dump CIP509 validation.")
46+
.action(ArgAction::SetTrue),
47+
arg!(--"log-raw-aux" "Dump raw auxiliary data.")
4348
.action(ArgAction::SetTrue),
4449
arg!(--"largest-metadata" "Dump The largest transaction metadata we find (as we find it).")
4550
.action(ArgAction::SetTrue),
@@ -146,7 +151,9 @@ async fn follow_for(network: Network, matches: ArgMatches) {
146151
let all_live_blocks = matches.get_flag("all-live-blocks");
147152
let stop_at_tip = matches.get_flag("stop-at-tip");
148153
let halt_on_error = matches.get_flag("halt-on-error");
149-
let bad_cip36 = matches.get_flag("bad-cip36");
154+
let log_bad_cip36 = matches.get_flag("log-bad-cip36");
155+
let log_cip509 = matches.get_flag("log-cip509");
156+
let log_raw_aux = matches.get_flag("log-raw-aux");
150157
let largest_metadata = matches.get_flag("largest-metadata");
151158

152159
let mut current_era = String::new();
@@ -235,44 +242,24 @@ async fn follow_for(network: Network, matches: ArgMatches) {
235242
}
236243

237244
// Inspect the transactions in the block.
238-
let mut dump_raw_aux_data = false;
239245
for (tx_idx, _tx) in block.txs().iter().enumerate() {
240-
if let Some(decoded_metadata) = chain_update
241-
.data
242-
.txn_metadata(tx_idx, Metadata::cip36::LABEL)
246+
if let Some(aux_data) =
247+
update_biggest_aux_data(&chain_update, tx_idx, largest_metadata, biggest_aux_data)
243248
{
244-
let raw_size = match chain_update
245-
.data
246-
.txn_raw_metadata(tx_idx, Metadata::cip36::LABEL)
247-
{
248-
Some(raw) => raw.len(),
249-
None => 0,
250-
};
251-
252-
if largest_metadata && raw_size > biggest_aux_data {
253-
biggest_aux_data = raw_size;
254-
dump_raw_aux_data = true;
255-
}
256-
257-
if bad_cip36 {
258-
#[allow(irrefutable_let_patterns)] // Won't always be irrefutable.
259-
if let Metadata::DecodedMetadataValues::Cip36(cip36) = &decoded_metadata.value {
260-
if !cip36.signed {
261-
dump_raw_aux_data = true;
262-
}
263-
if !decoded_metadata.report.is_empty() {
264-
info!(
265-
chain = network.to_string(),
266-
"Cip36 {tx_idx}:{:?} - {raw_size}", decoded_metadata
267-
);
268-
dump_raw_aux_data = true;
269-
}
270-
}
271-
}
249+
biggest_aux_data = aux_data;
250+
}
251+
252+
// If flag `log_bad_cip36` is set, log the bad CIP36.
253+
if log_bad_cip36 {
254+
log_bad_cip36_info(&chain_update, network, tx_idx);
255+
}
256+
// If flag `log_cip509` is set, log the CIP509 validation.
257+
if log_cip509 {
258+
log_cip509_info(&chain_update, block.number(), network, tx_idx);
272259
}
273260
}
274261

275-
if dump_raw_aux_data {
262+
if log_raw_aux {
276263
if let Some(x) = block.as_alonzo() {
277264
info!(
278265
chain = network.to_string(),
@@ -330,6 +317,80 @@ async fn follow_for(network: Network, matches: ArgMatches) {
330317
info!(chain = network.to_string(), "Following Completed.");
331318
}
332319

320+
/// Helper function for updating the biggest aux data.
321+
fn update_biggest_aux_data(
322+
chain_update: &ChainUpdate, tx_idx: usize, largest_metadata: bool, biggest_aux_data: usize,
323+
) -> Option<usize> {
324+
let raw_size_cip36 = match chain_update
325+
.data
326+
.txn_raw_metadata(tx_idx, Metadata::cip36::LABEL)
327+
{
328+
Some(raw) => raw.len(),
329+
None => 0,
330+
};
331+
332+
let raw_size_cip509 = match chain_update
333+
.data
334+
.txn_raw_metadata(tx_idx, Metadata::cip509::LABEL)
335+
{
336+
Some(raw) => raw.len(),
337+
None => 0,
338+
};
339+
340+
// Get the maximum raw size from both cip36 and cip509
341+
let raw_size = raw_size_cip36.max(raw_size_cip509);
342+
343+
if largest_metadata && raw_size > biggest_aux_data {
344+
return Some(raw_size);
345+
}
346+
347+
None
348+
}
349+
350+
/// Helper function for logging bad CIP36.
351+
fn log_bad_cip36_info(chain_update: &ChainUpdate, network: Network, tx_idx: usize) {
352+
if let Some(decoded_metadata) = chain_update
353+
.data
354+
.txn_metadata(tx_idx, Metadata::cip36::LABEL)
355+
{
356+
if let Metadata::DecodedMetadataValues::Cip36(cip36) = &decoded_metadata.value {
357+
if (!cip36.signed || !decoded_metadata.report.is_empty())
358+
&& !decoded_metadata.report.is_empty()
359+
{
360+
info!(
361+
chain = network.to_string(),
362+
"CIP36 {tx_idx}: {:?}", decoded_metadata
363+
);
364+
}
365+
}
366+
}
367+
}
368+
369+
/// Helper function for logging CIP509 validation.
370+
fn log_cip509_info(chain_update: &ChainUpdate, block_num: u64, network: Network, tx_idx: usize) {
371+
if let Some(decoded_metadata) = chain_update
372+
.data
373+
.txn_metadata(tx_idx, Metadata::cip509::LABEL)
374+
{
375+
info!("Block Number {}", block_num);
376+
377+
if let Metadata::DecodedMetadataValues::Cip509(cip509) = &decoded_metadata.value {
378+
info!(
379+
chain = network.to_string(),
380+
"CIP509 {tx_idx}: {:?}", cip509.validation
381+
);
382+
}
383+
384+
// If report is not empty, log it, log it as a warning.
385+
if !decoded_metadata.report.is_empty() {
386+
warn!(
387+
chain = network.to_string(),
388+
"CIP509 {tx_idx}: {:?}", decoded_metadata.report
389+
);
390+
}
391+
}
392+
}
393+
333394
#[tokio::main]
334395
async fn main() -> Result<(), Box<dyn Error>> {
335396
tracing_subscriber::fmt()

rust/cardano-chain-follower/src/metadata/cip36.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,12 @@ impl Cip36 {
7979
/// * `decoded_metadata` - Decoded Metadata - Will be updated only if CIP36 Metadata
8080
/// is found.
8181
/// * `slot` - Current Slot
82-
/// * `txn` - Transaction Aux data was attached to and to be validated/decoded
83-
/// against. Not used for CIP36 Metadata.
82+
/// * `txn` - Transaction data was attached to and to be validated/decoded against.
83+
/// Not used for CIP36 Metadata.
8484
/// * `raw_aux_data` - Raw Auxiliary Data for the transaction.
8585
/// * `catalyst_strict` - Strict Catalyst Validation - otherwise Catalyst Specific
8686
/// rules/workarounds are not applied.
87+
/// * `chain` - Network Chain
8788
///
8889
/// # Returns
8990
///

rust/cardano-chain-follower/src/metadata/cip509.rs

Lines changed: 0 additions & 82 deletions
This file was deleted.

0 commit comments

Comments
 (0)