Skip to content

Commit

Permalink
Sign get chunks (#1022)
Browse files Browse the repository at this point in the history
Signed-off-by: Cody Littley <[email protected]>
  • Loading branch information
cody-littley authored Dec 19, 2024
1 parent 1345e77 commit ca5f699
Show file tree
Hide file tree
Showing 5 changed files with 283 additions and 37 deletions.
66 changes: 59 additions & 7 deletions api/clients/v2/relay_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ package clients

import (
"context"
"errors"
"fmt"
"github.com/Layr-Labs/eigenda/core"
"github.com/Layr-Labs/eigenda/relay/auth"
"sync"

relaygrpc "github.com/Layr-Labs/eigenda/api/grpc/relay"
Expand All @@ -12,9 +15,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 {
Expand Down Expand Up @@ -62,7 +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) {
func NewRelayClient(config *RelayClientConfig, logger logging.Logger) (RelayClient, error) {
if config == nil || len(config.Sockets) <= 0 {
return nil, fmt.Errorf("invalid config: %v", config)
}
Expand Down Expand Up @@ -97,7 +105,32 @@ 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 {
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)
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")
}
Expand All @@ -118,18 +151,29 @@ 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
}

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")
}
Expand All @@ -150,9 +194,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
Expand Down
4 changes: 4 additions & 0 deletions node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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)
Expand Down
9 changes: 8 additions & 1 deletion node/node_v2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +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,
Sockets: relayURLs,
OperatorID: &c.node.Config.ID,
MessageSigner: messageSigner,
}, c.node.Logger)
require.NoError(t, err)
// set up non-mock client
Expand Down
68 changes: 68 additions & 0 deletions relay/mock/ics.go
Original file line number Diff line number Diff line change
@@ -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)
}
Loading

0 comments on commit ca5f699

Please sign in to comment.