diff --git a/flags/eigendaflags/cli.go b/flags/eigendaflags/cli.go index ffa37089..8761ef65 100644 --- a/flags/eigendaflags/cli.go +++ b/flags/eigendaflags/cli.go @@ -231,6 +231,7 @@ func readPayloadClientConfig(ctx *cli.Context) v2_clients.PayloadClientConfig { return v2_clients.PayloadClientConfig{ // TODO: Support proper user env injection + BlockNumberPollInterval: 1 * time.Second, BlobEncodingVersion: codecs.DefaultBlobEncoding, EthRpcUrl: ctx.String(EthRPCURLFlagName), EigenDACertVerifierAddr: ctx.String(CertVerifierAddrName), @@ -243,6 +244,7 @@ func ReadV2DispersalConfig(ctx *cli.Context) v2_clients.PayloadDisperserConfig { payCfg := readPayloadClientConfig(ctx) return v2_clients.PayloadDisperserConfig{ + SignerPaymentKey: ctx.String(SignerPrivateKeyHexFlagName), PayloadClientConfig: payCfg, DisperseBlobTimeout: ctx.Duration(ResponseTimeoutFlagName), // TODO: Explore making these user defined diff --git a/go.mod b/go.mod index f92f138b..040def8a 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.22.0 toolchain go1.22.7 require ( - github.com/Layr-Labs/eigenda v0.8.6-rc.0.0.20250201021742-a13af0245831 + github.com/Layr-Labs/eigenda v0.8.6-rc.0.0.20250204212656-37a4d6de4778 github.com/Layr-Labs/eigenda-proxy/client v0.0.0-00010101000000-000000000000 github.com/Layr-Labs/eigensdk-go v0.2.0-beta.1.0.20250118004418-2a25f31b3b28 github.com/avast/retry-go/v4 v4.6.0 @@ -36,7 +36,6 @@ require ( github.com/BurntSushi/toml v1.4.0 // indirect github.com/DataDog/zstd v1.5.6-0.20230824185856-869dae002e5e // indirect github.com/Layr-Labs/cerberus-api v0.0.2-0.20250117193600-e69c5e8b08fd // indirect - github.com/Layr-Labs/eigensdk-go v0.2.0-beta.1.0.20250118004418-2a25f31b3b28 // indirect github.com/Layr-Labs/eigensdk-go/signer v0.0.0-20250118004418-2a25f31b3b28 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/VictoriaMetrics/fastcache v1.12.2 // indirect @@ -224,6 +223,7 @@ require ( github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 // indirect + github.com/pingcap/errors v0.11.4 // indirect github.com/pion/datachannel v1.5.8 // indirect github.com/pion/dtls/v2 v2.2.12 // indirect github.com/pion/ice/v2 v2.3.34 // indirect diff --git a/go.sum b/go.sum index bf28bc98..1f5a8a2c 100644 --- a/go.sum +++ b/go.sum @@ -26,6 +26,10 @@ github.com/Layr-Labs/cerberus-api v0.0.2-0.20250117193600-e69c5e8b08fd h1:prMzW4 github.com/Layr-Labs/cerberus-api v0.0.2-0.20250117193600-e69c5e8b08fd/go.mod h1:Lm4fhzy0S3P7GjerzuseGaBFVczsIKmEhIjcT52Hluo= github.com/Layr-Labs/eigenda v0.8.6-rc.0.0.20250201021742-a13af0245831 h1:hfH2DruVKRVEksM0cX6bHwvuNncB6iLXqTjUH3A4CcM= github.com/Layr-Labs/eigenda v0.8.6-rc.0.0.20250201021742-a13af0245831/go.mod h1:MO3EyBXCmhzttrmmgqmIkzDg4gtqWjU+0fxSN0Q1EmM= +github.com/Layr-Labs/eigenda v0.8.6-rc.0.0.20250204211032-a66068efa5e1 h1:q5ErO7WNQSODdEvhXuRULi8KYsvBrZBRvOHD/LmiSeA= +github.com/Layr-Labs/eigenda v0.8.6-rc.0.0.20250204211032-a66068efa5e1/go.mod h1:MO3EyBXCmhzttrmmgqmIkzDg4gtqWjU+0fxSN0Q1EmM= +github.com/Layr-Labs/eigenda v0.8.6-rc.0.0.20250204212656-37a4d6de4778 h1:fi8LQPfB+bs0cmPWANHktMpK1Sp2p3uvIKrmtgvtvic= +github.com/Layr-Labs/eigenda v0.8.6-rc.0.0.20250204212656-37a4d6de4778/go.mod h1:MO3EyBXCmhzttrmmgqmIkzDg4gtqWjU+0fxSN0Q1EmM= github.com/Layr-Labs/eigensdk-go v0.2.0-beta.1.0.20250118004418-2a25f31b3b28 h1:Wig5FBBizIB5Z/ZcXJlm7KdOLnrXc6E3DjO63uWRzQM= github.com/Layr-Labs/eigensdk-go v0.2.0-beta.1.0.20250118004418-2a25f31b3b28/go.mod h1:YNzORpoebdDNv0sJLm/H9LTx72M85zA54eBSXI5DULw= github.com/Layr-Labs/eigensdk-go/signer v0.0.0-20250118004418-2a25f31b3b28 h1:rhIC2XpFpCcRkv4QYczIUe/fXvE4T+0B1mF9f6NJCuo= diff --git a/store/generated_key/eigenda_v2/eigenda.go b/store/generated_key/eigenda_v2/eigenda.go index 06ccd49d..1ca53d27 100644 --- a/store/generated_key/eigenda_v2/eigenda.go +++ b/store/generated_key/eigenda_v2/eigenda.go @@ -6,6 +6,9 @@ import ( "time" "github.com/Layr-Labs/eigenda-proxy/common" + "github.com/avast/retry-go/v4" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" "github.com/Layr-Labs/eigenda/api/clients/v2" "github.com/Layr-Labs/eigenda/api/clients/v2/verification" @@ -56,7 +59,7 @@ func NewStore(log log.Logger, cfg *Config, ethClient eigenda_common.EthClient, // against commitment to ensure data is valid and non-tampered. func (e Store) Get(ctx context.Context, key []byte) ([]byte, error) { var cert verification.EigenDACert - err := rlp.DecodeBytes(key, cert) + err := rlp.DecodeBytes(key, &cert) if err != nil { return nil, fmt.Errorf("RLP decoding EigenDA v2 cert: %w", err) } @@ -74,57 +77,54 @@ func (e Store) Get(ctx context.Context, key []byte) ([]byte, error) { // // Mapping status codes to 503 failover func (e Store) Put(ctx context.Context, value []byte) ([]byte, error) { - // salt := 0 + salt := uint32(0) log.Info("Put EigenDA V2 backend") // TODO: Verify this retry or failover code for correctness against V2 // protocol - cert, err := e.disperser.SendPayload(ctx, value, 0) + + // We attempt to disperse the blob to EigenDA up to 3 times, unless we get a 400 error on any attempt. + cert, err := retry.DoWithData( + func() (*verification.EigenDACert, error) { + // TODO: Figure out salt mgmt + return e.disperser.SendPayload(ctx, value, salt) + }, + retry.RetryIf(func(err error) bool { + salt++ // increment salt before retrying + st, isGRPCError := status.FromError(err) + if !isGRPCError { + // api.ErrorFailover is returned, so we should retry + return true + } + //nolint:exhaustive // we only care about a few grpc error codes + switch st.Code() { + case codes.InvalidArgument: + // we don't retry 400 errors because there is no point, + // we are passing invalid data + return false + case codes.ResourceExhausted: + // we retry on 429s because *can* mean we are being rate limited + // we sleep 1 second... very arbitrarily, because we don't have more info. + // grpc error itself should return a backoff time, + // see https://github.com/Layr-Labs/eigenda/issues/845 for more details + time.Sleep(1 * time.Second) + return true + default: + return true + } + }), + // only return the last error. If it is an api.ErrorFailover, then the handler will convert + // it to an http 503 to signify to the client (batcher) to failover to ethda + // b/c eigenda is temporarily down. + retry.LastErrorOnly(true), + retry.Attempts(e.cfg.PutRetries), + ) if err != nil { + // TODO: we will want to filter for errors here and return a 503 when needed + // ie when dispersal itself failed, or that we timed out waiting for batch to land onchain return nil, err } - // We attempt to disperse the blob to EigenDA up to 3 times, unless we get a 400 error on any attempt. - // cert, err := retry.DoWithData( - // func() (*verification.EigenDACert, error) { - // // TODO: Figure out salt mgmt - // return e.disperser.SendPayload(ctx, value, 0) - // }, - // retry.RetryIf(func(err error) bool { - // st, isGRPCError := status.FromError(err) - // if !isGRPCError { - // // api.ErrorFailover is returned, so we should retry - // return true - // } - // //nolint:exhaustive // we only care about a few grpc error codes - // switch st.Code() { - // case codes.InvalidArgument: - // // we don't retry 400 errors because there is no point, - // // we are passing invalid data - // return false - // case codes.ResourceExhausted: - // // we retry on 429s because *can* mean we are being rate limited - // // we sleep 1 second... very arbitrarily, because we don't have more info. - // // grpc error itself should return a backoff time, - // // see https://github.com/Layr-Labs/eigenda/issues/845 for more details - // time.Sleep(1 * time.Second) - // return true - // default: - // return true - // } - // }), - // // only return the last error. If it is an api.ErrorFailover, then the handler will convert - // // it to an http 503 to signify to the client (batcher) to failover to ethda - // // b/c eigenda is temporarily down. - // retry.LastErrorOnly(true), - // retry.Attempts(e.cfg.PutRetries), - // ) - // if err != nil { - // // TODO: we will want to filter for errors here and return a 503 when needed - // // ie when dispersal itself failed, or that we timed out waiting for batch to land onchain - // return nil, err - // } - return rlp.EncodeToBytes(cert) } @@ -136,11 +136,12 @@ func (e Store) BackendType() common.BackendType { // Key is used to recover certificate fields and that verifies blob // against commitment to ensure data is valid and non-tampered. func (e Store) Verify(ctx context.Context, key []byte, value []byte) error { - var cert verification.EigenDACert - err := rlp.DecodeBytes(key, cert) - if err != nil { - return fmt.Errorf("RLP decoding EigenDA v2 cert: %w", err) - } + // var cert verification.EigenDACert + // err := rlp.DecodeBytes(key, cert) + // if err != nil { + // return fmt.Errorf("RLP decoding EigenDA v2 cert: %w", err) + // } - return e.verifier.VerifyCertV2(ctx, &cert) + // return e.verifier.VerifyCertV2(ctx, &cert) + return nil }