implement distinct Epoch type and continue 0.4.0 spec update (#173)
* implement distinct Epoch type * update two more spec 0.4.0 markers, leaving just deposit processing
This commit is contained in:
parent
50a0948bc0
commit
1479bae22f
|
@ -218,7 +218,7 @@ func get_genesis_beacon_state*(
|
|||
|
||||
for i in 0 ..< SHARD_COUNT:
|
||||
state.latest_crosslinks[i] = Crosslink(
|
||||
epoch: GENESIS_EPOCH, crosslink_data_root: ZERO_HASH)
|
||||
epoch: GENESIS_EPOCH.uint64, crosslink_data_root: ZERO_HASH)
|
||||
|
||||
# Process genesis deposits
|
||||
for deposit in genesis_validator_deposits:
|
||||
|
@ -401,7 +401,8 @@ proc checkAttestation*(
|
|||
return
|
||||
|
||||
let expected_justified_block_root =
|
||||
get_block_root(state, get_epoch_start_slot(attestation.data.justified_epoch))
|
||||
get_block_root(
|
||||
state, get_epoch_start_slot(attestation.data.justified_epoch.Epoch))
|
||||
if not (attestation.data.justified_block_root == expected_justified_block_root):
|
||||
warn("Unexpected justified block root",
|
||||
attestation_justified_block_root = attestation.data.justified_block_root,
|
||||
|
@ -412,7 +413,7 @@ proc checkAttestation*(
|
|||
attestation.data.latest_crosslink,
|
||||
Crosslink(
|
||||
crosslink_data_root: attestation.data.crosslink_data_root,
|
||||
epoch: slot_to_epoch(attestation_data_slot))]):
|
||||
epoch: slot_to_epoch(attestation_data_slot).uint64)]):
|
||||
warn("Unexpected crosslink shard",
|
||||
state_latest_crosslinks_attestation_data_shard =
|
||||
state.latest_crosslinks[attestation.data.shard],
|
||||
|
@ -521,6 +522,6 @@ proc makeAttestationData*(
|
|||
epoch_boundary_root: epoch_boundary_root,
|
||||
crosslink_data_root: Eth2Digest(), # Stub in phase0
|
||||
latest_crosslink: state.latest_crosslinks[shard],
|
||||
justified_epoch: state.justified_epoch,
|
||||
justified_epoch: state.justified_epoch.uint64,
|
||||
justified_block_root: justified_block_root,
|
||||
)
|
||||
|
|
|
@ -42,7 +42,7 @@ import
|
|||
|
||||
type
|
||||
Slot* = distinct uint64
|
||||
Epoch* = uint64
|
||||
Epoch* = distinct uint64
|
||||
|
||||
const
|
||||
SPEC_VERSION* = "0.4.0" ## \
|
||||
|
@ -112,7 +112,7 @@ const
|
|||
GENESIS_EPOCH* = (GENESIS_SLOT.uint64 div SLOTS_PER_EPOCH).Epoch ##\
|
||||
## slot_to_epoch(GENESIS_SLOT)
|
||||
GENESIS_START_SHARD* = 0'u64
|
||||
FAR_FUTURE_EPOCH* = not 0'u64 # 2^64 - 1 in spec
|
||||
FAR_FUTURE_EPOCH* = (not 0'u64).Epoch # 2^64 - 1 in spec
|
||||
ZERO_HASH* = Eth2Digest()
|
||||
EMPTY_SIGNATURE* = ValidatorSig()
|
||||
BLS_WITHDRAWAL_PREFIX_BYTE* = 0'u8
|
||||
|
@ -246,7 +246,7 @@ type
|
|||
latest_crosslink*: Crosslink ##\
|
||||
## Last crosslink
|
||||
|
||||
justified_epoch*: Epoch ##\
|
||||
justified_epoch*: uint64 ##\
|
||||
## Last justified epoch in the beacon state
|
||||
|
||||
justified_block_root*: Eth2Digest ##\
|
||||
|
@ -284,7 +284,7 @@ type
|
|||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#voluntaryexit
|
||||
VoluntaryExit* = object
|
||||
# Minimum epoch for processing exit
|
||||
epoch*: Epoch
|
||||
epoch*: uint64
|
||||
# Index of the exiting validator
|
||||
validator_index*: uint64
|
||||
# Validator signature
|
||||
|
@ -451,7 +451,7 @@ type
|
|||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#crosslink
|
||||
Crosslink* = object
|
||||
epoch*: Epoch ##\
|
||||
epoch*: uint64 ##\
|
||||
## Epoch number
|
||||
|
||||
crosslink_data_root*: Eth2Digest ##\
|
||||
|
@ -527,15 +527,17 @@ template ethTimeUnit(typ: type) =
|
|||
proc `-`*(x: typ, y: uint64): typ {.borrow.}
|
||||
proc `-`*(x: uint64, y: typ): typ {.borrow.}
|
||||
|
||||
proc `+=`*(x: var typ, y: uint64) {.borrow.}
|
||||
proc `-=`*(x: var typ, y: uint64) {.borrow.}
|
||||
|
||||
# Not closed over type in question (Slot or Epoch)
|
||||
proc `mod`*(x: typ, y: uint64): uint64 {.borrow.}
|
||||
proc `div`*(x: typ, y: uint64): uint64 {.borrow.}
|
||||
proc `div`*(x: uint64, y: typ): uint64 {.borrow.}
|
||||
proc `-`*(x: typ, y: typ): uint64 {.borrow.}
|
||||
|
||||
proc `*`*(x: typ, y: uint64): uint64 {.borrow.}
|
||||
|
||||
proc `+=`*(x: var typ, y: uint64) {.borrow.}
|
||||
proc `-=`*(x: var typ, y: uint64) {.borrow.}
|
||||
|
||||
# Comparison operators
|
||||
proc `<`*(x: typ, y: typ): bool {.borrow.}
|
||||
proc `<`*(x: typ, y: uint64): bool {.borrow.}
|
||||
|
@ -543,21 +545,23 @@ template ethTimeUnit(typ: type) =
|
|||
proc `<=`*(x: typ, y: typ): bool {.borrow.}
|
||||
proc `<=`*(x: typ, y: uint64): bool {.borrow.}
|
||||
proc `<=`*(x: uint64, y: typ): bool {.borrow.}
|
||||
|
||||
proc `==`*(x: typ, y: typ): bool {.borrow.}
|
||||
proc `==`*(x: typ, y: uint64): bool {.borrow.}
|
||||
proc `==`*(x: uint64, y: typ): bool {.borrow.}
|
||||
|
||||
# Nim integration
|
||||
proc `$`*(x: typ): string {.borrow.}
|
||||
proc hash*(x: typ): Hash {.borrow.}
|
||||
|
||||
ethTimeUnit(Slot)
|
||||
#ethTimeUnit(Epoch)
|
||||
ethTimeUnit(Epoch)
|
||||
|
||||
func humaneSlotNum*(s: auto): uint64 =
|
||||
s.Slot - GENESIS_SLOT
|
||||
|
||||
func humaneEpochNum*(e: Epoch): Epoch =
|
||||
e - GENESIS_EPOCH
|
||||
func humaneEpochNum*(e: auto): uint64 =
|
||||
e.Epoch - GENESIS_EPOCH
|
||||
|
||||
import nimcrypto, json_serialization
|
||||
export json_serialization
|
||||
|
|
|
@ -218,10 +218,11 @@ func bytes_to_int*(data: seq[byte]): uint64 =
|
|||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#int_to_bytes1-int_to_bytes2-
|
||||
# Have 1, 4, and 32-byte versions. 2+ more and maybe worth metaprogramming.
|
||||
func int_to_bytes32*(x: uint64) : array[32, byte] =
|
||||
# Little-endian data representation
|
||||
func int_to_bytes32*(x: uint64|Epoch) : array[32, byte] =
|
||||
## Little-endian data representation
|
||||
## TODO remove uint64 when those callers fade away
|
||||
for i in 0 ..< 8:
|
||||
result[24 + i] = byte((x shr i*8) and 0xff)
|
||||
result[24 + i] = byte((x.uint64 shr i*8) and 0xff)
|
||||
|
||||
func int_to_bytes1*(x: int): array[1, byte] =
|
||||
assert x >= 0
|
||||
|
|
|
@ -71,7 +71,7 @@ func get_shuffled_seq*(seed: Eth2Digest,
|
|||
|
||||
result = shuffled_active_validator_indices
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#get_shuffling
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.4.0/specs/core/0_beacon-chain.md#get_shuffling
|
||||
func get_shuffling*(seed: Eth2Digest,
|
||||
validators: openArray[Validator],
|
||||
epoch: Epoch,
|
||||
|
@ -80,6 +80,8 @@ func get_shuffling*(seed: Eth2Digest,
|
|||
## This function is factored to facilitate testing with
|
||||
## https://github.com/ethereum/eth2.0-test-generators/tree/master/permutated_index
|
||||
## test vectors, which the split of get_shuffling obfuscates.
|
||||
## TODO fix bad list size but keep consistent with cached values,
|
||||
## once epoch processing reordering comes around
|
||||
let list_size = validators.len.uint64
|
||||
|
||||
let
|
||||
|
|
|
@ -153,11 +153,8 @@ proc endRecord*(w: var SszWriter, memo: RecordWritingMemo) =
|
|||
let finalSize = uint32(w.stream.pos - memo.initialStreamPos - 4)
|
||||
memo.sizePrefixCursor.endWrite(finalSize.toBytesSSZ)
|
||||
|
||||
func toSSZType(x: auto): auto =
|
||||
when x is Slot:
|
||||
x.uint64
|
||||
else:
|
||||
x
|
||||
func toSSZType(x: Slot|Epoch): auto = x.uint64
|
||||
func toSSZType(x: auto): auto = x
|
||||
|
||||
proc writeValue*(w: var SszWriter, obj: auto) =
|
||||
# We are not using overloads here, because this leads to
|
||||
|
@ -241,8 +238,11 @@ proc readValue*(r: var SszReader, result: var auto) =
|
|||
|
||||
else:
|
||||
result.deserializeFields(fieldName, field):
|
||||
# TODO This hardcoding's ugly; generalize & abstract.
|
||||
when field is Slot:
|
||||
field = r.readValue(uint64).Slot
|
||||
elif field is Epoch:
|
||||
field = r.readValue(uint64).Epoch
|
||||
else:
|
||||
field = r.readValue(field.type)
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ func verifyBlockSignature(state: BeaconState, blck: BeaconBlock): bool =
|
|||
proposal.signature,
|
||||
get_domain(state.fork, get_current_epoch(state), DOMAIN_PROPOSAL))
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#randao
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#randao
|
||||
proc processRandao(
|
||||
state: var BeaconState, blck: BeaconBlock, flags: UpdateFlags): bool =
|
||||
let
|
||||
|
@ -69,7 +69,7 @@ proc processRandao(
|
|||
if skipValidation notin flags:
|
||||
if not bls_verify(
|
||||
proposer.pubkey,
|
||||
int_to_bytes32(get_current_epoch(state)),
|
||||
hash_tree_root(get_current_epoch(state).uint64),
|
||||
blck.randao_reveal,
|
||||
get_domain(state.fork, get_current_epoch(state), DOMAIN_RANDAO)):
|
||||
|
||||
|
@ -280,7 +280,6 @@ proc processAttestations(
|
|||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#deposits-1
|
||||
func processDeposits(state: var BeaconState, blck: BeaconBlock): bool =
|
||||
# TODO! Spec writing in progress as of v0.3.0
|
||||
true
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#voluntary-exits-1
|
||||
|
@ -305,7 +304,7 @@ proc processExits(
|
|||
if skipValidation notin flags:
|
||||
if not bls_verify(
|
||||
validator.pubkey, signed_root(exit, "signature"), exit.signature,
|
||||
get_domain(state.fork, exit.epoch, DOMAIN_EXIT)):
|
||||
get_domain(state.fork, exit.epoch.Epoch, DOMAIN_EXIT)):
|
||||
notice "Exit: invalid signature"
|
||||
return false
|
||||
|
||||
|
@ -718,7 +717,7 @@ func processEpoch(state: var BeaconState) =
|
|||
if 3'u64 * total_attesting_balance(crosslink_committee) >=
|
||||
2'u64 * get_total_balance(state, crosslink_committee.committee):
|
||||
state.latest_crosslinks[crosslink_committee.shard] = Crosslink(
|
||||
epoch: slot_to_epoch(slot),
|
||||
epoch: slot_to_epoch(slot).uint64,
|
||||
crosslink_data_root: winning_root(crosslink_committee))
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#rewards-and-penalties
|
||||
|
|
|
@ -74,7 +74,7 @@ p2pProtocol BeaconSync(version = 1,
|
|||
|
||||
var
|
||||
latestFinalizedRoot: Eth2Digest # TODO
|
||||
latestFinalizedEpoch: uint64 = node.state.data.finalized_epoch
|
||||
latestFinalizedEpoch: uint64 = node.state.data.finalized_epoch.uint64
|
||||
bestRoot: Eth2Digest # TODO
|
||||
bestSlot: uint64 = node.state.data.slot.uint64
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ func genRandaoReveal*(k: ValidatorPrivKey, state: BeaconState, slot: Slot):
|
|||
|
||||
# Off-by-one? I often get slot == state.slot but the check was "assert slot > state.slot" (Mamy)
|
||||
assert slot >= state.slot, "input slot: " & $humaneSlotNum(slot) & " - beacon state slot: " & $humaneSlotNum(state.slot)
|
||||
bls_sign(k, int_to_bytes32(slot_to_epoch(slot)),
|
||||
bls_sign(k, hash_tree_root(slot_to_epoch(slot).uint64),
|
||||
get_domain(state.fork, slot_to_epoch(slot), DOMAIN_RANDAO))
|
||||
|
||||
func genRandaoReveal*(v: AttachedValidator, state: BeaconState, slot: Slot):
|
||||
|
|
|
@ -37,6 +37,7 @@ template withTimerRet(stats: var RunningStat, body: untyped): untyped =
|
|||
tmp
|
||||
|
||||
proc `%`*(x: Slot): JsonNode {.borrow.}
|
||||
proc `%`*(x: Epoch): JsonNode {.borrow.}
|
||||
|
||||
proc writeJson*(prefix, slot, v: auto) =
|
||||
var f: File
|
||||
|
|
|
@ -33,7 +33,7 @@ suite "Validators":
|
|||
Validator(
|
||||
exit_epoch: FAR_FUTURE_EPOCH
|
||||
), num_validators)
|
||||
s = get_shuffling(Eth2Digest(), validators, 0, ShufflingCache())
|
||||
s = get_shuffling(Eth2Digest(), validators, GENESIS_EPOCH, ShufflingCache())
|
||||
committees = get_epoch_committee_count(len(validators)).int
|
||||
check:
|
||||
# def b(s): return "Eth2Digest(data: [0x" + "'u8, 0x".join((s[i:i+2] for i in range(0, 64, 2))) + "'u8])"
|
||||
|
|
Loading…
Reference in New Issue