state_sim optimizations (#597)
* switch out quadratically scaling and wasteful attestation in state_sim to attest only to exactly the correct slots; avoid pointless committee index interconversion for 9-10x increase in state_sim speed at d:release, 60k validators, and validate=off * remove debugechos
This commit is contained in:
parent
63f49eff76
commit
45b7595ba1
|
@ -57,7 +57,7 @@ cli do(slots = SLOTS_PER_EPOCH * 6,
|
||||||
validators = SLOTS_PER_EPOCH * 11, # One per shard is minimum
|
validators = SLOTS_PER_EPOCH * 11, # One per shard is minimum
|
||||||
json_interval = SLOTS_PER_EPOCH,
|
json_interval = SLOTS_PER_EPOCH,
|
||||||
prefix = 0,
|
prefix = 0,
|
||||||
attesterRatio {.desc: "ratio of validators that attest in each round"} = 0.75,
|
attesterRatio {.desc: "ratio of validators that attest in each round"} = 0.73,
|
||||||
validate = true):
|
validate = true):
|
||||||
let
|
let
|
||||||
flags = if validate: {} else: {skipValidation}
|
flags = if validate: {} else: {skipValidation}
|
||||||
|
@ -83,6 +83,10 @@ cli do(slots = SLOTS_PER_EPOCH * 6,
|
||||||
else:
|
else:
|
||||||
write(stdout, ".")
|
write(stdout, ".")
|
||||||
|
|
||||||
|
# TODO doAssert against this up-front
|
||||||
|
# indexed attestation: validator index beyond max validators per committee
|
||||||
|
# len(indices) <= MAX_VALIDATORS_PER_COMMITTEE
|
||||||
|
|
||||||
for i in 0..<slots:
|
for i in 0..<slots:
|
||||||
maybeWrite()
|
maybeWrite()
|
||||||
verifyConsensus(state, attesterRatio)
|
verifyConsensus(state, attesterRatio)
|
||||||
|
@ -111,15 +115,13 @@ cli do(slots = SLOTS_PER_EPOCH * 6,
|
||||||
# work for every slot - we'll randomize it deterministically to give
|
# work for every slot - we'll randomize it deterministically to give
|
||||||
# some variation
|
# some variation
|
||||||
let
|
let
|
||||||
epoch = compute_epoch_at_slot(state.slot)
|
target_slot = state.slot + MIN_ATTESTATION_INCLUSION_DELAY - 1
|
||||||
scass = withTimerRet(timers[tShuffle]):
|
scass = withTimerRet(timers[tShuffle]):
|
||||||
mapIt(
|
mapIt(
|
||||||
0'u64 .. (get_committee_count_at_slot(state, state.slot) *
|
0'u64 ..< get_committee_count_at_slot(state, target_slot),
|
||||||
SLOTS_PER_EPOCH - 1),
|
get_beacon_committee(state, target_slot, it, cache))
|
||||||
get_beacon_committee(state, epoch.compute_start_slot_at_epoch + (it mod SLOTS_PER_EPOCH),
|
|
||||||
it div SLOTS_PER_EPOCH, cache))
|
|
||||||
|
|
||||||
for scas in scass:
|
for i, scas in scass:
|
||||||
var
|
var
|
||||||
attestation: Attestation
|
attestation: Attestation
|
||||||
first = true
|
first = true
|
||||||
|
@ -131,11 +133,13 @@ cli do(slots = SLOTS_PER_EPOCH * 6,
|
||||||
if (rand(r, high(int)).float * attesterRatio).int <= high(int):
|
if (rand(r, high(int)).float * attesterRatio).int <= high(int):
|
||||||
if first:
|
if first:
|
||||||
attestation =
|
attestation =
|
||||||
makeAttestation(state, latest_block_root, v, cache, flags)
|
makeAttestation(state, latest_block_root, scas, target_slot,
|
||||||
|
i.uint64, v, cache, flags)
|
||||||
first = false
|
first = false
|
||||||
else:
|
else:
|
||||||
attestation.combine(
|
attestation.combine(
|
||||||
makeAttestation(state, latest_block_root, v, cache, flags),
|
makeAttestation(state, latest_block_root, scas, target_slot,
|
||||||
|
i.uint64, v, cache, flags),
|
||||||
flags)
|
flags)
|
||||||
|
|
||||||
if not first:
|
if not first:
|
||||||
|
@ -145,11 +149,7 @@ cli do(slots = SLOTS_PER_EPOCH * 6,
|
||||||
let target_slot =
|
let target_slot =
|
||||||
attestation.data.slot + MIN_ATTESTATION_INCLUSION_DELAY - 1
|
attestation.data.slot + MIN_ATTESTATION_INCLUSION_DELAY - 1
|
||||||
|
|
||||||
## In principle, should enumerate possible shard/slot combinations by
|
doAssert target_slot > attestations_idx
|
||||||
## inverting get_attestation_data_slot(...), but this works. Could be
|
|
||||||
## filtering earlier if we know that this attestation's being created
|
|
||||||
## too late to be useful, as well.
|
|
||||||
if target_slot > attestations_idx:
|
|
||||||
var target_slot_attestations =
|
var target_slot_attestations =
|
||||||
getOrDefault(attestations, target_slot)
|
getOrDefault(attestations, target_slot)
|
||||||
target_slot_attestations.add attestation
|
target_slot_attestations.add attestation
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
# beacon_chain
|
# beacon_chain
|
||||||
# Copyright (c) 2019 Status Research & Development GmbH
|
# Copyright (c) 2019 Status Research & Development GmbH
|
||||||
# Licensed and distributed under either of
|
# Licensed and distributed under either of
|
||||||
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
|
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
|
||||||
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
|
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
|
||||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import
|
import
|
||||||
|
|
|
@ -164,11 +164,14 @@ proc find_beacon_committee(
|
||||||
|
|
||||||
proc makeAttestation*(
|
proc makeAttestation*(
|
||||||
state: BeaconState, beacon_block_root: Eth2Digest,
|
state: BeaconState, beacon_block_root: Eth2Digest,
|
||||||
validator_index: ValidatorIndex, cache: var StateCache,
|
committee: seq[ValidatorIndex], slot: Slot, index: uint64,
|
||||||
|
validator_index: auto, cache: var StateCache,
|
||||||
flags: UpdateFlags = {}): Attestation =
|
flags: UpdateFlags = {}): Attestation =
|
||||||
|
# Avoids state_sim silliness; as it's responsible for all validators,
|
||||||
|
# transforming, from monotonic enumerable index -> committee index ->
|
||||||
|
# montonoic enumerable index, is wasteful and slow. Most test callers
|
||||||
|
# want ValidatorIndex, so that's supported too.
|
||||||
let
|
let
|
||||||
(committee, slot, index) =
|
|
||||||
find_beacon_committee(state, validator_index, cache)
|
|
||||||
validator = state.validators[validator_index]
|
validator = state.validators[validator_index]
|
||||||
sac_index = committee.find(validator_index)
|
sac_index = committee.find(validator_index)
|
||||||
data = makeAttestationData(state, slot, index, beacon_block_root)
|
data = makeAttestationData(state, slot, index, beacon_block_root)
|
||||||
|
@ -197,6 +200,15 @@ proc makeAttestation*(
|
||||||
signature: sig
|
signature: sig
|
||||||
)
|
)
|
||||||
|
|
||||||
|
proc makeAttestation*(
|
||||||
|
state: BeaconState, beacon_block_root: Eth2Digest,
|
||||||
|
validator_index: ValidatorIndex, cache: var StateCache,
|
||||||
|
flags: UpdateFlags = {}): Attestation =
|
||||||
|
let (committee, slot, index) =
|
||||||
|
find_beacon_committee(state, validator_index, cache)
|
||||||
|
makeAttestation(state, beacon_block_root, committee, slot, index,
|
||||||
|
validator_index, cache, flags)
|
||||||
|
|
||||||
proc makeTestDB*(tailState: BeaconState, tailBlock: BeaconBlock): BeaconChainDB =
|
proc makeTestDB*(tailState: BeaconState, tailBlock: BeaconBlock): BeaconChainDB =
|
||||||
result = init(BeaconChainDB, newMemoryDB())
|
result = init(BeaconChainDB, newMemoryDB())
|
||||||
BlockPool.preInit(result, tailState, tailBlock)
|
BlockPool.preInit(result, tailState, tailBlock)
|
||||||
|
|
Loading…
Reference in New Issue