Skip to content
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
8 changes: 7 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
// eslint-disable-next-line no-undef
module.exports = {
root: true,
env: {
browser: true,
es6: true,
},
ignorePatterns: ['dist', 'coverage', 'packages/contracts/hardhat'],
ignorePatterns: [
'dist',
'coverage',
'packages/contracts/hardhat',
'test/**/*.ts',
],
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
Expand Down
1 change: 1 addition & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ You'll need the following:
- [Yarn](https://classic.yarnpkg.com/en/docs/install)
- [Docker](https://docs.docker.com/get-docker/)
- [Docker Compose](https://docs.docker.com/compose/install/)
- [Go](https://go.dev/dl/)
- [Foundry](https://getfoundry.sh)

### Setup
Expand Down
222 changes: 18 additions & 204 deletions bindings/bindings/kromaportal.go

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion bindings/bindings/kromaportal_more.go

Large diffs are not rendered by default.

156 changes: 109 additions & 47 deletions bindings/bindings/systemconfig.go

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions bindings/bindings/systemconfig_more.go

Large diffs are not rendered by default.

26 changes: 23 additions & 3 deletions components/batcher/batcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package batcher

import (
"context"
"errors"
"fmt"
"io"
"sync"
Expand Down Expand Up @@ -57,10 +58,14 @@ func Main(version string, cliCtx *cli.Context) error {

batcher, err := NewBatcher(ctx, *batcherCfg, l, m)
if err != nil {
l.Error("Unable to create batcher", "err", err)
return err
}

batcher.Start()
if err := batcher.Start(); err != nil {
l.Error("Unable to start batcher", "err", err)
return err
}
<-utils.WaitInterrupt()
batcher.Stop(context.Background())

Expand All @@ -72,6 +77,7 @@ type Batcher struct {
cancelShutdownCtx context.CancelFunc
killCtx context.Context
cancelKillCtx context.CancelFunc
running bool

cfg Config
l log.Logger
Expand Down Expand Up @@ -105,21 +111,33 @@ func NewBatcher(parentCtx context.Context, cfg Config, l log.Logger, m metrics.M
}, nil
}

func (b *Batcher) Start() {
func (b *Batcher) Start() error {
b.l.Info("starting Batcher")

if b.running {
return errors.New("batcher is already running")
}
b.running = true

b.shutdownCtx, b.cancelShutdownCtx = context.WithCancel(context.Background())
b.killCtx, b.cancelKillCtx = context.WithCancel(context.Background())

b.wg.Add(1)
go b.loop()

b.l.Info("Batcher started")

return nil
}

func (b *Batcher) Stop(ctx context.Context) {
func (b *Batcher) Stop(ctx context.Context) error {
b.l.Info("stopping Batcher")

if !b.running {
return errors.New("batcher is not running")
}
b.running = false

// go routine will call cancelKillCtx() if the passed in ctx is ever Done
cancelKill := b.cancelKillCtx
wrapped, cancel := context.WithCancel(ctx)
Expand All @@ -134,6 +152,8 @@ func (b *Batcher) Stop(ctx context.Context) {
b.cancelKillCtx()

b.l.Info("Batcher stopped")

return nil
}

// The following things occur:
Expand Down
2 changes: 2 additions & 0 deletions components/batcher/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ type CLIConfig struct {
// channel open. This allows to more eagerly send batcher transactions
// during times of low L2 transaction volume. Note that the effective
// L1-block distance between batcher transactions is then MaxChannelDuration
// + NumConfirmations because the batcher waits for NumConfirmations blocks
// after sending a batcher tx and only then starts a new channel.
//
// If 0, duration checks are disabled.
MaxChannelDuration uint64
Expand Down
10 changes: 5 additions & 5 deletions components/batcher/metrics/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ type Metrics struct {
Info prometheus.GaugeVec
Up prometheus.Gauge

// label by openend, closed, fully_submitted, timed_out
// label by opened, closed, fully_submitted, timed_out
ChannelEvs kmetrics.EventVec

PendingBlocksCount prometheus.GaugeVec
Expand Down Expand Up @@ -153,16 +153,16 @@ func (m *Metrics) Serve(ctx context.Context, host string, port int) error {
return kmetrics.ListenAndServe(ctx, m.registry, host, port)
}

func (m *Metrics) Document() []kmetrics.DocumentedMetric {
return m.factory.Document()
}

func (m *Metrics) StartBalanceMetrics(ctx context.Context,
l log.Logger, client *ethclient.Client, account common.Address,
) {
kmetrics.LaunchBalanceMetrics(ctx, l, m.registry, m.ns, client, account)
}

func (m *Metrics) Document() []kmetrics.DocumentedMetric {
return m.factory.Document()
}

// RecordInfo sets a pseudo-metric that contains versioning and
// config info for the kroma-batcher.
func (m *Metrics) RecordInfo(version string) {
Expand Down
14 changes: 14 additions & 0 deletions components/node/p2p/mocks/ConnectionGater.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion components/node/p2p/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ const (
)

func PayloadByNumberProtocolID(l2ChainID *big.Int) protocol.ID {
return protocol.ID(fmt.Sprintf("/opstack/req/payload_by_number/%d/0", l2ChainID))
return protocol.ID(fmt.Sprintf("/kroma-stack/req/payload_by_number/%d/0", l2ChainID))
}

type requestHandlerFn func(ctx context.Context, log log.Logger, stream network.Stream)
Expand Down
2 changes: 1 addition & 1 deletion components/node/rollup/driver/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ func (d *Driver) eventLoop() {
if !d.driverConfig.ProposerStopped {
resp.err <- errors.New("proposer already running")
} else if !bytes.Equal(unsafeHead[:], resp.hash[:]) {
resp.err <- fmt.Errorf("block hash does not match: head %d, received %d", unsafeHead.String(), resp.hash.String())
resp.err <- fmt.Errorf("block hash does not match: head %s, received %s", unsafeHead.String(), resp.hash.String())
} else {
d.log.Info("Proposer has been started")
d.driverConfig.ProposerStopped = false
Expand Down
119 changes: 119 additions & 0 deletions e2e/actions/block_processor.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package actions

import (
"errors"
"fmt"
"math/big"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/consensus/misc"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/params"

"github.com/kroma-network/kroma/components/node/eth"
)

var (
ErrExceedsGasLimit = errors.New("tx gas exceeds block gas limit")
ErrUsesTooMuchGas = errors.New("action takes too much gas")
)

type BlockDataProvider interface {
StateAt(root common.Hash) (*state.StateDB, error)
GetHeader(common.Hash, uint64) *types.Header
Engine() consensus.Engine
GetVMConfig() *vm.Config
Config() *params.ChainConfig
consensus.ChainHeaderReader
}

type BlockProcessor struct {
header *types.Header
state *state.StateDB
receipts types.Receipts
transactions types.Transactions
gasPool *core.GasPool
dataProvider BlockDataProvider
}

func NewBlockProcessorFromPayloadAttributes(provider BlockDataProvider, parent common.Hash, params *eth.PayloadAttributes) (*BlockProcessor, error) {
header := &types.Header{
ParentHash: parent,
Coinbase: params.SuggestedFeeRecipient,
Difficulty: common.Big0,
GasLimit: uint64(*params.GasLimit),
Time: uint64(params.Timestamp),
Extra: nil,
MixDigest: common.Hash(params.PrevRandao),
Nonce: types.EncodeNonce(0),
}
return NewBlockProcessorFromHeader(provider, header)
}

func NewBlockProcessorFromHeader(provider BlockDataProvider, h *types.Header) (*BlockProcessor, error) {
header := types.CopyHeader(h) // Copy to avoid mutating the original header

if header.GasLimit > params.MaxGasLimit {
return nil, fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, params.MaxGasLimit)
}
parentHeader := provider.GetHeaderByHash(header.ParentHash)
if header.Time <= parentHeader.Time {
return nil, errors.New("invalid timestamp")
}
statedb, err := provider.StateAt(parentHeader.Root)
if err != nil {
return nil, fmt.Errorf("get parent state: %w", err)
}
header.Number = new(big.Int).Add(parentHeader.Number, common.Big1)
header.BaseFee = misc.CalcBaseFee(provider.Config(), parentHeader)
header.GasUsed = 0
gasPool := new(core.GasPool).AddGas(header.GasLimit)
return &BlockProcessor{
header: header,
state: statedb,
gasPool: gasPool,
dataProvider: provider,
}, nil
}

func (b *BlockProcessor) CheckTxWithinGasLimit(tx *types.Transaction) error {
if tx.Gas() > b.header.GasLimit {
return fmt.Errorf("%w tx gas: %d, block gas limit: %d", ErrExceedsGasLimit, tx.Gas(), b.header.GasLimit)
}
if tx.Gas() > b.gasPool.Gas() {
return fmt.Errorf("%w: %d, only have %d", ErrUsesTooMuchGas, tx.Gas(), b.gasPool.Gas())
}
return nil
}

func (b *BlockProcessor) AddTx(tx *types.Transaction) error {
txIndex := len(b.transactions)
b.state.SetTxContext(tx.Hash(), txIndex)
receipt, err := core.ApplyTransaction(b.dataProvider.Config(), b.dataProvider, &common.Address{},
b.gasPool, b.state, b.header, tx, &b.header.GasUsed, *b.dataProvider.GetVMConfig())
if err != nil {
return fmt.Errorf("failed to apply deposit transaction to L2 block (tx %d): %w", txIndex, err)
}
b.receipts = append(b.receipts, receipt)
b.transactions = append(b.transactions, tx)
return nil
}

func (b *BlockProcessor) Assemble() (*types.Block, error) {
return b.dataProvider.Engine().FinalizeAndAssemble(b.dataProvider, b.header, b.state, b.transactions, nil, b.receipts, nil)
}

func (b *BlockProcessor) Commit() error {
root, err := b.state.Commit(b.dataProvider.Config().IsEIP158(b.header.Number))
if err != nil {
return fmt.Errorf("state write error: %w", err)
}
if err := b.state.Database().TrieDB().Commit(root, false); err != nil {
return fmt.Errorf("trie write error: %w", err)
}
return nil
}
4 changes: 2 additions & 2 deletions e2e/actions/blocktime_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func TestBatchInLastPossibleBlocks(gt *testing.T) {
ChainID: sd.L2Cfg.Config.ChainID,
Nonce: n,
GasTipCap: big.NewInt(2 * params.GWei),
GasFeeCap: new(big.Int).Add(miner.l1Chain.CurrentBlock().BaseFee(), big.NewInt(2*params.GWei)),
GasFeeCap: new(big.Int).Add(miner.l1Chain.CurrentBlock().BaseFee, big.NewInt(2*params.GWei)),
Gas: params.TxGas,
To: &dp.Addresses.Bob,
Value: e2eutils.Ether(2),
Expand Down Expand Up @@ -147,7 +147,7 @@ func TestLargeL1Gaps(gt *testing.T) {
ChainID: sd.L2Cfg.Config.ChainID,
Nonce: n,
GasTipCap: big.NewInt(2 * params.GWei),
GasFeeCap: new(big.Int).Add(miner.l1Chain.CurrentBlock().BaseFee(), big.NewInt(2*params.GWei)),
GasFeeCap: new(big.Int).Add(miner.l1Chain.CurrentBlock().BaseFee, big.NewInt(2*params.GWei)),
Gas: params.TxGas,
To: &dp.Addresses.Bob,
Value: e2eutils.Ether(2),
Expand Down
4 changes: 2 additions & 2 deletions e2e/actions/fork_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func TestShapellaL1Fork(gt *testing.T) {

_, _, miner, proposer, _, syncer, _, batcher := setupReorgTestActors(t, dp, sd, log)

require.False(t, sd.L1Cfg.Config.IsShanghai(miner.l1Chain.CurrentBlock().Time()), "not active yet")
require.False(t, sd.L1Cfg.Config.IsShanghai(miner.l1Chain.CurrentBlock().Time), "not active yet")

// start nodes
proposer.ActL2PipelineFull(t)
Expand All @@ -34,7 +34,7 @@ func TestShapellaL1Fork(gt *testing.T) {

// verify Shanghai is active
l1Block := miner.l1Chain.CurrentBlock()
require.True(t, sd.L1Cfg.Config.IsShanghai(l1Block.Time()))
require.True(t, sd.L1Cfg.Config.IsShanghai(l1Block.Time))

// build L2 chain up to and including L2 blocks referencing shanghai L1 blocks
proposer.ActL1HeadSignal(t)
Expand Down
17 changes: 11 additions & 6 deletions e2e/actions/l1_miner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,15 @@ func TestL1Miner_BuildBlock(gt *testing.T) {
})

cl := miner.EthClient()
l1Cl := miner.L1Client(t, sd.RollupCfg)
signer := types.LatestSigner(sd.L1Cfg.Config)

// send a tx to the miner
tx := types.MustSignNewTx(dp.Secrets.Alice, signer, &types.DynamicFeeTx{
ChainID: sd.L1Cfg.Config.ChainID,
Nonce: 0,
GasTipCap: big.NewInt(2 * params.GWei),
GasFeeCap: new(big.Int).Add(miner.l1Chain.CurrentBlock().BaseFee(), big.NewInt(2*params.GWei)),
GasFeeCap: new(big.Int).Add(miner.l1Chain.CurrentBlock().BaseFee, big.NewInt(2*params.GWei)),
Gas: params.TxGas,
To: &dp.Addresses.Bob,
Value: e2eutils.Ether(2),
Expand All @@ -42,17 +43,21 @@ func TestL1Miner_BuildBlock(gt *testing.T) {
miner.ActL1StartBlock(10)(t)
miner.ActL1EndBlock(t)
bl := miner.l1Chain.CurrentBlock()
require.Equal(t, uint64(1), bl.NumberU64())
require.Zero(gt, bl.Transactions().Len())
_, txs, err := l1Cl.InfoAndTxsByHash(t.Ctx(), bl.Hash())
require.NoError(t, err)
require.Equal(t, uint64(1), bl.Number.Uint64())
require.Zero(gt, txs.Len())

// now include the tx when we want it to
miner.ActL1StartBlock(10)(t)
miner.ActL1IncludeTx(dp.Addresses.Alice)(t)
miner.ActL1EndBlock(t)
bl = miner.l1Chain.CurrentBlock()
require.Equal(t, uint64(2), bl.NumberU64())
require.Equal(t, 1, bl.Transactions().Len())
require.Equal(t, tx.Hash(), bl.Transactions()[0].Hash())
_, txs, err = l1Cl.InfoAndTxsByHash(t.Ctx(), bl.Hash())
require.NoError(t, err)
require.Equal(t, uint64(2), bl.Number.Uint64())
require.Equal(t, 1, txs.Len())
require.Equal(t, tx.Hash(), txs[0].Hash())

// now make a replica that syncs these two blocks from the miner
replica := NewL1Replica(t, log, sd.L1Cfg)
Expand Down
Loading