From f9e89ccdfa306a8429268d9f7152d97af7d35b03 Mon Sep 17 00:00:00 2001 From: Ethen Pociask Date: Sat, 17 Aug 2024 04:28:31 -0400 Subject: [PATCH 01/12] chore: go fmt --- commitments/da_service_op.go | 3 +-- commitments/eigenda.go | 4 +--- commitments/mode.go | 17 ++++++++-------- commitments/op.go | 5 ++--- e2e/server_test.go | 39 ++++++++++++++++++------------------ server/config.go | 9 ++++----- server/load_store.go | 4 ++-- server/server.go | 8 ++++---- store/eigenda.go | 3 +-- store/router.go | 2 +- store/s3.go | 2 +- store/store.go | 1 - verify/cert.go | 22 ++++++++++---------- 13 files changed, 55 insertions(+), 64 deletions(-) diff --git a/commitments/da_service_op.go b/commitments/da_service_op.go index 820be73a..2c923a12 100644 --- a/commitments/da_service_op.go +++ b/commitments/da_service_op.go @@ -17,7 +17,6 @@ type DaSvcCommitment interface { type EigenDASvcCommitment []byte - // NewEigenDASvcCommitment creates a new commitment from the given input. func NewEigenDASvcCommitment(input []byte) EigenDASvcCommitment { return EigenDASvcCommitment(crypto.Keccak256(input)) @@ -40,4 +39,4 @@ func (c EigenDASvcCommitment) CommitmentType() DAServiceOPCommitmentType { // Encode adds a commitment type prefix self describing the commitment. func (c EigenDASvcCommitment) Encode() []byte { return append([]byte{byte(EigenDACommitmentType)}, c...) -} \ No newline at end of file +} diff --git a/commitments/eigenda.go b/commitments/eigenda.go index f8c9d483..2a6686d6 100644 --- a/commitments/eigenda.go +++ b/commitments/eigenda.go @@ -1,6 +1,5 @@ package commitments - type CertEncodingCommitment byte const ( @@ -16,7 +15,6 @@ type CertCommitment interface { type CertCommitmentV0 []byte - // NewV0CertCommitment creates a new commitment from the given input. func NewV0CertCommitment(input []byte) CertCommitmentV0 { return CertCommitmentV0(input) @@ -38,4 +36,4 @@ func (c CertCommitmentV0) CommitmentType() CertEncodingCommitment { // Encode adds a commitment type prefix self describing the commitment. func (c CertCommitmentV0) Encode() []byte { return append([]byte{byte(CertV0)}, c...) -} \ No newline at end of file +} diff --git a/commitments/mode.go b/commitments/mode.go index 182c9337..9788fe57 100644 --- a/commitments/mode.go +++ b/commitments/mode.go @@ -8,9 +8,9 @@ import ( type CommitmentMode string const ( - OptimismGeneric CommitmentMode = "optimism_keccak256" - OptimismAltDA CommitmentMode = "optimism_generic" - SimpleCommitmentMode CommitmentMode = "simple" + OptimismGeneric CommitmentMode = "optimism_keccak256" + OptimismAltDA CommitmentMode = "optimism_generic" + SimpleCommitmentMode CommitmentMode = "simple" ) func StringToCommitmentMode(s string) (CommitmentMode, error) { @@ -49,7 +49,7 @@ func StringToDecodedCommitment(key string, c CommitmentMode) ([]byte, error) { return b[3:], nil case SimpleCommitmentMode: // [cert_version, ...] - return b[1:], nil + return b[1:], nil default: return nil, fmt.Errorf("unknown commitment type") @@ -57,22 +57,21 @@ func StringToDecodedCommitment(key string, c CommitmentMode) ([]byte, error) { } func EncodeCommitment(b []byte, c CommitmentMode) ([]byte, error) { - + switch c { case OptimismGeneric: return Keccak256Commitment(b).Encode(), nil case OptimismAltDA: - certCommit := NewV0CertCommitment(b).Encode() + certCommit := NewV0CertCommitment(b).Encode() svcCommit := EigenDASvcCommitment(certCommit).Encode() altDACommit := NewGenericCommitment(svcCommit).Encode() return altDACommit, nil - + case SimpleCommitmentMode: return NewV0CertCommitment(b).Encode(), nil } return nil, fmt.Errorf("unknown commitment mode") -} - +} diff --git a/commitments/op.go b/commitments/op.go index 01bc60c7..f14c6613 100644 --- a/commitments/op.go +++ b/commitments/op.go @@ -14,7 +14,6 @@ var ErrInvalidCommitment = errors.New("invalid commitment") // ErrCommitmentMismatch is returned when the commitment does not match the given input. var ErrCommitmentMismatch = errors.New("commitment mismatch") - // OPCommitmentType is the commitment type prefix. type OPCommitmentType byte @@ -35,8 +34,8 @@ func CommitmentTypeFromString(s string) (OPCommitmentType, error) { const ( Keccak256CommitmentType OPCommitmentType = 0 GenericCommitmentType OPCommitmentType = 1 - KeccakCommitmentString string = "KeccakCommitment" - GenericCommitmentString string = "GenericCommitment" + KeccakCommitmentString string = "KeccakCommitment" + GenericCommitmentString string = "GenericCommitment" ) // OPCommitment is the binary representation of a commitment. diff --git a/e2e/server_test.go b/e2e/server_test.go index 804a18ef..d3e0ecc6 100644 --- a/e2e/server_test.go +++ b/e2e/server_test.go @@ -158,7 +158,6 @@ func TestProxyClientWithOversizedBlob(t *testing.T) { func TestProxyClient_MultiSameContentBlobs_SameBatch(t *testing.T) { t.Skip("Skipping test until fix is applied to holesky") - t.Parallel() ts, kill := e2e.CreateTestSuite(t, useMemory(), false) @@ -167,32 +166,32 @@ func TestProxyClient_MultiSameContentBlobs_SameBatch(t *testing.T) { cfg := &client.Config{ URL: ts.Address(), } - + errChan := make(chan error, 10) var wg sync.WaitGroup // disperse 10 blobs with the same content in the same batch - for i := 0; i < 4; i ++ { + for i := 0; i < 4; i++ { wg.Add(1) - go func(){ + go func() { defer wg.Done() daClient := client.New(cfg) testPreimage := []byte("hellooooooooooo world!") - + t.Log("Setting input data on proxy server...") blobInfo, err := daClient.SetData(ts.Ctx, testPreimage) if err != nil { errChan <- err return } - + t.Log("Getting input data from proxy server...") preimage, err := daClient.GetData(ts.Ctx, blobInfo) if err != nil { errChan <- err return } - + if !utils.EqualSlices(preimage, testPreimage) { errChan <- fmt.Errorf("expected preimage %s, got %s", testPreimage, preimage) return @@ -206,7 +205,7 @@ func TestProxyClient_MultiSameContentBlobs_SameBatch(t *testing.T) { } if len(errChan) > 0 { - // iterate over channel and log errors + // iterate over channel and log errors for i := 0; i < len(errChan); i++ { err := <-errChan t.Log(err.Error()) @@ -218,15 +217,15 @@ func TestProxyClient_MultiSameContentBlobs_SameBatch(t *testing.T) { // waitTimeout waits for the waitgroup for the specified max timeout. // Returns true if waiting timed out. func waitTimeout(wg *sync.WaitGroup, timeout time.Duration) bool { - c := make(chan struct{}) - go func() { - defer close(c) - wg.Wait() - }() - select { - case <-c: - return false - case <-time.After(timeout): - return true - } -} \ No newline at end of file + c := make(chan struct{}) + go func() { + defer close(c) + wg.Wait() + }() + select { + case <-c: + return false + case <-time.After(timeout): + return true + } +} diff --git a/server/config.go b/server/config.go index cb2a48ee..e9b93848 100644 --- a/server/config.go +++ b/server/config.go @@ -68,16 +68,15 @@ type Config struct { EthConfirmationDepth int64 // KZG vars - CacheDir string - G1Path string - G2Path string + CacheDir string + G1Path string + G2Path string G2PowerOfTauPath string // Size constraints MaxBlobLength string maxBlobLengthBytes uint64 - // Memstore MemstoreEnabled bool MemstoreBlobExpiration time.Duration @@ -360,4 +359,4 @@ func CLIFlags(envPrefix string) []cli.Flag { EnvVars: prefixEnvVars("S3_ACCESS_KEY_SECRET"), }, } -} \ No newline at end of file +} diff --git a/server/load_store.go b/server/load_store.go index 94cadbe1..af1c0398 100644 --- a/server/load_store.go +++ b/server/load_store.go @@ -3,7 +3,7 @@ package server import ( "context" "fmt" - + "github.com/Layr-Labs/eigenda-proxy/store" "github.com/Layr-Labs/eigenda-proxy/verify" "github.com/Layr-Labs/eigenda/api/clients" @@ -57,7 +57,7 @@ func LoadStoreRouter(cfg CLIConfig, ctx context.Context, log log.Logger) (*store if err != nil { return nil, err } - + eigenda, err := store.NewEigenDAStore( ctx, client, diff --git a/server/server.go b/server/server.go index b30ac873..a1be6e63 100644 --- a/server/server.go +++ b/server/server.go @@ -38,7 +38,7 @@ const ( type Server struct { log log.Logger endpoint string - router *store.Router + router *store.Router m metrics.Metricer tls *rpc.ServerTLSConfig httpServer *http.Server @@ -51,7 +51,7 @@ func NewServer(host string, port int, router *store.Router, log log.Logger, m me m: m, log: log, endpoint: endpoint, - router: router, + router: router, httpServer: &http.Server{ Addr: endpoint, ReadHeaderTimeout: 10 * time.Second, @@ -279,7 +279,7 @@ func ReadCommitmentMode(r *http.Request) (commitments.CommitmentMode, error) { default: return commitments.SimpleCommitmentMode, fmt.Errorf("unknown commit byte prefix") - + } } @@ -295,4 +295,4 @@ func (svr *Server) GetMemStats() *store.Stats { func (svr *Server) GetS3Stats() *store.Stats { return svr.router.GetS3Store().Stats() -} \ No newline at end of file +} diff --git a/store/eigenda.go b/store/eigenda.go index d8b1c250..bee0c90c 100644 --- a/store/eigenda.go +++ b/store/eigenda.go @@ -83,7 +83,6 @@ func (e EigenDAStore) Put(ctx context.Context, value []byte) (comm []byte, err e } cert := (*verify.Certificate)(blobInfo) - err = e.verifier.VerifyCommitment(cert.BlobHeader.Commitment, encodedBlob) if err != nil { return nil, err @@ -152,4 +151,4 @@ func (e EigenDAStore) EncodeAndVerify(ctx context.Context, key []byte, value []b } return value, nil -} \ No newline at end of file +} diff --git a/store/router.go b/store/router.go index b5a594a8..ea5fa56d 100644 --- a/store/router.go +++ b/store/router.go @@ -149,4 +149,4 @@ func (r *Router) GetMemStore() *MemStore { func (r *Router) GetS3Store() *S3Store { return r.s3 -} \ No newline at end of file +} diff --git a/store/s3.go b/store/s3.go index 5d4ed9c3..56bf282f 100644 --- a/store/s3.go +++ b/store/s3.go @@ -5,10 +5,10 @@ import ( "context" "encoding/hex" "errors" + "github.com/minio/minio-go/v7" "io" "path" "time" - "github.com/minio/minio-go/v7" "github.com/minio/minio-go/v7/pkg/credentials" ) diff --git a/store/store.go b/store/store.go index 3aa21a36..bde5d43a 100644 --- a/store/store.go +++ b/store/store.go @@ -2,7 +2,6 @@ package store import "context" - type Stats struct { Entries int Reads int diff --git a/verify/cert.go b/verify/cert.go index a520e19e..9a727dd4 100644 --- a/verify/cert.go +++ b/verify/cert.go @@ -21,7 +21,7 @@ var ErrBatchMetadataHashNotFound = errors.New("BatchMetadataHash not found for B // CertVerifier verifies the DA certificate against on-chain EigenDA contracts // to ensure disperser returned fields haven't been tampered with type CertVerifier struct { - l log.Logger + l log.Logger ethConfirmationDepth uint64 manager *binding.ContractEigenDAServiceManagerCaller ethClient *ethclient.Client @@ -42,7 +42,7 @@ func NewCertVerifier(cfg *Config, l log.Logger) (*CertVerifier, error) { } return &CertVerifier{ - l: l, + l: l, manager: m, ethConfirmationDepth: cfg.EthConfirmationDepth, ethClient: client, @@ -104,17 +104,17 @@ func (cv *CertVerifier) VerifyMerkleProof(inclusionProof []byte, root []byte, bl func (cv *CertVerifier) getContextBlock() (*big.Int, error) { var blockNumber *big.Int - blockHeader, err := cv.ethClient.BlockByNumber(context.Background(), nil) - if err != nil { - return nil, err - } + blockHeader, err := cv.ethClient.BlockByNumber(context.Background(), nil) + if err != nil { + return nil, err + } - if cv.ethConfirmationDepth == 0 { - return blockHeader.Number(), nil - } + if cv.ethConfirmationDepth == 0 { + return blockHeader.Number(), nil + } - blockNumber = new(big.Int) - blockNumber.Sub(blockHeader.Number(), big.NewInt(int64(cv.ethConfirmationDepth-1))) + blockNumber = new(big.Int) + blockNumber.Sub(blockHeader.Number(), big.NewInt(int64(cv.ethConfirmationDepth-1))) return blockNumber, nil } From bbf599227f96727757a179bfbab8c6c5b0eb8b5d Mon Sep 17 00:00:00 2001 From: Ethen Pociask Date: Mon, 19 Aug 2024 15:55:09 -0400 Subject: [PATCH 02/12] chore: EigenDA V8 dep bump --- go.mod | 6 ++++-- go.sum | 12 ++++++++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 40018f23..fb692fb4 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/Layr-Labs/eigenda-proxy go 1.21 require ( - github.com/Layr-Labs/eigenda v0.7.5-0.20240626225853-1645ffe3489e + github.com/Layr-Labs/eigenda v0.8.0 github.com/consensys/gnark-crypto v0.12.1 github.com/ethereum-optimism/optimism v1.9.0 github.com/ethereum/go-ethereum v1.14.0 @@ -119,6 +119,7 @@ require ( github.com/holiman/bloomfilter/v2 v2.0.3 // indirect github.com/holiman/uint256 v1.3.1 // indirect github.com/huin/goupnp v1.3.0 // indirect + github.com/iden3/go-iden3-crypto v0.0.16 // indirect github.com/influxdata/influxdb-client-go/v2 v2.4.0 // indirect github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c // indirect github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 // indirect @@ -221,10 +222,11 @@ require ( github.com/tklauser/numcpus v0.6.1 // indirect github.com/tyler-smith/go-bip39 v1.1.0 // indirect github.com/urfave/cli v1.22.14 // indirect - github.com/wealdtech/go-merkletree v1.0.1-0.20230205101955-ec7a95ea11ca // indirect + github.com/wealdtech/go-merkletree/v2 v2.6.0 // indirect github.com/x448/float16 v0.8.4 // indirect github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect github.com/yusufpapurcu/wmi v1.2.3 // indirect + go.uber.org/automaxprocs v1.5.2 // indirect go.uber.org/dig v1.17.1 // indirect go.uber.org/fx v1.21.1 // indirect go.uber.org/mock v0.4.0 // indirect diff --git a/go.sum b/go.sum index 3fc8f89e..ddf9d2d5 100644 --- a/go.sum +++ b/go.sum @@ -21,8 +21,8 @@ github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3 github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ= github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= -github.com/Layr-Labs/eigenda v0.7.5-0.20240626225853-1645ffe3489e h1:vibQgDKVXvuKZKqdyvIuCx8MH1B5uOGrKITAUp3bzJg= -github.com/Layr-Labs/eigenda v0.7.5-0.20240626225853-1645ffe3489e/go.mod h1:gG5KSp5gGY0lywj6aZwaK9ZEF8eEVX4ilo679pFpvAA= +github.com/Layr-Labs/eigenda v0.8.0 h1:OghLxQDLLJWrjPnGQ5Sykf/0n3tyOtAexdU+CNooK0I= +github.com/Layr-Labs/eigenda v0.8.0/go.mod h1:Nsp+Z7OAQbPvCVq/xqrUies3wBEohKN4bb668CBYvcM= github.com/Layr-Labs/eigensdk-go v0.1.7-0.20240507215523-7e4891d5099a h1:L/UsJFw9M31FD/WgXTPFB0oxbq9Cu4Urea1xWPMQS7Y= github.com/Layr-Labs/eigensdk-go v0.1.7-0.20240507215523-7e4891d5099a/go.mod h1:OF9lmS/57MKxS0xpSpX0qHZl0SKkDRpvJIvsGvMN1y8= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= @@ -442,6 +442,8 @@ github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= +github.com/iden3/go-iden3-crypto v0.0.16 h1:zN867xiz6HgErXVIV/6WyteGcOukE9gybYTorBMEdsk= +github.com/iden3/go-iden3-crypto v0.0.16/go.mod h1:dLpM4vEPJ3nDHzhWFXDjzkn1qHoBeOT/3UEhXsEsP3E= github.com/influxdata/influxdb-client-go/v2 v2.4.0 h1:HGBfZYStlx3Kqvsv1h2pJixbCl/jhnFtxpKFAv9Tu5k= github.com/influxdata/influxdb-client-go/v2 v2.4.0/go.mod h1:vLNHdxTJkIf2mSLvGrpj8TCcISApPoXkaxP8g9uRlW8= github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c h1:qSHzRbhzK8RdXOsAdfDgO49TtqC1oZ+acxPrkfTxcCs= @@ -741,6 +743,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= +github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= @@ -881,8 +885,8 @@ github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPU github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= -github.com/wealdtech/go-merkletree v1.0.1-0.20230205101955-ec7a95ea11ca h1:oK35INPN4CiubFw7ZPQkbxm2AsSU6Tjeb9YhciZnvIM= -github.com/wealdtech/go-merkletree v1.0.1-0.20230205101955-ec7a95ea11ca/go.mod h1:bM9mDSjsti+gkjl8FjovMoUH3MPR5bwJ3+ucaYFY0Jk= +github.com/wealdtech/go-merkletree/v2 v2.6.0 h1:/Qz2blWf+yblxWiudjSXPm5h6sBMgoL67+9Rq2IhfTE= +github.com/wealdtech/go-merkletree/v2 v2.6.0/go.mod h1:Ooz0/mhs/XF1iYfbowRawrkAI56YYZ+oUl5Dw2Tlnjk= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= From 0be34cca02bbdf8cec5000a541c20c17bdee0054 Mon Sep 17 00:00:00 2001 From: Ethen Pociask Date: Mon, 19 Aug 2024 15:58:26 -0400 Subject: [PATCH 03/12] chore: EigenDA V8 dep bump - update large blob test --- e2e/server_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/server_test.go b/e2e/server_test.go index d3e0ecc6..1c4986a6 100644 --- a/e2e/server_test.go +++ b/e2e/server_test.go @@ -108,7 +108,7 @@ func TestProxyClientWithLargeBlob(t *testing.T) { } daClient := client.New(cfg) // 2MB blob - testPreimage := []byte(e2e.RandString(2000000)) + testPreimage := []byte(e2e.RandString(4_000_000)) t.Log("Setting input data on proxy server...") blobInfo, err := daClient.SetData(ts.Ctx, testPreimage) From 77b8796f4a86ec369107bda49c1cb74b016f2f32 Mon Sep 17 00:00:00 2001 From: Ethen Pociask Date: Tue, 20 Aug 2024 04:35:22 -0400 Subject: [PATCH 04/12] chore: EigenDA V8 dep bump - bump eigenda to incorporate tls disperser read client fix && add linting --- .github/workflows/lint.yml | 21 ++++ .golangci.yml | 226 +++++++++++++++++++++++++++++++++++++ client/client.go | 6 +- cmd/server/entrypoint.go | 6 +- cmd/server/main.go | 1 - commitments/mode.go | 2 - commitments/op.go | 7 +- e2e/optimism_test.go | 96 ++++++++-------- e2e/server_test.go | 79 ------------- e2e/setup.go | 12 +- go.mod | 2 +- go.sum | 2 + metrics/metrics.go | 3 +- server/config.go | 35 +++--- server/flags.go | 2 +- server/load_store.go | 3 +- server/server.go | 57 +++++----- store/eigenda.go | 17 +-- store/memory.go | 10 +- store/router.go | 51 +++++---- store/s3.go | 11 +- utils/parse_bytes.go | 2 +- utils/parse_bytes_test.go | 3 + verify/cert.go | 15 +-- verify/certificate.go | 5 - verify/hasher.go | 4 +- verify/merkle.go | 4 +- verify/verifier.go | 7 +- 28 files changed, 424 insertions(+), 265 deletions(-) create mode 100644 .github/workflows/lint.yml create mode 100644 .golangci.yml diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 00000000..c4c21664 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,21 @@ +name: hygeiene + +on: + push: + branches: [ "master", "development" ] + pull_request: + branches: [ "master", "development" ] + +jobs: + golangci: + # Linting job + # https://github.com/golangci/golangci-lint-action + name: lint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: golangci-lint + uses: golangci/golangci-lint-action@v3 + with: + # Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version + version: v1.52.1 \ No newline at end of file diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 00000000..f042c06d --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,226 @@ +run: + # Analysis timeout, e.g. 30s, 5m. + # Default: 1m + timeout: 5m + +# https://github.com/golangci/golangci-lint/blob/master/.golangci.reference.yml +linters-settings: + cyclop: + # The maximal code complexity to report. + # Default: 10 + max-complexity: 30 + # The maximal average package complexity. + # If it's higher than 0.0 (float) the check is enabled + # Default: 0.0 + package-average: 20.0 + + errcheck: + # Report about not checking of errors in type assertions: `a := b.(MyStruct)`. + # Default: false + check-type-assertions: true + + exhaustive: + # Program elements to check for exhaustiveness. + # Default: [ switch ] + check: + - switch + - map + + exhaustruct: + # List of regular expressions to exclude struct packages and names from check. + # Default: [] + exclude: + # std libs + - "^os/exec.Cmd$" + # public libs + - "^github.com/stretchr/testify/mock.Mock$" + + funlen: + # Assert a maximum number of lines for a function. + # Default: 60 + lines: 150 + # Assert a maximum number of statements in a function. + # Default: 40 + statements: 60 + + gocognit: + # Minimal code complexity to report. + # Default: 30 + min-complexity: 35 + + gocritic: + # Settings passed to gocritic. + # The settings key is the name of a supported gocritic checker. + # The list of supported checkers can be find in https://go-critic.github.io/overview. + settings: + captLocal: + # Whether to restrict checker to params only. + # Default: true + paramsOnly: false + underef: + # Whether to skip (*x).method() calls where x is a pointer receiver. + # Default: true + skipRecvDeref: false + + # gomnd: + # # List of function regex patterns to exclude from analysis. + # # Default: [] + # ignored-functions: + # - + gomodguard: + blocked: + # List of blocked modules. + # Default: [] + modules: + - + govet: + # Enable all analyzers. + # Default: false + enable-all: true + # Disable analyzers by name. + # Run `go tool vet help` to see all analyzers. + # Default: [] + disable: + - fieldalignment # too strict + # Settings per analyzer. + settings: + shadow: + # Whether to be strict about shadowing; can be noisy. + # Default: false + strict: true + + nakedret: + # Make an issue if func has more lines of code than this setting, and it has naked returns. + # Default: 30 + max-func-lines: 0 + + nolintlint: + # Exclude following linters from requiring an explanation. + # Default: [] + allow-no-explanation: [ funlen, gocognit, lll, whitespace ] + # Enable to require an explanation of nonzero length after each nolint directive. + # Default: false + require-explanation: true + # Enable to require nolint directives to mention the specific linter being suppressed. + # Default: false + require-specific: true + + tenv: + # The option `all` will run against whole test files (`_test.go`) regardless of method/function signatures. + # Otherwise, only methods that take `*testing.T`, `*testing.B`, and `testing.TB` as arguments are checked. + # Default: false + all: true + + +linters: + disable-all: true + enable: + ## enabled by default + - errcheck # checking for unchecked errors, these unchecked errors can be critical bugs in some cases + - gosimple # specializes in simplifying a code + - ineffassign # detects when assignments to existing variables are not used + - staticcheck # is a go vet on steroids, applying a ton of static analysis checks + - typecheck # like the front-end of a Go compiler, parses and type-checks Go code + - unused # checks for unused constants, variables, functions and types + ## disabled by default + - asasalint # checks for pass []any as any in variadic func(...any) + - asciicheck # checks that your code does not contain non-ASCII identifiers + - bidichk # checks for dangerous unicode character sequences + - bodyclose # checks whether HTTP response body is closed successfully + - cyclop # checks function and package cyclomatic complexity + - dupl # tool for code clone detection + - durationcheck # checks for two durations multiplied together + - errname # checks that sentinel errors are prefixed with the Err and error types are suffixed with the Error + - errorlint # finds code that will cause problems with the error wrapping scheme introduced in Go 1.13 + - execinquery # checks query string in Query function which reads your Go src files and warning it finds + - exhaustive # checks exhaustiveness of enum switch statements + - exportloopref # checks for pointers to enclosing loop variables + - forbidigo # forbids identifiers + - funlen # tool for detection of long functions + - gocheckcompilerdirectives # validates go compiler directive comments (//go:) + # - gochecknoinits # checks that no init functions are present in Go code + - gocognit # computes and checks the cognitive complexity of functions + - goconst # finds repeated strings that could be replaced by a constant + - gocritic # provides diagnostics that check for bugs, performance and style issues + - gocyclo # computes and checks the cyclomatic complexity of functions + - goimports # in addition to fixing imports, goimports also formats your code in the same style as gofmt + # - gomnd # detects magic numbers + - gofmt + - gomodguard # allow and block lists linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations + - goprintffuncname # checks that printf-like functions are named with f at the end + - gosec # inspects source code for security problems + # - lll # reports long lines + - loggercheck # checks key value pairs for common logger libraries (kitlog,klog,logr,zap) + - makezero # finds slice declarations with non-zero initial length + - misspell # Ensures real english is used within strings + - nakedret # finds naked returns in functions greater than a specified function length + - nestif # reports deeply nested if statements + - nilerr # finds the code that returns nil even if it checks that the error is not nil + - nilnil # checks that there is no simultaneous return of nil error and an invalid value + - noctx # finds sending http request without context.Context + - nolintlint # reports ill-formed or insufficient nolint directives + - nonamedreturns # reports all named returns + - nosprintfhostport # checks for misuse of Sprintf to construct a host with port in a URL + - predeclared # finds code that shadows one of Go's predeclared identifiers + - promlinter # checks Prometheus metrics naming via promlint + - reassign # checks that package variables are not reassigned + - revive # fast, configurable, extensible, flexible, and beautiful linter for Go, drop-in replacement of golint + - rowserrcheck # checks whether Err of rows is checked successfully + - sqlclosecheck # checks that sql.Rows and sql.Stmt are closed + - stylecheck # is a replacement for golint + - tenv # detects using os.Setenv instead of t.Setenv since Go1.17 + - testableexamples # checks if examples are testable (have an expected output) + - testpackage # makes you use a separate _test package + - tparallel # detects inappropriate usage of t.Parallel() method in your Go test codes + - unconvert # removes unnecessary type conversions + - unparam # reports unused function parameters + - usestdlibvars # detects the possibility to use variables/constants from the Go standard library + - wastedassign # finds wasted assignment statements + - whitespace # detects leading and trailing whitespace + + ## May want to enable + #- - gochecknoglobals # checks that no global variables exist + #- - govet # reports suspicious constructs, such as Printf calls whose arguments do not align with the format string + #- - gomoddirectives # manages the use of 'replace', 'retract', and 'excludes' directives in go.mod + #- - godot # checks if comments end in a period + #- decorder # checks declaration order and count of types, constants, variables and functions + #- exhaustruct # [highly recommend to enable] checks if all structure fields are initialized + #- gci # controls golang package import order and makes it always deterministic + #- ginkgolinter # [if you use ginkgo/gomega] enforces standards of using ginkgo and gomega + #- godox # detects FIXME, TODO and other comment keywords + #- goheader # checks is file header matches to pattern + #- interfacebloat # checks the number of methods inside an interface + #- ireturn # accept interfaces, return concrete types + #- prealloc # [premature optimization, but can be used in some cases] finds slice declarations that could potentially be preallocated + #- varnamelen # [great idea, but too many false positives] checks that the length of a variable's name matches its scope + #- wrapcheck # checks that errors returned from external packages are wrapped + +issues: + # Maximum count of issues with the same text. + # Set to 0 to disable. + # Default: 3 + max-same-issues: 50 + + exclude-rules: + - source: "(noinspection|TODO)" + linters: [ godot ] + - source: "// noinspection" + linters: + - gocritic + - unparam + + - path: "_test\\.go" + linters: + - gocognit + - govet + - testpackage + - bodyclose + - dupl + - funlen + - goconst + - gosec + - noctx + - wrapcheck + - lll + - whitespace + diff --git a/client/client.go b/client/client.go index 6af15117..9b6822e4 100644 --- a/client/client.go +++ b/client/client.go @@ -39,7 +39,7 @@ func New(cfg *Config) ProxyClient { // when integration testing func (c *client) Health() error { url := c.cfg.URL + "/health" - req, err := http.NewRequest(http.MethodGet, url, nil) + req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, url, nil) if err != nil { return err } @@ -48,6 +48,7 @@ func (c *client) Health() error { if err != nil { return err } + defer resp.Body.Close() if resp.StatusCode != http.StatusOK { return fmt.Errorf("received bad status code: %d", resp.StatusCode) @@ -62,7 +63,7 @@ func (c *client) GetData(ctx context.Context, comm []byte) ([]byte, error) { req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) if err != nil { - return nil, fmt.Errorf("failed to construct http request: %e", err) + return nil, fmt.Errorf("failed to construct http request: %w", err) } req.Header.Set("Content-Type", "application/octet-stream") @@ -83,7 +84,6 @@ func (c *client) GetData(ctx context.Context, comm []byte) ([]byte, error) { } return b, nil - } // SetData writes raw byte data to DA and returns the respective certificate diff --git a/cmd/server/entrypoint.go b/cmd/server/entrypoint.go index a7c38251..2959ec97 100644 --- a/cmd/server/entrypoint.go +++ b/cmd/server/entrypoint.go @@ -30,7 +30,7 @@ func StartProxySvr(cliCtx *cli.Context) error { log.Info("Initializing EigenDA proxy server...") - daRouter, err := server.LoadStoreRouter(cfg, ctx, log) + daRouter, err := server.LoadStoreRouter(ctx, cfg, log) if err != nil { return fmt.Errorf("failed to create store: %w", err) } @@ -38,10 +38,10 @@ func StartProxySvr(cliCtx *cli.Context) error { if err := server.Start(); err != nil { return fmt.Errorf("failed to start the DA server") - } else { - log.Info("Started EigenDA proxy server") } + log.Info("Started EigenDA proxy server") + defer func() { if err := server.Stop(); err != nil { log.Error("failed to stop DA server", "err", err) diff --git a/cmd/server/main.go b/cmd/server/main.go index c24b00b6..94de2f01 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -47,5 +47,4 @@ func main() { if err != nil { log.Crit("Application failed", "message", err) } - } diff --git a/commitments/mode.go b/commitments/mode.go index 9788fe57..a0e43239 100644 --- a/commitments/mode.go +++ b/commitments/mode.go @@ -57,7 +57,6 @@ func StringToDecodedCommitment(key string, c CommitmentMode) ([]byte, error) { } func EncodeCommitment(b []byte, c CommitmentMode) ([]byte, error) { - switch c { case OptimismGeneric: return Keccak256Commitment(b).Encode(), nil @@ -70,7 +69,6 @@ func EncodeCommitment(b []byte, c CommitmentMode) ([]byte, error) { case SimpleCommitmentMode: return NewV0CertCommitment(b).Encode(), nil - } return nil, fmt.Errorf("unknown commitment mode") diff --git a/commitments/op.go b/commitments/op.go index f14c6613..470e0d48 100644 --- a/commitments/op.go +++ b/commitments/op.go @@ -128,7 +128,7 @@ func DecodeGenericCommitment(commitment []byte) (GenericCommitment, error) { if len(commitment) == 0 { return nil, ErrInvalidCommitment } - return commitment[:], nil + return commitment, nil } // CommitmentType returns the commitment type of Generic Commitment. @@ -141,7 +141,8 @@ func (c GenericCommitment) Encode() []byte { return append([]byte{byte(GenericCommitmentType)}, c...) } -// Verify always returns true for GenericCommitment because the DA Server must validate the data before returning it to the op-node. -func (c GenericCommitment) Verify(input []byte) error { +// Verify always returns true for GenericCommitment because the DA Server +// must validate the data before returning it to the op-node. +func (c GenericCommitment) Verify(_ []byte) error { return nil } diff --git a/e2e/optimism_test.go b/e2e/optimism_test.go index d115f386..8a83fd5e 100644 --- a/e2e/optimism_test.go +++ b/e2e/optimism_test.go @@ -121,46 +121,46 @@ func TestOptimismKeccak256Commitment(gt *testing.T) { gt.Skip("Skipping test as INTEGRATION or TESTNET env var not set") } - proxyTS, close := e2e.CreateTestSuite(gt, useMemory(), true) - defer close() + proxyTS, shutDown := e2e.CreateTestSuite(gt, useMemory(), true) + defer shutDown() t := actions.NewDefaultTesting(gt) - op_stack := NewL2PlasmaDA(t, proxyTS.Address(), false) + optimism := NewL2PlasmaDA(t, proxyTS.Address(), false) // build L1 block #1 - op_stack.ActL1Blocks(t, 1) - op_stack.miner.ActL1SafeNext(t) + optimism.ActL1Blocks(t, 1) + optimism.miner.ActL1SafeNext(t) // Fill with l2 blocks up to the L1 head - op_stack.sequencer.ActL1HeadSignal(t) - op_stack.sequencer.ActBuildToL1Head(t) + optimism.sequencer.ActL1HeadSignal(t) + optimism.sequencer.ActBuildToL1Head(t) - op_stack.sequencer.ActL2PipelineFull(t) - op_stack.sequencer.ActL1SafeSignal(t) - require.Equal(t, uint64(1), op_stack.sequencer.SyncStatus().SafeL1.Number) + optimism.sequencer.ActL2PipelineFull(t) + optimism.sequencer.ActL1SafeSignal(t) + require.Equal(t, uint64(1), optimism.sequencer.SyncStatus().SafeL1.Number) // add L1 block #2 - op_stack.ActL1Blocks(t, 1) - op_stack.miner.ActL1SafeNext(t) - op_stack.miner.ActL1FinalizeNext(t) - op_stack.sequencer.ActL1HeadSignal(t) - op_stack.sequencer.ActBuildToL1Head(t) + optimism.ActL1Blocks(t, 1) + optimism.miner.ActL1SafeNext(t) + optimism.miner.ActL1FinalizeNext(t) + optimism.sequencer.ActL1HeadSignal(t) + optimism.sequencer.ActBuildToL1Head(t) // Catch up derivation - op_stack.sequencer.ActL2PipelineFull(t) - op_stack.sequencer.ActL1FinalizedSignal(t) - op_stack.sequencer.ActL1SafeSignal(t) + optimism.sequencer.ActL2PipelineFull(t) + optimism.sequencer.ActL1FinalizedSignal(t) + optimism.sequencer.ActL1SafeSignal(t) // commit all the l2 blocks to L1 - op_stack.batcher.ActSubmitAll(t) - op_stack.miner.ActL1StartBlock(12)(t) - op_stack.miner.ActL1IncludeTx(op_stack.dp.Addresses.Batcher)(t) - op_stack.miner.ActL1EndBlock(t) + optimism.batcher.ActSubmitAll(t) + optimism.miner.ActL1StartBlock(12)(t) + optimism.miner.ActL1IncludeTx(optimism.dp.Addresses.Batcher)(t) + optimism.miner.ActL1EndBlock(t) // verify - op_stack.sequencer.ActL2PipelineFull(t) - op_stack.ActL1Finalized(t) + optimism.sequencer.ActL2PipelineFull(t) + optimism.ActL1Finalized(t) // assert that EigenDA proxy's was written and read from stat := proxyTS.Server.GetS3Stats() @@ -174,46 +174,46 @@ func TestOptimismAltDACommitment(gt *testing.T) { gt.Skip("Skipping test as INTEGRATION or TESTNET env var not set") } - proxyTS, close := e2e.CreateTestSuite(gt, useMemory(), false) - defer close() + proxyTS, shutDown := e2e.CreateTestSuite(gt, useMemory(), false) + defer shutDown() t := actions.NewDefaultTesting(gt) - op_stack := NewL2PlasmaDA(t, proxyTS.Address(), true) + optimism := NewL2PlasmaDA(t, proxyTS.Address(), true) // build L1 block #1 - op_stack.ActL1Blocks(t, 1) - op_stack.miner.ActL1SafeNext(t) + optimism.ActL1Blocks(t, 1) + optimism.miner.ActL1SafeNext(t) // Fill with l2 blocks up to the L1 head - op_stack.sequencer.ActL1HeadSignal(t) - op_stack.sequencer.ActBuildToL1Head(t) + optimism.sequencer.ActL1HeadSignal(t) + optimism.sequencer.ActBuildToL1Head(t) - op_stack.sequencer.ActL2PipelineFull(t) - op_stack.sequencer.ActL1SafeSignal(t) - require.Equal(t, uint64(1), op_stack.sequencer.SyncStatus().SafeL1.Number) + optimism.sequencer.ActL2PipelineFull(t) + optimism.sequencer.ActL1SafeSignal(t) + require.Equal(t, uint64(1), optimism.sequencer.SyncStatus().SafeL1.Number) // add L1 block #2 - op_stack.ActL1Blocks(t, 1) - op_stack.miner.ActL1SafeNext(t) - op_stack.miner.ActL1FinalizeNext(t) - op_stack.sequencer.ActL1HeadSignal(t) - op_stack.sequencer.ActBuildToL1Head(t) + optimism.ActL1Blocks(t, 1) + optimism.miner.ActL1SafeNext(t) + optimism.miner.ActL1FinalizeNext(t) + optimism.sequencer.ActL1HeadSignal(t) + optimism.sequencer.ActBuildToL1Head(t) // Catch up derivation - op_stack.sequencer.ActL2PipelineFull(t) - op_stack.sequencer.ActL1FinalizedSignal(t) - op_stack.sequencer.ActL1SafeSignal(t) + optimism.sequencer.ActL2PipelineFull(t) + optimism.sequencer.ActL1FinalizedSignal(t) + optimism.sequencer.ActL1SafeSignal(t) // commit all the l2 blocks to L1 - op_stack.batcher.ActSubmitAll(t) - op_stack.miner.ActL1StartBlock(12)(t) - op_stack.miner.ActL1IncludeTx(op_stack.dp.Addresses.Batcher)(t) - op_stack.miner.ActL1EndBlock(t) + optimism.batcher.ActSubmitAll(t) + optimism.miner.ActL1StartBlock(12)(t) + optimism.miner.ActL1IncludeTx(optimism.dp.Addresses.Batcher)(t) + optimism.miner.ActL1EndBlock(t) // verify - op_stack.sequencer.ActL2PipelineFull(t) - op_stack.ActL1Finalized(t) + optimism.sequencer.ActL2PipelineFull(t) + optimism.ActL1Finalized(t) // assert that EigenDA proxy's was written and read from diff --git a/e2e/server_test.go b/e2e/server_test.go index 1c4986a6..6cb1b439 100644 --- a/e2e/server_test.go +++ b/e2e/server_test.go @@ -1,15 +1,11 @@ package e2e_test import ( - "fmt" "strings" - "sync" "testing" - "time" "github.com/Layr-Labs/eigenda-proxy/client" "github.com/Layr-Labs/eigenda-proxy/e2e" - "github.com/Layr-Labs/eigenda-proxy/utils" op_plasma "github.com/ethereum-optimism/optimism/op-plasma" "github.com/stretchr/testify/require" ) @@ -154,78 +150,3 @@ func TestProxyClientWithOversizedBlob(t *testing.T) { require.True(t, oversizedError) } - -func TestProxyClient_MultiSameContentBlobs_SameBatch(t *testing.T) { - t.Skip("Skipping test until fix is applied to holesky") - - t.Parallel() - - ts, kill := e2e.CreateTestSuite(t, useMemory(), false) - defer kill() - - cfg := &client.Config{ - URL: ts.Address(), - } - - errChan := make(chan error, 10) - var wg sync.WaitGroup - - // disperse 10 blobs with the same content in the same batch - for i := 0; i < 4; i++ { - wg.Add(1) - go func() { - defer wg.Done() - daClient := client.New(cfg) - testPreimage := []byte("hellooooooooooo world!") - - t.Log("Setting input data on proxy server...") - blobInfo, err := daClient.SetData(ts.Ctx, testPreimage) - if err != nil { - errChan <- err - return - } - - t.Log("Getting input data from proxy server...") - preimage, err := daClient.GetData(ts.Ctx, blobInfo) - if err != nil { - errChan <- err - return - } - - if !utils.EqualSlices(preimage, testPreimage) { - errChan <- fmt.Errorf("expected preimage %s, got %s", testPreimage, preimage) - return - } - }() - } - - timedOut := waitTimeout(&wg, 10*time.Minute) - if timedOut { - t.Fatal("timed out waiting for parallel tests to complete") - } - - if len(errChan) > 0 { - // iterate over channel and log errors - for i := 0; i < len(errChan); i++ { - err := <-errChan - t.Log(err.Error()) - t.Fail() - } - } -} - -// waitTimeout waits for the waitgroup for the specified max timeout. -// Returns true if waiting timed out. -func waitTimeout(wg *sync.WaitGroup, timeout time.Duration) bool { - c := make(chan struct{}) - go func() { - defer close(c) - wg.Wait() - }() - select { - case <-c: - return false - case <-time.After(timeout): - return true - } -} diff --git a/e2e/setup.go b/e2e/setup.go index 68d2704d..7d23b3a4 100644 --- a/e2e/setup.go +++ b/e2e/setup.go @@ -38,7 +38,6 @@ type TestSuite struct { } func CreateTestSuite(t *testing.T, useMemory bool, useS3 bool) (TestSuite, func()) { - ctx := context.Background() // load signer key from environment @@ -78,7 +77,7 @@ func CreateTestSuite(t *testing.T, useMemory bool, useS3 bool) (TestSuite, func( SvcManagerAddr: "0xD4A7E1Bd8015057293f0D0A557088c286942e84b", // incompatible with non holeskly networks CacheDir: "../resources/SRSTables", G1Path: "../resources/g1.point", - MaxBlobLength: "2mib", + MaxBlobLength: "4mib", G2PowerOfTauPath: "../resources/g2.point.powerOf2", PutBlobEncodingVersion: 0x00, MemstoreEnabled: useMemory, @@ -110,17 +109,14 @@ func CreateTestSuite(t *testing.T, useMemory bool, useS3 bool) (TestSuite, func( }, } } else { - cfg = server.CLIConfig{ EigenDAConfig: eigendaCfg, MetricsCfg: opmetrics.CLIConfig{}, } - } - store, err := server.LoadStoreRouter( - cfg, ctx, + cfg, log, ) require.NoError(t, err) @@ -173,12 +169,12 @@ func createS3Bucket(bucketName string) { // Check to see if we already own this bucket (which happens if you run this twice) exists, errBucketExists := minioClient.BucketExists(ctx, bucketName) if errBucketExists == nil && exists { - fmt.Printf("We already own %s\n", bucketName) + log.Info(fmt.Sprintf("We already own %s\n", bucketName)) } else { panic(err) } } else { - fmt.Printf("Successfully created %s\n", bucketName) + log.Info(fmt.Sprintf("Successfully created %s\n", bucketName)) } } diff --git a/go.mod b/go.mod index fb692fb4..09c20fc7 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/Layr-Labs/eigenda-proxy go 1.21 require ( - github.com/Layr-Labs/eigenda v0.8.0 + github.com/Layr-Labs/eigenda v0.8.1-0.20240819231537-e4af079535b0 github.com/consensys/gnark-crypto v0.12.1 github.com/ethereum-optimism/optimism v1.9.0 github.com/ethereum/go-ethereum v1.14.0 diff --git a/go.sum b/go.sum index ddf9d2d5..0b3cb4e1 100644 --- a/go.sum +++ b/go.sum @@ -23,6 +23,8 @@ github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ= github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/Layr-Labs/eigenda v0.8.0 h1:OghLxQDLLJWrjPnGQ5Sykf/0n3tyOtAexdU+CNooK0I= github.com/Layr-Labs/eigenda v0.8.0/go.mod h1:Nsp+Z7OAQbPvCVq/xqrUies3wBEohKN4bb668CBYvcM= +github.com/Layr-Labs/eigenda v0.8.1-0.20240819231537-e4af079535b0 h1:Q40UqIDcgPZ1VY1tFbQ9kSNWrVxvH7U5GhT9QCRhSbg= +github.com/Layr-Labs/eigenda v0.8.1-0.20240819231537-e4af079535b0/go.mod h1:MzSFbxDQ1/tMcLlfxqz08YubB3rd+E2xme2p7hwP2YM= github.com/Layr-Labs/eigensdk-go v0.1.7-0.20240507215523-7e4891d5099a h1:L/UsJFw9M31FD/WgXTPFB0oxbq9Cu4Urea1xWPMQS7Y= github.com/Layr-Labs/eigensdk-go v0.1.7-0.20240507215523-7e4891d5099a/go.mod h1:OF9lmS/57MKxS0xpSpX0qHZl0SKkDRpvJIvsGvMN1y8= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= diff --git a/metrics/metrics.go b/metrics/metrics.go index 269311f9..5ab99c32 100644 --- a/metrics/metrics.go +++ b/metrics/metrics.go @@ -75,7 +75,6 @@ func NewMetrics(procName string) *Metrics { registry: registry, factory: factory, } - } // RecordInfo sets a pseudo-metric that contains versioning and @@ -113,7 +112,7 @@ func (n *noopMetricer) Document() []metrics.DocumentedMetric { return nil } -func (n *noopMetricer) RecordInfo(version string) { +func (n *noopMetricer) RecordInfo(_ string) { } func (n *noopMetricer) RecordUp() { diff --git a/server/config.go b/server/config.go index e9b93848..bfe8a5a0 100644 --- a/server/config.go +++ b/server/config.go @@ -22,7 +22,7 @@ const ( EthConfirmationDepthFlagName = "eigenda-eth-confirmation-depth" StatusQueryRetryIntervalFlagName = "eigenda-status-query-retry-interval" StatusQueryTimeoutFlagName = "eigenda-status-query-timeout" - DisableTlsFlagName = "eigenda-disable-tls" + DisableTLSFlagName = "eigenda-disable-tls" ResponseTimeoutFlagName = "eigenda-response-timeout" CustomQuorumIDsFlagName = "eigenda-custom-quorum-ids" SignerPrivateKeyHexFlagName = "eigenda-signer-private-key-hex" @@ -82,9 +82,9 @@ type Config struct { MemstoreBlobExpiration time.Duration } -func (c *Config) GetMaxBlobLength() (uint64, error) { - if c.maxBlobLengthBytes == 0 { - numBytes, err := utils.ParseBytesAmount(c.MaxBlobLength) +func (cfg *Config) GetMaxBlobLength() (uint64, error) { + if cfg.maxBlobLengthBytes == 0 { + numBytes, err := utils.ParseBytesAmount(cfg.MaxBlobLength) if err != nil { return 0, err } @@ -93,28 +93,28 @@ func (c *Config) GetMaxBlobLength() (uint64, error) { return 0, fmt.Errorf("excluding disperser constraints on max blob size, SRS points constrain the maxBlobLength configuration parameter to be less than than %d bytes", MaxAllowedBlobSize) } - c.maxBlobLengthBytes = numBytes + cfg.maxBlobLengthBytes = numBytes } - return c.maxBlobLengthBytes, nil + return cfg.maxBlobLengthBytes, nil } -func (c *Config) VerificationCfg() *verify.Config { - numBytes, err := c.GetMaxBlobLength() +func (cfg *Config) VerificationCfg() *verify.Config { + numBytes, err := cfg.GetMaxBlobLength() if err != nil { panic(fmt.Errorf("failed to read max blob length: %w", err)) } kzgCfg := &kzg.KzgConfig{ - G1Path: c.G1Path, - G2PowerOf2Path: c.G2PowerOfTauPath, - CacheDir: c.CacheDir, + G1Path: cfg.G1Path, + G2PowerOf2Path: cfg.G2PowerOfTauPath, + CacheDir: cfg.CacheDir, SRSOrder: 268435456, // 2 ^ 32 SRSNumberToLoad: numBytes / 32, // # of fp.Elements NumWorker: uint64(runtime.GOMAXPROCS(0)), } - if c.EthRPC == "" || c.SvcManagerAddr == "" { + if cfg.EthRPC == "" || cfg.SvcManagerAddr == "" { return &verify.Config{ Verify: false, KzgConfig: kzgCfg, @@ -123,12 +123,11 @@ func (c *Config) VerificationCfg() *verify.Config { return &verify.Config{ Verify: true, - RPCURL: c.EthRPC, - SvcManagerAddr: c.SvcManagerAddr, + RPCURL: cfg.EthRPC, + SvcManagerAddr: cfg.SvcManagerAddr, KzgConfig: kzgCfg, - EthConfirmationDepth: uint64(c.EthConfirmationDepth), + EthConfirmationDepth: uint64(cfg.EthConfirmationDepth), } - } // ReadConfig parses the Config from the provided flags or environment variables. @@ -146,7 +145,7 @@ func ReadConfig(ctx *cli.Context) Config { RPC: ctx.String(EigenDADisperserRPCFlagName), StatusQueryRetryInterval: ctx.Duration(StatusQueryRetryIntervalFlagName), StatusQueryTimeout: ctx.Duration(StatusQueryTimeoutFlagName), - DisableTLS: ctx.Bool(DisableTlsFlagName), + DisableTLS: ctx.Bool(DisableTLSFlagName), ResponseTimeout: ctx.Duration(ResponseTimeoutFlagName), CustomQuorumIDs: ctx.UintSlice(CustomQuorumIDsFlagName), SignerPrivateKeyHex: ctx.String(SignerPrivateKeyHexFlagName), @@ -241,7 +240,7 @@ func CLIFlags(envPrefix string) []cli.Flag { EnvVars: prefixEnvVars("STATUS_QUERY_INTERVAL"), }, &cli.BoolFlag{ - Name: DisableTlsFlagName, + Name: DisableTLSFlagName, Usage: "Disable TLS for gRPC communication with the EigenDA disperser. Default is false.", Value: false, EnvVars: prefixEnvVars("GRPC_DISABLE_TLS"), diff --git a/server/flags.go b/server/flags.go index f894d464..5c056ea4 100644 --- a/server/flags.go +++ b/server/flags.go @@ -48,7 +48,7 @@ func init() { optionalFlags = append(optionalFlags, oplog.CLIFlags(EnvVarPrefix)...) optionalFlags = append(optionalFlags, CLIFlags(EnvVarPrefix)...) optionalFlags = append(optionalFlags, opmetrics.CLIFlags(EnvVarPrefix)...) - Flags = append(requiredFlags, optionalFlags...) + Flags = append(requiredFlags, optionalFlags...) //nolint:gocritic // this is a global variable } // Flags contains the list of configuration options available to the binary. diff --git a/server/load_store.go b/server/load_store.go index af1c0398..fd208cfb 100644 --- a/server/load_store.go +++ b/server/load_store.go @@ -10,7 +10,7 @@ import ( "github.com/ethereum/go-ethereum/log" ) -func LoadStoreRouter(cfg CLIConfig, ctx context.Context, log log.Logger) (*store.Router, error) { +func LoadStoreRouter(ctx context.Context, cfg CLIConfig, log log.Logger) (*store.Router, error) { var err error var s3 *store.S3Store if cfg.S3Config.Bucket != "" && cfg.S3Config.Endpoint != "" { @@ -59,7 +59,6 @@ func LoadStoreRouter(cfg CLIConfig, ctx context.Context, log log.Logger) (*store } eigenda, err := store.NewEigenDAStore( - ctx, client, verifier, log, diff --git a/server/server.go b/server/server.go index a1be6e63..b344fb0a 100644 --- a/server/server.go +++ b/server/server.go @@ -45,7 +45,8 @@ type Server struct { listener net.Listener } -func NewServer(host string, port int, router *store.Router, log log.Logger, m metrics.Metricer) *Server { +func NewServer(host string, port int, router *store.Router, log log.Logger, + m metrics.Metricer) *Server { endpoint := net.JoinHostPort(host, strconv.Itoa(port)) return &Server{ m: m, @@ -62,7 +63,8 @@ func NewServer(host string, port int, router *store.Router, log log.Logger, m me } // WithMetrics is a middleware that records metrics for the route path. -func WithMetrics(handleFn func(http.ResponseWriter, *http.Request) error, m metrics.Metricer) func(http.ResponseWriter, *http.Request) error { +func WithMetrics(handleFn func(http.ResponseWriter, *http.Request) error, + m metrics.Metricer) func(http.ResponseWriter, *http.Request) error { return func(w http.ResponseWriter, r *http.Request) error { recordDur := m.RecordRPCServerRequest(r.URL.Path) defer recordDur() @@ -72,12 +74,13 @@ func WithMetrics(handleFn func(http.ResponseWriter, *http.Request) error, m metr } // WithLogging is a middleware that logs the request method and URL. -func WithLogging(handleFn func(http.ResponseWriter, *http.Request) error, log log.Logger) func(http.ResponseWriter, *http.Request) { +func WithLogging(handleFn func(http.ResponseWriter, *http.Request) error, + log log.Logger) func(http.ResponseWriter, *http.Request) { return func(w http.ResponseWriter, r *http.Request) { log.Info("request", "method", r.Method, "url", r.URL) err := handleFn(w, r) if err != nil { // #nosec G104 - w.Write([]byte(err.Error())) + w.Write([]byte(err.Error())) //nolint:errcheck // ignore error log.Error(err.Error()) } } @@ -139,13 +142,12 @@ func (svr *Server) Stop() error { } return nil } -func (svr *Server) Health(w http.ResponseWriter, r *http.Request) error { +func (svr *Server) Health(w http.ResponseWriter, _ *http.Request) error { w.WriteHeader(http.StatusOK) return nil } func (svr *Server) HandleGet(w http.ResponseWriter, r *http.Request) error { - ct, err := ReadCommitmentMode(r) if err != nil { svr.WriteBadRequest(w, invalidCommitmentMode) @@ -205,7 +207,6 @@ func (svr *Server) HandlePut(w http.ResponseWriter, r *http.Request) error { w.WriteHeader(http.StatusInternalServerError) return err } - } else { // without commitment, err = svr.router.PutWithoutKey(context.Background(), input) if err != nil { @@ -258,35 +259,33 @@ func (svr *Server) Port() int { func ReadCommitmentMode(r *http.Request) (commitments.CommitmentMode, error) { query := r.URL.Query() key := query.Get(CommitmentModeKey) - if key == "" { // default - commit := path.Base(r.URL.Path) - if len(commit) > 0 && commit != "put" { // provided commitment in request params - if !strings.HasPrefix(commit, "0x") { - commit = "0x" + commit - } + if key != "" { + return commitments.StringToCommitmentMode(key) + } - decodedCommit, err := hexutil.Decode(commit) - if err != nil { - return commitments.SimpleCommitmentMode, err - } + commit := path.Base(r.URL.Path) + if len(commit) > 0 && commit != "put" { // provided commitment in request params + if !strings.HasPrefix(commit, "0x") { + commit = "0x" + commit + } - switch decodedCommit[0] { - case byte(commitments.GenericCommitmentType): - return commitments.OptimismAltDA, nil + decodedCommit, err := hexutil.Decode(commit) + if err != nil { + return commitments.SimpleCommitmentMode, err + } - case byte(commitments.Keccak256CommitmentType): - return commitments.OptimismGeneric, nil + switch decodedCommit[0] { + case byte(commitments.GenericCommitmentType): + return commitments.OptimismAltDA, nil - default: - return commitments.SimpleCommitmentMode, fmt.Errorf("unknown commit byte prefix") + case byte(commitments.Keccak256CommitmentType): + return commitments.OptimismGeneric, nil - } + default: + return commitments.SimpleCommitmentMode, fmt.Errorf("unknown commit byte prefix") } - - return commitments.OptimismAltDA, nil } - - return commitments.StringToCommitmentMode(key) + return commitments.OptimismAltDA, nil } func (svr *Server) GetMemStats() *store.Stats { diff --git a/store/eigenda.go b/store/eigenda.go index bee0c90c..ee4cedb3 100644 --- a/store/eigenda.go +++ b/store/eigenda.go @@ -30,7 +30,8 @@ type EigenDAStore struct { var _ Store = (*EigenDAStore)(nil) -func NewEigenDAStore(ctx context.Context, client *clients.EigenDAClient, v *verify.Verifier, log log.Logger, cfg *EigenDAStoreConfig) (*EigenDAStore, error) { +func NewEigenDAStore(client *clients.EigenDAClient, + v *verify.Verifier, log log.Logger, cfg *EigenDAStoreConfig) (*EigenDAStore, error) { return &EigenDAStore{ client: client, verifier: v, @@ -67,7 +68,7 @@ func (e EigenDAStore) Get(ctx context.Context, key []byte) ([]byte, error) { } // Put disperses a blob for some pre-image and returns the associated RLP encoded certificate commit. -func (e EigenDAStore) Put(ctx context.Context, value []byte) (comm []byte, err error) { +func (e EigenDAStore) Put(ctx context.Context, value []byte) ([]byte, error) { encodedBlob, err := e.client.GetCodec().EncodeBlob(value) if err != nil { return nil, fmt.Errorf("EigenDA client failed to re-encode blob: %w", err) @@ -103,13 +104,13 @@ func (e EigenDAStore) Put(ctx context.Context, value []byte) (comm []byte, err e return nil, fmt.Errorf("timed out when trying to verify the DA certificate for a blob batch after dispersal") case <-ticker.C: err = e.verifier.VerifyCert(cert) - if err == nil { + switch { + case err == nil: done = true - - } else if !errors.Is(err, verify.ErrBatchMetadataHashNotFound) { - return nil, err - } else { + case errors.Is(err, verify.ErrBatchMetadataHashNotFound): e.log.Info("Blob confirmed, waiting for sufficient confirmation depth...", "targetDepth", e.cfg.EthConfirmationDepth) + default: + return nil, err } } } @@ -129,7 +130,7 @@ func (e EigenDAStore) Stats() *Stats { // Key is used to recover certificate fields and that verifies blob // against commitment to ensure data is valid and non-tampered. -func (e EigenDAStore) EncodeAndVerify(ctx context.Context, key []byte, value []byte) ([]byte, error) { +func (e EigenDAStore) EncodeAndVerify(key []byte, value []byte) ([]byte, error) { var cert verify.Certificate err := rlp.DecodeBytes(key, &cert) if err != nil { diff --git a/store/memory.go b/store/memory.go index 1c6924a4..3a21e862 100644 --- a/store/memory.go +++ b/store/memory.go @@ -42,7 +42,8 @@ type MemStore struct { var _ Store = (*MemStore)(nil) // NewMemStore ... constructor -func NewMemStore(ctx context.Context, verifier *verify.Verifier, l log.Logger, maxBlobSizeBytes uint64, blobExpiration time.Duration) (*MemStore, error) { +func NewMemStore(ctx context.Context, verifier *verify.Verifier, l log.Logger, + maxBlobSizeBytes uint64, blobExpiration time.Duration) (*MemStore, error) { store := &MemStore{ l: l, keyStarts: make(map[string]time.Time), @@ -88,12 +89,11 @@ func (e *MemStore) pruneExpired() { e.l.Info("blob pruned", "commit", commit) } } - } // Get fetches a value from the store. -func (e *MemStore) Get(ctx context.Context, commit []byte) ([]byte, error) { - e.reads += 1 +func (e *MemStore) Get(_ context.Context, commit []byte) ([]byte, error) { + e.reads++ e.RLock() defer e.RUnlock() @@ -119,7 +119,7 @@ func (e *MemStore) Get(ctx context.Context, commit []byte) ([]byte, error) { } // Put inserts a value into the store. -func (e *MemStore) Put(ctx context.Context, value []byte) ([]byte, error) { +func (e *MemStore) Put(_ context.Context, value []byte) ([]byte, error) { if uint64(len(value)) > e.maxBlobSizeBytes { return nil, fmt.Errorf("blob is larger than max blob size: blob length %d, max blob size %d", len(value), e.maxBlobSizeBytes) } diff --git a/store/router.go b/store/router.go index ea5fa56d..727372b2 100644 --- a/store/router.go +++ b/store/router.go @@ -29,7 +29,6 @@ func NewRouter(eigenda *EigenDAStore, mem *MemStore, s3 *S3Store, l log.Logger) } func (r *Router) Get(ctx context.Context, key []byte, cm commitments.CommitmentMode) ([]byte, error) { - switch cm { case commitments.OptimismGeneric: @@ -44,7 +43,8 @@ func (r *Router) Get(ctx context.Context, key []byte, cm commitments.CommitmentM } if actualHash := crypto.Keccak256(value); !utils.EqualSlices(actualHash, key) { - return nil, fmt.Errorf("expected key %s to be the hash of value %s, but got %s", hexutil.Encode(key), hexutil.Encode(value), hexutil.Encode(actualHash)) + return nil, fmt.Errorf("expected key %s to be the hash of value %s, but got %s", + hexutil.Encode(key), hexutil.Encode(value), hexutil.Encode(actualHash)) } return value, nil @@ -64,15 +64,13 @@ func (r *Router) Get(ctx context.Context, key []byte, cm commitments.CommitmentM return nil, err } r.log.Info("Got data from S3 now verifying") - return r.eigenda.EncodeAndVerify(ctx, key, value) + return r.eigenda.EncodeAndVerify(key, value) } return data, err default: return nil, errors.New("could not determine which storage backend to route to based on unknown commitment mode") - } - } func (r *Router) Put(ctx context.Context, cm commitments.CommitmentMode, key, value []byte) ([]byte, error) { @@ -86,48 +84,51 @@ func (r *Router) Put(ctx context.Context, cm commitments.CommitmentMode, key, va default: return nil, fmt.Errorf("unknown commitment mode") } +} +func (r *Router) putEigenDA(ctx context.Context, value []byte) ([]byte, error) { + r.log.Info("Storing data to eigenda backend") + result, err := r.eigenda.Put(ctx, value) + if err != nil { + return nil, err + } + + if r.s3 != nil && r.s3.cfg.Backup { + // we make a keccak of the commitment so that we get 32bytes (valid s3 key) + key := crypto.Keccak256(result) + r.log.Info("Storing data to S3 backend with key", "key", key) + ctx2, cancel := context.WithTimeout(ctx, r.s3.cfg.Timeout) + defer cancel() + err = r.s3.Put(ctx2, key, value) + if err != nil { + return nil, err + } + } + return result, err } // PutWithoutKey ... -func (r *Router) PutWithoutKey(ctx context.Context, value []byte) (key []byte, err error) { +func (r *Router) PutWithoutKey(ctx context.Context, value []byte) ([]byte, error) { if r.mem != nil { r.log.Debug("Storing data to memstore") return r.mem.Put(ctx, value) } if r.eigenda != nil { - r.log.Info("Storing data to eigenda backend") - //blob's commitment is verified and returned - result, err := r.eigenda.Put(ctx, value) - if err == nil { - if r.s3 != nil && r.s3.cfg.Backup { - //we make a keccak of the commitment so that we get 32bytes (valid s3 key) - key := crypto.Keccak256(result) - r.log.Info("Storing data to S3 backend with key", "key", key) - ctx2, cancel := context.WithTimeout(ctx, r.s3.cfg.Timeout) - defer cancel() - err = r.s3.Put(ctx2, key, value) - if err != nil { - return nil, err - } - } - } - return result, err + return r.putEigenDA(ctx, value) } if r.s3 != nil { r.log.Debug("Storing data to S3 backend") commitment := crypto.Keccak256(value) - err = r.s3.Put(ctx, commitment, value) + err := r.s3.Put(ctx, commitment, value) if err != nil { return nil, err } } return nil, errors.New("no DA storage backend found") - } // PutWithKey is only supported for S3 storage backends using OP's alt-da keccak256 commitment type diff --git a/store/s3.go b/store/s3.go index 56bf282f..063b3c4d 100644 --- a/store/s3.go +++ b/store/s3.go @@ -5,11 +5,12 @@ import ( "context" "encoding/hex" "errors" - "github.com/minio/minio-go/v7" "io" "path" "time" + "github.com/minio/minio-go/v7" + "github.com/minio/minio-go/v7/pkg/credentials" ) @@ -58,7 +59,6 @@ func NewS3(cfg S3Config) (*S3Store, error) { } func (s *S3Store) Get(ctx context.Context, key []byte) ([]byte, error) { - result, err := s.client.GetObject(ctx, s.cfg.Bucket, path.Join(s.cfg.Path, hex.EncodeToString(key)), minio.GetObjectOptions{}) if err != nil { errResponse := minio.ToErrorResponse(err) @@ -74,7 +74,7 @@ func (s *S3Store) Get(ctx context.Context, key []byte) ([]byte, error) { } if s.cfg.Profiling { - s.stats.Reads += 1 + s.stats.Reads++ } return data, nil @@ -87,7 +87,7 @@ func (s *S3Store) Put(ctx context.Context, key []byte, value []byte) error { } if s.cfg.Profiling { - s.stats.Entries += 1 + s.stats.Entries++ } return nil @@ -100,7 +100,6 @@ func (s *S3Store) Stats() *Stats { func creds(cfg S3Config) *credentials.Credentials { if cfg.S3CredentialType == S3CredentialIAM { return credentials.NewIAM("") - } else { - return credentials.NewStaticV4(cfg.AccessKeyID, cfg.AccessKeySecret, "") } + return credentials.NewStaticV4(cfg.AccessKeyID, cfg.AccessKeySecret, "") } diff --git a/utils/parse_bytes.go b/utils/parse_bytes.go index 5f9067d1..8a90119a 100644 --- a/utils/parse_bytes.go +++ b/utils/parse_bytes.go @@ -39,7 +39,7 @@ func ParseBytesAmount(s string) (uint64, error) { // Convert numeric part to float64 num, err := strconv.ParseFloat(numStr, 64) if err != nil { - return 0, fmt.Errorf("invalid numeric value: %v", err) + return 0, fmt.Errorf("invalid numeric value: %w", err) } unit = strings.ToLower(strings.TrimSpace(unit)) diff --git a/utils/parse_bytes_test.go b/utils/parse_bytes_test.go index aab53866..02177587 100644 --- a/utils/parse_bytes_test.go +++ b/utils/parse_bytes_test.go @@ -9,6 +9,7 @@ import ( func TestParseByteAmount(t *testing.T) { t.Parallel() + testCases := []struct { input string expected uint64 @@ -43,6 +44,8 @@ func TestParseByteAmount(t *testing.T) { for _, tc := range testCases { t.Run(fmt.Sprintf("Input: %s", tc.input), func(t *testing.T) { + t.Parallel() + got, err := utils.ParseBytesAmount(tc.input) if (err != nil) != tc.wantErr { t.Errorf("wantErr: %v, got error: %v", tc.wantErr, err) diff --git a/verify/cert.go b/verify/cert.go index 9a727dd4..33867471 100644 --- a/verify/cert.go +++ b/verify/cert.go @@ -35,7 +35,7 @@ func NewCertVerifier(cfg *Config, l log.Logger) (*CertVerifier, error) { return nil, fmt.Errorf("failed to dial ETH RPC node: %s", err.Error()) } - // construct binding + // construct caller binding m, err := binding.NewContractEigenDAServiceManagerCaller(common.HexToAddress(cfg.SvcManagerAddr), client) if err != nil { return nil, err @@ -49,16 +49,15 @@ func NewCertVerifier(cfg *Config, l log.Logger) (*CertVerifier, error) { }, nil } +// verifies on-chain batch ID for equivalence to certificate batch header fields func (cv *CertVerifier) VerifyBatch(header *binding.IEigenDAServiceManagerBatchHeader, id uint32, recordHash [32]byte, confirmationNumber uint32) error { - // 0 - Determine block context number blockNumber, err := cv.getContextBlock() if err != nil { return err } - // 1 - Verify batch hash - // 1.a - ensure that a batch hash can be looked up for a batch ID + // 1. ensure that a batch hash can be looked up for a batch ID for a given block number expectedHash, err := cv.manager.BatchIdToBatchMetadataHash(&bind.CallOpts{BlockNumber: blockNumber}, id) if err != nil { return err @@ -67,7 +66,7 @@ func (cv *CertVerifier) VerifyBatch(header *binding.IEigenDAServiceManagerBatchH return ErrBatchMetadataHashNotFound } - // 1.b - ensure that hash generated from local cert matches one stored on-chain + // 2. ensure that hash generated from local cert matches one stored on-chain actualHash, err := HashBatchMetadata(header, recordHash, confirmationNumber) if err != nil { @@ -82,8 +81,9 @@ func (cv *CertVerifier) VerifyBatch(header *binding.IEigenDAServiceManagerBatchH return nil } -// VerifyMerkleProof ... Verifies the blob batch inclusion proof against the blob root hash -func (cv *CertVerifier) VerifyMerkleProof(inclusionProof []byte, root []byte, blobIndex uint32, blobHeader BlobHeader) error { +// verifies the blob batch inclusion proof against the blob root hash +func (cv *CertVerifier) VerifyMerkleProof(inclusionProof []byte, root []byte, + blobIndex uint32, blobHeader BlobHeader) error { leafHash, err := HashEncodeBlobHeader(blobHeader) if err != nil { return err @@ -102,6 +102,7 @@ func (cv *CertVerifier) VerifyMerkleProof(inclusionProof []byte, root []byte, bl return nil } +// fetches a block number provided a subtraction of a user defined conf depth from latest block func (cv *CertVerifier) getContextBlock() (*big.Int, error) { var blockNumber *big.Int blockHeader, err := cv.ethClient.BlockByNumber(context.Background(), nil) diff --git a/verify/certificate.go b/verify/certificate.go index 54441a0a..ef2f09c7 100644 --- a/verify/certificate.go +++ b/verify/certificate.go @@ -1,16 +1,11 @@ package verify import ( - "fmt" "math/big" "github.com/Layr-Labs/eigenda/api/grpc/disperser" ) -var ( - ErrInvalidDomainType = fmt.Errorf("invalid domain type") -) - // G1Point struct to represent G1Point in Solidity type G1Point struct { X *big.Int diff --git a/verify/hasher.go b/verify/hasher.go index 70a4aae6..63bd9ed6 100644 --- a/verify/hasher.go +++ b/verify/hasher.go @@ -55,7 +55,7 @@ func HashBatchMetadata(bh *binding.IEigenDAServiceManagerBatchHeader, sigHash [3 bytes, err := arguments.Pack(s) if err != nil { - return [32]byte{}, nil + return [32]byte{}, err } headerHash := crypto.Keccak256Hash(bytes) @@ -65,7 +65,6 @@ func HashBatchMetadata(bh *binding.IEigenDAServiceManagerBatchHeader, sigHash [3 // HashBatchHashedMetadata hashes the given metadata into the commitment that will be stored in the contract // replicates: https://github.com/Layr-Labs/eigenda-utils/blob/c4cbc9ec078aeca3e4a04bd278e2fb136bf3e6de/src/libraries/EigenDAHasher.sol#L19-L25 func HashBatchHashedMetadata(batchHeaderHash [32]byte, signatoryRecordHash [32]byte, blockNumber uint32) (geth_common.Hash, error) { - // since the solidity function uses abi.encodePacked, we need to consolidate the byte space that // blockNum occupies to only 4 bytes versus 28 or 256 bits when encoded to abi buffer a := make([]byte, 4) @@ -98,7 +97,6 @@ func HashBatchHashedMetadata(batchHeaderHash [32]byte, signatoryRecordHash [32]b // HashBlobHeader function to hash BlobHeader func HashBlobHeader(blobHeader BlobHeader) (geth_common.Hash, error) { - blobHeaderType, err := abi.NewType("tuple", "", []abi.ArgumentMarshaling{ {Name: "commitment", Type: "tuple", Components: []abi.ArgumentMarshaling{ {Name: "X", Type: "uint256"}, diff --git a/verify/merkle.go b/verify/merkle.go index 3d8bc9b7..21757148 100644 --- a/verify/merkle.go +++ b/verify/merkle.go @@ -7,7 +7,7 @@ import ( "github.com/ethereum/go-ethereum/crypto" ) -// ProcessInclusionProof processes the Merkle proof +// ProcessInclusionProof processes the Merkle root proof func ProcessInclusionProof(proof []byte, leaf common.Hash, index uint64) (common.Hash, error) { if len(proof) == 0 || len(proof)%32 != 0 { return common.Hash{}, errors.New("proof length should be a multiple of 32 bytes or 256 bits") @@ -26,7 +26,7 @@ func ProcessInclusionProof(proof []byte, leaf common.Hash, index uint64) (common } computedHash = crypto.Keccak256Hash(combined) - index = index / 2 + index /= 2 } return computedHash, nil diff --git a/verify/verifier.go b/verify/verifier.go index 3c167568..58f2113d 100644 --- a/verify/verifier.go +++ b/verify/verifier.go @@ -53,6 +53,7 @@ func NewVerifier(cfg *Config, l log.Logger) (*Verifier, error) { }, nil } +// verifies V0 eigenda certificate type func (v *Verifier) VerifyCert(cert *Certificate) error { if !v.verifyCert { return nil @@ -86,6 +87,7 @@ func (v *Verifier) VerifyCert(cert *Certificate) error { return nil } +// compute kzg-bn254 commitment of raw blob data using SRS func (v *Verifier) Commit(blob []byte) (*bn254.G1Affine, error) { inputFr, err := rs.ToFrArray(blob) if err != nil { @@ -122,8 +124,8 @@ func (v *Verifier) VerifyCommitment(expectedCommit *common.G1Commitment, blob [] errMsg := "" if !actualCommit.X.Equal(expectedX) || !actualCommit.Y.Equal(expectedY) { - errMsg += fmt.Sprintf("field elements do not match, x actual commit: %x, x expected commit: %x, ", actualCommit.X.Marshal(), (*expectedX).Marshal()) - errMsg += fmt.Sprintf("y actual commit: %x, y expected commit: %x", actualCommit.Y.Marshal(), (*expectedY).Marshal()) + errMsg += fmt.Sprintf("field elements do not match, x actual commit: %x, x expected commit: %x, ", actualCommit.X.Marshal(), expectedX.Marshal()) + errMsg += fmt.Sprintf("y actual commit: %x, y expected commit: %x", actualCommit.Y.Marshal(), expectedY.Marshal()) return fmt.Errorf(errMsg) } @@ -132,7 +134,6 @@ func (v *Verifier) VerifyCommitment(expectedCommit *common.G1Commitment, blob [] // VerifySecurityParams ensures that returned security parameters are valid func (v *Verifier) VerifySecurityParams(blobHeader BlobHeader, batchHeader binding.IEigenDAServiceManagerBatchHeader) error { - confirmedQuorums := make(map[uint8]bool) // require that the security param in each blob is met From 7a4d5df1dbd579b36b76770b48cf66df166d5737 Mon Sep 17 00:00:00 2001 From: Ethen Pociask Date: Tue, 20 Aug 2024 04:44:38 -0400 Subject: [PATCH 05/12] chore: EigenDA V8 dep bump - consolidate linting actions --- .github/workflows/gosec.yml | 20 -------------------- .github/workflows/lint.yml | 20 ++++++++++++++++---- README.md | 2 +- 3 files changed, 17 insertions(+), 25 deletions(-) delete mode 100644 .github/workflows/gosec.yml diff --git a/.github/workflows/gosec.yml b/.github/workflows/gosec.yml deleted file mode 100644 index d6d7dac9..00000000 --- a/.github/workflows/gosec.yml +++ /dev/null @@ -1,20 +0,0 @@ -name: gosec - -on: - push: - branches: [ "main" ] - pull_request: - branches: [ "main" ] - -jobs: - go-sec: - runs-on: ubuntu-latest - env: - GO111MODULE: on - steps: - - name: Checkout Source - uses: actions/checkout@v3 - - name: Run Gosec Security Scanner - uses: securego/gosec@master - with: - args: ./... diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index c4c21664..92a474bd 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -1,10 +1,10 @@ -name: hygeiene +name: lint on: push: - branches: [ "master", "development" ] + branches: [ "main" ] pull_request: - branches: [ "master", "development" ] + branches: [ "main" ] jobs: golangci: @@ -18,4 +18,16 @@ jobs: uses: golangci/golangci-lint-action@v3 with: # Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version - version: v1.52.1 \ No newline at end of file + version: v1.52.1 + + go-sec: + runs-on: ubuntu-latest + env: + GO111MODULE: on + steps: + - name: Checkout Source + uses: actions/checkout@v3 + - name: Run Gosec Security Scanner + uses: securego/gosec@master + with: + args: ./... \ No newline at end of file diff --git a/README.md b/README.md index 34c64efd..b6bde35d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![Compiles](https://github.com/Layr-Labs/eigenda-proxy/actions/workflows/build.yml/badge.svg) ![Unit Tests](https://github.com/Layr-Labs/eigenda-proxy/actions/workflows/unit-tests.yml/badge.svg) -![Linter](https://github.com/Layr-Labs/eigenda-proxy/actions/workflows/gosec.yml/badge.svg) +![Linter](https://github.com/Layr-Labs/eigenda-proxy/actions/workflows/lint.yml/badge.svg) ![Integration Tests](https://github.com/Layr-Labs/eigenda-proxy/actions/workflows/holesky-test.yml/badge.svg) # EigenDA Sidecar Proxy From 525308d6bdc0b15659a7801b3257032d4fe388e1 Mon Sep 17 00:00:00 2001 From: Ethen Pociask Date: Tue, 20 Aug 2024 14:21:02 -0400 Subject: [PATCH 06/12] chore: EigenDA V8 dep bump - bump lint version --- .github/workflows/lint.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 92a474bd..e229f4f7 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -17,8 +17,7 @@ jobs: - name: golangci-lint uses: golangci/golangci-lint-action@v3 with: - # Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version - version: v1.52.1 + version: v6.1.0 go-sec: runs-on: ubuntu-latest From 3f07e19a5e3758a416e5875b532ec9f4e91369a4 Mon Sep 17 00:00:00 2001 From: Ethen Pociask Date: Tue, 20 Aug 2024 14:30:40 -0400 Subject: [PATCH 07/12] chore: EigenDA V8 dep bump - update to latest versoin --- .github/workflows/lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index e229f4f7..1a2d0fb2 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -17,7 +17,7 @@ jobs: - name: golangci-lint uses: golangci/golangci-lint-action@v3 with: - version: v6.1.0 + version: latest go-sec: runs-on: ubuntu-latest From e2aa42ccbafef49ec3964842af9497d05e212fc4 Mon Sep 17 00:00:00 2001 From: Ethen Pociask Date: Tue, 20 Aug 2024 15:47:52 -0400 Subject: [PATCH 08/12] chore: Update runners --- .github/workflows/lint.yml | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 1a2d0fb2..ad4e7dcb 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -7,17 +7,30 @@ on: branches: [ "main" ] jobs: - golangci: + lint: # Linting job # https://github.com/golangci/golangci-lint-action - name: lint + name: Lint runs-on: ubuntu-latest + steps: - - uses: actions/checkout@v3 - - name: golangci-lint - uses: golangci/golangci-lint-action@v3 - with: - version: latest + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Go + uses: actions/setup-go@v5 + with: + go-version: 1.21.x + cache: false # managed by golangci-lint + + - uses: golangci/golangci-lint-action@v3 + name: Install golangci-lint + with: + version: latest + args: --help # make lint will run the linter + + - run: make lint + name: Lint go-sec: runs-on: ubuntu-latest From aa6b4ab6680ce3b82d894188758c9f837e4d8215 Mon Sep 17 00:00:00 2001 From: Ethen Pociask Date: Tue, 20 Aug 2024 15:54:13 -0400 Subject: [PATCH 09/12] chore: Update lint install --- .github/workflows/lint.yml | 7 ++----- Makefile | 4 ++++ 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index ad4e7dcb..00cfc334 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -23,11 +23,8 @@ jobs: go-version: 1.21.x cache: false # managed by golangci-lint - - uses: golangci/golangci-lint-action@v3 - name: Install golangci-lint - with: - version: latest - args: --help # make lint will run the linter + - run: make install-lint + name: install linter - run: make lint name: Lint diff --git a/Makefile b/Makefile index bacd4805..489e755c 100644 --- a/Makefile +++ b/Makefile @@ -58,6 +58,10 @@ lint: @golangci-lint run +install-lint: + @echo "Installing golangci-lint..." + @sh -c $(GET_LINT_CMD) + gosec: @echo "Running security scan with gosec..." gosec ./... From 71b6a5a8551bc26b7cc47a0fccba929d3a6f6e5e Mon Sep 17 00:00:00 2001 From: Ethen Pociask Date: Tue, 20 Aug 2024 16:00:17 -0400 Subject: [PATCH 10/12] chore: Update lint install --- .github/workflows/lint.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 00cfc334..ad4e7dcb 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -23,8 +23,11 @@ jobs: go-version: 1.21.x cache: false # managed by golangci-lint - - run: make install-lint - name: install linter + - uses: golangci/golangci-lint-action@v3 + name: Install golangci-lint + with: + version: latest + args: --help # make lint will run the linter - run: make lint name: Lint From 3f3efdba18ce4fc3fb4d57440690381e99f0c5b4 Mon Sep 17 00:00:00 2001 From: Ethen Pociask Date: Tue, 20 Aug 2024 16:27:15 -0400 Subject: [PATCH 11/12] chore: Update lint install --- .github/workflows/lint.yml | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index ad4e7dcb..a6682db9 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -7,30 +7,23 @@ on: branches: [ "main" ] jobs: - lint: - # Linting job - # https://github.com/golangci/golangci-lint-action - name: Lint + golangci: + name: Linter runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Setup Go - uses: actions/setup-go@v5 - with: - go-version: 1.21.x - cache: false # managed by golangci-lint + - uses: actions/setup-go@v3 + with: + go-version: '1.21' # The Go version to download (if necessary) and use. + - run: go version - - uses: golangci/golangci-lint-action@v3 - name: Install golangci-lint - with: - version: latest - args: --help # make lint will run the linter + - name: Checkout EigenDA + uses: actions/checkout@v3 - - run: make lint - name: Lint + - name: golangci-lint + uses: golangci/golangci-lint-action@v3 + with: + version: v1.54 + args: --timeout 3m --verbose go-sec: runs-on: ubuntu-latest From 6240141805434904978ba684cf47786475ec53a0 Mon Sep 17 00:00:00 2001 From: Ethen Pociask Date: Tue, 20 Aug 2024 16:31:56 -0400 Subject: [PATCH 12/12] chore: rm gosec from lint cfg --- .golangci.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index f042c06d..f9d64eab 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -148,8 +148,6 @@ linters: - gofmt - gomodguard # allow and block lists linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations - goprintffuncname # checks that printf-like functions are named with f at the end - - gosec # inspects source code for security problems - # - lll # reports long lines - loggercheck # checks key value pairs for common logger libraries (kitlog,klog,logr,zap) - makezero # finds slice declarations with non-zero initial length - misspell # Ensures real english is used within strings