Skip to content

Handle multiple beacon types in Certificate #1601

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 42 commits into from
Mar 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
c4247d7
Add some observations & comments
Alenar Mar 15, 2024
eedd1fc
Refactor Certificate to add the signed entity type
Alenar Mar 18, 2024
56945c4
make signed entity type of Cert message mandatory
Alenar Mar 18, 2024
bf29ebf
Add `TimePoint` type in common
Alenar Mar 18, 2024
8e4e86a
Adapt nodes code to new design to make the workspace build
Alenar Mar 18, 2024
70f5b3f
Add db migration to add signed entity type & network to certificate
Alenar Mar 20, 2024
a64bfe6
Move signed entity type beacon read from db to a commun methods
Alenar Mar 21, 2024
4a236ac
Update hashes in aggregator certificate hash migrator tests
Alenar Mar 21, 2024
6fafc98
Adapt aggregator db certificate provider to the new record structure
Alenar Mar 21, 2024
953c2fd
Add `global_logger_for_tests` to aggregator for debugging
Alenar Mar 22, 2024
366d2d0
Make aggregator state machine take a AggregatorConfig as param
Alenar Mar 22, 2024
b89485a
Simplify aggregator state machines match in tests
Alenar Mar 22, 2024
98c3df6
Replace `CardanoDbBeacon` with `TimePoint` in aggregator state machine
Alenar Mar 22, 2024
1a88774
Add signed_entity_type to certificate list message
Alenar Mar 22, 2024
55dd2cf
Define signed_entity_type to `/certificates` & `/certificate/{hash}` …
Alenar Mar 22, 2024
0e846be
Make Signer state machine use a `Timepoint` instead of a `CardanoDbBe…
Alenar Mar 22, 2024
a13e40f
Rename common `BeaconProvider` to `TimePointProvider`
Alenar Mar 22, 2024
222b815
Update observations to current state of work
Alenar Mar 22, 2024
4909480
Simplify `CertificatePending` entity to use only an epoch
Alenar Mar 22, 2024
eb704f3
Add epoch to `CertificatePendingMessage` and deprecate its beacon field
Alenar Mar 22, 2024
ed0ebbd
Add epoch to Cert/CertList messages and deprecate their beacon field
Alenar Mar 22, 2024
d5d76d5
Deprecate immutable file number of `CertificateMetadata`
Alenar Mar 22, 2024
e1dff96
Remove `compare_to_older` from `CardanoDbBeacon` as this responsibili…
Alenar Mar 22, 2024
f6253bd
Update observations to current state of work
Alenar Mar 22, 2024
eeb1945
Remove PartialOrd implementation from Certificate
Alenar Mar 27, 2024
af1bea5
Add a todo to remove network from `CardanoDbBeacon`
Alenar Mar 27, 2024
10c57e7
Update fake aggregator default data
Alenar Mar 27, 2024
abf4ea7
Make fake aggregator import script download certificates last
Alenar Mar 28, 2024
ae52de9
Update fake aggregator default
Alenar Mar 28, 2024
168f8dc
Make FakeObserver use a TimePoint instead of a CardanoDbBeacon
Alenar Mar 28, 2024
a337be5
Replace beacon by TimePoint when applicable in signer
Alenar Mar 28, 2024
ecb2992
Replace beacon by TimePoint when applicable in common
Alenar Mar 28, 2024
05b19c0
Replace beacon by TimePoint when applicable in aggregator
Alenar Mar 28, 2024
5c23b74
Remove compare_to_older from `TimePoint`
Alenar Mar 28, 2024
72dff9f
Simplify Certifier certificate creation
Alenar Mar 28, 2024
bddad64
Remove observations file
Alenar Mar 28, 2024
924ba55
Split beacon into its component for `CertificateGenesisProducer::crea…
Alenar Mar 28, 2024
a87ff74
PR Review feedback
Alenar Mar 28, 2024
17d2e87
Rename Certificate table `beacon` column to `signed_entity_beacon` in…
Alenar Mar 29, 2024
9ebc638
Add a foreign key to signed_entity_type to aggregator certificate table
Alenar Mar 29, 2024
c628a95
Small typo fixes
Alenar Mar 29, 2024
92d877a
Upgrade crates and openapi versions
Alenar Mar 29, 2024
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
10 changes: 5 additions & 5 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion mithril-aggregator/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "mithril-aggregator"
version = "0.4.50"
version = "0.4.51"
description = "A Mithril Aggregator server"
authors = { workspace = true }
edition = { workspace = true }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ use crate::{
use super::ArtifactBuilder;
use mithril_common::{
entities::{
CardanoDbBeacon, Certificate, CompressionAlgorithm, ProtocolMessage,
ProtocolMessagePartKey, Snapshot,
CardanoDbBeacon, Certificate, CompressionAlgorithm, ProtocolMessagePartKey, Snapshot,
},
StdResult,
};
Expand Down Expand Up @@ -55,16 +54,11 @@ impl CardanoImmutableFilesFullArtifactBuilder {
async fn create_snapshot_archive(
&self,
beacon: &CardanoDbBeacon,
protocol_message: &ProtocolMessage,
snapshot_digest: &str,
) -> StdResult<OngoingSnapshot> {
debug!("CardanoImmutableFilesFullArtifactBuilder: create snapshot archive");

let snapshotter = self.snapshotter.clone();
let snapshot_digest = protocol_message
.get_message_part(&ProtocolMessagePartKey::SnapshotDigest)
.ok_or_else(|| {
CardanoImmutableFilesFullArtifactError::MissingProtocolMessage(beacon.clone())
})?;
let snapshot_name = format!(
"{}-e{}-i{}.{}.{}",
beacon.network,
Expand Down Expand Up @@ -107,23 +101,16 @@ impl CardanoImmutableFilesFullArtifactBuilder {

async fn create_snapshot(
&self,
certificate: &Certificate,
beacon: CardanoDbBeacon,
ongoing_snapshot: &OngoingSnapshot,
snapshot_digest: String,
remote_locations: Vec<String>,
) -> StdResult<Snapshot> {
debug!("CardanoImmutableFilesFullArtifactBuilder: create snapshot");
let snapshot_digest = certificate
.protocol_message
.get_message_part(&ProtocolMessagePartKey::SnapshotDigest)
.ok_or_else(|| {
CardanoImmutableFilesFullArtifactError::MissingProtocolMessage(
certificate.beacon.clone(),
)
})?
.to_owned();

let snapshot = Snapshot::new(
snapshot_digest,
certificate.beacon.to_owned(),
beacon,
*ongoing_snapshot.get_file_size(),
remote_locations,
self.compression_algorithm,
Expand All @@ -141,8 +128,16 @@ impl ArtifactBuilder<CardanoDbBeacon, Snapshot> for CardanoImmutableFilesFullArt
beacon: CardanoDbBeacon,
certificate: &Certificate,
) -> StdResult<Snapshot> {
let snapshot_digest = certificate
.protocol_message
.get_message_part(&ProtocolMessagePartKey::SnapshotDigest)
.ok_or_else(|| {
CardanoImmutableFilesFullArtifactError::MissingProtocolMessage(beacon.clone())
})?
.to_owned();

let ongoing_snapshot = self
.create_snapshot_archive(&beacon, &certificate.protocol_message)
.create_snapshot_archive(&beacon, &snapshot_digest)
.await
.with_context(|| {
"Cardano Immutable Files Full Artifact Builder can not create snapshot archive"
Expand All @@ -155,7 +150,7 @@ impl ArtifactBuilder<CardanoDbBeacon, Snapshot> for CardanoImmutableFilesFullArt
})?;

let snapshot = self
.create_snapshot(certificate, &ongoing_snapshot, locations)
.create_snapshot(beacon, &ongoing_snapshot, snapshot_digest, locations)
.await?;

Ok(snapshot)
Expand Down Expand Up @@ -194,7 +189,7 @@ mod tests {
CompressionAlgorithm::Zstandard,
);
let artifact = cardano_immutable_files_full_artifact_builder
.compute_artifact(beacon, &certificate)
.compute_artifact(beacon.clone(), &certificate)
.await
.unwrap();
let last_ongoing_snapshot = dumb_snapshotter
Expand All @@ -208,7 +203,7 @@ mod tests {
.expect("A snapshot should have been 'uploaded'")];
let artifact_expected = Snapshot::new(
snapshot_digest.to_owned(),
certificate.beacon.to_owned(),
beacon,
*last_ongoing_snapshot.get_file_size(),
remote_locations,
CompressionAlgorithm::Zstandard,
Expand Down Expand Up @@ -245,11 +240,7 @@ mod tests {
#[tokio::test]
async fn snapshot_archive_name_after_beacon_values() {
let beacon = CardanoDbBeacon::new("network".to_string(), 20, 145);
let mut message = ProtocolMessage::new();
message.set_message_part(
ProtocolMessagePartKey::SnapshotDigest,
"test+digest".to_string(),
);
let digest = "test+digest";

let cardano_immutable_files_full_artifact_builder =
CardanoImmutableFilesFullArtifactBuilder::new(
Expand All @@ -260,27 +251,21 @@ mod tests {
);

let ongoing_snapshot = cardano_immutable_files_full_artifact_builder
.create_snapshot_archive(&beacon, &message)
.create_snapshot_archive(&beacon, digest)
.await
.expect("create_snapshot_archive should not fail");

assert_eq!(
Path::new(&format!(
"{}-e{}-i{}.{}.tar.gz",
beacon.network, *beacon.epoch, beacon.immutable_file_number, "test+digest"
"{}-e{}-i{}.{digest}.tar.gz",
beacon.network, *beacon.epoch, beacon.immutable_file_number,
)),
ongoing_snapshot.get_file_path()
);
}

#[tokio::test]
async fn snapshot_archive_name_after_compression_algorithm() {
let mut message = ProtocolMessage::new();
message.set_message_part(
ProtocolMessagePartKey::SnapshotDigest,
"test+digest".to_string(),
);

let mut invalid_result: Vec<CompressionAlgorithm> = vec![];

for algorithm in CompressionAlgorithm::list() {
Expand All @@ -293,7 +278,7 @@ mod tests {
);

let ongoing_snapshot = cardano_immutable_files_full_artifact_builder
.create_snapshot_archive(&CardanoDbBeacon::default(), &message)
.create_snapshot_archive(&CardanoDbBeacon::default(), "test+digest")
.await
.expect("create_snapshot_archive should not fail");
let file_name = ongoing_snapshot
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,13 @@ mod tests {
certificate
};

let beacon = certificate.as_cardano_db_beacon();
let cardano_transaction_artifact_builder = CardanoTransactionsArtifactBuilder::new();
let artifact = cardano_transaction_artifact_builder
.compute_artifact(certificate.beacon.clone(), &certificate)
.compute_artifact(beacon.clone(), &certificate)
.await
.unwrap();
let artifact_expected =
CardanoTransactionsSnapshot::new("merkleroot".to_string(), certificate.beacon);
let artifact_expected = CardanoTransactionsSnapshot::new("merkleroot".to_string(), beacon);
assert_eq!(artifact_expected, artifact);
}

Expand Down
26 changes: 18 additions & 8 deletions mithril-aggregator/src/configuration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ use std::path::PathBuf;
use std::str::FromStr;

use mithril_common::entities::{
CardanoDbBeacon, CompressionAlgorithm, HexEncodedGenesisVerificationKey, ProtocolParameters,
SignedEntityType, SignedEntityTypeDiscriminants,
CompressionAlgorithm, HexEncodedGenesisVerificationKey, ProtocolParameters, SignedEntityType,
SignedEntityTypeDiscriminants, TimePoint,
};
use mithril_common::{CardanoNetwork, StdResult};

Expand Down Expand Up @@ -285,12 +285,14 @@ impl Configuration {
/// The signed entity types are discarded if they are not declared in the [SignedEntityType] enum.
pub fn list_allowed_signed_entity_types(
&self,
beacon: &CardanoDbBeacon,
time_point: &TimePoint,
) -> StdResult<Vec<SignedEntityType>> {
let allowed_discriminants = self.list_allowed_signed_entity_types_discriminants()?;
let signed_entity_types = allowed_discriminants
.into_iter()
.map(|discriminant| SignedEntityType::from_beacon(&discriminant, beacon))
.map(|discriminant| {
SignedEntityType::from_time_point(&discriminant, &self.network, time_point)
})
.collect();

Ok(signed_entity_types)
Expand Down Expand Up @@ -502,16 +504,20 @@ mod test {

#[test]
fn test_list_allowed_signed_entity_types_without_specific_configuration() {
let beacon = fake_data::beacon();
let config = Configuration {
signed_entity_types: None,
network: beacon.network.clone(),
..Configuration::new_sample()
};
let beacon = fake_data::beacon();
let time_point = TimePoint::new(*beacon.epoch, beacon.immutable_file_number);

let discriminants = config
.list_allowed_signed_entity_types_discriminants()
.unwrap();
let signed_entity_types = config.list_allowed_signed_entity_types(&beacon).unwrap();
let signed_entity_types = config
.list_allowed_signed_entity_types(&time_point)
.unwrap();

assert_eq!(
vec![
Expand All @@ -531,18 +537,22 @@ mod test {

#[test]
fn test_list_allowed_signed_entity_types_with_specific_configuration() {
let beacon = fake_data::beacon();
let config = Configuration {
network: beacon.network.clone(),
signed_entity_types: Some(
"MithrilStakeDistribution,Unknown, CardanoStakeDistribution".to_string(),
),
..Configuration::new_sample()
};
let beacon = fake_data::beacon();
let time_point = TimePoint::new(*beacon.epoch, beacon.immutable_file_number);

let discriminants = config
.list_allowed_signed_entity_types_discriminants()
.unwrap();
let signed_entity_types = config.list_allowed_signed_entity_types(&beacon).unwrap();
let signed_entity_types = config
.list_allowed_signed_entity_types(&time_point)
.unwrap();

assert_eq!(
vec![
Expand Down
80 changes: 80 additions & 0 deletions mithril-aggregator/src/database/migration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -619,5 +619,85 @@ insert into signed_entity_type (signed_entity_type_id, name)
values (3, 'Cardano Transactions');
"#,
),
// Migration 22
// Certificate table:
// * Remove beacon
// * Add network, immutable file number, signed_entity_type_id, signed_entity_type columns
SqlMigration::new(
22,
r#"
-- disable foreign keys since we will delete tables linked using them
pragma foreign_keys=false;

CREATE TABLE IF NOT EXISTS "new_certificate" (
certificate_id text not null,
parent_certificate_id text,
message text not null,
signature text not null,
aggregate_verification_key text not null,
epoch integer not null,
network text not null,
immutable_file_number integer not null,
signed_entity_type_id integer not null,
signed_entity_beacon json not null,
protocol_version text not null,
protocol_parameters json not null,
protocol_message json not null,
signers json not null,
initiated_at text not null,
sealed_at text not null,
primary key (certificate_id),
foreign key (parent_certificate_id) references certificate(certificate_id)
foreign key (signed_entity_type_id) references signed_entity_type(signed_entity_type_id)
);

insert into new_certificate
( certificate_id, parent_certificate_id, message, signature, aggregate_verification_key,
epoch,
network,
immutable_file_number,
signed_entity_type_id,
signed_entity_beacon,
protocol_version, protocol_parameters, protocol_message,
signers, initiated_at, sealed_at)
select c.certificate_id, c.parent_certificate_id, c.message, c.signature, c.aggregate_verification_key,
c.epoch,
json_extract(c.beacon, '$.network'),
json_extract(c.beacon, '$.immutable_file_number'),
-- genesis certificate doesn't have a signed_entity, we can just use directly the MithrilStakeDistribution
coalesce(s.signed_entity_type_id, 0),
-- genesis certificate doesn't have a signed_entity, so we need to deduce it from the old certificate
coalesce(s.beacon, c.epoch),
c.protocol_version, c.protocol_parameters, c.protocol_message,
c.signers, c.initiated_at, c.sealed_at
from certificate c
left join signed_entity s on s.certificate_id = c.certificate_id
order by c.rowid asc;


drop table certificate;
alter table new_certificate rename to certificate;

CREATE INDEX epoch_index on certificate(epoch);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need an index on signed_entity_type_id?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question, we did no indexes on any of our foreign key columns whatever the table. If we changes stance on that maybe we should do that on a dedicated ticket ?


-- reenable foreign keys
pragma foreign_key_check;
pragma foreign_keys=true;
"#,
),
// Migration 23
// Alter `pending_certificate` table to use only an Epoch instead of a full beacon.
SqlMigration::new(
23,
r#"
create table if not exists pending_certificate (key_hash text primary key, key json not null, value json not null);
update pending_certificate
set value =
json_remove(
json_insert(value, '$.epoch', json_extract(value, '$.beacon.epoch')),
'$.beacon'
);
"#,
),
]
}
Loading