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(validator): implement validator client and fix actions test #288

Merged
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
Prev Previous commit
feat(validator): apply PR Reviews
  • Loading branch information
sm-stack committed Apr 29, 2024
commit 6c80279ea2cb7f090e70e53331cfe920e416f63a
4 changes: 2 additions & 2 deletions kroma-chain-ops/genesis/layer_one.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ func PostProcessL1DeveloperGenesis(stateDB *state.MemoryStateDB, deployments *L1
stateDB.SetCode(predeploys.BeaconDepositContractAddr, predeploys.BeaconDepositContractCode)

//setup governance token balances on L1
log.Info("Set GovernanceContract balance on L1")
log.Info("Set GovernanceToken balance on L1")
if !stateDB.Exist(deployments.L1GovernanceTokenProxy) {
return fmt.Errorf("l1GovernanceToken proxy doesn't exist at %s", deployments.L1GovernanceTokenProxy)
}
Expand All @@ -211,7 +211,7 @@ func PostProcessL1DeveloperGenesis(stateDB *state.MemoryStateDB, deployments *L1
val = common.BigToHash(bigVal)
for _, account := range DevAccounts {
addrToBytes := append(make([]byte, 12), account.Bytes()...)
addrSlot := crypto.Keccak256Hash(append(addrToBytes, slot.Bytes()[:]...))
addrSlot := crypto.Keccak256Hash(append(addrToBytes, slot.Bytes()...))
stateDB.SetState(deployments.L1GovernanceTokenProxy, addrSlot, val)

log.Info("Post process update", "name", "GovernanceToken", "address", deployments.L1GovernanceTokenProxy, "slot", addrSlot.Hex(), "afterVal", val.Hex())
Expand Down
140 changes: 66 additions & 74 deletions kroma-validator/challenger.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import (
"github.com/kroma-network/kroma/kroma-bindings/bindings"
chal "github.com/kroma-network/kroma/kroma-validator/challenge"
"github.com/kroma-network/kroma/kroma-validator/metrics"
val "github.com/kroma-network/kroma/kroma-validator/validator"
)

var deletedOutputRoot = [32]byte{}
Expand All @@ -44,11 +43,11 @@ type Challenger struct {
l1Client *ethclient.Client
l2Client *ethclient.Client

l2ooContract *bindings.L2OutputOracle
l2ooABI *abi.ABI
l2OOContract *bindings.L2OutputOracle
l2OOABI *abi.ABI
colosseumContract *bindings.Colosseum
colosseumABI *abi.ABI
valpoolContract *bindings.ValidatorPoolCaller
valPoolContract *bindings.ValidatorPoolCaller
valManagerContract *bindings.ValidatorManagerCaller

submissionInterval *big.Int
Expand All @@ -57,9 +56,6 @@ type Challenger struct {
checkpoint *big.Int
requiredBondAmount *big.Int

seolaoh marked this conversation as resolved.
Show resolved Hide resolved
isValManagerEnabled bool
terminationIndex *big.Int

l2OutputSubmittedSub ethereum.Subscription
challengeCreatedSub ethereum.Subscription

Expand All @@ -80,17 +76,17 @@ func NewChallenger(cfg Config, l log.Logger, m metrics.Metricer) (*Challenger, e
return nil, err
}

l2ooContract, err := bindings.NewL2OutputOracle(cfg.L2OutputOracleAddr, cfg.L1Client)
l2OOContract, err := bindings.NewL2OutputOracle(cfg.L2OutputOracleAddr, cfg.L1Client)
if err != nil {
return nil, err
}

l2ooABI, err := bindings.L2OutputOracleMetaData.GetAbi()
l2OOABI, err := bindings.L2OutputOracleMetaData.GetAbi()
if err != nil {
return nil, err
}

valpoolContract, err := bindings.NewValidatorPoolCaller(cfg.ValidatorPoolAddr, cfg.L1Client)
valPoolContract, err := bindings.NewValidatorPoolCaller(cfg.ValidatorPoolAddr, cfg.L1Client)
if err != nil {
return nil, err
}
Expand All @@ -108,11 +104,11 @@ func NewChallenger(cfg Config, l log.Logger, m metrics.Metricer) (*Challenger, e
l1Client: cfg.L1Client,
l2Client: cfg.L2Client,

l2ooContract: l2ooContract,
l2ooABI: l2ooABI,
l2OOContract: l2OOContract,
l2OOABI: l2OOABI,
colosseumContract: colosseumContract,
colosseumABI: colosseumABI,
valpoolContract: valpoolContract,
valPoolContract: valPoolContract,
valManagerContract: valManagerContract,
}, nil
}
Expand All @@ -123,23 +119,23 @@ func (c *Challenger) InitConfig(ctx context.Context) error {
err := contractWatcher.WatchUpgraded(c.cfg.L2OutputOracleAddr, func() error {
cCtx, cCancel := context.WithTimeout(ctx, c.cfg.NetworkTimeout)
defer cCancel()
submissionInterval, err := c.l2ooContract.SUBMISSIONINTERVAL(optsutils.NewSimpleCallOpts(cCtx))
submissionInterval, err := c.l2OOContract.SUBMISSIONINTERVAL(optsutils.NewSimpleCallOpts(cCtx))
if err != nil {
return fmt.Errorf("failed to get submission interval: %w", err)
}
c.submissionInterval = submissionInterval

cCtx, cCancel = context.WithTimeout(ctx, c.cfg.NetworkTimeout)
defer cCancel()
l2BlockTime, err := c.l2ooContract.L2BLOCKTIME(optsutils.NewSimpleCallOpts(cCtx))
l2BlockTime, err := c.l2OOContract.L2BLOCKTIME(optsutils.NewSimpleCallOpts(cCtx))
if err != nil {
return fmt.Errorf("failed to get l2 block time: %w", err)
}
c.l2BlockTime = l2BlockTime

cCtx, cCancel = context.WithTimeout(ctx, c.cfg.NetworkTimeout)
defer cCancel()
finalizationPeriodSeconds, err := c.l2ooContract.FINALIZATIONPERIODSECONDS(optsutils.NewSimpleCallOpts(cCtx))
finalizationPeriodSeconds, err := c.l2OOContract.FINALIZATIONPERIODSECONDS(optsutils.NewSimpleCallOpts(cCtx))
if err != nil {
return fmt.Errorf("failed to get finalization period seconds: %w", err)
}
Expand All @@ -148,48 +144,22 @@ func (c *Challenger) InitConfig(ctx context.Context) error {
return nil
})
if err != nil {
return fmt.Errorf("failed to initiate l2oo config: %w", err)
return fmt.Errorf("failed to initiate l2OO config: %w", err)
}

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))
requiredBondAmount, err := c.valPoolContract.REQUIREDBONDAMOUNT(optsutils.NewSimpleCallOpts(cCtx))
if err != nil {
return fmt.Errorf("failed to get submission interval: %w", err)
}
c.requiredBondAmount = requiredBondAmount

cCtx, cCancel = context.WithTimeout(ctx, c.cfg.NetworkTimeout)
defer cCancel()
nextOutputIndex, err := c.l2ooContract.NextOutputIndex(optsutils.NewSimpleCallOpts(cCtx))
if err != nil {
return fmt.Errorf("failed to get latest output index: %w", err)
}

cCtx, cCancel = context.WithTimeout(ctx, c.cfg.NetworkTimeout)
defer cCancel()
isTerminated, err := c.valpoolContract.IsTerminated(
optsutils.NewSimpleCallOpts(cCtx),
nextOutputIndex,
)
if err != nil {
return fmt.Errorf("failed to whether valpool is terminated or not: %w", err)
}
c.isValManagerEnabled = isTerminated

cCtx, cCancel = context.WithTimeout(ctx, c.cfg.NetworkTimeout)
defer cCancel()
terminationIndex, err := c.valpoolContract.TERMINATEOUTPUTINDEX(optsutils.NewSimpleCallOpts(cCtx))
if err != nil {
return fmt.Errorf("failed to get termination index: %w", err)
}
c.terminationIndex = terminationIndex

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

return nil
Expand All @@ -205,7 +175,7 @@ func (c *Challenger) initSub() {
if err != nil {
c.log.Warn("resubscribing after failed OutputSubmitted event", "err", err)
}
return c.l2ooContract.WatchOutputSubmitted(opts, c.l2OutputSubmittedEventChan, nil, nil, nil)
return c.l2OOContract.WatchOutputSubmitted(opts, c.l2OutputSubmittedEventChan, nil, nil, nil)
})
}

Expand Down Expand Up @@ -292,7 +262,7 @@ func (c *Challenger) loop() {
func (c *Challenger) updateCheckpoint() error {
cCtx, cCancel := context.WithTimeout(c.ctx, c.cfg.NetworkTimeout)
defer cCancel()
nextOutputIndex, err := c.l2ooContract.NextOutputIndex(optsutils.NewSimpleCallOpts(cCtx))
nextOutputIndex, err := c.l2OOContract.NextOutputIndex(optsutils.NewSimpleCallOpts(cCtx))
if err != nil {
return fmt.Errorf("failed to get the latest output index: %w", err)
}
Expand Down Expand Up @@ -322,7 +292,7 @@ func (c *Challenger) scanPrevOutputs() error {
// The fromBlock is the maximum value of either genesis block(1) or the first block of the finalization window
fromBlock := math.BigMax(common.Big1, finalizationStartL1Block)

outputSubmittedEvent := c.l2ooABI.Events[KeyEventOutputSubmitted]
outputSubmittedEvent := c.l2OOABI.Events[KeyEventOutputSubmitted]
challengeCreatedEvent := c.colosseumABI.Events[KeyEventChallengeCreated]

addresses := []common.Address{c.cfg.ColosseumAddr}
Expand Down Expand Up @@ -380,10 +350,6 @@ func (c *Challenger) subscribeL2OutputSubmitted() {
select {
case ev := <-c.l2OutputSubmittedEventChan:
c.log.Info("watched output submitted event", "l2BlockNumber", ev.L2BlockNumber, "outputRoot", ev.OutputRoot, "outputIndex", ev.L2OutputIndex)
// if the emitted output index is greater than the termination output index, set the config to use the ValidatorManager
if ev.L2OutputIndex.Cmp(c.terminationIndex) > 0 {
c.isValManagerEnabled = true
}
// if the emitted output index is less than or equal to the checkpoint, it is considered reorg occurred.
if ev.L2OutputIndex.Cmp(c.checkpoint) <= 0 {
c.wg.Add(1)
Expand Down Expand Up @@ -479,7 +445,7 @@ func (c *Challenger) handleOutput(outputIndex *big.Int) {
return
}

canCreateChallenge, err := c.CanCreateChallenge(c.ctx)
canCreateChallenge, err := c.CanCreateChallenge(c.ctx, outputIndex)
if err != nil {
c.log.Error(err.Error())
continue
Expand Down Expand Up @@ -586,17 +552,22 @@ func (c *Challenger) handleChallenge(outputIndex *big.Int, asserter common.Addre

// if challenger
if isChallenger && c.cfg.ChallengerEnabled {
// if output has been already deleted, cancel challenge to refund pending bond
if isOutputDeleted && status != chal.StatusChallengerTimeout {
tx, err := c.CancelChallenge(c.ctx, outputIndex)
if err != nil {
c.log.Error("failed to create cancel challenge tx", "err", err, "outputIndex", outputIndex)
continue
}
if err := c.submitChallengeTx(tx); err != nil {
c.log.Error("failed to submit cancel challenge tx", "err", err, "outputIndex", outputIndex)
continue
if isOutputDeleted {
// if output has been already deleted, cancel challenge to refund pending bond in ValidatorPool
if !c.IsValPoolTerminated(outputIndex) && status != chal.StatusChallengerTimeout {
tx, err := c.CancelChallenge(c.ctx, outputIndex)
if err != nil {
c.log.Error("failed to create cancel challenge tx", "err", err, "outputIndex", outputIndex)
continue
}
if err := c.submitChallengeTx(tx); err != nil {
c.log.Error("failed to submit cancel challenge tx", "err", err, "outputIndex", outputIndex)
continue
}
}
// if output has been already deleted, terminate handling
c.log.Info("output is already deleted when handling challenge", "outputIndex", outputIndex)
return
}

// if output is already finalized, terminate handling
Expand Down Expand Up @@ -640,24 +611,29 @@ func (c *Challenger) submitChallengeTx(tx *types.Transaction) error {
}

// CanCreateChallenge checks if challenger is in the status that can make challenge.
func (c *Challenger) CanCreateChallenge(ctx context.Context) (bool, error) {
func (c *Challenger) CanCreateChallenge(ctx context.Context, outputIndex *big.Int) (bool, error) {
cCtx, cCancel := context.WithTimeout(ctx, c.cfg.NetworkTimeout)
defer cCancel()
from := c.cfg.TxManager.From()
if c.isValManagerEnabled {
vaultStatus, err := c.valManagerContract.GetStatus(optsutils.NewSimpleCallOpts(cCtx), from)
if c.IsValPoolTerminated(outputIndex) {
validatorStatus, err := c.valManagerContract.GetStatus(optsutils.NewSimpleCallOpts(cCtx), from)
if err != nil {
return false, fmt.Errorf("failed to fetch the vault status: %w", err)
return false, fmt.Errorf("failed to fetch the validator status: %w", err)
}

if vaultStatus != val.StatusCanSubmitOutput {
c.log.Warn("vault is not in the status to make a challenge", "status", vaultStatus)
if isInJail, err := c.IsInJail(ctx); err != nil {
return false, err
} else if isInJail {
c.log.Warn("validator is in jail")
return false, nil
}

c.log.Info("vault status", "status", vaultStatus)
if validatorStatus != StatusActive {
c.log.Warn("validator is not in the status that can create a challenge", "status", validatorStatus)
return false, nil
}
0xHansLee marked this conversation as resolved.
Show resolved Hide resolved
} else {
balance, err := c.valpoolContract.BalanceOf(optsutils.NewSimpleCallOpts(cCtx), from)
balance, err := c.valPoolContract.BalanceOf(optsutils.NewSimpleCallOpts(cCtx), from)
if err != nil {
return false, fmt.Errorf("failed to fetch deposit amount: %w", err)
}
Expand All @@ -672,12 +648,28 @@ func (c *Challenger) CanCreateChallenge(ctx context.Context) (bool, error) {
return false, nil
}

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

return true, nil
}

func (c *Challenger) IsValPoolTerminated(outputIndex *big.Int) bool {
0xHansLee marked this conversation as resolved.
Show resolved Hide resolved
return c.cfg.ValPoolTerminationIndex.Cmp(outputIndex) < 0
}

func (c *Challenger) IsInJail(ctx context.Context) (bool, error) {
cCtx, cCancel := context.WithTimeout(ctx, c.cfg.NetworkTimeout)
defer cCancel()
from := c.cfg.TxManager.From()
isInJail, err := c.valManagerContract.InJail(optsutils.NewSimpleCallOpts(cCtx), from)
if err != nil {
return false, fmt.Errorf("failed to fetch the jail status: %w", err)
}

return isInJail, nil
}

func (c *Challenger) IsInChallengeCreationPeriod(ctx context.Context, outputIndex *big.Int) (bool, error) {
cCtx, cCancel := context.WithTimeout(ctx, c.cfg.NetworkTimeout)
defer cCancel()
Expand All @@ -687,7 +679,7 @@ func (c *Challenger) IsInChallengeCreationPeriod(ctx context.Context, outputInde
func (c *Challenger) IsOutputFinalized(ctx context.Context, outputIndex *big.Int) (bool, error) {
cCtx, cCancel := context.WithTimeout(ctx, c.cfg.NetworkTimeout)
defer cCancel()
return c.l2ooContract.IsFinalized(optsutils.NewSimpleCallOpts(cCtx), outputIndex)
return c.l2OOContract.IsFinalized(optsutils.NewSimpleCallOpts(cCtx), outputIndex)
}

func (c *Challenger) GetChallenge(ctx context.Context, outputIndex *big.Int, challenger common.Address) (bindings.TypesChallenge, error) {
Expand Down Expand Up @@ -759,7 +751,7 @@ type Outputs struct {
func (c *Challenger) OutputsAtIndex(ctx context.Context, outputIndex *big.Int) (*Outputs, error) {
cCtx, cCancel := context.WithTimeout(ctx, c.cfg.NetworkTimeout)
defer cCancel()
RemoteOutput, err := c.l2ooContract.GetL2Output(optsutils.NewSimpleCallOpts(cCtx), outputIndex)
RemoteOutput, err := c.l2OOContract.GetL2Output(optsutils.NewSimpleCallOpts(cCtx), outputIndex)
if err != nil {
return nil, err
}
Expand Down
21 changes: 18 additions & 3 deletions kroma-validator/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package validator
import (
"context"
"errors"
"math/big"
"time"

"github.com/ethereum/go-ethereum/common"
Expand All @@ -15,10 +16,12 @@ import (
"github.com/ethereum-optimism/optimism/op-service/dial"
oplog "github.com/ethereum-optimism/optimism/op-service/log"
opmetrics "github.com/ethereum-optimism/optimism/op-service/metrics"
"github.com/ethereum-optimism/optimism/op-service/optsutils"
pprof "github.com/ethereum-optimism/optimism/op-service/pprof"
oprpc "github.com/ethereum-optimism/optimism/op-service/rpc"
"github.com/ethereum-optimism/optimism/op-service/sources"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/kroma-network/kroma/kroma-bindings/bindings"
chal "github.com/kroma-network/kroma/kroma-validator/challenge"
"github.com/kroma-network/kroma/kroma-validator/flags"
"github.com/kroma-network/kroma/kroma-validator/metrics"
Expand All @@ -31,9 +34,9 @@ type Config struct {
ColosseumAddr common.Address
SecurityCouncilAddr common.Address
ValidatorPoolAddr common.Address
ValPoolTerminationIndex *big.Int
ValidatorManagerAddr common.Address
AssetManagerAddr common.Address
GovTokenAddr common.Address
ChallengerPollInterval time.Duration
NetworkTimeout time.Duration
TxManager *txmgr.BufferedTxManager
Expand Down Expand Up @@ -180,7 +183,7 @@ func NewConfig(ctx *cli.Context) CLIConfig {

// NewValidatorConfig creates a validator config with given the CLIConfig
func NewValidatorConfig(cfg CLIConfig, l log.Logger, m metrics.Metricer) (*Config, error) {
l2ooAddress, err := opservice.ParseAddress(cfg.L2OOAddress)
l2OOAddress, err := opservice.ParseAddress(cfg.L2OOAddress)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -252,11 +255,23 @@ func NewValidatorConfig(cfg CLIConfig, l log.Logger, m metrics.Metricer) (*Confi
return nil, err
}

cCtx, cCancel := context.WithTimeout(ctx, time.Second*20)
defer cCancel()
valPoolContract, err := bindings.NewValidatorPoolCaller(valPoolAddress, l1Client)
if err != nil {
return nil, err
}
valPoolTerminationIndex, err := valPoolContract.TERMINATEOUTPUTINDEX(optsutils.NewSimpleCallOpts(cCtx))
if err != nil {
return nil, err
}

return &Config{
L2OutputOracleAddr: l2ooAddress,
L2OutputOracleAddr: l2OOAddress,
ColosseumAddr: colosseumAddress,
SecurityCouncilAddr: securityCouncilAddress,
ValidatorPoolAddr: valPoolAddress,
ValPoolTerminationIndex: valPoolTerminationIndex,
ValidatorManagerAddr: valManagerAddress,
AssetManagerAddr: assetManagerAddress,
ChallengerPollInterval: cfg.ChallengerPollInterval,
Expand Down
Loading
Loading