Compare commits

...

24 Commits

Author SHA1 Message Date
Kasey Kirkham
8d6c20d7ea fix e2e tests; state+block readers->[]byte 2022-02-04 22:57:03 -06:00
terence tsao
650615ba35 Add fork version 2022-02-04 15:44:12 -08:00
Kasey Kirkham
766168d4c0 WIP fixing e2e test 2022-02-04 16:33:12 -06:00
Kasey Kirkham
0cfb0ab228 remove old weak subjectivity checkpoint api 2022-02-03 12:27:39 -06:00
Kasey Kirkham
728dcefcf7 clean up integrated checkpoint downloader 2022-02-03 11:02:35 -06:00
Kasey Kirkham
6198741fa9 initializer using API instead of files 2022-02-02 09:23:40 -06:00
Kasey Kirkham
01f7bb04ba WIP new weak_subjectivity api 2022-02-01 21:15:44 -06:00
Kasey Kirkham
e190a89ad0 optimized method for computing ws checkpoint
due to the nuances of skip slots, it is more accurate to
find the highest block in the previous epoch and then fetch
the state it refers to, which should be the first state in the
subsequent epoch.
2022-01-31 11:48:23 -06:00
Kasey Kirkham
f5d1300a17 direct dl checkpoint from another node at startup
w/ flag:
--weak-subjectivity-checkpoint flag
2022-01-27 22:51:38 -06:00
Kasey Kirkham
7b29900dc1 rework cli tools to compute ws checkpoint locally 2022-01-27 14:08:10 -06:00
Kasey Kirkham
6ea1763391 more defensive checks around genesis data w/ wss 2022-01-24 17:26:57 -06:00
Kasey Kirkham
296202b39b add minimum slot and sync source data to stategen
the goal is to allow stategen to make better decisions about when
genesis state and block should be present in the db, and how far back
it is able to scan.
2022-01-24 13:18:56 -06:00
Kasey Kirkham
c2307efde9 trying to clear up checkpoint vs origin naming 2022-01-21 17:47:37 -06:00
Kasey Kirkham
98b117ad99 end-to-end test passing 2022-01-18 14:51:22 -06:00
Kasey Kirkham
22ce777504 WIP end-to-end test for checkpoint sync 2022-01-14 17:38:01 -06:00
Kasey Kirkham
178e69c6c4 ensuring exported methods have doc comments 2021-12-14 16:42:25 -06:00
Kasey Kirkham
47a86ce778 cli support for providing state+block 2021-12-14 16:10:20 -06:00
Kasey Kirkham
7c3b774e55 appease deepsource 2021-12-13 12:55:20 -06:00
Kasey Kirkham
966361c3f3 remove unnecessary Sprintfs 2021-12-13 12:43:30 -06:00
Kasey Kirkham
7e45a1353f appease deepsource 2021-12-13 12:12:25 -06:00
Kasey Kirkham
68c6f7b755 remove shameful TODOs and comments 2021-12-13 09:43:06 -06:00
Kasey Kirkham
bad14defc7 gazelle 2021-12-13 09:32:22 -06:00
Kasey Kirkham
f46270524f dialing down permissions 2021-12-13 09:30:59 -06:00
kasey
00593b5e30 support fetching origin sync data from a beacon node 2021-12-13 09:00:51 -06:00
85 changed files with 4968 additions and 1279 deletions

View File

@@ -0,0 +1,24 @@
load("@prysm//tools/go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"checkpoint.go",
"client.go",
],
importpath = "github.com/prysmaticlabs/prysm/api/client/openapi",
visibility = ["//visibility:public"],
deps = [
"//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/rpc/apimiddleware:go_default_library",
"//config/params:go_default_library",
"//encoding/bytesutil:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//proto/sniff:go_default_library",
"//time/slots:go_default_library",
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
"@com_github_pkg_errors//:go_default_library",
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
],
)

View File

@@ -0,0 +1,228 @@
package openapi
import (
"context"
"fmt"
"github.com/pkg/errors"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/config/params"
"github.com/prysmaticlabs/prysm/proto/sniff"
"github.com/prysmaticlabs/prysm/time/slots"
log "github.com/sirupsen/logrus"
"io"
)
var ErrMismatchedLatestBlockRoot = errors.New("block root in state does not match value from api")
type WeakSubjectivityData struct {
BlockRoot [32]byte
StateRoot [32]byte
Epoch types.Epoch
}
type OriginData struct {
WeakSubjectivity *WeakSubjectivityData
StateBytes []byte
blockBytes []byte
}
// this method downloads the head state, which can be used to find the correct chain config
// and use prysm's helper methods to compute the latest weak subjectivity epoch.
func getWeakSubjectivityEpochFromHead(ctx context.Context, client *Client) (types.Epoch, error) {
headReader, err := client.GetStateById(StateIdHead)
headBytes, err := io.ReadAll(headReader)
if err != nil {
return 0, errors.Wrap(err, "failed to read response body for get head state api call")
}
headState, err := sniff.BeaconState(headBytes)
if err != nil {
return 0, errors.Wrap(err, "error unmarshaling state to correct version")
}
cf, err := sniff.ConfigForkForState(headBytes)
if err != nil {
return 0, errors.Wrap(err, "error detecting chain config for beacon state")
}
log.Printf("detected supported config in remote head state, name=%s, fork=%s", cf.ConfigName.String(), cf.Fork)
// LatestWeakSubjectivityEpoch uses package-level vars from the params package, so we need to override it
params.OverrideBeaconConfig(cf.Config)
epoch, err := helpers.LatestWeakSubjectivityEpoch(ctx, headState)
if err != nil {
return 0, errors.Wrap(err, "error computing the weak subjectivity epoch from head state")
}
log.Printf("(computed client-side) weak subjectivity epoch = %d", epoch)
return epoch, nil
}
// for older endpoints or clients that do not support the weak_subjectivity api method (only prysm at release time)
// we gather the necessary data for a checkpoint sync by:
// - inspecting the remote server's head state and computing the weak subjectivity epoch locally
// - requesting the state at the first slot of the epoch
// - using hash_tree_root(state.latest_block_header) to compute the block the state integrates
// - requesting that block by its root
func downloadBackwardsCompatible(ctx context.Context, client *Client) (*OriginData, error) {
log.Print("falling back to generic checkpoint derivation, weak_subjectivity API not supported by server")
epoch, err := getWeakSubjectivityEpochFromHead(ctx, client)
if err != nil {
return nil, errors.Wrap(err, "error computing weak subjectivity epoch via head state inspection")
}
// use first slot of the epoch for the state slot
slot, err := slots.EpochStart(epoch)
if err != nil {
return nil, errors.Wrap(err, fmt.Sprintf("Error computing first slot of epoch=%d", epoch))
}
log.Printf("requesting checkpoint state at slot %d", slot)
// get the state at the first slot of the epoch
sReader, err := client.GetStateBySlot(uint64(slot))
if err != nil {
return nil, errors.Wrap(err, fmt.Sprintf("failed to request state by slot from api, slot=%d", slot))
}
stateBytes, err := io.ReadAll(sReader)
if err != nil {
return nil, errors.Wrap(err, "failed to read response body for get checkpoint state api call")
}
// ConfigFork is used to unmarshal the BeaconState so we can read the block root in latest_block_header
cf, err := sniff.ConfigForkForState(stateBytes)
if err != nil {
return nil, errors.Wrap(err, "error detecting chain config for beacon state")
}
log.Printf("detected supported config in checkpoint state, name=%s, fork=%s", cf.ConfigName.String(), cf.Fork)
state, err := sniff.BeaconStateForConfigFork(stateBytes, cf)
if err != nil {
return nil, errors.Wrap(err, "error using detected config fork to unmarshal state bytes")
}
// compute state and block roots
stateRoot, err := state.HashTreeRoot(ctx)
if err != nil {
return nil, errors.Wrap(err, "error computing hash_tree_root of state")
}
blockRoot, err := state.LatestBlockHeader().HashTreeRoot()
if err != nil {
return nil, errors.Wrap(err, "error computing hash_tree_root of latest_block_header")
}
log.Printf("found hash_tree_root(state.latest_block_header)=%#x", blockRoot)
bReader, err := client.GetBlockByRoot(fmt.Sprintf("%#x", blockRoot))
if err != nil {
return nil, errors.Wrap(err, fmt.Sprintf("error requesting block by root = %#x", blockRoot))
}
blockBytes, err := io.ReadAll(bReader)
if err != nil {
return nil, errors.Wrap(err, "failed to read response body for get checkpoint block api call")
}
block, err := sniff.BlockForConfigFork(blockBytes, cf)
if err != nil {
return nil, errors.Wrap(err, "unable to unmarshal block to a supported type using the detected fork schedule")
}
realBlockRoot, err := block.Block().HashTreeRoot()
if err != nil {
return nil, errors.Wrap(err, "error computing hash_tree_root of retrieved block")
}
log.Printf("BeaconState slot=%d, Block slot=%d", state.Slot(), block.Block().Slot())
log.Printf("BeaconState htr=%#xd, Block state_root=%#x", stateRoot, block.Block().StateRoot())
log.Printf("BeaconState latest_block_header htr=%#xd, block htr=%#x", blockRoot, realBlockRoot)
return &OriginData{
WeakSubjectivity: &WeakSubjectivityData{
BlockRoot: blockRoot,
StateRoot: stateRoot,
Epoch: epoch,
},
StateBytes: stateBytes,
blockBytes: blockBytes,
}, nil
}
// DownloadOriginData attempts to use the proposed weak_subjectivity beacon node api
// to obtain the weak_subjectivity metadata (epoch, block_root, state_root) needed to sync
// a beacon node from the canonical weak subjectivity checkpoint. As this is a proposed API
// that will only be supported by prysm at first, in the event of a 404 we fallback to using a
// different technique where we first download the head state which can be used to compute the
// weak subjectivity epoch on the client side.
func DownloadOriginData(ctx context.Context, client *Client) (*OriginData, error) {
ws, err := client.GetWeakSubjectivity()
if err != nil {
// a 404 is expected if querying an endpoint that doesn't support the weak subjectivity checkpoint api
if !errors.Is(err, ErrNotFound) {
return nil, errors.Wrap(err, "unexpected API response for prysm-only weak subjectivity checkpoint API")
}
// ok so it's a 404, use the head state method
return downloadBackwardsCompatible(ctx, client)
}
log.Printf("server weak subjectivity checkpoint response - epoch=%d, block_root=%#x, state_root=%#x", ws.Epoch, ws.BlockRoot, ws.StateRoot)
// use first slot of the epoch for the block slot
slot, err := slots.EpochStart(ws.Epoch)
if err != nil {
return nil, errors.Wrap(err, fmt.Sprintf("Error computing first slot of epoch=%d", ws.Epoch))
}
log.Printf("requesting checkpoint state at slot %d", slot)
sReader, err := client.GetStateBySlot(uint64(slot))
if err != nil {
return nil, errors.Wrap(err, fmt.Sprintf("failed to request state by slot from api, slot=%d", slot))
}
stateBytes, err := io.ReadAll(sReader)
if err != nil {
return nil, errors.Wrap(err, "failed to read response body for get checkpoint state api call")
}
cf, err := sniff.ConfigForkForState(stateBytes)
if err != nil {
return nil, errors.Wrap(err, "error detecting chain config for beacon state")
}
log.Printf("detected supported config in checkpoint state, name=%s, fork=%s", cf.ConfigName.String(), cf.Fork)
state, err := sniff.BeaconStateForConfigFork(stateBytes, cf)
if err != nil {
return nil, errors.Wrap(err, "error using detected config fork to unmarshal state bytes")
}
stateRoot, err := state.HashTreeRoot(ctx)
if err != nil {
return nil, errors.Wrap(err, fmt.Sprintf("failed to compute htr for state at slot=%d", slot))
}
blockRoot, err := state.LatestBlockHeader().HashTreeRoot()
if err != nil {
return nil, errors.Wrap(err, "error computing hash_tree_root of latest_block_header")
}
log.Printf("found hash_tree_root(state.latest_block_header)=%#x", blockRoot)
if blockRoot != ws.BlockRoot {
log.Warn("checkpoint block root doesn't match hash_tree_root(state.latest_block_header)")
msg := fmt.Sprintf("api block_root=%#x, hash_tree_root(state.latest_block_header)=%#x", ws.BlockRoot, blockRoot)
return nil, errors.Wrap(ErrMismatchedLatestBlockRoot, msg)
}
log.Printf("hash_tree_root(state.latest_block_header) matches API response, fetching %#x", blockRoot)
bReader, err := client.GetBlockByRoot(fmt.Sprintf("%#x", blockRoot))
if err != nil {
return nil, errors.Wrap(err, fmt.Sprintf("error requesting block by root = %#x", blockRoot))
}
blockBytes, err := io.ReadAll(bReader)
if err != nil {
return nil, errors.Wrap(err, "failed to read response body for get checkpoint block api call")
}
block, err := sniff.BlockForConfigFork(blockBytes, cf)
if err != nil {
return nil, errors.Wrap(err, "unable to unmarshal block to a supported type using the detected fork schedule")
}
realBlockRoot, err := block.Block().HashTreeRoot()
if err != nil {
return nil, errors.Wrap(err, "error computing hash_tree_root of retrieved block")
}
log.Printf("BeaconState slot=%d, Block slot=%d", state.Slot(), block.Block().Slot())
log.Printf("BeaconState htr=%#xd, Block state_root=%#x", stateRoot, block.Block().StateRoot())
log.Printf("BeaconState latest_block_header htr=%#xd, block htr=%#x", blockRoot, realBlockRoot)
return &OriginData{
WeakSubjectivity: ws,
StateBytes: stateBytes,
blockBytes: blockBytes,
}, nil
}

View File

@@ -0,0 +1,403 @@
package openapi
import (
"bytes"
"encoding/json"
"fmt"
"github.com/prysmaticlabs/prysm/beacon-chain/rpc/apimiddleware"
"io"
"io/ioutil"
"net"
"net/http"
"net/url"
"path"
"sort"
"strconv"
"text/template"
"time"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/pkg/errors"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/config/params"
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
log "github.com/sirupsen/logrus"
)
const (
GET_WEAK_SUBJECTIVITY_PATH = "/eth/v1/beacon/weak_subjectivity"
GET_SIGNED_BLOCK_PATH = "/eth/v2/beacon/blocks"
GET_STATE_PATH = "/eth/v2/debug/beacon/states"
GET_FORK_SCHEDULE_PATH = "/eth/v1/config/fork_schedule"
GET_FORK_FOR_STATE = "/eth/v1/beacon/states/{{.StateId}}/fork"
GET_BLOCK_ROOT = "/eth/v1/beacon/blocks/{{.BlockId}}/root"
)
const (
StateIdHead = "head"
)
var ErrNotOK = errors.New("did not receive 2xx response from API")
var ErrNotFound = errors.Wrap(ErrNotOK, "recv 404 NotFound response from API")
// ClientOpt is a functional option for the Client type (http.Client wrapper)
type ClientOpt func(*Client)
// WithTimeout sets the .Timeout attribute of the wrapped http.Client
func WithTimeout(timeout time.Duration) ClientOpt {
return func(c *Client) {
c.c.Timeout = timeout
}
}
// Client provides a collection of helper methods for calling the beacon node OpenAPI endpoints
type Client struct {
c *http.Client
host string
scheme string
}
func (c *Client) urlForPath(methodPath string) *url.URL {
u := &url.URL{
Scheme: c.scheme,
Host: c.host,
}
u.Path = path.Join(u.Path, methodPath)
return u
}
// NewClient constructs a new client with the provided options (ex WithTimeout).
// host is the base host + port used to construct request urls. This value can be
// a URL string, or NewClient will assume an http endpoint if just `host:port` is used.
func NewClient(host string, opts ...ClientOpt) (*Client, error) {
host, err := validHostname(host)
if err != nil {
return nil, err
}
c := &Client{
c: &http.Client{},
scheme: "http",
host: host,
}
for _, o := range opts {
o(c)
}
return c, nil
}
func validHostname(h string) (string, error) {
// try to parse as url (being permissive)
u, err := url.Parse(h)
if err == nil && u.Host != "" {
return u.Host, nil
}
// try to parse as host:port
host, port, err := net.SplitHostPort(h)
if err != nil {
return "", err
}
return fmt.Sprintf("%s:%s", host, port), nil
}
// GetBlockBySlot queries the beacon node API for the SignedBeaconBlockAltair for the given slot
func (c *Client) GetBlockBySlot(slot uint64) (io.Reader, error) {
blockPath := path.Join(GET_SIGNED_BLOCK_PATH, strconv.FormatUint(slot, 10))
u := c.urlForPath(blockPath)
log.Printf("requesting %s", u.String())
req, err := http.NewRequest(http.MethodGet, u.String(), nil)
if err != nil {
return nil, err
}
req.Header.Set("Accept", "application/octet-stream")
r, err := c.c.Do(req)
defer func() {
err = r.Body.Close()
}()
if err != nil {
return nil, err
}
if r.StatusCode != http.StatusOK {
return nil, non200Err(r)
}
b := bytes.NewBuffer(nil)
_, err = io.Copy(b, r.Body)
if err != nil {
return nil, errors.Wrap(err, "error reading http response body from GetBlockBySlot")
}
return b, nil
}
// blockId can be one of:
// - "head" (canonical head in node's view)
// - "genesis"
// - "finalized"
// - <slot>
// - <hex encoded blockRoot with 0x prefix>. -- you could, but should you?
func (c *Client) GetBlockRoot(blockId string) ([32]byte, error) {
var root [32]byte
t := template.Must(template.New("get-block-root").Parse(GET_BLOCK_ROOT))
b := bytes.NewBuffer(nil)
err := t.Execute(b, struct{ BlockId string }{BlockId: blockId})
if err != nil {
return root, errors.Wrap(err, fmt.Sprintf("unable to generate path w/ blockId=%s", blockId))
}
rootPath := b.String()
u := c.urlForPath(rootPath)
log.Printf("requesting %s", u.String())
req, err := http.NewRequest(http.MethodGet, u.String(), nil)
if err != nil {
return root, err
}
r, err := c.c.Do(req)
defer func() {
err = r.Body.Close()
}()
if err != nil {
return root, err
}
if r.StatusCode != http.StatusOK {
return root, non200Err(r)
}
jsonr := &struct{ Data struct{ Root string } }{}
err = json.NewDecoder(r.Body).Decode(jsonr)
if err != nil {
return root, errors.Wrap(err, "error decoding json data from get block root response")
}
rs, err := hexutil.Decode(jsonr.Data.Root)
if err != nil {
return root, errors.Wrap(err, fmt.Sprintf("error decoding hex-encoded value %s", jsonr.Data.Root))
}
return bytesutil.ToBytes32(rs), nil
}
// GetBlockByRoot retrieves a SignedBeaconBlockAltair with the given root via the beacon node API
func (c *Client) GetBlockByRoot(blockHex string) (io.Reader, error) {
blockPath := path.Join(GET_SIGNED_BLOCK_PATH, blockHex)
u := c.urlForPath(blockPath)
log.Printf("requesting %s", u.String())
req, err := http.NewRequest(http.MethodGet, u.String(), nil)
if err != nil {
return nil, err
}
req.Header.Set("Accept", "application/octet-stream")
r, err := c.c.Do(req)
defer func() {
err = r.Body.Close()
}()
if err != nil {
return nil, err
}
if r.StatusCode != http.StatusOK {
return nil, non200Err(r)
}
b := bytes.NewBuffer(nil)
_, err = io.Copy(b, r.Body)
return b, nil
}
// GetStateByRoot retrieves a BeaconStateAltair with the given root via the beacon node API
func (c *Client) GetStateByRoot(stateHex string) (io.Reader, error) {
return c.GetStateById(stateHex)
}
// GetStateBySlot retrieves a BeaconStateAltair at the given slot via the beacon node API
func (c *Client) GetStateBySlot(slot uint64) (io.Reader, error) {
slotStr := strconv.FormatUint(slot, 10)
return c.GetStateById(slotStr)
}
func (c *Client) GetStateById(stateId string) (io.Reader, error) {
statePath := path.Join(GET_STATE_PATH, stateId)
u := c.urlForPath(statePath)
log.Printf("requesting %s", u.String())
req, err := http.NewRequest(http.MethodGet, u.String(), nil)
if err != nil {
return nil, err
}
req.Header.Set("Accept", "application/octet-stream")
r, err := c.c.Do(req)
defer func() {
err = r.Body.Close()
}()
if err != nil {
return nil, err
}
if r.StatusCode != http.StatusOK {
return nil, non200Err(r)
}
b := bytes.NewBuffer(nil)
_, err = io.Copy(b, r.Body)
if err != nil {
return nil, errors.Wrap(err, "error reading http response body from GetStateById")
}
return b, nil
}
func (c *Client) GetForkForState(stateId string) (*ethpb.Fork, error) {
t := template.Must(template.New("get-for-for-state").Parse(GET_FORK_FOR_STATE))
b := bytes.NewBuffer(nil)
err := t.Execute(b, struct{ StateId string }{StateId: stateId})
if err != nil {
return nil, errors.Wrap(err, fmt.Sprintf("unable to generate path w/ stateId=%s", stateId))
}
u := c.urlForPath(b.String())
r, err := c.c.Get(u.String())
defer func() {
err = r.Body.Close()
}()
if err != nil {
return nil, err
}
if r.StatusCode != http.StatusOK {
return nil, non200Err(r)
}
fr := &forkResponse{}
dataWrapper := &struct{ Data *forkResponse }{Data: fr}
err = json.NewDecoder(r.Body).Decode(dataWrapper)
if err != nil {
return nil, errors.Wrap(err, "error decoding json response in GetForkForState")
}
return fr.Fork()
}
type forkResponse struct {
PreviousVersion string `json:"previous_version"`
CurrentVersion string `json:"current_version"`
Epoch string `json:"epoch"`
}
func (f *forkResponse) Fork() (*ethpb.Fork, error) {
epoch, err := strconv.Atoi(f.Epoch)
if err != nil {
return nil, err
}
cSlice, err := hexutil.Decode(f.CurrentVersion)
if err != nil {
return nil, err
}
if len(cSlice) != 4 {
return nil, fmt.Errorf("got %d byte version for CurrentVersion, expected 4 bytes. hex=%s", len(cSlice), f.CurrentVersion)
}
pSlice, err := hexutil.Decode(f.PreviousVersion)
if err != nil {
return nil, err
}
if len(pSlice) != 4 {
return nil, fmt.Errorf("got %d byte version, expected 4 bytes. version hex=%s", len(pSlice), f.PreviousVersion)
}
return &ethpb.Fork{
CurrentVersion: cSlice,
PreviousVersion: pSlice,
Epoch: types.Epoch(epoch),
}, nil
}
type forkScheduleResponse struct {
Data []forkResponse
}
func (fsr *forkScheduleResponse) OrderedForkSchedule() (params.OrderedForkSchedule, error) {
ofs := make(params.OrderedForkSchedule, 0)
for _, d := range fsr.Data {
epoch, err := strconv.Atoi(d.Epoch)
if err != nil {
return nil, err
}
vSlice, err := hexutil.Decode(d.CurrentVersion)
if err != nil {
return nil, err
}
if len(vSlice) != 4 {
return nil, fmt.Errorf("got %d byte version, expected 4 bytes. version hex=%s", len(vSlice), d.CurrentVersion)
}
version := bytesutil.ToBytes4(vSlice)
ofs = append(ofs, params.ForkScheduleEntry{
Version: version,
Epoch: types.Epoch(uint64(epoch)),
})
}
sort.Sort(ofs)
return ofs, nil
}
func (c *Client) GetForkSchedule() (params.OrderedForkSchedule, error) {
u := c.urlForPath(GET_FORK_SCHEDULE_PATH)
log.Printf("requesting %s", u.String())
r, err := c.c.Get(u.String())
defer func() {
err = r.Body.Close()
}()
if err != nil {
return nil, err
}
if r.StatusCode != http.StatusOK {
return nil, non200Err(r)
}
fsr := &forkScheduleResponse{}
err = json.NewDecoder(r.Body).Decode(fsr)
if err != nil {
return nil, err
}
ofs, err := fsr.OrderedForkSchedule()
if err != nil {
return nil, errors.Wrap(err, fmt.Sprintf("problem unmarshaling %s response", GET_FORK_SCHEDULE_PATH))
}
return ofs, nil
}
// GetWeakSubjectivity calls a proposed API endpoint that is unique to prysm
// This api method does the following:
// - computes weak subjectivity epoch
// - finds the highest non-skipped block preceding the epoch
// - returns the htr of the found block and returns this + the value of state_root from the block
func (c *Client) GetWeakSubjectivity() (*WeakSubjectivityData, error) {
u := c.urlForPath(GET_WEAK_SUBJECTIVITY_PATH)
r, err := c.c.Get(u.String())
if err != nil {
return nil, err
}
if r.StatusCode != http.StatusOK {
return nil, non200Err(r)
}
v := &apimiddleware.WeakSubjectivityResponse{}
err = json.NewDecoder(r.Body).Decode(v)
if err != nil {
return nil, err
}
epoch, err := strconv.ParseUint(v.Data.Checkpoint.Epoch, 10, 64)
if err != nil {
return nil, err
}
blockRoot, err := hexutil.Decode(v.Data.Checkpoint.Root)
if err != nil {
return nil, err
}
stateRoot, err := hexutil.Decode(v.Data.StateRoot)
if err != nil {
return nil, err
}
return &WeakSubjectivityData{
Epoch: types.Epoch(epoch),
BlockRoot: bytesutil.ToBytes32(blockRoot),
StateRoot: bytesutil.ToBytes32(stateRoot),
}, nil
}
func non200Err(response *http.Response) error {
bodyBytes, err := ioutil.ReadAll(response.Body)
var body string
if err != nil {
body = "(Unable to read response body.)"
} else {
body = "response body:\n" + string(bodyBytes)
}
msg := fmt.Sprintf("code=%d, url=%s, body=%s", response.StatusCode, response.Request.URL, body)
switch response.StatusCode {
case 404:
return errors.Wrap(ErrNotFound, msg)
default:
return errors.Wrap(ErrNotOK, msg)
}
}

View File

