Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion minter/src/lifecycle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,22 @@ use crate::{
event::EventType,
init_once_state, mutate_state,
},
storage::{record_event, total_event_count, with_event_iter, with_unstable_metrics_mut},
storage::{
migrate_event_log, record_event, total_event_count, with_event_iter,
with_unstable_metrics_mut,
},
};
use canlog::log;
use cksol_types_internal::{InitArgs, UpgradeArgs, log::Priority};

/// One-time migration: converts legacy `AcceptedManualDeposit` events (CBOR index 2,
/// no `source` field) to `AcceptedDeposit { source: Manual }` (same CBOR index).
///
/// Safe to call multiple times. Remove after the migration has been confirmed.
fn migrate_accepted_manual_deposit_events() {
migrate_event_log();
}

pub fn init<R: CanisterRuntime>(init_args: InitArgs, runtime: R) {
log!(
Priority::Info,
Expand All @@ -23,6 +34,7 @@ pub fn init<R: CanisterRuntime>(init_args: InitArgs, runtime: R) {
pub fn post_upgrade<R: CanisterRuntime>(upgrade_args: Option<UpgradeArgs>, runtime: R) {
let start = runtime.instruction_counter();

migrate_accepted_manual_deposit_events();
init_once_state(with_event_iter(|events| replay_events(events)));
if let Some(args) = upgrade_args {
log!(
Expand Down
108 changes: 108 additions & 0 deletions minter/src/state/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,3 +225,111 @@ impl Storable for Event {

const BOUND: Bound = Bound::Unbounded;
}

/// Legacy event type matching the CBOR encoding of events written before `AcceptedDeposit`
/// was introduced. Used only by the one-time migration in `post_upgrade`.
/// Remove after the migration has run.
#[derive(Decode, Encode)]
pub(crate) enum LegacyEventType {
#[n(0)]
Init(#[n(0)] InitArgs),
#[n(1)]
Upgrade(#[n(0)] UpgradeArgs),
/// Old form of `AcceptedDeposit` — no `source` field.
#[n(2)]
AcceptedManualDeposit {
#[n(0)]
deposit_id: DepositId,
#[n(1)]
deposit_amount: Lamport,
#[n(2)]
amount_to_mint: Lamport,
},
#[n(3)]
QuarantinedDeposit(#[n(0)] DepositId),
#[n(4)]
Minted {
#[n(0)]
deposit_id: DepositId,
#[cbor(n(1), with = "cbor::id")]
mint_block_index: LedgerMintIndex,
},
#[n(5)]
AcceptedWithdrawalRequest(#[n(0)] WithdrawalRequest),
#[n(6)]
SubmittedTransaction {
#[cbor(n(0), with = "cbor::signature")]
signature: Signature,
#[n(1)]
message: VersionedMessage,
#[n(2)]
signers: Vec<Account>,
#[n(3)]
slot: Slot,
#[n(4)]
purpose: TransactionPurpose,
},
#[n(7)]
ResubmittedTransaction {
#[cbor(n(0), with = "cbor::signature")]
old_signature: Signature,
#[cbor(n(1), with = "cbor::signature")]
new_signature: Signature,
#[n(2)]
new_slot: Slot,
},
#[n(8)]
SucceededTransaction {
#[cbor(n(0), with = "cbor::signature")]
signature: Signature,
},
#[n(9)]
FailedTransaction {
#[cbor(n(0), with = "cbor::signature")]
signature: Signature,
},
#[n(10)]
ExpiredTransaction {
#[cbor(n(0), with = "cbor::signature")]
signature: Signature,
},
#[n(11)]
StartedMonitoringAccount {
#[n(0)]
account: Account,
},
#[n(12)]
StoppedMonitoringAccount {
#[n(0)]
account: Account,
},
}

/// Legacy event wrapper for migration. See `LegacyEventType`.
/// Remove after the migration has run.
#[derive(Decode, Encode)]
pub(crate) struct LegacyEvent {
#[n(0)]
pub timestamp: u64,
#[n(1)]
pub payload: LegacyEventType,
}

impl Storable for LegacyEvent {
fn to_bytes(&self) -> Cow<'_, [u8]> {
let mut buf = vec![];
minicbor::encode(self, &mut buf).expect("event encoding should always succeed");
Cow::Owned(buf)
}

fn from_bytes(bytes: Cow<[u8]>) -> Self {
minicbor::decode(bytes.as_ref()).unwrap_or_else(|e| {
panic!(
"failed to decode legacy event bytes {}: {e}",
hex::encode(bytes)
)
})
}

const BOUND: Bound = Bound::Unbounded;
}
Loading
Loading