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?
|
# 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:
|
||||||
|
|
|
@ -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
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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(
|
||||||
|
|
Loading…
Reference in New Issue