Crate pallet_session_validator_management

Crate pallet_session_validator_management 

Source
Expand description

Pallet for setting the Partner Chain validators using inherent data

§Purpose of the pallet

This pallet provides a mechanism to rotate Partner Chain’s block producing committees based on candidate registrations and chain configuration sourced from Cardano. It works by integrating with pallet_session as a SessionManager and [ShouldEndSession] to provide it with committee information and to rotate sessions. In addition to managing the sessions, the pallet automatically registers session keys of all active block producers, alleviating the need for manual key registration, and ensures that all necessary chain-local accounts exist.

§Committee selection overview

Committees are selected for sessions corresponding roughly to Partner Chain epochs, whose duration is configurable for each Partner Chain. Due to the way session rotation works in pallet_session, these sessions are delayed by 2 blocks relative to their respective epoch.

Committees are selected based on the following inputs sourced from Cardano:

  • Registered candidates: Cardano SPOs who have registered themselves as willing to participate as block producers. These candidates need to control an ADA stake pool to be eligible for selection to a committee, and their chance at securing a seat is proportional to their pool’s size. This candidate group corresponds to a typical “trustless” Proof of Stake block producers.
  • Permissioned candidates: A list of trusted block producers that do not need to register themselves or control any ADA stake on Cardano to be eligible for a Partner Chain committee. This candidate group serves a special role as trusted block producers during initial phase of a Partner Chain’s lifetime (when there may not be enough registered candidates to ensure proper security and decentralization of the network), and are intended to be phased out as the number of trustless participants grows.
  • D-Parameter: A pair of two values R and P, controlling the number of committee seats alloted for registered and permissioned candidates respectively, which means that a committee has R+P seats overall. This parameter gives the Partner Chain the ability to bootstrap itself using an initial pool of permissioned candidates running trusted nodes, and then gradually shift to registered (trustless) candidates when proper decentralization is achieved
  • randomness seed: All randomness when selecting the committee is seeded from data sourced from Cardano so that it is tamper-proof and agreed upon by all nodes.

The permissioned candidate list and the D-Parameter are controlled by the Partner Chain’s governance authority and are crucial in ensuring the chain’s security in initial phases of its existence

§Observability parameters

All input data used when selecting a committee of a Partner Chain is sourced from Cardano. To correctly identify it, each node needs access to the current values of:

  • the registration validator address, at which all registration UTXOs are located
  • the D-Parameter minting policy, whose tokens mark the UTXO containing D-Parameter value
  • the permissioned candidate minting policy, whose tokens mark the UTXO containing the permissioned candidate list

These values are stored in the pallet storage, ensuring that they’re available for all nodes to use and agreed upon through the consensus mechanism, and can be updated using a governance level extrinsic [set_main_chain_scripts].

§Usage

§Prerequisites

This pallet’s operation requires the appropriate inherent data provider and data source be present in the node. As this pallet is crucial for the operation of the chain itself, these must be present before at the chain start or before the pallet is migrated to, to avoid down time. See documentation of sp_session_validator_management for information on how to add the IDP to your node. A Db-Sync-based data source implementation is provided by the partner_chains_db_sync_data_sources crate.

Aside from the node components, the pallet requires the Partner Chain smart contracts to have been initialized on Cardano and that at least one candidate - either a registered or permissioned one - exists. See docs/user-guides/governance/governance.md and docs/user-guides/chain-builder.md for more information about governance and how to set up the Partner Chain on Cardano.

§Adding into the runtime

§Defining key types

As with a stock Substrate chain, a Partner Chain needs to define its session keys. What these keys are depends on the consensus mechanisms used by the chain. For a Partner Chain using Aura as its consensus with a Grandpa finality gadget, the session keys can be defined as following:

sp_runtime::impl_opaque_keys! {
	#[derive(MaxEncodedLen, PartialOrd, Ord)]
	pub struct SessionKeys {
		pub aura: Aura
		pub grandpa: Grandpa,
	}
}

§Adding the pallet

The pallet should be added to the runtime before pallet_session, but after the consensus pallets used by the chain:

construct_runtime!(
	pub struct Runtime {
		System: frame_system,
		Timestamp: pallet_timestamp,
		Aura: pallet_aura,
		Grandpa: pallet_grandpa,
		Sidechain: pallet_sidechain,
		SessionCommitteeManagement: pallet_session_validator_management,
		Session: pallet_session exclude_parts { Call },
        // ... other pallets
	}
);

Important: It is recommended that when pallet_session is wired into the runtime, its extrinsics are hidden, using exclude_parts like in the example above. This ensures that chain users can’t manually register their keys in the pallet and so the registrations done on Cardano remain the sole source of truth about key ownership. Proper operation in presence of manually set user keys is not guaranteed by the toolkit and its behavior is left unspecified.

