mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-10 05:47:59 -05:00
Compare commits
262 Commits
unmarshal-
...
auth-kiln
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
77de59bf62 | ||
|
|
c1433c5c79 | ||
|
|
4767097c5b | ||
|
|
f39d1d01c4 | ||
|
|
01e9125761 | ||
|
|
8bc1648363 | ||
|
|
02a088d93c | ||
|
|
8cadb2ac6f | ||
|
|
78a90af679 | ||
|
|
be722604f7 | ||
|
|
3bb2acfc7d | ||
|
|
b280e796da | ||
|
|
7719356b69 | ||
|
|
75b9bdba7c | ||
|
|
1e32cd5596 | ||
|
|
72c1720704 | ||
|
|
b6fd9e5315 | ||
|
|
fa1509c970 | ||
|
|
525c818672 | ||
|
|
f9fbda80c2 | ||
|
|
a55fdf8949 | ||
|
|
7f41b69281 | ||
|
|
9a56a5d101 | ||
|
|
c5189a6862 | ||
|
|
5e8c49c871 | ||
|
|
4c7daf7a1f | ||
|
|
b4b976c28b | ||
|
|
c4454cae78 | ||
|
|
1cedf4ba9a | ||
|
|
4ce3da7ecc | ||
|
|
70a6fc4222 | ||
|
|
bb126a9829 | ||
|
|
99deee57d1 | ||
|
|
ced24892a5 | ||
|
|
4c23401a3b | ||
|
|
49f989e342 | ||
|
|
3003f08770 | ||
|
|
0232b5f8f5 | ||
|
|
9636fde1eb | ||
|
|
a424f523a1 | ||
|
|
90a15b2fbe | ||
|
|
68e75d5851 | ||
|
|
176ea137ee | ||
|
|
b15cd763b6 | ||
|
|
8e78eae897 | ||
|
|
f6883f2aa9 | ||
|
|
19782d2563 | ||
|
|
032cf433c5 | ||
|
|
fa656a86a5 | ||
|
|
5f414b3e82 | ||
|
|
41b8b1a0f8 | ||
|
|
1d36ecb98d | ||
|
|
80cd539297 | ||
|
|
f47b6af910 | ||
|
|
443df77bb3 | ||
|
|
062b2661c8 | ||
|
|
94fe3884a0 | ||
|
|
7d6046276d | ||
|
|
25425899b8 | ||
|
|
a6137cf774 | ||
|
|
2ccc27b1ba | ||
|
|
658fe3056f | ||
|
|
2598be6afa | ||
|
|
d77eb3533f | ||
|
|
4120abb62e | ||
|
|
7b411789ae | ||
|
|
49eccede3e | ||
|
|
9f7a554f0e | ||
|
|
f971b1728a | ||
|
|
4f77ad20c8 | ||
|
|
1b5a6d4195 | ||
|
|
eae0db383f | ||
|
|
b56bd9e9d8 | ||
|
|
481d8847c2 | ||
|
|
42d5416658 | ||
|
|
a1d8833749 | ||
|
|
695389b7bb | ||
|
|
a67b8610f0 | ||
|
|
29eceba4d2 | ||
|
|
4c34e5d424 | ||
|
|
569375286e | ||
|
|
924758a557 | ||
|
|
eedcb529fd | ||
|
|
30e796a4f1 | ||
|
|
ea6ca456e6 | ||
|
|
4b75b991dd | ||
|
|
8eaf391918 | ||
|
|
cbdb3c9e86 | ||
|
|
12754adddc | ||
|
|
08a5155ee3 | ||
|
|
f99a0419ef | ||
|
|
4ad31f9c05 | ||
|
|
26876d64d7 | ||
|
|
3450923661 | ||
|
|
aba628b56b | ||
|
|
5effb92d11 | ||
|
|
2b55368c99 | ||
|
|
327903b7bb | ||
|
|
77f815a39f | ||
|
|
80dc725412 | ||
|
|
263c18992e | ||
|
|
9e220f9052 | ||
|
|
99878d104c | ||
|
|
a870bf7a74 | ||
|
|
dc42ff382f | ||
|
|
53b78a38a3 | ||
|
|
b45826e731 | ||
|
|
7b59ecac5e | ||
|
|
9149178a9c | ||
|
|
51ef502b04 | ||
|
|
8d891821ee | ||
|
|
762863ce6a | ||
|
|
41f5fa7524 | ||
|
|
09744bac70 | ||
|
|
f5db847237 | ||
|
|
8600f70b0b | ||
|
|
6fe430de44 | ||
|
|
42a5f96d3f | ||
|
|
e7f0fcf202 | ||
|
|
5ae564f1bf | ||
|
|
719109c219 | ||
|
|
64533a4b0c | ||
|
|
9fecd761d7 | ||
|
|
f84c95667c | ||
|
|
9af081797e | ||
|
|
e4e9f12c8b | ||
|
|
2f4e8beae6 | ||
|
|
81c7b90d26 | ||
|
|
dd3d65ff18 | ||
|
|
ac5a227aeb | ||
|
|
33f4d5c3cc | ||
|
|
67d7f8baee | ||
|
|
3c54aef7b1 | ||
|
|
938c28c42e | ||
|
|
8ddb2c26c4 | ||
|
|
cf0e78c2f6 | ||
|
|
4c0b262fdc | ||
|
|
33e675e204 | ||
|
|
e599f6a8a1 | ||
|
|
49c9ab9fda | ||
|
|
f90dec287b | ||
|
|
12c36cff9d | ||
|
|
bc565d9ee6 | ||
|
|
db67d5bad8 | ||
|
|
3bc0c2be54 | ||
|
|
1bed9ef749 | ||
|
|
ec772beeaf | ||
|
|
56407dde02 | ||
|
|
445f17881e | ||
|
|
183d40d8f1 | ||
|
|
87bc6aa5e5 | ||
|
|
5b5065b01d | ||
|
|
ee1c567561 | ||
|
|
ff1416c98d | ||
|
|
471c94031f | ||
|
|
9863fb3d6a | ||
|
|
f3c2d1a00b | ||
|
|
5d8879a4df | ||
|
|
abea0a11bc | ||
|
|
80ce1603bd | ||
|
|
ca478244e0 | ||
|
|
8a864b66a1 | ||
|
|
72f3b9e84b | ||
|
|
493e95060f | ||
|
|
e7e1ecd72f | ||
|
|
c286ac8b87 | ||
|
|
bde315224c | ||
|
|
00520705bc | ||
|
|
c7fcd804d7 | ||
|
|
985ac2e848 | ||
|
|
f4a0e98926 | ||
|
|
5f93ff10ea | ||
|
|
544248f60f | ||
|
|
3b41968510 | ||
|
|
7fc418042a | ||
|
|
9a03946706 | ||
|
|
33dd6dd5f2 | ||
|
|
56542e1958 | ||
|
|
e82d7b4c0b | ||
|
|
6cb69d8ff0 | ||
|
|
70b55a0191 | ||
|
|
50f4951194 | ||
|
|
1a14f2368d | ||
|
|
bb8cad58f1 | ||
|
|
05412c1f0e | ||
|
|
b03441fed8 | ||
|
|
fa7d7cef69 | ||
|
|
1caa6c969f | ||
|
|
eeb7d5bbfb | ||
|
|
d7c7d150b1 | ||
|
|
63c4d2eb2b | ||
|
|
9de1f694a0 | ||
|
|
8a79d06cbd | ||
|
|
5290ad93b8 | ||
|
|
2128208ef7 | ||
|
|
296323719c | ||
|
|
5e9583ea85 | ||
|
|
17196e0f80 | ||
|
|
c50d54000d | ||
|
|
85b3061d1b | ||
|
|
0146c5317a | ||
|
|
fcbc48ffd9 | ||
|
|
76ee51af9d | ||
|
|
370b0b97ed | ||
|
|
990ebd3fe3 | ||
|
|
54449c72e8 | ||
|
|
1dbd0b98eb | ||
|
|
09c3896c6b | ||
|
|
d494845e19 | ||
|
|
4d0c0f7234 | ||
|
|
bfe570b1aa | ||
|
|
56db696823 | ||
|
|
d312e15db8 | ||
|
|
907d4cf7e6 | ||
|
|
891353d6ad | ||
|
|
0adc08660c | ||
|
|
de31425dcd | ||
|
|
2094e0f21f | ||
|
|
2c6f554500 | ||
|
|
18a1e07711 | ||
|
|
5e432f5aaa | ||
|
|
284e2696cb | ||
|
|
7547aaa6ce | ||
|
|
953315c2cc | ||
|
|
9662d06b08 | ||
|
|
ecaea26ace | ||
|
|
63819e2690 | ||
|
|
a6d0cd06b3 | ||
|
|
2dbe4f5e67 | ||
|
|
2689d6814d | ||
|
|
69a681ddc0 | ||
|
|
7f9f1fd36c | ||
|
|
57c97eb561 | ||
|
|
f0f94a8193 | ||
|
|
87b0bf2c2a | ||
|
|
d8ad317dec | ||
|
|
ab5f488cf4 | ||
|
|
296d7464ad | ||
|
|
221c542e4f | ||
|
|
7ad32aaa96 | ||
|
|
3dc0969c0c | ||
|
|
0e18e835c3 | ||
|
|
8adfbfc382 | ||
|
|
68b0b5e0ce | ||
|
|
eede309e0f | ||
|
|
b11628dc53 | ||
|
|
ea3ae22d3b | ||
|
|
02bb39ddeb | ||
|
|
1618c1f55d | ||
|
|
73c8493fd7 | ||
|
|
a4f59a4f15 | ||
|
|
3c497efdb8 | ||
|
|
9f5daafbb7 | ||
|
|
11d7ffdfa8 | ||
|
|
c26b3305e6 | ||
|
|
38d8b63fbf | ||
|
|
aea67405c8 | ||
|
|
57d830f8b3 | ||
|
|
ac4b1ef4ea | ||
|
|
1d32119f5a | ||
|
|
3540cc7b05 | ||
|
|
191e7767a6 |
@@ -183,7 +183,7 @@ load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_depe
|
||||
go_rules_dependencies()
|
||||
|
||||
go_register_toolchains(
|
||||
go_version = "1.16.4",
|
||||
go_version = "1.17.6",
|
||||
nogo = "@//:nogo",
|
||||
)
|
||||
|
||||
@@ -349,9 +349,9 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
sha256 = "f196fe4367c2d2d01d36565c0dc6eecfa4f03adba1fc03a61d62953fce606e1f",
|
||||
sha256 = "4797a7e594a5b1f4c1c8080701613f3ee451b01ec0861499ea7d9b60877a6b23",
|
||||
urls = [
|
||||
"https://github.com/prysmaticlabs/prysm-web-ui/releases/download/v1.0.2/prysm-web-ui.tar.gz",
|
||||
"https://github.com/prysmaticlabs/prysm-web-ui/releases/download/v1.0.3/prysm-web-ui.tar.gz",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -56,6 +56,7 @@ go_library(
|
||||
"//beacon-chain/operations/voluntaryexits:go_default_library",
|
||||
"//beacon-chain/p2p:go_default_library",
|
||||
"//beacon-chain/powchain:go_default_library",
|
||||
"//beacon-chain/powchain/engine-api-client/v1:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//beacon-chain/state/stategen:go_default_library",
|
||||
"//cmd/beacon-chain/flags:go_default_library",
|
||||
@@ -65,6 +66,7 @@ go_library(
|
||||
"//crypto/bls:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//monitoring/tracing:go_default_library",
|
||||
"//proto/engine/v1:go_default_library",
|
||||
"//proto/eth/v1:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//proto/prysm/v1alpha1/attestation:go_default_library",
|
||||
@@ -73,6 +75,8 @@ go_library(
|
||||
"//time:go_default_library",
|
||||
"//time/slots:go_default_library",
|
||||
"@com_github_emicklei_dot//:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
|
||||
"@com_github_holiman_uint256//:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_prometheus_client_golang//prometheus:go_default_library",
|
||||
@@ -104,6 +108,7 @@ go_test(
|
||||
"init_test.go",
|
||||
"log_test.go",
|
||||
"metrics_test.go",
|
||||
"mock_engine_test.go",
|
||||
"mock_test.go",
|
||||
"optimistic_sync_test.go",
|
||||
"pow_block_test.go",
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
@@ -334,6 +335,10 @@ func (s *Service) HeadValidatorIndexToPublicKey(_ context.Context, index types.V
|
||||
func (s *Service) IsOptimistic(ctx context.Context) (bool, error) {
|
||||
s.headLock.RLock()
|
||||
defer s.headLock.RUnlock()
|
||||
if slots.ToEpoch(s.CurrentSlot()) < params.BeaconConfig().BellatrixForkEpoch {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return s.cfg.ForkChoiceStore.Optimistic(ctx, s.head.root, s.head.slot)
|
||||
}
|
||||
|
||||
|
||||
@@ -357,6 +357,11 @@ func TestService_HeadValidatorIndexToPublicKeyNil(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestService_IsOptimistic(t *testing.T) {
|
||||
params.SetupTestConfigCleanup(t)
|
||||
cfg := params.BeaconConfig()
|
||||
cfg.BellatrixForkEpoch = 0
|
||||
params.OverrideBeaconConfig(cfg)
|
||||
|
||||
ctx := context.Background()
|
||||
c := &Service{cfg: &config{ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}, head: &head{slot: 101, root: [32]byte{'b'}}}
|
||||
require.NoError(t, c.cfg.ForkChoiceStore.ProcessBlock(ctx, 100, [32]byte{'a'}, [32]byte{}, [32]byte{}, 0, 0))
|
||||
@@ -367,6 +372,14 @@ func TestService_IsOptimistic(t *testing.T) {
|
||||
require.Equal(t, true, opt)
|
||||
}
|
||||
|
||||
func TestService_IsOptimisticBeforeBellatrix(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
c := &Service{genesisTime: time.Now()}
|
||||
opt, err := c.IsOptimistic(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, false, opt)
|
||||
}
|
||||
|
||||
func TestService_IsOptimisticForRoot(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
c := &Service{cfg: &config{ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}, head: &head{slot: 101, root: [32]byte{'b'}}}
|
||||
|
||||
48
beacon-chain/blockchain/mock_engine_test.go
Normal file
48
beacon-chain/blockchain/mock_engine_test.go
Normal file
@@ -0,0 +1,48 @@
|
||||
package blockchain
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/pkg/errors"
|
||||
v1 "github.com/prysmaticlabs/prysm/beacon-chain/powchain/engine-api-client/v1"
|
||||
enginev1 "github.com/prysmaticlabs/prysm/proto/engine/v1"
|
||||
)
|
||||
|
||||
type mockEngineService struct {
|
||||
blks map[[32]byte]*enginev1.ExecutionBlock
|
||||
}
|
||||
|
||||
func (*mockEngineService) NewPayload(context.Context, *enginev1.ExecutionPayload) (*enginev1.PayloadStatus, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (*mockEngineService) ForkchoiceUpdated(context.Context, *enginev1.ForkchoiceState, *enginev1.PayloadAttributes) (*v1.ForkchoiceUpdatedResponse, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (*mockEngineService) GetPayloadV1(
|
||||
_ context.Context, _ enginev1.PayloadIDBytes,
|
||||
) *enginev1.ExecutionPayload {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*mockEngineService) GetPayload(context.Context, [8]byte) (*enginev1.ExecutionPayload, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (*mockEngineService) ExchangeTransitionConfiguration(context.Context, *enginev1.TransitionConfiguration) (*enginev1.TransitionConfiguration, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (*mockEngineService) LatestExecutionBlock(context.Context) (*enginev1.ExecutionBlock, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *mockEngineService) ExecutionBlockByHash(_ context.Context, hash common.Hash) (*enginev1.ExecutionBlock, error) {
|
||||
blk, ok := m.blks[common.BytesToHash(hash.Bytes())]
|
||||
if !ok {
|
||||
return nil, errors.New("block not found")
|
||||
}
|
||||
return blk, nil
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/operations/voluntaryexits"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/p2p"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
|
||||
v1 "github.com/prysmaticlabs/prysm/beacon-chain/powchain/engine-api-client/v1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
@@ -50,6 +51,14 @@ func WithChainStartFetcher(f powchain.ChainStartFetcher) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// WithExecutionEngineCaller to call execution engine.
|
||||
func WithExecutionEngineCaller(c v1.EngineCaller) Option {
|
||||
return func(s *Service) error {
|
||||
s.cfg.ExecutionEngineCaller = c
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithDepositCache for deposit lifecycle after chain inclusion.
|
||||
func WithDepositCache(c *depositcache.DepositCache) Option {
|
||||
return func(s *Service) error {
|
||||
|
||||
@@ -1,20 +1,132 @@
|
||||
package blockchain
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/holiman/uint256"
|
||||
"github.com/pkg/errors"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
enginev1 "github.com/prysmaticlabs/prysm/proto/engine/v1"
|
||||
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// validates terminal pow block by comparing own total difficulty with parent's total difficulty.
|
||||
// validateMergeBlock validates terminal block hash in the event of manual overrides before checking for total difficulty.
|
||||
//
|
||||
// def validate_merge_block(block: BeaconBlock) -> None:
|
||||
// if TERMINAL_BLOCK_HASH != Hash32():
|
||||
// # If `TERMINAL_BLOCK_HASH` is used as an override, the activation epoch must be reached.
|
||||
// assert compute_epoch_at_slot(block.slot) >= TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH
|
||||
// assert block.body.execution_payload.parent_hash == TERMINAL_BLOCK_HASH
|
||||
// return
|
||||
//
|
||||
// pow_block = get_pow_block(block.body.execution_payload.parent_hash)
|
||||
// # Check if `pow_block` is available
|
||||
// assert pow_block is not None
|
||||
// pow_parent = get_pow_block(pow_block.parent_hash)
|
||||
// # Check if `pow_parent` is available
|
||||
// assert pow_parent is not None
|
||||
// # Check if `pow_block` is a valid terminal PoW block
|
||||
// assert is_valid_terminal_pow_block(pow_block, pow_parent)
|
||||
func (s *Service) validateMergeBlock(ctx context.Context, b block.SignedBeaconBlock) error {
|
||||
if err := helpers.BeaconBlockIsNil(b); err != nil {
|
||||
return err
|
||||
}
|
||||
payload, err := b.Block().Body().ExecutionPayload()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if payload == nil {
|
||||
return errors.New("nil execution payload")
|
||||
}
|
||||
if err := validateTerminalBlockHash(b.Block().Slot(), payload); err != nil {
|
||||
return errors.Wrap(err, "could not validate terminal block hash")
|
||||
}
|
||||
mergeBlockParentHash, mergeBlockTD, err := s.getBlkParentHashAndTD(ctx, payload.ParentHash)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get merge block parent hash and total difficulty")
|
||||
}
|
||||
_, mergeBlockParentTD, err := s.getBlkParentHashAndTD(ctx, mergeBlockParentHash)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get merge parent block total difficulty")
|
||||
}
|
||||
valid, err := validateTerminalBlockDifficulties(mergeBlockTD, mergeBlockParentTD)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !valid {
|
||||
return fmt.Errorf("invalid TTD, configTTD: %s, currentTTD: %s, parentTTD: %s",
|
||||
params.BeaconConfig().TerminalTotalDifficulty, mergeBlockTD, mergeBlockParentTD)
|
||||
}
|
||||
|
||||
log.WithFields(logrus.Fields{
|
||||
"slot": b.Block().Slot(),
|
||||
"mergeBlockHash": common.BytesToHash(payload.ParentHash).String(),
|
||||
"mergeBlockParentHash": common.BytesToHash(mergeBlockParentHash).String(),
|
||||
"terminalTotalDifficulty": params.BeaconConfig().TerminalTotalDifficulty,
|
||||
"mergeBlockTotalDifficulty": mergeBlockTD,
|
||||
"mergeBlockParentTotalDifficulty": mergeBlockParentTD,
|
||||
}).Info("Validated terminal block")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// getBlkParentHashAndTD retrieves the parent hash and total difficulty of the given block.
|
||||
func (s *Service) getBlkParentHashAndTD(ctx context.Context, blkHash []byte) ([]byte, *uint256.Int, error) {
|
||||
blk, err := s.cfg.ExecutionEngineCaller.ExecutionBlockByHash(ctx, common.BytesToHash(blkHash))
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "could not get pow block")
|
||||
}
|
||||
if blk == nil {
|
||||
return nil, nil, errors.New("pow block is nil")
|
||||
}
|
||||
blkTDBig, err := hexutil.DecodeBig(blk.TotalDifficulty)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "could not decode merge block total difficulty")
|
||||
}
|
||||
blkTDUint256, overflows := uint256.FromBig(blkTDBig)
|
||||
if overflows {
|
||||
return nil, nil, errors.New("total difficulty overflows")
|
||||
}
|
||||
return blk.ParentHash, blkTDUint256, nil
|
||||
}
|
||||
|
||||
// validateTerminalBlockHash validates if the merge block is a valid terminal PoW block.
|
||||
// spec code:
|
||||
// if TERMINAL_BLOCK_HASH != Hash32():
|
||||
// # If `TERMINAL_BLOCK_HASH` is used as an override, the activation epoch must be reached.
|
||||
// assert compute_epoch_at_slot(block.slot) >= TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH
|
||||
// assert block.body.execution_payload.parent_hash == TERMINAL_BLOCK_HASH
|
||||
// return
|
||||
func validateTerminalBlockHash(blkSlot types.Slot, payload *enginev1.ExecutionPayload) error {
|
||||
if bytesutil.ToBytes32(params.BeaconConfig().TerminalBlockHash.Bytes()) == [32]byte{} {
|
||||
return nil
|
||||
}
|
||||
if params.BeaconConfig().TerminalBlockHashActivationEpoch > slots.ToEpoch(blkSlot) {
|
||||
return errors.New("terminal block hash activation epoch not reached")
|
||||
}
|
||||
if !bytes.Equal(payload.ParentHash, params.BeaconConfig().TerminalBlockHash.Bytes()) {
|
||||
return errors.New("parent hash does not match terminal block hash")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// validateTerminalBlockDifficulties validates terminal pow block by comparing own total difficulty with parent's total difficulty.
|
||||
//
|
||||
// def is_valid_terminal_pow_block(block: PowBlock, parent: PowBlock) -> bool:
|
||||
// is_total_difficulty_reached = block.total_difficulty >= TERMINAL_TOTAL_DIFFICULTY
|
||||
// is_parent_total_difficulty_valid = parent.total_difficulty < TERMINAL_TOTAL_DIFFICULTY
|
||||
// return is_total_difficulty_reached and is_parent_total_difficulty_valid
|
||||
func validTerminalPowBlock(currentDifficulty *uint256.Int, parentDifficulty *uint256.Int) (bool, error) {
|
||||
func validateTerminalBlockDifficulties(currentDifficulty *uint256.Int, parentDifficulty *uint256.Int) (bool, error) {
|
||||
b, ok := new(big.Int).SetString(params.BeaconConfig().TerminalTotalDifficulty, 10)
|
||||
if !ok {
|
||||
return false, errors.New("failed to parse terminal total difficulty")
|
||||
|
||||
@@ -1,12 +1,21 @@
|
||||
package blockchain
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/holiman/uint256"
|
||||
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
enginev1 "github.com/prysmaticlabs/prysm/proto/engine/v1"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper"
|
||||
"github.com/prysmaticlabs/prysm/testing/require"
|
||||
)
|
||||
|
||||
@@ -66,10 +75,10 @@ func Test_validTerminalPowBlock(t *testing.T) {
|
||||
cfg := params.BeaconConfig()
|
||||
cfg.TerminalTotalDifficulty = fmt.Sprint(tt.ttd)
|
||||
params.OverrideBeaconConfig(cfg)
|
||||
got, err := validTerminalPowBlock(tt.currentDifficulty, tt.parentDifficulty)
|
||||
got, err := validateTerminalBlockDifficulties(tt.currentDifficulty, tt.parentDifficulty)
|
||||
require.NoError(t, err)
|
||||
if got != tt.want {
|
||||
t.Errorf("validTerminalPowBlock() = %v, want %v", got, tt.want)
|
||||
t.Errorf("validateTerminalBlockDifficulties() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -87,7 +96,115 @@ func Test_validTerminalPowBlockSpecConfig(t *testing.T) {
|
||||
parent, of := uint256.FromBig(i)
|
||||
require.Equal(t, of, false)
|
||||
|
||||
got, err := validTerminalPowBlock(current, parent)
|
||||
got, err := validateTerminalBlockDifficulties(current, parent)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, true, got)
|
||||
}
|
||||
|
||||
func Test_validateMergeBlock(t *testing.T) {
|
||||
cfg := params.BeaconConfig()
|
||||
cfg.TerminalTotalDifficulty = "2"
|
||||
params.OverrideBeaconConfig(cfg)
|
||||
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
fcs := protoarray.New(0, 0, [32]byte{'a'})
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
WithForkChoiceStore(fcs),
|
||||
}
|
||||
service, err := NewService(ctx, opts...)
|
||||
require.NoError(t, err)
|
||||
|
||||
engine := &mockEngineService{blks: map[[32]byte]*enginev1.ExecutionBlock{}}
|
||||
service.cfg.ExecutionEngineCaller = engine
|
||||
engine.blks[[32]byte{'a'}] = &enginev1.ExecutionBlock{
|
||||
ParentHash: bytesutil.PadTo([]byte{'b'}, fieldparams.RootLength),
|
||||
TotalDifficulty: "0x2",
|
||||
}
|
||||
engine.blks[[32]byte{'b'}] = &enginev1.ExecutionBlock{
|
||||
ParentHash: bytesutil.PadTo([]byte{'3'}, fieldparams.RootLength),
|
||||
TotalDifficulty: "0x1",
|
||||
}
|
||||
blk := ðpb.SignedBeaconBlockBellatrix{
|
||||
Block: ðpb.BeaconBlockBellatrix{
|
||||
Slot: 1,
|
||||
Body: ðpb.BeaconBlockBodyBellatrix{
|
||||
ExecutionPayload: &enginev1.ExecutionPayload{
|
||||
ParentHash: bytesutil.PadTo([]byte{'a'}, fieldparams.RootLength),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
b, err := wrapper.WrappedSignedBeaconBlock(blk)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, service.validateMergeBlock(ctx, b))
|
||||
|
||||
cfg.TerminalTotalDifficulty = "1"
|
||||
params.OverrideBeaconConfig(cfg)
|
||||
require.ErrorContains(t, "invalid TTD, configTTD: 1, currentTTD: 2, parentTTD: 1", service.validateMergeBlock(ctx, b))
|
||||
}
|
||||
|
||||
func Test_getBlkParentHashAndTD(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
fcs := protoarray.New(0, 0, [32]byte{'a'})
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
WithForkChoiceStore(fcs),
|
||||
}
|
||||
service, err := NewService(ctx, opts...)
|
||||
require.NoError(t, err)
|
||||
|
||||
engine := &mockEngineService{blks: map[[32]byte]*enginev1.ExecutionBlock{}}
|
||||
service.cfg.ExecutionEngineCaller = engine
|
||||
h := [32]byte{'a'}
|
||||
p := [32]byte{'b'}
|
||||
td := "0x1"
|
||||
engine.blks[h] = &enginev1.ExecutionBlock{
|
||||
ParentHash: p[:],
|
||||
TotalDifficulty: td,
|
||||
}
|
||||
parentHash, totalDifficulty, err := service.getBlkParentHashAndTD(ctx, h[:])
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, p, bytesutil.ToBytes32(parentHash))
|
||||
require.Equal(t, td, totalDifficulty.String())
|
||||
|
||||
_, _, err = service.getBlkParentHashAndTD(ctx, []byte{'c'})
|
||||
require.ErrorContains(t, "could not get pow block: block not found", err)
|
||||
|
||||
engine.blks[h] = nil
|
||||
_, _, err = service.getBlkParentHashAndTD(ctx, h[:])
|
||||
require.ErrorContains(t, "pow block is nil", err)
|
||||
|
||||
engine.blks[h] = &enginev1.ExecutionBlock{
|
||||
ParentHash: p[:],
|
||||
TotalDifficulty: "1",
|
||||
}
|
||||
_, _, err = service.getBlkParentHashAndTD(ctx, h[:])
|
||||
require.ErrorContains(t, "could not decode merge block total difficulty: hex string without 0x prefix", err)
|
||||
|
||||
engine.blks[h] = &enginev1.ExecutionBlock{
|
||||
ParentHash: p[:],
|
||||
TotalDifficulty: "0XFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
|
||||
}
|
||||
_, _, err = service.getBlkParentHashAndTD(ctx, h[:])
|
||||
require.ErrorContains(t, "could not decode merge block total difficulty: hex number > 256 bits", err)
|
||||
}
|
||||
|
||||
func Test_validateTerminalBlockHash(t *testing.T) {
|
||||
require.NoError(t, validateTerminalBlockHash(1, &enginev1.ExecutionPayload{}))
|
||||
|
||||
cfg := params.BeaconConfig()
|
||||
cfg.TerminalBlockHash = [32]byte{0x01}
|
||||
params.OverrideBeaconConfig(cfg)
|
||||
require.ErrorContains(t, "terminal block hash activation epoch not reached", validateTerminalBlockHash(1, &enginev1.ExecutionPayload{}))
|
||||
|
||||
cfg.TerminalBlockHashActivationEpoch = 0
|
||||
params.OverrideBeaconConfig(cfg)
|
||||
require.ErrorContains(t, "parent hash does not match terminal block hash", validateTerminalBlockHash(1, &enginev1.ExecutionPayload{}))
|
||||
|
||||
require.NoError(t, validateTerminalBlockHash(1, &enginev1.ExecutionPayload{ParentHash: cfg.TerminalBlockHash.Bytes()}))
|
||||
}
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
package blockchain
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/holiman/uint256"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/feed"
|
||||
statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
@@ -17,11 +22,14 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/crypto/bls"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/monitoring/tracing"
|
||||
enginev1 "github.com/prysmaticlabs/prysm/proto/engine/v1"
|
||||
ethpbv1 "github.com/prysmaticlabs/prysm/proto/eth/v1"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/attestation"
|
||||
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
"github.com/sirupsen/logrus"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
@@ -97,12 +105,76 @@ func (s *Service) onBlock(ctx context.Context, signed block.SignedBeaconBlock, b
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// TODO_MERGE: Optimize this copy.
|
||||
copiedPreState := preState.Copy()
|
||||
|
||||
body := signed.Block().Body()
|
||||
// TODO_MERGE: Break `ExecuteStateTransition` into per_slot and block processing so we can call `ExecutePayload` in the middle.
|
||||
postState, err := transition.ExecuteStateTransition(ctx, preState, signed)
|
||||
if err != nil {
|
||||
// TODO_MERGE: Notify execution client in the event of invalid conensus block
|
||||
return err
|
||||
}
|
||||
|
||||
fullyValidated := false
|
||||
if copiedPreState.Version() == version.Bellatrix || postState.Version() == version.Bellatrix {
|
||||
executionEnabled, err := blocks.ExecutionEnabled(postState, body)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not check if execution is enabled")
|
||||
}
|
||||
if executionEnabled {
|
||||
payload, err := body.ExecutionPayload()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get body execution payload")
|
||||
}
|
||||
// This is not the earliest we can call `ExecutePayload`, see above to do as the soonest we can call is after per_slot processing.
|
||||
status, err := s.cfg.ExecutionEngineCaller.NewPayload(ctx, payload)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.WithFields(logrus.Fields{
|
||||
"status:": status.Status,
|
||||
"hash:": fmt.Sprintf("%#x", payload.BlockHash),
|
||||
"parentHash": fmt.Sprintf("%#x", payload.ParentHash),
|
||||
}).Info("Successfully called newPayload")
|
||||
|
||||
switch status.Status {
|
||||
case enginev1.PayloadStatus_INVALID, enginev1.PayloadStatus_INVALID_BLOCK_HASH, enginev1.PayloadStatus_INVALID_TERMINAL_BLOCK:
|
||||
// TODO_MERGE walk up the parent chain removing
|
||||
return fmt.Errorf("could not prcess execution payload with status : %v", status.Status)
|
||||
case enginev1.PayloadStatus_SYNCING, enginev1.PayloadStatus_ACCEPTED:
|
||||
candidate, err := s.optimisticCandidateBlock(ctx, b)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not check if block is optimistic candidate")
|
||||
}
|
||||
if !candidate {
|
||||
return errors.New("could not optimistically sync block")
|
||||
}
|
||||
log.WithFields(logrus.Fields{
|
||||
"slot": b.Slot(),
|
||||
"root": fmt.Sprintf("%#x", bytesutil.Trunc(blockRoot[:])),
|
||||
"payloadHash": fmt.Sprintf("%#x", bytesutil.Trunc(payload.BlockHash)),
|
||||
}).Info("Block is optimistic candidate")
|
||||
break
|
||||
case enginev1.PayloadStatus_VALID:
|
||||
fullyValidated = true
|
||||
default:
|
||||
return errors.New("unknown payload status")
|
||||
}
|
||||
if fullyValidated {
|
||||
mergeBlock, err := blocks.MergeTransitionBlock(copiedPreState, body)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not check if merge block is terminal")
|
||||
}
|
||||
if mergeBlock {
|
||||
if err := s.validateTerminalBlock(ctx, signed); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We add a proposer score boost to fork choice for the block root if applicable, right after
|
||||
// running a successful state transition for the block.
|
||||
if err := s.cfg.ForkChoiceStore.BoostProposerRoot(
|
||||
@@ -115,6 +187,20 @@ func (s *Service) onBlock(ctx context.Context, signed block.SignedBeaconBlock, b
|
||||
return err
|
||||
}
|
||||
|
||||
// update forkchoice synced tips if the block is not optimistic
|
||||
if postState.Version() == version.Bellatrix || fullyValidated {
|
||||
root, err := b.HashTreeRoot()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.cfg.ForkChoiceStore.UpdateSyncedTipsWithValidRoot(ctx, root); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.saveSyncedTipsDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// If slasher is configured, forward the attestations in the block via
|
||||
// an event feed for processing.
|
||||
if features.Get().EnableSlasher {
|
||||
@@ -175,8 +261,63 @@ func (s *Service) onBlock(ctx context.Context, signed block.SignedBeaconBlock, b
|
||||
log.WithError(err).Warn("Could not update head")
|
||||
}
|
||||
|
||||
if err := s.saveSyncedTipsDB(ctx); err != nil {
|
||||
return errors.Wrap(err, "could not save synced tips")
|
||||
// Notify execution layer with fork choice head update if this is post merge block.
|
||||
if postState.Version() == version.Bellatrix {
|
||||
executionEnabled, err := blocks.ExecutionEnabled(postState, body)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not check if execution is enabled")
|
||||
}
|
||||
if executionEnabled {
|
||||
headPayload, err := s.headBlock().Block().Body().ExecutionPayload()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// TODO_MERGE: Loading the finalized block from DB on per block is not ideal. Finalized block should be cached here
|
||||
finalizedBlock, err := s.cfg.BeaconDB.Block(ctx, bytesutil.ToBytes32(finalized.Root))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
finalizedBlockHash := params.BeaconConfig().ZeroHash[:]
|
||||
if finalizedBlock != nil && finalizedBlock.Version() == version.Bellatrix {
|
||||
finalizedPayload, err := finalizedBlock.Block().Body().ExecutionPayload()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
finalizedBlockHash = finalizedPayload.BlockHash
|
||||
}
|
||||
|
||||
fcs := &enginev1.ForkchoiceState{
|
||||
HeadBlockHash: headPayload.BlockHash,
|
||||
SafeBlockHash: headPayload.BlockHash,
|
||||
FinalizedBlockHash: finalizedBlockHash,
|
||||
}
|
||||
resp, err := s.cfg.ExecutionEngineCaller.ForkchoiceUpdated(ctx, fcs, nil /* attribute */)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.WithFields(logrus.Fields{
|
||||
"status:": resp.Status.Status,
|
||||
"hash:": fmt.Sprintf("%#x", headPayload.BlockHash),
|
||||
}).Info("Successfully called forkchoiceUpdated")
|
||||
|
||||
switch resp.Status.Status {
|
||||
case enginev1.PayloadStatus_INVALID, enginev1.PayloadStatus_INVALID_BLOCK_HASH, enginev1.PayloadStatus_INVALID_TERMINAL_BLOCK:
|
||||
return fmt.Errorf("could not prcess execution payload with status : %v", resp.Status.Status)
|
||||
case enginev1.PayloadStatus_SYNCING, enginev1.PayloadStatus_ACCEPTED:
|
||||
candidate, err := s.optimisticCandidateBlock(ctx, b)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not check if block is optimistic candidate")
|
||||
}
|
||||
if !candidate {
|
||||
return errors.Wrap(err, "could not optimistically sync block")
|
||||
}
|
||||
break
|
||||
case enginev1.PayloadStatus_VALID:
|
||||
default:
|
||||
return errors.Wrap(err, "could not execute payload")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := s.pruneCanonicalAttsFromPool(ctx, blockRoot, signed); err != nil {
|
||||
@@ -251,32 +392,33 @@ func (s *Service) onBlock(ctx context.Context, signed block.SignedBeaconBlock, b
|
||||
}
|
||||
|
||||
func (s *Service) onBlockBatch(ctx context.Context, blks []block.SignedBeaconBlock,
|
||||
blockRoots [][32]byte) ([]*ethpb.Checkpoint, []*ethpb.Checkpoint, error) {
|
||||
blockRoots [][32]byte) ([]*ethpb.Checkpoint, []*ethpb.Checkpoint, []bool, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "blockChain.onBlockBatch")
|
||||
defer span.End()
|
||||
|
||||
if len(blks) == 0 || len(blockRoots) == 0 {
|
||||
return nil, nil, errors.New("no blocks provided")
|
||||
return nil, nil, nil, errors.New("no blocks provided")
|
||||
}
|
||||
if err := helpers.BeaconBlockIsNil(blks[0]); err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
b := blks[0].Block()
|
||||
|
||||
// Retrieve incoming block's pre state.
|
||||
if err := s.verifyBlkPreState(ctx, b); err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
preState, err := s.cfg.StateGen.StateByRootInitialSync(ctx, bytesutil.ToBytes32(b.ParentRoot()))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
if preState == nil || preState.IsNil() {
|
||||
return nil, nil, fmt.Errorf("nil pre state for slot %d", b.Slot())
|
||||
return nil, nil, nil, fmt.Errorf("nil pre state for slot %d", b.Slot())
|
||||
}
|
||||
|
||||
jCheckpoints := make([]*ethpb.Checkpoint, len(blks))
|
||||
fCheckpoints := make([]*ethpb.Checkpoint, len(blks))
|
||||
optimistic := make([]bool, len(blks))
|
||||
sigSet := &bls.SignatureBatch{
|
||||
Signatures: [][]byte{},
|
||||
PublicKeys: []bls.PublicKey{},
|
||||
@@ -285,43 +427,140 @@ func (s *Service) onBlockBatch(ctx context.Context, blks []block.SignedBeaconBlo
|
||||
var set *bls.SignatureBatch
|
||||
boundaries := make(map[[32]byte]state.BeaconState)
|
||||
for i, b := range blks {
|
||||
preStateCopied := preState.Copy() // TODO_MERGE: Optimize this copy.
|
||||
set, preState, err = transition.ExecuteStateTransitionNoVerifyAnySig(ctx, preState, b)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
// Non merge blocks are never optimistic
|
||||
optimistic[i] = false
|
||||
if preState.Version() == version.Bellatrix {
|
||||
executionEnabled, err := blocks.ExecutionEnabled(preState, b.Block().Body())
|
||||
if err != nil {
|
||||
return nil, nil, nil, errors.Wrap(err, "could not check if execution is enabled")
|
||||
}
|
||||
if executionEnabled {
|
||||
payload, err := b.Block().Body().ExecutionPayload()
|
||||
if err != nil {
|
||||
return nil, nil, nil, errors.Wrap(err, "could not get body execution payload")
|
||||
}
|
||||
status, err := s.cfg.ExecutionEngineCaller.NewPayload(ctx, payload)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
switch status.Status {
|
||||
case enginev1.PayloadStatus_INVALID, enginev1.PayloadStatus_INVALID_BLOCK_HASH, enginev1.PayloadStatus_INVALID_TERMINAL_BLOCK:
|
||||
// TODO_MERGE walk up the parent chain removing
|
||||
return nil, nil, nil, fmt.Errorf("could not prcess execution payload with status : %v", status.Status)
|
||||
case enginev1.PayloadStatus_SYNCING, enginev1.PayloadStatus_ACCEPTED:
|
||||
candidate, err := s.optimisticCandidateBlock(ctx, b.Block())
|
||||
if err != nil {
|
||||
return nil, nil, nil, errors.Wrap(err, "could not check if block is optimistic candidate")
|
||||
}
|
||||
if !candidate {
|
||||
return nil, nil, nil, errors.New("could not optimistically sync block")
|
||||
}
|
||||
log.WithFields(logrus.Fields{
|
||||
"slot": b.Block().Slot(),
|
||||
"root": fmt.Sprintf("%#x", bytesutil.Trunc(blockRoots[i][:])),
|
||||
"payloadHash": fmt.Sprintf("%#x", bytesutil.Trunc(payload.BlockHash)),
|
||||
}).Info("Block is optimistic candidate")
|
||||
optimistic[i] = true
|
||||
break
|
||||
case enginev1.PayloadStatus_VALID:
|
||||
default:
|
||||
return nil, nil, nil, errors.New("unknown payload status")
|
||||
}
|
||||
if !optimistic[i] {
|
||||
mergeBlock, err := blocks.MergeTransitionBlock(preStateCopied, b.Block().Body())
|
||||
if err != nil {
|
||||
return nil, nil, nil, errors.Wrap(err, "could not check if merge block is terminal")
|
||||
}
|
||||
if mergeBlock {
|
||||
if err := s.validateTerminalBlock(ctx, b); err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
headPayload, err := b.Block().Body().ExecutionPayload()
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
|
||||
}
|
||||
// TODO_MERGE: Loading the finalized block from DB on per block is not ideal. Finalized block should be cached here
|
||||
finalizedBlock, err := s.cfg.BeaconDB.Block(ctx, bytesutil.ToBytes32(preState.FinalizedCheckpoint().Root))
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
|
||||
}
|
||||
finalizedBlockHash := params.BeaconConfig().ZeroHash[:]
|
||||
if finalizedBlock != nil && finalizedBlock.Version() == version.Bellatrix {
|
||||
finalizedPayload, err := finalizedBlock.Block().Body().ExecutionPayload()
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
|
||||
}
|
||||
finalizedBlockHash = finalizedPayload.BlockHash
|
||||
}
|
||||
|
||||
fcs := &enginev1.ForkchoiceState{
|
||||
HeadBlockHash: headPayload.BlockHash,
|
||||
SafeBlockHash: headPayload.BlockHash,
|
||||
FinalizedBlockHash: finalizedBlockHash,
|
||||
}
|
||||
|
||||
resp, err := s.cfg.ExecutionEngineCaller.ForkchoiceUpdated(ctx, fcs, nil /* attribute */)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
switch resp.Status.Status {
|
||||
case enginev1.PayloadStatus_INVALID, enginev1.PayloadStatus_INVALID_BLOCK_HASH, enginev1.PayloadStatus_INVALID_TERMINAL_BLOCK:
|
||||
return nil, nil, nil, fmt.Errorf("could not prcess execution payload with status : %v", resp.Status.Status)
|
||||
case enginev1.PayloadStatus_SYNCING, enginev1.PayloadStatus_ACCEPTED:
|
||||
break
|
||||
case enginev1.PayloadStatus_VALID:
|
||||
default:
|
||||
return nil, nil, nil, errors.Wrap(err, "could not execute payload")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Save potential boundary states.
|
||||
if slots.IsEpochStart(preState.Slot()) {
|
||||
boundaries[blockRoots[i]] = preState.Copy()
|
||||
if err := s.handleEpochBoundary(ctx, preState); err != nil {
|
||||
return nil, nil, errors.Wrap(err, "could not handle epoch boundary state")
|
||||
return nil, nil, nil, errors.Wrap(err, "could not handle epoch boundary state")
|
||||
}
|
||||
}
|
||||
jCheckpoints[i] = preState.CurrentJustifiedCheckpoint()
|
||||
fCheckpoints[i] = preState.FinalizedCheckpoint()
|
||||
|
||||
sigSet.Join(set)
|
||||
}
|
||||
verify, err := sigSet.Verify()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
if !verify {
|
||||
return nil, nil, errors.New("batch block signature verification failed")
|
||||
return nil, nil, nil, errors.New("batch block signature verification failed")
|
||||
}
|
||||
for r, st := range boundaries {
|
||||
if err := s.cfg.StateGen.SaveState(ctx, r, st); err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
}
|
||||
// Also saves the last post state which to be used as pre state for the next batch.
|
||||
lastB := blks[len(blks)-1]
|
||||
lastBR := blockRoots[len(blockRoots)-1]
|
||||
if err := s.cfg.StateGen.SaveState(ctx, lastBR, preState); err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
if err := s.saveHeadNoDB(ctx, lastB, lastBR, preState); err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
return fCheckpoints, jCheckpoints, nil
|
||||
return fCheckpoints, jCheckpoints, optimistic, nil
|
||||
}
|
||||
|
||||
// handles a block after the block's batch has been verified, where we can save blocks
|
||||
@@ -334,10 +573,6 @@ func (s *Service) handleBlockAfterBatchVerify(ctx context.Context, signed block.
|
||||
if err := s.insertBlockToForkChoiceStore(ctx, b, blockRoot, fCheckpoint, jCheckpoint); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.saveSyncedTipsDB(ctx); err != nil {
|
||||
return errors.Wrap(err, "could not save synced tips")
|
||||
}
|
||||
|
||||
if err := s.cfg.BeaconDB.SaveStateSummary(ctx, ðpb.StateSummary{
|
||||
Slot: signed.Block().Slot(),
|
||||
Root: blockRoot[:],
|
||||
@@ -510,6 +745,88 @@ func (s *Service) pruneCanonicalAttsFromPool(ctx context.Context, r [32]byte, b
|
||||
return nil
|
||||
}
|
||||
|
||||
// validates terminal block hash in the event of manual overrides before checking for total difficulty.
|
||||
//
|
||||
// def validate_merge_block(block: BeaconBlock) -> None:
|
||||
// """
|
||||
// Check the parent PoW block of execution payload is a valid terminal PoW block.
|
||||
//
|
||||
// Note: Unavailable PoW block(s) may later become available,
|
||||
// and a client software MAY delay a call to ``validate_merge_block``
|
||||
// until the PoW block(s) become available.
|
||||
// """
|
||||
// if TERMINAL_BLOCK_HASH != Hash32():
|
||||
// # If `TERMINAL_BLOCK_HASH` is used as an override, the activation epoch must be reached.
|
||||
// assert compute_epoch_at_slot(block.slot) >= TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH
|
||||
// return block.block_hash == TERMINAL_BLOCK_HASH
|
||||
//
|
||||
// pow_block = get_pow_block(block.body.execution_payload.parent_hash)
|
||||
// # Check if `pow_block` is available
|
||||
// assert pow_block is not None
|
||||
// pow_parent = get_pow_block(pow_block.parent_hash)
|
||||
// # Check if `pow_parent` is available
|
||||
// assert pow_parent is not None
|
||||
// # Check if `pow_block` is a valid terminal PoW block
|
||||
// assert is_valid_terminal_pow_block(pow_block, pow_parent)
|
||||
func (s *Service) validateTerminalBlock(ctx context.Context, b block.SignedBeaconBlock) error {
|
||||
payload, err := b.Block().Body().ExecutionPayload()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if bytesutil.ToBytes32(params.BeaconConfig().TerminalBlockHash.Bytes()) != [32]byte{} {
|
||||
// `TERMINAL_BLOCK_HASH` is used as an override, the activation epoch must be reached.
|
||||
if params.BeaconConfig().TerminalBlockHashActivationEpoch > slots.ToEpoch(b.Block().Slot()) {
|
||||
return errors.New("terminal block hash activation epoch not reached")
|
||||
}
|
||||
if !bytes.Equal(payload.ParentHash, params.BeaconConfig().TerminalBlockHash.Bytes()) {
|
||||
return errors.New("parent hash does not match terminal block hash")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
transitionBlk, err := s.cfg.ExecutionEngineCaller.ExecutionBlockByHash(ctx, common.BytesToHash(payload.ParentHash))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get transition block")
|
||||
}
|
||||
parentTransitionBlk, err := s.cfg.ExecutionEngineCaller.ExecutionBlockByHash(ctx, common.BytesToHash(transitionBlk.ParentHash))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get transition parent block")
|
||||
}
|
||||
transitionBlkTDBig, err := hexutil.DecodeBig(transitionBlk.TotalDifficulty)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not decode transition total difficulty")
|
||||
}
|
||||
transitionBlkTTD, overflows := uint256.FromBig(transitionBlkTDBig)
|
||||
if overflows {
|
||||
return errors.New("total difficulty overflows")
|
||||
}
|
||||
parentBlkTD, err := hexutil.DecodeBig(parentTransitionBlk.TotalDifficulty)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not decode transition total difficulty")
|
||||
}
|
||||
parentBlkTTD, overflows := uint256.FromBig(parentBlkTD)
|
||||
if overflows {
|
||||
return errors.New("total difficulty overflows")
|
||||
}
|
||||
log.WithFields(logrus.Fields{
|
||||
"slot": b.Block().Slot(),
|
||||
"transitionBlockHash": common.BytesToHash(payload.ParentHash).String(),
|
||||
"transitionBlockParentHash": common.BytesToHash(transitionBlk.ParentHash).String(),
|
||||
"terminalTotalDifficulty": params.BeaconConfig().TerminalTotalDifficulty,
|
||||
"transitionBlockTotalDifficulty": transitionBlkTTD,
|
||||
"transitionBlockParentTotalDifficulty": parentBlkTTD,
|
||||
}).Info("Validating terminal block")
|
||||
|
||||
validated, err := validateTerminalBlockDifficulties(transitionBlkTTD, parentBlkTTD)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !validated {
|
||||
return errors.New("invalid difficulty for terminal block")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Saves synced and validated tips to DB.
|
||||
func (s *Service) saveSyncedTipsDB(ctx context.Context) error {
|
||||
tips := s.cfg.ForkChoiceStore.SyncedTips()
|
||||
|
||||
@@ -178,7 +178,7 @@ func TestStore_OnBlockBatch(t *testing.T) {
|
||||
rBlock.Block.ParentRoot = gRoot[:]
|
||||
require.NoError(t, beaconDB.SaveBlock(context.Background(), blks[0]))
|
||||
require.NoError(t, service.cfg.StateGen.SaveState(ctx, blkRoots[0], firstState))
|
||||
_, _, err = service.onBlockBatch(ctx, blks[1:], blkRoots[1:])
|
||||
_, _, _, err = service.onBlockBatch(ctx, blks[1:], blkRoots[1:])
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ func (s *Service) ReceiveBlockBatch(ctx context.Context, blocks []block.SignedBe
|
||||
defer span.End()
|
||||
|
||||
// Apply state transition on the incoming newly received blockCopy without verifying its BLS contents.
|
||||
fCheckpoints, jCheckpoints, err := s.onBlockBatch(ctx, blocks, blkRoots)
|
||||
fCheckpoints, jCheckpoints, optimistic, err := s.onBlockBatch(ctx, blocks, blkRoots)
|
||||
if err != nil {
|
||||
err := errors.Wrap(err, "could not process block in batch")
|
||||
tracing.AnnotateError(span, err)
|
||||
@@ -90,6 +90,19 @@ func (s *Service) ReceiveBlockBatch(ctx context.Context, blocks []block.SignedBe
|
||||
tracing.AnnotateError(span, err)
|
||||
return err
|
||||
}
|
||||
if !optimistic[i] {
|
||||
root, err := b.Block().HashTreeRoot()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.cfg.ForkChoiceStore.UpdateSyncedTipsWithValidRoot(ctx, root); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.saveSyncedTipsDB(ctx); err != nil {
|
||||
return errors.Wrap(err, "could not save synced tips")
|
||||
}
|
||||
}
|
||||
|
||||
// Send notification of the processed block to the state feed.
|
||||
s.cfg.StateNotifier.StateFeed().Send(&feed.Event{
|
||||
Type: statefeed.BlockProcessed,
|
||||
|
||||
@@ -27,6 +27,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/operations/voluntaryexits"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/p2p"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
|
||||
enginev1 "github.com/prysmaticlabs/prysm/beacon-chain/powchain/engine-api-client/v1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
|
||||
"github.com/prysmaticlabs/prysm/cmd/beacon-chain/flags"
|
||||
@@ -82,7 +83,9 @@ type config struct {
|
||||
StateGen *stategen.State
|
||||
SlasherAttestationsFeed *event.Feed
|
||||
WeakSubjectivityCheckpt *ethpb.Checkpoint
|
||||
BlockFetcher powchain.POWBlockFetcher
|
||||
FinalizedStateAtStartUp state.BeaconState
|
||||
ExecutionEngineCaller enginev1.EngineCaller
|
||||
}
|
||||
|
||||
// NewService instantiates a new block service instance that will
|
||||
|
||||
@@ -32,34 +32,35 @@ var ErrNilState = errors.New("nil state")
|
||||
|
||||
// ChainService defines the mock interface for testing
|
||||
type ChainService struct {
|
||||
State state.BeaconState
|
||||
Root []byte
|
||||
Block block.SignedBeaconBlock
|
||||
Optimistic bool
|
||||
ValidAttestation bool
|
||||
ValidatorsRoot [32]byte
|
||||
PublicKey [fieldparams.BLSPubkeyLength]byte
|
||||
FinalizedCheckPoint *ethpb.Checkpoint
|
||||
CurrentJustifiedCheckPoint *ethpb.Checkpoint
|
||||
PreviousJustifiedCheckPoint *ethpb.Checkpoint
|
||||
BlocksReceived []block.SignedBeaconBlock
|
||||
Slot *types.Slot // Pointer because 0 is a useful value, so checking against it can be incorrect.
|
||||
Balance *precompute.Balance
|
||||
Genesis time.Time
|
||||
ValidatorsRoot [32]byte
|
||||
ForkChoiceStore *protoarray.Store
|
||||
CanonicalRoots map[[32]byte]bool
|
||||
Fork *ethpb.Fork
|
||||
ETH1Data *ethpb.Eth1Data
|
||||
InitSyncBlockRoots map[[32]byte]bool
|
||||
DB db.Database
|
||||
State state.BeaconState
|
||||
Block block.SignedBeaconBlock
|
||||
VerifyBlkDescendantErr error
|
||||
stateNotifier statefeed.Notifier
|
||||
BlocksReceived []block.SignedBeaconBlock
|
||||
SyncCommitteeIndices []types.CommitteeIndex
|
||||
blockNotifier blockfeed.Notifier
|
||||
opNotifier opfeed.Notifier
|
||||
ValidAttestation bool
|
||||
ForkChoiceStore *protoarray.Store
|
||||
VerifyBlkDescendantErr error
|
||||
Slot *types.Slot // Pointer because 0 is a useful value, so checking against it can be incorrect.
|
||||
SyncCommitteeIndices []types.CommitteeIndex
|
||||
Root []byte
|
||||
SyncCommitteeDomain []byte
|
||||
SyncSelectionProofDomain []byte
|
||||
SyncContributionProofDomain []byte
|
||||
PublicKey [fieldparams.BLSPubkeyLength]byte
|
||||
SyncCommitteePubkeys [][]byte
|
||||
InitSyncBlockRoots map[[32]byte]bool
|
||||
Genesis time.Time
|
||||
}
|
||||
|
||||
// StateNotifier mocks the same method in the chain service.
|
||||
@@ -442,7 +443,7 @@ func (s *ChainService) HeadSyncContributionProofDomain(_ context.Context, _ type
|
||||
|
||||
// IsOptimistic mocks the same method in the chain service.
|
||||
func (s *ChainService) IsOptimistic(_ context.Context) (bool, error) {
|
||||
return false, nil
|
||||
return s.Optimistic, nil
|
||||
}
|
||||
|
||||
// IsOptimisticForRoot mocks the same method in the chain service.
|
||||
|
||||
@@ -120,11 +120,6 @@ func (_ *Service) AllDeposits(_ context.Context, _ *big.Int) []*ethpb.Deposit {
|
||||
return []*ethpb.Deposit{}
|
||||
}
|
||||
|
||||
// ChainStartDeposits mocks out the powchain functionality for interop.
|
||||
func (s *Service) ChainStartDeposits() []*ethpb.Deposit {
|
||||
return s.chainStartDeposits
|
||||
}
|
||||
|
||||
// ChainStartEth1Data mocks out the powchain functionality for interop.
|
||||
func (_ *Service) ChainStartEth1Data() *ethpb.Eth1Data {
|
||||
return ðpb.Eth1Data{}
|
||||
|
||||
@@ -119,6 +119,7 @@ func New(cliCtx *cli.Context, opts ...Option) (*BeaconNode, error) {
|
||||
configureEth1Config(cliCtx)
|
||||
configureNetwork(cliCtx)
|
||||
configureInteropConfig(cliCtx)
|
||||
configureExecutionSetting(cliCtx)
|
||||
|
||||
// Initializes any forks here.
|
||||
params.BeaconConfig().InitializeForkSchedule()
|
||||
@@ -554,6 +555,7 @@ func (b *BeaconNode) registerBlockchainService() error {
|
||||
blockchain.WithDatabase(b.db),
|
||||
blockchain.WithDepositCache(b.depositCache),
|
||||
blockchain.WithChainStartFetcher(web3Service),
|
||||
blockchain.WithExecutionEngineCaller(web3Service.EngineAPIClient()),
|
||||
blockchain.WithAttestationPool(b.attestationPool),
|
||||
blockchain.WithExitPool(b.exitPool),
|
||||
blockchain.WithSlashingPool(b.slashingsPool),
|
||||
@@ -780,6 +782,7 @@ func (b *BeaconNode) registerRPCService() error {
|
||||
StateGen: b.stateGen,
|
||||
EnableDebugRPCEndpoints: enableDebugRPCEndpoints,
|
||||
MaxMsgSize: maxMsgSize,
|
||||
ExecutionEngineCaller: web3Service.EngineAPIClient(),
|
||||
})
|
||||
|
||||
return b.services.RegisterService(rpcService)
|
||||
|
||||
@@ -3,6 +3,7 @@ load("@prysm//tools/go:def.bzl", "go_library", "go_test")
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"auth.go",
|
||||
"client.go",
|
||||
"errors.go",
|
||||
"options.go",
|
||||
@@ -14,13 +15,17 @@ go_library(
|
||||
"//proto/engine/v1:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//rpc:go_default_library",
|
||||
"@com_github_golang_jwt_jwt//:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["client_test.go"],
|
||||
srcs = [
|
||||
"auth_test.go",
|
||||
"client_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//config/fieldparams:go_default_library",
|
||||
@@ -30,6 +35,7 @@ go_test(
|
||||
"//testing/require:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//rpc:go_default_library",
|
||||
"@com_github_golang_jwt_jwt//:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@org_golang_google_protobuf//proto:go_default_library",
|
||||
],
|
||||
|
||||
44
beacon-chain/powchain/engine-api-client/v1/auth.go
Normal file
44
beacon-chain/powchain/engine-api-client/v1/auth.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/golang-jwt/jwt"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// This creates a custom HTTP transport which we can attach to our HTTP client
|
||||
// in order to inject JWT auth strings into our HTTP request headers. Authentication
|
||||
// is required when interacting with an Ethereum engine API server via HTTP, and JWT
|
||||
// is chosen as the scheme of choice.
|
||||
// For more details on the requirements of authentication when using the engine API, see
|
||||
// the specification here: https://github.com/ethereum/execution-apis/blob/main/src/engine/authentication.md
|
||||
//
|
||||
// To use this transport, initialize a new &http.Client{} from the standard library
|
||||
// and set the Transport field to &jwtTransport{} with values
|
||||
// http.DefaultTransport and a JWT secret.
|
||||
type jwtTransport struct {
|
||||
underlyingTransport http.RoundTripper
|
||||
jwtSecret []byte
|
||||
}
|
||||
|
||||
// RoundTrip ensures our transport implements http.RoundTripper interface from the
|
||||
// standard library. When used as the transport for an HTTP client, the code below
|
||||
// will run every time our client makes an HTTP request. This is used to inject
|
||||
// an JWT bearer token in the Authorization request header of every outgoing request
|
||||
// our HTTP client makes.
|
||||
func (t *jwtTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
|
||||
// Required claim for engine API auth. "iat" stands for issued at
|
||||
// and it must be a unix timestamp that is +/- 5 seconds from the current
|
||||
// timestamp at the moment the server verifies this value.
|
||||
"iat": time.Now().Unix(),
|
||||
})
|
||||
tokenString, err := token.SignedString(t.jwtSecret)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not produce signed JWT token")
|
||||
}
|
||||
req.Header.Set("Authorization", "Bearer "+tokenString)
|
||||
return t.underlyingTransport.RoundTrip(req)
|
||||
}
|
||||
53
beacon-chain/powchain/engine-api-client/v1/auth_test.go
Normal file
53
beacon-chain/powchain/engine-api-client/v1/auth_test.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/golang-jwt/jwt"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/testing/require"
|
||||
)
|
||||
|
||||
func TestJWTAuthTransport(t *testing.T) {
|
||||
secret := bytesutil.PadTo([]byte("foo"), 32)
|
||||
authTransport := &jwtTransport{
|
||||
underlyingTransport: http.DefaultTransport,
|
||||
jwtSecret: secret,
|
||||
}
|
||||
client := &http.Client{
|
||||
Timeout: DefaultTimeout,
|
||||
Transport: authTransport,
|
||||
}
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
reqToken := r.Header.Get("Authorization")
|
||||
splitToken := strings.Split(reqToken, "Bearer")
|
||||
// The format should be `Bearer ${token}`.
|
||||
require.Equal(t, 2, len(splitToken))
|
||||
reqToken = strings.TrimSpace(splitToken[1])
|
||||
token, err := jwt.Parse(reqToken, func(token *jwt.Token) (interface{}, error) {
|
||||
// We should be doing HMAC signing.
|
||||
_, ok := token.Method.(*jwt.SigningMethodHMAC)
|
||||
require.Equal(t, true, ok)
|
||||
return secret, nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, true, token.Valid)
|
||||
claims, ok := token.Claims.(jwt.MapClaims)
|
||||
require.Equal(t, true, ok)
|
||||
item, ok := claims["iat"]
|
||||
require.Equal(t, true, ok)
|
||||
iat, ok := item.(float64)
|
||||
require.Equal(t, true, ok)
|
||||
issuedAt := time.Unix(int64(iat), 0)
|
||||
// The claims should have an "iat" field (issued at) that is at most, 5 seconds ago.
|
||||
since := time.Since(issuedAt)
|
||||
require.Equal(t, true, since <= time.Second*5)
|
||||
}))
|
||||
defer srv.Close()
|
||||
_, err := client.Get(srv.URL)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
@@ -73,6 +73,11 @@ func New(ctx context.Context, endpoint string, opts ...Option) (*Client, error)
|
||||
c := &Client{
|
||||
cfg: defaultConfig(),
|
||||
}
|
||||
for _, opt := range opts {
|
||||
if err := opt(c); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
switch u.Scheme {
|
||||
case "http", "https":
|
||||
c.rpc, err = rpc.DialHTTPWithClient(endpoint, c.cfg.httpClient)
|
||||
@@ -84,11 +89,6 @@ func New(ctx context.Context, endpoint string, opts ...Option) (*Client, error)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, opt := range opts {
|
||||
if err := opt(c); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ func (c *Client) GetPayload(ctx context.Context, payloadId [8]byte) (*pb.Executi
|
||||
func (c *Client) ExchangeTransitionConfiguration(
|
||||
ctx context.Context, cfg *pb.TransitionConfiguration,
|
||||
) (*pb.TransitionConfiguration, error) {
|
||||
// Terminal block number should be set to 0
|
||||
// We set terminal block number to 0 as the parameter is not set on the consensus layer.
|
||||
zeroBigNum := big.NewInt(0)
|
||||
cfg.TerminalBlockNumber = zeroBigNum.Bytes()
|
||||
result := &pb.TransitionConfiguration{}
|
||||
|
||||
@@ -563,7 +563,7 @@ func fixtures() map[string]interface{} {
|
||||
ReceiptsRoot: receiptsRoot,
|
||||
LogsBloom: logsBloom,
|
||||
Difficulty: bytesutil.PadTo([]byte("1"), fieldparams.RootLength),
|
||||
TotalDifficulty: bytesutil.PadTo([]byte("2"), fieldparams.RootLength),
|
||||
TotalDifficulty: "2",
|
||||
GasLimit: 3,
|
||||
GasUsed: 4,
|
||||
Timestamp: 5,
|
||||
|
||||
@@ -19,11 +19,21 @@ func defaultConfig() *config {
|
||||
}
|
||||
}
|
||||
|
||||
// WithHTTPClient allows setting a custom HTTP client
|
||||
// for the API connection.
|
||||
func WithHTTPClient(httpClient *http.Client) Option {
|
||||
// WithJWTSecret allows setting a JWT secret for authenticating
|
||||
// the client via HTTP connections.
|
||||
func WithJWTSecret(secret []byte) Option {
|
||||
return func(c *Client) error {
|
||||
c.cfg.httpClient = httpClient
|
||||
if len(secret) == 0 {
|
||||
return nil
|
||||
}
|
||||
authTransport := &jwtTransport{
|
||||
underlyingTransport: http.DefaultTransport,
|
||||
jwtSecret: secret,
|
||||
}
|
||||
c.cfg.httpClient = &http.Client{
|
||||
Timeout: DefaultTimeout,
|
||||
Transport: authTransport,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -428,27 +428,27 @@ func (s *Service) requestBatchedHeadersAndLogs(ctx context.Context) error {
|
||||
}
|
||||
|
||||
func (s *Service) retrieveBlockHashAndTime(ctx context.Context, blkNum *big.Int) ([32]byte, uint64, error) {
|
||||
hash, err := s.BlockHashByHeight(ctx, blkNum)
|
||||
bHash, err := s.BlockHashByHeight(ctx, blkNum)
|
||||
if err != nil {
|
||||
return [32]byte{}, 0, errors.Wrap(err, "could not get eth1 block hash")
|
||||
}
|
||||
if hash == [32]byte{} {
|
||||
if bHash == [32]byte{} {
|
||||
return [32]byte{}, 0, errors.Wrap(err, "got empty block hash")
|
||||
}
|
||||
timeStamp, err := s.BlockTimeByHeight(ctx, blkNum)
|
||||
if err != nil {
|
||||
return [32]byte{}, 0, errors.Wrap(err, "could not get block timestamp")
|
||||
}
|
||||
return hash, timeStamp, nil
|
||||
return bHash, timeStamp, nil
|
||||
}
|
||||
|
||||
// checkBlockNumberForChainStart checks the given block number for if chainstart has occurred.
|
||||
func (s *Service) checkBlockNumberForChainStart(ctx context.Context, blkNum *big.Int) error {
|
||||
hash, timeStamp, err := s.retrieveBlockHashAndTime(ctx, blkNum)
|
||||
bHash, timeStamp, err := s.retrieveBlockHashAndTime(ctx, blkNum)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.checkForChainstart(ctx, hash, blkNum, timeStamp)
|
||||
s.checkForChainstart(ctx, bHash, blkNum, timeStamp)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -333,7 +333,7 @@ func TestProcessETH2GenesisLog(t *testing.T) {
|
||||
err = web3Service.ProcessETH1Block(context.Background(), big.NewInt(int64(logs[len(logs)-1].BlockNumber)))
|
||||
require.NoError(t, err)
|
||||
|
||||
cachedDeposits := web3Service.ChainStartDeposits()
|
||||
cachedDeposits := web3Service.chainStartData.ChainstartDeposits
|
||||
require.Equal(t, depositsReqForChainStart, len(cachedDeposits))
|
||||
|
||||
// Receive the chain started event.
|
||||
@@ -425,7 +425,7 @@ func TestProcessETH2GenesisLog_CorrectNumOfDeposits(t *testing.T) {
|
||||
err = web3Service.processPastLogs(context.Background())
|
||||
require.NoError(t, err)
|
||||
|
||||
cachedDeposits := web3Service.ChainStartDeposits()
|
||||
cachedDeposits := web3Service.chainStartData.ChainstartDeposits
|
||||
requiredDepsForChainstart := depositsReqForChainStart + depositOffset
|
||||
require.Equal(t, requiredDepsForChainstart, len(cachedDeposits), "Did not cache the chain start deposits correctly")
|
||||
|
||||
@@ -529,7 +529,7 @@ func TestProcessETH2GenesisLog_LargePeriodOfNoLogs(t *testing.T) {
|
||||
err = web3Service.processPastLogs(context.Background())
|
||||
require.NoError(t, err)
|
||||
|
||||
cachedDeposits := web3Service.ChainStartDeposits()
|
||||
cachedDeposits := web3Service.chainStartData.ChainstartDeposits
|
||||
require.Equal(t, totalNumOfDeposits, len(cachedDeposits), "Did not cache the chain start deposits correctly")
|
||||
|
||||
// Receive the chain started event.
|
||||
|
||||
@@ -40,6 +40,14 @@ func WithExecutionEndpoint(endpoint string) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// WithExecutionClientJWTSecret for authenticating the execution node JSON-RPC endpoint.
|
||||
func WithExecutionClientJWTSecret(jwtSecret []byte) Option {
|
||||
return func(s *Service) error {
|
||||
s.cfg.executionEndpointJWTSecret = jwtSecret
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithDepositContractAddress for the deposit contract.
|
||||
func WithDepositContractAddress(addr common.Address) Option {
|
||||
return func(s *Service) error {
|
||||
|
||||
@@ -81,7 +81,6 @@ var (
|
||||
// ChainStartFetcher retrieves information pertaining to the chain start event
|
||||
// of the beacon chain for usage across various services.
|
||||
type ChainStartFetcher interface {
|
||||
ChainStartDeposits() []*ethpb.Deposit
|
||||
ChainStartEth1Data() *ethpb.Eth1Data
|
||||
PreGenesisState() state.BeaconState
|
||||
ClearPreGenesisData()
|
||||
@@ -128,17 +127,18 @@ type RPCClient interface {
|
||||
|
||||
// config defines a config struct for dependencies into the service.
|
||||
type config struct {
|
||||
depositContractAddr common.Address
|
||||
beaconDB db.HeadAccessDatabase
|
||||
depositCache *depositcache.DepositCache
|
||||
stateNotifier statefeed.Notifier
|
||||
stateGen *stategen.State
|
||||
eth1HeaderReqLimit uint64
|
||||
beaconNodeStatsUpdater BeaconNodeStatsUpdater
|
||||
httpEndpoints []network.Endpoint
|
||||
executionEndpoint string
|
||||
currHttpEndpoint network.Endpoint
|
||||
finalizedStateAtStartup state.BeaconState
|
||||
depositContractAddr common.Address
|
||||
beaconDB db.HeadAccessDatabase
|
||||
depositCache *depositcache.DepositCache
|
||||
stateNotifier statefeed.Notifier
|
||||
stateGen *stategen.State
|
||||
eth1HeaderReqLimit uint64
|
||||
beaconNodeStatsUpdater BeaconNodeStatsUpdater
|
||||
httpEndpoints []network.Endpoint
|
||||
executionEndpoint string
|
||||
executionEndpointJWTSecret []byte
|
||||
currHttpEndpoint network.Endpoint
|
||||
finalizedStateAtStartup state.BeaconState
|
||||
}
|
||||
|
||||
// Service fetches important information about the canonical
|
||||
@@ -271,12 +271,6 @@ func (s *Service) Stop() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ChainStartDeposits returns a slice of validator deposit data processed
|
||||
// by the deposit contract and cached in the powchain service.
|
||||
func (s *Service) ChainStartDeposits() []*ethpb.Deposit {
|
||||
return s.chainStartData.ChainstartDeposits
|
||||
}
|
||||
|
||||
// ClearPreGenesisData clears out the stored chainstart deposits and beacon state.
|
||||
func (s *Service) ClearPreGenesisData() {
|
||||
s.chainStartData.ChainstartDeposits = []*ethpb.Deposit{}
|
||||
@@ -382,45 +376,6 @@ func (s *Service) ETH1ConnectionErrors() []error {
|
||||
return errs
|
||||
}
|
||||
|
||||
// DepositRoot returns the Merkle root of the latest deposit trie
|
||||
// from the ETH1.0 deposit contract.
|
||||
func (s *Service) DepositRoot() [32]byte {
|
||||
return s.depositTrie.HashTreeRoot()
|
||||
}
|
||||
|
||||
// DepositTrie returns the sparse Merkle trie used for storing
|
||||
// deposits from the ETH1.0 deposit contract.
|
||||
func (s *Service) DepositTrie() *trie.SparseMerkleTrie {
|
||||
return s.depositTrie
|
||||
}
|
||||
|
||||
// LatestBlockHeight in the ETH1.0 chain.
|
||||
func (s *Service) LatestBlockHeight() *big.Int {
|
||||
return big.NewInt(int64(s.latestEth1Data.BlockHeight))
|
||||
}
|
||||
|
||||
// LatestBlockHash in the ETH1.0 chain.
|
||||
func (s *Service) LatestBlockHash() common.Hash {
|
||||
return bytesutil.ToBytes32(s.latestEth1Data.BlockHash)
|
||||
}
|
||||
|
||||
// AreAllDepositsProcessed determines if all the logs from the deposit contract
|
||||
// are processed.
|
||||
func (s *Service) AreAllDepositsProcessed() (bool, error) {
|
||||
s.processingLock.RLock()
|
||||
defer s.processingLock.RUnlock()
|
||||
countByte, err := s.depositContractCaller.GetDepositCount(&bind.CallOpts{})
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "could not get deposit count")
|
||||
}
|
||||
count := bytesutil.FromBytes8(countByte)
|
||||
deposits := s.cfg.depositCache.AllDeposits(s.ctx, nil)
|
||||
if count != uint64(len(deposits)) {
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// refers to the latest eth1 block which follows the condition: eth1_timestamp +
|
||||
// SECONDS_PER_ETH1_BLOCK * ETH1_FOLLOW_DISTANCE <= current_unix_time
|
||||
func (s *Service) followBlockHeight(_ context.Context) (uint64, error) {
|
||||
@@ -1104,7 +1059,10 @@ func (s *Service) initializeEngineAPIClient(ctx context.Context) error {
|
||||
if s.cfg.executionEndpoint == "" {
|
||||
return nil
|
||||
}
|
||||
client, err := engine.New(ctx, s.cfg.executionEndpoint)
|
||||
opts := []engine.Option{
|
||||
engine.WithJWTSecret(s.cfg.executionEndpointJWTSecret),
|
||||
}
|
||||
client, err := engine.New(ctx, s.cfg.executionEndpoint, opts...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@ go_library(
|
||||
"//beacon-chain/powchain/types:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//beacon-chain/state/v1:go_default_library",
|
||||
"//container/trie:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//accounts/abi/bind/backends:go_default_library",
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/powchain/types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
|
||||
"github.com/prysmaticlabs/prysm/container/trie"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
@@ -25,11 +24,6 @@ func (_ *FaultyMockPOWChain) Eth2GenesisPowchainInfo() (uint64, *big.Int) {
|
||||
return 0, big.NewInt(0)
|
||||
}
|
||||
|
||||
// LatestBlockHeight --
|
||||
func (_ *FaultyMockPOWChain) LatestBlockHeight() *big.Int {
|
||||
return big.NewInt(0)
|
||||
}
|
||||
|
||||
// BlockExists --
|
||||
func (f *FaultyMockPOWChain) BlockExists(_ context.Context, _ common.Hash) (bool, *big.Int, error) {
|
||||
if f.HashesByHeight == nil {
|
||||
@@ -54,21 +48,6 @@ func (_ *FaultyMockPOWChain) BlockByTimestamp(_ context.Context, _ uint64) (*typ
|
||||
return &types.HeaderInfo{Number: big.NewInt(0)}, nil
|
||||
}
|
||||
|
||||
// DepositRoot --
|
||||
func (_ *FaultyMockPOWChain) DepositRoot() [32]byte {
|
||||
return [32]byte{}
|
||||
}
|
||||
|
||||
// DepositTrie --
|
||||
func (_ *FaultyMockPOWChain) DepositTrie() *trie.SparseMerkleTrie {
|
||||
return &trie.SparseMerkleTrie{}
|
||||
}
|
||||
|
||||
// ChainStartDeposits --
|
||||
func (_ *FaultyMockPOWChain) ChainStartDeposits() []*ethpb.Deposit {
|
||||
return []*ethpb.Deposit{}
|
||||
}
|
||||
|
||||
// ChainStartEth1Data --
|
||||
func (_ *FaultyMockPOWChain) ChainStartEth1Data() *ethpb.Eth1Data {
|
||||
return ðpb.Eth1Data{}
|
||||
|
||||
@@ -16,7 +16,6 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/async/event"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/powchain/types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/container/trie"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
)
|
||||
@@ -58,11 +57,6 @@ func (m *POWChain) Eth2GenesisPowchainInfo() (uint64, *big.Int) {
|
||||
return uint64(GenesisTime), blk
|
||||
}
|
||||
|
||||
// DepositTrie --
|
||||
func (_ *POWChain) DepositTrie() *trie.SparseMerkleTrie {
|
||||
return &trie.SparseMerkleTrie{}
|
||||
}
|
||||
|
||||
// BlockExists --
|
||||
func (m *POWChain) BlockExists(_ context.Context, hash common.Hash) (bool, *big.Int, error) {
|
||||
// Reverse the map of heights by hash.
|
||||
@@ -107,17 +101,6 @@ func (m *POWChain) BlockByTimestamp(_ context.Context, time uint64) (*types.Head
|
||||
return &types.HeaderInfo{Number: chosenNumber, Time: chosenTime}, nil
|
||||
}
|
||||
|
||||
// DepositRoot --
|
||||
func (_ *POWChain) DepositRoot() [32]byte {
|
||||
root := []byte("depositroot")
|
||||
return bytesutil.ToBytes32(root)
|
||||
}
|
||||
|
||||
// ChainStartDeposits --
|
||||
func (_ *POWChain) ChainStartDeposits() []*ethpb.Deposit {
|
||||
return []*ethpb.Deposit{}
|
||||
}
|
||||
|
||||
// ChainStartEth1Data --
|
||||
func (m *POWChain) ChainStartEth1Data() *ethpb.Eth1Data {
|
||||
return m.Eth1Data
|
||||
|
||||
@@ -22,6 +22,7 @@ go_library(
|
||||
"//beacon-chain/operations/voluntaryexits:go_default_library",
|
||||
"//beacon-chain/p2p:go_default_library",
|
||||
"//beacon-chain/powchain:go_default_library",
|
||||
"//beacon-chain/powchain/engine-api-client/v1:go_default_library",
|
||||
"//beacon-chain/rpc/eth/beacon:go_default_library",
|
||||
"//beacon-chain/rpc/eth/debug:go_default_library",
|
||||
"//beacon-chain/rpc/eth/events:go_default_library",
|
||||
|
||||
@@ -15,6 +15,7 @@ go_library(
|
||||
"proposer_bellatrix.go",
|
||||
"proposer_deposits.go",
|
||||
"proposer_eth1data.go",
|
||||
"proposer_execution_payload.go",
|
||||
"proposer_phase0.go",
|
||||
"proposer_sync_aggregate.go",
|
||||
"server.go",
|
||||
@@ -40,12 +41,14 @@ go_library(
|
||||
"//beacon-chain/core/transition:go_default_library",
|
||||
"//beacon-chain/core/transition/interop:go_default_library",
|
||||
"//beacon-chain/core/validators:go_default_library",
|
||||
"//beacon-chain/db:go_default_library",
|
||||
"//beacon-chain/operations/attestations:go_default_library",
|
||||
"//beacon-chain/operations/slashings:go_default_library",
|
||||
"//beacon-chain/operations/synccommittee:go_default_library",
|
||||
"//beacon-chain/operations/voluntaryexits:go_default_library",
|
||||
"//beacon-chain/p2p:go_default_library",
|
||||
"//beacon-chain/powchain:go_default_library",
|
||||
"//beacon-chain/powchain/engine-api-client/v1:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//beacon-chain/state/stategen:go_default_library",
|
||||
"//beacon-chain/sync:go_default_library",
|
||||
@@ -71,7 +74,9 @@ go_library(
|
||||
"//runtime/version:go_default_library",
|
||||
"//time:go_default_library",
|
||||
"//time/slots:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
|
||||
"@com_github_ferranbt_fastssz//:go_default_library",
|
||||
"@com_github_holiman_uint256//:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
|
||||
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
|
||||
@@ -154,6 +159,8 @@ go_test(
|
||||
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//hooks/test:go_default_library",
|
||||
"@org_golang_google_grpc//codes:go_default_library",
|
||||
"@org_golang_google_grpc//status:go_default_library",
|
||||
"@org_golang_google_protobuf//proto:go_default_library",
|
||||
"@org_golang_google_protobuf//types/known/emptypb:go_default_library",
|
||||
],
|
||||
|
||||
@@ -28,6 +28,11 @@ func (vs *Server) SubmitAggregateSelectionProof(ctx context.Context, req *ethpb.
|
||||
return nil, status.Errorf(codes.Unavailable, "Syncing to latest head, not ready to respond")
|
||||
}
|
||||
|
||||
// An optimistic validator MUST NOT participate in attestation. (i.e., sign across the DOMAIN_BEACON_ATTESTER, DOMAIN_SELECTION_PROOF or DOMAIN_AGGREGATE_AND_PROOF domains).
|
||||
//if err := vs.optimisticStatus(ctx); err != nil {
|
||||
// return nil, err
|
||||
//}
|
||||
|
||||
st, err := vs.HeadFetcher.HeadState(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not determine head state: %v", err)
|
||||
|
||||
@@ -37,6 +37,11 @@ func (vs *Server) GetAttestationData(ctx context.Context, req *ethpb.Attestation
|
||||
return nil, status.Errorf(codes.Unavailable, "Syncing to latest head, not ready to respond")
|
||||
}
|
||||
|
||||
// An optimistic validator MUST NOT participate in attestation. (i.e., sign across the DOMAIN_BEACON_ATTESTER, DOMAIN_SELECTION_PROOF or DOMAIN_AGGREGATE_AND_PROOF domains).
|
||||
//if err := vs.optimisticStatus(ctx); err != nil {
|
||||
// return nil, err
|
||||
//}
|
||||
|
||||
if err := helpers.ValidateAttestationTime(req.Slot, vs.TimeFetcher.GenesisTime(),
|
||||
params.BeaconNetworkConfig().MaximumGossipClockDisparity); err != nil {
|
||||
return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("invalid request: %v", err))
|
||||
|
||||
@@ -26,6 +26,8 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/testing/util"
|
||||
prysmTime "github.com/prysmaticlabs/prysm/time"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
@@ -169,6 +171,18 @@ func TestGetAttestationData_SyncNotReady(t *testing.T) {
|
||||
assert.ErrorContains(t, "Syncing to latest head", err)
|
||||
}
|
||||
|
||||
func TestGetAttestationData_Optimistic(t *testing.T) {
|
||||
as := &Server{
|
||||
SyncChecker: &mockSync.Sync{},
|
||||
HeadFetcher: &mock.ChainService{Optimistic: true},
|
||||
}
|
||||
_, err := as.GetAttestationData(context.Background(), ðpb.AttestationDataRequest{})
|
||||
s, ok := status.FromError(err)
|
||||
require.Equal(t, true, ok)
|
||||
require.DeepEqual(t, codes.Unavailable, s.Code())
|
||||
require.ErrorContains(t, " The node is currently optimistic and cannot serve validators", err)
|
||||
}
|
||||
|
||||
func TestAttestationDataAtSlot_HandlesFarAwayJustifiedEpoch(t *testing.T) {
|
||||
// Scenario:
|
||||
//
|
||||
@@ -317,6 +331,7 @@ func TestServer_GetAttestationData_InvalidRequestSlot(t *testing.T) {
|
||||
offset := int64(slot.Mul(params.BeaconConfig().SecondsPerSlot))
|
||||
attesterServer := &Server{
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
HeadFetcher: &mock.ChainService{},
|
||||
TimeFetcher: &mock.ChainService{Genesis: time.Now().Add(time.Duration(-1*offset) * time.Second)},
|
||||
}
|
||||
|
||||
|
||||
@@ -48,6 +48,11 @@ func (vs *Server) GetBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (
|
||||
return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Altair{Altair: blk}}, nil
|
||||
}
|
||||
|
||||
// An optimistic validator MUST NOT produce a block (i.e., sign across the DOMAIN_BEACON_PROPOSER domain).
|
||||
//if err := vs.optimisticStatus(ctx); err != nil {
|
||||
// return nil, err
|
||||
//}
|
||||
|
||||
blk, err := vs.getBellatrixBeaconBlock(ctx, req)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not fetch Bellatrix beacon block: %v", err)
|
||||
|
||||
@@ -89,7 +89,7 @@ func (a proposerAtts) filter(ctx context.Context, st state.BeaconState) (propose
|
||||
switch st.Version() {
|
||||
case version.Phase0:
|
||||
attestationProcessor = blocks.ProcessAttestationNoVerifySignature
|
||||
case version.Altair:
|
||||
case version.Altair, version.Bellatrix:
|
||||
// Use a wrapper here, as go needs strong typing for the function signature.
|
||||
attestationProcessor = func(ctx context.Context, st state.BeaconState, attestation *ethpb.Attestation) (state.BeaconState, error) {
|
||||
totalBalance, err := helpers.TotalActiveBalance(st)
|
||||
|
||||
@@ -5,11 +5,10 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/transition/interop"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
enginev1 "github.com/prysmaticlabs/prysm/proto/engine/v1"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func (vs *Server) getBellatrixBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (*ethpb.BeaconBlockBellatrix, error) {
|
||||
@@ -18,6 +17,18 @@ func (vs *Server) getBellatrixBeaconBlock(ctx context.Context, req *ethpb.BlockR
|
||||
return nil, err
|
||||
}
|
||||
|
||||
payload, err := vs.getExecutionPayload(ctx, req.Slot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
log.WithFields(logrus.Fields{
|
||||
"hash": fmt.Sprintf("%#x", payload.BlockHash),
|
||||
"parentHash": fmt.Sprintf("%#x", payload.ParentHash),
|
||||
"number": payload.BlockNumber,
|
||||
"txCount": len(payload.Transactions),
|
||||
}).Info("Received payload")
|
||||
|
||||
blk := ðpb.BeaconBlockBellatrix{
|
||||
Slot: altairBlk.Slot,
|
||||
ProposerIndex: altairBlk.ProposerIndex,
|
||||
@@ -33,16 +44,7 @@ func (vs *Server) getBellatrixBeaconBlock(ctx context.Context, req *ethpb.BlockR
|
||||
Deposits: altairBlk.Body.Deposits,
|
||||
VoluntaryExits: altairBlk.Body.VoluntaryExits,
|
||||
SyncAggregate: altairBlk.Body.SyncAggregate,
|
||||
ExecutionPayload: &enginev1.ExecutionPayload{
|
||||
ParentHash: make([]byte, fieldparams.RootLength),
|
||||
FeeRecipient: make([]byte, fieldparams.FeeRecipientLength),
|
||||
StateRoot: make([]byte, fieldparams.RootLength),
|
||||
ReceiptsRoot: make([]byte, fieldparams.RootLength),
|
||||
LogsBloom: make([]byte, fieldparams.LogsBloomLength),
|
||||
Random: make([]byte, fieldparams.RootLength),
|
||||
BaseFeePerGas: make([]byte, fieldparams.RootLength),
|
||||
BlockHash: make([]byte, fieldparams.RootLength),
|
||||
}, // TODO(9853) Insert real execution payload.
|
||||
ExecutionPayload: payload,
|
||||
},
|
||||
}
|
||||
// Compute state root with the newly constructed block.
|
||||
|
||||
@@ -0,0 +1,278 @@
|
||||
package validator
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/holiman/uint256"
|
||||
"github.com/pkg/errors"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/time"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/transition"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
enginev1 "github.com/prysmaticlabs/prysm/proto/engine/v1"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// This returns the execution payload of a given slot. The function has full awareness of pre and post merge.
|
||||
// Payload is computed given the respected time of merge.
|
||||
//
|
||||
// Spec code:
|
||||
// def prepare_execution_payload(state: BeaconState,
|
||||
// pow_chain: Dict[Hash32, PowBlock],
|
||||
// finalized_block_hash: Hash32,
|
||||
// fee_recipient: ExecutionAddress,
|
||||
// execution_engine: ExecutionEngine) -> Optional[PayloadId]:
|
||||
// if not is_merge_complete(state):
|
||||
// is_terminal_block_hash_set = TERMINAL_BLOCK_HASH != Hash32()
|
||||
// is_activation_epoch_reached = get_current_epoch(state.slot) >= TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH
|
||||
// if is_terminal_block_hash_set and not is_activation_epoch_reached:
|
||||
// # Terminal block hash is set but activation epoch is not yet reached, no prepare payload call is needed
|
||||
// return None
|
||||
//
|
||||
// terminal_pow_block = get_terminal_pow_block(pow_chain)
|
||||
// if terminal_pow_block is None:
|
||||
// # Pre-merge, no prepare payload call is needed
|
||||
// return None
|
||||
// # Signify merge via producing on top of the terminal PoW block
|
||||
// parent_hash = terminal_pow_block.block_hash
|
||||
// else:
|
||||
// # Post-merge, normal payload
|
||||
// parent_hash = state.latest_execution_payload_header.block_hash
|
||||
//
|
||||
// # Set the forkchoice head and initiate the payload build process
|
||||
// payload_attributes = PayloadAttributes(
|
||||
// timestamp=compute_timestamp_at_slot(state, state.slot),
|
||||
// random=get_randao_mix(state, get_current_epoch(state)),
|
||||
// fee_recipient=fee_recipient,
|
||||
// )
|
||||
// return execution_engine.notify_forkchoice_updated(parent_hash, finalized_block_hash, payload_attributes)
|
||||
func (vs *Server) getExecutionPayload(ctx context.Context, slot types.Slot) (*enginev1.ExecutionPayload, error) {
|
||||
// TODO_MERGE: Reuse the same head state as in building phase0 block attestation.
|
||||
st, err := vs.HeadFetcher.HeadState(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
st, err = transition.ProcessSlots(ctx, st, slot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var parentHash []byte
|
||||
var hasTerminalBlock bool
|
||||
complete, err := blocks.MergeTransitionComplete(st)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !complete {
|
||||
if bytesutil.ToBytes32(params.BeaconConfig().TerminalBlockHash.Bytes()) != [32]byte{} {
|
||||
// `TERMINAL_BLOCK_HASH` is used as an override, the activation epoch must be reached.
|
||||
isActivationEpochReached := params.BeaconConfig().TerminalBlockHashActivationEpoch <= slots.ToEpoch(slot)
|
||||
if !isActivationEpochReached {
|
||||
return emptyPayload(), nil
|
||||
}
|
||||
}
|
||||
|
||||
parentHash, hasTerminalBlock, err = vs.getTerminalBlockHash(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !hasTerminalBlock {
|
||||
// No terminal block signals this is pre merge, empty payload is used.
|
||||
return emptyPayload(), nil
|
||||
}
|
||||
// Terminal block found signals production on top of terminal PoW block.
|
||||
} else {
|
||||
// Post merge, normal payload is used.
|
||||
header, err := st.LatestExecutionPayloadHeader()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
parentHash = header.BlockHash
|
||||
}
|
||||
|
||||
t, err := slots.ToTime(st.GenesisTime(), slot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
random, err := helpers.RandaoMix(st, time.CurrentEpoch(st))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
finalizedBlock, err := vs.BeaconDB.Block(ctx, bytesutil.ToBytes32(st.FinalizedCheckpoint().Root))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
finalizedBlockHash := params.BeaconConfig().ZeroHash[:]
|
||||
if finalizedBlock != nil && finalizedBlock.Version() == version.Bellatrix {
|
||||
finalizedPayload, err := finalizedBlock.Block().Body().ExecutionPayload()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
finalizedBlockHash = finalizedPayload.BlockHash
|
||||
}
|
||||
|
||||
f := &enginev1.ForkchoiceState{
|
||||
HeadBlockHash: parentHash,
|
||||
SafeBlockHash: parentHash,
|
||||
FinalizedBlockHash: finalizedBlockHash,
|
||||
}
|
||||
p := &enginev1.PayloadAttributes{
|
||||
Timestamp: uint64(t.Unix()),
|
||||
Random: random,
|
||||
SuggestedFeeRecipient: params.BeaconConfig().FeeRecipient.Bytes(),
|
||||
}
|
||||
res, err := vs.ExecutionEngineCaller.ForkchoiceUpdated(ctx, f, p)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not prepare payload")
|
||||
}
|
||||
log.WithFields(logrus.Fields{
|
||||
"status:": res.Status.Status,
|
||||
"hash:": fmt.Sprintf("%#x", f.HeadBlockHash),
|
||||
}).Info("Successfully called forkchoiceUpdated with attribute")
|
||||
|
||||
if res == nil || res.PayloadId == nil {
|
||||
return nil, errors.New("forkchoice returned nil")
|
||||
}
|
||||
|
||||
log.WithFields(logrus.Fields{
|
||||
"id": fmt.Sprintf("%#x", &res.PayloadId),
|
||||
"slot": slot,
|
||||
"hash": fmt.Sprintf("%#x", parentHash),
|
||||
}).Info("Received payload ID")
|
||||
var id [8]byte
|
||||
copy(id[:], res.PayloadId[:])
|
||||
return vs.ExecutionEngineCaller.GetPayload(ctx, id)
|
||||
}
|
||||
|
||||
// This returns the valid terminal block hash with an existence bool value.
|
||||
//
|
||||
// Spec code:
|
||||
// def get_terminal_pow_block(pow_chain: Dict[Hash32, PowBlock]) -> Optional[PowBlock]:
|
||||
// if TERMINAL_BLOCK_HASH != Hash32():
|
||||
// # Terminal block hash override takes precedence over terminal total difficulty
|
||||
// if TERMINAL_BLOCK_HASH in pow_chain:
|
||||
// return pow_chain[TERMINAL_BLOCK_HASH]
|
||||
// else:
|
||||
// return None
|
||||
//
|
||||
// return get_pow_block_at_terminal_total_difficulty(pow_chain)
|
||||
func (vs *Server) getTerminalBlockHash(ctx context.Context) ([]byte, bool, error) {
|
||||
terminalBlockHash := params.BeaconConfig().TerminalBlockHash
|
||||
// Terminal block hash override takes precedence over terminal total difficult.
|
||||
if params.BeaconConfig().TerminalBlockHash != params.BeaconConfig().ZeroHash {
|
||||
e, _, err := vs.Eth1BlockFetcher.BlockExists(ctx, terminalBlockHash)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
if !e {
|
||||
return nil, false, nil
|
||||
}
|
||||
|
||||
return terminalBlockHash.Bytes(), true, nil
|
||||
}
|
||||
|
||||
return vs.getPowBlockHashAtTerminalTotalDifficulty(ctx)
|
||||
}
|
||||
|
||||
// This returns the valid terminal block hash based on total difficulty.
|
||||
//
|
||||
// Spec code:
|
||||
// def get_pow_block_at_terminal_total_difficulty(pow_chain: Dict[Hash32, PowBlock]) -> Optional[PowBlock]:
|
||||
// # `pow_chain` abstractly represents all blocks in the PoW chain
|
||||
// for block in pow_chain:
|
||||
// parent = pow_chain[block.parent_hash]
|
||||
// block_reached_ttd = block.total_difficulty >= TERMINAL_TOTAL_DIFFICULTY
|
||||
// parent_reached_ttd = parent.total_difficulty >= TERMINAL_TOTAL_DIFFICULTY
|
||||
// if block_reached_ttd and not parent_reached_ttd:
|
||||
// return block
|
||||
//
|
||||
// return None
|
||||
func (vs *Server) getPowBlockHashAtTerminalTotalDifficulty(ctx context.Context) ([]byte, bool, error) {
|
||||
ttd := new(big.Int)
|
||||
ttd.SetString(params.BeaconConfig().TerminalTotalDifficulty, 10)
|
||||
terminalTotalDifficulty, overflows := uint256.FromBig(ttd)
|
||||
if overflows {
|
||||
return nil, false, errors.New("could not convert terminal total difficulty to uint256")
|
||||
}
|
||||
blk, err := vs.ExecutionEngineCaller.LatestExecutionBlock(ctx)
|
||||
if err != nil {
|
||||
return nil, false, errors.Wrap(err, "could not get latest execution block")
|
||||
}
|
||||
log.WithFields(logrus.Fields{
|
||||
"number": blk.Number,
|
||||
"hash": fmt.Sprintf("%#x", blk.Hash),
|
||||
"td": blk.TotalDifficulty,
|
||||
}).Info("Retrieving latest execution block")
|
||||
|
||||
for {
|
||||
transitionBlkTDBig, err := hexutil.DecodeBig(blk.TotalDifficulty)
|
||||
if err != nil {
|
||||
return nil, false, errors.Wrap(err, "could not decode transition total difficulty")
|
||||
}
|
||||
currentTotalDifficulty, overflows := uint256.FromBig(transitionBlkTDBig)
|
||||
if overflows {
|
||||
return nil, false, errors.New("total difficulty overflowed")
|
||||
}
|
||||
blockReachedTTD := currentTotalDifficulty.Cmp(terminalTotalDifficulty) >= 0
|
||||
parentHash := bytesutil.ToBytes32(blk.ParentHash)
|
||||
if len(blk.ParentHash) == 0 || parentHash == params.BeaconConfig().ZeroHash {
|
||||
return nil, false, nil
|
||||
}
|
||||
parentBlk, err := vs.ExecutionEngineCaller.ExecutionBlockByHash(ctx, parentHash)
|
||||
if err != nil {
|
||||
return nil, false, errors.Wrap(err, "could not get parent execution block")
|
||||
}
|
||||
log.WithFields(logrus.Fields{
|
||||
"number": parentBlk.Number,
|
||||
"hash": fmt.Sprintf("%#x", parentBlk.Hash),
|
||||
"td": parentBlk.TotalDifficulty,
|
||||
}).Info("Retrieving parent execution block")
|
||||
|
||||
if blockReachedTTD {
|
||||
parentTDBig, err := hexutil.DecodeBig(parentBlk.TotalDifficulty)
|
||||
if err != nil {
|
||||
return nil, false, errors.Wrap(err, "could not decode transition total difficulty")
|
||||
}
|
||||
parentTotalDifficulty, overflows := uint256.FromBig(parentTDBig)
|
||||
if overflows {
|
||||
return nil, false, errors.New("total difficulty overflowed")
|
||||
}
|
||||
parentReachedTTD := parentTotalDifficulty.Cmp(terminalTotalDifficulty) >= 0
|
||||
if !parentReachedTTD {
|
||||
log.WithFields(logrus.Fields{
|
||||
"number": blk.Number,
|
||||
"hash": fmt.Sprintf("%#x", blk.Hash),
|
||||
"td": blk.TotalDifficulty,
|
||||
"parentTd": parentBlk.TotalDifficulty,
|
||||
"ttd": terminalTotalDifficulty,
|
||||
}).Info("Retrieved terminal block hash")
|
||||
return blk.Hash, true, nil
|
||||
}
|
||||
}
|
||||
blk = parentBlk
|
||||
}
|
||||
}
|
||||
|
||||
func emptyPayload() *enginev1.ExecutionPayload {
|
||||
return &enginev1.ExecutionPayload{
|
||||
ParentHash: make([]byte, fieldparams.RootLength),
|
||||
FeeRecipient: make([]byte, fieldparams.FeeRecipientLength),
|
||||
StateRoot: make([]byte, fieldparams.RootLength),
|
||||
ReceiptsRoot: make([]byte, fieldparams.RootLength),
|
||||
LogsBloom: make([]byte, fieldparams.LogsBloomLength),
|
||||
Random: make([]byte, fieldparams.RootLength),
|
||||
BaseFeePerGas: make([]byte, fieldparams.RootLength),
|
||||
BlockHash: make([]byte, fieldparams.RootLength),
|
||||
}
|
||||
}
|
||||
@@ -39,6 +39,8 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/testing/util"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
@@ -209,116 +211,79 @@ func TestProposer_GetBlock_AddsUnaggregatedAtts(t *testing.T) {
|
||||
assert.Equal(t, false, hasUnaggregatedAtt, "Expected block to not have unaggregated attestation")
|
||||
}
|
||||
|
||||
func TestProposer_ProposeBlock_Phase0_OK(t *testing.T) {
|
||||
db := dbutil.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
params.SetupTestConfigCleanup(t)
|
||||
params.OverrideBeaconConfig(params.MainnetConfig())
|
||||
|
||||
genesis := util.NewBeaconBlock()
|
||||
require.NoError(t, db.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(genesis)), "Could not save genesis block")
|
||||
|
||||
numDeposits := uint64(64)
|
||||
beaconState, _ := util.DeterministicGenesisState(t, numDeposits)
|
||||
bsRoot, err := beaconState.HashTreeRoot(ctx)
|
||||
require.NoError(t, err)
|
||||
genesisRoot, err := genesis.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, db.SaveState(ctx, beaconState, genesisRoot), "Could not save genesis state")
|
||||
|
||||
c := &mock.ChainService{Root: bsRoot[:], State: beaconState}
|
||||
proposerServer := &Server{
|
||||
ChainStartFetcher: &mockPOW.POWChain{},
|
||||
Eth1InfoFetcher: &mockPOW.POWChain{},
|
||||
Eth1BlockFetcher: &mockPOW.POWChain{},
|
||||
BlockReceiver: c,
|
||||
HeadFetcher: c,
|
||||
BlockNotifier: c.BlockNotifier(),
|
||||
P2P: mockp2p.NewTestP2P(t),
|
||||
func TestProposer_ProposeBlock_OK(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
block func([32]byte) *ethpb.GenericSignedBeaconBlock
|
||||
}{
|
||||
{
|
||||
name: "phase0",
|
||||
block: func(parent [32]byte) *ethpb.GenericSignedBeaconBlock {
|
||||
blockToPropose := util.NewBeaconBlock()
|
||||
blockToPropose.Block.Slot = 5
|
||||
blockToPropose.Block.ParentRoot = parent[:]
|
||||
blk := ðpb.GenericSignedBeaconBlock_Phase0{Phase0: blockToPropose}
|
||||
return ðpb.GenericSignedBeaconBlock{Block: blk}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "altair",
|
||||
block: func(parent [32]byte) *ethpb.GenericSignedBeaconBlock {
|
||||
blockToPropose := util.NewBeaconBlockAltair()
|
||||
blockToPropose.Block.Slot = 5
|
||||
blockToPropose.Block.ParentRoot = parent[:]
|
||||
blk := ðpb.GenericSignedBeaconBlock_Altair{Altair: blockToPropose}
|
||||
return ðpb.GenericSignedBeaconBlock{Block: blk}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "bellatrix",
|
||||
block: func(parent [32]byte) *ethpb.GenericSignedBeaconBlock {
|
||||
blockToPropose := util.NewBeaconBlockBellatrix()
|
||||
blockToPropose.Block.Slot = 5
|
||||
blockToPropose.Block.ParentRoot = parent[:]
|
||||
blk := ðpb.GenericSignedBeaconBlock_Bellatrix{Bellatrix: blockToPropose}
|
||||
return ðpb.GenericSignedBeaconBlock{Block: blk}
|
||||
},
|
||||
},
|
||||
}
|
||||
req := util.NewBeaconBlock()
|
||||
req.Block.Slot = 5
|
||||
req.Block.ParentRoot = bsRoot[:]
|
||||
require.NoError(t, db.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(req)))
|
||||
blk := ðpb.GenericSignedBeaconBlock_Phase0{Phase0: req}
|
||||
_, err = proposerServer.ProposeBeaconBlock(context.Background(), ðpb.GenericSignedBeaconBlock{Block: blk})
|
||||
assert.NoError(t, err, "Could not propose block correctly")
|
||||
}
|
||||
|
||||
func TestProposer_ProposeBlock_Altair_OK(t *testing.T) {
|
||||
db := dbutil.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
params.SetupTestConfigCleanup(t)
|
||||
params.OverrideBeaconConfig(params.MainnetConfig())
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
db := dbutil.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
params.SetupTestConfigCleanup(t)
|
||||
params.OverrideBeaconConfig(params.MainnetConfig())
|
||||
|
||||
genesis := util.NewBeaconBlock()
|
||||
require.NoError(t, db.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(genesis)), "Could not save genesis block")
|
||||
genesis := util.NewBeaconBlock()
|
||||
require.NoError(t, db.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(genesis)), "Could not save genesis block")
|
||||
|
||||
numDeposits := uint64(64)
|
||||
beaconState, _ := util.DeterministicGenesisStateAltair(t, numDeposits)
|
||||
bsRoot, err := beaconState.HashTreeRoot(ctx)
|
||||
require.NoError(t, err)
|
||||
genesisRoot, err := genesis.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, db.SaveState(ctx, beaconState, genesisRoot), "Could not save genesis state")
|
||||
numDeposits := uint64(64)
|
||||
beaconState, _ := util.DeterministicGenesisState(t, numDeposits)
|
||||
bsRoot, err := beaconState.HashTreeRoot(ctx)
|
||||
require.NoError(t, err)
|
||||
genesisRoot, err := genesis.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, db.SaveState(ctx, beaconState, genesisRoot), "Could not save genesis state")
|
||||
|
||||
c := &mock.ChainService{Root: bsRoot[:], State: beaconState}
|
||||
proposerServer := &Server{
|
||||
ChainStartFetcher: &mockPOW.POWChain{},
|
||||
Eth1InfoFetcher: &mockPOW.POWChain{},
|
||||
Eth1BlockFetcher: &mockPOW.POWChain{},
|
||||
BlockReceiver: c,
|
||||
HeadFetcher: c,
|
||||
BlockNotifier: c.BlockNotifier(),
|
||||
P2P: mockp2p.NewTestP2P(t),
|
||||
c := &mock.ChainService{Root: bsRoot[:], State: beaconState}
|
||||
proposerServer := &Server{
|
||||
ChainStartFetcher: &mockPOW.POWChain{},
|
||||
Eth1InfoFetcher: &mockPOW.POWChain{},
|
||||
Eth1BlockFetcher: &mockPOW.POWChain{},
|
||||
BlockReceiver: c,
|
||||
HeadFetcher: c,
|
||||
BlockNotifier: c.BlockNotifier(),
|
||||
P2P: mockp2p.NewTestP2P(t),
|
||||
}
|
||||
blockToPropose := tt.block(bsRoot)
|
||||
res, err := proposerServer.ProposeBeaconBlock(context.Background(), blockToPropose)
|
||||
assert.NoError(t, err, "Could not propose block correctly")
|
||||
if res == nil || len(res.BlockRoot) == 0 {
|
||||
t.Error("No block root was returned")
|
||||
}
|
||||
})
|
||||
}
|
||||
blockToPropose := util.NewBeaconBlockAltair()
|
||||
blockToPropose.Block.Slot = 5
|
||||
blockToPropose.Block.ParentRoot = bsRoot[:]
|
||||
blk := ðpb.GenericSignedBeaconBlock_Altair{Altair: blockToPropose}
|
||||
wrapped, err := wrapper.WrappedAltairSignedBeaconBlock(blockToPropose)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, db.SaveBlock(ctx, wrapped))
|
||||
_, err = proposerServer.ProposeBeaconBlock(context.Background(), ðpb.GenericSignedBeaconBlock{Block: blk})
|
||||
assert.NoError(t, err, "Could not propose block correctly")
|
||||
}
|
||||
|
||||
func TestProposer_ProposeBlock_Bellatrix_OK(t *testing.T) {
|
||||
db := dbutil.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
params.SetupTestConfigCleanup(t)
|
||||
params.OverrideBeaconConfig(params.MainnetConfig())
|
||||
|
||||
genesis := util.NewBeaconBlock()
|
||||
require.NoError(t, db.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(genesis)), "Could not save genesis block")
|
||||
|
||||
numDeposits := uint64(64)
|
||||
beaconState, _ := util.DeterministicGenesisStateBellatrix(t, numDeposits)
|
||||
bsRoot, err := beaconState.HashTreeRoot(ctx)
|
||||
require.NoError(t, err)
|
||||
genesisRoot, err := genesis.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, db.SaveState(ctx, beaconState, genesisRoot), "Could not save genesis state")
|
||||
|
||||
c := &mock.ChainService{Root: bsRoot[:], State: beaconState}
|
||||
proposerServer := &Server{
|
||||
ChainStartFetcher: &mockPOW.POWChain{},
|
||||
Eth1InfoFetcher: &mockPOW.POWChain{},
|
||||
Eth1BlockFetcher: &mockPOW.POWChain{},
|
||||
BlockReceiver: c,
|
||||
HeadFetcher: c,
|
||||
BlockNotifier: c.BlockNotifier(),
|
||||
P2P: mockp2p.NewTestP2P(t),
|
||||
}
|
||||
blockToPropose := util.NewBeaconBlockBellatrix()
|
||||
blockToPropose.Block.Slot = 5
|
||||
blockToPropose.Block.ParentRoot = bsRoot[:]
|
||||
blk := ðpb.GenericSignedBeaconBlock_Bellatrix{Bellatrix: blockToPropose}
|
||||
wrapped, err := wrapper.WrappedSignedBeaconBlock(blockToPropose)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, db.SaveBlock(ctx, wrapped))
|
||||
_, err = proposerServer.ProposeBeaconBlock(context.Background(), ðpb.GenericSignedBeaconBlock{Block: blk})
|
||||
assert.NoError(t, err, "Could not propose block correctly")
|
||||
}
|
||||
|
||||
func TestProposer_ComputeStateRoot_OK(t *testing.T) {
|
||||
@@ -2357,6 +2322,27 @@ func TestProposer_GetBeaconBlock_BellatrixEpoch(t *testing.T) {
|
||||
assert.DeepEqual(t, req.Graffiti, bellatrixBlk.Bellatrix.Body.Graffiti, "Expected block to have correct Graffiti")
|
||||
}
|
||||
|
||||
func TestProposer_GetBeaconBlock_Optimistic(t *testing.T) {
|
||||
params.SetupTestConfigCleanup(t)
|
||||
cfg := params.MainnetConfig().Copy()
|
||||
cfg.BellatrixForkEpoch = 2
|
||||
cfg.AltairForkEpoch = 1
|
||||
params.OverrideBeaconConfig(cfg)
|
||||
|
||||
bellatrixSlot, err := slots.EpochStart(params.BeaconConfig().BellatrixForkEpoch)
|
||||
require.NoError(t, err)
|
||||
|
||||
proposerServer := &Server{HeadFetcher: &mock.ChainService{Optimistic: true}}
|
||||
req := ðpb.BlockRequest{
|
||||
Slot: bellatrixSlot + 1,
|
||||
}
|
||||
_, err = proposerServer.GetBeaconBlock(context.Background(), req)
|
||||
s, ok := status.FromError(err)
|
||||
require.Equal(t, true, ok)
|
||||
require.DeepEqual(t, codes.Unavailable, s.Code())
|
||||
require.ErrorContains(t, " The node is currently optimistic and cannot serve validators", err)
|
||||
}
|
||||
|
||||
func TestProposer_GetSyncAggregate_OK(t *testing.T) {
|
||||
proposerServer := &Server{
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
|
||||
@@ -16,12 +16,14 @@ import (
|
||||
opfeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/operation"
|
||||
statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/signing"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/operations/attestations"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/operations/slashings"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/operations/synccommittee"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/operations/voluntaryexits"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/p2p"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
|
||||
v1 "github.com/prysmaticlabs/prysm/beacon-chain/powchain/engine-api-client/v1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/sync"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
@@ -62,6 +64,8 @@ type Server struct {
|
||||
PendingDepositsFetcher depositcache.PendingDepositsFetcher
|
||||
OperationNotifier opfeed.Notifier
|
||||
StateGen stategen.StateManager
|
||||
ExecutionEngineCaller v1.EngineCaller
|
||||
BeaconDB db.HeadAccessDatabase
|
||||
}
|
||||
|
||||
// WaitForActivation checks if a validator public key exists in the active validator registry of the current
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"errors"
|
||||
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/signing"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/time"
|
||||
@@ -237,6 +238,49 @@ func (vs *Server) activationStatus(
|
||||
return activeValidatorExists, statusResponses, nil
|
||||
}
|
||||
|
||||
// optimisticStatus returns an error if the node is currently optimistic with respect to head.
|
||||
// by definition, an optimistic node is not a full node. It is unable to produce blocks,
|
||||
// since an execution engine cannot produce a payload upon an unknown parent.
|
||||
// It cannot faithfully attest to the head block of the chain, since it has not fully verified that block.
|
||||
//
|
||||
// Spec:
|
||||
// https://github.com/ethereum/consensus-specs/blob/dev/sync/optimistic.md
|
||||
func (vs *Server) optimisticStatus(ctx context.Context) error {
|
||||
blk, err := vs.HeadFetcher.HeadBlock(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if slots.ToEpoch(blk.Block().Slot()) < params.BeaconConfig().BellatrixForkEpoch {
|
||||
return nil
|
||||
}
|
||||
st, err := vs.HeadFetcher.HeadState(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
enabled, err := blocks.ExecutionEnabled(st, blk.Block().Body())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !enabled {
|
||||
return nil
|
||||
}
|
||||
|
||||
optimistic, err := vs.HeadFetcher.IsOptimistic(ctx)
|
||||
if err != nil {
|
||||
return status.Errorf(codes.Internal, "Could not determine if the node is a optimistic node: %v", err)
|
||||
}
|
||||
if !optimistic {
|
||||
return nil
|
||||
}
|
||||
|
||||
root, err := vs.HeadFetcher.HeadRoot(ctx)
|
||||
if err != nil {
|
||||
return status.Errorf(codes.Internal, "Could not get head root: %v", err)
|
||||
}
|
||||
return status.Errorf(codes.Unavailable, "The node is currently optimistic and cannot serve validators. Head root: %#x", root)
|
||||
|
||||
}
|
||||
|
||||
// validatorStatus searches for the requested validator's state and deposit to retrieve its inclusion estimate. Also returns the validators index.
|
||||
func (vs *Server) validatorStatus(
|
||||
ctx context.Context,
|
||||
|
||||
@@ -27,6 +27,8 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/testing/util"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
@@ -582,6 +584,18 @@ func TestActivationStatus_OK(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestOptimisticStatus(t *testing.T) {
|
||||
server := &Server{HeadFetcher: &mockChain.ChainService{}}
|
||||
err := server.optimisticStatus(context.Background())
|
||||
require.NoError(t, err)
|
||||
server = &Server{HeadFetcher: &mockChain.ChainService{Optimistic: true}}
|
||||
err = server.optimisticStatus(context.Background())
|
||||
s, ok := status.FromError(err)
|
||||
require.Equal(t, true, ok)
|
||||
require.DeepEqual(t, codes.Unavailable, s.Code())
|
||||
require.ErrorContains(t, " The node is currently optimistic and cannot serve validators", err)
|
||||
}
|
||||
|
||||
func TestValidatorStatus_CorrectActivationQueue(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
|
||||
@@ -22,6 +22,12 @@ import (
|
||||
func (vs *Server) GetSyncMessageBlockRoot(
|
||||
ctx context.Context, _ *emptypb.Empty,
|
||||
) (*ethpb.SyncMessageBlockRootResponse, error) {
|
||||
// An optimistic validator MUST NOT participate in sync committees
|
||||
// (i.e., sign across the DOMAIN_SYNC_COMMITTEE, DOMAIN_SYNC_COMMITTEE_SELECTION_PROOF or DOMAIN_CONTRIBUTION_AND_PROOF domains).
|
||||
//if err := vs.optimisticStatus(ctx); err != nil {
|
||||
// return nil, err
|
||||
//}
|
||||
|
||||
r, err := vs.HeadFetcher.HeadRoot(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not retrieve head root: %v", err)
|
||||
@@ -81,6 +87,12 @@ func (vs *Server) GetSyncSubcommitteeIndex(
|
||||
func (vs *Server) GetSyncCommitteeContribution(
|
||||
ctx context.Context, req *ethpb.SyncCommitteeContributionRequest,
|
||||
) (*ethpb.SyncCommitteeContribution, error) {
|
||||
// An optimistic validator MUST NOT participate in sync committees
|
||||
// (i.e., sign across the DOMAIN_SYNC_COMMITTEE, DOMAIN_SYNC_COMMITTEE_SELECTION_PROOF or DOMAIN_CONTRIBUTION_AND_PROOF domains).
|
||||
//if err := vs.optimisticStatus(ctx); err != nil {
|
||||
// return nil, err
|
||||
//}
|
||||
|
||||
msgs, err := vs.SyncCommitteePool.SyncCommitteeMessages(req.Slot)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not get sync subcommittee messages: %v", err)
|
||||
|
||||
@@ -18,6 +18,8 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/testing/util"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/types/known/emptypb"
|
||||
)
|
||||
|
||||
@@ -31,6 +33,17 @@ func TestGetSyncMessageBlockRoot_OK(t *testing.T) {
|
||||
require.DeepEqual(t, r, res.Root)
|
||||
}
|
||||
|
||||
func TestGetSyncMessageBlockRoot_Optimistic(t *testing.T) {
|
||||
server := &Server{
|
||||
HeadFetcher: &mock.ChainService{Optimistic: true},
|
||||
}
|
||||
_, err := server.GetSyncMessageBlockRoot(context.Background(), &emptypb.Empty{})
|
||||
s, ok := status.FromError(err)
|
||||
require.Equal(t, true, ok)
|
||||
require.DeepEqual(t, codes.Unavailable, s.Code())
|
||||
require.ErrorContains(t, " The node is currently optimistic and cannot serve validators", err)
|
||||
}
|
||||
|
||||
func TestSubmitSyncMessage_OK(t *testing.T) {
|
||||
st, _ := util.DeterministicGenesisStateAltair(t, 10)
|
||||
server := &Server{
|
||||
|
||||
@@ -26,6 +26,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/operations/voluntaryexits"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/p2p"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
|
||||
v1 "github.com/prysmaticlabs/prysm/beacon-chain/powchain/engine-api-client/v1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/rpc/eth/beacon"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/rpc/eth/debug"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/rpc/eth/events"
|
||||
@@ -108,6 +109,7 @@ type Config struct {
|
||||
OperationNotifier opfeed.Notifier
|
||||
StateGen *stategen.State
|
||||
MaxMsgSize int
|
||||
ExecutionEngineCaller v1.EngineCaller
|
||||
}
|
||||
|
||||
// NewService instantiates a new RPC service instance that will
|
||||
@@ -192,6 +194,8 @@ func (s *Service) Start() {
|
||||
SlashingsPool: s.cfg.SlashingsPool,
|
||||
StateGen: s.cfg.StateGen,
|
||||
SyncCommitteePool: s.cfg.SyncCommitteeObjectPool,
|
||||
ExecutionEngineCaller: s.cfg.ExecutionEngineCaller,
|
||||
BeaconDB: s.cfg.BeaconDB,
|
||||
}
|
||||
validatorServerV1 := &validator.Server{
|
||||
HeadFetcher: s.cfg.HeadFetcher,
|
||||
|
||||
@@ -20,7 +20,7 @@ func TestFieldTrie_NewTrie(t *testing.T) {
|
||||
// 5 represents the enum value of state roots
|
||||
trie, err := fieldtrie.NewFieldTrie(5, stateTypes.BasicArray, newState.StateRoots(), uint64(params.BeaconConfig().SlotsPerHistoricalRoot))
|
||||
require.NoError(t, err)
|
||||
root, err := stateutil.RootsArrayHashTreeRoot(newState.StateRoots(), uint64(params.BeaconConfig().SlotsPerHistoricalRoot), "StateRoots")
|
||||
root, err := stateutil.RootsArrayHashTreeRoot(newState.StateRoots(), uint64(params.BeaconConfig().SlotsPerHistoricalRoot))
|
||||
require.NoError(t, err)
|
||||
newRoot, err := trie.TrieRoot()
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -4,15 +4,11 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
"github.com/prysmaticlabs/prysm/config/features"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
// computeFieldRoots returns the hash tree root computations of every field in
|
||||
// the beacon state as a list of 32 byte roots.
|
||||
func computeFieldRoots(ctx context.Context, state *ethpb.BeaconState) ([][]byte, error) {
|
||||
if features.Get().EnableSSZCache {
|
||||
return stateutil.CachedHasher.ComputeFieldRootsWithHasherPhase0(ctx, state)
|
||||
}
|
||||
return stateutil.NocachedHasher.ComputeFieldRootsWithHasherPhase0(ctx, state)
|
||||
return stateutil.ComputeFieldRootsWithHasherPhase0(ctx, state)
|
||||
}
|
||||
|
||||
@@ -4,15 +4,11 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
"github.com/prysmaticlabs/prysm/config/features"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
// computeFieldRoots returns the hash tree root computations of every field in
|
||||
// the beacon state as a list of 32 byte roots.
|
||||
func computeFieldRoots(ctx context.Context, state *ethpb.BeaconStateAltair) ([][]byte, error) {
|
||||
if features.Get().EnableSSZCache {
|
||||
return stateutil.CachedHasher.ComputeFieldRootsWithHasherAltair(ctx, state)
|
||||
}
|
||||
return stateutil.NocachedHasher.ComputeFieldRootsWithHasherAltair(ctx, state)
|
||||
return stateutil.ComputeFieldRootsWithHasherAltair(ctx, state)
|
||||
}
|
||||
|
||||
@@ -4,15 +4,11 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
"github.com/prysmaticlabs/prysm/config/features"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
// computeFieldRoots returns the hash tree root computations of every field in
|
||||
// the beacon state as a list of 32 byte roots.
|
||||
func computeFieldRoots(ctx context.Context, state *ethpb.BeaconStateBellatrix) ([][]byte, error) {
|
||||
if features.Get().EnableSSZCache {
|
||||
return stateutil.CachedHasher.ComputeFieldRootsWithHasherBellatrix(ctx, state)
|
||||
}
|
||||
return stateutil.NocachedHasher.ComputeFieldRootsWithHasherBellatrix(ctx, state)
|
||||
return stateutil.ComputeFieldRootsWithHasherBellatrix(ctx, state)
|
||||
}
|
||||
|
||||
@@ -32,7 +32,6 @@ go_library(
|
||||
],
|
||||
deps = [
|
||||
"//beacon-chain/core/transition/stateutils:go_default_library",
|
||||
"//config/features:go_default_library",
|
||||
"//config/fieldparams:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//container/trie:go_default_library",
|
||||
@@ -41,7 +40,6 @@ go_library(
|
||||
"//encoding/ssz:go_default_library",
|
||||
"//math:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"@com_github_dgraph_io_ristretto//:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
|
||||
"@io_opencensus_go//trace:go_default_library",
|
||||
@@ -55,13 +53,11 @@ go_test(
|
||||
"field_root_test.go",
|
||||
"reference_bench_test.go",
|
||||
"state_root_test.go",
|
||||
"stateutil_test.go",
|
||||
"trie_helpers_test.go",
|
||||
"validator_root_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//config/features:go_default_library",
|
||||
"//config/fieldparams:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//crypto/hash:go_default_library",
|
||||
|
||||
@@ -12,27 +12,6 @@ import (
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
// eth1DataEncKey returns the encoded key in bytes of input `eth1Data`,
|
||||
// the returned key bytes can be used for caching purposes.
|
||||
func eth1DataEncKey(eth1Data *ethpb.Eth1Data) []byte {
|
||||
enc := make([]byte, 0, 96)
|
||||
if eth1Data != nil {
|
||||
if len(eth1Data.DepositRoot) > 0 {
|
||||
depRoot := bytesutil.ToBytes32(eth1Data.DepositRoot)
|
||||
enc = append(enc, depRoot[:]...)
|
||||
}
|
||||
eth1DataCountBuf := make([]byte, 8)
|
||||
binary.LittleEndian.PutUint64(eth1DataCountBuf, eth1Data.DepositCount)
|
||||
eth1CountRoot := bytesutil.ToBytes32(eth1DataCountBuf)
|
||||
enc = append(enc, eth1CountRoot[:]...)
|
||||
if len(eth1Data.BlockHash) > 0 {
|
||||
blockHash := bytesutil.ToBytes32(eth1Data.BlockHash)
|
||||
enc = append(enc, blockHash[:]...)
|
||||
}
|
||||
}
|
||||
return enc
|
||||
}
|
||||
|
||||
// Eth1DataRootWithHasher returns the hash tree root of input `eth1Data`.
|
||||
func Eth1DataRootWithHasher(hasher ssz.HashFn, eth1Data *ethpb.Eth1Data) ([32]byte, error) {
|
||||
if eth1Data == nil {
|
||||
@@ -62,22 +41,6 @@ func Eth1DataRootWithHasher(hasher ssz.HashFn, eth1Data *ethpb.Eth1Data) ([32]by
|
||||
return root, nil
|
||||
}
|
||||
|
||||
// Eth1DatasEncKey returns the encoded key in bytes of input `eth1Data`s,
|
||||
// the returned key bytes can be used for caching purposes.
|
||||
func Eth1DatasEncKey(eth1Datas []*ethpb.Eth1Data) ([32]byte, error) {
|
||||
hasher := hash.CustomSHA256Hasher()
|
||||
enc := make([]byte, len(eth1Datas)*32)
|
||||
for i := 0; i < len(eth1Datas); i++ {
|
||||
eth1, err := Eth1DataRootWithHasher(hasher, eth1Datas[i])
|
||||
if err != nil {
|
||||
return [32]byte{}, errors.Wrap(err, "could not compute eth1data merkleization")
|
||||
}
|
||||
copy(enc[(i*32):(i+1)*32], eth1[:])
|
||||
}
|
||||
hashKey := hash.FastSum256(enc)
|
||||
return hashKey, nil
|
||||
}
|
||||
|
||||
// Eth1DatasRoot returns the hash tree root of input `eth1Datas`.
|
||||
func Eth1DatasRoot(eth1Datas []*ethpb.Eth1Data) ([32]byte, error) {
|
||||
hasher := hash.CustomSHA256Hasher()
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/config/features"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/crypto/hash"
|
||||
"github.com/prysmaticlabs/prysm/encoding/ssz"
|
||||
@@ -15,14 +14,11 @@ import (
|
||||
|
||||
// RootsArrayHashTreeRoot computes the Merkle root of arrays of 32-byte hashes, such as [64][32]byte
|
||||
// according to the Simple Serialize specification of Ethereum.
|
||||
func RootsArrayHashTreeRoot(vals [][]byte, length uint64, fieldName string) ([32]byte, error) {
|
||||
if features.Get().EnableSSZCache {
|
||||
return CachedHasher.arraysRoot(vals, length, fieldName)
|
||||
}
|
||||
return NocachedHasher.arraysRoot(vals, length, fieldName)
|
||||
func RootsArrayHashTreeRoot(vals [][]byte, length uint64) ([32]byte, error) {
|
||||
return arraysRoot(vals, length)
|
||||
}
|
||||
|
||||
func (h *stateRootHasher) epochAttestationsRoot(atts []*ethpb.PendingAttestation) ([32]byte, error) {
|
||||
func epochAttestationsRoot(atts []*ethpb.PendingAttestation) ([32]byte, error) {
|
||||
max := uint64(fieldparams.CurrentEpochAttestationsLength)
|
||||
if uint64(len(atts)) > max {
|
||||
return [32]byte{}, fmt.Errorf("epoch attestation exceeds max length %d", max)
|
||||
@@ -31,7 +27,7 @@ func (h *stateRootHasher) epochAttestationsRoot(atts []*ethpb.PendingAttestation
|
||||
hasher := hash.CustomSHA256Hasher()
|
||||
roots := make([][]byte, len(atts))
|
||||
for i := 0; i < len(atts); i++ {
|
||||
pendingRoot, err := h.pendingAttestationRoot(hasher, atts[i])
|
||||
pendingRoot, err := pendingAttestationRoot(hasher, atts[i])
|
||||
if err != nil {
|
||||
return [32]byte{}, errors.Wrap(err, "could not attestation merkleization")
|
||||
}
|
||||
@@ -58,26 +54,9 @@ func (h *stateRootHasher) epochAttestationsRoot(atts []*ethpb.PendingAttestation
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (h *stateRootHasher) pendingAttestationRoot(hasher ssz.HashFn, att *ethpb.PendingAttestation) ([32]byte, error) {
|
||||
func pendingAttestationRoot(hasher ssz.HashFn, att *ethpb.PendingAttestation) ([32]byte, error) {
|
||||
if att == nil {
|
||||
return [32]byte{}, errors.New("nil pending attestation")
|
||||
}
|
||||
// Marshal attestation to determine if it exists in the cache.
|
||||
enc := pendingAttEncKey(att)
|
||||
|
||||
// Check if it exists in cache:
|
||||
if h.rootsCache != nil {
|
||||
if found, ok := h.rootsCache.Get(string(enc)); found != nil && ok {
|
||||
return found.([32]byte), nil
|
||||
}
|
||||
}
|
||||
|
||||
res, err := PendingAttRootWithHasher(hasher, att)
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
if h.rootsCache != nil {
|
||||
h.rootsCache.Set(string(enc), res, 32)
|
||||
}
|
||||
return res, nil
|
||||
return PendingAttRootWithHasher(hasher, att)
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package stateutil
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/config/features"
|
||||
"github.com/prysmaticlabs/prysm/encoding/ssz"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
)
|
||||
@@ -14,45 +13,12 @@ func Eth1Root(hasher ssz.HashFn, eth1Data *ethpb.Eth1Data) ([32]byte, error) {
|
||||
if eth1Data == nil {
|
||||
return [32]byte{}, errors.New("nil eth1 data")
|
||||
}
|
||||
|
||||
enc := eth1DataEncKey(eth1Data)
|
||||
if features.Get().EnableSSZCache {
|
||||
if found, ok := CachedHasher.rootsCache.Get(string(enc)); ok && found != nil {
|
||||
return found.([32]byte), nil
|
||||
}
|
||||
}
|
||||
|
||||
root, err := Eth1DataRootWithHasher(hasher, eth1Data)
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
|
||||
if features.Get().EnableSSZCache {
|
||||
CachedHasher.rootsCache.Set(string(enc), root, 32)
|
||||
}
|
||||
return root, nil
|
||||
return Eth1DataRootWithHasher(hasher, eth1Data)
|
||||
}
|
||||
|
||||
// eth1DataVotesRoot computes the HashTreeRoot Merkleization of
|
||||
// a list of Eth1Data structs according to the eth2
|
||||
// Simple Serialize specification.
|
||||
func eth1DataVotesRoot(eth1DataVotes []*ethpb.Eth1Data) ([32]byte, error) {
|
||||
hashKey, err := Eth1DatasEncKey(eth1DataVotes)
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
|
||||
if features.Get().EnableSSZCache {
|
||||
if found, ok := CachedHasher.rootsCache.Get(string(hashKey[:])); ok && found != nil {
|
||||
return found.([32]byte), nil
|
||||
}
|
||||
}
|
||||
root, err := Eth1DatasRoot(eth1DataVotes)
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
if features.Get().EnableSSZCache {
|
||||
CachedHasher.rootsCache.Set(string(hashKey[:]), root, 32)
|
||||
}
|
||||
return root, nil
|
||||
return Eth1DatasRoot(eth1DataVotes)
|
||||
}
|
||||
|
||||
@@ -7,17 +7,17 @@ import (
|
||||
)
|
||||
|
||||
func TestArraysTreeRoot_OnlyPowerOf2(t *testing.T) {
|
||||
_, err := NocachedHasher.arraysRoot([][]byte{}, 1, "testing")
|
||||
_, err := arraysRoot([][]byte{}, 1)
|
||||
assert.NoError(t, err)
|
||||
_, err = NocachedHasher.arraysRoot([][]byte{}, 4, "testing")
|
||||
_, err = arraysRoot([][]byte{}, 4)
|
||||
assert.NoError(t, err)
|
||||
_, err = NocachedHasher.arraysRoot([][]byte{}, 8, "testing")
|
||||
_, err = arraysRoot([][]byte{}, 8)
|
||||
assert.NoError(t, err)
|
||||
_, err = NocachedHasher.arraysRoot([][]byte{}, 10, "testing")
|
||||
_, err = arraysRoot([][]byte{}, 10)
|
||||
assert.ErrorContains(t, "hash layer is a non power of 2", err)
|
||||
}
|
||||
|
||||
func TestArraysTreeRoot_ZeroLength(t *testing.T) {
|
||||
_, err := NocachedHasher.arraysRoot([][]byte{}, 0, "testing")
|
||||
_, err := arraysRoot([][]byte{}, 0)
|
||||
assert.ErrorContains(t, "zero leaves provided", err)
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/config/features"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/crypto/hash"
|
||||
"github.com/prysmaticlabs/prysm/encoding/ssz"
|
||||
@@ -16,33 +15,18 @@ import (
|
||||
// a list of validator structs according to the Ethereum
|
||||
// Simple Serialize specification.
|
||||
func ValidatorRegistryRoot(vals []*ethpb.Validator) ([32]byte, error) {
|
||||
if features.Get().EnableSSZCache {
|
||||
return CachedHasher.validatorRegistryRoot(vals)
|
||||
}
|
||||
return NocachedHasher.validatorRegistryRoot(vals)
|
||||
return validatorRegistryRoot(vals)
|
||||
}
|
||||
|
||||
func (h *stateRootHasher) validatorRegistryRoot(validators []*ethpb.Validator) ([32]byte, error) {
|
||||
hashKeyElements := make([]byte, len(validators)*32)
|
||||
func validatorRegistryRoot(validators []*ethpb.Validator) ([32]byte, error) {
|
||||
roots := make([][32]byte, len(validators))
|
||||
emptyKey := hash.FastSum256(hashKeyElements)
|
||||
hasher := hash.CustomSHA256Hasher()
|
||||
bytesProcessed := 0
|
||||
for i := 0; i < len(validators); i++ {
|
||||
val, err := h.validatorRoot(hasher, validators[i])
|
||||
val, err := validatorRoot(hasher, validators[i])
|
||||
if err != nil {
|
||||
return [32]byte{}, errors.Wrap(err, "could not compute validators merkleization")
|
||||
}
|
||||
copy(hashKeyElements[bytesProcessed:bytesProcessed+32], val[:])
|
||||
roots[i] = val
|
||||
bytesProcessed += 32
|
||||
}
|
||||
|
||||
hashKey := hash.FastSum256(hashKeyElements)
|
||||
if hashKey != emptyKey && h.rootsCache != nil {
|
||||
if found, ok := h.rootsCache.Get(string(hashKey[:])); found != nil && ok {
|
||||
return found.([32]byte), nil
|
||||
}
|
||||
}
|
||||
|
||||
validatorsRootsRoot, err := ssz.BitwiseMerkleizeArrays(hasher, roots, uint64(len(roots)), fieldparams.ValidatorRegistryLimit)
|
||||
@@ -57,32 +41,13 @@ func (h *stateRootHasher) validatorRegistryRoot(validators []*ethpb.Validator) (
|
||||
var validatorsRootsBufRoot [32]byte
|
||||
copy(validatorsRootsBufRoot[:], validatorsRootsBuf.Bytes())
|
||||
res := ssz.MixInLength(validatorsRootsRoot, validatorsRootsBufRoot[:])
|
||||
if hashKey != emptyKey && h.rootsCache != nil {
|
||||
h.rootsCache.Set(string(hashKey[:]), res, 32)
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (h *stateRootHasher) validatorRoot(hasher ssz.HashFn, validator *ethpb.Validator) ([32]byte, error) {
|
||||
func validatorRoot(hasher ssz.HashFn, validator *ethpb.Validator) ([32]byte, error) {
|
||||
if validator == nil {
|
||||
return [32]byte{}, errors.New("nil validator")
|
||||
}
|
||||
|
||||
enc := validatorEncKey(validator)
|
||||
// Check if it exists in cache:
|
||||
if h.rootsCache != nil {
|
||||
if found, ok := h.rootsCache.Get(string(enc)); found != nil && ok {
|
||||
return found.([32]byte), nil
|
||||
}
|
||||
}
|
||||
|
||||
valRoot, err := ValidatorRootWithHasher(hasher, validator)
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
|
||||
if h.rootsCache != nil {
|
||||
h.rootsCache.Set(string(enc), valRoot, 32)
|
||||
}
|
||||
return valRoot, nil
|
||||
return ValidatorRootWithHasher(hasher, validator)
|
||||
}
|
||||
|
||||
@@ -6,129 +6,23 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/encoding/ssz"
|
||||
)
|
||||
|
||||
func (h *stateRootHasher) arraysRoot(input [][]byte, length uint64, fieldName string) ([32]byte, error) {
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
func arraysRoot(input [][]byte, length uint64) ([32]byte, error) {
|
||||
hashFunc := hash.CustomSHA256Hasher()
|
||||
if _, ok := layersCache[fieldName]; !ok && h.rootsCache != nil {
|
||||
depth := ssz.Depth(length)
|
||||
layersCache[fieldName] = make([][][32]byte, depth+1)
|
||||
}
|
||||
|
||||
leaves := make([][32]byte, length)
|
||||
for i, chunk := range input {
|
||||
copy(leaves[i][:], chunk)
|
||||
}
|
||||
bytesProcessed := 0
|
||||
changedIndices := make([]int, 0)
|
||||
prevLeaves, ok := leavesCache[fieldName]
|
||||
if len(prevLeaves) == 0 || h.rootsCache == nil {
|
||||
prevLeaves = leaves
|
||||
}
|
||||
// Exit early if our previous leaves length don't match with the current set.
|
||||
// This should never happen but better to be defensive here.
|
||||
if len(prevLeaves) != len(leaves) {
|
||||
res, err := h.merkleizeWithCache(leaves, length, fieldName, hashFunc)
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
if h.rootsCache != nil {
|
||||
leavesCache[fieldName] = leaves
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
for i := 0; i < len(leaves); i++ {
|
||||
// We check if any items changed since the roots were last recomputed.
|
||||
notEqual := leaves[i] != prevLeaves[i]
|
||||
if ok && h.rootsCache != nil && notEqual {
|
||||
changedIndices = append(changedIndices, i)
|
||||
}
|
||||
bytesProcessed += 32
|
||||
}
|
||||
if len(changedIndices) > 0 && h.rootsCache != nil {
|
||||
var rt [32]byte
|
||||
var err error
|
||||
// If indices did change since last computation, we only recompute
|
||||
// the modified branches in the cached Merkle tree for this state field.
|
||||
chunks := leaves
|
||||
|
||||
// We need to ensure we recompute indices of the Merkle tree which
|
||||
// changed in-between calls to this function. This check adds an offset
|
||||
// to the recomputed indices to ensure we do so evenly.
|
||||
maxChangedIndex := changedIndices[len(changedIndices)-1]
|
||||
if maxChangedIndex+2 == len(chunks) && maxChangedIndex%2 != 0 {
|
||||
changedIndices = append(changedIndices, maxChangedIndex+1)
|
||||
}
|
||||
for i := 0; i < len(changedIndices); i++ {
|
||||
rt, err = recomputeRoot(changedIndices[i], chunks, fieldName, hashFunc)
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
}
|
||||
leavesCache[fieldName] = chunks
|
||||
return rt, nil
|
||||
}
|
||||
|
||||
res, err := h.merkleizeWithCache(leaves, length, fieldName, hashFunc)
|
||||
res, err := merkleize(leaves, length, hashFunc)
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
if h.rootsCache != nil {
|
||||
leavesCache[fieldName] = leaves
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func recomputeRoot(idx int, chunks [][32]byte, fieldName string, hasher func([]byte) [32]byte) ([32]byte, error) {
|
||||
items, ok := layersCache[fieldName]
|
||||
if !ok {
|
||||
return [32]byte{}, errors.New("could not recompute root as there was no cache found")
|
||||
}
|
||||
if items == nil {
|
||||
return [32]byte{}, errors.New("could not recompute root as there were no items found in the layers cache")
|
||||
}
|
||||
layers := items
|
||||
root := chunks[idx]
|
||||
layers[0] = chunks
|
||||
// The merkle tree structure looks as follows:
|
||||
// [[r1, r2, r3, r4], [parent1, parent2], [root]]
|
||||
// Using information about the index which changed, idx, we recompute
|
||||
// only its branch up the tree.
|
||||
currentIndex := idx
|
||||
for i := 0; i < len(layers)-1; i++ {
|
||||
isLeft := currentIndex%2 == 0
|
||||
neighborIdx := currentIndex ^ 1
|
||||
|
||||
neighbor := [32]byte{}
|
||||
if layers[i] != nil && len(layers[i]) != 0 && neighborIdx < len(layers[i]) {
|
||||
neighbor = layers[i][neighborIdx]
|
||||
}
|
||||
if isLeft {
|
||||
parentHash := hasher(append(root[:], neighbor[:]...))
|
||||
root = parentHash
|
||||
} else {
|
||||
parentHash := hasher(append(neighbor[:], root[:]...))
|
||||
root = parentHash
|
||||
}
|
||||
parentIdx := currentIndex / 2
|
||||
// Update the cached layers at the parent index.
|
||||
if len(layers[i+1]) == 0 {
|
||||
layers[i+1] = append(layers[i+1], root)
|
||||
} else {
|
||||
layers[i+1][parentIdx] = root
|
||||
}
|
||||
currentIndex = parentIdx
|
||||
}
|
||||
layersCache[fieldName] = layers
|
||||
// If there is only a single leaf, we return it (the identity element).
|
||||
if len(layers[0]) == 1 {
|
||||
return layers[0][0], nil
|
||||
}
|
||||
return root, nil
|
||||
}
|
||||
|
||||
func (h *stateRootHasher) merkleizeWithCache(leaves [][32]byte, length uint64,
|
||||
fieldName string, hasher func([]byte) [32]byte) ([32]byte, error) {
|
||||
func merkleize(leaves [][32]byte, length uint64,
|
||||
hasher func([]byte) [32]byte) ([32]byte, error) {
|
||||
if len(leaves) == 0 {
|
||||
return [32]byte{}, errors.New("zero leaves provided")
|
||||
}
|
||||
@@ -137,20 +31,12 @@ func (h *stateRootHasher) merkleizeWithCache(leaves [][32]byte, length uint64,
|
||||
}
|
||||
hashLayer := leaves
|
||||
layers := make([][][32]byte, ssz.Depth(length)+1)
|
||||
if items, ok := layersCache[fieldName]; ok && h.rootsCache != nil {
|
||||
if len(items[0]) == len(leaves) {
|
||||
layers = items
|
||||
}
|
||||
}
|
||||
layers[0] = hashLayer
|
||||
var err error
|
||||
layers, hashLayer, err = MerkleizeTrieLeaves(layers, hashLayer, hasher)
|
||||
_, hashLayer, err = MerkleizeTrieLeaves(layers, hashLayer, hasher)
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
root := hashLayer[0]
|
||||
if h.rootsCache != nil {
|
||||
layersCache[fieldName] = layers
|
||||
}
|
||||
return root, nil
|
||||
}
|
||||
|
||||
@@ -40,29 +40,6 @@ func PendingAttRootWithHasher(hasher ssz.HashFn, att *ethpb.PendingAttestation)
|
||||
return ssz.BitwiseMerkleizeArrays(hasher, fieldRoots, uint64(len(fieldRoots)), uint64(len(fieldRoots)))
|
||||
}
|
||||
|
||||
// pendingAttEncKey returns the encoded key in bytes of input `pendingAttestation`,
|
||||
// the returned key bytes can be used for caching purposes.
|
||||
func pendingAttEncKey(att *ethpb.PendingAttestation) []byte {
|
||||
enc := make([]byte, 2192)
|
||||
|
||||
if att != nil {
|
||||
copy(enc[0:2048], att.AggregationBits)
|
||||
|
||||
inclusionBuf := make([]byte, 8)
|
||||
binary.LittleEndian.PutUint64(inclusionBuf, uint64(att.InclusionDelay))
|
||||
copy(enc[2048:2056], inclusionBuf)
|
||||
|
||||
attDataBuf := marshalAttData(att.Data)
|
||||
copy(enc[2056:2184], attDataBuf)
|
||||
|
||||
proposerBuf := make([]byte, 8)
|
||||
binary.LittleEndian.PutUint64(proposerBuf, uint64(att.ProposerIndex))
|
||||
copy(enc[2184:2192], proposerBuf)
|
||||
}
|
||||
|
||||
return enc
|
||||
}
|
||||
|
||||
func attDataRootWithHasher(hasher ssz.HashFn, data *ethpb.AttestationData) ([32]byte, error) {
|
||||
fieldRoots := make([][]byte, 5)
|
||||
|
||||
@@ -100,39 +77,3 @@ func attDataRootWithHasher(hasher ssz.HashFn, data *ethpb.AttestationData) ([32]
|
||||
|
||||
return ssz.BitwiseMerkleize(hasher, fieldRoots, uint64(len(fieldRoots)), uint64(len(fieldRoots)))
|
||||
}
|
||||
|
||||
func marshalAttData(data *ethpb.AttestationData) []byte {
|
||||
enc := make([]byte, 128)
|
||||
|
||||
if data != nil {
|
||||
// Slot.
|
||||
slotBuf := make([]byte, 8)
|
||||
binary.LittleEndian.PutUint64(slotBuf, uint64(data.Slot))
|
||||
copy(enc[0:8], slotBuf)
|
||||
|
||||
// Committee index.
|
||||
indexBuf := make([]byte, 8)
|
||||
binary.LittleEndian.PutUint64(indexBuf, uint64(data.CommitteeIndex))
|
||||
copy(enc[8:16], indexBuf)
|
||||
|
||||
copy(enc[16:48], data.BeaconBlockRoot)
|
||||
|
||||
// Source epoch and root.
|
||||
if data.Source != nil {
|
||||
sourceEpochBuf := make([]byte, 8)
|
||||
binary.LittleEndian.PutUint64(sourceEpochBuf, uint64(data.Source.Epoch))
|
||||
copy(enc[48:56], sourceEpochBuf)
|
||||
copy(enc[56:88], data.Source.Root)
|
||||
}
|
||||
|
||||
// Target.
|
||||
if data.Target != nil {
|
||||
targetEpochBuf := make([]byte, 8)
|
||||
binary.LittleEndian.PutUint64(targetEpochBuf, uint64(data.Target.Epoch))
|
||||
copy(enc[88:96], targetEpochBuf)
|
||||
copy(enc[96:128], data.Target.Root)
|
||||
}
|
||||
}
|
||||
|
||||
return enc
|
||||
}
|
||||
|
||||
@@ -3,9 +3,7 @@ package stateutil
|
||||
import (
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"sync"
|
||||
|
||||
"github.com/dgraph-io/ristretto"
|
||||
"github.com/pkg/errors"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
@@ -16,45 +14,9 @@ import (
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
var (
|
||||
// Set the map size as equal to that of the latest state field count.
|
||||
leavesCache = make(map[string][][32]byte, params.BeaconConfig().BeaconStateBellatrixFieldCount)
|
||||
layersCache = make(map[string][][][32]byte, params.BeaconConfig().BeaconStateBellatrixFieldCount)
|
||||
lock sync.RWMutex
|
||||
)
|
||||
|
||||
const cacheSize = 100000
|
||||
|
||||
// NocachedHasher references a hasher that will not utilize a cache.
|
||||
var NocachedHasher *stateRootHasher
|
||||
|
||||
// CachedHasher references a hasher that will utilize a roots cache.
|
||||
var CachedHasher *stateRootHasher
|
||||
|
||||
func init() {
|
||||
rootsCache, err := ristretto.NewCache(&ristretto.Config{
|
||||
NumCounters: cacheSize, // number of keys to track frequency of (1M).
|
||||
MaxCost: 1 << 22, // maximum cost of cache (3MB).
|
||||
// 100,000 roots will take up approximately 3 MB in memory.
|
||||
BufferItems: 64, // number of keys per Get buffer.
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// Temporarily disable roots cache until cache issues can be resolved.
|
||||
CachedHasher = &stateRootHasher{rootsCache: rootsCache}
|
||||
NocachedHasher = &stateRootHasher{}
|
||||
}
|
||||
|
||||
// stateRootHasher defines an object through which we can
|
||||
// hash the different fields in the state with a few cached layers.
|
||||
type stateRootHasher struct {
|
||||
rootsCache *ristretto.Cache
|
||||
}
|
||||
|
||||
// ComputeFieldRootsWithHasherPhase0 hashes the provided phase 0 state and returns its respective field roots.
|
||||
func (h *stateRootHasher) ComputeFieldRootsWithHasherPhase0(ctx context.Context, state *ethpb.BeaconState) ([][]byte, error) {
|
||||
_, span := trace.StartSpan(ctx, "hasher.ComputeFieldRootsWithHasherPhase0")
|
||||
func ComputeFieldRootsWithHasherPhase0(ctx context.Context, state *ethpb.BeaconState) ([][]byte, error) {
|
||||
_, span := trace.StartSpan(ctx, "ComputeFieldRootsWithHasherPhase0")
|
||||
defer span.End()
|
||||
|
||||
if state == nil {
|
||||
@@ -91,14 +53,14 @@ func (h *stateRootHasher) ComputeFieldRootsWithHasherPhase0(ctx context.Context,
|
||||
fieldRoots[4] = headerHashTreeRoot[:]
|
||||
|
||||
// BlockRoots array root.
|
||||
blockRootsRoot, err := h.arraysRoot(state.BlockRoots, fieldparams.BlockRootsLength, "BlockRoots")
|
||||
blockRootsRoot, err := arraysRoot(state.BlockRoots, fieldparams.BlockRootsLength)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not compute block roots merkleization")
|
||||
}
|
||||
fieldRoots[5] = blockRootsRoot[:]
|
||||
|
||||
// StateRoots array root.
|
||||
stateRootsRoot, err := h.arraysRoot(state.StateRoots, fieldparams.StateRootsLength, "StateRoots")
|
||||
stateRootsRoot, err := arraysRoot(state.StateRoots, fieldparams.StateRootsLength)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not compute state roots merkleization")
|
||||
}
|
||||
@@ -132,7 +94,7 @@ func (h *stateRootHasher) ComputeFieldRootsWithHasherPhase0(ctx context.Context,
|
||||
fieldRoots[10] = eth1DepositBuf[:]
|
||||
|
||||
// Validators slice root.
|
||||
validatorsRoot, err := h.validatorRegistryRoot(state.Validators)
|
||||
validatorsRoot, err := validatorRegistryRoot(state.Validators)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not compute validator registry merkleization")
|
||||
}
|
||||
@@ -146,7 +108,7 @@ func (h *stateRootHasher) ComputeFieldRootsWithHasherPhase0(ctx context.Context,
|
||||
fieldRoots[12] = balancesRoot[:]
|
||||
|
||||
// RandaoMixes array root.
|
||||
randaoRootsRoot, err := h.arraysRoot(state.RandaoMixes, fieldparams.RandaoMixesLength, "RandaoMixes")
|
||||
randaoRootsRoot, err := arraysRoot(state.RandaoMixes, fieldparams.RandaoMixesLength)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not compute randao roots merkleization")
|
||||
}
|
||||
@@ -160,14 +122,14 @@ func (h *stateRootHasher) ComputeFieldRootsWithHasherPhase0(ctx context.Context,
|
||||
fieldRoots[14] = slashingsRootsRoot[:]
|
||||
|
||||
// PreviousEpochAttestations slice root.
|
||||
prevAttsRoot, err := h.epochAttestationsRoot(state.PreviousEpochAttestations)
|
||||
prevAttsRoot, err := epochAttestationsRoot(state.PreviousEpochAttestations)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not compute previous epoch attestations merkleization")
|
||||
}
|
||||
fieldRoots[15] = prevAttsRoot[:]
|
||||
|
||||
// CurrentEpochAttestations slice root.
|
||||
currAttsRoot, err := h.epochAttestationsRoot(state.CurrentEpochAttestations)
|
||||
currAttsRoot, err := epochAttestationsRoot(state.CurrentEpochAttestations)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not compute current epoch attestations merkleization")
|
||||
}
|
||||
@@ -201,8 +163,8 @@ func (h *stateRootHasher) ComputeFieldRootsWithHasherPhase0(ctx context.Context,
|
||||
}
|
||||
|
||||
// ComputeFieldRootsWithHasherAltair hashes the provided altair state and returns its respective field roots.
|
||||
func (h *stateRootHasher) ComputeFieldRootsWithHasherAltair(ctx context.Context, state *ethpb.BeaconStateAltair) ([][]byte, error) {
|
||||
_, span := trace.StartSpan(ctx, "hasher.ComputeFieldRootsWithHasherAltair")
|
||||
func ComputeFieldRootsWithHasherAltair(ctx context.Context, state *ethpb.BeaconStateAltair) ([][]byte, error) {
|
||||
_, span := trace.StartSpan(ctx, "ComputeFieldRootsWithHasherAltair")
|
||||
defer span.End()
|
||||
|
||||
if state == nil {
|
||||
@@ -239,14 +201,14 @@ func (h *stateRootHasher) ComputeFieldRootsWithHasherAltair(ctx context.Context,
|
||||
fieldRoots[4] = headerHashTreeRoot[:]
|
||||
|
||||
// BlockRoots array root.
|
||||
blockRootsRoot, err := h.arraysRoot(state.BlockRoots, fieldparams.BlockRootsLength, "BlockRoots")
|
||||
blockRootsRoot, err := arraysRoot(state.BlockRoots, fieldparams.BlockRootsLength)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not compute block roots merkleization")
|
||||
}
|
||||
fieldRoots[5] = blockRootsRoot[:]
|
||||
|
||||
// StateRoots array root.
|
||||
stateRootsRoot, err := h.arraysRoot(state.StateRoots, fieldparams.StateRootsLength, "StateRoots")
|
||||
stateRootsRoot, err := arraysRoot(state.StateRoots, fieldparams.StateRootsLength)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not compute state roots merkleization")
|
||||
}
|
||||
@@ -280,7 +242,7 @@ func (h *stateRootHasher) ComputeFieldRootsWithHasherAltair(ctx context.Context,
|
||||
fieldRoots[10] = eth1DepositBuf[:]
|
||||
|
||||
// Validators slice root.
|
||||
validatorsRoot, err := h.validatorRegistryRoot(state.Validators)
|
||||
validatorsRoot, err := validatorRegistryRoot(state.Validators)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not compute validator registry merkleization")
|
||||
}
|
||||
@@ -294,7 +256,7 @@ func (h *stateRootHasher) ComputeFieldRootsWithHasherAltair(ctx context.Context,
|
||||
fieldRoots[12] = balancesRoot[:]
|
||||
|
||||
// RandaoMixes array root.
|
||||
randaoRootsRoot, err := h.arraysRoot(state.RandaoMixes, fieldparams.RandaoMixesLength, "RandaoMixes")
|
||||
randaoRootsRoot, err := arraysRoot(state.RandaoMixes, fieldparams.RandaoMixesLength)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not compute randao roots merkleization")
|
||||
}
|
||||
@@ -371,8 +333,8 @@ func (h *stateRootHasher) ComputeFieldRootsWithHasherAltair(ctx context.Context,
|
||||
}
|
||||
|
||||
// ComputeFieldRootsWithHasherBellatrix hashes the provided bellatrix state and returns its respective field roots.
|
||||
func (h *stateRootHasher) ComputeFieldRootsWithHasherBellatrix(ctx context.Context, state *ethpb.BeaconStateBellatrix) ([][]byte, error) {
|
||||
_, span := trace.StartSpan(ctx, "hasher.ComputeFieldRootsWithHasherBellatrix")
|
||||
func ComputeFieldRootsWithHasherBellatrix(ctx context.Context, state *ethpb.BeaconStateBellatrix) ([][]byte, error) {
|
||||
_, span := trace.StartSpan(ctx, "ComputeFieldRootsWithHasherBellatrix")
|
||||
defer span.End()
|
||||
|
||||
if state == nil {
|
||||
@@ -409,14 +371,14 @@ func (h *stateRootHasher) ComputeFieldRootsWithHasherBellatrix(ctx context.Conte
|
||||
fieldRoots[4] = headerHashTreeRoot[:]
|
||||
|
||||
// BlockRoots array root.
|
||||
blockRootsRoot, err := h.arraysRoot(state.BlockRoots, fieldparams.BlockRootsLength, "BlockRoots")
|
||||
blockRootsRoot, err := arraysRoot(state.BlockRoots, fieldparams.BlockRootsLength)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not compute block roots merkleization")
|
||||
}
|
||||
fieldRoots[5] = blockRootsRoot[:]
|
||||
|
||||
// StateRoots array root.
|
||||
stateRootsRoot, err := h.arraysRoot(state.StateRoots, fieldparams.StateRootsLength, "StateRoots")
|
||||
stateRootsRoot, err := arraysRoot(state.StateRoots, fieldparams.StateRootsLength)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not compute state roots merkleization")
|
||||
}
|
||||
@@ -450,7 +412,7 @@ func (h *stateRootHasher) ComputeFieldRootsWithHasherBellatrix(ctx context.Conte
|
||||
fieldRoots[10] = eth1DepositBuf[:]
|
||||
|
||||
// Validators slice root.
|
||||
validatorsRoot, err := h.validatorRegistryRoot(state.Validators)
|
||||
validatorsRoot, err := validatorRegistryRoot(state.Validators)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not compute validator registry merkleization")
|
||||
}
|
||||
@@ -464,7 +426,7 @@ func (h *stateRootHasher) ComputeFieldRootsWithHasherBellatrix(ctx context.Conte
|
||||
fieldRoots[12] = balancesRoot[:]
|
||||
|
||||
// RandaoMixes array root.
|
||||
randaoRootsRoot, err := h.arraysRoot(state.RandaoMixes, fieldparams.RandaoMixesLength, "RandaoMixes")
|
||||
randaoRootsRoot, err := arraysRoot(state.RandaoMixes, fieldparams.RandaoMixesLength)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not compute randao roots merkleization")
|
||||
}
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
package stateutil_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/config/features"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
resetCfg := features.InitWithReset(&features.Flags{EnableSSZCache: true})
|
||||
defer resetCfg()
|
||||
m.Run()
|
||||
}
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
|
||||
func TestReturnTrieLayer_OK(t *testing.T) {
|
||||
newState, _ := util.DeterministicGenesisState(t, 32)
|
||||
root, err := stateutil.RootsArrayHashTreeRoot(newState.BlockRoots(), uint64(params.BeaconConfig().SlotsPerHistoricalRoot), "BlockRoots")
|
||||
root, err := stateutil.RootsArrayHashTreeRoot(newState.BlockRoots(), uint64(params.BeaconConfig().SlotsPerHistoricalRoot))
|
||||
require.NoError(t, err)
|
||||
blockRts := newState.BlockRoots()
|
||||
roots := make([][32]byte, 0, len(blockRts))
|
||||
@@ -63,7 +63,7 @@ func TestRecomputeFromLayer_FixedSizedArray(t *testing.T) {
|
||||
require.NoError(t, newState.UpdateBlockRootAtIndex(changedIdx[0], changedRoots[0]))
|
||||
require.NoError(t, newState.UpdateBlockRootAtIndex(changedIdx[1], changedRoots[1]))
|
||||
|
||||
expectedRoot, err := stateutil.RootsArrayHashTreeRoot(newState.BlockRoots(), uint64(params.BeaconConfig().SlotsPerHistoricalRoot), "BlockRoots")
|
||||
expectedRoot, err := stateutil.RootsArrayHashTreeRoot(newState.BlockRoots(), uint64(params.BeaconConfig().SlotsPerHistoricalRoot))
|
||||
require.NoError(t, err)
|
||||
root, _, err := stateutil.RecomputeFromLayer(changedRoots, changedIdx, layers)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -87,42 +87,3 @@ func Uint64ListRootWithRegistryLimit(balances []uint64) ([32]byte, error) {
|
||||
binary.LittleEndian.PutUint64(balancesLengthRoot, uint64(len(balances)))
|
||||
return ssz.MixInLength(balancesRootsRoot, balancesLengthRoot), nil
|
||||
}
|
||||
|
||||
// validatorEncKey returns the encoded key in bytes of input `validator`,
|
||||
// the returned key bytes can be used for caching purposes.
|
||||
func validatorEncKey(validator *ethpb.Validator) []byte {
|
||||
if validator == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
enc := make([]byte, 122)
|
||||
pubkey := bytesutil.ToBytes48(validator.PublicKey)
|
||||
copy(enc[0:48], pubkey[:])
|
||||
withdrawCreds := bytesutil.ToBytes32(validator.WithdrawalCredentials)
|
||||
copy(enc[48:80], withdrawCreds[:])
|
||||
effectiveBalanceBuf := [32]byte{}
|
||||
binary.LittleEndian.PutUint64(effectiveBalanceBuf[:8], validator.EffectiveBalance)
|
||||
copy(enc[80:88], effectiveBalanceBuf[:8])
|
||||
if validator.Slashed {
|
||||
enc[88] = uint8(1)
|
||||
} else {
|
||||
enc[88] = uint8(0)
|
||||
}
|
||||
activationEligibilityBuf := [32]byte{}
|
||||
binary.LittleEndian.PutUint64(activationEligibilityBuf[:8], uint64(validator.ActivationEligibilityEpoch))
|
||||
copy(enc[89:97], activationEligibilityBuf[:8])
|
||||
|
||||
activationBuf := [32]byte{}
|
||||
binary.LittleEndian.PutUint64(activationBuf[:8], uint64(validator.ActivationEpoch))
|
||||
copy(enc[97:105], activationBuf[:8])
|
||||
|
||||
exitBuf := [32]byte{}
|
||||
binary.LittleEndian.PutUint64(exitBuf[:8], uint64(validator.ExitEpoch))
|
||||
copy(enc[105:113], exitBuf[:8])
|
||||
|
||||
withdrawalBuf := [32]byte{}
|
||||
binary.LittleEndian.PutUint64(withdrawalBuf[:8], uint64(validator.WithdrawableEpoch))
|
||||
copy(enc[113:121], withdrawalBuf[:8])
|
||||
|
||||
return enc
|
||||
}
|
||||
|
||||
@@ -4,15 +4,11 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
"github.com/prysmaticlabs/prysm/config/features"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
// computeFieldRoots returns the hash tree root computations of every field in
|
||||
// the beacon state as a list of 32 byte roots.
|
||||
func computeFieldRoots(ctx context.Context, state *ethpb.BeaconState) ([][]byte, error) {
|
||||
if features.Get().EnableSSZCache {
|
||||
return stateutil.CachedHasher.ComputeFieldRootsWithHasherPhase0(ctx, state)
|
||||
}
|
||||
return stateutil.NocachedHasher.ComputeFieldRootsWithHasherPhase0(ctx, state)
|
||||
return stateutil.ComputeFieldRootsWithHasherPhase0(ctx, state)
|
||||
}
|
||||
|
||||
@@ -4,15 +4,11 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
"github.com/prysmaticlabs/prysm/config/features"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
// computeFieldRoots returns the hash tree root computations of every field in
|
||||
// the beacon state as a list of 32 byte roots.
|
||||
func computeFieldRoots(ctx context.Context, state *ethpb.BeaconStateAltair) ([][]byte, error) {
|
||||
if features.Get().EnableSSZCache {
|
||||
return stateutil.CachedHasher.ComputeFieldRootsWithHasherAltair(ctx, state)
|
||||
}
|
||||
return stateutil.NocachedHasher.ComputeFieldRootsWithHasherAltair(ctx, state)
|
||||
return stateutil.ComputeFieldRootsWithHasherAltair(ctx, state)
|
||||
}
|
||||
|
||||
@@ -4,15 +4,11 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
"github.com/prysmaticlabs/prysm/config/features"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
// computeFieldRoots returns the hash tree root computations of every field in
|
||||
// the beacon state as a list of 32 byte roots.
|
||||
func computeFieldRoots(ctx context.Context, state *ethpb.BeaconStateBellatrix) ([][]byte, error) {
|
||||
if features.Get().EnableSSZCache {
|
||||
return stateutil.CachedHasher.ComputeFieldRootsWithHasherBellatrix(ctx, state)
|
||||
}
|
||||
return stateutil.NocachedHasher.ComputeFieldRootsWithHasherBellatrix(ctx, state)
|
||||
return stateutil.ComputeFieldRootsWithHasherBellatrix(ctx, state)
|
||||
}
|
||||
|
||||
@@ -151,7 +151,8 @@ func (s *Service) processPendingBlocks(ctx context.Context) error {
|
||||
continue
|
||||
}
|
||||
|
||||
if err := s.validateBeaconBlock(ctx, b, blkRoot); err != nil {
|
||||
genesisTime := uint64(s.cfg.chain.GenesisTime().Unix())
|
||||
if err := s.validateBeaconBlock(ctx, b, blkRoot, genesisTime); err != nil {
|
||||
log.Debugf("Could not validate block from slot %d: %v", b.Block().Slot(), err)
|
||||
s.setBadBlock(ctx, blkRoot)
|
||||
tracing.AnnotateError(span, err)
|
||||
|
||||
@@ -161,7 +161,7 @@ func (s *Service) validateBeaconBlockPubSub(ctx context.Context, pid peer.ID, ms
|
||||
return pubsub.ValidationIgnore, errors.Errorf("unknown parent for block with slot %d and parent root %#x", blk.Block().Slot(), blk.Block().ParentRoot())
|
||||
}
|
||||
|
||||
if err := s.validateBeaconBlock(ctx, blk, blockRoot); err != nil {
|
||||
if err := s.validateBeaconBlock(ctx, blk, blockRoot, genesisTime); err != nil {
|
||||
return pubsub.ValidationReject, err
|
||||
}
|
||||
|
||||
@@ -181,7 +181,7 @@ func (s *Service) validateBeaconBlockPubSub(ctx context.Context, pid peer.ID, ms
|
||||
return pubsub.ValidationAccept, nil
|
||||
}
|
||||
|
||||
func (s *Service) validateBeaconBlock(ctx context.Context, blk block.SignedBeaconBlock, blockRoot [32]byte) error {
|
||||
func (s *Service) validateBeaconBlock(ctx context.Context, blk block.SignedBeaconBlock, blockRoot [32]byte, genesisTime uint64) error {
|
||||
ctx, span := trace.StartSpan(ctx, "sync.validateBeaconBlock")
|
||||
defer span.End()
|
||||
|
||||
|
||||
@@ -23,6 +23,14 @@ var (
|
||||
Usage: "An http endpoint for an Ethereum execution node",
|
||||
Value: "",
|
||||
}
|
||||
// ExecutionJWTSecretFlag provides a path to a file containing a hex-encoded string representing a 32 byte secret
|
||||
// used to authenticate with an execution node via HTTP. This is required if using an HTTP connection, otherwise all requests
|
||||
// to execution nodes for consensus-related calls will fail. This is not required if using an IPC connection.
|
||||
ExecutionJWTSecretFlag = &cli.StringFlag{
|
||||
Name: "jwt-secret",
|
||||
Usage: "REQUIRED if connecting to an execution node via HTTP. Provides a path to a file containing a hex-encoded string representing a 32 byte secret used for authentication with an execution node via HTTP. If this is not set, all requests to execution nodes via HTTP for consensus-related calls will fail, which will prevent your validators from performing their duties. This is not required if using an IPC connection.",
|
||||
Value: "",
|
||||
}
|
||||
// FallbackWeb3ProviderFlag provides a fallback endpoint to an ETH 1.0 RPC.
|
||||
FallbackWeb3ProviderFlag = &cli.StringSliceFlag{
|
||||
Name: "fallback-web3provider",
|
||||
|
||||
@@ -34,6 +34,7 @@ var appFlags = []cli.Flag{
|
||||
flags.DepositContractFlag,
|
||||
flags.HTTPWeb3ProviderFlag,
|
||||
flags.ExecutionProviderFlag,
|
||||
flags.ExecutionJWTSecretFlag,
|
||||
flags.FallbackWeb3ProviderFlag,
|
||||
flags.RPCHost,
|
||||
flags.RPCPort,
|
||||
@@ -231,11 +232,11 @@ func startNode(ctx *cli.Context) error {
|
||||
|
||||
blockchainFlagOpts, err := blockchaincmd.FlagOptions(ctx)
|
||||
if err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
powchainFlagOpts, err := powchaincmd.FlagOptions(ctx)
|
||||
if err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
opts := []node.Option{
|
||||
node.WithBlockchainFlagOptions(blockchainFlagOpts),
|
||||
|
||||
@@ -11,6 +11,9 @@ go_library(
|
||||
deps = [
|
||||
"//beacon-chain/powchain:go_default_library",
|
||||
"//cmd/beacon-chain/flags:go_default_library",
|
||||
"//io/file:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@com_github_urfave_cli_v2//:go_default_library",
|
||||
],
|
||||
@@ -22,6 +25,8 @@ go_test(
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//cmd/beacon-chain/flags:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//io/file:go_default_library",
|
||||
"//testing/assert:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
"@com_github_sirupsen_logrus//hooks/test:go_default_library",
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
package powchaincmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
|
||||
"github.com/prysmaticlabs/prysm/cmd/beacon-chain/flags"
|
||||
"github.com/prysmaticlabs/prysm/io/file"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
@@ -13,6 +19,10 @@ var log = logrus.WithField("prefix", "cmd-powchain")
|
||||
func FlagOptions(c *cli.Context) ([]powchain.Option, error) {
|
||||
endpoints := parsePowchainEndpoints(c)
|
||||
executionEndpoint := parseExecutionEndpoint(c)
|
||||
jwtSecret, err := parseJWTSecretFromFile(c)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not read JWT secret file for authenticating execution API")
|
||||
}
|
||||
opts := []powchain.Option{
|
||||
powchain.WithHttpEndpoints(endpoints),
|
||||
powchain.WithEth1HeaderRequestLimit(c.Uint64(flags.Eth1HeaderReqLimit.Name)),
|
||||
@@ -20,9 +30,43 @@ func FlagOptions(c *cli.Context) ([]powchain.Option, error) {
|
||||
if executionEndpoint != "" {
|
||||
opts = append(opts, powchain.WithExecutionEndpoint(executionEndpoint))
|
||||
}
|
||||
if len(jwtSecret) > 0 {
|
||||
opts = append(opts, powchain.WithExecutionClientJWTSecret(jwtSecret))
|
||||
}
|
||||
return opts, nil
|
||||
}
|
||||
|
||||
// Parses a JWT secret from a file path. This secret is required when connecting to execution nodes
|
||||
// over HTTP, and must be the same one used in Prysm and the execution node server Prysm is connecting to.
|
||||
// The engine API specification here https://github.com/ethereum/execution-apis/blob/main/src/engine/authentication.md
|
||||
// Explains how we should validate this secret and the format of the file a user can specify.
|
||||
//
|
||||
// The secret must be stored as a hex-encoded string within a file in the filesystem.
|
||||
// If the --jwt-secret flag is provided to Prysm, but the file cannot be read, or does not contain a hex-encoded
|
||||
// key of at least 256 bits, the client should treat this as an error and abort the startup.
|
||||
func parseJWTSecretFromFile(c *cli.Context) ([]byte, error) {
|
||||
jwtSecretFile := c.String(flags.ExecutionJWTSecretFlag.Name)
|
||||
if jwtSecretFile == "" {
|
||||
return nil, nil
|
||||
}
|
||||
enc, err := file.ReadFileAsBytes(jwtSecretFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
strData := strings.TrimSpace(string(enc))
|
||||
if len(strData) == 0 {
|
||||
return nil, fmt.Errorf("provided JWT secret in file %s cannot be empty", jwtSecretFile)
|
||||
}
|
||||
secret, err := hexutil.Decode(strData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(secret) < 32 {
|
||||
return nil, errors.New("provided JWT secret should be a hex string of at least 32 bytes")
|
||||
}
|
||||
return secret, nil
|
||||
}
|
||||
|
||||
func parsePowchainEndpoints(c *cli.Context) []string {
|
||||
if c.String(flags.HTTPWeb3ProviderFlag.Name) == "" && len(c.StringSlice(flags.FallbackWeb3ProviderFlag.Name)) == 0 {
|
||||
log.Error(
|
||||
|
||||
@@ -2,9 +2,14 @@ package powchaincmd
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/cmd/beacon-chain/flags"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/io/file"
|
||||
"github.com/prysmaticlabs/prysm/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/testing/require"
|
||||
logTest "github.com/sirupsen/logrus/hooks/test"
|
||||
@@ -27,6 +32,92 @@ func TestPowchainCmd(t *testing.T) {
|
||||
assert.DeepEqual(t, []string{"primary", "fallback1", "fallback2"}, endpoints)
|
||||
}
|
||||
|
||||
func Test_parseJWTSecretFromFile(t *testing.T) {
|
||||
t.Run("no flag value specified leads to nil secret", func(t *testing.T) {
|
||||
app := cli.App{}
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.String(flags.ExecutionJWTSecretFlag.Name, "", "")
|
||||
ctx := cli.NewContext(&app, set, nil)
|
||||
secret, err := parseJWTSecretFromFile(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, true, secret == nil)
|
||||
})
|
||||
t.Run("flag specified but no file found", func(t *testing.T) {
|
||||
app := cli.App{}
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.String(flags.ExecutionJWTSecretFlag.Name, "/tmp/askdjkajsd", "")
|
||||
ctx := cli.NewContext(&app, set, nil)
|
||||
_, err := parseJWTSecretFromFile(ctx)
|
||||
require.ErrorContains(t, "no such file", err)
|
||||
})
|
||||
t.Run("empty string in file", func(t *testing.T) {
|
||||
app := cli.App{}
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
fullPath := filepath.Join(os.TempDir(), "foohex")
|
||||
require.NoError(t, file.WriteFile(fullPath, []byte{}))
|
||||
t.Cleanup(func() {
|
||||
if err := os.RemoveAll(fullPath); err != nil {
|
||||
t.Fatalf("Could not delete temp dir: %v", err)
|
||||
}
|
||||
})
|
||||
set.String(flags.ExecutionJWTSecretFlag.Name, fullPath, "")
|
||||
ctx := cli.NewContext(&app, set, nil)
|
||||
_, err := parseJWTSecretFromFile(ctx)
|
||||
require.ErrorContains(t, "cannot be empty", err)
|
||||
})
|
||||
t.Run("less than 32 bytes", func(t *testing.T) {
|
||||
app := cli.App{}
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
fullPath := filepath.Join(os.TempDir(), "foohex")
|
||||
secret := bytesutil.PadTo([]byte("foo"), 31)
|
||||
hexData := fmt.Sprintf("%#x", secret)
|
||||
require.NoError(t, file.WriteFile(fullPath, []byte(hexData)))
|
||||
t.Cleanup(func() {
|
||||
if err := os.RemoveAll(fullPath); err != nil {
|
||||
t.Fatalf("Could not delete temp dir: %v", err)
|
||||
}
|
||||
})
|
||||
set.String(flags.ExecutionJWTSecretFlag.Name, fullPath, "")
|
||||
ctx := cli.NewContext(&app, set, nil)
|
||||
_, err := parseJWTSecretFromFile(ctx)
|
||||
require.ErrorContains(t, "should be a hex string of at least 32 bytes", err)
|
||||
})
|
||||
t.Run("bad data", func(t *testing.T) {
|
||||
app := cli.App{}
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
fullPath := filepath.Join(os.TempDir(), "foohex")
|
||||
secret := []byte("foo")
|
||||
require.NoError(t, file.WriteFile(fullPath, secret))
|
||||
t.Cleanup(func() {
|
||||
if err := os.RemoveAll(fullPath); err != nil {
|
||||
t.Fatalf("Could not delete temp dir: %v", err)
|
||||
}
|
||||
})
|
||||
set.String(flags.ExecutionJWTSecretFlag.Name, fullPath, "")
|
||||
ctx := cli.NewContext(&app, set, nil)
|
||||
_, err := parseJWTSecretFromFile(ctx)
|
||||
require.ErrorContains(t, "invalid byte", err)
|
||||
})
|
||||
t.Run("correct format", func(t *testing.T) {
|
||||
app := cli.App{}
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
fullPath := filepath.Join(os.TempDir(), "foohex")
|
||||
secret := bytesutil.ToBytes32([]byte("foo"))
|
||||
secretHex := fmt.Sprintf("%#x", secret)
|
||||
require.NoError(t, file.WriteFile(fullPath, []byte(secretHex)))
|
||||
t.Cleanup(func() {
|
||||
if err := os.RemoveAll(fullPath); err != nil {
|
||||
t.Fatalf("Could not delete temp dir: %v", err)
|
||||
}
|
||||
})
|
||||
set.String(flags.ExecutionJWTSecretFlag.Name, fullPath, "")
|
||||
ctx := cli.NewContext(&app, set, nil)
|
||||
got, err := parseJWTSecretFromFile(ctx)
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, secret[:], got)
|
||||
})
|
||||
}
|
||||
|
||||
func TestPowchainPreregistration_EmptyWeb3Provider(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
app := cli.App{}
|
||||
|
||||
@@ -107,6 +107,7 @@ var appHelpFlagGroups = []flagGroup{
|
||||
flags.GPRCGatewayCorsDomain,
|
||||
flags.HTTPWeb3ProviderFlag,
|
||||
flags.ExecutionProviderFlag,
|
||||
flags.ExecutionJWTSecretFlag,
|
||||
flags.FallbackWeb3ProviderFlag,
|
||||
flags.SetGCPercent,
|
||||
flags.HeadSync,
|
||||
|
||||
@@ -37,6 +37,7 @@ const disabledFeatureFlag = "Disabled feature flag"
|
||||
type Flags struct {
|
||||
// Testnet Flags.
|
||||
PyrmontTestnet bool // PyrmontTestnet defines the flag through which we can enable the node to run on the Pyrmont testnet.
|
||||
KilnTestnet bool // KilnTestnet defines the flag through which we can enable node to run on the merge testnet.
|
||||
|
||||
// Feature related flags.
|
||||
RemoteSlasherProtection bool // RemoteSlasherProtection utilizes a beacon node with --slasher mode for validator slashing protection.
|
||||
@@ -61,7 +62,6 @@ type Flags struct {
|
||||
DisableBroadcastSlashings bool // DisableBroadcastSlashings disables p2p broadcasting of proposer and attester slashings.
|
||||
|
||||
// Cache toggles.
|
||||
EnableSSZCache bool // EnableSSZCache see https://github.com/prysmaticlabs/prysm/pull/4558.
|
||||
EnableActiveBalanceCache bool // EnableActiveBalanceCache enables active balance cache.
|
||||
|
||||
// Bug fixes related flags.
|
||||
@@ -130,6 +130,11 @@ func configureTestnet(ctx *cli.Context, cfg *Flags) {
|
||||
log.Warn("Running on the Prater Testnet")
|
||||
params.UsePraterConfig()
|
||||
params.UsePraterNetworkConfig()
|
||||
} else if ctx.Bool(KilnTestnet.Name) {
|
||||
log.Warn("Running on the Kiln(merge) Testnet")
|
||||
params.UseMergeTestConfig()
|
||||
params.UseMergeTestNetworkConfig()
|
||||
cfg.KilnTestnet = true
|
||||
} else {
|
||||
log.Warn("Running on Ethereum Consensus Mainnet")
|
||||
params.UseMainnetConfig()
|
||||
@@ -151,8 +156,6 @@ func ConfigureBeaconChain(ctx *cli.Context) {
|
||||
cfg.WriteSSZStateTransitions = true
|
||||
}
|
||||
|
||||
cfg.EnableSSZCache = true
|
||||
|
||||
if ctx.IsSet(disableGRPCConnectionLogging.Name) {
|
||||
logDisabled(disableGRPCConnectionLogging)
|
||||
cfg.DisableGRPCConnectionLogs = true
|
||||
|
||||
@@ -17,6 +17,11 @@ var (
|
||||
Name: "prater",
|
||||
Usage: "Run Prysm configured for the Prater test network",
|
||||
}
|
||||
// KilnTestnet flag for the multiclient Ethereum consensus testnet.
|
||||
KilnTestnet = &cli.BoolFlag{
|
||||
Name: "kiln-testnet",
|
||||
Usage: "Run Prysm configured for the kiln test network",
|
||||
}
|
||||
// Mainnet flag for easier tooling, no-op
|
||||
Mainnet = &cli.BoolFlag{
|
||||
Value: true,
|
||||
@@ -148,6 +153,7 @@ var ValidatorFlags = append(deprecatedFlags, []cli.Flag{
|
||||
disableAttestingHistoryDBCache,
|
||||
PyrmontTestnet,
|
||||
PraterTestnet,
|
||||
KilnTestnet,
|
||||
Mainnet,
|
||||
dynamicKeyReloadDebounceInterval,
|
||||
attestTimely,
|
||||
@@ -167,6 +173,7 @@ var BeaconChainFlags = append(deprecatedFlags, []cli.Flag{
|
||||
disableGRPCConnectionLogging,
|
||||
PyrmontTestnet,
|
||||
PraterTestnet,
|
||||
KilnTestnet,
|
||||
Mainnet,
|
||||
enablePeerScorer,
|
||||
enableLargerGossipHistory,
|
||||
|
||||
@@ -12,6 +12,7 @@ go_library(
|
||||
"minimal_config.go",
|
||||
"network_config.go",
|
||||
"testnet_e2e_config.go",
|
||||
"testnet_kiln_config.go",
|
||||
"testnet_prater_config.go",
|
||||
"testnet_pyrmont_config.go",
|
||||
"testutils.go",
|
||||
|
||||
22
config/params/testnet_kiln_config.go
Normal file
22
config/params/testnet_kiln_config.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package params
|
||||
|
||||
// UseMergeTestNetworkConfig uses the Merge specific
|
||||
// network config.
|
||||
func UseMergeTestNetworkConfig() {
|
||||
cfg := BeaconNetworkConfig().Copy()
|
||||
cfg.ContractDeploymentBlock = 0
|
||||
cfg.BootstrapNodes = []string{}
|
||||
OverrideBeaconNetworkConfig(cfg)
|
||||
}
|
||||
|
||||
// UseMergeTestConfig sets the main beacon chain
|
||||
// config for Merge testnet.
|
||||
func UseMergeTestConfig() {
|
||||
beaconConfig = KilnTestnetConfig()
|
||||
}
|
||||
|
||||
// KilnTestnetConfig defines the config for the Kiln testnet.
|
||||
func KilnTestnetConfig() *BeaconChainConfig {
|
||||
cfg := MainnetConfig().Copy()
|
||||
return cfg
|
||||
}
|
||||
@@ -25,6 +25,17 @@ config_setting(
|
||||
},
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "darwin_arm64",
|
||||
constraint_values = [
|
||||
"@platforms//os:osx",
|
||||
"@platforms//cpu:arm64",
|
||||
],
|
||||
values = {
|
||||
"define": "blst_disabled=false",
|
||||
},
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "windows_amd64",
|
||||
constraint_values = [
|
||||
@@ -79,6 +90,7 @@ go_library(
|
||||
":linux_amd64",
|
||||
":linux_arm64",
|
||||
":darwin_amd64",
|
||||
":darwin_arm64",
|
||||
":windows_amd64",
|
||||
":android_amd64",
|
||||
":android_arm64",
|
||||
@@ -103,6 +115,7 @@ go_library(
|
||||
":linux_amd64",
|
||||
":linux_arm64",
|
||||
":darwin_amd64",
|
||||
":darwin_arm64",
|
||||
":windows_amd64",
|
||||
":android_amd64",
|
||||
":android_arm64",
|
||||
@@ -128,6 +141,7 @@ go_test(
|
||||
":linux_amd64",
|
||||
":linux_arm64",
|
||||
":darwin_amd64",
|
||||
":darwin_arm64",
|
||||
":windows_amd64",
|
||||
":android_amd64",
|
||||
":android_arm64",
|
||||
@@ -142,6 +156,7 @@ go_test(
|
||||
":linux_amd64",
|
||||
":linux_arm64",
|
||||
":darwin_amd64",
|
||||
":darwin_arm64",
|
||||
":windows_amd64",
|
||||
":android_amd64",
|
||||
":android_arm64",
|
||||
@@ -164,6 +179,7 @@ go_test(
|
||||
":linux_amd64",
|
||||
":linux_arm64",
|
||||
":darwin_amd64",
|
||||
":darwin_arm64",
|
||||
":windows_amd64",
|
||||
":android_amd64",
|
||||
":android_arm64",
|
||||
@@ -178,6 +194,7 @@ go_test(
|
||||
":linux_amd64",
|
||||
":linux_arm64",
|
||||
":darwin_amd64",
|
||||
":darwin_arm64",
|
||||
":windows_amd64",
|
||||
":android_amd64",
|
||||
":android_arm64",
|
||||
|
||||
9
deps.bzl
9
deps.bzl
@@ -659,8 +659,8 @@ def prysm_deps():
|
||||
go_repository(
|
||||
name = "com_github_deckarep_golang_set",
|
||||
importpath = "github.com/deckarep/golang-set",
|
||||
sum = "h1:SCQV0S6gTtp6itiFrTqI+pfmJ4LN85S1YzhDf9rTHJQ=",
|
||||
version = "v1.7.1",
|
||||
sum = "h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsPppp4=",
|
||||
version = "v1.8.0",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
@@ -825,8 +825,9 @@ def prysm_deps():
|
||||
importpath = "github.com/ethereum/go-ethereum",
|
||||
patch_args = ["-p1"],
|
||||
patches = ["//third_party:com_github_ethereum_go_ethereum_secp256k1.patch"],
|
||||
sum = "h1:DEYFP9zk+Gruf3ae1JOJVhNmxK28ee+sMELPLgYTXpA=",
|
||||
version = "v1.10.13",
|
||||
replace = "github.com/MariusVanDerWijden/go-ethereum",
|
||||
sum = "h1:nZkWdyuB0ehjFrXFx3HLfLF8e6F9oS/32MRhiT5zHdk=",
|
||||
version = "v1.8.22-0.20220214112821-d40107742729",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
|
||||
@@ -34,8 +34,8 @@ func Depth(v uint64) (out uint8) {
|
||||
// Then adding 1 to it to not get the index of the first bit, but the length of the bits (depth of tree)
|
||||
// Zero is a special case, it has a 0 depth.
|
||||
// Example:
|
||||
// (in out): (0 0), (1 1), (2 1), (3 2), (4 2), (5 3), (6 3), (7 3), (8 3), (9 4)
|
||||
if v == 0 {
|
||||
// (in out): (0 0), (1 0), (2 1), (3 2), (4 2), (5 3), (6 3), (7 3), (8 3), (9 4)
|
||||
if v <= 1 {
|
||||
return 0
|
||||
}
|
||||
v--
|
||||
|
||||
@@ -112,3 +112,7 @@ func TestConstructProofNormalPath(t *testing.T) {
|
||||
assert.DeepEqual(t, result[i], v)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDepthOfOne(t *testing.T) {
|
||||
assert.Equal(t, uint8(0), ssz.Depth(1))
|
||||
}
|
||||
|
||||
155
go.mod
155
go.mod
@@ -1,6 +1,6 @@
|
||||
module github.com/prysmaticlabs/prysm
|
||||
|
||||
go 1.16
|
||||
go 1.17
|
||||
|
||||
require (
|
||||
contrib.go.opencensus.io/exporter/jaeger v0.2.1
|
||||
@@ -10,7 +10,7 @@ require (
|
||||
github.com/dgraph-io/ristretto v0.0.4-0.20210318174700-74754f61e018
|
||||
github.com/dustin/go-humanize v1.0.0
|
||||
github.com/emicklei/dot v0.11.0
|
||||
github.com/ethereum/go-ethereum v1.10.13
|
||||
github.com/ethereum/go-ethereum v1.10.15
|
||||
github.com/ferranbt/fastssz v0.0.0-20210905181407-59cf6761a7d5
|
||||
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5
|
||||
github.com/fsnotify/fsnotify v1.4.9
|
||||
@@ -30,6 +30,7 @@ require (
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.0.1
|
||||
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d
|
||||
github.com/herumi/bls-eth-go-binary v0.0.0-20210917013441-d37c07cfda4e
|
||||
github.com/holiman/uint256 v1.2.0
|
||||
github.com/ianlancetaylor/cgosymbolizer v0.0.0-20200424224625-be1b05b0b279
|
||||
github.com/ipfs/go-log/v2 v2.4.0
|
||||
github.com/joonix/log v0.0.0-20200409080653-9c1d2ceb5f1d
|
||||
@@ -93,18 +94,162 @@ require (
|
||||
k8s.io/client-go v0.18.3
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/BurntSushi/toml v0.3.1 // indirect
|
||||
github.com/VictoriaMetrics/fastcache v1.6.0 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/btcsuite/btcd v0.22.0-beta // indirect
|
||||
github.com/cespare/xxhash v1.1.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.1.1 // indirect
|
||||
github.com/cheekybits/genny v1.0.0 // indirect
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect
|
||||
github.com/deepmap/oapi-codegen v1.8.2 // indirect
|
||||
github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91 // indirect
|
||||
github.com/dop251/goja v0.0.0-20211011172007-d99e4b8cbf48 // indirect
|
||||
github.com/edsrzf/mmap-go v1.0.0 // indirect
|
||||
github.com/flynn/noise v1.0.0 // indirect
|
||||
github.com/francoispqt/gojay v1.2.13 // indirect
|
||||
github.com/go-playground/locales v0.14.0 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.0 // indirect
|
||||
github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect
|
||||
github.com/go-stack/stack v1.8.0 // indirect
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect
|
||||
github.com/google/go-cmp v0.5.5 // indirect
|
||||
github.com/google/gopacket v1.1.19 // indirect
|
||||
github.com/gorilla/websocket v1.4.2 // indirect
|
||||
github.com/graph-gophers/graphql-go v0.0.0-20201113091052-beb923fada29 // indirect
|
||||
github.com/hashicorp/go-bexpr v0.1.10 // indirect
|
||||
github.com/holiman/bloomfilter/v2 v2.0.3 // indirect
|
||||
github.com/huin/goupnp v1.0.2 // indirect
|
||||
github.com/influxdata/influxdb v1.8.3 // indirect
|
||||
github.com/influxdata/influxdb-client-go/v2 v2.4.0 // indirect
|
||||
github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 // indirect
|
||||
github.com/ipfs/go-cid v0.0.7 // indirect
|
||||
github.com/ipfs/go-ipfs-util v0.0.2 // indirect
|
||||
github.com/ipfs/go-log v1.0.5 // indirect
|
||||
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
|
||||
github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect
|
||||
github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a // indirect
|
||||
github.com/karalabe/usb v0.0.0-20211005121534-4c5740d64559 // indirect
|
||||
github.com/klauspost/compress v1.11.7 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3 // indirect
|
||||
github.com/koron/go-ssdp v0.0.2 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/leodido/go-urn v1.2.1 // indirect
|
||||
github.com/libp2p/go-addr-util v0.1.0 // indirect
|
||||
github.com/libp2p/go-buffer-pool v0.0.2 // indirect
|
||||
github.com/libp2p/go-cidranger v1.1.0 // indirect
|
||||
github.com/libp2p/go-conn-security-multistream v0.3.0 // indirect
|
||||
github.com/libp2p/go-eventbus v0.2.1 // indirect
|
||||
github.com/libp2p/go-flow-metrics v0.0.3 // indirect
|
||||
github.com/libp2p/go-libp2p-asn-util v0.1.0 // indirect
|
||||
github.com/libp2p/go-libp2p-autonat v0.7.0 // indirect
|
||||
github.com/libp2p/go-libp2p-discovery v0.6.0 // indirect
|
||||
github.com/libp2p/go-libp2p-mplex v0.4.1 // indirect
|
||||
github.com/libp2p/go-libp2p-nat v0.1.0 // indirect
|
||||
github.com/libp2p/go-libp2p-pnet v0.2.0 // indirect
|
||||
github.com/libp2p/go-libp2p-quic-transport v0.15.2 // indirect
|
||||
github.com/libp2p/go-libp2p-testing v0.6.0 // indirect
|
||||
github.com/libp2p/go-libp2p-tls v0.3.1 // indirect
|
||||
github.com/libp2p/go-libp2p-transport-upgrader v0.6.0 // indirect
|
||||
github.com/libp2p/go-libp2p-yamux v0.7.0 // indirect
|
||||
github.com/libp2p/go-maddr-filter v0.1.0 // indirect
|
||||
github.com/libp2p/go-mplex v0.3.0 // indirect
|
||||
github.com/libp2p/go-msgio v0.1.0 // indirect
|
||||
github.com/libp2p/go-nat v0.1.0 // indirect
|
||||
github.com/libp2p/go-netroute v0.1.6 // indirect
|
||||
github.com/libp2p/go-openssl v0.0.7 // indirect
|
||||
github.com/libp2p/go-reuseport v0.1.0 // indirect
|
||||
github.com/libp2p/go-reuseport-transport v0.1.0 // indirect
|
||||
github.com/libp2p/go-sockaddr v0.1.1 // indirect
|
||||
github.com/libp2p/go-stream-muxer-multistream v0.3.0 // indirect
|
||||
github.com/libp2p/go-ws-transport v0.5.0 // indirect
|
||||
github.com/libp2p/go-yamux/v2 v2.3.0 // indirect
|
||||
github.com/lucas-clemente/quic-go v0.24.0 // indirect
|
||||
github.com/lunixbochs/vtclean v1.0.0 // indirect
|
||||
github.com/marten-seemann/qtls-go1-16 v0.1.4 // indirect
|
||||
github.com/marten-seemann/qtls-go1-17 v0.1.0 // indirect
|
||||
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect
|
||||
github.com/mattn/go-colorable v0.1.8 // indirect
|
||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.9 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect
|
||||
github.com/miekg/dns v1.1.43 // indirect
|
||||
github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect
|
||||
github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect
|
||||
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 // indirect
|
||||
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
|
||||
github.com/mitchellh/mapstructure v1.4.1 // indirect
|
||||
github.com/mitchellh/pointerstructure v1.2.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.1 // indirect
|
||||
github.com/mr-tron/base58 v1.2.0 // indirect
|
||||
github.com/multiformats/go-base32 v0.0.3 // indirect
|
||||
github.com/multiformats/go-base36 v0.1.0 // indirect
|
||||
github.com/multiformats/go-multiaddr-dns v0.3.1 // indirect
|
||||
github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect
|
||||
github.com/multiformats/go-multibase v0.0.3 // indirect
|
||||
github.com/multiformats/go-multihash v0.0.15 // indirect
|
||||
github.com/multiformats/go-multistream v0.2.2 // indirect
|
||||
github.com/multiformats/go-varint v0.0.6 // indirect
|
||||
github.com/nxadm/tail v1.4.8 // indirect
|
||||
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
||||
github.com/onsi/ginkgo v1.16.4 // indirect
|
||||
github.com/opentracing/opentracing-go v1.2.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/prometheus/common v0.30.0 // indirect
|
||||
github.com/prometheus/procfs v0.7.3 // indirect
|
||||
github.com/rjeczalik/notify v0.9.1 // indirect
|
||||
github.com/rogpeppe/go-internal v1.8.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.0.1 // indirect
|
||||
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
|
||||
github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 // indirect
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.5 // indirect
|
||||
github.com/tklauser/numcpus v0.2.2 // indirect
|
||||
github.com/uber/jaeger-client-go v2.25.0+incompatible // indirect
|
||||
github.com/wealdtech/go-eth2-types/v2 v2.5.2 // indirect
|
||||
github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 // indirect
|
||||
github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee // indirect
|
||||
go.uber.org/atomic v1.9.0 // indirect
|
||||
go.uber.org/multierr v1.7.0 // indirect
|
||||
go.uber.org/zap v1.19.0 // indirect
|
||||
golang.org/x/mod v0.5.1 // indirect
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c // indirect
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||
gopkg.in/cenkalti/backoff.v1 v1.1.0 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||
gopkg.in/urfave/cli.v1 v1.20.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
||||
k8s.io/apimachinery v0.18.3 // indirect
|
||||
k8s.io/klog v1.0.0 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0 // indirect
|
||||
sigs.k8s.io/yaml v1.2.0 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46 // indirect
|
||||
github.com/allegro/bigcache v1.2.1 // indirect
|
||||
github.com/cespare/cp v1.1.1 // indirect
|
||||
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf // indirect
|
||||
github.com/deckarep/golang-set v1.7.1 // indirect
|
||||
github.com/fatih/color v1.9.0 // indirect
|
||||
github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect
|
||||
github.com/go-logr/logr v0.2.1 // indirect
|
||||
github.com/go-ole/go-ole v1.2.5 // indirect
|
||||
github.com/go-playground/validator/v10 v10.10.0
|
||||
github.com/holiman/uint256 v1.2.0
|
||||
github.com/peterh/liner v1.2.0 // indirect
|
||||
github.com/prometheus/tsdb v0.10.0 // indirect
|
||||
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881 // indirect
|
||||
@@ -114,6 +259,8 @@ require (
|
||||
k8s.io/utils v0.0.0-20200520001619-278ece378a50 // indirect
|
||||
)
|
||||
|
||||
replace github.com/ethereum/go-ethereum => github.com/MariusVanDerWijden/go-ethereum v1.8.22-0.20220214112821-d40107742729
|
||||
|
||||
replace github.com/json-iterator/go => github.com/prestonvanloon/go v1.1.7-0.20190722034630-4f2e55fcf87b
|
||||
|
||||
// See https://github.com/prysmaticlabs/grpc-gateway/issues/2
|
||||
|
||||
10
go.sum
10
go.sum
@@ -66,6 +66,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
|
||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||
github.com/MariusVanDerWijden/go-ethereum v1.8.22-0.20220214112821-d40107742729 h1:nZkWdyuB0ehjFrXFx3HLfLF8e6F9oS/32MRhiT5zHdk=
|
||||
github.com/MariusVanDerWijden/go-ethereum v1.8.22-0.20220214112821-d40107742729/go.mod h1:yDL1pvpRjK/y5f25Cev5ITtywS9XqJAjhjWwm8ZfycI=
|
||||
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
|
||||
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
@@ -217,9 +219,8 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
|
||||
github.com/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018/go.mod h1:rQYf4tfk5sSwFsnDg3qYaBxSjsD9S8+59vW0dKUgme4=
|
||||
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c h1:pFUpOrbxDR6AkioZ1ySsx5yxlDQZ8stG2b88gTPxgJU=
|
||||
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6UhI8N9EjYm1c2odKpFpAYeR8dsBeM7PtzQhRgxRr9U=
|
||||
github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ=
|
||||
github.com/deckarep/golang-set v1.7.1 h1:SCQV0S6gTtp6itiFrTqI+pfmJ4LN85S1YzhDf9rTHJQ=
|
||||
github.com/deckarep/golang-set v1.7.1/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ=
|
||||
github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsPppp4=
|
||||
github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo=
|
||||
github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218=
|
||||
github.com/deepmap/oapi-codegen v1.6.0/go.mod h1:ryDa9AgbELGeB+YEXE1dR53yAjHwFvE9iAUlWl9Al3M=
|
||||
github.com/deepmap/oapi-codegen v1.8.2 h1:SegyeYGcdi0jLLrpbCMoJxnUUn8GBXHsvr4rbzjuhfU=
|
||||
@@ -264,8 +265,6 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/ethereum/go-ethereum v1.10.13 h1:DEYFP9zk+Gruf3ae1JOJVhNmxK28ee+sMELPLgYTXpA=
|
||||
github.com/ethereum/go-ethereum v1.10.13/go.mod h1:W3yfrFyL9C1pHcwY5hmRHVDaorTiQxhYBkKyu5mEDHw=
|
||||
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s=
|
||||
@@ -579,7 +578,6 @@ github.com/ipfs/go-log/v2 v2.1.3/go.mod h1:/8d0SH3Su5Ooc31QlL1WysJhvyOTDCjcCZ9Ax
|
||||
github.com/ipfs/go-log/v2 v2.3.0/go.mod h1:QqGoj30OTpnKaG/LKTGTxoP2mmQtjVMEnK72gynbe/g=
|
||||
github.com/ipfs/go-log/v2 v2.4.0 h1:iR/2o9PGWanVJrBgIH5Ff8mPGOwpqLaPIAFqSnsdlzk=
|
||||
github.com/ipfs/go-log/v2 v2.4.0/go.mod h1:nPZnh7Cj7lwS3LpRU5Mwr2ol1c2gXIEXuF6aywqrtmo=
|
||||
github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
|
||||
github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
|
||||
github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
|
||||
github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA=
|
||||
|
||||
8
proto/engine/v1/execution_engine.pb.go
generated
8
proto/engine/v1/execution_engine.pb.go
generated
@@ -98,7 +98,7 @@ type ExecutionBlock struct {
|
||||
ReceiptsRoot []byte `protobuf:"bytes,8,opt,name=receipts_root,json=receiptsRoot,proto3" json:"receipts_root,omitempty"`
|
||||
LogsBloom []byte `protobuf:"bytes,9,opt,name=logs_bloom,json=logsBloom,proto3" json:"logs_bloom,omitempty"`
|
||||
Difficulty []byte `protobuf:"bytes,10,opt,name=difficulty,proto3" json:"difficulty,omitempty"`
|
||||
TotalDifficulty []byte `protobuf:"bytes,11,opt,name=total_difficulty,json=totalDifficulty,proto3" json:"total_difficulty,omitempty"`
|
||||
TotalDifficulty string `protobuf:"bytes,11,opt,name=total_difficulty,json=totalDifficulty,proto3" json:"total_difficulty,omitempty"`
|
||||
GasLimit uint64 `protobuf:"varint,12,opt,name=gas_limit,json=gasLimit,proto3" json:"gas_limit,omitempty"`
|
||||
GasUsed uint64 `protobuf:"varint,13,opt,name=gas_used,json=gasUsed,proto3" json:"gas_used,omitempty"`
|
||||
BaseFeePerGas []byte `protobuf:"bytes,14,opt,name=base_fee_per_gas,json=baseFeePerGas,proto3" json:"base_fee_per_gas,omitempty"`
|
||||
@@ -213,11 +213,11 @@ func (x *ExecutionBlock) GetDifficulty() []byte {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *ExecutionBlock) GetTotalDifficulty() []byte {
|
||||
func (x *ExecutionBlock) GetTotalDifficulty() string {
|
||||
if x != nil {
|
||||
return x.TotalDifficulty
|
||||
}
|
||||
return nil
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *ExecutionBlock) GetGasLimit() uint64 {
|
||||
@@ -723,7 +723,7 @@ var file_proto_engine_v1_execution_engine_proto_rawDesc = []byte{
|
||||
0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x69, 0x66, 0x66, 0x69, 0x63, 0x75, 0x6c, 0x74, 0x79, 0x18, 0x0a,
|
||||
0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x64, 0x69, 0x66, 0x66, 0x69, 0x63, 0x75, 0x6c, 0x74, 0x79,
|
||||
0x12, 0x29, 0x0a, 0x10, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x64, 0x69, 0x66, 0x66, 0x69, 0x63,
|
||||
0x75, 0x6c, 0x74, 0x79, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x74, 0x6f, 0x74, 0x61,
|
||||
0x75, 0x6c, 0x74, 0x79, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x74, 0x6f, 0x74, 0x61,
|
||||
0x6c, 0x44, 0x69, 0x66, 0x66, 0x69, 0x63, 0x75, 0x6c, 0x74, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x67,
|
||||
0x61, 0x73, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08,
|
||||
0x67, 0x61, 0x73, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x67, 0x61, 0x73, 0x5f,
|
||||
|
||||
@@ -35,10 +35,10 @@ message ExecutionBlock {
|
||||
bytes receipts_root = 8;
|
||||
bytes logs_bloom = 9;
|
||||
bytes difficulty = 10;
|
||||
bytes total_difficulty = 11;
|
||||
string total_difficulty = 11;
|
||||
uint64 gas_limit = 12;
|
||||
uint64 gas_used = 13;
|
||||
bytes base_fee_per_gas = 14;
|
||||
bytes base_fee_per_gas = 14;
|
||||
bytes size = 15;
|
||||
uint64 timestamp = 16;
|
||||
bytes extra_data = 17;
|
||||
|
||||
@@ -71,9 +71,6 @@ func (e *ExecutionBlock) MarshalJSON() ([]byte, error) {
|
||||
diff := new(big.Int).SetBytes(e.Difficulty)
|
||||
diffHex := hexutil.EncodeBig(diff)
|
||||
|
||||
totalDiff := new(big.Int).SetBytes(e.TotalDifficulty)
|
||||
totalDiffHex := hexutil.EncodeBig(totalDiff)
|
||||
|
||||
size := new(big.Int).SetBytes(e.Size)
|
||||
sizeHex := hexutil.EncodeBig(size)
|
||||
|
||||
@@ -90,7 +87,7 @@ func (e *ExecutionBlock) MarshalJSON() ([]byte, error) {
|
||||
ReceiptsRoot: e.ReceiptsRoot,
|
||||
LogsBloom: e.LogsBloom,
|
||||
Difficulty: diffHex,
|
||||
TotalDifficulty: totalDiffHex,
|
||||
TotalDifficulty: e.TotalDifficulty,
|
||||
GasLimit: hexutil.Uint64(e.GasLimit),
|
||||
GasUsed: hexutil.Uint64(e.GasUsed),
|
||||
Timestamp: hexutil.Uint64(e.Timestamp),
|
||||
@@ -130,11 +127,7 @@ func (e *ExecutionBlock) UnmarshalJSON(enc []byte) error {
|
||||
return err
|
||||
}
|
||||
e.Difficulty = diff.Bytes()
|
||||
totalDiff, err := hexutil.DecodeBig(dec.TotalDifficulty)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
e.TotalDifficulty = totalDiff.Bytes()
|
||||
e.TotalDifficulty = dec.TotalDifficulty
|
||||
e.GasLimit = uint64(dec.GasLimit)
|
||||
e.GasUsed = uint64(dec.GasUsed)
|
||||
e.Timestamp = uint64(dec.Timestamp)
|
||||
@@ -187,7 +180,7 @@ func (e *ExecutionPayload) MarshalJSON() ([]byte, error) {
|
||||
for i, tx := range e.Transactions {
|
||||
transactions[i] = tx
|
||||
}
|
||||
baseFee := new(big.Int).SetBytes(e.BaseFeePerGas)
|
||||
baseFee := new(big.Int).SetBytes(bytesutil.ReverseByteOrder(e.BaseFeePerGas))
|
||||
baseFeeHex := hexutil.EncodeBig(baseFee)
|
||||
return json.Marshal(executionPayloadJSON{
|
||||
ParentHash: e.ParentHash,
|
||||
@@ -290,9 +283,13 @@ func (p *PayloadStatus) UnmarshalJSON(enc []byte) error {
|
||||
return err
|
||||
}
|
||||
*p = PayloadStatus{}
|
||||
p.LatestValidHash = *dec.LatestValidHash
|
||||
if dec.LatestValidHash != nil {
|
||||
p.LatestValidHash = *dec.LatestValidHash
|
||||
}
|
||||
p.Status = PayloadStatus_Status(PayloadStatus_Status_value[dec.Status])
|
||||
p.ValidationError = *dec.ValidationError
|
||||
if dec.ValidationError != nil {
|
||||
p.ValidationError = *dec.ValidationError
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -134,7 +134,7 @@ func TestJsonMarshalUnmarshal(t *testing.T) {
|
||||
ReceiptsRoot: []byte("receiptsRoot"),
|
||||
LogsBloom: []byte("logsBloom"),
|
||||
Difficulty: []byte("1"),
|
||||
TotalDifficulty: []byte("2"),
|
||||
TotalDifficulty: "2",
|
||||
GasLimit: 3,
|
||||
GasUsed: 4,
|
||||
Timestamp: 5,
|
||||
@@ -160,7 +160,7 @@ func TestJsonMarshalUnmarshal(t *testing.T) {
|
||||
require.DeepEqual(t, []byte("receiptsRoot"), payloadPb.ReceiptsRoot)
|
||||
require.DeepEqual(t, []byte("logsBloom"), payloadPb.LogsBloom)
|
||||
require.DeepEqual(t, []byte("1"), payloadPb.Difficulty)
|
||||
require.DeepEqual(t, []byte("2"), payloadPb.TotalDifficulty)
|
||||
require.DeepEqual(t, "2", payloadPb.TotalDifficulty)
|
||||
require.DeepEqual(t, uint64(3), payloadPb.GasLimit)
|
||||
require.DeepEqual(t, uint64(4), payloadPb.GasUsed)
|
||||
require.DeepEqual(t, uint64(5), payloadPb.Timestamp)
|
||||
|
||||
21
proto/eth/ext/options.pb.go
generated
21
proto/eth/ext/options.pb.go
generated
@@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.25.0
|
||||
// protoc-gen-go v1.27.1
|
||||
// protoc v3.15.8
|
||||
// source: proto/eth/ext/options.proto
|
||||
|
||||
@@ -9,10 +9,9 @@ package ext
|
||||
import (
|
||||
reflect "reflect"
|
||||
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
descriptor "github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
descriptorpb "google.golang.org/protobuf/types/descriptorpb"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -22,13 +21,9 @@ const (
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
// This is a compile-time assertion that a sufficiently up-to-date version
|
||||
// of the legacy proto package is being used.
|
||||
const _ = proto.ProtoPackageIsVersion4
|
||||
|
||||
var file_proto_eth_ext_options_proto_extTypes = []protoimpl.ExtensionInfo{
|
||||
{
|
||||
ExtendedType: (*descriptor.FieldOptions)(nil),
|
||||
ExtendedType: (*descriptorpb.FieldOptions)(nil),
|
||||
ExtensionType: (*string)(nil),
|
||||
Field: 50000,
|
||||
Name: "ethereum.eth.ext.cast_type",
|
||||
@@ -36,7 +31,7 @@ var file_proto_eth_ext_options_proto_extTypes = []protoimpl.ExtensionInfo{
|
||||
Filename: "proto/eth/ext/options.proto",
|
||||
},
|
||||
{
|
||||
ExtendedType: (*descriptor.FieldOptions)(nil),
|
||||
ExtendedType: (*descriptorpb.FieldOptions)(nil),
|
||||
ExtensionType: (*string)(nil),
|
||||
Field: 50001,
|
||||
Name: "ethereum.eth.ext.ssz_size",
|
||||
@@ -44,7 +39,7 @@ var file_proto_eth_ext_options_proto_extTypes = []protoimpl.ExtensionInfo{
|
||||
Filename: "proto/eth/ext/options.proto",
|
||||
},
|
||||
{
|
||||
ExtendedType: (*descriptor.FieldOptions)(nil),
|
||||
ExtendedType: (*descriptorpb.FieldOptions)(nil),
|
||||
ExtensionType: (*string)(nil),
|
||||
Field: 50002,
|
||||
Name: "ethereum.eth.ext.ssz_max",
|
||||
@@ -52,7 +47,7 @@ var file_proto_eth_ext_options_proto_extTypes = []protoimpl.ExtensionInfo{
|
||||
Filename: "proto/eth/ext/options.proto",
|
||||
},
|
||||
{
|
||||
ExtendedType: (*descriptor.FieldOptions)(nil),
|
||||
ExtendedType: (*descriptorpb.FieldOptions)(nil),
|
||||
ExtensionType: (*string)(nil),
|
||||
Field: 50003,
|
||||
Name: "ethereum.eth.ext.spec_name",
|
||||
@@ -61,7 +56,7 @@ var file_proto_eth_ext_options_proto_extTypes = []protoimpl.ExtensionInfo{
|
||||
},
|
||||
}
|
||||
|
||||
// Extension fields to descriptor.FieldOptions.
|
||||
// Extension fields to descriptorpb.FieldOptions.
|
||||
var (
|
||||
// optional string cast_type = 50000;
|
||||
E_CastType = &file_proto_eth_ext_options_proto_extTypes[0]
|
||||
@@ -108,7 +103,7 @@ var file_proto_eth_ext_options_proto_rawDesc = []byte{
|
||||
}
|
||||
|
||||
var file_proto_eth_ext_options_proto_goTypes = []interface{}{
|
||||
(*descriptor.FieldOptions)(nil), // 0: google.protobuf.FieldOptions
|
||||
(*descriptorpb.FieldOptions)(nil), // 0: google.protobuf.FieldOptions
|
||||
}
|
||||
var file_proto_eth_ext_options_proto_depIdxs = []int32{
|
||||
0, // 0: ethereum.eth.ext.cast_type:extendee -> google.protobuf.FieldOptions
|
||||
|
||||
7
proto/eth/service/beacon_chain_service.pb.go
generated
7
proto/eth/service/beacon_chain_service.pb.go
generated
@@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.25.0
|
||||
// protoc-gen-go v1.27.1
|
||||
// protoc v3.15.8
|
||||
// source: proto/eth/service/beacon_chain_service.proto
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
context "context"
|
||||
reflect "reflect"
|
||||
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
_ "github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||
empty "github.com/golang/protobuf/ptypes/empty"
|
||||
v1 "github.com/prysmaticlabs/prysm/proto/eth/v1"
|
||||
@@ -30,10 +29,6 @@ const (
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
// This is a compile-time assertion that a sufficiently up-to-date version
|
||||
// of the legacy proto package is being used.
|
||||
const _ = proto.ProtoPackageIsVersion4
|
||||
|
||||
var File_proto_eth_service_beacon_chain_service_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_proto_eth_service_beacon_chain_service_proto_rawDesc = []byte{
|
||||
|
||||
7
proto/eth/service/beacon_debug_service.pb.go
generated
7
proto/eth/service/beacon_debug_service.pb.go
generated
@@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.25.0
|
||||
// protoc-gen-go v1.27.1
|
||||
// protoc v3.15.8
|
||||
// source: proto/eth/service/beacon_debug_service.proto
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
context "context"
|
||||
reflect "reflect"
|
||||
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
_ "github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||
empty "github.com/golang/protobuf/ptypes/empty"
|
||||
v1 "github.com/prysmaticlabs/prysm/proto/eth/v1"
|
||||
@@ -30,10 +29,6 @@ const (
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
// This is a compile-time assertion that a sufficiently up-to-date version
|
||||
// of the legacy proto package is being used.
|
||||
const _ = proto.ProtoPackageIsVersion4
|
||||
|
||||
var File_proto_eth_service_beacon_debug_service_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_proto_eth_service_beacon_debug_service_proto_rawDesc = []byte{
|
||||
|
||||
7
proto/eth/service/events_service.pb.go
generated
7
proto/eth/service/events_service.pb.go
generated
@@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.25.0
|
||||
// protoc-gen-go v1.27.1
|
||||
// protoc v3.15.8
|
||||
// source: proto/eth/service/events_service.proto
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
context "context"
|
||||
reflect "reflect"
|
||||
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
_ "github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||
gateway "github.com/grpc-ecosystem/grpc-gateway/v2/proto/gateway"
|
||||
v1 "github.com/prysmaticlabs/prysm/proto/eth/v1"
|
||||
@@ -29,10 +28,6 @@ const (
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
// This is a compile-time assertion that a sufficiently up-to-date version
|
||||
// of the legacy proto package is being used.
|
||||
const _ = proto.ProtoPackageIsVersion4
|
||||
|
||||
var File_proto_eth_service_events_service_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_proto_eth_service_events_service_proto_rawDesc = []byte{
|
||||
|
||||
7
proto/eth/service/node_service.pb.go
generated
7
proto/eth/service/node_service.pb.go
generated
@@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.25.0
|
||||
// protoc-gen-go v1.27.1
|
||||
// protoc v3.15.8
|
||||
// source: proto/eth/service/node_service.proto
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
context "context"
|
||||
reflect "reflect"
|
||||
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
_ "github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||
empty "github.com/golang/protobuf/ptypes/empty"
|
||||
v1 "github.com/prysmaticlabs/prysm/proto/eth/v1"
|
||||
@@ -29,10 +28,6 @@ const (
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
// This is a compile-time assertion that a sufficiently up-to-date version
|
||||
// of the legacy proto package is being used.
|
||||
const _ = proto.ProtoPackageIsVersion4
|
||||
|
||||
var File_proto_eth_service_node_service_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_proto_eth_service_node_service_proto_rawDesc = []byte{
|
||||
|
||||
7
proto/eth/service/validator_service.pb.go
generated
7
proto/eth/service/validator_service.pb.go
generated
@@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.25.0
|
||||
// protoc-gen-go v1.27.1
|
||||
// protoc v3.15.8
|
||||
// source: proto/eth/service/validator_service.proto
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
context "context"
|
||||
reflect "reflect"
|
||||
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
_ "github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||
empty "github.com/golang/protobuf/ptypes/empty"
|
||||
v1 "github.com/prysmaticlabs/prysm/proto/eth/v1"
|
||||
@@ -30,10 +29,6 @@ const (
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
// This is a compile-time assertion that a sufficiently up-to-date version
|
||||
// of the legacy proto package is being used.
|
||||
const _ = proto.ProtoPackageIsVersion4
|
||||
|
||||
var File_proto_eth_service_validator_service_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_proto_eth_service_validator_service_proto_rawDesc = []byte{
|
||||
|
||||
7
proto/eth/v1/attestation.pb.go
generated
7
proto/eth/v1/attestation.pb.go
generated
@@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.25.0
|
||||
// protoc-gen-go v1.27.1
|
||||
// protoc v3.15.8
|
||||
// source: proto/eth/v1/attestation.proto
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
_ "github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||
github_com_prysmaticlabs_eth2_types "github.com/prysmaticlabs/eth2-types"
|
||||
github_com_prysmaticlabs_go_bitfield "github.com/prysmaticlabs/go-bitfield"
|
||||
@@ -26,10 +25,6 @@ const (
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
// This is a compile-time assertion that a sufficiently up-to-date version
|
||||
// of the legacy proto package is being used.
|
||||
const _ = proto.ProtoPackageIsVersion4
|
||||
|
||||
type Attestation struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
|
||||
7
proto/eth/v1/beacon_block.pb.go
generated
7
proto/eth/v1/beacon_block.pb.go
generated
@@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.25.0
|
||||
// protoc-gen-go v1.27.1
|
||||
// protoc v3.15.8
|
||||
// source: proto/eth/v1/beacon_block.proto
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
_ "github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||
github_com_prysmaticlabs_eth2_types "github.com/prysmaticlabs/eth2-types"
|
||||
github_com_prysmaticlabs_go_bitfield "github.com/prysmaticlabs/go-bitfield"
|
||||
@@ -26,10 +25,6 @@ const (
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
// This is a compile-time assertion that a sufficiently up-to-date version
|
||||
// of the legacy proto package is being used.
|
||||
const _ = proto.ProtoPackageIsVersion4
|
||||
|
||||
type BeaconBlock struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
|
||||
7
proto/eth/v1/beacon_chain.pb.go
generated
7
proto/eth/v1/beacon_chain.pb.go
generated
@@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.25.0
|
||||
// protoc-gen-go v1.27.1
|
||||
// protoc v3.15.8
|
||||
// source: proto/eth/v1/beacon_chain.proto
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
_ "github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||
github_com_prysmaticlabs_eth2_types "github.com/prysmaticlabs/eth2-types"
|
||||
_ "github.com/prysmaticlabs/prysm/proto/eth/ext"
|
||||
@@ -26,10 +25,6 @@ const (
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
// This is a compile-time assertion that a sufficiently up-to-date version
|
||||
// of the legacy proto package is being used.
|
||||
const _ = proto.ProtoPackageIsVersion4
|
||||
|
||||
type GenesisResponse struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
|
||||
7
proto/eth/v1/beacon_state.pb.go
generated
7
proto/eth/v1/beacon_state.pb.go
generated
@@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.25.0
|
||||
// protoc-gen-go v1.27.1
|
||||
// protoc v3.15.8
|
||||
// source: proto/eth/v1/beacon_state.proto
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
_ "github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||
github_com_prysmaticlabs_eth2_types "github.com/prysmaticlabs/eth2-types"
|
||||
github_com_prysmaticlabs_go_bitfield "github.com/prysmaticlabs/go-bitfield"
|
||||
@@ -26,10 +25,6 @@ const (
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
// This is a compile-time assertion that a sufficiently up-to-date version
|
||||
// of the legacy proto package is being used.
|
||||
const _ = proto.ProtoPackageIsVersion4
|
||||
|
||||
type BeaconState struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
|
||||
7
proto/eth/v1/events.pb.go
generated
7
proto/eth/v1/events.pb.go
generated
@@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.25.0
|
||||
// protoc-gen-go v1.27.1
|
||||
// protoc v3.15.8
|
||||
// source: proto/eth/v1/events.proto
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
_ "github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||
github_com_prysmaticlabs_eth2_types "github.com/prysmaticlabs/eth2-types"
|
||||
_ "github.com/prysmaticlabs/prysm/proto/eth/ext"
|
||||
@@ -25,10 +24,6 @@ const (
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
// This is a compile-time assertion that a sufficiently up-to-date version
|
||||
// of the legacy proto package is being used.
|
||||
const _ = proto.ProtoPackageIsVersion4
|
||||
|
||||
type StreamEventsRequest struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
|
||||
7
proto/eth/v1/node.pb.go
generated
7
proto/eth/v1/node.pb.go
generated
@@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.25.0
|
||||
// protoc-gen-go v1.27.1
|
||||
// protoc v3.15.8
|
||||
// source: proto/eth/v1/node.proto
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
_ "github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||
github_com_prysmaticlabs_eth2_types "github.com/prysmaticlabs/eth2-types"
|
||||
github_com_prysmaticlabs_go_bitfield "github.com/prysmaticlabs/go-bitfield"
|
||||
@@ -26,10 +25,6 @@ const (
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
// This is a compile-time assertion that a sufficiently up-to-date version
|
||||
// of the legacy proto package is being used.
|
||||
const _ = proto.ProtoPackageIsVersion4
|
||||
|
||||
type PeerDirection int32
|
||||
|
||||
const (
|
||||
|
||||
7
proto/eth/v1/validator.pb.go
generated
7
proto/eth/v1/validator.pb.go
generated
@@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.25.0
|
||||
// protoc-gen-go v1.27.1
|
||||
// protoc v3.15.8
|
||||
// source: proto/eth/v1/validator.proto
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
_ "github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||
github_com_prysmaticlabs_eth2_types "github.com/prysmaticlabs/eth2-types"
|
||||
_ "github.com/prysmaticlabs/prysm/proto/eth/ext"
|
||||
@@ -25,10 +24,6 @@ const (
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
// This is a compile-time assertion that a sufficiently up-to-date version
|
||||
// of the legacy proto package is being used.
|
||||
const _ = proto.ProtoPackageIsVersion4
|
||||
|
||||
type ValidatorStatus int32
|
||||
|
||||
const (
|
||||
|
||||
7
proto/eth/v2/beacon_state.pb.go
generated
7
proto/eth/v2/beacon_state.pb.go
generated
@@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.25.0
|
||||
// protoc-gen-go v1.27.1
|
||||
// protoc v3.15.8
|
||||
// source: proto/eth/v2/beacon_state.proto
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
github_com_prysmaticlabs_eth2_types "github.com/prysmaticlabs/eth2-types"
|
||||
github_com_prysmaticlabs_go_bitfield "github.com/prysmaticlabs/go-bitfield"
|
||||
_ "github.com/prysmaticlabs/prysm/proto/eth/ext"
|
||||
@@ -26,10 +25,6 @@ const (
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
// This is a compile-time assertion that a sufficiently up-to-date version
|
||||
// of the legacy proto package is being used.
|
||||
const _ = proto.ProtoPackageIsVersion4
|
||||
|
||||
type BeaconStateV2 struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
|
||||
7
proto/eth/v2/sync_committee.pb.go
generated
7
proto/eth/v2/sync_committee.pb.go
generated
@@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.25.0
|
||||
// protoc-gen-go v1.27.1
|
||||
// protoc v3.15.8
|
||||
// source: proto/eth/v2/sync_committee.proto
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
github_com_prysmaticlabs_eth2_types "github.com/prysmaticlabs/eth2-types"
|
||||
_ "github.com/prysmaticlabs/prysm/proto/eth/ext"
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
@@ -24,10 +23,6 @@ const (
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
// This is a compile-time assertion that a sufficiently up-to-date version
|
||||
// of the legacy proto package is being used.
|
||||
const _ = proto.ProtoPackageIsVersion4
|
||||
|
||||
type SubmitSyncCommitteeSignaturesRequest struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user