mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-11 06:18:05 -05:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8d444a941d | ||
|
|
feb16ae4aa | ||
|
|
219301339c | ||
|
|
aec349f75a | ||
|
|
5f909caedf | ||
|
|
ba6dff3adb | ||
|
|
8cd05f098b | ||
|
|
425f5387fa | ||
|
|
f2ce115ade | ||
|
|
090a3e1ded | ||
|
|
c0acb7d352 | ||
|
|
0d6070e6fc | ||
|
|
bd00f851f0 |
@@ -1,11 +1,24 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_library")
|
||||
load("@prysm//tools/go:def.bzl", "go_library", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"constants.go",
|
||||
"headers.go",
|
||||
"jwt.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v5/api",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//crypto/rand:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["jwt_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = ["//testing/require:go_default_library"],
|
||||
)
|
||||
|
||||
@@ -4,4 +4,6 @@ const (
|
||||
WebUrlPrefix = "/v2/validator/"
|
||||
WebApiUrlPrefix = "/api/v2/validator/"
|
||||
KeymanagerApiPrefix = "/eth/v1"
|
||||
|
||||
AuthTokenFileName = "auth-token"
|
||||
)
|
||||
|
||||
32
api/jwt.go
Normal file
32
api/jwt.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/crypto/rand"
|
||||
)
|
||||
|
||||
// GenerateRandomHexString generates a random hex string that follows the standards for jwt token
|
||||
// used for beacon node -> execution client
|
||||
// used for web client -> validator client
|
||||
func GenerateRandomHexString() (string, error) {
|
||||
secret := make([]byte, 32)
|
||||
randGen := rand.NewGenerator()
|
||||
n, err := randGen.Read(secret)
|
||||
if err != nil {
|
||||
return "", err
|
||||
} else if n != 32 {
|
||||
return "", errors.New("rand: unexpected length")
|
||||
}
|
||||
return hexutil.Encode(secret), nil
|
||||
}
|
||||
|
||||
// ValidateAuthToken validating auth token for web
|
||||
func ValidateAuthToken(token string) error {
|
||||
b, err := hexutil.Decode(token)
|
||||
// token should be hex-encoded and at least 256 bits
|
||||
if err != nil || len(b) < 32 {
|
||||
return errors.New("invalid auth token: token should be hex-encoded and at least 256 bits")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
13
api/jwt_test.go
Normal file
13
api/jwt_test.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
)
|
||||
|
||||
func TestGenerateRandomHexString(t *testing.T) {
|
||||
token, err := GenerateRandomHexString()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, ValidateAuthToken(token))
|
||||
}
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers"
|
||||
f "github.com/prysmaticlabs/prysm/v5/beacon-chain/forkchoice"
|
||||
doublylinkedtree "github.com/prysmaticlabs/prysm/v5/beacon-chain/forkchoice/doubly-linked-tree"
|
||||
forkchoicetypes "github.com/prysmaticlabs/prysm/v5/beacon-chain/forkchoice/types"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/params"
|
||||
@@ -399,14 +398,6 @@ func (s *Service) InForkchoice(root [32]byte) bool {
|
||||
return s.cfg.ForkChoiceStore.HasNode(root)
|
||||
}
|
||||
|
||||
// IsViableForCheckpoint returns whether the given checkpoint is a checkpoint in any
|
||||
// chain known to forkchoice
|
||||
func (s *Service) IsViableForCheckpoint(cp *forkchoicetypes.Checkpoint) (bool, error) {
|
||||
s.cfg.ForkChoiceStore.RLock()
|
||||
defer s.cfg.ForkChoiceStore.RUnlock()
|
||||
return s.cfg.ForkChoiceStore.IsViableForCheckpoint(cp)
|
||||
}
|
||||
|
||||
// IsOptimisticForRoot takes the root as argument instead of the current head
|
||||
// and returns true if it is optimistic.
|
||||
func (s *Service) IsOptimisticForRoot(ctx context.Context, root [32]byte) (bool, error) {
|
||||
|
||||
@@ -92,7 +92,7 @@ func (e *cacheEntry) filter(root [32]byte, kc safeCommitmentArray) ([]blocks.ROB
|
||||
if e.diskSummary.AllAvailable(kc.count()) {
|
||||
return nil, nil
|
||||
}
|
||||
scs := make([]blocks.ROBlob, kc.count())
|
||||
scs := make([]blocks.ROBlob, 0, kc.count())
|
||||
for i := uint64(0); i < fieldparams.MaxBlobsPerBlock; i++ {
|
||||
// We already have this blob, we don't need to write it or validate it.
|
||||
if e.diskSummary.HasIndex(i) {
|
||||
@@ -111,7 +111,7 @@ func (e *cacheEntry) filter(root [32]byte, kc safeCommitmentArray) ([]blocks.ROB
|
||||
if !bytes.Equal(kc[i], e.scs[i].KzgCommitment) {
|
||||
return nil, errors.Wrapf(errCommitmentMismatch, "root=%#x, index=%#x, commitment=%#x, block commitment=%#x", root, i, e.scs[i].KzgCommitment, kc[i])
|
||||
}
|
||||
scs[i] = *e.scs[i]
|
||||
scs = append(scs, *e.scs[i])
|
||||
}
|
||||
|
||||
return scs, nil
|
||||
|
||||
@@ -3,9 +3,14 @@ package das
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/db/filesystem"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/blocks"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/util"
|
||||
"github.com/prysmaticlabs/prysm/v5/time/slots"
|
||||
)
|
||||
|
||||
func TestCacheEnsureDelete(t *testing.T) {
|
||||
@@ -23,3 +28,145 @@ func TestCacheEnsureDelete(t *testing.T) {
|
||||
var nilEntry *cacheEntry
|
||||
require.Equal(t, nilEntry, c.entries[k])
|
||||
}
|
||||
|
||||
type filterTestCaseSetupFunc func(t *testing.T) (*cacheEntry, safeCommitmentArray, []blocks.ROBlob)
|
||||
|
||||
func filterTestCaseSetup(slot primitives.Slot, nBlobs int, onDisk []int, numExpected int) filterTestCaseSetupFunc {
|
||||
return func(t *testing.T) (*cacheEntry, safeCommitmentArray, []blocks.ROBlob) {
|
||||
blk, blobs := util.GenerateTestDenebBlockWithSidecar(t, [32]byte{}, slot, nBlobs)
|
||||
commits, err := commitmentsToCheck(blk, blk.Block().Slot())
|
||||
require.NoError(t, err)
|
||||
entry := &cacheEntry{}
|
||||
if len(onDisk) > 0 {
|
||||
od := map[[32]byte][]int{blk.Root(): onDisk}
|
||||
sumz := filesystem.NewMockBlobStorageSummarizer(t, od)
|
||||
sum := sumz.Summary(blk.Root())
|
||||
entry.setDiskSummary(sum)
|
||||
}
|
||||
expected := make([]blocks.ROBlob, 0, nBlobs)
|
||||
for i := 0; i < commits.count(); i++ {
|
||||
if entry.diskSummary.HasIndex(uint64(i)) {
|
||||
continue
|
||||
}
|
||||
// If we aren't telling the cache a blob is on disk, add it to the expected list and stash.
|
||||
expected = append(expected, blobs[i])
|
||||
require.NoError(t, entry.stash(&blobs[i]))
|
||||
}
|
||||
require.Equal(t, numExpected, len(expected))
|
||||
return entry, commits, expected
|
||||
}
|
||||
}
|
||||
|
||||
func TestFilterDiskSummary(t *testing.T) {
|
||||
denebSlot, err := slots.EpochStart(params.BeaconConfig().DenebForkEpoch)
|
||||
require.NoError(t, err)
|
||||
cases := []struct {
|
||||
name string
|
||||
setup filterTestCaseSetupFunc
|
||||
}{
|
||||
{
|
||||
name: "full blobs, all on disk",
|
||||
setup: filterTestCaseSetup(denebSlot, 6, []int{0, 1, 2, 3, 4, 5}, 0),
|
||||
},
|
||||
{
|
||||
name: "full blobs, first on disk",
|
||||
setup: filterTestCaseSetup(denebSlot, 6, []int{0}, 5),
|
||||
},
|
||||
{
|
||||
name: "full blobs, middle on disk",
|
||||
setup: filterTestCaseSetup(denebSlot, 6, []int{2}, 5),
|
||||
},
|
||||
{
|
||||
name: "full blobs, last on disk",
|
||||
setup: filterTestCaseSetup(denebSlot, 6, []int{5}, 5),
|
||||
},
|
||||
{
|
||||
name: "full blobs, none on disk",
|
||||
setup: filterTestCaseSetup(denebSlot, 6, []int{}, 6),
|
||||
},
|
||||
{
|
||||
name: "one commitment, on disk",
|
||||
setup: filterTestCaseSetup(denebSlot, 1, []int{0}, 0),
|
||||
},
|
||||
{
|
||||
name: "one commitment, not on disk",
|
||||
setup: filterTestCaseSetup(denebSlot, 1, []int{}, 1),
|
||||
},
|
||||
{
|
||||
name: "two commitments, first on disk",
|
||||
setup: filterTestCaseSetup(denebSlot, 2, []int{0}, 1),
|
||||
},
|
||||
{
|
||||
name: "two commitments, last on disk",
|
||||
setup: filterTestCaseSetup(denebSlot, 2, []int{1}, 1),
|
||||
},
|
||||
{
|
||||
name: "two commitments, none on disk",
|
||||
setup: filterTestCaseSetup(denebSlot, 2, []int{}, 2),
|
||||
},
|
||||
{
|
||||
name: "two commitments, all on disk",
|
||||
setup: filterTestCaseSetup(denebSlot, 2, []int{0, 1}, 0),
|
||||
},
|
||||
}
|
||||
for _, c := range cases {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
entry, commits, expected := c.setup(t)
|
||||
// first (root) argument doesn't matter, it is just for logs
|
||||
got, err := entry.filter([32]byte{}, commits)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, len(expected), len(got))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFilter(t *testing.T) {
|
||||
denebSlot, err := slots.EpochStart(params.BeaconConfig().DenebForkEpoch)
|
||||
require.NoError(t, err)
|
||||
cases := []struct {
|
||||
name string
|
||||
setup func(t *testing.T) (*cacheEntry, safeCommitmentArray, []blocks.ROBlob)
|
||||
err error
|
||||
}{
|
||||
{
|
||||
name: "commitments mismatch - extra sidecar",
|
||||
setup: func(t *testing.T) (*cacheEntry, safeCommitmentArray, []blocks.ROBlob) {
|
||||
entry, commits, expected := filterTestCaseSetup(denebSlot, 6, []int{0, 1}, 4)(t)
|
||||
commits[5] = nil
|
||||
return entry, commits, expected
|
||||
},
|
||||
err: errCommitmentMismatch,
|
||||
},
|
||||
{
|
||||
name: "sidecar missing",
|
||||
setup: func(t *testing.T) (*cacheEntry, safeCommitmentArray, []blocks.ROBlob) {
|
||||
entry, commits, expected := filterTestCaseSetup(denebSlot, 6, []int{0, 1}, 4)(t)
|
||||
entry.scs[5] = nil
|
||||
return entry, commits, expected
|
||||
},
|
||||
err: errMissingSidecar,
|
||||
},
|
||||
{
|
||||
name: "commitments mismatch - different bytes",
|
||||
setup: func(t *testing.T) (*cacheEntry, safeCommitmentArray, []blocks.ROBlob) {
|
||||
entry, commits, expected := filterTestCaseSetup(denebSlot, 6, []int{0, 1}, 4)(t)
|
||||
entry.scs[5].KzgCommitment = []byte("nope")
|
||||
return entry, commits, expected
|
||||
},
|
||||
err: errCommitmentMismatch,
|
||||
},
|
||||
}
|
||||
for _, c := range cases {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
entry, commits, expected := c.setup(t)
|
||||
// first (root) argument doesn't matter, it is just for logs
|
||||
got, err := entry.filter([32]byte{}, commits)
|
||||
if c.err != nil {
|
||||
require.ErrorIs(t, err, c.err)
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, len(expected), len(got))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package filesystem
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math"
|
||||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
@@ -299,6 +300,15 @@ func (bs *BlobStorage) Clear() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// WithinRetentionPeriod checks if the requested epoch is within the blob retention period.
|
||||
func (bs *BlobStorage) WithinRetentionPeriod(requested, current primitives.Epoch) bool {
|
||||
if requested > math.MaxUint64-bs.retentionEpochs {
|
||||
// If there is an overflow, then the retention period was set to an extremely large number.
|
||||
return true
|
||||
}
|
||||
return requested+bs.retentionEpochs >= current
|
||||
}
|
||||
|
||||
type blobNamer struct {
|
||||
root [32]byte
|
||||
index uint64
|
||||
|
||||
@@ -2,6 +2,7 @@ package filesystem
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"math"
|
||||
"os"
|
||||
"path"
|
||||
"sync"
|
||||
@@ -24,8 +25,7 @@ func TestBlobStorage_SaveBlobData(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Run("no error for duplicate", func(t *testing.T) {
|
||||
fs, bs, err := NewEphemeralBlobStorageWithFs(t)
|
||||
require.NoError(t, err)
|
||||
fs, bs := NewEphemeralBlobStorageWithFs(t)
|
||||
existingSidecar := testSidecars[0]
|
||||
|
||||
blobPath := namerForSidecar(existingSidecar).path()
|
||||
@@ -129,8 +129,7 @@ func TestBlobStorage_SaveBlobData(t *testing.T) {
|
||||
// pollUntil polls a condition function until it returns true or a timeout is reached.
|
||||
|
||||
func TestBlobIndicesBounds(t *testing.T) {
|
||||
fs, bs, err := NewEphemeralBlobStorageWithFs(t)
|
||||
require.NoError(t, err)
|
||||
fs, bs := NewEphemeralBlobStorageWithFs(t)
|
||||
root := [32]byte{}
|
||||
|
||||
okIdx := uint64(fieldparams.MaxBlobsPerBlock - 1)
|
||||
@@ -161,8 +160,7 @@ func writeFakeSSZ(t *testing.T, fs afero.Fs, root [32]byte, idx uint64) {
|
||||
|
||||
func TestBlobStoragePrune(t *testing.T) {
|
||||
currentSlot := primitives.Slot(200000)
|
||||
fs, bs, err := NewEphemeralBlobStorageWithFs(t)
|
||||
require.NoError(t, err)
|
||||
fs, bs := NewEphemeralBlobStorageWithFs(t)
|
||||
|
||||
t.Run("PruneOne", func(t *testing.T) {
|
||||
_, sidecars := util.GenerateTestDenebBlockWithSidecar(t, [32]byte{}, 300, fieldparams.MaxBlobsPerBlock)
|
||||
@@ -218,8 +216,7 @@ func TestBlobStoragePrune(t *testing.T) {
|
||||
|
||||
func BenchmarkPruning(b *testing.B) {
|
||||
var t *testing.T
|
||||
_, bs, err := NewEphemeralBlobStorageWithFs(t)
|
||||
require.NoError(t, err)
|
||||
_, bs := NewEphemeralBlobStorageWithFs(t)
|
||||
|
||||
blockQty := 10000
|
||||
currentSlot := primitives.Slot(150000)
|
||||
@@ -248,3 +245,50 @@ func TestNewBlobStorage(t *testing.T) {
|
||||
_, err = NewBlobStorage(WithBasePath(path.Join(t.TempDir(), "good")))
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestConfig_WithinRetentionPeriod(t *testing.T) {
|
||||
retention := primitives.Epoch(16)
|
||||
storage := &BlobStorage{retentionEpochs: retention}
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
requested primitives.Epoch
|
||||
current primitives.Epoch
|
||||
within bool
|
||||
}{
|
||||
{
|
||||
name: "before",
|
||||
requested: 0,
|
||||
current: retention + 1,
|
||||
within: false,
|
||||
},
|
||||
{
|
||||
name: "same",
|
||||
requested: 0,
|
||||
current: 0,
|
||||
within: true,
|
||||
},
|
||||
{
|
||||
name: "boundary",
|
||||
requested: 0,
|
||||
current: retention,
|
||||
within: true,
|
||||
},
|
||||
{
|
||||
name: "one less",
|
||||
requested: retention - 1,
|
||||
current: retention,
|
||||
within: true,
|
||||
},
|
||||
}
|
||||
for _, c := range cases {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
require.Equal(t, c.within, storage.WithinRetentionPeriod(c.requested, c.current))
|
||||
})
|
||||
}
|
||||
|
||||
t.Run("overflow", func(t *testing.T) {
|
||||
storage := &BlobStorage{retentionEpochs: math.MaxUint64}
|
||||
require.Equal(t, true, storage.WithinRetentionPeriod(1, 1))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -21,13 +21,13 @@ func NewEphemeralBlobStorage(t testing.TB) *BlobStorage {
|
||||
|
||||
// NewEphemeralBlobStorageWithFs can be used by tests that want access to the virtual filesystem
|
||||
// in order to interact with it outside the parameters of the BlobStorage api.
|
||||
func NewEphemeralBlobStorageWithFs(t testing.TB) (afero.Fs, *BlobStorage, error) {
|
||||
func NewEphemeralBlobStorageWithFs(t testing.TB) (afero.Fs, *BlobStorage) {
|
||||
fs := afero.NewMemMapFs()
|
||||
pruner, err := newBlobPruner(fs, params.BeaconConfig().MinEpochsForBlobsSidecarsRequest, withWarmedCache())
|
||||
if err != nil {
|
||||
t.Fatal("test setup issue", err)
|
||||
}
|
||||
return fs, &BlobStorage{fs: fs, pruner: pruner}, nil
|
||||
return fs, &BlobStorage{fs: fs, pruner: pruner}
|
||||
}
|
||||
|
||||
type BlobMocker struct {
|
||||
|
||||
@@ -51,8 +51,7 @@ func TestTryPruneDir_CachedExpired(t *testing.T) {
|
||||
require.Equal(t, 0, pruned)
|
||||
})
|
||||
t.Run("blobs to delete", func(t *testing.T) {
|
||||
fs, bs, err := NewEphemeralBlobStorageWithFs(t)
|
||||
require.NoError(t, err)
|
||||
fs, bs := NewEphemeralBlobStorageWithFs(t)
|
||||
var slot primitives.Slot = 0
|
||||
_, sidecars := util.GenerateTestDenebBlockWithSidecar(t, [32]byte{}, slot, 2)
|
||||
scs, err := verification.BlobSidecarSliceNoop(sidecars)
|
||||
@@ -83,8 +82,7 @@ func TestTryPruneDir_CachedExpired(t *testing.T) {
|
||||
|
||||
func TestTryPruneDir_SlotFromFile(t *testing.T) {
|
||||
t.Run("expired blobs deleted", func(t *testing.T) {
|
||||
fs, bs, err := NewEphemeralBlobStorageWithFs(t)
|
||||
require.NoError(t, err)
|
||||
fs, bs := NewEphemeralBlobStorageWithFs(t)
|
||||
var slot primitives.Slot = 0
|
||||
_, sidecars := util.GenerateTestDenebBlockWithSidecar(t, [32]byte{}, slot, 2)
|
||||
scs, err := verification.BlobSidecarSliceNoop(sidecars)
|
||||
@@ -116,8 +114,7 @@ func TestTryPruneDir_SlotFromFile(t *testing.T) {
|
||||
require.Equal(t, 0, len(files))
|
||||
})
|
||||
t.Run("not expired, intact", func(t *testing.T) {
|
||||
fs, bs, err := NewEphemeralBlobStorageWithFs(t)
|
||||
require.NoError(t, err)
|
||||
fs, bs := NewEphemeralBlobStorageWithFs(t)
|
||||
// Set slot equal to the window size, so it should be retained.
|
||||
slot := bs.pruner.windowSize
|
||||
_, sidecars := util.GenerateTestDenebBlockWithSidecar(t, [32]byte{}, slot, 2)
|
||||
@@ -184,8 +181,7 @@ func TestSlotFromFile(t *testing.T) {
|
||||
}
|
||||
for _, c := range cases {
|
||||
t.Run(fmt.Sprintf("slot %d", c.slot), func(t *testing.T) {
|
||||
fs, bs, err := NewEphemeralBlobStorageWithFs(t)
|
||||
require.NoError(t, err)
|
||||
fs, bs := NewEphemeralBlobStorageWithFs(t)
|
||||
_, sidecars := util.GenerateTestDenebBlockWithSidecar(t, [32]byte{}, c.slot, 1)
|
||||
sc, err := verification.BlobSidecarNoop(sidecars[0])
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -86,7 +86,7 @@ func (s *Service) buildOptions(ip net.IP, priKey *ecdsa.PrivateKey) ([]libp2p.Op
|
||||
return nil, errors.Wrapf(err, "cannot get ID from public key: %s", ifaceKey.GetPublic().Type().String())
|
||||
}
|
||||
|
||||
log.WithField("peerId", id).Info("Running node with id")
|
||||
log.Infof("Running node with peer id of %s ", id.String())
|
||||
|
||||
options := []libp2p.Option{
|
||||
privKeyOption(priKey),
|
||||
|
||||
@@ -369,16 +369,7 @@ func decodeIds(w http.ResponseWriter, st state.BeaconState, rawIds []string, ign
|
||||
func valsFromIds(w http.ResponseWriter, st state.BeaconState, ids []primitives.ValidatorIndex) ([]state.ReadOnlyValidator, bool) {
|
||||
var vals []state.ReadOnlyValidator
|
||||
if len(ids) == 0 {
|
||||
allVals := st.Validators()
|
||||
vals = make([]state.ReadOnlyValidator, len(allVals))
|
||||
for i, val := range allVals {
|
||||
readOnlyVal, err := statenative.NewValidator(val)
|
||||
if err != nil {
|
||||
httputil.HandleError(w, "Could not convert validator: "+err.Error(), http.StatusInternalServerError)
|
||||
return nil, false
|
||||
}
|
||||
vals[i] = readOnlyVal
|
||||
}
|
||||
vals = st.ValidatorsReadOnly()
|
||||
} else {
|
||||
vals = make([]state.ReadOnlyValidator, 0, len(ids))
|
||||
for _, id := range ids {
|
||||
|
||||
@@ -108,7 +108,7 @@ func (*Server) GetVersion(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// GetHealth returns node health status in http status codes. Useful for load balancers.
|
||||
func (s *Server) GetHealth(w http.ResponseWriter, r *http.Request) {
|
||||
_, span := trace.StartSpan(r.Context(), "node.GetHealth")
|
||||
ctx, span := trace.StartSpan(r.Context(), "node.GetHealth")
|
||||
defer span.End()
|
||||
|
||||
rawSyncingStatus, syncingStatus, ok := shared.UintFromQuery(w, r, "syncing_status", false)
|
||||
@@ -119,10 +119,14 @@ func (s *Server) GetHealth(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
if s.SyncChecker.Synced() {
|
||||
optimistic, err := s.OptimisticModeFetcher.IsOptimistic(ctx)
|
||||
if err != nil {
|
||||
httputil.HandleError(w, "Could not check optimistic status: "+err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
if s.SyncChecker.Synced() && !optimistic {
|
||||
return
|
||||
}
|
||||
if s.SyncChecker.Syncing() || s.SyncChecker.Initialized() {
|
||||
if s.SyncChecker.Syncing() || optimistic {
|
||||
if rawSyncingStatus != "" {
|
||||
w.WriteHeader(intSyncingStatus)
|
||||
} else {
|
||||
@@ -130,5 +134,6 @@ func (s *Server) GetHealth(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusServiceUnavailable)
|
||||
}
|
||||
|
||||
@@ -91,8 +91,10 @@ func TestGetVersion(t *testing.T) {
|
||||
|
||||
func TestGetHealth(t *testing.T) {
|
||||
checker := &syncmock.Sync{}
|
||||
optimisticFetcher := &mock.ChainService{Optimistic: false}
|
||||
s := &Server{
|
||||
SyncChecker: checker,
|
||||
SyncChecker: checker,
|
||||
OptimisticModeFetcher: optimisticFetcher,
|
||||
}
|
||||
|
||||
request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/node/health", nil)
|
||||
@@ -101,25 +103,30 @@ func TestGetHealth(t *testing.T) {
|
||||
s.GetHealth(writer, request)
|
||||
assert.Equal(t, http.StatusServiceUnavailable, writer.Code)
|
||||
|
||||
checker.IsInitialized = true
|
||||
request = httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/node/health", nil)
|
||||
writer = httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
s.GetHealth(writer, request)
|
||||
assert.Equal(t, http.StatusPartialContent, writer.Code)
|
||||
|
||||
checker.IsSyncing = true
|
||||
checker.IsSynced = false
|
||||
request = httptest.NewRequest(http.MethodGet, fmt.Sprintf("http://example.com/eth/v1/node/health?syncing_status=%d", http.StatusPaymentRequired), nil)
|
||||
writer = httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
s.GetHealth(writer, request)
|
||||
assert.Equal(t, http.StatusPaymentRequired, writer.Code)
|
||||
|
||||
checker.IsSyncing = false
|
||||
checker.IsSynced = true
|
||||
request = httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/node/health", nil)
|
||||
writer = httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
s.GetHealth(writer, request)
|
||||
assert.Equal(t, http.StatusOK, writer.Code)
|
||||
|
||||
checker.IsSyncing = false
|
||||
checker.IsSynced = true
|
||||
optimisticFetcher.Optimistic = true
|
||||
request = httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/node/health", nil)
|
||||
writer = httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
s.GetHealth(writer, request)
|
||||
assert.Equal(t, http.StatusPartialContent, writer.Code)
|
||||
}
|
||||
|
||||
func TestGetIdentity(t *testing.T) {
|
||||
|
||||
@@ -223,7 +223,7 @@ func (p *BeaconDbBlocker) Blobs(ctx context.Context, id string, indices []uint64
|
||||
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())) {
|
||||
if !p.BlobStorage.WithinRetentionPeriod(slots.ToEpoch(b.Block().Slot()), slots.ToEpoch(p.GenesisTimeFetcher.CurrentSlot())) {
|
||||
return make([]*blocks.VerifiedROBlob, 0), nil
|
||||
}
|
||||
commitments, err := b.Block().Body().BlobKzgCommitments()
|
||||
|
||||
@@ -164,8 +164,7 @@ func TestGetBlob(t *testing.T) {
|
||||
db := testDB.SetupDB(t)
|
||||
denebBlock, blobs := util.GenerateTestDenebBlockWithSidecar(t, [32]byte{}, 123, 4)
|
||||
require.NoError(t, db.SaveBlock(context.Background(), denebBlock))
|
||||
_, bs, err := filesystem.NewEphemeralBlobStorageWithFs(t)
|
||||
require.NoError(t, err)
|
||||
_, bs := filesystem.NewEphemeralBlobStorageWithFs(t)
|
||||
testSidecars, err := verification.BlobSidecarSliceNoop(blobs)
|
||||
require.NoError(t, err)
|
||||
for i := range testSidecars {
|
||||
|
||||
@@ -118,6 +118,7 @@ type ReadOnlyValidator interface {
|
||||
// ReadOnlyValidators defines a struct which only has read access to validators methods.
|
||||
type ReadOnlyValidators interface {
|
||||
Validators() []*ethpb.Validator
|
||||
ValidatorsReadOnly() []ReadOnlyValidator
|
||||
ValidatorAtIndex(idx primitives.ValidatorIndex) (*ethpb.Validator, error)
|
||||
ValidatorAtIndexReadOnly(idx primitives.ValidatorIndex) (ReadOnlyValidator, error)
|
||||
ValidatorIndexByPubkey(key [fieldparams.BLSPubkeyLength]byte) (primitives.ValidatorIndex, bool)
|
||||
|
||||
@@ -21,6 +21,14 @@ func (b *BeaconState) Validators() []*ethpb.Validator {
|
||||
return b.validatorsVal()
|
||||
}
|
||||
|
||||
// ValidatorsReadOnly participating in consensus on the beacon chain.
|
||||
func (b *BeaconState) ValidatorsReadOnly() []state.ReadOnlyValidator {
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
return b.validatorsReadOnlyVal()
|
||||
}
|
||||
|
||||
func (b *BeaconState) validatorsVal() []*ethpb.Validator {
|
||||
var v []*ethpb.Validator
|
||||
if features.Get().EnableExperimentalState {
|
||||
@@ -46,6 +54,35 @@ func (b *BeaconState) validatorsVal() []*ethpb.Validator {
|
||||
return res
|
||||
}
|
||||
|
||||
func (b *BeaconState) validatorsReadOnlyVal() []state.ReadOnlyValidator {
|
||||
var v []*ethpb.Validator
|
||||
if features.Get().EnableExperimentalState {
|
||||
if b.validatorsMultiValue == nil {
|
||||
return nil
|
||||
}
|
||||
v = b.validatorsMultiValue.Value(b)
|
||||
} else {
|
||||
if b.validators == nil {
|
||||
return nil
|
||||
}
|
||||
v = b.validators
|
||||
}
|
||||
|
||||
res := make([]state.ReadOnlyValidator, len(v))
|
||||
var err error
|
||||
for i := 0; i < len(res); i++ {
|
||||
val := v[i]
|
||||
if val == nil {
|
||||
continue
|
||||
}
|
||||
res[i], err = NewValidator(val)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// references of validators participating in consensus on the beacon chain.
|
||||
// This assumes that a lock is already held on BeaconState. This does not
|
||||
// copy fully and instead just copies the reference.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package backfill
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sort"
|
||||
"time"
|
||||
@@ -55,6 +56,8 @@ const (
|
||||
batchEndSequence
|
||||
)
|
||||
|
||||
var retryDelay = time.Second
|
||||
|
||||
type batchId string
|
||||
|
||||
type batch struct {
|
||||
@@ -62,6 +65,7 @@ type batch struct {
|
||||
scheduled time.Time
|
||||
seq int // sequence identifier, ie how many times has the sequence() method served this batch
|
||||
retries int
|
||||
retryAfter time.Time
|
||||
begin primitives.Slot
|
||||
end primitives.Slot // half-open interval, [begin, end), ie >= start, < end.
|
||||
results verifiedROBlocks
|
||||
@@ -74,7 +78,7 @@ type batch struct {
|
||||
}
|
||||
|
||||
func (b batch) logFields() logrus.Fields {
|
||||
return map[string]interface{}{
|
||||
f := map[string]interface{}{
|
||||
"batchId": b.id(),
|
||||
"state": b.state.String(),
|
||||
"scheduled": b.scheduled.String(),
|
||||
@@ -86,6 +90,10 @@ func (b batch) logFields() logrus.Fields {
|
||||
"blockPid": b.blockPid,
|
||||
"blobPid": b.blobPid,
|
||||
}
|
||||
if b.retries > 0 {
|
||||
f["retryAfter"] = b.retryAfter.String()
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
func (b batch) replaces(r batch) bool {
|
||||
@@ -153,7 +161,8 @@ func (b batch) withState(s batchState) batch {
|
||||
switch b.state {
|
||||
case batchErrRetryable:
|
||||
b.retries += 1
|
||||
log.WithFields(b.logFields()).Info("Sequencing batch for retry")
|
||||
b.retryAfter = time.Now().Add(retryDelay)
|
||||
log.WithFields(b.logFields()).Info("Sequencing batch for retry after delay")
|
||||
case batchInit, batchNil:
|
||||
b.firstScheduled = b.scheduled
|
||||
}
|
||||
@@ -190,8 +199,32 @@ func (b batch) availabilityStore() das.AvailabilityStore {
|
||||
return b.bs.store
|
||||
}
|
||||
|
||||
var batchBlockUntil = func(ctx context.Context, untilRetry time.Duration, b batch) error {
|
||||
log.WithFields(b.logFields()).WithField("untilRetry", untilRetry.String()).
|
||||
Debug("Sleeping for retry backoff delay")
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
case <-time.After(untilRetry):
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (b batch) waitUntilReady(ctx context.Context) error {
|
||||
// Wait to retry a failed batch to avoid hammering peers
|
||||
// if we've hit a state where batches will consistently fail.
|
||||
// Avoids spamming requests and logs.
|
||||
if b.retries > 0 {
|
||||
untilRetry := time.Until(b.retryAfter)
|
||||
if untilRetry > time.Millisecond {
|
||||
return batchBlockUntil(ctx, untilRetry, b)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func sortBatchDesc(bb []batch) {
|
||||
sort.Slice(bb, func(i, j int) bool {
|
||||
return bb[j].end < bb[i].end
|
||||
return bb[i].end > bb[j].end
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
package backfill
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
)
|
||||
@@ -19,3 +22,22 @@ func TestSortBatchDesc(t *testing.T) {
|
||||
require.Equal(t, orderOut[i], batches[i].end)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWaitUntilReady(t *testing.T) {
|
||||
b := batch{}.withState(batchErrRetryable)
|
||||
require.Equal(t, time.Time{}, b.retryAfter)
|
||||
var got time.Duration
|
||||
wur := batchBlockUntil
|
||||
var errDerp = errors.New("derp")
|
||||
batchBlockUntil = func(_ context.Context, ur time.Duration, _ batch) error {
|
||||
got = ur
|
||||
return errDerp
|
||||
}
|
||||
// retries counter and timestamp are set when we mark the batch for sequencing, if it is in the retry state
|
||||
b = b.withState(batchSequenced)
|
||||
require.ErrorIs(t, b.waitUntilReady(context.Background()), errDerp)
|
||||
require.Equal(t, true, retryDelay-time.Until(b.retryAfter) < time.Millisecond)
|
||||
require.Equal(t, true, got < retryDelay && got > retryDelay-time.Millisecond)
|
||||
require.Equal(t, 1, b.retries)
|
||||
batchBlockUntil = wur
|
||||
}
|
||||
|
||||
@@ -143,6 +143,11 @@ func (p *p2pBatchWorkerPool) batchRouter(pa PeerAssigner) {
|
||||
return
|
||||
}
|
||||
for _, pid := range assigned {
|
||||
if err := todo[0].waitUntilReady(p.ctx); err != nil {
|
||||
log.WithError(p.ctx.Err()).Info("p2pBatchWorkerPool context canceled, shutting down")
|
||||
p.shutdown(p.ctx.Err())
|
||||
return
|
||||
}
|
||||
busy[pid] = true
|
||||
todo[0].busy = pid
|
||||
p.toWorkers <- todo[0].withPeer(pid)
|
||||
|
||||
@@ -482,7 +482,10 @@ func TestSendRequest_SendBeaconBlocksByRootRequest(t *testing.T) {
|
||||
func TestBlobValidatorFromRootReq(t *testing.T) {
|
||||
rootA := bytesutil.PadTo([]byte("valid"), 32)
|
||||
rootB := bytesutil.PadTo([]byte("invalid"), 32)
|
||||
header := ðpb.SignedBeaconBlockHeader{}
|
||||
header := ðpb.SignedBeaconBlockHeader{
|
||||
Header: ðpb.BeaconBlockHeader{Slot: 0},
|
||||
Signature: make([]byte, fieldparams.BLSSignatureLength),
|
||||
}
|
||||
blobSidecarA0 := util.GenerateTestDenebBlobSidecar(t, bytesutil.ToBytes32(rootA), header, 0, []byte{}, make([][]byte, 0))
|
||||
blobSidecarA1 := util.GenerateTestDenebBlobSidecar(t, bytesutil.ToBytes32(rootA), header, 1, []byte{}, make([][]byte, 0))
|
||||
blobSidecarB0 := util.GenerateTestDenebBlobSidecar(t, bytesutil.ToBytes32(rootB), header, 0, []byte{}, make([][]byte, 0))
|
||||
@@ -590,7 +593,8 @@ func TestBlobValidatorFromRangeReq(t *testing.T) {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
vf := blobValidatorFromRangeReq(c.req)
|
||||
header := ðpb.SignedBeaconBlockHeader{
|
||||
Header: ðpb.BeaconBlockHeader{Slot: c.responseSlot},
|
||||
Header: ðpb.BeaconBlockHeader{Slot: c.responseSlot},
|
||||
Signature: make([]byte, fieldparams.BLSSignatureLength),
|
||||
}
|
||||
sc := util.GenerateTestDenebBlobSidecar(t, [32]byte{}, header, 0, []byte{}, make([][]byte, 0))
|
||||
err := vf(sc)
|
||||
|
||||
@@ -46,10 +46,12 @@ func (batch *BlobBatchVerifier) VerifiedROBlobs(ctx context.Context, blk blocks.
|
||||
if len(scs) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
blkSig := blk.Signature()
|
||||
// We assume the proposer is validated wrt the block in batch block processing before performing the DA check.
|
||||
// So at this stage we just need to make sure the value being signed and signature bytes match the block.
|
||||
for i := range scs {
|
||||
if blk.Signature() != bytesutil.ToBytes96(scs[i].SignedBlockHeader.Signature) {
|
||||
blobSig := bytesutil.ToBytes96(scs[i].SignedBlockHeader.Signature)
|
||||
if blkSig != blobSig {
|
||||
return nil, ErrBatchSignatureMismatch
|
||||
}
|
||||
// Extra defensive check to make sure the roots match. This should be unnecessary in practice since the root from
|
||||
|
||||
@@ -6,10 +6,9 @@ go_library(
|
||||
importpath = "github.com/prysmaticlabs/prysm/v5/cmd/beacon-chain/jwt",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//api:go_default_library",
|
||||
"//cmd:go_default_library",
|
||||
"//crypto/rand:go_default_library",
|
||||
"//io/file:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@com_github_urfave_cli_v2//:go_default_library",
|
||||
],
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
package jwt
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/api"
|
||||
"github.com/prysmaticlabs/prysm/v5/cmd"
|
||||
"github.com/prysmaticlabs/prysm/v5/crypto/rand"
|
||||
"github.com/prysmaticlabs/prysm/v5/io/file"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli/v2"
|
||||
@@ -52,7 +50,7 @@ func generateAuthSecretInFile(c *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
secret, err := generateRandomHexString()
|
||||
secret, err := api.GenerateRandomHexString()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -62,15 +60,3 @@ func generateAuthSecretInFile(c *cli.Context) error {
|
||||
logrus.Infof("Successfully wrote JSON-RPC authentication secret to file %s", fileName)
|
||||
return nil
|
||||
}
|
||||
|
||||
func generateRandomHexString() (string, error) {
|
||||
secret := make([]byte, 32)
|
||||
randGen := rand.NewGenerator()
|
||||
n, err := randGen.Read(secret)
|
||||
if err != nil {
|
||||
return "", err
|
||||
} else if n <= 0 {
|
||||
return "", errors.New("rand: unexpected length")
|
||||
}
|
||||
return hexutil.Encode(secret), nil
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ go_library(
|
||||
"//validator:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
"//api:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//io/file:go_default_library",
|
||||
"@com_github_urfave_cli_v2//:go_default_library",
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/api"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v5/io/file"
|
||||
"github.com/urfave/cli/v2"
|
||||
@@ -133,6 +134,15 @@ var (
|
||||
Usage: "Port used to listening and respond metrics for Prometheus.",
|
||||
Value: 8081,
|
||||
}
|
||||
|
||||
// AuthTokenPathFlag defines the path to the auth token used to secure the validator api.
|
||||
AuthTokenPathFlag = &cli.StringFlag{
|
||||
Name: "keymanager-token-file",
|
||||
Usage: "Path to auth token file used for validator apis.",
|
||||
Value: filepath.Join(filepath.Join(DefaultValidatorDir(), WalletDefaultDirName), api.AuthTokenFileName),
|
||||
Aliases: []string{"validator-api-bearer-file"},
|
||||
}
|
||||
|
||||
// WalletDirFlag defines the path to a wallet directory for Prysm accounts.
|
||||
WalletDirFlag = &cli.StringFlag{
|
||||
Name: "wallet-dir",
|
||||
|
||||
@@ -75,6 +75,7 @@ var appFlags = []cli.Flag{
|
||||
flags.EnableWebFlag,
|
||||
flags.GraffitiFileFlag,
|
||||
flags.EnableDistributed,
|
||||
flags.AuthTokenPathFlag,
|
||||
// Consensys' Web3Signer flags
|
||||
flags.Web3SignerURLFlag,
|
||||
flags.Web3SignerPublicValidatorKeysFlag,
|
||||
|
||||
@@ -123,6 +123,7 @@ var appHelpFlagGroups = []flagGroup{
|
||||
flags.BuilderGasLimitFlag,
|
||||
flags.ValidatorsRegistrationBatchSizeFlag,
|
||||
flags.EnableDistributed,
|
||||
flags.AuthTokenPathFlag,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -9,6 +9,7 @@ go_library(
|
||||
importpath = "github.com/prysmaticlabs/prysm/v5/cmd/validator/web",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//api:go_default_library",
|
||||
"//cmd:go_default_library",
|
||||
"//cmd/validator/flags:go_default_library",
|
||||
"//config/features:go_default_library",
|
||||
|
||||
@@ -2,7 +2,9 @@ package web
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/api"
|
||||
"github.com/prysmaticlabs/prysm/v5/cmd"
|
||||
"github.com/prysmaticlabs/prysm/v5/cmd/validator/flags"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/features"
|
||||
@@ -24,6 +26,7 @@ var Commands = &cli.Command{
|
||||
flags.WalletDirFlag,
|
||||
flags.GRPCGatewayHost,
|
||||
flags.GRPCGatewayPort,
|
||||
flags.AuthTokenPathFlag,
|
||||
cmd.AcceptTosFlag,
|
||||
}),
|
||||
Before: func(cliCtx *cli.Context) error {
|
||||
@@ -43,7 +46,12 @@ var Commands = &cli.Command{
|
||||
gatewayHost := cliCtx.String(flags.GRPCGatewayHost.Name)
|
||||
gatewayPort := cliCtx.Int(flags.GRPCGatewayPort.Name)
|
||||
validatorWebAddr := fmt.Sprintf("%s:%d", gatewayHost, gatewayPort)
|
||||
if err := rpc.CreateAuthToken(walletDirPath, validatorWebAddr); err != nil {
|
||||
authTokenPath := filepath.Join(walletDirPath, api.AuthTokenFileName)
|
||||
tempAuthTokenPath := cliCtx.String(flags.AuthTokenPathFlag.Name)
|
||||
if tempAuthTokenPath != "" {
|
||||
authTokenPath = tempAuthTokenPath
|
||||
}
|
||||
if err := rpc.CreateAuthToken(authTokenPath, validatorWebAddr); err != nil {
|
||||
log.WithError(err).Fatal("Could not create web auth token")
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -244,7 +244,8 @@ func Test_VerifyKZGInclusionProof(t *testing.T) {
|
||||
StateRoot: make([]byte, 32),
|
||||
}
|
||||
signedHeader := ðpb.SignedBeaconBlockHeader{
|
||||
Header: header,
|
||||
Header: header,
|
||||
Signature: make([]byte, fieldparams.BLSSignatureLength),
|
||||
}
|
||||
sidecar := ðpb.BlobSidecar{
|
||||
Index: uint64(index),
|
||||
|
||||
@@ -1,35 +1,42 @@
|
||||
package blocks
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
var errNilBlockHeader = errors.New("received nil beacon block header")
|
||||
|
||||
// ROBlob represents a read-only blob sidecar with its block root.
|
||||
type ROBlob struct {
|
||||
*ethpb.BlobSidecar
|
||||
root [32]byte
|
||||
}
|
||||
|
||||
func roblobNilCheck(b *ethpb.BlobSidecar) error {
|
||||
if b == nil {
|
||||
return errNilBlob
|
||||
}
|
||||
if b.SignedBlockHeader == nil || b.SignedBlockHeader.Header == nil {
|
||||
return errNilBlockHeader
|
||||
}
|
||||
if len(b.SignedBlockHeader.Signature) == 0 {
|
||||
return errMissingBlockSignature
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewROBlobWithRoot creates a new ROBlob with a given root.
|
||||
func NewROBlobWithRoot(b *ethpb.BlobSidecar, root [32]byte) (ROBlob, error) {
|
||||
if b == nil {
|
||||
return ROBlob{}, errNilBlock
|
||||
if err := roblobNilCheck(b); err != nil {
|
||||
return ROBlob{}, err
|
||||
}
|
||||
return ROBlob{BlobSidecar: b, root: root}, nil
|
||||
}
|
||||
|
||||
// NewROBlob creates a new ROBlob by computing the HashTreeRoot of the header.
|
||||
func NewROBlob(b *ethpb.BlobSidecar) (ROBlob, error) {
|
||||
if b == nil {
|
||||
return ROBlob{}, errNilBlock
|
||||
}
|
||||
if b.SignedBlockHeader == nil || b.SignedBlockHeader.Header == nil {
|
||||
return ROBlob{}, errNilBlockHeader
|
||||
if err := roblobNilCheck(b); err != nil {
|
||||
return ROBlob{}, err
|
||||
}
|
||||
root, err := b.SignedBlockHeader.Header.HashTreeRoot()
|
||||
if err != nil {
|
||||
|
||||
@@ -5,50 +5,94 @@ import (
|
||||
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
)
|
||||
|
||||
func TestNewROBlobWithRoot(t *testing.T) {
|
||||
sidecar := ðpb.BlobSidecar{}
|
||||
root := [32]byte{}
|
||||
|
||||
blob, err := NewROBlobWithRoot(sidecar, root)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, root, blob.BlockRoot())
|
||||
|
||||
blob, err = NewROBlobWithRoot(nil, root)
|
||||
assert.Equal(t, errNilBlock, err)
|
||||
}
|
||||
|
||||
// TestNewROBlob tests the NewROBlob function.
|
||||
func TestNewROBlob(t *testing.T) {
|
||||
h := ðpb.SignedBeaconBlockHeader{
|
||||
Header: ðpb.BeaconBlockHeader{
|
||||
ParentRoot: make([]byte, fieldparams.RootLength),
|
||||
StateRoot: make([]byte, fieldparams.RootLength),
|
||||
BodyRoot: make([]byte, fieldparams.RootLength),
|
||||
func TestROBlobNilChecks(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
bfunc func(t *testing.T) *ethpb.BlobSidecar
|
||||
err error
|
||||
root []byte
|
||||
}{
|
||||
{
|
||||
name: "nil signed blob",
|
||||
bfunc: func(t *testing.T) *ethpb.BlobSidecar {
|
||||
return nil
|
||||
},
|
||||
err: errNilBlob,
|
||||
root: bytesutil.PadTo([]byte("sup"), 32),
|
||||
},
|
||||
{
|
||||
name: "nil signed block header",
|
||||
bfunc: func(t *testing.T) *ethpb.BlobSidecar {
|
||||
return ðpb.BlobSidecar{
|
||||
SignedBlockHeader: nil,
|
||||
}
|
||||
},
|
||||
err: errNilBlockHeader,
|
||||
root: bytesutil.PadTo([]byte("sup"), 32),
|
||||
},
|
||||
{
|
||||
name: "nil inner header",
|
||||
bfunc: func(t *testing.T) *ethpb.BlobSidecar {
|
||||
return ðpb.BlobSidecar{
|
||||
SignedBlockHeader: ðpb.SignedBeaconBlockHeader{
|
||||
Header: nil,
|
||||
},
|
||||
}
|
||||
},
|
||||
err: errNilBlockHeader,
|
||||
root: bytesutil.PadTo([]byte("sup"), 32),
|
||||
},
|
||||
{
|
||||
name: "nil signature",
|
||||
bfunc: func(t *testing.T) *ethpb.BlobSidecar {
|
||||
return ðpb.BlobSidecar{
|
||||
SignedBlockHeader: ðpb.SignedBeaconBlockHeader{
|
||||
Header: ðpb.BeaconBlockHeader{
|
||||
ParentRoot: make([]byte, fieldparams.RootLength),
|
||||
StateRoot: make([]byte, fieldparams.RootLength),
|
||||
BodyRoot: make([]byte, fieldparams.RootLength),
|
||||
},
|
||||
Signature: nil,
|
||||
},
|
||||
}
|
||||
},
|
||||
err: errMissingBlockSignature,
|
||||
root: bytesutil.PadTo([]byte("sup"), 32),
|
||||
},
|
||||
Signature: make([]byte, fieldparams.BLSSignatureLength),
|
||||
}
|
||||
sidecar := ðpb.BlobSidecar{
|
||||
SignedBlockHeader: h,
|
||||
for _, c := range cases {
|
||||
t.Run(c.name+" NewROBlob", func(t *testing.T) {
|
||||
b := c.bfunc(t)
|
||||
bl, err := NewROBlob(b)
|
||||
if c.err != nil {
|
||||
require.ErrorIs(t, err, c.err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
hr, err := b.SignedBlockHeader.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, hr, bl.BlockRoot())
|
||||
}
|
||||
})
|
||||
if len(c.root) == 0 {
|
||||
continue
|
||||
}
|
||||
t.Run(c.name+" NewROBlobWithRoot", func(t *testing.T) {
|
||||
b := c.bfunc(t)
|
||||
// We want the same validation when specifying a root.
|
||||
bl, err := NewROBlobWithRoot(b, bytesutil.ToBytes32(c.root))
|
||||
if c.err != nil {
|
||||
require.ErrorIs(t, err, c.err)
|
||||
} else {
|
||||
assert.Equal(t, bytesutil.ToBytes32(c.root), bl.BlockRoot())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
blob, err := NewROBlob(sidecar)
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, blob)
|
||||
|
||||
_, err = NewROBlob(nil)
|
||||
assert.Equal(t, errNilBlock, err)
|
||||
|
||||
sidecar.SignedBlockHeader = nil
|
||||
_, err = NewROBlob(sidecar)
|
||||
assert.Equal(t, errNilBlockHeader, err)
|
||||
|
||||
sidecar.SignedBlockHeader = ðpb.SignedBeaconBlockHeader{}
|
||||
_, err = NewROBlob(sidecar)
|
||||
assert.Equal(t, errNilBlockHeader, err)
|
||||
}
|
||||
|
||||
func TestBlockRoot(t *testing.T) {
|
||||
|
||||
@@ -4,9 +4,11 @@ import (
|
||||
"sort"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
|
||||
eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
)
|
||||
|
||||
@@ -88,3 +90,103 @@ func testROBlock(t *testing.T, slot primitives.Slot, root [32]byte) ROBlock {
|
||||
root: root,
|
||||
}
|
||||
}
|
||||
|
||||
func TestROBlockNilChecks(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
bfunc func(t *testing.T) interfaces.SignedBeaconBlock
|
||||
err error
|
||||
root []byte
|
||||
}{
|
||||
{
|
||||
name: "happy path",
|
||||
bfunc: func(t *testing.T) interfaces.SignedBeaconBlock {
|
||||
b, err := NewSignedBeaconBlock(hydrateSignedBeaconBlock())
|
||||
require.NoError(t, err)
|
||||
return b
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "happy path - with root",
|
||||
bfunc: func(t *testing.T) interfaces.SignedBeaconBlock {
|
||||
b, err := NewSignedBeaconBlock(hydrateSignedBeaconBlock())
|
||||
require.NoError(t, err)
|
||||
return b
|
||||
},
|
||||
root: bytesutil.PadTo([]byte("sup"), 32),
|
||||
},
|
||||
{
|
||||
name: "nil signed block",
|
||||
bfunc: func(t *testing.T) interfaces.SignedBeaconBlock {
|
||||
return nil
|
||||
},
|
||||
err: ErrNilSignedBeaconBlock,
|
||||
},
|
||||
{
|
||||
name: "nil signed block - with root",
|
||||
bfunc: func(t *testing.T) interfaces.SignedBeaconBlock {
|
||||
return nil
|
||||
},
|
||||
err: ErrNilSignedBeaconBlock,
|
||||
root: bytesutil.PadTo([]byte("sup"), 32),
|
||||
},
|
||||
{
|
||||
name: "nil inner block",
|
||||
bfunc: func(t *testing.T) interfaces.SignedBeaconBlock {
|
||||
return &SignedBeaconBlock{
|
||||
version: version.Deneb,
|
||||
block: nil,
|
||||
signature: bytesutil.ToBytes96(nil),
|
||||
}
|
||||
},
|
||||
err: ErrNilSignedBeaconBlock,
|
||||
},
|
||||
{
|
||||
name: "nil inner block",
|
||||
bfunc: func(t *testing.T) interfaces.SignedBeaconBlock {
|
||||
return &SignedBeaconBlock{
|
||||
version: version.Deneb,
|
||||
block: nil,
|
||||
signature: bytesutil.ToBytes96(nil),
|
||||
}
|
||||
},
|
||||
err: ErrNilSignedBeaconBlock,
|
||||
},
|
||||
{
|
||||
name: "nil block body",
|
||||
bfunc: func(t *testing.T) interfaces.SignedBeaconBlock {
|
||||
bb := &BeaconBlock{
|
||||
version: version.Deneb,
|
||||
slot: 0,
|
||||
proposerIndex: 0,
|
||||
parentRoot: bytesutil.ToBytes32(nil),
|
||||
stateRoot: bytesutil.ToBytes32(nil),
|
||||
body: nil,
|
||||
}
|
||||
return &SignedBeaconBlock{
|
||||
version: version.Deneb,
|
||||
block: bb,
|
||||
signature: bytesutil.ToBytes96(nil),
|
||||
}
|
||||
},
|
||||
err: ErrNilSignedBeaconBlock,
|
||||
},
|
||||
}
|
||||
for _, c := range cases {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
b := c.bfunc(t)
|
||||
var err error
|
||||
if len(c.root) == 0 {
|
||||
_, err = NewROBlock(b)
|
||||
} else {
|
||||
_, err = NewROBlockWithRoot(b, bytesutil.ToBytes32(c.root))
|
||||
}
|
||||
if c.err != nil {
|
||||
require.ErrorIs(t, err, c.err)
|
||||
return
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,10 +27,13 @@ const (
|
||||
var (
|
||||
// ErrUnsupportedVersion for beacon block methods.
|
||||
ErrUnsupportedVersion = errors.New("unsupported beacon block version")
|
||||
errNilBlob = errors.New("received nil blob sidecar")
|
||||
errNilBlock = errors.New("received nil beacon block")
|
||||
errNilBlockBody = errors.New("received nil beacon block body")
|
||||
errIncorrectBlockVersion = errors.New(incorrectBlockVersion)
|
||||
errIncorrectBodyVersion = errors.New(incorrectBodyVersion)
|
||||
errNilBlockHeader = errors.New("received nil beacon block header")
|
||||
errMissingBlockSignature = errors.New("received nil beacon block signature")
|
||||
)
|
||||
|
||||
// BeaconBlockBody is the main beacon block body structure. It can represent any block type.
|
||||
|
||||
1354
proto/engine/v1/epbs.pb.go
generated
Executable file
1354
proto/engine/v1/epbs.pb.go
generated
Executable file
File diff suppressed because it is too large
Load Diff
938
proto/eth/v1/beacon_state.pb.go
generated
Executable file
938
proto/eth/v1/beacon_state.pb.go
generated
Executable file
@@ -0,0 +1,938 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.31.0
|
||||
// protoc v4.25.1
|
||||
// source: proto/eth/v1/beacon_state.proto
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
|
||||
github_com_prysmaticlabs_go_bitfield "github.com/prysmaticlabs/go-bitfield"
|
||||
github_com_prysmaticlabs_prysm_v5_consensus_types_primitives "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
_ "github.com/prysmaticlabs/prysm/v5/proto/eth/ext"
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
_ "google.golang.org/protobuf/types/descriptorpb"
|
||||
)
|
||||
|
||||
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 BeaconState struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
GenesisTime uint64 `protobuf:"varint,1001,opt,name=genesis_time,json=genesisTime,proto3" json:"genesis_time,omitempty"`
|
||||
GenesisValidatorsRoot []byte `protobuf:"bytes,1002,opt,name=genesis_validators_root,json=genesisValidatorsRoot,proto3" json:"genesis_validators_root,omitempty" ssz-size:"32"`
|
||||
Slot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,1003,opt,name=slot,proto3" json:"slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"`
|
||||
Fork *Fork `protobuf:"bytes,1004,opt,name=fork,proto3" json:"fork,omitempty"`
|
||||
LatestBlockHeader *BeaconBlockHeader `protobuf:"bytes,2001,opt,name=latest_block_header,json=latestBlockHeader,proto3" json:"latest_block_header,omitempty"`
|
||||
BlockRoots [][]byte `protobuf:"bytes,2002,rep,name=block_roots,json=blockRoots,proto3" json:"block_roots,omitempty" ssz-size:"8192,32"`
|
||||
StateRoots [][]byte `protobuf:"bytes,2003,rep,name=state_roots,json=stateRoots,proto3" json:"state_roots,omitempty" ssz-size:"8192,32"`
|
||||
HistoricalRoots [][]byte `protobuf:"bytes,2004,rep,name=historical_roots,json=historicalRoots,proto3" json:"historical_roots,omitempty" ssz-max:"16777216" ssz-size:"?,32"`
|
||||
Eth1Data *Eth1Data `protobuf:"bytes,3001,opt,name=eth1_data,json=eth1Data,proto3" json:"eth1_data,omitempty"`
|
||||
Eth1DataVotes []*Eth1Data `protobuf:"bytes,3002,rep,name=eth1_data_votes,json=eth1DataVotes,proto3" json:"eth1_data_votes,omitempty" ssz-max:"2048"`
|
||||
Eth1DepositIndex uint64 `protobuf:"varint,3003,opt,name=eth1_deposit_index,json=eth1DepositIndex,proto3" json:"eth1_deposit_index,omitempty"`
|
||||
Validators []*Validator `protobuf:"bytes,4001,rep,name=validators,proto3" json:"validators,omitempty" ssz-max:"1099511627776"`
|
||||
Balances []uint64 `protobuf:"varint,4002,rep,packed,name=balances,proto3" json:"balances,omitempty" ssz-max:"1099511627776"`
|
||||
RandaoMixes [][]byte `protobuf:"bytes,5001,rep,name=randao_mixes,json=randaoMixes,proto3" json:"randao_mixes,omitempty" ssz-size:"65536,32"`
|
||||
Slashings []uint64 `protobuf:"varint,6001,rep,packed,name=slashings,proto3" json:"slashings,omitempty" ssz-size:"8192"`
|
||||
PreviousEpochAttestations []*PendingAttestation `protobuf:"bytes,7001,rep,name=previous_epoch_attestations,json=previousEpochAttestations,proto3" json:"previous_epoch_attestations,omitempty" ssz-max:"4096"`
|
||||
CurrentEpochAttestations []*PendingAttestation `protobuf:"bytes,7002,rep,name=current_epoch_attestations,json=currentEpochAttestations,proto3" json:"current_epoch_attestations,omitempty" ssz-max:"4096"`
|
||||
JustificationBits github_com_prysmaticlabs_go_bitfield.Bitvector4 `protobuf:"bytes,8001,opt,name=justification_bits,json=justificationBits,proto3" json:"justification_bits,omitempty" cast-type:"github.com/prysmaticlabs/go-bitfield.Bitvector4" ssz-size:"1"`
|
||||
PreviousJustifiedCheckpoint *Checkpoint `protobuf:"bytes,8002,opt,name=previous_justified_checkpoint,json=previousJustifiedCheckpoint,proto3" json:"previous_justified_checkpoint,omitempty"`
|
||||
CurrentJustifiedCheckpoint *Checkpoint `protobuf:"bytes,8003,opt,name=current_justified_checkpoint,json=currentJustifiedCheckpoint,proto3" json:"current_justified_checkpoint,omitempty"`
|
||||
FinalizedCheckpoint *Checkpoint `protobuf:"bytes,8004,opt,name=finalized_checkpoint,json=finalizedCheckpoint,proto3" json:"finalized_checkpoint,omitempty"`
|
||||
}
|
||||
|
||||
func (x *BeaconState) Reset() {
|
||||
*x = BeaconState{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_proto_eth_v1_beacon_state_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *BeaconState) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*BeaconState) ProtoMessage() {}
|
||||
|
||||
func (x *BeaconState) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_eth_v1_beacon_state_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 BeaconState.ProtoReflect.Descriptor instead.
|
||||
func (*BeaconState) Descriptor() ([]byte, []int) {
|
||||
return file_proto_eth_v1_beacon_state_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *BeaconState) GetGenesisTime() uint64 {
|
||||
if x != nil {
|
||||
return x.GenesisTime
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *BeaconState) GetGenesisValidatorsRoot() []byte {
|
||||
if x != nil {
|
||||
return x.GenesisValidatorsRoot
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *BeaconState) GetSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot {
|
||||
if x != nil {
|
||||
return x.Slot
|
||||
}
|
||||
return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0)
|
||||
}
|
||||
|
||||
func (x *BeaconState) GetFork() *Fork {
|
||||
if x != nil {
|
||||
return x.Fork
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *BeaconState) GetLatestBlockHeader() *BeaconBlockHeader {
|
||||
if x != nil {
|
||||
return x.LatestBlockHeader
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *BeaconState) GetBlockRoots() [][]byte {
|
||||
if x != nil {
|
||||
return x.BlockRoots
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *BeaconState) GetStateRoots() [][]byte {
|
||||
if x != nil {
|
||||
return x.StateRoots
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *BeaconState) GetHistoricalRoots() [][]byte {
|
||||
if x != nil {
|
||||
return x.HistoricalRoots
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *BeaconState) GetEth1Data() *Eth1Data {
|
||||
if x != nil {
|
||||
return x.Eth1Data
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *BeaconState) GetEth1DataVotes() []*Eth1Data {
|
||||
if x != nil {
|
||||
return x.Eth1DataVotes
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *BeaconState) GetEth1DepositIndex() uint64 {
|
||||
if x != nil {
|
||||
return x.Eth1DepositIndex
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *BeaconState) GetValidators() []*Validator {
|
||||
if x != nil {
|
||||
return x.Validators
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *BeaconState) GetBalances() []uint64 {
|
||||
if x != nil {
|
||||
return x.Balances
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *BeaconState) GetRandaoMixes() [][]byte {
|
||||
if x != nil {
|
||||
return x.RandaoMixes
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *BeaconState) GetSlashings() []uint64 {
|
||||
if x != nil {
|
||||
return x.Slashings
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *BeaconState) GetPreviousEpochAttestations() []*PendingAttestation {
|
||||
if x != nil {
|
||||
return x.PreviousEpochAttestations
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *BeaconState) GetCurrentEpochAttestations() []*PendingAttestation {
|
||||
if x != nil {
|
||||
return x.CurrentEpochAttestations
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *BeaconState) GetJustificationBits() github_com_prysmaticlabs_go_bitfield.Bitvector4 {
|
||||
if x != nil {
|
||||
return x.JustificationBits
|
||||
}
|
||||
return github_com_prysmaticlabs_go_bitfield.Bitvector4(nil)
|
||||
}
|
||||
|
||||
func (x *BeaconState) GetPreviousJustifiedCheckpoint() *Checkpoint {
|
||||
if x != nil {
|
||||
return x.PreviousJustifiedCheckpoint
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *BeaconState) GetCurrentJustifiedCheckpoint() *Checkpoint {
|
||||
if x != nil {
|
||||
return x.CurrentJustifiedCheckpoint
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *BeaconState) GetFinalizedCheckpoint() *Checkpoint {
|
||||
if x != nil {
|
||||
return x.FinalizedCheckpoint
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type PendingAttestation struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
AggregationBits github_com_prysmaticlabs_go_bitfield.Bitlist `protobuf:"bytes,1,opt,name=aggregation_bits,json=aggregationBits,proto3" json:"aggregation_bits,omitempty" cast-type:"github.com/prysmaticlabs/go-bitfield.Bitlist" ssz-max:"2048"`
|
||||
Data *AttestationData `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"`
|
||||
InclusionDelay github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,3,opt,name=inclusion_delay,json=inclusionDelay,proto3" json:"inclusion_delay,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"`
|
||||
ProposerIndex github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex `protobuf:"varint,4,opt,name=proposer_index,json=proposerIndex,proto3" json:"proposer_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"`
|
||||
}
|
||||
|
||||
func (x *PendingAttestation) Reset() {
|
||||
*x = PendingAttestation{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_proto_eth_v1_beacon_state_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *PendingAttestation) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*PendingAttestation) ProtoMessage() {}
|
||||
|
||||
func (x *PendingAttestation) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_eth_v1_beacon_state_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 PendingAttestation.ProtoReflect.Descriptor instead.
|
||||
func (*PendingAttestation) Descriptor() ([]byte, []int) {
|
||||
return file_proto_eth_v1_beacon_state_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *PendingAttestation) GetAggregationBits() github_com_prysmaticlabs_go_bitfield.Bitlist {
|
||||
if x != nil {
|
||||
return x.AggregationBits
|
||||
}
|
||||
return github_com_prysmaticlabs_go_bitfield.Bitlist(nil)
|
||||
}
|
||||
|
||||
func (x *PendingAttestation) GetData() *AttestationData {
|
||||
if x != nil {
|
||||
return x.Data
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *PendingAttestation) GetInclusionDelay() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot {
|
||||
if x != nil {
|
||||
return x.InclusionDelay
|
||||
}
|
||||
return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0)
|
||||
}
|
||||
|
||||
func (x *PendingAttestation) GetProposerIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex {
|
||||
if x != nil {
|
||||
return x.ProposerIndex
|
||||
}
|
||||
return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(0)
|
||||
}
|
||||
|
||||
type Committee struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Index github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.CommitteeIndex `protobuf:"varint,1,opt,name=index,proto3" json:"index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.CommitteeIndex"`
|
||||
Slot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,2,opt,name=slot,proto3" json:"slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"`
|
||||
Validators []github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex `protobuf:"varint,3,rep,packed,name=validators,proto3" json:"validators,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"`
|
||||
}
|
||||
|
||||
func (x *Committee) Reset() {
|
||||
*x = Committee{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_proto_eth_v1_beacon_state_proto_msgTypes[2]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *Committee) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*Committee) ProtoMessage() {}
|
||||
|
||||
func (x *Committee) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_eth_v1_beacon_state_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 Committee.ProtoReflect.Descriptor instead.
|
||||
func (*Committee) Descriptor() ([]byte, []int) {
|
||||
return file_proto_eth_v1_beacon_state_proto_rawDescGZIP(), []int{2}
|
||||
}
|
||||
|
||||
func (x *Committee) GetIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.CommitteeIndex {
|
||||
if x != nil {
|
||||
return x.Index
|
||||
}
|
||||
return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.CommitteeIndex(0)
|
||||
}
|
||||
|
||||
func (x *Committee) GetSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot {
|
||||
if x != nil {
|
||||
return x.Slot
|
||||
}
|
||||
return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0)
|
||||
}
|
||||
|
||||
func (x *Committee) GetValidators() []github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex {
|
||||
if x != nil {
|
||||
return x.Validators
|
||||
}
|
||||
return []github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(nil)
|
||||
}
|
||||
|
||||
type Fork struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
PreviousVersion []byte `protobuf:"bytes,1,opt,name=previous_version,json=previousVersion,proto3" json:"previous_version,omitempty" ssz-size:"4"`
|
||||
CurrentVersion []byte `protobuf:"bytes,2,opt,name=current_version,json=currentVersion,proto3" json:"current_version,omitempty" ssz-size:"4"`
|
||||
Epoch github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Epoch `protobuf:"varint,3,opt,name=epoch,proto3" json:"epoch,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"`
|
||||
}
|
||||
|
||||
func (x *Fork) Reset() {
|
||||
*x = Fork{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_proto_eth_v1_beacon_state_proto_msgTypes[3]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *Fork) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*Fork) ProtoMessage() {}
|
||||
|
||||
func (x *Fork) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_eth_v1_beacon_state_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 Fork.ProtoReflect.Descriptor instead.
|
||||
func (*Fork) Descriptor() ([]byte, []int) {
|
||||
return file_proto_eth_v1_beacon_state_proto_rawDescGZIP(), []int{3}
|
||||
}
|
||||
|
||||
func (x *Fork) GetPreviousVersion() []byte {
|
||||
if x != nil {
|
||||
return x.PreviousVersion
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Fork) GetCurrentVersion() []byte {
|
||||
if x != nil {
|
||||
return x.CurrentVersion
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Fork) GetEpoch() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Epoch {
|
||||
if x != nil {
|
||||
return x.Epoch
|
||||
}
|
||||
return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Epoch(0)
|
||||
}
|
||||
|
||||
type ForkChoiceHeadsResponse struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Data []*ForkChoiceHead `protobuf:"bytes,1,rep,name=data,proto3" json:"data,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ForkChoiceHeadsResponse) Reset() {
|
||||
*x = ForkChoiceHeadsResponse{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_proto_eth_v1_beacon_state_proto_msgTypes[4]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *ForkChoiceHeadsResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ForkChoiceHeadsResponse) ProtoMessage() {}
|
||||
|
||||
func (x *ForkChoiceHeadsResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_eth_v1_beacon_state_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 ForkChoiceHeadsResponse.ProtoReflect.Descriptor instead.
|
||||
func (*ForkChoiceHeadsResponse) Descriptor() ([]byte, []int) {
|
||||
return file_proto_eth_v1_beacon_state_proto_rawDescGZIP(), []int{4}
|
||||
}
|
||||
|
||||
func (x *ForkChoiceHeadsResponse) GetData() []*ForkChoiceHead {
|
||||
if x != nil {
|
||||
return x.Data
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ForkChoiceHead struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Root []byte `protobuf:"bytes,1,opt,name=root,proto3" json:"root,omitempty" ssz-size:"32"`
|
||||
Slot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,2,opt,name=slot,proto3" json:"slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"`
|
||||
}
|
||||
|
||||
func (x *ForkChoiceHead) Reset() {
|
||||
*x = ForkChoiceHead{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_proto_eth_v1_beacon_state_proto_msgTypes[5]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *ForkChoiceHead) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ForkChoiceHead) ProtoMessage() {}
|
||||
|
||||
func (x *ForkChoiceHead) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_eth_v1_beacon_state_proto_msgTypes[5]
|
||||
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 ForkChoiceHead.ProtoReflect.Descriptor instead.
|
||||
func (*ForkChoiceHead) Descriptor() ([]byte, []int) {
|
||||
return file_proto_eth_v1_beacon_state_proto_rawDescGZIP(), []int{5}
|
||||
}
|
||||
|
||||
func (x *ForkChoiceHead) GetRoot() []byte {
|
||||
if x != nil {
|
||||
return x.Root
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *ForkChoiceHead) GetSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot {
|
||||
if x != nil {
|
||||
return x.Slot
|
||||
}
|
||||
return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0)
|
||||
}
|
||||
|
||||
type BeaconStateResponse struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Data *BeaconState `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
|
||||
}
|
||||
|
||||
func (x *BeaconStateResponse) Reset() {
|
||||
*x = BeaconStateResponse{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_proto_eth_v1_beacon_state_proto_msgTypes[6]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *BeaconStateResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*BeaconStateResponse) ProtoMessage() {}
|
||||
|
||||
func (x *BeaconStateResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_eth_v1_beacon_state_proto_msgTypes[6]
|
||||
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 BeaconStateResponse.ProtoReflect.Descriptor instead.
|
||||
func (*BeaconStateResponse) Descriptor() ([]byte, []int) {
|
||||
return file_proto_eth_v1_beacon_state_proto_rawDescGZIP(), []int{6}
|
||||
}
|
||||
|
||||
func (x *BeaconStateResponse) GetData() *BeaconState {
|
||||
if x != nil {
|
||||
return x.Data
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var File_proto_eth_v1_beacon_state_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_proto_eth_v1_beacon_state_proto_rawDesc = []byte{
|
||||
0x0a, 0x1f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62,
|
||||
0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x12, 0x0f, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e,
|
||||
0x76, 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, 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, 0x1a, 0x1e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f,
|
||||
0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x1a, 0x1f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f,
|
||||
0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x70, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x1a, 0x1c, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31,
|
||||
0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||
0x22, 0xdb, 0x0b, 0x0a, 0x0b, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65,
|
||||
0x12, 0x22, 0x0a, 0x0c, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x5f, 0x74, 0x69, 0x6d, 0x65,
|
||||
0x18, 0xe9, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73,
|
||||
0x54, 0x69, 0x6d, 0x65, 0x12, 0x3f, 0x0a, 0x17, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x5f,
|
||||
0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18,
|
||||
0xea, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x15,
|
||||
0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72,
|
||||
0x73, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x5a, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0xeb, 0x07,
|
||||
0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 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, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73,
|
||||
0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d,
|
||||
0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, 0x6f,
|
||||
0x74, 0x12, 0x2a, 0x0a, 0x04, 0x66, 0x6f, 0x72, 0x6b, 0x18, 0xec, 0x07, 0x20, 0x01, 0x28, 0x0b,
|
||||
0x32, 0x15, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e,
|
||||
0x76, 0x31, 0x2e, 0x46, 0x6f, 0x72, 0x6b, 0x52, 0x04, 0x66, 0x6f, 0x72, 0x6b, 0x12, 0x53, 0x0a,
|
||||
0x13, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x65,
|
||||
0x61, 0x64, 0x65, 0x72, 0x18, 0xd1, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x74,
|
||||
0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x65,
|
||||
0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52,
|
||||
0x11, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64,
|
||||
0x65, 0x72, 0x12, 0x2d, 0x0a, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x72, 0x6f, 0x6f, 0x74,
|
||||
0x73, 0x18, 0xd2, 0x0f, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x0b, 0x8a, 0xb5, 0x18, 0x07, 0x38, 0x31,
|
||||
0x39, 0x32, 0x2c, 0x33, 0x32, 0x52, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74,
|
||||
0x73, 0x12, 0x2d, 0x0a, 0x0b, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x73,
|
||||
0x18, 0xd3, 0x0f, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x0b, 0x8a, 0xb5, 0x18, 0x07, 0x38, 0x31, 0x39,
|
||||
0x32, 0x2c, 0x33, 0x32, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x73,
|
||||
0x12, 0x40, 0x0a, 0x10, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x72,
|
||||
0x6f, 0x6f, 0x74, 0x73, 0x18, 0xd4, 0x0f, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x14, 0x8a, 0xb5, 0x18,
|
||||
0x04, 0x3f, 0x2c, 0x33, 0x32, 0x92, 0xb5, 0x18, 0x08, 0x31, 0x36, 0x37, 0x37, 0x37, 0x32, 0x31,
|
||||
0x36, 0x52, 0x0f, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x52, 0x6f, 0x6f,
|
||||
0x74, 0x73, 0x12, 0x37, 0x0a, 0x09, 0x65, 0x74, 0x68, 0x31, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18,
|
||||
0xb9, 0x17, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75,
|
||||
0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74,
|
||||
0x61, 0x52, 0x08, 0x65, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x12, 0x4c, 0x0a, 0x0f, 0x65,
|
||||
0x74, 0x68, 0x31, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x76, 0x6f, 0x74, 0x65, 0x73, 0x18, 0xba,
|
||||
0x17, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d,
|
||||
0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61,
|
||||
0x42, 0x08, 0x92, 0xb5, 0x18, 0x04, 0x32, 0x30, 0x34, 0x38, 0x52, 0x0d, 0x65, 0x74, 0x68, 0x31,
|
||||
0x44, 0x61, 0x74, 0x61, 0x56, 0x6f, 0x74, 0x65, 0x73, 0x12, 0x2d, 0x0a, 0x12, 0x65, 0x74, 0x68,
|
||||
0x31, 0x5f, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18,
|
||||
0xbb, 0x17, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x65, 0x74, 0x68, 0x31, 0x44, 0x65, 0x70, 0x6f,
|
||||
0x73, 0x69, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x4e, 0x0a, 0x0a, 0x76, 0x61, 0x6c, 0x69,
|
||||
0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x18, 0xa1, 0x1f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e,
|
||||
0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e,
|
||||
0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x42, 0x11, 0x92, 0xb5, 0x18, 0x0d, 0x31,
|
||||
0x30, 0x39, 0x39, 0x35, 0x31, 0x31, 0x36, 0x32, 0x37, 0x37, 0x37, 0x36, 0x52, 0x0a, 0x76, 0x61,
|
||||
0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x2e, 0x0a, 0x08, 0x62, 0x61, 0x6c, 0x61,
|
||||
0x6e, 0x63, 0x65, 0x73, 0x18, 0xa2, 0x1f, 0x20, 0x03, 0x28, 0x04, 0x42, 0x11, 0x92, 0xb5, 0x18,
|
||||
0x0d, 0x31, 0x30, 0x39, 0x39, 0x35, 0x31, 0x31, 0x36, 0x32, 0x37, 0x37, 0x37, 0x36, 0x52, 0x08,
|
||||
0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x30, 0x0a, 0x0c, 0x72, 0x61, 0x6e, 0x64,
|
||||
0x61, 0x6f, 0x5f, 0x6d, 0x69, 0x78, 0x65, 0x73, 0x18, 0x89, 0x27, 0x20, 0x03, 0x28, 0x0c, 0x42,
|
||||
0x0c, 0x8a, 0xb5, 0x18, 0x08, 0x36, 0x35, 0x35, 0x33, 0x36, 0x2c, 0x33, 0x32, 0x52, 0x0b, 0x72,
|
||||
0x61, 0x6e, 0x64, 0x61, 0x6f, 0x4d, 0x69, 0x78, 0x65, 0x73, 0x12, 0x27, 0x0a, 0x09, 0x73, 0x6c,
|
||||
0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x18, 0xf1, 0x2e, 0x20, 0x03, 0x28, 0x04, 0x42, 0x08,
|
||||
0x8a, 0xb5, 0x18, 0x04, 0x38, 0x31, 0x39, 0x32, 0x52, 0x09, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69,
|
||||
0x6e, 0x67, 0x73, 0x12, 0x6e, 0x0a, 0x1b, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f,
|
||||
0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x73, 0x18, 0xd9, 0x36, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x65, 0x74, 0x68, 0x65,
|
||||
0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x65, 0x6e, 0x64,
|
||||
0x69, 0x6e, 0x67, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x08,
|
||||
0x92, 0xb5, 0x18, 0x04, 0x34, 0x30, 0x39, 0x36, 0x52, 0x19, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f,
|
||||
0x75, 0x73, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x73, 0x12, 0x6c, 0x0a, 0x1a, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x65,
|
||||
0x70, 0x6f, 0x63, 0x68, 0x5f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x73, 0x18, 0xda, 0x36, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72,
|
||||
0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x65, 0x6e, 0x64, 0x69,
|
||||
0x6e, 0x67, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x08, 0x92,
|
||||
0xb5, 0x18, 0x04, 0x34, 0x30, 0x39, 0x36, 0x52, 0x18, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74,
|
||||
0x45, 0x70, 0x6f, 0x63, 0x68, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x73, 0x12, 0x68, 0x0a, 0x12, 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x18, 0xc1, 0x3e, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x38,
|
||||
0x82, 0xb5, 0x18, 0x2f, 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, 0x67, 0x6f, 0x2d,
|
||||
0x62, 0x69, 0x74, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x2e, 0x42, 0x69, 0x74, 0x76, 0x65, 0x63, 0x74,
|
||||
0x6f, 0x72, 0x34, 0x8a, 0xb5, 0x18, 0x01, 0x31, 0x52, 0x11, 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66,
|
||||
0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x69, 0x74, 0x73, 0x12, 0x60, 0x0a, 0x1d, 0x70,
|
||||
0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x69, 0x65,
|
||||
0x64, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0xc2, 0x3e, 0x20,
|
||||
0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65,
|
||||
0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74,
|
||||
0x52, 0x1b, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x4a, 0x75, 0x73, 0x74, 0x69, 0x66,
|
||||
0x69, 0x65, 0x64, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x5e, 0x0a,
|
||||
0x1c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x69,
|
||||
0x65, 0x64, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0xc3, 0x3e,
|
||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e,
|
||||
0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e,
|
||||
0x74, 0x52, 0x1a, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x4a, 0x75, 0x73, 0x74, 0x69, 0x66,
|
||||
0x69, 0x65, 0x64, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x4f, 0x0a,
|
||||
0x14, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b,
|
||||
0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0xc4, 0x3e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x65,
|
||||
0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x43,
|
||||
0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x13, 0x66, 0x69, 0x6e, 0x61, 0x6c,
|
||||
0x69, 0x7a, 0x65, 0x64, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x22, 0x97,
|
||||
0x03, 0x0a, 0x12, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74,
|
||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x63, 0x0a, 0x10, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42,
|
||||
0x38, 0x82, 0xb5, 0x18, 0x2c, 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, 0x67, 0x6f,
|
||||
0x2d, 0x62, 0x69, 0x74, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x2e, 0x42, 0x69, 0x74, 0x6c, 0x69, 0x73,
|
||||
0x74, 0x92, 0xb5, 0x18, 0x04, 0x32, 0x30, 0x34, 0x38, 0x52, 0x0f, 0x61, 0x67, 0x67, 0x72, 0x65,
|
||||
0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x69, 0x74, 0x73, 0x12, 0x34, 0x0a, 0x04, 0x64, 0x61,
|
||||
0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72,
|
||||
0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73,
|
||||
0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61,
|
||||
0x12, 0x6e, 0x0a, 0x0f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x64, 0x65,
|
||||
0x6c, 0x61, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 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, 0x35,
|
||||
0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73,
|
||||
0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74,
|
||||
0x52, 0x0e, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x6c, 0x61, 0x79,
|
||||
0x12, 0x76, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64,
|
||||
0x65, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 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, 0x35, 0x2f,
|
||||
0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f,
|
||||
0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64,
|
||||
0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x70, 0x6f,
|
||||
0x73, 0x65, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x22, 0xbe, 0x02, 0x0a, 0x09, 0x43, 0x6f, 0x6d,
|
||||
0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x12, 0x65, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 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, 0x35, 0x2f, 0x63, 0x6f, 0x6e,
|
||||
0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69,
|
||||
0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65,
|
||||
0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x59, 0x0a,
|
||||
0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18,
|
||||
0x41, 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, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70,
|
||||
0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c,
|
||||
0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x12, 0x6f, 0x0a, 0x0a, 0x76, 0x61, 0x6c, 0x69,
|
||||
0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5,
|
||||
0x18, 0x4b, 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, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79,
|
||||
0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56,
|
||||
0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0a, 0x76,
|
||||
0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x22, 0xc6, 0x01, 0x0a, 0x04, 0x46, 0x6f,
|
||||
0x72, 0x6b, 0x12, 0x30, 0x0a, 0x10, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x76,
|
||||
0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x05, 0x8a, 0xb5,
|
||||
0x18, 0x01, 0x34, 0x52, 0x0f, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x56, 0x65, 0x72,
|
||||
0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2e, 0x0a, 0x0f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f,
|
||||
0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x05, 0x8a,
|
||||
0xb5, 0x18, 0x01, 0x34, 0x52, 0x0e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x56, 0x65, 0x72,
|
||||
0x73, 0x69, 0x6f, 0x6e, 0x12, 0x5c, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x03, 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, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65,
|
||||
0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69,
|
||||
0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x05, 0x65, 0x70, 0x6f,
|
||||
0x63, 0x68, 0x22, 0x4e, 0x0a, 0x17, 0x46, 0x6f, 0x72, 0x6b, 0x43, 0x68, 0x6f, 0x69, 0x63, 0x65,
|
||||
0x48, 0x65, 0x61, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a,
|
||||
0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x65, 0x74,
|
||||
0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x6f,
|
||||
0x72, 0x6b, 0x43, 0x68, 0x6f, 0x69, 0x63, 0x65, 0x48, 0x65, 0x61, 0x64, 0x52, 0x04, 0x64, 0x61,
|
||||
0x74, 0x61, 0x22, 0x87, 0x01, 0x0a, 0x0e, 0x46, 0x6f, 0x72, 0x6b, 0x43, 0x68, 0x6f, 0x69, 0x63,
|
||||
0x65, 0x48, 0x65, 0x61, 0x64, 0x12, 0x1a, 0x0a, 0x04, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x04, 0x72, 0x6f, 0x6f,
|
||||
0x74, 0x12, 0x59, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42,
|
||||
0x45, 0x82, 0xb5, 0x18, 0x41, 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, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73,
|
||||
0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65,
|
||||
0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x22, 0x47, 0x0a, 0x13,
|
||||
0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||
0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x0b, 0x32, 0x1c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68,
|
||||
0x2e, 0x76, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52,
|
||||
0x04, 0x64, 0x61, 0x74, 0x61, 0x42, 0x7d, 0x0a, 0x13, 0x6f, 0x72, 0x67, 0x2e, 0x65, 0x74, 0x68,
|
||||
0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x42, 0x10, 0x42, 0x65,
|
||||
0x61, 0x63, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01,
|
||||
0x5a, 0x2e, 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, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31,
|
||||
0xaa, 0x02, 0x0f, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x45, 0x74, 0x68, 0x2e,
|
||||
0x56, 0x31, 0xca, 0x02, 0x0f, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x5c, 0x45, 0x74,
|
||||
0x68, 0x5c, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
file_proto_eth_v1_beacon_state_proto_rawDescOnce sync.Once
|
||||
file_proto_eth_v1_beacon_state_proto_rawDescData = file_proto_eth_v1_beacon_state_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_proto_eth_v1_beacon_state_proto_rawDescGZIP() []byte {
|
||||
file_proto_eth_v1_beacon_state_proto_rawDescOnce.Do(func() {
|
||||
file_proto_eth_v1_beacon_state_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_eth_v1_beacon_state_proto_rawDescData)
|
||||
})
|
||||
return file_proto_eth_v1_beacon_state_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_proto_eth_v1_beacon_state_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
|
||||
var file_proto_eth_v1_beacon_state_proto_goTypes = []interface{}{
|
||||
(*BeaconState)(nil), // 0: ethereum.eth.v1.BeaconState
|
||||
(*PendingAttestation)(nil), // 1: ethereum.eth.v1.PendingAttestation
|
||||
(*Committee)(nil), // 2: ethereum.eth.v1.Committee
|
||||
(*Fork)(nil), // 3: ethereum.eth.v1.Fork
|
||||
(*ForkChoiceHeadsResponse)(nil), // 4: ethereum.eth.v1.ForkChoiceHeadsResponse
|
||||
(*ForkChoiceHead)(nil), // 5: ethereum.eth.v1.ForkChoiceHead
|
||||
(*BeaconStateResponse)(nil), // 6: ethereum.eth.v1.BeaconStateResponse
|
||||
(*BeaconBlockHeader)(nil), // 7: ethereum.eth.v1.BeaconBlockHeader
|
||||
(*Eth1Data)(nil), // 8: ethereum.eth.v1.Eth1Data
|
||||
(*Validator)(nil), // 9: ethereum.eth.v1.Validator
|
||||
(*Checkpoint)(nil), // 10: ethereum.eth.v1.Checkpoint
|
||||
(*AttestationData)(nil), // 11: ethereum.eth.v1.AttestationData
|
||||
}
|
||||
var file_proto_eth_v1_beacon_state_proto_depIdxs = []int32{
|
||||
3, // 0: ethereum.eth.v1.BeaconState.fork:type_name -> ethereum.eth.v1.Fork
|
||||
7, // 1: ethereum.eth.v1.BeaconState.latest_block_header:type_name -> ethereum.eth.v1.BeaconBlockHeader
|
||||
8, // 2: ethereum.eth.v1.BeaconState.eth1_data:type_name -> ethereum.eth.v1.Eth1Data
|
||||
8, // 3: ethereum.eth.v1.BeaconState.eth1_data_votes:type_name -> ethereum.eth.v1.Eth1Data
|
||||
9, // 4: ethereum.eth.v1.BeaconState.validators:type_name -> ethereum.eth.v1.Validator
|
||||
1, // 5: ethereum.eth.v1.BeaconState.previous_epoch_attestations:type_name -> ethereum.eth.v1.PendingAttestation
|
||||
1, // 6: ethereum.eth.v1.BeaconState.current_epoch_attestations:type_name -> ethereum.eth.v1.PendingAttestation
|
||||
10, // 7: ethereum.eth.v1.BeaconState.previous_justified_checkpoint:type_name -> ethereum.eth.v1.Checkpoint
|
||||
10, // 8: ethereum.eth.v1.BeaconState.current_justified_checkpoint:type_name -> ethereum.eth.v1.Checkpoint
|
||||
10, // 9: ethereum.eth.v1.BeaconState.finalized_checkpoint:type_name -> ethereum.eth.v1.Checkpoint
|
||||
11, // 10: ethereum.eth.v1.PendingAttestation.data:type_name -> ethereum.eth.v1.AttestationData
|
||||
5, // 11: ethereum.eth.v1.ForkChoiceHeadsResponse.data:type_name -> ethereum.eth.v1.ForkChoiceHead
|
||||
0, // 12: ethereum.eth.v1.BeaconStateResponse.data:type_name -> ethereum.eth.v1.BeaconState
|
||||
13, // [13:13] is the sub-list for method output_type
|
||||
13, // [13:13] is the sub-list for method input_type
|
||||
13, // [13:13] is the sub-list for extension type_name
|
||||
13, // [13:13] is the sub-list for extension extendee
|
||||
0, // [0:13] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_proto_eth_v1_beacon_state_proto_init() }
|
||||
func file_proto_eth_v1_beacon_state_proto_init() {
|
||||
if File_proto_eth_v1_beacon_state_proto != nil {
|
||||
return
|
||||
}
|
||||
file_proto_eth_v1_attestation_proto_init()
|
||||
file_proto_eth_v1_beacon_block_proto_init()
|
||||
file_proto_eth_v1_validator_proto_init()
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_proto_eth_v1_beacon_state_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*BeaconState); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_proto_eth_v1_beacon_state_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*PendingAttestation); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_proto_eth_v1_beacon_state_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*Committee); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_proto_eth_v1_beacon_state_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*Fork); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_proto_eth_v1_beacon_state_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ForkChoiceHeadsResponse); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_proto_eth_v1_beacon_state_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ForkChoiceHead); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_proto_eth_v1_beacon_state_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*BeaconStateResponse); 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_eth_v1_beacon_state_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 7,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
GoTypes: file_proto_eth_v1_beacon_state_proto_goTypes,
|
||||
DependencyIndexes: file_proto_eth_v1_beacon_state_proto_depIdxs,
|
||||
MessageInfos: file_proto_eth_v1_beacon_state_proto_msgTypes,
|
||||
}.Build()
|
||||
File_proto_eth_v1_beacon_state_proto = out.File
|
||||
file_proto_eth_v1_beacon_state_proto_rawDesc = nil
|
||||
file_proto_eth_v1_beacon_state_proto_goTypes = nil
|
||||
file_proto_eth_v1_beacon_state_proto_depIdxs = nil
|
||||
}
|
||||
4
proto/eth/v1/beacon_state.pb.gw.go
Executable file
4
proto/eth/v1/beacon_state.pb.gw.go
Executable file
@@ -0,0 +1,4 @@
|
||||
//go:build ignore
|
||||
// +build ignore
|
||||
|
||||
package ignore
|
||||
@@ -1,5 +1,5 @@
|
||||
// Code generated by fastssz. DO NOT EDIT.
|
||||
// Hash: 5890b3492dbdff08d332879e83ae45e7bd9f94da0716b1b0517f1766028a8d67
|
||||
// Hash: 6fed60156f1e57926b40b972ee25b48a82b18726a9c64fb0e974e4f638784049
|
||||
package v1
|
||||
|
||||
import (
|
||||
|
||||
2004
proto/eth/v2/beacon_state.pb.go
generated
Executable file
2004
proto/eth/v2/beacon_state.pb.go
generated
Executable file
File diff suppressed because it is too large
Load Diff
4
proto/eth/v2/beacon_state.pb.gw.go
Executable file
4
proto/eth/v2/beacon_state.pb.gw.go
Executable file
@@ -0,0 +1,4 @@
|
||||
//go:build ignore
|
||||
// +build ignore
|
||||
|
||||
package ignore
|
||||
@@ -1,5 +1,5 @@
|
||||
// Code generated by fastssz. DO NOT EDIT.
|
||||
// Hash: 2ed480e3c144fb091e0aa2757a79e78da573f90b18d0d8acd35fa9705f6c1b08
|
||||
// Hash: b6cc6e65f0679b3152fb6379d539ceeea78acabb1e413b6eacfac2d847537b1f
|
||||
package eth
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Code generated by fastssz. DO NOT EDIT.
|
||||
// Hash: eec7f00cb63ce6e76f0c38f25c23206f9700f1c9ba9f295908168d59f9af3f60
|
||||
// Hash: f4c321e03481bf096969c7c068f703bae574aca5c837766bf91f4767f6eaa14b
|
||||
package eth
|
||||
|
||||
import (
|
||||
|
||||
@@ -315,7 +315,7 @@ func (node *BeaconNode) Start(ctx context.Context) error {
|
||||
}
|
||||
|
||||
if config.UseFixedPeerIDs {
|
||||
peerId, err := helpers.FindFollowingTextInFile(stdOutFile, "Running node with id")
|
||||
peerId, err := helpers.FindFollowingTextInFile(stdOutFile, "Running node with peer id of ")
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not find peer id: %w", err)
|
||||
}
|
||||
|
||||
@@ -10,129 +10,117 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
)
|
||||
|
||||
var requests = map[string]endpoint{
|
||||
var getRequests = map[string]endpoint{
|
||||
"/beacon/genesis": newMetadata[structs.GetGenesisResponse](v1PathTemplate),
|
||||
"/beacon/states/{param1}/root": newMetadata[structs.GetStateRootResponse](v1PathTemplate,
|
||||
"/beacon/states/{param1}/root": newMetadata[structs.GetStateRootResponse](
|
||||
v1PathTemplate,
|
||||
withParams(func(_ primitives.Epoch) []string {
|
||||
return []string{"head"}
|
||||
})),
|
||||
"/beacon/states/{param1}/fork": newMetadata[structs.GetStateForkResponse](v1PathTemplate,
|
||||
"/beacon/states/{param1}/fork": newMetadata[structs.GetStateForkResponse](
|
||||
v1PathTemplate,
|
||||
withParams(func(_ primitives.Epoch) []string {
|
||||
return []string{"head"}
|
||||
})),
|
||||
"/beacon/states/{param1}/finality_checkpoints": newMetadata[structs.GetFinalityCheckpointsResponse](v1PathTemplate,
|
||||
"/beacon/states/{param1}/finality_checkpoints": newMetadata[structs.GetFinalityCheckpointsResponse](
|
||||
v1PathTemplate,
|
||||
withParams(func(_ primitives.Epoch) []string {
|
||||
return []string{"head"}
|
||||
})),
|
||||
// we want to test comma-separated query params
|
||||
"/beacon/states/{param1}/validators?id=0,1": newMetadata[structs.GetValidatorsResponse](v1PathTemplate,
|
||||
"/beacon/states/{param1}/validators?id=0,1": newMetadata[structs.GetValidatorsResponse](
|
||||
v1PathTemplate,
|
||||
withParams(func(_ primitives.Epoch) []string {
|
||||
return []string{"head"}
|
||||
})),
|
||||
"/beacon/states/{param1}/validators/{param2}": newMetadata[structs.GetValidatorResponse](v1PathTemplate,
|
||||
"/beacon/states/{param1}/validators/{param2}": newMetadata[structs.GetValidatorResponse](
|
||||
v1PathTemplate,
|
||||
withParams(func(_ primitives.Epoch) []string {
|
||||
return []string{"head", "0"}
|
||||
})),
|
||||
"/beacon/states/{param1}/validator_balances?id=0,1": newMetadata[structs.GetValidatorBalancesResponse](v1PathTemplate,
|
||||
"/beacon/states/{param1}/validator_balances?id=0,1": newMetadata[structs.GetValidatorBalancesResponse](
|
||||
v1PathTemplate,
|
||||
withParams(func(_ primitives.Epoch) []string {
|
||||
return []string{"head"}
|
||||
})),
|
||||
"/beacon/states/{param1}/committees?index=0": newMetadata[structs.GetCommitteesResponse](v1PathTemplate,
|
||||
"/beacon/states/{param1}/committees?index=0": newMetadata[structs.GetCommitteesResponse](
|
||||
v1PathTemplate,
|
||||
withParams(func(_ primitives.Epoch) []string {
|
||||
return []string{"head"}
|
||||
})),
|
||||
"/beacon/states/{param1}/sync_committees": newMetadata[structs.GetSyncCommitteeResponse](v1PathTemplate,
|
||||
"/beacon/states/{param1}/sync_committees": newMetadata[structs.GetSyncCommitteeResponse](
|
||||
v1PathTemplate,
|
||||
withStart(params.BeaconConfig().AltairForkEpoch),
|
||||
withParams(func(_ primitives.Epoch) []string {
|
||||
return []string{"head"}
|
||||
})),
|
||||
"/beacon/states/{param1}/randao": newMetadata[structs.GetRandaoResponse](v1PathTemplate,
|
||||
"/beacon/states/{param1}/randao": newMetadata[structs.GetRandaoResponse](
|
||||
v1PathTemplate,
|
||||
withParams(func(_ primitives.Epoch) []string {
|
||||
return []string{"head"}
|
||||
})),
|
||||
"/beacon/headers": newMetadata[structs.GetBlockHeadersResponse](v1PathTemplate),
|
||||
"/beacon/headers/{param1}": newMetadata[structs.GetBlockHeaderResponse](v1PathTemplate,
|
||||
withParams(func(e primitives.Epoch) []string {
|
||||
"/beacon/headers/{param1}": newMetadata[structs.GetBlockHeaderResponse](
|
||||
v1PathTemplate,
|
||||
withParams(func(currentEpoch primitives.Epoch) []string {
|
||||
slot := uint64(0)
|
||||
if e > 0 {
|
||||
slot = (uint64(e) * uint64(params.BeaconConfig().SlotsPerEpoch)) - 1
|
||||
if currentEpoch > 0 {
|
||||
slot = (uint64(currentEpoch) * uint64(params.BeaconConfig().SlotsPerEpoch)) - 1
|
||||
}
|
||||
return []string{fmt.Sprintf("%v", slot)}
|
||||
})),
|
||||
"/beacon/blocks/{param1}": newMetadata[structs.GetBlockV2Response](v2PathTemplate,
|
||||
"/beacon/blocks/{param1}": newMetadata[structs.GetBlockV2Response](
|
||||
v2PathTemplate,
|
||||
withSsz(),
|
||||
withParams(func(_ primitives.Epoch) []string {
|
||||
return []string{"head"}
|
||||
})),
|
||||
"/beacon/blocks/{param1}/root": newMetadata[structs.BlockRootResponse](v1PathTemplate,
|
||||
"/beacon/blocks/{param1}/root": newMetadata[structs.BlockRootResponse](
|
||||
v1PathTemplate,
|
||||
withParams(func(_ primitives.Epoch) []string {
|
||||
return []string{"head"}
|
||||
})),
|
||||
"/beacon/blocks/{param1}/attestations": newMetadata[structs.GetBlockAttestationsResponse](v1PathTemplate,
|
||||
"/beacon/blocks/{param1}/attestations": newMetadata[structs.GetBlockAttestationsResponse](
|
||||
v1PathTemplate,
|
||||
withParams(func(_ primitives.Epoch) []string {
|
||||
return []string{"head"}
|
||||
})),
|
||||
"/beacon/blinded_blocks/{param1}": newMetadata[structs.GetBlockV2Response](v1PathTemplate,
|
||||
"/beacon/blob_sidecars/{param1}": newMetadata[structs.SidecarsResponse](
|
||||
v1PathTemplate,
|
||||
withStart(params.BeaconConfig().DenebForkEpoch),
|
||||
withSsz(),
|
||||
withParams(func(_ primitives.Epoch) []string {
|
||||
return []string{"head"}
|
||||
})),
|
||||
"/beacon/pool/attestations": newMetadata[structs.ListAttestationsResponse](v1PathTemplate,
|
||||
withCustomEval(func(p interface{}, _ interface{}) error {
|
||||
pResp, ok := p.(*structs.ListAttestationsResponse)
|
||||
if !ok {
|
||||
return fmt.Errorf(msgWrongJson, &structs.ListAttestationsResponse{}, p)
|
||||
}
|
||||
if pResp.Data == nil {
|
||||
return errEmptyPrysmData
|
||||
}
|
||||
return nil
|
||||
"/beacon/blinded_blocks/{param1}": newMetadata[structs.GetBlockV2Response](
|
||||
v1PathTemplate,
|
||||
withSsz(),
|
||||
withParams(func(_ primitives.Epoch) []string {
|
||||
return []string{"head"}
|
||||
})),
|
||||
"/beacon/pool/attester_slashings": newMetadata[structs.GetAttesterSlashingsResponse](v1PathTemplate,
|
||||
withCustomEval(func(p interface{}, _ interface{}) error {
|
||||
pResp, ok := p.(*structs.GetAttesterSlashingsResponse)
|
||||
if !ok {
|
||||
return fmt.Errorf(msgWrongJson, &structs.GetAttesterSlashingsResponse{}, p)
|
||||
}
|
||||
if pResp.Data == nil {
|
||||
return errEmptyPrysmData
|
||||
}
|
||||
return nil
|
||||
"/beacon/pool/attestations": newMetadata[structs.ListAttestationsResponse](
|
||||
v1PathTemplate,
|
||||
withSanityCheckOnly()),
|
||||
"/beacon/pool/attester_slashings": newMetadata[structs.GetAttesterSlashingsResponse](
|
||||
v1PathTemplate,
|
||||
withSanityCheckOnly()),
|
||||
"/beacon/pool/proposer_slashings": newMetadata[structs.GetProposerSlashingsResponse](
|
||||
v1PathTemplate,
|
||||
withSanityCheckOnly()),
|
||||
"/beacon/pool/voluntary_exits": newMetadata[structs.ListVoluntaryExitsResponse](
|
||||
v1PathTemplate,
|
||||
withSanityCheckOnly()),
|
||||
"/beacon/pool/bls_to_execution_changes": newMetadata[structs.BLSToExecutionChangesPoolResponse](
|
||||
v1PathTemplate,
|
||||
withSanityCheckOnly()),
|
||||
"/builder/states/{param1}/expected_withdrawals": newMetadata[structs.ExpectedWithdrawalsResponse](
|
||||
v1PathTemplate,
|
||||
withStart(params.CapellaE2EForkEpoch),
|
||||
withParams(func(_ primitives.Epoch) []string {
|
||||
return []string{"head"}
|
||||
})),
|
||||
"/beacon/pool/proposer_slashings": newMetadata[structs.GetProposerSlashingsResponse](v1PathTemplate,
|
||||
withCustomEval(func(p interface{}, _ interface{}) error {
|
||||
pResp, ok := p.(*structs.GetProposerSlashingsResponse)
|
||||
if !ok {
|
||||
return fmt.Errorf(msgWrongJson, &structs.GetProposerSlashingsResponse{}, p)
|
||||
}
|
||||
if pResp.Data == nil {
|
||||
return errEmptyPrysmData
|
||||
}
|
||||
return nil
|
||||
})),
|
||||
"/beacon/pool/voluntary_exits": newMetadata[structs.ListVoluntaryExitsResponse](v1PathTemplate,
|
||||
withCustomEval(func(p interface{}, _ interface{}) error {
|
||||
pResp, ok := p.(*structs.ListVoluntaryExitsResponse)
|
||||
if !ok {
|
||||
return fmt.Errorf(msgWrongJson, &structs.ListVoluntaryExitsResponse{}, p)
|
||||
}
|
||||
if pResp.Data == nil {
|
||||
return errEmptyPrysmData
|
||||
}
|
||||
return nil
|
||||
})),
|
||||
"/beacon/pool/bls_to_execution_changes": newMetadata[structs.BLSToExecutionChangesPoolResponse](v1PathTemplate,
|
||||
withCustomEval(func(p interface{}, _ interface{}) error {
|
||||
pResp, ok := p.(*structs.BLSToExecutionChangesPoolResponse)
|
||||
if !ok {
|
||||
return fmt.Errorf(msgWrongJson, &structs.BLSToExecutionChangesPoolResponse{}, p)
|
||||
}
|
||||
if pResp.Data == nil {
|
||||
return errEmptyPrysmData
|
||||
}
|
||||
return nil
|
||||
})),
|
||||
"/config/fork_schedule": newMetadata[structs.GetForkScheduleResponse](v1PathTemplate,
|
||||
"/config/fork_schedule": newMetadata[structs.GetForkScheduleResponse](
|
||||
v1PathTemplate,
|
||||
withCustomEval(func(p interface{}, lh interface{}) error {
|
||||
pResp, ok := p.(*structs.GetForkScheduleResponse)
|
||||
if !ok {
|
||||
@@ -142,12 +130,6 @@ var requests = map[string]endpoint{
|
||||
if !ok {
|
||||
return fmt.Errorf(msgWrongJson, &structs.GetForkScheduleResponse{}, lh)
|
||||
}
|
||||
if pResp.Data == nil {
|
||||
return errEmptyPrysmData
|
||||
}
|
||||
if lhResp.Data == nil {
|
||||
return errEmptyLighthouseData
|
||||
}
|
||||
// remove all forks with far-future epoch
|
||||
for i := len(pResp.Data) - 1; i >= 0; i-- {
|
||||
if pResp.Data[i].Epoch == fmt.Sprintf("%d", params.BeaconConfig().FarFutureEpoch) {
|
||||
@@ -161,69 +143,52 @@ var requests = map[string]endpoint{
|
||||
}
|
||||
return compareJSON(pResp, lhResp)
|
||||
})),
|
||||
"/config/spec": newMetadata[structs.GetSpecResponse](
|
||||
v1PathTemplate,
|
||||
withSanityCheckOnly()),
|
||||
"/config/deposit_contract": newMetadata[structs.GetDepositContractResponse](v1PathTemplate),
|
||||
"/debug/beacon/heads": newMetadata[structs.GetForkChoiceHeadsV2Response](v2PathTemplate),
|
||||
"/node/identity": newMetadata[structs.GetIdentityResponse](v1PathTemplate,
|
||||
withCustomEval(func(p interface{}, _ interface{}) error {
|
||||
pResp, ok := p.(*structs.GetIdentityResponse)
|
||||
if !ok {
|
||||
return fmt.Errorf(msgWrongJson, &structs.GetIdentityResponse{}, p)
|
||||
}
|
||||
if pResp.Data == nil {
|
||||
return errEmptyPrysmData
|
||||
}
|
||||
return nil
|
||||
"/debug/beacon/states/{param1}": newMetadata[structs.GetBeaconStateV2Response](
|
||||
v2PathTemplate,
|
||||
withSanityCheckOnly(),
|
||||
withSsz(),
|
||||
withParams(func(_ primitives.Epoch) []string {
|
||||
return []string{"head"}
|
||||
})),
|
||||
"/node/peers": newMetadata[structs.GetPeersResponse](v1PathTemplate,
|
||||
"/debug/beacon/heads": newMetadata[structs.GetForkChoiceHeadsV2Response](
|
||||
v2PathTemplate,
|
||||
withSanityCheckOnly()),
|
||||
"/debug/fork_choice": newMetadata[structs.GetForkChoiceDumpResponse](
|
||||
v1PathTemplate,
|
||||
withSanityCheckOnly()),
|
||||
"/node/identity": newMetadata[structs.GetIdentityResponse](
|
||||
v1PathTemplate,
|
||||
withSanityCheckOnly()),
|
||||
"/node/peers": newMetadata[structs.GetPeersResponse](
|
||||
v1PathTemplate,
|
||||
withSanityCheckOnly()),
|
||||
"/node/peer_count": newMetadata[structs.GetPeerCountResponse](
|
||||
v1PathTemplate,
|
||||
withSanityCheckOnly()),
|
||||
"/node/version": newMetadata[structs.GetVersionResponse](
|
||||
v1PathTemplate,
|
||||
withCustomEval(func(p interface{}, _ interface{}) error {
|
||||
pResp, ok := p.(*structs.GetPeersResponse)
|
||||
if !ok {
|
||||
return fmt.Errorf(msgWrongJson, &structs.GetPeersResponse{}, p)
|
||||
}
|
||||
if pResp.Data == nil {
|
||||
return errEmptyPrysmData
|
||||
}
|
||||
return nil
|
||||
})),
|
||||
"/node/peer_count": newMetadata[structs.GetPeerCountResponse](v1PathTemplate,
|
||||
withCustomEval(func(p interface{}, _ interface{}) error {
|
||||
pResp, ok := p.(*structs.GetPeerCountResponse)
|
||||
if !ok {
|
||||
return fmt.Errorf(msgWrongJson, &structs.GetPeerCountResponse{}, p)
|
||||
}
|
||||
if pResp.Data == nil {
|
||||
return errEmptyPrysmData
|
||||
}
|
||||
return nil
|
||||
})),
|
||||
"/node/version": newMetadata[structs.GetVersionResponse](v1PathTemplate,
|
||||
withCustomEval(func(p interface{}, lh interface{}) error {
|
||||
pResp, ok := p.(*structs.GetVersionResponse)
|
||||
if !ok {
|
||||
return fmt.Errorf(msgWrongJson, &structs.ListAttestationsResponse{}, p)
|
||||
}
|
||||
lhResp, ok := lh.(*structs.GetVersionResponse)
|
||||
if !ok {
|
||||
return fmt.Errorf(msgWrongJson, &structs.ListAttestationsResponse{}, p)
|
||||
}
|
||||
if pResp.Data == nil {
|
||||
return errEmptyPrysmData
|
||||
}
|
||||
if !strings.Contains(pResp.Data.Version, "Prysm") {
|
||||
return errors.New("version response does not contain Prysm client name")
|
||||
}
|
||||
if lhResp.Data == nil {
|
||||
return errEmptyLighthouseData
|
||||
}
|
||||
if !strings.Contains(lhResp.Data.Version, "Lighthouse") {
|
||||
return errors.New("version response does not contain Lighthouse client name")
|
||||
}
|
||||
return nil
|
||||
})),
|
||||
"/node/syncing": newMetadata[structs.SyncStatusResponse](v1PathTemplate),
|
||||
"/validator/duties/proposer/{param1}": newMetadata[structs.GetProposerDutiesResponse](v1PathTemplate,
|
||||
withParams(func(e primitives.Epoch) []string {
|
||||
return []string{fmt.Sprintf("%v", e)}
|
||||
"/validator/duties/proposer/{param1}": newMetadata[structs.GetProposerDutiesResponse](
|
||||
v1PathTemplate,
|
||||
withParams(func(currentEpoch primitives.Epoch) []string {
|
||||
return []string{fmt.Sprintf("%v", currentEpoch)}
|
||||
}),
|
||||
withCustomEval(func(p interface{}, lh interface{}) error {
|
||||
pResp, ok := p.(*structs.GetProposerDutiesResponse)
|
||||
@@ -241,39 +206,56 @@ var requests = map[string]endpoint{
|
||||
return errEmptyLighthouseData
|
||||
}
|
||||
if lhResp.Data[0].Slot == "0" {
|
||||
// remove the first item from lighthouse data since lighthouse is returning a value despite no proposer
|
||||
// there is no proposer on slot 0 so prysm don't return anything for slot 0
|
||||
// Lighthouse returns a proposer for slot 0 and Prysm doesn't
|
||||
lhResp.Data = lhResp.Data[1:]
|
||||
}
|
||||
return compareJSON(pResp, lhResp)
|
||||
})),
|
||||
"/validator/duties/attester/{param1}": newMetadata[structs.GetAttesterDutiesResponse](v1PathTemplate,
|
||||
withParams(func(e primitives.Epoch) []string {
|
||||
//ask for a future epoch to test this case
|
||||
return []string{fmt.Sprintf("%v", e+1)}
|
||||
}
|
||||
|
||||
var postRequests = map[string]endpoint{
|
||||
"/beacon/states/{param1}/validators": newMetadata[structs.GetValidatorsResponse](
|
||||
v1PathTemplate,
|
||||
withParams(func(_ primitives.Epoch) []string {
|
||||
return []string{"head"}
|
||||
}),
|
||||
withReq(func() []string {
|
||||
withPOSTObj(func() interface{} {
|
||||
return struct {
|
||||
Ids []string `json:"ids"`
|
||||
Statuses []string `json:"statuses"`
|
||||
}{Ids: []string{"0", "1"}, Statuses: nil}
|
||||
}())),
|
||||
"/beacon/states/{param1}/validator_balances": newMetadata[structs.GetValidatorBalancesResponse](
|
||||
v1PathTemplate,
|
||||
withParams(func(_ primitives.Epoch) []string {
|
||||
return []string{"head"}
|
||||
}),
|
||||
withPOSTObj(func() []string {
|
||||
return []string{"0", "1"}
|
||||
}())),
|
||||
"/validator/duties/attester/{param1}": newMetadata[structs.GetAttesterDutiesResponse](
|
||||
v1PathTemplate,
|
||||
withParams(func(currentEpoch primitives.Epoch) []string {
|
||||
return []string{fmt.Sprintf("%v", currentEpoch)}
|
||||
}),
|
||||
withPOSTObj(func() []string {
|
||||
validatorIndices := make([]string, 64)
|
||||
for key := range validatorIndices {
|
||||
validatorIndices[key] = fmt.Sprintf("%d", key)
|
||||
for i := range validatorIndices {
|
||||
validatorIndices[i] = fmt.Sprintf("%d", i)
|
||||
}
|
||||
return validatorIndices
|
||||
}()),
|
||||
withCustomEval(func(p interface{}, lh interface{}) error {
|
||||
pResp, ok := p.(*structs.GetAttesterDutiesResponse)
|
||||
if !ok {
|
||||
return fmt.Errorf(msgWrongJson, &structs.GetAttesterDutiesResponse{}, p)
|
||||
}())),
|
||||
"/validator/duties/sync/{param1}": newMetadata[structs.GetSyncCommitteeDutiesResponse](
|
||||
v1PathTemplate,
|
||||
withStart(params.AltairE2EForkEpoch),
|
||||
withParams(func(currentEpoch primitives.Epoch) []string {
|
||||
return []string{fmt.Sprintf("%v", currentEpoch)}
|
||||
}),
|
||||
withPOSTObj(func() []string {
|
||||
validatorIndices := make([]string, 64)
|
||||
for i := range validatorIndices {
|
||||
validatorIndices[i] = fmt.Sprintf("%d", i)
|
||||
}
|
||||
lhResp, ok := lh.(*structs.GetAttesterDutiesResponse)
|
||||
if !ok {
|
||||
return fmt.Errorf(msgWrongJson, &structs.GetAttesterDutiesResponse{}, lh)
|
||||
}
|
||||
if pResp.Data == nil {
|
||||
return errEmptyPrysmData
|
||||
}
|
||||
if lhResp.Data == nil {
|
||||
return errEmptyLighthouseData
|
||||
}
|
||||
return compareJSON(pResp, lhResp)
|
||||
})),
|
||||
return validatorIndices
|
||||
}())),
|
||||
}
|
||||
|
||||
@@ -1,17 +1,21 @@
|
||||
package beaconapi
|
||||
|
||||
import "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
import (
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
)
|
||||
|
||||
type endpoint interface {
|
||||
getBasePath() string
|
||||
sanityCheckOnlyEnabled() bool
|
||||
enableSanityCheckOnly()
|
||||
sszEnabled() bool
|
||||
enableSsz()
|
||||
getSszResp() []byte // retrieves the Prysm SSZ response
|
||||
setSszResp(resp []byte) // sets the Prysm SSZ response
|
||||
getStart() primitives.Epoch
|
||||
setStart(start primitives.Epoch)
|
||||
getReq() interface{}
|
||||
setReq(req interface{})
|
||||
getPOSTObj() interface{}
|
||||
setPOSTObj(obj interface{})
|
||||
getPResp() interface{} // retrieves the Prysm JSON response
|
||||
getLHResp() interface{} // retrieves the Lighthouse JSON response
|
||||
getParams(epoch primitives.Epoch) []string
|
||||
@@ -22,9 +26,10 @@ type endpoint interface {
|
||||
|
||||
type apiEndpoint[Resp any] struct {
|
||||
basePath string
|
||||
sanity bool
|
||||
ssz bool
|
||||
start primitives.Epoch
|
||||
req interface{}
|
||||
postObj interface{}
|
||||
pResp *Resp // Prysm JSON response
|
||||
lhResp *Resp // Lighthouse JSON response
|
||||
sszResp []byte // Prysm SSZ response
|
||||
@@ -36,6 +41,14 @@ func (e *apiEndpoint[Resp]) getBasePath() string {
|
||||
return e.basePath
|
||||
}
|
||||
|
||||
func (e *apiEndpoint[Resp]) sanityCheckOnlyEnabled() bool {
|
||||
return e.sanity
|
||||
}
|
||||
|
||||
func (e *apiEndpoint[Resp]) enableSanityCheckOnly() {
|
||||
e.sanity = true
|
||||
}
|
||||
|
||||
func (e *apiEndpoint[Resp]) sszEnabled() bool {
|
||||
return e.ssz
|
||||
}
|
||||
@@ -60,12 +73,12 @@ func (e *apiEndpoint[Resp]) setStart(start primitives.Epoch) {
|
||||
e.start = start
|
||||
}
|
||||
|
||||
func (e *apiEndpoint[Resp]) getReq() interface{} {
|
||||
return e.req
|
||||
func (e *apiEndpoint[Resp]) getPOSTObj() interface{} {
|
||||
return e.postObj
|
||||
}
|
||||
|
||||
func (e *apiEndpoint[Resp]) setReq(req interface{}) {
|
||||
e.req = req
|
||||
func (e *apiEndpoint[Resp]) setPOSTObj(obj interface{}) {
|
||||
e.postObj = obj
|
||||
}
|
||||
|
||||
func (e *apiEndpoint[Resp]) getPResp() interface{} {
|
||||
@@ -109,30 +122,42 @@ func newMetadata[Resp any](basePath string, opts ...endpointOpt) *apiEndpoint[Re
|
||||
|
||||
type endpointOpt func(endpoint)
|
||||
|
||||
// We only care if the request was successful, without comparing responses.
|
||||
func withSanityCheckOnly() endpointOpt {
|
||||
return func(e endpoint) {
|
||||
e.enableSanityCheckOnly()
|
||||
}
|
||||
}
|
||||
|
||||
// We request SSZ data too.
|
||||
func withSsz() endpointOpt {
|
||||
return func(e endpoint) {
|
||||
e.enableSsz()
|
||||
}
|
||||
}
|
||||
|
||||
// We begin issuing the request at a particular epoch.
|
||||
func withStart(start primitives.Epoch) endpointOpt {
|
||||
return func(e endpoint) {
|
||||
e.setStart(start)
|
||||
}
|
||||
}
|
||||
|
||||
func withReq(req interface{}) endpointOpt {
|
||||
// We perform a POST instead of GET, sending an object.
|
||||
func withPOSTObj(obj interface{}) endpointOpt {
|
||||
return func(e endpoint) {
|
||||
e.setReq(req)
|
||||
e.setPOSTObj(obj)
|
||||
}
|
||||
}
|
||||
|
||||
// We specify URL parameters.
|
||||
func withParams(f func(currentEpoch primitives.Epoch) []string) endpointOpt {
|
||||
return func(e endpoint) {
|
||||
e.setParams(f)
|
||||
}
|
||||
}
|
||||
|
||||
// We perform custom evaluation on responses.
|
||||
func withCustomEval(f func(interface{}, interface{}) error) endpointOpt {
|
||||
return func(e endpoint) {
|
||||
e.setCustomEval(f)
|
||||
|
||||
@@ -25,16 +25,16 @@ const (
|
||||
msgSSZUnmarshalFailed = "failed to unmarshal SSZ"
|
||||
)
|
||||
|
||||
func doJSONGetRequest(template string, requestPath string, beaconNodeIdx int, resp interface{}, bnType ...string) error {
|
||||
func doJSONGetRequest(template, requestPath string, beaconNodeIdx int, resp interface{}, bnType ...string) error {
|
||||
if len(bnType) == 0 {
|
||||
bnType = []string{"prysm"}
|
||||
bnType = []string{"Prysm"}
|
||||
}
|
||||
|
||||
var port int
|
||||
switch bnType[0] {
|
||||
case "prysm":
|
||||
case "Prysm":
|
||||
port = params.TestParams.Ports.PrysmBeaconNodeGatewayPort
|
||||
case "lighthouse":
|
||||
case "Lighthouse":
|
||||
port = params.TestParams.Ports.LighthouseBeaconNodeHTTPPort
|
||||
default:
|
||||
return fmt.Errorf(msgUnknownNode, bnType[0])
|
||||
@@ -55,6 +55,7 @@ func doJSONGetRequest(template string, requestPath string, beaconNodeIdx int, re
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
defer closeBody(httpResp.Body)
|
||||
body, err = io.ReadAll(httpResp.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -65,17 +66,16 @@ func doJSONGetRequest(template string, requestPath string, beaconNodeIdx int, re
|
||||
return json.NewDecoder(httpResp.Body).Decode(&resp)
|
||||
}
|
||||
|
||||
func doSSZGetRequest(template string, requestPath string, beaconNodeIdx int, bnType ...string) ([]byte, error) {
|
||||
func doSSZGetRequest(template, requestPath string, beaconNodeIdx int, bnType ...string) ([]byte, error) {
|
||||
if len(bnType) == 0 {
|
||||
bnType = []string{"prysm"}
|
||||
bnType = []string{"Prysm"}
|
||||
}
|
||||
|
||||
client := &http.Client{}
|
||||
var port int
|
||||
switch bnType[0] {
|
||||
case "prysm":
|
||||
case "Prysm":
|
||||
port = params.TestParams.Ports.PrysmBeaconNodeGatewayPort
|
||||
case "lighthouse":
|
||||
case "Lighthouse":
|
||||
port = params.TestParams.Ports.LighthouseBeaconNodeHTTPPort
|
||||
default:
|
||||
return nil, fmt.Errorf(msgUnknownNode, bnType[0])
|
||||
@@ -83,24 +83,24 @@ func doSSZGetRequest(template string, requestPath string, beaconNodeIdx int, bnT
|
||||
|
||||
basePath := fmt.Sprintf(template, port+beaconNodeIdx)
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, basePath+requestPath, nil)
|
||||
req, err := http.NewRequest(http.MethodGet, basePath+requestPath, http.NoBody)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header.Set("Accept", "application/octet-stream")
|
||||
rsp, err := client.Do(req)
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if rsp.StatusCode != http.StatusOK {
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
var body interface{}
|
||||
if err := json.NewDecoder(rsp.Body).Decode(&body); err != nil {
|
||||
if err := json.NewDecoder(resp.Body).Decode(&body); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, fmt.Errorf(msgRequestFailed, bnType[0], rsp.StatusCode, body)
|
||||
return nil, fmt.Errorf(msgRequestFailed, bnType[0], resp.StatusCode, body)
|
||||
}
|
||||
defer closeBody(rsp.Body)
|
||||
body, err := io.ReadAll(rsp.Body)
|
||||
defer closeBody(resp.Body)
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -108,23 +108,23 @@ func doSSZGetRequest(template string, requestPath string, beaconNodeIdx int, bnT
|
||||
return body, nil
|
||||
}
|
||||
|
||||
func doJSONPostRequest(template string, requestPath string, beaconNodeIdx int, postData, resp interface{}, bnType ...string) error {
|
||||
func doJSONPostRequest(template, requestPath string, beaconNodeIdx int, postObj, resp interface{}, bnType ...string) error {
|
||||
if len(bnType) == 0 {
|
||||
bnType = []string{"prysm"}
|
||||
bnType = []string{"Prysm"}
|
||||
}
|
||||
|
||||
var port int
|
||||
switch bnType[0] {
|
||||
case "prysm":
|
||||
case "Prysm":
|
||||
port = params.TestParams.Ports.PrysmBeaconNodeGatewayPort
|
||||
case "lighthouse":
|
||||
case "Lighthouse":
|
||||
port = params.TestParams.Ports.LighthouseBeaconNodeHTTPPort
|
||||
default:
|
||||
return fmt.Errorf(msgUnknownNode, bnType[0])
|
||||
}
|
||||
|
||||
basePath := fmt.Sprintf(template, port+beaconNodeIdx)
|
||||
b, err := json.Marshal(postData)
|
||||
b, err := json.Marshal(postObj)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -144,6 +144,7 @@ func doJSONPostRequest(template string, requestPath string, beaconNodeIdx int, p
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
defer closeBody(httpResp.Body)
|
||||
body, err = io.ReadAll(httpResp.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -14,6 +15,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v5/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
params2 "github.com/prysmaticlabs/prysm/v5/testing/endtoend/params"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/endtoend/policies"
|
||||
e2etypes "github.com/prysmaticlabs/prysm/v5/testing/endtoend/types"
|
||||
"github.com/prysmaticlabs/prysm/v5/time/slots"
|
||||
@@ -54,7 +56,7 @@ func run(nodeIdx int) error {
|
||||
}
|
||||
currentEpoch := slots.EpochsSinceGenesis(time.Unix(genesisTime, 0))
|
||||
|
||||
for path, m := range requests {
|
||||
for path, m := range getRequests {
|
||||
if currentEpoch < m.getStart() {
|
||||
continue
|
||||
}
|
||||
@@ -62,26 +64,57 @@ func run(nodeIdx int) error {
|
||||
if m.getParams(currentEpoch) != nil {
|
||||
apiPath = pathFromParams(path, m.getParams(currentEpoch))
|
||||
}
|
||||
fmt.Printf("executing JSON path: %s\n", apiPath)
|
||||
if err = compareJSONMultiClient(nodeIdx, m.getBasePath(), apiPath, m.getReq(), m.getPResp(), m.getLHResp(), m.getCustomEval()); err != nil {
|
||||
return err
|
||||
}
|
||||
if m.sszEnabled() {
|
||||
fmt.Printf("executing SSZ path: %s\n", apiPath)
|
||||
b, err := compareSSZMultiClient(nodeIdx, m.getBasePath(), apiPath)
|
||||
if err != nil {
|
||||
|
||||
if m.sanityCheckOnlyEnabled() {
|
||||
resp := m.getPResp()
|
||||
if err = doJSONGetRequest(m.getBasePath(), apiPath, nodeIdx, resp); err != nil {
|
||||
return errors.Wrapf(err, "issue during Prysm JSON GET request for path %s", apiPath)
|
||||
}
|
||||
if resp == nil {
|
||||
return fmt.Errorf("nil response from Prysm JSON GET request for path %s", apiPath)
|
||||
}
|
||||
if m.sszEnabled() {
|
||||
sszResp, err := doSSZGetRequest(m.getBasePath(), apiPath, nodeIdx)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "issue during Prysm SSZ GET request for path %s", apiPath)
|
||||
}
|
||||
if sszResp == nil {
|
||||
return fmt.Errorf("nil response from Prysm SSZ GET request for path %s", apiPath)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if err = compareGETJSON(nodeIdx, m.getBasePath(), apiPath, m.getPResp(), m.getLHResp(), m.getCustomEval()); err != nil {
|
||||
return err
|
||||
}
|
||||
m.setSszResp(b)
|
||||
if m.sszEnabled() {
|
||||
b, err := compareGETSSZ(nodeIdx, m.getBasePath(), apiPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m.setSszResp(b)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return postEvaluation(requests, currentEpoch)
|
||||
for path, m := range postRequests {
|
||||
if currentEpoch < m.getStart() {
|
||||
continue
|
||||
}
|
||||
apiPath := path
|
||||
if m.getParams(currentEpoch) != nil {
|
||||
apiPath = pathFromParams(path, m.getParams(currentEpoch))
|
||||
}
|
||||
if err = comparePOSTJSON(nodeIdx, m.getBasePath(), apiPath, m.getPOSTObj(), m.getPResp(), m.getLHResp(), m.getCustomEval()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return postEvaluation(nodeIdx, getRequests, currentEpoch)
|
||||
}
|
||||
|
||||
// postEvaluation performs additional evaluation after all requests have been completed.
|
||||
// It is useful for things such as checking if specific fields match between endpoints.
|
||||
func postEvaluation(requests map[string]endpoint, epoch primitives.Epoch) error {
|
||||
func postEvaluation(nodeIdx int, requests map[string]endpoint, epoch primitives.Epoch) error {
|
||||
// verify that block SSZ responses have the correct structure
|
||||
blockData := requests["/beacon/blocks/{param1}"]
|
||||
blindedBlockData := requests["/beacon/blinded_blocks/{param1}"]
|
||||
@@ -147,24 +180,31 @@ func postEvaluation(requests map[string]endpoint, epoch primitives.Epoch) error
|
||||
return fmt.Errorf("header root %s does not match duties root %s ", header.Data.Root, duties.DependentRoot)
|
||||
}
|
||||
|
||||
// perform a health check
|
||||
basePath := fmt.Sprintf(v1PathTemplate, params2.PrysmBeaconNodeGatewayPort+nodeIdx)
|
||||
resp, err := http.Get(basePath + "/node/health")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not perform a health check")
|
||||
}
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return fmt.Errorf("health check response's status code is %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func compareJSONMultiClient(nodeIdx int, base, path string, req, pResp, lhResp interface{}, customEval func(interface{}, interface{}) error) error {
|
||||
if req != nil {
|
||||
if err := doJSONPostRequest(base, path, nodeIdx, req, pResp); err != nil {
|
||||
return errors.Wrapf(err, "could not perform Prysm JSON POST request for path %s", path)
|
||||
}
|
||||
if err := doJSONPostRequest(base, path, nodeIdx, req, lhResp, "lighthouse"); err != nil {
|
||||
return errors.Wrapf(err, "could not perform Lighthouse JSON POST request for path %s", path)
|
||||
}
|
||||
} else {
|
||||
if err := doJSONGetRequest(base, path, nodeIdx, pResp); err != nil {
|
||||
return errors.Wrapf(err, "could not perform Prysm JSON GET request for path %s", path)
|
||||
}
|
||||
if err := doJSONGetRequest(base, path, nodeIdx, lhResp, "lighthouse"); err != nil {
|
||||
return errors.Wrapf(err, "could not perform Lighthouse JSON GET request for path %s", path)
|
||||
}
|
||||
func compareGETJSON(nodeIdx int, base, path string, pResp, lhResp interface{}, customEval func(interface{}, interface{}) error) error {
|
||||
if err := doJSONGetRequest(base, path, nodeIdx, pResp); err != nil {
|
||||
return errors.Wrapf(err, "issue during Prysm JSON GET request for path %s", path)
|
||||
}
|
||||
if err := doJSONGetRequest(base, path, nodeIdx, lhResp, "Lighthouse"); err != nil {
|
||||
return errors.Wrapf(err, "issue during Lighthouse JSON GET request for path %s", path)
|
||||
}
|
||||
if pResp == nil {
|
||||
return errEmptyPrysmData
|
||||
}
|
||||
if lhResp == nil {
|
||||
return errEmptyLighthouseData
|
||||
}
|
||||
if customEval != nil {
|
||||
return customEval(pResp, lhResp)
|
||||
@@ -173,14 +213,34 @@ func compareJSONMultiClient(nodeIdx int, base, path string, req, pResp, lhResp i
|
||||
}
|
||||
}
|
||||
|
||||
func compareSSZMultiClient(nodeIdx int, base, path string) ([]byte, error) {
|
||||
func comparePOSTJSON(nodeIdx int, base, path string, postObj, pResp, lhResp interface{}, customEval func(interface{}, interface{}) error) error {
|
||||
if err := doJSONPostRequest(base, path, nodeIdx, postObj, pResp); err != nil {
|
||||
return errors.Wrapf(err, "issue during Prysm JSON POST request for path %s", path)
|
||||
}
|
||||
if err := doJSONPostRequest(base, path, nodeIdx, postObj, lhResp, "Lighthouse"); err != nil {
|
||||
return errors.Wrapf(err, "issue during Lighthouse JSON POST request for path %s", path)
|
||||
}
|
||||
if pResp == nil {
|
||||
return errEmptyPrysmData
|
||||
}
|
||||
if lhResp == nil {
|
||||
return errEmptyLighthouseData
|
||||
}
|
||||
if customEval != nil {
|
||||
return customEval(pResp, lhResp)
|
||||
} else {
|
||||
return compareJSON(pResp, lhResp)
|
||||
}
|
||||
}
|
||||
|
||||
func compareGETSSZ(nodeIdx int, base, path string) ([]byte, error) {
|
||||
pResp, err := doSSZGetRequest(base, path, nodeIdx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not perform Prysm SSZ GET request for path %s", path)
|
||||
return nil, errors.Wrapf(err, "issue during Prysm SSZ GET request for path %s", path)
|
||||
}
|
||||
lhResp, err := doSSZGetRequest(base, path, nodeIdx, "lighthouse")
|
||||
lhResp, err := doSSZGetRequest(base, path, nodeIdx, "Lighthouse")
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not perform Lighthouse SSZ GET request for path %s", path)
|
||||
return nil, errors.Wrapf(err, "issue during Lighthouse SSZ GET request for path %s", path)
|
||||
}
|
||||
if !bytes.Equal(pResp, lhResp) {
|
||||
return nil, errors.New("Prysm SSZ response does not match Lighthouse SSZ response")
|
||||
@@ -188,7 +248,7 @@ func compareSSZMultiClient(nodeIdx int, base, path string) ([]byte, error) {
|
||||
return pResp, nil
|
||||
}
|
||||
|
||||
func compareJSON(pResp interface{}, lhResp interface{}) error {
|
||||
func compareJSON(pResp, lhResp interface{}) error {
|
||||
if !reflect.DeepEqual(pResp, lhResp) {
|
||||
p, err := json.Marshal(pResp)
|
||||
if err != nil {
|
||||
|
||||
@@ -639,6 +639,17 @@ func (c *ValidatorClient) registerRPCService(router *mux.Router) error {
|
||||
walletDir := c.cliCtx.String(flags.WalletDirFlag.Name)
|
||||
grpcHeaders := c.cliCtx.String(flags.GrpcHeadersFlag.Name)
|
||||
clientCert := c.cliCtx.String(flags.CertFlag.Name)
|
||||
|
||||
authTokenPath := c.cliCtx.String(flags.AuthTokenPathFlag.Name)
|
||||
// if no auth token path flag was passed try to set a default value
|
||||
if authTokenPath == "" {
|
||||
authTokenPath = flags.AuthTokenPathFlag.Value
|
||||
// if a wallet dir is passed without an auth token then override the default with the wallet dir
|
||||
if walletDir != "" {
|
||||
authTokenPath = filepath.Join(walletDir, api.AuthTokenFileName)
|
||||
}
|
||||
}
|
||||
|
||||
server := rpc.NewServer(c.cliCtx.Context, &rpc.Config{
|
||||
ValDB: c.db,
|
||||
Host: rpcHost,
|
||||
@@ -648,6 +659,7 @@ func (c *ValidatorClient) registerRPCService(router *mux.Router) error {
|
||||
SyncChecker: vs,
|
||||
GenesisFetcher: vs,
|
||||
NodeGatewayEndpoint: nodeGatewayEndpoint,
|
||||
AuthTokenPath: authTokenPath,
|
||||
WalletDir: walletDir,
|
||||
Wallet: c.wallet,
|
||||
ValidatorGatewayHost: validatorGatewayHost,
|
||||
|
||||
@@ -38,7 +38,6 @@ go_library(
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//consensus-types/validator:go_default_library",
|
||||
"//crypto/bls:go_default_library",
|
||||
"//crypto/rand:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//io/file:go_default_library",
|
||||
"//io/logs:go_default_library",
|
||||
@@ -148,6 +147,7 @@ go_test(
|
||||
"@com_github_gorilla_mux//:go_default_library",
|
||||
"@com_github_grpc_ecosystem_grpc_gateway_v2//runtime:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//hooks/test:go_default_library",
|
||||
"@com_github_tyler_smith_go_bip39//:go_default_library",
|
||||
"@com_github_wealdtech_go_eth2_wallet_encryptor_keystorev4//:go_default_library",
|
||||
"@org_golang_google_grpc//:go_default_library",
|
||||
|
||||
@@ -15,32 +15,24 @@ import (
|
||||
"github.com/fsnotify/fsnotify"
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/crypto/rand"
|
||||
"github.com/prysmaticlabs/prysm/v5/api"
|
||||
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/io/file"
|
||||
)
|
||||
|
||||
const (
|
||||
AuthTokenFileName = "auth-token"
|
||||
)
|
||||
|
||||
// CreateAuthToken generates a new jwt key, token and writes them
|
||||
// to a file in the specified directory. Also, it logs out a prepared URL
|
||||
// for the user to navigate to and authenticate with the Prysm web interface.
|
||||
func CreateAuthToken(walletDirPath, validatorWebAddr string) error {
|
||||
jwtKey, err := createRandomJWTSecret()
|
||||
func CreateAuthToken(authPath, validatorWebAddr string) error {
|
||||
token, err := api.GenerateRandomHexString()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
token, err := createTokenString(jwtKey)
|
||||
if err != nil {
|
||||
log.Infof("Generating auth token and saving it to %s", authPath)
|
||||
if err := saveAuthToken(authPath, token); err != nil {
|
||||
return err
|
||||
}
|
||||
authTokenPath := filepath.Join(walletDirPath, AuthTokenFileName)
|
||||
log.Infof("Generating auth token and saving it to %s", authTokenPath)
|
||||
if err := saveAuthToken(walletDirPath, jwtKey, token); err != nil {
|
||||
return err
|
||||
}
|
||||
logValidatorWebAuth(validatorWebAddr, token, authTokenPath)
|
||||
logValidatorWebAuth(validatorWebAddr, token, authPath)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -49,18 +41,18 @@ func CreateAuthToken(walletDirPath, validatorWebAddr string) error {
|
||||
// user via stdout and the validator client should then attempt to open the default
|
||||
// browser. The web interface authenticates by looking for this token in the query parameters
|
||||
// of the URL. This token is then used as the bearer token for jwt auth.
|
||||
func (s *Server) initializeAuthToken(walletDir string) (string, error) {
|
||||
authTokenFile := filepath.Join(walletDir, AuthTokenFileName)
|
||||
exists, err := file.Exists(authTokenFile, file.Regular)
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "could not check if file exists: %s", authTokenFile)
|
||||
func (s *Server) initializeAuthToken() error {
|
||||
if s.authTokenPath == "" {
|
||||
return errors.New("auth token path is empty")
|
||||
}
|
||||
exists, err := file.Exists(s.authTokenPath, file.Regular)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not check if file %s exists", s.authTokenPath)
|
||||
}
|
||||
|
||||
if exists {
|
||||
// #nosec G304
|
||||
f, err := os.Open(authTokenFile)
|
||||
f, err := os.Open(filepath.Clean(s.authTokenPath))
|
||||
if err != nil {
|
||||
return "", err
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err := f.Close(); err != nil {
|
||||
@@ -69,24 +61,18 @@ func (s *Server) initializeAuthToken(walletDir string) (string, error) {
|
||||
}()
|
||||
secret, token, err := readAuthTokenFile(f)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return err
|
||||
}
|
||||
s.jwtSecret = secret
|
||||
return token, nil
|
||||
s.authToken = token
|
||||
return nil
|
||||
}
|
||||
jwtKey, err := createRandomJWTSecret()
|
||||
token, err := api.GenerateRandomHexString()
|
||||
if err != nil {
|
||||
return "", err
|
||||
return err
|
||||
}
|
||||
s.jwtSecret = jwtKey
|
||||
token, err := createTokenString(s.jwtSecret)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if err := saveAuthToken(walletDir, jwtKey, token); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return token, nil
|
||||
s.authToken = token
|
||||
return saveAuthToken(s.authTokenPath, token)
|
||||
}
|
||||
|
||||
func (s *Server) refreshAuthTokenFromFileChanges(ctx context.Context, authTokenPath string) {
|
||||
@@ -106,16 +92,20 @@ func (s *Server) refreshAuthTokenFromFileChanges(ctx context.Context, authTokenP
|
||||
}
|
||||
for {
|
||||
select {
|
||||
case <-watcher.Events:
|
||||
case event := <-watcher.Events:
|
||||
if event.Op.String() == "REMOVE" {
|
||||
log.Error("Auth Token was removed! Restart the validator client to regenerate a token")
|
||||
s.authToken = ""
|
||||
continue
|
||||
}
|
||||
// If a file was modified, we attempt to read that file
|
||||
// and parse it into our accounts store.
|
||||
token, err := s.initializeAuthToken(s.walletDir)
|
||||
if err != nil {
|
||||
if err := s.initializeAuthToken(); err != nil {
|
||||
log.WithError(err).Errorf("Could not watch for file changes for: %s", authTokenPath)
|
||||
continue
|
||||
}
|
||||
validatorWebAddr := fmt.Sprintf("%s:%d", s.validatorGatewayHost, s.validatorGatewayPort)
|
||||
logValidatorWebAuth(validatorWebAddr, token, authTokenPath)
|
||||
logValidatorWebAuth(validatorWebAddr, s.authToken, authTokenPath)
|
||||
case err := <-watcher.Errors:
|
||||
log.WithError(err).Errorf("Could not watch for file changes for: %s", authTokenPath)
|
||||
case <-ctx.Done():
|
||||
@@ -124,7 +114,7 @@ func (s *Server) refreshAuthTokenFromFileChanges(ctx context.Context, authTokenP
|
||||
}
|
||||
}
|
||||
|
||||
func logValidatorWebAuth(validatorWebAddr, token string, tokenPath string) {
|
||||
func logValidatorWebAuth(validatorWebAddr, token, tokenPath string) {
|
||||
webAuthURLTemplate := "http://%s/initialize?token=%s"
|
||||
webAuthURL := fmt.Sprintf(
|
||||
webAuthURLTemplate,
|
||||
@@ -136,18 +126,11 @@ func logValidatorWebAuth(validatorWebAddr, token string, tokenPath string) {
|
||||
"the Prysm web interface",
|
||||
)
|
||||
log.Info(webAuthURL)
|
||||
log.Infof("Validator CLient JWT for RPC and REST authentication set at:%s", tokenPath)
|
||||
log.Infof("Validator Client auth token for gRPC and REST authentication set at %s", tokenPath)
|
||||
}
|
||||
|
||||
func saveAuthToken(walletDirPath string, jwtKey []byte, token string) error {
|
||||
hashFilePath := filepath.Join(walletDirPath, AuthTokenFileName)
|
||||
func saveAuthToken(tokenPath string, token string) error {
|
||||
bytesBuf := new(bytes.Buffer)
|
||||
if _, err := bytesBuf.WriteString(fmt.Sprintf("%x", jwtKey)); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := bytesBuf.WriteString("\n"); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := bytesBuf.WriteString(token); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -155,34 +138,61 @@ func saveAuthToken(walletDirPath string, jwtKey []byte, token string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := file.MkdirAll(walletDirPath); err != nil {
|
||||
return errors.Wrapf(err, "could not create directory %s", walletDirPath)
|
||||
if err := file.MkdirAll(filepath.Dir(tokenPath)); err != nil {
|
||||
return errors.Wrapf(err, "could not create directory %s", filepath.Dir(tokenPath))
|
||||
}
|
||||
|
||||
if err := file.WriteFile(hashFilePath, bytesBuf.Bytes()); err != nil {
|
||||
return errors.Wrapf(err, "could not write to file %s", hashFilePath)
|
||||
if err := file.WriteFile(tokenPath, bytesBuf.Bytes()); err != nil {
|
||||
return errors.Wrapf(err, "could not write to file %s", tokenPath)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func readAuthTokenFile(r io.Reader) (secret []byte, token string, err error) {
|
||||
br := bufio.NewReader(r)
|
||||
var jwtKeyHex string
|
||||
jwtKeyHex, err = br.ReadString('\n')
|
||||
if err != nil {
|
||||
return
|
||||
func readAuthTokenFile(r io.Reader) ([]byte, string, error) {
|
||||
scanner := bufio.NewScanner(r)
|
||||
var lines []string
|
||||
var secret []byte
|
||||
var token string
|
||||
// Scan the file and collect lines, excluding empty lines
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
if strings.TrimSpace(line) != "" {
|
||||
lines = append(lines, line)
|
||||
}
|
||||
}
|
||||
secret, err = hex.DecodeString(strings.TrimSpace(jwtKeyHex))
|
||||
if err != nil {
|
||||
return
|
||||
|
||||
// Check for scanning errors
|
||||
if err := scanner.Err(); err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
tokenBytes, _, err := br.ReadLine()
|
||||
if err != nil {
|
||||
return
|
||||
|
||||
// Process based on the number of lines, excluding empty ones
|
||||
switch len(lines) {
|
||||
case 1:
|
||||
// If there is only one line, interpret it as the token
|
||||
token = strings.TrimSpace(lines[0])
|
||||
case 2:
|
||||
// TODO: Deprecate after a few releases
|
||||
// For legacy files
|
||||
// If there are two lines, the first is the jwt key and the second is the token
|
||||
jwtKeyHex := strings.TrimSpace(lines[0])
|
||||
s, err := hex.DecodeString(jwtKeyHex)
|
||||
if err != nil {
|
||||
return nil, "", errors.Wrapf(err, "could not decode JWT secret")
|
||||
}
|
||||
secret = bytesutil.SafeCopyBytes(s)
|
||||
token = strings.TrimSpace(lines[1])
|
||||
log.Warn("Auth token is a legacy file and should be regenerated.")
|
||||
default:
|
||||
return nil, "", errors.New("Auth token file format has multiple lines, please update the auth token to a single line that is a 256 bit hex string")
|
||||
}
|
||||
token = strings.TrimSpace(string(tokenBytes))
|
||||
return
|
||||
if err := api.ValidateAuthToken(token); err != nil {
|
||||
log.WithError(err).Warn("Auth token does not follow our standards and should be regenerated either \n" +
|
||||
"1. by removing the current token file and restarting \n" +
|
||||
"2. using the `validator web generate-auth-token` command. \n" +
|
||||
"Tokens can be generated through the `validator web generate-auth-token` command")
|
||||
}
|
||||
return secret, token, nil
|
||||
}
|
||||
|
||||
// Creates a JWT token string using the JWT key.
|
||||
@@ -195,16 +205,3 @@ func createTokenString(jwtKey []byte) (string, error) {
|
||||
}
|
||||
return tokenString, nil
|
||||
}
|
||||
|
||||
func createRandomJWTSecret() ([]byte, error) {
|
||||
r := rand.NewGenerator()
|
||||
jwtKey := make([]byte, 32)
|
||||
n, err := r.Read(jwtKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if n != len(jwtKey) {
|
||||
return nil, errors.New("could not create appropriately sized random JWT secret")
|
||||
}
|
||||
return jwtKey, nil
|
||||
}
|
||||
|
||||
@@ -1,16 +1,22 @@
|
||||
package rpc
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
"github.com/prysmaticlabs/prysm/v5/api"
|
||||
"github.com/prysmaticlabs/prysm/v5/io/file"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
logTest "github.com/sirupsen/logrus/hooks/test"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/metadata"
|
||||
)
|
||||
@@ -24,11 +30,14 @@ func setupWalletDir(t testing.TB) string {
|
||||
func TestServer_AuthenticateUsingExistingToken(t *testing.T) {
|
||||
// Initializing for the first time, there is no auth token file in
|
||||
// the wallet directory, so we generate a jwt token and secret from scratch.
|
||||
srv := &Server{}
|
||||
walletDir := setupWalletDir(t)
|
||||
token, err := srv.initializeAuthToken(walletDir)
|
||||
authTokenPath := filepath.Join(walletDir, api.AuthTokenFileName)
|
||||
srv := &Server{
|
||||
authTokenPath: authTokenPath,
|
||||
}
|
||||
|
||||
err := srv.initializeAuthToken()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, true, len(srv.jwtSecret) > 0)
|
||||
|
||||
unaryInfo := &grpc.UnaryServerInfo{
|
||||
FullMethod: "Proto.CreateWallet",
|
||||
@@ -37,78 +46,173 @@ func TestServer_AuthenticateUsingExistingToken(t *testing.T) {
|
||||
return nil, nil
|
||||
}
|
||||
ctxMD := map[string][]string{
|
||||
"authorization": {"Bearer " + token},
|
||||
"authorization": {"Bearer " + srv.authToken},
|
||||
}
|
||||
ctx := context.Background()
|
||||
ctx = metadata.NewIncomingContext(ctx, ctxMD)
|
||||
_, err = srv.JWTInterceptor()(ctx, "xyz", unaryInfo, unaryHandler)
|
||||
_, err = srv.AuthTokenInterceptor()(ctx, "xyz", unaryInfo, unaryHandler)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Next up, we make the same request but reinitialize the server and we should still
|
||||
// pass with the same auth token.
|
||||
srv = &Server{}
|
||||
_, err = srv.initializeAuthToken(walletDir)
|
||||
srv = &Server{
|
||||
authTokenPath: authTokenPath,
|
||||
}
|
||||
err = srv.initializeAuthToken()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, true, len(srv.jwtSecret) > 0)
|
||||
_, err = srv.JWTInterceptor()(ctx, "xyz", unaryInfo, unaryHandler)
|
||||
_, err = srv.AuthTokenInterceptor()(ctx, "xyz", unaryInfo, unaryHandler)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestServer_RefreshJWTSecretOnFileChange(t *testing.T) {
|
||||
func TestServer_RefreshAuthTokenOnFileChange(t *testing.T) {
|
||||
// Initializing for the first time, there is no auth token file in
|
||||
// the wallet directory, so we generate a jwt token and secret from scratch.
|
||||
srv := &Server{}
|
||||
walletDir := setupWalletDir(t)
|
||||
_, err := srv.initializeAuthToken(walletDir)
|
||||
require.NoError(t, err)
|
||||
currentSecret := srv.jwtSecret
|
||||
require.Equal(t, true, len(currentSecret) > 0)
|
||||
authTokenPath := filepath.Join(walletDir, api.AuthTokenFileName)
|
||||
srv := &Server{
|
||||
authTokenPath: authTokenPath,
|
||||
}
|
||||
|
||||
authTokenPath := filepath.Join(walletDir, AuthTokenFileName)
|
||||
err := srv.initializeAuthToken()
|
||||
require.NoError(t, err)
|
||||
currentToken := srv.authToken
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
go srv.refreshAuthTokenFromFileChanges(ctx, authTokenPath)
|
||||
go srv.refreshAuthTokenFromFileChanges(ctx, srv.authTokenPath)
|
||||
|
||||
// Wait for service to be ready.
|
||||
time.Sleep(time.Millisecond * 250)
|
||||
|
||||
// Update the auth token file with a new secret.
|
||||
require.NoError(t, CreateAuthToken(walletDir, "localhost:7500"))
|
||||
require.NoError(t, CreateAuthToken(srv.authTokenPath, "localhost:7500"))
|
||||
|
||||
// The service should have picked up the file change and set the jwt secret to the new one.
|
||||
time.Sleep(time.Millisecond * 500)
|
||||
newSecret := srv.jwtSecret
|
||||
require.Equal(t, true, len(newSecret) > 0)
|
||||
require.Equal(t, true, !bytes.Equal(currentSecret, newSecret))
|
||||
err = os.Remove(AuthTokenFileName)
|
||||
newToken := srv.authToken
|
||||
require.Equal(t, true, currentToken != newToken)
|
||||
err = os.Remove(srv.authTokenPath)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
// TODO: remove this test when legacy files are removed
|
||||
func TestServer_LegacyTokensStillWork(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
// Initializing for the first time, there is no auth token file in
|
||||
// the wallet directory, so we generate a jwt token and secret from scratch.
|
||||
walletDir := setupWalletDir(t)
|
||||
authTokenPath := filepath.Join(walletDir, api.AuthTokenFileName)
|
||||
|
||||
bytesBuf := new(bytes.Buffer)
|
||||
_, err := bytesBuf.WriteString("b5bbbaf533b625a93741978857f13d7adeca58445a1fb00ecf3373420b92776c")
|
||||
require.NoError(t, err)
|
||||
_, err = bytesBuf.WriteString("\n")
|
||||
require.NoError(t, err)
|
||||
_, err = bytesBuf.WriteString("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.MxwOozSH-TLbW_XKepjyYDHm2IT8Ki0tD3AHuajfNMg")
|
||||
require.NoError(t, err)
|
||||
_, err = bytesBuf.WriteString("\n")
|
||||
require.NoError(t, err)
|
||||
err = file.MkdirAll(walletDir)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = file.WriteFile(authTokenPath, bytesBuf.Bytes())
|
||||
require.NoError(t, err)
|
||||
|
||||
srv := &Server{
|
||||
authTokenPath: authTokenPath,
|
||||
}
|
||||
|
||||
err = srv.initializeAuthToken()
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, hexutil.Encode(srv.jwtSecret), "0xb5bbbaf533b625a93741978857f13d7adeca58445a1fb00ecf3373420b92776c")
|
||||
require.Equal(t, srv.authToken, "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.MxwOozSH-TLbW_XKepjyYDHm2IT8Ki0tD3AHuajfNMg")
|
||||
|
||||
f, err := os.Open(filepath.Clean(srv.authTokenPath))
|
||||
require.NoError(t, err)
|
||||
|
||||
scanner := bufio.NewScanner(f)
|
||||
var lines []string
|
||||
|
||||
// Scan the file and collect lines, excluding empty lines
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
if strings.TrimSpace(line) != "" {
|
||||
lines = append(lines, line)
|
||||
}
|
||||
}
|
||||
require.Equal(t, len(lines), 2)
|
||||
require.LogsContain(t, hook, "Auth token does not follow our standards and should be regenerated")
|
||||
// Check for scanning errors
|
||||
err = scanner.Err()
|
||||
require.NoError(t, err)
|
||||
err = f.Close()
|
||||
require.NoError(t, err)
|
||||
|
||||
err = os.Remove(srv.authTokenPath)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
// TODO: remove this test when legacy files are removed
|
||||
func TestServer_LegacyTokensBadSecret(t *testing.T) {
|
||||
// Initializing for the first time, there is no auth token file in
|
||||
// the wallet directory, so we generate a jwt token and secret from scratch.
|
||||
walletDir := setupWalletDir(t)
|
||||
authTokenPath := filepath.Join(walletDir, api.AuthTokenFileName)
|
||||
|
||||
bytesBuf := new(bytes.Buffer)
|
||||
_, err := bytesBuf.WriteString("----------------")
|
||||
require.NoError(t, err)
|
||||
_, err = bytesBuf.WriteString("\n")
|
||||
require.NoError(t, err)
|
||||
_, err = bytesBuf.WriteString("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.MxwOozSH-TLbW_XKepjyYDHm2IT8Ki0tD3AHuajfNMg")
|
||||
require.NoError(t, err)
|
||||
_, err = bytesBuf.WriteString("\n")
|
||||
require.NoError(t, err)
|
||||
err = file.MkdirAll(walletDir)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = file.WriteFile(authTokenPath, bytesBuf.Bytes())
|
||||
require.NoError(t, err)
|
||||
|
||||
srv := &Server{
|
||||
authTokenPath: authTokenPath,
|
||||
}
|
||||
|
||||
err = srv.initializeAuthToken()
|
||||
require.ErrorContains(t, "could not decode JWT secret", err)
|
||||
}
|
||||
|
||||
func Test_initializeAuthToken(t *testing.T) {
|
||||
// Initializing for the first time, there is no auth token file in
|
||||
// the wallet directory, so we generate a jwt token and secret from scratch.
|
||||
srv := &Server{}
|
||||
walletDir := setupWalletDir(t)
|
||||
token, err := srv.initializeAuthToken(walletDir)
|
||||
authTokenPath := filepath.Join(walletDir, api.AuthTokenFileName)
|
||||
srv := &Server{
|
||||
authTokenPath: authTokenPath,
|
||||
}
|
||||
err := srv.initializeAuthToken()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, true, len(srv.jwtSecret) > 0)
|
||||
|
||||
// Initializing second time, we generate something from the initial file.
|
||||
srv2 := &Server{}
|
||||
token2, err := srv2.initializeAuthToken(walletDir)
|
||||
srv2 := &Server{
|
||||
authTokenPath: authTokenPath,
|
||||
}
|
||||
err = srv2.initializeAuthToken()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, true, bytes.Equal(srv.jwtSecret, srv2.jwtSecret))
|
||||
require.Equal(t, token, token2)
|
||||
require.Equal(t, srv.authToken, srv2.authToken)
|
||||
|
||||
// Deleting the auth token and re-initializing means we create a jwt token
|
||||
// and secret from scratch again.
|
||||
srv3 := &Server{}
|
||||
walletDir = setupWalletDir(t)
|
||||
token3, err := srv3.initializeAuthToken(walletDir)
|
||||
authTokenPath = filepath.Join(walletDir, api.AuthTokenFileName)
|
||||
srv3 := &Server{
|
||||
authTokenPath: authTokenPath,
|
||||
}
|
||||
|
||||
err = srv3.initializeAuthToken()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, true, len(srv.jwtSecret) > 0)
|
||||
require.NotEqual(t, token, token3)
|
||||
require.NotEqual(t, srv.authToken, srv3.authToken)
|
||||
}
|
||||
|
||||
// "createTokenString" now uses jwt.RegisteredClaims instead of jwt.StandardClaims (deprecated),
|
||||
|
||||
@@ -2,7 +2,6 @@ package rpc
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/io/file"
|
||||
@@ -20,8 +19,7 @@ func (s *Server) Initialize(w http.ResponseWriter, r *http.Request) {
|
||||
httputil.HandleError(w, errors.Wrap(err, "Could not check if wallet exists").Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
authTokenPath := filepath.Join(s.walletDir, AuthTokenFileName)
|
||||
exists, err := file.Exists(authTokenPath, file.Regular)
|
||||
exists, err := file.Exists(s.authTokenPath, file.Regular)
|
||||
if err != nil {
|
||||
httputil.HandleError(w, errors.Wrap(err, "Could not check if auth token exists").Error(), http.StatusInternalServerError)
|
||||
return
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/api"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/v5/validator/accounts"
|
||||
"github.com/prysmaticlabs/prysm/v5/validator/keymanager"
|
||||
@@ -19,7 +20,7 @@ func TestInitialize(t *testing.T) {
|
||||
localWalletDir := setupWalletDir(t)
|
||||
|
||||
// Step 2: Optionally create a temporary 'auth-token' file
|
||||
authTokenPath := filepath.Join(localWalletDir, AuthTokenFileName)
|
||||
authTokenPath := filepath.Join(localWalletDir, api.AuthTokenFileName)
|
||||
_, err := os.Create(authTokenPath)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -34,7 +35,7 @@ func TestInitialize(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
_, err = acc.WalletCreate(context.Background())
|
||||
require.NoError(t, err)
|
||||
server := &Server{walletDir: localWalletDir}
|
||||
server := &Server{walletDir: localWalletDir, authTokenPath: authTokenPath}
|
||||
|
||||
// Step 4: Create an HTTP request and response recorder
|
||||
req := httptest.NewRequest(http.MethodGet, "/initialize", nil)
|
||||
@@ -43,6 +44,8 @@ func TestInitialize(t *testing.T) {
|
||||
// Step 5: Call the Initialize function
|
||||
server.Initialize(w, req)
|
||||
|
||||
require.Equal(t, w.Code, http.StatusOK)
|
||||
|
||||
// Step 6: Assert expectations
|
||||
result := w.Result()
|
||||
defer func() {
|
||||
|
||||
@@ -2,11 +2,9 @@ package rpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
"github.com/prysmaticlabs/prysm/v5/api"
|
||||
"github.com/sirupsen/logrus"
|
||||
"google.golang.org/grpc"
|
||||
@@ -15,8 +13,8 @@ import (
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// JWTInterceptor is a gRPC unary interceptor to authorize incoming requests.
|
||||
func (s *Server) JWTInterceptor() grpc.UnaryServerInterceptor {
|
||||
// AuthTokenInterceptor is a gRPC unary interceptor to authorize incoming requests.
|
||||
func (s *Server) AuthTokenInterceptor() grpc.UnaryServerInterceptor {
|
||||
return func(
|
||||
ctx context.Context,
|
||||
req interface{},
|
||||
@@ -35,8 +33,8 @@ func (s *Server) JWTInterceptor() grpc.UnaryServerInterceptor {
|
||||
}
|
||||
}
|
||||
|
||||
// JwtHttpInterceptor is an HTTP handler to authorize a route.
|
||||
func (s *Server) JwtHttpInterceptor(next http.Handler) http.Handler {
|
||||
// AuthTokenHandler is an HTTP handler to authorize a route.
|
||||
func (s *Server) AuthTokenHandler(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// if it's not initialize or has a web prefix
|
||||
if strings.Contains(r.URL.Path, api.WebApiUrlPrefix) || strings.Contains(r.URL.Path, api.KeymanagerApiPrefix) {
|
||||
@@ -53,9 +51,8 @@ func (s *Server) JwtHttpInterceptor(next http.Handler) http.Handler {
|
||||
}
|
||||
|
||||
token := tokenParts[1]
|
||||
_, err := jwt.Parse(token, s.validateJWT)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Errorf("forbidden: could not parse JWT token: %v", err).Error(), http.StatusForbidden)
|
||||
if strings.TrimSpace(token) != s.authToken || strings.TrimSpace(s.authToken) == "" {
|
||||
http.Error(w, "Forbidden: token value is invalid", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -78,16 +75,8 @@ func (s *Server) authorize(ctx context.Context) error {
|
||||
return status.Error(codes.Unauthenticated, "Invalid auth header, needs Bearer {token}")
|
||||
}
|
||||
token := strings.Split(authHeader[0], "Bearer ")[1]
|
||||
_, err := jwt.Parse(token, s.validateJWT)
|
||||
if err != nil {
|
||||
return status.Errorf(codes.Unauthenticated, "Could not parse JWT token: %v", err)
|
||||
if strings.TrimSpace(token) != s.authToken || strings.TrimSpace(s.authToken) == "" {
|
||||
return status.Errorf(codes.Unauthenticated, "Forbidden: token value is invalid")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) validateJWT(token *jwt.Token) (interface{}, error) {
|
||||
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
|
||||
return nil, fmt.Errorf("unexpected JWT signing method: %v", token.Header["alg"])
|
||||
}
|
||||
return s.jwtSecret, nil
|
||||
}
|
||||
|
||||
@@ -6,18 +6,18 @@ import (
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
"github.com/prysmaticlabs/prysm/v5/api"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/metadata"
|
||||
)
|
||||
|
||||
func TestServer_JWTInterceptor_Verify(t *testing.T) {
|
||||
func TestServer_AuthTokenInterceptor_Verify(t *testing.T) {
|
||||
token := "cool-token"
|
||||
s := Server{
|
||||
jwtSecret: []byte("testKey"),
|
||||
authToken: token,
|
||||
}
|
||||
interceptor := s.JWTInterceptor()
|
||||
interceptor := s.AuthTokenInterceptor()
|
||||
|
||||
unaryInfo := &grpc.UnaryServerInfo{
|
||||
FullMethod: "Proto.CreateWallet",
|
||||
@@ -25,22 +25,20 @@ func TestServer_JWTInterceptor_Verify(t *testing.T) {
|
||||
unaryHandler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return nil, nil
|
||||
}
|
||||
token, err := createTokenString(s.jwtSecret)
|
||||
require.NoError(t, err)
|
||||
ctxMD := map[string][]string{
|
||||
"authorization": {"Bearer " + token},
|
||||
}
|
||||
ctx := context.Background()
|
||||
ctx = metadata.NewIncomingContext(ctx, ctxMD)
|
||||
_, err = interceptor(ctx, "xyz", unaryInfo, unaryHandler)
|
||||
_, err := interceptor(ctx, "xyz", unaryInfo, unaryHandler)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestServer_JWTInterceptor_BadToken(t *testing.T) {
|
||||
func TestServer_AuthTokenInterceptor_BadToken(t *testing.T) {
|
||||
s := Server{
|
||||
jwtSecret: []byte("testKey"),
|
||||
authToken: "cool-token",
|
||||
}
|
||||
interceptor := s.JWTInterceptor()
|
||||
interceptor := s.AuthTokenInterceptor()
|
||||
|
||||
unaryInfo := &grpc.UnaryServerInfo{
|
||||
FullMethod: "Proto.CreateWallet",
|
||||
@@ -49,111 +47,65 @@ func TestServer_JWTInterceptor_BadToken(t *testing.T) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
badServer := Server{
|
||||
jwtSecret: []byte("badTestKey"),
|
||||
}
|
||||
token, err := createTokenString(badServer.jwtSecret)
|
||||
require.NoError(t, err)
|
||||
ctxMD := map[string][]string{
|
||||
"authorization": {"Bearer " + token},
|
||||
"authorization": {"Bearer bad-token"},
|
||||
}
|
||||
ctx := context.Background()
|
||||
ctx = metadata.NewIncomingContext(ctx, ctxMD)
|
||||
_, err = interceptor(ctx, "xyz", unaryInfo, unaryHandler)
|
||||
require.ErrorContains(t, "signature is invalid", err)
|
||||
_, err := interceptor(ctx, "xyz", unaryInfo, unaryHandler)
|
||||
require.ErrorContains(t, "token value is invalid", err)
|
||||
}
|
||||
|
||||
func TestServer_JWTInterceptor_InvalidSigningType(t *testing.T) {
|
||||
ss := &Server{jwtSecret: make([]byte, 32)}
|
||||
// Use a different signing type than the expected, HMAC.
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodRS256, jwt.RegisteredClaims{})
|
||||
_, err := ss.validateJWT(token)
|
||||
require.ErrorContains(t, "unexpected JWT signing method", err)
|
||||
}
|
||||
func TestServer_AuthTokenHandler(t *testing.T) {
|
||||
token := "cool-token"
|
||||
|
||||
func TestServer_JwtHttpInterceptor(t *testing.T) {
|
||||
jwtKey, err := createRandomJWTSecret()
|
||||
require.NoError(t, err)
|
||||
|
||||
s := &Server{jwtSecret: jwtKey}
|
||||
testHandler := s.JwtHttpInterceptor(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
s := &Server{authToken: token}
|
||||
testHandler := s.AuthTokenHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// Your test handler logic here
|
||||
w.WriteHeader(http.StatusOK)
|
||||
_, err := w.Write([]byte("Test Response"))
|
||||
require.NoError(t, err)
|
||||
}))
|
||||
t.Run("no jwt was sent", func(t *testing.T) {
|
||||
t.Run("no auth token was sent", func(t *testing.T) {
|
||||
rr := httptest.NewRecorder()
|
||||
req, err := http.NewRequest(http.MethodGet, "/eth/v1/keystores", nil)
|
||||
req, err := http.NewRequest(http.MethodGet, "/eth/v1/keystores", http.NoBody)
|
||||
require.NoError(t, err)
|
||||
testHandler.ServeHTTP(rr, req)
|
||||
require.Equal(t, http.StatusUnauthorized, rr.Code)
|
||||
})
|
||||
t.Run("wrong jwt was sent", func(t *testing.T) {
|
||||
t.Run("wrong auth token was sent", func(t *testing.T) {
|
||||
rr := httptest.NewRecorder()
|
||||
req, err := http.NewRequest(http.MethodGet, "/eth/v1/keystores", nil)
|
||||
req, err := http.NewRequest(http.MethodGet, "/eth/v1/keystores", http.NoBody)
|
||||
require.NoError(t, err)
|
||||
req.Header.Set("Authorization", "Bearer YOUR_JWT_TOKEN") // Replace with a valid JWT token
|
||||
testHandler.ServeHTTP(rr, req)
|
||||
require.Equal(t, http.StatusForbidden, rr.Code)
|
||||
})
|
||||
t.Run("jwt was sent", func(t *testing.T) {
|
||||
t.Run("good auth token was sent", func(t *testing.T) {
|
||||
rr := httptest.NewRecorder()
|
||||
req, err := http.NewRequest(http.MethodGet, "/eth/v1/keystores", nil)
|
||||
require.NoError(t, err)
|
||||
token, err := createTokenString(jwtKey)
|
||||
req, err := http.NewRequest(http.MethodGet, "/eth/v1/keystores", http.NoBody)
|
||||
require.NoError(t, err)
|
||||
req.Header.Set("Authorization", "Bearer "+token) // Replace with a valid JWT token
|
||||
testHandler.ServeHTTP(rr, req)
|
||||
require.Equal(t, http.StatusOK, rr.Code)
|
||||
})
|
||||
t.Run("wrong jwt format was sent", func(t *testing.T) {
|
||||
t.Run("web endpoint needs auth token", func(t *testing.T) {
|
||||
rr := httptest.NewRecorder()
|
||||
req, err := http.NewRequest(http.MethodGet, "/eth/v1/keystores", nil)
|
||||
require.NoError(t, err)
|
||||
token, err := createTokenString(jwtKey)
|
||||
require.NoError(t, err)
|
||||
req.Header.Set("Authorization", "Bearer"+token) // no space was added // Replace with a valid JWT token
|
||||
testHandler.ServeHTTP(rr, req)
|
||||
require.Equal(t, http.StatusBadRequest, rr.Code)
|
||||
})
|
||||
t.Run("wrong jwt no bearer format was sent", func(t *testing.T) {
|
||||
rr := httptest.NewRecorder()
|
||||
req, err := http.NewRequest(http.MethodGet, "/eth/v1/keystores", nil)
|
||||
require.NoError(t, err)
|
||||
token, err := createTokenString(jwtKey)
|
||||
require.NoError(t, err)
|
||||
req.Header.Set("Authorization", token) // Replace with a valid JWT token
|
||||
testHandler.ServeHTTP(rr, req)
|
||||
require.Equal(t, http.StatusBadRequest, rr.Code)
|
||||
})
|
||||
t.Run("broken jwt token format was sent", func(t *testing.T) {
|
||||
rr := httptest.NewRecorder()
|
||||
req, err := http.NewRequest(http.MethodGet, "/eth/v1/keystores", nil)
|
||||
require.NoError(t, err)
|
||||
token, err := createTokenString(jwtKey)
|
||||
require.NoError(t, err)
|
||||
req.Header.Set("Authorization", "Bearer "+token[0:2]+" "+token[2:]) // Replace with a valid JWT token
|
||||
testHandler.ServeHTTP(rr, req)
|
||||
require.Equal(t, http.StatusForbidden, rr.Code)
|
||||
})
|
||||
t.Run("web endpoint needs jwt token", func(t *testing.T) {
|
||||
rr := httptest.NewRecorder()
|
||||
req, err := http.NewRequest(http.MethodGet, "/api/v2/validator/beacon/status", nil)
|
||||
req, err := http.NewRequest(http.MethodGet, "/api/v2/validator/beacon/status", http.NoBody)
|
||||
require.NoError(t, err)
|
||||
testHandler.ServeHTTP(rr, req)
|
||||
require.Equal(t, http.StatusUnauthorized, rr.Code)
|
||||
})
|
||||
t.Run("initialize does not need jwt", func(t *testing.T) {
|
||||
t.Run("initialize does not need auth", func(t *testing.T) {
|
||||
rr := httptest.NewRecorder()
|
||||
req, err := http.NewRequest(http.MethodGet, api.WebUrlPrefix+"initialize", nil)
|
||||
req, err := http.NewRequest(http.MethodGet, api.WebUrlPrefix+"initialize", http.NoBody)
|
||||
require.NoError(t, err)
|
||||
testHandler.ServeHTTP(rr, req)
|
||||
require.Equal(t, http.StatusOK, rr.Code)
|
||||
})
|
||||
t.Run("health does not need jwt", func(t *testing.T) {
|
||||
t.Run("health does not need auth", func(t *testing.T) {
|
||||
rr := httptest.NewRecorder()
|
||||
req, err := http.NewRequest(http.MethodGet, api.WebUrlPrefix+"health/logs", nil)
|
||||
req, err := http.NewRequest(http.MethodGet, api.WebUrlPrefix+"health/logs", http.NoBody)
|
||||
require.NoError(t, err)
|
||||
testHandler.ServeHTTP(rr, req)
|
||||
require.Equal(t, http.StatusOK, rr.Code)
|
||||
|
||||
@@ -47,6 +47,7 @@ type Config struct {
|
||||
CertFlag string
|
||||
KeyFlag string
|
||||
ValDB db.Database
|
||||
AuthTokenPath string
|
||||
WalletDir string
|
||||
ValidatorService *client.ValidatorService
|
||||
SyncChecker client.SyncChecker
|
||||
@@ -87,6 +88,8 @@ type Server struct {
|
||||
validatorService *client.ValidatorService
|
||||
syncChecker client.SyncChecker
|
||||
genesisFetcher client.GenesisFetcher
|
||||
authTokenPath string
|
||||
authToken string
|
||||
walletDir string
|
||||
wallet *wallet.Wallet
|
||||
walletInitializedFeed *event.Feed
|
||||
@@ -123,6 +126,7 @@ func NewServer(ctx context.Context, cfg *Config) *Server {
|
||||
validatorService: cfg.ValidatorService,
|
||||
syncChecker: cfg.SyncChecker,
|
||||
genesisFetcher: cfg.GenesisFetcher,
|
||||
authTokenPath: cfg.AuthTokenPath,
|
||||
walletDir: cfg.WalletDir,
|
||||
walletInitializedFeed: cfg.WalletInitializedFeed,
|
||||
walletInitialized: cfg.Wallet != nil,
|
||||
@@ -136,6 +140,19 @@ func NewServer(ctx context.Context, cfg *Config) *Server {
|
||||
beaconApiEndpoint: cfg.BeaconApiEndpoint,
|
||||
router: cfg.Router,
|
||||
}
|
||||
|
||||
if server.authTokenPath == "" && server.walletDir != "" {
|
||||
server.authTokenPath = filepath.Join(server.walletDir, api.AuthTokenFileName)
|
||||
}
|
||||
|
||||
if server.authTokenPath != "" {
|
||||
if err := server.initializeAuthToken(); err != nil {
|
||||
log.WithError(err).Error("Could not initialize web auth token")
|
||||
}
|
||||
validatorWebAddr := fmt.Sprintf("%s:%d", server.validatorGatewayHost, server.validatorGatewayPort)
|
||||
logValidatorWebAuth(validatorWebAddr, server.authToken, server.authTokenPath)
|
||||
go server.refreshAuthTokenFromFileChanges(server.ctx, server.authTokenPath)
|
||||
}
|
||||
// immediately register routes to override any catchalls
|
||||
if err := server.InitializeRoutes(); err != nil {
|
||||
log.WithError(err).Fatal("Could not initialize routes")
|
||||
@@ -146,7 +163,7 @@ func NewServer(ctx context.Context, cfg *Config) *Server {
|
||||
// Start the gRPC server.
|
||||
func (s *Server) Start() {
|
||||
// Setup the gRPC server options and TLS configuration.
|
||||
address := fmt.Sprintf("%s:%s", s.host, s.port)
|
||||
address := net.JoinHostPort(s.host, s.port)
|
||||
lis, err := net.Listen("tcp", address)
|
||||
if err != nil {
|
||||
log.WithError(err).Errorf("Could not listen to port in Start() %s", address)
|
||||
@@ -163,7 +180,7 @@ func (s *Server) Start() {
|
||||
),
|
||||
grpcprometheus.UnaryServerInterceptor,
|
||||
grpcopentracing.UnaryServerInterceptor(),
|
||||
s.JWTInterceptor(),
|
||||
s.AuthTokenInterceptor(),
|
||||
)),
|
||||
}
|
||||
grpcprometheus.EnableHandlingTimeHistogram()
|
||||
@@ -198,17 +215,6 @@ func (s *Server) Start() {
|
||||
}()
|
||||
|
||||
log.WithField("address", address).Info("gRPC server listening on address")
|
||||
if s.walletDir != "" {
|
||||
token, err := s.initializeAuthToken(s.walletDir)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Could not initialize web auth token")
|
||||
return
|
||||
}
|
||||
validatorWebAddr := fmt.Sprintf("%s:%d", s.validatorGatewayHost, s.validatorGatewayPort)
|
||||
authTokenPath := filepath.Join(s.walletDir, AuthTokenFileName)
|
||||
logValidatorWebAuth(validatorWebAddr, token, authTokenPath)
|
||||
go s.refreshAuthTokenFromFileChanges(s.ctx, authTokenPath)
|
||||
}
|
||||
}
|
||||
|
||||
// InitializeRoutes initializes pure HTTP REST endpoints for the validator client.
|
||||
@@ -218,7 +224,7 @@ func (s *Server) InitializeRoutes() error {
|
||||
return errors.New("no router found on server")
|
||||
}
|
||||
// Adding Auth Interceptor for the routes below
|
||||
s.router.Use(s.JwtHttpInterceptor)
|
||||
s.router.Use(s.AuthTokenHandler)
|
||||
// Register all services, HandleFunc calls, etc.
|
||||
// ...
|
||||
s.router.HandleFunc("/eth/v1/keystores", s.ListKeystores).Methods(http.MethodGet)
|
||||
|
||||
Reference in New Issue
Block a user