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

Add eth accounts to allowlist #175

Merged
merged 9 commits into from
Jan 17, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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 disperser/apiserver/rate_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ func CLIFlags(envPrefix string) []cli.Flag {
},
cli.StringSliceFlag{
Name: AllowlistFlagName,
Usage: "Allowlist of IPs and corresponding blob/byte rates to bypass rate limiting. Format: <IP>:<quorum ID>:<blob rate>:<byte rate>. Example: 127.0.0.1:0:10:10485760",
Usage: "Allowlist of IPs or ethereum addresses (including initial \"0x\") and corresponding blob/byte rates to bypass rate limiting. Format: [<IP>||<ETH ADDRESS>]:<quorum ID>:<blob rate>:<byte rate>. Example: 127.0.0.1:0:10:10485760 0x1234567890123456789012345678901234567890:0:10:10485760",
mooselumph marked this conversation as resolved.
Show resolved Hide resolved
EnvVar: common.PrefixEnvVar(envPrefix, "ALLOWLIST"),
Required: false,
Value: &cli.StringSlice{},
Expand Down
36 changes: 27 additions & 9 deletions disperser/apiserver/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import (
"github.com/Layr-Labs/eigenda/core"
"github.com/Layr-Labs/eigenda/core/auth"
"github.com/Layr-Labs/eigenda/disperser"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto"
"github.com/prometheus/client_golang/prometheus"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
Expand Down Expand Up @@ -128,8 +130,24 @@ func (s *DispersalServer) DisperseBlobAuthenticated(stream pb.Disperser_Disperse
return fmt.Errorf("failed to authenticate blob request: %v", err)
}

// Get the ethereum address associated with the public key. This is just for convenience so we can put addresses instead of public keys in the allowlist.
authenticatedAddress := ""
// Decode public key
publicKeyBytes, err := hexutil.Decode(blob.RequestHeader.AccountID)
Copy link
Contributor

Choose a reason for hiding this comment

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

The check here and below assume the account id is in hex format ethereum. address. It'd be helpful to make this assumption clear at the interface: https://github.com/Layr-Labs/eigenda/blob/master/api/proto/disperser/disperser.proto#L83

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

if err != nil {
s.logger.Warn("failed to decode public key (%v): %v", blob.RequestHeader.AccountID, err)
mooselumph marked this conversation as resolved.
Show resolved Hide resolved
} else {
pubKey, err := crypto.UnmarshalPubkey(publicKeyBytes)
if err != nil {
s.logger.Warn("failed to decode public key (%v): %v", blob.RequestHeader.AccountID, err)
} else {
// Get the address
authenticatedAddress = crypto.PubkeyToAddress(*pubKey).String()
}
}

// Disperse the blob
reply, err := s.disperseBlob(stream.Context(), blob)
reply, err := s.disperseBlob(stream.Context(), blob, authenticatedAddress)
if err != nil {
return err
}
Expand All @@ -150,11 +168,11 @@ func (s *DispersalServer) DisperseBlob(ctx context.Context, req *pb.DisperseBlob

blob := getBlobFromRequest(req)

return s.disperseBlob(ctx, blob)
return s.disperseBlob(ctx, blob, "")

}

func (s *DispersalServer) disperseBlob(ctx context.Context, blob *core.Blob) (*pb.DisperseBlobReply, error) {
func (s *DispersalServer) disperseBlob(ctx context.Context, blob *core.Blob, authenticatedAddress string) (*pb.DisperseBlobReply, error) {
timer := prometheus.NewTimer(prometheus.ObserverFunc(func(f float64) {
s.metrics.ObserveLatency("DisperseBlob", f*1000) // make milliseconds
}))
Expand Down Expand Up @@ -219,7 +237,7 @@ func (s *DispersalServer) disperseBlob(ctx context.Context, blob *core.Blob) (*p
}

if s.ratelimiter != nil {
err := s.checkRateLimitsAndAddRates(ctx, blob, origin)
err := s.checkRateLimitsAndAddRates(ctx, blob, origin, authenticatedAddress)
if err != nil {
for _, param := range securityParams {
quorumId := string(param.QuorumID)
Expand Down Expand Up @@ -257,14 +275,14 @@ func (s *DispersalServer) disperseBlob(ctx context.Context, blob *core.Blob) (*p
}, nil
}

func (s *DispersalServer) getAccountRate(origin string, quorumID core.QuorumID) (*PerUserRateInfo, error) {
func (s *DispersalServer) getAccountRate(origin, address string, quorumID core.QuorumID) (*PerUserRateInfo, error) {
mooselumph marked this conversation as resolved.
Show resolved Hide resolved
unauthRates, ok := s.rateConfig.QuorumRateInfos[quorumID]
if !ok {
return nil, fmt.Errorf("no configured rate exists for quorum %d", quorumID)
}

for ip, rateInfoByQuorum := range s.rateConfig.Allowlist {
if !strings.Contains(origin, ip) {
for account, rateInfoByQuorum := range s.rateConfig.Allowlist {
if !strings.Contains(origin, account) && !strings.EqualFold(address, account) {
continue
}

Expand Down Expand Up @@ -295,7 +313,7 @@ func (s *DispersalServer) getAccountRate(origin string, quorumID core.QuorumID)
}, nil
}

func (s *DispersalServer) checkRateLimitsAndAddRates(ctx context.Context, blob *core.Blob, origin string) error {
func (s *DispersalServer) checkRateLimitsAndAddRates(ctx context.Context, blob *core.Blob, origin, authenticatedAddress string) error {

// TODO(robert): Remove these locks once we have resolved ratelimiting approach
s.mu.Lock()
Expand All @@ -307,7 +325,7 @@ func (s *DispersalServer) checkRateLimitsAndAddRates(ctx context.Context, blob *
if !ok {
return fmt.Errorf("no configured rate exists for quorum %d", param.QuorumID)
}
accountRates, err := s.getAccountRate(origin, param.QuorumID)
accountRates, err := s.getAccountRate(origin, authenticatedAddress, param.QuorumID)
if err != nil {
return err
}
Expand Down
Loading