Skip to content

Commit

Permalink
feat: add new API for provider registration (#229)
Browse files Browse the repository at this point in the history
  • Loading branch information
aloknerurkar authored and mrekucci committed Jul 15, 2024
1 parent d5a2c7b commit be998f7
Show file tree
Hide file tree
Showing 8 changed files with 146 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ job "{{ job.name }}" {
MEV_ORACLE_KEYSTORE_PATH="/local/data-{{ env "NOMAD_ALLOC_INDEX" }}/keystore"
MEV_ORACLE_KEYSTORE_FILENAME="{{ with secret "secret/data/mev-commit" }}{{ .Data.data.{% endraw %}{{ job.artifacts | selectattr('keystore', 'defined') | map(attribute='keystore.name') | first }}{% raw %}_filename }}{{ end }}"
MEV_ORACLE_KEYSTORE_PASSWORD="{{ with secret "secret/data/mev-commit" }}{{ .Data.data.{% endraw %}{{ job.artifacts | selectattr('keystore', 'defined') | map(attribute='keystore.name') | first }}{% raw %}_password }}{{ end }}"
MEV_ORACLE_REGISTER_PROVIDER_API_AUTH_TOKEN="{{ with secret "secret/data/mev-commit" }}{{ .Data.data.oracle_register_provider_api_auth_token }}{{ end }}"
{{- range nomadService "mev-commit-oracle" }}
{{- if contains "http" .Tags }}
MEV_ORACLE_HTTP_PORT="{{ .Port }}"
Expand Down
2 changes: 2 additions & 0 deletions infrastructure/nomad/playbooks/variables/profiles.yml
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,8 @@ jobs:
template: mev-commit-oracle.nomad.j2
artifacts:
- *oracle_artifact
- auth_token:
name: oracle_register_provider_api_auth_token
- keystore:
name: oracle_keystore
allocation: true
Expand Down
9 changes: 9 additions & 0 deletions oracle/cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,13 @@ var (
EnvVars: []string{"MEV_ORACLE_KEYSTORE_PATH"},
Value: filepath.Join(defaultConfigDir, defaultKeystore),
})

optionRegistrationAuthToken = altsrc.NewStringFlag(&cli.StringFlag{
Name: "register-provider-auth-token",
Usage: "Authorization token for provider registration",
EnvVars: []string{"MEV_ORACLE_REGISTER_PROVIDER_API_AUTH_TOKEN"},
Required: true,
})
)

