Skip to content

Commit

Permalink
feat: vault release migration
Browse files Browse the repository at this point in the history
  • Loading branch information
daniel-savu committed Jul 25, 2022
1 parent 362f524 commit 2c5710e
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 26 deletions.
54 changes: 43 additions & 11 deletions crates/vault-registry/src/lib.rs
Expand Up @@ -45,7 +45,9 @@ use frame_support::{
dispatch::{DispatchError, DispatchResult},
ensure,
traits::Get,
transactional, PalletId,
transactional,
weights::Weight,
PalletId,
};
use frame_system::{
ensure_signed,
Expand Down Expand Up @@ -131,6 +133,10 @@ pub mod pallet {
log::info!("Off-chain worker started on block {:?}", n);
Self::_offchain_worker();
}

fn on_runtime_upgrade() -> Weight {
crate::types::upgrade_vault_release::try_upgrade_current_vault_release::<T>()
}
}

#[pallet::validate_unsigned]
Expand Down Expand Up @@ -418,18 +424,34 @@ pub mod pallet {
Ok(())
}

/// Changes the collateral liquidation threshold for a currency (only executable by the Root account)
/// Sets the current client release version, in case of a bug fix or patch.
///
/// # Arguments
/// * `version` - the semver version, where the zero-index element is the major version
/// * `checksum` - the SHA256 checksum of the client binary
#[pallet::weight(<T as Config>::WeightInfo::set_liquidation_collateral_threshold())]
#[transactional]
pub fn set_current_client_release(origin: OriginFor<T>, uri: Vec<u8>, code_hash: T::Hash) -> DispatchResult {
ensure_root(origin)?;
let release = ClientRelease { uri, code_hash };
CurrentClientRelease::<T>::put(release.clone());
Self::deposit_event(Event::<T>::ApplyClientRelease { release });
Ok(())
}

/// Sets the pending client release version. To be batched alongside the
/// `parachainSystem.enactAuthorizedUpgrade` relay chain xcm call.
///
/// # Arguments
/// * `version` - the semver version, where the zero-index element is the major version
/// * `checksum` - the SHA256 checksum of the client binary
#[pallet::weight(<T as Config>::WeightInfo::set_liquidation_collateral_threshold())]
#[transactional]
pub fn set_client_release(origin: OriginFor<T>, version: [u32; 3], checksum: [u8; 32]) -> DispatchResult {
pub fn set_pending_client_release(origin: OriginFor<T>, uri: Vec<u8>, code_hash: T::Hash) -> DispatchResult {
ensure_root(origin)?;
// TODO: Should the new semver version have a check that ensures it is striclty ascending?
LatestClientRelease::<T>::put(ClientRelease { version, checksum });
Self::deposit_event(Event::<T>::ClientRelease { version, checksum });
let release = ClientRelease { uri, code_hash };
PendingClientRelease::<T>::put(Some(release.clone()));
Self::deposit_event(Event::<T>::NotifyClientRelease { release });
Ok(())
}
}
Expand Down Expand Up @@ -543,9 +565,11 @@ pub mod pallet {
vault_id: DefaultVaultId<T>,
banned_until: T::BlockNumber,
},
ClientRelease {
version: [u32; 3],
checksum: [u8; 32],
NotifyClientRelease {
release: ClientRelease<T::Hash>,
},
ApplyClientRelease {
release: ClientRelease<T::Hash>,
},
}

