Skip to content

Commit

Permalink
Add builder
Browse files Browse the repository at this point in the history
Signed-off-by: litt3 <[email protected]>
  • Loading branch information
litt3 committed Jan 31, 2025
1 parent d3ef6de commit 6449255
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 31 deletions.
81 changes: 68 additions & 13 deletions api/clients/v2/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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,
}
}

Expand All @@ -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 {

Check failure on line 195 in api/clients/v2/config.go

View workflow job for this annotation

GitHub Actions / Linter

func `(*DistributedPayloadRetrieverConfig).checkAndSetDefaults` is unused (unused)

Check failure on line 195 in api/clients/v2/config.go

View workflow job for this annotation

GitHub Actions / Linter

func `(*DistributedPayloadRetrieverConfig).checkAndSetDefaults` is unused (unused)
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
Expand Down
63 changes: 61 additions & 2 deletions api/clients/v2/distributed_payload_retriever.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,85 @@ 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
//
// This struct is goroutine safe.
type DistributedPayloadRetriever struct {
logger logging.Logger
config PayloadRetrieverConfig
config DistributedPayloadRetrieverConfig
codec codecs.BlobCodec
retrievalClient RetrievalClient
g1Srs []bn254.G1Affine
}

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(

Check failure on line 51 in api/clients/v2/distributed_payload_retriever.go

View workflow job for this annotation

GitHub Actions / Linter

ineffectual assignment to err (ineffassign)

Check failure on line 51 in api/clients/v2/distributed_payload_retriever.go

View workflow job for this annotation

GitHub Actions / Linter

ineffectual assignment to err (ineffassign)
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
Expand Down Expand Up @@ -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(
Expand Down
24 changes: 12 additions & 12 deletions api/clients/v2/relay_payload_retriever.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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) {
Expand All @@ -51,22 +51,22 @@ 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
}

return NewRelayPayloadRetriever(
log,
rand.New(rand.NewSource(rand.Int63())),
payloadRetrieverConfig,
relayPayloadRetrieverConfig,
relayClient,
certVerifier,
codec,
Expand All @@ -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,
Expand Down Expand Up @@ -187,15 +187,15 @@ 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)
}

// 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,
Expand Down
4 changes: 2 additions & 2 deletions api/clients/v2/test/relay_payload_retriever_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{}
Expand Down
3 changes: 1 addition & 2 deletions api/clients/v2/verification/blob_verifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down

0 comments on commit 6449255

Please sign in to comment.