Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

try-runtime pre-post hooks not executed if defined within the pallet #13681

Closed
Tracked by #178
kianenigma opened this issue Mar 22, 2023 · 23 comments
Closed
Tracked by #178

try-runtime pre-post hooks not executed if defined within the pallet #13681

kianenigma opened this issue Mar 22, 2023 · 23 comments
Labels
T1-runtime This PR/Issue is related to the topic “runtime”. U1-asap No need to stop dead in your tracks, however issue should be addressed as soon as possible.

Comments

@kianenigma
Copy link
Contributor

we have been increasingly using external migrations and have seemingly introduced a regression in how we define migrations, namely pre-post migration hooks within a pallet. Here's the most simple way to reproduce this:

Apply this:

diff --git a/Cargo.lock b/Cargo.lock
index 29ddf38328..d3200668fd 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -6506,6 +6506,7 @@ dependencies = [
  "sp-core",
  "sp-io",
  "sp-runtime",
+ "sp-std",
 ]
 
 [[package]]
diff --git a/bin/node-template/pallets/template/Cargo.toml b/bin/node-template/pallets/template/Cargo.toml
index f6607b25c4..6db219734d 100644
--- a/bin/node-template/pallets/template/Cargo.toml
+++ b/bin/node-template/pallets/template/Cargo.toml
@@ -20,6 +20,7 @@ scale-info = { version = "2.1.1", default-features = false, features = ["derive"
 frame-benchmarking = { version = "4.0.0-dev", default-features = false, optional = true, path = "../../../../frame/benchmarking" }
 frame-support = { version = "4.0.0-dev", default-features = false, path = "../../../../frame/support" }
 frame-system = { version = "4.0.0-dev", default-features = false, path = "../../../../frame/system" }
+sp-std = { path = "../../../../primitives/std", default-features = false }
 
 [dev-dependencies]
 sp-core = { version = "7.0.0", path = "../../../../primitives/core" }
diff --git a/bin/node-template/pallets/template/src/lib.rs b/bin/node-template/pallets/template/src/lib.rs
index 4630e344ad..3b760e06d6 100644
--- a/bin/node-template/pallets/template/src/lib.rs
+++ b/bin/node-template/pallets/template/src/lib.rs
@@ -30,6 +30,25 @@ pub mod pallet {
 		type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
 	}
 
+	#[pallet::hooks]
+	impl<T: Config> Hooks<T::BlockNumber> for Pallet<T> {
+		fn on_runtime_upgrade() -> Weight {
+			Default::default()
+		}
+
+		#[cfg(feature = "try-runtime")]
+		fn pre_upgrade() -> Result<sp_std::prelude::Vec<u8>, &'static str> {
+			frame_support::log::info!(target: "pallet-template", "pre_upgrade");
+			Err("BOOOO")
+		}
+
+		#[cfg(feature = "try-runtime")]
+		fn post_upgrade(_state: sp_std::prelude::Vec<u8>) -> Result<(), &'static str> {
+			frame_support::log::info!(target: "pallet-template", "post_upgrade");
+			Ok(())
+		}
+	}
+
 	// The pallet's runtime storage items.
 	// https://docs.substrate.io/main-docs/build/runtime-storage/
 	#[pallet::storage]

Then:

# Run a base node: 
cargo remote run --  --release -p node-template -- --dev

# Build a try-runtime CLI and runtime 
cargo remote build --  --release --features try-runtime -p node-template
cargo remote build --  --release --features try-runtime -p node-template-runtime 

# Execute
RUST_LOG=pallet-template=trace,info ./target/release/node-template try-runtime --runtime ./target/release/wbuild/node-template-runtime/node_template_runtime.wasm on-runtime-upgrade live -u ws://localhost:9944

Logs won't be emitted, the error that I return in pre_upgrade is also not caught. Seems like the code is not really executed.

Initially tested against polkadot-9.38 branch. Probably present in master as well.

@kianenigma kianenigma added I3-bug The node fails to follow expected behavior. U1-asap No need to stop dead in your tracks, however issue should be addressed as soon as possible. labels Mar 22, 2023
@ggwpez
Copy link
Member

ggwpez commented Mar 22, 2023

Did you try with --checks? I think they are not run per default.

@ruseinov
Copy link
Contributor

ruseinov commented Mar 22, 2023

Did you try with --checks? I think they are not run per default.

