Crate pallet_governed_map

Source
Expand description

Pallet exposing key-value pairs sourced from the Cardano ledger as part of the Governed Map feature.

§Purpose of this pallet

This pallet stores the most recent state of the key-value pairs in the Governed Map on Cardano for use by other runtime components. It also exposes hooks for other components to be notified when particular key-value pair is inserted, updated or deleted.

§Usage

§Adding to runtime

§Defining size limits

Before adding the pallet to your runtime, first decide on the limits for the data that it will process:

§MaxChanges

The maximum number of changes that will be processed in one inherent invocation. Changes are understood as the diff between previously stored mappings and the currently observed ones, as opposed to raw on-chain events altering those mappings.

Important: This number must be high enough to guarantee the inherent will always have the capacity required to process incoming changes. If the number of changes exceeds this limit, TooManyChanges error will be raised stalling block production.

If this error occurs on a live chain, then the only way of fixing it is to change the mappings on Cardano close enough to the last state registered in the pallet to bring the change count below the limit. Setting this limit above the expected number of keys in use is a safe option.

§MaxKeyLength

maximum length of keys that can be used.

Important: If a key is set in the Governed Map that exceeds this lenght limit, the KeyExceedsBounds error will be raised stalling block production, with the only recovery path being removal of this key so it is no longer in the change set.

§MaxValueLength

Maximum length of the value under a key. Same considerations as for MaxKeyLength apply.

§Defining the values in the code

Once the limit values are decided, define them in your runtime, like so:

frame_support::parameter_types! {
       pub const MaxChanges: u32 = 16;
       pub const MaxKeyLength: u32 = 64;
       pub const MaxValueLength: u32 = 512;
}

If at any point a need arises to either support higher volume of parameter changes or increase the maximum length of keys and values in the mappings, it can be achieved through a runtime upgrade that modifies the pallet’s configuration.

§Implementing on-change handler

The pallet allows the runtime implementer to define a handler that will be called for all key-value changes registered by the pallet. If your runtime needs to react to changes, crate a type implementing the OnGovernedMappingChange trait, eg:

struct ChangeHandler;

impl<MaxKeyLength, MaxValueLength> sp_governed_map::OnGovernedMappingChange<MaxKeyLength, MaxValueLength> for ChangeHandler
where
   MaxKeyLength: Get<u32>,
   MaxValueLength: Get<u32>,
{
   fn on_governed_mapping_change(
       key: BoundedString<MaxKeyLength>,
       new_value: Option<BoundedVec<u8, MaxValueLength>>,
       old_value: Option<BoundedVec<u8, MaxValueLength>>,
   ) {
       log::info!("Governed Map change for key {key}: old value: {old_value:?}, new value: {new_value:?}");
   }
}

If any handling is not needed, a no-op implementation for [()] can be used instead.

§Weights and Benchmarking

The pallet comes with pre-defined weights for its extrinsics that can be used during initial development through the SubstrateWeight type.

However, since data size limits and the on-change logic both can affect the weights, it is advisable to run your own benchmark to account for their impact. See the documentation on [crate::benchmarking] for details.

§Configuring the pallet

Once the above are defined, the pallet can finally be added to the runtime and configured like this:

impl pallet_governed_map::Config for Runtime {
    type MaxChanges = MaxChanges;
    type MaxKeyLength = MaxKeyLength;
    type MaxValueLength = MaxValueLength;
    type WeightInfo = pallet_governed_map::weights::SubstrateWeight<Runtime>;

    type OnGovernedMappingChange = ChangeHandler;

    #[cfg(feature = "runtime-benchmarks")]
    type BenchmarkHelper = ();
}

§Setting the main chain scripts

For the data sources to be able to observe the Governed Map state on Cardano, the pallet stores and exposes relevant addresses and script hashes which are necessary to query main chain state. Their values need to be set before the feature can be fully functional. How this is done depends on whether the pallet is present from the genesis block or added later to a live chain.

§Configuring the addresses at genesis

If the pallet is included in the runtime from genesis block, the scripts can be configured in the genesis config of your runtime:

pallet_governed_map::GenesisConfig {
    main_chain_scripts: Some(pallet_governed_map::MainChainScriptsV1 {
        asset_policy_id: PolicyId::from_hex_unsafe("00000000000000000000000000000000000000000000000000000001"),
        validator_address: MainchainAddress::from_str("test_addr1").unwrap(),
    }),
    ..Default::default()
}

At the same time main_chain_scripts field is optional and can be set to None if you wish to postpone setting the scripts for whatever reason.

§Setting the addresses via extrinsic

If the pallet is added to a running chain, it will initailly have no main chain scripts set and remain inactive until they are set. See section “Updating main chain scripts” for more information.

§Updating main chain scripts

To allow the Partner Chain’s governance to set and update main chain script values, the pallet provides the set_main_chain_scripts extrinsic which updates the script values in its storage. This extrinsic is required to be run with root access either via the sudo pallet or other governance mechanism.

Every time set_main_chain_scripts is successfuly invoked, the pallet will update its tracked Governed Map state to be congruent with the mappings pointed to by the updates scripts on the next Partner Chain block.

Re-exports§

pub use pallet::*;

Modules§

pallet
The pallet module in each FRAME pallet hosts the most important items needed to construct this pallet.
weights
Autogenerated weights for pallet_governed_map

Structs§

MainChainScriptsV1
Cardano identifiers necessary for observation of the Governed Map