§Configuring the pallet

Configuring the pallet is straightforward and mostly consists of passing to it types already defined by other crates and in previous steps:

use sidechain_domain::cross_chain_app::Public as CrossChainPublic;

impl pallet_session_validator_management::Config for Runtime {
	type MaxValidators = MaxValidators;
	type AuthorityId = CrossChainPublic;
	type AuthorityKeys = SessionKeys;
	type AuthoritySelectionInputs = authority_selection_inherents::AuthoritySelectionInputs;
	type ScEpochNumber = sidechain_domain::ScEpochNumber;
	type WeightInfo = pallet_session_validator_management::weights::SubstrateWeight<Runtime>;
	type CommitteeMember = authority_selection_inherents::CommitteeMember<CrossChainPublic, SessionKeys>;
	type MainChainScriptsOrigin = EnsureRoot<Self::AccountId>;

	fn select_authorities(
		input: AuthoritySelectionInputs,
		sidechain_epoch: ScEpochNumber,
	) -> Option<BoundedVec<Self::CommitteeMember, Self::MaxValidators>> {
		authority_selection_inherents::select_authorities::<CrossChainPublic, SessionKeys, MaxValidators>(
			Sidechain::genesis_utxo(),
			input,
			sidechain_epoch,
		)
	}

	fn current_epoch_number() -> ScEpochNumber {
		Sidechain::current_epoch_number()
	}
}

One value that needs to be decided upon by the chain builder is MaxValidators which dictates the maximum size of a committee. This value should be higher than the P + R of the D-Parameter used and should be adjusted accordingly before any D-Parameter changes that would exceed the previous value. In case a committee selected is bigger than MaxValidators, it will be truncated, potentially leading to a skewed seat allocation and threatening the security of the consensus.

§Genesis configuration

Genesis config can be created programmatically:

GenesisConfig {
	initial_authorities: vec![
       CommitteeMember::permissioned(cross_chain_pubkey_1, session_keys_1),
    ],
	main_chain_scripts: MainChainScripts::read_from_env()?,
}

However, it is more typical for production chains to define their specs using Json. In that case an example configuration could look like this:

{
  "initialAuthorities": [
    {
      "Permissioned": {
        "id": "KW39r9CJjAVzmkf9zQ4YDb2hqfAVGdRqn53eRqyruqpxAP5YL",
        "keys": {
          "aura": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
          "grandpa": "5FA9nQDVg267DEd8m1ZypXLBnvN7SFxYwV7ndqSYGiN9TTpu"
        }
      }
    }
  ],
  "mainChainScripts": {
    "committee_candidate_address": "addr_test1wrp8p2c5h7encl55gv26d5fpz9r99jxjcm0rxgny3993dxs2xy42p",
    "d_parameter_policy_id": "0x434dc797fd036b0b654c005551ec08f39d25fa7f0eecdf4b170d46cf",
    "permissioned_candidates_policy_id": "0xe1ce5d1b8b3e93a7493ecc11556790f915aabbc44a56b0b5145770b2"
  }
}

Important: Notice, that since the pallet’s operation is necessary for block production, all main chain script values and at least one initial authority (block producer) must be provided by the genesis config.

§Updating pallet configuration

§MaxValidators

The maximum number of committee seats. As this value is not typically expected to change, it is configured as part of the pallet’s Config. This means that it can only be updated as part of a runtime upgrade. The chain builder should release a new runtime version with this value updated and the Partner Chain’s governance mechanism should be used to apply it using set_code.

§Main chain scripts

The main chain scripts can change over time as the Partner Chain migrates to new versions of the Partner Chain smart contracts, either due to bug fixes or new features being released. This is necessary, because the script addresses are derived by hashing their Plutus code and are affected by any change made to it.

The scripts are updated by invoking the [set_main_chain_scripts] extrinsic using the Partner Chain’s governance mechanism.

Important: Setting incorrect main chain script values will result in stalling block production indefinitely, requiring a network-wide roll-back. As such, main chain scripts update should be carried out with special care.

Re-exports§

pub use weights::WeightInfo;
pub use pallet::*;

Modules§

migrations
Implements storage migrations of pallet-session-validator-management.
pallet
The pallet module in each FRAME pallet hosts the most important items needed to construct this pallet.
pallet_session_support
[pallet_session] integration. Implements [pallet_session::SessionManager] and [pallet_session::ShouldEndSession] for crate::Pallet.
weights
Autogenerated weights for pallet_session_validator_management

Enums§

CommitteeRotationStages
For session state machine

Traits§

CommitteeMember
Signifies that a type represents a committee member