Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[dont merge] runtime upgrade to fix polkadot vault #4055

Closed
wants to merge 9 commits into from
5 changes: 2 additions & 3 deletions state-chain/TROUBLESHOOTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ SKIP_WASM_BUILD=1 cargo build --release --features=try-runtime
Now you can run your tests like so (using an appropriate public rpc node):

```sh
./target/release/chainflip-node try-runtime --execution native \
./target/release/chainflip-node try-runtime \
--runtime ./path/to/state_chain_runtime.wasm \
on-runtime-upgrade live --uri wss://perseverance.chainflip.xyz:443
```

Expand All @@ -48,8 +49,6 @@ Once the node has synced, in another terminal window, run the checks:
on-runtime-upgrade live --uri ws://localhost:9944
```

> *Note: Using `--execution native` ensures faster execution and also prevents log messages from being scrubbed.

### General tips and guidelines

- There are some useful storage conversion utilities in `frame_support::storage::migration`.
Expand Down
8 changes: 7 additions & 1 deletion state-chain/chains/src/dot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,10 +267,12 @@ impl Chain for Polkadot {
type DepositChannelState = PolkadotChannelState;
type DepositDetails = ();
type Transaction = PolkadotTransactionData;
type ReplayProtectionParams = ();
type ReplayProtectionParams = ResetProxyAccountNonce;
type ReplayProtection = PolkadotReplayProtection;
}

pub type ResetProxyAccountNonce = bool;

#[derive(Clone, Encode, Decode, MaxEncodedLen, TypeInfo, Debug, PartialEq, Eq, Default)]
pub struct PolkadotChannelState;

Expand Down Expand Up @@ -341,6 +343,10 @@ impl PolkadotExtrinsicBuilder {
Self { extrinsic_call, replay_protection, signer_and_signature: None }
}

pub fn force_nonce(&mut self, nonce: u32) {
self.replay_protection.nonce = nonce;
}

pub fn signature(&self) -> Option<PolkadotSignature> {
self.signer_and_signature.as_ref().map(|(_, sig)| sig.clone())
}
Expand Down
7 changes: 4 additions & 3 deletions state-chain/chains/src/dot/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ where
transfer_params: Vec<TransferAssetParams<Polkadot>>,
) -> Result<Self, AllBatchError> {
Ok(Self::BatchFetchAndTransfer(batch_fetch_and_transfer::extrinsic_builder(
E::replay_protection(()),
E::replay_protection(false),
fetch_params,
transfer_params,
E::try_vault_account().ok_or(AllBatchError::Other)?,
Expand All @@ -85,7 +85,7 @@ where
let vault = E::try_vault_account().ok_or(())?;

Ok(Self::ChangeGovKey(rotate_vault_proxy::extrinsic_builder(
E::replay_protection(()),
E::replay_protection(false),
maybe_old_key,
new_key,
vault,
Expand All @@ -104,7 +104,8 @@ where
let vault = E::try_vault_account().ok_or(SetAggKeyWithAggKeyError::Failed)?;

Ok(Self::RotateVaultProxy(rotate_vault_proxy::extrinsic_builder(
E::replay_protection(()),
// we reset the proxy account nonce on a rotation tx
E::replay_protection(true),
maybe_old_key,
new_key,
vault,
Expand Down
20 changes: 11 additions & 9 deletions state-chain/pallets/cf-environment/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,10 +196,10 @@ pub mod pallet {
fn pre_upgrade() -> Result<sp_std::vec::Vec<u8>, DispatchError> {
if let Some(next_version) = NextCompatibilityVersion::<T>::get() {
if next_version != T::CurrentCompatibilityVersion::get() {
return Err("NextCompatibilityVersion does not match the current runtime".into())
log::warn!("NextCompatibilityVersion does not match the current runtime");
}
} else {
return Err("NextCompatibilityVersion is not set".into())
log::warn!("NextCompatibilityVersion is not set");
}
migrations::PalletMigration::<T>::pre_upgrade()
}
Expand Down Expand Up @@ -387,15 +387,17 @@ impl<T: Config> Pallet<T> {
})
}

pub fn next_polkadot_proxy_account_nonce() -> PolkadotIndex {
pub fn next_polkadot_proxy_account_nonce(reset_nonce: bool) -> PolkadotIndex {
PolkadotProxyAccountNonce::<T>::mutate(|nonce| {
*nonce += 1;
*nonce - 1
})
}
let current_nonce = *nonce;

pub fn reset_polkadot_proxy_account_nonce() {
PolkadotProxyAccountNonce::<T>::set(0);
if reset_nonce {
*nonce = 0;
} else {
*nonce += 1;
}
current_nonce
})
}

pub fn add_bitcoin_utxo_to_list(
Expand Down
5 changes: 1 addition & 4 deletions state-chain/pallets/cf-vaults/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use cf_traits::{
impl_pallet_safe_mode, offence_reporting::OffenceReporter, AccountRoleRegistry, AsyncResult,
Broadcaster, Chainflip, CurrentEpochIndex, EpochKey, GetBlockHeight, KeyProvider, KeyState,
SafeMode, SetSafeMode, Slashing, ThresholdSigner, VaultKeyWitnessedHandler, VaultRotator,
VaultStatus, VaultTransitionHandler,
VaultStatus,
};
use frame_support::{
pallet_prelude::*,
Expand Down Expand Up @@ -174,8 +174,6 @@ pub mod pallet {
<<Self as pallet::Config<I>>::Chain as Chain>::ChainCrypto,
>;

type VaultTransitionHandler: VaultTransitionHandler<Self::Chain>;

/// The pallet dispatches calls, so it depends on the runtime's aggregated Call type.
type RuntimeCall: From<Call<Self, I>> + IsType<<Self as frame_system::Config>::RuntimeCall>;

Expand Down Expand Up @@ -961,7 +959,6 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
active_from_block: block_number.saturating_add(One::one()),
},
);
T::VaultTransitionHandler::on_new_vault();
Self::deposit_event(Event::VaultRotationCompleted);
}
}
Expand Down
6 changes: 0 additions & 6 deletions state-chain/pallets/cf-vaults/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,11 +132,6 @@ impl ApiCall<MockEthereumChainCrypto> for MockSetAggKeyWithAggKey {
}
}

pub struct MockVaultTransitionHandler;
impl VaultTransitionHandler<MockEthereum> for MockVaultTransitionHandler {
fn on_new_vault() {}
}

pub struct MockBroadcaster;

impl MockBroadcaster {
Expand Down Expand Up @@ -223,7 +218,6 @@ impl pallet_cf_vaults::Config for Test {
type ThresholdSigner = MockThresholdSigner<MockEthereumChainCrypto, RuntimeCall>;
type OffenceReporter = MockOffenceReporter;
type SetAggKeyWithAggKey = MockSetAggKeyWithAggKey;
type VaultTransitionHandler = MockVaultTransitionHandler;
type WeightInfo = ();
type Broadcaster = MockBroadcaster;
type SafeMode = MockRuntimeSafeMode;
Expand Down
119 changes: 46 additions & 73 deletions state-chain/runtime-upgrade-utilities/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,83 +31,56 @@ pub struct VersionedMigration<

#[cfg(feature = "try-runtime")]
mod try_runtime_helpers {
use frame_support::traits::PalletInfoAccess;
use sp_std::vec::Vec;

#[cfg(feature = "std")]
pub use with_std::*;

#[cfg(not(feature = "std"))]
pub use without_std::*;

#[cfg(feature = "std")]
mod with_std {
use super::*;
use core::cell::RefCell;
use sp_std::{
cmp::{max, min},
collections::btree_map::BTreeMap,
};

thread_local! {
pub static MIGRATION_BOUNDS: RefCell<BTreeMap<&'static str, (u16, u16)>> = Default::default();
#[allow(clippy::type_complexity)]
pub static MIGRATION_STATE: RefCell<BTreeMap<&'static str, BTreeMap<(u16, u16), Vec<u8>>>> = Default::default();
}

pub fn update_migration_bounds<T: PalletInfoAccess, const FROM: u16, const TO: u16>() {
MIGRATION_BOUNDS.with(|cell| {
cell.borrow_mut()
.entry(T::name())
.and_modify(|(from, to)| {
*from = min(*from, FROM);
*to = max(*to, TO);
})
.or_insert((FROM, TO));
});
}

pub fn get_migration_bounds<T: PalletInfoAccess>() -> Option<(u16, u16)> {
MIGRATION_BOUNDS.with(|cell| cell.borrow().get(T::name()).copied())
}

pub fn save_state<T: PalletInfoAccess, const FROM: u16, const TO: u16>(s: Vec<u8>) {
MIGRATION_STATE
.with(|cell| cell.borrow_mut().entry(T::name()).or_default().insert((FROM, TO), s));
}

pub fn restore_state<T: PalletInfoAccess, const FROM: u16, const TO: u16>() -> Vec<u8> {
MIGRATION_STATE.with(|cell| {
cell.borrow()
.get(T::name())
.cloned()
.unwrap_or_default()
.get(&(FROM, TO))
.cloned()
.unwrap_or_default()
})
}
use frame_support::{pallet_prelude::ValueQuery, storage_alias, traits::PalletInfoAccess};
use sp_std::{
cmp::{max, min},
collections::btree_map::BTreeMap,
vec::Vec,
};

#[storage_alias]
pub type MigrationBounds =
StorageValue<CfUpgradeUtilities, BTreeMap<Vec<u8>, (u16, u16)>, ValueQuery>;

#[storage_alias]
pub type MigrationState = StorageValue<
CfUpgradeUtilities,
BTreeMap<Vec<u8>, BTreeMap<(u16, u16), Vec<u8>>>,
ValueQuery,
>;

pub fn update_migration_bounds<T: PalletInfoAccess, const FROM: u16, const TO: u16>() {
MigrationBounds::mutate(|bounds| {
bounds
.entry(T::name().as_bytes().to_vec())
.and_modify(|(from, to)| {
*from = min(*from, FROM);
*to = max(*to, TO);
})
.or_insert((FROM, TO));
});
}

#[cfg(not(feature = "std"))]
mod without_std {
use super::*;

pub fn update_migration_bounds<T: PalletInfoAccess, const FROM: u16, const TO: u16>() {
log::warn!("❗️ Runtime upgrade utilities are not supported in no-std.");
}

pub fn get_migration_bounds<T: PalletInfoAccess>() -> Option<(u16, u16)> {
Default::default()
}
pub fn get_migration_bounds<T: PalletInfoAccess>() -> Option<(u16, u16)> {
MigrationBounds::get().get(T::name().as_bytes()).copied()
}

pub fn save_state<T: PalletInfoAccess, const FROM: u16, const TO: u16>(s: Vec<u8>) {
log::warn!("❗️ Runtime upgrade utilities are not supported in no-std.");
}
pub fn save_state<T: PalletInfoAccess, const FROM: u16, const TO: u16>(s: Vec<u8>) {
MigrationState::mutate(|state| {
state.entry(T::name().as_bytes().to_vec()).or_default().insert((FROM, TO), s)
});
}

pub fn restore_state<T: PalletInfoAccess, const FROM: u16, const TO: u16>() -> Vec<u8> {
Default::default()
}
pub fn restore_state<T: PalletInfoAccess, const FROM: u16, const TO: u16>() -> Vec<u8> {
MigrationState::mutate(|state| {
state
.get(T::name().as_bytes())
.cloned()
.unwrap_or_default()
.get(&(FROM, TO))
.cloned()
.unwrap_or_default()
})
}
}

Expand Down
20 changes: 4 additions & 16 deletions state-chain/runtime/src/chainflip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use cf_chains::{
},
dot::{
api::PolkadotApi, Polkadot, PolkadotAccountId, PolkadotCrypto, PolkadotReplayProtection,
PolkadotTransactionData, RuntimeVersion,
PolkadotTransactionData, ResetProxyAccountNonce, RuntimeVersion,
},
eth::{
self,
Expand All @@ -47,7 +47,7 @@ use cf_traits::{
impl_runtime_safe_mode, AccountRoleRegistry, BlockEmissions, BroadcastAnyChainGovKey,
Broadcaster, Chainflip, CommKeyBroadcaster, DepositApi, DepositHandler, EgressApi, EpochInfo,
Heartbeat, Issuance, KeyProvider, OnBroadcastReady, QualifyNode, RewardsDistribution,
RuntimeUpgrade, VaultTransitionHandler,
RuntimeUpgrade,
};
use codec::{Decode, Encode};
use frame_support::{
Expand Down Expand Up @@ -323,10 +323,10 @@ pub struct DotEnvironment;
impl ReplayProtectionProvider<Polkadot> for DotEnvironment {
// Get the Environment values for vault_account, NetworkChoice and the next nonce for the
// proxy_account
fn replay_protection(_params: ()) -> PolkadotReplayProtection {
fn replay_protection(reset_nonce: ResetProxyAccountNonce) -> PolkadotReplayProtection {
PolkadotReplayProtection {
genesis_hash: Environment::polkadot_genesis_hash(),
nonce: Environment::next_polkadot_proxy_account_nonce(),
nonce: Environment::next_polkadot_proxy_account_nonce(reset_nonce),
}
}
}
Expand Down Expand Up @@ -369,18 +369,6 @@ impl ChainEnvironment<(), cf_chains::btc::AggKey> for BtcEnvironment {
}
}

pub struct EthVaultTransitionHandler;
impl VaultTransitionHandler<Ethereum> for EthVaultTransitionHandler {}

pub struct DotVaultTransitionHandler;
impl VaultTransitionHandler<Polkadot> for DotVaultTransitionHandler {
fn on_new_vault() {
Environment::reset_polkadot_proxy_account_nonce();
}
}
pub struct BtcVaultTransitionHandler;
impl VaultTransitionHandler<Bitcoin> for BtcVaultTransitionHandler {}

pub struct TokenholderGovernanceBroadcaster;

impl TokenholderGovernanceBroadcaster {
Expand Down
10 changes: 3 additions & 7 deletions state-chain/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,10 @@ pub use cf_traits::{EpochInfo, QualifyNode, SessionKeysRegistered, SwappingApi};
pub use chainflip::chain_instances::*;
use chainflip::{
epoch_transition::ChainflipEpochTransitions, BroadcastReadyProvider, BtcEnvironment,
BtcVaultTransitionHandler, ChainAddressConverter, ChainflipHeartbeat, EthEnvironment,
EthVaultTransitionHandler, TokenholderGovernanceBroadcaster,
ChainAddressConverter, ChainflipHeartbeat, EthEnvironment, TokenholderGovernanceBroadcaster,
};

use chainflip::{all_vaults_rotator::AllVaultRotator, DotEnvironment, DotVaultTransitionHandler};
use chainflip::{all_vaults_rotator::AllVaultRotator, DotEnvironment};
use constants::common::*;
use pallet_cf_flip::{Bonder, FlipSlasher};
use pallet_cf_vaults::Vault;
Expand Down Expand Up @@ -145,7 +144,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: create_runtime_str!("chainflip-node"),
impl_name: create_runtime_str!("chainflip-node"),
authoring_version: 1,
spec_version: 16,
spec_version: 20,
impl_version: 1,
apis: RUNTIME_API_VERSIONS,
transaction_version: 4,
Expand Down Expand Up @@ -230,7 +229,6 @@ impl pallet_cf_vaults::Config<EthereumInstance> for Runtime {
type Offence = chainflip::Offence;
type Chain = Ethereum;
type SetAggKeyWithAggKey = eth::api::EthereumApi<EthEnvironment>;
type VaultTransitionHandler = EthVaultTransitionHandler;
type Broadcaster = EthereumBroadcaster;
type OffenceReporter = Reputation;
type WeightInfo = pallet_cf_vaults::weights::PalletWeight<Runtime>;
Expand All @@ -248,7 +246,6 @@ impl pallet_cf_vaults::Config<PolkadotInstance> for Runtime {
type Offence = chainflip::Offence;
type Chain = Polkadot;
type SetAggKeyWithAggKey = dot::api::PolkadotApi<DotEnvironment>;
type VaultTransitionHandler = DotVaultTransitionHandler;
type Broadcaster = PolkadotBroadcaster;
type OffenceReporter = Reputation;
type WeightInfo = pallet_cf_vaults::weights::PalletWeight<Runtime>;
Expand All @@ -266,7 +263,6 @@ impl pallet_cf_vaults::Config<BitcoinInstance> for Runtime {
type Offence = chainflip::Offence;
type Chain = Bitcoin;
type SetAggKeyWithAggKey = cf_chains::btc::api::BitcoinApi<BtcEnvironment>;
type VaultTransitionHandler = BtcVaultTransitionHandler;
type Broadcaster = BitcoinBroadcaster;
type OffenceReporter = Reputation;
type WeightInfo = pallet_cf_vaults::weights::PalletWeight<Runtime>;
Expand Down
3 changes: 0 additions & 3 deletions state-chain/traits/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -738,9 +738,6 @@ impl<T: frame_system::Config> EgressApi<Polkadot> for T {
}
}

pub trait VaultTransitionHandler<C: Chain> {
fn on_new_vault() {}
}
pub trait VaultKeyWitnessedHandler<C: Chain> {
fn on_new_key_activated(block_number: C::ChainBlockNumber) -> DispatchResultWithPostInfo;
}
Expand Down
Loading