From e8c7ec7ca4de8bc73eb46996bec0d3fd47935afa Mon Sep 17 00:00:00 2001 From: Lucas Meier Date: Thu, 25 Jul 2024 11:53:32 -0700 Subject: [PATCH 1/3] Add a ProposalKind enum to protobuf This introduces a canonical way to serialize this enum, which is useful for storing it in a database. Co-authored-by: plaidfinch --- .../core/component/governance/src/proposal.rs | 28 ++++++ .../penumbra.core.component.governance.v1.rs | 42 +++++++++ ...mbra.core.component.governance.v1.serde.rs | 86 ++++++++++++++++++ .../proto/src/gen/proto_descriptor.bin.no_lfs | Bin 548215 -> 548850 bytes .../component/governance/v1/governance.proto | 11 +++ 5 files changed, 167 insertions(+) diff --git a/crates/core/component/governance/src/proposal.rs b/crates/core/component/governance/src/proposal.rs index 1f7b3bb2bb..9f02556c8e 100644 --- a/crates/core/component/governance/src/proposal.rs +++ b/crates/core/component/governance/src/proposal.rs @@ -257,6 +257,34 @@ impl Proposal { } } +impl From for pb::ProposalKind { + fn from(kind: ProposalKind) -> pb::ProposalKind { + match kind { + ProposalKind::Signaling => pb::ProposalKind::Signaling, + ProposalKind::Emergency => pb::ProposalKind::Emergency, + ProposalKind::ParameterChange => pb::ProposalKind::ParameterChange, + ProposalKind::CommunityPoolSpend => pb::ProposalKind::CommunityPoolSpend, + ProposalKind::UpgradePlan => pb::ProposalKind::UpgradePlan, + ProposalKind::FreezeIbcClient => pb::ProposalKind::FreezeIbcClient, + ProposalKind::UnfreezeIbcClient => pb::ProposalKind::UnfreezeIbcClient, + } + } +} + +impl From for ProposalKind { + fn from(kind: pb::ProposalKind) -> ProposalKind { + match kind { + pb::ProposalKind::Signaling => ProposalKind::Signaling, + pb::ProposalKind::Emergency => ProposalKind::Emergency, + pb::ProposalKind::ParameterChange => ProposalKind::ParameterChange, + pb::ProposalKind::CommunityPoolSpend => ProposalKind::CommunityPoolSpend, + pb::ProposalKind::UpgradePlan => ProposalKind::UpgradePlan, + pb::ProposalKind::FreezeIbcClient => ProposalKind::FreezeIbcClient, + pb::ProposalKind::UnfreezeIbcClient => ProposalKind::UnfreezeIbcClient, + } + } +} + /// The machine-interpretable body of a proposal. #[derive(Debug, Clone, Eq, PartialEq)] pub enum ProposalPayload { diff --git a/crates/proto/src/gen/penumbra.core.component.governance.v1.rs b/crates/proto/src/gen/penumbra.core.component.governance.v1.rs index 6da0dcebf1..d5a7a071db 100644 --- a/crates/proto/src/gen/penumbra.core.component.governance.v1.rs +++ b/crates/proto/src/gen/penumbra.core.component.governance.v1.rs @@ -1330,6 +1330,48 @@ impl ::prost::Name for EventProposalSlashed { ::prost::alloc::format!("penumbra.core.component.governance.v1.{}", Self::NAME) } } +/// All the different kinds of proposals. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum ProposalKind { + Signaling = 0, + Emergency = 1, + ParameterChange = 2, + CommunityPoolSpend = 3, + UpgradePlan = 4, + FreezeIbcClient = 5, + UnfreezeIbcClient = 6, +} +impl ProposalKind { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + ProposalKind::Signaling => "PROPOSAL_KIND_SIGNALING", + ProposalKind::Emergency => "PROPOSAL_KIND_EMERGENCY", + ProposalKind::ParameterChange => "PROPOSAL_KIND_PARAMETER_CHANGE", + ProposalKind::CommunityPoolSpend => "PROPOSAL_KIND_COMMUNITY_POOL_SPEND", + ProposalKind::UpgradePlan => "PROPOSAL_KIND_UPGRADE_PLAN", + ProposalKind::FreezeIbcClient => "PROPOSAL_KIND_FREEZE_IBC_CLIENT", + ProposalKind::UnfreezeIbcClient => "PROPOSAL_KIND_UNFREEZE_IBC_CLIENT", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "PROPOSAL_KIND_SIGNALING" => Some(Self::Signaling), + "PROPOSAL_KIND_EMERGENCY" => Some(Self::Emergency), + "PROPOSAL_KIND_PARAMETER_CHANGE" => Some(Self::ParameterChange), + "PROPOSAL_KIND_COMMUNITY_POOL_SPEND" => Some(Self::CommunityPoolSpend), + "PROPOSAL_KIND_UPGRADE_PLAN" => Some(Self::UpgradePlan), + "PROPOSAL_KIND_FREEZE_IBC_CLIENT" => Some(Self::FreezeIbcClient), + "PROPOSAL_KIND_UNFREEZE_IBC_CLIENT" => Some(Self::UnfreezeIbcClient), + _ => None, + } + } +} /// Generated client implementations. #[cfg(feature = "rpc")] pub mod query_service_client { diff --git a/crates/proto/src/gen/penumbra.core.component.governance.v1.serde.rs b/crates/proto/src/gen/penumbra.core.component.governance.v1.serde.rs index 14e37c1c1c..d32300debb 100644 --- a/crates/proto/src/gen/penumbra.core.component.governance.v1.serde.rs +++ b/crates/proto/src/gen/penumbra.core.component.governance.v1.serde.rs @@ -4746,6 +4746,92 @@ impl<'de> serde::Deserialize<'de> for ProposalInfoResponse { deserializer.deserialize_struct("penumbra.core.component.governance.v1.ProposalInfoResponse", FIELDS, GeneratedVisitor) } } +impl serde::Serialize for ProposalKind { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + let variant = match self { + Self::Signaling => "PROPOSAL_KIND_SIGNALING", + Self::Emergency => "PROPOSAL_KIND_EMERGENCY", + Self::ParameterChange => "PROPOSAL_KIND_PARAMETER_CHANGE", + Self::CommunityPoolSpend => "PROPOSAL_KIND_COMMUNITY_POOL_SPEND", + Self::UpgradePlan => "PROPOSAL_KIND_UPGRADE_PLAN", + Self::FreezeIbcClient => "PROPOSAL_KIND_FREEZE_IBC_CLIENT", + Self::UnfreezeIbcClient => "PROPOSAL_KIND_UNFREEZE_IBC_CLIENT", + }; + serializer.serialize_str(variant) + } +} +impl<'de> serde::Deserialize<'de> for ProposalKind { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "PROPOSAL_KIND_SIGNALING", + "PROPOSAL_KIND_EMERGENCY", + "PROPOSAL_KIND_PARAMETER_CHANGE", + "PROPOSAL_KIND_COMMUNITY_POOL_SPEND", + "PROPOSAL_KIND_UPGRADE_PLAN", + "PROPOSAL_KIND_FREEZE_IBC_CLIENT", + "PROPOSAL_KIND_UNFREEZE_IBC_CLIENT", + ]; + + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = ProposalKind; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + fn visit_i64(self, v: i64) -> std::result::Result + where + E: serde::de::Error, + { + i32::try_from(v) + .ok() + .and_then(|x| x.try_into().ok()) + .ok_or_else(|| { + serde::de::Error::invalid_value(serde::de::Unexpected::Signed(v), &self) + }) + } + + fn visit_u64(self, v: u64) -> std::result::Result + where + E: serde::de::Error, + { + i32::try_from(v) + .ok() + .and_then(|x| x.try_into().ok()) + .ok_or_else(|| { + serde::de::Error::invalid_value(serde::de::Unexpected::Unsigned(v), &self) + }) + } + + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "PROPOSAL_KIND_SIGNALING" => Ok(ProposalKind::Signaling), + "PROPOSAL_KIND_EMERGENCY" => Ok(ProposalKind::Emergency), + "PROPOSAL_KIND_PARAMETER_CHANGE" => Ok(ProposalKind::ParameterChange), + "PROPOSAL_KIND_COMMUNITY_POOL_SPEND" => Ok(ProposalKind::CommunityPoolSpend), + "PROPOSAL_KIND_UPGRADE_PLAN" => Ok(ProposalKind::UpgradePlan), + "PROPOSAL_KIND_FREEZE_IBC_CLIENT" => Ok(ProposalKind::FreezeIbcClient), + "PROPOSAL_KIND_UNFREEZE_IBC_CLIENT" => Ok(ProposalKind::UnfreezeIbcClient), + _ => Err(serde::de::Error::unknown_variant(value, FIELDS)), + } + } + } + deserializer.deserialize_any(GeneratedVisitor) + } +} impl serde::Serialize for ProposalListRequest { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result diff --git a/crates/proto/src/gen/proto_descriptor.bin.no_lfs b/crates/proto/src/gen/proto_descriptor.bin.no_lfs index 9184afa862c827ad52ab92fcd5406a45097a1c88..77a9851c1ccbab5269b11ed459bec72cf5b6fc66 100644 GIT binary patch delta 5397 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 Ra`4Z^zubK@TB3jM`Y!{+hVB3W diff --git a/proto/penumbra/penumbra/core/component/governance/v1/governance.proto b/proto/penumbra/penumbra/core/component/governance/v1/governance.proto index 7f015c6668..b4a1a3712e 100644 --- a/proto/penumbra/penumbra/core/component/governance/v1/governance.proto +++ b/proto/penumbra/penumbra/core/component/governance/v1/governance.proto @@ -323,6 +323,17 @@ message Proposal { } } +// All the different kinds of proposals. +enum ProposalKind { + PROPOSAL_KIND_SIGNALING = 0; + PROPOSAL_KIND_EMERGENCY = 1; + PROPOSAL_KIND_PARAMETER_CHANGE = 2; + PROPOSAL_KIND_COMMUNITY_POOL_SPEND = 3; + PROPOSAL_KIND_UPGRADE_PLAN = 4; + PROPOSAL_KIND_FREEZE_IBC_CLIENT = 5; + PROPOSAL_KIND_UNFREEZE_IBC_CLIENT = 6; +} + // Query operations for the governance component. service QueryService { rpc ProposalInfo(ProposalInfoRequest) returns (ProposalInfoResponse); From bcf51c4dc412fc1335abcb0d599b1f8c4b2fb21c Mon Sep 17 00:00:00 2001 From: Lucas Meier Date: Thu, 25 Jul 2024 12:30:44 -0700 Subject: [PATCH 2/3] Implement missing governance events This implements a few different additions to events to make governance-related indexing easier: - add the validator identity key to delegator vote events - add the voting power to validator votes - add the start and end height to proposal submissions This also renames the EventEnactProposal to EventProposalPassed, which hypothetically breaks existing consumers of that event, of which we know of none. Co-authored-by: plaidfinch --- .../app/src/action_handler/actions/submit.rs | 2 +- .../src/action_handler/delegator_vote.rs | 2 +- .../src/action_handler/validator_vote.rs | 5 +- .../component/governance/src/component.rs | 2 +- .../governance/src/component/view.rs | 14 ++ crates/core/component/governance/src/event.rs | 22 ++- .../core/component/governance/src/proposal.rs | 59 +++--- .../penumbra.core.component.governance.v1.rs | 22 ++- ...mbra.core.component.governance.v1.serde.rs | 179 +++++++++++++----- .../proto/src/gen/proto_descriptor.bin.no_lfs | Bin 548850 -> 549470 bytes .../component/governance/v1/governance.proto | 12 +- 11 files changed, 226 insertions(+), 93 deletions(-) diff --git a/crates/core/app/src/action_handler/actions/submit.rs b/crates/core/app/src/action_handler/actions/submit.rs index 8776798166..3d39681999 100644 --- a/crates/core/app/src/action_handler/actions/submit.rs +++ b/crates/core/app/src/action_handler/actions/submit.rs @@ -296,7 +296,7 @@ impl AppActionHandler for ProposalSubmit { // state needed to vote as delegators state.mark_proposal_started(); - state.record_proto(event::proposal_submit(self)); + state.record_proto(event::proposal_submit(self, current_block, voting_end)); tracing::debug!(proposal = %proposal_id, "created proposal"); diff --git a/crates/core/component/governance/src/action_handler/delegator_vote.rs b/crates/core/component/governance/src/action_handler/delegator_vote.rs index 8f284153ba..00194240aa 100644 --- a/crates/core/component/governance/src/action_handler/delegator_vote.rs +++ b/crates/core/component/governance/src/action_handler/delegator_vote.rs @@ -91,7 +91,7 @@ impl ActionHandler for DelegatorVote { .cast_delegator_vote(*proposal, identity_key, *vote, nullifier, *unbonded_amount) .await?; - state.record_proto(event::delegator_vote(self)); + state.record_proto(event::delegator_vote(self, &identity_key)); Ok(()) } diff --git a/crates/core/component/governance/src/action_handler/validator_vote.rs b/crates/core/component/governance/src/action_handler/validator_vote.rs index 33a0dccd24..caed7b3547 100644 --- a/crates/core/component/governance/src/action_handler/validator_vote.rs +++ b/crates/core/component/governance/src/action_handler/validator_vote.rs @@ -114,7 +114,10 @@ impl ActionHandler for ValidatorVote { } } - state.record_proto(event::validator_vote(self)); + let voting_power = state + .specific_validator_voting_power_at_proposal_start(*proposal, *identity_key) + .await?; + state.record_proto(event::validator_vote(self, voting_power)); Ok(()) } diff --git a/crates/core/component/governance/src/component.rs b/crates/core/component/governance/src/component.rs index 8b7b368362..4581dc0d81 100644 --- a/crates/core/component/governance/src/component.rs +++ b/crates/core/component/governance/src/component.rs @@ -144,7 +144,7 @@ pub async fn enact_all_passed_proposals(mut state: S) -> Result<( .ok_or_else(|| { anyhow::anyhow!("proposal {} does not exist", proposal_id) })?; - state.record_proto(event::enact_proposal(&proposal)); + state.record_proto(event::proposal_passed(&proposal)); } tally::Outcome::Fail => { tracing::info!(proposal = %proposal_id, "proposal failed"); diff --git a/crates/core/component/governance/src/component/view.rs b/crates/core/component/governance/src/component/view.rs index d76d9df811..d05a8b5911 100644 --- a/crates/core/component/governance/src/component/view.rs +++ b/crates/core/component/governance/src/component/view.rs @@ -422,6 +422,20 @@ pub trait StateReadExt: StateRead + penumbra_stake::StateReadExt { Ok(()) } + /// Get a specific validator's voting power for a proposal. + async fn specific_validator_voting_power_at_proposal_start( + &self, + proposal_id: u64, + identity_key: IdentityKey, + ) -> Result { + self.get_proto(&state_key::voting_power_at_proposal_start( + proposal_id, + identity_key, + )) + .await + .map(Option::unwrap_or_default) + } + /// Get all the active validator voting power for the proposal. async fn validator_voting_power_at_proposal_start( &self, diff --git a/crates/core/component/governance/src/event.rs b/crates/core/component/governance/src/event.rs index 5737ae405b..699f2bd2b4 100644 --- a/crates/core/component/governance/src/event.rs +++ b/crates/core/component/governance/src/event.rs @@ -1,12 +1,17 @@ use penumbra_proto::penumbra::core::component::governance::v1 as pb; +use penumbra_stake::IdentityKey; use crate::{ DelegatorVote, Proposal, ProposalDepositClaim, ProposalSubmit, ProposalWithdraw, ValidatorVote, }; -pub fn delegator_vote(delegator_vote: &DelegatorVote) -> pb::EventDelegatorVote { +pub fn delegator_vote( + delegator_vote: &DelegatorVote, + validator_identity_key: &IdentityKey, +) -> pb::EventDelegatorVote { pb::EventDelegatorVote { vote: Some(pb::DelegatorVote::from(*delegator_vote)), + validator_identity_key: Some(validator_identity_key.clone().into()), } } @@ -18,9 +23,10 @@ pub fn proposal_deposit_claim( } } -pub fn validator_vote(validator_vote: &ValidatorVote) -> pb::EventValidatorVote { +pub fn validator_vote(validator_vote: &ValidatorVote, voting_power: u64) -> pb::EventValidatorVote { pb::EventValidatorVote { vote: Some(pb::ValidatorVote::from(validator_vote.clone())), + voting_power, } } @@ -30,14 +36,20 @@ pub fn proposal_withdraw(withdraw: &ProposalWithdraw) -> pb::EventProposalWithdr } } -pub fn proposal_submit(submit: &ProposalSubmit) -> pb::EventProposalSubmit { +pub fn proposal_submit( + submit: &ProposalSubmit, + start_height: u64, + end_height: u64, +) -> pb::EventProposalSubmit { pb::EventProposalSubmit { submit: Some(pb::ProposalSubmit::from(submit.clone())), + start_height, + end_height, } } -pub fn enact_proposal(proposal: &Proposal) -> pb::EventEnactProposal { - pb::EventEnactProposal { +pub fn proposal_passed(proposal: &Proposal) -> pb::EventProposalPassed { + pb::EventProposalPassed { proposal: Some(pb::Proposal::from(proposal.clone())), } } diff --git a/crates/core/component/governance/src/proposal.rs b/crates/core/component/governance/src/proposal.rs index 9f02556c8e..f89268158f 100644 --- a/crates/core/component/governance/src/proposal.rs +++ b/crates/core/component/governance/src/proposal.rs @@ -201,8 +201,9 @@ impl TryFrom for Proposal { } /// The specific kind of a proposal. -#[derive(Debug, Clone, Eq, PartialEq)] +#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)] #[cfg_attr(feature = "clap", derive(clap::Subcommand))] +#[serde(try_from = "pb::ProposalKind", into = "pb::ProposalKind")] pub enum ProposalKind { /// A signaling proposal. #[cfg_attr(feature = "clap", clap(display_order = 100))] @@ -227,6 +228,34 @@ pub enum ProposalKind { UnfreezeIbcClient, } +impl From for pb::ProposalKind { + fn from(kind: ProposalKind) -> pb::ProposalKind { + match kind { + ProposalKind::Signaling => pb::ProposalKind::Signaling, + ProposalKind::Emergency => pb::ProposalKind::Emergency, + ProposalKind::ParameterChange => pb::ProposalKind::ParameterChange, + ProposalKind::CommunityPoolSpend => pb::ProposalKind::CommunityPoolSpend, + ProposalKind::UpgradePlan => pb::ProposalKind::UpgradePlan, + ProposalKind::FreezeIbcClient => pb::ProposalKind::FreezeIbcClient, + ProposalKind::UnfreezeIbcClient => pb::ProposalKind::UnfreezeIbcClient, + } + } +} + +impl From for ProposalKind { + fn from(kind: pb::ProposalKind) -> ProposalKind { + match kind { + pb::ProposalKind::Signaling => ProposalKind::Signaling, + pb::ProposalKind::Emergency => ProposalKind::Emergency, + pb::ProposalKind::ParameterChange => ProposalKind::ParameterChange, + pb::ProposalKind::CommunityPoolSpend => ProposalKind::CommunityPoolSpend, + pb::ProposalKind::UpgradePlan => ProposalKind::UpgradePlan, + pb::ProposalKind::FreezeIbcClient => ProposalKind::FreezeIbcClient, + pb::ProposalKind::UnfreezeIbcClient => ProposalKind::UnfreezeIbcClient, + } + } +} + impl FromStr for ProposalKind { type Err = anyhow::Error; @@ -257,34 +286,6 @@ impl Proposal { } } -impl From for pb::ProposalKind { - fn from(kind: ProposalKind) -> pb::ProposalKind { - match kind { - ProposalKind::Signaling => pb::ProposalKind::Signaling, - ProposalKind::Emergency => pb::ProposalKind::Emergency, - ProposalKind::ParameterChange => pb::ProposalKind::ParameterChange, - ProposalKind::CommunityPoolSpend => pb::ProposalKind::CommunityPoolSpend, - ProposalKind::UpgradePlan => pb::ProposalKind::UpgradePlan, - ProposalKind::FreezeIbcClient => pb::ProposalKind::FreezeIbcClient, - ProposalKind::UnfreezeIbcClient => pb::ProposalKind::UnfreezeIbcClient, - } - } -} - -impl From for ProposalKind { - fn from(kind: pb::ProposalKind) -> ProposalKind { - match kind { - pb::ProposalKind::Signaling => ProposalKind::Signaling, - pb::ProposalKind::Emergency => ProposalKind::Emergency, - pb::ProposalKind::ParameterChange => ProposalKind::ParameterChange, - pb::ProposalKind::CommunityPoolSpend => ProposalKind::CommunityPoolSpend, - pb::ProposalKind::UpgradePlan => ProposalKind::UpgradePlan, - pb::ProposalKind::FreezeIbcClient => ProposalKind::FreezeIbcClient, - pb::ProposalKind::UnfreezeIbcClient => ProposalKind::UnfreezeIbcClient, - } - } -} - /// The machine-interpretable body of a proposal. #[derive(Debug, Clone, Eq, PartialEq)] pub enum ProposalPayload { diff --git a/crates/proto/src/gen/penumbra.core.component.governance.v1.rs b/crates/proto/src/gen/penumbra.core.component.governance.v1.rs index d5a7a071db..792c16b681 100644 --- a/crates/proto/src/gen/penumbra.core.component.governance.v1.rs +++ b/crates/proto/src/gen/penumbra.core.component.governance.v1.rs @@ -1224,6 +1224,11 @@ pub struct EventDelegatorVote { /// The delegator vote. #[prost(message, optional, tag = "1")] pub vote: ::core::option::Option, + /// The corresponding validator's identity key. + #[prost(message, optional, tag = "2")] + pub validator_identity_key: ::core::option::Option< + super::super::super::keys::v1::IdentityKey, + >, } impl ::prost::Name for EventDelegatorVote { const NAME: &'static str = "EventDelegatorVote"; @@ -1252,6 +1257,9 @@ pub struct EventValidatorVote { /// The validator vote. #[prost(message, optional, tag = "1")] pub vote: ::core::option::Option, + /// The validator's voting power at the time of the proposal's start. + #[prost(uint64, tag = "2")] + pub voting_power: u64, } impl ::prost::Name for EventValidatorVote { const NAME: &'static str = "EventValidatorVote"; @@ -1280,6 +1288,12 @@ pub struct EventProposalSubmit { /// Details on the submitted proposal. #[prost(message, optional, tag = "1")] pub submit: ::core::option::Option, + /// The start height for the proposal. + #[prost(uint64, tag = "2")] + pub start_height: u64, + /// The end height for the proposal. + #[prost(uint64, tag = "3")] + pub end_height: u64, } impl ::prost::Name for EventProposalSubmit { const NAME: &'static str = "EventProposalSubmit"; @@ -1290,13 +1304,13 @@ impl ::prost::Name for EventProposalSubmit { } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] -pub struct EventEnactProposal { - /// The enacted proposal. +pub struct EventProposalPassed { + /// The passed proposal. #[prost(message, optional, tag = "1")] pub proposal: ::core::option::Option, } -impl ::prost::Name for EventEnactProposal { - const NAME: &'static str = "EventEnactProposal"; +impl ::prost::Name for EventProposalPassed { + const NAME: &'static str = "EventProposalPassed"; const PACKAGE: &'static str = "penumbra.core.component.governance.v1"; fn full_name() -> ::prost::alloc::string::String { ::prost::alloc::format!("penumbra.core.component.governance.v1.{}", Self::NAME) diff --git a/crates/proto/src/gen/penumbra.core.component.governance.v1.serde.rs b/crates/proto/src/gen/penumbra.core.component.governance.v1.serde.rs index d32300debb..dfb5534442 100644 --- a/crates/proto/src/gen/penumbra.core.component.governance.v1.serde.rs +++ b/crates/proto/src/gen/penumbra.core.component.governance.v1.serde.rs @@ -1952,10 +1952,16 @@ impl serde::Serialize for EventDelegatorVote { if self.vote.is_some() { len += 1; } + if self.validator_identity_key.is_some() { + len += 1; + } let mut struct_ser = serializer.serialize_struct("penumbra.core.component.governance.v1.EventDelegatorVote", len)?; if let Some(v) = self.vote.as_ref() { struct_ser.serialize_field("vote", v)?; } + if let Some(v) = self.validator_identity_key.as_ref() { + struct_ser.serialize_field("validatorIdentityKey", v)?; + } struct_ser.end() } } @@ -1967,11 +1973,14 @@ impl<'de> serde::Deserialize<'de> for EventDelegatorVote { { const FIELDS: &[&str] = &[ "vote", + "validator_identity_key", + "validatorIdentityKey", ]; #[allow(clippy::enum_variant_names)] enum GeneratedField { Vote, + ValidatorIdentityKey, __SkipField__, } impl<'de> serde::Deserialize<'de> for GeneratedField { @@ -1995,6 +2004,7 @@ impl<'de> serde::Deserialize<'de> for EventDelegatorVote { { match value { "vote" => Ok(GeneratedField::Vote), + "validatorIdentityKey" | "validator_identity_key" => Ok(GeneratedField::ValidatorIdentityKey), _ => Ok(GeneratedField::__SkipField__), } } @@ -2015,6 +2025,7 @@ impl<'de> serde::Deserialize<'de> for EventDelegatorVote { V: serde::de::MapAccess<'de>, { let mut vote__ = None; + let mut validator_identity_key__ = None; while let Some(k) = map_.next_key()? { match k { GeneratedField::Vote => { @@ -2023,6 +2034,12 @@ impl<'de> serde::Deserialize<'de> for EventDelegatorVote { } vote__ = map_.next_value()?; } + GeneratedField::ValidatorIdentityKey => { + if validator_identity_key__.is_some() { + return Err(serde::de::Error::duplicate_field("validatorIdentityKey")); + } + validator_identity_key__ = map_.next_value()?; + } GeneratedField::__SkipField__ => { let _ = map_.next_value::()?; } @@ -2030,13 +2047,14 @@ impl<'de> serde::Deserialize<'de> for EventDelegatorVote { } Ok(EventDelegatorVote { vote: vote__, + validator_identity_key: validator_identity_key__, }) } } deserializer.deserialize_struct("penumbra.core.component.governance.v1.EventDelegatorVote", FIELDS, GeneratedVisitor) } } -impl serde::Serialize for EventEnactProposal { +impl serde::Serialize for EventProposalDepositClaim { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result where @@ -2044,29 +2062,30 @@ impl serde::Serialize for EventEnactProposal { { use serde::ser::SerializeStruct; let mut len = 0; - if self.proposal.is_some() { + if self.deposit_claim.is_some() { len += 1; } - let mut struct_ser = serializer.serialize_struct("penumbra.core.component.governance.v1.EventEnactProposal", len)?; - if let Some(v) = self.proposal.as_ref() { - struct_ser.serialize_field("proposal", v)?; + let mut struct_ser = serializer.serialize_struct("penumbra.core.component.governance.v1.EventProposalDepositClaim", len)?; + if let Some(v) = self.deposit_claim.as_ref() { + struct_ser.serialize_field("depositClaim", v)?; } struct_ser.end() } } -impl<'de> serde::Deserialize<'de> for EventEnactProposal { +impl<'de> serde::Deserialize<'de> for EventProposalDepositClaim { #[allow(deprecated)] fn deserialize(deserializer: D) -> std::result::Result where D: serde::Deserializer<'de>, { const FIELDS: &[&str] = &[ - "proposal", + "deposit_claim", + "depositClaim", ]; #[allow(clippy::enum_variant_names)] enum GeneratedField { - Proposal, + DepositClaim, __SkipField__, } impl<'de> serde::Deserialize<'de> for GeneratedField { @@ -2089,7 +2108,7 @@ impl<'de> serde::Deserialize<'de> for EventEnactProposal { E: serde::de::Error, { match value { - "proposal" => Ok(GeneratedField::Proposal), + "depositClaim" | "deposit_claim" => Ok(GeneratedField::DepositClaim), _ => Ok(GeneratedField::__SkipField__), } } @@ -2099,39 +2118,39 @@ impl<'de> serde::Deserialize<'de> for EventEnactProposal { } struct GeneratedVisitor; impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = EventEnactProposal; + type Value = EventProposalDepositClaim; fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct penumbra.core.component.governance.v1.EventEnactProposal") + formatter.write_str("struct penumbra.core.component.governance.v1.EventProposalDepositClaim") } - fn visit_map(self, mut map_: V) -> std::result::Result + fn visit_map(self, mut map_: V) -> std::result::Result where V: serde::de::MapAccess<'de>, { - let mut proposal__ = None; + let mut deposit_claim__ = None; while let Some(k) = map_.next_key()? { match k { - GeneratedField::Proposal => { - if proposal__.is_some() { - return Err(serde::de::Error::duplicate_field("proposal")); + GeneratedField::DepositClaim => { + if deposit_claim__.is_some() { + return Err(serde::de::Error::duplicate_field("depositClaim")); } - proposal__ = map_.next_value()?; + deposit_claim__ = map_.next_value()?; } GeneratedField::__SkipField__ => { let _ = map_.next_value::()?; } } } - Ok(EventEnactProposal { - proposal: proposal__, + Ok(EventProposalDepositClaim { + deposit_claim: deposit_claim__, }) } } - deserializer.deserialize_struct("penumbra.core.component.governance.v1.EventEnactProposal", FIELDS, GeneratedVisitor) + deserializer.deserialize_struct("penumbra.core.component.governance.v1.EventProposalDepositClaim", FIELDS, GeneratedVisitor) } } -impl serde::Serialize for EventProposalDepositClaim { +impl serde::Serialize for EventProposalFailed { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result where @@ -2139,30 +2158,29 @@ impl serde::Serialize for EventProposalDepositClaim { { use serde::ser::SerializeStruct; let mut len = 0; - if self.deposit_claim.is_some() { + if self.proposal.is_some() { len += 1; } - let mut struct_ser = serializer.serialize_struct("penumbra.core.component.governance.v1.EventProposalDepositClaim", len)?; - if let Some(v) = self.deposit_claim.as_ref() { - struct_ser.serialize_field("depositClaim", v)?; + let mut struct_ser = serializer.serialize_struct("penumbra.core.component.governance.v1.EventProposalFailed", len)?; + if let Some(v) = self.proposal.as_ref() { + struct_ser.serialize_field("proposal", v)?; } struct_ser.end() } } -impl<'de> serde::Deserialize<'de> for EventProposalDepositClaim { +impl<'de> serde::Deserialize<'de> for EventProposalFailed { #[allow(deprecated)] fn deserialize(deserializer: D) -> std::result::Result where D: serde::Deserializer<'de>, { const FIELDS: &[&str] = &[ - "deposit_claim", - "depositClaim", + "proposal", ]; #[allow(clippy::enum_variant_names)] enum GeneratedField { - DepositClaim, + Proposal, __SkipField__, } impl<'de> serde::Deserialize<'de> for GeneratedField { @@ -2185,7 +2203,7 @@ impl<'de> serde::Deserialize<'de> for EventProposalDepositClaim { E: serde::de::Error, { match value { - "depositClaim" | "deposit_claim" => Ok(GeneratedField::DepositClaim), + "proposal" => Ok(GeneratedField::Proposal), _ => Ok(GeneratedField::__SkipField__), } } @@ -2195,39 +2213,39 @@ impl<'de> serde::Deserialize<'de> for EventProposalDepositClaim { } struct GeneratedVisitor; impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = EventProposalDepositClaim; + type Value = EventProposalFailed; fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct penumbra.core.component.governance.v1.EventProposalDepositClaim") + formatter.write_str("struct penumbra.core.component.governance.v1.EventProposalFailed") } - fn visit_map(self, mut map_: V) -> std::result::Result + fn visit_map(self, mut map_: V) -> std::result::Result where V: serde::de::MapAccess<'de>, { - let mut deposit_claim__ = None; + let mut proposal__ = None; while let Some(k) = map_.next_key()? { match k { - GeneratedField::DepositClaim => { - if deposit_claim__.is_some() { - return Err(serde::de::Error::duplicate_field("depositClaim")); + GeneratedField::Proposal => { + if proposal__.is_some() { + return Err(serde::de::Error::duplicate_field("proposal")); } - deposit_claim__ = map_.next_value()?; + proposal__ = map_.next_value()?; } GeneratedField::__SkipField__ => { let _ = map_.next_value::()?; } } } - Ok(EventProposalDepositClaim { - deposit_claim: deposit_claim__, + Ok(EventProposalFailed { + proposal: proposal__, }) } } - deserializer.deserialize_struct("penumbra.core.component.governance.v1.EventProposalDepositClaim", FIELDS, GeneratedVisitor) + deserializer.deserialize_struct("penumbra.core.component.governance.v1.EventProposalFailed", FIELDS, GeneratedVisitor) } } -impl serde::Serialize for EventProposalFailed { +impl serde::Serialize for EventProposalPassed { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result where @@ -2238,14 +2256,14 @@ impl serde::Serialize for EventProposalFailed { if self.proposal.is_some() { len += 1; } - let mut struct_ser = serializer.serialize_struct("penumbra.core.component.governance.v1.EventProposalFailed", len)?; + let mut struct_ser = serializer.serialize_struct("penumbra.core.component.governance.v1.EventProposalPassed", len)?; if let Some(v) = self.proposal.as_ref() { struct_ser.serialize_field("proposal", v)?; } struct_ser.end() } } -impl<'de> serde::Deserialize<'de> for EventProposalFailed { +impl<'de> serde::Deserialize<'de> for EventProposalPassed { #[allow(deprecated)] fn deserialize(deserializer: D) -> std::result::Result where @@ -2290,13 +2308,13 @@ impl<'de> serde::Deserialize<'de> for EventProposalFailed { } struct GeneratedVisitor; impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = EventProposalFailed; + type Value = EventProposalPassed; fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct penumbra.core.component.governance.v1.EventProposalFailed") + formatter.write_str("struct penumbra.core.component.governance.v1.EventProposalPassed") } - fn visit_map(self, mut map_: V) -> std::result::Result + fn visit_map(self, mut map_: V) -> std::result::Result where V: serde::de::MapAccess<'de>, { @@ -2314,12 +2332,12 @@ impl<'de> serde::Deserialize<'de> for EventProposalFailed { } } } - Ok(EventProposalFailed { + Ok(EventProposalPassed { proposal: proposal__, }) } } - deserializer.deserialize_struct("penumbra.core.component.governance.v1.EventProposalFailed", FIELDS, GeneratedVisitor) + deserializer.deserialize_struct("penumbra.core.component.governance.v1.EventProposalPassed", FIELDS, GeneratedVisitor) } } impl serde::Serialize for EventProposalSlashed { @@ -2428,10 +2446,24 @@ impl serde::Serialize for EventProposalSubmit { if self.submit.is_some() { len += 1; } + if self.start_height != 0 { + len += 1; + } + if self.end_height != 0 { + len += 1; + } let mut struct_ser = serializer.serialize_struct("penumbra.core.component.governance.v1.EventProposalSubmit", len)?; if let Some(v) = self.submit.as_ref() { struct_ser.serialize_field("submit", v)?; } + if self.start_height != 0 { + #[allow(clippy::needless_borrow)] + struct_ser.serialize_field("startHeight", ToString::to_string(&self.start_height).as_str())?; + } + if self.end_height != 0 { + #[allow(clippy::needless_borrow)] + struct_ser.serialize_field("endHeight", ToString::to_string(&self.end_height).as_str())?; + } struct_ser.end() } } @@ -2443,11 +2475,17 @@ impl<'de> serde::Deserialize<'de> for EventProposalSubmit { { const FIELDS: &[&str] = &[ "submit", + "start_height", + "startHeight", + "end_height", + "endHeight", ]; #[allow(clippy::enum_variant_names)] enum GeneratedField { Submit, + StartHeight, + EndHeight, __SkipField__, } impl<'de> serde::Deserialize<'de> for GeneratedField { @@ -2471,6 +2509,8 @@ impl<'de> serde::Deserialize<'de> for EventProposalSubmit { { match value { "submit" => Ok(GeneratedField::Submit), + "startHeight" | "start_height" => Ok(GeneratedField::StartHeight), + "endHeight" | "end_height" => Ok(GeneratedField::EndHeight), _ => Ok(GeneratedField::__SkipField__), } } @@ -2491,6 +2531,8 @@ impl<'de> serde::Deserialize<'de> for EventProposalSubmit { V: serde::de::MapAccess<'de>, { let mut submit__ = None; + let mut start_height__ = None; + let mut end_height__ = None; while let Some(k) = map_.next_key()? { match k { GeneratedField::Submit => { @@ -2499,6 +2541,22 @@ impl<'de> serde::Deserialize<'de> for EventProposalSubmit { } submit__ = map_.next_value()?; } + GeneratedField::StartHeight => { + if start_height__.is_some() { + return Err(serde::de::Error::duplicate_field("startHeight")); + } + start_height__ = + Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) + ; + } + GeneratedField::EndHeight => { + if end_height__.is_some() { + return Err(serde::de::Error::duplicate_field("endHeight")); + } + end_height__ = + Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) + ; + } GeneratedField::__SkipField__ => { let _ = map_.next_value::()?; } @@ -2506,6 +2564,8 @@ impl<'de> serde::Deserialize<'de> for EventProposalSubmit { } Ok(EventProposalSubmit { submit: submit__, + start_height: start_height__.unwrap_or_default(), + end_height: end_height__.unwrap_or_default(), }) } } @@ -2618,10 +2678,17 @@ impl serde::Serialize for EventValidatorVote { if self.vote.is_some() { len += 1; } + if self.voting_power != 0 { + len += 1; + } let mut struct_ser = serializer.serialize_struct("penumbra.core.component.governance.v1.EventValidatorVote", len)?; if let Some(v) = self.vote.as_ref() { struct_ser.serialize_field("vote", v)?; } + if self.voting_power != 0 { + #[allow(clippy::needless_borrow)] + struct_ser.serialize_field("votingPower", ToString::to_string(&self.voting_power).as_str())?; + } struct_ser.end() } } @@ -2633,11 +2700,14 @@ impl<'de> serde::Deserialize<'de> for EventValidatorVote { { const FIELDS: &[&str] = &[ "vote", + "voting_power", + "votingPower", ]; #[allow(clippy::enum_variant_names)] enum GeneratedField { Vote, + VotingPower, __SkipField__, } impl<'de> serde::Deserialize<'de> for GeneratedField { @@ -2661,6 +2731,7 @@ impl<'de> serde::Deserialize<'de> for EventValidatorVote { { match value { "vote" => Ok(GeneratedField::Vote), + "votingPower" | "voting_power" => Ok(GeneratedField::VotingPower), _ => Ok(GeneratedField::__SkipField__), } } @@ -2681,6 +2752,7 @@ impl<'de> serde::Deserialize<'de> for EventValidatorVote { V: serde::de::MapAccess<'de>, { let mut vote__ = None; + let mut voting_power__ = None; while let Some(k) = map_.next_key()? { match k { GeneratedField::Vote => { @@ -2689,6 +2761,14 @@ impl<'de> serde::Deserialize<'de> for EventValidatorVote { } vote__ = map_.next_value()?; } + GeneratedField::VotingPower => { + if voting_power__.is_some() { + return Err(serde::de::Error::duplicate_field("votingPower")); + } + voting_power__ = + Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) + ; + } GeneratedField::__SkipField__ => { let _ = map_.next_value::()?; } @@ -2696,6 +2776,7 @@ impl<'de> serde::Deserialize<'de> for EventValidatorVote { } Ok(EventValidatorVote { vote: vote__, + voting_power: voting_power__.unwrap_or_default(), }) } } diff --git a/crates/proto/src/gen/proto_descriptor.bin.no_lfs b/crates/proto/src/gen/proto_descriptor.bin.no_lfs index 77a9851c1ccbab5269b11ed459bec72cf5b6fc66..5821264a5f82538ffe843e8f6cca5c1192ea11da 100644 GIT binary patch delta 1211 zcmYk5PfQa*6vlUFUY9x`;sT`>ge`w;X=y2jNTN{>gox277-NhFNVO|8D%-Rhj3+UY z7|$HWiw7`(5TX(YZ4g2*1VhjZ=*h&yy9e}c;+yHN@i1xMoA3SJd~bGsZv?+@1;@tK zak5O=oM-YmVW;@wJoWSPmr$SYnWKNgq@eQdJvvaX-( zTuhlGcG`Y)$$Z2o_vl#p6P4*bqnNxQYWUSXdY&8aXn7b$E!)(CtPFqCBSV83>!F$T z6GIKdwbEj)Po((RKDEe<$`AHwYNFq6;;ZY>P~CW&RZ4DO*2-A9MNcP!R_D~2GB}W9j1VE1Y*YZVbi!{WwT~3 zV~wQnJp9K!>f@hhD7%6>O$w{oVdfEKvd-7$hE(jfCs-LH5Ye@1P+o(|N*RR+DyP94 zWFhPqA&L&O{9G7XduM_8WH}~LGYd7%Ziuv52!$mrs%!J0yme?%RL+Apz?zU26|@EZ zHViF~7l0g*<(Ndx0#sDFA<`D0#?Sg?32wdt5(sol!~bqAlrxGGH{>lCN!ze-Aa?qJ zX;^pV|BN$cl;-SY){Zl$gX+;Q3aHnOWsgI}Sw)G82Y3ViW71BWt}TMH?AU2TQ1eS@UMbZrHcb%z#1qM29sX{y?L|nIozHVUKYiVJL86;$vKcLzT|i2*TFDS0kOqb!`Kb5029~ zDmR4FX6zFePB%p#pX`&tXJDob_qv>GLKS|(C@bDtoSYS-*o4wzJKV;0n{K;yUE2cX zqtmV(m0NDRcF}H|KaIeN-fb6$Nz`n+Gz^ip?a~suwgdPIi!UO9${q05u@*dhLeO^k kuLy)1c3m1KQM2pPFhtt!v#u!M^5D{NmE^mk-uIn<0Zg#(6aWAK delta 700 zcmXxh&1(}u7zXg&ohRF6s#vFz4T;*uHqF;=5+tBk!9Wfo9t2Moq74X2Q)=;`AUy;; zil;di36VBZB4x`G4Jl=F@!Hy3@m~-;EBel|dl;DK<#~V1vOlNU-$&W)uHH2~#`kd8 zHMnf;;FjOmV}A?!s=Rx`R^^`)woUi9r*!{!$~yX*-1x!Pk~dmhG+wpWw;JoMr&|v; zI~$#strzmc8N2VlIb&m!2Rk~S5eZG3`ghLR?R)x1`MQ87xeMGtNtiuopP=(u&QQ_? zda$xQ&w-Mm3H0UjB8tsEj3mFv6KY7EKJ4W897!9%PKBBy%zbEIBF&-ZKCEl}CTWh+hVpv}_2v+U2-j&y zogwBkaU^Ys>kFag3iANkVWhd#Jb;x6HCJh#Y?M)dYb(!$0!YA^VgO%na)@VqbNvu&MZ4zrWVID)9Mp})U$FQ!3Ppv5}kdIyD e7lK%$A$5XSqexotuIGYIf{saN#_ze-xB7oF|9s&9 diff --git a/proto/penumbra/penumbra/core/component/governance/v1/governance.proto b/proto/penumbra/penumbra/core/component/governance/v1/governance.proto index b4a1a3712e..d5ddb4bcf4 100644 --- a/proto/penumbra/penumbra/core/component/governance/v1/governance.proto +++ b/proto/penumbra/penumbra/core/component/governance/v1/governance.proto @@ -543,6 +543,8 @@ message Ratio { message EventDelegatorVote { // The delegator vote. DelegatorVote vote = 1; + // The corresponding validator's identity key. + keys.v1.IdentityKey validator_identity_key = 2; } message EventProposalDepositClaim { @@ -553,6 +555,8 @@ message EventProposalDepositClaim { message EventValidatorVote { // The validator vote. ValidatorVote vote = 1; + // The validator's voting power at the time of the proposal's start. + uint64 voting_power = 2; } message EventProposalWithdraw { @@ -563,10 +567,14 @@ message EventProposalWithdraw { message EventProposalSubmit { // Details on the submitted proposal. ProposalSubmit submit = 1; + // The start height for the proposal. + uint64 start_height = 2; + // The end height for the proposal. + uint64 end_height = 3; } -message EventEnactProposal { - // The enacted proposal. +message EventProposalPassed { + // The passed proposal. Proposal proposal = 1; } From e610f1e84b25b4da7068a7d7c65e69679c65ab14 Mon Sep 17 00:00:00 2001 From: Lucas Meier Date: Thu, 25 Jul 2024 12:43:19 -0700 Subject: [PATCH 3/3] Fix protobuf lint about default enum variant not being unspecified --- .../core/component/governance/src/proposal.rs | 12 ++++++++---- .../penumbra.core.component.governance.v1.rs | 18 +++++++++++------- ...mbra.core.component.governance.v1.serde.rs | 3 +++ .../proto/src/gen/proto_descriptor.bin.no_lfs | Bin 549470 -> 549573 bytes .../component/governance/v1/governance.proto | 16 +++++++++------- 5 files changed, 31 insertions(+), 18 deletions(-) diff --git a/crates/core/component/governance/src/proposal.rs b/crates/core/component/governance/src/proposal.rs index f89268158f..050bc21fa6 100644 --- a/crates/core/component/governance/src/proposal.rs +++ b/crates/core/component/governance/src/proposal.rs @@ -242,9 +242,12 @@ impl From for pb::ProposalKind { } } -impl From for ProposalKind { - fn from(kind: pb::ProposalKind) -> ProposalKind { - match kind { +impl TryFrom for ProposalKind { + type Error = anyhow::Error; + + fn try_from(kind: pb::ProposalKind) -> anyhow::Result { + let kind = match kind { + pb::ProposalKind::Unspecified => anyhow::bail!("unspecified proposal kind"), pb::ProposalKind::Signaling => ProposalKind::Signaling, pb::ProposalKind::Emergency => ProposalKind::Emergency, pb::ProposalKind::ParameterChange => ProposalKind::ParameterChange, @@ -252,7 +255,8 @@ impl From for ProposalKind { pb::ProposalKind::UpgradePlan => ProposalKind::UpgradePlan, pb::ProposalKind::FreezeIbcClient => ProposalKind::FreezeIbcClient, pb::ProposalKind::UnfreezeIbcClient => ProposalKind::UnfreezeIbcClient, - } + }; + Ok(kind) } } diff --git a/crates/proto/src/gen/penumbra.core.component.governance.v1.rs b/crates/proto/src/gen/penumbra.core.component.governance.v1.rs index 792c16b681..4c188cf312 100644 --- a/crates/proto/src/gen/penumbra.core.component.governance.v1.rs +++ b/crates/proto/src/gen/penumbra.core.component.governance.v1.rs @@ -1348,13 +1348,15 @@ impl ::prost::Name for EventProposalSlashed { #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] #[repr(i32)] pub enum ProposalKind { - Signaling = 0, - Emergency = 1, - ParameterChange = 2, - CommunityPoolSpend = 3, - UpgradePlan = 4, - FreezeIbcClient = 5, - UnfreezeIbcClient = 6, + /// To make the linter happy + Unspecified = 0, + Signaling = 1, + Emergency = 2, + ParameterChange = 3, + CommunityPoolSpend = 4, + UpgradePlan = 5, + FreezeIbcClient = 6, + UnfreezeIbcClient = 7, } impl ProposalKind { /// String value of the enum field names used in the ProtoBuf definition. @@ -1363,6 +1365,7 @@ impl ProposalKind { /// (if the ProtoBuf definition does not change) and safe for programmatic use. pub fn as_str_name(&self) -> &'static str { match self { + ProposalKind::Unspecified => "PROPOSAL_KIND_UNSPECIFIED", ProposalKind::Signaling => "PROPOSAL_KIND_SIGNALING", ProposalKind::Emergency => "PROPOSAL_KIND_EMERGENCY", ProposalKind::ParameterChange => "PROPOSAL_KIND_PARAMETER_CHANGE", @@ -1375,6 +1378,7 @@ impl ProposalKind { /// Creates an enum from field names used in the ProtoBuf definition. pub fn from_str_name(value: &str) -> ::core::option::Option { match value { + "PROPOSAL_KIND_UNSPECIFIED" => Some(Self::Unspecified), "PROPOSAL_KIND_SIGNALING" => Some(Self::Signaling), "PROPOSAL_KIND_EMERGENCY" => Some(Self::Emergency), "PROPOSAL_KIND_PARAMETER_CHANGE" => Some(Self::ParameterChange), diff --git a/crates/proto/src/gen/penumbra.core.component.governance.v1.serde.rs b/crates/proto/src/gen/penumbra.core.component.governance.v1.serde.rs index dfb5534442..e5a2731256 100644 --- a/crates/proto/src/gen/penumbra.core.component.governance.v1.serde.rs +++ b/crates/proto/src/gen/penumbra.core.component.governance.v1.serde.rs @@ -4834,6 +4834,7 @@ impl serde::Serialize for ProposalKind { S: serde::Serializer, { let variant = match self { + Self::Unspecified => "PROPOSAL_KIND_UNSPECIFIED", Self::Signaling => "PROPOSAL_KIND_SIGNALING", Self::Emergency => "PROPOSAL_KIND_EMERGENCY", Self::ParameterChange => "PROPOSAL_KIND_PARAMETER_CHANGE", @@ -4852,6 +4853,7 @@ impl<'de> serde::Deserialize<'de> for ProposalKind { D: serde::Deserializer<'de>, { const FIELDS: &[&str] = &[ + "PROPOSAL_KIND_UNSPECIFIED", "PROPOSAL_KIND_SIGNALING", "PROPOSAL_KIND_EMERGENCY", "PROPOSAL_KIND_PARAMETER_CHANGE", @@ -4899,6 +4901,7 @@ impl<'de> serde::Deserialize<'de> for ProposalKind { E: serde::de::Error, { match value { + "PROPOSAL_KIND_UNSPECIFIED" => Ok(ProposalKind::Unspecified), "PROPOSAL_KIND_SIGNALING" => Ok(ProposalKind::Signaling), "PROPOSAL_KIND_EMERGENCY" => Ok(ProposalKind::Emergency), "PROPOSAL_KIND_PARAMETER_CHANGE" => Ok(ProposalKind::ParameterChange), diff --git a/crates/proto/src/gen/proto_descriptor.bin.no_lfs b/crates/proto/src/gen/proto_descriptor.bin.no_lfs index 5821264a5f82538ffe843e8f6cca5c1192ea11da..3734b128d3ae278c962ada23961532ffe80c875c 100644 GIT binary patch delta 5443 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 diff --git a/proto/penumbra/penumbra/core/component/governance/v1/governance.proto b/proto/penumbra/penumbra/core/component/governance/v1/governance.proto index d5ddb4bcf4..25d7ae69fc 100644 --- a/proto/penumbra/penumbra/core/component/governance/v1/governance.proto +++ b/proto/penumbra/penumbra/core/component/governance/v1/governance.proto @@ -325,13 +325,15 @@ message Proposal { // All the different kinds of proposals. enum ProposalKind { - PROPOSAL_KIND_SIGNALING = 0; - PROPOSAL_KIND_EMERGENCY = 1; - PROPOSAL_KIND_PARAMETER_CHANGE = 2; - PROPOSAL_KIND_COMMUNITY_POOL_SPEND = 3; - PROPOSAL_KIND_UPGRADE_PLAN = 4; - PROPOSAL_KIND_FREEZE_IBC_CLIENT = 5; - PROPOSAL_KIND_UNFREEZE_IBC_CLIENT = 6; + // To make the linter happy + PROPOSAL_KIND_UNSPECIFIED = 0; + PROPOSAL_KIND_SIGNALING = 1; + PROPOSAL_KIND_EMERGENCY = 2; + PROPOSAL_KIND_PARAMETER_CHANGE = 3; + PROPOSAL_KIND_COMMUNITY_POOL_SPEND = 4; + PROPOSAL_KIND_UPGRADE_PLAN = 5; + PROPOSAL_KIND_FREEZE_IBC_CLIENT = 6; + PROPOSAL_KIND_UNFREEZE_IBC_CLIENT = 7; } // Query operations for the governance component.