From ddcee57f1e9e0b71c80155ad66f40afbf7d26ce5 Mon Sep 17 00:00:00 2001 From: Thomas Dinsdale-Young Date: Wed, 4 Dec 2024 16:43:02 +0100 Subject: [PATCH 1/6] Support for inactive validator events. --- concordium-base | 2 +- src/types/mod.rs | 33 ++ src/types/queries.rs | 2 + src/types/summary_helper.rs | 26 ++ src/v2/conversions.rs | 37 ++ src/v2/generated/concordium.v2.rs | 743 +++++++++++++++++++++++++++++- src/v2/proto_schema_version.rs | 2 +- 7 files changed, 831 insertions(+), 14 deletions(-) diff --git a/concordium-base b/concordium-base index e83282f25..f15b9aa87 160000 --- a/concordium-base +++ b/concordium-base @@ -1 +1 @@ -Subproject commit e83282f25b4e71f3725352c6a774fd0472824a90 +Subproject commit f15b9aa87aea9a20946f63871b539f6ab9906008 diff --git a/src/types/mod.rs b/src/types/mod.rs index fdae82d24..6db5d6c92 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -891,6 +891,23 @@ pub enum SpecialTransactionOutcome { /// Accrued finalization rewards for pool. finalization_reward: Amount, }, + /// A validator was suspended due to too many missed rounds. + #[serde(rename_all = "camelCase")] + ValidatorSuspended { + /// The validator that was suspended. + baker_id: BakerId, + /// The account address of the validator. + account: AccountAddress, + }, + /// A validator was primed to be suspended at the next snapshot epoch due to + /// too many missed rounds. + #[serde(rename_all = "camelCase")] + ValidatorPrimedForSuspension { + /// The validator that was primed for suspension. + baker_id: BakerId, + /// The account address of the validator. + account: AccountAddress, + }, } impl SpecialTransactionOutcome { @@ -923,6 +940,12 @@ impl SpecialTransactionOutcome { SpecialTransactionOutcome::PaydayAccountReward { account, .. } => vec![*account], SpecialTransactionOutcome::BlockAccrueReward { .. } => Vec::new(), SpecialTransactionOutcome::PaydayPoolReward { .. } => Vec::new(), + SpecialTransactionOutcome::ValidatorSuspended { account, .. } => { + vec![*account] + } + SpecialTransactionOutcome::ValidatorPrimedForSuspension { account, .. } => { + vec![*account] + } } } } @@ -2111,6 +2134,16 @@ pub enum BakerEvent { /// from the account immediately. delegator_id: DelegatorId, }, + /// The baker was suspended. + BakerSuspended { + // Baker's id + baker_id: BakerId, + }, + /// The baker was suspended. + BakerResumed { + // Baker's id + baker_id: BakerId, + }, } #[derive(Debug, Clone)] diff --git a/src/types/queries.rs b/src/types/queries.rs index 46a5df2f0..2d6e6cdfc 100644 --- a/src/types/queries.rs +++ b/src/types/queries.rs @@ -322,6 +322,8 @@ pub enum PendingUpdateEffect { BlockEnergyLimit(Energy), #[serde(rename = "finalizationCommitteeParameters")] FinalizationCommitteeParameters(FinalizationCommitteeParameters), + #[serde(rename = "validatorScoreParameters")] + ValidatorScoreParameters(ValidatorScoreParameters), } #[derive(Debug, Copy, Clone, PartialEq, Eq)] diff --git a/src/types/summary_helper.rs b/src/types/summary_helper.rs index 9e830d280..3a3cd2008 100644 --- a/src/types/summary_helper.rs +++ b/src/types/summary_helper.rs @@ -354,6 +354,20 @@ pub(crate) enum Event { /// The new module reference that is in effect after the upgrade. to: smart_contracts::ModuleReference, }, + #[serde(rename_all = "camelCase")] + BakerSuspended { + /// Baker's id + baker_id: BakerId, + /// Baker account + account: AccountAddress, + }, + #[serde(rename_all = "camelCase")] + BakerResumed { + /// Baker's id + baker_id: BakerId, + /// Baker account + account: AccountAddress, + }, } impl From for Event { @@ -693,6 +707,18 @@ impl From for BlockItemSummary { account: sender, } } + super::BakerEvent::BakerSuspended { baker_id } => { + Event::BakerSuspended { + baker_id, + account: sender, + } + } + super::BakerEvent::BakerResumed { baker_id } => { + Event::BakerResumed { + baker_id, + account: sender, + } + } }) .collect(); (Some(ty), BlockItemResult::Success { events }) diff --git a/src/v2/conversions.rs b/src/v2/conversions.rs index 5933fbe21..620b6052b 100644 --- a/src/v2/conversions.rs +++ b/src/v2/conversions.rs @@ -447,6 +447,7 @@ impl From for super::types::ProtocolVersion { ProtocolVersion::ProtocolVersion5 => super::types::ProtocolVersion::P5, ProtocolVersion::ProtocolVersion6 => super::types::ProtocolVersion::P6, ProtocolVersion::ProtocolVersion7 => super::types::ProtocolVersion::P7, + ProtocolVersion::ProtocolVersion8 => super::types::ProtocolVersion::P8, } } } @@ -461,6 +462,7 @@ impl From for ProtocolVersion { super::types::ProtocolVersion::P5 => ProtocolVersion::ProtocolVersion5, super::types::ProtocolVersion::P6 => ProtocolVersion::ProtocolVersion6, super::types::ProtocolVersion::P7 => ProtocolVersion::ProtocolVersion7, + super::types::ProtocolVersion::P8 => ProtocolVersion::ProtocolVersion8, } } } @@ -1417,6 +1419,9 @@ impl TryFrom for super::types::UpdatePayload { update_payload::Payload::FinalizationCommitteeParametersUpdate(v) => { Self::FinalizationCommitteeParametersCPV2(v.try_into()?) } + update_payload::Payload::ValidatorScoreParametersUpdate(v) => { + Self::ValidatorScoreParametersCPV3(v.try_into()?) + } }) } } @@ -1941,6 +1946,12 @@ impl TryFrom for super::types::BakerEvent { baker_event::Event::DelegationRemoved(v) => Self::DelegationRemoved { delegator_id: v.delegator_id.require()?.try_into()?, }, + baker_event::Event::BakerSuspended(v) => Self::BakerSuspended { + baker_id: v.baker_id.require()?.into(), + }, + baker_event::Event::BakerResumed(v) => Self::BakerResumed { + baker_id: v.baker_id.require()?.into(), + }, }) } } @@ -2864,6 +2875,18 @@ impl TryFrom for super::types::SpecialTransactionOutcome { baker_reward: event.baker_reward.require()?.into(), finalization_reward: event.finalization_reward.require()?.into(), }, + block_special_event::Event::ValidatorSuspended(event) => Self::ValidatorSuspended { + baker_id: event.baker_id.require()?.into(), + // FIXME: Handle this + account: event.account.require()?.try_into()?, + }, + block_special_event::Event::ValidatorPrimedForSuspension(event) => { + Self::ValidatorPrimedForSuspension { + baker_id: event.baker_id.require()?.into(), + // FIXME: Handle this + account: event.account.require()?.try_into()?, + } + } }; Ok(event) } @@ -3006,6 +3029,16 @@ impl TryFrom for updates::FinalizationCommittee } } +impl TryFrom for updates::ValidatorScoreParameters { + type Error = tonic::Status; + + fn try_from(value: ValidatorScoreParameters) -> Result { + Ok(Self { + max_missed_rounds: value.maximum_missed_rounds, + }) + } +} + impl TryFrom for updates::PoolParameters { type Error = tonic::Status; @@ -3213,6 +3246,10 @@ impl TryFrom for super::types::queries::PendingUpdate { effective_time, effect: PendingUpdateEffect::FinalizationCommitteeParameters(update.try_into()?), }), + pending_update::Effect::ValidatorScoreParameters(update) => Ok(Self { + effective_time, + effect: PendingUpdateEffect::ValidatorScoreParameters(update.try_into()?), + }), } } } diff --git a/src/v2/generated/concordium.v2.rs b/src/v2/generated/concordium.v2.rs index 579fce8a2..561dbdacf 100644 --- a/src/v2/generated/concordium.v2.rs +++ b/src/v2/generated/concordium.v2.rs @@ -355,6 +355,14 @@ pub mod account_staking_info { /// baking committee of the current epoch. #[prost(message, optional, tag = "5")] pub pool_info: ::core::option::Option, + /// A flag indicating whether the account is currently suspended or not. + /// The flag has a meaning from protocol version 8 onwards. In + /// protocol version 8 it signals whether an account has been + /// suspended and is not participating in the consensus + /// algorithm. For protocol version < 8 the flag will always + /// be set to false. + #[prost(bool, tag = "6")] + pub is_suspended: bool, } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] @@ -1353,7 +1361,7 @@ pub mod reject_reason { /// A credential id that was to be removed is not part of the account. #[prost(message, tag = "35")] NonExistentCredIds(NonExistentCredIds), - /// Attempt to remove the first credential. + /// Attemp to remove the first credential. #[prost(message, tag = "36")] RemoveFirstCredential(super::Empty), /// The credential holder of the keys to be updated did not sign the @@ -1445,6 +1453,9 @@ pub struct ContractInitializedEvent { /// initialization. #[prost(message, repeated, tag = "6")] pub events: ::prost::alloc::vec::Vec, + /// The parameter passed to the initializer. + #[prost(message, optional, tag = "7")] + pub parameter: ::core::option::Option, } /// An event generated by a smart contract. #[allow(clippy::derive_partial_eq_without_eq)] @@ -1668,7 +1679,7 @@ pub struct RegisteredData { pub struct BakerEvent { #[prost( oneof = "baker_event::Event", - tags = "1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12" + tags = "1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14" )] pub event: ::core::option::Option, } @@ -1784,6 +1795,22 @@ pub mod baker_event { #[prost(message, optional, tag = "1")] pub delegator_id: ::core::option::Option, } + /// A baker has been suspended. + #[allow(clippy::derive_partial_eq_without_eq)] + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct BakerSuspended { + /// Suspended baker's id + #[prost(message, optional, tag = "1")] + pub baker_id: ::core::option::Option, + } + /// A baker has been resumed. + #[allow(clippy::derive_partial_eq_without_eq)] + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct BakerResumed { + /// The resumed baker's id + #[prost(message, optional, tag = "1")] + pub baker_id: ::core::option::Option, + } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum Event { @@ -1823,6 +1850,12 @@ pub mod baker_event { /// An existing delegator was removed. #[prost(message, tag = "12")] DelegationRemoved(DelegationRemoved), + /// The baker's account has been suspended. + #[prost(message, tag = "13")] + BakerSuspended(BakerSuspended), + /// The baker's account has been suspended. + #[prost(message, tag = "14")] + BakerResumed(BakerResumed), } } /// The identifier for a delegator. @@ -2147,6 +2180,13 @@ pub struct FinalizationCommitteeParameters { #[prost(message, optional, tag = "3")] pub finalizer_relative_stake_threshold: ::core::option::Option, } +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ValidatorScoreParameters { + /// The maximal number of missed rounds before a validator gets suspended. + #[prost(uint64, tag = "1")] + pub maximum_missed_rounds: u64, +} /// Parameters for the consensus protocol used from protocol version 6. #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] @@ -2668,7 +2708,7 @@ pub mod level1_update { pub struct UpdatePayload { #[prost( oneof = "update_payload::Payload", - tags = "1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22" + tags = "1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23" )] pub payload: ::core::option::Option, } @@ -2744,6 +2784,9 @@ pub mod update_payload { /// Finalization committee parameters (chain parameters version 2). #[prost(message, tag = "22")] FinalizationCommitteeParametersUpdate(super::FinalizationCommitteeParameters), + /// Validator score parameters (chain parameters version 3) + #[prost(message, tag = "23")] + ValidatorScoreParametersUpdate(super::ValidatorScoreParameters), } } /// Details about an account transaction. @@ -3526,7 +3569,10 @@ pub mod election_info { #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct BlockSpecialEvent { - #[prost(oneof = "block_special_event::Event", tags = "1, 2, 3, 4, 5, 6, 7, 8")] + #[prost( + oneof = "block_special_event::Event", + tags = "1, 2, 3, 4, 5, 6, 7, 8, 9, 10" + )] pub event: ::core::option::Option, } /// Nested message and enum types in `BlockSpecialEvent`. @@ -3694,6 +3740,29 @@ pub mod block_special_event { #[prost(message, optional, tag = "4")] pub finalization_reward: ::core::option::Option, } + /// The id of a validator that got suspended due to too many missed rounds. + #[allow(clippy::derive_partial_eq_without_eq)] + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct ValidatorSuspended { + /// The id of the suspended validator. + #[prost(message, optional, tag = "1")] + pub baker_id: ::core::option::Option, + /// The account of the suspended validator. + #[prost(message, optional, tag = "2")] + pub account: ::core::option::Option, + } + /// The id of a validator that is primed for suspension at the next snapshot + /// epoch due to too many missed rounds. + #[allow(clippy::derive_partial_eq_without_eq)] + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct ValidatorPrimedForSuspension { + /// The id of the primed validator. + #[prost(message, optional, tag = "1")] + pub baker_id: ::core::option::Option, + /// The account of the primed validator. + #[prost(message, optional, tag = "2")] + pub account: ::core::option::Option, + } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum Event { @@ -3713,6 +3782,10 @@ pub mod block_special_event { BlockAccrueReward(BlockAccrueReward), #[prost(message, tag = "8")] PaydayPoolReward(PaydayPoolReward), + #[prost(message, tag = "9")] + ValidatorSuspended(ValidatorSuspended), + #[prost(message, tag = "10")] + ValidatorPrimedForSuspension(ValidatorPrimedForSuspension), } } /// A pending update. @@ -3726,7 +3799,7 @@ pub struct PendingUpdate { #[prost( oneof = "pending_update::Effect", tags = "2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, \ - 24, 25" + 24, 25, 26" )] pub effect: ::core::option::Option, } @@ -3804,7 +3877,7 @@ pub mod pending_update { /// Updates to the consensus timeouts for chain parameters version 2. #[prost(message, tag = "22")] TimeoutParameters(super::TimeoutParameters), - /// Updates to the minimum time between blocks for chain parameters + /// Updates to the the minimum time between blocks for chain parameters /// version 2. #[prost(message, tag = "23")] MinBlockTime(super::Duration), @@ -3815,6 +3888,10 @@ pub mod pending_update { /// version 2. #[prost(message, tag = "25")] FinalizationCommitteeParameters(super::FinalizationCommitteeParameters), + /// Updates to the validator score parameters for chain parameters + /// version 3. + #[prost(message, tag = "26")] + ValidatorScoreParameters(super::ValidatorScoreParameters), } } /// The response for `GetNextUpdateSequenceNumbers`. @@ -3874,7 +3951,7 @@ pub struct NextUpdateSequenceNumbers { /// Updates to the timeout parameters #[prost(message, optional, tag = "17")] pub timeout_parameters: ::core::option::Option, - /// Updates to the minimum time between blocks for chain parameters + /// Updates to the the minimum time between blocks for chain parameters /// version 2. #[prost(message, optional, tag = "18")] pub min_block_time: ::core::option::Option, @@ -3884,6 +3961,10 @@ pub struct NextUpdateSequenceNumbers { /// Updates to the finalization committee parameters #[prost(message, optional, tag = "20")] pub finalization_committee_parameters: ::core::option::Option, + /// Updates to the validator score parameters for chain parameters version + /// 3. + #[prost(message, optional, tag = "21")] + pub validator_score_parameters: ::core::option::Option, } /// A request to send a new block item to the chain. /// An IP address @@ -4678,6 +4759,62 @@ pub struct ChainParametersV2 { #[prost(message, optional, tag = "15")] pub finalization_committee_parameters: ::core::option::Option, } +/// Updatable chain parameters that apply to protocol versions 8. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ChainParametersV3 { + /// Consensus parameters. + #[prost(message, optional, tag = "1")] + pub consensus_parameters: ::core::option::Option, + /// Euro per energy exchange rate. + #[prost(message, optional, tag = "2")] + pub euro_per_energy: ::core::option::Option, + /// Micro CCD per euro exchange rate. + #[prost(message, optional, tag = "3")] + pub micro_ccd_per_euro: ::core::option::Option, + /// Extra number of epochs before reduction in stake, or baker + /// deregistration is completed. + #[prost(message, optional, tag = "4")] + pub cooldown_parameters: ::core::option::Option, + /// Current time parameters. + /// The time parameters indicates the mint rate and the + /// reward period length, i.e. the time between paydays. + #[prost(message, optional, tag = "5")] + pub time_parameters: ::core::option::Option, + /// The limit for the number of account creations in a block. + #[prost(message, optional, tag = "6")] + pub account_creation_limit: ::core::option::Option, + /// Current mint distribution + #[prost(message, optional, tag = "7")] + pub mint_distribution: ::core::option::Option, + /// Current transaction fee distribution. + #[prost(message, optional, tag = "8")] + pub transaction_fee_distribution: ::core::option::Option, + /// Current gas reward parameters. + #[prost(message, optional, tag = "9")] + pub gas_rewards: ::core::option::Option, + /// The foundation account. + #[prost(message, optional, tag = "10")] + pub foundation_account: ::core::option::Option, + /// Parameters governing baking pools and their commissions. + #[prost(message, optional, tag = "11")] + pub pool_parameters: ::core::option::Option, + /// Keys allowed to do root updates. + #[prost(message, optional, tag = "12")] + pub root_keys: ::core::option::Option, + /// Keys allowed to do level1 updates; + #[prost(message, optional, tag = "13")] + pub level1_keys: ::core::option::Option, + /// Keys allowed to do parameter updates. + #[prost(message, optional, tag = "14")] + pub level2_keys: ::core::option::Option, + /// Finalization committee parameters + #[prost(message, optional, tag = "15")] + pub finalization_committee_parameters: ::core::option::Option, + /// Validator score parameters + #[prost(message, optional, tag = "16")] + pub validator_score_parameters: ::core::option::Option, +} /// Chain parameters. #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] @@ -4823,7 +4960,7 @@ pub struct BakerRewardPeriodInfo { #[prost(bool, tag = "6")] pub is_finalizer: bool, } -/// The signature of a 'QuorumCertificate'. +/// The signature of a 'QuorumCertificate' or 'QuorumMessage'. #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct QuorumSignature { @@ -5392,6 +5529,435 @@ pub mod dry_run_success_response { TransactionExecuted(TransactionExecuted), } } +/// The index of a particular finalizer in the finalization committee. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct FinalizerIndex { + #[prost(uint32, tag = "1")] + pub value: u32, +} +/// The message that is multicast by a finalizer when validating and signing a +/// block. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QuorumMessage { + /// Signature on the relevant quorum signature message. + #[prost(message, optional, tag = "1")] + pub signature: ::core::option::Option, + /// Hash of the block that is signed. + #[prost(message, optional, tag = "2")] + pub block: ::core::option::Option, + /// Index of the finalizer signing the message. + #[prost(message, optional, tag = "3")] + pub finalizer: ::core::option::Option, + /// Round of the block. + #[prost(message, optional, tag = "4")] + pub round: ::core::option::Option, + /// Epoch of the block. + #[prost(message, optional, tag = "5")] + pub epoch: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct RawQuorumCertificate { + /// The hash of the block that the quorum certificate refers to. + #[prost(message, optional, tag = "1")] + pub block_hash: ::core::option::Option, + /// The round of the block. + #[prost(message, optional, tag = "2")] + pub round: ::core::option::Option, + /// The epoch of the block. + #[prost(message, optional, tag = "3")] + pub epoch: ::core::option::Option, + /// The aggregated signature by the finalization committee on the block. + #[prost(message, optional, tag = "4")] + pub aggregate_signature: ::core::option::Option, + /// A list of the finalizers that formed the quorum certificate + /// i.e., the ones who have contributed to the 'aggregate_signature'. + /// The finalizers are identified by their finalizer index, which refers to + /// the finalization committee for the epoch. + #[prost(message, repeated, tag = "5")] + pub signatories: ::prost::alloc::vec::Vec, +} +/// A (non-aggregate) signature of a validator. This is used to sign blocks +/// produced by the validator as well as some finalization messages. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct BlockSignature { + #[prost(bytes = "vec", tag = "1")] + pub value: ::prost::alloc::vec::Vec, +} +/// A timeout message including the sender's signature. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TimeoutMessage { + /// Index of the finalizer signing the message. + #[prost(message, optional, tag = "1")] + pub finalizer: ::core::option::Option, + /// Round which timed out. + #[prost(message, optional, tag = "2")] + pub round: ::core::option::Option, + /// Current epoch number of the finalizer sending the timeout message. + /// This can be different from the epoch of the quorum certificate. + #[prost(message, optional, tag = "3")] + pub epoch: ::core::option::Option, + /// Highest quorum certificate known to the finalizer at the time of + /// timeout. + #[prost(message, optional, tag = "4")] + pub quorum_certificate: ::core::option::Option, + /// Signature on the appropriate timeout signature message. + #[prost(message, optional, tag = "5")] + pub signature: ::core::option::Option, + /// Signature of the finalizer on the timeout message as a whole. + #[prost(message, optional, tag = "6")] + pub message_signature: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct RawFinalizerRound { + /// The round that was signed off. + #[prost(message, optional, tag = "1")] + pub round: ::core::option::Option, + /// The finalizers (identified by their 'FinalizerIndex') that + /// signed off in 'round'. + #[prost(message, repeated, tag = "2")] + pub finalizers: ::prost::alloc::vec::Vec, +} +/// A timeout certificate is the certificate that the +/// finalization committee issues when a round times out, +/// thus making it possible for the protocol to proceed to the +/// next round. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct RawTimeoutCertificate { + /// The round that timed out. + #[prost(message, optional, tag = "1")] + pub round: ::core::option::Option, + /// The minimum epoch of which signatures are included + /// in the 'aggregate_signature'. + #[prost(message, optional, tag = "2")] + pub min_epoch: ::core::option::Option, + /// The rounds of which finalizers have their best + /// QCs in the 'min_epoch'. + #[prost(message, repeated, tag = "3")] + pub qc_rounds_first_epoch: ::prost::alloc::vec::Vec, + /// The rounds of which finalizers have their best + /// QCs in the epoch 'min_epoch' + 1. + #[prost(message, repeated, tag = "4")] + pub qc_rounds_second_epoch: ::prost::alloc::vec::Vec, + /// The aggregated signature by the finalization committee that witnessed + /// the 'round' timed out. + #[prost(message, optional, tag = "5")] + pub aggregate_signature: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PersistentRoundStatus { + /// The last signed quorum message by the node. + #[prost(message, optional, tag = "1")] + pub last_signed_quorum_message: ::core::option::Option, + /// The last signed timeout message by the node. + #[prost(message, optional, tag = "2")] + pub last_signed_timeout_message: ::core::option::Option, + /// The last round the node baked in. + #[prost(message, optional, tag = "3")] + pub last_baked_round: ::core::option::Option, + /// The latest timeout certificate seen by the node. May be absent if the + /// node has seen a quorum certificate for a more recent round. + #[prost(message, optional, tag = "4")] + pub latest_timeout: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct RoundTimeout { + /// Timeout certificate for the round that timed out. + #[prost(message, optional, tag = "1")] + pub timeout_certificate: ::core::option::Option, + /// The highest known quorum certificate when the round timed out. + #[prost(message, optional, tag = "2")] + pub quorum_certificate: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct RawFinalizationEntry { + /// The quorum certificate for the finalized block. + #[prost(message, optional, tag = "1")] + pub finalized_qc: ::core::option::Option, + /// The quorum certificate for the block that finalizes + /// the block that 'finalized_qc' points to. + #[prost(message, optional, tag = "2")] + pub successor_qc: ::core::option::Option, + /// A proof that the successor block is an immediate + /// successor of the finalized block. + #[prost(message, optional, tag = "3")] + pub successor_proof: ::core::option::Option, +} +/// The current round status. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct RoundStatus { + /// The current round from the perspective of the node. + /// This should always be higher than the round of the highest certified + /// block. If the previous round did not timeout, it should be one more + /// than the round of the `highest_certified_block`. Otherwise, it + /// should be one more than the round of the `previous_round_timeout`. + #[prost(message, optional, tag = "1")] + pub current_round: ::core::option::Option, + /// The quorum certificate for the highest certified block. + #[prost(message, optional, tag = "2")] + pub highest_certified_block: ::core::option::Option, + /// If the last round timed out, this is the timeout certificate for that + /// round and the highest quorum certificate at the time the round timed + /// out. + #[prost(message, optional, tag = "3")] + pub previous_round_timeout: ::core::option::Option, + /// Flag indicating whether the node should attempt to bake in the current + /// round. This is set to true when the round is advanced, and set to + /// false once the node has attempted to bake for the round. + #[prost(bool, tag = "4")] + pub round_eligible_to_bake: bool, + /// The current epoch. This should either be the same as the epoch of the + /// last finalized block (if its timestamp is before the trigger block + /// time) or the next epoch from the last finalized block (if its + /// timestamp is at least the trigger block time). + #[prost(message, optional, tag = "5")] + pub current_epoch: ::core::option::Option, + /// If present, an epoch finalization entry for the epoch before + /// `current_epoch`. An entry must be present if the current epoch is + /// greater than the epoch of the last finalized block. + #[prost(message, optional, tag = "6")] + pub last_epoch_finalization_entry: ::core::option::Option, + /// The current duration the node will wait before a round times out. + #[prost(message, optional, tag = "7")] + pub current_timeout: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct BlockTableSummary { + /// The number of blocks in the dead block cache. + #[prost(uint64, tag = "1")] + pub dead_block_cache_size: u64, + /// The blocks that are currently live (not dead and not finalized). + #[prost(message, repeated, tag = "2")] + pub live_blocks: ::prost::alloc::vec::Vec, +} +/// A list of block hashes at a particular branch height. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct BranchBlocks { + #[prost(message, repeated, tag = "1")] + pub blocks_at_branch_height: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct RoundExistingBlock { + /// The round for which the node saw a block. + #[prost(message, optional, tag = "1")] + pub round: ::core::option::Option, + /// The baker that baked the block. + #[prost(message, optional, tag = "2")] + pub baker: ::core::option::Option, + /// The hash of the block. + #[prost(message, optional, tag = "3")] + pub block: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct RoundExistingQc { + /// The round for which a QC was seen. + #[prost(message, optional, tag = "1")] + pub round: ::core::option::Option, + /// The epoch of the QC. + #[prost(message, optional, tag = "2")] + pub epoch: ::core::option::Option, +} +/// The keys an stake of a specific baker. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct FullBakerInfo { + /// The baker's identity. + #[prost(message, optional, tag = "1")] + pub baker_identity: ::core::option::Option, + /// The baker's election verify key. + #[prost(message, optional, tag = "2")] + pub election_verify_key: ::core::option::Option, + /// The baker's signature verify key. + #[prost(message, optional, tag = "3")] + pub signature_verify_key: ::core::option::Option, + /// The baker's aggregation verify key. + #[prost(message, optional, tag = "4")] + pub aggregation_verify_key: ::core::option::Option, + /// The stake of the baker. + #[prost(message, optional, tag = "5")] + pub stake: ::core::option::Option, +} +/// The hash of the finalization committee, derived from the weights and +/// aggregation keys of the finalizers. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct FinalizationCommitteeHash { + #[prost(bytes = "vec", tag = "1")] + pub value: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct BakersAndFinalizers { + /// The set of bakers. + #[prost(message, repeated, tag = "1")] + pub bakers: ::prost::alloc::vec::Vec, + /// The IDs of the bakers that are finalizers. + /// The order determines the finalizer index. + #[prost(message, repeated, tag = "2")] + pub finalizers: ::prost::alloc::vec::Vec, + /// The total effective stake of the bakers. + #[prost(message, optional, tag = "3")] + pub baker_total_stake: ::core::option::Option, + /// The total effective stake of the finalizers. + #[prost(message, optional, tag = "4")] + pub finalizer_total_stake: ::core::option::Option, + /// The hash of the finalization committee. + #[prost(message, optional, tag = "5")] + pub finalization_committee_hash: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct EpochBakers { + /// The bakers and finalizers for the previous epoch. + /// If the current epoch is 0, then this is the same as the bakers for the + /// current epoch. + #[prost(message, optional, tag = "1")] + pub previous_epoch_bakers: ::core::option::Option, + /// The bakers and finalizers for the current epoch. + /// If this is absent, it should be treated as the same as the bakers for + /// the previous epoch. + #[prost(message, optional, tag = "2")] + pub current_epoch_bakers: ::core::option::Option, + /// The bakers and finalizers for the next epoch. + /// If this is absent, it should be treated as the same as the bakers for + /// the current epoch. + #[prost(message, optional, tag = "3")] + pub next_epoch_bakers: ::core::option::Option, + /// The first epoch of the next payday. + #[prost(message, optional, tag = "4")] + pub next_payday: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TimeoutMessages { + /// The first epoch for which timeout messages are present. + #[prost(message, optional, tag = "1")] + pub first_epoch: ::core::option::Option, + /// The timeout messages for the first epoch. + /// There should always be at least one. + #[prost(message, repeated, tag = "2")] + pub first_epoch_timeouts: ::prost::alloc::vec::Vec, + /// The timeout messages for `first_epoch + 1`. + #[prost(message, repeated, tag = "3")] + pub second_epoch_timeouts: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct AggregatedSignatures { + /// The block hash for which the signatures are aggregated. + #[prost(message, optional, tag = "1")] + pub signed_block: ::core::option::Option, + /// The total weight of the finalizers that signed the block. + #[prost(message, optional, tag = "2")] + pub signature_weight: ::core::option::Option, + /// The aggregate signature of the finalizers. + #[prost(message, optional, tag = "3")] + pub aggregate_signature: ::core::option::Option, + /// The set of finalizers that have signed. + #[prost(message, repeated, tag = "4")] + pub signatories: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QuorumMessages { + /// The collected quorum messages for the current round. + #[prost(message, repeated, tag = "1")] + pub quorum_messages: ::prost::alloc::vec::Vec, + /// The current aggregate of the valid quorum messages. + #[prost(message, repeated, tag = "2")] + pub aggregated_signatures: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ConsensusDetailedStatusQuery { + /// If specified, this determines the genesis index to get status for. + /// If not specified, the status is returned for the latest genesis index. + #[prost(message, optional, tag = "1")] + pub genesis_index: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ConsensusDetailedStatus { + /// The hash of the genesis block. + #[prost(message, optional, tag = "1")] + pub genesis_block: ::core::option::Option, + /// The persisted elements of the round status. + #[prost(message, optional, tag = "2")] + pub persistent_round_status: ::core::option::Option, + /// The status of the current round. + #[prost(message, optional, tag = "3")] + pub round_status: ::core::option::Option, + /// The number of non-finalized transactions. + #[prost(uint64, tag = "4")] + pub non_finalized_transaction_count: u64, + /// The purge counter for the transaction table. + #[prost(int64, tag = "5")] + pub transaction_table_purge_counter: i64, + /// Summary of the block table. + #[prost(message, optional, tag = "6")] + pub block_table: ::core::option::Option, + /// The live blocks organized by height after the last finalized block. + #[prost(message, repeated, tag = "7")] + pub branches: ::prost::alloc::vec::Vec, + /// Which bakers the node has seen legally-signed blocks with live parents + /// from in non-finalized rounds. + #[prost(message, repeated, tag = "8")] + pub round_existing_blocks: ::prost::alloc::vec::Vec, + /// Which non-finalized rounds the node has seen quorum certificates for. + #[prost(message, repeated, tag = "9")] + pub round_existing_qcs: ::prost::alloc::vec::Vec, + /// The absolute block height of the genesis block of the era. + #[prost(message, optional, tag = "10")] + pub genesis_block_height: ::core::option::Option, + /// The hash of the last finalized block. + #[prost(message, optional, tag = "11")] + pub last_finalized_block: ::core::option::Option, + /// The height of the last finalized block. + #[prost(message, optional, tag = "12")] + pub last_finalized_block_height: ::core::option::Option, + /// Unless the last finalized block is the genesis block, this should be a + /// finalization entry for the last finalized block. + /// As this includes a quorum certificate for the last finalized block, that + /// can be used to determine the epoch and round of the last finalized + /// block. + #[prost(message, optional, tag = "13")] + pub latest_finalization_entry: ::core::option::Option, + /// The bakers and finalizers for the previous, current and next epoch, + /// relative to the last finalized block. + #[prost(message, optional, tag = "14")] + pub epoch_bakers: ::core::option::Option, + /// The timeout messages collected by the node for the current round. + #[prost(message, optional, tag = "15")] + pub timeout_messages: ::core::option::Option, + /// If a protocol update has occurred, this is the hash of the terminal + /// block. + #[prost(message, optional, tag = "16")] + pub terminal_block: ::core::option::Option, +} +/// Indicates that an account is pending -- either a scheduled release or a +/// cooldown -- and when the first release or cooldown will elapse. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct AccountPending { + #[prost(message, optional, tag = "1")] + pub account_index: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub first_timestamp: ::core::option::Option, +} /// Information about how open the pool is to new delegators. #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] #[repr(i32)] @@ -5508,6 +6074,7 @@ pub enum UpdateType { UpdateMinBlockTime = 17, UpdateBlockEnergyLimit = 18, UpdateFinalizationCommitteeParameters = 19, + UpdateValidatorScoreParameters = 20, } impl UpdateType { /// String value of the enum field names used in the ProtoBuf definition. @@ -5539,6 +6106,7 @@ impl UpdateType { UpdateType::UpdateFinalizationCommitteeParameters => { "UPDATE_FINALIZATION_COMMITTEE_PARAMETERS" } + UpdateType::UpdateValidatorScoreParameters => "UPDATE_VALIDATOR_SCORE_PARAMETERS", } } @@ -5567,6 +6135,7 @@ impl UpdateType { "UPDATE_FINALIZATION_COMMITTEE_PARAMETERS" => { Some(Self::UpdateFinalizationCommitteeParameters) } + "UPDATE_VALIDATOR_SCORE_PARAMETERS" => Some(Self::UpdateValidatorScoreParameters), _ => None, } } @@ -5670,6 +6239,7 @@ pub enum ProtocolVersion { ProtocolVersion5 = 4, ProtocolVersion6 = 5, ProtocolVersion7 = 6, + ProtocolVersion8 = 7, } impl ProtocolVersion { /// String value of the enum field names used in the ProtoBuf definition. @@ -5686,6 +6256,7 @@ impl ProtocolVersion { ProtocolVersion::ProtocolVersion5 => "PROTOCOL_VERSION_5", ProtocolVersion::ProtocolVersion6 => "PROTOCOL_VERSION_6", ProtocolVersion::ProtocolVersion7 => "PROTOCOL_VERSION_7", + ProtocolVersion::ProtocolVersion8 => "PROTOCOL_VERSION_8", } } @@ -5699,6 +6270,7 @@ impl ProtocolVersion { "PROTOCOL_VERSION_5" => Some(Self::ProtocolVersion5), "PROTOCOL_VERSION_6" => Some(Self::ProtocolVersion6), "PROTOCOL_VERSION_7" => Some(Self::ProtocolVersion7), + "PROTOCOL_VERSION_8" => Some(Self::ProtocolVersion8), _ => None, } } @@ -6662,6 +7234,123 @@ pub mod queries_client { self.inner.unary(req, path, codec).await } + /// Get all accounts that have scheduled releases, with the timestamp of + /// the first pending scheduled release for that account. (Note, + /// this only identifies accounts by index, and only indicates + /// the first pending release for each account.) + pub async fn get_scheduled_release_accounts( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response>, + tonic::Status, + > { + self.inner.ready().await.map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/concordium.v2.Queries/GetScheduledReleaseAccounts", + ); + let mut req = request.into_request(); + req.extensions_mut().insert(GrpcMethod::new( + "concordium.v2.Queries", + "GetScheduledReleaseAccounts", + )); + self.inner.server_streaming(req, path, codec).await + } + + /// Get all accounts that have stake in cooldown, with the timestamp of + /// the first pending cooldown expiry for each account. (Note, + /// this only identifies accounts by index, and only indicates + /// the first pending cooldown for each account.) + /// Prior to protocol version 7, the resulting stream will always be + /// empty. + pub async fn get_cooldown_accounts( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response>, + tonic::Status, + > { + self.inner.ready().await.map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = + http::uri::PathAndQuery::from_static("/concordium.v2.Queries/GetCooldownAccounts"); + let mut req = request.into_request(); + req.extensions_mut().insert(GrpcMethod::new( + "concordium.v2.Queries", + "GetCooldownAccounts", + )); + self.inner.server_streaming(req, path, codec).await + } + + /// Get all accounts that have stake in pre-cooldown. + /// (This only identifies accounts by index.) + /// Prior to protocol version 7, the resulting stream will always be + /// empty. + pub async fn get_pre_cooldown_accounts( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response>, + tonic::Status, + > { + self.inner.ready().await.map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/concordium.v2.Queries/GetPreCooldownAccounts", + ); + let mut req = request.into_request(); + req.extensions_mut().insert(GrpcMethod::new( + "concordium.v2.Queries", + "GetPreCooldownAccounts", + )); + self.inner.server_streaming(req, path, codec).await + } + + /// Get all accounts that have stake in pre-pre-cooldown. + /// (This only identifies accounts by index.) + /// Prior to protocol version 7, the resulting stream will always be + /// empty. + pub async fn get_pre_pre_cooldown_accounts( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response>, + tonic::Status, + > { + self.inner.ready().await.map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/concordium.v2.Queries/GetPrePreCooldownAccounts", + ); + let mut req = request.into_request(); + req.extensions_mut().insert(GrpcMethod::new( + "concordium.v2.Queries", + "GetPrePreCooldownAccounts", + )); + self.inner.server_streaming(req, path, codec).await + } + /// Get the projected earliest time at which a particular baker will be /// required to bake a block. If the current consensus version /// is 0, this returns the status 'Unavailable', as the endpoint @@ -6872,8 +7561,8 @@ pub mod queries_client { self.inner.unary(req, path, codec).await } - /// / Get a list of the peers that the node is connected to - /// / and assoicated network related information for each peer. + /// Get a list of the peers that the node is connected to + /// and assoicated network related information for each peer. pub async fn get_peers_info( &mut self, request: impl tonic::IntoRequest, @@ -7115,8 +7804,7 @@ pub mod queries_client { /// The following error cases are possible: /// * `NOT_FOUND` if the query specifies an unknown block. /// * `UNAVAILABLE` if the query is for an epoch that is not finalized - /// in the current genesis - /// / index, or is for a future genesis index. + /// in the current genesis index, or is for a future genesis index. /// * `INVALID_ARGUMENT` if the query is for an epoch that is not /// finalized for a past genesis index. /// * `INVALID_ARGUMENT` if the query is for a genesis index at @@ -7180,6 +7868,37 @@ pub mod queries_client { self.inner.unary(req, path, codec).await } + /// Get the detailed status of the consensus. This is only available for + /// consensus version 1. + /// + /// The following error cases are possible: + /// * `NOT_FOUND` if the query specifies an unknown genesis index. + /// * `INVALID_ARGUMENT` if the query specifies a genesis index at + /// consensus version 0. + /// * `UNIMPLEMENTED` if the endpoint is disabled on the node. + pub async fn get_consensus_detailed_status( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result, tonic::Status> + { + self.inner.ready().await.map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/concordium.v2.Queries/GetConsensusDetailedStatus", + ); + let mut req = request.into_request(); + req.extensions_mut().insert(GrpcMethod::new( + "concordium.v2.Queries", + "GetConsensusDetailedStatus", + )); + self.inner.unary(req, path, codec).await + } + /// Dry run a series of transactions and operations on a state derived /// from a specified block. The server should send a single /// `DryRunResponse` for each `DryRunRequest` received, unless diff --git a/src/v2/proto_schema_version.rs b/src/v2/proto_schema_version.rs index a65f80b87..6f774d155 100644 --- a/src/v2/proto_schema_version.rs +++ b/src/v2/proto_schema_version.rs @@ -1 +1 @@ -pub const PROTO_SCHEMA_VERSION: &str = "066a8514c1e89bbaa7989c708ae737fc466b0737"; +pub const PROTO_SCHEMA_VERSION: &str = "156b7ec751391c76847241c2912188bf8d46c3f9"; From 38ebef942a0e0b3e34c6a7b3688d17933cbd8864 Mon Sep 17 00:00:00 2001 From: Thomas Dinsdale-Young Date: Wed, 4 Dec 2024 16:54:08 +0100 Subject: [PATCH 2/6] Remove fixmes --- src/v2/conversions.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/v2/conversions.rs b/src/v2/conversions.rs index 620b6052b..4bb0efc7e 100644 --- a/src/v2/conversions.rs +++ b/src/v2/conversions.rs @@ -2877,13 +2877,11 @@ impl TryFrom for super::types::SpecialTransactionOutcome { }, block_special_event::Event::ValidatorSuspended(event) => Self::ValidatorSuspended { baker_id: event.baker_id.require()?.into(), - // FIXME: Handle this account: event.account.require()?.try_into()?, }, block_special_event::Event::ValidatorPrimedForSuspension(event) => { Self::ValidatorPrimedForSuspension { baker_id: event.baker_id.require()?.into(), - // FIXME: Handle this account: event.account.require()?.try_into()?, } } From 325ff3fe39383854ae0793571e3925b2c0717b42 Mon Sep 17 00:00:00 2001 From: Thomas Dinsdale-Young Date: Wed, 4 Dec 2024 17:10:34 +0100 Subject: [PATCH 3/6] Update CHANGELOG.md --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c057ce2e..734e4f907 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,15 @@ ## Unreleased changes - Add functionality for generating, and verifying account signatures. +- Support for protocol version 8 functionality: + - `ConfigureBakerPayload` supports the optional `suspend` flag. + - `BakerEvent` has new cases for `BakerSuspended` and `BakerResumed` when the flag is set in a + `ConfigureBaker` transaction. + - `SpecialTransactionOutcome` has new cases for `ValidatorSuspended` and + `ValidatorPrimedForSuspension`, which occur when a validator is (or potentially will be) + suspended. + - New `UpdatePayload` type `ValidatorScoreParametersCPV3`, which updates the maximum number of + consecutive failures a validator can have before it faces suspension. ## 5.0.0 From d5236ac891e1733591619431ced3fc2e0d879f9f Mon Sep 17 00:00:00 2001 From: Thomas Dinsdale-Young Date: Fri, 6 Dec 2024 15:47:48 +0100 Subject: [PATCH 4/6] Add `is_suspended` flag to Baker staking info. --- src/types/mod.rs | 5 +++++ src/v2/conversions.rs | 2 ++ 2 files changed, 7 insertions(+) diff --git a/src/types/mod.rs b/src/types/mod.rs index 6db5d6c92..ddbcf0c66 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -268,6 +268,11 @@ pub enum AccountStakingInfo { baker_info: Box, pending_change: Option, pool_info: Option, + /// A flag indicating whether the baker is currently suspended or not. + /// The flag will always be `false` for protocol versions before version + /// 8. A suspended validator will not be included in the validator + /// committee the next time it is calculated. + is_suspended: bool, }, /// The account is delegating stake to a baker. #[serde(rename_all = "camelCase")] diff --git a/src/v2/conversions.rs b/src/v2/conversions.rs index 4bb0efc7e..c53ad8b5e 100644 --- a/src/v2/conversions.rs +++ b/src/v2/conversions.rs @@ -562,12 +562,14 @@ impl TryFrom for super::types::AccountStakingInfo { None => None, Some(bi) => Some(bi.try_into()?), }; + let is_suspended = bsi.is_suspended; Ok(Self::Baker { staked_amount, restake_earnings, baker_info: Box::new(baker_info), pending_change, pool_info, + is_suspended, }) } account_staking_info::StakingInfo::Delegator(dsi) => { From 1dbe72ff9cab39e427a36c22e4cfea1efa3e56ad Mon Sep 17 00:00:00 2001 From: Thomas Dinsdale-Young Date: Fri, 6 Dec 2024 16:12:09 +0100 Subject: [PATCH 5/6] Update base. Support ChainParametersV3. --- concordium-base | 2 +- src/v2/conversions.rs | 41 ++++++++++++++++++++++++ src/v2/generated/concordium.v2.rs | 8 +++-- src/v2/mod.rs | 53 +++++++++++++++++++++++++++++-- src/v2/proto_schema_version.rs | 2 +- 5 files changed, 100 insertions(+), 6 deletions(-) diff --git a/concordium-base b/concordium-base index f15b9aa87..23f2746ee 160000 --- a/concordium-base +++ b/concordium-base @@ -1 +1 @@ -Subproject commit f15b9aa87aea9a20946f63871b539f6ab9906008 +Subproject commit 23f2746ee611d755e8249b9c9f9a09a52f5d6c4b diff --git a/src/v2/conversions.rs b/src/v2/conversions.rs index c53ad8b5e..9b27ec5a1 100644 --- a/src/v2/conversions.rs +++ b/src/v2/conversions.rs @@ -2458,6 +2458,46 @@ impl TryFrom for super::ChainParametersV2 { } } +impl TryFrom for super::ChainParametersV3 { + type Error = tonic::Status; + + fn try_from(value: ChainParametersV3) -> Result { + let consensus_parameters = value.consensus_parameters.require()?; + + Ok(Self { + timeout_parameters: consensus_parameters + .timeout_parameters + .require()? + .try_into()?, + min_block_time: consensus_parameters.min_block_time.require()?.into(), + block_energy_limit: consensus_parameters.block_energy_limit.require()?.into(), + euro_per_energy: value.euro_per_energy.require()?.try_into()?, + micro_ccd_per_euro: value.micro_ccd_per_euro.require()?.try_into()?, + pool_parameters: value.pool_parameters.require()?.try_into()?, + account_creation_limit: value.account_creation_limit.require()?.try_into()?, + mint_distribution: value.mint_distribution.require()?.try_into()?, + transaction_fee_distribution: value + .transaction_fee_distribution + .require()? + .try_into()?, + gas_rewards: value.gas_rewards.require()?.try_into()?, + foundation_account: value.foundation_account.require()?.try_into()?, + time_parameters: value.time_parameters.require()?.try_into()?, + cooldown_parameters: value.cooldown_parameters.require()?.try_into()?, + finalization_committee_parameters: value + .finalization_committee_parameters + .require()? + .try_into()?, + validator_score_parameters: value.validator_score_parameters.require()?.try_into()?, + keys: UpdateKeysCollectionSkeleton { + root_keys: value.root_keys.require()?.try_into()?, + level_1_keys: value.level1_keys.require()?.try_into()?, + level_2_keys: value.level2_keys.require()?.try_into()?, + }, + }) + } +} + impl TryFrom for super::ChainParameters { type Error = tonic::Status; @@ -2466,6 +2506,7 @@ impl TryFrom for super::ChainParameters { chain_parameters::Parameters::V0(v0) => Ok(Self::V0(v0.try_into()?)), chain_parameters::Parameters::V1(v1) => Ok(Self::V1(v1.try_into()?)), chain_parameters::Parameters::V2(v2) => Ok(Self::V2(v2.try_into()?)), + chain_parameters::Parameters::V3(v3) => Ok(Self::V3(v3.try_into()?)), } } } diff --git a/src/v2/generated/concordium.v2.rs b/src/v2/generated/concordium.v2.rs index 561dbdacf..eb81f6855 100644 --- a/src/v2/generated/concordium.v2.rs +++ b/src/v2/generated/concordium.v2.rs @@ -4819,7 +4819,7 @@ pub struct ChainParametersV3 { #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct ChainParameters { - #[prost(oneof = "chain_parameters::Parameters", tags = "1, 2, 3")] + #[prost(oneof = "chain_parameters::Parameters", tags = "1, 2, 3, 4")] pub parameters: ::core::option::Option, } /// Nested message and enum types in `ChainParameters`. @@ -4835,10 +4835,14 @@ pub mod chain_parameters { /// block. #[prost(message, tag = "2")] V1(super::ChainParametersV1), - /// Chain parameters that apply when the block is a protocol version 6- + /// Chain parameters that apply when the block is a protocol version 6-7 /// block. #[prost(message, tag = "3")] V2(super::ChainParametersV2), + /// Chain parameters that apply when the block is a protocol version 8- + /// block. + #[prost(message, tag = "4")] + V3(super::ChainParametersV3), } } /// Details about a finalizer for the finalization round. diff --git a/src/v2/mod.rs b/src/v2/mod.rs index 567f4a20c..dd5eb3a53 100644 --- a/src/v2/mod.rs +++ b/src/v2/mod.rs @@ -35,7 +35,7 @@ use concordium_base::{ updates::{ AuthorizationsV0, CooldownParameters, FinalizationCommitteeParameters, GASRewards, GASRewardsV1, PoolParameters, TimeParameters, TimeoutParameters, - TransactionFeeDistribution, + TransactionFeeDistribution, ValidatorScoreParameters, }, }; pub use endpoints::{QueryError, QueryResult, RPCError, RPCResult}; @@ -423,7 +423,7 @@ pub struct ChainParametersV1 { #[derive(Debug, Clone)] /// Values of chain parameters that can be updated via chain updates. -/// This applies to protocol version 6 and up. +/// This applies to protocol version 6 and 7. pub struct ChainParametersV2 { /// Consensus protocol version 2 timeout parameters. pub timeout_parameters: TimeoutParameters, @@ -457,6 +457,44 @@ pub struct ChainParametersV2 { pub keys: types::UpdateKeysCollection, } +#[derive(Debug, Clone)] +/// Values of chain parameters that can be updated via chain updates. +/// This applies to protocol version 8 and up. +pub struct ChainParametersV3 { + /// Consensus protocol version 2 timeout parameters. + pub timeout_parameters: TimeoutParameters, + /// Minimum time interval between blocks. + pub min_block_time: Duration, + /// Maximum energy allowed per block. + pub block_energy_limit: Energy, + /// Euro per energy exchange rate. + pub euro_per_energy: ExchangeRate, + /// Micro ccd per euro exchange rate. + pub micro_ccd_per_euro: ExchangeRate, + /// Parameters related to cooldowns when staking. + pub cooldown_parameters: CooldownParameters, + /// Parameters related mint rate and reward period. + pub time_parameters: TimeParameters, + /// The limit for the number of account creations in a block. + pub account_creation_limit: CredentialsPerBlockLimit, + /// Parameters related to the distribution of newly minted CCD. + pub mint_distribution: MintDistributionV1, + /// Parameters related to the distribution of transaction fees. + pub transaction_fee_distribution: TransactionFeeDistribution, + /// Parameters related to the distribution from the GAS account. + pub gas_rewards: GASRewardsV1, + /// Address of the foundation account. + pub foundation_account: AccountAddress, + /// Parameters for baker pools. + pub pool_parameters: PoolParameters, + /// The finalization committee parameters. + pub finalization_committee_parameters: FinalizationCommitteeParameters, + /// Validator score parameters. + pub validator_score_parameters: ValidatorScoreParameters, + /// Keys allowed to do updates. + pub keys: types::UpdateKeysCollection, +} + /// Chain parameters. See [`ChainParametersV0`] and [`ChainParametersV1`] for /// details. `V0` parameters apply to protocol version `1..=3`, and `V1` /// parameters apply to protocol versions `4` and up. @@ -465,6 +503,7 @@ pub enum ChainParameters { V0(ChainParametersV0), V1(ChainParametersV1), V2(ChainParametersV2), + V3(ChainParametersV3), } impl ChainParameters { @@ -474,6 +513,7 @@ impl ChainParameters { Self::V0(data) => &data.keys.level_2_keys, Self::V1(data) => &data.keys.level_2_keys.v0, Self::V2(data) => &data.keys.level_2_keys.v0, + Self::V3(data) => &data.keys.level_2_keys.v0, } } } @@ -506,6 +546,14 @@ impl ChainParameters { u128::from(x.denominator()) * u128::from(y.denominator()), ) } + ChainParameters::V3(v3) => { + let x = v3.micro_ccd_per_euro; + let y = v3.euro_per_energy; + ( + u128::from(x.numerator()) * u128::from(y.numerator()), + u128::from(x.denominator()) * u128::from(y.denominator()), + ) + } }; num::rational::Ratio::new(num, denom) } @@ -533,6 +581,7 @@ impl ChainParameters { ChainParameters::V0(v0) => v0.foundation_account, ChainParameters::V1(v1) => v1.foundation_account, ChainParameters::V2(v2) => v2.foundation_account, + ChainParameters::V3(v3) => v3.foundation_account, } } } diff --git a/src/v2/proto_schema_version.rs b/src/v2/proto_schema_version.rs index 6f774d155..b159a9bed 100644 --- a/src/v2/proto_schema_version.rs +++ b/src/v2/proto_schema_version.rs @@ -1 +1 @@ -pub const PROTO_SCHEMA_VERSION: &str = "156b7ec751391c76847241c2912188bf8d46c3f9"; +pub const PROTO_SCHEMA_VERSION: &str = "044d743617e8128203a329e81c77ba129192fd72"; From f8894dddf779473c7fb3cf569f7604fd88e1c2a0 Mon Sep 17 00:00:00 2001 From: Thomas Dinsdale-Young Date: Fri, 6 Dec 2024 16:16:14 +0100 Subject: [PATCH 6/6] Fix examples --- examples/v2_update_exchange_rate.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/v2_update_exchange_rate.rs b/examples/v2_update_exchange_rate.rs index 960684aa5..872552b9b 100644 --- a/examples/v2_update_exchange_rate.rs +++ b/examples/v2_update_exchange_rate.rs @@ -73,6 +73,7 @@ async fn main() -> anyhow::Result<()> { v2::ChainParameters::V0(v0) => v0.micro_ccd_per_euro, v2::ChainParameters::V1(v1) => v1.micro_ccd_per_euro, v2::ChainParameters::V2(v2) => v2.micro_ccd_per_euro, + v2::ChainParameters::V3(v3) => v3.micro_ccd_per_euro, }; let effective_time = 0.into(); // immediate effect