Compare commits

...

32 Commits

Author SHA1 Message Date
james-prysm
b1b3cd11f5 Merge branch 'develop' into beacon-proposer-settings 2024-02-12 13:47:04 -06:00
Preston Van Loon
c4c6b47d9b validator/exit: Print other testnet beaconcha.in URLs (#13610) 2024-02-12 19:36:58 +00:00
Manu NALEPA
06a5548424 Slasher: Fixes double votes false positive and attester slashings duplication. (#13596)
* `Test_processAttestations`: Remove duplicated tests.

* Sort indexed attestations by data root.

* `processAttestations`: Don't return duplicate slashings anymore.

Fix https://github.com/prysmaticlabs/prysm/issues/13592.

* `AttesterDoubleVote`: Rename fields.

* Detect double votes in different batches.

In order to do that:
1. Each attestation of the batch is tested against the other attestations of the batch.
2. Each attestation of the batch is tested against the content of the database.
2. Attestations are saved into the database.

Fixes https://github.com/prysmaticlabs/prysm/issues/13590.
2024-02-12 17:35:22 +00:00
terence
5e74c798d4 Use Gwei for value in get header log (#13608) 2024-02-12 15:14:58 +00:00
Nishant Das
7b955c94ec Reduce Lookahead Steps Parameter (#13599)
* reduce lookahead steps

* test
2024-02-12 14:39:42 +00:00
terence
256a05bfd5 Remove deprecated flags: optional engine and registration (#13606) 2024-02-10 04:59:00 +00:00
Preston Van Loon
03068ba781 db: clear blobs when using --clear-db or --force-clear-db (#13605)
* Call Close() as part of ClearDB

* Add method to clear blob storage

* Clear blob storage when clearing DB
2024-02-10 03:52:30 +00:00
Nishant Das
5df8b83a05 Validate Range Availibility (#13587)
* fix it

* check range avail

* add test cases

* add checks

* kasey's review

* gaz
2024-02-09 23:41:08 +00:00
terence
db653b8863 Remove deprecated build block parallel flag (#13539) 2024-02-09 22:13:51 +00:00
Manu NALEPA
af203efa0c Slasher: Refactor and add tests (#13589)
* `helpers.go`: Improve naming consistency.

* `detect_attestations.go`: Improve readability.

* `receive.go`: Add `attsQueueSize` in log message.

* `checkSlashableAttestations`: Improve logging.

`avgBatchProcessingTime` is not displayed any more if not batch is
processed.

* `loadChunks`: Use explicit `chunkKind` and `chunkIndices`.

* `getChunk`: Use specific `chunkIndex` and `chunkKind`.

* `validatorIndicesInChunk` -> `validatorIndexesInChunk`.

* `epochUpdateForValidator`: Use explicit arguments.

* `getChunk`: Change order of arguments.

* `latestEpochWrittenForValidator`: Use `ok` parameter.

So the default value is not any more considered as the absence of
value.

* `applyAttestationForValidator`: Use explicit arguments.

* `updateSpans`: Use explicit arguments.

* `saveUpdatedChunks`: Use explicit arguments.

* `checkSurrounds`: Use explicit arguments.

We see here that, previously, in `checkSlashableAttestations`,
`checkSurrounds` was called with the default value of `slashertypes`: `MinSpan`.

Now, we set it expliciterly at `MinSpan`, which may explicit a bug.

* `epochUpdateForValidator`: Set modified by the function argument first.

* `applyAttestationForValidator`: Set mutated argument `chunksByChunkIdx`first.

* `applyAttestationForValidator`: Rename variables.

* `Test_processQueuedAttestations`: Fix test.

Two tests were actually exactly the same.

* `updateSpans`: Keep happy path in the outer scope.

Even if in this case the "happy" path means slashing.

* `checkSurrounds`: Rename variable.

* `getChunk`: Avoid side effects.

It adds a few lines for callers, but it does not modify any more
arguments and it does what it says: getting a chunk.

* `CheckSlashable`: Flatten.

* `detect_attestations_test.go`: Simplify.

* `CheckSlashable`: Add error log in case of missing attestation.

* `processQueuedAttestations`: Extract a sub function.

So testing will be easier.

* `processAttesterSlashings` and `processProposerSlashings`: Improve.

* `processAttesterSlashings`: Return processed slashings.

* `createAttestationWrapper`: Rename variables.

* `signingRoot` ==> `headerRoot` or `dataRoot`.

Before this commit, there is two typse of `signing root`s floating around.
- The first one is a real signing root, aka a hash tree root computed from an object root and
a domain. This real signing root is the object ready to be signed.
- The second one is a "false" signing root, which is actually just the hash tree root of an object. This object is either the `Data` field of an attestation, or the `Header` field of a block.

Having 2 differents objects with the same name `signing root` is quite confusing.
This commit renames wrongly named `signing root` objects.

* `createAttestationWrapper` => `createAttestationWrapperEmptySig`.

So it's clear for the user that the created attestation wrapper has an empty signature.

* Implement `createAttestationWrapper`.

* `processAttestations`: Return processed attester slashings.

* Test `processAttestations` instead of `processQueuedAttestations`.

By testing `processAttestations` instead of `processQueuedAttestations`, we get rid of a lot of tests fixtures, including the 200 ms sleep.

The whole testing duration is shorter.

* `Test_processAttestations`: Allow multiple steps.

* `Test_processAttestations`: Add double steps tests.

Some new failing tests are commented with a corresponding github issue.

* `NextChunkStartEpoch`: Fix function comment.

Co-authored-by: Preston Van Loon <pvanloon@offchainlabs.com>

* `chunks.go`: Avoid templating log messages.

* `checkSlashableAttestations`: Simplify duration computation.

---------

Co-authored-by: Preston Van Loon <pvanloon@offchainlabs.com>
2024-02-09 21:02:18 +00:00
james-prysm
fa1df7ee53 adding unit tests and more logs 2024-02-09 14:43:16 -06:00
terence
5582c558c6 Remove deprecated aggregate parallel flag (#13538) 2024-02-09 20:18:36 +00:00
terence
573d9739ea Remove disable vectorized htr (#13537) 2024-02-09 18:28:13 +00:00
terence
bb18fa3f71 Remove deprecated late reorg flag (#13536) 2024-02-09 17:15:08 +00:00
Aditya Asgaonkar
6a605e6b6d Fork choice filter changes (#13464)
* implement confirmation rule prerequisite - f.c. filter changes

* update tests

* update WORKSPACE for spec v1.4.0-beta.6

* run bazel gazelle

* Fix consensus_spec sha256

* drift also forkchoice time when drifting the service on tests

* update minimal kzg_commitment_inclusion_proof_depth.size

* fix mock engine client

* remove unnecessary helper & revert test changes

* revert change of proof size in minimal preset

* fix tests

* fix loader test

---------

Co-authored-by: terence tsao <terence@prysmaticlabs.com>
Co-authored-by: Potuz <potuz@prysmaticlabs.com>
2024-02-09 17:01:44 +00:00
Nishant Das
a0787e2379 Handle Syncing Executon Client (#13597)
* fix it

* manu's review

* fix failing tests
2024-02-09 09:07:48 +00:00
Nishant Das
621bda068d Suppress Unwanted P2P Errors (#13598)
* supress unwanted errors

* gaz

* mod
2024-02-09 05:13:57 +00:00
james-prysm
48f0bef9bb Merge branch 'develop' into beacon-proposer-settings 2024-02-08 15:14:22 -06:00
Radosław Kapka
91504eb95a Improve vc logs (#13573)
* duties

* atts

* revert some changes

* revert timeTillDuty

* Manu's review

* Revert "Auxiliary commit to revert individual files from 6806ca9fbe18101f58ccb40fe191c61c183735a8"

This reverts commit 0820c870d2627950179b0edf7ce62ee4fa4a03a3.

* remove trash

* more reivew

* making Manu happy

* test fixes
2024-02-08 18:24:03 +00:00
james-prysm
3920cddb18 Merge branch 'develop' into beacon-proposer-settings 2024-02-08 10:31:33 -06:00
Sammy Rosso
5afb1255fe Add /eth/v1/beacon/deposit_snapshot endpoint (#13514)
* Add endpoint

* Uncomment in InitializeRoutes

* Add test

* Add 404

* Add more checks

* Test improvements

* Ssz

* Add ssz tags

* Add DepositSnapshot to bazel

* Fix tests

* Fix max size

* Resolve conflicts

* Revert untouched code

* Fix test + review

* Lint

* Oops

* Preston + Radek' review

* Only return 3 finalized roots

* Change to deposit contract depth

* Radek' review

* Gaz

---------

Co-authored-by: james-prysm <90280386+james-prysm@users.noreply.github.com>
2024-02-07 22:53:08 +00:00
Manu NALEPA
9d6160e112 Slasher: Remove unused RPC. (#13594) 2024-02-07 21:11:58 +00:00
james-prysm
1383546999 Beacon API: get blob fix retention cases (#13585)
* fixing the handling for certain cases

* fixing tests

* Update beacon-chain/rpc/eth/blob/handlers_test.go

Co-authored-by: Radosław Kapka <rkapka@wp.pl>

* update comment based on review

---------

Co-authored-by: Radosław Kapka <rkapka@wp.pl>
2024-02-06 22:31:17 +00:00
Justin Traglia
01116f7f82 Fix a few minor nits in protobuf definitions (#13512) 2024-02-06 21:17:32 +00:00
james-prysm
f102689c2c Merge branch 'develop' into beacon-proposer-settings 2024-02-05 10:25:03 -06:00
james-prysm
fd132103fd Merge branch 'develop' into beacon-proposer-settings 2024-02-05 09:08:44 -06:00
james-prysm
b71312f575 update the comments of auto generated proto 2024-01-26 14:49:01 -06:00
james-prysm
4540cd5cdc moving proposer settings outside of keymanager.proto 2024-01-26 14:47:12 -06:00
james-prysm
d33f1f2d98 fixing typo 2024-01-26 14:12:10 -06:00
james-prysm
3dc45c2041 adding flags to main.go 2024-01-26 14:10:47 -06:00
james-prysm
f7a04ab66d Merge branch 'develop' into beacon-proposer-settings 2024-01-26 14:06:13 -06:00
james-prysm
01eb14a0f0 poc on proposer settings for updating tracked cache 2024-01-26 13:58:14 -06:00
132 changed files with 3901 additions and 2329 deletions

View File

@@ -234,7 +234,7 @@ filegroup(
url = "https://github.com/ethereum/EIPs/archive/5480440fe51742ed23342b68cf106cefd427e39d.tar.gz",
)
consensus_spec_version = "v1.4.0-beta.5"
consensus_spec_version = "v1.4.0-beta.6"
bls_test_version = "v0.1.1"
@@ -250,7 +250,7 @@ filegroup(
visibility = ["//visibility:public"],
)
""",
sha256 = "9017ffff84d64a7c4c9e6ff9f421f9479f71d3b463b738f54e02158dbb4f50f0",
sha256 = "7dc467d7be97525c88a1d3683665c1354cc86297fd62009e7cf5000905b25652",
url = "https://github.com/ethereum/consensus-spec-tests/releases/download/%s/general.tar.gz" % consensus_spec_version,
)
@@ -266,7 +266,7 @@ filegroup(
visibility = ["//visibility:public"],
)
""",
sha256 = "f08711682553fe7c9362f1400ed8c56b2fa9576df08581fcad4c508ba8ad4788",
sha256 = "e163011254b6ce100205fb779ba660faedc9bc9f7bb4408c25746a7aa5e8d8bc",
url = "https://github.com/ethereum/consensus-spec-tests/releases/download/%s/minimal.tar.gz" % consensus_spec_version,
)
@@ -282,7 +282,7 @@ filegroup(
visibility = ["//visibility:public"],
)
""",
sha256 = "7ea3189e3879f2ac62467cbf2945c00b6c94d30cdefb2d645c630b1018c50e10",
sha256 = "b73c81b6386053a2141f6f43b457489668621c7013f740ed93edf9ac0e34f091",
url = "https://github.com/ethereum/consensus-spec-tests/releases/download/%s/mainnet.tar.gz" % consensus_spec_version,
)
@@ -297,7 +297,7 @@ filegroup(
visibility = ["//visibility:public"],
)
""",
sha256 = "4119992a2efc79e5cb2bdc07ed08c0b1fa32332cbd0d88e6467f34938df97026",
sha256 = "47726c527512d03ef3e706a8e7f8d5db6a5f2153351db0470dab780f6a87c4dd",
strip_prefix = "consensus-specs-" + consensus_spec_version[1:],
url = "https://github.com/ethereum/consensus-specs/archive/refs/tags/%s.tar.gz" % consensus_spec_version,
)

View File

@@ -1,4 +1,4 @@
load("@prysm//tools/go:def.bzl", "go_library")
load("@prysm//tools/go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
@@ -38,3 +38,13 @@ go_library(
"@com_github_pkg_errors//:go_default_library",
],
)
go_test(
name = "go_default_test",
srcs = ["conversions_test.go"],
embed = [":go_default_library"],
deps = [
"//proto/prysm/v1alpha1:go_default_library",
"//testing/require:go_default_library",
],
)

View File

@@ -1074,3 +1074,17 @@ func sszBytesToUint256String(b []byte) (string, error) {
}
return bi.String(), nil
}
func DepositSnapshotFromConsensus(ds *eth.DepositSnapshot) *DepositSnapshot {
finalized := make([]string, 0, len(ds.Finalized))
for _, f := range ds.Finalized {
finalized = append(finalized, hexutil.Encode(f))
}
return &DepositSnapshot{
Finalized: finalized,
DepositRoot: hexutil.Encode(ds.DepositRoot),
DepositCount: fmt.Sprintf("%d", ds.DepositCount),
ExecutionBlockHash: hexutil.Encode(ds.ExecutionHash),
ExecutionBlockHeight: fmt.Sprintf("%d", ds.ExecutionDepth),
}
}

View File

@@ -0,0 +1,26 @@
package structs
import (
"testing"
eth "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v4/testing/require"
)
func TestDepositSnapshotFromConsensus(t *testing.T) {
ds := &eth.DepositSnapshot{
Finalized: [][]byte{{0xde, 0xad, 0xbe, 0xef}, {0xca, 0xfe, 0xba, 0xbe}},
DepositRoot: []byte{0xab, 0xcd},
DepositCount: 12345,
ExecutionHash: []byte{0x12, 0x34},
ExecutionDepth: 67890,
}
res := DepositSnapshotFromConsensus(ds)
require.NotNil(t, res)
require.DeepEqual(t, []string{"0xdeadbeef", "0xcafebabe"}, res.Finalized)
require.Equal(t, "0xabcd", res.DepositRoot)
require.Equal(t, "12345", res.DepositCount)
require.Equal(t, "0x1234", res.ExecutionBlockHash)
require.Equal(t, "67890", res.ExecutionBlockHeight)
}

View File

@@ -184,3 +184,15 @@ type WeakSubjectivityData struct {
WsCheckpoint *Checkpoint `json:"ws_checkpoint"`
StateRoot string `json:"state_root"`
}
type GetDepositSnapshotResponse struct {
Data *DepositSnapshot `json:"data"`
}
type DepositSnapshot struct {
Finalized []string `json:"finalized"`
DepositRoot string `json:"deposit_root"`
DepositCount string `json:"deposit_count"`
ExecutionBlockHash string `json:"execution_block_hash"`
ExecutionBlockHeight string `json:"execution_block_height"`
}

View File

@@ -2046,7 +2046,9 @@ func TestFillMissingBlockPayloadId_PrepareAllPayloads(t *testing.T) {
// boost. It alters the genesisTime tracked by the store.
func driftGenesisTime(s *Service, slot, delay int64) {
offset := slot*int64(params.BeaconConfig().SecondsPerSlot) + delay
s.SetGenesisTime(time.Unix(time.Now().Unix()-offset, 0))
newTime := time.Unix(time.Now().Unix()-offset, 0)
s.SetGenesisTime(newTime)
s.cfg.ForkChoiceStore.SetGenesisTime(uint64(newTime.Unix()))
}
func TestMissingIndices(t *testing.T) {

View File

@@ -228,6 +228,20 @@ func (bs *BlobStorage) Indices(root [32]byte) ([fieldparams.MaxBlobsPerBlock]boo
return mask, nil
}
// Clear deletes all files on the filesystem.
func (bs *BlobStorage) Clear() error {
dirs, err := listDir(bs.fs, ".")
if err != nil {
return err
}
for _, dir := range dirs {
if err := bs.fs.RemoveAll(dir); err != nil {
return err
}
}
return nil
}
type blobNamer struct {
root [32]byte
index uint64

View File

@@ -88,6 +88,19 @@ func TestBlobStorage_SaveBlobData(t *testing.T) {
_, err = bs.Get(expected.BlockRoot(), expected.Index)
require.ErrorContains(t, "file does not exist", err)
})
t.Run("clear", func(t *testing.T) {
blob := testSidecars[0]
b := NewEphemeralBlobStorage(t)
require.NoError(t, b.Save(blob))
res, err := b.Get(blob.BlockRoot(), blob.Index)
require.NoError(t, err)
require.NotNil(t, res)
require.NoError(t, b.Clear())
// After clearing, the blob should not exist in the db.
_, err = b.Get(blob.BlockRoot(), blob.Index)
require.ErrorIs(t, err, os.ErrNotExist)
})
}
// pollUntil polls a condition function until it returns true or a timeout is reached.

View File

@@ -213,6 +213,9 @@ func NewKVStore(ctx context.Context, dirPath string, opts ...KVStoreOption) (*St
// ClearDB removes the previously stored database in the data directory.
func (s *Store) ClearDB() error {
if err := s.Close(); err != nil {
return fmt.Errorf("failed to close db: %w", err)
}
if _, err := os.Stat(s.databasePath); os.IsNotExist(err) {
return nil
}

View File

@@ -4,6 +4,7 @@ package slasherkv
import (
"context"
"fmt"
"os"
"path"
"time"
@@ -87,6 +88,9 @@ func NewKVStore(ctx context.Context, dirPath string) (*Store, error) {
// ClearDB removes the previously stored database in the data directory.
func (s *Store) ClearDB() error {
if err := s.Close(); err != nil {
return fmt.Errorf("failed to close db: %w", err)
}
if _, err := os.Stat(s.databasePath); os.IsNotExist(err) {
return nil
}

View File

@@ -21,9 +21,8 @@ import (
)
const (
// Signing root (32 bytes)
attestationRecordKeySize = 32 // Bytes.
signingRootSize = 32 // Bytes.
rootSize = 32 // Bytes.
)
// LastEpochWrittenForValidators given a list of validator indices returns the latest
@@ -170,15 +169,15 @@ func (s *Store) CheckAttesterDoubleVotes(
continue
}
// Retrieve the attestation record corresponding to the signing root
// Retrieve the attestation record corresponding to the data root
// from the database.
encExistingAttRecord := attRecordsBkt.Get(attRecordsKey)
if encExistingAttRecord == nil {
continue
}
existingSigningRoot := bytesutil.ToBytes32(attRecordsKey[:signingRootSize])
if existingSigningRoot == attToProcess.SigningRoot {
existingDataRoot := bytesutil.ToBytes32(attRecordsKey[:rootSize])
if existingDataRoot == attToProcess.DataRoot {
continue
}
@@ -190,10 +189,10 @@ func (s *Store) CheckAttesterDoubleVotes(
// Build the proof of double vote.
slashAtt := &slashertypes.AttesterDoubleVote{
ValidatorIndex: primitives.ValidatorIndex(valIdx),
Target: attToProcess.IndexedAttestation.Data.Target.Epoch,
PrevAttestationWrapper: existingAttRecord,
AttestationWrapper: attToProcess,
ValidatorIndex: primitives.ValidatorIndex(valIdx),
Target: attToProcess.IndexedAttestation.Data.Target.Epoch,
Wrapper_1: existingAttRecord,
Wrapper_2: attToProcess,
}
localDoubleVotes = append(localDoubleVotes, slashAtt)
@@ -281,12 +280,12 @@ func (s *Store) SaveAttestationRecordsForValidators(
return s.db.Update(func(tx *bolt.Tx) error {
attRecordsBkt := tx.Bucket(attestationRecordsBucket)
signingRootsBkt := tx.Bucket(attestationDataRootsBucket)
dataRootsBkt := tx.Bucket(attestationDataRootsBucket)
for i := len(attestations) - 1; i >= 0; i-- {
attestation := attestations[i]
if err := attRecordsBkt.Put(attestation.SigningRoot[:], encodedRecords[i]); err != nil {
if err := attRecordsBkt.Put(attestation.DataRoot[:], encodedRecords[i]); err != nil {
return err
}
@@ -294,7 +293,7 @@ func (s *Store) SaveAttestationRecordsForValidators(
encIdx := encodeValidatorIndex(primitives.ValidatorIndex(valIdx))
key := append(encodedTargetEpoch[i], encIdx...)
if err := signingRootsBkt.Put(key, attestation.SigningRoot[:]); err != nil {
if err := dataRootsBkt.Put(key, attestation.DataRoot[:]); err != nil {
return err
}
}
@@ -396,14 +395,14 @@ func (s *Store) CheckDoubleBlockProposals(
// If there is no existing proposal record (empty result), then there is no double proposal.
// We can continue to the next proposal.
if len(encExistingProposalWrapper) < signingRootSize {
if len(encExistingProposalWrapper) < rootSize {
continue
}
// Compare the proposal signing root in the DB with the incoming proposal signing root.
// If they differ, we have a double proposal.
existingSigningRoot := bytesutil.ToBytes32(encExistingProposalWrapper[:signingRootSize])
if existingSigningRoot != incomingProposal.SigningRoot {
existingRoot := bytesutil.ToBytes32(encExistingProposalWrapper[:rootSize])
if existingRoot != incomingProposal.HeaderRoot {
existingProposalWrapper, err := decodeProposalRecord(encExistingProposalWrapper)
if err != nil {
return err
@@ -610,18 +609,18 @@ func encodeAttestationRecord(att *slashertypes.IndexedAttestationWrapper) ([]byt
// Compress attestation.
compressedAtt := snappy.Encode(nil, encodedAtt)
return append(att.SigningRoot[:], compressedAtt...), nil
return append(att.DataRoot[:], compressedAtt...), nil
}
// Decode attestation record from bytes.
// The input encoded attestation record consists in the signing root concatened with the compressed attestation record.
func decodeAttestationRecord(encoded []byte) (*slashertypes.IndexedAttestationWrapper, error) {
if len(encoded) < signingRootSize {
return nil, fmt.Errorf("wrong length for encoded attestation record, want minimum %d, got %d", signingRootSize, len(encoded))
if len(encoded) < rootSize {
return nil, fmt.Errorf("wrong length for encoded attestation record, want minimum %d, got %d", rootSize, len(encoded))
}
// Decompress attestation.
decodedAttBytes, err := snappy.Decode(nil, encoded[signingRootSize:])
decodedAttBytes, err := snappy.Decode(nil, encoded[rootSize:])
if err != nil {
return nil, err
}
@@ -633,13 +632,13 @@ func decodeAttestationRecord(encoded []byte) (*slashertypes.IndexedAttestationWr
}
// Decode signing root.
signingRootBytes := encoded[:signingRootSize]
signingRoot := bytesutil.ToBytes32(signingRootBytes)
dataRootBytes := encoded[:rootSize]
dataRoot := bytesutil.ToBytes32(dataRootBytes)
// Return decoded attestation.
attestation := &slashertypes.IndexedAttestationWrapper{
IndexedAttestation: decodedAtt,
SigningRoot: signingRoot,
DataRoot: dataRoot,
}
return attestation, nil
@@ -654,18 +653,18 @@ func encodeProposalRecord(blkHdr *slashertypes.SignedBlockHeaderWrapper) ([]byte
return nil, err
}
compressedHdr := snappy.Encode(nil, encodedHdr)
return append(blkHdr.SigningRoot[:], compressedHdr...), nil
return append(blkHdr.HeaderRoot[:], compressedHdr...), nil
}
func decodeProposalRecord(encoded []byte) (*slashertypes.SignedBlockHeaderWrapper, error) {
if len(encoded) < signingRootSize {
if len(encoded) < rootSize {
return nil, fmt.Errorf(
"wrong length for encoded proposal record, want %d, got %d", signingRootSize, len(encoded),
"wrong length for encoded proposal record, want %d, got %d", rootSize, len(encoded),
)
}
signingRoot := encoded[:signingRootSize]
dataRoot := encoded[:rootSize]
decodedBlkHdr := &ethpb.SignedBeaconBlockHeader{}
decodedHdrBytes, err := snappy.Decode(nil, encoded[signingRootSize:])
decodedHdrBytes, err := snappy.Decode(nil, encoded[rootSize:])
if err != nil {
return nil, err
}
@@ -674,7 +673,7 @@ func decodeProposalRecord(encoded []byte) (*slashertypes.SignedBlockHeaderWrappe
}
return &slashertypes.SignedBlockHeaderWrapper{
SignedBeaconBlockHeader: decodedBlkHdr,
SigningRoot: bytesutil.ToBytes32(signingRoot),
HeaderRoot: bytesutil.ToBytes32(dataRoot),
}, nil
}

View File

@@ -40,7 +40,7 @@ func TestStore_AttestationRecordForValidator_SaveRetrieve(t *testing.T) {
require.NoError(t, err)
assert.DeepEqual(t, target, attRecord.IndexedAttestation.Data.Target.Epoch)
assert.DeepEqual(t, source, attRecord.IndexedAttestation.Data.Source.Epoch)
assert.DeepEqual(t, sr, attRecord.SigningRoot)
assert.DeepEqual(t, sr, attRecord.DataRoot)
}
func TestStore_LastEpochWrittenForValidators(t *testing.T) {
@@ -93,28 +93,28 @@ func TestStore_CheckAttesterDoubleVotes(t *testing.T) {
wanted := []*slashertypes.AttesterDoubleVote{
{
ValidatorIndex: 0,
Target: 3,
PrevAttestationWrapper: createAttestationWrapper(2, 3, []uint64{0, 1}, []byte{1}),
AttestationWrapper: createAttestationWrapper(2, 3, []uint64{0, 1}, []byte{2}),
ValidatorIndex: 0,
Target: 3,
Wrapper_1: createAttestationWrapper(2, 3, []uint64{0, 1}, []byte{1}),
Wrapper_2: createAttestationWrapper(2, 3, []uint64{0, 1}, []byte{2}),
},
{
ValidatorIndex: 1,
Target: 3,
PrevAttestationWrapper: createAttestationWrapper(2, 3, []uint64{0, 1}, []byte{1}),
AttestationWrapper: createAttestationWrapper(2, 3, []uint64{0, 1}, []byte{2}),
ValidatorIndex: 1,
Target: 3,
Wrapper_1: createAttestationWrapper(2, 3, []uint64{0, 1}, []byte{1}),
Wrapper_2: createAttestationWrapper(2, 3, []uint64{0, 1}, []byte{2}),
},
{
ValidatorIndex: 2,
Target: 4,
PrevAttestationWrapper: createAttestationWrapper(3, 4, []uint64{2, 3}, []byte{3}),
AttestationWrapper: createAttestationWrapper(3, 4, []uint64{2, 3}, []byte{4}),
ValidatorIndex: 2,
Target: 4,
Wrapper_1: createAttestationWrapper(3, 4, []uint64{2, 3}, []byte{3}),
Wrapper_2: createAttestationWrapper(3, 4, []uint64{2, 3}, []byte{4}),
},
{
ValidatorIndex: 3,
Target: 4,
PrevAttestationWrapper: createAttestationWrapper(3, 4, []uint64{2, 3}, []byte{3}),
AttestationWrapper: createAttestationWrapper(3, 4, []uint64{2, 3}, []byte{4}),
ValidatorIndex: 3,
Target: 4,
Wrapper_1: createAttestationWrapper(3, 4, []uint64{2, 3}, []byte{3}),
Wrapper_2: createAttestationWrapper(3, 4, []uint64{2, 3}, []byte{4}),
},
}
doubleVotes, err := beaconDB.CheckAttesterDoubleVotes(ctx, slashableAtts)
@@ -126,8 +126,8 @@ func TestStore_CheckAttesterDoubleVotes(t *testing.T) {
for i, double := range doubleVotes {
require.DeepEqual(t, wanted[i].ValidatorIndex, double.ValidatorIndex)
require.DeepEqual(t, wanted[i].Target, double.Target)
require.DeepEqual(t, wanted[i].PrevAttestationWrapper, double.PrevAttestationWrapper)
require.DeepEqual(t, wanted[i].AttestationWrapper, double.AttestationWrapper)
require.DeepEqual(t, wanted[i].Wrapper_1, double.Wrapper_1)
require.DeepEqual(t, wanted[i].Wrapper_2, double.Wrapper_2)
}
}
@@ -224,9 +224,9 @@ func TestStore_ExistingBlockProposals(t *testing.T) {
// Second time checking same proposals but all with different signing root should
// return all double proposals.
proposals[0].SigningRoot = bytesutil.ToBytes32([]byte{2})
proposals[1].SigningRoot = bytesutil.ToBytes32([]byte{2})
proposals[2].SigningRoot = bytesutil.ToBytes32([]byte{2})
proposals[0].HeaderRoot = bytesutil.ToBytes32([]byte{2})
proposals[1].HeaderRoot = bytesutil.ToBytes32([]byte{2})
proposals[2].HeaderRoot = bytesutil.ToBytes32([]byte{2})
doubleProposals, err = beaconDB.CheckDoubleBlockProposals(ctx, proposals)
require.NoError(t, err)
@@ -515,7 +515,7 @@ func createProposalWrapper(t *testing.T, slot primitives.Slot, proposerIndex pri
StateRoot: bytesutil.PadTo(signingRoot, 32),
BodyRoot: params.BeaconConfig().ZeroHash[:],
}
signRoot, err := header.HashTreeRoot()
headerRoot, err := header.HashTreeRoot()
if err != nil {
t.Fatal(err)
}
@@ -524,15 +524,16 @@ func createProposalWrapper(t *testing.T, slot primitives.Slot, proposerIndex pri
Header: header,
Signature: params.BeaconConfig().EmptySignature[:],
},
SigningRoot: signRoot,
HeaderRoot: headerRoot,
}
}
func createAttestationWrapper(source, target primitives.Epoch, indices []uint64, signingRoot []byte) *slashertypes.IndexedAttestationWrapper {
signRoot := bytesutil.ToBytes32(signingRoot)
if signingRoot == nil {
signRoot = params.BeaconConfig().ZeroHash
func createAttestationWrapper(source, target primitives.Epoch, indices []uint64, dataRootBytes []byte) *slashertypes.IndexedAttestationWrapper {
dataRoot := bytesutil.ToBytes32(dataRootBytes)
if dataRootBytes == nil {
dataRoot = params.BeaconConfig().ZeroHash
}
data := &ethpb.AttestationData{
BeaconBlockRoot: params.BeaconConfig().ZeroHash[:],
Source: &ethpb.Checkpoint{
@@ -544,13 +545,14 @@ func createAttestationWrapper(source, target primitives.Epoch, indices []uint64,
Root: params.BeaconConfig().ZeroHash[:],
},
}
return &slashertypes.IndexedAttestationWrapper{
IndexedAttestation: &ethpb.IndexedAttestation{
AttestingIndices: indices,
Data: data,
Signature: params.BeaconConfig().EmptySignature[:],
},
SigningRoot: signRoot,
DataRoot: dataRoot,
}
}

View File

@@ -493,7 +493,12 @@ func (s *Service) GetPayloadBodiesByHash(ctx context.Context, executionBlockHash
return result, nil
}
err := s.rpcClient.CallContext(ctx, &result, GetPayloadBodiesByHashV1, executionBlockHashes)
if err != nil {
return nil, handleRPCError(err)
}
if len(result) != len(executionBlockHashes) {
return nil, fmt.Errorf("mismatch of payloads retrieved from the execution client: %d vs %d", len(result), len(executionBlockHashes))
}
for i, item := range result {
if item == nil {
result[i] = &pb.ExecutionPayloadBodyV1{
@@ -502,7 +507,7 @@ func (s *Service) GetPayloadBodiesByHash(ctx context.Context, executionBlockHash
}
}
}
return result, handleRPCError(err)
return result, nil
}
// GetPayloadBodiesByRange returns the relevant payload bodies for the provided range.
@@ -635,6 +640,8 @@ func (s *Service) retrievePayloadFromExecutionHash(ctx context.Context, executio
return fullPayloadFromPayloadBody(header, bdy, version)
}
// This method assumes that the provided execution hashes are all valid and part of the
// canonical chain.
func (s *Service) retrievePayloadsFromExecutionHashes(
ctx context.Context,
executionHashes []common.Hash,

View File

@@ -912,6 +912,73 @@ func TestReconstructFullBellatrixBlockBatch(t *testing.T) {
require.NoError(t, err)
require.DeepEqual(t, payload, got.Proto())
})
t.Run("handles invalid response from EL", func(t *testing.T) {
fix := fixtures()
payload, ok := fix["ExecutionPayload"].(*pb.ExecutionPayload)
require.Equal(t, true, ok)
jsonPayload := make(map[string]interface{})
tx := gethtypes.NewTransaction(
0,
common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87"),
big.NewInt(0), 0, big.NewInt(0),
nil,
)
txs := []*gethtypes.Transaction{tx}
encodedBinaryTxs := make([][]byte, 1)
var err error
encodedBinaryTxs[0], err = txs[0].MarshalBinary()
require.NoError(t, err)
payload.Transactions = encodedBinaryTxs
jsonPayload["transactions"] = []hexutil.Bytes{encodedBinaryTxs[0]}
wrappedPayload, err := blocks.WrappedExecutionPayload(payload)
require.NoError(t, err)
header, err := blocks.PayloadToHeader(wrappedPayload)
require.NoError(t, err)
bellatrixBlock := util.NewBlindedBeaconBlockBellatrix()
wanted := util.NewBeaconBlockBellatrix()
wanted.Block.Slot = 1
// Make sure block hash is the zero hash.
bellatrixBlock.Block.Body.ExecutionPayloadHeader.BlockHash = make([]byte, 32)
bellatrixBlock.Block.Slot = 1
wrappedEmpty, err := blocks.NewSignedBeaconBlock(bellatrixBlock)
require.NoError(t, err)
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
defer func() {
require.NoError(t, r.Body.Close())
}()
respJSON := map[string]interface{}{
"jsonrpc": "2.0",
"id": 1,
"result": []map[string]interface{}{},
}
require.NoError(t, json.NewEncoder(w).Encode(respJSON))
}))
defer srv.Close()
rpcClient, err := rpc.DialHTTP(srv.URL)
require.NoError(t, err)
defer rpcClient.Close()
service := &Service{}
service.rpcClient = rpcClient
blindedBlock := util.NewBlindedBeaconBlockBellatrix()
blindedBlock.Block.Body.ExecutionPayloadHeader = header
wrapped, err := blocks.NewSignedBeaconBlock(blindedBlock)
require.NoError(t, err)
copiedWrapped, err := wrapped.Copy()
require.NoError(t, err)
_, err = service.ReconstructFullBellatrixBlockBatch(ctx, []interfaces.ReadOnlySignedBeaconBlock{wrappedEmpty, wrapped, copiedWrapped})
require.ErrorContains(t, "mismatch of payloads retrieved from the execution client", err)
})
}
func TestServer_getPowBlockHashAtTerminalTotalDifficulty(t *testing.T) {
@@ -2166,7 +2233,7 @@ func TestCapella_PayloadBodiesByHash(t *testing.T) {
bRoot := [32]byte{}
copy(bRoot[:], "hash")
results, err := service.GetPayloadBodiesByHash(ctx, []common.Hash{bRoot})
results, err := service.GetPayloadBodiesByHash(ctx, []common.Hash{bRoot, bRoot})
require.NoError(t, err)
require.Equal(t, 2, len(results))

View File

@@ -77,5 +77,6 @@ go_test(
"//testing/assert:go_default_library",
"//testing/require:go_default_library",
"//testing/util:go_default_library",
"//time/slots:go_default_library",
],
)

View File

@@ -93,13 +93,13 @@ func (n *Node) updateBestDescendant(ctx context.Context, justifiedEpoch, finaliz
// Any node with different finalized or justified epoch than
// the ones in fork choice store should not be viable to head.
func (n *Node) viableForHead(justifiedEpoch, currentEpoch primitives.Epoch) bool {
justified := justifiedEpoch == n.justifiedEpoch || justifiedEpoch == 0
if !justified && justifiedEpoch+1 == currentEpoch {
if n.unrealizedJustifiedEpoch+1 >= currentEpoch && n.justifiedEpoch+2 >= currentEpoch {
justified = true
}
if justifiedEpoch == 0 {
return true
}
return justified
// We use n.justifiedEpoch as the voting source because:
// 1. if this node is from current epoch, n.justifiedEpoch is the realized justification epoch.
// 2. if this node is from a previous epoch, n.justifiedEpoch has already been updated to the unrealized justification epoch.
return n.justifiedEpoch == justifiedEpoch || n.justifiedEpoch+2 >= currentEpoch
}
func (n *Node) leadsToViableHead(justifiedEpoch, currentEpoch primitives.Epoch) bool {

View File

@@ -146,7 +146,9 @@ func TestNode_ViableForHead(t *testing.T) {
{&Node{}, 1, false},
{&Node{finalizedEpoch: 1, justifiedEpoch: 1}, 1, true},
{&Node{finalizedEpoch: 1, justifiedEpoch: 1}, 2, false},
{&Node{finalizedEpoch: 3, justifiedEpoch: 4}, 4, true},
{&Node{finalizedEpoch: 1, justifiedEpoch: 2}, 3, false},
{&Node{finalizedEpoch: 1, justifiedEpoch: 2}, 4, false},
{&Node{finalizedEpoch: 1, justifiedEpoch: 3}, 4, true},
}
for _, tc := range tests {
got := tc.n.viableForHead(tc.justifiedEpoch, 5)

View File

@@ -8,6 +8,7 @@ import (
"github.com/prysmaticlabs/prysm/v4/config/params"
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v4/testing/require"
"github.com/prysmaticlabs/prysm/v4/time/slots"
)
func TestStore_SetUnrealizedEpochs(t *testing.T) {
@@ -63,14 +64,14 @@ func TestStore_UpdateUnrealizedCheckpoints(t *testing.T) {
func TestStore_LongFork(t *testing.T) {
f := setup(1, 1)
ctx := context.Background()
state, blkRoot, err := prepareForkchoiceState(ctx, 100, [32]byte{'a'}, params.BeaconConfig().ZeroHash, [32]byte{'A'}, 1, 1)
state, blkRoot, err := prepareForkchoiceState(ctx, 75, [32]byte{'a'}, params.BeaconConfig().ZeroHash, [32]byte{'A'}, 1, 1)
require.NoError(t, err)
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
state, blkRoot, err = prepareForkchoiceState(ctx, 101, [32]byte{'b'}, [32]byte{'a'}, [32]byte{'B'}, 1, 1)
state, blkRoot, err = prepareForkchoiceState(ctx, 80, [32]byte{'b'}, [32]byte{'a'}, [32]byte{'B'}, 1, 1)
require.NoError(t, err)
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
require.NoError(t, f.store.setUnrealizedJustifiedEpoch([32]byte{'b'}, 2))
state, blkRoot, err = prepareForkchoiceState(ctx, 102, [32]byte{'c'}, [32]byte{'b'}, [32]byte{'C'}, 1, 1)
state, blkRoot, err = prepareForkchoiceState(ctx, 95, [32]byte{'c'}, [32]byte{'b'}, [32]byte{'C'}, 1, 1)
require.NoError(t, err)
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
require.NoError(t, f.store.setUnrealizedJustifiedEpoch([32]byte{'c'}, 2))
@@ -78,27 +79,28 @@ func TestStore_LongFork(t *testing.T) {
// Add an attestation to c, it is head
f.ProcessAttestation(ctx, []uint64{0}, [32]byte{'c'}, 1)
f.justifiedBalances = []uint64{100}
c := f.store.nodeByRoot[[32]byte{'c'}]
require.Equal(t, primitives.Epoch(2), slots.ToEpoch(c.slot))
driftGenesisTime(f, c.slot, 0)
headRoot, err := f.Head(ctx)
require.NoError(t, err)
require.Equal(t, [32]byte{'c'}, headRoot)
// D is head even though its weight is lower.
// c remains the head even if a block d with higher realized justification is seen
ha := [32]byte{'a'}
state, blkRoot, err = prepareForkchoiceState(ctx, 103, [32]byte{'d'}, [32]byte{'b'}, [32]byte{'D'}, 2, 1)
require.NoError(t, err)
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
require.NoError(t, f.UpdateJustifiedCheckpoint(ctx, &forkchoicetypes.Checkpoint{Epoch: 2, Root: ha}))
headRoot, err = f.Head(ctx)
require.NoError(t, err)
require.Equal(t, [32]byte{'d'}, headRoot)
require.Equal(t, uint64(0), f.store.nodeByRoot[[32]byte{'d'}].weight)
require.Equal(t, uint64(100), f.store.nodeByRoot[[32]byte{'c'}].weight)
// Update unrealized justification, c becomes head
require.NoError(t, f.updateUnrealizedCheckpoints(ctx))
d := f.store.nodeByRoot[[32]byte{'d'}]
require.Equal(t, primitives.Epoch(3), slots.ToEpoch(d.slot))
driftGenesisTime(f, d.slot, 0)
require.Equal(t, true, d.viableForHead(f.store.justifiedCheckpoint.Epoch, slots.ToEpoch(d.slot)))
headRoot, err = f.Head(ctx)
require.NoError(t, err)
require.Equal(t, [32]byte{'c'}, headRoot)
require.Equal(t, uint64(0), f.store.nodeByRoot[[32]byte{'d'}].weight)
require.Equal(t, uint64(100), f.store.nodeByRoot[[32]byte{'c'}].weight)
}
// Epoch 1 Epoch 2 Epoch 3

View File

@@ -55,6 +55,7 @@ go_library(
"//beacon-chain/verification:go_default_library",
"//cmd:go_default_library",
"//cmd/beacon-chain/flags:go_default_library",
"//config:go_default_library",
"//config/features:go_default_library",
"//config/params:go_default_library",
"//consensus-types/primitives:go_default_library",
@@ -62,6 +63,7 @@ go_library(
"//encoding/bytesutil:go_default_library",
"//monitoring/prometheus:go_default_library",
"//monitoring/tracing:go_default_library",
"//proto/prysm/config:go_default_library",
"//runtime:go_default_library",
"//runtime/debug:go_default_library",
"//runtime/prereqs:go_default_library",

View File

@@ -57,12 +57,14 @@ import (
"github.com/prysmaticlabs/prysm/v4/beacon-chain/verification"
"github.com/prysmaticlabs/prysm/v4/cmd"
"github.com/prysmaticlabs/prysm/v4/cmd/beacon-chain/flags"
"github.com/prysmaticlabs/prysm/v4/config"
"github.com/prysmaticlabs/prysm/v4/config/features"
"github.com/prysmaticlabs/prysm/v4/config/params"
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v4/container/slice"
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
"github.com/prysmaticlabs/prysm/v4/monitoring/prometheus"
proposersettings "github.com/prysmaticlabs/prysm/v4/proto/prysm/config"
"github.com/prysmaticlabs/prysm/v4/runtime"
"github.com/prysmaticlabs/prysm/v4/runtime/debug"
"github.com/prysmaticlabs/prysm/v4/runtime/prereqs"
@@ -277,7 +279,7 @@ func New(cliCtx *cli.Context, cancel context.CancelFunc, opts ...Option) (*Beaco
}
log.Debugln("Registering Sync Service")
if err := beacon.registerSyncService(beacon.initialSyncComplete); err != nil {
if err := beacon.registerSyncService(beacon.initialSyncComplete, bfs); err != nil {
return nil, err
}
@@ -427,13 +429,12 @@ func (b *BeaconNode) startDB(cliCtx *cli.Context, depositAddress string) error {
}
if clearDBConfirmed || forceClearDB {
log.Warning("Removing database")
if err := d.Close(); err != nil {
return errors.Wrap(err, "could not close db prior to clearing")
}
if err := d.ClearDB(); err != nil {
return errors.Wrap(err, "could not clear database")
}
if err := b.BlobStorage.Clear(); err != nil {
return errors.Wrap(err, "could not clear blob storage")
}
d, err = kv.NewKVStore(b.ctx, dbPath)
if err != nil {
return errors.Wrap(err, "could not create new database")
@@ -531,12 +532,12 @@ func (b *BeaconNode) startSlasherDB(cliCtx *cli.Context) error {
}
if clearDBConfirmed || forceClearDB {
log.Warning("Removing database")
if err := d.Close(); err != nil {
return errors.Wrap(err, "could not close db prior to clearing")
}
if err := d.ClearDB(); err != nil {
return errors.Wrap(err, "could not clear database")
}
if err := b.BlobStorage.Clear(); err != nil {
return errors.Wrap(err, "could not clear blob storage")
}
d, err = slasherkv.NewKVStore(b.ctx, dbPath)
if err != nil {
return errors.Wrap(err, "could not create new database")
@@ -719,7 +720,7 @@ func (b *BeaconNode) registerPOWChainService() error {
return b.services.RegisterService(web3Service)
}
func (b *BeaconNode) registerSyncService(initialSyncComplete chan struct{}) error {
func (b *BeaconNode) registerSyncService(initialSyncComplete chan struct{}, bFillStore *backfill.Store) error {
var web3Service *execution.Service
if err := b.services.FetchService(&web3Service); err != nil {
return err
@@ -758,6 +759,7 @@ func (b *BeaconNode) registerSyncService(initialSyncComplete chan struct{}) erro
regularsync.WithStateNotifier(b),
regularsync.WithBlobStorage(b.BlobStorage),
regularsync.WithVerifierWaiter(b.verifyInitWaiter),
regularsync.WithAvailableBlocker(bFillStore),
)
return b.services.RegisterService(rs)
}
@@ -816,6 +818,21 @@ func (b *BeaconNode) registerSlasherService() error {
return b.services.RegisterService(slasherSrv)
}
func proposerSettings(cliCtx *cli.Context) (*proposersettings.ProposerSettingsPayload, error) {
var fileConfig *proposersettings.ProposerSettingsPayload
if cliCtx.IsSet(flags.ProposerSettingsFlag.Name) {
if err := config.UnmarshalFromFile(cliCtx.Context, cliCtx.String(flags.ProposerSettingsFlag.Name), &fileConfig); err != nil {
return nil, err
}
}
if cliCtx.IsSet(flags.ProposerSettingsURLFlag.Name) {
if err := config.UnmarshalFromURL(cliCtx.Context, cliCtx.String(flags.ProposerSettingsURLFlag.Name), &fileConfig); err != nil {
return nil, err
}
}
return fileConfig, nil
}
func (b *BeaconNode) registerRPCService(router *mux.Router) error {
var chainService *blockchain.Service
if err := b.services.FetchService(&chainService); err != nil {
@@ -865,6 +882,11 @@ func (b *BeaconNode) registerRPCService(router *mux.Router) error {
maxMsgSize := b.cliCtx.Int(cmd.GrpcMaxCallRecvMsgSizeFlag.Name)
enableDebugRPCEndpoints := b.cliCtx.Bool(flags.EnableDebugRPCEndpoints.Name)
psettings, err := proposerSettings(b.cliCtx)
if err != nil {
return err
}
p2pService := b.fetchP2P()
rpcService := rpc.NewService(b.ctx, &rpc.Config{
ExecutionEngineCaller: web3Service,
@@ -896,7 +918,6 @@ func (b *BeaconNode) registerRPCService(router *mux.Router) error {
ExitPool: b.exitPool,
SlashingsPool: b.slashingsPool,
BLSChangesPool: b.blsToExecPool,
SlashingChecker: slasherService,
SyncCommitteeObjectPool: b.syncCommitteePool,
ExecutionChainService: web3Service,
ExecutionChainInfoFetcher: web3Service,
@@ -917,8 +938,8 @@ func (b *BeaconNode) registerRPCService(router *mux.Router) error {
BlobStorage: b.BlobStorage,
TrackedValidatorsCache: b.trackedValidatorsCache,
PayloadIDCache: b.payloadIDCache,
ProposerSettings: psettings,
})
return b.services.RegisterService(rpcService)
}
@@ -1047,7 +1068,7 @@ func (b *BeaconNode) registerBuilderService(cliCtx *cli.Context) error {
if err := b.services.FetchService(&chainService); err != nil {
return err
}
// update here based on proposer settings
opts := append(b.serviceFlagOpts.builderOpts,
builder.WithHeadFetcher(chainService),
builder.WithDatabase(b.db))

View File

@@ -14,4 +14,5 @@ var (
ErrInvalidRequest = errors.New("invalid range, step or count")
ErrBlobLTMinRequest = errors.New("blob slot < minimum_request_epoch")
ErrMaxBlobReqExceeded = errors.New("requested more than MAX_REQUEST_BLOB_SIDECARS")
ErrResourceUnavailable = errors.New("resource requested unavailable")
)

View File

@@ -44,15 +44,21 @@ go_library(
"//beacon-chain/rpc/prysm/v1alpha1/node:go_default_library",
"//beacon-chain/rpc/prysm/v1alpha1/validator:go_default_library",
"//beacon-chain/rpc/prysm/validator:go_default_library",
"//beacon-chain/slasher:go_default_library",
"//beacon-chain/startup:go_default_library",
"//beacon-chain/state/stategen:go_default_library",
"//beacon-chain/sync:go_default_library",
"//config/features:go_default_library",
"//config/fieldparams:go_default_library",
"//config/params:go_default_library",
"//config/proposer:go_default_library",
"//consensus-types/primitives:go_default_library",
"//encoding/bytesutil:go_default_library",
"//io/logs:go_default_library",
"//monitoring/tracing:go_default_library",
"//proto/prysm/config:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"@com_github_ethereum_go_ethereum//common:go_default_library",
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
"@com_github_gorilla_mux//:go_default_library",
"@com_github_grpc_ecosystem_go_grpc_middleware//:go_default_library",
"@com_github_grpc_ecosystem_go_grpc_middleware//recovery:go_default_library",

View File

@@ -17,6 +17,7 @@ go_library(
"//api/server:go_default_library",
"//api/server/structs:go_default_library",
"//beacon-chain/blockchain:go_default_library",
"//beacon-chain/cache/depositsnapshot:go_default_library",
"//beacon-chain/core/altair:go_default_library",
"//beacon-chain/core/blocks:go_default_library",
"//beacon-chain/core/feed:go_default_library",
@@ -77,6 +78,7 @@ go_test(
"//api/server:go_default_library",
"//api/server/structs:go_default_library",
"//beacon-chain/blockchain/testing:go_default_library",
"//beacon-chain/cache/depositsnapshot:go_default_library",
"//beacon-chain/core/signing:go_default_library",
"//beacon-chain/core/time:go_default_library",
"//beacon-chain/core/transition:go_default_library",

View File

@@ -15,6 +15,7 @@ import (
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/v4/api"
"github.com/prysmaticlabs/prysm/v4/api/server/structs"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/cache/depositsnapshot"
corehelpers "github.com/prysmaticlabs/prysm/v4/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/core/transition"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/db/filters"
@@ -2071,3 +2072,48 @@ func (s *Server) GetGenesis(w http.ResponseWriter, r *http.Request) {
}
httputil.WriteJson(w, resp)
}
// GetDepositSnapshot retrieves the EIP-4881 Deposit Tree Snapshot. Either a JSON or,
// if the Accept header was added, bytes serialized by SSZ will be returned.
func (s *Server) GetDepositSnapshot(w http.ResponseWriter, r *http.Request) {
ctx, span := trace.StartSpan(r.Context(), "beacon.GetDepositSnapshot")
defer span.End()
if s.BeaconDB == nil {
httputil.HandleError(w, "Could not retrieve beaconDB", http.StatusInternalServerError)
return
}
eth1data, err := s.BeaconDB.ExecutionChainData(ctx)
if err != nil {
httputil.HandleError(w, "Could not retrieve execution chain data: "+err.Error(), http.StatusInternalServerError)
return
}
if eth1data == nil {
httputil.HandleError(w, "Could not retrieve execution chain data: empty Eth1Data", http.StatusInternalServerError)
return
}
snapshot := eth1data.DepositSnapshot
if snapshot == nil || len(snapshot.Finalized) == 0 {
httputil.HandleError(w, "No Finalized Snapshot Available", http.StatusNotFound)
return
}
if len(snapshot.Finalized) > depositsnapshot.DepositContractDepth {
httputil.HandleError(w, "Retrieved invalid deposit snapshot", http.StatusInternalServerError)
return
}
if httputil.RespondWithSsz(r) {
sszData, err := snapshot.MarshalSSZ()
if err != nil {
httputil.HandleError(w, "Could not marshal deposit snapshot into SSZ: "+err.Error(), http.StatusInternalServerError)
return
}
httputil.WriteSsz(w, sszData, "deposit_snapshot.ssz")
return
}
httputil.WriteJson(
w,
&structs.GetDepositSnapshotResponse{
Data: structs.DepositSnapshotFromConsensus(snapshot),
},
)
}

View File

@@ -20,6 +20,7 @@ import (
"github.com/prysmaticlabs/prysm/v4/api"
"github.com/prysmaticlabs/prysm/v4/api/server/structs"
chainMock "github.com/prysmaticlabs/prysm/v4/beacon-chain/blockchain/testing"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/cache/depositsnapshot"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/core/transition"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/db"
dbTest "github.com/prysmaticlabs/prysm/v4/beacon-chain/db/testing"
@@ -3617,3 +3618,64 @@ func TestGetGenesis(t *testing.T) {
assert.StringContains(t, "Chain genesis info is not yet known", e.Message)
})
}
func TestGetDepositSnapshot(t *testing.T) {
beaconDB := dbTest.SetupDB(t)
mockTrie := depositsnapshot.NewDepositTree()
deposits := [][32]byte{
bytesutil.ToBytes32([]byte{1}),
bytesutil.ToBytes32([]byte{2}),
bytesutil.ToBytes32([]byte{3}),
}
finalized := 2
for _, leaf := range deposits {
err := mockTrie.Insert(leaf[:], 0)
require.NoError(t, err)
}
err := mockTrie.Finalize(1, deposits[1], 1)
require.NoError(t, err)
err = mockTrie.Finalize(2, deposits[2], 2)
require.NoError(t, err)
snapshot, err := mockTrie.GetSnapshot()
require.NoError(t, err)
root, err := snapshot.CalculateRoot()
require.NoError(t, err)
chainData := &eth.ETH1ChainData{
DepositSnapshot: snapshot.ToProto(),
}
err = beaconDB.SaveExecutionChainData(context.Background(), chainData)
require.NoError(t, err)
s := Server{
BeaconDB: beaconDB,
}
request := httptest.NewRequest(http.MethodGet, "/eth/v1/beacon/deposit_snapshot", nil)
writer := httptest.NewRecorder()
t.Run("JSON response", func(t *testing.T) {
writer.Body = &bytes.Buffer{}
s.GetDepositSnapshot(writer, request)
assert.Equal(t, http.StatusOK, writer.Code)
resp := &structs.GetDepositSnapshotResponse{}
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp))
require.NotNil(t, resp.Data)
assert.Equal(t, hexutil.Encode(root[:]), resp.Data.DepositRoot)
assert.Equal(t, hexutil.Encode(deposits[2][:]), resp.Data.ExecutionBlockHash)
assert.Equal(t, strconv.Itoa(mockTrie.NumOfItems()), resp.Data.DepositCount)
assert.Equal(t, finalized, len(resp.Data.Finalized))
})
t.Run("SSZ response", func(t *testing.T) {
writer.Body = &bytes.Buffer{}
request.Header.Set("Accept", api.OctetStreamMediaType)
s.GetDepositSnapshot(writer, request)
assert.Equal(t, http.StatusOK, writer.Code)
resp := &eth.DepositSnapshot{}
require.NoError(t, resp.UnmarshalSSZ(writer.Body.Bytes()))
assert.Equal(t, hexutil.Encode(root[:]), hexutil.Encode(resp.DepositRoot))
assert.Equal(t, hexutil.Encode(deposits[2][:]), hexutil.Encode(resp.ExecutionHash))
assert.Equal(t, uint64(mockTrie.NumOfItems()), resp.DepositCount)
assert.Equal(t, finalized, len(resp.Finalized))
})
}

View File

@@ -30,6 +30,7 @@ go_test(
"//beacon-chain/db/filesystem:go_default_library",
"//beacon-chain/db/testing:go_default_library",
"//beacon-chain/rpc/lookup:go_default_library",
"//beacon-chain/rpc/testutil:go_default_library",
"//beacon-chain/verification:go_default_library",
"//config/params:go_default_library",
"//network/httputil:go_default_library",

View File

@@ -9,6 +9,7 @@ import (
"net/url"
"strings"
"testing"
"time"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/prysmaticlabs/prysm/v4/api/server/structs"
@@ -16,6 +17,7 @@ import (
"github.com/prysmaticlabs/prysm/v4/beacon-chain/db/filesystem"
testDB "github.com/prysmaticlabs/prysm/v4/beacon-chain/db/testing"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/lookup"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/testutil"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/verification"
"github.com/prysmaticlabs/prysm/v4/config/params"
"github.com/prysmaticlabs/prysm/v4/network/httputil"
@@ -71,8 +73,11 @@ func TestBlobs(t *testing.T) {
writer.Body = &bytes.Buffer{}
blocker := &lookup.BeaconDbBlocker{
ChainInfoFetcher: &mockChain.ChainService{Root: blockRoot[:]},
BeaconDB: db,
BlobStorage: bs,
GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{
Genesis: time.Now(),
},
BeaconDB: db,
BlobStorage: bs,
}
s := &Server{
Blocker: blocker,
@@ -116,8 +121,11 @@ func TestBlobs(t *testing.T) {
writer.Body = &bytes.Buffer{}
blocker := &lookup.BeaconDbBlocker{
ChainInfoFetcher: &mockChain.ChainService{FinalizedCheckPoint: &eth.Checkpoint{Root: blockRoot[:]}},
BeaconDB: db,
BlobStorage: bs,
GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{
Genesis: time.Now(),
},
BeaconDB: db,
BlobStorage: bs,
}
s := &Server{
Blocker: blocker,
@@ -137,8 +145,11 @@ func TestBlobs(t *testing.T) {
writer.Body = &bytes.Buffer{}
blocker := &lookup.BeaconDbBlocker{
ChainInfoFetcher: &mockChain.ChainService{CurrentJustifiedCheckPoint: &eth.Checkpoint{Root: blockRoot[:]}},
BeaconDB: db,
BlobStorage: bs,
GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{
Genesis: time.Now(),
},
BeaconDB: db,
BlobStorage: bs,
}
s := &Server{
Blocker: blocker,
@@ -157,7 +168,10 @@ func TestBlobs(t *testing.T) {
writer := httptest.NewRecorder()
writer.Body = &bytes.Buffer{}
blocker := &lookup.BeaconDbBlocker{
BeaconDB: db,
BeaconDB: db,
GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{
Genesis: time.Now(),
},
BlobStorage: bs,
}
s := &Server{
@@ -177,7 +191,10 @@ func TestBlobs(t *testing.T) {
writer := httptest.NewRecorder()
writer.Body = &bytes.Buffer{}
blocker := &lookup.BeaconDbBlocker{
BeaconDB: db,
BeaconDB: db,
GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{
Genesis: time.Now(),
},
BlobStorage: bs,
}
s := &Server{
@@ -198,8 +215,11 @@ func TestBlobs(t *testing.T) {
writer.Body = &bytes.Buffer{}
blocker := &lookup.BeaconDbBlocker{
ChainInfoFetcher: &mockChain.ChainService{FinalizedCheckPoint: &eth.Checkpoint{Root: blockRoot[:]}},
BeaconDB: db,
BlobStorage: bs,
GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{
Genesis: time.Now(),
},
BeaconDB: db,
BlobStorage: bs,
}
s := &Server{
Blocker: blocker,
@@ -225,8 +245,11 @@ func TestBlobs(t *testing.T) {
writer.Body = &bytes.Buffer{}
blocker := &lookup.BeaconDbBlocker{
ChainInfoFetcher: &mockChain.ChainService{FinalizedCheckPoint: &eth.Checkpoint{Root: blockRoot[:]}},
BeaconDB: db,
BlobStorage: filesystem.NewEphemeralBlobStorage(t), // new ephemeral storage
GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{
Genesis: time.Now(),
},
BeaconDB: db,
BlobStorage: filesystem.NewEphemeralBlobStorage(t), // new ephemeral storage
}
s := &Server{
Blocker: blocker,
@@ -238,6 +261,59 @@ func TestBlobs(t *testing.T) {
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp))
require.Equal(t, len(resp.Data), 0)
})
t.Run("outside retention period returns 200 w/ empty list ", func(t *testing.T) {
u := "http://foo.example/123"
request := httptest.NewRequest("GET", u, nil)
writer := httptest.NewRecorder()
writer.Body = &bytes.Buffer{}
moc := &mockChain.ChainService{FinalizedCheckPoint: &eth.Checkpoint{Root: blockRoot[:]}}
blocker := &lookup.BeaconDbBlocker{
ChainInfoFetcher: moc,
GenesisTimeFetcher: moc, // genesis time is set to 0 here, so it results in current epoch being extremely large
BeaconDB: db,
BlobStorage: bs,
}
s := &Server{
Blocker: blocker,
}
s.Blobs(writer, request)
assert.Equal(t, http.StatusOK, writer.Code)
resp := &structs.SidecarsResponse{}
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp))
require.Equal(t, 0, len(resp.Data))
})
t.Run("block without commitments returns 200 w/empty list ", func(t *testing.T) {
denebBlock, _ := util.GenerateTestDenebBlockWithSidecar(t, [32]byte{}, 333, 0)
commitments, err := denebBlock.Block().Body().BlobKzgCommitments()
require.NoError(t, err)
require.Equal(t, len(commitments), 0)
require.NoError(t, db.SaveBlock(context.Background(), denebBlock))
u := "http://foo.example/333"
request := httptest.NewRequest("GET", u, nil)
writer := httptest.NewRecorder()
writer.Body = &bytes.Buffer{}
blocker := &lookup.BeaconDbBlocker{
ChainInfoFetcher: &mockChain.ChainService{FinalizedCheckPoint: &eth.Checkpoint{Root: blockRoot[:]}},
GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{
Genesis: time.Now(),
},
BeaconDB: db,
BlobStorage: bs,
}
s := &Server{
Blocker: blocker,
}
s.Blobs(writer, request)
assert.Equal(t, http.StatusOK, writer.Code)
resp := &structs.SidecarsResponse{}
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp))
require.Equal(t, 0, len(resp.Data))
})
t.Run("slot before Deneb fork", func(t *testing.T) {
u := "http://foo.example/31"
request := httptest.NewRequest("GET", u, nil)
@@ -282,8 +358,11 @@ func TestBlobs(t *testing.T) {
writer.Body = &bytes.Buffer{}
blocker := &lookup.BeaconDbBlocker{
ChainInfoFetcher: &mockChain.ChainService{FinalizedCheckPoint: &eth.Checkpoint{Root: blockRoot[:]}},
BeaconDB: db,
BlobStorage: bs,
GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{
Genesis: time.Now(),
},
BeaconDB: db,
BlobStorage: bs,
}
s := &Server{
Blocker: blocker,

View File

@@ -47,9 +47,10 @@ type Blocker interface {
// BeaconDbBlocker is an implementation of Blocker. It retrieves blocks from the beacon chain database.
type BeaconDbBlocker struct {
BeaconDB db.ReadOnlyDatabase
ChainInfoFetcher blockchain.ChainInfoFetcher
BlobStorage *filesystem.BlobStorage
BeaconDB db.ReadOnlyDatabase
ChainInfoFetcher blockchain.ChainInfoFetcher
GenesisTimeFetcher blockchain.TimeFetcher
BlobStorage *filesystem.BlobStorage
}
// Block returns the beacon block for a given identifier. The identifier can be one of:
@@ -139,6 +140,13 @@ func (p *BeaconDbBlocker) Block(ctx context.Context, id []byte) (interfaces.Read
// - <slot>
// - <hex encoded block root with '0x' prefix>
// - <block root>
//
// cases:
// - no block, 404
// - block exists, no commitment, 200 w/ empty list
// - block exists, has commitments, inside retention period (greater of protocol- or user-specified) serve then w/ 200 unless we hit an error reading them.
// we are technically not supposed to import a block to forkchoice unless we have the blobs, so the nuance here is if we can't find the file and we are inside the protocol-defined retention period, then it's actually a 500.
// - block exists, has commitments, outside retention period (greater of protocol- or user-specified) - ie just like block exists, no commitment
func (p *BeaconDbBlocker) Blobs(ctx context.Context, id string, indices []uint64) ([]*blocks.VerifiedROBlob, *core.RpcError) {
var root []byte
switch id {
@@ -207,7 +215,25 @@ func (p *BeaconDbBlocker) Blobs(ctx context.Context, id string, indices []uint64
}
}
}
if !p.BeaconDB.HasBlock(ctx, bytesutil.ToBytes32(root)) {
return nil, &core.RpcError{Err: errors.New("block not found"), Reason: core.NotFound}
}
b, err := p.BeaconDB.Block(ctx, bytesutil.ToBytes32(root))
if err != nil {
return nil, &core.RpcError{Err: errors.Wrap(err, "failed to retrieve block from db"), Reason: core.Internal}
}
// if block is not in the retention window return 200 w/ empty list
if !params.WithinDAPeriod(slots.ToEpoch(b.Block().Slot()), slots.ToEpoch(p.GenesisTimeFetcher.CurrentSlot())) {
return make([]*blocks.VerifiedROBlob, 0), nil
}
commitments, err := b.Block().Body().BlobKzgCommitments()
if err != nil {
return nil, &core.RpcError{Err: errors.Wrap(err, "failed to retrieve kzg commitments from block"), Reason: core.Internal}
}
// if there are no commitments return 200 w/ empty list
if len(commitments) == 0 {
return make([]*blocks.VerifiedROBlob, 0), nil
}
if len(indices) == 0 {
m, err := p.BlobStorage.Indices(bytesutil.ToBytes32(root))
if err != nil {

View File

@@ -6,6 +6,7 @@ import (
"net/http"
"reflect"
"testing"
"time"
"github.com/ethereum/go-ethereum/common/hexutil"
mockChain "github.com/prysmaticlabs/prysm/v4/beacon-chain/blockchain/testing"
@@ -180,8 +181,11 @@ func TestGetBlob(t *testing.T) {
t.Run("head", func(t *testing.T) {
blocker := &BeaconDbBlocker{
ChainInfoFetcher: &mockChain.ChainService{Root: blockRoot[:]},
BeaconDB: db,
BlobStorage: bs,
GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{
Genesis: time.Now(),
},
BeaconDB: db,
BlobStorage: bs,
}
verifiedBlobs, rpcErr := blocker.Blobs(ctx, "head", nil)
assert.Equal(t, rpcErr == nil, true)
@@ -214,8 +218,11 @@ func TestGetBlob(t *testing.T) {
t.Run("finalized", func(t *testing.T) {
blocker := &BeaconDbBlocker{
ChainInfoFetcher: &mockChain.ChainService{FinalizedCheckPoint: &ethpbalpha.Checkpoint{Root: blockRoot[:]}},
BeaconDB: db,
BlobStorage: bs,
GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{
Genesis: time.Now(),
},
BeaconDB: db,
BlobStorage: bs,
}
verifiedBlobs, rpcErr := blocker.Blobs(ctx, "finalized", nil)
@@ -225,8 +232,11 @@ func TestGetBlob(t *testing.T) {
t.Run("justified", func(t *testing.T) {
blocker := &BeaconDbBlocker{
ChainInfoFetcher: &mockChain.ChainService{CurrentJustifiedCheckPoint: &ethpbalpha.Checkpoint{Root: blockRoot[:]}},
BeaconDB: db,
BlobStorage: bs,
GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{
Genesis: time.Now(),
},
BeaconDB: db,
BlobStorage: bs,
}
verifiedBlobs, rpcErr := blocker.Blobs(ctx, "justified", nil)
@@ -235,6 +245,9 @@ func TestGetBlob(t *testing.T) {
})
t.Run("root", func(t *testing.T) {
blocker := &BeaconDbBlocker{
GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{
Genesis: time.Now(),
},
BeaconDB: db,
BlobStorage: bs,
}
@@ -244,6 +257,9 @@ func TestGetBlob(t *testing.T) {
})
t.Run("slot", func(t *testing.T) {
blocker := &BeaconDbBlocker{
GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{
Genesis: time.Now(),
},
BeaconDB: db,
BlobStorage: bs,
}
@@ -254,8 +270,11 @@ func TestGetBlob(t *testing.T) {
t.Run("one blob only", func(t *testing.T) {
blocker := &BeaconDbBlocker{
ChainInfoFetcher: &mockChain.ChainService{FinalizedCheckPoint: &ethpbalpha.Checkpoint{Root: blockRoot[:]}},
BeaconDB: db,
BlobStorage: bs,
GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{
Genesis: time.Now(),
},
BeaconDB: db,
BlobStorage: bs,
}
verifiedBlobs, rpcErr := blocker.Blobs(ctx, "123", []uint64{2})
assert.Equal(t, rpcErr == nil, true)
@@ -270,8 +289,11 @@ func TestGetBlob(t *testing.T) {
t.Run("no blobs returns an empty array", func(t *testing.T) {
blocker := &BeaconDbBlocker{
ChainInfoFetcher: &mockChain.ChainService{FinalizedCheckPoint: &ethpbalpha.Checkpoint{Root: blockRoot[:]}},
BeaconDB: db,
BlobStorage: filesystem.NewEphemeralBlobStorage(t),
GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{
Genesis: time.Now(),
},
BeaconDB: db,
BlobStorage: filesystem.NewEphemeralBlobStorage(t),
}
verifiedBlobs, rpcErr := blocker.Blobs(ctx, "123", nil)
assert.Equal(t, rpcErr == nil, true)

View File

@@ -18,6 +18,7 @@ import (
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
"github.com/prysmaticlabs/prysm/v4/encoding/ssz"
"github.com/prysmaticlabs/prysm/v4/math"
"github.com/prysmaticlabs/prysm/v4/monitoring/tracing"
"github.com/prysmaticlabs/prysm/v4/network/forks"
"github.com/prysmaticlabs/prysm/v4/runtime/version"
@@ -231,7 +232,7 @@ func (vs *Server) getPayloadHeaderFromBuilder(ctx context.Context, slot primitiv
}
l := log.WithFields(logrus.Fields{
"value": v.String(),
"gweiValue": math.WeiToGwei(v),
"builderPubKey": fmt.Sprintf("%#x", bid.Pubkey()),
"blockHash": fmt.Sprintf("%#x", header.BlockHash()),
"slot": slot,

View File

@@ -9,6 +9,8 @@ import (
"net/http"
"sync"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/gorilla/mux"
middleware "github.com/grpc-ecosystem/go-grpc-middleware"
recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery"
@@ -21,6 +23,11 @@ import (
beaconprysm "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/prysm/beacon"
nodeprysm "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/prysm/node"
validatorprysm "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/prysm/validator"
fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams"
"github.com/prysmaticlabs/prysm/v4/config/proposer"
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
proposersettings "github.com/prysmaticlabs/prysm/v4/proto/prysm/config"
"github.com/sirupsen/logrus"
"go.opencensus.io/plugin/ocgrpc"
"google.golang.org/grpc"
@@ -57,7 +64,6 @@ import (
debugv1alpha1 "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/prysm/v1alpha1/debug"
nodev1alpha1 "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/prysm/v1alpha1/node"
validatorv1alpha1 "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/prysm/v1alpha1/validator"
slasherservice "github.com/prysmaticlabs/prysm/v4/beacon-chain/slasher"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/startup"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state/stategen"
chainSync "github.com/prysmaticlabs/prysm/v4/beacon-chain/sync"
@@ -112,7 +118,6 @@ type Config struct {
AttestationsPool attestations.Pool
ExitPool voluntaryexits.PoolManager
SlashingsPool slashings.PoolManager
SlashingChecker slasherservice.SlashingChecker
SyncCommitteeObjectPool synccommittee.Pool
BLSChangesPool blstoexec.PoolManager
SyncService chainSync.Checker
@@ -135,6 +140,7 @@ type Config struct {
BlobStorage *filesystem.BlobStorage
TrackedValidatorsCache *cache.TrackedValidatorsCache
PayloadIDCache *cache.PayloadIDCache
ProposerSettings *proposersettings.ProposerSettingsPayload
}
// NewService instantiates a new RPC service instance that will
@@ -256,6 +262,7 @@ func (s *Service) initializeBeaconServerRoutes(beaconServer *beacon.Server) {
s.cfg.Router.HandleFunc("/eth/v1/beacon/blocks/{block_id}/attestations", beaconServer.GetBlockAttestations).Methods(http.MethodGet)
s.cfg.Router.HandleFunc("/eth/v1/beacon/blinded_blocks/{block_id}", beaconServer.GetBlindedBlock).Methods(http.MethodGet)
s.cfg.Router.HandleFunc("/eth/v1/beacon/blocks/{block_id}/root", beaconServer.GetBlockRoot).Methods(http.MethodGet)
s.cfg.Router.HandleFunc("/eth/v1/beacon/deposit_snapshot", beaconServer.GetDepositSnapshot).Methods(http.MethodGet)
s.cfg.Router.HandleFunc("/eth/v1/beacon/pool/attestations", beaconServer.ListAttestations).Methods(http.MethodGet)
s.cfg.Router.HandleFunc("/eth/v1/beacon/pool/attestations", beaconServer.SubmitAttestations).Methods(http.MethodPost)
s.cfg.Router.HandleFunc("/eth/v1/beacon/pool/voluntary_exits", beaconServer.ListVoluntaryExits).Methods(http.MethodGet)
@@ -335,9 +342,10 @@ func (s *Service) Start() {
ReplayerBuilder: ch,
}
blocker := &lookup.BeaconDbBlocker{
BeaconDB: s.cfg.BeaconDB,
ChainInfoFetcher: s.cfg.ChainInfoFetcher,
BlobStorage: s.cfg.BlobStorage,
BeaconDB: s.cfg.BeaconDB,
ChainInfoFetcher: s.cfg.ChainInfoFetcher,
GenesisTimeFetcher: s.cfg.GenesisTimeFetcher,
BlobStorage: s.cfg.BlobStorage,
}
rewardFetcher := &rewards.BlockRewardService{Replayer: ch}
@@ -373,6 +381,11 @@ func (s *Service) Start() {
OptimisticModeFetcher: s.cfg.OptimisticModeFetcher,
}
// update the tracked validator cache before starting servers
if err := updateTrackValidatorCacheWithProposerSettings(s.ctx, s.cfg.SyncService, s.cfg.ChainInfoFetcher, s.cfg.ProposerSettings, s.cfg.TrackedValidatorsCache); err != nil {
log.WithError(err).Errorf("Could NOT update tracked validator cache with proposer settings")
}
validatorServer := &validatorv1alpha1.Server{
Ctx: s.ctx,
AttPool: s.cfg.AttestationsPool,
@@ -599,6 +612,67 @@ func (s *Service) Start() {
}()
}
func updateTrackValidatorCacheWithProposerSettings(ctx context.Context, syncChecker chainSync.Checker, chain blockchain.ChainInfoFetcher, settings *proposersettings.ProposerSettingsPayload, tackedValidatorCache *cache.TrackedValidatorsCache) error {
if settings == nil {
return nil
}
if !syncChecker.Synced() {
log.Warning("proposer cache is updating while the chain is not fully synced, using head state for validator information")
}
if settings.ProposerConfig != nil {
st, err := chain.HeadState(ctx)
if err != nil {
return err
}
builderSettingsProvided := false
for key, option := range settings.ProposerConfig {
decodedKey, err := hexutil.Decode(key)
if err != nil {
return errors.Wrapf(err, "could not decode public key %s", key)
}
if len(decodedKey) != fieldparams.BLSPubkeyLength {
return fmt.Errorf("%v is not a bls public key", key)
}
if err := proposer.VerifyOption(key, option); err != nil {
return err
}
validatorIndex, ok := st.ValidatorIndexByPubkey(bytesutil.ToBytes48(decodedKey))
if !ok {
continue
}
tackedValidatorCache.Set(cache.TrackedValidator{
Active: true, // TODO: either check or add the field in the request
Index: validatorIndex,
FeeRecipient: primitives.ExecutionAddress(common.HexToAddress(option.FeeRecipient).Bytes()),
})
if option.Builder != nil {
builderSettingsProvided = true
}
}
if builderSettingsProvided {
log.Warning("builder settings will be ignored. please provide proposer settings in the validator client to register validators")
}
return nil
}
if settings.DefaultConfig != nil {
if settings.DefaultConfig.FeeRecipient == "" {
return errors.New("default fee recipient cannot be empty")
}
if !common.IsHexAddress(settings.DefaultConfig.FeeRecipient) {
return errors.New("fee recipient is not a valid eth1 address")
}
if err := proposer.WarnNonChecksummedAddress(settings.DefaultConfig.FeeRecipient); err != nil {
return err
}
if settings.DefaultConfig.Builder != nil {
log.Warning("builder settings will be ignored. please provide proposer settings in the validator client to register validators")
}
log.Warning("no public keys provided, proposer cache is not updated from proposer settings file")
params.BeaconConfig().DefaultFeeRecipient = common.HexToAddress(settings.DefaultConfig.FeeRecipient)
}
return nil
}
// Stop the service.
func (s *Service) Stop() error {
s.cancel()

View File

@@ -5,11 +5,15 @@ import (
"errors"
"io"
"net/http"
"strings"
"testing"
"time"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/gorilla/mux"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/blockchain"
mock "github.com/prysmaticlabs/prysm/v4/beacon-chain/blockchain/testing"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/cache"
mockExecution "github.com/prysmaticlabs/prysm/v4/beacon-chain/execution/testing"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/beacon"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/blob"
@@ -24,9 +28,15 @@ import (
nodeprysm "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/prysm/node"
validatorprysm "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/prysm/validator"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/startup"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/sync"
mockSync "github.com/prysmaticlabs/prysm/v4/beacon-chain/sync/initial-sync/testing"
"github.com/prysmaticlabs/prysm/v4/config/params"
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
proposersettings "github.com/prysmaticlabs/prysm/v4/proto/prysm/config"
ethpbalpha "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v4/testing/assert"
"github.com/prysmaticlabs/prysm/v4/testing/require"
"github.com/prysmaticlabs/prysm/v4/testing/util"
"github.com/sirupsen/logrus"
logTest "github.com/sirupsen/logrus/hooks/test"
)
@@ -93,20 +103,20 @@ func TestServer_InitializeRoutes(t *testing.T) {
"/eth/v1/beacon/blocks/{block_id}/attestations": {http.MethodGet},
"/eth/v1/beacon/blob_sidecars/{block_id}": {http.MethodGet},
"/eth/v1/beacon/rewards/sync_committee/{block_id}": {http.MethodPost},
//"/eth/v1/beacon/deposit_snapshot": {http.MethodGet}, not implemented
"/eth/v1/beacon/rewards/blocks/{block_id}": {http.MethodGet},
"/eth/v1/beacon/rewards/attestations/{epoch}": {http.MethodPost},
"/eth/v1/beacon/blinded_blocks/{block_id}": {http.MethodGet},
"/eth/v1/beacon/light_client/bootstrap/{block_root}": {http.MethodGet},
"/eth/v1/beacon/light_client/updates": {http.MethodGet},
"/eth/v1/beacon/light_client/finality_update": {http.MethodGet},
"/eth/v1/beacon/light_client/optimistic_update": {http.MethodGet},
"/eth/v1/beacon/pool/attestations": {http.MethodGet, http.MethodPost},
"/eth/v1/beacon/pool/attester_slashings": {http.MethodGet, http.MethodPost},
"/eth/v1/beacon/pool/proposer_slashings": {http.MethodGet, http.MethodPost},
"/eth/v1/beacon/pool/sync_committees": {http.MethodPost},
"/eth/v1/beacon/pool/voluntary_exits": {http.MethodGet, http.MethodPost},
"/eth/v1/beacon/pool/bls_to_execution_changes": {http.MethodGet, http.MethodPost},
"/eth/v1/beacon/deposit_snapshot": {http.MethodGet},
"/eth/v1/beacon/rewards/blocks/{block_id}": {http.MethodGet},
"/eth/v1/beacon/rewards/attestations/{epoch}": {http.MethodPost},
"/eth/v1/beacon/blinded_blocks/{block_id}": {http.MethodGet},
"/eth/v1/beacon/light_client/bootstrap/{block_root}": {http.MethodGet},
"/eth/v1/beacon/light_client/updates": {http.MethodGet},
"/eth/v1/beacon/light_client/finality_update": {http.MethodGet},
"/eth/v1/beacon/light_client/optimistic_update": {http.MethodGet},
"/eth/v1/beacon/pool/attestations": {http.MethodGet, http.MethodPost},
"/eth/v1/beacon/pool/attester_slashings": {http.MethodGet, http.MethodPost},
"/eth/v1/beacon/pool/proposer_slashings": {http.MethodGet, http.MethodPost},
"/eth/v1/beacon/pool/sync_committees": {http.MethodPost},
"/eth/v1/beacon/pool/voluntary_exits": {http.MethodGet, http.MethodPost},
"/eth/v1/beacon/pool/bls_to_execution_changes": {http.MethodGet, http.MethodPost},
}
builderRoutes := map[string][]string{
@@ -254,3 +264,167 @@ func TestRPC_InsecureEndpoint(t *testing.T) {
require.LogsContain(t, hook, "You are using an insecure gRPC server")
assert.NoError(t, rpcService.Stop())
}
func Test_updateTrackValidatorCacheWithProposerSettings(t *testing.T) {
tests := []struct {
name string
setup func() (sync.Checker, blockchain.ChainInfoFetcher, *proposersettings.ProposerSettingsPayload)
verify func(t *testing.T, settings *proposersettings.ProposerSettingsPayload, tackedValidatorCache *cache.TrackedValidatorsCache, err error)
}{
{
name: "proposer settings empty",
setup: func() (sync.Checker, blockchain.ChainInfoFetcher, *proposersettings.ProposerSettingsPayload) {
key := "0xa99a76ed7796f7be22d5b7e85deeb7c5677e88e511e0b337618f8c4eb61349b4bf2d153f649f7b53359fe8b94a38e44c"
pubkey1decoded, err := hexutil.Decode(key)
require.NoError(t, err)
st, err := util.NewBeaconStateDeneb(util.FillRootsNaturalOptDeneb, func(state *ethpbalpha.BeaconStateDeneb) error {
state.Validators = []*ethpbalpha.Validator{{
PublicKey: pubkey1decoded,
WithdrawalCredentials: bytesutil.PadTo([]byte("withdrawalcredentials"), 32),
EffectiveBalance: 9,
Slashed: true,
ActivationEligibilityEpoch: 10,
ActivationEpoch: 11,
ExitEpoch: 12,
WithdrawableEpoch: 13,
}}
return nil
})
require.NoError(t, err)
return &mockSync.Sync{IsSynced: true},
&mock.ChainService{
State: st,
}, nil
},
verify: func(t *testing.T, settings *proposersettings.ProposerSettingsPayload, tackedValidatorCache *cache.TrackedValidatorsCache, err error) {
require.NoError(t, err)
_, ok := tackedValidatorCache.Validator(0)
require.Equal(t, ok, false)
},
},
{
name: "proposer settings filled and chain is synced",
setup: func() (sync.Checker, blockchain.ChainInfoFetcher, *proposersettings.ProposerSettingsPayload) {
key := "0xa99a76ed7796f7be22d5b7e85deeb7c5677e88e511e0b337618f8c4eb61349b4bf2d153f649f7b53359fe8b94a38e44c"
pubkey1decoded, err := hexutil.Decode(key)
require.NoError(t, err)
st, err := util.NewBeaconStateDeneb(util.FillRootsNaturalOptDeneb, func(state *ethpbalpha.BeaconStateDeneb) error {
state.Validators = []*ethpbalpha.Validator{{
PublicKey: pubkey1decoded,
WithdrawalCredentials: bytesutil.PadTo([]byte("withdrawalcredentials"), 32),
EffectiveBalance: 9,
Slashed: true,
ActivationEligibilityEpoch: 10,
ActivationEpoch: 11,
ExitEpoch: 12,
WithdrawableEpoch: 13,
}}
return nil
})
require.NoError(t, err)
return &mockSync.Sync{IsSynced: true},
&mock.ChainService{
State: st,
},
&proposersettings.ProposerSettingsPayload{
ProposerConfig: map[string]*proposersettings.ProposerOptionPayload{
key: {
FeeRecipient: "0x967646dCD8d34F4E02204faeDcbAe0cC96fB9245",
},
},
}
},
verify: func(t *testing.T, settings *proposersettings.ProposerSettingsPayload, tackedValidatorCache *cache.TrackedValidatorsCache, err error) {
require.NoError(t, err)
tr, ok := tackedValidatorCache.Validator(0)
require.Equal(t, ok, true)
require.StringContains(t, strings.ToLower(hexutil.Encode(tr.FeeRecipient[:])), strings.ToLower("0x967646dCD8d34F4E02204faeDcbAe0cC96fB9245"))
},
},
{
name: "proposer settings filled with non active or non matching key and chain is synced",
setup: func() (sync.Checker, blockchain.ChainInfoFetcher, *proposersettings.ProposerSettingsPayload) {
key := "0xa99a76ed7796f7be22d5b7e85deeb7c5677e88e511e0b337618f8c4eb61349b4bf2d153f649f7b53359fe8b94a38e44c"
key2 := "0xa99a76ed7796f7be22d5b7e85deeb7c5677e88e511e0b337618f8c4eb61349b4bf2d153f649f7b53359fe8b94a38e44b"
pubkey2decoded, err := hexutil.Decode(key2)
require.NoError(t, err)
st, err := util.NewBeaconStateDeneb(util.FillRootsNaturalOptDeneb, func(state *ethpbalpha.BeaconStateDeneb) error {
state.Validators = []*ethpbalpha.Validator{{
PublicKey: pubkey2decoded,
WithdrawalCredentials: bytesutil.PadTo([]byte("withdrawalcredentials"), 32),
EffectiveBalance: 9,
Slashed: true,
ActivationEligibilityEpoch: 10,
ActivationEpoch: 11,
ExitEpoch: 12,
WithdrawableEpoch: 13,
}}
return nil
})
require.NoError(t, err)
return &mockSync.Sync{IsSynced: true},
&mock.ChainService{
State: st,
},
&proposersettings.ProposerSettingsPayload{
ProposerConfig: map[string]*proposersettings.ProposerOptionPayload{
key: {
FeeRecipient: "0x967646dCD8d34F4E02204faeDcbAe0cC96fB9245",
},
},
}
},
verify: func(t *testing.T, settings *proposersettings.ProposerSettingsPayload, tackedValidatorCache *cache.TrackedValidatorsCache, err error) {
require.NoError(t, err)
_, ok := tackedValidatorCache.Validator(0)
require.Equal(t, ok, false)
},
},
{
name: "default proposer settings filled and chain is synced",
setup: func() (sync.Checker, blockchain.ChainInfoFetcher, *proposersettings.ProposerSettingsPayload) {
key := "0xa99a76ed7796f7be22d5b7e85deeb7c5677e88e511e0b337618f8c4eb61349b4bf2d153f649f7b53359fe8b94a38e44c"
pubkey1decoded, err := hexutil.Decode(key)
require.NoError(t, err)
st, err := util.NewBeaconStateDeneb(util.FillRootsNaturalOptDeneb, func(state *ethpbalpha.BeaconStateDeneb) error {
state.Validators = []*ethpbalpha.Validator{{
PublicKey: pubkey1decoded,
WithdrawalCredentials: bytesutil.PadTo([]byte("withdrawalcredentials"), 32),
EffectiveBalance: 9,
Slashed: true,
ActivationEligibilityEpoch: 10,
ActivationEpoch: 11,
ExitEpoch: 12,
WithdrawableEpoch: 13,
}}
return nil
})
require.NoError(t, err)
return &mockSync.Sync{IsSynced: true},
&mock.ChainService{
State: st,
},
&proposersettings.ProposerSettingsPayload{
DefaultConfig: &proposersettings.ProposerOptionPayload{
FeeRecipient: "0x967646dCD8d34F4E02204faeDcbAe0cC96fB9245",
},
}
},
verify: func(t *testing.T, settings *proposersettings.ProposerSettingsPayload, tackedValidatorCache *cache.TrackedValidatorsCache, err error) {
require.NoError(t, err)
_, ok := tackedValidatorCache.Validator(0)
require.Equal(t, ok, false)
require.Equal(t, params.BeaconConfig().DefaultFeeRecipient.String(), "0x967646dCD8d34F4E02204faeDcbAe0cC96fB9245")
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c := cache.NewTrackedValidatorsCache()
syncChecker, chain, settings := tt.setup()
err := updateTrackValidatorCacheWithProposerSettings(context.Background(), syncChecker, chain, settings, c)
tt.verify(t, settings, c, err)
})
}
}

View File

@@ -14,7 +14,6 @@ go_library(
"process_slashings.go",
"queue.go",
"receive.go",
"rpc.go",
"service.go",
],
importpath = "github.com/prysmaticlabs/prysm/v4/beacon-chain/slasher",
@@ -31,7 +30,6 @@ go_library(
"//beacon-chain/operations/slashings:go_default_library",
"//beacon-chain/slasher/types:go_default_library",
"//beacon-chain/startup:go_default_library",
"//beacon-chain/state:go_default_library",
"//beacon-chain/state/stategen:go_default_library",
"//beacon-chain/sync:go_default_library",
"//config/fieldparams:go_default_library",
@@ -47,8 +45,6 @@ go_library(
"@com_github_prysmaticlabs_fastssz//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
"@io_opencensus_go//trace:go_default_library",
"@org_golang_google_grpc//codes:go_default_library",
"@org_golang_google_grpc//status:go_default_library",
],
)
@@ -63,7 +59,6 @@ go_test(
"process_slashings_test.go",
"queue_test.go",
"receive_test.go",
"rpc_test.go",
"service_test.go",
],
embed = [":go_default_library"],
@@ -82,6 +77,7 @@ go_test(
"//config/params:go_default_library",
"//consensus-types/primitives:go_default_library",
"//crypto/bls:go_default_library",
"//crypto/bls/common:go_default_library",
"//encoding/bytesutil:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//testing/assert:go_default_library",

View File

@@ -1,6 +1,7 @@
package slasher
import (
"bytes"
"context"
"fmt"
"math"
@@ -10,16 +11,15 @@ import (
slashertypes "github.com/prysmaticlabs/prysm/v4/beacon-chain/slasher/types"
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
"github.com/sirupsen/logrus"
)
// A struct encapsulating input arguments to
// functions used for attester slashing detection and
// loading, saving, and updating min/max span chunks.
type chunkUpdateArgs struct {
kind slashertypes.ChunkKind
chunkIndex uint64
validatorChunkIndex uint64
currentEpoch primitives.Epoch
chunkIndex uint64
currentEpoch primitives.Epoch
}
// Chunker defines a struct which represents a slice containing a chunk for K different validator's
@@ -187,10 +187,10 @@ func (m *MinSpanChunksSlice) CheckSlashable(
ctx context.Context,
slasherDB db.SlasherDatabase,
validatorIdx primitives.ValidatorIndex,
attestation *slashertypes.IndexedAttestationWrapper,
incomingAttWrapper *slashertypes.IndexedAttestationWrapper,
) (*ethpb.AttesterSlashing, error) {
sourceEpoch := attestation.IndexedAttestation.Data.Source.Epoch
targetEpoch := attestation.IndexedAttestation.Data.Target.Epoch
sourceEpoch := incomingAttWrapper.IndexedAttestation.Data.Source.Epoch
targetEpoch := incomingAttWrapper.IndexedAttestation.Data.Target.Epoch
minTarget, err := chunkDataAtEpoch(m.params, m.data, validatorIdx, sourceEpoch)
if err != nil {
@@ -199,30 +199,56 @@ func (m *MinSpanChunksSlice) CheckSlashable(
)
}
if targetEpoch > minTarget {
existingAttRecord, err := slasherDB.AttestationRecordForValidator(
ctx, validatorIdx, minTarget,
)
if err != nil {
return nil, errors.Wrapf(
err, "could not get existing attestation record at target %d", minTarget,
)
if targetEpoch <= minTarget {
// The incoming attestation does not surround any existing ones.
return nil, nil
}
// The incoming attestation surrounds an existing one.
existingAttWrapper, err := slasherDB.AttestationRecordForValidator(ctx, validatorIdx, minTarget)
if err != nil {
return nil, errors.Wrapf(err, "could not get existing attestation record at target %d", minTarget)
}
if existingAttWrapper == nil {
// This case should normally not happen. If this happen, it means we previously
// recorded in our min/max DB an distance corresponding to an attestaiton, but WITHOUT
// recording the attestation itself. As a consequence, we say there is no surrounding vote,
// but we log an error.
fields := logrus.Fields{
"validatorIndex": validatorIdx,
"targetEpoch": minTarget,
}
if existingAttRecord == nil {
return nil, nil
}
log.WithFields(fields).Error("No existing attestation record found while a surrounding vote was detected.")
return nil, nil
}
if sourceEpoch < existingAttRecord.IndexedAttestation.Data.Source.Epoch {
surroundingVotesTotal.Inc()
return &ethpb.AttesterSlashing{
Attestation_1: attestation.IndexedAttestation,
Attestation_2: existingAttRecord.IndexedAttestation,
}, nil
if existingAttWrapper.IndexedAttestation.Data.Source.Epoch <= sourceEpoch {
// This case should normally not happen, since if we have targetEpoch > minTarget,
// then there is at least one attestation we surround.
// However, it can happens if we have multiple attestation with the same target
// but with a different source. In this case, we have both a double vote AND a surround vote.
// The validator will be slashed for the double vote, and the surround vote will be ignored.
return nil, nil
}
surroundingVotesTotal.Inc()
slashing := &ethpb.AttesterSlashing{
Attestation_1: existingAttWrapper.IndexedAttestation,
Attestation_2: incomingAttWrapper.IndexedAttestation,
}
// Ensure the attestation with the lower data root is the first attestation.
if bytes.Compare(existingAttWrapper.DataRoot[:], incomingAttWrapper.DataRoot[:]) > 0 {
slashing = &ethpb.AttesterSlashing{
Attestation_1: incomingAttWrapper.IndexedAttestation,
Attestation_2: existingAttWrapper.IndexedAttestation,
}
}
return nil, nil
return slashing, nil
}
// CheckSlashable takes in a validator index and an incoming attestation
@@ -240,10 +266,10 @@ func (m *MaxSpanChunksSlice) CheckSlashable(
ctx context.Context,
slasherDB db.SlasherDatabase,
validatorIdx primitives.ValidatorIndex,
attestation *slashertypes.IndexedAttestationWrapper,
incomingAttWrapper *slashertypes.IndexedAttestationWrapper,
) (*ethpb.AttesterSlashing, error) {
sourceEpoch := attestation.IndexedAttestation.Data.Source.Epoch
targetEpoch := attestation.IndexedAttestation.Data.Target.Epoch
sourceEpoch := incomingAttWrapper.IndexedAttestation.Data.Source.Epoch
targetEpoch := incomingAttWrapper.IndexedAttestation.Data.Target.Epoch
maxTarget, err := chunkDataAtEpoch(m.params, m.data, validatorIdx, sourceEpoch)
if err != nil {
@@ -252,29 +278,56 @@ func (m *MaxSpanChunksSlice) CheckSlashable(
)
}
if targetEpoch < maxTarget {
existingAttRecord, err := slasherDB.AttestationRecordForValidator(
ctx, validatorIdx, maxTarget,
)
if err != nil {
return nil, errors.Wrapf(
err, "could not get existing attestation record at target %d", maxTarget,
)
if targetEpoch >= maxTarget {
// The incoming attestation is not surrounded by any existing ones.
return nil, nil
}
// The incoming attestation is surrounded by an existing one.
existingAttWrapper, err := slasherDB.AttestationRecordForValidator(ctx, validatorIdx, maxTarget)
if err != nil {
return nil, errors.Wrapf(err, "could not get existing attestation record at target %d", maxTarget)
}
if existingAttWrapper == nil {
// This case should normally not happen. If this happen, it means we previously
// recorded in our min/max DB an distance corresponding to an attestaiton, but WITHOUT
// recording the attestation itself. As a consequence, we say there is no surrounded vote,
// but we log an error.
fields := logrus.Fields{
"validatorIndex": validatorIdx,
"targetEpoch": maxTarget,
}
if existingAttRecord == nil {
return nil, nil
}
log.WithFields(fields).Error("No existing attestation record found while a surrounded vote was detected.")
return nil, nil
}
if existingAttRecord.IndexedAttestation.Data.Source.Epoch < sourceEpoch {
surroundedVotesTotal.Inc()
return &ethpb.AttesterSlashing{
Attestation_1: existingAttRecord.IndexedAttestation,
Attestation_2: attestation.IndexedAttestation,
}, nil
if existingAttWrapper.IndexedAttestation.Data.Source.Epoch >= sourceEpoch {
// This case should normally not happen, since if we have targetEpoch < maxTarget,
// then there is at least one attestation that surrounds us.
// However, it can happens if we have multiple attestation with the same target
// but with a different source. In this case, we have both a double vote AND a surround vote.
// The validator will be slashed for the double vote, and the surround vote will be ignored.
return nil, nil
}
surroundedVotesTotal.Inc()
slashing := &ethpb.AttesterSlashing{
Attestation_1: existingAttWrapper.IndexedAttestation,
Attestation_2: incomingAttWrapper.IndexedAttestation,
}
// Ensure the attestation with the lower data root is the first attestation.
if bytes.Compare(existingAttWrapper.DataRoot[:], incomingAttWrapper.DataRoot[:]) > 0 {
slashing = &ethpb.AttesterSlashing{
Attestation_1: incomingAttWrapper.IndexedAttestation,
Attestation_2: existingAttWrapper.IndexedAttestation,
}
}
return nil, nil
return slashing, nil
}
// Update a min span chunk for a validator index starting at the current epoch, e_c, then updating
@@ -492,13 +545,13 @@ func (m *MinSpanChunksSlice) NextChunkStartEpoch(startEpoch primitives.Epoch) pr
// max_spans_val_i = [[-, -, -], [-, -, -], [-, -, -]]
//
// If C = chunkSize is 3 epochs per chunk, and we input start epoch of chunk 1 which is 3. The next start
// epoch is the start epoch of chunk 2, which is epoch 4. This is computed as:
// epoch is the start epoch of chunk 2, which is epoch 6. This is computed as:
//
// first_epoch(chunkIndex(startEpoch)+1)
// first_epoch(chunkIndex(3)+1)
// first_epoch(1 + 1)
// first_epoch(2)
// 4
// 6
func (m *MaxSpanChunksSlice) NextChunkStartEpoch(startEpoch primitives.Epoch) primitives.Epoch {
return m.params.firstEpoch(m.params.chunkIndex(startEpoch) + 1)
}

View File

@@ -91,7 +91,7 @@ func TestMinSpanChunksSlice_CheckSlashable(t *testing.T) {
validatorIdx := primitives.ValidatorIndex(1)
source := primitives.Epoch(1)
target := primitives.Epoch(2)
att := createAttestationWrapper(t, source, target, nil, nil)
att := createAttestationWrapperEmptySig(t, source, target, nil, nil)
// A faulty chunk should lead to error.
chunk := &MinSpanChunksSlice{
@@ -126,7 +126,7 @@ func TestMinSpanChunksSlice_CheckSlashable(t *testing.T) {
chunk = EmptyMinSpanChunksSlice(params)
source = primitives.Epoch(1)
target = primitives.Epoch(2)
att = createAttestationWrapper(t, source, target, nil, nil)
att = createAttestationWrapperEmptySig(t, source, target, nil, nil)
chunkIdx := uint64(0)
startEpoch := target
currentEpoch := target
@@ -141,7 +141,7 @@ func TestMinSpanChunksSlice_CheckSlashable(t *testing.T) {
// because we DO NOT have an existing attestation record in our database at the min target epoch.
source = primitives.Epoch(0)
target = primitives.Epoch(3)
surroundingVote := createAttestationWrapper(t, source, target, nil, nil)
surroundingVote := createAttestationWrapperEmptySig(t, source, target, nil, nil)
slashing, err = chunk.CheckSlashable(ctx, slasherDB, validatorIdx, surroundingVote)
require.NoError(t, err)
@@ -150,7 +150,7 @@ func TestMinSpanChunksSlice_CheckSlashable(t *testing.T) {
// Next up, we save the old attestation record, then check if the
// surrounding vote is indeed slashable.
attData := att.IndexedAttestation.Data
attRecord := createAttestationWrapper(t, attData.Source.Epoch, attData.Target.Epoch, []uint64{uint64(validatorIdx)}, []byte{1})
attRecord := createAttestationWrapperEmptySig(t, attData.Source.Epoch, attData.Target.Epoch, []uint64{uint64(validatorIdx)}, []byte{1})
err = slasherDB.SaveAttestationRecordsForValidators(
ctx,
[]*slashertypes.IndexedAttestationWrapper{attRecord},
@@ -173,7 +173,7 @@ func TestMaxSpanChunksSlice_CheckSlashable(t *testing.T) {
validatorIdx := primitives.ValidatorIndex(1)
source := primitives.Epoch(1)
target := primitives.Epoch(2)
att := createAttestationWrapper(t, source, target, nil, nil)
att := createAttestationWrapperEmptySig(t, source, target, nil, nil)
// A faulty chunk should lead to error.
chunk := &MaxSpanChunksSlice{
@@ -208,7 +208,7 @@ func TestMaxSpanChunksSlice_CheckSlashable(t *testing.T) {
chunk = EmptyMaxSpanChunksSlice(params)
source = primitives.Epoch(0)
target = primitives.Epoch(3)
att = createAttestationWrapper(t, source, target, nil, nil)
att = createAttestationWrapperEmptySig(t, source, target, nil, nil)
chunkIdx := uint64(0)
startEpoch := source
currentEpoch := target
@@ -223,7 +223,7 @@ func TestMaxSpanChunksSlice_CheckSlashable(t *testing.T) {
// because we DO NOT have an existing attestation record in our database at the max target epoch.
source = primitives.Epoch(1)
target = primitives.Epoch(2)
surroundedVote := createAttestationWrapper(t, source, target, nil, nil)
surroundedVote := createAttestationWrapperEmptySig(t, source, target, nil, nil)
slashing, err = chunk.CheckSlashable(ctx, slasherDB, validatorIdx, surroundedVote)
require.NoError(t, err)
@@ -233,7 +233,7 @@ func TestMaxSpanChunksSlice_CheckSlashable(t *testing.T) {
// surroundedVote vote is indeed slashable.
attData := att.IndexedAttestation.Data
signingRoot := [32]byte{1}
attRecord := createAttestationWrapper(
attRecord := createAttestationWrapperEmptySig(
t, attData.Source.Epoch, attData.Target.Epoch, []uint64{uint64(validatorIdx)}, signingRoot[:],
)
err = slasherDB.SaveAttestationRecordsForValidators(

View File

@@ -1,12 +1,14 @@
package slasher
import (
"bytes"
"context"
"fmt"
"time"
"github.com/pkg/errors"
slashertypes "github.com/prysmaticlabs/prysm/v4/beacon-chain/slasher/types"
fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams"
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
"github.com/sirupsen/logrus"
@@ -17,61 +19,73 @@ import (
// found attester slashings to the caller.
func (s *Service) checkSlashableAttestations(
ctx context.Context, currentEpoch primitives.Epoch, atts []*slashertypes.IndexedAttestationWrapper,
) ([]*ethpb.AttesterSlashing, error) {
slashings := make([]*ethpb.AttesterSlashing, 0)
) (map[[fieldparams.RootLength]byte]*ethpb.AttesterSlashing, error) {
totalStart := time.Now()
slashings := map[[fieldparams.RootLength]byte]*ethpb.AttesterSlashing{}
// Double votes
log.Debug("Checking for double votes")
start := time.Now()
doubleVoteSlashings, err := s.checkDoubleVotes(ctx, atts)
if err != nil {
return nil, errors.Wrap(err, "could not check slashable double votes")
}
log.WithField("elapsed", time.Since(start)).Debug("Done checking double votes")
slashings = append(slashings, doubleVoteSlashings...)
for root, slashing := range doubleVoteSlashings {
slashings[root] = slashing
}
// Save the attestation records to our database.
// If multiple attestations are provided for the same validator index + target epoch combination,
// then the first (validator index + target epoch) => signing root) link is kept into the database.
if err := s.serviceCfg.Database.SaveAttestationRecordsForValidators(ctx, atts); err != nil {
return nil, errors.Wrap(err, couldNotSaveAttRecord)
}
// Surrounding / surrounded votes
groupedAtts := s.groupByValidatorChunkIndex(atts)
log.WithField("numBatches", len(groupedAtts)).Debug("Batching attestations by validator chunk index")
start = time.Now()
batchTimes := make([]time.Duration, 0, len(groupedAtts))
groupedByValidatorChunkIndexAtts := s.groupByValidatorChunkIndex(atts)
log.WithField("numBatches", len(groupedByValidatorChunkIndexAtts)).Debug("Batching attestations by validator chunk index")
groupsCount := len(groupedByValidatorChunkIndexAtts)
for validatorChunkIdx, batch := range groupedAtts {
innerStart := time.Now()
surroundStart := time.Now()
attSlashings, err := s.checkSurrounds(ctx, &chunkUpdateArgs{
validatorChunkIndex: validatorChunkIdx,
currentEpoch: currentEpoch,
}, batch)
for validatorChunkIndex, attestations := range groupedByValidatorChunkIndexAtts {
// The fact that we use always slashertypes.MinSpan is probably the root cause of
// https://github.com/prysmaticlabs/prysm/issues/13591
surroundSlashings, err := s.checkSurrounds(ctx, attestations, slashertypes.MinSpan, currentEpoch, validatorChunkIndex)
if err != nil {
return nil, err
}
slashings = append(slashings, attSlashings...)
for root, slashing := range surroundSlashings {
slashings[root] = slashing
}
indices := s.params.validatorIndicesInChunk(validatorChunkIdx)
indices := s.params.validatorIndexesInChunk(validatorChunkIndex)
for _, idx := range indices {
s.latestEpochWrittenForValidator[idx] = currentEpoch
}
batchTimes = append(batchTimes, time.Since(innerStart))
}
avgProcessingTimePerBatch := time.Duration(0)
for _, dur := range batchTimes {
avgProcessingTimePerBatch += dur
}
surroundElapsed := time.Since(surroundStart)
totalElapsed := time.Since(totalStart)
if avgProcessingTimePerBatch != time.Duration(0) {
avgProcessingTimePerBatch = avgProcessingTimePerBatch / time.Duration(len(batchTimes))
}
log.WithFields(logrus.Fields{
fields := logrus.Fields{
"numAttestations": len(atts),
"numBatchesByValidatorChunkIndex": len(groupedAtts),
"elapsed": time.Since(start),
"avgBatchProcessingTime": avgProcessingTimePerBatch,
}).Info("Done checking slashable attestations")
"numBatchesByValidatorChunkIndex": groupsCount,
"elapsed": totalElapsed,
}
if groupsCount > 0 {
avgProcessingTimePerBatch := surroundElapsed / time.Duration(groupsCount)
fields["avgBatchProcessingTime"] = avgProcessingTimePerBatch
}
log.WithFields(fields).Info("Done checking slashable attestations")
if len(slashings) > 0 {
log.WithField("numSlashings", len(slashings)).Warn("Slashable attestation offenses found")
@@ -92,119 +106,204 @@ func (s *Service) checkSlashableAttestations(
// This function performs a lot of critical actions and is split into smaller helpers for cleanliness.
func (s *Service) checkSurrounds(
ctx context.Context,
args *chunkUpdateArgs,
attestations []*slashertypes.IndexedAttestationWrapper,
) ([]*ethpb.AttesterSlashing, error) {
chunkKind slashertypes.ChunkKind,
currentEpoch primitives.Epoch,
validatorChunkIndex uint64,
) (map[[fieldparams.RootLength]byte]*ethpb.AttesterSlashing, error) {
// Map of updated chunks by chunk index, which will be saved at the end.
updatedChunks := make(map[uint64]Chunker)
groupedAtts := s.groupByChunkIndex(attestations)
validatorIndices := s.params.validatorIndicesInChunk(args.validatorChunkIndex)
groupedByChunkIndexAtts := s.groupByChunkIndex(attestations)
validatorIndexes := s.params.validatorIndexesInChunk(validatorChunkIndex)
// Update the min/max span chunks for the change of current epoch.
for _, validatorIndex := range validatorIndices {
if err := s.epochUpdateForValidator(ctx, args, updatedChunks, validatorIndex); err != nil {
return nil, errors.Wrapf(
err,
"could not update validator index chunks %d",
validatorIndex,
)
slashings := map[[fieldparams.RootLength]byte]*ethpb.AttesterSlashing{}
// Update epoch for validators.
for _, validatorIndex := range validatorIndexes {
// This function modifies `updatedChunks` in place.
if err := s.epochUpdateForValidator(ctx, updatedChunks, validatorChunkIndex, chunkKind, currentEpoch, validatorIndex); err != nil {
return nil, errors.Wrapf(err, "could not update validator index chunks %d", validatorIndex)
}
}
// Update min and max spans and retrieve any detected slashable offenses.
surroundingSlashings, err := s.updateSpans(ctx, updatedChunks, &chunkUpdateArgs{
kind: slashertypes.MinSpan,
validatorChunkIndex: args.validatorChunkIndex,
currentEpoch: args.currentEpoch,
}, groupedAtts)
// Check for surrounding votes.
surroundingSlashings, err := s.updateSpans(ctx, updatedChunks, groupedByChunkIndexAtts, slashertypes.MinSpan, validatorChunkIndex, currentEpoch)
if err != nil {
return nil, errors.Wrapf(
err,
"could not update min attestation spans for validator chunk index %d",
args.validatorChunkIndex,
)
return nil, errors.Wrapf(err, "could not update min attestation spans for validator chunk index %d", validatorChunkIndex)
}
surroundedSlashings, err := s.updateSpans(ctx, updatedChunks, &chunkUpdateArgs{
kind: slashertypes.MaxSpan,
validatorChunkIndex: args.validatorChunkIndex,
currentEpoch: args.currentEpoch,
}, groupedAtts)
if err != nil {
return nil, errors.Wrapf(
err,
"could not update max attestation spans for validator chunk index %d",
args.validatorChunkIndex,
)
for root, slashing := range surroundingSlashings {
slashings[root] = slashing
}
slashings := make([]*ethpb.AttesterSlashing, 0, len(surroundingSlashings)+len(surroundedSlashings))
slashings = append(slashings, surroundingSlashings...)
slashings = append(slashings, surroundedSlashings...)
if err := s.saveUpdatedChunks(ctx, args, updatedChunks); err != nil {
// Check for surrounded votes.
surroundedSlashings, err := s.updateSpans(ctx, updatedChunks, groupedByChunkIndexAtts, slashertypes.MaxSpan, validatorChunkIndex, currentEpoch)
if err != nil {
return nil, errors.Wrapf(err, "could not update max attestation spans for validator chunk index %d", validatorChunkIndex)
}
for root, slashing := range surroundedSlashings {
slashings[root] = slashing
}
if err := s.saveUpdatedChunks(ctx, updatedChunks, chunkKind, validatorChunkIndex); err != nil {
return nil, err
}
return slashings, nil
}
// Check for double votes in our database given a list of incoming attestations.
func (s *Service) checkDoubleVotes(
ctx context.Context, attestations []*slashertypes.IndexedAttestationWrapper,
) ([]*ethpb.AttesterSlashing, error) {
ctx context.Context, incomingAttWrappers []*slashertypes.IndexedAttestationWrapper,
) (map[[fieldparams.RootLength]byte]*ethpb.AttesterSlashing, error) {
ctx, span := trace.StartSpan(ctx, "Slasher.checkDoubleVotesOnDisk")
defer span.End()
doubleVotes, err := s.serviceCfg.Database.CheckAttesterDoubleVotes(
ctx, attestations,
)
type attestationInfo struct {
validatorIndex uint64
epoch primitives.Epoch
}
slashings := map[[fieldparams.RootLength]byte]*ethpb.AttesterSlashing{}
// Check each incoming attestation for double votes against other incoming attestations.
existingAttWrappers := make(map[attestationInfo]*slashertypes.IndexedAttestationWrapper)
for _, incomingAttWrapper := range incomingAttWrappers {
targetEpoch := incomingAttWrapper.IndexedAttestation.Data.Target.Epoch
for _, validatorIndex := range incomingAttWrapper.IndexedAttestation.AttestingIndices {
info := attestationInfo{
validatorIndex: validatorIndex,
epoch: targetEpoch,
}
existingAttWrapper, ok := existingAttWrappers[info]
if !ok {
// This is the first attestation for this `validator index x epoch` combination.
// There is no double vote. This attestation is memoized for future checks.
existingAttWrappers[info] = incomingAttWrapper
continue
}
if existingAttWrapper.DataRoot == incomingAttWrapper.DataRoot {
// Both attestations are the same, this is not a double vote.
continue
}
// There is two different attestations for the same `validator index x epoch` combination.
// This is a double vote.
doubleVotesTotal.Inc()
slashing := &ethpb.AttesterSlashing{
Attestation_1: existingAttWrapper.IndexedAttestation,
Attestation_2: incomingAttWrapper.IndexedAttestation,
}
// Ensure the attestation with the lower data root is the first attestation.
// It will be useful for comparing with other double votes.
if bytes.Compare(existingAttWrapper.DataRoot[:], incomingAttWrapper.DataRoot[:]) > 0 {
slashing = &ethpb.AttesterSlashing{
Attestation_1: incomingAttWrapper.IndexedAttestation,
Attestation_2: existingAttWrapper.IndexedAttestation,
}
}
root, err := slashing.HashTreeRoot()
if err != nil {
return nil, errors.Wrap(err, "could not hash tree root for attester slashing")
}
slashings[root] = slashing
}
}
// Check each incoming attestation for double votes against the database.
doubleVotes, err := s.serviceCfg.Database.CheckAttesterDoubleVotes(ctx, incomingAttWrappers)
if err != nil {
return nil, errors.Wrap(err, "could not retrieve potential double votes from disk")
}
doubleVoteSlashings := make([]*ethpb.AttesterSlashing, 0)
for _, doubleVote := range doubleVotes {
doubleVotesTotal.Inc()
doubleVoteSlashings = append(doubleVoteSlashings, &ethpb.AttesterSlashing{
Attestation_1: doubleVote.PrevAttestationWrapper.IndexedAttestation,
Attestation_2: doubleVote.AttestationWrapper.IndexedAttestation,
})
wrapper_1 := doubleVote.Wrapper_1
wrapper_2 := doubleVote.Wrapper_2
slashing := &ethpb.AttesterSlashing{
Attestation_1: wrapper_1.IndexedAttestation,
Attestation_2: wrapper_2.IndexedAttestation,
}
// Ensure the attestation with the lower data root is the first attestation.
if bytes.Compare(wrapper_1.DataRoot[:], wrapper_2.DataRoot[:]) > 0 {
slashing = &ethpb.AttesterSlashing{
Attestation_1: wrapper_2.IndexedAttestation,
Attestation_2: wrapper_1.IndexedAttestation,
}
}
root, err := slashing.HashTreeRoot()
if err != nil {
return nil, errors.Wrap(err, "could not hash tree root for attester slashing")
}
slashings[root] = slashing
}
return doubleVoteSlashings, nil
return slashings, nil
}
// This function updates the slashing spans for a given validator for a change in epoch
// since the last epoch we have recorded for the validator. For example, if the last epoch a validator
// has written is N, and the current epoch is N+5, we update entries in the slashing spans
// with their neutral element for epochs N+1 to N+4. This also puts any loaded chunks in a
// map used as a cache for further processing and minimizing database reads later on.
// This function updates `updatedChunks`, representing the slashing spans for a given validator for
// a change in epoch since the last epoch we have recorded for the validator.
// For example, if the last epoch a validator has written is N, and the current epoch is N+5,
// we update entries in the slashing spans with their neutral element for epochs N+1 to N+4.
// This also puts any loaded chunks in a map used as a cache for further processing and minimizing
// database reads later on.
func (s *Service) epochUpdateForValidator(
ctx context.Context,
args *chunkUpdateArgs,
updatedChunks map[uint64]Chunker,
validatorChunkIndex uint64,
chunkKind slashertypes.ChunkKind,
currentEpoch primitives.Epoch,
validatorIndex primitives.ValidatorIndex,
) error {
epoch := s.latestEpochWrittenForValidator[validatorIndex]
if epoch == 0 {
var err error
latestEpochWritten, ok := s.latestEpochWrittenForValidator[validatorIndex]
if !ok {
return nil
}
for epoch <= args.currentEpoch {
chunkIdx := s.params.chunkIndex(epoch)
currentChunk, err := s.getChunk(ctx, args, updatedChunks, chunkIdx)
if err != nil {
return err
for latestEpochWritten <= currentEpoch {
chunkIndex := s.params.chunkIndex(latestEpochWritten)
currentChunk, ok := updatedChunks[chunkIndex]
if !ok {
currentChunk, err = s.getChunk(ctx, chunkKind, validatorChunkIndex, chunkIndex)
if err != nil {
return errors.Wrap(err, "could not get chunk")
}
}
for s.params.chunkIndex(epoch) == chunkIdx && epoch <= args.currentEpoch {
for s.params.chunkIndex(latestEpochWritten) == chunkIndex && latestEpochWritten <= currentEpoch {
if err := setChunkRawDistance(
s.params,
currentChunk.Chunk(),
validatorIndex,
epoch,
latestEpochWritten,
currentChunk.NeutralElement(),
); err != nil {
return err
}
updatedChunks[chunkIdx] = currentChunk
epoch++
updatedChunks[chunkIndex] = currentChunk
latestEpochWritten++
}
}
return nil
}
@@ -219,23 +318,26 @@ func (s *Service) epochUpdateForValidator(
func (s *Service) updateSpans(
ctx context.Context,
updatedChunks map[uint64]Chunker,
args *chunkUpdateArgs,
attestationsByChunkIdx map[uint64][]*slashertypes.IndexedAttestationWrapper,
) ([]*ethpb.AttesterSlashing, error) {
attWrapperByChunkIdx map[uint64][]*slashertypes.IndexedAttestationWrapper,
kind slashertypes.ChunkKind,
validatorChunkIndex uint64,
currentEpoch primitives.Epoch,
) (map[[fieldparams.RootLength]byte]*ethpb.AttesterSlashing, error) {
ctx, span := trace.StartSpan(ctx, "Slasher.updateSpans")
defer span.End()
// Apply the attestations to the related chunks and find any
// slashings along the way.
slashings := make([]*ethpb.AttesterSlashing, 0)
for _, attestationBatch := range attestationsByChunkIdx {
for _, att := range attestationBatch {
for _, validatorIdx := range att.IndexedAttestation.AttestingIndices {
slashings := map[[fieldparams.RootLength]byte]*ethpb.AttesterSlashing{}
for _, attWrappers := range attWrapperByChunkIdx {
for _, attWrapper := range attWrappers {
for _, validatorIdx := range attWrapper.IndexedAttestation.AttestingIndices {
validatorIndex := primitives.ValidatorIndex(validatorIdx)
computedValidatorChunkIdx := s.params.validatorChunkIndex(validatorIndex)
// Every validator chunk index represents a range of validators.
// If it possible that the validator index in this loop iteration is
// It is possible that the validator index in this loop iteration is
// not part of the validator chunk index we are updating chunks for.
//
// For example, if there are 4 validators per validator chunk index,
@@ -243,26 +345,28 @@ func (s *Service) updateSpans(
// If we see an attestation with attesting indices [3, 4, 5] and we are updating
// chunks for validator chunk index 0, only validator index 3 should make
// it past this line.
if args.validatorChunkIndex != computedValidatorChunkIdx {
if validatorChunkIndex != computedValidatorChunkIdx {
continue
}
slashing, err := s.applyAttestationForValidator(
ctx,
args,
validatorIndex,
updatedChunks,
att,
ctx, updatedChunks, attWrapper, kind, validatorChunkIndex, validatorIndex, currentEpoch,
)
if err != nil {
return nil, errors.Wrapf(
err,
"could not apply attestation for validator index %d",
validatorIndex,
)
return nil, errors.Wrapf(err, "could not apply attestation for validator index %d", validatorIndex)
}
if slashing != nil {
slashings = append(slashings, slashing)
if slashing == nil {
continue
}
root, err := slashing.HashTreeRoot()
if err != nil {
return nil, errors.Wrap(err, "could not hash tree root for attester slashing")
}
slashings[root] = slashing
}
}
}
@@ -277,22 +381,30 @@ func (s *Service) updateSpans(
// source epoch up to its target.
func (s *Service) applyAttestationForValidator(
ctx context.Context,
args *chunkUpdateArgs,
validatorIndex primitives.ValidatorIndex,
chunksByChunkIdx map[uint64]Chunker,
attestation *slashertypes.IndexedAttestationWrapper,
chunkKind slashertypes.ChunkKind,
validatorChunkIndex uint64,
validatorIndex primitives.ValidatorIndex,
currentEpoch primitives.Epoch,
) (*ethpb.AttesterSlashing, error) {
ctx, span := trace.StartSpan(ctx, "Slasher.applyAttestationForValidator")
defer span.End()
var err error
sourceEpoch := attestation.IndexedAttestation.Data.Source.Epoch
targetEpoch := attestation.IndexedAttestation.Data.Target.Epoch
attestationDistance.Observe(float64(targetEpoch) - float64(sourceEpoch))
chunkIndex := s.params.chunkIndex(sourceEpoch)
chunkIdx := s.params.chunkIndex(sourceEpoch)
chunk, err := s.getChunk(ctx, args, chunksByChunkIdx, chunkIdx)
if err != nil {
return nil, errors.Wrapf(err, "could not get chunk at index %d", chunkIdx)
chunk, ok := chunksByChunkIdx[chunkIndex]
if !ok {
chunk, err = s.getChunk(ctx, chunkKind, validatorChunkIndex, chunkIndex)
if err != nil {
return nil, errors.Wrapf(err, "could not get chunk at index %d", chunkIndex)
}
}
// Check slashable, if so, return the slashing.
@@ -315,7 +427,7 @@ func (s *Service) applyAttestationForValidator(
// Get the first start epoch for the chunk. If it does not exist or
// is not possible based on the input arguments, do not continue with the update.
startEpoch, exists := chunk.StartEpoch(sourceEpoch, args.currentEpoch)
startEpoch, exists := chunk.StartEpoch(sourceEpoch, currentEpoch)
if !exists {
return nil, nil
}
@@ -327,62 +439,67 @@ func (s *Service) applyAttestationForValidator(
// the start epoch of the next chunk. We exit once no longer need to
// keep updating chunks.
for {
chunkIdx = s.params.chunkIndex(startEpoch)
chunk, err := s.getChunk(ctx, args, chunksByChunkIdx, chunkIdx)
if err != nil {
return nil, errors.Wrapf(err, "could not get chunk at index %d", chunkIdx)
chunkIndex = s.params.chunkIndex(startEpoch)
chunk, ok := chunksByChunkIdx[chunkIndex]
if !ok {
chunk, err = s.getChunk(ctx, chunkKind, validatorChunkIndex, chunkIndex)
if err != nil {
return nil, errors.Wrapf(err, "could not get chunk at index %d", chunkIndex)
}
}
keepGoing, err := chunk.Update(
&chunkUpdateArgs{
chunkIndex: chunkIdx,
currentEpoch: args.currentEpoch,
chunkIndex: chunkIndex,
currentEpoch: currentEpoch,
},
validatorIndex,
startEpoch,
targetEpoch,
)
if err != nil {
return nil, errors.Wrapf(
err,
"could not update chunk at chunk index %d for validator index %d and current epoch %d",
chunkIdx,
chunkIndex,
validatorIndex,
args.currentEpoch,
currentEpoch,
)
}
// We update the chunksByChunkIdx map with the chunk we just updated.
chunksByChunkIdx[chunkIdx] = chunk
chunksByChunkIdx[chunkIndex] = chunk
if !keepGoing {
break
}
// Move to first epoch of next chunk if needed.
startEpoch = chunk.NextChunkStartEpoch(startEpoch)
}
return nil, nil
}
// Retrieves a chunk at a chunk index from a map. If such chunk does not exist, which
// should be rare (occurring when we receive an attestation with source and target epochs
// that span multiple chunk indices), then we fallback to fetching from disk.
// Retrieve a chunk from database from database.
func (s *Service) getChunk(
ctx context.Context,
args *chunkUpdateArgs,
chunksByChunkIdx map[uint64]Chunker,
chunkIdx uint64,
chunkKind slashertypes.ChunkKind,
validatorChunkIndex uint64,
chunkIndex uint64,
) (Chunker, error) {
chunk, ok := chunksByChunkIdx[chunkIdx]
if ok {
return chunk, nil
}
// We can ensure we load the appropriate chunk we need by fetching from the DB.
diskChunks, err := s.loadChunks(ctx, args, []uint64{chunkIdx})
diskChunks, err := s.loadChunks(ctx, validatorChunkIndex, chunkKind, []uint64{chunkIndex})
if err != nil {
return nil, errors.Wrapf(err, "could not load chunk at index %d", chunkIdx)
return nil, errors.Wrapf(err, "could not load chunk at index %d", chunkIndex)
}
if chunk, ok := diskChunks[chunkIdx]; ok {
if chunk, ok := diskChunks[chunkIndex]; ok {
return chunk, nil
}
return nil, fmt.Errorf("could not retrieve chunk at chunk index %d from disk", chunkIdx)
return nil, fmt.Errorf("could not retrieve chunk at chunk index %d from disk", chunkIndex)
}
// Load chunks for a specified list of chunk indices. We attempt to load it from the database.
@@ -390,63 +507,75 @@ func (s *Service) getChunk(
// an empty chunk, add it to our map, and then return it to the caller.
func (s *Service) loadChunks(
ctx context.Context,
args *chunkUpdateArgs,
validatorChunkIndex uint64,
chunkKind slashertypes.ChunkKind,
chunkIndices []uint64,
) (map[uint64]Chunker, error) {
ctx, span := trace.StartSpan(ctx, "Slasher.loadChunks")
defer span.End()
chunkKeys := make([][]byte, 0, len(chunkIndices))
for _, chunkIdx := range chunkIndices {
chunkKeys = append(chunkKeys, s.params.flatSliceID(args.validatorChunkIndex, chunkIdx))
chunkKeys = append(chunkKeys, s.params.flatSliceID(validatorChunkIndex, chunkIdx))
}
rawChunks, chunksExist, err := s.serviceCfg.Database.LoadSlasherChunks(ctx, args.kind, chunkKeys)
rawChunks, chunksExist, err := s.serviceCfg.Database.LoadSlasherChunks(ctx, chunkKind, chunkKeys)
if err != nil {
return nil, errors.Wrapf(
err,
"could not load slasher chunk index",
)
return nil, errors.Wrapf(err, "could not load slasher chunk index")
}
chunksByChunkIdx := make(map[uint64]Chunker, len(rawChunks))
for i := 0; i < len(rawChunks); i++ {
// If the chunk exists in the database, we initialize it from the raw bytes data.
// If it does not exist, we initialize an empty chunk.
var chunk Chunker
switch args.kind {
var (
chunk Chunker
err error
)
chunkExists := chunksExist[i]
switch chunkKind {
case slashertypes.MinSpan:
if chunksExist[i] {
if chunkExists {
chunk, err = MinChunkSpansSliceFrom(s.params, rawChunks[i])
} else {
chunk = EmptyMinSpanChunksSlice(s.params)
break
}
chunk = EmptyMinSpanChunksSlice(s.params)
case slashertypes.MaxSpan:
if chunksExist[i] {
if chunkExists {
chunk, err = MaxChunkSpansSliceFrom(s.params, rawChunks[i])
} else {
chunk = EmptyMaxSpanChunksSlice(s.params)
break
}
chunk = EmptyMaxSpanChunksSlice(s.params)
}
if err != nil {
return nil, errors.Wrap(err, "could not initialize chunk")
}
chunksByChunkIdx[chunkIndices[i]] = chunk
}
return chunksByChunkIdx, nil
}
// Saves updated chunks to disk given the required database schema.
func (s *Service) saveUpdatedChunks(
ctx context.Context,
args *chunkUpdateArgs,
updatedChunksByChunkIdx map[uint64]Chunker,
chunkKind slashertypes.ChunkKind,
validatorChunkIndex uint64,
) error {
ctx, span := trace.StartSpan(ctx, "Slasher.saveUpdatedChunks")
defer span.End()
chunkKeys := make([][]byte, 0, len(updatedChunksByChunkIdx))
chunks := make([][]uint16, 0, len(updatedChunksByChunkIdx))
for chunkIdx, chunk := range updatedChunksByChunkIdx {
chunkKeys = append(chunkKeys, s.params.flatSliceID(args.validatorChunkIndex, chunkIdx))
chunkKeys = append(chunkKeys, s.params.flatSliceID(validatorChunkIndex, chunkIdx))
chunks = append(chunks, chunk.Chunk())
}
chunksSavedTotal.Add(float64(len(chunks)))
return s.serviceCfg.Database.SaveSlasherChunks(ctx, args.kind, chunkKeys, chunks)
return s.serviceCfg.Database.SaveSlasherChunks(ctx, chunkKind, chunkKeys, chunks)
}

File diff suppressed because it is too large Load Diff

View File

@@ -37,7 +37,7 @@ func (s *Service) detectProposerSlashings(
}
// If we have seen this proposal before, we check if it is a double proposal.
if isDoubleProposal(incomingProposal.SigningRoot, existingProposal.SigningRoot) {
if isDoubleProposal(incomingProposal.HeaderRoot, existingProposal.HeaderRoot) {
doubleProposalsTotal.Inc()
slashing := &ethpb.ProposerSlashing{

View File

@@ -204,7 +204,7 @@ func createProposalWrapper(t *testing.T, slot primitives.Slot, proposerIndex pri
StateRoot: bytesutil.PadTo(signingRoot, 32),
BodyRoot: params.BeaconConfig().ZeroHash[:],
}
signRoot, err := header.HashTreeRoot()
headerRoot, err := header.HashTreeRoot()
require.NoError(t, err)
fakeSig := make([]byte, 96)
copy(fakeSig, "hello")
@@ -213,6 +213,6 @@ func createProposalWrapper(t *testing.T, slot primitives.Slot, proposerIndex pri
Header: header,
Signature: fakeSig,
},
SigningRoot: signRoot,
HeaderRoot: headerRoot,
}
}

View File

@@ -21,19 +21,23 @@ func (s *Service) groupByValidatorChunkIndex(
attestations []*slashertypes.IndexedAttestationWrapper,
) map[uint64][]*slashertypes.IndexedAttestationWrapper {
groupedAttestations := make(map[uint64][]*slashertypes.IndexedAttestationWrapper)
for _, att := range attestations {
validatorChunkIndices := make(map[uint64]bool)
for _, validatorIdx := range att.IndexedAttestation.AttestingIndices {
validatorChunkIndex := s.params.validatorChunkIndex(primitives.ValidatorIndex(validatorIdx))
validatorChunkIndices[validatorChunkIndex] = true
for _, attestation := range attestations {
validatorChunkIndexes := make(map[uint64]bool)
for _, validatorIndex := range attestation.IndexedAttestation.AttestingIndices {
validatorChunkIndex := s.params.validatorChunkIndex(primitives.ValidatorIndex(validatorIndex))
validatorChunkIndexes[validatorChunkIndex] = true
}
for validatorChunkIndex := range validatorChunkIndices {
for validatorChunkIndex := range validatorChunkIndexes {
groupedAttestations[validatorChunkIndex] = append(
groupedAttestations[validatorChunkIndex],
att,
attestation,
)
}
}
return groupedAttestations
}
@@ -42,10 +46,12 @@ func (s *Service) groupByChunkIndex(
attestations []*slashertypes.IndexedAttestationWrapper,
) map[uint64][]*slashertypes.IndexedAttestationWrapper {
attestationsByChunkIndex := make(map[uint64][]*slashertypes.IndexedAttestationWrapper)
for _, att := range attestations {
chunkIdx := s.params.chunkIndex(att.IndexedAttestation.Data.Source.Epoch)
attestationsByChunkIndex[chunkIdx] = append(attestationsByChunkIndex[chunkIdx], att)
for _, attestation := range attestations {
chunkIndex := s.params.chunkIndex(attestation.IndexedAttestation.Data.Source.Epoch)
attestationsByChunkIndex[chunkIndex] = append(attestationsByChunkIndex[chunkIndex], attestation)
}
return attestationsByChunkIndex
}

View File

@@ -32,13 +32,13 @@ func TestService_groupByValidatorChunkIndex(t *testing.T) {
validatorChunkSize: 2,
},
atts: []*slashertypes.IndexedAttestationWrapper{
createAttestationWrapper(t, 0, 0, []uint64{0, 1}, nil),
createAttestationWrapper(t, 0, 0, []uint64{0, 1}, nil),
createAttestationWrapperEmptySig(t, 0, 0, []uint64{0, 1}, nil),
createAttestationWrapperEmptySig(t, 0, 0, []uint64{0, 1}, nil),
},
want: map[uint64][]*slashertypes.IndexedAttestationWrapper{
0: {
createAttestationWrapper(t, 0, 0, []uint64{0, 1}, nil),
createAttestationWrapper(t, 0, 0, []uint64{0, 1}, nil),
createAttestationWrapperEmptySig(t, 0, 0, []uint64{0, 1}, nil),
createAttestationWrapperEmptySig(t, 0, 0, []uint64{0, 1}, nil),
},
},
},
@@ -48,17 +48,17 @@ func TestService_groupByValidatorChunkIndex(t *testing.T) {
validatorChunkSize: 2,
},
atts: []*slashertypes.IndexedAttestationWrapper{
createAttestationWrapper(t, 0, 0, []uint64{0, 2, 4}, nil),
createAttestationWrapperEmptySig(t, 0, 0, []uint64{0, 2, 4}, nil),
},
want: map[uint64][]*slashertypes.IndexedAttestationWrapper{
0: {
createAttestationWrapper(t, 0, 0, []uint64{0, 2, 4}, nil),
createAttestationWrapperEmptySig(t, 0, 0, []uint64{0, 2, 4}, nil),
},
1: {
createAttestationWrapper(t, 0, 0, []uint64{0, 2, 4}, nil),
createAttestationWrapperEmptySig(t, 0, 0, []uint64{0, 2, 4}, nil),
},
2: {
createAttestationWrapper(t, 0, 0, []uint64{0, 2, 4}, nil),
createAttestationWrapperEmptySig(t, 0, 0, []uint64{0, 2, 4}, nil),
},
},
},
@@ -95,13 +95,13 @@ func TestService_groupByChunkIndex(t *testing.T) {
historyLength: 3,
},
atts: []*slashertypes.IndexedAttestationWrapper{
createAttestationWrapper(t, 0, 0, nil, nil),
createAttestationWrapper(t, 1, 0, nil, nil),
createAttestationWrapperEmptySig(t, 0, 0, nil, nil),
createAttestationWrapperEmptySig(t, 1, 0, nil, nil),
},
want: map[uint64][]*slashertypes.IndexedAttestationWrapper{
0: {
createAttestationWrapper(t, 0, 0, nil, nil),
createAttestationWrapper(t, 1, 0, nil, nil),
createAttestationWrapperEmptySig(t, 0, 0, nil, nil),
createAttestationWrapperEmptySig(t, 1, 0, nil, nil),
},
},
},
@@ -112,17 +112,17 @@ func TestService_groupByChunkIndex(t *testing.T) {
historyLength: 3,
},
atts: []*slashertypes.IndexedAttestationWrapper{
createAttestationWrapper(t, 0, 0, nil, nil),
createAttestationWrapper(t, 1, 0, nil, nil),
createAttestationWrapper(t, 2, 0, nil, nil),
createAttestationWrapperEmptySig(t, 0, 0, nil, nil),
createAttestationWrapperEmptySig(t, 1, 0, nil, nil),
createAttestationWrapperEmptySig(t, 2, 0, nil, nil),
},
want: map[uint64][]*slashertypes.IndexedAttestationWrapper{
0: {
createAttestationWrapper(t, 0, 0, nil, nil),
createAttestationWrapper(t, 1, 0, nil, nil),
createAttestationWrapperEmptySig(t, 0, 0, nil, nil),
createAttestationWrapperEmptySig(t, 1, 0, nil, nil),
},
1: {
createAttestationWrapper(t, 2, 0, nil, nil),
createAttestationWrapperEmptySig(t, 2, 0, nil, nil),
},
},
},
@@ -207,7 +207,7 @@ func TestService_filterAttestations(t *testing.T) {
{
name: "Source > target gets dropped",
input: []*slashertypes.IndexedAttestationWrapper{
createAttestationWrapper(t, 1, 0, []uint64{1}, make([]byte, 32)),
createAttestationWrapperEmptySig(t, 1, 0, []uint64{1}, make([]byte, 32)),
},
inputEpoch: 0,
wantedDropped: 1,
@@ -215,33 +215,33 @@ func TestService_filterAttestations(t *testing.T) {
{
name: "Source < target is valid",
input: []*slashertypes.IndexedAttestationWrapper{
createAttestationWrapper(t, 0, 1, []uint64{1}, make([]byte, 32)),
createAttestationWrapperEmptySig(t, 0, 1, []uint64{1}, make([]byte, 32)),
},
inputEpoch: 1,
wantedValid: []*slashertypes.IndexedAttestationWrapper{
createAttestationWrapper(t, 0, 1, []uint64{1}, make([]byte, 32)),
createAttestationWrapperEmptySig(t, 0, 1, []uint64{1}, make([]byte, 32)),
},
wantedDropped: 0,
},
{
name: "Source == target is valid",
input: []*slashertypes.IndexedAttestationWrapper{
createAttestationWrapper(t, 0, 0, []uint64{1}, make([]byte, 32)),
createAttestationWrapperEmptySig(t, 0, 0, []uint64{1}, make([]byte, 32)),
},
inputEpoch: 1,
wantedValid: []*slashertypes.IndexedAttestationWrapper{
createAttestationWrapper(t, 0, 0, []uint64{1}, make([]byte, 32)),
createAttestationWrapperEmptySig(t, 0, 0, []uint64{1}, make([]byte, 32)),
},
wantedDropped: 0,
},
{
name: "Attestation from the future is deferred",
input: []*slashertypes.IndexedAttestationWrapper{
createAttestationWrapper(t, 0, 2, []uint64{1}, make([]byte, 32)),
createAttestationWrapperEmptySig(t, 0, 2, []uint64{1}, make([]byte, 32)),
},
inputEpoch: 1,
wantedDeferred: []*slashertypes.IndexedAttestationWrapper{
createAttestationWrapper(t, 0, 2, []uint64{1}, make([]byte, 32)),
createAttestationWrapperEmptySig(t, 0, 2, []uint64{1}, make([]byte, 32)),
},
wantedDropped: 0,
},
@@ -271,22 +271,22 @@ func Test_logSlashingEvent(t *testing.T) {
{
name: "Surrounding vote",
slashing: &ethpb.AttesterSlashing{
Attestation_1: createAttestationWrapper(t, 0, 0, nil, nil).IndexedAttestation,
Attestation_2: createAttestationWrapper(t, 0, 0, nil, nil).IndexedAttestation,
Attestation_1: createAttestationWrapperEmptySig(t, 0, 0, nil, nil).IndexedAttestation,
Attestation_2: createAttestationWrapperEmptySig(t, 0, 0, nil, nil).IndexedAttestation,
},
},
{
name: "Surrounded vote",
slashing: &ethpb.AttesterSlashing{
Attestation_1: createAttestationWrapper(t, 0, 0, nil, nil).IndexedAttestation,
Attestation_2: createAttestationWrapper(t, 0, 0, nil, nil).IndexedAttestation,
Attestation_1: createAttestationWrapperEmptySig(t, 0, 0, nil, nil).IndexedAttestation,
Attestation_2: createAttestationWrapperEmptySig(t, 0, 0, nil, nil).IndexedAttestation,
},
},
{
name: "Double vote",
slashing: &ethpb.AttesterSlashing{
Attestation_1: createAttestationWrapper(t, 0, 0, nil, nil).IndexedAttestation,
Attestation_2: createAttestationWrapper(t, 0, 0, nil, nil).IndexedAttestation,
Attestation_1: createAttestationWrapperEmptySig(t, 0, 0, nil, nil).IndexedAttestation,
Attestation_2: createAttestationWrapperEmptySig(t, 0, 0, nil, nil).IndexedAttestation,
},
},
}

View File

@@ -141,12 +141,14 @@ func (p *Parameters) flatSliceID(validatorChunkIndex, chunkIndex uint64) []byte
// Given a validator chunk index, we determine all of the validator
// indices that will belong in that chunk.
func (p *Parameters) validatorIndicesInChunk(validatorChunkIdx uint64) []primitives.ValidatorIndex {
func (p *Parameters) validatorIndexesInChunk(validatorChunkIndex uint64) []primitives.ValidatorIndex {
validatorIndices := make([]primitives.ValidatorIndex, 0)
low := validatorChunkIdx * p.validatorChunkSize
high := (validatorChunkIdx + 1) * p.validatorChunkSize
low := validatorChunkIndex * p.validatorChunkSize
high := (validatorChunkIndex + 1) * p.validatorChunkSize
for i := low; i < high; i++ {
validatorIndices = append(validatorIndices, primitives.ValidatorIndex(i))
}
return validatorIndices
}

View File

@@ -468,7 +468,7 @@ func TestParams_validatorIndicesInChunk(t *testing.T) {
c := &Parameters{
validatorChunkSize: tt.fields.validatorChunkSize,
}
if got := c.validatorIndicesInChunk(tt.validatorChunkIdx); !reflect.DeepEqual(got, tt.want) {
if got := c.validatorIndexesInChunk(tt.validatorChunkIdx); !reflect.DeepEqual(got, tt.want) {
t.Errorf("validatorIndicesInChunk() = %v, want %v", got, tt.want)
}
})

View File

@@ -3,78 +3,102 @@ package slasher
import (
"context"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state"
fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams"
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
)
// Verifies attester slashings, logs them, and submits them to the slashing operations pool
// in the beacon node if they pass validation.
func (s *Service) processAttesterSlashings(ctx context.Context, slashings []*ethpb.AttesterSlashing) error {
var beaconState state.BeaconState
var err error
if len(slashings) > 0 {
beaconState, err = s.serviceCfg.HeadStateFetcher.HeadState(ctx)
if err != nil {
return err
}
func (s *Service) processAttesterSlashings(
ctx context.Context, slashings map[[fieldparams.RootLength]byte]*ethpb.AttesterSlashing,
) (map[[fieldparams.RootLength]byte]*ethpb.AttesterSlashing, error) {
processedSlashings := map[[fieldparams.RootLength]byte]*ethpb.AttesterSlashing{}
// If no slashings, return early.
if len(slashings) == 0 {
return processedSlashings, nil
}
for _, sl := range slashings {
if err := s.verifyAttSignature(ctx, sl.Attestation_1); err != nil {
log.WithError(err).WithField("a", sl.Attestation_1).Warn(
// Get the head state.
beaconState, err := s.serviceCfg.HeadStateFetcher.HeadState(ctx)
if err != nil {
return nil, errors.Wrap(err, "could not get head state")
}
for root, slashing := range slashings {
// Verify the signature of the first attestation.
if err := s.verifyAttSignature(ctx, slashing.Attestation_1); err != nil {
log.WithError(err).WithField("a", slashing.Attestation_1).Warn(
"Invalid signature for attestation in detected slashing offense",
)
continue
}
if err := s.verifyAttSignature(ctx, sl.Attestation_2); err != nil {
log.WithError(err).WithField("b", sl.Attestation_2).Warn(
// Verify the signature of the second attestation.
if err := s.verifyAttSignature(ctx, slashing.Attestation_2); err != nil {
log.WithError(err).WithField("b", slashing.Attestation_2).Warn(
"Invalid signature for attestation in detected slashing offense",
)
continue
}
// Log the slashing event and insert into the beacon node's operations pool.
logAttesterSlashing(sl)
if err := s.serviceCfg.SlashingPoolInserter.InsertAttesterSlashing(
ctx, beaconState, sl,
); err != nil {
logAttesterSlashing(slashing)
if err := s.serviceCfg.SlashingPoolInserter.InsertAttesterSlashing(ctx, beaconState, slashing); err != nil {
log.WithError(err).Error("Could not insert attester slashing into operations pool")
}
processedSlashings[root] = slashing
}
return nil
return processedSlashings, nil
}
// Verifies proposer slashings, logs them, and submits them to the slashing operations pool
// in the beacon node if they pass validation.
func (s *Service) processProposerSlashings(ctx context.Context, slashings []*ethpb.ProposerSlashing) error {
var beaconState state.BeaconState
var err error
if len(slashings) > 0 {
beaconState, err = s.serviceCfg.HeadStateFetcher.HeadState(ctx)
if err != nil {
return err
}
// If no slashings, return early.
if len(slashings) == 0 {
return nil
}
for _, sl := range slashings {
if err := s.verifyBlockSignature(ctx, sl.Header_1); err != nil {
log.WithError(err).WithField("a", sl.Header_1).Warn(
// Get the head state.
beaconState, err := s.serviceCfg.HeadStateFetcher.HeadState(ctx)
if err != nil {
return err
}
for _, slashing := range slashings {
// Verify the signature of the first block.
if err := s.verifyBlockSignature(ctx, slashing.Header_1); err != nil {
log.WithError(err).WithField("a", slashing.Header_1).Warn(
"Invalid signature for block header in detected slashing offense",
)
continue
}
if err := s.verifyBlockSignature(ctx, sl.Header_2); err != nil {
log.WithError(err).WithField("b", sl.Header_2).Warn(
// Verify the signature of the second block.
if err := s.verifyBlockSignature(ctx, slashing.Header_2); err != nil {
log.WithError(err).WithField("b", slashing.Header_2).Warn(
"Invalid signature for block header in detected slashing offense",
)
continue
}
// Log the slashing event and insert into the beacon node's operations pool.
logProposerSlashing(sl)
if err := s.serviceCfg.SlashingPoolInserter.InsertProposerSlashing(ctx, beaconState, sl); err != nil {
logProposerSlashing(slashing)
if err := s.serviceCfg.SlashingPoolInserter.InsertProposerSlashing(ctx, beaconState, slashing); err != nil {
log.WithError(err).Error("Could not insert proposer slashing into operations pool")
}
}
return nil
}

View File

@@ -10,6 +10,7 @@ import (
doublylinkedtree "github.com/prysmaticlabs/prysm/v4/beacon-chain/forkchoice/doubly-linked-tree"
slashingsmock "github.com/prysmaticlabs/prysm/v4/beacon-chain/operations/slashings/mock"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state/stategen"
fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams"
"github.com/prysmaticlabs/prysm/v4/config/params"
"github.com/prysmaticlabs/prysm/v4/crypto/bls"
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
@@ -75,14 +76,19 @@ func TestService_processAttesterSlashings(t *testing.T) {
firstAtt.Signature = signature.Marshal()
secondAtt.Signature = make([]byte, 96)
slashings := []*ethpb.AttesterSlashing{
{
Attestation_1: firstAtt,
Attestation_2: secondAtt,
},
slashing := &ethpb.AttesterSlashing{
Attestation_1: firstAtt,
Attestation_2: secondAtt,
}
err = s.processAttesterSlashings(ctx, slashings)
root, err := slashing.HashTreeRoot()
require.NoError(tt, err, "failed to hash tree root")
slashings := map[[fieldparams.RootLength]byte]*ethpb.AttesterSlashing{
root: slashing,
}
_, err = s.processAttesterSlashings(ctx, slashings)
require.NoError(tt, err)
require.LogsContain(tt, hook, "Invalid signature")
})
@@ -94,14 +100,19 @@ func TestService_processAttesterSlashings(t *testing.T) {
firstAtt.Signature = make([]byte, 96)
secondAtt.Signature = signature.Marshal()
slashings := []*ethpb.AttesterSlashing{
{
Attestation_1: firstAtt,
Attestation_2: secondAtt,
},
slashing := &ethpb.AttesterSlashing{
Attestation_1: firstAtt,
Attestation_2: secondAtt,
}
err = s.processAttesterSlashings(ctx, slashings)
root, err := slashing.HashTreeRoot()
require.NoError(tt, err, "failed to hash tree root")
slashings := map[[fieldparams.RootLength]byte]*ethpb.AttesterSlashing{
root: slashing,
}
_, err = s.processAttesterSlashings(ctx, slashings)
require.NoError(tt, err)
require.LogsContain(tt, hook, "Invalid signature")
})
@@ -113,14 +124,19 @@ func TestService_processAttesterSlashings(t *testing.T) {
firstAtt.Signature = signature.Marshal()
secondAtt.Signature = signature.Marshal()
slashings := []*ethpb.AttesterSlashing{
{
Attestation_1: firstAtt,
Attestation_2: secondAtt,
},
slashing := &ethpb.AttesterSlashing{
Attestation_1: firstAtt,
Attestation_2: secondAtt,
}
err = s.processAttesterSlashings(ctx, slashings)
root, err := slashing.HashTreeRoot()
require.NoError(tt, err, "failed to hash tree root")
slashings := map[[fieldparams.RootLength]byte]*ethpb.AttesterSlashing{
root: slashing,
}
_, err = s.processAttesterSlashings(ctx, slashings)
require.NoError(tt, err)
require.LogsDoNotContain(tt, hook, "Invalid signature")
})

View File

@@ -12,8 +12,8 @@ func Test_attestationsQueue(t *testing.T) {
t.Run("push_and_dequeue", func(tt *testing.T) {
attQueue := newAttestationsQueue()
wantedAtts := []*slashertypes.IndexedAttestationWrapper{
createAttestationWrapper(t, 0, 1, []uint64{1}, make([]byte, 32)),
createAttestationWrapper(t, 1, 2, []uint64{1}, make([]byte, 32)),
createAttestationWrapperEmptySig(t, 0, 1, []uint64{1}, make([]byte, 32)),
createAttestationWrapperEmptySig(t, 1, 2, []uint64{1}, make([]byte, 32)),
}
attQueue.push(wantedAtts[0])
attQueue.push(wantedAtts[1])
@@ -27,8 +27,8 @@ func Test_attestationsQueue(t *testing.T) {
t.Run("extend_and_dequeue", func(tt *testing.T) {
attQueue := newAttestationsQueue()
wantedAtts := []*slashertypes.IndexedAttestationWrapper{
createAttestationWrapper(t, 0, 1, []uint64{1}, make([]byte, 32)),
createAttestationWrapper(t, 1, 2, []uint64{1}, make([]byte, 32)),
createAttestationWrapperEmptySig(t, 0, 1, []uint64{1}, make([]byte, 32)),
createAttestationWrapperEmptySig(t, 1, 2, []uint64{1}, make([]byte, 32)),
}
attQueue.extend(wantedAtts)
require.DeepEqual(t, 2, attQueue.size())

View File

@@ -6,6 +6,7 @@ import (
"github.com/pkg/errors"
slashertypes "github.com/prysmaticlabs/prysm/v4/beacon-chain/slasher/types"
fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams"
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v4/time/slots"
@@ -32,14 +33,14 @@ func (s *Service) receiveAttestations(ctx context.Context, indexedAttsChan chan
if !validateAttestationIntegrity(att) {
continue
}
signingRoot, err := att.Data.HashTreeRoot()
dataRoot, err := att.Data.HashTreeRoot()
if err != nil {
log.WithError(err).Error("Could not get hash tree root of attestation")
continue
}
attWrapper := &slashertypes.IndexedAttestationWrapper{
IndexedAttestation: att,
SigningRoot: signingRoot,
DataRoot: dataRoot,
}
s.attsQueue.push(attWrapper)
case err := <-sub.Err():
@@ -63,14 +64,14 @@ func (s *Service) receiveBlocks(ctx context.Context, beaconBlockHeadersChan chan
if !validateBlockHeaderIntegrity(blockHeader) {
continue
}
signingRoot, err := blockHeader.Header.HashTreeRoot()
headerRoot, err := blockHeader.Header.HashTreeRoot()
if err != nil {
log.WithError(err).Error("Could not get hash tree root of signed block header")
continue
}
wrappedProposal := &slashertypes.SignedBlockHeaderWrapper{
SignedBeaconBlockHeader: blockHeader,
SigningRoot: signingRoot,
HeaderRoot: headerRoot,
}
s.blksQueue.push(wrappedProposal)
case err := <-sub.Err():
@@ -92,57 +93,70 @@ func (s *Service) processQueuedAttestations(ctx context.Context, slotTicker <-ch
for {
select {
case currentSlot := <-slotTicker:
// Retrieve all attestations from the queue.
attestations := s.attsQueue.dequeue()
currentEpoch := slots.ToEpoch(currentSlot)
// We take all the attestations in the queue and filter out
// those which are valid now and valid in the future.
validAtts, validInFuture, numDropped := s.filterAttestations(attestations, currentEpoch)
deferredAttestationsTotal.Add(float64(len(validInFuture)))
droppedAttestationsTotal.Add(float64(numDropped))
// We add back those attestations that are valid in the future to the queue.
s.attsQueue.extend(validInFuture)
log.WithFields(logrus.Fields{
"currentSlot": currentSlot,
"currentEpoch": currentEpoch,
"numValidAtts": len(validAtts),
"numDeferredAtts": len(validInFuture),
"numDroppedAtts": numDropped,
}).Info("Processing queued attestations for slashing detection")
// Save the attestation records to our database.
// If multiple attestations are provided for the same validator index + target epoch combination,
// then last (validator index + target epoch) => signing root) link is kept into the database.
if err := s.serviceCfg.Database.SaveAttestationRecordsForValidators(
ctx, validAtts,
); err != nil {
log.WithError(err).Error(couldNotSaveAttRecord)
continue
}
// Check for slashings.
slashings, err := s.checkSlashableAttestations(ctx, currentEpoch, validAtts)
if err != nil {
log.WithError(err).Error(couldNotCheckSlashableAtt)
continue
}
// Process attester slashings by verifying their signatures, submitting
// to the beacon node's operations pool, and logging them.
if err := s.processAttesterSlashings(ctx, slashings); err != nil {
log.WithError(err).Error(couldNotProcessAttesterSlashings)
continue
}
processedAttestationsTotal.Add(float64(len(validAtts)))
// Process the retrieved attestations.
s.processAttestations(ctx, attestations, currentSlot)
case <-ctx.Done():
return
}
}
}
func (s *Service) processAttestations(
ctx context.Context,
attestations []*slashertypes.IndexedAttestationWrapper,
currentSlot primitives.Slot,
) map[[fieldparams.RootLength]byte]*ethpb.AttesterSlashing {
// Get the current epoch from the current slot.
currentEpoch := slots.ToEpoch(currentSlot)
// Take all the attestations in the queue and filter out
// those which are valid now and valid in the future.
validAttestations, validInFutureAttestations, numDropped := s.filterAttestations(attestations, currentEpoch)
// Increase corresponding prometheus metrics.
deferredAttestationsTotal.Add(float64(len(validInFutureAttestations)))
droppedAttestationsTotal.Add(float64(numDropped))
processedAttestationsTotal.Add(float64(len(validAttestations)))
// We add back those attestations that are valid in the future to the queue.
s.attsQueue.extend(validInFutureAttestations)
// Compute some counts.
queuedAttestationsCount := s.attsQueue.size()
validAttestationsCount := len(validAttestations)
validInFutureAttestationsCount := len(validInFutureAttestations)
// Log useful infrormation
log.WithFields(logrus.Fields{
"currentSlot": currentSlot,
"currentEpoch": currentEpoch,
"numValidAtts": validAttestationsCount,
"numDeferredAtts": validInFutureAttestationsCount,
"numDroppedAtts": numDropped,
"attsQueueSize": queuedAttestationsCount,
}).Info("Processing queued attestations for slashing detection")
// Check for attestatinos slashings (double, sourrounding, surrounded votes).
slashings, err := s.checkSlashableAttestations(ctx, currentEpoch, validAttestations)
if err != nil {
log.WithError(err).Error(couldNotCheckSlashableAtt)
return nil
}
// Process attester slashings by verifying their signatures, submitting
// to the beacon node's operations pool, and logging them.
processedAttesterSlashings, err := s.processAttesterSlashings(ctx, slashings)
if err != nil {
log.WithError(err).Error(couldNotProcessAttesterSlashings)
return nil
}
return processedAttesterSlashings
}
// Process queued blocks every time an epoch ticker fires. We retrieve
// these blocks from a queue, then perform double proposal detection.
func (s *Service) processQueuedBlocks(ctx context.Context, slotTicker <-chan primitives.Slot) {

View File

@@ -38,8 +38,8 @@ func TestSlasher_receiveAttestations_OK(t *testing.T) {
}()
firstIndices := []uint64{1, 2, 3}
secondIndices := []uint64{4, 5, 6}
att1 := createAttestationWrapper(t, 1, 2, firstIndices, nil)
att2 := createAttestationWrapper(t, 1, 2, secondIndices, nil)
att1 := createAttestationWrapperEmptySig(t, 1, 2, firstIndices, nil)
att2 := createAttestationWrapperEmptySig(t, 1, 2, secondIndices, nil)
indexedAttsChan <- att1.IndexedAttestation
indexedAttsChan <- att2.IndexedAttestation
cancel()
@@ -65,14 +65,14 @@ func TestService_pruneSlasherDataWithinSlidingWindow_AttestationsPruned(t *testi
// Setup attestations for 2 validators at each epoch for epochs 0, 1, 2, 3.
err := slasherDB.SaveAttestationRecordsForValidators(ctx, []*slashertypes.IndexedAttestationWrapper{
createAttestationWrapper(t, 0, 0, []uint64{0}, bytesutil.PadTo([]byte("0a"), 32)),
createAttestationWrapper(t, 0, 0, []uint64{1}, bytesutil.PadTo([]byte("0b"), 32)),
createAttestationWrapper(t, 0, 1, []uint64{0}, bytesutil.PadTo([]byte("1a"), 32)),
createAttestationWrapper(t, 0, 1, []uint64{1}, bytesutil.PadTo([]byte("1b"), 32)),
createAttestationWrapper(t, 0, 2, []uint64{0}, bytesutil.PadTo([]byte("2a"), 32)),
createAttestationWrapper(t, 0, 2, []uint64{1}, bytesutil.PadTo([]byte("2b"), 32)),
createAttestationWrapper(t, 0, 3, []uint64{0}, bytesutil.PadTo([]byte("3a"), 32)),
createAttestationWrapper(t, 0, 3, []uint64{1}, bytesutil.PadTo([]byte("3b"), 32)),
createAttestationWrapperEmptySig(t, 0, 0, []uint64{0}, bytesutil.PadTo([]byte("0a"), 32)),
createAttestationWrapperEmptySig(t, 0, 0, []uint64{1}, bytesutil.PadTo([]byte("0b"), 32)),
createAttestationWrapperEmptySig(t, 0, 1, []uint64{0}, bytesutil.PadTo([]byte("1a"), 32)),
createAttestationWrapperEmptySig(t, 0, 1, []uint64{1}, bytesutil.PadTo([]byte("1b"), 32)),
createAttestationWrapperEmptySig(t, 0, 2, []uint64{0}, bytesutil.PadTo([]byte("2a"), 32)),
createAttestationWrapperEmptySig(t, 0, 2, []uint64{1}, bytesutil.PadTo([]byte("2b"), 32)),
createAttestationWrapperEmptySig(t, 0, 3, []uint64{0}, bytesutil.PadTo([]byte("3a"), 32)),
createAttestationWrapperEmptySig(t, 0, 3, []uint64{1}, bytesutil.PadTo([]byte("3b"), 32)),
})
require.NoError(t, err)
@@ -93,8 +93,8 @@ func TestService_pruneSlasherDataWithinSlidingWindow_AttestationsPruned(t *testi
// Setup attestations for 2 validators at epoch 4.
err = slasherDB.SaveAttestationRecordsForValidators(ctx, []*slashertypes.IndexedAttestationWrapper{
createAttestationWrapper(t, 0, 4, []uint64{0}, bytesutil.PadTo([]byte("4a"), 32)),
createAttestationWrapper(t, 0, 4, []uint64{1}, bytesutil.PadTo([]byte("4b"), 32)),
createAttestationWrapperEmptySig(t, 0, 4, []uint64{0}, bytesutil.PadTo([]byte("4a"), 32)),
createAttestationWrapperEmptySig(t, 0, 4, []uint64{1}, bytesutil.PadTo([]byte("4b"), 32)),
})
require.NoError(t, err)
@@ -222,7 +222,7 @@ func TestSlasher_receiveAttestations_OnlyValidAttestations(t *testing.T) {
firstIndices := []uint64{1, 2, 3}
secondIndices := []uint64{4, 5, 6}
// Add a valid attestation.
validAtt := createAttestationWrapper(t, 1, 2, firstIndices, nil)
validAtt := createAttestationWrapperEmptySig(t, 1, 2, firstIndices, nil)
indexedAttsChan <- validAtt.IndexedAttestation
// Send an invalid, bad attestation which will not
// pass integrity checks at it has invalid attestation data.

View File

@@ -1,79 +0,0 @@
package slasher
import (
"context"
"github.com/pkg/errors"
slashertypes "github.com/prysmaticlabs/prysm/v4/beacon-chain/slasher/types"
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v4/time/slots"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
// HighestAttestations committed for an input list of validator indices.
func (s *Service) HighestAttestations(
ctx context.Context, validatorIndices []primitives.ValidatorIndex,
) ([]*ethpb.HighestAttestation, error) {
atts, err := s.serviceCfg.Database.HighestAttestations(ctx, validatorIndices)
if err != nil {
return nil, errors.Wrap(err, "could not get highest attestations from database")
}
return atts, nil
}
// IsSlashableBlock checks if an input block header is slashable
// with respect to historical block proposal data.
func (s *Service) IsSlashableBlock(
ctx context.Context, block *ethpb.SignedBeaconBlockHeader,
) (*ethpb.ProposerSlashing, error) {
dataRoot, err := block.Header.HashTreeRoot()
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not get block header hash tree root: %v", err)
}
signedBlockWrapper := &slashertypes.SignedBlockHeaderWrapper{
SignedBeaconBlockHeader: block,
SigningRoot: dataRoot,
}
proposerSlashings, err := s.detectProposerSlashings(ctx, []*slashertypes.SignedBlockHeaderWrapper{signedBlockWrapper})
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not check if proposal is slashable: %v", err)
}
if len(proposerSlashings) == 0 {
return nil, nil
}
return proposerSlashings[0], nil
}
// IsSlashableAttestation checks if an input indexed attestation is slashable
// with respect to historical attestation data.
func (s *Service) IsSlashableAttestation(
ctx context.Context, attestation *ethpb.IndexedAttestation,
) ([]*ethpb.AttesterSlashing, error) {
dataRoot, err := attestation.Data.HashTreeRoot()
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not get attestation data hash tree root: %v", err)
}
indexedAttWrapper := &slashertypes.IndexedAttestationWrapper{
IndexedAttestation: attestation,
SigningRoot: dataRoot,
}
currentEpoch := slots.EpochsSinceGenesis(s.genesisTime)
attesterSlashings, err := s.checkSlashableAttestations(ctx, currentEpoch, []*slashertypes.IndexedAttestationWrapper{indexedAttWrapper})
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not check if attestation is slashable: %v", err)
}
if len(attesterSlashings) == 0 {
// If the incoming attestations are not slashable, we mark them as saved in
// slasher's DB storage to help us with future detection.
if err := s.serviceCfg.Database.SaveAttestationRecordsForValidators(
ctx, []*slashertypes.IndexedAttestationWrapper{indexedAttWrapper},
); err != nil {
return nil, status.Errorf(codes.Internal, "Could not save attestation records to DB: %v", err)
}
return nil, nil
}
return attesterSlashings, nil
}

View File

@@ -1,200 +0,0 @@
package slasher
import (
"context"
"testing"
"time"
dbtest "github.com/prysmaticlabs/prysm/v4/beacon-chain/db/testing"
slashertypes "github.com/prysmaticlabs/prysm/v4/beacon-chain/slasher/types"
"github.com/prysmaticlabs/prysm/v4/config/params"
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v4/testing/assert"
"github.com/prysmaticlabs/prysm/v4/testing/require"
)
func TestIsSlashableBlock(t *testing.T) {
ctx := context.Background()
slasherDB := dbtest.SetupSlasherDB(t)
s := &Service{
serviceCfg: &ServiceConfig{
Database: slasherDB,
},
params: DefaultParams(),
blksQueue: newBlocksQueue(),
}
err := slasherDB.SaveBlockProposals(ctx, []*slashertypes.SignedBlockHeaderWrapper{
createProposalWrapper(t, 2, 3, []byte{1}),
createProposalWrapper(t, 3, 3, []byte{1}),
})
require.NoError(t, err)
tests := []struct {
name string
blockToCheck *slashertypes.SignedBlockHeaderWrapper
shouldBeSlashable bool
}{
{
name: "should not detect if same signing root",
blockToCheck: createProposalWrapper(t, 2, 3, []byte{1}),
shouldBeSlashable: false,
},
{
name: "should not detect if different slot",
blockToCheck: createProposalWrapper(t, 1, 3, []byte{2}),
shouldBeSlashable: false,
},
{
name: "should not detect if different validator index",
blockToCheck: createProposalWrapper(t, 2, 4, []byte{2}),
shouldBeSlashable: false,
},
{
name: "detects differing signing root",
blockToCheck: createProposalWrapper(t, 2, 3, []byte{2}),
shouldBeSlashable: true,
},
{
name: "should detect another slot",
blockToCheck: createProposalWrapper(t, 3, 3, []byte{2}),
shouldBeSlashable: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
proposerSlashing, err := s.IsSlashableBlock(ctx, tt.blockToCheck.SignedBeaconBlockHeader)
require.NoError(t, err)
assert.Equal(t, tt.shouldBeSlashable, proposerSlashing != nil)
})
}
}
func TestIsSlashableAttestation(t *testing.T) {
ctx := context.Background()
slasherDB := dbtest.SetupSlasherDB(t)
currentEpoch := primitives.Epoch(3)
currentTime := time.Now()
totalSlots := uint64(currentEpoch) * uint64(params.BeaconConfig().SlotsPerEpoch)
secondsSinceGenesis := time.Duration(totalSlots * params.BeaconConfig().SecondsPerSlot)
genesisTime := currentTime.Add(-secondsSinceGenesis * time.Second)
s := &Service{
serviceCfg: &ServiceConfig{
Database: slasherDB,
},
params: DefaultParams(),
blksQueue: newBlocksQueue(),
genesisTime: genesisTime,
latestEpochWrittenForValidator: map[primitives.ValidatorIndex]primitives.Epoch{},
}
prevAtts := []*slashertypes.IndexedAttestationWrapper{
createAttestationWrapper(t, 2, 3, []uint64{0}, []byte{1}),
createAttestationWrapper(t, 2, 3, []uint64{1}, []byte{1}),
}
err := slasherDB.SaveAttestationRecordsForValidators(ctx, prevAtts)
require.NoError(t, err)
attesterSlashings, err := s.checkSlashableAttestations(ctx, currentEpoch, prevAtts)
require.NoError(t, err)
require.Equal(t, 0, len(attesterSlashings))
tests := []struct {
name string
attToCheck *slashertypes.IndexedAttestationWrapper
amtSlashable uint64
}{
{
name: "should not detect if same attestation data",
attToCheck: createAttestationWrapper(t, 2, 3, []uint64{1}, []byte{1}),
amtSlashable: 0,
},
{
name: "should not detect if different index",
attToCheck: createAttestationWrapper(t, 0, 3, []uint64{2}, []byte{2}),
amtSlashable: 0,
},
{
name: "should detect double if same index",
attToCheck: createAttestationWrapper(t, 0, 3, []uint64{0}, []byte{2}),
amtSlashable: 1,
},
{
name: "should detect multiple double if multiple same indices",
attToCheck: createAttestationWrapper(t, 0, 3, []uint64{0, 1}, []byte{2}),
amtSlashable: 2,
},
{
name: "should detect multiple surround if multiple same indices",
attToCheck: createAttestationWrapper(t, 1, 4, []uint64{0, 1}, []byte{2}),
amtSlashable: 4,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
attesterSlashings, err = s.IsSlashableAttestation(ctx, tt.attToCheck.IndexedAttestation)
require.NoError(t, err)
assert.Equal(t, tt.amtSlashable, uint64(len(attesterSlashings)))
})
}
}
func TestService_HighestAttestations(t *testing.T) {
ctx := context.Background()
slasherDB := dbtest.SetupSlasherDB(t)
currentEpoch := primitives.Epoch(3)
currentTime := time.Now()
totalSlots := uint64(currentEpoch) * uint64(params.BeaconConfig().SlotsPerEpoch)
secondsSinceGenesis := time.Duration(totalSlots * params.BeaconConfig().SecondsPerSlot)
genesisTime := currentTime.Add(-secondsSinceGenesis * time.Second)
s := &Service{
serviceCfg: &ServiceConfig{
Database: slasherDB,
},
params: DefaultParams(),
blksQueue: newBlocksQueue(),
genesisTime: genesisTime,
}
prevAtts := []*slashertypes.IndexedAttestationWrapper{
createAttestationWrapper(t, 0, 1, []uint64{1}, []byte{1}),
createAttestationWrapper(t, 2, 3, []uint64{2}, []byte{1}),
}
err := slasherDB.SaveAttestationRecordsForValidators(ctx, prevAtts)
require.NoError(t, err)
t.Run("single index not found", func(t *testing.T) {
atts, err := s.HighestAttestations(ctx, []primitives.ValidatorIndex{0})
require.NoError(t, err)
require.Equal(t, 0, len(atts))
})
t.Run("single index case 1", func(t *testing.T) {
atts, err := s.HighestAttestations(ctx, []primitives.ValidatorIndex{1})
require.NoError(t, err)
require.Equal(t, 1, len(atts))
require.DeepEqual(t, &ethpb.HighestAttestation{ValidatorIndex: 1, HighestSourceEpoch: 0, HighestTargetEpoch: 1}, atts[0])
})
t.Run("single index case 2", func(t *testing.T) {
atts, err := s.HighestAttestations(ctx, []primitives.ValidatorIndex{2})
require.NoError(t, err)
require.Equal(t, 1, len(atts))
require.DeepEqual(t, &ethpb.HighestAttestation{ValidatorIndex: 2, HighestSourceEpoch: 2, HighestTargetEpoch: 3}, atts[0])
})
t.Run("multiple indices all found", func(t *testing.T) {
atts, err := s.HighestAttestations(ctx, []primitives.ValidatorIndex{1, 2})
require.NoError(t, err)
require.Equal(t, 2, len(atts))
require.DeepEqual(t, &ethpb.HighestAttestation{ValidatorIndex: 1, HighestSourceEpoch: 0, HighestTargetEpoch: 1}, atts[0])
require.DeepEqual(t, &ethpb.HighestAttestation{ValidatorIndex: 2, HighestSourceEpoch: 2, HighestTargetEpoch: 3}, atts[1])
})
t.Run("multiple indices all not found", func(t *testing.T) {
atts, err := s.HighestAttestations(ctx, []primitives.ValidatorIndex{3, 4})
require.NoError(t, err)
require.Equal(t, 0, len(atts))
})
t.Run("multiple indices some not found", func(t *testing.T) {
atts, err := s.HighestAttestations(ctx, []primitives.ValidatorIndex{1, 4})
require.NoError(t, err)
require.Equal(t, 1, len(atts))
require.DeepEqual(t, &ethpb.HighestAttestation{ValidatorIndex: 1, HighestSourceEpoch: 0, HighestTargetEpoch: 1}, atts[0])
})
}

View File

@@ -43,15 +43,6 @@ type ServiceConfig struct {
ClockWaiter startup.ClockWaiter
}
// SlashingChecker is an interface for defining services that the beacon node may interact with to provide slashing data.
type SlashingChecker interface {
IsSlashableBlock(ctx context.Context, proposal *ethpb.SignedBeaconBlockHeader) (*ethpb.ProposerSlashing, error)
IsSlashableAttestation(ctx context.Context, attestation *ethpb.IndexedAttestation) ([]*ethpb.AttesterSlashing, error)
HighestAttestations(
ctx context.Context, indices []primitives.ValidatorIndex,
) ([]*ethpb.HighestAttestation, error)
}
// Service defining a slasher implementation as part of
// the beacon node, able to detect eth2 slashable offenses.
type Service struct {

View File

@@ -19,8 +19,6 @@ import (
logTest "github.com/sirupsen/logrus/hooks/test"
)
var _ = SlashingChecker(&Service{})
func TestMain(m *testing.M) {
logrus.SetLevel(logrus.DebugLevel)
logrus.SetOutput(io.Discard)

View File

@@ -15,19 +15,19 @@ const (
)
// IndexedAttestationWrapper contains an indexed attestation with its
// signing root to reduce duplicated computation.
// data root to reduce duplicated computation.
type IndexedAttestationWrapper struct {
IndexedAttestation *ethpb.IndexedAttestation
SigningRoot [32]byte
DataRoot [32]byte
}
// AttesterDoubleVote represents a double vote instance
// which is a slashable event for attesters.
type AttesterDoubleVote struct {
Target primitives.Epoch
ValidatorIndex primitives.ValidatorIndex
PrevAttestationWrapper *IndexedAttestationWrapper
AttestationWrapper *IndexedAttestationWrapper
Target primitives.Epoch
ValidatorIndex primitives.ValidatorIndex
Wrapper_1 *IndexedAttestationWrapper
Wrapper_2 *IndexedAttestationWrapper
}
// DoubleBlockProposal containing an incoming and an existing proposal's signing root.
@@ -39,10 +39,10 @@ type DoubleBlockProposal struct {
}
// SignedBlockHeaderWrapper contains an signed beacon block header with its
// signing root to reduce duplicated computation.
// header root to reduce duplicated computation.
type SignedBlockHeaderWrapper struct {
SignedBeaconBlockHeader *ethpb.SignedBeaconBlockHeader
SigningRoot [32]byte
HeaderRoot [32]byte
}
// AttestedEpochForValidator encapsulates a previously attested epoch

View File

@@ -90,6 +90,7 @@ go_library(
"//beacon-chain/startup:go_default_library",
"//beacon-chain/state:go_default_library",
"//beacon-chain/state/stategen:go_default_library",
"//beacon-chain/sync/backfill/coverage:go_default_library",
"//beacon-chain/sync/verify:go_default_library",
"//beacon-chain/verification:go_default_library",
"//cache/lru:go_default_library",
@@ -125,6 +126,7 @@ go_library(
"@com_github_libp2p_go_libp2p//core/peer:go_default_library",
"@com_github_libp2p_go_libp2p//core/protocol:go_default_library",
"@com_github_libp2p_go_libp2p_pubsub//:go_default_library",
"@com_github_libp2p_go_mplex//:go_default_library",
"@com_github_patrickmn_go_cache//:go_default_library",
"@com_github_pkg_errors//:go_default_library",
"@com_github_prometheus_client_golang//prometheus:go_default_library",

View File

@@ -3,9 +3,11 @@ package sync
import (
"bytes"
"errors"
"io"
libp2pcore "github.com/libp2p/go-libp2p/core"
"github.com/libp2p/go-libp2p/core/network"
multiplex "github.com/libp2p/go-mplex"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/p2p"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/p2p/encoder"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/p2p/types"
@@ -98,7 +100,7 @@ func readStatusCodeNoDeadline(stream network.Stream, encoding encoder.NetworkEnc
func isValidStreamError(err error) bool {
// check the error message itself as well as libp2p doesn't currently
// return the correct error type from Close{Read,Write,}.
return err != nil && !errors.Is(err, network.ErrReset) && err.Error() != network.ErrReset.Error()
return err != nil && !isUnwantedError(err)
}
func closeStream(stream network.Stream, log *logrus.Entry) {
@@ -130,3 +132,12 @@ func closeStreamAndWait(stream network.Stream, log *logrus.Entry) {
_err = stream.Close()
_ = _err
}
func isUnwantedError(err error) bool {
for _, e := range []error{network.ErrReset, multiplex.ErrShutdown, io.EOF, types.ErrIODeadline} {
if errors.Is(err, e) || err.Error() == e.Error() {
return true
}
}
return false
}

View File

@@ -29,7 +29,7 @@ const (
skippedMachineTimeout = 10 * staleEpochTimeout
// lookaheadSteps is a limit on how many forward steps are loaded into queue.
// Each step is managed by assigned finite state machine. Must be >= 2.
lookaheadSteps = 8
lookaheadSteps = 4
// noRequiredPeersErrMaxRetries defines number of retries when no required peers are found.
noRequiredPeersErrMaxRetries = 1000
// noRequiredPeersErrRefreshInterval defines interval for which queue will be paused before

View File

@@ -874,7 +874,7 @@ func TestBlocksQueue_onProcessSkippedEvent(t *testing.T) {
t.Run("ready to update machines - constrained mode", func(t *testing.T) {
p := p2pt.NewTestP2P(t)
connectPeers(t, p, []*peerData{
{blocks: makeSequence(500, 628), finalizedEpoch: 16, headSlot: 600},
{blocks: makeSequence(200, 320), finalizedEpoch: 8, headSlot: 300},
}, p.Peers())
fetcher := newBlocksFetcher(ctx, &blocksFetcherConfig{
chain: mc,
@@ -924,7 +924,7 @@ func TestBlocksQueue_onProcessSkippedEvent(t *testing.T) {
t.Run("ready to update machines - unconstrained mode", func(t *testing.T) {
p := p2pt.NewTestP2P(t)
connectPeers(t, p, []*peerData{
{blocks: makeSequence(500, 628), finalizedEpoch: 16, headSlot: 600},
{blocks: makeSequence(200, 320), finalizedEpoch: 8, headSlot: 320},
}, p.Peers())
fetcher := newBlocksFetcher(ctx, &blocksFetcherConfig{
chain: mc,

View File

@@ -16,6 +16,7 @@ import (
"github.com/prysmaticlabs/prysm/v4/beacon-chain/p2p"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/startup"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state/stategen"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/sync/backfill/coverage"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/verification"
)
@@ -170,3 +171,12 @@ func WithVerifierWaiter(v *verification.InitializerWaiter) Option {
return nil
}
}
// WithAvailableBlocker allows the sync package to access the current
// status of backfill.
func WithAvailableBlocker(avb coverage.AvailableBlocker) Option {
return func(s *Service) error {
s.availableBlocker = avb
return nil
}
}

View File

@@ -244,6 +244,9 @@ func (s *Service) registerRPC(baseTopic string, handle rpcHandler) {
}
func logStreamErrors(err error, topic string) {
if isUnwantedError(err) {
return
}
if strings.Contains(topic, p2p.RPCGoodByeTopicV1) {
log.WithError(err).WithField("topic", topic).Trace("Could not decode goodbye stream message")
return

View File

@@ -38,6 +38,13 @@ func (s *Service) beaconBlocksByRangeRPCHandler(ctx context.Context, msg interfa
tracing.AnnotateError(span, err)
return err
}
available := s.validateRangeAvailability(rp)
if !available {
log.Debug("error in validating range availability")
s.writeErrorResponseToStream(responseCodeResourceUnavailable, p2ptypes.ErrResourceUnavailable.Error(), stream)
tracing.AnnotateError(span, err)
return nil
}
blockLimiter, err := s.rateLimiter.topicCollector(string(stream.Protocol()))
if err != nil {
@@ -126,6 +133,11 @@ func validateRangeRequest(r *pb.BeaconBlocksByRangeRequest, current primitives.S
return rp, nil
}
func (s *Service) validateRangeAvailability(rp rangeParams) bool {
startBlock := rp.start
return s.availableBlocker.AvailableBlock(startBlock)
}
func (s *Service) writeBlockBatchToStream(ctx context.Context, batch blockBatch, stream libp2pcore.Stream) error {
ctx, span := trace.StartSpan(ctx, "sync.WriteBlockRangeToStream")
defer span.End()

View File

@@ -64,7 +64,7 @@ func TestRPCBeaconBlocksByRange_RPCHandlerReturnsBlocks(t *testing.T) {
clock := startup.NewClock(time.Unix(0, 0), [32]byte{})
// Start service with 160 as allowed blocks capacity (and almost zero capacity recovery).
r := &Service{cfg: &config{p2p: p1, beaconDB: d, clock: clock, chain: &chainMock.ChainService{}}, rateLimiter: newRateLimiter(p1)}
r := &Service{cfg: &config{p2p: p1, beaconDB: d, clock: clock, chain: &chainMock.ChainService{}}, availableBlocker: mockBlocker{avail: true}, rateLimiter: newRateLimiter(p1)}
pcl := protocol.ID(p2p.RPCBlocksByRangeTopicV1)
topic := string(pcl)
r.rateLimiter.limiterMap[topic] = leakybucket.NewCollector(0.000001, int64(req.Count*10), time.Second, false)
@@ -127,7 +127,7 @@ func TestRPCBeaconBlocksByRange_ReturnCorrectNumberBack(t *testing.T) {
clock := startup.NewClock(time.Unix(0, 0), [32]byte{})
// Start service with 160 as allowed blocks capacity (and almost zero capacity recovery).
r := &Service{cfg: &config{p2p: p1, beaconDB: d, chain: &chainMock.ChainService{}, clock: clock}, rateLimiter: newRateLimiter(p1)}
r := &Service{cfg: &config{p2p: p1, beaconDB: d, chain: &chainMock.ChainService{}, clock: clock}, availableBlocker: mockBlocker{avail: true}, rateLimiter: newRateLimiter(p1)}
pcl := protocol.ID(p2p.RPCBlocksByRangeTopicV1)
topic := string(pcl)
r.rateLimiter.limiterMap[topic] = leakybucket.NewCollector(0.000001, int64(req.Count*10), time.Second, false)
@@ -244,7 +244,8 @@ func TestRPCBeaconBlocksByRange_ReconstructsPayloads(t *testing.T) {
clock: clock,
executionPayloadReconstructor: mockEngine,
},
rateLimiter: newRateLimiter(p1),
rateLimiter: newRateLimiter(p1),
availableBlocker: mockBlocker{avail: true},
}
pcl := protocol.ID(p2p.RPCBlocksByRangeTopicV1)
topic := string(pcl)
@@ -314,7 +315,7 @@ func TestRPCBeaconBlocksByRange_RPCHandlerReturnsSortedBlocks(t *testing.T) {
clock := startup.NewClock(time.Unix(0, 0), [32]byte{})
// Start service with 160 as allowed blocks capacity (and almost zero capacity recovery).
r := &Service{cfg: &config{p2p: p1, beaconDB: d, clock: clock, chain: &chainMock.ChainService{}}, rateLimiter: newRateLimiter(p1)}
r := &Service{cfg: &config{p2p: p1, beaconDB: d, clock: clock, chain: &chainMock.ChainService{}}, availableBlocker: mockBlocker{avail: true}, rateLimiter: newRateLimiter(p1)}
pcl := protocol.ID(p2p.RPCBlocksByRangeTopicV1)
topic := string(pcl)
r.rateLimiter.limiterMap[topic] = leakybucket.NewCollector(0.000001, int64(req.Count*10), time.Second, false)
@@ -380,7 +381,7 @@ func TestRPCBeaconBlocksByRange_ReturnsGenesisBlock(t *testing.T) {
}
clock := startup.NewClock(time.Unix(0, 0), [32]byte{})
r := &Service{cfg: &config{p2p: p1, beaconDB: d, clock: clock, chain: &chainMock.ChainService{}}, rateLimiter: newRateLimiter(p1)}
r := &Service{cfg: &config{p2p: p1, beaconDB: d, clock: clock, chain: &chainMock.ChainService{}}, availableBlocker: mockBlocker{avail: true}, rateLimiter: newRateLimiter(p1)}
pcl := protocol.ID(p2p.RPCBlocksByRangeTopicV1)
topic := string(pcl)
r.rateLimiter.limiterMap[topic] = leakybucket.NewCollector(10000, 10000, time.Second, false)
@@ -472,7 +473,7 @@ func TestRPCBeaconBlocksByRange_RPCHandlerRateLimitOverflow(t *testing.T) {
capacity := int64(flags.Get().BlockBatchLimit * 3)
clock := startup.NewClock(time.Unix(0, 0), [32]byte{})
r := &Service{cfg: &config{p2p: p1, beaconDB: d, chain: &chainMock.ChainService{}, clock: clock}, rateLimiter: newRateLimiter(p1)}
r := &Service{cfg: &config{p2p: p1, beaconDB: d, chain: &chainMock.ChainService{}, clock: clock}, availableBlocker: mockBlocker{avail: true}, rateLimiter: newRateLimiter(p1)}
pcl := protocol.ID(p2p.RPCBlocksByRangeTopicV1)
topic := string(pcl)
@@ -499,7 +500,7 @@ func TestRPCBeaconBlocksByRange_RPCHandlerRateLimitOverflow(t *testing.T) {
capacity := int64(flags.Get().BlockBatchLimit * 3)
clock := startup.NewClock(time.Unix(0, 0), [32]byte{})
r := &Service{cfg: &config{p2p: p1, beaconDB: d, clock: clock, chain: &chainMock.ChainService{}}, rateLimiter: newRateLimiter(p1)}
r := &Service{cfg: &config{p2p: p1, beaconDB: d, clock: clock, chain: &chainMock.ChainService{}}, availableBlocker: mockBlocker{avail: true}, rateLimiter: newRateLimiter(p1)}
pcl := protocol.ID(p2p.RPCBlocksByRangeTopicV1)
topic := string(pcl)
@@ -530,7 +531,7 @@ func TestRPCBeaconBlocksByRange_RPCHandlerRateLimitOverflow(t *testing.T) {
capacity := int64(flags.Get().BlockBatchLimit * flags.Get().BlockBatchLimitBurstFactor)
clock := startup.NewClock(time.Unix(0, 0), [32]byte{})
r := &Service{cfg: &config{p2p: p1, beaconDB: d, clock: clock, chain: &chainMock.ChainService{}}, rateLimiter: newRateLimiter(p1)}
r := &Service{cfg: &config{p2p: p1, beaconDB: d, clock: clock, chain: &chainMock.ChainService{}}, availableBlocker: mockBlocker{avail: true}, rateLimiter: newRateLimiter(p1)}
pcl := protocol.ID(p2p.RPCBlocksByRangeTopicV1)
topic := string(pcl)
r.rateLimiter.limiterMap[topic] = leakybucket.NewCollector(0.000001, capacity, time.Second, false)
@@ -722,7 +723,7 @@ func TestRPCBeaconBlocksByRange_EnforceResponseInvariants(t *testing.T) {
assert.Equal(t, 1, len(p1.BHost.Network().Peers()), "Expected peers to be connected")
clock := startup.NewClock(time.Unix(0, 0), [32]byte{})
r := &Service{cfg: &config{p2p: p1, beaconDB: d, chain: &chainMock.ChainService{}, clock: clock}, rateLimiter: newRateLimiter(p1)}
r := &Service{cfg: &config{p2p: p1, beaconDB: d, chain: &chainMock.ChainService{}, clock: clock}, availableBlocker: mockBlocker{avail: true}, rateLimiter: newRateLimiter(p1)}
r.rateLimiter.limiterMap[string(pcl)] = leakybucket.NewCollector(0.000001, 640, time.Second, false)
req := &ethpb.BeaconBlocksByRangeRequest{
StartSlot: 448,
@@ -891,7 +892,7 @@ func TestRPCBeaconBlocksByRange_FilterBlocks(t *testing.T) {
assert.Equal(t, 1, len(p1.BHost.Network().Peers()), "Expected peers to be connected")
clock := startup.NewClock(time.Unix(0, 0), [32]byte{})
r := &Service{cfg: &config{p2p: p1, beaconDB: d, clock: clock, chain: &chainMock.ChainService{}}, rateLimiter: newRateLimiter(p1)}
r := &Service{cfg: &config{p2p: p1, beaconDB: d, clock: clock, chain: &chainMock.ChainService{}}, availableBlocker: mockBlocker{avail: true}, rateLimiter: newRateLimiter(p1)}
r.rateLimiter.limiterMap[string(pcl)] = leakybucket.NewCollector(0.000001, 640, time.Second, false)
req := &ethpb.BeaconBlocksByRangeRequest{
StartSlot: 1,
@@ -923,7 +924,7 @@ func TestRPCBeaconBlocksByRange_FilterBlocks(t *testing.T) {
assert.Equal(t, 1, len(p1.BHost.Network().Peers()), "Expected peers to be connected")
clock := startup.NewClock(time.Unix(0, 0), [32]byte{})
r := &Service{cfg: &config{p2p: p1, beaconDB: d, clock: clock, chain: &chainMock.ChainService{}}, rateLimiter: newRateLimiter(p1)}
r := &Service{cfg: &config{p2p: p1, beaconDB: d, clock: clock, chain: &chainMock.ChainService{}}, availableBlocker: mockBlocker{avail: true}, rateLimiter: newRateLimiter(p1)}
r.rateLimiter.limiterMap[string(pcl)] = leakybucket.NewCollector(0.000001, 640, time.Second, false)
req := &ethpb.BeaconBlocksByRangeRequest{
StartSlot: 1,
@@ -958,7 +959,7 @@ func TestRPCBeaconBlocksByRange_FilterBlocks(t *testing.T) {
p1.Connect(p2)
assert.Equal(t, 1, len(p1.BHost.Network().Peers()), "Expected peers to be connected")
clock := startup.NewClock(time.Unix(0, 0), [32]byte{})
r := &Service{cfg: &config{p2p: p1, beaconDB: d, chain: &chainMock.ChainService{}, clock: clock}, rateLimiter: newRateLimiter(p1)}
r := &Service{cfg: &config{p2p: p1, beaconDB: d, chain: &chainMock.ChainService{}, clock: clock}, availableBlocker: mockBlocker{avail: true}, rateLimiter: newRateLimiter(p1)}
r.rateLimiter.limiterMap[string(pcl)] = leakybucket.NewCollector(0.000001, 640, time.Second, false)
req := &ethpb.BeaconBlocksByRangeRequest{
StartSlot: 1,
@@ -994,7 +995,7 @@ func TestRPCBeaconBlocksByRange_FilterBlocks(t *testing.T) {
assert.Equal(t, 1, len(p1.BHost.Network().Peers()), "Expected peers to be connected")
clock := startup.NewClock(time.Unix(0, 0), [32]byte{})
r := &Service{cfg: &config{p2p: p1, beaconDB: d, chain: &chainMock.ChainService{}, clock: clock}, rateLimiter: newRateLimiter(p1)}
r := &Service{cfg: &config{p2p: p1, beaconDB: d, chain: &chainMock.ChainService{}, clock: clock}, availableBlocker: mockBlocker{avail: true}, rateLimiter: newRateLimiter(p1)}
r.rateLimiter.limiterMap[string(pcl)] = leakybucket.NewCollector(0.000001, 640, time.Second, false)
req := &ethpb.BeaconBlocksByRangeRequest{
StartSlot: 1,
@@ -1035,7 +1036,7 @@ func TestRPCBeaconBlocksByRange_FilterBlocks(t *testing.T) {
assert.Equal(t, 1, len(p1.BHost.Network().Peers()), "Expected peers to be connected")
clock := startup.NewClock(time.Unix(0, 0), [32]byte{})
r := &Service{cfg: &config{p2p: p1, beaconDB: d, chain: &chainMock.ChainService{}, clock: clock}, rateLimiter: newRateLimiter(p1)}
r := &Service{cfg: &config{p2p: p1, beaconDB: d, chain: &chainMock.ChainService{}, clock: clock}, availableBlocker: mockBlocker{avail: true}, rateLimiter: newRateLimiter(p1)}
r.rateLimiter.limiterMap[string(pcl)] = leakybucket.NewCollector(0.000001, 640, time.Second, false)
req := &ethpb.BeaconBlocksByRangeRequest{
StartSlot: 1,
@@ -1105,3 +1106,11 @@ func TestRPCBeaconBlocksByRange_FilterBlocks_PreviousRoot(t *testing.T) {
// pointer should reference a new root.
require.NotEqual(t, cf.prevRoot, [32]byte{})
}
type mockBlocker struct {
avail bool
}
func (m mockBlocker) AvailableBlock(_ primitives.Slot) bool {
return m.avail
}

View File

@@ -181,7 +181,7 @@ func (s *Service) reValidatePeer(ctx context.Context, id peer.ID) error {
return err
}
// Do not return an error for ping requests.
if err := s.sendPingRequest(ctx, id); err != nil {
if err := s.sendPingRequest(ctx, id); err != nil && !isUnwantedError(err) {
log.WithError(err).Debug("Could not ping peer")
}
return nil
@@ -235,7 +235,7 @@ func (s *Service) statusRPCHandler(ctx context.Context, msg interface{}, stream
resp, err := s.generateErrorResponse(respCode, err.Error())
if err != nil {
log.WithError(err).Debug("Could not generate a response error")
} else if _, err := stream.Write(resp); err != nil {
} else if _, err := stream.Write(resp); err != nil && !isUnwantedError(err) {
// The peer may already be ignoring us, as we disagree on fork version, so log this as debug only.
log.WithError(err).Debug("Could not write to stream")
}
@@ -273,7 +273,7 @@ func (s *Service) respondWithStatus(ctx context.Context, stream network.Stream)
HeadSlot: s.cfg.chain.HeadSlot(),
}
if _, err := stream.Write([]byte{responseCodeSuccess}); err != nil {
if _, err := stream.Write([]byte{responseCodeSuccess}); err != nil && !isUnwantedError(err) {
log.WithError(err).Debug("Could not write to stream")
}
_, err = s.cfg.p2p.Encoding().EncodeWithMaxLength(stream, resp)

View File

@@ -33,6 +33,7 @@ import (
"github.com/prysmaticlabs/prysm/v4/beacon-chain/p2p"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/startup"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state/stategen"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/sync/backfill/coverage"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/verification"
lruwrpr "github.com/prysmaticlabs/prysm/v4/cache/lru"
"github.com/prysmaticlabs/prysm/v4/config/params"
@@ -155,6 +156,7 @@ type Service struct {
initialSyncComplete chan struct{}
verifierWaiter *verification.InitializerWaiter
newBlobVerifier verification.NewBlobVerifier
availableBlocker coverage.AvailableBlocker
}
// NewService initializes new regular sync service.

View File

@@ -232,12 +232,28 @@ var (
Usage: "Sets the minimum number of peers that a node will attempt to peer with that are subscribed to a subnet.",
Value: 6,
}
// SuggestedFeeRecipient specifies the fee recipient for the transaction fees.
SuggestedFeeRecipient = &cli.StringFlag{
Name: "suggested-fee-recipient",
Usage: "Post bellatrix, this address will receive the transaction fees produced by any blocks from this node. Default to junk whilst bellatrix is in development state. Validator client can override this value through the preparebeaconproposer api.",
Value: params.BeaconConfig().EthBurnAddressHex,
}
// ProposerSettingsFlag defines the path or URL to a file with proposer config.
ProposerSettingsFlag = &cli.StringFlag{
Name: "proposer-settings-file",
Usage: `Sets path to a YAML or JSON file containing validator settings used when proposing blocks such as
fee recipient and gas limit. File format found in docs.`,
Value: "",
}
// ProposerSettingsURLFlag defines the path or URL to a file with proposer config.
ProposerSettingsURLFlag = &cli.StringFlag{
Name: "proposer-settings-url",
Usage: `Sets URL to a REST endpoint containing validator settings used when proposing blocks such as
fee recipient and gas limit. File format found in docs`,
Value: "",
}
// TerminalTotalDifficultyOverride specifies the total difficulty to manual overrides the `TERMINAL_TOTAL_DIFFICULTY` parameter.
TerminalTotalDifficultyOverride = &cli.StringFlag{
Name: "terminal-total-difficulty-override",

View File

@@ -72,6 +72,8 @@ var appFlags = []cli.Flag{
flags.Eth1HeaderReqLimit,
flags.MinPeersPerSubnet,
flags.SuggestedFeeRecipient,
flags.ProposerSettingsFlag,
flags.ProposerSettingsURLFlag,
flags.TerminalTotalDifficultyOverride,
flags.TerminalBlockHashOverride,
flags.TerminalBlockHashActivationEpochOverride,

View File

@@ -130,6 +130,9 @@ var appHelpFlagGroups = []flagGroup{
flags.SlasherDirFlag,
flags.LocalBlockValueBoost,
flags.JwtId,
flags.SuggestedFeeRecipient,
flags.ProposerSettingsFlag,
flags.ProposerSettingsURLFlag,
checkpoint.BlockPath,
checkpoint.StatePath,
checkpoint.RemoteURL,
@@ -145,7 +148,6 @@ var appHelpFlagGroups = []flagGroup{
{
Name: "merge",
Flags: []cli.Flag{
flags.SuggestedFeeRecipient,
flags.TerminalTotalDifficultyOverride,
flags.TerminalBlockHashOverride,
flags.TerminalBlockHashActivationEpochOverride,

View File

@@ -26,7 +26,7 @@ go_library(
"//encoding/bytesutil:go_default_library",
"//io/file:go_default_library",
"//io/prompt:go_default_library",
"//proto/prysm/v1alpha1/validator-client:go_default_library",
"//proto/prysm/config:go_default_library",
"//runtime/tos:go_default_library",
"@com_github_ethereum_go_ethereum//common:go_default_library",
"@com_github_logrusorgru_aurora//:go_default_library",

View File

@@ -14,7 +14,7 @@ import (
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
"github.com/prysmaticlabs/prysm/v4/io/file"
"github.com/prysmaticlabs/prysm/v4/io/prompt"
validatorpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1/validator-client"
proposersettings "github.com/prysmaticlabs/prysm/v4/proto/prysm/config"
log "github.com/sirupsen/logrus"
"github.com/urfave/cli/v2"
"go.opencensus.io/trace"
@@ -68,25 +68,25 @@ func getProposerSettings(c *cli.Context, r io.Reader) error {
if c.IsSet(ProposerSettingsOutputFlag.Name) {
log.Infof("The default fee recipient is set to %s", defaultFeeRecipient)
var builderSettings *validatorpb.BuilderConfig
var builderSettings *proposersettings.BuilderConfig
if c.Bool(WithBuilderFlag.Name) {
builderSettings = &validatorpb.BuilderConfig{
builderSettings = &proposersettings.BuilderConfig{
Enabled: true,
GasLimit: validatorType.Uint64(params.BeaconConfig().DefaultBuilderGasLimit),
}
} else {
log.Infof("Default builder settings can be included with the `--%s` flag", WithBuilderFlag.Name)
}
proposerConfig := make(map[string]*validatorpb.ProposerOptionPayload)
proposerConfig := make(map[string]*proposersettings.ProposerOptionPayload)
for index, val := range validators {
proposerConfig[val] = &validatorpb.ProposerOptionPayload{
proposerConfig[val] = &proposersettings.ProposerOptionPayload{
FeeRecipient: feeRecipients[index],
Builder: builderSettings,
}
}
fileConfig := &validatorpb.ProposerSettingsPayload{
fileConfig := &proposersettings.ProposerSettingsPayload{
ProposerConfig: proposerConfig,
DefaultConfig: &validatorpb.ProposerOptionPayload{
DefaultConfig: &proposersettings.ProposerOptionPayload{
FeeRecipient: defaultFeeRecipient,
Builder: builderSettings,
},

View File

@@ -1,3 +1,5 @@
load("@prysm//tools/go:def.bzl", "go_library")
config_setting(
name = "mainnet",
flag_values = {
@@ -11,3 +13,15 @@ config_setting(
"//proto:network": "minimal",
},
)
go_library(
name = "go_default_library",
srcs = ["util.go"],
importpath = "github.com/prysmaticlabs/prysm/v4/config",
visibility = ["//visibility:public"],
deps = [
"@com_github_pkg_errors//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
"@io_k8s_apimachinery//pkg/util/yaml:go_default_library",
],
)

View File

@@ -12,37 +12,6 @@ var (
Usage: deprecatedUsage,
Hidden: true,
}
deprecatedDisableVecHTR = &cli.BoolFlag{
Name: "disable-vectorized-htr",
Usage: deprecatedUsage,
Hidden: true,
}
deprecatedEnableReorgLateBlocks = &cli.BoolFlag{
Name: "enable-reorg-late-blocks",
Usage: deprecatedUsage,
Hidden: true,
}
deprecatedDisableGossipBatchAggregation = &cli.BoolFlag{
Name: "disable-gossip-batch-aggregation",
Usage: deprecatedUsage,
Hidden: true,
}
deprecatedBuildBlockParallel = &cli.BoolFlag{
Name: "build-block-parallel",
Usage: deprecatedUsage,
Hidden: true,
}
deprecatedEnableRegistrationCache = &cli.BoolFlag{
Name: "enable-registration-cache",
Usage: deprecatedUsage,
Hidden: true,
}
deprecatedAggregateParallel = &cli.BoolFlag{
Name: "aggregate-parallel",
Usage: deprecatedUsage,
Hidden: true,
}
deprecatedEnableOptionalEngineMethods = &cli.BoolFlag{
Name: "enable-optional-engine-methods",
Usage: deprecatedUsage,
@@ -83,12 +52,6 @@ var (
// Deprecated flags for both the beacon node and validator client.
var deprecatedFlags = []cli.Flag{
exampleDeprecatedFeatureFlag,
deprecatedDisableVecHTR,
deprecatedEnableReorgLateBlocks,
deprecatedDisableGossipBatchAggregation,
deprecatedBuildBlockParallel,
deprecatedEnableRegistrationCache,
deprecatedAggregateParallel,
deprecatedEnableOptionalEngineMethods,
deprecatedDisableBuildBlockParallel,
deprecatedDisableReorgLateBlocks,

View File

@@ -27,6 +27,8 @@ var placeholderFields = []string{
"EIP6110_FORK_VERSION",
"EIP7002_FORK_EPOCH",
"EIP7002_FORK_VERSION",
"EIP7594_FORK_EPOCH",
"EIP7594_FORK_VERSION",
"MAX_BLOBS_PER_BLOCK",
"REORG_HEAD_WEIGHT_THRESHOLD",
"UPDATE_TIMEOUT",

View File

@@ -3,16 +3,17 @@ load("@prysm//tools/go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = ["proposer_settings.go"],
importpath = "github.com/prysmaticlabs/prysm/v4/config/validator/service",
importpath = "github.com/prysmaticlabs/prysm/v4/config/proposer",
visibility = ["//visibility:public"],
deps = [
"//config/fieldparams:go_default_library",
"//consensus-types/validator:go_default_library",
"//encoding/bytesutil:go_default_library",
"//proto/prysm/v1alpha1/validator-client:go_default_library",
"//proto/prysm/config:go_default_library",
"@com_github_ethereum_go_ethereum//common:go_default_library",
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
"@com_github_pkg_errors//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
],
)

View File

@@ -1,4 +1,4 @@
package validator_service_config
package proposer
import (
"fmt"
@@ -9,11 +9,12 @@ import (
fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams"
"github.com/prysmaticlabs/prysm/v4/consensus-types/validator"
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
validatorpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1/validator-client"
proposersettings "github.com/prysmaticlabs/prysm/v4/proto/prysm/config"
log "github.com/sirupsen/logrus"
)
// ToSettings converts struct to ProposerSettings
func ToSettings(ps *validatorpb.ProposerSettingsPayload) (*ProposerSettings, error) {
func ToSettings(ps *proposersettings.ProposerSettingsPayload) (*ProposerSettings, error) {
settings := &ProposerSettings{}
if ps.ProposerConfig != nil {
settings.ProposeConfig = make(map[[fieldparams.BLSPubkeyLength]byte]*ProposerOption)
@@ -60,7 +61,7 @@ type BuilderConfig struct {
}
// ToBuilderConfig converts protobuf to a builder config used in inmemory storage
func ToBuilderConfig(from *validatorpb.BuilderConfig) *BuilderConfig {
func ToBuilderConfig(from *proposersettings.BuilderConfig) *BuilderConfig {
if from == nil {
return nil
}
@@ -78,7 +79,7 @@ func ToBuilderConfig(from *validatorpb.BuilderConfig) *BuilderConfig {
}
// ProposerSettings is a Prysm internal representation of the fee recipient config on the validator client.
// validatorpb.ProposerSettingsPayload maps to ProposerSettings on import through the CLI.
// proposersettings.ProposerSettingsPayload maps to ProposerSettings on import through the CLI.
type ProposerSettings struct {
ProposeConfig map[[fieldparams.BLSPubkeyLength]byte]*ProposerOption
DefaultConfig *ProposerOption
@@ -94,15 +95,15 @@ func (settings *ProposerSettings) ShouldBeSaved() bool {
}
// ToPayload converts struct to ProposerSettingsPayload
func (ps *ProposerSettings) ToPayload() *validatorpb.ProposerSettingsPayload {
func (ps *ProposerSettings) ToPayload() *proposersettings.ProposerSettingsPayload {
if ps == nil {
return nil
}
payload := &validatorpb.ProposerSettingsPayload{}
payload := &proposersettings.ProposerSettingsPayload{}
if ps.ProposeConfig != nil {
payload.ProposerConfig = make(map[string]*validatorpb.ProposerOptionPayload)
payload.ProposerConfig = make(map[string]*proposersettings.ProposerOptionPayload)
for key, option := range ps.ProposeConfig {
p := &validatorpb.ProposerOptionPayload{}
p := &proposersettings.ProposerOptionPayload{}
if option.FeeRecipientConfig != nil {
p.FeeRecipient = option.FeeRecipientConfig.FeeRecipient.Hex()
}
@@ -113,7 +114,7 @@ func (ps *ProposerSettings) ToPayload() *validatorpb.ProposerSettingsPayload {
}
}
if ps.DefaultConfig != nil {
p := &validatorpb.ProposerOptionPayload{}
p := &proposersettings.ProposerOptionPayload{}
if ps.DefaultConfig.FeeRecipientConfig != nil {
p.FeeRecipient = ps.DefaultConfig.FeeRecipientConfig.FeeRecipient.Hex()
}
@@ -183,11 +184,11 @@ func (bc *BuilderConfig) Clone() *BuilderConfig {
}
// ToPayload converts Builder Config to the protobuf object
func (bc *BuilderConfig) ToPayload() *validatorpb.BuilderConfig {
func (bc *BuilderConfig) ToPayload() *proposersettings.BuilderConfig {
if bc == nil {
return nil
}
config := &validatorpb.BuilderConfig{}
config := &proposersettings.BuilderConfig{}
config.Enabled = bc.Enabled
var relays []string
if bc.Relays != nil {
@@ -213,3 +214,30 @@ func (po *ProposerOption) Clone() *ProposerOption {
}
return p
}
func VerifyOption(key string, option *proposersettings.ProposerOptionPayload) error {
if option == nil {
return fmt.Errorf("fee recipient is required for proposer %s", key)
}
if !common.IsHexAddress(option.FeeRecipient) {
return errors.New("fee recipient is not a valid eth1 address")
}
if err := WarnNonChecksummedAddress(option.FeeRecipient); err != nil {
return err
}
return nil
}
func WarnNonChecksummedAddress(feeRecipient string) error {
mixedcaseAddress, err := common.NewMixedcaseAddressFromString(feeRecipient)
if err != nil {
return errors.Wrapf(err, "could not decode fee recipient %s", feeRecipient)
}
if !mixedcaseAddress.ValidChecksum() {
log.Warnf("Fee recipient %s is not a checksum Ethereum address. "+
"The checksummed address is %s and will be used as the fee recipient. "+
"We recommend using a mixed-case address (checksum) "+
"to prevent spelling mistakes in your fee recipient Ethereum address", feeRecipient, mixedcaseAddress.Address().Hex())
}
return nil
}

View File

@@ -1,4 +1,4 @@
package validator_service_config
package proposer
import (
"testing"

65
config/util.go Normal file
View File

@@ -0,0 +1,65 @@
package config
import (
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"os"
"path/filepath"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
"k8s.io/apimachinery/pkg/util/yaml"
)
func UnmarshalFromURL(ctx context.Context, from string, to interface{}) error {
u, err := url.ParseRequestURI(from)
if err != nil {
return err
}
if u.Scheme == "" || u.Host == "" {
return fmt.Errorf("invalid URL: %s", from)
}
req, reqerr := http.NewRequestWithContext(ctx, http.MethodGet, from, nil)
if reqerr != nil {
return errors.Wrap(reqerr, "failed to create http request")
}
req.Header.Set("Content-Type", "application/json")
resp, resperr := http.DefaultClient.Do(req)
if resperr != nil {
return errors.Wrap(resperr, "failed to send http request")
}
defer func(Body io.ReadCloser) {
err = Body.Close()
if err != nil {
log.WithError(err).Error("failed to close response body")
}
}(resp.Body)
if resp.StatusCode != http.StatusOK {
return errors.Errorf("http request to %v failed with status code %d", from, resp.StatusCode)
}
if decodeerr := json.NewDecoder(resp.Body).Decode(&to); decodeerr != nil {
return errors.Wrap(decodeerr, "failed to decode http response")
}
return nil
}
func UnmarshalFromFile(ctx context.Context, from string, to interface{}) error {
if ctx == nil {
return errors.New("node: nil context passed to unmarshalFromFile")
}
cleanpath := filepath.Clean(from)
b, err := os.ReadFile(cleanpath)
if err != nil {
return errors.Wrap(err, "failed to open file")
}
if err := yaml.Unmarshal(b, to); err != nil {
return errors.Wrap(err, "failed to unmarshal yaml file")
}
return nil
}

2
go.mod
View File

@@ -47,6 +47,7 @@ require (
github.com/libp2p/go-libp2p v0.32.1
github.com/libp2p/go-libp2p-mplex v0.9.0
github.com/libp2p/go-libp2p-pubsub v0.10.0
github.com/libp2p/go-mplex v0.7.0
github.com/logrusorgru/aurora v2.0.3+incompatible
github.com/manifoldco/promptui v0.7.0
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b
@@ -171,7 +172,6 @@ require (
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
github.com/libp2p/go-flow-metrics v0.1.0 // indirect
github.com/libp2p/go-libp2p-asn-util v0.4.1 // indirect
github.com/libp2p/go-mplex v0.7.0 // indirect
github.com/libp2p/go-msgio v0.3.0 // indirect
github.com/libp2p/go-nat v0.2.0 // indirect
github.com/libp2p/go-netroute v0.2.1 // indirect

View File

@@ -215,15 +215,17 @@ message Withdrawal {
message BlobsBundle {
// The KZG commitments of the blobs.
repeated bytes kzg_commitments = 1 [(ethereum.eth.ext.ssz_size) = "?,48", (ethereum.eth.ext.ssz_max) = "max_blob_commitments.size"];
// The proofs of the blobs.
repeated bytes proofs = 2 [(ethereum.eth.ext.ssz_size) = "?,48", (ethereum.eth.ext.ssz_max) = "max_blob_commitments.size"];
// The blobs itself.
repeated bytes blobs = 3 [(ethereum.eth.ext.ssz_size) = "?,131072", (ethereum.eth.ext.ssz_max) = "max_blob_commitments.size"];
repeated bytes blobs = 3 [(ethereum.eth.ext.ssz_size) = "?,blob.size", (ethereum.eth.ext.ssz_max) = "max_blob_commitments.size"];
}
// Blob contains the data that is to be committed on chain.
message Blob {
// Each blob consists of `BLS_FIELD_ELEMENT`(32) multiplies `FIELD_ELEMENTS_PER_BLOB`(4096)
// The blob bytes.
bytes data = 1 [(ethereum.eth.ext.ssz_size) = "blob.size"];
}

View File

@@ -331,7 +331,7 @@ message BeaconBlockBodyBellatrix {
// At most MAX_VOLUNTARY_EXITS.
repeated v1.SignedVoluntaryExit voluntary_exits = 8 [(ethereum.eth.ext.ssz_max) = "16"];
// Sync aggregate object to track sync committee votes for light client support.
// Sync aggregate object to track sync committee votes for light client support.
v1.SyncAggregate sync_aggregate = 9;
// Execution payload: the embedded execution payload of the block [New in Bellatrix]
@@ -523,7 +523,7 @@ message BeaconBlockBodyDeneb {
// At most MAX_BLS_TO_EXECUTION_CHANGES. New in Capella network upgrade.
repeated SignedBLSToExecutionChange bls_to_execution_changes = 11 [(ethereum.eth.ext.ssz_max) = "16"];
// At most MAX_BLOBS_PER_BLOCK. New in Deneb network upgrade.
// At most MAX_BLOB_COMMITMENTS_PER_BLOCK. New in Deneb network upgrade.
repeated bytes blob_kzg_commitments = 12 [(ethereum.eth.ext.ssz_size) = "?,48", (ethereum.eth.ext.ssz_max) = "max_blob_commitments.size"];
}

View File

@@ -0,0 +1,48 @@
##############################################################################
# Common
##############################################################################
load("@rules_proto//proto:defs.bzl", "proto_library")
##############################################################################
# Go
##############################################################################
# gazelle:ignore
load("@io_bazel_rules_go//go:def.bzl", "go_library")
load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library")
proto_library(
name = "proposersettings_proto",
srcs = ["proposer_settings.proto"],
visibility = ["//visibility:public"],
deps = [
"//proto/eth/ext:proto",
"@com_google_protobuf//:any_proto",
"@com_google_protobuf//:descriptor_proto",
"@com_google_protobuf//:empty_proto",
"@com_google_protobuf//:timestamp_proto",
"@googleapis//google/api:annotations_proto",
],
)
go_proto_library(
name = "proposersettings_go_proto",
compilers = [
"@com_github_prysmaticlabs_protoc_gen_go_cast//:go_cast_grpc",
],
importpath = "github.com/prysmaticlabs/prysm/v4/proto/prysm/config",
proto = ":proposersettings_proto",
visibility = ["//visibility:public"],
deps = [
"//consensus-types/primitives:go_default_library",
"//consensus-types/validator:go_default_library",
"//proto/eth/ext:go_default_library",
],
)
go_library(
name = "go_default_library",
embed = [":proposersettings_go_proto"],
importpath = "github.com/prysmaticlabs/prysm/v4/proto/prysm/config",
visibility = ["//visibility:public"],
)

350
proto/prysm/config/proposer_settings.pb.go generated Executable file
View File

@@ -0,0 +1,350 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc v4.25.1
// source: proto/prysm/config/proposer_settings.proto
package proposersettings
import (
reflect "reflect"
sync "sync"
github_com_prysmaticlabs_prysm_v4_consensus_types_validator "github.com/prysmaticlabs/prysm/v4/consensus-types/validator"
_ "github.com/prysmaticlabs/prysm/v4/proto/eth/ext"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type ProposerOptionPayload struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
FeeRecipient string `protobuf:"bytes,1,opt,name=fee_recipient,json=feeRecipient,proto3" json:"fee_recipient,omitempty"`
Builder *BuilderConfig `protobuf:"bytes,2,opt,name=builder,proto3" json:"builder,omitempty"`
}
func (x *ProposerOptionPayload) Reset() {
*x = ProposerOptionPayload{}
if protoimpl.UnsafeEnabled {
mi := &file_proto_prysm_config_proposer_settings_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ProposerOptionPayload) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ProposerOptionPayload) ProtoMessage() {}
func (x *ProposerOptionPayload) ProtoReflect() protoreflect.Message {
mi := &file_proto_prysm_config_proposer_settings_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ProposerOptionPayload.ProtoReflect.Descriptor instead.
func (*ProposerOptionPayload) Descriptor() ([]byte, []int) {
return file_proto_prysm_config_proposer_settings_proto_rawDescGZIP(), []int{0}
}
func (x *ProposerOptionPayload) GetFeeRecipient() string {
if x != nil {
return x.FeeRecipient
}
return ""
}
func (x *ProposerOptionPayload) GetBuilder() *BuilderConfig {
if x != nil {
return x.Builder
}
return nil
}
type BuilderConfig struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"`
GasLimit github_com_prysmaticlabs_prysm_v4_consensus_types_validator.Uint64 `protobuf:"varint,2,opt,name=gas_limit,json=gasLimit,proto3" json:"gas_limit,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v4/consensus-types/validator.Uint64"`
Relays []string `protobuf:"bytes,3,rep,name=relays,proto3" json:"relays,omitempty"`
}
func (x *BuilderConfig) Reset() {
*x = BuilderConfig{}
if protoimpl.UnsafeEnabled {
mi := &file_proto_prysm_config_proposer_settings_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *BuilderConfig) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*BuilderConfig) ProtoMessage() {}
func (x *BuilderConfig) ProtoReflect() protoreflect.Message {
mi := &file_proto_prysm_config_proposer_settings_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use BuilderConfig.ProtoReflect.Descriptor instead.
func (*BuilderConfig) Descriptor() ([]byte, []int) {
return file_proto_prysm_config_proposer_settings_proto_rawDescGZIP(), []int{1}
}
func (x *BuilderConfig) GetEnabled() bool {
if x != nil {
return x.Enabled
}
return false
}
func (x *BuilderConfig) GetGasLimit() github_com_prysmaticlabs_prysm_v4_consensus_types_validator.Uint64 {
if x != nil {
return x.GasLimit
}
return github_com_prysmaticlabs_prysm_v4_consensus_types_validator.Uint64(0)
}
func (x *BuilderConfig) GetRelays() []string {
if x != nil {
return x.Relays
}
return nil
}
type ProposerSettingsPayload struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
ProposerConfig map[string]*ProposerOptionPayload `protobuf:"bytes,1,rep,name=proposer_config,json=proposerConfig,proto3" json:"proposer_config,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
DefaultConfig *ProposerOptionPayload `protobuf:"bytes,2,opt,name=default_config,json=defaultConfig,proto3" json:"default_config,omitempty"`
}
func (x *ProposerSettingsPayload) Reset() {
*x = ProposerSettingsPayload{}
if protoimpl.UnsafeEnabled {
mi := &file_proto_prysm_config_proposer_settings_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ProposerSettingsPayload) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ProposerSettingsPayload) ProtoMessage() {}
func (x *ProposerSettingsPayload) ProtoReflect() protoreflect.Message {
mi := &file_proto_prysm_config_proposer_settings_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ProposerSettingsPayload.ProtoReflect.Descriptor instead.
func (*ProposerSettingsPayload) Descriptor() ([]byte, []int) {
return file_proto_prysm_config_proposer_settings_proto_rawDescGZIP(), []int{2}
}
func (x *ProposerSettingsPayload) GetProposerConfig() map[string]*ProposerOptionPayload {
if x != nil {
return x.ProposerConfig
}
return nil
}
func (x *ProposerSettingsPayload) GetDefaultConfig() *ProposerOptionPayload {
if x != nil {
return x.DefaultConfig
}
return nil
}
var File_proto_prysm_config_proposer_settings_proto protoreflect.FileDescriptor
var file_proto_prysm_config_proposer_settings_proto_rawDesc = []byte{
0x0a, 0x2a, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x63, 0x6f,
0x6e, 0x66, 0x69, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x73, 0x65,
0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x65, 0x74,
0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x1a, 0x1b, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x65, 0x78, 0x74, 0x2f, 0x6f, 0x70, 0x74,
0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x76, 0x0a, 0x15, 0x50, 0x72,
0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c,
0x6f, 0x61, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x66, 0x65, 0x65, 0x5f, 0x72, 0x65, 0x63, 0x69, 0x70,
0x69, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x66, 0x65, 0x65, 0x52,
0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x38, 0x0a, 0x07, 0x62, 0x75, 0x69, 0x6c,
0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x65, 0x74, 0x68, 0x65,
0x72, 0x65, 0x75, 0x6d, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x42, 0x75, 0x69, 0x6c,
0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x07, 0x62, 0x75, 0x69, 0x6c, 0x64,
0x65, 0x72, 0x22, 0xa6, 0x01, 0x0a, 0x0d, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x43, 0x6f,
0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18,
0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x63,
0x0a, 0x09, 0x67, 0x61, 0x73, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28,
0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f,
0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f,
0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x34, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73,
0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74,
0x6f, 0x72, 0x2e, 0x55, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x52, 0x08, 0x67, 0x61, 0x73, 0x4c, 0x69,
0x6d, 0x69, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x73, 0x18, 0x03, 0x20,
0x03, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x73, 0x22, 0xba, 0x02, 0x0a, 0x17,
0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73,
0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x65, 0x0a, 0x0f, 0x70, 0x72, 0x6f, 0x70, 0x6f,
0x73, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
0x32, 0x3c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x63, 0x6f, 0x6e, 0x66,
0x69, 0x67, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69,
0x6e, 0x67, 0x73, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f,
0x73, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0e,
0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x4d,
0x0a, 0x0e, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75,
0x6d, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65,
0x72, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x0d,
0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x1a, 0x69, 0x0a,
0x13, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x45,
0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x3c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18,
0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d,
0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72,
0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x05, 0x76,
0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x99, 0x01, 0x0a, 0x13, 0x6f, 0x72, 0x67,
0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
0x42, 0x15, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e,
0x67, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x45, 0x67, 0x69, 0x74, 0x68, 0x75,
0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c,
0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x34, 0x2f, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x3b,
0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73,
0xaa, 0x02, 0x0f, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x43, 0x6f, 0x6e, 0x66,
0x69, 0x67, 0xca, 0x02, 0x0f, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x5c, 0x63, 0x6f,
0x6e, 0x66, 0x69, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_proto_prysm_config_proposer_settings_proto_rawDescOnce sync.Once
file_proto_prysm_config_proposer_settings_proto_rawDescData = file_proto_prysm_config_proposer_settings_proto_rawDesc
)
func file_proto_prysm_config_proposer_settings_proto_rawDescGZIP() []byte {
file_proto_prysm_config_proposer_settings_proto_rawDescOnce.Do(func() {
file_proto_prysm_config_proposer_settings_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_prysm_config_proposer_settings_proto_rawDescData)
})
return file_proto_prysm_config_proposer_settings_proto_rawDescData
}
var file_proto_prysm_config_proposer_settings_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
var file_proto_prysm_config_proposer_settings_proto_goTypes = []interface{}{
(*ProposerOptionPayload)(nil), // 0: ethereum.config.ProposerOptionPayload
(*BuilderConfig)(nil), // 1: ethereum.config.BuilderConfig
(*ProposerSettingsPayload)(nil), // 2: ethereum.config.ProposerSettingsPayload
nil, // 3: ethereum.config.ProposerSettingsPayload.ProposerConfigEntry
}
var file_proto_prysm_config_proposer_settings_proto_depIdxs = []int32{
1, // 0: ethereum.config.ProposerOptionPayload.builder:type_name -> ethereum.config.BuilderConfig
3, // 1: ethereum.config.ProposerSettingsPayload.proposer_config:type_name -> ethereum.config.ProposerSettingsPayload.ProposerConfigEntry
0, // 2: ethereum.config.ProposerSettingsPayload.default_config:type_name -> ethereum.config.ProposerOptionPayload
0, // 3: ethereum.config.ProposerSettingsPayload.ProposerConfigEntry.value:type_name -> ethereum.config.ProposerOptionPayload
4, // [4:4] is the sub-list for method output_type
4, // [4:4] is the sub-list for method input_type
4, // [4:4] is the sub-list for extension type_name
4, // [4:4] is the sub-list for extension extendee
0, // [0:4] is the sub-list for field type_name
}
func init() { file_proto_prysm_config_proposer_settings_proto_init() }
func file_proto_prysm_config_proposer_settings_proto_init() {
if File_proto_prysm_config_proposer_settings_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_proto_prysm_config_proposer_settings_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ProposerOptionPayload); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_proto_prysm_config_proposer_settings_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*BuilderConfig); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_proto_prysm_config_proposer_settings_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ProposerSettingsPayload); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_proto_prysm_config_proposer_settings_proto_rawDesc,
NumEnums: 0,
NumMessages: 4,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_proto_prysm_config_proposer_settings_proto_goTypes,
DependencyIndexes: file_proto_prysm_config_proposer_settings_proto_depIdxs,
MessageInfos: file_proto_prysm_config_proposer_settings_proto_msgTypes,
}.Build()
File_proto_prysm_config_proposer_settings_proto = out.File
file_proto_prysm_config_proposer_settings_proto_rawDesc = nil
file_proto_prysm_config_proposer_settings_proto_goTypes = nil
file_proto_prysm_config_proposer_settings_proto_depIdxs = nil
}

View File

@@ -0,0 +1,30 @@
syntax = "proto3";
package ethereum.config;
import "proto/eth/ext/options.proto";
option csharp_namespace = "Ethereum.Config";
option go_package = "github.com/prysmaticlabs/prysm/v4/proto/prysm/config;proposersettings";
option java_multiple_files = true;
option java_outer_classname = "ProposerSettingsProto";
option java_package = "org.ethereum.config";
option php_namespace = "Ethereum\\config";
// ProposerOptionPayload is a property of ProposerSettingsPayload
message ProposerOptionPayload {
string fee_recipient = 1;
BuilderConfig builder = 2;
}
// BuilderConfig is a property of ProposerOptionPayload
message BuilderConfig {
bool enabled = 1;
uint64 gas_limit = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v4/consensus-types/validator.Uint64"];
repeated string relays = 3;
}
// ProposerSettingsPayload is used to unmarshal files sent from the validator flag as well as safe to bolt db bucket
message ProposerSettingsPayload {
map<string, ProposerOptionPayload> proposer_config = 1;
ProposerOptionPayload default_config = 2;
}

View File

@@ -35,8 +35,8 @@ proto_library(
"@com_google_protobuf//:any_proto",
"@com_google_protobuf//:descriptor_proto",
"@com_google_protobuf//:empty_proto",
"@com_google_protobuf//:wrappers_proto",
"@com_google_protobuf//:timestamp_proto",
"@com_google_protobuf//:wrappers_proto",
"@googleapis//google/api:annotations_proto",
],
)
@@ -130,6 +130,7 @@ ssz_gen_marshal(
"BlobSidecar",
"BlobSidecars",
"BlobIdentifier",
"DepositSnapshot",
],
)
@@ -155,8 +156,8 @@ go_proto_library(
"@org_golang_google_protobuf//runtime/protoimpl:go_default_library",
"@org_golang_google_protobuf//types/descriptorpb:go_default_library",
"@org_golang_google_protobuf//types/known/emptypb:go_default_library",
"@org_golang_google_protobuf//types/known/wrapperspb:go_default_library",
"@org_golang_google_protobuf//types/known/timestamppb:go_default_library",
"@org_golang_google_protobuf//types/known/wrapperspb:go_default_library",
],
)
@@ -176,8 +177,8 @@ go_proto_library(
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
"@googleapis//google/api:annotations_go_proto",
"@io_bazel_rules_go//proto/wkt:descriptor_go_proto",
"@io_bazel_rules_go//proto/wkt:wrappers_go_proto",
"@io_bazel_rules_go//proto/wkt:timestamp_go_proto",
"@io_bazel_rules_go//proto/wkt:wrappers_go_proto",
"@org_golang_google_protobuf//types/descriptorpb:go_default_library",
"@org_golang_google_protobuf//types/known/emptypb:go_default_library",
],

View File

@@ -710,7 +710,7 @@ message BlindedBeaconBlockBodyDeneb {
// Execution payload header from the execution chain. New in Bellatrix network upgrade to accommodate MEV interaction.
ethereum.engine.v1.ExecutionPayloadHeaderDeneb execution_payload_header = 10;
// At most MAX_BLS_TO_EXECUTION_CHANGES. New in Deneb network upgrade.
// At most MAX_BLS_TO_EXECUTION_CHANGES. New in Capella network upgrade.
repeated SignedBLSToExecutionChange bls_to_execution_changes = 11 [(ethereum.eth.ext.ssz_max) = "16"];
repeated bytes blob_kzg_commitments = 12 [(ethereum.eth.ext.ssz_size) = "?,48", (ethereum.eth.ext.ssz_max) = "max_blob_commitments.size"];

View File

@@ -1,5 +1,5 @@
// Code generated by fastssz. DO NOT EDIT.
// Hash: 28837d1c80ab7592d4877ebbd9881adf756b7da77c5614263c8442c2b3dea5c2
// Hash: 277e239dcf280a4b2a1912458e9a7cd90ba4332d1fc1c6148c105fa481f9c66f
package eth
import (
@@ -15648,6 +15648,182 @@ func (b *BlobSidecarsByRangeRequest) HashTreeRootWith(hh *ssz.Hasher) (err error
return
}
// MarshalSSZ ssz marshals the DepositSnapshot object
func (d *DepositSnapshot) MarshalSSZ() ([]byte, error) {
return ssz.MarshalSSZ(d)
}
// MarshalSSZTo ssz marshals the DepositSnapshot object to a target array
func (d *DepositSnapshot) MarshalSSZTo(buf []byte) (dst []byte, err error) {
dst = buf
offset := int(84)
// Offset (0) 'Finalized'
dst = ssz.WriteOffset(dst, offset)
offset += len(d.Finalized) * 32
// Field (1) 'DepositRoot'
if size := len(d.DepositRoot); size != 32 {
err = ssz.ErrBytesLengthFn("--.DepositRoot", size, 32)
return
}
dst = append(dst, d.DepositRoot...)
// Field (2) 'DepositCount'
dst = ssz.MarshalUint64(dst, d.DepositCount)
// Field (3) 'ExecutionHash'
if size := len(d.ExecutionHash); size != 32 {
err = ssz.ErrBytesLengthFn("--.ExecutionHash", size, 32)
return
}
dst = append(dst, d.ExecutionHash...)
// Field (4) 'ExecutionDepth'
dst = ssz.MarshalUint64(dst, d.ExecutionDepth)
// Field (0) 'Finalized'
if size := len(d.Finalized); size > 32 {
err = ssz.ErrListTooBigFn("--.Finalized", size, 32)
return
}
for ii := 0; ii < len(d.Finalized); ii++ {
if size := len(d.Finalized[ii]); size != 32 {
err = ssz.ErrBytesLengthFn("--.Finalized[ii]", size, 32)
return
}
dst = append(dst, d.Finalized[ii]...)
}
return
}
// UnmarshalSSZ ssz unmarshals the DepositSnapshot object
func (d *DepositSnapshot) UnmarshalSSZ(buf []byte) error {
var err error
size := uint64(len(buf))
if size < 84 {
return ssz.ErrSize
}
tail := buf
var o0 uint64
// Offset (0) 'Finalized'
if o0 = ssz.ReadOffset(buf[0:4]); o0 > size {
return ssz.ErrOffset
}
if o0 < 84 {
return ssz.ErrInvalidVariableOffset
}
// Field (1) 'DepositRoot'
if cap(d.DepositRoot) == 0 {
d.DepositRoot = make([]byte, 0, len(buf[4:36]))
}
d.DepositRoot = append(d.DepositRoot, buf[4:36]...)
// Field (2) 'DepositCount'
d.DepositCount = ssz.UnmarshallUint64(buf[36:44])
// Field (3) 'ExecutionHash'
if cap(d.ExecutionHash) == 0 {
d.ExecutionHash = make([]byte, 0, len(buf[44:76]))
}
d.ExecutionHash = append(d.ExecutionHash, buf[44:76]...)
// Field (4) 'ExecutionDepth'
d.ExecutionDepth = ssz.UnmarshallUint64(buf[76:84])
// Field (0) 'Finalized'
{
buf = tail[o0:]
num, err := ssz.DivideInt2(len(buf), 32, 32)
if err != nil {
return err
}
d.Finalized = make([][]byte, num)
for ii := 0; ii < num; ii++ {
if cap(d.Finalized[ii]) == 0 {
d.Finalized[ii] = make([]byte, 0, len(buf[ii*32:(ii+1)*32]))
}
d.Finalized[ii] = append(d.Finalized[ii], buf[ii*32:(ii+1)*32]...)
}
}
return err
}
// SizeSSZ returns the ssz encoded size in bytes for the DepositSnapshot object
func (d *DepositSnapshot) SizeSSZ() (size int) {
size = 84
// Field (0) 'Finalized'
size += len(d.Finalized) * 32
return
}
// HashTreeRoot ssz hashes the DepositSnapshot object
func (d *DepositSnapshot) HashTreeRoot() ([32]byte, error) {
return ssz.HashWithDefaultHasher(d)
}
// HashTreeRootWith ssz hashes the DepositSnapshot object with a hasher
func (d *DepositSnapshot) HashTreeRootWith(hh *ssz.Hasher) (err error) {
indx := hh.Index()
// Field (0) 'Finalized'
{
if size := len(d.Finalized); size > 32 {
err = ssz.ErrListTooBigFn("--.Finalized", size, 32)
return
}
subIndx := hh.Index()
for _, i := range d.Finalized {
if len(i) != 32 {
err = ssz.ErrBytesLength
return
}
hh.Append(i)
}
numItems := uint64(len(d.Finalized))
if ssz.EnableVectorizedHTR {
hh.MerkleizeWithMixinVectorizedHTR(subIndx, numItems, 32)
} else {
hh.MerkleizeWithMixin(subIndx, numItems, 32)
}
}
// Field (1) 'DepositRoot'
if size := len(d.DepositRoot); size != 32 {
err = ssz.ErrBytesLengthFn("--.DepositRoot", size, 32)
return
}
hh.PutBytes(d.DepositRoot)
// Field (2) 'DepositCount'
hh.PutUint64(d.DepositCount)
// Field (3) 'ExecutionHash'
if size := len(d.ExecutionHash); size != 32 {
err = ssz.ErrBytesLengthFn("--.ExecutionHash", size, 32)
return
}
hh.PutBytes(d.ExecutionHash)
// Field (4) 'ExecutionDepth'
hh.PutUint64(d.ExecutionDepth)
if ssz.EnableVectorizedHTR {
hh.MerkleizeVectorizedHTR(indx)
} else {
hh.Merkleize(indx)
}
return
}
// MarshalSSZ ssz marshals the SyncCommitteeMessage object
func (s *SyncCommitteeMessage) MarshalSSZ() ([]byte, error) {
return ssz.MarshalSSZ(s)

View File

@@ -10,8 +10,10 @@ import (
reflect "reflect"
sync "sync"
_ "github.com/prysmaticlabs/prysm/v4/proto/eth/ext"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
_ "google.golang.org/protobuf/types/descriptorpb"
)
const (
@@ -113,10 +115,10 @@ type DepositSnapshot struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Finalized [][]byte `protobuf:"bytes,1,rep,name=finalized,proto3" json:"finalized,omitempty"`
DepositRoot []byte `protobuf:"bytes,2,opt,name=deposit_root,json=depositRoot,proto3" json:"deposit_root,omitempty"`
Finalized [][]byte `protobuf:"bytes,1,rep,name=finalized,proto3" json:"finalized,omitempty" ssz-max:"32" ssz-size:"?,32"`
DepositRoot []byte `protobuf:"bytes,2,opt,name=deposit_root,json=depositRoot,proto3" json:"deposit_root,omitempty" ssz-size:"32"`
DepositCount uint64 `protobuf:"varint,3,opt,name=deposit_count,json=depositCount,proto3" json:"deposit_count,omitempty"`
ExecutionHash []byte `protobuf:"bytes,4,opt,name=execution_hash,json=executionHash,proto3" json:"execution_hash,omitempty"`
ExecutionHash []byte `protobuf:"bytes,4,opt,name=execution_hash,json=executionHash,proto3" json:"execution_hash,omitempty" ssz-size:"32"`
ExecutionDepth uint64 `protobuf:"varint,5,opt,name=execution_depth,json=executionDepth,proto3" json:"execution_depth,omitempty"`
}
@@ -524,115 +526,121 @@ var file_proto_prysm_v1alpha1_powchain_proto_rawDesc = []byte{
0x0a, 0x23, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x31,
0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x70, 0x6f, 0x77, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x15, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e,
0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x1a, 0x27, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68,
0x61, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x27, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x79,
0x73, 0x6d, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63,
0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xe1,
0x03, 0x0a, 0x0d, 0x45, 0x54, 0x48, 0x31, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x44, 0x61, 0x74, 0x61,
0x12, 0x51, 0x0a, 0x11, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x65, 0x74, 0x68, 0x31,
0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x65, 0x74,
0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x1a, 0x20, 0x67, 0x6f,
0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x65,
0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x27,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x31, 0x61, 0x6c,
0x70, 0x68, 0x61, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x62, 0x6c, 0x6f, 0x63,
0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x27, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70,
0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x62, 0x65,
0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x1a, 0x1b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x65, 0x78, 0x74, 0x2f,
0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xe1, 0x03,
0x0a, 0x0d, 0x45, 0x54, 0x48, 0x31, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x12,
0x51, 0x0a, 0x11, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x65, 0x74, 0x68, 0x31, 0x5f,
0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x65, 0x74, 0x68,
0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68,
0x61, 0x31, 0x2e, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x45, 0x54, 0x48, 0x31, 0x44, 0x61, 0x74,
0x61, 0x52, 0x0f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x45, 0x74, 0x68, 0x31, 0x44, 0x61,
0x74, 0x61, 0x12, 0x4e, 0x0a, 0x0f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x72, 0x74,
0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x65, 0x74,
0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70,
0x68, 0x61, 0x31, 0x2e, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x45, 0x54, 0x48, 0x31, 0x44, 0x61,
0x74, 0x61, 0x52, 0x0f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x45, 0x74, 0x68, 0x31, 0x44,
0x61, 0x74, 0x61, 0x12, 0x4e, 0x0a, 0x0f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x72,
0x74, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x65,
0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c,
0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x44,
0x61, 0x74, 0x61, 0x52, 0x0e, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x72, 0x74, 0x44,
0x61, 0x74, 0x61, 0x12, 0x45, 0x0a, 0x0c, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x73, 0x74,
0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65,
0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61,
0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x0b, 0x62,
0x65, 0x61, 0x63, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x3b, 0x0a, 0x04, 0x74, 0x72,
0x69, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72,
0x68, 0x61, 0x31, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x44, 0x61,
0x74, 0x61, 0x52, 0x0e, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x72, 0x74, 0x44, 0x61,
0x74, 0x61, 0x12, 0x45, 0x0a, 0x0c, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61,
0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72,
0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31,
0x2e, 0x53, 0x70, 0x61, 0x72, 0x73, 0x65, 0x4d, 0x65, 0x72, 0x6b, 0x6c, 0x65, 0x54, 0x72, 0x69,
0x65, 0x52, 0x04, 0x74, 0x72, 0x69, 0x65, 0x12, 0x56, 0x0a, 0x12, 0x64, 0x65, 0x70, 0x6f, 0x73,
0x69, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x05, 0x20,
0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65,
0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x70, 0x6f,
0x73, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x11, 0x64, 0x65,
0x70, 0x6f, 0x73, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x12,
0x51, 0x0a, 0x10, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x5f, 0x73, 0x6e, 0x61, 0x70, 0x73,
0x68, 0x6f, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x65, 0x74, 0x68, 0x65,
0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61,
0x31, 0x2e, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f,
0x74, 0x52, 0x0f, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68,
0x6f, 0x74, 0x22, 0xc7, 0x01, 0x0a, 0x0f, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x53, 0x6e,
0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69,
0x7a, 0x65, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x09, 0x66, 0x69, 0x6e, 0x61, 0x6c,
0x69, 0x7a, 0x65, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x5f,
0x72, 0x6f, 0x6f, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x64, 0x65, 0x70, 0x6f,
0x73, 0x69, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x65, 0x70, 0x6f, 0x73,
0x69, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c,
0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x25, 0x0a, 0x0e,
0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x04,
0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x48,
0x61, 0x73, 0x68, 0x12, 0x27, 0x0a, 0x0f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e,
0x5f, 0x64, 0x65, 0x70, 0x74, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x65, 0x78,
0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x70, 0x74, 0x68, 0x22, 0xa3, 0x01, 0x0a,
0x0e, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x45, 0x54, 0x48, 0x31, 0x44, 0x61, 0x74, 0x61, 0x12,
0x21, 0x0a, 0x0c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18,
0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x69, 0x67,
0x68, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x74, 0x69, 0x6d, 0x65,
0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x54, 0x69, 0x6d,
0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18,
0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68,
0x12, 0x30, 0x0a, 0x14, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x65, 0x64, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x12,
0x6c, 0x61, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x64, 0x42, 0x6c, 0x6f,
0x63, 0x6b, 0x22, 0x8b, 0x02, 0x0a, 0x0e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x61, 0x72,
0x74, 0x44, 0x61, 0x74, 0x61, 0x12, 0x22, 0x0a, 0x0c, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x74,
0x61, 0x72, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x63, 0x68, 0x61,
0x69, 0x6e, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x67, 0x65, 0x6e,
0x65, 0x73, 0x69, 0x73, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52,
0x0b, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d,
0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x03, 0x20,
0x01, 0x28, 0x04, 0x52, 0x0c, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x42, 0x6c, 0x6f, 0x63,
0x6b, 0x12, 0x3c, 0x0a, 0x09, 0x65, 0x74, 0x68, 0x31, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e,
0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x45, 0x74, 0x68,
0x31, 0x44, 0x61, 0x74, 0x61, 0x52, 0x08, 0x65, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x12,
0x4f, 0x0a, 0x13, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x64, 0x65,
0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x65,
0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c,
0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, 0x12, 0x63, 0x68,
0x61, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x72, 0x74, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73,
0x22, 0x89, 0x01, 0x0a, 0x10, 0x53, 0x70, 0x61, 0x72, 0x73, 0x65, 0x4d, 0x65, 0x72, 0x6b, 0x6c,
0x65, 0x54, 0x72, 0x69, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x64, 0x65, 0x70, 0x74, 0x68, 0x18, 0x01,
0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x64, 0x65, 0x70, 0x74, 0x68, 0x12, 0x38, 0x0a, 0x06, 0x6c,
0x61, 0x79, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x65, 0x74,
0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70,
0x68, 0x61, 0x31, 0x2e, 0x54, 0x72, 0x69, 0x65, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x52, 0x06, 0x6c,
0x61, 0x79, 0x65, 0x72, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61,
0x6c, 0x5f, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x0d, 0x6f,
0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x49, 0x74, 0x65, 0x6d, 0x73, 0x22, 0x21, 0x0a, 0x09,
0x54, 0x72, 0x69, 0x65, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x61, 0x79,
0x65, 0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x05, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x22,
0xb1, 0x01, 0x0a, 0x10, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61,
0x69, 0x6e, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x01, 0x20,
0x01, 0x28, 0x03, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x2a, 0x0a, 0x11, 0x65, 0x74,
0x68, 0x31, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18,
0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x65, 0x74, 0x68, 0x31, 0x42, 0x6c, 0x6f, 0x63, 0x6b,
0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x38, 0x0a, 0x07, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69,
0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65,
0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x0b, 0x62, 0x65,
0x61, 0x63, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x3b, 0x0a, 0x04, 0x74, 0x72, 0x69,
0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65,
0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e,
0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, 0x07, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74,
0x12, 0x21, 0x0a, 0x0c, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74,
0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52,
0x6f, 0x6f, 0x74, 0x42, 0x98, 0x01, 0x0a, 0x19, 0x6f, 0x72, 0x67, 0x2e, 0x65, 0x74, 0x68, 0x65,
0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61,
0x31, 0x42, 0x0d, 0x50, 0x6f, 0x77, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f,
0x50, 0x01, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70,
0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79,
0x73, 0x6d, 0x2f, 0x76, 0x34, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x79, 0x73,
0x6d, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x65, 0x74, 0x68, 0xaa, 0x02,
0x15, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x45, 0x74, 0x68, 0x2e, 0x56, 0x31,
0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x15, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75,
0x6d, 0x5c, 0x45, 0x74, 0x68, 0x5c, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x53, 0x70, 0x61, 0x72, 0x73, 0x65, 0x4d, 0x65, 0x72, 0x6b, 0x6c, 0x65, 0x54, 0x72, 0x69, 0x65,
0x52, 0x04, 0x74, 0x72, 0x69, 0x65, 0x12, 0x56, 0x0a, 0x12, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69,
0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x05, 0x20, 0x03,
0x28, 0x0b, 0x32, 0x27, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74,
0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x70, 0x6f, 0x73,
0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x11, 0x64, 0x65, 0x70,
0x6f, 0x73, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x51,
0x0a, 0x10, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x5f, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68,
0x6f, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72,
0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31,
0x2e, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74,
0x52, 0x0f, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f,
0x74, 0x22, 0xe7, 0x01, 0x0a, 0x0f, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x53, 0x6e, 0x61,
0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, 0x2c, 0x0a, 0x09, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a,
0x65, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x0e, 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c,
0x33, 0x32, 0x92, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69,
0x7a, 0x65, 0x64, 0x12, 0x29, 0x0a, 0x0c, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x5f, 0x72,
0x6f, 0x6f, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33,
0x32, 0x52, 0x0b, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x23,
0x0a, 0x0d, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18,
0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x43, 0x6f,
0x75, 0x6e, 0x74, 0x12, 0x2d, 0x0a, 0x0e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e,
0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18,
0x02, 0x33, 0x32, 0x52, 0x0d, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x61,
0x73, 0x68, 0x12, 0x27, 0x0a, 0x0f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f,
0x64, 0x65, 0x70, 0x74, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x65, 0x78, 0x65,
0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x70, 0x74, 0x68, 0x22, 0xa3, 0x01, 0x0a, 0x0e,
0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x45, 0x54, 0x48, 0x31, 0x44, 0x61, 0x74, 0x61, 0x12, 0x21,
0x0a, 0x0c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02,
0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x69, 0x67, 0x68,
0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18,
0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x54, 0x69, 0x6d, 0x65,
0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x04,
0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x12,
0x30, 0x0a, 0x14, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65,
0x64, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x12, 0x6c,
0x61, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x64, 0x42, 0x6c, 0x6f, 0x63,
0x6b, 0x22, 0x8b, 0x02, 0x0a, 0x0e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x61, 0x72, 0x74,
0x44, 0x61, 0x74, 0x61, 0x12, 0x22, 0x0a, 0x0c, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x74, 0x61,
0x72, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x63, 0x68, 0x61, 0x69,
0x6e, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x67, 0x65, 0x6e, 0x65,
0x73, 0x69, 0x73, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b,
0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x67,
0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x03, 0x20, 0x01,
0x28, 0x04, 0x52, 0x0c, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x42, 0x6c, 0x6f, 0x63, 0x6b,
0x12, 0x3c, 0x0a, 0x09, 0x65, 0x74, 0x68, 0x31, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65,
0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x45, 0x74, 0x68, 0x31,
0x44, 0x61, 0x74, 0x61, 0x52, 0x08, 0x65, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x12, 0x4f,
0x0a, 0x13, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x64, 0x65, 0x70,
0x6f, 0x73, 0x69, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x65, 0x74,
0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70,
0x68, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, 0x12, 0x63, 0x68, 0x61,
0x69, 0x6e, 0x73, 0x74, 0x61, 0x72, 0x74, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x22,
0x89, 0x01, 0x0a, 0x10, 0x53, 0x70, 0x61, 0x72, 0x73, 0x65, 0x4d, 0x65, 0x72, 0x6b, 0x6c, 0x65,
0x54, 0x72, 0x69, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x64, 0x65, 0x70, 0x74, 0x68, 0x18, 0x01, 0x20,
0x01, 0x28, 0x04, 0x52, 0x05, 0x64, 0x65, 0x70, 0x74, 0x68, 0x12, 0x38, 0x0a, 0x06, 0x6c, 0x61,
0x79, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x65, 0x74, 0x68,
0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68,
0x61, 0x31, 0x2e, 0x54, 0x72, 0x69, 0x65, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x52, 0x06, 0x6c, 0x61,
0x79, 0x65, 0x72, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c,
0x5f, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x0d, 0x6f, 0x72,
0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x49, 0x74, 0x65, 0x6d, 0x73, 0x22, 0x21, 0x0a, 0x09, 0x54,
0x72, 0x69, 0x65, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x61, 0x79, 0x65,
0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x05, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x22, 0xb1,
0x01, 0x0a, 0x10, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69,
0x6e, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01,
0x28, 0x03, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x2a, 0x0a, 0x11, 0x65, 0x74, 0x68,
0x31, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02,
0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x65, 0x74, 0x68, 0x31, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48,
0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x38, 0x0a, 0x07, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74,
0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75,
0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44,
0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, 0x07, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x12,
0x21, 0x0a, 0x0c, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18,
0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, 0x6f,
0x6f, 0x74, 0x42, 0x98, 0x01, 0x0a, 0x19, 0x6f, 0x72, 0x67, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72,
0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31,
0x42, 0x0d, 0x50, 0x6f, 0x77, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50,
0x01, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72,
0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73,
0x6d, 0x2f, 0x76, 0x34, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d,
0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x65, 0x74, 0x68, 0xaa, 0x02, 0x15,
0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x45, 0x74, 0x68, 0x2e, 0x56, 0x31, 0x61,
0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x15, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d,
0x5c, 0x45, 0x74, 0x68, 0x5c, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (

View File

@@ -2,8 +2,10 @@ syntax = "proto3";
package ethereum.eth.v1alpha1;
import "google/protobuf/descriptor.proto";
import "proto/prysm/v1alpha1/beacon_block.proto";
import "proto/prysm/v1alpha1/beacon_state.proto";
import "proto/eth/ext/options.proto";
option csharp_namespace = "Ethereum.Eth.V1alpha1";
option go_package = "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1;eth";
@@ -25,12 +27,13 @@ message ETH1ChainData {
// DepositSnapshot represents an EIP-4881 deposit snapshot
message DepositSnapshot {
repeated bytes finalized = 1;
bytes deposit_root = 2;
repeated bytes finalized = 1 [(ethereum.eth.ext.ssz_size) = "?,32", (ethereum.eth.ext.ssz_max) = "32"];
bytes deposit_root = 2 [(ethereum.eth.ext.ssz_size) = "32"];
uint64 deposit_count = 3;
bytes execution_hash = 4;
bytes execution_hash = 4 [(ethereum.eth.ext.ssz_size) = "32"];
uint64 execution_depth = 5;
}
// LatestETH1Data contains the current state of the eth1 chain.
message LatestETH1Data {
uint64 block_height = 2;

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc v4.23.3
// protoc v4.25.1
// source: proto/prysm/v1alpha1/validator-client/keymanager.proto
package validatorpb
@@ -11,7 +11,6 @@ import (
sync "sync"
github_com_prysmaticlabs_prysm_v4_consensus_types_primitives "github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
github_com_prysmaticlabs_prysm_v4_consensus_types_validator "github.com/prysmaticlabs/prysm/v4/consensus-types/validator"
_ "github.com/prysmaticlabs/prysm/v4/proto/eth/ext"
v1alpha1 "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
@@ -455,179 +454,6 @@ func (x *SignResponse) GetStatus() SignResponse_Status {
return SignResponse_UNKNOWN
}
type ProposerOptionPayload struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
FeeRecipient string `protobuf:"bytes,1,opt,name=fee_recipient,json=feeRecipient,proto3" json:"fee_recipient,omitempty"`
Builder *BuilderConfig `protobuf:"bytes,2,opt,name=builder,proto3" json:"builder,omitempty"`
}
func (x *ProposerOptionPayload) Reset() {
*x = ProposerOptionPayload{}
if protoimpl.UnsafeEnabled {
mi := &file_proto_prysm_v1alpha1_validator_client_keymanager_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ProposerOptionPayload) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ProposerOptionPayload) ProtoMessage() {}
func (x *ProposerOptionPayload) ProtoReflect() protoreflect.Message {
mi := &file_proto_prysm_v1alpha1_validator_client_keymanager_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ProposerOptionPayload.ProtoReflect.Descriptor instead.
func (*ProposerOptionPayload) Descriptor() ([]byte, []int) {
return file_proto_prysm_v1alpha1_validator_client_keymanager_proto_rawDescGZIP(), []int{2}
}
func (x *ProposerOptionPayload) GetFeeRecipient() string {
if x != nil {
return x.FeeRecipient
}
return ""
}
func (x *ProposerOptionPayload) GetBuilder() *BuilderConfig {
if x != nil {
return x.Builder
}
return nil
}
type BuilderConfig struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"`
GasLimit github_com_prysmaticlabs_prysm_v4_consensus_types_validator.Uint64 `protobuf:"varint,2,opt,name=gas_limit,json=gasLimit,proto3" json:"gas_limit,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v4/consensus-types/validator.Uint64"`
Relays []string `protobuf:"bytes,3,rep,name=relays,proto3" json:"relays,omitempty"`
}
func (x *BuilderConfig) Reset() {
*x = BuilderConfig{}
if protoimpl.UnsafeEnabled {
mi := &file_proto_prysm_v1alpha1_validator_client_keymanager_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *BuilderConfig) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*BuilderConfig) ProtoMessage() {}
func (x *BuilderConfig) ProtoReflect() protoreflect.Message {
mi := &file_proto_prysm_v1alpha1_validator_client_keymanager_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use BuilderConfig.ProtoReflect.Descriptor instead.
func (*BuilderConfig) Descriptor() ([]byte, []int) {
return file_proto_prysm_v1alpha1_validator_client_keymanager_proto_rawDescGZIP(), []int{3}
}
func (x *BuilderConfig) GetEnabled() bool {
if x != nil {
return x.Enabled
}
return false
}
func (x *BuilderConfig) GetGasLimit() github_com_prysmaticlabs_prysm_v4_consensus_types_validator.Uint64 {
if x != nil {
return x.GasLimit
}
return github_com_prysmaticlabs_prysm_v4_consensus_types_validator.Uint64(0)
}
func (x *BuilderConfig) GetRelays() []string {
if x != nil {
return x.Relays
}
return nil
}
type ProposerSettingsPayload struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
ProposerConfig map[string]*ProposerOptionPayload `protobuf:"bytes,1,rep,name=proposer_config,json=proposerConfig,proto3" json:"proposer_config,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
DefaultConfig *ProposerOptionPayload `protobuf:"bytes,2,opt,name=default_config,json=defaultConfig,proto3" json:"default_config,omitempty"`
}
func (x *ProposerSettingsPayload) Reset() {
*x = ProposerSettingsPayload{}
if protoimpl.UnsafeEnabled {
mi := &file_proto_prysm_v1alpha1_validator_client_keymanager_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ProposerSettingsPayload) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ProposerSettingsPayload) ProtoMessage() {}
func (x *ProposerSettingsPayload) ProtoReflect() protoreflect.Message {
mi := &file_proto_prysm_v1alpha1_validator_client_keymanager_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ProposerSettingsPayload.ProtoReflect.Descriptor instead.
func (*ProposerSettingsPayload) Descriptor() ([]byte, []int) {
return file_proto_prysm_v1alpha1_validator_client_keymanager_proto_rawDescGZIP(), []int{4}
}
func (x *ProposerSettingsPayload) GetProposerConfig() map[string]*ProposerOptionPayload {
if x != nil {
return x.ProposerConfig
}
return nil
}
func (x *ProposerSettingsPayload) GetDefaultConfig() *ProposerOptionPayload {
if x != nil {
return x.DefaultConfig
}
return nil
}
var File_proto_prysm_v1alpha1_validator_client_keymanager_proto protoreflect.FileDescriptor
var file_proto_prysm_v1alpha1_validator_client_keymanager_proto_rawDesc = []byte{
@@ -771,62 +597,20 @@ var file_proto_prysm_v1alpha1_validator_client_keymanager_proto_rawDesc = []byte
0x73, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0d,
0x0a, 0x09, 0x53, 0x55, 0x43, 0x43, 0x45, 0x45, 0x44, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0a, 0x0a,
0x06, 0x44, 0x45, 0x4e, 0x49, 0x45, 0x44, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x46, 0x41, 0x49,
0x4c, 0x45, 0x44, 0x10, 0x03, 0x22, 0x85, 0x01, 0x0a, 0x15, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73,
0x65, 0x72, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12,
0x23, 0x0a, 0x0d, 0x66, 0x65, 0x65, 0x5f, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x66, 0x65, 0x65, 0x52, 0x65, 0x63, 0x69, 0x70,
0x69, 0x65, 0x6e, 0x74, 0x12, 0x47, 0x0a, 0x07, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x18,
0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d,
0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75,
0x6e, 0x74, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x43, 0x6f,
0x6e, 0x66, 0x69, 0x67, 0x52, 0x07, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x22, 0xa6, 0x01,
0x0a, 0x0d, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12,
0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08,
0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x63, 0x0a, 0x09, 0x67, 0x61, 0x73,
0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5,
0x18, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79,
0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d,
0x2f, 0x76, 0x34, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79,
0x70, 0x65, 0x73, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x55, 0x69,
0x6e, 0x74, 0x36, 0x34, 0x52, 0x08, 0x67, 0x61, 0x73, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x16,
0x0a, 0x06, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06,
0x72, 0x65, 0x6c, 0x61, 0x79, 0x73, 0x22, 0xe7, 0x02, 0x0a, 0x17, 0x50, 0x72, 0x6f, 0x70, 0x6f,
0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x50, 0x61, 0x79, 0x6c, 0x6f,
0x61, 0x64, 0x12, 0x74, 0x0a, 0x0f, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x63,
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x4b, 0x2e, 0x65, 0x74,
0x4c, 0x45, 0x44, 0x10, 0x03, 0x42, 0xce, 0x01, 0x0a, 0x22, 0x6f, 0x72, 0x67, 0x2e, 0x65, 0x74,
0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72,
0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x50, 0x72, 0x6f,
0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x50, 0x61, 0x79,
0x6c, 0x6f, 0x61, 0x64, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x43, 0x6f, 0x6e,
0x66, 0x69, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0e, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73,
0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x5c, 0x0a, 0x0e, 0x64, 0x65, 0x66, 0x61,
0x75, 0x6c, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x35, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x76, 0x61, 0x6c, 0x69,
0x64, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76,
0x32, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e,
0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x0d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74,
0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x1a, 0x78, 0x0a, 0x13, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73,
0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a,
0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12,
0x4b, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35,
0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61,
0x74, 0x6f, 0x72, 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x32, 0x2e,
0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61,
0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01,
0x42, 0xce, 0x01, 0x0a, 0x22, 0x6f, 0x72, 0x67, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75,
0x6d, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x61, 0x63, 0x63, 0x6f,
0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x32, 0x42, 0x0f, 0x4b, 0x65, 0x79, 0x6d, 0x61, 0x6e, 0x61,
0x67, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x53, 0x67, 0x69, 0x74, 0x68,
0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63,
0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x34, 0x2f, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68,
0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2d, 0x63, 0x6c, 0x69,
0x65, 0x6e, 0x74, 0x3b, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x70, 0x62, 0xaa,
0x02, 0x1e, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64,
0x61, 0x74, 0x6f, 0x72, 0x2e, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x56, 0x32,
0xca, 0x02, 0x1e, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x5c, 0x56, 0x61, 0x6c, 0x69,
0x64, 0x61, 0x74, 0x6f, 0x72, 0x5c, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x5c, 0x56,
0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x32, 0x42, 0x0f, 0x4b, 0x65,
0x79, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a,
0x53, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73,
0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f,
0x76, 0x34, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76,
0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f,
0x72, 0x2d, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x3b, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74,
0x6f, 0x72, 0x70, 0x62, 0xaa, 0x02, 0x1e, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e,
0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e,
0x74, 0x73, 0x2e, 0x56, 0x32, 0xca, 0x02, 0x1e, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d,
0x5c, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5c, 0x41, 0x63, 0x63, 0x6f, 0x75,
0x6e, 0x74, 0x73, 0x5c, 0x56, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@@ -842,55 +626,47 @@ func file_proto_prysm_v1alpha1_validator_client_keymanager_proto_rawDescGZIP() [
}
var file_proto_prysm_v1alpha1_validator_client_keymanager_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_proto_prysm_v1alpha1_validator_client_keymanager_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
var file_proto_prysm_v1alpha1_validator_client_keymanager_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_proto_prysm_v1alpha1_validator_client_keymanager_proto_goTypes = []interface{}{
(SignResponse_Status)(0), // 0: ethereum.validator.accounts.v2.SignResponse.Status
(*SignRequest)(nil), // 1: ethereum.validator.accounts.v2.SignRequest
(*SignResponse)(nil), // 2: ethereum.validator.accounts.v2.SignResponse
(*ProposerOptionPayload)(nil), // 3: ethereum.validator.accounts.v2.ProposerOptionPayload
(*BuilderConfig)(nil), // 4: ethereum.validator.accounts.v2.BuilderConfig
(*ProposerSettingsPayload)(nil), // 5: ethereum.validator.accounts.v2.ProposerSettingsPayload
nil, // 6: ethereum.validator.accounts.v2.ProposerSettingsPayload.ProposerConfigEntry
(*v1alpha1.BeaconBlock)(nil), // 7: ethereum.eth.v1alpha1.BeaconBlock
(*v1alpha1.AttestationData)(nil), // 8: ethereum.eth.v1alpha1.AttestationData
(*v1alpha1.AggregateAttestationAndProof)(nil), // 9: ethereum.eth.v1alpha1.AggregateAttestationAndProof
(*v1alpha1.VoluntaryExit)(nil), // 10: ethereum.eth.v1alpha1.VoluntaryExit
(*v1alpha1.BeaconBlockAltair)(nil), // 11: ethereum.eth.v1alpha1.BeaconBlockAltair
(*v1alpha1.SyncAggregatorSelectionData)(nil), // 12: ethereum.eth.v1alpha1.SyncAggregatorSelectionData
(*v1alpha1.ContributionAndProof)(nil), // 13: ethereum.eth.v1alpha1.ContributionAndProof
(*v1alpha1.BeaconBlockBellatrix)(nil), // 14: ethereum.eth.v1alpha1.BeaconBlockBellatrix
(*v1alpha1.BlindedBeaconBlockBellatrix)(nil), // 15: ethereum.eth.v1alpha1.BlindedBeaconBlockBellatrix
(*v1alpha1.ValidatorRegistrationV1)(nil), // 16: ethereum.eth.v1alpha1.ValidatorRegistrationV1
(*v1alpha1.BeaconBlockCapella)(nil), // 17: ethereum.eth.v1alpha1.BeaconBlockCapella
(*v1alpha1.BlindedBeaconBlockCapella)(nil), // 18: ethereum.eth.v1alpha1.BlindedBeaconBlockCapella
(*v1alpha1.BeaconBlockDeneb)(nil), // 19: ethereum.eth.v1alpha1.BeaconBlockDeneb
(*v1alpha1.BlindedBeaconBlockDeneb)(nil), // 20: ethereum.eth.v1alpha1.BlindedBeaconBlockDeneb
(*v1alpha1.BeaconBlock)(nil), // 3: ethereum.eth.v1alpha1.BeaconBlock
(*v1alpha1.AttestationData)(nil), // 4: ethereum.eth.v1alpha1.AttestationData
(*v1alpha1.AggregateAttestationAndProof)(nil), // 5: ethereum.eth.v1alpha1.AggregateAttestationAndProof
(*v1alpha1.VoluntaryExit)(nil), // 6: ethereum.eth.v1alpha1.VoluntaryExit
(*v1alpha1.BeaconBlockAltair)(nil), // 7: ethereum.eth.v1alpha1.BeaconBlockAltair
(*v1alpha1.SyncAggregatorSelectionData)(nil), // 8: ethereum.eth.v1alpha1.SyncAggregatorSelectionData
(*v1alpha1.ContributionAndProof)(nil), // 9: ethereum.eth.v1alpha1.ContributionAndProof
(*v1alpha1.BeaconBlockBellatrix)(nil), // 10: ethereum.eth.v1alpha1.BeaconBlockBellatrix
(*v1alpha1.BlindedBeaconBlockBellatrix)(nil), // 11: ethereum.eth.v1alpha1.BlindedBeaconBlockBellatrix
(*v1alpha1.ValidatorRegistrationV1)(nil), // 12: ethereum.eth.v1alpha1.ValidatorRegistrationV1
(*v1alpha1.BeaconBlockCapella)(nil), // 13: ethereum.eth.v1alpha1.BeaconBlockCapella
(*v1alpha1.BlindedBeaconBlockCapella)(nil), // 14: ethereum.eth.v1alpha1.BlindedBeaconBlockCapella
(*v1alpha1.BeaconBlockDeneb)(nil), // 15: ethereum.eth.v1alpha1.BeaconBlockDeneb
(*v1alpha1.BlindedBeaconBlockDeneb)(nil), // 16: ethereum.eth.v1alpha1.BlindedBeaconBlockDeneb
}
var file_proto_prysm_v1alpha1_validator_client_keymanager_proto_depIdxs = []int32{
7, // 0: ethereum.validator.accounts.v2.SignRequest.block:type_name -> ethereum.eth.v1alpha1.BeaconBlock
8, // 1: ethereum.validator.accounts.v2.SignRequest.attestation_data:type_name -> ethereum.eth.v1alpha1.AttestationData
9, // 2: ethereum.validator.accounts.v2.SignRequest.aggregate_attestation_and_proof:type_name -> ethereum.eth.v1alpha1.AggregateAttestationAndProof
10, // 3: ethereum.validator.accounts.v2.SignRequest.exit:type_name -> ethereum.eth.v1alpha1.VoluntaryExit
11, // 4: ethereum.validator.accounts.v2.SignRequest.block_altair:type_name -> ethereum.eth.v1alpha1.BeaconBlockAltair
12, // 5: ethereum.validator.accounts.v2.SignRequest.sync_aggregator_selection_data:type_name -> ethereum.eth.v1alpha1.SyncAggregatorSelectionData
13, // 6: ethereum.validator.accounts.v2.SignRequest.contribution_and_proof:type_name -> ethereum.eth.v1alpha1.ContributionAndProof
14, // 7: ethereum.validator.accounts.v2.SignRequest.block_bellatrix:type_name -> ethereum.eth.v1alpha1.BeaconBlockBellatrix
15, // 8: ethereum.validator.accounts.v2.SignRequest.blinded_block_bellatrix:type_name -> ethereum.eth.v1alpha1.BlindedBeaconBlockBellatrix
16, // 9: ethereum.validator.accounts.v2.SignRequest.registration:type_name -> ethereum.eth.v1alpha1.ValidatorRegistrationV1
17, // 10: ethereum.validator.accounts.v2.SignRequest.block_capella:type_name -> ethereum.eth.v1alpha1.BeaconBlockCapella
18, // 11: ethereum.validator.accounts.v2.SignRequest.blinded_block_capella:type_name -> ethereum.eth.v1alpha1.BlindedBeaconBlockCapella
19, // 12: ethereum.validator.accounts.v2.SignRequest.block_deneb:type_name -> ethereum.eth.v1alpha1.BeaconBlockDeneb
20, // 13: ethereum.validator.accounts.v2.SignRequest.blinded_block_deneb:type_name -> ethereum.eth.v1alpha1.BlindedBeaconBlockDeneb
3, // 0: ethereum.validator.accounts.v2.SignRequest.block:type_name -> ethereum.eth.v1alpha1.BeaconBlock
4, // 1: ethereum.validator.accounts.v2.SignRequest.attestation_data:type_name -> ethereum.eth.v1alpha1.AttestationData
5, // 2: ethereum.validator.accounts.v2.SignRequest.aggregate_attestation_and_proof:type_name -> ethereum.eth.v1alpha1.AggregateAttestationAndProof
6, // 3: ethereum.validator.accounts.v2.SignRequest.exit:type_name -> ethereum.eth.v1alpha1.VoluntaryExit
7, // 4: ethereum.validator.accounts.v2.SignRequest.block_altair:type_name -> ethereum.eth.v1alpha1.BeaconBlockAltair
8, // 5: ethereum.validator.accounts.v2.SignRequest.sync_aggregator_selection_data:type_name -> ethereum.eth.v1alpha1.SyncAggregatorSelectionData
9, // 6: ethereum.validator.accounts.v2.SignRequest.contribution_and_proof:type_name -> ethereum.eth.v1alpha1.ContributionAndProof
10, // 7: ethereum.validator.accounts.v2.SignRequest.block_bellatrix:type_name -> ethereum.eth.v1alpha1.BeaconBlockBellatrix
11, // 8: ethereum.validator.accounts.v2.SignRequest.blinded_block_bellatrix:type_name -> ethereum.eth.v1alpha1.BlindedBeaconBlockBellatrix
12, // 9: ethereum.validator.accounts.v2.SignRequest.registration:type_name -> ethereum.eth.v1alpha1.ValidatorRegistrationV1
13, // 10: ethereum.validator.accounts.v2.SignRequest.block_capella:type_name -> ethereum.eth.v1alpha1.BeaconBlockCapella
14, // 11: ethereum.validator.accounts.v2.SignRequest.blinded_block_capella:type_name -> ethereum.eth.v1alpha1.BlindedBeaconBlockCapella
15, // 12: ethereum.validator.accounts.v2.SignRequest.block_deneb:type_name -> ethereum.eth.v1alpha1.BeaconBlockDeneb
16, // 13: ethereum.validator.accounts.v2.SignRequest.blinded_block_deneb:type_name -> ethereum.eth.v1alpha1.BlindedBeaconBlockDeneb
0, // 14: ethereum.validator.accounts.v2.SignResponse.status:type_name -> ethereum.validator.accounts.v2.SignResponse.Status
4, // 15: ethereum.validator.accounts.v2.ProposerOptionPayload.builder:type_name -> ethereum.validator.accounts.v2.BuilderConfig
6, // 16: ethereum.validator.accounts.v2.ProposerSettingsPayload.proposer_config:type_name -> ethereum.validator.accounts.v2.ProposerSettingsPayload.ProposerConfigEntry
3, // 17: ethereum.validator.accounts.v2.ProposerSettingsPayload.default_config:type_name -> ethereum.validator.accounts.v2.ProposerOptionPayload
3, // 18: ethereum.validator.accounts.v2.ProposerSettingsPayload.ProposerConfigEntry.value:type_name -> ethereum.validator.accounts.v2.ProposerOptionPayload
19, // [19:19] is the sub-list for method output_type
19, // [19:19] is the sub-list for method input_type
19, // [19:19] is the sub-list for extension type_name
19, // [19:19] is the sub-list for extension extendee
0, // [0:19] is the sub-list for field type_name
15, // [15:15] is the sub-list for method output_type
15, // [15:15] is the sub-list for method input_type
15, // [15:15] is the sub-list for extension type_name
15, // [15:15] is the sub-list for extension extendee
0, // [0:15] is the sub-list for field type_name
}
func init() { file_proto_prysm_v1alpha1_validator_client_keymanager_proto_init() }
@@ -923,42 +699,6 @@ func file_proto_prysm_v1alpha1_validator_client_keymanager_proto_init() {
return nil
}
}
file_proto_prysm_v1alpha1_validator_client_keymanager_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ProposerOptionPayload); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_proto_prysm_v1alpha1_validator_client_keymanager_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*BuilderConfig); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_proto_prysm_v1alpha1_validator_client_keymanager_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ProposerSettingsPayload); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
file_proto_prysm_v1alpha1_validator_client_keymanager_proto_msgTypes[0].OneofWrappers = []interface{}{
(*SignRequest_Block)(nil),
@@ -985,7 +725,7 @@ func file_proto_prysm_v1alpha1_validator_client_keymanager_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_proto_prysm_v1alpha1_validator_client_keymanager_proto_rawDesc,
NumEnums: 1,
NumMessages: 6,
NumMessages: 2,
NumExtensions: 0,
NumServices: 0,
},

View File

@@ -81,23 +81,4 @@ message SignResponse {
// to ensure different remote signing servers follow the
// same conventions.
Status status = 2;
}
// ProposerOptionPayload is a property of ProposerSettingsPayload
message ProposerOptionPayload {
string fee_recipient = 1;
BuilderConfig builder = 2;
}
// BuilderConfig is a property of ProposerOptionPayload
message BuilderConfig {
bool enabled = 1;
uint64 gas_limit = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v4/consensus-types/validator.Uint64"];
repeated string relays = 3;
}
// ProposerSettingsPayload is used to unmarshal files sent from the validator flag as well as safe to bolt db bucket
message ProposerSettingsPayload {
map<string, ProposerOptionPayload> proposer_config = 1;
ProposerOptionPayload default_config = 2;
}

View File

@@ -20,7 +20,7 @@ mainnet = {
"sync_committee_aggregate_bytes.size": "16",
"sync_committee_aggregate_bits.type": "github.com/prysmaticlabs/go-bitfield.Bitvector128",
"withdrawal.size": "16",
"blob.size": "131072",
"blob.size": "131072", # BYTES_PER_FIELD_ELEMENT * FIELD_ELEMENTS_PER_BLOB
"logs_bloom.size": "256",
"extra_data.size": "32",
"max_blobs_per_block.size": "6",

View File

@@ -31,7 +31,7 @@ go_library(
"//config/params:go_default_library",
"//crypto/bls:go_default_library",
"//io/file:go_default_library",
"//proto/prysm/v1alpha1/validator-client:go_default_library",
"//proto/prysm/config:go_default_library",
"//runtime/interop:go_default_library",
"//testing/endtoend/helpers:go_default_library",
"//testing/endtoend/params:go_default_library",

View File

@@ -21,7 +21,7 @@ import (
fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams"
"github.com/prysmaticlabs/prysm/v4/config/params"
"github.com/prysmaticlabs/prysm/v4/io/file"
validatorpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1/validator-client"
proposersettings "github.com/prysmaticlabs/prysm/v4/proto/prysm/config"
"github.com/prysmaticlabs/prysm/v4/runtime/interop"
"github.com/prysmaticlabs/prysm/v4/testing/endtoend/helpers"
e2e "github.com/prysmaticlabs/prysm/v4/testing/endtoend/params"
@@ -340,16 +340,16 @@ func createProposerSettingsPath(pubkeys []string, nodeIdx int) (string, error) {
if len(pubkeys) == 0 {
return "", errors.New("number of validators must be greater than 0")
}
config := make(map[string]*validatorpb.ProposerOptionPayload)
config := make(map[string]*proposersettings.ProposerOptionPayload)
for i, pubkey := range pubkeys {
config[pubkeys[i]] = &validatorpb.ProposerOptionPayload{
config[pubkeys[i]] = &proposersettings.ProposerOptionPayload{
FeeRecipient: FeeRecipientFromPubkey(pubkey),
}
}
proposerSettingsPayload := &validatorpb.ProposerSettingsPayload{
proposerSettingsPayload := &proposersettings.ProposerSettingsPayload{
ProposerConfig: config,
DefaultConfig: &validatorpb.ProposerOptionPayload{
DefaultConfig: &proposersettings.ProposerOptionPayload{
FeeRecipient: DefaultFeeRecipientAddress,
},
}

View File

@@ -32,6 +32,7 @@ go_library(
"//encoding/bytesutil:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//time/slots:go_default_library",
"@com_github_pkg_errors//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
],
)

View File

@@ -1,9 +1,11 @@
package simulator
import (
"bytes"
"context"
"math"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/core/signing"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state"
@@ -88,10 +90,31 @@ func (s *Simulator) generateAttestationsForSlot(
}
slashableAtt.Signature = aggSig.Marshal()
slashedIndices = append(slashedIndices, slashableAtt.AttestingIndices...)
slashings = append(slashings, &ethpb.AttesterSlashing{
attDataRoot, err := att.Data.HashTreeRoot()
if err != nil {
return nil, nil, errors.Wrap(err, "cannot compte `att` hash tree root")
}
slashableAttDataRoot, err := slashableAtt.Data.HashTreeRoot()
if err != nil {
return nil, nil, errors.Wrap(err, "cannot compte `slashableAtt` hash tree root")
}
slashing := &ethpb.AttesterSlashing{
Attestation_1: att,
Attestation_2: slashableAtt,
})
}
// Ensure the attestation with the lower data root is the first attestation.
if bytes.Compare(attDataRoot[:], slashableAttDataRoot[:]) > 0 {
slashing = &ethpb.AttesterSlashing{
Attestation_1: slashableAtt,
Attestation_2: att,
}
}
slashings = append(slashings, slashing)
attestations = append(attestations, slashableAtt)
}
}

View File

@@ -55,7 +55,7 @@ func (acm *CLIManager) Delete(ctx context.Context) error {
}); err != nil {
return err
}
log.WithField("publicKeys", allAccountStr).Warn(
log.WithField("pubkeys", allAccountStr).Warn(
"Attempted to delete accounts. IMPORTANT: please run `validator accounts list` to ensure " +
"the public keys are indeed deleted. If they are still there, please file an issue at " +
"https://github.com/prysmaticlabs/prysm/issues/new")

View File

@@ -154,9 +154,14 @@ func displayExitInfo(rawExitedKeys [][]byte, trimmedExitedKeys []string) {
urlFormattedPubKeys := make([]string, len(rawExitedKeys))
for i, key := range rawExitedKeys {
var baseUrl string
if params.BeaconConfig().ConfigName == params.PraterName || params.BeaconConfig().ConfigName == params.GoerliName {
switch params.BeaconConfig().ConfigName {
case params.PraterName, params.GoerliName:
baseUrl = "https://goerli.beaconcha.in/validator/"
} else {
case params.HoleskyName:
baseUrl = "https://holesky.beaconcha.in/validator/"
case params.SepoliaName:
baseUrl = "https://sepolia.beaconcha.in/validator/"
default:
baseUrl = "https://beaconcha.in/validator/"
}
// Remove '0x' prefix
@@ -171,7 +176,7 @@ func displayExitInfo(rawExitedKeys [][]byte, trimmedExitedKeys []string) {
info := fmt.Sprintf("Voluntary exit was successful for the accounts listed. "+
"URLs where you can track each validator's exit:\n"+strings.Repeat("%s\n", len(ifaceKeys)), ifaceKeys...)
log.WithField("publicKeys", strings.Join(trimmedExitedKeys, ", ")).Info(info)
log.WithField("pubkeys", strings.Join(trimmedExitedKeys, ", ")).Info(info)
} else {
log.Info("No successful voluntary exits")
}

View File

@@ -10,7 +10,7 @@ go_library(
"//validator:__subpackages__",
],
deps = [
"//config/validator/service:go_default_library",
"//config/proposer:go_default_library",
"//consensus-types/primitives:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//validator/accounts/iface:go_default_library",

View File

@@ -7,7 +7,7 @@ import (
"sync"
"time"
validatorserviceconfig "github.com/prysmaticlabs/prysm/v4/config/validator/service"
"github.com/prysmaticlabs/prysm/v4/config/proposer"
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v4/validator/accounts/iface"
@@ -89,10 +89,10 @@ func (_ *Wallet) InitializeKeymanager(_ context.Context, _ iface.InitKeymanagerC
type Validator struct {
Km keymanager.IKeymanager
proposerSettings *validatorserviceconfig.ProposerSettings
proposerSettings *proposer.ProposerSettings
}
func (_ *Validator) LogSyncCommitteeMessagesSubmitted() {}
func (_ *Validator) LogSubmittedSyncCommitteeMessages() {}
func (_ *Validator) Done() {
panic("implement me")
@@ -154,7 +154,7 @@ func (_ *Validator) SubmitSignedContributionAndProof(_ context.Context, _ primit
panic("implement me")
}
func (_ *Validator) LogAttestationsSubmitted() {
func (_ *Validator) LogSubmittedAtts(_ primitives.Slot) {
panic("implement me")
}
@@ -203,12 +203,12 @@ func (_ *Validator) SignValidatorRegistrationRequest(_ context.Context, _ iface2
}
// ProposerSettings for mocking
func (m *Validator) ProposerSettings() *validatorserviceconfig.ProposerSettings {
func (m *Validator) ProposerSettings() *proposer.ProposerSettings {
return m.proposerSettings
}
// SetProposerSettings for mocking
func (m *Validator) SetProposerSettings(_ context.Context, settings *validatorserviceconfig.ProposerSettings) error {
func (m *Validator) SetProposerSettings(_ context.Context, settings *proposer.ProposerSettings) error {
m.proposerSettings = settings
return nil
}

View File

@@ -36,7 +36,7 @@ go_library(
"//config/features:go_default_library",
"//config/fieldparams:go_default_library",
"//config/params:go_default_library",
"//config/validator/service:go_default_library",
"//config/proposer:go_default_library",
"//consensus-types/blocks:go_default_library",
"//consensus-types/interfaces:go_default_library",
"//consensus-types/primitives:go_default_library",
@@ -126,7 +126,7 @@ go_test(
"//config/features:go_default_library",
"//config/fieldparams:go_default_library",
"//config/params:go_default_library",
"//config/validator/service:go_default_library",
"//config/proposer:go_default_library",
"//consensus-types/blocks:go_default_library",
"//consensus-types/blocks/testing:go_default_library",
"//consensus-types/interfaces:go_default_library",

View File

@@ -124,7 +124,7 @@ func (v *validator) SubmitAggregateAndProof(ctx context.Context, slot primitives
return
}
if err := v.addIndicesToLog(duty); err != nil {
if err := v.saveSubmittedAtt(res.AggregateAndProof.Aggregate.Data, pubKey[:], true); err != nil {
log.WithError(err).Error("Could not add aggregator indices to logs")
if v.emitAccountMetrics {
ValidatorAggFailVec.WithLabelValues(fmtKey).Inc()
@@ -216,16 +216,3 @@ func (v *validator) aggregateAndProofSig(ctx context.Context, pubKey [fieldparam
return sig.Marshal(), nil
}
func (v *validator) addIndicesToLog(duty *ethpb.DutiesResponse_Duty) error {
v.attLogsLock.Lock()
defer v.attLogsLock.Unlock()
for _, log := range v.attLogs {
if duty.CommitteeIndex == log.data.CommitteeIndex {
log.aggregatorIndices = append(log.aggregatorIndices, duty.ValidatorIndex)
}
}
return nil
}

View File

@@ -3,11 +3,11 @@ package client
import (
"bytes"
"context"
"errors"
"fmt"
"strings"
"time"
"github.com/pkg/errors"
"github.com/prysmaticlabs/go-bitfield"
"github.com/prysmaticlabs/prysm/v4/async"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/core/signing"
@@ -15,7 +15,6 @@ import (
fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams"
"github.com/prysmaticlabs/prysm/v4/config/params"
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v4/crypto/hash"
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
"github.com/prysmaticlabs/prysm/v4/monitoring/tracing"
ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
@@ -55,7 +54,7 @@ func (v *validator) SubmitAttestation(ctx context.Context, slot primitives.Slot,
defer lock.Unlock()
fmtKey := fmt.Sprintf("%#x", pubKey[:])
log := log.WithField("pubKey", fmt.Sprintf("%#x", bytesutil.Trunc(pubKey[:]))).WithField("slot", slot)
log := log.WithField("pubkey", fmt.Sprintf("%#x", bytesutil.Trunc(pubKey[:]))).WithField("slot", slot)
duty, err := v.duty(pubKey)
if err != nil {
log.WithError(err).Error("Could not fetch validator assignment")
@@ -154,7 +153,7 @@ func (v *validator) SubmitAttestation(ctx context.Context, slot primitives.Slot,
return
}
if err := v.saveAttesterIndexToData(data, duty.ValidatorIndex); err != nil {
if err := v.saveSubmittedAtt(data, pubKey[:], false); err != nil {
log.WithError(err).Error("Could not save validator index for logging")
if v.emitAccountMetrics {
ValidatorAttestFailVec.WithLabelValues(fmtKey).Inc()
@@ -228,25 +227,6 @@ func (v *validator) getDomainAndSigningRoot(ctx context.Context, data *ethpb.Att
return domain, root, nil
}
// For logging, this saves the last submitted attester index to its attestation data. The purpose of this
// is to enhance attesting logs to be readable when multiple validator keys ran in a single client.
func (v *validator) saveAttesterIndexToData(data *ethpb.AttestationData, index primitives.ValidatorIndex) error {
v.attLogsLock.Lock()
defer v.attLogsLock.Unlock()
h, err := hash.Proto(data)
if err != nil {
return err
}
if v.attLogs[h] == nil {
v.attLogs[h] = &attSubmitted{data, []primitives.ValidatorIndex{}, []primitives.ValidatorIndex{}}
}
v.attLogs[h] = &attSubmitted{data, append(v.attLogs[h].attesterIndices, index), []primitives.ValidatorIndex{}}
return nil
}
// highestSlot returns the highest slot with a valid block seen by the validator
func (v *validator) highestSlot() primitives.Slot {
v.highestValidSlotLock.Lock()
@@ -313,14 +293,14 @@ func (v *validator) waitOneThirdOrValidBlock(ctx context.Context, slot primitive
func attestationLogFields(pubKey [fieldparams.BLSPubkeyLength]byte, indexedAtt *ethpb.IndexedAttestation) logrus.Fields {
return logrus.Fields{
"attesterPublicKey": fmt.Sprintf("%#x", pubKey),
"attestationSlot": indexedAtt.Data.Slot,
"committeeIndex": indexedAtt.Data.CommitteeIndex,
"beaconBlockRoot": fmt.Sprintf("%#x", indexedAtt.Data.BeaconBlockRoot),
"sourceEpoch": indexedAtt.Data.Source.Epoch,
"sourceRoot": fmt.Sprintf("%#x", indexedAtt.Data.Source.Root),
"targetEpoch": indexedAtt.Data.Target.Epoch,
"targetRoot": fmt.Sprintf("%#x", indexedAtt.Data.Target.Root),
"signature": fmt.Sprintf("%#x", indexedAtt.Signature),
"pubkey": fmt.Sprintf("%#x", pubKey),
"slot": indexedAtt.Data.Slot,
"committeeIndex": indexedAtt.Data.CommitteeIndex,
"blockRoot": fmt.Sprintf("%#x", indexedAtt.Data.BeaconBlockRoot),
"sourceEpoch": indexedAtt.Data.Source.Epoch,
"sourceRoot": fmt.Sprintf("%#x", indexedAtt.Data.Source.Root),
"targetEpoch": indexedAtt.Data.Target.Epoch,
"targetRoot": fmt.Sprintf("%#x", indexedAtt.Data.Target.Root),
"signature": fmt.Sprintf("%#x", indexedAtt.Signature),
}
}

Some files were not shown because too many files have changed in this diff Show More