<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: SoYounJeong</title>
    <description>The latest articles on DEV Community by SoYounJeong (@cocoyoon).</description>
    <link>https://dev.to/cocoyoon</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F779385%2F01a46dff-a781-45f9-83e1-e211eb570b09.png</url>
      <title>DEV Community: SoYounJeong</title>
      <link>https://dev.to/cocoyoon</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/cocoyoon"/>
    <language>en</language>
    <item>
      <title>Substrate Pallet Code Analysis: Sudo</title>
      <dc:creator>SoYounJeong</dc:creator>
      <pubDate>Thu, 28 Jul 2022 05:12:00 +0000</pubDate>
      <link>https://dev.to/cocoyoon/substrate-pallet-code-analysis-sudo-45kp</link>
      <guid>https://dev.to/cocoyoon/substrate-pallet-code-analysis-sudo-45kp</guid>
      <description>&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;In substrate-based chain, there is a &lt;em&gt;god-like&lt;/em&gt; account who can call a privileged function which is called &lt;strong&gt;&lt;em&gt;sudo&lt;/em&gt;&lt;/strong&gt; account. Sudo pallet composed of that function what sudo account can do. There should be only one sudo account for the Runtime, which is called 'sudo-key'. Before launching public blockchain network, having sudo account could be useful but after launching, most of the &lt;em&gt;Parachain&lt;/em&gt; projects tend to get rid of this Sudo pallet for safety. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Let's look at how this pallet is implemented.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Source Code Analysis
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Storage
&lt;/h3&gt;

&lt;p&gt;There is only one storage for this pallet. Storage type is &lt;em&gt;StorageValue&lt;/em&gt; to store only one sudo key account for Runtime.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#[pallet::storage]
#[pallet::getter(fn key)]
pub(super) type Key&amp;lt;T: Config&amp;gt; = StorageValue&amp;lt;_, T::AccountId, OptionQuery&amp;gt;;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Dispatch Call
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;sudo&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Dispatch a call with Root origin.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Params&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;origin: &lt;em&gt;who&lt;/em&gt; calls this function&lt;/li&gt;
&lt;li&gt;call: Some Call type like dispatch calls. When building runtime, Compiler collects all the &lt;strong&gt;Call&lt;/strong&gt; type into one single Call Enum type by &lt;em&gt;#[pallet::call] macro&lt;/em&gt;. Code below is how Substrate deals with Call data type.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;


&lt;/blockquote&gt;

