Implement chain adapter to read on chain protocol configurations - #3482
Implement chain adapter to read on chain protocol configurations#3482turmelclem wants to merge 7 commits into
Conversation
4f87a71 to
cb72f72
Compare
Test Results 5 files 209 suites 58m 46s ⏱️ Results for commit 551848d. ♻️ This comment has been updated with latest results. |
cb72f72 to
9a7ac9a
Compare
9a7ac9a to
4a79c83
Compare
4a79c83 to
192a144
Compare
192a144 to
38c6548
Compare
…nsistency in model
…kConfigurationProvider
…figurationProvider instead of local impl for leader aggregator
…guration commands
38c6548 to
551848d
Compare
| } | ||
|
|
||
| /// Verify the signature of a signed protocol configuration markers payload | ||
| pub fn verify_signature( |
There was a problem hiding this comment.
I think this method should be tested, at least with a roundtrip test (create a full message with at least two markers and a legitimate signature, then run this method).
| use mithril_common::entities::Epoch; | ||
| use std::collections::BTreeMap; | ||
| use std::sync::Arc; | ||
|
|
||
| use crate::cardano_chain::message::{ | ||
| ProtocolConfigurationForEpochMessage, ProtocolConfigurationMarker, | ||
| }; | ||
| use crate::cardano_chain::payload::SignedProtocolConfigurationMarkersPayload; | ||
| use crate::interface::ProtocolConfigurationMarkersReader; | ||
| use crate::model::{ConfigurationResolverFromMarkers, ProtocolConfigurationForEpoch}; | ||
| use mithril_cardano_node_chain::chain_observer::ChainObserver; | ||
| use mithril_cardano_node_chain::entities::ChainAddress; | ||
| use mithril_common::StdResult; | ||
| use mithril_cardano_node_chain::entities::{ChainAddress, TxDatumFieldTypeName}; | ||
| use mithril_common::crypto_helper::ProtocolConfigurationMarkersVerifierVerificationKey; | ||
|
|
||
| use crate::interface::ProtocolConfigurationMarkersReader; | ||
| use crate::model::ConfigurationResolverFromMarkers; | ||
| use mithril_common::{StdError, StdResult}; |
There was a problem hiding this comment.
Some import issues here (epoch in the wrong block, use crate mixed up)
| let markers_list = tx_datums | ||
| .into_iter() | ||
| .filter_map(|datum| datum.get_fields_by_type(&TxDatumFieldTypeName::Bytes).ok()) | ||
| .map(|fields| { | ||
| fields | ||
| .iter() | ||
| .filter_map(|field_value| field_value.as_str().map(|s| s.to_string())) | ||
| .collect::<Vec<String>>() | ||
| .join("") | ||
| }) | ||
| .filter_map(|field_value_str| { | ||
| SignedProtocolConfigurationMarkersPayload::from_json_hex(&field_value_str).ok() | ||
| }) | ||
| .filter_map(|markers_payload| { | ||
| markers_payload | ||
| .verify_signature(self.verification_key) | ||
| .ok() | ||
| .map(|_| markers_payload.markers) | ||
| }) | ||
| .collect::<Vec<Vec<ProtocolConfigurationMarker>>>(); | ||
|
|
||
| let last_markers = markers_list.first().cloned().unwrap_or_default(); |
There was a problem hiding this comment.
Wouldn't it be more efficient to only read the first item? Is there any reason to collecting them all?
| let markers_list = tx_datums | |
| .into_iter() | |
| .filter_map(|datum| datum.get_fields_by_type(&TxDatumFieldTypeName::Bytes).ok()) | |
| .map(|fields| { | |
| fields | |
| .iter() | |
| .filter_map(|field_value| field_value.as_str().map(|s| s.to_string())) | |
| .collect::<Vec<String>>() | |
| .join("") | |
| }) | |
| .filter_map(|field_value_str| { | |
| SignedProtocolConfigurationMarkersPayload::from_json_hex(&field_value_str).ok() | |
| }) | |
| .filter_map(|markers_payload| { | |
| markers_payload | |
| .verify_signature(self.verification_key) | |
| .ok() | |
| .map(|_| markers_payload.markers) | |
| }) | |
| .collect::<Vec<Vec<ProtocolConfigurationMarker>>>(); | |
| let last_markers = markers_list.first().cloned().unwrap_or_default(); | |
| let last_markers: Vec<ProtocolConfigurationMarker> = tx_datums | |
| .into_iter() | |
| .filter_map(|datum| datum.get_fields_by_type(&TxDatumFieldTypeName::Bytes).ok()) | |
| .map(|fields| { | |
| fields | |
| .iter() | |
| .filter_map(|field_value| field_value.as_str().map(|s| s.to_string())) | |
| .collect::<Vec<String>>() | |
| .join("") | |
| }) | |
| .filter_map(|field_value_str| { | |
| SignedProtocolConfigurationMarkersPayload::from_json_hex(&field_value_str).ok() | |
| }) | |
| .filter_map(|markers_payload| { | |
| markers_payload | |
| .verify_signature(self.verification_key) | |
| .ok() | |
| .map(|_| markers_payload.markers) | |
| }) | |
| .next() | |
| .unwrap_or_default(); |
| .map_err(|e| { | ||
| StdError::msg(format!( | ||
| "ProtocolConfigurationForEpochMessage for Epoch({}) could not be decoded from cbor hex: {}", | ||
| marker.epoch, | ||
| e | ||
| )) | ||
| })? |
There was a problem hiding this comment.
Is there a some incompatibility with anyhow context for this convoluted map?
| .map_err(|e| { | |
| StdError::msg(format!( | |
| "ProtocolConfigurationForEpochMessage for Epoch({}) could not be decoded from cbor hex: {}", | |
| marker.epoch, | |
| e | |
| )) | |
| })? | |
| .with_context(|| { | |
| format!( | |
| "ProtocolConfigurationForEpochMessage for Epoch({}) could not be decoded from cbor hex", | |
| marker.epoch, | |
| ) | |
| })? |
| } | ||
|
|
||
| #[tokio::test] | ||
| async fn test_cardano_chain_reader() { |
There was a problem hiding this comment.
The test name is too broad, here is a tentative name:
| async fn test_cardano_chain_reader() { | |
| async fn markers_signed_by_third_parties_are_rejected() { |
| use mithril_cli_helper::{register_config_value, serde_deserialization}; | ||
| use mithril_dmq::DmqNetwork; | ||
| use mithril_doc::{Documenter, DocumenterDefault, StructDoc}; | ||
| use mithril_protocol_config::builder::AdapterConfig; |
There was a problem hiding this comment.
You could use this opportunity to move those mithril_* uses below
| } | ||
| pub mod protocol_configuration { | ||
| use super::*; |
There was a problem hiding this comment.
Oups, missing line breaks
| } | |
| pub mod protocol_configuration { | |
| use super::*; | |
| } | |
| pub mod protocol_configuration { | |
| use super::*; | |
| self.root_logger(), | ||
| )); | ||
|
|
||
| let protocol_configuration_adapter = build_protocol_configuration_adapter( |
There was a problem hiding this comment.
I wonder if we should adapt the signer integration tests as well?
| cardano_transactions_signing_config: Some(CardanoTransactionsSigningConfig { | ||
| security_parameter: BlockNumberOffset(0), | ||
| step: BlockNumber(30), | ||
| }), | ||
| cardano_blocks_transactions_signing_config: Some(CardanoBlocksTransactionsSigningConfig { | ||
| security_parameter: BlockNumberOffset(0), | ||
| step: BlockNumber(24), | ||
| }), |
There was a problem hiding this comment.
Maybe you should remove those configurations?
|
|
||
| use anyhow::Context; | ||
| use config::{ConfigError, Map, Source, Value, ValueKind}; | ||
| use mithril_protocol_config::builder::AdapterConfig; |
There was a problem hiding this comment.
this mithril import should be below
There was a problem hiding this comment.
Pull request overview
Implements on-chain protocol configuration retrieval for signers and leader aggregators.
Changes:
- Adds signed Cardano marker decoding, verification, and configuration resolution.
- Wires marker-backed providers through signer and aggregator dependency injection.
- Updates CLI configuration and integration tests for marker-based settings.
Reviewed changes
Copilot reviewed 33 out of 33 changed files in this pull request and generated 17 comments.
Show a summary per file
| File | Description |
|---|---|
mithril-signer/src/dependency_injection/builder.rs |
Wires marker-based configuration into signer services. |
mithril-signer/src/configuration.rs |
Adds protocol reader adapter configuration. |
mithril-common/src/crypto_helper/mod.rs |
Exports protocol-configuration crypto aliases. |
mithril-common/src/crypto_helper/ed25519_alias.rs |
Defines marker verifier aliases. |
mithril-aggregator/tests/test_extensions/runtime_tester.rs |
Injects marker-reader test doubles. |
mithril-aggregator/tests/signed_entity_support.rs |
Migrates signed-entity test configuration. |
mithril-aggregator/tests/prove_transactions.rs |
Supplies transaction marker configuration. |
mithril-aggregator/tests/prove_blocks_transactions.rs |
Supplies block-transaction marker configuration. |
mithril-aggregator/tests/open_message_newer_exists.rs |
Migrates open-message test configuration. |
mithril-aggregator/tests/open_message_expiration.rs |
Migrates expiration test configuration. |
mithril-aggregator/tests/leader_signed_entity_config_propagation.rs |
Tests marker-backed configuration propagation. |
mithril-aggregator/tests/genesis_to_signing.rs |
Migrates genesis transition setup. |
mithril-aggregator/tests/era_checker.rs |
Supplies marker configuration to era tests. |
mithril-aggregator/tests/create_certificate.rs |
Migrates certificate creation configuration. |
mithril-aggregator/tests/create_certificate_with_buffered_signatures.rs |
Migrates buffered-signature setup. |
mithril-aggregator/tests/create_certificate_follower.rs |
Updates leader/follower marker setup. |
mithril-aggregator/tests/certificate_chain.rs |
Migrates certificate-chain configuration. |
mithril-aggregator/tests/cardano_stake_distribution_verify_stakes.rs |
Migrates stake verification configuration. |
mithril-aggregator/src/dependency_injection/builder/support/compatibility.rs |
Removes the former reader construction path. |
mithril-aggregator/src/dependency_injection/builder/enablers/epoch.rs |
Builds marker-backed network configuration providers. |
mithril-aggregator/src/configuration.rs |
Adds adapter configuration and updates samples. |
mithril-aggregator/src/commands/protocol_configuration_command.rs |
Refactors protocol-configuration command parameters. |
internal/mithril-protocol-config/src/test/mod.rs |
Exports test helpers. |
internal/mithril-protocol-config/src/test/helper.rs |
Adds protocol configuration fixtures. |
internal/mithril-protocol-config/src/test/double/fake_markers_reader.rs |
Adds default fake marker data. |
internal/mithril-protocol-config/src/model.rs |
Centralizes consistency handling and conversion. |
internal/mithril-protocol-config/src/markers.rs |
Implements the marker-backed provider. |
internal/mithril-protocol-config/src/lib.rs |
Exposes builder and marker modules. |
internal/mithril-protocol-config/src/http.rs |
Reuses model-level consistency handling. |
internal/mithril-protocol-config/src/cardano_chain/protocol_configuration_reader.rs |
Reads and verifies on-chain marker datums. |
internal/mithril-protocol-config/src/cardano_chain/payload.rs |
Verifies signed marker payloads. |
internal/mithril-protocol-config/src/cardano_chain/message.rs |
Converts decoded messages into domain models. |
internal/mithril-protocol-config/src/builder.rs |
Builds configured marker readers. |
Suppressed comments (3)
internal/mithril-protocol-config/src/markers.rs:154
- Test names must describe behavior without a
test_prefix. Rename this test accordingly.
async fn test_get_network_configuration_removes_unavailable_discriminants_when_config_missing()
internal/mithril-protocol-config/src/cardano_chain/protocol_configuration_reader.rs:179
- Test names must describe behavior without a
test_prefix. Rename this test accordingly.
async fn test_cardano_chain_reader_should_throw_error_on_invalid_cbor() {
internal/mithril-protocol-config/src/test/helper.rs:56
- This helper also builds an invalid domain model because
phi_f = 1.2is outside the accepted(0, 1]range. Keep the message and model helpers valid and consistent.
phi_f: 1.2,
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| }) | ||
| .collect::<Vec<Vec<ProtocolConfigurationMarker>>>(); | ||
|
|
||
| let last_markers = markers_list.first().cloned().unwrap_or_default(); |
| SignedEntityTypeDiscriminants::CardanoTransactions, | ||
| ]), | ||
| cardano_blocks_transactions: None, | ||
| cardano_transactions: None, |
| cardano_blocks_transactions: None, | ||
| cardano_transactions: None, |
| protocol_parameters: ProtocolParametersMessage { | ||
| k: conf as u64, | ||
| m: conf as u64, | ||
| phi_f: 1.2, |
| } | ||
|
|
||
| #[tokio::test] | ||
| async fn test_get_network_configuration_retrieve_configurations_for_aggregation_next_aggregation_and_registration() |
| } | ||
| } | ||
|
|
||
| /// A epoch configuration used for the CBOR HEX representation in the [ProtocolConfigurationMarker] |
| use mithril_protocol_config::model::{ | ||
| ConfigurationResolverFromMarkers, ProtocolConfigurationForEpoch, | ||
| }; | ||
| use std::collections::{BTreeMap, BTreeSet}; |
|
|
||
| /// Protocol configuration reader adapter configuration | ||
| #[example = "\ | ||
| - cardano-chain:<br/>`{ \"type\": \"cardano-chain\", \"address\": \"test_address\", \"verification_key\": \"136372c3138312c3138382c3130352c3233312c3135\" }`<br/>\ |
|
|
||
| /// Protocol configuration reader adapter configuration | ||
| #[example = "\ | ||
| - cardano-chain:<br/>`{ \"type\": \"cardano-chain\", \"address\": \"test_address\", \"verification_key\": \"136372c3138312c3138382c3130352c3233312c3135\" }`<br/>\ |
| /// Protocol configuration reader adapter configuration | ||
| #[example = "\ | ||
| `{ \"address\": \"address\", \"verification_key\": \"key\" }`\ | ||
| - cardano-chain:<br/>`{ \"type\": \"cardano-chain\", \"address\": \"test_address\", \"verification_key\": \"136372c3138312c3138382c3130352c3233312c3135\" }`<br/>\ |
Content
This PR includes modification to implement chain adapater to read on chain protocol configurations :
MithrilNetworkConfigurationProviderMarkersMithrilNetworkConfigurationProviderin the SignerMarkersMithrilNetworkConfigurationProviderinstead of local impl for leader aggregatorprotocol-configurationcommandsPre-submit checklist
Relates to #3393