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:
Dustin Brody 2019-03-13 01:46:44 +00:00 committed by Jacek Sieka
parent 50a0948bc0
commit 1479bae22f
10 changed files with 40 additions and 32 deletions

View File

@ -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,
)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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):

View File

@ -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

View 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])"