Skip to content

Commit 654cd6d

Browse files
committed
Merge branch 'main' into wip/document-schemas
2 parents 52cf095 + 698afa3 commit 654cd6d

File tree

17 files changed

+320
-180
lines changed

17 files changed

+320
-180
lines changed

.github/workflows/ci.yml

+3-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ on:
77
types:
88
- synchronize
99
- ready_for_review
10+
- opened
1011

1112

1213
permissions:
@@ -17,11 +18,12 @@ permissions:
1718

1819
jobs:
1920
ci:
21+
if: ${{ !github.event.pull_request.draft }}
2022
uses: input-output-hk/catalyst-forge/.github/workflows/ci.yml@ci/v1.7.1
2123
with:
2224
forge_version: 0.8.0
2325

2426
test_reporting:
25-
if: always()
27+
if: ${{ !github.event.pull_request.draft }}
2628
needs: ci
2729
uses: ./.github/workflows/generate-allure-report.yml

rust/cardano-blockchain-types/Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ workspace = true
2020
[dependencies]
2121
pallas = { version = "0.30.1", git = "https://github.com/input-output-hk/catalyst-pallas.git", rev = "9b5183c8b90b90fe2cc319d986e933e9518957b3" }
2222
# pallas-hardano = { version = "0.30.1", git = "https://github.com/input-output-hk/catalyst-pallas.git", rev = "9b5183c8b90b90fe2cc319d986e933e9518957b3" }
23-
cbork-utils = { version = "0.0.1", git = "https://github.com/input-output-hk/catalyst-libs.git", tag = "r20250226-00" }
24-
catalyst-types = { version = "0.0.3", git = "https://github.com/input-output-hk/catalyst-libs.git", tag = "r20250226-00" }
23+
cbork-utils = { version = "0.0.1", path = "../cbork-utils" }
24+
catalyst-types = { version = "0.0.3", path = "../catalyst-types" }
2525

2626
ouroboros = "0.18.4"
2727
tracing = "0.1.41"

rust/cardano-blockchain-types/src/metadata/cip36/key_registration.rs

