mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
cmd,eth,beacon: accept custom http headers for beacon api
This commit is contained in:
parent
2333dcdb24
commit
70e2451c57
6 changed files with 50 additions and 17 deletions
|
|
@ -22,6 +22,7 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
eth2client "github.com/attestantio/go-eth2-client"
|
||||
eth2api "github.com/attestantio/go-eth2-client/api"
|
||||
|
|
@ -41,26 +42,40 @@ var (
|
|||
|
||||
// Client is a wrapper around the attestantio/go-eth2-client beacon api client.
|
||||
type Client struct {
|
||||
ctx context.Context
|
||||
url string
|
||||
client eth2client.Service
|
||||
ctx context.Context
|
||||
url string
|
||||
http *http.Client
|
||||
extraHeaders map[string]string
|
||||
client eth2client.Service
|
||||
}
|
||||
|
||||
// NewClient creates a Client for the given server URL.
|
||||
func NewClient(ctx context.Context, server string) (*Client, error) {
|
||||
func NewClient(ctx context.Context, server string, headers []string) (*Client, error) {
|
||||
// Parse additional headers.
|
||||
extraHeaders := make(map[string]string)
|
||||
for _, h := range headers {
|
||||
s := strings.Split(h, ":")
|
||||
if len(s) != 2 {
|
||||
return nil, fmt.Errorf("malformed extra header: %s", h)
|
||||
}
|
||||
extraHeaders[s[0]] = s[1]
|
||||
}
|
||||
client, err := eth2http.New(
|
||||
ctx,
|
||||
eth2http.WithAddress(server),
|
||||
eth2http.WithLogLevel(zerolog.WarnLevel),
|
||||
eth2http.WithEnforceJSON(true),
|
||||
eth2http.WithExtraHeaders(extraHeaders),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Client{
|
||||
ctx: ctx,
|
||||
url: server,
|
||||
client: client,
|
||||
ctx: ctx,
|
||||
url: server,
|
||||
http: &http.Client{},
|
||||
extraHeaders: extraHeaders,
|
||||
client: client,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
@ -68,7 +83,7 @@ func NewClient(ctx context.Context, server string) (*Client, error) {
|
|||
// the beacon server.
|
||||
func (c *Client) Bootstrap(root common.Hash) (*types.Bootstrap, error) {
|
||||
var bs types.Bootstrap
|
||||
if err := fetch(fmt.Sprintf("%s/%s/%s", c.url, beaconLightClientBootstrap, root.String()), &bs); err != nil {
|
||||
if err := c.fetch(fmt.Sprintf("%s/%s/%s", c.url, beaconLightClientBootstrap, root.String()), &bs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &bs, nil
|
||||
|
|
@ -78,7 +93,7 @@ func (c *Client) Bootstrap(root common.Hash) (*types.Bootstrap, error) {
|
|||
// include the next sync committee and finalized header from the period.
|
||||
func (c *Client) GetRangeUpdate(start, count int) ([]*types.LightClientUpdate, error) {
|
||||
var u []*types.LightClientUpdate
|
||||
if err := fetch(fmt.Sprintf("%s/%s?start_period=%d&count=%d", c.url, beaconLightClientUpdate, start, count), &u); err != nil {
|
||||
if err := c.fetch(fmt.Sprintf("%s/%s?start_period=%d&count=%d", c.url, beaconLightClientUpdate, start, count), &u); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return u, nil
|
||||
|
|
@ -89,7 +104,7 @@ func (c *Client) GetRangeUpdate(start, count int) ([]*types.LightClientUpdate, e
|
|||
// beacon api server.
|
||||
func (c *Client) GetOptimisticUpdate() (*types.LightClientUpdate, error) {
|
||||
var u types.LightClientUpdate
|
||||
if err := fetch(fmt.Sprintf("%s/%s", c.url, beaconLightClientOptimisticUpdate), &u); err != nil {
|
||||
if err := c.fetch(fmt.Sprintf("%s/%s", c.url, beaconLightClientOptimisticUpdate), &u); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &u, nil
|
||||
|
|
@ -99,7 +114,7 @@ func (c *Client) GetOptimisticUpdate() (*types.LightClientUpdate, error) {
|
|||
// beacon api server.
|
||||
func (c *Client) GetFinalityUpdate() (*types.LightClientUpdate, error) {
|
||||
var u types.LightClientUpdate
|
||||
if err := fetch(fmt.Sprintf("%s/%s", c.url, beaconLightClientFinalityUpdate), &u); err != nil {
|
||||
if err := c.fetch(fmt.Sprintf("%s/%s", c.url, beaconLightClientFinalityUpdate), &u); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &u, nil
|
||||
|
|
@ -118,11 +133,21 @@ func (c *Client) GetBlock(root common.Hash) (*eth2spec.VersionedSignedBeaconBloc
|
|||
return resp.Data, nil
|
||||
}
|
||||
|
||||
func fetch(url string, val any) error {
|
||||
resp, err := http.Get(url)
|
||||
func (c *Client) fetch(url string, val any) error {
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for k, v := range c.extraHeaders {
|
||||
req.Header.Set(k, v)
|
||||
}
|
||||
resp, err := c.http.Do(req)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed http request: %w", err)
|
||||
}
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return fmt.Errorf("failed http request: status %d", resp.StatusCode)
|
||||
}
|
||||
b, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read response: %w", err)
|
||||
|
|
|
|||
|
|
@ -45,8 +45,8 @@ type LightClient struct {
|
|||
|
||||
// Bootstrap retrieves a light client bootstrap and authenticates it against the
|
||||
// provided trusted root.
|
||||
func Bootstrap(ctx context.Context, server string, root common.Hash) (*LightClient, error) {
|
||||
api, err := beaclient.NewClient(ctx, server)
|
||||
func Bootstrap(server string, headers []string, root common.Hash) (*LightClient, error) {
|
||||
api, err := beaclient.NewClient(context.Background(), server, headers)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to connect to beacon server: %w", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -147,6 +147,7 @@ var (
|
|||
utils.LogDebugFlag,
|
||||
utils.LogBacktraceAtFlag,
|
||||
utils.BeaconAPIFlag,
|
||||
utils.BeaconAPIHeadersFlag,
|
||||
utils.BeaconTrustedBlockRootFlag,
|
||||
}, utils.NetworkFlags, utils.DatabaseFlags)
|
||||
|
||||
|
|
|
|||
|
|
@ -915,6 +915,11 @@ Please note that --` + MetricsHTTPFlag.Name + ` must be set to start the server.
|
|||
Usage: "server which provides the beacon light client apis",
|
||||
Category: flags.BeaconCategory,
|
||||
}
|
||||
BeaconAPIHeadersFlag = &cli.StringSliceFlag{
|
||||
Name: "beacon.api.headers",
|
||||
Usage: "headers to provide with each request",
|
||||
Category: flags.BeaconCategory,
|
||||
}
|
||||
BeaconTrustedBlockRootFlag = &cli.StringFlag{
|
||||
Name: "beacon.wss",
|
||||
Usage: "root of trusted block within the weak-subjectivity window",
|
||||
|
|
@ -1599,6 +1604,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
|||
// Avoid conflicting network flags
|
||||
CheckExclusive(ctx, MainnetFlag, DeveloperFlag, GoerliFlag, SepoliaFlag, HoleskyFlag)
|
||||
CheckExclusive(ctx, DeveloperFlag, ExternalSignerFlag) // Can't use both ephemeral unlocked and external signer
|
||||
CheckExclusive(ctx, DeveloperFlag, BeaconAPIFlag) // Can't use both simulated beacon and blsync
|
||||
|
||||
// Set configurations from CLI flags
|
||||
setEtherbase(ctx, cfg)
|
||||
|
|
@ -1859,6 +1865,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
|||
Fatalf("Must set both beacon api flag and beacon trusted block root flag to use beacon light client")
|
||||
}
|
||||
cfg.BeaconAPI = ctx.String(BeaconAPIFlag.Name)
|
||||
cfg.BeaconAPIHeaders = ctx.StringSlice(BeaconAPIHeadersFlag.Name)
|
||||
cfg.BeaconTrustedBlockRoot = ctx.String(BeaconTrustedBlockRootFlag.Name)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@
|
|||
package eth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
|
@ -277,7 +276,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
|
|||
}
|
||||
|
||||
if config.BeaconAPI != "" && config.BeaconTrustedBlockRoot != "" {
|
||||
beacon, err := light.Bootstrap(context.Background(), config.BeaconAPI, common.HexToHash(config.BeaconTrustedBlockRoot))
|
||||
beacon, err := light.Bootstrap(config.BeaconAPI, config.BeaconAPIHeaders, common.HexToHash(config.BeaconTrustedBlockRoot))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -115,6 +115,7 @@ type Config struct {
|
|||
|
||||
// Beacon light client options
|
||||
BeaconAPI string
|
||||
BeaconAPIHeaders []string
|
||||
BeaconTrustedBlockRoot string
|
||||
|
||||
// Database options
|
||||
|
|
|
|||
Loading…
Reference in a new issue