penumbra_governance/validator_vote/
action.rsuse decaf377_rdsa::{Signature, SpendAuth};
use penumbra_proto::{penumbra::core::component::governance::v1 as pb, DomainType};
use penumbra_stake::{GovernanceKey, IdentityKey};
use penumbra_txhash::{EffectHash, EffectingData};
use serde::{Deserialize, Serialize};
use crate::{vote::Vote, MAX_VALIDATOR_VOTE_REASON_LENGTH};
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(try_from = "pb::ValidatorVote", into = "pb::ValidatorVote")]
pub struct ValidatorVote {
pub body: ValidatorVoteBody,
pub auth_sig: Signature<SpendAuth>,
}
impl EffectingData for ValidatorVote {
fn effect_hash(&self) -> EffectHash {
EffectHash::from_proto_effecting_data(&self.to_proto())
}
}
impl DomainType for ValidatorVote {
type Proto = pb::ValidatorVote;
}
impl From<ValidatorVote> for pb::ValidatorVote {
fn from(msg: ValidatorVote) -> Self {
Self {
body: Some(msg.body.into()),
auth_sig: Some(msg.auth_sig.into()),
}
}
}
impl TryFrom<pb::ValidatorVote> for ValidatorVote {
type Error = anyhow::Error;
fn try_from(msg: pb::ValidatorVote) -> Result<Self, Self::Error> {
Ok(Self {
body: msg
.body
.ok_or_else(|| anyhow::anyhow!("missing validator vote body"))?
.try_into()?,
auth_sig: msg
.auth_sig
.ok_or_else(|| anyhow::anyhow!("missing validator auth sig"))?
.try_into()?,
})
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(try_from = "pb::ValidatorVoteBody", into = "pb::ValidatorVoteBody")]
pub struct ValidatorVoteBody {
pub proposal: u64,
pub vote: Vote,
pub identity_key: IdentityKey,
pub governance_key: GovernanceKey,
pub reason: ValidatorVoteReason,
}
impl From<ValidatorVoteBody> for pb::ValidatorVoteBody {
fn from(value: ValidatorVoteBody) -> Self {
pb::ValidatorVoteBody {
proposal: value.proposal,
vote: Some(value.vote.into()),
identity_key: Some(value.identity_key.into()),
governance_key: Some(value.governance_key.into()),
reason: Some(value.reason.into()),
}
}
}
impl TryFrom<pb::ValidatorVoteBody> for ValidatorVoteBody {
type Error = anyhow::Error;
fn try_from(msg: pb::ValidatorVoteBody) -> Result<Self, Self::Error> {
Ok(ValidatorVoteBody {
proposal: msg.proposal,
vote: msg
.vote
.ok_or_else(|| anyhow::anyhow!("missing vote in `ValidatorVote`"))?
.try_into()?,
identity_key: msg
.identity_key
.ok_or_else(|| anyhow::anyhow!("missing validator identity in `ValidatorVote`"))?
.try_into()?,
governance_key: msg
.governance_key
.ok_or_else(|| {
anyhow::anyhow!("missing validator governance key in `ValidatorVote`")
})?
.try_into()?,
reason: msg
.reason
.ok_or_else(|| {
anyhow::anyhow!("missing validator governance key in `ValidatorVote`")
})?
.try_into()?,
})
}
}
impl DomainType for ValidatorVoteBody {
type Proto = pb::ValidatorVoteBody;
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(try_from = "pb::ValidatorVoteReason", into = "pb::ValidatorVoteReason")]
pub struct ValidatorVoteReason(pub String);
impl From<ValidatorVoteReason> for pb::ValidatorVoteReason {
fn from(value: ValidatorVoteReason) -> Self {
pb::ValidatorVoteReason { reason: value.0 }
}
}
impl TryFrom<pb::ValidatorVoteReason> for ValidatorVoteReason {
type Error = anyhow::Error;
fn try_from(msg: pb::ValidatorVoteReason) -> Result<Self, Self::Error> {
if msg.reason.len() > MAX_VALIDATOR_VOTE_REASON_LENGTH {
anyhow::bail!("validator vote reason is too long");
}
Ok(ValidatorVoteReason(msg.reason))
}
}
impl DomainType for ValidatorVoteReason {
type Proto = pb::ValidatorVoteReason;
}