+31-25
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use catalyst_types::{
1212
use cbork_utils::decode_helper::{decode_array_len, decode_bytes, decode_helper, decode_map_len};
1313
use ed25519_dalek::VerifyingKey;
1414
use minicbor::{decode, Decode, Decoder};
15-
use pallas::ledger::addresses::{Address, ShelleyAddress};
15+
use pallas::ledger::addresses::Address;
1616
use strum::FromRepr;
1717

1818
use super::voting_pk::VotingPubKey;
@@ -45,23 +45,28 @@ pub(crate) struct Cip36KeyRegistration {
4545
/// Payment Address to associate with the voting keys.
4646
/// Field 3 in the CIP-36 61284 Spec.
4747
/// None if it is not set.
48-
pub payment_addr: Option<ShelleyAddress>,
48+
pub payment_addr: Option<Address>,
4949
/// Nonce (nonce that has been slot corrected).
50-
/// Field 4 in the CIP-36 61284 Spec.
5150
/// None if it is not set.
5251
pub nonce: Option<u64>,
5352
/// Registration Purpose (Always 0 for Catalyst).
5453
/// Field 5 in the CIP-36 61284 Spec.
5554
/// Default to 0.
5655
pub purpose: u64,
5756
/// Raw nonce (nonce that has not had slot correction applied).
57+
/// Field 4 in the CIP-36 61284 Spec.
5858
/// None if it is not set.
5959
pub raw_nonce: Option<u64>,
6060
/// Is payment address payable? (not a script)
6161
/// None if it is not set.
6262
pub is_payable: Option<bool>,
6363
}
6464

65+
/// Header type of Shelley address that are consider as payable.
66+
/// Payable if payment part is a `PaymentKeyHash`
67+
/// <https://cips.cardano.org/cip/CIP-19>
68+
const VALID_PAYABLE_HEADER: [u8; 4] = [0, 2, 4, 6];
69+
6570
/// Enum of CIP36 registration (61284) with its associated unsigned integer key.
6671
#[derive(FromRepr, Debug, PartialEq)]
6772
#[repr(u16)]
@@ -111,12 +116,12 @@ impl Decode<'_, ProblemReport> for Cip36KeyRegistration {
111116
cip36_key_registration.stake_pk = stake_pk;
112117
},
113118
Cip36KeyRegistrationKeys::PaymentAddr => {
114-
let shelley_addr = decode_payment_addr(d, err_report)?;
115-
cip36_key_registration.is_payable = shelley_addr
119+
let address = decode_payment_addr(d, err_report)?;
120+
cip36_key_registration.is_payable = address
116121
.as_ref()
117-
.map(|addr| !addr.payment().is_script())
122+
.map(|addr| VALID_PAYABLE_HEADER.contains(&addr.typeid()))
118123
.or(None);
119-
cip36_key_registration.payment_addr = shelley_addr;
124+
cip36_key_registration.payment_addr = address;
120125
},
121126
Cip36KeyRegistrationKeys::Nonce => {
122127
cip36_key_registration.raw_nonce = Some(decode_nonce(d)?);
@@ -294,16 +299,29 @@ fn decode_stake_pk(
294299
///
295300
/// # Returns
296301
///
297-
/// - The payment address as a `ShelleyAddress`.
298-
/// - None if cannot converted `Vec<u8>` to `ShelleyAddress`.
302+
/// - The payment address as a `Address`.
303+
/// - None if cannot converted `Vec<u8>` to `Address` or the address is a Byron address.
299304
/// - Error if decoding failed.
300305
fn decode_payment_addr(
301306
d: &mut Decoder, err_report: &ProblemReport,
302-
) -> Result<Option<ShelleyAddress>, decode::Error> {
307+
) -> Result<Option<Address>, decode::Error> {
303308
let raw_addr = decode_bytes(d, "CIP36 Key Registration payment address")?;
304309
// Cannot convert raw address to Address type
305-
let address = match Address::from_bytes(&raw_addr) {
306-
Ok(addr) => addr,
310+
match Address::from_bytes(&raw_addr) {
311+
Ok(addr) => {
312+
match addr {
313+
Address::Byron(byron_address) => {
314+
err_report.invalid_value(
315+
"Address",
316+
format!("{byron_address:?}").as_str(),
317+
"Expected non Byron address",
318+
"CIP36 Key Registration payment address",
319+
);
320+
Ok(None)
321+
},
322+
_ => Ok(Some(addr)),
323+
}
324+
},
307325
Err(e) => {
308326
err_report.conversion_error(
309327
"Cardano address",
@@ -312,20 +330,8 @@ fn decode_payment_addr(
312330
"CIP36 Key Registration payment address",
313331
);
314332
// Can't process any further
315-
return Ok(None);
333+
Ok(None)
316334
},
317-
};
318-
319-
if let Address::Shelley(addr) = address {
320-
Ok(Some(addr.clone()))
321-
} else {
322-
err_report.invalid_value(
323-
"Shelley Address",
324-
format!("{address}").as_str(),
325-
"Expected Shelley address",
326-
"CIP36 Key Registration payment address",
327-
);
328-
Ok(None)
329335
}
330336
}
331337

rust/cardano-blockchain-types/src/metadata/cip36/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@ use catalyst_types::problem_report::ProblemReport;
1010
use ed25519_dalek::VerifyingKey;
1111
use key_registration::Cip36KeyRegistration;
1212
use minicbor::{Decode, Decoder};
13-
use pallas::ledger::addresses::ShelleyAddress;
13+
use pallas::ledger::addresses::Address;
1414
use registration_witness::Cip36RegistrationWitness;
1515
use voting_pk::VotingPubKey;
1616

1717
use crate::{MetadatumLabel, MultiEraBlock, Network, Slot, TxnIndex};
1818

1919
/// CIP-36 Catalyst registration
20-
#[derive(Clone)]
20+
#[derive(Debug, Clone)]
2121
#[allow(clippy::struct_excessive_bools)]
2222
pub struct Cip36 {
2323
/// Key registration - 61284
@@ -247,7 +247,7 @@ impl Cip36 {
247247

248248
/// Get the payment address from the registration.
249249
#[must_use]
250-
pub fn payment_address(&self) -> Option<&ShelleyAddress> {
250+
pub fn payment_address(&self) -> Option<&Address> {
251251
self.key_registration.payment_addr.as_ref()
252252
}
253253

rust/cardano-blockchain-types/src/metadata/cip36/validation.rs

+12-9
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,16 @@ impl Cip36 {
7474
return;
7575
};
7676
// Extract the network tag and validate
77-
let network_tag = address.network();
77+
let Some(network_tag) = address.network() else {
78+
// Byron address don't have network tag
79+
self.err_report.missing_field(
80+
"Network tag",
81+
"Validate CIP36 payment address network, network tag not found",
82+
);
83+
self.is_valid_payment_address_network = false;
84+
return;
85+
};
86+
7887
let valid = match self.network {
7988
Network::Mainnet => network_tag.value() == 1,
8089
Network::Preprod | Network::Preview => network_tag.value() == 0,
@@ -164,12 +173,9 @@ mod tests {
164173
// cSpell:disable
165174
let addr = Address::from_bech32("addr_test1qprhw4s70k0vzyhvxp6h97hvrtlkrlcvlmtgmaxdtjz87xrjkctk27ypuv9dzlzxusqse89naweygpjn5dxnygvus05sdq9h07").expect("Failed to create address");
166175
// cSpell:enable
167-
let Address::Shelley(shelley_addr) = addr else {
168-
panic!("Invalid address type")
169-
};
170176
let mut cip36 = create_cip36();
171177
cip36.key_registration = Cip36KeyRegistration {
172-
payment_addr: Some(shelley_addr),
178+
payment_addr: Some(addr),
173179
..Default::default()
174180
};
175181
cip36.validate_payment_address_network();
@@ -183,13 +189,10 @@ mod tests {
183189
// cSpell:disable
184190
let addr = Address::from_bech32("addr_test1qprhw4s70k0vzyhvxp6h97hvrtlkrlcvlmtgmaxdtjz87xrjkctk27ypuv9dzlzxusqse89naweygpjn5dxnygvus05sdq9h07").expect("Failed to create address");
185191
// cSpell:enable
186-
let Address::Shelley(shelley_addr) = addr else {
187-
panic!("Invalid address type")
188-
};
189192
let mut cip36 = create_cip36();
190193
cip36.network = Network::Mainnet;
191194
cip36.key_registration = Cip36KeyRegistration {
192-
payment_addr: Some(shelley_addr),
195+
payment_addr: Some(addr),
193196
..Default::default()
194197
};
195198
cip36.validate_payment_address_network();

rust/cardano-blockchain-types/src/stake_address.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use std::fmt::{Display, Formatter};
66

77
use anyhow::{anyhow, Context};
8+
use catalyst_types::hashes::Blake2b224Hash;
89
use pallas::{
910
crypto::hash::Hash,
1011
ledger::{
@@ -26,8 +27,9 @@ impl StakeAddress {
2627
/// Creates a new instance from the given parameters.
2728
#[allow(clippy::expect_used, clippy::missing_panics_doc)]
2829
#[must_use]
29-
pub fn new(network: Network, is_script: bool, hash: Hash<28>) -> Self {
30+
pub fn new(network: Network, is_script: bool, stake_pk_hash: Blake2b224Hash) -> Self {
3031
let network = network.into();
32+
let hash = stake_pk_hash.into();
3133
// `pallas::StakeAddress` can only be constructed from `ShelleyAddress`, so we are forced
3234
// to create a dummy shelley address. The input hash parameter is used to construct both
3335
// payment and delegation parts, but the payment part isn't used in the stake address
@@ -49,8 +51,8 @@ impl StakeAddress {
4951
#[must_use]
5052
pub fn from_stake_cred(network: Network, cred: &conway::StakeCredential) -> Self {
5153
match cred {
52-
conway::StakeCredential::Scripthash(h) => Self::new(network, true, *h),
53-
conway::StakeCredential::AddrKeyhash(h) => Self::new(network, false, *h),
54+
conway::StakeCredential::Scripthash(h) => Self::new(network, true, (*h).into()),
55+
conway::StakeCredential::AddrKeyhash(h) => Self::new(network, false, (*h).into()),
5456
}
5557
}
5658

@@ -111,7 +113,7 @@ impl TryFrom<&[u8]> for StakeAddress {
111113
v => return Err(anyhow!("Unexpected type value: {v}, header = {header}")),
112114
};
113115

114-
Ok(Self::new(network, is_script, hash))
116+
Ok(Self::new(network, is_script, hash.into()))
115117
}
116118
}
117119

@@ -155,7 +157,7 @@ mod tests {
155157
];
156158

157159
for (network, is_script, hash, expected_header) in test_data {
158-
let stake_address = StakeAddress::new(network, is_script, hash);
160+
let stake_address = StakeAddress::new(network, is_script, hash.into());
159161
assert_eq!(stake_address.is_script(), is_script);
160162

161163
// Check that conversion to bytes includes the expected header value.
@@ -227,7 +229,7 @@ mod tests {
227229
// cSpell:enable
228230

229231
for (network, is_script, hash, expected) in test_data {
230-
let address = StakeAddress::new(network, is_script, hash);
232+
let address = StakeAddress::new(network, is_script, hash.into());
231233
assert_eq!(expected, format!("{address}"));
232234
}
233235
}

rust/cardano-blockchain-types/src/txn_index.rs

+6
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@ impl From<TxnIndex> for usize {
3131
}
3232
}
3333

34+
impl From<TxnIndex> for u16 {
35+
fn from(value: TxnIndex) -> Self {
36+
value.0
37+
}
38+
}
39+
3440
#[cfg(test)]
3541
mod tests {
3642
use super::*;

rust/cardano-chain-follower/Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ mithril-client = { version = "0.10.4", default-features = false, features = [
1919
"full",
2020
"num-integer-backend",
2121
] }
22-
cardano-blockchain-types = { version = "0.0.3", git = "https://github.com/input-output-hk/catalyst-libs.git", tag = "r20250226-00" }
23-
catalyst-types = { version = "0.0.3", git = "https://github.com/input-output-hk/catalyst-libs.git", tag = "r20250226-00" }
22+
cardano-blockchain-types = { version = "0.0.3", path = "../cardano-blockchain-types" }
23+
catalyst-types = { version = "0.0.3", path = "../catalyst-types" }
2424

2525

2626
thiserror = "1.0.69"

rust/cardano-chain-follower/src/chain_sync.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -561,7 +561,7 @@ pub(crate) async fn chain_sync(cfg: ChainSyncConfig, rx: mpsc::Receiver<MithrilU
561561
// Note: This can ONLY return with an error, otherwise it will sync indefinitely.
562562
if let Err(error) = follow_chain(&mut peer, cfg.chain, &mut fork_count).await {
563563
error!(
564-
"Cardano Client {} failed to follow chain: {}: Reconnecting.",
564+
"Cardano Client {} failed to follow chain: {:?}: Reconnecting.",
565565
cfg.relay_address, error
566566
);
567567
continue;

rust/catalyst-types/src/hashes.rs

+7
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,13 @@ impl<const BYTES: usize> From<Hash<BYTES>> for Blake2bHash<BYTES> {
8484
}
8585
}
8686

87+
impl<const BYTES: usize> From<Blake2bHash<BYTES>> for Hash<BYTES> {
88+
#[inline]
89+
fn from(hash: Blake2bHash<BYTES>) -> Self {
90+
hash.0
91+
}
92+
}
93+
8794
impl<const BYTES: usize> From<Blake2bHash<BYTES>> for Vec<u8> {
8895
fn from(val: Blake2bHash<BYTES>) -> Self {
8996
val.0.to_vec()

rust/rbac-registration/Cargo.toml

+4-4
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ tracing = "0.1.40"
3030
ed25519-dalek = "2.1.1"
3131
uuid = "1.11.0"
3232

33-
c509-certificate = { version = "0.0.3", git = "https://github.com/input-output-hk/catalyst-libs.git", tag = "r20250226-00" }
33+
c509-certificate = { version = "0.0.3", path = "../c509-certificate" }
3434
pallas = { version = "0.30.1", git = "https://github.com/input-output-hk/catalyst-pallas.git", rev = "9b5183c8b90b90fe2cc319d986e933e9518957b3" }
35-
cbork-utils = { version = "0.0.1", git = "https://github.com/input-output-hk/catalyst-libs.git", tag = "r20250226-00" }
36-
cardano-blockchain-types = { version = "0.0.3", git = "https://github.com/input-output-hk/catalyst-libs.git", tag = "r20250226-00" }
37-
catalyst-types = { version = "0.0.3", git = "https://github.com/input-output-hk/catalyst-libs.git", tag = "r20250226-00" }
35+
cbork-utils = { version = "0.0.1", path = "../cbork-utils" }
36+
cardano-blockchain-types = { version = "0.0.3", path = "../cardano-blockchain-types" }
37+
catalyst-types = { version = "0.0.3", path = "../catalyst-types" }

rust/rbac-registration/src/cardano/cip509/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ pub use cip509::Cip509;
66
#[allow(clippy::module_name_repetitions)]
77
pub use rbac::{C509Cert, Cip509RbacMetadata, SimplePublicKeyType, X509DerCert};
88
pub use types::{
9-
CertKeyHash, KeyLocalRef, LocalRefInt, Payment, PaymentHistory, PointTxnIdx, RoleData,
10-
RoleNumber, TxInputHash, ValidationSignature,
9+
CertKeyHash, KeyLocalRef, LocalRefInt, Payment, PaymentHistory, PointData, PointTxnIdx,
10+
RoleData, RoleNumber, TxInputHash, ValidationSignature,
1111
};
1212
pub use utils::Cip0134UriSet;
1313

rust/rbac-registration/src/cardano/cip509/types/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
pub use cert_key_hash::CertKeyHash;
44
pub use key_local_ref::{KeyLocalRef, LocalRefInt};
55
pub use payment_history::{Payment, PaymentHistory};
6+
pub use point_data::PointData;
67
pub use point_tx_idx::PointTxnIdx;
78
pub use role_data::RoleData;
89
pub use role_number::RoleNumber;
@@ -12,6 +13,7 @@ pub use validation_signature::ValidationSignature;
1213
mod cert_key_hash;
1314
mod key_local_ref;
1415
mod payment_history;
16+
mod point_data;
1517
mod point_tx_idx;
1618
mod role_data;
1719
mod role_number;

0 commit comments

Comments
 (0)