Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Component updates for M2 mainnet contracts #196

Merged
Show file tree
Hide file tree
Changes from 3 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
2 changes: 1 addition & 1 deletion churner/churner.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ type churner struct {
mu sync.Mutex
Indexer thegraph.IndexedChainState
Transactor core.Transactor
QuorumCount uint16
QuorumCount uint8
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The max of uint8 is 255, so it can have 256 quorums, and uint8 cannot represent 256.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The onchain quorumCount was changed to a uint8 (https://github.com/Layr-Labs/eigenlayer-middleware/blob/98f884454d9e9de1e344bb6fba9a2cd3915e5b57/src/RegistryCoordinator.sol#L71), so it looks like we would only support up to 255 quorums.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, so the range of quorum ID is [0, 254] (not [0, 255]).


privateKey *ecdsa.PrivateKey
logger common.Logger
Expand Down
2 changes: 1 addition & 1 deletion churner/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ func setupMockTransactor() {
transactorMock.On("OperatorIDToAddress").Return(operatorAddr, nil)
transactorMock.On("GetCurrentQuorumBitmapByOperatorId").Return(big.NewInt(2), nil)
transactorMock.On("GetCurrentBlockNumber").Return(uint32(2), nil)
transactorMock.On("GetQuorumCount").Return(uint16(1), nil)
transactorMock.On("GetQuorumCount").Return(uint8(1), nil)
transactorMock.On("GetOperatorStakesForQuorums").Return(dacore.OperatorStakes{
0: {
0: {
Expand Down
17 changes: 16 additions & 1 deletion churner/tests/churner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ package test

import (
"context"
"crypto/rand"
"flag"
"fmt"
"log"
"math/big"
"os"
"testing"

Expand Down Expand Up @@ -102,7 +104,20 @@ func TestChurner(t *testing.T) {
keyPair, err := dacore.GenRandomBlsKeys()
assert.NoError(t, err)

err = operatorTransactor.RegisterBLSPublicKey(ctx, keyPair)
quorumIds_ := make([]uint8, len(quorumIds))
for i, q := range quorumIds {
quorumIds_[i] = uint8(q)
}

operatorSalt := [32]byte{}
_, err = rand.Read(operatorSalt[:])
assert.NoError(t, err)

expiry := big.NewInt(1000)
privKey, err := crypto.GenerateKey()
assert.NoError(t, err)

err = operatorTransactor.RegisterOperator(ctx, keyPair, "socket", quorumIds_, privKey, operatorSalt, expiry)
assert.NoError(t, err)

server := newTestServer(t)
Expand Down
6 changes: 3 additions & 3 deletions disperser/apiserver/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ type DispersalServer struct {

blobStore disperser.BlobStore
tx core.Transactor
quorumCount uint16
quorumCount uint8

rateConfig RateConfig
ratelimiter common.RateLimiter
Expand Down Expand Up @@ -177,13 +177,13 @@ func (s *DispersalServer) disperseBlob(ctx context.Context, blob *core.Blob) (*p
}
seenQuorums[param.QuorumID] = struct{}{}

if uint16(param.QuorumID) >= s.quorumCount {
if param.QuorumID >= s.quorumCount {
err := s.updateQuorumCount(ctx)
if err != nil {
return nil, fmt.Errorf("failed to get onchain quorum count: %w", err)
}

if uint16(param.QuorumID) >= s.quorumCount {
if param.QuorumID >= s.quorumCount {
return nil, fmt.Errorf("invalid request: the quorum_id must be in range [0, %d], but found %d", s.quorumCount-1, param.QuorumID)
}
}
Expand Down
6 changes: 3 additions & 3 deletions disperser/apiserver/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -310,8 +310,8 @@ func TestRatelimit(t *testing.T) {
})
assert.ErrorContains(t, err, "account throughput limit")

// Try with non-allowlisted IP. Should fail with account blob limit because blob rate (3 blobs/s) X bucket size (3s) is smaller than 10 blobs.
for i := 0; i < 10; i++ {
// Try with non-allowlisted IP. Should fail with account blob limit because blob rate (3 blobs/s) X bucket size (3s) is smaller than 20 blobs.
for i := 0; i < 20; i++ {
_, err = dispersalServer.DisperseBlob(ctx, &pb.DisperseBlobRequest{
Data: data1KiB,
SecurityParams: []*pb.SecurityParams{
Expand Down Expand Up @@ -463,7 +463,7 @@ func newTestServer(m *testing.M) *apiserver.DispersalServer {
queue = blobstore.NewSharedStorage(bucketName, s3Client, blobMetadataStore, logger)
tx := &mock.MockTransactor{}
tx.On("GetCurrentBlockNumber").Return(uint32(100), nil)
tx.On("GetQuorumCount").Return(uint16(2), nil)
tx.On("GetQuorumCount").Return(uint8(2), nil)

return apiserver.NewDispersalServer(disperser.ServerConfig{
GrpcPort: "51001",
Expand Down
12 changes: 6 additions & 6 deletions disperser/batcher/batcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -486,21 +486,21 @@ func (b *Batcher) parseBatchIDFromReceipt(ctx context.Context, txReceipt *types.
if log.Topics[0] == common.BatchConfirmedEventSigHash {
smAbi, err := abi.JSON(bytes.NewReader(common.ServiceManagerAbi))
if err != nil {
return 0, err
return 0, fmt.Errorf("failed to parse ServiceManager ABI: %w", err)
}
eventAbi, err := smAbi.EventByID(common.BatchConfirmedEventSigHash)
if err != nil {
return 0, err
return 0, fmt.Errorf("failed to parse BatchConfirmed event ABI: %w", err)
}
unpackedData, err := eventAbi.Inputs.Unpack(log.Data)
if err != nil {
return 0, err
return 0, fmt.Errorf("failed to unpack BatchConfirmed log data: %w", err)
}

// There should be exactly two inputs in the data field, batchId and fee.
// There should be exactly two inputs in the data field, batchId.
// ref: https://github.com/Layr-Labs/eigenda/blob/master/contracts/src/interfaces/IEigenDAServiceManager.sol#L20
mooselumph marked this conversation as resolved.
Show resolved Hide resolved
if len(unpackedData) != 2 {
return 0, fmt.Errorf("BatchConfirmed log should contain exactly 2 inputs. Found %d", len(unpackedData))
if len(unpackedData) != 1 {
return 0, fmt.Errorf("BatchConfirmed log should contain exactly 1 inputs. Found %d", len(unpackedData))
}
return unpackedData[0].(uint32), nil
}
Expand Down
26 changes: 19 additions & 7 deletions node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import (

"github.com/Layr-Labs/eigenda/common/pubip"
gethcommon "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/prometheus/client_golang/prometheus"

"github.com/Layr-Labs/eigenda/api/grpc/node"
"github.com/Layr-Labs/eigenda/common"
Expand All @@ -21,6 +23,7 @@ import (
"github.com/Layr-Labs/eigenda/core/eth"
"github.com/Layr-Labs/eigenda/core/indexer"
"github.com/Layr-Labs/eigensdk-go/chainio/constructor"
"github.com/Layr-Labs/eigensdk-go/metrics"
"github.com/Layr-Labs/eigensdk-go/metrics/collectors/economic"
rpccalls "github.com/Layr-Labs/eigensdk-go/metrics/collectors/rpc_calls"
"github.com/Layr-Labs/eigensdk-go/nodeapi"
Expand Down Expand Up @@ -62,12 +65,16 @@ type Node struct {
// NewNode creates a new Node with the provided config.
func NewNode(config *Config, pubIPProvider pubip.Provider, logger common.Logger) (*Node, error) {
// Setup metrics
sdkClients, err := buildSdkClients(config, logger)
if err != nil {
return nil, err
}
metrics := NewMetrics(sdkClients.Metrics, sdkClients.PrometheusRegistry, logger, ":"+config.MetricsPort)
rpcCallsCollector := rpccalls.NewCollector(AppName, sdkClients.PrometheusRegistry)
// sdkClients, err := buildSdkClients(config, logger)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why was this commented out?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At the time, the SDK hadn't been updated to reflect the new contracts. Since the client from the SDK was only being used for metrics, I created the metrics separately.

I'm not sure if it makes sense to build all of the SDK clients if we aren't using them.

My preference here would be to remove this commented code and create a ticket to track further integration with the SDK.

// if err != nil {
// return nil, err
// }

promReg := prometheus.NewRegistry()
eigenMetrics := metrics.NewEigenMetrics(AppName, ":"+config.MetricsPort, promReg, logger)

metrics := NewMetrics(eigenMetrics, promReg, logger, ":"+config.MetricsPort)
rpcCallsCollector := rpccalls.NewCollector(AppName, promReg)

// Generate BLS keys
keyPair, err := core.MakeKeyPairFromString(config.PrivateBls)
Expand Down Expand Up @@ -183,14 +190,19 @@ func (n *Node) Start(ctx context.Context) error {
n.Config.ID, "hostname", n.Config.Hostname, "dispersalPort", n.Config.DispersalPort,
"retrievalPort", n.Config.RetrievalPort, "churnerUrl", n.Config.ChurnerUrl, "quorumIds", n.Config.QuorumIDList)
socket := string(core.MakeOperatorSocket(n.Config.Hostname, n.Config.DispersalPort, n.Config.RetrievalPort))
privateKey, err := crypto.HexToECDSA(n.Config.EthClientConfig.PrivateKeyString)
if err != nil {
return fmt.Errorf("NewClient: cannot parse private key: %w", err)
}
operator := &Operator{
Socket: socket,
Timeout: 10 * time.Second,
PrivKey: privateKey,
KeyPair: n.KeyPair,
OperatorId: n.Config.ID,
QuorumIDs: n.Config.QuorumIDList,
}
err := RegisterOperator(ctx, operator, n.Transactor, n.Config.ChurnerUrl, n.Config.UseSecureGrpc, n.Logger)
err = RegisterOperator(ctx, operator, n.Transactor, n.Config.ChurnerUrl, n.Config.UseSecureGrpc, n.Logger)
if err != nil {
return fmt.Errorf("failed to register the operator: %w", err)
}
Expand Down
22 changes: 14 additions & 8 deletions node/operator.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ package node

import (
"context"
"crypto/ecdsa"
"crypto/tls"
"errors"
"fmt"
"math/big"
"time"

grpcchurner "github.com/Layr-Labs/eigenda/api/grpc/churner"
Expand All @@ -20,6 +22,7 @@ import (
type Operator struct {
Socket string
Timeout time.Duration
PrivKey *ecdsa.PrivateKey
KeyPair *core.KeyPair
OperatorId core.OperatorID
QuorumIDs []core.QuorumID
Expand All @@ -37,12 +40,6 @@ func RegisterOperator(ctx context.Context, operator *Operator, transactor core.T
return nil
}

// if the operator is not registered, we may need to register the BLSPublicKey
err = transactor.RegisterBLSPublicKey(ctx, operator.KeyPair)
if err != nil {
return fmt.Errorf("failed to register the nodes bls public key: %w", err)
}

logger.Info("Quorums to register for", "quorums", operator.QuorumIDs)

if len(operator.QuorumIDs) == 0 {
Expand Down Expand Up @@ -72,17 +69,26 @@ func RegisterOperator(ctx context.Context, operator *Operator, transactor core.T

logger.Info("Should call churner", "shouldCallChurner", shouldCallChurner)

// Generate salt and expiry

privateKeyBytes := []byte(operator.KeyPair.PrivKey.String())
salt := [32]byte{}
copy(salt[:], crypto.Keccak256([]byte("churn"), []byte(time.Now().String()), operator.QuorumIDs[:], privateKeyBytes))

// Get the current block number
expiry := big.NewInt((time.Now().Add(10 * time.Minute)).Unix())

// if we should call the churner, call it
if shouldCallChurner {
churnReply, err := requestChurnApproval(ctx, operator, churnerUrl, useSecureGrpc, logger)
if err != nil {
return fmt.Errorf("failed to request churn approval: %w", err)
}

return transactor.RegisterOperatorWithChurn(ctx, operator.KeyPair.PubKey, operator.Socket, operator.QuorumIDs, churnReply)
return transactor.RegisterOperatorWithChurn(ctx, operator.KeyPair, operator.Socket, operator.QuorumIDs, operator.PrivKey, salt, expiry, churnReply)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to update the nodeplugin path to have this private key as well: https://github.com/Layr-Labs/eigenda/blob/master/node/plugin/cmd/main.go#L118

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Updated!

} else {
// other wise just register normally
return transactor.RegisterOperator(ctx, operator.KeyPair.PubKey, operator.Socket, operator.QuorumIDs)
return transactor.RegisterOperator(ctx, operator.KeyPair, operator.Socket, operator.QuorumIDs, operator.PrivKey, salt, expiry)
}
}

Expand Down