2018-12-21 22:37:46 +00:00
|
|
|
import
|
2019-12-03 16:45:12 +00:00
|
|
|
confutils, stats, times, std/monotimes,
|
2019-07-03 07:35:05 +00:00
|
|
|
strformat,
|
2019-06-29 09:17:24 +00:00
|
|
|
options, sequtils, random, tables,
|
2019-12-03 16:45:12 +00:00
|
|
|
../tests/[testutil, testblockutil],
|
2019-01-26 19:32:10 +00:00
|
|
|
../beacon_chain/spec/[beaconstate, crypto, datatypes, digest, helpers, validator],
|
2019-10-25 10:59:56 +00:00
|
|
|
../beacon_chain/[attestation_pool, extras, ssz]
|
2018-12-21 22:37:46 +00:00
|
|
|
|
2019-03-04 13:04:26 +00:00
|
|
|
type Timers = enum
|
|
|
|
tBlock = "Process non-epoch slot with block"
|
2019-03-23 04:55:41 +00:00
|
|
|
tEpoch = "Process epoch slot with block"
|
2019-03-04 13:04:26 +00:00
|
|
|
tHashBlock = "Tree-hash block"
|
2019-11-25 06:31:37 +00:00
|
|
|
tShuffle = "Retrieve committee once using get_beacon_committee"
|
2019-03-04 13:04:26 +00:00
|
|
|
tAttest = "Combine committee attestations"
|
|
|
|
|
2018-12-21 22:37:46 +00:00
|
|
|
proc writeJson*(prefix, slot, v: auto) =
|
|
|
|
var f: File
|
|
|
|
defer: close(f)
|
2019-08-15 16:01:55 +00:00
|
|
|
let fileName = fmt"{prefix:04}-{shortLog(slot):08}.json"
|
2019-07-03 07:35:05 +00:00
|
|
|
Json.saveFile(fileName, v, pretty = true)
|
2018-12-21 22:37:46 +00:00
|
|
|
|
2019-11-15 22:37:39 +00:00
|
|
|
func verifyConsensus(state: BeaconState, attesterRatio: auto) =
|
|
|
|
if attesterRatio < 0.63:
|
|
|
|
doAssert state.current_justified_checkpoint.epoch == 0
|
|
|
|
doAssert state.finalized_checkpoint.epoch == 0
|
|
|
|
|
|
|
|
# Quorum is 2/3 of validators, and at low numbers, quantization effects
|
|
|
|
# can dominate, so allow for play above/below attesterRatio of 2/3.
|
|
|
|
if attesterRatio < 0.72:
|
|
|
|
return
|
|
|
|
|
|
|
|
let current_epoch = get_current_epoch(state)
|
|
|
|
if current_epoch >= 3:
|
|
|
|
doAssert state.current_justified_checkpoint.epoch + 1 >= current_epoch
|
|
|
|
if current_epoch >= 4:
|
|
|
|
doAssert state.finalized_checkpoint.epoch + 2 >= current_epoch
|
|
|
|
|
|
|
|
cli do(slots = SLOTS_PER_EPOCH * 6,
|
2019-12-03 16:45:12 +00:00
|
|
|
validators = SLOTS_PER_EPOCH * 30, # One per shard is minimum
|
2019-02-20 01:33:58 +00:00
|
|
|
json_interval = SLOTS_PER_EPOCH,
|
2019-01-23 18:45:15 +00:00
|
|
|
prefix = 0,
|
2019-11-27 22:48:12 +00:00
|
|
|
attesterRatio {.desc: "ratio of validators that attest in each round"} = 0.73,
|
2019-04-05 14:18:13 +00:00
|
|
|
validate = true):
|
2018-12-21 22:37:46 +00:00
|
|
|
let
|
2018-12-27 23:40:22 +00:00
|
|
|
flags = if validate: {} else: {skipValidation}
|
2019-07-10 12:23:02 +00:00
|
|
|
genesisState = initialize_beacon_state_from_eth1(
|
2019-09-02 10:31:14 +00:00
|
|
|
Eth2Digest(), 0,
|
|
|
|
makeInitialDeposits(validators, flags), flags)
|
2019-02-21 04:42:17 +00:00
|
|
|
genesisBlock = get_initial_beacon_block(genesisState)
|
2018-12-21 22:37:46 +00:00
|
|
|
|
|
|
|
var
|
2019-06-29 09:17:24 +00:00
|
|
|
attestations = initTable[Slot, seq[Attestation]]()
|
2018-12-21 22:37:46 +00:00
|
|
|
state = genesisState
|
2019-05-09 12:27:37 +00:00
|
|
|
latest_block_root = signing_root(genesisBlock)
|
2019-03-04 13:04:26 +00:00
|
|
|
timers: array[Timers, RunningStat]
|
|
|
|
attesters: RunningStat
|
|
|
|
r: Rand
|
|
|
|
blck: BeaconBlock
|
2019-06-24 09:21:56 +00:00
|
|
|
cache = get_empty_per_epoch_cache()
|
2018-12-21 22:37:46 +00:00
|
|
|
|
2019-03-04 13:04:26 +00:00
|
|
|
proc maybeWrite() =
|
2018-12-21 22:37:46 +00:00
|
|
|
if state.slot mod json_interval.uint64 == 0:
|
|
|
|
writeJson(prefix, state.slot, state)
|
|
|
|
write(stdout, ":")
|
|
|
|
else:
|
|
|
|
write(stdout, ".")
|
|
|
|
|
2019-11-27 22:48:12 +00:00
|
|
|
# TODO doAssert against this up-front
|
|
|
|
# indexed attestation: validator index beyond max validators per committee
|
|
|
|
# len(indices) <= MAX_VALIDATORS_PER_COMMITTEE
|
|
|
|
|
2019-03-04 13:04:26 +00:00
|
|
|
for i in 0..<slots:
|
|
|
|
maybeWrite()
|
2019-11-15 22:37:39 +00:00
|
|
|
verifyConsensus(state, attesterRatio)
|
2019-03-04 13:04:26 +00:00
|
|
|
|
2018-12-27 23:40:22 +00:00
|
|
|
let
|
2019-06-29 09:17:24 +00:00
|
|
|
attestations_idx = state.slot
|
|
|
|
body = BeaconBlockBody(
|
|
|
|
attestations: attestations.getOrDefault(attestations_idx))
|
2018-12-27 23:40:22 +00:00
|
|
|
|
2019-06-29 09:17:24 +00:00
|
|
|
attestations.del attestations_idx
|
|
|
|
doAssert len(attestations) <=
|
|
|
|
(SLOTS_PER_EPOCH.int + MIN_ATTESTATION_INCLUSION_DELAY.int)
|
2018-12-27 23:40:22 +00:00
|
|
|
|
2019-03-04 13:04:26 +00:00
|
|
|
let t =
|
2019-03-23 04:52:45 +00:00
|
|
|
if (state.slot > GENESIS_SLOT and
|
|
|
|
(state.slot + 1) mod SLOTS_PER_EPOCH == 0): tEpoch
|
2019-03-04 13:04:26 +00:00
|
|
|
else: tBlock
|
|
|
|
|
|
|
|
withTimer(timers[t]):
|
|
|
|
blck = addBlock(state, latest_block_root, body, flags)
|
|
|
|
latest_block_root = withTimerRet(timers[tHashBlock]):
|
2019-05-09 12:27:37 +00:00
|
|
|
signing_root(blck)
|
2018-12-27 23:40:22 +00:00
|
|
|
|
|
|
|
if attesterRatio > 0.0:
|
|
|
|
# attesterRatio is the fraction of attesters that actually do their
|
2019-03-11 15:33:24 +00:00
|
|
|
# work for every slot - we'll randomize it deterministically to give
|
2018-12-27 23:40:22 +00:00
|
|
|
# some variation
|
2019-06-24 09:21:56 +00:00
|
|
|
let
|
2019-11-27 22:48:12 +00:00
|
|
|
target_slot = state.slot + MIN_ATTESTATION_INCLUSION_DELAY - 1
|
2019-06-24 09:21:56 +00:00
|
|
|
scass = withTimerRet(timers[tShuffle]):
|
|
|
|
mapIt(
|
2019-11-27 22:48:12 +00:00
|
|
|
0'u64 ..< get_committee_count_at_slot(state, target_slot),
|
|
|
|
get_beacon_committee(state, target_slot, it, cache))
|
2018-12-27 23:40:22 +00:00
|
|
|
|
2019-11-27 22:48:12 +00:00
|
|
|
for i, scas in scass:
|
2018-12-27 23:40:22 +00:00
|
|
|
var
|
|
|
|
attestation: Attestation
|
|
|
|
first = true
|
|
|
|
|
2019-06-24 09:21:56 +00:00
|
|
|
attesters.push scas.len()
|
2019-03-04 13:04:26 +00:00
|
|
|
|
|
|
|
withTimer(timers[tAttest]):
|
2019-06-24 09:21:56 +00:00
|
|
|
for v in scas:
|
2019-03-04 13:04:26 +00:00
|
|
|
if (rand(r, high(int)).float * attesterRatio).int <= high(int):
|
|
|
|
if first:
|
2019-11-15 22:37:39 +00:00
|
|
|
attestation =
|
2019-11-27 22:48:12 +00:00
|
|
|
makeAttestation(state, latest_block_root, scas, target_slot,
|
|
|
|
i.uint64, v, cache, flags)
|
2019-03-04 13:04:26 +00:00
|
|
|
first = false
|
|
|
|
else:
|
|
|
|
attestation.combine(
|
2019-11-27 22:48:12 +00:00
|
|
|
makeAttestation(state, latest_block_root, scas, target_slot,
|
|
|
|
i.uint64, v, cache, flags),
|
2019-11-15 22:37:39 +00:00
|
|
|
flags)
|
2018-12-27 23:40:22 +00:00
|
|
|
|
|
|
|
if not first:
|
|
|
|
# add the attestation if any of the validators attested, as given
|
|
|
|
# by the randomness. We have to delay when the attestation is
|
|
|
|
# actually added to the block per the attestation delay rule!
|
2019-06-29 09:17:24 +00:00
|
|
|
let target_slot =
|
2019-11-12 05:35:52 +00:00
|
|
|
attestation.data.slot + MIN_ATTESTATION_INCLUSION_DELAY - 1
|
2019-06-29 09:17:24 +00:00
|
|
|
|
2019-11-27 22:48:12 +00:00
|
|
|
doAssert target_slot > attestations_idx
|
|
|
|
var target_slot_attestations =
|
|
|
|
getOrDefault(attestations, target_slot)
|
|
|
|
target_slot_attestations.add attestation
|
|
|
|
attestations[target_slot] = target_slot_attestations
|
2018-12-21 22:37:46 +00:00
|
|
|
|
|
|
|
flushFile(stdout)
|
|
|
|
|
2019-03-04 13:04:26 +00:00
|
|
|
if (state.slot) mod SLOTS_PER_EPOCH == 0:
|
2019-08-15 16:01:55 +00:00
|
|
|
echo &" slot: {shortLog(state.slot)} ",
|
initial 0.9.0 spec sync (#509)
* rename compute_epoch_of_slot(...) to compute_epoch_at_slot(...)
* remove some unnecessary imports; remove some crosslink-related code and tests; complete renaming of compute_epoch_of_slot(...) to compute_epoch_at_slot(...)
* rm more transfer-related code and tests; rm more unnecessary strutils imports
* rm remaining unused imports
* remove useless get_empty_per_epoch_cache(...)/compute_start_slot_of_epoch(...) calls
* rename compute_start_slot_of_epoch(...) to compute_start_slot_at_epoch(...)
* rename ACTIVATION_EXIT_DELAY to MAX_SEED_LOOKAHEAD
* update domain types to 0.9.0
* mark AttesterSlashing, IndexedAttestation, AttestationDataAndCustodyBit, DepositData, BeaconBlockHeader, Fork, integer_squareroot(...), and process_voluntary_exit(...) as 0.9.0
* mark increase_balance(...), decrease_balance(...), get_block_root(...), CheckPoint, Deposit, PendingAttestation, HistoricalBatch, is_active_validator(...), and is_slashable_attestation_data(...) as 0.9.0
* mark compute_activation_exit_epoch(...), bls_verify(...), Validator, get_active_validator_indices(...), get_current_epoch(...), get_total_active_balance(...), and get_previous_epoch(...) as 0.9.0
* mark get_block_root_at_slot(...), ProposerSlashing, get_domain(...), VoluntaryExit, mainnet preset Gwei values, minimal preset max operations, process_block_header(...), and is_slashable_validator(...) as 0.9.0
* mark makeWithdrawalCredentials(...), get_validator_churn_limit(...), get_total_balance(...), is_valid_indexed_attestation(...), bls_aggregate_pubkeys(...), initial genesis value/constants, Attestation, get_randao_mix(...), mainnet preset max operations per block constants, minimal preset Gwei values and time parameters, process_eth1_data(...), get_shuffled_seq(...), compute_committee(...), and process_slots(...) as 0.9.0; partially update get_indexed_attestation(...) to 0.9.0 by removing crosslink refs and associated tests
* mark initiate_validator_exit(...), process_registry_updates(...), BeaconBlock, Eth1Data, compute_domain(...), process_randao(...), process_attester_slashing(...), get_base_reward(...), and process_slot(...) as 0.9.0
2019-10-30 19:41:19 +00:00
|
|
|
&"epoch: {shortLog(state.slot.compute_epoch_at_slot)}"
|
2019-03-04 13:04:26 +00:00
|
|
|
|
|
|
|
maybeWrite() # catch that last state as well..
|
|
|
|
|
2018-12-21 22:37:46 +00:00
|
|
|
echo "done!"
|
|
|
|
|
2019-03-04 13:04:26 +00:00
|
|
|
echo "Validators: ", validators, ", epoch length: ", SLOTS_PER_EPOCH
|
|
|
|
echo "Validators per attestation (mean): ", attesters.mean
|
|
|
|
|
|
|
|
proc fmtTime(t: float): string = &"{t * 1000 :>12.3f}, "
|
|
|
|
|
|
|
|
echo "All time are ms"
|
|
|
|
echo &"{\"Average\" :>12}, {\"StdDev\" :>12}, {\"Min\" :>12}, " &
|
|
|
|
&"{\"Max\" :>12}, {\"Samples\" :>12}, {\"Test\" :>12}"
|
2019-03-07 13:59:28 +00:00
|
|
|
|
|
|
|
if not validate:
|
|
|
|
echo "Validation is turned off meaning that no BLS operations are performed"
|
|
|
|
|
2019-03-04 13:04:26 +00:00
|
|
|
for t in Timers:
|
|
|
|
echo fmtTime(timers[t].mean), fmtTime(timers[t].standardDeviationS),
|
|
|
|
fmtTime(timers[t].min), fmtTime(timers[t].max), &"{timers[t].n :>12}, ",
|
|
|
|
$t
|