-
Notifications
You must be signed in to change notification settings - Fork 231
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement the /eth/v1/validator/prepare_beacon_proposer end-point #3901
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import | ||
std/tables, | ||
stew/results, | ||
web3/ethtypes, | ||
../datatypes/base | ||
|
||
type | ||
Entry = object | ||
recipient: Eth1Address | ||
addedAt: Epoch | ||
|
||
DynamicFeeRecipientsStore* = object | ||
mappings: Table[ValidatorIndex, Entry] | ||
|
||
func init*(T: type DynamicFeeRecipientsStore): T = | ||
T(mappings: initTable[ValidatorIndex, Entry]()) | ||
|
||
func addMapping*(store: var DynamicFeeRecipientsStore, | ||
validator: ValidatorIndex, | ||
feeRecipient: Eth1Address, | ||
currentEpoch: Epoch) = | ||
store.mappings[validator] = Entry(recipient: feeRecipient, | ||
addedAt: currentEpoch) | ||
|
||
func getDynamicFeeRecipient*(store: var DynamicFeeRecipientsStore, | ||
validator: ValidatorIndex, | ||
currentEpoch: Epoch): Opt[Eth1Address] = | ||
store.mappings.withValue(validator, entry) do: | ||
# https://ethereum.github.io/beacon-APIs/#/ValidatorRequiredApi/prepareBeaconProposer | ||
# | ||
# The information supplied for each validator index will persist | ||
# through the epoch in which the call is submitted and for a further | ||
# two epochs after that, or until the beacon node restarts. | ||
# | ||
# It is expected that validator clients will send this information | ||
# periodically, for example each epoch, to ensure beacon nodes have | ||
# correct and timely fee recipient information. | ||
return if (currentEpoch - entry.addedAt) > 2: | ||
err() | ||
else: | ||
ok entry.recipient | ||
do: | ||
return err() | ||
|
||
func pruneOldMappings*(store: var DynamicFeeRecipientsStore, | ||
currentEpoch: Epoch) = | ||
var toPrune: seq[ValidatorIndex] | ||
|
||
for idx, entry in store.mappings: | ||
if (currentEpoch - entry.addedAt) > 2: | ||
toPrune.add idx | ||
|
||
for idx in toPrune: | ||
store.mappings.del idx |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -305,6 +305,7 @@ proc getBlockProposalEth1Data*(node: BeaconNode, | |
state, finalizedEpochRef.eth1_data, | ||
finalizedEpochRef.eth1_deposit_index) | ||
|
||
# TODO: This copies the entire BeaconState on each call | ||
proc forkchoice_updated(state: bellatrix.BeaconState, | ||
head_block_hash: Eth2Digest, | ||
finalized_block_hash: Eth2Digest, | ||
|
@@ -340,7 +341,10 @@ proc get_execution_payload( | |
await execution_engine.getPayload(payload_id.get)) | ||
|
||
proc getExecutionPayload( | ||
node: BeaconNode, proposalState: auto, pubkey: ValidatorPubKey): | ||
node: BeaconNode, proposalState: auto, | ||
epoch: Epoch, | ||
validator_index: ValidatorIndex, | ||
pubkey: ValidatorPubKey): | ||
Future[ExecutionPayload] {.async.} = | ||
# https://github.com/ethereum/consensus-specs/blob/v1.1.10/specs/bellatrix/validator.md#executionpayload | ||
|
||
|
@@ -374,8 +378,11 @@ proc getExecutionPayload( | |
terminalBlockHash | ||
latestFinalized = | ||
node.dag.loadExecutionBlockRoot(node.dag.finalizedHead.blck) | ||
feeRecipient = node.config.getSuggestedFeeRecipient(pubkey).valueOr: | ||
node.config.defaultFeeRecipient | ||
dynamicFeeRecipient = node.dynamicFeeRecipientsStore.getDynamicFeeRecipient( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fwiw, I think this can be written as There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
validator_index, epoch) | ||
feeRecipient = dynamicFeeRecipient.valueOr: | ||
node.config.getSuggestedFeeRecipient(pubkey).valueOr: | ||
node.config.defaultFeeRecipient | ||
payload_id = (await forkchoice_updated( | ||
proposalState.bellatrixData.data, latestHead, latestFinalized, | ||
feeRecipient, | ||
|
@@ -461,6 +468,7 @@ proc makeBeaconBlockForHeadAndSlot*(node: BeaconNode, | |
let pubkey = node.dag.validatorKey(validator_index) | ||
(await getExecutionPayload( | ||
node, proposalState, | ||
slot.epoch, validator_index, | ||
# TODO https://github.com/nim-lang/Nim/issues/19802 | ||
if pubkey.isSome: pubkey.get.toPubKey else: default(ValidatorPubKey))), | ||
noRollback, # Temporary state - no need for rollback | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RestValidatorIndex
I believe?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RestValidatorIndex
was something that raised in prominence when we tried to introduce a widerValidatorIndex
reform (which wasn't merged). In the current code, it's used only for a single field and all other REST data types use the specValidatorIndex
type.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The wider VI is unrelated -
RestValidatorIndex
is used to differentiate between errors: a validator index that is larger than2**32
but smaller than2**41
(or something like that) is a valid but not yet assigned validator index - theValidatorIndex
parser is unable to distinguish these two cases, resulting in a poor error message, or in some requests, invalid responses (because some requests give an empty response for a not-yet-assigned validator index)