Expand Down Expand Up @@ -673,8 +697,14 @@ pub mod pallet {
/// Tuple of (semver_version, sha256_checksum) indicating the latest vault client release.
/// `semver_version`: The element at index zero is the major semver version.
#[pallet::storage]
#[pallet::getter(fn latest_client_release)]
pub(super) type LatestClientRelease<T: Config> = StorageValue<_, ClientRelease, ValueQuery>;
#[pallet::getter(fn current_client_release)]
pub(super) type CurrentClientRelease<T: Config> = StorageValue<_, ClientRelease<T::Hash>, ValueQuery>;

/// Tuple of (semver_version, sha256_checksum) indicating the latest vault client release.
/// `semver_version`: The element at index zero is the major semver version.
#[pallet::storage]
#[pallet::getter(fn pending_client_release)]
pub(super) type PendingClientRelease<T: Config> = StorageValue<_, Option<ClientRelease<T::Hash>>, ValueQuery>;

#[pallet::type_value]
pub(super) fn DefaultForStorageVersion() -> Version {
Expand Down Expand Up @@ -730,6 +760,8 @@ pub mod pallet {
LiquidationCollateralThreshold::<T>::insert(currency_pair, threshold);
}
StorageVersion::<T>::put(Version::V3);
let no_release: Option<ClientRelease<T::Hash>> = None;
PendingClientRelease::<T>::put(no_release);
}
}
}
Expand Down
92 changes: 87 additions & 5 deletions crates/vault-registry/src/types.rs
Expand Up @@ -11,7 +11,7 @@ pub use primitives::{VaultCurrencyPair, VaultId};
use scale_info::TypeInfo;
use sp_core::H256;
use sp_runtime::traits::{CheckedAdd, CheckedSub, Zero};
use sp_std::collections::btree_set::BTreeSet;
use sp_std::{collections::btree_set::BTreeSet, vec::Vec};

#[cfg(test)]
use mocktopus::macros::mockable;
Expand All @@ -33,12 +33,12 @@ pub enum Version {
V4,
}

