Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion api/clients/v2/payload_client_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,17 @@ type PayloadClientConfig struct {
//
// BlobVersion needs to point to a version defined in the threshold registry contract.
// https://github.com/Layr-Labs/eigenda/blob/3ed9ef6ed3eb72c46ce3050eb84af28f0afdfae2/contracts/src/interfaces/IEigenDAThresholdRegistry.sol#L6
//
// Version > 0 signals to the disperser that anchor signatures are required, preventing replay attacks.
// Since the blob key includes the version, an attacker cannot strip the anchor signature and replay
// the request as version=0.
BlobVersion v2.BlobVersion
}

// GetDefaultPayloadClientConfig creates a PayloadClientConfig with default values
func GetDefaultPayloadClientConfig() *PayloadClientConfig {
return &PayloadClientConfig{
PayloadPolynomialForm: codecs.PolynomialFormEval,
BlobVersion: 0,
BlobVersion: 1,
}
}
4 changes: 2 additions & 2 deletions api/proxy/config/v2/eigendaflags/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,10 +187,10 @@ func CLIFlags(envPrefix, category string) []cli.Flag {
&cli.UintFlag{
Name: BlobParamsVersionFlagName,
Usage: `Blob params version used when dispersing. This refers to a global version maintained by EigenDA
governance and is injected in the BlobHeader before dispersing. Currently only supports (0).`,
governance and is injected in the BlobHeader before dispersing.`,
EnvVars: []string{withEnvPrefix(envPrefix, "BLOB_PARAMS_VERSION")},
Category: category,
Value: uint(0),
Value: uint(1),
Required: false,
},
&cli.StringFlag{
Expand Down
4 changes: 2 additions & 2 deletions api/proxy/docs/help_out.txt
Original file line number Diff line number Diff line change
Expand Up @@ -131,11 +131,11 @@ GLOBAL OPTIONS:
--eigenda.v2.blob-status-poll-interval value (default: 1s) ($EIGENDA_PROXY_EIGENDA_V2_BLOB_STATUS_POLL_INTERVAL)
Duration to query for blob status updates during dispersal.

--eigenda.v2.blob-version value (default: 0) ($EIGENDA_PROXY_EIGENDA_V2_BLOB_PARAMS_VERSION)
--eigenda.v2.blob-version value (default: 1) ($EIGENDA_PROXY_EIGENDA_V2_BLOB_PARAMS_VERSION)
Blob params version used when dispersing. This refers to a global version
maintained by EigenDA
governance and is injected in the BlobHeader before
dispersing. Currently only supports (0).
dispersing.

--eigenda.v2.cert-verifier-router-or-immutable-verifier-addr value ($EIGENDA_PROXY_EIGENDA_V2_CERT_VERIFIER_ROUTER_OR_IMMUTABLE_VERIFIER_ADDR)
Address of either the EigenDACertVerifierRouter or immutable EigenDACertVerifier
Expand Down
21 changes: 15 additions & 6 deletions disperser/apiserver/disperse_blob_v2.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,12 +270,19 @@ func (s *DispersalServerV2) validateDispersalRequest(
//
// If DisableAnchorSignatureVerification is true, then this method will skip all validation and return nil.
//
// If TolerateMissingAnchorSignature is true, then this method will pass validation even if no anchor signature is
// provided in the request.
// Anchor signatures are required for blob version > 0. For blob version 0, missing anchor signatures are tolerated
// for backward compatibility with legacy clients.
//
// If an anchor signature is provided, it will be validated whether or not TolerateMissingAnchorSignature is true.
// If an anchor signature is provided, it will be validated regardless of blob version.
// While validating the anchor signature, this method will also verify that the disperser ID and chain ID in the request
// match the expected values.
//
// Version-based enforcement rationale:
// We co-opt the BlobVersion field to signal client capability. Without this, an attacker could strip the anchor
// signature from a request and replay it, since we can't reject unsigned requests outright (that would break legacy
// clients). By requiring anchor signatures for version > 0, the blob key hash changes, making it impossible to forge
// a valid version=0 signature from a version=1 request. This workaround is necessary since there isn't a "proper" blob
// version field included in the hash, so there are limited options available to communicate version compatibility.
func (s *DispersalServerV2) validateAnchorSignature(
req *pb.DisperseBlobRequest,
blobHeader *corev2.BlobHeader,
Expand All @@ -287,11 +294,13 @@ func (s *DispersalServerV2) validateAnchorSignature(
anchorSignature := req.GetAnchorSignature()

if len(anchorSignature) == 0 {
if s.serverConfig.TolerateMissingAnchorSignature {
return nil
if blobHeader.BlobVersion > 0 {
return fmt.Errorf("anchor signature is required for blob version > 0 (got version %d)",
blobHeader.BlobVersion)
}

return errors.New("anchor signature is required but not provided")
// Version 0: allow missing anchor signature for backward compatibility
return nil
}

if len(anchorSignature) != 65 {
Expand Down
6 changes: 5 additions & 1 deletion disperser/apiserver/server_v2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,11 @@ func newTestServerV2WithDeprecationFlag(t *testing.T, disableGetBlobCommitment b
CodingRate: 8,
MaxNumOperators: 2048,
},
1: {
NumChunks: 8192,
CodingRate: 8,
MaxNumOperators: 2048,
},
}, nil)

// Create listener for test server
Expand All @@ -584,7 +589,6 @@ func newTestServerV2WithDeprecationFlag(t *testing.T, disableGetBlobCommitment b
GrpcTimeout: 1 * time.Second,
DisableGetBlobCommitment: disableGetBlobCommitment,
DisperserId: 0,
TolerateMissingAnchorSignature: false,
DisableAnchorSignatureVerification: false,
},
time.Now,
Expand Down
9 changes: 1 addition & 8 deletions disperser/cmd/apiserver/flags/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -287,15 +287,9 @@ var (
Required: true,
EnvVar: common.PrefixEnvVar(envVarPrefix, "DISPERSER_ID"),
}
TolerateMissingAnchorSignatureFlag = cli.BoolTFlag{
Name: common.PrefixFlag(FlagPrefix, "tolerate-missing-anchor-signature"),
Usage: "Whether to accept DisperseBlob requests without an anchor signature. Ignored if disable-anchor-signature-verification is true.",
Required: false,
EnvVar: common.PrefixEnvVar(envVarPrefix, "TOLERATE_MISSING_ANCHOR_SIGNATURE"),
}
DisableAnchorSignatureVerificationFlag = cli.BoolFlag{
Name: common.PrefixFlag(FlagPrefix, "disable-anchor-signature-verification"),
Usage: "If true, anchor signature verification is skipped entirely. Takes precedence over tolerate-missing-anchor-signature.",
Usage: "If true, anchor signature verification is skipped entirely, regardless of blob version.",
Required: false,
EnvVar: common.PrefixEnvVar(envVarPrefix, "DISABLE_ANCHOR_SIGNATURE_VERIFICATION"),
}
Expand Down Expand Up @@ -371,7 +365,6 @@ var optionalFlags = []cli.Flag{
DisablePerAccountMetricsFlag,
SigningRateRetentionPeriodFlag,
SigningRatePollIntervalFlag,
TolerateMissingAnchorSignatureFlag,
DisableAnchorSignatureVerificationFlag,
OperatorStateRetrieverFlag,
EigenDAServiceManagerFlag,
Expand Down
1 change: 0 additions & 1 deletion disperser/cmd/apiserver/lib/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,6 @@ func NewConfig(ctx *cli.Context) (Config, error) {
SigningRateRetentionPeriod: ctx.GlobalDuration(flags.SigningRateRetentionPeriodFlag.Name),
SigningRatePollInterval: ctx.GlobalDuration(flags.SigningRatePollIntervalFlag.Name),
DisperserId: uint32(ctx.GlobalUint64(flags.DisperserIdFlag.Name)),
TolerateMissingAnchorSignature: ctx.GlobalBool(flags.TolerateMissingAnchorSignatureFlag.Name),
DisableAnchorSignatureVerification: ctx.GlobalBool(flags.DisableAnchorSignatureVerificationFlag.Name),
},
BlobstoreConfig: blobstore.Config{
Expand Down
10 changes: 0 additions & 10 deletions disperser/server_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,8 @@ type ServerConfig struct {
// Unique identifier for this disperser instance.
DisperserId uint32

// Whether to tolerate requests without an anchor signature.
// If false, DisperseBlob requests without an anchor_signature will be rejected.
// Ignored if DisableAnchorSignatureVerification is true.
// Default: true (for backwards compatibility with old client code during migration)
//
// TODO (litt3): this field should eventually be set to false, and then removed, once all clients have updated
// to a version that includes anchor signatures.
TolerateMissingAnchorSignature bool

// Whether to disable anchor signature verification entirely.
// If true, anchor signatures will not be verified even if present.
// Takes precedence over TolerateMissingAnchorSignature.
// Default: false
//
// TODO (litt3): This is a temporary flag to allow a second LayrLabs disperser to handle dispersal requests created
Expand Down
2 changes: 0 additions & 2 deletions inabox/deploy/env_vars.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions inabox/templates/testconfig-anvil-nochurner.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,14 @@ eigenda:
# NOTE: This uses a different blob version configuration than live deployments.
# Live deployments typically use higher coding rates (e.g., 8) with more chunks and operators.
# TODO: Investigate the revert that occurs when trying to use codingRate 2.
# Two blob versions are registered: version 0 for backward compatibility, version 1 as the new default.
blobVersions:
- codingRate: 8
numChunks: 16
maxNumOperators: 3
- codingRate: 8
numChunks: 16
maxNumOperators: 3

privateKeys:
ecdsaMap:
Expand Down
4 changes: 4 additions & 0 deletions inabox/templates/testconfig-anvil.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,14 @@ eigenda:
# NOTE: This uses a different blob version configuration than live deployments.
# Live deployments typically use higher coding rates (e.g., 8) with more chunks and operators.
# TODO: Investigate the revert that occurs when trying to use codingRate 2.
# Two blob versions are registered: version 0 for backward compatibility, version 1 as the new default.
blobVersions:
- codingRate: 8
numChunks: 16
maxNumOperators: 3
- codingRate: 8
numChunks: 16
maxNumOperators: 3

privateKeys:
ecdsaMap:
Expand Down
1 change: 0 additions & 1 deletion inabox/tests/setup_disperser_harness.go
Original file line number Diff line number Diff line change
Expand Up @@ -1220,7 +1220,6 @@ func startAPIServer(
MaxConnectionAgeGrace: 30 * time.Second,
MaxIdleConnectionAge: 1 * time.Minute,
DisperserId: 0,
TolerateMissingAnchorSignature: false,
DisableAnchorSignatureVerification: false,
}

Expand Down
Loading