func main() {
Expand Down Expand Up @@ -237,6 +244,7 @@ func main() {
optionOverrideWinners,
optionKeystorePath,
optionKeystorePassword,
optionRegistrationAuthToken,
}
app := &cli.App{
Name: "mev-oracle",
Expand Down Expand Up @@ -322,6 +330,7 @@ func launchOracleWithConfig(c *cli.Context) error {
PgDbname: c.String(optionPgDbname.Name),
LaggerdMode: c.Int(optionLaggerdMode.Name),
OverrideWinners: c.StringSlice(optionOverrideWinners.Name),
RegistrationAuthToken: c.String(optionRegistrationAuthToken.Name),
})
if err != nil {
return fmt.Errorf("failed starting node: %w", err)
Expand Down
100 changes: 100 additions & 0 deletions oracle/pkg/apiserver/apiserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,18 @@ import (
"net"
"net/http"
"net/http/pprof"
"strings"
"sync"
"time"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
lru "github.com/hashicorp/golang-lru/v2"
blocktracker "github.com/primev/mev-commit/contracts-abi/clients/BlockTracker"
providerregistry "github.com/primev/mev-commit/contracts-abi/clients/ProviderRegistry"
"github.com/primev/mev-commit/oracle/pkg/updater"
"github.com/primev/mev-commit/x/contracts/events"
"github.com/primev/mev-commit/x/contracts/txmonitor"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/collectors"
"github.com/prometheus/client_golang/prometheus/promhttp"
Expand All @@ -40,6 +46,9 @@ type Service struct {
blockStats *lru.Cache[uint64, *BlockStats]
providerStakes *lru.Cache[string, *ProviderBalances]
bidderAllowances *lru.Cache[uint64, []*BidderAllowance]
blockTracker *blocktracker.BlocktrackerTransactorSession
providerRegistry *providerregistry.ProviderregistryCallerSession
monitor *txmonitor.Monitor
lastBlock uint64
shutdown chan struct{}
}
Expand All @@ -49,6 +58,10 @@ func New(
logger *slog.Logger,
evm events.EventManager,
store Store,
token string,
blockTracker *blocktracker.BlocktrackerTransactorSession,
providerRegistry *providerregistry.ProviderregistryCallerSession,
monitor *txmonitor.Monitor,
) *Service {
blockStats, _ := lru.New[uint64, *BlockStats](10000)
providerStakes, _ := lru.New[string, *ProviderBalances](1000)
Expand All @@ -60,6 +73,9 @@ func New(
metricsRegistry: newMetrics(),
evtMgr: evm,
store: store,
blockTracker: blockTracker,
providerRegistry: providerRegistry,
monitor: monitor,
shutdown: make(chan struct{}),
blockStats: blockStats,
providerStakes: providerStakes,
Expand All @@ -71,10 +87,94 @@ func New(
logger.Error("failed to configure dashboard", "error", err)
}

srv.router.Handle("/register_provider", srv.registerProvider(token))

srv.registerDebugEndpoints()
return srv
}

func (s *Service) registerProvider(token string) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}

authHeader := r.Header.Get("Authorization")
if authHeader == "" {
http.Error(w, "Authorization header missing", http.StatusUnauthorized)
return
}

// Expected format "Bearer <token>"
headerToken, found := strings.CutPrefix(authHeader, "Bearer ")
if !found {
http.Error(w, "Invalid Authorization header format", http.StatusUnauthorized)
return
}

if headerToken != token {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}

provider := r.URL.Query().Get("provider")
if provider == "" {
http.Error(w, "Provider not specified", http.StatusBadRequest)
return
}

if !common.IsHexAddress(provider) {
http.Error(w, "Invalid provider address", http.StatusBadRequest)
return
}

providerAddress := common.HexToAddress(provider)

grafiti := r.URL.Query().Get("grafiti")
if grafiti == "" {
http.Error(w, "Grafiti not specified", http.StatusBadRequest)
return
}

minStake, err := s.providerRegistry.MinStake()
if err != nil {
http.Error(w, "Failed to get minimum stake amount", http.StatusInternalServerError)
return
}

stake, err := s.providerRegistry.CheckStake(providerAddress)
if err != nil {
http.Error(w, "Failed to check provider stake", http.StatusInternalServerError)
return
}

if stake.Cmp(minStake) < 0 {
http.Error(w, "Insufficient stake", http.StatusBadRequest)
return
}

txn, err := s.blockTracker.AddBuilderAddress(grafiti, providerAddress)
if err != nil {
http.Error(w, "Failed to add provider mapping", http.StatusInternalServerError)
return
}

receipt, err := s.monitor.WaitForReceipt(context.Background(), txn)
if err != nil {
http.Error(w, "Failed to get receipt for transaction", http.StatusInternalServerError)
return
}

if receipt.Status != types.ReceiptStatusSuccessful {
http.Error(w, "Transaction failed", http.StatusInternalServerError)
return
}

w.WriteHeader(http.StatusOK)
})
}

