Skip to content

Commit a77c2db

Browse files
authored
migration(testnet78): Avoid deserializing proto types to domain types in migration (#4606)
## Describe your changes Don't deserialize proto types to avoid applying new domain validations to old types in migration 78 ## Issue ticket number and link #4596 (comment) ## Checklist before requesting a review - [x ] If this code contains consensus-breaking changes, I have added the "consensus-breaking" label. Otherwise, I declare my belief that there are not consensus-breaking changes, for the following reason: > Migration change
1 parent 9398d67 commit a77c2db

File tree

1 file changed

+165
-83
lines changed

1 file changed

+165
-83
lines changed

crates/bin/pd/src/migrate/testnet78.rs

+165-83
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@ use cnidarium::{Snapshot, StateDelta, Storage};
44
use futures::TryStreamExt as _;
55
use jmt::RootHash;
66
use penumbra_app::app::StateReadExt as _;
7+
use penumbra_governance::proposal_state::State as ProposalState;
8+
use penumbra_governance::Proposal;
79
use penumbra_governance::StateReadExt as _;
810
use penumbra_governance::StateWriteExt;
11+
use penumbra_proto::core::component::governance::v1 as pb_governance;
912
use penumbra_proto::{StateReadProto as _, StateWriteProto as _};
1013
use penumbra_sct::component::clock::EpochManager;
1114
use penumbra_sct::component::clock::EpochRead as _;
@@ -160,6 +163,7 @@ async fn truncate_validator_fields(delta: &mut StateDelta<Snapshot>) -> anyhow::
160163
validator.website = truncate(&validator.website, 70).to_string();
161164
validator.description = truncate(&validator.description, 280).to_string();
162165

166+
// Ensure the validator can be serialized back to the domain type:
163167
let validator: Validator = validator.try_into()?;
164168
tracing::info!("put key {:?}", key);
165169
delta.put(key, validator);
@@ -188,7 +192,11 @@ async fn truncate_proposal_fields(delta: &mut StateDelta<Snapshot>) -> anyhow::R
188192
// Range each proposal and truncate the fields.
189193
for proposal_id in 0..next_proposal_id {
190194
tracing::info!("truncating proposal: {}", proposal_id);
191-
let proposal = delta.proposal_definition(proposal_id).await?;
195+
let proposal = delta
196+
.get_proto::<pb_governance::Proposal>(
197+
&penumbra_governance::state_key::proposal_definition(proposal_id),
198+
)
199+
.await?;
192200

193201
if proposal.is_none() {
194202
break;
@@ -200,14 +208,20 @@ async fn truncate_proposal_fields(delta: &mut StateDelta<Snapshot>) -> anyhow::R
200208
proposal.description = truncate(&proposal.description, 10_000).to_string();
201209

202210
// Depending on the proposal type, we may need to truncate additional fields.
203-
match proposal.payload {
204-
penumbra_governance::ProposalPayload::Signaling { commit } => {
205-
proposal.payload = penumbra_governance::ProposalPayload::Signaling {
206-
commit: commit.map(|commit| truncate(&commit, 255).to_string()),
207-
};
211+
match proposal
212+
.payload
213+
.clone()
214+
.expect("proposal payload always set")
215+
{
216+
pb_governance::proposal::Payload::Signaling(commit) => {
217+
proposal.payload = Some(pb_governance::proposal::Payload::Signaling(
218+
pb_governance::proposal::Signaling {
219+
commit: truncate(&commit.commit, 255).to_string(),
220+
},
221+
));
208222
}
209-
penumbra_governance::ProposalPayload::Emergency { halt_chain: _ } => {}
210-
penumbra_governance::ProposalPayload::ParameterChange(mut param_change) => {
223+
pb_governance::proposal::Payload::Emergency(_halt_chain) => {}
224+
pb_governance::proposal::Payload::ParameterChange(mut param_change) => {
211225
for (i, mut change) in param_change.changes.clone().into_iter().enumerate() {
212226
let key = truncate(&change.key, 64).to_string();
213227
let value = truncate(&change.value, 2048).to_string();
@@ -232,22 +246,25 @@ async fn truncate_proposal_fields(delta: &mut StateDelta<Snapshot>) -> anyhow::R
232246
param_change.preconditions[i] = change;
233247
}
234248

235-
proposal.payload =
236-
penumbra_governance::ProposalPayload::ParameterChange(param_change);
249+
proposal.payload = Some(pb_governance::proposal::Payload::ParameterChange(
250+
param_change,
251+
));
237252
}
238-
penumbra_governance::ProposalPayload::CommunityPoolSpend {
239-
transaction_plan: _,
240-
} => {}
241-
penumbra_governance::ProposalPayload::UpgradePlan { height: _ } => {}
242-
penumbra_governance::ProposalPayload::FreezeIbcClient { client_id } => {
243-
proposal.payload = penumbra_governance::ProposalPayload::FreezeIbcClient {
244-
client_id: truncate(&client_id, 128).to_string(),
245-
};
253+
pb_governance::proposal::Payload::CommunityPoolSpend(_transaction_plan) => {}
254+
pb_governance::proposal::Payload::UpgradePlan(_height) => {}
255+
pb_governance::proposal::Payload::FreezeIbcClient(client_id) => {
256+
proposal.payload = Some(pb_governance::proposal::Payload::FreezeIbcClient(
257+
pb_governance::proposal::FreezeIbcClient {
258+
client_id: truncate(&client_id.client_id, 128).to_string(),
259+
},
260+
));
246261
}
247-
penumbra_governance::ProposalPayload::UnfreezeIbcClient { client_id } => {
248-
proposal.payload = penumbra_governance::ProposalPayload::UnfreezeIbcClient {
249-
client_id: truncate(&client_id, 128).to_string(),
250-
};
262+
pb_governance::proposal::Payload::UnfreezeIbcClient(client_id) => {
263+
proposal.payload = Some(pb_governance::proposal::Payload::UnfreezeIbcClient(
264+
pb_governance::proposal::UnfreezeIbcClient {
265+
client_id: truncate(&client_id.client_id, 128).to_string(),
266+
},
267+
));
251268
}
252269
};
253270

@@ -256,9 +273,11 @@ async fn truncate_proposal_fields(delta: &mut StateDelta<Snapshot>) -> anyhow::R
256273
"put key {:?}",
257274
penumbra_governance::state_key::proposal_definition(proposal_id)
258275
);
276+
// Ensure the proposal can be serialized back to the domain type:
277+
let proposal: Proposal = proposal.try_into()?;
259278
delta.put(
260279
penumbra_governance::state_key::proposal_definition(proposal_id),
261-
proposal.clone(),
280+
proposal,
262281
);
263282
}
264283

@@ -274,83 +293,145 @@ async fn truncate_proposal_outcome_fields(delta: &mut StateDelta<Snapshot>) -> a
274293
// Range each proposal outcome and truncate the fields.
275294
for proposal_id in 0..next_proposal_id {
276295
tracing::info!("truncating proposal outcomes: {}", proposal_id);
277-
let proposal_state = delta.proposal_state(proposal_id).await?;
296+
let proposal_state = delta
297+
.get_proto::<pb_governance::ProposalState>(
298+
&penumbra_governance::state_key::proposal_state(proposal_id),
299+
)
300+
.await?;
278301

279302
if proposal_state.is_none() {
280303
break;
281304
}
282305

283306
let mut proposal_state = proposal_state.unwrap();
284307

285-
match proposal_state {
286-
penumbra_governance::proposal_state::State::Withdrawn { reason } => {
287-
proposal_state = penumbra_governance::proposal_state::State::Withdrawn {
288-
reason: truncate(&reason, 1024).to_string(),
289-
};
308+
match proposal_state
309+
.state
310+
.clone()
311+
.expect("proposal state always set")
312+
{
313+
pb_governance::proposal_state::State::Withdrawn(reason) => {
314+
proposal_state.state = Some(pb_governance::proposal_state::State::Withdrawn(
315+
pb_governance::proposal_state::Withdrawn {
316+
reason: truncate(&reason.reason, 1024).to_string(),
317+
},
318+
));
290319
}
291-
penumbra_governance::proposal_state::State::Voting => {}
292-
penumbra_governance::proposal_state::State::Finished { ref outcome } => match outcome {
293-
penumbra_governance::proposal_state::Outcome::Passed => {}
294-
penumbra_governance::proposal_state::Outcome::Failed { withdrawn } => {
295-
match withdrawn {
296-
penumbra_governance::proposal_state::Withdrawn::No => {}
297-
penumbra_governance::proposal_state::Withdrawn::WithReason { reason } => {
298-
proposal_state = penumbra_governance::proposal_state::State::Finished {
299-
outcome: penumbra_governance::proposal_state::Outcome::Failed {
300-
withdrawn:
301-
penumbra_governance::proposal_state::Withdrawn::WithReason {
302-
reason: truncate(&reason, 1024).to_string(),
303-
},
304-
},
305-
};
320+
pb_governance::proposal_state::State::Voting(_) => {}
321+
pb_governance::proposal_state::State::Finished(ref outcome) => match outcome
322+
.outcome
323+
.clone()
324+
.expect("proposal outcome always set")
325+
.outcome
326+
.expect("proposal outcome always set")
327+
{
328+
pb_governance::proposal_outcome::Outcome::Passed(_) => {}
329+
pb_governance::proposal_outcome::Outcome::Failed(withdrawn) => {
330+
match withdrawn.withdrawn {
331+
None => {
332+
// Withdrawn::No
333+
}
334+
Some(pb_governance::proposal_outcome::Withdrawn { reason }) => {
335+
// Withdrawn::WithReason
336+
proposal_state.state =
337+
Some(pb_governance::proposal_state::State::Finished(
338+
pb_governance::proposal_state::Finished {
339+
outcome: Some(pb_governance::ProposalOutcome{
340+
outcome: Some(pb_governance::proposal_outcome::Outcome::Failed(
341+
pb_governance::proposal_outcome::Failed {
342+
withdrawn:
343+
Some(pb_governance::proposal_outcome::Withdrawn {
344+
reason: truncate(&reason, 1024)
345+
.to_string(),
346+
}),
347+
},
348+
)),
349+
}),
350+
},
351+
));
306352
}
307353
}
308354
}
309-
penumbra_governance::proposal_state::Outcome::Slashed { withdrawn } => {
310-
match withdrawn {
311-
penumbra_governance::proposal_state::Withdrawn::No => {}
312-
penumbra_governance::proposal_state::Withdrawn::WithReason { reason } => {
313-
proposal_state = penumbra_governance::proposal_state::State::Finished {
314-
outcome: penumbra_governance::proposal_state::Outcome::Slashed {
315-
withdrawn:
316-
penumbra_governance::proposal_state::Withdrawn::WithReason {
317-
reason: truncate(&reason, 1024).to_string(),
318-
},
319-
},
320-
};
355+
pb_governance::proposal_outcome::Outcome::Slashed(withdrawn) => {
356+
match withdrawn.withdrawn {
357+
None => {
358+
// Withdrawn::No
359+
}
360+
Some(pb_governance::proposal_outcome::Withdrawn { reason }) => {
361+
// Withdrawn::WithReason
362+
proposal_state.state = Some(pb_governance::proposal_state::State::Finished(
363+
pb_governance::proposal_state::Finished {
364+
outcome: Some(pb_governance::ProposalOutcome{
365+
outcome: Some(pb_governance::proposal_outcome::Outcome::Slashed(
366+
pb_governance::proposal_outcome::Slashed {
367+
withdrawn:
368+
Some(pb_governance::proposal_outcome::Withdrawn {
369+
reason: truncate(&reason, 1024)
370+
.to_string(),
371+
}),
372+
},
373+
)),
374+
}),
375+
},
376+
));
321377
}
322378
}
323379
}
324380
},
325-
penumbra_governance::proposal_state::State::Claimed { ref outcome } => match outcome {
326-
penumbra_governance::proposal_state::Outcome::Passed => {}
327-
penumbra_governance::proposal_state::Outcome::Failed { withdrawn } => {
328-
match withdrawn {
329-
penumbra_governance::proposal_state::Withdrawn::No => {}
330-
penumbra_governance::proposal_state::Withdrawn::WithReason { reason } => {
331-
proposal_state = penumbra_governance::proposal_state::State::Claimed {
332-
outcome: penumbra_governance::proposal_state::Outcome::Failed {
333-
withdrawn:
334-
penumbra_governance::proposal_state::Withdrawn::WithReason {
335-
reason: truncate(&reason, 1024).to_string(),
336-
},
337-
},
338-
};
381+
pb_governance::proposal_state::State::Claimed(ref outcome) => match outcome
382+
.outcome
383+
.clone()
384+
.expect("outcome is set")
385+
.outcome
386+
.expect("outcome is set")
387+
{
388+
pb_governance::proposal_outcome::Outcome::Passed(_) => {}
389+
pb_governance::proposal_outcome::Outcome::Failed(withdrawn) => {
390+
match withdrawn.withdrawn {
391+
None => {
392+
// Withdrawn::No
393+
}
394+
Some(pb_governance::proposal_outcome::Withdrawn { reason }) => {
395+
// Withdrawn::WithReason
396+
proposal_state.state = Some(pb_governance::proposal_state::State::Claimed(
397+
pb_governance::proposal_state::Claimed {
398+
outcome: Some(pb_governance::ProposalOutcome{
399+
outcome: Some(pb_governance::proposal_outcome::Outcome::Failed(
400+
pb_governance::proposal_outcome::Failed{
401+
withdrawn:
402+
Some(pb_governance::proposal_outcome::Withdrawn {
403+
reason: truncate(&reason, 1024)
404+
.to_string(),
405+
}),
406+
},
407+
)),
408+
}),
409+
},
410+
));
339411
}
340412
}
341413
}
342-
penumbra_governance::proposal_state::Outcome::Slashed { withdrawn } => {
343-
match withdrawn {
344-
penumbra_governance::proposal_state::Withdrawn::No => {}
345-
penumbra_governance::proposal_state::Withdrawn::WithReason { reason } => {
346-
proposal_state = penumbra_governance::proposal_state::State::Claimed {
347-
outcome: penumbra_governance::proposal_state::Outcome::Slashed {
348-
withdrawn:
349-
penumbra_governance::proposal_state::Withdrawn::WithReason {
350-
reason: truncate(&reason, 1024).to_string(),
351-
},
352-
},
353-
};
414+
pb_governance::proposal_outcome::Outcome::Slashed(withdrawn) => {
415+
match withdrawn.withdrawn {
416+
None => {
417+
// Withdrawn::No
418+
}
419+
Some(pb_governance::proposal_outcome::Withdrawn { reason }) => {
420+
proposal_state.state = Some(pb_governance::proposal_state::State::Claimed(
421+
pb_governance::proposal_state::Claimed {
422+
outcome: Some(pb_governance::ProposalOutcome{
423+
outcome: Some(pb_governance::proposal_outcome::Outcome::Slashed(
424+
pb_governance::proposal_outcome::Slashed{
425+
withdrawn:
426+
Some(pb_governance::proposal_outcome::Withdrawn {
427+
reason: truncate(&reason, 1024)
428+
.to_string(),
429+
}),
430+
},
431+
)),
432+
}),
433+
},
434+
));
354435
}
355436
}
356437
}
@@ -362,9 +443,10 @@ async fn truncate_proposal_outcome_fields(delta: &mut StateDelta<Snapshot>) -> a
362443
"put key {:?}",
363444
penumbra_governance::state_key::proposal_state(proposal_id)
364445
);
446+
let proposal_state: ProposalState = proposal_state.try_into()?;
365447
delta.put(
366448
penumbra_governance::state_key::proposal_state(proposal_id),
367-
proposal_state.clone(),
449+
proposal_state,
368450
);
369451
}
370452
Ok(())

0 commit comments

Comments
 (0)