Going to try that right now,
according to this PR the only thing we need to add is —checks without value.

@ruseinov
Copy link
Contributor

ruseinov commented Mar 22, 2023

Confirmed, this works on polkadot-v0.9.38 branch:

RUST_LOG=pallet-template=trace,info ./target/release/node-template try-runtime  --runtime ./target/release/wbuild/node-template-runtime/node_template_runtime.wasm on-runtime-upgrade --checks live -u ws://localhost:9944
2023-03-22 15:03:31.392  INFO main remote-ext: since no at is provided, setting it to latest finalized head, 0x85bad3a2ae7f67e151108e8f9bf7b095d87b93d3066837efeed8427883dd27cb
2023-03-22 15:03:31.392  INFO main remote-ext: since no prefix is filtered, the data for all pallets will be downloaded
2023-03-22 15:03:31.393  INFO main remote-ext: scraping key-pairs from remote at block height 0x85bad3a2ae7f67e151108e8f9bf7b095d87b93d3066837efeed8427883dd27cb
2023-03-22 15:03:31.394  INFO main remote-ext: Querying a total of 72 keys from prefix , splitting among 10 threads, 8 keys per thread
2023-03-22 15:03:31.404  INFO main remote-ext: adding data for hashed prefix: , took 0s
2023-03-22 15:03:31.404  INFO main remote-ext: adding data for hashed key: 3a636f6465
2023-03-22 15:03:31.407  INFO main remote-ext: adding data for hashed key: 26aa394eea5630e07c48ae0c9558cef7f9cce9c888469bb1a0dceaa129672ef8
2023-03-22 15:03:31.408  INFO main remote-ext: adding data for hashed key: 26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac
2023-03-22 15:03:31.408  INFO main remote-ext: initialized state externalities with storage root 0x75a96cbd51e73ff2319038cc925d17eafc119fe7bca5df187eb0b3885c27e9b8 and state_version V1
2023-03-22 15:03:31.422  INFO main try-runtime::cli: original spec: RuntimeString::Owned("node-template")-100, code hash: e9867166882f8cda2458ff62a521933d9e47f294ae94d6708e3695245bcd8a48
2023-03-22 15:03:31.432  INFO main try-runtime::cli: new spec: RuntimeString::Owned("node-template")-100, code hash: 1382010979e72649821f5ec6eb3c8db270587f0b908271f8f85b47adcbf8b2dc
2023-03-22 15:03:31.495  INFO main pallet-template: pre_upgrade
2023-03-22 15:03:31.495 ERROR main runtime: panicked at 'called `Result::unwrap()` on an `Err` value: "BOOOO"', .../substrate/bin/node-template/runtime/src/lib.rs:559:26

@crystalin
Copy link
Contributor

This makes sense, but that doesn't explain why in our case we can't get pre-runtime and post-runtime to work.
In our repo (Moonbeam), we have the migration defined as:

        #[pallet::hooks]
	impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
		fn on_runtime_upgrade() -> Weight {
			log::warn!("Performing on_runtime_upgrade !");
			T::BlockWeights::get().max_block
		}

		fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
			log::warn!("Performing pre_upgrade !");
			Ok(vec![])
		}

		fn post_upgrade(state: Vec<u8>) -> Result<(), &'static str> {
			log::warn!("Performing post_upgrade !");
			Ok(())
		}
	}

