mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-10 13:58:09 -05:00
Compare commits
30 Commits
fixPrivate
...
processSlo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8a3c0e4dfb | ||
|
|
df2b47213a | ||
|
|
e9250e1d0d | ||
|
|
3efbc9d001 | ||
|
|
46acb4210f | ||
|
|
a16ab9b439 | ||
|
|
ae451a3a02 | ||
|
|
83fe9bc2f2 | ||
|
|
17561a6576 | ||
|
|
b842b7ea01 | ||
|
|
9bbe12e28c | ||
|
|
0674cf64cc | ||
|
|
3413d05b34 | ||
|
|
070a765d24 | ||
|
|
8ac1647436 | ||
|
|
dfe31c9242 | ||
|
|
b7866be3a9 | ||
|
|
8413660d5f | ||
|
|
e037491756 | ||
|
|
ea2624b5ab | ||
|
|
1b40f941cf | ||
|
|
57830435d7 | ||
|
|
44d850de51 | ||
|
|
b08e691127 | ||
|
|
968e82b02d | ||
|
|
de04ce8329 | ||
|
|
5efecff631 | ||
|
|
3ab759e163 | ||
|
|
836d369c6c | ||
|
|
568273453b |
@@ -48,8 +48,13 @@ func (n *NodeHealthTracker) CheckHealth(ctx context.Context) bool {
|
||||
if isStatusChanged {
|
||||
// Update the health status
|
||||
n.isHealthy = &newStatus
|
||||
// Send the new status to the health channel
|
||||
n.healthChan <- newStatus
|
||||
// Send the new status to the health channel, potentially overwriting the existing value
|
||||
select {
|
||||
case <-n.healthChan:
|
||||
n.healthChan <- newStatus
|
||||
default:
|
||||
n.healthChan <- newStatus
|
||||
}
|
||||
}
|
||||
return newStatus
|
||||
}
|
||||
|
||||
@@ -87,12 +87,6 @@ func TestNodeHealth_Concurrency(t *testing.T) {
|
||||
// Number of goroutines to spawn for both reading and writing
|
||||
numGoroutines := 6
|
||||
|
||||
go func() {
|
||||
for range n.HealthUpdates() {
|
||||
// Consume values to avoid blocking on channel send.
|
||||
}
|
||||
}()
|
||||
|
||||
wg.Add(numGoroutines * 2) // for readers and writers
|
||||
|
||||
// Concurrently update health status
|
||||
|
||||
@@ -3,6 +3,7 @@ package testing
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
"sync"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/iface"
|
||||
"go.uber.org/mock/gomock"
|
||||
@@ -16,6 +17,7 @@ var (
|
||||
type MockHealthClient struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockHealthClientMockRecorder
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
// MockHealthClientMockRecorder is the mock recorder for MockHealthClient.
|
||||
@@ -25,6 +27,8 @@ type MockHealthClientMockRecorder struct {
|
||||
|
||||
// IsHealthy mocks base method.
|
||||
func (m *MockHealthClient) IsHealthy(arg0 context.Context) bool {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "IsHealthy", arg0)
|
||||
ret0, ok := ret[0].(bool)
|
||||
@@ -41,6 +45,8 @@ func (m *MockHealthClient) EXPECT() *MockHealthClientMockRecorder {
|
||||
|
||||
// IsHealthy indicates an expected call of IsHealthy.
|
||||
func (mr *MockHealthClientMockRecorder) IsHealthy(arg0 any) *gomock.Call {
|
||||
mr.mock.Lock()
|
||||
defer mr.mock.Unlock()
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsHealthy", reflect.TypeOf((*MockHealthClient)(nil).IsHealthy), arg0)
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ go_library(
|
||||
"//validator:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
"//api/server:go_default_library",
|
||||
"//api/server/middleware:go_default_library",
|
||||
"//runtime:go_default_library",
|
||||
"@com_github_gorilla_mux//:go_default_library",
|
||||
"@com_github_grpc_ecosystem_grpc_gateway_v2//runtime:go_default_library",
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
"github.com/gorilla/mux"
|
||||
gwruntime "github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/middleware"
|
||||
"github.com/prysmaticlabs/prysm/v5/runtime"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/connectivity"
|
||||
@@ -104,7 +104,7 @@ func (g *Gateway) Start() {
|
||||
}
|
||||
}
|
||||
|
||||
corsMux := server.CorsHandler(g.cfg.allowedOrigins).Middleware(g.cfg.router)
|
||||
corsMux := middleware.CorsHandler(g.cfg.allowedOrigins).Middleware(g.cfg.router)
|
||||
|
||||
if g.cfg.muxHandler != nil {
|
||||
g.cfg.router.PathPrefix("/").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
@@ -2,29 +2,14 @@ load("@prysm//tools/go:def.bzl", "go_library", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"error.go",
|
||||
"middleware.go",
|
||||
"util.go",
|
||||
],
|
||||
srcs = ["error.go"],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v5/api/server",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"@com_github_gorilla_mux//:go_default_library",
|
||||
"@com_github_rs_cors//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"error_test.go",
|
||||
"middleware_test.go",
|
||||
"util_test.go",
|
||||
],
|
||||
srcs = ["error_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//testing/assert:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
],
|
||||
deps = ["//testing/assert:go_default_library"],
|
||||
)
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/rs/cors"
|
||||
)
|
||||
|
||||
// NormalizeQueryValuesHandler normalizes an input query of "key=value1,value2,value3" to "key=value1&key=value2&key=value3"
|
||||
func NormalizeQueryValuesHandler(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
query := r.URL.Query()
|
||||
NormalizeQueryValues(query)
|
||||
r.URL.RawQuery = query.Encode()
|
||||
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
// CorsHandler sets the cors settings on api endpoints
|
||||
func CorsHandler(allowOrigins []string) mux.MiddlewareFunc {
|
||||
c := cors.New(cors.Options{
|
||||
AllowedOrigins: allowOrigins,
|
||||
AllowedMethods: []string{http.MethodPost, http.MethodGet, http.MethodDelete, http.MethodOptions},
|
||||
AllowCredentials: true,
|
||||
MaxAge: 600,
|
||||
AllowedHeaders: []string{"*"},
|
||||
})
|
||||
|
||||
return c.Handler
|
||||
}
|
||||
29
api/server/middleware/BUILD.bazel
Normal file
29
api/server/middleware/BUILD.bazel
Normal file
@@ -0,0 +1,29 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_library", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"middleware.go",
|
||||
"util.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v5/api/server/middleware",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"@com_github_gorilla_mux//:go_default_library",
|
||||
"@com_github_rs_cors//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"middleware_test.go",
|
||||
"util_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//api:go_default_library",
|
||||
"//testing/assert:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
],
|
||||
)
|
||||
112
api/server/middleware/middleware.go
Normal file
112
api/server/middleware/middleware.go
Normal file
@@ -0,0 +1,112 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/rs/cors"
|
||||
)
|
||||
|
||||
// NormalizeQueryValuesHandler normalizes an input query of "key=value1,value2,value3" to "key=value1&key=value2&key=value3"
|
||||
func NormalizeQueryValuesHandler(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
query := r.URL.Query()
|
||||
NormalizeQueryValues(query)
|
||||
r.URL.RawQuery = query.Encode()
|
||||
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
// CorsHandler sets the cors settings on api endpoints
|
||||
func CorsHandler(allowOrigins []string) mux.MiddlewareFunc {
|
||||
c := cors.New(cors.Options{
|
||||
AllowedOrigins: allowOrigins,
|
||||
AllowedMethods: []string{http.MethodPost, http.MethodGet, http.MethodDelete, http.MethodOptions},
|
||||
AllowCredentials: true,
|
||||
MaxAge: 600,
|
||||
AllowedHeaders: []string{"*"},
|
||||
})
|
||||
|
||||
return c.Handler
|
||||
}
|
||||
|
||||
// ContentTypeHandler checks request for the appropriate media types otherwise returning a http.StatusUnsupportedMediaType error
|
||||
func ContentTypeHandler(acceptedMediaTypes []string) mux.MiddlewareFunc {
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// skip the GET request
|
||||
if r.Method == http.MethodGet {
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
contentType := r.Header.Get("Content-Type")
|
||||
if contentType == "" {
|
||||
http.Error(w, "Content-Type header is missing", http.StatusUnsupportedMediaType)
|
||||
return
|
||||
}
|
||||
|
||||
accepted := false
|
||||
for _, acceptedType := range acceptedMediaTypes {
|
||||
if strings.Contains(strings.TrimSpace(contentType), strings.TrimSpace(acceptedType)) {
|
||||
accepted = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !accepted {
|
||||
http.Error(w, fmt.Sprintf("Unsupported media type: %s", contentType), http.StatusUnsupportedMediaType)
|
||||
return
|
||||
}
|
||||
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// AcceptHeaderHandler checks if the client's response preference is handled
|
||||
func AcceptHeaderHandler(serverAcceptedTypes []string) mux.MiddlewareFunc {
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
acceptHeader := r.Header.Get("Accept")
|
||||
// header is optional and should skip if not provided
|
||||
if acceptHeader == "" {
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
accepted := false
|
||||
acceptTypes := strings.Split(acceptHeader, ",")
|
||||
// follows rules defined in https://datatracker.ietf.org/doc/html/rfc2616#section-14.1
|
||||
for _, acceptType := range acceptTypes {
|
||||
acceptType = strings.TrimSpace(acceptType)
|
||||
if acceptType == "*/*" {
|
||||
accepted = true
|
||||
break
|
||||
}
|
||||
for _, serverAcceptedType := range serverAcceptedTypes {
|
||||
if strings.HasPrefix(acceptType, serverAcceptedType) {
|
||||
accepted = true
|
||||
break
|
||||
}
|
||||
if acceptType != "/*" && strings.HasSuffix(acceptType, "/*") && strings.HasPrefix(serverAcceptedType, acceptType[:len(acceptType)-2]) {
|
||||
accepted = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if accepted {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !accepted {
|
||||
http.Error(w, fmt.Sprintf("Not Acceptable: %s", acceptHeader), http.StatusNotAcceptable)
|
||||
return
|
||||
}
|
||||
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
}
|
||||
204
api/server/middleware/middleware_test.go
Normal file
204
api/server/middleware/middleware_test.go
Normal file
@@ -0,0 +1,204 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/api"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
)
|
||||
|
||||
func TestNormalizeQueryValuesHandler(t *testing.T) {
|
||||
nextHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
_, err := w.Write([]byte("next handler"))
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
handler := NormalizeQueryValuesHandler(nextHandler)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
inputQuery string
|
||||
expectedQuery string
|
||||
}{
|
||||
{
|
||||
name: "3 values",
|
||||
inputQuery: "key=value1,value2,value3",
|
||||
expectedQuery: "key=value1&key=value2&key=value3", // replace with expected normalized value
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
req, err := http.NewRequest("GET", "/test?"+test.inputQuery, http.NoBody)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
handler.ServeHTTP(rr, req)
|
||||
|
||||
if rr.Code != http.StatusOK {
|
||||
t.Errorf("handler returned wrong status code: got %v want %v", rr.Code, http.StatusOK)
|
||||
}
|
||||
|
||||
if req.URL.RawQuery != test.expectedQuery {
|
||||
t.Errorf("query not normalized: got %v want %v", req.URL.RawQuery, test.expectedQuery)
|
||||
}
|
||||
|
||||
if rr.Body.String() != "next handler" {
|
||||
t.Errorf("next handler was not executed")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestContentTypeHandler(t *testing.T) {
|
||||
acceptedMediaTypes := []string{api.JsonMediaType, api.OctetStreamMediaType}
|
||||
|
||||
nextHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
_, err := w.Write([]byte("next handler"))
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
handler := ContentTypeHandler(acceptedMediaTypes)(nextHandler)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
contentType string
|
||||
expectedStatusCode int
|
||||
isGet bool
|
||||
}{
|
||||
{
|
||||
name: "Accepted Content-Type - application/json",
|
||||
contentType: api.JsonMediaType,
|
||||
expectedStatusCode: http.StatusOK,
|
||||
},
|
||||
{
|
||||
name: "Accepted Content-Type - ssz format",
|
||||
contentType: api.OctetStreamMediaType,
|
||||
expectedStatusCode: http.StatusOK,
|
||||
},
|
||||
{
|
||||
name: "Unsupported Content-Type - text/plain",
|
||||
contentType: "text/plain",
|
||||
expectedStatusCode: http.StatusUnsupportedMediaType,
|
||||
},
|
||||
{
|
||||
name: "Missing Content-Type",
|
||||
contentType: "",
|
||||
expectedStatusCode: http.StatusUnsupportedMediaType,
|
||||
},
|
||||
{
|
||||
name: "GET request skips content type check",
|
||||
contentType: "",
|
||||
expectedStatusCode: http.StatusOK,
|
||||
isGet: true,
|
||||
},
|
||||
{
|
||||
name: "Content type contains charset is ok",
|
||||
contentType: "application/json; charset=utf-8",
|
||||
expectedStatusCode: http.StatusOK,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
httpMethod := http.MethodPost
|
||||
if tt.isGet {
|
||||
httpMethod = http.MethodGet
|
||||
}
|
||||
req := httptest.NewRequest(httpMethod, "/", nil)
|
||||
if tt.contentType != "" {
|
||||
req.Header.Set("Content-Type", tt.contentType)
|
||||
}
|
||||
rr := httptest.NewRecorder()
|
||||
|
||||
handler.ServeHTTP(rr, req)
|
||||
|
||||
if status := rr.Code; status != tt.expectedStatusCode {
|
||||
t.Errorf("handler returned wrong status code: got %v want %v", status, tt.expectedStatusCode)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAcceptHeaderHandler(t *testing.T) {
|
||||
acceptedTypes := []string{"application/json", "application/octet-stream"}
|
||||
|
||||
nextHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
_, err := w.Write([]byte("next handler"))
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
handler := AcceptHeaderHandler(acceptedTypes)(nextHandler)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
acceptHeader string
|
||||
expectedStatusCode int
|
||||
}{
|
||||
{
|
||||
name: "Accepted Accept-Type - application/json",
|
||||
acceptHeader: "application/json",
|
||||
expectedStatusCode: http.StatusOK,
|
||||
},
|
||||
{
|
||||
name: "Accepted Accept-Type - application/octet-stream",
|
||||
acceptHeader: "application/octet-stream",
|
||||
expectedStatusCode: http.StatusOK,
|
||||
},
|
||||
{
|
||||
name: "Accepted Accept-Type with parameters",
|
||||
acceptHeader: "application/json;q=0.9, application/octet-stream;q=0.8",
|
||||
expectedStatusCode: http.StatusOK,
|
||||
},
|
||||
{
|
||||
name: "Unsupported Accept-Type - text/plain",
|
||||
acceptHeader: "text/plain",
|
||||
expectedStatusCode: http.StatusNotAcceptable,
|
||||
},
|
||||
{
|
||||
name: "Missing Accept header",
|
||||
acceptHeader: "",
|
||||
expectedStatusCode: http.StatusOK,
|
||||
},
|
||||
{
|
||||
name: "*/* is accepted",
|
||||
acceptHeader: "*/*",
|
||||
expectedStatusCode: http.StatusOK,
|
||||
},
|
||||
{
|
||||
name: "application/* is accepted",
|
||||
acceptHeader: "application/*",
|
||||
expectedStatusCode: http.StatusOK,
|
||||
},
|
||||
{
|
||||
name: "/* is unsupported",
|
||||
acceptHeader: "/*",
|
||||
expectedStatusCode: http.StatusNotAcceptable,
|
||||
},
|
||||
{
|
||||
name: "application/ is unsupported",
|
||||
acceptHeader: "application/",
|
||||
expectedStatusCode: http.StatusNotAcceptable,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
req := httptest.NewRequest("GET", "/", nil)
|
||||
if tt.acceptHeader != "" {
|
||||
req.Header.Set("Accept", tt.acceptHeader)
|
||||
}
|
||||
rr := httptest.NewRecorder()
|
||||
|
||||
handler.ServeHTTP(rr, req)
|
||||
|
||||
if status := rr.Code; status != tt.expectedStatusCode {
|
||||
t.Errorf("handler returned wrong status code: got %v want %v", status, tt.expectedStatusCode)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package server
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
@@ -1,4 +1,4 @@
|
||||
package server
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"testing"
|
||||
@@ -1,54 +0,0 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
)
|
||||
|
||||
func TestNormalizeQueryValuesHandler(t *testing.T) {
|
||||
nextHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
_, err := w.Write([]byte("next handler"))
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
handler := NormalizeQueryValuesHandler(nextHandler)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
inputQuery string
|
||||
expectedQuery string
|
||||
}{
|
||||
{
|
||||
name: "3 values",
|
||||
inputQuery: "key=value1,value2,value3",
|
||||
expectedQuery: "key=value1&key=value2&key=value3", // replace with expected normalized value
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
req, err := http.NewRequest("GET", "/test?"+test.inputQuery, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
handler.ServeHTTP(rr, req)
|
||||
|
||||
if rr.Code != http.StatusOK {
|
||||
t.Errorf("handler returned wrong status code: got %v want %v", rr.Code, http.StatusOK)
|
||||
}
|
||||
|
||||
if req.URL.RawQuery != test.expectedQuery {
|
||||
t.Errorf("query not normalized: got %v want %v", req.URL.RawQuery, test.expectedQuery)
|
||||
}
|
||||
|
||||
if rr.Body.String() != "next handler" {
|
||||
t.Errorf("next handler was not executed")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
coreState "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/transition"
|
||||
"go.opencensus.io/trace"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers"
|
||||
@@ -71,6 +72,7 @@ type HeadFetcher interface {
|
||||
HeadState(ctx context.Context) (state.BeaconState, error)
|
||||
HeadStateReadOnly(ctx context.Context) (state.ReadOnlyBeaconState, error)
|
||||
HeadValidatorsIndices(ctx context.Context, epoch primitives.Epoch) ([]primitives.ValidatorIndex, error)
|
||||
HeadValidatorsIndicesFromAdvancedSlots(ctx context.Context, slot primitives.Slot) ([]primitives.ValidatorIndex, error)
|
||||
HeadGenesisValidatorsRoot() [32]byte
|
||||
HeadETH1Data() *ethpb.Eth1Data
|
||||
HeadPublicKeyToValidatorIndex(pubKey [fieldparams.BLSPubkeyLength]byte) (primitives.ValidatorIndex, bool)
|
||||
@@ -244,6 +246,22 @@ func (s *Service) HeadValidatorsIndices(ctx context.Context, epoch primitives.Ep
|
||||
return helpers.ActiveValidatorIndices(ctx, s.headState(ctx), epoch)
|
||||
}
|
||||
|
||||
// HeadValidatorsIndicesFromAdvancedSlots returns a list of active validator indices from the head view of a given epoch.
|
||||
func (s *Service) HeadValidatorsIndicesFromAdvancedSlots(ctx context.Context, slot primitives.Slot) ([]primitives.ValidatorIndex, error) {
|
||||
s.headLock.RLock()
|
||||
defer s.headLock.RUnlock()
|
||||
|
||||
if !s.hasHeadState() {
|
||||
return []primitives.ValidatorIndex{}, nil
|
||||
}
|
||||
rt := s.headRoot()
|
||||
st, err := coreState.ProcessSlotsUsingNextSlotCache(ctx, s.headState(ctx), rt[:], slot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return helpers.ActiveValidatorIndices(ctx, st, slots.ToEpoch(slot))
|
||||
}
|
||||
|
||||
// HeadGenesisValidatorsRoot returns genesis validators root of the head state.
|
||||
func (s *Service) HeadGenesisValidatorsRoot() [32]byte {
|
||||
s.headLock.RLock()
|
||||
|
||||
@@ -31,6 +31,7 @@ go_library(
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//proto/engine/v1:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//time/slots:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
],
|
||||
|
||||
@@ -30,6 +30,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
|
||||
enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/time/slots"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
@@ -346,6 +347,13 @@ func (s *ChainService) HeadValidatorsIndices(ctx context.Context, epoch primitiv
|
||||
return helpers.ActiveValidatorIndices(ctx, s.State, epoch)
|
||||
}
|
||||
|
||||
func (s *ChainService) HeadValidatorsIndicesFromAdvancedSlots(ctx context.Context, slot primitives.Slot) ([]primitives.ValidatorIndex, error) {
|
||||
if s.State == nil {
|
||||
return []primitives.ValidatorIndex{}, nil
|
||||
}
|
||||
return helpers.ActiveValidatorIndices(ctx, s.State, slots.ToEpoch(slot))
|
||||
}
|
||||
|
||||
// HeadETH1Data provides the current ETH1Data of the head state.
|
||||
func (s *ChainService) HeadETH1Data() *ethpb.Eth1Data {
|
||||
return s.ETH1Data
|
||||
|
||||
@@ -28,87 +28,87 @@ import (
|
||||
// process_historical_roots_update(state)
|
||||
// process_participation_flag_updates(state) # [New in Altair]
|
||||
// process_sync_committee_updates(state) # [New in Altair]
|
||||
func ProcessEpoch(ctx context.Context, state state.BeaconState) (state.BeaconState, error) {
|
||||
func ProcessEpoch(ctx context.Context, state state.BeaconState) error {
|
||||
ctx, span := trace.StartSpan(ctx, "altair.ProcessEpoch")
|
||||
defer span.End()
|
||||
|
||||
if state == nil || state.IsNil() {
|
||||
return nil, errors.New("nil state")
|
||||
return errors.New("nil state")
|
||||
}
|
||||
vp, bp, err := InitializePrecomputeValidators(ctx, state)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
// New in Altair.
|
||||
vp, bp, err = ProcessEpochParticipation(ctx, state, bp, vp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
state, err = precompute.ProcessJustificationAndFinalizationPreCompute(state, bp)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not process justification")
|
||||
return errors.Wrap(err, "could not process justification")
|
||||
}
|
||||
|
||||
// New in Altair.
|
||||
state, vp, err = ProcessInactivityScores(ctx, state, vp)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not process inactivity updates")
|
||||
return errors.Wrap(err, "could not process inactivity updates")
|
||||
}
|
||||
|
||||
// New in Altair.
|
||||
state, err = ProcessRewardsAndPenaltiesPrecompute(state, bp, vp)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not process rewards and penalties")
|
||||
return errors.Wrap(err, "could not process rewards and penalties")
|
||||
}
|
||||
|
||||
state, err = e.ProcessRegistryUpdates(ctx, state)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not process registry updates")
|
||||
return errors.Wrap(err, "could not process registry updates")
|
||||
}
|
||||
|
||||
// Modified in Altair and Bellatrix.
|
||||
proportionalSlashingMultiplier, err := state.ProportionalSlashingMultiplier()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
state, err = e.ProcessSlashings(state, proportionalSlashingMultiplier)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
state, err = e.ProcessEth1DataReset(state)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
state, err = e.ProcessEffectiveBalanceUpdates(state)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
state, err = e.ProcessSlashingsReset(state)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
state, err = e.ProcessRandaoMixesReset(state)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
state, err = e.ProcessHistoricalDataUpdate(state)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
// New in Altair.
|
||||
state, err = ProcessParticipationFlagUpdates(state)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
// New in Altair.
|
||||
state, err = ProcessSyncCommitteeUpdates(ctx, state)
|
||||
_, err = ProcessSyncCommitteeUpdates(ctx, state)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
return state, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -13,9 +13,9 @@ import (
|
||||
func TestProcessEpoch_CanProcess(t *testing.T) {
|
||||
st, _ := util.DeterministicGenesisStateAltair(t, params.BeaconConfig().MaxValidatorsPerCommittee)
|
||||
require.NoError(t, st.SetSlot(10*params.BeaconConfig().SlotsPerEpoch))
|
||||
newState, err := altair.ProcessEpoch(context.Background(), st)
|
||||
err := altair.ProcessEpoch(context.Background(), st)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(0), newState.Slashings()[2], "Unexpected slashed balance")
|
||||
require.Equal(t, uint64(0), st.Slashings()[2], "Unexpected slashed balance")
|
||||
|
||||
b := st.Balances()
|
||||
require.Equal(t, params.BeaconConfig().MaxValidatorsPerCommittee, uint64(len(b)))
|
||||
@@ -45,9 +45,9 @@ func TestProcessEpoch_CanProcess(t *testing.T) {
|
||||
func TestProcessEpoch_CanProcessBellatrix(t *testing.T) {
|
||||
st, _ := util.DeterministicGenesisStateBellatrix(t, params.BeaconConfig().MaxValidatorsPerCommittee)
|
||||
require.NoError(t, st.SetSlot(10*params.BeaconConfig().SlotsPerEpoch))
|
||||
newState, err := altair.ProcessEpoch(context.Background(), st)
|
||||
err := altair.ProcessEpoch(context.Background(), st)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(0), newState.Slashings()[2], "Unexpected slashed balance")
|
||||
require.Equal(t, uint64(0), st.Slashings()[2], "Unexpected slashed balance")
|
||||
|
||||
b := st.Balances()
|
||||
require.Equal(t, params.BeaconConfig().MaxValidatorsPerCommittee, uint64(len(b)))
|
||||
|
||||
@@ -3,6 +3,7 @@ load("@prysm//tools/go:def.bzl", "go_library", "go_test")
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"attestation.go",
|
||||
"churn.go",
|
||||
"consolidations.go",
|
||||
"deposits.go",
|
||||
@@ -22,6 +23,7 @@ go_library(
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/core/signing:go_default_library",
|
||||
"//beacon-chain/core/time:go_default_library",
|
||||
"//beacon-chain/core/validators:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//beacon-chain/state/state-native:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
@@ -32,7 +34,9 @@ go_library(
|
||||
"//proto/engine/v1:go_default_library",
|
||||
"//proto/prysm/v1alpha1: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_sirupsen_logrus//:go_default_library",
|
||||
"@io_opencensus_go//trace:go_default_library",
|
||||
],
|
||||
)
|
||||
@@ -46,6 +50,7 @@ go_test(
|
||||
"effective_balance_updates_test.go",
|
||||
"upgrade_test.go",
|
||||
"validator_test.go",
|
||||
"withdrawals_test.go",
|
||||
],
|
||||
deps = [
|
||||
":go_default_library",
|
||||
@@ -63,8 +68,12 @@ go_test(
|
||||
"//proto/engine/v1:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//runtime/interop:go_default_library",
|
||||
"//testing/assert:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
"//testing/util:go_default_library",
|
||||
"//time/slots:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//hooks/test:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
7
beacon-chain/core/electra/attestation.go
Normal file
7
beacon-chain/core/electra/attestation.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package electra
|
||||
|
||||
import "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/altair"
|
||||
|
||||
var (
|
||||
ProcessAttestationsNoVerifySignature = altair.ProcessAttestationsNoVerifySignature
|
||||
)
|
||||
@@ -77,11 +77,11 @@ func ProcessPendingBalanceDeposits(ctx context.Context, st state.BeaconState, ac
|
||||
}
|
||||
}
|
||||
|
||||
// ProcessDepositReceipts is a function as part of electra to process execution layer deposits
|
||||
func ProcessDepositReceipts(ctx context.Context, beaconState state.BeaconState, receipts []*enginev1.DepositReceipt) (state.BeaconState, error) {
|
||||
_, span := trace.StartSpan(ctx, "electra.ProcessDepositReceipts")
|
||||
// ProcessDepositRequests is a function as part of electra to process execution layer deposits
|
||||
func ProcessDepositRequests(ctx context.Context, beaconState state.BeaconState, requests []*enginev1.DepositRequest) (state.BeaconState, error) {
|
||||
_, span := trace.StartSpan(ctx, "electra.ProcessDepositRequests")
|
||||
defer span.End()
|
||||
// TODO: replace with 6110 logic
|
||||
// return b.ProcessDepositReceipts(beaconState, receipts)
|
||||
// return b.ProcessDepositRequests(beaconState, requests)
|
||||
return beaconState, nil
|
||||
}
|
||||
|
||||
@@ -46,80 +46,84 @@ var (
|
||||
// process_effective_balance_updates(state)
|
||||
// process_slashings_reset(state)
|
||||
// process_randao_mixes_reset(state)
|
||||
func ProcessEpoch(ctx context.Context, state state.BeaconState) (state.BeaconState, error) {
|
||||
func ProcessEpoch(ctx context.Context, state state.BeaconState) error {
|
||||
_, span := trace.StartSpan(ctx, "electra.ProcessEpoch")
|
||||
defer span.End()
|
||||
|
||||
if state == nil || state.IsNil() {
|
||||
return nil, errors.New("nil state")
|
||||
return errors.New("nil state")
|
||||
}
|
||||
vp, bp, err := InitializePrecomputeValidators(ctx, state)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
vp, bp, err = ProcessEpochParticipation(ctx, state, bp, vp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
state, err = precompute.ProcessJustificationAndFinalizationPreCompute(state, bp)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not process justification")
|
||||
return errors.Wrap(err, "could not process justification")
|
||||
}
|
||||
state, vp, err = ProcessInactivityScores(ctx, state, vp)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not process inactivity updates")
|
||||
return errors.Wrap(err, "could not process inactivity updates")
|
||||
}
|
||||
state, err = ProcessRewardsAndPenaltiesPrecompute(state, bp, vp)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not process rewards and penalties")
|
||||
return errors.Wrap(err, "could not process rewards and penalties")
|
||||
}
|
||||
|
||||
state, err = ProcessRegistryUpdates(ctx, state)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not process registry updates")
|
||||
return errors.Wrap(err, "could not process registry updates")
|
||||
}
|
||||
|
||||
proportionalSlashingMultiplier, err := state.ProportionalSlashingMultiplier()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
state, err = ProcessSlashings(state, proportionalSlashingMultiplier)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
state, err = ProcessEth1DataReset(state)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
if err = ProcessPendingBalanceDeposits(ctx, state, primitives.Gwei(bp.ActiveCurrentEpoch)); err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
if err := ProcessPendingConsolidations(ctx, state); err != nil {
|
||||
return nil, err
|
||||
if err = ProcessPendingConsolidations(ctx, state); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ProcessEffectiveBalanceUpdates(state); err != nil {
|
||||
return nil, err
|
||||
if err = ProcessEffectiveBalanceUpdates(state); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
state, err = ProcessSlashingsReset(state)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
state, err = ProcessRandaoMixesReset(state)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
state, err = ProcessHistoricalDataUpdate(state)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
state, err = ProcessParticipationFlagUpdates(state)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
state, err = ProcessSyncCommitteeUpdates(ctx, state)
|
||||
_, err = ProcessSyncCommitteeUpdates(ctx, state)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
return state, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ import (
|
||||
// withdrawals_root=pre.latest_execution_payload_header.withdrawals_root,
|
||||
// blob_gas_used=pre.latest_execution_payload_header.blob_gas_used,
|
||||
// excess_blob_gas=pre.latest_execution_payload_header.excess_blob_gas,
|
||||
// deposit_receipts_root=Root(), # [New in Electra:EIP6110]
|
||||
// deposit_requests_root=Root(), # [New in Electra:EIP6110]
|
||||
// withdrawal_requests_root=Root(), # [New in Electra:EIP7002],
|
||||
// )
|
||||
//
|
||||
@@ -94,7 +94,7 @@ import (
|
||||
// # Deep history valid from Capella onwards
|
||||
// historical_summaries=pre.historical_summaries,
|
||||
// # [New in Electra:EIP6110]
|
||||
// deposit_receipts_start_index=UNSET_DEPOSIT_RECEIPTS_START_INDEX,
|
||||
// deposit_requests_start_index=UNSET_DEPOSIT_REQUESTS_START_INDEX,
|
||||
// # [New in Electra:EIP7251]
|
||||
// deposit_balance_to_consume=0,
|
||||
// exit_balance_to_consume=0,
|
||||
@@ -261,14 +261,14 @@ func UpgradeToElectra(beaconState state.BeaconState) (state.BeaconState, error)
|
||||
WithdrawalsRoot: wdRoot,
|
||||
ExcessBlobGas: excessBlobGas,
|
||||
BlobGasUsed: blobGasUsed,
|
||||
DepositReceiptsRoot: bytesutil.Bytes32(0), // [New in Electra:EIP6110]
|
||||
DepositRequestsRoot: bytesutil.Bytes32(0), // [New in Electra:EIP6110]
|
||||
WithdrawalRequestsRoot: bytesutil.Bytes32(0), // [New in Electra:EIP7002]
|
||||
},
|
||||
NextWithdrawalIndex: wi,
|
||||
NextWithdrawalValidatorIndex: vi,
|
||||
HistoricalSummaries: summaries,
|
||||
|
||||
DepositReceiptsStartIndex: params.BeaconConfig().UnsetDepositReceiptsStartIndex,
|
||||
DepositRequestsStartIndex: params.BeaconConfig().UnsetDepositRequestsStartIndex,
|
||||
DepositBalanceToConsume: 0,
|
||||
ExitBalanceToConsume: helpers.ActivationExitChurnLimit(primitives.Gwei(tab)),
|
||||
EarliestExitEpoch: earliestExitEpoch,
|
||||
|
||||
@@ -128,7 +128,7 @@ func TestUpgradeToElectra(t *testing.T) {
|
||||
BlockHash: prevHeader.BlockHash(),
|
||||
TransactionsRoot: txRoot,
|
||||
WithdrawalsRoot: wdRoot,
|
||||
DepositReceiptsRoot: bytesutil.Bytes32(0),
|
||||
DepositRequestsRoot: bytesutil.Bytes32(0),
|
||||
WithdrawalRequestsRoot: bytesutil.Bytes32(0),
|
||||
}
|
||||
require.DeepEqual(t, wanted, protoHeader)
|
||||
@@ -145,9 +145,9 @@ func TestUpgradeToElectra(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 0, len(summaries))
|
||||
|
||||
startIndex, err := mSt.DepositReceiptsStartIndex()
|
||||
startIndex, err := mSt.DepositRequestsStartIndex()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, params.BeaconConfig().UnsetDepositReceiptsStartIndex, startIndex)
|
||||
require.Equal(t, params.BeaconConfig().UnsetDepositRequestsStartIndex, startIndex)
|
||||
|
||||
balance, err := mSt.DepositBalanceToConsume()
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -1,21 +1,33 @@
|
||||
package electra
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/validators"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
|
||||
enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/time/slots"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
// ProcessExecutionLayerWithdrawRequests processes the validator withdrawals from the provided execution payload
|
||||
// ProcessWithdrawalRequests processes the validator withdrawals from the provided execution payload
|
||||
// into the beacon state triggered by the execution layer.
|
||||
//
|
||||
// Spec pseudocode definition:
|
||||
//
|
||||
// def process_execution_layer_withdrawal_request(
|
||||
// def process_withdrawal_request(
|
||||
//
|
||||
// state: BeaconState,
|
||||
// execution_layer_withdrawal_request: ExecutionLayerWithdrawalRequest
|
||||
// withdrawal_request: WithdrawalRequest
|
||||
//
|
||||
// ) -> None:
|
||||
// amount = execution_layer_withdrawal_request.amount
|
||||
@@ -74,7 +86,109 @@ import (
|
||||
// amount=to_withdraw,
|
||||
// withdrawable_epoch=withdrawable_epoch,
|
||||
// ))
|
||||
func ProcessExecutionLayerWithdrawRequests(ctx context.Context, st state.BeaconState, wrs []*enginev1.ExecutionLayerWithdrawalRequest) (state.BeaconState, error) {
|
||||
//TODO: replace with real implementation
|
||||
func ProcessWithdrawalRequests(ctx context.Context, st state.BeaconState, wrs []*enginev1.WithdrawalRequest) (state.BeaconState, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "electra.ProcessWithdrawalRequests")
|
||||
defer span.End()
|
||||
currentEpoch := slots.ToEpoch(st.Slot())
|
||||
for _, wr := range wrs {
|
||||
if wr == nil {
|
||||
return nil, errors.New("nil execution layer withdrawal request")
|
||||
}
|
||||
amount := wr.Amount
|
||||
isFullExitRequest := amount == params.BeaconConfig().FullExitRequestAmount
|
||||
// If partial withdrawal queue is full, only full exits are processed
|
||||
if n, err := st.NumPendingPartialWithdrawals(); err != nil {
|
||||
return nil, err
|
||||
} else if n == params.BeaconConfig().PendingPartialWithdrawalsLimit && !isFullExitRequest {
|
||||
// if the PendingPartialWithdrawalsLimit is met, the user would have paid for a partial withdrawal that's not included
|
||||
log.Debugln("Skipping execution layer withdrawal request, PendingPartialWithdrawalsLimit reached")
|
||||
continue
|
||||
}
|
||||
|
||||
vIdx, exists := st.ValidatorIndexByPubkey(bytesutil.ToBytes48(wr.ValidatorPubkey))
|
||||
if !exists {
|
||||
log.Debugf("Skipping execution layer withdrawal request, validator index for %s not found\n", hexutil.Encode(wr.ValidatorPubkey))
|
||||
continue
|
||||
}
|
||||
validator, err := st.ValidatorAtIndex(vIdx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Verify withdrawal credentials
|
||||
hasCorrectCredential := helpers.HasExecutionWithdrawalCredentials(validator)
|
||||
isCorrectSourceAddress := bytes.Equal(validator.WithdrawalCredentials[12:], wr.SourceAddress)
|
||||
if !hasCorrectCredential || !isCorrectSourceAddress {
|
||||
log.Debugln("Skipping execution layer withdrawal request, wrong withdrawal credentials")
|
||||
continue
|
||||
}
|
||||
|
||||
// Verify the validator is active.
|
||||
if !helpers.IsActiveValidator(validator, currentEpoch) {
|
||||
log.Debugln("Skipping execution layer withdrawal request, validator not active")
|
||||
continue
|
||||
}
|
||||
// Verify the validator has not yet submitted an exit.
|
||||
if validator.ExitEpoch != params.BeaconConfig().FarFutureEpoch {
|
||||
log.Debugln("Skipping execution layer withdrawal request, validator has submitted an exit already")
|
||||
continue
|
||||
}
|
||||
// Verify the validator has been active long enough.
|
||||
if currentEpoch < validator.ActivationEpoch.AddEpoch(params.BeaconConfig().ShardCommitteePeriod) {
|
||||
log.Debugln("Skipping execution layer withdrawal request, validator has not been active long enough")
|
||||
continue
|
||||
}
|
||||
|
||||
pendingBalanceToWithdraw, err := st.PendingBalanceToWithdraw(vIdx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if isFullExitRequest {
|
||||
// Only exit validator if it has no pending withdrawals in the queue
|
||||
if pendingBalanceToWithdraw == 0 {
|
||||
maxExitEpoch, churn := validators.MaxExitEpochAndChurn(st)
|
||||
var err error
|
||||
st, _, err = validators.InitiateValidatorExit(ctx, st, vIdx, maxExitEpoch, churn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
hasSufficientEffectiveBalance := validator.EffectiveBalance >= params.BeaconConfig().MinActivationBalance
|
||||
vBal, err := st.BalanceAtIndex(vIdx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
hasExcessBalance := vBal > params.BeaconConfig().MinActivationBalance+pendingBalanceToWithdraw
|
||||
|
||||
// Only allow partial withdrawals with compounding withdrawal credentials
|
||||
if helpers.HasCompoundingWithdrawalCredential(validator) && hasSufficientEffectiveBalance && hasExcessBalance {
|
||||
// Spec definition:
|
||||
// to_withdraw = min(
|
||||
// state.balances[index] - MIN_ACTIVATION_BALANCE - pending_balance_to_withdraw,
|
||||
// amount
|
||||
// )
|
||||
|
||||
// note: you can safely subtract these values because haxExcessBalance is checked
|
||||
toWithdraw := min(vBal-params.BeaconConfig().MinActivationBalance-pendingBalanceToWithdraw, amount)
|
||||
exitQueueEpoch, err := st.ExitEpochAndUpdateChurn(primitives.Gwei(toWithdraw))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// safe add the uint64 to avoid overflow
|
||||
withdrawableEpoch, err := exitQueueEpoch.SafeAddEpoch(params.BeaconConfig().MinValidatorWithdrawabilityDelay)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to add withdrawability delay to exit queue epoch")
|
||||
}
|
||||
if err := st.AppendPendingPartialWithdrawal(ðpb.PendingPartialWithdrawal{
|
||||
Index: vIdx,
|
||||
Amount: toWithdraw,
|
||||
WithdrawableEpoch: withdrawableEpoch,
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
return st, nil
|
||||
}
|
||||
|
||||
295
beacon-chain/core/electra/withdrawals_test.go
Normal file
295
beacon-chain/core/electra/withdrawals_test.go
Normal file
@@ -0,0 +1,295 @@
|
||||
package electra_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/electra"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
|
||||
enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1"
|
||||
eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/util"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/sirupsen/logrus/hooks/test"
|
||||
)
|
||||
|
||||
func TestProcessWithdrawRequests(t *testing.T) {
|
||||
logHook := test.NewGlobal()
|
||||
source, err := hexutil.Decode("0xb20a608c624Ca5003905aA834De7156C68b2E1d0")
|
||||
require.NoError(t, err)
|
||||
st, _ := util.DeterministicGenesisStateElectra(t, 1)
|
||||
currentSlot := primitives.Slot(uint64(params.BeaconConfig().SlotsPerEpoch)*uint64(params.BeaconConfig().ShardCommitteePeriod) + 1)
|
||||
require.NoError(t, st.SetSlot(currentSlot))
|
||||
val, err := st.ValidatorAtIndex(0)
|
||||
require.NoError(t, err)
|
||||
type args struct {
|
||||
st state.BeaconState
|
||||
wrs []*enginev1.WithdrawalRequest
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantFn func(t *testing.T, got state.BeaconState)
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "happy path exit and withdrawal only",
|
||||
args: args{
|
||||
st: func() state.BeaconState {
|
||||
preSt := st.Copy()
|
||||
require.NoError(t, preSt.AppendPendingPartialWithdrawal(ð.PendingPartialWithdrawal{
|
||||
Index: 0,
|
||||
Amount: params.BeaconConfig().FullExitRequestAmount,
|
||||
WithdrawableEpoch: 0,
|
||||
}))
|
||||
v, err := preSt.ValidatorAtIndex(0)
|
||||
require.NoError(t, err)
|
||||
prefix := make([]byte, 12)
|
||||
prefix[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte
|
||||
v.WithdrawalCredentials = append(prefix, source...)
|
||||
require.NoError(t, preSt.SetValidators([]*eth.Validator{v}))
|
||||
return preSt
|
||||
}(),
|
||||
wrs: []*enginev1.WithdrawalRequest{
|
||||
{
|
||||
SourceAddress: source,
|
||||
ValidatorPubkey: bytesutil.SafeCopyBytes(val.PublicKey),
|
||||
Amount: params.BeaconConfig().FullExitRequestAmount,
|
||||
},
|
||||
},
|
||||
},
|
||||
wantFn: func(t *testing.T, got state.BeaconState) {
|
||||
wantPostSt := st.Copy()
|
||||
v, err := wantPostSt.ValidatorAtIndex(0)
|
||||
require.NoError(t, err)
|
||||
prefix := make([]byte, 12)
|
||||
prefix[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte
|
||||
v.WithdrawalCredentials = append(prefix, source...)
|
||||
v.ExitEpoch = 261
|
||||
v.WithdrawableEpoch = 517
|
||||
require.NoError(t, wantPostSt.SetValidators([]*eth.Validator{v}))
|
||||
require.NoError(t, wantPostSt.AppendPendingPartialWithdrawal(ð.PendingPartialWithdrawal{
|
||||
Index: 0,
|
||||
Amount: params.BeaconConfig().FullExitRequestAmount,
|
||||
WithdrawableEpoch: 0,
|
||||
}))
|
||||
_, err = wantPostSt.ExitEpochAndUpdateChurn(primitives.Gwei(v.EffectiveBalance))
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, wantPostSt.Validators(), got.Validators())
|
||||
webc, err := wantPostSt.ExitBalanceToConsume()
|
||||
require.NoError(t, err)
|
||||
gebc, err := got.ExitBalanceToConsume()
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, webc, gebc)
|
||||
weee, err := wantPostSt.EarliestExitEpoch()
|
||||
require.NoError(t, err)
|
||||
geee, err := got.EarliestExitEpoch()
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, weee, geee)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "happy path has compounding",
|
||||
args: args{
|
||||
st: func() state.BeaconState {
|
||||
preSt := st.Copy()
|
||||
require.NoError(t, preSt.AppendPendingPartialWithdrawal(ð.PendingPartialWithdrawal{
|
||||
Index: 0,
|
||||
Amount: params.BeaconConfig().FullExitRequestAmount,
|
||||
WithdrawableEpoch: 0,
|
||||
}))
|
||||
v, err := preSt.ValidatorAtIndex(0)
|
||||
require.NoError(t, err)
|
||||
prefix := make([]byte, 12)
|
||||
prefix[0] = params.BeaconConfig().CompoundingWithdrawalPrefixByte
|
||||
v.WithdrawalCredentials = append(prefix, source...)
|
||||
require.NoError(t, preSt.SetValidators([]*eth.Validator{v}))
|
||||
bal, err := preSt.BalanceAtIndex(0)
|
||||
require.NoError(t, err)
|
||||
bal += 200
|
||||
require.NoError(t, preSt.SetBalances([]uint64{bal}))
|
||||
require.NoError(t, preSt.AppendPendingPartialWithdrawal(ð.PendingPartialWithdrawal{
|
||||
Index: 0,
|
||||
Amount: 100,
|
||||
WithdrawableEpoch: 0,
|
||||
}))
|
||||
return preSt
|
||||
}(),
|
||||
wrs: []*enginev1.WithdrawalRequest{
|
||||
{
|
||||
SourceAddress: source,
|
||||
ValidatorPubkey: bytesutil.SafeCopyBytes(val.PublicKey),
|
||||
Amount: 100,
|
||||
},
|
||||
},
|
||||
},
|
||||
wantFn: func(t *testing.T, got state.BeaconState) {
|
||||
wantPostSt := st.Copy()
|
||||
v, err := wantPostSt.ValidatorAtIndex(0)
|
||||
require.NoError(t, err)
|
||||
prefix := make([]byte, 12)
|
||||
prefix[0] = params.BeaconConfig().CompoundingWithdrawalPrefixByte
|
||||
v.WithdrawalCredentials = append(prefix, source...)
|
||||
require.NoError(t, wantPostSt.SetValidators([]*eth.Validator{v}))
|
||||
bal, err := wantPostSt.BalanceAtIndex(0)
|
||||
require.NoError(t, err)
|
||||
bal += 200
|
||||
require.NoError(t, wantPostSt.SetBalances([]uint64{bal}))
|
||||
require.NoError(t, wantPostSt.AppendPendingPartialWithdrawal(ð.PendingPartialWithdrawal{
|
||||
Index: 0,
|
||||
Amount: 0,
|
||||
WithdrawableEpoch: 0,
|
||||
}))
|
||||
require.NoError(t, wantPostSt.AppendPendingPartialWithdrawal(ð.PendingPartialWithdrawal{
|
||||
Index: 0,
|
||||
Amount: 100,
|
||||
WithdrawableEpoch: 0,
|
||||
}))
|
||||
require.NoError(t, wantPostSt.AppendPendingPartialWithdrawal(ð.PendingPartialWithdrawal{
|
||||
Index: 0,
|
||||
Amount: 100,
|
||||
WithdrawableEpoch: 517,
|
||||
}))
|
||||
wnppw, err := wantPostSt.NumPendingPartialWithdrawals()
|
||||
require.NoError(t, err)
|
||||
gnppw, err := got.NumPendingPartialWithdrawals()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, wnppw, gnppw)
|
||||
wece, err := wantPostSt.EarliestConsolidationEpoch()
|
||||
require.NoError(t, err)
|
||||
gece, err := got.EarliestConsolidationEpoch()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, wece, gece)
|
||||
_, err = wantPostSt.ExitEpochAndUpdateChurn(primitives.Gwei(100))
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, wantPostSt.Validators(), got.Validators())
|
||||
webc, err := wantPostSt.ExitBalanceToConsume()
|
||||
require.NoError(t, err)
|
||||
gebc, err := got.ExitBalanceToConsume()
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, webc, gebc)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "validator already submitted exit",
|
||||
args: args{
|
||||
st: func() state.BeaconState {
|
||||
preSt := st.Copy()
|
||||
v, err := preSt.ValidatorAtIndex(0)
|
||||
require.NoError(t, err)
|
||||
prefix := make([]byte, 12)
|
||||
prefix[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte
|
||||
v.WithdrawalCredentials = append(prefix, source...)
|
||||
v.ExitEpoch = 1000
|
||||
require.NoError(t, preSt.SetValidators([]*eth.Validator{v}))
|
||||
return preSt
|
||||
}(),
|
||||
wrs: []*enginev1.WithdrawalRequest{
|
||||
{
|
||||
SourceAddress: source,
|
||||
ValidatorPubkey: bytesutil.SafeCopyBytes(val.PublicKey),
|
||||
Amount: params.BeaconConfig().FullExitRequestAmount,
|
||||
},
|
||||
},
|
||||
},
|
||||
wantFn: func(t *testing.T, got state.BeaconState) {
|
||||
wantPostSt := st.Copy()
|
||||
v, err := wantPostSt.ValidatorAtIndex(0)
|
||||
require.NoError(t, err)
|
||||
prefix := make([]byte, 12)
|
||||
prefix[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte
|
||||
v.WithdrawalCredentials = append(prefix, source...)
|
||||
v.ExitEpoch = 1000
|
||||
require.NoError(t, wantPostSt.SetValidators([]*eth.Validator{v}))
|
||||
eee, err := got.EarliestExitEpoch()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, eee, primitives.Epoch(0))
|
||||
require.DeepEqual(t, wantPostSt.Validators(), got.Validators())
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "validator too new",
|
||||
args: args{
|
||||
st: func() state.BeaconState {
|
||||
preSt := st.Copy()
|
||||
require.NoError(t, preSt.SetSlot(0))
|
||||
v, err := preSt.ValidatorAtIndex(0)
|
||||
require.NoError(t, err)
|
||||
prefix := make([]byte, 12)
|
||||
prefix[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte
|
||||
v.WithdrawalCredentials = append(prefix, source...)
|
||||
require.NoError(t, preSt.SetValidators([]*eth.Validator{v}))
|
||||
return preSt
|
||||
}(),
|
||||
wrs: []*enginev1.WithdrawalRequest{
|
||||
{
|
||||
SourceAddress: source,
|
||||
ValidatorPubkey: bytesutil.SafeCopyBytes(val.PublicKey),
|
||||
Amount: params.BeaconConfig().FullExitRequestAmount,
|
||||
},
|
||||
},
|
||||
},
|
||||
wantFn: func(t *testing.T, got state.BeaconState) {
|
||||
wantPostSt := st.Copy()
|
||||
require.NoError(t, wantPostSt.SetSlot(0))
|
||||
v, err := wantPostSt.ValidatorAtIndex(0)
|
||||
require.NoError(t, err)
|
||||
prefix := make([]byte, 12)
|
||||
prefix[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte
|
||||
v.WithdrawalCredentials = append(prefix, source...)
|
||||
require.NoError(t, wantPostSt.SetValidators([]*eth.Validator{v}))
|
||||
eee, err := got.EarliestExitEpoch()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, eee, primitives.Epoch(0))
|
||||
require.DeepEqual(t, wantPostSt.Validators(), got.Validators())
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "PendingPartialWithdrawalsLimit reached with partial withdrawal results in a skip",
|
||||
args: args{
|
||||
st: func() state.BeaconState {
|
||||
cfg := params.BeaconConfig().Copy()
|
||||
cfg.PendingPartialWithdrawalsLimit = 1
|
||||
params.OverrideBeaconConfig(cfg)
|
||||
logrus.SetLevel(logrus.DebugLevel)
|
||||
preSt := st.Copy()
|
||||
require.NoError(t, preSt.AppendPendingPartialWithdrawal(ð.PendingPartialWithdrawal{
|
||||
Index: 0,
|
||||
Amount: params.BeaconConfig().FullExitRequestAmount,
|
||||
WithdrawableEpoch: 0,
|
||||
}))
|
||||
return preSt
|
||||
}(),
|
||||
wrs: []*enginev1.WithdrawalRequest{
|
||||
{
|
||||
SourceAddress: source,
|
||||
ValidatorPubkey: bytesutil.SafeCopyBytes(val.PublicKey),
|
||||
Amount: 100,
|
||||
},
|
||||
},
|
||||
},
|
||||
wantFn: func(t *testing.T, got state.BeaconState) {
|
||||
assert.LogsContain(t, logHook, "Skipping execution layer withdrawal request, PendingPartialWithdrawalsLimit reached")
|
||||
params.SetupTestConfigCleanup(t)
|
||||
logrus.SetLevel(logrus.InfoLevel) // reset
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
||||
got, err := electra.ProcessWithdrawalRequests(context.Background(), tt.args.st, tt.args.wrs)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("ProcessWithdrawalRequests() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
tt.wantFn(t, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -500,11 +500,11 @@ func LastActivatedValidatorIndex(ctx context.Context, st state.ReadOnlyBeaconSta
|
||||
|
||||
// hasETH1WithdrawalCredential returns whether the validator has an ETH1
|
||||
// Withdrawal prefix. It assumes that the caller has a lock on the state
|
||||
func HasETH1WithdrawalCredential(val *ethpb.Validator) bool {
|
||||
func HasETH1WithdrawalCredential(val interfaces.WithWithdrawalCredentials) bool {
|
||||
if val == nil {
|
||||
return false
|
||||
}
|
||||
return isETH1WithdrawalCredential(val.WithdrawalCredentials)
|
||||
return isETH1WithdrawalCredential(val.GetWithdrawalCredentials())
|
||||
}
|
||||
|
||||
func isETH1WithdrawalCredential(creds []byte) bool {
|
||||
|
||||
@@ -226,7 +226,7 @@ func TestProcessEpoch_BadBalanceAltair(t *testing.T) {
|
||||
epochParticipation[0] = participation
|
||||
assert.NoError(t, s.SetCurrentParticipationBits(epochParticipation))
|
||||
assert.NoError(t, s.SetPreviousParticipationBits(epochParticipation))
|
||||
_, err = altair.ProcessEpoch(context.Background(), s)
|
||||
err = altair.ProcessEpoch(context.Background(), s)
|
||||
assert.ErrorContains(t, "addition overflows", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -216,7 +216,7 @@ func TestProcessEpoch_BadBalanceBellatrix(t *testing.T) {
|
||||
epochParticipation[0] = participation
|
||||
assert.NoError(t, s.SetCurrentParticipationBits(epochParticipation))
|
||||
assert.NoError(t, s.SetPreviousParticipationBits(epochParticipation))
|
||||
_, err = altair.ProcessEpoch(context.Background(), s)
|
||||
err = altair.ProcessEpoch(context.Background(), s)
|
||||
assert.ErrorContains(t, "addition overflows", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -257,14 +257,12 @@ func ProcessSlots(ctx context.Context, state state.BeaconState, slot primitives.
|
||||
return nil, errors.Wrap(err, "could not process epoch with optimizations")
|
||||
}
|
||||
} else if state.Version() <= version.Deneb {
|
||||
state, err = altair.ProcessEpoch(ctx, state)
|
||||
if err != nil {
|
||||
if err = altair.ProcessEpoch(ctx, state); err != nil {
|
||||
tracing.AnnotateError(span, err)
|
||||
return nil, errors.Wrap(err, fmt.Sprintf("could not process %s epoch", version.String(state.Version())))
|
||||
}
|
||||
} else {
|
||||
state, err = electra.ProcessEpoch(ctx, state)
|
||||
if err != nil {
|
||||
if err = electra.ProcessEpoch(ctx, state); err != nil {
|
||||
tracing.AnnotateError(span, err)
|
||||
return nil, errors.Wrap(err, fmt.Sprintf("could not process %s epoch", version.String(state.Version())))
|
||||
}
|
||||
|
||||
@@ -227,7 +227,7 @@ func ProcessBlockNoVerifyAnySig(
|
||||
// def process_operations(state: BeaconState, body: BeaconBlockBody) -> None:
|
||||
// # [Modified in Electra:EIP6110]
|
||||
// # Disable former deposit mechanism once all prior deposits are processed
|
||||
// eth1_deposit_index_limit = min(state.eth1_data.deposit_count, state.deposit_receipts_start_index)
|
||||
// eth1_deposit_index_limit = min(state.eth1_data.deposit_count, state.deposit_requests_start_index)
|
||||
// if state.eth1_deposit_index < eth1_deposit_index_limit:
|
||||
// assert len(body.deposits) == min(MAX_DEPOSITS, eth1_deposit_index_limit - state.eth1_deposit_index)
|
||||
// else:
|
||||
@@ -245,7 +245,7 @@ func ProcessBlockNoVerifyAnySig(
|
||||
// for_ops(body.bls_to_execution_changes, process_bls_to_execution_change)
|
||||
// # [New in Electra:EIP7002:EIP7251]
|
||||
// for_ops(body.execution_payload.withdrawal_requests, process_execution_layer_withdrawal_request)
|
||||
// for_ops(body.execution_payload.deposit_receipts, process_deposit_receipt) # [New in Electra:EIP6110]
|
||||
// for_ops(body.execution_payload.deposit_requests, process_deposit_requests) # [New in Electra:EIP6110]
|
||||
// for_ops(body.consolidations, process_consolidation) # [New in Electra:EIP7251]
|
||||
func ProcessOperationsNoVerifyAttsSigs(
|
||||
ctx context.Context,
|
||||
@@ -401,7 +401,7 @@ func VerifyBlobCommitmentCount(blk interfaces.ReadOnlyBeaconBlock) error {
|
||||
// def process_operations(state: BeaconState, body: BeaconBlockBody) -> None:
|
||||
// # [Modified in Electra:EIP6110]
|
||||
// # Disable former deposit mechanism once all prior deposits are processed
|
||||
// eth1_deposit_index_limit = min(state.eth1_data.deposit_count, state.deposit_receipts_start_index)
|
||||
// eth1_deposit_index_limit = min(state.eth1_data.deposit_count, state.deposit_requests_start_index)
|
||||
// if state.eth1_deposit_index < eth1_deposit_index_limit:
|
||||
// assert len(body.deposits) == min(MAX_DEPOSITS, eth1_deposit_index_limit - state.eth1_deposit_index)
|
||||
// else:
|
||||
@@ -419,7 +419,7 @@ func VerifyBlobCommitmentCount(blk interfaces.ReadOnlyBeaconBlock) error {
|
||||
// for_ops(body.bls_to_execution_changes, process_bls_to_execution_change)
|
||||
// # [New in Electra:EIP7002:EIP7251]
|
||||
// for_ops(body.execution_payload.withdrawal_requests, process_execution_layer_withdrawal_request)
|
||||
// for_ops(body.execution_payload.deposit_receipts, process_deposit_receipt) # [New in Electra:EIP6110]
|
||||
// for_ops(body.execution_payload.deposit_requests, process_deposit_requests) # [New in Electra:EIP6110]
|
||||
// for_ops(body.consolidations, process_consolidation) # [New in Electra:EIP7251]
|
||||
func electraOperations(
|
||||
ctx context.Context,
|
||||
@@ -445,11 +445,12 @@ func electraOperations(
|
||||
if !ok {
|
||||
return nil, errors.New("could not cast execution data to electra execution data")
|
||||
}
|
||||
st, err = electra.ProcessExecutionLayerWithdrawRequests(ctx, st, exe.WithdrawalRequests())
|
||||
st, err = electra.ProcessWithdrawalRequests(ctx, st, exe.WithdrawalRequests())
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not process execution layer withdrawal requests")
|
||||
}
|
||||
st, err = electra.ProcessDepositReceipts(ctx, st, exe.DepositReceipts())
|
||||
|
||||
st, err = electra.ProcessDepositRequests(ctx, st, exe.DepositRequests()) // TODO: EIP-6110 deposit changes.
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not process deposit receipts")
|
||||
}
|
||||
|
||||
@@ -92,14 +92,16 @@ func windowMin(latest, offset primitives.Slot) primitives.Slot {
|
||||
|
||||
func (p *blobPruner) warmCache() error {
|
||||
p.Lock()
|
||||
defer p.Unlock()
|
||||
defer func() {
|
||||
if !p.warmed {
|
||||
p.warmed = true
|
||||
close(p.cacheReady)
|
||||
}
|
||||
p.Unlock()
|
||||
}()
|
||||
if err := p.prune(0); err != nil {
|
||||
return err
|
||||
}
|
||||
if !p.warmed {
|
||||
p.warmed = true
|
||||
close(p.cacheReady)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -2,16 +2,19 @@ package filesystem
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"math"
|
||||
"os"
|
||||
"path"
|
||||
"sort"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/verification"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/util"
|
||||
"github.com/spf13/afero"
|
||||
@@ -34,6 +37,34 @@ func TestTryPruneDir_CachedNotExpired(t *testing.T) {
|
||||
require.Equal(t, 0, pruned)
|
||||
}
|
||||
|
||||
func TestCacheWarmFail(t *testing.T) {
|
||||
fs := afero.NewMemMapFs()
|
||||
n := blobNamer{root: bytesutil.ToBytes32([]byte("derp")), index: 0}
|
||||
bp := n.path()
|
||||
mkdir := path.Dir(bp)
|
||||
require.NoError(t, fs.MkdirAll(mkdir, directoryPermissions))
|
||||
|
||||
// Create an empty blob index in the fs by touching the file at a seemingly valid path.
|
||||
fi, err := fs.Create(bp)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, fi.Close())
|
||||
|
||||
// Cache warm should fail due to the unexpected EOF.
|
||||
pr, err := newBlobPruner(fs, 0)
|
||||
require.NoError(t, err)
|
||||
require.ErrorIs(t, pr.warmCache(), errPruningFailures)
|
||||
|
||||
// The cache warm has finished, so calling waitForCache with a super short deadline
|
||||
// should not block or hit the context deadline.
|
||||
ctx := context.Background()
|
||||
ctx, cancel := context.WithDeadline(ctx, time.Now().Add(1*time.Millisecond))
|
||||
defer cancel()
|
||||
c, err := pr.waitForCache(ctx)
|
||||
// We will get an error and a nil value for the cache if we hit the deadline.
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, c)
|
||||
}
|
||||
|
||||
func TestTryPruneDir_CachedExpired(t *testing.T) {
|
||||
t.Run("empty directory", func(t *testing.T) {
|
||||
fs := afero.NewMemMapFs()
|
||||
|
||||
@@ -149,7 +149,7 @@ func TestState_CanSaveRetrieve(t *testing.T) {
|
||||
BlockHash: make([]byte, 32),
|
||||
TransactionsRoot: make([]byte, 32),
|
||||
WithdrawalsRoot: make([]byte, 32),
|
||||
DepositReceiptsRoot: make([]byte, 32),
|
||||
DepositRequestsRoot: make([]byte, 32),
|
||||
WithdrawalRequestsRoot: make([]byte, 32),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -631,7 +631,7 @@ func fullPayloadFromPayloadBody(
|
||||
Withdrawals: body.Withdrawals,
|
||||
ExcessBlobGas: ebg,
|
||||
BlobGasUsed: bgu,
|
||||
DepositReceipts: dr,
|
||||
DepositRequests: dr,
|
||||
WithdrawalRequests: wr,
|
||||
}) // We can't get the block value and don't care about the block value for this instance
|
||||
default:
|
||||
@@ -780,8 +780,8 @@ func buildEmptyExecutionPayload(v int) (proto.Message, error) {
|
||||
BlockHash: make([]byte, fieldparams.RootLength),
|
||||
Transactions: make([][]byte, 0),
|
||||
Withdrawals: make([]*pb.Withdrawal, 0),
|
||||
WithdrawalRequests: make([]*pb.ExecutionLayerWithdrawalRequest, 0),
|
||||
DepositReceipts: make([]*pb.DepositReceipt, 0),
|
||||
WithdrawalRequests: make([]*pb.WithdrawalRequest, 0),
|
||||
DepositRequests: make([]*pb.DepositRequest, 0),
|
||||
}, nil
|
||||
default:
|
||||
return nil, errors.Wrapf(ErrUnsupportedVersion, "version=%s", version.String(v))
|
||||
|
||||
@@ -1559,7 +1559,7 @@ func fixturesStruct() *payloadFixtures {
|
||||
Withdrawals: []*pb.Withdrawal{},
|
||||
BlobGasUsed: 2,
|
||||
ExcessBlobGas: 3,
|
||||
DepositReceipts: dr,
|
||||
DepositRequests: dr,
|
||||
WithdrawalRequests: wr,
|
||||
}
|
||||
hexUint := hexutil.Uint64(1)
|
||||
|
||||
@@ -66,7 +66,7 @@ func payloadToBody(t *testing.T, ed interfaces.ExecutionData) *pb.ExecutionPaylo
|
||||
}
|
||||
eed, isElectra := ed.(interfaces.ExecutionDataElectra)
|
||||
if isElectra {
|
||||
body.DepositRequests = pb.ProtoDepositRequestsToJson(eed.DepositReceipts())
|
||||
body.DepositRequests = pb.ProtoDepositRequestsToJson(eed.DepositRequests())
|
||||
body.WithdrawalRequests = pb.ProtoWithdrawalRequestsToJson(eed.WithdrawalRequests())
|
||||
}
|
||||
return body
|
||||
|
||||
@@ -16,7 +16,7 @@ go_library(
|
||||
],
|
||||
deps = [
|
||||
"//api/gateway:go_default_library",
|
||||
"//api/server:go_default_library",
|
||||
"//api/server/middleware:go_default_library",
|
||||
"//async/event:go_default_library",
|
||||
"//beacon-chain/blockchain:go_default_library",
|
||||
"//beacon-chain/builder:go_default_library",
|
||||
|
||||
@@ -20,7 +20,7 @@ import (
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/pkg/errors"
|
||||
apigateway "github.com/prysmaticlabs/prysm/v5/api/gateway"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/middleware"
|
||||
"github.com/prysmaticlabs/prysm/v5/async/event"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/builder"
|
||||
@@ -120,7 +120,6 @@ type BeaconNode struct {
|
||||
initialSyncComplete chan struct{}
|
||||
BlobStorage *filesystem.BlobStorage
|
||||
BlobStorageOptions []filesystem.BlobStorageOption
|
||||
blobRetentionEpochs primitives.Epoch
|
||||
verifyInitWaiter *verification.InitializerWaiter
|
||||
syncChecker *initialsync.SyncChecker
|
||||
}
|
||||
@@ -409,8 +408,8 @@ func newRouter(cliCtx *cli.Context) *mux.Router {
|
||||
allowedOrigins = strings.Split(flags.GPRCGatewayCorsDomain.Value, ",")
|
||||
}
|
||||
r := mux.NewRouter()
|
||||
r.Use(server.NormalizeQueryValuesHandler)
|
||||
r.Use(server.CorsHandler(allowedOrigins))
|
||||
r.Use(middleware.NormalizeQueryValuesHandler)
|
||||
r.Use(middleware.CorsHandler(allowedOrigins))
|
||||
return r
|
||||
}
|
||||
|
||||
@@ -965,9 +964,8 @@ func (b *BeaconNode) registerRPCService(router *mux.Router) error {
|
||||
cert := b.cliCtx.String(flags.CertFlag.Name)
|
||||
key := b.cliCtx.String(flags.KeyFlag.Name)
|
||||
mockEth1DataVotes := b.cliCtx.Bool(flags.InteropMockEth1DataVotesFlag.Name)
|
||||
|
||||
maxMsgSize := b.cliCtx.Int(cmd.GrpcMaxCallRecvMsgSizeFlag.Name)
|
||||
enableDebugRPCEndpoints := b.cliCtx.Bool(flags.EnableDebugRPCEndpoints.Name)
|
||||
enableDebugRPCEndpoints := !b.cliCtx.Bool(flags.DisableDebugRPCEndpoints.Name)
|
||||
|
||||
p2pService := b.fetchP2P()
|
||||
rpcService := rpc.NewService(b.ctx, &rpc.Config{
|
||||
@@ -1056,11 +1054,10 @@ func (b *BeaconNode) registerGRPCGateway(router *mux.Router) error {
|
||||
gatewayPort := b.cliCtx.Int(flags.GRPCGatewayPort.Name)
|
||||
rpcHost := b.cliCtx.String(flags.RPCHost.Name)
|
||||
rpcPort := b.cliCtx.Int(flags.RPCPort.Name)
|
||||
|
||||
enableDebugRPCEndpoints := !b.cliCtx.Bool(flags.DisableDebugRPCEndpoints.Name)
|
||||
selfAddress := net.JoinHostPort(rpcHost, strconv.Itoa(rpcPort))
|
||||
gatewayAddress := net.JoinHostPort(gatewayHost, strconv.Itoa(gatewayPort))
|
||||
allowedOrigins := strings.Split(b.cliCtx.String(flags.GPRCGatewayCorsDomain.Name), ",")
|
||||
enableDebugRPCEndpoints := b.cliCtx.Bool(flags.EnableDebugRPCEndpoints.Name)
|
||||
selfCert := b.cliCtx.String(flags.CertFlag.Name)
|
||||
maxCallSize := b.cliCtx.Uint64(cmd.GrpcMaxCallRecvMsgSizeFlag.Name)
|
||||
httpModules := b.cliCtx.String(flags.HTTPModules.Name)
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/builder"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/db/filesystem"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/execution"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
)
|
||||
|
||||
// Option for beacon node configuration.
|
||||
@@ -51,11 +50,3 @@ func WithBlobStorageOptions(opt ...filesystem.BlobStorageOption) Option {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithBlobRetentionEpochs sets the blobRetentionEpochs value, used in kv store initialization.
|
||||
func WithBlobRetentionEpochs(e primitives.Epoch) Option {
|
||||
return func(bn *BeaconNode) error {
|
||||
bn.blobRetentionEpochs = e
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,7 +142,7 @@ func (s *Service) internalBroadcastAttestation(ctx context.Context, subnet uint6
|
||||
log.WithFields(logrus.Fields{
|
||||
"attestationSlot": att.GetData().Slot,
|
||||
"currentSlot": currSlot,
|
||||
}).WithError(err).Warning("Attestation is too old to broadcast, discarding it")
|
||||
}).WithError(err).Debug("Attestation is too old to broadcast, discarding it")
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -336,7 +336,7 @@ func TestService_InterceptAddrDial_Public(t *testing.T) {
|
||||
}),
|
||||
}
|
||||
var err error
|
||||
//test with public filter
|
||||
// test with public filter
|
||||
cidr := "public"
|
||||
ip := "212.67.10.122"
|
||||
s.addrFilter, err = configureFilter(&Config{AllowListCIDR: cidr})
|
||||
@@ -348,7 +348,7 @@ func TestService_InterceptAddrDial_Public(t *testing.T) {
|
||||
t.Errorf("Expected multiaddress with ip %s to not be rejected since we allow public addresses", ip)
|
||||
}
|
||||
|
||||
ip = "192.168.1.0" //this is private and should fail
|
||||
ip = "192.168.1.0" // this is private and should fail
|
||||
multiAddress, err = ma.NewMultiaddr(fmt.Sprintf("/ip4/%s/tcp/%d", ip, 3000))
|
||||
require.NoError(t, err)
|
||||
valid = s.InterceptAddrDial("", multiAddress)
|
||||
@@ -356,7 +356,7 @@ func TestService_InterceptAddrDial_Public(t *testing.T) {
|
||||
t.Errorf("Expected multiaddress with ip %s to be rejected since we are only allowing public addresses", ip)
|
||||
}
|
||||
|
||||
//test with public allow filter, with a public address added to the deny list
|
||||
// test with public allow filter, with a public address added to the deny list
|
||||
invalidPublicIp := "212.67.10.122"
|
||||
validPublicIp := "91.65.69.69"
|
||||
s.addrFilter, err = configureFilter(&Config{AllowListCIDR: "public", DenyListCIDR: []string{"212.67.89.112/16"}})
|
||||
@@ -384,7 +384,7 @@ func TestService_InterceptAddrDial_Private(t *testing.T) {
|
||||
}),
|
||||
}
|
||||
var err error
|
||||
//test with private filter
|
||||
// test with private filter
|
||||
cidr := "private"
|
||||
s.addrFilter, err = configureFilter(&Config{DenyListCIDR: []string{cidr}})
|
||||
require.NoError(t, err)
|
||||
@@ -413,7 +413,7 @@ func TestService_InterceptAddrDial_AllowPrivate(t *testing.T) {
|
||||
}),
|
||||
}
|
||||
var err error
|
||||
//test with private filter
|
||||
// test with private filter
|
||||
cidr := "private"
|
||||
s.addrFilter, err = configureFilter(&Config{AllowListCIDR: cidr})
|
||||
require.NoError(t, err)
|
||||
@@ -442,7 +442,7 @@ func TestService_InterceptAddrDial_DenyPublic(t *testing.T) {
|
||||
}),
|
||||
}
|
||||
var err error
|
||||
//test with private filter
|
||||
// test with private filter
|
||||
cidr := "public"
|
||||
s.addrFilter, err = configureFilter(&Config{DenyListCIDR: []string{cidr}})
|
||||
require.NoError(t, err)
|
||||
@@ -471,7 +471,7 @@ func TestService_InterceptAddrDial_AllowConflict(t *testing.T) {
|
||||
}),
|
||||
}
|
||||
var err error
|
||||
//test with private filter
|
||||
// test with private filter
|
||||
cidr := "public"
|
||||
s.addrFilter, err = configureFilter(&Config{DenyListCIDR: []string{cidr, "192.168.0.0/16"}})
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -51,7 +51,7 @@ func (quicProtocol) ENRKey() string { return "quic" }
|
||||
// with the tracked committee ids for the epoch, allowing our node
|
||||
// to be dynamically discoverable by others given our tracked committee ids.
|
||||
func (s *Service) RefreshENR() {
|
||||
// return early if discv5 isnt running
|
||||
// return early if discv5 isn't running
|
||||
if s.dv5Listener == nil || !s.isInitialized() {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ func TestStartDiscV5_FindPeersWithSubnet(t *testing.T) {
|
||||
bootNodeENR := bootListener.Self().String()
|
||||
|
||||
// Create 3 nodes, each subscribed to a different subnet.
|
||||
// Each node is connected to the boostrap node.
|
||||
// Each node is connected to the bootstrap node.
|
||||
services := make([]*Service, 0, 3)
|
||||
|
||||
for i := 1; i <= 3; i++ {
|
||||
|
||||
@@ -10,6 +10,8 @@ go_library(
|
||||
importpath = "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc",
|
||||
visibility = ["//beacon-chain:__subpackages__"],
|
||||
deps = [
|
||||
"//api:go_default_library",
|
||||
"//api/server/middleware:go_default_library",
|
||||
"//beacon-chain/blockchain:go_default_library",
|
||||
"//beacon-chain/builder:go_default_library",
|
||||
"//beacon-chain/cache:go_default_library",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -60,8 +60,7 @@ func (s *Server) GetBlockV2(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
blk, err := s.Blocker.Block(ctx, []byte(blockId))
|
||||
if err != nil {
|
||||
shared.WriteBlockFetchError(w, blk, err)
|
||||
if !shared.WriteBlockFetchError(w, blk, err) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -69,7 +68,7 @@ func (s *Server) GetBlockV2(w http.ResponseWriter, r *http.Request) {
|
||||
if blk.Version() >= version.Bellatrix && blk.IsBlinded() {
|
||||
blk, err = s.ExecutionPayloadReconstructor.ReconstructFullBlock(ctx, blk)
|
||||
if err != nil {
|
||||
shared.WriteBlockFetchError(w, blk, errors.Wrapf(err, "could not reconstruct full execution payload to create signed beacon block"))
|
||||
httputil.HandleError(w, errors.Wrapf(err, "could not reconstruct full execution payload to create signed beacon block").Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -892,6 +891,11 @@ func (s *Server) validateConsensus(ctx context.Context, blk interfaces.ReadOnlyS
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get parent block")
|
||||
}
|
||||
|
||||
if err := blocks.BeaconBlockIsNil(blk); err != nil {
|
||||
return errors.Wrap(err, "could not validate block")
|
||||
}
|
||||
|
||||
parentStateRoot := parentBlock.Block().StateRoot()
|
||||
parentState, err := s.Stater.State(ctx, parentStateRoot[:])
|
||||
if err != nil {
|
||||
|
||||
@@ -147,8 +147,7 @@ func (s *Server) SubmitAttestations(w http.ResponseWriter, r *http.Request) {
|
||||
failedBroadcasts := make([]string, 0)
|
||||
for i, att := range validAttestations {
|
||||
// Determine subnet to broadcast attestation to
|
||||
wantedEpoch := slots.ToEpoch(att.Data.Slot)
|
||||
vals, err := s.HeadFetcher.HeadValidatorsIndices(ctx, wantedEpoch)
|
||||
vals, err := s.HeadFetcher.HeadValidatorsIndicesFromAdvancedSlots(ctx, att.Data.Slot)
|
||||
if err != nil {
|
||||
httputil.HandleError(w, "Could not get head validator indices: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
|
||||
@@ -86,6 +86,24 @@ func fillDBTestBlocks(ctx context.Context, t *testing.T, beaconDB db.Database) (
|
||||
}
|
||||
|
||||
func TestGetBlockV2(t *testing.T) {
|
||||
t.Run("Unsycned Block", func(t *testing.T) {
|
||||
mockBlockFetcher := &testutil.MockBlocker{BlockToReturn: nil}
|
||||
mockChainService := &chainMock.ChainService{
|
||||
FinalizedRoots: map[[32]byte]bool{},
|
||||
}
|
||||
s := &Server{
|
||||
FinalizationFetcher: mockChainService,
|
||||
Blocker: mockBlockFetcher,
|
||||
}
|
||||
|
||||
request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v2/beacon/blocks/{block_id}", nil)
|
||||
request = mux.SetURLVars(request, map[string]string{"block_id": "123552314"})
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
|
||||
s.GetBlockV2(writer, request)
|
||||
require.Equal(t, http.StatusNotFound, writer.Code)
|
||||
})
|
||||
t.Run("phase0", func(t *testing.T) {
|
||||
b := util.NewBeaconBlock()
|
||||
b.Block.Slot = 123
|
||||
|
||||
@@ -149,7 +149,8 @@ func TestGetSpec(t *testing.T) {
|
||||
config.MaxAttestationsElectra = 89
|
||||
config.MaxWithdrawalRequestsPerPayload = 90
|
||||
config.MaxCellsInExtendedMatrix = 91
|
||||
config.UnsetDepositReceiptsStartIndex = 92
|
||||
config.UnsetDepositRequestsStartIndex = 92
|
||||
config.MaxDepositRequestsPerPayload = 93
|
||||
|
||||
var dbp [4]byte
|
||||
copy(dbp[:], []byte{'0', '0', '0', '1'})
|
||||
@@ -192,7 +193,7 @@ func TestGetSpec(t *testing.T) {
|
||||
data, ok := resp.Data.(map[string]interface{})
|
||||
require.Equal(t, true, ok)
|
||||
|
||||
assert.Equal(t, 154, len(data))
|
||||
assert.Equal(t, 155, len(data))
|
||||
for k, v := range data {
|
||||
t.Run(k, func(t *testing.T) {
|
||||
switch k {
|
||||
@@ -525,8 +526,10 @@ func TestGetSpec(t *testing.T) {
|
||||
assert.Equal(t, "90", v)
|
||||
case "MAX_CELLS_IN_EXTENDED_MATRIX":
|
||||
assert.Equal(t, "91", v)
|
||||
case "UNSET_DEPOSIT_RECEIPTS_START_INDEX":
|
||||
case "UNSET_DEPOSIT_REQUESTS_START_INDEX":
|
||||
assert.Equal(t, "92", v)
|
||||
case "MAX_DEPOSIT_REQUESTS_PER_PAYLOAD":
|
||||
assert.Equal(t, "93", v)
|
||||
default:
|
||||
t.Errorf("Incorrect key: %s", k)
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/blocks"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/network/httputil"
|
||||
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
||||
@@ -33,6 +34,12 @@ func (s *Server) BlockRewards(w http.ResponseWriter, r *http.Request) {
|
||||
if !shared.WriteBlockFetchError(w, blk, err) {
|
||||
return
|
||||
}
|
||||
|
||||
if err := blocks.BeaconBlockIsNil(blk); err != nil {
|
||||
httputil.HandleError(w, fmt.Sprintf("block id %s was not found", blockId), http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
if blk.Version() == version.Phase0 {
|
||||
httputil.HandleError(w, "Block rewards are not supported for Phase 0 blocks", http.StatusBadRequest)
|
||||
return
|
||||
|
||||
@@ -5,6 +5,7 @@ go_library(
|
||||
srcs = [
|
||||
"handlers.go",
|
||||
"handlers_block.go",
|
||||
"log.go",
|
||||
"server.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/eth/validator",
|
||||
|
||||
@@ -31,7 +31,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v5/network/httputil"
|
||||
ethpbalpha "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/time/slots"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/sirupsen/logrus"
|
||||
"go.opencensus.io/trace"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
@@ -360,8 +360,7 @@ func (s *Server) SubmitBeaconCommitteeSubscription(w http.ResponseWriter, r *htt
|
||||
}
|
||||
|
||||
fetchValsLen := func(slot primitives.Slot) (uint64, error) {
|
||||
wantedEpoch := slots.ToEpoch(slot)
|
||||
vals, err := s.HeadFetcher.HeadValidatorsIndices(ctx, wantedEpoch)
|
||||
vals, err := s.HeadFetcher.HeadValidatorsIndicesFromAdvancedSlots(ctx, slot)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -592,7 +591,7 @@ func (s *Server) PrepareBeaconProposer(w http.ResponseWriter, r *http.Request) {
|
||||
if len(validatorIndices) == 0 {
|
||||
return
|
||||
}
|
||||
log.WithFields(log.Fields{
|
||||
log.WithFields(logrus.Fields{
|
||||
"validatorIndices": validatorIndices,
|
||||
}).Info("Updated fee recipient addresses")
|
||||
}
|
||||
|
||||
@@ -220,8 +220,9 @@ func (s *Server) produceBlockV3(ctx context.Context, w http.ResponseWriter, r *h
|
||||
|
||||
consensusBlockValue, httpError := getConsensusBlockValue(ctx, s.BlockRewardFetcher, v1alpha1resp.Block)
|
||||
if httpError != nil {
|
||||
httputil.WriteError(w, httpError)
|
||||
return
|
||||
log.WithError(httpError).Debug("Failed to get consensus block value")
|
||||
// Having the consensus block value is not critical to block production
|
||||
consensusBlockValue = ""
|
||||
}
|
||||
|
||||
w.Header().Set(api.ExecutionPayloadBlindedHeader, fmt.Sprintf("%v", v1alpha1resp.IsBlinded))
|
||||
@@ -297,7 +298,7 @@ func getConsensusBlockValue(ctx context.Context, blockRewardsFetcher rewards.Blo
|
||||
}
|
||||
}
|
||||
if bb.Version() == version.Phase0 {
|
||||
// ignore for phase 0
|
||||
// Getting the block value for Phase 0 is very hard, so we ignore it
|
||||
return "", nil
|
||||
}
|
||||
// Get consensus payload value which is the same as the total from the block rewards api.
|
||||
|
||||
5
beacon-chain/rpc/eth/validator/log.go
Normal file
5
beacon-chain/rpc/eth/validator/log.go
Normal file
@@ -0,0 +1,5 @@
|
||||
package validator
|
||||
|
||||
import "github.com/sirupsen/logrus"
|
||||
|
||||
var log = logrus.WithField("prefix", "beacon-api")
|
||||
@@ -9,6 +9,8 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v5/api/pagination"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/db/filters"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/operations/attestations"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state/stategen"
|
||||
"github.com/prysmaticlabs/prysm/v5/cmd"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces"
|
||||
@@ -67,6 +69,13 @@ func (bs *Server) ListAttestations(
|
||||
return nil, status.Errorf(codes.Internal, "Could not fetch attestations: %v", err)
|
||||
}
|
||||
case *ethpb.ListAttestationsRequest_Epoch:
|
||||
if q.Epoch >= params.BeaconConfig().ElectraForkEpoch {
|
||||
return ðpb.ListAttestationsResponse{
|
||||
Attestations: make([]*ethpb.Attestation, 0),
|
||||
TotalSize: int32(0),
|
||||
NextPageToken: strconv.Itoa(0),
|
||||
}, nil
|
||||
}
|
||||
blocks, _, err = bs.BeaconDB.Blocks(ctx, filters.NewFilter().SetStartEpoch(q.Epoch).SetEndEpoch(q.Epoch))
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not fetch attestations: %v", err)
|
||||
@@ -74,17 +83,15 @@ func (bs *Server) ListAttestations(
|
||||
default:
|
||||
return nil, status.Error(codes.InvalidArgument, "Must specify a filter criteria for fetching attestations")
|
||||
}
|
||||
atts := make([]ethpb.Att, 0, params.BeaconConfig().MaxAttestations*uint64(len(blocks)))
|
||||
for _, blk := range blocks {
|
||||
atts = append(atts, blk.Block().Body().Attestations()...)
|
||||
|
||||
atts, err := blockAttestations[*ethpb.Attestation](blocks)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// We sort attestations according to the Sortable interface.
|
||||
sort.Sort(sortableAttestations(atts))
|
||||
numAttestations := len(atts)
|
||||
|
||||
// If there are no attestations, we simply return a response specifying this.
|
||||
// Otherwise, attempting to paginate 0 attestations below would result in an error.
|
||||
if numAttestations == 0 {
|
||||
if len(atts) == 0 {
|
||||
return ðpb.ListAttestationsResponse{
|
||||
Attestations: make([]*ethpb.Attestation, 0),
|
||||
TotalSize: int32(0),
|
||||
@@ -92,20 +99,77 @@ func (bs *Server) ListAttestations(
|
||||
}, nil
|
||||
}
|
||||
|
||||
start, end, nextPageToken, err := pagination.StartAndEndPage(req.PageToken, int(req.PageSize), numAttestations)
|
||||
start, end, nextPageToken, err := pagination.StartAndEndPage(req.PageToken, int(req.PageSize), len(atts))
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not paginate attestations: %v", err)
|
||||
}
|
||||
attestations := make([]*ethpb.Attestation, 0, len(atts))
|
||||
for _, att := range atts {
|
||||
a, ok := att.(*ethpb.Attestation)
|
||||
if ok {
|
||||
attestations = append(attestations, a)
|
||||
}
|
||||
}
|
||||
|
||||
return ðpb.ListAttestationsResponse{
|
||||
Attestations: attestations[start:end],
|
||||
TotalSize: int32(numAttestations),
|
||||
Attestations: atts[start:end],
|
||||
TotalSize: int32(len(atts)),
|
||||
NextPageToken: nextPageToken,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ListAttestationsElectra retrieves attestations by block root, slot, or epoch.
|
||||
// Attestations are sorted by data slot by default.
|
||||
//
|
||||
// The server may return an empty list when no attestations match the given
|
||||
// filter criteria. This RPC should not return NOT_FOUND. Only one filter
|
||||
// criteria should be used.
|
||||
func (bs *Server) ListAttestationsElectra(ctx context.Context, req *ethpb.ListAttestationsRequest) (*ethpb.ListAttestationsElectraResponse, error) {
|
||||
if int(req.PageSize) > cmd.Get().MaxRPCPageSize {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "Requested page size %d can not be greater than max size %d",
|
||||
req.PageSize, cmd.Get().MaxRPCPageSize)
|
||||
}
|
||||
var blocks []interfaces.ReadOnlySignedBeaconBlock
|
||||
var err error
|
||||
switch q := req.QueryFilter.(type) {
|
||||
case *ethpb.ListAttestationsRequest_GenesisEpoch:
|
||||
return ðpb.ListAttestationsElectraResponse{
|
||||
Attestations: make([]*ethpb.AttestationElectra, 0),
|
||||
TotalSize: int32(0),
|
||||
NextPageToken: strconv.Itoa(0),
|
||||
}, nil
|
||||
case *ethpb.ListAttestationsRequest_Epoch:
|
||||
if q.Epoch < params.BeaconConfig().ElectraForkEpoch {
|
||||
return ðpb.ListAttestationsElectraResponse{
|
||||
Attestations: make([]*ethpb.AttestationElectra, 0),
|
||||
TotalSize: int32(0),
|
||||
NextPageToken: strconv.Itoa(0),
|
||||
}, nil
|
||||
}
|
||||
blocks, _, err = bs.BeaconDB.Blocks(ctx, filters.NewFilter().SetStartEpoch(q.Epoch).SetEndEpoch(q.Epoch))
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not fetch attestations: %v", err)
|
||||
}
|
||||
default:
|
||||
return nil, status.Error(codes.InvalidArgument, "Must specify a filter criteria for fetching attestations")
|
||||
}
|
||||
|
||||
atts, err := blockAttestations[*ethpb.AttestationElectra](blocks)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// If there are no attestations, we simply return a response specifying this.
|
||||
// Otherwise, attempting to paginate 0 attestations below would result in an error.
|
||||
if len(atts) == 0 {
|
||||
return ðpb.ListAttestationsElectraResponse{
|
||||
Attestations: make([]*ethpb.AttestationElectra, 0),
|
||||
TotalSize: int32(0),
|
||||
NextPageToken: strconv.Itoa(0),
|
||||
}, nil
|
||||
}
|
||||
|
||||
start, end, nextPageToken, err := pagination.StartAndEndPage(req.PageToken, int(req.PageSize), len(atts))
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not paginate attestations: %v", err)
|
||||
}
|
||||
|
||||
return ðpb.ListAttestationsElectraResponse{
|
||||
Attestations: atts[start:end],
|
||||
TotalSize: int32(len(atts)),
|
||||
NextPageToken: nextPageToken,
|
||||
}, nil
|
||||
}
|
||||
@@ -128,6 +192,13 @@ func (bs *Server) ListIndexedAttestations(
|
||||
return nil, status.Errorf(codes.Internal, "Could not fetch attestations: %v", err)
|
||||
}
|
||||
case *ethpb.ListIndexedAttestationsRequest_Epoch:
|
||||
if q.Epoch >= params.BeaconConfig().ElectraForkEpoch {
|
||||
return ðpb.ListIndexedAttestationsResponse{
|
||||
IndexedAttestations: make([]*ethpb.IndexedAttestation, 0),
|
||||
TotalSize: int32(0),
|
||||
NextPageToken: strconv.Itoa(0),
|
||||
}, nil
|
||||
}
|
||||
blocks, _, err = bs.BeaconDB.Blocks(ctx, filters.NewFilter().SetStartEpoch(q.Epoch).SetEndEpoch(q.Epoch))
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not fetch attestations: %v", err)
|
||||
@@ -136,29 +207,205 @@ func (bs *Server) ListIndexedAttestations(
|
||||
return nil, status.Error(codes.InvalidArgument, "Must specify a filter criteria for fetching attestations")
|
||||
}
|
||||
|
||||
attsArray := make([]ethpb.Att, 0, params.BeaconConfig().MaxAttestations*uint64(len(blocks)))
|
||||
for _, b := range blocks {
|
||||
attsArray = append(attsArray, b.Block().Body().Attestations()...)
|
||||
indexedAtts, err := blockIndexedAttestations[*ethpb.IndexedAttestation](ctx, blocks, bs.StateGen)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// We sort attestations according to the Sortable interface.
|
||||
sort.Sort(sortableAttestations(attsArray))
|
||||
numAttestations := len(attsArray)
|
||||
|
||||
// If there are no attestations, we simply return a response specifying this.
|
||||
// Otherwise, attempting to paginate 0 attestations below would result in an error.
|
||||
if numAttestations == 0 {
|
||||
if len(indexedAtts) == 0 {
|
||||
return ðpb.ListIndexedAttestationsResponse{
|
||||
IndexedAttestations: make([]*ethpb.IndexedAttestation, 0),
|
||||
TotalSize: int32(0),
|
||||
NextPageToken: strconv.Itoa(0),
|
||||
}, nil
|
||||
}
|
||||
|
||||
start, end, nextPageToken, err := pagination.StartAndEndPage(req.PageToken, int(req.PageSize), len(indexedAtts))
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not paginate attestations: %v", err)
|
||||
}
|
||||
|
||||
return ðpb.ListIndexedAttestationsResponse{
|
||||
IndexedAttestations: indexedAtts[start:end],
|
||||
TotalSize: int32(len(indexedAtts)),
|
||||
NextPageToken: nextPageToken,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ListIndexedAttestationsElectra retrieves indexed attestations by block root.
|
||||
// IndexedAttestationsForEpoch are sorted by data slot by default. Start-end epoch
|
||||
// filter is used to retrieve blocks with.
|
||||
//
|
||||
// The server may return an empty list when no attestations match the given
|
||||
// filter criteria. This RPC should not return NOT_FOUND.
|
||||
func (bs *Server) ListIndexedAttestationsElectra(
|
||||
ctx context.Context,
|
||||
req *ethpb.ListIndexedAttestationsRequest,
|
||||
) (*ethpb.ListIndexedAttestationsElectraResponse, error) {
|
||||
var blocks []interfaces.ReadOnlySignedBeaconBlock
|
||||
var err error
|
||||
switch q := req.QueryFilter.(type) {
|
||||
case *ethpb.ListIndexedAttestationsRequest_GenesisEpoch:
|
||||
return ðpb.ListIndexedAttestationsElectraResponse{
|
||||
IndexedAttestations: make([]*ethpb.IndexedAttestationElectra, 0),
|
||||
TotalSize: int32(0),
|
||||
NextPageToken: strconv.Itoa(0),
|
||||
}, nil
|
||||
case *ethpb.ListIndexedAttestationsRequest_Epoch:
|
||||
if q.Epoch < params.BeaconConfig().ElectraForkEpoch {
|
||||
return ðpb.ListIndexedAttestationsElectraResponse{
|
||||
IndexedAttestations: make([]*ethpb.IndexedAttestationElectra, 0),
|
||||
TotalSize: int32(0),
|
||||
NextPageToken: strconv.Itoa(0),
|
||||
}, nil
|
||||
}
|
||||
blocks, _, err = bs.BeaconDB.Blocks(ctx, filters.NewFilter().SetStartEpoch(q.Epoch).SetEndEpoch(q.Epoch))
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not fetch attestations: %v", err)
|
||||
}
|
||||
default:
|
||||
return nil, status.Error(codes.InvalidArgument, "Must specify a filter criteria for fetching attestations")
|
||||
}
|
||||
|
||||
indexedAtts, err := blockIndexedAttestations[*ethpb.IndexedAttestationElectra](ctx, blocks, bs.StateGen)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// If there are no attestations, we simply return a response specifying this.
|
||||
// Otherwise, attempting to paginate 0 attestations below would result in an error.
|
||||
if len(indexedAtts) == 0 {
|
||||
return ðpb.ListIndexedAttestationsElectraResponse{
|
||||
IndexedAttestations: make([]*ethpb.IndexedAttestationElectra, 0),
|
||||
TotalSize: int32(0),
|
||||
NextPageToken: strconv.Itoa(0),
|
||||
}, nil
|
||||
}
|
||||
|
||||
start, end, nextPageToken, err := pagination.StartAndEndPage(req.PageToken, int(req.PageSize), len(indexedAtts))
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not paginate attestations: %v", err)
|
||||
}
|
||||
|
||||
return ðpb.ListIndexedAttestationsElectraResponse{
|
||||
IndexedAttestations: indexedAtts[start:end],
|
||||
TotalSize: int32(len(indexedAtts)),
|
||||
NextPageToken: nextPageToken,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// AttestationPool retrieves pending attestations.
|
||||
//
|
||||
// The server returns a list of attestations that have been seen but not
|
||||
// yet processed. Pool attestations eventually expire as the slot
|
||||
// advances, so an attestation missing from this request does not imply
|
||||
// that it was included in a block. The attestation may have expired.
|
||||
// Refer to the ethereum consensus specification for more details on how
|
||||
// attestations are processed and when they are no longer valid.
|
||||
// https://github.com/ethereum/consensus-specs/blob/dev/specs/core/0_beacon-chain.md#attestations
|
||||
func (bs *Server) AttestationPool(_ context.Context, req *ethpb.AttestationPoolRequest) (*ethpb.AttestationPoolResponse, error) {
|
||||
atts, err := attestationsFromPool[*ethpb.Attestation](req.PageSize, bs.AttestationsPool)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// If there are no attestations, we simply return a response specifying this.
|
||||
// Otherwise, attempting to paginate 0 attestations below would result in an error.
|
||||
if len(atts) == 0 {
|
||||
return ðpb.AttestationPoolResponse{
|
||||
Attestations: make([]*ethpb.Attestation, 0),
|
||||
TotalSize: int32(0),
|
||||
NextPageToken: strconv.Itoa(0),
|
||||
}, nil
|
||||
}
|
||||
|
||||
start, end, nextPageToken, err := pagination.StartAndEndPage(req.PageToken, int(req.PageSize), len(atts))
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not paginate attestations: %v", err)
|
||||
}
|
||||
|
||||
return ðpb.AttestationPoolResponse{
|
||||
Attestations: atts[start:end],
|
||||
TotalSize: int32(len(atts)),
|
||||
NextPageToken: nextPageToken,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (bs *Server) AttestationPoolElectra(_ context.Context, req *ethpb.AttestationPoolRequest) (*ethpb.AttestationPoolElectraResponse, error) {
|
||||
atts, err := attestationsFromPool[*ethpb.AttestationElectra](req.PageSize, bs.AttestationsPool)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// If there are no attestations, we simply return a response specifying this.
|
||||
// Otherwise, attempting to paginate 0 attestations below would result in an error.
|
||||
if len(atts) == 0 {
|
||||
return ðpb.AttestationPoolElectraResponse{
|
||||
Attestations: make([]*ethpb.AttestationElectra, 0),
|
||||
TotalSize: int32(0),
|
||||
NextPageToken: strconv.Itoa(0),
|
||||
}, nil
|
||||
}
|
||||
|
||||
start, end, nextPageToken, err := pagination.StartAndEndPage(req.PageToken, int(req.PageSize), len(atts))
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not paginate attestations: %v", err)
|
||||
}
|
||||
|
||||
return ðpb.AttestationPoolElectraResponse{
|
||||
Attestations: atts[start:end],
|
||||
TotalSize: int32(len(atts)),
|
||||
NextPageToken: nextPageToken,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func blockAttestations[T ethpb.Att](blocks []interfaces.ReadOnlySignedBeaconBlock) ([]T, error) {
|
||||
blockAtts := make([]ethpb.Att, 0, params.BeaconConfig().MaxAttestations*uint64(len(blocks)))
|
||||
for _, blk := range blocks {
|
||||
blockAtts = append(blockAtts, blk.Block().Body().Attestations()...)
|
||||
}
|
||||
// We sort attestations according to the Sortable interface.
|
||||
sort.Sort(sortableAttestations(blockAtts))
|
||||
numAttestations := len(blockAtts)
|
||||
if numAttestations == 0 {
|
||||
return []T{}, nil
|
||||
}
|
||||
|
||||
atts := make([]T, 0, len(blockAtts))
|
||||
for _, att := range blockAtts {
|
||||
a, ok := att.(T)
|
||||
if !ok {
|
||||
var expected T
|
||||
return nil, status.Errorf(codes.Internal, "Attestation is of the wrong type (expected %T, got %T)", expected, att)
|
||||
}
|
||||
atts = append(atts, a)
|
||||
}
|
||||
|
||||
return atts, nil
|
||||
}
|
||||
|
||||
func blockIndexedAttestations[T ethpb.IndexedAtt](
|
||||
ctx context.Context,
|
||||
blocks []interfaces.ReadOnlySignedBeaconBlock,
|
||||
stateGen stategen.StateManager,
|
||||
) ([]T, error) {
|
||||
attsArray := make([]ethpb.Att, 0, params.BeaconConfig().MaxAttestations*uint64(len(blocks)))
|
||||
for _, b := range blocks {
|
||||
attsArray = append(attsArray, b.Block().Body().Attestations()...)
|
||||
}
|
||||
|
||||
// We sort attestations according to the Sortable interface.
|
||||
sort.Sort(sortableAttestations(attsArray))
|
||||
numAttestations := len(attsArray)
|
||||
if numAttestations == 0 {
|
||||
return []T{}, nil
|
||||
}
|
||||
|
||||
// We use the retrieved committees for the b root to convert all attestations
|
||||
// into indexed form effectively.
|
||||
mappedAttestations := mapAttestationsByTargetRoot(attsArray)
|
||||
indexedAtts := make([]*ethpb.IndexedAttestation, 0, numAttestations)
|
||||
indexed := make([]T, 0, numAttestations)
|
||||
for targetRoot, atts := range mappedAttestations {
|
||||
attState, err := bs.StateGen.StateByRoot(ctx, targetRoot)
|
||||
attState, err := stateGen.StateByRoot(ctx, targetRoot)
|
||||
if err != nil && strings.Contains(err.Error(), "unknown state summary") {
|
||||
// We shouldn't stop the request if we encounter an attestation we don't have the state for.
|
||||
log.Debugf("Could not get state for attestation target root %#x", targetRoot)
|
||||
@@ -185,67 +432,36 @@ func (bs *Server) ListIndexedAttestations(
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
a, ok := idxAtt.(*ethpb.IndexedAttestation)
|
||||
if ok {
|
||||
indexedAtts = append(indexedAtts, a)
|
||||
a, ok := idxAtt.(T)
|
||||
if !ok {
|
||||
var expected T
|
||||
return nil, status.Errorf(codes.Internal, "Indexed attestation is of the wrong type (expected %T, got %T)", expected, idxAtt)
|
||||
}
|
||||
indexed = append(indexed, a)
|
||||
}
|
||||
}
|
||||
|
||||
start, end, nextPageToken, err := pagination.StartAndEndPage(req.PageToken, int(req.PageSize), len(indexedAtts))
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not paginate attestations: %v", err)
|
||||
}
|
||||
return ðpb.ListIndexedAttestationsResponse{
|
||||
IndexedAttestations: indexedAtts[start:end],
|
||||
TotalSize: int32(len(indexedAtts)),
|
||||
NextPageToken: nextPageToken,
|
||||
}, nil
|
||||
return indexed, nil
|
||||
}
|
||||
|
||||
// AttestationPool retrieves pending attestations.
|
||||
//
|
||||
// The server returns a list of attestations that have been seen but not
|
||||
// yet processed. Pool attestations eventually expire as the slot
|
||||
// advances, so an attestation missing from this request does not imply
|
||||
// that it was included in a block. The attestation may have expired.
|
||||
// Refer to the ethereum consensus specification for more details on how
|
||||
// attestations are processed and when they are no longer valid.
|
||||
// https://github.com/ethereum/consensus-specs/blob/dev/specs/core/0_beacon-chain.md#attestations
|
||||
func (bs *Server) AttestationPool(
|
||||
_ context.Context, req *ethpb.AttestationPoolRequest,
|
||||
) (*ethpb.AttestationPoolResponse, error) {
|
||||
if int(req.PageSize) > cmd.Get().MaxRPCPageSize {
|
||||
func attestationsFromPool[T ethpb.Att](pageSize int32, pool attestations.Pool) ([]T, error) {
|
||||
if int(pageSize) > cmd.Get().MaxRPCPageSize {
|
||||
return nil, status.Errorf(
|
||||
codes.InvalidArgument,
|
||||
"Requested page size %d can not be greater than max size %d",
|
||||
req.PageSize,
|
||||
pageSize,
|
||||
cmd.Get().MaxRPCPageSize,
|
||||
)
|
||||
}
|
||||
atts := bs.AttestationsPool.AggregatedAttestations()
|
||||
numAtts := len(atts)
|
||||
if numAtts == 0 {
|
||||
return ðpb.AttestationPoolResponse{
|
||||
Attestations: make([]*ethpb.Attestation, 0),
|
||||
TotalSize: int32(0),
|
||||
NextPageToken: strconv.Itoa(0),
|
||||
}, nil
|
||||
}
|
||||
start, end, nextPageToken, err := pagination.StartAndEndPage(req.PageToken, int(req.PageSize), numAtts)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not paginate attestations: %v", err)
|
||||
}
|
||||
attestations := make([]*ethpb.Attestation, 0, len(atts))
|
||||
for _, att := range atts {
|
||||
a, ok := att.(*ethpb.Attestation)
|
||||
if ok {
|
||||
attestations = append(attestations, a)
|
||||
poolAtts := pool.AggregatedAttestations()
|
||||
atts := make([]T, 0, len(poolAtts))
|
||||
for _, att := range poolAtts {
|
||||
a, ok := att.(T)
|
||||
if !ok {
|
||||
var expected T
|
||||
return nil, status.Errorf(codes.Internal, "Attestation is of the wrong type (expected %T, got %T)", expected, att)
|
||||
}
|
||||
atts = append(atts, a)
|
||||
}
|
||||
return ðpb.AttestationPoolResponse{
|
||||
Attestations: attestations[start:end],
|
||||
TotalSize: int32(numAtts),
|
||||
NextPageToken: nextPageToken,
|
||||
}, nil
|
||||
return atts, nil
|
||||
}
|
||||
|
||||
@@ -462,6 +462,59 @@ func TestServer_ListAttestations_Pagination_DefaultPageSize(t *testing.T) {
|
||||
assert.DeepEqual(t, atts[i:j], res.Attestations, "Incorrect attestations response")
|
||||
}
|
||||
|
||||
func TestServer_ListAttestationsElectra(t *testing.T) {
|
||||
params.SetupTestConfigCleanup(t)
|
||||
cfg := params.BeaconConfig()
|
||||
cfg.ElectraForkEpoch = 0
|
||||
params.OverrideBeaconConfig(cfg)
|
||||
|
||||
db := dbTest.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
|
||||
st, err := state_native.InitializeFromProtoElectra(ðpb.BeaconStateElectra{
|
||||
Slot: 0,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
bs := &Server{
|
||||
BeaconDB: db,
|
||||
HeadFetcher: &chainMock.ChainService{
|
||||
State: st,
|
||||
},
|
||||
}
|
||||
|
||||
cb := primitives.NewAttestationCommitteeBits()
|
||||
cb.SetBitAt(2, true)
|
||||
att := util.HydrateAttestationElectra(ðpb.AttestationElectra{
|
||||
AggregationBits: bitfield.NewBitlist(0),
|
||||
Data: ðpb.AttestationData{
|
||||
Slot: 2,
|
||||
},
|
||||
CommitteeBits: cb,
|
||||
})
|
||||
|
||||
parentRoot := [32]byte{1, 2, 3}
|
||||
signedBlock := util.NewBeaconBlockElectra()
|
||||
signedBlock.Block.ParentRoot = bytesutil.PadTo(parentRoot[:], 32)
|
||||
signedBlock.Block.Body.Attestations = []*ethpb.AttestationElectra{att}
|
||||
root, err := signedBlock.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
util.SaveBlock(t, ctx, db, signedBlock)
|
||||
require.NoError(t, db.SaveGenesisBlockRoot(ctx, root))
|
||||
wanted := ðpb.ListAttestationsElectraResponse{
|
||||
Attestations: []*ethpb.AttestationElectra{att},
|
||||
NextPageToken: "",
|
||||
TotalSize: 1,
|
||||
}
|
||||
|
||||
res, err := bs.ListAttestationsElectra(ctx, ðpb.ListAttestationsRequest{
|
||||
QueryFilter: ðpb.ListAttestationsRequest_Epoch{
|
||||
Epoch: params.BeaconConfig().ElectraForkEpoch,
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.DeepSSZEqual(t, wanted, res)
|
||||
}
|
||||
|
||||
func TestServer_mapAttestationToTargetRoot(t *testing.T) {
|
||||
count := primitives.Slot(100)
|
||||
atts := make([]ethpb.Att, count)
|
||||
@@ -494,8 +547,6 @@ func TestServer_mapAttestationToTargetRoot(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestServer_ListIndexedAttestations_GenesisEpoch(t *testing.T) {
|
||||
params.SetupTestConfigCleanup(t)
|
||||
params.OverrideBeaconConfig(params.BeaconConfig())
|
||||
db := dbTest.SetupDB(t)
|
||||
helpers.ClearCache()
|
||||
ctx := context.Background()
|
||||
@@ -606,8 +657,6 @@ func TestServer_ListIndexedAttestations_GenesisEpoch(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestServer_ListIndexedAttestations_OldEpoch(t *testing.T) {
|
||||
params.SetupTestConfigCleanup(t)
|
||||
params.OverrideBeaconConfig(params.BeaconConfig())
|
||||
db := dbTest.SetupDB(t)
|
||||
helpers.ClearCache()
|
||||
ctx := context.Background()
|
||||
@@ -690,6 +739,123 @@ func TestServer_ListIndexedAttestations_OldEpoch(t *testing.T) {
|
||||
require.DeepEqual(t, indexedAtts, res.IndexedAttestations, "Incorrect list indexed attestations response")
|
||||
}
|
||||
|
||||
func TestServer_ListIndexedAttestationsElectra(t *testing.T) {
|
||||
params.SetupTestConfigCleanup(t)
|
||||
cfg := params.BeaconConfig()
|
||||
cfg.ElectraForkEpoch = 0
|
||||
params.OverrideBeaconConfig(cfg)
|
||||
|
||||
db := dbTest.SetupDB(t)
|
||||
helpers.ClearCache()
|
||||
ctx := context.Background()
|
||||
targetRoot1 := bytesutil.ToBytes32([]byte("root"))
|
||||
targetRoot2 := bytesutil.ToBytes32([]byte("root2"))
|
||||
|
||||
count := params.BeaconConfig().SlotsPerEpoch
|
||||
atts := make([]*ethpb.AttestationElectra, 0, count)
|
||||
atts2 := make([]*ethpb.AttestationElectra, 0, count)
|
||||
|
||||
for i := primitives.Slot(0); i < count; i++ {
|
||||
var targetRoot [32]byte
|
||||
if i%2 == 0 {
|
||||
targetRoot = targetRoot1
|
||||
} else {
|
||||
targetRoot = targetRoot2
|
||||
}
|
||||
cb := primitives.NewAttestationCommitteeBits()
|
||||
cb.SetBitAt(0, true)
|
||||
blockExample := util.NewBeaconBlockElectra()
|
||||
blockExample.Block.Body.Attestations = []*ethpb.AttestationElectra{
|
||||
{
|
||||
Signature: make([]byte, fieldparams.BLSSignatureLength),
|
||||
Data: ðpb.AttestationData{
|
||||
BeaconBlockRoot: make([]byte, fieldparams.RootLength),
|
||||
Target: ðpb.Checkpoint{
|
||||
Root: targetRoot[:],
|
||||
},
|
||||
Source: ðpb.Checkpoint{
|
||||
Root: make([]byte, fieldparams.RootLength),
|
||||
},
|
||||
Slot: i,
|
||||
},
|
||||
AggregationBits: bitfield.NewBitlist(128 / uint64(params.BeaconConfig().SlotsPerEpoch)),
|
||||
CommitteeBits: cb,
|
||||
},
|
||||
}
|
||||
util.SaveBlock(t, ctx, db, blockExample)
|
||||
if i%2 == 0 {
|
||||
atts = append(atts, blockExample.Block.Body.Attestations...)
|
||||
} else {
|
||||
atts2 = append(atts2, blockExample.Block.Body.Attestations...)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// We setup 512 validators so that committee size matches the length of attestations' aggregation bits.
|
||||
numValidators := uint64(512)
|
||||
state, _ := util.DeterministicGenesisStateElectra(t, numValidators)
|
||||
|
||||
// Next up we convert the test attestations to indexed form:
|
||||
indexedAtts := make([]*ethpb.IndexedAttestationElectra, len(atts)+len(atts2))
|
||||
for i := 0; i < len(atts); i++ {
|
||||
att := atts[i]
|
||||
committee, err := helpers.BeaconCommitteeFromState(context.Background(), state, att.Data.Slot, 0)
|
||||
require.NoError(t, err)
|
||||
idxAtt, err := attestation.ConvertToIndexed(ctx, atts[i], committee)
|
||||
require.NoError(t, err, "Could not convert attestation to indexed")
|
||||
a, ok := idxAtt.(*ethpb.IndexedAttestationElectra)
|
||||
require.Equal(t, true, ok, "unexpected type of indexed attestation")
|
||||
indexedAtts[i] = a
|
||||
}
|
||||
for i := 0; i < len(atts2); i++ {
|
||||
att := atts2[i]
|
||||
committee, err := helpers.BeaconCommitteeFromState(context.Background(), state, att.Data.Slot, 0)
|
||||
require.NoError(t, err)
|
||||
idxAtt, err := attestation.ConvertToIndexed(ctx, atts2[i], committee)
|
||||
require.NoError(t, err, "Could not convert attestation to indexed")
|
||||
a, ok := idxAtt.(*ethpb.IndexedAttestationElectra)
|
||||
require.Equal(t, true, ok, "unexpected type of indexed attestation")
|
||||
indexedAtts[i+len(atts)] = a
|
||||
}
|
||||
|
||||
bs := &Server{
|
||||
BeaconDB: db,
|
||||
GenesisTimeFetcher: &chainMock.ChainService{State: state},
|
||||
HeadFetcher: &chainMock.ChainService{State: state},
|
||||
StateGen: stategen.New(db, doublylinkedtree.New()),
|
||||
}
|
||||
err := db.SaveStateSummary(ctx, ðpb.StateSummary{
|
||||
Root: targetRoot1[:],
|
||||
Slot: 1,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
err = db.SaveStateSummary(ctx, ðpb.StateSummary{
|
||||
Root: targetRoot2[:],
|
||||
Slot: 2,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, db.SaveState(ctx, state, bytesutil.ToBytes32(targetRoot1[:])))
|
||||
require.NoError(t, state.SetSlot(state.Slot()+1))
|
||||
require.NoError(t, db.SaveState(ctx, state, bytesutil.ToBytes32(targetRoot2[:])))
|
||||
res, err := bs.ListIndexedAttestationsElectra(ctx, ðpb.ListIndexedAttestationsRequest{
|
||||
QueryFilter: ðpb.ListIndexedAttestationsRequest_Epoch{
|
||||
Epoch: 0,
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, len(indexedAtts), len(res.IndexedAttestations), "Incorrect indexted attestations length")
|
||||
sort.Slice(indexedAtts, func(i, j int) bool {
|
||||
return indexedAtts[i].GetData().Slot < indexedAtts[j].GetData().Slot
|
||||
})
|
||||
sort.Slice(res.IndexedAttestations, func(i, j int) bool {
|
||||
return res.IndexedAttestations[i].Data.Slot < res.IndexedAttestations[j].Data.Slot
|
||||
})
|
||||
|
||||
assert.DeepEqual(t, indexedAtts, res.IndexedAttestations, "Incorrect list indexed attestations response")
|
||||
}
|
||||
|
||||
func TestServer_AttestationPool_Pagination_ExceedsMaxPageSize(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
bs := &Server{}
|
||||
@@ -827,3 +993,24 @@ func TestServer_AttestationPool_Pagination_CustomPageSize(t *testing.T) {
|
||||
assert.Equal(t, tt.res.NextPageToken, res.NextPageToken, "Unexpected next page token")
|
||||
}
|
||||
}
|
||||
|
||||
func TestServer_AttestationPoolElectra(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
bs := &Server{
|
||||
AttestationsPool: attestations.NewPool(),
|
||||
}
|
||||
|
||||
atts := make([]ethpb.Att, params.BeaconConfig().DefaultPageSize+1)
|
||||
for i := 0; i < len(atts); i++ {
|
||||
att := util.NewAttestationElectra()
|
||||
att.Data.Slot = primitives.Slot(i)
|
||||
atts[i] = att
|
||||
}
|
||||
require.NoError(t, bs.AttestationsPool.SaveAggregatedAttestations(atts))
|
||||
|
||||
req := ðpb.AttestationPoolRequest{}
|
||||
res, err := bs.AttestationPoolElectra(ctx, req)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, params.BeaconConfig().DefaultPageSize, len(res.Attestations), "Unexpected number of attestations")
|
||||
assert.Equal(t, params.BeaconConfig().DefaultPageSize+1, int(res.TotalSize), "Unexpected total size")
|
||||
}
|
||||
|
||||
@@ -36,26 +36,31 @@ func (bs *Server) SubmitProposerSlashing(
|
||||
}, nil
|
||||
}
|
||||
|
||||
// SubmitAttesterSlashing receives an attester slashing object via
|
||||
func (bs *Server) SubmitAttesterSlashing(ctx context.Context, req *ethpb.AttesterSlashing) (*ethpb.SubmitSlashingResponse, error) {
|
||||
return bs.submitAttesterSlashing(ctx, req)
|
||||
}
|
||||
|
||||
// SubmitAttesterSlashingElectra receives an attester slashing object via
|
||||
// RPC and injects it into the beacon node's operations pool.
|
||||
// Submission into this pool does not guarantee inclusion into a beacon block.
|
||||
func (bs *Server) SubmitAttesterSlashing(
|
||||
ctx context.Context,
|
||||
req *ethpb.AttesterSlashing,
|
||||
) (*ethpb.SubmitSlashingResponse, error) {
|
||||
func (bs *Server) SubmitAttesterSlashingElectra(ctx context.Context, req *ethpb.AttesterSlashingElectra) (*ethpb.SubmitSlashingResponse, error) {
|
||||
return bs.submitAttesterSlashing(ctx, req)
|
||||
}
|
||||
|
||||
func (bs *Server) submitAttesterSlashing(ctx context.Context, slashing ethpb.AttSlashing) (*ethpb.SubmitSlashingResponse, error) {
|
||||
beaconState, err := bs.HeadFetcher.HeadStateReadOnly(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not retrieve head state: %v", err)
|
||||
}
|
||||
if err := bs.SlashingsPool.InsertAttesterSlashing(ctx, beaconState, req); err != nil {
|
||||
if err := bs.SlashingsPool.InsertAttesterSlashing(ctx, beaconState, slashing); err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not insert attester slashing into pool: %v", err)
|
||||
}
|
||||
if !features.Get().DisableBroadcastSlashings {
|
||||
if err := bs.Broadcaster.Broadcast(ctx, req); err != nil {
|
||||
if err := bs.Broadcaster.Broadcast(ctx, slashing); err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not broadcast slashing object: %v", err)
|
||||
}
|
||||
}
|
||||
indices := slice.IntersectionUint64(req.Attestation_1.AttestingIndices, req.Attestation_2.AttestingIndices)
|
||||
indices := slice.IntersectionUint64(slashing.FirstAttestation().GetAttestingIndices(), slashing.SecondAttestation().GetAttestingIndices())
|
||||
slashedIndices := make([]primitives.ValidatorIndex, len(indices))
|
||||
for i, index := range indices {
|
||||
slashedIndices[i] = primitives.ValidatorIndex(index)
|
||||
|
||||
@@ -167,3 +167,28 @@ func TestServer_SubmitAttesterSlashing_DontBroadcast(t *testing.T) {
|
||||
_, err = bs.SubmitAttesterSlashing(ctx, generatedSlashing.(*ethpb.AttesterSlashing))
|
||||
assert.NotNil(t, err, "Expected including a attester slashing for an already slashed validator to fail")
|
||||
}
|
||||
|
||||
func TestServer_SubmitAttesterSlashingElectra(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
st, privs := util.DeterministicGenesisStateElectra(t, 64)
|
||||
slashedVal, err := st.ValidatorAtIndex(5)
|
||||
require.NoError(t, err)
|
||||
slashedVal.Slashed = true
|
||||
require.NoError(t, st.UpdateValidatorAtIndex(5, slashedVal))
|
||||
|
||||
mb := &mockp2p.MockBroadcaster{}
|
||||
bs := &Server{
|
||||
HeadFetcher: &mock.ChainService{
|
||||
State: st,
|
||||
},
|
||||
SlashingsPool: slashings.NewPool(),
|
||||
Broadcaster: mb,
|
||||
}
|
||||
|
||||
generatedSlashing, err := util.GenerateAttesterSlashingForValidator(st, privs[2], primitives.ValidatorIndex(2))
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = bs.SubmitAttesterSlashingElectra(ctx, generatedSlashing.(*ethpb.AttesterSlashingElectra))
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, true, mb.BroadcastCalled.Load(), "Expected broadcast to be called when flag is set")
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/transition"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/core"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
|
||||
@@ -32,10 +33,18 @@ func (vs *Server) SubmitAggregateSelectionProof(ctx context.Context, req *ethpb.
|
||||
return nil, err
|
||||
}
|
||||
|
||||
st, err := vs.HeadFetcher.HeadStateReadOnly(ctx)
|
||||
st, err := vs.HeadFetcher.HeadState(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not determine head state: %v", err)
|
||||
}
|
||||
rt, err := vs.HeadFetcher.HeadRoot(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not determine head root: %v", err)
|
||||
}
|
||||
st, err = transition.ProcessSlotsUsingNextSlotCache(ctx, st, rt, req.Slot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
validatorIndex, exists := st.ValidatorIndexByPubkey(bytesutil.ToBytes48(req.PublicKey))
|
||||
if !exists {
|
||||
|
||||
@@ -109,6 +109,7 @@ func TestSubmitAggregateAndProof_UnaggregateOk(t *testing.T) {
|
||||
|
||||
beaconState, privKeys := util.DeterministicGenesisState(t, 32)
|
||||
att0, err := generateUnaggregatedAtt(beaconState, 0, privKeys)
|
||||
att0.Data.Slot += params.BeaconConfig().MinAttestationInclusionDelay
|
||||
require.NoError(t, err)
|
||||
err = beaconState.SetSlot(beaconState.Slot() + params.BeaconConfig().MinAttestationInclusionDelay)
|
||||
require.NoError(t, err)
|
||||
@@ -127,7 +128,7 @@ func TestSubmitAggregateAndProof_UnaggregateOk(t *testing.T) {
|
||||
v, err := beaconState.ValidatorAtIndex(1)
|
||||
require.NoError(t, err)
|
||||
pubKey := v.PublicKey
|
||||
req := ðpb.AggregateSelectionRequest{CommitteeIndex: 1, SlotSignature: sig.Marshal(), PublicKey: pubKey}
|
||||
req := ðpb.AggregateSelectionRequest{Slot: beaconState.Slot(), CommitteeIndex: 1, SlotSignature: sig.Marshal(), PublicKey: pubKey}
|
||||
|
||||
require.NoError(t, aggregatorServer.AttPool.SaveUnaggregatedAttestation(att0))
|
||||
_, err = aggregatorServer.SubmitAggregateSelectionProof(ctx, req)
|
||||
@@ -144,8 +145,10 @@ func TestSubmitAggregateAndProof_AggregateOk(t *testing.T) {
|
||||
|
||||
beaconState, privKeys := util.DeterministicGenesisState(t, 32)
|
||||
att0, err := generateAtt(beaconState, 0, privKeys)
|
||||
att0.Data.Slot += params.BeaconConfig().MinAttestationInclusionDelay
|
||||
require.NoError(t, err)
|
||||
att1, err := generateAtt(beaconState, 2, privKeys)
|
||||
att1.Data.Slot += params.BeaconConfig().MinAttestationInclusionDelay
|
||||
require.NoError(t, err)
|
||||
|
||||
err = beaconState.SetSlot(beaconState.Slot() + params.BeaconConfig().MinAttestationInclusionDelay)
|
||||
@@ -165,7 +168,7 @@ func TestSubmitAggregateAndProof_AggregateOk(t *testing.T) {
|
||||
v, err := beaconState.ValidatorAtIndex(1)
|
||||
require.NoError(t, err)
|
||||
pubKey := v.PublicKey
|
||||
req := ðpb.AggregateSelectionRequest{CommitteeIndex: 1, SlotSignature: sig.Marshal(), PublicKey: pubKey}
|
||||
req := ðpb.AggregateSelectionRequest{Slot: beaconState.Slot(), CommitteeIndex: 1, SlotSignature: sig.Marshal(), PublicKey: pubKey}
|
||||
|
||||
require.NoError(t, aggregatorServer.AttPool.SaveAggregatedAttestation(att0))
|
||||
require.NoError(t, aggregatorServer.AttPool.SaveAggregatedAttestation(att1))
|
||||
@@ -205,7 +208,7 @@ func TestSubmitAggregateAndProof_AggregateNotOk(t *testing.T) {
|
||||
v, err := beaconState.ValidatorAtIndex(1)
|
||||
require.NoError(t, err)
|
||||
pubKey := v.PublicKey
|
||||
req := ðpb.AggregateSelectionRequest{CommitteeIndex: 1, SlotSignature: sig.Marshal(), PublicKey: pubKey}
|
||||
req := ðpb.AggregateSelectionRequest{Slot: beaconState.Slot(), CommitteeIndex: 1, SlotSignature: sig.Marshal(), PublicKey: pubKey}
|
||||
|
||||
_, err = aggregatorServer.SubmitAggregateSelectionProof(ctx, req)
|
||||
assert.ErrorContains(t, "Could not find attestation for slot and committee in pool", err)
|
||||
@@ -308,14 +311,17 @@ func TestSubmitAggregateAndProof_PreferOwnAttestation(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
att0.Data.BeaconBlockRoot = bytesutil.PadTo([]byte("foo"), fieldparams.RootLength)
|
||||
att0.AggregationBits = bitfield.Bitlist{0b11100}
|
||||
att0.Data.Slot += params.BeaconConfig().MinAttestationInclusionDelay
|
||||
att1, err := generateAtt(beaconState, 0, privKeys)
|
||||
require.NoError(t, err)
|
||||
att1.Data.BeaconBlockRoot = bytesutil.PadTo([]byte("bar"), fieldparams.RootLength)
|
||||
att1.AggregationBits = bitfield.Bitlist{0b11001}
|
||||
att1.Data.Slot += params.BeaconConfig().MinAttestationInclusionDelay
|
||||
att2, err := generateAtt(beaconState, 2, privKeys)
|
||||
require.NoError(t, err)
|
||||
att2.Data.BeaconBlockRoot = bytesutil.PadTo([]byte("foo"), fieldparams.RootLength)
|
||||
att2.AggregationBits = bitfield.Bitlist{0b11110}
|
||||
att2.Data.Slot += params.BeaconConfig().MinAttestationInclusionDelay
|
||||
|
||||
err = beaconState.SetSlot(beaconState.Slot() + params.BeaconConfig().MinAttestationInclusionDelay)
|
||||
require.NoError(t, err)
|
||||
@@ -334,7 +340,7 @@ func TestSubmitAggregateAndProof_PreferOwnAttestation(t *testing.T) {
|
||||
v, err := beaconState.ValidatorAtIndex(1)
|
||||
require.NoError(t, err)
|
||||
pubKey := v.PublicKey
|
||||
req := ðpb.AggregateSelectionRequest{CommitteeIndex: 1, SlotSignature: sig.Marshal(), PublicKey: pubKey}
|
||||
req := ðpb.AggregateSelectionRequest{Slot: beaconState.Slot(), CommitteeIndex: 1, SlotSignature: sig.Marshal(), PublicKey: pubKey}
|
||||
|
||||
err = aggregatorServer.AttPool.SaveAggregatedAttestations([]ethpb.Att{
|
||||
att0,
|
||||
@@ -363,10 +369,12 @@ func TestSubmitAggregateAndProof_SelectsMostBitsWhenOwnAttestationNotPresent(t *
|
||||
require.NoError(t, err)
|
||||
att0.Data.BeaconBlockRoot = bytesutil.PadTo([]byte("foo"), fieldparams.RootLength)
|
||||
att0.AggregationBits = bitfield.Bitlist{0b11100}
|
||||
att0.Data.Slot += params.BeaconConfig().MinAttestationInclusionDelay
|
||||
att1, err := generateAtt(beaconState, 2, privKeys)
|
||||
require.NoError(t, err)
|
||||
att1.Data.BeaconBlockRoot = bytesutil.PadTo([]byte("bar"), fieldparams.RootLength)
|
||||
att1.AggregationBits = bitfield.Bitlist{0b11110}
|
||||
att1.Data.Slot += params.BeaconConfig().MinAttestationInclusionDelay
|
||||
|
||||
err = beaconState.SetSlot(beaconState.Slot() + params.BeaconConfig().MinAttestationInclusionDelay)
|
||||
require.NoError(t, err)
|
||||
@@ -385,7 +393,7 @@ func TestSubmitAggregateAndProof_SelectsMostBitsWhenOwnAttestationNotPresent(t *
|
||||
v, err := beaconState.ValidatorAtIndex(1)
|
||||
require.NoError(t, err)
|
||||
pubKey := v.PublicKey
|
||||
req := ðpb.AggregateSelectionRequest{CommitteeIndex: 1, SlotSignature: sig.Marshal(), PublicKey: pubKey}
|
||||
req := ðpb.AggregateSelectionRequest{Slot: beaconState.Slot(), CommitteeIndex: 1, SlotSignature: sig.Marshal(), PublicKey: pubKey}
|
||||
|
||||
err = aggregatorServer.AttPool.SaveAggregatedAttestations([]ethpb.Att{
|
||||
att0,
|
||||
|
||||
@@ -63,8 +63,7 @@ func (vs *Server) ProposeAttestation(ctx context.Context, att *ethpb.Attestation
|
||||
})
|
||||
|
||||
// Determine subnet to broadcast attestation to
|
||||
wantedEpoch := slots.ToEpoch(att.Data.Slot)
|
||||
vals, err := vs.HeadFetcher.HeadValidatorsIndices(ctx, wantedEpoch)
|
||||
vals, err := vs.HeadFetcher.HeadValidatorsIndicesFromAdvancedSlots(ctx, att.Data.Slot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -102,8 +101,7 @@ func (vs *Server) SubscribeCommitteeSubnets(ctx context.Context, req *ethpb.Comm
|
||||
}
|
||||
|
||||
fetchValsLen := func(slot primitives.Slot) (uint64, error) {
|
||||
wantedEpoch := slots.ToEpoch(slot)
|
||||
vals, err := vs.HeadFetcher.HeadValidatorsIndices(ctx, wantedEpoch)
|
||||
vals, err := vs.HeadFetcher.HeadValidatorsIndicesFromAdvancedSlots(ctx, slot)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
@@ -630,14 +630,14 @@ func TestServer_GetBeaconBlock_Electra(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
timeStamp, err := slots.ToTime(beaconState.GenesisTime(), electraSlot+1)
|
||||
require.NoError(t, err)
|
||||
dr := []*enginev1.DepositReceipt{{
|
||||
dr := []*enginev1.DepositRequest{{
|
||||
Pubkey: bytesutil.PadTo(privKeys[0].PublicKey().Marshal(), 48),
|
||||
WithdrawalCredentials: bytesutil.PadTo([]byte("wc"), 32),
|
||||
Amount: 123,
|
||||
Signature: bytesutil.PadTo([]byte("sig"), 96),
|
||||
Index: 456,
|
||||
}}
|
||||
wr := []*enginev1.ExecutionLayerWithdrawalRequest{
|
||||
wr := []*enginev1.WithdrawalRequest{
|
||||
{
|
||||
SourceAddress: bytesutil.PadTo([]byte("sa"), 20),
|
||||
ValidatorPubkey: bytesutil.PadTo(privKeys[1].PublicKey().Marshal(), 48),
|
||||
@@ -654,7 +654,7 @@ func TestServer_GetBeaconBlock_Electra(t *testing.T) {
|
||||
PrevRandao: random,
|
||||
BaseFeePerGas: make([]byte, fieldparams.RootLength),
|
||||
BlockHash: make([]byte, fieldparams.RootLength),
|
||||
DepositReceipts: dr,
|
||||
DepositRequests: dr,
|
||||
WithdrawalRequests: wr,
|
||||
}
|
||||
|
||||
@@ -680,7 +680,7 @@ func TestServer_GetBeaconBlock_Electra(t *testing.T) {
|
||||
got, err := proposerServer.GetBeaconBlock(ctx, req)
|
||||
require.NoError(t, err)
|
||||
p := got.GetElectra().Block.Body.ExecutionPayload
|
||||
require.DeepEqual(t, dr, p.DepositReceipts)
|
||||
require.DeepEqual(t, dr, p.DepositRequests)
|
||||
require.DeepEqual(t, wr, p.WithdrawalRequests)
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ package rpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"sync"
|
||||
|
||||
@@ -16,7 +15,6 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/builder"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/cache"
|
||||
@@ -114,8 +112,8 @@ type Config struct {
|
||||
ExecutionChainInfoFetcher execution.ChainInfoFetcher
|
||||
GenesisTimeFetcher blockchain.TimeFetcher
|
||||
GenesisFetcher blockchain.GenesisFetcher
|
||||
EnableDebugRPCEndpoints bool
|
||||
MockEth1Votes bool
|
||||
EnableDebugRPCEndpoints bool
|
||||
AttestationsPool attestations.Pool
|
||||
ExitPool voluntaryexits.PoolManager
|
||||
SlashingsPool slashings.PoolManager
|
||||
@@ -155,7 +153,7 @@ func NewService(ctx context.Context, cfg *Config) *Service {
|
||||
connectedRPCClients: make(map[net.Addr]bool),
|
||||
}
|
||||
|
||||
address := fmt.Sprintf("%s:%s", s.cfg.Host, s.cfg.Port)
|
||||
address := net.JoinHostPort(s.cfg.Host, s.cfg.Port)
|
||||
lis, err := net.Listen("tcp", address)
|
||||
if err != nil {
|
||||
log.WithError(err).Errorf("Could not listen to port in Start() %s", address)
|
||||
@@ -311,13 +309,7 @@ func NewService(ctx context.Context, cfg *Config) *Service {
|
||||
for _, e := range endpoints {
|
||||
s.cfg.Router.HandleFunc(
|
||||
e.template,
|
||||
promhttp.InstrumentHandlerDuration(
|
||||
httpRequestLatency.MustCurryWith(prometheus.Labels{"endpoint": e.name}),
|
||||
promhttp.InstrumentHandlerCounter(
|
||||
httpRequestCount.MustCurryWith(prometheus.Labels{"endpoint": e.name}),
|
||||
e.handler,
|
||||
),
|
||||
),
|
||||
e.handlerWithMiddleware(),
|
||||
).Methods(e.methods...)
|
||||
}
|
||||
|
||||
@@ -325,7 +317,6 @@ func NewService(ctx context.Context, cfg *Config) *Service {
|
||||
ethpbv1alpha1.RegisterHealthServer(s.grpcServer, nodeServer)
|
||||
ethpbv1alpha1.RegisterBeaconChainServer(s.grpcServer, beaconChainServer)
|
||||
if s.cfg.EnableDebugRPCEndpoints {
|
||||
log.Info("Enabled debug gRPC endpoints")
|
||||
debugServer := &debugv1alpha1.Server{
|
||||
GenesisTimeFetcher: s.cfg.GenesisTimeFetcher,
|
||||
BeaconDB: s.cfg.BeaconDB,
|
||||
|
||||
@@ -141,7 +141,7 @@ func (s *Service) processAttestations(
|
||||
|
||||
start := time.Now()
|
||||
|
||||
// Check for attestatinos slashings (double, sourrounding, surrounded votes).
|
||||
// Check for attestations slashings (double, surrounding, surrounded votes).
|
||||
slashings, err := s.checkSlashableAttestations(ctx, currentEpoch, validAttestations)
|
||||
if err != nil {
|
||||
log.WithError(err).Error(couldNotCheckSlashableAtt)
|
||||
|
||||
@@ -219,7 +219,7 @@ type ReadOnlySyncCommittee interface {
|
||||
|
||||
type ReadOnlyDeposits interface {
|
||||
DepositBalanceToConsume() (primitives.Gwei, error)
|
||||
DepositReceiptsStartIndex() (uint64, error)
|
||||
DepositRequestsStartIndex() (uint64, error)
|
||||
PendingBalanceDeposits() ([]*ethpb.PendingBalanceDeposit, error)
|
||||
}
|
||||
|
||||
@@ -327,7 +327,7 @@ type WriteOnlyConsolidations interface {
|
||||
|
||||
type WriteOnlyDeposits interface {
|
||||
AppendPendingBalanceDeposit(index primitives.ValidatorIndex, amount uint64) error
|
||||
SetDepositReceiptsStartIndex(index uint64) error
|
||||
SetDepositRequestsStartIndex(index uint64) error
|
||||
SetPendingBalanceDeposits(val []*ethpb.PendingBalanceDeposit) error
|
||||
SetDepositBalanceToConsume(primitives.Gwei) error
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ go_library(
|
||||
"getters_block.go",
|
||||
"getters_checkpoint.go",
|
||||
"getters_consolidation.go",
|
||||
"getters_deposit_receipts.go",
|
||||
"getters_deposit_requests.go",
|
||||
"getters_eth1.go",
|
||||
"getters_exit.go",
|
||||
"getters_misc.go",
|
||||
@@ -33,7 +33,7 @@ go_library(
|
||||
"setters_checkpoint.go",
|
||||
"setters_churn.go",
|
||||
"setters_consolidation.go",
|
||||
"setters_deposit_receipts.go",
|
||||
"setters_deposit_requests.go",
|
||||
"setters_eth1.go",
|
||||
"setters_misc.go",
|
||||
"setters_participation.go",
|
||||
@@ -94,7 +94,7 @@ go_test(
|
||||
"getters_block_test.go",
|
||||
"getters_checkpoint_test.go",
|
||||
"getters_consolidation_test.go",
|
||||
"getters_deposit_receipts_test.go",
|
||||
"getters_deposit_requests_test.go",
|
||||
"getters_exit_test.go",
|
||||
"getters_participation_test.go",
|
||||
"getters_test.go",
|
||||
@@ -109,7 +109,7 @@ go_test(
|
||||
"setters_balance_deposits_test.go",
|
||||
"setters_churn_test.go",
|
||||
"setters_consolidation_test.go",
|
||||
"setters_deposit_receipts_test.go",
|
||||
"setters_deposit_requests_test.go",
|
||||
"setters_eth1_test.go",
|
||||
"setters_misc_test.go",
|
||||
"setters_participation_test.go",
|
||||
|
||||
@@ -62,7 +62,7 @@ type BeaconState struct {
|
||||
nextWithdrawalValidatorIndex primitives.ValidatorIndex
|
||||
|
||||
// Electra fields
|
||||
depositReceiptsStartIndex uint64
|
||||
depositRequestsStartIndex uint64
|
||||
depositBalanceToConsume primitives.Gwei
|
||||
exitBalanceToConsume primitives.Gwei
|
||||
earliestExitEpoch primitives.Epoch
|
||||
@@ -119,7 +119,7 @@ type beaconStateMarshalable struct {
|
||||
LatestExecutionPayloadHeaderElectra *enginev1.ExecutionPayloadHeaderElectra `json:"latest_execution_payload_header_electra" yaml:"latest_execution_payload_header_electra"`
|
||||
NextWithdrawalIndex uint64 `json:"next_withdrawal_index" yaml:"next_withdrawal_index"`
|
||||
NextWithdrawalValidatorIndex primitives.ValidatorIndex `json:"next_withdrawal_validator_index" yaml:"next_withdrawal_validator_index"`
|
||||
DepositReceiptsStartIndex uint64 `json:"deposit_receipts_start_index" yaml:"deposit_receipts_start_index"`
|
||||
DepositRequestsStartIndex uint64 `json:"deposit_requests_start_index" yaml:"deposit_requests_start_index"`
|
||||
DepositBalanceToConsume primitives.Gwei `json:"deposit_balance_to_consume" yaml:"deposit_balance_to_consume"`
|
||||
ExitBalanceToConsume primitives.Gwei `json:"exit_balance_to_consume" yaml:"exit_balance_to_consume"`
|
||||
EarliestExitEpoch primitives.Epoch `json:"earliest_exit_epoch" yaml:"earliest_exit_epoch"`
|
||||
@@ -189,7 +189,7 @@ func (b *BeaconState) MarshalJSON() ([]byte, error) {
|
||||
LatestExecutionPayloadHeaderElectra: b.latestExecutionPayloadHeaderElectra,
|
||||
NextWithdrawalIndex: b.nextWithdrawalIndex,
|
||||
NextWithdrawalValidatorIndex: b.nextWithdrawalValidatorIndex,
|
||||
DepositReceiptsStartIndex: b.depositReceiptsStartIndex,
|
||||
DepositRequestsStartIndex: b.depositRequestsStartIndex,
|
||||
DepositBalanceToConsume: b.depositBalanceToConsume,
|
||||
ExitBalanceToConsume: b.exitBalanceToConsume,
|
||||
EarliestExitEpoch: b.earliestExitEpoch,
|
||||
|
||||
@@ -62,7 +62,7 @@ type BeaconState struct {
|
||||
nextWithdrawalValidatorIndex primitives.ValidatorIndex
|
||||
|
||||
// Electra fields
|
||||
depositReceiptsStartIndex uint64
|
||||
depositRequestsStartIndex uint64
|
||||
depositBalanceToConsume primitives.Gwei
|
||||
exitBalanceToConsume primitives.Gwei
|
||||
earliestExitEpoch primitives.Epoch
|
||||
@@ -119,7 +119,7 @@ type beaconStateMarshalable struct {
|
||||
LatestExecutionPayloadHeaderElectra *enginev1.ExecutionPayloadHeaderElectra `json:"latest_execution_payload_header_electra" yaml:"latest_execution_payload_header_electra"`
|
||||
NextWithdrawalIndex uint64 `json:"next_withdrawal_index" yaml:"next_withdrawal_index"`
|
||||
NextWithdrawalValidatorIndex primitives.ValidatorIndex `json:"next_withdrawal_validator_index" yaml:"next_withdrawal_validator_index"`
|
||||
DepositReceiptsStartIndex uint64 `json:"deposit_receipts_start_index" yaml:"deposit_receipts_start_index"`
|
||||
DepositRequestsStartIndex uint64 `json:"deposit_requests_start_index" yaml:"deposit_requests_start_index"`
|
||||
DepositBalanceToConsume primitives.Gwei `json:"deposit_balance_to_consume" yaml:"deposit_balance_to_consume"`
|
||||
ExitBalanceToConsume primitives.Gwei `json:"exit_balance_to_consume" yaml:"exit_balance_to_consume"`
|
||||
EarliestExitEpoch primitives.Epoch `json:"earliest_exit_epoch" yaml:"earliest_exit_epoch"`
|
||||
@@ -189,7 +189,7 @@ func (b *BeaconState) MarshalJSON() ([]byte, error) {
|
||||
LatestExecutionPayloadHeaderElectra: b.latestExecutionPayloadHeaderElectra,
|
||||
NextWithdrawalIndex: b.nextWithdrawalIndex,
|
||||
NextWithdrawalValidatorIndex: b.nextWithdrawalValidatorIndex,
|
||||
DepositReceiptsStartIndex: b.depositReceiptsStartIndex,
|
||||
DepositRequestsStartIndex: b.depositRequestsStartIndex,
|
||||
DepositBalanceToConsume: b.depositBalanceToConsume,
|
||||
ExitBalanceToConsume: b.exitBalanceToConsume,
|
||||
EarliestExitEpoch: b.earliestExitEpoch,
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
||||
)
|
||||
|
||||
// DepositReceiptsStartIndex is used for returning the deposit receipts start index which is used for eip6110
|
||||
func (b *BeaconState) DepositReceiptsStartIndex() (uint64, error) {
|
||||
if b.version < version.Electra {
|
||||
return 0, errNotSupported("DepositReceiptsStartIndex", b.version)
|
||||
}
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
return b.depositReceiptsStartIndex, nil
|
||||
}
|
||||
16
beacon-chain/state/state-native/getters_deposit_requests.go
Normal file
16
beacon-chain/state/state-native/getters_deposit_requests.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
||||
)
|
||||
|
||||
// DepositRequestsStartIndex is used for returning the deposit receipts start index which is used for eip6110
|
||||
func (b *BeaconState) DepositRequestsStartIndex() (uint64, error) {
|
||||
if b.version < version.Electra {
|
||||
return 0, errNotSupported("DepositRequestsStartIndex", b.version)
|
||||
}
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
return b.depositRequestsStartIndex, nil
|
||||
}
|
||||
@@ -9,17 +9,17 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/util"
|
||||
)
|
||||
|
||||
func TestDepositReceiptsStartIndex(t *testing.T) {
|
||||
func TestDepositRequestsStartIndex(t *testing.T) {
|
||||
t.Run("previous fork returns expected error", func(t *testing.T) {
|
||||
dState, _ := util.DeterministicGenesisState(t, 1)
|
||||
_, err := dState.DepositReceiptsStartIndex()
|
||||
_, err := dState.DepositRequestsStartIndex()
|
||||
require.ErrorContains(t, "is not supported", err)
|
||||
})
|
||||
t.Run("electra returns expected value", func(t *testing.T) {
|
||||
want := uint64(2)
|
||||
dState, err := state_native.InitializeFromProtoElectra(ðpb.BeaconStateElectra{DepositReceiptsStartIndex: want})
|
||||
dState, err := state_native.InitializeFromProtoElectra(ðpb.BeaconStateElectra{DepositRequestsStartIndex: want})
|
||||
require.NoError(t, err)
|
||||
got, err := dState.DepositReceiptsStartIndex()
|
||||
got, err := dState.DepositRequestsStartIndex()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, want, got)
|
||||
})
|
||||
@@ -202,7 +202,7 @@ func (b *BeaconState) ToProtoUnsafe() interface{} {
|
||||
NextWithdrawalIndex: b.nextWithdrawalIndex,
|
||||
NextWithdrawalValidatorIndex: b.nextWithdrawalValidatorIndex,
|
||||
HistoricalSummaries: b.historicalSummaries,
|
||||
DepositReceiptsStartIndex: b.depositReceiptsStartIndex,
|
||||
DepositRequestsStartIndex: b.depositRequestsStartIndex,
|
||||
DepositBalanceToConsume: b.depositBalanceToConsume,
|
||||
ExitBalanceToConsume: b.exitBalanceToConsume,
|
||||
EarliestExitEpoch: b.earliestExitEpoch,
|
||||
@@ -408,7 +408,7 @@ func (b *BeaconState) ToProto() interface{} {
|
||||
NextWithdrawalIndex: b.nextWithdrawalIndex,
|
||||
NextWithdrawalValidatorIndex: b.nextWithdrawalValidatorIndex,
|
||||
HistoricalSummaries: b.historicalSummariesVal(),
|
||||
DepositReceiptsStartIndex: b.depositReceiptsStartIndex,
|
||||
DepositRequestsStartIndex: b.depositRequestsStartIndex,
|
||||
DepositBalanceToConsume: b.depositBalanceToConsume,
|
||||
ExitBalanceToConsume: b.exitBalanceToConsume,
|
||||
EarliestExitEpoch: b.earliestExitEpoch,
|
||||
|
||||
@@ -158,7 +158,7 @@ func (b *BeaconState) ExpectedWithdrawals() ([]*enginev1.Withdrawal, uint64, err
|
||||
withdrawals = append(withdrawals, &enginev1.Withdrawal{
|
||||
Index: withdrawalIndex,
|
||||
ValidatorIndex: validatorIndex,
|
||||
Address: bytesutil.SafeCopyBytes(val.WithdrawalCredentials[ETH1AddressOffset:]),
|
||||
Address: bytesutil.SafeCopyBytes(val.GetWithdrawalCredentials()[ETH1AddressOffset:]),
|
||||
Amount: balance,
|
||||
})
|
||||
withdrawalIndex++
|
||||
@@ -166,7 +166,7 @@ func (b *BeaconState) ExpectedWithdrawals() ([]*enginev1.Withdrawal, uint64, err
|
||||
withdrawals = append(withdrawals, &enginev1.Withdrawal{
|
||||
Index: withdrawalIndex,
|
||||
ValidatorIndex: validatorIndex,
|
||||
Address: bytesutil.SafeCopyBytes(val.WithdrawalCredentials[ETH1AddressOffset:]),
|
||||
Address: bytesutil.SafeCopyBytes(val.GetWithdrawalCredentials()[ETH1AddressOffset:]),
|
||||
Amount: balance - helpers.ValidatorMaxEffectiveBalance(val),
|
||||
})
|
||||
withdrawalIndex++
|
||||
|
||||
@@ -281,9 +281,9 @@ func ComputeFieldRootsWithHasher(ctx context.Context, state *BeaconState) ([][]b
|
||||
}
|
||||
|
||||
if state.version >= version.Electra {
|
||||
// DepositReceiptsStartIndex root.
|
||||
drsiRoot := ssz.Uint64Root(state.depositReceiptsStartIndex)
|
||||
fieldRoots[types.DepositReceiptsStartIndex.RealPosition()] = drsiRoot[:]
|
||||
// DepositRequestsStartIndex root.
|
||||
drsiRoot := ssz.Uint64Root(state.depositRequestsStartIndex)
|
||||
fieldRoots[types.DepositRequestsStartIndex.RealPosition()] = drsiRoot[:]
|
||||
|
||||
// DepositBalanceToConsume root.
|
||||
dbtcRoot := ssz.Uint64Root(uint64(state.depositBalanceToConsume))
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native/types"
|
||||
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
||||
)
|
||||
|
||||
// SetDepositReceiptsStartIndex for the beacon state. Updates the DepositReceiptsStartIndex
|
||||
func (b *BeaconState) SetDepositReceiptsStartIndex(index uint64) error {
|
||||
if b.version < version.Electra {
|
||||
return errNotSupported("SetDepositReceiptsStartIndex", b.version)
|
||||
}
|
||||
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.depositReceiptsStartIndex = index
|
||||
b.markFieldAsDirty(types.DepositReceiptsStartIndex)
|
||||
b.rebuildTrie[types.DepositReceiptsStartIndex] = true
|
||||
return nil
|
||||
}
|
||||
21
beacon-chain/state/state-native/setters_deposit_requests.go
Normal file
21
beacon-chain/state/state-native/setters_deposit_requests.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native/types"
|
||||
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
||||
)
|
||||
|
||||
// SetDepositRequestsStartIndex for the beacon state. Updates the DepositRequestsStartIndex
|
||||
func (b *BeaconState) SetDepositRequestsStartIndex(index uint64) error {
|
||||
if b.version < version.Electra {
|
||||
return errNotSupported("SetDepositRequestsStartIndex", b.version)
|
||||
}
|
||||
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.depositRequestsStartIndex = index
|
||||
b.markFieldAsDirty(types.DepositRequestsStartIndex)
|
||||
b.rebuildTrie[types.DepositRequestsStartIndex] = true
|
||||
return nil
|
||||
}
|
||||
@@ -9,18 +9,18 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/util"
|
||||
)
|
||||
|
||||
func TestSetDepositReceiptsStartIndex(t *testing.T) {
|
||||
func TestSetDepositRequestsStartIndex(t *testing.T) {
|
||||
t.Run("previous fork returns expected error", func(t *testing.T) {
|
||||
dState, _ := util.DeterministicGenesisState(t, 1)
|
||||
require.ErrorContains(t, "is not supported", dState.SetDepositReceiptsStartIndex(1))
|
||||
require.ErrorContains(t, "is not supported", dState.SetDepositRequestsStartIndex(1))
|
||||
})
|
||||
t.Run("electra sets expected value", func(t *testing.T) {
|
||||
old := uint64(2)
|
||||
dState, err := state_native.InitializeFromProtoElectra(ðpb.BeaconStateElectra{DepositReceiptsStartIndex: old})
|
||||
dState, err := state_native.InitializeFromProtoElectra(ðpb.BeaconStateElectra{DepositRequestsStartIndex: old})
|
||||
require.NoError(t, err)
|
||||
want := uint64(3)
|
||||
require.NoError(t, dState.SetDepositReceiptsStartIndex(want))
|
||||
got, err := dState.DepositReceiptsStartIndex()
|
||||
require.NoError(t, dState.SetDepositRequestsStartIndex(want))
|
||||
got, err := dState.DepositRequestsStartIndex()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, want, got)
|
||||
})
|
||||
@@ -100,7 +100,7 @@ var electraFields = append(
|
||||
types.NextWithdrawalValidatorIndex,
|
||||
types.HistoricalSummaries,
|
||||
types.LatestExecutionPayloadHeaderElectra,
|
||||
types.DepositReceiptsStartIndex,
|
||||
types.DepositRequestsStartIndex,
|
||||
types.DepositBalanceToConsume,
|
||||
types.ExitBalanceToConsume,
|
||||
types.EarliestExitEpoch,
|
||||
@@ -744,7 +744,7 @@ func InitializeFromProtoUnsafeElectra(st *ethpb.BeaconStateElectra) (state.Beaco
|
||||
nextWithdrawalIndex: st.NextWithdrawalIndex,
|
||||
nextWithdrawalValidatorIndex: st.NextWithdrawalValidatorIndex,
|
||||
historicalSummaries: st.HistoricalSummaries,
|
||||
depositReceiptsStartIndex: st.DepositReceiptsStartIndex,
|
||||
depositRequestsStartIndex: st.DepositRequestsStartIndex,
|
||||
depositBalanceToConsume: st.DepositBalanceToConsume,
|
||||
exitBalanceToConsume: st.ExitBalanceToConsume,
|
||||
earliestExitEpoch: st.EarliestExitEpoch,
|
||||
@@ -862,7 +862,7 @@ func (b *BeaconState) Copy() state.BeaconState {
|
||||
eth1DepositIndex: b.eth1DepositIndex,
|
||||
nextWithdrawalIndex: b.nextWithdrawalIndex,
|
||||
nextWithdrawalValidatorIndex: b.nextWithdrawalValidatorIndex,
|
||||
depositReceiptsStartIndex: b.depositReceiptsStartIndex,
|
||||
depositRequestsStartIndex: b.depositRequestsStartIndex,
|
||||
depositBalanceToConsume: b.depositBalanceToConsume,
|
||||
exitBalanceToConsume: b.exitBalanceToConsume,
|
||||
earliestExitEpoch: b.earliestExitEpoch,
|
||||
@@ -1286,8 +1286,8 @@ func (b *BeaconState) rootSelector(ctx context.Context, field types.FieldIndex)
|
||||
return ssz.Uint64Root(uint64(b.nextWithdrawalValidatorIndex)), nil
|
||||
case types.HistoricalSummaries:
|
||||
return stateutil.HistoricalSummariesRoot(b.historicalSummaries)
|
||||
case types.DepositReceiptsStartIndex:
|
||||
return ssz.Uint64Root(b.depositReceiptsStartIndex), nil
|
||||
case types.DepositRequestsStartIndex:
|
||||
return ssz.Uint64Root(b.depositRequestsStartIndex), nil
|
||||
case types.DepositBalanceToConsume:
|
||||
return ssz.Uint64Root(uint64(b.depositBalanceToConsume)), nil
|
||||
case types.ExitBalanceToConsume:
|
||||
|
||||
@@ -96,8 +96,8 @@ func (f FieldIndex) String() string {
|
||||
return "nextWithdrawalValidatorIndex"
|
||||
case HistoricalSummaries:
|
||||
return "historicalSummaries"
|
||||
case DepositReceiptsStartIndex:
|
||||
return "depositReceiptsStartIndex"
|
||||
case DepositRequestsStartIndex:
|
||||
return "depositRequestsStartIndex"
|
||||
case DepositBalanceToConsume:
|
||||
return "depositBalanceToConsume"
|
||||
case ExitBalanceToConsume:
|
||||
@@ -179,7 +179,7 @@ func (f FieldIndex) RealPosition() int {
|
||||
return 26
|
||||
case HistoricalSummaries:
|
||||
return 27
|
||||
case DepositReceiptsStartIndex:
|
||||
case DepositRequestsStartIndex:
|
||||
return 28
|
||||
case DepositBalanceToConsume:
|
||||
return 29
|
||||
@@ -253,7 +253,7 @@ const (
|
||||
NextWithdrawalIndex
|
||||
NextWithdrawalValidatorIndex
|
||||
HistoricalSummaries
|
||||
DepositReceiptsStartIndex // Electra: EIP-6110
|
||||
DepositRequestsStartIndex // Electra: EIP-6110
|
||||
DepositBalanceToConsume // Electra: EIP-7251
|
||||
ExitBalanceToConsume // Electra: EIP-7251
|
||||
EarliestExitEpoch // Electra: EIP-7251
|
||||
|
||||
@@ -209,7 +209,7 @@ func ReplayProcessSlots(ctx context.Context, state state.BeaconState, slot primi
|
||||
return nil, errors.Wrap(err, "could not process epoch with optimizations")
|
||||
}
|
||||
} else {
|
||||
state, err = altair.ProcessEpoch(ctx, state)
|
||||
err = altair.ProcessEpoch(ctx, state)
|
||||
if err != nil {
|
||||
tracing.AnnotateError(span, err)
|
||||
return nil, errors.Wrap(err, "could not process epoch")
|
||||
|
||||
@@ -174,10 +174,10 @@ var (
|
||||
Usage: "The factor by which blob batch limit may increase on burst.",
|
||||
Value: 2,
|
||||
}
|
||||
// EnableDebugRPCEndpoints as /v1/beacon/state.
|
||||
EnableDebugRPCEndpoints = &cli.BoolFlag{
|
||||
Name: "enable-debug-rpc-endpoints",
|
||||
Usage: "Enables the debug rpc service, containing utility endpoints such as /eth/v1alpha1/beacon/state.",
|
||||
// DisableDebugRPCEndpoints disables the debug Beacon API namespace.
|
||||
DisableDebugRPCEndpoints = &cli.BoolFlag{
|
||||
Name: "disable-debug-rpc-endpoints",
|
||||
Usage: "Disables the debug Beacon API namespace.",
|
||||
}
|
||||
// SubscribeToAllSubnets defines a flag to specify whether to subscribe to all possible attestation/sync subnets or not.
|
||||
SubscribeToAllSubnets = &cli.BoolFlag{
|
||||
|
||||
@@ -64,7 +64,7 @@ var appFlags = []cli.Flag{
|
||||
flags.InteropNumValidatorsFlag,
|
||||
flags.InteropGenesisTimeFlag,
|
||||
flags.SlotsPerArchivedPoint,
|
||||
flags.EnableDebugRPCEndpoints,
|
||||
flags.DisableDebugRPCEndpoints,
|
||||
flags.SubscribeToAllSubnets,
|
||||
flags.HistoricalSlasherNode,
|
||||
flags.ChainID,
|
||||
|
||||
@@ -116,7 +116,7 @@ var appHelpFlagGroups = []flagGroup{
|
||||
flags.BlockBatchLimitBurstFactor,
|
||||
flags.BlobBatchLimit,
|
||||
flags.BlobBatchLimitBurstFactor,
|
||||
flags.EnableDebugRPCEndpoints,
|
||||
flags.DisableDebugRPCEndpoints,
|
||||
flags.SubscribeToAllSubnets,
|
||||
flags.HistoricalSlasherNode,
|
||||
flags.ChainID,
|
||||
|
||||
0
cmd/prysmctl/tosaccepted
Normal file
0
cmd/prysmctl/tosaccepted
Normal file
@@ -160,12 +160,12 @@ var Commands = []*cli.Command{
|
||||
flags.InteropStartIndex,
|
||||
cmd.GrpcMaxCallRecvMsgSizeFlag,
|
||||
flags.CertFlag,
|
||||
flags.GrpcHeadersFlag,
|
||||
flags.GrpcRetriesFlag,
|
||||
flags.GrpcRetryDelayFlag,
|
||||
flags.GRPCHeadersFlag,
|
||||
flags.GRPCRetriesFlag,
|
||||
flags.GRPCRetryDelayFlag,
|
||||
flags.ExitAllFlag,
|
||||
flags.ForceExitFlag,
|
||||
flags.VoluntaryExitJSONOutputPath,
|
||||
flags.VoluntaryExitJSONOutputPathFlag,
|
||||
features.Mainnet,
|
||||
features.SepoliaTestnet,
|
||||
features.HoleskyTestnet,
|
||||
|
||||
@@ -58,9 +58,9 @@ var Commands = &cli.Command{
|
||||
flags.BeaconRPCProviderFlag,
|
||||
cmd.GrpcMaxCallRecvMsgSizeFlag,
|
||||
flags.CertFlag,
|
||||
flags.GrpcHeadersFlag,
|
||||
flags.GrpcRetriesFlag,
|
||||
flags.GrpcRetryDelayFlag,
|
||||
flags.GRPCHeadersFlag,
|
||||
flags.GRPCRetriesFlag,
|
||||
flags.GRPCRetryDelayFlag,
|
||||
features.Mainnet,
|
||||
features.SepoliaTestnet,
|
||||
features.HoleskyTestnet,
|
||||
@@ -93,7 +93,7 @@ var Commands = &cli.Command{
|
||||
flags.WalletPasswordFileFlag,
|
||||
flags.BackupDirFlag,
|
||||
flags.BackupPublicKeysFlag,
|
||||
flags.BackupPasswordFile,
|
||||
flags.BackupPasswordFileFlag,
|
||||
features.Mainnet,
|
||||
features.SepoliaTestnet,
|
||||
features.HoleskyTestnet,
|
||||
@@ -160,12 +160,12 @@ var Commands = &cli.Command{
|
||||
flags.InteropStartIndex,
|
||||
cmd.GrpcMaxCallRecvMsgSizeFlag,
|
||||
flags.CertFlag,
|
||||
flags.GrpcHeadersFlag,
|
||||
flags.GrpcRetriesFlag,
|
||||
flags.GrpcRetryDelayFlag,
|
||||
flags.GRPCHeadersFlag,
|
||||
flags.GRPCRetriesFlag,
|
||||
flags.GRPCRetryDelayFlag,
|
||||
flags.ExitAllFlag,
|
||||
flags.ForceExitFlag,
|
||||
flags.VoluntaryExitJSONOutputPath,
|
||||
flags.VoluntaryExitJSONOutputPathFlag,
|
||||
features.Mainnet,
|
||||
features.SepoliaTestnet,
|
||||
features.HoleskyTestnet,
|
||||
|
||||
@@ -23,10 +23,10 @@ func accountsBackup(c *cli.Context) error {
|
||||
dialOpts := client.ConstructDialOptions(
|
||||
c.Int(cmd.GrpcMaxCallRecvMsgSizeFlag.Name),
|
||||
c.String(flags.CertFlag.Name),
|
||||
c.Uint(flags.GrpcRetriesFlag.Name),
|
||||
c.Duration(flags.GrpcRetryDelayFlag.Name),
|
||||
c.Uint(flags.GRPCRetriesFlag.Name),
|
||||
c.Duration(flags.GRPCRetryDelayFlag.Name),
|
||||
)
|
||||
grpcHeaders := strings.Split(c.String(flags.GrpcHeadersFlag.Name), ",")
|
||||
grpcHeaders := strings.Split(c.String(flags.GRPCHeadersFlag.Name), ",")
|
||||
|
||||
opts := []accounts.Option{
|
||||
accounts.WithWallet(w),
|
||||
@@ -62,7 +62,7 @@ func accountsBackup(c *cli.Context) error {
|
||||
// Ask the user for their desired password for their backed up accounts.
|
||||
backupsPassword, err := prompt.InputPassword(
|
||||
c,
|
||||
flags.BackupPasswordFile,
|
||||
flags.BackupPasswordFileFlag,
|
||||
"Enter a new password for your backed up accounts",
|
||||
"Confirm new password",
|
||||
true,
|
||||
|
||||
@@ -20,10 +20,10 @@ func accountsDelete(c *cli.Context) error {
|
||||
dialOpts := client.ConstructDialOptions(
|
||||
c.Int(cmd.GrpcMaxCallRecvMsgSizeFlag.Name),
|
||||
c.String(flags.CertFlag.Name),
|
||||
c.Uint(flags.GrpcRetriesFlag.Name),
|
||||
c.Duration(flags.GrpcRetryDelayFlag.Name),
|
||||
c.Uint(flags.GRPCRetriesFlag.Name),
|
||||
c.Duration(flags.GRPCRetryDelayFlag.Name),
|
||||
)
|
||||
grpcHeaders := strings.Split(c.String(flags.GrpcHeadersFlag.Name), ",")
|
||||
grpcHeaders := strings.Split(c.String(flags.GRPCHeadersFlag.Name), ",")
|
||||
|
||||
opts := []accounts.Option{
|
||||
accounts.WithWallet(w),
|
||||
|
||||
@@ -98,7 +98,7 @@ func setupWalletCtx(
|
||||
set.String(flags.DeletePublicKeysFlag.Name, cfg.deletePublicKeys, "")
|
||||
set.String(flags.VoluntaryExitPublicKeysFlag.Name, cfg.voluntaryExitPublicKeys, "")
|
||||
set.String(flags.BackupDirFlag.Name, cfg.backupDir, "")
|
||||
set.String(flags.BackupPasswordFile.Name, cfg.backupPasswordFile, "")
|
||||
set.String(flags.BackupPasswordFileFlag.Name, cfg.backupPasswordFile, "")
|
||||
set.String(flags.BackupPublicKeysFlag.Name, cfg.backupPublicKeys, "")
|
||||
set.String(flags.WalletPasswordFileFlag.Name, cfg.walletPasswordFile, "")
|
||||
set.String(flags.AccountPasswordFileFlag.Name, cfg.accountPasswordFile, "")
|
||||
@@ -106,7 +106,7 @@ func setupWalletCtx(
|
||||
set.Bool(flags.SkipDepositConfirmationFlag.Name, cfg.skipDepositConfirm, "")
|
||||
set.Bool(flags.SkipMnemonic25thWordCheckFlag.Name, true, "")
|
||||
set.Bool(flags.ExitAllFlag.Name, cfg.exitAll, "")
|
||||
set.String(flags.GrpcHeadersFlag.Name, cfg.grpcHeaders, "")
|
||||
set.String(flags.GRPCHeadersFlag.Name, cfg.grpcHeaders, "")
|
||||
|
||||
if cfg.privateKeyFile != "" {
|
||||
set.String(flags.ImportPrivateKeyFileFlag.Name, cfg.privateKeyFile, "")
|
||||
@@ -120,13 +120,13 @@ func setupWalletCtx(
|
||||
assert.NoError(tb, set.Set(flags.VoluntaryExitPublicKeysFlag.Name, cfg.voluntaryExitPublicKeys))
|
||||
assert.NoError(tb, set.Set(flags.BackupDirFlag.Name, cfg.backupDir))
|
||||
assert.NoError(tb, set.Set(flags.BackupPublicKeysFlag.Name, cfg.backupPublicKeys))
|
||||
assert.NoError(tb, set.Set(flags.BackupPasswordFile.Name, cfg.backupPasswordFile))
|
||||
assert.NoError(tb, set.Set(flags.BackupPasswordFileFlag.Name, cfg.backupPasswordFile))
|
||||
assert.NoError(tb, set.Set(flags.WalletPasswordFileFlag.Name, cfg.walletPasswordFile))
|
||||
assert.NoError(tb, set.Set(flags.AccountPasswordFileFlag.Name, cfg.accountPasswordFile))
|
||||
assert.NoError(tb, set.Set(flags.NumAccountsFlag.Name, strconv.Itoa(int(cfg.numAccounts))))
|
||||
assert.NoError(tb, set.Set(flags.SkipDepositConfirmationFlag.Name, strconv.FormatBool(cfg.skipDepositConfirm)))
|
||||
assert.NoError(tb, set.Set(flags.ExitAllFlag.Name, strconv.FormatBool(cfg.exitAll)))
|
||||
assert.NoError(tb, set.Set(flags.GrpcHeadersFlag.Name, cfg.grpcHeaders))
|
||||
assert.NoError(tb, set.Set(flags.GRPCHeadersFlag.Name, cfg.grpcHeaders))
|
||||
return cli.NewContext(&app, set, nil)
|
||||
}
|
||||
|
||||
|
||||
@@ -27,10 +27,10 @@ func Exit(c *cli.Context, r io.Reader) error {
|
||||
dialOpts := client.ConstructDialOptions(
|
||||
c.Int(cmd.GrpcMaxCallRecvMsgSizeFlag.Name),
|
||||
c.String(flags.CertFlag.Name),
|
||||
c.Uint(flags.GrpcRetriesFlag.Name),
|
||||
c.Duration(flags.GrpcRetryDelayFlag.Name),
|
||||
c.Uint(flags.GRPCRetriesFlag.Name),
|
||||
c.Duration(flags.GRPCRetryDelayFlag.Name),
|
||||
)
|
||||
grpcHeaders := strings.Split(c.String(flags.GrpcHeadersFlag.Name), ",")
|
||||
grpcHeaders := strings.Split(c.String(flags.GRPCHeadersFlag.Name), ",")
|
||||
beaconRPCProvider := c.String(flags.BeaconRPCProviderFlag.Name)
|
||||
if !c.IsSet(flags.Web3SignerURLFlag.Name) && !c.IsSet(flags.WalletDirFlag.Name) && !c.IsSet(flags.InteropNumValidators.Name) {
|
||||
return errors.Errorf("No validators found, please provide a prysm wallet directory via flag --%s "+
|
||||
@@ -83,7 +83,7 @@ func Exit(c *cli.Context, r io.Reader) error {
|
||||
accounts.WithBeaconRPCProvider(beaconRPCProvider),
|
||||
accounts.WithBeaconRESTApiProvider(c.String(flags.BeaconRESTApiProviderFlag.Name)),
|
||||
accounts.WithGRPCHeaders(grpcHeaders),
|
||||
accounts.WithExitJSONOutputPath(c.String(flags.VoluntaryExitJSONOutputPath.Name)),
|
||||
accounts.WithExitJSONOutputPath(c.String(flags.VoluntaryExitJSONOutputPathFlag.Name)),
|
||||
}
|
||||
// Get full set of public keys from the keymanager.
|
||||
validatingPublicKeys, err := km.FetchValidatingPublicKeys(c.Context)
|
||||
|
||||
@@ -37,7 +37,7 @@ func TestExitAccountsCli_OK(t *testing.T) {
|
||||
}
|
||||
|
||||
mockNodeClient.EXPECT().
|
||||
GetGenesis(gomock.Any(), gomock.Any()).
|
||||
Genesis(gomock.Any(), gomock.Any()).
|
||||
Return(ðpb.Genesis{GenesisTime: genesisTime}, nil)
|
||||
|
||||
mockValidatorClient.EXPECT().
|
||||
@@ -133,7 +133,7 @@ func TestExitAccountsCli_OK_AllPublicKeys(t *testing.T) {
|
||||
}
|
||||
|
||||
mockNodeClient.EXPECT().
|
||||
GetGenesis(gomock.Any(), gomock.Any()).
|
||||
Genesis(gomock.Any(), gomock.Any()).
|
||||
Return(ðpb.Genesis{GenesisTime: genesisTime}, nil)
|
||||
|
||||
mockValidatorClient.EXPECT().
|
||||
@@ -235,7 +235,7 @@ func TestExitAccountsCli_OK_ForceExit(t *testing.T) {
|
||||
}
|
||||
|
||||
mockNodeClient.EXPECT().
|
||||
GetGenesis(gomock.Any(), gomock.Any()).
|
||||
Genesis(gomock.Any(), gomock.Any()).
|
||||
Return(ðpb.Genesis{GenesisTime: genesisTime}, nil)
|
||||
|
||||
mockValidatorClient.EXPECT().
|
||||
@@ -324,7 +324,7 @@ func TestExitAccountsCli_WriteJSON_NoBroadcast(t *testing.T) {
|
||||
}
|
||||
|
||||
mockNodeClient.EXPECT().
|
||||
GetGenesis(gomock.Any(), gomock.Any()).
|
||||
Genesis(gomock.Any(), gomock.Any()).
|
||||
Return(ðpb.Genesis{GenesisTime: genesisTime}, nil)
|
||||
|
||||
mockValidatorClient.EXPECT().
|
||||
|
||||
@@ -27,10 +27,10 @@ func accountsImport(c *cli.Context) error {
|
||||
dialOpts := client.ConstructDialOptions(
|
||||
c.Int(cmd.GrpcMaxCallRecvMsgSizeFlag.Name),
|
||||
c.String(flags.CertFlag.Name),
|
||||
c.Uint(flags.GrpcRetriesFlag.Name),
|
||||
c.Duration(flags.GrpcRetryDelayFlag.Name),
|
||||
c.Uint(flags.GRPCRetriesFlag.Name),
|
||||
c.Duration(flags.GRPCRetryDelayFlag.Name),
|
||||
)
|
||||
grpcHeaders := strings.Split(c.String(flags.GrpcHeadersFlag.Name), ",")
|
||||
grpcHeaders := strings.Split(c.String(flags.GRPCHeadersFlag.Name), ",")
|
||||
|
||||
opts := []accounts.Option{
|
||||
accounts.WithWallet(w),
|
||||
|
||||
@@ -18,10 +18,10 @@ func accountsList(c *cli.Context) error {
|
||||
dialOpts := client.ConstructDialOptions(
|
||||
c.Int(cmd.GrpcMaxCallRecvMsgSizeFlag.Name),
|
||||
c.String(flags.CertFlag.Name),
|
||||
c.Uint(flags.GrpcRetriesFlag.Name),
|
||||
c.Duration(flags.GrpcRetryDelayFlag.Name),
|
||||
c.Uint(flags.GRPCRetriesFlag.Name),
|
||||
c.Duration(flags.GRPCRetryDelayFlag.Name),
|
||||
)
|
||||
grpcHeaders := strings.Split(c.String(flags.GrpcHeadersFlag.Name), ",")
|
||||
grpcHeaders := strings.Split(c.String(flags.GRPCHeadersFlag.Name), ",")
|
||||
|
||||
opts := []accounts.Option{
|
||||
accounts.WithWallet(w),
|
||||
|
||||
@@ -91,20 +91,20 @@ var (
|
||||
Name: "graffiti",
|
||||
Usage: "String to include in proposed blocks.",
|
||||
}
|
||||
// GrpcRetriesFlag defines the number of times to retry a failed gRPC request.
|
||||
GrpcRetriesFlag = &cli.UintFlag{
|
||||
// GRPCRetriesFlag defines the number of times to retry a failed gRPC request.
|
||||
GRPCRetriesFlag = &cli.UintFlag{
|
||||
Name: "grpc-retries",
|
||||
Usage: "Number of attempts to retry gRPC requests.",
|
||||
Value: 5,
|
||||
}
|
||||
// GrpcRetryDelayFlag defines the interval to retry a failed gRPC request.
|
||||
GrpcRetryDelayFlag = &cli.DurationFlag{
|
||||
// GRPCRetryDelayFlag defines the interval to retry a failed gRPC request.
|
||||
GRPCRetryDelayFlag = &cli.DurationFlag{
|
||||
Name: "grpc-retry-delay",
|
||||
Usage: "Amount of time between gRPC retry requests.",
|
||||
Value: 1 * time.Second,
|
||||
}
|
||||
// GrpcHeadersFlag defines a list of headers to send with all gRPC requests.
|
||||
GrpcHeadersFlag = &cli.StringFlag{
|
||||
// GRPCHeadersFlag defines a list of headers to send with all gRPC requests.
|
||||
GRPCHeadersFlag = &cli.StringFlag{
|
||||
Name: "grpc-headers",
|
||||
Usage: `Comma separated list of key value pairs to pass as gRPC headers for all gRPC calls.
|
||||
Example: --grpc-headers=key=value`,
|
||||
@@ -121,8 +121,8 @@ var (
|
||||
Usage: "Enables gRPC gateway for JSON requests.",
|
||||
Value: 7500,
|
||||
}
|
||||
// GPRCGatewayCorsDomain serves preflight requests when serving gRPC JSON gateway.
|
||||
GPRCGatewayCorsDomain = &cli.StringFlag{
|
||||
// GRPCGatewayCorsDomain serves preflight requests when serving gRPC JSON gateway.
|
||||
GRPCGatewayCorsDomain = &cli.StringFlag{
|
||||
Name: "grpc-gateway-corsdomain",
|
||||
Usage: `Comma separated list of domains from which to accept cross origin requests (browser enforced).
|
||||
This flag has no effect if not used with --grpc-gateway-port.
|
||||
@@ -142,7 +142,6 @@ var (
|
||||
Value: filepath.Join(filepath.Join(DefaultValidatorDir(), WalletDefaultDirName), api.AuthTokenFileName),
|
||||
Aliases: []string{"validator-api-bearer-file"},
|
||||
}
|
||||
|
||||
// WalletDirFlag defines the path to a wallet directory for Prysm accounts.
|
||||
WalletDirFlag = &cli.StringFlag{
|
||||
Name: "wallet-dir",
|
||||
@@ -184,7 +183,6 @@ var (
|
||||
Name: "mnemonic-language",
|
||||
Usage: "Allows specifying mnemonic language. Supported languages are: english|chinese_traditional|chinese_simplified|czech|french|japanese|korean|italian|spanish.",
|
||||
}
|
||||
|
||||
// ShowPrivateKeysFlag for accounts.
|
||||
ShowPrivateKeysFlag = &cli.BoolFlag{
|
||||
Name: "show-private-keys",
|
||||
@@ -236,14 +234,15 @@ var (
|
||||
Name: "force-exit",
|
||||
Usage: "Exits without displaying the confirmation prompt.",
|
||||
}
|
||||
VoluntaryExitJSONOutputPath = &cli.StringFlag{
|
||||
// VoluntaryExitJSONOutputPathFlag to write voluntary exits as JSON files instead of broadcasting them.
|
||||
VoluntaryExitJSONOutputPathFlag = &cli.StringFlag{
|
||||
Name: "exit-json-output-dir",
|
||||
Usage: "Output directory to write voluntary exits as individual unencrypted JSON " +
|
||||
"files. If this flag is provided, voluntary exits will be written to the provided " +
|
||||
"directory and will not be broadcasted.",
|
||||
}
|
||||
// BackupPasswordFile for encrypting accounts a user wishes to back up.
|
||||
BackupPasswordFile = &cli.StringFlag{
|
||||
// BackupPasswordFileFlag for encrypting accounts a user wishes to back up.
|
||||
BackupPasswordFileFlag = &cli.StringFlag{
|
||||
Name: "backup-password-file",
|
||||
Usage: "Path to a plain-text, .txt file containing the desired password for your backed up accounts.",
|
||||
Value: "",
|
||||
@@ -264,7 +263,6 @@ var (
|
||||
Name: "keys-dir",
|
||||
Usage: "Path to a directory where keystores to be imported are stored.",
|
||||
}
|
||||
|
||||
// RemoteSignerCertPathFlag defines the path to a client.crt file for a wallet to connect to
|
||||
// a secure signer via TLS and gRPC.
|
||||
RemoteSignerCertPathFlag = &cli.StringFlag{
|
||||
@@ -294,7 +292,6 @@ var (
|
||||
Usage: "URL for consensys' web3signer software to use with the Prysm validator client.",
|
||||
Value: "",
|
||||
}
|
||||
|
||||
// Web3SignerPublicValidatorKeysFlag defines a comma-separated list of hex string public keys or external url for web3signer to use for validator signing.
|
||||
// example with external url: --validators-external-signer-public-keys= https://web3signer.com/api/v1/eth2/publicKeys
|
||||
// example with public key: --validators-external-signer-public-keys=0xa99a...e44c,0xb89b...4a0b
|
||||
@@ -303,7 +300,6 @@ var (
|
||||
Name: "validators-external-signer-public-keys",
|
||||
Usage: "Comma separated list of public keys OR an external url endpoint for the validator to retrieve public keys from for usage with web3signer.",
|
||||
}
|
||||
|
||||
// KeymanagerKindFlag defines the kind of keymanager desired by a user during wallet creation.
|
||||
KeymanagerKindFlag = &cli.StringFlag{
|
||||
Name: "keymanager-kind",
|
||||
@@ -348,7 +344,6 @@ var (
|
||||
fee recipient and gas limit. File format found in docs`,
|
||||
Value: "",
|
||||
}
|
||||
|
||||
// SuggestedFeeRecipientFlag defines the address of the fee recipient.
|
||||
SuggestedFeeRecipientFlag = &cli.StringFlag{
|
||||
Name: "suggested-fee-recipient",
|
||||
@@ -358,7 +353,6 @@ var (
|
||||
--` + ProposerSettingsFlag.Name + " or --" + ProposerSettingsURLFlag.Name + " flags.",
|
||||
Value: params.BeaconConfig().EthBurnAddressHex,
|
||||
}
|
||||
|
||||
// EnableBuilderFlag enables the periodic validator registration API calls that will update the custom builder with validator settings.
|
||||
EnableBuilderFlag = &cli.BoolFlag{
|
||||
Name: "enable-builder",
|
||||
@@ -368,21 +362,18 @@ var (
|
||||
Value: false,
|
||||
Aliases: []string{"enable-validator-registration"},
|
||||
}
|
||||
|
||||
// BuilderGasLimitFlag defines the gas limit for the builder to use for constructing a payload.
|
||||
BuilderGasLimitFlag = &cli.StringFlag{
|
||||
Name: "suggested-gas-limit",
|
||||
Usage: "Sets gas limit for the builder to use for constructing a payload for all the validators.",
|
||||
Value: fmt.Sprint(params.BeaconConfig().DefaultBuilderGasLimit),
|
||||
}
|
||||
|
||||
// ValidatorsRegistrationBatchSizeFlag sets the maximum size for one batch of validator registrations. Use a non-positive value to disable batching.
|
||||
ValidatorsRegistrationBatchSizeFlag = &cli.IntFlag{
|
||||
Name: "validators-registration-batch-size",
|
||||
Usage: "Sets the maximum size for one batch of validator registrations. Use a non-positive value to disable batching.",
|
||||
Value: 0,
|
||||
}
|
||||
|
||||
// EnableDistributed enables the usage of prysm validator client in a Distributed Validator Cluster.
|
||||
EnableDistributed = &cli.BoolFlag{
|
||||
Name: "distributed",
|
||||
|
||||
@@ -62,10 +62,10 @@ var appFlags = []cli.Flag{
|
||||
flags.RPCPort,
|
||||
flags.GRPCGatewayPort,
|
||||
flags.GRPCGatewayHost,
|
||||
flags.GrpcRetriesFlag,
|
||||
flags.GrpcRetryDelayFlag,
|
||||
flags.GrpcHeadersFlag,
|
||||
flags.GPRCGatewayCorsDomain,
|
||||
flags.GRPCRetriesFlag,
|
||||
flags.GRPCRetryDelayFlag,
|
||||
flags.GRPCHeadersFlag,
|
||||
flags.GRPCGatewayCorsDomain,
|
||||
flags.DisableAccountMetricsFlag,
|
||||
flags.MonitoringPortFlag,
|
||||
flags.SlasherRPCProviderFlag,
|
||||
|
||||
@@ -56,6 +56,8 @@ var appHelpFlagGroups = []flagGroup{
|
||||
cmd.E2EConfigFlag,
|
||||
cmd.VerbosityFlag,
|
||||
cmd.DataDirFlag,
|
||||
flags.WalletDirFlag,
|
||||
flags.WalletPasswordFileFlag,
|
||||
cmd.ClearDB,
|
||||
cmd.ForceClearDB,
|
||||
cmd.EnableBackupWebhookFlag,
|
||||
@@ -90,38 +92,56 @@ var appHelpFlagGroups = []flagGroup{
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "validator",
|
||||
Name: "rpc",
|
||||
Flags: []cli.Flag{
|
||||
flags.CertFlag,
|
||||
flags.BeaconRPCProviderFlag,
|
||||
flags.BeaconRPCGatewayProviderFlag,
|
||||
flags.BeaconRESTApiProviderFlag,
|
||||
flags.CertFlag,
|
||||
flags.EnableWebFlag,
|
||||
flags.DisablePenaltyRewardLogFlag,
|
||||
flags.GraffitiFlag,
|
||||
flags.EnableRPCFlag,
|
||||
flags.RPCHost,
|
||||
flags.RPCPort,
|
||||
flags.GRPCGatewayPort,
|
||||
flags.GRPCGatewayHost,
|
||||
flags.GrpcRetriesFlag,
|
||||
flags.GrpcRetryDelayFlag,
|
||||
flags.GPRCGatewayCorsDomain,
|
||||
flags.GrpcHeadersFlag,
|
||||
flags.SlasherRPCProviderFlag,
|
||||
flags.SlasherCertFlag,
|
||||
flags.DisableAccountMetricsFlag,
|
||||
flags.WalletDirFlag,
|
||||
flags.WalletPasswordFileFlag,
|
||||
flags.GraffitiFileFlag,
|
||||
flags.Web3SignerURLFlag,
|
||||
flags.Web3SignerPublicValidatorKeysFlag,
|
||||
flags.GRPCRetriesFlag,
|
||||
flags.GRPCRetryDelayFlag,
|
||||
flags.GRPCGatewayCorsDomain,
|
||||
flags.GRPCHeadersFlag,
|
||||
flags.BeaconRESTApiProviderFlag,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "proposer",
|
||||
Flags: []cli.Flag{
|
||||
flags.ProposerSettingsFlag,
|
||||
flags.ProposerSettingsURLFlag,
|
||||
flags.SuggestedFeeRecipientFlag,
|
||||
flags.EnableBuilderFlag,
|
||||
flags.BuilderGasLimitFlag,
|
||||
flags.ValidatorsRegistrationBatchSizeFlag,
|
||||
flags.GraffitiFlag,
|
||||
flags.GraffitiFileFlag,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "remote signer",
|
||||
Flags: []cli.Flag{
|
||||
flags.Web3SignerURLFlag,
|
||||
flags.Web3SignerPublicValidatorKeysFlag,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "slasher",
|
||||
Flags: []cli.Flag{
|
||||
flags.SlasherRPCProviderFlag,
|
||||
flags.SlasherCertFlag,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "misc",
|
||||
Flags: []cli.Flag{
|
||||
flags.EnableWebFlag,
|
||||
flags.DisablePenaltyRewardLogFlag,
|
||||
flags.DisableAccountMetricsFlag,
|
||||
flags.EnableDistributed,
|
||||
flags.AuthTokenPathFlag,
|
||||
},
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
|
||||
func TestAllFlagsExistInHelp(t *testing.T) {
|
||||
// If this test is failing, it is because you've recently added/removed a
|
||||
// flag in beacon chain main.go, but did not add/remove it to the usage.go
|
||||
// flag in main.go, but did not add/remove it to the usage.go
|
||||
// flag grouping (appHelpFlagGroups).
|
||||
|
||||
var helpFlags []cli.Flag
|
||||
|
||||
@@ -68,7 +68,7 @@ func SetupWalletCtx(
|
||||
set.String(flags.DeletePublicKeysFlag.Name, cfg.deletePublicKeys, "")
|
||||
set.String(flags.VoluntaryExitPublicKeysFlag.Name, cfg.voluntaryExitPublicKeys, "")
|
||||
set.String(flags.BackupDirFlag.Name, cfg.backupDir, "")
|
||||
set.String(flags.BackupPasswordFile.Name, cfg.backupPasswordFile, "")
|
||||
set.String(flags.BackupPasswordFileFlag.Name, cfg.backupPasswordFile, "")
|
||||
set.String(flags.BackupPublicKeysFlag.Name, cfg.backupPublicKeys, "")
|
||||
set.String(flags.WalletPasswordFileFlag.Name, cfg.walletPasswordFile, "")
|
||||
set.String(flags.AccountPasswordFileFlag.Name, cfg.accountPasswordFile, "")
|
||||
@@ -76,7 +76,7 @@ func SetupWalletCtx(
|
||||
set.Bool(flags.SkipDepositConfirmationFlag.Name, cfg.skipDepositConfirm, "")
|
||||
set.Bool(flags.SkipMnemonic25thWordCheckFlag.Name, true, "")
|
||||
set.Bool(flags.ExitAllFlag.Name, cfg.exitAll, "")
|
||||
set.String(flags.GrpcHeadersFlag.Name, cfg.grpcHeaders, "")
|
||||
set.String(flags.GRPCHeadersFlag.Name, cfg.grpcHeaders, "")
|
||||
|
||||
if cfg.privateKeyFile != "" {
|
||||
set.String(flags.ImportPrivateKeyFileFlag.Name, cfg.privateKeyFile, "")
|
||||
@@ -90,13 +90,13 @@ func SetupWalletCtx(
|
||||
assert.NoError(tb, set.Set(flags.VoluntaryExitPublicKeysFlag.Name, cfg.voluntaryExitPublicKeys))
|
||||
assert.NoError(tb, set.Set(flags.BackupDirFlag.Name, cfg.backupDir))
|
||||
assert.NoError(tb, set.Set(flags.BackupPublicKeysFlag.Name, cfg.backupPublicKeys))
|
||||
assert.NoError(tb, set.Set(flags.BackupPasswordFile.Name, cfg.backupPasswordFile))
|
||||
assert.NoError(tb, set.Set(flags.BackupPasswordFileFlag.Name, cfg.backupPasswordFile))
|
||||
assert.NoError(tb, set.Set(flags.WalletPasswordFileFlag.Name, cfg.walletPasswordFile))
|
||||
assert.NoError(tb, set.Set(flags.AccountPasswordFileFlag.Name, cfg.accountPasswordFile))
|
||||
assert.NoError(tb, set.Set(flags.NumAccountsFlag.Name, strconv.Itoa(int(cfg.numAccounts))))
|
||||
assert.NoError(tb, set.Set(flags.SkipDepositConfirmationFlag.Name, strconv.FormatBool(cfg.skipDepositConfirm)))
|
||||
assert.NoError(tb, set.Set(flags.ExitAllFlag.Name, strconv.FormatBool(cfg.exitAll)))
|
||||
assert.NoError(tb, set.Set(flags.GrpcHeadersFlag.Name, cfg.grpcHeaders))
|
||||
assert.NoError(tb, set.Set(flags.GRPCHeadersFlag.Name, cfg.grpcHeaders))
|
||||
return cli.NewContext(&app, set, nil)
|
||||
}
|
||||
|
||||
|
||||
@@ -52,6 +52,11 @@ var (
|
||||
Usage: deprecatedUsage,
|
||||
Hidden: true,
|
||||
}
|
||||
deprecatedEnableDebugRPCEndpoints = &cli.BoolFlag{
|
||||
Name: "enable-debug-rpc-endpoints",
|
||||
Usage: deprecatedUsage,
|
||||
Hidden: true,
|
||||
}
|
||||
)
|
||||
|
||||
// Deprecated flags for both the beacon node and validator client.
|
||||
@@ -65,6 +70,7 @@ var deprecatedFlags = []cli.Flag{
|
||||
deprecatedEnableEIP4881,
|
||||
deprecatedDisableEIP4881,
|
||||
deprecatedVerboseSigVerification,
|
||||
deprecatedEnableDebugRPCEndpoints,
|
||||
}
|
||||
|
||||
// deprecatedBeaconFlags contains flags that are still used by other components
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user