Add another condition to the reject-obsolete-parachain-heads extension#1505
Conversation
serban300
left a comment
There was a problem hiding this comment.
Looks good ! I just have 2 comments. If they make sense I would be happy to implement them.
| let (parachain, parachain_head_hash) = parachains.get(0).expect("verified by match condition; qed"); | ||
|
|
||
| let bundled_relay_block_number = at_relay_block.0; | ||
|
|
||
| let best_parachain_head = $crate::BestParaHeads::<$runtime, $instance>::get(parachain); | ||
|
|
||
| match best_parachain_head { | ||
| Some(best_parachain_head) if best_parachain_head.at_relay_block_number | ||
| >= bundled_relay_block_number => | ||
| sp_runtime::transaction_validity::InvalidTransaction::Stale.into(), | ||
| >= bundled_relay_block_number => { | ||
| log::trace!( | ||
| target: $crate::LOG_TARGET, | ||
| "Rejecting obsolete parachain-head {:?} transaction: bundled relay block number: \ | ||
| {:?} best relay block number: {:?}", | ||
| parachain, | ||
| bundled_relay_block_number, | ||
| best_parachain_head.at_relay_block_number, | ||
| ); | ||
| sp_runtime::transaction_validity::InvalidTransaction::Stale.into() | ||
| } | ||
| Some(best_parachain_head) if best_parachain_head.head_hash == *parachain_head_hash => { | ||
| log::trace!( | ||
| target: $crate::LOG_TARGET, | ||
| "Rejecting obsolete parachain-head {:?} transaction: head hash {:?}", | ||
| parachain, | ||
| best_parachain_head.head_hash, | ||
| ); | ||
| sp_runtime::transaction_validity::InvalidTransaction::Stale.into() | ||
| } |
There was a problem hiding this comment.
This validation looks very similar with the one here. 2 questions:
- The equality case for
at_relay_block_numberseems to be treated differently. Here it is treated as invalid, inupdate_parachain_head()it's treated as valid. Is this expected ? - Would it make sense to do the same validation in both places ? In this case would it make sense to deduplicate the code ?
There was a problem hiding this comment.
- Imo in both cases
at_relay_block_numberleads to error, no (I maybe missing something - sorry)?
fn update_parachain_head() {
...
match stored_best_head {
Some(stored_best_head) if stored_best_head.at_relay_block_number <= updated_at_relay_block_number => {
if updated_head_hash == stored_best_head.head_hash {
return Err(());
}
// else: pass
}
...
}
fn validate() {
...
match best_parachain_head {
Some(best_parachain_head) if best_parachain_head.at_relay_block_number
>= bundled_relay_block_number => Err(()),
Some(best_parachain_head) if best_parachain_head.head_hash == *parachain_head_hash => Err(())
...
}A few notes on that: the other condition (matching hashes) is actually a separate condition, so maybe in the extension it is expressed better, with a dedicated match branch. In general, we shall ignore tx if it supplies head updated at <= stored_best_head.at_relay_block_number and we shall ignore if it has matching hashes. In practice we can't have two blocks with the same hash (crypto-safe hashing) - there's a lot that will break if we'll see it, so second condition may be checked separately or not.
- Yeah - if there's a better way to do that, go ahead! Thank you!
There was a problem hiding this comment.
- Imo in both cases
at_relay_block_numberleads to error, no (I maybe missing something - sorry)?
From what I understand, if stored_best_head.at_relay_block_number == updated_at_relay_block_number and the hashes are different, for update_parachain_head() it will go to // else: pass, while the extension will trigger an error. So if I understand correctly this case is treated differently now, even if in practice we shouldn't have to blocks with the same hash.
Anyway, I just wanted to make sure if we should have the same check in both places.
There was a problem hiding this comment.
Yeah - correct. It is impossible to have two with blocks the same hashes in practice. And if it is the same block (that is already imported), we shall reject/ignore tx
| if parachains.len() != 1 || parachains[0].0 != P::SOURCE_PARACHAIN_PARA_ID { | ||
| return Err(SubstrateError::Custom(format!( | ||
| "Trying to prove unexpected parachains {:?}. Expected {:?}", | ||
| parachains, | ||
| P::SOURCE_PARACHAIN_PARA_ID, | ||
| ))) | ||
| } | ||
|
|
||
| let parachain = parachains[0]; |
There was a problem hiding this comment.
Nit: I would do something like:
let parachain = ParaId(P::SOURCE_PARACHAIN_PARA_ID);
if parachains != &[parachain] {
return Err(SubstrateError::Custom(format!(
"Trying to prove unexpected parachains {:?}. Expected {:?}",
parachains, parachain,
)))
}
|
#1520 was merged. Marking this PR as reviewed. |
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.31 to 1.0.32. - [Release notes](https://github.com/dtolnay/thiserror/releases) - [Commits](dtolnay/thiserror@1.0.31...1.0.32) --- updated-dependencies: - dependency-name: thiserror dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
paritytech#1505) * add another condition to the reject-obsolete-parachain-heads extension * add tracing to obsolete-tx-extensions * fix tests * extension_rejects_header_from_new_relay_block_with_same_hash * fmt * fix benchmarks
paritytech#1505) * add another condition to the reject-obsolete-parachain-heads extension * add tracing to obsolete-tx-extensions * fix tests * extension_rejects_header_from_new_relay_block_with_same_hash * fmt * fix benchmarks
So currently this extension only rejects transaction if bundled at-relay-chain-block-number is lesser or equal than the existing one. But there's another condition - when parachain head remains the same (i.e. is not updated) in some relay blocks, then the other relay may use different relay chain block to prove it. The extension won't reject the transaction, even though the pallet will ignore the head (since it is the same). This PR handles this situation.
TODOs: