Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Paras authorize_code_hash + apply_authorized_code feature #7592

Open
wants to merge 42 commits into
base: master
Choose a base branch
from

Conversation

bkontur
Copy link
Contributor

@bkontur bkontur commented Feb 17, 2025

Closes: #7574
Relates to: #7591

This feature is useful when triggering a Paras pallet call from a different chain than the one where the Paras pallet is deployed. For example, we may want to send Paras::force_set_current_code(para, code) from the Collectives and/or AssetHub to the relay chain (because the relaychain governance will be migrated to the AssetHub as a part of AHM).

The primary reason for this approach is to avoid transferring the entire new_code Wasm blob between chains. Instead, we authorize the code_hash using root via fn authorize_force_set_current_code_hash(new_authorization, expire_at). This authorization can later be applied by anyone using Paras::apply_authorized_force_set_current_code(para, new_code). If expire_at is reached without the authorization being used, it is automatically removed.

TODO

Open questions

  • Do we need something like poke_authorized_code_hash? E.g. in case that we authorize code hash, but nobody would apply it and the parachain starts working with old/other_new code? Is this possible?
  • Do we need something similar for frame_system pallet and set_code / set_code_without_checks?
  • Can we achieve the same with pallet-whitelist?
  • Do we have other extrinsics over chains which has code attribute?
  • Do we need to add validate_unsigned for apply_authorized_code?

@bkontur
Copy link
Contributor Author

bkontur commented Feb 17, 2025

/cmd fmt

@bkontur bkontur added T14-system_parachains This PR/Issue is related to system parachains. A4-needs-backport Pull request must be backported to all maintained releases. labels Feb 17, 2025
@bkontur
Copy link
Contributor Author

bkontur commented Feb 17, 2025

/cmd prdoc --audience runtime_dev --bump patch

@bkontur
Copy link
Contributor Author

bkontur commented Feb 17, 2025

/cmd bench --pallet polkadot_runtime_parachains::paras --runtime westend rococo

Copy link
Contributor

Command "bench --pallet polkadot_runtime_parachains::paras --runtime westend rococo" has started 🚀 See logs here

Copy link
Contributor

Command "bench --pallet polkadot_runtime_parachains::paras --runtime westend rococo" has finished ✅ See logs here

Subweight results:
File Extrinsic Old New Change [%]
cumulus/pallets/collator-selection/src/weights.rs leave_intent - - ERROR
cumulus/pallets/collator-selection/src/weights.rs new_session - - ERROR
cumulus/pallets/collator-selection/src/weights.rs register_as_candidate - - ERROR
cumulus/pallets/collator-selection/src/weights.rs set_invulnerables - - ERROR
cumulus/pallets/collator-selection/src/weights.rs take_candidate_slot - - ERROR
cumulus/pallets/collator-selection/src/weights.rs update_bond - - ERROR
cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_collator_selection.rs take_candidate_slot - - ERROR
cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_collator_selection.rs update_bond - - ERROR
cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_collator_selection.rs take_candidate_slot - - ERROR
cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_collator_selection.rs update_bond - - ERROR
cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/pallet_collator_selection.rs take_candidate_slot - - ERROR
cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/pallet_collator_selection.rs update_bond - - ERROR
cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/pallet_collator_selection.rs take_candidate_slot - - ERROR
cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/pallet_collator_selection.rs update_bond - - ERROR
cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/pallet_collator_selection.rs take_candidate_slot - - ERROR
cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/pallet_collator_selection.rs update_bond - - ERROR
cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/pallet_preimage.rs ensure_updated - - ERROR
cumulus/parachains/runtimes/people/people-rococo/src/weights/pallet_collator_selection.rs take_candidate_slot - - ERROR
cumulus/parachains/runtimes/people/people-rococo/src/weights/pallet_collator_selection.rs update_bond - - ERROR
cumulus/parachains/runtimes/people/people-westend/src/weights/pallet_collator_selection.rs take_candidate_slot - - ERROR
cumulus/parachains/runtimes/people/people-westend/src/weights/pallet_collator_selection.rs update_bond - - ERROR
polkadot/runtime/rococo/src/weights/polkadot_runtime_parachains_paras.rs add_trusted_validation_code - - ERROR
polkadot/runtime/rococo/src/weights/polkadot_runtime_parachains_paras.rs force_note_new_head - - ERROR
polkadot/runtime/rococo/src/weights/polkadot_runtime_parachains_paras.rs force_schedule_code_upgrade - - ERROR
polkadot/runtime/rococo/src/weights/polkadot_runtime_parachains_paras.rs force_set_current_code - - ERROR
polkadot/runtime/rococo/src/weights/polkadot_runtime_parachains_paras.rs force_set_current_head - - ERROR
polkadot/runtime/westend/src/weights/pallet_preimage.rs ensure_updated - - ERROR
polkadot/runtime/westend/src/weights/polkadot_runtime_parachains_paras.rs add_trusted_validation_code - - ERROR
polkadot/runtime/westend/src/weights/polkadot_runtime_parachains_paras.rs force_note_new_head - - ERROR
polkadot/runtime/westend/src/weights/polkadot_runtime_parachains_paras.rs force_schedule_code_upgrade - - ERROR
polkadot/runtime/westend/src/weights/polkadot_runtime_parachains_paras.rs force_set_current_code - - ERROR
polkadot/runtime/westend/src/weights/polkadot_runtime_parachains_paras.rs force_set_current_head - - ERROR
substrate/frame/election-provider-support/src/weights.rs phragmen - - ERROR
substrate/frame/election-provider-support/src/weights.rs phragmms - - ERROR
polkadot/runtime/westend/src/weights/polkadot_runtime_parachains_paras.rs force_set_most_recent_context 110.16us 103.91us -5.67
polkadot/runtime/westend/src/weights/polkadot_runtime_parachains_paras.rs include_pvf_check_statement_finalize_onboarding_accept 1.21ms 1.03ms -14.87
polkadot/runtime/westend/src/weights/polkadot_runtime_parachains_paras.rs authorize_force_set_current_code_hash 137.18us Added
polkadot/runtime/westend/src/weights/polkadot_runtime_parachains_paras.rs apply_authorized_force_set_current_code 40.31ms Added
polkadot/runtime/rococo/src/weights/polkadot_runtime_parachains_paras.rs authorize_force_set_current_code_hash 137.30us Added
polkadot/runtime/rococo/src/weights/polkadot_runtime_parachains_paras.rs apply_authorized_force_set_current_code 38.43ms Added
Command output:

