<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Cradicle Explorer</title>
    <link href="/css/bootstrap/bootstrap.min.css" rel="stylesheet">
    <style>
      .form-control-dark::placeholder {
          color: #aaa;
          opacity: 1;
      }
    </style>
    <link rel="stylesheet" href="/assets/fontawesome/css/all.min.css">
    <link rel="icon" type="image/png" href="/favicon.png">


                <link href="/css/dashboard.css" rel="stylesheet">
                </head>
                <body>
                <header class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0 shadow">
                  <a class="navbar-brand col-md-3 col-lg-2 me-0 px-3 fs-6" href="/">Cradicle Explorer</a>
                  <button class="navbar-toggler position-absolute d-md-none collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#sidebarMenu" aria-controls="sidebarMenu" aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                  </button>
                  <form method="get" action="/cgi-bin/main" style="width:100%;"><input class="form-control form-control-dark w-100 rounded-0 border-0" type="text" name="q" placeholder="Search repos" aria-label="Search"></form>
                  <div class="navbar-nav flex-row">
                    <div class="nav-item text-nowrap">
                      <a class="nav-link px-3 active" href="/cgi-bin/repo?id=z4WW9U9uLHmYSFF8FKftH8GsPZUHa">eth2.0-specs</a>
                    </div>
                  </div>
                </header>
                <div class="container-fluid">
                  <div class="row">
                    <nav id="sidebarMenu" class="col-md-3 col-lg-2 d-md-block bg-dark sidebar collapse">
                      <div class="position-sticky pt-3 sidebar-sticky">
                        <ul class="nav flex-column">
                          <li class="nav-item">
                            <a class="nav-link" href="/cgi-bin/repo?id=z4WW9U9uLHmYSFF8FKftH8GsPZUHa">
                              <i class="align-text-bottom fa-solid fa-info"></i>
                              Info
                            </a>
                          </li>
                          <li class="nav-item">
                            <a class="nav-link" href="/cgi-bin/repo?id=z4WW9U9uLHmYSFF8FKftH8GsPZUHa&issue=list">
                              <i class="align-text-bottom fa-solid fa-layer-group"></i>
                              Issues
                            </a>
                          </li>
                          <li class="nav-item">
                            <a class="nav-link" href="/cgi-bin/repo?id=z4WW9U9uLHmYSFF8FKftH8GsPZUHa&patch=list">
                              <i class="align-text-bottom fa-solid fa-vest-patches"></i>
                              Patches
                            </a>
                          </li>
                          <li class="nav-item">
                            <a class="nav-link" href="/cgi-bin/repo?id=z4WW9U9uLHmYSFF8FKftH8GsPZUHa&wallet=list">
                              <i class="align-text-bottom fa-solid fa-wallet"></i>
                              Wallets
                            </a>
                          </li>
                          <li class="nav-item">
                            <a class="nav-link active" href="/cgi-bin/repo?id=z4WW9U9uLHmYSFF8FKftH8GsPZUHa&source=.">
                              <i class="align-text-bottom fa-solid fa-code"></i>
                              Source
                            </a>
                          </li>
                        <h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted text-uppercase">
                          <span></span>
                        </h6>
                        <ul class="nav flex-column mb-2">
                        
    <h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-1 mb-1 text-muted text-uppercase">
      <span>Source</span>
    </h6>
    <li><a class="nav-link py-0" style="padding-left:16px;" href="/cgi-bin/repo?id=z4WW9U9uLHmYSFF8FKftH8GsPZUHa&source=.circleci"><i class="fa-solid fa-folder" style="color:#f0c040;"></i> .circleci</a></li><li><a class="nav-link py-0" style="padding-left:16px;" href="/cgi-bin/repo?id=z4WW9U9uLHmYSFF8FKftH8GsPZUHa&source=configs"><i class="fa-solid fa-folder" style="color:#f0c040;"></i> configs</a></li><li><a class="nav-link py-0" style="padding-left:16px;" href="/cgi-bin/repo?id=z4WW9U9uLHmYSFF8FKftH8GsPZUHa&source=scripts"><i class="fa-solid fa-folder" style="color:#f0c040;"></i> scripts</a></li><li><a class="nav-link py-0" style="padding-left:16px;" href="/cgi-bin/repo?id=z4WW9U9uLHmYSFF8FKftH8GsPZUHa&source=specs"><i class="fa-solid fa-folder-open" style="color:#f0c040;"></i> specs</a></li><li><a class="nav-link py-0" style="padding-left:32px;" href="/cgi-bin/repo?id=z4WW9U9uLHmYSFF8FKftH8GsPZUHa&source=specs%2Fcore"><i class="fa-solid fa-folder-open" style="color:#f0c040;"></i> core</a></li><li><a class="nav-link py-0" style="padding-left:48px;" href="/cgi-bin/repo?id=z4WW9U9uLHmYSFF8FKftH8GsPZUHa&file=specs%2Fcore%2F0_beacon-chain.md"><i class="fa-solid fa-file" style="color:#888;"></i> 0_beacon-chain.md</a></li><li><a class="nav-link py-0" style="padding-left:48px;" href="/cgi-bin/repo?id=z4WW9U9uLHmYSFF8FKftH8GsPZUHa&file=specs%2Fcore%2F0_deposit-contract.md"><i class="fa-solid fa-file" style="color:#888;"></i> 0_deposit-contract.md</a></li><li><a class="nav-link py-0" style="padding-left:48px;" href="/cgi-bin/repo?id=z4WW9U9uLHmYSFF8FKftH8GsPZUHa&file=specs%2Fcore%2F0_fork-choice.md"><i class="fa-solid fa-file" style="color:#888;"></i> 0_fork-choice.md</a></li><li><a class="nav-link py-0 active" style="padding-left:48px;" href="/cgi-bin/repo?id=z4WW9U9uLHmYSFF8FKftH8GsPZUHa&file=specs%2Fcore%2F1_custody-game.md"><i class="fa-solid fa-file" style="color:#888;"></i> 1_custody-game.md</a></li><li><a class="nav-link py-0" style="padding-left:48px;" href="/cgi-bin/repo?id=z4WW9U9uLHmYSFF8FKftH8GsPZUHa&file=specs%2Fcore%2F1_shard-data-chains.md"><i class="fa-solid fa-file" style="color:#888;"></i> 1_shard-data-chains.md</a></li><li><a class="nav-link py-0" style="padding-left:32px;" href="/cgi-bin/repo?id=z4WW9U9uLHmYSFF8FKftH8GsPZUHa&source=specs%2Flight_client"><i class="fa-solid fa-folder" style="color:#f0c040;"></i> light_client</a></li><li><a class="nav-link py-0" style="padding-left:32px;" href="/cgi-bin/repo?id=z4WW9U9uLHmYSFF8FKftH8GsPZUHa&source=specs%2Fnetworking"><i class="fa-solid fa-folder" style="color:#f0c040;"></i> networking</a></li><li><a class="nav-link py-0" style="padding-left:32px;" href="/cgi-bin/repo?id=z4WW9U9uLHmYSFF8FKftH8GsPZUHa&source=specs%2Ftest_formats"><i class="fa-solid fa-folder" style="color:#f0c040;"></i> test_formats</a></li><li><a class="nav-link py-0" style="padding-left:32px;" href="/cgi-bin/repo?id=z4WW9U9uLHmYSFF8FKftH8GsPZUHa&source=specs%2Fvalidator"><i class="fa-solid fa-folder" style="color:#f0c040;"></i> validator</a></li><li><a class="nav-link py-0" style="padding-left:32px;" href="/cgi-bin/repo?id=z4WW9U9uLHmYSFF8FKftH8GsPZUHa&file=specs%2Fbls_signature.md"><i class="fa-solid fa-file" style="color:#888;"></i> bls_signature.md</a></li><li><a class="nav-link py-0" style="padding-left:32px;" href="/cgi-bin/repo?id=z4WW9U9uLHmYSFF8FKftH8GsPZUHa&file=specs%2Fsimple-serialize.md"><i class="fa-solid fa-file" style="color:#888;"></i> simple-serialize.md</a></li><li><a class="nav-link py-0" style="padding-left:16px;" href="/cgi-bin/repo?id=z4WW9U9uLHmYSFF8FKftH8GsPZUHa&source=test_generators"><i class="fa-solid fa-folder" style="color:#f0c040;"></i> test_generators</a></li><li><a class="nav-link py-0" style="padding-left:16px;" href="/cgi-bin/repo?id=z4WW9U9uLHmYSFF8FKftH8GsPZUHa&source=test_libs"><i class="fa-solid fa-folder" style="color:#f0c040;"></i> test_libs</a></li><li><a class="nav-link py-0" style="padding-left:16px;" href="/cgi-bin/repo?id=z4WW9U9uLHmYSFF8FKftH8GsPZUHa&file=.gitignore"><i class="fa-solid fa-file" style="color:#888;"></i> .gitignore</a></li><li><a class="nav-link py-0" style="padding-left:16px;" href="/cgi-bin/repo?id=z4WW9U9uLHmYSFF8FKftH8GsPZUHa&file=LICENSE"><i class="fa-solid fa-file" style="color:#888;"></i> LICENSE</a></li><li><a class="nav-link py-0" style="padding-left:16px;" href="/cgi-bin/repo?id=z4WW9U9uLHmYSFF8FKftH8GsPZUHa&file=Makefile"><i class="fa-solid fa-file" style="color:#888;"></i> Makefile</a></li><li><a class="nav-link py-0" style="padding-left:16px;" href="/cgi-bin/repo?id=z4WW9U9uLHmYSFF8FKftH8GsPZUHa&file=README.md"><i class="fa-solid fa-file" style="color:#888;"></i> README.md</a></li>
    
                        </ul>
                      </div>
                    </nav>
                <main class="col-md-9 ms-sm-auto col-lg-10">
                  <div class="container px-1 py-3">
        
