//! ## Overview //! This module stores the previous contract state—the one you want to migrate from. //! The goal is to describe the data layout _exactly_ as it existed before. //! //! ## Guideline //! In theory, you could copy-paste every struct from the specific commit you're migrating from. //! However, this approach (a) requires manual effort from a developer and (b) increases the binary size. //! A better approach: only copy the structures that have changed and import the rest from the existing codebase. use borsh::{BorshDeserialize, BorshSerialize}; const PRE_3_14_1_EXPIRATION_DURATION_SECONDS: u64 = 60 * 60 * 24 * 7; // 7 days use near_mpc_contract_interface::types::{Metrics, VerifyForeignTransactionRequest}; use near_sdk::{ AccountId, env, store::{Lazy, LookupMap}, }; use std::time::Duration; use crate::{ SupportedForeignChainsByNode, config::Config, foreign_chains_metadata::ForeignChainsMetadata, node_migrations::NodeMigrations, primitives::{ ckd::CKDRequest, signature::{SignatureRequest, YieldIndex}, }, state::ProtocolContractState, tee::{tee_state::TeeState, verifier_votes::TeeVerifierVotes}, update::ProposedUpdates, }; /// Keep this module in sync with [`crate::MpcContract`]: the moment a field's borsh /// layout diverges, shadow the old type here (see this module's history for examples) so /// state written by the `3.14.0` contract still deserializes during migration. #[derive(Debug, BorshSerialize, BorshDeserialize)] pub struct MpcContract { protocol_state: ProtocolContractState, pending_signature_requests: LookupMap>, pending_ckd_requests: LookupMap>, pending_verify_foreign_tx_requests: LookupMap>, proposed_updates: ProposedUpdates, node_foreign_chain_support: SupportedForeignChainsByNode, config: Config, tee_state: TeeState, accept_requests: bool, node_migrations: NodeMigrations, metrics: Metrics, foreign_chains: Lazy, tee_verifier_account_id: Option, tee_verifier_votes: TeeVerifierVotes, } impl From for crate::MpcContract { fn from(old: MpcContract) -> Self { let ProtocolContractState::Running(running) = &old.protocol_state else { env::panic_str("Contract must be in running state when migrating."); }; let participants = running.parameters.participants().clone(); let mut tee_state = old.tee_state; tee_state.extend_dstack_attestation_expiries( &participants, Duration::from_secs( mpc_attestation::attestation::DEFAULT_EXPIRATION_DURATION_SECONDS - PRE_3_14_1_EXPIRATION_DURATION_SECONDS, ), ); let mut config = old.config; config.launcher_hash_unused_ttl_seconds = config .launcher_hash_unused_ttl_seconds .max(crate::config::DEFAULT_LAUNCHER_HASH_UNUSED_TTL_SECONDS); crate::MpcContract { protocol_state: old.protocol_state, pending_signature_requests: old.pending_signature_requests, pending_ckd_requests: old.pending_ckd_requests, pending_verify_foreign_tx_requests: old.pending_verify_foreign_tx_requests, proposed_updates: old.proposed_updates, node_foreign_chain_support: old.node_foreign_chain_support, config, tee_state, accept_requests: old.accept_requests, node_migrations: old.node_migrations, metrics: old.metrics, foreign_chains: old.foreign_chains, tee_verifier_account_id: old.tee_verifier_account_id, tee_verifier_votes: old.tee_verifier_votes, } } }