mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-09 21:38:05 -05:00
prysmctl: check capella fork for blstoexecutionchange (#12039)
* adding in a check for current fork to disable submission prior * fixing linting * fixing error return * updating error contains in test * fixing unit test --------- Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
This commit is contained in:
@@ -16,6 +16,8 @@ go_library(
|
||||
"//cmd/validator/flags:go_default_library",
|
||||
"//config/features:go_default_library",
|
||||
"//config/fieldparams:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//runtime/tos:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common:go_default_library",
|
||||
"@com_github_logrusorgru_aurora//:go_default_library",
|
||||
@@ -33,8 +35,10 @@ go_test(
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//beacon-chain/rpc/apimiddleware:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//testing/assert:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
|
||||
"@com_github_sirupsen_logrus//hooks/test:go_default_library",
|
||||
"@com_github_urfave_cli_v2//:go_default_library",
|
||||
],
|
||||
|
||||
@@ -15,6 +15,8 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v3/api/client/beacon"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/rpc/apimiddleware"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v3/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/v3/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v3/encoding/bytesutil"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli/v2"
|
||||
"go.opencensus.io/trace"
|
||||
@@ -87,6 +89,13 @@ func callWithdrawalEndpoints(ctx context.Context, host string, request []*apimid
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fork, err := client.GetFork(ctx, "head")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not retrieve current fork information")
|
||||
}
|
||||
if !(params.BeaconConfig().ForkVersionSchedule[bytesutil.ToBytes4(fork.CurrentVersion)] >= params.BeaconConfig().CapellaForkEpoch) {
|
||||
return errors.New("setting withdrawals using the BLStoExecutionChange endpoint is only available after the Capella/Shanghai hard fork.")
|
||||
}
|
||||
err = client.SubmitChangeBLStoExecution(ctx, request)
|
||||
if err != nil && strings.Contains(err.Error(), "POST error") {
|
||||
// just log the error, so we can check the pool for partial inclusions.
|
||||
|
||||
@@ -3,6 +3,7 @@ package validator
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
@@ -10,33 +11,54 @@ import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/rpc/apimiddleware"
|
||||
"github.com/prysmaticlabs/prysm/v3/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/require"
|
||||
logtest "github.com/sirupsen/logrus/hooks/test"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func getHappyPathTestServer(file string, t *testing.T) *httptest.Server {
|
||||
return httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(200)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
if r.Method == http.MethodGet {
|
||||
fmt.Println(r.RequestURI)
|
||||
if r.RequestURI == "/eth/v1/beacon/pool/bls_to_execution_changes" {
|
||||
b, err := os.ReadFile(filepath.Clean(file))
|
||||
require.NoError(t, err)
|
||||
var to []*apimiddleware.SignedBLSToExecutionChangeJson
|
||||
err = json.Unmarshal(b, &to)
|
||||
require.NoError(t, err)
|
||||
err = json.NewEncoder(w).Encode(&apimiddleware.BLSToExecutionChangesPoolResponseJson{
|
||||
Data: to,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
} else if r.RequestURI == "/eth/v1/beacon/states/head/fork" {
|
||||
err := json.NewEncoder(w).Encode(&apimiddleware.StateForkResponseJson{
|
||||
Data: &apimiddleware.ForkJson{
|
||||
PreviousVersion: hexutil.Encode(params.BeaconConfig().CapellaForkVersion),
|
||||
CurrentVersion: hexutil.Encode(params.BeaconConfig().CapellaForkVersion),
|
||||
Epoch: fmt.Sprintf("%d", params.BeaconConfig().CapellaForkEpoch),
|
||||
},
|
||||
ExecutionOptimistic: false,
|
||||
Finalized: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
func TestCallWithdrawalEndpoint(t *testing.T) {
|
||||
file := "./testdata/change-operations.json"
|
||||
baseurl := "127.0.0.1:3500"
|
||||
l, err := net.Listen("tcp", baseurl)
|
||||
require.NoError(t, err)
|
||||
srv := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(200)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
if r.Method == http.MethodGet {
|
||||
b, err := os.ReadFile(filepath.Clean(file))
|
||||
require.NoError(t, err)
|
||||
var to []*apimiddleware.SignedBLSToExecutionChangeJson
|
||||
err = json.Unmarshal(b, &to)
|
||||
require.NoError(t, err)
|
||||
err = json.NewEncoder(w).Encode(&apimiddleware.BLSToExecutionChangesPoolResponseJson{
|
||||
Data: to,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
}))
|
||||
srv := getHappyPathTestServer(file, t)
|
||||
err = srv.Listener.Close()
|
||||
require.NoError(t, err)
|
||||
srv.Listener = l
|
||||
@@ -65,21 +87,7 @@ func TestCallWithdrawalEndpoint_Mutiple(t *testing.T) {
|
||||
baseurl := "127.0.0.1:3500"
|
||||
l, err := net.Listen("tcp", baseurl)
|
||||
require.NoError(t, err)
|
||||
srv := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(200)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
if r.Method == http.MethodGet {
|
||||
b, err := os.ReadFile(filepath.Clean(file))
|
||||
require.NoError(t, err)
|
||||
var to []*apimiddleware.SignedBLSToExecutionChangeJson
|
||||
err = json.Unmarshal(b, &to)
|
||||
require.NoError(t, err)
|
||||
err = json.NewEncoder(w).Encode(&apimiddleware.BLSToExecutionChangesPoolResponseJson{
|
||||
Data: to,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
}))
|
||||
srv := getHappyPathTestServer(file, t)
|
||||
err = srv.Listener.Close()
|
||||
require.NoError(t, err)
|
||||
srv.Listener = l
|
||||
@@ -111,21 +119,7 @@ func TestCallWithdrawalEndpoint_Mutiple_stakingcli(t *testing.T) {
|
||||
baseurl := "127.0.0.1:3500"
|
||||
l, err := net.Listen("tcp", baseurl)
|
||||
require.NoError(t, err)
|
||||
srv := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(200)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
if r.Method == http.MethodGet {
|
||||
b, err := os.ReadFile(filepath.Clean(file))
|
||||
require.NoError(t, err)
|
||||
var to []*apimiddleware.SignedBLSToExecutionChangeJson
|
||||
err = json.Unmarshal(b, &to)
|
||||
require.NoError(t, err)
|
||||
err = json.NewEncoder(w).Encode(&apimiddleware.BLSToExecutionChangesPoolResponseJson{
|
||||
Data: to,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
}))
|
||||
srv := getHappyPathTestServer(file, t)
|
||||
err = srv.Listener.Close()
|
||||
require.NoError(t, err)
|
||||
srv.Listener = l
|
||||
@@ -157,21 +151,7 @@ func TestCallWithdrawalEndpoint_Mutiple_notfound(t *testing.T) {
|
||||
baseurl := "127.0.0.1:3500"
|
||||
l, err := net.Listen("tcp", baseurl)
|
||||
require.NoError(t, err)
|
||||
srv := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(200)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
if r.Method == http.MethodGet {
|
||||
b, err := os.ReadFile(filepath.Clean(respFile))
|
||||
require.NoError(t, err)
|
||||
var to []*apimiddleware.SignedBLSToExecutionChangeJson
|
||||
err = json.Unmarshal(b, &to)
|
||||
require.NoError(t, err)
|
||||
err = json.NewEncoder(w).Encode(&apimiddleware.BLSToExecutionChangesPoolResponseJson{
|
||||
Data: to,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
}))
|
||||
srv := getHappyPathTestServer(respFile, t)
|
||||
err = srv.Listener.Close()
|
||||
require.NoError(t, err)
|
||||
srv.Listener = l
|
||||
@@ -228,14 +208,34 @@ func TestCallWithdrawalEndpoint_Errors(t *testing.T) {
|
||||
l, err := net.Listen("tcp", baseurl)
|
||||
require.NoError(t, err)
|
||||
srv := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(400)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
err = json.NewEncoder(w).Encode(&apimiddleware.IndexedVerificationFailureErrorJson{
|
||||
Failures: []*apimiddleware.SingleIndexedVerificationFailureJson{
|
||||
{Index: 0, Message: "Could not validate SignedBLSToExecutionChange"},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
if r.Method == http.MethodPost && r.RequestURI == "/eth/v1/beacon/pool/bls_to_execution_changes" {
|
||||
w.WriteHeader(400)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
err = json.NewEncoder(w).Encode(&apimiddleware.IndexedVerificationFailureErrorJson{
|
||||
Failures: []*apimiddleware.SingleIndexedVerificationFailureJson{
|
||||
{Index: 0, Message: "Could not validate SignedBLSToExecutionChange"},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
} else if r.Method == http.MethodGet {
|
||||
if r.RequestURI == "/eth/v1/beacon/states/head/fork" {
|
||||
w.WriteHeader(200)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
err := json.NewEncoder(w).Encode(&apimiddleware.StateForkResponseJson{
|
||||
Data: &apimiddleware.ForkJson{
|
||||
PreviousVersion: hexutil.Encode(params.BeaconConfig().CapellaForkVersion),
|
||||
CurrentVersion: hexutil.Encode(params.BeaconConfig().CapellaForkVersion),
|
||||
Epoch: fmt.Sprintf("%d", params.BeaconConfig().CapellaForkEpoch),
|
||||
},
|
||||
ExecutionOptimistic: false,
|
||||
Finalized: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
} else {
|
||||
w.WriteHeader(400)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
}
|
||||
}
|
||||
}))
|
||||
err = srv.Listener.Close()
|
||||
require.NoError(t, err)
|
||||
@@ -260,6 +260,45 @@ func TestCallWithdrawalEndpoint_Errors(t *testing.T) {
|
||||
assert.LogsContain(t, hook, "Could not validate SignedBLSToExecutionChange")
|
||||
}
|
||||
|
||||
func TestCallWithdrawalEndpoint_ForkBeforeCapella(t *testing.T) {
|
||||
file := "./testdata/change-operations.json"
|
||||
baseurl := "127.0.0.1:3500"
|
||||
l, err := net.Listen("tcp", baseurl)
|
||||
require.NoError(t, err)
|
||||
srv := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(200)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
err := json.NewEncoder(w).Encode(&apimiddleware.StateForkResponseJson{
|
||||
Data: &apimiddleware.ForkJson{
|
||||
PreviousVersion: hexutil.Encode(params.BeaconConfig().BellatrixForkVersion),
|
||||
CurrentVersion: hexutil.Encode(params.BeaconConfig().BellatrixForkVersion),
|
||||
Epoch: fmt.Sprintf("%d", params.BeaconConfig().BellatrixForkEpoch),
|
||||
},
|
||||
ExecutionOptimistic: false,
|
||||
Finalized: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
}))
|
||||
err = srv.Listener.Close()
|
||||
require.NoError(t, err)
|
||||
srv.Listener = l
|
||||
srv.Start()
|
||||
defer srv.Close()
|
||||
|
||||
app := cli.App{}
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.String("beacon-node-host", baseurl, "")
|
||||
set.String("path", file, "")
|
||||
set.Bool("confirm", true, "")
|
||||
set.Bool("accept-terms-of-use", true, "")
|
||||
assert.NoError(t, set.Set("beacon-node-host", baseurl))
|
||||
assert.NoError(t, set.Set("path", file))
|
||||
cliCtx := cli.NewContext(&app, set, nil)
|
||||
|
||||
err = setWithdrawalAddresses(cliCtx)
|
||||
require.ErrorContains(t, "setting withdrawals using the BLStoExecutionChange endpoint is only available after the Capella/Shanghai hard fork.", err)
|
||||
}
|
||||
|
||||
func TestVerifyWithdrawal_Mutiple(t *testing.T) {
|
||||
file := "./testdata/change-operations-multiple.json"
|
||||
baseurl := "127.0.0.1:3500"
|
||||
|
||||
Reference in New Issue
Block a user