diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 53932810c..79dc356a8 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -34,6 +34,7 @@ import ( "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rpc" + eigenda_proxy "github.com/Layr-Labs/eigenda-proxy/client" "github.com/offchainlabs/nitro/arbnode/dataposter" "github.com/offchainlabs/nitro/arbnode/dataposter/storage" "github.com/offchainlabs/nitro/arbnode/redislock" @@ -1471,13 +1472,13 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error) } eigenDaBlobInfo, err = b.eigenDAWriter.Store(ctx, sequencerMsg) - if err != nil && errors.Is(err, eigenda.ErrServiceUnavailable) && b.config().EnableEigenDAFailover && b.dapWriter != nil { // Failover to anytrust commitee if enabled + if err != nil && errors.Is(err, eigenda_proxy.ErrServiceUnavailable) && b.config().EnableEigenDAFailover && b.dapWriter != nil { // Failover to anytrust commitee if enabled log.Error("EigenDA service is unavailable, failing over to any trust mode") b.building.useEigenDA = false failOver = true } - if err != nil && errors.Is(err, eigenda.ErrServiceUnavailable) && b.config().EnableEigenDAFailover && b.dapWriter == nil { // Failover to ETH DA if enabled + if err != nil && errors.Is(err, eigenda_proxy.ErrServiceUnavailable) && b.config().EnableEigenDAFailover && b.dapWriter == nil { // Failover to ETH DA if enabled // when failing over to ETHDA (i.e 4844, calldata), we may need to re-encode the batch. To do this in compliance with the existing code, it's easiest // to update an internal field and retrigger the poster's event loop. Since the batch poster can be distributed across mulitple nodes, there could be // degraded temporary performance as each batch poster will re-encode the batch on another event loop tick using the coordination lock which could worst case diff --git a/eigenda/proxy.go b/eigenda/proxy.go index 9c49edfd0..472f56cf5 100644 --- a/eigenda/proxy.go +++ b/eigenda/proxy.go @@ -1,26 +1,20 @@ package eigenda import ( - "bytes" "context" "fmt" - "io" - "net/http" + "github.com/Layr-Labs/eigenda-proxy/client" "github.com/Layr-Labs/eigenda/api/grpc/disperser" "github.com/ethereum/go-ethereum/rlp" ) -var ( - ErrServiceUnavailable = fmt.Errorf("eigenda service is unavailable") -) - type EigenDAProxyClient struct { client ProxyClient } func NewEigenDAProxyClient(rpcUrl string) *EigenDAProxyClient { - c := New(&Config{ + c := client.New(&client.Config{ URL: rpcUrl, }) return &EigenDAProxyClient{client: c} @@ -58,114 +52,9 @@ func (c *EigenDAProxyClient) Get(ctx context.Context, blobInfo *DisperserBlobInf return data, nil } -// TODO: Add support for custom http client option -type Config struct { - URL string -} - // ProxyClient is an interface for communicating with the EigenDA proxy server type ProxyClient interface { Health() error GetData(ctx context.Context, cert []byte) ([]byte, error) SetData(ctx context.Context, b []byte) ([]byte, error) } - -// client is the implementation of ProxyClient -type client struct { - cfg *Config - httpClient *http.Client -} - -var _ ProxyClient = (*client)(nil) - -func New(cfg *Config) ProxyClient { - return &client{ - cfg, - http.DefaultClient, - } -} - -// Health indicates if the server is operational; useful for event based awaits -// when integration testing -func (c *client) Health() error { - url := c.cfg.URL + "/health" - req, err := http.NewRequest(http.MethodGet, url, nil) - if err != nil { - return err - } - - resp, err := c.httpClient.Do(req) - if err != nil { - return err - } - - if resp.StatusCode != http.StatusOK { - return fmt.Errorf("received bad status code: %d", resp.StatusCode) - } - - return nil -} - -// GetData fetches blob data associated with a DA certificate -func (c *client) GetData(ctx context.Context, comm []byte) ([]byte, error) { - url := fmt.Sprintf("%s/get/0x%x?commitment_mode=simple", c.cfg.URL, comm) - - req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) - if err != nil { - return nil, fmt.Errorf("failed to construct http request: %w", err) - } - - req.Header.Set("Content-Type", "application/octet-stream") - resp, err := c.httpClient.Do(req) - if err != nil { - return nil, err - } - - defer resp.Body.Close() - - b, err := io.ReadAll(resp.Body) - if err != nil { - return nil, err - } - - if resp.StatusCode != http.StatusOK { - return nil, fmt.Errorf("received error response, code=%d, msg = %s", resp.StatusCode, string(b)) - } - - return b, nil -} - -// SetData writes raw byte data to DA and returns the associated certificate -// which should be verified within the proxy -func (c *client) SetData(ctx context.Context, b []byte) ([]byte, error) { - url := fmt.Sprintf("%s/put?commitment_mode=simple", c.cfg.URL) - req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewReader(b)) - if err != nil { - return nil, fmt.Errorf("failed to create HTTP request: %w", err) - } - req.Header.Set("Content-Type", "application/octet-stream") - resp, err := http.DefaultClient.Do(req) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - b, err = io.ReadAll(resp.Body) - if err != nil { - return nil, err - } - - if resp.StatusCode == http.StatusServiceUnavailable { - return nil, ErrServiceUnavailable - } - - if resp.StatusCode != http.StatusOK { - return nil, fmt.Errorf("failed to store data: %v, err = %s", resp.StatusCode, string(b)) - } - - if len(b) == 0 { - return nil, fmt.Errorf("read certificate is empty") - } - - return b, err -} diff --git a/eigenda/proxy_mock.go b/eigenda/proxy_mock.go index 544c219e8..7858783fc 100644 --- a/eigenda/proxy_mock.go +++ b/eigenda/proxy_mock.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" + "github.com/Layr-Labs/eigenda-proxy/client" "github.com/Layr-Labs/eigenda/api/grpc/disperser" ) @@ -92,7 +93,7 @@ func NewMockEigenDAProxyClient(shouldFail bool) *MockEigenDAProxyClient { func (c *MockEigenDAProxyClient) Put(ctx context.Context, data []byte) (*disperser.BlobInfo, error) { if c.client.(*MockProxyClient).ShouldFail { - return nil, ErrServiceUnavailable + return nil, client.ErrServiceUnavailable } return &mockBlobInfo, nil } @@ -103,7 +104,7 @@ func (c *MockEigenDAProxyClient) Get(ctx context.Context, blobInfo *disperser.Bl } if c.client.(*MockProxyClient).ShouldReturn503 { - return nil, ErrServiceUnavailable + return nil, client.ErrServiceUnavailable } return mockBlobData, nil diff --git a/go.mod b/go.mod index 804fb170b..9a2cd8a71 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/offchainlabs/nitro -go 1.21 +go 1.21.0 replace github.com/VictoriaMetrics/fastcache => ./fastcache @@ -58,6 +58,7 @@ require ( require github.com/google/go-querystring v1.1.0 // indirect require ( + github.com/Layr-Labs/eigenda-proxy/client v0.0.0-20241207145455-553417ea0500 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b // indirect google.golang.org/grpc v1.59.0 // indirect ) diff --git a/go.sum b/go.sum index 310b51376..eaba0f662 100644 --- a/go.sum +++ b/go.sum @@ -12,6 +12,8 @@ github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible h1 github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/Layr-Labs/eigenda v0.6.1 h1:uU04t+dsR5oHsbr+A5XIeJdyZIfNW3YvG03dMTKLSK4= github.com/Layr-Labs/eigenda v0.6.1/go.mod h1:XongI0xM6ks66DzxvTpF2yi4x2QH0X2RgEbKl/WFebY= +github.com/Layr-Labs/eigenda-proxy/client v0.0.0-20241207145455-553417ea0500 h1:3pescJNSxoEtCFZMQSprJPDJoE23Hw2xCCHywMVkO4w= +github.com/Layr-Labs/eigenda-proxy/client v0.0.0-20241207145455-553417ea0500/go.mod h1:U8iAmZIDzpuKD4yDVBIE4v4Oruyqj6IS0GjoNZI4hKU= github.com/Layr-Labs/eigenda/api v0.6.1 h1:TAstOttTmFZQoFlZtgu/rNktNOhx62TwRFMxGOhUx8M= github.com/Layr-Labs/eigenda/api v0.6.1/go.mod h1:kVXqWM13s/1hXyv9QdHweWAbKin9MeOBbS4i8c9rLbU= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=