penumbra_sdk_app/
genesis.rs1use penumbra_sdk_auction::genesis::Content as AuctionContent;
2use penumbra_sdk_community_pool::genesis::Content as CommunityPoolContent;
3use penumbra_sdk_dex::genesis::Content as DexContent;
4use penumbra_sdk_distributions::genesis::Content as DistributionsContent;
5use penumbra_sdk_fee::genesis::Content as FeeContent;
6use penumbra_sdk_funding::genesis::Content as FundingContent;
7use penumbra_sdk_governance::genesis::Content as GovernanceContent;
8use penumbra_sdk_ibc::genesis::Content as IBCContent;
9use penumbra_sdk_proto::{penumbra::core::app::v1 as pb, DomainType};
10use penumbra_sdk_sct::genesis::Content as SctContent;
11use penumbra_sdk_shielded_pool::genesis::Content as ShieldedPoolContent;
12use penumbra_sdk_stake::genesis::Content as StakeContent;
13use serde::{Deserialize, Serialize};
14
15#[derive(Deserialize, Serialize, Debug, Clone)]
17#[serde(try_from = "pb::GenesisAppState", into = "pb::GenesisAppState")]
18#[allow(clippy::large_enum_variant)]
19pub enum AppState {
20 Content(Content),
22 Checkpoint(Vec<u8>),
24}
25
26impl AppState {
27 pub fn content(&self) -> Option<&Content> {
28 match self {
29 AppState::Content(content) => Some(content),
30 _ => None,
31 }
32 }
33}
34
35#[derive(Deserialize, Serialize, Debug, Clone, Default)]
36#[serde(try_from = "pb::GenesisContent", into = "pb::GenesisContent")]
37pub struct Content {
38 pub chain_id: String,
40 pub community_pool_content: CommunityPoolContent,
42 pub distributions_content: DistributionsContent,
44 pub fee_content: FeeContent,
46 pub funding_content: FundingContent,
48 pub governance_content: GovernanceContent,
50 pub ibc_content: IBCContent,
52 pub sct_content: SctContent,
54 pub shielded_pool_content: ShieldedPoolContent,
56 pub stake_content: StakeContent,
58 pub dex_content: DexContent,
60 pub auction_content: AuctionContent,
62}
63
64impl DomainType for Content {
65 type Proto = pb::GenesisContent;
66}
67
68impl Default for AppState {
69 fn default() -> Self {
70 Self::Content(Default::default())
71 }
72}
73
74impl From<AppState> for pb::GenesisAppState {
75 fn from(a: AppState) -> Self {
76 let genesis_state = match a {
77 AppState::Content(c) => {
78 pb::genesis_app_state::GenesisAppState::GenesisContent(c.into())
79 }
80 AppState::Checkpoint(h) => pb::genesis_app_state::GenesisAppState::GenesisCheckpoint(h),
81 };
82
83 pb::GenesisAppState {
84 genesis_app_state: Some(genesis_state),
85 }
86 }
87}
88
89impl From<Content> for pb::GenesisContent {
90 fn from(genesis: Content) -> Self {
91 pb::GenesisContent {
92 chain_id: genesis.chain_id,
93 auction_content: Some(genesis.auction_content.into()),
94 community_pool_content: Some(genesis.community_pool_content.into()),
95 distributions_content: Some(genesis.distributions_content.into()),
96 fee_content: Some(genesis.fee_content.into()),
97 funding_content: Some(genesis.funding_content.into()),
98 governance_content: Some(genesis.governance_content.into()),
99 ibc_content: Some(genesis.ibc_content.into()),
100 sct_content: Some(genesis.sct_content.into()),
101 shielded_pool_content: Some(genesis.shielded_pool_content.into()),
102 stake_content: Some(genesis.stake_content.into()),
103 dex_content: Some(genesis.dex_content.into()),
104 }
105 }
106}
107
108impl TryFrom<pb::GenesisAppState> for AppState {
109 type Error = anyhow::Error;
110
111 fn try_from(msg: pb::GenesisAppState) -> Result<Self, Self::Error> {
112 let state = msg
113 .genesis_app_state
114 .ok_or_else(|| anyhow::anyhow!("missing genesis_app_state field in proto"))?;
115 match state {
116 pb::genesis_app_state::GenesisAppState::GenesisContent(c) => {
117 Ok(AppState::Content(c.try_into()?))
118 }
119 pb::genesis_app_state::GenesisAppState::GenesisCheckpoint(h) => {
120 Ok(AppState::Checkpoint(h))
121 }
122 }
123 }
124}
125
126impl TryFrom<pb::GenesisContent> for Content {
127 type Error = anyhow::Error;
128
129 fn try_from(msg: pb::GenesisContent) -> Result<Self, Self::Error> {
130 Ok(Content {
131 chain_id: msg.chain_id,
132 auction_content: msg
133 .auction_content
134 .ok_or_else(|| anyhow::anyhow!("proto response missing Auction content"))?
135 .try_into()?,
136 community_pool_content: msg
137 .community_pool_content
138 .ok_or_else(|| anyhow::anyhow!("proto response missing Community Pool content"))?
139 .try_into()?,
140 distributions_content: msg
141 .distributions_content
142 .ok_or_else(|| anyhow::anyhow!("proto response missing distributions content"))?
143 .try_into()?,
144 governance_content: msg
145 .governance_content
146 .ok_or_else(|| anyhow::anyhow!("proto response missing governance content"))?
147 .try_into()?,
148 fee_content: msg
149 .fee_content
150 .ok_or_else(|| anyhow::anyhow!("proto response missing fee content"))?
151 .try_into()?,
152 funding_content: msg
153 .funding_content
154 .ok_or_else(|| anyhow::anyhow!("proto response missing funding content"))?
155 .try_into()?,
156 ibc_content: msg
157 .ibc_content
158 .ok_or_else(|| anyhow::anyhow!("proto response missing ibc content"))?
159 .try_into()?,
160 sct_content: msg
161 .sct_content
162 .ok_or_else(|| anyhow::anyhow!("proto response missing sct content"))?
163 .try_into()?,
164 shielded_pool_content: msg
165 .shielded_pool_content
166 .ok_or_else(|| anyhow::anyhow!("proto response missing shielded pool content"))?
167 .try_into()?,
168 stake_content: msg
169 .stake_content
170 .ok_or_else(|| anyhow::anyhow!("proto response missing stake content"))?
171 .try_into()?,
172 dex_content: msg
173 .dex_content
174 .ok_or_else(|| anyhow::anyhow!("proto response missing dex content"))?
175 .try_into()?,
176 })
177 }
178}
179
180impl DomainType for AppState {
181 type Proto = pb::GenesisAppState;
182}
183
184impl Content {
185 pub fn with_chain_id(self, chain_id: String) -> Self {
186 Self { chain_id, ..self }
187 }
188
189 pub fn with_epoch_duration(self, epoch_duration: u64) -> Self {
190 Self {
191 sct_content: penumbra_sdk_sct::genesis::Content {
192 sct_params: penumbra_sdk_sct::params::SctParameters { epoch_duration },
193 },
194 ..self
195 }
196 }
197
198 pub fn with_unbonding_delay(self, unbonding_delay: u64) -> Self {
199 Self {
200 stake_content: penumbra_sdk_stake::genesis::Content {
201 stake_params: penumbra_sdk_stake::params::StakeParameters {
202 unbonding_delay,
203 ..self.stake_content.stake_params
204 },
205 ..self.stake_content
206 },
207 ..self
208 }
209 }
210}
211
212#[cfg(test)]
213mod test {
214 use super::*;
215 #[test]
220 fn check_validator_defaults() -> anyhow::Result<()> {
221 let a = Content {
222 ..Default::default()
223 };
224 assert!(a.stake_content.validators.is_empty());
225 Ok(())
226 }
227}