Skip to content
5 changes: 4 additions & 1 deletion rust/c509-certificate/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,10 @@ mod test {
fn test_generate_and_verify_signed_c509_cert() {
let tbs_cert = tbs();

let private_key = FromStr::from_str(&private_key_str()).expect("Cannot create private key");
let private_key = FromStr::from_str(&private_key_str()).expect(
"Cannot create
private key",
);

let signed_c509 = generate(&tbs_cert, Some(&private_key))
.expect("Failed to generate signed C509 certificate");
Expand Down
168 changes: 73 additions & 95 deletions rust/cardano-chain-follower/src/metadata/cip509/decode_helper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,86 +2,52 @@

use minicbor::{data::Tag, decode, Decoder};

/// Helper function for decoding map.
pub(crate) fn decode_map_len(d: &mut Decoder, from: &str) -> Result<u64, decode::Error> {
d.map()
.map_err(|e| decode::Error::message(format!("Failed to decode map in {from}: {e}")))?
.ok_or(decode::Error::message(format!(
"Failed to decode map in {from}, unexpected indefinite length",
)))
}

/// Helper function for decoding u8.
pub(crate) fn decode_u8(d: &mut Decoder, from: &str) -> Result<u8, decode::Error> {
d.u8()
.map_err(|e| decode::Error::message(format!("Failed to decode u8 in {from}: {e}")))
}

/// Helper function for decoding u16.
pub(crate) fn decode_u16(d: &mut Decoder, from: &str) -> Result<u16, decode::Error> {
d.u16()
.map_err(|e| decode::Error::message(format!("Failed to decode u16 in {from}: {e}")))
}

/// Helper function for decoding u32.
pub(crate) fn decode_u32(d: &mut Decoder, from: &str) -> Result<u32, decode::Error> {
d.u32()
.map_err(|e| decode::Error::message(format!("Failed to decode u32 in {from}: {e}")))
}

/// Helper function for decoding u64.
pub(crate) fn decode_u64(d: &mut Decoder, from: &str) -> Result<u64, decode::Error> {
d.u64()
.map_err(|e| decode::Error::message(format!("Failed to decode u64 in {from}: {e}")))
}

/// Helper function for decoding i8.
pub(crate) fn decode_i8(d: &mut Decoder, from: &str) -> Result<i8, decode::Error> {
d.i8()
.map_err(|e| decode::Error::message(format!("Failed to decode i8 in {from}: {e}")))
}

/// Helper function for decoding i16.
pub(crate) fn decode_i16(d: &mut Decoder, from: &str) -> Result<i16, decode::Error> {
d.i16()
.map_err(|e| decode::Error::message(format!("Failed to decode i16 in {from}: {e}")))
}

/// Helper function for decoding i32.
pub(crate) fn decode_i32(d: &mut Decoder, from: &str) -> Result<i32, decode::Error> {
d.i32()
.map_err(|e| decode::Error::message(format!("Failed to decode i32 in {from}: {e}")))
}

/// Helper function for decoding i64.
pub(crate) fn decode_i64(d: &mut Decoder, from: &str) -> Result<i64, decode::Error> {
d.i64()
.map_err(|e| decode::Error::message(format!("Failed to decode i64 in {from}: {e}")))
}

/// Helper function for decoding string.
pub(crate) fn decode_string(d: &mut Decoder, from: &str) -> Result<String, decode::Error> {
d.str()
.map(std::borrow::ToOwned::to_owned)
.map_err(|e| decode::Error::message(format!("Failed to decode string in {from}: {e}")))
/// Generic helper function for decoding different types.
pub(crate) fn decode_helper<'a, T, C>(
d: &mut Decoder<'a>, from: &str, context: &mut C,
) -> Result<T, decode::Error>
where T: minicbor::Decode<'a, C> {
T::decode(d, context).map_err(|e| {
decode::Error::message(&format!(
"Failed to decode {:?} in {from}: {e}",
std::any::type_name::<T>()
))
})
}

/// Helper function for decoding bytes.
pub(crate) fn decode_bytes(d: &mut Decoder, from: &str) -> Result<Vec<u8>, decode::Error> {
d.bytes()
.map(<[u8]>::to_vec)
.map_err(|e| decode::Error::message(format!("Failed to decode bytes in {from}: {e}")))
d.bytes().map(<[u8]>::to_vec).map_err(|e| {
decode::Error::message(&format!(
"Failed to decode bytes in {from}:
{e}"
))
})
}

/// Helper function for decoding array.
pub(crate) fn decode_array_len(d: &mut Decoder, from: &str) -> Result<u64, decode::Error> {
d.array()
.map_err(|e| decode::Error::message(format!("Failed to decode array in {from}: {e}")))?
.ok_or(decode::Error::message(format!(
.map_err(|e| {
decode::Error::message(&format!(
"Failed to decode array in {from}:
{e}"
))
})?
.ok_or(decode::Error::message(&format!(
"Failed to decode array in {from}, unexpected indefinite length",
)))
}

/// Helper function for decoding map.
pub(crate) fn decode_map_len(d: &mut Decoder, from: &str) -> Result<u64, decode::Error> {
d.map()
.map_err(|e| decode::Error::message(format!("Failed to decode map in {from}: {e}")))?
.ok_or(decode::Error::message(format!(
"Failed to decode map in {from}, unexpected indefinite length",
)))
}

/// Helper function for decoding tag.
pub(crate) fn decode_tag(d: &mut Decoder, from: &str) -> Result<Tag, decode::Error> {
d.tag()
Expand All @@ -91,50 +57,63 @@ pub(crate) fn decode_tag(d: &mut Decoder, from: &str) -> Result<Tag, decode::Err
/// Decode any in CDDL, only support basic datatype
pub(crate) fn decode_any(d: &mut Decoder, from: &str) -> Result<Vec<u8>, decode::Error> {
match d.datatype()? {
minicbor::data::Type::Bytes => Ok(decode_bytes(d, &format!("{from} Any"))?),
minicbor::data::Type::String => {
Ok(decode_string(d, &format!("{from} Any"))?
.as_bytes()
.to_vec())
},
minicbor::data::Type::Array => {
Ok(decode_array_len(d, &format!("{from} Any"))?
.to_be_bytes()
.to_vec())
match decode_helper::<String, _>(d, &format!("{from} Any"), &mut ()) {
Ok(i) => Ok(i.as_bytes().to_vec()),
Err(e) => Err(e),
}
},
minicbor::data::Type::U8 => {
Ok(decode_u8(d, &format!("{from} Any"))?.to_be_bytes().to_vec())
match decode_helper::<u8, _>(d, &format!("{from} Any"), &mut ()) {
Ok(i) => Ok(i.to_be_bytes().to_vec()),
Err(e) => Err(e),
}
},
minicbor::data::Type::U16 => {
Ok(decode_u16(d, &format!("{from} Any"))?
.to_be_bytes()
.to_vec())
match decode_helper::<u16, _>(d, &format!("{from} Any"), &mut ()) {
Ok(i) => Ok(i.to_be_bytes().to_vec()),
Err(e) => Err(e),
}
},
minicbor::data::Type::U32 => {
Ok(decode_u32(d, &format!("{from} Any"))?
.to_be_bytes()
.to_vec())
match decode_helper::<u32, _>(d, &format!("{from} Any"), &mut ()) {
Ok(i) => Ok(i.to_be_bytes().to_vec()),
Err(e) => Err(e),
}
},
minicbor::data::Type::U64 => {
Ok(decode_u64(d, &format!("{from} Any"))?
.to_be_bytes()
.to_vec())
match decode_helper::<u64, _>(d, &format!("{from} Any"), &mut ()) {
Ok(i) => Ok(i.to_be_bytes().to_vec()),
Err(e) => Err(e),
}
},
minicbor::data::Type::I8 => {
Ok(decode_i8(d, &format!("{from} Any"))?.to_be_bytes().to_vec())
match decode_helper::<i8, _>(d, &format!("{from} Any"), &mut ()) {
Ok(i) => Ok(i.to_be_bytes().to_vec()),
Err(e) => Err(e),
}
},
minicbor::data::Type::I16 => {
Ok(decode_i16(d, &format!("{from} Any"))?
.to_be_bytes()
.to_vec())
match decode_helper::<i16, _>(d, &format!("{from} Any"), &mut ()) {
Ok(i) => Ok(i.to_be_bytes().to_vec()),
Err(e) => Err(e),
}
},
minicbor::data::Type::I32 => {
Ok(decode_i32(d, &format!("{from} Any"))?
.to_be_bytes()
.to_vec())
match decode_helper::<i32, _>(d, &format!("{from} Any"), &mut ()) {
Ok(i) => Ok(i.to_be_bytes().to_vec()),
Err(e) => Err(e),
}
},
minicbor::data::Type::I64 => {
Ok(decode_i64(d, &format!("{from} Any"))?
match decode_helper::<i64, _>(d, &format!("{from} Any"), &mut ()) {
Ok(i) => Ok(i.to_be_bytes().to_vec()),
Err(e) => Err(e),
}
},
minicbor::data::Type::Bytes => Ok(decode_bytes(d, &format!("{from} Any"))?),
minicbor::data::Type::Array => {
Ok(decode_array_len(d, &format!("{from} Any"))?
.to_be_bytes()
.to_vec())
},
Expand Down Expand Up @@ -213,7 +192,6 @@ mod tests {
let mut e = Encoder::new(&mut buf);
let num: i32 = -123_456_789;
e.i32(num).expect("Error encoding i32");

let mut d = Decoder::new(&buf);
let result = decode_any(&mut d, "test").expect("Error decoding i32");
assert_eq!(
Expand Down
58 changes: 32 additions & 26 deletions rust/cardano-chain-follower/src/metadata/cip509/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

// cspell: words pkix
use c509_certificate::general_names::general_name::GeneralNameValue;
use decode_helper::{decode_bytes, decode_map_len, decode_u8};
use decode_helper::{decode_bytes, decode_helper, decode_map_len};
use der_parser::{asn1_rs::oid, der::parse_der_sequence, Oid};
use rbac::{certs::C509Cert, role_data::RoleData};

Expand Down Expand Up @@ -110,7 +110,7 @@ impl Decode<'_, ()> for Cip509 {
let key = d.probe().u8()?;
if let Some(key) = Cip509IntIdentifier::from_repr(key) {
// Consuming the int
decode_u8(d, "CIP509")?;
let _: u8 = decode_helper(d, "CIP509", ctx)?;
match key {
Cip509IntIdentifier::Purpose => {
cip509_metadatum.purpose = decode_bytes(d, "CIP509 purpose")?
Expand Down Expand Up @@ -1085,14 +1085,15 @@ mod tests {

let transactions = multi_era_block.txs();
// Second transaction of this test data contains the CIP509 auxiliary data
#[allow(clippy::indexing_slicing)]
let tx = transactions[1].clone();
let aux_data = cip_509_aux_data(&tx);
let tx = transactions
.get(1)
.expect("Failed to get transaction index");
let aux_data = cip_509_aux_data(tx);

let mut decoder = Decoder::new(aux_data.as_slice());
let cip509 = Cip509::decode(&mut decoder, &mut ()).expect("Failed to decode Cip509");
assert!(cip509
.validate_txn_inputs_hash(&tx, &mut validation_report, &decoded_metadata)
.validate_txn_inputs_hash(tx, &mut validation_report, &decoded_metadata)
.unwrap());
}

Expand All @@ -1106,15 +1107,16 @@ mod tests {

let transactions = multi_era_block.txs();
// Second transaction of this test data contains the CIP509 auxiliary data
#[allow(clippy::indexing_slicing)]
let tx = transactions[1].clone();
let tx = transactions
.get(1)
.expect("Failed to get transaction index");

let aux_data = cip_509_aux_data(&tx);
let aux_data = cip_509_aux_data(tx);

let mut decoder = Decoder::new(aux_data.as_slice());
let mut cip509 = Cip509::decode(&mut decoder, &mut ()).expect("Failed to decode Cip509");
assert!(cip509
.validate_aux(&tx, &mut validation_report, &decoded_metadata)
.validate_aux(tx, &mut validation_report, &decoded_metadata)
.unwrap());
}

Expand All @@ -1128,15 +1130,16 @@ mod tests {

let transactions = multi_era_block.txs();
// Second transaction of this test data contains the CIP509 auxiliary data
#[allow(clippy::indexing_slicing)]
let tx = transactions[1].clone();
let tx = transactions
.get(1)
.expect("Failed to get transaction index");

let aux_data = cip_509_aux_data(&tx);
let aux_data = cip_509_aux_data(tx);

let mut decoder = Decoder::new(aux_data.as_slice());
let cip509 = Cip509::decode(&mut decoder, &mut ()).expect("Failed to decode Cip509");
assert!(cip509
.validate_stake_public_key(&tx, &mut validation_report, &decoded_metadata, 0)
.validate_stake_public_key(tx, &mut validation_report, &decoded_metadata, 0)
.unwrap());
}

Expand All @@ -1150,10 +1153,11 @@ mod tests {

let transactions = multi_era_block.txs();
// Second transaction of this test data contains the CIP509 auxiliary data
#[allow(clippy::indexing_slicing)]
let tx = transactions[1].clone();
let tx = transactions
.get(1)
.expect("Failed to get transaction index");

let aux_data = cip_509_aux_data(&tx);
let aux_data = cip_509_aux_data(tx);

let mut decoder = Decoder::new(aux_data.as_slice());
let cip509 = Cip509::decode(&mut decoder, &mut ()).expect("Failed to decode Cip509");
Expand All @@ -1163,7 +1167,7 @@ mod tests {
if role.role_number == 0 {
assert!(cip509
.validate_payment_key(
&tx,
tx,
&mut validation_report,
&decoded_metadata,
0,
Expand All @@ -1185,10 +1189,11 @@ mod tests {

let transactions = multi_era_block.txs();
// Second transaction of this test data contains the CIP509 auxiliary data
#[allow(clippy::indexing_slicing)]
let tx = transactions[1].clone();
let tx = transactions
.get(1)
.expect("Failed to get transaction index");

let aux_data = cip_509_aux_data(&tx);
let aux_data = cip_509_aux_data(tx);

let mut decoder = Decoder::new(aux_data.as_slice());
let cip509 = Cip509::decode(&mut decoder, &mut ()).expect("Failed to decode Cip509");
Expand All @@ -1199,7 +1204,7 @@ mod tests {
println!(
"{:?}",
cip509.validate_payment_key(
&tx,
tx,
&mut validation_report,
&decoded_metadata,
0,
Expand All @@ -1221,15 +1226,16 @@ mod tests {

let transactions = multi_era_block.txs();
// Fifth transaction of this test data contains the CIP509 auxiliary data
#[allow(clippy::indexing_slicing)]
let tx = transactions[4].clone();
let tx = transactions
.get(4)
.expect("Failed to get transaction index");

let aux_data = cip_509_aux_data(&tx);
let aux_data = cip_509_aux_data(tx);

let mut decoder = Decoder::new(aux_data.as_slice());
let cip509 = Cip509::decode(&mut decoder, &mut ()).expect("Failed to decode Cip509");
assert!(!cip509
.validate_stake_public_key(&tx, &mut validation_report, &decoded_metadata, 0)
.validate_stake_public_key(tx, &mut validation_report, &decoded_metadata, 0)
.unwrap());
}
}
Loading