Merge branch 'feat_eip-7688' into feat_eip-6493

This commit is contained in:
Etan Kissling 2024-06-13 16:00:53 +02:00
commit 176a8117eb
No known key found for this signature in database
GPG Key ID: B21DA824C5A3D03D
90 changed files with 1169 additions and 668 deletions

View File

@ -213,7 +213,7 @@ jobs:
devbuild:
name: "Developer builds"
runs-on: ubuntu-latest
runs-on: ['self-hosted','ubuntu-22.04']
steps:
- name: Checkout
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).
# 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"]
path = vendor/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
ignore = untracked
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"]
path = vendor/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
+ getAttestationDataScore() test vectors OK
+ getLiveness() response deserialization test OK
+ getProduceBlockResponseV3Score() default test OK
+ getProduceBlockResponseV3Score() test vectors OK
+ getSyncCommitteeContributionDataScore() test vectors OK
+ getSyncCommitteeMessageDataScore() test vectors OK
+ getUniqueVotes() 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
```diff
+ addValidatorChangeMessage/getAttesterSlashingMessage OK

View File

@ -593,7 +593,7 @@ define MAKE_DEPOSIT
build/deposit_contract sendDeposits \
$(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 \
--min-delay=$(DEPOSITS_DELAY) \
--max-delay=$(DEPOSITS_DELAY) \

View File

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

View File

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

View File

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

View File

@ -184,7 +184,7 @@ proc updateExecutionClientHead*(
headBlockHash = headExecutionBlockHash,
safeBlockHash = newHead.safeExecutionBlockHash,
finalizedBlockHash = newHead.finalizedExecutionBlockHash,
payloadAttributes = none attributes)
payloadAttributes = Opt.none attributes)
# Can't use dag.head here because it hasn't been updated yet
let
@ -374,7 +374,7 @@ proc runProposalForkchoiceUpdated*(
let (status, _) = await self.elManager.forkchoiceUpdated(
headBlockHash, safeBlockHash,
beaconHead.finalizedExecutionBlockHash,
payloadAttributes = some fcPayloadAttributes)
payloadAttributes = Opt.some fcPayloadAttributes)
debug "Fork-choice updated for proposal", status
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.
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)
# 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 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.} =
let tr = TransactionArgs(
`from`: web3.defaultAccount.some,
data: code.some,
gas: Quantity(3000000).some,
gasPrice: Quantity(1).some)
`from`: Opt.some web3.defaultAccount,
data: Opt.some code,
gas: Opt.some Quantity(3000000),
gasPrice: Opt.some Quantity(1))
let r = await web3.send(tr)
result = await web3.getMinedTransactionReceipt(r)
proc sendEth(web3: Web3, to: Eth1Address, valueEth: int): Future[TxHash] =
let tr = TransactionArgs(
`from`: web3.defaultAccount.some,
`from`: Opt.some web3.defaultAccount,
# TODO: Force json-rpc to generate 'data' field
# should not be needed anymore, new execution-api schema
# is using `input` field
data: some(newSeq[byte]()),
gas: Quantity(3000000).some,
gasPrice: Quantity(1).some,
value: some(valueEth.u256 * 1000000000000000000.u256),
to: some(to))
data: Opt.some(newSeq[byte]()),
gas: Opt.some Quantity(3000000),
gasPrice: Opt.some Quantity(1),
value: Opt.some(valueEth.u256 * 1000000000000000000.u256),
to: Opt.some(to))
web3.send(tr)
type
@ -153,7 +153,7 @@ proc ethToWei(eth: UInt256): UInt256 =
proc initWeb3(web3Url, privateKey: string): Future[Web3] {.async.} =
result = await newWeb3(web3Url)
if privateKey.len != 0:
result.privateKey = some(PrivateKey.fromHex(privateKey)[])
result.privateKey = Opt.some(PrivateKey.fromHex(privateKey)[])
else:
let accounts = await result.provider.eth_accounts()
doAssert(accounts.len > 0)

View File

@ -106,7 +106,7 @@ type
Running, Closing, Closed
ELManager* = ref object
eth1Network: Option[Eth1Network]
eth1Network: Opt[Eth1Network]
## If this value is supplied the EL manager will check whether
## all configured EL nodes are connected to the same network.
@ -133,7 +133,7 @@ type
## also includes blocks without deposits because we must
## vote for a block only if it's part of our known history.
syncTargetBlock: Option[Eth1BlockNumber]
syncTargetBlock: Opt[Eth1BlockNumber]
chainSyncingLoopFut: Future[void]
exchangeTransitionConfigurationLoopFut: Future[void]
@ -177,7 +177,7 @@ type
depositContractSyncStatus: DepositContractSyncStatus
## Are we sure that this EL has synced the deposit contract?
lastPayloadId: Option[PayloadID]
lastPayloadId: Opt[PayloadID]
FullBlockId* = object
number: Eth1BlockNumber
@ -419,7 +419,7 @@ func asConsensusType*(payloadWithValue: BellatrixExecutionPayloadWithValue):
executionPayload: payloadWithValue.executionPayload.asConsensusType,
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
func asConsensusType*(rpcExecutionPayload: ExecutionPayloadV1OrV2|ExecutionPayloadV2):
@ -584,12 +584,13 @@ func asConsensusType*(rpcExecutionPayload: ExecutionPayloadV4):
blob_versioned_hashes:
if tt.payload.blobVersionedHashes.isSome:
Opt.some(
List[deneb.VersionedHash, Limit MAX_BLOB_COMMITMENTS_PER_BLOCK]
List[stable.VersionedHash, Limit MAX_BLOB_COMMITMENTS_PER_BLOCK]
.init(tt.payload.blobVersionedHashes.get.mapIt(
deneb.VersionedHash(it))))
stable.VersionedHash(it))))
else:
Opt.none(
List[deneb.VersionedHash, Limit MAX_BLOB_COMMITMENTS_PER_BLOCK])),
List[stable.VersionedHash,
Limit MAX_BLOB_COMMITMENTS_PER_BLOCK])),
signature: Eip6493TransactionSignature(
`from`:
if tt.signature.`from`.isSome:
@ -751,97 +752,97 @@ func asEngineExecutionPayload*(executionPayload: electra.ExecutionPayload):
payload: engine_api_types.TransactionPayload(
`type`:
if tt.payload.`type`.isSome:
options.some(tt.payload.`type`.get.Quantity)
Opt.some(tt.payload.`type`.get.Quantity)
else:
options.none(Quantity),
Opt.none(Quantity),
chainId:
if tt.payload.chain_id.isSome:
options.some(tt.payload.chain_id.get.Quantity)
Opt.some(tt.payload.chain_id.get.Quantity)
else:
options.none(Quantity),
Opt.none(Quantity),
nonce:
if tt.payload.nonce.isSome:
options.some(tt.payload.nonce.get.Quantity)
Opt.some(tt.payload.nonce.get.Quantity)
else:
options.none(Quantity),
Opt.none(Quantity),
maxFeesPerGas:
if tt.payload.max_fees_per_gas.isSome:
options.some(engine_api_types.TransactionFeesPerGas(
Opt.some(engine_api_types.TransactionFeesPerGas(
regular:
if tt.payload.max_fees_per_gas.get.regular.isSome:
options.some(tt.payload.max_fees_per_gas.get.regular.get)
Opt.some(tt.payload.max_fees_per_gas.get.regular.get)
else:
options.none(UInt256),
Opt.none(UInt256),
blob:
if tt.payload.max_fees_per_gas.get.blob.isSome:
options.some(tt.payload.max_fees_per_gas.get.blob.get)
Opt.some(tt.payload.max_fees_per_gas.get.blob.get)
else:
options.none(UInt256)))
Opt.none(UInt256)))
else:
options.none(engine_api_types.TransactionFeesPerGas),
Opt.none(engine_api_types.TransactionFeesPerGas),
gas:
if tt.payload.gas.isSome:
options.some(tt.payload.gas.get.Quantity)
Opt.some(tt.payload.gas.get.Quantity)
else:
options.none(Quantity),
Opt.none(Quantity),
to:
if tt.payload.to.isSome:
options.some(Address(tt.payload.to.get.data))
Opt.some(Address(tt.payload.to.get.data))
else:
options.none(Address),
Opt.none(Address),
value:
if tt.payload.value.isSome:
options.some(tt.payload.value.get)
Opt.some(tt.payload.value.get)
else:
options.none(UInt256),
Opt.none(UInt256),
input:
if tt.payload.input.isSome:
options.some(distinctBase(tt.payload.input.get))
Opt.some(distinctBase(tt.payload.input.get))
else:
options.none(seq[byte]),
Opt.none(seq[byte]),
accessList:
if tt.payload.access_list.isSome:
options.some(distinctBase(tt.payload.access_list.get).mapIt(
Opt.some(distinctBase(tt.payload.access_list.get).mapIt(
AccessTuple(
address: Address(it.address.data),
storage_keys: distinctBase(it.storage_keys)
.mapIt(FixedBytes[32](it.data)))))
else:
options.none(seq[AccessTuple]),
Opt.none(seq[AccessTuple]),
maxPriorityFeesPerGas:
if tt.payload.max_priority_fees_per_gas.isSome:
options.some(engine_api_types.TransactionFeesPerGas(
Opt.some(engine_api_types.TransactionFeesPerGas(
regular:
if tt.payload.max_priority_fees_per_gas.get.regular.isSome:
options.some(
Opt.some(
tt.payload.max_priority_fees_per_gas.get.regular.get)
else:
options.none(UInt256),
Opt.none(UInt256),
blob:
if tt.payload.max_priority_fees_per_gas.get.blob.isSome:
options.some(
Opt.some(
tt.payload.max_priority_fees_per_gas.get.blob.get)
else:
options.none(UInt256)))
Opt.none(UInt256)))
else:
options.none(engine_api_types.TransactionFeesPerGas),
Opt.none(engine_api_types.TransactionFeesPerGas),
blobVersionedHashes:
if tt.payload.blob_versioned_hashes.isSome:
options.some(distinctBase(tt.payload.blob_versioned_hashes.get)
Opt.some(distinctBase(tt.payload.blob_versioned_hashes.get)
.mapIt(FixedBytes[32](it)))
else:
options.none(seq[FixedBytes[32]])),
Opt.none(seq[FixedBytes[32]])),
signature: engine_api_types.TransactionSignature(
`from`:
if tt.signature.`from`.isSome:
options.some(Address(tt.signature.`from`.get.data))
Opt.some(Address(tt.signature.`from`.get.data))
else:
options.none(Address),
Opt.none(Address),
ecdsaSignature:
if tt.signature.ecdsa_signature.isSome:
options.some(FixedBytes[65](tt.signature.ecdsa_signature.get))
Opt.some(FixedBytes[65](tt.signature.ecdsa_signature.get))
else:
options.none(FixedBytes[65])))
Opt.none(FixedBytes[65])))
template getDepositReceipt(dr: DepositReceipt): DepositReceiptV1 =
DepositReceiptV1(
@ -975,15 +976,15 @@ func areSameAs(expectedParams: Option[NextExpectedPayloadParams],
proc forkchoiceUpdated(rpcClient: RpcClient,
state: ForkchoiceStateV1,
payloadAttributes: Option[PayloadAttributesV1] |
Option[PayloadAttributesV2] |
Option[PayloadAttributesV3]):
payloadAttributes: Opt[PayloadAttributesV1] |
Opt[PayloadAttributesV2] |
Opt[PayloadAttributesV3]):
Future[ForkchoiceUpdatedResponse] =
when payloadAttributes is Option[PayloadAttributesV1]:
when payloadAttributes is Opt[PayloadAttributesV1]:
rpcClient.engine_forkchoiceUpdatedV1(state, payloadAttributes)
elif payloadAttributes is Option[PayloadAttributesV2]:
elif payloadAttributes is Opt[PayloadAttributesV2]:
rpcClient.engine_forkchoiceUpdatedV2(state, payloadAttributes)
elif payloadAttributes is Option[PayloadAttributesV3]:
elif payloadAttributes is Opt[PayloadAttributesV3]:
rpcClient.engine_forkchoiceUpdatedV3(state, payloadAttributes)
else:
static: doAssert false
@ -1013,7 +1014,7 @@ proc getPayloadFromSingleEL(
headBlockHash: headBlock.asBlockHash,
safeBlockHash: safeBlock.asBlockHash,
finalizedBlockHash: finalizedBlock.asBlockHash),
some PayloadAttributesV1(
Opt.some PayloadAttributesV1(
timestamp: Quantity timestamp,
prevRandao: FixedBytes[32] randomData.data,
suggestedFeeRecipient: suggestedFeeRecipient))
@ -1023,7 +1024,7 @@ proc getPayloadFromSingleEL(
headBlockHash: headBlock.asBlockHash,
safeBlockHash: safeBlock.asBlockHash,
finalizedBlockHash: finalizedBlock.asBlockHash),
some PayloadAttributesV2(
Opt.some PayloadAttributesV2(
timestamp: Quantity timestamp,
prevRandao: FixedBytes[32] randomData.data,
suggestedFeeRecipient: suggestedFeeRecipient,
@ -1037,7 +1038,7 @@ proc getPayloadFromSingleEL(
headBlockHash: headBlock.asBlockHash,
safeBlockHash: safeBlock.asBlockHash,
finalizedBlockHash: finalizedBlock.asBlockHash),
some PayloadAttributesV3(
Opt.some PayloadAttributesV3(
timestamp: Quantity timestamp,
prevRandao: FixedBytes[32] randomData.data,
suggestedFeeRecipient: suggestedFeeRecipient,
@ -1537,9 +1538,9 @@ proc sendNewPayload*(
proc forkchoiceUpdatedForSingleEL(
connection: ELConnection,
state: ref ForkchoiceStateV1,
payloadAttributes: Option[PayloadAttributesV1] |
Option[PayloadAttributesV2] |
Option[PayloadAttributesV3]
payloadAttributes: Opt[PayloadAttributesV1] |
Opt[PayloadAttributesV2] |
Opt[PayloadAttributesV3]
): Future[PayloadStatusV1] {.async: (raises: [CatchableError]).} =
let
rpcClient = await connection.connectedRpcClient()
@ -1559,10 +1560,10 @@ proc forkchoiceUpdatedForSingleEL(
proc forkchoiceUpdated*(
m: ELManager,
headBlockHash, safeBlockHash, finalizedBlockHash: Eth2Digest,
payloadAttributes: Option[PayloadAttributesV1] |
Option[PayloadAttributesV2] |
Option[PayloadAttributesV3]
): Future[(PayloadExecutionStatus, Option[BlockHash])] {.
payloadAttributes: Opt[PayloadAttributesV1] |
Opt[PayloadAttributesV2] |
Opt[PayloadAttributesV3]
): Future[(PayloadExecutionStatus, Opt[BlockHash])] {.
async: (raises: [CancelledError]).} =
doAssert not headBlockHash.isZero
@ -1579,16 +1580,16 @@ proc forkchoiceUpdated*(
# payload (`Hash32()` if none yet finalized)"
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 =
if payloadAttributes.isSome:
payloadAttributes.get
else:
# As timestamp and prevRandao are both 0, won't false-positive match
(static(default(PayloadAttributesV3)))
elif payloadAttributes is Option[PayloadAttributesV2]:
elif payloadAttributes is Opt[PayloadAttributesV2]:
template payloadAttributesV3(): auto =
if payloadAttributes.isSome:
PayloadAttributesV3(
@ -1600,7 +1601,7 @@ proc forkchoiceUpdated*(
else:
# As timestamp and prevRandao are both 0, won't false-positive match
(static(default(PayloadAttributesV3)))
elif payloadAttributes is Option[PayloadAttributesV1]:
elif payloadAttributes is Opt[PayloadAttributesV1]:
template payloadAttributesV3(): auto =
if payloadAttributes.isSome:
PayloadAttributesV3(
@ -1685,7 +1686,7 @@ proc forkchoiceUpdated*(
pendingRequests.filterIt(not(it.finished())).
mapIt(it.cancelAndWait())
await noCancel allFutures(pending)
return (PayloadExecutionStatus.invalid, none BlockHash)
return (PayloadExecutionStatus.invalid, Opt.none BlockHash)
elif responseProcessor.selectedResponse.isSome:
# We spawn task which will wait for all other responses which are
# still pending, after 30.seconds all pending requests will be
@ -1700,7 +1701,7 @@ proc forkchoiceUpdated*(
pendingRequests.filterIt(not(it.finished())).
mapIt(it.cancelAndWait())
await noCancel allFutures(pending)
return (PayloadExecutionStatus.syncing, none BlockHash)
return (PayloadExecutionStatus.syncing, Opt.none BlockHash)
if len(pendingRequests) == 0:
# All requests failed, we will continue our attempts until deadline
@ -1958,7 +1959,7 @@ proc new*(T: type ELManager,
depositContractBlockHash: Eth2Digest,
db: BeaconChainDB,
engineApiUrls: seq[EngineApiUrl],
eth1Network: Option[Eth1Network]): T =
eth1Network: Opt[Eth1Network]): T =
let
eth1Chain = Eth1Chain.init(
cfg, db, depositContractBlockNumber, depositContractBlockHash)
@ -2043,8 +2044,8 @@ proc syncBlockRange(
await connection.engineApiRequest(
depositContract.getJsonLogs(
DepositEvent,
fromBlock = some blockId(currentBlock),
toBlock = some blockId(maxBlockNumberRequested)),
fromBlock = Opt.some blockId(currentBlock),
toBlock = Opt.some blockId(maxBlockNumberRequested)),
"getLogs", Moment.now(), 30.seconds)
except CancelledError as exc:
debug "Request for deposit logs was interrupted"
@ -2152,7 +2153,6 @@ proc startExchangeTransitionConfigurationLoop(
while true:
# 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 sleepAsync(60.seconds)
@ -2286,7 +2286,7 @@ proc syncEth1Chain(
latestBlockNumber = latestBlock.number
m.syncTargetBlock = some(
m.syncTargetBlock = Opt.some(
if latestBlock.number > m.cfg.ETH1_FOLLOW_DISTANCE.Eth1BlockNumber:
latestBlock.number - m.cfg.ETH1_FOLLOW_DISTANCE
else:

View File

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

View File

@ -9,8 +9,8 @@
import
std/tables,
stew/results,
chronicles, chronos, metrics, taskpools,
chronicles, chronos, metrics,
taskpools,
../spec/[helpers, forks],
../spec/datatypes/[altair, phase0, deneb],
../consensus_object_pools/[
@ -122,7 +122,7 @@ type
# ----------------------------------------------------------------
dag*: ChainDAGRef
attestationPool*: ref AttestationPool
validatorPool: ref ValidatorPool
validatorPool*: ref ValidatorPool
syncCommitteeMsgPool: ref SyncCommitteeMsgPool
lightClientPool: ref LightClientPool
@ -366,7 +366,8 @@ proc checkForPotentialDoppelganger(
proc processAttestation*(
self: ref Eth2Processor, src: MsgSource,
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()
let (afterGenesis, wallSlot) = wallTime.toSlot()
@ -393,19 +394,26 @@ proc processAttestation*(
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"
self.attestationPool[].addAttestation(
attestation, [attester_index], sig, wallTime)
trace "Attestation validated"
self.attestationPool[].addAttestation(
attestation, [attester_index], sig, wallTime)
self.validatorMonitor[].registerAttestation(
src, wallTime, attestation, attester_index)
self.validatorMonitor[].registerAttestation(
src, wallTime, attestation, attester_index)
beacon_attestations_received.inc()
beacon_attestation_delay.observe(delay.toFloatSeconds())
beacon_attestations_received.inc()
beacon_attestation_delay.observe(delay.toFloatSeconds())
ok()
ok()
else:
debug "Dropping attestation", reason = $v.error
beacon_attestations_dropped.inc(1, [$v.error[0]])

View File

@ -9,7 +9,6 @@
import
std/[json, sequtils, times],
stew/saturation_arith,
eth/common/[eth_types_rlp, transaction],
eth/keys,
eth/p2p/discoveryv5/random2,
@ -1254,37 +1253,37 @@ proc ETHExecutionBlockHeaderCreateFromJson(
coinbase: distinctBase(data.miner),
stateRoot: data.stateRoot.asEth2Digest,
txRoot: data.transactionsRoot.asEth2Digest,
receiptRoot: data.receiptsRoot.asEth2Digest,
bloom: distinctBase(data.logsBloom),
receiptsRoot: data.receiptsRoot.asEth2Digest,
logsBloom: distinctBase(data.logsBloom),
difficulty: data.difficulty,
blockNumber: distinctBase(data.number).u256,
gasLimit: cast[int64](data.gasLimit),
gasUsed: cast[int64](data.gasUsed),
timestamp: EthTime(int64.saturate distinctBase(data.timestamp)),
number: distinctBase(data.number),
gasLimit: distinctBase(data.gasLimit),
gasUsed: distinctBase(data.gasUsed),
timestamp: EthTime(distinctBase(data.timestamp)),
extraData: distinctBase(data.extraData),
mixDigest: data.mixHash.asEth2Digest,
mixHash: data.mixHash.asEth2Digest,
nonce: distinctBase(data.nonce.get),
fee: data.baseFeePerGas,
baseFeePerGas: data.baseFeePerGas,
withdrawalsRoot:
if data.withdrawalsRoot.isSome:
some(data.withdrawalsRoot.get.asEth2Digest)
Opt.some(data.withdrawalsRoot.get.asEth2Digest)
else:
none(ExecutionHash256),
Opt.none(ExecutionHash256),
blobGasUsed:
if data.blobGasUsed.isSome:
some distinctBase(data.blobGasUsed.get)
Opt.some distinctBase(data.blobGasUsed.get)
else:
none(uint64),
Opt.none(uint64),
excessBlobGas:
if data.excessBlobGas.isSome:
some distinctBase(data.excessBlobGas.get)
Opt.some distinctBase(data.excessBlobGas.get)
else:
none(uint64),
Opt.none(uint64),
parentBeaconBlockRoot:
if data.parentBeaconBlockRoot.isSome:
some distinctBase(data.parentBeaconBlockRoot.get.asEth2Digest)
Opt.some distinctBase(data.parentBeaconBlockRoot.get.asEth2Digest)
else:
none(ExecutionHash256))
Opt.none(ExecutionHash256))
if rlpHash(blockHeader) != executionHash[]:
return nil
@ -1529,15 +1528,15 @@ proc ETHTransactionsCreateFromJson(
chainId: data.chainId.get(0.Quantity).ChainId,
nonce: distinctBase(data.nonce),
gasPrice: data.gasPrice.GasInt,
maxPriorityFee:
maxPriorityFeePerGas:
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,
to:
if data.to.isSome:
some(distinctBase(data.to.get))
Opt.some(distinctBase(data.to.get))
else:
none(EthAddress),
Opt.none(EthAddress),
value: data.value,
payload: data.input,
accessList:
@ -1555,7 +1554,7 @@ proc ETHTransactionsCreateFromJson(
ExecutionHash256(data: distinctBase(it)))
else:
@[],
V: data.v.int64,
V: data.v.uint64,
R: data.r,
S: data.s)
rlpBytes =
@ -1567,7 +1566,7 @@ proc ETHTransactionsCreateFromJson(
if data.hash.asEth2Digest != hash:
return nil
template isEven(x: int64): bool =
template isEven(x: uint64): bool =
(x and 1) == 0
# Compute from execution address
@ -1614,9 +1613,9 @@ proc ETHTransactionsCreateFromJson(
chainId: distinctBase(tx.chainId).u256,
`from`: ExecutionAddress(data: fromAddress),
nonce: tx.nonce,
maxPriorityFeePerGas: tx.maxPriorityFee.uint64,
maxFeePerGas: tx.maxFee.uint64,
gas: tx.gasLimit.uint64,
maxPriorityFeePerGas: tx.maxPriorityFeePerGas,
maxFeePerGas: tx.maxFeePerGas,
gas: tx.gasLimit,
destinationType: destinationType,
to: ExecutionAddress(data: toAddress),
value: tx.value,
@ -2178,7 +2177,7 @@ proc ETHReceiptsCreateFromJson(
else:
default(ExecutionHash256),
cumulativeGasUsed: distinctBase(data.cumulativeGasUsed).GasInt,
bloom: distinctBase(data.logsBloom),
logsBloom: distinctBase(data.logsBloom),
logs: data.logs.mapIt(Log(
address: distinctBase(it.address),
topics: it.topics.mapIt(distinctBase(it)),
@ -2198,7 +2197,7 @@ proc ETHReceiptsCreateFromJson(
root: rec.hash,
status: rec.status,
gasUsed: distinctBase(data.gasUsed), # Validated during sanity checks.
logsBloom: BloomLogs(data: rec.bloom),
logsBloom: BloomLogs(data: rec.logsBloom),
logs: rec.logs.mapIt(ETHLog(
address: ExecutionAddress(data: it.address),
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
std/[algorithm, sequtils],
chronos, chronicles, stew/results,
chronos, chronicles,
eth/p2p/discoveryv5/[enr, protocol, node, random2],
../spec/datatypes/altair,
../spec/eth2_ssz_serialization,
@ -53,7 +53,7 @@ proc addBootstrapNode*(bootstrapAddr: string,
return
# 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])
if enrRes.isOk:
bootstrapEnrs.add enrRes.value
@ -127,7 +127,7 @@ proc queryRandom*(
forkId: ENRForkID,
wantedAttnets: AttnetBits,
wantedSyncnets: SyncnetBits,
minScore: int): Future[seq[Node]] {.async.} =
minScore: int): Future[seq[Node]] {.async: (raises: [CancelledError]).} =
## Perform a discovery query for a random target
## (forkId) and matching at least one of the attestation subnets.
@ -143,7 +143,7 @@ proc queryRandom*(
peerForkId =
try:
SSZ.decode(eth2FieldBytes, ENRForkID)
except SszError as e:
except SerializationError as e:
debug "Could not decode the eth2 field of peer",
peer = n.record.toURI(), exception = e.name, msg = e.msg
continue
@ -156,7 +156,7 @@ proc queryRandom*(
let attnetsNode =
try:
SSZ.decode(attnetsBytes.get(), AttnetBits)
except SszError as e:
except SerializationError as e:
debug "Could not decode the attnets ERN bitfield of peer",
peer = n.record.toURI(), exception = e.name, msg = e.msg
continue
@ -170,7 +170,7 @@ proc queryRandom*(
let syncnetsNode =
try:
SSZ.decode(syncnetsBytes.get(), SyncnetBits)
except SszError as e:
except SerializationError as e:
debug "Could not decode the syncnets ENR bitfield of peer",
peer = n.record.toURI(), exception = e.name, msg = e.msg
continue

View File

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

View File

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

View File

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

View File

@ -147,14 +147,16 @@ func getVanityLogs(stdoutKind: StdoutLogKind): VanityLogs =
onFinalizedMergeTransitionBlock: bellatrixBlink,
onUpgradeToCapella: capellaColor,
onKnownBlsToExecutionChange: capellaBlink,
onUpgradeToDeneb: denebColor)
onUpgradeToDeneb: denebColor,
onUpgradeToElectra: electraColor)
of StdoutLogKind.NoColors:
VanityLogs(
onMergeTransitionBlock: bellatrixMono,
onFinalizedMergeTransitionBlock: bellatrixMono,
onUpgradeToCapella: capellaMono,
onKnownBlsToExecutionChange: capellaMono,
onUpgradeToDeneb: denebMono)
onUpgradeToDeneb: denebMono,
onUpgradeToElectra: electraMono)
of StdoutLogKind.Json, StdoutLogKind.None:
VanityLogs(
onMergeTransitionBlock:
@ -166,12 +168,14 @@ func getVanityLogs(stdoutKind: StdoutLogKind): VanityLogs =
onKnownBlsToExecutionChange:
(proc() = notice "🦉 BLS to execution changed 🦉"),
onUpgradeToDeneb:
(proc() = notice "🐟 Proto-Danksharding is ON 🐟"))
(proc() = notice "🐟 Proto-Danksharding is ON 🐟"),
onUpgradeToElectra:
(proc() = notice "🦒 [PH] Electra 🦒"))
func getVanityMascot(consensusFork: ConsensusFork): string =
case consensusFork
of ConsensusFork.Electra:
" "
"🦒"
of ConsensusFork.Deneb:
"🐟"
of ConsensusFork.Capella:
@ -1767,7 +1771,8 @@ proc installMessageValidators(node: BeaconNode) =
): Future[ValidationResult] {.async: (raises: [CancelledError]).} =
return toValidationResult(
await node.processor.processAttestation(
MsgSource.gossip, attestation, subnet_id)))
MsgSource.gossip, attestation, subnet_id,
checkSignature = true, checkValidator = false)))
else:
for it in SubnetId:
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]).} =
return toValidationResult(
await node.processor.processAttestation(
MsgSource.gossip, attestation, subnet_id)))
MsgSource.gossip, attestation, subnet_id,
checkSignature = true, checkValidator = false)))
# 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,
safeBlockHash = payload.block_hash, # stub value
finalizedBlockHash = ZERO_HASH,
payloadAttributes = none(consensusFork.PayloadAttributes))
payloadAttributes = Opt.none(consensusFork.PayloadAttributes))
else: discard
optimisticProcessor = initOptimisticProcessor(
getBeaconTime, optimisticHandler)

View File

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

View File

@ -9,7 +9,6 @@
import
std/sequtils,
stew/results,
chronicles,
chronos/apps/http/httpserver,
./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).
# at your option. This file may not be copied, modified, or distributed except according to those terms.
{.push raises: [].}
import
std/[sequtils],
stew/[results, base10],
stew/base10,
chronicles,
chronos/apps/http/httpdebug,
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).
# at your option. This file may not be copied, modified, or distributed except according to those terms.
{.push raises: [].}
import
stew/[byteutils, results],
stew/byteutils,
chronicles,
eth/p2p/discoveryv5/enr,
libp2p/[multiaddress, multicodec, peerstore],

View File

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

View File

@ -77,7 +77,7 @@ type
BlsResult*[T] = Result[T, cstring]
TrustedSig* = object
data* {.align: 16.}: array[RawSigSize, byte]
blob* {.align: 16.}: array[RawSigSize, byte]
SomeSig* = TrustedSig | ValidatorSig
@ -390,12 +390,9 @@ func toRaw*(x: ValidatorPrivKey): array[32, byte] =
# TODO: distinct type - see https://github.com/status-im/nim-blscurve/pull/67
static: doAssert BLS_BACKEND == BLST
result = SecretKey(x).exportRaw()
template toRaw*(x: ValidatorPubKey | ValidatorSig): auto =
x.blob
template toRaw*(x: TrustedSig): auto =
x.data
template toRaw*(x: ValidatorPubKey | SomeSig): auto =
x.blob
func toHex*(x: BlsCurveType): string =
toHex(toRaw(x))
@ -507,7 +504,7 @@ template fromSszBytes*(T: type[ValidatorPubKey | ValidatorSig], bytes: openArray
# Logging
# ----------------------------------------------------------------------
func shortLog*(x: ValidatorPubKey | ValidatorSig): string =
func shortLog*(x: ValidatorPubKey | SomeSig): string =
## Logging for wrapped BLS types
## that may contain valid or non-validated data
byteutils.toHex(x.blob.toOpenArray(0, 3))
@ -520,9 +517,6 @@ func shortLog*(x: ValidatorPrivKey): string =
## Logging for raw unwrapped BLS types
"<private key>"
func shortLog*(x: TrustedSig): string =
byteutils.toHex(x.data.toOpenArray(0, 3))
# Initialization
# ----------------------------------------------------------------------

View File

@ -75,29 +75,6 @@ static: doAssert TIMELY_SOURCE_WEIGHT + TIMELY_TARGET_WEIGHT +
type
### New types
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/altair/beacon-chain.md#custom-types
ParticipationFlags* = uint8
EpochParticipationFlags* =
distinct List[ParticipationFlags, Limit VALIDATOR_REGISTRY_LIMIT]
## Not a HashList because the list sees significant updates every block
## effectively making the cost of clearing the cache higher than the typical
## gains
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/altair/beacon-chain.md#syncaggregate
SyncAggregate* = object
sync_committee_bits*: BitArray[SYNC_COMMITTEE_SIZE]
sync_committee_signature*: ValidatorSig
TrustedSyncAggregate* = object
sync_committee_bits*: BitArray[SYNC_COMMITTEE_SIZE]
sync_committee_signature*: TrustedSig
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/altair/beacon-chain.md#synccommittee
SyncCommittee* = object
pubkeys*: HashArray[Limit SYNC_COMMITTEE_SIZE, ValidatorPubKey]
aggregate_pubkey*: ValidatorPubKey
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.2/specs/altair/validator.md#synccommitteemessage
SyncCommitteeMessage* = object
slot*: Slot
@ -255,8 +232,6 @@ type
## (used to compute safety threshold)
current_max_active_participants*: uint64
InactivityScores* = HashList[uint64, Limit VALIDATOR_REGISTRY_LIMIT]
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/altair/beacon-chain.md#beaconstate
BeaconState* = object
# Versioning
@ -529,8 +504,6 @@ type
SigVerifiedBeaconBlockBody |
TrustedBeaconBlockBody
SomeSyncAggregate* = SyncAggregate | TrustedSyncAggregate
SyncSubcommitteeIndex* = distinct uint8
IndexInSyncCommittee* = distinct uint16
@ -547,45 +520,6 @@ template `[]`*(arr: array[SYNC_COMMITTEE_SIZE, auto] | seq;
makeLimitedU8(SyncSubcommitteeIndex, SYNC_COMMITTEE_SUBNET_COUNT)
makeLimitedU16(IndexInSyncCommittee, SYNC_COMMITTEE_SIZE)
template asList*(epochFlags: EpochParticipationFlags): untyped =
List[ParticipationFlags, Limit VALIDATOR_REGISTRY_LIMIT] epochFlags
template asList*(epochFlags: var EpochParticipationFlags): untyped =
let tmp = cast[ptr List[ParticipationFlags, Limit VALIDATOR_REGISTRY_LIMIT]](addr epochFlags)
tmp[]
template asSeq*(epochFlags: EpochParticipationFlags): untyped =
seq[ParticipationFlags] asList(epochFlags)
template asSeq*(epochFlags: var EpochParticipationFlags): untyped =
let tmp = cast[ptr seq[ParticipationFlags]](addr epochFlags)
tmp[]
template item*(epochFlags: EpochParticipationFlags, idx: ValidatorIndex): ParticipationFlags =
asList(epochFlags)[idx]
template `[]`*(epochFlags: EpochParticipationFlags, idx: ValidatorIndex|uint64|int): ParticipationFlags =
asList(epochFlags)[idx]
template `[]=`*(epochFlags: EpochParticipationFlags, idx: ValidatorIndex, flags: ParticipationFlags) =
asList(epochFlags)[idx] = flags
template add*(epochFlags: var EpochParticipationFlags, flags: ParticipationFlags): bool =
asList(epochFlags).add flags
template len*(epochFlags: EpochParticipationFlags): int =
asList(epochFlags).len
template low*(epochFlags: EpochParticipationFlags): int =
asSeq(epochFlags).low
template high*(epochFlags: EpochParticipationFlags): int =
asSeq(epochFlags).high
template assign*(v: var EpochParticipationFlags, src: EpochParticipationFlags) =
# TODO https://github.com/nim-lang/Nim/issues/21123
mixin assign
var tmp = cast[ptr seq[ParticipationFlags]](addr v)
assign(tmp[], distinctBase src)
func shortLog*(v: SomeBeaconBlock): auto =
(
slot: shortLog(v.slot),
@ -630,23 +564,6 @@ func shortLog*(v: SyncCommitteeMessage): auto =
signature: shortLog(v.signature)
)
func init*(T: type SyncAggregate): SyncAggregate =
SyncAggregate(sync_committee_signature: ValidatorSig.infinity)
func num_active_participants*(v: SomeSyncAggregate): int =
countOnes(v.sync_committee_bits)
func hasSupermajoritySyncParticipation*(
num_active_participants: uint64): bool =
const max_active_participants = SYNC_COMMITTEE_SIZE.uint64
num_active_participants * 3 >= static(max_active_participants * 2)
func hasSupermajoritySyncParticipation*(v: SomeSyncAggregate): bool =
hasSupermajoritySyncParticipation(v.num_active_participants.uint64)
func shortLog*(v: SyncAggregate): auto =
$(v.sync_committee_bits)
func shortLog*(v: ContributionAndProof): auto =
(
aggregator_index: v.aggregator_index,
@ -741,7 +658,3 @@ template asTrusted*(
SigVerifiedSignedBeaconBlock |
MsgTrustedSignedBeaconBlock): TrustedSignedBeaconBlock =
isomorphicCast[TrustedSignedBeaconBlock](x)
template asTrusted*(
x: SyncAggregate): TrustedSyncAggregate =
isomorphicCast[TrustedSyncAggregate](x)

View File

@ -70,9 +70,11 @@ import
../../version,
".."/[beacon_time, crypto, digest, presets]
from kzg4844 import KzgCommitment
export
tables, results, endians2, json_serialization, sszTypes, beacon_time, crypto,
digest, presets
digest, presets, kzg4844
const SPEC_VERSION* = "1.5.0-alpha.2"
## Spec version we're aiming to be compatible with, right now
@ -224,6 +226,11 @@ type
CommitteeValidatorsBits* = BitList[Limit MAX_VALIDATORS_PER_COMMITTEE]
ElectraCommitteeValidatorsBits* =
BitList[Limit MAX_VALIDATORS_PER_COMMITTEE * MAX_COMMITTEES_PER_SLOT]
AttestationCommitteeBits* = BitArray[MAX_COMMITTEES_PER_SLOT.int]
ForkDigest* = distinct array[4, byte]
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.6/specs/phase0/beacon-chain.md#forkdata
@ -281,6 +288,7 @@ type
SomeProposerSlashing* = ProposerSlashing | TrustedProposerSlashing
SomeSignedBeaconBlockHeader* = SignedBeaconBlockHeader | TrustedSignedBeaconBlockHeader
SomeSignedVoluntaryExit* = SignedVoluntaryExit | TrustedSignedVoluntaryExit
SomeSyncAggregate* = SyncAggregate | TrustedSyncAggregate
# Legacy database type, see BeaconChainDB
ImmutableValidatorData* = object
@ -363,6 +371,116 @@ type
message*: VoluntaryExit
signature*: TrustedSig
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/altair/beacon-chain.md#syncaggregate
SyncAggregate* = object
sync_committee_bits*: BitArray[SYNC_COMMITTEE_SIZE]
sync_committee_signature*: ValidatorSig
TrustedSyncAggregate* = object
sync_committee_bits*: BitArray[SYNC_COMMITTEE_SIZE]
sync_committee_signature*: TrustedSig
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.2/specs/bellatrix/beacon-chain.md#custom-types
Transaction* = List[byte, Limit MAX_BYTES_PER_TRANSACTION]
ExecutionAddress* = object
data*: array[20, byte] # TODO there's a network_metadata type, but the import hierarchy's inconvenient
BloomLogs* = object
data*: array[BYTES_PER_LOGS_BLOOM, byte]
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.5/specs/capella/beacon-chain.md#withdrawal
Withdrawal* = object
index*: WithdrawalIndex
validator_index*: uint64
address*: ExecutionAddress
amount*: Gwei
# https://github.com/ethereum/consensus-specs/blob/94a0b6c581f2809aa8aca4ef7ee6fbb63f9d74e9/specs/electra/beacon-chain.md#depositreceipt
DepositReceipt* = object
pubkey*: ValidatorPubKey
withdrawal_credentials*: Eth2Digest
amount*: Gwei
signature*: ValidatorSig
index*: uint64
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.2/specs/electra/beacon-chain.md#executionlayerwithdrawalrequest
ExecutionLayerWithdrawalRequest* = object
source_address*: ExecutionAddress
validator_pubkey*: ValidatorPubKey
amount*: Gwei
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.5/specs/capella/beacon-chain.md#blstoexecutionchange
BLSToExecutionChange* = object
validator_index*: uint64
from_bls_pubkey*: ValidatorPubKey
to_execution_address*: ExecutionAddress
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.2/specs/capella/beacon-chain.md#signedblstoexecutionchange
SignedBLSToExecutionChange* = object
message*: BLSToExecutionChange
signature*: ValidatorSig
SignedBLSToExecutionChangeList* =
List[SignedBLSToExecutionChange, Limit MAX_BLS_TO_EXECUTION_CHANGES]
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/deneb/beacon-chain.md#beaconblockbody
KzgCommitments* = List[KzgCommitment, Limit MAX_BLOB_COMMITMENTS_PER_BLOCK]
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.2/specs/electra/beacon-chain.md#consolidation
Consolidation* = object
source_index*: uint64
target_index*: uint64
epoch*: Epoch
# https://github.com/ethereum/consensus-specs/blob/82133085a1295e93394ebdf71df8f2f6e0962588/specs/electra/beacon-chain.md#signedconsolidation
SignedConsolidation* = object
message*: Consolidation
signature*: ValidatorSig
TrustedSignedConsolidation* = object
message*: Consolidation
signature*: TrustedSig
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.2/specs/capella/beacon-chain.md#historicalsummary
HistoricalSummary* = object
# `HistoricalSummary` matches the components of the phase0
# `HistoricalBatch` making the two hash_tree_root-compatible.
block_summary_root*: Eth2Digest
state_summary_root*: Eth2Digest
# https://github.com/ethereum/consensus-specs/blob/82133085a1295e93394ebdf71df8f2f6e0962588/specs/electra/beacon-chain.md#depositreceipt
PendingBalanceDeposit* = object
index*: uint64
amount*: Gwei
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.2/specs/electra/beacon-chain.md#pendingpartialwithdrawal
PendingPartialWithdrawal* = object
index*: uint64
amount*: Gwei
withdrawable_epoch*: Epoch
# https://github.com/ethereum/consensus-specs/blob/82133085a1295e93394ebdf71df8f2f6e0962588/specs/electra/beacon-chain.md#pendingconsolidation
PendingConsolidation* = object
source_index*: uint64
target_index*: uint64
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/altair/beacon-chain.md#custom-types
ParticipationFlags* = uint8
EpochParticipationFlags* =
distinct List[ParticipationFlags, Limit VALIDATOR_REGISTRY_LIMIT]
## Not a HashList because the list sees significant updates every block
## effectively making the cost of clearing the cache higher than the typical
## gains
InactivityScores* = HashList[uint64, Limit VALIDATOR_REGISTRY_LIMIT]
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/altair/beacon-chain.md#synccommittee
SyncCommittee* = object
pubkeys*: HashArray[Limit SYNC_COMMITTEE_SIZE, ValidatorPubKey]
aggregate_pubkey*: ValidatorPubKey
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.6/specs/phase0/beacon-chain.md#beaconblockheader
BeaconBlockHeader* = object
slot*: Slot
@ -806,9 +924,106 @@ func shortLog*(v: SomeSignedVoluntaryExit): auto =
signature: shortLog(v.signature)
)
func shortLog*(v: SomeSyncAggregate): auto =
$(v.sync_committee_bits)
func init*(T: type SyncAggregate): SyncAggregate =
SyncAggregate(sync_committee_signature: ValidatorSig.infinity)
template asTrusted*(
x: SyncAggregate): TrustedSyncAggregate =
isomorphicCast[TrustedSyncAggregate](x)
func num_active_participants*(v: SomeSyncAggregate): int =
countOnes(v.sync_committee_bits)
func hasSupermajoritySyncParticipation*(
num_active_participants: uint64): bool =
const max_active_participants = SYNC_COMMITTEE_SIZE.uint64
num_active_participants * 3 >= static(max_active_participants * 2)
func hasSupermajoritySyncParticipation*(v: SomeSyncAggregate): bool =
hasSupermajoritySyncParticipation(v.num_active_participants.uint64)
func fromHex*(
T: typedesc[BloomLogs], s: string): T {.raises: [ValueError].} =
hexToByteArray(s, result.data)
func fromHex*(
T: typedesc[ExecutionAddress], s: string): T {.raises: [ValueError].} =
hexToByteArray(s, result.data)
proc writeValue*(
writer: var JsonWriter, value: ExecutionAddress) {.raises: [IOError].} =
writer.writeValue to0xHex(value.data)
proc readValue*(
reader: var JsonReader,
value: var ExecutionAddress) {.raises: [IOError, SerializationError].} =
try:
hexToByteArray(reader.readValue(string), value.data)
except ValueError:
reader.raiseUnexpectedValue(
"ExecutionAddress value should be a valid hex string")
func `$`*(v: ExecutionAddress): string =
v.data.toHex()
func shortLog*(v: BLSToExecutionChange): auto =
(
validator_index: v.validator_index,
from_bls_pubkey: shortLog(v.from_bls_pubkey),
to_execution_address: $v.to_execution_address
)
func shortLog*(v: SignedBLSToExecutionChange): auto =
(
bls_to_execution_change: shortLog(v.message),
signature: shortLog(v.signature)
)
chronicles.formatIt AttestationData: it.shortLog
chronicles.formatIt Checkpoint: it.shortLog
template asList*(epochFlags: EpochParticipationFlags): untyped =
List[ParticipationFlags, Limit VALIDATOR_REGISTRY_LIMIT] epochFlags
template asList*(epochFlags: var EpochParticipationFlags): untyped =
let tmp = cast[ptr List[ParticipationFlags, Limit VALIDATOR_REGISTRY_LIMIT]](addr epochFlags)
tmp[]
template asSeq*(epochFlags: EpochParticipationFlags): untyped =
seq[ParticipationFlags] asList(epochFlags)
template asSeq*(epochFlags: var EpochParticipationFlags): untyped =
let tmp = cast[ptr seq[ParticipationFlags]](addr epochFlags)
tmp[]
template item*(epochFlags: EpochParticipationFlags, idx: ValidatorIndex): ParticipationFlags =
asList(epochFlags)[idx]
template `[]`*(epochFlags: EpochParticipationFlags, idx: ValidatorIndex|uint64|int): ParticipationFlags =
asList(epochFlags)[idx]
template `[]=`*(epochFlags: EpochParticipationFlags, idx: ValidatorIndex, flags: ParticipationFlags) =
asList(epochFlags)[idx] = flags
template add*(epochFlags: var EpochParticipationFlags, flags: ParticipationFlags): bool =
asList(epochFlags).add flags
template len*(epochFlags: EpochParticipationFlags): int =
asList(epochFlags).len
template low*(epochFlags: EpochParticipationFlags): int =
asSeq(epochFlags).low
template high*(epochFlags: EpochParticipationFlags): int =
asSeq(epochFlags).high
template assign*(v: var EpochParticipationFlags, src: EpochParticipationFlags) =
# TODO https://github.com/nim-lang/Nim/issues/21123
mixin assign
var tmp = cast[ptr seq[ParticipationFlags]](addr v)
assign(tmp[], distinctBase src)
const
# http://facweb.cs.depaul.edu/sjost/it212/documents/ascii-pr.htm
PrintableAsciiChars = {' '..'~'}

View File

@ -35,15 +35,6 @@ const
NEWPAYLOAD_TIMEOUT* = 8.seconds
type
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.2/specs/bellatrix/beacon-chain.md#custom-types
Transaction* = List[byte, Limit MAX_BYTES_PER_TRANSACTION]
ExecutionAddress* = object
data*: array[20, byte] # TODO there's a network_metadata type, but the import hierarchy's inconvenient
BloomLogs* = object
data*: array[BYTES_PER_LOGS_BLOOM, byte]
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.2/specs/bellatrix/beacon-chain.md#executionpayload
ExecutionPayload* = object
# Execution block header fields
@ -361,29 +352,6 @@ type
func initHashedBeaconState*(s: BeaconState): HashedBeaconState =
HashedBeaconState(data: s)
func fromHex*(T: typedesc[BloomLogs], s: string): T {.
raises: [ValueError].} =
hexToByteArray(s, result.data)
func fromHex*(T: typedesc[ExecutionAddress], s: string): T {.
raises: [ValueError].} =
hexToByteArray(s, result.data)
proc writeValue*(
writer: var JsonWriter, value: ExecutionAddress) {.raises: [IOError].} =
writer.writeValue to0xHex(value.data)
proc readValue*(reader: var JsonReader, value: var ExecutionAddress) {.
raises: [IOError, SerializationError].} =
try:
hexToByteArray(reader.readValue(string), value.data)
except ValueError:
raiseUnexpectedValue(reader,
"ExecutionAddress value should be a valid hex string")
func `$`*(v: ExecutionAddress): string =
v.data.toHex()
func shortLog*(v: SomeBeaconBlock): auto =
(
slot: shortLog(v.slot),

View File

@ -36,34 +36,6 @@ const
EXECUTION_PAYLOAD_GINDEX* = 25.GeneralizedIndex # execution_payload
type
SignedBLSToExecutionChangeList* =
List[SignedBLSToExecutionChange, Limit MAX_BLS_TO_EXECUTION_CHANGES]
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.5/specs/capella/beacon-chain.md#withdrawal
Withdrawal* = object
index*: WithdrawalIndex
validator_index*: uint64
address*: ExecutionAddress
amount*: Gwei
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.5/specs/capella/beacon-chain.md#blstoexecutionchange
BLSToExecutionChange* = object
validator_index*: uint64
from_bls_pubkey*: ValidatorPubKey
to_execution_address*: ExecutionAddress
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.2/specs/capella/beacon-chain.md#signedblstoexecutionchange
SignedBLSToExecutionChange* = object
message*: BLSToExecutionChange
signature*: ValidatorSig
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.2/specs/capella/beacon-chain.md#historicalsummary
HistoricalSummary* = object
# `HistoricalSummary` matches the components of the phase0
# `HistoricalBatch` making the two hash_tree_root-compatible.
block_summary_root*: Eth2Digest
state_summary_root*: Eth2Digest
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.5/specs/capella/beacon-chain.md#executionpayload
ExecutionPayload* = object
# Execution block header fields
@ -644,19 +616,6 @@ func shortLog*(v: ExecutionPayload): auto =
num_withdrawals: len(v.withdrawals)
)
func shortLog*(v: BLSToExecutionChange): auto =
(
validator_index: v.validator_index,
from_bls_pubkey: shortLog(v.from_bls_pubkey),
to_execution_address: $v.to_execution_address
)
func shortLog*(v: SignedBLSToExecutionChange): auto =
(
bls_to_execution_change: shortLog(v.message),
signature: shortLog(v.signature)
)
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.5/specs/capella/light-client/sync-protocol.md#get_lc_execution_root
func get_lc_execution_root*(
header: LightClientHeader, cfg: RuntimeConfig): Eth2Digest =

View File

@ -36,22 +36,12 @@ const
BLS_MODULUS* = "52435875175126190479447740508185965837690552500527637822603658699938581184513".u256
type
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/deneb/beacon-chain.md#beaconblockbody
KzgCommitments* = List[KzgCommitment, Limit MAX_BLOB_COMMITMENTS_PER_BLOCK]
# TODO this apparently is suppposed to be SSZ-equivalent to Bytes32, but
# current spec doesn't ever SSZ-serialize it or hash_tree_root it
# TODO make `distinct` then add a REST serialization for it specifically, via
# basically to0xHex, then fix BlobSidecarInfoObject to use VersionedHash, not
# string, and rely on REST serialization, rather than serialize VersionedHash
# field manually
VersionedHash* = array[32, byte]
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/deneb/beacon-chain.md#custom-types
BlobIndex* = uint64
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.5/specs/deneb/polynomial-commitments.md#custom-types
Blob* = array[BYTES_PER_FIELD_ELEMENT * FIELD_ELEMENTS_PER_BLOB, byte]
Blob* = array[
BYTES_PER_FIELD_ELEMENT * deneb_preset.FIELD_ELEMENTS_PER_BLOB, byte]
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/deneb/p2p-interface.md#blobsidecar
BlobSidecar* = object
@ -616,7 +606,7 @@ func kzg_commitment_inclusion_proof_gindex*(
(BLOB_KZG_COMMITMENTS_GINDEX shl 1) + 0
# List depth
BLOB_KZG_COMMITMENTS_PROOF_DEPTH =
log2trunc(nextPow2(deneb.KzgCommitments.maxLen.uint64))
log2trunc(nextPow2(KzgCommitments.maxLen.uint64))
# First item
BLOB_KZG_COMMITMENTS_FIRST_GINDEX =
(BLOB_KZG_COMMITMENTS_BASE_GINDEX shl BLOB_KZG_COMMITMENTS_PROOF_DEPTH)

View File

@ -7,7 +7,7 @@
{.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
# TODO Careful, not nil analysis is broken / incomplete and the semantics will
@ -22,7 +22,7 @@ import
ssz_serialization/[merkleization, proofs],
ssz_serialization/types as sszTypes,
../digest,
"."/[base, phase0]
"."/[stable, phase0]
from kzg4844 import KzgCommitment, KzgProof
from stew/bitops2 import log2trunc
@ -35,7 +35,7 @@ from ./capella import
HistoricalSummary, SignedBLSToExecutionChangeList, Withdrawal
from ./deneb import Blobs, BlobsBundle, KzgCommitments, KzgProofs
export json_serialization, base, kzg4844
export json_serialization, stable, kzg4844
const
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.5/specs/altair/light-client/sync-protocol.md#constants
@ -48,72 +48,17 @@ const
CURRENT_SYNC_COMMITTEE_GINDEX = 86.GeneralizedIndex # current_sync_committee
NEXT_SYNC_COMMITTEE_GINDEX = 87.GeneralizedIndex # next_sync_committee
# https://eips.ethereum.org/EIPS/eip-6493
MAX_CALLDATA_SIZE* = 16_777_216
MAX_ACCESS_LIST_STORAGE_KEYS* = 524_288
MAX_ACCESS_LIST_SIZE* = 524_288
type
ChainId* = uint64
Eip6493FeesPerGas* {.sszStableContainer: 16.} = object
regular*: Opt[UInt256]
# EIP-4844
blob*: Opt[UInt256]
Eip6493AccessTuple* = object
address*: ExecutionAddress
storage_keys*: List[Eth2Digest, Limit MAX_ACCESS_LIST_STORAGE_KEYS]
Eip6493TransactionPayload* {.sszStableContainer: 32.} = object
# EIP-2718
`type`*: Opt[uint8]
# EIP-155
chain_id*: Opt[ChainId]
nonce*: Opt[uint64]
max_fees_per_gas*: Opt[Eip6493FeesPerGas]
gas*: Opt[uint64]
to*: Opt[ExecutionAddress]
value*: Opt[UInt256]
input*: Opt[List[byte, Limit MAX_CALLDATA_SIZE]]
# EIP-2930
access_list*: Opt[List[Eip6493AccessTuple, Limit MAX_ACCESS_LIST_SIZE]]
# EIP-1559
max_priority_fees_per_gas*: Opt[Eip6493FeesPerGas]
# EIP-4844
blob_versioned_hashes*:
Opt[List[deneb.VersionedHash, Limit MAX_BLOB_COMMITMENTS_PER_BLOCK]]
Eip6493TransactionSignature* {.sszStableContainer: 16.} = object
`from`*: Opt[ExecutionAddress]
ecdsa_signature*: Opt[array[65, byte]]
Eip6493Transaction* = object
payload*: Eip6493TransactionPayload
signature*: Eip6493TransactionSignature
# https://github.com/ethereum/consensus-specs/blob/94a0b6c581f2809aa8aca4ef7ee6fbb63f9d74e9/specs/electra/beacon-chain.md#depositreceipt
DepositReceipt* = object
pubkey*: ValidatorPubKey
withdrawal_credentials*: Eth2Digest
amount*: Gwei
signature*: ValidatorSig
index*: uint64
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.0/specs/electra/beacon-chain.md#indexedattestation
IndexedAttestation* = object
IndexedAttestation* {.
sszProfile: StableIndexedAttestation.} = object
attesting_indices*:
List[uint64, Limit MAX_VALIDATORS_PER_COMMITTEE * MAX_COMMITTEES_PER_SLOT]
data*: AttestationData
signature*: ValidatorSig
TrustedIndexedAttestation* = object
TrustedIndexedAttestation* {.
sszProfile: StableIndexedAttestation.} = object
# The Trusted version, at the moment, implies that the cryptographic signature was checked.
# It DOES NOT imply that the state transition was verified.
# Currently the code MUST verify the state transition as soon as the signature is verified
@ -135,7 +80,8 @@ type
attestation_2*: TrustedIndexedAttestation # Modified in Electra:EIP7549]
# https://github.com/ethereum/consensus-specs/blob/82133085a1295e93394ebdf71df8f2f6e0962588/specs/electra/beacon-chain.md#executionpayload
ExecutionPayload* = object
ExecutionPayload* {.
sszProfile: StableExecutionPayload.} = object
# Execution block header fields
parent_hash*: Eth2Digest
fee_recipient*: ExecutionAddress
@ -171,7 +117,8 @@ type
blobsBundle*: BlobsBundle
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.0/specs/electra/beacon-chain.md#executionpayloadheader
ExecutionPayloadHeader* = object
ExecutionPayloadHeader* {.
sszProfile: StableExecutionPayloadHeader.} = object
# Execution block header fields
parent_hash*: Eth2Digest
fee_recipient*: ExecutionAddress
@ -199,43 +146,6 @@ type
ExecutePayload* = proc(
execution_payload: ExecutionPayload): bool {.gcsafe, raises: [].}
# https://github.com/ethereum/consensus-specs/blob/82133085a1295e93394ebdf71df8f2f6e0962588/specs/electra/beacon-chain.md#depositreceipt
PendingBalanceDeposit* = object
index*: uint64
amount*: Gwei
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.2/specs/electra/beacon-chain.md#pendingpartialwithdrawal
PendingPartialWithdrawal* = object
index*: uint64
amount*: Gwei
withdrawable_epoch*: Epoch
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.2/specs/electra/beacon-chain.md#executionlayerwithdrawalrequest
ExecutionLayerWithdrawalRequest* = object
source_address*: ExecutionAddress
validator_pubkey*: ValidatorPubKey
amount*: Gwei
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.2/specs/electra/beacon-chain.md#consolidation
Consolidation* = object
source_index*: uint64
target_index*: uint64
epoch*: Epoch
# https://github.com/ethereum/consensus-specs/blob/82133085a1295e93394ebdf71df8f2f6e0962588/specs/electra/beacon-chain.md#signedconsolidation
SignedConsolidation* = object
message*: Consolidation
signature*: ValidatorSig
TrustedSignedConsolidation* = object
message*: Consolidation
signature*: TrustedSig
# https://github.com/ethereum/consensus-specs/blob/82133085a1295e93394ebdf71df8f2f6e0962588/specs/electra/beacon-chain.md#pendingconsolidation
PendingConsolidation* = object
source_index*: uint64
target_index*: uint64
FinalityBranch =
array[log2trunc(FINALIZED_ROOT_GINDEX), Eth2Digest]
@ -355,7 +265,8 @@ type
current_max_active_participants*: uint64
# https://github.com/ethereum/consensus-specs/blob/82133085a1295e93394ebdf71df8f2f6e0962588/specs/electra/beacon-chain.md#beaconstate
BeaconState* = object
BeaconState* {.
sszProfile: StableBeaconState.}= object
# Versioning
genesis_time*: uint64
genesis_validators_root*: Eth2Digest
@ -507,7 +418,8 @@ type
body*: TrustedBeaconBlockBody
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.0/specs/electra/beacon-chain.md#beaconblockbody
BeaconBlockBody* = object
BeaconBlockBody* {.
sszProfile: StableBeaconBlockBody.} = object
randao_reveal*: ValidatorSig
eth1_data*: Eth1Data
## Eth1 data vote
@ -534,7 +446,8 @@ type
consolidations*: List[SignedConsolidation, Limit MAX_CONSOLIDATIONS]
## [New in Electra:EIP7251]
SigVerifiedBeaconBlockBody* = object
SigVerifiedBeaconBlockBody* {.
sszProfile: StableBeaconBlockBody.} = object
## A BeaconBlock body with signatures verified
## including:
## - Randao reveal
@ -575,7 +488,8 @@ type
consolidations*: List[TrustedSignedConsolidation, Limit MAX_CONSOLIDATIONS]
## [New in Electra:EIP7251]
TrustedBeaconBlockBody* = object
TrustedBeaconBlockBody* {.
sszProfile: StableBeaconBlockBody.} = object
## A full verified block
randao_reveal*: TrustedSig
eth1_data*: Eth1Data
@ -642,26 +556,23 @@ type
root* {.dontSerialize.}: Eth2Digest # cached root of signed beacon block
ElectraCommitteeValidatorsBits* =
BitList[Limit MAX_VALIDATORS_PER_COMMITTEE * MAX_COMMITTEES_PER_SLOT]
AttestationCommitteeBits* = BitArray[MAX_COMMITTEES_PER_SLOT.int]
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.0/specs/electra/beacon-chain.md#attestation
Attestation* = object
Attestation* {.
sszProfile: StableAttestation.} = object
aggregation_bits*: ElectraCommitteeValidatorsBits
data*: AttestationData
committee_bits*: AttestationCommitteeBits # [New in Electra:EIP7549]
signature*: ValidatorSig
committee_bits*: AttestationCommitteeBits # [New in Electra:EIP7549]
TrustedAttestation* = object
TrustedAttestation* {.
sszProfile: StableAttestation.} = object
# The Trusted version, at the moment, implies that the cryptographic signature was checked.
# It DOES NOT imply that the state transition was verified.
# Currently the code MUST verify the state transition as soon as the signature is verified
aggregation_bits*: ElectraCommitteeValidatorsBits
data*: AttestationData
committee_bits*: AttestationCommitteeBits # [New in Electra:EIP7549]
signature*: TrustedSig
committee_bits*: AttestationCommitteeBits # [New in Electra:EIP7549]
SomeSignedBeaconBlock* =
SignedBeaconBlock |

View File

@ -0,0 +1,261 @@
# beacon_chain
# Copyright (c) 2024 Status Research & Development GmbH
# Licensed and distributed under either of
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
# at your option. This file may not be copied, modified, or distributed except according to those terms.
{.push raises: [].}
import
ssz_serialization,
./base
export base
const
# https://eips.ethereum.org/EIPS/eip-7688
MAX_ATTESTATION_FIELDS* = 8
MAX_INDEXED_ATTESTATION_FIELDS* = 8
MAX_EXECUTION_PAYLOAD_FIELDS* = 64
MAX_BEACON_BLOCK_BODY_FIELDS* = 64
MAX_BEACON_STATE_FIELDS* = 128
# https://eips.ethereum.org/EIPS/eip-6493
MAX_CALLDATA_SIZE* = 16_777_216
MAX_ACCESS_LIST_STORAGE_KEYS* = 524_288
MAX_ACCESS_LIST_SIZE* = 524_288
type
# TODO this apparently is suppposed to be SSZ-equivalent to Bytes32, but
# current spec doesn't ever SSZ-serialize it or hash_tree_root it
# TODO make `distinct` then add a REST serialization for it specifically, via
# basically to0xHex, then fix BlobSidecarInfoObject to use VersionedHash, not
# string, and rely on REST serialization, rather than serialize VersionedHash
# field manually
VersionedHash* = array[32, byte]
ChainId* = uint64
Eip6493FeesPerGas* {.sszStableContainer: 16.} = object
regular*: Opt[UInt256]
# EIP-4844
blob*: Opt[UInt256]
Eip6493AccessTuple* = object
address*: ExecutionAddress
storage_keys*: List[Eth2Digest, Limit MAX_ACCESS_LIST_STORAGE_KEYS]
Eip6493TransactionPayload* {.sszStableContainer: 32.} = object
# EIP-2718
`type`*: Opt[uint8]
# EIP-155
chain_id*: Opt[ChainId]
nonce*: Opt[uint64]
max_fees_per_gas*: Opt[Eip6493FeesPerGas]
gas*: Opt[uint64]
to*: Opt[ExecutionAddress]
value*: Opt[UInt256]
input*: Opt[List[byte, Limit MAX_CALLDATA_SIZE]]
# EIP-2930
access_list*: Opt[List[Eip6493AccessTuple, Limit MAX_ACCESS_LIST_SIZE]]
# EIP-1559
max_priority_fees_per_gas*: Opt[Eip6493FeesPerGas]
# EIP-4844
blob_versioned_hashes*:
Opt[List[VersionedHash, Limit MAX_BLOB_COMMITMENTS_PER_BLOCK]]
Eip6493TransactionSignature* {.sszStableContainer: 16.} = object
`from`*: Opt[ExecutionAddress]
ecdsa_signature*: Opt[array[65, byte]]
Eip6493Transaction* = object
payload*: Eip6493TransactionPayload
signature*: Eip6493TransactionSignature
# https://eips.ethereum.org/EIPS/eip-7688
StableAttestation* {.
sszStableContainer: MAX_ATTESTATION_FIELDS.} = object
aggregation_bits*: Opt[ElectraCommitteeValidatorsBits]
data*: Opt[AttestationData]
signature*: Opt[ValidatorSig]
committee_bits*: Opt[AttestationCommitteeBits]
StableIndexedAttestation* {.
sszStableContainer: MAX_INDEXED_ATTESTATION_FIELDS.} = object
attesting_indices*: Opt[List[uint64,
Limit MAX_VALIDATORS_PER_COMMITTEE * MAX_COMMITTEES_PER_SLOT]]
data*: Opt[AttestationData]
signature*: Opt[ValidatorSig]
StableAttesterSlashing* = object
attestation_1*: StableIndexedAttestation
attestation_2*: StableIndexedAttestation
StableExecutionPayload* {.
sszStableContainer: MAX_EXECUTION_PAYLOAD_FIELDS.} = object
# Execution block header fields
parent_hash*: Opt[Eth2Digest]
fee_recipient*: Opt[ExecutionAddress]
## 'beneficiary' in the yellow paper
state_root*: Opt[Eth2Digest]
receipts_root*: Opt[Eth2Digest]
logs_bloom*: Opt[BloomLogs]
prev_randao*: Opt[Eth2Digest]
## 'difficulty' in the yellow paper
block_number*: Opt[uint64]
## 'number' in the yellow paper
gas_limit*: Opt[uint64]
gas_used*: Opt[uint64]
timestamp*: Opt[uint64]
extra_data*: Opt[List[byte, MAX_EXTRA_DATA_BYTES]]
base_fee_per_gas*: Opt[UInt256]
# Extra payload fields
block_hash*: Opt[Eth2Digest] # Hash of execution block
transactions*: Opt[List[Eip6493Transaction, MAX_TRANSACTIONS_PER_PAYLOAD]]
withdrawals*: Opt[List[Withdrawal, MAX_WITHDRAWALS_PER_PAYLOAD]]
blob_gas_used*: Opt[uint64]
excess_blob_gas*: Opt[uint64]
deposit_receipts*: Opt[List[DepositReceipt,
MAX_DEPOSIT_RECEIPTS_PER_PAYLOAD]]
withdrawal_requests*: Opt[List[ExecutionLayerWithdrawalRequest,
MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD]]
StableExecutionPayloadHeader* {.
sszStableContainer: MAX_EXECUTION_PAYLOAD_FIELDS.} = object
# Execution block header fields
parent_hash*: Opt[Eth2Digest]
fee_recipient*: Opt[ExecutionAddress]
state_root*: Opt[Eth2Digest]
receipts_root*: Opt[Eth2Digest]
logs_bloom*: Opt[BloomLogs]
prev_randao*: Opt[Eth2Digest]
block_number*: Opt[uint64]
gas_limit*: Opt[uint64]
gas_used*: Opt[uint64]
timestamp*: Opt[uint64]
extra_data*: Opt[List[byte, MAX_EXTRA_DATA_BYTES]]
base_fee_per_gas*: Opt[UInt256]
# Extra payload fields
block_hash*: Opt[Eth2Digest]
## Hash of execution block
transactions_root*: Opt[Eth2Digest]
withdrawals_root*: Opt[Eth2Digest]
blob_gas_used*: Opt[uint64]
excess_blob_gas*: Opt[uint64]
deposit_receipts_root*: Opt[Eth2Digest]
withdrawal_requests_root*: Opt[Eth2Digest]
StableBeaconBlockBody* {.
sszStableContainer: MAX_BEACON_BLOCK_BODY_FIELDS.} = object
randao_reveal*: Opt[ValidatorSig]
eth1_data*: Opt[Eth1Data]
## Eth1 data vote
graffiti*: Opt[GraffitiBytes]
## Arbitrary data
# Operations
proposer_slashings*: Opt[List[ProposerSlashing,
Limit MAX_PROPOSER_SLASHINGS]]
attester_slashings*: Opt[List[StableAttesterSlashing,
Limit MAX_ATTESTER_SLASHINGS_ELECTRA]]
attestations*: Opt[List[StableAttestation, Limit MAX_ATTESTATIONS_ELECTRA]]
deposits*: Opt[List[Deposit, Limit MAX_DEPOSITS]]
voluntary_exits*: Opt[List[SignedVoluntaryExit, Limit MAX_VOLUNTARY_EXITS]]
sync_aggregate*: Opt[SyncAggregate]
# Execution
execution_payload*: Opt[StableExecutionPayload]
bls_to_execution_changes*: Opt[SignedBLSToExecutionChangeList]
blob_kzg_commitments*: Opt[KzgCommitments]
consolidations*: Opt[List[SignedConsolidation, Limit MAX_CONSOLIDATIONS]]
StableBeaconState* {.sszStableContainer: MAX_BEACON_STATE_FIELDS.} = object
# Versioning
genesis_time*: Opt[uint64]
genesis_validators_root*: Opt[Eth2Digest]
slot*: Opt[Slot]
fork*: Opt[Fork]
# History
latest_block_header*: Opt[BeaconBlockHeader]
## `latest_block_header.state_root == ZERO_HASH` temporarily
block_roots*: Opt[HashArray[Limit SLOTS_PER_HISTORICAL_ROOT, Eth2Digest]]
## Needed to process attestations, older to newer
state_roots*: Opt[HashArray[Limit SLOTS_PER_HISTORICAL_ROOT, Eth2Digest]]
historical_roots*: Opt[HashList[Eth2Digest, Limit HISTORICAL_ROOTS_LIMIT]]
## Frozen in Capella, replaced by historical_summaries
# Eth1
eth1_data*: Opt[Eth1Data]
eth1_data_votes*: Opt[HashList[Eth1Data,
Limit(EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH)]]
eth1_deposit_index*: Opt[uint64]
# Registry
validators*: Opt[HashList[Validator, Limit VALIDATOR_REGISTRY_LIMIT]]
balances*: Opt[HashList[Gwei, Limit VALIDATOR_REGISTRY_LIMIT]]
# Randomness
randao_mixes*: Opt[HashArray[
Limit EPOCHS_PER_HISTORICAL_VECTOR, Eth2Digest]]
# Slashings
slashings*: Opt[HashArray[Limit EPOCHS_PER_SLASHINGS_VECTOR, Gwei]]
## Per-epoch sums of slashed effective balances
# Participation
previous_epoch_participation*: Opt[EpochParticipationFlags]
current_epoch_participation*: Opt[EpochParticipationFlags]
# Finality
justification_bits*: Opt[JustificationBits]
## Bit set for every recent justified epoch
previous_justified_checkpoint*: Opt[Checkpoint]
current_justified_checkpoint*: Opt[Checkpoint]
finalized_checkpoint*: Opt[Checkpoint]
# Inactivity
inactivity_scores*: Opt[InactivityScores]
# Light client sync committees
current_sync_committee*: Opt[SyncCommittee]
next_sync_committee*: Opt[SyncCommittee]
# Execution
latest_execution_payload_header*: Opt[StableExecutionPayloadHeader]
# Withdrawals
next_withdrawal_index*: Opt[WithdrawalIndex]
next_withdrawal_validator_index*: Opt[uint64]
# Deep history valid from Capella onwards
historical_summaries*:
Opt[HashList[HistoricalSummary, Limit HISTORICAL_ROOTS_LIMIT]]
deposit_receipts_start_index*: Opt[uint64]
deposit_balance_to_consume*: Opt[Gwei]
exit_balance_to_consume*: Opt[Gwei]
earliest_exit_epoch*: Opt[Epoch]
consolidation_balance_to_consume*: Opt[Gwei]
earliest_consolidation_epoch*: Opt[Epoch]
pending_balance_deposits*: Opt[HashList[PendingBalanceDeposit,
Limit PENDING_BALANCE_DEPOSITS_LIMIT]]
pending_partial_withdrawals*: Opt[HashList[PendingPartialWithdrawal,
Limit PENDING_PARTIAL_WITHDRAWALS_LIMIT]]
pending_consolidations*: Opt[HashList[PendingConsolidation,
Limit PENDING_CONSOLIDATIONS_LIMIT]]

View File

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

View File

@ -487,24 +487,24 @@ proc blockToBlockHeader*(blck: ForkyBeaconBlock): ExecutionBlockHeader =
txRoot = payload.computeTransactionsTrieRoot()
withdrawalsRoot =
when typeof(payload).kind >= ConsensusFork.Capella:
some payload.computeWithdrawalsTrieRoot()
Opt.some payload.computeWithdrawalsTrieRoot()
else:
none(ExecutionHash256)
Opt.none(ExecutionHash256)
blobGasUsed =
when typeof(payload).kind >= ConsensusFork.Deneb:
some payload.blob_gas_used
Opt.some payload.blob_gas_used
else:
none(uint64)
Opt.none(uint64)
excessBlobGas =
when typeof(payload).kind >= ConsensusFork.Deneb:
some payload.excess_blob_gas
Opt.some payload.excess_blob_gas
else:
none(uint64)
Opt.none(uint64)
parentBeaconBlockRoot =
when typeof(payload).kind >= ConsensusFork.Deneb:
some ExecutionHash256(data: blck.parent_root.data)
Opt.some ExecutionHash256(data: blck.parent_root.data)
else:
none(ExecutionHash256)
Opt.none(ExecutionHash256)
ExecutionBlockHeader(
parentHash : payload.parent_hash,
@ -512,17 +512,17 @@ proc blockToBlockHeader*(blck: ForkyBeaconBlock): ExecutionBlockHeader =
coinbase : EthAddress payload.fee_recipient.data,
stateRoot : payload.state_root,
txRoot : txRoot,
receiptRoot : payload.receipts_root,
bloom : payload.logs_bloom.data,
receiptsRoot : payload.receipts_root,
logsBloom : payload.logs_bloom.data,
difficulty : default(DifficultyInt),
blockNumber : payload.block_number.u256,
number : payload.block_number,
gasLimit : cast[GasInt](payload.gas_limit),
gasUsed : cast[GasInt](payload.gas_used),
timestamp : EthTime(int64.saturate payload.timestamp),
extraData : payload.extra_data.asSeq,
mixDigest : payload.prev_randao, # EIP-4399 `mixDigest` -> `prevRandao`
mixHash : payload.prev_randao, # EIP-4399 `mixHash` -> `prevRandao`
nonce : default(BlockNonce),
fee : some payload.base_fee_per_gas,
baseFeePerGas : Opt.some payload.base_fee_per_gas,
withdrawalsRoot : withdrawalsRoot,
blobGasUsed : blobGasUsed, # 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(
genesisFork, genesis_validators_root, msg.message)
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],
validator_changes: BeaconBlockValidatorChanges,
sync_aggregate: SyncAggregate,
execution_payload: ForkyExecutionPayloadForSigning
execution_payload: ForkyExecutionPayloadForSigning,
consolidations: openArray[SignedConsolidation]
): auto =
const consensusFork = typeof(state).kind
@ -411,12 +412,14 @@ func partialBeaconBlock*(
deposits: seq[Deposit],
validator_changes: BeaconBlockValidatorChanges,
sync_aggregate: SyncAggregate,
execution_payload: ForkyExecutionPayloadForSigning
execution_payload: ForkyExecutionPayloadForSigning,
consolidations: seq[SignedConsolidation],
): auto =
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
var res = consensusFork.BeaconBlock(
consensusFork.BeaconBlock(
slot: state.data.slot,
proposer_index: proposer_index.uint64,
parent_root: state.latest_block_root,
@ -429,28 +432,14 @@ func partialBeaconBlock*(
attestations:
List[electra.Attestation, Limit MAX_ATTESTATIONS_ELECTRA](attestations),
deposits: List[Deposit, Limit MAX_DEPOSITS](deposits),
voluntary_exits: validator_changes.voluntary_exits))
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/altair/validator.md#preparing-a-beaconblock
when consensusFork >= ConsensusFork.Altair:
res.body.sync_aggregate = sync_aggregate
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.2/specs/bellatrix/validator.md#block-proposal
when consensusFork >= ConsensusFork.Bellatrix:
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
voluntary_exits: validator_changes.voluntary_exits,
sync_aggregate: sync_aggregate,
execution_payload: execution_payload.executionPayload,
bls_to_execution_changes: validator_changes.bls_to_execution_changes,
blob_kzg_commitments: execution_payload.blobsBundle.commitments,
consolidations:
List[SignedConsolidation, Limit MAX_CONSOLIDATIONS].init(
consolidations)))
proc makeBeaconBlockWithRewards*(
cfg: RuntimeConfig,
@ -464,6 +453,7 @@ proc makeBeaconBlockWithRewards*(
validator_changes: BeaconBlockValidatorChanges,
sync_aggregate: SyncAggregate,
executionPayload: ForkyExecutionPayloadForSigning,
consolidations: seq[SignedConsolidation],
rollback: RollbackForkedHashedProc,
cache: var StateCache,
# TODO:
@ -490,7 +480,7 @@ proc makeBeaconBlockWithRewards*(
partialBeaconBlock(
cfg, state.`kind Data`, proposer_index, randao_reveal, eth1_data,
graffiti, attestations, deposits, validator_changes, sync_aggregate,
executionPayload))
executionPayload, consolidations))
let res = process_block(
cfg, state.`kind Data`.data, blck.`kind Data`.asSigVerified(),
@ -533,9 +523,8 @@ proc makeBeaconBlockWithRewards*(
forkyState.data.latest_execution_payload_header.transactions_root =
transactions_root.get
debugComment "makeBeaconBlock doesn't support Electra (i.e. check for missing beaconblock body fields)"
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(
[hash_tree_root(randao_reveal),
hash_tree_root(eth1_data),
@ -550,7 +539,9 @@ proc makeBeaconBlockWithRewards*(
hash_tree_root(sync_aggregate),
execution_payload_root.get,
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:
raiseAssert "Attempt to use non-Electra payload with post-Deneb state"
@ -593,6 +584,7 @@ proc makeBeaconBlock*(
validator_changes: BeaconBlockValidatorChanges,
sync_aggregate: SyncAggregate,
executionPayload: ForkyExecutionPayloadForSigning,
consolidations: seq[SignedConsolidation],
rollback: RollbackForkedHashedProc, cache: var StateCache,
verificationFlags: UpdateFlags,
transactions_root: Opt[Eth2Digest],
@ -603,8 +595,8 @@ proc makeBeaconBlock*(
? makeBeaconBlockWithRewards(
cfg, state, proposer_index, randao_reveal, eth1_data, graffiti,
attestations, deposits, validator_changes, sync_aggregate,
executionPayload, rollback, cache, verificationFlags, transactions_root,
execution_payload_root, kzg_commitments)
executionPayload, consolidations, rollback, cache, verificationFlags,
transactions_root, execution_payload_root, kzg_commitments)
ok(blockAndRewards.blck)
proc makeBeaconBlock*(
@ -616,12 +608,13 @@ proc makeBeaconBlock*(
validator_changes: BeaconBlockValidatorChanges,
sync_aggregate: SyncAggregate,
executionPayload: ForkyExecutionPayloadForSigning,
consolidations: seq[SignedConsolidation],
rollback: RollbackForkedHashedProc, cache: var StateCache):
Result[ForkedBeaconBlock, cstring] =
makeBeaconBlock(
cfg, state, proposer_index, randao_reveal, eth1_data, graffiti,
attestations, deposits, validator_changes, sync_aggregate,
executionPayload, rollback, cache,
executionPayload, consolidations, rollback, cache,
verificationFlags = {}, transactions_root = Opt.none Eth2Digest,
execution_payload_root = Opt.none Eth2Digest,
kzg_commitments = Opt.none KzgCommitments)
@ -635,13 +628,14 @@ proc makeBeaconBlock*(
validator_changes: BeaconBlockValidatorChanges,
sync_aggregate: SyncAggregate,
executionPayload: ForkyExecutionPayloadForSigning,
consolidations: seq[SignedConsolidation],
rollback: RollbackForkedHashedProc,
cache: var StateCache, verificationFlags: UpdateFlags):
Result[ForkedBeaconBlock, cstring] =
makeBeaconBlock(
cfg, state, proposer_index, randao_reveal, eth1_data, graffiti,
attestations, deposits, validator_changes, sync_aggregate,
executionPayload, rollback, cache,
executionPayload, consolidations, rollback, cache,
verificationFlags = verificationFlags,
transactions_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)):
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
let
domain = compute_domain(
DOMAIN_CONSOLIDATION, cfg.GENESIS_FORK_VERSION,
genesis_validators_root=state.genesis_validators_root)
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")
if not verify_consolidation_signature(
cfg.genesisFork, state.genesis_validators_root, signed_consolidation,
[source_validator[].pubkey, target_validator.pubkey]):
return err("Consolidation: invalid signature")
# Initiate source validator exit and append pending consolidation
source_validator[].exit_epoch = compute_consolidation_epoch_and_update_churn(
@ -667,8 +658,7 @@ proc process_consolidation*(
debugComment "check HashList add return value"
discard state.pending_consolidations.add(PendingConsolidation(
source_index: consolidation.source_index,
target_index: consolidation.target_index
))
target_index: consolidation.target_index))
ok()

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -10,6 +10,7 @@
import std/strutils
import ssz_serialization/[types, bitseqs]
import stew/endians2
import stint
import nimcrypto/hash
import "."/common
@ -24,6 +25,9 @@ const
func perfectScore*(score: float64): bool =
score == Inf
func perfectScore*(score: UInt256): bool =
score == high(UInt256)
proc shortScore*(score: float64): string =
if score == Inf:
"<perfect>"
@ -32,6 +36,9 @@ proc shortScore*(score: float64): string =
else:
formatFloat(score, ffDecimal, 4)
proc shortScore*(score: UInt256): string =
$score
func getLexicographicScore(digest: Eth2Digest): float64 =
# We calculate score on first 8 bytes of digest.
let
@ -183,3 +190,28 @@ proc getUniqueVotes*(attestations: openArray[phase0.Attestation]): int =
processVotes(attestation)
res += count
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)
v = node.attachedValidators[].addValidator(keystore, feeRecipient,
gasLimit)
v.updateValidator(data)
node.attachedValidators[].updateValidator(v, data)
proc addValidators*(node: BeaconNode) {.async: (raises: [CancelledError]).} =
info "Loading validators", validatorsDir = node.config.validatorsDir(),
@ -174,7 +174,7 @@ proc addValidators*(node: BeaconNode) {.async: (raises: [CancelledError]).} =
v = node.attachedValidators[].addValidator(keystore, feeRecipient,
gasLimit)
v.updateValidator(data)
node.attachedValidators[].updateValidator(v, data)
# We use `allFutures` because all failures are already reported as
# user-visible warnings in `queryValidatorsSource`.
@ -363,10 +363,12 @@ proc createAndSendAttestation(node: BeaconNode,
res =
if consensusFork >= ConsensusFork.Electra:
await node.router.routeAttestation(
registered.toElectraAttestation(signature), subnet_id, checkSignature = false)
registered.toElectraAttestation(signature), subnet_id,
checkSignature = false, checkValidator = false)
else:
await node.router.routeAttestation(
registered.toAttestation(signature), subnet_id, checkSignature = false)
registered.toAttestation(signature), subnet_id,
checkSignature = false, checkValidator = false)
if not res.isOk():
return
@ -537,6 +539,7 @@ proc makeBeaconBlockForHeadAndSlot*(
slot, validator_index
return err("Unable to get execution payload")
debugComment "flesh out consolidations"
let res = makeBeaconBlockWithRewards(
node.dag.cfg,
state[],
@ -549,6 +552,7 @@ proc makeBeaconBlockForHeadAndSlot*(
exits,
node.syncCommitteeMsgPool[].produceSyncAggregate(head.bid, slot),
payload,
@[], # consolidations
noRollback, # Temporary state - no need for rollback
cache,
verificationFlags = {},
@ -1292,7 +1296,8 @@ proc proposeBlockAux(
else:
Opt.none(seq[BlobSidecar])
newBlockRef = (
await node.router.routeSignedBeaconBlock(signedBlock, blobsOpt)
await node.router.routeSignedBeaconBlock(signedBlock, blobsOpt,
checkValidator = false)
).valueOr:
return head # Errors logged in router
@ -1853,7 +1858,7 @@ proc updateValidators(
let
v = node.attachedValidators[].getValidator(validators[i].pubkey).valueOr:
continue
v.index = Opt.some ValidatorIndex(i)
node.attachedValidators[].setValidatorIndex(v, ValidatorIndex(i))
node.dutyValidatorCount = validators.len
@ -1863,10 +1868,12 @@ proc updateValidators(
# Activation epoch can change after index is assigned..
let index = validator.index.get()
if index < validators.lenu64:
validator.updateValidator(
node.attachedValidators[].updateValidator(
validator,
Opt.some(ValidatorAndIndex(
index: index, validator: validators[int index]
)))
))
)
proc handleFallbackAttestations(node: BeaconNode, lastSlot, slot: Slot) =
# 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):
let data = host.getValidatorAndIdxFn(keystore.pubkey)
v.updateValidator(data)
host.validatorPool[].updateValidator(v, data)
proc generateDeposits*(cfg: RuntimeConfig,
rng: var HmacDrbgContext,

View File

@ -8,7 +8,6 @@
{.push raises: [].}
import
stew/results,
std/sequtils,
chronicles,
metrics,
@ -85,13 +84,22 @@ template getCurrentBeaconTime(router: MessageRouter): BeaconTime =
type RouteBlockResult = Result[Opt[BlockRef], string]
proc routeSignedBeaconBlock*(
router: ref MessageRouter, blck: ForkySignedBeaconBlock,
blobsOpt: Opt[seq[BlobSidecar]]):
blobsOpt: Opt[seq[BlobSidecar]], checkValidator: bool):
Future[RouteBlockResult] {.async: (raises: [CancelledError]).} =
## 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
## block passes validation but is not added, and error otherwise
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
# block doesn't get the node into trouble
block:
@ -193,13 +201,14 @@ proc routeSignedBeaconBlock*(
proc routeAttestation*(
router: ref MessageRouter,
attestation: phase0.Attestation | electra.Attestation,
subnet_id: SubnetId, checkSignature: bool):
subnet_id: SubnetId, checkSignature, checkValidator: bool):
Future[SendResult] {.async: (raises: [CancelledError]).} =
## Process and broadcast attestation - processing will register the it with
## the attestation pool
block:
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:
warn "Attestation failed validation",
@ -250,7 +259,7 @@ proc routeAttestation*(
committee_index)
return await router.routeAttestation(
attestation, subnet_id, checkSignature = true)
attestation, subnet_id, checkSignature = true, checkValidator = true)
proc routeSignedAggregateAndProof*(
router: ref MessageRouter, proof: phase0.SignedAggregateAndProof,

View File

@ -144,7 +144,8 @@ proc unblindAndRouteBlockMEV*(
blck = shortLog(signedBlock)
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
return err("routeSignedBeaconBlock error") # Errors logged in router

View File

@ -8,7 +8,7 @@
{.push raises: [].}
import
std/[tables, json, streams, sequtils, uri],
std/[tables, json, streams, sequtils, uri, sets],
chronos, chronicles, metrics,
json_serialization/std/net,
presto/client,
@ -93,6 +93,7 @@ type
ValidatorPool* = object
validators*: Table[ValidatorPubKey, AttachedValidator]
indexSet*: HashSet[ValidatorIndex]
slashingProtection*: SlashingProtectionDB
doppelgangerDetectionEnabled*: bool
@ -223,10 +224,24 @@ func contains*(pool: ValidatorPool, pubkey: ValidatorPubKey): bool =
## Returns ``true`` if validator with key ``pubkey`` present in ``pool``.
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) =
## Delete validator with public key ``pubkey`` from ``pool``.
let validator = pool.validators.getOrDefault(pubkey)
if not(isNil(validator)):
if validator.index.isSome():
pool.removeValidatorIndex(validator.index.get)
pool.validators.del(pubkey)
case validator.kind
of ValidatorKind.Local:
@ -243,8 +258,9 @@ proc removeValidator*(pool: var ValidatorPool, pubkey: ValidatorPubKey) =
func needsUpdate*(validator: AttachedValidator): bool =
validator.index.isNone() or validator.activationEpoch == FAR_FUTURE_EPOCH
proc updateValidator*(
validator: AttachedValidator, validatorData: Opt[ValidatorAndIndex]) =
proc updateValidator*(pool: var ValidatorPool,
validator: AttachedValidator,
validatorData: Opt[ValidatorAndIndex]) =
defer: validator.updated = true
let
@ -259,6 +275,7 @@ proc updateValidator*(
## Update activation information for a validator
if validator.index != Opt.some data.index:
pool.setValidatorIndex(validator, data.index)
validator.index = Opt.some data.index
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 =
asEth2Digest(address)
func getOrDefault[T](x: Option[T]): T =
func getOrDefault[T](x: Opt[T]): T =
if x.isSome:
x.get
else:
@ -505,25 +505,25 @@ proc doCreateTestnet*(config: CliConfig,
proc deployContract(web3: Web3, code: seq[byte]): Future[ReceiptObject] {.async.} =
let tr = TransactionArgs(
`from`: web3.defaultAccount.some,
data: code.some,
gas: Quantity(3000000).some,
gasPrice: Quantity(1).some)
`from`: Opt.some web3.defaultAccount,
data: Opt.some code,
gas: Opt.some Quantity(3000000),
gasPrice: Opt.some Quantity(1))
let r = await web3.send(tr)
result = await web3.getMinedTransactionReceipt(r)
proc sendEth(web3: Web3, to: Eth1Address, valueEth: int): Future[TxHash] =
let tr = TransactionArgs(
`from`: web3.defaultAccount.some,
`from`: Opt.some web3.defaultAccount,
# TODO: Force json-rpc to generate 'data' field
# should not be needed anymore, new execution-api schema
# is using `input` field
data: some(newSeq[byte]()),
gas: Quantity(3000000).some,
gasPrice: Quantity(1).some,
value: some(valueEth.u256 * 1000000000000000000.u256),
to: some(to))
data: Opt.some(newSeq[byte]()),
gas: Opt.some Quantity(3000000),
gasPrice: Opt.some Quantity(1),
value: Opt.some(valueEth.u256 * 1000000000000000000.u256),
to: Opt.some(to))
web3.send(tr)
type
@ -535,7 +535,7 @@ func ethToWei(eth: UInt256): UInt256 =
proc initWeb3(web3Url, privateKey: string): Future[Web3] {.async.} =
result = await newWeb3(web3Url)
if privateKey.len != 0:
result.privateKey = some(keys.PrivateKey.fromHex(privateKey)[])
result.privateKey = Opt.some(keys.PrivateKey.fromHex(privateKey)[])
else:
let accounts = await result.provider.eth_accounts()
doAssert(accounts.len > 0)

View File

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

View File

@ -85,7 +85,7 @@ proc makeSimulationBlock(
var blck = partialBeaconBlock(
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(
cfg, state.data, blck.asSigVerified(), verificationFlags, cache)
@ -128,7 +128,7 @@ proc makeSimulationBlock(
var blck = partialBeaconBlock(
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(
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
server.rpc("engine_forkchoiceUpdatedV1") do(
update: ForkchoiceStateV1,
payloadAttributes: Option[PayloadAttributesV1]) -> ForkchoiceUpdatedResponse:
payloadAttributes: Opt[PayloadAttributesV1]) -> ForkchoiceUpdatedResponse:
info "engine_forkchoiceUpdatedV1",
update,
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
server.rpc("engine_forkchoiceUpdatedV2") do(
forkchoiceState: ForkchoiceStateV1, payloadAttributes: Option[PayloadAttributesV2]) -> ForkchoiceUpdatedResponse:
forkchoiceState: ForkchoiceStateV1, payloadAttributes: Opt[PayloadAttributesV2]) -> ForkchoiceUpdatedResponse:
info "engine_forkchoiceUpdatedV2",
forkchoiceState, payloadAttributes

View File

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

View File

@ -21,7 +21,7 @@ source "${SCRIPTS_DIR}/bash_utils.sh"
download_geth_stable() {
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/"
case "${OS}-${ARCH}" in

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -389,6 +389,7 @@ const
("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01", "0.9995"),
("0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101", "0.0005"),
]
ContributionDataVectors = [
("0xffffffffffffffffffffffffffff7f7f", "0.9844"),
("0xffffffffffffffffffffffff7f7f7f7f", "0.9688"),
@ -446,6 +447,15 @@ const
([("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 =
let length = len(data)
var dst = Eth2Digest()
@ -755,6 +765,25 @@ suite "Validator Client test suite":
score == "0.0000"
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":
for vector in ContributionDataVectors:
let
@ -773,11 +802,24 @@ suite "Validator Client test suite":
check:
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":
for vector in AttestationBitsVectors:
let
a1 = phase0.Attestation.init(vector[0][0][0], vector[0][0][1], vector[0][0][2])
a2 = phase0.Attestation.init(vector[0][1][0], vector[0][1][1], vector[0][1][2])
a1 = phase0.Attestation.init(vector[0][0][0], vector[0][0][1],
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]
asyncTest "firstSuccessParallel() API timeout test":
@ -850,6 +892,7 @@ suite "Validator Client test suite":
let response = vc.bestSuccess(
RestPlainResponse,
uint64,
float64,
100.milliseconds,
AllBeaconNodeStatuses,
{BeaconNodeRole.Duties},

View File

@ -71,13 +71,14 @@ func checkResponse(a, b: openArray[KeystoreData]): bool =
suite "Validator pool":
test "Doppelganger for genesis validator":
let
pool = newClone(ValidatorPool())
v = AttachedValidator(activationEpoch: FAR_FUTURE_EPOCH)
check:
not v.triggersDoppelganger(GENESIS_EPOCH) # no check
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:
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":
let
pool = newClone(ValidatorPool())
v = AttachedValidator(activationEpoch: FAR_FUTURE_EPOCH)
now = Epoch(10).start_slot()
@ -104,7 +106,7 @@ suite "Validator pool":
not v.doppelgangerReady(GENESIS_EPOCH.start_slot)
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
not v.triggersDoppelganger(GENESIS_EPOCH)
@ -113,7 +115,7 @@ suite "Validator pool":
not v.doppelgangerReady(GENESIS_EPOCH.start_slot)
not v.doppelgangerReady(now)
v.updateValidator(makeValidatorAndIndex(ValidatorIndex(5), now.epoch()))
pool[].updateValidator(v, makeValidatorAndIndex(ValidatorIndex(5), now.epoch()))
check: # No check done yet
not v.triggersDoppelganger(GENESIS_EPOCH)

View File

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

@ -1 +1 @@
Subproject commit 695d1c9dbec4fa0f746a15df259a19fed49e075e
Subproject commit 9f6fc631e24bb49e6afa2bdd708e6efc840d240c

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 2e4c259d1bc6debc80ceff611e1ff6071af89ea9
Subproject commit 6e551d737a91ecaac09f485502185e7e20e4042d