Merge branch 'dev/etan/bd-serialization' into feat/eip-7495
This commit is contained in:
commit
728d7db66e
|
@ -213,7 +213,7 @@ jobs:
|
||||||
|
|
||||||
devbuild:
|
devbuild:
|
||||||
name: "Developer builds"
|
name: "Developer builds"
|
||||||
runs-on: ubuntu-latest
|
runs-on: ['self-hosted','ubuntu-22.04']
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
|
@ -5,6 +5,11 @@
|
||||||
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
|
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
|
||||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
|
[submodule "vendor/mainnet"]
|
||||||
|
path = vendor/mainnet
|
||||||
|
url = https://github.com/eth-clients/mainnet.git
|
||||||
|
ignore = untracked
|
||||||
|
branch = main
|
||||||
[submodule "vendor/nim-eth2-scenarios"]
|
[submodule "vendor/nim-eth2-scenarios"]
|
||||||
path = vendor/nim-eth2-scenarios
|
path = vendor/nim-eth2-scenarios
|
||||||
url = https://github.com/status-im/nim-eth2-scenarios
|
url = https://github.com/status-im/nim-eth2-scenarios
|
||||||
|
@ -170,11 +175,6 @@
|
||||||
url = https://github.com/status-im/nim-presto.git
|
url = https://github.com/status-im/nim-presto.git
|
||||||
ignore = untracked
|
ignore = untracked
|
||||||
branch = master
|
branch = master
|
||||||
[submodule "vendor/eth2-networks"]
|
|
||||||
path = vendor/eth2-networks
|
|
||||||
url = https://github.com/eth-clients/eth2-networks.git
|
|
||||||
ignore = untracked
|
|
||||||
branch = master
|
|
||||||
[submodule "vendor/nim-taskpools"]
|
[submodule "vendor/nim-taskpools"]
|
||||||
path = vendor/nim-taskpools
|
path = vendor/nim-taskpools
|
||||||
url = https://github.com/status-im/nim-taskpools
|
url = https://github.com/status-im/nim-taskpools
|
||||||
|
|
|
@ -907,12 +907,14 @@ OK: 1/1 Fail: 0/1 Skip: 0/1
|
||||||
+ getAggregatedAttestationDataScore() test vectors OK
|
+ getAggregatedAttestationDataScore() test vectors OK
|
||||||
+ getAttestationDataScore() test vectors OK
|
+ getAttestationDataScore() test vectors OK
|
||||||
+ getLiveness() response deserialization test OK
|
+ getLiveness() response deserialization test OK
|
||||||
|
+ getProduceBlockResponseV3Score() default test OK
|
||||||
|
+ getProduceBlockResponseV3Score() test vectors OK
|
||||||
+ getSyncCommitteeContributionDataScore() test vectors OK
|
+ getSyncCommitteeContributionDataScore() test vectors OK
|
||||||
+ getSyncCommitteeMessageDataScore() test vectors OK
|
+ getSyncCommitteeMessageDataScore() test vectors OK
|
||||||
+ getUniqueVotes() test vectors OK
|
+ getUniqueVotes() test vectors OK
|
||||||
+ normalizeUri() test vectors OK
|
+ normalizeUri() test vectors OK
|
||||||
```
|
```
|
||||||
OK: 12/12 Fail: 0/12 Skip: 0/12
|
OK: 14/14 Fail: 0/14 Skip: 0/14
|
||||||
## Validator change pool testing suite
|
## Validator change pool testing suite
|
||||||
```diff
|
```diff
|
||||||
+ addValidatorChangeMessage/getAttesterSlashingMessage OK
|
+ addValidatorChangeMessage/getAttesterSlashingMessage OK
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -593,7 +593,7 @@ define MAKE_DEPOSIT
|
||||||
|
|
||||||
build/deposit_contract sendDeposits \
|
build/deposit_contract sendDeposits \
|
||||||
$(2) \
|
$(2) \
|
||||||
--deposit-contract=$$(cat vendor/eth2-networks/shared/$(1)/deposit_contract.txt) \
|
--deposit-contract=$$(cat vendor/$(1)/metadata/deposit_contract.txt) \
|
||||||
--deposits-file=nbc-$(1)-deposits.json \
|
--deposits-file=nbc-$(1)-deposits.json \
|
||||||
--min-delay=$(DEPOSITS_DELAY) \
|
--min-delay=$(DEPOSITS_DELAY) \
|
||||||
--max-delay=$(DEPOSITS_DELAY) \
|
--max-delay=$(DEPOSITS_DELAY) \
|
||||||
|
|
|
@ -73,7 +73,7 @@ proc initLightClient*(
|
||||||
headBlockHash = blckPayload.block_hash,
|
headBlockHash = blckPayload.block_hash,
|
||||||
safeBlockHash = beaconHead.safeExecutionBlockHash,
|
safeBlockHash = beaconHead.safeExecutionBlockHash,
|
||||||
finalizedBlockHash = beaconHead.finalizedExecutionBlockHash,
|
finalizedBlockHash = beaconHead.finalizedExecutionBlockHash,
|
||||||
payloadAttributes = none attributes)
|
payloadAttributes = Opt.none attributes)
|
||||||
|
|
||||||
case node.dag.cfg.consensusForkAtEpoch(
|
case node.dag.cfg.consensusForkAtEpoch(
|
||||||
forkyBlck.message.slot.epoch)
|
forkyBlck.message.slot.epoch)
|
||||||
|
|
|
@ -1047,7 +1047,7 @@ type
|
||||||
|
|
||||||
monitoringType* {.
|
monitoringType* {.
|
||||||
desc: "Enable block monitoring which are seen by beacon node (BETA)"
|
desc: "Enable block monitoring which are seen by beacon node (BETA)"
|
||||||
defaultValue: BlockMonitoringType.Disabled
|
defaultValue: BlockMonitoringType.Event
|
||||||
name: "block-monitor-type".}: BlockMonitoringType
|
name: "block-monitor-type".}: BlockMonitoringType
|
||||||
|
|
||||||
SigningNodeConf* = object
|
SigningNodeConf* = object
|
||||||
|
|
|
@ -2408,7 +2408,7 @@ proc updateHead*(
|
||||||
|
|
||||||
if dag.headState.kind > lastHeadKind:
|
if dag.headState.kind > lastHeadKind:
|
||||||
case dag.headState.kind
|
case dag.headState.kind
|
||||||
of ConsensusFork.Phase0 .. ConsensusFork.Bellatrix, ConsensusFork.Electra:
|
of ConsensusFork.Phase0 .. ConsensusFork.Bellatrix:
|
||||||
discard
|
discard
|
||||||
of ConsensusFork.Capella:
|
of ConsensusFork.Capella:
|
||||||
if dag.vanityLogs.onUpgradeToCapella != nil:
|
if dag.vanityLogs.onUpgradeToCapella != nil:
|
||||||
|
@ -2416,6 +2416,9 @@ proc updateHead*(
|
||||||
of ConsensusFork.Deneb:
|
of ConsensusFork.Deneb:
|
||||||
if dag.vanityLogs.onUpgradeToDeneb != nil:
|
if dag.vanityLogs.onUpgradeToDeneb != nil:
|
||||||
dag.vanityLogs.onUpgradeToDeneb()
|
dag.vanityLogs.onUpgradeToDeneb()
|
||||||
|
of ConsensusFork.Electra:
|
||||||
|
if dag.vanityLogs.onUpgradeToElectra != nil:
|
||||||
|
dag.vanityLogs.onUpgradeToElectra()
|
||||||
|
|
||||||
if dag.vanityLogs.onKnownBlsToExecutionChange != nil and
|
if dag.vanityLogs.onKnownBlsToExecutionChange != nil and
|
||||||
checkBlsToExecutionChanges(
|
checkBlsToExecutionChanges(
|
||||||
|
|
|
@ -184,7 +184,7 @@ proc updateExecutionClientHead*(
|
||||||
headBlockHash = headExecutionBlockHash,
|
headBlockHash = headExecutionBlockHash,
|
||||||
safeBlockHash = newHead.safeExecutionBlockHash,
|
safeBlockHash = newHead.safeExecutionBlockHash,
|
||||||
finalizedBlockHash = newHead.finalizedExecutionBlockHash,
|
finalizedBlockHash = newHead.finalizedExecutionBlockHash,
|
||||||
payloadAttributes = none attributes)
|
payloadAttributes = Opt.none attributes)
|
||||||
|
|
||||||
# Can't use dag.head here because it hasn't been updated yet
|
# Can't use dag.head here because it hasn't been updated yet
|
||||||
let
|
let
|
||||||
|
@ -374,7 +374,7 @@ proc runProposalForkchoiceUpdated*(
|
||||||
let (status, _) = await self.elManager.forkchoiceUpdated(
|
let (status, _) = await self.elManager.forkchoiceUpdated(
|
||||||
headBlockHash, safeBlockHash,
|
headBlockHash, safeBlockHash,
|
||||||
beaconHead.finalizedExecutionBlockHash,
|
beaconHead.finalizedExecutionBlockHash,
|
||||||
payloadAttributes = some fcPayloadAttributes)
|
payloadAttributes = Opt.some fcPayloadAttributes)
|
||||||
debug "Fork-choice updated for proposal", status
|
debug "Fork-choice updated for proposal", status
|
||||||
|
|
||||||
static: doAssert high(ConsensusFork) == ConsensusFork.Electra
|
static: doAssert high(ConsensusFork) == ConsensusFork.Electra
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
[0;40;37m[0;0;0;0t[1;171;171;171t
|
||||||
|
[22C[33m[1;171;87;0t[8C..-|\_/|
|
||||||
|
[37m[1;171;171;171t [32m[1;0;171;0t text [37m[1;171;171;171t[10C[33m[1;171;87;0t[9C.-'[37m[1;171;171;171t.[33m[1;171;87;0t.d [37m[1;171;171;171t:.:[33m[1;171;87;0t $
|
||||||
|
[37m[1;171;171;171t[18C[33m[1;171;87;0t[8C(_[37m[1;171;171;171t:[33m[1;171;87;0t __. [37m[1;171;171;171t::[33m[1;171;87;0t:::$
|
||||||
|
[37m[1;171;171;171t[18C[33m[1;171;87;0t[9C`-' ? ::[37m[1;171;171;171t::[33m[1;171;87;0t $
|
||||||
|
[37m[1;171;171;171t[18C[33m[1;171;87;0t[16C\ [37m[1;171;171;171t::[33m[1;171;87;0t:: $
|
||||||
|
[37m[1;171;171;171t[18C[33m[1;171;87;0t[17C\::[37m[1;171;171;171t::[33m[1;171;87;0t::$
|
||||||
|
[37m[1;171;171;171t[8C[32m[1;0;171;0tarea[37m[1;171;171;171t[8C[33m[1;171;87;0t[16C\ :::[37m[1;171;171;171t::[33m[1;171;87;0t$
|
||||||
|
[37m[1;171;171;171t[27C[33m[1;171;87;0t[10C|[37m[1;171;171;171t:[33m[1;171;87;0t.[37m[1;171;171;171t:[33m[1;171;87;0t:: $
|
||||||
|
[37m[1;171;171;171t[33C[33m[1;171;87;0t `| [37m[1;171;171;171t::::[33m[1;171;87;0t $..__
|
||||||
|
[37m[1;171;171;171t[33C[33m[1;171;87;0t[5C`.:::[37m[1;171;171;171t:[33m[1;171;87;0t:[37m[1;171;171;171t:.[33m[1;171;87;0t:[37m[1;171;171;171t:.[33m[1;171;87;0t`-.
|
||||||
|
[37m[1;171;171;171t[33C[33m[1;171;87;0t[6C|::::[37m[1;171;171;171t:[33m[1;171;87;0t::[37m[1;171;171;171t:[33m[1;171;87;0t::[37m[1;171;171;171t:[33m[1;171;87;0t::`--.
|
||||||
|
[37m[1;171;171;171t[14C[32m[1;0;171;0there[37m[1;171;171;171t[18C[33m[1;171;87;0t `.:::[37m[1;171;171;171t:.:[33m[1;171;87;0t:[37m[1;171;171;171t:::[33m[1;171;87;0t:[37m[1;171;171;171t::[33m[1;171;87;0t::[37m[1;171;171;171t:[33m[1;171;87;0t`---.....
|
||||||
|
[37m[1;171;171;171t[28C[33m[1;171;87;0t [37m[1;171;171;171t [33m[1;171;87;0t[5C`.[37m[1;171;171;171t:[33m[1;171;87;0t:::[37m[1;171;171;171t::[33m[1;171;87;0t:::[37m[1;171;171;171t:::[33m[1;171;87;0t::::[37m[1;171;171;171t::[33m[1;171;87;0t:::[37m[1;171;171;171t::[33m[1;171;87;0t`\
|
||||||
|
[37m[1;171;171;171t[28C[33m[1;171;87;0t[7C[37m[1;171;171;171t [33m[1;171;87;0t[6C|:[37m[1;171;171;171t:[33m[1;171;87;0t::[37m[1;171;171;171t:::::::[33m[1;171;87;0t:::[37m[1;171;171;171t::[33m[1;171;87;0t::[37m[1;171;171;171t::[33m[1;171;87;0t:[37m[1;171;171;171t::::[33m[1;171;87;0t|
|
||||||
|
[37m[1;171;171;171t[28C[33m[1;171;87;0t[7C[37m[1;171;171;171t [33m[1;171;87;0t[6C|:[37m[1;171;171;171t:[33m[1;171;87;0t:::[37m[1;171;171;171t::[33m[1;171;87;0t:::[37m[1;171;171;171t::[33m[1;171;87;0t:[37m[1;171;171;171t:::[33m[1;171;87;0t:[37m[1;171;171;171t:[33m[1;171;87;0t:[37m[1;171;171;171t::[33m[1;171;87;0t:[37m[1;171;171;171t:[33m[1;171;87;0t|[37m[1;171;171;171t:[33m[1;171;87;0t|
|
||||||
|
[37m[1;171;171;171t[31C[33m[1;171;87;0t [37m[1;171;171;171t [33m[1;171;87;0t[6C|[37m[1;171;171;171t::[33m[1;171;87;0t:[37m[1;171;171;171t::[33m[1;171;87;0t:[37m[1;171;171;171t:::::[33m[1;171;87;0t:|[37m[1;171;171;171t:[33m[1;171;87;0t::[37m[1;171;171;171t::[33m[1;171;87;0t:[37m[1;171;171;171t::::[33m[1;171;87;0t|[37m[1;171;171;171t:[33m[1;171;87;0t|
|
||||||
|
[37m[1;171;171;171t[36C[33m[1;171;87;0t[6C':[37m[1;171;171;171t::[33m[1;171;87;0t)___..----\ [37m[1;171;171;171t:[33m[1;171;87;0t::[37m[1;171;171;171t:[33m[1;171;87;0t:| .`. \
|
||||||
|
[37m[1;171;171;171t[37C[33m[1;171;87;0t[5C|:[37m[1;171;171;171t::[33m[1;171;87;0t| | :|[5C`.[37m[1;171;171;171t::[33m[1;171;87;0t::|: : `.`.
|
||||||
|
[37m[1;171;171;171t[21C[32m[1;0;171;0t()[37m[1;171;171;171t [32m[1;0;171;0t()[33m[1;171;87;0t [36m[1;0;171;171tO[33m[1;171;87;0t [37m[1;171;171;171t [36m[1;0;171;171tO[33m[1;171;87;0t |[37m[1;171;171;171t:[33m[1;171;87;0t::| |. |[7C|:[37m[1;171;171;171t::[33m[1;171;87;0t| `.: |[37m[1;171;171;171t:[33m[1;171;87;0t|
|
||||||
|
[37m[1;171;171;171t[23C[32m[1;0;171;0t\[37m[1;171;171;171t [32m[1;0;171;0t/[37m[1;171;171;171t [33m[1;171;87;0t[6C[36m[1;0;171;171t\[33m[1;171;87;0t [36m[1;0;171;171t/[33m[1;171;87;0t [37m[1;171;171;171t [33m[1;171;87;0t |:[37m[1;171;171;171t:[33m[1;171;87;0t:| | :|[7C`.[37m[1;171;171;171t:[33m[1;171;87;0t:[37m[1;171;171;171t:[33m[1;171;87;0t`. .:`.`.
|
||||||
|
[37m[1;171;171;171t[11C[32m[1;0;171;0t()[37m[1;171;171;171t [32m[1;0;171;0t()() [37m[1;171;171;171t [32m[1;0;171;0t()[37m[1;171;171;171t [33m[1;171;87;0t [32m[1;0;171;0t()[33m[1;171;87;0t [36m[1;0;171;171tO[33m[1;171;87;0t [32m[1;0;171;0t()[33m[1;171;87;0t |:[37m[1;171;171;171t:[33m[1;171;87;0t:| |: |[9C:[37m[1;171;171;171t:[33m[1;171;87;0t:[37m[1;171;171;171t:[33m[1;171;87;0t| |::|`.`.
|
||||||
|
[37m[1;171;171;171t[13C[32m[1;0;171;0t\[37m[1;171;171;171t [32m[1;0;171;0t /[37m[1;171;171;171t [32m[1;0;171;0t\ /[37m[1;171;171;171t[6C[32m[1;0;171;0t/[33m[1;171;87;0t [36m[1;0;171;171t/[33m[1;171;87;0t [32m[1;0;171;0t/[33m[1;171;87;0t |[37m[1;171;171;171t:[33m[1;171;87;0t:[37m[1;171;171;171t:[33m[1;171;87;0t| | :|[9C|:[37m[1;171;171;171t:[33m[1;171;87;0t:| | :| )))
|
||||||
|
[37m[1;171;171;171t [32m[1;0;171;0t()[37m[1;171;171;171t [32m[1;0;171;0t()[37m[1;171;171;171t [36m[1;0;171;171t O[32m[1;0;171;0t()[37m[1;171;171;171t [36m[1;0;171;171tO[37m[1;171;171;171t [32m[1;0;171;0t() [37m[1;171;171;171t [32m[1;0;171;0t()[37m[1;171;171;171t [36m[1;0;171;171tO[37m[1;171;171;171t [33m[1;171;87;0t [32m[1;0;171;0t()[33m[1;171;87;0t |:::||.:.| [32m[1;0;171;0t()[33m[1;171;87;0t [32m[1;0;171;0t()[33m[1;171;87;0t:[37m[1;171;171;171t:[33m[1;171;87;0t| |:..;((( [32m[1;0;171;0t()
|
||||||
|
[34m[1;0;0;171t.[37m[1;171;171;171t [32m[1;0;171;0t\[34m[1;0;0;171t.[32m[1;0;171;0t /[34m[1;0;0;171t.[37m[1;171;171;171t [36m[1;0;171;171t\[34m[1;0;0;171t.[36m[1;0;171;171t /[32m[1;0;171;0t/[37m[1;171;171;171t [36m[1;0;171;171tO[34m[1;0;0;171t.[37m[1;171;171;171t [36m[1;0;171;171t/[34m[1;0;0;171t.[37m[1;171;171;171t [34m[1;0;0;171t.[37m[1;171;171;171t [32m[1;0;171;0t\[34m[1;0;0;171t.[32m[1;0;171;0t /[34m[1;0;0;171t.[37m[1;171;171;171t [36m[1;0;171;171t\[37m[1;171;171;171t [36m[1;0;171;171t/[34m[1;0;0;171t.[37m[1;171;171;171t [34m[1;0;0;171t.[33m[1;171;87;0t [32m[1;0;171;0t\[33m[1;171;87;0t .'[37m[1;171;171;171t:[33m[1;171;87;0t:.'|::'|[34m[1;0;0;171t.[33m[1;171;87;0t [32m[1;0;171;0t/[34m[1;0;0;171t.[33m[1;171;87;0t [34m[1;0;0;171t.[33m[1;171;87;0t [32m[1;0;171;0t/[34m[1;0;0;171t.[33m[1;171;87;0t|[37m[1;171;171;171t:[33m[1;171;87;0t:|[34m[1;0;0;171t.[33m[1;171;87;0t ` :.\ `[32m[1;0;171;0t/[33m[1;171;87;0t [34m[1;0;0;171t.
|
||||||
|
....[32m[1;0;171;0t()[36m[1;0;171;171tO[34m[1;0;0;171t...[36m[1;0;171;171tO[32m[1;0;171;0t()[34m[1;0;0;171t...[36m[1;0;171;171t\[32m[1;0;171;0t()()[34m[1;0;0;171t....[32m[1;0;171;0t()[36m[1;0;171;171tO[34m[1;0;0;171t...[36m[1;0;171;171tO[34m[1;0;0;171t.[32m[1;0;171;0t()[34m[1;0;0;171t....[32m[1;0;171;0t()[33m[1;171;87;0t|[37m[1;171;171;171t:[33m[1;171;87;0t:[37m[1;171;171;171t:[33m[1;171;87;0t| |_M[32m[1;0;171;0t()()[34m[1;0;0;171t....[32m[1;0;171;0t()[34m[1;0;0;171t.[33m[1;171;87;0t.::[37m[1;171;171;171t:[33m[1;171;87;0t|[34m[1;0;0;171t.[32m[1;0;171;0t()[33m[1;171;87;0t|: :[32m[1;0;171;0t()[34m[1;0;0;171t..[32m[1;0;171;0t()
|
||||||
|
\[34m[1;0;0;171t..[32m[1;0;171;0t/[34m[1;0;0;171t...[36m[1;0;171;171t\[34m[1;0;0;171t.[36m[1;0;171;171t/[34m[1;0;0;171t...[32m[1;0;171;0t\[34m[1;0;0;171t..[32m[1;0;171;0t/[34m[1;0;0;171t....[32m[1;0;171;0t\[34m[1;0;0;171t..[32m[1;0;171;0t/[34m[1;0;0;171t...[36m[1;0;171;171t\[34m[1;0;0;171t.[36m[1;0;171;171t/[34m[1;0;0;171t....[32m[1;0;171;0t\[34m[1;0;0;171t..[32m[1;0;171;0t/[34m[1;0;0;171t..[33m[1;171;87;0t|:[37m[1;171;171;171t:[33m[1;171;87;0t:|[32m[1;0;171;0t\[34m[1;0;0;171t..[32m[1;0;171;0t/[34m[1;0;0;171t....[32m[1;0;171;0t\[34m[1;0;0;171t..[32m[1;0;171;0t/[34m[1;0;0;171t...[33m[1;171;87;0t|[37m[1;171;171;171t:[33m[1;171;87;0t::<[34m[1;0;0;171t...[32m[1;0;171;0t\[33m[1;171;87;0t_M[32m[1;0;171;0t/[33m[1;171;87;0t|[34m[1;0;0;171t.....
|
||||||
|
[32m[1;0;171;0t ()[34m[1;0;0;171t:::::[36m[1;0;171;171tO[34m[1;0;0;171t:::::[32m[1;0;171;0t()[34m[1;0;0;171t::::::[32m[1;0;171;0t()[34m[1;0;0;171t:::::[36m[1;0;171;171tO[34m[1;0;0;171t::::::[32m[1;0;171;0t()[34m[1;0;0;171t:::[33m[1;171;87;0t|_N_|[34m[1;0;0;171t:[32m[1;0;171;0t()[34m[1;0;0;171t::::::[32m[1;0;171;0t()[34m[1;0;0;171t::::[33m[1;171;87;0t|_N_|[34m[1;0;0;171t::::[32m[1;0;171;0t()[34m[1;0;0;171t:::::::
|
|
@ -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_|::::():::::::
|
|
@ -34,6 +34,10 @@ type
|
||||||
# in case of chain reorgs around the upgrade.
|
# in case of chain reorgs around the upgrade.
|
||||||
onUpgradeToDeneb*: LogProc
|
onUpgradeToDeneb*: LogProc
|
||||||
|
|
||||||
|
# Gets displayed on upgrade to Electra. May be displayed multiple times
|
||||||
|
# in case of chain reorgs around the upgrade.
|
||||||
|
onUpgradeToElectra*: LogProc
|
||||||
|
|
||||||
# Created by http://beatscribe.com/ (beatscribe#1008 on Discord)
|
# Created by http://beatscribe.com/ (beatscribe#1008 on Discord)
|
||||||
# These need to be the main body of the log not to be reformatted or escaped.
|
# These need to be the main body of the log not to be reformatted or escaped.
|
||||||
|
|
||||||
|
@ -47,3 +51,6 @@ proc capellaBlink*() = notice "\n" & staticRead("capella" / "blink.ans")
|
||||||
|
|
||||||
proc denebMono*() = notice "\n" & staticRead("deneb" / "mono.txt")
|
proc denebMono*() = notice "\n" & staticRead("deneb" / "mono.txt")
|
||||||
proc denebColor*() = notice "\n" & staticRead("deneb" / "color.ans")
|
proc denebColor*() = notice "\n" & staticRead("deneb" / "color.ans")
|
||||||
|
|
||||||
|
proc electraMono*() = notice "\n" & staticRead("electra" / "mono.txt")
|
||||||
|
proc electraColor*() = notice "\n" & staticRead("electra" / "color.ans")
|
||||||
|
|
|
@ -123,25 +123,25 @@ contract(DepositContract):
|
||||||
|
|
||||||
proc deployContract*(web3: Web3, code: seq[byte]): Future[ReceiptObject] {.async.} =
|
proc deployContract*(web3: Web3, code: seq[byte]): Future[ReceiptObject] {.async.} =
|
||||||
let tr = TransactionArgs(
|
let tr = TransactionArgs(
|
||||||
`from`: web3.defaultAccount.some,
|
`from`: Opt.some web3.defaultAccount,
|
||||||
data: code.some,
|
data: Opt.some code,
|
||||||
gas: Quantity(3000000).some,
|
gas: Opt.some Quantity(3000000),
|
||||||
gasPrice: Quantity(1).some)
|
gasPrice: Opt.some Quantity(1))
|
||||||
|
|
||||||
let r = await web3.send(tr)
|
let r = await web3.send(tr)
|
||||||
result = await web3.getMinedTransactionReceipt(r)
|
result = await web3.getMinedTransactionReceipt(r)
|
||||||
|
|
||||||
proc sendEth(web3: Web3, to: Eth1Address, valueEth: int): Future[TxHash] =
|
proc sendEth(web3: Web3, to: Eth1Address, valueEth: int): Future[TxHash] =
|
||||||
let tr = TransactionArgs(
|
let tr = TransactionArgs(
|
||||||
`from`: web3.defaultAccount.some,
|
`from`: Opt.some web3.defaultAccount,
|
||||||
# TODO: Force json-rpc to generate 'data' field
|
# TODO: Force json-rpc to generate 'data' field
|
||||||
# should not be needed anymore, new execution-api schema
|
# should not be needed anymore, new execution-api schema
|
||||||
# is using `input` field
|
# is using `input` field
|
||||||
data: some(newSeq[byte]()),
|
data: Opt.some(newSeq[byte]()),
|
||||||
gas: Quantity(3000000).some,
|
gas: Opt.some Quantity(3000000),
|
||||||
gasPrice: Quantity(1).some,
|
gasPrice: Opt.some Quantity(1),
|
||||||
value: some(valueEth.u256 * 1000000000000000000.u256),
|
value: Opt.some(valueEth.u256 * 1000000000000000000.u256),
|
||||||
to: some(to))
|
to: Opt.some(to))
|
||||||
web3.send(tr)
|
web3.send(tr)
|
||||||
|
|
||||||
type
|
type
|
||||||
|
@ -153,7 +153,7 @@ proc ethToWei(eth: UInt256): UInt256 =
|
||||||
proc initWeb3(web3Url, privateKey: string): Future[Web3] {.async.} =
|
proc initWeb3(web3Url, privateKey: string): Future[Web3] {.async.} =
|
||||||
result = await newWeb3(web3Url)
|
result = await newWeb3(web3Url)
|
||||||
if privateKey.len != 0:
|
if privateKey.len != 0:
|
||||||
result.privateKey = some(PrivateKey.fromHex(privateKey)[])
|
result.privateKey = Opt.some(PrivateKey.fromHex(privateKey)[])
|
||||||
else:
|
else:
|
||||||
let accounts = await result.provider.eth_accounts()
|
let accounts = await result.provider.eth_accounts()
|
||||||
doAssert(accounts.len > 0)
|
doAssert(accounts.len > 0)
|
||||||
|
|
|
@ -106,7 +106,7 @@ type
|
||||||
Running, Closing, Closed
|
Running, Closing, Closed
|
||||||
|
|
||||||
ELManager* = ref object
|
ELManager* = ref object
|
||||||
eth1Network: Option[Eth1Network]
|
eth1Network: Opt[Eth1Network]
|
||||||
## If this value is supplied the EL manager will check whether
|
## If this value is supplied the EL manager will check whether
|
||||||
## all configured EL nodes are connected to the same network.
|
## all configured EL nodes are connected to the same network.
|
||||||
|
|
||||||
|
@ -133,7 +133,7 @@ type
|
||||||
## also includes blocks without deposits because we must
|
## also includes blocks without deposits because we must
|
||||||
## vote for a block only if it's part of our known history.
|
## vote for a block only if it's part of our known history.
|
||||||
|
|
||||||
syncTargetBlock: Option[Eth1BlockNumber]
|
syncTargetBlock: Opt[Eth1BlockNumber]
|
||||||
|
|
||||||
chainSyncingLoopFut: Future[void]
|
chainSyncingLoopFut: Future[void]
|
||||||
exchangeTransitionConfigurationLoopFut: Future[void]
|
exchangeTransitionConfigurationLoopFut: Future[void]
|
||||||
|
@ -177,7 +177,7 @@ type
|
||||||
depositContractSyncStatus: DepositContractSyncStatus
|
depositContractSyncStatus: DepositContractSyncStatus
|
||||||
## Are we sure that this EL has synced the deposit contract?
|
## Are we sure that this EL has synced the deposit contract?
|
||||||
|
|
||||||
lastPayloadId: Option[PayloadID]
|
lastPayloadId: Opt[PayloadID]
|
||||||
|
|
||||||
FullBlockId* = object
|
FullBlockId* = object
|
||||||
number: Eth1BlockNumber
|
number: Eth1BlockNumber
|
||||||
|
@ -419,7 +419,7 @@ func asConsensusType*(payloadWithValue: BellatrixExecutionPayloadWithValue):
|
||||||
executionPayload: payloadWithValue.executionPayload.asConsensusType,
|
executionPayload: payloadWithValue.executionPayload.asConsensusType,
|
||||||
blockValue: payloadWithValue.blockValue)
|
blockValue: payloadWithValue.blockValue)
|
||||||
|
|
||||||
template maybeDeref[T](o: Option[T]): T = o.get
|
template maybeDeref[T](o: Opt[T]): T = o.get
|
||||||
template maybeDeref[V](v: V): V = v
|
template maybeDeref[V](v: V): V = v
|
||||||
|
|
||||||
func asConsensusType*(rpcExecutionPayload: ExecutionPayloadV1OrV2|ExecutionPayloadV2):
|
func asConsensusType*(rpcExecutionPayload: ExecutionPayloadV1OrV2|ExecutionPayloadV2):
|
||||||
|
@ -779,15 +779,15 @@ func areSameAs(expectedParams: Option[NextExpectedPayloadParams],
|
||||||
|
|
||||||
proc forkchoiceUpdated(rpcClient: RpcClient,
|
proc forkchoiceUpdated(rpcClient: RpcClient,
|
||||||
state: ForkchoiceStateV1,
|
state: ForkchoiceStateV1,
|
||||||
payloadAttributes: Option[PayloadAttributesV1] |
|
payloadAttributes: Opt[PayloadAttributesV1] |
|
||||||
Option[PayloadAttributesV2] |
|
Opt[PayloadAttributesV2] |
|
||||||
Option[PayloadAttributesV3]):
|
Opt[PayloadAttributesV3]):
|
||||||
Future[ForkchoiceUpdatedResponse] =
|
Future[ForkchoiceUpdatedResponse] =
|
||||||
when payloadAttributes is Option[PayloadAttributesV1]:
|
when payloadAttributes is Opt[PayloadAttributesV1]:
|
||||||
rpcClient.engine_forkchoiceUpdatedV1(state, payloadAttributes)
|
rpcClient.engine_forkchoiceUpdatedV1(state, payloadAttributes)
|
||||||
elif payloadAttributes is Option[PayloadAttributesV2]:
|
elif payloadAttributes is Opt[PayloadAttributesV2]:
|
||||||
rpcClient.engine_forkchoiceUpdatedV2(state, payloadAttributes)
|
rpcClient.engine_forkchoiceUpdatedV2(state, payloadAttributes)
|
||||||
elif payloadAttributes is Option[PayloadAttributesV3]:
|
elif payloadAttributes is Opt[PayloadAttributesV3]:
|
||||||
rpcClient.engine_forkchoiceUpdatedV3(state, payloadAttributes)
|
rpcClient.engine_forkchoiceUpdatedV3(state, payloadAttributes)
|
||||||
else:
|
else:
|
||||||
static: doAssert false
|
static: doAssert false
|
||||||
|
@ -817,7 +817,7 @@ proc getPayloadFromSingleEL(
|
||||||
headBlockHash: headBlock.asBlockHash,
|
headBlockHash: headBlock.asBlockHash,
|
||||||
safeBlockHash: safeBlock.asBlockHash,
|
safeBlockHash: safeBlock.asBlockHash,
|
||||||
finalizedBlockHash: finalizedBlock.asBlockHash),
|
finalizedBlockHash: finalizedBlock.asBlockHash),
|
||||||
some PayloadAttributesV1(
|
Opt.some PayloadAttributesV1(
|
||||||
timestamp: Quantity timestamp,
|
timestamp: Quantity timestamp,
|
||||||
prevRandao: FixedBytes[32] randomData.data,
|
prevRandao: FixedBytes[32] randomData.data,
|
||||||
suggestedFeeRecipient: suggestedFeeRecipient))
|
suggestedFeeRecipient: suggestedFeeRecipient))
|
||||||
|
@ -827,7 +827,7 @@ proc getPayloadFromSingleEL(
|
||||||
headBlockHash: headBlock.asBlockHash,
|
headBlockHash: headBlock.asBlockHash,
|
||||||
safeBlockHash: safeBlock.asBlockHash,
|
safeBlockHash: safeBlock.asBlockHash,
|
||||||
finalizedBlockHash: finalizedBlock.asBlockHash),
|
finalizedBlockHash: finalizedBlock.asBlockHash),
|
||||||
some PayloadAttributesV2(
|
Opt.some PayloadAttributesV2(
|
||||||
timestamp: Quantity timestamp,
|
timestamp: Quantity timestamp,
|
||||||
prevRandao: FixedBytes[32] randomData.data,
|
prevRandao: FixedBytes[32] randomData.data,
|
||||||
suggestedFeeRecipient: suggestedFeeRecipient,
|
suggestedFeeRecipient: suggestedFeeRecipient,
|
||||||
|
@ -841,7 +841,7 @@ proc getPayloadFromSingleEL(
|
||||||
headBlockHash: headBlock.asBlockHash,
|
headBlockHash: headBlock.asBlockHash,
|
||||||
safeBlockHash: safeBlock.asBlockHash,
|
safeBlockHash: safeBlock.asBlockHash,
|
||||||
finalizedBlockHash: finalizedBlock.asBlockHash),
|
finalizedBlockHash: finalizedBlock.asBlockHash),
|
||||||
some PayloadAttributesV3(
|
Opt.some PayloadAttributesV3(
|
||||||
timestamp: Quantity timestamp,
|
timestamp: Quantity timestamp,
|
||||||
prevRandao: FixedBytes[32] randomData.data,
|
prevRandao: FixedBytes[32] randomData.data,
|
||||||
suggestedFeeRecipient: suggestedFeeRecipient,
|
suggestedFeeRecipient: suggestedFeeRecipient,
|
||||||
|
@ -1341,9 +1341,9 @@ proc sendNewPayload*(
|
||||||
proc forkchoiceUpdatedForSingleEL(
|
proc forkchoiceUpdatedForSingleEL(
|
||||||
connection: ELConnection,
|
connection: ELConnection,
|
||||||
state: ref ForkchoiceStateV1,
|
state: ref ForkchoiceStateV1,
|
||||||
payloadAttributes: Option[PayloadAttributesV1] |
|
payloadAttributes: Opt[PayloadAttributesV1] |
|
||||||
Option[PayloadAttributesV2] |
|
Opt[PayloadAttributesV2] |
|
||||||
Option[PayloadAttributesV3]
|
Opt[PayloadAttributesV3]
|
||||||
): Future[PayloadStatusV1] {.async: (raises: [CatchableError]).} =
|
): Future[PayloadStatusV1] {.async: (raises: [CatchableError]).} =
|
||||||
let
|
let
|
||||||
rpcClient = await connection.connectedRpcClient()
|
rpcClient = await connection.connectedRpcClient()
|
||||||
|
@ -1363,10 +1363,10 @@ proc forkchoiceUpdatedForSingleEL(
|
||||||
proc forkchoiceUpdated*(
|
proc forkchoiceUpdated*(
|
||||||
m: ELManager,
|
m: ELManager,
|
||||||
headBlockHash, safeBlockHash, finalizedBlockHash: Eth2Digest,
|
headBlockHash, safeBlockHash, finalizedBlockHash: Eth2Digest,
|
||||||
payloadAttributes: Option[PayloadAttributesV1] |
|
payloadAttributes: Opt[PayloadAttributesV1] |
|
||||||
Option[PayloadAttributesV2] |
|
Opt[PayloadAttributesV2] |
|
||||||
Option[PayloadAttributesV3]
|
Opt[PayloadAttributesV3]
|
||||||
): Future[(PayloadExecutionStatus, Option[BlockHash])] {.
|
): Future[(PayloadExecutionStatus, Opt[BlockHash])] {.
|
||||||
async: (raises: [CancelledError]).} =
|
async: (raises: [CancelledError]).} =
|
||||||
|
|
||||||
doAssert not headBlockHash.isZero
|
doAssert not headBlockHash.isZero
|
||||||
|
@ -1383,16 +1383,16 @@ proc forkchoiceUpdated*(
|
||||||
# payload (`Hash32()` if none yet finalized)"
|
# payload (`Hash32()` if none yet finalized)"
|
||||||
|
|
||||||
if m.elConnections.len == 0:
|
if m.elConnections.len == 0:
|
||||||
return (PayloadExecutionStatus.syncing, none BlockHash)
|
return (PayloadExecutionStatus.syncing, Opt.none BlockHash)
|
||||||
|
|
||||||
when payloadAttributes is Option[PayloadAttributesV3]:
|
when payloadAttributes is Opt[PayloadAttributesV3]:
|
||||||
template payloadAttributesV3(): auto =
|
template payloadAttributesV3(): auto =
|
||||||
if payloadAttributes.isSome:
|
if payloadAttributes.isSome:
|
||||||
payloadAttributes.get
|
payloadAttributes.get
|
||||||
else:
|
else:
|
||||||
# As timestamp and prevRandao are both 0, won't false-positive match
|
# As timestamp and prevRandao are both 0, won't false-positive match
|
||||||
(static(default(PayloadAttributesV3)))
|
(static(default(PayloadAttributesV3)))
|
||||||
elif payloadAttributes is Option[PayloadAttributesV2]:
|
elif payloadAttributes is Opt[PayloadAttributesV2]:
|
||||||
template payloadAttributesV3(): auto =
|
template payloadAttributesV3(): auto =
|
||||||
if payloadAttributes.isSome:
|
if payloadAttributes.isSome:
|
||||||
PayloadAttributesV3(
|
PayloadAttributesV3(
|
||||||
|
@ -1404,7 +1404,7 @@ proc forkchoiceUpdated*(
|
||||||
else:
|
else:
|
||||||
# As timestamp and prevRandao are both 0, won't false-positive match
|
# As timestamp and prevRandao are both 0, won't false-positive match
|
||||||
(static(default(PayloadAttributesV3)))
|
(static(default(PayloadAttributesV3)))
|
||||||
elif payloadAttributes is Option[PayloadAttributesV1]:
|
elif payloadAttributes is Opt[PayloadAttributesV1]:
|
||||||
template payloadAttributesV3(): auto =
|
template payloadAttributesV3(): auto =
|
||||||
if payloadAttributes.isSome:
|
if payloadAttributes.isSome:
|
||||||
PayloadAttributesV3(
|
PayloadAttributesV3(
|
||||||
|
@ -1489,7 +1489,7 @@ proc forkchoiceUpdated*(
|
||||||
pendingRequests.filterIt(not(it.finished())).
|
pendingRequests.filterIt(not(it.finished())).
|
||||||
mapIt(it.cancelAndWait())
|
mapIt(it.cancelAndWait())
|
||||||
await noCancel allFutures(pending)
|
await noCancel allFutures(pending)
|
||||||
return (PayloadExecutionStatus.invalid, none BlockHash)
|
return (PayloadExecutionStatus.invalid, Opt.none BlockHash)
|
||||||
elif responseProcessor.selectedResponse.isSome:
|
elif responseProcessor.selectedResponse.isSome:
|
||||||
# We spawn task which will wait for all other responses which are
|
# We spawn task which will wait for all other responses which are
|
||||||
# still pending, after 30.seconds all pending requests will be
|
# still pending, after 30.seconds all pending requests will be
|
||||||
|
@ -1504,7 +1504,7 @@ proc forkchoiceUpdated*(
|
||||||
pendingRequests.filterIt(not(it.finished())).
|
pendingRequests.filterIt(not(it.finished())).
|
||||||
mapIt(it.cancelAndWait())
|
mapIt(it.cancelAndWait())
|
||||||
await noCancel allFutures(pending)
|
await noCancel allFutures(pending)
|
||||||
return (PayloadExecutionStatus.syncing, none BlockHash)
|
return (PayloadExecutionStatus.syncing, Opt.none BlockHash)
|
||||||
|
|
||||||
if len(pendingRequests) == 0:
|
if len(pendingRequests) == 0:
|
||||||
# All requests failed, we will continue our attempts until deadline
|
# All requests failed, we will continue our attempts until deadline
|
||||||
|
@ -1762,7 +1762,7 @@ proc new*(T: type ELManager,
|
||||||
depositContractBlockHash: Eth2Digest,
|
depositContractBlockHash: Eth2Digest,
|
||||||
db: BeaconChainDB,
|
db: BeaconChainDB,
|
||||||
engineApiUrls: seq[EngineApiUrl],
|
engineApiUrls: seq[EngineApiUrl],
|
||||||
eth1Network: Option[Eth1Network]): T =
|
eth1Network: Opt[Eth1Network]): T =
|
||||||
let
|
let
|
||||||
eth1Chain = Eth1Chain.init(
|
eth1Chain = Eth1Chain.init(
|
||||||
cfg, db, depositContractBlockNumber, depositContractBlockHash)
|
cfg, db, depositContractBlockNumber, depositContractBlockHash)
|
||||||
|
@ -1847,8 +1847,8 @@ proc syncBlockRange(
|
||||||
await connection.engineApiRequest(
|
await connection.engineApiRequest(
|
||||||
depositContract.getJsonLogs(
|
depositContract.getJsonLogs(
|
||||||
DepositEvent,
|
DepositEvent,
|
||||||
fromBlock = some blockId(currentBlock),
|
fromBlock = Opt.some blockId(currentBlock),
|
||||||
toBlock = some blockId(maxBlockNumberRequested)),
|
toBlock = Opt.some blockId(maxBlockNumberRequested)),
|
||||||
"getLogs", Moment.now(), 30.seconds)
|
"getLogs", Moment.now(), 30.seconds)
|
||||||
except CancelledError as exc:
|
except CancelledError as exc:
|
||||||
debug "Request for deposit logs was interrupted"
|
debug "Request for deposit logs was interrupted"
|
||||||
|
@ -1956,7 +1956,6 @@ proc startExchangeTransitionConfigurationLoop(
|
||||||
|
|
||||||
while true:
|
while true:
|
||||||
# https://github.com/ethereum/execution-apis/blob/v1.0.0-beta.3/src/engine/paris.md#specification-3
|
# https://github.com/ethereum/execution-apis/blob/v1.0.0-beta.3/src/engine/paris.md#specification-3
|
||||||
debug "Exchange transition configuration tick"
|
|
||||||
await m.exchangeTransitionConfiguration()
|
await m.exchangeTransitionConfiguration()
|
||||||
await sleepAsync(60.seconds)
|
await sleepAsync(60.seconds)
|
||||||
|
|
||||||
|
@ -2090,7 +2089,7 @@ proc syncEth1Chain(
|
||||||
|
|
||||||
latestBlockNumber = latestBlock.number
|
latestBlockNumber = latestBlock.number
|
||||||
|
|
||||||
m.syncTargetBlock = some(
|
m.syncTargetBlock = Opt.some(
|
||||||
if latestBlock.number > m.cfg.ETH1_FOLLOW_DISTANCE.Eth1BlockNumber:
|
if latestBlock.number > m.cfg.ETH1_FOLLOW_DISTANCE.Eth1BlockNumber:
|
||||||
latestBlock.number - m.cfg.ETH1_FOLLOW_DISTANCE
|
latestBlock.number - m.cfg.ETH1_FOLLOW_DISTANCE
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
{.push raises: [].}
|
{.push raises: [].}
|
||||||
|
|
||||||
import
|
import
|
||||||
stew/results,
|
|
||||||
chronicles, chronos, metrics,
|
chronicles, chronos, metrics,
|
||||||
../spec/[forks, signatures, signatures_batch],
|
../spec/[forks, signatures, signatures_batch],
|
||||||
../sszdump
|
../sszdump
|
||||||
|
@ -243,7 +242,7 @@ proc expectValidForkchoiceUpdated(
|
||||||
headBlockHash = headBlockHash,
|
headBlockHash = headBlockHash,
|
||||||
safeBlockHash = safeBlockHash,
|
safeBlockHash = safeBlockHash,
|
||||||
finalizedBlockHash = finalizedBlockHash,
|
finalizedBlockHash = finalizedBlockHash,
|
||||||
payloadAttributes = none headBlockPayloadAttributesType)
|
payloadAttributes = Opt.none headBlockPayloadAttributesType)
|
||||||
receivedExecutionBlockHash =
|
receivedExecutionBlockHash =
|
||||||
when typeof(receivedBlock).kind >= ConsensusFork.Bellatrix:
|
when typeof(receivedBlock).kind >= ConsensusFork.Bellatrix:
|
||||||
receivedBlock.message.body.execution_payload.block_hash
|
receivedBlock.message.body.execution_payload.block_hash
|
||||||
|
@ -685,7 +684,7 @@ proc storeBlock(
|
||||||
self.consensusManager[].optimisticExecutionBlockHash,
|
self.consensusManager[].optimisticExecutionBlockHash,
|
||||||
safeBlockHash = newHead.get.safeExecutionBlockHash,
|
safeBlockHash = newHead.get.safeExecutionBlockHash,
|
||||||
finalizedBlockHash = newHead.get.finalizedExecutionBlockHash,
|
finalizedBlockHash = newHead.get.finalizedExecutionBlockHash,
|
||||||
payloadAttributes = none attributes)
|
payloadAttributes = Opt.none attributes)
|
||||||
|
|
||||||
let consensusFork = self.consensusManager.dag.cfg.consensusForkAtEpoch(
|
let consensusFork = self.consensusManager.dag.cfg.consensusForkAtEpoch(
|
||||||
newHead.get.blck.bid.slot.epoch)
|
newHead.get.blck.bid.slot.epoch)
|
||||||
|
|
|
@ -9,8 +9,8 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
std/tables,
|
std/tables,
|
||||||
stew/results,
|
chronicles, chronos, metrics,
|
||||||
chronicles, chronos, metrics, taskpools,
|
taskpools,
|
||||||
../spec/[helpers, forks],
|
../spec/[helpers, forks],
|
||||||
../spec/datatypes/[altair, phase0, deneb],
|
../spec/datatypes/[altair, phase0, deneb],
|
||||||
../consensus_object_pools/[
|
../consensus_object_pools/[
|
||||||
|
@ -122,7 +122,7 @@ type
|
||||||
# ----------------------------------------------------------------
|
# ----------------------------------------------------------------
|
||||||
dag*: ChainDAGRef
|
dag*: ChainDAGRef
|
||||||
attestationPool*: ref AttestationPool
|
attestationPool*: ref AttestationPool
|
||||||
validatorPool: ref ValidatorPool
|
validatorPool*: ref ValidatorPool
|
||||||
syncCommitteeMsgPool: ref SyncCommitteeMsgPool
|
syncCommitteeMsgPool: ref SyncCommitteeMsgPool
|
||||||
lightClientPool: ref LightClientPool
|
lightClientPool: ref LightClientPool
|
||||||
|
|
||||||
|
@ -366,7 +366,8 @@ proc checkForPotentialDoppelganger(
|
||||||
proc processAttestation*(
|
proc processAttestation*(
|
||||||
self: ref Eth2Processor, src: MsgSource,
|
self: ref Eth2Processor, src: MsgSource,
|
||||||
attestation: phase0.Attestation | electra.Attestation, subnet_id: SubnetId,
|
attestation: phase0.Attestation | electra.Attestation, subnet_id: SubnetId,
|
||||||
checkSignature: bool = true): Future[ValidationRes] {.async: (raises: [CancelledError]).} =
|
checkSignature, checkValidator: bool
|
||||||
|
): Future[ValidationRes] {.async: (raises: [CancelledError]).} =
|
||||||
var wallTime = self.getCurrentBeaconTime()
|
var wallTime = self.getCurrentBeaconTime()
|
||||||
let (afterGenesis, wallSlot) = wallTime.toSlot()
|
let (afterGenesis, wallSlot) = wallTime.toSlot()
|
||||||
|
|
||||||
|
@ -393,19 +394,26 @@ proc processAttestation*(
|
||||||
|
|
||||||
let (attester_index, sig) = v.get()
|
let (attester_index, sig) = v.get()
|
||||||
|
|
||||||
self[].checkForPotentialDoppelganger(attestation, [attester_index])
|
if checkValidator and (attester_index in self.validatorPool[]):
|
||||||
|
warn "A validator client has attempted to send an attestation from " &
|
||||||
|
"validator that is also managed by the beacon node",
|
||||||
|
validator_index = attester_index
|
||||||
|
errReject("An attestation could not be sent from a validator that is " &
|
||||||
|
"also managed by the beacon node")
|
||||||
|
else:
|
||||||
|
self[].checkForPotentialDoppelganger(attestation, [attester_index])
|
||||||
|
|
||||||
trace "Attestation validated"
|
trace "Attestation validated"
|
||||||
self.attestationPool[].addAttestation(
|
self.attestationPool[].addAttestation(
|
||||||
attestation, [attester_index], sig, wallTime)
|
attestation, [attester_index], sig, wallTime)
|
||||||
|
|
||||||
self.validatorMonitor[].registerAttestation(
|
self.validatorMonitor[].registerAttestation(
|
||||||
src, wallTime, attestation, attester_index)
|
src, wallTime, attestation, attester_index)
|
||||||
|
|
||||||
beacon_attestations_received.inc()
|
beacon_attestations_received.inc()
|
||||||
beacon_attestation_delay.observe(delay.toFloatSeconds())
|
beacon_attestation_delay.observe(delay.toFloatSeconds())
|
||||||
|
|
||||||
ok()
|
ok()
|
||||||
else:
|
else:
|
||||||
debug "Dropping attestation", reason = $v.error
|
debug "Dropping attestation", reason = $v.error
|
||||||
beacon_attestations_dropped.inc(1, [$v.error[0]])
|
beacon_attestations_dropped.inc(1, [$v.error[0]])
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
std/[json, sequtils, times],
|
std/[json, sequtils, times],
|
||||||
stew/saturation_arith,
|
|
||||||
eth/common/[eth_types_rlp, transaction],
|
eth/common/[eth_types_rlp, transaction],
|
||||||
eth/keys,
|
eth/keys,
|
||||||
eth/p2p/discoveryv5/random2,
|
eth/p2p/discoveryv5/random2,
|
||||||
|
@ -1254,37 +1253,37 @@ proc ETHExecutionBlockHeaderCreateFromJson(
|
||||||
coinbase: distinctBase(data.miner),
|
coinbase: distinctBase(data.miner),
|
||||||
stateRoot: data.stateRoot.asEth2Digest,
|
stateRoot: data.stateRoot.asEth2Digest,
|
||||||
txRoot: data.transactionsRoot.asEth2Digest,
|
txRoot: data.transactionsRoot.asEth2Digest,
|
||||||
receiptRoot: data.receiptsRoot.asEth2Digest,
|
receiptsRoot: data.receiptsRoot.asEth2Digest,
|
||||||
bloom: distinctBase(data.logsBloom),
|
logsBloom: distinctBase(data.logsBloom),
|
||||||
difficulty: data.difficulty,
|
difficulty: data.difficulty,
|
||||||
blockNumber: distinctBase(data.number).u256,
|
number: distinctBase(data.number),
|
||||||
gasLimit: cast[int64](data.gasLimit),
|
gasLimit: distinctBase(data.gasLimit),
|
||||||
gasUsed: cast[int64](data.gasUsed),
|
gasUsed: distinctBase(data.gasUsed),
|
||||||
timestamp: EthTime(int64.saturate distinctBase(data.timestamp)),
|
timestamp: EthTime(distinctBase(data.timestamp)),
|
||||||
extraData: distinctBase(data.extraData),
|
extraData: distinctBase(data.extraData),
|
||||||
mixDigest: data.mixHash.asEth2Digest,
|
mixHash: data.mixHash.asEth2Digest,
|
||||||
nonce: distinctBase(data.nonce.get),
|
nonce: distinctBase(data.nonce.get),
|
||||||
fee: data.baseFeePerGas,
|
baseFeePerGas: data.baseFeePerGas,
|
||||||
withdrawalsRoot:
|
withdrawalsRoot:
|
||||||
if data.withdrawalsRoot.isSome:
|
if data.withdrawalsRoot.isSome:
|
||||||
some(data.withdrawalsRoot.get.asEth2Digest)
|
Opt.some(data.withdrawalsRoot.get.asEth2Digest)
|
||||||
else:
|
else:
|
||||||
none(ExecutionHash256),
|
Opt.none(ExecutionHash256),
|
||||||
blobGasUsed:
|
blobGasUsed:
|
||||||
if data.blobGasUsed.isSome:
|
if data.blobGasUsed.isSome:
|
||||||
some distinctBase(data.blobGasUsed.get)
|
Opt.some distinctBase(data.blobGasUsed.get)
|
||||||
else:
|
else:
|
||||||
none(uint64),
|
Opt.none(uint64),
|
||||||
excessBlobGas:
|
excessBlobGas:
|
||||||
if data.excessBlobGas.isSome:
|
if data.excessBlobGas.isSome:
|
||||||
some distinctBase(data.excessBlobGas.get)
|
Opt.some distinctBase(data.excessBlobGas.get)
|
||||||
else:
|
else:
|
||||||
none(uint64),
|
Opt.none(uint64),
|
||||||
parentBeaconBlockRoot:
|
parentBeaconBlockRoot:
|
||||||
if data.parentBeaconBlockRoot.isSome:
|
if data.parentBeaconBlockRoot.isSome:
|
||||||
some distinctBase(data.parentBeaconBlockRoot.get.asEth2Digest)
|
Opt.some distinctBase(data.parentBeaconBlockRoot.get.asEth2Digest)
|
||||||
else:
|
else:
|
||||||
none(ExecutionHash256))
|
Opt.none(ExecutionHash256))
|
||||||
if rlpHash(blockHeader) != executionHash[]:
|
if rlpHash(blockHeader) != executionHash[]:
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
|
@ -1529,15 +1528,15 @@ proc ETHTransactionsCreateFromJson(
|
||||||
chainId: data.chainId.get(0.Quantity).ChainId,
|
chainId: data.chainId.get(0.Quantity).ChainId,
|
||||||
nonce: distinctBase(data.nonce),
|
nonce: distinctBase(data.nonce),
|
||||||
gasPrice: data.gasPrice.GasInt,
|
gasPrice: data.gasPrice.GasInt,
|
||||||
maxPriorityFee:
|
maxPriorityFeePerGas:
|
||||||
distinctBase(data.maxPriorityFeePerGas.get(data.gasPrice)).GasInt,
|
distinctBase(data.maxPriorityFeePerGas.get(data.gasPrice)).GasInt,
|
||||||
maxFee: distinctBase(data.maxFeePerGas.get(data.gasPrice)).GasInt,
|
maxFeePerGas: distinctBase(data.maxFeePerGas.get(data.gasPrice)).GasInt,
|
||||||
gasLimit: distinctBase(data.gas).GasInt,
|
gasLimit: distinctBase(data.gas).GasInt,
|
||||||
to:
|
to:
|
||||||
if data.to.isSome:
|
if data.to.isSome:
|
||||||
some(distinctBase(data.to.get))
|
Opt.some(distinctBase(data.to.get))
|
||||||
else:
|
else:
|
||||||
none(EthAddress),
|
Opt.none(EthAddress),
|
||||||
value: data.value,
|
value: data.value,
|
||||||
payload: data.input,
|
payload: data.input,
|
||||||
accessList:
|
accessList:
|
||||||
|
@ -1555,7 +1554,7 @@ proc ETHTransactionsCreateFromJson(
|
||||||
ExecutionHash256(data: distinctBase(it)))
|
ExecutionHash256(data: distinctBase(it)))
|
||||||
else:
|
else:
|
||||||
@[],
|
@[],
|
||||||
V: data.v.int64,
|
V: data.v.uint64,
|
||||||
R: data.r,
|
R: data.r,
|
||||||
S: data.s)
|
S: data.s)
|
||||||
rlpBytes =
|
rlpBytes =
|
||||||
|
@ -1567,7 +1566,7 @@ proc ETHTransactionsCreateFromJson(
|
||||||
if data.hash.asEth2Digest != hash:
|
if data.hash.asEth2Digest != hash:
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
template isEven(x: int64): bool =
|
template isEven(x: uint64): bool =
|
||||||
(x and 1) == 0
|
(x and 1) == 0
|
||||||
|
|
||||||
# Compute from execution address
|
# Compute from execution address
|
||||||
|
@ -1614,9 +1613,9 @@ proc ETHTransactionsCreateFromJson(
|
||||||
chainId: distinctBase(tx.chainId).u256,
|
chainId: distinctBase(tx.chainId).u256,
|
||||||
`from`: ExecutionAddress(data: fromAddress),
|
`from`: ExecutionAddress(data: fromAddress),
|
||||||
nonce: tx.nonce,
|
nonce: tx.nonce,
|
||||||
maxPriorityFeePerGas: tx.maxPriorityFee.uint64,
|
maxPriorityFeePerGas: tx.maxPriorityFeePerGas,
|
||||||
maxFeePerGas: tx.maxFee.uint64,
|
maxFeePerGas: tx.maxFeePerGas,
|
||||||
gas: tx.gasLimit.uint64,
|
gas: tx.gasLimit,
|
||||||
destinationType: destinationType,
|
destinationType: destinationType,
|
||||||
to: ExecutionAddress(data: toAddress),
|
to: ExecutionAddress(data: toAddress),
|
||||||
value: tx.value,
|
value: tx.value,
|
||||||
|
@ -2178,7 +2177,7 @@ proc ETHReceiptsCreateFromJson(
|
||||||
else:
|
else:
|
||||||
default(ExecutionHash256),
|
default(ExecutionHash256),
|
||||||
cumulativeGasUsed: distinctBase(data.cumulativeGasUsed).GasInt,
|
cumulativeGasUsed: distinctBase(data.cumulativeGasUsed).GasInt,
|
||||||
bloom: distinctBase(data.logsBloom),
|
logsBloom: distinctBase(data.logsBloom),
|
||||||
logs: data.logs.mapIt(Log(
|
logs: data.logs.mapIt(Log(
|
||||||
address: distinctBase(it.address),
|
address: distinctBase(it.address),
|
||||||
topics: it.topics.mapIt(distinctBase(it)),
|
topics: it.topics.mapIt(distinctBase(it)),
|
||||||
|
@ -2198,7 +2197,7 @@ proc ETHReceiptsCreateFromJson(
|
||||||
root: rec.hash,
|
root: rec.hash,
|
||||||
status: rec.status,
|
status: rec.status,
|
||||||
gasUsed: distinctBase(data.gasUsed), # Validated during sanity checks.
|
gasUsed: distinctBase(data.gasUsed), # Validated during sanity checks.
|
||||||
logsBloom: BloomLogs(data: rec.bloom),
|
logsBloom: BloomLogs(data: rec.logsBloom),
|
||||||
logs: rec.logs.mapIt(ETHLog(
|
logs: rec.logs.mapIt(ETHLog(
|
||||||
address: ExecutionAddress(data: it.address),
|
address: ExecutionAddress(data: it.address),
|
||||||
topics: it.topics.mapIt(Eth2Digest(data: it)),
|
topics: it.topics.mapIt(Eth2Digest(data: it)),
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
../../../vendor/eth2-networks/shared/mainnet/config.yaml
|
../../../vendor/mainnet/metadata/config.yaml
|
|
@ -1 +1 @@
|
||||||
../../../vendor/eth2-networks/shared/mainnet/genesis.ssz
|
../../../vendor/mainnet/metadata/genesis.ssz
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
std/[algorithm, sequtils],
|
std/[algorithm, sequtils],
|
||||||
chronos, chronicles, stew/results,
|
chronos, chronicles,
|
||||||
eth/p2p/discoveryv5/[enr, protocol, node, random2],
|
eth/p2p/discoveryv5/[enr, protocol, node, random2],
|
||||||
../spec/datatypes/altair,
|
../spec/datatypes/altair,
|
||||||
../spec/eth2_ssz_serialization,
|
../spec/eth2_ssz_serialization,
|
||||||
|
@ -53,7 +53,7 @@ proc addBootstrapNode*(bootstrapAddr: string,
|
||||||
return
|
return
|
||||||
|
|
||||||
# Ignore comments in
|
# Ignore comments in
|
||||||
# https://github.com/eth-clients/eth2-networks/blob/063f826a03676c33c95a66306916f18b690d35eb/shared/mainnet/bootstrap_nodes.txt
|
# https://github.com/eth-clients/mainnet/blob/main/metadata/bootstrap_nodes.txt
|
||||||
let enrRes = parseBootstrapAddress(bootstrapAddr.split(" # ")[0])
|
let enrRes = parseBootstrapAddress(bootstrapAddr.split(" # ")[0])
|
||||||
if enrRes.isOk:
|
if enrRes.isOk:
|
||||||
bootstrapEnrs.add enrRes.value
|
bootstrapEnrs.add enrRes.value
|
||||||
|
@ -127,7 +127,7 @@ proc queryRandom*(
|
||||||
forkId: ENRForkID,
|
forkId: ENRForkID,
|
||||||
wantedAttnets: AttnetBits,
|
wantedAttnets: AttnetBits,
|
||||||
wantedSyncnets: SyncnetBits,
|
wantedSyncnets: SyncnetBits,
|
||||||
minScore: int): Future[seq[Node]] {.async.} =
|
minScore: int): Future[seq[Node]] {.async: (raises: [CancelledError]).} =
|
||||||
## Perform a discovery query for a random target
|
## Perform a discovery query for a random target
|
||||||
## (forkId) and matching at least one of the attestation subnets.
|
## (forkId) and matching at least one of the attestation subnets.
|
||||||
|
|
||||||
|
@ -143,7 +143,7 @@ proc queryRandom*(
|
||||||
peerForkId =
|
peerForkId =
|
||||||
try:
|
try:
|
||||||
SSZ.decode(eth2FieldBytes, ENRForkID)
|
SSZ.decode(eth2FieldBytes, ENRForkID)
|
||||||
except SszError as e:
|
except SerializationError as e:
|
||||||
debug "Could not decode the eth2 field of peer",
|
debug "Could not decode the eth2 field of peer",
|
||||||
peer = n.record.toURI(), exception = e.name, msg = e.msg
|
peer = n.record.toURI(), exception = e.name, msg = e.msg
|
||||||
continue
|
continue
|
||||||
|
@ -156,7 +156,7 @@ proc queryRandom*(
|
||||||
let attnetsNode =
|
let attnetsNode =
|
||||||
try:
|
try:
|
||||||
SSZ.decode(attnetsBytes.get(), AttnetBits)
|
SSZ.decode(attnetsBytes.get(), AttnetBits)
|
||||||
except SszError as e:
|
except SerializationError as e:
|
||||||
debug "Could not decode the attnets ERN bitfield of peer",
|
debug "Could not decode the attnets ERN bitfield of peer",
|
||||||
peer = n.record.toURI(), exception = e.name, msg = e.msg
|
peer = n.record.toURI(), exception = e.name, msg = e.msg
|
||||||
continue
|
continue
|
||||||
|
@ -170,7 +170,7 @@ proc queryRandom*(
|
||||||
let syncnetsNode =
|
let syncnetsNode =
|
||||||
try:
|
try:
|
||||||
SSZ.decode(syncnetsBytes.get(), SyncnetBits)
|
SSZ.decode(syncnetsBytes.get(), SyncnetBits)
|
||||||
except SszError as e:
|
except SerializationError as e:
|
||||||
debug "Could not decode the syncnets ENR bitfield of peer",
|
debug "Could not decode the syncnets ENR bitfield of peer",
|
||||||
peer = n.record.toURI(), exception = e.name, msg = e.msg
|
peer = n.record.toURI(), exception = e.name, msg = e.msg
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -1550,7 +1550,7 @@ proc getLowSubnets(node: Eth2Node, epoch: Epoch): (AttnetBits, SyncnetBits) =
|
||||||
default(SyncnetBits)
|
default(SyncnetBits)
|
||||||
)
|
)
|
||||||
|
|
||||||
proc runDiscoveryLoop(node: Eth2Node) {.async.} =
|
proc runDiscoveryLoop(node: Eth2Node) {.async: (raises: [CancelledError]).} =
|
||||||
debug "Starting discovery loop"
|
debug "Starting discovery loop"
|
||||||
|
|
||||||
while true:
|
while true:
|
||||||
|
|
|
@ -78,7 +78,7 @@ type
|
||||||
# additional checks to ensure we are connecting to a web3 provider
|
# additional checks to ensure we are connecting to a web3 provider
|
||||||
# serving data for the same network. The value can be set to `None`
|
# serving data for the same network. The value can be set to `None`
|
||||||
# for custom networks and testing purposes.
|
# for custom networks and testing purposes.
|
||||||
eth1Network*: Option[Eth1Network]
|
eth1Network*: Opt[Eth1Network]
|
||||||
cfg*: RuntimeConfig
|
cfg*: RuntimeConfig
|
||||||
|
|
||||||
# Parsing `enr.Records` is still not possible at compile-time
|
# Parsing `enr.Records` is still not possible at compile-time
|
||||||
|
@ -112,13 +112,13 @@ proc readBootEnr*(path: string): seq[string] {.raises: [IOError].} =
|
||||||
|
|
||||||
proc loadEth2NetworkMetadata*(
|
proc loadEth2NetworkMetadata*(
|
||||||
path: string,
|
path: string,
|
||||||
eth1Network = none(Eth1Network),
|
eth1Network = Opt.none(Eth1Network),
|
||||||
isCompileTime = false,
|
isCompileTime = false,
|
||||||
downloadGenesisFrom = none(DownloadInfo),
|
downloadGenesisFrom = Opt.none(DownloadInfo),
|
||||||
useBakedInGenesis = none(string)
|
useBakedInGenesis = Opt.none(string)
|
||||||
): Result[Eth2NetworkMetadata, string] {.raises: [IOError, PresetFileError].} =
|
): Result[Eth2NetworkMetadata, string] {.raises: [IOError, PresetFileError].} =
|
||||||
# Load data in eth2-networks format
|
# Load data in mainnet format
|
||||||
# https://github.com/eth-clients/eth2-networks
|
# https://github.com/eth-clients/mainnet
|
||||||
|
|
||||||
try:
|
try:
|
||||||
let
|
let
|
||||||
|
@ -208,9 +208,9 @@ proc loadEth2NetworkMetadata*(
|
||||||
|
|
||||||
proc loadCompileTimeNetworkMetadata(
|
proc loadCompileTimeNetworkMetadata(
|
||||||
path: string,
|
path: string,
|
||||||
eth1Network = none(Eth1Network),
|
eth1Network = Opt.none(Eth1Network),
|
||||||
useBakedInGenesis = none(string),
|
useBakedInGenesis = Opt.none(string),
|
||||||
downloadGenesisFrom = none(DownloadInfo)): Eth2NetworkMetadata =
|
downloadGenesisFrom = Opt.none(DownloadInfo)): Eth2NetworkMetadata =
|
||||||
if fileExists(path & "/config.yaml"):
|
if fileExists(path & "/config.yaml"):
|
||||||
try:
|
try:
|
||||||
let res = loadEth2NetworkMetadata(
|
let res = loadEth2NetworkMetadata(
|
||||||
|
@ -255,13 +255,13 @@ when const_preset == "gnosis":
|
||||||
const
|
const
|
||||||
gnosisMetadata = loadCompileTimeNetworkMetadata(
|
gnosisMetadata = loadCompileTimeNetworkMetadata(
|
||||||
vendorDir & "/gnosis-chain-configs/mainnet",
|
vendorDir & "/gnosis-chain-configs/mainnet",
|
||||||
none(Eth1Network),
|
Opt.none(Eth1Network),
|
||||||
useBakedInGenesis = some "gnosis")
|
useBakedInGenesis = Opt.some "gnosis")
|
||||||
|
|
||||||
chiadoMetadata = loadCompileTimeNetworkMetadata(
|
chiadoMetadata = loadCompileTimeNetworkMetadata(
|
||||||
vendorDir & "/gnosis-chain-configs/chiado",
|
vendorDir & "/gnosis-chain-configs/chiado",
|
||||||
none(Eth1Network),
|
Opt.none(Eth1Network),
|
||||||
useBakedInGenesis = some "chiado")
|
useBakedInGenesis = Opt.some "chiado")
|
||||||
|
|
||||||
static:
|
static:
|
||||||
for network in [gnosisMetadata, chiadoMetadata]:
|
for network in [gnosisMetadata, chiadoMetadata]:
|
||||||
|
@ -292,28 +292,28 @@ elif const_preset == "mainnet":
|
||||||
else:
|
else:
|
||||||
const
|
const
|
||||||
mainnetGenesis* = slurp(
|
mainnetGenesis* = slurp(
|
||||||
vendorDir & "/eth2-networks/shared/mainnet/genesis.ssz")
|
vendorDir & "/mainnet/metadata/genesis.ssz")
|
||||||
|
|
||||||
sepoliaGenesis* = slurp(
|
sepoliaGenesis* = slurp(
|
||||||
vendorDir & "/sepolia/bepolia/genesis.ssz")
|
vendorDir & "/sepolia/bepolia/genesis.ssz")
|
||||||
|
|
||||||
const
|
const
|
||||||
mainnetMetadata = loadCompileTimeNetworkMetadata(
|
mainnetMetadata = loadCompileTimeNetworkMetadata(
|
||||||
vendorDir & "/eth2-networks/shared/mainnet",
|
vendorDir & "/mainnet/metadata",
|
||||||
some mainnet,
|
Opt.some mainnet,
|
||||||
useBakedInGenesis = some "mainnet")
|
useBakedInGenesis = Opt.some "mainnet")
|
||||||
|
|
||||||
holeskyMetadata = loadCompileTimeNetworkMetadata(
|
holeskyMetadata = loadCompileTimeNetworkMetadata(
|
||||||
vendorDir & "/holesky/custom_config_data",
|
vendorDir & "/holesky/custom_config_data",
|
||||||
some holesky,
|
Opt.some holesky,
|
||||||
downloadGenesisFrom = some DownloadInfo(
|
downloadGenesisFrom = Opt.some DownloadInfo(
|
||||||
url: "https://github.com/status-im/nimbus-eth2/releases/download/v23.9.1/holesky-genesis.ssz.sz",
|
url: "https://github.com/status-im/nimbus-eth2/releases/download/v23.9.1/holesky-genesis.ssz.sz",
|
||||||
digest: Eth2Digest.fromHex "0x0ea3f6f9515823b59c863454675fefcd1d8b4f2dbe454db166206a41fda060a0"))
|
digest: Eth2Digest.fromHex "0x0ea3f6f9515823b59c863454675fefcd1d8b4f2dbe454db166206a41fda060a0"))
|
||||||
|
|
||||||
sepoliaMetadata = loadCompileTimeNetworkMetadata(
|
sepoliaMetadata = loadCompileTimeNetworkMetadata(
|
||||||
vendorDir & "/sepolia/bepolia",
|
vendorDir & "/sepolia/bepolia",
|
||||||
some sepolia,
|
Opt.some sepolia,
|
||||||
useBakedInGenesis = some "sepolia")
|
useBakedInGenesis = Opt.some "sepolia")
|
||||||
|
|
||||||
static:
|
static:
|
||||||
for network in [mainnetMetadata, sepoliaMetadata, holeskyMetadata]:
|
for network in [mainnetMetadata, sepoliaMetadata, holeskyMetadata]:
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
# name_size = 64-bit length in bytes
|
# name_size = 64-bit length in bytes
|
||||||
|
|
||||||
eth2_mainnet_genesis_data:
|
eth2_mainnet_genesis_data:
|
||||||
.incbin "eth2-networks/shared/mainnet/genesis.ssz"
|
.incbin "mainnet/metadata/genesis.ssz"
|
||||||
eth2_mainnet_genesis_end:
|
eth2_mainnet_genesis_end:
|
||||||
.global cdecl(eth2_mainnet_genesis_size)
|
.global cdecl(eth2_mainnet_genesis_size)
|
||||||
.p2align 3
|
.p2align 3
|
||||||
|
|
|
@ -147,14 +147,16 @@ func getVanityLogs(stdoutKind: StdoutLogKind): VanityLogs =
|
||||||
onFinalizedMergeTransitionBlock: bellatrixBlink,
|
onFinalizedMergeTransitionBlock: bellatrixBlink,
|
||||||
onUpgradeToCapella: capellaColor,
|
onUpgradeToCapella: capellaColor,
|
||||||
onKnownBlsToExecutionChange: capellaBlink,
|
onKnownBlsToExecutionChange: capellaBlink,
|
||||||
onUpgradeToDeneb: denebColor)
|
onUpgradeToDeneb: denebColor,
|
||||||
|
onUpgradeToElectra: electraColor)
|
||||||
of StdoutLogKind.NoColors:
|
of StdoutLogKind.NoColors:
|
||||||
VanityLogs(
|
VanityLogs(
|
||||||
onMergeTransitionBlock: bellatrixMono,
|
onMergeTransitionBlock: bellatrixMono,
|
||||||
onFinalizedMergeTransitionBlock: bellatrixMono,
|
onFinalizedMergeTransitionBlock: bellatrixMono,
|
||||||
onUpgradeToCapella: capellaMono,
|
onUpgradeToCapella: capellaMono,
|
||||||
onKnownBlsToExecutionChange: capellaMono,
|
onKnownBlsToExecutionChange: capellaMono,
|
||||||
onUpgradeToDeneb: denebMono)
|
onUpgradeToDeneb: denebMono,
|
||||||
|
onUpgradeToElectra: electraMono)
|
||||||
of StdoutLogKind.Json, StdoutLogKind.None:
|
of StdoutLogKind.Json, StdoutLogKind.None:
|
||||||
VanityLogs(
|
VanityLogs(
|
||||||
onMergeTransitionBlock:
|
onMergeTransitionBlock:
|
||||||
|
@ -166,12 +168,14 @@ func getVanityLogs(stdoutKind: StdoutLogKind): VanityLogs =
|
||||||
onKnownBlsToExecutionChange:
|
onKnownBlsToExecutionChange:
|
||||||
(proc() = notice "🦉 BLS to execution changed 🦉"),
|
(proc() = notice "🦉 BLS to execution changed 🦉"),
|
||||||
onUpgradeToDeneb:
|
onUpgradeToDeneb:
|
||||||
(proc() = notice "🐟 Proto-Danksharding is ON 🐟"))
|
(proc() = notice "🐟 Proto-Danksharding is ON 🐟"),
|
||||||
|
onUpgradeToElectra:
|
||||||
|
(proc() = notice "🦒 [PH] Electra 🦒"))
|
||||||
|
|
||||||
func getVanityMascot(consensusFork: ConsensusFork): string =
|
func getVanityMascot(consensusFork: ConsensusFork): string =
|
||||||
case consensusFork
|
case consensusFork
|
||||||
of ConsensusFork.Electra:
|
of ConsensusFork.Electra:
|
||||||
" "
|
"🦒"
|
||||||
of ConsensusFork.Deneb:
|
of ConsensusFork.Deneb:
|
||||||
"🐟"
|
"🐟"
|
||||||
of ConsensusFork.Capella:
|
of ConsensusFork.Capella:
|
||||||
|
@ -1767,7 +1771,8 @@ proc installMessageValidators(node: BeaconNode) =
|
||||||
): Future[ValidationResult] {.async: (raises: [CancelledError]).} =
|
): Future[ValidationResult] {.async: (raises: [CancelledError]).} =
|
||||||
return toValidationResult(
|
return toValidationResult(
|
||||||
await node.processor.processAttestation(
|
await node.processor.processAttestation(
|
||||||
MsgSource.gossip, attestation, subnet_id)))
|
MsgSource.gossip, attestation, subnet_id,
|
||||||
|
checkSignature = true, checkValidator = false)))
|
||||||
else:
|
else:
|
||||||
for it in SubnetId:
|
for it in SubnetId:
|
||||||
closureScope: # Needed for inner `proc`; don't lift it out of loop.
|
closureScope: # Needed for inner `proc`; don't lift it out of loop.
|
||||||
|
@ -1778,7 +1783,8 @@ proc installMessageValidators(node: BeaconNode) =
|
||||||
): Future[ValidationResult] {.async: (raises: [CancelledError]).} =
|
): Future[ValidationResult] {.async: (raises: [CancelledError]).} =
|
||||||
return toValidationResult(
|
return toValidationResult(
|
||||||
await node.processor.processAttestation(
|
await node.processor.processAttestation(
|
||||||
MsgSource.gossip, attestation, subnet_id)))
|
MsgSource.gossip, attestation, subnet_id,
|
||||||
|
checkSignature = true, checkValidator = false)))
|
||||||
|
|
||||||
# beacon_aggregate_and_proof
|
# beacon_aggregate_and_proof
|
||||||
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/p2p-interface.md#beacon_aggregate_and_proof
|
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/p2p-interface.md#beacon_aggregate_and_proof
|
||||||
|
|
|
@ -123,7 +123,7 @@ programMain:
|
||||||
headBlockHash = payload.block_hash,
|
headBlockHash = payload.block_hash,
|
||||||
safeBlockHash = payload.block_hash, # stub value
|
safeBlockHash = payload.block_hash, # stub value
|
||||||
finalizedBlockHash = ZERO_HASH,
|
finalizedBlockHash = ZERO_HASH,
|
||||||
payloadAttributes = none(consensusFork.PayloadAttributes))
|
payloadAttributes = Opt.none(consensusFork.PayloadAttributes))
|
||||||
else: discard
|
else: discard
|
||||||
optimisticProcessor = initOptimisticProcessor(
|
optimisticProcessor = initOptimisticProcessor(
|
||||||
getBeaconTime, optimisticHandler)
|
getBeaconTime, optimisticHandler)
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
std/[typetraits, sequtils, sets],
|
std/[typetraits, sequtils, sets],
|
||||||
stew/[results, base10],
|
stew/base10,
|
||||||
chronicles, metrics,
|
chronicles, metrics,
|
||||||
./rest_utils,
|
./rest_utils,
|
||||||
./state_ttl_cache,
|
./state_ttl_cache,
|
||||||
|
@ -911,10 +911,12 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
when consensusFork >= ConsensusFork.Deneb:
|
when consensusFork >= ConsensusFork.Deneb:
|
||||||
await node.router.routeSignedBeaconBlock(
|
await node.router.routeSignedBeaconBlock(
|
||||||
forkyBlck, Opt.some(
|
forkyBlck, Opt.some(
|
||||||
forkyBlck.create_blob_sidecars(kzg_proofs, blobs)))
|
forkyBlck.create_blob_sidecars(kzg_proofs, blobs)),
|
||||||
|
checkValidator = true)
|
||||||
else:
|
else:
|
||||||
await node.router.routeSignedBeaconBlock(
|
await node.router.routeSignedBeaconBlock(
|
||||||
forkyBlck, Opt.none(seq[BlobSidecar]))
|
forkyBlck, Opt.none(seq[BlobSidecar]),
|
||||||
|
checkValidator = true)
|
||||||
|
|
||||||
if res.isErr():
|
if res.isErr():
|
||||||
return RestApiResponse.jsonError(
|
return RestApiResponse.jsonError(
|
||||||
|
@ -966,10 +968,12 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
when consensusFork >= ConsensusFork.Deneb:
|
when consensusFork >= ConsensusFork.Deneb:
|
||||||
await node.router.routeSignedBeaconBlock(
|
await node.router.routeSignedBeaconBlock(
|
||||||
forkyBlck, Opt.some(
|
forkyBlck, Opt.some(
|
||||||
forkyBlck.create_blob_sidecars(kzg_proofs, blobs)))
|
forkyBlck.create_blob_sidecars(kzg_proofs, blobs)),
|
||||||
|
checkValidator = true)
|
||||||
else:
|
else:
|
||||||
await node.router.routeSignedBeaconBlock(
|
await node.router.routeSignedBeaconBlock(
|
||||||
forkyBlck, Opt.none(seq[BlobSidecar]))
|
forkyBlck, Opt.none(seq[BlobSidecar]),
|
||||||
|
checkValidator = true)
|
||||||
|
|
||||||
if res.isErr():
|
if res.isErr():
|
||||||
return RestApiResponse.jsonError(
|
return RestApiResponse.jsonError(
|
||||||
|
@ -1087,7 +1091,8 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
let res = withBlck(forked):
|
let res = withBlck(forked):
|
||||||
forkyBlck.root = hash_tree_root(forkyBlck.message)
|
forkyBlck.root = hash_tree_root(forkyBlck.message)
|
||||||
await node.router.routeSignedBeaconBlock(
|
await node.router.routeSignedBeaconBlock(
|
||||||
forkyBlck, Opt.none(seq[BlobSidecar]))
|
forkyBlck, Opt.none(seq[BlobSidecar]),
|
||||||
|
checkValidator = true)
|
||||||
|
|
||||||
if res.isErr():
|
if res.isErr():
|
||||||
return RestApiResponse.jsonError(
|
return RestApiResponse.jsonError(
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
std/sequtils,
|
std/sequtils,
|
||||||
stew/results,
|
|
||||||
chronicles,
|
chronicles,
|
||||||
chronos/apps/http/httpserver,
|
chronos/apps/http/httpserver,
|
||||||
./rest_utils,
|
./rest_utils,
|
||||||
|
|
|
@ -5,9 +5,11 @@
|
||||||
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
|
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
|
||||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
|
{.push raises: [].}
|
||||||
|
|
||||||
import
|
import
|
||||||
std/[sequtils],
|
std/[sequtils],
|
||||||
stew/[results, base10],
|
stew/base10,
|
||||||
chronicles,
|
chronicles,
|
||||||
chronos/apps/http/httpdebug,
|
chronos/apps/http/httpdebug,
|
||||||
libp2p/[multiaddress, multicodec, peerstore],
|
libp2p/[multiaddress, multicodec, peerstore],
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
|
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
|
||||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
|
{.push raises: [].}
|
||||||
|
|
||||||
import
|
import
|
||||||
stew/[byteutils, results],
|
stew/byteutils,
|
||||||
chronicles,
|
chronicles,
|
||||||
eth/p2p/discoveryv5/enr,
|
eth/p2p/discoveryv5/enr,
|
||||||
libp2p/[multiaddress, multicodec, peerstore],
|
libp2p/[multiaddress, multicodec, peerstore],
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
{.push raises: [].}
|
{.push raises: [].}
|
||||||
|
|
||||||
import std/[typetraits, sets, sequtils]
|
import std/[typetraits, sets, sequtils]
|
||||||
import stew/[results, base10], chronicles
|
import stew/base10, chronicles
|
||||||
import ".."/[beacon_chain_db, beacon_node],
|
import ".."/[beacon_chain_db, beacon_node],
|
||||||
".."/networking/eth2_network,
|
".."/networking/eth2_network,
|
||||||
".."/consensus_object_pools/[blockchain_dag, spec_cache,
|
".."/consensus_object_pools/[blockchain_dag, spec_cache,
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
{.push raises: [].}
|
{.push raises: [].}
|
||||||
|
|
||||||
# Types specific to Deneb (i.e. known to have changed across hard forks) - see
|
# Types specific to Electra (i.e. known to have changed across hard forks) - see
|
||||||
# `base` for types and guidelines common across forks
|
# `base` for types and guidelines common across forks
|
||||||
|
|
||||||
# TODO Careful, not nil analysis is broken / incomplete and the semantics will
|
# TODO Careful, not nil analysis is broken / incomplete and the semantics will
|
||||||
|
|
|
@ -1173,6 +1173,16 @@ template withForkyMaybeBlindedBlck*(
|
||||||
template forkyMaybeBlindedBlck: untyped {.inject, used.} = b.phase0Data
|
template forkyMaybeBlindedBlck: untyped {.inject, used.} = b.phase0Data
|
||||||
body
|
body
|
||||||
|
|
||||||
|
template shortLog*(x: ForkedMaybeBlindedBeaconBlock): auto =
|
||||||
|
withForkyMaybeBlindedBlck(x):
|
||||||
|
when consensusFork >= ConsensusFork.Deneb:
|
||||||
|
when isBlinded == true:
|
||||||
|
shortLog(forkyMaybeBlindedBlck)
|
||||||
|
else:
|
||||||
|
shortLog(forkyMaybeBlindedBlck.`block`)
|
||||||
|
else:
|
||||||
|
shortLog(forkyMaybeBlindedBlck)
|
||||||
|
|
||||||
template withStateAndBlck*(
|
template withStateAndBlck*(
|
||||||
s: ForkedHashedBeaconState,
|
s: ForkedHashedBeaconState,
|
||||||
b: ForkedBeaconBlock | ForkedSignedBeaconBlock |
|
b: ForkedBeaconBlock | ForkedSignedBeaconBlock |
|
||||||
|
@ -1360,19 +1370,19 @@ func readSszForkedHashedBeaconState*(cfg: RuntimeConfig, data: openArray[byte]):
|
||||||
ForkedHashedBeaconState {.raises: [SerializationError].} =
|
ForkedHashedBeaconState {.raises: [SerializationError].} =
|
||||||
## Read a state picking the right fork by first reading the slot from the byte
|
## Read a state picking the right fork by first reading the slot from the byte
|
||||||
## source
|
## source
|
||||||
if data.len() < sizeof(BeaconStateHeader):
|
const numHeaderBytes = fixedPortionSize(BeaconStateHeader)
|
||||||
raise (ref MalformedSszError)(msg: "Not enough data for BeaconState header")
|
if data.len() < numHeaderBytes:
|
||||||
|
raise (ref MalformedSszError)(msg: "Incomplete BeaconState header")
|
||||||
let header = SSZ.decode(
|
let header = SSZ.decode(
|
||||||
data.toOpenArray(0, sizeof(BeaconStateHeader) - 1),
|
data.toOpenArray(0, numHeaderBytes - 1), BeaconStateHeader)
|
||||||
BeaconStateHeader)
|
|
||||||
|
|
||||||
# TODO https://github.com/nim-lang/Nim/issues/19357
|
# TODO https://github.com/nim-lang/Nim/issues/19357
|
||||||
result = readSszForkedHashedBeaconState(cfg, header.slot, data)
|
result = readSszForkedHashedBeaconState(cfg, header.slot, data)
|
||||||
|
|
||||||
type
|
type
|
||||||
ForkedBeaconBlockHeader = object
|
ForkedBeaconBlockHeader = object
|
||||||
message*: uint32 # message offset
|
message: uint32 # message offset
|
||||||
signature*: ValidatorSig
|
signature: ValidatorSig
|
||||||
slot: Slot # start of BeaconBlock
|
slot: Slot # start of BeaconBlock
|
||||||
|
|
||||||
func readSszForkedSignedBeaconBlock*(
|
func readSszForkedSignedBeaconBlock*(
|
||||||
|
@ -1380,11 +1390,11 @@ func readSszForkedSignedBeaconBlock*(
|
||||||
ForkedSignedBeaconBlock {.raises: [SerializationError].} =
|
ForkedSignedBeaconBlock {.raises: [SerializationError].} =
|
||||||
## Helper to read a header from bytes when it's not certain what kind of block
|
## Helper to read a header from bytes when it's not certain what kind of block
|
||||||
## it is
|
## it is
|
||||||
if data.len() < sizeof(ForkedBeaconBlockHeader):
|
const numHeaderBytes = fixedPortionSize(ForkedBeaconBlockHeader)
|
||||||
raise (ref MalformedSszError)(msg: "Not enough data for SignedBeaconBlock header")
|
if data.len() < numHeaderBytes:
|
||||||
|
raise (ref MalformedSszError)(msg: "Incomplete SignedBeaconBlock header")
|
||||||
let header = SSZ.decode(
|
let header = SSZ.decode(
|
||||||
data.toOpenArray(0, sizeof(ForkedBeaconBlockHeader) - 1),
|
data.toOpenArray(0, numHeaderBytes - 1), ForkedBeaconBlockHeader)
|
||||||
ForkedBeaconBlockHeader)
|
|
||||||
|
|
||||||
# TODO https://github.com/nim-lang/Nim/issues/19357
|
# TODO https://github.com/nim-lang/Nim/issues/19357
|
||||||
result = ForkedSignedBeaconBlock(
|
result = ForkedSignedBeaconBlock(
|
||||||
|
|
|
@ -484,24 +484,24 @@ proc blockToBlockHeader*(blck: ForkyBeaconBlock): ExecutionBlockHeader =
|
||||||
txRoot = payload.computeTransactionsTrieRoot()
|
txRoot = payload.computeTransactionsTrieRoot()
|
||||||
withdrawalsRoot =
|
withdrawalsRoot =
|
||||||
when typeof(payload).kind >= ConsensusFork.Capella:
|
when typeof(payload).kind >= ConsensusFork.Capella:
|
||||||
some payload.computeWithdrawalsTrieRoot()
|
Opt.some payload.computeWithdrawalsTrieRoot()
|
||||||
else:
|
else:
|
||||||
none(ExecutionHash256)
|
Opt.none(ExecutionHash256)
|
||||||
blobGasUsed =
|
blobGasUsed =
|
||||||
when typeof(payload).kind >= ConsensusFork.Deneb:
|
when typeof(payload).kind >= ConsensusFork.Deneb:
|
||||||
some payload.blob_gas_used
|
Opt.some payload.blob_gas_used
|
||||||
else:
|
else:
|
||||||
none(uint64)
|
Opt.none(uint64)
|
||||||
excessBlobGas =
|
excessBlobGas =
|
||||||
when typeof(payload).kind >= ConsensusFork.Deneb:
|
when typeof(payload).kind >= ConsensusFork.Deneb:
|
||||||
some payload.excess_blob_gas
|
Opt.some payload.excess_blob_gas
|
||||||
else:
|
else:
|
||||||
none(uint64)
|
Opt.none(uint64)
|
||||||
parentBeaconBlockRoot =
|
parentBeaconBlockRoot =
|
||||||
when typeof(payload).kind >= ConsensusFork.Deneb:
|
when typeof(payload).kind >= ConsensusFork.Deneb:
|
||||||
some ExecutionHash256(data: blck.parent_root.data)
|
Opt.some ExecutionHash256(data: blck.parent_root.data)
|
||||||
else:
|
else:
|
||||||
none(ExecutionHash256)
|
Opt.none(ExecutionHash256)
|
||||||
|
|
||||||
ExecutionBlockHeader(
|
ExecutionBlockHeader(
|
||||||
parentHash : payload.parent_hash,
|
parentHash : payload.parent_hash,
|
||||||
|
@ -509,17 +509,17 @@ proc blockToBlockHeader*(blck: ForkyBeaconBlock): ExecutionBlockHeader =
|
||||||
coinbase : EthAddress payload.fee_recipient.data,
|
coinbase : EthAddress payload.fee_recipient.data,
|
||||||
stateRoot : payload.state_root,
|
stateRoot : payload.state_root,
|
||||||
txRoot : txRoot,
|
txRoot : txRoot,
|
||||||
receiptRoot : payload.receipts_root,
|
receiptsRoot : payload.receipts_root,
|
||||||
bloom : payload.logs_bloom.data,
|
logsBloom : payload.logs_bloom.data,
|
||||||
difficulty : default(DifficultyInt),
|
difficulty : default(DifficultyInt),
|
||||||
blockNumber : payload.block_number.u256,
|
number : payload.block_number,
|
||||||
gasLimit : cast[GasInt](payload.gas_limit),
|
gasLimit : cast[GasInt](payload.gas_limit),
|
||||||
gasUsed : cast[GasInt](payload.gas_used),
|
gasUsed : cast[GasInt](payload.gas_used),
|
||||||
timestamp : EthTime(int64.saturate payload.timestamp),
|
timestamp : EthTime(int64.saturate payload.timestamp),
|
||||||
extraData : payload.extra_data.asSeq,
|
extraData : payload.extra_data.asSeq,
|
||||||
mixDigest : payload.prev_randao, # EIP-4399 `mixDigest` -> `prevRandao`
|
mixHash : payload.prev_randao, # EIP-4399 `mixHash` -> `prevRandao`
|
||||||
nonce : default(BlockNonce),
|
nonce : default(BlockNonce),
|
||||||
fee : some payload.base_fee_per_gas,
|
baseFeePerGas : Opt.some payload.base_fee_per_gas,
|
||||||
withdrawalsRoot : withdrawalsRoot,
|
withdrawalsRoot : withdrawalsRoot,
|
||||||
blobGasUsed : blobGasUsed, # EIP-4844
|
blobGasUsed : blobGasUsed, # EIP-4844
|
||||||
excessBlobGas : excessBlobGas, # EIP-4844
|
excessBlobGas : excessBlobGas, # EIP-4844
|
||||||
|
|
|
@ -421,3 +421,23 @@ proc verify_bls_to_execution_change_signature*(
|
||||||
let signing_root = compute_bls_to_execution_change_signing_root(
|
let signing_root = compute_bls_to_execution_change_signing_root(
|
||||||
genesisFork, genesis_validators_root, msg.message)
|
genesisFork, genesis_validators_root, msg.message)
|
||||||
blsVerify(pubkey, signing_root.data, signature)
|
blsVerify(pubkey, signing_root.data, signature)
|
||||||
|
|
||||||
|
func compute_consolidation_signing_root(
|
||||||
|
genesisFork: Fork, genesis_validators_root: Eth2Digest,
|
||||||
|
msg: Consolidation): Eth2Digest =
|
||||||
|
# Uses genesis fork version regardless
|
||||||
|
doAssert genesisFork.current_version == genesisFork.previous_version
|
||||||
|
|
||||||
|
let domain = compute_domain(
|
||||||
|
DOMAIN_CONSOLIDATION, genesisFork.current_version,
|
||||||
|
genesis_validators_root=genesis_validators_root)
|
||||||
|
compute_signing_root(msg, domain)
|
||||||
|
|
||||||
|
proc verify_consolidation_signature*(
|
||||||
|
genesisFork: Fork, genesis_validators_root: Eth2Digest,
|
||||||
|
msg: SignedConsolidation | TrustedSignedConsolidation,
|
||||||
|
pubkeys: openArray[ValidatorPubKey]): bool =
|
||||||
|
withTrust(msg.signature):
|
||||||
|
let signing_root = compute_consolidation_signing_root(
|
||||||
|
genesisFork, genesis_validators_root, msg.message)
|
||||||
|
blsFastAggregateVerify(pubkeys, signing_root.data, msg.signature)
|
||||||
|
|
|
@ -361,7 +361,8 @@ func partialBeaconBlock*(
|
||||||
deposits: seq[Deposit],
|
deposits: seq[Deposit],
|
||||||
validator_changes: BeaconBlockValidatorChanges,
|
validator_changes: BeaconBlockValidatorChanges,
|
||||||
sync_aggregate: SyncAggregate,
|
sync_aggregate: SyncAggregate,
|
||||||
execution_payload: ForkyExecutionPayloadForSigning
|
execution_payload: ForkyExecutionPayloadForSigning,
|
||||||
|
consolidations: openArray[SignedConsolidation]
|
||||||
): auto =
|
): auto =
|
||||||
const consensusFork = typeof(state).kind
|
const consensusFork = typeof(state).kind
|
||||||
|
|
||||||
|
@ -411,12 +412,14 @@ func partialBeaconBlock*(
|
||||||
deposits: seq[Deposit],
|
deposits: seq[Deposit],
|
||||||
validator_changes: BeaconBlockValidatorChanges,
|
validator_changes: BeaconBlockValidatorChanges,
|
||||||
sync_aggregate: SyncAggregate,
|
sync_aggregate: SyncAggregate,
|
||||||
execution_payload: ForkyExecutionPayloadForSigning
|
execution_payload: ForkyExecutionPayloadForSigning,
|
||||||
|
consolidations: seq[SignedConsolidation],
|
||||||
): auto =
|
): auto =
|
||||||
const consensusFork = typeof(state).kind
|
const consensusFork = typeof(state).kind
|
||||||
|
|
||||||
|
debugComment "re-enable attester slashing packing in electra"
|
||||||
# https://github.com/ethereum/consensus-specs/blob/v1.3.0/specs/phase0/validator.md#preparing-for-a-beaconblock
|
# https://github.com/ethereum/consensus-specs/blob/v1.3.0/specs/phase0/validator.md#preparing-for-a-beaconblock
|
||||||
var res = consensusFork.BeaconBlock(
|
consensusFork.BeaconBlock(
|
||||||
slot: state.data.slot,
|
slot: state.data.slot,
|
||||||
proposer_index: proposer_index.uint64,
|
proposer_index: proposer_index.uint64,
|
||||||
parent_root: state.latest_block_root,
|
parent_root: state.latest_block_root,
|
||||||
|
@ -429,28 +432,14 @@ func partialBeaconBlock*(
|
||||||
attestations:
|
attestations:
|
||||||
List[electra.Attestation, Limit MAX_ATTESTATIONS_ELECTRA](attestations),
|
List[electra.Attestation, Limit MAX_ATTESTATIONS_ELECTRA](attestations),
|
||||||
deposits: List[Deposit, Limit MAX_DEPOSITS](deposits),
|
deposits: List[Deposit, Limit MAX_DEPOSITS](deposits),
|
||||||
voluntary_exits: validator_changes.voluntary_exits))
|
voluntary_exits: validator_changes.voluntary_exits,
|
||||||
|
sync_aggregate: sync_aggregate,
|
||||||
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/altair/validator.md#preparing-a-beaconblock
|
execution_payload: execution_payload.executionPayload,
|
||||||
when consensusFork >= ConsensusFork.Altair:
|
bls_to_execution_changes: validator_changes.bls_to_execution_changes,
|
||||||
res.body.sync_aggregate = sync_aggregate
|
blob_kzg_commitments: execution_payload.blobsBundle.commitments,
|
||||||
|
consolidations:
|
||||||
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.2/specs/bellatrix/validator.md#block-proposal
|
List[SignedConsolidation, Limit MAX_CONSOLIDATIONS].init(
|
||||||
when consensusFork >= ConsensusFork.Bellatrix:
|
consolidations)))
|
||||||
res.body.execution_payload = execution_payload.executionPayload
|
|
||||||
|
|
||||||
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/capella/validator.md#block-proposal
|
|
||||||
when consensusFork >= ConsensusFork.Capella:
|
|
||||||
res.body.bls_to_execution_changes =
|
|
||||||
validator_changes.bls_to_execution_changes
|
|
||||||
|
|
||||||
# https://github.com/ethereum/consensus-specs/blob/v1.3.0/specs/deneb/validator.md#constructing-the-beaconblockbody
|
|
||||||
when consensusFork >= ConsensusFork.Deneb:
|
|
||||||
res.body.blob_kzg_commitments = execution_payload.blobsBundle.commitments
|
|
||||||
|
|
||||||
debugComment "either consolidate this within separate function or recombine, re when consensusFork >= foo and atts/attslashings; here to allow noninterference with pre-pectra"
|
|
||||||
|
|
||||||
res
|
|
||||||
|
|
||||||
proc makeBeaconBlockWithRewards*(
|
proc makeBeaconBlockWithRewards*(
|
||||||
cfg: RuntimeConfig,
|
cfg: RuntimeConfig,
|
||||||
|
@ -464,6 +453,7 @@ proc makeBeaconBlockWithRewards*(
|
||||||
validator_changes: BeaconBlockValidatorChanges,
|
validator_changes: BeaconBlockValidatorChanges,
|
||||||
sync_aggregate: SyncAggregate,
|
sync_aggregate: SyncAggregate,
|
||||||
executionPayload: ForkyExecutionPayloadForSigning,
|
executionPayload: ForkyExecutionPayloadForSigning,
|
||||||
|
consolidations: seq[SignedConsolidation],
|
||||||
rollback: RollbackForkedHashedProc,
|
rollback: RollbackForkedHashedProc,
|
||||||
cache: var StateCache,
|
cache: var StateCache,
|
||||||
# TODO:
|
# TODO:
|
||||||
|
@ -490,7 +480,7 @@ proc makeBeaconBlockWithRewards*(
|
||||||
partialBeaconBlock(
|
partialBeaconBlock(
|
||||||
cfg, state.`kind Data`, proposer_index, randao_reveal, eth1_data,
|
cfg, state.`kind Data`, proposer_index, randao_reveal, eth1_data,
|
||||||
graffiti, attestations, deposits, validator_changes, sync_aggregate,
|
graffiti, attestations, deposits, validator_changes, sync_aggregate,
|
||||||
executionPayload))
|
executionPayload, consolidations))
|
||||||
|
|
||||||
let res = process_block(
|
let res = process_block(
|
||||||
cfg, state.`kind Data`.data, blck.`kind Data`.asSigVerified(),
|
cfg, state.`kind Data`.data, blck.`kind Data`.asSigVerified(),
|
||||||
|
@ -533,9 +523,8 @@ proc makeBeaconBlockWithRewards*(
|
||||||
forkyState.data.latest_execution_payload_header.transactions_root =
|
forkyState.data.latest_execution_payload_header.transactions_root =
|
||||||
transactions_root.get
|
transactions_root.get
|
||||||
|
|
||||||
debugComment "makeBeaconBlock doesn't support Electra (i.e. check for missing beaconblock body fields)"
|
|
||||||
when executionPayload is electra.ExecutionPayloadForSigning:
|
when executionPayload is electra.ExecutionPayloadForSigning:
|
||||||
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/deneb/beacon-chain.md#beaconblockbody
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.2/specs/electra/beacon-chain.md#beaconblockbody
|
||||||
forkyState.data.latest_block_header.body_root = hash_tree_root(
|
forkyState.data.latest_block_header.body_root = hash_tree_root(
|
||||||
[hash_tree_root(randao_reveal),
|
[hash_tree_root(randao_reveal),
|
||||||
hash_tree_root(eth1_data),
|
hash_tree_root(eth1_data),
|
||||||
|
@ -550,7 +539,9 @@ proc makeBeaconBlockWithRewards*(
|
||||||
hash_tree_root(sync_aggregate),
|
hash_tree_root(sync_aggregate),
|
||||||
execution_payload_root.get,
|
execution_payload_root.get,
|
||||||
hash_tree_root(validator_changes.bls_to_execution_changes),
|
hash_tree_root(validator_changes.bls_to_execution_changes),
|
||||||
hash_tree_root(kzg_commitments.get)
|
hash_tree_root(kzg_commitments.get),
|
||||||
|
hash_tree_root(List[SignedConsolidation, Limit MAX_CONSOLIDATIONS].init(
|
||||||
|
consolidations))
|
||||||
])
|
])
|
||||||
else:
|
else:
|
||||||
raiseAssert "Attempt to use non-Electra payload with post-Deneb state"
|
raiseAssert "Attempt to use non-Electra payload with post-Deneb state"
|
||||||
|
@ -593,6 +584,7 @@ proc makeBeaconBlock*(
|
||||||
validator_changes: BeaconBlockValidatorChanges,
|
validator_changes: BeaconBlockValidatorChanges,
|
||||||
sync_aggregate: SyncAggregate,
|
sync_aggregate: SyncAggregate,
|
||||||
executionPayload: ForkyExecutionPayloadForSigning,
|
executionPayload: ForkyExecutionPayloadForSigning,
|
||||||
|
consolidations: seq[SignedConsolidation],
|
||||||
rollback: RollbackForkedHashedProc, cache: var StateCache,
|
rollback: RollbackForkedHashedProc, cache: var StateCache,
|
||||||
verificationFlags: UpdateFlags,
|
verificationFlags: UpdateFlags,
|
||||||
transactions_root: Opt[Eth2Digest],
|
transactions_root: Opt[Eth2Digest],
|
||||||
|
@ -603,8 +595,8 @@ proc makeBeaconBlock*(
|
||||||
? makeBeaconBlockWithRewards(
|
? makeBeaconBlockWithRewards(
|
||||||
cfg, state, proposer_index, randao_reveal, eth1_data, graffiti,
|
cfg, state, proposer_index, randao_reveal, eth1_data, graffiti,
|
||||||
attestations, deposits, validator_changes, sync_aggregate,
|
attestations, deposits, validator_changes, sync_aggregate,
|
||||||
executionPayload, rollback, cache, verificationFlags, transactions_root,
|
executionPayload, consolidations, rollback, cache, verificationFlags,
|
||||||
execution_payload_root, kzg_commitments)
|
transactions_root, execution_payload_root, kzg_commitments)
|
||||||
ok(blockAndRewards.blck)
|
ok(blockAndRewards.blck)
|
||||||
|
|
||||||
proc makeBeaconBlock*(
|
proc makeBeaconBlock*(
|
||||||
|
@ -616,12 +608,13 @@ proc makeBeaconBlock*(
|
||||||
validator_changes: BeaconBlockValidatorChanges,
|
validator_changes: BeaconBlockValidatorChanges,
|
||||||
sync_aggregate: SyncAggregate,
|
sync_aggregate: SyncAggregate,
|
||||||
executionPayload: ForkyExecutionPayloadForSigning,
|
executionPayload: ForkyExecutionPayloadForSigning,
|
||||||
|
consolidations: seq[SignedConsolidation],
|
||||||
rollback: RollbackForkedHashedProc, cache: var StateCache):
|
rollback: RollbackForkedHashedProc, cache: var StateCache):
|
||||||
Result[ForkedBeaconBlock, cstring] =
|
Result[ForkedBeaconBlock, cstring] =
|
||||||
makeBeaconBlock(
|
makeBeaconBlock(
|
||||||
cfg, state, proposer_index, randao_reveal, eth1_data, graffiti,
|
cfg, state, proposer_index, randao_reveal, eth1_data, graffiti,
|
||||||
attestations, deposits, validator_changes, sync_aggregate,
|
attestations, deposits, validator_changes, sync_aggregate,
|
||||||
executionPayload, rollback, cache,
|
executionPayload, consolidations, rollback, cache,
|
||||||
verificationFlags = {}, transactions_root = Opt.none Eth2Digest,
|
verificationFlags = {}, transactions_root = Opt.none Eth2Digest,
|
||||||
execution_payload_root = Opt.none Eth2Digest,
|
execution_payload_root = Opt.none Eth2Digest,
|
||||||
kzg_commitments = Opt.none KzgCommitments)
|
kzg_commitments = Opt.none KzgCommitments)
|
||||||
|
@ -635,13 +628,14 @@ proc makeBeaconBlock*(
|
||||||
validator_changes: BeaconBlockValidatorChanges,
|
validator_changes: BeaconBlockValidatorChanges,
|
||||||
sync_aggregate: SyncAggregate,
|
sync_aggregate: SyncAggregate,
|
||||||
executionPayload: ForkyExecutionPayloadForSigning,
|
executionPayload: ForkyExecutionPayloadForSigning,
|
||||||
|
consolidations: seq[SignedConsolidation],
|
||||||
rollback: RollbackForkedHashedProc,
|
rollback: RollbackForkedHashedProc,
|
||||||
cache: var StateCache, verificationFlags: UpdateFlags):
|
cache: var StateCache, verificationFlags: UpdateFlags):
|
||||||
Result[ForkedBeaconBlock, cstring] =
|
Result[ForkedBeaconBlock, cstring] =
|
||||||
makeBeaconBlock(
|
makeBeaconBlock(
|
||||||
cfg, state, proposer_index, randao_reveal, eth1_data, graffiti,
|
cfg, state, proposer_index, randao_reveal, eth1_data, graffiti,
|
||||||
attestations, deposits, validator_changes, sync_aggregate,
|
attestations, deposits, validator_changes, sync_aggregate,
|
||||||
executionPayload, rollback, cache,
|
executionPayload, consolidations, rollback, cache,
|
||||||
verificationFlags = verificationFlags,
|
verificationFlags = verificationFlags,
|
||||||
transactions_root = Opt.none Eth2Digest,
|
transactions_root = Opt.none Eth2Digest,
|
||||||
execution_payload_root = Opt.none Eth2Digest,
|
execution_payload_root = Opt.none Eth2Digest,
|
||||||
|
|
|
@ -644,20 +644,11 @@ proc process_consolidation*(
|
||||||
target_validator.withdrawal_credentials.data.toOpenArray(12, 31)):
|
target_validator.withdrawal_credentials.data.toOpenArray(12, 31)):
|
||||||
return err("Consolidation: source and target don't have same withdrawal address")
|
return err("Consolidation: source and target don't have same withdrawal address")
|
||||||
|
|
||||||
debugComment "this is per spec, near-verbatim, but Nimbus generally factors this out into spec/signatures.nim. so, create verify_consolidation_signature infra there, call here"
|
|
||||||
# Verify consolidation is signed by the source and the target
|
# Verify consolidation is signed by the source and the target
|
||||||
let
|
if not verify_consolidation_signature(
|
||||||
domain = compute_domain(
|
cfg.genesisFork, state.genesis_validators_root, signed_consolidation,
|
||||||
DOMAIN_CONSOLIDATION, cfg.GENESIS_FORK_VERSION,
|
[source_validator[].pubkey, target_validator.pubkey]):
|
||||||
genesis_validators_root=state.genesis_validators_root)
|
return err("Consolidation: invalid signature")
|
||||||
signing_root = compute_signing_root(consolidation, domain)
|
|
||||||
pubkeys = [source_validator[].pubkey, target_validator.pubkey]
|
|
||||||
|
|
||||||
debugComment "as a good example, this trustedsig hack typically/should live in spec/signatures.nim"
|
|
||||||
when not (signed_consolidation.signature is TrustedSig):
|
|
||||||
if not blsFastAggregateVerify(
|
|
||||||
pubkeys, signing_root.data, signed_consolidation.signature):
|
|
||||||
return err("Consolidation: invalid signature")
|
|
||||||
|
|
||||||
# Initiate source validator exit and append pending consolidation
|
# Initiate source validator exit and append pending consolidation
|
||||||
source_validator[].exit_epoch = compute_consolidation_epoch_and_update_churn(
|
source_validator[].exit_epoch = compute_consolidation_epoch_and_update_churn(
|
||||||
|
@ -667,8 +658,7 @@ proc process_consolidation*(
|
||||||
debugComment "check HashList add return value"
|
debugComment "check HashList add return value"
|
||||||
discard state.pending_consolidations.add(PendingConsolidation(
|
discard state.pending_consolidations.add(PendingConsolidation(
|
||||||
source_index: consolidation.source_index,
|
source_index: consolidation.source_index,
|
||||||
target_index: consolidation.target_index
|
target_index: consolidation.target_index))
|
||||||
))
|
|
||||||
|
|
||||||
ok()
|
ok()
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
{.push raises: [].}
|
{.push raises: [].}
|
||||||
|
|
||||||
import std/[strutils, sequtils, algorithm]
|
import std/[strutils, sequtils, algorithm]
|
||||||
import stew/[results, base10], chronos, chronicles
|
import stew/base10, chronos, chronicles
|
||||||
import
|
import
|
||||||
../spec/datatypes/[phase0, altair],
|
../spec/datatypes/[phase0, altair],
|
||||||
../spec/eth2_apis/rest_types,
|
../spec/eth2_apis/rest_types,
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
{.push raises: [].}
|
{.push raises: [].}
|
||||||
|
|
||||||
import std/[heapqueue, tables, strutils, sequtils, math]
|
import std/[heapqueue, tables, strutils, sequtils, math]
|
||||||
import stew/[results, base10], chronos, chronicles
|
import stew/base10, chronos, chronicles
|
||||||
import
|
import
|
||||||
../spec/datatypes/[base, phase0, altair],
|
../spec/datatypes/[base, phase0, altair],
|
||||||
../spec/[helpers, forks],
|
../spec/[helpers, forks],
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
{.push raises: [].}
|
{.push raises: [].}
|
||||||
|
|
||||||
import
|
import
|
||||||
stew/[base10, results],
|
stew/base10,
|
||||||
chronicles, chronos, eth/async_utils,
|
chronicles, chronos, eth/async_utils,
|
||||||
./sync/[light_client_sync_helpers, sync_manager],
|
./sync/[light_client_sync_helpers, sync_manager],
|
||||||
./consensus_object_pools/[block_clearance, blockchain_dag],
|
./consensus_object_pools/[block_clearance, blockchain_dag],
|
||||||
|
|
|
@ -39,14 +39,14 @@ type
|
||||||
status*: ApiOperation
|
status*: ApiOperation
|
||||||
data*: seq[ApiNodeResponse[T]]
|
data*: seq[ApiNodeResponse[T]]
|
||||||
|
|
||||||
ApiScore* = object
|
ApiScore*[T] = object
|
||||||
index*: int
|
index*: int
|
||||||
score*: Opt[float64]
|
score*: Opt[T]
|
||||||
|
|
||||||
BestNodeResponse*[T] = object
|
BestNodeResponse*[T, X] = object
|
||||||
node*: BeaconNodeServerRef
|
node*: BeaconNodeServerRef
|
||||||
data*: ApiResponse[T]
|
data*: ApiResponse[T]
|
||||||
score*: float64
|
score*: X
|
||||||
|
|
||||||
const
|
const
|
||||||
ViableNodeStatus* = {
|
ViableNodeStatus* = {
|
||||||
|
@ -56,7 +56,7 @@ const
|
||||||
RestBeaconNodeStatus.Synced
|
RestBeaconNodeStatus.Synced
|
||||||
}
|
}
|
||||||
|
|
||||||
proc `$`*(s: ApiScore): string =
|
proc `$`*[T](s: ApiScore[T]): string =
|
||||||
var res = Base10.toString(uint64(s.index))
|
var res = Base10.toString(uint64(s.index))
|
||||||
res.add(": ")
|
res.add(": ")
|
||||||
if s.score.isSome():
|
if s.score.isSome():
|
||||||
|
@ -65,22 +65,27 @@ proc `$`*(s: ApiScore): string =
|
||||||
res.add("<n/a>")
|
res.add("<n/a>")
|
||||||
res
|
res
|
||||||
|
|
||||||
proc `$`*(ss: openArray[ApiScore]): string =
|
proc `$`*[T](ss: openArray[ApiScore[T]]): string =
|
||||||
"[" & ss.mapIt($it).join(",") & "]"
|
"[" & ss.mapIt($it).join(",") & "]"
|
||||||
|
|
||||||
chronicles.formatIt(seq[ApiScore]):
|
chronicles.formatIt(seq[ApiScore]):
|
||||||
$it
|
$it
|
||||||
|
|
||||||
func init*(t: typedesc[ApiScore], node: BeaconNodeServerRef,
|
func init*(t: typedesc[ApiScore], node: BeaconNodeServerRef,
|
||||||
score: float64): ApiScore =
|
score: float64): ApiScore[float64] =
|
||||||
ApiScore(index: node.index, score: Opt.some(score))
|
ApiScore[float64](index: node.index, score: Opt.some(score))
|
||||||
|
|
||||||
func init*(t: typedesc[ApiScore], node: BeaconNodeServerRef): ApiScore =
|
func init*(t: typedesc[ApiScore], node: BeaconNodeServerRef,
|
||||||
ApiScore(index: node.index, score: Opt.none(float64))
|
score: UInt256): ApiScore[UInt256] =
|
||||||
|
ApiScore[UInt256](index: node.index, score: Opt.some(score))
|
||||||
|
|
||||||
func init*[T](t: typedesc[BestNodeResponse], node: BeaconNodeServerRef,
|
func init*(tt: typedesc[ApiScore],
|
||||||
data: ApiResponse[T], score: float64): BestNodeResponse[T] =
|
node: BeaconNodeServerRef, T: typedesc): ApiScore[T] =
|
||||||
BestNodeResponse[T](node: node, data: data, score: score)
|
ApiScore[T](index: node.index, score: Opt.none(T))
|
||||||
|
|
||||||
|
func init*[T, X](t: typedesc[BestNodeResponse], node: BeaconNodeServerRef,
|
||||||
|
data: ApiResponse[T], score: X): BestNodeResponse[T, X] =
|
||||||
|
BestNodeResponse[T, X](node: node, data: data, score: score)
|
||||||
|
|
||||||
proc lazyWaiter(node: BeaconNodeServerRef, request: FutureBase,
|
proc lazyWaiter(node: BeaconNodeServerRef, request: FutureBase,
|
||||||
requestName: string, strategy: ApiStrategyKind) {.async.} =
|
requestName: string, strategy: ApiStrategyKind) {.async.} =
|
||||||
|
@ -234,7 +239,7 @@ template firstSuccessParallel*(
|
||||||
pendingNodes.del(index)
|
pendingNodes.del(index)
|
||||||
|
|
||||||
let
|
let
|
||||||
node {.inject.} = beaconNode
|
node {.inject, used.} = beaconNode
|
||||||
apiResponse {.inject.} =
|
apiResponse {.inject.} =
|
||||||
apiResponseOr[responseType](requestFut, timerFut,
|
apiResponseOr[responseType](requestFut, timerFut,
|
||||||
"Timeout exceeded while awaiting for the response")
|
"Timeout exceeded while awaiting for the response")
|
||||||
|
@ -283,6 +288,7 @@ template bestSuccess*(
|
||||||
vc: ValidatorClientRef,
|
vc: ValidatorClientRef,
|
||||||
responseType: typedesc,
|
responseType: typedesc,
|
||||||
handlerType: typedesc,
|
handlerType: typedesc,
|
||||||
|
scoreType: typedesc,
|
||||||
timeout: Duration,
|
timeout: Duration,
|
||||||
statuses: set[RestBeaconNodeStatus],
|
statuses: set[RestBeaconNodeStatus],
|
||||||
roles: set[BeaconNodeRole],
|
roles: set[BeaconNodeRole],
|
||||||
|
@ -301,8 +307,8 @@ template bestSuccess*(
|
||||||
|
|
||||||
var
|
var
|
||||||
retRes: ApiResponse[handlerType]
|
retRes: ApiResponse[handlerType]
|
||||||
scores: seq[ApiScore]
|
scores: seq[ApiScore[scoreType]]
|
||||||
bestResponse: Opt[BestNodeResponse[handlerType]]
|
bestResponse: Opt[BestNodeResponse[handlerType, scoreType]]
|
||||||
|
|
||||||
block mainLoop:
|
block mainLoop:
|
||||||
while true:
|
while true:
|
||||||
|
@ -395,7 +401,7 @@ template bestSuccess*(
|
||||||
perfectScoreFound = true
|
perfectScoreFound = true
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
scores.add(ApiScore.init(node))
|
scores.add(ApiScore.init(node, scoreType))
|
||||||
|
|
||||||
if perfectScoreFound:
|
if perfectScoreFound:
|
||||||
# lazyWait will cancel `pendingRequests` on timeout.
|
# lazyWait will cancel `pendingRequests` on timeout.
|
||||||
|
@ -714,16 +720,30 @@ template firstSuccessSequential*(
|
||||||
break
|
break
|
||||||
|
|
||||||
proc getErrorMessage*(response: RestPlainResponse): string =
|
proc getErrorMessage*(response: RestPlainResponse): string =
|
||||||
let res = decodeBytes(RestErrorMessage, response.data,
|
let res =
|
||||||
response.contentType)
|
decodeBytes(RestErrorMessage, response.data, response.contentType).valueOr:
|
||||||
if res.isOk():
|
return "Unable to decode error response: [" & $error & "]"
|
||||||
let errorObj = res.get()
|
|
||||||
if errorObj.stacktraces.isSome():
|
if res.stacktraces.isSome():
|
||||||
errorObj.message & ": [" & errorObj.stacktraces.get().join("; ") & "]"
|
res.message & ": [" & res.stacktraces.get().join("; ") & "]"
|
||||||
else:
|
|
||||||
errorObj.message
|
|
||||||
else:
|
else:
|
||||||
"Unable to decode error response: [" & $res.error & "]"
|
res.message
|
||||||
|
|
||||||
|
proc unpackErrorMessage*(response: RestPlainResponse): RestIndexedErrorMessage =
|
||||||
|
decodeBytes(RestIndexedErrorMessage, response.data,
|
||||||
|
response.contentType).valueOr:
|
||||||
|
let message = "Unable to decode error response: [" & $error & "]"
|
||||||
|
return RestIndexedErrorMessage(
|
||||||
|
code: -1,
|
||||||
|
message: message,
|
||||||
|
failures: default(seq[RestIndexedErrorMessageItem]))
|
||||||
|
|
||||||
|
proc getErrorMessage*(msg: RestIndexedErrorMessage): string =
|
||||||
|
if len(msg.failures) > 0:
|
||||||
|
msg.message & ": [" &
|
||||||
|
msg.failures.mapIt($it.index & ":" & it.message).join("; ") & "]"
|
||||||
|
else:
|
||||||
|
msg.message
|
||||||
|
|
||||||
template handleCommunicationError(): untyped {.dirty.} =
|
template handleCommunicationError(): untyped {.dirty.} =
|
||||||
let failure = ApiNodeFailure.init(ApiFailure.Communication, RequestName,
|
let failure = ApiNodeFailure.init(ApiFailure.Communication, RequestName,
|
||||||
|
@ -755,6 +775,13 @@ template handle400(): untyped {.dirty.} =
|
||||||
node.updateStatus(RestBeaconNodeStatus.Incompatible, failure)
|
node.updateStatus(RestBeaconNodeStatus.Incompatible, failure)
|
||||||
failures.add(failure)
|
failures.add(failure)
|
||||||
|
|
||||||
|
template handle400Indexed(): untyped {.dirty.} =
|
||||||
|
let failure = ApiNodeFailure.init(ApiFailure.Invalid, RequestName,
|
||||||
|
strategy, node, response.status,
|
||||||
|
response.unpackErrorMessage().getErrorMessage())
|
||||||
|
node.updateStatus(RestBeaconNodeStatus.Incompatible, failure)
|
||||||
|
failures.add(failure)
|
||||||
|
|
||||||
template handle404(): untyped {.dirty.} =
|
template handle404(): untyped {.dirty.} =
|
||||||
let failure = ApiNodeFailure.init(ApiFailure.NotFound, RequestName,
|
let failure = ApiNodeFailure.init(ApiFailure.NotFound, RequestName,
|
||||||
strategy, node, response.status, response.getErrorMessage())
|
strategy, node, response.status, response.getErrorMessage())
|
||||||
|
@ -1181,6 +1208,7 @@ proc getHeadBlockRoot*(
|
||||||
let res = vc.bestSuccess(
|
let res = vc.bestSuccess(
|
||||||
RestPlainResponse,
|
RestPlainResponse,
|
||||||
GetBlockRootResponse,
|
GetBlockRootResponse,
|
||||||
|
float64,
|
||||||
SlotDuration,
|
SlotDuration,
|
||||||
ViableNodeStatus,
|
ViableNodeStatus,
|
||||||
{BeaconNodeRole.SyncCommitteeData},
|
{BeaconNodeRole.SyncCommitteeData},
|
||||||
|
@ -1413,6 +1441,7 @@ proc produceAttestationData*(
|
||||||
let res = vc.bestSuccess(
|
let res = vc.bestSuccess(
|
||||||
RestPlainResponse,
|
RestPlainResponse,
|
||||||
ProduceAttestationDataResponse,
|
ProduceAttestationDataResponse,
|
||||||
|
float64,
|
||||||
OneThirdDuration,
|
OneThirdDuration,
|
||||||
ViableNodeStatus,
|
ViableNodeStatus,
|
||||||
{BeaconNodeRole.AttestationData},
|
{BeaconNodeRole.AttestationData},
|
||||||
|
@ -1514,7 +1543,7 @@ proc submitPoolAttestations*(
|
||||||
of 200:
|
of 200:
|
||||||
ApiResponse[bool].ok(true)
|
ApiResponse[bool].ok(true)
|
||||||
of 400:
|
of 400:
|
||||||
handle400()
|
handle400Indexed()
|
||||||
ApiResponse[bool].err(ResponseInvalidError)
|
ApiResponse[bool].err(ResponseInvalidError)
|
||||||
of 500:
|
of 500:
|
||||||
handle500()
|
handle500()
|
||||||
|
@ -1542,7 +1571,7 @@ proc submitPoolAttestations*(
|
||||||
of 200:
|
of 200:
|
||||||
return true
|
return true
|
||||||
of 400:
|
of 400:
|
||||||
handle400()
|
handle400Indexed()
|
||||||
false
|
false
|
||||||
of 500:
|
of 500:
|
||||||
handle500()
|
handle500()
|
||||||
|
@ -1589,7 +1618,7 @@ proc submitPoolSyncCommitteeSignature*(
|
||||||
of 200:
|
of 200:
|
||||||
ApiResponse[bool].ok(true)
|
ApiResponse[bool].ok(true)
|
||||||
of 400:
|
of 400:
|
||||||
handle400()
|
handle400Indexed()
|
||||||
ApiResponse[bool].err(ResponseInvalidError)
|
ApiResponse[bool].err(ResponseInvalidError)
|
||||||
of 500:
|
of 500:
|
||||||
handle500()
|
handle500()
|
||||||
|
@ -1618,7 +1647,7 @@ proc submitPoolSyncCommitteeSignature*(
|
||||||
of 200:
|
of 200:
|
||||||
return true
|
return true
|
||||||
of 400:
|
of 400:
|
||||||
handle400()
|
handle400Indexed()
|
||||||
false
|
false
|
||||||
of 500:
|
of 500:
|
||||||
handle500()
|
handle500()
|
||||||
|
@ -1685,6 +1714,7 @@ proc getAggregatedAttestation*(
|
||||||
let res = vc.bestSuccess(
|
let res = vc.bestSuccess(
|
||||||
RestPlainResponse,
|
RestPlainResponse,
|
||||||
GetAggregatedAttestationResponse,
|
GetAggregatedAttestationResponse,
|
||||||
|
float64,
|
||||||
OneThirdDuration,
|
OneThirdDuration,
|
||||||
ViableNodeStatus,
|
ViableNodeStatus,
|
||||||
{BeaconNodeRole.AggregatedData},
|
{BeaconNodeRole.AggregatedData},
|
||||||
|
@ -1818,6 +1848,7 @@ proc produceSyncCommitteeContribution*(
|
||||||
let res = vc.bestSuccess(
|
let res = vc.bestSuccess(
|
||||||
RestPlainResponse,
|
RestPlainResponse,
|
||||||
ProduceSyncCommitteeContributionResponse,
|
ProduceSyncCommitteeContributionResponse,
|
||||||
|
float64,
|
||||||
OneThirdDuration,
|
OneThirdDuration,
|
||||||
ViableNodeStatus,
|
ViableNodeStatus,
|
||||||
{BeaconNodeRole.SyncCommitteeData},
|
{BeaconNodeRole.SyncCommitteeData},
|
||||||
|
@ -2036,7 +2067,59 @@ proc produceBlockV3*(
|
||||||
var failures: seq[ApiNodeFailure]
|
var failures: seq[ApiNodeFailure]
|
||||||
|
|
||||||
case strategy
|
case strategy
|
||||||
of ApiStrategyKind.First, ApiStrategyKind.Best:
|
of ApiStrategyKind.Best:
|
||||||
|
let res = vc.bestSuccess(
|
||||||
|
RestPlainResponse,
|
||||||
|
ProduceBlockResponseV3,
|
||||||
|
UInt256,
|
||||||
|
SlotDuration,
|
||||||
|
ViableNodeStatus,
|
||||||
|
{BeaconNodeRole.BlockProposalData},
|
||||||
|
produceBlockV3Plain(it, slot, randao_reveal, graffiti,
|
||||||
|
builder_boost_factor),
|
||||||
|
getProduceBlockResponseV3Score(itresponse)):
|
||||||
|
if apiResponse.isErr():
|
||||||
|
handleCommunicationError()
|
||||||
|
ApiResponse[ProduceBlockResponseV3].err(apiResponse.error)
|
||||||
|
else:
|
||||||
|
let response = apiResponse.get()
|
||||||
|
case response.status
|
||||||
|
of 200:
|
||||||
|
let
|
||||||
|
version = response.headers.getString("eth-consensus-version")
|
||||||
|
blinded =
|
||||||
|
response.headers.getString("eth-execution-payload-blinded")
|
||||||
|
executionValue =
|
||||||
|
response.headers.getString("eth-execution-payload-value")
|
||||||
|
consensusValue =
|
||||||
|
response.headers.getString("eth-consensus-block-value")
|
||||||
|
res = decodeBytes(ProduceBlockResponseV3, response.data,
|
||||||
|
response.contentType, version, blinded,
|
||||||
|
executionValue, consensusValue)
|
||||||
|
if res.isErr():
|
||||||
|
handleUnexpectedData()
|
||||||
|
ApiResponse[ProduceBlockResponseV3].err($res.error)
|
||||||
|
else:
|
||||||
|
ApiResponse[ProduceBlockResponseV3].ok(res.get())
|
||||||
|
of 400:
|
||||||
|
handle400()
|
||||||
|
ApiResponse[ProduceBlockResponseV3].err(ResponseInvalidError)
|
||||||
|
of 500:
|
||||||
|
handle500()
|
||||||
|
ApiResponse[ProduceBlockResponseV3].err(ResponseInternalError)
|
||||||
|
of 503:
|
||||||
|
handle503()
|
||||||
|
ApiResponse[ProduceBlockResponseV3].err(
|
||||||
|
ResponseNoSyncError)
|
||||||
|
else:
|
||||||
|
handleUnexpectedCode()
|
||||||
|
ApiResponse[ProduceBlockResponseV3].err(
|
||||||
|
ResponseUnexpectedError)
|
||||||
|
if res.isErr():
|
||||||
|
raise (ref ValidatorApiError)(msg: res.error, data: failures)
|
||||||
|
return res.get()
|
||||||
|
|
||||||
|
of ApiStrategyKind.First:
|
||||||
let res = vc.firstSuccessParallel(
|
let res = vc.firstSuccessParallel(
|
||||||
RestPlainResponse,
|
RestPlainResponse,
|
||||||
ProduceBlockResponseV3,
|
ProduceBlockResponseV3,
|
||||||
|
@ -2222,7 +2305,7 @@ proc publishBlock*(
|
||||||
return true
|
return true
|
||||||
of 202:
|
of 202:
|
||||||
debug BlockBroadcasted, node = node,
|
debug BlockBroadcasted, node = node,
|
||||||
blck = shortLog(ForkedSignedBeaconBlock.init(data))
|
blck = shortLog(ForkedSignedBeaconBlock.init(data))
|
||||||
return true
|
return true
|
||||||
of 400:
|
of 400:
|
||||||
handle400()
|
handle400()
|
||||||
|
|
|
@ -87,9 +87,9 @@ proc pollForValidatorIndices*(service: DutiesServiceRef) {.async.} =
|
||||||
if validator.isNone():
|
if validator.isNone():
|
||||||
missing.add(validatorLog(item.validator.pubkey, item.index))
|
missing.add(validatorLog(item.validator.pubkey, item.index))
|
||||||
else:
|
else:
|
||||||
validator.get().updateValidator(Opt.some ValidatorAndIndex(
|
vc.attachedValidators[].updateValidator(validator.get(),
|
||||||
index: item.index,
|
Opt.some ValidatorAndIndex(index: item.index,
|
||||||
validator: item.validator))
|
validator: item.validator))
|
||||||
updated.add(validatorLog(item.validator.pubkey, item.index))
|
updated.add(validatorLog(item.validator.pubkey, item.index))
|
||||||
list.add(validator.get())
|
list.add(validator.get())
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
import std/strutils
|
import std/strutils
|
||||||
import ssz_serialization/[types, bitseqs]
|
import ssz_serialization/[types, bitseqs]
|
||||||
import stew/endians2
|
import stew/endians2
|
||||||
|
import stint
|
||||||
import nimcrypto/hash
|
import nimcrypto/hash
|
||||||
import "."/common
|
import "."/common
|
||||||
|
|
||||||
|
@ -24,6 +25,9 @@ const
|
||||||
func perfectScore*(score: float64): bool =
|
func perfectScore*(score: float64): bool =
|
||||||
score == Inf
|
score == Inf
|
||||||
|
|
||||||
|
func perfectScore*(score: UInt256): bool =
|
||||||
|
score == high(UInt256)
|
||||||
|
|
||||||
proc shortScore*(score: float64): string =
|
proc shortScore*(score: float64): string =
|
||||||
if score == Inf:
|
if score == Inf:
|
||||||
"<perfect>"
|
"<perfect>"
|
||||||
|
@ -32,6 +36,9 @@ proc shortScore*(score: float64): string =
|
||||||
else:
|
else:
|
||||||
formatFloat(score, ffDecimal, 4)
|
formatFloat(score, ffDecimal, 4)
|
||||||
|
|
||||||
|
proc shortScore*(score: UInt256): string =
|
||||||
|
$score
|
||||||
|
|
||||||
func getLexicographicScore(digest: Eth2Digest): float64 =
|
func getLexicographicScore(digest: Eth2Digest): float64 =
|
||||||
# We calculate score on first 8 bytes of digest.
|
# We calculate score on first 8 bytes of digest.
|
||||||
let
|
let
|
||||||
|
@ -183,3 +190,28 @@ proc getUniqueVotes*(attestations: openArray[phase0.Attestation]): int =
|
||||||
processVotes(attestation)
|
processVotes(attestation)
|
||||||
res += count
|
res += count
|
||||||
res
|
res
|
||||||
|
|
||||||
|
proc getProduceBlockResponseV3Score*(blck: ProduceBlockResponseV3): UInt256 =
|
||||||
|
let (res, cv, ev) =
|
||||||
|
block:
|
||||||
|
var score256 = UInt256.zero
|
||||||
|
let
|
||||||
|
cvalue =
|
||||||
|
if blck.consensusValue.isSome():
|
||||||
|
let value = blck.consensusValue.get()
|
||||||
|
score256 = score256 + value
|
||||||
|
$value
|
||||||
|
else:
|
||||||
|
"<missing>"
|
||||||
|
evalue =
|
||||||
|
if blck.executionValue.isSome():
|
||||||
|
let value = blck.executionValue.get()
|
||||||
|
score256 = score256 + value
|
||||||
|
$value
|
||||||
|
else:
|
||||||
|
"<missing>"
|
||||||
|
(score256, cvalue, evalue)
|
||||||
|
|
||||||
|
debug "Block score", blck = shortLog(blck), consensus_value = cv,
|
||||||
|
execution_value = ev, score = shortScore(res)
|
||||||
|
res
|
||||||
|
|
|
@ -152,7 +152,7 @@ proc addValidatorsFromWeb3Signer(
|
||||||
gasLimit = node.consensusManager[].getGasLimit(keystore.pubkey)
|
gasLimit = node.consensusManager[].getGasLimit(keystore.pubkey)
|
||||||
v = node.attachedValidators[].addValidator(keystore, feeRecipient,
|
v = node.attachedValidators[].addValidator(keystore, feeRecipient,
|
||||||
gasLimit)
|
gasLimit)
|
||||||
v.updateValidator(data)
|
node.attachedValidators[].updateValidator(v, data)
|
||||||
|
|
||||||
proc addValidators*(node: BeaconNode) {.async: (raises: [CancelledError]).} =
|
proc addValidators*(node: BeaconNode) {.async: (raises: [CancelledError]).} =
|
||||||
info "Loading validators", validatorsDir = node.config.validatorsDir(),
|
info "Loading validators", validatorsDir = node.config.validatorsDir(),
|
||||||
|
@ -174,7 +174,7 @@ proc addValidators*(node: BeaconNode) {.async: (raises: [CancelledError]).} =
|
||||||
|
|
||||||
v = node.attachedValidators[].addValidator(keystore, feeRecipient,
|
v = node.attachedValidators[].addValidator(keystore, feeRecipient,
|
||||||
gasLimit)
|
gasLimit)
|
||||||
v.updateValidator(data)
|
node.attachedValidators[].updateValidator(v, data)
|
||||||
|
|
||||||
# We use `allFutures` because all failures are already reported as
|
# We use `allFutures` because all failures are already reported as
|
||||||
# user-visible warnings in `queryValidatorsSource`.
|
# user-visible warnings in `queryValidatorsSource`.
|
||||||
|
@ -363,10 +363,12 @@ proc createAndSendAttestation(node: BeaconNode,
|
||||||
res =
|
res =
|
||||||
if consensusFork >= ConsensusFork.Electra:
|
if consensusFork >= ConsensusFork.Electra:
|
||||||
await node.router.routeAttestation(
|
await node.router.routeAttestation(
|
||||||
registered.toElectraAttestation(signature), subnet_id, checkSignature = false)
|
registered.toElectraAttestation(signature), subnet_id,
|
||||||
|
checkSignature = false, checkValidator = false)
|
||||||
else:
|
else:
|
||||||
await node.router.routeAttestation(
|
await node.router.routeAttestation(
|
||||||
registered.toAttestation(signature), subnet_id, checkSignature = false)
|
registered.toAttestation(signature), subnet_id,
|
||||||
|
checkSignature = false, checkValidator = false)
|
||||||
if not res.isOk():
|
if not res.isOk():
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -537,6 +539,7 @@ proc makeBeaconBlockForHeadAndSlot*(
|
||||||
slot, validator_index
|
slot, validator_index
|
||||||
return err("Unable to get execution payload")
|
return err("Unable to get execution payload")
|
||||||
|
|
||||||
|
debugComment "flesh out consolidations"
|
||||||
let res = makeBeaconBlockWithRewards(
|
let res = makeBeaconBlockWithRewards(
|
||||||
node.dag.cfg,
|
node.dag.cfg,
|
||||||
state[],
|
state[],
|
||||||
|
@ -549,6 +552,7 @@ proc makeBeaconBlockForHeadAndSlot*(
|
||||||
exits,
|
exits,
|
||||||
node.syncCommitteeMsgPool[].produceSyncAggregate(head.bid, slot),
|
node.syncCommitteeMsgPool[].produceSyncAggregate(head.bid, slot),
|
||||||
payload,
|
payload,
|
||||||
|
@[], # consolidations
|
||||||
noRollback, # Temporary state - no need for rollback
|
noRollback, # Temporary state - no need for rollback
|
||||||
cache,
|
cache,
|
||||||
verificationFlags = {},
|
verificationFlags = {},
|
||||||
|
@ -1292,7 +1296,8 @@ proc proposeBlockAux(
|
||||||
else:
|
else:
|
||||||
Opt.none(seq[BlobSidecar])
|
Opt.none(seq[BlobSidecar])
|
||||||
newBlockRef = (
|
newBlockRef = (
|
||||||
await node.router.routeSignedBeaconBlock(signedBlock, blobsOpt)
|
await node.router.routeSignedBeaconBlock(signedBlock, blobsOpt,
|
||||||
|
checkValidator = false)
|
||||||
).valueOr:
|
).valueOr:
|
||||||
return head # Errors logged in router
|
return head # Errors logged in router
|
||||||
|
|
||||||
|
@ -1869,7 +1874,7 @@ proc updateValidators(
|
||||||
let
|
let
|
||||||
v = node.attachedValidators[].getValidator(validators[i].pubkey).valueOr:
|
v = node.attachedValidators[].getValidator(validators[i].pubkey).valueOr:
|
||||||
continue
|
continue
|
||||||
v.index = Opt.some ValidatorIndex(i)
|
node.attachedValidators[].setValidatorIndex(v, ValidatorIndex(i))
|
||||||
|
|
||||||
node.dutyValidatorCount = validators.len
|
node.dutyValidatorCount = validators.len
|
||||||
|
|
||||||
|
@ -1879,10 +1884,12 @@ proc updateValidators(
|
||||||
# Activation epoch can change after index is assigned..
|
# Activation epoch can change after index is assigned..
|
||||||
let index = validator.index.get()
|
let index = validator.index.get()
|
||||||
if index < validators.lenu64:
|
if index < validators.lenu64:
|
||||||
validator.updateValidator(
|
node.attachedValidators[].updateValidator(
|
||||||
|
validator,
|
||||||
Opt.some(ValidatorAndIndex(
|
Opt.some(ValidatorAndIndex(
|
||||||
index: index, validator: validators[int index]
|
index: index, validator: validators[int index]
|
||||||
)))
|
))
|
||||||
|
)
|
||||||
|
|
||||||
proc handleFallbackAttestations(node: BeaconNode, lastSlot, slot: Slot) =
|
proc handleFallbackAttestations(node: BeaconNode, lastSlot, slot: Slot) =
|
||||||
# Neither block proposal nor sync committee duties can be done in this
|
# Neither block proposal nor sync committee duties can be done in this
|
||||||
|
|
|
@ -1607,7 +1607,7 @@ proc addValidator*(
|
||||||
|
|
||||||
if not isNil(host.getValidatorAndIdxFn):
|
if not isNil(host.getValidatorAndIdxFn):
|
||||||
let data = host.getValidatorAndIdxFn(keystore.pubkey)
|
let data = host.getValidatorAndIdxFn(keystore.pubkey)
|
||||||
v.updateValidator(data)
|
host.validatorPool[].updateValidator(v, data)
|
||||||
|
|
||||||
proc generateDeposits*(cfg: RuntimeConfig,
|
proc generateDeposits*(cfg: RuntimeConfig,
|
||||||
rng: var HmacDrbgContext,
|
rng: var HmacDrbgContext,
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
{.push raises: [].}
|
{.push raises: [].}
|
||||||
|
|
||||||
import
|
import
|
||||||
stew/results,
|
|
||||||
std/sequtils,
|
std/sequtils,
|
||||||
chronicles,
|
chronicles,
|
||||||
metrics,
|
metrics,
|
||||||
|
@ -85,13 +84,22 @@ template getCurrentBeaconTime(router: MessageRouter): BeaconTime =
|
||||||
type RouteBlockResult = Result[Opt[BlockRef], string]
|
type RouteBlockResult = Result[Opt[BlockRef], string]
|
||||||
proc routeSignedBeaconBlock*(
|
proc routeSignedBeaconBlock*(
|
||||||
router: ref MessageRouter, blck: ForkySignedBeaconBlock,
|
router: ref MessageRouter, blck: ForkySignedBeaconBlock,
|
||||||
blobsOpt: Opt[seq[BlobSidecar]]):
|
blobsOpt: Opt[seq[BlobSidecar]], checkValidator: bool):
|
||||||
Future[RouteBlockResult] {.async: (raises: [CancelledError]).} =
|
Future[RouteBlockResult] {.async: (raises: [CancelledError]).} =
|
||||||
## Validate and broadcast beacon block, then add it to the block database
|
## Validate and broadcast beacon block, then add it to the block database
|
||||||
## Returns the new Head when block is added successfully to dag, none when
|
## Returns the new Head when block is added successfully to dag, none when
|
||||||
## block passes validation but is not added, and error otherwise
|
## block passes validation but is not added, and error otherwise
|
||||||
let wallTime = router[].getCurrentBeaconTime()
|
let wallTime = router[].getCurrentBeaconTime()
|
||||||
|
|
||||||
|
block:
|
||||||
|
let vindex = ValidatorIndex(blck.message.proposer_index)
|
||||||
|
if checkValidator and (vindex in router.processor.validatorPool[]):
|
||||||
|
warn "A validator client attempts to send a block from " &
|
||||||
|
"validator that is also manager by beacon node",
|
||||||
|
validator_index = vindex
|
||||||
|
return err("Block could not be sent from validator that is also " &
|
||||||
|
"managed by the beacon node")
|
||||||
|
|
||||||
# Start with a quick gossip validation check such that broadcasting the
|
# Start with a quick gossip validation check such that broadcasting the
|
||||||
# block doesn't get the node into trouble
|
# block doesn't get the node into trouble
|
||||||
block:
|
block:
|
||||||
|
@ -193,13 +201,14 @@ proc routeSignedBeaconBlock*(
|
||||||
proc routeAttestation*(
|
proc routeAttestation*(
|
||||||
router: ref MessageRouter,
|
router: ref MessageRouter,
|
||||||
attestation: phase0.Attestation | electra.Attestation,
|
attestation: phase0.Attestation | electra.Attestation,
|
||||||
subnet_id: SubnetId, checkSignature: bool):
|
subnet_id: SubnetId, checkSignature, checkValidator: bool):
|
||||||
Future[SendResult] {.async: (raises: [CancelledError]).} =
|
Future[SendResult] {.async: (raises: [CancelledError]).} =
|
||||||
## Process and broadcast attestation - processing will register the it with
|
## Process and broadcast attestation - processing will register the it with
|
||||||
## the attestation pool
|
## the attestation pool
|
||||||
block:
|
block:
|
||||||
let res = await router[].processor.processAttestation(
|
let res = await router[].processor.processAttestation(
|
||||||
MsgSource.api, attestation, subnet_id, checkSignature)
|
MsgSource.api, attestation, subnet_id,
|
||||||
|
checkSignature = checkSignature, checkValidator = checkValidator)
|
||||||
|
|
||||||
if not res.isGoodForSending:
|
if not res.isGoodForSending:
|
||||||
warn "Attestation failed validation",
|
warn "Attestation failed validation",
|
||||||
|
@ -250,7 +259,7 @@ proc routeAttestation*(
|
||||||
committee_index)
|
committee_index)
|
||||||
|
|
||||||
return await router.routeAttestation(
|
return await router.routeAttestation(
|
||||||
attestation, subnet_id, checkSignature = true)
|
attestation, subnet_id, checkSignature = true, checkValidator = true)
|
||||||
|
|
||||||
proc routeSignedAggregateAndProof*(
|
proc routeSignedAggregateAndProof*(
|
||||||
router: ref MessageRouter, proof: phase0.SignedAggregateAndProof,
|
router: ref MessageRouter, proof: phase0.SignedAggregateAndProof,
|
||||||
|
|
|
@ -143,7 +143,8 @@ proc unblindAndRouteBlockMEV*(
|
||||||
blck = shortLog(signedBlock)
|
blck = shortLog(signedBlock)
|
||||||
|
|
||||||
let newBlockRef =
|
let newBlockRef =
|
||||||
(await node.router.routeSignedBeaconBlock(signedBlock, blobsOpt)).valueOr:
|
(await node.router.routeSignedBeaconBlock(
|
||||||
|
signedBlock, blobsOpt, checkValidator = false)).valueOr:
|
||||||
# submitBlindedBlock has run, so don't allow fallback to run
|
# submitBlindedBlock has run, so don't allow fallback to run
|
||||||
return err("routeSignedBeaconBlock error") # Errors logged in router
|
return err("routeSignedBeaconBlock error") # Errors logged in router
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
{.push raises: [].}
|
{.push raises: [].}
|
||||||
|
|
||||||
import
|
import
|
||||||
std/[tables, json, streams, sequtils, uri],
|
std/[tables, json, streams, sequtils, uri, sets],
|
||||||
chronos, chronicles, metrics,
|
chronos, chronicles, metrics,
|
||||||
json_serialization/std/net,
|
json_serialization/std/net,
|
||||||
presto/client,
|
presto/client,
|
||||||
|
@ -93,6 +93,7 @@ type
|
||||||
|
|
||||||
ValidatorPool* = object
|
ValidatorPool* = object
|
||||||
validators*: Table[ValidatorPubKey, AttachedValidator]
|
validators*: Table[ValidatorPubKey, AttachedValidator]
|
||||||
|
indexSet*: HashSet[ValidatorIndex]
|
||||||
slashingProtection*: SlashingProtectionDB
|
slashingProtection*: SlashingProtectionDB
|
||||||
doppelgangerDetectionEnabled*: bool
|
doppelgangerDetectionEnabled*: bool
|
||||||
|
|
||||||
|
@ -223,10 +224,24 @@ func contains*(pool: ValidatorPool, pubkey: ValidatorPubKey): bool =
|
||||||
## Returns ``true`` if validator with key ``pubkey`` present in ``pool``.
|
## Returns ``true`` if validator with key ``pubkey`` present in ``pool``.
|
||||||
pool.validators.contains(pubkey)
|
pool.validators.contains(pubkey)
|
||||||
|
|
||||||
|
proc contains*(pool: ValidatorPool, index: ValidatorIndex): bool =
|
||||||
|
## Returns ``true`` if validator with index ``index`` present in ``pool``.
|
||||||
|
pool.indexSet.contains(index)
|
||||||
|
|
||||||
|
proc setValidatorIndex*(pool: var ValidatorPool, validator: AttachedValidator,
|
||||||
|
index: ValidatorIndex) =
|
||||||
|
pool.indexSet.incl(index)
|
||||||
|
validator.index = Opt.some(index)
|
||||||
|
|
||||||
|
proc removeValidatorIndex(pool: var ValidatorPool, index: ValidatorIndex) =
|
||||||
|
pool.indexSet.excl(index)
|
||||||
|
|
||||||
proc removeValidator*(pool: var ValidatorPool, pubkey: ValidatorPubKey) =
|
proc removeValidator*(pool: var ValidatorPool, pubkey: ValidatorPubKey) =
|
||||||
## Delete validator with public key ``pubkey`` from ``pool``.
|
## Delete validator with public key ``pubkey`` from ``pool``.
|
||||||
let validator = pool.validators.getOrDefault(pubkey)
|
let validator = pool.validators.getOrDefault(pubkey)
|
||||||
if not(isNil(validator)):
|
if not(isNil(validator)):
|
||||||
|
if validator.index.isSome():
|
||||||
|
pool.removeValidatorIndex(validator.index.get)
|
||||||
pool.validators.del(pubkey)
|
pool.validators.del(pubkey)
|
||||||
case validator.kind
|
case validator.kind
|
||||||
of ValidatorKind.Local:
|
of ValidatorKind.Local:
|
||||||
|
@ -243,8 +258,9 @@ proc removeValidator*(pool: var ValidatorPool, pubkey: ValidatorPubKey) =
|
||||||
func needsUpdate*(validator: AttachedValidator): bool =
|
func needsUpdate*(validator: AttachedValidator): bool =
|
||||||
validator.index.isNone() or validator.activationEpoch == FAR_FUTURE_EPOCH
|
validator.index.isNone() or validator.activationEpoch == FAR_FUTURE_EPOCH
|
||||||
|
|
||||||
proc updateValidator*(
|
proc updateValidator*(pool: var ValidatorPool,
|
||||||
validator: AttachedValidator, validatorData: Opt[ValidatorAndIndex]) =
|
validator: AttachedValidator,
|
||||||
|
validatorData: Opt[ValidatorAndIndex]) =
|
||||||
defer: validator.updated = true
|
defer: validator.updated = true
|
||||||
|
|
||||||
let
|
let
|
||||||
|
@ -259,6 +275,7 @@ proc updateValidator*(
|
||||||
|
|
||||||
## Update activation information for a validator
|
## Update activation information for a validator
|
||||||
if validator.index != Opt.some data.index:
|
if validator.index != Opt.some data.index:
|
||||||
|
pool.setValidatorIndex(validator, data.index)
|
||||||
validator.index = Opt.some data.index
|
validator.index = Opt.some data.index
|
||||||
validator.validator = Opt.some data.validator
|
validator.validator = Opt.some data.validator
|
||||||
|
|
||||||
|
|
|
@ -289,7 +289,7 @@ template `as`(address: Eth1Address, T: type bellatrix.ExecutionAddress): T =
|
||||||
template `as`(address: BlockHash, T: type Eth2Digest): T =
|
template `as`(address: BlockHash, T: type Eth2Digest): T =
|
||||||
asEth2Digest(address)
|
asEth2Digest(address)
|
||||||
|
|
||||||
func getOrDefault[T](x: Option[T]): T =
|
func getOrDefault[T](x: Opt[T]): T =
|
||||||
if x.isSome:
|
if x.isSome:
|
||||||
x.get
|
x.get
|
||||||
else:
|
else:
|
||||||
|
@ -505,25 +505,25 @@ proc doCreateTestnet*(config: CliConfig,
|
||||||
|
|
||||||
proc deployContract(web3: Web3, code: seq[byte]): Future[ReceiptObject] {.async.} =
|
proc deployContract(web3: Web3, code: seq[byte]): Future[ReceiptObject] {.async.} =
|
||||||
let tr = TransactionArgs(
|
let tr = TransactionArgs(
|
||||||
`from`: web3.defaultAccount.some,
|
`from`: Opt.some web3.defaultAccount,
|
||||||
data: code.some,
|
data: Opt.some code,
|
||||||
gas: Quantity(3000000).some,
|
gas: Opt.some Quantity(3000000),
|
||||||
gasPrice: Quantity(1).some)
|
gasPrice: Opt.some Quantity(1))
|
||||||
|
|
||||||
let r = await web3.send(tr)
|
let r = await web3.send(tr)
|
||||||
result = await web3.getMinedTransactionReceipt(r)
|
result = await web3.getMinedTransactionReceipt(r)
|
||||||
|
|
||||||
proc sendEth(web3: Web3, to: Eth1Address, valueEth: int): Future[TxHash] =
|
proc sendEth(web3: Web3, to: Eth1Address, valueEth: int): Future[TxHash] =
|
||||||
let tr = TransactionArgs(
|
let tr = TransactionArgs(
|
||||||
`from`: web3.defaultAccount.some,
|
`from`: Opt.some web3.defaultAccount,
|
||||||
# TODO: Force json-rpc to generate 'data' field
|
# TODO: Force json-rpc to generate 'data' field
|
||||||
# should not be needed anymore, new execution-api schema
|
# should not be needed anymore, new execution-api schema
|
||||||
# is using `input` field
|
# is using `input` field
|
||||||
data: some(newSeq[byte]()),
|
data: Opt.some(newSeq[byte]()),
|
||||||
gas: Quantity(3000000).some,
|
gas: Opt.some Quantity(3000000),
|
||||||
gasPrice: Quantity(1).some,
|
gasPrice: Opt.some Quantity(1),
|
||||||
value: some(valueEth.u256 * 1000000000000000000.u256),
|
value: Opt.some(valueEth.u256 * 1000000000000000000.u256),
|
||||||
to: some(to))
|
to: Opt.some(to))
|
||||||
web3.send(tr)
|
web3.send(tr)
|
||||||
|
|
||||||
type
|
type
|
||||||
|
@ -535,7 +535,7 @@ func ethToWei(eth: UInt256): UInt256 =
|
||||||
proc initWeb3(web3Url, privateKey: string): Future[Web3] {.async.} =
|
proc initWeb3(web3Url, privateKey: string): Future[Web3] {.async.} =
|
||||||
result = await newWeb3(web3Url)
|
result = await newWeb3(web3Url)
|
||||||
if privateKey.len != 0:
|
if privateKey.len != 0:
|
||||||
result.privateKey = some(keys.PrivateKey.fromHex(privateKey)[])
|
result.privateKey = Opt.some(keys.PrivateKey.fromHex(privateKey)[])
|
||||||
else:
|
else:
|
||||||
let accounts = await result.provider.eth_accounts()
|
let accounts = await result.provider.eth_accounts()
|
||||||
doAssert(accounts.len > 0)
|
doAssert(accounts.len > 0)
|
||||||
|
|
|
@ -79,7 +79,7 @@ stack-data==0.1.4
|
||||||
terminado==0.12.1
|
terminado==0.12.1
|
||||||
testpath==0.5.0
|
testpath==0.5.0
|
||||||
tomli==1.2.3
|
tomli==1.2.3
|
||||||
tornado==6.3.3
|
tornado==6.4.1
|
||||||
traitlets==5.1.1
|
traitlets==5.1.1
|
||||||
typing_extensions==4.0.1
|
typing_extensions==4.0.1
|
||||||
wcwidth==0.2.5
|
wcwidth==0.2.5
|
||||||
|
|
|
@ -85,7 +85,7 @@ proc makeSimulationBlock(
|
||||||
|
|
||||||
var blck = partialBeaconBlock(
|
var blck = partialBeaconBlock(
|
||||||
cfg, state, proposer_index, randao_reveal, eth1_data, graffiti,
|
cfg, state, proposer_index, randao_reveal, eth1_data, graffiti,
|
||||||
attestations, deposits, exits, sync_aggregate, execution_payload)
|
attestations, deposits, exits, sync_aggregate, execution_payload, @[])
|
||||||
|
|
||||||
let res = process_block(
|
let res = process_block(
|
||||||
cfg, state.data, blck.asSigVerified(), verificationFlags, cache)
|
cfg, state.data, blck.asSigVerified(), verificationFlags, cache)
|
||||||
|
@ -128,7 +128,7 @@ proc makeSimulationBlock(
|
||||||
|
|
||||||
var blck = partialBeaconBlock(
|
var blck = partialBeaconBlock(
|
||||||
cfg, state, proposer_index, randao_reveal, eth1_data, graffiti,
|
cfg, state, proposer_index, randao_reveal, eth1_data, graffiti,
|
||||||
attestations, deposits, exits, sync_aggregate, execution_payload)
|
attestations, deposits, exits, sync_aggregate, execution_payload, @[])
|
||||||
|
|
||||||
let res = process_block(
|
let res = process_block(
|
||||||
cfg, state.data, blck.asSigVerified(), verificationFlags, cache)
|
cfg, state.data, blck.asSigVerified(), verificationFlags, cache)
|
||||||
|
|
|
@ -57,7 +57,7 @@ proc setupEngineAPI*(server: RpcServer) =
|
||||||
# https://github.com/ethereum/execution-apis/blob/v1.0.0-beta.3/src/engine/paris.md#engine_forkchoiceupdatedv1
|
# https://github.com/ethereum/execution-apis/blob/v1.0.0-beta.3/src/engine/paris.md#engine_forkchoiceupdatedv1
|
||||||
server.rpc("engine_forkchoiceUpdatedV1") do(
|
server.rpc("engine_forkchoiceUpdatedV1") do(
|
||||||
update: ForkchoiceStateV1,
|
update: ForkchoiceStateV1,
|
||||||
payloadAttributes: Option[PayloadAttributesV1]) -> ForkchoiceUpdatedResponse:
|
payloadAttributes: Opt[PayloadAttributesV1]) -> ForkchoiceUpdatedResponse:
|
||||||
info "engine_forkchoiceUpdatedV1",
|
info "engine_forkchoiceUpdatedV1",
|
||||||
update,
|
update,
|
||||||
payloadAttributes
|
payloadAttributes
|
||||||
|
@ -68,7 +68,7 @@ proc setupEngineAPI*(server: RpcServer) =
|
||||||
|
|
||||||
# https://github.com/ethereum/execution-apis/blob/v1.0.0-beta.3/src/engine/shanghai.md#engine_forkchoiceupdatedv2
|
# https://github.com/ethereum/execution-apis/blob/v1.0.0-beta.3/src/engine/shanghai.md#engine_forkchoiceupdatedv2
|
||||||
server.rpc("engine_forkchoiceUpdatedV2") do(
|
server.rpc("engine_forkchoiceUpdatedV2") do(
|
||||||
forkchoiceState: ForkchoiceStateV1, payloadAttributes: Option[PayloadAttributesV2]) -> ForkchoiceUpdatedResponse:
|
forkchoiceState: ForkchoiceStateV1, payloadAttributes: Opt[PayloadAttributesV2]) -> ForkchoiceUpdatedResponse:
|
||||||
info "engine_forkchoiceUpdatedV2",
|
info "engine_forkchoiceUpdatedV2",
|
||||||
forkchoiceState, payloadAttributes
|
forkchoiceState, payloadAttributes
|
||||||
|
|
||||||
|
|
|
@ -134,7 +134,7 @@ cli do(validatorsDir: string, secretsDir: string,
|
||||||
headBlockHash = payload.block_hash,
|
headBlockHash = payload.block_hash,
|
||||||
safeBlockHash = payload.block_hash,
|
safeBlockHash = payload.block_hash,
|
||||||
finalizedBlockHash = ZERO_HASH,
|
finalizedBlockHash = ZERO_HASH,
|
||||||
payloadAttributes = none(consensusFork.PayloadAttributes))
|
payloadAttributes = Opt.none(consensusFork.PayloadAttributes))
|
||||||
if status != PayloadExecutionStatus.valid:
|
if status != PayloadExecutionStatus.valid:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
@ -295,6 +295,7 @@ cli do(validatorsDir: string, secretsDir: string,
|
||||||
BeaconBlockValidatorChanges(),
|
BeaconBlockValidatorChanges(),
|
||||||
syncAggregate,
|
syncAggregate,
|
||||||
payload,
|
payload,
|
||||||
|
@[], # consolidations
|
||||||
noRollback,
|
noRollback,
|
||||||
cache).get()
|
cache).get()
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ source "${SCRIPTS_DIR}/bash_utils.sh"
|
||||||
|
|
||||||
download_geth_stable() {
|
download_geth_stable() {
|
||||||
if [[ ! -e "${STABLE_GETH_BINARY}" ]]; then
|
if [[ ! -e "${STABLE_GETH_BINARY}" ]]; then
|
||||||
GETH_VERSION="1.14.0-87246f3c" # https://geth.ethereum.org/downloads
|
GETH_VERSION="1.14.5-0dd173a7" # https://geth.ethereum.org/downloads
|
||||||
GETH_URL="https://gethstore.blob.core.windows.net/builds/"
|
GETH_URL="https://gethstore.blob.core.windows.net/builds/"
|
||||||
|
|
||||||
case "${OS}-${ARCH}" in
|
case "${OS}-${ARCH}" in
|
||||||
|
|
|
@ -12,7 +12,6 @@ import
|
||||||
# Utilities
|
# Utilities
|
||||||
chronicles,
|
chronicles,
|
||||||
unittest2,
|
unittest2,
|
||||||
stew/results,
|
|
||||||
# Beacon chain internals
|
# Beacon chain internals
|
||||||
../../../beacon_chain/spec/[beaconstate, state_transition_block],
|
../../../beacon_chain/spec/[beaconstate, state_transition_block],
|
||||||
../../../beacon_chain/spec/datatypes/altair,
|
../../../beacon_chain/spec/datatypes/altair,
|
||||||
|
|
|
@ -12,7 +12,6 @@ import
|
||||||
# Utilities
|
# Utilities
|
||||||
chronicles,
|
chronicles,
|
||||||
unittest2,
|
unittest2,
|
||||||
stew/results,
|
|
||||||
# Beacon chain internals
|
# Beacon chain internals
|
||||||
../../../beacon_chain/spec/state_transition_block,
|
../../../beacon_chain/spec/state_transition_block,
|
||||||
../../../beacon_chain/spec/datatypes/bellatrix,
|
../../../beacon_chain/spec/datatypes/bellatrix,
|
||||||
|
|
|
@ -12,7 +12,6 @@ import
|
||||||
# Utilities
|
# Utilities
|
||||||
chronicles,
|
chronicles,
|
||||||
unittest2,
|
unittest2,
|
||||||
stew/results,
|
|
||||||
# Beacon chain internals
|
# Beacon chain internals
|
||||||
../../../beacon_chain/spec/state_transition_block,
|
../../../beacon_chain/spec/state_transition_block,
|
||||||
../../../beacon_chain/spec/datatypes/capella,
|
../../../beacon_chain/spec/datatypes/capella,
|
||||||
|
|
|
@ -12,7 +12,6 @@ import
|
||||||
# Utilities
|
# Utilities
|
||||||
chronicles,
|
chronicles,
|
||||||
unittest2,
|
unittest2,
|
||||||
stew/results,
|
|
||||||
# Beacon chain internals
|
# Beacon chain internals
|
||||||
../../../beacon_chain/spec/state_transition_block,
|
../../../beacon_chain/spec/state_transition_block,
|
||||||
../../../beacon_chain/spec/datatypes/deneb,
|
../../../beacon_chain/spec/datatypes/deneb,
|
||||||
|
|
|
@ -12,7 +12,6 @@ import
|
||||||
# Utilities
|
# Utilities
|
||||||
chronicles,
|
chronicles,
|
||||||
unittest2,
|
unittest2,
|
||||||
stew/results,
|
|
||||||
# Beacon chain internals
|
# Beacon chain internals
|
||||||
../../../beacon_chain/spec/state_transition_block,
|
../../../beacon_chain/spec/state_transition_block,
|
||||||
../../../beacon_chain/spec/datatypes/electra,
|
../../../beacon_chain/spec/datatypes/electra,
|
||||||
|
|
|
@ -12,7 +12,6 @@ import
|
||||||
# Utilities
|
# Utilities
|
||||||
chronicles,
|
chronicles,
|
||||||
unittest2,
|
unittest2,
|
||||||
stew/results,
|
|
||||||
# Beacon chain internals
|
# Beacon chain internals
|
||||||
../../../beacon_chain/spec/[beaconstate, state_transition_block],
|
../../../beacon_chain/spec/[beaconstate, state_transition_block],
|
||||||
../../../beacon_chain/spec/datatypes/phase0,
|
../../../beacon_chain/spec/datatypes/phase0,
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
# Status libraries
|
# Status libraries
|
||||||
stew/[byteutils, results], chronicles,
|
stew/byteutils, chronicles,
|
||||||
taskpools,
|
taskpools,
|
||||||
# Internals
|
# Internals
|
||||||
../../beacon_chain/spec/[helpers, forks, state_transition_block],
|
../../beacon_chain/spec/[helpers, forks, state_transition_block],
|
||||||
|
|
|
@ -12,7 +12,7 @@ import
|
||||||
std/json,
|
std/json,
|
||||||
yaml,
|
yaml,
|
||||||
kzg4844/kzg_ex,
|
kzg4844/kzg_ex,
|
||||||
stew/[byteutils, results],
|
stew/byteutils,
|
||||||
../testutil,
|
../testutil,
|
||||||
./fixtures_utils, ./os_ops
|
./fixtures_utils, ./os_ops
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
# Status lib
|
# Status lib
|
||||||
stew/results,
|
|
||||||
chronicles,
|
chronicles,
|
||||||
# Internal
|
# Internal
|
||||||
../../beacon_chain/validators/[slashing_protection, slashing_protection_v2],
|
../../beacon_chain/validators/[slashing_protection, slashing_protection_v2],
|
||||||
|
|
|
@ -10,10 +10,10 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
# Standard library
|
# Standard library
|
||||||
std/[os],
|
std/os,
|
||||||
# Status lib
|
# Status lib
|
||||||
eth/db/[kvstore, kvstore_sqlite3],
|
eth/db/[kvstore, kvstore_sqlite3],
|
||||||
stew/[results, endians2],
|
stew/endians2,
|
||||||
# Internal
|
# Internal
|
||||||
../../beacon_chain/validators/slashing_protection,
|
../../beacon_chain/validators/slashing_protection,
|
||||||
../../beacon_chain/spec/[helpers],
|
../../beacon_chain/spec/[helpers],
|
||||||
|
|
|
@ -10,7 +10,8 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
std/[json, os, random, sequtils, strutils, times],
|
std/[json, os, random, sequtils, strutils, times],
|
||||||
chronos, stew/[base10, results], chronicles, unittest2,
|
chronos,
|
||||||
|
stew/base10, chronicles, unittest2,
|
||||||
yaml,
|
yaml,
|
||||||
../beacon_chain/beacon_chain_db,
|
../beacon_chain/beacon_chain_db,
|
||||||
../beacon_chain/spec/deposit_snapshots,
|
../beacon_chain/spec/deposit_snapshots,
|
||||||
|
@ -39,7 +40,7 @@ proc ifNecessaryMigrateDCS(db: BeaconChainDB,
|
||||||
db.putDepositContractSnapshot upgradeProc(oldSnapshot.get)
|
db.putDepositContractSnapshot upgradeProc(oldSnapshot.get)
|
||||||
|
|
||||||
# Hexlified copy of
|
# Hexlified copy of
|
||||||
# eth2-networks/shared/mainnet/genesis_deposit_contract_snapshot.ssz
|
# mainnet/metadata/genesis_deposit_contract_snapshot.ssz
|
||||||
let ds1: seq[byte] = hexToSeqByte(
|
let ds1: seq[byte] = hexToSeqByte(
|
||||||
"""
|
"""
|
||||||
eeea1373d4aa9e099d7c9deddb694db9aeb4577755ef83f9b6345ce4357d9abfca3bfce2c
|
eeea1373d4aa9e099d7c9deddb694db9aeb4577755ef83f9b6345ce4357d9abfca3bfce2c
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
{.used.}
|
{.used.}
|
||||||
|
|
||||||
import
|
import
|
||||||
stew/results, presto/client,
|
presto/client,
|
||||||
testutils/unittests, chronicles,
|
testutils/unittests, chronicles,
|
||||||
../beacon_chain/spec/eth2_apis/[eth2_rest_serialization, rest_types],
|
../beacon_chain/spec/eth2_apis/[eth2_rest_serialization, rest_types],
|
||||||
./testutil
|
./testutil
|
||||||
|
|
|
@ -389,6 +389,7 @@ const
|
||||||
("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01", "0.9995"),
|
("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01", "0.9995"),
|
||||||
("0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101", "0.0005"),
|
("0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101", "0.0005"),
|
||||||
]
|
]
|
||||||
|
|
||||||
ContributionDataVectors = [
|
ContributionDataVectors = [
|
||||||
("0xffffffffffffffffffffffffffff7f7f", "0.9844"),
|
("0xffffffffffffffffffffffffffff7f7f", "0.9844"),
|
||||||
("0xffffffffffffffffffffffff7f7f7f7f", "0.9688"),
|
("0xffffffffffffffffffffffff7f7f7f7f", "0.9688"),
|
||||||
|
@ -446,6 +447,15 @@ const
|
||||||
([("0xff01", Slot(0), 0'u64), ("0xff01", Slot(0), 1'u64)], 16)
|
([("0xff01", Slot(0), 0'u64), ("0xff01", Slot(0), 1'u64)], 16)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
UInt256ScoreVectors = [
|
||||||
|
("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||||
|
"0x0000000000000000000000000000000000000000000000000000000000000001",
|
||||||
|
"0"),
|
||||||
|
("0x10",
|
||||||
|
"0x10",
|
||||||
|
"32")
|
||||||
|
]
|
||||||
|
|
||||||
proc init(t: typedesc[Eth2Digest], data: string): Eth2Digest =
|
proc init(t: typedesc[Eth2Digest], data: string): Eth2Digest =
|
||||||
let length = len(data)
|
let length = len(data)
|
||||||
var dst = Eth2Digest()
|
var dst = Eth2Digest()
|
||||||
|
@ -755,6 +765,25 @@ suite "Validator Client test suite":
|
||||||
score == "0.0000"
|
score == "0.0000"
|
||||||
isLowestScoreAggregatedAttestation(adata.data) == true
|
isLowestScoreAggregatedAttestation(adata.data) == true
|
||||||
|
|
||||||
|
test "getProduceBlockResponseV3Score() default test":
|
||||||
|
let
|
||||||
|
bdata1 = ProduceBlockResponseV3()
|
||||||
|
bdata2 = ProduceBlockResponseV3(
|
||||||
|
consensusValue: Opt.some(UInt256.zero)
|
||||||
|
)
|
||||||
|
bdata3 = ProduceBlockResponseV3(
|
||||||
|
executionValue: Opt.some(UInt256.zero),
|
||||||
|
)
|
||||||
|
bdata4 = ProduceBlockResponseV3(
|
||||||
|
consensusValue: Opt.some(UInt256.zero),
|
||||||
|
executionValue: Opt.some(UInt256.zero)
|
||||||
|
)
|
||||||
|
check:
|
||||||
|
shortScore(getProduceBlockResponseV3Score(bdata1)) == "0"
|
||||||
|
shortScore(getProduceBlockResponseV3Score(bdata2)) == "0"
|
||||||
|
shortScore(getProduceBlockResponseV3Score(bdata3)) == "0"
|
||||||
|
shortScore(getProduceBlockResponseV3Score(bdata4)) == "0"
|
||||||
|
|
||||||
test "getSyncCommitteeContributionDataScore() test vectors":
|
test "getSyncCommitteeContributionDataScore() test vectors":
|
||||||
for vector in ContributionDataVectors:
|
for vector in ContributionDataVectors:
|
||||||
let
|
let
|
||||||
|
@ -773,11 +802,24 @@ suite "Validator Client test suite":
|
||||||
check:
|
check:
|
||||||
score == vector[5]
|
score == vector[5]
|
||||||
|
|
||||||
|
test "getProduceBlockResponseV3Score() test vectors":
|
||||||
|
for vector in UInt256ScoreVectors:
|
||||||
|
let
|
||||||
|
value1 = strictParse(vector[0], UInt256, 16).get()
|
||||||
|
value2 = strictParse(vector[1], UInt256, 16).get()
|
||||||
|
bdata = ProduceBlockResponseV3(
|
||||||
|
executionValue: Opt.some(value1),
|
||||||
|
consensusValue: Opt.some(value2)
|
||||||
|
)
|
||||||
|
check shortScore(getProduceBlockResponseV3Score(bdata)) == vector[2]
|
||||||
|
|
||||||
test "getUniqueVotes() test vectors":
|
test "getUniqueVotes() test vectors":
|
||||||
for vector in AttestationBitsVectors:
|
for vector in AttestationBitsVectors:
|
||||||
let
|
let
|
||||||
a1 = phase0.Attestation.init(vector[0][0][0], vector[0][0][1], vector[0][0][2])
|
a1 = phase0.Attestation.init(vector[0][0][0], vector[0][0][1],
|
||||||
a2 = phase0.Attestation.init(vector[0][1][0], vector[0][1][1], vector[0][1][2])
|
vector[0][0][2])
|
||||||
|
a2 = phase0.Attestation.init(vector[0][1][0], vector[0][1][1],
|
||||||
|
vector[0][1][2])
|
||||||
check getUniqueVotes([a1, a2]) == vector[1]
|
check getUniqueVotes([a1, a2]) == vector[1]
|
||||||
|
|
||||||
asyncTest "firstSuccessParallel() API timeout test":
|
asyncTest "firstSuccessParallel() API timeout test":
|
||||||
|
@ -850,6 +892,7 @@ suite "Validator Client test suite":
|
||||||
let response = vc.bestSuccess(
|
let response = vc.bestSuccess(
|
||||||
RestPlainResponse,
|
RestPlainResponse,
|
||||||
uint64,
|
uint64,
|
||||||
|
float64,
|
||||||
100.milliseconds,
|
100.milliseconds,
|
||||||
AllBeaconNodeStatuses,
|
AllBeaconNodeStatuses,
|
||||||
{BeaconNodeRole.Duties},
|
{BeaconNodeRole.Duties},
|
||||||
|
|
|
@ -71,13 +71,14 @@ func checkResponse(a, b: openArray[KeystoreData]): bool =
|
||||||
suite "Validator pool":
|
suite "Validator pool":
|
||||||
test "Doppelganger for genesis validator":
|
test "Doppelganger for genesis validator":
|
||||||
let
|
let
|
||||||
|
pool = newClone(ValidatorPool())
|
||||||
v = AttachedValidator(activationEpoch: FAR_FUTURE_EPOCH)
|
v = AttachedValidator(activationEpoch: FAR_FUTURE_EPOCH)
|
||||||
|
|
||||||
check:
|
check:
|
||||||
not v.triggersDoppelganger(GENESIS_EPOCH) # no check
|
not v.triggersDoppelganger(GENESIS_EPOCH) # no check
|
||||||
not v.doppelgangerReady(GENESIS_EPOCH.start_slot) # no activation
|
not v.doppelgangerReady(GENESIS_EPOCH.start_slot) # no activation
|
||||||
|
|
||||||
v.updateValidator(makeValidatorAndIndex(ValidatorIndex(1), GENESIS_EPOCH))
|
pool[].updateValidator(v, makeValidatorAndIndex(ValidatorIndex(1), GENESIS_EPOCH))
|
||||||
|
|
||||||
check:
|
check:
|
||||||
not v.triggersDoppelganger(GENESIS_EPOCH) # no check
|
not v.triggersDoppelganger(GENESIS_EPOCH) # no check
|
||||||
|
@ -94,6 +95,7 @@ suite "Validator pool":
|
||||||
|
|
||||||
test "Doppelganger for validator that activates in same epoch as check":
|
test "Doppelganger for validator that activates in same epoch as check":
|
||||||
let
|
let
|
||||||
|
pool = newClone(ValidatorPool())
|
||||||
v = AttachedValidator(activationEpoch: FAR_FUTURE_EPOCH)
|
v = AttachedValidator(activationEpoch: FAR_FUTURE_EPOCH)
|
||||||
now = Epoch(10).start_slot()
|
now = Epoch(10).start_slot()
|
||||||
|
|
||||||
|
@ -104,7 +106,7 @@ suite "Validator pool":
|
||||||
not v.doppelgangerReady(GENESIS_EPOCH.start_slot)
|
not v.doppelgangerReady(GENESIS_EPOCH.start_slot)
|
||||||
not v.doppelgangerReady(now)
|
not v.doppelgangerReady(now)
|
||||||
|
|
||||||
v.updateValidator(makeValidatorAndIndex(ValidatorIndex(5), FAR_FUTURE_EPOCH))
|
pool[].updateValidator(v, makeValidatorAndIndex(ValidatorIndex(5), FAR_FUTURE_EPOCH))
|
||||||
|
|
||||||
check: # We still don't know when validator activates so we wouldn't trigger
|
check: # We still don't know when validator activates so we wouldn't trigger
|
||||||
not v.triggersDoppelganger(GENESIS_EPOCH)
|
not v.triggersDoppelganger(GENESIS_EPOCH)
|
||||||
|
@ -113,7 +115,7 @@ suite "Validator pool":
|
||||||
not v.doppelgangerReady(GENESIS_EPOCH.start_slot)
|
not v.doppelgangerReady(GENESIS_EPOCH.start_slot)
|
||||||
not v.doppelgangerReady(now)
|
not v.doppelgangerReady(now)
|
||||||
|
|
||||||
v.updateValidator(makeValidatorAndIndex(ValidatorIndex(5), now.epoch()))
|
pool[].updateValidator(v, makeValidatorAndIndex(ValidatorIndex(5), now.epoch()))
|
||||||
|
|
||||||
check: # No check done yet
|
check: # No check done yet
|
||||||
not v.triggersDoppelganger(GENESIS_EPOCH)
|
not v.triggersDoppelganger(GENESIS_EPOCH)
|
||||||
|
|
|
@ -118,8 +118,6 @@ proc build_empty_merge_execution_payload(state: bellatrix.BeaconState):
|
||||||
bellatrix.ExecutionPayloadForSigning(executionPayload: payload,
|
bellatrix.ExecutionPayloadForSigning(executionPayload: payload,
|
||||||
blockValue: Wei.zero)
|
blockValue: Wei.zero)
|
||||||
|
|
||||||
from stew/saturating_arith import saturate
|
|
||||||
|
|
||||||
proc build_empty_execution_payload(
|
proc build_empty_execution_payload(
|
||||||
state: bellatrix.BeaconState,
|
state: bellatrix.BeaconState,
|
||||||
feeRecipient: Eth1Address): bellatrix.ExecutionPayloadForSigning =
|
feeRecipient: Eth1Address): bellatrix.ExecutionPayloadForSigning =
|
||||||
|
@ -129,8 +127,8 @@ proc build_empty_execution_payload(
|
||||||
latest = state.latest_execution_payload_header
|
latest = state.latest_execution_payload_header
|
||||||
timestamp = compute_timestamp_at_slot(state, state.slot)
|
timestamp = compute_timestamp_at_slot(state, state.slot)
|
||||||
randao_mix = get_randao_mix(state, get_current_epoch(state))
|
randao_mix = get_randao_mix(state, get_current_epoch(state))
|
||||||
base_fee = calcEip1599BaseFee(GasInt.saturate latest.gas_limit,
|
base_fee = calcEip1599BaseFee(latest.gas_limit,
|
||||||
GasInt.saturate latest.gas_used,
|
latest.gas_used,
|
||||||
latest.base_fee_per_gas)
|
latest.base_fee_per_gas)
|
||||||
|
|
||||||
var payload = bellatrix.ExecutionPayloadForSigning(
|
var payload = bellatrix.ExecutionPayloadForSigning(
|
||||||
|
@ -172,6 +170,8 @@ proc addTestBlock*(
|
||||||
cfg, state, getStateField(state, slot) + 1, cache, info, flags).expect(
|
cfg, state, getStateField(state, slot) + 1, cache, info, flags).expect(
|
||||||
"can advance 1")
|
"can advance 1")
|
||||||
|
|
||||||
|
debugComment "add consolidations support to addTestBlock"
|
||||||
|
|
||||||
let
|
let
|
||||||
proposer_index = get_beacon_proposer_index(
|
proposer_index = get_beacon_proposer_index(
|
||||||
state, cache, getStateField(state, slot)).expect("valid proposer index")
|
state, cache, getStateField(state, slot)).expect("valid proposer index")
|
||||||
|
@ -208,8 +208,6 @@ proc addTestBlock*(
|
||||||
else:
|
else:
|
||||||
default(bellatrix.ExecutionPayloadForSigning)
|
default(bellatrix.ExecutionPayloadForSigning)
|
||||||
|
|
||||||
debugComment "addTestBlock Electra attestation support"
|
|
||||||
|
|
||||||
makeBeaconBlock(
|
makeBeaconBlock(
|
||||||
cfg,
|
cfg,
|
||||||
state,
|
state,
|
||||||
|
@ -229,6 +227,7 @@ proc addTestBlock*(
|
||||||
BeaconBlockValidatorChanges(),
|
BeaconBlockValidatorChanges(),
|
||||||
sync_aggregate,
|
sync_aggregate,
|
||||||
execution_payload,
|
execution_payload,
|
||||||
|
@[],
|
||||||
noRollback,
|
noRollback,
|
||||||
cache,
|
cache,
|
||||||
verificationFlags = {skipBlsValidation})
|
verificationFlags = {skipBlsValidation})
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit ab581251bcda11e3cc120cc9e9ad1ad679340949
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit c115f3688c19eb6153e22c1e76477db4ed27fae3
|
Subproject commit 9ed6c63314899d17e2c3f669adbe2bc915610982
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit f6b7882618a5ad2c1d2731ae35e5d16a660d5bb7
|
|
@ -1 +1 @@
|
||||||
Subproject commit d091a579a2e7c4668140e675a6fb2c78b8c6dc57
|
Subproject commit f29698d2e9a59453d99db7315a5af58add3c8715
|
|
@ -1 +1 @@
|
||||||
Subproject commit c482b4c5b658a77cc96b49d4a397aa6d98472ac7
|
Subproject commit 9b6497ed8a05ba25ee47142f3fc1f61742b51a6c
|
|
@ -1 +1 @@
|
||||||
Subproject commit 1ac1d69f9512d55d15e8218a9dbdff129bf96ddb
|
Subproject commit 4d0b0662ed960ab2c5a1ddbd08f77048bac13ae7
|
|
@ -1 +1 @@
|
||||||
Subproject commit 4fbcfbe4c452313bd440936318a87ed708987d8b
|
Subproject commit f12616d0675d9f6346141ca95f0840ab227eb213
|
|
@ -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
|
|
@ -1 +1 @@
|
||||||
Subproject commit aaef74113cadaaca690c6144eae0cf2c2a10db28
|
Subproject commit 913c426d571cf82601452642e01cd11ea26f7ac6
|
|
@ -1 +1 @@
|
||||||
Subproject commit 104132fd0217e846b04dd26a5fbe3e43a4929a05
|
Subproject commit a0a53c911606cace989074f6b806eb0546a64ef6
|
|
@ -1 +1 @@
|
||||||
Subproject commit 3c238df6cd4b9c1f37a9f103383e7d2bbd420c13
|
Subproject commit 9d2b382c5dc34f0d6bbd93b2a5d65dde85067e0f
|
|
@ -1 +1 @@
|
||||||
Subproject commit 9aed14a7373f51715730712adfde39546708296f
|
Subproject commit b705f816439f0068ece8c234336bc7093222d00f
|
Loading…
Reference in New Issue