mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-09 13:28:01 -05:00
Compare commits
16 Commits
ba2333069a
...
go-1.24.7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
51b2cef211 | ||
|
|
29fe707143 | ||
|
|
d68196822b | ||
|
|
924fe4de98 | ||
|
|
fe9dd255c7 | ||
|
|
83d75bcb78 | ||
|
|
ba5f7361ad | ||
|
|
8fa956036a | ||
|
|
58ce1c25f5 | ||
|
|
98532a2df3 | ||
|
|
08be6fde92 | ||
|
|
4585cdc932 | ||
|
|
aa47435c91 | ||
|
|
80eba4e6dd | ||
|
|
606294e17f | ||
|
|
977e923692 |
2
.github/actions/gomodtidy/Dockerfile
vendored
2
.github/actions/gomodtidy/Dockerfile
vendored
@@ -1,4 +1,4 @@
|
||||
FROM golang:1.24-alpine
|
||||
FROM golang:1.25.1-alpine
|
||||
|
||||
COPY entrypoint.sh /entrypoint.sh
|
||||
|
||||
|
||||
4
.github/workflows/fuzz.yml
vendored
4
.github/workflows/fuzz.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: '1.23.5'
|
||||
go-version: '1.25.1'
|
||||
- id: list
|
||||
uses: shogo82148/actions-go-fuzz/list@v0
|
||||
with:
|
||||
@@ -36,7 +36,7 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: '1.23.5'
|
||||
go-version: '1.25.1'
|
||||
- uses: shogo82148/actions-go-fuzz/run@v0
|
||||
with:
|
||||
packages: ${{ matrix.package }}
|
||||
|
||||
22
.github/workflows/go.yml
vendored
22
.github/workflows/go.yml
vendored
@@ -31,7 +31,7 @@ jobs:
|
||||
- name: Set up Go 1.24
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: '1.24.0'
|
||||
go-version: '1.25.1'
|
||||
- name: Run Gosec Security Scanner
|
||||
run: | # https://github.com/securego/gosec/issues/469
|
||||
export PATH=$PATH:$(go env GOPATH)/bin
|
||||
@@ -44,27 +44,27 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Go 1.24
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: '1.24.0'
|
||||
id: go
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Go 1.25.1
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.25.1'
|
||||
|
||||
- name: Golangci-lint
|
||||
uses: golangci/golangci-lint-action@v5
|
||||
uses: golangci/golangci-lint-action@v8
|
||||
with:
|
||||
version: v1.64.5
|
||||
args: --config=.golangci.yml --out-${NO_FUTURE}format colored-line-number
|
||||
version: v2.4
|
||||
|
||||
build:
|
||||
name: Build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Set up Go 1.x
|
||||
- name: Set up Go 1.25.1
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: '1.24.0'
|
||||
go-version: '1.25.1'
|
||||
id: go
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
|
||||
121
.golangci.yml
121
.golangci.yml
@@ -1,90 +1,41 @@
|
||||
version: "2"
|
||||
run:
|
||||
timeout: 10m
|
||||
go: '1.23.5'
|
||||
|
||||
issues:
|
||||
exclude-files:
|
||||
- validator/web/site_data.go
|
||||
- .*_test.go
|
||||
exclude-dirs:
|
||||
- proto
|
||||
- tools/analyzers
|
||||
|
||||
go: 1.23.5
|
||||
linters:
|
||||
enable-all: true
|
||||
disable:
|
||||
# Deprecated linters:
|
||||
enable:
|
||||
- errcheck
|
||||
- ineffassign
|
||||
- govet
|
||||
|
||||
# Disabled for now:
|
||||
- asasalint
|
||||
- bodyclose
|
||||
- containedctx
|
||||
- contextcheck
|
||||
- cyclop
|
||||
- depguard
|
||||
- dogsled
|
||||
- dupl
|
||||
- durationcheck
|
||||
- errname
|
||||
- err113
|
||||
- exhaustive
|
||||
- exhaustruct
|
||||
- forbidigo
|
||||
- forcetypeassert
|
||||
- funlen
|
||||
- gci
|
||||
- gochecknoglobals
|
||||
- gochecknoinits
|
||||
- goconst
|
||||
- gocritic
|
||||
- gocyclo
|
||||
- godot
|
||||
- godox
|
||||
- gofumpt
|
||||
- gomoddirectives
|
||||
- gosec
|
||||
- inamedparam
|
||||
- interfacebloat
|
||||
- intrange
|
||||
- ireturn
|
||||
- lll
|
||||
- maintidx
|
||||
- makezero
|
||||
- mnd
|
||||
- musttag
|
||||
- nakedret
|
||||
- nestif
|
||||
- nilnil
|
||||
- nlreturn
|
||||
- noctx
|
||||
- nolintlint
|
||||
- nonamedreturns
|
||||
- nosprintfhostport
|
||||
- perfsprint
|
||||
- prealloc
|
||||
- predeclared
|
||||
- promlinter
|
||||
- protogetter
|
||||
- recvcheck
|
||||
- revive
|
||||
- spancheck
|
||||
disable:
|
||||
- staticcheck
|
||||
- stylecheck
|
||||
- tagalign
|
||||
- tagliatelle
|
||||
- thelper
|
||||
- unparam
|
||||
- usetesting
|
||||
- varnamelen
|
||||
- wrapcheck
|
||||
- wsl
|
||||
- unused
|
||||
exclusions:
|
||||
generated: lax
|
||||
presets:
|
||||
- comments
|
||||
- common-false-positives
|
||||
- legacy
|
||||
- std-error-handling
|
||||
paths:
|
||||
- validator/web/site_data.go
|
||||
- .*_test.go
|
||||
- proto
|
||||
- tools/analyzers
|
||||
- third_party$
|
||||
- builtin$
|
||||
- examples$
|
||||
|
||||
linters-settings:
|
||||
gocognit:
|
||||
# TODO: We should target for < 50
|
||||
min-complexity: 65
|
||||
|
||||
output:
|
||||
print-issued-lines: true
|
||||
sort-results: true
|
||||
formatters:
|
||||
enable:
|
||||
- gofmt
|
||||
- goimports
|
||||
exclusions:
|
||||
generated: lax
|
||||
paths:
|
||||
- validator/web/site_data.go
|
||||
- .*_test.go
|
||||
- proto
|
||||
- tools/analyzers
|
||||
- third_party$
|
||||
- builtin$
|
||||
- examples$
|
||||
46
WORKSPACE
46
WORKSPACE
@@ -208,7 +208,7 @@ load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_depe
|
||||
go_rules_dependencies()
|
||||
|
||||
go_register_toolchains(
|
||||
go_version = "1.25.1",
|
||||
go_version = "1.24.7",
|
||||
nogo = "@//:nogo",
|
||||
)
|
||||
|
||||
@@ -253,16 +253,16 @@ filegroup(
|
||||
url = "https://github.com/ethereum/EIPs/archive/5480440fe51742ed23342b68cf106cefd427e39d.tar.gz",
|
||||
)
|
||||
|
||||
consensus_spec_version = "v1.6.0-alpha.6"
|
||||
consensus_spec_version = "v1.6.0-beta.0"
|
||||
|
||||
load("@prysm//tools:download_spectests.bzl", "consensus_spec_tests")
|
||||
|
||||
consensus_spec_tests(
|
||||
name = "consensus_spec_tests",
|
||||
flavors = {
|
||||
"general": "sha256-7wkWuahuCO37uVYnxq8Badvi+jY907pBj68ixL8XDOI=",
|
||||
"minimal": "sha256-Qy/f27N0LffS/ej7VhIubwDejD6LMK0VdenKkqtZVt4=",
|
||||
"mainnet": "sha256-3H7mu5yE+FGz2Wr/nc8Nd9aEu93YoEpsYtn0zBSoeDE=",
|
||||
"general": "sha256-rT3jQp2+ZaDiO66gIQggetzqr+kGeexaLqEhbx4HDMY=",
|
||||
"minimal": "sha256-wowwwyvd0KJLsE+oDOtPkrhZyJndJpJ0lbXYsLH6XBw=",
|
||||
"mainnet": "sha256-4ZLrLNeO7NihZ4TuWH5V5fUhvW9Y3mAPBQDCqrfShps=",
|
||||
},
|
||||
version = consensus_spec_version,
|
||||
)
|
||||
@@ -278,7 +278,7 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
integrity = "sha256-uvz3XfMTGfy3/BtQQoEp5XQOgrWgcH/5Zo/gR0iiP+k=",
|
||||
integrity = "sha256-sBe3Rx8zGq9IrvfgIhZQpYidGjy3mE1SiCb6/+pjLdY=",
|
||||
strip_prefix = "consensus-specs-" + consensus_spec_version[1:],
|
||||
url = "https://github.com/ethereum/consensus-specs/archive/refs/tags/%s.tar.gz" % consensus_spec_version,
|
||||
)
|
||||
@@ -300,22 +300,6 @@ filegroup(
|
||||
url = "https://github.com/ethereum/bls12-381-tests/releases/download/%s/bls_tests_yaml.tar.gz" % bls_test_version,
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "eth2_networks",
|
||||
build_file_content = """
|
||||
filegroup(
|
||||
name = "configs",
|
||||
srcs = glob([
|
||||
"shared/**/config.yaml",
|
||||
]),
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
sha256 = "77e7e3ed65e33b7bb19d30131f4c2bb39e4dfeb188ab9ae84651c3cc7600131d",
|
||||
strip_prefix = "eth2-networks-934c948e69205dcf2deb87e4ae6cc140c335f94d",
|
||||
url = "https://github.com/eth-clients/eth2-networks/archive/934c948e69205dcf2deb87e4ae6cc140c335f94d.tar.gz",
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "holesky_testnet",
|
||||
build_file_content = """
|
||||
@@ -327,9 +311,9 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
integrity = "sha256-YVFFrCmjoGZ3fXMWpsCpSsYbANy1grnqYwOLKIg2SsA=",
|
||||
strip_prefix = "holesky-32a72e21c6e53c262f27d50dd540cb654517d03a",
|
||||
url = "https://github.com/eth-clients/holesky/archive/32a72e21c6e53c262f27d50dd540cb654517d03a.tar.gz", # 2025-03-17
|
||||
integrity = "sha256-htyxg8Ln2o8eCiifFN7/hcHGZg8Ir9CPzCEx+FUnnCs=",
|
||||
strip_prefix = "holesky-8aec65f11f0c986d6b76b2eb902420635eb9b815",
|
||||
url = "https://github.com/eth-clients/holesky/archive/8aec65f11f0c986d6b76b2eb902420635eb9b815.tar.gz",
|
||||
)
|
||||
|
||||
http_archive(
|
||||
@@ -359,9 +343,9 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
integrity = "sha256-b5F7Wg9LLMqGRIpP2uqb/YsSFVn2ynzlV7g/Nb1EFLk=",
|
||||
strip_prefix = "sepolia-562d9938f08675e9ba490a1dfba21fb05843f39f",
|
||||
url = "https://github.com/eth-clients/sepolia/archive/562d9938f08675e9ba490a1dfba21fb05843f39f.tar.gz", # 2025-03-17
|
||||
integrity = "sha256-+UZgfvBcea0K0sbvAJZOz5ZNmxdWZYbohP38heUuc6w=",
|
||||
strip_prefix = "sepolia-f9158732adb1a2a6440613ad2232eb50e7384c4f",
|
||||
url = "https://github.com/eth-clients/sepolia/archive/f9158732adb1a2a6440613ad2232eb50e7384c4f.tar.gz",
|
||||
)
|
||||
|
||||
http_archive(
|
||||
@@ -375,9 +359,9 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
integrity = "sha256-dPiEWUd8QvbYGwGtIm0QtCekitVLOLsW5rpQIGzz8PU=",
|
||||
strip_prefix = "hoodi-828c2c940e1141092bd4bb979cef547ea926d272",
|
||||
url = "https://github.com/eth-clients/hoodi/archive/828c2c940e1141092bd4bb979cef547ea926d272.tar.gz",
|
||||
integrity = "sha256-G+4c9c/vci1OyPrQJnQCI+ZCv/E0cWN4hrHDY3i7ns0=",
|
||||
strip_prefix = "hoodi-b6ee51b2045a5e7fe3efac52534f75b080b049c6",
|
||||
url = "https://github.com/eth-clients/hoodi/archive/b6ee51b2045a5e7fe3efac52534f75b080b049c6.tar.gz",
|
||||
)
|
||||
|
||||
http_archive(
|
||||
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/state"
|
||||
"github.com/OffchainLabs/prysm/v6/config/features"
|
||||
"github.com/OffchainLabs/prysm/v6/config/params"
|
||||
consensusblocks "github.com/OffchainLabs/prysm/v6/consensus-types/blocks"
|
||||
blocktypes "github.com/OffchainLabs/prysm/v6/consensus-types/blocks"
|
||||
"github.com/OffchainLabs/prysm/v6/consensus-types/interfaces"
|
||||
payloadattribute "github.com/OffchainLabs/prysm/v6/consensus-types/payload-attribute"
|
||||
"github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
|
||||
@@ -218,24 +218,18 @@ func (s *Service) getPayloadHash(ctx context.Context, root []byte) ([32]byte, er
|
||||
|
||||
// notifyNewPayload signals execution engine on a new payload.
|
||||
// It returns true if the EL has returned VALID for the block
|
||||
func (s *Service) notifyNewPayload(ctx context.Context, preStateVersion int,
|
||||
preStateHeader interfaces.ExecutionData, blk interfaces.ReadOnlySignedBeaconBlock) (bool, error) {
|
||||
// stVersion should represent the version of the pre-state; header should also be from the pre-state.
|
||||
func (s *Service) notifyNewPayload(ctx context.Context, stVersion int, header interfaces.ExecutionData, blk blocktypes.ROBlock) (bool, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "blockChain.notifyNewPayload")
|
||||
defer span.End()
|
||||
|
||||
// Execution payload is only supported in Bellatrix and beyond. Pre
|
||||
// merge blocks are never optimistic
|
||||
if blk == nil {
|
||||
return false, errors.New("signed beacon block can't be nil")
|
||||
}
|
||||
if preStateVersion < version.Bellatrix {
|
||||
if stVersion < version.Bellatrix {
|
||||
return true, nil
|
||||
}
|
||||
if err := consensusblocks.BeaconBlockIsNil(blk); err != nil {
|
||||
return false, err
|
||||
}
|
||||
body := blk.Block().Body()
|
||||
enabled, err := blocks.IsExecutionEnabledUsingHeader(preStateHeader, body)
|
||||
enabled, err := blocks.IsExecutionEnabledUsingHeader(header, body)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(invalidBlock{error: err}, "could not determine if execution is enabled")
|
||||
}
|
||||
@@ -268,28 +262,32 @@ func (s *Service) notifyNewPayload(ctx context.Context, preStateVersion int,
|
||||
return false, errors.New("nil execution requests")
|
||||
}
|
||||
}
|
||||
lastValidHash, err = s.cfg.ExecutionEngineCaller.NewPayload(ctx, payload, versionedHashes, parentRoot, requests)
|
||||
|
||||
switch {
|
||||
case err == nil:
|
||||
lastValidHash, err = s.cfg.ExecutionEngineCaller.NewPayload(ctx, payload, versionedHashes, parentRoot, requests)
|
||||
if err == nil {
|
||||
newPayloadValidNodeCount.Inc()
|
||||
return true, nil
|
||||
case errors.Is(err, execution.ErrAcceptedSyncingPayloadStatus):
|
||||
}
|
||||
logFields := logrus.Fields{
|
||||
"slot": blk.Block().Slot(),
|
||||
"parentRoot": fmt.Sprintf("%#x", parentRoot),
|
||||
"root": fmt.Sprintf("%#x", blk.Root()),
|
||||
"payloadBlockHash": fmt.Sprintf("%#x", bytesutil.Trunc(payload.BlockHash())),
|
||||
}
|
||||
if errors.Is(err, execution.ErrAcceptedSyncingPayloadStatus) {
|
||||
newPayloadOptimisticNodeCount.Inc()
|
||||
log.WithFields(logrus.Fields{
|
||||
"slot": blk.Block().Slot(),
|
||||
"payloadBlockHash": fmt.Sprintf("%#x", bytesutil.Trunc(payload.BlockHash())),
|
||||
}).Info("Called new payload with optimistic block")
|
||||
log.WithFields(logFields).Info("Called new payload with optimistic block")
|
||||
return false, nil
|
||||
case errors.Is(err, execution.ErrInvalidPayloadStatus):
|
||||
lvh := bytesutil.ToBytes32(lastValidHash)
|
||||
}
|
||||
if errors.Is(err, execution.ErrInvalidPayloadStatus) {
|
||||
log.WithFields(logFields).WithError(err).Error("Invalid payload status")
|
||||
return false, invalidBlock{
|
||||
error: ErrInvalidPayload,
|
||||
lastValidHash: lvh,
|
||||
lastValidHash: bytesutil.ToBytes32(lastValidHash),
|
||||
}
|
||||
default:
|
||||
return false, errors.WithMessage(ErrUndefinedExecutionEngineError, err.Error())
|
||||
}
|
||||
log.WithFields(logFields).WithError(err).Error("Unexpected execution engine error")
|
||||
return false, errors.WithMessage(ErrUndefinedExecutionEngineError, err.Error())
|
||||
}
|
||||
|
||||
// reportInvalidBlock deals with the event that an invalid block was detected by the execution layer
|
||||
|
||||
@@ -481,33 +481,12 @@ func Test_NotifyNewPayload(t *testing.T) {
|
||||
phase0State, _ := util.DeterministicGenesisState(t, 1)
|
||||
altairState, _ := util.DeterministicGenesisStateAltair(t, 1)
|
||||
bellatrixState, _ := util.DeterministicGenesisStateBellatrix(t, 2)
|
||||
a := ðpb.SignedBeaconBlockAltair{
|
||||
Block: ðpb.BeaconBlockAltair{
|
||||
Body: ðpb.BeaconBlockBodyAltair{},
|
||||
},
|
||||
}
|
||||
a := util.NewBeaconBlockAltair()
|
||||
altairBlk, err := consensusblocks.NewSignedBeaconBlock(a)
|
||||
require.NoError(t, err)
|
||||
blk := ðpb.SignedBeaconBlockBellatrix{
|
||||
Block: ðpb.BeaconBlockBellatrix{
|
||||
Slot: 1,
|
||||
Body: ðpb.BeaconBlockBodyBellatrix{
|
||||
ExecutionPayload: &v1.ExecutionPayload{
|
||||
BlockNumber: 1,
|
||||
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),
|
||||
PrevRandao: make([]byte, fieldparams.RootLength),
|
||||
ExtraData: make([]byte, 0),
|
||||
BaseFeePerGas: make([]byte, fieldparams.RootLength),
|
||||
BlockHash: make([]byte, fieldparams.RootLength),
|
||||
Transactions: make([][]byte, 0),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
blk := util.NewBeaconBlockBellatrix()
|
||||
blk.Block.Slot = 1
|
||||
blk.Block.Body.ExecutionPayload.BlockNumber = 1
|
||||
bellatrixBlk, err := consensusblocks.NewSignedBeaconBlock(util.HydrateSignedBeaconBlockBellatrix(blk))
|
||||
require.NoError(t, err)
|
||||
st := params.BeaconConfig().SlotsPerEpoch.Mul(uint64(epochsSinceFinalitySaveHotStateDB))
|
||||
@@ -544,12 +523,6 @@ func Test_NotifyNewPayload(t *testing.T) {
|
||||
blk: altairBlk,
|
||||
isValidPayload: true,
|
||||
},
|
||||
{
|
||||
name: "nil beacon block",
|
||||
postState: bellatrixState,
|
||||
errString: "signed beacon block can't be nil",
|
||||
isValidPayload: false,
|
||||
},
|
||||
{
|
||||
name: "new payload with optimistic block",
|
||||
postState: bellatrixState,
|
||||
@@ -576,15 +549,8 @@ func Test_NotifyNewPayload(t *testing.T) {
|
||||
name: "altair pre state, happy case",
|
||||
postState: bellatrixState,
|
||||
blk: func() interfaces.ReadOnlySignedBeaconBlock {
|
||||
blk := ðpb.SignedBeaconBlockBellatrix{
|
||||
Block: ðpb.BeaconBlockBellatrix{
|
||||
Body: ðpb.BeaconBlockBodyBellatrix{
|
||||
ExecutionPayload: &v1.ExecutionPayload{
|
||||
ParentHash: bytesutil.PadTo([]byte{'a'}, fieldparams.RootLength),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
blk := util.NewBeaconBlockBellatrix()
|
||||
blk.Block.Body.ExecutionPayload.ParentHash = bytesutil.PadTo([]byte{'a'}, fieldparams.RootLength)
|
||||
b, err := consensusblocks.NewSignedBeaconBlock(blk)
|
||||
require.NoError(t, err)
|
||||
return b
|
||||
@@ -595,24 +561,7 @@ func Test_NotifyNewPayload(t *testing.T) {
|
||||
name: "not at merge transition",
|
||||
postState: bellatrixState,
|
||||
blk: func() interfaces.ReadOnlySignedBeaconBlock {
|
||||
blk := ðpb.SignedBeaconBlockBellatrix{
|
||||
Block: ðpb.BeaconBlockBellatrix{
|
||||
Body: ðpb.BeaconBlockBodyBellatrix{
|
||||
ExecutionPayload: &v1.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),
|
||||
PrevRandao: make([]byte, fieldparams.RootLength),
|
||||
ExtraData: make([]byte, 0),
|
||||
BaseFeePerGas: make([]byte, fieldparams.RootLength),
|
||||
BlockHash: make([]byte, fieldparams.RootLength),
|
||||
Transactions: make([][]byte, 0),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
blk := util.NewBeaconBlockBellatrix()
|
||||
b, err := consensusblocks.NewSignedBeaconBlock(blk)
|
||||
require.NoError(t, err)
|
||||
return b
|
||||
@@ -623,15 +572,8 @@ func Test_NotifyNewPayload(t *testing.T) {
|
||||
name: "happy case",
|
||||
postState: bellatrixState,
|
||||
blk: func() interfaces.ReadOnlySignedBeaconBlock {
|
||||
blk := ðpb.SignedBeaconBlockBellatrix{
|
||||
Block: ðpb.BeaconBlockBellatrix{
|
||||
Body: ðpb.BeaconBlockBodyBellatrix{
|
||||
ExecutionPayload: &v1.ExecutionPayload{
|
||||
ParentHash: bytesutil.PadTo([]byte{'a'}, fieldparams.RootLength),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
blk := util.NewBeaconBlockBellatrix()
|
||||
blk.Block.Body.ExecutionPayload.ParentHash = bytesutil.PadTo([]byte{'a'}, fieldparams.RootLength)
|
||||
b, err := consensusblocks.NewSignedBeaconBlock(blk)
|
||||
require.NoError(t, err)
|
||||
return b
|
||||
@@ -642,15 +584,8 @@ func Test_NotifyNewPayload(t *testing.T) {
|
||||
name: "undefined error from ee",
|
||||
postState: bellatrixState,
|
||||
blk: func() interfaces.ReadOnlySignedBeaconBlock {
|
||||
blk := ðpb.SignedBeaconBlockBellatrix{
|
||||
Block: ðpb.BeaconBlockBellatrix{
|
||||
Body: ðpb.BeaconBlockBodyBellatrix{
|
||||
ExecutionPayload: &v1.ExecutionPayload{
|
||||
ParentHash: bytesutil.PadTo([]byte{'a'}, fieldparams.RootLength),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
blk := util.NewBeaconBlockBellatrix()
|
||||
blk.Block.Body.ExecutionPayload.ParentHash = bytesutil.PadTo([]byte{'a'}, fieldparams.RootLength)
|
||||
b, err := consensusblocks.NewSignedBeaconBlock(blk)
|
||||
require.NoError(t, err)
|
||||
return b
|
||||
@@ -662,15 +597,8 @@ func Test_NotifyNewPayload(t *testing.T) {
|
||||
name: "invalid block hash error from ee",
|
||||
postState: bellatrixState,
|
||||
blk: func() interfaces.ReadOnlySignedBeaconBlock {
|
||||
blk := ðpb.SignedBeaconBlockBellatrix{
|
||||
Block: ðpb.BeaconBlockBellatrix{
|
||||
Body: ðpb.BeaconBlockBodyBellatrix{
|
||||
ExecutionPayload: &v1.ExecutionPayload{
|
||||
ParentHash: bytesutil.PadTo([]byte{'a'}, fieldparams.RootLength),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
blk := util.NewBeaconBlockBellatrix()
|
||||
blk.Block.Body.ExecutionPayload.ParentHash = bytesutil.PadTo([]byte{'a'}, fieldparams.RootLength)
|
||||
b, err := consensusblocks.NewSignedBeaconBlock(blk)
|
||||
require.NoError(t, err)
|
||||
return b
|
||||
@@ -701,7 +629,9 @@ func Test_NotifyNewPayload(t *testing.T) {
|
||||
require.NoError(t, service.cfg.ForkChoiceStore.InsertNode(ctx, state, blkRoot))
|
||||
postVersion, postHeader, err := getStateVersionAndPayload(tt.postState)
|
||||
require.NoError(t, err)
|
||||
isValidPayload, err := service.notifyNewPayload(ctx, postVersion, postHeader, tt.blk)
|
||||
rob, err := consensusblocks.NewROBlock(tt.blk)
|
||||
require.NoError(t, err)
|
||||
isValidPayload, err := service.notifyNewPayload(ctx, postVersion, postHeader, rob)
|
||||
if tt.errString != "" {
|
||||
require.ErrorContains(t, tt.errString, err)
|
||||
if tt.invalidBlock {
|
||||
@@ -725,17 +655,12 @@ func Test_NotifyNewPayload_SetOptimisticToValid(t *testing.T) {
|
||||
ctx := tr.ctx
|
||||
|
||||
bellatrixState, _ := util.DeterministicGenesisStateBellatrix(t, 2)
|
||||
blk := ðpb.SignedBeaconBlockBellatrix{
|
||||
Block: ðpb.BeaconBlockBellatrix{
|
||||
Body: ðpb.BeaconBlockBodyBellatrix{
|
||||
ExecutionPayload: &v1.ExecutionPayload{
|
||||
ParentHash: bytesutil.PadTo([]byte{'a'}, fieldparams.RootLength),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
blk := util.NewBeaconBlockBellatrix()
|
||||
blk.Block.Body.ExecutionPayload.ParentHash = bytesutil.PadTo([]byte{'a'}, fieldparams.RootLength)
|
||||
bellatrixBlk, err := consensusblocks.NewSignedBeaconBlock(blk)
|
||||
require.NoError(t, err)
|
||||
rob, err := consensusblocks.NewROBlock(bellatrixBlk)
|
||||
require.NoError(t, err)
|
||||
e := &mockExecution.EngineClient{BlockByHashMap: map[[32]byte]*v1.ExecutionBlock{}}
|
||||
e.BlockByHashMap[[32]byte{'a'}] = &v1.ExecutionBlock{
|
||||
Header: gethtypes.Header{
|
||||
@@ -752,7 +677,7 @@ func Test_NotifyNewPayload_SetOptimisticToValid(t *testing.T) {
|
||||
service.cfg.ExecutionEngineCaller = e
|
||||
postVersion, postHeader, err := getStateVersionAndPayload(bellatrixState)
|
||||
require.NoError(t, err)
|
||||
validated, err := service.notifyNewPayload(ctx, postVersion, postHeader, bellatrixBlk)
|
||||
validated, err := service.notifyNewPayload(ctx, postVersion, postHeader, rob)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, true, validated)
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package blockchain
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"slices"
|
||||
"time"
|
||||
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/core/blocks"
|
||||
@@ -746,14 +745,14 @@ func (s *Service) areDataColumnsAvailable(
|
||||
}
|
||||
|
||||
// Get a map of data column indices that are not currently available.
|
||||
missingMap, err := missingDataColumnIndices(s.dataColumnStorage, root, peerInfo.CustodyColumns)
|
||||
missing, err := missingDataColumnIndices(s.dataColumnStorage, root, peerInfo.CustodyColumns)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "missing data columns")
|
||||
}
|
||||
|
||||
// If there are no missing indices, all data column sidecars are available.
|
||||
// This is the happy path.
|
||||
if len(missingMap) == 0 {
|
||||
if len(missing) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -770,33 +769,17 @@ func (s *Service) areDataColumnsAvailable(
|
||||
// Avoid logging if DA check is called after next slot start.
|
||||
if nextSlot.After(time.Now()) {
|
||||
timer := time.AfterFunc(time.Until(nextSlot), func() {
|
||||
missingMapCount := uint64(len(missingMap))
|
||||
missingCount := uint64(len(missing))
|
||||
|
||||
if missingMapCount == 0 {
|
||||
if missingCount == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
var (
|
||||
expected interface{} = "all"
|
||||
missing interface{} = "all"
|
||||
)
|
||||
|
||||
numberOfColumns := params.BeaconConfig().NumberOfColumns
|
||||
colMapCount := uint64(len(peerInfo.CustodyColumns))
|
||||
|
||||
if colMapCount < numberOfColumns {
|
||||
expected = uint64MapToSortedSlice(peerInfo.CustodyColumns)
|
||||
}
|
||||
|
||||
if missingMapCount < numberOfColumns {
|
||||
missing = uint64MapToSortedSlice(missingMap)
|
||||
}
|
||||
|
||||
log.WithFields(logrus.Fields{
|
||||
"slot": block.Slot(),
|
||||
"root": fmt.Sprintf("%#x", root),
|
||||
"columnsExpected": expected,
|
||||
"columnsWaiting": missing,
|
||||
"columnsExpected": helpers.SortedPrettySliceFromMap(peerInfo.CustodyColumns),
|
||||
"columnsWaiting": helpers.SortedPrettySliceFromMap(missing),
|
||||
}).Warning("Data columns still missing at slot end")
|
||||
})
|
||||
defer timer.Stop()
|
||||
@@ -812,7 +795,7 @@ func (s *Service) areDataColumnsAvailable(
|
||||
|
||||
for _, index := range idents.Indices {
|
||||
// This is a data column we are expecting.
|
||||
if _, ok := missingMap[index]; ok {
|
||||
if _, ok := missing[index]; ok {
|
||||
storedDataColumnsCount++
|
||||
}
|
||||
|
||||
@@ -823,10 +806,10 @@ func (s *Service) areDataColumnsAvailable(
|
||||
}
|
||||
|
||||
// Remove the index from the missing map.
|
||||
delete(missingMap, index)
|
||||
delete(missing, index)
|
||||
|
||||
// Return if there is no more missing data columns.
|
||||
if len(missingMap) == 0 {
|
||||
if len(missing) == 0 {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@@ -834,10 +817,10 @@ func (s *Service) areDataColumnsAvailable(
|
||||
case <-ctx.Done():
|
||||
var missingIndices interface{} = "all"
|
||||
numberOfColumns := params.BeaconConfig().NumberOfColumns
|
||||
missingIndicesCount := uint64(len(missingMap))
|
||||
missingIndicesCount := uint64(len(missing))
|
||||
|
||||
if missingIndicesCount < numberOfColumns {
|
||||
missingIndices = uint64MapToSortedSlice(missingMap)
|
||||
missingIndices = helpers.SortedPrettySliceFromMap(missing)
|
||||
}
|
||||
|
||||
return errors.Wrapf(ctx.Err(), "data column sidecars slot: %d, BlockRoot: %#x, missing: %v", block.Slot(), root, missingIndices)
|
||||
@@ -921,16 +904,6 @@ func (s *Service) areBlobsAvailable(ctx context.Context, root [fieldparams.RootL
|
||||
}
|
||||
}
|
||||
|
||||
// uint64MapToSortedSlice produces a sorted uint64 slice from a map.
|
||||
func uint64MapToSortedSlice(input map[uint64]bool) []uint64 {
|
||||
output := make([]uint64, 0, len(input))
|
||||
for idx := range input {
|
||||
output = append(output, idx)
|
||||
}
|
||||
slices.Sort[[]uint64](output)
|
||||
return output
|
||||
}
|
||||
|
||||
// lateBlockTasks is called 4 seconds into the slot and performs tasks
|
||||
// related to late blocks. It emits a MissedSlot state feed event.
|
||||
// It calls FCU and sets the right attributes if we are proposing next slot
|
||||
|
||||
@@ -248,7 +248,7 @@ func (s *Service) handleDA(ctx context.Context, avs das.AvailabilityStore, block
|
||||
err = s.isDataAvailable(ctx, block)
|
||||
}
|
||||
elapsed := time.Since(start)
|
||||
if err != nil {
|
||||
if err == nil {
|
||||
dataAvailWaitedTime.Observe(float64(elapsed.Milliseconds()))
|
||||
}
|
||||
return elapsed, err
|
||||
|
||||
@@ -10,6 +10,7 @@ go_library(
|
||||
"legacy.go",
|
||||
"metrics.go",
|
||||
"randao.go",
|
||||
"ranges.go",
|
||||
"rewards_penalties.go",
|
||||
"shuffle.go",
|
||||
"sync_committee.go",
|
||||
@@ -56,6 +57,7 @@ go_test(
|
||||
"private_access_fuzz_noop_test.go", # keep
|
||||
"private_access_test.go",
|
||||
"randao_test.go",
|
||||
"ranges_test.go",
|
||||
"rewards_penalties_test.go",
|
||||
"shuffle_test.go",
|
||||
"sync_committee_test.go",
|
||||
|
||||
62
beacon-chain/core/helpers/ranges.go
Normal file
62
beacon-chain/core/helpers/ranges.go
Normal file
@@ -0,0 +1,62 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"slices"
|
||||
)
|
||||
|
||||
// SortedSliceFromMap takes a map with uint64 keys and returns a sorted slice of the keys.
|
||||
func SortedSliceFromMap(toSort map[uint64]bool) []uint64 {
|
||||
slice := make([]uint64, 0, len(toSort))
|
||||
for key := range toSort {
|
||||
slice = append(slice, key)
|
||||
}
|
||||
|
||||
slices.Sort(slice)
|
||||
return slice
|
||||
}
|
||||
|
||||
// PrettySlice returns a pretty string representation of a sorted slice of uint64.
|
||||
// `sortedSlice` must be sorted in ascending order.
|
||||
// Example: [1,2,3,5,6,7,8,10] -> "1-3,5-8,10"
|
||||
func PrettySlice(sortedSlice []uint64) string {
|
||||
if len(sortedSlice) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
var result string
|
||||
start := sortedSlice[0]
|
||||
end := sortedSlice[0]
|
||||
|
||||
for i := 1; i < len(sortedSlice); i++ {
|
||||
if sortedSlice[i] == end+1 {
|
||||
end = sortedSlice[i]
|
||||
continue
|
||||
}
|
||||
|
||||
if start == end {
|
||||
result += fmt.Sprintf("%d,", start)
|
||||
start = sortedSlice[i]
|
||||
end = sortedSlice[i]
|
||||
continue
|
||||
}
|
||||
|
||||
result += fmt.Sprintf("%d-%d,", start, end)
|
||||
start = sortedSlice[i]
|
||||
end = sortedSlice[i]
|
||||
}
|
||||
|
||||
if start == end {
|
||||
result += fmt.Sprintf("%d", start)
|
||||
return result
|
||||
}
|
||||
|
||||
result += fmt.Sprintf("%d-%d", start, end)
|
||||
return result
|
||||
}
|
||||
|
||||
// SortedPrettySliceFromMap combines SortedSliceFromMap and PrettySlice to return a pretty string representation of the keys in a map.
|
||||
func SortedPrettySliceFromMap(toSort map[uint64]bool) string {
|
||||
sorted := SortedSliceFromMap(toSort)
|
||||
return PrettySlice(sorted)
|
||||
}
|
||||
64
beacon-chain/core/helpers/ranges_test.go
Normal file
64
beacon-chain/core/helpers/ranges_test.go
Normal file
@@ -0,0 +1,64 @@
|
||||
package helpers_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/core/helpers"
|
||||
"github.com/OffchainLabs/prysm/v6/testing/require"
|
||||
)
|
||||
|
||||
func TestSortedSliceFromMap(t *testing.T) {
|
||||
input := map[uint64]bool{5: true, 3: true, 8: true, 1: true}
|
||||
expected := []uint64{1, 3, 5, 8}
|
||||
|
||||
actual := helpers.SortedSliceFromMap(input)
|
||||
require.Equal(t, len(expected), len(actual))
|
||||
|
||||
for i := range expected {
|
||||
require.Equal(t, expected[i], actual[i])
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrettySlice(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input []uint64
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "empty slice",
|
||||
input: []uint64{},
|
||||
expected: "",
|
||||
},
|
||||
{
|
||||
name: "only distinct elements",
|
||||
input: []uint64{1, 3, 5, 7, 9},
|
||||
expected: "1,3,5,7,9",
|
||||
},
|
||||
{
|
||||
name: "single range",
|
||||
input: []uint64{1, 2, 3, 4, 5},
|
||||
expected: "1-5",
|
||||
},
|
||||
{
|
||||
name: "multiple ranges and distinct elements",
|
||||
input: []uint64{1, 2, 3, 5, 6, 7, 8, 10, 12, 13, 14},
|
||||
expected: "1-3,5-8,10,12-14",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
actual := helpers.PrettySlice(tt.input)
|
||||
require.Equal(t, tt.expected, actual)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSortedPrettySliceFromMap(t *testing.T) {
|
||||
input := map[uint64]bool{5: true, 7: true, 8: true, 10: true}
|
||||
expected := "5,7-8,10"
|
||||
|
||||
actual := helpers.SortedPrettySliceFromMap(input)
|
||||
require.Equal(t, expected, actual)
|
||||
}
|
||||
@@ -122,18 +122,18 @@ type BlobStorage struct {
|
||||
func (bs *BlobStorage) WarmCache() {
|
||||
start := time.Now()
|
||||
if bs.layoutName == LayoutNameFlat {
|
||||
log.Info("Blob filesystem cache warm-up started. This may take a few minutes.")
|
||||
log.Info("Blob filesystem cache warm-up started. This may take a few minutes")
|
||||
} else {
|
||||
log.Info("Blob filesystem cache warm-up started.")
|
||||
log.Info("Blob filesystem cache warm-up started")
|
||||
}
|
||||
|
||||
if err := warmCache(bs.layout, bs.cache); err != nil {
|
||||
log.WithError(err).Error("Error encountered while warming up blob filesystem cache.")
|
||||
log.WithError(err).Error("Error encountered while warming up blob filesystem cache")
|
||||
}
|
||||
if err := bs.migrateLayouts(); err != nil {
|
||||
log.WithError(err).Error("Error encountered while migrating blob storage.")
|
||||
log.WithError(err).Error("Error encountered while migrating blob storage")
|
||||
}
|
||||
log.WithField("elapsed", time.Since(start)).Info("Blob filesystem cache warm-up complete.")
|
||||
log.WithField("elapsed", time.Since(start)).Info("Blob filesystem cache warm-up complete")
|
||||
}
|
||||
|
||||
// If any blob storage directories are found for layouts besides the configured layout, migrate them.
|
||||
|
||||
@@ -4,17 +4,26 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"time"
|
||||
|
||||
"github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
|
||||
"github.com/OffchainLabs/prysm/v6/time/slots"
|
||||
"github.com/pkg/errors"
|
||||
bolt "go.etcd.io/bbolt"
|
||||
)
|
||||
|
||||
var errTimeOut = errors.New("operation timed out")
|
||||
|
||||
// PruneAttestationsAtEpoch deletes all attestations from the slasher DB with target epoch
|
||||
// less than or equal to the specified epoch.
|
||||
func (s *Store) PruneAttestationsAtEpoch(
|
||||
_ context.Context, maxEpoch primitives.Epoch,
|
||||
ctx context.Context, maxEpoch primitives.Epoch,
|
||||
) (numPruned uint, err error) {
|
||||
// In some cases, pruning may take a very long time and consume significant memory in the
|
||||
// open Update transaction. Therefore, we impose a 1 minute timeout on this operation.
|
||||
ctx, cancel := context.WithTimeout(ctx, 1*time.Minute)
|
||||
defer cancel()
|
||||
|
||||
// We can prune everything less than the current epoch - history length.
|
||||
encodedEndPruneEpoch := make([]byte, 8)
|
||||
binary.BigEndian.PutUint64(encodedEndPruneEpoch, uint64(maxEpoch))
|
||||
@@ -48,13 +57,18 @@ func (s *Store) PruneAttestationsAtEpoch(
|
||||
return
|
||||
}
|
||||
|
||||
if err = s.db.Update(func(tx *bolt.Tx) error {
|
||||
err = s.db.Update(func(tx *bolt.Tx) error {
|
||||
signingRootsBkt := tx.Bucket(attestationDataRootsBucket)
|
||||
attRecordsBkt := tx.Bucket(attestationRecordsBucket)
|
||||
c := signingRootsBkt.Cursor()
|
||||
|
||||
// We begin a pruning iteration starting from the first item in the bucket.
|
||||
for k, v := c.First(); k != nil; k, v = c.Next() {
|
||||
if ctx.Err() != nil {
|
||||
// Exit the routine if the context has expired.
|
||||
return errTimeOut
|
||||
}
|
||||
|
||||
// We check the epoch from the current key in the database.
|
||||
// If we have hit an epoch that is greater than the end epoch of the pruning process,
|
||||
// we then completely exit the process as we are done.
|
||||
@@ -67,18 +81,27 @@ func (s *Store) PruneAttestationsAtEpoch(
|
||||
// so it is possible we have a few adjacent objects that have the same slot, such as
|
||||
// (target_epoch = 3 ++ _) => encode(attestation)
|
||||
if err := signingRootsBkt.Delete(k); err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "delete attestation signing root")
|
||||
}
|
||||
if err := attRecordsBkt.Delete(v); err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "delete attestation record")
|
||||
}
|
||||
slasherAttestationsPrunedTotal.Inc()
|
||||
numPruned++
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
})
|
||||
|
||||
if errors.Is(err, errTimeOut) {
|
||||
log.Warning("Aborting pruning routine")
|
||||
return
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Failed to prune attestations")
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -142,10 +142,9 @@ var ErrEmptyBlockHash = errors.New("Block hash is empty 0x0000...")
|
||||
func (s *Service) NewPayload(ctx context.Context, payload interfaces.ExecutionData, versionedHashes []common.Hash, parentBlockRoot *common.Hash, executionRequests *pb.ExecutionRequests) ([]byte, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "powchain.engine-api-client.NewPayload")
|
||||
defer span.End()
|
||||
start := time.Now()
|
||||
defer func() {
|
||||
defer func(start time.Time) {
|
||||
newPayloadLatency.Observe(float64(time.Since(start).Milliseconds()))
|
||||
}()
|
||||
}(time.Now())
|
||||
|
||||
d := time.Now().Add(time.Duration(params.BeaconConfig().ExecutionEngineTimeoutValue) * time.Second)
|
||||
ctx, cancel := context.WithDeadline(ctx, d)
|
||||
@@ -183,7 +182,10 @@ func (s *Service) NewPayload(ctx context.Context, payload interfaces.ExecutionDa
|
||||
return nil, errors.New("unknown execution data type")
|
||||
}
|
||||
if result.ValidationError != "" {
|
||||
log.WithError(errors.New(result.ValidationError)).Error("Got a validation error in newPayload")
|
||||
log.WithField("status", result.Status.String()).
|
||||
WithField("parentRoot", fmt.Sprintf("%#x", parentBlockRoot)).
|
||||
WithError(errors.New(result.ValidationError)).
|
||||
Error("Got a validation error in newPayload")
|
||||
}
|
||||
switch result.Status {
|
||||
case pb.PayloadStatus_INVALID_BLOCK_HASH:
|
||||
@@ -195,7 +197,7 @@ func (s *Service) NewPayload(ctx context.Context, payload interfaces.ExecutionDa
|
||||
case pb.PayloadStatus_VALID:
|
||||
return result.LatestValidHash, nil
|
||||
default:
|
||||
return nil, ErrUnknownPayloadStatus
|
||||
return nil, errors.Wrapf(ErrUnknownPayloadStatus, "unknown payload status: %s", result.Status.String())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -928,7 +928,7 @@ func TestClient_HTTP(t *testing.T) {
|
||||
wrappedPayload, err := blocks.WrappedExecutionPayload(execPayload)
|
||||
require.NoError(t, err)
|
||||
resp, err := client.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{}, nil)
|
||||
require.ErrorIs(t, ErrUnknownPayloadStatus, err)
|
||||
require.ErrorIs(t, err, ErrUnknownPayloadStatus)
|
||||
require.DeepEqual(t, []uint8(nil), resp)
|
||||
})
|
||||
t.Run(BlockByNumberMethod, func(t *testing.T) {
|
||||
|
||||
@@ -10,6 +10,8 @@ import (
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var errNoCustodyInfo = errors.New("no custody info available")
|
||||
|
||||
var _ CustodyManager = (*Service)(nil)
|
||||
|
||||
// EarliestAvailableSlot returns the earliest available slot.
|
||||
@@ -30,7 +32,7 @@ func (s *Service) CustodyGroupCount() (uint64, error) {
|
||||
defer s.custodyInfoLock.Unlock()
|
||||
|
||||
if s.custodyInfo == nil {
|
||||
return 0, errors.New("no custody info available")
|
||||
return 0, errNoCustodyInfo
|
||||
}
|
||||
|
||||
return s.custodyInfo.groupCount, nil
|
||||
|
||||
@@ -79,7 +79,7 @@ func (quicProtocol) ENRKey() string { return quickProtocolEnrKey }
|
||||
func newListener(listenerCreator func() (*discover.UDPv5, error)) (*listenerWrapper, error) {
|
||||
rawListener, err := listenerCreator()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not create new listener")
|
||||
return nil, errors.Wrap(err, "create new listener")
|
||||
}
|
||||
return &listenerWrapper{
|
||||
listener: rawListener,
|
||||
@@ -536,7 +536,7 @@ func (s *Service) createListener(
|
||||
int(s.cfg.QUICPort),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not create local node")
|
||||
return nil, errors.Wrap(err, "create local node")
|
||||
}
|
||||
|
||||
bootNodes := make([]*enode.Node, 0, len(s.cfg.Discv5BootStrapAddrs))
|
||||
@@ -604,13 +604,27 @@ func (s *Service) createLocalNode(
|
||||
localNode = initializeSyncCommSubnets(localNode)
|
||||
|
||||
if params.FuluEnabled() {
|
||||
custodyGroupCount, err := s.CustodyGroupCount()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not retrieve custody group count")
|
||||
}
|
||||
// TODO: Replace this quick fix with a proper synchronization scheme (chan?)
|
||||
const delay = 1 * time.Second
|
||||
|
||||
custodyGroupCountEntry := peerdas.Cgc(custodyGroupCount)
|
||||
localNode.Set(custodyGroupCountEntry)
|
||||
var custodyGroupCount uint64
|
||||
|
||||
err := errNoCustodyInfo
|
||||
for errors.Is(err, errNoCustodyInfo) {
|
||||
custodyGroupCount, err = s.CustodyGroupCount()
|
||||
if errors.Is(err, errNoCustodyInfo) {
|
||||
log.WithField("delay", delay).Debug("No custody info available yet, retrying later")
|
||||
time.Sleep(delay)
|
||||
continue
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "retrieve custody group count")
|
||||
}
|
||||
|
||||
custodyGroupCountEntry := peerdas.Cgc(custodyGroupCount)
|
||||
localNode.Set(custodyGroupCountEntry)
|
||||
}
|
||||
}
|
||||
|
||||
if s.cfg != nil && s.cfg.HostAddress != "" {
|
||||
@@ -652,7 +666,7 @@ func (s *Service) startDiscoveryV5(
|
||||
}
|
||||
wrappedListener, err := newListener(createListener)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not create listener")
|
||||
return nil, errors.Wrap(err, "create listener")
|
||||
}
|
||||
record := wrappedListener.Self()
|
||||
|
||||
|
||||
@@ -1465,8 +1465,7 @@ func (s *Server) GetBlockHeader(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
blk, err := s.Blocker.Block(ctx, []byte(blockID))
|
||||
ok := shared.WriteBlockFetchError(w, blk, err)
|
||||
if !ok {
|
||||
if !shared.WriteBlockFetchError(w, blk, err) {
|
||||
return
|
||||
}
|
||||
blockHeader, err := blk.Header()
|
||||
|
||||
@@ -58,12 +58,7 @@ func (s *Server) Blobs(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
blk, err := s.Blocker.Block(ctx, []byte(blockId))
|
||||
if err != nil {
|
||||
httputil.HandleError(w, "Could not fetch block: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if blk == nil {
|
||||
httputil.HandleError(w, "Block not found", http.StatusNotFound)
|
||||
if !shared.WriteBlockFetchError(w, blk, err) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -174,12 +169,7 @@ func (s *Server) GetBlobs(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
blk, err := s.Blocker.Block(ctx, []byte(blockId))
|
||||
if err != nil {
|
||||
httputil.HandleError(w, "Could not fetch block: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if blk == nil {
|
||||
httputil.HandleError(w, "Block not found", http.StatusNotFound)
|
||||
if !shared.WriteBlockFetchError(w, blk, err) {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -269,12 +269,7 @@ func (s *Server) DataColumnSidecars(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
blk, err := s.Blocker.Block(ctx, []byte(blockId))
|
||||
if err != nil {
|
||||
httputil.HandleError(w, "Could not fetch block: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if blk == nil {
|
||||
httputil.HandleError(w, "Block not found", http.StatusNotFound)
|
||||
if !shared.WriteBlockFetchError(w, blk, err) {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,11 @@ func WriteStateFetchError(w http.ResponseWriter, err error) {
|
||||
// WriteBlockFetchError writes an appropriate error based on the supplied argument.
|
||||
// The argument error should be a result of fetching block.
|
||||
func WriteBlockFetchError(w http.ResponseWriter, blk interfaces.ReadOnlySignedBeaconBlock, err error) bool {
|
||||
var blockNotFoundErr *lookup.BlockNotFoundError
|
||||
if errors.As(err, &blockNotFoundErr) {
|
||||
httputil.HandleError(w, "Block not found: "+blockNotFoundErr.Error(), http.StatusNotFound)
|
||||
return false
|
||||
}
|
||||
var invalidBlockIdErr *lookup.BlockIdParseError
|
||||
if errors.As(err, &invalidBlockIdErr) {
|
||||
httputil.HandleError(w, "Invalid block ID: "+invalidBlockIdErr.Error(), http.StatusBadRequest)
|
||||
|
||||
@@ -49,3 +49,59 @@ func TestWriteStateFetchError(t *testing.T) {
|
||||
assert.NoError(t, json.Unmarshal(writer.Body.Bytes(), e), "failed to unmarshal response")
|
||||
}
|
||||
}
|
||||
|
||||
// TestWriteBlockFetchError tests the WriteBlockFetchError function
|
||||
// to ensure that the correct error message and code are written to the response
|
||||
// and that the function returns the correct boolean value.
|
||||
func TestWriteBlockFetchError(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
err error
|
||||
expectedMessage string
|
||||
expectedCode int
|
||||
expectedReturn bool
|
||||
}{
|
||||
{
|
||||
name: "BlockNotFoundError should return 404",
|
||||
err: lookup.NewBlockNotFoundError("block not found at slot 123"),
|
||||
expectedMessage: "Block not found",
|
||||
expectedCode: http.StatusNotFound,
|
||||
expectedReturn: false,
|
||||
},
|
||||
{
|
||||
name: "BlockIdParseError should return 400",
|
||||
err: &lookup.BlockIdParseError{},
|
||||
expectedMessage: "Invalid block ID",
|
||||
expectedCode: http.StatusBadRequest,
|
||||
expectedReturn: false,
|
||||
},
|
||||
{
|
||||
name: "Generic error should return 500",
|
||||
err: errors.New("database connection failed"),
|
||||
expectedMessage: "Could not get block from block ID",
|
||||
expectedCode: http.StatusInternalServerError,
|
||||
expectedReturn: false,
|
||||
},
|
||||
{
|
||||
name: "Nil block should return 404",
|
||||
err: nil,
|
||||
expectedMessage: "Could not find requested block",
|
||||
expectedCode: http.StatusNotFound,
|
||||
expectedReturn: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
writer := httptest.NewRecorder()
|
||||
result := WriteBlockFetchError(writer, nil, c.err)
|
||||
|
||||
assert.Equal(t, c.expectedReturn, result, "incorrect return value")
|
||||
assert.Equal(t, c.expectedCode, writer.Code, "incorrect status code")
|
||||
assert.StringContains(t, c.expectedMessage, writer.Body.String(), "incorrect error message")
|
||||
|
||||
e := &httputil.DefaultJsonError{}
|
||||
assert.NoError(t, json.Unmarshal(writer.Body.Bytes(), e), "failed to unmarshal response")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/blockchain"
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/core/helpers"
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/core/peerdas"
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/db/filesystem"
|
||||
prysmP2P "github.com/OffchainLabs/prysm/v6/beacon-chain/p2p"
|
||||
@@ -187,7 +188,7 @@ func requestSidecarsFromStorage(
|
||||
requestedIndicesMap map[uint64]bool,
|
||||
roots map[[fieldparams.RootLength]byte]bool,
|
||||
) (map[[fieldparams.RootLength]byte][]blocks.VerifiedRODataColumn, error) {
|
||||
requestedIndices := sortedSliceFromMap(requestedIndicesMap)
|
||||
requestedIndices := helpers.SortedSliceFromMap(requestedIndicesMap)
|
||||
|
||||
result := make(map[[fieldparams.RootLength]byte][]blocks.VerifiedRODataColumn, len(roots))
|
||||
|
||||
@@ -599,7 +600,7 @@ func assembleAvailableSidecarsForRoot(
|
||||
root [fieldparams.RootLength]byte,
|
||||
indices map[uint64]bool,
|
||||
) ([]blocks.VerifiedRODataColumn, error) {
|
||||
stored, err := storage.Get(root, sortedSliceFromMap(indices))
|
||||
stored, err := storage.Get(root, helpers.SortedSliceFromMap(indices))
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "storage get for root %#x", root)
|
||||
}
|
||||
@@ -802,25 +803,27 @@ func sendDataColumnSidecarsRequest(
|
||||
roDataColumns = append(roDataColumns, localRoDataColumns...)
|
||||
}
|
||||
|
||||
prettyByRangeRequests := make([]map[string]any, 0, len(byRangeRequests))
|
||||
for _, request := range byRangeRequests {
|
||||
prettyRequest := map[string]any{
|
||||
"startSlot": request.StartSlot,
|
||||
"count": request.Count,
|
||||
"columns": request.Columns,
|
||||
if logrus.GetLevel() >= logrus.DebugLevel {
|
||||
prettyByRangeRequests := make([]map[string]any, 0, len(byRangeRequests))
|
||||
for _, request := range byRangeRequests {
|
||||
prettyRequest := map[string]any{
|
||||
"startSlot": request.StartSlot,
|
||||
"count": request.Count,
|
||||
"columns": helpers.PrettySlice(request.Columns),
|
||||
}
|
||||
|
||||
prettyByRangeRequests = append(prettyByRangeRequests, prettyRequest)
|
||||
}
|
||||
|
||||
prettyByRangeRequests = append(prettyByRangeRequests, prettyRequest)
|
||||
log.WithFields(logrus.Fields{
|
||||
"respondedSidecars": len(roDataColumns),
|
||||
"requestCount": len(byRangeRequests),
|
||||
"type": "byRange",
|
||||
"duration": time.Since(start),
|
||||
"requests": prettyByRangeRequests,
|
||||
}).Debug("Received data column sidecars")
|
||||
}
|
||||
|
||||
log.WithFields(logrus.Fields{
|
||||
"respondedSidecars": len(roDataColumns),
|
||||
"requestCount": len(byRangeRequests),
|
||||
"type": "byRange",
|
||||
"duration": time.Since(start),
|
||||
"requests": prettyByRangeRequests,
|
||||
}).Debug("Received data column sidecars")
|
||||
|
||||
return roDataColumns, nil
|
||||
}
|
||||
|
||||
@@ -895,7 +898,7 @@ func buildByRangeRequests(
|
||||
}
|
||||
}
|
||||
|
||||
columns := sortedSliceFromMap(reference)
|
||||
columns := helpers.SortedSliceFromMap(reference)
|
||||
startSlot, endSlot := slots[0], slots[len(slots)-1]
|
||||
totalCount := uint64(endSlot - startSlot + 1)
|
||||
|
||||
@@ -920,7 +923,7 @@ func buildByRootRequest(indicesByRoot map[[fieldparams.RootLength]byte]map[uint6
|
||||
for root, indices := range indicesByRoot {
|
||||
identifier := ð.DataColumnsByRootIdentifier{
|
||||
BlockRoot: root[:],
|
||||
Columns: sortedSliceFromMap(indices),
|
||||
Columns: helpers.SortedSliceFromMap(indices),
|
||||
}
|
||||
identifiers = append(identifiers, identifier)
|
||||
}
|
||||
@@ -1173,17 +1176,6 @@ func compareIndices(left, right map[uint64]bool) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// sortedSliceFromMap converts a map[uint64]bool to a sorted slice of keys.
|
||||
func sortedSliceFromMap(m map[uint64]bool) []uint64 {
|
||||
result := make([]uint64, 0, len(m))
|
||||
for k := range m {
|
||||
result = append(result, k)
|
||||
}
|
||||
|
||||
slices.Sort(result)
|
||||
return result
|
||||
}
|
||||
|
||||
// computeTotalCount calculates the total count of indices across all roots.
|
||||
func computeTotalCount(input map[[fieldparams.RootLength]byte]map[uint64]bool) int {
|
||||
totalCount := 0
|
||||
|
||||
@@ -1007,13 +1007,6 @@ func TestCompareIndices(t *testing.T) {
|
||||
require.Equal(t, true, compareIndices(left, right))
|
||||
}
|
||||
|
||||
func TestSlortedSliceFromMap(t *testing.T) {
|
||||
input := map[uint64]bool{54: true, 23: true, 35: true}
|
||||
expected := []uint64{23, 35, 54}
|
||||
actual := sortedSliceFromMap(input)
|
||||
require.DeepEqual(t, expected, actual)
|
||||
}
|
||||
|
||||
func TestComputeTotalCount(t *testing.T) {
|
||||
input := map[[fieldparams.RootLength]byte]map[uint64]bool{
|
||||
[fieldparams.RootLength]byte{1}: {1: true, 3: true},
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/core/helpers"
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/core/peerdas"
|
||||
fieldparams "github.com/OffchainLabs/prysm/v6/config/fieldparams"
|
||||
"github.com/OffchainLabs/prysm/v6/config/params"
|
||||
@@ -95,7 +96,7 @@ func (s *Service) processDataColumnSidecarsFromReconstruction(ctx context.Contex
|
||||
"slot": slot,
|
||||
"proposerIndex": proposerIndex,
|
||||
"count": len(unseenIndices),
|
||||
"indices": sortedSliceFromMap(unseenIndices),
|
||||
"indices": helpers.SortedPrettySliceFromMap(unseenIndices),
|
||||
"duration": duration,
|
||||
}).Debug("Reconstructed data column sidecars")
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ go_library(
|
||||
"//beacon-chain/blockchain:go_default_library",
|
||||
"//beacon-chain/core/feed/block:go_default_library",
|
||||
"//beacon-chain/core/feed/state:go_default_library",
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/core/peerdas:go_default_library",
|
||||
"//beacon-chain/core/transition:go_default_library",
|
||||
"//beacon-chain/das:go_default_library",
|
||||
|
||||
@@ -3,12 +3,12 @@ package initialsync
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"slices"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/core/helpers"
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/core/peerdas"
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/db"
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/db/filesystem"
|
||||
@@ -430,9 +430,9 @@ func (f *blocksFetcher) fetchSidecars(ctx context.Context, pid peer.ID, peers []
|
||||
}
|
||||
|
||||
if len(missingIndicesByRoot) > 0 {
|
||||
prettyMissingIndicesByRoot := make(map[string][]uint64, len(missingIndicesByRoot))
|
||||
prettyMissingIndicesByRoot := make(map[string]string, len(missingIndicesByRoot))
|
||||
for root, indices := range missingIndicesByRoot {
|
||||
prettyMissingIndicesByRoot[fmt.Sprintf("%#x", root)] = sortedSliceFromMap(indices)
|
||||
prettyMissingIndicesByRoot[fmt.Sprintf("%#x", root)] = helpers.SortedPrettySliceFromMap(indices)
|
||||
}
|
||||
return "", errors.Errorf("some sidecars are still missing after fetch: %v", prettyMissingIndicesByRoot)
|
||||
}
|
||||
@@ -727,17 +727,6 @@ func (f *blocksFetcher) fetchBlobsFromPeer(ctx context.Context, bwb []blocks.Blo
|
||||
return "", errNoPeersAvailable
|
||||
}
|
||||
|
||||
// sortedSliceFromMap returns a sorted slice of keys from a map.
|
||||
func sortedSliceFromMap(m map[uint64]bool) []uint64 {
|
||||
result := make([]uint64, 0, len(m))
|
||||
for k := range m {
|
||||
result = append(result, k)
|
||||
}
|
||||
|
||||
slices.Sort(result)
|
||||
return result
|
||||
}
|
||||
|
||||
// requestBlocks is a wrapper for handling BeaconBlocksByRangeRequest requests/streams.
|
||||
func (f *blocksFetcher) requestBlocks(
|
||||
ctx context.Context,
|
||||
|
||||
@@ -1349,14 +1349,6 @@ func TestBlockFetcher_HasSufficientBandwidth(t *testing.T) {
|
||||
assert.Equal(t, 2, len(receivedPeers))
|
||||
}
|
||||
|
||||
func TestSortedSliceFromMap(t *testing.T) {
|
||||
m := map[uint64]bool{1: true, 3: true, 2: true, 4: true}
|
||||
expected := []uint64{1, 2, 3, 4}
|
||||
|
||||
actual := sortedSliceFromMap(m)
|
||||
require.DeepSSZEqual(t, expected, actual)
|
||||
}
|
||||
|
||||
func TestFetchSidecars(t *testing.T) {
|
||||
ctx := t.Context()
|
||||
t.Run("No blocks", func(t *testing.T) {
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/blockchain"
|
||||
blockfeed "github.com/OffchainLabs/prysm/v6/beacon-chain/core/feed/block"
|
||||
statefeed "github.com/OffchainLabs/prysm/v6/beacon-chain/core/feed/state"
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/core/helpers"
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/core/peerdas"
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/das"
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/db"
|
||||
@@ -479,7 +480,7 @@ func (s *Service) fetchOriginDataColumnSidecars(roBlock blocks.ROBlock, delay ti
|
||||
// Some sidecars are still missing.
|
||||
log := log.WithFields(logrus.Fields{
|
||||
"attempt": attempt,
|
||||
"missingIndices": sortedSliceFromMap(missingIndicesByRoot[root]),
|
||||
"missingIndices": helpers.SortedPrettySliceFromMap(missingIndicesByRoot[root]),
|
||||
"delay": delay,
|
||||
})
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/core/helpers"
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/core/peerdas"
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/db/filesystem"
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/execution"
|
||||
@@ -121,9 +122,9 @@ func (s *Service) requestAndSaveMissingDataColumnSidecars(blks []blocks.ROBlock)
|
||||
}
|
||||
|
||||
if len(missingIndicesByRoot) > 0 {
|
||||
prettyMissingIndicesByRoot := make(map[string][]uint64, len(missingIndicesByRoot))
|
||||
prettyMissingIndicesByRoot := make(map[string]string, len(missingIndicesByRoot))
|
||||
for root, indices := range missingIndicesByRoot {
|
||||
prettyMissingIndicesByRoot[fmt.Sprintf("%#x", root)] = sortedSliceFromMap(indices)
|
||||
prettyMissingIndicesByRoot[fmt.Sprintf("%#x", root)] = helpers.SortedPrettySliceFromMap(indices)
|
||||
}
|
||||
return errors.Errorf("some sidecars are still missing after fetch: %v", prettyMissingIndicesByRoot)
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"slices"
|
||||
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/blockchain"
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/core/helpers"
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/p2p"
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/p2p/encoder"
|
||||
p2ptypes "github.com/OffchainLabs/prysm/v6/beacon-chain/p2p/types"
|
||||
@@ -598,7 +599,7 @@ func isSidecarIndexRequested(request *ethpb.DataColumnSidecarsByRangeRequest) Da
|
||||
return func(sidecar blocks.RODataColumn) error {
|
||||
columnIndex := sidecar.Index
|
||||
if !requestedIndices[columnIndex] {
|
||||
requested := sortedSliceFromMap(requestedIndices)
|
||||
requested := helpers.SortedPrettySliceFromMap(requestedIndices)
|
||||
return errors.Errorf("data column sidecar index %d returned by the peer but not found in requested indices %v", columnIndex, requested)
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/blockchain"
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/core/helpers"
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/core/peerdas"
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/core/transition/interop"
|
||||
"github.com/OffchainLabs/prysm/v6/config/features"
|
||||
@@ -227,7 +228,7 @@ func (s *Service) processDataColumnSidecarsFromExecution(ctx context.Context, so
|
||||
"iteration": iteration,
|
||||
"type": source.Type(),
|
||||
"count": len(unseenIndices),
|
||||
"indices": sortedSliceFromMap(unseenIndices),
|
||||
"indices": helpers.SortedPrettySliceFromMap(unseenIndices),
|
||||
}).Debug("Constructed data column sidecars from the execution client")
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
### Fixed
|
||||
|
||||
- Replace fmt.Printf with proper test error handling in web3signer keymanager tests, using require.NoError(t, err) instead of t.Fatalf for better error handling and debugging.
|
||||
3
changelog/james-prysm_fix-da-metric.md
Normal file
3
changelog/james-prysm_fix-da-metric.md
Normal file
@@ -0,0 +1,3 @@
|
||||
### Fixed
|
||||
|
||||
- da metric was not writing correctly because if statement on err was accidently flipped
|
||||
3
changelog/james_prysm-fix-blocker-notfound.md
Normal file
3
changelog/james_prysm-fix-blocker-notfound.md
Normal file
@@ -0,0 +1,3 @@
|
||||
### Fixed
|
||||
|
||||
- fixed regression introduced in PR #15715 , blocker now returns an error for not found, and error handling correctly handles error and returns 404 instead of 500
|
||||
2
changelog/kasey_log-invalid-ee-root.md
Normal file
2
changelog/kasey_log-invalid-ee-root.md
Normal file
@@ -0,0 +1,2 @@
|
||||
### Ignored
|
||||
- Adding context to logs around execution engine notification failures.
|
||||
2
changelog/manu-fix-cgc-not-initialized.md
Normal file
2
changelog/manu-fix-cgc-not-initialized.md
Normal file
@@ -0,0 +1,2 @@
|
||||
### Fixed
|
||||
- In P2P service start, wait for the custody info to be correctly initialized.
|
||||
3
changelog/manu-go-1.25.1.md
Normal file
3
changelog/manu-go-1.25.1.md
Normal file
@@ -0,0 +1,3 @@
|
||||
### Changed
|
||||
|
||||
- Updated go.mod to v1.25.1
|
||||
2
changelog/manu-logs-datacolumns.md
Normal file
2
changelog/manu-logs-datacolumns.md
Normal file
@@ -0,0 +1,2 @@
|
||||
## Changed
|
||||
- Improve logging of data column sidecars
|
||||
2
changelog/manu-wait.md
Normal file
2
changelog/manu-wait.md
Normal file
@@ -0,0 +1,2 @@
|
||||
### Fixed
|
||||
- `createLocalNode`: Wait before retrying to retrieve the custody group count if not present.
|
||||
3
changelog/potuz_update_quic_go.md
Normal file
3
changelog/potuz_update_quic_go.md
Normal file
@@ -0,0 +1,3 @@
|
||||
### Changed
|
||||
|
||||
- Updated quick-go to latest version.
|
||||
3
changelog/potuz_update_spectest.md
Normal file
3
changelog/potuz_update_spectest.md
Normal file
@@ -0,0 +1,3 @@
|
||||
### Added
|
||||
|
||||
- Update spectests to 1.6.0-beta.0
|
||||
3
changelog/pvl-go-1.24.7.md
Normal file
3
changelog/pvl-go-1.24.7.md
Normal file
@@ -0,0 +1,3 @@
|
||||
### Changed
|
||||
|
||||
- Rollback to go 1.24.7. Go 1.25 is causing issues windows builds.
|
||||
2
changelog/pvl-slasherkv-timeout.md
Normal file
2
changelog/pvl-slasherkv-timeout.md
Normal file
@@ -0,0 +1,2 @@
|
||||
### Added
|
||||
- Added a 1 minute timeout on PruneAttestationOnEpoch operations to prevent very large bolt transactions
|
||||
6
changelog/pvl-update-eth-clients.md
Normal file
6
changelog/pvl-update-eth-clients.md
Normal file
@@ -0,0 +1,6 @@
|
||||
### Ignored
|
||||
|
||||
- Updated pinned commit for eth-clients/holesky
|
||||
- Updated pinned commit for eth-clients/hoodi
|
||||
- Updated pinned commit for eth-clients/sepolia
|
||||
- Removed deprecated dependency for eth-clients/eth2-networks
|
||||
3
changelog/syjn99_ssz-ql-nested-list.md
Normal file
3
changelog/syjn99_ssz-ql-nested-list.md
Normal file
@@ -0,0 +1,3 @@
|
||||
### Fixed
|
||||
|
||||
- SSZ-QL: Support nested `List` type (e.g., `ExecutionPayload.Transactions`)
|
||||
3
changelog/ttsao_set-fulu-fork-epochs.md
Normal file
3
changelog/ttsao_set-fulu-fork-epochs.md
Normal file
@@ -0,0 +1,3 @@
|
||||
### Changed
|
||||
|
||||
- Set Fulu fork epochs for Holesky, Hoodi, and Sepolia testnets
|
||||
3
changelog/ttsao_simplify-golangci-config.md
Normal file
3
changelog/ttsao_simplify-golangci-config.md
Normal file
@@ -0,0 +1,3 @@
|
||||
### Ignored
|
||||
|
||||
- Update golangci-lint config to enable only basic linters that currently pass
|
||||
@@ -67,7 +67,6 @@ go_test(
|
||||
"testdata/e2e_config.yaml",
|
||||
"@consensus_spec//:spec_data",
|
||||
"@consensus_spec_tests//:test_data",
|
||||
"@eth2_networks//:configs",
|
||||
"@holesky_testnet//:configs",
|
||||
"@hoodi_testnet//:configs",
|
||||
"@mainnet//:configs",
|
||||
|
||||
@@ -30,6 +30,7 @@ var placeholderFields = []string{
|
||||
"ATTESTATION_DUE_BPS",
|
||||
"ATTESTATION_DUE_BPS_GLOAS",
|
||||
"BLOB_SIDECAR_SUBNET_COUNT_FULU",
|
||||
"CELLS_PER_EXT_BLOB",
|
||||
"CONTRIBUTION_DUE_BPS",
|
||||
"CONTRIBUTION_DUE_BPS_GLOAS",
|
||||
"EIP6110_FORK_EPOCH",
|
||||
@@ -45,10 +46,13 @@ var placeholderFields = []string{
|
||||
"EIP7928_FORK_EPOCH",
|
||||
"EIP7928_FORK_VERSION",
|
||||
"EPOCHS_PER_SHUFFLING_PHASE",
|
||||
"FIELD_ELEMENTS_PER_CELL", // Configured as a constant in config/fieldparams/mainnet.go
|
||||
"FIELD_ELEMENTS_PER_EXT_BLOB", // Configured in proto/ssz_proto_library.bzl
|
||||
"GLOAS_FORK_EPOCH",
|
||||
"GLOAS_FORK_VERSION",
|
||||
"INCLUSION_LIST_SUBMISSION_DEADLINE",
|
||||
"INCLUSION_LIST_SUBMISSION_DUE_BPS",
|
||||
"KZG_COMMITMENTS_INCLUSION_PROOF_DEPTH", // Configured in proto/ssz_proto_library.bzl
|
||||
"MAX_BYTES_PER_INCLUSION_LIST",
|
||||
"MAX_REQUEST_BLOB_SIDECARS_FULU",
|
||||
"MAX_REQUEST_INCLUSION_LIST",
|
||||
@@ -388,6 +392,7 @@ func presetsFilePath(t *testing.T, config string) []string {
|
||||
path.Join(fPath, "presets", config, "capella.yaml"),
|
||||
path.Join(fPath, "presets", config, "deneb.yaml"),
|
||||
path.Join(fPath, "presets", config, "electra.yaml"),
|
||||
path.Join(fPath, "presets", config, "fulu.yaml"),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package params
|
||||
|
||||
import "math"
|
||||
|
||||
// UseHoleskyNetworkConfig uses the Holesky beacon chain specific network config.
|
||||
func UseHoleskyNetworkConfig() {
|
||||
cfg := BeaconNetworkConfig().Copy()
|
||||
@@ -41,12 +39,21 @@ func HoleskyConfig() *BeaconChainConfig {
|
||||
cfg.DenebForkVersion = []byte{0x05, 0x1, 0x70, 0x0}
|
||||
cfg.ElectraForkEpoch = 115968 // Mon, Feb 24 at 21:55:12 UTC
|
||||
cfg.ElectraForkVersion = []byte{0x06, 0x1, 0x70, 0x0}
|
||||
cfg.FuluForkEpoch = math.MaxUint64
|
||||
cfg.FuluForkVersion = []byte{0x07, 0x1, 0x70, 0x0} // TODO: Define holesky fork version for fulu. This is a placeholder value.
|
||||
cfg.FuluForkEpoch = 165120 // 2025-10-01 08:48:00 UTC
|
||||
cfg.FuluForkVersion = []byte{0x07, 0x1, 0x70, 0x0}
|
||||
cfg.TerminalTotalDifficulty = "0"
|
||||
cfg.DepositContractAddress = "0x4242424242424242424242424242424242424242"
|
||||
cfg.EjectionBalance = 28000000000
|
||||
cfg.BlobSchedule = []BlobScheduleEntry{}
|
||||
cfg.BlobSchedule = []BlobScheduleEntry{
|
||||
{
|
||||
MaxBlobsPerBlock: 15,
|
||||
Epoch: 166400, // 2025-10-07 01:20:00 UTC
|
||||
},
|
||||
{
|
||||
MaxBlobsPerBlock: 21,
|
||||
Epoch: 167936, // 2025-10-13 21:10:24 UTC
|
||||
},
|
||||
}
|
||||
cfg.InitializeForkSchedule()
|
||||
return cfg
|
||||
}
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
package params
|
||||
|
||||
import (
|
||||
"math"
|
||||
)
|
||||
|
||||
// UseHoodiNetworkConfig uses the Hoodi beacon chain specific network config.
|
||||
func UseHoodiNetworkConfig() {
|
||||
cfg := BeaconNetworkConfig().Copy()
|
||||
@@ -49,11 +45,20 @@ func HoodiConfig() *BeaconChainConfig {
|
||||
cfg.DenebForkVersion = []byte{0x50, 0x00, 0x09, 0x10}
|
||||
cfg.ElectraForkEpoch = 2048
|
||||
cfg.ElectraForkVersion = []byte{0x60, 0x00, 0x09, 0x10}
|
||||
cfg.FuluForkEpoch = math.MaxUint64
|
||||
cfg.FuluForkEpoch = 50688 // 2025-10-28 18:53:12 UTC
|
||||
cfg.FuluForkVersion = []byte{0x70, 0x00, 0x09, 0x10}
|
||||
cfg.TerminalTotalDifficulty = "0"
|
||||
cfg.DepositContractAddress = "0x00000000219ab540356cBB839Cbe05303d7705Fa"
|
||||
cfg.BlobSchedule = []BlobScheduleEntry{}
|
||||
cfg.BlobSchedule = []BlobScheduleEntry{
|
||||
{
|
||||
MaxBlobsPerBlock: 15,
|
||||
Epoch: 52480, // 2025-11-05 18:02:00 UTC
|
||||
},
|
||||
{
|
||||
MaxBlobsPerBlock: 21,
|
||||
Epoch: 54016, // 2025-11-12 13:52:24 UTC
|
||||
},
|
||||
}
|
||||
cfg.DefaultBuilderGasLimit = uint64(60000000)
|
||||
cfg.InitializeForkSchedule()
|
||||
return cfg
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package params
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
eth1Params "github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
|
||||
@@ -46,12 +44,21 @@ func SepoliaConfig() *BeaconChainConfig {
|
||||
cfg.DenebForkVersion = []byte{0x90, 0x00, 0x00, 0x73}
|
||||
cfg.ElectraForkEpoch = 222464 // Wed, Mar 5 at 07:29:36 UTC
|
||||
cfg.ElectraForkVersion = []byte{0x90, 0x00, 0x00, 0x74}
|
||||
cfg.FuluForkEpoch = math.MaxUint64
|
||||
cfg.FuluForkVersion = []byte{0x90, 0x00, 0x00, 0x75} // TODO: Define sepolia fork version for fulu. This is a placeholder value.
|
||||
cfg.FuluForkEpoch = 272640 // 2025-10-14 07:36:00 UTC
|
||||
cfg.FuluForkVersion = []byte{0x90, 0x00, 0x00, 0x75}
|
||||
cfg.TerminalTotalDifficulty = "17000000000000000"
|
||||
cfg.DepositContractAddress = "0x7f02C3E3c98b133055B8B348B2Ac625669Ed295D"
|
||||
cfg.DefaultBuilderGasLimit = uint64(60000000)
|
||||
cfg.BlobSchedule = []BlobScheduleEntry{}
|
||||
cfg.BlobSchedule = []BlobScheduleEntry{
|
||||
{
|
||||
MaxBlobsPerBlock: 15,
|
||||
Epoch: 274176, // 2025-10-21 03:26:24 UTC
|
||||
},
|
||||
{
|
||||
MaxBlobsPerBlock: 21,
|
||||
Epoch: 275712, // 2025-10-27 23:16:48 UTC
|
||||
},
|
||||
}
|
||||
cfg.InitializeForkSchedule()
|
||||
return cfg
|
||||
}
|
||||
|
||||
4
deps.bzl
4
deps.bzl
@@ -2915,8 +2915,8 @@ def prysm_deps():
|
||||
"gazelle:exclude tools.go",
|
||||
],
|
||||
importpath = "github.com/quic-go/quic-go",
|
||||
sum = "h1:w5iJHXwHxs1QxyBv1EHKuC50GX5to8mJAxvtnttJp94=",
|
||||
version = "v0.49.0",
|
||||
sum = "h1:x09Agz4ATTMEP3qb5P0MRxNZfd6O9wAyK3qwwqQZVQc=",
|
||||
version = "v0.49.1-0.20250925085836-275c172fec2b",
|
||||
)
|
||||
go_repository(
|
||||
name = "com_github_quic_go_webtransport_go",
|
||||
|
||||
@@ -60,9 +60,21 @@ func PopulateVariableLengthInfo(sszInfo *sszInfo, value any) error {
|
||||
if val.Kind() != reflect.Slice {
|
||||
return fmt.Errorf("expected slice for List type, got %v", val.Kind())
|
||||
}
|
||||
length := val.Len()
|
||||
|
||||
length := uint64(val.Len())
|
||||
if err := listInfo.SetLength(length); err != nil {
|
||||
if listInfo.element.isVariable {
|
||||
listInfo.elementSizes = make([]uint64, 0, length)
|
||||
|
||||
// Populate nested variable-sized type element lengths recursively.
|
||||
for i := range length {
|
||||
if err := PopulateVariableLengthInfo(listInfo.element, val.Index(i).Interface()); err != nil {
|
||||
return fmt.Errorf("could not populate nested list element at index %d: %w", i, err)
|
||||
}
|
||||
listInfo.elementSizes = append(listInfo.elementSizes, listInfo.element.Size())
|
||||
}
|
||||
}
|
||||
|
||||
if err := listInfo.SetLength(uint64(length)); err != nil {
|
||||
return fmt.Errorf("could not set list length: %w", err)
|
||||
}
|
||||
|
||||
@@ -111,15 +123,20 @@ func PopulateVariableLengthInfo(sszInfo *sszInfo, value any) error {
|
||||
continue
|
||||
}
|
||||
|
||||
// Set the actual offset for variable-sized fields.
|
||||
fieldInfo.offset = currentOffset
|
||||
|
||||
// Recursively populate variable-sized fields.
|
||||
fieldValue := derefValue.FieldByName(fieldInfo.goFieldName)
|
||||
if err := PopulateVariableLengthInfo(childSszInfo, fieldValue.Interface()); err != nil {
|
||||
return fmt.Errorf("could not populate from value for field %s: %w", fieldName, err)
|
||||
}
|
||||
|
||||
// Each variable-sized element needs an offset entry.
|
||||
if childSszInfo.sszType == List {
|
||||
currentOffset += childSszInfo.listInfo.OffsetBytes()
|
||||
}
|
||||
|
||||
// Set the actual offset for variable-sized fields.
|
||||
fieldInfo.offset = currentOffset
|
||||
|
||||
currentOffset += childSszInfo.Size()
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@ type listInfo struct {
|
||||
element *sszInfo
|
||||
// length is the actual number of elements at runtime (0 if not set).
|
||||
length uint64
|
||||
// elementSizes caches each element's byte size for variable-sized type elements
|
||||
elementSizes []uint64
|
||||
}
|
||||
|
||||
func (l *listInfo) Limit() uint64 {
|
||||
@@ -51,3 +53,35 @@ func (l *listInfo) SetLength(length uint64) error {
|
||||
l.length = length
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *listInfo) Size() uint64 {
|
||||
if l == nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
// For fixed-sized type elements, size is multiplying length by element size.
|
||||
if !l.element.isVariable {
|
||||
return l.length * l.element.Size()
|
||||
}
|
||||
|
||||
// For variable-sized type elements, sum up the sizes of each element.
|
||||
totalSize := uint64(0)
|
||||
for _, sz := range l.elementSizes {
|
||||
totalSize += sz
|
||||
}
|
||||
return totalSize
|
||||
}
|
||||
|
||||
// OffsetBytes returns the total number of offset bytes used for the list elements.
|
||||
// Each variable-sized element uses 4 bytes to store its offset.
|
||||
func (l *listInfo) OffsetBytes() uint64 {
|
||||
if l == nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
if !l.element.isVariable {
|
||||
return 0
|
||||
}
|
||||
|
||||
return offsetBytes * l.length
|
||||
}
|
||||
|
||||
@@ -133,56 +133,73 @@ func TestCalculateOffsetAndLength(t *testing.T) {
|
||||
{
|
||||
name: "field_list_uint64",
|
||||
path: ".field_list_uint64",
|
||||
expectedOffset: 108, // First part of variable-sized type.
|
||||
expectedOffset: 112, // First part of variable-sized type.
|
||||
expectedLength: 40, // 5 elements * uint64 (8 bytes each)
|
||||
},
|
||||
{
|
||||
name: "field_list_container",
|
||||
path: ".field_list_container",
|
||||
expectedOffset: 148, // Second part of variable-sized type.
|
||||
expectedOffset: 152, // Second part of variable-sized type.
|
||||
expectedLength: 120, // 3 elements * FixedNestedContainer (40 bytes each)
|
||||
},
|
||||
{
|
||||
name: "field_list_bytes32",
|
||||
path: ".field_list_bytes32",
|
||||
expectedOffset: 268,
|
||||
expectedOffset: 272,
|
||||
expectedLength: 96, // 3 elements * 32 bytes each
|
||||
},
|
||||
// Nested paths
|
||||
{
|
||||
name: "nested",
|
||||
path: ".nested",
|
||||
expectedOffset: 364,
|
||||
expectedOffset: 368,
|
||||
// Calculated with:
|
||||
// - Value1: 8 bytes
|
||||
// - field_list_uint64 offset: 4 bytes
|
||||
// - field_list_uint64 length: 40 bytes
|
||||
expectedLength: 52,
|
||||
// - nested_list_field offset: 4 bytes
|
||||
// - nested_list_field length: 99 bytes
|
||||
// - 3 offset pointers for each element in nested_list_field: 12 bytes
|
||||
// Total: 8 + 4 + 40 + 4 + 99 + 12 = 167 bytes
|
||||
expectedLength: 167,
|
||||
},
|
||||
{
|
||||
name: "nested.value1",
|
||||
path: ".nested.value1",
|
||||
expectedOffset: 364,
|
||||
expectedOffset: 368,
|
||||
expectedLength: 8,
|
||||
},
|
||||
{
|
||||
name: "nested.field_list_uint64",
|
||||
path: ".nested.field_list_uint64",
|
||||
expectedOffset: 376,
|
||||
expectedOffset: 384,
|
||||
expectedLength: 40,
|
||||
},
|
||||
{
|
||||
name: "nested.nested_list_field",
|
||||
path: ".nested.nested_list_field",
|
||||
expectedOffset: 436,
|
||||
expectedLength: 99,
|
||||
},
|
||||
// Bitlist field
|
||||
{
|
||||
name: "bitlist_field",
|
||||
path: ".bitlist_field",
|
||||
expectedOffset: 416,
|
||||
expectedOffset: 535,
|
||||
expectedLength: 33, // 32 bytes + 1 byte for length delimiter
|
||||
},
|
||||
// 2D bytes field
|
||||
{
|
||||
name: "nested_list_field",
|
||||
path: ".nested_list_field",
|
||||
expectedOffset: 580,
|
||||
expectedLength: 99,
|
||||
},
|
||||
// Fixed trailing field
|
||||
{
|
||||
name: "trailing_field",
|
||||
path: ".trailing_field",
|
||||
expectedOffset: 52, // After leading_field + 5 offset pointers
|
||||
expectedOffset: 56, // After leading_field + 6 offset pointers
|
||||
expectedLength: 56,
|
||||
},
|
||||
}
|
||||
@@ -377,6 +394,15 @@ func createVariableTestContainer() *sszquerypb.VariableTestContainer {
|
||||
bitlistField.SetBitAt(100, true)
|
||||
bitlistField.SetBitAt(255, true)
|
||||
|
||||
// Total size: 3 lists with lengths 32, 33, and 34 = 99 bytes
|
||||
nestedListField := make([][]byte, 3)
|
||||
for i := range nestedListField {
|
||||
nestedListField[i] = make([]byte, (32 + i)) // Different lengths for each sub-list
|
||||
for j := range nestedListField[i] {
|
||||
nestedListField[i][j] = byte(j + i*16)
|
||||
}
|
||||
}
|
||||
|
||||
return &sszquerypb.VariableTestContainer{
|
||||
// Fixed leading field
|
||||
LeadingField: leadingField,
|
||||
@@ -394,11 +420,15 @@ func createVariableTestContainer() *sszquerypb.VariableTestContainer {
|
||||
Nested: &sszquerypb.VariableNestedContainer{
|
||||
Value1: 42,
|
||||
FieldListUint64: []uint64{1, 2, 3, 4, 5},
|
||||
NestedListField: nestedListField,
|
||||
},
|
||||
|
||||
// Bitlist field
|
||||
BitlistField: bitlistField,
|
||||
|
||||
// 2D bytes field
|
||||
NestedListField: nestedListField,
|
||||
|
||||
// Fixed trailing field
|
||||
TrailingField: trailingField,
|
||||
}
|
||||
@@ -445,11 +475,20 @@ func getVariableTestContainerSpec() testutil.TestSpec {
|
||||
Path: ".nested.field_list_uint64",
|
||||
Expected: testContainer.Nested.FieldListUint64,
|
||||
},
|
||||
{
|
||||
Path: ".nested.nested_list_field",
|
||||
Expected: testContainer.Nested.NestedListField,
|
||||
},
|
||||
// Bitlist field
|
||||
{
|
||||
Path: ".bitlist_field",
|
||||
Expected: testContainer.BitlistField,
|
||||
},
|
||||
// 2D bytes field
|
||||
{
|
||||
Path: ".nested_list_field",
|
||||
Expected: testContainer.NestedListField,
|
||||
},
|
||||
// Fixed trailing field
|
||||
{
|
||||
Path: ".trailing_field",
|
||||
|
||||
@@ -54,10 +54,7 @@ func (info *sszInfo) Size() uint64 {
|
||||
|
||||
switch info.sszType {
|
||||
case List:
|
||||
length := info.listInfo.length
|
||||
elementSize := info.listInfo.element.Size()
|
||||
|
||||
return length * elementSize
|
||||
return info.listInfo.Size()
|
||||
|
||||
case Bitlist:
|
||||
return info.bitlistInfo.Size()
|
||||
@@ -69,6 +66,11 @@ func (info *sszInfo) Size() uint64 {
|
||||
continue
|
||||
}
|
||||
|
||||
// Include offset bytes inside nested lists.
|
||||
if fieldInfo.sszInfo.sszType == List {
|
||||
size += fieldInfo.sszInfo.listInfo.OffsetBytes()
|
||||
}
|
||||
|
||||
size += fieldInfo.sszInfo.Size()
|
||||
}
|
||||
return size
|
||||
|
||||
@@ -31,10 +31,10 @@ func RunStructTest(t *testing.T, spec TestSpec) {
|
||||
_, offset, length, err := query.CalculateOffsetAndLength(info, path)
|
||||
require.NoError(t, err)
|
||||
|
||||
expectedRawBytes := marshalledData[offset : offset+length]
|
||||
rawBytes, err := marshalAny(pathTest.Expected)
|
||||
actualRawBytes := marshalledData[offset : offset+length]
|
||||
expectedRawBytes, err := marshalAny(pathTest.Expected)
|
||||
require.NoError(t, err, "Marshalling expected value should not return an error")
|
||||
require.DeepEqual(t, expectedRawBytes, rawBytes, "Extracted value should match expected")
|
||||
require.DeepEqual(t, actualRawBytes, expectedRawBytes, "Extracted value should match expected")
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
4
go.mod
4
go.mod
@@ -1,6 +1,6 @@
|
||||
module github.com/OffchainLabs/prysm/v6
|
||||
|
||||
go 1.24.5
|
||||
go 1.25.1
|
||||
|
||||
require (
|
||||
github.com/MariusVanDerWijden/FuzzyVM v0.0.0-20240516070431-7828990cad7d
|
||||
@@ -238,7 +238,7 @@ require (
|
||||
github.com/prometheus/common v0.62.0 // indirect
|
||||
github.com/prometheus/procfs v0.15.1 // indirect
|
||||
github.com/quic-go/qpack v0.5.1 // indirect
|
||||
github.com/quic-go/quic-go v0.49.0 // indirect
|
||||
github.com/quic-go/quic-go v0.49.1-0.20250925085836-275c172fec2b // indirect
|
||||
github.com/quic-go/webtransport-go v0.8.1-0.20241018022711-4ac2c9250e66 // indirect
|
||||
github.com/raulk/go-watchdog v1.3.0 // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
|
||||
4
go.sum
4
go.sum
@@ -916,8 +916,8 @@ github.com/prysmaticlabs/protoc-gen-go-cast v0.0.0-20230228205207-28762a7b9294 h
|
||||
github.com/prysmaticlabs/protoc-gen-go-cast v0.0.0-20230228205207-28762a7b9294/go.mod h1:ZVEbRdnMkGhp/pu35zq4SXxtvUwWK0J1MATtekZpH2Y=
|
||||
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
|
||||
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
|
||||
github.com/quic-go/quic-go v0.49.0 h1:w5iJHXwHxs1QxyBv1EHKuC50GX5to8mJAxvtnttJp94=
|
||||
github.com/quic-go/quic-go v0.49.0/go.mod h1:s2wDnmCdooUQBmQfpUSTCYBl1/D4FcqbULMMkASvR6s=
|
||||
github.com/quic-go/quic-go v0.49.1-0.20250925085836-275c172fec2b h1:x09Agz4ATTMEP3qb5P0MRxNZfd6O9wAyK3qwwqQZVQc=
|
||||
github.com/quic-go/quic-go v0.49.1-0.20250925085836-275c172fec2b/go.mod h1:s2wDnmCdooUQBmQfpUSTCYBl1/D4FcqbULMMkASvR6s=
|
||||
github.com/quic-go/webtransport-go v0.8.1-0.20241018022711-4ac2c9250e66 h1:4WFk6u3sOT6pLa1kQ50ZVdm8BQFgJNA117cepZxtLIg=
|
||||
github.com/quic-go/webtransport-go v0.8.1-0.20241018022711-4ac2c9250e66/go.mod h1:Vp72IJajgeOL6ddqrAhmp7IM9zbTcgkQxD/YdxrVwMw=
|
||||
github.com/r3labs/sse/v2 v2.10.0 h1:hFEkLLFY4LDifoHdiCN/LlGBAdVJYsANaLqNYa1l/v0=
|
||||
|
||||
58
proto/ssz_query/ssz_query.pb.go
generated
58
proto/ssz_query/ssz_query.pb.go
generated
@@ -195,6 +195,7 @@ type VariableNestedContainer struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Value1 uint64 `protobuf:"varint,1,opt,name=value1,proto3" json:"value1,omitempty"`
|
||||
FieldListUint64 []uint64 `protobuf:"varint,2,rep,packed,name=field_list_uint64,json=fieldListUint64,proto3" json:"field_list_uint64,omitempty" ssz-max:"100"`
|
||||
NestedListField [][]byte `protobuf:"bytes,3,rep,name=nested_list_field,json=nestedListField,proto3" json:"nested_list_field,omitempty" ssz-max:"100,50" ssz-size:"?,?"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
@@ -243,6 +244,13 @@ func (x *VariableNestedContainer) GetFieldListUint64() []uint64 {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *VariableNestedContainer) GetNestedListField() [][]byte {
|
||||
if x != nil {
|
||||
return x.NestedListField
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type VariableTestContainer struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
LeadingField []byte `protobuf:"bytes,1,opt,name=leading_field,json=leadingField,proto3" json:"leading_field,omitempty" ssz-size:"32"`
|
||||
@@ -251,7 +259,8 @@ type VariableTestContainer struct {
|
||||
FieldListBytes32 [][]byte `protobuf:"bytes,4,rep,name=field_list_bytes32,json=fieldListBytes32,proto3" json:"field_list_bytes32,omitempty" ssz-max:"100" ssz-size:"?,32"`
|
||||
Nested *VariableNestedContainer `protobuf:"bytes,5,opt,name=nested,proto3" json:"nested,omitempty"`
|
||||
BitlistField github_com_prysmaticlabs_go_bitfield.Bitlist `protobuf:"bytes,6,opt,name=bitlist_field,json=bitlistField,proto3" json:"bitlist_field,omitempty" cast-type:"github.com/prysmaticlabs/go-bitfield.Bitlist" ssz-max:"2048"`
|
||||
TrailingField []byte `protobuf:"bytes,7,opt,name=trailing_field,json=trailingField,proto3" json:"trailing_field,omitempty" ssz-size:"56"`
|
||||
NestedListField [][]byte `protobuf:"bytes,7,rep,name=nested_list_field,json=nestedListField,proto3" json:"nested_list_field,omitempty" ssz-max:"100,50" ssz-size:"?,?"`
|
||||
TrailingField []byte `protobuf:"bytes,8,opt,name=trailing_field,json=trailingField,proto3" json:"trailing_field,omitempty" ssz-size:"56"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
@@ -328,6 +337,13 @@ func (x *VariableTestContainer) GetBitlistField() github_com_prysmaticlabs_go_bi
|
||||
return github_com_prysmaticlabs_go_bitfield.Bitlist(nil)
|
||||
}
|
||||
|
||||
func (x *VariableTestContainer) GetNestedListField() [][]byte {
|
||||
if x != nil {
|
||||
return x.NestedListField
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *VariableTestContainer) GetTrailingField() []byte {
|
||||
if x != nil {
|
||||
return x.TrailingField
|
||||
@@ -384,14 +400,18 @@ var file_proto_ssz_query_ssz_query_proto_rawDesc = []byte{
|
||||
0x74, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x35, 0x31, 0x32, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12,
|
||||
0x2d, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x66, 0x69, 0x65, 0x6c,
|
||||
0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x35, 0x36, 0x52,
|
||||
0x0d, 0x74, 0x72, 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x22, 0x66,
|
||||
0x0a, 0x17, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64,
|
||||
0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x76, 0x61, 0x6c,
|
||||
0x75, 0x65, 0x31, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65,
|
||||
0x31, 0x12, 0x33, 0x0a, 0x11, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x5f,
|
||||
0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x18, 0x02, 0x20, 0x03, 0x28, 0x04, 0x42, 0x07, 0x92, 0xb5,
|
||||
0x18, 0x03, 0x31, 0x30, 0x30, 0x52, 0x0f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4c, 0x69, 0x73, 0x74,
|
||||
0x55, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x22, 0xdf, 0x03, 0x0a, 0x15, 0x56, 0x61, 0x72, 0x69, 0x61,
|
||||
0x0d, 0x74, 0x72, 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x22, 0xa5,
|
||||
0x01, 0x0a, 0x17, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x65, 0x73, 0x74, 0x65,
|
||||
0x64, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x76, 0x61,
|
||||
0x6c, 0x75, 0x65, 0x31, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75,
|
||||
0x65, 0x31, 0x12, 0x33, 0x0a, 0x11, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6c, 0x69, 0x73, 0x74,
|
||||
0x5f, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x18, 0x02, 0x20, 0x03, 0x28, 0x04, 0x42, 0x07, 0x92,
|
||||
0xb5, 0x18, 0x03, 0x31, 0x30, 0x30, 0x52, 0x0f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4c, 0x69, 0x73,
|
||||
0x74, 0x55, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x12, 0x3d, 0x0a, 0x11, 0x6e, 0x65, 0x73, 0x74, 0x65,
|
||||
0x64, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x03, 0x20, 0x03,
|
||||
0x28, 0x0c, 0x42, 0x11, 0x8a, 0xb5, 0x18, 0x03, 0x3f, 0x2c, 0x3f, 0x92, 0xb5, 0x18, 0x06, 0x31,
|
||||
0x30, 0x30, 0x2c, 0x35, 0x30, 0x52, 0x0f, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x4c, 0x69, 0x73,
|
||||
0x74, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x22, 0x9e, 0x04, 0x0a, 0x15, 0x56, 0x61, 0x72, 0x69, 0x61,
|
||||
0x62, 0x6c, 0x65, 0x54, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72,
|
||||
0x12, 0x2b, 0x0a, 0x0d, 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x66, 0x69, 0x65, 0x6c,
|
||||
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52,
|
||||
@@ -418,14 +438,18 @@ var file_proto_ssz_query_ssz_query_proto_rawDesc = []byte{
|
||||
0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f,
|
||||
0x67, 0x6f, 0x2d, 0x62, 0x69, 0x74, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x2e, 0x42, 0x69, 0x74, 0x6c,
|
||||
0x69, 0x73, 0x74, 0x92, 0xb5, 0x18, 0x04, 0x32, 0x30, 0x34, 0x38, 0x52, 0x0c, 0x62, 0x69, 0x74,
|
||||
0x6c, 0x69, 0x73, 0x74, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x2d, 0x0a, 0x0e, 0x74, 0x72, 0x61,
|
||||
0x69, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28,
|
||||
0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x35, 0x36, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x69, 0x6c,
|
||||
0x69, 0x6e, 0x67, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x42, 0x32, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68,
|
||||
0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x4f, 0x66, 0x66, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x4c,
|
||||
0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x36, 0x2f, 0x70, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x2f, 0x73, 0x73, 0x7a, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x62, 0x06, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x33,
|
||||
0x6c, 0x69, 0x73, 0x74, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x3d, 0x0a, 0x11, 0x6e, 0x65, 0x73,
|
||||
0x74, 0x65, 0x64, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x07,
|
||||
0x20, 0x03, 0x28, 0x0c, 0x42, 0x11, 0x8a, 0xb5, 0x18, 0x03, 0x3f, 0x2c, 0x3f, 0x92, 0xb5, 0x18,
|
||||
0x06, 0x31, 0x30, 0x30, 0x2c, 0x35, 0x30, 0x52, 0x0f, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x4c,
|
||||
0x69, 0x73, 0x74, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x2d, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x69,
|
||||
0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c,
|
||||
0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x35, 0x36, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x69, 0x6c, 0x69,
|
||||
0x6e, 0x67, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x42, 0x32, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75,
|
||||
0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x4f, 0x66, 0x66, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x61,
|
||||
0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x36, 0x2f, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x2f, 0x73, 0x73, 0x7a, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x62, 0x06, 0x70, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
@@ -65,6 +65,10 @@ message FixedTestContainer {
|
||||
message VariableNestedContainer {
|
||||
uint64 value1 = 1;
|
||||
repeated uint64 field_list_uint64 = 2 [ (ethereum.eth.ext.ssz_max) = "100" ];
|
||||
repeated bytes nested_list_field = 3 [
|
||||
(ethereum.eth.ext.ssz_size) = "?,?",
|
||||
(ethereum.eth.ext.ssz_max) = "100,50"
|
||||
];
|
||||
}
|
||||
|
||||
// VariableTestContainer - comprehensive variable-size container for SSZ query testing
|
||||
@@ -96,7 +100,14 @@ message VariableTestContainer {
|
||||
"github.com/prysmaticlabs/go-bitfield.Bitlist"
|
||||
];
|
||||
|
||||
// 2D bytes list - test list of bytelists.
|
||||
// e.g., ExecutionPayload.transactions
|
||||
repeated bytes nested_list_field = 7 [
|
||||
(ethereum.eth.ext.ssz_size) = "?,?",
|
||||
(ethereum.eth.ext.ssz_max) = "100,50"
|
||||
];
|
||||
|
||||
// Fixed-size trailing field - test fixed field after variable fields
|
||||
// Verifies correct offset calculation after variable-size fields
|
||||
bytes trailing_field = 7 [ (ethereum.eth.ext.ssz_size) = "56" ]; // Test: fixed 56-byte field at end, offset: 32 + 4 + 4 + 4 + 4 + 4 = 52
|
||||
bytes trailing_field = 8 [ (ethereum.eth.ext.ssz_size) = "56" ]; // Test: fixed 56-byte field at end, offset: 32 + 4 + 4 + 4 + 4 + 4 + 4 = 56
|
||||
}
|
||||
|
||||
@@ -324,7 +324,7 @@ func (v *VariableNestedContainer) MarshalSSZ() ([]byte, error) {
|
||||
// MarshalSSZTo ssz marshals the VariableNestedContainer object to a target array
|
||||
func (v *VariableNestedContainer) MarshalSSZTo(buf []byte) (dst []byte, err error) {
|
||||
dst = buf
|
||||
offset := int(12)
|
||||
offset := int(16)
|
||||
|
||||
// Field (0) 'Value1'
|
||||
dst = ssz.MarshalUint64(dst, v.Value1)
|
||||
@@ -333,6 +333,13 @@ func (v *VariableNestedContainer) MarshalSSZTo(buf []byte) (dst []byte, err erro
|
||||
dst = ssz.WriteOffset(dst, offset)
|
||||
offset += len(v.FieldListUint64) * 8
|
||||
|
||||
// Offset (2) 'NestedListField'
|
||||
dst = ssz.WriteOffset(dst, offset)
|
||||
for ii := 0; ii < len(v.NestedListField); ii++ {
|
||||
offset += 4
|
||||
offset += len(v.NestedListField[ii])
|
||||
}
|
||||
|
||||
// Field (1) 'FieldListUint64'
|
||||
if size := len(v.FieldListUint64); size > 100 {
|
||||
err = ssz.ErrListTooBigFn("--.FieldListUint64", size, 100)
|
||||
@@ -342,6 +349,26 @@ func (v *VariableNestedContainer) MarshalSSZTo(buf []byte) (dst []byte, err erro
|
||||
dst = ssz.MarshalUint64(dst, v.FieldListUint64[ii])
|
||||
}
|
||||
|
||||
// Field (2) 'NestedListField'
|
||||
if size := len(v.NestedListField); size > 100 {
|
||||
err = ssz.ErrListTooBigFn("--.NestedListField", size, 100)
|
||||
return
|
||||
}
|
||||
{
|
||||
offset = 4 * len(v.NestedListField)
|
||||
for ii := 0; ii < len(v.NestedListField); ii++ {
|
||||
dst = ssz.WriteOffset(dst, offset)
|
||||
offset += len(v.NestedListField[ii])
|
||||
}
|
||||
}
|
||||
for ii := 0; ii < len(v.NestedListField); ii++ {
|
||||
if size := len(v.NestedListField[ii]); size > 50 {
|
||||
err = ssz.ErrBytesLengthFn("--.NestedListField[ii]", size, 50)
|
||||
return
|
||||
}
|
||||
dst = append(dst, v.NestedListField[ii]...)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -349,12 +376,12 @@ func (v *VariableNestedContainer) MarshalSSZTo(buf []byte) (dst []byte, err erro
|
||||
func (v *VariableNestedContainer) UnmarshalSSZ(buf []byte) error {
|
||||
var err error
|
||||
size := uint64(len(buf))
|
||||
if size < 12 {
|
||||
if size < 16 {
|
||||
return ssz.ErrSize
|
||||
}
|
||||
|
||||
tail := buf
|
||||
var o1 uint64
|
||||
var o1, o2 uint64
|
||||
|
||||
// Field (0) 'Value1'
|
||||
v.Value1 = ssz.UnmarshallUint64(buf[0:8])
|
||||
@@ -364,13 +391,18 @@ func (v *VariableNestedContainer) UnmarshalSSZ(buf []byte) error {
|
||||
return ssz.ErrOffset
|
||||
}
|
||||
|
||||
if o1 != 12 {
|
||||
if o1 != 16 {
|
||||
return ssz.ErrInvalidVariableOffset
|
||||
}
|
||||
|
||||
// Offset (2) 'NestedListField'
|
||||
if o2 = ssz.ReadOffset(buf[12:16]); o2 > size || o1 > o2 {
|
||||
return ssz.ErrOffset
|
||||
}
|
||||
|
||||
// Field (1) 'FieldListUint64'
|
||||
{
|
||||
buf = tail[o1:]
|
||||
buf = tail[o1:o2]
|
||||
num, err := ssz.DivideInt2(len(buf), 8, 100)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -380,16 +412,45 @@ func (v *VariableNestedContainer) UnmarshalSSZ(buf []byte) error {
|
||||
v.FieldListUint64[ii] = ssz.UnmarshallUint64(buf[ii*8 : (ii+1)*8])
|
||||
}
|
||||
}
|
||||
|
||||
// Field (2) 'NestedListField'
|
||||
{
|
||||
buf = tail[o2:]
|
||||
num, err := ssz.DecodeDynamicLength(buf, 100)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
v.NestedListField = make([][]byte, num)
|
||||
err = ssz.UnmarshalDynamic(buf, num, func(indx int, buf []byte) (err error) {
|
||||
if len(buf) > 50 {
|
||||
return ssz.ErrBytesLength
|
||||
}
|
||||
if cap(v.NestedListField[indx]) == 0 {
|
||||
v.NestedListField[indx] = make([]byte, 0, len(buf))
|
||||
}
|
||||
v.NestedListField[indx] = append(v.NestedListField[indx], buf...)
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// SizeSSZ returns the ssz encoded size in bytes for the VariableNestedContainer object
|
||||
func (v *VariableNestedContainer) SizeSSZ() (size int) {
|
||||
size = 12
|
||||
size = 16
|
||||
|
||||
// Field (1) 'FieldListUint64'
|
||||
size += len(v.FieldListUint64) * 8
|
||||
|
||||
// Field (2) 'NestedListField'
|
||||
for ii := 0; ii < len(v.NestedListField); ii++ {
|
||||
size += 4
|
||||
size += len(v.NestedListField[ii])
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -421,6 +482,29 @@ func (v *VariableNestedContainer) HashTreeRootWith(hh *ssz.Hasher) (err error) {
|
||||
hh.MerkleizeWithMixin(subIndx, numItems, ssz.CalculateLimit(100, numItems, 8))
|
||||
}
|
||||
|
||||
// Field (2) 'NestedListField'
|
||||
{
|
||||
subIndx := hh.Index()
|
||||
num := uint64(len(v.NestedListField))
|
||||
if num > 100 {
|
||||
err = ssz.ErrIncorrectListSize
|
||||
return
|
||||
}
|
||||
for _, elem := range v.NestedListField {
|
||||
{
|
||||
elemIndx := hh.Index()
|
||||
byteLen := uint64(len(elem))
|
||||
if byteLen > 50 {
|
||||
err = ssz.ErrIncorrectListSize
|
||||
return
|
||||
}
|
||||
hh.AppendBytes32(elem)
|
||||
hh.MerkleizeWithMixin(elemIndx, byteLen, (50+31)/32)
|
||||
}
|
||||
}
|
||||
hh.MerkleizeWithMixin(subIndx, num, 100)
|
||||
}
|
||||
|
||||
hh.Merkleize(indx)
|
||||
return
|
||||
}
|
||||
@@ -433,7 +517,7 @@ func (v *VariableTestContainer) MarshalSSZ() ([]byte, error) {
|
||||
// MarshalSSZTo ssz marshals the VariableTestContainer object to a target array
|
||||
func (v *VariableTestContainer) MarshalSSZTo(buf []byte) (dst []byte, err error) {
|
||||
dst = buf
|
||||
offset := int(108)
|
||||
offset := int(112)
|
||||
|
||||
// Field (0) 'LeadingField'
|
||||
if size := len(v.LeadingField); size != 32 {
|
||||
@@ -465,7 +549,14 @@ func (v *VariableTestContainer) MarshalSSZTo(buf []byte) (dst []byte, err error)
|
||||
dst = ssz.WriteOffset(dst, offset)
|
||||
offset += len(v.BitlistField)
|
||||
|
||||
// Field (6) 'TrailingField'
|
||||
// Offset (6) 'NestedListField'
|
||||
dst = ssz.WriteOffset(dst, offset)
|
||||
for ii := 0; ii < len(v.NestedListField); ii++ {
|
||||
offset += 4
|
||||
offset += len(v.NestedListField[ii])
|
||||
}
|
||||
|
||||
// Field (7) 'TrailingField'
|
||||
if size := len(v.TrailingField); size != 56 {
|
||||
err = ssz.ErrBytesLengthFn("--.TrailingField", size, 56)
|
||||
return
|
||||
@@ -517,6 +608,26 @@ func (v *VariableTestContainer) MarshalSSZTo(buf []byte) (dst []byte, err error)
|
||||
}
|
||||
dst = append(dst, v.BitlistField...)
|
||||
|
||||
// Field (6) 'NestedListField'
|
||||
if size := len(v.NestedListField); size > 100 {
|
||||
err = ssz.ErrListTooBigFn("--.NestedListField", size, 100)
|
||||
return
|
||||
}
|
||||
{
|
||||
offset = 4 * len(v.NestedListField)
|
||||
for ii := 0; ii < len(v.NestedListField); ii++ {
|
||||
dst = ssz.WriteOffset(dst, offset)
|
||||
offset += len(v.NestedListField[ii])
|
||||
}
|
||||
}
|
||||
for ii := 0; ii < len(v.NestedListField); ii++ {
|
||||
if size := len(v.NestedListField[ii]); size > 50 {
|
||||
err = ssz.ErrBytesLengthFn("--.NestedListField[ii]", size, 50)
|
||||
return
|
||||
}
|
||||
dst = append(dst, v.NestedListField[ii]...)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -524,12 +635,12 @@ func (v *VariableTestContainer) MarshalSSZTo(buf []byte) (dst []byte, err error)
|
||||
func (v *VariableTestContainer) UnmarshalSSZ(buf []byte) error {
|
||||
var err error
|
||||
size := uint64(len(buf))
|
||||
if size < 108 {
|
||||
if size < 112 {
|
||||
return ssz.ErrSize
|
||||
}
|
||||
|
||||
tail := buf
|
||||
var o1, o2, o3, o4, o5 uint64
|
||||
var o1, o2, o3, o4, o5, o6 uint64
|
||||
|
||||
// Field (0) 'LeadingField'
|
||||
if cap(v.LeadingField) == 0 {
|
||||
@@ -542,7 +653,7 @@ func (v *VariableTestContainer) UnmarshalSSZ(buf []byte) error {
|
||||
return ssz.ErrOffset
|
||||
}
|
||||
|
||||
if o1 != 108 {
|
||||
if o1 != 112 {
|
||||
return ssz.ErrInvalidVariableOffset
|
||||
}
|
||||
|
||||
@@ -566,11 +677,16 @@ func (v *VariableTestContainer) UnmarshalSSZ(buf []byte) error {
|
||||
return ssz.ErrOffset
|
||||
}
|
||||
|
||||
// Field (6) 'TrailingField'
|
||||
if cap(v.TrailingField) == 0 {
|
||||
v.TrailingField = make([]byte, 0, len(buf[52:108]))
|
||||
// Offset (6) 'NestedListField'
|
||||
if o6 = ssz.ReadOffset(buf[52:56]); o6 > size || o5 > o6 {
|
||||
return ssz.ErrOffset
|
||||
}
|
||||
v.TrailingField = append(v.TrailingField, buf[52:108]...)
|
||||
|
||||
// Field (7) 'TrailingField'
|
||||
if cap(v.TrailingField) == 0 {
|
||||
v.TrailingField = make([]byte, 0, len(buf[56:112]))
|
||||
}
|
||||
v.TrailingField = append(v.TrailingField, buf[56:112]...)
|
||||
|
||||
// Field (1) 'FieldListUint64'
|
||||
{
|
||||
@@ -632,7 +748,7 @@ func (v *VariableTestContainer) UnmarshalSSZ(buf []byte) error {
|
||||
|
||||
// Field (5) 'BitlistField'
|
||||
{
|
||||
buf = tail[o5:]
|
||||
buf = tail[o5:o6]
|
||||
if err = ssz.ValidateBitlist(buf, 2048); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -641,12 +757,35 @@ func (v *VariableTestContainer) UnmarshalSSZ(buf []byte) error {
|
||||
}
|
||||
v.BitlistField = append(v.BitlistField, buf...)
|
||||
}
|
||||
|
||||
// Field (6) 'NestedListField'
|
||||
{
|
||||
buf = tail[o6:]
|
||||
num, err := ssz.DecodeDynamicLength(buf, 100)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
v.NestedListField = make([][]byte, num)
|
||||
err = ssz.UnmarshalDynamic(buf, num, func(indx int, buf []byte) (err error) {
|
||||
if len(buf) > 50 {
|
||||
return ssz.ErrBytesLength
|
||||
}
|
||||
if cap(v.NestedListField[indx]) == 0 {
|
||||
v.NestedListField[indx] = make([]byte, 0, len(buf))
|
||||
}
|
||||
v.NestedListField[indx] = append(v.NestedListField[indx], buf...)
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// SizeSSZ returns the ssz encoded size in bytes for the VariableTestContainer object
|
||||
func (v *VariableTestContainer) SizeSSZ() (size int) {
|
||||
size = 108
|
||||
size = 112
|
||||
|
||||
// Field (1) 'FieldListUint64'
|
||||
size += len(v.FieldListUint64) * 8
|
||||
@@ -666,6 +805,12 @@ func (v *VariableTestContainer) SizeSSZ() (size int) {
|
||||
// Field (5) 'BitlistField'
|
||||
size += len(v.BitlistField)
|
||||
|
||||
// Field (6) 'NestedListField'
|
||||
for ii := 0; ii < len(v.NestedListField); ii++ {
|
||||
size += 4
|
||||
size += len(v.NestedListField[ii])
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -748,7 +893,30 @@ func (v *VariableTestContainer) HashTreeRootWith(hh *ssz.Hasher) (err error) {
|
||||
}
|
||||
hh.PutBitlist(v.BitlistField, 2048)
|
||||
|
||||
// Field (6) 'TrailingField'
|
||||
// Field (6) 'NestedListField'
|
||||
{
|
||||
subIndx := hh.Index()
|
||||
num := uint64(len(v.NestedListField))
|
||||
if num > 100 {
|
||||
err = ssz.ErrIncorrectListSize
|
||||
return
|
||||
}
|
||||
for _, elem := range v.NestedListField {
|
||||
{
|
||||
elemIndx := hh.Index()
|
||||
byteLen := uint64(len(elem))
|
||||
if byteLen > 50 {
|
||||
err = ssz.ErrIncorrectListSize
|
||||
return
|
||||
}
|
||||
hh.AppendBytes32(elem)
|
||||
hh.MerkleizeWithMixin(elemIndx, byteLen, (50+31)/32)
|
||||
}
|
||||
}
|
||||
hh.MerkleizeWithMixin(subIndx, num, 100)
|
||||
}
|
||||
|
||||
// Field (7) 'TrailingField'
|
||||
if size := len(v.TrailingField); size != 56 {
|
||||
err = ssz.ErrBytesLengthFn("--.TrailingField", size, 56)
|
||||
return
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
version: v1.6.0-alpha.6
|
||||
version: v1.6.0-beta.0
|
||||
style: full
|
||||
|
||||
specrefs:
|
||||
@@ -90,14 +90,14 @@ exceptions:
|
||||
- BuilderPendingWithdrawal#gloas
|
||||
- DataColumnSidecar#gloas
|
||||
- ExecutionPayloadEnvelope#gloas
|
||||
- ExecutionPayloadHeader#gloas
|
||||
- ExecutionPayloadBid#gloas
|
||||
- ForkChoiceNode#gloas
|
||||
- IndexedPayloadAttestation#gloas
|
||||
- PayloadAttestation#gloas
|
||||
- PayloadAttestationData#gloas
|
||||
- PayloadAttestationMessage#gloas
|
||||
- SignedExecutionPayloadEnvelope#gloas
|
||||
- SignedExecutionPayloadHeader#gloas
|
||||
- SignedExecutionPayloadBid#gloas
|
||||
|
||||
dataclasses:
|
||||
# Not implemented
|
||||
@@ -172,7 +172,9 @@ exceptions:
|
||||
- compute_pulled_up_tip#phase0
|
||||
- filter_block_tree#phase0
|
||||
- get_aggregate_and_proof#phase0
|
||||
- get_aggregate_due_ms#phase0
|
||||
- get_attestation_component_deltas#phase0
|
||||
- get_attestation_due_ms#phase0
|
||||
- get_attesting_balance#phase0
|
||||
- get_base_reward#phase0
|
||||
- get_checkpoint_block#phase0
|
||||
@@ -186,6 +188,7 @@ exceptions:
|
||||
- get_matching_source_attestations#phase0
|
||||
- get_matching_target_attestations#phase0
|
||||
- get_proposer_head#phase0
|
||||
- get_proposer_reorg_cutoff_ms#phase0
|
||||
- get_proposer_score#phase0
|
||||
- get_slot_component_duration_ms#phase0
|
||||
- get_slot_signature#phase0
|
||||
@@ -214,11 +217,13 @@ exceptions:
|
||||
- compute_sync_committee_period_at_slot#altair
|
||||
- compute_timestamp_at_slot#bellatrix
|
||||
- get_contribution_and_proof#altair
|
||||
- get_contribution_due_ms#altair
|
||||
- get_index_for_new_validator#altair
|
||||
- get_safety_threshold#altair
|
||||
- get_subtree_index#altair
|
||||
- get_sync_committee_message#altair
|
||||
- get_sync_committee_selection_proof#altair
|
||||
- get_sync_message_due_ms#altair
|
||||
- get_unslashed_participating_indices#altair
|
||||
- is_assigned_to_sync_committee#altair
|
||||
- is_finality_update#altair
|
||||
@@ -294,13 +299,17 @@ exceptions:
|
||||
- compute_fork_version#gloas
|
||||
- compute_proposer_indices#gloas
|
||||
- get_ancestor#gloas
|
||||
- get_aggregate_due_ms#gloas
|
||||
- get_attestation_due_ms#gloas
|
||||
- get_attestation_participation_flag_indices#gloas
|
||||
- get_builder_payment_quorum_threshold#gloas
|
||||
- get_checkpoint_block#gloas
|
||||
- get_contribution_due_ms#gloas
|
||||
- get_data_column_sidecars#gloas
|
||||
- get_data_column_sidecars_from_block#gloas
|
||||
- get_data_column_sidecars_from_column_sidecar#gloas
|
||||
- get_execution_payload_envelope_signature#gloas
|
||||
- get_execution_payload_header_signature#gloas
|
||||
- get_execution_payload_bid_signature#gloas
|
||||
- get_expected_withdrawals#gloas
|
||||
- get_forkchoice_store#gloas
|
||||
- get_head#gloas
|
||||
@@ -308,8 +317,11 @@ exceptions:
|
||||
- get_next_sync_committee_indices#gloas
|
||||
- get_node_children#gloas
|
||||
- get_parent_payload_status#gloas
|
||||
- get_payload_attestation_due_ms#gloas
|
||||
- get_payload_attestation_message_signature#gloas
|
||||
- get_payload_status_tiebreaker#gloas
|
||||
- get_pending_balance_to_withdraw#gloas
|
||||
- get_sync_message_due_ms#gloas
|
||||
- get_ptc#gloas
|
||||
- get_ptc_assignment#gloas
|
||||
- get_weight#gloas
|
||||
@@ -334,9 +346,10 @@ exceptions:
|
||||
- process_builder_pending_payments#gloas
|
||||
- process_epoch#gloas
|
||||
- process_execution_payload#gloas
|
||||
- process_execution_payload_header#gloas
|
||||
- process_execution_payload_bid#gloas
|
||||
- process_operations#gloas
|
||||
- process_payload_attestation#gloas
|
||||
- process_proposer_slashing#gloas
|
||||
- process_slot#gloas
|
||||
- process_withdrawals#gloas
|
||||
- remove_flag#gloas
|
||||
@@ -347,4 +360,4 @@ exceptions:
|
||||
- validate_on_attestation#gloas
|
||||
- verify_data_column_sidecar_inclusion_proof#gloas
|
||||
- verify_execution_payload_envelope_signature#gloas
|
||||
- verify_execution_payload_header_signature#gloas
|
||||
- verify_execution_payload_bid_signature#gloas
|
||||
|
||||
@@ -4200,11 +4200,12 @@
|
||||
- name: is_proposing_on_time
|
||||
sources: []
|
||||
spec: |
|
||||
<spec fn="is_proposing_on_time" fork="phase0" hash="cadfde05">
|
||||
<spec fn="is_proposing_on_time" fork="phase0" hash="dc5256b4">
|
||||
def is_proposing_on_time(store: Store) -> bool:
|
||||
seconds_since_genesis = store.time - store.genesis_time
|
||||
time_into_slot_ms = seconds_to_milliseconds(seconds_since_genesis) % SLOT_DURATION_MS
|
||||
proposer_reorg_cutoff_ms = get_slot_component_duration_ms(PROPOSER_REORG_CUTOFF_BPS)
|
||||
epoch = get_current_store_epoch(store)
|
||||
proposer_reorg_cutoff_ms = get_proposer_reorg_cutoff_ms(epoch)
|
||||
return time_into_slot_ms <= proposer_reorg_cutoff_ms
|
||||
</spec>
|
||||
|
||||
@@ -4655,7 +4656,7 @@
|
||||
- file: beacon-chain/blockchain/receive_block.go
|
||||
search: func (s *Service) ReceiveBlock(
|
||||
spec: |
|
||||
<spec fn="on_block" fork="phase0" hash="0bd081f0">
|
||||
<spec fn="on_block" fork="phase0" hash="aff24b59">
|
||||
def on_block(store: Store, signed_block: SignedBeaconBlock) -> None:
|
||||
block = signed_block.message
|
||||
# Parent block must be known
|
||||
@@ -4688,7 +4689,8 @@
|
||||
# Add block timeliness to the store
|
||||
seconds_since_genesis = store.time - store.genesis_time
|
||||
time_into_slot_ms = seconds_to_milliseconds(seconds_since_genesis) % SLOT_DURATION_MS
|
||||
attestation_threshold_ms = get_slot_component_duration_ms(ATTESTATION_DUE_BPS)
|
||||
epoch = get_current_store_epoch(store)
|
||||
attestation_threshold_ms = get_attestation_due_ms(epoch)
|
||||
is_before_attesting_interval = time_into_slot_ms < attestation_threshold_ms
|
||||
is_timely = get_current_slot(store) == block.slot and is_before_attesting_interval
|
||||
store.block_timeliness[hash_tree_root(block)] = is_timely
|
||||
@@ -4710,7 +4712,7 @@
|
||||
- file: beacon-chain/blockchain/receive_block.go
|
||||
search: func (s *Service) ReceiveBlock(
|
||||
spec: |
|
||||
<spec fn="on_block" fork="bellatrix" hash="cceac63a">
|
||||
<spec fn="on_block" fork="bellatrix" hash="a3193d92">
|
||||
def on_block(store: Store, signed_block: SignedBeaconBlock) -> None:
|
||||
"""
|
||||
Run ``on_block`` upon receiving a new block.
|
||||
@@ -4754,7 +4756,8 @@
|
||||
# Add block timeliness to the store
|
||||
seconds_since_genesis = store.time - store.genesis_time
|
||||
time_into_slot_ms = seconds_to_milliseconds(seconds_since_genesis) % SLOT_DURATION_MS
|
||||
attestation_threshold_ms = get_slot_component_duration_ms(ATTESTATION_DUE_BPS)
|
||||
epoch = get_current_store_epoch(store)
|
||||
attestation_threshold_ms = get_attestation_due_ms(epoch)
|
||||
is_before_attesting_interval = time_into_slot_ms < attestation_threshold_ms
|
||||
is_timely = get_current_slot(store) == block.slot and is_before_attesting_interval
|
||||
store.block_timeliness[hash_tree_root(block)] = is_timely
|
||||
@@ -4776,7 +4779,7 @@
|
||||
- file: beacon-chain/blockchain/receive_block.go
|
||||
search: func (s *Service) ReceiveBlock(
|
||||
spec: |
|
||||
<spec fn="on_block" fork="capella" hash="b051b7c6">
|
||||
<spec fn="on_block" fork="capella" hash="560056ad">
|
||||
def on_block(store: Store, signed_block: SignedBeaconBlock) -> None:
|
||||
"""
|
||||
Run ``on_block`` upon receiving a new block.
|
||||
@@ -4812,7 +4815,8 @@
|
||||
# Add block timeliness to the store
|
||||
seconds_since_genesis = store.time - store.genesis_time
|
||||
time_into_slot_ms = seconds_to_milliseconds(seconds_since_genesis) % SLOT_DURATION_MS
|
||||
attestation_threshold_ms = get_slot_component_duration_ms(ATTESTATION_DUE_BPS)
|
||||
epoch = get_current_store_epoch(store)
|
||||
attestation_threshold_ms = get_attestation_due_ms(epoch)
|
||||
is_before_attesting_interval = time_into_slot_ms < attestation_threshold_ms
|
||||
is_timely = get_current_slot(store) == block.slot and is_before_attesting_interval
|
||||
store.block_timeliness[hash_tree_root(block)] = is_timely
|
||||
@@ -4834,7 +4838,7 @@
|
||||
- file: beacon-chain/blockchain/receive_block.go
|
||||
search: func (s *Service) ReceiveBlock(
|
||||
spec: |
|
||||
<spec fn="on_block" fork="deneb" hash="1f48df4d">
|
||||
<spec fn="on_block" fork="deneb" hash="9565acee">
|
||||
def on_block(store: Store, signed_block: SignedBeaconBlock) -> None:
|
||||
"""
|
||||
Run ``on_block`` upon receiving a new block.
|
||||
@@ -4875,7 +4879,8 @@
|
||||
# Add block timeliness to the store
|
||||
seconds_since_genesis = store.time - store.genesis_time
|
||||
time_into_slot_ms = seconds_to_milliseconds(seconds_since_genesis) % SLOT_DURATION_MS
|
||||
attestation_threshold_ms = get_slot_component_duration_ms(ATTESTATION_DUE_BPS)
|
||||
epoch = get_current_store_epoch(store)
|
||||
attestation_threshold_ms = get_attestation_due_ms(epoch)
|
||||
is_before_attesting_interval = time_into_slot_ms < attestation_threshold_ms
|
||||
is_timely = get_current_slot(store) == block.slot and is_before_attesting_interval
|
||||
store.block_timeliness[hash_tree_root(block)] = is_timely
|
||||
@@ -4897,7 +4902,7 @@
|
||||
- file: beacon-chain/blockchain/receive_block.go
|
||||
search: func (s *Service) ReceiveBlock(
|
||||
spec: |
|
||||
<spec fn="on_block" fork="fulu" hash="a27a9edb">
|
||||
<spec fn="on_block" fork="fulu" hash="4f955de9">
|
||||
def on_block(store: Store, signed_block: SignedBeaconBlock) -> None:
|
||||
"""
|
||||
Run ``on_block`` upon receiving a new block.
|
||||
@@ -4938,7 +4943,8 @@
|
||||
# Add block timeliness to the store
|
||||
seconds_since_genesis = store.time - store.genesis_time
|
||||
time_into_slot_ms = seconds_to_milliseconds(seconds_since_genesis) % SLOT_DURATION_MS
|
||||
attestation_threshold_ms = get_slot_component_duration_ms(ATTESTATION_DUE_BPS)
|
||||
epoch = get_current_store_epoch(store)
|
||||
attestation_threshold_ms = get_attestation_due_ms(epoch)
|
||||
is_before_attesting_interval = time_into_slot_ms < attestation_threshold_ms
|
||||
is_timely = get_current_slot(store) == block.slot and is_before_attesting_interval
|
||||
store.block_timeliness[hash_tree_root(block)] = is_timely
|
||||
@@ -7034,7 +7040,7 @@
|
||||
- file: beacon-chain/core/blocks/exit.go
|
||||
search: func ProcessVoluntaryExits(
|
||||
spec: |
|
||||
<spec fn="process_voluntary_exit" fork="electra" hash="6dcb5530">
|
||||
<spec fn="process_voluntary_exit" fork="electra" hash="51b07d36">
|
||||
def process_voluntary_exit(state: BeaconState, signed_voluntary_exit: SignedVoluntaryExit) -> None:
|
||||
voluntary_exit = signed_voluntary_exit.message
|
||||
validator = state.validators[voluntary_exit.validator_index]
|
||||
@@ -7048,7 +7054,6 @@
|
||||
assert get_current_epoch(state) >= validator.activation_epoch + SHARD_COMMITTEE_PERIOD
|
||||
# [New in Electra:EIP7251]
|
||||
# Only exit validator if it has no pending withdrawals in the queue
|
||||
|
||||
assert get_pending_balance_to_withdraw(state, voluntary_exit.validator_index) == 0
|
||||
# Verify signature
|
||||
domain = compute_domain(
|
||||
|
||||
@@ -90,6 +90,7 @@ func (r *runner) run(ctx context.Context) {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
log.Info("Context canceled, stopping validator")
|
||||
//nolint:govet
|
||||
return // Exit if context is canceled.
|
||||
case slot := <-v.NextSlot():
|
||||
if !r.healthMonitor.IsHealthy() {
|
||||
@@ -98,7 +99,7 @@ func (r *runner) run(ctx context.Context) {
|
||||
}
|
||||
|
||||
deadline := v.SlotDeadline(slot)
|
||||
slotCtx, cancel := context.WithDeadline(ctx, deadline)
|
||||
slotCtx, cancel := context.WithDeadline(ctx, deadline) //nolint:govet
|
||||
|
||||
var span trace.Span
|
||||
slotCtx, span = prysmTrace.StartSpan(slotCtx, "validator.processSlot")
|
||||
@@ -131,7 +132,7 @@ func (r *runner) run(ctx context.Context) {
|
||||
|
||||
// Start fetching domain data for the next epoch.
|
||||
if slots.IsEpochEnd(slot) {
|
||||
domainCtx, _ := context.WithDeadline(ctx, deadline)
|
||||
domainCtx, _ := context.WithDeadline(ctx, deadline) //nolint:govet
|
||||
go v.UpdateDomainDataCaches(domainCtx, slot+1)
|
||||
}
|
||||
|
||||
@@ -145,7 +146,7 @@ func (r *runner) run(ctx context.Context) {
|
||||
continue
|
||||
}
|
||||
// performRoles calls span.End()
|
||||
rolesCtx, _ := context.WithDeadline(ctx, deadline)
|
||||
rolesCtx, _ := context.WithDeadline(ctx, deadline) //nolint:govet
|
||||
performRoles(rolesCtx, allRoles, v, slot, &wg, span)
|
||||
case e := <-v.EventsChan():
|
||||
v.ProcessEvent(ctx, e)
|
||||
|
||||
@@ -52,9 +52,7 @@ func TestNewKeymanager(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
}))
|
||||
root, err := hexutil.Decode("0x270d43e74ce340de4bca2b1936beca0f4f5408d9e78aec4850920baf659d5b69")
|
||||
if err != nil {
|
||||
fmt.Printf("error: %v", err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
tests := []struct {
|
||||
name string
|
||||
args *SetupConfig
|
||||
@@ -361,27 +359,19 @@ func TestKeymanager_Sign(t *testing.T) {
|
||||
}
|
||||
ctx := t.Context()
|
||||
root, err := hexutil.Decode("0x270d43e74ce340de4bca2b1936beca0f4f5408d9e78aec4850920baf659d5b69")
|
||||
if err != nil {
|
||||
fmt.Printf("error: %v", err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
config := &SetupConfig{
|
||||
BaseEndpoint: "http://example.com",
|
||||
GenesisValidatorsRoot: root,
|
||||
PublicKeysURL: "http://example2.com/api/v1/eth2/publicKeys",
|
||||
}
|
||||
km, err := NewKeymanager(ctx, config)
|
||||
if err != nil {
|
||||
fmt.Printf("error: %v", err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
km.client = client
|
||||
desiredSigBytes, err := hexutil.Decode(client.Signature)
|
||||
if err != nil {
|
||||
fmt.Printf("error: %v", err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
desiredSig, err := bls.SignatureFromBytes(desiredSigBytes)
|
||||
if err != nil {
|
||||
fmt.Printf("error: %v", err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
type args struct {
|
||||
request *validatorpb.SignRequest
|
||||
}
|
||||
@@ -508,13 +498,9 @@ func TestKeymanager_FetchValidatingPublicKeys_HappyPath_WithKeyList(t *testing.T
|
||||
ProvidedPublicKeys: []string{"0xa2b5aaad9c6efefe7bb9b1243a043404f3362937cfb6b31833929833173f476630ea2cfeb0d9ddf15f97ca8685948820"},
|
||||
}
|
||||
km, err := NewKeymanager(ctx, config)
|
||||
if err != nil {
|
||||
fmt.Printf("error: %v", err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
resp, err := km.FetchValidatingPublicKeys(ctx)
|
||||
if err != nil {
|
||||
fmt.Printf("error: %v", err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, resp)
|
||||
assert.Nil(t, err)
|
||||
assert.EqualValues(t, resp, keys)
|
||||
@@ -523,16 +509,12 @@ func TestKeymanager_FetchValidatingPublicKeys_HappyPath_WithKeyList(t *testing.T
|
||||
func TestKeymanager_FetchValidatingPublicKeys_HappyPath_WithExternalURL(t *testing.T) {
|
||||
ctx := t.Context()
|
||||
decodedKey, err := hexutil.Decode("0xa2b5aaad9c6efefe7bb9b1243a043404f3362937cfb6b31833929833173f476630ea2cfeb0d9ddf15f97ca8685948820")
|
||||
if err != nil {
|
||||
fmt.Printf("error: %v", err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
keys := [][48]byte{
|
||||
bytesutil.ToBytes48(decodedKey),
|
||||
}
|
||||
root, err := hexutil.Decode("0x270d43e74ce340de4bca2b1936beca0f4f5408d9e78aec4850920baf659d5b69")
|
||||
if err != nil {
|
||||
fmt.Printf("error: %v", err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
@@ -546,9 +528,7 @@ func TestKeymanager_FetchValidatingPublicKeys_HappyPath_WithExternalURL(t *testi
|
||||
PublicKeysURL: srv.URL + "/api/v1/eth2/publicKeys",
|
||||
}
|
||||
km, err := NewKeymanager(ctx, config)
|
||||
if err != nil {
|
||||
fmt.Printf("error: %v", err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
resp, err := km.FetchValidatingPublicKeys(ctx)
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, resp)
|
||||
@@ -565,9 +545,7 @@ func TestKeymanager_FetchValidatingPublicKeys_WithExternalURL_ThrowsError(t *tes
|
||||
defer srv.Close()
|
||||
|
||||
root, err := hexutil.Decode("0x270d43e74ce340de4bca2b1936beca0f4f5408d9e78aec4850920baf659d5b69")
|
||||
if err != nil {
|
||||
fmt.Printf("error: %v", err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
config := &SetupConfig{
|
||||
BaseEndpoint: "http://example.com",
|
||||
GenesisValidatorsRoot: root,
|
||||
@@ -581,17 +559,13 @@ func TestKeymanager_FetchValidatingPublicKeys_WithExternalURL_ThrowsError(t *tes
|
||||
func TestKeymanager_AddPublicKeys(t *testing.T) {
|
||||
ctx := t.Context()
|
||||
root, err := hexutil.Decode("0x270d43e74ce340de4bca2b1936beca0f4f5408d9e78aec4850920baf659d5b69")
|
||||
if err != nil {
|
||||
fmt.Printf("error: %v", err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
config := &SetupConfig{
|
||||
BaseEndpoint: "http://example.com",
|
||||
GenesisValidatorsRoot: root,
|
||||
}
|
||||
km, err := NewKeymanager(ctx, config)
|
||||
if err != nil {
|
||||
fmt.Printf("error: %v", err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
publicKeys := []string{"0xa2b5aaad9c6efefe7bb9b1243a043404f3362937cfb6b31833929833173f476630ea2cfeb0d9ddf15f97ca8685948820"}
|
||||
statuses, err := km.AddPublicKeys(publicKeys)
|
||||
require.NoError(t, err)
|
||||
@@ -614,18 +588,14 @@ func TestKeymanager_AddPublicKeys_WithFile(t *testing.T) {
|
||||
require.NoError(t, stdOutFile.Chmod(os.FileMode(0600)))
|
||||
keyFilePath := filepath.Join(dir, "keyfile.txt")
|
||||
root, err := hexutil.Decode("0x270d43e74ce340de4bca2b1936beca0f4f5408d9e78aec4850920baf659d5b69")
|
||||
if err != nil {
|
||||
fmt.Printf("error: %v", err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
config := &SetupConfig{
|
||||
BaseEndpoint: "http://example.com",
|
||||
GenesisValidatorsRoot: root,
|
||||
KeyFilePath: keyFilePath,
|
||||
}
|
||||
km, err := NewKeymanager(ctx, config)
|
||||
if err != nil {
|
||||
fmt.Printf("error: %v", err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
publicKeys := []string{"0xa2b5aaad9c6efefe7bb9b1243a043404f3362937cfb6b31833929833173f476630ea2cfeb0d9ddf15f97ca8685948820"}
|
||||
statuses, err := km.AddPublicKeys(publicKeys)
|
||||
require.NoError(t, err)
|
||||
@@ -646,17 +616,13 @@ func TestKeymanager_AddPublicKeys_WithFile(t *testing.T) {
|
||||
func TestKeymanager_DeletePublicKeys(t *testing.T) {
|
||||
ctx := t.Context()
|
||||
root, err := hexutil.Decode("0x270d43e74ce340de4bca2b1936beca0f4f5408d9e78aec4850920baf659d5b69")
|
||||
if err != nil {
|
||||
fmt.Printf("error: %v", err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
config := &SetupConfig{
|
||||
BaseEndpoint: "http://example.com",
|
||||
GenesisValidatorsRoot: root,
|
||||
}
|
||||
km, err := NewKeymanager(ctx, config)
|
||||
if err != nil {
|
||||
fmt.Printf("error: %v", err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
publicKeys := []string{"0xa2b5aaad9c6efefe7bb9b1243a043404f3362937cfb6b31833929833173f476630ea2cfeb0d9ddf15f97ca8685948820"}
|
||||
statuses, err := km.AddPublicKeys(publicKeys)
|
||||
require.NoError(t, err)
|
||||
@@ -686,18 +652,14 @@ func TestKeymanager_DeletePublicKeys_WithFile(t *testing.T) {
|
||||
require.NoError(t, stdOutFile.Chmod(os.FileMode(0600)))
|
||||
keyFilePath := filepath.Join(dir, "keyfile.txt")
|
||||
root, err := hexutil.Decode("0x270d43e74ce340de4bca2b1936beca0f4f5408d9e78aec4850920baf659d5b69")
|
||||
if err != nil {
|
||||
fmt.Printf("error: %v", err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
config := &SetupConfig{
|
||||
BaseEndpoint: "http://example.com",
|
||||
GenesisValidatorsRoot: root,
|
||||
KeyFilePath: keyFilePath,
|
||||
}
|
||||
km, err := NewKeymanager(ctx, config)
|
||||
if err != nil {
|
||||
fmt.Printf("error: %v", err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
publicKeys := []string{"0xa2b5aaad9c6efefe7bb9b1243a043404f3362937cfb6b31833929833173f476630ea2cfeb0d9ddf15f97ca8685948820", "0x8000a9a6d3f5e22d783eefaadbcf0298146adb5d95b04db910a0d4e16976b30229d0b1e7b9cda6c7e0bfa11f72efe055"}
|
||||
statuses, err := km.AddPublicKeys(publicKeys)
|
||||
require.NoError(t, err)
|
||||
|
||||
Reference in New Issue
Block a user