From 2c7e31fb4d801662ce1edf79f92b9f964507a3ae Mon Sep 17 00:00:00 2001 From: hopeyen Date: Fri, 13 Sep 2024 16:50:53 -0500 Subject: [PATCH 1/3] feat: generate a random private key if not provided --- e2e/setup.go | 10 ++++++++-- server/config.go | 25 ++++++++++++++++++------- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/e2e/setup.go b/e2e/setup.go index 3eea3f0..cb1d0ff 100644 --- a/e2e/setup.go +++ b/e2e/setup.go @@ -2,6 +2,7 @@ package e2e import ( "context" + "encoding/hex" "fmt" "os" "testing" @@ -93,10 +94,15 @@ type TestSuite struct { func CreateTestSuite(t *testing.T, testCfg *Cfg) (TestSuite, func()) { ctx := context.Background() - // load signer key from environment + // load signer key from environment or generate a random one pk := os.Getenv(privateKey) if pk == "" && !testCfg.UseMemory { - t.Fatal("SIGNER_PRIVATE_KEY environment variable not set") + t.Logf("SIGNER_PRIVATE_KEY environment variable not set. Generated random private key") + randomBytes := make([]byte, 32) + if _, err := rand.Read(randomBytes); err != nil { + t.Fatalf("Failed to generate random private key: %v", err) + } + pk = hex.EncodeToString(randomBytes) } // load node url from environment diff --git a/server/config.go b/server/config.go index 2f0afc3..dd35ce9 100644 --- a/server/config.go +++ b/server/config.go @@ -1,6 +1,8 @@ package server import ( + "crypto/rand" + "encoding/hex" "fmt" "runtime" "time" @@ -179,13 +181,22 @@ func ReadConfig(ctx *cli.Context) Config { Timeout: ctx.Duration(S3TimeoutFlagName), }, ClientConfig: clients.EigenDAClientConfig{ - RPC: ctx.String(EigenDADisperserRPCFlagName), - StatusQueryRetryInterval: ctx.Duration(StatusQueryRetryIntervalFlagName), - StatusQueryTimeout: ctx.Duration(StatusQueryTimeoutFlagName), - DisableTLS: ctx.Bool(DisableTLSFlagName), - ResponseTimeout: ctx.Duration(ResponseTimeoutFlagName), - CustomQuorumIDs: ctx.UintSlice(CustomQuorumIDsFlagName), - SignerPrivateKeyHex: ctx.String(SignerPrivateKeyHexFlagName), + RPC: ctx.String(EigenDADisperserRPCFlagName), + StatusQueryRetryInterval: ctx.Duration(StatusQueryRetryIntervalFlagName), + StatusQueryTimeout: ctx.Duration(StatusQueryTimeoutFlagName), + DisableTLS: ctx.Bool(DisableTLSFlagName), + ResponseTimeout: ctx.Duration(ResponseTimeoutFlagName), + CustomQuorumIDs: ctx.UintSlice(CustomQuorumIDsFlagName), + SignerPrivateKeyHex: func() string { + if key := ctx.String(SignerPrivateKeyHexFlagName); key != "" { + return key + } + randomBytes := make([]byte, 32) + if _, err := rand.Read(randomBytes); err != nil { + panic(fmt.Errorf("failed to generate random private key: %w", err)) + } + return hex.EncodeToString(randomBytes) + }(), PutBlobEncodingVersion: codecs.BlobEncodingVersion(ctx.Uint(PutBlobEncodingVersionFlagName)), DisablePointVerificationMode: ctx.Bool(DisablePointVerificationModeFlagName), }, From d124ef8bd80eb97f4feadd6901cc3947d6350874 Mon Sep 17 00:00:00 2001 From: hopeyen Date: Fri, 13 Sep 2024 23:34:51 -0500 Subject: [PATCH 2/3] feat: read-only mode --- .env.example.holesky | 3 +++ .env.example.mainnet | 5 ++++- Makefile | 6 ++++++ server/config.go | 9 +++++++++ server/load_store.go | 2 +- store/router.go | 14 ++++++++++---- 6 files changed, 33 insertions(+), 6 deletions(-) diff --git a/.env.example.holesky b/.env.example.holesky index 26fa3a0..09cd14f 100644 --- a/.env.example.holesky +++ b/.env.example.holesky @@ -87,3 +87,6 @@ EIGENDA_PROXY_SERVICE_MANAGER_ADDR=0xD4A7E1Bd8015057293f0D0A557088c286942e84b # endpoint for S3 storage # EIGENDA_PROXY_S3_ENDPOINT + +# set to true to disable writing to EigenDA +# EIGENDA_PROXY_READ_ONLY=false diff --git a/.env.example.mainnet b/.env.example.mainnet index 1dba80d..f087678 100644 --- a/.env.example.mainnet +++ b/.env.example.mainnet @@ -85,4 +85,7 @@ EIGENDA_PROXY_SERVICE_MANAGER_ADDR=0x870679E138bCdf293b7Ff14dD44b70FC97e12fc0 # EIGENDA_PROXY_S3_BUCKET= # endpoint for S3 storage -# EIGENDA_PROXY_S3_ENDPOINT \ No newline at end of file +# EIGENDA_PROXY_S3_ENDPOINT + +# set to true to disable writing to EigenDA +# EIGENDA_PROXY_READ_ONLY=false diff --git a/Makefile b/Makefile index 8dbd5b0..cafb47c 100644 --- a/Makefile +++ b/Makefile @@ -19,6 +19,12 @@ HOLESKYTEST = TESTNET=true go test -timeout 50m -v ./e2e -parallel 4 -deploy-co eigenda-proxy: env GO111MODULE=on GOOS=$(TARGETOS) GOARCH=$(TARGETARCH) go build -v $(LDFLAGS) -o ./bin/eigenda-proxy ./cmd/server +.PHONY: eigenda-proxy-codesign +proxy-build-sign-run: + env GO111MODULE=on GOOS=$(TARGETOS) GOARCH=$(TARGETARCH) go build -v $(LDFLAGS) -o ./bin/eigenda-proxy ./cmd/server + codesign --sign - --force --preserve-metadata=entitlements,requirements,flags,runtime ./bin/eigenda-proxy + ENV_PATH=.env ./bin/eigenda-proxy --addr 127.0.0.1 --port 3100 + .PHONY: docker-build docker-build: @docker build -t $(IMAGE_NAME) . diff --git a/server/config.go b/server/config.go index dd35ce9..693bbfd 100644 --- a/server/config.go +++ b/server/config.go @@ -30,6 +30,7 @@ const ( SignerPrivateKeyHexFlagName = "eigenda-signer-private-key-hex" PutBlobEncodingVersionFlagName = "eigenda-put-blob-encoding-version" DisablePointVerificationModeFlagName = "eigenda-disable-point-verification-mode" + ReadOnlyFlagName = "read-only" // kzg flags G1PathFlagName = "eigenda-g1-path" @@ -77,6 +78,7 @@ var ( type Config struct { // eigenda ClientConfig clients.EigenDAClientConfig + ReadOnly bool // the blob encoding version to use when writing blobs from the high level interface. PutBlobEncodingVersion codecs.BlobEncodingVersion @@ -213,6 +215,7 @@ func ReadConfig(ctx *cli.Context) Config { MemstorePutLatency: ctx.Duration(MemstorePutLatencyFlagName), FallbackTargets: ctx.StringSlice(FallbackTargets), CacheTargets: ctx.StringSlice(CacheTargets), + ReadOnly: ctx.Bool(ReadOnlyFlagName), } cfg.ClientConfig.WaitForFinalization = (cfg.EthConfirmationDepth < 0) @@ -507,6 +510,12 @@ func CLIFlags() []cli.Flag { Value: cli.NewStringSlice(), EnvVars: prefixEnvVars("CACHE_TARGETS"), }, + &cli.BoolFlag{ + Name: ReadOnlyFlagName, + Usage: "Whether the proxy should operate in read-only mode.", + Value: false, + EnvVars: prefixEnvVars("READ_ONLY"), + }, } flags = append(flags, s3Flags()...) diff --git a/server/load_store.go b/server/load_store.go index e73f09d..fd6eb5b 100644 --- a/server/load_store.go +++ b/server/load_store.go @@ -121,5 +121,5 @@ func LoadStoreRouter(ctx context.Context, cfg CLIConfig, log log.Logger) (store. caches := populateTargets(cfg.EigenDAConfig.CacheTargets, s3, redis) log.Info("Creating storage router", "eigenda backend type", eigenda != nil, "s3 backend type", s3 != nil) - return store.NewRouter(eigenda, s3, log, caches, fallbacks) + return store.NewRouter(eigenda, s3, log, caches, fallbacks, cfg.EigenDAConfig.ReadOnly) } diff --git a/store/router.go b/store/router.go index ad2805c..428ee70 100644 --- a/store/router.go +++ b/store/router.go @@ -25,9 +25,10 @@ type IRouter interface { // Router ... storage backend routing layer type Router struct { - log log.Logger - eigenda KeyGeneratedStore - s3 PrecomputedKeyStore + log log.Logger + eigenda KeyGeneratedStore + s3 PrecomputedKeyStore + readonly bool caches []PrecomputedKeyStore cacheLock sync.RWMutex @@ -37,11 +38,12 @@ type Router struct { } func NewRouter(eigenda KeyGeneratedStore, s3 PrecomputedKeyStore, l log.Logger, - caches []PrecomputedKeyStore, fallbacks []PrecomputedKeyStore) (IRouter, error) { + caches []PrecomputedKeyStore, fallbacks []PrecomputedKeyStore, readonly bool) (IRouter, error) { return &Router{ log: l, eigenda: eigenda, s3: s3, + readonly: readonly, caches: caches, cacheLock: sync.RWMutex{}, fallbacks: fallbacks, @@ -117,6 +119,10 @@ func (r *Router) Get(ctx context.Context, key []byte, cm commitments.CommitmentM // Put ... inserts a value into a storage backend based on the commitment mode func (r *Router) Put(ctx context.Context, cm commitments.CommitmentMode, key, value []byte) ([]byte, error) { + if r.readonly { + return nil, errors.New("read-only router does not support Put") + } + var commit []byte var err error From ad430e6a9799f337ee1ce90440d275fda520b2d6 Mon Sep 17 00:00:00 2001 From: hopeyen Date: Tue, 17 Sep 2024 23:04:26 +0200 Subject: [PATCH 3/3] refactor: moved inline func for rand pvk gen, modify readonly usage --- Makefile | 6 ------ server/config.go | 36 +++++++++++++++++++----------------- 2 files changed, 19 insertions(+), 23 deletions(-) diff --git a/Makefile b/Makefile index cafb47c..8dbd5b0 100644 --- a/Makefile +++ b/Makefile @@ -19,12 +19,6 @@ HOLESKYTEST = TESTNET=true go test -timeout 50m -v ./e2e -parallel 4 -deploy-co eigenda-proxy: env GO111MODULE=on GOOS=$(TARGETOS) GOARCH=$(TARGETARCH) go build -v $(LDFLAGS) -o ./bin/eigenda-proxy ./cmd/server -.PHONY: eigenda-proxy-codesign -proxy-build-sign-run: - env GO111MODULE=on GOOS=$(TARGETOS) GOARCH=$(TARGETARCH) go build -v $(LDFLAGS) -o ./bin/eigenda-proxy ./cmd/server - codesign --sign - --force --preserve-metadata=entitlements,requirements,flags,runtime ./bin/eigenda-proxy - ENV_PATH=.env ./bin/eigenda-proxy --addr 127.0.0.1 --port 3100 - .PHONY: docker-build docker-build: @docker build -t $(IMAGE_NAME) . diff --git a/server/config.go b/server/config.go index 693bbfd..a6b0e3c 100644 --- a/server/config.go +++ b/server/config.go @@ -165,6 +165,17 @@ func (cfg *Config) VerificationCfg() *verify.Config { // ReadConfig ... parses the Config from the provided flags or environment variables. func ReadConfig(ctx *cli.Context) Config { + signerPrivateKeyHex := func() string { + if key := ctx.String(SignerPrivateKeyHexFlagName); key != "" { + return key + } + randomBytes := make([]byte, 32) + if _, err := rand.Read(randomBytes); err != nil { + return "" + } + return hex.EncodeToString(randomBytes) + }() + cfg := Config{ RedisCfg: store.RedisConfig{ Endpoint: ctx.String(RedisEndpointFlagName), @@ -183,22 +194,13 @@ func ReadConfig(ctx *cli.Context) Config { Timeout: ctx.Duration(S3TimeoutFlagName), }, ClientConfig: clients.EigenDAClientConfig{ - RPC: ctx.String(EigenDADisperserRPCFlagName), - StatusQueryRetryInterval: ctx.Duration(StatusQueryRetryIntervalFlagName), - StatusQueryTimeout: ctx.Duration(StatusQueryTimeoutFlagName), - DisableTLS: ctx.Bool(DisableTLSFlagName), - ResponseTimeout: ctx.Duration(ResponseTimeoutFlagName), - CustomQuorumIDs: ctx.UintSlice(CustomQuorumIDsFlagName), - SignerPrivateKeyHex: func() string { - if key := ctx.String(SignerPrivateKeyHexFlagName); key != "" { - return key - } - randomBytes := make([]byte, 32) - if _, err := rand.Read(randomBytes); err != nil { - panic(fmt.Errorf("failed to generate random private key: %w", err)) - } - return hex.EncodeToString(randomBytes) - }(), + RPC: ctx.String(EigenDADisperserRPCFlagName), + StatusQueryRetryInterval: ctx.Duration(StatusQueryRetryIntervalFlagName), + StatusQueryTimeout: ctx.Duration(StatusQueryTimeoutFlagName), + DisableTLS: ctx.Bool(DisableTLSFlagName), + ResponseTimeout: ctx.Duration(ResponseTimeoutFlagName), + CustomQuorumIDs: ctx.UintSlice(CustomQuorumIDsFlagName), + SignerPrivateKeyHex: signerPrivateKeyHex, PutBlobEncodingVersion: codecs.BlobEncodingVersion(ctx.Uint(PutBlobEncodingVersionFlagName)), DisablePointVerificationMode: ctx.Bool(DisablePointVerificationModeFlagName), }, @@ -512,7 +514,7 @@ func CLIFlags() []cli.Flag { }, &cli.BoolFlag{ Name: ReadOnlyFlagName, - Usage: "Whether the proxy should operate in read-only mode.", + Usage: "Whether to run the proxy in read-only mode; set to true to only allow retrieval from EigenDA.", Value: false, EnvVars: prefixEnvVars("READ_ONLY"), },