replace get_attestation_slot(...) with 0.7.1 get_attestation_data_slot(...) and update all callers; update AttestationData to be almost 0.7.1, except nonextistent slot field; update Crosslink and get_winning_crosslink_and_attesting_indices(...) to 0.7.1 (#297)

This commit is contained in:
Dustin Brody 2019-06-25 11:17:08 +00:00 committed by GitHub
parent 1eef531259
commit 43a9e904cf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 59 additions and 85 deletions

View File

@ -38,7 +38,7 @@ proc validate(
# TODO half of this stuff is from beaconstate.validateAttestation - merge?
let attestationSlot = get_attestation_slot(state, attestation)
let attestationSlot = get_attestation_data_slot(state, attestation.data)
if attestationSlot < state.finalized_epoch.get_epoch_start_slot():
debug "Old attestation",
@ -99,7 +99,7 @@ proc validate(
],
attestation.signature,
get_domain(state, DOMAIN_ATTESTATION,
slot_to_epoch(get_attestation_slot(state, attestation))),
slot_to_epoch(get_attestation_data_slot(state, attestation.data))),
):
notice "Invalid signature", participants
return false
@ -174,7 +174,7 @@ proc add*(pool: var AttestationPool,
# TODO inefficient data structures..
let
attestationSlot = get_attestation_slot(state, attestation)
attestationSlot = get_attestation_data_slot(state, attestation.data)
idx = pool.slotIndex(state, attestationSlot)
slotData = addr pool.slots[idx]
validation = Validation(
@ -326,7 +326,7 @@ proc resolve*(pool: var AttestationPool, state: BeaconState) =
var resolved: seq[Attestation]
for k, v in pool.unresolved.mpairs():
let attestation_slot = get_attestation_slot(state, v.attestation)
let attestation_slot = get_attestation_data_slot(state, v.attestation.data)
if v.tries > 8 or attestation_slot < pool.startingSlot:
done.add(k)
else:

View File

@ -246,10 +246,6 @@ func get_genesis_beacon_state*(
deposit_index: 0,
)
for i in 0 ..< SHARD_COUNT:
state.current_crosslinks[i] = Crosslink(
epoch: GENESIS_EPOCH, crosslink_data_root: ZERO_HASH)
# Process genesis deposits
for deposit in genesis_validator_deposits:
discard process_deposit(state, deposit, flags)
@ -278,25 +274,22 @@ func get_initial_beacon_block*(state: BeaconState): BeaconBlock =
# initialized to default values.
)
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#get_attestation_slot
func get_attestation_slot*(state: BeaconState,
attestation: Attestation|PendingAttestation,
committee_count: uint64): Slot =
# https://github.com/ethereum/eth2.0-specs/blob/v0.7.1/specs/core/0_beacon-chain.md#get_attestation_data_slot
func get_attestation_data_slot*(state: BeaconState,
data: AttestationData, committee_count: uint64): Slot =
let
epoch = attestation.data.target_epoch
offset = (attestation.data.shard + SHARD_COUNT -
get_epoch_start_shard(state, epoch)) mod SHARD_COUNT
offset = (data.crosslink.shard + SHARD_COUNT -
get_epoch_start_shard(state, data.target_epoch)) mod SHARD_COUNT
# TODO re-instate once double-check correct conditions in attestation pool
#get_epoch_start_slot(epoch) + offset div (committee_count div SLOTS_PER_EPOCH)
attestation.data.slot
#get_epoch_start_slot(data.target_epoch) + offset div (committee_count div SLOTS_PER_EPOCH)
data.slot
# This is the slower (O(n)), spec-compatible signature.
func get_attestation_slot*(state: BeaconState,
attestation: Attestation|PendingAttestation): Slot =
let epoch = attestation.data.target_epoch
get_attestation_slot(
state, attestation, get_epoch_committee_count(state, epoch))
func get_attestation_data_slot*(state: BeaconState,
data: AttestationData): Slot =
get_attestation_data_slot(
state, data, get_epoch_committee_count(state, data.target_epoch))
# https://github.com/ethereum/eth2.0-specs/blob/v0.7.1/specs/core/0_beacon-chain.md#get_block_root_at_slot
func get_block_root_at_slot*(state: BeaconState,
@ -425,8 +418,9 @@ func get_attesting_indices*(state: BeaconState,
## possible to follow the spec more literally.
result = initSet[ValidatorIndex]()
let committee =
get_crosslink_committee(state, attestation_data.target_epoch,
attestation_data.shard, stateCache)
get_crosslink_committee(
state, attestation_data.target_epoch, attestation_data.crosslink.shard,
stateCache)
doAssert verify_bitfield(bitfield, len(committee))
for i, index in committee:
if get_bitfield_bit(bitfield, i):
@ -508,7 +502,7 @@ proc checkAttestation*(
let
data = attestation.data
attestation_slot = get_attestation_slot(state, attestation)
attestation_slot = get_attestation_data_slot(state, attestation.data)
if not (attestation_slot + MIN_ATTESTATION_INCLUSION_DELAY <= stateSlot):
warn("Attestation too new",
@ -602,13 +596,15 @@ proc makeAttestationData*(
AttestationData(
slot: state.slot,
# Alternative is to put this offset into all callers
shard: shard + get_epoch_start_shard(state, slot_to_epoch(state.slot)),
beacon_block_root: beacon_block_root,
target_root: target_root,
crosslink_data_root: Eth2Digest(), # Stub in phase0
previous_crosslink_root: hash_tree_root(state.current_crosslinks[shard]),
source_epoch: state.current_justified_epoch,
source_root: state.current_justified_root,
target_epoch: slot_to_epoch(state.slot)
target_epoch: slot_to_epoch(state.slot),
crosslink: Crosslink(
# Alternative is to put this offset into all callers
shard: shard + get_epoch_start_shard(state, slot_to_epoch(state.slot)),
parent_root: hash_tree_root(state.current_crosslinks[shard]),
data_root: Eth2Digest(), # Stub in phase0
)
)

View File

@ -130,9 +130,7 @@ type
target_root*: Eth2Digest
# Crosslink vote
shard*: uint64
previous_crosslink_root*: Eth2Digest
crosslink_data_root*: Eth2Digest
crosslink*: Crosslink
# https://github.com/ethereum/eth2.0-specs/blob/v0.7.1/specs/core/0_beacon-chain.md#attestationdataandcustodybit
AttestationDataAndCustodyBit* = object
@ -309,16 +307,20 @@ type
effective_balance*: uint64 ##\
## Effective balance
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.3/specs/core/0_beacon-chain.md#crosslink
# https://github.com/ethereum/eth2.0-specs/blob/v0.7.1/specs/core/0_beacon-chain.md#crosslink
Crosslink* = object
epoch*: Epoch ##\
## Epoch number
shard*: Shard ##\
## Shard number
previous_crosslink_root*: Eth2Digest ##\
start_epoch*: Epoch
end_epoch*: Epoch ##\
## Crosslinking data from epochs [start....end-1]
parent_root*: Eth2Digest ##\
## Root of the previous crosslink
crosslink_data_root*: Eth2Digest ##\
## Shard data since the previous crosslink
data_root*: Eth2Digest ##\
## Root of the crosslinked shard data since the previous crosslink
# https://github.com/ethereum/eth2.0-specs/blob/v0.7.1/specs/core/0_beacon-chain.md#pendingattestation
PendingAttestation* = object
@ -451,8 +453,7 @@ func shortLog*(v: AttestationData): auto =
shortLog(v.beacon_block_root),
humaneEpochNum(v.source_epoch), shortLog(v.target_root),
shortLog(v.source_root),
v.shard, v.previous_crosslink_root,
shortLog(v.crosslink_data_root)
v.crosslink
)
chronicles.formatIt Slot: it.humaneSlotNum

View File

@ -264,7 +264,7 @@ proc processAttestations(
# Spec content
let attestation_slot =
get_attestation_slot(state, attestation, committee_count)
get_attestation_data_slot(state, attestation.data, committee_count)
let pending_attestation = PendingAttestation(
data: attestation.data,
aggregation_bitfield: attestation.aggregation_bitfield,
@ -507,7 +507,7 @@ func get_matching_head_attestations(state: BeaconState, epoch: Epoch):
filterIt(
get_matching_source_attestations(state, epoch),
it.data.beacon_block_root ==
get_block_root_at_slot(state, get_attestation_slot(state, it))
get_block_root_at_slot(state, get_attestation_data_slot(state, it.data))
)
func get_unslashed_attesting_indices(
@ -528,15 +528,6 @@ func get_attesting_balance(
get_total_balance(state, get_unslashed_attesting_indices(
state, attestations, stateCache))
func get_crosslink_from_attestation_data(
state: BeaconState, data: AttestationData): Crosslink =
Crosslink(
epoch: min(data.target_epoch,
state.current_crosslinks[data.shard].epoch + MAX_CROSSLINK_EPOCHS),
previous_crosslink_root: data.previous_crosslink_root,
crosslink_data_root: data.crosslink_data_root,
)
# Not exactly in spec, but for get_winning_crosslink_and_attesting_indices
func lowerThan(candidate, current: Eth2Digest): bool =
# return true iff candidate is "lower" than current, per spec rule:
@ -549,62 +540,48 @@ func get_winning_crosslink_and_attesting_indices(
state: BeaconState, epoch: Epoch, shard: Shard,
stateCache: var StateCache): tuple[a: Crosslink, b: HashSet[ValidatorIndex]] =
let
## TODO Z-F could help here
## TODO get_winning_crosslink_and_attesting_indices was profiling hotspot
shard_attestations =
attestations =
filterIt(
get_matching_source_attestations(state, epoch), it.data.shard == shard)
shard_crosslinks =
mapIt(shard_attestations,
get_crosslink_from_attestation_data(state, it.data))
# TODO this seems like a lot of hash_tree_root'ing on same data
candidate_crosslinks =
filterIt(shard_crosslinks,
get_matching_source_attestations(state, epoch),
it.data.crosslink.shard == shard)
# TODO don't keep h_t_r'ing state.current_crosslinks[shard]
crosslinks =
filterIt(
mapIt(attestations, it.data.crosslink),
hash_tree_root(state.current_crosslinks[shard]) in
# TODO pointless memory allocation, etc.
@[it.previous_crosslink_root, hash_tree_root(it)])
@[it.parent_root, hash_tree_root(it)])
if len(candidate_crosslinks) == 0:
# default=Crosslink()
if len(crosslinks) == 0:
return (Crosslink(), initSet[ValidatorIndex]())
## TODO check if should cache this again, as with 0.5
## var attestations_for = initTable[Eth2Digest, seq[PendingAttestation]]()
## for valid_attestation in valid_attestations:
## if valid_attestation.data.crosslink_data_root in attestations_for:
## attestations_for[valid_attestation.data.crosslink_data_root].add(
## valid_attestation)
## else:
## attestations_for[valid_attestation.data.crosslink_data_root] =
## @[valid_attestation]
## TODO either way, this nested function not great; {.fastcall.} pragma
## not directly applicable either, since it does need some closure
func get_attestations_for(crosslink: Crosslink): seq[PendingAttestation] =
filterIt(shard_attestations,
get_crosslink_from_attestation_data(state, it.data) == crosslink)
## Winning crosslink has the crosslink data root with the most balance voting
## for it (ties broken lexicographically)
var
winning_crosslink: Crosslink
winning_crosslink_balance = 0.Gwei
for candidate_crosslink in candidate_crosslinks:
for candidate_crosslink in crosslinks:
## TODO check if should cache this again
## let root_balance = get_attesting_balance_cached(
## state, attestations_for.getOrDefault(r), cache)
let crosslink_balance =
get_attesting_balance(
state, get_attestations_for(candidate_crosslink), stateCache)
state,
filterIt(attestations, it.data.crosslink == candidate_crosslink),
stateCache)
if (crosslink_balance > winning_crosslink_balance or
(winning_crosslink_balance == crosslink_balance and
lowerThan(winning_crosslink.crosslink_data_root,
candidate_crosslink.crosslink_data_root))):
lowerThan(winning_crosslink.data_root,
candidate_crosslink.data_root))):
winning_crosslink = candidate_crosslink
winning_crosslink_balance = crosslink_balance
let winning_attestations =
filterIt(attestations, it.data.crosslink == winning_crosslink)
(winning_crosslink,
get_unslashed_attesting_indices(state,
get_attestations_for(winning_crosslink), stateCache))
get_unslashed_attesting_indices(state, winning_attestations, stateCache))
# https://github.com/ethereum/eth2.0-specs/blob/v0.7.1/specs/core/0_beacon-chain.md#justification-and-finalization
func process_justification_and_finalization(