Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix config checker logic #138

Merged
merged 7 commits into from
Sep 22, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ clean:
rm bin/eigenda-proxy

test:
go test -v ./... -parallel 4
go test ./... -parallel 4

e2e-test: stop-minio stop-redis run-minio run-redis
$(E2ETEST) && \
Expand Down
107 changes: 60 additions & 47 deletions server/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@ import (
const (
// eigenda client flags
EigenDADisperserRPCFlagName = "eigenda-disperser-rpc"
EthRPCFlagName = "eigenda-eth-rpc"
SvcManagerAddrFlagName = "eigenda-svc-manager-addr"
EthConfirmationDepthFlagName = "eigenda-eth-confirmation-depth"
StatusQueryRetryIntervalFlagName = "eigenda-status-query-retry-interval"
StatusQueryTimeoutFlagName = "eigenda-status-query-timeout"
DisableTLSFlagName = "eigenda-disable-tls"
Expand All @@ -29,6 +26,11 @@ const (
PutBlobEncodingVersionFlagName = "eigenda-put-blob-encoding-version"
DisablePointVerificationModeFlagName = "eigenda-disable-point-verification-mode"

CertVerificationEnabledFlagName = "eigenda-cert-verification-enabled"
EthRPCFlagName = "eigenda-eth-rpc"
SvcManagerAddrFlagName = "eigenda-svc-manager-addr"
EthConfirmationDepthFlagName = "eigenda-eth-confirmation-depth"

// kzg flags
G1PathFlagName = "eigenda-g1-path"
G2TauFlagName = "eigenda-g2-tau-path"
Expand Down Expand Up @@ -79,10 +81,13 @@ type Config struct {
// the blob encoding version to use when writing blobs from the high level interface.
PutBlobEncodingVersion codecs.BlobEncodingVersion

// eth vars
EthRPC string
SvcManagerAddr string
EthConfirmationDepth int64
// eth verification vars
// TODO: right now verification and confirmation depth are tightly coupled
// we should decouple them
CertVerificationEnabled bool
EthRPC string
SvcManagerAddr string
EthConfirmationDepth int64

// kzg vars
CacheDir string
Expand Down Expand Up @@ -143,18 +148,11 @@ func (cfg *Config) VerificationCfg() *verify.Config {
NumWorker: uint64(runtime.GOMAXPROCS(0)), // #nosec G115
}

if cfg.EthRPC == "" || cfg.SvcManagerAddr == "" {
return &verify.Config{
Verify: false,
KzgConfig: kzgCfg,
}
}

return &verify.Config{
Verify: true,
KzgConfig: kzgCfg,
VerifyCerts: cfg.CertVerificationEnabled,
RPCURL: cfg.EthRPC,
SvcManagerAddr: cfg.SvcManagerAddr,
KzgConfig: kzgCfg,
EthConfirmationDepth: uint64(cfg.EthConfirmationDepth), // #nosec G115
}
}
Expand Down Expand Up @@ -189,19 +187,20 @@ func ReadConfig(ctx *cli.Context) Config {
PutBlobEncodingVersion: codecs.BlobEncodingVersion(ctx.Uint(PutBlobEncodingVersionFlagName)),
DisablePointVerificationMode: ctx.Bool(DisablePointVerificationModeFlagName),
},
G1Path: ctx.String(G1PathFlagName),
G2PowerOfTauPath: ctx.String(G2TauFlagName),
CacheDir: ctx.String(CachePathFlagName),
MaxBlobLength: ctx.String(MaxBlobLengthFlagName),
SvcManagerAddr: ctx.String(SvcManagerAddrFlagName),
EthRPC: ctx.String(EthRPCFlagName),
EthConfirmationDepth: ctx.Int64(EthConfirmationDepthFlagName),
MemstoreEnabled: ctx.Bool(MemstoreFlagName),
MemstoreBlobExpiration: ctx.Duration(MemstoreExpirationFlagName),
MemstoreGetLatency: ctx.Duration(MemstoreGetLatencyFlagName),
MemstorePutLatency: ctx.Duration(MemstorePutLatencyFlagName),
FallbackTargets: ctx.StringSlice(FallbackTargets),
CacheTargets: ctx.StringSlice(CacheTargets),
G1Path: ctx.String(G1PathFlagName),
G2PowerOfTauPath: ctx.String(G2TauFlagName),
CacheDir: ctx.String(CachePathFlagName),
CertVerificationEnabled: ctx.Bool(CertVerificationEnabledFlagName),
MaxBlobLength: ctx.String(MaxBlobLengthFlagName),
SvcManagerAddr: ctx.String(SvcManagerAddrFlagName),
EthRPC: ctx.String(EthRPCFlagName),
EthConfirmationDepth: ctx.Int64(EthConfirmationDepthFlagName),
MemstoreEnabled: ctx.Bool(MemstoreFlagName),
MemstoreBlobExpiration: ctx.Duration(MemstoreExpirationFlagName),
MemstoreGetLatency: ctx.Duration(MemstoreGetLatencyFlagName),
MemstorePutLatency: ctx.Duration(MemstorePutLatencyFlagName),
FallbackTargets: ctx.StringSlice(FallbackTargets),
CacheTargets: ctx.StringSlice(CacheTargets),
}
// the eigenda client can only wait for 0 confirmations or finality
// the da-proxy has a more fine-grained notion of confirmation depth
Expand Down Expand Up @@ -246,16 +245,22 @@ func (cfg *Config) Check() error {
return fmt.Errorf("max blob length is 0")
}

if cfg.SvcManagerAddr != "" && cfg.EthRPC == "" {
return fmt.Errorf("svc manager address is set, but Eth RPC is not set")
}

if cfg.EthRPC != "" && cfg.SvcManagerAddr == "" {
return fmt.Errorf("eth rpc is set, but svc manager address is not set")
if !cfg.MemstoreEnabled {
if cfg.ClientConfig.RPC == "" {
return fmt.Errorf("using eigenda backend (memstore.enabled=false) but eigenda disperser rpc url is not set")
}
}

if cfg.EthConfirmationDepth >= 0 && (cfg.SvcManagerAddr == "" || cfg.EthRPC == "") {
return fmt.Errorf("eth confirmation depth is set for certificate verification, but Eth RPC or SvcManagerAddr is not set")
if cfg.CertVerificationEnabled {
if cfg.MemstoreEnabled {
return fmt.Errorf("cannot enable cert verification when memstore is enabled")
}
if cfg.EthRPC == "" {
return fmt.Errorf("cert verification enabled but eth rpc is not set")
}
if cfg.SvcManagerAddr == "" {
return fmt.Errorf("cert verification enabled but svc manager address is not set")
}
}

if cfg.S3Config.S3CredentialType == store.S3CredentialUnknown && cfg.S3Config.Endpoint != "" {
Expand All @@ -271,10 +276,6 @@ func (cfg *Config) Check() error {
return fmt.Errorf("redis password is set, but endpoint is not")
}

if !cfg.MemstoreEnabled && cfg.ClientConfig.RPC == "" {
return fmt.Errorf("eigenda disperser rpc url is not set")
}

err = cfg.checkTargets(cfg.FallbackTargets)
if err != nil {
return err
Expand Down Expand Up @@ -453,19 +454,31 @@ func CLIFlags() []cli.Flag {
EnvVars: prefixEnvVars("TARGET_CACHE_PATH"),
Value: "resources/SRSTables/",
},
&cli.BoolFlag{
Name: CertVerificationEnabledFlagName,
Usage: "Whether to verify certificates from EigenDA. If false, the DA-proxy will not verify certificates and will not require an Ethereum RPC endpoint.",
EnvVars: prefixEnvVars("CERT_VERIFICATION_ENABLED"),
// TODO: ideally we'd want this to be turned on by default when eigenda backend is used (memstore.enabled=false)
Value: false,
},
&cli.StringFlag{
Name: EthRPCFlagName,
Usage: "JSON RPC node endpoint for the Ethereum network used for finalizing DA blobs. See available list here: https://docs.eigenlayer.xyz/eigenda/networks/",
Name: EthRPCFlagName,
Usage: "JSON RPC node endpoint for the Ethereum network used for finalizing DA blobs.\n" +
"See available list here: https://docs.eigenlayer.xyz/eigenda/networks/\n" +
fmt.Sprintf("Mandatory when %s is true.", CertVerificationEnabledFlagName),
EnvVars: prefixEnvVars("ETH_RPC"),
},
&cli.StringFlag{
Name: SvcManagerAddrFlagName,
Usage: "The deployed EigenDA service manager address. The list can be found here: https://github.com/Layr-Labs/eigenlayer-middleware/?tab=readme-ov-file#current-mainnet-deployment",
Name: SvcManagerAddrFlagName,
Usage: "The deployed EigenDA service manager address.\n" +
"The list can be found here: https://github.com/Layr-Labs/eigenlayer-middleware/?tab=readme-ov-file#current-mainnet-deployment\n" +
fmt.Sprintf("Mandatory when %s is true.", CertVerificationEnabledFlagName),
EnvVars: prefixEnvVars("SERVICE_MANAGER_ADDR"),
},
&cli.Int64Flag{
Name: EthConfirmationDepthFlagName,
Usage: "The number of Ethereum blocks to wait before considering a submitted blob's DA batch submission confirmed. `0` means wait for inclusion only. `-1` means wait for finality.",
Name: EthConfirmationDepthFlagName,
Usage: "The number of Ethereum blocks to wait before considering a submitted blob's DA batch submission confirmed.\n" +
"`0` means wait for inclusion only. `-1` means wait for finality.",
EnvVars: prefixEnvVars("ETH_CONFIRMATION_DEPTH"),
Value: -1,
},
Expand Down
83 changes: 43 additions & 40 deletions server/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,16 @@ func validCfg() *Config {
PutBlobEncodingVersion: 0,
DisablePointVerificationMode: false,
},
G1Path: "path/to/g1",
G2PowerOfTauPath: "path/to/g2",
CacheDir: "path/to/cache",
MaxBlobLength: "2MiB",
SvcManagerAddr: "0x1234567890abcdef",
EthRPC: "http://localhost:8545",
EthConfirmationDepth: 12,
MemstoreEnabled: true,
MemstoreBlobExpiration: 25 * time.Minute,
G1Path: "path/to/g1",
G2PowerOfTauPath: "path/to/g2",
CacheDir: "path/to/cache",
MaxBlobLength: "2MiB",
CertVerificationEnabled: false,
SvcManagerAddr: "0x1234567890abcdef",
EthRPC: "http://localhost:8545",
EthConfirmationDepth: 12,
MemstoreEnabled: true,
MemstoreBlobExpiration: 25 * time.Minute,
}
}

Expand Down Expand Up @@ -71,37 +72,39 @@ func TestConfigVerification(t *testing.T) {
require.Error(t, err)
})

t.Run("MissingSvcManagerAddr", func(t *testing.T) {
cfg := validCfg()

cfg.EthRPC = "http://localhost:6969"
cfg.EthConfirmationDepth = 12
cfg.SvcManagerAddr = ""

err := cfg.Check()
require.Error(t, err)
})

t.Run("MissingCertVerificationParams", func(t *testing.T) {
cfg := validCfg()

cfg.EthConfirmationDepth = 12
cfg.SvcManagerAddr = ""
cfg.EthRPC = "http://localhost:6969"

err := cfg.Check()
require.Error(t, err)
})

t.Run("MissingEthRPC", func(t *testing.T) {
cfg := validCfg()

cfg.EthConfirmationDepth = 12
cfg.SvcManagerAddr = "0x00000000123"
cfg.EthRPC = ""

err := cfg.Check()
require.Error(t, err)
t.Run("CertVerificationEnabled", func(t *testing.T) {
// when eigenDABackend is enabled (memstore.enabled = false),
// some extra fields are required.
t.Run("MissingSvcManagerAddr", func(t *testing.T) {
cfg := validCfg()
// cert verification only makes sense when memstore is disabled (we use eigenda as backend)
cfg.MemstoreEnabled = false
cfg.CertVerificationEnabled = true
cfg.SvcManagerAddr = ""

err := cfg.Check()
require.Error(t, err)
})

t.Run("MissingEthRPC", func(t *testing.T) {
cfg := validCfg()
// cert verification only makes sense when memstore is disabled (we use eigenda as backend)
cfg.MemstoreEnabled = false
cfg.CertVerificationEnabled = true
cfg.EthRPC = ""

err := cfg.Check()
require.Error(t, err)
})

t.Run("CantDoCertVerificationWhenMemstoreEnabled", func(t *testing.T) {
cfg := validCfg()
cfg.MemstoreEnabled = true
cfg.CertVerificationEnabled = true

err := cfg.Check()
require.Error(t, err)
})
})

t.Run("MissingS3AccessKeys", func(t *testing.T) {
Expand Down
8 changes: 4 additions & 4 deletions server/load_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func LoadStoreRouter(ctx context.Context, cfg CLIConfig, log log.Logger) (store.
log.Info("Using S3 backend")
s3, err = store.NewS3(cfg.S3Config)
if err != nil {
return nil, err
return nil, fmt.Errorf("failed to create S3 store: %w", err)
}
}

Expand All @@ -58,7 +58,7 @@ func LoadStoreRouter(ctx context.Context, cfg CLIConfig, log log.Logger) (store.
// create Redis backend store
redis, err = store.NewRedisStore(&cfg.RedisCfg)
if err != nil {
return nil, err
return nil, fmt.Errorf("failed to create Redis store: %w", err)
}
}

Expand All @@ -68,10 +68,10 @@ func LoadStoreRouter(ctx context.Context, cfg CLIConfig, log log.Logger) (store.

verifier, err := verify.NewVerifier(vCfg, log)
if err != nil {
return nil, err
return nil, fmt.Errorf("failed to create verifier: %w", err)
}

if vCfg.Verify {
if vCfg.VerifyCerts {
log.Info("Certificate verification with Ethereum enabled")
} else {
log.Warn("Verification disabled")
Expand Down
2 changes: 1 addition & 1 deletion store/memory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func getDefaultMemStoreTestConfig() MemStoreConfig {

func getDefaultVerifierTestConfig() *verify.Config {
return &verify.Config{
Verify: false,
VerifyCerts: false,
KzgConfig: &kzg.KzgConfig{
G1Path: "../resources/g1.point",
G2PowerOf2Path: "../resources/g2.point.powerOf2",
Expand Down
19 changes: 11 additions & 8 deletions verify/verifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,45 +17,48 @@ import (
)

type Config struct {
Verify bool
KzgConfig *kzg.KzgConfig
VerifyCerts bool
// below 3 fields are only required if VerifyCerts is true
RPCURL string
SvcManagerAddr string
KzgConfig *kzg.KzgConfig
EthConfirmationDepth uint64
}

type Verifier struct {
verifyCert bool
// kzgVerifier is needed to commit blobs to the memstore
kzgVerifier *kzgverifier.Verifier
// cert verification is optional, and verifies certs retrieved from eigenDA when turned on
verifyCerts bool
cv *CertVerifier
}

func NewVerifier(cfg *Config, l log.Logger) (*Verifier, error) {
var cv *CertVerifier
var err error

if cfg.Verify {
if cfg.VerifyCerts {
cv, err = NewCertVerifier(cfg, l)
if err != nil {
return nil, err
return nil, fmt.Errorf("failed to create cert verifier: %w", err)
}
}

kzgVerifier, err := kzgverifier.NewVerifier(cfg.KzgConfig, false)
if err != nil {
return nil, err
return nil, fmt.Errorf("failed to create kzg verifier: %w", err)
}

return &Verifier{
verifyCert: cfg.Verify,
kzgVerifier: kzgVerifier,
verifyCerts: cfg.VerifyCerts,
cv: cv,
}, nil
}

// verifies V0 eigenda certificate type
func (v *Verifier) VerifyCert(cert *Certificate) error {
if !v.verifyCert {
if !v.verifyCerts {
return nil
}

Expand Down
8 changes: 4 additions & 4 deletions verify/verify_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ func TestCommitmentVerification(t *testing.T) {
}

cfg := &Config{
Verify: false,
KzgConfig: kzgConfig,
VerifyCerts: false,
KzgConfig: kzgConfig,
}

v, err := NewVerifier(cfg, nil)
Expand Down Expand Up @@ -78,8 +78,8 @@ func TestCommitmentWithTooLargeBlob(t *testing.T) {
}

cfg := &Config{
Verify: false,
KzgConfig: kzgConfig,
VerifyCerts: false,
KzgConfig: kzgConfig,
}

v, err := NewVerifier(cfg, nil)
Expand Down
Loading