mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-24 20:37:17 +00:00
2e49fdb3d2
* WIP trying to start from bellatrix state * env var to control log path with unique paths due to flaky test re-run behavior, logs from a failed test run are overwritten by subsequent retries. This makes it difficult to retrieve logs after the first failed run. It also takes some squinting through output to find the location of the log file in the first place. This flag enables logs to be placed in an arbitrary path. Note that bazel sandboxing generally will force this path to be in the /tmp tree. * WIP - grabbing changes from rm-pre-genesis branch * combine bellatrix state w/ rm-pre-genesis branch * WIP * use encoding/detect for genesis state bytes * WIP more fixes towards start from bellatrix * remove debug wrapping * WIP * multiple bugfixes * fix fork ordering bug and bellatrix genesis blocks * send deposits, spam tx to advance, fix miner alloc * WIP * WIP mess * WIP * Print process ID information for purposes of attaching a debugger * bugs: genesis body_root and deposit index mismatch * fix voting period start, skip altair check * add changes * make it better * rm startup FCU, rm logs * cleanup import grouping&ordering * restore FCU log, get rid of tmp var * rm newline * restore newline * restore wrapped error * rm newline * removing boot node version override this doesn't seem to matter? * add issue number to todo comment * rm commented code * rm vmdebug geth flag * unexport values only used with genesis test pkg and add comments where missing from exported values. * adding comments to special cases for testnets * migrate comments from PR to actual code :) * rm unused test param * mark e2e spawns exempt from gosec warning * Fix DeepSource errors in `proposer_bellatrix.go` (#11739) * Fix DeepSource errors in * Omit receiver name * Address PR comments * Remove unused variable * Fix more DeepSource errors Co-authored-by: Radosław Kapka <rkapka@wp.pl> * Remove `Test_IsExecutionEnabledCapella` (#11752) Co-authored-by: Radosław Kapka <rkapka@wp.pl> * Add REST implementation for Validator's `ProposeBeaconBlock` (#11731) * WIP * WIP * WIP * Add tests * WIP * Add more tests * Address DeepSource errors * Remove unused param * Add more tests * Address PR comments * Address PR comments * Fix formatting * Remove unused parameter * Fix TestLittleEndianBytesToBigInt Co-authored-by: Radosław Kapka <rkapka@wp.pl> * fix validator client (#11755) * fix validator client (cherry picked from commit deb138959a2ffcb89cd2e3eb8304477526f4a168) * Use signed changes in middleware block Co-authored-by: Potuz <potuz@prysmaticlabs.com> * API `finalized` metadata field - update protos (#11749) * API `finalized` metadata field - update protos * change nums Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com> * log breaks unit tests that don't do full arg setup easiest to just remove it for now * restore prior behavior of phase0 block for altair * update unit tests to account for special case * loosen condition for fork version to match config we don't know which fork version genesis will start from, so we shouldn't force it to be a phase0 genesis. * skip until we can mod configs at runtime * NewGenesisBlockForState computes state root itself * rm noisy log * this log would be noisy in mainnet * fix format specifier, []byte -> string * core.Genesis UnmarshalJson has a value receiver :) * no longer needs to be exported Co-authored-by: Kasey Kirkham <kasey@users.noreply.github.com> Co-authored-by: prestonvanloon <preston@prysmaticlabs.com> Co-authored-by: nisdas <nishdas93@gmail.com> Co-authored-by: Patrice Vignola <vignola.patrice@gmail.com> Co-authored-by: Radosław Kapka <rkapka@wp.pl> Co-authored-by: terencechain <terence@prysmaticlabs.com> Co-authored-by: Potuz <potuz@prysmaticlabs.com> Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
163 lines
5.1 KiB
Go
163 lines
5.1 KiB
Go
package execution
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/url"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/ethereum/go-ethereum/ethclient"
|
|
gethRPC "github.com/ethereum/go-ethereum/rpc"
|
|
"github.com/pkg/errors"
|
|
"github.com/prysmaticlabs/prysm/v3/config/params"
|
|
contracts "github.com/prysmaticlabs/prysm/v3/contracts/deposit"
|
|
"github.com/prysmaticlabs/prysm/v3/io/logs"
|
|
"github.com/prysmaticlabs/prysm/v3/network"
|
|
"github.com/prysmaticlabs/prysm/v3/network/authorization"
|
|
)
|
|
|
|
func (s *Service) setupExecutionClientConnections(ctx context.Context, currEndpoint network.Endpoint) error {
|
|
client, err := s.newRPCClientWithAuth(ctx, currEndpoint)
|
|
if err != nil {
|
|
return errors.Wrap(err, "could not dial execution node")
|
|
}
|
|
// Attach the clients to the service struct.
|
|
fetcher := ethclient.NewClient(client)
|
|
s.rpcClient = client
|
|
s.httpLogger = fetcher
|
|
|
|
depositContractCaller, err := contracts.NewDepositContractCaller(s.cfg.depositContractAddr, fetcher)
|
|
if err != nil {
|
|
client.Close()
|
|
return errors.Wrap(err, "could not initialize deposit contract caller")
|
|
}
|
|
s.depositContractCaller = depositContractCaller
|
|
|
|
// Ensure we have the correct chain and deposit IDs.
|
|
if err := ensureCorrectExecutionChain(ctx, fetcher); err != nil {
|
|
client.Close()
|
|
errStr := err.Error()
|
|
if strings.Contains(errStr, "401 Unauthorized") {
|
|
errStr = "could not verify execution chain ID as your connection is not authenticated. " +
|
|
"If connecting to your execution client via HTTP, you will need to set up JWT authentication. " +
|
|
"See our documentation here https://docs.prylabs.network/docs/execution-node/authentication"
|
|
}
|
|
return errors.Wrap(err, errStr)
|
|
}
|
|
s.updateConnectedETH1(true)
|
|
s.runError = nil
|
|
return nil
|
|
}
|
|
|
|
// Every N seconds, defined as a backoffPeriod, attempts to re-establish an execution client
|
|
// connection and if this does not work, we fallback to the next endpoint if defined.
|
|
func (s *Service) pollConnectionStatus(ctx context.Context) {
|
|
// Use a custom logger to only log errors
|
|
logCounter := 0
|
|
errorLogger := func(err error, msg string) {
|
|
if logCounter > logThreshold {
|
|
log.WithError(err).Error(msg)
|
|
logCounter = 0
|
|
}
|
|
logCounter++
|
|
}
|
|
ticker := time.NewTicker(backOffPeriod)
|
|
defer ticker.Stop()
|
|
for {
|
|
select {
|
|
case <-ticker.C:
|
|
log.Debugf("Trying to dial endpoint: %s", logs.MaskCredentialsLogging(s.cfg.currHttpEndpoint.Url))
|
|
currClient := s.rpcClient
|
|
if err := s.setupExecutionClientConnections(ctx, s.cfg.currHttpEndpoint); err != nil {
|
|
errorLogger(err, "Could not connect to execution client endpoint")
|
|
continue
|
|
}
|
|
// Close previous client, if connection was successful.
|
|
if currClient != nil {
|
|
currClient.Close()
|
|
}
|
|
log.Infof("Connected to new endpoint: %s", logs.MaskCredentialsLogging(s.cfg.currHttpEndpoint.Url))
|
|
return
|
|
case <-s.ctx.Done():
|
|
log.Debug("Received cancelled context,closing existing powchain service")
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
// Forces to retry an execution client connection.
|
|
func (s *Service) retryExecutionClientConnection(ctx context.Context, err error) {
|
|
s.runError = errors.Wrap(err, "retryExecutionClientConnection")
|
|
s.updateConnectedETH1(false)
|
|
// Back off for a while before redialing.
|
|
time.Sleep(backOffPeriod)
|
|
currClient := s.rpcClient
|
|
if err := s.setupExecutionClientConnections(ctx, s.cfg.currHttpEndpoint); err != nil {
|
|
s.runError = errors.Wrap(err, "setupExecutionClientConnections")
|
|
return
|
|
}
|
|
// Close previous client, if connection was successful.
|
|
if currClient != nil {
|
|
currClient.Close()
|
|
}
|
|
// Reset run error in the event of a successful connection.
|
|
s.runError = nil
|
|
}
|
|
|
|
// Initializes an RPC connection with authentication headers.
|
|
func (s *Service) newRPCClientWithAuth(ctx context.Context, endpoint network.Endpoint) (*gethRPC.Client, error) {
|
|
// Need to handle ipc and http
|
|
var client *gethRPC.Client
|
|
u, err := url.Parse(endpoint.Url)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
switch u.Scheme {
|
|
case "http", "https":
|
|
client, err = gethRPC.DialHTTPWithClient(endpoint.Url, endpoint.HttpClient())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
case "", "ipc":
|
|
client, err = gethRPC.DialIPC(ctx, endpoint.Url)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
default:
|
|
return nil, fmt.Errorf("no known transport for URL scheme %q", u.Scheme)
|
|
}
|
|
if endpoint.Auth.Method != authorization.None {
|
|
header, err := endpoint.Auth.ToHeaderValue()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
client.SetHeader("Authorization", header)
|
|
}
|
|
for _, h := range s.cfg.headers {
|
|
if h != "" {
|
|
keyValue := strings.Split(h, "=")
|
|
if len(keyValue) < 2 {
|
|
log.Warnf("Incorrect HTTP header flag format. Skipping %v", keyValue[0])
|
|
continue
|
|
}
|
|
client.SetHeader(keyValue[0], strings.Join(keyValue[1:], "="))
|
|
}
|
|
}
|
|
return client, nil
|
|
}
|
|
|
|
// Checks the chain ID of the execution client to ensure
|
|
// it matches local parameters of what Prysm expects.
|
|
func ensureCorrectExecutionChain(ctx context.Context, client *ethclient.Client) error {
|
|
cID, err := client.ChainID(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
wantChainID := params.BeaconConfig().DepositChainID
|
|
if cID.Uint64() != wantChainID {
|
|
return fmt.Errorf("wanted chain ID %d, got %d", wantChainID, cID.Uint64())
|
|
}
|
|
return nil
|
|
}
|