simplify validator api (#573)
* avoid passing whole state to validator api (easier when it goes out-of-process) * clean up some cruft
This commit is contained in:
parent
2fdfba1f34
commit
7c6d87051a
|
@ -287,7 +287,7 @@ proc updateHead(node: BeaconNode, slot: Slot): BlockRef =
|
||||||
newHead
|
newHead
|
||||||
|
|
||||||
proc sendAttestation(node: BeaconNode,
|
proc sendAttestation(node: BeaconNode,
|
||||||
state: BeaconState,
|
fork: Fork,
|
||||||
validator: AttachedValidator,
|
validator: AttachedValidator,
|
||||||
attestationData: AttestationData,
|
attestationData: AttestationData,
|
||||||
committeeLen: int,
|
committeeLen: int,
|
||||||
|
@ -295,7 +295,7 @@ proc sendAttestation(node: BeaconNode,
|
||||||
logScope: pcs = "send_attestation"
|
logScope: pcs = "send_attestation"
|
||||||
|
|
||||||
let
|
let
|
||||||
validatorSignature = await validator.signAttestation(attestationData, state)
|
validatorSignature = await validator.signAttestation(attestationData, fork)
|
||||||
|
|
||||||
var aggregationBits = CommitteeValidatorsBits.init(committeeLen)
|
var aggregationBits = CommitteeValidatorsBits.init(committeeLen)
|
||||||
aggregationBits.raiseBit indexInCommittee
|
aggregationBits.raiseBit indexInCommittee
|
||||||
|
@ -374,8 +374,9 @@ proc proposeBlock(node: BeaconNode,
|
||||||
# To create a block, we'll first apply a partial block to the state, skipping
|
# To create a block, we'll first apply a partial block to the state, skipping
|
||||||
# some validations.
|
# some validations.
|
||||||
let
|
let
|
||||||
|
fork = state.fork
|
||||||
blockBody = BeaconBlockBody(
|
blockBody = BeaconBlockBody(
|
||||||
randao_reveal: validator.genRandaoReveal(state, slot),
|
randao_reveal: validator.genRandaoReveal(fork, slot),
|
||||||
eth1_data: eth1data,
|
eth1_data: eth1data,
|
||||||
attestations:
|
attestations:
|
||||||
node.attestationPool.getAttestationsForBlock(state, slot),
|
node.attestationPool.getAttestationsForBlock(state, slot),
|
||||||
|
@ -388,10 +389,7 @@ proc proposeBlock(node: BeaconNode,
|
||||||
body: blockBody,
|
body: blockBody,
|
||||||
# TODO: This shouldn't be necessary if OpaqueBlob is the default
|
# TODO: This shouldn't be necessary if OpaqueBlob is the default
|
||||||
signature: ValidatorSig(kind: OpaqueBlob))
|
signature: ValidatorSig(kind: OpaqueBlob))
|
||||||
|
|
||||||
var
|
|
||||||
tmpState = hashedState
|
tmpState = hashedState
|
||||||
|
|
||||||
discard state_transition(tmpState, newBlock, {skipValidation})
|
discard state_transition(tmpState, newBlock, {skipValidation})
|
||||||
# TODO only enable in fast-fail debugging situations
|
# TODO only enable in fast-fail debugging situations
|
||||||
# otherwise, bad attestations can bring down network
|
# otherwise, bad attestations can bring down network
|
||||||
|
@ -402,8 +400,11 @@ proc proposeBlock(node: BeaconNode,
|
||||||
let blockRoot = signing_root(newBlock)
|
let blockRoot = signing_root(newBlock)
|
||||||
|
|
||||||
# Careful, state no longer valid after here..
|
# Careful, state no longer valid after here..
|
||||||
|
# We use the fork from the pre-newBlock state which should be fine because
|
||||||
|
# fork carries two epochs, so even if it's a fork block, the right thing
|
||||||
|
# will happen here
|
||||||
newBlock.signature =
|
newBlock.signature =
|
||||||
await validator.signBlockProposal(state, slot, blockRoot)
|
await validator.signBlockProposal(fork, slot, blockRoot)
|
||||||
|
|
||||||
(blockRoot, newBlock)
|
(blockRoot, newBlock)
|
||||||
|
|
||||||
|
@ -551,7 +552,7 @@ proc handleAttestations(node: BeaconNode, head: BlockRef, slot: Slot) =
|
||||||
|
|
||||||
for a in attestations:
|
for a in attestations:
|
||||||
traceAsyncErrors sendAttestation(
|
traceAsyncErrors sendAttestation(
|
||||||
node, state, a.validator, a.data, a.committeeLen, a.indexInCommittee)
|
node, state.fork, a.validator, a.data, a.committeeLen, a.indexInCommittee)
|
||||||
|
|
||||||
proc handleProposal(node: BeaconNode, head: BlockRef, slot: Slot):
|
proc handleProposal(node: BeaconNode, head: BlockRef, slot: Slot):
|
||||||
Future[BlockRef] {.async.} =
|
Future[BlockRef] {.async.} =
|
||||||
|
@ -1052,9 +1053,6 @@ when isMainModule:
|
||||||
config.depositPrivateKey)
|
config.depositPrivateKey)
|
||||||
|
|
||||||
of query:
|
of query:
|
||||||
var
|
|
||||||
trieDB = trieDB newChainDb(config.databaseDir)
|
|
||||||
|
|
||||||
case config.queryCmd
|
case config.queryCmd
|
||||||
of QueryCmd.nimQuery:
|
of QueryCmd.nimQuery:
|
||||||
# TODO: This will handle a simple subset of Nim using
|
# TODO: This will handle a simple subset of Nim using
|
||||||
|
|
|
@ -345,15 +345,17 @@ proc is_valid_indexed_attestation*(
|
||||||
return false
|
return false
|
||||||
|
|
||||||
# Verify aggregate signature
|
# Verify aggregate signature
|
||||||
result = bls_verify(
|
if not bls_verify(
|
||||||
bls_aggregate_pubkeys(mapIt(indices, state.validators[it.int].pubkey)),
|
bls_aggregate_pubkeys(mapIt(indices, state.validators[it.int].pubkey)),
|
||||||
hash_tree_root(indexed_attestation.data).data,
|
hash_tree_root(indexed_attestation.data).data,
|
||||||
indexed_attestation.signature,
|
indexed_attestation.signature,
|
||||||
get_domain(
|
get_domain(
|
||||||
state, DOMAIN_BEACON_ATTESTER, indexed_attestation.data.target.epoch)
|
state, DOMAIN_BEACON_ATTESTER, indexed_attestation.data.target.epoch)
|
||||||
)
|
):
|
||||||
if not result:
|
|
||||||
notice "indexed attestation: signature verification failure"
|
notice "indexed attestation: signature verification failure"
|
||||||
|
return false
|
||||||
|
|
||||||
|
true
|
||||||
|
|
||||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.9.1/specs/core/0_beacon-chain.md#get_attesting_indices
|
# https://github.com/ethereum/eth2.0-specs/blob/v0.9.1/specs/core/0_beacon-chain.md#get_attesting_indices
|
||||||
func get_attesting_indices*(state: BeaconState,
|
func get_attesting_indices*(state: BeaconState,
|
||||||
|
|
|
@ -122,17 +122,24 @@ func compute_domain*(
|
||||||
result[4..7] = fork_version
|
result[4..7] = fork_version
|
||||||
|
|
||||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.9.1/specs/core/0_beacon-chain.md#get_domain
|
# https://github.com/ethereum/eth2.0-specs/blob/v0.9.1/specs/core/0_beacon-chain.md#get_domain
|
||||||
|
|
||||||
|
func get_domain*(
|
||||||
|
fork: Fork, domain_type: DomainType, epoch: Epoch): Domain =
|
||||||
|
## Return the signature domain (fork version concatenated with domain type)
|
||||||
|
## of a message.
|
||||||
|
let
|
||||||
|
fork_version =
|
||||||
|
if epoch < fork.epoch:
|
||||||
|
fork.previous_version
|
||||||
|
else:
|
||||||
|
fork.current_version
|
||||||
|
compute_domain(domain_type, fork_version)
|
||||||
|
|
||||||
func get_domain*(
|
func get_domain*(
|
||||||
state: BeaconState, domain_type: DomainType, message_epoch: Epoch): Domain =
|
state: BeaconState, domain_type: DomainType, message_epoch: Epoch): Domain =
|
||||||
## Return the signature domain (fork version concatenated with domain type)
|
## Return the signature domain (fork version concatenated with domain type)
|
||||||
## of a message.
|
## of a message.
|
||||||
let
|
get_domain(state.fork, domain_type, message_epoch)
|
||||||
epoch = message_epoch
|
|
||||||
fork_version = if epoch < state.fork.epoch:
|
|
||||||
state.fork.previous_version
|
|
||||||
else:
|
|
||||||
state.fork.current_version
|
|
||||||
compute_domain(domain_type, fork_version)
|
|
||||||
|
|
||||||
func get_domain*(state: BeaconState, domain_type: DomainType): Domain =
|
func get_domain*(state: BeaconState, domain_type: DomainType): Domain =
|
||||||
get_domain(state, domain_type, get_current_epoch(state))
|
get_domain(state, domain_type, get_current_epoch(state))
|
||||||
|
|
|
@ -26,7 +26,7 @@ func getValidator*(pool: ValidatorPool,
|
||||||
validatorKey: ValidatorPubKey): AttachedValidator =
|
validatorKey: ValidatorPubKey): AttachedValidator =
|
||||||
pool.validators.getOrDefault(validatorKey)
|
pool.validators.getOrDefault(validatorKey)
|
||||||
|
|
||||||
proc signBlockProposal*(v: AttachedValidator, state: BeaconState, slot: Slot,
|
proc signBlockProposal*(v: AttachedValidator, fork: Fork, slot: Slot,
|
||||||
blockRoot: Eth2Digest): Future[ValidatorSig] {.async.} =
|
blockRoot: Eth2Digest): Future[ValidatorSig] {.async.} =
|
||||||
|
|
||||||
if v.kind == inProcess:
|
if v.kind == inProcess:
|
||||||
|
@ -34,7 +34,7 @@ proc signBlockProposal*(v: AttachedValidator, state: BeaconState, slot: Slot,
|
||||||
# care about this in here
|
# care about this in here
|
||||||
let
|
let
|
||||||
domain =
|
domain =
|
||||||
get_domain(state, DOMAIN_BEACON_PROPOSER, compute_epoch_at_slot(slot))
|
get_domain(fork, DOMAIN_BEACON_PROPOSER, compute_epoch_at_slot(slot))
|
||||||
# TODO this is an ugly hack to fake a delay and subsequent async reordering
|
# TODO this is an ugly hack to fake a delay and subsequent async reordering
|
||||||
# for the purpose of testing the external validator delay - to be
|
# for the purpose of testing the external validator delay - to be
|
||||||
# replaced by something more sensible
|
# replaced by something more sensible
|
||||||
|
@ -47,11 +47,11 @@ proc signBlockProposal*(v: AttachedValidator, state: BeaconState, slot: Slot,
|
||||||
|
|
||||||
proc signAttestation*(v: AttachedValidator,
|
proc signAttestation*(v: AttachedValidator,
|
||||||
attestation: AttestationData,
|
attestation: AttestationData,
|
||||||
state: BeaconState): Future[ValidatorSig] {.async.} =
|
fork: Fork): Future[ValidatorSig] {.async.} =
|
||||||
if v.kind == inProcess:
|
if v.kind == inProcess:
|
||||||
let
|
let
|
||||||
attestationRoot = hash_tree_root(attestation)
|
attestationRoot = hash_tree_root(attestation)
|
||||||
domain = get_domain(state, DOMAIN_BEACON_ATTESTER, attestation.target.epoch)
|
domain = get_domain(fork, DOMAIN_BEACON_ATTESTER, attestation.target.epoch)
|
||||||
|
|
||||||
# TODO this is an ugly hack to fake a delay and subsequent async reordering
|
# TODO this is an ugly hack to fake a delay and subsequent async reordering
|
||||||
# for the purpose of testing the external validator delay - to be
|
# for the purpose of testing the external validator delay - to be
|
||||||
|
@ -63,14 +63,14 @@ proc signAttestation*(v: AttachedValidator,
|
||||||
error "Unimplemented"
|
error "Unimplemented"
|
||||||
quit 1
|
quit 1
|
||||||
|
|
||||||
func genRandaoReveal*(k: ValidatorPrivKey, state: BeaconState, slot: Slot):
|
func genRandaoReveal*(k: ValidatorPrivKey, fork: Fork, slot: Slot):
|
||||||
ValidatorSig =
|
ValidatorSig =
|
||||||
let
|
let
|
||||||
domain = get_domain(state, DOMAIN_RANDAO, compute_epoch_at_slot(slot))
|
domain = get_domain(fork, DOMAIN_RANDAO, compute_epoch_at_slot(slot))
|
||||||
root = hash_tree_root(compute_epoch_at_slot(slot).uint64).data
|
root = hash_tree_root(compute_epoch_at_slot(slot).uint64).data
|
||||||
|
|
||||||
bls_sign(k, root, domain)
|
bls_sign(k, root, domain)
|
||||||
|
|
||||||
func genRandaoReveal*(v: AttachedValidator, state: BeaconState, slot: Slot):
|
func genRandaoReveal*(v: AttachedValidator, fork: Fork, slot: Slot):
|
||||||
ValidatorSig =
|
ValidatorSig =
|
||||||
genRandaoReveal(v.privKey, state, slot)
|
genRandaoReveal(v.privKey, fork, slot)
|
||||||
|
|
|
@ -75,17 +75,6 @@ func makeInitialDeposits*(
|
||||||
for i in 0..<n.int:
|
for i in 0..<n.int:
|
||||||
result.add makeDeposit(i, flags)
|
result.add makeDeposit(i, flags)
|
||||||
|
|
||||||
func getNextBeaconProposerIndex*(state: BeaconState): ValidatorIndex =
|
|
||||||
# TODO: This is a special version of get_beacon_proposer_index that takes into
|
|
||||||
# account the partial update done at the start of slot processing -
|
|
||||||
# see get_shard_committees_index
|
|
||||||
var
|
|
||||||
next_state = state
|
|
||||||
cache = get_empty_per_epoch_cache()
|
|
||||||
|
|
||||||
next_state.slot += 1
|
|
||||||
get_beacon_proposer_index(next_state, cache)
|
|
||||||
|
|
||||||
proc addBlock*(
|
proc addBlock*(
|
||||||
state: var BeaconState, previous_block_root: Eth2Digest,
|
state: var BeaconState, previous_block_root: Eth2Digest,
|
||||||
body: BeaconBlockBody, flags: UpdateFlags = {}): BeaconBlock =
|
body: BeaconBlockBody, flags: UpdateFlags = {}): BeaconBlock =
|
||||||
|
@ -106,7 +95,7 @@ proc addBlock*(
|
||||||
|
|
||||||
# TODO ugly hack; API needs rethinking
|
# TODO ugly hack; API needs rethinking
|
||||||
var new_body = body
|
var new_body = body
|
||||||
new_body.randao_reveal = privKey.genRandaoReveal(state, state.slot + 1)
|
new_body.randao_reveal = privKey.genRandaoReveal(state.fork, state.slot + 1)
|
||||||
new_body.eth1_data = Eth1Data()
|
new_body.eth1_data = Eth1Data()
|
||||||
|
|
||||||
var
|
var
|
||||||
|
@ -128,21 +117,22 @@ proc addBlock*(
|
||||||
# can set the state root in order to be able to create a valid signature
|
# can set the state root in order to be able to create a valid signature
|
||||||
new_block.state_root = hash_tree_root(state)
|
new_block.state_root = hash_tree_root(state)
|
||||||
|
|
||||||
let proposerPrivkey = hackPrivKey(proposer)
|
doAssert privKey.pubKey() == proposer.pubkey,
|
||||||
doAssert proposerPrivkey.pubKey() == proposer.pubkey,
|
|
||||||
"signature key should be derived from private key! - wrong privkey?"
|
"signature key should be derived from private key! - wrong privkey?"
|
||||||
|
|
||||||
if skipValidation notin flags:
|
if skipValidation notin flags:
|
||||||
let block_root = signing_root(new_block)
|
let block_root = signing_root(new_block)
|
||||||
# We have a signature - put it in the block and we should be done!
|
# We have a signature - put it in the block and we should be done!
|
||||||
new_block.signature =
|
new_block.signature =
|
||||||
bls_sign(proposerPrivkey, block_root.data,
|
bls_sign(privKey, block_root.data,
|
||||||
get_domain(state, DOMAIN_BEACON_PROPOSER, compute_epoch_at_slot(new_block.slot)))
|
get_domain(state, DOMAIN_BEACON_PROPOSER,
|
||||||
|
compute_epoch_at_slot(new_block.slot)))
|
||||||
|
|
||||||
doAssert bls_verify(
|
doAssert bls_verify(
|
||||||
proposer.pubkey,
|
proposer.pubkey,
|
||||||
block_root.data, new_block.signature,
|
block_root.data, new_block.signature,
|
||||||
get_domain(state, DOMAIN_BEACON_PROPOSER, compute_epoch_at_slot(new_block.slot))),
|
get_domain(
|
||||||
|
state, DOMAIN_BEACON_PROPOSER, compute_epoch_at_slot(new_block.slot))),
|
||||||
"we just signed this message - it should pass verification!"
|
"we just signed this message - it should pass verification!"
|
||||||
|
|
||||||
new_block
|
new_block
|
||||||
|
|
Loading…
Reference in New Issue