spec v0.11.3 update

This commit is contained in:
Dustin Brody 2020-05-19 16:37:29 +02:00 committed by tersec
parent c014f0b301
commit 6c941b1ff7
20 changed files with 66 additions and 75 deletions

View File

@ -90,13 +90,14 @@ OK: 20/20 Fail: 0/20 Skip: 0/20
OK: 20/20 Fail: 0/20 Skip: 0/20
## Official - Operations - Block header [Preset: mainnet]
```diff
+ [Invalid] invalid_multiple_blocks_single_slot OK
+ [Invalid] invalid_parent_root OK
+ [Invalid] invalid_proposer_index OK
+ [Invalid] invalid_slot_block_header OK
+ [Invalid] proposer_slashed OK
+ [Valid] success_block_header OK
```
OK: 5/5 Fail: 0/5 Skip: 0/5
OK: 6/6 Fail: 0/6 Skip: 0/6
## Official - Operations - Deposits [Preset: mainnet]
```diff
+ [Invalid] bad_merkle_proof OK
@ -138,7 +139,10 @@ OK: 9/9 Fail: 0/9 Skip: 0/9
+ [Invalid] invalid_proposer_index_sig_from_expected_proposer OK
+ [Invalid] invalid_proposer_index_sig_from_proposer_index OK
+ [Invalid] invalid_state_root OK
+ [Invalid] parent_from_same_slot OK
+ [Invalid] prev_slot_block_transition OK
+ [Invalid] proposal_for_genesis_slot OK
+ [Invalid] same_slot_block_transition OK
+ [Invalid] zero_block_sig OK
+ [Valid] attestation OK
+ [Valid] attester_slashing OK
@ -151,11 +155,10 @@ OK: 9/9 Fail: 0/9 Skip: 0/9
+ [Valid] historical_batch OK
+ [Valid] proposer_after_inactive_index OK
+ [Valid] proposer_slashing OK
+ [Valid] same_slot_block_transition OK
+ [Valid] skipped_slots OK
+ [Valid] voluntary_exit OK
```
OK: 21/21 Fail: 0/21 Skip: 0/21
OK: 23/23 Fail: 0/23 Skip: 0/23
## Official - Sanity - Slots [Preset: mainnet]
```diff
+ Slots - double_empty_epoch OK
@ -167,4 +170,4 @@ OK: 21/21 Fail: 0/21 Skip: 0/21
OK: 5/5 Fail: 0/5 Skip: 0/5
---TOTAL---
OK: 117/117 Fail: 0/117 Skip: 0/117
OK: 120/120 Fail: 0/120 Skip: 0/120

View File

@ -90,13 +90,14 @@ OK: 20/20 Fail: 0/20 Skip: 0/20
OK: 20/20 Fail: 0/20 Skip: 0/20
## Official - Operations - Block header [Preset: minimal]
```diff
+ [Invalid] invalid_multiple_blocks_single_slot OK
+ [Invalid] invalid_parent_root OK
+ [Invalid] invalid_proposer_index OK
+ [Invalid] invalid_slot_block_header OK
+ [Invalid] proposer_slashed OK
+ [Valid] success_block_header OK
```
OK: 5/5 Fail: 0/5 Skip: 0/5
OK: 6/6 Fail: 0/6 Skip: 0/6
## Official - Operations - Deposits [Preset: minimal]
```diff
+ [Invalid] bad_merkle_proof OK
@ -138,7 +139,10 @@ OK: 9/9 Fail: 0/9 Skip: 0/9
+ [Invalid] invalid_proposer_index_sig_from_expected_proposer OK
+ [Invalid] invalid_proposer_index_sig_from_proposer_index OK
+ [Invalid] invalid_state_root OK
+ [Invalid] parent_from_same_slot OK
+ [Invalid] prev_slot_block_transition OK
+ [Invalid] proposal_for_genesis_slot OK
+ [Invalid] same_slot_block_transition OK
+ [Invalid] zero_block_sig OK
+ [Valid] attestation OK
+ [Valid] attester_slashing OK
@ -154,11 +158,10 @@ OK: 9/9 Fail: 0/9 Skip: 0/9
+ [Valid] historical_batch OK
+ [Valid] proposer_after_inactive_index OK
+ [Valid] proposer_slashing OK
+ [Valid] same_slot_block_transition OK
+ [Valid] skipped_slots OK
+ [Valid] voluntary_exit OK
```
OK: 24/24 Fail: 0/24 Skip: 0/24
OK: 26/26 Fail: 0/26 Skip: 0/26
## Official - Sanity - Slots [Preset: minimal]
```diff
+ Slots - double_empty_epoch OK
@ -170,4 +173,4 @@ OK: 24/24 Fail: 0/24 Skip: 0/24
OK: 5/5 Fail: 0/5 Skip: 0/5
---TOTAL---
OK: 120/120 Fail: 0/120 Skip: 0/120
OK: 123/123 Fail: 0/123 Skip: 0/123

