HackMD
  • Beta
    Beta  Get a sneak peek of HackMD’s new design
    Turn on the feature preview and give us feedback.
    Go → Got it
      • Create new note
      • Create a note from template
    • Beta  Get a sneak peek of HackMD’s new design
      Beta  Get a sneak peek of HackMD’s new design
      Turn on the feature preview and give us feedback.
      Go → Got it
      • Sharing Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • More (Comment, Invitee)
      • Publishing
        Please check the box to agree to the Community Guidelines.
        Everyone on the web can find and read all notes of this public team.
        After the note is published, everyone on the web can find and read this note.
        See all published notes on profile page.
      • Commenting Enable
        Disabled Forbidden Owners Signed-in users Everyone
      • Permission
        • Forbidden
        • Owners
        • Signed-in users
        • Everyone
      • Invitee
      • No invitee
      • Options
      • Versions and GitHub Sync
      • Transfer ownership
      • Delete this note
      • Template
      • Save as template
      • Insert from template
      • Export
      • Dropbox
      • Google Drive Export to Google Drive
      • Gist
      • Import
      • Dropbox
      • Google Drive Import from Google Drive
      • Gist
      • Clipboard
      • Download
      • Markdown
      • HTML
      • Raw HTML
    Menu Sharing Create Help
    Create Create new note Create a note from template
    Menu
    Options
    Versions and GitHub Sync Transfer ownership Delete this note
    Export
    Dropbox Google Drive Export to Google Drive Gist
    Import
    Dropbox Google Drive Import from Google Drive Gist Clipboard
    Download
    Markdown HTML Raw HTML
    Back
    Sharing
    Sharing Link copied
    /edit
    View mode
    • Edit mode
    • View mode
    • Book mode
    • Slide mode
    Edit mode View mode Book mode Slide mode
    Note Permission
    Read
    Only me
    • Only me
    • Signed-in users
    • Everyone
    Only me Signed-in users Everyone
    Write
    Only me
    • Only me
    • Signed-in users
    • Everyone
    Only me Signed-in users Everyone
    More (Comment, Invitee)
    Publishing
    Please check the box to agree to the Community Guidelines.
    Everyone on the web can find and read all notes of this public team.
    After the note is published, everyone on the web can find and read this note.
    See all published notes on profile page.
    More (Comment, Invitee)
    Commenting Enable
    Disabled Forbidden Owners Signed-in users Everyone
    Permission
    Owners
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Invitee
    No invitee
       owned this note    owned this note      
    Published Linked with GitHub
    Like BookmarkBookmarked
    Subscribed
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    Subscribe
    # Table of Contents [TOC] import pandas as pd import numpy as np # Assumptions & Key Considerations ### 1. Base reward per increment > The number of validators considered is 491,875 (As on 23rd Dec’22) and the corresponding base reward per increment is 510. > num_validators = 491875 base_reward_factor = 64 #constant base_reward_ = (10** 9 * base_reward_factor) / np.sqrt(32*10**9 * num_validators) print(base_reward_) base_reward = base_reward_ Ws=14 Wt=26 Wh=14 Wsum = 64 ### 2. Performance Metrics for Permissionless node operators - bottom performers **Basis of Permissionless node operators - bottom performers** * Considered the bottom 20th percentile of deposit addresses from rated.network, arranged by uptime * Source: [https://www.rated.network/o/Rocketpool?network=mainnet&view=pool](https://) * The analysis was performed in Nov’22 and to ensure the base data was still relevant at the time of publication of this analysis, the performance metrics of the bottom 20th percentile was recalculated for the last 30 days on 7th Jan’23. Since the validator performance improved from 89.24% to 90.11%, the data for Oct’22 was considered to be sufficient. **Performance Metrics** Rsth = (Ws+Wt+Wh)/Wsum # percent reward for correct source + target + head Rnst = (-Ws-Wt)/Wsum # penality for wrong source + target Rsnt = (Ws-Wt)/Wsum #Penality for correct source, wrong target Rstnh = (Ws+Wt)/Wsum # Not included due to lack of data on Permissionless node operators - bottom performers k= (Rsth*base_reward)/(10**9) k1=(Rnst*base_reward)/(10** 9) k2 =(Rsnt*base_reward)/(10** 9) ![](https://i.imgur.com/Y2gxDfO.png) ### 3. Performance Metrics for Permissionless node operators - Bottom Performers in a DVT Network DVT significantly improves operator uptime: ![](https://i.imgur.com/9q0xEju.png) DVT technology makes a validator more efficient by improving uptime to 94% when compared to a stand-alone validator with an uptime of 89.2%, given the same level of validator performance. In a DVT-network, for a validator to perform duties (correctly & timely), atleast 3 out 4 nodes will need to correctly perform duties ie, we will need to calculate: > Probability of atleast 3 nodes performing duties correctly = probability of all 4 nodes performing duties correctly + probability of 3 out of 4 nodes performing duties correctly ![](https://i.imgur.com/Cm5SWQe.png) ### 4. Penalties and Inactivity Leak It is assumed that the period of poor performance that attracts penalties and the inactivity leak occursconsecutively in the first set of epochs, and this repeats for 6 cycles of 30 days each. The implications are as follows: 1. In all scenarios, has the effect of being more conservative on the effective balance - The effective balance is reduced right at the start leading to a lower balance at the end of the penalty epoch and hence has a lower effective balance on which the rewards are applied. 1. In case of an inactivity leak, has the effect of assuming the worst-case in the calculation of the inactivity score - This would cover the worst-case scenario with the inactivity score increasing every epoch 1. Inactivity leak penalty quotient = 16777216 ### 5. Slashing 1. Simulations for slashing is the same as assuming a validator is offline throughout the entire duration (36 days). However, in addition, there are 2 subtractions to the active balance 2. The first is initial slash of 1 ETH at the 1st epoch ( It is assumed to occur at the first epoch) 3. The second is correlation penalty applied at the 4050 epoch (18 days) **Correlation Penalty Calculation:** To calculate correlation penalty we need to get the sum of effective balances of slashed validators in the past 36 days. In order to do so we need the probability of slash of a validator in a 36 day window. **Probability of a validator being slashed in a 36 day window** ![](https://i.imgur.com/hvfs8MO.png) 1. Let p be the probability of a slashing event per epoch per validator 1. The probability of a validator being slashed in 36 days would be 1 - (1-p)^(36*225) 1. Calculating probability of a slash event per epoch per validator 3. There have been 220 slashing events over 168120 epochs of the beacon chain. The number of validators have increased from 21,063 to 490,751 4. P = (total number of slashing incidents)/(area under the curve) 5. The area under the graph is calculated by approximating it to a trapezium 6. P =0.000000005102789204 [5.10E-09] 7. Based on the value of p the value of Probability of a validator being slashed in a 36 day window comes out to be 0.00004133173837 8. Correlation penalty =min( B, 3* S/T * B), S/T 9. S= 0.00004133173837 *n *32 10. T =n*32 11. N is the number of validators 12. S/T =0.00004133173837 ->represented in the code as corr_penallity_sbyt 13. Correlation penalty then becomes 3*0.00004133173837 *b_eff where b_eff is the effective balance at the 4050th epoch ### 6. Attestor & Sync Committee Rewards 1. Proposer rewards are calculated using the formula wp/(wt-wp)*R where R is the value of a single attestation, wt and wp and the total and poposer weights. 1. Combining the probability of being selected to propose a block with the reward earned we get the total proposer reward for a validator to be 0.01377385714 ETH for 30 days and 0.08264314286 for 180 days. 1. The sync committee reward per validator per slot is calculated using Wy*T*b/(32*512*100) where Wy is is the sync reward weight, T is the total number of validators and b is the base reward. Combining this with the probability of being included in the sync committee we get the sync committee rewards to be 0.0034425 ETH for 30 days and 0.020655 ETH for 180 days 1. The total rewards combining Proposer and sync committee rewards are as follows: ![](https://i.imgur.com/Ah82hvD.png) # Simulation Code ## 1. Normal Network Conditions ### Normal Network conditions (Non-DVT) def thirty_day_cycle_no_inactivity(b,k1,k2,k3,b_eff): b_new=b b_eff=b_eff inactivity_score=0 attest_penality=0 k=k1 for i in range(1,6751): if i <519: k =k1 inactivity_score =inactivity_score+4 inactivity_score =inactivity_score-16 elif i <727: k =k2 inactivity_score =inactivity_score+4 inactivity_score =inactivity_score-16 else : k = k3 inactivity_score =inactivity_score-1 inactivity_score =inactivity_score-16 inactivity_score =max(inactivity_score,0) attest_penality =k*b_eff inactivity_penality = (inactivity_score*b_eff)/(4*16777216) b_new = b_new + attest_penality -inactivity_penality if b_new -b_eff >=1.25: b_eff =b_eff+1 b_eff =min(b_eff,32) if b_eff-b_new>=0.25: b_eff =b_eff-1 b_eff =max(b_eff,0) b_eff =min(b_eff,32) b_prev =b_new return b_new, b_eff #### Simulation Results for Normal Network Conditions # Simualtion for Permissionless node operators - Bottom Performers with no inactivity leak b_new=32 b_eff=32 for i in range(1,7): b_new,b_eff =thirty_day_cycle_no_inactivity(b_new,k1,k2,k,b_eff) print(b_new, i*30,'days') Result: 32.077049457807114 30 days 32.15409891561533 60 days 32.231148373423544 90 days 32.30819783123176 120 days 32.385247289039974 150 days 32.46229674684819 180 days ### Normal network conditions (DVT Infra) def thirty_day_cycle_ssv(b,k1,k2,b_eff): b_new=b b_eff =b_eff inactivity_score=0 attest_penality=0 k=k1 for i in range(1,6751): if i <406: k =k1 inactivity_score =inactivity_score+4 inactivity_score =inactivity_score-16 else : k = k2 inactivity_score =inactivity_score-1 inactivity_score =inactivity_score-16 inactivity_score =max(inactivity_score,0) attest_penality =k*b_eff inactivity_penality = (inactivity_score*b_eff)/(4*16777216) b_new = b_new + attest_penality -inactivity_penality if b_new -b_eff >=1.25: b_eff =b_eff+1 b_eff =min(b_eff,32) if b_eff-b_new>=0.25: b_eff =b_eff-1 b_eff =max(b_eff,0) b_eff =min(b_eff,32) b_prev =b_new return b_new,b_eff #### Simulation results for Normal Network Conditions (DVT Infra) b_new=32 b_eff=32 for i in range(1,7): b_new,b_eff =thirty_day_cycle_ssv(b_new,k1,k,b_eff) print(b_new, i*30,'days') Result: 32.08326024401464 30 days 32.16652048803072 60 days 32.2497807320468 90 days 32.33304097606288 120 days 32.416301220078964 150 days 32.499561464095045 180 days ## 2. Inactivity leak for 7 days ### Inactivity Leak for 7 days (Non-DVT) def thirty_day_cycle_with_inactivity(b,k1,k2,k3,b_eff): b_new=b b_eff =b inactivity_score=0 attest_penality=0 k=k1 for i in range(1,6751): if i <519 : k =k1 inactivity_score =inactivity_score+4 elif i <727: k =k2 inactivity_score =inactivity_score+4 elif i <=1575 : k = 0 inactivity_score =inactivity_score-1 else: k=k3 inactivity_score=inactivity_score-17 # 16 from no inactivity and 1 from being active in epoch participation so total 17 inactivity_score =max(inactivity_score,0) attest_penality =k*b_eff inactivity_penality = (inactivity_score*b_eff)/(4*16777216) b_new = b_new + attest_penality -inactivity_penality if b_new -b_eff >=1.25: b_eff =b_eff+1 b_eff =min(b_eff,32) if b_eff-b_new>=0.25: b_eff =b_eff-1 b_eff =max(b_eff,0) b_eff =min(b_eff,32) return b_new, b_eff #### Simulation results for Inactivity leak for 7 days (Non-DVT) # Permissionless node operators - Bottom Performers with inactivity leak for 7 days b_new=32 b_eff=32 for i in range(1,7): if i==1: b_new,b_eff =thirty_day_cycle_with_inactivity(b_new,k1,k2,k,b_eff) else: b_new,b_eff=thirty_day_cycle_no_inactivity(b_new,k1,k2,k,b_eff) print(b_new, i*30,'days') Result: 30.545535629329766 30 days 30.617769496015566 60 days 30.690003362701365 90 days 30.762237229387164 120 days 30.834471096072964 150 days 30.906704962758763 180 days ### Inactivity leak for 7 days (DVT Infra) def thirty_day_cycle_ssv_inactivity(b,k1,k2,b_eff): b_new=b b_eff=b_eff inactivity_score=0 attest_penality=0 k=k1 for i in range(1,6751): if i <406: #worst case k =k1 inactivity_score =inactivity_score+4 elif i <1575:#1575 ->7 days k = 0 # during inactivity leak you do not receive rewards inactivity_score =inactivity_score-1 else: k = k2 #good case inactivity_score =inactivity_score-17 inactivity_score =max(inactivity_score,0) attest_penality =k*b_eff inactivity_penality = (inactivity_score*b_eff)/(4*16777216) b_new = b_new + attest_penality -inactivity_penality if b_new -b_eff >=1.25: b_eff =b_eff+1 b_eff =min(b_eff,32) if b_eff-b_new>=0.25: b_eff =b_eff-1 b_eff =max(b_eff,0) b_eff =min(b_eff,32) b_prev =b_new return b_new,b_eff #### Simulation results for Inactivity leak for 7 days (DVT Infra) b_new=32 b_eff=32 for i in range(1,7): if i==1: b_new,b_eff =thirty_day_cycle_ssv_inactivity(b_new,k1,k,b_eff) else: b_new,b_eff=thirty_day_cycle_ssv(b_new,k1,k,b_eff) print(b_new, i*30,'days') Result: 31.34376643054227 30 days 31.424424791915733 60 days 31.505083153289196 90 days 31.585741514662658 120 days 31.66639987603612 150 days 31.747058237409583 180 days #### Simulation extended for 180 days b_new=32 b_eff=32 for i in range(1,7): b_new,b_eff =thirty_day_cycle_ssv(b_new,k1,k,b_eff) print(b_new, i*30,'days') Result: 32.08326024401464 30 days 32.16652048803072 60 days 32.2497807320468 90 days 32.33304097606288 120 days 32.416301220078964 150 days 32.499561464095045 180 days ## 3. Isolated slashing event ### Isolated slashing event without inactivity leak def slashing_thirty_day_cycle_no_inactivity(b,k1,epoch,b_eff): b_new=b b_eff=b_eff attest_penality=0 k=k1 initial_slash=1 corr_penality_sbyt=0.00004133173837 for i in range(1,epoch): if i==1: b_new=b_new-initial_slash if i==4050: corr_penality =3*corr_penality_sbyt*b_eff b_new =b_new-corr_penality k =k1 attest_penality =k*b_eff b_new = b_new + attest_penality if b_new -b_eff >=1.25: b_eff =b_eff+1 b_eff =min(b_eff,32) if b_eff-b_new>=0.25: b_eff =b_eff-1 b_eff =max(b_eff,0) b_eff =min(b_eff,32) b_prev =b_new return b_new,b_eff #### Simulation Results ``` #30 day slashing_thirty_day_cycle_no_inactivity(32,k1,30*225,32) Result: (30.929450774080273, 31) #36 day (180 day) slashing_thirty_day_cycle_no_inactivity(32,k1,36*225,32) Result: (30.916107786256845, 31) ``` ### Isolated slashing event with inactivity leak for 7 days ``` def slashing_with_inactivity(b,epoch,k1,b_eff): b_new=b b_eff =b_eff inactivity_score=0 attest_penality=0 k=k1 initial_slash=1 corr_penality_sbyt=0.00004133173837 for i in range(1,epoch): # inactivity leak lasts for 7 days-our assumption if i==1: b_new=b_new-initial_slash if i==4050: corr_penality =3*corr_penality_sbyt*b_eff print(corr_penality,'-',corr_penality_sbyt,'-',b_eff) b_new =b_new-corr_penality if i <1575 : k=k1 inactivity_score =inactivity_score+4 else: k=k1 inactivity_score =inactivity_score+4 inactivity_score=inactivity_score-16 inactivity_score =max(inactivity_score,0) attest_penality =k*b_eff inactivity_penality = (inactivity_score*b_eff)/(4*16777216) b_new = b_new + attest_penality -inactivity_penality if b_new -b_eff >=1.25: b_eff =b_eff+1 b_eff =min(b_eff,32) if b_eff-b_new>=0.25: b_eff =b_eff-1 b_eff =max(b_eff,0) b_eff =min(b_eff,32) b_prev =b_new return b_new,b_eff ``` #### Simulation Results ``` slashing_with_inactivity(32,30*225,k1,32) Result: (28.05433309931474, 28) slashing_with_inactivity(32,36*225,k1,32) Result: (28.042281368379925, 28) ``` ## 4. Non-Isolated Slashing Event ### Non-Isolated slashing without inactivity leak ``` def slashing_thirty_day_cycle_no_inactivity(b,k1,epoch,b_eff): b_new=b b_eff=b_eff inactivity_score=0 attest_penality=0 k=k1 initial_slash=1 corr_penality_sbyt=0.00004133173837 ->Normal Slash corr_penality_sbyt=0.0009689140088817117 #->Staked.us for i in range(1,epoch): if i==1: b_new=b_new-initial_slash if i==4050: corr_penality =3*corr_penality_sbyt*b_eff b_new =b_new-corr_penality k =k1 inactivity_score =max(inactivity_score,0) attest_penality =k*b_eff inactivity_penality = (inactivity_score*b_new)/(4*50331648) b_new = b_new + attest_penality print(i,'-',inactivity_score,'-', round(inactivity_penality,10),'-', round(attest_penality,10), round(b_new,5)) if b_new -b_eff >=1.25: b_eff =b_eff+1 b_eff =min(b_eff,32) if b_eff-b_new>=0.25: b_eff =b_eff-1 b_eff =max(b_eff,0) print(i,'-',b_prev,'-',b_new,'-',b_prev-b_new,'-',b_eff,'-',i,'-',inactivity_score) b_eff =min(b_eff,32) b_prev =b_new return b_new,b_eff ``` #### Simulation Result #### 36 day or 180 day slashing ``` slashing_thirty_day_cycle_no_inactivity(32,k1,36*225,32) (30.829842635099254, 31) ``` ### Non-Isolated slashing with inactivity leak 7 days ``` def slashing_with_inactivity(b,epoch,k1,b_eff): b_new=b b_eff =b_eff inactivity_score=0 attest_penality=0 k=k1 initial_slash=1 corr_penality_sbyt=0.00004133173837 ->normal slash corr_penality_sbyt=0.0009689140088817117 #staked.us for i in range(1,epoch): inactivity leak lasts for 7 days-our assumption if i==1: b_new=b_new-initial_slash if i==4050: corr_penality =3*corr_penality_sbyt*b_eff print(corr_penality,'-',corr_penality_sbyt,'-',b_eff) b_new =b_new-corr_penality if i <1575 : k=k1 inactivity_score =inactivity_score+4 else: k=k1 inactivity_score =inactivity_score+4 inactivity_score=inactivity_score-16 inactivity_score =max(inactivity_score,0) attest_penality =k*b_eff inactivity_penality = (inactivity_score*b_eff)/(4*16777216) b_new = b_new + attest_penality -inactivity_penality if b_new -b_eff >=1.25: b_eff =b_eff+1 b_eff =min(b_eff,32) if b_eff-b_new>=0.25: b_eff =b_eff-1 b_eff =max(b_eff,0) b_eff =min(b_eff,32) b_prev =b_new print(i,'-',inactivity_score,'-',b_new,'-',b_eff) return b_new,b_eff ``` #### Simulation Results ``` slashing_with_inactivity(32,30*225,k1,32) (27.976416188591756, 28) slashing_with_inactivity(32,36*225,k1,32) (27.96436445765694, 28) ```

    Import from clipboard

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lost their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template is not available.


    Upgrade

    All
    • All
    • Team
    No template found.

    Create custom template


    Upgrade

    Delete template

    Do you really want to delete this template?

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Tutorials

    Book Mode Tutorial

    Slide Mode Tutorial

    YAML Metadata

    Contacts

    Facebook

    Twitter

    Feedback

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions

    Versions and GitHub Sync

    Sign in to link this note to GitHub Learn more
    This note is not linked with GitHub Learn more
     
    Add badge Pull Push GitHub Link Settings
    Upgrade now

    Version named by    

    More Less
    • Edit
    • Delete

    Note content is identical to the latest version.
    Compare with
      Choose a version
      No search result
      Version not found

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub

        Please sign in to GitHub and install the HackMD app on your GitHub repo. Learn more

         Sign in to GitHub

        HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Available push count

        Upgrade

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Upgrade

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully