Merge branch 'dev/etan/bd-serialization' into feat/eip-7495

This commit is contained in:
Etan Kissling 2024-06-13 13:41:04 +02:00
commit 728d7db66e
No known key found for this signature in database
GPG Key ID: B21DA824C5A3D03D
82 changed files with 622 additions and 333 deletions

View File

@ -213,7 +213,7 @@ jobs:
devbuild: devbuild:
name: "Developer builds" name: "Developer builds"
runs-on: ubuntu-latest runs-on: ['self-hosted','ubuntu-22.04']
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4

10
.gitmodules vendored
View File

@ -5,6 +5,11 @@
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0). # * Apache v2 license (license terms in the root directory or at http://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.
[submodule "vendor/mainnet"]
path = vendor/mainnet
url = https://github.com/eth-clients/mainnet.git
ignore = untracked
branch = main
[submodule "vendor/nim-eth2-scenarios"] [submodule "vendor/nim-eth2-scenarios"]
path = vendor/nim-eth2-scenarios path = vendor/nim-eth2-scenarios
url = https://github.com/status-im/nim-eth2-scenarios url = https://github.com/status-im/nim-eth2-scenarios
@ -170,11 +175,6 @@
url = https://github.com/status-im/nim-presto.git url = https://github.com/status-im/nim-presto.git
ignore = untracked ignore = untracked
branch = master branch = master
[submodule "vendor/eth2-networks"]
path = vendor/eth2-networks
url = https://github.com/eth-clients/eth2-networks.git
ignore = untracked
branch = master
[submodule "vendor/nim-taskpools"] [submodule "vendor/nim-taskpools"]
path = vendor/nim-taskpools path = vendor/nim-taskpools
url = https://github.com/status-im/nim-taskpools url = https://github.com/status-im/nim-taskpools

View File

@ -907,12 +907,14 @@ OK: 1/1 Fail: 0/1 Skip: 0/1
+ getAggregatedAttestationDataScore() test vectors OK + getAggregatedAttestationDataScore() test vectors OK
+ getAttestationDataScore() test vectors OK + getAttestationDataScore() test vectors OK
+ getLiveness() response deserialization test OK + getLiveness() response deserialization test OK
+ getProduceBlockResponseV3Score() default test OK
+ getProduceBlockResponseV3Score() test vectors OK
+ getSyncCommitteeContributionDataScore() test vectors OK + getSyncCommitteeContributionDataScore() test vectors OK
+ getSyncCommitteeMessageDataScore() test vectors OK + getSyncCommitteeMessageDataScore() test vectors OK
+ getUniqueVotes() test vectors OK + getUniqueVotes() test vectors OK
+ normalizeUri() test vectors OK + normalizeUri() test vectors OK
``` ```
OK: 12/12 Fail: 0/12 Skip: 0/12 OK: 14/14 Fail: 0/14 Skip: 0/14
## Validator change pool testing suite ## Validator change pool testing suite
```diff ```diff
+ addValidatorChangeMessage/getAttesterSlashingMessage OK + addValidatorChangeMessage/getAttesterSlashingMessage OK

View File

@ -593,7 +593,7 @@ define MAKE_DEPOSIT
build/deposit_contract sendDeposits \ build/deposit_contract sendDeposits \
$(2) \ $(2) \
--deposit-contract=$$(cat vendor/eth2-networks/shared/$(1)/deposit_contract.txt) \ --deposit-contract=$$(cat vendor/$(1)/metadata/deposit_contract.txt) \
--deposits-file=nbc-$(1)-deposits.json \ --deposits-file=nbc-$(1)-deposits.json \
--min-delay=$(DEPOSITS_DELAY) \ --min-delay=$(DEPOSITS_DELAY) \
--max-delay=$(DEPOSITS_DELAY) \ --max-delay=$(DEPOSITS_DELAY) \

View File

@ -73,7 +73,7 @@ proc initLightClient*(
headBlockHash = blckPayload.block_hash, headBlockHash = blckPayload.block_hash,
safeBlockHash = beaconHead.safeExecutionBlockHash, safeBlockHash = beaconHead.safeExecutionBlockHash,
finalizedBlockHash = beaconHead.finalizedExecutionBlockHash, finalizedBlockHash = beaconHead.finalizedExecutionBlockHash,
payloadAttributes = none attributes) payloadAttributes = Opt.none attributes)
case node.dag.cfg.consensusForkAtEpoch( case node.dag.cfg.consensusForkAtEpoch(
forkyBlck.message.slot.epoch) forkyBlck.message.slot.epoch)

View File

@ -1047,7 +1047,7 @@ type
monitoringType* {. monitoringType* {.
desc: "Enable block monitoring which are seen by beacon node (BETA)" desc: "Enable block monitoring which are seen by beacon node (BETA)"
defaultValue: BlockMonitoringType.Disabled defaultValue: BlockMonitoringType.Event
name: "block-monitor-type".}: BlockMonitoringType name: "block-monitor-type".}: BlockMonitoringType
SigningNodeConf* = object SigningNodeConf* = object

View File

@ -2408,7 +2408,7 @@ proc updateHead*(
if dag.headState.kind > lastHeadKind: if dag.headState.kind > lastHeadKind:
case dag.headState.kind case dag.headState.kind
of ConsensusFork.Phase0 .. ConsensusFork.Bellatrix, ConsensusFork.Electra: of ConsensusFork.Phase0 .. ConsensusFork.Bellatrix:
discard discard
of ConsensusFork.Capella: of ConsensusFork.Capella:
if dag.vanityLogs.onUpgradeToCapella != nil: if dag.vanityLogs.onUpgradeToCapella != nil:
@ -2416,6 +2416,9 @@ proc updateHead*(
of ConsensusFork.Deneb: of ConsensusFork.Deneb:
if dag.vanityLogs.onUpgradeToDeneb != nil: if dag.vanityLogs.onUpgradeToDeneb != nil:
dag.vanityLogs.onUpgradeToDeneb() dag.vanityLogs.onUpgradeToDeneb()
of ConsensusFork.Electra:
if dag.vanityLogs.onUpgradeToElectra != nil:
dag.vanityLogs.onUpgradeToElectra()
if dag.vanityLogs.onKnownBlsToExecutionChange != nil and if dag.vanityLogs.onKnownBlsToExecutionChange != nil and
checkBlsToExecutionChanges( checkBlsToExecutionChanges(

View File

@ -184,7 +184,7 @@ proc updateExecutionClientHead*(
headBlockHash = headExecutionBlockHash, headBlockHash = headExecutionBlockHash,
safeBlockHash = newHead.safeExecutionBlockHash, safeBlockHash = newHead.safeExecutionBlockHash,
finalizedBlockHash = newHead.finalizedExecutionBlockHash, finalizedBlockHash = newHead.finalizedExecutionBlockHash,
payloadAttributes = none attributes) payloadAttributes = Opt.none attributes)
# Can't use dag.head here because it hasn't been updated yet # Can't use dag.head here because it hasn't been updated yet
let let
@ -374,7 +374,7 @@ proc runProposalForkchoiceUpdated*(
let (status, _) = await self.elManager.forkchoiceUpdated( let (status, _) = await self.elManager.forkchoiceUpdated(
headBlockHash, safeBlockHash, headBlockHash, safeBlockHash,
beaconHead.finalizedExecutionBlockHash, beaconHead.finalizedExecutionBlockHash,
payloadAttributes = some fcPayloadAttributes) payloadAttributes = Opt.some fcPayloadAttributes)
debug "Fork-choice updated for proposal", status debug "Fork-choice updated for proposal", status
static: doAssert high(ConsensusFork) == ConsensusFork.Electra static: doAssert high(ConsensusFork) == ConsensusFork.Electra

View File

@ -0,0 +1,28 @@

..-|\_/|
  text .-'..d :.: $
(_: __. :::::$
`-' ? :::: $
\ :::: $
\::::::$
area\ :::::$
|:.::: $
 `| :::: $..__
`.::::::.::.`-.
|:::::::::::::`--.
here `.::::.:::::::::::`---.....
  `.:::::::::::::::::::::::`\
 |:::::::::::::::::::::::::|
 |:::::::::::::::::::::::|:|
  |::::::::::::|::::::::::|:|
':::)___..----\ :::::| .`. \
|:::| | :|`.::::|: : `.`.
() () O  O |:::| |. ||:::| `.: |:|
\ / \ /   |:::| | :|`.:::`. .:`.`.
() ()()  ()  () O () |:::| |: |::::| |::|`.`.
\  / \ // / / |:::| | :||:::| | :| )))
 () ()  O() O ()  () O  () |:::||.:.| () ()::| |:..;((( ()
. \. /. \. // O. /. . \. /. \ /. . \ .'::.'|::'|. /. . /.|::|. ` :.\ `/ .
....()O...O()...\()()....()O...O.()....()|:::| |_M()()....()..:::|.()|: :()..()
\../...\./...\../....\../...\./....\../..|:::|\../....\../...|:::<...\_M/|.....
 ():::::O:::::()::::::():::::O::::::():::|_N_|:()::::::()::::|_N_|::::():::::::

View File

@ -0,0 +1,28 @@
..-|\_/|
text .-'..d :.: $
(_: __. :::::$
`-' ? :::: $
\ :::: $
\::::::$
area \ :::::$
|:.::: $
`| :::: $..__
`.::::::.::.`-.
|:::::::::::::`--.
here `.::::.:::::::::::`---.....
`.:::::::::::::::::::::::`\
|:::::::::::::::::::::::::|
|:::::::::::::::::::::::|:|
|::::::::::::|::::::::::|:|
':::)___..----\ :::::| .`. \
|:::| | :| `.::::|: : `.`.
() () O O |:::| |. | |:::| `.: |:|
\ / \ / |:::| | :| `.:::`. .:`.`.
() ()() () () O () |:::| |: | ::::| |::|`.`.
\ / \ / / / / |:::| | :| |:::| | :| )))
() () O() O () () O () |:::||.:.| () ()::| |:..;((( ()
. \. /. \. // O. /. . \. /. \ /. . \ .'::.'|::'|. /. . /.|::|. ` :.\ `/ .
....()O...O()...\()()....()O...O.()....()|:::| |_M()()....()..:::|.()|: :()..()
\../...\./...\../....\../...\./....\../..|:::|\../....\../...|:::<...\_M/|.....
():::::O:::::()::::::():::::O::::::():::|_N_|:()::::::()::::|_N_|::::():::::::

View File

@ -34,6 +34,10 @@ type
# in case of chain reorgs around the upgrade. # in case of chain reorgs around the upgrade.
onUpgradeToDeneb*: LogProc onUpgradeToDeneb*: LogProc
# Gets displayed on upgrade to Electra. May be displayed multiple times
# in case of chain reorgs around the upgrade.
onUpgradeToElectra*: LogProc
# Created by http://beatscribe.com/ (beatscribe#1008 on Discord) # Created by http://beatscribe.com/ (beatscribe#1008 on Discord)
# These need to be the main body of the log not to be reformatted or escaped. # These need to be the main body of the log not to be reformatted or escaped.
@ -47,3 +51,6 @@ proc capellaBlink*() = notice "\n" & staticRead("capella" / "blink.ans")
proc denebMono*() = notice "\n" & staticRead("deneb" / "mono.txt") proc denebMono*() = notice "\n" & staticRead("deneb" / "mono.txt")
proc denebColor*() = notice "\n" & staticRead("deneb" / "color.ans") proc denebColor*() = notice "\n" & staticRead("deneb" / "color.ans")
proc electraMono*() = notice "\n" & staticRead("electra" / "mono.txt")
proc electraColor*() = notice "\n" & staticRead("electra" / "color.ans")

View File

@ -123,25 +123,25 @@ contract(DepositContract):
proc deployContract*(web3: Web3, code: seq[byte]): Future[ReceiptObject] {.async.} = proc deployContract*(web3: Web3, code: seq[byte]): Future[ReceiptObject] {.async.} =
let tr = TransactionArgs( let tr = TransactionArgs(
`from`: web3.defaultAccount.some, `from`: Opt.some web3.defaultAccount,
data: code.some, data: Opt.some code,
gas: Quantity(3000000).some, gas: Opt.some Quantity(3000000),
gasPrice: Quantity(1).some) gasPrice: Opt.some Quantity(1))
let r = await web3.send(tr) let r = await web3.send(tr)
result = await web3.getMinedTransactionReceipt(r) result = await web3.getMinedTransactionReceipt(r)
proc sendEth(web3: Web3, to: Eth1Address, valueEth: int): Future[TxHash] = proc sendEth(web3: Web3, to: Eth1Address, valueEth: int): Future[TxHash] =
let tr = TransactionArgs( let tr = TransactionArgs(
`from`: web3.defaultAccount.some, `from`: Opt.some web3.defaultAccount,
# TODO: Force json-rpc to generate 'data' field # TODO: Force json-rpc to generate 'data' field
# should not be needed anymore, new execution-api schema # should not be needed anymore, new execution-api schema
# is using `input` field # is using `input` field
data: some(newSeq[byte]()), data: Opt.some(newSeq[byte]()),
gas: Quantity(3000000).some, gas: Opt.some Quantity(3000000),
gasPrice: Quantity(1).some, gasPrice: Opt.some Quantity(1),
value: some(valueEth.u256 * 1000000000000000000.u256), value: Opt.some(valueEth.u256 * 1000000000000000000.u256),
to: some(to)) to: Opt.some(to))
web3.send(tr) web3.send(tr)
type type
@ -153,7 +153,7 @@ proc ethToWei(eth: UInt256): UInt256 =
proc initWeb3(web3Url, privateKey: string): Future[Web3] {.async.} = proc initWeb3(web3Url, privateKey: string): Future[Web3] {.async.} =
result = await newWeb3(web3Url) result = await newWeb3(web3Url)
if privateKey.len != 0: if privateKey.len != 0:
result.privateKey = some(PrivateKey.fromHex(privateKey)[]) result.privateKey = Opt.some(PrivateKey.fromHex(privateKey)[])
else: else:
let accounts = await result.provider.eth_accounts() let accounts = await result.provider.eth_accounts()
doAssert(accounts.len > 0) doAssert(accounts.len > 0)

View File

@ -106,7 +106,7 @@ type
Running, Closing, Closed Running, Closing, Closed
ELManager* = ref object ELManager* = ref object
eth1Network: Option[Eth1Network] eth1Network: Opt[Eth1Network]
## If this value is supplied the EL manager will check whether ## If this value is supplied the EL manager will check whether
## all configured EL nodes are connected to the same network. ## all configured EL nodes are connected to the same network.
@ -133,7 +133,7 @@ type
## also includes blocks without deposits because we must ## also includes blocks without deposits because we must
## vote for a block only if it's part of our known history. ## vote for a block only if it's part of our known history.
syncTargetBlock: Option[Eth1BlockNumber] syncTargetBlock: Opt[Eth1BlockNumber]
chainSyncingLoopFut: Future[void] chainSyncingLoopFut: Future[void]
exchangeTransitionConfigurationLoopFut: Future[void] exchangeTransitionConfigurationLoopFut: Future[void]
@ -177,7 +177,7 @@ type
depositContractSyncStatus: DepositContractSyncStatus depositContractSyncStatus: DepositContractSyncStatus
## Are we sure that this EL has synced the deposit contract? ## Are we sure that this EL has synced the deposit contract?
lastPayloadId: Option[PayloadID] lastPayloadId: Opt[PayloadID]
FullBlockId* = object FullBlockId* = object
number: Eth1BlockNumber number: Eth1BlockNumber
@ -419,7 +419,7 @@ func asConsensusType*(payloadWithValue: BellatrixExecutionPayloadWithValue):
executionPayload: payloadWithValue.executionPayload.asConsensusType, executionPayload: payloadWithValue.executionPayload.asConsensusType,
blockValue: payloadWithValue.blockValue) blockValue: payloadWithValue.blockValue)
template maybeDeref[T](o: Option[T]): T = o.get template maybeDeref[T](o: Opt[T]): T = o.get
template maybeDeref[V](v: V): V = v template maybeDeref[V](v: V): V = v
func asConsensusType*(rpcExecutionPayload: ExecutionPayloadV1OrV2|ExecutionPayloadV2): func asConsensusType*(rpcExecutionPayload: ExecutionPayloadV1OrV2|ExecutionPayloadV2):
@ -779,15 +779,15 @@ func areSameAs(expectedParams: Option[NextExpectedPayloadParams],
proc forkchoiceUpdated(rpcClient: RpcClient, proc forkchoiceUpdated(rpcClient: RpcClient,
state: ForkchoiceStateV1, state: ForkchoiceStateV1,
payloadAttributes: Option[PayloadAttributesV1] | payloadAttributes: Opt[PayloadAttributesV1] |
Option[PayloadAttributesV2] | Opt[PayloadAttributesV2] |
Option[PayloadAttributesV3]): Opt[PayloadAttributesV3]):
Future[ForkchoiceUpdatedResponse] = Future[ForkchoiceUpdatedResponse] =
when payloadAttributes is Option[PayloadAttributesV1]: when payloadAttributes is Opt[PayloadAttributesV1]:
rpcClient.engine_forkchoiceUpdatedV1(state, payloadAttributes) rpcClient.engine_forkchoiceUpdatedV1(state, payloadAttributes)
elif payloadAttributes is Option[PayloadAttributesV2]: elif payloadAttributes is Opt[PayloadAttributesV2]:
rpcClient.engine_forkchoiceUpdatedV2(state, payloadAttributes) rpcClient.engine_forkchoiceUpdatedV2(state, payloadAttributes)
elif payloadAttributes is Option[PayloadAttributesV3]: elif payloadAttributes is Opt[PayloadAttributesV3]:
rpcClient.engine_forkchoiceUpdatedV3(state, payloadAttributes) rpcClient.engine_forkchoiceUpdatedV3(state, payloadAttributes)
else: else:
static: doAssert false static: doAssert false
@ -817,7 +817,7 @@ proc getPayloadFromSingleEL(
headBlockHash: headBlock.asBlockHash, headBlockHash: headBlock.asBlockHash,
safeBlockHash: safeBlock.asBlockHash, safeBlockHash: safeBlock.asBlockHash,
finalizedBlockHash: finalizedBlock.asBlockHash), finalizedBlockHash: finalizedBlock.asBlockHash),
some PayloadAttributesV1( Opt.some PayloadAttributesV1(
timestamp: Quantity timestamp, timestamp: Quantity timestamp,
prevRandao: FixedBytes[32] randomData.data, prevRandao: FixedBytes[32] randomData.data,
suggestedFeeRecipient: suggestedFeeRecipient)) suggestedFeeRecipient: suggestedFeeRecipient))
@ -827,7 +827,7 @@ proc getPayloadFromSingleEL(
headBlockHash: headBlock.asBlockHash, headBlockHash: headBlock.asBlockHash,
safeBlockHash: safeBlock.asBlockHash, safeBlockHash: safeBlock.asBlockHash,
finalizedBlockHash: finalizedBlock.asBlockHash), finalizedBlockHash: finalizedBlock.asBlockHash),
some PayloadAttributesV2( Opt.some PayloadAttributesV2(
timestamp: Quantity timestamp, timestamp: Quantity timestamp,
prevRandao: FixedBytes[32] randomData.data, prevRandao: FixedBytes[32] randomData.data,
suggestedFeeRecipient: suggestedFeeRecipient, suggestedFeeRecipient: suggestedFeeRecipient,
@ -841,7 +841,7 @@ proc getPayloadFromSingleEL(
headBlockHash: headBlock.asBlockHash, headBlockHash: headBlock.asBlockHash,
safeBlockHash: safeBlock.asBlockHash, safeBlockHash: safeBlock.asBlockHash,
finalizedBlockHash: finalizedBlock.asBlockHash), finalizedBlockHash: finalizedBlock.asBlockHash),
some PayloadAttributesV3( Opt.some PayloadAttributesV3(
timestamp: Quantity timestamp, timestamp: Quantity timestamp,
prevRandao: FixedBytes[32] randomData.data, prevRandao: FixedBytes[32] randomData.data,
suggestedFeeRecipient: suggestedFeeRecipient, suggestedFeeRecipient: suggestedFeeRecipient,
@ -1341,9 +1341,9 @@ proc sendNewPayload*(
proc forkchoiceUpdatedForSingleEL( proc forkchoiceUpdatedForSingleEL(
connection: ELConnection, connection: ELConnection,
state: ref ForkchoiceStateV1, state: ref ForkchoiceStateV1,
payloadAttributes: Option[PayloadAttributesV1] | payloadAttributes: Opt[PayloadAttributesV1] |
Option[PayloadAttributesV2] | Opt[PayloadAttributesV2] |
Option[PayloadAttributesV3] Opt[PayloadAttributesV3]
): Future[PayloadStatusV1] {.async: (raises: [CatchableError]).} = ): Future[PayloadStatusV1] {.async: (raises: [CatchableError]).} =
let let
rpcClient = await connection.connectedRpcClient() rpcClient = await connection.connectedRpcClient()
@ -1363,10 +1363,10 @@ proc forkchoiceUpdatedForSingleEL(
proc forkchoiceUpdated*( proc forkchoiceUpdated*(
m: ELManager, m: ELManager,
headBlockHash, safeBlockHash, finalizedBlockHash: Eth2Digest, headBlockHash, safeBlockHash, finalizedBlockHash: Eth2Digest,
payloadAttributes: Option[PayloadAttributesV1] | payloadAttributes: Opt[PayloadAttributesV1] |
Option[PayloadAttributesV2] | Opt[PayloadAttributesV2] |
Option[PayloadAttributesV3] Opt[PayloadAttributesV3]
): Future[(PayloadExecutionStatus, Option[BlockHash])] {. ): Future[(PayloadExecutionStatus, Opt[BlockHash])] {.
async: (raises: [CancelledError]).} = async: (raises: [CancelledError]).} =
doAssert not headBlockHash.isZero doAssert not headBlockHash.isZero
@ -1383,16 +1383,16 @@ proc forkchoiceUpdated*(
# payload (`Hash32()` if none yet finalized)" # payload (`Hash32()` if none yet finalized)"
if m.elConnections.len == 0: if m.elConnections.len == 0:
return (PayloadExecutionStatus.syncing, none BlockHash) return (PayloadExecutionStatus.syncing, Opt.none BlockHash)
when payloadAttributes is Option[PayloadAttributesV3]: when payloadAttributes is Opt[PayloadAttributesV3]:
template payloadAttributesV3(): auto = template payloadAttributesV3(): auto =
if payloadAttributes.isSome: if payloadAttributes.isSome:
payloadAttributes.get payloadAttributes.get
else: else:
# As timestamp and prevRandao are both 0, won't false-positive match # As timestamp and prevRandao are both 0, won't false-positive match
(static(default(PayloadAttributesV3))) (static(default(PayloadAttributesV3)))
elif payloadAttributes is Option[PayloadAttributesV2]: elif payloadAttributes is Opt[PayloadAttributesV2]:
template payloadAttributesV3(): auto = template payloadAttributesV3(): auto =
if payloadAttributes.isSome: if payloadAttributes.isSome:
PayloadAttributesV3( PayloadAttributesV3(
@ -1404,7 +1404,7 @@ proc forkchoiceUpdated*(
else: else:
# As timestamp and prevRandao are both 0, won't false-positive match # As timestamp and prevRandao are both 0, won't false-positive match
(static(default(PayloadAttributesV3))) (static(default(PayloadAttributesV3)))
elif payloadAttributes is Option[PayloadAttributesV1]: elif payloadAttributes is Opt[PayloadAttributesV1]:
template payloadAttributesV3(): auto = template payloadAttributesV3(): auto =
if payloadAttributes.isSome: if payloadAttributes.isSome:
PayloadAttributesV3( PayloadAttributesV3(
@ -1489,7 +1489,7 @@ proc forkchoiceUpdated*(
pendingRequests.filterIt(not(it.finished())). pendingRequests.filterIt(not(it.finished())).
mapIt(it.cancelAndWait()) mapIt(it.cancelAndWait())
await noCancel allFutures(pending) await noCancel allFutures(pending)
return (PayloadExecutionStatus.invalid, none BlockHash) return (PayloadExecutionStatus.invalid, Opt.none BlockHash)
elif responseProcessor.selectedResponse.isSome: elif responseProcessor.selectedResponse.isSome:
# We spawn task which will wait for all other responses which are # We spawn task which will wait for all other responses which are
# still pending, after 30.seconds all pending requests will be # still pending, after 30.seconds all pending requests will be
@ -1504,7 +1504,7 @@ proc forkchoiceUpdated*(
pendingRequests.filterIt(not(it.finished())). pendingRequests.filterIt(not(it.finished())).
mapIt(it.cancelAndWait()) mapIt(it.cancelAndWait())
await noCancel allFutures(pending) await noCancel allFutures(pending)
return (PayloadExecutionStatus.syncing, none BlockHash) return (PayloadExecutionStatus.syncing, Opt.none BlockHash)
if len(pendingRequests) == 0: if len(pendingRequests) == 0:
# All requests failed, we will continue our attempts until deadline # All requests failed, we will continue our attempts until deadline
@ -1762,7 +1762,7 @@ proc new*(T: type ELManager,
depositContractBlockHash: Eth2Digest, depositContractBlockHash: Eth2Digest,
db: BeaconChainDB, db: BeaconChainDB,
engineApiUrls: seq[EngineApiUrl], engineApiUrls: seq[EngineApiUrl],
eth1Network: Option[Eth1Network]): T = eth1Network: Opt[Eth1Network]): T =
let let
eth1Chain = Eth1Chain.init( eth1Chain = Eth1Chain.init(
cfg, db, depositContractBlockNumber, depositContractBlockHash) cfg, db, depositContractBlockNumber, depositContractBlockHash)
@ -1847,8 +1847,8 @@ proc syncBlockRange(
await connection.engineApiRequest( await connection.engineApiRequest(
depositContract.getJsonLogs( depositContract.getJsonLogs(
DepositEvent, DepositEvent,
fromBlock = some blockId(currentBlock), fromBlock = Opt.some blockId(currentBlock),
toBlock = some blockId(maxBlockNumberRequested)), toBlock = Opt.some blockId(maxBlockNumberRequested)),
"getLogs", Moment.now(), 30.seconds) "getLogs", Moment.now(), 30.seconds)
except CancelledError as exc: except CancelledError as exc:
debug "Request for deposit logs was interrupted" debug "Request for deposit logs was interrupted"
@ -1956,7 +1956,6 @@ proc startExchangeTransitionConfigurationLoop(
while true: while true:
# https://github.com/ethereum/execution-apis/blob/v1.0.0-beta.3/src/engine/paris.md#specification-3 # https://github.com/ethereum/execution-apis/blob/v1.0.0-beta.3/src/engine/paris.md#specification-3
debug "Exchange transition configuration tick"
await m.exchangeTransitionConfiguration() await m.exchangeTransitionConfiguration()
await sleepAsync(60.seconds) await sleepAsync(60.seconds)
@ -2090,7 +2089,7 @@ proc syncEth1Chain(
latestBlockNumber = latestBlock.number latestBlockNumber = latestBlock.number
m.syncTargetBlock = some( m.syncTargetBlock = Opt.some(
if latestBlock.number > m.cfg.ETH1_FOLLOW_DISTANCE.Eth1BlockNumber: if latestBlock.number > m.cfg.ETH1_FOLLOW_DISTANCE.Eth1BlockNumber:
latestBlock.number - m.cfg.ETH1_FOLLOW_DISTANCE latestBlock.number - m.cfg.ETH1_FOLLOW_DISTANCE
else: else:

View File

@ -8,7 +8,6 @@
{.push raises: [].} {.push raises: [].}
import import
stew/results,
chronicles, chronos, metrics, chronicles, chronos, metrics,
../spec/[forks, signatures, signatures_batch], ../spec/[forks, signatures, signatures_batch],
../sszdump ../sszdump
@ -243,7 +242,7 @@ proc expectValidForkchoiceUpdated(
headBlockHash = headBlockHash, headBlockHash = headBlockHash,
safeBlockHash = safeBlockHash, safeBlockHash = safeBlockHash,
finalizedBlockHash = finalizedBlockHash, finalizedBlockHash = finalizedBlockHash,
payloadAttributes = none headBlockPayloadAttributesType) payloadAttributes = Opt.none headBlockPayloadAttributesType)
receivedExecutionBlockHash = receivedExecutionBlockHash =
when typeof(receivedBlock).kind >= ConsensusFork.Bellatrix: when typeof(receivedBlock).kind >= ConsensusFork.Bellatrix:
receivedBlock.message.body.execution_payload.block_hash receivedBlock.message.body.execution_payload.block_hash
@ -685,7 +684,7 @@ proc storeBlock(
self.consensusManager[].optimisticExecutionBlockHash, self.consensusManager[].optimisticExecutionBlockHash,
safeBlockHash = newHead.get.safeExecutionBlockHash, safeBlockHash = newHead.get.safeExecutionBlockHash,
finalizedBlockHash = newHead.get.finalizedExecutionBlockHash, finalizedBlockHash = newHead.get.finalizedExecutionBlockHash,
payloadAttributes = none attributes) payloadAttributes = Opt.none attributes)
let consensusFork = self.consensusManager.dag.cfg.consensusForkAtEpoch( let consensusFork = self.consensusManager.dag.cfg.consensusForkAtEpoch(
newHead.get.blck.bid.slot.epoch) newHead.get.blck.bid.slot.epoch)

View File

@ -9,8 +9,8 @@
import import
std/tables, std/tables,
stew/results, chronicles, chronos, metrics,
chronicles, chronos, metrics, taskpools, taskpools,
../spec/[helpers, forks], ../spec/[helpers, forks],
../spec/datatypes/[altair, phase0, deneb], ../spec/datatypes/[altair, phase0, deneb],
../consensus_object_pools/[ ../consensus_object_pools/[
@ -122,7 +122,7 @@ type
# ---------------------------------------------------------------- # ----------------------------------------------------------------
dag*: ChainDAGRef dag*: ChainDAGRef
attestationPool*: ref AttestationPool attestationPool*: ref AttestationPool
validatorPool: ref ValidatorPool validatorPool*: ref ValidatorPool
syncCommitteeMsgPool: ref SyncCommitteeMsgPool syncCommitteeMsgPool: ref SyncCommitteeMsgPool
lightClientPool: ref LightClientPool lightClientPool: ref LightClientPool
@ -366,7 +366,8 @@ proc checkForPotentialDoppelganger(
proc processAttestation*( proc processAttestation*(
self: ref Eth2Processor, src: MsgSource, self: ref Eth2Processor, src: MsgSource,
attestation: phase0.Attestation | electra.Attestation, subnet_id: SubnetId, attestation: phase0.Attestation | electra.Attestation, subnet_id: SubnetId,
checkSignature: bool = true): Future[ValidationRes] {.async: (raises: [CancelledError]).} = checkSignature, checkValidator: bool
): Future[ValidationRes] {.async: (raises: [CancelledError]).} =
var wallTime = self.getCurrentBeaconTime() var wallTime = self.getCurrentBeaconTime()
let (afterGenesis, wallSlot) = wallTime.toSlot() let (afterGenesis, wallSlot) = wallTime.toSlot()
@ -393,19 +394,26 @@ proc processAttestation*(
let (attester_index, sig) = v.get() let (attester_index, sig) = v.get()
self[].checkForPotentialDoppelganger(attestation, [attester_index]) if checkValidator and (attester_index in self.validatorPool[]):
warn "A validator client has attempted to send an attestation from " &
"validator that is also managed by the beacon node",
validator_index = attester_index
errReject("An attestation could not be sent from a validator that is " &
"also managed by the beacon node")
else:
self[].checkForPotentialDoppelganger(attestation, [attester_index])
trace "Attestation validated" trace "Attestation validated"
self.attestationPool[].addAttestation( self.attestationPool[].addAttestation(
attestation, [attester_index], sig, wallTime) attestation, [attester_index], sig, wallTime)
self.validatorMonitor[].registerAttestation( self.validatorMonitor[].registerAttestation(
src, wallTime, attestation, attester_index) src, wallTime, attestation, attester_index)
beacon_attestations_received.inc() beacon_attestations_received.inc()
beacon_attestation_delay.observe(delay.toFloatSeconds()) beacon_attestation_delay.observe(delay.toFloatSeconds())
ok() ok()
else: else:
debug "Dropping attestation", reason = $v.error debug "Dropping attestation", reason = $v.error
beacon_attestations_dropped.inc(1, [$v.error[0]]) beacon_attestations_dropped.inc(1, [$v.error[0]])

View File

@ -9,7 +9,6 @@
import import
std/[json, sequtils, times], std/[json, sequtils, times],
stew/saturation_arith,
eth/common/[eth_types_rlp, transaction], eth/common/[eth_types_rlp, transaction],
eth/keys, eth/keys,
eth/p2p/discoveryv5/random2, eth/p2p/discoveryv5/random2,
@ -1254,37 +1253,37 @@ proc ETHExecutionBlockHeaderCreateFromJson(
coinbase: distinctBase(data.miner), coinbase: distinctBase(data.miner),
stateRoot: data.stateRoot.asEth2Digest, stateRoot: data.stateRoot.asEth2Digest,
txRoot: data.transactionsRoot.asEth2Digest, txRoot: data.transactionsRoot.asEth2Digest,
receiptRoot: data.receiptsRoot.asEth2Digest, receiptsRoot: data.receiptsRoot.asEth2Digest,
bloom: distinctBase(data.logsBloom), logsBloom: distinctBase(data.logsBloom),
difficulty: data.difficulty, difficulty: data.difficulty,
blockNumber: distinctBase(data.number).u256, number: distinctBase(data.number),
gasLimit: cast[int64](data.gasLimit), gasLimit: distinctBase(data.gasLimit),
gasUsed: cast[int64](data.gasUsed), gasUsed: distinctBase(data.gasUsed),
timestamp: EthTime(int64.saturate distinctBase(data.timestamp)), timestamp: EthTime(distinctBase(data.timestamp)),
extraData: distinctBase(data.extraData), extraData: distinctBase(data.extraData),
mixDigest: data.mixHash.asEth2Digest, mixHash: data.mixHash.asEth2Digest,
nonce: distinctBase(data.nonce.get), nonce: distinctBase(data.nonce.get),
fee: data.baseFeePerGas, baseFeePerGas: data.baseFeePerGas,
withdrawalsRoot: withdrawalsRoot:
if data.withdrawalsRoot.isSome: if data.withdrawalsRoot.isSome:
some(data.withdrawalsRoot.get.asEth2Digest) Opt.some(data.withdrawalsRoot.get.asEth2Digest)
else: else:
none(ExecutionHash256), Opt.none(ExecutionHash256),
blobGasUsed: blobGasUsed:
if data.blobGasUsed.isSome: if data.blobGasUsed.isSome:
some distinctBase(data.blobGasUsed.get) Opt.some distinctBase(data.blobGasUsed.get)
else: else:
none(uint64), Opt.none(uint64),
excessBlobGas: excessBlobGas:
if data.excessBlobGas.isSome: if data.excessBlobGas.isSome:
some distinctBase(data.excessBlobGas.get) Opt.some distinctBase(data.excessBlobGas.get)
else: else:
none(uint64), Opt.none(uint64),
parentBeaconBlockRoot: parentBeaconBlockRoot:
if data.parentBeaconBlockRoot.isSome: if data.parentBeaconBlockRoot.isSome:
some distinctBase(data.parentBeaconBlockRoot.get.asEth2Digest) Opt.some distinctBase(data.parentBeaconBlockRoot.get.asEth2Digest)
else: else:
none(ExecutionHash256)) Opt.none(ExecutionHash256))
if rlpHash(blockHeader) != executionHash[]: if rlpHash(blockHeader) != executionHash[]:
return nil return nil
@ -1529,15 +1528,15 @@ proc ETHTransactionsCreateFromJson(
chainId: data.chainId.get(0.Quantity).ChainId, chainId: data.chainId.get(0.Quantity).ChainId,
nonce: distinctBase(data.nonce), nonce: distinctBase(data.nonce),
gasPrice: data.gasPrice.GasInt, gasPrice: data.gasPrice.GasInt,
maxPriorityFee: maxPriorityFeePerGas:
distinctBase(data.maxPriorityFeePerGas.get(data.gasPrice)).GasInt, distinctBase(data.maxPriorityFeePerGas.get(data.gasPrice)).GasInt,
maxFee: distinctBase(data.maxFeePerGas.get(data.gasPrice)).GasInt, maxFeePerGas: distinctBase(data.maxFeePerGas.get(data.gasPrice)).GasInt,
gasLimit: distinctBase(data.gas).GasInt, gasLimit: distinctBase(data.gas).GasInt,
to: to:
if data.to.isSome: if data.to.isSome:
some(distinctBase(data.to.get)) Opt.some(distinctBase(data.to.get))
else: else:
none(EthAddress), Opt.none(EthAddress),
value: data.value, value: data.value,
payload: data.input, payload: data.input,
accessList: accessList:
@ -1555,7 +1554,7 @@ proc ETHTransactionsCreateFromJson(
ExecutionHash256(data: distinctBase(it))) ExecutionHash256(data: distinctBase(it)))
else: else:
@[], @[],
V: data.v.int64, V: data.v.uint64,
R: data.r, R: data.r,
S: data.s) S: data.s)
rlpBytes = rlpBytes =
@ -1567,7 +1566,7 @@ proc ETHTransactionsCreateFromJson(
if data.hash.asEth2Digest != hash: if data.hash.asEth2Digest != hash:
return nil return nil
template isEven(x: int64): bool = template isEven(x: uint64): bool =
(x and 1) == 0 (x and 1) == 0
# Compute from execution address # Compute from execution address
@ -1614,9 +1613,9 @@ proc ETHTransactionsCreateFromJson(
chainId: distinctBase(tx.chainId).u256, chainId: distinctBase(tx.chainId).u256,
`from`: ExecutionAddress(data: fromAddress), `from`: ExecutionAddress(data: fromAddress),
nonce: tx.nonce, nonce: tx.nonce,
maxPriorityFeePerGas: tx.maxPriorityFee.uint64, maxPriorityFeePerGas: tx.maxPriorityFeePerGas,
maxFeePerGas: tx.maxFee.uint64, maxFeePerGas: tx.maxFeePerGas,
gas: tx.gasLimit.uint64, gas: tx.gasLimit,
destinationType: destinationType, destinationType: destinationType,
to: ExecutionAddress(data: toAddress), to: ExecutionAddress(data: toAddress),
value: tx.value, value: tx.value,
@ -2178,7 +2177,7 @@ proc ETHReceiptsCreateFromJson(
else: else:
default(ExecutionHash256), default(ExecutionHash256),
cumulativeGasUsed: distinctBase(data.cumulativeGasUsed).GasInt, cumulativeGasUsed: distinctBase(data.cumulativeGasUsed).GasInt,
bloom: distinctBase(data.logsBloom), logsBloom: distinctBase(data.logsBloom),
logs: data.logs.mapIt(Log( logs: data.logs.mapIt(Log(
address: distinctBase(it.address), address: distinctBase(it.address),
topics: it.topics.mapIt(distinctBase(it)), topics: it.topics.mapIt(distinctBase(it)),
@ -2198,7 +2197,7 @@ proc ETHReceiptsCreateFromJson(
root: rec.hash, root: rec.hash,
status: rec.status, status: rec.status,
gasUsed: distinctBase(data.gasUsed), # Validated during sanity checks. gasUsed: distinctBase(data.gasUsed), # Validated during sanity checks.
logsBloom: BloomLogs(data: rec.bloom), logsBloom: BloomLogs(data: rec.logsBloom),
logs: rec.logs.mapIt(ETHLog( logs: rec.logs.mapIt(ETHLog(
address: ExecutionAddress(data: it.address), address: ExecutionAddress(data: it.address),
topics: it.topics.mapIt(Eth2Digest(data: it)), topics: it.topics.mapIt(Eth2Digest(data: it)),

View File

@ -1 +1 @@
../../../vendor/eth2-networks/shared/mainnet/config.yaml ../../../vendor/mainnet/metadata/config.yaml

View File

@ -1 +1 @@
../../../vendor/eth2-networks/shared/mainnet/genesis.ssz ../../../vendor/mainnet/metadata/genesis.ssz

View File

@ -9,7 +9,7 @@
import import
std/[algorithm, sequtils], std/[algorithm, sequtils],
chronos, chronicles, stew/results, chronos, chronicles,
eth/p2p/discoveryv5/[enr, protocol, node, random2], eth/p2p/discoveryv5/[enr, protocol, node, random2],
../spec/datatypes/altair, ../spec/datatypes/altair,
../spec/eth2_ssz_serialization, ../spec/eth2_ssz_serialization,
@ -53,7 +53,7 @@ proc addBootstrapNode*(bootstrapAddr: string,
return return
# Ignore comments in # Ignore comments in
# https://github.com/eth-clients/eth2-networks/blob/063f826a03676c33c95a66306916f18b690d35eb/shared/mainnet/bootstrap_nodes.txt # https://github.com/eth-clients/mainnet/blob/main/metadata/bootstrap_nodes.txt
let enrRes = parseBootstrapAddress(bootstrapAddr.split(" # ")[0]) let enrRes = parseBootstrapAddress(bootstrapAddr.split(" # ")[0])
if enrRes.isOk: if enrRes.isOk:
bootstrapEnrs.add enrRes.value bootstrapEnrs.add enrRes.value
@ -127,7 +127,7 @@ proc queryRandom*(
forkId: ENRForkID, forkId: ENRForkID,
wantedAttnets: AttnetBits, wantedAttnets: AttnetBits,
wantedSyncnets: SyncnetBits, wantedSyncnets: SyncnetBits,
minScore: int): Future[seq[Node]] {.async.} = minScore: int): Future[seq[Node]] {.async: (raises: [CancelledError]).} =
## Perform a discovery query for a random target ## Perform a discovery query for a random target
## (forkId) and matching at least one of the attestation subnets. ## (forkId) and matching at least one of the attestation subnets.
@ -143,7 +143,7 @@ proc queryRandom*(
peerForkId = peerForkId =
try: try:
SSZ.decode(eth2FieldBytes, ENRForkID) SSZ.decode(eth2FieldBytes, ENRForkID)
except SszError as e: except SerializationError as e:
debug "Could not decode the eth2 field of peer", debug "Could not decode the eth2 field of peer",
peer = n.record.toURI(), exception = e.name, msg = e.msg peer = n.record.toURI(), exception = e.name, msg = e.msg
continue continue
@ -156,7 +156,7 @@ proc queryRandom*(
let attnetsNode = let attnetsNode =
try: try:
SSZ.decode(attnetsBytes.get(), AttnetBits) SSZ.decode(attnetsBytes.get(), AttnetBits)
except SszError as e: except SerializationError as e:
debug "Could not decode the attnets ERN bitfield of peer", debug "Could not decode the attnets ERN bitfield of peer",
peer = n.record.toURI(), exception = e.name, msg = e.msg peer = n.record.toURI(), exception = e.name, msg = e.msg
continue continue
@ -170,7 +170,7 @@ proc queryRandom*(
let syncnetsNode = let syncnetsNode =
try: try:
SSZ.decode(syncnetsBytes.get(), SyncnetBits) SSZ.decode(syncnetsBytes.get(), SyncnetBits)
except SszError as e: except SerializationError as e:
debug "Could not decode the syncnets ENR bitfield of peer", debug "Could not decode the syncnets ENR bitfield of peer",
peer = n.record.toURI(), exception = e.name, msg = e.msg peer = n.record.toURI(), exception = e.name, msg = e.msg
continue continue

View File

@ -1550,7 +1550,7 @@ proc getLowSubnets(node: Eth2Node, epoch: Epoch): (AttnetBits, SyncnetBits) =
default(SyncnetBits) default(SyncnetBits)
) )
proc runDiscoveryLoop(node: Eth2Node) {.async.} = proc runDiscoveryLoop(node: Eth2Node) {.async: (raises: [CancelledError]).} =
debug "Starting discovery loop" debug "Starting discovery loop"
while true: while true:

View File

@ -78,7 +78,7 @@ type
# additional checks to ensure we are connecting to a web3 provider # additional checks to ensure we are connecting to a web3 provider
# serving data for the same network. The value can be set to `None` # serving data for the same network. The value can be set to `None`
# for custom networks and testing purposes. # for custom networks and testing purposes.
eth1Network*: Option[Eth1Network] eth1Network*: Opt[Eth1Network]
cfg*: RuntimeConfig cfg*: RuntimeConfig
# Parsing `enr.Records` is still not possible at compile-time # Parsing `enr.Records` is still not possible at compile-time
@ -112,13 +112,13 @@ proc readBootEnr*(path: string): seq[string] {.raises: [IOError].} =
proc loadEth2NetworkMetadata*( proc loadEth2NetworkMetadata*(
path: string, path: string,
eth1Network = none(Eth1Network), eth1Network = Opt.none(Eth1Network),
isCompileTime = false, isCompileTime = false,
downloadGenesisFrom = none(DownloadInfo), downloadGenesisFrom = Opt.none(DownloadInfo),
useBakedInGenesis = none(string) useBakedInGenesis = Opt.none(string)
): Result[Eth2NetworkMetadata, string] {.raises: [IOError, PresetFileError].} = ): Result[Eth2NetworkMetadata, string] {.raises: [IOError, PresetFileError].} =
# Load data in eth2-networks format # Load data in mainnet format
# https://github.com/eth-clients/eth2-networks # https://github.com/eth-clients/mainnet
try: try:
let let
@ -208,9 +208,9 @@ proc loadEth2NetworkMetadata*(
proc loadCompileTimeNetworkMetadata( proc loadCompileTimeNetworkMetadata(
path: string, path: string,
eth1Network = none(Eth1Network), eth1Network = Opt.none(Eth1Network),
useBakedInGenesis = none(string), useBakedInGenesis = Opt.none(string),
downloadGenesisFrom = none(DownloadInfo)): Eth2NetworkMetadata = downloadGenesisFrom = Opt.none(DownloadInfo)): Eth2NetworkMetadata =
if fileExists(path & "/config.yaml"): if fileExists(path & "/config.yaml"):
try: try:
let res = loadEth2NetworkMetadata( let res = loadEth2NetworkMetadata(
@ -255,13 +255,13 @@ when const_preset == "gnosis":
const const
gnosisMetadata = loadCompileTimeNetworkMetadata( gnosisMetadata = loadCompileTimeNetworkMetadata(
vendorDir & "/gnosis-chain-configs/mainnet", vendorDir & "/gnosis-chain-configs/mainnet",
none(Eth1Network), Opt.none(Eth1Network),
useBakedInGenesis = some "gnosis") useBakedInGenesis = Opt.some "gnosis")
chiadoMetadata = loadCompileTimeNetworkMetadata( chiadoMetadata = loadCompileTimeNetworkMetadata(
vendorDir & "/gnosis-chain-configs/chiado", vendorDir & "/gnosis-chain-configs/chiado",
none(Eth1Network), Opt.none(Eth1Network),
useBakedInGenesis = some "chiado") useBakedInGenesis = Opt.some "chiado")
static: static:
for network in [gnosisMetadata, chiadoMetadata]: for network in [gnosisMetadata, chiadoMetadata]:
@ -292,28 +292,28 @@ elif const_preset == "mainnet":
else: else:
const const
mainnetGenesis* = slurp( mainnetGenesis* = slurp(
vendorDir & "/eth2-networks/shared/mainnet/genesis.ssz") vendorDir & "/mainnet/metadata/genesis.ssz")
sepoliaGenesis* = slurp( sepoliaGenesis* = slurp(
vendorDir & "/sepolia/bepolia/genesis.ssz") vendorDir & "/sepolia/bepolia/genesis.ssz")
const const
mainnetMetadata = loadCompileTimeNetworkMetadata( mainnetMetadata = loadCompileTimeNetworkMetadata(
vendorDir & "/eth2-networks/shared/mainnet", vendorDir & "/mainnet/metadata",
some mainnet, Opt.some mainnet,
useBakedInGenesis = some "mainnet") useBakedInGenesis = Opt.some "mainnet")
holeskyMetadata = loadCompileTimeNetworkMetadata( holeskyMetadata = loadCompileTimeNetworkMetadata(
vendorDir & "/holesky/custom_config_data", vendorDir & "/holesky/custom_config_data",
some holesky, Opt.some holesky,
downloadGenesisFrom = some DownloadInfo( downloadGenesisFrom = Opt.some DownloadInfo(
url: "https://github.com/status-im/nimbus-eth2/releases/download/v23.9.1/holesky-genesis.ssz.sz", url: "https://github.com/status-im/nimbus-eth2/releases/download/v23.9.1/holesky-genesis.ssz.sz",
digest: Eth2Digest.fromHex "0x0ea3f6f9515823b59c863454675fefcd1d8b4f2dbe454db166206a41fda060a0")) digest: Eth2Digest.fromHex "0x0ea3f6f9515823b59c863454675fefcd1d8b4f2dbe454db166206a41fda060a0"))
sepoliaMetadata = loadCompileTimeNetworkMetadata( sepoliaMetadata = loadCompileTimeNetworkMetadata(
vendorDir & "/sepolia/bepolia", vendorDir & "/sepolia/bepolia",
some sepolia, Opt.some sepolia,
useBakedInGenesis = some "sepolia") useBakedInGenesis = Opt.some "sepolia")
static: static:
for network in [mainnetMetadata, sepoliaMetadata, holeskyMetadata]: for network in [mainnetMetadata, sepoliaMetadata, holeskyMetadata]:

View File

@ -28,7 +28,7 @@
# name_size = 64-bit length in bytes # name_size = 64-bit length in bytes
eth2_mainnet_genesis_data: eth2_mainnet_genesis_data:
.incbin "eth2-networks/shared/mainnet/genesis.ssz" .incbin "mainnet/metadata/genesis.ssz"
eth2_mainnet_genesis_end: eth2_mainnet_genesis_end:
.global cdecl(eth2_mainnet_genesis_size) .global cdecl(eth2_mainnet_genesis_size)
.p2align 3 .p2align 3

View File

@ -147,14 +147,16 @@ func getVanityLogs(stdoutKind: StdoutLogKind): VanityLogs =
onFinalizedMergeTransitionBlock: bellatrixBlink, onFinalizedMergeTransitionBlock: bellatrixBlink,
onUpgradeToCapella: capellaColor, onUpgradeToCapella: capellaColor,
onKnownBlsToExecutionChange: capellaBlink, onKnownBlsToExecutionChange: capellaBlink,
onUpgradeToDeneb: denebColor) onUpgradeToDeneb: denebColor,
onUpgradeToElectra: electraColor)
of StdoutLogKind.NoColors: of StdoutLogKind.NoColors:
VanityLogs( VanityLogs(
onMergeTransitionBlock: bellatrixMono, onMergeTransitionBlock: bellatrixMono,
onFinalizedMergeTransitionBlock: bellatrixMono, onFinalizedMergeTransitionBlock: bellatrixMono,
onUpgradeToCapella: capellaMono, onUpgradeToCapella: capellaMono,
onKnownBlsToExecutionChange: capellaMono, onKnownBlsToExecutionChange: capellaMono,
onUpgradeToDeneb: denebMono) onUpgradeToDeneb: denebMono,
onUpgradeToElectra: electraMono)
of StdoutLogKind.Json, StdoutLogKind.None: of StdoutLogKind.Json, StdoutLogKind.None:
VanityLogs( VanityLogs(
onMergeTransitionBlock: onMergeTransitionBlock:
@ -166,12 +168,14 @@ func getVanityLogs(stdoutKind: StdoutLogKind): VanityLogs =
onKnownBlsToExecutionChange: onKnownBlsToExecutionChange:
(proc() = notice "🦉 BLS to execution changed 🦉"), (proc() = notice "🦉 BLS to execution changed 🦉"),
onUpgradeToDeneb: onUpgradeToDeneb:
(proc() = notice "🐟 Proto-Danksharding is ON 🐟")) (proc() = notice "🐟 Proto-Danksharding is ON 🐟"),
onUpgradeToElectra:
(proc() = notice "🦒 [PH] Electra 🦒"))
func getVanityMascot(consensusFork: ConsensusFork): string = func getVanityMascot(consensusFork: ConsensusFork): string =
case consensusFork case consensusFork
of ConsensusFork.Electra: of ConsensusFork.Electra:
" " "🦒"
of ConsensusFork.Deneb: of ConsensusFork.Deneb:
"🐟" "🐟"
of ConsensusFork.Capella: of ConsensusFork.Capella:
@ -1767,7 +1771,8 @@ proc installMessageValidators(node: BeaconNode) =
): Future[ValidationResult] {.async: (raises: [CancelledError]).} = ): Future[ValidationResult] {.async: (raises: [CancelledError]).} =
return toValidationResult( return toValidationResult(
await node.processor.processAttestation( await node.processor.processAttestation(
MsgSource.gossip, attestation, subnet_id))) MsgSource.gossip, attestation, subnet_id,
checkSignature = true, checkValidator = false)))
else: else:
for it in SubnetId: for it in SubnetId:
closureScope: # Needed for inner `proc`; don't lift it out of loop. closureScope: # Needed for inner `proc`; don't lift it out of loop.
@ -1778,7 +1783,8 @@ proc installMessageValidators(node: BeaconNode) =
): Future[ValidationResult] {.async: (raises: [CancelledError]).} = ): Future[ValidationResult] {.async: (raises: [CancelledError]).} =
return toValidationResult( return toValidationResult(
await node.processor.processAttestation( await node.processor.processAttestation(
MsgSource.gossip, attestation, subnet_id))) MsgSource.gossip, attestation, subnet_id,
checkSignature = true, checkValidator = false)))
# beacon_aggregate_and_proof # beacon_aggregate_and_proof
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/p2p-interface.md#beacon_aggregate_and_proof # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/p2p-interface.md#beacon_aggregate_and_proof

View File

@ -123,7 +123,7 @@ programMain:
headBlockHash = payload.block_hash, headBlockHash = payload.block_hash,
safeBlockHash = payload.block_hash, # stub value safeBlockHash = payload.block_hash, # stub value
finalizedBlockHash = ZERO_HASH, finalizedBlockHash = ZERO_HASH,
payloadAttributes = none(consensusFork.PayloadAttributes)) payloadAttributes = Opt.none(consensusFork.PayloadAttributes))
else: discard else: discard
optimisticProcessor = initOptimisticProcessor( optimisticProcessor = initOptimisticProcessor(
getBeaconTime, optimisticHandler) getBeaconTime, optimisticHandler)

View File

@ -9,7 +9,7 @@
import import
std/[typetraits, sequtils, sets], std/[typetraits, sequtils, sets],
stew/[results, base10], stew/base10,
chronicles, metrics, chronicles, metrics,
./rest_utils, ./rest_utils,
./state_ttl_cache, ./state_ttl_cache,
@ -911,10 +911,12 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
when consensusFork >= ConsensusFork.Deneb: when consensusFork >= ConsensusFork.Deneb:
await node.router.routeSignedBeaconBlock( await node.router.routeSignedBeaconBlock(
forkyBlck, Opt.some( forkyBlck, Opt.some(
forkyBlck.create_blob_sidecars(kzg_proofs, blobs))) forkyBlck.create_blob_sidecars(kzg_proofs, blobs)),
checkValidator = true)
else: else:
await node.router.routeSignedBeaconBlock( await node.router.routeSignedBeaconBlock(
forkyBlck, Opt.none(seq[BlobSidecar])) forkyBlck, Opt.none(seq[BlobSidecar]),
checkValidator = true)
if res.isErr(): if res.isErr():
return RestApiResponse.jsonError( return RestApiResponse.jsonError(
@ -966,10 +968,12 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
when consensusFork >= ConsensusFork.Deneb: when consensusFork >= ConsensusFork.Deneb:
await node.router.routeSignedBeaconBlock( await node.router.routeSignedBeaconBlock(
forkyBlck, Opt.some( forkyBlck, Opt.some(
forkyBlck.create_blob_sidecars(kzg_proofs, blobs))) forkyBlck.create_blob_sidecars(kzg_proofs, blobs)),
checkValidator = true)
else: else:
await node.router.routeSignedBeaconBlock( await node.router.routeSignedBeaconBlock(
forkyBlck, Opt.none(seq[BlobSidecar])) forkyBlck, Opt.none(seq[BlobSidecar]),
checkValidator = true)
if res.isErr(): if res.isErr():
return RestApiResponse.jsonError( return RestApiResponse.jsonError(
@ -1087,7 +1091,8 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
let res = withBlck(forked): let res = withBlck(forked):
forkyBlck.root = hash_tree_root(forkyBlck.message) forkyBlck.root = hash_tree_root(forkyBlck.message)
await node.router.routeSignedBeaconBlock( await node.router.routeSignedBeaconBlock(
forkyBlck, Opt.none(seq[BlobSidecar])) forkyBlck, Opt.none(seq[BlobSidecar]),
checkValidator = true)
if res.isErr(): if res.isErr():
return RestApiResponse.jsonError( return RestApiResponse.jsonError(

View File

@ -9,7 +9,6 @@
import import
std/sequtils, std/sequtils,
stew/results,
chronicles, chronicles,
chronos/apps/http/httpserver, chronos/apps/http/httpserver,
./rest_utils, ./rest_utils,

View File

@ -5,9 +5,11 @@
# * 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: [].}
import import
std/[sequtils], std/[sequtils],
stew/[results, base10], stew/base10,
chronicles, chronicles,
chronos/apps/http/httpdebug, chronos/apps/http/httpdebug,
libp2p/[multiaddress, multicodec, peerstore], libp2p/[multiaddress, multicodec, peerstore],

View File

@ -4,8 +4,10 @@
# * 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: [].}
import import
stew/[byteutils, results], stew/byteutils,
chronicles, chronicles,
eth/p2p/discoveryv5/enr, eth/p2p/discoveryv5/enr,
libp2p/[multiaddress, multicodec, peerstore], libp2p/[multiaddress, multicodec, peerstore],

View File

@ -7,7 +7,7 @@
{.push raises: [].} {.push raises: [].}
import std/[typetraits, sets, sequtils] import std/[typetraits, sets, sequtils]
import stew/[results, base10], chronicles import stew/base10, chronicles
import ".."/[beacon_chain_db, beacon_node], import ".."/[beacon_chain_db, beacon_node],
".."/networking/eth2_network, ".."/networking/eth2_network,
".."/consensus_object_pools/[blockchain_dag, spec_cache, ".."/consensus_object_pools/[blockchain_dag, spec_cache,

View File

@ -7,7 +7,7 @@
{.push raises: [].} {.push raises: [].}
# Types specific to Deneb (i.e. known to have changed across hard forks) - see # Types specific to Electra (i.e. known to have changed across hard forks) - see
# `base` for types and guidelines common across forks # `base` for types and guidelines common across forks
# TODO Careful, not nil analysis is broken / incomplete and the semantics will # TODO Careful, not nil analysis is broken / incomplete and the semantics will

View File

@ -1173,6 +1173,16 @@ template withForkyMaybeBlindedBlck*(
template forkyMaybeBlindedBlck: untyped {.inject, used.} = b.phase0Data template forkyMaybeBlindedBlck: untyped {.inject, used.} = b.phase0Data
body body
template shortLog*(x: ForkedMaybeBlindedBeaconBlock): auto =
withForkyMaybeBlindedBlck(x):
when consensusFork >= ConsensusFork.Deneb:
when isBlinded == true:
shortLog(forkyMaybeBlindedBlck)
else:
shortLog(forkyMaybeBlindedBlck.`block`)
else:
shortLog(forkyMaybeBlindedBlck)
template withStateAndBlck*( template withStateAndBlck*(
s: ForkedHashedBeaconState, s: ForkedHashedBeaconState,
b: ForkedBeaconBlock | ForkedSignedBeaconBlock | b: ForkedBeaconBlock | ForkedSignedBeaconBlock |
@ -1360,19 +1370,19 @@ func readSszForkedHashedBeaconState*(cfg: RuntimeConfig, data: openArray[byte]):
ForkedHashedBeaconState {.raises: [SerializationError].} = ForkedHashedBeaconState {.raises: [SerializationError].} =
## Read a state picking the right fork by first reading the slot from the byte ## Read a state picking the right fork by first reading the slot from the byte
## source ## source
if data.len() < sizeof(BeaconStateHeader): const numHeaderBytes = fixedPortionSize(BeaconStateHeader)
raise (ref MalformedSszError)(msg: "Not enough data for BeaconState header") if data.len() < numHeaderBytes:
raise (ref MalformedSszError)(msg: "Incomplete BeaconState header")
let header = SSZ.decode( let header = SSZ.decode(
data.toOpenArray(0, sizeof(BeaconStateHeader) - 1), data.toOpenArray(0, numHeaderBytes - 1), BeaconStateHeader)
BeaconStateHeader)
# TODO https://github.com/nim-lang/Nim/issues/19357 # TODO https://github.com/nim-lang/Nim/issues/19357
result = readSszForkedHashedBeaconState(cfg, header.slot, data) result = readSszForkedHashedBeaconState(cfg, header.slot, data)
type type
ForkedBeaconBlockHeader = object ForkedBeaconBlockHeader = object
message*: uint32 # message offset message: uint32 # message offset
signature*: ValidatorSig signature: ValidatorSig
slot: Slot # start of BeaconBlock slot: Slot # start of BeaconBlock
func readSszForkedSignedBeaconBlock*( func readSszForkedSignedBeaconBlock*(
@ -1380,11 +1390,11 @@ func readSszForkedSignedBeaconBlock*(
ForkedSignedBeaconBlock {.raises: [SerializationError].} = ForkedSignedBeaconBlock {.raises: [SerializationError].} =
## Helper to read a header from bytes when it's not certain what kind of block ## Helper to read a header from bytes when it's not certain what kind of block
## it is ## it is
if data.len() < sizeof(ForkedBeaconBlockHeader): const numHeaderBytes = fixedPortionSize(ForkedBeaconBlockHeader)
raise (ref MalformedSszError)(msg: "Not enough data for SignedBeaconBlock header") if data.len() < numHeaderBytes:
raise (ref MalformedSszError)(msg: "Incomplete SignedBeaconBlock header")
let header = SSZ.decode( let header = SSZ.decode(
data.toOpenArray(0, sizeof(ForkedBeaconBlockHeader) - 1), data.toOpenArray(0, numHeaderBytes - 1), ForkedBeaconBlockHeader)
ForkedBeaconBlockHeader)
# TODO https://github.com/nim-lang/Nim/issues/19357 # TODO https://github.com/nim-lang/Nim/issues/19357
result = ForkedSignedBeaconBlock( result = ForkedSignedBeaconBlock(

View File

@ -484,24 +484,24 @@ proc blockToBlockHeader*(blck: ForkyBeaconBlock): ExecutionBlockHeader =
txRoot = payload.computeTransactionsTrieRoot() txRoot = payload.computeTransactionsTrieRoot()
withdrawalsRoot = withdrawalsRoot =
when typeof(payload).kind >= ConsensusFork.Capella: when typeof(payload).kind >= ConsensusFork.Capella:
some payload.computeWithdrawalsTrieRoot() Opt.some payload.computeWithdrawalsTrieRoot()
else: else:
none(ExecutionHash256) Opt.none(ExecutionHash256)
blobGasUsed = blobGasUsed =
when typeof(payload).kind >= ConsensusFork.Deneb: when typeof(payload).kind >= ConsensusFork.Deneb:
some payload.blob_gas_used Opt.some payload.blob_gas_used
else: else:
none(uint64) Opt.none(uint64)
excessBlobGas = excessBlobGas =
when typeof(payload).kind >= ConsensusFork.Deneb: when typeof(payload).kind >= ConsensusFork.Deneb:
some payload.excess_blob_gas Opt.some payload.excess_blob_gas
else: else:
none(uint64) Opt.none(uint64)
parentBeaconBlockRoot = parentBeaconBlockRoot =
when typeof(payload).kind >= ConsensusFork.Deneb: when typeof(payload).kind >= ConsensusFork.Deneb:
some ExecutionHash256(data: blck.parent_root.data) Opt.some ExecutionHash256(data: blck.parent_root.data)
else: else:
none(ExecutionHash256) Opt.none(ExecutionHash256)
ExecutionBlockHeader( ExecutionBlockHeader(
parentHash : payload.parent_hash, parentHash : payload.parent_hash,
@ -509,17 +509,17 @@ proc blockToBlockHeader*(blck: ForkyBeaconBlock): ExecutionBlockHeader =
coinbase : EthAddress payload.fee_recipient.data, coinbase : EthAddress payload.fee_recipient.data,
stateRoot : payload.state_root, stateRoot : payload.state_root,
txRoot : txRoot, txRoot : txRoot,
receiptRoot : payload.receipts_root, receiptsRoot : payload.receipts_root,
bloom : payload.logs_bloom.data, logsBloom : payload.logs_bloom.data,
difficulty : default(DifficultyInt), difficulty : default(DifficultyInt),
blockNumber : payload.block_number.u256, number : payload.block_number,
gasLimit : cast[GasInt](payload.gas_limit), gasLimit : cast[GasInt](payload.gas_limit),
gasUsed : cast[GasInt](payload.gas_used), gasUsed : cast[GasInt](payload.gas_used),
timestamp : EthTime(int64.saturate payload.timestamp), timestamp : EthTime(int64.saturate payload.timestamp),
extraData : payload.extra_data.asSeq, extraData : payload.extra_data.asSeq,
mixDigest : payload.prev_randao, # EIP-4399 `mixDigest` -> `prevRandao` mixHash : payload.prev_randao, # EIP-4399 `mixHash` -> `prevRandao`
nonce : default(BlockNonce), nonce : default(BlockNonce),
fee : some payload.base_fee_per_gas, baseFeePerGas : Opt.some payload.base_fee_per_gas,
withdrawalsRoot : withdrawalsRoot, withdrawalsRoot : withdrawalsRoot,
blobGasUsed : blobGasUsed, # EIP-4844 blobGasUsed : blobGasUsed, # EIP-4844
excessBlobGas : excessBlobGas, # EIP-4844 excessBlobGas : excessBlobGas, # EIP-4844

View File

@ -421,3 +421,23 @@ proc verify_bls_to_execution_change_signature*(
let signing_root = compute_bls_to_execution_change_signing_root( let signing_root = compute_bls_to_execution_change_signing_root(
genesisFork, genesis_validators_root, msg.message) genesisFork, genesis_validators_root, msg.message)
blsVerify(pubkey, signing_root.data, signature) blsVerify(pubkey, signing_root.data, signature)
func compute_consolidation_signing_root(
genesisFork: Fork, genesis_validators_root: Eth2Digest,
msg: Consolidation): Eth2Digest =
# Uses genesis fork version regardless
doAssert genesisFork.current_version == genesisFork.previous_version
let domain = compute_domain(
DOMAIN_CONSOLIDATION, genesisFork.current_version,
genesis_validators_root=genesis_validators_root)
compute_signing_root(msg, domain)
proc verify_consolidation_signature*(
genesisFork: Fork, genesis_validators_root: Eth2Digest,
msg: SignedConsolidation | TrustedSignedConsolidation,
pubkeys: openArray[ValidatorPubKey]): bool =
withTrust(msg.signature):
let signing_root = compute_consolidation_signing_root(
genesisFork, genesis_validators_root, msg.message)
blsFastAggregateVerify(pubkeys, signing_root.data, msg.signature)

View File

@ -361,7 +361,8 @@ func partialBeaconBlock*(
deposits: seq[Deposit], deposits: seq[Deposit],
validator_changes: BeaconBlockValidatorChanges, validator_changes: BeaconBlockValidatorChanges,
sync_aggregate: SyncAggregate, sync_aggregate: SyncAggregate,
execution_payload: ForkyExecutionPayloadForSigning execution_payload: ForkyExecutionPayloadForSigning,
consolidations: openArray[SignedConsolidation]
): auto = ): auto =
const consensusFork = typeof(state).kind const consensusFork = typeof(state).kind
@ -411,12 +412,14 @@ func partialBeaconBlock*(
deposits: seq[Deposit], deposits: seq[Deposit],
validator_changes: BeaconBlockValidatorChanges, validator_changes: BeaconBlockValidatorChanges,
sync_aggregate: SyncAggregate, sync_aggregate: SyncAggregate,
execution_payload: ForkyExecutionPayloadForSigning execution_payload: ForkyExecutionPayloadForSigning,
consolidations: seq[SignedConsolidation],
): auto = ): auto =
const consensusFork = typeof(state).kind const consensusFork = typeof(state).kind
debugComment "re-enable attester slashing packing in electra"
# https://github.com/ethereum/consensus-specs/blob/v1.3.0/specs/phase0/validator.md#preparing-for-a-beaconblock # https://github.com/ethereum/consensus-specs/blob/v1.3.0/specs/phase0/validator.md#preparing-for-a-beaconblock
var res = consensusFork.BeaconBlock( consensusFork.BeaconBlock(
slot: state.data.slot, slot: state.data.slot,
proposer_index: proposer_index.uint64, proposer_index: proposer_index.uint64,
parent_root: state.latest_block_root, parent_root: state.latest_block_root,
@ -429,28 +432,14 @@ func partialBeaconBlock*(
attestations: attestations:
List[electra.Attestation, Limit MAX_ATTESTATIONS_ELECTRA](attestations), List[electra.Attestation, Limit MAX_ATTESTATIONS_ELECTRA](attestations),
deposits: List[Deposit, Limit MAX_DEPOSITS](deposits), deposits: List[Deposit, Limit MAX_DEPOSITS](deposits),
voluntary_exits: validator_changes.voluntary_exits)) voluntary_exits: validator_changes.voluntary_exits,
sync_aggregate: sync_aggregate,
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/altair/validator.md#preparing-a-beaconblock execution_payload: execution_payload.executionPayload,
when consensusFork >= ConsensusFork.Altair: bls_to_execution_changes: validator_changes.bls_to_execution_changes,
res.body.sync_aggregate = sync_aggregate blob_kzg_commitments: execution_payload.blobsBundle.commitments,
consolidations:
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.2/specs/bellatrix/validator.md#block-proposal List[SignedConsolidation, Limit MAX_CONSOLIDATIONS].init(
when consensusFork >= ConsensusFork.Bellatrix: consolidations)))
res.body.execution_payload = execution_payload.executionPayload
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/capella/validator.md#block-proposal
when consensusFork >= ConsensusFork.Capella:
res.body.bls_to_execution_changes =
validator_changes.bls_to_execution_changes
# https://github.com/ethereum/consensus-specs/blob/v1.3.0/specs/deneb/validator.md#constructing-the-beaconblockbody
when consensusFork >= ConsensusFork.Deneb:
res.body.blob_kzg_commitments = execution_payload.blobsBundle.commitments
debugComment "either consolidate this within separate function or recombine, re when consensusFork >= foo and atts/attslashings; here to allow noninterference with pre-pectra"
res
proc makeBeaconBlockWithRewards*( proc makeBeaconBlockWithRewards*(
cfg: RuntimeConfig, cfg: RuntimeConfig,
@ -464,6 +453,7 @@ proc makeBeaconBlockWithRewards*(
validator_changes: BeaconBlockValidatorChanges, validator_changes: BeaconBlockValidatorChanges,
sync_aggregate: SyncAggregate, sync_aggregate: SyncAggregate,
executionPayload: ForkyExecutionPayloadForSigning, executionPayload: ForkyExecutionPayloadForSigning,
consolidations: seq[SignedConsolidation],
rollback: RollbackForkedHashedProc, rollback: RollbackForkedHashedProc,
cache: var StateCache, cache: var StateCache,
# TODO: # TODO:
@ -490,7 +480,7 @@ proc makeBeaconBlockWithRewards*(
partialBeaconBlock( partialBeaconBlock(
cfg, state.`kind Data`, proposer_index, randao_reveal, eth1_data, cfg, state.`kind Data`, proposer_index, randao_reveal, eth1_data,
graffiti, attestations, deposits, validator_changes, sync_aggregate, graffiti, attestations, deposits, validator_changes, sync_aggregate,
executionPayload)) executionPayload, consolidations))
let res = process_block( let res = process_block(
cfg, state.`kind Data`.data, blck.`kind Data`.asSigVerified(), cfg, state.`kind Data`.data, blck.`kind Data`.asSigVerified(),
@ -533,9 +523,8 @@ proc makeBeaconBlockWithRewards*(
forkyState.data.latest_execution_payload_header.transactions_root = forkyState.data.latest_execution_payload_header.transactions_root =
transactions_root.get transactions_root.get
debugComment "makeBeaconBlock doesn't support Electra (i.e. check for missing beaconblock body fields)"
when executionPayload is electra.ExecutionPayloadForSigning: when executionPayload is electra.ExecutionPayloadForSigning:
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/deneb/beacon-chain.md#beaconblockbody # https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.2/specs/electra/beacon-chain.md#beaconblockbody
forkyState.data.latest_block_header.body_root = hash_tree_root( forkyState.data.latest_block_header.body_root = hash_tree_root(
[hash_tree_root(randao_reveal), [hash_tree_root(randao_reveal),
hash_tree_root(eth1_data), hash_tree_root(eth1_data),
@ -550,7 +539,9 @@ proc makeBeaconBlockWithRewards*(
hash_tree_root(sync_aggregate), hash_tree_root(sync_aggregate),
execution_payload_root.get, execution_payload_root.get,
hash_tree_root(validator_changes.bls_to_execution_changes), hash_tree_root(validator_changes.bls_to_execution_changes),
hash_tree_root(kzg_commitments.get) hash_tree_root(kzg_commitments.get),
hash_tree_root(List[SignedConsolidation, Limit MAX_CONSOLIDATIONS].init(
consolidations))
]) ])
else: else:
raiseAssert "Attempt to use non-Electra payload with post-Deneb state" raiseAssert "Attempt to use non-Electra payload with post-Deneb state"
@ -593,6 +584,7 @@ proc makeBeaconBlock*(
validator_changes: BeaconBlockValidatorChanges, validator_changes: BeaconBlockValidatorChanges,
sync_aggregate: SyncAggregate, sync_aggregate: SyncAggregate,
executionPayload: ForkyExecutionPayloadForSigning, executionPayload: ForkyExecutionPayloadForSigning,
consolidations: seq[SignedConsolidation],
rollback: RollbackForkedHashedProc, cache: var StateCache, rollback: RollbackForkedHashedProc, cache: var StateCache,
verificationFlags: UpdateFlags, verificationFlags: UpdateFlags,
transactions_root: Opt[Eth2Digest], transactions_root: Opt[Eth2Digest],
@ -603,8 +595,8 @@ proc makeBeaconBlock*(
? makeBeaconBlockWithRewards( ? makeBeaconBlockWithRewards(
cfg, state, proposer_index, randao_reveal, eth1_data, graffiti, cfg, state, proposer_index, randao_reveal, eth1_data, graffiti,
attestations, deposits, validator_changes, sync_aggregate, attestations, deposits, validator_changes, sync_aggregate,
executionPayload, rollback, cache, verificationFlags, transactions_root, executionPayload, consolidations, rollback, cache, verificationFlags,
execution_payload_root, kzg_commitments) transactions_root, execution_payload_root, kzg_commitments)
ok(blockAndRewards.blck) ok(blockAndRewards.blck)
proc makeBeaconBlock*( proc makeBeaconBlock*(
@ -616,12 +608,13 @@ proc makeBeaconBlock*(
validator_changes: BeaconBlockValidatorChanges, validator_changes: BeaconBlockValidatorChanges,
sync_aggregate: SyncAggregate, sync_aggregate: SyncAggregate,
executionPayload: ForkyExecutionPayloadForSigning, executionPayload: ForkyExecutionPayloadForSigning,
consolidations: seq[SignedConsolidation],
rollback: RollbackForkedHashedProc, cache: var StateCache): rollback: RollbackForkedHashedProc, cache: var StateCache):
Result[ForkedBeaconBlock, cstring] = Result[ForkedBeaconBlock, cstring] =
makeBeaconBlock( makeBeaconBlock(
cfg, state, proposer_index, randao_reveal, eth1_data, graffiti, cfg, state, proposer_index, randao_reveal, eth1_data, graffiti,
attestations, deposits, validator_changes, sync_aggregate, attestations, deposits, validator_changes, sync_aggregate,
executionPayload, rollback, cache, executionPayload, consolidations, rollback, cache,
verificationFlags = {}, transactions_root = Opt.none Eth2Digest, verificationFlags = {}, transactions_root = Opt.none Eth2Digest,
execution_payload_root = Opt.none Eth2Digest, execution_payload_root = Opt.none Eth2Digest,
kzg_commitments = Opt.none KzgCommitments) kzg_commitments = Opt.none KzgCommitments)
@ -635,13 +628,14 @@ proc makeBeaconBlock*(
validator_changes: BeaconBlockValidatorChanges, validator_changes: BeaconBlockValidatorChanges,
sync_aggregate: SyncAggregate, sync_aggregate: SyncAggregate,
executionPayload: ForkyExecutionPayloadForSigning, executionPayload: ForkyExecutionPayloadForSigning,
consolidations: seq[SignedConsolidation],
rollback: RollbackForkedHashedProc, rollback: RollbackForkedHashedProc,
cache: var StateCache, verificationFlags: UpdateFlags): cache: var StateCache, verificationFlags: UpdateFlags):
Result[ForkedBeaconBlock, cstring] = Result[ForkedBeaconBlock, cstring] =
makeBeaconBlock( makeBeaconBlock(
cfg, state, proposer_index, randao_reveal, eth1_data, graffiti, cfg, state, proposer_index, randao_reveal, eth1_data, graffiti,
attestations, deposits, validator_changes, sync_aggregate, attestations, deposits, validator_changes, sync_aggregate,
executionPayload, rollback, cache, executionPayload, consolidations, rollback, cache,
verificationFlags = verificationFlags, verificationFlags = verificationFlags,
transactions_root = Opt.none Eth2Digest, transactions_root = Opt.none Eth2Digest,
execution_payload_root = Opt.none Eth2Digest, execution_payload_root = Opt.none Eth2Digest,

View File

@ -644,20 +644,11 @@ proc process_consolidation*(
target_validator.withdrawal_credentials.data.toOpenArray(12, 31)): target_validator.withdrawal_credentials.data.toOpenArray(12, 31)):
return err("Consolidation: source and target don't have same withdrawal address") return err("Consolidation: source and target don't have same withdrawal address")
debugComment "this is per spec, near-verbatim, but Nimbus generally factors this out into spec/signatures.nim. so, create verify_consolidation_signature infra there, call here"
# Verify consolidation is signed by the source and the target # Verify consolidation is signed by the source and the target
let if not verify_consolidation_signature(
domain = compute_domain( cfg.genesisFork, state.genesis_validators_root, signed_consolidation,
DOMAIN_CONSOLIDATION, cfg.GENESIS_FORK_VERSION, [source_validator[].pubkey, target_validator.pubkey]):
genesis_validators_root=state.genesis_validators_root) return err("Consolidation: invalid signature")
signing_root = compute_signing_root(consolidation, domain)
pubkeys = [source_validator[].pubkey, target_validator.pubkey]
debugComment "as a good example, this trustedsig hack typically/should live in spec/signatures.nim"
when not (signed_consolidation.signature is TrustedSig):
if not blsFastAggregateVerify(
pubkeys, signing_root.data, signed_consolidation.signature):
return err("Consolidation: invalid signature")
# Initiate source validator exit and append pending consolidation # Initiate source validator exit and append pending consolidation
source_validator[].exit_epoch = compute_consolidation_epoch_and_update_churn( source_validator[].exit_epoch = compute_consolidation_epoch_and_update_churn(
@ -667,8 +658,7 @@ proc process_consolidation*(
debugComment "check HashList add return value" debugComment "check HashList add return value"
discard state.pending_consolidations.add(PendingConsolidation( discard state.pending_consolidations.add(PendingConsolidation(
source_index: consolidation.source_index, source_index: consolidation.source_index,
target_index: consolidation.target_index target_index: consolidation.target_index))
))
ok() ok()

View File

@ -8,7 +8,7 @@
{.push raises: [].} {.push raises: [].}
import std/[strutils, sequtils, algorithm] import std/[strutils, sequtils, algorithm]
import stew/[results, base10], chronos, chronicles import stew/base10, chronos, chronicles
import import
../spec/datatypes/[phase0, altair], ../spec/datatypes/[phase0, altair],
../spec/eth2_apis/rest_types, ../spec/eth2_apis/rest_types,

View File

@ -8,7 +8,7 @@
{.push raises: [].} {.push raises: [].}
import std/[heapqueue, tables, strutils, sequtils, math] import std/[heapqueue, tables, strutils, sequtils, math]
import stew/[results, base10], chronos, chronicles import stew/base10, chronos, chronicles
import import
../spec/datatypes/[base, phase0, altair], ../spec/datatypes/[base, phase0, altair],
../spec/[helpers, forks], ../spec/[helpers, forks],

View File

@ -8,7 +8,7 @@
{.push raises: [].} {.push raises: [].}
import import
stew/[base10, results], stew/base10,
chronicles, chronos, eth/async_utils, chronicles, chronos, eth/async_utils,
./sync/[light_client_sync_helpers, sync_manager], ./sync/[light_client_sync_helpers, sync_manager],
./consensus_object_pools/[block_clearance, blockchain_dag], ./consensus_object_pools/[block_clearance, blockchain_dag],

View File

@ -39,14 +39,14 @@ type
status*: ApiOperation status*: ApiOperation
data*: seq[ApiNodeResponse[T]] data*: seq[ApiNodeResponse[T]]
ApiScore* = object ApiScore*[T] = object
index*: int index*: int
score*: Opt[float64] score*: Opt[T]
BestNodeResponse*[T] = object BestNodeResponse*[T, X] = object
node*: BeaconNodeServerRef node*: BeaconNodeServerRef
data*: ApiResponse[T] data*: ApiResponse[T]
score*: float64 score*: X
const const
ViableNodeStatus* = { ViableNodeStatus* = {
@ -56,7 +56,7 @@ const
RestBeaconNodeStatus.Synced RestBeaconNodeStatus.Synced
} }
proc `$`*(s: ApiScore): string = proc `$`*[T](s: ApiScore[T]): string =
var res = Base10.toString(uint64(s.index)) var res = Base10.toString(uint64(s.index))
res.add(": ") res.add(": ")
if s.score.isSome(): if s.score.isSome():
@ -65,22 +65,27 @@ proc `$`*(s: ApiScore): string =
res.add("<n/a>") res.add("<n/a>")
res res
proc `$`*(ss: openArray[ApiScore]): string = proc `$`*[T](ss: openArray[ApiScore[T]]): string =
"[" & ss.mapIt($it).join(",") & "]" "[" & ss.mapIt($it).join(",") & "]"
chronicles.formatIt(seq[ApiScore]): chronicles.formatIt(seq[ApiScore]):
$it $it
func init*(t: typedesc[ApiScore], node: BeaconNodeServerRef, func init*(t: typedesc[ApiScore], node: BeaconNodeServerRef,
score: float64): ApiScore = score: float64): ApiScore[float64] =
ApiScore(index: node.index, score: Opt.some(score)) ApiScore[float64](index: node.index, score: Opt.some(score))
func init*(t: typedesc[ApiScore], node: BeaconNodeServerRef): ApiScore = func init*(t: typedesc[ApiScore], node: BeaconNodeServerRef,
ApiScore(index: node.index, score: Opt.none(float64)) score: UInt256): ApiScore[UInt256] =
ApiScore[UInt256](index: node.index, score: Opt.some(score))
func init*[T](t: typedesc[BestNodeResponse], node: BeaconNodeServerRef, func init*(tt: typedesc[ApiScore],
data: ApiResponse[T], score: float64): BestNodeResponse[T] = node: BeaconNodeServerRef, T: typedesc): ApiScore[T] =
BestNodeResponse[T](node: node, data: data, score: score) ApiScore[T](index: node.index, score: Opt.none(T))
func init*[T, X](t: typedesc[BestNodeResponse], node: BeaconNodeServerRef,
data: ApiResponse[T], score: X): BestNodeResponse[T, X] =
BestNodeResponse[T, X](node: node, data: data, score: score)
proc lazyWaiter(node: BeaconNodeServerRef, request: FutureBase, proc lazyWaiter(node: BeaconNodeServerRef, request: FutureBase,
requestName: string, strategy: ApiStrategyKind) {.async.} = requestName: string, strategy: ApiStrategyKind) {.async.} =
@ -234,7 +239,7 @@ template firstSuccessParallel*(
pendingNodes.del(index) pendingNodes.del(index)
let let
node {.inject.} = beaconNode node {.inject, used.} = beaconNode
apiResponse {.inject.} = apiResponse {.inject.} =
apiResponseOr[responseType](requestFut, timerFut, apiResponseOr[responseType](requestFut, timerFut,
"Timeout exceeded while awaiting for the response") "Timeout exceeded while awaiting for the response")
@ -283,6 +288,7 @@ template bestSuccess*(
vc: ValidatorClientRef, vc: ValidatorClientRef,
responseType: typedesc, responseType: typedesc,
handlerType: typedesc, handlerType: typedesc,
scoreType: typedesc,
timeout: Duration, timeout: Duration,
statuses: set[RestBeaconNodeStatus], statuses: set[RestBeaconNodeStatus],
roles: set[BeaconNodeRole], roles: set[BeaconNodeRole],
@ -301,8 +307,8 @@ template bestSuccess*(
var var
retRes: ApiResponse[handlerType] retRes: ApiResponse[handlerType]
scores: seq[ApiScore] scores: seq[ApiScore[scoreType]]
bestResponse: Opt[BestNodeResponse[handlerType]] bestResponse: Opt[BestNodeResponse[handlerType, scoreType]]
block mainLoop: block mainLoop:
while true: while true:
@ -395,7 +401,7 @@ template bestSuccess*(
perfectScoreFound = true perfectScoreFound = true
break break
else: else:
scores.add(ApiScore.init(node)) scores.add(ApiScore.init(node, scoreType))
if perfectScoreFound: if perfectScoreFound:
# lazyWait will cancel `pendingRequests` on timeout. # lazyWait will cancel `pendingRequests` on timeout.
@ -714,16 +720,30 @@ template firstSuccessSequential*(
break break
proc getErrorMessage*(response: RestPlainResponse): string = proc getErrorMessage*(response: RestPlainResponse): string =
let res = decodeBytes(RestErrorMessage, response.data, let res =
response.contentType) decodeBytes(RestErrorMessage, response.data, response.contentType).valueOr:
if res.isOk(): return "Unable to decode error response: [" & $error & "]"
let errorObj = res.get()
if errorObj.stacktraces.isSome(): if res.stacktraces.isSome():
errorObj.message & ": [" & errorObj.stacktraces.get().join("; ") & "]" res.message & ": [" & res.stacktraces.get().join("; ") & "]"
else:
errorObj.message
else: else:
"Unable to decode error response: [" & $res.error & "]" res.message
proc unpackErrorMessage*(response: RestPlainResponse): RestIndexedErrorMessage =
decodeBytes(RestIndexedErrorMessage, response.data,
response.contentType).valueOr:
let message = "Unable to decode error response: [" & $error & "]"
return RestIndexedErrorMessage(
code: -1,
message: message,
failures: default(seq[RestIndexedErrorMessageItem]))
proc getErrorMessage*(msg: RestIndexedErrorMessage): string =
if len(msg.failures) > 0:
msg.message & ": [" &
msg.failures.mapIt($it.index & ":" & it.message).join("; ") & "]"
else:
msg.message
template handleCommunicationError(): untyped {.dirty.} = template handleCommunicationError(): untyped {.dirty.} =
let failure = ApiNodeFailure.init(ApiFailure.Communication, RequestName, let failure = ApiNodeFailure.init(ApiFailure.Communication, RequestName,
@ -755,6 +775,13 @@ template handle400(): untyped {.dirty.} =
node.updateStatus(RestBeaconNodeStatus.Incompatible, failure) node.updateStatus(RestBeaconNodeStatus.Incompatible, failure)
failures.add(failure) failures.add(failure)
template handle400Indexed(): untyped {.dirty.} =
let failure = ApiNodeFailure.init(ApiFailure.Invalid, RequestName,
strategy, node, response.status,
response.unpackErrorMessage().getErrorMessage())
node.updateStatus(RestBeaconNodeStatus.Incompatible, failure)
failures.add(failure)
template handle404(): untyped {.dirty.} = template handle404(): untyped {.dirty.} =
let failure = ApiNodeFailure.init(ApiFailure.NotFound, RequestName, let failure = ApiNodeFailure.init(ApiFailure.NotFound, RequestName,
strategy, node, response.status, response.getErrorMessage()) strategy, node, response.status, response.getErrorMessage())
@ -1181,6 +1208,7 @@ proc getHeadBlockRoot*(
let res = vc.bestSuccess( let res = vc.bestSuccess(
RestPlainResponse, RestPlainResponse,
GetBlockRootResponse, GetBlockRootResponse,
float64,
SlotDuration, SlotDuration,
ViableNodeStatus, ViableNodeStatus,
{BeaconNodeRole.SyncCommitteeData}, {BeaconNodeRole.SyncCommitteeData},
@ -1413,6 +1441,7 @@ proc produceAttestationData*(
let res = vc.bestSuccess( let res = vc.bestSuccess(
RestPlainResponse, RestPlainResponse,
ProduceAttestationDataResponse, ProduceAttestationDataResponse,
float64,
OneThirdDuration, OneThirdDuration,
ViableNodeStatus, ViableNodeStatus,
{BeaconNodeRole.AttestationData}, {BeaconNodeRole.AttestationData},
@ -1514,7 +1543,7 @@ proc submitPoolAttestations*(
of 200: of 200:
ApiResponse[bool].ok(true) ApiResponse[bool].ok(true)
of 400: of 400:
handle400() handle400Indexed()
ApiResponse[bool].err(ResponseInvalidError) ApiResponse[bool].err(ResponseInvalidError)
of 500: of 500:
handle500() handle500()
@ -1542,7 +1571,7 @@ proc submitPoolAttestations*(
of 200: of 200:
return true return true
of 400: of 400:
handle400() handle400Indexed()
false false
of 500: of 500:
handle500() handle500()
@ -1589,7 +1618,7 @@ proc submitPoolSyncCommitteeSignature*(
of 200: of 200:
ApiResponse[bool].ok(true) ApiResponse[bool].ok(true)
of 400: of 400:
handle400() handle400Indexed()
ApiResponse[bool].err(ResponseInvalidError) ApiResponse[bool].err(ResponseInvalidError)
of 500: of 500:
handle500() handle500()
@ -1618,7 +1647,7 @@ proc submitPoolSyncCommitteeSignature*(
of 200: of 200:
return true return true
of 400: of 400:
handle400() handle400Indexed()
false false
of 500: of 500:
handle500() handle500()
@ -1685,6 +1714,7 @@ proc getAggregatedAttestation*(
let res = vc.bestSuccess( let res = vc.bestSuccess(
RestPlainResponse, RestPlainResponse,
GetAggregatedAttestationResponse, GetAggregatedAttestationResponse,
float64,
OneThirdDuration, OneThirdDuration,
ViableNodeStatus, ViableNodeStatus,
{BeaconNodeRole.AggregatedData}, {BeaconNodeRole.AggregatedData},
@ -1818,6 +1848,7 @@ proc produceSyncCommitteeContribution*(
let res = vc.bestSuccess( let res = vc.bestSuccess(
RestPlainResponse, RestPlainResponse,
ProduceSyncCommitteeContributionResponse, ProduceSyncCommitteeContributionResponse,
float64,
OneThirdDuration, OneThirdDuration,
ViableNodeStatus, ViableNodeStatus,
{BeaconNodeRole.SyncCommitteeData}, {BeaconNodeRole.SyncCommitteeData},
@ -2036,7 +2067,59 @@ proc produceBlockV3*(
var failures: seq[ApiNodeFailure] var failures: seq[ApiNodeFailure]
case strategy case strategy
of ApiStrategyKind.First, ApiStrategyKind.Best: of ApiStrategyKind.Best:
let res = vc.bestSuccess(
RestPlainResponse,
ProduceBlockResponseV3,
UInt256,
SlotDuration,
ViableNodeStatus,
{BeaconNodeRole.BlockProposalData},
produceBlockV3Plain(it, slot, randao_reveal, graffiti,
builder_boost_factor),
getProduceBlockResponseV3Score(itresponse)):
if apiResponse.isErr():
handleCommunicationError()
ApiResponse[ProduceBlockResponseV3].err(apiResponse.error)
else:
let response = apiResponse.get()
case response.status
of 200:
let
version = response.headers.getString("eth-consensus-version")
blinded =
response.headers.getString("eth-execution-payload-blinded")
executionValue =
response.headers.getString("eth-execution-payload-value")
consensusValue =
response.headers.getString("eth-consensus-block-value")
res = decodeBytes(ProduceBlockResponseV3, response.data,
response.contentType, version, blinded,
executionValue, consensusValue)
if res.isErr():
handleUnexpectedData()
ApiResponse[ProduceBlockResponseV3].err($res.error)
else:
ApiResponse[ProduceBlockResponseV3].ok(res.get())
of 400:
handle400()
ApiResponse[ProduceBlockResponseV3].err(ResponseInvalidError)
of 500:
handle500()
ApiResponse[ProduceBlockResponseV3].err(ResponseInternalError)
of 503:
handle503()
ApiResponse[ProduceBlockResponseV3].err(
ResponseNoSyncError)
else:
handleUnexpectedCode()
ApiResponse[ProduceBlockResponseV3].err(
ResponseUnexpectedError)
if res.isErr():
raise (ref ValidatorApiError)(msg: res.error, data: failures)
return res.get()
of ApiStrategyKind.First:
let res = vc.firstSuccessParallel( let res = vc.firstSuccessParallel(
RestPlainResponse, RestPlainResponse,
ProduceBlockResponseV3, ProduceBlockResponseV3,
@ -2222,7 +2305,7 @@ proc publishBlock*(
return true return true
of 202: of 202:
debug BlockBroadcasted, node = node, debug BlockBroadcasted, node = node,
blck = shortLog(ForkedSignedBeaconBlock.init(data)) blck = shortLog(ForkedSignedBeaconBlock.init(data))
return true return true
of 400: of 400:
handle400() handle400()

View File

@ -87,9 +87,9 @@ proc pollForValidatorIndices*(service: DutiesServiceRef) {.async.} =
if validator.isNone(): if validator.isNone():
missing.add(validatorLog(item.validator.pubkey, item.index)) missing.add(validatorLog(item.validator.pubkey, item.index))
else: else:
validator.get().updateValidator(Opt.some ValidatorAndIndex( vc.attachedValidators[].updateValidator(validator.get(),
index: item.index, Opt.some ValidatorAndIndex(index: item.index,
validator: item.validator)) validator: item.validator))
updated.add(validatorLog(item.validator.pubkey, item.index)) updated.add(validatorLog(item.validator.pubkey, item.index))
list.add(validator.get()) list.add(validator.get())

View File

@ -10,6 +10,7 @@
import std/strutils import std/strutils
import ssz_serialization/[types, bitseqs] import ssz_serialization/[types, bitseqs]
import stew/endians2 import stew/endians2
import stint
import nimcrypto/hash import nimcrypto/hash
import "."/common import "."/common
@ -24,6 +25,9 @@ const
func perfectScore*(score: float64): bool = func perfectScore*(score: float64): bool =
score == Inf score == Inf
func perfectScore*(score: UInt256): bool =
score == high(UInt256)
proc shortScore*(score: float64): string = proc shortScore*(score: float64): string =
if score == Inf: if score == Inf:
"<perfect>" "<perfect>"
@ -32,6 +36,9 @@ proc shortScore*(score: float64): string =
else: else:
formatFloat(score, ffDecimal, 4) formatFloat(score, ffDecimal, 4)
proc shortScore*(score: UInt256): string =
$score
func getLexicographicScore(digest: Eth2Digest): float64 = func getLexicographicScore(digest: Eth2Digest): float64 =
# We calculate score on first 8 bytes of digest. # We calculate score on first 8 bytes of digest.
let let
@ -183,3 +190,28 @@ proc getUniqueVotes*(attestations: openArray[phase0.Attestation]): int =
processVotes(attestation) processVotes(attestation)
res += count res += count
res res
proc getProduceBlockResponseV3Score*(blck: ProduceBlockResponseV3): UInt256 =
let (res, cv, ev) =
block:
var score256 = UInt256.zero
let
cvalue =
if blck.consensusValue.isSome():
let value = blck.consensusValue.get()
score256 = score256 + value
$value
else:
"<missing>"
evalue =
if blck.executionValue.isSome():
let value = blck.executionValue.get()
score256 = score256 + value
$value
else:
"<missing>"
(score256, cvalue, evalue)
debug "Block score", blck = shortLog(blck), consensus_value = cv,
execution_value = ev, score = shortScore(res)
res

View File

@ -152,7 +152,7 @@ proc addValidatorsFromWeb3Signer(
gasLimit = node.consensusManager[].getGasLimit(keystore.pubkey) gasLimit = node.consensusManager[].getGasLimit(keystore.pubkey)
v = node.attachedValidators[].addValidator(keystore, feeRecipient, v = node.attachedValidators[].addValidator(keystore, feeRecipient,
gasLimit) gasLimit)
v.updateValidator(data) node.attachedValidators[].updateValidator(v, data)
proc addValidators*(node: BeaconNode) {.async: (raises: [CancelledError]).} = proc addValidators*(node: BeaconNode) {.async: (raises: [CancelledError]).} =
info "Loading validators", validatorsDir = node.config.validatorsDir(), info "Loading validators", validatorsDir = node.config.validatorsDir(),
@ -174,7 +174,7 @@ proc addValidators*(node: BeaconNode) {.async: (raises: [CancelledError]).} =
v = node.attachedValidators[].addValidator(keystore, feeRecipient, v = node.attachedValidators[].addValidator(keystore, feeRecipient,
gasLimit) gasLimit)
v.updateValidator(data) node.attachedValidators[].updateValidator(v, data)
# We use `allFutures` because all failures are already reported as # We use `allFutures` because all failures are already reported as
# user-visible warnings in `queryValidatorsSource`. # user-visible warnings in `queryValidatorsSource`.
@ -363,10 +363,12 @@ proc createAndSendAttestation(node: BeaconNode,
res = res =
if consensusFork >= ConsensusFork.Electra: if consensusFork >= ConsensusFork.Electra:
await node.router.routeAttestation( await node.router.routeAttestation(
registered.toElectraAttestation(signature), subnet_id, checkSignature = false) registered.toElectraAttestation(signature), subnet_id,
checkSignature = false, checkValidator = false)
else: else:
await node.router.routeAttestation( await node.router.routeAttestation(
registered.toAttestation(signature), subnet_id, checkSignature = false) registered.toAttestation(signature), subnet_id,
checkSignature = false, checkValidator = false)
if not res.isOk(): if not res.isOk():
return return
@ -537,6 +539,7 @@ proc makeBeaconBlockForHeadAndSlot*(
slot, validator_index slot, validator_index
return err("Unable to get execution payload") return err("Unable to get execution payload")
debugComment "flesh out consolidations"
let res = makeBeaconBlockWithRewards( let res = makeBeaconBlockWithRewards(
node.dag.cfg, node.dag.cfg,
state[], state[],
@ -549,6 +552,7 @@ proc makeBeaconBlockForHeadAndSlot*(
exits, exits,
node.syncCommitteeMsgPool[].produceSyncAggregate(head.bid, slot), node.syncCommitteeMsgPool[].produceSyncAggregate(head.bid, slot),
payload, payload,
@[], # consolidations
noRollback, # Temporary state - no need for rollback noRollback, # Temporary state - no need for rollback
cache, cache,
verificationFlags = {}, verificationFlags = {},
@ -1292,7 +1296,8 @@ proc proposeBlockAux(
else: else:
Opt.none(seq[BlobSidecar]) Opt.none(seq[BlobSidecar])
newBlockRef = ( newBlockRef = (
await node.router.routeSignedBeaconBlock(signedBlock, blobsOpt) await node.router.routeSignedBeaconBlock(signedBlock, blobsOpt,
checkValidator = false)
).valueOr: ).valueOr:
return head # Errors logged in router return head # Errors logged in router
@ -1869,7 +1874,7 @@ proc updateValidators(
let let
v = node.attachedValidators[].getValidator(validators[i].pubkey).valueOr: v = node.attachedValidators[].getValidator(validators[i].pubkey).valueOr:
continue continue
v.index = Opt.some ValidatorIndex(i) node.attachedValidators[].setValidatorIndex(v, ValidatorIndex(i))
node.dutyValidatorCount = validators.len node.dutyValidatorCount = validators.len
@ -1879,10 +1884,12 @@ proc updateValidators(
# Activation epoch can change after index is assigned.. # Activation epoch can change after index is assigned..
let index = validator.index.get() let index = validator.index.get()
if index < validators.lenu64: if index < validators.lenu64:
validator.updateValidator( node.attachedValidators[].updateValidator(
validator,
Opt.some(ValidatorAndIndex( Opt.some(ValidatorAndIndex(
index: index, validator: validators[int index] index: index, validator: validators[int index]
))) ))
)
proc handleFallbackAttestations(node: BeaconNode, lastSlot, slot: Slot) = proc handleFallbackAttestations(node: BeaconNode, lastSlot, slot: Slot) =
# Neither block proposal nor sync committee duties can be done in this # Neither block proposal nor sync committee duties can be done in this

View File

@ -1607,7 +1607,7 @@ proc addValidator*(
if not isNil(host.getValidatorAndIdxFn): if not isNil(host.getValidatorAndIdxFn):
let data = host.getValidatorAndIdxFn(keystore.pubkey) let data = host.getValidatorAndIdxFn(keystore.pubkey)
v.updateValidator(data) host.validatorPool[].updateValidator(v, data)
proc generateDeposits*(cfg: RuntimeConfig, proc generateDeposits*(cfg: RuntimeConfig,
rng: var HmacDrbgContext, rng: var HmacDrbgContext,

View File

@ -8,7 +8,6 @@
{.push raises: [].} {.push raises: [].}
import import
stew/results,
std/sequtils, std/sequtils,
chronicles, chronicles,
metrics, metrics,
@ -85,13 +84,22 @@ template getCurrentBeaconTime(router: MessageRouter): BeaconTime =
type RouteBlockResult = Result[Opt[BlockRef], string] type RouteBlockResult = Result[Opt[BlockRef], string]
proc routeSignedBeaconBlock*( proc routeSignedBeaconBlock*(
router: ref MessageRouter, blck: ForkySignedBeaconBlock, router: ref MessageRouter, blck: ForkySignedBeaconBlock,
blobsOpt: Opt[seq[BlobSidecar]]): blobsOpt: Opt[seq[BlobSidecar]], checkValidator: bool):
Future[RouteBlockResult] {.async: (raises: [CancelledError]).} = Future[RouteBlockResult] {.async: (raises: [CancelledError]).} =
## Validate and broadcast beacon block, then add it to the block database ## Validate and broadcast beacon block, then add it to the block database
## Returns the new Head when block is added successfully to dag, none when ## Returns the new Head when block is added successfully to dag, none when
## block passes validation but is not added, and error otherwise ## block passes validation but is not added, and error otherwise
let wallTime = router[].getCurrentBeaconTime() let wallTime = router[].getCurrentBeaconTime()
block:
let vindex = ValidatorIndex(blck.message.proposer_index)
if checkValidator and (vindex in router.processor.validatorPool[]):
warn "A validator client attempts to send a block from " &
"validator that is also manager by beacon node",
validator_index = vindex
return err("Block could not be sent from validator that is also " &
"managed by the beacon node")
# Start with a quick gossip validation check such that broadcasting the # Start with a quick gossip validation check such that broadcasting the
# block doesn't get the node into trouble # block doesn't get the node into trouble
block: block:
@ -193,13 +201,14 @@ proc routeSignedBeaconBlock*(
proc routeAttestation*( proc routeAttestation*(
router: ref MessageRouter, router: ref MessageRouter,
attestation: phase0.Attestation | electra.Attestation, attestation: phase0.Attestation | electra.Attestation,
subnet_id: SubnetId, checkSignature: bool): subnet_id: SubnetId, checkSignature, checkValidator: bool):
Future[SendResult] {.async: (raises: [CancelledError]).} = Future[SendResult] {.async: (raises: [CancelledError]).} =
## Process and broadcast attestation - processing will register the it with ## Process and broadcast attestation - processing will register the it with
## the attestation pool ## the attestation pool
block: block:
let res = await router[].processor.processAttestation( let res = await router[].processor.processAttestation(
MsgSource.api, attestation, subnet_id, checkSignature) MsgSource.api, attestation, subnet_id,
checkSignature = checkSignature, checkValidator = checkValidator)
if not res.isGoodForSending: if not res.isGoodForSending:
warn "Attestation failed validation", warn "Attestation failed validation",
@ -250,7 +259,7 @@ proc routeAttestation*(
committee_index) committee_index)
return await router.routeAttestation( return await router.routeAttestation(
attestation, subnet_id, checkSignature = true) attestation, subnet_id, checkSignature = true, checkValidator = true)
proc routeSignedAggregateAndProof*( proc routeSignedAggregateAndProof*(
router: ref MessageRouter, proof: phase0.SignedAggregateAndProof, router: ref MessageRouter, proof: phase0.SignedAggregateAndProof,

View File

@ -143,7 +143,8 @@ proc unblindAndRouteBlockMEV*(
blck = shortLog(signedBlock) blck = shortLog(signedBlock)
let newBlockRef = let newBlockRef =
(await node.router.routeSignedBeaconBlock(signedBlock, blobsOpt)).valueOr: (await node.router.routeSignedBeaconBlock(
signedBlock, blobsOpt, checkValidator = false)).valueOr:
# submitBlindedBlock has run, so don't allow fallback to run # submitBlindedBlock has run, so don't allow fallback to run
return err("routeSignedBeaconBlock error") # Errors logged in router return err("routeSignedBeaconBlock error") # Errors logged in router

View File

@ -8,7 +8,7 @@
{.push raises: [].} {.push raises: [].}
import import
std/[tables, json, streams, sequtils, uri], std/[tables, json, streams, sequtils, uri, sets],
chronos, chronicles, metrics, chronos, chronicles, metrics,
json_serialization/std/net, json_serialization/std/net,
presto/client, presto/client,
@ -93,6 +93,7 @@ type
ValidatorPool* = object ValidatorPool* = object
validators*: Table[ValidatorPubKey, AttachedValidator] validators*: Table[ValidatorPubKey, AttachedValidator]
indexSet*: HashSet[ValidatorIndex]
slashingProtection*: SlashingProtectionDB slashingProtection*: SlashingProtectionDB
doppelgangerDetectionEnabled*: bool doppelgangerDetectionEnabled*: bool
@ -223,10 +224,24 @@ func contains*(pool: ValidatorPool, pubkey: ValidatorPubKey): bool =
## Returns ``true`` if validator with key ``pubkey`` present in ``pool``. ## Returns ``true`` if validator with key ``pubkey`` present in ``pool``.
pool.validators.contains(pubkey) pool.validators.contains(pubkey)
proc contains*(pool: ValidatorPool, index: ValidatorIndex): bool =
## Returns ``true`` if validator with index ``index`` present in ``pool``.
pool.indexSet.contains(index)
proc setValidatorIndex*(pool: var ValidatorPool, validator: AttachedValidator,
index: ValidatorIndex) =
pool.indexSet.incl(index)
validator.index = Opt.some(index)
proc removeValidatorIndex(pool: var ValidatorPool, index: ValidatorIndex) =
pool.indexSet.excl(index)
proc removeValidator*(pool: var ValidatorPool, pubkey: ValidatorPubKey) = proc removeValidator*(pool: var ValidatorPool, pubkey: ValidatorPubKey) =
## Delete validator with public key ``pubkey`` from ``pool``. ## Delete validator with public key ``pubkey`` from ``pool``.
let validator = pool.validators.getOrDefault(pubkey) let validator = pool.validators.getOrDefault(pubkey)
if not(isNil(validator)): if not(isNil(validator)):
if validator.index.isSome():
pool.removeValidatorIndex(validator.index.get)
pool.validators.del(pubkey) pool.validators.del(pubkey)
case validator.kind case validator.kind
of ValidatorKind.Local: of ValidatorKind.Local:
@ -243,8 +258,9 @@ proc removeValidator*(pool: var ValidatorPool, pubkey: ValidatorPubKey) =
func needsUpdate*(validator: AttachedValidator): bool = func needsUpdate*(validator: AttachedValidator): bool =
validator.index.isNone() or validator.activationEpoch == FAR_FUTURE_EPOCH validator.index.isNone() or validator.activationEpoch == FAR_FUTURE_EPOCH
proc updateValidator*( proc updateValidator*(pool: var ValidatorPool,
validator: AttachedValidator, validatorData: Opt[ValidatorAndIndex]) = validator: AttachedValidator,
validatorData: Opt[ValidatorAndIndex]) =
defer: validator.updated = true defer: validator.updated = true
let let
@ -259,6 +275,7 @@ proc updateValidator*(
## Update activation information for a validator ## Update activation information for a validator
if validator.index != Opt.some data.index: if validator.index != Opt.some data.index:
pool.setValidatorIndex(validator, data.index)
validator.index = Opt.some data.index validator.index = Opt.some data.index
validator.validator = Opt.some data.validator validator.validator = Opt.some data.validator

View File

@ -289,7 +289,7 @@ template `as`(address: Eth1Address, T: type bellatrix.ExecutionAddress): T =
template `as`(address: BlockHash, T: type Eth2Digest): T = template `as`(address: BlockHash, T: type Eth2Digest): T =
asEth2Digest(address) asEth2Digest(address)
func getOrDefault[T](x: Option[T]): T = func getOrDefault[T](x: Opt[T]): T =
if x.isSome: if x.isSome:
x.get x.get
else: else:
@ -505,25 +505,25 @@ proc doCreateTestnet*(config: CliConfig,
proc deployContract(web3: Web3, code: seq[byte]): Future[ReceiptObject] {.async.} = proc deployContract(web3: Web3, code: seq[byte]): Future[ReceiptObject] {.async.} =
let tr = TransactionArgs( let tr = TransactionArgs(
`from`: web3.defaultAccount.some, `from`: Opt.some web3.defaultAccount,
data: code.some, data: Opt.some code,
gas: Quantity(3000000).some, gas: Opt.some Quantity(3000000),
gasPrice: Quantity(1).some) gasPrice: Opt.some Quantity(1))
let r = await web3.send(tr) let r = await web3.send(tr)
result = await web3.getMinedTransactionReceipt(r) result = await web3.getMinedTransactionReceipt(r)
proc sendEth(web3: Web3, to: Eth1Address, valueEth: int): Future[TxHash] = proc sendEth(web3: Web3, to: Eth1Address, valueEth: int): Future[TxHash] =
let tr = TransactionArgs( let tr = TransactionArgs(
`from`: web3.defaultAccount.some, `from`: Opt.some web3.defaultAccount,
# TODO: Force json-rpc to generate 'data' field # TODO: Force json-rpc to generate 'data' field
# should not be needed anymore, new execution-api schema # should not be needed anymore, new execution-api schema
# is using `input` field # is using `input` field
data: some(newSeq[byte]()), data: Opt.some(newSeq[byte]()),
gas: Quantity(3000000).some, gas: Opt.some Quantity(3000000),
gasPrice: Quantity(1).some, gasPrice: Opt.some Quantity(1),
value: some(valueEth.u256 * 1000000000000000000.u256), value: Opt.some(valueEth.u256 * 1000000000000000000.u256),
to: some(to)) to: Opt.some(to))
web3.send(tr) web3.send(tr)
type type
@ -535,7 +535,7 @@ func ethToWei(eth: UInt256): UInt256 =
proc initWeb3(web3Url, privateKey: string): Future[Web3] {.async.} = proc initWeb3(web3Url, privateKey: string): Future[Web3] {.async.} =
result = await newWeb3(web3Url) result = await newWeb3(web3Url)
if privateKey.len != 0: if privateKey.len != 0:
result.privateKey = some(keys.PrivateKey.fromHex(privateKey)[]) result.privateKey = Opt.some(keys.PrivateKey.fromHex(privateKey)[])
else: else:
let accounts = await result.provider.eth_accounts() let accounts = await result.provider.eth_accounts()
doAssert(accounts.len > 0) doAssert(accounts.len > 0)

View File

@ -79,7 +79,7 @@ stack-data==0.1.4
terminado==0.12.1 terminado==0.12.1
testpath==0.5.0 testpath==0.5.0
tomli==1.2.3 tomli==1.2.3
tornado==6.3.3 tornado==6.4.1
traitlets==5.1.1 traitlets==5.1.1
typing_extensions==4.0.1 typing_extensions==4.0.1
wcwidth==0.2.5 wcwidth==0.2.5

View File

@ -85,7 +85,7 @@ proc makeSimulationBlock(
var blck = partialBeaconBlock( var blck = partialBeaconBlock(
cfg, state, proposer_index, randao_reveal, eth1_data, graffiti, cfg, state, proposer_index, randao_reveal, eth1_data, graffiti,
attestations, deposits, exits, sync_aggregate, execution_payload) attestations, deposits, exits, sync_aggregate, execution_payload, @[])
let res = process_block( let res = process_block(
cfg, state.data, blck.asSigVerified(), verificationFlags, cache) cfg, state.data, blck.asSigVerified(), verificationFlags, cache)
@ -128,7 +128,7 @@ proc makeSimulationBlock(
var blck = partialBeaconBlock( var blck = partialBeaconBlock(
cfg, state, proposer_index, randao_reveal, eth1_data, graffiti, cfg, state, proposer_index, randao_reveal, eth1_data, graffiti,
attestations, deposits, exits, sync_aggregate, execution_payload) attestations, deposits, exits, sync_aggregate, execution_payload, @[])
let res = process_block( let res = process_block(
cfg, state.data, blck.asSigVerified(), verificationFlags, cache) cfg, state.data, blck.asSigVerified(), verificationFlags, cache)

View File

@ -57,7 +57,7 @@ proc setupEngineAPI*(server: RpcServer) =
# https://github.com/ethereum/execution-apis/blob/v1.0.0-beta.3/src/engine/paris.md#engine_forkchoiceupdatedv1 # https://github.com/ethereum/execution-apis/blob/v1.0.0-beta.3/src/engine/paris.md#engine_forkchoiceupdatedv1
server.rpc("engine_forkchoiceUpdatedV1") do( server.rpc("engine_forkchoiceUpdatedV1") do(
update: ForkchoiceStateV1, update: ForkchoiceStateV1,
payloadAttributes: Option[PayloadAttributesV1]) -> ForkchoiceUpdatedResponse: payloadAttributes: Opt[PayloadAttributesV1]) -> ForkchoiceUpdatedResponse:
info "engine_forkchoiceUpdatedV1", info "engine_forkchoiceUpdatedV1",
update, update,
payloadAttributes payloadAttributes
@ -68,7 +68,7 @@ proc setupEngineAPI*(server: RpcServer) =
# https://github.com/ethereum/execution-apis/blob/v1.0.0-beta.3/src/engine/shanghai.md#engine_forkchoiceupdatedv2 # https://github.com/ethereum/execution-apis/blob/v1.0.0-beta.3/src/engine/shanghai.md#engine_forkchoiceupdatedv2
server.rpc("engine_forkchoiceUpdatedV2") do( server.rpc("engine_forkchoiceUpdatedV2") do(
forkchoiceState: ForkchoiceStateV1, payloadAttributes: Option[PayloadAttributesV2]) -> ForkchoiceUpdatedResponse: forkchoiceState: ForkchoiceStateV1, payloadAttributes: Opt[PayloadAttributesV2]) -> ForkchoiceUpdatedResponse:
info "engine_forkchoiceUpdatedV2", info "engine_forkchoiceUpdatedV2",
forkchoiceState, payloadAttributes forkchoiceState, payloadAttributes

View File

@ -134,7 +134,7 @@ cli do(validatorsDir: string, secretsDir: string,
headBlockHash = payload.block_hash, headBlockHash = payload.block_hash,
safeBlockHash = payload.block_hash, safeBlockHash = payload.block_hash,
finalizedBlockHash = ZERO_HASH, finalizedBlockHash = ZERO_HASH,
payloadAttributes = none(consensusFork.PayloadAttributes)) payloadAttributes = Opt.none(consensusFork.PayloadAttributes))
if status != PayloadExecutionStatus.valid: if status != PayloadExecutionStatus.valid:
continue continue
@ -295,6 +295,7 @@ cli do(validatorsDir: string, secretsDir: string,
BeaconBlockValidatorChanges(), BeaconBlockValidatorChanges(),
syncAggregate, syncAggregate,
payload, payload,
@[], # consolidations
noRollback, noRollback,
cache).get() cache).get()

View File

@ -21,7 +21,7 @@ source "${SCRIPTS_DIR}/bash_utils.sh"
download_geth_stable() { download_geth_stable() {
if [[ ! -e "${STABLE_GETH_BINARY}" ]]; then if [[ ! -e "${STABLE_GETH_BINARY}" ]]; then
GETH_VERSION="1.14.0-87246f3c" # https://geth.ethereum.org/downloads GETH_VERSION="1.14.5-0dd173a7" # https://geth.ethereum.org/downloads
GETH_URL="https://gethstore.blob.core.windows.net/builds/" GETH_URL="https://gethstore.blob.core.windows.net/builds/"
case "${OS}-${ARCH}" in case "${OS}-${ARCH}" in

View File

@ -12,7 +12,6 @@ import
# Utilities # Utilities
chronicles, chronicles,
unittest2, unittest2,
stew/results,
# Beacon chain internals # Beacon chain internals
../../../beacon_chain/spec/[beaconstate, state_transition_block], ../../../beacon_chain/spec/[beaconstate, state_transition_block],
../../../beacon_chain/spec/datatypes/altair, ../../../beacon_chain/spec/datatypes/altair,

View File

@ -12,7 +12,6 @@ import
# Utilities # Utilities
chronicles, chronicles,
unittest2, unittest2,
stew/results,
# Beacon chain internals # Beacon chain internals
../../../beacon_chain/spec/state_transition_block, ../../../beacon_chain/spec/state_transition_block,
../../../beacon_chain/spec/datatypes/bellatrix, ../../../beacon_chain/spec/datatypes/bellatrix,

View File

@ -12,7 +12,6 @@ import
# Utilities # Utilities
chronicles, chronicles,
unittest2, unittest2,
stew/results,
# Beacon chain internals # Beacon chain internals
../../../beacon_chain/spec/state_transition_block, ../../../beacon_chain/spec/state_transition_block,
../../../beacon_chain/spec/datatypes/capella, ../../../beacon_chain/spec/datatypes/capella,

View File

@ -12,7 +12,6 @@ import
# Utilities # Utilities
chronicles, chronicles,
unittest2, unittest2,
stew/results,
# Beacon chain internals # Beacon chain internals
../../../beacon_chain/spec/state_transition_block, ../../../beacon_chain/spec/state_transition_block,
../../../beacon_chain/spec/datatypes/deneb, ../../../beacon_chain/spec/datatypes/deneb,

View File

@ -12,7 +12,6 @@ import
# Utilities # Utilities
chronicles, chronicles,
unittest2, unittest2,
stew/results,
# Beacon chain internals # Beacon chain internals
../../../beacon_chain/spec/state_transition_block, ../../../beacon_chain/spec/state_transition_block,
../../../beacon_chain/spec/datatypes/electra, ../../../beacon_chain/spec/datatypes/electra,

View File

@ -12,7 +12,6 @@ import
# Utilities # Utilities
chronicles, chronicles,
unittest2, unittest2,
stew/results,
# Beacon chain internals # Beacon chain internals
../../../beacon_chain/spec/[beaconstate, state_transition_block], ../../../beacon_chain/spec/[beaconstate, state_transition_block],
../../../beacon_chain/spec/datatypes/phase0, ../../../beacon_chain/spec/datatypes/phase0,

View File

@ -10,7 +10,7 @@
import import
# Status libraries # Status libraries
stew/[byteutils, results], chronicles, stew/byteutils, chronicles,
taskpools, taskpools,
# Internals # Internals
../../beacon_chain/spec/[helpers, forks, state_transition_block], ../../beacon_chain/spec/[helpers, forks, state_transition_block],

View File

@ -12,7 +12,7 @@ import
std/json, std/json,
yaml, yaml,
kzg4844/kzg_ex, kzg4844/kzg_ex,
stew/[byteutils, results], stew/byteutils,
../testutil, ../testutil,
./fixtures_utils, ./os_ops ./fixtures_utils, ./os_ops

View File

@ -10,7 +10,6 @@
import import
# Status lib # Status lib
stew/results,
chronicles, chronicles,
# Internal # Internal
../../beacon_chain/validators/[slashing_protection, slashing_protection_v2], ../../beacon_chain/validators/[slashing_protection, slashing_protection_v2],

View File

@ -10,10 +10,10 @@
import import
# Standard library # Standard library
std/[os], std/os,
# Status lib # Status lib
eth/db/[kvstore, kvstore_sqlite3], eth/db/[kvstore, kvstore_sqlite3],
stew/[results, endians2], stew/endians2,
# Internal # Internal
../../beacon_chain/validators/slashing_protection, ../../beacon_chain/validators/slashing_protection,
../../beacon_chain/spec/[helpers], ../../beacon_chain/spec/[helpers],

View File

@ -10,7 +10,8 @@
import import
std/[json, os, random, sequtils, strutils, times], std/[json, os, random, sequtils, strutils, times],
chronos, stew/[base10, results], chronicles, unittest2, chronos,
stew/base10, chronicles, unittest2,
yaml, yaml,
../beacon_chain/beacon_chain_db, ../beacon_chain/beacon_chain_db,
../beacon_chain/spec/deposit_snapshots, ../beacon_chain/spec/deposit_snapshots,
@ -39,7 +40,7 @@ proc ifNecessaryMigrateDCS(db: BeaconChainDB,
db.putDepositContractSnapshot upgradeProc(oldSnapshot.get) db.putDepositContractSnapshot upgradeProc(oldSnapshot.get)
# Hexlified copy of # Hexlified copy of
# eth2-networks/shared/mainnet/genesis_deposit_contract_snapshot.ssz # mainnet/metadata/genesis_deposit_contract_snapshot.ssz
let ds1: seq[byte] = hexToSeqByte( let ds1: seq[byte] = hexToSeqByte(
""" """
eeea1373d4aa9e099d7c9deddb694db9aeb4577755ef83f9b6345ce4357d9abfca3bfce2c eeea1373d4aa9e099d7c9deddb694db9aeb4577755ef83f9b6345ce4357d9abfca3bfce2c

View File

@ -9,7 +9,7 @@
{.used.} {.used.}
import import
stew/results, presto/client, presto/client,
testutils/unittests, chronicles, testutils/unittests, chronicles,
../beacon_chain/spec/eth2_apis/[eth2_rest_serialization, rest_types], ../beacon_chain/spec/eth2_apis/[eth2_rest_serialization, rest_types],
./testutil ./testutil

View File

@ -389,6 +389,7 @@ const
("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01", "0.9995"), ("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01", "0.9995"),
("0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101", "0.0005"), ("0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101", "0.0005"),
] ]
ContributionDataVectors = [ ContributionDataVectors = [
("0xffffffffffffffffffffffffffff7f7f", "0.9844"), ("0xffffffffffffffffffffffffffff7f7f", "0.9844"),
("0xffffffffffffffffffffffff7f7f7f7f", "0.9688"), ("0xffffffffffffffffffffffff7f7f7f7f", "0.9688"),
@ -446,6 +447,15 @@ const
([("0xff01", Slot(0), 0'u64), ("0xff01", Slot(0), 1'u64)], 16) ([("0xff01", Slot(0), 0'u64), ("0xff01", Slot(0), 1'u64)], 16)
] ]
UInt256ScoreVectors = [
("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"0x0000000000000000000000000000000000000000000000000000000000000001",
"0"),
("0x10",
"0x10",
"32")
]
proc init(t: typedesc[Eth2Digest], data: string): Eth2Digest = proc init(t: typedesc[Eth2Digest], data: string): Eth2Digest =
let length = len(data) let length = len(data)
var dst = Eth2Digest() var dst = Eth2Digest()
@ -755,6 +765,25 @@ suite "Validator Client test suite":
score == "0.0000" score == "0.0000"
isLowestScoreAggregatedAttestation(adata.data) == true isLowestScoreAggregatedAttestation(adata.data) == true
test "getProduceBlockResponseV3Score() default test":
let
bdata1 = ProduceBlockResponseV3()
bdata2 = ProduceBlockResponseV3(
consensusValue: Opt.some(UInt256.zero)
)
bdata3 = ProduceBlockResponseV3(
executionValue: Opt.some(UInt256.zero),
)
bdata4 = ProduceBlockResponseV3(
consensusValue: Opt.some(UInt256.zero),
executionValue: Opt.some(UInt256.zero)
)
check:
shortScore(getProduceBlockResponseV3Score(bdata1)) == "0"
shortScore(getProduceBlockResponseV3Score(bdata2)) == "0"
shortScore(getProduceBlockResponseV3Score(bdata3)) == "0"
shortScore(getProduceBlockResponseV3Score(bdata4)) == "0"
test "getSyncCommitteeContributionDataScore() test vectors": test "getSyncCommitteeContributionDataScore() test vectors":
for vector in ContributionDataVectors: for vector in ContributionDataVectors:
let let
@ -773,11 +802,24 @@ suite "Validator Client test suite":
check: check:
score == vector[5] score == vector[5]
test "getProduceBlockResponseV3Score() test vectors":
for vector in UInt256ScoreVectors:
let
value1 = strictParse(vector[0], UInt256, 16).get()
value2 = strictParse(vector[1], UInt256, 16).get()
bdata = ProduceBlockResponseV3(
executionValue: Opt.some(value1),
consensusValue: Opt.some(value2)
)
check shortScore(getProduceBlockResponseV3Score(bdata)) == vector[2]
test "getUniqueVotes() test vectors": test "getUniqueVotes() test vectors":
for vector in AttestationBitsVectors: for vector in AttestationBitsVectors:
let let
a1 = phase0.Attestation.init(vector[0][0][0], vector[0][0][1], vector[0][0][2]) a1 = phase0.Attestation.init(vector[0][0][0], vector[0][0][1],
a2 = phase0.Attestation.init(vector[0][1][0], vector[0][1][1], vector[0][1][2]) vector[0][0][2])
a2 = phase0.Attestation.init(vector[0][1][0], vector[0][1][1],
vector[0][1][2])
check getUniqueVotes([a1, a2]) == vector[1] check getUniqueVotes([a1, a2]) == vector[1]
asyncTest "firstSuccessParallel() API timeout test": asyncTest "firstSuccessParallel() API timeout test":
@ -850,6 +892,7 @@ suite "Validator Client test suite":
let response = vc.bestSuccess( let response = vc.bestSuccess(
RestPlainResponse, RestPlainResponse,
uint64, uint64,
float64,
100.milliseconds, 100.milliseconds,
AllBeaconNodeStatuses, AllBeaconNodeStatuses,
{BeaconNodeRole.Duties}, {BeaconNodeRole.Duties},

View File

@ -71,13 +71,14 @@ func checkResponse(a, b: openArray[KeystoreData]): bool =
suite "Validator pool": suite "Validator pool":
test "Doppelganger for genesis validator": test "Doppelganger for genesis validator":
let let
pool = newClone(ValidatorPool())
v = AttachedValidator(activationEpoch: FAR_FUTURE_EPOCH) v = AttachedValidator(activationEpoch: FAR_FUTURE_EPOCH)
check: check:
not v.triggersDoppelganger(GENESIS_EPOCH) # no check not v.triggersDoppelganger(GENESIS_EPOCH) # no check
not v.doppelgangerReady(GENESIS_EPOCH.start_slot) # no activation not v.doppelgangerReady(GENESIS_EPOCH.start_slot) # no activation
v.updateValidator(makeValidatorAndIndex(ValidatorIndex(1), GENESIS_EPOCH)) pool[].updateValidator(v, makeValidatorAndIndex(ValidatorIndex(1), GENESIS_EPOCH))
check: check:
not v.triggersDoppelganger(GENESIS_EPOCH) # no check not v.triggersDoppelganger(GENESIS_EPOCH) # no check
@ -94,6 +95,7 @@ suite "Validator pool":
test "Doppelganger for validator that activates in same epoch as check": test "Doppelganger for validator that activates in same epoch as check":
let let
pool = newClone(ValidatorPool())
v = AttachedValidator(activationEpoch: FAR_FUTURE_EPOCH) v = AttachedValidator(activationEpoch: FAR_FUTURE_EPOCH)
now = Epoch(10).start_slot() now = Epoch(10).start_slot()
@ -104,7 +106,7 @@ suite "Validator pool":
not v.doppelgangerReady(GENESIS_EPOCH.start_slot) not v.doppelgangerReady(GENESIS_EPOCH.start_slot)
not v.doppelgangerReady(now) not v.doppelgangerReady(now)
v.updateValidator(makeValidatorAndIndex(ValidatorIndex(5), FAR_FUTURE_EPOCH)) pool[].updateValidator(v, makeValidatorAndIndex(ValidatorIndex(5), FAR_FUTURE_EPOCH))
check: # We still don't know when validator activates so we wouldn't trigger check: # We still don't know when validator activates so we wouldn't trigger
not v.triggersDoppelganger(GENESIS_EPOCH) not v.triggersDoppelganger(GENESIS_EPOCH)
@ -113,7 +115,7 @@ suite "Validator pool":
not v.doppelgangerReady(GENESIS_EPOCH.start_slot) not v.doppelgangerReady(GENESIS_EPOCH.start_slot)
not v.doppelgangerReady(now) not v.doppelgangerReady(now)
v.updateValidator(makeValidatorAndIndex(ValidatorIndex(5), now.epoch())) pool[].updateValidator(v, makeValidatorAndIndex(ValidatorIndex(5), now.epoch()))
check: # No check done yet check: # No check done yet
not v.triggersDoppelganger(GENESIS_EPOCH) not v.triggersDoppelganger(GENESIS_EPOCH)

View File

@ -118,8 +118,6 @@ proc build_empty_merge_execution_payload(state: bellatrix.BeaconState):
bellatrix.ExecutionPayloadForSigning(executionPayload: payload, bellatrix.ExecutionPayloadForSigning(executionPayload: payload,
blockValue: Wei.zero) blockValue: Wei.zero)
from stew/saturating_arith import saturate
proc build_empty_execution_payload( proc build_empty_execution_payload(
state: bellatrix.BeaconState, state: bellatrix.BeaconState,
feeRecipient: Eth1Address): bellatrix.ExecutionPayloadForSigning = feeRecipient: Eth1Address): bellatrix.ExecutionPayloadForSigning =
@ -129,8 +127,8 @@ proc build_empty_execution_payload(
latest = state.latest_execution_payload_header latest = state.latest_execution_payload_header
timestamp = compute_timestamp_at_slot(state, state.slot) timestamp = compute_timestamp_at_slot(state, state.slot)
randao_mix = get_randao_mix(state, get_current_epoch(state)) randao_mix = get_randao_mix(state, get_current_epoch(state))
base_fee = calcEip1599BaseFee(GasInt.saturate latest.gas_limit, base_fee = calcEip1599BaseFee(latest.gas_limit,
GasInt.saturate latest.gas_used, latest.gas_used,
latest.base_fee_per_gas) latest.base_fee_per_gas)
var payload = bellatrix.ExecutionPayloadForSigning( var payload = bellatrix.ExecutionPayloadForSigning(
@ -172,6 +170,8 @@ proc addTestBlock*(
cfg, state, getStateField(state, slot) + 1, cache, info, flags).expect( cfg, state, getStateField(state, slot) + 1, cache, info, flags).expect(
"can advance 1") "can advance 1")
debugComment "add consolidations support to addTestBlock"
let let
proposer_index = get_beacon_proposer_index( proposer_index = get_beacon_proposer_index(
state, cache, getStateField(state, slot)).expect("valid proposer index") state, cache, getStateField(state, slot)).expect("valid proposer index")
@ -208,8 +208,6 @@ proc addTestBlock*(
else: else:
default(bellatrix.ExecutionPayloadForSigning) default(bellatrix.ExecutionPayloadForSigning)
debugComment "addTestBlock Electra attestation support"
makeBeaconBlock( makeBeaconBlock(
cfg, cfg,
state, state,
@ -229,6 +227,7 @@ proc addTestBlock*(
BeaconBlockValidatorChanges(), BeaconBlockValidatorChanges(),
sync_aggregate, sync_aggregate,
execution_payload, execution_payload,
@[],
noRollback, noRollback,
cache, cache,
verificationFlags = {skipBlsValidation}) verificationFlags = {skipBlsValidation})

@ -1 +0,0 @@
Subproject commit ab581251bcda11e3cc120cc9e9ad1ad679340949

@ -1 +1 @@
Subproject commit c115f3688c19eb6153e22c1e76477db4ed27fae3 Subproject commit 9ed6c63314899d17e2c3f669adbe2bc915610982

1
vendor/mainnet vendored Submodule

@ -0,0 +1 @@
Subproject commit f6b7882618a5ad2c1d2731ae35e5d16a660d5bb7

2
vendor/nim-blscurve vendored

@ -1 +1 @@
Subproject commit d091a579a2e7c4668140e675a6fb2c78b8c6dc57 Subproject commit f29698d2e9a59453d99db7315a5af58add3c8715

2
vendor/nim-eth vendored

@ -1 +1 @@
Subproject commit c482b4c5b658a77cc96b49d4a397aa6d98472ac7 Subproject commit 9b6497ed8a05ba25ee47142f3fc1f61742b51a6c

@ -1 +1 @@
Subproject commit 1ac1d69f9512d55d15e8218a9dbdff129bf96ddb Subproject commit 4d0b0662ed960ab2c5a1ddbd08f77048bac13ae7

2
vendor/nim-kzg4844 vendored

@ -1 +1 @@
Subproject commit 4fbcfbe4c452313bd440936318a87ed708987d8b Subproject commit f12616d0675d9f6346141ca95f0840ab227eb213

2
vendor/nim-libp2p vendored

@ -1 +1 @@
Subproject commit 21cbe3a91a70811522554e89e6a791172cebfef2 Subproject commit 2fa2c4425f4bb835c0517efc03009925dcd28239

@ -1 +1 @@
Subproject commit 4c4fc6f1436b5e0468a6b3a7929bb603f0b43f33 Subproject commit 9c7dc8c58ff9c3dfb11c2d333171b47659ed824c

@ -1 +1 @@
Subproject commit 2bc945cc9ebfae1b688f72ea59f78fd23873d1d4 Subproject commit 194b715b16766e383b5aef92dd779fb182faf45d

@ -1 +1 @@
Subproject commit afae13adac25b6fa98bacf4b9f38458dc64317b0 Subproject commit 005ee90cb6aa563cdd690910455ea05f916ead3f

2
vendor/nim-snappy vendored

@ -1 +1 @@
Subproject commit aaef74113cadaaca690c6144eae0cf2c2a10db28 Subproject commit 913c426d571cf82601452642e01cd11ea26f7ac6

2
vendor/nim-stew vendored

@ -1 +1 @@
Subproject commit 104132fd0217e846b04dd26a5fbe3e43a4929a05 Subproject commit a0a53c911606cace989074f6b806eb0546a64ef6

2
vendor/nim-stint vendored

@ -1 +1 @@
Subproject commit 3c238df6cd4b9c1f37a9f103383e7d2bbd420c13 Subproject commit 9d2b382c5dc34f0d6bbd93b2a5d65dde85067e0f

2
vendor/nim-web3 vendored

@ -1 +1 @@
Subproject commit 9aed14a7373f51715730712adfde39546708296f Subproject commit b705f816439f0068ece8c234336bc7093222d00f