mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 14:01:02 +00:00
Fix historical validation code runtime API (#3187)
* remove some 'allow(unused)' * fix historical validation code runtime API
This commit is contained in:
committed by
GitHub
parent
9c014f7c8b
commit
a87df9d854
@@ -84,8 +84,8 @@ pub struct ParaPastCodeMeta<N> {
|
|||||||
/// pruning on an accurate timeframe. These can be used as indices
|
/// pruning on an accurate timeframe. These can be used as indices
|
||||||
/// into the `PastCodeHash` map along with the `ParaId` to fetch the code itself.
|
/// into the `PastCodeHash` map along with the `ParaId` to fetch the code itself.
|
||||||
upgrade_times: Vec<ReplacementTimes<N>>,
|
upgrade_times: Vec<ReplacementTimes<N>>,
|
||||||
/// Tracks the highest pruned code-replacement, if any. This is the `expected_at` value,
|
/// Tracks the highest pruned code-replacement, if any. This is the `activated_at` value,
|
||||||
/// not the `activated_at` value.
|
/// not the `expected_at` value.
|
||||||
last_pruned: Option<N>,
|
last_pruned: Option<N>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,23 +169,45 @@ impl ParaLifecycle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: Ord + Copy> ParaPastCodeMeta<N> {
|
impl<N: Ord + Copy + PartialEq> ParaPastCodeMeta<N> {
|
||||||
// note a replacement has occurred at a given block number.
|
// note a replacement has occurred at a given block number.
|
||||||
fn note_replacement(&mut self, expected_at: N, activated_at: N) {
|
fn note_replacement(&mut self, expected_at: N, activated_at: N) {
|
||||||
self.upgrade_times.push(ReplacementTimes { expected_at, activated_at })
|
self.upgrade_times.push(ReplacementTimes { expected_at, activated_at })
|
||||||
}
|
}
|
||||||
|
|
||||||
// Yields an identifier that should be used for validating a
|
// Yields an identifier that should be used for validating a
|
||||||
// parablock in the context of a particular relay-chain block number.
|
// parablock in the context of a particular relay-chain block number in this chain.
|
||||||
//
|
//
|
||||||
// a return value of `None` means that there is no code we are aware of that
|
// a return value of `None` means that there is no code we are aware of that
|
||||||
// should be used to validate at the given height.
|
// should be used to validate at the given height.
|
||||||
#[allow(unused)]
|
|
||||||
fn code_at(&self, para_at: N) -> Option<UseCodeAt<N>> {
|
fn code_at(&self, para_at: N) -> Option<UseCodeAt<N>> {
|
||||||
// Find out
|
// Find out
|
||||||
// a) if there is a point where code was replaced _after_ execution in this context and
|
// a) if there is a point where code was replaced in the current chain after the context
|
||||||
|
// we are finding out code for.
|
||||||
// b) what the index of that point is.
|
// b) what the index of that point is.
|
||||||
let replaced_after_pos = self.upgrade_times.iter().position(|t| t.expected_at >= para_at);
|
//
|
||||||
|
// The reason we use `activated_at` instead of `expected_at` is that a gap may occur
|
||||||
|
// between expectation and actual activation. Any block executed in a context from
|
||||||
|
// `expected_at..activated_at` is expected to activate the code upgrade and therefore should
|
||||||
|
// use the previous code.
|
||||||
|
//
|
||||||
|
// A block executed in the context of `activated_at` should use the new code.
|
||||||
|
//
|
||||||
|
// Cases where `expected_at` and `activated_at` are the same, that is, zero-delay code upgrades
|
||||||
|
// are also handled by this rule correctly.
|
||||||
|
let replaced_after_pos = self.upgrade_times.iter().position(|t| {
|
||||||
|
// example: code replaced at (5, 5)
|
||||||
|
//
|
||||||
|
// context #4 should use old code
|
||||||
|
// context #5 should use new code
|
||||||
|
//
|
||||||
|
// example: code replaced at (10, 20)
|
||||||
|
// context #9 should use the old code
|
||||||
|
// context #10 should use the old code
|
||||||
|
// context #19 should use the old code
|
||||||
|
// context #20 should use the new code
|
||||||
|
para_at < t.activated_at
|
||||||
|
});
|
||||||
|
|
||||||
if let Some(replaced_after_pos) = replaced_after_pos {
|
if let Some(replaced_after_pos) = replaced_after_pos {
|
||||||
// The earliest stored code replacement needs to be special-cased, since we need to check
|
// The earliest stored code replacement needs to be special-cased, since we need to check
|
||||||
@@ -205,7 +227,11 @@ impl<N: Ord + Copy> ParaPastCodeMeta<N> {
|
|||||||
// we don't know the code necessary anymore. Compare against `last_pruned` to determine.
|
// we don't know the code necessary anymore. Compare against `last_pruned` to determine.
|
||||||
self.last_pruned.as_ref().map_or(
|
self.last_pruned.as_ref().map_or(
|
||||||
Some(UseCodeAt::Current), // nothing pruned, use current
|
Some(UseCodeAt::Current), // nothing pruned, use current
|
||||||
|t| if t >= ¶_at { None } else { Some(UseCodeAt::Current) },
|
|earliest_activation| if ¶_at < earliest_activation {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(UseCodeAt::Current)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -233,7 +259,7 @@ impl<N: Ord + Copy> ParaPastCodeMeta<N> {
|
|||||||
self.upgrade_times.drain(self.upgrade_times.len()..)
|
self.upgrade_times.drain(self.upgrade_times.len()..)
|
||||||
} else {
|
} else {
|
||||||
// if we are actually pruning something, update the last_pruned member.
|
// if we are actually pruning something, update the last_pruned member.
|
||||||
self.last_pruned = Some(self.upgrade_times[to_prune - 1].expected_at);
|
self.last_pruned = Some(self.upgrade_times[to_prune - 1].activated_at);
|
||||||
self.upgrade_times.drain(..to_prune)
|
self.upgrade_times.drain(..to_prune)
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -691,7 +717,6 @@ impl<T: Config> Module<T> {
|
|||||||
/// Schedule a parathread to be upgraded to a parachain.
|
/// Schedule a parathread to be upgraded to a parachain.
|
||||||
///
|
///
|
||||||
/// Will return error if `ParaLifecycle` is not `Parathread`.
|
/// Will return error if `ParaLifecycle` is not `Parathread`.
|
||||||
#[allow(unused)]
|
|
||||||
pub(crate) fn schedule_parathread_upgrade(id: ParaId) -> DispatchResult {
|
pub(crate) fn schedule_parathread_upgrade(id: ParaId) -> DispatchResult {
|
||||||
let scheduled_session = Self::scheduled_session();
|
let scheduled_session = Self::scheduled_session();
|
||||||
let lifecycle = ParaLifecycles::get(&id).ok_or(Error::<T>::NotRegistered)?;
|
let lifecycle = ParaLifecycles::get(&id).ok_or(Error::<T>::NotRegistered)?;
|
||||||
@@ -711,7 +736,6 @@ impl<T: Config> Module<T> {
|
|||||||
/// Schedule a parachain to be downgraded to a parathread.
|
/// Schedule a parachain to be downgraded to a parathread.
|
||||||
///
|
///
|
||||||
/// Noop if `ParaLifecycle` is not `Parachain`.
|
/// Noop if `ParaLifecycle` is not `Parachain`.
|
||||||
#[allow(unused)]
|
|
||||||
pub(crate) fn schedule_parachain_downgrade(id: ParaId) -> DispatchResult {
|
pub(crate) fn schedule_parachain_downgrade(id: ParaId) -> DispatchResult {
|
||||||
let scheduled_session = Self::scheduled_session();
|
let scheduled_session = Self::scheduled_session();
|
||||||
let lifecycle = ParaLifecycles::get(&id).ok_or(Error::<T>::NotRegistered)?;
|
let lifecycle = ParaLifecycles::get(&id).ok_or(Error::<T>::NotRegistered)?;
|
||||||
@@ -808,15 +832,11 @@ impl<T: Config> Module<T> {
|
|||||||
/// code has been pruned.
|
/// code has been pruned.
|
||||||
///
|
///
|
||||||
/// To get associated code see [`Self::validation_code_at`].
|
/// To get associated code see [`Self::validation_code_at`].
|
||||||
#[allow(unused)]
|
|
||||||
pub(crate) fn validation_code_hash_at(
|
pub(crate) fn validation_code_hash_at(
|
||||||
id: ParaId,
|
id: ParaId,
|
||||||
at: T::BlockNumber,
|
at: T::BlockNumber,
|
||||||
assume_intermediate: Option<T::BlockNumber>,
|
assume_intermediate: Option<T::BlockNumber>,
|
||||||
) -> Option<Hash> {
|
) -> Option<Hash> {
|
||||||
let now = <frame_system::Pallet<T>>::block_number();
|
|
||||||
let config = <configuration::Module<T>>::config();
|
|
||||||
|
|
||||||
if assume_intermediate.as_ref().map_or(false, |i| &at <= i) {
|
if assume_intermediate.as_ref().map_or(false, |i| &at <= i) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
@@ -839,7 +859,6 @@ impl<T: Config> Module<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Fetch validation code of para in specific context, see [`Self::validation_code_hash_at`].
|
/// Fetch validation code of para in specific context, see [`Self::validation_code_hash_at`].
|
||||||
#[allow(unused)]
|
|
||||||
pub(crate) fn validation_code_at(
|
pub(crate) fn validation_code_at(
|
||||||
id: ParaId,
|
id: ParaId,
|
||||||
at: T::BlockNumber,
|
at: T::BlockNumber,
|
||||||
@@ -1011,19 +1030,34 @@ mod tests {
|
|||||||
past_code.note_replacement(10, 12);
|
past_code.note_replacement(10, 12);
|
||||||
assert_eq!(past_code.code_at(0), Some(UseCodeAt::ReplacedAt(10)));
|
assert_eq!(past_code.code_at(0), Some(UseCodeAt::ReplacedAt(10)));
|
||||||
assert_eq!(past_code.code_at(10), Some(UseCodeAt::ReplacedAt(10)));
|
assert_eq!(past_code.code_at(10), Some(UseCodeAt::ReplacedAt(10)));
|
||||||
assert_eq!(past_code.code_at(11), Some(UseCodeAt::Current));
|
assert_eq!(past_code.code_at(11), Some(UseCodeAt::ReplacedAt(10)));
|
||||||
|
assert_eq!(past_code.code_at(12), Some(UseCodeAt::Current));
|
||||||
|
|
||||||
past_code.note_replacement(20, 25);
|
past_code.note_replacement(20, 25);
|
||||||
assert_eq!(past_code.code_at(1), Some(UseCodeAt::ReplacedAt(10)));
|
assert_eq!(past_code.code_at(1), Some(UseCodeAt::ReplacedAt(10)));
|
||||||
assert_eq!(past_code.code_at(10), Some(UseCodeAt::ReplacedAt(10)));
|
assert_eq!(past_code.code_at(10), Some(UseCodeAt::ReplacedAt(10)));
|
||||||
assert_eq!(past_code.code_at(11), Some(UseCodeAt::ReplacedAt(20)));
|
assert_eq!(past_code.code_at(11), Some(UseCodeAt::ReplacedAt(10)));
|
||||||
assert_eq!(past_code.code_at(20), Some(UseCodeAt::ReplacedAt(20)));
|
assert_eq!(past_code.code_at(12), Some(UseCodeAt::ReplacedAt(20)));
|
||||||
assert_eq!(past_code.code_at(21), Some(UseCodeAt::Current));
|
assert_eq!(past_code.code_at(24), Some(UseCodeAt::ReplacedAt(20)));
|
||||||
|
assert_eq!(past_code.code_at(25), Some(UseCodeAt::Current));
|
||||||
|
|
||||||
|
past_code.note_replacement(30, 30);
|
||||||
|
assert_eq!(past_code.code_at(1), Some(UseCodeAt::ReplacedAt(10)));
|
||||||
|
assert_eq!(past_code.code_at(10), Some(UseCodeAt::ReplacedAt(10)));
|
||||||
|
assert_eq!(past_code.code_at(11), Some(UseCodeAt::ReplacedAt(10)));
|
||||||
|
assert_eq!(past_code.code_at(12), Some(UseCodeAt::ReplacedAt(20)));
|
||||||
|
assert_eq!(past_code.code_at(24), Some(UseCodeAt::ReplacedAt(20)));
|
||||||
|
assert_eq!(past_code.code_at(25), Some(UseCodeAt::ReplacedAt(30)));
|
||||||
|
assert_eq!(past_code.code_at(30), Some(UseCodeAt::Current));
|
||||||
|
|
||||||
past_code.last_pruned = Some(5);
|
past_code.last_pruned = Some(5);
|
||||||
assert_eq!(past_code.code_at(1), None);
|
assert_eq!(past_code.code_at(1), None);
|
||||||
assert_eq!(past_code.code_at(5), None);
|
assert_eq!(past_code.code_at(5), None);
|
||||||
assert_eq!(past_code.code_at(6), Some(UseCodeAt::ReplacedAt(10)));
|
assert_eq!(past_code.code_at(6), Some(UseCodeAt::ReplacedAt(10)));
|
||||||
|
assert_eq!(past_code.code_at(24), Some(UseCodeAt::ReplacedAt(20)));
|
||||||
|
assert_eq!(past_code.code_at(25), Some(UseCodeAt::ReplacedAt(30)));
|
||||||
|
assert_eq!(past_code.code_at(30), Some(UseCodeAt::Current));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -1048,7 +1082,7 @@ mod tests {
|
|||||||
assert_eq!(past_code.prune_up_to(26).collect::<Vec<_>>(), vec![20]);
|
assert_eq!(past_code.prune_up_to(26).collect::<Vec<_>>(), vec![20]);
|
||||||
assert_eq!(past_code, ParaPastCodeMeta {
|
assert_eq!(past_code, ParaPastCodeMeta {
|
||||||
upgrade_times: vec![upgrade_at(30, 35)],
|
upgrade_times: vec![upgrade_at(30, 35)],
|
||||||
last_pruned: Some(20),
|
last_pruned: Some(25),
|
||||||
});
|
});
|
||||||
|
|
||||||
past_code.note_replacement(40, 42);
|
past_code.note_replacement(40, 42);
|
||||||
@@ -1057,20 +1091,21 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(past_code, ParaPastCodeMeta {
|
assert_eq!(past_code, ParaPastCodeMeta {
|
||||||
upgrade_times: vec![upgrade_at(30, 35), upgrade_at(40, 42), upgrade_at(50, 53), upgrade_at(60, 66)],
|
upgrade_times: vec![upgrade_at(30, 35), upgrade_at(40, 42), upgrade_at(50, 53), upgrade_at(60, 66)],
|
||||||
last_pruned: Some(20),
|
last_pruned: Some(25),
|
||||||
});
|
});
|
||||||
|
|
||||||
assert_eq!(past_code.prune_up_to(60).collect::<Vec<_>>(), vec![30, 40, 50]);
|
assert_eq!(past_code.prune_up_to(60).collect::<Vec<_>>(), vec![30, 40, 50]);
|
||||||
assert_eq!(past_code, ParaPastCodeMeta {
|
assert_eq!(past_code, ParaPastCodeMeta {
|
||||||
upgrade_times: vec![upgrade_at(60, 66)],
|
upgrade_times: vec![upgrade_at(60, 66)],
|
||||||
last_pruned: Some(50),
|
last_pruned: Some(53),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
assert_eq!(past_code.most_recent_change(), Some(60));
|
||||||
assert_eq!(past_code.prune_up_to(66).collect::<Vec<_>>(), vec![60]);
|
assert_eq!(past_code.prune_up_to(66).collect::<Vec<_>>(), vec![60]);
|
||||||
|
|
||||||
assert_eq!(past_code, ParaPastCodeMeta {
|
assert_eq!(past_code, ParaPastCodeMeta {
|
||||||
upgrade_times: Vec::new(),
|
upgrade_times: Vec::new(),
|
||||||
last_pruned: Some(60),
|
last_pruned: Some(66),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1371,6 +1406,28 @@ mod tests {
|
|||||||
Paras::past_code_meta(¶_id).most_recent_change(),
|
Paras::past_code_meta(¶_id).most_recent_change(),
|
||||||
Some(expected_at),
|
Some(expected_at),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Some hypothetical block which would have triggered the code change
|
||||||
|
// should still use the old code.
|
||||||
|
assert_eq!(
|
||||||
|
Paras::past_code_meta(¶_id).code_at(expected_at),
|
||||||
|
Some(UseCodeAt::ReplacedAt(expected_at)),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Some hypothetical block at the context which actually triggered the
|
||||||
|
// code change should still use the old code.
|
||||||
|
assert_eq!(
|
||||||
|
Paras::past_code_meta(¶_id).code_at(expected_at + 4),
|
||||||
|
Some(UseCodeAt::ReplacedAt(expected_at)),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Some hypothetical block at the context after the code was upgraded
|
||||||
|
// should use the new code.
|
||||||
|
assert_eq!(
|
||||||
|
Paras::past_code_meta(¶_id).code_at(expected_at + 4 + 1),
|
||||||
|
Some(UseCodeAt::Current),
|
||||||
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
<Paras as Store>::PastCodeHash::get(&(para_id, expected_at)),
|
<Paras as Store>::PastCodeHash::get(&(para_id, expected_at)),
|
||||||
Some(original_code.hash()),
|
Some(original_code.hash()),
|
||||||
@@ -1694,12 +1751,16 @@ mod tests {
|
|||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(Paras::validation_code_at(para_id, 2, None), Some(old_code.clone()));
|
assert_eq!(Paras::validation_code_at(para_id, 2, None), Some(old_code.clone()));
|
||||||
assert_eq!(Paras::validation_code_at(para_id, 3, None), Some(new_code.clone()));
|
assert_eq!(Paras::validation_code_at(para_id, 3, None), Some(old_code.clone()));
|
||||||
|
assert_eq!(Paras::validation_code_at(para_id, 9, None), Some(old_code.clone()));
|
||||||
|
assert_eq!(Paras::validation_code_at(para_id, 10, None), Some(new_code.clone()));
|
||||||
|
|
||||||
run_to_block(10 + code_retention_period, None);
|
run_to_block(10 + code_retention_period, None);
|
||||||
|
|
||||||
assert_eq!(Paras::validation_code_at(para_id, 2, None), Some(old_code.clone()));
|
assert_eq!(Paras::validation_code_at(para_id, 2, None), Some(old_code.clone()));
|
||||||
assert_eq!(Paras::validation_code_at(para_id, 3, None), Some(new_code.clone()));
|
assert_eq!(Paras::validation_code_at(para_id, 3, None), Some(old_code.clone()));
|
||||||
|
assert_eq!(Paras::validation_code_at(para_id, 9, None), Some(old_code.clone()));
|
||||||
|
assert_eq!(Paras::validation_code_at(para_id, 10, None), Some(new_code.clone()));
|
||||||
|
|
||||||
run_to_block(10 + code_retention_period + 1, None);
|
run_to_block(10 + code_retention_period + 1, None);
|
||||||
|
|
||||||
@@ -1709,12 +1770,14 @@ mod tests {
|
|||||||
Paras::past_code_meta(¶_id),
|
Paras::past_code_meta(¶_id),
|
||||||
ParaPastCodeMeta {
|
ParaPastCodeMeta {
|
||||||
upgrade_times: Vec::new(),
|
upgrade_times: Vec::new(),
|
||||||
last_pruned: Some(2),
|
last_pruned: Some(10),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(Paras::validation_code_at(para_id, 2, None), None); // pruned :(
|
assert_eq!(Paras::validation_code_at(para_id, 2, None), None); // pruned :(
|
||||||
assert_eq!(Paras::validation_code_at(para_id, 3, None), Some(new_code.clone()));
|
assert_eq!(Paras::validation_code_at(para_id, 9, None), None);
|
||||||
|
assert_eq!(Paras::validation_code_at(para_id, 10, None), Some(new_code.clone()));
|
||||||
|
assert_eq!(Paras::validation_code_at(para_id, 11, None), Some(new_code.clone()));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user