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§
- Main
Chain Scripts V1 - Cardano identifiers necessary for observation of the Governed Map