@@ -74,10 +74,21 @@ func (m *ApiProxyMiddleware) PrepareRequestForProxying(endpoint Endpoint, req *h
return nil
}
type ClientOption func(*http.Client)
func WithTimeout(t time.Duration) ClientOption {
return func(c *http.Client) {
c.Timeout = t
}
}
// ProxyRequest proxies the request to grpc-gateway.
func ProxyRequest(req *http.Request) (*http.Response, ErrorJson) {
func ProxyRequest(req *http.Request, opts ...ClientOption) (*http.Response, ErrorJson) {
// We do not use http.DefaultClient because it does not have any timeout.
netClient := &http.Client{Timeout: time.Minute * 2}
for _, o := range opts {
o(netClient)
}
grpcResp, err := netClient.Do(req)
if err != nil {
return nil, InternalServerErrorWithMessage(err, "could not proxy request")

View File

@@ -232,7 +232,7 @@ func (s *Service) startFromSavedState(saved state.BeaconState) error {
func (s *Service) originRootFromSavedState(ctx context.Context) ([32]byte, error) {
// first check if we have started from checkpoint sync and have a root
originRoot, err := s.cfg.BeaconDB.OriginBlockRoot(ctx)
originRoot, err := s.cfg.BeaconDB.OriginCheckpointBlockRoot(ctx)
if err == nil {
return originRoot, nil
}
@@ -240,7 +240,7 @@ func (s *Service) originRootFromSavedState(ctx context.Context) ([32]byte, error
return originRoot, errors.Wrap(err, "could not retrieve checkpoint sync chain origin data from db")
}
// we got here because OriginBlockRoot gave us an ErrNotFound. this means the node was started from a genesis state,
// we got here because OriginCheckpointBlockRoot gave us an ErrNotFound. this means the node was started from a genesis state,
// so we should have a value for GenesisBlock
genesisBlock, err := s.cfg.BeaconDB.GenesisBlock(ctx)
if err != nil {

View File

@@ -36,6 +36,7 @@ func NewWeakSubjectivityVerifier(wsc *ethpb.Checkpoint, db weakSubjectivityDB) (
// per 7342, a nil checkpoint, zero-root or zero-epoch should all fail validation
// and return an error instead of creating a WeakSubjectivityVerifier that permits any chain history.
if wsc == nil || len(wsc.Root) == 0 || wsc.Epoch == 0 {
log.Warn("no valid weak subjectivity checkpoint specified, running without weak subjectivity verification")
return &WeakSubjectivityVerifier{
enabled: false,
}, nil
@@ -81,6 +82,7 @@ func (v *WeakSubjectivityVerifier) VerifyWeakSubjectivity(ctx context.Context, f
}
filter := filters.NewFilter().SetStartSlot(v.slot).SetEndSlot(v.slot + params.BeaconConfig().SlotsPerEpoch)
// A node should have the weak subjectivity block corresponds to the correct epoch in the DB.
log.Infof("searching block roots index for weak subjectivity root=%#x", v.root)
roots, err := v.db.BlockRoots(ctx, filter)
if err != nil {
return errors.Wrap(err, "error while retrieving block roots to verify weak subjectivity")

View File

@@ -2,12 +2,13 @@ package blockchain
import (
"context"
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
"github.com/prysmaticlabs/prysm/time/slots"
"testing"
"github.com/pkg/errors"
types "github.com/prysmaticlabs/eth2-types"
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper"
"github.com/prysmaticlabs/prysm/testing/require"
@@ -18,52 +19,55 @@ func TestService_VerifyWeakSubjectivityRoot(t *testing.T) {
beaconDB := testDB.SetupDB(t)
b := util.NewBeaconBlock()
b.Block.Slot = 32
b.Block.Slot = 1792480
blockEpoch := slots.ToEpoch(b.Block.Slot)
require.NoError(t, beaconDB.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(b)))
r, err := b.Block.HashTreeRoot()
require.NoError(t, err)
tests := []struct {
wsVerified bool
disabled bool
wantErr error
checkpt *ethpb.Checkpoint
finalizedEpoch types.Epoch
name string
}{
{
name: "nil root and epoch",
},
{
name: "already verified",
checkpt: &ethpb.Checkpoint{Epoch: 2},
finalizedEpoch: 2,
wsVerified: true,
name: "nil root and epoch",
disabled: true,
},
{
name: "not yet to verify, ws epoch higher than finalized epoch",
checkpt: &ethpb.Checkpoint{Epoch: 2},
finalizedEpoch: 1,
checkpt: &ethpb.Checkpoint{Root: bytesutil.PadTo([]byte{'a'}, 32), Epoch: blockEpoch},
finalizedEpoch: blockEpoch - 1,
},
{
name: "can't find the block in DB",
checkpt: &ethpb.Checkpoint{Root: bytesutil.PadTo([]byte{'a'}, 32), Epoch: 1},
finalizedEpoch: 3,
finalizedEpoch: blockEpoch + 1,
wantErr: errWSBlockNotFound,
},
{
name: "can't find the block corresponds to ws epoch in DB",
checkpt: &ethpb.Checkpoint{Root: r[:], Epoch: 2}, // Root belongs in epoch 1.
finalizedEpoch: 3,
checkpt: &ethpb.Checkpoint{Root: r[:], Epoch: blockEpoch - 2}, // Root belongs in epoch 1.
finalizedEpoch: blockEpoch - 1,
wantErr: errWSBlockNotFoundInEpoch,
},
{
name: "can verify and pass",
checkpt: &ethpb.Checkpoint{Root: r[:], Epoch: 1},
finalizedEpoch: 3,
checkpt: &ethpb.Checkpoint{Root: r[:], Epoch: blockEpoch},
finalizedEpoch: blockEpoch + 1,
},
{
name: "equal epoch",
checkpt: &ethpb.Checkpoint{Root: r[:], Epoch: blockEpoch},
finalizedEpoch: blockEpoch,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
wv, err := NewWeakSubjectivityVerifier(tt.checkpt, beaconDB)
require.Equal(t, !tt.disabled, wv.enabled)
require.NoError(t, err)
s := &Service{
cfg: &config{BeaconDB: beaconDB, WeakSubjectivityCheckpt: tt.checkpt},

View File

@@ -15,27 +15,7 @@ go_library(
"weak_subjectivity.go",
],
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers",
visibility = [
"//beacon-chain:__subpackages__",
"//cmd/beacon-chain:__subpackages__",
"//contracts/deposit:__pkg__",
"//crypto/keystore:__pkg__",
"//fuzz:__pkg__",
"//network/forks:__pkg__",
"//proto/prysm/v1alpha1:__subpackages__",
"//proto/prysm/v1alpha1/attestation:__pkg__",
"//runtime/interop:__pkg__",
"//slasher:__subpackages__",
"//testing/altair:__pkg__",
"//testing/benchmark/benchmark_files:__subpackages__",
"//testing/endtoend/evaluators:__pkg__",
"//testing/fuzz:__pkg__",
"//testing/slasher/simulator:__pkg__",
"//testing/spectest:__subpackages__",
"//testing/util:__pkg__",
"//tools:__subpackages__",
"//validator:__subpackages__",
],
visibility = ["//visibility:public"],
deps = [
"//beacon-chain/cache:go_default_library",
"//beacon-chain/core/time:go_default_library",

View File

@@ -1,11 +1,11 @@
package helpers
import (
"bytes"
"context"
"encoding/hex"
"errors"
"fmt"
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
"strconv"
"strings"
@@ -14,7 +14,7 @@ import (
"github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/config/params"
"github.com/prysmaticlabs/prysm/math"
eth "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
v1alpha1 "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/time/slots"
)
@@ -122,20 +122,20 @@ func ComputeWeakSubjectivityPeriod(ctx context.Context, st state.ReadOnlyBeaconS
// current_epoch = compute_epoch_at_slot(get_current_slot(store))
// return current_epoch <= ws_state_epoch + ws_period
func IsWithinWeakSubjectivityPeriod(
ctx context.Context, currentEpoch types.Epoch, wsState state.ReadOnlyBeaconState, wsCheckpoint *eth.WeakSubjectivityCheckpoint) (bool, error) {
ctx context.Context, currentEpoch types.Epoch, wsState state.ReadOnlyBeaconState, wsStateRoot [32]byte, wsEpoch types.Epoch) (bool, error) {
// Make sure that incoming objects are not nil.
if wsState == nil || wsState.IsNil() || wsState.LatestBlockHeader() == nil || wsCheckpoint == nil {
if wsState == nil || wsState.IsNil() || wsState.LatestBlockHeader() == nil {
return false, errors.New("invalid weak subjectivity state or checkpoint")
}
// Assert that state and checkpoint have the same root and epoch.
if !bytes.Equal(wsState.LatestBlockHeader().StateRoot, wsCheckpoint.StateRoot) {
if bytesutil.ToBytes32(wsState.LatestBlockHeader().StateRoot) != wsStateRoot {
return false, fmt.Errorf("state (%#x) and checkpoint (%#x) roots do not match",
wsState.LatestBlockHeader().StateRoot, wsCheckpoint.StateRoot)
wsState.LatestBlockHeader().StateRoot, wsStateRoot)
}
if slots.ToEpoch(wsState.Slot()) != wsCheckpoint.Epoch {
if slots.ToEpoch(wsState.Slot()) != wsEpoch {
return false, fmt.Errorf("state (%v) and checkpoint (%v) epochs do not match",
slots.ToEpoch(wsState.Slot()), wsCheckpoint.Epoch)
slots.ToEpoch(wsState.Slot()), wsEpoch)
}
// Compare given epoch to state epoch + weak subjectivity period.
@@ -164,7 +164,7 @@ func LatestWeakSubjectivityEpoch(ctx context.Context, st state.ReadOnlyBeaconSta
}
// ParseWeakSubjectivityInputString parses "blocks_root:epoch_number" string into a checkpoint.
func ParseWeakSubjectivityInputString(wsCheckpointString string) (*eth.Checkpoint, error) {
func ParseWeakSubjectivityInputString(wsCheckpointString string) (*v1alpha1.Checkpoint, error) {
if wsCheckpointString == "" {
return nil, nil
}
@@ -197,7 +197,7 @@ func ParseWeakSubjectivityInputString(wsCheckpointString string) (*eth.Checkpoin
return nil, err
}
return &eth.Checkpoint{
return &v1alpha1.Checkpoint{
Epoch: types.Epoch(epoch),
Root: bRoot,
}, nil

View File

@@ -54,12 +54,15 @@ func TestWeakSubjectivity_ComputeWeakSubjectivityPeriod(t *testing.T) {
})
}
}
type mockWsCheckpoint func() (stateRoot [32]byte, blockRoot [32]byte, e types.Epoch)
func TestWeakSubjectivity_IsWithinWeakSubjectivityPeriod(t *testing.T) {
tests := []struct {
name string
epoch types.Epoch
genWsState func() state.ReadOnlyBeaconState
genWsCheckpoint func() *ethpb.WeakSubjectivityCheckpoint
genWsCheckpoint mockWsCheckpoint
want bool
wantedErr string
}{
@@ -68,22 +71,8 @@ func TestWeakSubjectivity_IsWithinWeakSubjectivityPeriod(t *testing.T) {
genWsState: func() state.ReadOnlyBeaconState {
return nil
},
genWsCheckpoint: func() *ethpb.WeakSubjectivityCheckpoint {
return &ethpb.WeakSubjectivityCheckpoint{
BlockRoot: make([]byte, 32),
StateRoot: make([]byte, 32),
Epoch: 42,
}
},
wantedErr: "invalid weak subjectivity state or checkpoint",
},
{
name: "nil weak subjectivity checkpoint",
genWsState: func() state.ReadOnlyBeaconState {
return genState(t, 128, 32)
},
genWsCheckpoint: func() *ethpb.WeakSubjectivityCheckpoint {
return nil
genWsCheckpoint: func() ([32]byte, [32]byte, types.Epoch) {
return [32]byte{}, [32]byte{}, 42
},
wantedErr: "invalid weak subjectivity state or checkpoint",
},
@@ -99,11 +88,10 @@ func TestWeakSubjectivity_IsWithinWeakSubjectivityPeriod(t *testing.T) {
require.NoError(t, err)
return beaconState
},
genWsCheckpoint: func() *ethpb.WeakSubjectivityCheckpoint {
return &ethpb.WeakSubjectivityCheckpoint{
StateRoot: bytesutil.PadTo([]byte("stateroot2"), 32),
Epoch: 42,
}
genWsCheckpoint: func() ([32]byte, [32]byte, types.Epoch) {
var sr [32]byte
copy(sr[:], bytesutil.PadTo([]byte("stateroot2"), 32))
return sr, [32]byte{}, 42
},
wantedErr: fmt.Sprintf("state (%#x) and checkpoint (%#x) roots do not match",
bytesutil.PadTo([]byte("stateroot1"), 32), bytesutil.PadTo([]byte("stateroot2"), 32)),
@@ -120,11 +108,10 @@ func TestWeakSubjectivity_IsWithinWeakSubjectivityPeriod(t *testing.T) {
require.NoError(t, err)
return beaconState
},
genWsCheckpoint: func() *ethpb.WeakSubjectivityCheckpoint {
return &ethpb.WeakSubjectivityCheckpoint{
StateRoot: bytesutil.PadTo([]byte("stateroot"), 32),
Epoch: 43,
}
genWsCheckpoint: func() ([32]byte, [32]byte, types.Epoch) {
var sr [32]byte
copy(sr[:], bytesutil.PadTo([]byte("stateroot"), 32))
return sr, [32]byte{}, 43
},
wantedErr: "state (42) and checkpoint (43) epochs do not match",
},
@@ -140,11 +127,10 @@ func TestWeakSubjectivity_IsWithinWeakSubjectivityPeriod(t *testing.T) {
require.NoError(t, err)
return beaconState
},
genWsCheckpoint: func() *ethpb.WeakSubjectivityCheckpoint {
return &ethpb.WeakSubjectivityCheckpoint{
StateRoot: bytesutil.PadTo([]byte("stateroot"), 32),
Epoch: 42,
}
genWsCheckpoint: func() ([32]byte, [32]byte, types.Epoch) {
var sr [32]byte
copy(sr[:], bytesutil.PadTo([]byte("stateroot"), 32))
return sr, [32]byte{}, 42
},
wantedErr: "cannot compute weak subjectivity period: no active validators found",
},
@@ -161,11 +147,10 @@ func TestWeakSubjectivity_IsWithinWeakSubjectivityPeriod(t *testing.T) {
require.NoError(t, err)
return beaconState
},
genWsCheckpoint: func() *ethpb.WeakSubjectivityCheckpoint {
return &ethpb.WeakSubjectivityCheckpoint{
StateRoot: bytesutil.PadTo([]byte("stateroot"), 32),
Epoch: 42,
}
genWsCheckpoint: func() ([32]byte, [32]byte, types.Epoch) {
var sr [32]byte
copy(sr[:], bytesutil.PadTo([]byte("stateroot"), 32))
return sr, [32]byte{}, 42
},
want: false,
},
@@ -182,18 +167,18 @@ func TestWeakSubjectivity_IsWithinWeakSubjectivityPeriod(t *testing.T) {
require.NoError(t, err)
return beaconState
},
genWsCheckpoint: func() *ethpb.WeakSubjectivityCheckpoint {
return &ethpb.WeakSubjectivityCheckpoint{
StateRoot: bytesutil.PadTo([]byte("stateroot"), 32),
Epoch: 42,
}
genWsCheckpoint: func() ([32]byte, [32]byte, types.Epoch) {
var sr [32]byte
copy(sr[:], bytesutil.PadTo([]byte("stateroot"), 32))
return sr, [32]byte{}, 42
},
want: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := helpers.IsWithinWeakSubjectivityPeriod(context.Background(), tt.epoch, tt.genWsState(), tt.genWsCheckpoint())
sr, _, e := tt.genWsCheckpoint()
got, err := helpers.IsWithinWeakSubjectivityPeriod(context.Background(), tt.epoch, tt.genWsState(), sr, e)
if tt.wantedErr != "" {
assert.Equal(t, false, got)
assert.ErrorContains(t, tt.wantedErr, err)

View File

@@ -50,7 +50,8 @@ type ReadOnlyDatabase interface {
PowchainData(ctx context.Context) (*ethpb.ETH1ChainData, error)
// origin checkpoint sync support
OriginBlockRoot(ctx context.Context) ([32]byte, error)
OriginCheckpointBlockRoot(ctx context.Context) ([32]byte, error)
LowestSyncedBlockSlot(ctx context.Context) (types.Slot, error)
}
// NoHeadAccessDatabase defines a struct without access to chain head data.
@@ -95,7 +96,7 @@ type HeadAccessDatabase interface {
EnsureEmbeddedGenesis(ctx context.Context) error
// initialization method needed for origin checkpoint sync
SaveOrigin(ctx context.Context, state io.Reader, block io.Reader) error
SaveOrigin(ctx context.Context, state []byte, block []byte) error
}
// SlasherDatabase interface for persisting data related to detecting slashable offenses on Ethereum.

View File

@@ -53,6 +53,7 @@ go_library(
"//proto/prysm/v1alpha1:go_default_library",
"//proto/prysm/v1alpha1/block:go_default_library",
"//proto/prysm/v1alpha1/wrapper:go_default_library",
"//proto/sniff:go_default_library",
"//runtime/version:go_default_library",
"//time/slots:go_default_library",
"@com_github_dgraph_io_ristretto//:go_default_library",

View File

@@ -23,6 +23,7 @@ import (
// used to represent errors for inconsistent slot ranges.
var errInvalidSlotRange = errors.New("invalid end slot and start slot provided")
var errEmptyBucket = errors.New("unexpectedly empty bucket")
// Block retrieval by root.
func (s *Store) Block(ctx context.Context, blockRoot [32]byte) (block.SignedBeaconBlock, error) {
@@ -46,18 +47,18 @@ func (s *Store) Block(ctx context.Context, blockRoot [32]byte) (block.SignedBeac
return blk, err
}
// OriginBlockRoot returns the value written to the db in SaveOriginBlockRoot
// OriginCheckpointBlockRoot returns the value written to the db in SaveOriginCheckpointBlockRoot
// This is the root of a finalized block within the weak subjectivity period
// at the time the chain was started, used to initialize the database and chain
// without syncing from genesis.
func (s *Store) OriginBlockRoot(ctx context.Context) ([32]byte, error) {
_, span := trace.StartSpan(ctx, "BeaconDB.OriginBlockRoot")
func (s *Store) OriginCheckpointBlockRoot(ctx context.Context) ([32]byte, error) {
_, span := trace.StartSpan(ctx, "BeaconDB.OriginCheckpointBlockRoot")
defer span.End()
var root [32]byte
err := s.db.View(func(tx *bolt.Tx) error {
bkt := tx.Bucket(blocksBucket)
rootSlice := bkt.Get(originBlockRootKey)
rootSlice := bkt.Get(originCheckpointBlockRootKey)
if rootSlice == nil {
return ErrNotFoundOriginBlockRoot
}
@@ -68,6 +69,25 @@ func (s *Store) OriginBlockRoot(ctx context.Context) ([32]byte, error) {
return root, err
}
// LowestSyncedBlockSlot returns the lowest slot number in the block root index
func (s *Store) LowestSyncedBlockSlot(ctx context.Context) (types.Slot, error) {
// start scan at zero, which will yield the lowest key in the collection.
var slot types.Slot
err := s.db.View(func(tx *bolt.Tx) error {
// Iterate through the index, which is in byte sorted order.
bkt := tx.Bucket(blockSlotIndicesBucket)
c := bkt.Cursor()
k, _ := c.First()
if k == nil {
msg := fmt.Sprintf("'%s' bucket is empty", string(blockSlotIndicesBucket))
return errors.Wrap(errEmptyBucket, msg)
}
slot = bytesutil.BytesToSlotBigEndian(k)
return nil
})
return slot, err
}
// HeadBlock returns the latest canonical block in the Ethereum Beacon Chain.
func (s *Store) HeadBlock(ctx context.Context) (block.SignedBeaconBlock, error) {
ctx, span := trace.StartSpan(ctx, "BeaconDB.HeadBlock")
@@ -358,16 +378,16 @@ func (s *Store) SaveGenesisBlockRoot(ctx context.Context, blockRoot [32]byte) er
})
}
// SaveOriginBlockRoot is used to keep track of the block root used for origin sync.
// SaveOriginCheckpointBlockRoot is used to keep track of the block root used for syncing from a checkpoint origin.
// This should be a finalized block from within the current weak subjectivity period.
// This value is used by a running beacon chain node to locate the state at the beginning
// of the chain history, in places where genesis would typically be used.
func (s *Store) SaveOriginBlockRoot(ctx context.Context, blockRoot [32]byte) error {
_, span := trace.StartSpan(ctx, "BeaconDB.SaveOriginBlockRoot")
func (s *Store) SaveOriginCheckpointBlockRoot(ctx context.Context, blockRoot [32]byte) error {
_, span := trace.StartSpan(ctx, "BeaconDB.SaveOriginCheckpointBlockRoot")
defer span.End()
return s.db.Update(func(tx *bolt.Tx) error {
bucket := tx.Bucket(blocksBucket)
return bucket.Put(originBlockRootKey, blockRoot[:])
return bucket.Put(originCheckpointBlockRootKey, blockRoot[:])
})
}

View File

@@ -17,6 +17,30 @@ import (
"google.golang.org/protobuf/proto"
)
func TestStore_LowestSyncedBlockSlot(t *testing.T) {
// test case: make sure expected error is returned w/ an empty bucket
db := setupDB(t)
ctx := context.Background()
_, err := db.LowestSyncedBlockSlot(ctx)
require.ErrorIs(t, err, errEmptyBucket)
// test case: make sure that the right value is returned using a non-zero key
block := util.NewBeaconBlock()
block.Block.Slot = types.Slot(1 << 32)
require.NoError(t, db.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(block)))
slot, err := db.LowestSyncedBlockSlot(ctx)
require.NoError(t, err)
require.Equal(t, slot, block.Block.Slot)
// test case: write a lower value and make sure that it is returned instead of the existing value
zero := util.NewBeaconBlock()
zero.Block.Slot = types.Slot(0)
require.NoError(t, db.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(zero)))
zslot, err := db.LowestSyncedBlockSlot(ctx)
require.NoError(t, err)
require.Equal(t, zslot, zero.Block.Slot)
}
func TestStore_SaveBlock_NoDuplicates(t *testing.T) {
BlockCacheSize = 1
db := setupDB(t)

View File

@@ -7,7 +7,7 @@ import "errors"
var ErrNotFound = errors.New("not found in db")
// ErrNotFoundOriginBlockRoot is an error specifically for the origin block root getter
var ErrNotFoundOriginBlockRoot = WrapDBError(ErrNotFound, "OriginBlockRoot")
var ErrNotFoundOriginBlockRoot = WrapDBError(ErrNotFound, "OriginCheckpointBlockRoot")
// WrapDBError wraps an error in a DBError. See commentary on DBError for more context.
func WrapDBError(e error, outer string) error {

View File

@@ -46,6 +46,7 @@ func (s *Store) updateFinalizedBlockRoots(ctx context.Context, tx *bolt.Tx, chec
root := checkpoint.Root
var previousRoot []byte
genesisRoot := tx.Bucket(blocksBucket).Get(genesisBlockRootKey)
initCheckpointRoot := tx.Bucket(blocksBucket).Get(originCheckpointBlockRootKey)
// De-index recent finalized block roots, to be re-indexed.
previousFinalizedCheckpoint := &ethpb.Checkpoint{}
@@ -74,7 +75,7 @@ func (s *Store) updateFinalizedBlockRoots(ctx context.Context, tx *bolt.Tx, chec
// Walk up the ancestry chain until we reach a block root present in the finalized block roots
// index bucket or genesis block root.
for {
if bytes.Equal(root, genesisRoot) {
if bytes.Equal(root, genesisRoot) || bytes.Equal(root, initCheckpointRoot) {
break
}

View File

@@ -49,7 +49,7 @@ var (
altairKey = []byte("altair")
mergeKey = []byte("merge")
// block root included in the beacon state used by weak subjectivity initial sync
originBlockRootKey = []byte("origin-block-root")
originCheckpointBlockRootKey = []byte("origin-checkpoint-block-root")
// Deprecated: This index key was migrated in PR 6461. Do not use, except for migrations.
lastArchivedIndexKey = []byte("last-archived")

View File

@@ -2,56 +2,57 @@ package kv
import (
"context"
"io"
"io/ioutil"
"fmt"
"github.com/pkg/errors"
types "github.com/prysmaticlabs/eth2-types"
statev2 "github.com/prysmaticlabs/prysm/beacon-chain/state/v2"
"github.com/prysmaticlabs/prysm/config/params"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper"
"github.com/prysmaticlabs/prysm/proto/sniff"
)
// SaveOrigin loads an ssz serialized Block & BeaconState from an io.Reader
// (ex: an open file) prepares the database so that the beacon node can begin
// syncing, using the provided values as their point of origin. This is an alternative
// to syncing from genesis, and should only be run on an empty database.
func (s *Store) SaveOrigin(ctx context.Context, stateReader, blockReader io.Reader) error {
// unmarshal both block and state before trying to save anything
// so that we fail early if there is any issue with the ssz data
blk := &ethpb.SignedBeaconBlockAltair{}
bb, err := ioutil.ReadAll(blockReader)
func (s *Store) SaveOrigin(ctx context.Context, serState, serBlock []byte) error {
cf, err := sniff.ConfigForkForState(serState)
if err != nil {
return errors.Wrap(err, "error reading block given to SaveOrigin")
return errors.Wrap(err, "could not sniff config+fork for origin state bytes")
}
if err := blk.UnmarshalSSZ(bb); err != nil {
return errors.Wrap(err, "could not unmarshal checkpoint block")
}
wblk, err := wrapper.WrappedAltairSignedBeaconBlock(blk)
if err != nil {
return errors.Wrap(err, "could not wrap checkpoint block")
}
bs, err := statev2.InitializeFromSSZReader(stateReader)
if err != nil {
return errors.Wrap(err, "could not initialize checkpoint state from reader")
_, ok := params.BeaconConfig().ForkVersionSchedule[cf.Version]
if !ok {
return fmt.Errorf("config mismatch, beacon node configured to connect to %s, detected state is for %s", params.BeaconConfig().ConfigName, cf.ConfigName.String())
}
// save block
if err := s.SaveBlock(ctx, wblk); err != nil {
return errors.Wrap(err, "could not save checkpoint block")
log.Printf("detected supported config for state & block version detection, name=%s, fork=%s", cf.ConfigName.String(), cf.Fork)
state, err := sniff.BeaconStateForConfigFork(serState, cf)
if err != nil {
return errors.Wrap(err, "failed to initialize origin state w/ bytes + config+fork")
}
blockRoot, err := blk.Block.HashTreeRoot()
wblk, err := sniff.BlockForConfigFork(serBlock, cf)
if err != nil {
return errors.Wrap(err, "failed to initialize origin block w/ bytes + config+fork")
}
blk := wblk.Block()
// save block
blockRoot, err := blk.HashTreeRoot()
if err != nil {
return errors.Wrap(err, "could not compute HashTreeRoot of checkpoint block")
}
log.Infof("saving checkpoint block to db, w/ root=%#x", blockRoot)
if err := s.SaveBlock(ctx, wblk); err != nil {
return errors.Wrap(err, "could not save checkpoint block")
}
// save state
if err = s.SaveState(ctx, bs, blockRoot); err != nil {
log.Infof("calling SaveState w/ blockRoot=%x", blockRoot)
if err = s.SaveState(ctx, state, blockRoot); err != nil {
return errors.Wrap(err, "could not save state")
}
if err = s.SaveStateSummary(ctx, &ethpb.StateSummary{
Slot: bs.Slot(),
Slot: state.Slot(),
Root: blockRoot[:],
}); err != nil {
return errors.Wrap(err, "could not save state summary")
@@ -59,7 +60,7 @@ func (s *Store) SaveOrigin(ctx context.Context, stateReader, blockReader io.Read
// save origin block root in special key, to be used when the canonical
// origin (start of chain, ie alternative to genesis) block or state is needed
if err = s.SaveOriginBlockRoot(ctx, blockRoot); err != nil {
if err = s.SaveOriginCheckpointBlockRoot(ctx, blockRoot); err != nil {
return errors.Wrap(err, "could not save origin block root")
}
@@ -70,7 +71,7 @@ func (s *Store) SaveOrigin(ctx context.Context, stateReader, blockReader io.Read
// rebuild the checkpoint from the block
// use it to mark the block as justified and finalized
slotEpoch, err := blk.Block.Slot.SafeDivSlot(params.BeaconConfig().SlotsPerEpoch)
slotEpoch, err := blk.Slot().SafeDivSlot(params.BeaconConfig().SlotsPerEpoch)
if err != nil {
return err
}

View File

@@ -40,6 +40,7 @@ go_library(
"//beacon-chain/state:go_default_library",
"//beacon-chain/state/stategen:go_default_library",
"//beacon-chain/sync:go_default_library",
"//beacon-chain/sync/checkpoint:go_default_library",
"//beacon-chain/sync/initial-sync:go_default_library",
"//cmd:go_default_library",
"//cmd/beacon-chain/flags:go_default_library",

View File

@@ -15,6 +15,8 @@ import (
"sync"
"syscall"
"github.com/prysmaticlabs/prysm/beacon-chain/sync/checkpoint"
"github.com/ethereum/go-ethereum/common"
"github.com/pkg/errors"
types "github.com/prysmaticlabs/eth2-types"
@@ -100,6 +102,8 @@ type BeaconNode struct {
slasherAttestationsFeed *event.Feed
finalizedStateAtStartUp state.BeaconState
serviceFlagOpts *serviceFlagOpts
blockchainFlagOpts []blockchain.Option
CheckpointInitializer checkpoint.Initializer
}
// New creates a new node instance, sets up configuration options, and registers
@@ -219,7 +223,7 @@ func New(cliCtx *cli.Context, opts ...Option) (*BeaconNode, error) {
// db.DatabasePath is the path to the containing directory
// db.NewDBFilename expands that to the canonical full path using
// the same constuction as NewDB()
// the same construction as NewDB()
c, err := newBeaconNodePromCollector(db.NewDBFilename(beacon.db.DatabasePath()))
if err != nil {
return nil, err
@@ -373,6 +377,13 @@ func (b *BeaconNode) startDB(cliCtx *cli.Context, depositAddress string) error {
if err := b.db.EnsureEmbeddedGenesis(b.ctx); err != nil {
return err
}
if b.CheckpointInitializer != nil {
if err := b.CheckpointInitializer.Initialize(b.ctx, d); err != nil {
return err
}
}
knownContract, err := b.db.DepositContractAddress(b.ctx)
if err != nil {
return err
@@ -441,7 +452,29 @@ func (b *BeaconNode) startSlasherDB(cliCtx *cli.Context) error {
}
func (b *BeaconNode) startStateGen() error {
b.stateGen = stategen.New(b.db)
o := make([]stategen.StateGenOption, 0)
_, err := b.db.OriginCheckpointBlockRoot(b.ctx)
if err == nil {
// we'll get a db.ErrNotFound if the db was not initialized with a checkpoint
// so if err == nil, the node was initialized with checkpoint init.
o = append(o, stategen.WithInitType(stategen.BeaconDBInitTypeCheckpoint))
lowestSlot, err := b.db.LowestSyncedBlockSlot(b.ctx)
if err != nil {
return errors.Wrap(err, "error searching for lowest block slot on checkpoint-initialized node")
}
o = append(o, stategen.WithMinimumSlot(lowestSlot))
} else {
if errors.Is(err, db.ErrNotFound) {
// error is ErrNotFound, so we can assume the node was initialized with a genesis state (or via powchain)
o = append(o, stategen.WithInitType(stategen.BeaconDBInitTypeGenesisState))
} else {
// if the error is not an ErrNotFound, we failed to query the db for some reason,
// can't be confident how it was initialized.
return errors.Wrap(err, "could not retrieve checkpoint sync chain origin data from db")
}
}
sg := stategen.New(b.db, o...)
cp, err := b.db.FinalizedCheckpoint(b.ctx)
if err != nil {
@@ -451,6 +484,12 @@ func (b *BeaconNode) startStateGen() error {
r := bytesutil.ToBytes32(cp.Root)
// Consider edge case where finalized root are zeros instead of genesis root hash.
if r == params.BeaconConfig().ZeroHash {
if sg.MinimumSlot() > 0 {
// using checkpoint sync the minimum slot will be > 0, but the checkpoint block is marked as finalized,
// so if it is equal to ZeroHash, this is likely an error (and the genesis block won't be available).
msg := fmt.Sprintf("unable to retrieve genesis block, no slots before %d in db", sg.MinimumSlot())
return errors.Wrap(err, msg)
}
genesisBlock, err := b.db.GenesisBlock(b.ctx)
if err != nil {
return err
@@ -463,10 +502,12 @@ func (b *BeaconNode) startStateGen() error {
}
}
b.finalizedStateAtStartUp, err = b.stateGen.StateByRoot(b.ctx, r)
b.finalizedStateAtStartUp, err = sg.StateByRoot(b.ctx, r)
if err != nil {
return err
}
b.stateGen = sg
return nil
}

View File

@@ -10,7 +10,7 @@ go_library(
"structs_marshalling.go",
],
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/rpc/apimiddleware",
visibility = ["//beacon-chain:__subpackages__"],
visibility = ["//visibility:public"],
deps = [
"//api/gateway/apimiddleware:go_default_library",
"//api/grpc:go_default_library",

View File

@@ -10,6 +10,7 @@ import (
"net/http"
"strconv"
"strings"
"time"
"github.com/prysmaticlabs/prysm/api/gateway/apimiddleware"
"github.com/prysmaticlabs/prysm/api/grpc"
@@ -21,6 +22,7 @@ type sszConfig struct {
sszPath string
fileName string
responseJson sszResponseJson
clientOpts []apimiddleware.ClientOption
}
func handleGetBeaconStateSSZ(m *apimiddleware.ApiProxyMiddleware, endpoint apimiddleware.Endpoint, w http.ResponseWriter, req *http.Request) (handled bool) {
@@ -28,6 +30,7 @@ func handleGetBeaconStateSSZ(m *apimiddleware.ApiProxyMiddleware, endpoint apimi
sszPath: "/eth/v1/debug/beacon/states/{state_id}/ssz",
fileName: "beacon_state.ssz",
responseJson: &beaconStateSSZResponseJson{},
clientOpts: []apimiddleware.ClientOption{apimiddleware.WithTimeout(time.Minute * 4)},
}
return handleGetSSZ(m, endpoint, w, req, config)
}
@@ -46,6 +49,7 @@ func handleGetBeaconStateSSZV2(m *apimiddleware.ApiProxyMiddleware, endpoint api
sszPath: "/eth/v2/debug/beacon/states/{state_id}/ssz",
fileName: "beacon_state.ssz",
responseJson: &beaconStateSSZResponseV2Json{},
clientOpts: []apimiddleware.ClientOption{apimiddleware.WithTimeout(time.Minute * 4)},
}
return handleGetSSZ(m, endpoint, w, req, config)
}
@@ -74,7 +78,7 @@ func handleGetSSZ(
apimiddleware.WriteError(w, errJson, nil)
return true
}
grpcResponse, errJson := apimiddleware.ProxyRequest(req)
grpcResponse, errJson := apimiddleware.ProxyRequest(req, config.clientOpts...)
if errJson != nil {
apimiddleware.WriteError(w, errJson, nil)
return true

View File

@@ -37,6 +37,7 @@ func (_ *BeaconEndpointFactory) Paths() []string {
"/eth/v1/beacon/pool/proposer_slashings",
"/eth/v1/beacon/pool/voluntary_exits",
"/eth/v1/beacon/pool/sync_committees",
"/eth/v1/beacon/weak_subjectivity",
"/eth/v1/node/identity",
"/eth/v1/node/peers",
"/eth/v1/node/peers/{peer_id}",
@@ -141,6 +142,8 @@ func (_ *BeaconEndpointFactory) Create(path string) (*apimiddleware.Endpoint, er
endpoint.Hooks = apimiddleware.HookCollection{
OnPreDeserializeRequestBodyIntoContainer: wrapSyncCommitteeSignaturesArray,
}
case "/eth/v1/beacon/weak_subjectivity":
endpoint.GetResponse = &WeakSubjectivityResponse{}
case "/eth/v1/node/identity":
endpoint.GetResponse = &identityResponseJson{}
case "/eth/v1/node/peers":

View File

@@ -19,6 +19,13 @@ type genesisResponse_GenesisJson struct {
GenesisForkVersion string `json:"genesis_fork_version" hex:"true"`
}
type WeakSubjectivityResponse struct {
Data *struct {
Checkpoint *checkpointJson `json:"ws_checkpoint"`
StateRoot string `json:"state_root" hex:"true"`
} `json:"data"`
}
// stateRootResponseJson is used in /beacon/states/{state_id}/root API endpoint.
type stateRootResponseJson struct {
Data *stateRootResponse_StateRootJson `json:"data"`

View File

@@ -3,6 +3,8 @@ package beacon
import (
"context"
"fmt"
"github.com/golang/protobuf/ptypes/empty"
"github.com/prysmaticlabs/prysm/time/slots"
"strconv"
"github.com/pkg/errors"
@@ -41,6 +43,41 @@ func (e *blockIdParseError) Error() string {
return e.message
}
func (bs *Server) GetWeakSubjectivity(ctx context.Context, _ *empty.Empty) (*ethpbv1.WeakSubjectivityResponse, error) {
hs, err := bs.HeadFetcher.HeadState(ctx)
if err != nil {
return nil, status.Error(codes.Internal, "could not get head state")
}
wsEpoch, err := helpers.LatestWeakSubjectivityEpoch(ctx, hs)
if err != nil {
return nil, status.Errorf(codes.Internal, "could not get weak subjectivity epoch: %v", err)
}
wsSlot, err := slots.EpochStart(wsEpoch)
if err != nil {
return nil, status.Errorf(codes.Internal, "could not get weak subjectivity slot: %v", err)
}
blks, err := bs.BeaconDB.HighestSlotBlocksBelow(ctx, wsSlot)
if err != nil {
return nil, status.Errorf(codes.Internal, fmt.Sprintf("could not find highest block below slot %d", wsSlot))
}
block := blks[0]
blockRoot, err := block.Block().HashTreeRoot()
if err != nil {
return nil, status.Errorf(codes.Internal, fmt.Sprintf("failed to compute hash_tree_root for block at slot=%d", block.Block().Slot()))
}
stateRoot := bytesutil.ToBytes32(block.Block().StateRoot())
log.Printf("weak subjectivity checkpoint reported as epoch=%d, block root=%#x, state root=%#x", wsEpoch, blockRoot, stateRoot)
return &ethpbv1.WeakSubjectivityResponse{
Data: &ethpbv1.WeakSubjectivityData{
WsCheckpoint: &ethpbv1.Checkpoint{
Epoch: wsEpoch,
Root: blockRoot[:],
},
StateRoot: stateRoot[:],
},
}, nil
}
// GetBlockHeader retrieves block header for given block id.
func (bs *Server) GetBlockHeader(ctx context.Context, req *ethpbv1.BlockRequest) (*ethpbv1.BlockHeaderResponse, error) {
ctx, span := trace.StartSpan(ctx, "beacon.GetBlockHeader")
@@ -49,7 +86,7 @@ func (bs *Server) GetBlockHeader(ctx context.Context, req *ethpbv1.BlockRequest)
blk, err := bs.blockFromBlockID(ctx, req.BlockId)
err = handleGetBlockError(blk, err)
if err != nil {
return nil, err
return nil, errors.Wrap(err, "GetBlockHeader")
}
v1alpha1Header, err := blk.Header()
if err != nil {
@@ -232,7 +269,7 @@ func (bs *Server) GetBlock(ctx context.Context, req *ethpbv1.BlockRequest) (*eth
blk, err := bs.blockFromBlockID(ctx, req.BlockId)
err = handleGetBlockError(blk, err)
if err != nil {
return nil, err
return nil, errors.Wrap(err, "GetBlock")
}
signedBeaconBlock, err := migration.SignedBeaconBlock(blk)
if err != nil {
@@ -255,7 +292,7 @@ func (bs *Server) GetBlockSSZ(ctx context.Context, req *ethpbv1.BlockRequest) (*
blk, err := bs.blockFromBlockID(ctx, req.BlockId)
err = handleGetBlockError(blk, err)
if err != nil {
return nil, err
return nil, errors.Wrap(err, "GetBlockSSZ")
}
signedBeaconBlock, err := migration.SignedBeaconBlock(blk)
if err != nil {
@@ -277,7 +314,7 @@ func (bs *Server) GetBlockV2(ctx context.Context, req *ethpbv2.BlockRequestV2) (
blk, phase0Blk, err := bs.blocksFromId(ctx, req.BlockId)
err = handleGetBlockError(blk, err)
if err != nil {
return nil, err
return nil, errors.Wrap(err, "GetBlockV2")
}
if phase0Blk != nil {
v1Blk, err := migration.SignedBeaconBlock(blk)
@@ -317,7 +354,7 @@ func (bs *Server) GetBlockSSZV2(ctx context.Context, req *ethpbv2.BlockRequestV2
blk, phase0Blk, err := bs.blocksFromId(ctx, req.BlockId)
err = handleGetBlockError(blk, err)
if err != nil {
return nil, err
return nil, errors.Wrap(err, "GetBlockSSZV2")
}
if phase0Blk != nil {
signedBeaconBlock, err := migration.SignedBeaconBlock(blk)
@@ -467,7 +504,7 @@ func (bs *Server) blocksFromId(ctx context.Context, blockId []byte) (
blk, err := bs.blockFromBlockID(ctx, blockId)
err = handleGetBlockError(blk, err)
if err != nil {
return nil, nil, err
return nil, nil, errors.Wrap(err, "blocksFromId")
}
phase0Blk, err := blk.PbPhase0Block()
// Assume we have an Altair block when Phase 0 block is unsupported.

View File

@@ -117,12 +117,7 @@ func (bs *Server) GetFinalityCheckpoints(ctx context.Context, req *ethpb.StateRe
st, err = bs.StateFetcher.State(ctx, req.StateId)
if err != nil {
if stateNotFoundErr, ok := err.(*statefetcher.StateNotFoundError); ok {
return nil, status.Errorf(codes.NotFound, "State not found: %v", stateNotFoundErr)
} else if parseErr, ok := err.(*statefetcher.StateIdParseError); ok {
return nil, status.Errorf(codes.InvalidArgument, "Invalid state ID: %v", parseErr)
}
return nil, status.Errorf(codes.Internal, "Could not get state: %v", err)
return nil, helpers.PrepareStateFetchGRPCError(err)
}
return &ethpb.StateFinalityCheckpointResponse{

View File

@@ -14,6 +14,7 @@ go_library(
"//beacon-chain/blockchain:go_default_library",
"//beacon-chain/rpc/statefetcher:go_default_library",
"//beacon-chain/state:go_default_library",
"//beacon-chain/state/stategen:go_default_library",
"//beacon-chain/sync:go_default_library",
"//config/params:go_default_library",
"//proto/eth/v1:go_default_library",

View File

@@ -1,7 +1,9 @@
package helpers
import (
"errors"
"github.com/prysmaticlabs/prysm/beacon-chain/rpc/statefetcher"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
@@ -9,9 +11,13 @@ import (
// PrepareStateFetchGRPCError returns an appropriate gRPC error based on the supplied argument.
// The argument error should be a result of fetching state.
func PrepareStateFetchGRPCError(err error) error {
if errors.Is(err, stategen.ErrSlotBeforeOrigin) {
return status.Errorf(codes.NotFound, "lacking historical data needed to fulfill request")
}
if stateNotFoundErr, ok := err.(*statefetcher.StateNotFoundError); ok {
return status.Errorf(codes.NotFound, "State not found: %v", stateNotFoundErr)
} else if parseErr, ok := err.(*statefetcher.StateIdParseError); ok {
}
if parseErr, ok := err.(*statefetcher.StateIdParseError); ok {
return status.Errorf(codes.InvalidArgument, "Invalid state ID: %v", parseErr)
}
return status.Errorf(codes.Internal, "Invalid state ID: %v", err)

View File

@@ -483,11 +483,6 @@ func (bs *Server) chainHeadRetrieval(ctx context.Context) (*ethpb.ChainHead, err
isGenesis := func(cp *ethpb.Checkpoint) bool {
return bytesutil.ToBytes32(cp.Root) == params.BeaconConfig().ZeroHash && cp.Epoch == 0
}
// Retrieve genesis block in the event we have genesis checkpoints.
genBlock, err := bs.BeaconDB.GenesisBlock(ctx)
if err != nil || genBlock == nil || genBlock.IsNil() || genBlock.Block().IsNil() {
return nil, status.Error(codes.Internal, "Could not get genesis block")
}
finalizedCheckpoint := bs.FinalizationFetcher.FinalizedCheckpt()
if !isGenesis(finalizedCheckpoint) {
@@ -549,38 +544,3 @@ func (bs *Server) chainHeadRetrieval(ctx context.Context) (*ethpb.ChainHead, err
PreviousJustifiedBlockRoot: prevJustifiedCheckpoint.Root,
}, nil
}
// GetWeakSubjectivityCheckpoint retrieves weak subjectivity state root, block root, and epoch.
func (bs *Server) GetWeakSubjectivityCheckpoint(ctx context.Context, _ *emptypb.Empty) (*ethpb.WeakSubjectivityCheckpoint, error) {
hs, err := bs.HeadFetcher.HeadState(ctx)
if err != nil {
return nil, status.Error(codes.Internal, "Could not get head state")
}
wsEpoch, err := helpers.LatestWeakSubjectivityEpoch(ctx, hs)
if err != nil {
return nil, status.Error(codes.Internal, "Could not get weak subjectivity epoch")
}
wsSlot, err := slots.EpochStart(wsEpoch)
if err != nil {
return nil, status.Error(codes.Internal, "Could not get weak subjectivity slot")
}
wsState, err := bs.StateGen.StateBySlot(ctx, wsSlot)
if err != nil {
return nil, status.Error(codes.Internal, "Could not get weak subjectivity state")
}
stateRoot, err := wsState.HashTreeRoot(ctx)
if err != nil {
return nil, status.Error(codes.Internal, "Could not get weak subjectivity state root")
}
blkRoot, err := wsState.LatestBlockHeader().HashTreeRoot()
if err != nil {
return nil, status.Error(codes.Internal, "Could not get weak subjectivity block root")
}
return &ethpb.WeakSubjectivityCheckpoint{
BlockRoot: blkRoot[:],
StateRoot: stateRoot[:],
Epoch: wsEpoch,
}, nil
}

View File

@@ -103,7 +103,7 @@ func (p *StateProvider) State(ctx context.Context, stateId []byte) (state.Beacon
return nil, errors.Wrap(err, "could not get head state")
}
case "genesis":
s, err = p.BeaconDB.GenesisState(ctx)
s, err = p.stateBySlot(ctx, 0)
if err != nil {
return nil, errors.Wrap(err, "could not get genesis state")
}

View File

@@ -7,21 +7,7 @@ go_library(
"phase0.go",
],
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state",
visibility = [
"//beacon-chain:__subpackages__",
"//contracts/deposit:__subpackages__",
"//proto/prysm/v1alpha1:__subpackages__",
"//proto/testing:__subpackages__",
"//slasher/rpc:__subpackages__",
"//testing/benchmark:__pkg__",
"//testing/fuzz:__pkg__",
"//testing/slasher/simulator:__pkg__",
"//testing/spectest:__subpackages__",
"//testing/util:__pkg__",
"//tools/benchmark-files-gen:__pkg__",
"//tools/exploredb:__pkg__",
"//tools/pcli:__pkg__",
],
visibility = ["//visibility:public"],
deps = [
"//proto/prysm/v1alpha1:go_default_library",
"@com_github_prysmaticlabs_eth2_types//:go_default_library",

View File

@@ -2,6 +2,7 @@ package stategen
import (
"context"
"fmt"
"github.com/pkg/errors"
types "github.com/prysmaticlabs/eth2-types"
@@ -13,6 +14,8 @@ import (
"go.opencensus.io/trace"
)
var ErrSlotBeforeOrigin = errors.New("cannot retrieve data for slots before sync origin")
// HasState returns true if the state exists in cache or in DB.
func (s *State) HasState(ctx context.Context, blockRoot [32]byte) (bool, error) {
has, err := s.HasStateInCache(ctx, blockRoot)
@@ -53,6 +56,10 @@ func (s *State) StateByRoot(ctx context.Context, blockRoot [32]byte) (state.Beac
// Genesis case. If block root is zero hash, short circuit to use genesis cachedState stored in DB.
if blockRoot == params.BeaconConfig().ZeroHash {
if s.MinimumSlot() > 0 {
msg := fmt.Sprintf("cannot retrieve genesis state, lowest block in db is slot %d", s.MinimumSlot())
return nil, errors.Wrap(ErrSlotBeforeOrigin, msg)
}
return s.beaconDB.GenesisState(ctx)
}
return s.loadStateByRoot(ctx, blockRoot)
@@ -66,6 +73,9 @@ func (s *State) StateByRoot(ctx context.Context, blockRoot [32]byte) (state.Beac
func (s *State) StateByRootInitialSync(ctx context.Context, blockRoot [32]byte) (state.BeaconState, error) {
// Genesis case. If block root is zero hash, short circuit to use genesis state stored in DB.
if blockRoot == params.BeaconConfig().ZeroHash {
if s.beaconDBInitType == BeaconDBInitTypeCheckpoint {
return nil, fmt.Errorf("node initialized through checkpoint sync received invalid (zero value) block root")
}
return s.beaconDB.GenesisState(ctx)
}
@@ -213,6 +223,11 @@ func (s *State) loadStateBySlot(ctx context.Context, slot types.Slot) (state.Bea
ctx, span := trace.StartSpan(ctx, "stateGen.loadStateBySlot")
defer span.End()
if slot < s.MinimumSlot() {
msg := fmt.Sprintf("no data from before slot %d", s.MinimumSlot())
return nil, errors.Wrap(ErrSlotBeforeOrigin, msg)
}
// Return genesis state if slot is 0.
if slot == 0 {
return s.beaconDB.GenesisState(ctx)
@@ -266,6 +281,12 @@ func (s *State) lastAncestorState(ctx context.Context, root [32]byte) (state.Bea
if ctx.Err() != nil {
return nil, ctx.Err()
}
// return an error if we have rewound to before the checkpoint sync slot
if (b.Block().Slot() - 1) < s.MinimumSlot() {
msg := fmt.Sprintf("no blocks in db prior to slot %d", s.MinimumSlot())
return nil, errors.Wrap(ErrSlotBeforeOrigin, msg)
}
// Is the state a genesis state.
parentRoot := bytesutil.ToBytes32(b.Block().ParentRoot())
if parentRoot == params.BeaconConfig().ZeroHash {

View File

@@ -239,9 +239,18 @@ func (s *State) lastSavedBlock(ctx context.Context, slot types.Slot) ([32]byte,
ctx, span := trace.StartSpan(ctx, "stateGen.lastSavedBlock")
defer span.End()
if slot < s.MinimumSlot() {
msg := fmt.Sprintf("no data from before slot %d", s.MinimumSlot())
return [32]byte{}, 0, errors.Wrap(ErrSlotBeforeOrigin, msg)
}
// Handle the genesis case where the input slot is 0.
if slot == 0 {
gRoot, err := s.genesisRoot(ctx)
gb, err := s.beaconDB.GenesisBlock(ctx)
if err != nil {
return [32]byte{}, 0, err
}
gRoot, err := gb.Block().HashTreeRoot()
if err != nil {
return [32]byte{}, 0, err
}
@@ -275,6 +284,11 @@ func (s *State) lastSavedState(ctx context.Context, slot types.Slot) (state.Read
ctx, span := trace.StartSpan(ctx, "stateGen.lastSavedState")
defer span.End()
if slot < s.MinimumSlot() {
msg := fmt.Sprintf("no data from before slot %d", s.MinimumSlot())
return nil, errors.Wrap(ErrSlotBeforeOrigin, msg)
}
// Handle the genesis case where the input slot is 0.
if slot == 0 {
return s.beaconDB.GenesisState(ctx)
@@ -296,15 +310,6 @@ func (s *State) lastSavedState(ctx context.Context, slot types.Slot) (state.Read
return lastSaved[0], nil
}
// This returns the genesis root.
func (s *State) genesisRoot(ctx context.Context) ([32]byte, error) {
b, err := s.beaconDB.GenesisBlock(ctx)
if err != nil {
return [32]byte{}, err
}
return b.Block().HashTreeRoot()
}
// Given the start slot and the end slot, this returns the finalized beacon blocks in between.
// Since hot states don't have finalized blocks, this should ONLY be used for replaying cold state.
func (s *State) loadFinalizedBlocks(ctx context.Context, startSlot, endSlot types.Slot) ([]block.SignedBeaconBlock, error) {

View File

@@ -6,6 +6,7 @@ package stategen
import (
"context"
"errors"
"fmt"
"sync"
types "github.com/prysmaticlabs/eth2-types"
@@ -49,6 +50,8 @@ type State struct {
finalizedInfo *finalizedInfo
epochBoundaryStateCache *epochBoundaryState
saveHotStateDB *saveHotStateDbConfig
minimumSlot types.Slot
beaconDBInitType BeaconDBInitType
}
// This tracks the config in the event of long non-finality,
@@ -70,9 +73,31 @@ type finalizedInfo struct {
lock sync.RWMutex
}
func WithMinimumSlot(min types.Slot) StateGenOption {
return func(s *State) {
s.minimumSlot = min
}
}
type BeaconDBInitType uint
const (
BeaconDBInitTypeGenesisState = iota
BeaconDBInitTypeCheckpoint
)
func WithInitType(t BeaconDBInitType) StateGenOption {
return func(s *State) {
s.beaconDBInitType = t
}
}
// StateGenOption is a functional option for controlling the initialization of a *State value
type StateGenOption func(*State)
// New returns a new state management object.
func New(beaconDB db.NoHeadAccessDatabase) *State {
return &State{
func New(beaconDB db.NoHeadAccessDatabase, opts ...StateGenOption) *State {
s := &State{
beaconDB: beaconDB,
hotStateCache: newHotStateCache(),
finalizedInfo: &finalizedInfo{slot: 0, root: params.BeaconConfig().ZeroHash},
@@ -81,7 +106,13 @@ func New(beaconDB db.NoHeadAccessDatabase) *State {
saveHotStateDB: &saveHotStateDbConfig{
duration: defaultHotStateDBInterval,
},
// defaults to minimumSlot of zero (genesis), overridden by checkpoint sync
minimumSlot: types.Slot(0),
}
for _, o := range opts {
o(s)
}
return s
}
// Resume resumes a new state management object from previously saved finalized check point in DB.
@@ -96,6 +127,9 @@ func (s *State) Resume(ctx context.Context, fState state.BeaconState) (state.Bea
fRoot := bytesutil.ToBytes32(c.Root)
// Resume as genesis state if last finalized root is zero hashes.
if fRoot == params.BeaconConfig().ZeroHash {
if s.MinimumSlot() > 0 {
return nil, fmt.Errorf("no finalized checkpoint, and history before slot %d not currently available", s.MinimumSlot())
}
return s.beaconDB.GenesisState(ctx)
}
@@ -138,3 +172,7 @@ func (s *State) finalizedState() state.BeaconState {
defer s.finalizedInfo.lock.RUnlock()
return s.finalizedInfo.state.Copy()
}
func (s *State) MinimumSlot() types.Slot {
return s.minimumSlot
}

View File

@@ -28,21 +28,7 @@ go_library(
"unsupported_setters.go",
],
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state/v1",
visibility = [
"//beacon-chain:__subpackages__",
"//contracts/deposit:__subpackages__",
"//proto/migration:__subpackages__",
"//proto/prysm/v1alpha1:__subpackages__",
"//proto/testing:__subpackages__",
"//runtime/interop:__subpackages__",
"//slasher/rpc:__subpackages__",
"//testing/benchmark:__pkg__",
"//testing/fuzz:__pkg__",
"//testing/spectest:__subpackages__",
"//testing/util:__pkg__",
"//tools/benchmark-files-gen:__pkg__",
"//tools/pcli:__pkg__",
],
visibility = ["//visibility:public"],
deps = [
"//beacon-chain/state:go_default_library",
"//beacon-chain/state/fieldtrie:go_default_library",

View File

@@ -36,6 +36,16 @@ func InitializeFromProto(st *ethpb.BeaconState) (*BeaconState, error) {
return InitializeFromProtoUnsafe(proto.Clone(st).(*ethpb.BeaconState))
}
// InitializeFromSSZBytes is a convenience method to obtain a BeaconState by unmarshaling
// a slice of bytes containing the ssz-serialized representation of the state.
func InitializeFromSSZBytes(marshaled []byte) (*BeaconState, error) {
st := &ethpb.BeaconState{}
if err := st.UnmarshalSSZ(marshaled); err != nil {
return nil, err
}
return InitializeFromProtoUnsafe(st)
}
// InitializeFromProtoUnsafe directly uses the beacon state protobuf pointer
// and sets it as the inner state of the BeaconState type.
func InitializeFromProtoUnsafe(st *ethpb.BeaconState) (*BeaconState, error) {

View File

@@ -28,12 +28,7 @@ go_library(
"types.go",
],
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state/v2",
visibility = [
"//beacon-chain:__subpackages__",
"//proto/migration:__subpackages__",
"//testing/spectest:__subpackages__",
"//testing/util:__pkg__",
],
visibility = ["//visibility:public"],
deps = [
"//beacon-chain/state:go_default_library",
"//beacon-chain/state/fieldtrie:go_default_library",

View File

@@ -30,10 +30,7 @@ go_library(
"types.go",
],
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state/v3",
visibility = [
"//beacon-chain:__subpackages__",
"//testing/util:__pkg__",
],
visibility = ["//visibility:public"],
deps = [
"//beacon-chain/state:go_default_library",
"//beacon-chain/state/fieldtrie:go_default_library",

View File

@@ -35,6 +35,16 @@ func InitializeFromProto(st *ethpb.BeaconStateMerge) (*BeaconState, error) {
return InitializeFromProtoUnsafe(proto.Clone(st).(*ethpb.BeaconStateMerge))
}
// InitializeFromSSZBytes is a convenience method to obtain a BeaconState by unmarshaling
// a slice of bytes containing the ssz-serialized representation of the state.
func InitializeFromSSZBytes(marshaled []byte) (*BeaconState, error) {
st := &ethpb.BeaconStateMerge{}
if err := st.UnmarshalSSZ(marshaled); err != nil {
return nil, err
}
return InitializeFromProtoUnsafe(st)
}
// InitializeFromProtoUnsafe directly uses the beacon state protobuf pointer
// and sets it as the inner state of the BeaconState type.
func InitializeFromProtoUnsafe(st *ethpb.BeaconStateMerge) (*BeaconState, error) {

View File

@@ -0,0 +1,21 @@
load("@prysm//tools/go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"api.go",
"initialize.go",
],
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/sync/checkpoint",
visibility = ["//visibility:public"],
deps = [
"//api/client/openapi:go_default_library",
"//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/db:go_default_library",
"//config/params:go_default_library",
"//proto/sniff:go_default_library",
"//time/slots:go_default_library",
"@com_github_pkg_errors//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
],
)

View File

@@ -0,0 +1,115 @@
package checkpoint
import (
"context"
"fmt"
"github.com/prysmaticlabs/prysm/api/client/openapi"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/db"
"github.com/prysmaticlabs/prysm/config/params"
"github.com/prysmaticlabs/prysm/proto/sniff"
"github.com/prysmaticlabs/prysm/time/slots"
log "github.com/sirupsen/logrus"
"io"
"io/ioutil"
//"os"
"github.com/pkg/errors"
//"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
//"github.com/prysmaticlabs/prysm/config/params"
//"github.com/prysmaticlabs/prysm/proto/sniff"
//"github.com/prysmaticlabs/prysm/time/slots"
)
type APIInitializer struct {
c *openapi.Client
}
func NewAPIInitializer(beaconNodeHost string) (*APIInitializer, error) {
c, err := openapi.NewClient(beaconNodeHost)
if err != nil {
return nil, errors.Wrap(err, fmt.Sprintf("unable to parse beacon node url or hostname - %s", beaconNodeHost))
}
return &APIInitializer{c: c}, nil
}
func (dl *APIInitializer) StateReader(ctx context.Context) (io.Reader, error) {
return nil, nil
}
func (dl *APIInitializer) BlockReader(ctx context.Context) (io.Reader, error) {
return nil, nil
}
// - step 1: get the weak subjectivity epoch
// - step 2: get the state at the epoch
// - step 3: get the block corresponding to that state
func (dl *APIInitializer) Initialize(ctx context.Context, d db.Database) error {
// the weak subjectivity period computation requires the active validator count and balance
// the fastest way to get this information is to request the head state from the remote api
headReader, err := dl.c.GetStateById(openapi.StateIdHead)
if err != nil {
return errors.Wrap(err, "failed api request for head state")
}
headBytes, err := io.ReadAll(headReader)
if err != nil {
return errors.Wrap(err, "failed to read response body for get head state api call")
}
log.Printf("state response byte len=%d", len(headBytes))
headState, err := sniff.BeaconState(headBytes)
if err != nil {
return errors.Wrap(err, "error unmarshaling state to correct version")
}
// by confirming that the fork version found in the head state is included in the fork version schedule of
// the currently running beacon node, we ensure that the retrieved state is from the same network
cf, err := sniff.ConfigForkForState(headBytes)
if err != nil {
return errors.Wrap(err, "error detecting chain config for beacon state")
}
_, ok := params.BeaconConfig().ForkVersionSchedule[cf.Version]
if !ok {
return fmt.Errorf("config mismatch, beacon node configured to connect to %s, detected state is for %s", params.BeaconConfig().ConfigName, cf.ConfigName.String())
}
log.Printf("detected supported config for state & block version detection, name=%s, fork=%s", cf.ConfigName.String(), cf.Fork)
epoch, err := helpers.LatestWeakSubjectivityEpoch(ctx, headState)
if err != nil {
return errors.Wrap(err, "error computing the weak subjectivity epoch from head state")
}
// use first slot of the epoch for the block slot
bSlot, err := slots.EpochStart(epoch)
if err != nil {
return errors.Wrap(err, fmt.Sprintf("Error computing first slot of epoch=%d", epoch))
}
// assigning this variable to make it extra obvious that the state slot is different
sSlot := bSlot + 1
// using the state at (slot % 32 = 1) instead of the epoch boundary ensures the
// next block applied to the state will have the block at the weak subjectivity checkpoint
// as its parent, satisfying prysm's sync code current verification that the parent block is present in the db
log.Printf("weak subjectivity epoch computed as %d. downloading block@slot=%d, state@slot=%d", epoch, bSlot, sSlot)
stateReader, err := dl.c.GetStateBySlot(uint64(sSlot))
if err != nil {
return errors.Wrap(err, fmt.Sprintf("failed to retrieve state bytes for slot %d from api", sSlot))
}
serState, err := ioutil.ReadAll(stateReader)
if err != nil {
return errors.Wrap(err, fmt.Sprintf("failed to read state bytes for slot %d from api", bSlot))
}
blockReader, err := dl.c.GetBlockBySlot(uint64(bSlot))
if err != nil {
return errors.Wrap(err, fmt.Sprintf("failed to retrieve block bytes for slot %d from api", bSlot))
}
serBlock, err := ioutil.ReadAll(blockReader)
if err != nil {
return errors.Wrap(err, fmt.Sprintf("failed to read block bytes for slot %d from api", bSlot))
}
return d.SaveOrigin(ctx, serState, serBlock)
}

View File

@@ -0,0 +1,84 @@
package checkpoint
import (
"context"
"fmt"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/beacon-chain/db"
log "github.com/sirupsen/logrus"
"io/ioutil"
"os"
)
type Initializer interface {
Initialize(ctx context.Context, d db.Database) error
}
func NewFileInitializer(blockPath string, statePath string) (*FileInitializer, error) {
var err error
if err = existsAndIsFile(blockPath); err != nil {
return nil, err
}
if err = existsAndIsFile(statePath); err != nil {
return nil, err
}
// stat just to make sure it actually exists and is a file
return &FileInitializer{blockPath: blockPath, statePath: statePath}, nil
}
// FileInitializer initializes a beacon-node database to use checkpoint sync,
// using ssz-encoded block and state data stored in files on the local filesystem.
type FileInitializer struct {
blockPath string
statePath string
}
// Initialize is called in the BeaconNode db startup code if an Initializer is present.
// Initialize does what is needed to prepare the beacon node database for syncing from the weak subjectivity checkpoint.
func (fi *FileInitializer) Initialize(ctx context.Context, d db.Database) error {
blockFH, err := os.Open(fi.blockPath)
if err != nil {
return errors.Wrap(err, fmt.Sprintf("error opening block file %s for checkpoint sync initialization", fi.blockPath))
}
defer func() {
err := blockFH.Close()
if err != nil {
log.Errorf("error while closing checkpoint block input stream: %s", err)
}
}()
serBlock, err := ioutil.ReadAll(blockFH)
if err != nil {
return errors.Wrap(err, fmt.Sprintf("error reading block file %s for checkpoint sync initialization", fi.blockPath))
}
stateFH, err := os.Open(fi.statePath)
if err != nil {
return errors.Wrap(err, fmt.Sprintf("error reading state file %s for checkpoint sync initialization", fi.statePath))
}
defer func() {
err := stateFH.Close()
if err != nil {
log.Errorf("error while closing checkpoint state input stream: %s", err)
}
}()
serState, err := ioutil.ReadAll(stateFH)
if err != nil {
return errors.Wrap(err, fmt.Sprintf("error reading block file %s for checkpoint sync initialization", fi.statePath))
}
return d.SaveOrigin(ctx, serState, serBlock)
}
var _ Initializer = &FileInitializer{}
func existsAndIsFile(path string) error {
info, err := os.Stat(path)
if err != nil {
msg := fmt.Sprintf("error checking existence of ssz-encoded file %s for checkpoint sync init", path)
return errors.Wrap(err, msg)
}
if info.IsDir() {
return fmt.Errorf("%s is a directory, please specify full path to file", path)
}
return nil
}

View File

@@ -234,7 +234,7 @@ func (s *Service) processBlock(
s.logSyncStatus(genesis, blk.Block(), blkRoot)
parentRoot := bytesutil.ToBytes32(blk.Block().ParentRoot())
if !s.cfg.DB.HasBlock(ctx, parentRoot) && !s.cfg.Chain.HasInitSyncBlock(parentRoot) {
return fmt.Errorf("%w: %#x", errParentDoesNotExist, blk.Block().ParentRoot())
return fmt.Errorf("%w: (in processBlock @ slot %d) %#x", errParentDoesNotExist, blk.Block().Slot(), blk.Block().ParentRoot())
}
return blockReceiver(ctx, blk, blkRoot)
}
@@ -264,7 +264,7 @@ func (s *Service) processBatchedBlocks(ctx context.Context, genesis time.Time,
s.logBatchSyncStatus(genesis, blks, blkRoot)
parentRoot := bytesutil.ToBytes32(firstBlock.Block().ParentRoot())
if !s.cfg.DB.HasBlock(ctx, parentRoot) && !s.cfg.Chain.HasInitSyncBlock(parentRoot) {
return fmt.Errorf("%w: %#x", errParentDoesNotExist, firstBlock.Block().ParentRoot())
return fmt.Errorf("%w: %#x (in processBatchedBlocks @ slot %d)", errParentDoesNotExist, firstBlock.Block().ParentRoot(), firstBlock.Block().Slot())
}
blockRoots := make([][32]byte, len(blks))
blockRoots[0] = blkRoot

View File

@@ -21,6 +21,7 @@ go_library(
"//cmd/beacon-chain/db:go_default_library",
"//cmd/beacon-chain/flags:go_default_library",
"//cmd/beacon-chain/powchain:go_default_library",
"//cmd/beacon-chain/sync/checkpoint:go_default_library",
"//config/features:go_default_library",
"//io/file:go_default_library",
"//io/logs:go_default_library",

View File

@@ -10,7 +10,7 @@ import (
// FlagOptions for blockchain service flag configurations.
func FlagOptions(c *cli.Context) ([]blockchain.Option, error) {
wsp := c.String(flags.WeakSubjectivityCheckpt.Name)
wsp := c.String(flags.WeakSubjectivityCheckpoint.Name)
wsCheckpt, err := helpers.ParseWeakSubjectivityInputString(wsp)
if err != nil {
return nil, err

View File

@@ -165,13 +165,6 @@ var (
Name: "network-id",
Usage: "Sets the network id of the beacon chain.",
}
// WeakSubjectivityCheckpt defines the weak subjectivity checkpoint the node must sync through to defend against long range attacks.
WeakSubjectivityCheckpt = &cli.StringFlag{
Name: "weak-subjectivity-checkpoint",
Usage: "Input in `block_root:epoch_number` format. This guarantees that syncing leads to the given Weak Subjectivity Checkpoint along the canonical chain. " +
"If such a sync is not possible, the node will treat it a critical and irrecoverable failure",
Value: "",
}
// Eth1HeaderReqLimit defines a flag to set the maximum number of headers that a deposit log query can fetch. If none is set, 1000 will be the limit.
Eth1HeaderReqLimit = &cli.Uint64Flag{
Name: "eth1-header-req-limit",
@@ -184,6 +177,14 @@ var (
Usage: "Load a genesis state from ssz file. Testnet genesis files can be found in the " +
"eth2-clients/eth2-testnets repository on github.",
}
// WeakSubjectivityCheckpoint defines the weak subjectivity checkpoint the node must sync through to defend against long range attacks.
WeakSubjectivityCheckpoint = &cli.StringFlag{
Name: "weak-subjectivity-checkpoint",
Usage: "Input in `block_root:epoch_number` format." +
" This guarantees that syncing leads to the given Weak Subjectivity Checkpoint along the canonical chain. " +
"If such a sync is not possible, the node will treat it as a critical and irrecoverable failure",
Value: "",
}
// MinPeersPerSubnet defines a flag to set the minimum number of peers that a node will attempt to peer with for a subnet.
MinPeersPerSubnet = &cli.Uint64Flag{
Name: "minimum-peers-per-subnet",

View File

@@ -8,6 +8,8 @@ import (
"runtime"
runtimeDebug "runtime/debug"
"github.com/prysmaticlabs/prysm/cmd/beacon-chain/sync/checkpoint"
gethlog "github.com/ethereum/go-ethereum/log"
golog "github.com/ipfs/go-log/v2"
joonix "github.com/joonix/log"
@@ -61,7 +63,7 @@ var appFlags = []cli.Flag{
flags.HistoricalSlasherNode,
flags.ChainID,
flags.NetworkID,
flags.WeakSubjectivityCheckpt,
flags.WeakSubjectivityCheckpoint,
flags.Eth1HeaderReqLimit,
flags.GenesisStatePath,
flags.MinPeersPerSubnet,
@@ -119,6 +121,9 @@ var appFlags = []cli.Flag{
cmd.RestoreTargetDirFlag,
cmd.BoltMMapInitialSizeFlag,
cmd.ValidatorMonitorIndicesFlag,
checkpoint.BlockPath,
checkpoint.StatePath,
checkpoint.RemoteURL,
}
func init() {
@@ -243,6 +248,13 @@ func startNode(ctx *cli.Context) error {
node.WithBlockchainFlagOptions(blockchainFlagOpts),
node.WithPowchainFlagOptions(powchainFlagOpts),
}
cptOpts, err := checkpoint.BeaconNodeOptions(ctx)
if err != nil {
return err
}
if cptOpts != nil {
opts = append(opts, cptOpts)
}
beacon, err := node.New(ctx, opts...)
if err != nil {
return err

View File

@@ -0,0 +1,14 @@
load("@prysm//tools/go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["options.go"],
importpath = "github.com/prysmaticlabs/prysm/cmd/beacon-chain/sync/checkpoint",
visibility = ["//visibility:public"],
deps = [
"//beacon-chain/node:go_default_library",
"//beacon-chain/sync/checkpoint:go_default_library",
"@com_github_pkg_errors//:go_default_library",
"@com_github_urfave_cli_v2//:go_default_library",
],
)

View File

@@ -0,0 +1,67 @@
package checkpoint
import (
"fmt"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/beacon-chain/node"
"github.com/prysmaticlabs/prysm/beacon-chain/sync/checkpoint"
"github.com/urfave/cli/v2"
)
var (
// StatePath defines a flag to start the beacon chain from a give genesis state file.
StatePath = &cli.PathFlag{
Name: "checkpoint-state",
Usage: "Rather than syncing from genesis, you can start processing from a ssz-serialized BeaconState+Block." +
" This flag allows you to specify a local file containing the checkpoint BeaconState to load.",
}
// BlockPath is required when using StatePath to also provide the latest integrated block.
BlockPath = &cli.PathFlag{
Name: "checkpoint-block",
Usage: "Rather than syncing from genesis, you can start processing from a ssz-serialized BeaconState+Block." +
" This flag allows you to specify a local file containing the checkpoint Block to load.",
}
RemoteURL = &cli.StringFlag{
Name: "checkpoint-sync-url",
Usage: "URL of a synced beacon node to trust in obtaining checkpoint sync data. " +
"as an additional safety measure, it is strongly recommended to only use this option in conjunction with " +
"--weak-subjectivity-checkpoint flag",
}
)
// BeaconNodeOptions is responsible for determining if the checkpoint sync options have been used, and if so,
// reading the block and state ssz-serialized values from the filesystem locations specified and preparing a
// checkpoint.Initializer, which uses the provided io.ReadClosers to initialize the beacon node database.
func BeaconNodeOptions(c *cli.Context) (node.Option, error) {
blockPath := c.Path(BlockPath.Name)
statePath := c.Path(StatePath.Name)
remoteURL := c.String(RemoteURL.Name)
if remoteURL != "" {
return func(node *node.BeaconNode) error {
var err error
node.CheckpointInitializer, err = checkpoint.NewAPIInitializer(remoteURL)
if err != nil {
return errors.Wrap(err, "error while constructing beacon node api client for checkpoint sync")
}
return nil
}, nil
}
if blockPath == "" && statePath == "" {
return nil, nil
}
if blockPath != "" && statePath == "" {
return nil, fmt.Errorf("--checkpoint-block specified, but not --checkpoint-state. both are required")
}
if blockPath == "" && statePath != "" {
return nil, fmt.Errorf("--checkpoint-state specified, but not --checkpoint-block. both are required")
}
return func(node *node.BeaconNode) (err error) {
node.CheckpointInitializer, err = checkpoint.NewFileInitializer(blockPath, statePath)
if err != nil {
return errors.Wrap(err, "error preparing to initialize checkpoint from local ssz files")
}
return nil
}, nil
}

View File

@@ -119,7 +119,7 @@ var appHelpFlagGroups = []flagGroup{
flags.HistoricalSlasherNode,
flags.ChainID,
flags.NetworkID,
flags.WeakSubjectivityCheckpt,
flags.WeakSubjectivityCheckpoint,
flags.Eth1HeaderReqLimit,
flags.GenesisStatePath,
flags.MinPeersPerSubnet,

20
cmd/prysmctl/BUILD.bazel Normal file
View File

@@ -0,0 +1,20 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary")
load("@prysm//tools/go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["main.go"],
importpath = "github.com/prysmaticlabs/prysm/cmd/prysmctl",
visibility = ["//visibility:private"],
deps = [
"//cmd/prysmctl/checkpoint:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
"@com_github_urfave_cli_v2//:go_default_library",
],
)
go_binary(
name = "prysmctl",
embed = [":go_default_library"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,23 @@
load("@prysm//tools/go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"checkpoint.go",
"latest.go",
"save.go",
],
importpath = "github.com/prysmaticlabs/prysm/cmd/prysmctl/checkpoint",
visibility = ["//visibility:public"],
deps = [
"//api/client/openapi:go_default_library",
"//beacon-chain/core/helpers:go_default_library",
"//config/params:go_default_library",
"//proto/sniff:go_default_library",
"//time/slots:go_default_library",
"@com_github_pkg_errors//:go_default_library",
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
"@com_github_urfave_cli_v2//:go_default_library",
],
)

View File

@@ -0,0 +1,15 @@
package checkpoint
import "github.com/urfave/cli/v2"
var Commands = []*cli.Command{
{
Name: "checkpoint",
Aliases: []string{"cpt"},
Usage: "commands for managing checkpoint syncing",
Subcommands: []*cli.Command{
latestCmd,
saveCmd,
},
},
}

View File

@@ -0,0 +1,140 @@
package checkpoint
import (
"context"
"fmt"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/api/client/openapi"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/config/params"
"github.com/prysmaticlabs/prysm/proto/sniff"
"github.com/prysmaticlabs/prysm/time/slots"
"io"
"net"
"net/url"
"strconv"
"time"
//"time"
//"github.com/prysmaticlabs/prysm/api/client/openapi"
log "github.com/sirupsen/logrus"
"github.com/urfave/cli/v2"
)
var latestFlags = struct {
BeaconNodeHost string
Timeout string
}{}
var latestCmd = &cli.Command{
Name: "latest",
Usage: "Compute the latest weak subjectivity checkpoint (block_root:epoch) using trusted server data.",
Action: cliActionLatest,
Flags: []cli.Flag{
&cli.StringFlag{
Name: "beacon-node-host",
Usage: "host:port for beacon node to query",
Destination: &latestFlags.BeaconNodeHost,
Value: "http://localhost:3500",
},
&cli.StringFlag{
Name: "http-timeout",
Usage: "timeout for http requests made to beacon-node-url (uses duration format, ex: 2m31s). default: 2m",
Destination: &latestFlags.Timeout,
Value: "2m",
},
},
}
func setupClient() (*openapi.Client, error) {
f := latestFlags
log.Printf("--beacon-node-url=%s", f.BeaconNodeHost)
opts := make([]openapi.ClientOpt, 0)
timeout, err := time.ParseDuration(f.Timeout)
if err != nil {
return nil, err
}
opts = append(opts, openapi.WithTimeout(timeout))
validatedHost, err := validHostname(latestFlags.BeaconNodeHost)
if err != nil {
return nil, err
}
log.Printf("host:port=%s", validatedHost)
client, err := openapi.NewClient(validatedHost, opts...)
if err != nil {
return nil, err
}
return client, nil
}
func cliActionLatest(_ *cli.Context) error {
ctx := context.Background()
client, err := setupClient()
if err != nil {
log.Fatalf(err.Error())
}
_, err = openapi.DownloadOriginData(ctx, client)
if err != nil {
log.Fatalf(err.Error())
}
return nil
}
func _cliActionLatest(_ *cli.Context) error {
ctx := context.Background()
client, err := setupClient()
if err != nil {
return err
}
stateReader, err := client.GetStateById(openapi.StateIdHead)
if err != nil {
return errors.Wrap(err, "error fetching head state")
}
stateBytes, err := io.ReadAll(stateReader)
if err != nil {
return errors.Wrap(err, "failed to read response body for get head state api call")
}
log.Printf("state response byte len=%d", len(stateBytes))
state, err := sniff.BeaconState(stateBytes)
if err != nil {
return errors.Wrap(err, "error unmarshaling state to correct version")
}
cf, err := sniff.ConfigForkForState(stateBytes)
if err != nil {
return errors.Wrap(err, "error detecting chain config for beacon state")
}
params.OverrideBeaconConfig(cf.Config)
epoch, err := helpers.LatestWeakSubjectivityEpoch(ctx, state)
if err != nil {
return errors.Wrap(err, "error computing the weak subjectivity epoch from head state")
}
bSlot, err := slots.EpochStart(epoch)
if err != nil {
return errors.Wrap(err, fmt.Sprintf("Error computing first slot of epoch=%d", epoch))
}
root, err := client.GetBlockRoot(strconv.Itoa(int(bSlot)))
if err != nil {
return errors.Wrap(err, fmt.Sprintf("error requesting block root from api for slot=%d", bSlot))
}
wsFlag := fmt.Sprintf("--weak-subjectivity-checkpoint=%#x:%d", root, epoch)
log.Printf("latest weak subjectivity checkpoint verification flag:\n%s", wsFlag)
return nil
}
func validHostname(h string) (string, error) {
// try to parse as url (being permissive)
u, err := url.Parse(h)
if err == nil && u.Host != "" {
return u.Host, nil
}
// try to parse as host:port
host, port, err := net.SplitHostPort(h)
if err != nil {
return "", err
}
return fmt.Sprintf("%s:%s", host, port), nil
}

View File

@@ -0,0 +1,199 @@
package checkpoint
import (
"context"
"fmt"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/config/params"
"github.com/prysmaticlabs/prysm/time/slots"
"io"
"os"
"time"
"github.com/pkg/errors"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/api/client/openapi"
"github.com/prysmaticlabs/prysm/proto/sniff"
log "github.com/sirupsen/logrus"
"github.com/urfave/cli/v2"
)
var saveFlags = struct {
BeaconNodeHost string
Timeout string
}{}
var saveCmd = &cli.Command{
Name: "save",
Usage: "query for the current weak subjectivity period epoch, then download the corresponding state and block. To be used for checkpoint sync.",
Action: cliActionSave,
Flags: []cli.Flag{
&cli.StringFlag{
Name: "beacon-node-host",
Usage: "host:port for beacon node connection",
Destination: &saveFlags.BeaconNodeHost,
Value: "localhost:3500",
},
&cli.StringFlag{
Name: "http-timeout",
Usage: "timeout for http requests made to beacon-node-url (uses duration format, ex: 2m31s). default: 2m",
Destination: &saveFlags.Timeout,
Value: "4m",
},
},
}
func cliActionSave(_ *cli.Context) error {
f := saveFlags
opts := make([]openapi.ClientOpt, 0)
log.Printf("--beacon-node-url=%s", f.BeaconNodeHost)
timeout, err := time.ParseDuration(f.Timeout)
if err != nil {
return err
}
opts = append(opts, openapi.WithTimeout(timeout))
client, err := openapi.NewClient(saveFlags.BeaconNodeHost, opts...)
if err != nil {
return err
}
return saveCheckpoint(client)
}
func saveCheckpoint(client *openapi.Client) error {
ctx := context.Background()
headReader, err := client.GetStateById(openapi.StateIdHead)
headBytes, err := io.ReadAll(headReader)
if err != nil {
return errors.Wrap(err, "failed to read response body for get head state api call")
}
log.Printf("state response byte len=%d", len(headBytes))
headState, err := sniff.BeaconState(headBytes)
if err != nil {
return errors.Wrap(err, "error unmarshaling state to correct version")
}
cf, err := sniff.ConfigForkForState(headBytes)
if err != nil {
return errors.Wrap(err, "error detecting chain config for beacon state")
}
log.Printf("detected supported config for state & block version detection, name=%s, fork=%s", cf.ConfigName.String(), cf.Fork)
// LatestWeakSubjectivityEpoch uses package-level vars from the params package, so we need to override it
params.OverrideBeaconConfig(cf.Config)
epoch, err := helpers.LatestWeakSubjectivityEpoch(ctx, headState)
if err != nil {
return errors.Wrap(err, "error computing the weak subjectivity epoch from head state")
}
// use first slot of the epoch for the block slot
bSlot, err := slots.EpochStart(epoch)
if err != nil {
return errors.Wrap(err, fmt.Sprintf("Error computing first slot of epoch=%d", epoch))
}
// assigning this variable to make it extra obvious that the state slot is different
sSlot := bSlot + 1
// using the state at (slot % 32 = 1) instead of the epoch boundary ensures the
// next block applied to the state will have the block at the weak subjectivity checkpoint
// as its parent, satisfying prysm's sync code current verification that the parent block is present in the db
log.Printf("weak subjectivity epoch computed as %d. download block@slot=%d, state@slot=%d", epoch, bSlot, sSlot)
stateReader, err := client.GetStateBySlot(uint64(sSlot))
if err != nil {
return err
}
stateBytes, err := io.ReadAll(stateReader)
if err != nil {
return errors.Wrap(err, fmt.Sprintf("failed to read response body for state at slot %d from api", sSlot))
}
log.Printf("state response byte len=%d", len(stateBytes))
state, err := sniff.BeaconStateForConfigFork(stateBytes, cf)
if err != nil {
return errors.Wrap(err, fmt.Sprintf("unmarshaling state using auto-detected schema failed for state at slot %d", sSlot))
}
stateRoot, err := state.HashTreeRoot(ctx)
if err != nil {
return err
}
log.Printf("retrieved state for checkpoint at slot %d, w/ root=%#x", sSlot, stateRoot)
latestBlockRoot, err := state.LatestBlockHeader().HashTreeRoot()
if err != nil {
return err
}
// Fork schedule is used to query for chain config metadata that is used to unmarshal values with the correct type
fs, err := client.GetForkSchedule()
if err != nil {
return err
}
// get the version and find the config fork
version, err := fs.VersionForEpoch(epoch)
if err != nil {
return err
}
cf, err = sniff.FindConfigFork(version)
if err != nil {
return errors.Wrap(err, "beacon node provided an unrecognized fork schedule")
}
blockReader, err := client.GetBlockBySlot(uint64(bSlot))
if err != nil {
return errors.Wrap(err, fmt.Sprintf("failed to retrieve block bytes for slot %d from api", bSlot))
}
blockBytes, err := io.ReadAll(blockReader)
if err != nil {
return errors.Wrap(err, fmt.Sprintf("failed to read response body for block at slot %d from api", bSlot))
}
block, err := sniff.BlockForConfigFork(blockBytes, cf)
if err != nil {
return errors.Wrap(err, "failed to detect config/version from block inspection")
}
blockRoot, err := block.Block().HashTreeRoot()
if err != nil {
return err
}
log.Printf("retrieved block at slot %d with root=%#x", bSlot, blockRoot)
blockStateRoot := block.Block().StateRoot()
log.Printf("retrieved block has state root=%#x", blockStateRoot)
// we only want to provide checkpoints+state pairs where the state integrates the checkpoint block as its latest root
// this ensures that when syncing begins from the provided state, the next block in the chain can find the
// latest block in the db.
if blockRoot == latestBlockRoot {
log.Printf("State latest_block_header root matches block root=%#x", latestBlockRoot)
} else {
return fmt.Errorf("fatal error, state latest_block_header root=%#x, does not match block root=%#x", latestBlockRoot, blockRoot)
}
bb, err := block.MarshalSSZ()
if err != nil {
return err
}
blockPath := fname("block", cf, bSlot, blockRoot)
log.Printf("saving ssz-encoded block to to %s", blockPath)
err = os.WriteFile(blockPath, bb, 0600)
if err != nil {
return err
}
sb, err := state.MarshalSSZ()
if err != nil {
return err
}
statePath := fname("state", cf, sSlot, stateRoot)
log.Printf("saving ssz-encoded state to to %s", statePath)
err = os.WriteFile(statePath, sb, 0600)
if err != nil {
return err
}
fmt.Println("To validate that your client is using this checkpoint, specify the following flag when starting prysm:")
fmt.Printf("--weak-subjectivity-checkpoint=%#x:%d\n\n", blockRoot, epoch)
fmt.Println("To sync a new beacon node starting from the checkpoint state, you may specify the following flags (assuming the files are in your current working directory)")
fmt.Printf("--checkpoint-block=%s --checkpoint-state=%s\n", blockPath, statePath)
return nil
}
func fname(prefix string, cf *sniff.ConfigFork, slot types.Slot, root [32]byte) string {
return fmt.Sprintf("%s_%s_%s_%d-%#x.ssz", prefix, cf.ConfigName.String(), cf.Fork.String(), slot, root)
}

25
cmd/prysmctl/main.go Normal file
View File

@@ -0,0 +1,25 @@
package main
import (
"os"
"github.com/prysmaticlabs/prysm/cmd/prysmctl/checkpoint"
log "github.com/sirupsen/logrus"
"github.com/urfave/cli/v2"
)
var prysmctlCommands []*cli.Command
func main() {
app := &cli.App{
Commands: prysmctlCommands,
}
err := app.Run(os.Args)
if err != nil {
log.Fatal(err)
}
}
func init() {
prysmctlCommands = append(prysmctlCommands, checkpoint.Commands...)
}

View File

@@ -30,6 +30,8 @@ func WrapFlags(flags []cli.Flag) []cli.Flag {
f = altsrc.NewUint64Flag(t)
case *cli.UintFlag:
f = altsrc.NewUintFlag(t)
case *cli.PathFlag:
f = altsrc.NewPathFlag(t)
case *cli.Int64Flag:
// Int64Flag does not work. See https://github.com/prysmaticlabs/prysm/issues/6478
panic(fmt.Sprintf("unsupported flag type type %T", f))

View File

@@ -25,6 +25,7 @@ go_library(
"@com_github_ethereum_go_ethereum//common:go_default_library",
"@com_github_ethereum_go_ethereum//params:go_default_library",
"@com_github_mohae_deepcopy//:go_default_library",
"@com_github_pkg_errors//:go_default_library",
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
"@in_gopkg_yaml_v2//:go_default_library",
@@ -53,6 +54,7 @@ go_test(
":go_default_library",
"//testing/assert:go_default_library",
"//testing/require:go_default_library",
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
"@in_gopkg_yaml_v2//:go_default_library",
"@io_bazel_rules_go//go/tools/bazel:go_default_library",

View File

@@ -2,9 +2,12 @@
package params
import (
"fmt"
"sort"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/pkg/errors"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
)
@@ -197,3 +200,56 @@ func (b *BeaconChainConfig) InitializeForkSchedule() {
// Set Altair fork data.
b.ForkVersionSchedule[bytesutil.ToBytes4(b.AltairForkVersion)] = b.AltairForkEpoch
}
// ForkScheduleEntry is a Version+Epoch tuple for sorted storage in an OrderedForkSchedule
type ForkScheduleEntry struct {
Version [4]byte
Epoch types.Epoch
}
// OrderedForkSchedule provides a type that can be used to sort the fork schedule and find the Version
// the chain should be at for a given epoch (via VersionForEpoch).
type OrderedForkSchedule []ForkScheduleEntry
// Len implements the Len method of sort.Interface
func (o OrderedForkSchedule) Len() int { return len(o) }
// Swap implements the Swap method of sort.Interface
func (o OrderedForkSchedule) Swap(i, j int) { o[i], o[j] = o[j], o[i] }
// Less implements the Less method of sort.Interface
func (o OrderedForkSchedule) Less(i, j int) bool { return o[i].Epoch < o[j].Epoch }
var VersionForEpochNotFound = errors.New("could not find an entry in the ForkVersionSchedule")
// VersionForEpoch finds the Version of the last entry in the last that comes before the given epoch
func (o OrderedForkSchedule) VersionForEpoch(epoch types.Epoch) ([4]byte, error) {
for i := range o {
// moving from lowest to highest, only consider epochs that start at or before the slot
if epoch < o[i].Epoch {
continue
}
// `i+1 == len(o)`: at last element, don't need to check if there is another fork schedule entry in between
// `o[i+1].Epoch > fse.Epoch`: next version's epoch is past the epoch in question, so `i` is correct
if i+1 == len(o) || epoch < o[i+1].Epoch {
return o[i].Version, nil
}
}
var nope [4]byte
return nope, errors.Wrap(VersionForEpochNotFound, fmt.Sprintf("no epoch in list <= %d", epoch))
}
// Converts the ForkVersionSchedule map into a list of Version+Epoch values, ordered by Epoch from lowest to highest.
// See docs for OrderedForkSchedule for more detail on what you can do with this type.
func (b *BeaconChainConfig) OrderedForkSchedule() OrderedForkSchedule {
ofs := make(OrderedForkSchedule, 0)
for version, epoch := range b.ForkVersionSchedule {
fse := ForkScheduleEntry{
Version: version,
Epoch: epoch,
}
ofs = append(ofs, fse)
}
sort.Sort(ofs)
return ofs
}

View File

@@ -1,9 +1,12 @@
package params_test
import (
"math"
"testing"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/config/params"
"github.com/prysmaticlabs/prysm/testing/require"
)
// Test cases can be executed in an arbitrary order. TestOverrideBeaconConfigTestTeardown checks
@@ -44,3 +47,97 @@ func TestConfig_DataRace(t *testing.T) {
}()
}
}
func TestOrderedConfigSchedule(t *testing.T) {
params.SetupTestConfigCleanup(t)
for name, cfg := range params.AllConfigs() {
t.Run(name.String(), func(t *testing.T) {
prevVersion := [4]byte{0, 0, 0, 0}
// epoch 0 is genesis, and it's a uint so can't make it -1
// so we use a pointer to detect the boundary condition and skip it
var prevEpoch *types.Epoch
for _, fse := range cfg.OrderedForkSchedule() {
// copy loop variable so we can take the address of fields
f := fse
if prevEpoch == nil {
prevEpoch = &f.Epoch
prevVersion = f.Version
continue
}
if *prevEpoch > f.Epoch {
t.Errorf("Epochs out of order! %#x/%d before %#x/%d", f.Version, f.Epoch, prevVersion, prevEpoch)
}
prevEpoch = &f.Epoch
prevVersion = f.Version
}
})
}
bc := testForkVersionScheduleBCC()
ofs := bc.OrderedForkSchedule()
for i := range ofs {
if ofs[i].Epoch != types.Epoch(math.Pow(2, float64(i))) {
t.Errorf("expected %dth element of list w/ epoch=%d, got=%d. list=%v", i, types.Epoch(2^i), ofs[i].Epoch, ofs)
}
}
}
func TestVersionForEpoch(t *testing.T) {
bc := testForkVersionScheduleBCC()
ofs := bc.OrderedForkSchedule()
testCases := []struct {
name string
version [4]byte
epoch types.Epoch
err error
}{
{
name: "found between versions",
version: [4]byte{2, 1, 2, 3},
epoch: types.Epoch(7),
},
{
name: "found at end",
version: [4]byte{4, 1, 2, 3},
epoch: types.Epoch(100),
},
{
name: "found at start",
version: [4]byte{0, 1, 2, 3},
epoch: types.Epoch(1),
},
{
name: "found at boundary",
version: [4]byte{1, 1, 2, 3},
epoch: types.Epoch(2),
},
{
name: "not found before",
epoch: types.Epoch(0),
err: params.VersionForEpochNotFound,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
v, err := ofs.VersionForEpoch(tc.epoch)
if tc.err == nil {
require.NoError(t, err)
} else {
require.ErrorIs(t, err, tc.err)
}
require.Equal(t, tc.version, v)
})
}
}
func testForkVersionScheduleBCC() *params.BeaconChainConfig {
return &params.BeaconChainConfig{
ForkVersionSchedule: map[[4]byte]types.Epoch{
{1, 1, 2, 3}: types.Epoch(2),
{0, 1, 2, 3}: types.Epoch(1),
{4, 1, 2, 3}: types.Epoch(16),
{3, 1, 2, 3}: types.Epoch(8),
{2, 1, 2, 3}: types.Epoch(4),
},
}
}

View File

@@ -1,5 +1,11 @@
package params
import (
"math"
types "github.com/prysmaticlabs/eth2-types"
)
const altairE2EForkEpoch = 6
// UseE2EConfig for beacon chain services.
@@ -40,5 +46,17 @@ func E2ETestConfig() *BeaconChainConfig {
// Prysm constants.
e2eConfig.ConfigName = ConfigNames[EndToEnd]
e2eConfig.GenesisForkVersion = []byte{0x00, 0x00, 0xFF, 0xFF}
e2eConfig.AltairForkVersion = []byte{0x1, 0x0, 0xFF, 0xFF}
e2eConfig.ShardingForkVersion = []byte{0x3, 0x0, 0xFF, 0xFF}
e2eConfig.MergeForkVersion = []byte{0x2, 0x0, 0xFF, 0xFF}
e2eConfig.ForkVersionSchedule = map[[4]byte]types.Epoch{
{0x00, 0x00, 0xFF, 0xFF}: 0,
{0x1, 0x0, 0xFF, 0xFF}: math.MaxUint64,
{0x3, 0x0, 0xFF, 0xFF}: math.MaxUint64,
{0x2, 0x0, 0xFF, 0xFF}: math.MaxUint64,
}
return e2eConfig
}

View File

@@ -18,4 +18,54 @@ var ConfigNames = map[ConfigName]string{
}
// ConfigName enum describes the type of known network in use.
type ConfigName = int
type ConfigName int
func (n ConfigName) String() string {
s, ok := ConfigNames[n]
if !ok {
return "undefined"
}
return s
}
func AllConfigs() map[ConfigName]*BeaconChainConfig {
all := make(map[ConfigName]*BeaconChainConfig)
for name := range ConfigNames {
var cfg *BeaconChainConfig
switch name {
case Mainnet:
cfg = MainnetConfig()
case Prater:
cfg = PraterConfig()
case Pyrmont:
cfg = PyrmontConfig()
case Minimal:
cfg = MinimalSpecConfig()
case EndToEnd:
cfg = E2ETestConfig()
}
cfg = cfg.Copy()
cfg.InitializeForkSchedule()
all[name] = cfg
}
return all
}
type ForkName int
const (
ForkGenesis ForkName = iota
ForkAltair
ForkMerge
)
func (n ForkName) String() string {
switch n {
case ForkGenesis:
return "genesis"
case ForkAltair:
return "altair"
}
return "undefined"
}

View File

@@ -55,7 +55,7 @@ var file_proto_eth_service_beacon_chain_service_proto_rawDesc = []byte{
0x32, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x21, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f,
0x76, 0x32, 0x2f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65,
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x32, 0xe8, 0x22, 0x0a, 0x0b, 0x42, 0x65, 0x61, 0x63,
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x32, 0xf6, 0x23, 0x0a, 0x0b, 0x42, 0x65, 0x61, 0x63,
0x6f, 0x6e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x12, 0x6f, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x47, 0x65,
0x6e, 0x65, 0x73, 0x69, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x20, 0x2e,
@@ -63,288 +63,296 @@ var file_proto_eth_service_beacon_chain_service_proto_rawDesc = []byte{
0x47, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
0x27, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x21, 0x12, 0x1f, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e,
0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e,
0x2f, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x12, 0x89, 0x01, 0x0a, 0x0c, 0x47, 0x65, 0x74,
0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x1d, 0x2e, 0x65, 0x74, 0x68, 0x65,
0x2f, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x12, 0x8b, 0x01, 0x0a, 0x13, 0x47, 0x65, 0x74,
0x57, 0x65, 0x61, 0x6b, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79,
0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72,
0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x65, 0x61, 0x6b, 0x53,
0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x22, 0x31, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2b, 0x12, 0x29, 0x2f, 0x69, 0x6e,
0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65,
0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x77, 0x65, 0x61, 0x6b, 0x5f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63,
0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x12, 0x89, 0x01, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x53, 0x74,
0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x1d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65,
0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75,
0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f,
0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x36, 0x82, 0xd3, 0xe4, 0x93,
0x02, 0x30, 0x12, 0x2e, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74,
0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x73, 0x74, 0x61, 0x74,
0x65, 0x73, 0x2f, 0x7b, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f,
0x6f, 0x74, 0x12, 0x89, 0x01, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x46,
0x6f, 0x72, 0x6b, 0x12, 0x1d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65,
0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x1a, 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74,
0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x46, 0x6f, 0x72, 0x6b, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x36, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x30, 0x12, 0x2e,
0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31,
0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x73, 0x2f, 0x7b,
0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x66, 0x6f, 0x72, 0x6b, 0x12, 0xb1,
0x01, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x43, 0x68,
0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x1d, 0x2e, 0x65, 0x74, 0x68, 0x65,
0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74,
0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72,
0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72,
0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65,
0x52, 0x6f, 0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x36, 0x82, 0xd3,
0xe4, 0x93, 0x02, 0x30, 0x12, 0x2e, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f,
0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x73, 0x74,
0x61, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f,
0x72, 0x6f, 0x6f, 0x74, 0x12, 0x89, 0x01, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74,
0x65, 0x46, 0x6f, 0x72, 0x6b, 0x12, 0x1d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d,
0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e,
0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x46, 0x6f, 0x72, 0x6b,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x36, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x30,
0x12, 0x2e, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f,
0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x73,
0x2f, 0x7b, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x66, 0x6f, 0x72, 0x6b,
0x12, 0xb1, 0x01, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79,
0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x1d, 0x2e, 0x65, 0x74,
0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74,
0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x65, 0x74, 0x68,
0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61,
0x74, 0x65, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70,
0x6f, 0x69, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x46, 0x82, 0xd3,
0xe4, 0x93, 0x02, 0x40, 0x12, 0x3e, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f,
0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x73, 0x74,
0x61, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f,
0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f,
0x69, 0x6e, 0x74, 0x73, 0x12, 0xa1, 0x01, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c,
0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x27, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65,
0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56,
0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x1a, 0x28, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e,
0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f,
0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3c, 0x82, 0xd3, 0xe4, 0x93,
0x02, 0x36, 0x12, 0x34, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74,
0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69,
0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x46, 0x82, 0xd3, 0xe4, 0x93,
0x02, 0x40, 0x12, 0x3e, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74,
0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x73, 0x74, 0x61, 0x74,
0x65, 0x73, 0x2f, 0x7b, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x76, 0x61,
0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x12, 0xac, 0x01, 0x0a, 0x0c, 0x47, 0x65, 0x74,
0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x26, 0x2e, 0x65, 0x74, 0x68, 0x65,
0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74,
0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x1a, 0x27, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68,
0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74,
0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4b, 0x82, 0xd3, 0xe4, 0x93,
0x02, 0x45, 0x12, 0x43, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74,
0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x73, 0x74, 0x61, 0x74,
0x65, 0x73, 0x2f, 0x7b, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x76, 0x61,
0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x2f, 0x7b, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61,
0x74, 0x6f, 0x72, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0xb4, 0x01, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74,
0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65,
0x73, 0x12, 0x29, 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, 0x61, 0x6c,
0x61, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 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, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x44, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3e,
0x12, 0x3c, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f,
0x65, 0x73, 0x2f, 0x7b, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x66, 0x69,
0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e,
0x74, 0x73, 0x12, 0xa1, 0x01, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64,
0x61, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x27, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d,
0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c,
0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28,
0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31,
0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x36,
0x12, 0x34, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f,
0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x73,
0x2f, 0x7b, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x76, 0x61, 0x6c, 0x69,
0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12, 0xa1,
0x01, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65,
0x73, 0x12, 0x27, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68,
0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74,
0x65, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x65, 0x74, 0x68,
0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61,
0x74, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x36, 0x12, 0x34, 0x2f, 0x69,
0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62,
0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x73, 0x74,
0x61, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65,
0x65, 0x73, 0x12, 0xb2, 0x01, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x43,
0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x12, 0x2b, 0x2e, 0x65, 0x74, 0x68, 0x65,
0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x74, 0x61, 0x74,
0x65, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75,
0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x79,
0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x41, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3b, 0x12, 0x39, 0x2f, 0x69,
0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62,
0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x73, 0x74,
0x61, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x63, 0x6f, 0x6d,
0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x12, 0x88, 0x01, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74,
0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x24, 0x2e, 0x65,
0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42,
0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x1a, 0x25, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74,
0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72,
0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x27, 0x82, 0xd3, 0xe4, 0x93, 0x02,
0x21, 0x12, 0x1f, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68,
0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65,
0x72, 0x73, 0x12, 0x89, 0x01, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48,
0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x1d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d,
0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e,
0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64,
0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x32, 0x82, 0xd3, 0xe4, 0x93,
0x02, 0x2c, 0x12, 0x2a, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74,
0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x68, 0x65, 0x61, 0x64,
0x65, 0x72, 0x73, 0x2f, 0x7b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x7f,
0x0a, 0x0b, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x2d, 0x2e,
0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e,
0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63,
0x6b, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x56, 0x32, 0x1a, 0x16, 0x2e, 0x67,
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45,
0x6d, 0x70, 0x74, 0x79, 0x22, 0x29, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x23, 0x22, 0x1e, 0x2f, 0x69,
0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62,
0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x3a, 0x01, 0x2a, 0x12,
0x89, 0x01, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74,
0x12, 0x1d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e,
0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76,
0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x22, 0x36, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x30, 0x12, 0x2e, 0x2f, 0x69, 0x6e,
0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65,
0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2f, 0x7b, 0x62, 0x6c, 0x6f,
0x63, 0x6b, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6f, 0x74, 0x12, 0x7c, 0x0a, 0x08, 0x47,
0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x1d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65,
0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75,
0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x31, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2b, 0x12, 0x29,
0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x12, 0xac, 0x01, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x56, 0x61,
0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x26, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65,
0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56,
0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
0x27, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76,
0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x45,
0x12, 0x43, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f,
0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x73,
0x2f, 0x7b, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x76, 0x61, 0x6c, 0x69,
0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x2f, 0x7b, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f,
0x72, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0xb4, 0x01, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61,
0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12,
0x29, 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, 0x61, 0x6c, 0x61, 0x6e,
0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 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, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x44, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3e, 0x12, 0x3c,
0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31,
0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2f, 0x7b,
0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x86, 0x01, 0x0a, 0x0b, 0x47, 0x65,
0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x53, 0x5a, 0x12, 0x1d, 0x2e, 0x65, 0x74, 0x68, 0x65,
0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63,
0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72,
0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b,
0x53, 0x53, 0x5a, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x35, 0x82, 0xd3, 0xe4,
0x93, 0x02, 0x2f, 0x12, 0x2d, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65,
0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x62, 0x6c, 0x6f,
0x63, 0x6b, 0x73, 0x2f, 0x7b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x73,
0x73, 0x7a, 0x12, 0x82, 0x01, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x56,
0x32, 0x12, 0x1f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68,
0x2e, 0x76, 0x32, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x56, 0x32, 0x1a, 0x20, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74,
0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x56, 0x32, 0x22, 0x31, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2b, 0x12, 0x29, 0x2f, 0x69,
0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x32, 0x2f, 0x62,
0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2f, 0x7b, 0x62, 0x6c,
0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x8c, 0x01, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x42,
0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x53, 0x5a, 0x56, 0x32, 0x12, 0x1f, 0x2e, 0x65, 0x74, 0x68, 0x65,
0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x6c, 0x6f, 0x63,
0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x32, 0x1a, 0x23, 0x2e, 0x65, 0x74, 0x68,
0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x6c, 0x6f,
0x63, 0x6b, 0x53, 0x53, 0x5a, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x56, 0x32, 0x22,
0x35, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2f, 0x12, 0x2d, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e,
0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x32, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e,
0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2f, 0x7b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69,
0x64, 0x7d, 0x2f, 0x73, 0x73, 0x7a, 0x12, 0xa2, 0x01, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x42,
0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73,
0x12, 0x1d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e,
0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
0x2a, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76,
0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3e, 0x82, 0xd3, 0xe4,
0x93, 0x02, 0x38, 0x12, 0x36, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65,
0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x62, 0x6c, 0x6f,
0x63, 0x6b, 0x73, 0x2f, 0x7b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x61,
0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x9e, 0x01, 0x0a, 0x14,
0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x73, 0x12, 0x28, 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, 0x73, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29,
0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x73, 0x2f, 0x7b,
0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61,
0x74, 0x6f, 0x72, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12, 0xa1, 0x01, 0x0a,
0x0e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x12,
0x27, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76,
0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65,
0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72,
0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65,
0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x22, 0x3c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x36, 0x12, 0x34, 0x2f, 0x69, 0x6e, 0x74,
0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61,
0x63, 0x6f, 0x6e, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x73, 0x74, 0x61, 0x74,
0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73,
0x12, 0xb2, 0x01, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d,
0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x12, 0x2b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65,
0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53,
0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e,
0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x79, 0x6e, 0x63,
0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x22, 0x41, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3b, 0x12, 0x39, 0x2f, 0x69, 0x6e, 0x74,
0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61,
0x63, 0x6f, 0x6e, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x73, 0x74, 0x61, 0x74,
0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69,
0x74, 0x74, 0x65, 0x65, 0x73, 0x12, 0x88, 0x01, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x6c,
0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x24, 0x2e, 0x65, 0x74, 0x68,
0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f,
0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x1a, 0x25, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e,
0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x52,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x27, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x21, 0x12,
0x1f, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76,
0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73,
0x12, 0x89, 0x01, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61,
0x64, 0x65, 0x72, 0x12, 0x1d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65,
0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x1a, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74,
0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x32, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2c,
0x12, 0x2a, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f,
0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72,
0x73, 0x2f, 0x7b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x7f, 0x0a, 0x0b,
0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x2d, 0x2e, 0x65, 0x74,
0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x69,
0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43,
0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x56, 0x32, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f,
0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70,
0x74, 0x79, 0x22, 0x29, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x23, 0x22, 0x1e, 0x2f, 0x69, 0x6e, 0x74,
0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61,
0x63, 0x6f, 0x6e, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x89, 0x01,
0x0a, 0x0c, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x1d,
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, 0x73, 0x50, 0x6f, 0x6f,
0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x31, 0x82, 0xd3, 0xe4, 0x93, 0x02,
0x2b, 0x12, 0x29, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68,
0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x70, 0x6f, 0x6f, 0x6c, 0x2f,
0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x8e, 0x01, 0x0a,
0x12, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x73, 0x12, 0x2a, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65,
0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x41, 0x74, 0x74, 0x65,
0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x34, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2e, 0x22,
0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e,
0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e,
0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x22, 0x36, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x30, 0x12, 0x2e, 0x2f, 0x69, 0x6e, 0x74, 0x65,
0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63,
0x6f, 0x6e, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2f, 0x7b, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6f, 0x74, 0x12, 0x7c, 0x0a, 0x08, 0x47, 0x65, 0x74,
0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x1d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d,
0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e,
0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x31, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2b, 0x12, 0x29, 0x2f, 0x69,
0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62,
0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2f, 0x7b, 0x62, 0x6c,
0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x86, 0x01, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x42,
0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x53, 0x5a, 0x12, 0x1d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65,
0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75,
0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x53,
0x5a, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x35, 0x82, 0xd3, 0xe4, 0x93, 0x02,
0x2f, 0x12, 0x2d, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68,
0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
0x73, 0x2f, 0x7b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x73, 0x73, 0x7a,
0x12, 0x82, 0x01, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x56, 0x32, 0x12,
0x1f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76,
0x32, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x32,
0x1a, 0x20, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e,
0x76, 0x32, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x56, 0x32, 0x22, 0x31, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2b, 0x12, 0x29, 0x2f, 0x69, 0x6e, 0x74,
0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x32, 0x2f, 0x62, 0x65, 0x61,
0x63, 0x6f, 0x6e, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2f, 0x7b, 0x62, 0x6c, 0x6f, 0x63,
0x6b, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x8c, 0x01, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f,
0x63, 0x6b, 0x53, 0x53, 0x5a, 0x56, 0x32, 0x12, 0x1f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65,
0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x32, 0x1a, 0x23, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72,
0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b,
0x53, 0x53, 0x5a, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x56, 0x32, 0x22, 0x35, 0x82,
0xd3, 0xe4, 0x93, 0x02, 0x2f, 0x12, 0x2d, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c,
0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x32, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x62,
0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2f, 0x7b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x64, 0x7d,
0x2f, 0x73, 0x73, 0x7a, 0x12, 0xa2, 0x01, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x6c, 0x6f,
0x63, 0x6b, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1d,
0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31,
0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e,
0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e,
0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3e, 0x82, 0xd3, 0xe4, 0x93, 0x02,
0x38, 0x12, 0x36, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68,
0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
0x73, 0x2f, 0x7b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x61, 0x74, 0x74,
0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x9e, 0x01, 0x0a, 0x14, 0x4c, 0x69,
0x73, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x73, 0x12, 0x28, 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,
0x73, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 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, 0x73, 0x50, 0x6f, 0x6f, 0x6c, 0x52,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x31, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2b, 0x12,
0x29, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76,
0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x70, 0x6f, 0x6f, 0x6c, 0x2f, 0x61, 0x74,
0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x9c, 0x01,
0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74,
0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f,
0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d,
0x70, 0x74, 0x79, 0x1a, 0x2e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65,
0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c,
0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x22, 0x37, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x31, 0x12, 0x2f, 0x2f, 0x69, 0x6e,
0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65,
0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x70, 0x6f, 0x6f, 0x6c, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74,
0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x8f, 0x01, 0x0a,
0x16, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53,
0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x12, 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65,
0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74,
0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f,
0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70,
0x74, 0x79, 0x22, 0x3a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x34, 0x22, 0x2f, 0x2f, 0x69, 0x6e, 0x74,
0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61,
0x63, 0x6f, 0x6e, 0x2f, 0x70, 0x6f, 0x6f, 0x6c, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65,
0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x9b,
0x01, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x50, 0x72, 0x6f, 0x70, 0x6f,
0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x16, 0x2e, 0x67,
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45,
0x6d, 0x70, 0x74, 0x79, 0x1a, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e,
0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53,
0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x22, 0x37, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x31, 0x12, 0x2f, 0x2f, 0x69, 0x6e,
0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65,
0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x70, 0x6f, 0x6f, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73,
0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x8f, 0x01, 0x0a,
0x16, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53,
0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x12, 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65,
0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73,
0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f,
0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70,
0x74, 0x79, 0x22, 0x3a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x34, 0x22, 0x2f, 0x2f, 0x69, 0x6e, 0x74,
0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61,
0x63, 0x6f, 0x6e, 0x2f, 0x70, 0x6f, 0x6f, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65,
0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x93,
0x01, 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x56, 0x6f, 0x6c, 0x75, 0x6e,
0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74,
0x79, 0x1a, 0x2b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68,
0x2e, 0x76, 0x31, 0x2e, 0x56, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69,
0x74, 0x73, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x34,
0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2e, 0x12, 0x2c, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61,
0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f,
0x70, 0x6f, 0x6f, 0x6c, 0x2f, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f, 0x65,
0x78, 0x69, 0x74, 0x73, 0x12, 0x8c, 0x01, 0x0a, 0x13, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x56,
0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x12, 0x24, 0x2e, 0x65,
0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53,
0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78,
0x69, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x37, 0x82, 0xd3, 0xe4, 0x93,
0x02, 0x31, 0x22, 0x2c, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74,
0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x70, 0x6f, 0x6f, 0x6c,
0x2f, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x73,
0x3a, 0x01, 0x2a, 0x12, 0xa8, 0x01, 0x0a, 0x21, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x50, 0x6f,
0x6f, 0x6c, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x53,
0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x32, 0x2e, 0x65, 0x74, 0x68, 0x65,
0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x75, 0x62, 0x6d,
0x69, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74,
0x74, 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x1a, 0x16, 0x2e,
0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x8e, 0x01, 0x0a, 0x12, 0x53,
0x75, 0x62, 0x6d, 0x69, 0x74, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x73, 0x12, 0x2a, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68,
0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e,
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x37, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x31, 0x22, 0x2c, 0x2f,
0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x34, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2e, 0x22, 0x29, 0x2f,
0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f,
0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x70, 0x6f, 0x6f, 0x6c, 0x2f, 0x73, 0x79, 0x6e, 0x63,
0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x7f,
0x0a, 0x0f, 0x47, 0x65, 0x74, 0x46, 0x6f, 0x72, 0x6b, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c,
0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x25, 0x2e, 0x65, 0x74, 0x68, 0x65,
0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x6f, 0x72, 0x6b,
0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x22, 0x2d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x27, 0x12, 0x25, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72,
0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69,
0x67, 0x2f, 0x66, 0x6f, 0x72, 0x6b, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x12,
0x66, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x53, 0x70, 0x65, 0x63, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f,
0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x70, 0x6f, 0x6f, 0x6c, 0x2f, 0x61, 0x74, 0x74, 0x65,
0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x9c, 0x01, 0x0a, 0x19,
0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72,
0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74,
0x79, 0x1a, 0x2e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68,
0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73,
0x68, 0x69, 0x6e, 0x67, 0x73, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x22, 0x37, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x31, 0x12, 0x2f, 0x2f, 0x69, 0x6e, 0x74, 0x65,
0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63,
0x6f, 0x6e, 0x2f, 0x70, 0x6f, 0x6f, 0x6c, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72,
0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x8f, 0x01, 0x0a, 0x16, 0x53,
0x75, 0x62, 0x6d, 0x69, 0x74, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61,
0x73, 0x68, 0x69, 0x6e, 0x67, 0x12, 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d,
0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72,
0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79,
0x22, 0x3a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x34, 0x22, 0x2f, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72,
0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f,
0x6e, 0x2f, 0x70, 0x6f, 0x6f, 0x6c, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x5f,
0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x9b, 0x01, 0x0a,
0x19, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65,
0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f,
0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70,
0x74, 0x79, 0x1a, 0x1d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74,
0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x70, 0x65, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x12, 0x1c, 0x2f, 0x69, 0x6e, 0x74, 0x65,
0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x66,
0x69, 0x67, 0x2f, 0x73, 0x70, 0x65, 0x63, 0x12, 0x88, 0x01, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x44,
0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x12, 0x16,
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x28, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75,
0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74,
0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x22, 0x30, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2a, 0x12, 0x28, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72,
0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69,
0x67, 0x2f, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61,
0x63, 0x74, 0x42, 0x95, 0x01, 0x0a, 0x18, 0x6f, 0x72, 0x67, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72,
0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x42,
0x17, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x53, 0x65, 0x72, 0x76,
0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x30, 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, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x2f, 0x65, 0x74, 0x68, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0xaa, 0x02, 0x14, 0x45,
0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x45, 0x74, 0x68, 0x2e, 0x53, 0x65, 0x72, 0x76,
0x69, 0x63, 0x65, 0xca, 0x02, 0x14, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x5c, 0x45,
0x74, 0x68, 0x5c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x33,
0x74, 0x79, 0x1a, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74,
0x68, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61,
0x73, 0x68, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x22, 0x37, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x31, 0x12, 0x2f, 0x2f, 0x69, 0x6e, 0x74, 0x65,
0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63,
0x6f, 0x6e, 0x2f, 0x70, 0x6f, 0x6f, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72,
0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x8f, 0x01, 0x0a, 0x16, 0x53,
0x75, 0x62, 0x6d, 0x69, 0x74, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61,
0x73, 0x68, 0x69, 0x6e, 0x67, 0x12, 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d,
0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72,
0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79,
0x22, 0x3a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x34, 0x22, 0x2f, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72,
0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f,
0x6e, 0x2f, 0x70, 0x6f, 0x6f, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f,
0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x93, 0x01, 0x0a,
0x16, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x56, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61,
0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a,
0x2b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76,
0x31, 0x2e, 0x56, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x73,
0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x34, 0x82, 0xd3,
0xe4, 0x93, 0x02, 0x2e, 0x12, 0x2c, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f,
0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x70, 0x6f,
0x6f, 0x6c, 0x2f, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f, 0x65, 0x78, 0x69,
0x74, 0x73, 0x12, 0x8c, 0x01, 0x0a, 0x13, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x56, 0x6f, 0x6c,
0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x12, 0x24, 0x2e, 0x65, 0x74, 0x68,
0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x67,
0x6e, 0x65, 0x64, 0x56, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74,
0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x37, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x31,
0x22, 0x2c, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f,
0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x70, 0x6f, 0x6f, 0x6c, 0x2f, 0x76,
0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x73, 0x3a, 0x01,
0x2a, 0x12, 0xa8, 0x01, 0x0a, 0x21, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x50, 0x6f, 0x6f, 0x6c,
0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x53, 0x69, 0x67,
0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x32, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65,
0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74,
0x50, 0x6f, 0x6f, 0x6c, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65,
0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x1a, 0x16, 0x2e, 0x67, 0x6f,
0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d,
0x70, 0x74, 0x79, 0x22, 0x37, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x31, 0x22, 0x2c, 0x2f, 0x69, 0x6e,
0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65,
0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x70, 0x6f, 0x6f, 0x6c, 0x2f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x63,
0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x7f, 0x0a, 0x0f,
0x47, 0x65, 0x74, 0x46, 0x6f, 0x72, 0x6b, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x12,
0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x25, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65,
0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x6f, 0x72, 0x6b, 0x53, 0x63,
0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2d,
0x82, 0xd3, 0xe4, 0x93, 0x02, 0x27, 0x12, 0x25, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61,
0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f,
0x66, 0x6f, 0x72, 0x6b, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x12, 0x66, 0x0a,
0x07, 0x47, 0x65, 0x74, 0x53, 0x70, 0x65, 0x63, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79,
0x1a, 0x1d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e,
0x76, 0x31, 0x2e, 0x53, 0x70, 0x65, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x12, 0x1c, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e,
0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
0x2f, 0x73, 0x70, 0x65, 0x63, 0x12, 0x88, 0x01, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x44, 0x65, 0x70,
0x6f, 0x73, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x12, 0x16, 0x2e, 0x67,
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45,
0x6d, 0x70, 0x74, 0x79, 0x1a, 0x28, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e,
0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x43, 0x6f,
0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x30,
0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2a, 0x12, 0x28, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61,
0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f,
0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74,
0x42, 0x95, 0x01, 0x0a, 0x18, 0x6f, 0x72, 0x67, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75,
0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x42, 0x17, 0x42,
0x65, 0x61, 0x63, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63,
0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x30, 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, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65,
0x74, 0x68, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0xaa, 0x02, 0x14, 0x45, 0x74, 0x68,
0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x45, 0x74, 0x68, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63,
0x65, 0xca, 0x02, 0x14, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x5c, 0x45, 0x74, 0x68,
0x5c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var file_proto_eth_service_beacon_chain_service_proto_goTypes = []interface{}{
@@ -366,93 +374,96 @@ var file_proto_eth_service_beacon_chain_service_proto_goTypes = []interface{}{
(*v1.SignedVoluntaryExit)(nil), // 15: ethereum.eth.v1.SignedVoluntaryExit
(*v2.SubmitPoolSyncCommitteeSignatures)(nil), // 16: ethereum.eth.v2.SubmitPoolSyncCommitteeSignatures
(*v1.GenesisResponse)(nil), // 17: ethereum.eth.v1.GenesisResponse
(*v1.StateRootResponse)(nil), // 18: ethereum.eth.v1.StateRootResponse
(*v1.StateForkResponse)(nil), // 19: ethereum.eth.v1.StateForkResponse
(*v1.StateFinalityCheckpointResponse)(nil), // 20: ethereum.eth.v1.StateFinalityCheckpointResponse
(*v1.StateValidatorsResponse)(nil), // 21: ethereum.eth.v1.StateValidatorsResponse
(*v1.StateValidatorResponse)(nil), // 22: ethereum.eth.v1.StateValidatorResponse
(*v1.ValidatorBalancesResponse)(nil), // 23: ethereum.eth.v1.ValidatorBalancesResponse
(*v1.StateCommitteesResponse)(nil), // 24: ethereum.eth.v1.StateCommitteesResponse
(*v2.StateSyncCommitteesResponse)(nil), // 25: ethereum.eth.v2.StateSyncCommitteesResponse
(*v1.BlockHeadersResponse)(nil), // 26: ethereum.eth.v1.BlockHeadersResponse
(*v1.BlockHeaderResponse)(nil), // 27: ethereum.eth.v1.BlockHeaderResponse
(*v1.BlockRootResponse)(nil), // 28: ethereum.eth.v1.BlockRootResponse
(*v1.BlockResponse)(nil), // 29: ethereum.eth.v1.BlockResponse
(*v1.BlockSSZResponse)(nil), // 30: ethereum.eth.v1.BlockSSZResponse
(*v2.BlockResponseV2)(nil), // 31: ethereum.eth.v2.BlockResponseV2
(*v2.BlockSSZResponseV2)(nil), // 32: ethereum.eth.v2.BlockSSZResponseV2
(*v1.BlockAttestationsResponse)(nil), // 33: ethereum.eth.v1.BlockAttestationsResponse
(*v1.AttestationsPoolResponse)(nil), // 34: ethereum.eth.v1.AttestationsPoolResponse
(*v1.AttesterSlashingsPoolResponse)(nil), // 35: ethereum.eth.v1.AttesterSlashingsPoolResponse
(*v1.ProposerSlashingPoolResponse)(nil), // 36: ethereum.eth.v1.ProposerSlashingPoolResponse
(*v1.VoluntaryExitsPoolResponse)(nil), // 37: ethereum.eth.v1.VoluntaryExitsPoolResponse
(*v1.ForkScheduleResponse)(nil), // 38: ethereum.eth.v1.ForkScheduleResponse
(*v1.SpecResponse)(nil), // 39: ethereum.eth.v1.SpecResponse
(*v1.DepositContractResponse)(nil), // 40: ethereum.eth.v1.DepositContractResponse
(*v1.WeakSubjectivityResponse)(nil), // 18: ethereum.eth.v1.WeakSubjectivityResponse
(*v1.StateRootResponse)(nil), // 19: ethereum.eth.v1.StateRootResponse
(*v1.StateForkResponse)(nil), // 20: ethereum.eth.v1.StateForkResponse
(*v1.StateFinalityCheckpointResponse)(nil), // 21: ethereum.eth.v1.StateFinalityCheckpointResponse
(*v1.StateValidatorsResponse)(nil), // 22: ethereum.eth.v1.StateValidatorsResponse
(*v1.StateValidatorResponse)(nil), // 23: ethereum.eth.v1.StateValidatorResponse
(*v1.ValidatorBalancesResponse)(nil), // 24: ethereum.eth.v1.ValidatorBalancesResponse
(*v1.StateCommitteesResponse)(nil), // 25: ethereum.eth.v1.StateCommitteesResponse
(*v2.StateSyncCommitteesResponse)(nil), // 26: ethereum.eth.v2.StateSyncCommitteesResponse
(*v1.BlockHeadersResponse)(nil), // 27: ethereum.eth.v1.BlockHeadersResponse
(*v1.BlockHeaderResponse)(nil), // 28: ethereum.eth.v1.BlockHeaderResponse
(*v1.BlockRootResponse)(nil), // 29: ethereum.eth.v1.BlockRootResponse
(*v1.BlockResponse)(nil), // 30: ethereum.eth.v1.BlockResponse
(*v1.BlockSSZResponse)(nil), // 31: ethereum.eth.v1.BlockSSZResponse
(*v2.BlockResponseV2)(nil), // 32: ethereum.eth.v2.BlockResponseV2
(*v2.BlockSSZResponseV2)(nil), // 33: ethereum.eth.v2.BlockSSZResponseV2
(*v1.BlockAttestationsResponse)(nil), // 34: ethereum.eth.v1.BlockAttestationsResponse
(*v1.AttestationsPoolResponse)(nil), // 35: ethereum.eth.v1.AttestationsPoolResponse
(*v1.AttesterSlashingsPoolResponse)(nil), // 36: ethereum.eth.v1.AttesterSlashingsPoolResponse
(*v1.ProposerSlashingPoolResponse)(nil), // 37: ethereum.eth.v1.ProposerSlashingPoolResponse
(*v1.VoluntaryExitsPoolResponse)(nil), // 38: ethereum.eth.v1.VoluntaryExitsPoolResponse
(*v1.ForkScheduleResponse)(nil), // 39: ethereum.eth.v1.ForkScheduleResponse
(*v1.SpecResponse)(nil), // 40: ethereum.eth.v1.SpecResponse
(*v1.DepositContractResponse)(nil), // 41: ethereum.eth.v1.DepositContractResponse
}
var file_proto_eth_service_beacon_chain_service_proto_depIdxs = []int32{
0, // 0: ethereum.eth.service.BeaconChain.GetGenesis:input_type -> google.protobuf.Empty
1, // 1: ethereum.eth.service.BeaconChain.GetStateRoot:input_type -> ethereum.eth.v1.StateRequest
1, // 2: ethereum.eth.service.BeaconChain.GetStateFork:input_type -> ethereum.eth.v1.StateRequest
1, // 3: ethereum.eth.service.BeaconChain.GetFinalityCheckpoints:input_type -> ethereum.eth.v1.StateRequest
2, // 4: ethereum.eth.service.BeaconChain.ListValidators:input_type -> ethereum.eth.v1.StateValidatorsRequest
3, // 5: ethereum.eth.service.BeaconChain.GetValidator:input_type -> ethereum.eth.v1.StateValidatorRequest
4, // 6: ethereum.eth.service.BeaconChain.ListValidatorBalances:input_type -> ethereum.eth.v1.ValidatorBalancesRequest
5, // 7: ethereum.eth.service.BeaconChain.ListCommittees:input_type -> ethereum.eth.v1.StateCommitteesRequest
6, // 8: ethereum.eth.service.BeaconChain.ListSyncCommittees:input_type -> ethereum.eth.v2.StateSyncCommitteesRequest
7, // 9: ethereum.eth.service.BeaconChain.ListBlockHeaders:input_type -> ethereum.eth.v1.BlockHeadersRequest
8, // 10: ethereum.eth.service.BeaconChain.GetBlockHeader:input_type -> ethereum.eth.v1.BlockRequest
9, // 11: ethereum.eth.service.BeaconChain.SubmitBlock:input_type -> ethereum.eth.v2.SignedBeaconBlockContainerV2
8, // 12: ethereum.eth.service.BeaconChain.GetBlockRoot:input_type -> ethereum.eth.v1.BlockRequest
8, // 13: ethereum.eth.service.BeaconChain.GetBlock:input_type -> ethereum.eth.v1.BlockRequest
8, // 14: ethereum.eth.service.BeaconChain.GetBlockSSZ:input_type -> ethereum.eth.v1.BlockRequest
10, // 15: ethereum.eth.service.BeaconChain.GetBlockV2:input_type -> ethereum.eth.v2.BlockRequestV2
10, // 16: ethereum.eth.service.BeaconChain.GetBlockSSZV2:input_type -> ethereum.eth.v2.BlockRequestV2
8, // 17: ethereum.eth.service.BeaconChain.ListBlockAttestations:input_type -> ethereum.eth.v1.BlockRequest
11, // 18: ethereum.eth.service.BeaconChain.ListPoolAttestations:input_type -> ethereum.eth.v1.AttestationsPoolRequest
12, // 19: ethereum.eth.service.BeaconChain.SubmitAttestations:input_type -> ethereum.eth.v1.SubmitAttestationsRequest
0, // 20: ethereum.eth.service.BeaconChain.ListPoolAttesterSlashings:input_type -> google.protobuf.Empty
13, // 21: ethereum.eth.service.BeaconChain.SubmitAttesterSlashing:input_type -> ethereum.eth.v1.AttesterSlashing
0, // 22: ethereum.eth.service.BeaconChain.ListPoolProposerSlashings:input_type -> google.protobuf.Empty
14, // 23: ethereum.eth.service.BeaconChain.SubmitProposerSlashing:input_type -> ethereum.eth.v1.ProposerSlashing
0, // 24: ethereum.eth.service.BeaconChain.ListPoolVoluntaryExits:input_type -> google.protobuf.Empty
15, // 25: ethereum.eth.service.BeaconChain.SubmitVoluntaryExit:input_type -> ethereum.eth.v1.SignedVoluntaryExit
16, // 26: ethereum.eth.service.BeaconChain.SubmitPoolSyncCommitteeSignatures:input_type -> ethereum.eth.v2.SubmitPoolSyncCommitteeSignatures
0, // 27: ethereum.eth.service.BeaconChain.GetForkSchedule:input_type -> google.protobuf.Empty
0, // 28: ethereum.eth.service.BeaconChain.GetSpec:input_type -> google.protobuf.Empty
0, // 29: ethereum.eth.service.BeaconChain.GetDepositContract:input_type -> google.protobuf.Empty
17, // 30: ethereum.eth.service.BeaconChain.GetGenesis:output_type -> ethereum.eth.v1.GenesisResponse
18, // 31: ethereum.eth.service.BeaconChain.GetStateRoot:output_type -> ethereum.eth.v1.StateRootResponse
19, // 32: ethereum.eth.service.BeaconChain.GetStateFork:output_type -> ethereum.eth.v1.StateForkResponse
20, // 33: ethereum.eth.service.BeaconChain.GetFinalityCheckpoints:output_type -> ethereum.eth.v1.StateFinalityCheckpointResponse
21, // 34: ethereum.eth.service.BeaconChain.ListValidators:output_type -> ethereum.eth.v1.StateValidatorsResponse
22, // 35: ethereum.eth.service.BeaconChain.GetValidator:output_type -> ethereum.eth.v1.StateValidatorResponse
23, // 36: ethereum.eth.service.BeaconChain.ListValidatorBalances:output_type -> ethereum.eth.v1.ValidatorBalancesResponse
24, // 37: ethereum.eth.service.BeaconChain.ListCommittees:output_type -> ethereum.eth.v1.StateCommitteesResponse
25, // 38: ethereum.eth.service.BeaconChain.ListSyncCommittees:output_type -> ethereum.eth.v2.StateSyncCommitteesResponse
26, // 39: ethereum.eth.service.BeaconChain.ListBlockHeaders:output_type -> ethereum.eth.v1.BlockHeadersResponse
27, // 40: ethereum.eth.service.BeaconChain.GetBlockHeader:output_type -> ethereum.eth.v1.BlockHeaderResponse
0, // 41: ethereum.eth.service.BeaconChain.SubmitBlock:output_type -> google.protobuf.Empty
28, // 42: ethereum.eth.service.BeaconChain.GetBlockRoot:output_type -> ethereum.eth.v1.BlockRootResponse
29, // 43: ethereum.eth.service.BeaconChain.GetBlock:output_type -> ethereum.eth.v1.BlockResponse
30, // 44: ethereum.eth.service.BeaconChain.GetBlockSSZ:output_type -> ethereum.eth.v1.BlockSSZResponse
31, // 45: ethereum.eth.service.BeaconChain.GetBlockV2:output_type -> ethereum.eth.v2.BlockResponseV2
32, // 46: ethereum.eth.service.BeaconChain.GetBlockSSZV2:output_type -> ethereum.eth.v2.BlockSSZResponseV2
33, // 47: ethereum.eth.service.BeaconChain.ListBlockAttestations:output_type -> ethereum.eth.v1.BlockAttestationsResponse
34, // 48: ethereum.eth.service.BeaconChain.ListPoolAttestations:output_type -> ethereum.eth.v1.AttestationsPoolResponse
0, // 49: ethereum.eth.service.BeaconChain.SubmitAttestations:output_type -> google.protobuf.Empty
35, // 50: ethereum.eth.service.BeaconChain.ListPoolAttesterSlashings:output_type -> ethereum.eth.v1.AttesterSlashingsPoolResponse
0, // 51: ethereum.eth.service.BeaconChain.SubmitAttesterSlashing:output_type -> google.protobuf.Empty
36, // 52: ethereum.eth.service.BeaconChain.ListPoolProposerSlashings:output_type -> ethereum.eth.v1.ProposerSlashingPoolResponse
0, // 53: ethereum.eth.service.BeaconChain.SubmitProposerSlashing:output_type -> google.protobuf.Empty
37, // 54: ethereum.eth.service.BeaconChain.ListPoolVoluntaryExits:output_type -> ethereum.eth.v1.VoluntaryExitsPoolResponse
0, // 55: ethereum.eth.service.BeaconChain.SubmitVoluntaryExit:output_type -> google.protobuf.Empty
0, // 56: ethereum.eth.service.BeaconChain.SubmitPoolSyncCommitteeSignatures:output_type -> google.protobuf.Empty
38, // 57: ethereum.eth.service.BeaconChain.GetForkSchedule:output_type -> ethereum.eth.v1.ForkScheduleResponse
39, // 58: ethereum.eth.service.BeaconChain.GetSpec:output_type -> ethereum.eth.v1.SpecResponse
40, // 59: ethereum.eth.service.BeaconChain.GetDepositContract:output_type -> ethereum.eth.v1.DepositContractResponse
30, // [30:60] is the sub-list for method output_type
0, // [0:30] is the sub-list for method input_type
0, // 1: ethereum.eth.service.BeaconChain.GetWeakSubjectivity:input_type -> google.protobuf.Empty
1, // 2: ethereum.eth.service.BeaconChain.GetStateRoot:input_type -> ethereum.eth.v1.StateRequest
1, // 3: ethereum.eth.service.BeaconChain.GetStateFork:input_type -> ethereum.eth.v1.StateRequest
1, // 4: ethereum.eth.service.BeaconChain.GetFinalityCheckpoints:input_type -> ethereum.eth.v1.StateRequest
2, // 5: ethereum.eth.service.BeaconChain.ListValidators:input_type -> ethereum.eth.v1.StateValidatorsRequest
3, // 6: ethereum.eth.service.BeaconChain.GetValidator:input_type -> ethereum.eth.v1.StateValidatorRequest
4, // 7: ethereum.eth.service.BeaconChain.ListValidatorBalances:input_type -> ethereum.eth.v1.ValidatorBalancesRequest
5, // 8: ethereum.eth.service.BeaconChain.ListCommittees:input_type -> ethereum.eth.v1.StateCommitteesRequest
6, // 9: ethereum.eth.service.BeaconChain.ListSyncCommittees:input_type -> ethereum.eth.v2.StateSyncCommitteesRequest
7, // 10: ethereum.eth.service.BeaconChain.ListBlockHeaders:input_type -> ethereum.eth.v1.BlockHeadersRequest
8, // 11: ethereum.eth.service.BeaconChain.GetBlockHeader:input_type -> ethereum.eth.v1.BlockRequest
9, // 12: ethereum.eth.service.BeaconChain.SubmitBlock:input_type -> ethereum.eth.v2.SignedBeaconBlockContainerV2
8, // 13: ethereum.eth.service.BeaconChain.GetBlockRoot:input_type -> ethereum.eth.v1.BlockRequest
8, // 14: ethereum.eth.service.BeaconChain.GetBlock:input_type -> ethereum.eth.v1.BlockRequest
8, // 15: ethereum.eth.service.BeaconChain.GetBlockSSZ:input_type -> ethereum.eth.v1.BlockRequest
10, // 16: ethereum.eth.service.BeaconChain.GetBlockV2:input_type -> ethereum.eth.v2.BlockRequestV2
10, // 17: ethereum.eth.service.BeaconChain.GetBlockSSZV2:input_type -> ethereum.eth.v2.BlockRequestV2
8, // 18: ethereum.eth.service.BeaconChain.ListBlockAttestations:input_type -> ethereum.eth.v1.BlockRequest
11, // 19: ethereum.eth.service.BeaconChain.ListPoolAttestations:input_type -> ethereum.eth.v1.AttestationsPoolRequest
12, // 20: ethereum.eth.service.BeaconChain.SubmitAttestations:input_type -> ethereum.eth.v1.SubmitAttestationsRequest
0, // 21: ethereum.eth.service.BeaconChain.ListPoolAttesterSlashings:input_type -> google.protobuf.Empty
13, // 22: ethereum.eth.service.BeaconChain.SubmitAttesterSlashing:input_type -> ethereum.eth.v1.AttesterSlashing
0, // 23: ethereum.eth.service.BeaconChain.ListPoolProposerSlashings:input_type -> google.protobuf.Empty
14, // 24: ethereum.eth.service.BeaconChain.SubmitProposerSlashing:input_type -> ethereum.eth.v1.ProposerSlashing
0, // 25: ethereum.eth.service.BeaconChain.ListPoolVoluntaryExits:input_type -> google.protobuf.Empty
15, // 26: ethereum.eth.service.BeaconChain.SubmitVoluntaryExit:input_type -> ethereum.eth.v1.SignedVoluntaryExit
16, // 27: ethereum.eth.service.BeaconChain.SubmitPoolSyncCommitteeSignatures:input_type -> ethereum.eth.v2.SubmitPoolSyncCommitteeSignatures
0, // 28: ethereum.eth.service.BeaconChain.GetForkSchedule:input_type -> google.protobuf.Empty
0, // 29: ethereum.eth.service.BeaconChain.GetSpec:input_type -> google.protobuf.Empty
0, // 30: ethereum.eth.service.BeaconChain.GetDepositContract:input_type -> google.protobuf.Empty
17, // 31: ethereum.eth.service.BeaconChain.GetGenesis:output_type -> ethereum.eth.v1.GenesisResponse
18, // 32: ethereum.eth.service.BeaconChain.GetWeakSubjectivity:output_type -> ethereum.eth.v1.WeakSubjectivityResponse
19, // 33: ethereum.eth.service.BeaconChain.GetStateRoot:output_type -> ethereum.eth.v1.StateRootResponse
20, // 34: ethereum.eth.service.BeaconChain.GetStateFork:output_type -> ethereum.eth.v1.StateForkResponse
21, // 35: ethereum.eth.service.BeaconChain.GetFinalityCheckpoints:output_type -> ethereum.eth.v1.StateFinalityCheckpointResponse
22, // 36: ethereum.eth.service.BeaconChain.ListValidators:output_type -> ethereum.eth.v1.StateValidatorsResponse
23, // 37: ethereum.eth.service.BeaconChain.GetValidator:output_type -> ethereum.eth.v1.StateValidatorResponse
24, // 38: ethereum.eth.service.BeaconChain.ListValidatorBalances:output_type -> ethereum.eth.v1.ValidatorBalancesResponse
25, // 39: ethereum.eth.service.BeaconChain.ListCommittees:output_type -> ethereum.eth.v1.StateCommitteesResponse
26, // 40: ethereum.eth.service.BeaconChain.ListSyncCommittees:output_type -> ethereum.eth.v2.StateSyncCommitteesResponse
27, // 41: ethereum.eth.service.BeaconChain.ListBlockHeaders:output_type -> ethereum.eth.v1.BlockHeadersResponse
28, // 42: ethereum.eth.service.BeaconChain.GetBlockHeader:output_type -> ethereum.eth.v1.BlockHeaderResponse
0, // 43: ethereum.eth.service.BeaconChain.SubmitBlock:output_type -> google.protobuf.Empty
29, // 44: ethereum.eth.service.BeaconChain.GetBlockRoot:output_type -> ethereum.eth.v1.BlockRootResponse
30, // 45: ethereum.eth.service.BeaconChain.GetBlock:output_type -> ethereum.eth.v1.BlockResponse
31, // 46: ethereum.eth.service.BeaconChain.GetBlockSSZ:output_type -> ethereum.eth.v1.BlockSSZResponse
32, // 47: ethereum.eth.service.BeaconChain.GetBlockV2:output_type -> ethereum.eth.v2.BlockResponseV2
33, // 48: ethereum.eth.service.BeaconChain.GetBlockSSZV2:output_type -> ethereum.eth.v2.BlockSSZResponseV2
34, // 49: ethereum.eth.service.BeaconChain.ListBlockAttestations:output_type -> ethereum.eth.v1.BlockAttestationsResponse
35, // 50: ethereum.eth.service.BeaconChain.ListPoolAttestations:output_type -> ethereum.eth.v1.AttestationsPoolResponse
0, // 51: ethereum.eth.service.BeaconChain.SubmitAttestations:output_type -> google.protobuf.Empty
36, // 52: ethereum.eth.service.BeaconChain.ListPoolAttesterSlashings:output_type -> ethereum.eth.v1.AttesterSlashingsPoolResponse
0, // 53: ethereum.eth.service.BeaconChain.SubmitAttesterSlashing:output_type -> google.protobuf.Empty
37, // 54: ethereum.eth.service.BeaconChain.ListPoolProposerSlashings:output_type -> ethereum.eth.v1.ProposerSlashingPoolResponse
0, // 55: ethereum.eth.service.BeaconChain.SubmitProposerSlashing:output_type -> google.protobuf.Empty
38, // 56: ethereum.eth.service.BeaconChain.ListPoolVoluntaryExits:output_type -> ethereum.eth.v1.VoluntaryExitsPoolResponse
0, // 57: ethereum.eth.service.BeaconChain.SubmitVoluntaryExit:output_type -> google.protobuf.Empty
0, // 58: ethereum.eth.service.BeaconChain.SubmitPoolSyncCommitteeSignatures:output_type -> google.protobuf.Empty
39, // 59: ethereum.eth.service.BeaconChain.GetForkSchedule:output_type -> ethereum.eth.v1.ForkScheduleResponse
40, // 60: ethereum.eth.service.BeaconChain.GetSpec:output_type -> ethereum.eth.v1.SpecResponse
41, // 61: ethereum.eth.service.BeaconChain.GetDepositContract:output_type -> ethereum.eth.v1.DepositContractResponse
31, // [31:62] is the sub-list for method output_type
0, // [0:31] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
@@ -495,6 +506,7 @@ const _ = grpc.SupportPackageIsVersion6
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type BeaconChainClient interface {
GetGenesis(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*v1.GenesisResponse, error)
GetWeakSubjectivity(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*v1.WeakSubjectivityResponse, error)
GetStateRoot(ctx context.Context, in *v1.StateRequest, opts ...grpc.CallOption) (*v1.StateRootResponse, error)
GetStateFork(ctx context.Context, in *v1.StateRequest, opts ...grpc.CallOption) (*v1.StateForkResponse, error)
GetFinalityCheckpoints(ctx context.Context, in *v1.StateRequest, opts ...grpc.CallOption) (*v1.StateFinalityCheckpointResponse, error)
@@ -543,6 +555,15 @@ func (c *beaconChainClient) GetGenesis(ctx context.Context, in *empty.Empty, opt
return out, nil
}
func (c *beaconChainClient) GetWeakSubjectivity(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*v1.WeakSubjectivityResponse, error) {
out := new(v1.WeakSubjectivityResponse)
err := c.cc.Invoke(ctx, "/ethereum.eth.service.BeaconChain/GetWeakSubjectivity", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *beaconChainClient) GetStateRoot(ctx context.Context, in *v1.StateRequest, opts ...grpc.CallOption) (*v1.StateRootResponse, error) {
out := new(v1.StateRootResponse)
err := c.cc.Invoke(ctx, "/ethereum.eth.service.BeaconChain/GetStateRoot", in, out, opts...)
@@ -807,6 +828,7 @@ func (c *beaconChainClient) GetDepositContract(ctx context.Context, in *empty.Em
// BeaconChainServer is the server API for BeaconChain service.
type BeaconChainServer interface {
GetGenesis(context.Context, *empty.Empty) (*v1.GenesisResponse, error)
GetWeakSubjectivity(context.Context, *empty.Empty) (*v1.WeakSubjectivityResponse, error)
GetStateRoot(context.Context, *v1.StateRequest) (*v1.StateRootResponse, error)
GetStateFork(context.Context, *v1.StateRequest) (*v1.StateForkResponse, error)
GetFinalityCheckpoints(context.Context, *v1.StateRequest) (*v1.StateFinalityCheckpointResponse, error)
@@ -845,6 +867,9 @@ type UnimplementedBeaconChainServer struct {
func (*UnimplementedBeaconChainServer) GetGenesis(context.Context, *empty.Empty) (*v1.GenesisResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetGenesis not implemented")
}
func (*UnimplementedBeaconChainServer) GetWeakSubjectivity(context.Context, *empty.Empty) (*v1.WeakSubjectivityResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetWeakSubjectivity not implemented")
}
func (*UnimplementedBeaconChainServer) GetStateRoot(context.Context, *v1.StateRequest) (*v1.StateRootResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetStateRoot not implemented")
}
@@ -955,6 +980,24 @@ func _BeaconChain_GetGenesis_Handler(srv interface{}, ctx context.Context, dec f
return interceptor(ctx, in, info, handler)
}
func _BeaconChain_GetWeakSubjectivity_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(empty.Empty)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(BeaconChainServer).GetWeakSubjectivity(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/ethereum.eth.service.BeaconChain/GetWeakSubjectivity",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(BeaconChainServer).GetWeakSubjectivity(ctx, req.(*empty.Empty))
}
return interceptor(ctx, in, info, handler)
}
func _BeaconChain_GetStateRoot_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(v1.StateRequest)
if err := dec(in); err != nil {
@@ -1485,6 +1528,10 @@ var _BeaconChain_serviceDesc = grpc.ServiceDesc{
MethodName: "GetGenesis",
Handler: _BeaconChain_GetGenesis_Handler,
},
{
MethodName: "GetWeakSubjectivity",
Handler: _BeaconChain_GetWeakSubjectivity_Handler,
},
{
MethodName: "GetStateRoot",
Handler: _BeaconChain_GetStateRoot_Handler,

View File

@@ -57,6 +57,24 @@ func local_request_BeaconChain_GetGenesis_0(ctx context.Context, marshaler runti
}
func request_BeaconChain_GetWeakSubjectivity_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconChainClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq emptypb.Empty
var metadata runtime.ServerMetadata
msg, err := client.GetWeakSubjectivity(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_BeaconChain_GetWeakSubjectivity_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconChainServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq emptypb.Empty
var metadata runtime.ServerMetadata
msg, err := server.GetWeakSubjectivity(ctx, &protoReq)
return msg, metadata, err
}
func request_BeaconChain_GetStateRoot_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconChainClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq v1.StateRequest
var metadata runtime.ServerMetadata
@@ -1374,6 +1392,29 @@ func RegisterBeaconChainHandlerServer(ctx context.Context, mux *runtime.ServeMux
})
mux.Handle("GET", pattern_BeaconChain_GetWeakSubjectivity_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
var stream runtime.ServerTransportStream
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.service.BeaconChain/GetWeakSubjectivity")
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_BeaconChain_GetWeakSubjectivity_0(rctx, inboundMarshaler, server, req, pathParams)
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_BeaconChain_GetWeakSubjectivity_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_BeaconChain_GetStateRoot_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
@@ -2102,6 +2143,26 @@ func RegisterBeaconChainHandlerClient(ctx context.Context, mux *runtime.ServeMux
})
mux.Handle("GET", pattern_BeaconChain_GetWeakSubjectivity_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.service.BeaconChain/GetWeakSubjectivity")
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_BeaconChain_GetWeakSubjectivity_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_BeaconChain_GetWeakSubjectivity_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_BeaconChain_GetStateRoot_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
@@ -2688,6 +2749,8 @@ func RegisterBeaconChainHandlerClient(ctx context.Context, mux *runtime.ServeMux
var (
pattern_BeaconChain_GetGenesis_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"internal", "eth", "v1", "beacon", "genesis"}, ""))
pattern_BeaconChain_GetWeakSubjectivity_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"internal", "eth", "v1", "beacon", "weak_subjectivity"}, ""))
pattern_BeaconChain_GetStateRoot_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6}, []string{"internal", "eth", "v1", "beacon", "states", "state_id", "root"}, ""))
pattern_BeaconChain_GetStateFork_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6}, []string{"internal", "eth", "v1", "beacon", "states", "state_id", "fork"}, ""))
@@ -2750,6 +2813,8 @@ var (
var (
forward_BeaconChain_GetGenesis_0 = runtime.ForwardResponseMessage
forward_BeaconChain_GetWeakSubjectivity_0 = runtime.ForwardResponseMessage
forward_BeaconChain_GetStateRoot_0 = runtime.ForwardResponseMessage
forward_BeaconChain_GetStateFork_0 = runtime.ForwardResponseMessage

View File

@@ -45,6 +45,12 @@ service BeaconChain {
option (google.api.http) = { get: "/internal/eth/v1/beacon/genesis" };
}
// GetWeakSubjectivity is a new proposed endpoint to retrieve the details necessary to download
// the ssz data needed to start a beacon node - checkpoint(epoch + blocK_root) and state_root
rpc GetWeakSubjectivity(google.protobuf.Empty) returns (v1.WeakSubjectivityResponse) {
option (google.api.http) = { get: "/internal/eth/v1/beacon/weak_subjectivity" };
}
// GetStateRoot calculates HashTreeRoot for state with given 'stateId'. If stateId is root, same value will be returned.
rpc GetStateRoot(v1.StateRequest) returns (v1.StateRootResponse) {
option (google.api.http) = {

View File

@@ -1842,6 +1842,108 @@ func (x *DepositContract) GetAddress() string {
return ""
}
type WeakSubjectivityResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Data *WeakSubjectivityData `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
}
func (x *WeakSubjectivityResponse) Reset() {
*x = WeakSubjectivityResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_proto_eth_v1_beacon_chain_proto_msgTypes[36]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *WeakSubjectivityResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*WeakSubjectivityResponse) ProtoMessage() {}
func (x *WeakSubjectivityResponse) ProtoReflect() protoreflect.Message {
mi := &file_proto_eth_v1_beacon_chain_proto_msgTypes[36]
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 WeakSubjectivityResponse.ProtoReflect.Descriptor instead.
func (*WeakSubjectivityResponse) Descriptor() ([]byte, []int) {
return file_proto_eth_v1_beacon_chain_proto_rawDescGZIP(), []int{36}
}
func (x *WeakSubjectivityResponse) GetData() *WeakSubjectivityData {
if x != nil {
return x.Data
}
return nil
}
type WeakSubjectivityData struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
WsCheckpoint *Checkpoint `protobuf:"bytes,1,opt,name=ws_checkpoint,json=wsCheckpoint,proto3" json:"ws_checkpoint,omitempty"`
StateRoot []byte `protobuf:"bytes,2,opt,name=state_root,json=stateRoot,proto3" json:"state_root,omitempty"`
}
func (x *WeakSubjectivityData) Reset() {
*x = WeakSubjectivityData{}
if protoimpl.UnsafeEnabled {
mi := &file_proto_eth_v1_beacon_chain_proto_msgTypes[37]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *WeakSubjectivityData) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*WeakSubjectivityData) ProtoMessage() {}
func (x *WeakSubjectivityData) ProtoReflect() protoreflect.Message {
mi := &file_proto_eth_v1_beacon_chain_proto_msgTypes[37]
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 WeakSubjectivityData.ProtoReflect.Descriptor instead.
func (*WeakSubjectivityData) Descriptor() ([]byte, []int) {
return file_proto_eth_v1_beacon_chain_proto_rawDescGZIP(), []int{37}
}
func (x *WeakSubjectivityData) GetWsCheckpoint() *Checkpoint {
if x != nil {
return x.WsCheckpoint
}
return nil
}
func (x *WeakSubjectivityData) GetStateRoot() []byte {
if x != nil {
return x.StateRoot
}
return nil
}
type GenesisResponse_Genesis struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -1855,7 +1957,7 @@ type GenesisResponse_Genesis struct {
func (x *GenesisResponse_Genesis) Reset() {
*x = GenesisResponse_Genesis{}
if protoimpl.UnsafeEnabled {
mi := &file_proto_eth_v1_beacon_chain_proto_msgTypes[36]
mi := &file_proto_eth_v1_beacon_chain_proto_msgTypes[38]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1868,7 +1970,7 @@ func (x *GenesisResponse_Genesis) String() string {
func (*GenesisResponse_Genesis) ProtoMessage() {}
func (x *GenesisResponse_Genesis) ProtoReflect() protoreflect.Message {
mi := &file_proto_eth_v1_beacon_chain_proto_msgTypes[36]
mi := &file_proto_eth_v1_beacon_chain_proto_msgTypes[38]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1916,7 +2018,7 @@ type StateRootResponse_StateRoot struct {
func (x *StateRootResponse_StateRoot) Reset() {
*x = StateRootResponse_StateRoot{}
if protoimpl.UnsafeEnabled {
mi := &file_proto_eth_v1_beacon_chain_proto_msgTypes[37]
mi := &file_proto_eth_v1_beacon_chain_proto_msgTypes[39]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1929,7 +2031,7 @@ func (x *StateRootResponse_StateRoot) String() string {
func (*StateRootResponse_StateRoot) ProtoMessage() {}
func (x *StateRootResponse_StateRoot) ProtoReflect() protoreflect.Message {
mi := &file_proto_eth_v1_beacon_chain_proto_msgTypes[37]
mi := &file_proto_eth_v1_beacon_chain_proto_msgTypes[39]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1965,7 +2067,7 @@ type StateFinalityCheckpointResponse_StateFinalityCheckpoint struct {
func (x *StateFinalityCheckpointResponse_StateFinalityCheckpoint) Reset() {
*x = StateFinalityCheckpointResponse_StateFinalityCheckpoint{}
if protoimpl.UnsafeEnabled {
mi := &file_proto_eth_v1_beacon_chain_proto_msgTypes[38]
mi := &file_proto_eth_v1_beacon_chain_proto_msgTypes[40]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1978,7 +2080,7 @@ func (x *StateFinalityCheckpointResponse_StateFinalityCheckpoint) String() strin
func (*StateFinalityCheckpointResponse_StateFinalityCheckpoint) ProtoMessage() {}
func (x *StateFinalityCheckpointResponse_StateFinalityCheckpoint) ProtoReflect() protoreflect.Message {
mi := &file_proto_eth_v1_beacon_chain_proto_msgTypes[38]
mi := &file_proto_eth_v1_beacon_chain_proto_msgTypes[40]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -2286,7 +2388,20 @@ var file_proto_eth_v1_beacon_chain_proto_rawDesc = []byte{
0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68,
0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x63, 0x68,
0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73,
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42,
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22,
0x55, 0x0a, 0x18, 0x57, 0x65, 0x61, 0x6b, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x76,
0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x04, 0x64,
0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x65, 0x74, 0x68, 0x65,
0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x65, 0x61, 0x6b,
0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x61, 0x74, 0x61,
0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x77, 0x0a, 0x14, 0x57, 0x65, 0x61, 0x6b, 0x53, 0x75,
0x62, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x61, 0x74, 0x61, 0x12, 0x40,
0x0a, 0x0d, 0x77, 0x73, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18,
0x01, 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, 0x0c, 0x77, 0x73, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74,
0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x02,
0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x42,
0x7a, 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, 0x43, 0x68,
0x61, 0x69, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2b, 0x67, 0x69, 0x74, 0x68,
@@ -2310,7 +2425,7 @@ func file_proto_eth_v1_beacon_chain_proto_rawDescGZIP() []byte {
return file_proto_eth_v1_beacon_chain_proto_rawDescData
}
var file_proto_eth_v1_beacon_chain_proto_msgTypes = make([]protoimpl.MessageInfo, 40)
var file_proto_eth_v1_beacon_chain_proto_msgTypes = make([]protoimpl.MessageInfo, 42)
var file_proto_eth_v1_beacon_chain_proto_goTypes = []interface{}{
(*GenesisResponse)(nil), // 0: ethereum.eth.v1.GenesisResponse
(*StateRequest)(nil), // 1: ethereum.eth.v1.StateRequest
@@ -2348,58 +2463,62 @@ var file_proto_eth_v1_beacon_chain_proto_goTypes = []interface{}{
(*SpecResponse)(nil), // 33: ethereum.eth.v1.SpecResponse
(*DepositContractResponse)(nil), // 34: ethereum.eth.v1.DepositContractResponse
(*DepositContract)(nil), // 35: ethereum.eth.v1.DepositContract
(*GenesisResponse_Genesis)(nil), // 36: ethereum.eth.v1.GenesisResponse.Genesis
(*StateRootResponse_StateRoot)(nil), // 37: ethereum.eth.v1.StateRootResponse.StateRoot
(*StateFinalityCheckpointResponse_StateFinalityCheckpoint)(nil), // 38: ethereum.eth.v1.StateFinalityCheckpointResponse.StateFinalityCheckpoint
nil, // 39: ethereum.eth.v1.SpecResponse.DataEntry
(*Fork)(nil), // 40: ethereum.eth.v1.Fork
(ValidatorStatus)(0), // 41: ethereum.eth.v1.ValidatorStatus
(*ValidatorContainer)(nil), // 42: ethereum.eth.v1.ValidatorContainer
(*Committee)(nil), // 43: ethereum.eth.v1.Committee
(*Attestation)(nil), // 44: ethereum.eth.v1.Attestation
(*BeaconBlockHeader)(nil), // 45: ethereum.eth.v1.BeaconBlockHeader
(*BeaconBlock)(nil), // 46: ethereum.eth.v1.BeaconBlock
(*AttesterSlashing)(nil), // 47: ethereum.eth.v1.AttesterSlashing
(*ProposerSlashing)(nil), // 48: ethereum.eth.v1.ProposerSlashing
(*SignedVoluntaryExit)(nil), // 49: ethereum.eth.v1.SignedVoluntaryExit
(*timestamppb.Timestamp)(nil), // 50: google.protobuf.Timestamp
(*Checkpoint)(nil), // 51: ethereum.eth.v1.Checkpoint
(*WeakSubjectivityResponse)(nil), // 36: ethereum.eth.v1.WeakSubjectivityResponse
(*WeakSubjectivityData)(nil), // 37: ethereum.eth.v1.WeakSubjectivityData
(*GenesisResponse_Genesis)(nil), // 38: ethereum.eth.v1.GenesisResponse.Genesis
(*StateRootResponse_StateRoot)(nil), // 39: ethereum.eth.v1.StateRootResponse.StateRoot
(*StateFinalityCheckpointResponse_StateFinalityCheckpoint)(nil), // 40: ethereum.eth.v1.StateFinalityCheckpointResponse.StateFinalityCheckpoint
nil, // 41: ethereum.eth.v1.SpecResponse.DataEntry
(*Fork)(nil), // 42: ethereum.eth.v1.Fork
(ValidatorStatus)(0), // 43: ethereum.eth.v1.ValidatorStatus
(*ValidatorContainer)(nil), // 44: ethereum.eth.v1.ValidatorContainer
(*Committee)(nil), // 45: ethereum.eth.v1.Committee
(*Attestation)(nil), // 46: ethereum.eth.v1.Attestation
(*BeaconBlockHeader)(nil), // 47: ethereum.eth.v1.BeaconBlockHeader
(*BeaconBlock)(nil), // 48: ethereum.eth.v1.BeaconBlock
(*AttesterSlashing)(nil), // 49: ethereum.eth.v1.AttesterSlashing
(*ProposerSlashing)(nil), // 50: ethereum.eth.v1.ProposerSlashing
(*SignedVoluntaryExit)(nil), // 51: ethereum.eth.v1.SignedVoluntaryExit
(*Checkpoint)(nil), // 52: ethereum.eth.v1.Checkpoint
(*timestamppb.Timestamp)(nil), // 53: google.protobuf.Timestamp
}
var file_proto_eth_v1_beacon_chain_proto_depIdxs = []int32{
36, // 0: ethereum.eth.v1.GenesisResponse.data:type_name -> ethereum.eth.v1.GenesisResponse.Genesis
37, // 1: ethereum.eth.v1.StateRootResponse.data:type_name -> ethereum.eth.v1.StateRootResponse.StateRoot
40, // 2: ethereum.eth.v1.StateForkResponse.data:type_name -> ethereum.eth.v1.Fork
38, // 3: ethereum.eth.v1.StateFinalityCheckpointResponse.data:type_name -> ethereum.eth.v1.StateFinalityCheckpointResponse.StateFinalityCheckpoint
41, // 4: ethereum.eth.v1.StateValidatorsRequest.status:type_name -> ethereum.eth.v1.ValidatorStatus
42, // 5: ethereum.eth.v1.StateValidatorsResponse.data:type_name -> ethereum.eth.v1.ValidatorContainer
38, // 0: ethereum.eth.v1.GenesisResponse.data:type_name -> ethereum.eth.v1.GenesisResponse.Genesis
39, // 1: ethereum.eth.v1.StateRootResponse.data:type_name -> ethereum.eth.v1.StateRootResponse.StateRoot
42, // 2: ethereum.eth.v1.StateForkResponse.data:type_name -> ethereum.eth.v1.Fork
40, // 3: ethereum.eth.v1.StateFinalityCheckpointResponse.data:type_name -> ethereum.eth.v1.StateFinalityCheckpointResponse.StateFinalityCheckpoint
43, // 4: ethereum.eth.v1.StateValidatorsRequest.status:type_name -> ethereum.eth.v1.ValidatorStatus
44, // 5: ethereum.eth.v1.StateValidatorsResponse.data:type_name -> ethereum.eth.v1.ValidatorContainer
9, // 6: ethereum.eth.v1.ValidatorBalancesResponse.data:type_name -> ethereum.eth.v1.ValidatorBalance
42, // 7: ethereum.eth.v1.StateValidatorResponse.data:type_name -> ethereum.eth.v1.ValidatorContainer
43, // 8: ethereum.eth.v1.StateCommitteesResponse.data:type_name -> ethereum.eth.v1.Committee
44, // 9: ethereum.eth.v1.BlockAttestationsResponse.data:type_name -> ethereum.eth.v1.Attestation
44, // 7: ethereum.eth.v1.StateValidatorResponse.data:type_name -> ethereum.eth.v1.ValidatorContainer
45, // 8: ethereum.eth.v1.StateCommitteesResponse.data:type_name -> ethereum.eth.v1.Committee
46, // 9: ethereum.eth.v1.BlockAttestationsResponse.data:type_name -> ethereum.eth.v1.Attestation
15, // 10: ethereum.eth.v1.BlockRootResponse.data:type_name -> ethereum.eth.v1.BlockRootContainer
21, // 11: ethereum.eth.v1.BlockHeadersResponse.data:type_name -> ethereum.eth.v1.BlockHeaderContainer
21, // 12: ethereum.eth.v1.BlockHeaderResponse.data:type_name -> ethereum.eth.v1.BlockHeaderContainer
22, // 13: ethereum.eth.v1.BlockHeaderContainer.header:type_name -> ethereum.eth.v1.BeaconBlockHeaderContainer
45, // 14: ethereum.eth.v1.BeaconBlockHeaderContainer.message:type_name -> ethereum.eth.v1.BeaconBlockHeader
47, // 14: ethereum.eth.v1.BeaconBlockHeaderContainer.message:type_name -> ethereum.eth.v1.BeaconBlockHeader
25, // 15: ethereum.eth.v1.BlockResponse.data:type_name -> ethereum.eth.v1.BeaconBlockContainer
46, // 16: ethereum.eth.v1.BeaconBlockContainer.message:type_name -> ethereum.eth.v1.BeaconBlock
44, // 17: ethereum.eth.v1.SubmitAttestationsRequest.data:type_name -> ethereum.eth.v1.Attestation
44, // 18: ethereum.eth.v1.AttestationsPoolResponse.data:type_name -> ethereum.eth.v1.Attestation
47, // 19: ethereum.eth.v1.AttesterSlashingsPoolResponse.data:type_name -> ethereum.eth.v1.AttesterSlashing
48, // 20: ethereum.eth.v1.ProposerSlashingPoolResponse.data:type_name -> ethereum.eth.v1.ProposerSlashing
49, // 21: ethereum.eth.v1.VoluntaryExitsPoolResponse.data:type_name -> ethereum.eth.v1.SignedVoluntaryExit
40, // 22: ethereum.eth.v1.ForkScheduleResponse.data:type_name -> ethereum.eth.v1.Fork
39, // 23: ethereum.eth.v1.SpecResponse.data:type_name -> ethereum.eth.v1.SpecResponse.DataEntry
48, // 16: ethereum.eth.v1.BeaconBlockContainer.message:type_name -> ethereum.eth.v1.BeaconBlock
46, // 17: ethereum.eth.v1.SubmitAttestationsRequest.data:type_name -> ethereum.eth.v1.Attestation
46, // 18: ethereum.eth.v1.AttestationsPoolResponse.data:type_name -> ethereum.eth.v1.Attestation
49, // 19: ethereum.eth.v1.AttesterSlashingsPoolResponse.data:type_name -> ethereum.eth.v1.AttesterSlashing
50, // 20: ethereum.eth.v1.ProposerSlashingPoolResponse.data:type_name -> ethereum.eth.v1.ProposerSlashing
51, // 21: ethereum.eth.v1.VoluntaryExitsPoolResponse.data:type_name -> ethereum.eth.v1.SignedVoluntaryExit
42, // 22: ethereum.eth.v1.ForkScheduleResponse.data:type_name -> ethereum.eth.v1.Fork
41, // 23: ethereum.eth.v1.SpecResponse.data:type_name -> ethereum.eth.v1.SpecResponse.DataEntry
35, // 24: ethereum.eth.v1.DepositContractResponse.data:type_name -> ethereum.eth.v1.DepositContract
50, // 25: ethereum.eth.v1.GenesisResponse.Genesis.genesis_time:type_name -> google.protobuf.Timestamp
51, // 26: ethereum.eth.v1.StateFinalityCheckpointResponse.StateFinalityCheckpoint.previous_justified:type_name -> ethereum.eth.v1.Checkpoint
51, // 27: ethereum.eth.v1.StateFinalityCheckpointResponse.StateFinalityCheckpoint.current_justified:type_name -> ethereum.eth.v1.Checkpoint
51, // 28: ethereum.eth.v1.StateFinalityCheckpointResponse.StateFinalityCheckpoint.finalized:type_name -> ethereum.eth.v1.Checkpoint
29, // [29:29] is the sub-list for method output_type
29, // [29:29] is the sub-list for method input_type
29, // [29:29] is the sub-list for extension type_name
29, // [29:29] is the sub-list for extension extendee
0, // [0:29] is the sub-list for field type_name
37, // 25: ethereum.eth.v1.WeakSubjectivityResponse.data:type_name -> ethereum.eth.v1.WeakSubjectivityData
52, // 26: ethereum.eth.v1.WeakSubjectivityData.ws_checkpoint:type_name -> ethereum.eth.v1.Checkpoint
53, // 27: ethereum.eth.v1.GenesisResponse.Genesis.genesis_time:type_name -> google.protobuf.Timestamp
52, // 28: ethereum.eth.v1.StateFinalityCheckpointResponse.StateFinalityCheckpoint.previous_justified:type_name -> ethereum.eth.v1.Checkpoint
52, // 29: ethereum.eth.v1.StateFinalityCheckpointResponse.StateFinalityCheckpoint.current_justified:type_name -> ethereum.eth.v1.Checkpoint
52, // 30: ethereum.eth.v1.StateFinalityCheckpointResponse.StateFinalityCheckpoint.finalized:type_name -> ethereum.eth.v1.Checkpoint
31, // [31:31] is the sub-list for method output_type
31, // [31:31] is the sub-list for method input_type
31, // [31:31] is the sub-list for extension type_name
31, // [31:31] is the sub-list for extension extendee
0, // [0:31] is the sub-list for field type_name
}
func init() { file_proto_eth_v1_beacon_chain_proto_init() }
@@ -2845,7 +2964,7 @@ func file_proto_eth_v1_beacon_chain_proto_init() {
}
}
file_proto_eth_v1_beacon_chain_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GenesisResponse_Genesis); i {
switch v := v.(*WeakSubjectivityResponse); i {
case 0:
return &v.state
case 1:
@@ -2857,7 +2976,7 @@ func file_proto_eth_v1_beacon_chain_proto_init() {
}
}
file_proto_eth_v1_beacon_chain_proto_msgTypes[37].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*StateRootResponse_StateRoot); i {
switch v := v.(*WeakSubjectivityData); i {
case 0:
return &v.state
case 1:
@@ -2869,6 +2988,30 @@ func file_proto_eth_v1_beacon_chain_proto_init() {
}
}
file_proto_eth_v1_beacon_chain_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GenesisResponse_Genesis); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_proto_eth_v1_beacon_chain_proto_msgTypes[39].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*StateRootResponse_StateRoot); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_proto_eth_v1_beacon_chain_proto_msgTypes[40].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*StateFinalityCheckpointResponse_StateFinalityCheckpoint); i {
case 0:
return &v.state
@@ -2890,7 +3033,7 @@ func file_proto_eth_v1_beacon_chain_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_proto_eth_v1_beacon_chain_proto_rawDesc,
NumEnums: 0,
NumMessages: 40,
NumMessages: 42,
NumExtensions: 0,
NumServices: 0,
},

View File

@@ -270,3 +270,12 @@ message DepositContract {
// The address of the deployed deposit contract in use.
string address = 2;
}
message WeakSubjectivityResponse {
WeakSubjectivityData data = 1;
}
message WeakSubjectivityData {
ethereum.eth.v1.Checkpoint ws_checkpoint = 1;
bytes state_root = 2;
}

View File

@@ -36,6 +36,7 @@ ssz_gen_marshal(
],
objs = [
"SignedBeaconBlockAltair",
"SignedBeaconBlockMerge",
],
)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -314,24 +314,6 @@ func local_request_BeaconChain_GetChainHead_0(ctx context.Context, marshaler run
}
func request_BeaconChain_GetWeakSubjectivityCheckpoint_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconChainClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq emptypb.Empty
var metadata runtime.ServerMetadata
msg, err := client.GetWeakSubjectivityCheckpoint(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_BeaconChain_GetWeakSubjectivityCheckpoint_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconChainServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq emptypb.Empty
var metadata runtime.ServerMetadata
msg, err := server.GetWeakSubjectivityCheckpoint(ctx, &protoReq)
return msg, metadata, err
}
var (
filter_BeaconChain_ListBeaconCommittees_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
)
@@ -988,29 +970,6 @@ func RegisterBeaconChainHandlerServer(ctx context.Context, mux *runtime.ServeMux
})
mux.Handle("GET", pattern_BeaconChain_GetWeakSubjectivityCheckpoint_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
var stream runtime.ServerTransportStream
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconChain/GetWeakSubjectivityCheckpoint")
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_BeaconChain_GetWeakSubjectivityCheckpoint_0(rctx, inboundMarshaler, server, req, pathParams)
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_BeaconChain_GetWeakSubjectivityCheckpoint_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_BeaconChain_ListBeaconCommittees_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
@@ -1558,26 +1517,6 @@ func RegisterBeaconChainHandlerClient(ctx context.Context, mux *runtime.ServeMux
})
mux.Handle("GET", pattern_BeaconChain_GetWeakSubjectivityCheckpoint_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconChain/GetWeakSubjectivityCheckpoint")
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_BeaconChain_GetWeakSubjectivityCheckpoint_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_BeaconChain_GetWeakSubjectivityCheckpoint_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_BeaconChain_ListBeaconCommittees_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
@@ -1882,8 +1821,6 @@ var (
pattern_BeaconChain_GetChainHead_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "beacon", "chainhead"}, ""))
pattern_BeaconChain_GetWeakSubjectivityCheckpoint_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "beacon", "weak_subjectivity_checkpoint"}, ""))
pattern_BeaconChain_ListBeaconCommittees_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "beacon", "committees"}, ""))
pattern_BeaconChain_ListValidatorBalances_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "validators", "balances"}, ""))
@@ -1934,8 +1871,6 @@ var (
forward_BeaconChain_GetChainHead_0 = runtime.ForwardResponseMessage
forward_BeaconChain_GetWeakSubjectivityCheckpoint_0 = runtime.ForwardResponseMessage
forward_BeaconChain_ListBeaconCommittees_0 = runtime.ForwardResponseMessage
forward_BeaconChain_ListValidatorBalances_0 = runtime.ForwardResponseMessage

View File

@@ -150,16 +150,6 @@ service BeaconChain {
};
}
// Retrieve information about the weak subjectivity of the beacon chain from the view of
// the beacon chain node.
//
// This includes the weak subjectivity block root, state root and epoch number.
rpc GetWeakSubjectivityCheckpoint(google.protobuf.Empty) returns (WeakSubjectivityCheckpoint) {
option (google.api.http) = {
get: "/eth/v1alpha1/beacon/weak_subjectivity_checkpoint"
};
}
// Retrieve the beacon chain committees for a given epoch.
//
// If no filter criteria is specified, the response returns
@@ -904,13 +894,4 @@ message IndividualVotesRespond {
}
repeated IndividualVote individual_votes = 1;
}
message WeakSubjectivityCheckpoint {
// The block root of weak subjectivity checkpoint.
bytes block_root = 1;
// The state root of weak subjectivity checkpoint.
bytes state_root = 2;
// The epoch of weak subjectivity checkpoint.
uint64 epoch = 3 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/eth2-types.Epoch"];
}
}

View File

@@ -1,5 +1,5 @@
// Code generated by fastssz. DO NOT EDIT.
// Hash: 036fa88e7ecacbc13431c0b240e9aca847ce683c0568236674aebfd928cb3a63
// Hash: 5c2dafe1f4c2bcfd6acd77a1c392d1afb280053e41ac2af9e7aac2acf9f4cc05
package eth
import (

View File

@@ -73,6 +73,11 @@ func (w Phase0SignedBeaconBlock) UnmarshalSSZ(buf []byte) error {
return w.b.UnmarshalSSZ(buf)
}
// HashTreeRoot computes the HTR of the value by delegating to the underlying concrete type
func (w Phase0SignedBeaconBlock) HashTreeRoot() ([32]byte, error) {
return w.b.HashTreeRoot()
}
// Proto returns the block in its underlying protobuf
// interface.
func (w Phase0SignedBeaconBlock) Proto() proto.Message {

36
proto/sniff/BUILD.bazel Normal file
View File

@@ -0,0 +1,36 @@
load("@prysm//tools/go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = [
"initialize.go",
"sniffer.go",
],
importpath = "github.com/prysmaticlabs/prysm/proto/sniff",
visibility = ["//visibility:public"],
deps = [
"//beacon-chain/state:go_default_library",
"//beacon-chain/state/v1:go_default_library",
"//beacon-chain/state/v2:go_default_library",
"//beacon-chain/state/v3:go_default_library",
"//config/params:go_default_library",
"//encoding/bytesutil:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//proto/prysm/v1alpha1/block:go_default_library",
"//proto/prysm/v1alpha1/wrapper:go_default_library",
"//time/slots:go_default_library",
"@com_github_pkg_errors//:go_default_library",
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
],
)
go_test(
name = "go_default_test",
srcs = ["sniffer_test.go"],
embed = [":go_default_library"],
deps = [
"//proto/prysm/v1alpha1:go_default_library",
"//testing/require:go_default_library",
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
],
)

126
proto/sniff/initialize.go Normal file
View File

@@ -0,0 +1,126 @@
package sniff
import (
"fmt"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
v2 "github.com/prysmaticlabs/prysm/beacon-chain/state/v2"
v3 "github.com/prysmaticlabs/prysm/beacon-chain/state/v3"
"github.com/prysmaticlabs/prysm/config/params"
v1alpha1 "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper"
"github.com/prysmaticlabs/prysm/time/slots"
)
// BeaconStateForConfigFork uses metadata from the provided *ConfigFork to pick the right BeaconState schema
// to Unmarshal the value contained in the marshaled argument.
func BeaconStateForConfigFork(marshaled []byte, cf *ConfigFork) (state.BeaconState, error) {
cv, err := CurrentVersionFromState(marshaled)
if err != nil {
return nil, errors.Wrap(err, "in BeaconStateForConfigFork error from CurrentVersionFromState")
}
if cv != cf.Version {
return nil, fmt.Errorf("state fork version mismatch, detected=%#x, expected=%#x", cv, cf.Version)
}
var s state.BeaconState
switch cf.Fork {
case params.ForkGenesis:
s, err = v1.InitializeFromSSZBytes(marshaled)
if err != nil {
return nil, errors.Wrap(err, "InitializeFromSSZBytes for ForkGenesis failed")
}
case params.ForkAltair:
s, err = v2.InitializeFromSSZBytes(marshaled)
if err != nil {
return nil, errors.Wrap(err, "InitializeFromSSZBytes for ForkAltair failed")
}
case params.ForkMerge:
s, err = v3.InitializeFromSSZBytes(marshaled)
if err != nil {
return nil, errors.Wrap(err, "InitializeFromSSZBytes for ForkMerge failed")
}
default:
return nil, fmt.Errorf("unable to initialize BeaconState for fork version=%s", cf.Fork.String())
}
return s, nil
}
func BeaconState(marshaled []byte) (state.BeaconState, error) {
cf, err := ConfigForkForState(marshaled)
if err != nil {
return nil, errors.Wrap(err, "in sniff.BeaconState error from ConfigForkForState")
}
var s state.BeaconState
switch cf.Fork {
case params.ForkGenesis:
s, err = v1.InitializeFromSSZBytes(marshaled)
if err != nil {
return nil, errors.Wrap(err, "InitializeFromSSZBytes for ForkGenesis failed")
}
case params.ForkAltair:
s, err = v2.InitializeFromSSZBytes(marshaled)
if err != nil {
return nil, errors.Wrap(err, "InitializeFromSSZBytes for ForkAltair failed")
}
case params.ForkMerge:
s, err = v3.InitializeFromSSZBytes(marshaled)
if err != nil {
return nil, errors.Wrap(err, "InitializeFromSSZBytes for ForkMerge failed")
}
default:
return nil, fmt.Errorf("unable to initialize BeaconState for fork version=%s", cf.Fork.String())
}
return s, nil
}
// BlockForConfigFork attempts to unmarshal a block from a marshaled byte slice into the correct block type.
// In order to do this it needs to know what fork the block is from using ConfigFork, which can be obtained
// by using ConfigForkForState.
func BlockForConfigFork(b []byte, cf *ConfigFork) (block.SignedBeaconBlock, error) {
slot, err := SlotFromBlock(b)
if err != nil {
return nil, err
}
// heuristic to make sure block is from the same version as the state
// based on the fork schedule for the Config detected from the state
// get the version that corresponds to the epoch the block is from according to the fork choice schedule
// and make sure that the version is the same one that was pulled from the state
epoch := slots.ToEpoch(slot)
fs := cf.Config.OrderedForkSchedule()
ver, err := fs.VersionForEpoch(epoch)
if err != nil {
return nil, err
}
if ver != cf.Version {
return nil, fmt.Errorf("cannot sniff block schema, block (slot=%d, epoch=%d) is on a different fork", slot, epoch)
}
switch cf.Fork {
case params.ForkGenesis:
blk := &v1alpha1.SignedBeaconBlock{}
err := blk.UnmarshalSSZ(b)
if err != nil {
return nil, errors.Wrap(err, "failed to unmarshal SignedBeaconBlock in BlockFromSSZReader")
}
return wrapper.WrappedPhase0SignedBeaconBlock(blk), nil
case params.ForkAltair:
blk := &v1alpha1.SignedBeaconBlockAltair{}
err := blk.UnmarshalSSZ(b)
if err != nil {
return nil, errors.Wrap(err, "failed to unmarshal SignedBeaconBlockAltair in BlockFromSSZReader")
}
return wrapper.WrappedAltairSignedBeaconBlock(blk)
case params.ForkMerge:
blk := &v1alpha1.SignedBeaconBlockMerge{}
err := blk.UnmarshalSSZ(b)
if err != nil {
return nil, errors.Wrap(err, "failed to unmarshal SignedBeaconBlockMerge in BlockFromSSZReader")
}
return wrapper.WrappedMergeSignedBeaconBlock(blk)
}
return nil, fmt.Errorf("unable to initialize BeaconBlock for fork version=%s at slot=%d", cf.Fork.String(), slot)
}

148
proto/sniff/sniffer.go Normal file
View File

@@ -0,0 +1,148 @@
package sniff
import (
"encoding/binary"
"fmt"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/config/params"
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
)
type fieldType int
const (
TypeUint64 fieldType = iota
TypeBytes4
TypeByteSlice
TypeRoot
TypeContainer
)
type fieldSpec struct {
offset int
size int
t fieldType
}
func (f *fieldSpec) Uint64(state []byte) (uint64, error) {
if f.t != TypeUint64 {
return 0, fmt.Errorf("Uint64 called on non-uint64 field: %v", f)
}
s, err := f.slice(state)
if err != nil {
return 0, err
}
return binary.LittleEndian.Uint64(s), nil
}
func (f *fieldSpec) Bytes4(state []byte) ([4]byte, error) {
var b4 [4]byte
if f.t != TypeBytes4 {
return b4, fmt.Errorf("Bytes4 called on non-bytes4 field %v", f)
}
if f.size != 4 {
return b4, fmt.Errorf("Bytes4 types must have a size of 4, invalid fieldSpec %v", f)
}
val, err := f.slice(state)
if err != nil {
return b4, err
}
return bytesutil.ToBytes4(val), nil
}
func (f *fieldSpec) slice(value []byte) ([]byte, error) {
if len(value) < f.offset+f.size {
return nil, fmt.Errorf("cannot pull bytes from value; offset=%d, size=%d, so value must be at least %d bytes (actual=%d)", f.offset, f.size, f.offset+f.size, len(value))
}
return value[f.offset : f.offset+f.size], nil
}
var beaconStateCurrentVersion = fieldSpec{
// 52 = 8 (genesis_time) + 32 (genesis_validators_root) + 8 (slot) + 4 (previous_version)
offset: 52,
size: 4,
t: TypeBytes4,
}
var beaconStateEpoch = fieldSpec{
// 52 = 8 (genesis_time) + 32 (genesis_validators_root) + 8 (slot) + 4 (previous_version) + 4 (current_version)
offset: 56,
size: 8,
t: TypeUint64,
}
type ConfigFork struct {
ConfigName params.ConfigName
Fork params.ForkName
Config *params.BeaconChainConfig
Version [4]byte
Epoch types.Epoch
}
func ConfigForkForState(marshaled []byte) (*ConfigFork, error) {
cv, err := CurrentVersionFromState(marshaled)
if err != nil {
return nil, err
}
return FindConfigFork(cv)
}
func CurrentVersionFromState(marshaled []byte) ([4]byte, error) {
return beaconStateCurrentVersion.Bytes4(marshaled)
}
func EpochFromState(marshaled []byte) (types.Epoch, error) {
epoch, err := beaconStateEpoch.Uint64(marshaled)
if err != nil {
return types.Epoch(0), err
}
return types.Epoch(epoch), nil
}
func FindConfigFork(cv [4]byte) (*ConfigFork, error) {
cf := &ConfigFork{
Version: cv,
}
for name, cfg := range params.AllConfigs() {
genesis := bytesutil.ToBytes4(cfg.GenesisForkVersion)
altair := bytesutil.ToBytes4(cfg.AltairForkVersion)
merge := bytesutil.ToBytes4(cfg.MergeForkVersion)
for v, e := range cfg.ForkVersionSchedule {
if v == cv {
cf.ConfigName = name
cf.Config = cfg
cf.Epoch = e
switch v {
case genesis:
cf.Fork = params.ForkGenesis
case altair:
cf.Fork = params.ForkAltair
case merge:
cf.Fork = params.ForkMerge
default:
return cf, fmt.Errorf("unrecognized fork for config name=%s, BeaconState.fork.current_version=%#x", name.String(), cv)
}
return cf, nil
}
}
}
return cf, fmt.Errorf("could not find a config+fork match with version=%#x", cv)
}
var beaconBlockSlot = fieldSpec{
// ssz variable length offset (not to be confused with the fieldSpec offest) is a uint32
// variable length offsets come before fixed length data, so that's 4 bytes at the beginning
// then signature is 96 bytes, 4+96 = 100
offset: 100,
size: 8,
t: TypeUint64,
}
func SlotFromBlock(marshaled []byte) (types.Slot, error) {
slot, err := beaconBlockSlot.Uint64(marshaled)
if err != nil {
return 0, err
}
return types.Slot(slot), nil
}

135
proto/sniff/sniffer_test.go Normal file
View File

@@ -0,0 +1,135 @@
package sniff
import (
"testing"
types "github.com/prysmaticlabs/eth2-types"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/testing/require"
)
func TestSlotFromBlock(t *testing.T) {
b := testBlock()
var slot types.Slot = 3
b.Block.Slot = slot
bb, err := b.MarshalSSZ()
require.NoError(t, err)
sfb, err := SlotFromBlock(bb)
require.NoError(t, err)
require.Equal(t, slot, sfb)
ba := testBlockAltair()
ba.Block.Slot = slot
bab, err := ba.MarshalSSZ()
require.NoError(t, err)
sfba, err := SlotFromBlock(bab)
require.NoError(t, err)
require.Equal(t, slot, sfba)
bm := testBlockMerge()
bm.Block.Slot = slot
bmb, err := ba.MarshalSSZ()
require.NoError(t, err)
sfbm, err := SlotFromBlock(bmb)
require.NoError(t, err)
require.Equal(t, slot, sfbm)
}
func testBlock() *ethpb.SignedBeaconBlock {
return &ethpb.SignedBeaconBlock{
Block: &ethpb.BeaconBlock{
ProposerIndex: types.ValidatorIndex(0),
ParentRoot: make([]byte, 32),
StateRoot: make([]byte, 32),
Body: &ethpb.BeaconBlockBody{
RandaoReveal: make([]byte, 96),
Graffiti: make([]byte, 32),
ProposerSlashings: []*ethpb.ProposerSlashing{},
AttesterSlashings: []*ethpb.AttesterSlashing{},
Attestations: []*ethpb.Attestation{},
Deposits: []*ethpb.Deposit{},
VoluntaryExits: []*ethpb.SignedVoluntaryExit{},
Eth1Data: &ethpb.Eth1Data{
DepositRoot: make([]byte, 32),
DepositCount: 0,
BlockHash: make([]byte, 32),
},
},
},
Signature: make([]byte, 96),
}
}
func testBlockAltair() *ethpb.SignedBeaconBlockAltair {
return &ethpb.SignedBeaconBlockAltair{
Block: &ethpb.BeaconBlockAltair{
ProposerIndex: types.ValidatorIndex(0),
ParentRoot: make([]byte, 32),
StateRoot: make([]byte, 32),
Body: &ethpb.BeaconBlockBodyAltair{
RandaoReveal: make([]byte, 96),
Eth1Data: &ethpb.Eth1Data{
DepositRoot: make([]byte, 32),
DepositCount: 0,
BlockHash: make([]byte, 32),
},
Graffiti: make([]byte, 32),
ProposerSlashings: []*ethpb.ProposerSlashing{},
AttesterSlashings: []*ethpb.AttesterSlashing{},
Attestations: []*ethpb.Attestation{},
Deposits: []*ethpb.Deposit{},
VoluntaryExits: []*ethpb.SignedVoluntaryExit{},
SyncAggregate: &ethpb.SyncAggregate{
SyncCommitteeBits: make([]byte, 64),
SyncCommitteeSignature: make([]byte, 96),
},
},
},
Signature: make([]byte, 96),
}
}
func testBlockMerge() *ethpb.SignedBeaconBlockMerge {
return &ethpb.SignedBeaconBlockMerge{
Block: &ethpb.BeaconBlockMerge{
ProposerIndex: types.ValidatorIndex(0),
ParentRoot: make([]byte, 32),
StateRoot: make([]byte, 32),
Body: &ethpb.BeaconBlockBodyMerge{
RandaoReveal: make([]byte, 96),
Eth1Data: &ethpb.Eth1Data{
DepositRoot: make([]byte, 32),
DepositCount: 0,
BlockHash: make([]byte, 32),
},
Graffiti: make([]byte, 32),
ProposerSlashings: []*ethpb.ProposerSlashing{},
AttesterSlashings: []*ethpb.AttesterSlashing{},
Attestations: []*ethpb.Attestation{},
Deposits: []*ethpb.Deposit{},
VoluntaryExits: []*ethpb.SignedVoluntaryExit{},
SyncAggregate: &ethpb.SyncAggregate{
SyncCommitteeBits: make([]byte, 64),
SyncCommitteeSignature: make([]byte, 96),
},
ExecutionPayload: &ethpb.ExecutionPayload{
ParentHash: make([]byte, 32),
FeeRecipient: make([]byte, 20),
StateRoot: make([]byte, 32),
ReceiptRoot: make([]byte, 32),
LogsBloom: make([]byte, 256),
Random: make([]byte, 32),
BlockNumber: 0,
GasLimit: 0,
GasUsed: 0,
Timestamp: 0,
ExtraData: make([]byte, 32),
BaseFeePerGas: make([]byte, 32),
BlockHash: make([]byte, 32),
Transactions: make([][]byte, 0),
},
},
},
Signature: make([]byte, 96),
}
}

View File

@@ -36,7 +36,12 @@ go_test(
"//beacon-chain/state/stategen:go_default_library",
"//config/params:go_default_library",
"//crypto/bls:go_default_library",
"//encoding/bytesutil:go_default_library",
"//proto/eth/service:go_default_library",
"//proto/eth/v1:go_default_library",
"//proto/eth/v2:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//proto/sniff:go_default_library",
"//testing/assert:go_default_library",
"//testing/endtoend/components:go_default_library",
"//testing/endtoend/evaluators:go_default_library",
@@ -46,11 +51,14 @@ go_test(
"//testing/require:go_default_library",
"//testing/slasher/simulator:go_default_library",
"//testing/util:go_default_library",
"//time/slots:go_default_library",
"@com_github_pkg_errors//:go_default_library",
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
"@com_github_sirupsen_logrus//hooks/test:go_default_library",
"@org_golang_google_grpc//:go_default_library",
"@org_golang_google_grpc//codes:go_default_library",
"@org_golang_google_grpc//status:go_default_library",
"@org_golang_google_protobuf//types/known/emptypb:go_default_library",
"@org_golang_x_sync//errgroup:go_default_library",
],

View File

@@ -27,9 +27,10 @@ var _ e2etypes.ComponentRunner = (*BeaconNodeSet)(nil)
// BeaconNodeSet represents set of beacon nodes.
type BeaconNodeSet struct {
e2etypes.ComponentRunner
config *e2etypes.E2EConfig
enr string
started chan struct{}
flags []string
usePprof bool
enr string
started chan struct{}
}
// SetENR assigns ENR to the set of beacon nodes.
@@ -38,10 +39,11 @@ func (s *BeaconNodeSet) SetENR(enr string) {
}
// NewBeaconNodes creates and returns a set of beacon nodes.
func NewBeaconNodes(config *e2etypes.E2EConfig) *BeaconNodeSet {
func NewBeaconNodes(flags []string, usePprof bool) *BeaconNodeSet {
return &BeaconNodeSet{
config: config,
started: make(chan struct{}, 1),
flags: flags,
usePprof: usePprof,
started: make(chan struct{}, 1),
}
}
@@ -54,7 +56,7 @@ func (s *BeaconNodeSet) Start(ctx context.Context) error {
// Create beacon nodes.
nodes := make([]e2etypes.ComponentRunner, e2e.TestParams.BeaconNodeCount)
for i := 0; i < e2e.TestParams.BeaconNodeCount; i++ {
nodes[i] = NewBeaconNode(s.config, i, s.enr)
nodes[i] = NewBeaconNode(i, s.enr, s.flags, s.usePprof)
}
// Wait for all nodes to finish their job (blocking).
@@ -73,19 +75,21 @@ func (s *BeaconNodeSet) Started() <-chan struct{} {
// BeaconNode represents beacon node.
type BeaconNode struct {
e2etypes.ComponentRunner
config *e2etypes.E2EConfig
started chan struct{}
index int
enr string
flags []string
usePprof bool
started chan struct{}
index int
enr string
}
// NewBeaconNode creates and returns a beacon node.
func NewBeaconNode(config *e2etypes.E2EConfig, index int, enr string) *BeaconNode {
func NewBeaconNode(index int, enr string, flags []string, usePprof bool) *BeaconNode {
return &BeaconNode{
config: config,
index: index,
enr: enr,
started: make(chan struct{}, 1),
index: index,
enr: enr,
started: make(chan struct{}, 1),
flags: flags,
usePprof: usePprof,
}
}
@@ -97,7 +101,7 @@ func (node *BeaconNode) Start(ctx context.Context) error {
return errors.New("beacon chain binary not found")
}
config, index, enr := node.config, node.index, node.enr
nodeFlags, index, enr := node.flags, node.index, node.enr
stdOutFile, err := helpers.DeleteAndCreateFile(e2e.TestParams.LogPath, fmt.Sprintf(e2e.BeaconNodeLogFileName, index))
if err != nil {
return err
@@ -123,11 +127,11 @@ func (node *BeaconNode) Start(ctx context.Context) error {
"--" + cmdshared.E2EConfigFlag.Name,
"--" + cmdshared.AcceptTosFlag.Name,
}
if config.UsePprof {
if node.usePprof {
args = append(args, "--pprof", fmt.Sprintf("--pprofport=%d", e2e.TestParams.BeaconNodeRPCPort+index+50))
}
args = append(args, features.E2EBeaconChainFlags...)
args = append(args, config.BeaconFlags...)
args = append(args, nodeFlags...)
cmd := exec.CommandContext(ctx, binaryPath, args...) // #nosec G204 -- Safe
// Write stdout and stderr to log files.

View File

@@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"
"github.com/prysmaticlabs/prysm/config/params"
"io/ioutil"
"os/exec"
"strings"
@@ -48,10 +49,12 @@ func (node *BootNode) Start(ctx context.Context) error {
return err
}
cfg := params.E2ETestConfig()
args := []string{
fmt.Sprintf("--log-file=%s", stdOutFile.Name()),
fmt.Sprintf("--discv5-port=%d", e2e.TestParams.BootNodePort),
fmt.Sprintf("--metrics-port=%d", e2e.TestParams.BootNodePort+20),
fmt.Sprintf("--fork-version=%#x", cfg.GenesisForkVersion),
"--debug",
}

View File

@@ -18,7 +18,12 @@ import (
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/beacon-chain/core/transition"
"github.com/prysmaticlabs/prysm/config/params"
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
"github.com/prysmaticlabs/prysm/proto/eth/service"
v1 "github.com/prysmaticlabs/prysm/proto/eth/v1"
eth2 "github.com/prysmaticlabs/prysm/proto/eth/v2"
eth "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/sniff"
"github.com/prysmaticlabs/prysm/testing/assert"
"github.com/prysmaticlabs/prysm/testing/endtoend/components"
ev "github.com/prysmaticlabs/prysm/testing/endtoend/evaluators"
@@ -26,9 +31,12 @@ import (
e2e "github.com/prysmaticlabs/prysm/testing/endtoend/params"
e2etypes "github.com/prysmaticlabs/prysm/testing/endtoend/types"
"github.com/prysmaticlabs/prysm/testing/require"
"github.com/prysmaticlabs/prysm/time/slots"
log "github.com/sirupsen/logrus"
"golang.org/x/sync/errgroup"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/emptypb"
)
@@ -47,15 +55,23 @@ func init() {
// testRunner abstracts E2E test configuration and running.
type testRunner struct {
t *testing.T
config *e2etypes.E2EConfig
t *testing.T
config *e2etypes.E2EConfig
ctx context.Context
doneChan context.CancelFunc
group *errgroup.Group
}
// newTestRunner creates E2E test runner.
func newTestRunner(t *testing.T, config *e2etypes.E2EConfig) *testRunner {
ctx, done := context.WithCancel(context.Background())
g, ctx := errgroup.WithContext(ctx)
return &testRunner{
t: t,
config: config,
ctx: ctx,
doneChan: done,
group: g,
t: t,
config: config,
}
}
@@ -66,11 +82,15 @@ func (r *testRunner) run() {
t.Logf("Starting time: %s\n", time.Now().String())
t.Logf("Log Path: %s\n", e2e.TestParams.LogPath)
// we need debug turned on and max ssz payload bumped up when running checkpoint sync tests
if config.TestSync {
config.BeaconFlags = appendDebugEndpoints(config.BeaconFlags)
}
minGenesisActiveCount := int(params.BeaconConfig().MinGenesisActiveValidatorCount)
ctx, done := context.WithCancel(context.Background())
g, ctx := errgroup.WithContext(ctx)
ctx := r.ctx
g := r.group
done := r.doneChan
tracingSink := components.NewTracingSink(config.TracingSinkEndpoint)
g.Go(func() error {
return tracingSink.Start(ctx)
@@ -104,7 +124,7 @@ func (r *testRunner) run() {
})
// Beacon nodes.
beaconNodes := components.NewBeaconNodes(config)
beaconNodes := components.NewBeaconNodes(config.BeaconFlags, config.UsePprof)
g.Go(func() error {
if err := helpers.ComponentsStarted(ctx, []e2etypes.ComponentRunner{eth1Node, bootNode}); err != nil {
return errors.Wrap(err, "beacon nodes require ETH1 and boot node to run")
@@ -190,9 +210,13 @@ func (r *testRunner) run() {
if !config.TestSync {
return nil
}
if err := r.testBeaconChainSync(ctx, g, conns, tickingStartTime, bootNode.ENR()); err != nil {
index := e2e.TestParams.BeaconNodeCount
if err := r.testBeaconChainSync(index, conns, tickingStartTime, bootNode.ENR()); err != nil {
return errors.Wrap(err, "beacon chain sync test failed")
}
if err := r.testCheckpointSync(index+1, conns, tickingStartTime, bootNode.ENR()); err != nil {
return errors.Wrap(err, "checkpoint sync test failed")
}
if err := r.testDoppelGangerProtection(ctx); err != nil {
return errors.Wrap(err, "doppel ganger protection check failed")
}
@@ -208,6 +232,14 @@ func (r *testRunner) run() {
}
}
func appendDebugEndpoints(flags []string) []string {
debugFlags := []string{
"--enable-debug-rpc-endpoints",
"--grpc-max-msg-size=65568081",
}
return append(flags, debugFlags...)
}
// waitForChainStart allows to wait up until beacon nodes are started.
func (r *testRunner) waitForChainStart() {
// Sleep depending on the count of validators, as generating the genesis state could take some time.
@@ -275,35 +307,301 @@ func (r *testRunner) testDeposits(ctx context.Context, g *errgroup.Group,
})
}
// testBeaconChainSync creates another beacon node, and tests whether it can sync to head using previous nodes.
func (r *testRunner) testBeaconChainSync(ctx context.Context, g *errgroup.Group,
conns []*grpc.ClientConn, tickingStartTime time.Time, enr string) error {
t, config := r.t, r.config
index := e2e.TestParams.BeaconNodeCount
syncBeaconNode := components.NewBeaconNode(config, index, enr)
g.Go(func() error {
return syncBeaconNode.Start(ctx)
type saveable interface {
MarshalSSZ() ([]byte, error)
}
func saveSSZBytes(filePath string, value saveable) (err error) {
b, err := value.MarshalSSZ()
if err != nil {
err = errors.Wrap(err, "saveSSZBytes/MarshalSSZ")
return err
}
fh, err := os.Create(filePath)
if err != nil {
err = errors.Wrap(err, "saveSSZBytes/os.Create")
return err
}
defer func() {
err = errors.Wrap(err, "saveSSZBytes/defered close")
err = fh.Close()
}()
_, err = fh.Write(b)
if err != nil {
err = errors.Wrap(err, "saveSSZBytes/fh.Write")
}
return err
}
func saveBlock(ctx context.Context, conn *grpc.ClientConn, cf *sniff.ConfigFork, root [32]byte, basePath string) (string, error) {
v1Client := service.NewBeaconChainClient(conn)
//blockId := fmt.Sprintf("%#x", root)
bResp, err := v1Client.GetBlockSSZV2(ctx, &eth2.BlockRequestV2{BlockId: root[:]})
if err != nil {
err = errors.Wrap(err, "saveBlock/GetBeaconBlock")
return "", err
}
sb, err := sniff.BlockForConfigFork(bResp.GetData(), cf)
if err != nil {
err = errors.Wrap(err, "saveBlock/GetBeaconBlock")
return "", err
}
p := path.Join(basePath, fmt.Sprintf("block_%d_%x.ssz", sb.Block().Slot(), root))
err = saveSSZBytes(p, sb)
if err != nil {
err = errors.Wrap(err, "saveBlock/saveSSZBytes")
}
return p, err
}
func getConfigFork(ctx context.Context, conn *grpc.ClientConn, slot types.Slot) (*sniff.ConfigFork, error) {
ofs, err := getOrderedForkSchedule(ctx, conn)
if err != nil {
err = errors.Wrap(err, "getConfigFork/getOrderedForkSchedule")
return nil, err
}
epoch := slots.ToEpoch(slot)
version, err := ofs.VersionForEpoch(epoch)
if err != nil {
err = errors.Wrap(err, "getConfigFork/VersionForEpoch")
return nil, err
}
cf, err := sniff.FindConfigFork(version)
if err != nil {
err = errors.Wrap(err, "getConfigFork/FindConfigFork")
return nil, err
}
return cf, nil
}
func saveState(ctx context.Context, conn *grpc.ClientConn, cf *sniff.ConfigFork, slot types.Slot, basePath string) (string, [32]byte, error) {
debugClient := service.NewBeaconDebugClient(conn)
stateId := []byte(fmt.Sprintf("%d", slot))
sResp, err := debugClient.GetBeaconStateSSZV2(ctx, &eth2.StateRequestV2{StateId: stateId})
if err != nil {
err = errors.Wrap(err, "saveState/GetBeaconState")
return "", [32]byte{}, err
}
state, err := sniff.BeaconStateForConfigFork(sResp.Data, cf)
if err != nil {
return "", [32]byte{}, errors.Wrap(err, "saveState/BeaconStateForConfigFork")
}
stateRoot, err := state.HashTreeRoot(ctx)
if err != nil {
return "", [32]byte{}, errors.Wrap(err, "saveState/BeaconStateForConfigFork")
}
p := path.Join(basePath, fmt.Sprintf("state_%d_%x.ssz", state.Slot(), stateRoot))
err = saveSSZBytes(p, state)
if err != nil {
err = errors.Wrap(err, "saveState/saveSSZBytes")
}
return p, stateRoot, err
}
type checkpoint struct {
statePath string
stateRoot [32]byte
blockPath string
blockRoot [32]byte
headRoot [32]byte
epoch types.Epoch
}
func (c *checkpoint) flags() []string {
return []string{
fmt.Sprintf("--checkpoint-state=%s", c.statePath),
fmt.Sprintf("--checkpoint-block=%s", c.blockPath),
fmt.Sprintf("--weak-subjectivity-checkpoint=%x:%d", c.blockRoot, c.epoch),
}
}
func getOrderedForkSchedule(ctx context.Context, conn *grpc.ClientConn) (params.OrderedForkSchedule, error) {
v1Client := service.NewBeaconChainClient(conn)
fsResp, err := v1Client.GetForkSchedule(ctx, &emptypb.Empty{})
if err != nil {
err = errors.Wrap(err, "getOrderedForkSchedule:GetForkSchedule")
return nil, err
}
ofs := make(params.OrderedForkSchedule, 0)
for _, f := range fsResp.Data {
ofs = append(ofs, params.ForkScheduleEntry{
Version: bytesutil.ToBytes4(f.CurrentVersion),
Epoch: f.Epoch,
})
}
return ofs, nil
}
func getHeadBlockRoot(ctx context.Context, conn *grpc.ClientConn) ([32]byte, error) {
v1Client := service.NewBeaconChainClient(conn)
bResp, err := v1Client.GetBlockRoot(ctx, &v1.BlockRequest{BlockId: []byte("head")})
if err != nil {
err = errors.Wrap(err, "getHeadBlockRoot:GetBlockRoot")
return [32]byte{}, err
}
return bytesutil.ToBytes32(bResp.Data.Root), nil
}
func DownloadCheckpoint(ctx context.Context, conn *grpc.ClientConn) (*checkpoint, error) {
v1Client := service.NewBeaconChainClient(conn)
resp, err := v1Client.GetWeakSubjectivity(ctx, &emptypb.Empty{})
if err != nil {
err = errors.Wrap(err, "DownloadCheckpoint:GetWeakSubjectivityCheckpointEpoch")
return nil, err
}
ws := resp.Data
cp := &checkpoint{
epoch: ws.WsCheckpoint.Epoch,
stateRoot: bytesutil.ToBytes32(ws.StateRoot),
blockRoot: bytesutil.ToBytes32(ws.WsCheckpoint.Root),
}
headRoot, err := getHeadBlockRoot(ctx, conn)
if err != nil {
err = errors.Wrap(err, "DownloadCheckpoint:getHeadBlockRoot")
return nil, err
}
cp.headRoot = headRoot
// save the block at epoch start slot
wsSlot, err := slots.EpochStart(cp.epoch)
if err != nil {
err = errors.Wrap(err, "DownloadCheckpoint:EpochStart")
return nil, err
}
// fetch the state for the slot immediately following (and therefore integrating) the block
cf, err := getConfigFork(ctx, conn, wsSlot)
if err != nil {
err = errors.Wrap(err, "DownloadCheckpoint:getConfigFork")
return nil, err
}
cp.blockPath, err = saveBlock(ctx, conn, cf, cp.blockRoot, e2e.TestParams.TestPath)
if err != nil {
err = errors.Wrap(err, "DownloadCheckpoint:saveBlock")
return nil, err
}
var sr [32]byte
cp.statePath, sr, err = saveState(ctx, conn, cf, wsSlot, e2e.TestParams.TestPath)
if err != nil {
err = errors.Wrap(err, "DownloadCheckpoint:saveState")
return nil, err
}
if sr != cp.stateRoot {
err = fmt.Errorf("state htr (%#x) at slot %d != weak_subjectivity response (%#x)", cp.stateRoot, wsSlot, sr)
return nil, err
}
return cp, nil
}
func (r *testRunner) waitForSentinelBlock(ctx context.Context, conn *grpc.ClientConn, root [32]byte) error {
// sleep hack copied from testBeaconChainSync
// Sleep a second for every 4 blocks that need to be synced for the newly started node.
secondsPerEpoch := uint64(params.BeaconConfig().SlotsPerEpoch.Mul(params.BeaconConfig().SecondsPerSlot))
extraSecondsToSync := (r.config.EpochsToRun)*secondsPerEpoch + uint64(params.BeaconConfig().SlotsPerEpoch.Div(4).Mul(r.config.EpochsToRun))
ctx, cancel := context.WithDeadline(r.ctx, time.Now().Add(time.Second*time.Duration(extraSecondsToSync)))
defer cancel()
for {
select {
case <-ctx.Done():
// deadline ensures that the test eventually exits when beacon node fails to sync in a resonable timeframe
return fmt.Errorf("deadline exceeded waiting for known good block to appear in checkpoint-synced node")
case <-time.After(time.Second * 1):
v1Client := service.NewBeaconChainClient(conn)
bResp, err := v1Client.GetBlockRoot(ctx, &v1.BlockRequest{BlockId: []byte("head")})
if err != nil {
errStatus, ok := status.FromError(err)
// in the happy path we expect NotFound results until the node has synced
if ok && errStatus.Code() == codes.NotFound {
continue
}
return fmt.Errorf("error requesting block w/ root '%x' = %s", root, err)
}
// we have a match, sentinel block found
if bytesutil.ToBytes32(bResp.Data.Root) == root {
return nil
}
}
}
}
func (r *testRunner) testCheckpointSync(i int, conns []*grpc.ClientConn, tickingStartTime time.Time, enr string) error {
conn := conns[0]
cp, err := DownloadCheckpoint(r.ctx, conn)
if err != nil {
return err
}
flags := append(r.config.BeaconFlags, cp.flags()...)
usePprof := r.config.UsePprof
// zero-indexed, so next value would be len of list
cpsyncer := components.NewBeaconNode(i, enr, flags, usePprof)
r.group.Go(func() error {
return cpsyncer.Start(r.ctx)
})
if err := helpers.ComponentsStarted(ctx, []e2etypes.ComponentRunner{syncBeaconNode}); err != nil {
if err := helpers.ComponentsStarted(r.ctx, []e2etypes.ComponentRunner{cpsyncer}); err != nil {
return fmt.Errorf("checkpoint sync beacon node not ready: %w", err)
}
c, err := grpc.Dial(fmt.Sprintf("127.0.0.1:%d", e2e.TestParams.BeaconNodeRPCPort+i), grpc.WithInsecure())
require.NoError(r.t, err, "Failed to dial")
// this is so that the syncEvaluators checks can run on the checkpoint sync'd node
conns = append(conns, c)
err = r.waitForSentinelBlock(r.ctx, conn, cp.headRoot)
if err != nil {
return err
}
syncLogFile, err := os.Open(path.Join(e2e.TestParams.LogPath, fmt.Sprintf(e2e.BeaconNodeLogFileName, i)))
require.NoError(r.t, err)
defer helpers.LogErrorOutput(r.t, syncLogFile, "beacon chain node", i)
r.t.Run("sync completed", func(t *testing.T) {
assert.NoError(t, helpers.WaitForTextInFile(syncLogFile, "Synced up to"), "Failed to sync")
})
if r.t.Failed() {
return errors.New("cannot sync beacon node")
}
syncEvaluators := []e2etypes.Evaluator{ev.FinishedSyncing, ev.AllNodesHaveSameHead}
for _, evaluator := range syncEvaluators {
r.t.Run(evaluator.Name, func(t *testing.T) {
assert.NoError(t, evaluator.Evaluation(conns...), "Evaluation failed for sync node")
})
}
return nil
}
// testBeaconChainSync creates another beacon node, and tests whether it can sync to head using previous nodes.
func (r *testRunner) testBeaconChainSync(index int, conns []*grpc.ClientConn, tickingStartTime time.Time, enr string) error {
syncBeaconNode := components.NewBeaconNode(index, enr, r.config.BeaconFlags, r.config.UsePprof)
r.group.Go(func() error {
return syncBeaconNode.Start(r.ctx)
})
if err := helpers.ComponentsStarted(r.ctx, []e2etypes.ComponentRunner{syncBeaconNode}); err != nil {
return fmt.Errorf("sync beacon node not ready: %w", err)
}
syncConn, err := grpc.Dial(fmt.Sprintf("127.0.0.1:%d", e2e.TestParams.BeaconNodeRPCPort+index), grpc.WithInsecure())
require.NoError(t, err, "Failed to dial")
require.NoError(r.t, err, "Failed to dial")
conns = append(conns, syncConn)
// Sleep a second for every 4 blocks that need to be synced for the newly started node.
secondsPerEpoch := uint64(params.BeaconConfig().SlotsPerEpoch.Mul(params.BeaconConfig().SecondsPerSlot))
extraSecondsToSync := (config.EpochsToRun)*secondsPerEpoch + uint64(params.BeaconConfig().SlotsPerEpoch.Div(4).Mul(config.EpochsToRun))
extraSecondsToSync := (r.config.EpochsToRun)*secondsPerEpoch + uint64(params.BeaconConfig().SlotsPerEpoch.Div(4).Mul(r.config.EpochsToRun))
waitForSync := tickingStartTime.Add(time.Duration(extraSecondsToSync) * time.Second)
time.Sleep(time.Until(waitForSync))
syncLogFile, err := os.Open(path.Join(e2e.TestParams.LogPath, fmt.Sprintf(e2e.BeaconNodeLogFileName, index)))
require.NoError(t, err)
defer helpers.LogErrorOutput(t, syncLogFile, "beacon chain node", index)
t.Run("sync completed", func(t *testing.T) {
require.NoError(r.t, err)
defer helpers.LogErrorOutput(r.t, syncLogFile, "beacon chain node", index)
r.t.Run("sync completed", func(t *testing.T) {
assert.NoError(t, helpers.WaitForTextInFile(syncLogFile, "Synced up to"), "Failed to sync")
})
if t.Failed() {
if r.t.Failed() {
return errors.New("cannot sync beacon node")
}
@@ -311,7 +609,7 @@ func (r *testRunner) testBeaconChainSync(ctx context.Context, g *errgroup.Group,
time.Sleep(time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second)
syncEvaluators := []e2etypes.Evaluator{ev.FinishedSyncing, ev.AllNodesHaveSameHead}
for _, evaluator := range syncEvaluators {
t.Run(evaluator.Name, func(t *testing.T) {
r.t.Run(evaluator.Name, func(t *testing.T) {
assert.NoError(t, evaluator.Evaluation(conns...), "Evaluation failed for sync node")
})
}

View File

@@ -23,6 +23,7 @@ type params struct {
ContractAddress common.Address
BootNodePort int
BeaconNodeRPCPort int
BeaconNodeOAPIPort int
BeaconNodeMetricsPort int
ValidatorMetricsPort int
ValidatorGatewayPort int

View File

@@ -218,24 +218,24 @@ func (mr *MockBeaconChainClientMockRecorder) GetValidatorQueue(arg0, arg1 interf
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetValidatorQueue", reflect.TypeOf((*MockBeaconChainClient)(nil).GetValidatorQueue), varargs...)
}
// GetWeakSubjectivityCheckpoint mocks base method
func (m *MockBeaconChainClient) GetWeakSubjectivityCheckpoint(arg0 context.Context, arg1 *emptypb.Empty, arg2 ...grpc.CallOption) (*eth.WeakSubjectivityCheckpoint, error) {
// GetWeakSubjectivityCheckpointEpoch mock implementation
func (m *MockBeaconChainClient) GetWeakSubjectivityCheckpointEpoch(arg0 context.Context, arg1 *emptypb.Empty, arg2 ...grpc.CallOption) (*eth.WeakSubjectivityCheckpointEpoch, error) {
m.ctrl.T.Helper()
varargs := []interface{}{arg0, arg1}
for _, a := range arg2 {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "GetWeakSubjectivityCheckpoint", varargs...)
ret0, _ := ret[0].(*eth.WeakSubjectivityCheckpoint)
ret := m.ctrl.Call(m, "GetWeakSubjectivityCheckpointEpoch", varargs...)
ret0, _ := ret[0].(*eth.WeakSubjectivityCheckpointEpoch)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetWeakSubjectivityCheckpoint indicates an expected call of GetWeakSubjectivityCheckpoint
func (mr *MockBeaconChainClientMockRecorder) GetWeakSubjectivityCheckpoint(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call {
// GetWeakSubjectivityCheckpointEpoch impersonates the GetWeakSubjectivityCheckpointEpoch and records the parameters
func (mr *MockBeaconChainClientMockRecorder) GetWeakSubjectivityCheckpointEpoch(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
varargs := append([]interface{}{arg0, arg1}, arg2...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetWeakSubjectivityCheckpoint", reflect.TypeOf((*MockBeaconChainClient)(nil).GetWeakSubjectivityCheckpoint), varargs...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetWeakSubjectivityCheckpointEpoch", reflect.TypeOf((*MockBeaconChainClient)(nil).GetWeakSubjectivityCheckpointEpoch), varargs...)
}
// ListAttestations mocks base method

View File

@@ -192,8 +192,12 @@ func createLocalNode(privKey *ecdsa.PrivateKey, ipAddr net.IP, port int) (*enode
external = ipAddr
}
fVersion := params.BeaconConfig().GenesisForkVersion
if *forkVersion != "" {
fVersion, err = hex.DecodeString(*forkVersion)
fv := *forkVersion
if fv != "" {
if fv[0:2] == "0x" {
fv = fv[2:]
}
fVersion, err = hex.DecodeString(fv)
if err != nil {
return nil, errors.Wrap(err, "Could not retrieve fork version")
}