func (s *Service) registerDebugEndpoints() {
// register metrics handler
s.router.Handle("/metrics", promhttp.HandlerFor(s.metricsRegistry, promhttp.HandlerOpts{}))
Expand Down
24 changes: 24 additions & 0 deletions oracle/pkg/node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ type Options struct {
PgDbname string
LaggerdMode int
OverrideWinners []string
RegistrationAuthToken string
}

type Node struct {
Expand Down Expand Up @@ -248,10 +249,32 @@ func NewNode(opts *Options) (*Node, error) {

updtrClosed := updtr.Start(ctx)

providerRegistry, err := providerregistry.NewProviderregistryCaller(
opts.ProviderRegistryContractAddr,
settlementClient,
)
if err != nil {
nd.logger.Error("failed to instantiate provider registry contract", "error", err)
cancel()
return nil, err
}

providerRegistryCaller := &providerregistry.ProviderregistryCallerSession{
Contract: providerRegistry,
CallOpts: bind.CallOpts{
From: opts.KeySigner.GetAddress(),
Pending: false,
},
}

srv := apiserver.New(
nd.logger.With("component", "apiserver"),
evtMgr,
st,
opts.RegistrationAuthToken,
blockTrackerTransactor,
providerRegistryCaller,
monitor,
)

pubDone := eventsPublisher.Start(ctx, contractAddrs...)
Expand Down Expand Up @@ -461,6 +484,7 @@ func (i *infiniteRetryL1Client) BlockByNumber(ctx context.Context, number *big.I
}
return blk, nil
}

func setBuilderMapping(
ctx context.Context,
bt *blocktracker.BlocktrackerTransactorSession,
Expand Down
6 changes: 4 additions & 2 deletions p2p/pkg/autodepositor/autodepositor.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import (
"golang.org/x/sync/errgroup"
)

var ErrNotRunning = fmt.Errorf("auto deposit tracker is not running")

type OptsGetter func(context.Context) (*bind.TransactOpts, error)

type BidderRegistryContract interface {
Expand Down Expand Up @@ -228,7 +230,7 @@ func (adt *AutoDepositTracker) Stop() ([]*big.Int, error) {
defer adt.startMu.Unlock()

if !adt.isWorking {
return nil, fmt.Errorf("auto deposit tracker is not running")
return nil, ErrNotRunning
}
if adt.cancelFunc != nil {
adt.cancelFunc()
Expand All @@ -247,7 +249,7 @@ func (adt *AutoDepositTracker) Stop() ([]*big.Int, error) {

adt.isWorking = false

adt.logger.Info("stop auto deposit tracker", "windows", windowNumbers)
adt.logger.Info("stop auto deposit tracker", "windowsToWithdraw", windowNumbers)
return windowNumbers, nil
}

Expand Down
5 changes: 4 additions & 1 deletion p2p/pkg/node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -661,8 +661,11 @@ func (n *Node) Close() error {
}

_, adErr := n.autoDeposit.Stop()
if adErr != nil && !errors.Is(adErr, autodepositor.ErrNotRunning) {
return errors.Join(err, adErr)
}

return errors.Join(err, adErr)
return err
}

type noOpBidProcessor struct{}
Expand Down
4 changes: 2 additions & 2 deletions p2p/pkg/rpc/provider/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func (t *testRegistryContract) MinStake(_ *bind.CallOpts) (*big.Int, error) {

func (t *testRegistryContract) ParseProviderRegistered(log types.Log) (*providerregistry.ProviderregistryProviderRegistered, error) {
return &providerregistry.ProviderregistryProviderRegistered{
Provider: common.Address{},
Provider: common.Address{},
StakedAmount: t.stake,
}, nil
}
Expand Down Expand Up @@ -97,7 +97,7 @@ func startServer(t *testing.T) (providerapiv1.ProviderClient, *providerapi.Servi
if err := baseServer.Serve(lis); err != nil {
// Ignore "use of closed network connection" error
if opErr, ok := err.(*net.OpError); !ok || !errors.Is(opErr.Err, net.ErrClosed) {
t.Logf("server stopped err: %v", err)
t.Errorf("server stopped err: %v", err)
}
}
}()
Expand Down

0 comments on commit be998f7

Please sign in to comment.