Skip to content

Custom Runtime

Introduction

For teams that already have been working on a Substrate runtime, it will be necessary to implement the required modules and configurations into the runtime. This will ensure that the runtime can evolve into a Tanssi appchain successfully deployed through Tanssi and run properly within Polkadot.

Failing to do so might lead to reduced interoperability within the ecosystem and unnecessary exposure to vulnerabilities.

Minimum Requirements

Already existing Substrate runtimes need to at least have both Cumulus and Tanssi-specific modules.

Nevertheless, teams might have already implemented certain modules that can collide with some functionalities related to Tanssi, for example, block production, block authority assignment, and consensus.

If the starting point for your project was the parachain template, the following modules are included by default and must be removed along with their corresponding configuration:

Authorship: pallet_authorship = 20,
CollatorSelection: pallet_collator_selection = 21,
Session: pallet_session = 22,
Aura: pallet_aura = 23,
AuraExt: cumulus_pallet_aura_ext = 24,

In any case, make sure to check your runtime and remove all the modules that might interfere with the block production as a service before starting the registration process.

Adding Cumulus Support

If the runtime is set up as a solo chain, check the official Cumulus template or any of the templates available in the Tanssi repository for a reference setup.

Adding Tanssi Protocol Support

To support the Tanssi protocol, it will be necessary to add the modules through the following steps:

  1. Include the dependencies in the Cargo.toml manifesto (usually located in the root folder). Open the Cargo.toml file and add the modules in the dependencies section

    [dependencies]
    ...
    pallet-cc-authorities-noting = { 
        git = "https://github.com/moondance-labs/tanssi", 
        branch = "master", default-features = false 
    }
    pallet_authorities_noting = {
        git = "https://github.com/moondance-labs/moonkit",
        branch = "tanssi-polkadot-v0.9.43", default-features = false
    }
    ...
    
  2. Configure the modules. Open the file lib.rs located in the folder */runtime/src and add the configuration for both modules:

    impl pallet_author_inherent::Config for Runtime {
        type AuthorId = NimbusId;
        type AccountLookup = tp_consensus::NimbusLookUp;
        type CanAuthor = pallet_cc_authorities_noting::CanAuthor<Runtime>;
        type SlotBeacon = tp_consensus::AuraDigestSlotBeacon<Runtime>;
        type WeightInfo = 
            pallet_author_inherent::weights::SubstrateWeight<Runtime>;
    }
    
    impl pallet_cc_authorities_noting::Config for Runtime {
        type RuntimeEvent = RuntimeEvent;
        type SelfParaId = parachain_info::Pallet<Runtime>;
        type RelayChainStateProvider = 
            cumulus_pallet_parachain_system::RelaychainDataProvider<Self>;
        type AuthorityId = NimbusId;
        type WeightInfo = 
            pallet_cc_authorities_noting::weights::SubstrateWeight<Runtime>;
    }
    

    Note that this configuration is agnostic from the use case

  3. Declare the modules as part of the runtime. In the same lib.rs file, located in the folder */runtime/src, add the modules to the construction of the runtime:

    construct_runtime!(
    pub enum Runtime where
        Block = Block,
        NodeBlock = opaque::Block,
        UncheckedExtrinsic = UncheckedExtrinsic,
    {
        ...
        // Tanssi appchain
        AuthoritiesNoting: pallet_cc_authorities_noting = 50,
        AuthorInherent: pallet_author_inherent = 51,
        ...
    }
    
  4. Make sure your Header is configured as follows:

    type Header = generic::Header<BlockNumber, BlakeTwo256>;
    /// An index to a block.
    pub type BlockNumber = u32; 
    
  5. Add the block executor, to allow the validators in the relay chain to check that the authors are the block producers assigned by Tanssi (and not a malicious actor)

    cumulus_pallet_parachain_system::register_validate_block! {
        Runtime = Runtime,
        BlockExecutor = pallet_author_inherent::BlockExecutor::<Runtime, Executive>
        CheckInherents = CheckInherents,
    }
    
Last update: May 14, 2024
| Created: November 4, 2023