From 5f19622f86de8c858fd689692a40b01cccd80230 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Wed, 2 Jan 2019 20:29:42 -0600 Subject: [PATCH 01/14] Add clarifying comment about where this index is coming from --- specs/core/0_beacon-chain.md | 1 + 1 file changed, 1 insertion(+) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 2f5b1b3f9..fc1ad3323 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -358,6 +358,7 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted # Receipt Merkle branch 'merkle_branch': '[hash32]', # Merkle tree index + # referred to as `deposit_count` in the Ethereum 1.0 deposit contract 'merkle_tree_index': 'uint64', # Deposit data 'deposit_data': DepositData, From dff84c00b0fa7a4ff583f9414f10522d744910a7 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Wed, 2 Jan 2019 20:37:41 -0600 Subject: [PATCH 02/14] Fixes bugs with description of deposit verification. 1. The order of the `deposit_data` serialization does not match the current Vyper contract. The description now matches that serialization. 2. The `deposit.merkle_tree_index` was not being used (at least explicitly) so the text now reflects which inputs are to be used for which parameters in the pseudocode spec that follows. 3. There seems to be a bug where we want the initial leaf to be the `hash` of the `DepositData`, not the data itself. The text now reflects this requirement. --- specs/core/0_beacon-chain.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index fc1ad3323..a0887f140 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -1474,8 +1474,8 @@ Verify that `len(block.body.deposits) <= MAX_DEPOSITS`. For each `deposit` in `block.body.deposits`: -* Let `serialized_deposit_data` be the serialized form of `deposit.deposit_data`. It should be the `DepositInput` followed by 8 bytes for `deposit_data.amount` and 8 bytes for `deposit_data.timestamp`. That is, it should match `deposit_data` in the [Ethereum 1.0 deposit contract](#ethereum-10-deposit-contract) of which the hash was placed into the Merkle tree. -* Use the following procedure to verify `deposit.merkle_branch`, setting `leaf=serialized_deposit_data`, `depth=DEPOSIT_CONTRACT_TREE_DEPTH` and `root=state.latest_deposit_root`: +* Let `serialized_deposit_data` be the serialized form of `deposit.deposit_data`. It should be 8 bytes for `deposit_data.value` followed by 8 bytes for `deposit_data.timestamp` and then the `DepositInput` bytes. That is, it should match `deposit_data` in the [Ethereum 1.0 deposit contract](#ethereum-10-deposit-contract) of which the hash was placed into the Merkle tree. +* Use the following procedure to verify `deposit.merkle_branch`, setting `leaf=hash(serialized_deposit_data)`, `branch=deposit.merkle_branch`, `depth=DEPOSIT_CONTRACT_TREE_DEPTH`, `index=deposit.merkle_tree_index`, and `root=state.processed_pow_receipt_root`: ```python def verify_merkle_branch(leaf: Hash32, branch: [Hash32], depth: int, index: int, root: Hash32) -> bool: From 4ea430207b6ff4fe0f753948498f1bfae2299f2c Mon Sep 17 00:00:00 2001 From: Justin Date: Fri, 4 Jan 2019 16:52:25 +0000 Subject: [PATCH 03/14] Update 0_beacon-chain.md --- specs/core/0_beacon-chain.md | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index a0887f140..15ae02eda 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -355,12 +355,11 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted ```python { - # Receipt Merkle branch - 'merkle_branch': '[hash32]', - # Merkle tree index - # referred to as `deposit_count` in the Ethereum 1.0 deposit contract - 'merkle_tree_index': 'uint64', - # Deposit data + # Branch in the deposit tree + 'branch': '[hash32]', + # Index in the deposit tree + 'index': 'uint64', + # Data 'deposit_data': DepositData, } ``` @@ -667,7 +666,7 @@ def deposit(deposit_input: bytes[2048]): assert msg.value >= as_wei_value(MIN_DEPOSIT, "ether") assert msg.value <= as_wei_value(MAX_DEPOSIT, "ether") - index: uint256 = self.deposit_count + TWO_TO_POWER_OF_TREE_DEPTH + index: uint256 = self.deposit_tree_index + TWO_TO_POWER_OF_TREE_DEPTH msg_gwei_bytes8: bytes[8] = slice(concat("", convert(msg.value / GWEI_PER_ETH, bytes32)), start=24, len=8) timestamp_bytes8: bytes[8] = slice(concat("", convert(block.timestamp, bytes32)), start=24, len=8) deposit_data: bytes[2064] = concat(msg_gwei_bytes8, timestamp_bytes8, deposit_input) @@ -680,7 +679,7 @@ def deposit(deposit_input: bytes[2048]): index /= 2 self.deposit_tree[index] = sha3(concat(self.deposit_tree[index * 2], self.deposit_tree[index * 2 + 1])) - self.deposit_count += 1 + self.deposit_tree_index += 1 if msg.value == as_wei_value(MAX_DEPOSIT, "ether"): self.full_deposit_count += 1 if self.full_deposit_count == CHAIN_START_FULL_DEPOSIT_THRESHOLD: @@ -1475,7 +1474,7 @@ Verify that `len(block.body.deposits) <= MAX_DEPOSITS`. For each `deposit` in `block.body.deposits`: * Let `serialized_deposit_data` be the serialized form of `deposit.deposit_data`. It should be 8 bytes for `deposit_data.value` followed by 8 bytes for `deposit_data.timestamp` and then the `DepositInput` bytes. That is, it should match `deposit_data` in the [Ethereum 1.0 deposit contract](#ethereum-10-deposit-contract) of which the hash was placed into the Merkle tree. -* Use the following procedure to verify `deposit.merkle_branch`, setting `leaf=hash(serialized_deposit_data)`, `branch=deposit.merkle_branch`, `depth=DEPOSIT_CONTRACT_TREE_DEPTH`, `index=deposit.merkle_tree_index`, and `root=state.processed_pow_receipt_root`: +* Verify that `verify_merkle_branch(hash(serialized_deposit_data), deposit.branch, DEPOSIT_CONTRACT_TREE_DEPTH, deposit.index)` is `True`. ```python def verify_merkle_branch(leaf: Hash32, branch: [Hash32], depth: int, index: int, root: Hash32) -> bool: From 6f5a8655088914f197fa4233853ca83418ae3f85 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Wed, 9 Jan 2019 14:35:26 -0600 Subject: [PATCH 04/14] Reorder type so the ssz serialization matches other uses There is an order based on the Vyper deposit contract which should be maintained here. There is also a reference to it when processing `Deposit` messages. This commit corrects the order here so all serializations will match. --- specs/core/0_beacon-chain.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 15ae02eda..c9257620d 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -368,12 +368,12 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted ```python { - # Deposit input - 'deposit_input': DepositInput, # Amount in Gwei 'amount': 'uint64', # Timestamp from deposit contract 'timestamp': 'uint64', + # Deposit input + 'deposit_input': DepositInput, } ``` From c5de2fe710ac82870f3e7fa14c7be4c41872d828 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Wed, 9 Jan 2019 14:37:51 -0600 Subject: [PATCH 05/14] Add missing deposit root when performing Merkle verification --- specs/core/0_beacon-chain.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index c9257620d..3cb62fdc7 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -1470,11 +1470,12 @@ For each `attestation` in `block.body.attestations`: Verify that `len(block.body.deposits) <= MAX_DEPOSITS`. [TODO: add logic to ensure that deposits from 1.0 chain are processed in order] +[TODO: update the call to `verify_merkle_branch` below if it needs to change after we process deposits in order] For each `deposit` in `block.body.deposits`: * Let `serialized_deposit_data` be the serialized form of `deposit.deposit_data`. It should be 8 bytes for `deposit_data.value` followed by 8 bytes for `deposit_data.timestamp` and then the `DepositInput` bytes. That is, it should match `deposit_data` in the [Ethereum 1.0 deposit contract](#ethereum-10-deposit-contract) of which the hash was placed into the Merkle tree. -* Verify that `verify_merkle_branch(hash(serialized_deposit_data), deposit.branch, DEPOSIT_CONTRACT_TREE_DEPTH, deposit.index)` is `True`. +* Verify that `verify_merkle_branch(hash(serialized_deposit_data), deposit.branch, DEPOSIT_CONTRACT_TREE_DEPTH, deposit.index, state.latest_deposit_root)` is `True`. ```python def verify_merkle_branch(leaf: Hash32, branch: [Hash32], depth: int, index: int, root: Hash32) -> bool: From f49f7eddf99ed200af2897068b655e735159d439 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Wed, 9 Jan 2019 14:44:06 -0600 Subject: [PATCH 06/14] Use the correct name for the `amount` field --- specs/core/0_beacon-chain.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 3cb62fdc7..b7cdae168 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -1474,7 +1474,7 @@ Verify that `len(block.body.deposits) <= MAX_DEPOSITS`. For each `deposit` in `block.body.deposits`: -* Let `serialized_deposit_data` be the serialized form of `deposit.deposit_data`. It should be 8 bytes for `deposit_data.value` followed by 8 bytes for `deposit_data.timestamp` and then the `DepositInput` bytes. That is, it should match `deposit_data` in the [Ethereum 1.0 deposit contract](#ethereum-10-deposit-contract) of which the hash was placed into the Merkle tree. +* Let `serialized_deposit_data` be the serialized form of `deposit.deposit_data`. It should be 8 bytes for `deposit_data.amount` followed by 8 bytes for `deposit_data.timestamp` and then the `DepositInput` bytes. That is, it should match `deposit_data` in the [Ethereum 1.0 deposit contract](#ethereum-10-deposit-contract) of which the hash was placed into the Merkle tree. * Verify that `verify_merkle_branch(hash(serialized_deposit_data), deposit.branch, DEPOSIT_CONTRACT_TREE_DEPTH, deposit.index, state.latest_deposit_root)` is `True`. ```python From 7a6854aab97a3969b8da76ce3406cd2d637186fd Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Wed, 9 Jan 2019 16:52:43 -0600 Subject: [PATCH 07/14] Fix variable name that was lost in botched rebase --- specs/core/0_beacon-chain.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index b7cdae168..dfe7f3fa3 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -666,7 +666,7 @@ def deposit(deposit_input: bytes[2048]): assert msg.value >= as_wei_value(MIN_DEPOSIT, "ether") assert msg.value <= as_wei_value(MAX_DEPOSIT, "ether") - index: uint256 = self.deposit_tree_index + TWO_TO_POWER_OF_TREE_DEPTH + index: uint256 = self.deposit_count + TWO_TO_POWER_OF_TREE_DEPTH msg_gwei_bytes8: bytes[8] = slice(concat("", convert(msg.value / GWEI_PER_ETH, bytes32)), start=24, len=8) timestamp_bytes8: bytes[8] = slice(concat("", convert(block.timestamp, bytes32)), start=24, len=8) deposit_data: bytes[2064] = concat(msg_gwei_bytes8, timestamp_bytes8, deposit_input) @@ -679,7 +679,7 @@ def deposit(deposit_input: bytes[2048]): index /= 2 self.deposit_tree[index] = sha3(concat(self.deposit_tree[index * 2], self.deposit_tree[index * 2 + 1])) - self.deposit_tree_index += 1 + self.deposit_count += 1 if msg.value == as_wei_value(MAX_DEPOSIT, "ether"): self.full_deposit_count += 1 if self.full_deposit_count == CHAIN_START_FULL_DEPOSIT_THRESHOLD: From d62834654f192115fb66868efe002e5c837edbf6 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Wed, 9 Jan 2019 17:02:19 -0600 Subject: [PATCH 08/14] Broadcast `merkle_tree_index` in lieu of the deposit count --- specs/core/0_beacon-chain.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index dfe7f3fa3..f7b7247f6 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -653,7 +653,7 @@ DEPOSIT_CONTRACT_TREE_DEPTH: constant(uint256) = 32 TWO_TO_POWER_OF_TREE_DEPTH: constant(uint256) = 4294967296 # 2**32 SECONDS_PER_DAY: constant(uint256) = 86400 -Deposit: event({previous_deposit_root: bytes32, data: bytes[2064], deposit_count: uint256}) +Deposit: event({previous_deposit_root: bytes32, data: bytes[2064], merkle_tree_index: uint256}) ChainStart: event({deposit_root: bytes32, time: bytes[8]}) deposit_tree: map(uint256, bytes32) @@ -666,18 +666,18 @@ def deposit(deposit_input: bytes[2048]): assert msg.value >= as_wei_value(MIN_DEPOSIT, "ether") assert msg.value <= as_wei_value(MAX_DEPOSIT, "ether") - index: uint256 = self.deposit_count + TWO_TO_POWER_OF_TREE_DEPTH + merkle_tree_index: uint256 = self.deposit_count + TWO_TO_POWER_OF_TREE_DEPTH msg_gwei_bytes8: bytes[8] = slice(concat("", convert(msg.value / GWEI_PER_ETH, bytes32)), start=24, len=8) timestamp_bytes8: bytes[8] = slice(concat("", convert(block.timestamp, bytes32)), start=24, len=8) deposit_data: bytes[2064] = concat(msg_gwei_bytes8, timestamp_bytes8, deposit_input) - log.Deposit(self.deposit_tree[1], deposit_data, self.deposit_count) + log.Deposit(self.deposit_tree[1], deposit_data, merkle_tree_index) # add deposit to merkle tree - self.deposit_tree[index] = sha3(deposit_data) + self.deposit_tree[merkle_tree_index] = sha3(deposit_data) for i in range(DEPOSIT_CONTRACT_TREE_DEPTH): - index /= 2 - self.deposit_tree[index] = sha3(concat(self.deposit_tree[index * 2], self.deposit_tree[index * 2 + 1])) + merkle_tree_index /= 2 + self.deposit_tree[merkle_tree_index] = sha3(concat(self.deposit_tree[merkle_tree_index * 2], self.deposit_tree[merkle_tree_index * 2 + 1])) self.deposit_count += 1 if msg.value == as_wei_value(MAX_DEPOSIT, "ether"): From 4cf06d908adf1b5a438623d3e90182cee5f501f2 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Wed, 9 Jan 2019 17:18:15 -0600 Subject: [PATCH 09/14] Truncate the index into the Merkle tree to bytes[8] The beacon chain expects a `uint64` in part to avoid big-int computation. This commit updates the `Deposit` log so that it broadcasts data of the appropriate size. --- specs/core/0_beacon-chain.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index f7b7247f6..5648d20ed 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -653,7 +653,7 @@ DEPOSIT_CONTRACT_TREE_DEPTH: constant(uint256) = 32 TWO_TO_POWER_OF_TREE_DEPTH: constant(uint256) = 4294967296 # 2**32 SECONDS_PER_DAY: constant(uint256) = 86400 -Deposit: event({previous_deposit_root: bytes32, data: bytes[2064], merkle_tree_index: uint256}) +Deposit: event({previous_deposit_root: bytes32, data: bytes[2064], merkle_tree_index: bytes[8]}) ChainStart: event({deposit_root: bytes32, time: bytes[8]}) deposit_tree: map(uint256, bytes32) @@ -666,18 +666,19 @@ def deposit(deposit_input: bytes[2048]): assert msg.value >= as_wei_value(MIN_DEPOSIT, "ether") assert msg.value <= as_wei_value(MAX_DEPOSIT, "ether") - merkle_tree_index: uint256 = self.deposit_count + TWO_TO_POWER_OF_TREE_DEPTH + index: uint256 = self.deposit_count + TWO_TO_POWER_OF_TREE_DEPTH msg_gwei_bytes8: bytes[8] = slice(concat("", convert(msg.value / GWEI_PER_ETH, bytes32)), start=24, len=8) timestamp_bytes8: bytes[8] = slice(concat("", convert(block.timestamp, bytes32)), start=24, len=8) deposit_data: bytes[2064] = concat(msg_gwei_bytes8, timestamp_bytes8, deposit_input) + merkle_tree_index: bytes[8] = slice(concat("", convert(index, bytes32)), start=24, len=8) log.Deposit(self.deposit_tree[1], deposit_data, merkle_tree_index) # add deposit to merkle tree - self.deposit_tree[merkle_tree_index] = sha3(deposit_data) + self.deposit_tree[index] = sha3(deposit_data) for i in range(DEPOSIT_CONTRACT_TREE_DEPTH): - merkle_tree_index /= 2 - self.deposit_tree[merkle_tree_index] = sha3(concat(self.deposit_tree[merkle_tree_index * 2], self.deposit_tree[merkle_tree_index * 2 + 1])) + index /= 2 + self.deposit_tree[index] = sha3(concat(self.deposit_tree[index * 2], self.deposit_tree[index * 2 + 1])) self.deposit_count += 1 if msg.value == as_wei_value(MAX_DEPOSIT, "ether"): From 3476b02ffa2c432762d379f8085d4bc74108ded9 Mon Sep 17 00:00:00 2001 From: Justin Date: Thu, 10 Jan 2019 11:52:21 +0000 Subject: [PATCH 10/14] Fix #320 * Avoids unnecessary hashing of `message` * Makes the ordering of arguments (`message` followed by `domain`) consistent with usage order --- specs/bls_signature.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specs/bls_signature.md b/specs/bls_signature.md index d04c7f39a..8e0b76c6b 100644 --- a/specs/bls_signature.md +++ b/specs/bls_signature.md @@ -71,8 +71,8 @@ q = 4002409555221667393417789825735904156556882819939007885332058136124031650490 def hash_to_G2(message: bytes32, domain: uint64) -> [uint384]: # Initial candidate x coordinate - x_re = int.from_bytes(hash(bytes8(domain) + b'\x01' + message), 'big') - x_im = int.from_bytes(hash(bytes8(domain) + b'\x02' + message), 'big') + x_re = int.from_bytes(hash(message + bytes8(domain) + b'\x01'), 'big') + x_im = int.from_bytes(hash(message + bytes8(domain) + b'\x02'), 'big') x_coordinate = Fq2([x_re, x_im]) # x = x_re + i * x_im # Test candidate y coordinates until a one is found From c141d90f0f466f0a95fe6ae335c35c46fac85d97 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Thu, 10 Jan 2019 15:41:15 -0600 Subject: [PATCH 11/14] Fix typo with initial generation of `latest_penalized_exit_balances` The spec as written is not valid python -- the generator of the list comprehension must be iterable. It looks like the author simply meant to `range` over the intended length. This commit fixes the missing `range` operator --- specs/core/0_beacon-chain.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 72be599b8..5127a541f 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -1182,7 +1182,7 @@ def get_initial_beacon_state(initial_validator_deposits: List[Deposit], # Recent state latest_crosslinks=[CrosslinkRecord(slot=GENESIS_SLOT, shard_block_root=ZERO_HASH) for _ in range(SHARD_COUNT)], latest_block_roots=[ZERO_HASH for _ in range(LATEST_BLOCK_ROOTS_LENGTH)], - latest_penalized_exit_balances=[0 for _ in LATEST_PENALIZED_EXIT_LENGTH], + latest_penalized_exit_balances=[0 for _ in range(LATEST_PENALIZED_EXIT_LENGTH)], latest_attestations=[], batched_block_roots=[], From d2eca7348270d5de21fe72fd38da4522099e5a63 Mon Sep 17 00:00:00 2001 From: jonny rhea Date: Thu, 10 Jan 2019 18:09:58 -0600 Subject: [PATCH 12/14] added assertion that n >= 0 --- specs/core/0_beacon-chain.md | 1 + 1 file changed, 1 insertion(+) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 5127a541f..671130ebe 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -1097,6 +1097,7 @@ def integer_squareroot(n: int) -> int: """ The largest integer ``x`` such that ``x**2`` is less than ``n``. """ + assert n >= 0 x = n y = (x + 1) // 2 while y < x: From b75ac05ab61f7050aba522237a13fc4ad451c07c Mon Sep 17 00:00:00 2001 From: Ben Edgington Date: Fri, 11 Jan 2019 11:05:43 +0000 Subject: [PATCH 13/14] Fix typo seed -> randao_mix --- specs/core/0_beacon-chain.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 671130ebe..22e8c6dfe 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -859,7 +859,7 @@ def split(values: List[Any], split_count: int) -> List[Any]: #### `get_shuffling` ```python -def get_shuffling(seed: Hash32, +def get_shuffling(randao_mix: Hash32, validators: List[ValidatorRecord], crosslinking_start_shard: int, slot: int) -> List[List[ShardCommittee]]: From d9c6ad90085375ca1f0f91fe00e9d6ca00045a87 Mon Sep 17 00:00:00 2001 From: Stan Drozd Date: Fri, 11 Jan 2019 15:37:38 +0100 Subject: [PATCH 14/14] get_attestation_participants: inline ceil_div8() (#430) --- specs/core/0_beacon-chain.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 22e8c6dfe..b3c056310 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -979,7 +979,7 @@ def get_attestation_participants(state: BeaconState, # Find the relevant committee shard_committees = get_shard_committees_at_slot(state, attestation_data.slot) shard_committee = [x for x in shard_committees if x.shard == attestation_data.shard][0] - assert len(participation_bitfield) == ceil_div8(len(shard_committee.committee)) + assert len(participation_bitfield) == (len(shard_committee.committee) + 7) // 8 # Find the participating attesters in the committee participants = []