Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
14 commits
Select commit Hold shift + click to select a range
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
5 changes: 5 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion internal/mithril-protocol-config/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,18 @@ include = ["**/*.rs", "Cargo.toml", "README.md", ".gitignore"]
[dependencies]
anyhow = { workspace = true }
async-trait = { workspace = true }
ciborium = "0.2.2"
hex = { workspace = true }
mithril-aggregator-client = { path = "../mithril-aggregator-client" }
mithril-cardano-node-chain = { path = "../cardano-node/mithril-cardano-node-chain" }
mithril-common = { path = "../../mithril-common" }
serde = { workspace = true }
serde_json = { workspace = true }
slog = { workspace = true }
thiserror = { workspace = true }
tokio = { workspace = true }

[dev-dependencies]
httpmock = "0.8.3"
serde_json = { workspace = true }
slog-async = { workspace = true }
slog-term = { workspace = true }
132 changes: 132 additions & 0 deletions internal/mithril-protocol-config/src/adapters/cardano_chain.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
use anyhow::Context;
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use thiserror::Error;

use mithril_cardano_node_chain::chain_observer::ChainObserver;
use mithril_cardano_node_chain::entities::ChainAddress;
use mithril_common::crypto_helper::{
ProtocolConfigurationMarkersSigner, ProtocolConfigurationMarkersVerifierSignature,
ProtocolConfigurationMarkersVerifierVerificationKey, key_encode_hex,
};
use mithril_common::{StdError, StdResult};

use crate::{ProtocolConfigurationMarker, ProtocolConfigurationReaderAdapter};

