Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
84 changes: 56 additions & 28 deletions mithril-common/src/crypto_helper/cardano/codec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use anyhow::{Context, anyhow};
use hex::FromHex;
use kes_summed_ed25519::kes::Sum6Kes;
use kes_summed_ed25519::traits::KesSk;
use rand_core::RngCore;
use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
use serde_with::{As, Bytes};
Expand All @@ -24,6 +25,7 @@ use std::path::Path;
use thiserror::Error;

use crate::StdError;
use crate::test::crypto_helper::SerDeShelleyFileFormatTestExtension;

/// We need to create this struct because the design of Sum6Kes takes
/// a reference to a mutable pointer. It is therefore not possible to
Expand Down Expand Up @@ -62,7 +64,7 @@ pub trait SerDeShelleyFileFormat: Serialize + DeserializeOwned {
/// Shelley file format.
fn from_file<P: AsRef<Path>>(path: P) -> Result<Self, CodecParseError> {
let data = fs::read_to_string(path)
.with_context(|| "SerDeShelleyFileFormat can not read data from file {}")
.with_context(|| "SerDeShelleyFileFormat can not read data from file")
.map_err(CodecParseError)?;
let file: ShelleyFileFormat = serde_json::from_str(&data)
.with_context(|| "SerDeShelleyFileFormat can not unserialize json data")
Expand All @@ -71,33 +73,6 @@ pub trait SerDeShelleyFileFormat: Serialize + DeserializeOwned {
Self::from_cbor_hex(&file.cbor_hex)
}

/// Serialize a type `T: Serialize + DeserializeOwned` to file following Cardano
/// Shelley file format.
fn to_file<P: AsRef<Path>>(&self, path: P) -> Result<(), CodecParseError> {
let cbor_string = self
.to_cbor_hex()
.with_context(|| "SerDeShelleyFileFormat can not serialize data to cbor")
.map_err(CodecParseError)?;

let file_format = ShelleyFileFormat {
file_type: Self::TYPE.to_string(),
description: Self::DESCRIPTION.to_string(),
cbor_hex: cbor_string,
};

let mut file = fs::File::create(path)
.with_context(|| "SerDeShelleyFileFormat can not create file")
.map_err(CodecParseError)?;
let json_str = serde_json::to_string(&file_format)
.with_context(|| "SerDeShelleyFileFormat can not serialize data to json")
.map_err(CodecParseError)?;

write!(file, "{json_str}")
.with_context(|| "SerDeShelleyFileFormat can not write data to file")
.map_err(CodecParseError)?;
Ok(())
}

/// Serialize the structure to a CBOR bytes representation.
fn to_cbor_bytes(&self) -> Result<Vec<u8>, CodecParseError> {
let mut cursor = std::io::Cursor::new(Vec::new());
Expand Down Expand Up @@ -177,6 +152,44 @@ impl<'a> TryFrom<&'a mut Sum6KesBytes> for Sum6Kes<'a> {
}
}

impl<T> SerDeShelleyFileFormatTestExtension for T
where
T: SerDeShelleyFileFormat,
{
fn to_file<P: AsRef<Path>>(&self, path: P) -> Result<(), CodecParseError> {
let cbor_string = self
.to_cbor_hex()
.with_context(|| "SerDeShelleyFileFormat can not serialize data to cbor")
.map_err(CodecParseError)?;

let file_format = ShelleyFileFormat {
file_type: Self::TYPE.to_string(),
description: Self::DESCRIPTION.to_string(),
cbor_hex: cbor_string,
};

let path_ref = path.as_ref();
let mut rng = rand_core::OsRng;
let temp_path = path_ref.with_added_extension(format!("{}.tmp", rng.next_u64()));

let mut file = fs::File::create(temp_path.clone())
.with_context(|| "SerDeShelleyFileFormat can not create file")
.map_err(CodecParseError)?;
let json_str = serde_json::to_string(&file_format)
.with_context(|| "SerDeShelleyFileFormat can not serialize data to json")
.map_err(CodecParseError)?;

write!(file, "{json_str}")
.with_context(|| "SerDeShelleyFileFormat can not write data to file")
.map_err(CodecParseError)?;

fs::rename(&temp_path, path_ref)
.with_context(|| "SerDeShelleyFileFormat can not rename temporary file")
.map_err(CodecParseError)?;
Ok(())
}
}

#[cfg(test)]
mod test {
use super::*;
Expand Down Expand Up @@ -206,4 +219,19 @@ mod test {

assert!(Sum6Kes::try_from(&mut kes_sk_bytes).is_ok());
}

#[test]
fn to_file_must_create_a_file() {
let temp_dir = TempDir::create("crypto_helper", "to_file_must_create_a_file");
let cbor_hex_string = "590264fe77acdfa56281e4b05198f5136018057a65f425411f0990cac4aca0f2917aa00a3d51e191f6f425d870aca3c6a2a41833621f5729d7bc0e3dfc3ae77d057e5e1253b71def7a54157b9f98973ca3c49edd9f311e5f4b23ac268b56a6ac040c14c6d2217925492e42f00dc89a2a01ff363571df0ca0db5ba37001cee56790cc01cd69c6aa760fca55a65a110305ea3c11da0a27be345a589329a584ebfc499c43c55e8c6db5d9c0b014692533ee78abd7ac1e79f7ec9335c7551d31668369b4d5111db78072f010043e35e5ca7f11acc3c05b26b9c7fe56f02aa41544f00cb7685e87f34c73b617260ade3c7b8d8c4df46693694998f85ad80d2cbab0b575b6ccd65d90574e84368169578bff57f751bc94f7eec5c0d7055ec88891a69545eedbfbd3c5f1b1c1fe09c14099f6b052aa215efdc5cb6cdc84aa810db41dbe8cb7d28f7c4beb75cc53915d3ac75fc9d0bf1c734a46e401e15150c147d013a938b7e07cc4f25a582b914e94783d15896530409b8acbe31ef471de8a1988ac78dfb7510729eff008084885f07df870b65e4f382ca15908e1dcda77384b5c724350de90cec22b1dcbb1cdaed88da08bb4772a82266ec154f5887f89860d0920dba705c45957ef6d93e42f6c9509c966277d368dd0eefa67c8147aa15d40a222f7953a4f34616500b310d00aa1b5b73eb237dc4f76c0c16813d321b2fc5ac97039be25b22509d1201d61f4ccc11cd4ff40fffe39f0e937b4722074d8e073a775d7283b715d46f79ce128e3f1362f35615fa72364d20b6db841193d96e58d9d8e86b516bbd1f05e45b39823a93f6e9f29d9e01acf2c12c072d1c64e0afbbabf6903ef542e00000000";
let kes_bytes = Sum6KesBytes::from_cbor_hex(cbor_hex_string).unwrap();
let kes_file_path = temp_dir.join("kes.sk");

kes_bytes
.to_file(kes_file_path.clone())
.expect("Sum6KesBytes to_file should not fail");

assert!(kes_file_path.exists(), "KES file should be created");
assert_eq!(fs::read_dir(&temp_dir).unwrap().count(), 1)
}
}
2 changes: 1 addition & 1 deletion mithril-common/src/crypto_helper/cardano/opcert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ impl From<(OpCertWithoutColdVerificationKey, EdVerificationKey)> for OpCert {
mod tests {
use super::*;
use crate::crypto_helper::cardano::ColdKeyGenerator;
use crate::test::TempDir;
use crate::test::{TempDir, crypto_helper::SerDeShelleyFileFormatTestExtension};

use kes_summed_ed25519::{kes::Sum6Kes, traits::KesSk};
use std::path::PathBuf;
Expand Down
8 changes: 4 additions & 4 deletions mithril-common/src/crypto_helper/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ mod types;
pub use cardano::ColdKeyGenerator;

pub use cardano::{
KesEvolutions, KesPeriod, KesSigner, KesSignerStandard, KesVerifier, KesVerifierStandard,
KesVerifyError, OpCert, OpCertWithoutColdVerificationKey, ProtocolInitializerErrorWrapper,
ProtocolRegistrationErrorWrapper, SerDeShelleyFileFormat, SignerRegistrationParameters,
Sum6KesBytes,
CodecParseError, KesEvolutions, KesPeriod, KesSigner, KesSignerStandard, KesVerifier,
KesVerifierStandard, KesVerifyError, OpCert, OpCertWithoutColdVerificationKey,
ProtocolInitializerErrorWrapper, ProtocolRegistrationErrorWrapper, SerDeShelleyFileFormat,
SignerRegistrationParameters, Sum6KesBytes,
};
pub use codec::*;
pub use ed25519_alias::{era::*, manifest::*};
Expand Down
7 changes: 2 additions & 5 deletions mithril-common/src/test/builder/fixture_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,11 @@ use rand_chacha::ChaCha20Rng;
use rand_core::{RngCore, SeedableRng};

use crate::{
crypto_helper::{
ColdKeyGenerator, KesPeriod, OpCert, ProtocolStakeDistribution, SerDeShelleyFileFormat,
Sum6KesBytes,
},
crypto_helper::{ColdKeyGenerator, KesPeriod, OpCert, ProtocolStakeDistribution, Sum6KesBytes},
entities::{PartyId, ProtocolParameters, Stake, StakeDistribution},
test::{
builder::MithrilFixture,
crypto_helper,
crypto_helper::{self, SerDeShelleyFileFormatTestExtension},
double::{fake_data, precomputed_kes_key},
},
};
Expand Down
10 changes: 9 additions & 1 deletion mithril-common/src/test/crypto_helper/cardano/extensions.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
use crate::crypto_helper::ProtocolParameters;
use std::path::Path;

use crate::crypto_helper::{CodecParseError, ProtocolParameters, SerDeShelleyFileFormat};

/// Extension trait adding test utilities to [ProtocolInitializer][crate::crypto_helper::ProtocolInitializer]
pub trait ProtocolInitializerTestExtension {
/// `TEST ONLY` - Override the protocol parameters of the `Initializer`
fn override_protocol_parameters(&mut self, protocol_parameters: &ProtocolParameters);
}

/// Extension trait adding test-only file export utilities to any type implementing [SerDeShelleyFileFormat].
pub trait SerDeShelleyFileFormatTestExtension: SerDeShelleyFileFormat {
/// `TEST ONLY` - Serialize the structure to a Shelley-formatted file.
fn to_file<P: AsRef<Path>>(&self, path: P) -> Result<(), CodecParseError>;
}
5 changes: 2 additions & 3 deletions mithril-common/src/test/crypto_helper/cardano/kes/setup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ use std::{fs, path::PathBuf};
use kes_summed_ed25519::kes::Sum6Kes;
use kes_summed_ed25519::traits::KesSk;

use crate::crypto_helper::{
ColdKeyGenerator, KesPeriod, OpCert, ProtocolPartyId, SerDeShelleyFileFormat, Sum6KesBytes,
};
use crate::crypto_helper::{ColdKeyGenerator, KesPeriod, OpCert, ProtocolPartyId, Sum6KesBytes};
use crate::test::crypto_helper::SerDeShelleyFileFormatTestExtension;

/// A type alias for the party index used in KES cryptographic material.
pub type KesPartyIndexForTest = u64;
Expand Down
Loading