Skip to content

Commit

Permalink
feat: add check for bond amount at validator system v2
Browse files Browse the repository at this point in the history
  • Loading branch information
sm-stack committed Jul 24, 2024
1 parent 65bc391 commit a3d2c5f
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 49 deletions.
69 changes: 53 additions & 16 deletions kroma-validator/challenger.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,14 @@ type Challenger struct {
colosseumABI *abi.ABI
valPoolContract *bindings.ValidatorPoolCaller
valMgrContract *bindings.ValidatorManagerCaller
assetMgrContract *bindings.AssetManagerCaller

submissionInterval *big.Int
finalizationPeriodSeconds *big.Int
l2BlockTime *big.Int
checkpoint *big.Int
requiredBondAmount *big.Int
requiredBondAmountV1 *big.Int
requiredBondAmountV2 *big.Int
valPoolTerminationIndex *big.Int

l2OutputSubmittedSub ethereum.Subscription
Expand Down Expand Up @@ -97,6 +99,11 @@ func NewChallenger(cfg Config, l log.Logger, m metrics.Metricer) (*Challenger, e
return nil, err
}

assetMgrContract, err := bindings.NewAssetManagerCaller(cfg.AssetManagerAddr, cfg.L1Client)
if err != nil {
return nil, err
}

return &Challenger{
log: l.New("service", "challenge"),
cfg: cfg,
Expand All @@ -111,6 +118,7 @@ func NewChallenger(cfg Config, l log.Logger, m metrics.Metricer) (*Challenger, e
colosseumABI: colosseumABI,
valPoolContract: valPoolContract,
valMgrContract: valMgrContract,
assetMgrContract: assetMgrContract,
}, nil
}

Expand Down Expand Up @@ -151,18 +159,18 @@ func (c *Challenger) InitConfig(ctx context.Context) error {
err = contractWatcher.WatchUpgraded(c.cfg.ValidatorPoolAddr, func() error {
cCtx, cCancel := context.WithTimeout(ctx, c.cfg.NetworkTimeout)
defer cCancel()
requiredBondAmount, err := c.valPoolContract.REQUIREDBONDAMOUNT(optsutils.NewSimpleCallOpts(cCtx))
requiredBondAmountV1, err := c.valPoolContract.REQUIREDBONDAMOUNT(optsutils.NewSimpleCallOpts(cCtx))
if err != nil {
return fmt.Errorf("failed to get submission interval: %w", err)
}
c.requiredBondAmount = requiredBondAmount
c.requiredBondAmountV1 = requiredBondAmountV1

cCtx, cCancel = context.WithTimeout(ctx, c.cfg.NetworkTimeout)
defer cCancel()
valPoolTerminationIndex, err := c.valPoolContract.TERMINATEOUTPUTINDEX(optsutils.NewSimpleCallOpts(cCtx))
if err != nil {
// If method is not in ValidatorPool, set the termination index to big value to ensure it sticks to validator system V1.
if errors.Is(err, ErrMethodNotFound) {
if errors.Is(err, errors.New("method 'TERMINATION_OUTPUT_INDEX' not found")) {
valPoolTerminationIndex = big.NewInt(math.MaxUint32)
} else {
return fmt.Errorf("failed to get valPool termination index: %w", err)
Expand All @@ -176,6 +184,24 @@ func (c *Challenger) InitConfig(ctx context.Context) error {
return fmt.Errorf("failed to initiate valPool config: %w", err)
}

err = contractWatcher.WatchUpgraded(c.cfg.AssetManagerAddr, func() error {
cCtx, cCancel := context.WithTimeout(ctx, c.cfg.NetworkTimeout)
defer cCancel()
requiredBondAmountV2, err := c.assetMgrContract.BONDAMOUNT(optsutils.NewSimpleCallOpts(cCtx))
if err != nil {
if errors.Is(err, errors.New("method 'BOND_AMOUNT' not found")) {
requiredBondAmountV2 = big.NewInt(0)
}
return fmt.Errorf("failed to get required bond amount: %w", err)
}
c.requiredBondAmountV2 = requiredBondAmountV2

return nil
})
if err != nil {
return fmt.Errorf("failed to initiate assetMgr config: %w, err")
}

return nil
}

Expand Down Expand Up @@ -637,6 +663,7 @@ func (c *Challenger) CanCreateChallenge(ctx context.Context, outputIndex *big.In
cCtx, cCancel := context.WithTimeout(ctx, c.cfg.NetworkTimeout)
defer cCancel()
from := c.cfg.TxManager.From()
var balance, requiredBondAmount *big.Int
if c.IsValPoolTerminated(outputIndex) {
if isInJail, err := c.isInJail(ctx); err != nil {
return false, err
Expand All @@ -655,25 +682,35 @@ func (c *Challenger) CanCreateChallenge(ctx context.Context, outputIndex *big.In
c.log.Warn("validator is not in the status that can create a challenge", "status", validatorStatus)
return false, nil
}

balance, err = c.assetMgrContract.TotalValidatorBalance(optsutils.NewSimpleCallOpts(cCtx), from)
if err != nil {
return false, fmt.Errorf("failed to fetch balance: %w", err)
}
requiredBondAmount = c.requiredBondAmountV2
} else {
balance, err := c.valPoolContract.BalanceOf(optsutils.NewSimpleCallOpts(cCtx), from)
var err error
balance, err = c.valPoolContract.BalanceOf(optsutils.NewSimpleCallOpts(cCtx), from)
if err != nil {
return false, fmt.Errorf("failed to fetch deposit amount: %w", err)
}
c.metr.RecordDepositAmount(balance)

if balance.Cmp(c.requiredBondAmount) == -1 {
c.log.Warn(
"deposit is less than bond attempt amount",
"requiredBondAmount", c.requiredBondAmount,
"deposit", balance,
)
return false, nil
}
requiredBondAmount = c.requiredBondAmountV1
}

c.log.Info("deposit amount and bond amount", "deposit", balance, "bond", c.requiredBondAmount)
c.metr.RecordDepositAmount(balance)

// Check if the deposit amount is less than the required bond amount
if balance.Cmp(requiredBondAmount) == -1 {
c.log.Warn(
"deposit is less than bond attempt amount",
"requiredBondAmount", requiredBondAmount,
"deposit", balance,
)
return false, nil
}

c.log.Info("deposit amount and bond amount", "deposit", balance, "bond", requiredBondAmount)

return true, nil
}

Expand Down
96 changes: 63 additions & 33 deletions kroma-validator/l2_output_submitter.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ const (
)

var PublicRoundAddress = common.HexToAddress(publicRoundHex)
var ErrMethodNotFound = errors.New("method 'TERMINATION_OUTPUT_INDEX' not found")

// L2OutputSubmitter is responsible for submitting outputs.
type L2OutputSubmitter struct {
Expand All @@ -42,15 +41,16 @@ type L2OutputSubmitter struct {
log log.Logger
metr metrics.Metricer

l2OOContract *bindings.L2OutputOracleCaller
l2OOABI *abi.ABI
valPoolContract *bindings.ValidatorPoolCaller
valMgrContract *bindings.ValidatorManagerCaller
valMgrAbi *abi.ABI
l2OOContract *bindings.L2OutputOracleCaller
l2OOABI *abi.ABI
valPoolContract *bindings.ValidatorPoolCaller
valMgrContract *bindings.ValidatorManagerCaller
assetMgrContract *bindings.AssetManagerCaller

singleRoundInterval *big.Int
l2BlockTime *big.Int
requiredBondAmount *big.Int
requiredBondAmountV1 *big.Int
requiredBondAmountV2 *big.Int
valPoolTerminationIndex *big.Int

submitChan chan struct{}
Expand All @@ -70,30 +70,30 @@ func NewL2OutputSubmitter(cfg Config, l log.Logger, m metrics.Metricer) (*L2Outp
return nil, err
}

parsedValMgrAbi, err := bindings.ValidatorManagerMetaData.GetAbi()
valPoolContract, err := bindings.NewValidatorPoolCaller(cfg.ValidatorPoolAddr, cfg.L1Client)
if err != nil {
return nil, err
}

valPoolContract, err := bindings.NewValidatorPoolCaller(cfg.ValidatorPoolAddr, cfg.L1Client)
valMgrContract, err := bindings.NewValidatorManagerCaller(cfg.ValidatorManagerAddr, cfg.L1Client)
if err != nil {
return nil, err
}

valMgrContract, err := bindings.NewValidatorManagerCaller(cfg.ValidatorManagerAddr, cfg.L1Client)
assetMgrContract, err := bindings.NewAssetManagerCaller(cfg.AssetManagerAddr, cfg.L1Client)
if err != nil {
return nil, err
}

return &L2OutputSubmitter{
cfg: cfg,
log: l.New("service", "submitter"),
metr: m,
l2OOContract: l2OOContract,
l2OOABI: parsedL2OOAbi,
valPoolContract: valPoolContract,
valMgrContract: valMgrContract,
valMgrAbi: parsedValMgrAbi,
cfg: cfg,
log: l.New("service", "submitter"),
metr: m,
l2OOContract: l2OOContract,
l2OOABI: parsedL2OOAbi,
valPoolContract: valPoolContract,
valMgrContract: valMgrContract,
assetMgrContract: assetMgrContract,
}, nil
}

Expand Down Expand Up @@ -127,18 +127,18 @@ func (l *L2OutputSubmitter) InitConfig(ctx context.Context) error {
err = contractWatcher.WatchUpgraded(l.cfg.ValidatorPoolAddr, func() error {
cCtx, cCancel := context.WithTimeout(ctx, l.cfg.NetworkTimeout)
defer cCancel()
requiredBondAmount, err := l.valPoolContract.REQUIREDBONDAMOUNT(optsutils.NewSimpleCallOpts(cCtx))
requiredBondAmountV1, err := l.valPoolContract.REQUIREDBONDAMOUNT(optsutils.NewSimpleCallOpts(cCtx))
if err != nil {
return fmt.Errorf("failed to get required bond amount: %w", err)
}
l.requiredBondAmount = requiredBondAmount
l.requiredBondAmountV1 = requiredBondAmountV1

cCtx, cCancel = context.WithTimeout(ctx, l.cfg.NetworkTimeout)
defer cCancel()
valPoolTerminationIndex, err := l.valPoolContract.TERMINATEOUTPUTINDEX(optsutils.NewSimpleCallOpts(cCtx))
if err != nil {
// If method is not in ValidatorPool, set the termination index to big value to ensure it sticks to validator system V1.
if errors.Is(err, ErrMethodNotFound) {
if errors.Is(err, errors.New("method 'TERMINATION_OUTPUT_INDEX' not found")) {
valPoolTerminationIndex = big.NewInt(math.MaxUint32)
} else {
return fmt.Errorf("failed to get valPool termination index: %w", err)
Expand All @@ -152,6 +152,24 @@ func (l *L2OutputSubmitter) InitConfig(ctx context.Context) error {
return fmt.Errorf("failed to initiate valPool config: %w", err)
}

err = contractWatcher.WatchUpgraded(l.cfg.AssetManagerAddr, func() error {
cCtx, cCancel := context.WithTimeout(ctx, l.cfg.NetworkTimeout)
defer cCancel()
requiredBondAmountV2, err := l.assetMgrContract.BONDAMOUNT(optsutils.NewSimpleCallOpts(cCtx))
if err != nil {
if errors.Is(err, errors.New("method 'BOND_AMOUNT' not found")) {
requiredBondAmountV2 = big.NewInt(0)
}
return fmt.Errorf("failed to get required bond amount: %w", err)
}
l.requiredBondAmountV2 = requiredBondAmountV2

return nil
})
if err != nil {
return fmt.Errorf("failed to initiate assetMgr config: %w, err")
}

return nil
}

Expand Down Expand Up @@ -307,6 +325,8 @@ func (l *L2OutputSubmitter) CalculateWaitTime(ctx context.Context, nextBlockNumb
func (l *L2OutputSubmitter) assertCanSubmitOutput(ctx context.Context, outputIndex *big.Int) error {
cCtx, cCancel := context.WithTimeout(ctx, l.cfg.NetworkTimeout)
defer cCancel()
from := l.cfg.TxManager.From()
var balance, requiredBondAmount *big.Int
if l.IsValPoolTerminated(outputIndex) {
if isInJail, err := l.IsInJail(ctx); err != nil {
return err
Expand All @@ -325,25 +345,35 @@ func (l *L2OutputSubmitter) assertCanSubmitOutput(ctx context.Context, outputInd
l.log.Warn("validator is not in the status to submit output", "currentStatus", validatorStatus)
return nil
}

balance, err = l.assetMgrContract.TotalValidatorBalance(optsutils.NewSimpleCallOpts(cCtx), from)
if err != nil {
return fmt.Errorf("failed to fetch balance: %w", err)
}
requiredBondAmount = l.requiredBondAmountV2
} else {
balance, err := l.valPoolContract.BalanceOf(optsutils.NewSimpleCallOpts(cCtx), l.cfg.TxManager.From())
var err error
balance, err = l.valPoolContract.BalanceOf(optsutils.NewSimpleCallOpts(cCtx), from)
if err != nil {
return fmt.Errorf("failed to fetch deposit amount: %w", err)
}
l.metr.RecordDepositAmount(balance)

if balance.Cmp(l.requiredBondAmount) == -1 {
l.log.Warn(
"deposit is less than bond attempt amount",
"requiredBondAmount", l.requiredBondAmount,
"deposit", balance,
)
return nil
}
requiredBondAmount = l.requiredBondAmountV1
}

l.log.Info("deposit amount and bond amount", "deposit", balance, "bond", l.requiredBondAmount)
l.metr.RecordDepositAmount(balance)

// Check if the deposit amount is less than the required bond amount
if balance.Cmp(requiredBondAmount) == -1 {
l.log.Warn(
"deposit is less than bond attempt amount",
"requiredBondAmount", requiredBondAmount,
"deposit", balance,
)
return nil
}

l.log.Info("deposit amount and bond amount", "deposit", balance, "bond", requiredBondAmount)

return nil
}

Expand Down

0 comments on commit a3d2c5f

Please sign in to comment.