✅ Successful benchmarks of runtimes/pallets:
-- westend: ['polkadot_runtime_parachains::paras']
-- rococo: ['polkadot_runtime_parachains::paras']

/// triggering the same functionality as `force_set_current_code`.
#[pallet::call_index(10)]
#[pallet::weight(<T as Config>::WeightInfo::apply_authorized_force_set_current_code(new_code.0.len() as u32))]
pub fn apply_authorized_force_set_current_code(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could use the feeless_if attribute.

Copy link
Contributor Author

@bkontur bkontur Feb 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could use the feeless_if attribute.

I don't see much example of feeless_if, but iiuc it can do calculation just based on the inputs?
Or should I do something like:

#[pallet::feeless_if(|_: &OriginFor<T>, para: ParaId, validation_code: ValidationCode| -> bool {
            // check that the code was applied
            Self::current_code(para) == Some(validation_code.hash())
})]

But this way, we allow spamming the chain for free, because I cannot check Self::current_code(para) before and after.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because I cannot check Self::current_code(para) before and after.

What you mean by this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand correctly, the purpose of using feeless_if here was to allow free execution when the code is actually applied, essentially the same effect as the PostDispatchInfo hack at the end (which should be removed when using feeless_if):

let post = PostDispatchInfo {
    // Consume the rest of the block to prevent further transactions
    actual_weight: Some(T::BlockWeights::get().max_block),
    // No fee for a valid upgrade
    pays_fee: Pays::No,
};
Ok(post)

However, in this case, the PostDispatchInfo hack is applied after validations, when do_force_set_current_code_update is actually executed.

Is this really enough? Is it ok to access storage and calculate hash again inside feeless_if?

#[pallet::feeless_if(|_: &OriginFor<T>, para: ParaId, validation_code: ValidationCode| -> bool {
            // check that the code was applied
            Self::current_code(para) == Some(validation_code.hash())
})]

because I cannot check Self::current_code(para) before and after.

Forget about it, I'm probably overthinking. My idea was to check the result of the extrinsic inside #[pallet::feeless_if], something like (but that's not possible):

let code_before = Self::current_code(para);
.. wait extrinsic to do the job
let code_after = Self::current_code(para);

if code_before ! code_after {
   PaysFee::No
} else {
   PaysFee::Yes
}

In other words, I’m not sure how to properly use feeless_if here. 😅

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this really enough? Is it ok to access storage and calculate hash again inside feeless_if?

Yes that would be enough.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIUC, for feeless_if, we need to add the SkipCheckIfFeeless extension wrapper and configure the pallet accordingly:
https://github.com/paritytech/polkadot-sdk/blob/master/substrate/frame/transaction-payment/skip-feeless-payment/src/lib.rs#L16-L35

impl pallet_skip_feeless_payment::Config for Runtime {
    type RuntimeEvent = RuntimeEvent;
}

However, we don’t currently use SkipCheckIfFeeless anywhere in polkadot-sdk (except in kitchensink), polkadot-fellows, or other runtimes.


IIUC, all charge payment extensions below use type Val = Val<T>; and type Pre = Pre<T>;, but SkipCheckIfFeeless instead uses type Val = Intermediate<S::Val, ...> and type Pre = Intermediate<S::Pre, ...>

pallet_skip_feeless_payment::SkipCheckIfFeeless<Runtime, 
        pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
>

pallet_skip_feeless_payment::SkipCheckIfFeeless<Runtime, 
        pallet_asset_conversion_tx_payment::ChargeAssetTxPayment<Runtime>,
