diff --git a/api/clients/config.go b/api/clients/config.go index 096134e18..16d74742d 100644 --- a/api/clients/config.go +++ b/api/clients/config.go @@ -52,9 +52,10 @@ func (c *EigenDAClientConfig) CheckAndSetDefaults() error { if c.ResponseTimeout == 0 { c.ResponseTimeout = 30 * time.Second } - if len(c.SignerPrivateKeyHex) != 64 { - return fmt.Errorf("EigenDAClientConfig.SignerPrivateKeyHex should be 64 hex characters long, should not have 0x prefix") + if len(c.SignerPrivateKeyHex) > 0 && len(c.SignerPrivateKeyHex) != 64 { + return fmt.Errorf("a valid length SignerPrivateKeyHex needs to have 64 bytes") } + if len(c.RPC) == 0 { return fmt.Errorf("EigenDAClientConfig.RPC not set") } diff --git a/api/clients/disperser_client.go b/api/clients/disperser_client.go index 07af709c8..2c5e46a74 100644 --- a/api/clients/disperser_client.go +++ b/api/clients/disperser_client.go @@ -107,6 +107,32 @@ func (c *disperserClient) DisperseBlob(ctx context.Context, data []byte, quorums } func (c *disperserClient) DisperseBlobAuthenticated(ctx context.Context, data []byte, quorums []uint8) (*disperser.BlobStatus, []byte, error) { + if c.signer == nil { + return nil, nil, fmt.Errorf("uninitialized signer for authenticated dispersal") + } + + // first check if signer is valid + accountId, err := c.signer.GetAccountID() + if err != nil { + return nil, nil, fmt.Errorf("please configure signer key if you want to use authenticated endpoint %w", err) + } + + quorumNumbers := make([]uint32, len(quorums)) + for i, q := range quorums { + quorumNumbers[i] = uint32(q) + } + + // check every 32 bytes of data are within the valid range for a bn254 field element + _, err = rs.ToFrArray(data) + if err != nil { + return nil, nil, fmt.Errorf("encountered an error to convert a 32-bytes into a valid field element, please use the correct format where every 32bytes(big-endian) is less than 21888242871839275222246405745257275088548364400416034343698204186575808495617, %w", err) + } + + request := &disperser_rpc.DisperseBlobRequest{ + Data: data, + CustomQuorumNumbers: quorumNumbers, + AccountId: accountId, + } addr := fmt.Sprintf("%v:%v", c.config.Hostname, c.config.Port) @@ -128,22 +154,6 @@ func (c *disperserClient) DisperseBlobAuthenticated(ctx context.Context, data [] return nil, nil, fmt.Errorf("error while calling DisperseBlobAuthenticated: %w", err) } - quorumNumbers := make([]uint32, len(quorums)) - for i, q := range quorums { - quorumNumbers[i] = uint32(q) - } - - // check every 32 bytes of data are within the valid range for a bn254 field element - _, err = rs.ToFrArray(data) - if err != nil { - return nil, nil, fmt.Errorf("encountered an error to convert a 32-bytes into a valid field element, please use the correct format where every 32bytes(big-endian) is less than 21888242871839275222246405745257275088548364400416034343698204186575808495617, %w", err) - } - request := &disperser_rpc.DisperseBlobRequest{ - Data: data, - CustomQuorumNumbers: quorumNumbers, - AccountId: c.signer.GetAccountID(), - } - // Send the initial request err = stream.Send(&disperser_rpc.AuthenticatedRequest{Payload: &disperser_rpc.AuthenticatedRequest_DisperseRequest{ DisperseRequest: request, diff --git a/api/clients/eigenda_client.go b/api/clients/eigenda_client.go index c6141bd7d..cc7597f8c 100644 --- a/api/clients/eigenda_client.go +++ b/api/clients/eigenda_client.go @@ -10,6 +10,7 @@ import ( "github.com/Layr-Labs/eigenda/api/clients/codecs" grpcdisperser "github.com/Layr-Labs/eigenda/api/grpc/disperser" + "github.com/Layr-Labs/eigenda/core" "github.com/Layr-Labs/eigenda/core/auth" "github.com/Layr-Labs/eigenda/disperser" "github.com/ethereum/go-ethereum/log" @@ -41,7 +42,15 @@ func NewEigenDAClient(log log.Logger, config EigenDAClientConfig) (*EigenDAClien return nil, fmt.Errorf("failed to parse EigenDA RPC: %w", err) } - signer := auth.NewLocalBlobRequestSigner(config.SignerPrivateKeyHex) + var signer core.BlobRequestSigner + if len(config.SignerPrivateKeyHex) == 64 { + signer = auth.NewLocalBlobRequestSigner(config.SignerPrivateKeyHex) + } else if len(config.SignerPrivateKeyHex) == 0 { + signer = auth.NewLocalNoopSigner() + } else { + return nil, fmt.Errorf("invalid length for signer private key") + } + llConfig := NewConfig(host, port, config.ResponseTimeout, !config.DisableTLS) llClient := NewDisperserClient(llConfig, signer) diff --git a/api/clients/eigenda_client_test.go b/api/clients/eigenda_client_test.go index 41351158f..8b49fbbb6 100644 --- a/api/clients/eigenda_client_test.go +++ b/api/clients/eigenda_client_test.go @@ -11,6 +11,7 @@ import ( clientsmock "github.com/Layr-Labs/eigenda/api/clients/mock" "github.com/Layr-Labs/eigenda/api/grpc/common" grpcdisperser "github.com/Layr-Labs/eigenda/api/grpc/disperser" + "github.com/Layr-Labs/eigenda/core/auth" "github.com/Layr-Labs/eigenda/disperser" "github.com/ethereum/go-ethereum/log" "github.com/stretchr/testify/assert" @@ -505,3 +506,14 @@ func TestPutBlobTotalTimeout(t *testing.T) { require.Error(t, err) require.Nil(t, blobInfo) } + +func TestPutBlobNoopSigner(t *testing.T) { + config := clients.NewConfig("nohost", "noport", time.Second, false) + disperserClient := clients.NewDisperserClient(config, auth.NewLocalNoopSigner()) + + test := []byte("test") + test[0] = 0x00 // make sure the first byte of the requst is always 0 + quorums := []uint8{0} + _, _, err := disperserClient.DisperseBlobAuthenticated(context.Background(), test, quorums) + assert.EqualError(t, err, "please configure signer key if you want to use authenticated endpoint noop signer cannot get accountID") +} diff --git a/core/auth.go b/core/auth.go index 558cd834a..1348be4c9 100644 --- a/core/auth.go +++ b/core/auth.go @@ -6,5 +6,5 @@ type BlobRequestAuthenticator interface { type BlobRequestSigner interface { SignBlobRequest(header BlobAuthHeader) ([]byte, error) - GetAccountID() string + GetAccountID() (string, error) } diff --git a/core/auth/auth_test.go b/core/auth/auth_test.go index 80f318f2c..55c405f55 100644 --- a/core/auth/auth_test.go +++ b/core/auth/auth_test.go @@ -19,9 +19,12 @@ func TestAuthentication(t *testing.T) { privateKeyHex := "0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" signer := auth.NewLocalBlobRequestSigner(privateKeyHex) + accountId, err := signer.GetAccountID() + assert.NoError(t, err) + testHeader := core.BlobAuthHeader{ BlobCommitments: encoding.BlobCommitments{}, - AccountID: signer.GetAccountID(), + AccountID: accountId, Nonce: rand.Uint32(), AuthenticationData: []byte{}, } @@ -46,9 +49,12 @@ func TestAuthenticationFail(t *testing.T) { privateKeyHex := "0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" signer := auth.NewLocalBlobRequestSigner(privateKeyHex) + accountId, err := signer.GetAccountID() + assert.NoError(t, err) + testHeader := core.BlobAuthHeader{ BlobCommitments: encoding.BlobCommitments{}, - AccountID: signer.GetAccountID(), + AccountID: accountId, Nonce: rand.Uint32(), AuthenticationData: []byte{}, } @@ -66,3 +72,18 @@ func TestAuthenticationFail(t *testing.T) { assert.Error(t, err) } + +func TestNoopSignerFail(t *testing.T) { + signer := auth.NewLocalNoopSigner() + accountId, err := signer.GetAccountID() + assert.EqualError(t, err, "noop signer cannot get accountID") + + testHeader := core.BlobAuthHeader{ + BlobCommitments: encoding.BlobCommitments{}, + AccountID: accountId, + Nonce: rand.Uint32(), + AuthenticationData: []byte{}, + } + _, err = signer.SignBlobRequest(testHeader) + assert.EqualError(t, err, "noop signer cannot sign blob request") +} diff --git a/core/auth/signer.go b/core/auth/signer.go index 86632f379..015db23fc 100644 --- a/core/auth/signer.go +++ b/core/auth/signer.go @@ -47,9 +47,23 @@ func (s *LocalBlobRequestSigner) SignBlobRequest(header core.BlobAuthHeader) ([] return sig, nil } -func (s *LocalBlobRequestSigner) GetAccountID() string { +func (s *LocalBlobRequestSigner) GetAccountID() (string, error) { publicKeyBytes := crypto.FromECDSAPub(&s.PrivateKey.PublicKey) - return hexutil.Encode(publicKeyBytes) + return hexutil.Encode(publicKeyBytes), nil } + +type LocalNoopSigner struct{} + +func NewLocalNoopSigner() *LocalNoopSigner { + return &LocalNoopSigner{} +} + +func (s *LocalNoopSigner) SignBlobRequest(header core.BlobAuthHeader) ([]byte, error) { + return nil, fmt.Errorf("noop signer cannot sign blob request") +} + +func (s *LocalNoopSigner) GetAccountID() (string, error) { + return "", fmt.Errorf("noop signer cannot get accountID") +} diff --git a/disperser/apiserver/ratelimit_test.go b/disperser/apiserver/ratelimit_test.go index 69b3f9909..63bb02c72 100644 --- a/disperser/apiserver/ratelimit_test.go +++ b/disperser/apiserver/ratelimit_test.go @@ -225,12 +225,15 @@ func simulateClient(t *testing.T, signer core.BlobRequestSigner, origin string, stream.Close() }() - err := stream.SendFromClient(&pb.AuthenticatedRequest{ + accountId, err := signer.GetAccountID() + assert.NoError(t, err) + + err = stream.SendFromClient(&pb.AuthenticatedRequest{ Payload: &pb.AuthenticatedRequest_DisperseRequest{ DisperseRequest: &pb.DisperseBlobRequest{ Data: data, CustomQuorumNumbers: quorums, - AccountId: signer.GetAccountID(), + AccountId: accountId, }, }, })