Merge branch 'dev' into shardblobs
This commit is contained in:
commit
cb29a7ed91
7
setup.py
7
setup.py
|
@ -277,6 +277,12 @@ ALTAIR_HARDCODED_SSZ_DEP_CONSTANTS = {
|
|||
}
|
||||
|
||||
|
||||
ALTAIR_INVAIANT_CHECKS = '''
|
||||
assert (
|
||||
TIMELY_HEAD_WEIGHT + TIMELY_SOURCE_WEIGHT + TIMELY_TARGET_WEIGHT + SYNC_REWARD_WEIGHT + PROPOSER_WEIGHT
|
||||
) == WEIGHT_DENOMINATOR'''
|
||||
|
||||
|
||||
def is_phase0(fork):
|
||||
return fork == PHASE0
|
||||
|
||||
|
@ -331,6 +337,7 @@ def objects_to_spec(spec_object: SpecObject, imports: str, fork: str, ordered_cl
|
|||
if is_altair(fork):
|
||||
altair_ssz_dep_constants_verification = '\n'.join(map(lambda x: 'assert %s == %s' % (x, spec_object.ssz_dep_constants[x]), ALTAIR_HARDCODED_SSZ_DEP_CONSTANTS))
|
||||
spec += '\n\n\n' + altair_ssz_dep_constants_verification
|
||||
spec += '\n' + ALTAIR_INVAIANT_CHECKS
|
||||
|
||||
spec += '\n'
|
||||
return spec
|
||||
|
|
|
@ -88,9 +88,10 @@ Altair is the first beacon chain hard fork. Its main features are:
|
|||
| `TIMELY_SOURCE_WEIGHT` | `uint64(12)` |
|
||||
| `TIMELY_TARGET_WEIGHT` | `uint64(24)` |
|
||||
| `SYNC_REWARD_WEIGHT` | `uint64(8)` |
|
||||
| `PROPOSER_WEIGHT` | `uint64(8)` |
|
||||
| `WEIGHT_DENOMINATOR` | `uint64(64)` |
|
||||
|
||||
*Note*: The sum of the weight fractions (7/8) plus the proposer inclusion fraction (1/8) equals 1.
|
||||
*Note*: The sum of the weights equal `WEIGHT_DENOMINATOR`.
|
||||
|
||||
### Misc
|
||||
|
||||
|
@ -412,7 +413,7 @@ def slash_validator(state: BeaconState,
|
|||
if whistleblower_index is None:
|
||||
whistleblower_index = proposer_index
|
||||
whistleblower_reward = Gwei(validator.effective_balance // WHISTLEBLOWER_REWARD_QUOTIENT)
|
||||
proposer_reward = Gwei(whistleblower_reward // PROPOSER_REWARD_QUOTIENT)
|
||||
proposer_reward = Gwei(whistleblower_reward * PROPOSER_WEIGHT // WEIGHT_DENOMINATOR)
|
||||
increase_balance(state, proposer_index, proposer_reward)
|
||||
increase_balance(state, whistleblower_index, Gwei(whistleblower_reward - proposer_reward))
|
||||
```
|
||||
|
@ -477,7 +478,8 @@ def process_attestation(state: BeaconState, attestation: Attestation) -> None:
|
|||
proposer_reward_numerator += get_base_reward(state, index) * weight
|
||||
|
||||
# Reward proposer
|
||||
proposer_reward = Gwei(proposer_reward_numerator // (WEIGHT_DENOMINATOR * PROPOSER_REWARD_QUOTIENT))
|
||||
proposer_reward_denominator = (WEIGHT_DENOMINATOR - PROPOSER_WEIGHT) * WEIGHT_DENOMINATOR // PROPOSER_WEIGHT
|
||||
proposer_reward = Gwei(proposer_reward_numerator // proposer_reward_denominator)
|
||||
increase_balance(state, get_beacon_proposer_index(state), proposer_reward)
|
||||
```
|
||||
|
||||
|
@ -529,29 +531,26 @@ def process_deposit(state: BeaconState, deposit: Deposit) -> None:
|
|||
```python
|
||||
def process_sync_committee(state: BeaconState, aggregate: SyncAggregate) -> None:
|
||||
# Verify sync committee aggregate signature signing over the previous slot block root
|
||||
previous_slot = Slot(max(int(state.slot), 1) - 1)
|
||||
committee_indices = get_sync_committee_indices(state, get_current_epoch(state))
|
||||
included_indices = [index for index, bit in zip(committee_indices, aggregate.sync_committee_bits) if bit]
|
||||
committee_pubkeys = state.current_sync_committee.pubkeys
|
||||
included_pubkeys = [pubkey for pubkey, bit in zip(committee_pubkeys, aggregate.sync_committee_bits) if bit]
|
||||
participant_pubkeys = [pubkey for pubkey, bit in zip(committee_pubkeys, aggregate.sync_committee_bits) if bit]
|
||||
previous_slot = max(state.slot, Slot(1)) - Slot(1)
|
||||
domain = get_domain(state, DOMAIN_SYNC_COMMITTEE, compute_epoch_at_slot(previous_slot))
|
||||
signing_root = compute_signing_root(get_block_root_at_slot(state, previous_slot), domain)
|
||||
assert eth2_fast_aggregate_verify(included_pubkeys, signing_root, aggregate.sync_committee_signature)
|
||||
assert eth2_fast_aggregate_verify(participant_pubkeys, signing_root, aggregate.sync_committee_signature)
|
||||
|
||||
# Compute the maximum sync rewards for the slot
|
||||
# Compute participant and proposer rewards
|
||||
total_active_increments = get_total_active_balance(state) // EFFECTIVE_BALANCE_INCREMENT
|
||||
total_base_rewards = Gwei(get_base_reward_per_increment(state) * total_active_increments)
|
||||
max_epoch_rewards = Gwei(total_base_rewards * SYNC_REWARD_WEIGHT // WEIGHT_DENOMINATOR)
|
||||
max_slot_rewards = Gwei(max_epoch_rewards * len(included_indices) // len(committee_indices) // SLOTS_PER_EPOCH)
|
||||
max_participant_rewards = Gwei(total_base_rewards * SYNC_REWARD_WEIGHT // WEIGHT_DENOMINATOR // SLOTS_PER_EPOCH)
|
||||
participant_reward = Gwei(max_participant_rewards // SYNC_COMMITTEE_SIZE)
|
||||
proposer_reward = Gwei(participant_reward * PROPOSER_WEIGHT // (WEIGHT_DENOMINATOR - PROPOSER_WEIGHT))
|
||||
|
||||
# Compute the participant and proposer sync rewards
|
||||
committee_effective_balance = get_total_balance(state, set(included_indices))
|
||||
for included_index in included_indices:
|
||||
effective_balance = state.validators[included_index].effective_balance
|
||||
inclusion_reward = Gwei(max_slot_rewards * effective_balance // committee_effective_balance)
|
||||
proposer_reward = Gwei(inclusion_reward // PROPOSER_REWARD_QUOTIENT)
|
||||
# Apply participant and proposer rewards
|
||||
committee_indices = get_sync_committee_indices(state, get_current_epoch(state))
|
||||
participant_indices = [index for index, bit in zip(committee_indices, aggregate.sync_committee_bits) if bit]
|
||||
for participant_index in participant_indices:
|
||||
increase_balance(state, participant_index, participant_reward)
|
||||
increase_balance(state, get_beacon_proposer_index(state), proposer_reward)
|
||||
increase_balance(state, included_index, inclusion_reward - proposer_reward)
|
||||
```
|
||||
|
||||
### Epoch processing
|
||||
|
|
|
@ -92,7 +92,7 @@ The following validations MUST pass before forwarding the `signed_contribution_a
|
|||
- _[REJECT]_ `contribution_and_proof.selection_proof` selects the validator as an aggregator for the slot -- i.e. `is_sync_committee_aggregator(state, contribution.slot, contribution_and_proof.selection_proof)` returns `True`.
|
||||
- _[REJECT]_ The aggregator's validator index is within the current sync committee --
|
||||
i.e. `state.validators[contribution_and_proof.aggregator_index].pubkey in state.current_sync_committee.pubkeys`.
|
||||
- _[REJECT]_ The `contribution_and_proof.selection_proof` is a valid signature of the `contribution.slot` by the validator with index `contribution_and_proof.aggregator_index`.
|
||||
- _[REJECT]_ The `contribution_and_proof.selection_proof` is a valid signature of the `SyncCommitteeSigningData` derived from the `contribution` by the validator with index `contribution_and_proof.aggregator_index`.
|
||||
- _[REJECT]_ The aggregator signature, `signed_contribution_and_proof.signature`, is valid.
|
||||
- _[REJECT]_ The aggregate signature is valid for the message `beacon_block_root` and aggregate pubkey derived from the participation info in `aggregation_bits` for the subcommittee specified by the `subcommittee_index`.
|
||||
|
||||
|
@ -183,6 +183,7 @@ Request and Response remain unchanged. A `ForkDigest`-context is used to select
|
|||
Per `context = compute_fork_digest(fork_version, genesis_validators_root)`:
|
||||
|
||||
| `fork_version` | Chunk SSZ type |
|
||||
| ------------------------ | -------------------------- |
|
||||
| `GENESIS_FORK_VERSION` | `phase0.SignedBeaconBlock` |
|
||||
| `ALTAIR_FORK_VERSION` | `altair.SignedBeaconBlock` |
|
||||
|
||||
|
@ -195,6 +196,7 @@ Request and Response remain unchanged. A `ForkDigest`-context is used to select
|
|||
Per `context = compute_fork_digest(fork_version, genesis_validators_root)`:
|
||||
|
||||
| `fork_version` | Chunk SSZ type |
|
||||
| ------------------------ | -------------------------- |
|
||||
| `GENESIS_FORK_VERSION` | `phase0.SignedBeaconBlock` |
|
||||
| `ALTAIR_FORK_VERSION` | `altair.SignedBeaconBlock` |
|
||||
|
||||
|
|
|
@ -220,8 +220,7 @@ Given a collection of the best seen `contributions` (with no repeating `subcommi
|
|||
the proposer processes them as follows:
|
||||
|
||||
```python
|
||||
def process_sync_committee_contributions(state: BeaconState,
|
||||
block: BeaconBlock,
|
||||
def process_sync_committee_contributions(block: BeaconBlock,
|
||||
contributions: Set[SyncCommitteeContribution]) -> None:
|
||||
sync_aggregate = SyncAggregate()
|
||||
signatures = []
|
||||
|
@ -310,12 +309,12 @@ Each slot some sync committee members in each subcommittee are selected to aggre
|
|||
|
||||
##### Aggregation selection
|
||||
|
||||
A validator is selected to aggregate based on the computation in `is_sync_committee_aggregator` where `state` is a `BeaconState` as supplied to `get_sync_committee_slot_signature` and `signature` is the BLS signature returned by `get_sync_committee_slot_signature`.
|
||||
A validator is selected to aggregate based on the computation in `is_sync_committee_aggregator` where `signature` is the BLS signature returned by `get_sync_committee_selection_proof`.
|
||||
The signature function takes a `BeaconState` with the relevant sync committees for the queried `slot` (i.e. `state.slot` is within the span covered by the current or next sync committee period), the `subcommittee_index` equal to the `subnet_id`, and the `privkey` is the BLS private key associated with the validator.
|
||||
|
||||
```python
|
||||
def get_sync_committee_slot_signature(state: BeaconState, slot: Slot,
|
||||
subcommittee_index: uint64, privkey: int) -> BLSSignature:
|
||||
def get_sync_committee_selection_proof(state: BeaconState, slot: Slot,
|
||||
subcommittee_index: uint64, privkey: int) -> BLSSignature:
|
||||
domain = get_domain(state, DOMAIN_SYNC_COMMITTEE_SELECTION_PROOF, compute_epoch_at_slot(slot))
|
||||
signing_data = SyncCommitteeSigningData(
|
||||
slot=slot,
|
||||
|
@ -326,7 +325,7 @@ def get_sync_committee_slot_signature(state: BeaconState, slot: Slot,
|
|||
```
|
||||
|
||||
```python
|
||||
def is_sync_committee_aggregator(state: BeaconState, signature: BLSSignature) -> bool:
|
||||
def is_sync_committee_aggregator(signature: BLSSignature) -> bool:
|
||||
modulo = max(1, SYNC_COMMITTEE_SIZE // SYNC_COMMITTEE_SUBNET_COUNT // TARGET_AGGREGATORS_PER_SYNC_SUBCOMMITTEE)
|
||||
return bytes_to_uint64(hash(signature)[0:8]) % modulo == 0
|
||||
```
|
||||
|
@ -378,7 +377,7 @@ def get_contribution_and_proof(state: BeaconState,
|
|||
aggregator_index: ValidatorIndex,
|
||||
contribution: SyncCommitteeContribution,
|
||||
privkey: int) -> ContributionAndProof:
|
||||
selection_proof = get_sync_committee_slot_signature(
|
||||
selection_proof = get_sync_committee_selection_proof(
|
||||
state,
|
||||
contribution.slot,
|
||||
contribution.subcommittee_index,
|
||||
|
@ -391,7 +390,7 @@ def get_contribution_and_proof(state: BeaconState,
|
|||
)
|
||||
```
|
||||
|
||||
Then `signed_contribution_and_proof = SignedContributionAndProof(message=contribution_and_proof, signature=signature)` is constructed and broadast. Where `signature` is obtained from:
|
||||
Then `signed_contribution_and_proof = SignedContributionAndProof(message=contribution_and_proof, signature=signature)` is constructed and broadcast. Where `signature` is obtained from:
|
||||
|
||||
```python
|
||||
def get_contribution_and_proof_signature(state: BeaconState,
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
- [Configuration](#configuration)
|
||||
- [Misc](#misc)
|
||||
- [New containers](#new-containers)
|
||||
- [DASSample](#dassample)
|
||||
- [`DASSample`](#dassample)
|
||||
- [Helper functions](#helper-functions)
|
||||
- [Reverse bit ordering](#reverse-bit-ordering)
|
||||
- [`reverse_bit_order`](#reverse_bit_order)
|
||||
|
@ -45,7 +45,7 @@ We define the following Python custom types for type hinting and readability:
|
|||
|
||||
## New containers
|
||||
|
||||
### DASSample
|
||||
### `DASSample`
|
||||
|
||||
```python
|
||||
class DASSample(Container):
|
||||
|
|
|
@ -589,7 +589,7 @@ def get_aggregate_and_proof(state: BeaconState,
|
|||
)
|
||||
```
|
||||
|
||||
Then `signed_aggregate_and_proof = SignedAggregateAndProof(message=aggregate_and_proof, signature=signature)` is constructed and broadast. Where `signature` is obtained from:
|
||||
Then `signed_aggregate_and_proof = SignedAggregateAndProof(message=aggregate_and_proof, signature=signature)` is constructed and broadcast. Where `signature` is obtained from:
|
||||
|
||||
```python
|
||||
def get_aggregate_and_proof_signature(state: BeaconState,
|
||||
|
|
|
@ -75,7 +75,7 @@ We define the following Python custom types for type hinting and readability:
|
|||
| Name | SSZ equivalent | Description |
|
||||
| - | - | - |
|
||||
| `Shard` | `uint64` | A shard number |
|
||||
| `BLSCommitment` | `bytes48` | A G1 curve point |
|
||||
| `BLSCommitment` | `Bytes48` | A G1 curve point |
|
||||
| `BLSPoint` | `uint256` | A number `x` in the range `0 <= x < MODULUS` |
|
||||
|
||||
## Constants
|
||||
|
@ -114,7 +114,7 @@ The following values are (non-configurable) constants used throughout the specif
|
|||
| - | - |
|
||||
| `G1_SETUP` | Type `List[G1]`. The G1-side trusted setup `[G, G*s, G*s**2....]`; note that the first point is the generator. |
|
||||
| `G2_SETUP` | Type `List[G2]`. The G2-side trusted setup `[G, G*s, G*s**2....]` |
|
||||
| `ROOT_OF_UNITY` | `pow(PRIMITIVE_ROOT_OF_UNITY, (MODULUS - 1) // (MAX_SAMPLES_PER_BLOCK * POINTS_PER_SAMPLE, MODULUS)` |
|
||||
| `ROOT_OF_UNITY` | `pow(PRIMITIVE_ROOT_OF_UNITY, (MODULUS - 1) // (MAX_SAMPLES_PER_BLOCK * POINTS_PER_SAMPLE), MODULUS)` |
|
||||
|
||||
### Gwei values
|
||||
|
||||
|
@ -241,7 +241,7 @@ class PendingShardHeader(Container):
|
|||
# Who voted for the header
|
||||
votes: Bitlist[MAX_VALIDATORS_PER_COMMITTEE]
|
||||
# Has this header been confirmed?
|
||||
confirmed: bool
|
||||
confirmed: boolean
|
||||
```
|
||||
|
||||
### `ShardBlobReference`
|
||||
|
@ -572,7 +572,7 @@ def process_shard_header(state: BeaconState,
|
|||
assert body_summary.degree_proof == G1_SETUP[0]
|
||||
assert (
|
||||
bls.Pairing(body_summary.degree_proof, G2_SETUP[0])
|
||||
== bls.Pairing(body_summary.commitment.point, G2_SETUP[-body_summary.commitment.length]))
|
||||
== bls.Pairing(body_summary.commitment.point, G2_SETUP[-body_summary.commitment.length])
|
||||
)
|
||||
|
||||
# Get the correct pending header list
|
||||
|
@ -704,7 +704,7 @@ def process_pending_headers(state: BeaconState) -> None:
|
|||
for slot_index in range(SLOTS_PER_EPOCH):
|
||||
for shard in range(SHARD_COUNT):
|
||||
state.grandparent_epoch_confirmed_commitments[shard][slot_index] = DataCommitment()
|
||||
confirmed_headers = [candidate in state.previous_epoch_pending_shard_headers if candidate.confirmed]
|
||||
confirmed_headers = [candidate for candidate in state.previous_epoch_pending_shard_headers if candidate.confirmed]
|
||||
for header in confirmed_headers:
|
||||
state.grandparent_epoch_confirmed_commitments[c.shard][c.slot % SLOTS_PER_EPOCH] = c.commitment
|
||||
```
|
||||
|
@ -752,7 +752,7 @@ def reset_pending_headers(state: BeaconState) -> None:
|
|||
next_epoch = get_current_epoch(state) + 1
|
||||
next_epoch_start_slot = compute_start_slot_at_epoch(next_epoch)
|
||||
for slot in range(next_epoch_start_slot, next_epoch_start_slot + SLOTS_IN_EPOCH):
|
||||
for index in range(get_committee_count_per_slot(next_epoch):
|
||||
for index in range(get_committee_count_per_slot(next_epoch)):
|
||||
shard = compute_shard_from_committee_index(state, slot, index)
|
||||
committee_length = len(get_beacon_committee(state, slot, shard))
|
||||
state.current_epoch_pending_shard_headers.append(PendingShardHeader(
|
||||
|
|
|
@ -1 +1 @@
|
|||
1.1.0-alpha.1
|
||||
1.1.0-alpha.3
|
|
@ -126,8 +126,7 @@ def compute_sync_committee_participant_reward(spec, state, participant_index, co
|
|||
inclusion_reward = compute_sync_committee_inclusion_reward(
|
||||
spec, state, participant_index, committee, committee_bits,
|
||||
)
|
||||
proposer_reward = spec.Gwei(inclusion_reward // spec.PROPOSER_REWARD_QUOTIENT)
|
||||
return spec.Gwei((inclusion_reward - proposer_reward) * multiplicities[participant_index])
|
||||
return spec.Gwei(inclusion_reward * multiplicities[participant_index])
|
||||
|
||||
|
||||
def compute_sync_committee_proposer_reward(spec, state, committee, committee_bits):
|
||||
|
@ -138,7 +137,12 @@ def compute_sync_committee_proposer_reward(spec, state, committee, committee_bit
|
|||
inclusion_reward = compute_sync_committee_inclusion_reward(
|
||||
spec, state, index, committee, committee_bits,
|
||||
)
|
||||
proposer_reward += spec.Gwei(inclusion_reward // spec.PROPOSER_REWARD_QUOTIENT)
|
||||
proposer_reward_denominator = (
|
||||
(spec.WEIGHT_DENOMINATOR - spec.PROPOSER_WEIGHT)
|
||||
* spec.WEIGHT_DENOMINATOR
|
||||
// spec.PROPOSER_WEIGHT
|
||||
)
|
||||
proposer_reward += spec.Gwei((inclusion_reward * spec.WEIGHT_DENOMINATOR) // proposer_reward_denominator)
|
||||
return proposer_reward
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue