Merge branch 'feat/eip-7495' into feat_eip-6493

This commit is contained in:
Etan Kissling 2024-05-24 17:19:04 +02:00
commit d221cd5a6b
No known key found for this signature in database
GPG Key ID: B21DA824C5A3D03D
42 changed files with 453 additions and 929 deletions

View File

@ -431,20 +431,22 @@ OK: 2/2 Fail: 0/2 Skip: 0/2
OK: 253/253 Fail: 0/253 Skip: 0/253 OK: 253/253 Fail: 0/253 Skip: 0/253
## EF - SSZ generic types ## EF - SSZ generic types
```diff ```diff
Testing basic_vector inputs - invalid Skip Testing basic_vector inputs - invalid Skip
+ Testing basic_vector inputs - valid OK + Testing basic_vector inputs - valid OK
+ Testing bitlist inputs - invalid OK + Testing bitlist inputs - invalid OK
+ Testing bitlist inputs - valid OK + Testing bitlist inputs - valid OK
Testing bitvector inputs - invalid Skip Testing bitvector inputs - invalid Skip
+ Testing bitvector inputs - valid OK + Testing bitvector inputs - valid OK
+ Testing boolean inputs - invalid OK + Testing boolean inputs - invalid OK
+ Testing boolean inputs - valid OK + Testing boolean inputs - valid OK
+ Testing containers inputs - invalid - skipping BitsStruct OK + Testing containers inputs - invalid - skipping BitsStruct OK
+ Testing containers inputs - valid - skipping BitsStruct OK + Testing containers inputs - valid - skipping BitsStruct OK
+ Testing uints inputs - invalid OK + Testing profiles inputs - valid OK
+ Testing uints inputs - valid OK + Testing stablecontainers inputs - valid OK
+ Testing uints inputs - invalid OK
+ Testing uints inputs - valid OK
``` ```
OK: 10/12 Fail: 0/12 Skip: 2/12 OK: 12/14 Fail: 0/14 Skip: 2/14
## EIP-4881 ## EIP-4881
```diff ```diff
+ deposit_cases OK + deposit_cases OK
@ -1030,4 +1032,4 @@ OK: 2/2 Fail: 0/2 Skip: 0/2
OK: 9/9 Fail: 0/9 Skip: 0/9 OK: 9/9 Fail: 0/9 Skip: 0/9
---TOTAL--- ---TOTAL---
OK: 686/691 Fail: 0/691 Skip: 5/691 OK: 689/694 Fail: 0/694 Skip: 5/694

View File

@ -9,12 +9,8 @@
import import
chronicles, chronicles,
../spec/datatypes/[phase0, altair, bellatrix],
../spec/forks ../spec/forks
from ../spec/datatypes/capella import SomeBeaconBlock, TrustedBeaconBlock
from ../spec/datatypes/deneb import SomeBeaconBlock, TrustedBeaconBlock
export chronicles, forks export chronicles, forks
type type
@ -76,7 +72,7 @@ func init*(
deneb.SomeBeaconBlock | deneb.TrustedBeaconBlock | deneb.SomeBeaconBlock | deneb.TrustedBeaconBlock |
electra.SomeBeaconBlock | electra.TrustedBeaconBlock): BlockRef = electra.SomeBeaconBlock | electra.TrustedBeaconBlock): BlockRef =
BlockRef.init( BlockRef.init(
root, Opt.some Eth2Digest(blck.body.execution_payload.block_hash), root, Opt.some blck.body.execution_payload.block_hash,
executionValid = executionValid =
executionValid or blck.body.execution_payload.block_hash == ZERO_HASH, executionValid or blck.body.execution_payload.block_hash == ZERO_HASH,
blck.slot) blck.slot)

View File

@ -16,8 +16,7 @@ import
../spec/datatypes/base, ../spec/datatypes/base,
./block_pools_types, blockchain_dag ./block_pools_types, blockchain_dag
debugComment "probably just need Electra shortLog here" from ../spec/datatypes/electra import shortLog
import ../spec/forks # prune this, it's for electra attestation logging
export export
base, extras, block_pools_types, results base, extras, block_pools_types, results

View File

@ -273,7 +273,7 @@ proc main() {.async.} =
error "Failed to read an Eth1 private key from standard input" error "Failed to read an Eth1 private key from standard input"
if privateKey.len > 0: if privateKey.len > 0:
conf.privateKey = privateKey.string conf.privateKey = privateKey
let web3 = await initWeb3(conf.web3Url, conf.privateKey) let web3 = await initWeb3(conf.web3Url, conf.privateKey)

View File

@ -366,8 +366,6 @@ proc updateGossipStatus*(
lightClient: LightClient, slot: Slot, dagIsBehind = default(Option[bool])) = lightClient: LightClient, slot: Slot, dagIsBehind = default(Option[bool])) =
template cfg(): auto = lightClient.cfg template cfg(): auto = lightClient.cfg
debugComment "when LC on electra works, add cfg.ELECTRA_FORK_EPOCH"
let let
epoch = slot.epoch epoch = slot.epoch

View File

@ -26,10 +26,10 @@ type
func parseBootstrapAddress*(address: string): func parseBootstrapAddress*(address: string):
Result[enr.Record, cstring] = Result[enr.Record, cstring] =
let lowerCaseAddress = toLowerAscii(string address) let lowerCaseAddress = toLowerAscii(address)
if lowerCaseAddress.startsWith("enr:"): if lowerCaseAddress.startsWith("enr:"):
var enrRec: enr.Record var enrRec: enr.Record
if enrRec.fromURI(string address): if enrRec.fromURI(address):
return ok enrRec return ok enrRec
return err "Invalid ENR bootstrap record" return err "Invalid ENR bootstrap record"
elif lowerCaseAddress.startsWith("enode:"): elif lowerCaseAddress.startsWith("enode:"):

View File

@ -1,5 +1,5 @@
# beacon_chain # beacon_chain
# Copyright (c) 2021-2023 Status Research & Development GmbH # Copyright (c) 2021-2024 Status Research & Development GmbH
# Licensed and distributed under either of # Licensed and distributed under either of
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT). # * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0). # * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
@ -10,5 +10,4 @@
--styleCheck:usages --styleCheck:usages
--styleCheck:hint --styleCheck:hint
--hint[ConvFromXtoItselfNotNeeded]:off
--hint[Processing]:off --hint[Processing]:off

View File

@ -46,7 +46,7 @@ proc listRemoteValidators*(
if item.kind == ValidatorKind.Remote and item.data.remotes.len == 1: if item.kind == ValidatorKind.Remote and item.data.remotes.len == 1:
validators.add RemoteKeystoreInfo( validators.add RemoteKeystoreInfo(
pubkey: item.pubkey, pubkey: item.pubkey,
url: HttpHostUri(item.data.remotes[0].url) url: item.data.remotes[0].url
) )
validators validators

View File

@ -688,8 +688,8 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
message = (await PayloadType.makeBeaconBlockForHeadAndSlot( message = (await PayloadType.makeBeaconBlockForHeadAndSlot(
node, qrandao, proposer, qgraffiti, qhead, qslot)).valueOr: node, qrandao, proposer, qgraffiti, qhead, qslot)).valueOr:
return RestApiResponse.jsonError(Http500, error) return RestApiResponse.jsonError(Http500, error)
executionValue = Opt.some(UInt256(message.executionPayloadValue)) executionValue = Opt.some(message.executionPayloadValue)
consensusValue = Opt.some(UInt256(message.consensusBlockValue)) consensusValue = Opt.some(message.consensusBlockValue)
headers = consensusFork.getMaybeBlindedHeaders( headers = consensusFork.getMaybeBlindedHeaders(
isBlinded = false, executionValue, consensusValue) isBlinded = false, executionValue, consensusValue)
@ -914,7 +914,7 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
request.validator_index).pubkey request.validator_index).pubkey
node.validatorMonitor[].addAutoMonitor( node.validatorMonitor[].addAutoMonitor(
validator_pubkey, ValidatorIndex(request.validator_index)) validator_pubkey, request.validator_index)
RestApiResponse.jsonMsgResponse(BeaconCommitteeSubscriptionSuccess) RestApiResponse.jsonMsgResponse(BeaconCommitteeSubscriptionSuccess)
@ -955,7 +955,7 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
validator_pubkey, item.until_epoch) validator_pubkey, item.until_epoch)
node.validatorMonitor[].addAutoMonitor( node.validatorMonitor[].addAutoMonitor(
validator_pubkey, ValidatorIndex(item.validator_index)) validator_pubkey, item.validator_index)
RestApiResponse.jsonMsgResponse(SyncCommitteeSubscriptionSuccess) RestApiResponse.jsonMsgResponse(SyncCommitteeSubscriptionSuccess)

View File