View File

@ -2,9 +2,8 @@
import
deques, tables,
stew/[endians2, byteutils], chronicles,
stew/endians2,
spec/[datatypes, crypto, digest],
beacon_chain_db, extras,
block_pools/block_pools_types,
block_pool # TODO: refactoring compat shim

View File

@ -65,7 +65,7 @@ else:
loadCustomPreset const_preset
const
SPEC_VERSION* = "0.11.2" ## \
SPEC_VERSION* = "0.11.3" ## \
## Spec version we're aiming to be compatible with, right now
GENESIS_SLOT* = Slot(0)

View File

@ -15,17 +15,12 @@
# The entry point is `process_block` which is at the bottom of this file.
#
# General notes about the code (TODO):
# * It's inefficient - we quadratically copy, allocate and iterate when there
# are faster options
# * Weird styling - the sections taken from the spec use python styling while
# the others use NEP-1 - helps grepping identifiers in spec
# * We mix procedural and functional styles for no good reason, except that the
# spec does so also.
# * There are likely lots of bugs.
# * For indices, we get a mix of uint64, ValidatorIndex and int - this is currently
# swept under the rug with casts
# * The spec uses uint64 for data types, but functions in the spec often assume
# signed bigint semantics - under- and overflows ensue
# * Sane error handling is missing in most cases (yay, we'll get the chance to
# debate exceptions again!)
# When updating the code, add TODO sections to mark where there are clear
@ -46,7 +41,7 @@ declareGauge beacon_previous_live_validators, "Number of active validators that
declareGauge beacon_pending_deposits, "Number of pending deposits (state.eth1_data.deposit_count - state.eth1_deposit_index)" # On block
declareGauge beacon_processed_deposits_total, "Number of total deposits included on chain" # On block
# https://github.com/ethereum/eth2.0-specs/blob/v0.11.1/specs/phase0/beacon-chain.md#block-header
# https://github.com/ethereum/eth2.0-specs/blob/v0.11.3/specs/phase0/beacon-chain.md#block-header
proc process_block_header*(
state: var BeaconState, blck: BeaconBlock, flags: UpdateFlags,
stateCache: var StateCache): bool {.nbench.}=
@ -57,6 +52,11 @@ proc process_block_header*(
state_slot = shortLog(state.slot)
return false
# Verify that the block is newer than latest block header
if not (blck.slot > state.latest_block_header.slot):
debug "Block header: block not newer than latest block header"
return false
# Verify that proposer index is the correct index
let proposer_index = get_beacon_proposer_index(state, stateCache)
if proposer_index.isNone:

View File

@ -143,9 +143,9 @@ proc advance_slot*(state: var HashedBeaconState,
else:
state.root = hash_tree_root(state.data)
# https://github.com/ethereum/eth2.0-specs/blob/v0.11.1/specs/phase0/beacon-chain.md#beacon-chain-state-transition-function
# https://github.com/ethereum/eth2.0-specs/blob/v0.11.3/specs/phase0/beacon-chain.md#beacon-chain-state-transition-function
proc process_slots*(state: var HashedBeaconState, slot: Slot,
updateFlags: UpdateFlags = {}) {.nbench.} =
updateFlags: UpdateFlags = {}): bool {.nbench.} =
# TODO: Eth specs strongly assert that state.data.slot <= slot
# This prevents receiving attestation in any order
# (see tests/test_attestation_pool)
@ -157,18 +157,21 @@ proc process_slots*(state: var HashedBeaconState, slot: Slot,
# we avoid the state root calculation - as such, instead of advancing
# slots "automatically" in `state_transition`, perhaps it would be better
# to keep a pre-condition that state must be at the right slot already?
if state.data.slot > slot:
if not (state.data.slot < slot):
notice(
"Unusual request for a slot in the past",
state_root = shortLog(state.root),
current_slot = state.data.slot,
target_slot = slot
)
return false
# Catch up to the target slot
while state.data.slot < slot:
advance_slot(state, err(Opt[Eth2Digest]), updateFlags)
true
proc noRollback*(state: var HashedBeaconState) =
trace "Skipping rollback of broken state"
@ -206,8 +209,10 @@ proc state_transition*(
# the changes in case of failure (look out for `var BeaconState` and
# bool return values...)
doAssert not rollback.isNil, "use noRollback if it's ok to mess up state"
# These should never fail.
process_slots(state, signedBlock.message.slot, flags)
if not process_slots(state, signedBlock.message.slot, flags):
rollback(state)
return false
# Block updates - these happen when there's a new block being suggested
# by the block proposer. Every actor in the network will update its state

View File

@ -127,7 +127,7 @@ proc add*(state: var HashedBeaconState, attestation: Attestation, slot: Slot) =
var signedBlock = mockBlockForNextSlot(state.data)
signedBlock.message.slot = slot
signedBlock.message.body.attestations.add attestation
process_slots(state, slot)
discard process_slots(state, slot)
signMockBlock(state.data, signedBlock)
doAssert state_transition(

View File

@ -10,7 +10,7 @@ import
# Specs
../../beacon_chain/spec/[datatypes, validator, state_transition_block],
# Internals
../../beacon_chain/[ssz, extras, state_transition],
../../beacon_chain/[ssz, extras],
# Mock helpers
./mock_validator_keys
@ -60,10 +60,3 @@ proc mockBlock(
proc mockBlockForNextSlot*(state: BeaconState, flags: UpdateFlags = {}):
SignedBeaconBlock =
mockBlock(state, state.slot + 1, flags)
proc applyEmptyBlock*(state: var HashedBeaconState) =
## Do a state transition with an empty signed block
## on the current slot
let signedBlock = mockBlock(state.data, state.data.slot, flags = {})
doAssert state_transition(
state, signedBlock, {skipStateRootValidation}, noRollback)

View File

@ -18,8 +18,8 @@ proc nextEpoch*(state: var HashedBeaconState) =
## Transition to the start of the next epoch
let slot =
state.data.slot + SLOTS_PER_EPOCH - (state.data.slot mod SLOTS_PER_EPOCH)
process_slots(state, slot)
discard process_slots(state, slot)
proc nextSlot*(state: var HashedBeaconState) =
## Transition to the next slot
process_slots(state, state.data.slot + 1)
discard process_slots(state, state.data.slot + 1)

View File

@ -40,7 +40,7 @@ type
const
FixturesDir* = currentSourcePath.rsplit(DirSep, 1)[0] / ".." / ".." / "vendor" / "nim-eth2-scenarios"
SszTestsDir* = FixturesDir/"tests-v0.11.2"
SszTestsDir* = FixturesDir/"tests-v0.11.3"
proc parseTest*(path: string, Format: typedesc[Json or SSZ], T: typedesc): T =
try:

View File

@ -42,7 +42,8 @@ proc runTest(identifier: string) =
# In test cases with more than 10 blocks the first 10 aren't 0-prefixed,
# so purely lexicographic sorting wouldn't sort properly.
for i in 0 ..< toSeq(walkPattern(testDir/"blocks_*.ssz")).len:
let numBlocks = toSeq(walkPattern(testDir/"blocks_*.ssz")).len
for i in 0 ..< numBlocks:
let blck = parseTest(testDir/"blocks_" & $i & ".ssz", SSZ, SignedBeaconBlock)
if hasPostState:
@ -52,7 +53,8 @@ proc runTest(identifier: string) =
else:
let success = state_transition(
hashedPreState, blck, flags = {}, noRollback)
doAssert not success, "We didn't expect this invalid block to be processed"
doAssert (i + 1 < numBlocks) or not success,
"We didn't expect these invalid blocks to be processed"
if hasPostState:
let postState = newClone(parseTest(testDir/"post.ssz", SSZ, BeaconState))

View File

@ -37,7 +37,8 @@ proc runTest(identifier: string) =
data: preState[], root: hash_tree_root(preState[]))
let postState = newClone(parseTest(testDir/"post.ssz", SSZ, BeaconState))
process_slots(hashedPreState, hashedPreState.data.slot + num_slots)
discard process_slots(
hashedPreState, hashedPreState.data.slot + num_slots)
check: hashedPreState.root == postState[].hash_tree_root()
let newPreState = newClone(hashedPreState.data)

View File

@ -6,7 +6,7 @@
# at your option. This file may not be copied, modified, or distributed except according to those terms.
# process_attestation (beaconstate.nim)
# https://github.com/ethereum/eth2.0-specs/blob/v0.11.2/specs/phase0/beacon-chain.md#attestations
# https://github.com/ethereum/eth2.0-specs/blob/v0.11.3/specs/phase0/beacon-chain.md#attestations
# ---------------------------------------------------------------
{.used.}
@ -17,7 +17,7 @@ import
# Specs
../../beacon_chain/spec/[beaconstate, datatypes, helpers, validator],
# Mock helpers
../mocking/[mock_genesis, mock_attestations, mock_state, mock_blocks],
../mocking/[mock_genesis, mock_attestations, mock_state],
../testutil
suiteReport "[Unit - Spec - Block processing] Attestations " & preset():
@ -63,27 +63,10 @@ suiteReport "[Unit - Spec - Block processing] Attestations " & preset():
state.data.slot += MIN_ATTESTATION_INCLUSION_DELAY
valid_attestation("Valid attestation from previous epoch"):
nextSlot(state[])
let attestation = mockAttestation(state.data)
state.data.slot = Slot(SLOTS_PER_EPOCH - 1)
nextEpoch(state[])
applyEmptyBlock(state[])
# TODO check if this should be replaced
when false:
when MAX_EPOCHS_PER_CROSSLINK > 4'u64:
timedTest "Valid attestation since max epochs per crosslinks [Skipped for preset: " & const_preset & ']':
discard
else:
valid_attestation("Valid attestation since max epochs per crosslinks"):
for _ in 0 ..< MAX_EPOCHS_PER_CROSSLINK + 2:
nextEpoch(state[])
applyEmptyBlock(state[])
let attestation = mockAttestation(state[])
check: attestation.data.crosslink.end_epoch - attestation.data.crosslink.start_epoch == MAX_EPOCHS_PER_CROSSLINK
for _ in 0 ..< MIN_ATTESTATION_INCLUSION_DELAY:
nextSlot(state[])
# TODO: regression BLS V0.10.1
echo "[Skipping] \"Empty aggregation bit\""

View File

@ -7,7 +7,7 @@
# process_deposit (beaconstate.nim)
# https://github.com/ethereum/eth2.0-specs/blob/v0.11.2/specs/phase0/beacon-chain.md#deposits
# https://github.com/ethereum/eth2.0-specs/blob/v0.11.3/specs/phase0/beacon-chain.md#deposits
# ---------------------------------------------------------------
{.used.}

View File

@ -17,7 +17,7 @@ proc processSlotsUntilEndCurrentEpoch(state: var HashedBeaconState) =
state.data.slot + SLOTS_PER_EPOCH - (state.data.slot mod SLOTS_PER_EPOCH)
# Transition to slot before the epoch state transition
process_slots(state, slot - 1)
discard process_slots(state, slot - 1)
# For the last slot of the epoch,
# only process_slot without process_epoch

View File

@ -26,7 +26,7 @@ suiteReport "Attestation pool processing" & preset():
pool = AttestationPool.init(blockPool)
state = newClone(loadTailState(blockPool))
# Slot 0 is a finalized slot - won't be making attestations for it..
process_slots(state.data, state.data.data.slot + 1)
discard process_slots(state.data, state.data.data.slot + 1)
timedTest "Can add and retrieve simple attestation" & preset():
var cache = get_empty_per_epoch_cache()
@ -39,7 +39,7 @@ suiteReport "Attestation pool processing" & preset():
pool.add(attestation)
process_slots(state.data, MIN_ATTESTATION_INCLUSION_DELAY.Slot + 1)
discard process_slots(state.data, MIN_ATTESTATION_INCLUSION_DELAY.Slot + 1)
let attestations = pool.getAttestationsForBlock(state.data.data)
@ -55,7 +55,7 @@ suiteReport "Attestation pool processing" & preset():
attestation0 = makeAttestation(
state.data.data, state.blck.root, bc0[0], cache)
process_slots(state.data, state.data.data.slot + 1)
discard process_slots(state.data, state.data.data.slot + 1)
let
bc1 = get_beacon_committee(state.data.data,
@ -67,7 +67,7 @@ suiteReport "Attestation pool processing" & preset():
pool.add(attestation1)
pool.add(attestation0)
process_slots(state.data, MIN_ATTESTATION_INCLUSION_DELAY.Slot + 1)
discard process_slots(state.data, MIN_ATTESTATION_INCLUSION_DELAY.Slot + 1)
let attestations = pool.getAttestationsForBlock(state.data.data)
@ -88,7 +88,7 @@ suiteReport "Attestation pool processing" & preset():
pool.add(attestation0)
pool.add(attestation1)
process_slots(state.data, MIN_ATTESTATION_INCLUSION_DELAY.Slot + 1)
discard process_slots(state.data, MIN_ATTESTATION_INCLUSION_DELAY.Slot + 1)
let attestations = pool.getAttestationsForBlock(state.data.data)
@ -112,7 +112,7 @@ suiteReport "Attestation pool processing" & preset():
pool.add(attestation0)
pool.add(attestation1)
process_slots(state.data, MIN_ATTESTATION_INCLUSION_DELAY.Slot + 1)
discard process_slots(state.data, MIN_ATTESTATION_INCLUSION_DELAY.Slot + 1)
let attestations = pool.getAttestationsForBlock(state.data.data)
@ -135,7 +135,7 @@ suiteReport "Attestation pool processing" & preset():
pool.add(attestation1)
pool.add(attestation0)
process_slots(state.data, MIN_ATTESTATION_INCLUSION_DELAY.Slot + 1)
discard process_slots(state.data, MIN_ATTESTATION_INCLUSION_DELAY.Slot + 1)
let attestations = pool.getAttestationsForBlock(state.data.data)

View File

@ -132,7 +132,7 @@ suiteReport "Block pool processing" & preset():
pool.heads[0].blck == b2Add
# Skip one slot to get a gap
process_slots(stateData.data, stateData.data.data.slot + 1)
discard process_slots(stateData.data, stateData.data.data.slot + 1)
let
b4 = addTestBlock(stateData.data.data, b2Root)
@ -345,7 +345,8 @@ when const_preset == "minimal": # These require some minutes in mainnet
pool.updateHead(added)
# Advance past epoch so that the epoch transition is gapped
process_slots(pool.headState.data, Slot(SLOTS_PER_EPOCH * 6 + 2) )
discard process_slots(
pool.headState.data, Slot(SLOTS_PER_EPOCH * 6 + 2) )
var blck = makeTestBlock(
pool.headState.data.data, pool.head.blck.root,

View File

@ -29,7 +29,7 @@ suiteReport "Block processing" & preset():
var state = newClone(genesisState)
timedTest "Passes from genesis state, no block" & preset():
process_slots(state[], state.data.slot + 1)
discard process_slots(state[], state.data.slot + 1)
check:
state.data.slot == genesisState.data.slot + 1
@ -46,7 +46,7 @@ suiteReport "Block processing" & preset():
state.data.slot == genesisState.data.slot + 1
timedTest "Passes through epoch update, no block" & preset():
process_slots(state[], Slot(SLOTS_PER_EPOCH))
discard process_slots(state[], Slot(SLOTS_PER_EPOCH))
check:
state.data.slot == genesisState.data.slot + SLOTS_PER_EPOCH
@ -74,7 +74,7 @@ suiteReport "Block processing" & preset():
cache = get_empty_per_epoch_cache()
# Slot 0 is a finalized slot - won't be making attestations for it..
process_slots(state[], state.data.slot + 1)
discard process_slots(state[], state.data.slot + 1)
let
# Create an attestation for slot 1 signed by the only attester we have!
@ -85,7 +85,8 @@ suiteReport "Block processing" & preset():
# Some time needs to pass before attestations are included - this is
# to let the attestation propagate properly to interested participants
process_slots(state[], GENESIS_SLOT + MIN_ATTESTATION_INCLUSION_DELAY + 1)
discard process_slots(
state[], GENESIS_SLOT + MIN_ATTESTATION_INCLUSION_DELAY + 1)
let
new_block = makeTestBlock(state.data, previous_block_root,
@ -100,7 +101,7 @@ suiteReport "Block processing" & preset():
when const_preset=="minimal":
# Can take several minutes with mainnet settings
process_slots(state[], Slot(191))
discard process_slots(state[], Slot(191))
# Would need to process more epochs for the attestation to be removed from
# the state! (per above bug)

View File

@ -97,7 +97,7 @@ proc addTestBlock*(
# TODO workaround, disable when this works directly
var hashedState = HashedBeaconState(data: state, root: hash_tree_root(state))
process_slots(hashedState, hashedState.data.slot + 1)
discard process_slots(hashedState, hashedState.data.slot + 1)
state = hashedState.data
var cache = get_empty_per_epoch_cache()

@ -1 +1 @@
Subproject commit 0e390c80735c39f3f0375007f158f23dec0f7b0a
Subproject commit 9b040171408fdc56f5b3b1daf306b880ad54327f