From 80e224be8cf5e8d54b7bdc7a0c72769fce63d676 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Thu, 6 Dec 2018 19:02:23 -0600 Subject: [PATCH 01/23] remove specials --- specs/core/0_beacon-chain.md | 460 ++++++++++++++++++----------------- 1 file changed, 233 insertions(+), 227 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 3192baa33..eccd45bf5 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -17,20 +17,25 @@ - [Time parameters](#time-parameters) - [Reward and penalty quotients](#reward-and-penalty-quotients) - [Status codes](#status-codes) - - [Special record types](#special-record-types) + - [Max transactions](#max-transactions) - [Validator registry delta flags](#validator-registry-delta-flags) - [Signature domains](#signature-domains) - [Data structures](#data-structures) - [Deposits](#deposits) - [`DepositParametersRecord`](#depositparametersrecord) + - [Beacon chain transactions](#beacon-chain-transactions) + - [`AttestationRecord`](#attestationrecord) + - [`AttestationData`](#attestationdata) + - [`ProposerSlashingRecord`](#proposerslashingrecord) + - [`CasperSlashingRecord`](#casperslashingrecord) + - [`SpecialAttestationData`](#specialattestationdata) + - [`DepositRecord`](#depositproofrecord) + - [`ExitRecord`](#voluntaryexitrecord) - [Beacon chain blocks](#beacon-chain-blocks) - [`BeaconBlockHeader`](#beaconblockheader) - [`BeaconBlockBody`](#beaconblockbody) - [`BeaconBlock`](#beaconblock) - - [`AttestationRecord`](#attestationrecord) - - [`AttestationData`](#attestationdata) - [`ProposalSignedData`](#proposalsigneddata) - - [`SpecialRecord`](#specialrecord) - [Beacon chain state](#beacon-chain-state) - [`BeaconState`](#beaconstate) - [`ValidatorRecord`](#validatorrecord) @@ -40,12 +45,6 @@ - [`CandidatePoWReceiptRootRecord`](#candidatepowreceiptrootrecord) - [`PendingAttestationRecord`](#pendingattestationrecord) - [`ForkData`](#forkdata) - - [Specials](#specials) - - [`VoluntaryExitSpecial`](#voluntaryexitspecial) - - [`CasperSlashingSpecial`](#casperslashingspecial) - - [`SpecialAttestationData`](#specialattestationdata) - - [`ProposerSlashingSpecial`](#proposerslashingspecial) - - [`DepositProofSpecial`](#depositproofspecial) - [Ethereum 1.0 deposit contract](#ethereum-10-deposit-contract) - [Deposit arguments](#deposit-arguments) - [`Deposit` logs](#deposit-logs) @@ -68,20 +67,21 @@ - [`get_effective_balance`](#get_effective_balance) - [`get_new_validator_registry_delta_chain_tip`](#get_new_validator_registry_delta_chain_tip) - [`get_domain`](#get_domain) + - [`verify_special_attestation_data`](#verify_special_attestation_data) - [`integer_squareroot`](#integer_squareroot) - [On startup](#on-startup) - [Routine for activating a validator](#routine-for-activating-a-validator) - [Routine for exiting a validator](#routine-for-exiting-a-validator) - [Per-slot processing](#per-slot-processing) - [Proposer signature](#proposer-signature) - - [Attestations](#attestations) - [RANDAO](#randao) - [PoW receipt root](#pow-receipt-root) - - [Special objects](#special-objects) - - [`VOLUNTARY_EXIT`](#voluntary_exit) - - [`CASPER_SLASHING`](#casper_slashing) - - [`PROPOSER_SLASHING`](#proposer_slashing) - - [`DEPOSIT_PROOF`](#deposit_proof) + - [Transactions](#transactions) + - [Proposer slashings](#proposer-slashing) + - [Casper slashings](#casper-slashing) + - [Attestations](#attestations) + - [Deposits](#deposits) + - [Exits](#exits) - [Per-epoch processing](#per-epoch-processing) - [Helpers](#helpers) - [Receipt roots](#receipt-roots) @@ -200,14 +200,15 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted | `EXITED_WITHOUT_PENALTY` | `3` | | `EXITED_WITH_PENALTY` | `4` | -### Special record types +### Max transactions -| Name | Value | Maximum count | +| Name | Value | | - | - | :-: | -| `VOLUNTARY_EXIT` | `0` | `16` | -| `CASPER_SLASHING` | `1` | `16` | -| `PROPOSER_SLASHING` | `2` | `16` | -| `DEPOSIT_PROOF` | `3` | `16` | +| `MAX_PROPOSER_SLASHINGS` | `2**4` (= 16) | +| `MAX_CASPER_SLASHINGS` | `2**4` (= 16) | +| `MAX_ATTESTATIONS` | `2**7` (= 128) | +| `MAX_DEPOSITS` | `2**4` (= 16) | +| `MAX_EXITS` | `2**4` (= 16) | ### Validator registry delta flags @@ -244,40 +245,7 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted } ``` -### Beacon chain blocks - -#### `BeaconBlockHeader` - -```python -{ - 'slot': 'uint64', - # Skip list of ancestor beacon block hashes - # i'th item is the most recent ancestor whose slot is a multiple of 2**i for i = 0, ..., 31 - 'ancestor_hashes': ['hash32'], - 'state_root': 'hash32', - 'randao_reveal': 'hash32', - 'candidate_pow_receipt_root': 'hash32', - 'signature': ['uint384'], -} -``` - -#### `BeaconBlockBody` - -```python -{ - 'attestations': [AttestationRecord], - 'specials': [SpecialRecord], -} -``` - -#### `BeaconBlock` - -```python -{ - 'header': BeaconBlockHeader, - 'body': BeaconBlockBody, -} -``` +### Beacon chain transactions #### `AttestationRecord` @@ -317,6 +285,120 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted } ``` +#### `ProposerSlashingRecord` + +```python +{ + # Proposer index + 'proposer_index': 'uint24', + # First proposal data + 'proposal_data_1': ProposalSignedData, + # First proposal signature + 'proposal_signature_1': '[uint384]', + # Second proposal data + 'proposal_data_2': ProposalSignedData, + # Second proposal signature + 'proposal_signature_2': '[uint384]', +} +``` + +#### `CasperSlashingRecord` + +```python +{ + # First vote + vote_1: SpecialAttestationData, + # Second vote + vote_2: SpecialAttestationData, +} +``` + +#### `SpecialAttestationData` + + ```python +{ + # Proof-of-custody indices (0 bits) + 'aggregate_signature_poc_0_indices': '[uint24]', + # Proof-of-custody indices (1 bits) + 'aggregate_signature_poc_1_indices': '[uint24]', + # Attestation data + 'data': AttestationData, + # Aggregate signature + 'aggregate_signature': '[uint384]', +} +``` + +#### `DepositRecord` + +```python +{ + # Receipt Merkle branch + 'merkle_branch': '[hash32]', + # Merkle tree index + 'merkle_tree_index': 'uint64', + # Deposit data + 'deposit_data': { + # Deposit parameters + 'deposit_parameters': DepositParametersRecord, + # Value in Gwei + 'value': 'uint64', + # Timestamp from deposit contract + 'timestamp': 'uint64', + }, +} +``` + +#### `ExitRecord` + +```python +{ + # Minimum slot for processing exit + 'slot': 'unit64', + # Index of the exiting validator + 'validator_index': 'uint64', + # Validator signature + 'signature': '[uint384]', +} +``` + +### Beacon chain blocks + +#### `BeaconBlockHeader` + +```python +{ + 'slot': 'uint64', + # Skip list of ancestor beacon block hashes + # i'th item is the most recent ancestor whose slot is a multiple of 2**i for i = 0, ..., 31 + 'ancestor_hashes': ['hash32'], + 'state_root': 'hash32', + 'randao_reveal': 'hash32', + 'candidate_pow_receipt_root': 'hash32', + 'signature': ['uint384'], +} +``` + +#### `BeaconBlockBody` + +```python +{ + 'attestations': [AttestationRecord], + 'proposer_slashings': [ProposerSlashingRecord], + 'casper_slashings': [CasperSlashingRecord], + 'deposits': [DepositRecord], + 'exits': [ExitRecord], +} +``` + +#### `BeaconBlock` + +```python +{ + 'header': BeaconBlockHeader, + 'body': BeaconBlockBody, +} +``` + #### `ProposalSignedData` ```python @@ -330,17 +412,6 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted } ``` -#### `SpecialRecord` - -```python -{ - # Kind - 'kind': 'uint64', - # Data - 'data': 'bytes', -} -``` - ### Beacon chain state #### `BeaconState` @@ -482,84 +553,6 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted } ``` -### Specials - -#### `VoluntaryExitSpecial` - -```python -{ - # Minimum slot for processing exit - 'slot': 'unit64', - # Index of the exiting validator - 'validator_index': 'uint64', - # Validator signature - 'signature': '[uint384]', -} -``` - -#### `CasperSlashingSpecial` - -```python -{ - # First vote - vote_1: SpecialAttestationData, - # Second vote - vote_2: SpecialAttestationData, -} -``` - -#### `SpecialAttestationData` - - ```python -{ - # Proof-of-custody indices (0 bits) - 'aggregate_signature_poc_0_indices': '[uint24]', - # Proof-of-custody indices (1 bits) - 'aggregate_signature_poc_1_indices': '[uint24]', - # Attestation data - 'data': AttestationData, - # Aggregate signature - 'aggregate_signature': '[uint384]', -} -``` - -#### `ProposerSlashingSpecial` - -```python -{ - # Proposer index - 'proposer_index': 'uint24', - # First proposal data - 'proposal_data_1': ProposalSignedData, - # First proposal signature - 'proposal_signature_1': '[uint384]', - # Second proposal data - 'proposal_data_2': ProposalSignedData, - # Second proposal signature - 'proposal_signature_2': '[uint384]', -} -``` - -#### `DepositProofSpecial` - -```python -{ - # Receipt Merkle branch - 'merkle_branch': '[hash32]', - # Merkle tree index - 'merkle_tree_index': 'uint64', - # Deposit data - 'deposit_data': { - # Deposit parameters - 'deposit_parameters': DepositParametersRecord, - # Value in Gwei - 'value': 'uint64', - # Timestamp from deposit contract - 'timestamp': 'uint64', - }, -} -``` - ## Ethereum 1.0 deposit contract The initial deployment phases of Ethereum 2.0 are implemented without consensus changes to Ethereum 1.0. A deposit contract at address `DEPOSIT_CONTRACT_ADDRESS` is added to Ethereum 1.0 for deposits of ETH to the beacon chain. Validator balances will be withdrawable to the shards when the EVM2.0 is deployed and the shards have state. @@ -960,6 +953,15 @@ def get_domain(fork_data: ForkData, ) * 2**32 + domain_type ``` +#### `verify_special_attestation_data` + +```python +def verify_special_attestation_data(state: State, obj: SpecialAttestationData) -> bool: + pubs = [aggregate_pubkey([state.validators[i].pubkey for i in obj.aggregate_signature_poc_0_indices]), + aggregate_pubkey([state.validators[i].pubkey for i in obj.aggregate_signature_poc_1_indices])] + return BLSMultiVerify(pubkeys=pubs, msgs=[SSZTreeHash(obj)+bytes1(0), SSZTreeHash(obj)+bytes1(1), sig=aggregate_signature) +``` + #### `integer_squareroot` ```python @@ -981,14 +983,21 @@ A valid block with slot `INITIAL_SLOT_NUMBER` (a "genesis block") has the follow ```python { - 'slot': INITIAL_SLOT_NUMBER, - 'randao_reveal': ZERO_HASH, - 'candidate_pow_receipt_root': ZERO_HASH, - 'ancestor_hashes': [ZERO_HASH for i in range(32)], - 'state_root': STARTUP_STATE_ROOT, - 'attestations': [], - 'specials': [], - 'proposer_signature': [0, 0], + 'header': BeaconBlockHeader( + slot=INITIAL_SLOT_NUMBER, + ancestor_hashes=[ZERO_HASH for i in range(32)], + state_root=STARTUP_STATE_ROOT, + randao_reveal=ZERO_HASH, + candidate_pow_receipt_root=ZERO_HASH, + proposer_signature=[0, 0] + ), + 'body': BeaconBlockBody( + proposer_slashings=[], + casper_slashings=[], + attestations=[], + deposits=[], + exits=[] + ), } ``` @@ -1236,9 +1245,54 @@ If there is no block from the proposer at state.slot: * Let `proposal_hash = hash(ProposalSignedData(state.slot, BEACON_CHAIN_SHARD_NUMBER, block_hash_without_sig))`. * Verify that `BLSVerify(pubkey=state.validator_registry[get_beacon_proposer_index(state, state.slot)].pubkey, data=proposal_hash, sig=block.header.signature, domain=get_domain(state.fork_data, state.slot, DOMAIN_PROPOSAL))`. -### Attestations +### RANDAO -* Verify that `len(block.body.attestations) <= MAX_ATTESTATIONS_PER_BLOCK`. +* Let `repeat_hash(x, n) = x if n == 0 else repeat_hash(hash(x), n-1)`. +* Let `proposer = state.validator_registry[get_beacon_proposer_index(state, state.slot)]`. +* Verify that `repeat_hash(block.header.randao_reveal, proposer.randao_skips + 1) == proposer.randao_commitment`. +* Set `state.randao_mix = xor(state.randao_mix, block.header.randao_reveal)`. +* Set `proposer.randao_commitment = block.header.randao_reveal`. +* Set `proposer.randao_skips = 0`. + +### PoW receipt root + +* If `block.header.candidate_pow_receipt_root` is `x.candidate_pow_receipt_root` for some `x` in `state.candidate_pow_receipt_roots`, set `x.votes += 1`. +* Otherwise, append to `state.candidate_pow_receipt_roots` a new `CandidatePoWReceiptRootRecord(candidate_pow_receipt_root=block.header.candidate_pow_receipt_root, votes=1)`. + +### Transactions + +#### Proposer slashings + +Verify that `len(block.body.proposer_slashings) <= MAX_PROPOSER_SLASHINGS`. + +For each `proposer_slashing` in `block.body.proposer_slashings`: + +* Let `proposer = state.validator_registry[proposer_slashing.proposer_index]` +* Verify that `BLSVerify(pubkey=proposer.pubkey, msg=hash(proposer_slashing.proposal_data_1), sig=proposer_slashing.proposal_signature_1, domain=get_domain(state.fork_data, proposer_slashing.proposal_data_1.slot, DOMAIN_PROPOSAL))`. +* Verify that `BLSVerify(pubkey=proposer.pubkey, msg=hash(proposer_slashing.proposal_data_2), sig=proposer_slashing.proposal_signature_2, domain=get_domain(state.fork_data, proposer_slashing.proposal_data_2.slot, DOMAIN_PROPOSAL))`. +* Verify that `proposer_slashing.proposal_data_1 != proposer_slashing.proposal_data_2`. +* Verify that `proposer_slashing.proposal_data_1.slot == proposer_slashing.proposal_data_2.slot`. +* Verify that `proposer.status != EXITED_WITH_PENALTY`. +* Run `exit_validator(proposer_slashing.proposer_index, state, penalize=True, current_slot=state.slot)`. + +#### Casper slashings + +Verify that `len(block.body.casper_slashings) <= MAX_CASPER_SLASHINGS`. + +For each `casper_slashing` in `block.body.casper_slashings`: + +* Verify that `verify_special_attestation_data(casper_slashing.vote_1)`. +* Verify that `verify_special_attestation_data(casper_slashing.vote_2)`. +* Verify that `casper_slashing.vote_1.data != casper_slashing.vote_2.data`. +* Let `indices(vote) = vote.aggregate_signature_poc_0_indices + vote.aggregate_signature_poc_1_indices`. +* Let `intersection = [x for x in indices(casper_slashing.vote_1) if x in indices(casper_slashing.vote_2)]`. +* Verify that `len(intersection) >= 1`. +* Verify that `casper_slashing.vote_1.data.justified_slot + 1 < casper_slashing.vote_2.data.justified_slot + 1 == casper_slashing.vote_2.data.slot < casper_slashing.vote_1.data.slot` or `casper_slashing.vote_1.data.slot == casper_slashing.vote_2.data.slot`. +* For each [validator](#dfn-validator) index `i` in `intersection`, if `state.validator_registry[i].status` does not equal `EXITED_WITH_PENALTY`, then run `exit_validator(i, state, penalize=True, current_slot=state.slot)` + +#### Attestations + +Verify that `len(block.body.attestations) <= MAX_ATTESTATIONS`. For each `attestation` in `block.body.attestations`: @@ -1254,75 +1308,14 @@ For each `attestation` in `block.body.attestations`: * [TO BE REMOVED IN PHASE 1] Verify that `shard_block_hash == ZERO_HASH`. * Append `PendingAttestationRecord(data=attestation.data, participation_bitfield=attestation.participation_bitfield, custody_bitfield=attestation.custody_bitfield, slot_included=state.slot)` to `state.latest_attestations`. -### RANDAO +#### Deposits -* Let `repeat_hash(x, n) = x if n == 0 else repeat_hash(hash(x), n-1)`. -* Let `proposer = state.validator_registry[get_beacon_proposer_index(state, state.slot)]`. -* Verify that `repeat_hash(block.header.randao_reveal, proposer.randao_skips + 1) == proposer.randao_commitment`. -* Set `state.randao_mix = xor(state.randao_mix, block.header.randao_reveal)`. -* Set `proposer.randao_commitment = block.header.randao_reveal`. -* Set `proposer.randao_skips = 0`. +Verify that `len(block.body.deposits) <= MAX_DEPOSITS`. -### PoW receipt root +For each `deposit` in `block.body.deposits`: -* If `block.header.candidate_pow_receipt_root` is `x.candidate_pow_receipt_root` for some `x` in `state.candidate_pow_receipt_roots`, set `x.votes += 1`. -* Otherwise, append to `state.candidate_pow_receipt_roots` a new `CandidatePoWReceiptRootRecord(candidate_pow_receipt_root=block.header.candidate_pow_receipt_root, votes=1)`. - -### Special objects - -* Verify that the quantity of each type of object in `block.body.specials` is less than or equal to its maximum (see table at the top). -* Verify that objects are sorted in order of `kind`. That is, `block.body.specials[i+1].kind >= block.body.specials[i].kind` for `0 <= i < len(block.body.specials-1)`. - -For each `special` in `block.body.specials`: - -* Verify that `special.kind` is a valid value. -* Verify that `special.data` deserializes according to the format for the given `kind` (see format definitions in "Data structures" above). -* Process `special.data` as specified below for each kind. - -#### `VOLUNTARY_EXIT` - -* Let `validator = state.validator_registry[validator_index]`. -* Verify that `BLSVerify(pubkey=validator.pubkey, msg=ZERO_HASH, sig=signature, domain=get_domain(state.fork_data, slot, DOMAIN_EXIT))`. -* Verify that `validator.status == ACTIVE`. -* Verify that `state.slot >= slot`. -* Verify that `state.slot >= validator.latest_status_change_slot + SHARD_PERSISTENT_COMMITTEE_CHANGE_PERIOD`. -* Run `exit_validator(validator_index, state, penalize=False, current_slot=state.slot)`. - -#### `CASPER_SLASHING` - -Let `verify_special_attestation_data` be the following helper: - - ```python -def verify_special_attestation_data(state: State, obj: SpecialAttestationData) -> bool: - pubs = [aggregate_pubkey([state.validators[i].pubkey for i in obj.aggregate_signature_poc_0_indices]), - aggregate_pubkey([state.validators[i].pubkey for i in obj.aggregate_signature_poc_1_indices])] - return BLSMultiVerify(pubkeys=pubs, msgs=[SSZTreeHash(obj)+bytes1(0), SSZTreeHash(obj)+bytes1(1), sig=aggregate_signature) -``` - -* Verify that `verify_special_attestation_data(vote_1)`. -* Verify that `verify_special_attestation_data(vote_2)`. -* Verify that `vote_1.data != vote_2.data`. -* Let `indices(vote) = vote.aggregate_signature_poc_0_indices + vote.aggregate_signature_poc_1_indices`. -* Let `intersection = [x for x in indices(vote_1) if x in indices(vote_2)]`. -* Verify that `len(intersection) >= 1`. -* Verify that `vote_1.data.justified_slot + 1 < vote_2.data.justified_slot + 1 == vote_2.data.slot < vote_1.data.slot` or `vote_1.data.slot == vote_2.data.slot`. - -For each [validator](#dfn-validator) index `i` in `intersection`, if `state.validator_registry[i].status` does not equal `EXITED_WITH_PENALTY`, then run `exit_validator(i, state, penalize=True, current_slot=state.slot)` - -#### `PROPOSER_SLASHING` - -* Verify that `BLSVerify(pubkey=state.validator_registry[proposer_index].pubkey, msg=hash(proposal_data_1), sig=proposal_signature_1, domain=get_domain(state.fork_data, proposal_data_1.slot, DOMAIN_PROPOSAL))`. -* Verify that `BLSVerify(pubkey=state.validator_registry[proposer_index].pubkey, msg=hash(proposal_data_2), sig=proposal_signature_2, domain=get_domain(state.fork_data, proposal_data_2.slot, DOMAIN_PROPOSAL))`. -* Verify that `proposal_data_1 != proposal_data_2`. -* Verify that `proposal_data_1.slot == proposal_data_2.slot`. -* Verify that `state.validator_registry[proposer_index].status != EXITED_WITH_PENALTY`. -* Run `exit_validator(proposer_index, state, penalize=True, current_slot=state.slot)`. - -#### `DEPOSIT_PROOF` - -Let `serialized_deposit_data` be the serialized form of `deposit_data. It should be the `DepositParametersRecord` followed by 8 bytes for `deposit_data.value` and 8 bytes for `deposit_data.timestamp`. That is, it should match `deposit_data` in the [Ethereum 1.0 deposit contract](#ethereum-10-chain-deposit-contract) of which the hash was placed into the Merkle tree. - -Use the following procedure to verify the `merkle_branch`, setting `leaf=serialized_deposit_data`, `depth=DEPOSIT_CONTRACT_TREE_DEPTH` and `root=state.processed_pow_receipt_root`: +* Let `serialized_deposit_data` be the serialized form of `deposit.deposit_data`. It should be the `DepositParametersRecord` followed by 8 bytes for `deposit_data.value` and 8 bytes for `deposit_data.timestamp`. That is, it should match `deposit_data` in the [Ethereum 1.0 deposit contract](#ethereum-10-chain-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.processed_pow_receipt_root`: ```python def verify_merkle_branch(leaf: Hash32, branch: [Hash32], depth: int, index: int, root: Hash32) -> bool: @@ -1335,22 +1328,35 @@ def verify_merkle_branch(leaf: Hash32, branch: [Hash32], depth: int, index: int, return value == root ``` -* Verify that `state.slot - (deposit_data.timestamp - state.genesis_time) // SLOT_DURATION < ZERO_BALANCE_VALIDATOR_TTL`. +* Verify that `state.slot - (deposit.deposit_data.timestamp - state.genesis_time) // SLOT_DURATION < ZERO_BALANCE_VALIDATOR_TTL`. * Run the following: ```python process_deposit( state=state, - pubkey=deposit_data.deposit_parameters.pubkey, - deposit=deposit_data.value, - proof_of_possession=deposit_data.deposit_parameters.proof_of_possession, - withdrawal_credentials=deposit_data.deposit_parameters.withdrawal_credentials, - randao_commitment=deposit_data.deposit_parameters.randao_commitment, + pubkey=deposit.deposit_data.deposit_parameters.pubkey, + deposit=deposit.deposit_data.value, + proof_of_possession=deposit.deposit_data.deposit_parameters.proof_of_possession, + withdrawal_credentials=deposit.deposit_data.deposit_parameters.withdrawal_credentials, + randao_commitment=deposit.deposit_data.deposit_parameters.randao_commitment, status=PENDING_ACTIVATION, current_slot=state.slot ) ``` +#### Exits + +Verify that `len(block.body.exits) <= MAX_EXITS`. + +For each `exit` in `block.body.exits`: + +* Let `validator = state.validator_registry[exit.validator_index]`. +* Verify that `BLSVerify(pubkey=validator.pubkey, msg=ZERO_HASH, sig=exit.signature, domain=get_domain(state.fork_data, exit.slot, DOMAIN_EXIT))`. +* Verify that `validator.status == ACTIVE`. +* Verify that `state.slot >= exit.slot`. +* Verify that `state.slot >= validator.latest_status_change_slot + SHARD_PERSISTENT_COMMITTEE_CHANGE_PERIOD`. +* Run `exit_validator(validator_index, state, penalize=False, current_slot=state.slot)`. + ## Per-epoch processing The steps below happen when `state.slot % EPOCH_LENGTH == 0`. From 3ea04a28ca4f3e58a0542ae37cb94cdd43eedd39 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Thu, 6 Dec 2018 19:07:26 -0600 Subject: [PATCH 02/23] fix table --- 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 eccd45bf5..3af0288f9 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -203,7 +203,7 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted ### Max transactions | Name | Value | -| - | - | :-: | +| - | - | | `MAX_PROPOSER_SLASHINGS` | `2**4` (= 16) | | `MAX_CASPER_SLASHINGS` | `2**4` (= 16) | | `MAX_ATTESTATIONS` | `2**7` (= 128) | From bcb09a49a045fb9e047aec2721f2a46e548522ac Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Thu, 6 Dec 2018 19:13:19 -0600 Subject: [PATCH 03/23] rework transactions data structure ordering --- specs/core/0_beacon-chain.md | 144 +++++++++++++++++++---------------- 1 file changed, 78 insertions(+), 66 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 3af0288f9..74695576d 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -21,16 +21,20 @@ - [Validator registry delta flags](#validator-registry-delta-flags) - [Signature domains](#signature-domains) - [Data structures](#data-structures) - - [Deposits](#deposits) - - [`DepositParametersRecord`](#depositparametersrecord) - [Beacon chain transactions](#beacon-chain-transactions) - - [`AttestationRecord`](#attestationrecord) - - [`AttestationData`](#attestationdata) - - [`ProposerSlashingRecord`](#proposerslashingrecord) - - [`CasperSlashingRecord`](#casperslashingrecord) - - [`SpecialAttestationData`](#specialattestationdata) - - [`DepositRecord`](#depositproofrecord) - - [`ExitRecord`](#voluntaryexitrecord) + - [Proposer slashings](#proposer-slashings) + - [`ProposerSlashingRecord`](#proposerslashingrecord) + - [Casper slashings](#casper-slashings) + - [`CasperSlashingRecord`](#casperslashingrecord) + - [`SpecialAttestationData`](#specialattestationdata) + - [Attestations](#attestations) + - [`AttestationRecord`](#attestationrecord) + - [`AttestationData`](#attestationdata) + - [Deposits](#deposits) + - [`DepositRecord`](#depositproofrecord) + - [`DepositParametersRecord`](#depositparametersrecord) + - [Exits](#exits) + - [`ExitRecord`](#voluntaryexitrecord) - [Beacon chain blocks](#beacon-chain-blocks) - [`BeaconBlockHeader`](#beaconblockheader) - [`BeaconBlockBody`](#beaconblockbody) @@ -228,26 +232,58 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted ## Data structures -### Deposits +### Beacon chain transactions -#### `DepositParametersRecord` +#### Proposer slashings + +##### `ProposerSlashingRecord` ```python { - # BLS pubkey - 'pubkey': 'uint384', - # BLS proof of possession (a BLS signature) - 'proof_of_possession': ['uint384'], - # Withdrawal credentials - 'withdrawal_credentials': 'hash32', - # Initial RANDAO commitment - 'randao_commitment': 'hash32', + # Proposer index + 'proposer_index': 'uint24', + # First proposal data + 'proposal_data_1': ProposalSignedData, + # First proposal signature + 'proposal_signature_1': '[uint384]', + # Second proposal data + 'proposal_data_2': ProposalSignedData, + # Second proposal signature + 'proposal_signature_2': '[uint384]', } ``` -### Beacon chain transactions +#### Casper slashings -#### `AttestationRecord` +##### `CasperSlashingRecord` + +```python +{ + # First vote + vote_1: SpecialAttestationData, + # Second vote + vote_2: SpecialAttestationData, +} +``` + +##### `SpecialAttestationData` + + ```python +{ + # Proof-of-custody indices (0 bits) + 'aggregate_signature_poc_0_indices': '[uint24]', + # Proof-of-custody indices (1 bits) + 'aggregate_signature_poc_1_indices': '[uint24]', + # Attestation data + 'data': AttestationData, + # Aggregate signature + 'aggregate_signature': '[uint384]', +} +``` + +#### Attestations + +##### `AttestationRecord` ```python { @@ -262,7 +298,7 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted } ``` -#### `AttestationData` +##### `AttestationData` ```python { @@ -285,50 +321,9 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted } ``` -#### `ProposerSlashingRecord` +#### Deposits -```python -{ - # Proposer index - 'proposer_index': 'uint24', - # First proposal data - 'proposal_data_1': ProposalSignedData, - # First proposal signature - 'proposal_signature_1': '[uint384]', - # Second proposal data - 'proposal_data_2': ProposalSignedData, - # Second proposal signature - 'proposal_signature_2': '[uint384]', -} -``` - -#### `CasperSlashingRecord` - -```python -{ - # First vote - vote_1: SpecialAttestationData, - # Second vote - vote_2: SpecialAttestationData, -} -``` - -#### `SpecialAttestationData` - - ```python -{ - # Proof-of-custody indices (0 bits) - 'aggregate_signature_poc_0_indices': '[uint24]', - # Proof-of-custody indices (1 bits) - 'aggregate_signature_poc_1_indices': '[uint24]', - # Attestation data - 'data': AttestationData, - # Aggregate signature - 'aggregate_signature': '[uint384]', -} -``` - -#### `DepositRecord` +##### `DepositRecord` ```python { @@ -348,7 +343,24 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted } ``` -#### `ExitRecord` +#### `DepositParametersRecord` + +```python +{ + # BLS pubkey + 'pubkey': 'uint384', + # BLS proof of possession (a BLS signature) + 'proof_of_possession': ['uint384'], + # Withdrawal credentials + 'withdrawal_credentials': 'hash32', + # Initial RANDAO commitment + 'randao_commitment': 'hash32', +} +``` + +#### Exits + +##### `ExitRecord` ```python { From 57b86e3204de15d9a093d1213c7ee94a16589a95 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Thu, 6 Dec 2018 19:16:10 -0600 Subject: [PATCH 04/23] fix toc --- specs/core/0_beacon-chain.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 74695576d..6d184a79e 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -81,11 +81,11 @@ - [RANDAO](#randao) - [PoW receipt root](#pow-receipt-root) - [Transactions](#transactions) - - [Proposer slashings](#proposer-slashing) - - [Casper slashings](#casper-slashing) - - [Attestations](#attestations) - - [Deposits](#deposits) - - [Exits](#exits) + - [Proposer slashings](#proposer-slashings-1) + - [Casper slashings](#casper-slashings-1) + - [Attestations](#attestations-1) + - [Deposits](#deposits-1) + - [Exits](#exits-1) - [Per-epoch processing](#per-epoch-processing) - [Helpers](#helpers) - [Receipt roots](#receipt-roots) From 35f8eccc1f73deb586a1fc0ef4f10db697f91cd4 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Thu, 6 Dec 2018 19:18:49 -0600 Subject: [PATCH 05/23] fix tox --- 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 6d184a79e..51e297826 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -31,10 +31,10 @@ - [`AttestationRecord`](#attestationrecord) - [`AttestationData`](#attestationdata) - [Deposits](#deposits) - - [`DepositRecord`](#depositproofrecord) + - [`DepositRecord`](#depositrecord) - [`DepositParametersRecord`](#depositparametersrecord) - [Exits](#exits) - - [`ExitRecord`](#voluntaryexitrecord) + - [`ExitRecord`](#exitrecord) - [Beacon chain blocks](#beacon-chain-blocks) - [`BeaconBlockHeader`](#beaconblockheader) - [`BeaconBlockBody`](#beaconblockbody) From 1a716609ba7766e0489b6d900138048925596da2 Mon Sep 17 00:00:00 2001 From: Mikhail Kalinin Date: Fri, 7 Dec 2018 18:23:55 +0600 Subject: [PATCH 06/23] Fix epoch_boundary_attesting_balance calculation get_effective_balance accepts ValidatorRecord object as an input but it was called with validator index instead --- specs/core/0_beacon-chain.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 3192baa33..aa968722e 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -1368,14 +1368,16 @@ All [validators](#dfn-validator): * Let `this_epoch_attestations = [a for a in state.latest_attestations if state.slot - EPOCH_LENGTH <= a.data.slot < state.slot]`. (Note: this is the set of attestations of slots in the epoch `state.slot-EPOCH_LENGTH...state.slot-1`, _not_ attestations that got included in the chain during the epoch `state.slot-EPOCH_LENGTH...state.slot-1`.) * Let `this_epoch_boundary_attestations = [a for a in this_epoch_attestations if a.data.epoch_boundary_hash == get_block_hash(state, state.slot-EPOCH_LENGTH) and a.justified_slot == state.justified_slot]`. -* Let `this_epoch_boundary_attesters` be the union of the [validator](#dfn-validator) index sets given by `[get_attestation_participants(state, a.data, a.participation_bitfield) for a in this_epoch_boundary_attestations]`. +* Let `this_epoch_boundary_attester_indices` be the union of the [validator](#dfn-validator) index sets given by `[get_attestation_participants(state, a.data, a.participation_bitfield) for a in this_epoch_boundary_attestations]`. +* Let `this_epoch_boundary_attesters = [state.validator_registry[i] for indices in this_epoch_boundary_attester_indices for i in indices]`. * Let `this_epoch_boundary_attesting_balance = sum([get_effective_balance(v) for v in this_epoch_boundary_attesters])`. [Validators](#dfn-Validator) justifying the epoch boundary block at the start of the previous epoch: * Let `previous_epoch_attestations = [a for a in state.latest_attestations if state.slot - 2 * EPOCH_LENGTH <= a.slot < state.slot - EPOCH_LENGTH]`. * Let `previous_epoch_boundary_attestations = [a for a in this_epoch_attestations + previous_epoch_attestations if a.epoch_boundary_hash == get_block_hash(state, state.slot - 2 * EPOCH_LENGTH) and a.justified_slot == state.previous_justified_slot]`. -* Let `previous_epoch_boundary_attesters` be the union of the validator index sets given by `[get_attestation_participants(state, a.data, a.participation_bitfield) for a in previous_epoch_boundary_attestations]`. +* Let `previous_epoch_boundary_attester_indices` be the union of the validator index sets given by `[get_attestation_participants(state, a.data, a.participation_bitfield) for a in previous_epoch_boundary_attestations]`. +* Let `previous_epoch_boundary_attesters = [state.validator_registry[i] for indices in previous_epoch_boundary_attester_indices for i in indices]`. * Let `previous_epoch_boundary_attesting_balance = sum([get_effective_balance(v) for v in previous_epoch_boundary_attesters])`. For every `shard_committee` in `state.shard_committees_at_slots`: From 9f64530aacff3c0b2dbc174ac9f33b4680481077 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Fri, 7 Dec 2018 07:46:52 -0600 Subject: [PATCH 07/23] remove BeaconBlockHeader --- specs/core/0_beacon-chain.md | 52 ++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 29 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 3192baa33..175c4158f 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -24,9 +24,8 @@ - [Deposits](#deposits) - [`DepositParametersRecord`](#depositparametersrecord) - [Beacon chain blocks](#beacon-chain-blocks) - - [`BeaconBlockHeader`](#beaconblockheader) - - [`BeaconBlockBody`](#beaconblockbody) - [`BeaconBlock`](#beaconblock) + - [`BeaconBlockBody`](#beaconblockbody) - [`AttestationRecord`](#attestationrecord) - [`AttestationData`](#attestationdata) - [`ProposalSignedData`](#proposalsigneddata) @@ -246,10 +245,11 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted ### Beacon chain blocks -#### `BeaconBlockHeader` +#### `BeaconBlock` ```python { + ## Header ## 'slot': 'uint64', # Skip list of ancestor beacon block hashes # i'th item is the most recent ancestor whose slot is a multiple of 2**i for i = 0, ..., 31 @@ -258,6 +258,9 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted 'randao_reveal': 'hash32', 'candidate_pow_receipt_root': 'hash32', 'signature': ['uint384'], + + ## Body ## + 'body': BeaconBlockBody, } ``` @@ -270,15 +273,6 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted } ``` -#### `BeaconBlock` - -```python -{ - 'header': BeaconBlockHeader, - 'body': BeaconBlockBody, -} -``` - #### `AttestationRecord` ```python @@ -648,10 +642,10 @@ Processing the beacon chain is similar to processing the Ethereum 1.0 chain. Cli For a beacon chain block, `block`, to be processed by a node, the following conditions must be met: -* The parent block with hash `block.header.ancestor_hashes[0]` has been processed and accepted. -* The node has processed its `state` up to slot, `block.header.slot - 1`. +* The parent block with hash `block.ancestor_hashes[0]` has been processed and accepted. +* The node has processed its `state` up to slot, `block.slot - 1`. * The Ethereum 1.0 block pointed to by the `state.processed_pow_receipt_root` has been processed and accepted. -* The node's local clock time is greater than or equal to `state.genesis_time + block.header.slot * SLOT_DURATION`. +* The node's local clock time is greater than or equal to `state.genesis_time + block.slot * SLOT_DURATION`. If these conditions are not met, the client should delay processing the beacon block until the conditions are all satisfied. @@ -664,7 +658,7 @@ The beacon chain fork choice rule is a hybrid that combines justification and fi * Let `store` be the set of attestations and blocks that the [validator](#dfn-validator) `v` has observed and verified (in particular, block ancestors must be recursively verified). Attestations not part of any chain are still included in `store`. * Let `finalized_head` be the finalized block with the highest slot number. (A block `B` is finalized if there is a descendant of `B` in `store` the processing of which sets `B` as finalized.) * Let `justified_head` be the descendant of `finalized_head` with the highest slot number that has been justified for at least `EPOCH_LENGTH` slots. (A block `B` is justified if there is a descendant of `B` in `store` the processing of which sets `B` as justified.) If no such descendant exists set `justified_head` to `finalized_head`. -* Let `get_ancestor(store, block, slot)` be the ancestor of `block` with slot number `slot`. The `get_ancestor` function can be defined recursively as `def get_ancestor(store, block, slot): return block if block.header.slot == slot else get_ancestor(store, store.get_parent(block), slot)`. +* Let `get_ancestor(store, block, slot)` be the ancestor of `block` with slot number `slot`. The `get_ancestor` function can be defined recursively as `def get_ancestor(store, block, slot): return block if block.slot == slot else get_ancestor(store, store.get_parent(block), slot)`. * Let `get_latest_attestation(store, validator)` be the attestation with the highest slot number in `store` from `validator`. If several such attestations exist, use the one the [validator](#dfn-validator) `v` observed first. * Let `get_latest_attestation_target(store, validator)` be the target block in the attestation `get_latest_attestation(store, validator)`. * The head is `lmd_ghost(store, justified_head)` where the function `lmd_ghost` is defined below. Note that the implementation below is suboptimal; there are implementations that compute the head in time logarithmic in slot count. @@ -678,7 +672,7 @@ def lmd_ghost(store, start): for validator in active_validators] def get_vote_count(block): return len([target for target in attestation_targets if - get_ancestor(store, target, block.header.slot) == block]) + get_ancestor(store, target, block.slot) == block]) head = start while 1: @@ -885,9 +879,9 @@ def get_beacon_proposer_index(state: BeaconState, ```python def get_updated_ancestor_hashes(latest_block: BeaconBlock, latest_hash: Hash32) -> List[Hash32]: - new_ancestor_hashes = copy.deepcopy(latest_block.header.ancestor_hashes) + new_ancestor_hashes = copy.deepcopy(latest_block.ancestor_hashes) for i in range(32): - if latest_block.header.slot % 2**i == 0: + if latest_block.slot % 2**i == 0: new_ancestor_hashes[i] = latest_hash return new_ancestor_hashes ``` @@ -1223,8 +1217,8 @@ Below are the processing steps that happen at every slot. If there is a block from the proposer for `state.slot`, we process that incoming block: * Let `block` be that associated incoming block. -* Verify that `block.header.slot == state.slot` -* Verify that `block.header.ancestor_hashes` equals `get_updated_ancestor_hashes(latest_block, latest_hash)`. +* Verify that `block.slot == state.slot` +* Verify that `block.ancestor_hashes` equals `get_updated_ancestor_hashes(latest_block, latest_hash)`. If there is no block from the proposer at state.slot: * Set `state.validator_registry[get_beacon_proposer_index(state, state.slot)].randao_skips += 1`. @@ -1232,9 +1226,9 @@ If there is no block from the proposer at state.slot: ### Proposer signature -* Let `block_hash_without_sig` be the hash of `block` where `block.header.signature` is set to `[0, 0]`. +* Let `block_hash_without_sig` be the hash of `block` where `block.signature` is set to `[0, 0]`. * Let `proposal_hash = hash(ProposalSignedData(state.slot, BEACON_CHAIN_SHARD_NUMBER, block_hash_without_sig))`. -* Verify that `BLSVerify(pubkey=state.validator_registry[get_beacon_proposer_index(state, state.slot)].pubkey, data=proposal_hash, sig=block.header.signature, domain=get_domain(state.fork_data, state.slot, DOMAIN_PROPOSAL))`. +* Verify that `BLSVerify(pubkey=state.validator_registry[get_beacon_proposer_index(state, state.slot)].pubkey, data=proposal_hash, sig=block.signature, domain=get_domain(state.fork_data, state.slot, DOMAIN_PROPOSAL))`. ### Attestations @@ -1258,15 +1252,15 @@ For each `attestation` in `block.body.attestations`: * Let `repeat_hash(x, n) = x if n == 0 else repeat_hash(hash(x), n-1)`. * Let `proposer = state.validator_registry[get_beacon_proposer_index(state, state.slot)]`. -* Verify that `repeat_hash(block.header.randao_reveal, proposer.randao_skips + 1) == proposer.randao_commitment`. -* Set `state.randao_mix = xor(state.randao_mix, block.header.randao_reveal)`. -* Set `proposer.randao_commitment = block.header.randao_reveal`. +* Verify that `repeat_hash(block.randao_reveal, proposer.randao_skips + 1) == proposer.randao_commitment`. +* Set `state.randao_mix = xor(state.randao_mix, block.randao_reveal)`. +* Set `proposer.randao_commitment = block.randao_reveal`. * Set `proposer.randao_skips = 0`. ### PoW receipt root -* If `block.header.candidate_pow_receipt_root` is `x.candidate_pow_receipt_root` for some `x` in `state.candidate_pow_receipt_roots`, set `x.votes += 1`. -* Otherwise, append to `state.candidate_pow_receipt_roots` a new `CandidatePoWReceiptRootRecord(candidate_pow_receipt_root=block.header.candidate_pow_receipt_root, votes=1)`. +* If `block.candidate_pow_receipt_root` is `x.candidate_pow_receipt_root` for some `x` in `state.candidate_pow_receipt_roots`, set `x.votes += 1`. +* Otherwise, append to `state.candidate_pow_receipt_roots` a new `CandidatePoWReceiptRootRecord(candidate_pow_receipt_root=block.candidate_pow_receipt_root, votes=1)`. ### Special objects @@ -1603,7 +1597,7 @@ while len(state.persistent_committee_reassignments) > 0 and state.persistent_com ## State root processing -Verify `block.header.state_root == hash(state)` if there exists a `block` for the slot being processed. +Verify `block.state_root == hash(state)` if there exists a `block` for the slot being processed. # Appendix ## Appendix A - Hash function From d9abce4471345d45d94b59dc15047baea4d24671 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Fri, 7 Dec 2018 09:04:16 -0600 Subject: [PATCH 08/23] rename transactiosn to block objects --- specs/core/0_beacon-chain.md | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index f898e3a4e..672091ca2 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -17,11 +17,11 @@ - [Time parameters](#time-parameters) - [Reward and penalty quotients](#reward-and-penalty-quotients) - [Status codes](#status-codes) - - [Max transactions](#max-transactions) + - [Max block objects](#max-block-objects) - [Validator registry delta flags](#validator-registry-delta-flags) - [Signature domains](#signature-domains) - [Data structures](#data-structures) - - [Beacon chain transactions](#beacon-chain-transactions) + - [Beacon chain objects](#beacon-chain-objects) - [Proposer slashings](#proposer-slashings) - [`ProposerSlashingRecord`](#proposerslashingrecord) - [Casper slashings](#casper-slashings) @@ -79,7 +79,7 @@ - [Proposer signature](#proposer-signature) - [RANDAO](#randao) - [PoW receipt root](#pow-receipt-root) - - [Transactions](#transactions) + - [Block objects](#block-objects) - [Proposer slashings](#proposer-slashings-1) - [Casper slashings](#casper-slashings-1) - [Attestations](#attestations-1) @@ -142,7 +142,6 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted | - | - | :-: | | `SHARD_COUNT` | `2**10` (= 1,024) | shards | | `TARGET_COMMITTEE_SIZE` | `2**8` (= 256) | [validators](#dfn-validator) | -| `MAX_ATTESTATIONS_PER_BLOCK` | `2**7` (= 128) | attestations | | `MIN_BALANCE` | `2**4` (= 16) | ETH | | `MAX_BALANCE_CHURN_QUOTIENT` | `2**5` (= 32) | - | | `GWEI_PER_ETH` | `10**9` | Gwei/ETH | @@ -203,7 +202,7 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted | `EXITED_WITHOUT_PENALTY` | `3` | | `EXITED_WITH_PENALTY` | `4` | -### Max transactions +### Max block objects | Name | Value | | - | - | @@ -231,7 +230,7 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted ## Data structures -### Beacon chain transactions +### Beacon chain objects #### Proposer slashings @@ -1265,7 +1264,7 @@ If there is no block from the proposer at state.slot: * If `block.candidate_pow_receipt_root` is `x.candidate_pow_receipt_root` for some `x` in `state.candidate_pow_receipt_roots`, set `x.votes += 1`. * Otherwise, append to `state.candidate_pow_receipt_roots` a new `CandidatePoWReceiptRootRecord(candidate_pow_receipt_root=block.candidate_pow_receipt_root, votes=1)`. -### Transactions +### Block objects #### Proposer slashings From 3a24fed1948268cbca9926711d545e9761c0808a Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Fri, 7 Dec 2018 09:05:29 -0600 Subject: [PATCH 09/23] fix toc' --- 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 672091ca2..3dacf3be2 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -65,6 +65,7 @@ - [`get_shard_committees_at_slot`](#get_shard_committees_at_slot) - [`get_block_hash`](#get_block_hash) - [`get_beacon_proposer_index`](#get_beacon_proposer_index) + - [`get_updated_ancestor_hashes`](#get_updated_ancestor_hashes) - [`get_attestation_participants`](#get_attestation_participants) - [`bytes1`, `bytes2`, ...](#bytes1-bytes2-) - [`get_effective_balance`](#get_effective_balance) From c4acafdb5858db9ed498e940dc5972a896c5cf09 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Fri, 7 Dec 2018 09:15:55 -0600 Subject: [PATCH 10/23] change block objects to operations --- specs/core/0_beacon-chain.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 3dacf3be2..5fd7e1892 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -17,11 +17,11 @@ - [Time parameters](#time-parameters) - [Reward and penalty quotients](#reward-and-penalty-quotients) - [Status codes](#status-codes) - - [Max block objects](#max-block-objects) + - [Max operations](#max-operations) - [Validator registry delta flags](#validator-registry-delta-flags) - [Signature domains](#signature-domains) - [Data structures](#data-structures) - - [Beacon chain objects](#beacon-chain-objects) + - [Beacon chain operations](#beacon-chain-operations) - [Proposer slashings](#proposer-slashings) - [`ProposerSlashingRecord`](#proposerslashingrecord) - [Casper slashings](#casper-slashings) @@ -80,7 +80,7 @@ - [Proposer signature](#proposer-signature) - [RANDAO](#randao) - [PoW receipt root](#pow-receipt-root) - - [Block objects](#block-objects) + - [Operations](#operations) - [Proposer slashings](#proposer-slashings-1) - [Casper slashings](#casper-slashings-1) - [Attestations](#attestations-1) @@ -203,7 +203,7 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted | `EXITED_WITHOUT_PENALTY` | `3` | | `EXITED_WITH_PENALTY` | `4` | -### Max block objects +### Max operations | Name | Value | | - | - | @@ -231,7 +231,7 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted ## Data structures -### Beacon chain objects +### Beacon chain operations #### Proposer slashings @@ -565,7 +565,7 @@ The initial deployment phases of Ethereum 2.0 are implemented without consensus ### Deposit arguments -The deposit contract has a single `deposit` function which takes as argument a SimpleSerialize'd `DepositParametersRecord` object. One of the `DepositParametersRecord` fields is `withdrawal_credentials` which must satisfy: +The deposit contract has a single `deposit` function which takes as argument a SimpleSerialize'd `DepositParametersRecord`. One of the `DepositParametersRecord` fields is `withdrawal_credentials` which must satisfy: * `withdrawal_credentials[:1] == BLS_WITHDRAWAL_CREDENTIALS` * `withdrawal_credentials[1:] == hash(withdrawal_pubkey)[1:]` where `withdrawal_pubkey` is a BLS pubkey @@ -1265,7 +1265,7 @@ If there is no block from the proposer at state.slot: * If `block.candidate_pow_receipt_root` is `x.candidate_pow_receipt_root` for some `x` in `state.candidate_pow_receipt_roots`, set `x.votes += 1`. * Otherwise, append to `state.candidate_pow_receipt_roots` a new `CandidatePoWReceiptRootRecord(candidate_pow_receipt_root=block.candidate_pow_receipt_root, votes=1)`. -### Block objects +### Operations #### Proposer slashings From dc4bbfedab3f1cdfd5669e3769f28dcc88606d76 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Fri, 7 Dec 2018 09:18:06 -0600 Subject: [PATCH 11/23] clarify header --- 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 5fd7e1892..61c50187e 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -17,7 +17,7 @@ - [Time parameters](#time-parameters) - [Reward and penalty quotients](#reward-and-penalty-quotients) - [Status codes](#status-codes) - - [Max operations](#max-operations) + - [Max operations per block](#max-operations-per-block) - [Validator registry delta flags](#validator-registry-delta-flags) - [Signature domains](#signature-domains) - [Data structures](#data-structures) @@ -203,7 +203,7 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted | `EXITED_WITHOUT_PENALTY` | `3` | | `EXITED_WITH_PENALTY` | `4` | -### Max operations +### Max operations per block | Name | Value | | - | - | From 357cb72d7a8f0aa253e0c75df4fb4f02791f3851 Mon Sep 17 00:00:00 2001 From: Chih Cheng Liang Date: Sat, 8 Dec 2018 00:16:09 +0800 Subject: [PATCH 12/23] fix broken md (#257) --- 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 175c4158f..a0b14e543 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -1314,7 +1314,7 @@ For each [validator](#dfn-validator) index `i` in `intersection`, if `state.vali #### `DEPOSIT_PROOF` -Let `serialized_deposit_data` be the serialized form of `deposit_data. It should be the `DepositParametersRecord` followed by 8 bytes for `deposit_data.value` and 8 bytes for `deposit_data.timestamp`. That is, it should match `deposit_data` in the [Ethereum 1.0 deposit contract](#ethereum-10-chain-deposit-contract) of which the hash was placed into the Merkle tree. +Let `serialized_deposit_data` be the serialized form of `deposit_data`. It should be the `DepositParametersRecord` followed by 8 bytes for `deposit_data.value` and 8 bytes for `deposit_data.timestamp`. That is, it should match `deposit_data` in the [Ethereum 1.0 deposit contract](#ethereum-10-chain-deposit-contract) of which the hash was placed into the Merkle tree. Use the following procedure to verify the `merkle_branch`, setting `leaf=serialized_deposit_data`, `depth=DEPOSIT_CONTRACT_TREE_DEPTH` and `root=state.processed_pow_receipt_root`: From 74ac7e6ee1aacf0fb3b7fac2132d3c22afb3d162 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Fri, 7 Dec 2018 12:43:11 -0600 Subject: [PATCH 13/23] PR feedback --- specs/core/0_beacon-chain.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 61c50187e..4f4d12138 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -1273,11 +1273,12 @@ Verify that `len(block.body.proposer_slashings) <= MAX_PROPOSER_SLASHINGS`. For each `proposer_slashing` in `block.body.proposer_slashings`: -* Let `proposer = state.validator_registry[proposer_slashing.proposer_index]` +* Let `proposer = state.validator_registry[proposer_slashing.proposer_index]`. * Verify that `BLSVerify(pubkey=proposer.pubkey, msg=hash(proposer_slashing.proposal_data_1), sig=proposer_slashing.proposal_signature_1, domain=get_domain(state.fork_data, proposer_slashing.proposal_data_1.slot, DOMAIN_PROPOSAL))`. * Verify that `BLSVerify(pubkey=proposer.pubkey, msg=hash(proposer_slashing.proposal_data_2), sig=proposer_slashing.proposal_signature_2, domain=get_domain(state.fork_data, proposer_slashing.proposal_data_2.slot, DOMAIN_PROPOSAL))`. -* Verify that `proposer_slashing.proposal_data_1 != proposer_slashing.proposal_data_2`. * Verify that `proposer_slashing.proposal_data_1.slot == proposer_slashing.proposal_data_2.slot`. +* Verify that `proposer_slashing.proposal_data_1.shard == proposer_slashing.proposal_data_2.shard`. +* Verify that `proposer_slashing.proposal_data_1.block_hash != proposer_slashing.proposal_data_2.block_hash`. * Verify that `proposer.status != EXITED_WITH_PENALTY`. * Run `exit_validator(proposer_slashing.proposer_index, state, penalize=True, current_slot=state.slot)`. From a0e226c9575abf29cba8de7630a8b7b130e46a45 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Fri, 7 Dec 2018 12:51:15 -0600 Subject: [PATCH 14/23] remove record from operation types --- specs/core/0_beacon-chain.md | 44 ++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 4f4d12138..edc7ad401 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -23,18 +23,18 @@ - [Data structures](#data-structures) - [Beacon chain operations](#beacon-chain-operations) - [Proposer slashings](#proposer-slashings) - - [`ProposerSlashingRecord`](#proposerslashingrecord) + - [`ProposerSlashing`](#proposerslashing) - [Casper slashings](#casper-slashings) - - [`CasperSlashingRecord`](#casperslashingrecord) + - [`CasperSlashing`](#casperslashing) - [`SpecialAttestationData`](#specialattestationdata) - [Attestations](#attestations) - - [`AttestationRecord`](#attestationrecord) + - [`Attestation`](#attestation) - [`AttestationData`](#attestationdata) - [Deposits](#deposits) - - [`DepositRecord`](#depositrecord) - - [`DepositParametersRecord`](#depositparametersrecord) + - [`Deposit`](#deposit) + - [`DepositParameters`](#depositparameters) - [Exits](#exits) - - [`ExitRecord`](#exitrecord) + - [`Exit`](#exit) - [Beacon chain blocks](#beacon-chain-blocks) - [`BeaconBlock`](#beaconblock) - [`BeaconBlockBody`](#beaconblockbody) @@ -80,7 +80,7 @@ - [Proposer signature](#proposer-signature) - [RANDAO](#randao) - [PoW receipt root](#pow-receipt-root) - - [Operations](#operations) + - [Block operations](#block-operations) - [Proposer slashings](#proposer-slashings-1) - [Casper slashings](#casper-slashings-1) - [Attestations](#attestations-1) @@ -235,7 +235,7 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted #### Proposer slashings -##### `ProposerSlashingRecord` +##### `ProposerSlashing` ```python { @@ -254,7 +254,7 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted #### Casper slashings -##### `CasperSlashingRecord` +##### `CasperSlashing` ```python { @@ -282,7 +282,7 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted #### Attestations -##### `AttestationRecord` +##### `Attestation` ```python { @@ -322,7 +322,7 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted #### Deposits -##### `DepositRecord` +##### `Deposit` ```python { @@ -333,7 +333,7 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted # Deposit data 'deposit_data': { # Deposit parameters - 'deposit_parameters': DepositParametersRecord, + 'deposit_parameters': DepositParameters, # Value in Gwei 'value': 'uint64', # Timestamp from deposit contract @@ -342,7 +342,7 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted } ``` -##### `DepositParametersRecord` +##### `DepositParameters` ```python { @@ -359,7 +359,7 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted #### Exits -##### `ExitRecord` +##### `Exit` ```python { @@ -397,11 +397,11 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted ```python { - 'attestations': [AttestationRecord], - 'proposer_slashings': [ProposerSlashingRecord], - 'casper_slashings': [CasperSlashingRecord], - 'deposits': [DepositRecord], - 'exits': [ExitRecord], + 'attestations': [Attestation], + 'proposer_slashings': [ProposerSlashing], + 'casper_slashings': [CasperSlashing], + 'deposits': [Deposit], + 'exits': [Exit], } ``` @@ -565,7 +565,7 @@ The initial deployment phases of Ethereum 2.0 are implemented without consensus ### Deposit arguments -The deposit contract has a single `deposit` function which takes as argument a SimpleSerialize'd `DepositParametersRecord`. One of the `DepositParametersRecord` fields is `withdrawal_credentials` which must satisfy: +The deposit contract has a single `deposit` function which takes as argument a SimpleSerialize'd `DepositParameters`. One of the `DepositParameters` fields is `withdrawal_credentials` which must satisfy: * `withdrawal_credentials[:1] == BLS_WITHDRAWAL_CREDENTIALS` * `withdrawal_credentials[1:] == hash(withdrawal_pubkey)[1:]` where `withdrawal_pubkey` is a BLS pubkey @@ -1265,7 +1265,7 @@ If there is no block from the proposer at state.slot: * If `block.candidate_pow_receipt_root` is `x.candidate_pow_receipt_root` for some `x` in `state.candidate_pow_receipt_roots`, set `x.votes += 1`. * Otherwise, append to `state.candidate_pow_receipt_roots` a new `CandidatePoWReceiptRootRecord(candidate_pow_receipt_root=block.candidate_pow_receipt_root, votes=1)`. -### Operations +### Block operations #### Proposer slashings @@ -1321,7 +1321,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 the `DepositParametersRecord` followed by 8 bytes for `deposit_data.value` and 8 bytes for `deposit_data.timestamp`. That is, it should match `deposit_data` in the [Ethereum 1.0 deposit contract](#ethereum-10-chain-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 the `DepositParameters` followed by 8 bytes for `deposit_data.value` and 8 bytes for `deposit_data.timestamp`. That is, it should match `deposit_data` in the [Ethereum 1.0 deposit contract](#ethereum-10-chain-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.processed_pow_receipt_root`: ```python From 2ed18bfa1fbb4217e6d92e91dc6bfeee707a6e88 Mon Sep 17 00:00:00 2001 From: Justin Date: Fri, 7 Dec 2018 20:09:49 +0000 Subject: [PATCH 15/23] Casper cleanups and bug fixes * (cleanup) `SpecialAttestationData` => `CasperVotes` * (cleanup) `vote_1`, `vote_2` => `votes_1`, `votes_2` * (bug fix) Place a bound on the number of votes with `MAX_CASPER_VOTES` * (bug fix) Supply `state` when calling `verify_casper_votes` --- specs/core/0_beacon-chain.md | 38 ++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index edc7ad401..a96282928 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -26,7 +26,7 @@ - [`ProposerSlashing`](#proposerslashing) - [Casper slashings](#casper-slashings) - [`CasperSlashing`](#casperslashing) - - [`SpecialAttestationData`](#specialattestationdata) + - [`CasperVotes`](#caspervotes) - [Attestations](#attestations) - [`Attestation`](#attestation) - [`AttestationData`](#attestationdata) @@ -71,7 +71,7 @@ - [`get_effective_balance`](#get_effective_balance) - [`get_new_validator_registry_delta_chain_tip`](#get_new_validator_registry_delta_chain_tip) - [`get_domain`](#get_domain) - - [`verify_special_attestation_data`](#verify_special_attestation_data) + - [`verify_casper_votes`](#verify_casper_votes) - [`integer_squareroot`](#integer_squareroot) - [On startup](#on-startup) - [Routine for activating a validator](#routine-for-activating-a-validator) @@ -148,6 +148,7 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted | `GWEI_PER_ETH` | `10**9` | Gwei/ETH | | `BEACON_CHAIN_SHARD_NUMBER` | `2**64 - 1` | - | | `BLS_WITHDRAWAL_CREDENTIALS` | `0x00` | - | +| `MAX_CASPER_VOTES` | `2**10` (= 1,024) | votes | * For the safety of crosslinks a minimum committee size of 111 is [recommended](https://vitalik.ca/files/Ithaca201807_Sharding.pdf). (Unbiasable randomness with a Verifiable Delay Function (VDF) will improve committee robustness and lower the safe minimum committee size.) The shuffling algorithm generally ensures (assuming sufficient validators) committee sizes at least `TARGET_COMMITTEE_SIZE // 2`. @@ -258,14 +259,14 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted ```python { - # First vote - vote_1: SpecialAttestationData, - # Second vote - vote_2: SpecialAttestationData, + # First batch of votes + 'votes_1': CasperVotes, + # Second batch of votes + 'votes_2': CasperVotes, } ``` -##### `SpecialAttestationData` +##### `CasperVotes` ```python { @@ -959,13 +960,16 @@ def get_domain(fork_data: ForkData, ) * 2**32 + domain_type ``` -#### `verify_special_attestation_data` +#### `verify_casper_votes` ```python -def verify_special_attestation_data(state: State, obj: SpecialAttestationData) -> bool: - pubs = [aggregate_pubkey([state.validators[i].pubkey for i in obj.aggregate_signature_poc_0_indices]), - aggregate_pubkey([state.validators[i].pubkey for i in obj.aggregate_signature_poc_1_indices])] - return BLSMultiVerify(pubkeys=pubs, msgs=[SSZTreeHash(obj)+bytes1(0), SSZTreeHash(obj)+bytes1(1), sig=aggregate_signature) +def verify_casper_votes(state: State, votes: CasperVotes) -> bool: + if len(votes.aggregate_signature_poc_0_indices) + len(votes.aggregate_signature_poc_1_indices) > MAX_CASPER_VOTES: + return False + + pubs = [aggregate_pubkey([state.validators[i].pubkey for i in votes.aggregate_signature_poc_0_indices]), + aggregate_pubkey([state.validators[i].pubkey for i in votes.aggregate_signature_poc_1_indices])] + return BLSMultiVerify(pubkeys=pubs, msgs=[SSZTreeHash(votes)+bytes1(0), SSZTreeHash(votes)+bytes1(1), sig=aggregate_signature) ``` #### `integer_squareroot` @@ -1288,13 +1292,13 @@ Verify that `len(block.body.casper_slashings) <= MAX_CASPER_SLASHINGS`. For each `casper_slashing` in `block.body.casper_slashings`: -* Verify that `verify_special_attestation_data(casper_slashing.vote_1)`. -* Verify that `verify_special_attestation_data(casper_slashing.vote_2)`. -* Verify that `casper_slashing.vote_1.data != casper_slashing.vote_2.data`. +* Verify that `verify_casper_votes(state, casper_slashing.votes_1)`. +* Verify that `verify_casper_votes(state, casper_slashing.votes_2)`. +* Verify that `casper_slashing.votes_1.data != casper_slashing.votes_2.data`. * Let `indices(vote) = vote.aggregate_signature_poc_0_indices + vote.aggregate_signature_poc_1_indices`. -* Let `intersection = [x for x in indices(casper_slashing.vote_1) if x in indices(casper_slashing.vote_2)]`. +* Let `intersection = [x for x in indices(casper_slashing.votes_1) if x in indices(casper_slashing.votes_2)]`. * Verify that `len(intersection) >= 1`. -* Verify that `casper_slashing.vote_1.data.justified_slot + 1 < casper_slashing.vote_2.data.justified_slot + 1 == casper_slashing.vote_2.data.slot < casper_slashing.vote_1.data.slot` or `casper_slashing.vote_1.data.slot == casper_slashing.vote_2.data.slot`. +* Verify that `casper_slashing.votes_1.data.justified_slot + 1 < casper_slashing.votes_2.data.justified_slot + 1 == casper_slashing.votes_2.data.slot < casper_slashing.votes_1.data.slot` or `casper_slashing.votes_1.data.slot == casper_slashing.votes_2.data.slot`. * For each [validator](#dfn-validator) index `i` in `intersection`, if `state.validator_registry[i].status` does not equal `EXITED_WITH_PENALTY`, then run `exit_validator(i, state, penalize=True, current_slot=state.slot)` #### Attestations From eefaaf5ac3b68e9f733bfb22212ac86b329e8bc4 Mon Sep 17 00:00:00 2001 From: Chris Leishman Date: Fri, 7 Dec 2018 16:39:52 -0800 Subject: [PATCH 16/23] Clarify TreeHash treatment of integers > 256bit Also clarify treatment of hashes < 32bytes --- specs/simple-serialize.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specs/simple-serialize.md b/specs/simple-serialize.md index 2bd781d4e..4af75ed63 100644 --- a/specs/simple-serialize.md +++ b/specs/simple-serialize.md @@ -394,11 +394,11 @@ The below `SSZTreeHash` algorithm is defined recursively in the case of lists an We define `hash(x)` as `BLAKE2b-512(x)[0:32]`. -#### `uintN`, `bool`, `address`, `hash32` +#### `uint8`..`uint256`, `bool`, `address`, `hash1`..`hash32` Return the serialization of the value. -#### `bytes`, `hashN` +#### `uint264`..`uintN`, `bytes`, `hash33`..`hashN` Return the hash of the serialization of the value. From e04378c38cc72a4db70eebe954012a3a44e95e02 Mon Sep 17 00:00:00 2001 From: Hsiao-Wei Wang Date: Sun, 9 Dec 2018 20:33:13 +0800 Subject: [PATCH 17/23] bytes32(pubkey) -> bytes48(pubkey) (#265) --- 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 876725482..5a62919ec 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -938,7 +938,7 @@ def get_new_validator_registry_delta_chain_tip(current_validator_registry_delta_ current_validator_registry_delta_chain_tip + bytes1(flag) + bytes3(index) + - bytes32(pubkey) + bytes48(pubkey) ) ``` From 238c0e10fea3efbea2692bd477dc56ddf996b02d Mon Sep 17 00:00:00 2001 From: vbuterin Date: Sun, 9 Dec 2018 07:33:37 -0500 Subject: [PATCH 18/23] Added explicit "must be < q" phrasing to BLS description (#262) --- specs/bls_verify.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/specs/bls_verify.md b/specs/bls_verify.md index 9736c0151..a84711cc1 100644 --- a/specs/bls_verify.md +++ b/specs/bls_verify.md @@ -2,19 +2,19 @@ **Warning: This document is pending academic review and should not yet be considered secure.** -See https://z.cash/blog/new-snark-curve/ for BLS-12-381 parameters. +See https://z.cash/blog/new-snark-curve/ for BLS-12-381 parameters. `q` is the field modulus. We represent coordinates as defined in https://github.com/zkcrypto/pairing/tree/master/src/bls12_381/. Specifically, a point in G1 as a 384-bit integer `z`, which we decompose into: -* `x = z % 2**381` +* `x = z % 2**381` (must be `< q`) * `highflag = z // 2**382` * `lowflag = (z % 2**382) // 2**381` If `highflag == 3`, the point is the point at infinity and we require `lowflag = x = 0`. Otherwise, we require `highflag == 2`, in which case the point is `(x, y)` where `y` is the valid coordinate such that `(y * 2) // q == lowflag`. -We represent a point in G2 as a pair of 384-bit integers `(z1, z2)` that are each decomposed into `x1`, `highflag1`, `lowflag1`, `x2`, `highflag2`, `lowflag2` as above. We require `lowflag2 == highflag2 == 0`. If `highflag1 == 3`, the point is the point at infinity and we require `lowflag1 == x1 == x2 == 0`. Otherwise, we require `highflag == 2`, in which case the point is `(x1 * i + x2, y)` where `y` is the valid coordinate such that the imaginary part of `y` satisfies `(y_im * 2) // q == lowflag1`. +We represent a point in G2 as a pair of 384-bit integers `(z1, z2)` that are each decomposed into `x1`, `highflag1`, `lowflag1`, `x2`, `highflag2`, `lowflag2` as above, where `x1` and `x2` must both be `< q`. We require `lowflag2 == highflag2 == 0`. If `highflag1 == 3`, the point is the point at infinity and we require `lowflag1 == x1 == x2 == 0`. Otherwise, we require `highflag == 2`, in which case the point is `(x1 * i + x2, y)` where `y` is the valid coordinate such that the imaginary part of `y` satisfies `(y_im * 2) // q == lowflag1`. `BLSVerify(pubkey: uint384, msg: bytes32, sig: [uint384], domain: uint64)` is done as follows: From 70836ecd1c7b325e0e36fcf991bcb3f4ec530465 Mon Sep 17 00:00:00 2001 From: vbuterin Date: Sun, 9 Dec 2018 08:08:11 -0500 Subject: [PATCH 19/23] Clarify why it's called INVERSE_SQRT_E_DROP_TIME (#261) * (cleanup) Rename `SQRT_E_DROP_TIME` to `INVERSE_SQRT_E_DROP_TIME` to reflect `1/sqrt(e)` * (cleanup) Justify why it's called INVERSE_SQRT_E_DROP_TIME * (cleanup) Polish and simplify presentation * (bug fix) Fixed 2**34 value * (bug fix) Replace epochs with slots to make the calculations work --- specs/core/0_beacon-chain.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 5a62919ec..1d05d30ba 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -184,10 +184,10 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted | `BASE_REWARD_QUOTIENT` | `2**11` (= 2,048) | | `WHISTLEBLOWER_REWARD_QUOTIENT` | `2**9` (= 512) | | `INCLUDER_REWARD_QUOTIENT` | `2**3` (= 8) | -| `INACTIVITY_PENALTY_QUOTIENT` | `2**34` (= 131,072) | +| `INACTIVITY_PENALTY_QUOTIENT` | `2**34` (= 17,179,869,184) | -* The `BASE_REWARD_QUOTIENT` constant dictates the per-epoch reward. It corresponds to ~2.54% annual interest assuming 10 million participating ETH in every epoch. -* The `INACTIVITY_PENALTY_QUOTIENT` equals `SQRT_E_DROP_TIME**2` where `SQRT_E_DROP_TIME := 2**17 slots` (~9 days) is the amount of time it takes for the inactivity penalty to cut deposits of non-participating [validators](#dfn-validator) by ~39.4%. The portion lost by offline [validators](#dfn-validator) after `D` epochs is about `D*D/2/INACTIVITY_PENALTY_QUOTIENT`. +* The `BASE_REWARD_QUOTIENT` parameter dictates the per-epoch reward. It corresponds to ~2.54% annual interest assuming 10 million participating ETH in every epoch. +* The `INACTIVITY_PENALTY_QUOTIENT` equals `INVERSE_SQRT_E_DROP_TIME**2` where `INVERSE_SQRT_E_DROP_TIME := 2**17 slots` (~9 days) is the time it takes the inactivity penalty to reduce the balance of non-participating [validators](#dfn-validator) to about `1/sqrt(e) ~= 60.6%`. Indeed, the balance retained by offline [validators](#dfn-validator) after `n` slots is about `(1-1/INACTIVITY_PENALTY_QUOTIENT)**(n**2/2)` so after `INVERSE_SQRT_E_DROP_TIME` slots it is roughly `(1-1/INACTIVITY_PENALTY_QUOTIENT)**(INACTIVITY_PENALTY_QUOTIENT/2) ~= 1/sqrt(e)`. ### Status codes From c897dd99c222aa890bcd01df008c3e3596004a3f Mon Sep 17 00:00:00 2001 From: Hsiao-Wei Wang Date: Sun, 9 Dec 2018 08:25:34 -0600 Subject: [PATCH 20/23] Update specs/core/0_beacon-chain.md Co-Authored-By: djrtwo --- 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 a96282928..e83601dc5 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -268,7 +268,7 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted ##### `CasperVotes` - ```python +```python { # Proof-of-custody indices (0 bits) 'aggregate_signature_poc_0_indices': '[uint24]', From cc476db8c96d174a1459fe9fc9e3dda7d0fbd9d9 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Sun, 9 Dec 2018 08:33:12 -0600 Subject: [PATCH 21/23] address pr ffeedback --- specs/core/0_beacon-chain.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index e83601dc5..9d5a3ba27 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -26,7 +26,7 @@ - [`ProposerSlashing`](#proposerslashing) - [Casper slashings](#casper-slashings) - [`CasperSlashing`](#casperslashing) - - [`CasperVotes`](#caspervotes) + - [`SlashableVoteData`](#slashablevotedata) - [Attestations](#attestations) - [`Attestation`](#attestation) - [`AttestationData`](#attestationdata) @@ -147,7 +147,7 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted | `MAX_BALANCE_CHURN_QUOTIENT` | `2**5` (= 32) | - | | `GWEI_PER_ETH` | `10**9` | Gwei/ETH | | `BEACON_CHAIN_SHARD_NUMBER` | `2**64 - 1` | - | -| `BLS_WITHDRAWAL_CREDENTIALS` | `0x00` | - | +| `BLS_WITHDRAWAL_PREFIX_BYTE` | `0x00` | - | | `MAX_CASPER_VOTES` | `2**10` (= 1,024) | votes | * For the safety of crosslinks a minimum committee size of 111 is [recommended](https://vitalik.ca/files/Ithaca201807_Sharding.pdf). (Unbiasable randomness with a Verifiable Delay Function (VDF) will improve committee robustness and lower the safe minimum committee size.) The shuffling algorithm generally ensures (assuming sufficient validators) committee sizes at least `TARGET_COMMITTEE_SIZE // 2`. @@ -260,13 +260,13 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted ```python { # First batch of votes - 'votes_1': CasperVotes, + 'votes_1': SlashableVoteData, # Second batch of votes - 'votes_2': CasperVotes, + 'votes_2': SlashableVoteData, } ``` -##### `CasperVotes` +##### `SlashableVoteData` ```python { @@ -568,7 +568,7 @@ The initial deployment phases of Ethereum 2.0 are implemented without consensus The deposit contract has a single `deposit` function which takes as argument a SimpleSerialize'd `DepositParameters`. One of the `DepositParameters` fields is `withdrawal_credentials` which must satisfy: -* `withdrawal_credentials[:1] == BLS_WITHDRAWAL_CREDENTIALS` +* `withdrawal_credentials[:1] == BLS_WITHDRAWAL_PREFIX_BYTE` * `withdrawal_credentials[1:] == hash(withdrawal_pubkey)[1:]` where `withdrawal_pubkey` is a BLS pubkey We recommend the private key corresponding to `withdrawal_pubkey` be stored in cold storage until a withdrawal is required. @@ -963,7 +963,7 @@ def get_domain(fork_data: ForkData, #### `verify_casper_votes` ```python -def verify_casper_votes(state: State, votes: CasperVotes) -> bool: +def verify_casper_votes(state: State, votes: SlashableVoteData) -> bool: if len(votes.aggregate_signature_poc_0_indices) + len(votes.aggregate_signature_poc_1_indices) > MAX_CASPER_VOTES: return False From de32e25bfc1c558534b423d7b22ceb6b5e0c1519 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Sun, 9 Dec 2018 08:47:30 -0600 Subject: [PATCH 22/23] fix initial initial persistent_committees (#258) * fix initial persistent_committees * initial persistent commmitees from active validator indices --- specs/core/0_beacon-chain.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index eb4bff1ec..b621f83c0 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -1038,6 +1038,9 @@ def on_startup(initial_validator_entries: List[Any], # Setup state initial_shuffling = get_new_shuffling(ZERO_HASH, initial_validator_registry, 0) + active_validator_indices = get_active_validator_indices(initial_validator_registry) + initial_persistent_committees = split(shuffle(active_validator_indices, ZERO_HASH), SHARD_COUNT) + state = BeaconState( # Misc slot=INITIAL_SLOT_NUMBER, @@ -1058,7 +1061,7 @@ def on_startup(initial_validator_entries: List[Any], randao_mix=ZERO_HASH, next_seed=ZERO_HASH, shard_committees_at_slots=initial_shuffling + initial_shuffling, - persistent_committees=split(shuffle(initial_validator_registry, ZERO_HASH), SHARD_COUNT), + persistent_committees=initial_persistent_committees, persistent_committee_reassignments=[], # Finality From 88ef7b8186a7630b85ec9b81c6f0ca2f67b14bc4 Mon Sep 17 00:00:00 2001 From: Nishant Das Date: Mon, 10 Dec 2018 16:28:11 +0800 Subject: [PATCH 23/23] typo (#270) --- specs/simple-serialize.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/simple-serialize.md b/specs/simple-serialize.md index 4af75ed63..82d472ea4 100644 --- a/specs/simple-serialize.md +++ b/specs/simple-serialize.md @@ -56,7 +56,7 @@ overhead. | Constant | Value | Definition | |:------------------|:-----:|:--------------------------------------------------------------------------------------| | `LENGTH_BYTES` | 4 | Number of bytes used for the length added before a variable-length serialized object. | -| `SSZ_CHUNK_SIZE` | 128 | Number of bytes for the chuck size of the Merkle tree leaf. | +| `SSZ_CHUNK_SIZE` | 128 | Number of bytes for the chunk size of the Merkle tree leaf. | ## Overview