Skip to content

Latest commit

 

History

History
170 lines (143 loc) · 2.92 KB

File metadata and controls

170 lines (143 loc) · 2.92 KB

References

Docs:

Video

Some built-in functions

  • on_initialize, trait: OnInitialize
  • on_finalize, trait: OnFinalize
  • offchain_worker
  • on_runtime_upgrade, trait: OnRuntimeUpgrade

Example

original storages

#[derive(Encode, Decode, Clone, Debug, PartialEq)]
pub enum Version {
	V0,
	V1,
	V2,
}

impl Default for Version {
	fn default() -> Self {
		Self::V1
	}
}

#[derive(Encode, Decode, Clone, Debug, Default)]
pub struct Foo {
	a: u32
}

decl_storage! {
	trait Store for Module<T: Trait> as Migration {
		pub FooStorage: map hasher(blake2_128_concat) T::AccountId => Foo;
		pub StorageVersion: Version = Version::V0;
	}
}

New storages

There're some data types added and changed.

#[derive(Encode, Decode, Clone, Debug, PartialEq)]
pub enum Status {
	Open,
	Close,
	Unknown,
}

impl Default for Status {
	fn default() -> Self {
		Self::Close
	}
}

#[derive(Encode, Decode, Clone, Debug, Default)]
pub struct Foo {
	a: u64,
	b: Status,
}

// but no storage changes.
decl_storage! {
	trait Store for Module<T: Trait> as Migration {
		pub FooStorage: map hasher(blake2_128_concat) T::AccountId => Foo;
		pub StorageVersion: Version = Version::V0;
	}
}

How to migrate

Use module to include the deprecated data type

pub mod storage_migration {
	use crate::{Trait};
	use codec::{Decode, Encode};
	use frame_support::{weights::Weight, decl_module, decl_storage, IterableStorageMap, StorageValue};

	#[derive(Encode, Decode, Clone, Debug, Default)]
	pub struct Foo {
		a: u32,
	}

	decl_storage! {
		trait Store for Module<T: Trait> as Assets {
			pub FooStorage: map hasher(blake2_128_concat) T::AccountId => Foo;
		}
	}

	decl_module! {
		pub struct Module<T: Trait> for enum Call where origin: T::Origin {}
	}

	pub fn migration_to_new_foo<T: Trait>() -> Weight {
		if crate::StorageVersion::get() == crate::Version::V0 {
		    // take all old storages from previous state
			for (who, old_val) in FooStorage::<T>::drain() {
				let new_val = crate::Foo {
					a: old_val.a as u64,
					b: crate::Status::Open
				};

				crate::FooStorage::<T>::insert(who, new_val);
				crate::StorageVersion::put(crate::Version::V1);
			}

			1000
		} else {
			0
		}
	}
}

decl_module! {
    // ...
    
    fn on_runtime_upgrade() -> Weight {
    	storage_migration::migration_to_new_foo::<T>()
    }
    
    // ...
}

Demonstration

Remember to update type definition to front-end.

  • Old types
"Foo": {
    "a": "u32"
},
"Version": {
    "_enum": [
      "V0",
      "V1",
      "V2"
    ]
}
  • New types
"Foo": {
    "a": "u64",
    "b": "Status"
},
"Version": {
    "_enum": [
      "V0",
      "V1",
      "V2"
    ]
},
"Status": {
    "_enum": [
      "Open",
      "Close",
      "Unknown"
    ]
}