#[derive(Encode, Decode, Default, TypeInfo, Eq, PartialEq, Debug)]
pub struct ClientRelease {
#[derive(Encode, Decode, Eq, PartialEq, Clone, Default, TypeInfo, Debug)]
pub struct ClientRelease<Hash> {
/// The semver version, where the zero-index element is the major version
pub version: [u32; 3],
pub uri: Vec<u8>,
/// SHA256 checksum of the client binary
pub checksum: [u8; 32],
pub code_hash: Hash,
}

#[derive(Debug, PartialEq)]
Expand Down Expand Up @@ -114,6 +114,88 @@ pub type DefaultVaultId<T> = VaultId<<T as frame_system::Config>::AccountId, Cur

pub type DefaultVaultCurrencyPair<T> = VaultCurrencyPair<CurrencyId<T>>;

pub mod upgrade_vault_release {

use super::*;
use frame_support::weights::Weight;

/// If a pending client release exists, set the current release to that.
/// The pending release becomes `None`.
pub fn try_upgrade_current_vault_release<T: Config>() -> Weight {
let mut writes: Weight = if let Some(pending_release) = Pallet::<T>::pending_client_release() {
log::info!("Upgrading current vault release.");
crate::CurrentClientRelease::<T>::put(pending_release);
let no_release: Option<ClientRelease<T::Hash>> = None;
crate::PendingClientRelease::<T>::put(no_release);
2
} else {
log::info!("No pending vault release, skipping migration.");
0
};
T::DbWeight::get().reads_writes(1, writes)
}

#[cfg(test)]
#[test]
fn test_vault_release_migration_is_skipped() {
use crate::mock::Test;

crate::mock::run_test(|| {
let pre_migration_pending_release = None;
crate::PendingClientRelease::<Test>::put(pre_migration_pending_release.clone());

let pre_migration_current_release = ClientRelease {
uri: b"https://github.com/interlay/interbtc-clients/releases/download/1.15.0/vault-standalone-metadata"
.to_vec(),
code_hash: H256::default(),
};
crate::CurrentClientRelease::<Test>::put(pre_migration_current_release.clone());

try_upgrade_current_vault_release::<Test>();

assert_eq!(
crate::PendingClientRelease::<Test>::get(),
pre_migration_pending_release
);
assert_eq!(
crate::CurrentClientRelease::<Test>::get(),
pre_migration_current_release
);
});
}

#[cfg(test)]
#[test]
fn test_vault_release_migration_executes() {
use crate::mock::Test;

crate::mock::run_test(|| {
let pre_migration_pending_release = ClientRelease {
uri: b"https://github.com/interlay/interbtc-clients/releases/download/1.14.0/vault-standalone-metadata"
.to_vec(),
code_hash: H256::default(),
};
crate::PendingClientRelease::<Test>::put(Some(pre_migration_pending_release.clone()));

let pre_migration_current_release = ClientRelease {
uri: b"https://github.com/interlay/interbtc-clients/releases/download/1.15.0/vault-standalone-metadata"
.to_vec(),
code_hash: H256::default(),
};
crate::CurrentClientRelease::<Test>::put(pre_migration_current_release.clone());

try_upgrade_current_vault_release::<Test>();

let no_release: Option<ClientRelease<H256>> = None;
assert_eq!(crate::PendingClientRelease::<Test>::get(), no_release);
assert_eq!(
crate::CurrentClientRelease::<Test>::get(),
pre_migration_pending_release
);
});
}
}

pub mod liquidation_vault_fix {
use super::*;
use primitives::{
Expand Down
1 change: 0 additions & 1 deletion parachain/runtime/interlay/src/lib.rs
Expand Up @@ -461,7 +461,6 @@ impl frame_support::traits::OnRuntimeUpgrade for SchedulerMigrationV3 {
fn pre_upgrade() -> Result<(), &'static str> {
Scheduler::pre_migrate_to_v3()
}

#[cfg(feature = "try-runtime")]
fn post_upgrade() -> Result<(), &'static str> {
Scheduler::post_migrate_to_v3()
Expand Down
5 changes: 3 additions & 2 deletions parachain/runtime/kintsugi/src/lib.rs
Expand Up @@ -381,11 +381,12 @@ mod migrate_aura {
pub struct AuraMigration;
impl frame_support::traits::OnRuntimeUpgrade for AuraMigration {
fn on_runtime_upgrade() -> frame_support::weights::Weight {
if migrate_aura::should_run_upgrade() {
let aura_migration = if migrate_aura::should_run_upgrade() {
migrate_aura::on_runtime_upgrade()
} else {
Default::default()
}
};
aura_migration
}

#[cfg(feature = "try-runtime")]
Expand Down
32 changes: 25 additions & 7 deletions standalone/runtime/tests/test_vault_registry.rs
Expand Up @@ -231,18 +231,36 @@ mod withdraw_collateral_test {
}

#[test]
fn integration_test_vault_registry_set_client_release_works() {
fn integration_test_vault_registry_set_current_client_release_works() {
test_with(|_vault_id| {
let new_release = ClientRelease {
version: [1, 0, 2],
checksum: [1u8; 32],
uri: b"https://github.com/interlay/interbtc-clients/releases/download/1.14.0/vault-standalone-metadata"
.to_vec(),
code_hash: H256::default(),
};
assert_ok!(Call::VaultRegistry(VaultRegistryCall::set_client_release {
version: new_release.version,
checksum: new_release.checksum
assert_ok!(Call::VaultRegistry(VaultRegistryCall::set_current_client_release {
uri: new_release.uri.clone(),
code_hash: new_release.code_hash.clone()
})
.dispatch(root()));
assert_eq!(VaultRegistryPallet::latest_client_release(), new_release);
assert_eq!(VaultRegistryPallet::current_client_release(), new_release);
});
}

#[test]
fn integration_test_vault_registry_set_pending_client_release_works() {
test_with(|_vault_id| {
let new_release = ClientRelease {
uri: b"https://github.com/interlay/interbtc-clients/releases/download/1.15.0/vault-standalone-metadata"
.to_vec(),
code_hash: H256::default(),
};
assert_ok!(Call::VaultRegistry(VaultRegistryCall::set_pending_client_release {
uri: new_release.uri.clone(),
code_hash: new_release.code_hash.clone()
})
.dispatch(root()));
assert_eq!(VaultRegistryPallet::pending_client_release(), Some(new_release));
});
}
}
Expand Down

0 comments on commit 2c5710e

Please sign in to comment.