&lt;p&gt;In Runtime,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pub enum Call {

    System( &amp;lt;Pallet&amp;lt;Runtime&amp;gt; as Callable&amp;lt;Runtime&amp;gt;&amp;gt;::Call ),
    Balances( &amp;lt;Pallet&amp;lt;Runtime&amp;gt; as Callable&amp;lt;Runtime&amp;gt;&amp;gt;::Call ),
    Staking( &amp;lt;Pallet&amp;lt;Runtime&amp;gt; as Callable&amp;lt;Runtime&amp;gt;&amp;gt;::Call ),
    ...
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example, in Staking Pallet, any dispatch call is defined in &lt;strong&gt;Call&lt;/strong&gt; enum type&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pub enum Call {
   ...
   Staking(pallet_staking::Call::&amp;lt;Runtime&amp;gt;)
   ...
}

pub enum Call {
    bond { controller, value, payee },
    nominate { targets }
    ....
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Analysis&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Check whether origin is signed.&lt;/li&gt;
&lt;li&gt;Check whether caller is 'sudo-key account'&lt;/li&gt;
&lt;li&gt;dispatch_bypass_filter: Skip checking origin filter in dispatch call.&lt;/li&gt;
&lt;li&gt;Emit 'Sudid' event&lt;/li&gt;
&lt;li&gt;Sudo account doesn't pay fee
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pub fn sudo(
    origin: OriginFor&amp;lt;T&amp;gt;,
    call: Box&amp;lt;&amp;lt;T as Config&amp;gt;::Call&amp;gt;,
) -&amp;gt; DispatchResultWithPostInfo {

    // 1
    let sender = ensure_signed(origin)?;

    // 2
    ensure!(Self::key().map_or(false, |k| sender == k), Error::&amp;lt;T&amp;gt;::RequireSudo);

    // 3 
    let res = call.dispatch_bypass_filter(frame_system::RawOrigin::Root.into());

    // 4
    Self::deposit_event(Event::Sudid { sudo_result: res.map(|_| ()).map_err(|e| e.error) });

    // 5 
    Ok(Pays::No.into())
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;sudo_unchecked_weight&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;The logic of this method is same with _sudo&lt;/em&gt; but this time, &lt;strong&gt;Sudo&lt;/strong&gt; account can control the &lt;strong&gt;Weight&lt;/strong&gt; of the call. As we can see the parameter we give as &lt;strong&gt;_weight&lt;/strong&gt; is used in the weight calculation in &lt;em&gt;#[pallet::weight((*_weight, call.get_dispatch_info().class))]&lt;/em&gt; macro._&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Params&lt;/em&gt; &lt;/p&gt;

&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;_weight: Amount of weight sudo want to control
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#[pallet::weight((*_weight, call.get_dispatch_info().class))]
pub fn sudo_unchecked_weight(
    origin: OriginFor&amp;lt;T&amp;gt;,
    call: Box&amp;lt;&amp;lt;T as Config&amp;gt;::Call&amp;gt;,
    _weight: Weight,
) -&amp;gt; DispatchResultWithPostInfo {

    // Same logic with sudo
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;set_key&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Set sudo key with different account&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Params&lt;/p&gt;

&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;new: New sudo key account. Type is Source type of StaticLookup trait. This type is for converting any source type into AccountId. Let's take a closer look!&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;


&lt;/blockquote&gt;

&lt;p&gt;First of all, &lt;em&gt;StaticLookup&lt;/em&gt; is defined as&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;type Source: any type that we want to look&lt;/li&gt;
&lt;li&gt;type Target: Type that we want to covert&lt;/li&gt;
&lt;li&gt;fn lookup: Convert Source type into Target type&lt;/li&gt;
&lt;li&gt;fn unlookup: Convert Target type into Source type
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pub trait StaticLookup {
    // 1
    pub type Source;
    // 2 
    pub type Target;
    // 3 
    fn lookup(s: Self::Source) -&amp;gt; Result&amp;lt;Self::Target, LookupError&amp;gt;
    // 4
    fn unlookup(t: Self::Target) -&amp;gt; Self::Source;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;em&gt;frame system pallet&lt;/em&gt;, Target is defined with AccountId type, which means any Source type that we want to look can be converted into &lt;em&gt;AccountId&lt;/em&gt; type when we call &lt;em&gt;lookup&lt;/em&gt; method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pub trait Config {
    ...

    type lookup: StaticLookup&amp;lt;Target = AccountId&amp;gt;

    ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Runtime, when we look at how frame_system's config is implemented for Runtime, &lt;em&gt;pallet_indices&lt;/em&gt; is defined as lookup, which means &lt;em&gt;pallet_indices&lt;/em&gt; must implement StaticLookup trait.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;impl frame_system::Config for Runtime {

    ...

    type lookup = Indices(pallet_indices)

    ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside pallet_indices&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;impl StaticLookup for Pallet&lt;/li&gt;
&lt;li&gt;MultiAddress: Type of address formats&lt;/li&gt;
&lt;li&gt;fn lookup_address(): Returns address if exists depending on the formats of address. Here, type of address format we are looking for is &lt;em&gt;Account Id&lt;/em&gt; and &lt;em&gt;AccountIndex&lt;/em&gt;.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// 1
impl&amp;lt;T: Config&amp;gt; StaticLookup for Pallet&amp;lt;T&amp;gt; {
    type Source = MultiAddress&amp;lt;T::AccountId, T::AccountIndex&amp;gt;,
    type Target = T::AccountId,

    fn lookup(a: Self::Source) -&amp;gt; Result&amp;lt;Self::Target, LookupError&amp;gt; {
        Self::lookup_address(a).ok_or(LookupError);
    }

    fn unlookup(a: Self::Target) -&amp;gt; Self::Source {
       Multiaddress::Id(a)
    } 
}

// 2
pub enum MultiAddress&amp;lt;AccountId, AccountIndex&amp;gt; {
    Id(AccountId), // public address
    Index(AccountIndex), // Account index for database
    ...
}

// 3
impl&amp;lt;T: Config&amp;gt; Pallet&amp;lt;T&amp;gt; {

    fn lookup_index(index: T::AccountIndex) -&amp;gt; Option&amp;lt;T::AccountId&amp;gt; {
        // where Accounts is a storage that maps _AccountIndex_ to (AccountId, Balance)
        Accounts::&amp;lt;T&amp;gt;::get(index).map(|x| x.0)

    }  

    fn lookup_address(a: Multiaddress&amp;lt;T::AccountId, T::AccountIndex&amp;gt; -&amp;gt; Option&amp;lt;T::AccountId&amp;gt; {
         match a {
              Multiaddress::Id(account) =&amp;gt; Some(account)
              Multiaddress::Index(index) =&amp;gt; Self::lookup_index(index)
         }
    }
}

#[pallet::storage]
pub type Accounts&amp;lt;T: Config&amp;gt; = StorageMap&amp;lt;_, Blake2_128Concat, T::AccountIndex, (T::AccountId, BalanceOf&amp;lt;T&amp;gt;, bool)&amp;gt;;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Analysis&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Check whether origin is signed.&lt;/li&gt;
&lt;li&gt;Check whether caller is 'sudo-key account'&lt;/li&gt;
&lt;li&gt;Convert &lt;em&gt;MultiAddress&lt;/em&gt; type into AccountId,&lt;/li&gt;
&lt;li&gt;Emit 'KeyChanged' event &lt;/li&gt;
&lt;li&gt;Put new sudo-key into Key storage &lt;/li&gt;
&lt;li&gt;Sudo doesn't pay a fee
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#[pallet::weight(0)]
pub fn set_key(
    origin: OriginFor&amp;lt;T&amp;gt;,
    new: &amp;lt;T::Lookup as StaticLookup&amp;gt;::Source,
) -&amp;gt; DispatchResultWithPostInfo {

    // 1
    let sender = ensure_signed(origin)?;

    // 2
    ensure!(Self::key().map_or(false, |k| sender == k), Error::&amp;lt;T&amp;gt;::RequireSudo);

    // 3
    let new = T::Lookup::lookup(new)?;

    // 4
    Self::deposit_event(Event::KeyChanged { old_sudoer: Key::&amp;lt;T&amp;gt;::get() });

    // 5
    Key::&amp;lt;T&amp;gt;::put(&amp;amp;new);

    // 6
    Ok(Pays::No.into())
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;sudo_as&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Sudo account calls and dispatches a call with a signed account.&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Make signed account as sudo account which pays no fee&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Params&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;who: The one who calls the dispatch call
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pub fn sudo_as(
    origin: OriginFor&amp;lt;T&amp;gt;,
    who: &amp;lt;T::Lookup as StaticLookup&amp;gt;::Source,
    call: Box&amp;lt;&amp;lt;T as Config&amp;gt;::Call&amp;gt;,
) -&amp;gt; DispatchResultWithPostInfo {

    let sender = ensure_signed(origin)?;
    ensure!(Self::key().map_or(false, |k| sender == k), Error::&amp;lt;T&amp;gt;::RequireSudo);

    let who = T::Lookup::lookup(who)?;

    let res = call.dispatch_bypass_filter(frame_system::RawOrigin::Signed(who).into());

    Self::deposit_event(Event::SudoAsDone {
                sudo_result: res.map(|_| ()).map_err(|e| e.error),
            });

    Ok(Pays::No.into())
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Sudo is special feature that only exists in Substrate based chain which can do everything and it is not preferred to have in &lt;strong&gt;public&lt;/strong&gt; blockchain. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Feel free to leave a comment if you have some questions.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Reference
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/paritytech/substrate/tree/master/frame/sudo"&gt;Sudo&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/paritytech/substrate/tree/master/frame/system"&gt;Frame System&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/paritytech/substrate/tree/master/frame/indices"&gt;Indices&lt;/a&gt;&lt;/p&gt;

</description>
      <category>substrate</category>
      <category>rust</category>
      <category>algorithms</category>
      <category>blockchain</category>
    </item>
    <item>
      <title>Polkadot Consensus Part 1: BABE Algorithm Analysis</title>
      <dc:creator>SoYounJeong</dc:creator>
      <pubDate>Fri, 08 Jul 2022 02:19:06 +0000</pubDate>
      <link>https://dev.to/cocoyoon/polkadot-consensus-part-1-babe-code-base-3ch4</link>
      <guid>https://dev.to/cocoyoon/polkadot-consensus-part-1-babe-code-base-3ch4</guid>
      <description>&lt;h2&gt;
  
  
  Why do we need consensus?
&lt;/h2&gt;

&lt;p&gt;Every blockchain system has its own consensus algorithm. It is the way that the nodes in a decentralized network are able to stay synced with each other. It is the process by which these nodes communicate and come to agreement, and are able to produce new blocks. To secure the blockchain network, it is crucial to consistently produce the blocks. &lt;em&gt;It should never stop.&lt;/em&gt; Today, let's closely look at consensus algorithm of Polkadot, which is &lt;em&gt;BABE&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Polkadot's Consensus
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Babe Overview&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;One of the consensus protocol &lt;em&gt;&lt;strong&gt;Polkadot/Kusama&lt;/strong&gt;&lt;/em&gt; use is &lt;em&gt;BABE&lt;/em&gt;(Blind Assignment for Blockchain Extension). It is a &lt;em&gt;slot-based&lt;/em&gt; block production mechanism which uses a VRF function to randomly perform the slot allocation for &lt;em&gt;validators(authorities)&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Polkadot's block time can be split into epoch and slot. Epochs can be broken into slots and every slot is six seconds long.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqtrpka1fkjrbio3za9cf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqtrpka1fkjrbio3za9cf.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On every slot, all validators(authorities) generate a random number from VRF and if it is lower than threshold value which is proportional to &lt;em&gt;weight/amount of stake&lt;/em&gt;(Currently, amount of stake has nothing to do with threshold value) they have right to produce new block. Since it is fully randomized and probabilistic way, which Polkadot called &lt;em&gt;Primary Slots&lt;/em&gt;, there are some chances that no validators(authorities) are chosen for specific slot. To prevent not to be delayed for producing blocks, Polkadot has made &lt;em&gt;Secondary slots&lt;/em&gt;, which is also using VRF but deterministic way. Moreover, there could be multiple authorities for single slot, which could lead to &lt;strong&gt;temporal fork&lt;/strong&gt;. BABE's fork-choice rule is &lt;em&gt;weight-based&lt;/em&gt;, which mean chains that has more primary slots are chosen for the system. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Code Overview&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So let's look at how slot-based BABE is implemented.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;claim_slot&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Explanation&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tries to claim the given slot.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Params&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;slot: pub struct Slot(u64)&lt;/li&gt;
&lt;li&gt;epoch: pub struct Epoch { some fields }&lt;/li&gt;
&lt;li&gt;keystore: Pointer to keystore. Arc&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Returns&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Option&amp;lt;(PreDigest, AuthorityId)&amp;gt;&lt;/li&gt;
&lt;li&gt;PreDigest: Enum type that contains all data required to validate a block such as &lt;em&gt;Primary&lt;/em&gt;, &lt;em&gt;Secondary&lt;/em&gt;, &lt;em&gt;SecondaryVRF&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;AuthorityId: Public address of authority
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
// Get authorities for specific epoch
// authorities = Vec[(authorityId, index), ...]
// pub struct Slot(u64);
// epoch.authorities = [(authority's public address, weight)]

pub fn claim_slot(
    slot: Slot,
    epoch: &amp;amp;Epoch,
    keystore: &amp;amp;SyncCryptoStorePtr,
) -&amp;gt; Option&amp;lt;(PreDigest, AuthorityId)&amp;gt; {

    let authorities = epoch
        .authorities
        .iter()
        .enumerate()
        .map(|(index, a)| (a.0.clone(), index))
        .collect::&amp;lt;Vec&amp;lt;_&amp;gt;&amp;gt;();

    claim_slot_using_keys(slot, epoch, keystore, &amp;amp;authorities)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;claim_slot_using_keys&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Explanation&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Claim Primary and claim Secondary&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Params&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;slot,epoch,keystore&lt;/em&gt; are mentioned above&lt;/li&gt;
&lt;li&gt;keys: [(author's public address, index for epoch)]&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Returns&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Option&amp;lt;(PreDigest, AuthorityId)&amp;gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Comment&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In &lt;em&gt;claim_primary_slot&lt;/em&gt;, there is &lt;em&gt;epoch.config.c&lt;/em&gt;. This is pre-defined constant when we build our node. That is, &lt;em&gt;pub const PRIMARY_PROBABILITY: (u64, u64) = (1, 4)&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// claim primary. If fail, claim secondary
pub fn claim_slot_using_keys(
    slot: Slot,
    epoch: &amp;amp;Epoch,
    keystore: &amp;amp;SyncCryptoStorePtr,
    keys: &amp;amp;[(AuthorityId, usize)],
) -&amp;gt; Option&amp;lt;(PreDigest, AuthorityId)&amp;gt; {

    claim_primary_slot(slot, epoch, epoch.config.c, keystore, keys).or_else(|| {
        if epoch.config.allowed_slots.is_secondary_plain_slots_allowed() ||
            epoch.config.allowed_slots.is_secondary_vrf_slots_allowed()
        {
            claim_secondary_slot(
                slot,
                epoch,
                keys,
                keystore,
                epoch.config.allowed_slots.is_secondary_vrf_slots_allowed(),
            )
        } else {
            None
        }
    })
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;claim_primary_slot&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Explanation&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If the result of VRF, here, it is &lt;em&gt;inout&lt;/em&gt;, is less than threshold returns &lt;em&gt;Some((pre_digest, authority_id.clone()&lt;/em&gt; else returns &lt;em&gt;None&lt;/em&gt;.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fn claim_primary_slot(
    slot: Slot,
    epoch: &amp;amp;Epoch,
    c: (u64, u64),
    keystore: &amp;amp;SyncCryptoStorePtr,
    keys: &amp;amp;[(AuthorityId, usize)],
) -&amp;gt; Option&amp;lt;(PreDigest, AuthorityId)&amp;gt; {

    ---snippet---

    let threshold = calculate_primary_threshold(c, authorities, *authority_index);
    if check_primary_threshold(&amp;amp;inout, threshold) {
    let pre_digest =
PreDigest::Primary(PrimaryPreDigest {
        slot,
        vrf_output: VRFOutput(signature.output),
        vrf_proof: VRFProof(signature.proof),
        authority_index: *authority_index as u32,
    });
    return Some((pre_digest,
authority_id.clone()))}

    None
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Secondary Slot&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Explanation&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If there is no &lt;em&gt;primary authorities&lt;/em&gt;, set up to back-up plan.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;sencondary_author&lt;/strong&gt; should return authority if there is no primary slot authority.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Params&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;slot,epoch,keys,keystore&lt;/em&gt; are same with above.&lt;/li&gt;
&lt;li&gt;author_secondary_vrf: &lt;em&gt;bool type&lt;/em&gt; for whether VRF secondary slots are allowed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Returns&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Option&amp;lt;(PreDigest, AuthorityId)&amp;gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fn claim_secondary_slot(
    slot: Slot,
    epoch: &amp;amp;Epoch,
    keys: &amp;amp;[(AuthorityId, usize)],
    keystore: &amp;amp;SyncCryptoStorePtr,
    author_secondary_vrf: bool,
) -&amp;gt; Option&amp;lt;(PreDigest, AuthorityId)&amp;gt; {

    if authorities.is_empty() {
    // It means there is authorities for primary slot. Return Immediately
    return None
    }

    let expected_author = secondary_slot_author(slot, authorities, *randomness)?;

    --snippet--
}

pub(super) fn secondary_slot_author(
    slot: Slot,
    authorities: &amp;amp;[(AuthorityId, BabeAuthorityWeight)],
    randomness: [u8; 32],
) -&amp;gt; Option&amp;lt;&amp;amp;AuthorityId&amp;gt; {
    if authorities.is_empty() {
        return None
    }

    let rand = U256::from((randomness, slot).using_encoded(blake2_256));

    let authorities_len = U256::from(authorities.len());
    let idx = rand % authorities_len;

    let expected_author = authorities.get(idx.as_u32() as usize).expect(
        "authorities not empty; index constrained to list length; \
                this is a valid index; qed",
    );

    Some(&amp;amp;expected_author.0)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;BabeApi&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Explanation&lt;/em&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;After claim &lt;em&gt;primary/secondary&lt;/em&gt; slot, it is used in BabeAPi for give epochs.&lt;/li&gt;
&lt;li&gt;Result would be used for &lt;em&gt;fork-choice&lt;/em&gt; rule.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Variables&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;claims: Hashmap &lt;/li&gt;
&lt;li&gt;EpochAuthorship: Struct{
primary: Vec,
Secondary: Vec,
SecondaryVRF: Vec
}
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;async fn epoch_authorship(&amp;amp;self) -&amp;gt; RpcResult&amp;lt;HashMap&amp;lt;AuthorityId, EpochAuthorship&amp;gt;&amp;gt; {

    --snippet--

    for slot in *epoch_start..*epoch_end {
            if let Some((claim, key)) =
                authorship::claim_slot_using_keys(slot.into(), &amp;amp;epoch, &amp;amp;self.keystore, &amp;amp;keys)
            {
                match claim {
                    PreDigest::Primary { .. } =&amp;gt; {
                        claims.entry(key).or_default().primary.push(slot);
                    },
                    PreDigest::SecondaryPlain { .. } =&amp;gt; {
                        claims.entry(key).or_default().secondary.push(slot);
                    },
                    PreDigest::SecondaryVRF { .. } =&amp;gt; {
                        claims.entry(key).or_default().secondary_vrf.push(slot.into());
                    },
                };
            }

    Ok(claims)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Further Thought
&lt;/h2&gt;

&lt;p&gt;When BABE calculates threshold value in *calculate_primary_threshold_ , they have used the sum of all authorities' weight which is equal to 1 as denominator. It doesn't seem like threshold value is proportional to (weight/stake) as they said. Since validators' weight in Polkadot/Kusama is same, amount of stake is not important for current BABE system.&lt;/p&gt;
&lt;h2&gt;
  
  
  Reference
&lt;/h2&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="https://medium.com/polkadot-network/polkadot-consensus-part-3-babe-dcc2e0dd8878" class="ltag__link__link" rel="noopener noreferrer"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2Fresize%3Afill%3A88%3A88%2F1%2AHD8hu_ydbXyam5XU-eAKPw.jpeg" alt="Joe Petrowski"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://medium.com/polkadot-network/polkadot-consensus-part-3-babe-dcc2e0dd8878" class="ltag__link__link" rel="noopener noreferrer"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Polkadot Consensus Part 3: BABE. This is part 3 in our Polkadot… | by Joe Petrowski | Polkadot Network | Medium&lt;/h2&gt;
      &lt;h3&gt;Joe Petrowski ・ &lt;time&gt;Dec 19, 2019&lt;/time&gt; ・ 
      &lt;div class="ltag__link__servicename"&gt;
        &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fmedium-f709f79cf29704f9f4c2a83f950b2964e95007a3e311b77f686915c71574fef2.svg" alt="Medium Logo"&gt;
        Medium
      &lt;/div&gt;
    &lt;/h3&gt;
&lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;



&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
      &lt;div class="c-embed__cover"&gt;
        &lt;a href="https://wiki.polkadot.network/docs/learn-consensus" class="c-link s:max-w-50 align-middle" rel="noopener noreferrer"&gt;
          &lt;img alt="" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwiki.polkadot.network%2Fimg%2Fog-polkadot-wiki.png" height="auto" class="m-0"&gt;
        &lt;/a&gt;
      &lt;/div&gt;
    &lt;div class="c-embed__body"&gt;
      &lt;h2 class="fs-xl lh-tight"&gt;
        &lt;a href="https://wiki.polkadot.network/docs/learn-consensus" rel="noopener noreferrer" class="c-link"&gt;
          Polkadot's Consensus Protocols · Polkadot Wiki
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;p class="truncate-at-3"&gt;
          The Consensus Mechanisms of Polkadot.
        &lt;/p&gt;
      &lt;div class="color-secondary fs-s flex items-center"&gt;
          &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwiki.polkadot.network%2Fimg%2FPolkadot_Favicon.png"&gt;
        wiki.polkadot.network
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>polkadot</category>
      <category>consensus</category>
      <category>algorithms</category>
      <category>blockchain</category>
    </item>
    <item>
      <title>Polkadot NPoS Overview</title>
      <dc:creator>SoYounJeong</dc:creator>
      <pubDate>Sat, 04 Jun 2022 18:47:27 +0000</pubDate>
      <link>https://dev.to/cocoyoon/polkadot-npos-overview-4km7</link>
      <guid>https://dev.to/cocoyoon/polkadot-npos-overview-4km7</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Polkadot is the fully-sharded blockchain that is built to connect and secure the other blockchains as layer-0. &lt;/p&gt;

&lt;p&gt;Polkadot has interesting feature that it gives any Dot holders a role to be part of network security entities, called &lt;em&gt;Nominated-Proof-of-Staking(NPoS)&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;So what is &lt;strong&gt;NPoS&lt;/strong&gt;?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;What is NPoS?&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To continuously produce blocks and secure the network in blockchain, it is important to have good &lt;strong&gt;validators&lt;/strong&gt;. In normal &lt;em&gt;proof-of-staking&lt;/em&gt;, validators are the entities who have the great amount of stakes in the network, which can lead to be centralized network. However, in Polkadot, the system encourages any Dot holders to participate in securing the network in two ways, &lt;strong&gt;Nominators&lt;/strong&gt; and &lt;strong&gt;Validators&lt;/strong&gt;. In general, most of the crypto users would be a &lt;em&gt;nominator&lt;/em&gt; because being a &lt;em&gt;validator&lt;/em&gt; requires lots of works. Nominators can select up to 16 validators who they trust with minimum bonded asset. Then, a limit number of validators(&lt;em&gt;not all validators!&lt;/em&gt;) would be elected by the system who have the most backing Dot. Both locked their assets as collateral and receive staking rewards. Most importantly, staking system pays out staking rewards equally to all elected Validators not proportional to their amount of stake. The network creates an incentive to lower-staked validators so when certain time passed, Polkadot system wants to achieve as much &lt;em&gt;&lt;strong&gt;equally-staked validator&lt;/strong&gt;&lt;/em&gt; set as possible. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Let's say there are two validation pools, A with 1000 Dot and B with 500 Dot and rewards are 2000 Dot for each. Then, someone who backed 200 Dot in pool B will get more rewards than someone who backed 200 Dot in pool A&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;Finally, rewards are distributed into nominators with proportional to their amount of stake.&lt;/p&gt;

&lt;h2&gt;
  
  
  NPoS Scheme
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;What Polkadot wants to achieve through NPoS?&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Polkadot gives validator equal voting power in consensus protocol. To reach this, NPoS election mechanism tries to distribute nominators' stake to elected validators as evenly as possible. The objective of this mechanism is to maximize the &lt;em&gt;security&lt;/em&gt; of network as most of the validators have equal amount stake, and to achieve &lt;strong&gt;two&lt;/strong&gt; important factors, &lt;strong&gt;Fair Representation&lt;/strong&gt; and &lt;strong&gt;Security&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fair Representation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Polkadot NPoS election system is inspired by Swedish Mathematician Lars Edvard Phragmén's &lt;em&gt;proportional justified representation&lt;/em&gt;. That is, when we want &lt;em&gt;n validators&lt;/em&gt; to be elected, nominators who stake about (n / total staking) are guaranteed to have at least one of their validators to be elected. Let's look at the illustration about &lt;em&gt;fair representation&lt;/em&gt; from Medium.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--J0zvcSaV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/00ar2uvy5vl5viq3tvye.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--J0zvcSaV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/00ar2uvy5vl5viq3tvye.png" alt="Fair Representation" width="880" height="389"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;This illustration is electing 4 validators. First seems unfair representation because it doesn't represent the validator which is backed by 10 Dot nominators. Since 10 Dot is 1/4 of total stake, there should be at least one validator to be elected. However, there is no validator for this nominator, so it is unfair. Rest is fair.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Security &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Remember&lt;/em&gt; nominators can select up to 16 validators who they trust? Polkadot NPoS mechanism tries to distribute the nominator stake among these validators equal as possible. However, there is a situation where malicious validator is selected with the most backed while other validators with small equal amount. To make this situation difficult, Polkadot reaches &lt;em&gt;Security&lt;/em&gt; with the &lt;strong&gt;&lt;em&gt;minimum amounts&lt;/em&gt;&lt;/strong&gt; backing of any elected validators. Let's look at the illustration.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7STHmUcr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lsprzka7al2g36pthgxx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7STHmUcr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lsprzka7al2g36pthgxx.png" alt="Security" width="880" height="411"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Left is level 6 security and right is 9 security. As you can see, second seems more secure since almost all validators have equal amount of backed stake. This is what NPoS mechanism tries to optimize so far.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;NPoS&lt;/strong&gt; is the same way we choose &lt;em&gt;congress man&lt;/em&gt; for our country. To make our country a great place, it is our responsibilities to have great interest in whom we pick.  Since validators are acting as representatives in Polkadot network, nominators should know who is going to be a good validator and choose carefully. If they choose bad validators, their asset could be slashed, so &lt;em&gt;Nominating&lt;/em&gt; is not &lt;em&gt;"set and forget"&lt;/em&gt; operation. &lt;/p&gt;

&lt;p&gt;There are lots of things happen behind NPoS such as &lt;em&gt;How NPoS handle the nominators and _How Phragmén method is used in NPoS&lt;/em&gt;. Later, I am going to handle the details of this mechanism. &lt;/p&gt;

&lt;h2&gt;
  
  
  Reference
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://medium.com/web3foundation/how-nominated-proof-of-stake-will-work-in-polkadot-377d70c6bd43"&gt;Medium: How Nominated Proof-of-Stake will work in Polkadot&lt;/a&gt;&lt;br&gt;
&lt;a href="https://wiki.polkadot.network/docs/learn-staking"&gt;Polkadot-Wiki: Staking&lt;/a&gt;&lt;/p&gt;

</description>
      <category>polkadot</category>
      <category>consensus</category>
      <category>blockchain</category>
      <category>npos</category>
    </item>
  </channel>
</rss>
