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:
james-prysm
2023-02-24 10:28:32 -06:00
committed by GitHub
parent 0e4185b40c
commit 8918e8c274
3 changed files with 120 additions and 68 deletions

View File

@@ -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",
],

View File

@@ -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.

View File

@@ -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"