(the #[cfg(feature = "try-runtime")] is removed to ensure this is not due to some missing features)

Here is the output:

./target/release/moonbeam try-runtime --wasm-execution compiled  --detailed-log-output --runtime target/release/wbuild/moonbase-runtime/moonbase_runtime.wasm -lXcmV2ToV3=trace,runtime=trace on-runtime-upgrade --checks=all live --uri wss://wss.api.moonbase.moonbeam.network:443 --at 0x9039446d397077d081ca1e6b9a2e0cc78cd78002ff39bbb3a76b5ee2b21c0106 --pallet AssetManager
2023-03-22 20:56:52.914  INFO main remote-ext: scraping key-pairs from remote at block height 0x9039446d397077d081ca1e6b9a2e0cc78cd78002ff39bbb3a76b5ee2b21c0106
2023-03-22 20:56:52.950  INFO main remote-ext: Querying a total of 112 keys from prefix 4ae7e256f92e5888372d72f3e4db1003, splitting among 32 threads, 4 keys per thread
2023-03-22 20:56:53.156  INFO main remote-ext: adding data for hashed prefix: 4ae7e256f92e5888372d72f3e4db1003, took 0s
2023-03-22 20:56:53.156  INFO main remote-ext: adding data for hashed key: 3a636f6465
2023-03-22 20:56:53.308  INFO main remote-ext: adding data for hashed key: 26aa394eea5630e07c48ae0c9558cef7f9cce9c888469bb1a0dceaa129672ef8
2023-03-22 20:56:53.335  INFO main remote-ext: adding data for hashed key: 26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac
2023-03-22 20:56:53.358  INFO main remote-ext: initialized state externalities with storage root 0x2f6cb5ede9d784b168a968682426f377e96bc285b86e9457c4ff16b09cacc379 and state_version V0

2023-03-22 20:56:53.512  INFO main try-runtime::cli: original spec: RuntimeString::Owned("moonbase")-2201, code hash: 0d236e1cd0517b366bed534fcf7da586481e0f09e34eb50d1fcb2dd2cd9459ff
2023-03-22 20:56:53.587  INFO main try-runtime::cli: new spec: RuntimeString::Owned("moonbase")-2300, code hash: 50098ad8f04d650875d75c7d2352e0f3da63cd23891f69c0717dab9f5b9acc5c
2023-03-22 20:56:53.829  INFO main moonbase_runtime: try-runtime::on_runtime_upgrade()
2023-03-22 20:56:53.829  INFO main hooks: try_on_runtime_upgrade
2023-03-22 20:56:53.829  INFO main hooks: pre_upgrade
2023-03-22 20:56:53.829 DEBUG main runtime::frame-support: ✅ no migration for System
2023-03-22 20:56:53.829 DEBUG main runtime::frame-support: ✅ no migration for Utility
2023-03-22 20:56:53.829 DEBUG main runtime::frame-support: ✅ no migration for Timestamp
2023-03-22 20:56:53.829 DEBUG main runtime::frame-support: ✅ no migration for Balances
2023-03-22 20:56:53.829 DEBUG main runtime::frame-support: ✅ no migration for Sudo
2023-03-22 20:56:53.829  INFO main runtime::frame-support: ⚠️ ParachainSystem declares internal migrations (which *might* execute). On-chain `StorageVersion(0)` vs current storage version `StorageVersion(2)`
2023-03-22 20:56:53.829 DEBUG main runtime::frame-support: ✅ no migration for TransactionPayment
2023-03-22 20:56:53.829 DEBUG main runtime::frame-support: ✅ no migration for ParachainInfo
2023-03-22 20:56:53.829 DEBUG main runtime::frame-support: ✅ no migration for EthereumChainId
2023-03-22 20:56:53.829 DEBUG main runtime::frame-support: ✅ no migration for EVM
2023-03-22 20:56:53.829  INFO main runtime::frame-support: ⚠️ Ethereum declares internal migrations (which *might* execute). On-chain `StorageVersion(0)` vs current storage version `StorageVersion(0)`
2023-03-22 20:56:53.829 DEBUG main runtime::frame-support: ✅ no migration for ParachainStaking
2023-03-22 20:56:53.829 DEBUG main runtime::frame-support: ✅ no migration for Scheduler
2023-03-22 20:56:53.829 DEBUG main runtime::frame-support: ✅ no migration for Democracy
2023-03-22 20:56:53.829 DEBUG main runtime::frame-support: ✅ no migration for CouncilCollective
2023-03-22 20:56:53.829 DEBUG main runtime::frame-support: ✅ no migration for TechCommitteeCollective
2023-03-22 20:56:53.829 DEBUG main runtime::frame-support: ✅ no migration for Treasury
2023-03-22 20:56:53.829 DEBUG main runtime::frame-support: ✅ no migration for AuthorInherent
2023-03-22 20:56:53.829 DEBUG main runtime::frame-support: ✅ no migration for AuthorFilter
2023-03-22 20:56:53.829 DEBUG main runtime::frame-support: ✅ no migration for CrowdloanRewards
2023-03-22 20:56:53.829 DEBUG main runtime::frame-support: ✅ no migration for AuthorMapping
2023-03-22 20:56:53.829 DEBUG main runtime::frame-support: ✅ no migration for Proxy
2023-03-22 20:56:53.829 DEBUG main runtime::frame-support: ✅ no migration for MaintenanceMode
2023-03-22 20:56:53.829 DEBUG main runtime::frame-support: ✅ no migration for Identity
2023-03-22 20:56:53.829  INFO main runtime::frame-support: ⚠️ XcmpQueue declares internal migrations (which *might* execute). On-chain `StorageVersion(0)` vs current storage version `StorageVersion(2)`
2023-03-22 20:56:53.829 DEBUG main runtime::frame-support: ✅ no migration for CumulusXcm
2023-03-22 20:56:53.829  INFO main runtime::frame-support: ⚠️ DmpQueue declares internal migrations (which *might* execute). On-chain `StorageVersion(0)` vs current storage version `StorageVersion(1)`
2023-03-22 20:56:53.829  INFO main runtime::frame-support: ⚠️ PolkadotXcm declares internal migrations (which *might* execute). On-chain `StorageVersion(0)` vs current storage version `StorageVersion(1)`
2023-03-22 20:56:53.829 DEBUG main runtime::frame-support: ✅ no migration for Assets
2023-03-22 20:56:53.829 DEBUG main runtime::frame-support: ✅ no migration for XTokens
2023-03-22 20:56:53.829 DEBUG main runtime::frame-support: ✅ no migration for AssetManager
2023-03-22 20:56:53.830  INFO main runtime::frame-support: ⚠️ Migrations declares internal migrations (which *might* execute). On-chain `StorageVersion(0)` vs current storage version `StorageVersion(0)`
2023-03-22 20:56:53.830  WARN main pallet_migrations::pallet: Performing on_runtime_upgrade !
2023-03-22 20:56:53.830 DEBUG main runtime::frame-support: ✅ no migration for XcmTransactor
2023-03-22 20:56:53.830 DEBUG main runtime::frame-support: ✅ no migration for ProxyGenesisCompanion
2023-03-22 20:56:53.830 DEBUG main runtime::frame-support: ✅ no migration for LocalAssets
2023-03-22 20:56:53.830 DEBUG main runtime::frame-support: ✅ no migration for MoonbeamOrbiters
2023-03-22 20:56:53.830 DEBUG main runtime::frame-support: ✅ no migration for EthereumXcm
2023-03-22 20:56:53.830 DEBUG main runtime::frame-support: ✅ no migration for Randomness
2023-03-22 20:56:53.830 DEBUG main runtime::frame-support: ✅ no migration for TreasuryCouncilCollective
2023-03-22 20:56:53.830 DEBUG main runtime::frame-support: ✅ no migration for ConvictionVoting
2023-03-22 20:56:53.830 DEBUG main runtime::frame-support: ✅ no migration for Referenda
2023-03-22 20:56:53.830 DEBUG main runtime::frame-support: ✅ no migration for Origins
2023-03-22 20:56:53.830 DEBUG main runtime::frame-support: ✅ no migration for Preimage
2023-03-22 20:56:53.830 DEBUG main runtime::frame-support: ✅ no migration for Whitelist
2023-03-22 20:56:53.830 DEBUG main runtime::frame-support: ✅ no migration for OpenTechCommitteeCollective
2023-03-22 20:56:53.830 DEBUG main runtime::frame-support: ✅ no migration for RootTesting
2023-03-22 20:56:53.830 DEBUG main runtime::frame-support: ✅ no migration for Erc20XcmBridge
2023-03-22 20:56:53.848  INFO main hooks: post_upgrade
2023-03-22 20:56:53.889  INFO main try-runtime::cli: TryRuntime_on_runtime_upgrade executed without errors. Consumed weight = (501275000000 ps, 5242880 byte), total weight = (500000000000 ps, 5242880 byte) (100.26 %, 100.00 %).

(I also added logs in the https://github.com/paritytech/substrate/blob/master/frame/support/src/traits/hooks.rs#L170 for try_on_runtime_upgrade, pre_upgrade and post_upgrade, which all appear in the logs with target:"hooks" )

@ggwpez
Copy link
Member

ggwpez commented Mar 22, 2023

Could you give us a commit hash to try this please @crystalin ?

@crystalin
Copy link
Contributor

Here is the branch https://github.com/PureStake/moonbeam/tree/crystalin-broken-try-runtime

cargo build --release
./target/release/moonbeam try-runtime --wasm-execution compiled  --detailed-log-output --runtime target/release/wbuild/moonbase-runtime/moonbase_runtime.wasm -lXcmV2ToV3=trace,runtime=trace on-runtime-upgrade --checks=all live --uri wss://wss.api.moonbase.moonbeam.network:443 --at 0x9039446d397077d081ca1e6b9a2e0cc78cd78002ff39bbb3a76b5ee2b21c0106 --pallet AssetManager

@crystalin
Copy link
Contributor

Not directly related, but I opened #13692 as the interpreted execution is not easy to debug

@librelois
Copy link
Contributor

librelois commented Mar 23, 2023

I think that was break by #12537, this PR removed the pre/post_upgrade impl for tuples: https://github.com/paritytech/substrate/pull/12537/files#diff-1c449417be9803cb427eed15d51557931141d47d0047561407f1651d319f7103L205

And frame executive use a tuple:

<(COnRuntimeUpgrade, AllPalletsWithSystem) as OnRuntimeUpgrade>::try_on_runtime_upgrade(...)

@crystalin
Copy link
Contributor

crystalin commented Mar 23, 2023

I confirm @kianenigma ,
Adding to https://github.com/paritytech/substrate/blob/master/frame/support/src/traits/hooks.rs#L193

	
	#[cfg(feature = "try-runtime")]
	fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
		for_tuples!( #( Tuple::pre_upgrade()?; )* );
		Ok(vec![])
	}

	#[cfg(feature = "try-runtime")]
	fn post_upgrade(_state: Vec<u8>) -> Result<(), &'static str> {
		for_tuples!( #( Tuple::post_upgrade(vec![])?; )*  );
		Ok(())
	}

makes the pre_upgrade and post_upgrade work

@ggwpez
Copy link
Member

ggwpez commented Mar 24, 2023

How do you diener moonbeam? I want to try it, since I cant reproduce it directly in the substrate kitchensink runtime.
diener patch --crates-to-patch ../substrate --substrate does not make a difference.

@crystalin
Copy link
Contributor

I don't know what diener is. Maybe @librelois can help here

@ggwpez
Copy link
Member

ggwpez commented Mar 24, 2023

How do you build moonbeam with a patched Substrate version? Diener can be used to patch Polkadot and Cumulus to local clones.

@crystalin
Copy link
Contributor

edit the .cargo/config.toml and add
paths=["../substrate"]

In our case we use a fork of substrate https://github.com/purestake/substrate/tree/moonbeam-polkadot-v0.9.38

@kianenigma
Copy link
Contributor Author

I am a bit confused by the current implementation that I have put there, it is a bit hard to argue about it -- looking further, but for now not easy to replicate a failing test:

diff --git a/frame/support/src/lib.rs b/frame/support/src/lib.rs
index 4e9bc32b00..5e8cb9b4d4 100644
--- a/frame/support/src/lib.rs
+++ b/frame/support/src/lib.rs
@@ -371,16 +371,14 @@ macro_rules! parameter_types {
 
 			/// Set the value of this parameter type in the storage.
 			///
-			/// This needs to be executed in an externalities provided
-			/// environment.
+			/// This needs to be executed in an externalities provided environment.
 			pub fn set(value: &$type) {
 				$crate::storage::unhashed::put(&Self::key(), value);
 			}
 
 			/// Returns the value of this parameter type.
 			///
-			/// This needs to be executed in an externalities provided
-			/// environment.
+			/// This needs to be executed in an externalities provided environment.
 			#[allow(unused)]
 			pub fn get() -> $type {
 				$crate::storage::unhashed::get(&Self::key()).unwrap_or_else(|| $value)
diff --git a/frame/support/src/traits/hooks.rs b/frame/support/src/traits/hooks.rs
index a3374d0bf5..592d9733aa 100644
--- a/frame/support/src/traits/hooks.rs
+++ b/frame/support/src/traits/hooks.rs
@@ -197,10 +197,10 @@ impl OnRuntimeUpgrade for Tuple {
 		weight
 	}
 
-	#[cfg(feature = "try-runtime")]
 	/// We are executing pre- and post-checks sequentially in order to be able to test several
 	/// consecutive migrations for the same pallet without errors. Therefore pre and post upgrade
 	/// hooks for tuples are a noop.
+	#[cfg(feature = "try-runtime")]
 	fn try_on_runtime_upgrade(checks: bool) -> Result<Weight, &'static str> {
 		let mut weight = Weight::zero();
 		for_tuples!( #( weight = weight.saturating_add(Tuple::try_on_runtime_upgrade(checks)?); )* );
@@ -359,10 +359,64 @@ pub trait OnTimestampSet<Moment> {
 #[cfg(test)]
 mod tests {
 	use super::*;
+	use sp_io::TestExternalities;
+
+	#[test]
+	fn on_runtime_upgrade_pre_post_exeucted_tuple() {
+		crate::parameter_types! {
+			pub static Pre: Vec<&'static str> = Default::default();
+			pub static Post: Vec<&'static str> = Default::default();
+		}
+
+		macro_rules! impl_test_type {
+			($name:ident) => {
+				struct $name;
+				impl OnRuntimeUpgrade for $name {
+					fn on_runtime_upgrade() -> Weight {
+						Default::default()
+					}
+
+					#[cfg(feature = "try-runtime")]
+					fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
+						Pre::mutate(|s| s.push(stringify!($name)));
+						Ok(Vec::new())
+					}
+
+					#[cfg(feature = "try-runtime")]
+					fn post_upgrade(_: Vec<u8>) -> Result<(), &'static str> {
+						Post::mutate(|s| s.push(stringify!($name)));
+						Ok(())
+					}
+				}
+			};
+		}
+
+		impl_test_type!(Foo);
+		impl_test_type!(Bar);
+		impl_test_type!(Baz);
+
+		TestExternalities::default().execute_with(|| {
+			Foo::try_on_runtime_upgrade(true).unwrap();
+			// todo unify the API for storage parameter_types! output.
+			assert_eq!(Pre::take(), vec!["Foo"]);
+			assert_eq!(Post::take(), vec!["Foo"]);
+
+			<(Foo, Bar, Baz)>::try_on_runtime_upgrade(true).unwrap();
+			assert_eq!(Pre::take(), vec!["Foo", "Bar", "Baz"]);
+			assert_eq!(Post::take(), vec!["Foo", "Bar", "Baz"]);
+
+			<((Foo, Bar), Baz)>::try_on_runtime_upgrade(true).unwrap();
+			assert_eq!(Pre::take(), vec!["Foo", "Bar", "Baz"]);
+			assert_eq!(Post::take(), vec!["Foo", "Bar", "Baz"]);
+
+			<(Foo, (Bar, Baz))>::try_on_runtime_upgrade(true).unwrap();
+			assert_eq!(Pre::take(), vec!["Foo", "Bar", "Baz"]);
+			assert_eq!(Post::take(), vec!["Foo", "Bar", "Baz"]);
+		});
+	}
 
 	#[test]
 	fn on_initialize_and_on_runtime_upgrade_weight_merge_works() {
-		use sp_io::TestExternalities;
 		struct Test;
 
 		impl OnInitialize<u8> for Test {

@crystalin
Copy link
Contributor

@kianenigma is there something else we can do to help ? @librelois identified the part (the for_tuples) that is failing for us, but I don't know actually how it works and why it fixes it. Elois can help if you need

@tgmichel
Copy link
Contributor

To follow up a bit on a temporary solution, I managed to run both pre and post upgrade tests by expanding what @crystalin suggested:

Add the following to

impl OnRuntimeUpgrade for Tuple {

#[cfg(feature = "try-runtime")]
fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
	let mut state: Vec<Vec<u8>> = Vec::default();
	for_tuples!( #( state.push(Tuple::pre_upgrade()?); )* );
	Ok(state.encode())
}

#[cfg(feature = "try-runtime")]
fn post_upgrade(state: Vec<u8>) -> Result<(), &'static str> {
	let state: Vec<Vec<u8>> = Decode::decode(&mut state.as_slice())
		.expect("the state parameter should be the same as pre_upgrade generated");
	let mut state_iter = state.into_iter();
	for_tuples!( #( Tuple::post_upgrade(
		state_iter.next().expect("the state parameter should be the same as pre_upgrade generated")
	)?; )* );
	Ok(())
} 

Which is essentially adding back what was removed in #12319

@liamaharon
Copy link
Contributor

liamaharon commented Mar 30, 2023

edit the .cargo/config.toml and add paths=["../substrate"]

In our case we use a fork of substrate https://github.com/purestake/substrate/tree/moonbeam-polkadot-v0.9.38

Hey @crystalin, I wasn't able to get this to work (it seems paths only works for crates published to crates.io?).

Screenshot 2023-03-30 at 18 07 16

I was able to get a little closer checking out my local substrate to https://github.com/purestake/substrate/tree/moonbeam-polkadot-v0.9.38, running diener, and modifying the output to use your repo path, but bumped up against a compile error.

Could you please elaborate how to get this working with a local/patched Substrate? I'm unable to reproduce this using polkadot or substrate-node-template, so need to get a local moonbeam dev env set up to investigate further.

@juangirini juangirini added the T1-runtime This PR/Issue is related to the topic “runtime”. label Jun 7, 2023
@kianenigma
Copy link
Contributor Author

I wonder if this actually got solved or not? perhaps this is still some bug in how try_runtime_upgrade is applied to pallets?

This is all to some extent a consequence of the fact that we use OnRuntimeUpgrade directly in executive, and in pallets.

In Parity Ops, we 99% use the former, so we rarely test the latter. Ideally, some integration tests should mimic a combination of the two.

@crystalin
Copy link
Contributor

I confirm it is still NOT working in v0.9.43

@liamaharon
Copy link
Contributor

I confirm it is still NOT working in v0.9.43

Hey @crystalin this is on my list of things to look into. Do you have a branch I can reproduce that uses v0.9.43?

@liamaharon
Copy link
Contributor

liamaharon commented Aug 14, 2023

This bug is due to Moonbeem using an old version of the Executive pallet.

Moonbeam's Executive try_runtime_upgrade method (https://github.com/moonbeam-foundation/substrate/blob/95067ccc3a7683768f8a10036785cde8d5f8a098/frame/executive/src/lib.rs#L261-L272) needs to be updated to call try_on_runtime_upgrade instead of pre_upgarde and post_upgrade directly, like the current Executive:

/// Execute all `OnRuntimeUpgrade` of this runtime, including the pre and post migration checks.
///
/// Runs the try-state code both before and after the migration function if `checks` is set to
/// `true`. Also, if set to `true`, it runs the `pre_upgrade` and `post_upgrade` hooks.
pub fn try_runtime_upgrade(
checks: frame_try_runtime::UpgradeCheckSelect,
) -> Result<Weight, TryRuntimeError> {
if checks.try_state() {
let _guard = frame_support::StorageNoopGuard::default();
<AllPalletsWithSystem as frame_support::traits::TryState<
BlockNumberFor<System>,
>>::try_state(
frame_system::Pallet::<System>::block_number(),
frame_try_runtime::TryStateSelect::All,
)?;
}
let weight =
<(COnRuntimeUpgrade, AllPalletsWithSystem) as OnRuntimeUpgrade>::try_on_runtime_upgrade(
checks.pre_and_post(),
)?;
if checks.try_state() {
let _guard = frame_support::StorageNoopGuard::default();
<AllPalletsWithSystem as frame_support::traits::TryState<
BlockNumberFor<System>,
>>::try_state(
frame_system::Pallet::<System>::block_number(),
frame_try_runtime::TryStateSelect::All,
)?;
}
Ok(weight)
}
}

To prevent this silent failure again I'm going to implement Tuples for pre_upgrade and post_upgrade but just make it log an error prompting users to call try_on_runtime_upgrade instead.

@liamaharon liamaharon removed the I3-bug The node fails to follow expected behavior. label Aug 14, 2023
@crystalin
Copy link
Contributor

@liamaharon you are looking at a commit that is from April 2022 (more than a year late).
We are using 0.9.43 at the moment (and were using 0.9.40 at the time of the bug being reported IIRC), which included the change to try_on_runtime_upgrade :
https://github.com/moonbeam-foundation/substrate/blob/moonbeam-polkadot-v0.9.40/frame/executive/src/lib.rs#L348

@liamaharon
Copy link
Contributor

I suspect your runtime is still trying to call the Tuples impl of pre_upgrade and post_upgrade because @tgmichel mentioned restoring their functionality fixed the issue #13681 (comment).

Can you add some logging into your Executive and try_on_runtime_upgrade tuples implementation to verify?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
T1-runtime This PR/Issue is related to the topic “runtime”. U1-asap No need to stop dead in your tracks, however issue should be addressed as soon as possible.
Projects
Status: Done
Development

No branches or pull requests

8 participants