>

pallet_skip_feeless_payment::SkipCheckIfFeeless<Runtime, 
        pallet_asset_tx_payment::ChargeAssetTxPayment<Runtime>,
>

IIUC, based on the kitchensink extras, which include SkipCheckIfFeeless, and the usage of get_eth_extension, it should be safe to add without breaking anything.


@gupnik @georgepisaltu @bkchr

  1. Could you help confirm whether it is safe to add the SkipCheckIfFeeless wrapper to existing (relay and/or parachain) runtimes? Specifically, would this change affect backwards compatibility for existing TransactionExtensions, or cause issues for clients submitting extrinsics (e.g., requiring them to change the format or anything else)?

  2. If it is safe, I can manage/handle adding SkipCheckIfFeeless to all runtimes. However, should/want we apply it to all runtimes, only relay chains, or just system parachains?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1. Could you help confirm whether it is safe to add the `SkipCheckIfFeeless` wrapper to existing (relay and/or parachain) runtimes? Specifically, would this change affect backwards compatibility for existing `TransactionExtensions`, or cause issues for clients submitting extrinsics (e.g., requiring them to change the format or anything else)?

The encoding/decoding of transaction is not changed when adding SkipCheckIfFeeless.
In the metadata SkipCheckIfFeeless will not appear and instead only the inner transaction identifier, type and implicit will show up.

2. If it is safe, I can manage/handle adding `SkipCheckIfFeeless` to all runtimes. However, should/want we apply it to all runtimes, only relay chains, or just system parachains?

I don't know audit status but otherwise I don't see anything that would break from this.

bkontur and others added 3 commits February 18, 2025 10:27
Co-authored-by: Bastian Köcher <git@kchr.de>
Co-authored-by: Bastian Köcher <git@kchr.de>
@bkontur
Copy link
Contributor Author

bkontur commented Feb 18, 2025

/cmd fmt

@bkontur bkontur requested a review from bkchr February 18, 2025 10:05
@bkontur bkontur self-assigned this Feb 18, 2025
@bkontur
Copy link
Contributor Author

bkontur commented Mar 3, 2025

/cmd fmt

@bkontur
Copy link
Contributor Author

bkontur commented Mar 4, 2025

/cmd prdoc --audience runtime_dev --bump patch --force

@bkontur
Copy link
Contributor Author

bkontur commented Mar 4, 2025

/cmd fmt

@bkontur
Copy link
Contributor Author

bkontur commented Mar 4, 2025

/cmd bench --pallet polkadot_runtime_parachains::paras --runtime westend rococo

@bkontur bkontur requested a review from bkchr March 4, 2025 15:35
Copy link
Contributor

github-actions bot commented Mar 4, 2025

Command "bench --pallet polkadot_runtime_parachains::paras --runtime westend rococo" has started 🚀 See logs here

@paritytech-workflow-stopper
Copy link

All GitHub workflows were cancelled due to failure one of the required jobs.
Failed workflow url: https://github.com/paritytech/polkadot-sdk/actions/runs/13657313223
Failed job name: quick-benchmarks-omni

Copy link
Contributor

github-actions bot commented Mar 4, 2025

Command "bench --pallet polkadot_runtime_parachains::paras --runtime westend rococo" has failed ❌! See logs here

@bkontur
Copy link
Contributor Author

bkontur commented Mar 4, 2025

/cmd bench --pallet polkadot_runtime_parachains::paras --runtime westend rococo

Copy link
Contributor

github-actions bot commented Mar 4, 2025

Command "bench --pallet polkadot_runtime_parachains::paras --runtime westend rococo" has started 🚀 See logs here

Copy link
Contributor

github-actions bot commented Mar 4, 2025

Command "bench --pallet polkadot_runtime_parachains::paras --runtime westend rococo" has finished ✅ See logs here

Subweight results:
File Extrinsic Old New Change [%]
polkadot/runtime/westend/src/weights/polkadot_runtime_parachains_paras.rs authorize_force_set_current_code_hash 108.40us Added
polkadot/runtime/westend/src/weights/polkadot_runtime_parachains_paras.rs apply_authorized_force_set_current_code 46.85ms Added
polkadot/runtime/rococo/src/weights/polkadot_runtime_parachains_paras.rs authorize_force_set_current_code_hash 108.42us Added
polkadot/runtime/rococo/src/weights/polkadot_runtime_parachains_paras.rs apply_authorized_force_set_current_code 38.75ms Added
Command output:

✅ Successful benchmarks of runtimes/pallets:
-- westend: ['polkadot_runtime_parachains::paras']
-- rococo: ['polkadot_runtime_parachains::paras']

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A4-needs-backport Pull request must be backported to all maintained releases. T14-system_parachains This PR/Issue is related to system parachains.
Projects
Status: In Progress
Status: In review
Development

Successfully merging this pull request may close these issues.

paras pallet - add new extrinsincs for authorize/apply set_current_code
3 participants