<div class="mb-2" style="font-size:1.1rem;"><a href="/cgi-bin/repo?id=z4WW9U9uLHmYSFF8FKftH8GsPZUHa&source=.">/</a> <a href="/cgi-bin/repo?id=z4WW9U9uLHmYSFF8FKftH8GsPZUHa&source=specs">specs</a> / <a href="/cgi-bin/repo?id=z4WW9U9uLHmYSFF8FKftH8GsPZUHa&source=specs%2Fcore">core</a> / 1_custody-game.md</div>
        <div class="list-group">
        <div class="list-group-item">
        <div class="mb-2" style="font-weight:bold;"><i class="fa-solid fa-file"></i> 1_custody-game.md</div>
        <pre style="margin:0; font-size:0.85rem; overflow-x:auto; color:#fafafa;"><span style="color:#666; user-select:none;">  1</span>  # Ethereum 2.0 Phase 1 -- Custody Game
<span style="color:#666; user-select:none;">  2</span>  
<span style="color:#666; user-select:none;">  3</span>  **NOTICE**: This spec is a work-in-progress for researchers and implementers.
<span style="color:#666; user-select:none;">  4</span>  
<span style="color:#666; user-select:none;">  5</span>  ## Table of contents
<span style="color:#666; user-select:none;">  6</span>  
<span style="color:#666; user-select:none;">  7</span>  &lt;!-- TOC --&gt;
<span style="color:#666; user-select:none;">  8</span>  
<span style="color:#666; user-select:none;">  9</span>  - [Ethereum 2.0 Phase 1 -- Custody Game](#ethereum-20-phase-1----custody-game)
<span style="color:#666; user-select:none;"> 10</span>      - [Table of contents](#table-of-contents)
<span style="color:#666; user-select:none;"> 11</span>      - [Introduction](#introduction)
<span style="color:#666; user-select:none;"> 12</span>      - [Terminology](#terminology)
<span style="color:#666; user-select:none;"> 13</span>      - [Constants](#constants)
<span style="color:#666; user-select:none;"> 14</span>          - [Misc](#misc)
<span style="color:#666; user-select:none;"> 15</span>          - [Time parameters](#time-parameters)
<span style="color:#666; user-select:none;"> 16</span>          - [Max operations per block](#max-operations-per-block)
<span style="color:#666; user-select:none;"> 17</span>          - [Signature domains](#signature-domains)
<span style="color:#666; user-select:none;"> 18</span>      - [Data structures](#data-structures)
<span style="color:#666; user-select:none;"> 19</span>          - [Custody objects](#custody-objects)
<span style="color:#666; user-select:none;"> 20</span>              - [`CustodyChunkChallenge`](#custodychunkchallenge)
<span style="color:#666; user-select:none;"> 21</span>              - [`CustodyBitChallenge`](#custodybitchallenge)
<span style="color:#666; user-select:none;"> 22</span>              - [`CustodyChunkChallengeRecord`](#custodychunkchallengerecord)
<span style="color:#666; user-select:none;"> 23</span>              - [`CustodyBitChallengeRecord`](#custodybitchallengerecord)
<span style="color:#666; user-select:none;"> 24</span>              - [`CustodyResponse`](#custodyresponse)
<span style="color:#666; user-select:none;"> 25</span>              - [`CustodyKeyReveal`](#custodykeyreveal)
<span style="color:#666; user-select:none;"> 26</span>          - [Phase 0 container updates](#phase-0-container-updates)
<span style="color:#666; user-select:none;"> 27</span>              - [`Validator`](#validator)
<span style="color:#666; user-select:none;"> 28</span>              - [`BeaconState`](#beaconstate)
<span style="color:#666; user-select:none;"> 29</span>              - [`BeaconBlockBody`](#beaconblockbody)
<span style="color:#666; user-select:none;"> 30</span>      - [Helpers](#helpers)
<span style="color:#666; user-select:none;"> 31</span>          - [`typeof`](#typeof)
<span style="color:#666; user-select:none;"> 32</span>          - [`empty`](#empty)
<span style="color:#666; user-select:none;"> 33</span>          - [`get_crosslink_chunk_count`](#get_crosslink_chunk_count)
<span style="color:#666; user-select:none;"> 34</span>          - [`get_custody_chunk_bit`](#get_custody_chunk_bit)
<span style="color:#666; user-select:none;"> 35</span>          - [`epoch_to_custody_period`](#epoch_to_custody_period)
<span style="color:#666; user-select:none;"> 36</span>          - [`replace_empty_or_append`](#replace_empty_or_append)
<span style="color:#666; user-select:none;"> 37</span>          - [`verify_custody_key`](#verify_custody_key)
<span style="color:#666; user-select:none;"> 38</span>      - [Per-block processing](#per-block-processing)
<span style="color:#666; user-select:none;"> 39</span>          - [Operations](#operations)
<span style="color:#666; user-select:none;"> 40</span>              - [Custody reveals](#custody-reveals)
<span style="color:#666; user-select:none;"> 41</span>              - [Chunk challenges](#chunk-challenges)
<span style="color:#666; user-select:none;"> 42</span>              - [Bit challenges](#bit-challenges)
<span style="color:#666; user-select:none;"> 43</span>              - [Custody responses](#custody-responses)
<span style="color:#666; user-select:none;"> 44</span>      - [Per-epoch processing](#per-epoch-processing)
<span style="color:#666; user-select:none;"> 45</span>  
<span style="color:#666; user-select:none;"> 46</span>  &lt;!-- /TOC --&gt;
<span style="color:#666; user-select:none;"> 47</span>  
<span style="color:#666; user-select:none;"> 48</span>  ## Introduction
<span style="color:#666; user-select:none;"> 49</span>  
<span style="color:#666; user-select:none;"> 50</span>  This document details the beacon chain additions and changes in Phase 1 of Ethereum 2.0 to support the shard data custody game, building upon the [phase 0](0_beacon-chain.md) specification.
<span style="color:#666; user-select:none;"> 51</span>  
<span style="color:#666; user-select:none;"> 52</span>  ## Terminology
<span style="color:#666; user-select:none;"> 53</span>  
<span style="color:#666; user-select:none;"> 54</span>  * **Custody game**:
<span style="color:#666; user-select:none;"> 55</span>  * **Custody period**:
<span style="color:#666; user-select:none;"> 56</span>  * **Custody chunk**:
<span style="color:#666; user-select:none;"> 57</span>  * **Custody chunk bit**:
<span style="color:#666; user-select:none;"> 58</span>  * **Custody chunk challenge**:
<span style="color:#666; user-select:none;"> 59</span>  * **Custody bit**:
<span style="color:#666; user-select:none;"> 60</span>  * **Custody bit challenge**:
<span style="color:#666; user-select:none;"> 61</span>  * **Custody key**:
<span style="color:#666; user-select:none;"> 62</span>  * **Custody key reveal**:
<span style="color:#666; user-select:none;"> 63</span>  * **Custody key mask**:
<span style="color:#666; user-select:none;"> 64</span>  * **Custody response**:
<span style="color:#666; user-select:none;"> 65</span>  * **Custody response deadline**:
<span style="color:#666; user-select:none;"> 66</span>  
<span style="color:#666; user-select:none;"> 67</span>  ## Constants
<span style="color:#666; user-select:none;"> 68</span>  
<span style="color:#666; user-select:none;"> 69</span>  ### Misc
<span style="color:#666; user-select:none;"> 70</span>  
<span style="color:#666; user-select:none;"> 71</span>  | Name | Value |
<span style="color:#666; user-select:none;"> 72</span>  | - | - |
<span style="color:#666; user-select:none;"> 73</span>  | `BYTES_PER_SHARD_BLOCK` | `2**14` (= 16,384) |
<span style="color:#666; user-select:none;"> 74</span>  | `BYTES_PER_CUSTODY_CHUNK` | `2**9` (= 512) |
<span style="color:#666; user-select:none;"> 75</span>  | `MINOR_REWARD_QUOTIENT` | `2**8` (= 256) |
<span style="color:#666; user-select:none;"> 76</span>  
<span style="color:#666; user-select:none;"> 77</span>  ### Time parameters
<span style="color:#666; user-select:none;"> 78</span>  
<span style="color:#666; user-select:none;"> 79</span>  | Name | Value | Unit | Duration |
<span style="color:#666; user-select:none;"> 80</span>  | - | - | :-: | :-: |
<span style="color:#666; user-select:none;"> 81</span>  | `MAX_CHUNK_CHALLENGE_DELAY` | `2**11` (= 2,048) | epochs | ~9 days |
<span style="color:#666; user-select:none;"> 82</span>  | `EPOCHS_PER_CUSTODY_PERIOD` | `2**11` (= 2,048) | epochs | ~9 days |
<span style="color:#666; user-select:none;"> 83</span>  | `CUSTODY_RESPONSE_DEADLINE` | `2**14` (= 16,384) | epochs | ~73 days |
<span style="color:#666; user-select:none;"> 84</span>  
<span style="color:#666; user-select:none;"> 85</span>  ### Max operations per block
<span style="color:#666; user-select:none;"> 86</span>  
<span style="color:#666; user-select:none;"> 87</span>  | Name | Value |
<span style="color:#666; user-select:none;"> 88</span>  | - | - |
<span style="color:#666; user-select:none;"> 89</span>  | `MAX_CUSTODY_KEY_REVEALS` | `2**4` (= 16) |
<span style="color:#666; user-select:none;"> 90</span>  | `MAX_CUSTODY_CHUNK_CHALLENGES` | `2**2` (= 4) |
<span style="color:#666; user-select:none;"> 91</span>  | `MAX_CUSTODY_BIT_CHALLENGES` | `2**2` (= 4) |
<span style="color:#666; user-select:none;"> 92</span>  | `MAX_CUSTODY_RESPONSES` | `2**5` (= 32) |
<span style="color:#666; user-select:none;"> 93</span>  
<span style="color:#666; user-select:none;"> 94</span>  ### Signature domains
<span style="color:#666; user-select:none;"> 95</span>  
<span style="color:#666; user-select:none;"> 96</span>  | Name | Value |
<span style="color:#666; user-select:none;"> 97</span>  | - | - |
<span style="color:#666; user-select:none;"> 98</span>  | `DOMAIN_CUSTODY_KEY_REVEAL` | `6` |
<span style="color:#666; user-select:none;"> 99</span>  | `DOMAIN_CUSTODY_BIT_CHALLENGE` | `7` |
<span style="color:#666; user-select:none;">100</span>  
<span style="color:#666; user-select:none;">101</span>  ## Data structures
<span style="color:#666; user-select:none;">102</span>  
<span style="color:#666; user-select:none;">103</span>  ### Custody objects
<span style="color:#666; user-select:none;">104</span>  
<span style="color:#666; user-select:none;">105</span>  #### `CustodyChunkChallenge`
<span style="color:#666; user-select:none;">106</span>  
<span style="color:#666; user-select:none;">107</span>  ```python
<span style="color:#666; user-select:none;">108</span>  {
<span style="color:#666; user-select:none;">109</span>      &#x27;responder_index&#x27;: ValidatorIndex,
<span style="color:#666; user-select:none;">110</span>      &#x27;attestation&#x27;: Attestation,
<span style="color:#666; user-select:none;">111</span>      &#x27;chunk_index&#x27;: &#x27;uint64&#x27;,
<span style="color:#666; user-select:none;">112</span>  }
<span style="color:#666; user-select:none;">113</span>  ```
<span style="color:#666; user-select:none;">114</span>  
<span style="color:#666; user-select:none;">115</span>  #### `CustodyBitChallenge`
<span style="color:#666; user-select:none;">116</span>  
<span style="color:#666; user-select:none;">117</span>  ```python
<span style="color:#666; user-select:none;">118</span>  {
<span style="color:#666; user-select:none;">119</span>      &#x27;responder_index&#x27;: ValidatorIndex,
<span style="color:#666; user-select:none;">120</span>      &#x27;attestation&#x27;: Attestation,
<span style="color:#666; user-select:none;">121</span>      &#x27;challenger_index&#x27;: ValidatorIndex,
<span style="color:#666; user-select:none;">122</span>      &#x27;responder_key&#x27;: BLSSignature,
<span style="color:#666; user-select:none;">123</span>      &#x27;chunk_bits&#x27;: Bitfield,
<span style="color:#666; user-select:none;">124</span>      &#x27;signature&#x27;: BLSSignature,
<span style="color:#666; user-select:none;">125</span>  }
<span style="color:#666; user-select:none;">126</span>  ```
<span style="color:#666; user-select:none;">127</span>  
<span style="color:#666; user-select:none;">128</span>  #### `CustodyChunkChallengeRecord`
<span style="color:#666; user-select:none;">129</span>  
<span style="color:#666; user-select:none;">130</span>  ```python
<span style="color:#666; user-select:none;">131</span>  {
<span style="color:#666; user-select:none;">132</span>      &#x27;challenge_index&#x27;: &#x27;uint64&#x27;,
<span style="color:#666; user-select:none;">133</span>      &#x27;challenger_index&#x27;: ValidatorIndex,
<span style="color:#666; user-select:none;">134</span>      &#x27;responder_index&#x27;: ValidatorIndex,
<span style="color:#666; user-select:none;">135</span>      &#x27;deadline&#x27;: Epoch,
<span style="color:#666; user-select:none;">136</span>      &#x27;crosslink_data_root&#x27;: Hash,
<span style="color:#666; user-select:none;">137</span>      &#x27;depth&#x27;: &#x27;uint64&#x27;,
<span style="color:#666; user-select:none;">138</span>      &#x27;chunk_index&#x27;: &#x27;uint64&#x27;,
<span style="color:#666; user-select:none;">139</span>  }
<span style="color:#666; user-select:none;">140</span>  ```
<span style="color:#666; user-select:none;">141</span>  
<span style="color:#666; user-select:none;">142</span>  #### `CustodyBitChallengeRecord`
<span style="color:#666; user-select:none;">143</span>  
<span style="color:#666; user-select:none;">144</span>  ```python
<span style="color:#666; user-select:none;">145</span>  {
<span style="color:#666; user-select:none;">146</span>      &#x27;challenge_index&#x27;: &#x27;uint64&#x27;,
<span style="color:#666; user-select:none;">147</span>      &#x27;challenger_index&#x27;: ValidatorIndex,
<span style="color:#666; user-select:none;">148</span>      &#x27;responder_index&#x27;: ValidatorIndex,
<span style="color:#666; user-select:none;">149</span>      &#x27;deadline&#x27;: Epoch,
<span style="color:#666; user-select:none;">150</span>      &#x27;crosslink_data_root&#x27;: Hash,
<span style="color:#666; user-select:none;">151</span>      &#x27;chunk_bits&#x27;: Bitfield,
<span style="color:#666; user-select:none;">152</span>      &#x27;responder_key&#x27;: BLSSignature,
<span style="color:#666; user-select:none;">153</span>  }
<span style="color:#666; user-select:none;">154</span>  ```
<span style="color:#666; user-select:none;">155</span>  
<span style="color:#666; user-select:none;">156</span>  #### `CustodyResponse`
<span style="color:#666; user-select:none;">157</span>  
<span style="color:#666; user-select:none;">158</span>  ```python
<span style="color:#666; user-select:none;">159</span>  {
<span style="color:#666; user-select:none;">160</span>      &#x27;challenge_index&#x27;: &#x27;uint64&#x27;,
<span style="color:#666; user-select:none;">161</span>      &#x27;chunk_index&#x27;: &#x27;uint64&#x27;,
<span style="color:#666; user-select:none;">162</span>      &#x27;chunk&#x27;: [&#x27;byte&#x27;, BYTES_PER_CUSTODY_CHUNK],
<span style="color:#666; user-select:none;">163</span>      &#x27;branch&#x27;: [Hash],
<span style="color:#666; user-select:none;">164</span>  }
<span style="color:#666; user-select:none;">165</span>  ```
<span style="color:#666; user-select:none;">166</span>  
<span style="color:#666; user-select:none;">167</span>  #### `CustodyKeyReveal`
<span style="color:#666; user-select:none;">168</span>  
<span style="color:#666; user-select:none;">169</span>  ```python
<span style="color:#666; user-select:none;">170</span>  {
<span style="color:#666; user-select:none;">171</span>      &#x27;revealer_index&#x27;: ValidatorIndex,
<span style="color:#666; user-select:none;">172</span>      &#x27;period&#x27;: &#x27;uint64&#x27;,
<span style="color:#666; user-select:none;">173</span>      &#x27;key&#x27;: BLSSignature,
<span style="color:#666; user-select:none;">174</span>      &#x27;masker_index&#x27;: ValidatorIndex,
<span style="color:#666; user-select:none;">175</span>      &#x27;mask&#x27;: Hash,
<span style="color:#666; user-select:none;">176</span>  }
<span style="color:#666; user-select:none;">177</span>  ```
<span style="color:#666; user-select:none;">178</span>  
<span style="color:#666; user-select:none;">179</span>  ### Phase 0 container updates
<span style="color:#666; user-select:none;">180</span>  
<span style="color:#666; user-select:none;">181</span>  Add the following fields to the end of the specified container objects. Fields with underlying type `uint64` are initialized to `0` and list fields are initialized to `[]`.
<span style="color:#666; user-select:none;">182</span>  
<span style="color:#666; user-select:none;">183</span>  #### `Validator`
<span style="color:#666; user-select:none;">184</span>  
<span style="color:#666; user-select:none;">185</span>  ```python
<span style="color:#666; user-select:none;">186</span>      &#x27;custody_reveal_index&#x27;: &#x27;uint64&#x27;,
<span style="color:#666; user-select:none;">187</span>      &#x27;max_reveal_lateness&#x27;: &#x27;uint64&#x27;,
<span style="color:#666; user-select:none;">188</span>  ```
<span style="color:#666; user-select:none;">189</span>  
<span style="color:#666; user-select:none;">190</span>  #### `BeaconState`
<span style="color:#666; user-select:none;">191</span>  
<span style="color:#666; user-select:none;">192</span>  ```python
<span style="color:#666; user-select:none;">193</span>      &#x27;custody_chunk_challenge_records&#x27;: [CustodyChunkChallengeRecord],
<span style="color:#666; user-select:none;">194</span>      &#x27;custody_bit_challenge_records&#x27;: [CustodyBitChallengeRecord],
<span style="color:#666; user-select:none;">195</span>      &#x27;custody_challenge_index&#x27;: &#x27;uint64&#x27;,
<span style="color:#666; user-select:none;">196</span>  ```
<span style="color:#666; user-select:none;">197</span>  
<span style="color:#666; user-select:none;">198</span>  #### `BeaconBlockBody`
<span style="color:#666; user-select:none;">199</span>  
<span style="color:#666; user-select:none;">200</span>  ```python
<span style="color:#666; user-select:none;">201</span>      &#x27;custody_key_reveals&#x27;: [CustodyKeyReveal],
<span style="color:#666; user-select:none;">202</span>      &#x27;custody_chunk_challenges&#x27;: [CustodyChunkChallenge],
<span style="color:#666; user-select:none;">203</span>      &#x27;custody_bit_challenges&#x27;: [CustodyBitChallenge],
<span style="color:#666; user-select:none;">204</span>      &#x27;custody_responses&#x27;: [CustodyResponse],
<span style="color:#666; user-select:none;">205</span>  ```
<span style="color:#666; user-select:none;">206</span>  
<span style="color:#666; user-select:none;">207</span>  ## Helpers
<span style="color:#666; user-select:none;">208</span>  
<span style="color:#666; user-select:none;">209</span>  ### `typeof`
<span style="color:#666; user-select:none;">210</span>  
<span style="color:#666; user-select:none;">211</span>  The `typeof` function accepts and SSZ object as a single input and returns the corresponding SSZ type.
<span style="color:#666; user-select:none;">212</span>  
<span style="color:#666; user-select:none;">213</span>  ### `empty`
<span style="color:#666; user-select:none;">214</span>  
<span style="color:#666; user-select:none;">215</span>  The `empty` function accepts and SSZ type as input and returns an object of that type with all fields initialized to default values.
<span style="color:#666; user-select:none;">216</span>  
<span style="color:#666; user-select:none;">217</span>  ### `get_crosslink_chunk_count`
<span style="color:#666; user-select:none;">218</span>  
<span style="color:#666; user-select:none;">219</span>  ```python
<span style="color:#666; user-select:none;">220</span>  def get_custody_chunk_count(attestation: Attestation) -&gt; int:
<span style="color:#666; user-select:none;">221</span>      crosslink_start_epoch = attestation.data.latest_crosslink.epoch
<span style="color:#666; user-select:none;">222</span>      crosslink_end_epoch = slot_to_epoch(attestation.data.slot)
<span style="color:#666; user-select:none;">223</span>      crosslink_crosslink_length = min(MAX_CROSSLINK_EPOCHS, end_epoch - start_epoch)
<span style="color:#666; user-select:none;">224</span>      chunks_per_epoch = 2 * BYTES_PER_SHARD_BLOCK * SLOTS_PER_EPOCH // BYTES_PER_CUSTODY_CHUNK
<span style="color:#666; user-select:none;">225</span>      return crosslink_crosslink_length * chunks_per_epoch
<span style="color:#666; user-select:none;">226</span>  ```
<span style="color:#666; user-select:none;">227</span>  
<span style="color:#666; user-select:none;">228</span>  ### `get_custody_chunk_bit`
<span style="color:#666; user-select:none;">229</span>  
<span style="color:#666; user-select:none;">230</span>  ```python
<span style="color:#666; user-select:none;">231</span>  def get_custody_chunk_bit(key: BLSSignature, chunk: bytes) -&gt; bool:
<span style="color:#666; user-select:none;">232</span>      # TODO: Replace with something MPC-friendly, e.g. the Legendre symbol
<span style="color:#666; user-select:none;">233</span>      return get_bitfield_bit(hash(challenge.responder_key + chunk), 0)
<span style="color:#666; user-select:none;">234</span>  ```
<span style="color:#666; user-select:none;">235</span>  
<span style="color:#666; user-select:none;">236</span>  ### `epoch_to_custody_period`
<span style="color:#666; user-select:none;">237</span>  
<span style="color:#666; user-select:none;">238</span>  ```python
<span style="color:#666; user-select:none;">239</span>  def epoch_to_custody_period(epoch: Epoch) -&gt; int:
<span style="color:#666; user-select:none;">240</span>      return epoch // EPOCHS_PER_CUSTODY_PERIOD
<span style="color:#666; user-select:none;">241</span>  ```
<span style="color:#666; user-select:none;">242</span>  
<span style="color:#666; user-select:none;">243</span>  ### `replace_empty_or_append`
<span style="color:#666; user-select:none;">244</span>  
<span style="color:#666; user-select:none;">245</span>  ```python
<span style="color:#666; user-select:none;">246</span>  def replace_empty_or_append(list: List[Any], new_element: Any) -&gt; int:
<span style="color:#666; user-select:none;">247</span>      for i in range(len(list)):
<span style="color:#666; user-select:none;">248</span>          if list[i] == empty(typeof(new_element)):
<span style="color:#666; user-select:none;">249</span>              list[i] = new_element
<span style="color:#666; user-select:none;">250</span>              return i
<span style="color:#666; user-select:none;">251</span>      list.append(new_element)
<span style="color:#666; user-select:none;">252</span>      return len(list) - 1
<span style="color:#666; user-select:none;">253</span>  ```
<span style="color:#666; user-select:none;">254</span>  
<span style="color:#666; user-select:none;">255</span>  ### `verify_custody_key`
<span style="color:#666; user-select:none;">256</span>  
<span style="color:#666; user-select:none;">257</span>  ```python
<span style="color:#666; user-select:none;">258</span>  def verify_custody_key(state: BeaconState, reveal: CustodyKeyReveal) -&gt; bool:
<span style="color:#666; user-select:none;">259</span>      # Case 1: non-masked non-punitive non-early reveal
<span style="color:#666; user-select:none;">260</span>      pubkeys = [state.validator_registry[reveal.revealer_index].pubkey]
<span style="color:#666; user-select:none;">261</span>      message_hashes = [hash_tree_root(reveal.period)]
<span style="color:#666; user-select:none;">262</span>  
<span style="color:#666; user-select:none;">263</span>      # Case 2: masked punitive early reveal
<span style="color:#666; user-select:none;">264</span>      # Masking prevents proposer stealing the whistleblower reward
<span style="color:#666; user-select:none;">265</span>      # Secure under the aggregate extraction infeasibility assumption
<span style="color:#666; user-select:none;">266</span>      # See pages 11-12 of https://crypto.stanford.edu/~dabo/pubs/papers/aggreg.pdf
<span style="color:#666; user-select:none;">267</span>      if reveal.mask != ZERO_HASH:
<span style="color:#666; user-select:none;">268</span>          pubkeys.append(state.validator_registry[reveal.masker_index].pubkey)
<span style="color:#666; user-select:none;">269</span>          message_hashes.append(reveal.mask)
<span style="color:#666; user-select:none;">270</span>  
<span style="color:#666; user-select:none;">271</span>      return bls_verify_multiple(
<span style="color:#666; user-select:none;">272</span>          pubkeys=pubkeys,
<span style="color:#666; user-select:none;">273</span>          message_hashes=message_hashes,
<span style="color:#666; user-select:none;">274</span>          signature=reveal.key,
<span style="color:#666; user-select:none;">275</span>          domain=get_domain(
<span style="color:#666; user-select:none;">276</span>              fork=state.fork,
<span style="color:#666; user-select:none;">277</span>              epoch=reveal.period * EPOCHS_PER_CUSTODY_PERIOD,
<span style="color:#666; user-select:none;">278</span>              domain_type=DOMAIN_CUSTODY_KEY_REVEAL,
<span style="color:#666; user-select:none;">279</span>          ),
<span style="color:#666; user-select:none;">280</span>      )
<span style="color:#666; user-select:none;">281</span>  ```
<span style="color:#666; user-select:none;">282</span>  
<span style="color:#666; user-select:none;">283</span>  ## Per-block processing
<span style="color:#666; user-select:none;">284</span>  
<span style="color:#666; user-select:none;">285</span>  ### Operations
<span style="color:#666; user-select:none;">286</span>  
<span style="color:#666; user-select:none;">287</span>  Add the following operations to the per-block processing, in order the given below and after all other operations in phase 0.
<span style="color:#666; user-select:none;">288</span>  
<span style="color:#666; user-select:none;">289</span>  #### Custody reveals
<span style="color:#666; user-select:none;">290</span>  
<span style="color:#666; user-select:none;">291</span>  Verify that `len(block.body.custody_key_reveals) &lt;= MAX_CUSTODY_KEY_REVEALS`.
<span style="color:#666; user-select:none;">292</span>  
<span style="color:#666; user-select:none;">293</span>  For each `reveal` in `block.body.custody_key_reveals`, run the following function:
<span style="color:#666; user-select:none;">294</span>  
<span style="color:#666; user-select:none;">295</span>  ```python
<span style="color:#666; user-select:none;">296</span>  def process_custody_reveal(state: BeaconState,
<span style="color:#666; user-select:none;">297</span>                             reveal: CustodyKeyReveal) -&gt; None:
<span style="color:#666; user-select:none;">298</span>      assert verify_custody_key(state, reveal)
<span style="color:#666; user-select:none;">299</span>      revealer = state.validator_registry[reveal.revealer_index]
<span style="color:#666; user-select:none;">300</span>      current_custody_period = epoch_to_custody_period(get_current_epoch(state))
<span style="color:#666; user-select:none;">301</span>  
<span style="color:#666; user-select:none;">302</span>      # Case 1: non-masked non-punitive non-early reveal
<span style="color:#666; user-select:none;">303</span>      if reveal.mask == ZERO_HASH:
<span style="color:#666; user-select:none;">304</span>          assert reveal.period == epoch_to_custody_period(revealer.activation_epoch) + revealer.custody_reveal_index
<span style="color:#666; user-select:none;">305</span>          # Revealer is active or exited
<span style="color:#666; user-select:none;">306</span>          assert is_active_validator(revealer, get_current_epoch(state)) or revealer.exit_epoch &gt; get_current_epoch(state)
<span style="color:#666; user-select:none;">307</span>          revealer.custody_reveal_index += 1
<span style="color:#666; user-select:none;">308</span>          revealer.max_reveal_lateness = max(revealer.max_reveal_lateness, current_custody_period - reveal.period)
<span style="color:#666; user-select:none;">309</span>          proposer_index = get_beacon_proposer_index(state)
<span style="color:#666; user-select:none;">310</span>          increase_balance(state, proposer_index, base_reward(state, index) // MINOR_REWARD_QUOTIENT)
<span style="color:#666; user-select:none;">311</span>  
<span style="color:#666; user-select:none;">312</span>      # Case 2: masked punitive early reveal
<span style="color:#666; user-select:none;">313</span>      else:
<span style="color:#666; user-select:none;">314</span>          assert reveal.period &gt; current_custody_period
<span style="color:#666; user-select:none;">315</span>          assert revealer.slashed is False
<span style="color:#666; user-select:none;">316</span>          slash_validator(state, reveal.revealer_index, reveal.masker_index)
<span style="color:#666; user-select:none;">317</span>  ```
<span style="color:#666; user-select:none;">318</span>  
<span style="color:#666; user-select:none;">319</span>  #### Chunk challenges
<span style="color:#666; user-select:none;">320</span>  
<span style="color:#666; user-select:none;">321</span>  Verify that `len(block.body.custody_chunk_challenges) &lt;= MAX_CUSTODY_CHUNK_CHALLENGES`.
<span style="color:#666; user-select:none;">322</span>  
<span style="color:#666; user-select:none;">323</span>  For each `challenge` in `block.body.custody_chunk_challenges`, run the following function:
<span style="color:#666; user-select:none;">324</span>  
<span style="color:#666; user-select:none;">325</span>  ```python
<span style="color:#666; user-select:none;">326</span>  def process_chunk_challenge(state: BeaconState,
<span style="color:#666; user-select:none;">327</span>                              challenge: CustodyChunkChallenge) -&gt; None:
<span style="color:#666; user-select:none;">328</span>      # Verify the attestation
<span style="color:#666; user-select:none;">329</span>      assert verify_standalone_attestation(state, convert_to_standalone(state, challenge.attestation))
<span style="color:#666; user-select:none;">330</span>      # Verify it is not too late to challenge
<span style="color:#666; user-select:none;">331</span>      assert slot_to_epoch(challenge.attestation.data.slot) &gt;= get_current_epoch(state) - MAX_CHUNK_CHALLENGE_DELAY
<span style="color:#666; user-select:none;">332</span>      responder = state.validator_registry[challenge.responder_index]
<span style="color:#666; user-select:none;">333</span>      assert responder.exit_epoch &gt;= get_current_epoch(state) - MAX_CHUNK_CHALLENGE_DELAY
<span style="color:#666; user-select:none;">334</span>      # Verify the responder participated in the attestation
<span style="color:#666; user-select:none;">335</span>      attesters = get_attesting_indices(state, attestation.data, attestation.aggregation_bitfield)
<span style="color:#666; user-select:none;">336</span>      assert challenge.responder_index in attesters
<span style="color:#666; user-select:none;">337</span>      # Verify the challenge is not a duplicate
<span style="color:#666; user-select:none;">338</span>      for record in state.custody_chunk_challenge_records:
<span style="color:#666; user-select:none;">339</span>          assert (
<span style="color:#666; user-select:none;">340</span>              record.crosslink_data_root != challenge.attestation.data.crosslink_data_root or
<span style="color:#666; user-select:none;">341</span>              record.chunk_index != challenge.chunk_index
<span style="color:#666; user-select:none;">342</span>          )
<span style="color:#666; user-select:none;">343</span>      # Verify depth
<span style="color:#666; user-select:none;">344</span>      depth = math.log2(next_power_of_two(get_custody_chunk_count(challenge.attestation)))
<span style="color:#666; user-select:none;">345</span>      assert challenge.chunk_index &lt; 2**depth
<span style="color:#666; user-select:none;">346</span>      # Add new chunk challenge record
<span style="color:#666; user-select:none;">347</span>      new_record = CustodyChunkChallengeRecord(
<span style="color:#666; user-select:none;">348</span>          challenge_index=state.custody_challenge_index,
<span style="color:#666; user-select:none;">349</span>          challenger_index=get_beacon_proposer_index(state),
<span style="color:#666; user-select:none;">350</span>          responder_index=challenge.responder_index
<span style="color:#666; user-select:none;">351</span>          deadline=get_current_epoch(state) + CUSTODY_RESPONSE_DEADLINE,
<span style="color:#666; user-select:none;">352</span>          crosslink_data_root=challenge.attestation.data.crosslink_data_root,
<span style="color:#666; user-select:none;">353</span>          depth=depth,
<span style="color:#666; user-select:none;">354</span>          chunk_index=challenge.chunk_index,
<span style="color:#666; user-select:none;">355</span>      )
<span style="color:#666; user-select:none;">356</span>      replace_empty_or_append(state.custody_chunk_challenge_records, new_record)
<span style="color:#666; user-select:none;">357</span>  
<span style="color:#666; user-select:none;">358</span>      state.custody_challenge_index += 1
<span style="color:#666; user-select:none;">359</span>      # Postpone responder withdrawability
<span style="color:#666; user-select:none;">360</span>      responder.withdrawable_epoch = FAR_FUTURE_EPOCH
<span style="color:#666; user-select:none;">361</span>  ```
<span style="color:#666; user-select:none;">362</span>  
<span style="color:#666; user-select:none;">363</span>  #### Bit challenges
<span style="color:#666; user-select:none;">364</span>  
<span style="color:#666; user-select:none;">365</span>  Verify that `len(block.body.custody_bit_challenges) &lt;= MAX_CUSTODY_BIT_CHALLENGES`.
<span style="color:#666; user-select:none;">366</span>  
<span style="color:#666; user-select:none;">367</span>  For each `challenge` in `block.body.custody_bit_challenges`, run the following function:
<span style="color:#666; user-select:none;">368</span>  
<span style="color:#666; user-select:none;">369</span>  ```python
<span style="color:#666; user-select:none;">370</span>  def process_bit_challenge(state: BeaconState,
<span style="color:#666; user-select:none;">371</span>                            challenge: CustodyBitChallenge) -&gt; None:
<span style="color:#666; user-select:none;">372</span>      # Verify challenge signature
<span style="color:#666; user-select:none;">373</span>      challenger = state.validator_registry[challenge.challenger_index]
<span style="color:#666; user-select:none;">374</span>      assert bls_verify(
<span style="color:#666; user-select:none;">375</span>          pubkey=challenger.pubkey,
<span style="color:#666; user-select:none;">376</span>          message_hash=signing_root(challenge),
<span style="color:#666; user-select:none;">377</span>          signature=challenge.signature,
<span style="color:#666; user-select:none;">378</span>          domain=get_domain(state, get_current_epoch(state), DOMAIN_CUSTODY_BIT_CHALLENGE),
<span style="color:#666; user-select:none;">379</span>      )
<span style="color:#666; user-select:none;">380</span>      # Verify the challenger is not slashed
<span style="color:#666; user-select:none;">381</span>      assert challenger.slashed is False
<span style="color:#666; user-select:none;">382</span>      # Verify the attestation
<span style="color:#666; user-select:none;">383</span>      assert verify_standalone_attestation(state, convert_to_standalone(state, challenge.attestation))
<span style="color:#666; user-select:none;">384</span>      # Verify the attestation is eligible for challenging
<span style="color:#666; user-select:none;">385</span>      responder = state.validator_registry[challenge.responder_index]
<span style="color:#666; user-select:none;">386</span>      min_challengeable_epoch = responder.exit_epoch - EPOCHS_PER_CUSTODY_PERIOD * (1 + responder.max_reveal_lateness)
<span style="color:#666; user-select:none;">387</span>      assert min_challengeable_epoch &lt;= slot_to_epoch(challenge.attestation.data.slot)
<span style="color:#666; user-select:none;">388</span>      # Verify the responder participated in the attestation
<span style="color:#666; user-select:none;">389</span>      attesters = get_attesting_indices(state, attestation.data, attestation.aggregation_bitfield)
<span style="color:#666; user-select:none;">390</span>      assert challenge.responder_index in attesters
<span style="color:#666; user-select:none;">391</span>      # A validator can be the challenger or responder for at most one challenge at a time
<span style="color:#666; user-select:none;">392</span>      for record in state.custody_bit_challenge_records:
<span style="color:#666; user-select:none;">393</span>          assert record.challenger_index != challenge.challenger_index
<span style="color:#666; user-select:none;">394</span>          assert record.responder_index != challenge.responder_index
<span style="color:#666; user-select:none;">395</span>      # Verify the responder key
<span style="color:#666; user-select:none;">396</span>      assert verify_custody_key(state, CustodyKeyReveal(
<span style="color:#666; user-select:none;">397</span>          revealer_index=challenge.responder_index,
<span style="color:#666; user-select:none;">398</span>          period=epoch_to_custody_period(slot_to_epoch(attestation.data.slot)),
<span style="color:#666; user-select:none;">399</span>          key=challenge.responder_key,
<span style="color:#666; user-select:none;">400</span>          masker_index=0,
<span style="color:#666; user-select:none;">401</span>          mask=ZERO_HASH,
<span style="color:#666; user-select:none;">402</span>      ))
<span style="color:#666; user-select:none;">403</span>      # Verify the chunk count
<span style="color:#666; user-select:none;">404</span>      chunk_count = get_custody_chunk_count(challenge.attestation)
<span style="color:#666; user-select:none;">405</span>      assert verify_bitfield(challenge.chunk_bits, chunk_count)
<span style="color:#666; user-select:none;">406</span>      # Verify the xor of the chunk bits does not equal the custody bit
<span style="color:#666; user-select:none;">407</span>      chunk_bits_xor = 0b0
<span style="color:#666; user-select:none;">408</span>      for i in range(chunk_count):
<span style="color:#666; user-select:none;">409</span>          chunk_bits_xor ^ get_bitfield_bit(challenge.chunk_bits, i)
<span style="color:#666; user-select:none;">410</span>      custody_bit = get_bitfield_bit(attestation.custody_bitfield, attesters.index(responder_index))
<span style="color:#666; user-select:none;">411</span>      assert custody_bit != chunk_bits_xor
<span style="color:#666; user-select:none;">412</span>      # Add new bit challenge record
<span style="color:#666; user-select:none;">413</span>      new_record = CustodyBitChallengeRecord(
<span style="color:#666; user-select:none;">414</span>          challenge_index=state.custody_challenge_index,
<span style="color:#666; user-select:none;">415</span>          challenger_index=challenge.challenger_index,
<span style="color:#666; user-select:none;">416</span>          responder_index=challenge.responder_index,
<span style="color:#666; user-select:none;">417</span>          deadline=get_current_epoch(state) + CUSTODY_RESPONSE_DEADLINE
<span style="color:#666; user-select:none;">418</span>          crosslink_data_root=challenge.attestation.crosslink_data_root,
<span style="color:#666; user-select:none;">419</span>          chunk_bits=challenge.chunk_bits,
<span style="color:#666; user-select:none;">420</span>          responder_key=challenge.responder_key,
<span style="color:#666; user-select:none;">421</span>      )
<span style="color:#666; user-select:none;">422</span>      replace_empty_or_append(state.custody_bit_challenge_records, new_record)
<span style="color:#666; user-select:none;">423</span>      state.custody_challenge_index += 1
<span style="color:#666; user-select:none;">424</span>      # Postpone responder withdrawability
<span style="color:#666; user-select:none;">425</span>      responder.withdrawable_epoch = FAR_FUTURE_EPOCH
<span style="color:#666; user-select:none;">426</span>  ```
<span style="color:#666; user-select:none;">427</span>  
<span style="color:#666; user-select:none;">428</span>  #### Custody responses
<span style="color:#666; user-select:none;">429</span>  
<span style="color:#666; user-select:none;">430</span>  Verify that `len(block.body.custody_responses) &lt;= MAX_CUSTODY_RESPONSES`.
<span style="color:#666; user-select:none;">431</span>  
<span style="color:#666; user-select:none;">432</span>  For each `response` in `block.body.custody_responses`, run the following function:
<span style="color:#666; user-select:none;">433</span>  
<span style="color:#666; user-select:none;">434</span>  ```python
<span style="color:#666; user-select:none;">435</span>  def process_custody_response(state: BeaconState,
<span style="color:#666; user-select:none;">436</span>                               response: CustodyResponse) -&gt; None:
<span style="color:#666; user-select:none;">437</span>      chunk_challenge = next(record for record in state.custody_chunk_challenge_records if record.challenge_index == response.challenge_index, None)
<span style="color:#666; user-select:none;">438</span>      if chunk_challenge is not None:
<span style="color:#666; user-select:none;">439</span>          return process_chunk_challenge_response(state, response, chunk_challenge)
<span style="color:#666; user-select:none;">440</span>  
<span style="color:#666; user-select:none;">441</span>      bit_challenge = next(record for record in state.custody_bit_challenge_records if record.challenge_index == response.challenge_index, None)
<span style="color:#666; user-select:none;">442</span>      if bit_challenge is not None:
<span style="color:#666; user-select:none;">443</span>          return process_bit_challenge_response(state, response, bit_challenge)
<span style="color:#666; user-select:none;">444</span>  
<span style="color:#666; user-select:none;">445</span>      assert False
<span style="color:#666; user-select:none;">446</span>  ```
<span style="color:#666; user-select:none;">447</span>  
<span style="color:#666; user-select:none;">448</span>  ```python
<span style="color:#666; user-select:none;">449</span>  def process_chunk_challenge_response(state: BeaconState,
<span style="color:#666; user-select:none;">450</span>                                       response: CustodyResponse,
<span style="color:#666; user-select:none;">451</span>                                       challenge: CustodyChunkChallengeRecord) -&gt; None:
<span style="color:#666; user-select:none;">452</span>      # Verify chunk index
<span style="color:#666; user-select:none;">453</span>      assert response.chunk_index == challenge.chunk_index
<span style="color:#666; user-select:none;">454</span>      # Verify the chunk matches the crosslink data root
<span style="color:#666; user-select:none;">455</span>      assert verify_merkle_branch(
<span style="color:#666; user-select:none;">456</span>          leaf=hash_tree_root(response.chunk),
<span style="color:#666; user-select:none;">457</span>          branch=response.branch,
<span style="color:#666; user-select:none;">458</span>          depth=challenge.depth,
<span style="color:#666; user-select:none;">459</span>          index=response.chunk_index,
<span style="color:#666; user-select:none;">460</span>          root=challenge.crosslink_data_root,
<span style="color:#666; user-select:none;">461</span>      )
<span style="color:#666; user-select:none;">462</span>      # Clear the challenge
<span style="color:#666; user-select:none;">463</span>      records = state.custody_chunk_challenge_records
<span style="color:#666; user-select:none;">464</span>      records[records.index(challenge)] = CustodyChunkChallengeRecord()
<span style="color:#666; user-select:none;">465</span>      # Reward the proposer
<span style="color:#666; user-select:none;">466</span>      proposer_index = get_beacon_proposer_index(state)
<span style="color:#666; user-select:none;">467</span>      increase_balance(state, proposer_index, base_reward(state, index) // MINOR_REWARD_QUOTIENT)
<span style="color:#666; user-select:none;">468</span>  ```
<span style="color:#666; user-select:none;">469</span>  
<span style="color:#666; user-select:none;">470</span>  ```python
<span style="color:#666; user-select:none;">471</span>  def process_bit_challenge_response(state: BeaconState,
<span style="color:#666; user-select:none;">472</span>                                     response: CustodyResponse,
<span style="color:#666; user-select:none;">473</span>                                     challenge: CustodyBitChallengeRecord) -&gt; None:
<span style="color:#666; user-select:none;">474</span>      # Verify chunk index
<span style="color:#666; user-select:none;">475</span>      assert response.chunk_index &lt; len(challenge.chunk_bits)
<span style="color:#666; user-select:none;">476</span>      # Verify the chunk matches the crosslink data root
<span style="color:#666; user-select:none;">477</span>      assert verify_merkle_branch(
<span style="color:#666; user-select:none;">478</span>          leaf=hash_tree_root(response.chunk),
<span style="color:#666; user-select:none;">479</span>          branch=response.branch,
<span style="color:#666; user-select:none;">480</span>          depth=math.log2(next_power_of_two(len(challenge.chunk_bits))),
<span style="color:#666; user-select:none;">481</span>          index=response.chunk_index,
<span style="color:#666; user-select:none;">482</span>          root=challenge.crosslink_data_root,
<span style="color:#666; user-select:none;">483</span>      )
<span style="color:#666; user-select:none;">484</span>      # Verify the chunk bit does not match the challenge chunk bit
<span style="color:#666; user-select:none;">485</span>      assert get_custody_chunk_bit(challenge.responder_key, response.chunk) != get_bitfield_bit(challenge.chunk_bits, response.chunk_index)
<span style="color:#666; user-select:none;">486</span>      # Clear the challenge
<span style="color:#666; user-select:none;">487</span>      records = state.custody_bit_challenge_records
<span style="color:#666; user-select:none;">488</span>      records[records.index(challenge)] = CustodyBitChallengeRecord()
<span style="color:#666; user-select:none;">489</span>      # Slash challenger
<span style="color:#666; user-select:none;">490</span>      slash_validator(state, challenge.challenger_index, challenge.responder_index)
<span style="color:#666; user-select:none;">491</span>  ```
<span style="color:#666; user-select:none;">492</span>  
<span style="color:#666; user-select:none;">493</span>  ## Per-epoch processing
<span style="color:#666; user-select:none;">494</span>  
<span style="color:#666; user-select:none;">495</span>  Run `process_challenge_deadlines(state)` immediately after `process_ejections(state)`:
<span style="color:#666; user-select:none;">496</span>  
<span style="color:#666; user-select:none;">497</span>  ```python
<span style="color:#666; user-select:none;">498</span>  def process_challenge_deadlines(state: BeaconState) -&gt; None:
<span style="color:#666; user-select:none;">499</span>      for challenge in state.custody_chunk_challenge_records:
<span style="color:#666; user-select:none;">500</span>          if get_current_epoch(state) &gt; challenge.deadline:
<span style="color:#666; user-select:none;">501</span>              slash_validator(state, challenge.responder_index, challenge.challenger_index)
<span style="color:#666; user-select:none;">502</span>              records = state.custody_chunk_challenge_records
<span style="color:#666; user-select:none;">503</span>              records[records.index(challenge)] = CustodyChunkChallengeRecord()
<span style="color:#666; user-select:none;">504</span>  
<span style="color:#666; user-select:none;">505</span>      for challenge in state.custody_bit_challenge_records:
<span style="color:#666; user-select:none;">506</span>          if get_current_epoch(state) &gt; challenge.deadline:
<span style="color:#666; user-select:none;">507</span>              slash_validator(state, challenge.responder_index, challenge.challenger_index)
<span style="color:#666; user-select:none;">508</span>              records = state.custody_bit_challenge_records
<span style="color:#666; user-select:none;">509</span>              records[records.index(challenge)] = CustodyBitChallengeRecord()
<span style="color:#666; user-select:none;">510</span>  ```
<span style="color:#666; user-select:none;">511</span>  
<span style="color:#666; user-select:none;">512</span>  In `process_penalties_and_exits`, change the definition of `eligible` to the following (note that it is not a pure function because `state` is declared in the surrounding scope):
<span style="color:#666; user-select:none;">513</span>  
<span style="color:#666; user-select:none;">514</span>  ```python
<span style="color:#666; user-select:none;">515</span>  def eligible(index):
<span style="color:#666; user-select:none;">516</span>      validator = state.validator_registry[index]
<span style="color:#666; user-select:none;">517</span>      # Cannot exit if there are still open chunk challenges
<span style="color:#666; user-select:none;">518</span>      if len([record for record in state.custody_chunk_challenge_records if record.responder_index == index]) &gt; 0:
<span style="color:#666; user-select:none;">519</span>          return False
<span style="color:#666; user-select:none;">520</span>      # Cannot exit if you have not revealed all of your custody keys
<span style="color:#666; user-select:none;">521</span>      elif epoch_to_custody_period(revealer.activation_epoch) + validator.custody_reveal_index &lt;= epoch_to_custody_period(validator.exit_epoch):
<span style="color:#666; user-select:none;">522</span>          return False
<span style="color:#666; user-select:none;">523</span>      # Cannot exit if you already have
<span style="color:#666; user-select:none;">524</span>      elif validator.withdrawable_epoch &lt; FAR_FUTURE_EPOCH:
<span style="color:#666; user-select:none;">525</span>          return False
<span style="color:#666; user-select:none;">526</span>      # Return minimum time
<span style="color:#666; user-select:none;">527</span>      else:
<span style="color:#666; user-select:none;">528</span>          return current_epoch &gt;= validator.exit_epoch + MIN_VALIDATOR_WITHDRAWAL_EPOCHS
<span style="color:#666; user-select:none;">529</span>  ```
</pre>
        </div>
        </div>

</div>
</main>
</div>
</div>


</body>
</html>