@ -289,7 +289,7 @@ func initiate_validator_exit*(
# Set validator exit epoch and withdrawable epoch # Set validator exit epoch and withdrawable epoch
validator.exit_epoch = exit_queue_epoch validator.exit_epoch = exit_queue_epoch
validator.withdrawable_epoch = validator.withdrawable_epoch =
Epoch(validator.exit_epoch + cfg.MIN_VALIDATOR_WITHDRAWABILITY_DELAY) validator.exit_epoch + cfg.MIN_VALIDATOR_WITHDRAWABILITY_DELAY
if validator.withdrawable_epoch < validator.exit_epoch: if validator.withdrawable_epoch < validator.exit_epoch:
return err("Invalid large withdrawable epoch") return err("Invalid large withdrawable epoch")
state.validators.mitem(index) = validator state.validators.mitem(index) = validator

View File

@ -986,4 +986,3 @@ func ofLen*[T, N](ListType: type List[T, N], n: int): ListType =
raise newException(SszSizeMismatchError) raise newException(SszSizeMismatchError)
template debugComment*(s: string) = discard template debugComment*(s: string) = discard
template debugRaiseAssert*(s: string) = discard

View File

@ -408,8 +408,7 @@ type
RestNimbusTimestamp2 | RestNimbusTimestamp2 |
GetGraffitiResponse GetGraffitiResponse
DecodeConsensysTypes* = DecodeConsensysTypes* = ProduceBlindedBlockResponse
ProduceBlockResponseV2 | ProduceBlindedBlockResponse
RestVersioned*[T] = object RestVersioned*[T] = object
data*: T data*: T
@ -1443,8 +1442,7 @@ template prepareForkedBlockReading(blockType: typedesc,
if version.isNone(): if version.isNone():
reader.raiseUnexpectedValue("Incorrect version field value") reader.raiseUnexpectedValue("Incorrect version field value")
of "data": of "data":
when (blockType is ProduceBlockResponseV2) or when (blockType is ForkedBlindedBeaconBlock) or
(blockType is ForkedBlindedBeaconBlock) or
(blockType is ProduceBlockResponseV3): (blockType is ProduceBlockResponseV3):
if data.isSome(): if data.isSome():
reader.raiseUnexpectedField( reader.raiseUnexpectedField(
@ -1492,92 +1490,6 @@ template prepareForkedBlockReading(blockType: typedesc,
if data.isNone(): if data.isNone():
reader.raiseUnexpectedValue("Field `data` is missing") reader.raiseUnexpectedValue("Field `data` is missing")
proc readValue*[BlockType: ProduceBlockResponseV2](
reader: var JsonReader[RestJson],
value: var BlockType) {.raises: [IOError, SerializationError].} =
var
version: Opt[ConsensusFork]
data: Opt[JsonString]
blinded: Opt[bool]
payloadValue: Opt[Uint256]
blockValue: Opt[Uint256]
prepareForkedBlockReading(BlockType, reader, version, data, blinded,
payloadValue, blockValue)
case version.get():
of ConsensusFork.Phase0:
let res =
try:
RestJson.decode(string(data.get()),
phase0.BeaconBlock,
requireAllFields = true,
allowUnknownFields = true)
except SerializationError:
reader.raiseUnexpectedValue("Incorrect phase0 block format")
value = ProduceBlockResponseV2(kind: ConsensusFork.Phase0,
phase0Data: res)
of ConsensusFork.Altair:
let res =
try:
RestJson.decode(string(data.get()),
altair.BeaconBlock,
requireAllFields = true,
allowUnknownFields = true)
except SerializationError:
reader.raiseUnexpectedValue("Incorrect altair block format")
value = ProduceBlockResponseV2(kind: ConsensusFork.Altair,
altairData: res)
of ConsensusFork.Bellatrix:
let res =
try:
RestJson.decode(string(data.get()),
bellatrix.BeaconBlock,
requireAllFields = true,
allowUnknownFields = true)
except SerializationError:
reader.raiseUnexpectedValue("Incorrect bellatrix block format")
value = ProduceBlockResponseV2(kind: ConsensusFork.Bellatrix,
bellatrixData: res)
of ConsensusFork.Capella:
let res =
try:
RestJson.decode(string(data.get()),
capella.BeaconBlock,
requireAllFields = true,
allowUnknownFields = true)
except SerializationError:
reader.raiseUnexpectedValue("Incorrect capella block format")
value = ProduceBlockResponseV2(kind: ConsensusFork.Capella,
capellaData: res)
of ConsensusFork.Deneb:
let res =
try:
RestJson.decode(string(data.get()),
deneb.BlockContents,
requireAllFields = true,
allowUnknownFields = true)
except SerializationError:
reader.raiseUnexpectedValue("Incorrect deneb block format")
value = ProduceBlockResponseV2(kind: ConsensusFork.Deneb,
denebData: res)
of ConsensusFork.Electra:
let res =
try:
RestJson.decode(string(data.get()),
electra.BlockContents,
requireAllFields = true,
allowUnknownFields = true)
except SerializationError:
reader.raiseUnexpectedValue("Incorrect electra block format")
value = ProduceBlockResponseV2(kind: ConsensusFork.Electra,
electraData: res)
proc readValue*[BlockType: ForkedBlindedBeaconBlock]( proc readValue*[BlockType: ForkedBlindedBeaconBlock](
reader: var JsonReader[RestJson], reader: var JsonReader[RestJson],
value: var BlockType value: var BlockType
@ -3777,35 +3689,7 @@ proc decodeBytes*[T: DecodeConsensysTypes](
data = string.fromBytes(value) data = string.fromBytes(value)
return err("Serialization error") return err("Serialization error")
elif mediaType == OctetStreamMediaType: elif mediaType == OctetStreamMediaType:
when t is ProduceBlockResponseV2: when t is ProduceBlindedBlockResponse:
let fork = ConsensusFork.decodeString(consensusVersion).valueOr:
return err("Invalid or Unsupported consensus version")
case fork
of ConsensusFork.Electra:
let blckContents = ? readSszResBytes(electra.BlockContents, value)
ok(ProduceBlockResponseV2(kind: ConsensusFork.Electra,
electraData: blckContents))
of ConsensusFork.Deneb:
let blckContents = ? readSszResBytes(deneb.BlockContents, value)
ok(ProduceBlockResponseV2(kind: ConsensusFork.Deneb,
denebData: blckContents))
of ConsensusFork.Capella:
let blck = ? readSszResBytes(capella.BeaconBlock, value)
ok(ProduceBlockResponseV2(kind: ConsensusFork.Capella,
capellaData: blck))
of ConsensusFork.Bellatrix:
let blck = ? readSszResBytes(bellatrix.BeaconBlock, value)
ok(ProduceBlockResponseV2(kind: ConsensusFork.Bellatrix,
bellatrixData: blck))
of ConsensusFork.Altair:
let blck = ? readSszResBytes(altair.BeaconBlock, value)
ok(ProduceBlockResponseV2(kind: ConsensusFork.Altair,
altairData: blck))
of ConsensusFork.Phase0:
let blck = ? readSszResBytes(phase0.BeaconBlock, value)
ok(ProduceBlockResponseV2(kind: ConsensusFork.Phase0,
phase0Data: blck))
elif t is ProduceBlindedBlockResponse:
let fork = ConsensusFork.decodeString(consensusVersion).valueOr: let fork = ConsensusFork.decodeString(consensusVersion).valueOr:
return err("Invalid or Unsupported consensus version") return err("Invalid or Unsupported consensus version")
case fork case fork

View File

@ -212,7 +212,7 @@ proc getLightClientBootstrap*(
let consensusForkRes = ConsensusFork.decodeString( let consensusForkRes = ConsensusFork.decodeString(
resp.headers.getString("eth-consensus-version")) resp.headers.getString("eth-consensus-version"))
if consensusForkRes.isErr: if consensusForkRes.isErr:
raiseRestDecodingBytesError(cstring(consensusForkRes.error)) raiseRestDecodingBytesError(consensusForkRes.error)
ForkedLightClientBootstrap.decodeHttpLightClientObject( ForkedLightClientBootstrap.decodeHttpLightClientObject(
data, resp.contentType, consensusForkRes.get, cfg) data, resp.contentType, consensusForkRes.get, cfg)
of 404: of 404:
@ -294,7 +294,7 @@ proc getLightClientFinalityUpdate*(
let consensusForkRes = ConsensusFork.decodeString( let consensusForkRes = ConsensusFork.decodeString(
resp.headers.getString("eth-consensus-version")) resp.headers.getString("eth-consensus-version"))
if consensusForkRes.isErr: if consensusForkRes.isErr:
raiseRestDecodingBytesError(cstring(consensusForkRes.error)) raiseRestDecodingBytesError(consensusForkRes.error)
ForkedLightClientFinalityUpdate.decodeHttpLightClientObject( ForkedLightClientFinalityUpdate.decodeHttpLightClientObject(
data, resp.contentType, consensusForkRes.get, cfg) data, resp.contentType, consensusForkRes.get, cfg)
of 404: of 404:
@ -336,7 +336,7 @@ proc getLightClientOptimisticUpdate*(
let consensusForkRes = ConsensusFork.decodeString( let consensusForkRes = ConsensusFork.decodeString(
resp.headers.getString("eth-consensus-version")) resp.headers.getString("eth-consensus-version"))
if consensusForkRes.isErr: if consensusForkRes.isErr:
raiseRestDecodingBytesError(cstring(consensusForkRes.error)) raiseRestDecodingBytesError(consensusForkRes.error)
ForkedLightClientOptimisticUpdate.decodeHttpLightClientObject( ForkedLightClientOptimisticUpdate.decodeHttpLightClientObject(
data, resp.contentType, consensusForkRes.get, cfg) data, resp.contentType, consensusForkRes.get, cfg)
of 404: of 404:

View File

@ -370,15 +370,6 @@ type
of ConsensusFork.Deneb: denebBody*: deneb.BeaconBlockBody of ConsensusFork.Deneb: denebBody*: deneb.BeaconBlockBody
of ConsensusFork.Electra: electraBody*: electra.BeaconBlockBody of ConsensusFork.Electra: electraBody*: electra.BeaconBlockBody
ProduceBlockResponseV2* = object
case kind*: ConsensusFork
of ConsensusFork.Phase0: phase0Data*: phase0.BeaconBlock
of ConsensusFork.Altair: altairData*: altair.BeaconBlock
of ConsensusFork.Bellatrix: bellatrixData*: bellatrix.BeaconBlock
of ConsensusFork.Capella: capellaData*: capella.BeaconBlock
of ConsensusFork.Deneb: denebData*: deneb.BlockContents
of ConsensusFork.Electra: electraData*: electra.BlockContents
ProduceBlockResponseV3* = ForkedMaybeBlindedBeaconBlock ProduceBlockResponseV3* = ForkedMaybeBlindedBeaconBlock
VCRuntimeConfig* = Table[string, string] VCRuntimeConfig* = Table[string, string]
@ -1113,27 +1104,3 @@ func toValidatorIndex*(value: RestValidatorIndex): Result[ValidatorIndex,
err(ValidatorIndexError.TooHighValue) err(ValidatorIndexError.TooHighValue)
else: else:
doAssert(false, "ValidatorIndex type size is incorrect") doAssert(false, "ValidatorIndex type size is incorrect")
template withBlck*(x: ProduceBlockResponseV2,
body: untyped): untyped =
case x.kind
of ConsensusFork.Phase0:
const consensusFork {.inject, used.} = ConsensusFork.Phase0
template blck: untyped {.inject.} = x.phase0Data
body
of ConsensusFork.Altair:
const consensusFork {.inject, used.} = ConsensusFork.Altair
template blck: untyped {.inject.} = x.altairData
body
of ConsensusFork.Bellatrix:
const consensusFork {.inject, used.} = ConsensusFork.Bellatrix
template blck: untyped {.inject.} = x.bellatrixData
body
of ConsensusFork.Capella:
const consensusFork {.inject, used.} = ConsensusFork.Capella
template blck: untyped {.inject.} = x.capellaData
body
of ConsensusFork.Deneb:
const consensusFork {.inject, used.} = ConsensusFork.Deneb
template blck: untyped {.inject.} = x.denebData.blck
body

View File

@ -36,15 +36,6 @@ proc getSyncCommitteeDutiesPlain*(
meth: MethodPost.} meth: MethodPost.}
## https://ethereum.github.io/beacon-APIs/#/Validator/getSyncCommitteeDuties ## https://ethereum.github.io/beacon-APIs/#/Validator/getSyncCommitteeDuties
proc produceBlockV2Plain*(
slot: Slot,
randao_reveal: ValidatorSig,
graffiti: GraffitiBytes
): RestPlainResponse {.
rest, endpoint: "/eth/v2/validator/blocks/{slot}",
accept: preferSSZ, meth: MethodGet.}
## https://ethereum.github.io/beacon-APIs/#/Validator/produceBlockV2
proc produceBlockV3Plain*( proc produceBlockV3Plain*(
slot: Slot, slot: Slot,
randao_reveal: ValidatorSig, randao_reveal: ValidatorSig,

View File

@ -291,7 +291,7 @@ template `$`*(x: WalletName): string =
# TODO: `burnMem` in nimcrypto could use distinctBase # TODO: `burnMem` in nimcrypto could use distinctBase
# to make its usage less error-prone. # to make its usage less error-prone.
template burnMem*(m: var (Mnemonic|string)) = template burnMem*(m: var (Mnemonic|string)) =
ncrutils.burnMem(string m) ncrutils.burnMem(distinctBase m)
template burnMem*(m: var KeySeed) = template burnMem*(m: var KeySeed) =
ncrutils.burnMem(distinctBase m) ncrutils.burnMem(distinctBase m)
@ -324,7 +324,7 @@ const
englishWordsDigest = englishWordsDigest =
"AD90BF3BEB7B0EB7E5ACD74727DC0DA96E0A280A258354E7293FB7E211AC03DB".toDigest "AD90BF3BEB7B0EB7E5ACD74727DC0DA96E0A280A258354E7293FB7E211AC03DB".toDigest
proc checkEnglishWords(): bool = func checkEnglishWords(): bool =
if len(englishWords) != wordListLen: if len(englishWords) != wordListLen:
false false
else: else:
@ -341,7 +341,7 @@ func validateKeyPath*(path: string): Result[KeyPath, cstring] =
var digitCount: int var digitCount: int
var number: BiggestUInt var number: BiggestUInt
try: try:
for elem in path.string.split("/"): for elem in path.split("/"):
# TODO: doesn't "m" have to be the first character and is it the only # TODO: doesn't "m" have to be the first character and is it the only
# place where it is valid? # place where it is valid?
if elem == "m": if elem == "m":
@ -382,7 +382,7 @@ func isControlRune(r: Rune): bool =
let r = int r let r = int r
(r >= 0 and r < 0x20) or (r >= 0x7F and r < 0xA0) (r >= 0 and r < 0x20) or (r >= 0x7F and r < 0xA0)
proc init*(T: type KeystorePass, input: string): T = func init*(T: type KeystorePass, input: string): T =
for rune in toNFKD(input): for rune in toNFKD(input):
if not isControlRune(rune): if not isControlRune(rune):
result.str.add rune result.str.add rune
@ -395,7 +395,7 @@ func getSeed*(mnemonic: Mnemonic, password: KeystorePass): KeySeed =
template add(m: var Mnemonic, s: cstring) = template add(m: var Mnemonic, s: cstring) =
m.string.add s m.string.add s
proc generateMnemonic*( func generateMnemonic*(
rng: var HmacDrbgContext, rng: var HmacDrbgContext,
words: openArray[cstring] = englishWords, words: openArray[cstring] = englishWords,
entropyParam: openArray[byte] = @[]): Mnemonic = entropyParam: openArray[byte] = @[]): Mnemonic =
@ -429,12 +429,12 @@ proc generateMnemonic*(
result.add " " result.add " "
result.add words[entropy.getBitsBE(firstBit..lastBit)] result.add words[entropy.getBitsBE(firstBit..lastBit)]
proc cmpIgnoreCase(lhs: cstring, rhs: string): int = func cmpIgnoreCase(lhs: cstring, rhs: string): int =
# TODO: This is a bit silly. # TODO: This is a bit silly.
# Nim should have a `cmp` function for C strings. # Nim should have a `cmp` function for C strings.
cmpIgnoreCase($lhs, rhs) cmpIgnoreCase($lhs, rhs)
proc validateMnemonic*(inputWords: string, func validateMnemonic*(inputWords: string,
outputMnemonic: var Mnemonic): bool = outputMnemonic: var Mnemonic): bool =
## Accept a case-insensitive input string and returns `true` ## Accept a case-insensitive input string and returns `true`
## if it represents a valid mnenomic. The `outputMnemonic` ## if it represents a valid mnenomic. The `outputMnemonic`
@ -465,7 +465,7 @@ proc validateMnemonic*(inputWords: string,
return true return true
proc deriveChildKey*(parentKey: ValidatorPrivKey, func deriveChildKey*(parentKey: ValidatorPrivKey,
index: Natural): ValidatorPrivKey = index: Natural): ValidatorPrivKey =
let success = derive_child_secretKey(SecretKey result, let success = derive_child_secretKey(SecretKey result,
SecretKey parentKey, SecretKey parentKey,
@ -475,7 +475,7 @@ proc deriveChildKey*(parentKey: ValidatorPrivKey,
# into asserts inside the function. # into asserts inside the function.
doAssert success doAssert success
proc deriveMasterKey*(seed: KeySeed): ValidatorPrivKey = func deriveMasterKey*(seed: KeySeed): ValidatorPrivKey =
let success = derive_master_secretKey(SecretKey result, let success = derive_master_secretKey(SecretKey result,
seq[byte] seed) seq[byte] seed)
# TODO `derive_master_secretKey` is reporting pre-condition # TODO `derive_master_secretKey` is reporting pre-condition
@ -483,17 +483,17 @@ proc deriveMasterKey*(seed: KeySeed): ValidatorPrivKey =
# into asserts inside the function. # into asserts inside the function.
doAssert success doAssert success
proc deriveMasterKey*(mnemonic: Mnemonic, func deriveMasterKey*(mnemonic: Mnemonic,
password: KeystorePass): ValidatorPrivKey = password: KeystorePass): ValidatorPrivKey =
deriveMasterKey(getSeed(mnemonic, password)) deriveMasterKey(getSeed(mnemonic, password))
proc deriveChildKey*(masterKey: ValidatorPrivKey, func deriveChildKey*(masterKey: ValidatorPrivKey,
path: KeyPath): ValidatorPrivKey = path: KeyPath): ValidatorPrivKey =
result = masterKey result = masterKey
for idx in pathNodes(path): for idx in pathNodes(path):
result = deriveChildKey(result, idx) result = deriveChildKey(result, idx)
proc deriveChildKey*(masterKey: ValidatorPrivKey, func deriveChildKey*(masterKey: ValidatorPrivKey,
path: openArray[Natural]): ValidatorPrivKey = path: openArray[Natural]): ValidatorPrivKey =
result = masterKey result = masterKey
for idx in path: for idx in path:
@ -503,12 +503,12 @@ proc deriveChildKey*(masterKey: ValidatorPrivKey,
# if we fail we want to scrub secrets from memory # if we fail we want to scrub secrets from memory
result = deriveChildKey(result, idx) result = deriveChildKey(result, idx)
proc keyFromPath*(mnemonic: Mnemonic, func keyFromPath*(mnemonic: Mnemonic,
password: KeystorePass, password: KeystorePass,
path: KeyPath): ValidatorPrivKey = path: KeyPath): ValidatorPrivKey =
deriveChildKey(deriveMasterKey(mnemonic, password), path) deriveChildKey(deriveMasterKey(mnemonic, password), path)
proc shaChecksum(key, cipher: openArray[byte]): Sha256Digest = func shaChecksum(key, cipher: openArray[byte]): Sha256Digest =
var ctx: sha256 var ctx: sha256
ctx.init() ctx.init()
ctx.update(key) ctx.update(key)
@ -681,7 +681,7 @@ proc readValue*(r: var JsonReader[DefaultFlavor], value: var Kdf)
readValueImpl(r, value) readValueImpl(r, value)
{.pop.} {.pop.}
proc readValue*(r: var JsonReader, value: var (Checksum|Cipher|Kdf)) = func readValue*(r: var JsonReader, value: var (Checksum|Cipher|Kdf)) =
static: raiseAssert "Unknown flavor `JsonReader[" & $typeof(r).Flavor & static: raiseAssert "Unknown flavor `JsonReader[" & $typeof(r).Flavor &
"]` for `readValue` of `" & $typeof(value) & "`" "]` for `readValue` of `" & $typeof(value) & "`"
@ -951,7 +951,7 @@ func areValid(params: ScryptParams): bool =
params.p == scryptParams.p and params.p == scryptParams.p and
params.salt.bytes.len > 0 params.salt.bytes.len > 0
proc decryptCryptoField*(crypto: Crypto, decKey: openArray[byte], func decryptCryptoField*(crypto: Crypto, decKey: openArray[byte],
outSecret: var seq[byte]): DecryptionStatus = outSecret: var seq[byte]): DecryptionStatus =
if crypto.cipher.message.bytes.len == 0: if crypto.cipher.message.bytes.len == 0:
return DecryptionStatus.InvalidKeystore return DecryptionStatus.InvalidKeystore
@ -977,7 +977,7 @@ proc decryptCryptoField*(crypto: Crypto, decKey: openArray[byte],
aesCipher.clear() aesCipher.clear()
DecryptionStatus.Success DecryptionStatus.Success
proc getDecryptionKey*(crypto: Crypto, password: KeystorePass, func getDecryptionKey*(crypto: Crypto, password: KeystorePass,
decKey: var seq[byte]): DecryptionStatus = decKey: var seq[byte]): DecryptionStatus =
let res = let res =
case crypto.kdf.function case crypto.kdf.function
@ -996,7 +996,7 @@ proc getDecryptionKey*(crypto: Crypto, password: KeystorePass,
decKey = res decKey = res
DecryptionStatus.Success DecryptionStatus.Success
proc decryptCryptoField*(crypto: Crypto, func decryptCryptoField*(crypto: Crypto,
password: KeystorePass, password: KeystorePass,
outSecret: var seq[byte]): DecryptionStatus = outSecret: var seq[byte]): DecryptionStatus =
# https://github.com/ethereum/wiki/wiki/Web3-Secret-Storage-Definition # https://github.com/ethereum/wiki/wiki/Web3-Secret-Storage-Definition
@ -1027,7 +1027,7 @@ template parseRemoteKeystore*(jsonContent: string): RemoteKeystore =
requireAllFields = false, requireAllFields = false,
allowUnknownFields = true) allowUnknownFields = true)
proc getSaltKey(keystore: Keystore, password: KeystorePass): KdfSaltKey = func getSaltKey(keystore: Keystore, password: KeystorePass): KdfSaltKey =
let digest = let digest =
case keystore.crypto.kdf.function case keystore.crypto.kdf.function
of kdfPbkdf2: of kdfPbkdf2:
@ -1050,8 +1050,8 @@ proc getSaltKey(keystore: Keystore, password: KeystorePass): KdfSaltKey =
h.update(toBytesLE(uint64(params.r))) h.update(toBytesLE(uint64(params.r)))
KdfSaltKey(digest.data) KdfSaltKey(digest.data)
proc `==`*(a, b: KdfSaltKey): bool {.borrow.} func `==`*(a, b: KdfSaltKey): bool {.borrow.}
proc hash*(salt: KdfSaltKey): Hash {.borrow.} func hash*(salt: KdfSaltKey): Hash {.borrow.}
{.push warning[ProveField]:off.} {.push warning[ProveField]:off.}
func `==`*(a, b: Kdf): bool = func `==`*(a, b: Kdf): bool =
@ -1089,7 +1089,7 @@ func init*(t: typedesc[KeystoreCacheRef],
expireTime: expireTime expireTime: expireTime
) )
proc clear*(cache: KeystoreCacheRef) = func clear*(cache: KeystoreCacheRef) =
cache.table.clear() cache.table.clear()
proc pruneExpiredKeys*(cache: KeystoreCacheRef) = proc pruneExpiredKeys*(cache: KeystoreCacheRef) =
@ -1110,7 +1110,7 @@ proc init*(t: typedesc[KeystoreCacheItem], keystore: Keystore,
cipher: keystore.crypto.cipher, decryptionKey: @key, cipher: keystore.crypto.cipher, decryptionKey: @key,
timestamp: Moment.now()) timestamp: Moment.now())
proc getCachedKey*(cache: KeystoreCacheRef, func getCachedKey*(cache: KeystoreCacheRef,
keystore: Keystore, password: KeystorePass): Opt[seq[byte]] = keystore: Keystore, password: KeystorePass): Opt[seq[byte]] =
if isNil(cache): return Opt.none(seq[byte]) if isNil(cache): return Opt.none(seq[byte])
let let
@ -1132,7 +1132,7 @@ proc setCachedKey*(cache: KeystoreCacheRef, keystore: Keystore,
let saltKey = keystore.getSaltKey(password) let saltKey = keystore.getSaltKey(password)
cache.table[saltKey] = KeystoreCacheItem.init(keystore, key) cache.table[saltKey] = KeystoreCacheItem.init(keystore, key)
proc destroyCacheKey*(cache: KeystoreCacheRef, func destroyCacheKey*(cache: KeystoreCacheRef,
keystore: Keystore, password: KeystorePass) = keystore: Keystore, password: KeystorePass) =
if isNil(cache): return if isNil(cache): return
let saltKey = keystore.getSaltKey(password) let saltKey = keystore.getSaltKey(password)
@ -1206,7 +1206,7 @@ proc readValue*(reader: var JsonReader, value: var lcrypto.PublicKey) {.
# TODO: Can we provide better diagnostic? # TODO: Can we provide better diagnostic?
raiseUnexpectedValue(reader, "Valid hex-encoded public key expected") raiseUnexpectedValue(reader, "Valid hex-encoded public key expected")
proc decryptNetKeystore*(nkeystore: NetKeystore, func decryptNetKeystore*(nkeystore: NetKeystore,
password: KeystorePass): KsResult[lcrypto.PrivateKey] = password: KeystorePass): KsResult[lcrypto.PrivateKey] =
var secret: seq[byte] var secret: seq[byte]
defer: burnMem(secret) defer: burnMem(secret)
@ -1221,7 +1221,7 @@ proc decryptNetKeystore*(nkeystore: NetKeystore,
else: else:
err $status err $status
proc decryptNetKeystore*(nkeystore: JsonString, func decryptNetKeystore*(nkeystore: JsonString,
password: KeystorePass): KsResult[lcrypto.PrivateKey] = password: KeystorePass): KsResult[lcrypto.PrivateKey] =
try: try:
let keystore = parseNetKeystore(string nkeystore) let keystore = parseNetKeystore(string nkeystore)
@ -1229,10 +1229,10 @@ proc decryptNetKeystore*(nkeystore: JsonString,
except SerializationError as exc: except SerializationError as exc:
return err(exc.formatMsg("<keystore>")) return err(exc.formatMsg("<keystore>"))
proc generateKeystoreSalt*(rng: var HmacDrbgContext): seq[byte] = func generateKeystoreSalt*(rng: var HmacDrbgContext): seq[byte] =
rng.generateBytes(keyLen) rng.generateBytes(keyLen)
proc createCryptoField(kdfKind: KdfKind, func createCryptoField(kdfKind: KdfKind,
rng: var HmacDrbgContext, rng: var HmacDrbgContext,
secret: openArray[byte], secret: openArray[byte],
password = KeystorePass.init "", password = KeystorePass.init "",
@ -1339,7 +1339,7 @@ proc createKeystore*(kdfKind: KdfKind,
uuid: $uuid, uuid: $uuid,
version: 4) version: 4)
proc createRemoteKeystore*(pubKey: ValidatorPubKey, remoteUri: HttpHostUri, func createRemoteKeystore*(pubKey: ValidatorPubKey, remoteUri: HttpHostUri,
version = 1'u64, description = "", version = 1'u64, description = "",
remoteType = RemoteSignerType.Web3Signer, remoteType = RemoteSignerType.Web3Signer,
flags: set[RemoteKeystoreFlag] = {}): RemoteKeystore = flags: set[RemoteKeystoreFlag] = {}): RemoteKeystore =
@ -1387,10 +1387,10 @@ func makeWithdrawalCredentials*(k: ValidatorPubKey): Eth2Digest =
bytes bytes
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.2/specs/phase0/deposit-contract.md#withdrawal-credentials # https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.2/specs/phase0/deposit-contract.md#withdrawal-credentials
proc makeWithdrawalCredentials*(k: CookedPubKey): Eth2Digest = func makeWithdrawalCredentials*(k: CookedPubKey): Eth2Digest =
makeWithdrawalCredentials(k.toPubKey()) makeWithdrawalCredentials(k.toPubKey())
proc prepareDeposit*(cfg: RuntimeConfig, func prepareDeposit*(cfg: RuntimeConfig,
withdrawalPubKey: CookedPubKey, withdrawalPubKey: CookedPubKey,
signingKey: ValidatorPrivKey, signingPubKey: CookedPubKey, signingKey: ValidatorPrivKey, signingPubKey: CookedPubKey,
amount = MAX_EFFECTIVE_BALANCE.Gwei): DepositData = amount = MAX_EFFECTIVE_BALANCE.Gwei): DepositData =

View File

@ -507,43 +507,86 @@ proc process_bls_to_execution_change*(
ok() ok()
# https://github.com/ethereum/consensus-specs/blob/94a0b6c581f2809aa8aca4ef7ee6fbb63f9d74e9/specs/electra/beacon-chain.md#new-process_execution_layer_exit # https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.2/specs/electra/beacon-chain.md#new-process_execution_layer_withdrawal_request
func process_execution_layer_withdrawal_request( func process_execution_layer_withdrawal_request*(
cfg: RuntimeConfig, state: var electra.BeaconState, cfg: RuntimeConfig, state: var electra.BeaconState,
execution_layer_withdrawal_request: ExecutionLayerWithdrawalRequest, execution_layer_withdrawal_request: ExecutionLayerWithdrawalRequest,
exit_queue_info: ExitQueueInfo, cache: var StateCache): cache: var StateCache) =
Result[ExitQueueInfo, cstring] =
# Verify pubkey exists
let let
pubkey_to_exit = execution_layer_withdrawal_request.validator_pubkey amount = execution_layer_withdrawal_request.amount
validator_index = findValidatorIndex(state, pubkey_to_exit).valueOr: is_full_exit_request = amount == static(FULL_EXIT_REQUEST_AMOUNT.Gwei)
return err("process_execution_layer_withdrawal_request: unknown index for validator pubkey")
validator = state.validators.item(validator_index) # If partial withdrawal queue is full, only full exits are processed
if lenu64(state.pending_partial_withdrawals) ==
PENDING_PARTIAL_WITHDRAWALS_LIMIT and not is_full_exit_request:
return
let
request_pubkey = execution_layer_withdrawal_request.validator_pubkey
index = findValidatorIndex(state, request_pubkey).valueOr:
return
validator = state.validators.item(index)
# Verify withdrawal credentials # Verify withdrawal credentials
let let
is_execution_address = validator.has_eth1_withdrawal_credential has_correct_credential = has_execution_withdrawal_credential(validator)
is_correct_source_address = is_correct_source_address =
validator.withdrawal_credentials.data.toOpenArray(12, 31) == validator.withdrawal_credentials.data.toOpenArray(12, 31) ==
execution_layer_withdrawal_request.source_address.data execution_layer_withdrawal_request.source_address.data
if not (is_execution_address and is_correct_source_address):
return err("process_execution_layer_withdrawal_request: not both execution address and correct source address") if not (has_correct_credential and is_correct_source_address):
return
# Verify the validator is active # Verify the validator is active
if not is_active_validator(validator, get_current_epoch(state)): if not is_active_validator(validator, get_current_epoch(state)):
return err("process_execution_layer_withdrawal_request: not active validator") return
# Verify exit has not been initiated # Verify exit has not been initiated
if validator.exit_epoch != FAR_FUTURE_EPOCH: if validator.exit_epoch != FAR_FUTURE_EPOCH:
return err("process_execution_layer_withdrawal_request: validator exit already initiated") return
# Verify the validator has been active long enough # Verify the validator has been active long enough
if get_current_epoch(state) < validator.activation_epoch + cfg.SHARD_COMMITTEE_PERIOD: if get_current_epoch(state) <
return err("process_execution_layer_withdrawal_request: validator not active long enough") validator.activation_epoch + cfg.SHARD_COMMITTEE_PERIOD:
return
# Initiate exit let pending_balance_to_withdraw =
ok(? initiate_validator_exit( get_pending_balance_to_withdraw(state, index)
cfg, state, validator_index, exit_queue_info, cache))
if is_full_exit_request:
# Only exit validator if it has no pending withdrawals in the queue
if pending_balance_to_withdraw == 0.Gwei:
if initiate_validator_exit(cfg, state, index, default(ExitQueueInfo),
cache).isErr():
return
return
let
has_sufficient_effective_balance =
validator.effective_balance >= static(MIN_ACTIVATION_BALANCE.Gwei)
has_excess_balance = state.balances.item(index) >
static(MIN_ACTIVATION_BALANCE.Gwei) + pending_balance_to_withdraw
# Only allow partial withdrawals with compounding withdrawal credentials
if has_compounding_withdrawal_credential(validator) and
has_sufficient_effective_balance and has_excess_balance:
let
to_withdraw = min(
state.balances.item(index) - static(MIN_ACTIVATION_BALANCE.Gwei) -
pending_balance_to_withdraw,
amount
)
exit_queue_epoch =
compute_exit_epoch_and_update_churn(cfg, state, to_withdraw, cache)
withdrawable_epoch =
exit_queue_epoch + cfg.MIN_VALIDATOR_WITHDRAWABILITY_DELAY
# In theory can fail, but failing/early returning here is indistinguishable
discard state.pending_partial_withdrawals.add(PendingPartialWithdrawal(
index: index.uint64,
amount: to_withdraw,
withdrawable_epoch: withdrawable_epoch,
))
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.0/specs/electra/beacon-chain.md#consolidations # https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.0/specs/electra/beacon-chain.md#consolidations
proc process_consolidation*( proc process_consolidation*(
@ -703,8 +746,8 @@ proc process_operations(
# [New in Electra:EIP7002:EIP7251] # [New in Electra:EIP7002:EIP7251]
when typeof(body).kind >= ConsensusFork.Electra: when typeof(body).kind >= ConsensusFork.Electra:
for op in body.execution_payload.withdrawal_requests: for op in body.execution_payload.withdrawal_requests:
discard ? process_execution_layer_withdrawal_request( process_execution_layer_withdrawal_request(
cfg, state, op, default(ExitQueueInfo), cache) cfg, state, op, cache)
for op in body.execution_payload.deposit_receipts: for op in body.execution_payload.deposit_receipts:
debugComment "combine with previous bloom filter construction" debugComment "combine with previous bloom filter construction"
let bloom_filter = constructBloomFilter(state.validators.asSeq) let bloom_filter = constructBloomFilter(state.validators.asSeq)
@ -1035,87 +1078,6 @@ func process_withdrawals*(
ok() ok()
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.0/specs/electra/beacon-chain.md#new-process_execution_layer_withdrawal_request
func process_execution_layer_withdrawal_request*(
cfg: RuntimeConfig, state: var electra.BeaconState,
execution_layer_withdrawal_request: ExecutionLayerWithdrawalRequest,
cache: var StateCache) =
let
amount = execution_layer_withdrawal_request.amount
is_full_exit_request = amount == static(FULL_EXIT_REQUEST_AMOUNT.Gwei)
# If partial withdrawal queue is full, only full exits are processed
if lenu64(state.pending_partial_withdrawals) ==
PENDING_PARTIAL_WITHDRAWALS_LIMIT and not is_full_exit_request:
return
let
request_pubkey = execution_layer_withdrawal_request.validator_pubkey
index = findValidatorIndex(state, request_pubkey).valueOr:
return
validator = state.validators.item(index)
# Verify withdrawal credentials
let
has_correct_credential = has_execution_withdrawal_credential(validator)
is_correct_source_address =
validator.withdrawal_credentials.data.toOpenArray(12, 31) ==
execution_layer_withdrawal_request.source_address.data
if not (has_correct_credential and is_correct_source_address):
return
# Verify the validator is active
if not is_active_validator(validator, get_current_epoch(state)):
return
# Verify exit has not been initiated
if validator.exit_epoch != FAR_FUTURE_EPOCH:
return
# Verify the validator has been active long enough
if get_current_epoch(state) <
validator.activation_epoch + cfg.SHARD_COMMITTEE_PERIOD:
return
let pending_balance_to_withdraw =
get_pending_balance_to_withdraw(state, index)
if is_full_exit_request:
# Only exit validator if it has no pending withdrawals in the queue
if pending_balance_to_withdraw == 0.Gwei:
if initiate_validator_exit(cfg, state, index, default(ExitQueueInfo),
cache).isErr():
return
return
let
has_sufficient_effective_balance =
validator.effective_balance >= static(MIN_ACTIVATION_BALANCE.Gwei)
has_excess_balance = state.balances.item(index) >
static(MIN_ACTIVATION_BALANCE.Gwei) + pending_balance_to_withdraw
# Only allow partial withdrawals with compounding withdrawal credentials
if has_compounding_withdrawal_credential(validator) and
has_sufficient_effective_balance and has_excess_balance:
let
to_withdraw = min(
state.balances.item(index) - static(MIN_ACTIVATION_BALANCE.Gwei) -
pending_balance_to_withdraw,
amount
)
exit_queue_epoch =
compute_exit_epoch_and_update_churn(cfg, state, to_withdraw, cache)
withdrawable_epoch =
Epoch(exit_queue_epoch + cfg.MIN_VALIDATOR_WITHDRAWABILITY_DELAY)
# In theory can fail, but failing/early returning here is indistinguishable
discard state.pending_partial_withdrawals.add(PendingPartialWithdrawal(
index: index.uint64,
amount: to_withdraw,
withdrawable_epoch: withdrawable_epoch,
))
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/deneb/beacon-chain.md#kzg_commitment_to_versioned_hash # https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/deneb/beacon-chain.md#kzg_commitment_to_versioned_hash
func kzg_commitment_to_versioned_hash*( func kzg_commitment_to_versioned_hash*(
kzg_commitment: KzgCommitment): VersionedHash = kzg_commitment: KzgCommitment): VersionedHash =

View File

@ -1221,7 +1221,7 @@ func process_historical_summaries_update*(
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.0/specs/electra/beacon-chain.md#new-process_pending_balance_deposits # https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.0/specs/electra/beacon-chain.md#new-process_pending_balance_deposits
func process_pending_balance_deposits*( func process_pending_balance_deposits*(
cfg: RuntimeConfig, state: var electra.BeaconState, cfg: RuntimeConfig, state: var electra.BeaconState,
cache: var StateCache) = cache: var StateCache): Result[void, cstring] =
let let
available_for_processing = state.deposit_balance_to_consume + available_for_processing = state.deposit_balance_to_consume +
get_activation_exit_churn_limit(cfg, state, cache) get_activation_exit_churn_limit(cfg, state, cache)
@ -1232,8 +1232,9 @@ func process_pending_balance_deposits*(
for deposit in state.pending_balance_deposits: for deposit in state.pending_balance_deposits:
if processed_amount + deposit.amount > available_for_processing: if processed_amount + deposit.amount > available_for_processing:
break break
debugComment "do this validatorindex check properly (it truncates)" let deposit_validator_index = ValidatorIndex.init(deposit.index).valueOr:
increase_balance(state, deposit.index.ValidatorIndex, deposit.amount) return err("process_pending_balance_deposits: deposit index out of range")
increase_balance(state, deposit_validator_index, deposit.amount)
processed_amount += deposit.amount processed_amount += deposit.amount
inc next_deposit_index inc next_deposit_index
@ -1247,8 +1248,12 @@ func process_pending_balance_deposits*(
state.deposit_balance_to_consume = state.deposit_balance_to_consume =
available_for_processing - processed_amount available_for_processing - processed_amount
ok()
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.0/specs/electra/beacon-chain.md#new-process_pending_consolidations # https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.0/specs/electra/beacon-chain.md#new-process_pending_consolidations
func process_pending_consolidations*(cfg: RuntimeConfig, state: var electra.BeaconState) = func process_pending_consolidations*(
cfg: RuntimeConfig, state: var electra.BeaconState):
Result[void, cstring] =
var next_pending_consolidation = 0 var next_pending_consolidation = 0
for pending_consolidation in state.pending_consolidations: for pending_consolidation in state.pending_consolidations:
let source_validator = let source_validator =
@ -1259,25 +1264,29 @@ func process_pending_consolidations*(cfg: RuntimeConfig, state: var electra.Beac
if source_validator.withdrawable_epoch > get_current_epoch(state): if source_validator.withdrawable_epoch > get_current_epoch(state):
break break
let
source_validator_index = ValidatorIndex.init(
pending_consolidation.source_index).valueOr:
return err("process_pending_consolidations: source index out of range")
target_validator_index = ValidatorIndex.init(
pending_consolidation.target_index).valueOr:
return err("process_pending_consolidations: target index out of range")
# Churn any target excess active balance of target and raise its max # Churn any target excess active balance of target and raise its max
debugComment "truncating integer conversion" switch_to_compounding_validator(state, target_validator_index)
switch_to_compounding_validator(
state, pending_consolidation.target_index.ValidatorIndex)
# Move active balance to target. Excess balance is withdrawable. # Move active balance to target. Excess balance is withdrawable.
debugComment "Truncating" let active_balance = get_active_balance(state, source_validator_index)
let active_balance = get_active_balance( decrease_balance(state, source_validator_index, active_balance)
state, pending_consolidation.source_index.ValidatorIndex) increase_balance(state, target_validator_index, active_balance)
decrease_balance(
state, pending_consolidation.source_index.ValidatorIndex, active_balance)
increase_balance(
state, pending_consolidation.target_index.ValidatorIndex, active_balance)
inc next_pending_consolidation inc next_pending_consolidation
state.pending_consolidations = state.pending_consolidations =
HashList[PendingConsolidation, Limit PENDING_CONSOLIDATIONS_LIMIT].init( HashList[PendingConsolidation, Limit PENDING_CONSOLIDATIONS_LIMIT].init(
state.pending_consolidations.asSeq[next_pending_consolidation..^1]) state.pending_consolidations.asSeq[next_pending_consolidation..^1])
ok()
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/phase0/beacon-chain.md#epoch-processing # https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/phase0/beacon-chain.md#epoch-processing
proc process_epoch*( proc process_epoch*(
cfg: RuntimeConfig, state: var phase0.BeaconState, flags: UpdateFlags, cfg: RuntimeConfig, state: var phase0.BeaconState, flags: UpdateFlags,
@ -1464,8 +1473,8 @@ proc process_epoch*(
process_slashings(state, info.balances.current_epoch) process_slashings(state, info.balances.current_epoch)
process_eth1_data_reset(state) process_eth1_data_reset(state)
process_pending_balance_deposits(cfg, state, cache) # [New in Electra:EIP7251] ? process_pending_balance_deposits(cfg, state, cache) # [New in Electra:EIP7251]
process_pending_consolidations(cfg, state) # [New in Electra:EIP7251] ? process_pending_consolidations(cfg, state) # [New in Electra:EIP7251]
process_effective_balance_updates(state) # [Modified in Electra:EIP7251] process_effective_balance_updates(state) # [Modified in Electra:EIP7251]
process_slashings_reset(state) process_slashings_reset(state)
process_randao_mixes_reset(state) process_randao_mixes_reset(state)

View File

@ -110,7 +110,7 @@ proc initQueue[A, B](man: SyncManager[A, B]) =
# there is present check `needsBackfill(). # there is present check `needsBackfill().
firstSlot firstSlot
else: else:
Slot(firstSlot - 1'u64) firstSlot - 1'u64
man.queue = SyncQueue.init(A, man.direction, startSlot, lastSlot, man.queue = SyncQueue.init(A, man.direction, startSlot, lastSlot,
man.chunkSize, man.getSafeSlot, man.chunkSize, man.getSafeSlot,
man.blockVerifier, 1, man.ident) man.blockVerifier, 1, man.ident)

View File

@ -2022,97 +2022,6 @@ proc publishContributionAndProofs*(
raise (ref ValidatorApiError)( raise (ref ValidatorApiError)(
msg: "Failed to publish sync committee contribution", data: failures) msg: "Failed to publish sync committee contribution", data: failures)
proc produceBlockV2*(
vc: ValidatorClientRef,
slot: Slot,
randao_reveal: ValidatorSig,
graffiti: GraffitiBytes,
strategy: ApiStrategyKind
): Future[ProduceBlockResponseV2] {.async.} =
const
RequestName = "produceBlockV2"
var failures: seq[ApiNodeFailure]
case strategy
of ApiStrategyKind.First, ApiStrategyKind.Best:
let res = vc.firstSuccessParallel(
RestPlainResponse,
ProduceBlockResponseV2,
SlotDuration,
ViableNodeStatus,
{BeaconNodeRole.BlockProposalData},
produceBlockV2Plain(it, slot, randao_reveal, graffiti)):
if apiResponse.isErr():
handleCommunicationError()
ApiResponse[ProduceBlockResponseV2].err(apiResponse.error)
else:
let response = apiResponse.get()
case response.status:
of 200:
let
version = response.headers.getString("eth-consensus-version")
res = decodeBytes(ProduceBlockResponseV2, response.data,
response.contentType, version)
if res.isErr():
handleUnexpectedData()
ApiResponse[ProduceBlockResponseV2].err($res.error)
else:
ApiResponse[ProduceBlockResponseV2].ok(res.get())
of 400:
handle400()
ApiResponse[ProduceBlockResponseV2].err(ResponseInvalidError)
of 500:
handle500()
ApiResponse[ProduceBlockResponseV2].err(ResponseInternalError)
of 503:
handle503()
ApiResponse[ProduceBlockResponseV2].err(ResponseNoSyncError)
else:
handleUnexpectedCode()
ApiResponse[ProduceBlockResponseV2].err(ResponseUnexpectedError)
if res.isErr():
raise (ref ValidatorApiError)(msg: res.error, data: failures)
return res.get()
of ApiStrategyKind.Priority:
vc.firstSuccessSequential(
RestPlainResponse,
SlotDuration,
ViableNodeStatus,
{BeaconNodeRole.BlockProposalData},
produceBlockV2Plain(it, slot, randao_reveal, graffiti)):
if apiResponse.isErr():
handleCommunicationError()
false
else:
let response = apiResponse.get()
case response.status:
of 200:
let
version = response.headers.getString("eth-consensus-version")
res = decodeBytes(ProduceBlockResponseV2, response.data,
response.contentType, version)
if res.isOk(): return res.get()
handleUnexpectedData()
false
of 400:
handle400()
false
of 500:
handle500()
false
of 503:
handle503()
false
else:
handleUnexpectedCode()
false
raise (ref ValidatorApiError)(
msg: "Failed to produce block", data: failures)
proc produceBlockV3*( proc produceBlockV3*(
vc: ValidatorClientRef, vc: ValidatorClientRef,
slot: Slot, slot: Slot,
@ -2161,24 +2070,15 @@ proc produceBlockV3*(
ApiResponse[ProduceBlockResponseV3].ok(res.get()) ApiResponse[ProduceBlockResponseV3].ok(res.get())
of 400: of 400:
handle400() handle400()
node.features.incl(RestBeaconNodeFeature.NoProduceBlockV3)
ApiResponse[ProduceBlockResponseV3].err(ResponseInvalidError)
of 404:
# TODO (cheatfate): Remove this handler when produceBlockV2 support
# will be dropped.
handle400()
node.features.incl(RestBeaconNodeFeature.NoProduceBlockV3)
ApiResponse[ProduceBlockResponseV3].err(ResponseInvalidError) ApiResponse[ProduceBlockResponseV3].err(ResponseInvalidError)
of 500: of 500:
handle500() handle500()
node.features.incl(RestBeaconNodeFeature.NoProduceBlockV3)
ApiResponse[ProduceBlockResponseV3].err(ResponseInternalError) ApiResponse[ProduceBlockResponseV3].err(ResponseInternalError)
of 503: of 503:
handle503() handle503()
ApiResponse[ProduceBlockResponseV3].err(ResponseNoSyncError) ApiResponse[ProduceBlockResponseV3].err(ResponseNoSyncError)
else: else:
handleUnexpectedCode() handleUnexpectedCode()
node.features.incl(RestBeaconNodeFeature.NoProduceBlockV3)
ApiResponse[ProduceBlockResponseV3].err(ResponseUnexpectedError) ApiResponse[ProduceBlockResponseV3].err(ResponseUnexpectedError)
if res.isErr(): if res.isErr():
@ -2216,24 +2116,15 @@ proc produceBlockV3*(
false false
of 400: of 400:
handle400() handle400()
node.features.incl(RestBeaconNodeFeature.NoProduceBlockV3)
false
of 404:
# TODO (cheatfate): Remove this handler when produceBlockV2 support
# will be dropped.
handle400()
node.features.incl(RestBeaconNodeFeature.NoProduceBlockV3)
false false
of 500: of 500:
handle500() handle500()
node.features.incl(RestBeaconNodeFeature.NoProduceBlockV3)
false false
of 503: of 503:
handle503() handle503()
false false
else: else:
handleUnexpectedCode() handleUnexpectedCode()
node.features.incl(RestBeaconNodeFeature.NoProduceBlockV3)
false false
raise (ref ValidatorApiError)( raise (ref ValidatorApiError)(

View File

@ -49,114 +49,6 @@ func shortLog(v: ForkedMaybeBlindedBeaconBlock): auto =
proc proposeBlock(vc: ValidatorClientRef, slot: Slot, proc proposeBlock(vc: ValidatorClientRef, slot: Slot,
proposerKey: ValidatorPubKey) {.async.} proposerKey: ValidatorPubKey) {.async.}
proc produceBlock(
vc: ValidatorClientRef,
currentSlot, slot: Slot,
randao_reveal: ValidatorSig,
graffiti: GraffitiBytes,
validator: AttachedValidator
): Future[Opt[PreparedBeaconBlock]] {.async.} =
logScope:
slot = slot
wall_slot = currentSlot
validator = validatorLog(validator)
let
produceBlockResponse =
try:
await vc.produceBlockV2(slot, randao_reveal, graffiti,
ApiStrategyKind.Best)
except ValidatorApiError as exc:
warn "Unable to retrieve block data", reason = exc.getFailureReason()
return Opt.none(PreparedBeaconBlock)
except CancelledError as exc:
debug "Block data production has been interrupted"
raise exc
except CatchableError as exc:
error "An unexpected error occurred while getting block data",
error_name = exc.name, error_msg = exc.msg
return Opt.none(PreparedBeaconBlock)
case produceBlockResponse.kind
of ConsensusFork.Phase0:
let blck = produceBlockResponse.phase0Data
return Opt.some(PreparedBeaconBlock(blockRoot: hash_tree_root(blck),
data: ForkedBeaconBlock.init(blck),
kzgProofsOpt: Opt.none(deneb.KzgProofs),
blobsOpt: Opt.none(deneb.Blobs)))
of ConsensusFork.Altair:
let blck = produceBlockResponse.altairData
return Opt.some(PreparedBeaconBlock(blockRoot: hash_tree_root(blck),
data: ForkedBeaconBlock.init(blck),
kzgProofsOpt: Opt.none(deneb.KzgProofs),
blobsOpt: Opt.none(deneb.Blobs)))
of ConsensusFork.Bellatrix:
let blck = produceBlockResponse.bellatrixData
return Opt.some(PreparedBeaconBlock(blockRoot: hash_tree_root(blck),
data: ForkedBeaconBlock.init(blck),
kzgProofsOpt: Opt.none(deneb.KzgProofs),
blobsOpt: Opt.none(deneb.Blobs)))
of ConsensusFork.Capella:
let blck = produceBlockResponse.capellaData
return Opt.some(PreparedBeaconBlock(blockRoot: hash_tree_root(blck),
data: ForkedBeaconBlock.init(blck),
kzgProofsOpt: Opt.none(deneb.KzgProofs),
blobsOpt: Opt.none(deneb.Blobs)))
of ConsensusFork.Deneb:
let
blck = produceBlockResponse.denebData.`block`
kzgProofs = produceBlockResponse.denebData.kzg_proofs
blobs = produceBlockResponse.denebData.blobs
return Opt.some(PreparedBeaconBlock(blockRoot: hash_tree_root(blck),
data: ForkedBeaconBlock.init(blck),
kzgProofsOpt: Opt.some(kzgProofs),
blobsOpt: Opt.some(blobs)))
of ConsensusFork.Electra:
let
blck = produceBlockResponse.electraData.`block`
kzgProofs = produceBlockResponse.electraData.kzg_proofs
blobs = produceBlockResponse.electraData.blobs
return Opt.some(PreparedBeaconBlock(blockRoot: hash_tree_root(blck),
data: ForkedBeaconBlock.init(blck),
kzgProofsOpt: Opt.some(kzgProofs),
blobsOpt: Opt.some(blobs)))
proc produceBlindedBlock(
vc: ValidatorClientRef,
currentSlot, slot: Slot,
randao_reveal: ValidatorSig,
graffiti: GraffitiBytes,
validator: AttachedValidator
): Future[Opt[PreparedBlindedBeaconBlock]] {.async.} =
logScope:
slot = slot
wall_slot = currentSlot
validator = validatorLog(validator)
let
beaconBlock =
try:
await vc.produceBlindedBlock(slot, randao_reveal, graffiti,
ApiStrategyKind.Best)
except ValidatorApiError as exc:
warn "Unable to retrieve blinded block data", error_msg = exc.msg,
reason = exc.getFailureReason()
return Opt.none(PreparedBlindedBeaconBlock)
except CancelledError as exc:
debug "Blinded block data production has been interrupted"
raise exc
except CatchableError as exc:
error "An unexpected error occurred while getting blinded block data",
error_name = exc.name, error_msg = exc.msg
return Opt.none(PreparedBlindedBeaconBlock)
blockRoot = withBlck(beaconBlock): hash_tree_root(forkyBlck)
return Opt.some(
PreparedBlindedBeaconBlock(blockRoot: blockRoot, data: beaconBlock))
proc lazyWait[T](fut: Future[T]) {.async.} =
try:
discard await fut
except CatchableError:
discard
proc prepareRandao(vc: ValidatorClientRef, slot: Slot, proc prepareRandao(vc: ValidatorClientRef, slot: Slot,
proposerKey: ValidatorPubKey) {.async.} = proposerKey: ValidatorPubKey) {.async.} =
if slot == GENESIS_SLOT: if slot == GENESIS_SLOT:
@ -209,21 +101,9 @@ proc spawnProposalTask(vc: ValidatorClientRef,
duty: duty duty: duty
) )
proc isProduceBlockV3Supported(vc: ValidatorClientRef): bool =
let
# Both `statuses` and `roles` should be set to values which are used in
# api.produceBlockV3() call.
statuses = ViableNodeStatus
roles = {BeaconNodeRole.BlockProposalData}
for node in vc.filterNodes(statuses, roles):
if RestBeaconNodeFeature.NoProduceBlockV3 notin node.features:
return true
false
proc publishBlockV3(vc: ValidatorClientRef, currentSlot, slot: Slot, proc publishBlockV3(vc: ValidatorClientRef, currentSlot, slot: Slot,
fork: Fork, randaoReveal: ValidatorSig, fork: Fork, randaoReveal: ValidatorSig,
validator: AttachedValidator): Future[bool] {.async.} = validator: AttachedValidator) {.async.} =
let let
genesisRoot = vc.beaconGenesis.genesis_validators_root genesisRoot = vc.beaconGenesis.genesis_validators_root
graffiti = graffiti =
@ -247,14 +127,14 @@ proc publishBlockV3(vc: ValidatorClientRef, currentSlot, slot: Slot,
ApiStrategyKind.Best) ApiStrategyKind.Best)
except ValidatorApiError as exc: except ValidatorApiError as exc:
warn "Unable to retrieve block data", reason = exc.getFailureReason() warn "Unable to retrieve block data", reason = exc.getFailureReason()
return false return
except CancelledError as exc: except CancelledError as exc:
debug "Block data production has been interrupted" debug "Block data production has been interrupted"
raise exc raise exc
except CatchableError as exc: except CatchableError as exc:
error "An unexpected error occurred while getting block data", error "An unexpected error occurred while getting block data",
error_name = exc.name, error_msg = exc.msg error_name = exc.name, error_msg = exc.msg
return false return
withForkyMaybeBlindedBlck(maybeBlock): withForkyMaybeBlindedBlck(maybeBlock):
when isBlinded: when isBlinded:
@ -282,7 +162,7 @@ proc publishBlockV3(vc: ValidatorClientRef, currentSlot, slot: Slot,
if notSlashable.isErr(): if notSlashable.isErr():
warn "Slashing protection activated for blinded block proposal" warn "Slashing protection activated for blinded block proposal"
return false return
let signature = let signature =
try: try:
@ -292,7 +172,7 @@ proc publishBlockV3(vc: ValidatorClientRef, currentSlot, slot: Slot,
if res.isErr(): if res.isErr():
warn "Unable to sign blinded block proposal using remote signer", warn "Unable to sign blinded block proposal using remote signer",
reason = res.error() reason = res.error()
return false return
res.get() res.get()
except CancelledError as exc: except CancelledError as exc:
debug "Blinded block signature process has been interrupted" debug "Blinded block signature process has been interrupted"
@ -300,7 +180,7 @@ proc publishBlockV3(vc: ValidatorClientRef, currentSlot, slot: Slot,
except CatchableError as exc: except CatchableError as exc:
error "An unexpected error occurred while signing blinded block", error "An unexpected error occurred while signing blinded block",
error_name = exc.name, error_msg = exc.msg error_name = exc.name, error_msg = exc.msg
return false return
let let
signedBlock = signedBlock =
@ -313,7 +193,7 @@ proc publishBlockV3(vc: ValidatorClientRef, currentSlot, slot: Slot,
except ValidatorApiError as exc: except ValidatorApiError as exc:
warn "Unable to publish blinded block", warn "Unable to publish blinded block",
reason = exc.getFailureReason() reason = exc.getFailureReason()
return false return
except CancelledError as exc: except CancelledError as exc:
debug "Blinded block publication has been interrupted" debug "Blinded block publication has been interrupted"
raise exc raise exc
@ -321,17 +201,15 @@ proc publishBlockV3(vc: ValidatorClientRef, currentSlot, slot: Slot,
error "An unexpected error occurred while publishing blinded " & error "An unexpected error occurred while publishing blinded " &
"block", "block",
error_name = exc.name, error_msg = exc.msg error_name = exc.name, error_msg = exc.msg
return false return
if res: if res:
let delay = vc.getDelay(slot.block_deadline()) let delay = vc.getDelay(slot.block_deadline())
beacon_blocks_sent.inc() beacon_blocks_sent.inc()
beacon_blocks_sent_delay.observe(delay.toFloatSeconds()) beacon_blocks_sent_delay.observe(delay.toFloatSeconds())
notice "Blinded block published", delay = delay notice "Blinded block published", delay = delay
true
else: else:
warn "Blinded block was not accepted by beacon node" warn "Blinded block was not accepted by beacon node"
false
else: else:
let let
blockRoot = hash_tree_root( blockRoot = hash_tree_root(
@ -367,7 +245,7 @@ proc publishBlockV3(vc: ValidatorClientRef, currentSlot, slot: Slot,
if notSlashable.isErr(): if notSlashable.isErr():
warn "Slashing protection activated for block proposal" warn "Slashing protection activated for block proposal"
return false return
let let
signature = signature =
@ -377,7 +255,7 @@ proc publishBlockV3(vc: ValidatorClientRef, currentSlot, slot: Slot,
if res.isErr(): if res.isErr():
warn "Unable to sign block proposal using remote signer", warn "Unable to sign block proposal using remote signer",
reason = res.error() reason = res.error()
return false return
res.get() res.get()
except CancelledError as exc: except CancelledError as exc:
debug "Block signature process has been interrupted" debug "Block signature process has been interrupted"
@ -385,240 +263,12 @@ proc publishBlockV3(vc: ValidatorClientRef, currentSlot, slot: Slot,
except CatchableError as exc: except CatchableError as exc:
error "An unexpected error occurred while signing block", error "An unexpected error occurred while signing block",
error_name = exc.name, error_msg = exc.msg error_name = exc.name, error_msg = exc.msg
return false return
signedBlockContents = signedBlockContents =
RestPublishedSignedBlockContents.init( RestPublishedSignedBlockContents.init(
forkyMaybeBlindedBlck, blockRoot, signature) forkyMaybeBlindedBlck, blockRoot, signature)
res =
try:
debug "Sending block"
await vc.publishBlock(signedBlockContents, ApiStrategyKind.First)
except ValidatorApiError as exc:
warn "Unable to publish block", reason = exc.getFailureReason()
return false
except CancelledError as exc:
debug "Block publication has been interrupted"
raise exc
except CatchableError as exc:
error "An unexpected error occurred while publishing block",
error_name = exc.name, error_msg = exc.msg
return false
if res:
let delay = vc.getDelay(slot.block_deadline())
beacon_blocks_sent.inc()
beacon_blocks_sent_delay.observe(delay.toFloatSeconds())
notice "Block published", delay = delay
true
else:
warn "Block was not accepted by beacon node"
false
proc publishBlockV2(vc: ValidatorClientRef, currentSlot, slot: Slot,
fork: Fork, randaoReveal: ValidatorSig,
validator: AttachedValidator) {.async.} =
let
genesisRoot = vc.beaconGenesis.genesis_validators_root
graffiti = vc.getGraffitiBytes(validator)
vindex = validator.index.get()
logScope:
validator = validatorLog(validator)
validator_index = vindex
slot = slot
wall_slot = currentSlot
var beaconBlocks =
block:
let blindedBlockFut =
if vc.config.payloadBuilderEnable:
vc.produceBlindedBlock(currentSlot, slot, randaoReveal, graffiti,
validator)
else:
nil
let normalBlockFut = vc.produceBlock(currentSlot, slot, randaoReveal,
graffiti, validator)
let blindedBlock =
if isNil(blindedBlockFut):
Opt.none(PreparedBlindedBeaconBlock)
else:
try:
await blindedBlockFut
except CancelledError as exc:
if not(normalBlockFut.finished()):
await normalBlockFut.cancelAndWait()
raise exc
except CatchableError:
# This should not happen, because all the exceptions are handled.
Opt.none(PreparedBlindedBeaconBlock)
let normalBlock =
if blindedBlock.isNone():
try:
await normalBlockFut
except CancelledError as exc:
raise exc
except CatchableError:
# This should not happen, because all the exceptions are handled.
Opt.none(PreparedBeaconBlock)
else:
if not(normalBlockFut.finished()):
asyncSpawn lazyWait(normalBlockFut)
Opt.none(PreparedBeaconBlock)
if blindedBlock.isNone() and normalBlock.isNone():
return
(blindedBlock: blindedBlock, normalBlock: normalBlock)
if beaconBlocks.blindedBlock.isSome():
let
preparedBlock = beaconBlocks.blindedBlock.get()
signingRoot = compute_block_signing_root(fork, genesisRoot, slot,
preparedBlock.blockRoot)
notSlashable = vc.attachedValidators[]
.slashingProtection
.registerBlock(vindex, validator.pubkey, slot, signingRoot)
logScope:
blck = shortLog(preparedBlock.data)
block_root = shortLog(preparedBlock.blockRoot)
signing_root = shortLog(signingRoot)
if notSlashable.isOk():
let
signature =
try:
let res = await validator.getBlockSignature(fork, genesisRoot,
slot,
preparedBlock.blockRoot,
preparedBlock.data)
if res.isErr():
warn "Unable to sign blinded block proposal using remote signer",
reason = res.error()
return
res.get()
except CancelledError as exc:
debug "Blinded block signature process has been interrupted"
raise exc
except CatchableError as exc:
error "An unexpected error occurred while signing blinded block",
error_name = exc.name, error_msg = exc.msg
return
logScope:
signature = shortLog(signature)
let
signedBlock = ForkedSignedBlindedBeaconBlock.init(preparedBlock.data,
preparedBlock.blockRoot, signature)
res =
try:
debug "Sending blinded block"
await vc.publishBlindedBlock(signedBlock, ApiStrategyKind.First)
except ValidatorApiError as exc:
warn "Unable to publish blinded block",
reason = exc.getFailureReason()
return
except CancelledError as exc:
debug "Blinded block publication has been interrupted"
raise exc
except CatchableError as exc:
error "An unexpected error occurred while publishing blinded block",
error_name = exc.name, error_msg = exc.msg
return
if res:
let delay = vc.getDelay(slot.block_deadline())
beacon_blocks_sent.inc()
beacon_blocks_sent_delay.observe(delay.toFloatSeconds())
notice "Blinded block published", delay = delay
else:
warn "Blinded block was not accepted by beacon node"
else:
warn "Slashing protection activated for blinded block proposal"
else:
let
preparedBlock = beaconBlocks.normalBlock.get()
signingRoot = compute_block_signing_root(fork, genesisRoot, slot,
preparedBlock.blockRoot)
notSlashable = vc.attachedValidators[]
.slashingProtection
.registerBlock(vindex, validator.pubkey, slot, signingRoot)
logScope:
blck = shortLog(preparedBlock.data)
block_root = shortLog(preparedBlock.blockRoot)
signing_root = shortLog(signingRoot)
if notSlashable.isOk():
let
signature =
try:
let res = await validator.getBlockSignature(fork,
genesisRoot, slot,
preparedBlock.blockRoot,
preparedBlock.data)
if res.isErr():
warn "Unable to sign block proposal using remote signer",
reason = res.error()
return
res.get()
except CancelledError as exc:
debug "Block signature process has been interrupted"
raise exc
except CatchableError as exc:
error "An unexpected error occurred while signing block",
error_name = exc.name, error_msg = exc.msg
return
signedBlockContents =
case preparedBlock.data.kind
of ConsensusFork.Phase0:
RestPublishedSignedBlockContents(kind: ConsensusFork.Phase0,
phase0Data: phase0.SignedBeaconBlock(
message: preparedBlock.data.phase0Data,
root: preparedBlock.blockRoot,
signature: signature))
of ConsensusFork.Altair:
RestPublishedSignedBlockContents(kind: ConsensusFork.Altair,
altairData: altair.SignedBeaconBlock(
message: preparedBlock.data.altairData,
root: preparedBlock.blockRoot,
signature: signature))
of ConsensusFork.Bellatrix:
RestPublishedSignedBlockContents(kind: ConsensusFork.Bellatrix,
bellatrixData: bellatrix.SignedBeaconBlock(
message: preparedBlock.data.bellatrixData,
root: preparedBlock.blockRoot,
signature: signature))
of ConsensusFork.Capella:
RestPublishedSignedBlockContents(kind: ConsensusFork.Capella,
capellaData: capella.SignedBeaconBlock(
message: preparedBlock.data.capellaData,
root: preparedBlock.blockRoot,
signature: signature))
of ConsensusFork.Deneb:
RestPublishedSignedBlockContents(kind: ConsensusFork.Deneb,
denebData: DenebSignedBlockContents(
signed_block: deneb.SignedBeaconBlock(
message: preparedBlock.data.denebData,
root: preparedBlock.blockRoot,
signature: signature),
kzg_proofs: preparedBlock.kzgProofsOpt.get,
blobs: preparedBlock.blobsOpt.get))
of ConsensusFork.Electra:
RestPublishedSignedBlockContents(kind: ConsensusFork.Electra,
electraData: ElectraSignedBlockContents(
signed_block: electra.SignedBeaconBlock(
message: preparedBlock.data.electraData,
root: preparedBlock.blockRoot,
signature: signature),
kzg_proofs: preparedBlock.kzgProofsOpt.get,
blobs: preparedBlock.blobsOpt.get))
res = res =
try: try:
debug "Sending block" debug "Sending block"
@ -641,8 +291,6 @@ proc publishBlockV2(vc: ValidatorClientRef, currentSlot, slot: Slot,
notice "Block published", delay = delay notice "Block published", delay = delay
else: else:
warn "Block was not accepted by beacon node" warn "Block was not accepted by beacon node"
else:
warn "Slashing protection activated for block proposal"
proc publishBlock(vc: ValidatorClientRef, currentSlot, slot: Slot, proc publishBlock(vc: ValidatorClientRef, currentSlot, slot: Slot,
validator: AttachedValidator) {.async.} = validator: AttachedValidator) {.async.} =
@ -677,18 +325,7 @@ proc publishBlock(vc: ValidatorClientRef, currentSlot, slot: Slot,
error_name = exc.name, error_msg = exc.msg error_name = exc.name, error_msg = exc.msg
return return
# TODO (cheatfate): This branch should be removed as soon as `produceBlockV2` await vc.publishBlockV3(currentSlot, slot, fork, randaoReveal, validator)
# call will be fully deprecated.
if vc.isProduceBlockV3Supported():
# We call `V3` first, if call fails and `isProduceBlockV3Supported()`
# did not find any nodes which support `V3` we try to call `V2`.
let res =
await vc.publishBlockV3(currentSlot, slot, fork, randaoReveal, validator)
if not(res) and not(vc.isProduceBlockV3Supported()):
notice "Block production using V3 failed, trying V2"
await vc.publishBlockV2(currentSlot, slot, fork, randaoReveal, validator)
else:
await vc.publishBlockV2(currentSlot, slot, fork, randaoReveal, validator)
proc proposeBlock(vc: ValidatorClientRef, slot: Slot, proc proposeBlock(vc: ValidatorClientRef, slot: Slot,
proposerKey: ValidatorPubKey) {.async.} = proposerKey: ValidatorPubKey) {.async.} =

View File

@ -117,7 +117,6 @@ type
RestBeaconNodeFeature* {.pure.} = enum RestBeaconNodeFeature* {.pure.} = enum
NoNimbusExtensions, ## BN does not support Nimbus Extensions NoNimbusExtensions, ## BN does not support Nimbus Extensions
NoProduceBlockV3 ## BN does not support produceBlockV3 call
TimeOffset* = object TimeOffset* = object
value: int64 value: int64
@ -1512,7 +1511,7 @@ proc `+`*(slot: Slot, epochs: Epoch): Slot =
func finish_slot*(epoch: Epoch): Slot = func finish_slot*(epoch: Epoch): Slot =
## Return the last slot of ``epoch``. ## Return the last slot of ``epoch``.
Slot((epoch + 1).start_slot() - 1) (epoch + 1).start_slot() - 1
proc getGraffitiBytes*(vc: ValidatorClientRef, proc getGraffitiBytes*(vc: ValidatorClientRef,
validator: AttachedValidator): GraffitiBytes = validator: AttachedValidator): GraffitiBytes =

View File

@ -92,41 +92,43 @@ proc appendRecord(f: IoHandle, index: Index): Result[int64, string] =
f.appendIndex(index.startSlot, index.offsets) f.appendIndex(index.startSlot, index.offsets)
proc readIndex*(f: IoHandle): Result[Index, string] = proc readIndex*(f: IoHandle): Result[Index, string] =
var
buf: seq[byte]
pos: int
let let
startPos = ? f.getFilePos().mapErr(toString) startPos = ? f.getFilePos().mapErr(toString)
fileSize = ? f.getFileSize().mapErr(toString) fileSize = ? f.getFileSize().mapErr(toString)
header = ? f.readHeader() header = ? f.readRecord(buf)
if header.typ != E2Index: return err("not an index") if header.typ != E2Index: return err("not an index")
if header.len < 16: return err("index entry too small") if buf.len < 16: return err("index entry too small")
if header.len mod 8 != 0: return err("index length invalid") if buf.len mod 8 != 0: return err("index length invalid")
var buf: array[8, byte]
? f.readFileExact(buf)
let let
slot = uint64.fromBytesLE(buf) slot = uint64.fromBytesLE(buf.toOpenArray(pos, pos + 7))
count = header.len div 8 - 2 count = buf.len div 8 - 2
pos += 8
# technically not an error, but we'll throw this sanity check in here..
if slot > int32.high().uint64: return err("fishy slot")
var offsets = newSeqUninitialized[int64](count) var offsets = newSeqUninitialized[int64](count)
for i in 0..<count: for i in 0..<count:
? f.readFileExact(buf)
let let
offset = uint64.fromBytesLE(buf) offset = uint64.fromBytesLE(buf.toOpenArray(pos, pos + 7))
absolute = absolute =
if offset == 0: 0'i64 if offset == 0: 0'i64
else: else:
# Wrapping math is actually convenient here # Wrapping math is actually convenient here
cast[int64](cast[uint64](startPos) + offset) cast[int64](cast[uint64](startPos) + offset)
if absolute < 0 or absolute > fileSize: return err("Invalid offset") if absolute < 0 or absolute > fileSize: return err("invalid offset")
offsets[i] = absolute offsets[i] = absolute
pos += 8
? f.readFileExact(buf) if uint64(count) != uint64.fromBytesLE(buf.toOpenArray(pos, pos + 7)):
if uint64(count) != uint64.fromBytesLE(buf): return err("invalid count") return err("invalid count")
# technically not an error, but we'll throw this sanity check in here..
if slot > int32.high().uint64: return err("fishy slot")
ok(Index(startSlot: Slot(slot), offsets: offsets)) ok(Index(startSlot: Slot(slot), offsets: offsets))

View File

@ -239,16 +239,19 @@ proc doSSZ(conf: NcliConf) =
of "bellatrix_signed_block": printit(bellatrix.SignedBeaconBlock) of "bellatrix_signed_block": printit(bellatrix.SignedBeaconBlock)
of "capella_signed_block": printit(capella.SignedBeaconBlock) of "capella_signed_block": printit(capella.SignedBeaconBlock)
of "deneb_signed_block": printit(deneb.SignedBeaconBlock) of "deneb_signed_block": printit(deneb.SignedBeaconBlock)
of "electra_signed_block": printit(electra.SignedBeaconBlock)
of "phase0_block": printit(phase0.BeaconBlock) of "phase0_block": printit(phase0.BeaconBlock)
of "altair_block": printit(altair.BeaconBlock) of "altair_block": printit(altair.BeaconBlock)
of "bellatrix_block": printit(bellatrix.BeaconBlock) of "bellatrix_block": printit(bellatrix.BeaconBlock)
of "capella_block": printit(capella.BeaconBlock) of "capella_block": printit(capella.BeaconBlock)
of "deneb_block": printit(deneb.BeaconBlock) of "deneb_block": printit(deneb.BeaconBlock)
of "electra_block": printit(electra.BeaconBlock)
of "phase0_block_body": printit(phase0.BeaconBlockBody) of "phase0_block_body": printit(phase0.BeaconBlockBody)
of "altair_block_body": printit(altair.BeaconBlockBody) of "altair_block_body": printit(altair.BeaconBlockBody)
of "bellatrix_block_body": printit(bellatrix.BeaconBlockBody) of "bellatrix_block_body": printit(bellatrix.BeaconBlockBody)
of "capella_block_body": printit(capella.BeaconBlockBody) of "capella_block_body": printit(capella.BeaconBlockBody)
of "deneb_block_body": printit(deneb.BeaconBlockBody) of "deneb_block_body": printit(deneb.BeaconBlockBody)
of "electra_block_body": printit(electra.BeaconBlockBody)
of "block_header": printit(BeaconBlockHeader) of "block_header": printit(BeaconBlockHeader)
of "deposit": printit(Deposit) of "deposit": printit(Deposit)
of "deposit_data": printit(DepositData) of "deposit_data": printit(DepositData)
@ -258,6 +261,7 @@ proc doSSZ(conf: NcliConf) =
of "bellatrix_state": printit(bellatrix.BeaconState) of "bellatrix_state": printit(bellatrix.BeaconState)
of "capella_state": printit(capella.BeaconState) of "capella_state": printit(capella.BeaconState)
of "deneb_state": printit(deneb.BeaconState) of "deneb_state": printit(deneb.BeaconState)
of "electra_state": printit(electra.BeaconState)
of "proposer_slashing": printit(ProposerSlashing) of "proposer_slashing": printit(ProposerSlashing)
of "voluntary_exit": printit(VoluntaryExit) of "voluntary_exit": printit(VoluntaryExit)

View File

@ -126,14 +126,13 @@ static:
"15227487_86601706.echop"]: # Wrong extension "15227487_86601706.echop"]: # Wrong extension
doAssert not filename.matchFilenameAggregatedFiles doAssert not filename.matchFilenameAggregatedFiles
proc getUnaggregatedFilesEpochRange*( proc getUnaggregatedFilesEpochRange*(dir: string):
dir: string tuple[firstEpoch, lastEpoch: Epoch] {.raises: [OSError, ValueError].} =
): tuple[firstEpoch, lastEpoch: Epoch] {.raises: [OSError, ValueError].} =
var smallestEpochFileName = var smallestEpochFileName =
'9'.repeat(epochInfoFileNameDigitsCount) & epochFileNameExtension '9'.repeat(epochInfoFileNameDigitsCount) & epochFileNameExtension
var largestEpochFileName = var largestEpochFileName =
'0'.repeat(epochInfoFileNameDigitsCount) & epochFileNameExtension '0'.repeat(epochInfoFileNameDigitsCount) & epochFileNameExtension
for (_, fn) in walkDir(dir.string, relative = true): for (_, fn) in walkDir(dir, relative = true):
if fn.matchFilenameUnaggregatedFiles: if fn.matchFilenameUnaggregatedFiles:
if fn < smallestEpochFileName: if fn < smallestEpochFileName:
smallestEpochFileName = fn smallestEpochFileName = fn
@ -151,7 +150,7 @@ proc getUnaggregatedFilesLastEpoch*(
proc getAggregatedFilesLastEpoch*( proc getAggregatedFilesLastEpoch*(
dir: string): Epoch {.raises: [OSError, ValueError].}= dir: string): Epoch {.raises: [OSError, ValueError].}=
var largestEpochInFileName = 0'u var largestEpochInFileName = 0'u
for (_, fn) in walkDir(dir.string, relative = true): for (_, fn) in walkDir(dir, relative = true):
if fn.matchFilenameAggregatedFiles: if fn.matchFilenameAggregatedFiles:
let fileLastEpoch = parseUInt( let fileLastEpoch = parseUInt(
fn[epochInfoFileNameDigitsCount + 1 .. 2 * epochInfoFileNameDigitsCount]) fn[epochInfoFileNameDigitsCount + 1 .. 2 * epochInfoFileNameDigitsCount])

View File

@ -553,8 +553,8 @@ proc sendDeposits(deposits: seq[LaunchPadDeposit],
var web3 = await initWeb3(web3Url, privateKey) var web3 = await initWeb3(web3Url, privateKey)
let gasPrice = int(await web3.provider.eth_gasPrice()) * 2 let gasPrice = int(await web3.provider.eth_gasPrice()) * 2
let depositContract = web3.contractSender(DepositContract, let depositContract = web3.contractSender(
Eth1Address depositContractAddress) DepositContract, depositContractAddress)
for i in 4200 ..< deposits.len: for i in 4200 ..< deposits.len:
let dp = deposits[i] as DepositData let dp = deposits[i] as DepositData
@ -656,7 +656,7 @@ when isMainModule:
error "Failed to read an Eth1 private key from standard input" error "Failed to read an Eth1 private key from standard input"
if privateKey.len > 0: if privateKey.len > 0:
conf.privateKey = privateKey.string conf.privateKey = privateKey
case conf.cmd case conf.cmd
of StartUpCommand.createTestnet: of StartUpCommand.createTestnet:

View File

@ -11,5 +11,4 @@
--styleCheck:usages --styleCheck:usages
--styleCheck:error --styleCheck:error
--hint[ConvFromXtoItselfNotNeeded]:off
--hint[Processing]:off --hint[Processing]:off

View File

@ -326,8 +326,7 @@ cli do(slots = SLOTS_PER_EPOCH * 7,
contribution: contribution, contribution: contribution,
selection_proof: aggregator.selectionProof) selection_proof: aggregator.selectionProof)
validatorPrivKey = validatorPrivKey = MockPrivKeys[aggregator.validatorIdx]
MockPrivKeys[aggregator.validatorIdx.ValidatorIndex]
signedContributionAndProof = SignedContributionAndProof( signedContributionAndProof = SignedContributionAndProof(
message: contributionAndProof, message: contributionAndProof,

View File

@ -11,5 +11,4 @@
--styleCheck:usages --styleCheck:usages
--styleCheck:error --styleCheck:error
--hint[ConvFromXtoItselfNotNeeded]:off
--hint[Processing]:off --hint[Processing]:off

View File

@ -11,7 +11,7 @@
import import
# Beacon chain internals # Beacon chain internals
chronicles, chronicles,
../../../beacon_chain/spec/[beaconstate, presets, state_transition_epoch], ../../../beacon_chain/spec/[presets, state_transition_epoch],
../../../beacon_chain/spec/datatypes/altair, ../../../beacon_chain/spec/datatypes/altair,
# Test utilities # Test utilities
../../testutil, ../../testutil,

View File

@ -10,7 +10,7 @@
import import
# Beacon chain internals # Beacon chain internals
../../../beacon_chain/spec/[beaconstate, presets, state_transition_epoch], ../../../beacon_chain/spec/[presets, state_transition_epoch],
../../../beacon_chain/spec/datatypes/[altair, bellatrix], ../../../beacon_chain/spec/datatypes/[altair, bellatrix],
# Test utilities # Test utilities
../../testutil, ../../testutil,

View File

@ -5,13 +5,14 @@
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0). # * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
# at your option. This file may not be copied, modified, or distributed except according to those terms. # at your option. This file may not be copied, modified, or distributed except according to those terms.
{.push raises: [].}
{.used.} {.used.}
import import
# Status internals # Status internals
chronicles, chronicles,
# Beacon chain internals # Beacon chain internals
../../../beacon_chain/spec/[beaconstate, presets, state_transition_epoch], ../../../beacon_chain/spec/[presets, state_transition_epoch],
../../../beacon_chain/spec/datatypes/[altair, capella], ../../../beacon_chain/spec/datatypes/[altair, capella],
# Test utilities # Test utilities
../../testutil, ../../testutil,

View File

@ -12,7 +12,7 @@ import
# Status internals # Status internals
chronicles, chronicles,
# Beacon chain internals # Beacon chain internals
../../../beacon_chain/spec/[beaconstate, presets, state_transition_epoch], ../../../beacon_chain/spec/[presets, state_transition_epoch],
../../../beacon_chain/spec/datatypes/[altair, deneb], ../../../beacon_chain/spec/datatypes/[altair, deneb],
# Test utilities # Test utilities
../../testutil, ../../testutil,

View File

@ -12,7 +12,7 @@ import
# Status internals # Status internals
chronicles, chronicles,
# Beacon chain internals # Beacon chain internals
../../../beacon_chain/spec/[beaconstate, presets, state_transition_epoch], ../../../beacon_chain/spec/[presets, state_transition_epoch],
../../../beacon_chain/spec/datatypes/[altair, electra], ../../../beacon_chain/spec/datatypes/[altair, electra],
# Test utilities # Test utilities
../../testutil, ../../testutil,
@ -146,13 +146,11 @@ runSuite(ParticipationFlagDir, "Participation flag updates"):
# --------------------------------------------------------------- # ---------------------------------------------------------------
runSuite(PendingBalanceDepositsDir, "Pending balance deposits"): runSuite(PendingBalanceDepositsDir, "Pending balance deposits"):
process_pending_balance_deposits(cfg, state, cache) process_pending_balance_deposits(cfg, state, cache)
Result[void, cstring].ok()
# Pending consolidations # Pending consolidations
# --------------------------------------------------------------- # ---------------------------------------------------------------
runSuite(PendingConsolidationsDir, "Pending consolidations"): runSuite(PendingConsolidationsDir, "Pending consolidations"):
process_pending_consolidations(cfg, state) process_pending_consolidations(cfg, state)
Result[void, cstring].ok()
# Sync committee updates # Sync committee updates
# --------------------------------------------------------------- # ---------------------------------------------------------------

View File

@ -80,6 +80,132 @@ type
D: BitList[6] D: BitList[6]
E: BitArray[8] E: BitArray[8]
# https://github.com/wemeetagain/consensus-specs/blob/eip-7495/tests/generators/ssz_generic/ssz_stablecontainer.py
SingleFieldTestStableStruct {.sszStableContainer: 4.} = object
A: Opt[byte]
SmallTestStableStruct {.sszStableContainer: 4.} = object
A: Opt[uint16]
B: Opt[uint16]
FixedTestStableStruct {.sszStableContainer: 4.} = object
A: Opt[uint8]
B: Opt[uint64]
C: Opt[uint32]
VarTestStableStruct {.sszStableContainer: 4.} = object
A: Opt[uint16]
B: Opt[List[uint16, 1024]]
C: Opt[uint8]
ComplexTestStableStruct {.sszStableContainer: 8.} = object
A: Opt[uint16]
B: Opt[List[uint16, 128]]
C: Opt[uint8]
D: Opt[List[byte, 256]]
E: Opt[VarTestStableStruct]
F: Opt[array[4, FixedTestStableStruct]]
G: Opt[array[2, VarTestStableStruct]]
BitsStableStruct {.sszStableContainer: 8.} = object
A: Opt[BitList[5]]
B: Opt[BitArray[2]]
C: Opt[BitArray[1]]
D: Opt[BitList[6]]
E: Opt[BitArray[8]]
# https://github.com/wemeetagain/consensus-specs/blob/eip-7495/tests/generators/ssz_generic/ssz_profile.py
SingleFieldTestProfile {.sszProfile: SingleFieldTestStableStruct.} = object
A: byte
SmallTestProfile1 {.sszProfile: SmallTestStableStruct.} = object
A: uint16
B: uint16
SmallTestProfile2 {.sszProfile: SmallTestStableStruct.} = object
A: uint16
SmallTestProfile3 {.sszProfile: SmallTestStableStruct.} = object
B: uint16
FixedTestProfile1 {.sszProfile: FixedTestStableStruct.} = object
A: uint8
B: uint64
C: uint32
FixedTestProfile2 {.sszProfile: FixedTestStableStruct.} = object
A: uint8
B: uint64
FixedTestProfile3 {.sszProfile: FixedTestStableStruct.} = object
A: uint8
C: uint32
FixedTestProfile4 {.sszProfile: FixedTestStableStruct.} = object
C: uint32
VarTestProfile1 {.sszProfile: VarTestStableStruct.} = object
A: uint16
B: List[uint16, 1024]
C: uint8
VarTestProfile2 {.sszProfile: VarTestStableStruct.} = object
B: List[uint16, 1024]
C: uint8
VarTestProfile3 {.sszProfile: VarTestStableStruct.} = object
B: List[uint16, 1024]
ComplexTestProfile1 {.sszProfile: ComplexTestStableStruct.} = object
A: uint16
B: List[uint16, 128]
C: uint8
D: List[byte, 256]
E: VarTestStableStruct
F: array[4, FixedTestStableStruct]
G: array[2, VarTestStableStruct]
ComplexTestProfile2 {.sszProfile: ComplexTestStableStruct.} = object
A: uint16
B: List[uint16, 128]
C: uint8
D: List[byte, 256]
E: VarTestStableStruct
ComplexTestProfile3 {.sszProfile: ComplexTestStableStruct.} = object
A: uint16
C: uint8
E: VarTestStableStruct
G: array[2, VarTestStableStruct]
ComplexTestProfile4 {.sszProfile: ComplexTestStableStruct.} = object
B: List[uint16, 128]
D: List[byte, 256]
F: array[4, FixedTestStableStruct]
ComplexTestProfile5 {.sszProfile: ComplexTestStableStruct.} = object
E: VarTestStableStruct
F: array[4, FixedTestStableStruct]
G: array[2, VarTestStableStruct]
BitsProfile1 {.sszProfile: BitsStableStruct.} = object
A: BitList[5]
B: BitArray[2]
C: BitArray[1]
D: BitList[6]
E: BitArray[8]
BitsProfile2 {.sszProfile: BitsStableStruct.} = object
A: BitList[5]
B: BitArray[2]
C: BitArray[1]
D: BitList[6]
BitsProfile3 {.sszProfile: BitsStableStruct.} = object
A: BitList[5]
D: BitList[6]
E: BitArray[8]
# Type specific checks # Type specific checks
# ------------------------------------------------------------------------ # ------------------------------------------------------------------------
@ -285,6 +411,71 @@ proc sszCheck(
of "BitsStruct": checkBasic(BitsStruct, dir, expectedHash) of "BitsStruct": checkBasic(BitsStruct, dir, expectedHash)
else: else:
raise newException(ValueError, "unknown container in test: " & sszSubType) raise newException(ValueError, "unknown container in test: " & sszSubType)
of "profiles":
var name: string
let wasMatched = scanf(sszSubType, "$+_", name)
doAssert wasMatched
case name
of "BitsProfile1":
checkBasic(BitsProfile1, dir, expectedHash)
of "BitsProfile2":
checkBasic(BitsProfile2, dir, expectedHash)
of "BitsProfile3":
checkBasic(BitsProfile3, dir, expectedHash)
of "ComplexTestProfile1":
checkBasic(ComplexTestProfile1, dir, expectedHash)
of "ComplexTestProfile2":
checkBasic(ComplexTestProfile2, dir, expectedHash)
of "ComplexTestProfile3":
checkBasic(ComplexTestProfile3, dir, expectedHash)
of "ComplexTestProfile4":
checkBasic(ComplexTestProfile4, dir, expectedHash)
of "ComplexTestProfile5":
checkBasic(ComplexTestProfile5, dir, expectedHash)
of "FixedTestProfile1":
checkBasic(FixedTestProfile1, dir, expectedHash)
of "FixedTestProfile2":
checkBasic(FixedTestProfile2, dir, expectedHash)
of "FixedTestProfile3":
checkBasic(FixedTestProfile3, dir, expectedHash)
of "FixedTestProfile4":
checkBasic(FixedTestProfile4, dir, expectedHash)
of "SingleFieldTestProfile":
checkBasic(SingleFieldTestProfile, dir, expectedHash)
of "SmallTestProfile1":
checkBasic(SmallTestProfile1, dir, expectedHash)
of "SmallTestProfile2":
checkBasic(SmallTestProfile2, dir, expectedHash)
of "SmallTestProfile3":
checkBasic(SmallTestProfile3, dir, expectedHash)
of "VarTestProfile1":
checkBasic(VarTestProfile1, dir, expectedHash)
of "VarTestProfile2":
checkBasic(VarTestProfile2, dir, expectedHash)
of "VarTestProfile3":
checkBasic(VarTestProfile3, dir, expectedHash)
else:
raise newException(ValueError, "unknown profile in test: " & sszSubType)
of "stablecontainers":
var name: string
let wasMatched = scanf(sszSubType, "$+_", name)
doAssert wasMatched
case name
of "BitsStableStruct":
checkBasic(BitsStableStruct, dir, expectedHash)
of "ComplexTestStableStruct":
checkBasic(ComplexTestStableStruct, dir, expectedHash)
of "FixedTestStableStruct":
checkBasic(FixedTestStableStruct, dir, expectedHash)
of "SingleFieldTestStableStruct":
checkBasic(SingleFieldTestStableStruct, dir, expectedHash)
of "SmallTestStableStruct":
checkBasic(SmallTestStableStruct, dir, expectedHash)
of "VarTestStableStruct":
checkBasic(VarTestStableStruct, dir, expectedHash)
else:
raise newException(ValueError,
"unknown stablecontainer in test: " & sszSubType)
else: else:
raise newException(ValueError, "unknown ssz type in test: " & sszType) raise newException(ValueError, "unknown ssz type in test: " & sszType)
@ -306,26 +497,27 @@ suite "EF - SSZ generic types":
of "containers": of "containers":
skipped = " - skipping BitsStruct" skipped = " - skipping BitsStruct"
test &"Testing {sszType:12} inputs - valid" & skipped: test &"Testing {sszType:16} inputs - valid" & skipped:
let path = SSZDir/sszType/"valid" let path = SSZDir/sszType/"valid"
for pathKind, sszSubType in walkDir( for pathKind, sszSubType in walkDir(
path, relative = true, checkDir = true): path, relative = true, checkDir = true):
if pathKind != pcDir: continue if pathKind != pcDir: continue
sszCheck(path, sszType, sszSubType) sszCheck(path, sszType, sszSubType)
test &"Testing {sszType:12} inputs - invalid" & skipped: template invalidPath: untyped = SSZDir/sszType/"invalid"
let path = SSZDir/sszType/"invalid" if os_ops.dirExists(invalidPath):
for pathKind, sszSubType in walkDir( test &"Testing {sszType:16} inputs - invalid" & skipped:
path, relative = true, checkDir = true): for pathKind, sszSubType in walkDir(
if pathKind != pcDir: continue invalidPath, relative = true, checkDir = true):
try: if pathKind != pcDir: continue
sszCheck(path, sszType, sszSubType) try:
except SszError, UnconsumedInput: sszCheck(invalidPath, sszType, sszSubType)
discard except SszError, UnconsumedInput:
except TestSizeError as err: discard
echo err.msg except TestSizeError as err:
skip() echo err.msg
except: skip()
checkpoint getStackTrace(getCurrentException()) except:
checkpoint getCurrentExceptionMsg() checkpoint getStackTrace(getCurrentException())
check false checkpoint getCurrentExceptionMsg()
check false

View File

@ -1,5 +1,5 @@
# beacon_chain # beacon_chain
# Copyright (c) 2019-2023 Status Research & Development GmbH # Copyright (c) 2019-2024 Status Research & Development GmbH
# Licensed and distributed under either of # Licensed and distributed under either of
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT). # * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0). # * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
@ -11,5 +11,4 @@
--styleCheck:usages --styleCheck:usages
--styleCheck:hint --styleCheck:hint
--hint[ConvFromXtoItselfNotNeeded]:off
--hint[Processing]:off --hint[Processing]:off

View File

@ -6,6 +6,7 @@
# at your option. This file may not be copied, modified, or distributed except according to those terms. # at your option. This file may not be copied, modified, or distributed except according to those terms.
{.push raises: [].} {.push raises: [].}
{.used.}
import unittest2, results, chronos, stint import unittest2, results, chronos, stint
import ../beacon_chain/validators/beacon_validators, import ../beacon_chain/validators/beacon_validators,

View File

@ -1336,8 +1336,7 @@ suite "State history":
res = process_slots(cfg, dag.headState, 5.Slot, cache, info, flags = {}) res = process_slots(cfg, dag.headState, 5.Slot, cache, info, flags = {})
check res.isOk check res.isOk
for i in 0.Slot .. 5.Slot: for i in 0.Slot .. 5.Slot:
check state.getBlockIdAtSlot(i) == check state.getBlockIdAtSlot(i) == Opt.some BlockSlotId.init(gen, i)
Opt.some BlockSlotId.init(gen, i.Slot)
check state.getBlockIdAtSlot(6.Slot).isNone check state.getBlockIdAtSlot(6.Slot).isNone
# Fill 5 slots # Fill 5 slots

View File

@ -6,10 +6,10 @@
# at your option. This file may not be copied, modified, or distributed except according to those terms. # at your option. This file may not be copied, modified, or distributed except according to those terms.
{.push raises: [].} {.push raises: [].}
{.used.}
import import
std/algorithm, unittest2, chronicles, results, stew/[byteutils, io2],
unittest2, chronicles, stew/[results, byteutils, io2],
chronos/asyncproc, chronos/asyncproc,
chronos/unittest2/asynctests, chronos/unittest2/asynctests,
../beacon_chain/spec/[signatures, crypto], ../beacon_chain/spec/[signatures, crypto],
@ -19,8 +19,6 @@ import
from std/os import getEnv, osErrorMsg from std/os import getEnv, osErrorMsg
{.used.}
const const
TestDirectoryName = "test-signing-node" TestDirectoryName = "test-signing-node"
TestDirectoryNameVerifyingWeb3Signer = "test-signing-node-verifying-web3signer" TestDirectoryNameVerifyingWeb3Signer = "test-signing-node-verifying-web3signer"
@ -63,8 +61,8 @@ const
AgAttestation = "{\"data\":{\"aggregation_bits\":\"0x01\",\"signature\":\"0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505\",\"data\":{\"slot\":\"1\",\"index\":\"1\",\"beacon_block_root\":\"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2\",\"source\":{\"epoch\":\"1\",\"root\":\"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2\"},\"target\":{\"epoch\":\"1\",\"root\":\"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2\"}}}}" AgAttestation = "{\"data\":{\"aggregation_bits\":\"0x01\",\"signature\":\"0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505\",\"data\":{\"slot\":\"1\",\"index\":\"1\",\"beacon_block_root\":\"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2\",\"source\":{\"epoch\":\"1\",\"root\":\"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2\"},\"target\":{\"epoch\":\"1\",\"root\":\"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2\"}}}}"
CapellaBlock = "{\"version\":\"capella\",\"data\":{\"slot\":\"5297696\",\"proposer_index\":\"153094\",\"parent_root\":\"0xe6106533af9be918120ead7440a8006c7f123cc3cb7daf1f11d951864abea014\",\"state_root\":\"0xf86196d34500ca25d1f4e7431d4d52f6f85540bcaf97dd0d2ad9ecdb3eebcdf0\",\"body\":{\"randao_reveal\":\"0xa7efee3d5ddceb60810b23e3b5d39734696418f41dfd13a0851c7be7a72acbdceaa61e1db27513801917d72519d1c1040ccfed829faf06abe06d9964949554bf4369134b66de715ea49eb4fecf3e2b7e646f1764a1993e31e53dbc6557929c12\",\"eth1_data\":{\"deposit_root\":\"0x8ec87d7219a3c873fff3bfe206b4f923d1b471ce4ff9d6d6ecc162ef07825e14\",\"deposit_count\":\"259476\",\"block_hash\":\"0x877b6f8332c7397251ff3f0c5cecec105ff7d4cb78251b47f91fd15a86a565ab\"},\"graffiti\":\"\",\"proposer_slashings\":[],\"attester_slashings\":[],\"attestations\":[],\"deposits\":[],\"voluntary_exits\":[],\"sync_aggregate\":{\"sync_committee_bits\":\"0x733dfda7f5ffde5ade73367fcbf7fffeef7fe43777ffdffab9dbad6f7eed5fff9bfec4affdefbfaddf35bf5efbff9ffff9dfd7dbf97fbfcdfaddfeffbf95f75f\",\"sync_committee_signature\":\"0x81fdf76e797f81b0116a1c1ae5200b613c8041115223cd89e8bd5477aab13de6097a9ebf42b130c59527bbb4c96811b809353a17c717549f82d4bd336068ef0b99b1feebd4d2432a69fa77fac12b78f1fcc9d7b59edbeb381adf10b15bc4a520\"},\"execution_payload\":{\"parent_hash\":\"0x14c2242a8cfbce559e84c391f5f16d10d7719751b8558873012dc88ae5a193e8\",\"fee_recipient\":\"$1\",\"state_root\":\"0xdf8d96b2c292736d39e72e25802c2744d34d3d3c616de5b362425cab01f72fa5\",\"receipts_root\":\"0x4938a2bf640846d213b156a1a853548b369cd02917fa63d8766ab665d7930bac\",\"logs_bloom\":\"0x298610600038408c201080013832408850a00bc8f801920121840030a015310010e2a0e0108628110552062811441c84802f43825c4fc82140b036c58025a28800054c80a44025c052090a0f2c209a0400058040019ea0008e589084078048050880930113a2894082e0112408b088382402a851621042212aa40018a408d07e178c68691486411aa9a2809043b000a04c040000065a030028018540b04b1820271d00821b00c29059095022322c10a530060223240416140190056608200063c82248274ba8f0098e402041cd9f451031481a1010b8220824833520490221071898802d206348449116812280014a10a2d1c210100a30010802490f0a221849\",\"prev_randao\":\"0xc061711e135cd40531ec3ee29d17d3824c0e5f80d07f721e792ab83240aa0ab5\",\"block_number\":\"8737497\",\"gas_limit\":\"30000000\",\"gas_used\":\"16367052\",\"timestamp\":\"1680080352\",\"extra_data\":\"0xd883010b05846765746888676f312e32302e32856c696e7578\",\"base_fee_per_gas\":\"231613172261\",\"block_hash\":\"0x5aa9fd22a9238925adb2b038fd6eafc77adabf554051db5bc16ae5168a52eff6\",\"transactions\":[],\"withdrawals\":[]},\"bls_to_execution_changes\":[]}}}" CapellaBlock = "{\"message\":{\"slot\":\"5297696\",\"proposer_index\":\"153094\",\"parent_root\":\"0xe6106533af9be918120ead7440a8006c7f123cc3cb7daf1f11d951864abea014\",\"state_root\":\"0xf86196d34500ca25d1f4e7431d4d52f6f85540bcaf97dd0d2ad9ecdb3eebcdf0\",\"body\":{\"randao_reveal\":\"0xa7efee3d5ddceb60810b23e3b5d39734696418f41dfd13a0851c7be7a72acbdceaa61e1db27513801917d72519d1c1040ccfed829faf06abe06d9964949554bf4369134b66de715ea49eb4fecf3e2b7e646f1764a1993e31e53dbc6557929c12\",\"eth1_data\":{\"deposit_root\":\"0x8ec87d7219a3c873fff3bfe206b4f923d1b471ce4ff9d6d6ecc162ef07825e14\",\"deposit_count\":\"259476\",\"block_hash\":\"0x877b6f8332c7397251ff3f0c5cecec105ff7d4cb78251b47f91fd15a86a565ab\"},\"graffiti\":\"\",\"proposer_slashings\":[],\"attester_slashings\":[],\"attestations\":[],\"deposits\":[],\"voluntary_exits\":[],\"sync_aggregate\":{\"sync_committee_bits\":\"0x733dfda7f5ffde5ade73367fcbf7fffeef7fe43777ffdffab9dbad6f7eed5fff9bfec4affdefbfaddf35bf5efbff9ffff9dfd7dbf97fbfcdfaddfeffbf95f75f\",\"sync_committee_signature\":\"0x81fdf76e797f81b0116a1c1ae5200b613c8041115223cd89e8bd5477aab13de6097a9ebf42b130c59527bbb4c96811b809353a17c717549f82d4bd336068ef0b99b1feebd4d2432a69fa77fac12b78f1fcc9d7b59edbeb381adf10b15bc4a520\"},\"execution_payload\":{\"parent_hash\":\"0x14c2242a8cfbce559e84c391f5f16d10d7719751b8558873012dc88ae5a193e8\",\"fee_recipient\":\"$1\",\"state_root\":\"0xdf8d96b2c292736d39e72e25802c2744d34d3d3c616de5b362425cab01f72fa5\",\"receipts_root\":\"0x4938a2bf640846d213b156a1a853548b369cd02917fa63d8766ab665d7930bac\",\"logs_bloom\":\"0x298610600038408c201080013832408850a00bc8f801920121840030a015310010e2a0e0108628110552062811441c84802f43825c4fc82140b036c58025a28800054c80a44025c052090a0f2c209a0400058040019ea0008e589084078048050880930113a2894082e0112408b088382402a851621042212aa40018a408d07e178c68691486411aa9a2809043b000a04c040000065a030028018540b04b1820271d00821b00c29059095022322c10a530060223240416140190056608200063c82248274ba8f0098e402041cd9f451031481a1010b8220824833520490221071898802d206348449116812280014a10a2d1c210100a30010802490f0a221849\",\"prev_randao\":\"0xc061711e135cd40531ec3ee29d17d3824c0e5f80d07f721e792ab83240aa0ab5\",\"block_number\":\"8737497\",\"gas_limit\":\"30000000\",\"gas_used\":\"16367052\",\"timestamp\":\"1680080352\",\"extra_data\":\"0xd883010b05846765746888676f312e32302e32856c696e7578\",\"base_fee_per_gas\":\"231613172261\",\"block_hash\":\"0x5aa9fd22a9238925adb2b038fd6eafc77adabf554051db5bc16ae5168a52eff6\",\"transactions\":[],\"withdrawals\":[]},\"bls_to_execution_changes\":[]}},\"signature\":\"$2\"}"
DenebBlockContents = "{\"version\":\"deneb\",\"data\":{\"block\":{\"slot\":\"5297696\",\"proposer_index\":\"153094\",\"parent_root\":\"0xe6106533af9be918120ead7440a8006c7f123cc3cb7daf1f11d951864abea014\",\"state_root\":\"0xf86196d34500ca25d1f4e7431d4d52f6f85540bcaf97dd0d2ad9ecdb3eebcdf0\",\"body\":{\"randao_reveal\":\"0xa7efee3d5ddceb60810b23e3b5d39734696418f41dfd13a0851c7be7a72acbdceaa61e1db27513801917d72519d1c1040ccfed829faf06abe06d9964949554bf4369134b66de715ea49eb4fecf3e2b7e646f1764a1993e31e53dbc6557929c12\",\"eth1_data\":{\"deposit_root\":\"0x8ec87d7219a3c873fff3bfe206b4f923d1b471ce4ff9d6d6ecc162ef07825e14\",\"deposit_count\":\"259476\",\"block_hash\":\"0x877b6f8332c7397251ff3f0c5cecec105ff7d4cb78251b47f91fd15a86a565ab\"},\"graffiti\":\"\",\"proposer_slashings\":[],\"attester_slashings\":[],\"attestations\":[],\"deposits\":[],\"voluntary_exits\":[],\"sync_aggregate\":{\"sync_committee_bits\":\"0x733dfda7f5ffde5ade73367fcbf7fffeef7fe43777ffdffab9dbad6f7eed5fff9bfec4affdefbfaddf35bf5efbff9ffff9dfd7dbf97fbfcdfaddfeffbf95f75f\",\"sync_committee_signature\":\"0x81fdf76e797f81b0116a1c1ae5200b613c8041115223cd89e8bd5477aab13de6097a9ebf42b130c59527bbb4c96811b809353a17c717549f82d4bd336068ef0b99b1feebd4d2432a69fa77fac12b78f1fcc9d7b59edbeb381adf10b15bc4a520\"},\"execution_payload\":{\"parent_hash\":\"0x14c2242a8cfbce559e84c391f5f16d10d7719751b8558873012dc88ae5a193e8\",\"fee_recipient\":\"$1\",\"state_root\":\"0xdf8d96b2c292736d39e72e25802c2744d34d3d3c616de5b362425cab01f72fa5\",\"receipts_root\":\"0x4938a2bf640846d213b156a1a853548b369cd02917fa63d8766ab665d7930bac\",\"logs_bloom\":\"0x298610600038408c201080013832408850a00bc8f801920121840030a015310010e2a0e0108628110552062811441c84802f43825c4fc82140b036c58025a28800054c80a44025c052090a0f2c209a0400058040019ea0008e589084078048050880930113a2894082e0112408b088382402a851621042212aa40018a408d07e178c68691486411aa9a2809043b000a04c040000065a030028018540b04b1820271d00821b00c29059095022322c10a530060223240416140190056608200063c82248274ba8f0098e402041cd9f451031481a1010b8220824833520490221071898802d206348449116812280014a10a2d1c210100a30010802490f0a221849\",\"prev_randao\":\"0xc061711e135cd40531ec3ee29d17d3824c0e5f80d07f721e792ab83240aa0ab5\",\"block_number\":\"8737497\",\"gas_limit\":\"30000000\",\"gas_used\":\"16367052\",\"timestamp\":\"1680080352\",\"extra_data\":\"0xd883010b05846765746888676f312e32302e32856c696e7578\",\"base_fee_per_gas\":\"231613172261\",\"block_hash\":\"0x5aa9fd22a9238925adb2b038fd6eafc77adabf554051db5bc16ae5168a52eff6\",\"transactions\":[],\"withdrawals\":[],\"blob_gas_used\":\"2316131761\",\"excess_blob_gas\":\"231613172261\"},\"bls_to_execution_changes\":[],\"blob_kzg_commitments\":[]}},\"kzg_proofs\":[],\"blobs\":[]}}" DenebBlockContents = "{\"signed_block\":{\"message\":{\"slot\":\"5297696\",\"proposer_index\":\"153094\",\"parent_root\":\"0xe6106533af9be918120ead7440a8006c7f123cc3cb7daf1f11d951864abea014\",\"state_root\":\"0xf86196d34500ca25d1f4e7431d4d52f6f85540bcaf97dd0d2ad9ecdb3eebcdf0\",\"body\":{\"randao_reveal\":\"0xa7efee3d5ddceb60810b23e3b5d39734696418f41dfd13a0851c7be7a72acbdceaa61e1db27513801917d72519d1c1040ccfed829faf06abe06d9964949554bf4369134b66de715ea49eb4fecf3e2b7e646f1764a1993e31e53dbc6557929c12\",\"eth1_data\":{\"deposit_root\":\"0x8ec87d7219a3c873fff3bfe206b4f923d1b471ce4ff9d6d6ecc162ef07825e14\",\"deposit_count\":\"259476\",\"block_hash\":\"0x877b6f8332c7397251ff3f0c5cecec105ff7d4cb78251b47f91fd15a86a565ab\"},\"graffiti\":\"\",\"proposer_slashings\":[],\"attester_slashings\":[],\"attestations\":[],\"deposits\":[],\"voluntary_exits\":[],\"sync_aggregate\":{\"sync_committee_bits\":\"0x733dfda7f5ffde5ade73367fcbf7fffeef7fe43777ffdffab9dbad6f7eed5fff9bfec4affdefbfaddf35bf5efbff9ffff9dfd7dbf97fbfcdfaddfeffbf95f75f\",\"sync_committee_signature\":\"0x81fdf76e797f81b0116a1c1ae5200b613c8041115223cd89e8bd5477aab13de6097a9ebf42b130c59527bbb4c96811b809353a17c717549f82d4bd336068ef0b99b1feebd4d2432a69fa77fac12b78f1fcc9d7b59edbeb381adf10b15bc4a520\"},\"execution_payload\":{\"parent_hash\":\"0x14c2242a8cfbce559e84c391f5f16d10d7719751b8558873012dc88ae5a193e8\",\"fee_recipient\":\"$1\",\"state_root\":\"0xdf8d96b2c292736d39e72e25802c2744d34d3d3c616de5b362425cab01f72fa5\",\"receipts_root\":\"0x4938a2bf640846d213b156a1a853548b369cd02917fa63d8766ab665d7930bac\",\"logs_bloom\":\"0x298610600038408c201080013832408850a00bc8f801920121840030a015310010e2a0e0108628110552062811441c84802f43825c4fc82140b036c58025a28800054c80a44025c052090a0f2c209a0400058040019ea0008e589084078048050880930113a2894082e0112408b088382402a851621042212aa40018a408d07e178c68691486411aa9a2809043b000a04c040000065a030028018540b04b1820271d00821b00c29059095022322c10a530060223240416140190056608200063c82248274ba8f0098e402041cd9f451031481a1010b8220824833520490221071898802d206348449116812280014a10a2d1c210100a30010802490f0a221849\",\"prev_randao\":\"0xc061711e135cd40531ec3ee29d17d3824c0e5f80d07f721e792ab83240aa0ab5\",\"block_number\":\"8737497\",\"gas_limit\":\"30000000\",\"gas_used\":\"16367052\",\"timestamp\":\"1680080352\",\"extra_data\":\"0xd883010b05846765746888676f312e32302e32856c696e7578\",\"base_fee_per_gas\":\"231613172261\",\"block_hash\":\"0x5aa9fd22a9238925adb2b038fd6eafc77adabf554051db5bc16ae5168a52eff6\",\"transactions\":[],\"withdrawals\":[],\"blob_gas_used\":\"2316131761\",\"excess_blob_gas\":\"231613172261\"},\"bls_to_execution_changes\":[],\"blob_kzg_commitments\":[]}},\"signature\":\"$2\"},\"kzg_proofs\":[],\"blobs\":[]}"
SigningNodeAddress = "127.0.0.1" SigningNodeAddress = "127.0.0.1"
defaultSigningNodePort = 35333 defaultSigningNodePort = 35333
@ -84,43 +82,42 @@ func getNodePort(basePort: int, rt: RemoteSignerType): int =
of RemoteSignerType.VerifyingWeb3Signer: of RemoteSignerType.VerifyingWeb3Signer:
basePort + 1 basePort + 1
func init(T: type ForkedBeaconBlock, contents: ProduceBlockResponseV2): T = func init(
T: type ForkedBeaconBlock, contents: RestPublishedSignedBlockContents): T =
case contents.kind case contents.kind
of ConsensusFork.Phase0 .. ConsensusFork.Bellatrix: of ConsensusFork.Phase0 .. ConsensusFork.Bellatrix:
raiseAssert "Unsupported fork" raiseAssert "Unsupported fork"
of ConsensusFork.Capella: of ConsensusFork.Capella:
return ForkedBeaconBlock.init(contents.capellaData) return ForkedBeaconBlock.init(contents.capellaData.message)
of ConsensusFork.Deneb: of ConsensusFork.Deneb:
return ForkedBeaconBlock.init(contents.denebData.`block`) return ForkedBeaconBlock.init(contents.denebData.signed_block.message)
of ConsensusFork.Electra: of ConsensusFork.Electra:
debugComment "probably like the deneb case" return ForkedBeaconBlock.init(contents.electraData.signed_block.message)
return default(T)
proc getBlock( proc getBlock(
fork: ConsensusFork, fork: ConsensusFork,
feeRecipient = SigningExpectedFeeRecipient feeRecipient = SigningExpectedFeeRecipient
): ForkedBeaconBlock {.raises: [ResultError[cstring]].} = ): ForkedBeaconBlock {.raises: [ResultError[cstring]].} =
let let blckData =
blckData = try:
try: case fork
case fork of ConsensusFork.Phase0 .. ConsensusFork.Bellatrix:
of ConsensusFork.Phase0 .. ConsensusFork.Bellatrix: raiseAssert "Unsupported fork" raiseAssert "Unsupported fork"
of ConsensusFork.Capella: CapellaBlock % [feeRecipient] of ConsensusFork.Capella: CapellaBlock % [feeRecipient, SomeSignature]
of ConsensusFork.Deneb: DenebBlockContents % [feeRecipient] of ConsensusFork.Deneb:
of ConsensusFork.Electra: DenebBlockContents % [feeRecipient, SomeSignature]
debugComment "electra test signing node getblock" of ConsensusFork.Electra:
raiseAssert "electra unsupported" debugComment "electra test signing node getblock"
except ValueError: raiseAssert "electra unsupported"
# https://github.com/nim-lang/Nim/pull/23356 except ValueError:
raiseAssert "Arguments match the format string" # https://github.com/nim-lang/Nim/pull/23356
contentType = ContentTypeData( raiseAssert "Arguments match the format string"
mediaType: MediaType.init("application/json"))
let b = decodeBytes(ProduceBlockResponseV2, try:
blckData.toOpenArrayByte(0, len(blckData) - 1), ForkedBeaconBlock.init(RestJson.decode(
Opt.some(contentType), blckData, RestPublishedSignedBlockContents))
$fork).tryGet() except SerializationError:
ForkedBeaconBlock.init(b) raiseAssert "malformed block contents"
func init(t: typedesc[Web3SignerForkedBeaconBlock], func init(t: typedesc[Web3SignerForkedBeaconBlock],
forked: ForkedBeaconBlock): Web3SignerForkedBeaconBlock = forked: ForkedBeaconBlock): Web3SignerForkedBeaconBlock =
@ -371,6 +368,8 @@ let
fatal "Invalid base port arg", basePort = basePortStr, exc = exc.msg fatal "Invalid base port arg", basePort = basePortStr, exc = exc.msg
quit 1 quit 1
from std/algorithm import sorted
block: block:
let res = createTestDir(RemoteSignerType.Web3Signer) let res = createTestDir(RemoteSignerType.Web3Signer)
doAssert(res.isOk()) doAssert(res.isOk())

View File

@ -103,7 +103,7 @@ suite "Sync committee pool":
privkey2 = MockPrivKeys[1.ValidatorIndex] privkey2 = MockPrivKeys[1.ValidatorIndex]
bid1 = BlockId( bid1 = BlockId(
slot: Slot(cfg.BELLATRIX_FORK_EPOCH.start_slot - 1), slot: cfg.BELLATRIX_FORK_EPOCH.start_slot - 1,
root: eth2digest(@[1.byte])) root: eth2digest(@[1.byte]))
sig1 = get_sync_committee_message_signature( sig1 = get_sync_committee_message_signature(

View File

@ -369,7 +369,7 @@ suite "SyncManager test suite":
aq = newAsyncQueue[BlockEntry]() aq = newAsyncQueue[BlockEntry]()
chunkSize = 3'u64 chunkSize = 3'u64
numberOfChunks = 3'u64 numberOfChunks = 3'u64
finishSlot = Slot(startSlot + numberOfChunks * chunkSize - 1'u64) finishSlot = startSlot + numberOfChunks * chunkSize - 1'u64
queueSize = 1 queueSize = 1
var counter = var counter =
@ -734,7 +734,7 @@ suite "SyncManager test suite":
startSlot = Slot(0) startSlot = Slot(0)
chunkSize = SLOTS_PER_EPOCH chunkSize = SLOTS_PER_EPOCH
numberOfChunks = 4'u64 numberOfChunks = 4'u64
finishSlot = Slot(startSlot + numberOfChunks * chunkSize - 1'u64) finishSlot = startSlot + numberOfChunks * chunkSize - 1'u64
queueSize = 1 queueSize = 1
var counter = int(startSlot) var counter = int(startSlot)
@ -855,7 +855,7 @@ suite "SyncManager test suite":
startSlot = Slot(0) startSlot = Slot(0)
chunkSize = SLOTS_PER_EPOCH chunkSize = SLOTS_PER_EPOCH
numberOfChunks = 1'u64 numberOfChunks = 1'u64
finishSlot = Slot(startSlot + numberOfChunks * chunkSize - 1'u64) finishSlot = startSlot + numberOfChunks * chunkSize - 1'u64
queueSize = 1 queueSize = 1
var counter = int(startSlot) var counter = int(startSlot)
@ -902,7 +902,7 @@ suite "SyncManager test suite":
startSlot = Slot(0) startSlot = Slot(0)
chunkSize = SLOTS_PER_EPOCH chunkSize = SLOTS_PER_EPOCH
numberOfChunks = 4'u64 numberOfChunks = 4'u64
finishSlot = Slot(startSlot + numberOfChunks * chunkSize - 1'u64) finishSlot = startSlot + numberOfChunks * chunkSize - 1'u64
queueSize = 1 queueSize = 1
var var

@ -1 +1 @@
Subproject commit 5de55bab8c4e161d3ae1c39f284c26262b5ebf82 Subproject commit 695d1c9dbec4fa0f746a15df259a19fed49e075e