16
16
17
17
#![ cfg_attr( not( feature = "std" ) , no_std) ]
18
18
19
- //! cumulus-pallet-parachain-system is a base pallet for cumulus -based parachains.
19
+ //! ` cumulus-pallet-parachain-system` is a base pallet for Cumulus -based parachains.
20
20
//!
21
- //! This pallet handles low-level details of being a parachain. It's responsibilities include:
21
+ //! This pallet handles low-level details of being a parachain. Its responsibilities include:
22
22
//!
23
- //! - ingestion of the parachain validation data
24
- //! - ingestion of incoming downward and lateral messages and dispatching them
25
- //! - coordinating upgrades with the relay-chain
26
- //! - communication of parachain outputs, such as sent messages, signalling an upgrade, etc.
23
+ //! - ingestion of the parachain validation data;
24
+ //! - ingestion and dispatch of incoming downward and lateral messages;
25
+ //! - coordinating upgrades with the Relay Chain; and
26
+ //! - communication of parachain outputs, such as sent messages, signaling an upgrade, etc.
27
27
//!
28
28
//! Users must ensure that they register this pallet as an inherent provider.
29
29
30
- use codec:: Encode ;
30
+ use codec:: { Decode , Encode , MaxEncodedLen } ;
31
31
use cumulus_primitives_core:: {
32
32
relay_chain, AbridgedHostConfiguration , ChannelStatus , CollationInfo , DmpMessageHandler ,
33
33
GetChannelInfo , InboundDownwardMessage , InboundHrmpMessage , MessageSendError ,
@@ -45,6 +45,7 @@ use frame_support::{
45
45
} ;
46
46
use frame_system:: { ensure_none, ensure_root} ;
47
47
use polkadot_parachain:: primitives:: RelayChainBlockNumber ;
48
+ use scale_info:: TypeInfo ;
48
49
use sp_runtime:: {
49
50
traits:: { Block as BlockT , BlockNumberProvider , Hash } ,
50
51
transaction_validity:: {
@@ -134,6 +135,20 @@ impl CheckAssociatedRelayNumber for AnyRelayNumber {
134
135
fn check_associated_relay_number ( _: RelayChainBlockNumber , _: RelayChainBlockNumber ) { }
135
136
}
136
137
138
+ /// Information needed when a new runtime binary is submitted and needs to be authorized before
139
+ /// replacing the current runtime.
140
+ #[ derive( Decode , Encode , Default , PartialEq , Eq , MaxEncodedLen , TypeInfo ) ]
141
+ #[ scale_info( skip_type_params( T ) ) ]
142
+ struct CodeUpgradeAuthorization < T >
143
+ where
144
+ T : Config ,
145
+ {
146
+ /// Hash of the new runtime binary.
147
+ code_hash : T :: Hash ,
148
+ /// Whether or not to carry out version checks.
149
+ check_version : bool ,
150
+ }
151
+
137
152
#[ frame_support:: pallet]
138
153
pub mod pallet {
139
154
use super :: * ;
@@ -442,17 +457,40 @@ pub mod pallet {
442
457
Ok ( ( ) )
443
458
}
444
459
460
+ /// Authorize an upgrade to a given `code_hash` for the runtime. The runtime can be supplied
461
+ /// later.
462
+ ///
463
+ /// The `check_version` parameter sets a boolean flag for whether or not the runtime's spec
464
+ /// version and name should be verified on upgrade. Since the authorization only has a hash,
465
+ /// it cannot actually perform the verification.
466
+ ///
467
+ /// This call requires Root origin.
445
468
#[ pallet:: call_index( 2 ) ]
446
469
#[ pallet:: weight( ( 1_000_000 , DispatchClass :: Operational ) ) ]
447
- pub fn authorize_upgrade ( origin : OriginFor < T > , code_hash : T :: Hash ) -> DispatchResult {
470
+ pub fn authorize_upgrade (
471
+ origin : OriginFor < T > ,
472
+ code_hash : T :: Hash ,
473
+ check_version : bool ,
474
+ ) -> DispatchResult {
448
475
ensure_root ( origin) ?;
449
-
450
- AuthorizedUpgrade :: < T > :: put ( & code_hash) ;
476
+ AuthorizedUpgrade :: < T > :: put ( CodeUpgradeAuthorization {
477
+ code_hash : code_hash. clone ( ) ,
478
+ check_version,
479
+ } ) ;
451
480
452
481
Self :: deposit_event ( Event :: UpgradeAuthorized { code_hash } ) ;
453
482
Ok ( ( ) )
454
483
}
455
484
485
+ /// Provide the preimage (runtime binary) `code` for an upgrade that has been authorized.
486
+ ///
487
+ /// If the authorization required a version check, this call will ensure the spec name
488
+ /// remains unchanged and that the spec version has increased.
489
+ ///
490
+ /// Note that this function will not apply the new `code`, but only attempt to schedule the
491
+ /// upgrade with the Relay Chain.
492
+ ///
493
+ /// All origins are allowed.
456
494
#[ pallet:: call_index( 3 ) ]
457
495
#[ pallet:: weight( 1_000_000 ) ]
458
496
pub fn enact_authorized_upgrade (
@@ -487,16 +525,16 @@ pub mod pallet {
487
525
488
526
#[ pallet:: error]
489
527
pub enum Error < T > {
490
- /// Attempt to upgrade validation function while existing upgrade pending
528
+ /// Attempt to upgrade validation function while existing upgrade pending.
491
529
OverlappingUpgrades ,
492
- /// Polkadot currently prohibits this parachain from upgrading its validation function
530
+ /// Polkadot currently prohibits this parachain from upgrading its validation function.
493
531
ProhibitedByPolkadot ,
494
532
/// The supplied validation function has compiled into a blob larger than Polkadot is
495
- /// willing to run
533
+ /// willing to run.
496
534
TooBig ,
497
- /// The inherent which supplies the validation data did not run this block
535
+ /// The inherent which supplies the validation data did not run this block.
498
536
ValidationDataNotAvailable ,
499
- /// The inherent which supplies the host configuration did not run this block
537
+ /// The inherent which supplies the host configuration did not run this block.
500
538
HostConfigurationNotAvailable ,
501
539
/// No validation function upgrade is currently scheduled.
502
540
NotScheduled ,
@@ -645,7 +683,7 @@ pub mod pallet {
645
683
646
684
/// The next authorized upgrade, if there is one.
647
685
#[ pallet:: storage]
648
- pub ( super ) type AuthorizedUpgrade < T : Config > = StorageValue < _ , T :: Hash > ;
686
+ pub ( super ) type AuthorizedUpgrade < T : Config > = StorageValue < _ , CodeUpgradeAuthorization < T > > ;
649
687
650
688
/// A custom head data that should be returned as result of `validate_block`.
651
689
///
@@ -712,9 +750,17 @@ pub mod pallet {
712
750
713
751
impl < T : Config > Pallet < T > {
714
752
fn validate_authorized_upgrade ( code : & [ u8 ] ) -> Result < T :: Hash , DispatchError > {
715
- let required_hash = AuthorizedUpgrade :: < T > :: get ( ) . ok_or ( Error :: < T > :: NothingAuthorized ) ?;
753
+ let authorization = AuthorizedUpgrade :: < T > :: get ( ) . ok_or ( Error :: < T > :: NothingAuthorized ) ?;
754
+
755
+ // ensure that the actual hash matches the authorized hash
716
756
let actual_hash = T :: Hashing :: hash ( & code[ ..] ) ;
717
- ensure ! ( actual_hash == required_hash, Error :: <T >:: Unauthorized ) ;
757
+ ensure ! ( actual_hash == authorization. code_hash, Error :: <T >:: Unauthorized ) ;
758
+
759
+ // check versions if required as part of the authorization
760
+ if authorization. check_version {
761
+ frame_system:: Pallet :: < T > :: can_set_code ( code) ?;
762
+ }
763
+
718
764
Ok ( actual_hash)
719
765
}
720
766
}
0 commit comments