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

feat(autodeposit): add flag from config #217

Merged
merged 10 commits into from
Jul 10, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
27 changes: 27 additions & 0 deletions p2p/cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import (
"fmt"
"math/big"
"os"
"path/filepath"
"slices"
Expand Down Expand Up @@ -199,6 +200,19 @@ var (
Value: contracts.TestnetContracts.BlockTracker,
})

optionAutodepositAmount = altsrc.NewStringFlag(&cli.StringFlag{
Name: "autodeposit-amount",
Usage: "amount to auto deposit",
EnvVars: []string{"MEV_COMMIT_AUTODEPOSIT_AMOUNT"},
})

optionAutodepositEnabled = altsrc.NewBoolFlag(&cli.BoolFlag{
Name: "autodeposit-enabled",
Usage: "enable auto deposit",
EnvVars: []string{"MEV_COMMIT_AUTODEPOSIT_ENABLED"},
Value: false,
})

optionSettlementRPCEndpoint = altsrc.NewStringFlag(&cli.StringFlag{
Name: "settlement-rpc-endpoint",
Usage: "rpc endpoint of the settlement layer",
Expand Down Expand Up @@ -260,6 +274,8 @@ func main() {
optionProviderRegistryAddr,
optionPreconfStoreAddr,
optionBlockTrackerAddr,
optionAutodepositAmount,
optionAutodepositEnabled,
optionSettlementRPCEndpoint,
optionSettlementWSRPCEndpoint,
optionNATAddr,
Expand Down Expand Up @@ -326,6 +342,16 @@ func launchNodeWithConfig(c *cli.Context) error {
natAddr = fmt.Sprintf("%s:%d", c.String(optionNATAddr.Name), c.Int(optionNATPort.Name))
}

var (
autodepositAmount *big.Int
ok bool
)
if c.String(optionAutodepositAmount.Name) != "" && c.Bool(optionAutodepositEnabled.Name) {
autodepositAmount, ok = new(big.Int).SetString(c.String(optionAutodepositAmount.Name), 10)
if !ok {
return fmt.Errorf("failed to parse autodeposit amount %q", c.String(optionAutodepositAmount.Name))
}
}
crtFile := c.String(optionServerTLSCert.Name)
keyFile := c.String(optionServerTLSPrivateKey.Name)
if (crtFile == "") != (keyFile == "") {
Expand All @@ -346,6 +372,7 @@ func launchNodeWithConfig(c *cli.Context) error {
ProviderRegistryContract: c.String(optionProviderRegistryAddr.Name),
BidderRegistryContract: c.String(optionBidderRegistryAddr.Name),
BlockTrackerContract: c.String(optionBlockTrackerAddr.Name),
AutodepositAmount: autodepositAmount,
RPCEndpoint: c.String(optionSettlementRPCEndpoint.Name),
WSRPCEndpoint: c.String(optionSettlementWSRPCEndpoint.Name),
NatAddr: natAddr,
Expand Down
93 changes: 68 additions & 25 deletions p2p/pkg/autodepositor/autodepositor.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,19 @@ type BidderRegistryContract interface {
WithdrawFromWindows(opts *bind.TransactOpts, windows []*big.Int) (*types.Transaction, error)
}

type BlockTrackerContract interface {
GetCurrentWindow() (*big.Int, error)
}

type AutoDepositTracker struct {
startMu sync.Mutex
isWorking bool
eventMgr events.EventManager
deposits sync.Map
windowChan chan *blocktracker.BlocktrackerNewWindow
brContract BidderRegistryContract
btContract BlockTrackerContract
initialAmount *big.Int
optsGetter OptsGetter
logger *slog.Logger
cancelFunc context.CancelFunc
Expand All @@ -37,14 +43,18 @@ type AutoDepositTracker struct {
func New(
evtMgr events.EventManager,
brContract BidderRegistryContract,
btContract BlockTrackerContract,
optsGetter OptsGetter,
initialAmount *big.Int,
logger *slog.Logger,
) *AutoDepositTracker {
return &AutoDepositTracker{
eventMgr: evtMgr,
brContract: brContract,
btContract: btContract,
optsGetter: optsGetter,
windowChan: make(chan *blocktracker.BlocktrackerNewWindow, 1),
initialAmount: initialAmount,
logger: logger,
}
}
Expand All @@ -60,28 +70,76 @@ func (adt *AutoDepositTracker) Start(
return fmt.Errorf("auto deposit tracker is already running")
}

if startWindow == nil {
var err error
startWindow, err = adt.btContract.GetCurrentWindow()
if err != nil {
adt.logger.Error("failed to get current window", "error", err)
return err
}
// adding +2 as oracle runs two windows behind
startWindow = new(big.Int).Add(startWindow, big.NewInt(2))

}

eg, egCtx := errgroup.WithContext(context.Background())
egCtx, cancel := context.WithCancel(egCtx)
adt.cancelFunc = cancel

sub, err := adt.initSub(egCtx)

if err != nil {
return fmt.Errorf("error subscribing to event: %w", err)
}

err = adt.doInitialDeposit(ctx, startWindow, amount)
if err != nil {
return fmt.Errorf("failed to do initial deposit, err: %w", err)
}

adt.startAutodeposit(egCtx, eg, amount, sub)

started := make(chan struct{})
go func() {
close(started)
if err := eg.Wait(); err != nil {
adt.logger.Error("error in errgroup", "err", err)
}
adt.startMu.Lock()
adt.isWorking = false
adt.startMu.Unlock()
}()
select {
case <-ctx.Done():
return ctx.Err()
case <-started:
adt.isWorking = true
}
return nil
}

func (adt *AutoDepositTracker) doInitialDeposit(ctx context.Context, startWindow, amount *big.Int) error {
nextWindow := new(big.Int).Add(startWindow, big.NewInt(1))

opts, err := adt.optsGetter(ctx)
if err != nil {
return err
return fmt.Errorf("failed to get transact opts, err: %w", err)
}

opts.Value = big.NewInt(0).Mul(amount, big.NewInt(2))

// Make initial deposit for the first two windows
_, err = adt.brContract.DepositForWindows(opts, []*big.Int{startWindow, nextWindow})
if err != nil {
return err
return fmt.Errorf("failed to deposit for windows, err: %w", err)
}

adt.deposits.Store(startWindow.Uint64(), true)
adt.deposits.Store(nextWindow.Uint64(), true)

eg, egCtx := errgroup.WithContext(context.Background())
egCtx, cancel := context.WithCancel(egCtx)
adt.cancelFunc = cancel
return nil
}

func (adt *AutoDepositTracker) initSub(egCtx context.Context) (events.Subscription, error) {
evt := events.NewEventHandler(
"NewWindow",
func(update *blocktracker.BlocktrackerNewWindow) {
Expand All @@ -98,9 +156,12 @@ func (adt *AutoDepositTracker) Start(

sub, err := adt.eventMgr.Subscribe(evt)
if err != nil {
return fmt.Errorf("error subscribing to event: %w", err)
return nil, fmt.Errorf("error subscribing to event: %w", err)
}
return sub, nil
}

func (adt *AutoDepositTracker) startAutodeposit(egCtx context.Context, eg *errgroup.Group, amount *big.Int, sub events.Subscription) {
eg.Go(func() error {
for {
select {
Expand Down Expand Up @@ -161,24 +222,6 @@ func (adt *AutoDepositTracker) Start(
}
}
})

started := make(chan struct{})
go func() {
close(started)
if err := eg.Wait(); err != nil {
adt.logger.Error("error in errgroup", "err", err)
}
adt.startMu.Lock()
adt.isWorking = false
adt.startMu.Unlock()
}()
select {
case <-ctx.Done():
return ctx.Err()
case <-started:
adt.isWorking = true
}
return nil
}

func (adt *AutoDepositTracker) Stop() ([]*big.Int, error) {
Expand Down
36 changes: 31 additions & 5 deletions p2p/pkg/autodepositor/autodepositor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ func (m *MockBidderRegistryContract) WithdrawFromWindows(opts *bind.TransactOpts
return m.WithdrawFromWindowsFunc(opts, windows)
}

type MockBlockTrackerContract struct {
GetCurrentWindowFunc func() (*big.Int, error)
}

func (m *MockBlockTrackerContract) GetCurrentWindow() (*big.Int, error) {
return m.GetCurrentWindowFunc()
}

func TestAutoDepositTracker_Start(t *testing.T) {
t.Parallel()

Expand All @@ -47,6 +55,7 @@ func TestAutoDepositTracker_Start(t *testing.T) {
t.Fatal(err)
}

amount := big.NewInt(100)
logger := util.NewTestLogger(os.Stdout)
evtMgr := events.NewListener(logger, &btABI, &brABI)
brContract := &MockBidderRegistryContract{
Expand All @@ -57,17 +66,21 @@ func TestAutoDepositTracker_Start(t *testing.T) {
return types.NewTransaction(1, common.Address{}, nil, 0, nil, nil), nil
},
}
btContract := &MockBlockTrackerContract{
GetCurrentWindowFunc: func() (*big.Int, error) {
return big.NewInt(1), nil
},
}
optsGetter := func(ctx context.Context) (*bind.TransactOpts, error) {
return &bind.TransactOpts{}, nil
}

// Create AutoDepositTracker instance
adt := autodepositor.New(evtMgr, brContract, optsGetter, logger)
adt := autodepositor.New(evtMgr, brContract, btContract, optsGetter, nil, logger)

// Start AutoDepositTracker
ctx := context.Background()
startWindow := big.NewInt(2)
amount := big.NewInt(100)
err = adt.Start(ctx, startWindow, amount)
if err != nil {
t.Fatal(err)
Expand Down Expand Up @@ -150,12 +163,17 @@ func TestAutoDepositTracker_Start_CancelContext(t *testing.T) {
return types.NewTransaction(1, common.Address{}, nil, 0, nil, nil), nil
},
}
btContract := &MockBlockTrackerContract{
GetCurrentWindowFunc: func() (*big.Int, error) {
return big.NewInt(1), nil
},
}
optsGetter := func(ctx context.Context) (*bind.TransactOpts, error) {
return &bind.TransactOpts{}, nil
}

// Create AutoDepositTracker instance
adt := autodepositor.New(evtMgr, brContract, optsGetter, logger)
adt := autodepositor.New(evtMgr, brContract, btContract, optsGetter, nil, logger)

// Start AutoDepositTracker with a cancelable context
ctx, cancel := context.WithCancel(context.Background())
Expand Down Expand Up @@ -185,12 +203,13 @@ func TestAutoDepositTracker_Stop_NotRunning(t *testing.T) {
logger := util.NewTestLogger(io.Discard)
evtMgr := events.NewListener(logger, &btABI, &brABI)
brContract := &MockBidderRegistryContract{}
btContract := &MockBlockTrackerContract{}
optsGetter := func(ctx context.Context) (*bind.TransactOpts, error) {
return &bind.TransactOpts{}, nil
}

// Create AutoDepositTracker instance
adt := autodepositor.New(evtMgr, brContract, optsGetter, logger)
adt := autodepositor.New(evtMgr, brContract, btContract, optsGetter, nil, logger)

// Stop AutoDepositTracker when not running
_, err = adt.Stop()
Expand Down Expand Up @@ -220,12 +239,18 @@ func TestAutoDepositTracker_IsWorking(t *testing.T) {
return types.NewTransaction(1, common.Address{}, nil, 0, nil, nil), nil
},
}
btContract := &MockBlockTrackerContract{
GetCurrentWindowFunc: func() (*big.Int, error) {
return big.NewInt(1), nil
},
}

optsGetter := func(ctx context.Context) (*bind.TransactOpts, error) {
return &bind.TransactOpts{}, nil
}

// Create AutoDepositTracker instance
adt := autodepositor.New(evtMgr, brContract, optsGetter, logger)
adt := autodepositor.New(evtMgr, brContract, btContract, optsGetter, nil, logger)

// Assert initial IsWorking status
if adt.IsWorking() {
Expand Down Expand Up @@ -272,3 +297,4 @@ func publishNewWindow(
}
evtMgr.PublishLogEvent(context.Background(), testLog)
}

17 changes: 15 additions & 2 deletions p2p/pkg/node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"fmt"
"io"
"log/slog"
"math/big"
"net"
"net/http"
"strings"
Expand Down Expand Up @@ -74,6 +75,7 @@ type Options struct {
BlockTrackerContract string
ProviderRegistryContract string
BidderRegistryContract string
AutodepositAmount *big.Int
RPCEndpoint string
WSRPCEndpoint string
NatAddr string
Expand All @@ -82,8 +84,9 @@ type Options struct {
}

type Node struct {
cancelFunc context.CancelFunc
closers []io.Closer
cancelFunc context.CancelFunc
closers []io.Closer
autoDeposit *autodepositor.AutoDepositTracker
}

func NewNode(opts *Options) (*Node, error) {
Expand Down Expand Up @@ -439,10 +442,17 @@ func NewNode(opts *Options) (*Node, error) {
autoDeposit := autodepositor.New(
evtMgr,
bidderRegistry,
blockTrackerSession,
optsGetter,
opts.AutodepositAmount,
opts.Logger.With("component", "auto_deposit_tracker"),
)

if opts.AutodepositAmount != nil {
autoDeposit.Start(context.Background(), nil, opts.AutodepositAmount)
nd.autoDeposit = autoDeposit
}

bidderAPI := bidderapi.NewService(
opts.KeySigner.GetAddress(),
blocksPerWindow,
Expand Down Expand Up @@ -643,6 +653,9 @@ func (n *Node) Close() error {
for _, c := range n.closers {
err = errors.Join(err, c.Close())
}

_, adErr := n.autoDeposit.Stop()
errors.Join(err, adErr)

return err
}
Expand Down