From 8bf1fa0888bd59754b69d86df4a4b1ae8dac7c91 Mon Sep 17 00:00:00 2001 From: Cody Littley Date: Tue, 17 Dec 2024 11:07:41 -0600 Subject: [PATCH 1/8] DA nodes sign GetChunks() requests. Signed-off-by: Cody Littley --- api/clients/relay_client.go | 62 +++++++++++++++++++++++++---- inabox/tests/integration_v2_test.go | 3 +- node/node.go | 4 ++ node/node_v2_test.go | 3 +- relay/auth/authenticator.go | 6 --- 5 files changed, 62 insertions(+), 16 deletions(-) diff --git a/api/clients/relay_client.go b/api/clients/relay_client.go index f43d747ab8..56f53a4e4c 100644 --- a/api/clients/relay_client.go +++ b/api/clients/relay_client.go @@ -3,6 +3,8 @@ package clients import ( "context" "fmt" + "github.com/Layr-Labs/eigenda/core" + "github.com/Layr-Labs/eigenda/relay/auth" "sync" relaygrpc "github.com/Layr-Labs/eigenda/api/grpc/relay" @@ -12,9 +14,14 @@ import ( "google.golang.org/grpc" ) +// MessageSigner is a function that signs a message with a private BLS key. +type MessageSigner func(ctx context.Context, data [32]byte) (*core.Signature, error) + type RelayClientConfig struct { Sockets map[corev2.RelayKey]string UseSecureGrpcFlag bool + OperatorID core.OperatorID + MessageSigner MessageSigner } type ChunkRequestByRange struct { @@ -62,8 +69,10 @@ var _ RelayClient = (*relayClient)(nil) // NewRelayClient creates a new RelayClient that connects to the relays specified in the config. // It keeps a connection to each relay and reuses it for subsequent requests, and the connection is lazily instantiated. -func NewRelayClient(config *RelayClientConfig, logger logging.Logger) (*relayClient, error) { - if config == nil || len(config.Sockets) <= 0 { +func NewRelayClient(config *RelayClientConfig, logger logging.Logger) (RelayClient, error) { + + var zeroID core.OperatorID + if config == nil || len(config.Sockets) <= 0 || config.OperatorID == zeroID || config.MessageSigner == nil { return nil, fmt.Errorf("invalid config: %v", config) } @@ -97,7 +106,25 @@ func (c *relayClient) GetBlob(ctx context.Context, relayKey corev2.RelayKey, blo return res.GetBlob(), nil } -func (c *relayClient) GetChunksByRange(ctx context.Context, relayKey corev2.RelayKey, requests []*ChunkRequestByRange) ([][]byte, error) { +// signGetChunksRequest signs the GetChunksRequest with the operator's private key +// and sets the signature in the request. +func (c *relayClient) signGetChunksRequest(ctx context.Context, request *relaygrpc.GetChunksRequest) error { + hash := auth.HashGetChunksRequest(request) + hashArray := [32]byte{} + copy(hashArray[:], hash) + signature, err := c.config.MessageSigner(ctx, hashArray) + if err != nil { + return fmt.Errorf("failed to sign get chunks request: %v", err) + } + request.OperatorSignature = signature.Serialize() + return nil +} + +func (c *relayClient) GetChunksByRange( + ctx context.Context, + relayKey corev2.RelayKey, + requests []*ChunkRequestByRange) ([][]byte, error) { + if len(requests) == 0 { return nil, fmt.Errorf("no requests") } @@ -118,10 +145,17 @@ func (c *relayClient) GetChunksByRange(ctx context.Context, relayKey corev2.Rela }, } } - res, err := client.GetChunks(ctx, &relaygrpc.GetChunksRequest{ + + request := &relaygrpc.GetChunksRequest{ ChunkRequests: grpcRequests, - }) + OperatorId: c.config.OperatorID[:], + } + err = c.signGetChunksRequest(ctx, request) + if err != nil { + return nil, err + } + res, err := client.GetChunks(ctx, request) if err != nil { return nil, err } @@ -129,7 +163,11 @@ func (c *relayClient) GetChunksByRange(ctx context.Context, relayKey corev2.Rela return res.GetData(), nil } -func (c *relayClient) GetChunksByIndex(ctx context.Context, relayKey corev2.RelayKey, requests []*ChunkRequestByIndex) ([][]byte, error) { +func (c *relayClient) GetChunksByIndex( + ctx context.Context, + relayKey corev2.RelayKey, + requests []*ChunkRequestByIndex) ([][]byte, error) { + if len(requests) == 0 { return nil, fmt.Errorf("no requests") } @@ -150,9 +188,17 @@ func (c *relayClient) GetChunksByIndex(ctx context.Context, relayKey corev2.Rela }, } } - res, err := client.GetChunks(ctx, &relaygrpc.GetChunksRequest{ + + request := &relaygrpc.GetChunksRequest{ ChunkRequests: grpcRequests, - }) + OperatorId: c.config.OperatorID[:], + } + err = c.signGetChunksRequest(ctx, request) + if err != nil { + return nil, err + } + + res, err := client.GetChunks(ctx, request) if err != nil { return nil, err diff --git a/inabox/tests/integration_v2_test.go b/inabox/tests/integration_v2_test.go index 3a9f19b6b6..6c65313895 100644 --- a/inabox/tests/integration_v2_test.go +++ b/inabox/tests/integration_v2_test.go @@ -133,7 +133,8 @@ var _ = Describe("Inabox v2 Integration", func() { // Test retrieval from relay relayClient, err := clients.NewRelayClient(&clients.RelayClientConfig{ - Sockets: relays, + Sockets: relays, + OperatorID: nil, // TODO }, logger) Expect(err).To(BeNil()) ctx, cancel = context.WithTimeout(context.Background(), time.Second*5) diff --git a/node/node.go b/node/node.go index 1196c2c455..98b7d1271f 100644 --- a/node/node.go +++ b/node/node.go @@ -280,6 +280,8 @@ func NewNode( relayClient, err = clients.NewRelayClient(&clients.RelayClientConfig{ Sockets: relayURLs, UseSecureGrpcFlag: config.UseSecureGrpc, + OperatorID: config.ID, + MessageSigner: n.SignMessage, }, logger) if err != nil { @@ -460,6 +462,8 @@ func (n *Node) RefreshOnchainState(ctx context.Context) error { relayClient, err := clients.NewRelayClient(&clients.RelayClientConfig{ Sockets: relayURLs, UseSecureGrpcFlag: n.Config.UseSecureGrpc, + OperatorID: n.Config.ID, + MessageSigner: n.SignMessage, }, n.Logger) if err != nil { n.Logger.Error("error creating relay client", "err", err) diff --git a/node/node_v2_test.go b/node/node_v2_test.go index 14e1b0259b..d81a6ffc68 100644 --- a/node/node_v2_test.go +++ b/node/node_v2_test.go @@ -182,7 +182,8 @@ func TestRefreshOnchainStateSuccess(t *testing.T) { 0: "http://localhost:8080", } relayClient, err := clients.NewRelayClient(&clients.RelayClientConfig{ - Sockets: relayURLs, + Sockets: relayURLs, + OperatorID: c.node.Config.ID, }, c.node.Logger) require.NoError(t, err) // set up non-mock client diff --git a/relay/auth/authenticator.go b/relay/auth/authenticator.go index 8a47a48063..0264920bb0 100644 --- a/relay/auth/authenticator.go +++ b/relay/auth/authenticator.go @@ -4,7 +4,6 @@ import ( "context" "errors" "fmt" - "strings" "sync" "time" @@ -107,11 +106,6 @@ func (a *requestAuthenticator) AuthenticateGetChunksRequest( request *pb.GetChunksRequest, now time.Time) error { - if strings.HasPrefix(origin, "127.0.0.1") { - // TODO(ian-shim): Remove this block once we have a way to authenticate requests. - return nil - } - if a.isAuthenticationStillValid(now, origin) { // We've recently authenticated this client. Do not authenticate again for a while. return nil From 5ce2082c3477a17d5a0aabdc101698d7bff75c30 Mon Sep 17 00:00:00 2001 From: Cody Littley Date: Tue, 17 Dec 2024 12:06:49 -0600 Subject: [PATCH 2/8] checkin Signed-off-by: Cody Littley --- api/clients/relay_client.go | 10 +++++----- inabox/tests/integration_v2_test.go | 5 +++-- node/node.go | 4 ++-- node/node_v2_test.go | 10 ++++++++-- 4 files changed, 18 insertions(+), 11 deletions(-) diff --git a/api/clients/relay_client.go b/api/clients/relay_client.go index 56f53a4e4c..9100db2ded 100644 --- a/api/clients/relay_client.go +++ b/api/clients/relay_client.go @@ -20,7 +20,7 @@ type MessageSigner func(ctx context.Context, data [32]byte) (*core.Signature, er type RelayClientConfig struct { Sockets map[corev2.RelayKey]string UseSecureGrpcFlag bool - OperatorID core.OperatorID + OperatorID *core.OperatorID MessageSigner MessageSigner } @@ -70,9 +70,7 @@ var _ RelayClient = (*relayClient)(nil) // NewRelayClient creates a new RelayClient that connects to the relays specified in the config. // It keeps a connection to each relay and reuses it for subsequent requests, and the connection is lazily instantiated. func NewRelayClient(config *RelayClientConfig, logger logging.Logger) (RelayClient, error) { - - var zeroID core.OperatorID - if config == nil || len(config.Sockets) <= 0 || config.OperatorID == zeroID || config.MessageSigner == nil { + if config == nil || len(config.Sockets) <= 0 || config.OperatorID == nil || config.MessageSigner == nil { return nil, fmt.Errorf("invalid config: %v", config) } @@ -123,7 +121,9 @@ func (c *relayClient) signGetChunksRequest(ctx context.Context, request *relaygr func (c *relayClient) GetChunksByRange( ctx context.Context, relayKey corev2.RelayKey, - requests []*ChunkRequestByRange) ([][]byte, error) { + requests []*ChunkRequestByRange, + operatorID *core.OperatorID, + messageSigner MessageSigner) ([][]byte, error) { if len(requests) == 0 { return nil, fmt.Errorf("no requests") diff --git a/inabox/tests/integration_v2_test.go b/inabox/tests/integration_v2_test.go index 6c65313895..02c0564bc3 100644 --- a/inabox/tests/integration_v2_test.go +++ b/inabox/tests/integration_v2_test.go @@ -133,8 +133,9 @@ var _ = Describe("Inabox v2 Integration", func() { // Test retrieval from relay relayClient, err := clients.NewRelayClient(&clients.RelayClientConfig{ - Sockets: relays, - OperatorID: nil, // TODO + Sockets: relays, + //OperatorID: &dummyOperatorID, // TODO + //MessageSigner: nil, }, logger) Expect(err).To(BeNil()) ctx, cancel = context.WithTimeout(context.Background(), time.Second*5) diff --git a/node/node.go b/node/node.go index 98b7d1271f..9290e44f48 100644 --- a/node/node.go +++ b/node/node.go @@ -280,7 +280,7 @@ func NewNode( relayClient, err = clients.NewRelayClient(&clients.RelayClientConfig{ Sockets: relayURLs, UseSecureGrpcFlag: config.UseSecureGrpc, - OperatorID: config.ID, + OperatorID: &config.ID, MessageSigner: n.SignMessage, }, logger) @@ -462,7 +462,7 @@ func (n *Node) RefreshOnchainState(ctx context.Context) error { relayClient, err := clients.NewRelayClient(&clients.RelayClientConfig{ Sockets: relayURLs, UseSecureGrpcFlag: n.Config.UseSecureGrpc, - OperatorID: n.Config.ID, + OperatorID: &n.Config.ID, MessageSigner: n.SignMessage, }, n.Logger) if err != nil { diff --git a/node/node_v2_test.go b/node/node_v2_test.go index d81a6ffc68..8228548e21 100644 --- a/node/node_v2_test.go +++ b/node/node_v2_test.go @@ -181,9 +181,15 @@ func TestRefreshOnchainStateSuccess(t *testing.T) { relayURLs := map[v2.RelayKey]string{ 0: "http://localhost:8080", } + + messageSigner := func(ctx context.Context, data [32]byte) (*core.Signature, error) { + return nil, nil + } + relayClient, err := clients.NewRelayClient(&clients.RelayClientConfig{ - Sockets: relayURLs, - OperatorID: c.node.Config.ID, + Sockets: relayURLs, + OperatorID: &c.node.Config.ID, + MessageSigner: messageSigner, }, c.node.Logger) require.NoError(t, err) // set up non-mock client From 73583d8da3f6a8b54a2cf2646447e4ff15d4885d Mon Sep 17 00:00:00 2001 From: Cody Littley Date: Tue, 17 Dec 2024 12:33:00 -0600 Subject: [PATCH 3/8] Incremental changes. Signed-off-by: Cody Littley --- api/clients/relay_client.go | 4 +--- inabox/tests/integration_v2_test.go | 13 ++++++++++--- relay/server_test.go | 1 - 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/api/clients/relay_client.go b/api/clients/relay_client.go index 9100db2ded..68e6679c45 100644 --- a/api/clients/relay_client.go +++ b/api/clients/relay_client.go @@ -121,9 +121,7 @@ func (c *relayClient) signGetChunksRequest(ctx context.Context, request *relaygr func (c *relayClient) GetChunksByRange( ctx context.Context, relayKey corev2.RelayKey, - requests []*ChunkRequestByRange, - operatorID *core.OperatorID, - messageSigner MessageSigner) ([][]byte, error) { + requests []*ChunkRequestByRange) ([][]byte, error) { if len(requests) == 0 { return nil, fmt.Errorf("no requests") diff --git a/inabox/tests/integration_v2_test.go b/inabox/tests/integration_v2_test.go index 02c0564bc3..c9e7fb780d 100644 --- a/inabox/tests/integration_v2_test.go +++ b/inabox/tests/integration_v2_test.go @@ -131,11 +131,18 @@ var _ = Describe("Inabox v2 Integration", func() { } } + // These values are only used by the relay client to get chunks, which we do not call from the relay + // client below. So ok to use dummy values here. + var dummyOperatorID core.OperatorID + dummySigner := func(ctx context.Context, data [32]byte) (*core.Signature, error) { + return nil, nil + } + // Test retrieval from relay relayClient, err := clients.NewRelayClient(&clients.RelayClientConfig{ - Sockets: relays, - //OperatorID: &dummyOperatorID, // TODO - //MessageSigner: nil, + Sockets: relays, + OperatorID: &dummyOperatorID, + MessageSigner: dummySigner, }, logger) Expect(err).To(BeNil()) ctx, cancel = context.WithTimeout(context.Background(), time.Second*5) diff --git a/relay/server_test.go b/relay/server_test.go index 801ebeef87..ba0c7441ca 100644 --- a/relay/server_test.go +++ b/relay/server_test.go @@ -47,7 +47,6 @@ func defaultConfig() *Config { GetChunkBytesBurstinessClient: 2 * 1024 * 1024, MaxConcurrentGetChunkOpsClient: 1, }, - AuthenticationDisabled: true, Timeouts: TimeoutConfig{ GetBlobTimeout: 10 * time.Second, GetChunksTimeout: 10 * time.Second, From c818beec8c3cceb136849a0e6b83a9e8df5dd9bf Mon Sep 17 00:00:00 2001 From: Cody Littley Date: Tue, 17 Dec 2024 13:35:42 -0600 Subject: [PATCH 4/8] Fixed unit tests. Signed-off-by: Cody Littley --- relay/server_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/relay/server_test.go b/relay/server_test.go index ba0c7441ca..9521987163 100644 --- a/relay/server_test.go +++ b/relay/server_test.go @@ -30,6 +30,7 @@ func defaultConfig() *Config { ChunkCacheSize: 1024 * 1024, ChunkMaxConcurrency: 32, MaxKeysPerGetChunksRequest: 1024, + AuthenticationDisabled: true, RateLimits: limiter.Config{ MaxGetBlobOpsPerSecond: 1024, GetBlobOpsBurstiness: 1024, From a073a2825a7d2821016fd852e93696c4927aa8d9 Mon Sep 17 00:00:00 2001 From: Cody Littley Date: Wed, 18 Dec 2024 08:55:07 -0600 Subject: [PATCH 5/8] Made reccomended changes. Signed-off-by: Cody Littley --- api/clients/v2/relay_client.go | 10 ++++++- inabox/tests/integration_v2_test.go | 11 +------ relay/server_test.go | 46 ++++++++++++++++++++++++----- 3 files changed, 48 insertions(+), 19 deletions(-) diff --git a/api/clients/v2/relay_client.go b/api/clients/v2/relay_client.go index 68e6679c45..d6be360643 100644 --- a/api/clients/v2/relay_client.go +++ b/api/clients/v2/relay_client.go @@ -2,6 +2,7 @@ package clients import ( "context" + "errors" "fmt" "github.com/Layr-Labs/eigenda/core" "github.com/Layr-Labs/eigenda/relay/auth" @@ -70,7 +71,7 @@ var _ RelayClient = (*relayClient)(nil) // NewRelayClient creates a new RelayClient that connects to the relays specified in the config. // It keeps a connection to each relay and reuses it for subsequent requests, and the connection is lazily instantiated. func NewRelayClient(config *RelayClientConfig, logger logging.Logger) (RelayClient, error) { - if config == nil || len(config.Sockets) <= 0 || config.OperatorID == nil || config.MessageSigner == nil { + if config == nil || len(config.Sockets) <= 0 { return nil, fmt.Errorf("invalid config: %v", config) } @@ -107,6 +108,13 @@ func (c *relayClient) GetBlob(ctx context.Context, relayKey corev2.RelayKey, blo // signGetChunksRequest signs the GetChunksRequest with the operator's private key // and sets the signature in the request. func (c *relayClient) signGetChunksRequest(ctx context.Context, request *relaygrpc.GetChunksRequest) error { + if c.config.OperatorID == nil { + return errors.New("no operator ID provided in config, cannot sign get chunks request") + } + if c.config.MessageSigner == nil { + return errors.New("no message signer provided in config, cannot sign get chunks request") + } + hash := auth.HashGetChunksRequest(request) hashArray := [32]byte{} copy(hashArray[:], hash) diff --git a/inabox/tests/integration_v2_test.go b/inabox/tests/integration_v2_test.go index 8a78c9bf40..6f11b04292 100644 --- a/inabox/tests/integration_v2_test.go +++ b/inabox/tests/integration_v2_test.go @@ -135,18 +135,9 @@ var _ = Describe("Inabox v2 Integration", func() { } } - // These values are only used by the relay client to get chunks, which we do not call from the relay - // client below. So ok to use dummy values here. - var dummyOperatorID core.OperatorID - dummySigner := func(ctx context.Context, data [32]byte) (*core.Signature, error) { - return nil, nil - } - // Test retrieval from relay relayClient, err := clients.NewRelayClient(&clients.RelayClientConfig{ - Sockets: relays, - OperatorID: &dummyOperatorID, - MessageSigner: dummySigner, + Sockets: relays, }, logger) Expect(err).To(BeNil()) diff --git a/relay/server_test.go b/relay/server_test.go index 9521987163..1413c35f0c 100644 --- a/relay/server_test.go +++ b/relay/server_test.go @@ -2,6 +2,7 @@ package relay import ( "context" + "github.com/Layr-Labs/eigenda/core/mock" "math/rand" "testing" "time" @@ -30,7 +31,8 @@ func defaultConfig() *Config { ChunkCacheSize: 1024 * 1024, ChunkMaxConcurrency: 32, MaxKeysPerGetChunksRequest: 1024, - AuthenticationDisabled: true, + AuthenticationKeyCacheSize: 1024, + AuthenticationDisabled: false, RateLimits: limiter.Config{ MaxGetBlobOpsPerSecond: 1024, GetBlobOpsBurstiness: 1024, @@ -106,6 +108,10 @@ func TestReadWriteBlobs(t *testing.T) { blobStore := buildBlobStore(t, logger) chainReader := newMockChainReader() + ics, err := mock.NewChainDataMock(nil) + require.NoError(t, err) + ics.Mock.On("GetCurrentBlockNumber").Return(uint(0), nil) + // This is the server used to read it back config := defaultConfig() server, err := NewServer( @@ -116,7 +122,7 @@ func TestReadWriteBlobs(t *testing.T) { blobStore, nil, /* not used in this test*/ chainReader, - nil /* not used in this test*/) + ics) require.NoError(t, err) go func() { @@ -188,6 +194,10 @@ func TestReadNonExistentBlob(t *testing.T) { metadataStore := buildMetadataStore(t) blobStore := buildBlobStore(t, logger) + ics, err := mock.NewChainDataMock(nil) + require.NoError(t, err) + ics.Mock.On("GetCurrentBlockNumber").Return(uint(0), nil) + // This is the server used to read it back config := defaultConfig() chainReader := newMockChainReader() @@ -199,7 +209,7 @@ func TestReadNonExistentBlob(t *testing.T) { blobStore, nil, /* not used in this test */ chainReader, - nil /* not used in this test*/) + ics) require.NoError(t, err) go func() { @@ -245,6 +255,10 @@ func TestReadWriteBlobsWithSharding(t *testing.T) { } } + ics, err := mock.NewChainDataMock(nil) + require.NoError(t, err) + ics.Mock.On("GetCurrentBlockNumber").Return(uint(0), nil) + // This is the server used to read it back config := defaultConfig() config.RelayIDs = shardList @@ -257,7 +271,7 @@ func TestReadWriteBlobsWithSharding(t *testing.T) { blobStore, nil, /* not used in this test*/ chainReader, - nil /* not used in this test*/) + ics) require.NoError(t, err) go func() { @@ -365,6 +379,10 @@ func TestReadWriteChunks(t *testing.T) { metadataStore := buildMetadataStore(t) chunkReader, chunkWriter := buildChunkStore(t, logger) + ics, err := mock.NewChainDataMock(nil) + require.NoError(t, err) + ics.Mock.On("GetCurrentBlockNumber").Return(uint(0), nil) + // This is the server used to read it back config := defaultConfig() config.RateLimits.MaxGetChunkOpsPerSecond = 1000 @@ -380,7 +398,7 @@ func TestReadWriteChunks(t *testing.T) { nil, /* not used in this test*/ chunkReader, chainReader, - nil /* not used in this test*/) + ics) require.NoError(t, err) go func() { @@ -570,6 +588,10 @@ func TestBatchedReadWriteChunks(t *testing.T) { metadataStore := buildMetadataStore(t) chunkReader, chunkWriter := buildChunkStore(t, logger) + ics, err := mock.NewChainDataMock(nil) + require.NoError(t, err) + ics.Mock.On("GetCurrentBlockNumber").Return(uint(0), nil) + // This is the server used to read it back config := defaultConfig() chainReader := newMockChainReader() @@ -581,7 +603,7 @@ func TestBatchedReadWriteChunks(t *testing.T) { nil, /* not used in this test */ chunkReader, chainReader, - nil /* not used in this test*/) + ics) require.NoError(t, err) go func() { @@ -696,6 +718,10 @@ func TestReadWriteChunksWithSharding(t *testing.T) { } shardMap := make(map[v2.BlobKey][]v2.RelayKey) + ics, err := mock.NewChainDataMock(nil) + require.NoError(t, err) + ics.Mock.On("GetCurrentBlockNumber").Return(uint(0), nil) + // This is the server used to read it back config := defaultConfig() config.RelayIDs = shardList @@ -712,7 +738,7 @@ func TestReadWriteChunksWithSharding(t *testing.T) { nil, /* not used in this test*/ chunkReader, chainReader, - nil /* not used in this test*/) + ics) require.NoError(t, err) go func() { @@ -976,6 +1002,10 @@ func TestBatchedReadWriteChunksWithSharding(t *testing.T) { } shardMap := make(map[v2.BlobKey][]v2.RelayKey) + ics, err := mock.NewChainDataMock(nil) + require.NoError(t, err) + ics.Mock.On("GetCurrentBlockNumber").Return(uint(0), nil) + // This is the server used to read it back config := defaultConfig() config.RelayIDs = shardList @@ -992,7 +1022,7 @@ func TestBatchedReadWriteChunksWithSharding(t *testing.T) { nil, /* not used in this test */ chunkReader, chainReader, - nil /* not used in this test*/) + ics) require.NoError(t, err) go func() { From 8bf552b55c71e714b700a6724b98150811f7afd5 Mon Sep 17 00:00:00 2001 From: Cody Littley Date: Wed, 18 Dec 2024 09:31:20 -0600 Subject: [PATCH 6/8] Incremental progress. Signed-off-by: Cody Littley --- relay/mock/ics.go | 68 ++++++++++++++++++++++++++++++++++++++++++++ relay/server_test.go | 58 +++++++++++++++++++++++-------------- 2 files changed, 104 insertions(+), 22 deletions(-) create mode 100644 relay/mock/ics.go diff --git a/relay/mock/ics.go b/relay/mock/ics.go new file mode 100644 index 0000000000..d72bb5c5e9 --- /dev/null +++ b/relay/mock/ics.go @@ -0,0 +1,68 @@ +package mock + +import ( + "context" + "github.com/Layr-Labs/eigenda/core" + "github.com/stretchr/testify/mock" +) + +var _ core.IndexedChainState = (*IndexedChainState)(nil) + +// IndexedChainState is a mock implementation of core.IndexedChainState. +type IndexedChainState struct { + Mock mock.Mock +} + +func (m *IndexedChainState) GetCurrentBlockNumber() (uint, error) { + args := m.Mock.Called() + return args.Get(0).(uint), args.Error(1) +} + +func (m *IndexedChainState) GetOperatorState( + ctx context.Context, + blockNumber uint, + quorums []core.QuorumID) (*core.OperatorState, error) { + + args := m.Mock.Called(blockNumber, quorums) + return args.Get(0).(*core.OperatorState), args.Error(1) +} + +func (m *IndexedChainState) GetOperatorStateByOperator( + ctx context.Context, + blockNumber uint, + operator core.OperatorID) (*core.OperatorState, error) { + + args := m.Mock.Called(blockNumber, operator) + return args.Get(0).(*core.OperatorState), args.Error(1) +} + +func (m *IndexedChainState) GetOperatorSocket( + ctx context.Context, + blockNumber uint, + operator core.OperatorID) (string, error) { + + args := m.Mock.Called(blockNumber, operator) + return args.Get(0).(string), args.Error(1) +} + +func (m *IndexedChainState) GetIndexedOperatorState( + ctx context.Context, + blockNumber uint, + quorums []core.QuorumID) (*core.IndexedOperatorState, error) { + + args := m.Mock.Called(blockNumber, quorums) + return args.Get(0).(*core.IndexedOperatorState), args.Error(1) +} + +func (m *IndexedChainState) GetIndexedOperators( + ctx context.Context, + blockNumber uint) (map[core.OperatorID]*core.IndexedOperatorInfo, error) { + + args := m.Mock.Called(blockNumber) + return args.Get(0).(map[core.OperatorID]*core.IndexedOperatorInfo), args.Error(1) +} + +func (m *IndexedChainState) Start(context context.Context) error { + args := m.Mock.Called() + return args.Error(0) +} diff --git a/relay/server_test.go b/relay/server_test.go index 1413c35f0c..3e83f3bb1a 100644 --- a/relay/server_test.go +++ b/relay/server_test.go @@ -2,7 +2,7 @@ package relay import ( "context" - "github.com/Layr-Labs/eigenda/core/mock" + "github.com/Layr-Labs/eigenda/relay/mock" "math/rand" "testing" "time" @@ -108,9 +108,11 @@ func TestReadWriteBlobs(t *testing.T) { blobStore := buildBlobStore(t, logger) chainReader := newMockChainReader() - ics, err := mock.NewChainDataMock(nil) - require.NoError(t, err) - ics.Mock.On("GetCurrentBlockNumber").Return(uint(0), nil) + ics := &mock.IndexedChainState{} + blockNumber := uint(rand.Uint32()) + ics.Mock.On("GetCurrentBlockNumber").Return(blockNumber, nil) + operatorInfo := make(map[core.OperatorID]*core.IndexedOperatorInfo) + ics.Mock.On("GetIndexedOperators", blockNumber).Return(operatorInfo, nil) // This is the server used to read it back config := defaultConfig() @@ -194,9 +196,11 @@ func TestReadNonExistentBlob(t *testing.T) { metadataStore := buildMetadataStore(t) blobStore := buildBlobStore(t, logger) - ics, err := mock.NewChainDataMock(nil) - require.NoError(t, err) - ics.Mock.On("GetCurrentBlockNumber").Return(uint(0), nil) + ics := &mock.IndexedChainState{} + blockNumber := uint(rand.Uint32()) + ics.Mock.On("GetCurrentBlockNumber").Return(blockNumber, nil) + operatorInfo := make(map[core.OperatorID]*core.IndexedOperatorInfo) + ics.Mock.On("GetIndexedOperators", blockNumber).Return(operatorInfo, nil) // This is the server used to read it back config := defaultConfig() @@ -255,9 +259,11 @@ func TestReadWriteBlobsWithSharding(t *testing.T) { } } - ics, err := mock.NewChainDataMock(nil) - require.NoError(t, err) - ics.Mock.On("GetCurrentBlockNumber").Return(uint(0), nil) + ics := &mock.IndexedChainState{} + blockNumber := uint(rand.Uint32()) + ics.Mock.On("GetCurrentBlockNumber").Return(blockNumber, nil) + operatorInfo := make(map[core.OperatorID]*core.IndexedOperatorInfo) + ics.Mock.On("GetIndexedOperators", blockNumber).Return(operatorInfo, nil) // This is the server used to read it back config := defaultConfig() @@ -379,9 +385,11 @@ func TestReadWriteChunks(t *testing.T) { metadataStore := buildMetadataStore(t) chunkReader, chunkWriter := buildChunkStore(t, logger) - ics, err := mock.NewChainDataMock(nil) - require.NoError(t, err) - ics.Mock.On("GetCurrentBlockNumber").Return(uint(0), nil) + ics := &mock.IndexedChainState{} + blockNumber := uint(rand.Uint32()) + ics.Mock.On("GetCurrentBlockNumber").Return(blockNumber, nil) + operatorInfo := make(map[core.OperatorID]*core.IndexedOperatorInfo) + ics.Mock.On("GetIndexedOperators", blockNumber).Return(operatorInfo, nil) // This is the server used to read it back config := defaultConfig() @@ -588,9 +596,11 @@ func TestBatchedReadWriteChunks(t *testing.T) { metadataStore := buildMetadataStore(t) chunkReader, chunkWriter := buildChunkStore(t, logger) - ics, err := mock.NewChainDataMock(nil) - require.NoError(t, err) - ics.Mock.On("GetCurrentBlockNumber").Return(uint(0), nil) + ics := &mock.IndexedChainState{} + blockNumber := uint(rand.Uint32()) + ics.Mock.On("GetCurrentBlockNumber").Return(blockNumber, nil) + operatorInfo := make(map[core.OperatorID]*core.IndexedOperatorInfo) + ics.Mock.On("GetIndexedOperators", blockNumber).Return(operatorInfo, nil) // This is the server used to read it back config := defaultConfig() @@ -718,9 +728,11 @@ func TestReadWriteChunksWithSharding(t *testing.T) { } shardMap := make(map[v2.BlobKey][]v2.RelayKey) - ics, err := mock.NewChainDataMock(nil) - require.NoError(t, err) - ics.Mock.On("GetCurrentBlockNumber").Return(uint(0), nil) + ics := &mock.IndexedChainState{} + blockNumber := uint(rand.Uint32()) + ics.Mock.On("GetCurrentBlockNumber").Return(blockNumber, nil) + operatorInfo := make(map[core.OperatorID]*core.IndexedOperatorInfo) + ics.Mock.On("GetIndexedOperators", blockNumber).Return(operatorInfo, nil) // This is the server used to read it back config := defaultConfig() @@ -1002,9 +1014,11 @@ func TestBatchedReadWriteChunksWithSharding(t *testing.T) { } shardMap := make(map[v2.BlobKey][]v2.RelayKey) - ics, err := mock.NewChainDataMock(nil) - require.NoError(t, err) - ics.Mock.On("GetCurrentBlockNumber").Return(uint(0), nil) + ics := &mock.IndexedChainState{} + blockNumber := uint(rand.Uint32()) + ics.Mock.On("GetCurrentBlockNumber").Return(blockNumber, nil) + operatorInfo := make(map[core.OperatorID]*core.IndexedOperatorInfo) + ics.Mock.On("GetIndexedOperators", blockNumber).Return(operatorInfo, nil) // This is the server used to read it back config := defaultConfig() From cb1e42c0373bc98f2261a97732421977600cd391 Mon Sep 17 00:00:00 2001 From: Cody Littley Date: Wed, 18 Dec 2024 10:18:11 -0600 Subject: [PATCH 7/8] Augment random utils. Signed-off-by: Cody Littley --- common/testutils/random/test_random.go | 82 +++++++++++++++++-- common/testutils/random/test_random_test.go | 89 +++++++++++++++++++-- 2 files changed, 157 insertions(+), 14 deletions(-) diff --git a/common/testutils/random/test_random.go b/common/testutils/random/test_random.go index ed4699a6dc..63135803c9 100644 --- a/common/testutils/random/test_random.go +++ b/common/testutils/random/test_random.go @@ -1,19 +1,35 @@ package random import ( + "crypto/ecdsa" + crand "crypto/rand" "fmt" + "github.com/Layr-Labs/eigenda/core" + "github.com/consensys/gnark-crypto/ecc/bn254/fr" + "github.com/ethereum/go-ethereum/crypto" + "github.com/stretchr/testify/require" + "io" + "math/big" "math/rand" + "testing" "time" ) // TestRandom provides all the functionality of math/rand.Rand, plus additional randomness functionality useful for testing type TestRandom struct { + // The source of randomness *rand.Rand + + // The testing object + t *testing.T + + // The seed used to initialize the random number generator + seed int64 } // NewTestRandom creates a new instance of TestRandom // This method may either be seeded, or not seeded. If no seed is provided, then current unix nano time is used. -func NewTestRandom(fixedSeed ...int64) *TestRandom { +func NewTestRandom(t *testing.T, fixedSeed ...int64) *TestRandom { var seed int64 if len(fixedSeed) == 0 { seed = time.Now().UnixNano() @@ -25,12 +41,20 @@ func NewTestRandom(fixedSeed ...int64) *TestRandom { fmt.Printf("Random seed: %d\n", seed) return &TestRandom{ - rand.New(rand.NewSource(seed)), + Rand: rand.New(rand.NewSource(seed)), + t: t, + seed: seed, } } -// RandomBytes generates a random byte slice of a given length. -func (r *TestRandom) RandomBytes(length int) []byte { +// Reset resets the random number generator to the state it was in when it was first created. +// This method is not thread safe with respect to other methods in this struct. +func (r *TestRandom) Reset() { + r.Seed(r.seed) +} + +// Bytes generates a random byte slice of a given length. +func (r *TestRandom) Bytes(length int) []byte { bytes := make([]byte, length) _, err := r.Read(bytes) if err != nil { @@ -39,13 +63,13 @@ func (r *TestRandom) RandomBytes(length int) []byte { return bytes } -// RandomTime generates a random time. -func (r *TestRandom) RandomTime() time.Time { +// Time generates a random time. +func (r *TestRandom) Time() time.Time { return time.Unix(r.Int63(), r.Int63()) } -// RandomString generates a random string out of printable ASCII characters. -func (r *TestRandom) RandomString(length int) string { +// String generates a random string out of printable ASCII characters. +func (r *TestRandom) String(length int) string { const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" b := make([]byte, length) for i := range b { @@ -53,3 +77,45 @@ func (r *TestRandom) RandomString(length int) string { } return string(b) } + +var _ io.Reader = &randIOReader{} + +// randIOReader is an io.Reader that reads from a random number generator. +type randIOReader struct { + rand *TestRandom +} + +func (i *randIOReader) Read(p []byte) (n int, err error) { + return i.rand.Read(p) +} + +// IOReader creates an io.Reader that reads from a random number generator. +func (r *TestRandom) IOReader() io.Reader { + return &randIOReader{r} +} + +// ECDSA generates a random ECDSA key. Note that the returned keys are not deterministic due to limitations +// **intentionally** imposed by the Go standard libraries. (╯°□°)╯︵ ┻━┻ +// +// NOT CRYPTOGRAPHICALLY SECURE!!! FOR TESTING PURPOSES ONLY. DO NOT USE THESE KEYS FOR SECURITY PURPOSES. +func (r *TestRandom) ECDSA() (*ecdsa.PublicKey, *ecdsa.PrivateKey) { + key, err := ecdsa.GenerateKey(crypto.S256(), crand.Reader) + require.NoError(r.t, err) + return &key.PublicKey, key +} + +// BLS generates a random BLS key pair. +// +// NOT CRYPTOGRAPHICALLY SECURE!!! FOR TESTING PURPOSES ONLY. DO NOT USE THESE KEYS FOR SECURITY PURPOSES. +func (r *TestRandom) BLS() *core.KeyPair { + //Max random value is order of the curve + maxValue := new(big.Int) + maxValue.SetString(fr.Modulus().String(), 10) + + //Generate cryptographically strong pseudo-random between 0 - max + n, err := crand.Int(r.IOReader(), maxValue) + require.NoError(r.t, err) + + sk := new(core.PrivateKey).SetBigInt(n) + return core.MakeKeyPair(sk) +} diff --git a/common/testutils/random/test_random_test.go b/common/testutils/random/test_random_test.go index 822afd8555..52129f3470 100644 --- a/common/testutils/random/test_random_test.go +++ b/common/testutils/random/test_random_test.go @@ -1,27 +1,104 @@ package random import ( + "github.com/ethereum/go-ethereum/crypto" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "math/rand" "testing" ) // Tests that random seeding produces random results, and that consistent seeding produces consistent results func TestSetup(t *testing.T) { - testRandom1 := NewTestRandom() + testRandom1 := NewTestRandom(t) x := testRandom1.Int() - testRandom2 := NewTestRandom() + testRandom2 := NewTestRandom(t) y := testRandom2.Int() - assert.NotEqual(t, x, y) + require.NotEqual(t, x, y) seed := rand.Int63() - testRandom3 := NewTestRandom(seed) + testRandom3 := NewTestRandom(t, seed) a := testRandom3.Int() - testRandom4 := NewTestRandom(seed) + testRandom4 := NewTestRandom(t, seed) b := testRandom4.Int() - assert.Equal(t, a, b) + require.Equal(t, a, b) +} + +func TestReset(t *testing.T) { + random := NewTestRandom(t) + + a := random.Uint64() + b := random.Uint64() + c := random.Uint64() + d := random.Uint64() + + random.Reset() + + require.Equal(t, a, random.Uint64()) + require.Equal(t, b, random.Uint64()) + require.Equal(t, c, random.Uint64()) + require.Equal(t, d, random.Uint64()) +} + +func TestECDSAKeyGeneration(t *testing.T) { + random := NewTestRandom(t) + + // We should not get the same key pair twice in a row + public1, private1 := random.ECDSA() + public2, private2 := random.ECDSA() + + assert.NotEqual(t, &public1, &public2) + assert.NotEqual(t, &private1, &private2) + + // Getting keys should result in deterministic generator state. + generatorState := random.Uint64() + random.Reset() + random.ECDSA() + random.ECDSA() + require.Equal(t, generatorState, random.Uint64()) + + // Keypair should be valid. + data := random.Bytes(32) + + signature, err := crypto.Sign(data, private1) + require.NoError(t, err) + + signingPublicKey, err := crypto.SigToPub(data, signature) + require.NoError(t, err) + require.Equal(t, &public1, &signingPublicKey) +} + +func TestBLSKeyGeneration(t *testing.T) { + random := NewTestRandom(t) + + // We should not get the same key pair twice in a row + keypair1 := random.BLS() + keypair2 := random.BLS() + + require.False(t, keypair1.PrivKey.Equal(keypair2.PrivKey)) + require.False(t, keypair1.PubKey.Equal(keypair2.PubKey.G1Affine)) + + // Getting keys should result in deterministic generator state. + generatorState := random.Uint64() + random.Reset() + random.BLS() + random.BLS() + require.Equal(t, generatorState, random.Uint64()) + + // Keys should be deterministic. + random.Reset() + keypair3 := random.BLS() + require.True(t, keypair1.PrivKey.Equal(keypair3.PrivKey)) + require.True(t, keypair1.PubKey.Equal(keypair3.PubKey.G1Affine)) + + // Keypair should be valid. + data := random.Bytes(32) + signature := keypair1.SignMessage(([32]byte)(data)) + + isValid := signature.Verify(keypair1.GetPubKeyG2(), ([32]byte)(data)) + require.True(t, isValid) } From 4743516cd9be5937f4829037d480851c5e37d9fb Mon Sep 17 00:00:00 2001 From: Cody Littley Date: Wed, 18 Dec 2024 10:53:29 -0600 Subject: [PATCH 8/8] Made suggested changes, test improvements. Signed-off-by: Cody Littley --- relay/server_test.go | 121 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 96 insertions(+), 25 deletions(-) diff --git a/relay/server_test.go b/relay/server_test.go index 3e83f3bb1a..94adcba01d 100644 --- a/relay/server_test.go +++ b/relay/server_test.go @@ -2,8 +2,10 @@ package relay import ( "context" + "encoding/binary" + "github.com/Layr-Labs/eigenda/common/testutils/random" + "github.com/Layr-Labs/eigenda/relay/auth" "github.com/Layr-Labs/eigenda/relay/mock" - "math/rand" "testing" "time" @@ -78,7 +80,20 @@ func getBlob(t *testing.T, request *pb.GetBlobRequest) (*pb.GetBlobReply, error) return response, err } -func getChunks(t *testing.T, request *pb.GetChunksRequest) (*pb.GetChunksReply, error) { +func getChunks( + t *testing.T, + random *random.TestRandom, + operatorKeys map[uint32]*core.KeyPair, + request *pb.GetChunksRequest) (*pb.GetChunksReply, error) { + + // Choose a random operator to send this request as. Operator IDs are expected to be sequential starting at 0. + operatorID := random.Uint32() % uint32(len(operatorKeys)) + operatorIDBytes := make([]byte, 32) + binary.BigEndian.PutUint32(operatorIDBytes[24:], operatorID) + request.OperatorId = operatorIDBytes + signature := auth.SignGetChunksRequest(operatorKeys[operatorID], request) + request.OperatorSignature = signature + var opts []grpc.DialOption opts = append(opts, grpc.WithTransportCredentials(insecure.NewCredentials())) @@ -95,7 +110,7 @@ func getChunks(t *testing.T, request *pb.GetChunksRequest) (*pb.GetChunksReply, } func TestReadWriteBlobs(t *testing.T) { - tu.InitializeRandom() + rand := random.NewTestRandom(t) logger, err := common.NewLogger(common.DefaultLoggerConfig()) require.NoError(t, err) @@ -184,7 +199,7 @@ func TestReadWriteBlobs(t *testing.T) { } func TestReadNonExistentBlob(t *testing.T) { - tu.InitializeRandom() + rand := random.NewTestRandom(t) logger, err := common.NewLogger(common.DefaultLoggerConfig()) require.NoError(t, err) @@ -237,7 +252,7 @@ func TestReadNonExistentBlob(t *testing.T) { } func TestReadWriteBlobsWithSharding(t *testing.T) { - tu.InitializeRandom() + rand := random.NewTestRandom(t) logger, err := common.NewLogger(common.DefaultLoggerConfig()) require.NoError(t, err) @@ -373,7 +388,7 @@ func TestReadWriteBlobsWithSharding(t *testing.T) { } func TestReadWriteChunks(t *testing.T) { - tu.InitializeRandom() + rand := random.NewTestRandom(t) logger, err := common.NewLogger(common.DefaultLoggerConfig()) require.NoError(t, err) @@ -385,10 +400,24 @@ func TestReadWriteChunks(t *testing.T) { metadataStore := buildMetadataStore(t) chunkReader, chunkWriter := buildChunkStore(t, logger) + operatorCount := rand.Intn(3) + 1 + operatorKeys := make(map[uint32]*core.KeyPair) + operatorInfo := make(map[core.OperatorID]*core.IndexedOperatorInfo) + for i := 0; i < operatorCount; i++ { + keypair := rand.BLS() + operatorKeys[uint32(i)] = keypair + + var operatorID core.OperatorID + binary.BigEndian.PutUint32(operatorID[24:], uint32(i)) + operatorInfo[operatorID] = &core.IndexedOperatorInfo{ + PubkeyG1: keypair.GetPubKeyG1(), + PubkeyG2: keypair.GetPubKeyG2(), + } + } + ics := &mock.IndexedChainState{} blockNumber := uint(rand.Uint32()) ics.Mock.On("GetCurrentBlockNumber").Return(blockNumber, nil) - operatorInfo := make(map[core.OperatorID]*core.IndexedOperatorInfo) ics.Mock.On("GetIndexedOperators", blockNumber).Return(operatorInfo, nil) // This is the server used to read it back @@ -464,7 +493,7 @@ func TestReadWriteChunks(t *testing.T) { ChunkRequests: requestedChunks, } - response, err := getChunks(t, request) + response, err := getChunks(t, rand, operatorKeys, request) require.NoError(t, err) require.Equal(t, 1, len(response.Data)) @@ -498,7 +527,7 @@ func TestReadWriteChunks(t *testing.T) { ChunkRequests: requestedChunks, } - response, err := getChunks(t, request) + response, err := getChunks(t, rand, operatorKeys, request) require.NoError(t, err) require.Equal(t, 1, len(response.Data)) @@ -531,7 +560,7 @@ func TestReadWriteChunks(t *testing.T) { ChunkRequests: requestedChunks, } - response, err := getChunks(t, request) + response, err := getChunks(t, rand, operatorKeys, request) require.NoError(t, err) require.Equal(t, 1, len(response.Data)) @@ -567,7 +596,7 @@ func TestReadWriteChunks(t *testing.T) { ChunkRequests: requestedChunks, } - response, err := getChunks(t, request) + response, err := getChunks(t, rand, operatorKeys, request) require.NoError(t, err) require.Equal(t, 1, len(response.Data)) @@ -584,7 +613,7 @@ func TestReadWriteChunks(t *testing.T) { } func TestBatchedReadWriteChunks(t *testing.T) { - tu.InitializeRandom() + rand := random.NewTestRandom(t) logger, err := common.NewLogger(common.DefaultLoggerConfig()) require.NoError(t, err) @@ -596,10 +625,24 @@ func TestBatchedReadWriteChunks(t *testing.T) { metadataStore := buildMetadataStore(t) chunkReader, chunkWriter := buildChunkStore(t, logger) + operatorCount := rand.Intn(3) + 1 + operatorKeys := make(map[uint32]*core.KeyPair) + operatorInfo := make(map[core.OperatorID]*core.IndexedOperatorInfo) + for i := 0; i < operatorCount; i++ { + keypair := rand.BLS() + operatorKeys[uint32(i)] = keypair + + var operatorID core.OperatorID + binary.BigEndian.PutUint32(operatorID[24:], uint32(i)) + operatorInfo[operatorID] = &core.IndexedOperatorInfo{ + PubkeyG1: keypair.GetPubKeyG1(), + PubkeyG2: keypair.GetPubKeyG2(), + } + } + ics := &mock.IndexedChainState{} blockNumber := uint(rand.Uint32()) ics.Mock.On("GetCurrentBlockNumber").Return(blockNumber, nil) - operatorInfo := make(map[core.OperatorID]*core.IndexedOperatorInfo) ics.Mock.On("GetIndexedOperators", blockNumber).Return(operatorInfo, nil) // This is the server used to read it back @@ -686,7 +729,7 @@ func TestBatchedReadWriteChunks(t *testing.T) { ChunkRequests: requestedChunks, } - response, err := getChunks(t, request) + response, err := getChunks(t, rand, operatorKeys, request) require.NoError(t, err) require.Equal(t, keyCount, len(response.Data)) @@ -705,7 +748,7 @@ func TestBatchedReadWriteChunks(t *testing.T) { } func TestReadWriteChunksWithSharding(t *testing.T) { - tu.InitializeRandom() + rand := random.NewTestRandom(t) logger, err := common.NewLogger(common.DefaultLoggerConfig()) require.NoError(t, err) @@ -728,10 +771,24 @@ func TestReadWriteChunksWithSharding(t *testing.T) { } shardMap := make(map[v2.BlobKey][]v2.RelayKey) + operatorCount := rand.Intn(3) + 1 + operatorKeys := make(map[uint32]*core.KeyPair) + operatorInfo := make(map[core.OperatorID]*core.IndexedOperatorInfo) + for i := 0; i < operatorCount; i++ { + keypair := rand.BLS() + operatorKeys[uint32(i)] = keypair + + var operatorID core.OperatorID + binary.BigEndian.PutUint32(operatorID[24:], uint32(i)) + operatorInfo[operatorID] = &core.IndexedOperatorInfo{ + PubkeyG1: keypair.GetPubKeyG1(), + PubkeyG2: keypair.GetPubKeyG2(), + } + } + ics := &mock.IndexedChainState{} blockNumber := uint(rand.Uint32()) ics.Mock.On("GetCurrentBlockNumber").Return(blockNumber, nil) - operatorInfo := make(map[core.OperatorID]*core.IndexedOperatorInfo) ics.Mock.On("GetIndexedOperators", blockNumber).Return(operatorInfo, nil) // This is the server used to read it back @@ -824,7 +881,7 @@ func TestReadWriteChunksWithSharding(t *testing.T) { } } - response, err := getChunks(t, request) + response, err := getChunks(t, rand, operatorKeys, request) if isBlobInCorrectShard { require.NoError(t, err) @@ -874,7 +931,7 @@ func TestReadWriteChunksWithSharding(t *testing.T) { } if isBlobInCorrectShard { - response, err := getChunks(t, request) + response, err := getChunks(t, rand, operatorKeys, request) require.NoError(t, err) require.Equal(t, 1, len(response.Data)) @@ -886,7 +943,7 @@ func TestReadWriteChunksWithSharding(t *testing.T) { require.Equal(t, data[i], frame) } } else { - response, err := getChunks(t, request) + response, err := getChunks(t, rand, operatorKeys, request) require.Error(t, err) require.Nil(t, response) } @@ -922,7 +979,7 @@ func TestReadWriteChunksWithSharding(t *testing.T) { } if isBlobInCorrectShard { - response, err := getChunks(t, request) + response, err := getChunks(t, rand, operatorKeys, request) require.NoError(t, err) require.Equal(t, 1, len(response.Data)) @@ -969,7 +1026,7 @@ func TestReadWriteChunksWithSharding(t *testing.T) { } if isBlobInCorrectShard { - response, err := getChunks(t, request) + response, err := getChunks(t, rand, operatorKeys, request) require.NoError(t, err) require.Equal(t, 1, len(response.Data)) @@ -983,7 +1040,7 @@ func TestReadWriteChunksWithSharding(t *testing.T) { } } } else { - response, err := getChunks(t, request) + response, err := getChunks(t, rand, operatorKeys, request) require.Error(t, err) require.Nil(t, response) } @@ -991,7 +1048,7 @@ func TestReadWriteChunksWithSharding(t *testing.T) { } func TestBatchedReadWriteChunksWithSharding(t *testing.T) { - tu.InitializeRandom() + rand := random.NewTestRandom(t) logger, err := common.NewLogger(common.DefaultLoggerConfig()) require.NoError(t, err) @@ -1014,10 +1071,24 @@ func TestBatchedReadWriteChunksWithSharding(t *testing.T) { } shardMap := make(map[v2.BlobKey][]v2.RelayKey) + operatorCount := rand.Intn(3) + 1 + operatorKeys := make(map[uint32]*core.KeyPair) + operatorInfo := make(map[core.OperatorID]*core.IndexedOperatorInfo) + for i := 0; i < operatorCount; i++ { + keypair := rand.BLS() + operatorKeys[uint32(i)] = keypair + + var operatorID core.OperatorID + binary.BigEndian.PutUint32(operatorID[24:], uint32(i)) + operatorInfo[operatorID] = &core.IndexedOperatorInfo{ + PubkeyG1: keypair.GetPubKeyG1(), + PubkeyG2: keypair.GetPubKeyG2(), + } + } + ics := &mock.IndexedChainState{} blockNumber := uint(rand.Uint32()) ics.Mock.On("GetCurrentBlockNumber").Return(blockNumber, nil) - operatorInfo := make(map[core.OperatorID]*core.IndexedOperatorInfo) ics.Mock.On("GetIndexedOperators", blockNumber).Return(operatorInfo, nil) // This is the server used to read it back @@ -1143,7 +1214,7 @@ func TestBatchedReadWriteChunksWithSharding(t *testing.T) { } } - response, err := getChunks(t, request) + response, err := getChunks(t, rand, operatorKeys, request) if allInCorrectShard { require.NoError(t, err)