more 0.4.0 spec updates: renamings, continue Proposal updates, and note several more functions which were verified not to have changed in 0.4.0 (#163)

This commit is contained in:
Dustin Brody 2019-03-11 15:33:24 +00:00 committed by Jacek Sieka
parent 89aa3ec53f
commit 13de015038
9 changed files with 57 additions and 69 deletions

View File

@ -324,8 +324,9 @@ proc proposeBlock(node: BeaconNode,
parent_root: node.state.blck.root,
randao_reveal: validator.genRandaoReveal(state, slot),
eth1_data: node.mainchainMonitor.getBeaconBlockRef(),
body: blockBody,
signature: ValidatorSig(), # we need the rest of the block first!
body: blockBody)
)
let ok =
updateState(state, node.state.blck.root, newBlock, {skipValidation})
@ -333,12 +334,13 @@ proc proposeBlock(node: BeaconNode,
newBlock.state_root = Eth2Digest(data: hash_tree_root(state))
var signedData = ProposalSignedData(
let proposal = Proposal(
slot: slot,
shard: BEACON_CHAIN_SHARD_NUMBER,
blockRoot: hash_tree_root_final(newBlock))
newBlock.signature = await validator.signBlockProposal(state.fork, signedData)
block_root: Eth2Digest(data: signed_root(newBlock, "signature")),
signature: ValidatorSig(),
)
newBlock.signature = await validator.signBlockProposal(state.fork, proposal)
# TODO what are we waiting for here? broadcast should never block, and never
# fail...

View File

@ -61,25 +61,25 @@ func process_deposit(state: var BeaconState, deposit: Deposit) =
state.validator_balances[index] += amount
# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#get_entry_exit_effect_epoch
func get_entry_exit_effect_epoch*(epoch: Epoch): Epoch =
# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#get_delayed_activation_exit_epoch
func get_delayed_activation_exit_epoch*(epoch: Epoch): Epoch =
## An entry or exit triggered in the ``epoch`` given by the input takes effect at
## the epoch given by the output.
epoch + 1 + ACTIVATION_EXIT_DELAY
# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#activate_validator
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#activate_validator
func activate_validator(state: var BeaconState,
index: ValidatorIndex,
genesis: bool) =
is_genesis: bool) =
## Activate the validator with the given ``index``.
## Note that this function mutates ``state``.
let validator = addr state.validator_registry[index]
validator.activation_epoch =
if genesis:
if is_genesis:
GENESIS_EPOCH
else:
get_entry_exit_effect_epoch(get_current_epoch(state))
get_delayed_activation_exit_epoch(get_current_epoch(state))
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#initiate_validator_exit
func initiate_validator_exit*(state: var BeaconState,
@ -89,7 +89,7 @@ func initiate_validator_exit*(state: var BeaconState,
var validator = addr state.validator_registry[index]
validator.initiated_exit = true
# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#exit_validator
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#exit_validator
func exit_validator*(state: var BeaconState,
index: ValidatorIndex) =
## Exit the validator with the given ``index``.
@ -98,10 +98,10 @@ func exit_validator*(state: var BeaconState,
let validator = addr state.validator_registry[index]
# The following updates only occur if not previous exited
if validator.exit_epoch <= get_entry_exit_effect_epoch(get_current_epoch(state)):
if validator.exit_epoch <= get_delayed_activation_exit_epoch(get_current_epoch(state)):
return
validator.exit_epoch = get_entry_exit_effect_epoch(get_current_epoch(state))
validator.exit_epoch = get_delayed_activation_exit_epoch(get_current_epoch(state))
func reduce_balance*(balance: var uint64, amount: uint64) =
# Not in spec, but useful to avoid underflow.
@ -484,14 +484,12 @@ proc checkAttestation*(
true
# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#prepare_validator_for_withdrawal
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#prepare_validator_for_withdrawal
func prepare_validator_for_withdrawal*(state: var BeaconState, index: ValidatorIndex) =
## Set the validator with the given ``index`` as withdrawable
## ``MIN_VALIDATOR_WITHDRAWABILITY_DELAY`` after the current epoch.
## Note that this function mutates ``state``.
var validator = addr state.validator_registry[index]
# Bug in 0.3.0 spec; constant got renamed. Use 0.3.0 name.
validator.withdrawable_epoch = get_current_epoch(state) +
MIN_VALIDATOR_WITHDRAWABILITY_DELAY

View File

@ -313,7 +313,7 @@ type
signature*: ValidatorSig ##\
## Sender signature
# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#beaconblock
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#beaconblock
BeaconBlock* = object
## For each slot, a proposer is chosen from the validator pool to propose
## a new block. Once the block as been proposed, it is transmitted to
@ -333,11 +333,11 @@ type
eth1_data*: Eth1Data
body*: BeaconBlockBody
signature*: ValidatorSig ##\
## Proposer signature
body*: BeaconBlockBody
BeaconBlockHeader* = object
## Same as BeaconBlock, except `body` is the `hash_tree_root` of the
## associated BeaconBlockBody.
@ -350,7 +350,7 @@ type
signature*: ValidatorSig
body*: Eth2Digest
# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#beaconblockbody
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#beaconblockbody
BeaconBlockBody* = object
proposer_slashings*: seq[ProposerSlashing]
attester_slashings*: seq[AttesterSlashing]
@ -373,13 +373,6 @@ type
signature*: ValidatorSig ##\
## Signature
# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#proposalsigneddata
ProposalSignedData* = object
slot*: uint64
shard*: uint64 ##\
## Shard number (or `BEACON_CHAIN_SHARD_NUMBER` for beacon chain)
block_root*: Eth2Digest
# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#beaconstate
BeaconState* = object
slot*: uint64

View File

@ -75,13 +75,13 @@ func get_fork_version*(fork: Fork, epoch: Epoch): uint64 =
else:
fork.current_version
# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#get_domain
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#get_domain
func get_domain*(
fork: Fork, epoch: Epoch, domain_type: SignatureDomain): uint64 =
# Get the domain number that represents the fork meta and signature domain.
(get_fork_version(fork, epoch) shl 32) + domain_type.uint32
# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#is_power_of_two
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#is_power_of_two
func is_power_of_2*(v: uint64): bool = (v and (v-1)) == 0
# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#merkle_root
@ -119,11 +119,11 @@ func merkle_root*(values: openArray[Eth2Digest]): Eth2Digest =
o[1]
# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#slot_to_epoch
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#slot_to_epoch
func slot_to_epoch*(slot: Slot): Epoch =
slot div SLOTS_PER_EPOCH
# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#get_epoch_start_slot
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#get_epoch_start_slot
func get_epoch_start_slot*(epoch: Epoch): Slot =
# Return the starting slot of the given ``epoch``.
epoch * SLOTS_PER_EPOCH
@ -162,13 +162,13 @@ func get_active_validator_indices*(validators: openArray[Validator], epoch: Epoc
if is_active_validator(val, epoch):
result.add idx.ValidatorIndex
# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#get_epoch_committee_count
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#get_epoch_committee_count
func get_epoch_committee_count*(active_validator_count: int): uint64 =
clamp(
active_validator_count div SLOTS_PER_EPOCH div TARGET_COMMITTEE_SIZE,
1, SHARD_COUNT div SLOTS_PER_EPOCH).uint64 * SLOTS_PER_EPOCH
# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#get_current_epoch_committee_count
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#get_current_epoch_committee_count
func get_current_epoch_committee_count*(state: BeaconState): uint64 =
# Return the number of committees in the current epoch of the given ``state``.
let current_active_validators = get_active_validator_indices(
@ -177,13 +177,13 @@ func get_current_epoch_committee_count*(state: BeaconState): uint64 =
)
get_epoch_committee_count(len(current_active_validators))
# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#get_current_epoch
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#get_current_epoch
func get_current_epoch*(state: BeaconState): Epoch =
# Return the current epoch of the given ``state``.
doAssert state.slot >= GENESIS_SLOT, $state.slot
slot_to_epoch(state.slot)
# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#get_randao_mix
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#get_randao_mix
func get_randao_mix*(state: BeaconState,
epoch: Epoch): Eth2Digest =
## Returns the randao mix at a recent ``epoch``.
@ -237,7 +237,7 @@ func int_to_bytes4*(x: uint64): array[4, byte] =
result[2] = ((x shr 16) and 0xff).byte
result[3] = ((x shr 24) and 0xff).byte
# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#generate_seed
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#generate_seed
func generate_seed*(state: BeaconState, epoch: Epoch): Eth2Digest =
# Generate a seed for the given ``epoch``.

View File

@ -110,7 +110,7 @@ func get_previous_epoch_committee_count(state: BeaconState): uint64 =
)
get_epoch_committee_count(len(previous_active_validators))
# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#get_next_epoch_committee_count
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#get_next_epoch_committee_count
func get_next_epoch_committee_count(state: BeaconState): uint64 =
## Return the number of committees in the next epoch of the given ``state``.
let next_active_validators = get_active_validator_indices(

View File

@ -39,27 +39,24 @@ func flatten[T](v: openArray[seq[T]]): seq[T] =
# TODO not in nim - doh.
for x in v: result.add x
# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#proposer-signature
func verifyProposerSignature(state: BeaconState, blck: BeaconBlock): bool =
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#block-signature
func verifyBlockSignature(state: BeaconState, blck: BeaconBlock): bool =
## When creating a block, the proposer will sign a version of the block that
## doesn't contain the data (chicken and egg), then add the signature to that
## block. Here, we check that the signature is correct by repeating the same
## process.
var blck_without_signature = blck
blck_without_signature.signature = ValidatorSig()
let
signed_data = ProposalSignedData(
slot: state.slot,
proposer =
state.validator_registry[get_beacon_proposer_index(state, state.slot)]
proposal = Proposal(
slot: blck.slot,
shard: BEACON_CHAIN_SHARD_NUMBER,
block_root: hash_tree_root_final(blck_without_signature)
)
proposal_root = hash_tree_root_final(signed_data)
proposer_index = get_beacon_proposer_index(state, state.slot)
block_root: Eth2Digest(data: signed_root(blck, "signature")),
signature: blck.signature)
bls_verify(
state.validator_registry[proposer_index].pubkey,
proposal_root.data, blck.signature,
proposer.pubkey,
signed_root(proposal, "signature"),
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
@ -296,7 +293,7 @@ proc processExits(
for exit in blck.body.voluntary_exits:
let validator = state.validator_registry[exit.validator_index.int]
if not (validator.exit_epoch > get_entry_exit_effect_epoch(get_current_epoch(state))):
if not (validator.exit_epoch > get_delayed_activation_exit_epoch(get_current_epoch(state))):
notice "Exit: exit/entry too close"
return false
@ -350,7 +347,10 @@ proc processTransfers(state: var BeaconState, blck: BeaconBlock,
return false
if not (get_current_epoch(state) >=
state.validator_registry[transfer.from_field.int].withdrawable_epoch):
state.validator_registry[
transfer.from_field.int].withdrawable_epoch or
state.validator_registry[transfer.from_field.int].activation_epoch ==
FAR_FUTURE_EPOCH):
notice "Transfer: epoch mismatch"
return false
@ -362,11 +362,7 @@ proc processTransfers(state: var BeaconState, blck: BeaconBlock,
return false
if skipValidation notin flags:
let transfer_message = hash_tree_root(
Transfer(
from_field: transfer.from_field, to: transfer.to,
amount: transfer.amount, fee: transfer.fee, slot: transfer.slot,
signature: EMPTY_SIGNATURE))
let transfer_message = signed_root(transfer, "signature")
if not bls_verify(
pubkey=transfer.pubkey, transfer_message, transfer.signature,
get_domain(state.fork, slot_to_epoch(transfer.slot), DOMAIN_TRANSFER)):
@ -430,8 +426,8 @@ proc processBlock(
# of BeaconBlock - we would then have an intermediate `ProposedBlock`
# type that omits some fields - this way, the compiler would guarantee
# that we don't try to access fields that don't have a value yet
if not verifyProposerSignature(state, blck):
notice "Proposer signature not valid", slot = humaneSlotNum(state.slot)
if not verifyBlockSignature(state, blck):
notice "Block signature not valid", slot = humaneSlotNum(state.slot)
return false
if not processRandao(state, blck, flags):

View File

@ -41,13 +41,12 @@ proc getValidator*(pool: ValidatorPool,
pool.validators.getOrDefault(validatorKey)
proc signBlockProposal*(v: AttachedValidator, fork: Fork,
proposal: ProposalSignedData): Future[ValidatorSig] {.async.} =
proposal: Proposal): Future[ValidatorSig] {.async.} =
if v.kind == inProcess:
await sleepAsync(1)
let proposalRoot = hash_tree_root_final(proposal)
# TODO: Should we use proposalRoot as data, or digest in regards to signature?
result = bls_sign(v.privKey, proposalRoot.data,
result = bls_sign(v.privKey, signed_root(proposal, "signature"),
get_domain(fork, slot_to_epoch(proposal.slot), DOMAIN_PROPOSAL))
else:
# TODO:

View File

@ -90,7 +90,7 @@ cli do(slots = 1945,
if attesterRatio > 0.0:
# attesterRatio is the fraction of attesters that actually do their
# work for every slot - we'll randimize it deterministically to give
# work for every slot - we'll randomize it deterministically to give
# some variation
let scass = withTimerRet(timers[tShuffle]):
get_crosslink_committees_at_slot(state, state.slot)

View File

@ -119,19 +119,19 @@ proc addBlock*(
# Once we've collected all the state data, we sign the block data along with
# some book-keeping values
signed_data = ProposalSignedData(
signed_data = Proposal(
slot: new_block.slot,
shard: BEACON_CHAIN_SHARD_NUMBER,
block_root: Eth2Digest(data: hash_tree_root(new_block))
block_root: Eth2Digest(data: signed_root(new_block, "signature")),
signature: ValidatorSig(),
)
proposal_hash = hash_tree_root(signed_data)
proposal_hash = signed_root(signed_data, "signature")
assert proposerPrivkey.pubKey() == proposer.pubkey,
"signature key should be derived from private key! - wrong privkey?"
if skipValidation notin flags:
# We have a signature - put it in the block and we should be done!
# TODO domain present do something!
new_block.signature =
bls_sign(proposerPrivkey, proposal_hash,
get_domain(state.fork, slot_to_epoch(state.slot), DOMAIN_PROPOSAL))