/// [ProtocolConfigurationMarkersPayload] related errors.
#[derive(Debug, Error)]
pub enum ProtocolConfigurationMarkersPayloadError {
/// Error raised when the message serialization fails
#[error("could not serialize message")]
SerializeMessage(#[source] StdError),

/// Error raised when the signature deserialization fails
#[error("could not deserialize signature")]
DeserializeSignature(#[source] StdError),

/// Error raised when the signature is missing
#[error("could not verify signature: signature is missing")]
MissingSignature,

/// Error raised when the signature is invalid
#[error("could not verify signature")]
VerifySignature(#[source] StdError),

/// Error raised when the signing the markers
#[error("could not create signature")]
CreateSignature(#[source] StdError),
}

/// Protocol Configuration markers payload
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ProtocolConfigurationMarkersPayload {
/// List of protocol configuration markers
pub markers: Vec<ProtocolConfigurationMarker>,
}

/// Signed Protocol Configuration markers payload
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SignedProtocolConfigurationMarkersPayload {
/// List of protocol configuration markers
pub markers: Vec<ProtocolConfigurationMarker>,

/// Protocol Configuration markers signature
pub signature: ProtocolConfigurationMarkersVerifierSignature,
}

impl SignedProtocolConfigurationMarkersPayload {
/// Instanciate a new SignedProtocolConfigurationMarkersPayload with markers and signature
pub fn new(
markers: Vec<ProtocolConfigurationMarker>,
signature: ProtocolConfigurationMarkersVerifierSignature,
) -> Self {
Self { markers, signature }
}

/// Encode this payload to a json hex string
pub fn to_json_hex(&self) -> StdResult<String> {
key_encode_hex(self).with_context(
|| "SignedProtocolConfigurationMarkersPayload could not be json hex encoded",
)
}
}

impl ProtocolConfigurationMarkersPayload {
/// Instanciate a new ProtocolConfigurationMarkersPayload with markers
pub fn new(markers: Vec<ProtocolConfigurationMarker>) -> Self {
Self { markers }
}

fn message_to_bytes(&self) -> Result<Vec<u8>, ProtocolConfigurationMarkersPayloadError> {
serde_json::to_vec(&self.markers)
.map_err(|e| ProtocolConfigurationMarkersPayloadError::SerializeMessage(e.into()))
}

/// Sign an protocol configuration markers payload
pub fn sign(
self,
signer: &ProtocolConfigurationMarkersSigner,
) -> Result<SignedProtocolConfigurationMarkersPayload, ProtocolConfigurationMarkersPayloadError>
{
let signature =
signer.sign(&self.message_to_bytes().map_err(|e| {
ProtocolConfigurationMarkersPayloadError::CreateSignature(e.into())
})?);

Ok(SignedProtocolConfigurationMarkersPayload {
markers: self.markers,
signature,
})
}
}

/// Cardano Chain adapter retrieves protocol configuration markers on chain
pub struct CardanoChainAdapter {

Check warning

Code scanning / clippy

fields address, chain_observer, and verification_key are never read Warning

fields address, chain_observer, and verification_key are never read

Check warning

Code scanning / clippy

fields address, chain_observer, and verification_key are never read Warning

fields address, chain_observer, and verification_key are never read

Check warning

Code scanning / clippy

fields address, chain_observer, and verification_key are never read Warning

fields address, chain_observer, and verification_key are never read
address: ChainAddress,

Check warning

Code scanning / clippy

fields address, chain_observer, and verification_key are never read Warning

fields address, chain_observer, and verification_key are never read

Check warning

Code scanning / clippy

fields address, chain_observer, and verification_key are never read Warning

fields address, chain_observer, and verification_key are never read

Check warning

Code scanning / clippy

fields address, chain_observer, and verification_key are never read Warning

fields address, chain_observer, and verification_key are never read
chain_observer: Arc<dyn ChainObserver>,

Check warning

Code scanning / clippy

fields address, chain_observer, and verification_key are never read Warning

fields address, chain_observer, and verification_key are never read

Check warning

Code scanning / clippy

fields address, chain_observer, and verification_key are never read Warning

fields address, chain_observer, and verification_key are never read

Check warning

Code scanning / clippy

fields address, chain_observer, and verification_key are never read Warning

fields address, chain_observer, and verification_key are never read
verification_key: ProtocolConfigurationMarkersVerifierVerificationKey,

Check warning

Code scanning / clippy

fields address, chain_observer, and verification_key are never read Warning

fields address, chain_observer, and verification_key are never read

Check warning

Code scanning / clippy

fields address, chain_observer, and verification_key are never read Warning

fields address, chain_observer, and verification_key are never read

Check warning

Code scanning / clippy

fields address, chain_observer, and verification_key are never read Warning

fields address, chain_observer, and verification_key are never read
}

impl CardanoChainAdapter {
/// CardanoChainAdapter factory
pub fn new(
address: ChainAddress,
chain_observer: Arc<dyn ChainObserver>,
verification_key: ProtocolConfigurationMarkersVerifierVerificationKey,
) -> Self {
Self {
address,
chain_observer,
verification_key,
}
}
}

#[async_trait]
impl ProtocolConfigurationReaderAdapter for CardanoChainAdapter {
async fn read(&self) -> StdResult<Vec<ProtocolConfigurationMarker>> {
//TODO to implement
Ok(Vec::new())
}
}
9 changes: 9 additions & 0 deletions internal/mithril-protocol-config/src/adapters/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
//! Module dedicated to ProtocolConfigurationReaderAdapter implementations.

mod cardano_chain;

pub use cardano_chain::{
CardanoChainAdapter as ProtocolConfigurationReaderCardanoChainAdapter,
ProtocolConfigurationMarkersPayload as ProtocolConfigurationMarkersPayloadCardanoChain,
SignedProtocolConfigurationMarkersPayload as SignedProtocolConfigurationMarkersPayloadCardanoChain,
};
117 changes: 117 additions & 0 deletions internal/mithril-protocol-config/src/configuration_computer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
//! //! Model definitions for ProtocolConfigurationReader.

use std::collections::BTreeMap;

use mithril_common::entities::Epoch;

use crate::ProtocolConfigurationForEpoch;

/// [ConfigurationComputerFromMarkers] containing markers by epoch
#[derive(PartialEq, Clone, Debug)]
pub struct ConfigurationComputerFromMarkers {
/// BTreeMap assotiation of ProtocolConfigurationForEpoch to a coresponding Epoch
pub markers: BTreeMap<Epoch, ProtocolConfigurationForEpoch>,
}

impl ConfigurationComputerFromMarkers {
/// Create a new [ConfigurationComputerFromMarkers] with the given markers.
pub fn new(markers: BTreeMap<Epoch, ProtocolConfigurationForEpoch>) -> Self {
Self { markers }
}

/// retrieve configuration for given Epoch or fallback to last known configuration
pub fn get_network_configuration(&self, epoch: Epoch) -> Option<ProtocolConfigurationForEpoch> {
self.markers
.range(..=epoch)
.next_back()
.map(|(_, marker)| marker.clone())
}
}

#[cfg(test)]
mod tests {
use std::collections::BTreeMap;

use mithril_common::{
entities::{
CardanoBlocksTransactionsSigningConfig, CardanoTransactionsSigningConfig, Epoch,
ProtocolParameters, SignedEntityTypeDiscriminants,
},
test::double::Dummy,
};

use crate::ProtocolConfigurationForEpoch;

use super::*;

fn fake_config_for_epoch(epoch: Epoch) -> ProtocolConfigurationForEpoch {
ProtocolConfigurationForEpoch {
protocol_parameters: ProtocolParameters::new(*epoch, *epoch, 0.1),
enabled_signed_entity_types: SignedEntityTypeDiscriminants::all(),
cardano_transactions: Some(CardanoTransactionsSigningConfig::dummy()),
cardano_blocks_transactions: Some(CardanoBlocksTransactionsSigningConfig::dummy()),
}
}

#[derive(Debug)]
struct TestCase {
requested_epoch: Epoch,
expected_conf_epoch: Epoch,
}

macro_rules! test_case {
(
requested: $requested_epoch:expr,
expected: $expected_conf_epoch:expr
) => {
TestCase {
requested_epoch: Epoch($requested_epoch),
expected_conf_epoch: Epoch($expected_conf_epoch),
}
};
}

#[test]
fn test_get_network_configuration_must_fallback_to_last_known_configuration_if_epoch_not_found()
{
let markers = BTreeMap::from([
(Epoch(2), fake_config_for_epoch(Epoch(2))),
(Epoch(6), fake_config_for_epoch(Epoch(6))),
(Epoch(10), fake_config_for_epoch(Epoch(10))),
]);

fn test_cases() -> Vec<TestCase> {
vec![
test_case!(requested: 3, expected: 2 ),
test_case!(requested: 5, expected: 2 ),
test_case!(requested: 6, expected: 6 ),
test_case!(requested: 7, expected: 6 ),
test_case!(requested: 9, expected: 6 ),
test_case!(requested: 10, expected: 10),
test_case!(requested: 11, expected: 10),
test_case!(requested: 12, expected: 10),
]
}

let configurations = ConfigurationComputerFromMarkers::new(markers);

for test_case in test_cases() {
assert_eq!(
configurations.get_network_configuration(test_case.requested_epoch),
Some(fake_config_for_epoch(test_case.expected_conf_epoch))
);
}
}

#[test]
fn test_get_network_configuration_return_none_if_no_fallback_conf_is_available() {
let markers = BTreeMap::from([
(Epoch(6), fake_config_for_epoch(Epoch(6))),
(Epoch(10), fake_config_for_epoch(Epoch(10))),
]);

let configurations = ConfigurationComputerFromMarkers::new(markers);

assert_eq!(configurations.get_network_configuration(Epoch(4)), None);
}
}
5 changes: 5 additions & 0 deletions internal/mithril-protocol-config/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
#![warn(missing_docs)]
//! This crate provides mechanisms to read and check the configuration parameters of a Mithril network.

pub mod adapters;
pub mod configuration_computer;
pub mod http;
pub mod interface;
pub mod model;
mod protocol_configuration_reader;
pub mod test;

pub use protocol_configuration_reader::*;
6 changes: 3 additions & 3 deletions internal/mithril-protocol-config/src/model.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Model definitions for Mithril Protocol Configuration.

use serde::{Deserialize, Serialize};
use std::collections::BTreeSet;

use mithril_common::{
Expand All @@ -10,7 +11,7 @@ use mithril_common::{
messages::{ProtocolConfigurationMessage, SignedEntityTypeDiscriminantsMessage},
};

#[derive(PartialEq, Clone, Debug)]
#[derive(PartialEq, Clone, Debug, Serialize, Deserialize)]

/// Custom configuration for the signed entity types
pub struct SignedEntityTypeConfiguration {
Expand Down Expand Up @@ -38,7 +39,7 @@ pub struct MithrilNetworkConfiguration {
}

//A epoch configuration
#[derive(PartialEq, Clone, Debug)]
#[derive(PartialEq, Clone, Debug, Serialize, Deserialize)]
/// A network configuration available for an epoch
pub struct MithrilNetworkConfigurationForEpoch {
/// Cryptographic protocol parameters (`k`, `m` and `phi_f`)
Expand Down Expand Up @@ -66,7 +67,6 @@ impl From<ProtocolConfigurationMessage> for MithrilNetworkConfigurationForEpoch
}
}
}

#[cfg(test)]
mod tests {
use mithril_common::messages::{
Expand Down
Loading
Loading