From 64492557b0d109e1fda53fd64175c5a7a640ddec Mon Sep 17 00:00:00 2001 From: litt3 <102969658+litt3@users.noreply.github.com> Date: Fri, 31 Jan 2025 16:06:22 -0500 Subject: [PATCH] Add builder Signed-off-by: litt3 <102969658+litt3@users.noreply.github.com> --- api/clients/v2/config.go | 81 ++++++++++++++++--- .../v2/distributed_payload_retriever.go | 63 ++++++++++++++- api/clients/v2/relay_payload_retriever.go | 24 +++--- .../v2/test/relay_payload_retriever_test.go | 4 +- api/clients/v2/verification/blob_verifier.go | 3 +- 5 files changed, 144 insertions(+), 31 deletions(-) diff --git a/api/clients/v2/config.go b/api/clients/v2/config.go index b0f77f2d97..f6b96666d4 100644 --- a/api/clients/v2/config.go +++ b/api/clients/v2/config.go @@ -45,13 +45,31 @@ type PayloadClientConfig struct { BlobVersion v2.BlobVersion } -// PayloadRetrieverConfig contains an embedded PayloadClientConfig, plus all additional configuration values needed -// by a PayloadRetriever -type PayloadRetrieverConfig struct { +// RelayPayloadRetrieverConfig contains an embedded PayloadClientConfig, plus all additional configuration values needed +// by a RelayPayloadRetriever +type RelayPayloadRetrieverConfig struct { PayloadClientConfig - // The timeout duration for calls to retrieve blobs. - FetchTimeout time.Duration + // The timeout duration for relay calls to retrieve blobs. + RelayTimeout time.Duration +} + +// DistributedPayloadRetrieverConfig contains an embedded PayloadClientConfig, plus all additional configuration values +// needed by a DistributedPayloadRetriever +type DistributedPayloadRetrieverConfig struct { + PayloadClientConfig + + // The timeout duration for calls to retrieve blobs from a given quorum. + RetrievalTimeout time.Duration + + // The address of the BlsOperatorStateRetriever contract + BlsOperatorStateRetrieverAddr string + + // The address of the EigenDAServiceManager contract + EigenDAServiceManagerAddr string + + // The number of simultaneous connections to use when fetching chunks during distributed retrieval + ConnectionCount uint } // PayloadDisperserConfig contains an embedded PayloadClientConfig, plus all additional configuration values needed @@ -125,13 +143,47 @@ func (cc *PayloadClientConfig) checkAndSetDefaults() error { return nil } -// GetDefaultPayloadRetrieverConfig creates a GetDefaultPayloadRetrieverConfig with default values +// GetDefaultRelayPayloadRetrieverConfig creates a RelayPayloadRetrieverConfig with default values // // NOTE: EthRpcUrl and EigenDACertVerifierAddr do not have defined defaults. These must always be specifically configured. -func GetDefaultPayloadRetrieverConfig() *PayloadRetrieverConfig { - return &PayloadRetrieverConfig{ +func GetDefaultRelayPayloadRetrieverConfig() *RelayPayloadRetrieverConfig { + return &RelayPayloadRetrieverConfig{ + PayloadClientConfig: *getDefaultPayloadClientConfig(), + RelayTimeout: 5 * time.Second, + } +} + +// checkAndSetDefaults checks an existing config struct and performs the following actions: +// +// 1. If a config value is 0, and a 0 value makes sense, do nothing. +// 2. If a config value is 0, but a 0 value doesn't make sense and a default value is defined, then set it to the default. +// 3. If a config value is 0, but a 0 value doesn't make sense and a default value isn't defined, return an error. +func (rc *RelayPayloadRetrieverConfig) checkAndSetDefaults() error { + err := rc.PayloadClientConfig.checkAndSetDefaults() + if err != nil { + return err + } + + defaultConfig := GetDefaultRelayPayloadRetrieverConfig() + if rc.RelayTimeout == 0 { + rc.RelayTimeout = defaultConfig.RelayTimeout + } + + return nil +} + +// GetDefaultDistributedPayloadRetrieverConfig creates a DistributedPayloadRetrieverConfig with default values +// +// NOTE: The following fields do not have defined defaults and must always be specifically configured: +// - EthRpcUrl +// - EigenDACertVerifierAddr +// - BlsOperatorStateRetrieverAddr +// - EigenDAServiceManagerAddr +func GetDefaultDistributedPayloadRetrieverConfig() *DistributedPayloadRetrieverConfig { + return &DistributedPayloadRetrieverConfig{ PayloadClientConfig: *getDefaultPayloadClientConfig(), - FetchTimeout: 5 * time.Second, + RetrievalTimeout: 20 * time.Second, + ConnectionCount: 10, } } @@ -140,15 +192,18 @@ func GetDefaultPayloadRetrieverConfig() *PayloadRetrieverConfig { // 1. If a config value is 0, and a 0 value makes sense, do nothing. // 2. If a config value is 0, but a 0 value doesn't make sense and a default value is defined, then set it to the default. // 3. If a config value is 0, but a 0 value doesn't make sense and a default value isn't defined, return an error. -func (rc *PayloadRetrieverConfig) checkAndSetDefaults() error { +func (rc *DistributedPayloadRetrieverConfig) checkAndSetDefaults() error { err := rc.PayloadClientConfig.checkAndSetDefaults() if err != nil { return err } - defaultConfig := GetDefaultPayloadRetrieverConfig() - if rc.FetchTimeout == 0 { - rc.FetchTimeout = defaultConfig.FetchTimeout + defaultConfig := GetDefaultDistributedPayloadRetrieverConfig() + if rc.RetrievalTimeout == 0 { + rc.RetrievalTimeout = defaultConfig.RetrievalTimeout + } + if rc.ConnectionCount == 0 { + rc.ConnectionCount = defaultConfig.ConnectionCount } return nil diff --git a/api/clients/v2/distributed_payload_retriever.go b/api/clients/v2/distributed_payload_retriever.go index 528435fd2a..f3f8e8bdba 100644 --- a/api/clients/v2/distributed_payload_retriever.go +++ b/api/clients/v2/distributed_payload_retriever.go @@ -6,11 +6,17 @@ import ( "github.com/Layr-Labs/eigenda/api/clients/codecs" "github.com/Layr-Labs/eigenda/api/clients/v2/verification" + "github.com/Layr-Labs/eigenda/common/geth" "github.com/Layr-Labs/eigenda/core" + "github.com/Layr-Labs/eigenda/core/eth" + "github.com/Layr-Labs/eigenda/core/thegraph" corev2 "github.com/Layr-Labs/eigenda/core/v2" "github.com/Layr-Labs/eigenda/encoding" + "github.com/Layr-Labs/eigenda/encoding/kzg" + "github.com/Layr-Labs/eigenda/encoding/kzg/verifier" "github.com/Layr-Labs/eigensdk-go/logging" "github.com/consensys/gnark-crypto/ecc/bn254" + gethcommon "github.com/ethereum/go-ethereum/common" ) // DistributedPayloadRetriever provides the ability to get payloads from the EigenDA nodes directly @@ -18,7 +24,7 @@ import ( // This struct is goroutine safe. type DistributedPayloadRetriever struct { logger logging.Logger - config PayloadRetrieverConfig + config DistributedPayloadRetrieverConfig codec codecs.BlobCodec retrievalClient RetrievalClient g1Srs []bn254.G1Affine @@ -26,6 +32,59 @@ type DistributedPayloadRetriever struct { var _ PayloadRetriever = &DistributedPayloadRetriever{} +// TODO: add basic constructor + +// BuildDistributedPayloadRetriever builds a DistributedPayloadRetriever from config structs. +func BuildDistributedPayloadRetriever( + logger logging.Logger, + distributedPayloadRetrieverConfig DistributedPayloadRetrieverConfig, + ethConfig geth.EthClientConfig, + thegraphConfig thegraph.Config, + kzgConfig kzg.KzgConfig, +) (*DistributedPayloadRetriever, error) { + + ethClient, err := geth.NewClient(ethConfig, gethcommon.Address{}, 0, logger) + if err != nil { + return nil, fmt.Errorf("new eth client: %w", err) + } + + reader, err := eth.NewReader( + logger, + ethClient, + distributedPayloadRetrieverConfig.BlsOperatorStateRetrieverAddr, + distributedPayloadRetrieverConfig.EigenDAServiceManagerAddr) + + chainState := eth.NewChainState(reader, ethClient) + indexedChainState := thegraph.MakeIndexedChainState(thegraphConfig, chainState, logger) + + kzgVerifier, err := verifier.NewVerifier(&kzgConfig, nil) + if err != nil { + return nil, fmt.Errorf("new verifier: %w", err) + } + + retrievalClient := NewRetrievalClient( + logger, + reader, + indexedChainState, + kzgVerifier, + int(distributedPayloadRetrieverConfig.ConnectionCount)) + + codec, err := codecs.CreateCodec( + distributedPayloadRetrieverConfig.PayloadPolynomialForm, + distributedPayloadRetrieverConfig.BlobEncodingVersion) + if err != nil { + return nil, err + } + + return &DistributedPayloadRetriever{ + logger: logger, + config: distributedPayloadRetrieverConfig, + codec: codec, + retrievalClient: retrievalClient, + g1Srs: kzgVerifier.Srs.G1, + }, nil +} + // GetPayload iteratively attempts to retrieve a given blob from the quorums listed in the EigenDACert. // // If the blob is successfully retrieved, then the blob is verified. If the verification succeeds, the blob is decoded @@ -103,7 +162,7 @@ func (pr *DistributedPayloadRetriever) getBlobWithTimeout( referenceBlockNumber uint32, quorumID core.QuorumID) ([]byte, error) { - timeoutCtx, cancel := context.WithTimeout(ctx, pr.config.FetchTimeout) + timeoutCtx, cancel := context.WithTimeout(ctx, pr.config.RetrievalTimeout) defer cancel() return pr.retrievalClient.GetBlob( diff --git a/api/clients/v2/relay_payload_retriever.go b/api/clients/v2/relay_payload_retriever.go index bee46e0efb..1ae715671d 100644 --- a/api/clients/v2/relay_payload_retriever.go +++ b/api/clients/v2/relay_payload_retriever.go @@ -24,7 +24,7 @@ type RelayPayloadRetriever struct { // Not all methods on Rand are guaranteed goroutine safe: if additional usages of random are added, they // must be evaluated for thread safety. random *rand.Rand - config PayloadRetrieverConfig + config RelayPayloadRetrieverConfig codec codecs.BlobCodec relayClient RelayClient g1Srs []bn254.G1Affine @@ -36,7 +36,7 @@ var _ PayloadRetriever = &RelayPayloadRetriever{} // BuildRelayPayloadRetriever builds a RelayPayloadRetriever from config structs. func BuildRelayPayloadRetriever( log logging.Logger, - payloadRetrieverConfig PayloadRetrieverConfig, + relayPayloadRetrieverConfig RelayPayloadRetrieverConfig, ethConfig geth.EthClientConfig, relayClientConfig *RelayClientConfig, g1Srs []bn254.G1Affine) (*RelayPayloadRetriever, error) { @@ -51,14 +51,14 @@ func BuildRelayPayloadRetriever( return nil, fmt.Errorf("new eth client: %w", err) } - certVerifier, err := verification.NewCertVerifier(*ethClient, payloadRetrieverConfig.EigenDACertVerifierAddr) + certVerifier, err := verification.NewCertVerifier(*ethClient, relayPayloadRetrieverConfig.EigenDACertVerifierAddr) if err != nil { return nil, fmt.Errorf("new cert verifier: %w", err) } codec, err := codecs.CreateCodec( - payloadRetrieverConfig.PayloadPolynomialForm, - payloadRetrieverConfig.BlobEncodingVersion) + relayPayloadRetrieverConfig.PayloadPolynomialForm, + relayPayloadRetrieverConfig.BlobEncodingVersion) if err != nil { return nil, err } @@ -66,7 +66,7 @@ func BuildRelayPayloadRetriever( return NewRelayPayloadRetriever( log, rand.New(rand.NewSource(rand.Int63())), - payloadRetrieverConfig, + relayPayloadRetrieverConfig, relayClient, certVerifier, codec, @@ -77,21 +77,21 @@ func BuildRelayPayloadRetriever( func NewRelayPayloadRetriever( log logging.Logger, random *rand.Rand, - payloadRetrieverConfig PayloadRetrieverConfig, + relayPayloadRetrieverConfig RelayPayloadRetrieverConfig, relayClient RelayClient, certVerifier verification.ICertVerifier, codec codecs.BlobCodec, g1Srs []bn254.G1Affine) (*RelayPayloadRetriever, error) { - err := payloadRetrieverConfig.checkAndSetDefaults() + err := relayPayloadRetrieverConfig.checkAndSetDefaults() if err != nil { - return nil, fmt.Errorf("check and set RelayPayloadRetrieverConfig config: %w", err) + return nil, fmt.Errorf("check and set RelayRelayPayloadRetrieverConfig config: %w", err) } return &RelayPayloadRetriever{ log: log, random: random, - config: payloadRetrieverConfig, + config: relayPayloadRetrieverConfig, codec: codec, relayClient: relayClient, certVerifier: certVerifier, @@ -187,7 +187,7 @@ func (pr *RelayPayloadRetriever) getBlobWithTimeout( relayKey core.RelayKey, blobKey *core.BlobKey) ([]byte, error) { - timeoutCtx, cancel := context.WithTimeout(ctx, pr.config.FetchTimeout) + timeoutCtx, cancel := context.WithTimeout(ctx, pr.config.RelayTimeout) defer cancel() return pr.relayClient.GetBlob(timeoutCtx, relayKey, *blobKey) @@ -195,7 +195,7 @@ func (pr *RelayPayloadRetriever) getBlobWithTimeout( // verifyCertWithTimeout verifies an EigenDACert by making a call to VerifyCertV2. // -// This method times out after the duration configured in relayPayloadRetrieverConfig.ContractCallTimeout +// This method times out after the duration configured in RelayPayloadRetrieverConfig.ContractCallTimeout func (pr *RelayPayloadRetriever) verifyCertWithTimeout( ctx context.Context, eigenDACert *verification.EigenDACert, diff --git a/api/clients/v2/test/relay_payload_retriever_test.go b/api/clients/v2/test/relay_payload_retriever_test.go index 970daccb0b..3b5fa3ceb5 100644 --- a/api/clients/v2/test/relay_payload_retriever_test.go +++ b/api/clients/v2/test/relay_payload_retriever_test.go @@ -50,9 +50,9 @@ func buildRelayPayloadRetrieverTester(t *testing.T) RelayPayloadRetrieverTester EigenDACertVerifierAddr: "y", } - clientConfig := clients.PayloadRetrieverConfig{ + clientConfig := clients.RelayPayloadRetrieverConfig{ PayloadClientConfig: payloadClientConfig, - FetchTimeout: 50 * time.Millisecond, + RelayTimeout: 50 * time.Millisecond, } mockRelayClient := clientsmock.MockRelayClient{} diff --git a/api/clients/v2/verification/blob_verifier.go b/api/clients/v2/verification/blob_verifier.go index 003f378b45..969812a3e3 100644 --- a/api/clients/v2/verification/blob_verifier.go +++ b/api/clients/v2/verification/blob_verifier.go @@ -14,8 +14,7 @@ import ( // If verification succeeds, the method returns nil. Otherwise, it returns an error. // // TODO: in the future, this will be optimized to use fiat shamir transformation for verification, rather than -// -// regenerating the commitment: https://github.com/Layr-Labs/eigenda/issues/1037 +// regenerating the commitment: https://github.com/Layr-Labs/eigenda/issues/1037 func VerifyBlobAgainstCert( blobKey *core.BlobKey, blobBytes []byte,