Skip to content

Commit

Permalink
added docs for elections, network, and timegraph pallets (#986)
Browse files Browse the repository at this point in the history
Co-authored-by: TaniaSaleem <[email protected]>
Co-authored-by: Metadata Update Bot <[email protected]>
  • Loading branch information
3 people authored Jul 3, 2024
1 parent cc0e6d5 commit 7f0035f
Show file tree
Hide file tree
Showing 15 changed files with 308 additions and 5 deletions.
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file modified config/subxt/testnet.default.scale
Binary file not shown.
Binary file modified config/subxt/testnet.development.scale
Binary file not shown.
1 change: 1 addition & 0 deletions pallets/elections/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ sp-std = { git = "https://github.com/analog-labs/polkadot-sdk", tag = "v1.13.0-p
frame-benchmarking = { git = "https://github.com/analog-labs/polkadot-sdk", tag = "v1.13.0-patched", default-features = false, optional = true }

time-primitives = { path = "../../primitives", default-features = false }
simple-mermaid.workspace = true

[dev-dependencies]
env_logger.workspace = true
Expand Down
63 changes: 63 additions & 0 deletions pallets/elections/docs/elections_flow.mmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
flowchart TB



New3[set_shard_config] --> setShardConfig1[Ensure root]
validateShard[Validate shard_size >= shard_threshold]
updateStorage[Update ShardSize and ShardThreshold]
emitEvent[Emit ShardConfigSet event]
iterateUnassigned[Iterate through Unassigned members]
tryElectShard1[try_elect_shard]

setShardConfig1 --> validateShard
validateShard -->|Valid| updateStorage
updateStorage --> emitEvent
emitEvent --> iterateUnassigned
iterateUnassigned --> tryElectShard1


New2[member_online] --> memberOnline1[Check if member is shard member]
checkElectable[Check if member is electable]
insertUnassigned[Insert member to Unassigned]
tryElectShard2[try_elect_shard]
notifyShards1[Notify Shards interface]

memberOnline1 -->|No| checkElectable
checkElectable --> insertUnassigned
insertUnassigned --> tryElectShard2
tryElectShard2 --> notifyShards1

memberOnline1 -->|Yes| notifyShards2[Notify Shards interface]


shardOffline1[shard_offline]
insertUnassignedShard[Insert shard members to Unassigned]
tryElectShard3[try_elect_shard]

shardOffline1 --> insertUnassignedShard
insertUnassignedShard --> tryElectShard3

memberOffline[member_offline]
memberOffline --> removeUnassigned[Remove member from Unassigned]
removeUnassigned --> notifyShards3[Notify Shards interface]





%%tryElectShard1 -->|Calls| tryElectShard4
%%tryElectShard3 -->|Calls| tryElectShard4
%%tryElectShard2 -->|Calls| tryElectShard4
%%createShard -->|Calls| New1

%% styles
style New2 fill:#9f9,stroke:#333,stroke-width:2px;
style New3 fill:#9f9,stroke:#333,stroke-width:2px
style memberOffline fill:#9f9,stroke:#333,stroke-width:2px;
style shardOffline1 fill:#9f9,stroke:#333,stroke-width:2px;
style tryElectShard1 fill:#9f9,stroke:#333,stroke-width:2px;
style tryElectShard2 fill:#9f9,stroke:#333,stroke-width:2px;
style tryElectShard3 fill:#9f9,stroke:#333,stroke-width:2px;


style emitEvent fill:#bbf,stroke:#333,stroke-width:2px;
41 changes: 41 additions & 0 deletions pallets/elections/docs/elections_flow_2.mmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
flowchart TD

tryElectShard4[try_elect_shard]
checkNewShard[Check if new shard can be formed]
removeSelectedMembers[Remove selected members from Unassigned]
createShard[Create shard using Shards interface]

tryElectShard4 --> checkNewShard
checkNewShard -->|Yes| removeSelectedMembers
removeSelectedMembers --> createShard



New1[new_shard_members] --> newShardMembers2[Retrieve required shard size]
collectUnassigned[Collect unassigned members and filter online members]
checkEnoughMembers[Enough members to form shard?]
returnNone[Return None]
sortMembers[Sort members by stake]
selectTopMembers[Select top members to form shard]
returnSelected[Return selected members]

newShardMembers2 --> collectUnassigned
collectUnassigned --> checkEnoughMembers
checkEnoughMembers -->|No| returnNone
checkEnoughMembers -->|Yes| sortMembers
sortMembers --> selectTopMembers
selectTopMembers --> returnSelected


setElectable[set_electable]
setElectable -->|Ensure root| clearElectable[Clear current electable list]
clearElectable --> insertElectable[Insert new electable members]




%% styles

style New1 fill:#9f9,stroke:#333,stroke-width:2px;
style tryElectShard4 fill:#9f9,stroke:#333,stroke-width:2px;
style setElectable fill:#9f9,stroke:#333,stroke-width:2px;
66 changes: 66 additions & 0 deletions pallets/elections/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,20 @@
#![cfg_attr(not(feature = "std"), no_std)]
//! # Elections Pallet
//!
//!
//!
//! The flowchart represents the logical flow and interactions within the pallet, detailing how various functions and operations are interconnected. It begins with different entry points corresponding to various operations: setting shard configuration, setting electable members, handling member online/offline events, handling shard offline events.
//!
//! **Set Shard Configuration** Flow starts by ensuring the caller is a root user, validating the shard size and threshold, updating the storage, emitting an event, iterating through unassigned members, and trying to elect a new shard.
//!
//! **Member Online** Flow checks if the member is part of a shard. If not, it verifies if the member is electable, adds them to the unassigned list, and attempts to elect a new shard. If the member is already part of a shard, it simply notifies the shards interface.
//!
//! **Shard Offline Flow** adds the shard members to the unassigned list and tries to elect a new shard. **Try Elect Shard** Flow evaluates if a new shard can be formed, removes the selected members from the unassigned list, and creates a new shard using the shards interface. **New Shard Members** Flow retrieves the required shard size, gathers unassigned and online members, ensures there are enough members to form a shard, sorts members by stake, selects the top members to form the shard, and returns the selected members.
//!
#![doc = simple_mermaid::mermaid!("../docs/elections_flow.mmd")]
//!
#![doc = simple_mermaid::mermaid!("../docs/elections_flow_2.mmd")]

pub use pallet::*;

//use polkadot_sdk::{frame_support, frame_system, sp_std};
Expand Down Expand Up @@ -34,13 +50,18 @@ pub mod pallet {

#[pallet::pallet]
#[pallet::without_storage_info]

pub struct Pallet<T>(_);

#[pallet::config]
pub trait Config: frame_system::Config<AccountId = AccountId> {
/// The runtime event type.
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
/// The weight information for the pallet's extrinsics.
type WeightInfo: WeightInfo;
/// The interface for shard-related operations.
type Shards: ShardsInterface + MemberEvents;
/// The storage interface for member-related data.
type Members: MemberStorage;
}

Expand Down Expand Up @@ -111,8 +132,17 @@ pub mod pallet {
ThresholdLargerThanSize,
}

/// The pallet provides mechanisms to configure and manage shards, elect members to shards, and handle member events. It includes storage items to keep track of shard sizes, thresholds, and electable members. It also defines events and errors related to shard management.
#[pallet::call]
impl<T: Config> Pallet<T> {
/// Sets the configuration for shard size and threshold.
/// # Flow:
/// 1. Ensures the caller is the root.
/// 2. Validates that `shard_size` is greater than or equal to `shard_threshold`.
/// 3. Updates [`ShardSize`] and [`ShardThreshold`] storage values.
/// 4. Emits the [`Event::ShardConfigSet`] event.
/// 5. Iterates through all unassigned members in the [`Unassigned`] storage.
/// 6. Calls `try_elect_shard` for each network to form new shards if possible.
#[pallet::call_index(0)]
#[pallet::weight(T::WeightInfo::set_shard_config())]
pub fn set_shard_config(
Expand All @@ -131,6 +161,11 @@ pub mod pallet {
Ok(())
}

/// Sets the electable members who can be assigned to shards.
/// # Flow
/// 1. Ensures the caller is the root.
/// 2. Clears the existing electable members list from the [`Electable`] storage.
/// 3. Inserts the new electable members into the [`Electable`] storage.
#[pallet::call_index(1)]
#[pallet::weight(T::WeightInfo::set_shard_config())]
pub fn set_electable(origin: OriginFor<T>, electable: Vec<AccountId>) -> DispatchResult {
Expand All @@ -144,6 +179,13 @@ pub mod pallet {
}

impl<T: Config> MemberEvents for Pallet<T> {
/// Handles the event when a member comes online.
/// # Flow
/// 1. Checks if the member is not already a shard member.
/// 2. Checks if the member is electable or if there are no electable members defined.
/// 3. Inserts the member into the [`Unassigned`] storage for the given network.
/// 4. Attempts to elect a new shard for the network by calling `try_elect_shard`.
/// 5. Notifies the `Shards` interface about the member coming online.
fn member_online(member: &AccountId, network: NetworkId) {
if !T::Shards::is_shard_member(member) {
if Electable::<T>::iter().next().is_none() || Electable::<T>::get(member).is_some()
Expand All @@ -154,6 +196,11 @@ pub mod pallet {
}
T::Shards::member_online(member, network);
}
/// Handles the event when a member goes offline.
/// # Flow
/// 1. Removes the member from the [`Unassigned`] storage for the given network.
/// 2. Notifies the `Shards` interface about the member going offline.
/// 3. Returns the weight of the operation.
fn member_offline(member: &AccountId, network: NetworkId) -> Weight {
Unassigned::<T>::remove(network, member);
T::DbWeight::get()
Expand All @@ -163,24 +210,43 @@ pub mod pallet {
}

impl<T: Config> ElectionsInterface for Pallet<T> {
/// Handles the event when a shard goes offline.
/// # Flow
/// 1. Inserts each member of the offline shard into the [`Unassigned`] storage for the given network.
/// 2. Attempts to elect a new shard for the network by calling `try_elect_shard`.
fn shard_offline(network: NetworkId, members: Vec<AccountId>) {
members.into_iter().for_each(|m| Unassigned::<T>::insert(network, m, ()));
Self::try_elect_shard(network);
}

/// Retrieves the default shard size.
/// # Flow
/// 1. Returns the value of [`ShardSize`] from storage.
fn default_shard_size() -> u16 {
ShardSize::<T>::get()
}
}

impl<T: Config> Pallet<T> {
/// Attempts to elect a new shard for a network.
/// # Flow
/// 1. Calls `new_shard_members` to get a list of new shard members.
/// 2. If a new shard can be formed, removes the selected members from [`Unassigned`] storage.
/// 3. Creates a new shard using the `Shards` interface with the selected members and current shard threshold.
fn try_elect_shard(network: NetworkId) {
if let Some(members) = Self::new_shard_members(network) {
members.iter().for_each(|m| Unassigned::<T>::remove(network, m));
T::Shards::create_shard(network, members, ShardThreshold::<T>::get());
}
}

/// Determines the members for a new shard.
/// # Flow
/// 1. Retrieves the required shard size.
/// 2. Collects unassigned members for the given network who are online.
/// 3. Returns `None` if there are not enough members to form a shard.
/// 4. If there are just enough members, returns the list of members.
/// 5. If there are more members than needed, sorts them by their stake and selects the top members to form the shard.
fn new_shard_members(network: NetworkId) -> Option<Vec<AccountId>> {
let shard_members_len = ShardSize::<T>::get() as usize;
let mut members = Unassigned::<T>::iter_prefix(network)
Expand Down
3 changes: 3 additions & 0 deletions pallets/networks/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ frame-benchmarking = { git = "https://github.com/analog-labs/polkadot-sdk", tag

time-primitives = { path = "../../primitives", default-features = false }

simple-mermaid.workspace = true


[dev-dependencies]
#polkadot-sdk = { workspace = true, features = [ "pallet-balances", "sp-core", "sp-io" ] }

Expand Down
32 changes: 32 additions & 0 deletions pallets/networks/docs/network_flow.mmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
graph TD
B[add_network]
B --> C{Ensure Root}
C -->|Root| D[Call insert_network]
C -->|Not Root| E[Return Error::NotRoot]

D --> F{Check Network Exists}
F -->|Exists| G[Return Error::NetworkExists]
F -->|Doesn't Exist| H[Get NetworkIdCounter]

H --> I{Check Overflow}
I -->|Overflow| J[Return Error::NetworkIdOverflow]
I -->|No Overflow| K[Increment NetworkIdCounter]

K --> L[Store Network in Networks]
L --> M[Update NetworkIdCounter]

M --> N[Emit NetworkAdded Event]
N --> O[Return Ok]



%% style extrinsics
style B fill:#f9f,stroke:#333,stroke-width:2px;

%% style errors
style E fill:#f96,stroke:#333,stroke-width:2px;
style G fill:#f96,stroke:#333,stroke-width:2px;
style J fill:#f96,stroke:#333,stroke-width:2px;

%% style events
style N fill:#bbf,stroke:#333,stroke-width:2px;
Loading

0 comments on commit 7f0035f

Please sign in to comment.