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:
parent
1eef531259
commit
43a9e904cf
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
)
|
||||
)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(
|
||||
|
|
Loading…
Reference in New Issue