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

View File

@ -246,10 +246,6 @@ func get_genesis_beacon_state*(
deposit_index: 0, 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 # Process genesis deposits
for deposit in genesis_validator_deposits: for deposit in genesis_validator_deposits:
discard process_deposit(state, deposit, flags) discard process_deposit(state, deposit, flags)
@ -278,25 +274,22 @@ func get_initial_beacon_block*(state: BeaconState): BeaconBlock =
# initialized to default values. # initialized to default values.
) )
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#get_attestation_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_slot*(state: BeaconState, func get_attestation_data_slot*(state: BeaconState,
attestation: Attestation|PendingAttestation, data: AttestationData, committee_count: uint64): Slot =
committee_count: uint64): Slot =
let let
epoch = attestation.data.target_epoch offset = (data.crosslink.shard + SHARD_COUNT -
offset = (attestation.data.shard + SHARD_COUNT - get_epoch_start_shard(state, data.target_epoch)) mod SHARD_COUNT
get_epoch_start_shard(state, epoch)) mod SHARD_COUNT
# TODO re-instate once double-check correct conditions in attestation pool # TODO re-instate once double-check correct conditions in attestation pool
#get_epoch_start_slot(epoch) + offset div (committee_count div SLOTS_PER_EPOCH) #get_epoch_start_slot(data.target_epoch) + offset div (committee_count div SLOTS_PER_EPOCH)
attestation.data.slot data.slot
# This is the slower (O(n)), spec-compatible signature. # This is the slower (O(n)), spec-compatible signature.
func get_attestation_slot*(state: BeaconState, func get_attestation_data_slot*(state: BeaconState,
attestation: Attestation|PendingAttestation): Slot = data: AttestationData): Slot =
let epoch = attestation.data.target_epoch get_attestation_data_slot(
get_attestation_slot( state, data, get_epoch_committee_count(state, data.target_epoch))
state, attestation, get_epoch_committee_count(state, epoch))
# https://github.com/ethereum/eth2.0-specs/blob/v0.7.1/specs/core/0_beacon-chain.md#get_block_root_at_slot # 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, 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. ## possible to follow the spec more literally.
result = initSet[ValidatorIndex]() result = initSet[ValidatorIndex]()
let committee = let committee =
get_crosslink_committee(state, attestation_data.target_epoch, get_crosslink_committee(
attestation_data.shard, stateCache) state, attestation_data.target_epoch, attestation_data.crosslink.shard,
stateCache)
doAssert verify_bitfield(bitfield, len(committee)) doAssert verify_bitfield(bitfield, len(committee))
for i, index in committee: for i, index in committee:
if get_bitfield_bit(bitfield, i): if get_bitfield_bit(bitfield, i):
@ -508,7 +502,7 @@ proc checkAttestation*(
let let
data = attestation.data 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): if not (attestation_slot + MIN_ATTESTATION_INCLUSION_DELAY <= stateSlot):
warn("Attestation too new", warn("Attestation too new",
@ -602,13 +596,15 @@ proc makeAttestationData*(
AttestationData( AttestationData(
slot: state.slot, 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, beacon_block_root: beacon_block_root,
target_root: target_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_epoch: state.current_justified_epoch,
source_root: state.current_justified_root, 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 target_root*: Eth2Digest
# Crosslink vote # Crosslink vote
shard*: uint64 crosslink*: Crosslink
previous_crosslink_root*: Eth2Digest
crosslink_data_root*: Eth2Digest
# https://github.com/ethereum/eth2.0-specs/blob/v0.7.1/specs/core/0_beacon-chain.md#attestationdataandcustodybit # https://github.com/ethereum/eth2.0-specs/blob/v0.7.1/specs/core/0_beacon-chain.md#attestationdataandcustodybit
AttestationDataAndCustodyBit* = object AttestationDataAndCustodyBit* = object
@ -309,16 +307,20 @@ type
effective_balance*: uint64 ##\ effective_balance*: uint64 ##\
## Effective balance ## 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 Crosslink* = object
epoch*: Epoch ##\ shard*: Shard ##\
## Epoch number ## 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 ## Root of the previous crosslink
crosslink_data_root*: Eth2Digest ##\ data_root*: Eth2Digest ##\
## Shard data since the previous crosslink ## 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 # https://github.com/ethereum/eth2.0-specs/blob/v0.7.1/specs/core/0_beacon-chain.md#pendingattestation
PendingAttestation* = object PendingAttestation* = object
@ -451,8 +453,7 @@ func shortLog*(v: AttestationData): auto =
shortLog(v.beacon_block_root), shortLog(v.beacon_block_root),
humaneEpochNum(v.source_epoch), shortLog(v.target_root), humaneEpochNum(v.source_epoch), shortLog(v.target_root),
shortLog(v.source_root), shortLog(v.source_root),
v.shard, v.previous_crosslink_root, v.crosslink
shortLog(v.crosslink_data_root)
) )
chronicles.formatIt Slot: it.humaneSlotNum chronicles.formatIt Slot: it.humaneSlotNum

View File

@ -264,7 +264,7 @@ proc processAttestations(
# Spec content # Spec content
let attestation_slot = let attestation_slot =
get_attestation_slot(state, attestation, committee_count) get_attestation_data_slot(state, attestation.data, committee_count)
let pending_attestation = PendingAttestation( let pending_attestation = PendingAttestation(
data: attestation.data, data: attestation.data,
aggregation_bitfield: attestation.aggregation_bitfield, aggregation_bitfield: attestation.aggregation_bitfield,
@ -507,7 +507,7 @@ func get_matching_head_attestations(state: BeaconState, epoch: Epoch):
filterIt( filterIt(
get_matching_source_attestations(state, epoch), get_matching_source_attestations(state, epoch),
it.data.beacon_block_root == 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( func get_unslashed_attesting_indices(
@ -528,15 +528,6 @@ func get_attesting_balance(
get_total_balance(state, get_unslashed_attesting_indices( get_total_balance(state, get_unslashed_attesting_indices(
state, attestations, stateCache)) 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 # Not exactly in spec, but for get_winning_crosslink_and_attesting_indices
func lowerThan(candidate, current: Eth2Digest): bool = func lowerThan(candidate, current: Eth2Digest): bool =
# return true iff candidate is "lower" than current, per spec rule: # 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, state: BeaconState, epoch: Epoch, shard: Shard,
stateCache: var StateCache): tuple[a: Crosslink, b: HashSet[ValidatorIndex]] = stateCache: var StateCache): tuple[a: Crosslink, b: HashSet[ValidatorIndex]] =
let let
## TODO Z-F could help here attestations =
## TODO get_winning_crosslink_and_attesting_indices was profiling hotspot
shard_attestations =
filterIt( filterIt(
get_matching_source_attestations(state, epoch), it.data.shard == shard) get_matching_source_attestations(state, epoch),
shard_crosslinks = it.data.crosslink.shard == shard)
mapIt(shard_attestations, # TODO don't keep h_t_r'ing state.current_crosslinks[shard]
get_crosslink_from_attestation_data(state, it.data)) crosslinks =
# TODO this seems like a lot of hash_tree_root'ing on same data filterIt(
candidate_crosslinks = mapIt(attestations, it.data.crosslink),
filterIt(shard_crosslinks,
hash_tree_root(state.current_crosslinks[shard]) in hash_tree_root(state.current_crosslinks[shard]) in
# TODO pointless memory allocation, etc. # 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]()) 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 ## Winning crosslink has the crosslink data root with the most balance voting
## for it (ties broken lexicographically) ## for it (ties broken lexicographically)
var var
winning_crosslink: Crosslink winning_crosslink: Crosslink
winning_crosslink_balance = 0.Gwei winning_crosslink_balance = 0.Gwei
for candidate_crosslink in candidate_crosslinks: for candidate_crosslink in crosslinks:
## TODO check if should cache this again ## TODO check if should cache this again
## let root_balance = get_attesting_balance_cached( ## let root_balance = get_attesting_balance_cached(
## state, attestations_for.getOrDefault(r), cache) ## state, attestations_for.getOrDefault(r), cache)
let crosslink_balance = let crosslink_balance =
get_attesting_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 if (crosslink_balance > winning_crosslink_balance or
(winning_crosslink_balance == crosslink_balance and (winning_crosslink_balance == crosslink_balance and
lowerThan(winning_crosslink.crosslink_data_root, lowerThan(winning_crosslink.data_root,
candidate_crosslink.crosslink_data_root))): candidate_crosslink.data_root))):
winning_crosslink = candidate_crosslink winning_crosslink = candidate_crosslink
winning_crosslink_balance = crosslink_balance winning_crosslink_balance = crosslink_balance
let winning_attestations =
filterIt(attestations, it.data.crosslink == winning_crosslink)
(winning_crosslink, (winning_crosslink,
get_unslashed_attesting_indices(state, get_unslashed_attesting_indices(state, winning_attestations, stateCache))
get_attestations_for(winning_crosslink), stateCache))
# https://github.com/ethereum/eth2.0-specs/blob/v0.7.1/specs/core/0_beacon-chain.md#justification-and-finalization # 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( func process_justification_and_finalization(