From e8aa93e53edebc52767b34465bec27f318c9617f Mon Sep 17 00:00:00 2001 From: vbuterin Date: Sun, 25 Nov 2018 06:23:34 -0500 Subject: [PATCH 1/8] Addressed Justin's 16, 17, 18 --- specs/core/0_beacon-chain.md | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 3f8104b15..b29b41a5a 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -44,7 +44,6 @@ The primary source of load on the beacon chain are "attestations". Attestations | `MIN_VALIDATOR_SET_CHANGE_INTERVAL` | 2**8 (= 256) | slots | ~25 minutes | | `SHARD_PERSISTENT_COMMITTEE_CHANGE_PERIOD` | 2**17 (= 131,072) | slots | ~9 days | | `MIN_ATTESTATION_INCLUSION_DELAY` | 2**2 (= 4) | slots | ~24 seconds | -| `RANDAO_SLOTS_PER_LAYER` | 2**12 (= 4,096) | slots | ~7 hours | | `SQRT_E_DROP_TIME` | 2**18 (= 262,144) | slots | ~18 days | | `WITHDRAWALS_PER_CYCLE` | 2**2 (=4) | validators | 5.2m ETH in ~6 months | | `MIN_WITHDRAWAL_PERIOD` | 2**13 (= 8,192) | slots | ~14 hours | @@ -55,6 +54,7 @@ The primary source of load on the beacon chain are "attestations". Attestations | `BASE_REWARD_QUOTIENT` | 2**15 (= 32,768) | — | | `MAX_VALIDATOR_CHURN_QUOTIENT` | 2**5 (= 32) | — | | `POW_CONTRACT_MERKLE_TREE_DEPTH` | 2**5 (= 32) | - | +| `MAX_ATTESTATION_COUNT` | 2**7 (= 128) | - | | `LOGOUT_MESSAGE` | `"LOGOUT"` | — | | `INITIAL_FORK_VERSION` | 0 | — | @@ -263,8 +263,8 @@ A `ValidatorRecord` has the following fields: 'withdrawal_credentials': 'hash32', # RANDAO commitment 'randao_commitment': 'hash32', - # Slot the RANDAO commitment was last changed - 'randao_last_change': 'uint64', + # Slot the proposer has skipped (ie. layers of RANDAO expected) + 'randao_skips': 'uint64', # Balance in Gwei 'balance': 'uint64', # Status code @@ -597,7 +597,9 @@ def deposit(deposit_params: bytes[2048]): self.receipt_tree[index] = sha3(concat(self.receipt_tree[index * 2], self.receipt_tree[index * 2 + 1])) self.total_deposit_count += 1 if self.total_deposit_count == 16384: - log.ChainStart(self.receipt_tree[1], timestamp_bytes8) + timestamp_day_boundary = (block.timestamp - block.timestamp % 86400) + 86400 + timestamp_day_boundary_bytes8: bytes[8] = slice(convert(timestamp_day_boundary, 'bytes32'), 24, 8) + log.ChainStart(self.receipt_tree[1], timestamp_day_boundary_bytes8 ) @public @constant @@ -733,7 +735,7 @@ def add_validator(validators: List[ValidatorRecord], pubkey=pubkey, withdrawal_credentials=withdrawal_credentials, randao_commitment=randao_commitment, - randao_last_change=current_slot, + randao_skips=0, balance=DEPOSIT_SIZE * GWEI_PER_ETH, status=status, last_status_change_slot=current_slot, @@ -800,7 +802,7 @@ def update_ancestor_hashes(parent_ancestor_hashes: List[Hash32], ### Verify attestations -For each `AttestationRecord` object: +Verify that there are at most `MAX_ATTESTATION_COUNT` `AttestationRecord` objects. For each `AttestationRecord` object: * Verify that `slot <= block.slot - MIN_ATTESTATION_INCLUSION_DELAY` and `slot >= max(parent.slot - CYCLE_LENGTH + 1, 0)`. * Verify that `justified_slot` is equal to or earlier than `last_justified_slot`. @@ -824,10 +826,20 @@ Verify that `BLSVerify(pubkey=get_beacon_proposer(state, block.slot).pubkey, dat ### Verify and process RANDAO reveal +First run the following state transition to update `randao_skips` variables for the missing slots. + +```python +for slot in range(parent.slot + 1, block.slot): + proposer = get_beacon_proposer(state, slot) + proposer.randao_skips += 1 +``` + +Then: + * Let `repeat_hash(x, n) = x if n == 0 else repeat_hash(hash(x), n-1)`. * Let `V = get_beacon_proposer(state, block.slot)`. -* Verify that `repeat_hash(block.randao_reveal, (block.slot - V.randao_last_change) // RANDAO_SLOTS_PER_LAYER + 1) == V.randao_commitment` -* Set `state.randao_mix = xor(state.randao_mix, block.randao_reveal)`, `V.randao_commitment = block.randao_reveal`, `V.randao_last_change = block.slot` +* Verify that `repeat_hash(block.randao_reveal, V.randao_skips + 1) == V.randao_commitment` +* Set `state.randao_mix = xor(state.randao_mix, block.randao_reveal)`, `V.randao_commitment = block.randao_reveal`, `V.randao_skips = 0` ### Process PoW receipt root From b6349eefd421cab20635df42a9fd78e9ff4b8807 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Sun, 25 Nov 2018 11:33:07 -0500 Subject: [PATCH 2/8] Update specs/core/0_beacon-chain.md Co-Authored-By: vbuterin --- 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 b29b41a5a..18173c1ab 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -597,7 +597,7 @@ def deposit(deposit_params: bytes[2048]): self.receipt_tree[index] = sha3(concat(self.receipt_tree[index * 2], self.receipt_tree[index * 2 + 1])) self.total_deposit_count += 1 if self.total_deposit_count == 16384: - timestamp_day_boundary = (block.timestamp - block.timestamp % 86400) + 86400 + timestamp_day_boundary: timestamp = (block.timestamp - block.timestamp % 86400) + 86400 timestamp_day_boundary_bytes8: bytes[8] = slice(convert(timestamp_day_boundary, 'bytes32'), 24, 8) log.ChainStart(self.receipt_tree[1], timestamp_day_boundary_bytes8 ) From ed8dd1eabc839b020ec1ba3cc84085ae97c5e3b3 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Sun, 25 Nov 2018 11:33:17 -0500 Subject: [PATCH 3/8] Update specs/core/0_beacon-chain.md Co-Authored-By: vbuterin --- 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 18173c1ab..f1d1638c4 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -599,7 +599,7 @@ def deposit(deposit_params: bytes[2048]): if self.total_deposit_count == 16384: timestamp_day_boundary: timestamp = (block.timestamp - block.timestamp % 86400) + 86400 timestamp_day_boundary_bytes8: bytes[8] = slice(convert(timestamp_day_boundary, 'bytes32'), 24, 8) - log.ChainStart(self.receipt_tree[1], timestamp_day_boundary_bytes8 ) + log.ChainStart(self.receipt_tree[1], timestamp_day_boundary_bytes8) @public @constant From 2a7103d1f67f6e25fce3f59601caba4d8e6a8ff3 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Sun, 25 Nov 2018 10:41:59 -0600 Subject: [PATCH 4/8] change SpecialRecord.kind to uint64 --- 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 611aa8ce6..634a1f7e5 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -201,7 +201,7 @@ A `SpecialRecord` has the following fields: ```python { # Kind - 'kind': 'uint8', + 'kind': 'uint64', # Data 'data': 'bytes' } From e6a15edc8d19d3ed184f2e109d15aab142f9139c Mon Sep 17 00:00:00 2001 From: vbuterin Date: Sun, 25 Nov 2018 12:08:06 -0500 Subject: [PATCH 5/8] Made contract compile in Vyper --- specs/core/0_beacon-chain.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index f1d1638c4..8f1191ded 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -575,6 +575,9 @@ def int_sqrt(n: int) -> int: The beacon chain is initialized when a condition is met inside a contract on the existing PoW chain. This contract's code in Vyper is as follows: ```python +SECONDS_PER_DAY: constant(uint256) = 86400 +POW_CONTRACT_MERKLE_TREE_DEPTH: constant(int128) = 32 + HashChainValue: event({previous_receipt_root: bytes32, data: bytes[2064], total_deposit_count: int128}) ChainStart: event({receipt_root: bytes32, time: bytes[8]}) @@ -585,20 +588,20 @@ total_deposit_count: int128 @public def deposit(deposit_params: bytes[2048]): index:int128 = self.total_deposit_count + 2**POW_CONTRACT_MERKLE_TREE_DEPTH - msg_gwei_bytes8: bytes[8] = slice(convert(msg.value / 10**9, 'bytes32'), 24, 8) - timestamp_bytes8: bytes[8] = slice(convert(block.timestamp, 'bytes32'), 24, 8) + msg_gwei_bytes8: bytes[8] = slice(concat("", convert(msg.value / 10**9, bytes32)), start=24, len=8) + timestamp_bytes8: bytes[8] = slice(concat("", convert(block.timestamp, bytes32)), start=24, len=8) deposit_data: bytes[2064] = concat(deposit_params, msg_gwei_bytes8, timestamp_bytes8) log.HashChainValue(self.receipt_tree[1], deposit_data, self.total_deposit_count) self.receipt_tree[index] = sha3(deposit_data) for i in range(POW_CONTRACT_MERKLE_TREE_DEPTH): - index //= 2 + index /= 2 self.receipt_tree[index] = sha3(concat(self.receipt_tree[index * 2], self.receipt_tree[index * 2 + 1])) self.total_deposit_count += 1 if self.total_deposit_count == 16384: - timestamp_day_boundary: timestamp = (block.timestamp - block.timestamp % 86400) + 86400 - timestamp_day_boundary_bytes8: bytes[8] = slice(convert(timestamp_day_boundary, 'bytes32'), 24, 8) + timestamp_day_boundary: uint256 = as_unitless_number(block.timestamp) - as_unitless_number(block.timestamp) % SECONDS_PER_DAY + SECONDS_PER_DAY + timestamp_day_boundary_bytes8: bytes[8] = slice(concat("", convert(timestamp_day_boundary, bytes32)), start=24, len=8) log.ChainStart(self.receipt_tree[1], timestamp_day_boundary_bytes8) @public From 13866e3e049629738413559324c625fe22a53cc8 Mon Sep 17 00:00:00 2001 From: Justin Date: Sun, 25 Nov 2018 18:19:22 +0000 Subject: [PATCH 6/8] Remove fork_version for DOMAIN_LOGOUT Also remove `LOGOUT_MESSAGE ` --- specs/core/0_beacon-chain.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 47178dc4b..dfead4820 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -54,7 +54,6 @@ The primary source of load on the beacon chain are "attestations". Attestations | `BASE_REWARD_QUOTIENT` | 2**15 (= 32,768) | — | | `MAX_VALIDATOR_CHURN_QUOTIENT` | 2**5 (= 32) | — | | `POW_CONTRACT_MERKLE_TREE_DEPTH` | 2**5 (= 32) | - | -| `LOGOUT_MESSAGE` | `"LOGOUT"` | — | | `INITIAL_FORK_VERSION` | 0 | — | **Notes** @@ -864,7 +863,7 @@ For each `SpecialRecord` `obj` in `block.specials`, verify that its `kind` is on ``` Perform the following checks: -* Verify that `BLSVerify(pubkey=validators[data.validator_index].pubkey, msg=hash(LOGOUT_MESSAGE + bytes8(fork_version)), sig=data.signature, domain=get_domain(state, current_slot, DOMAIN_LOGOUT))` +* Verify that `BLSVerify(pubkey=validators[data.validator_index].pubkey, msg="", sig=data.signature, domain=get_domain(state, current_slot, DOMAIN_LOGOUT))` * Verify that `validators[validator_index].status == ACTIVE`. * Verify that `block.slot >= last_status_change_slot + SHARD_PERSISTENT_COMMITTEE_CHANGE_PERIOD` From 6a7b280d4908c29dc3c962ff75487e2e0d2e29e4 Mon Sep 17 00:00:00 2001 From: Hsiao-Wei Wang Date: Mon, 26 Nov 2018 10:45:39 +0000 Subject: [PATCH 7/8] Update specs/core/0_beacon-chain.md Co-Authored-By: JustinDrake --- 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 dfead4820..27ada3007 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -863,7 +863,7 @@ For each `SpecialRecord` `obj` in `block.specials`, verify that its `kind` is on ``` Perform the following checks: -* Verify that `BLSVerify(pubkey=validators[data.validator_index].pubkey, msg="", sig=data.signature, domain=get_domain(state, current_slot, DOMAIN_LOGOUT))` +* Verify that `BLSVerify(pubkey=validators[data.validator_index].pubkey, msg=bytes([0] * 32), sig=data.signature, domain=get_domain(state, current_slot, DOMAIN_LOGOUT))` * Verify that `validators[validator_index].status == ACTIVE`. * Verify that `block.slot >= last_status_change_slot + SHARD_PERSISTENT_COMMITTEE_CHANGE_PERIOD` From 1bf04c8c17b8a8696fe0c90a82429a6ecd12f10c Mon Sep 17 00:00:00 2001 From: Justin Date: Mon, 26 Nov 2018 10:47:32 +0000 Subject: [PATCH 8/8] Make status uint64 --- 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 634a1f7e5..e8419fde0 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -274,7 +274,7 @@ A `ValidatorRecord` has the following fields: # Balance in Gwei 'balance': 'uint64', # Status code - 'status': 'uint8', + 'status': 'uint64', # Slot when validator last changed status (or 0) 'last_status_change_slot': 'uint64' # Sequence number when validator exited (or 0)