penumbra_sdk_governance/delegator_vote/
action.rs1use anyhow::Context;
2
3use crate::{vote::Vote, DelegatorVoteProof};
4use decaf377_rdsa::{Signature, SpendAuth, VerificationKey};
5use penumbra_sdk_asset::Value;
6use penumbra_sdk_num::Amount;
7use penumbra_sdk_proto::{core::component::governance::v1 as pb, DomainType};
8use penumbra_sdk_sct::Nullifier;
9use penumbra_sdk_tct as tct;
10use penumbra_sdk_txhash::{EffectHash, EffectingData};
11
12#[derive(Debug, Clone, Copy)]
13pub struct DelegatorVote {
14 pub body: DelegatorVoteBody,
15 pub auth_sig: Signature<SpendAuth>,
16 pub proof: DelegatorVoteProof,
17}
18
19impl EffectingData for DelegatorVote {
20 fn effect_hash(&self) -> EffectHash {
21 self.body.effect_hash()
22 }
23}
24
25#[derive(Debug, Clone, Copy)]
27pub struct DelegatorVoteBody {
28 pub proposal: u64,
30 pub start_position: tct::Position,
32 pub vote: Vote, pub value: Value, pub unbonded_amount: Amount,
38 pub nullifier: Nullifier,
40 pub rk: VerificationKey<SpendAuth>,
42}
43
44impl EffectingData for DelegatorVoteBody {
45 fn effect_hash(&self) -> EffectHash {
46 EffectHash::from_proto_effecting_data(&self.to_proto())
47 }
48}
49
50impl From<DelegatorVoteBody> for pb::DelegatorVoteBody {
51 fn from(value: DelegatorVoteBody) -> Self {
52 pb::DelegatorVoteBody {
53 proposal: value.proposal,
54 start_position: value.start_position.into(),
55 vote: Some(value.vote.into()),
56 value: Some(value.value.into()),
57 unbonded_amount: Some(value.unbonded_amount.into()),
58 nullifier: Some(value.nullifier.into()),
59 rk: Some(value.rk.into()),
60 }
61 }
62}
63
64impl TryFrom<pb::DelegatorVoteBody> for DelegatorVoteBody {
65 type Error = anyhow::Error;
66
67 fn try_from(msg: pb::DelegatorVoteBody) -> Result<Self, Self::Error> {
68 Ok(DelegatorVoteBody {
69 proposal: msg.proposal,
70 start_position: msg
71 .start_position
72 .try_into()
73 .context("invalid start position in `DelegatorVote`")?,
74 vote: msg
75 .vote
76 .ok_or_else(|| anyhow::anyhow!("missing vote in `DelegatorVote`"))?
77 .try_into()?,
78 value: msg
79 .value
80 .ok_or_else(|| anyhow::anyhow!("missing value in `DelegatorVote`"))?
81 .try_into()?,
82 unbonded_amount: msg
83 .unbonded_amount
84 .ok_or_else(|| anyhow::anyhow!("missing unbonded amount in `DelegatorVote`"))?
85 .try_into()?,
86 nullifier: msg
87 .nullifier
88 .ok_or_else(|| anyhow::anyhow!("missing nullifier in `DelegatorVote`"))?
89 .try_into()
90 .context("invalid nullifier in `DelegatorVote`")?,
91 rk: msg
92 .rk
93 .ok_or_else(|| anyhow::anyhow!("missing rk in `DelegatorVote`"))?
94 .try_into()
95 .context("invalid rk in `DelegatorVote`")?,
96 })
97 }
98}
99
100impl DomainType for DelegatorVoteBody {
101 type Proto = pb::DelegatorVoteBody;
102}
103
104impl From<DelegatorVote> for pb::DelegatorVote {
105 fn from(value: DelegatorVote) -> Self {
106 pb::DelegatorVote {
107 body: Some(value.body.into()),
108 auth_sig: Some(value.auth_sig.into()),
109 proof: Some(value.proof.into()),
110 }
111 }
112}
113
114impl TryFrom<pb::DelegatorVote> for DelegatorVote {
115 type Error = anyhow::Error;
116
117 fn try_from(msg: pb::DelegatorVote) -> Result<Self, Self::Error> {
118 Ok(DelegatorVote {
119 body: msg
120 .body
121 .ok_or_else(|| anyhow::anyhow!("missing body in `DelegatorVote`"))?
122 .try_into()?,
123 auth_sig: msg
124 .auth_sig
125 .ok_or_else(|| anyhow::anyhow!("missing auth sig in `DelegatorVote`"))?
126 .try_into()?,
127 proof: msg
128 .proof
129 .ok_or_else(|| anyhow::anyhow!("missing delegator vote proof"))?
130 .try_into()
131 .context("delegator vote proof malformed")?,
132 })
133 }
134}