Skip to content

Commit dba341c

Browse files
committed
feat(rust): add cardano-blockchain-types crate
1 parent 0aeadb9 commit dba341c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+2920
-1
lines changed

.config/dictionaries/project.dic

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Arissara
1010
asyncio
1111
Attributes
1212
auditability
13+
auxdata
1314
babystep
1415
backpressure
1516
bech

rust/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
resolver = "2"
33
members = [
44
"c509-certificate",
5+
"cardano-blockchain-types",
56
"cardano-chain-follower",
67
"hermes-ipfs",
78
"cbork",

rust/Earthfile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ COPY_SRC:
99
Cargo.toml clippy.toml deny.toml rustfmt.toml \
1010
.cargo .config \
1111
c509-certificate \
12+
cardano-blockchain-types \
1213
cardano-chain-follower \
1314
catalyst-voting vote-tx-v1 vote-tx-v2 \
1415
cbork cbork-abnf-parser cbork-cddl-parser \
@@ -53,7 +54,7 @@ build:
5354

5455
DO rust-ci+EXECUTE \
5556
--cmd="/scripts/std_build.py" \
56-
--args1="--libs=c509-certificate --libs=cardano-chain-follower --libs=hermes-ipfs" \
57+
--args1="--libs=c509-certificate --libs=cardano-blockchain-types --libs=cardano-chain-follower --libs=hermes-ipfs" \
5758
--args2="--libs=cbork-cddl-parser --libs=cbork-abnf-parser" \
5859
--args3="--libs=catalyst-voting --libs=vote-tx-v1 --libs=vote-tx-v2" \
5960
--args4="--bins=cbork/cbork --libs=rbac-registration --libs=signed_doc" \
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
[package]
2+
name = "cardano-blockchain-types"
3+
description = "Common Cardano Blockchain data types for use in both applications and crates"
4+
keywords = ["cardano", "catalyst",]
5+
version = "0.0.1"
6+
authors = [
7+
"Steven Johnson <[email protected]>"
8+
]
9+
edition.workspace = true
10+
license.workspace = true
11+
homepage.workspace = true
12+
repository.workspace = true
13+
14+
[lib]
15+
crate-type = ["cdylib", "rlib"]
16+
17+
[lints]
18+
workspace = true
19+
20+
[dependencies]
21+
pallas = { version = "0.30.1", git = "https://github.com/input-output-hk/catalyst-pallas.git", rev = "9b5183c8b90b90fe2cc319d986e933e9518957b3" }
22+
pallas-hardano = { version = "0.30.1", git = "https://github.com/input-output-hk/catalyst-pallas.git", rev = "9b5183c8b90b90fe2cc319d986e933e9518957b3" }
23+
pallas-crypto = { version = "0.30.1", git = "https://github.com/input-output-hk/catalyst-pallas.git", rev = "9b5183c8b90b90fe2cc319d986e933e9518957b3" }
24+
25+
ouroboros = "0.18.4"
26+
tracing = "0.1.41"
27+
anyhow = "1.0.94"
28+
chrono = "0.4.39"
29+
strum = { version = "0.26.3", features = ["derive"] }
30+
strum_macros = "0.26.4"
31+
dirs = "5.0.1"
32+
hex = "0.4.3"
33+
dashmap = "6.1.0"
34+
blake2b_simd = "1.0.2"
35+
minicbor = { version = "0.25.1", features = ["alloc"] }
36+
num-traits = "0.2.19"
37+
ed25519-dalek = "2.1.1"
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
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Improved version of Pallas Multi Era Block
2+
3+
Adds features to the Pallas Multi Era Block to allow us to re-use it between the different cardano crates,
4+
and the services that use them.
5+
6+
The original source was `cardano-chain-follower`.
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
2+
rbac-registration = { version = "0.0.2", git = "https://github.com/input-output-hk/catalyst-libs.git", tag = "v0.0.8" }
3+
4+
thiserror = "1.0.64"
5+
tokio = { version = "1.40.0", features = [
6+
"macros",
7+
"rt",
8+
"net",
9+
"rt-multi-thread",
10+
] }
11+
tracing = "0.1.40"
12+
tracing-log = "0.2.0"
13+
dashmap = "6.1.0"
14+
url = "2.5.2"
15+
anyhow = "1.0.89"
16+
chrono = "0.4.38"
17+
async-trait = "0.1.83"
18+
dirs = "5.0.1"
19+
futures = "0.3.31"
20+
humantime = "2.1.0"
21+
crossbeam-skiplist = "0.1.3"
22+
crossbeam-channel = "0.5.13"
23+
crossbeam-epoch = "0.9.18"
24+
strum = "0.26.3"
25+
ouroboros = "0.18.4"
26+
hex = "0.4.3"
27+
rayon = "1.10.0"
28+
serde = "1.0.210"
29+
serde_json = "1.0.128"
30+
mimalloc = { version = "0.1.43", optional = true }
31+
memx = "0.1.32"
32+
fmmap = { version = "0.3.3", features = ["sync", "tokio-async"] }
33+
minicbor = { version = "0.25.1", features = ["alloc", "derive", "half"] }
34+
zstd = "0.13.2"
35+
ed25519-dalek = "2.1.1"
36+
blake2b_simd = "1.0.2"
37+
num-traits = "0.2.19"
38+
logcall = "0.1.9"
39+
tar = "0.4.42"
40+
ureq = { version = "2.10.1", features = ["native-certs"] }
41+
http = "1.1.0"
42+
hickory-resolver = { version = "0.24.1", features = ["dns-over-rustls"] }
43+
moka = { version = "0.12.8", features = ["sync"] }
44+
45+
hex = "0.4.3"
46+
anyhow = "1.0.89"
47+
strum_macros = "0.26.4"
48+
regex = "1.11.0"
49+
minicbor = { version = "0.25.1", features = ["alloc", "derive", "half"] }
50+
brotli = "7.0.0"
51+
zstd = "0.13.2"
52+
x509-cert = "0.2.5"
53+
der-parser = "9.0.0"
54+
bech32 = "0.11.0"
55+
dashmap = "6.1.0"
56+
blake2b_simd = "1.0.2"
57+
tracing = "0.1.40"
58+
ed25519-dalek = "2.1.1"
59+
uuid = "1.11.0"
60+
61+
c509-certificate = { version = "0.0.3", git = "https://github.com/input-output-hk/catalyst-libs.git" , tag = "v0.0.3" }
62+
pallas = { version = "0.30.1", git = "https://github.com/input-output-hk/catalyst-pallas.git", rev = "9b5183c8b90b90fe2cc319d986e933e9518957b3" }
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
//! Auxiliary Data Decoding
2+
3+
use minicbor::Decode;
4+
5+
use super::{
6+
metadatum::Metadata,
7+
metadatum_label::MetadatumLabel,
8+
metadatum_value::MetadatumValue,
9+
scripts::{MutableTransactionScriptsMap, ScriptArray, ScriptType, TransactionScripts},
10+
};
11+
12+
/// Auxiliary Data (Metadata) for a single Transaction in a block
13+
#[derive(Clone, Debug)]
14+
#[allow(clippy::module_name_repetitions)]
15+
pub struct TransactionAuxData {
16+
/// Metadata attached to a transaction
17+
metadata: Metadata,
18+
/// Scripts attached to a transaction
19+
#[allow(dead_code)]
20+
scripts: TransactionScripts,
21+
}
22+
23+
impl Decode<'_, ()> for TransactionAuxData {
24+
fn decode(
25+
d: &mut minicbor::Decoder<'_>, _ctx: &mut (),
26+
) -> Result<Self, minicbor::decode::Error> {
27+
// Check what kind of aux data we have to deal with
28+
match d.datatype() {
29+
// Shelley: https://github.com/IntersectMBO/cardano-ledger/blob/78b32d585fd4a0340fb2b184959fb0d46f32c8d2/eras/conway/impl/cddl-files/conway.cddl#L522
30+
Ok(minicbor::data::Type::Map) => {
31+
Ok(TransactionAuxData {
32+
metadata: Metadata::decode(d, &mut ())?,
33+
scripts: TransactionScripts::default(),
34+
})
35+
},
36+
// Shelley-MA: https://github.com/IntersectMBO/cardano-ledger/blob/78b32d585fd4a0340fb2b184959fb0d46f32c8d2/eras/conway/impl/cddl-files/conway.cddl#L523
37+
Ok(minicbor::data::Type::Array) => Self::decode_shelley_ma_array(d),
38+
// Maybe Alonzo and beyond: https://github.com/IntersectMBO/cardano-ledger/blob/78b32d585fd4a0340fb2b184959fb0d46f32c8d2/eras/conway/impl/cddl-files/conway.cddl#L526
39+
Ok(minicbor::data::Type::Tag) => Self::decode_alonzo_plus_map(d),
40+
Ok(unexpected) => {
41+
let msg = format!(
42+
"Error decoding Transaction Aux Data: Unexpected datatype {unexpected}"
43+
);
44+
Err(minicbor::decode::Error::message(&msg))
45+
},
46+
Err(error) => {
47+
let msg = format!("Error decoding Transaction Aux Data: {error}");
48+
Err(minicbor::decode::Error::message(msg))
49+
},
50+
}
51+
}
52+
}
53+
54+
impl TransactionAuxData {
55+
/// Get metadata with the given label.
56+
#[must_use]
57+
pub fn metadata(&self, label: MetadatumLabel) -> Option<&MetadatumValue> {
58+
self.metadata.get(label)
59+
}
60+
61+
/// Decode a Shelley-MA Auxiliary Data Array
62+
fn decode_shelley_ma_array(d: &mut minicbor::Decoder) -> Result<Self, minicbor::decode::Error> {
63+
match d.array() {
64+
Ok(Some(entries)) => {
65+
if entries != 2 {
66+
let msg = format!(
67+
"Error decoding Transaction Aux Data: Script Data Array Expected 2 entries, found {entries}."
68+
);
69+
return Err(minicbor::decode::Error::message(&msg));
70+
}
71+
},
72+
Ok(None) => {
73+
return Err(minicbor::decode::Error::message(
74+
"Error decoding Transaction Aux Data: Indefinite Array found decoding Metadata. Invalid."));
75+
},
76+
Err(error) => {
77+
return Err(minicbor::decode::Error::message(format!(
78+
"Error decoding Transaction Aux Data: {error}."
79+
)));
80+
},
81+
};
82+
83+
let metadata = Metadata::decode(d, &mut ())?;
84+
let script_array = ScriptArray::decode(d, &mut ScriptType::Native)?;
85+
86+
let scripts = MutableTransactionScriptsMap::default();
87+
scripts.insert(ScriptType::Native, script_array);
88+
89+
Ok(Self {
90+
metadata,
91+
scripts: scripts.into(),
92+
})
93+
}
94+
95+
/// Decode an Alonzo Plus MAP
96+
fn decode_alonzo_plus_map(d: &mut minicbor::Decoder) -> Result<Self, minicbor::decode::Error> {
97+
match d.tag() {
98+
Ok(tag) => {
99+
if tag.as_u64() != 259 {
100+
return Err(minicbor::decode::Error::message(format!(
101+
"Invalid tag for Alonzo+ Aux Data. Expected 259, found {tag}."
102+
)));
103+
}
104+
},
105+
Err(error) => {
106+
return Err(minicbor::decode::Error::message(format!(
107+
"Error decoding Transaction Alonzo+ Aux Data: {error}."
108+
)));
109+
},
110+
}
111+
112+
let entries = match d.map() {
113+
Ok(Some(entries)) => entries,
114+
Ok(None) => {
115+
return Err(minicbor::decode::Error::message(
116+
"Indefinite Map found decoding Alonzo+ Metadata. Invalid.",
117+
))
118+
},
119+
Err(error) => {
120+
return Err(minicbor::decode::Error::message(format!(
121+
"Error decoding Transaction Alonzo+ Aux Data: {error}."
122+
)))
123+
},
124+
};
125+
126+
// Make the default versions of the metadata and script types
127+
let mut metadata = Metadata::default();
128+
let scripts = MutableTransactionScriptsMap::default();
129+
130+
// iterate the map
131+
for _ in 0..entries {
132+
let script_type = match d.u64() {
133+
Ok(key) => {
134+
if let Ok(script_type) = ScriptType::try_from(key) {
135+
script_type
136+
} else {
137+
// Only fails if its Metadata and not a script.
138+
if metadata.is_empty() {
139+
metadata = Metadata::decode(d, &mut ())?;
140+
continue;
141+
}
142+
return Err(minicbor::decode::Error::message(
143+
"Multiple Alonzo+ Metadata entries found. Invalid.",
144+
));
145+
}
146+
},
147+
148+
Err(error) => {
149+
return Err(minicbor::decode::Error::message(format!(
150+
"Error decoding Alonzo+ Metadata Aux Data Type Key: {error}"
151+
)));
152+
},
153+
};
154+
155+
let mut ctx = script_type;
156+
157+
let script_array = ScriptArray::decode(d, &mut ctx)?;
158+
if scripts.insert(script_type, script_array).is_some() {
159+
return Err(minicbor::decode::Error::message(
160+
"Multiple Alonzo+ Script entries of type {script_type} found. Invalid.",
161+
));
162+
}
163+
}
164+
165+
Ok(Self {
166+
metadata,
167+
scripts: scripts.into(),
168+
})
169+
}
170+
}

0 commit comments

Comments
 (0)