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

update L1Block contract with new fields for 4844 #5

Draft
wants to merge 9 commits into
base: 4844/rebase
Choose a base branch
from
Draft
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
21 changes: 18 additions & 3 deletions op-batcher/batcher/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ func (l *BatchSubmitter) publishTxToL1(ctx context.Context, queue *txmgr.Queue[t
// send all available transactions
l1tip, err := l.l1Tip(ctx)
if err != nil {
l.Log.Error("Failed to query L1 tip", "error", err)
l.Log.Error("Failed to query L1 tip", "err", err)
return err
}
l.recordL1Tip(l1tip)
Expand All @@ -353,22 +353,37 @@ func (l *BatchSubmitter) publishTxToL1(ctx context.Context, queue *txmgr.Queue[t
return nil
}

// sendTransaction creates & submits a transaction to the batch inbox address with the given `data`.
// sendTransaction creates & submits a transaction to the batch inbox address with the given `txData`.
// It currently uses the underlying `txmgr` to handle transaction sending & price management.
// This is a blocking method. It should not be called concurrently.
func (l *BatchSubmitter) sendTransaction(txdata txData, queue *txmgr.Queue[txData], receiptsCh chan txmgr.TxReceipt[txData]) {
// Do the gas estimation offline. A value of 0 will cause the [txmgr] to estimate the gas limit.
data := txdata.Bytes()

var blobs []*eth.Blob
if l.RollupConfig.BlobsEnabledL1Timestamp != nil && *l.RollupConfig.BlobsEnabledL1Timestamp <= uint64(time.Now().Unix()) {
var b eth.Blob
if err := b.FromData(data); err != nil {
l.Log.Error("data could not be converted to blob", "err", err)
return
}
blobs = append(blobs, &b)

// no calldata
data = []byte{}
}

intrinsicGas, err := core.IntrinsicGas(data, nil, false, true, true, false)
if err != nil {
l.Log.Error("Failed to calculate intrinsic gas", "error", err)
l.Log.Error("Failed to calculate intrinsic gas", "err", err)
return
}

candidate := txmgr.TxCandidate{
To: &l.RollupConfig.BatchInboxAddress,
TxData: data,
GasLimit: intrinsicGas,
Blobs: blobs,
}
queue.Send(txdata, candidate, receiptsCh)
}
Expand Down
14 changes: 7 additions & 7 deletions op-chain-ops/genesis/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,9 @@ type DeployConfig struct {
// L2GenesisDeltaTimeOffset is the number of seconds after genesis block that Delta hard fork activates.
// Set it to 0 to activate at genesis. Nil to disable Delta.
L2GenesisDeltaTimeOffset *hexutil.Uint64 `json:"l2GenesisDeltaTimeOffset,omitempty"`
// L2GenesisEclipseTimeOffset is the number of seconds after genesis block that Eclipse hard fork activates.
// Set it to 0 to activate at genesis. Nil to disable Eclipse.
L2GenesisEclipseTimeOffset *hexutil.Uint64 `json:"l2GenesisEclipseTimeOffset,omitempty"`
// L2GenesisEcotoneTimeOffset is the number of seconds after genesis block that Ecotone hard fork activates.
// Set it to 0 to activate at genesis. Nil to disable Ecotone.
L2GenesisEcotoneTimeOffset *hexutil.Uint64 `json:"l2GenesisEcotoneTimeOffset,omitempty"`
// L2GenesisFjordTimeOffset is the number of seconds after genesis block that Fjord hard fork activates.
// Set it to 0 to activate at genesis. Nil to disable Fjord.
L2GenesisFjordTimeOffset *hexutil.Uint64 `json:"l2GenesisFjordTimeOffset,omitempty"`
Expand Down Expand Up @@ -489,12 +489,12 @@ func (d *DeployConfig) DeltaTime(genesisTime uint64) *uint64 {
return &v
}

func (d *DeployConfig) EclipseTime(genesisTime uint64) *uint64 {
if d.L2GenesisEclipseTimeOffset == nil {
func (d *DeployConfig) EcotoneTime(genesisTime uint64) *uint64 {
if d.L2GenesisEcotoneTimeOffset == nil {
return nil
}
v := uint64(0)
if offset := *d.L2GenesisEclipseTimeOffset; offset > 0 {
if offset := *d.L2GenesisEcotoneTimeOffset; offset > 0 {
v = genesisTime + uint64(offset)
}
return &v
Expand Down Expand Up @@ -561,7 +561,7 @@ func (d *DeployConfig) RollupConfig(l1StartBlock *types.Block, l2GenesisBlockHas
RegolithTime: d.RegolithTime(l1StartBlock.Time()),
CanyonTime: d.CanyonTime(l1StartBlock.Time()),
DeltaTime: d.DeltaTime(l1StartBlock.Time()),
EclipseTime: d.EclipseTime(l1StartBlock.Time()),
EcotoneTime: d.EcotoneTime(l1StartBlock.Time()),
FjordTime: d.FjordTime(l1StartBlock.Time()),
InteropTime: d.InteropTime(l1StartBlock.Time()),
}, nil
Expand Down
16 changes: 11 additions & 5 deletions op-e2e/actions/l2_engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@ package actions
import (
"errors"

"github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
"github.com/ethereum-optimism/optimism/op-program/client/l2/engineapi"
"github.com/stretchr/testify/require"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/txpool/blobpool"
"github.com/ethereum/go-ethereum/core/types"
geth "github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/eth/ethconfig"
Expand All @@ -20,9 +19,11 @@ import (
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/rpc"

"github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-program/client/l2/engineapi"
"github.com/ethereum-optimism/optimism/op-service/client"
"github.com/ethereum-optimism/optimism/op-service/eth"
opeth "github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum-optimism/optimism/op-service/sources"
"github.com/ethereum-optimism/optimism/op-service/testutils"
)
Expand All @@ -48,7 +49,7 @@ type L2Engine struct {

type EngineOption func(ethCfg *ethconfig.Config, nodeCfg *node.Config) error

func NewL2Engine(t Testing, log log.Logger, genesis *core.Genesis, rollupGenesisL1 eth.BlockID, jwtPath string, options ...EngineOption) *L2Engine {
func NewL2Engine(t Testing, log log.Logger, genesis *core.Genesis, rollupGenesisL1 opeth.BlockID, jwtPath string, options ...EngineOption) *L2Engine {
n, ethBackend, apiBackend := newBackend(t, genesis, jwtPath, options)
engineApi := engineapi.NewL2EngineAPI(log, apiBackend)
chain := ethBackend.BlockChain()
Expand All @@ -59,7 +60,7 @@ func NewL2Engine(t Testing, log log.Logger, genesis *core.Genesis, rollupGenesis
eth: ethBackend,
rollupGenesis: &rollup.Genesis{
L1: rollupGenesisL1,
L2: eth.BlockID{Hash: genesisBlock.Hash(), Number: genesisBlock.NumberU64()},
L2: opeth.BlockID{Hash: genesisBlock.Hash(), Number: genesisBlock.NumberU64()},
L2Time: genesis.Timestamp,
},
l2Chain: chain,
Expand All @@ -84,6 +85,11 @@ func newBackend(t e2eutils.TestingBase, genesis *core.Genesis, jwtPath string, o
ethCfg := &ethconfig.Config{
NetworkId: genesis.Config.ChainID.Uint64(),
Genesis: genesis,
BlobPool: blobpool.Config{
Datadir: t.TempDir(),
Datacap: blobpool.DefaultConfig.Datacap,
PriceBump: blobpool.DefaultConfig.PriceBump,
},
}
nodeCfg := &node.Config{
Name: "l2-geth",
Expand Down
3 changes: 2 additions & 1 deletion op-e2e/actions/l2_verifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ type L2API interface {

func NewL2Verifier(t Testing, log log.Logger, l1 derive.L1Fetcher, eng L2API, cfg *rollup.Config, syncCfg *sync.Config) *L2Verifier {
metrics := &testutils.TestDerivationMetrics{}
pipeline := derive.NewDerivationPipeline(log, cfg, l1, eng, metrics, syncCfg)
// TODO blob testing
pipeline := derive.NewDerivationPipeline(log, cfg, l1, nil, eng, metrics, syncCfg)
pipeline.Reset()

rollupNode := &L2Verifier{
Expand Down
7 changes: 6 additions & 1 deletion op-e2e/e2eutils/geth/geth.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ func defaultNodeConfig(name string, jwtPath string) *node.Config {
type GethOption func(ethCfg *ethconfig.Config, nodeCfg *node.Config) error

// InitL2 inits a L2 geth node.
func InitL2(name string, l2ChainID *big.Int, genesis *core.Genesis, jwtPath string, opts ...GethOption) (*node.Node, *eth.Ethereum, error) {
func InitL2(name string, l2ChainID *big.Int, genesis *core.Genesis, jwtPath string, blobPoolDir string, opts ...GethOption) (*node.Node, *eth.Ethereum, error) {
ethConfig := &ethconfig.Config{
NetworkId: l2ChainID.Uint64(),
Genesis: genesis,
Expand All @@ -96,6 +96,11 @@ func InitL2(name string, l2ChainID *big.Int, genesis *core.Genesis, jwtPath stri
Recommit: 0,
NewPayloadTimeout: 0,
},
BlobPool: blobpool.Config{
Datadir: blobPoolDir,
Datacap: blobpool.DefaultConfig.Datacap,
PriceBump: blobpool.DefaultConfig.PriceBump,
},
}
nodeConfig := defaultNodeConfig(fmt.Sprintf("l2-geth-%v", name), jwtPath)
return createGethNode(true, nodeConfig, ethConfig, opts...)
Expand Down
2 changes: 1 addition & 1 deletion op-e2e/e2eutils/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ func Setup(t require.TestingT, deployParams *DeployParams, alloc *AllocParams) *
RegolithTime: deployConf.RegolithTime(uint64(deployConf.L1GenesisBlockTimestamp)),
CanyonTime: deployConf.CanyonTime(uint64(deployConf.L1GenesisBlockTimestamp)),
DeltaTime: deployConf.DeltaTime(uint64(deployConf.L1GenesisBlockTimestamp)),
EclipseTime: deployConf.EclipseTime(uint64(deployConf.L1GenesisBlockTimestamp)),
EcotoneTime: deployConf.EcotoneTime(uint64(deployConf.L1GenesisBlockTimestamp)),
FjordTime: deployConf.FjordTime(uint64(deployConf.L1GenesisBlockTimestamp)),
InteropTime: deployConf.InteropTime(uint64(deployConf.L1GenesisBlockTimestamp)),
}
Expand Down
112 changes: 112 additions & 0 deletions op-e2e/eip4844_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package op_e2e

import (
"context"
"math/big"
"testing"
"time"

"github.com/stretchr/testify/require"

"github.com/ethereum-optimism/optimism/op-service/client"
"github.com/ethereum-optimism/optimism/op-service/sources"
"github.com/ethereum-optimism/optimism/op-service/testlog"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rpc"
)

// TestSystem4844E2E runs the SystemE2E test with 4844 enabled on L1,
// and active on the rollup in the op-batcher and verifier.
func TestSystem4844E2E(t *testing.T) {
InitParallel(t)

cfg := DefaultSystemConfig(t)
genesisActivation := uint64(0)
cfg.DeployConfig.L1CancunTimeOffset = &genesisActivation
hu := hexutil.Uint64(0)
cfg.DeployConfig.L2GenesisEcotoneTimeOffset = &hu

sys, err := cfg.Start(t)
require.Nil(t, err, "Error starting up system")
defer sys.Close()

log := testlog.Logger(t, log.LvlInfo)
log.Info("genesis", "l2", sys.RollupConfig.Genesis.L2, "l1", sys.RollupConfig.Genesis.L1, "l2_time", sys.RollupConfig.Genesis.L2Time)

l1Client := sys.Clients["l1"]
l2Seq := sys.Clients["sequencer"]
l2Verif := sys.Clients["verifier"]

// Transactor Account
ethPrivKey := cfg.Secrets.Alice

// Send Transaction & wait for success
fromAddr := cfg.Secrets.Addresses().Alice
log.Info("alice", "addr", fromAddr)

ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
defer cancel()
startBalance, err := l2Verif.BalanceAt(ctx, fromAddr, nil)
require.Nil(t, err)

// Send deposit transaction
opts, err := bind.NewKeyedTransactorWithChainID(ethPrivKey, cfg.L1ChainIDBig())
require.Nil(t, err)
mintAmount := big.NewInt(1_000_000_000_000)
opts.Value = mintAmount
SendDepositTx(t, cfg, l1Client, l2Verif, opts, func(l2Opts *DepositTxOpts) {})

// Confirm balance
ctx, cancel = context.WithTimeout(context.Background(), 15*time.Second)
defer cancel()
endBalance, err := l2Verif.BalanceAt(ctx, fromAddr, nil)
require.Nil(t, err)

diff := new(big.Int)
diff = diff.Sub(endBalance, startBalance)
require.Equal(t, mintAmount, diff, "Did not get expected balance change")

// Submit TX to L2 sequencer node
receipt := SendL2Tx(t, cfg, l2Seq, ethPrivKey, func(opts *TxOpts) {
opts.Value = big.NewInt(1_000_000_000)
opts.Nonce = 1 // Already have deposit
opts.ToAddr = &common.Address{0xff, 0xff}
opts.VerifyOnClients(l2Verif)
})

// Verify blocks match after batch submission on verifiers and sequencers
verifBlock, err := l2Verif.BlockByNumber(context.Background(), receipt.BlockNumber)
require.Nil(t, err)
seqBlock, err := l2Seq.BlockByNumber(context.Background(), receipt.BlockNumber)
require.Nil(t, err)
require.Equal(t, verifBlock.NumberU64(), seqBlock.NumberU64(), "Verifier and sequencer blocks not the same after including a batch tx")
require.Equal(t, verifBlock.ParentHash(), seqBlock.ParentHash(), "Verifier and sequencer blocks parent hashes not the same after including a batch tx")
require.Equal(t, verifBlock.Hash(), seqBlock.Hash(), "Verifier and sequencer blocks not the same after including a batch tx")

rollupRPCClient, err := rpc.DialContext(context.Background(), sys.RollupNodes["sequencer"].HTTPEndpoint())
require.Nil(t, err)
rollupClient := sources.NewRollupClient(client.NewBaseRPCClient(rollupRPCClient))
// basic check that sync status works
seqStatus, err := rollupClient.SyncStatus(context.Background())
require.Nil(t, err)
require.LessOrEqual(t, seqBlock.NumberU64(), seqStatus.UnsafeL2.Number)
// basic check that version endpoint works
seqVersion, err := rollupClient.Version(context.Background())
require.Nil(t, err)
require.NotEqual(t, "", seqVersion)

// quick check that the batch submitter works
for i := 0; i < 10; i++ {
// wait for chain to be marked as "safe" (i.e. confirm batch-submission works)
stat, err := rollupClient.SyncStatus(context.Background())
require.NoError(t, err)
if stat.SafeL2.Number > 0 {
return
}
time.Sleep(2 * time.Second)
}
t.Fatal("expected L2 to be batch-submitted and labeled as safe")
}
2 changes: 1 addition & 1 deletion op-e2e/op_geth.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func NewOpGeth(t *testing.T, ctx context.Context, cfg *SystemConfig) (*OpGeth, e

var node EthInstance
if cfg.ExternalL2Shim == "" {
gethNode, _, err := geth.InitL2("l2", big.NewInt(int64(cfg.DeployConfig.L2ChainID)), l2Genesis, cfg.JWTFilePath)
gethNode, _, err := geth.InitL2("l2", big.NewInt(int64(cfg.DeployConfig.L2ChainID)), l2Genesis, cfg.JWTFilePath, t.TempDir())
require.Nil(t, err)
require.Nil(t, gethNode.Start())
node = gethNode
Expand Down
23 changes: 13 additions & 10 deletions op-e2e/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -490,7 +490,7 @@ func (cfg SystemConfig) Start(t *testing.T, _opts ...SystemConfigOption) (*Syste
RegolithTime: cfg.DeployConfig.RegolithTime(uint64(cfg.DeployConfig.L1GenesisBlockTimestamp)),
CanyonTime: cfg.DeployConfig.CanyonTime(uint64(cfg.DeployConfig.L1GenesisBlockTimestamp)),
DeltaTime: cfg.DeployConfig.DeltaTime(uint64(cfg.DeployConfig.L1GenesisBlockTimestamp)),
EclipseTime: cfg.DeployConfig.EclipseTime(uint64(cfg.DeployConfig.L1GenesisBlockTimestamp)),
EcotoneTime: cfg.DeployConfig.EcotoneTime(uint64(cfg.DeployConfig.L1GenesisBlockTimestamp)),
FjordTime: cfg.DeployConfig.FjordTime(uint64(cfg.DeployConfig.L1GenesisBlockTimestamp)),
InteropTime: cfg.DeployConfig.InteropTime(uint64(cfg.DeployConfig.L1GenesisBlockTimestamp)),
ProtocolVersionsAddress: cfg.L1Deployments.ProtocolVersionsProxy,
Expand All @@ -509,8 +509,8 @@ func (cfg SystemConfig) Start(t *testing.T, _opts ...SystemConfigOption) (*Syste
_ = bcn.Close()
})
require.NoError(t, bcn.Start("127.0.0.1:0"))
beaconApiAddr := bcn.BeaconAddr()
require.NotEmpty(t, beaconApiAddr, "beacon API listener must be up")
sys.L1BeaconAPIAddr = bcn.BeaconAddr()
require.NotEmpty(t, sys.L1BeaconAPIAddr, "beacon API listener must be up")

// Initialize nodes
l1Node, l1Backend, err := geth.InitL1(cfg.DeployConfig.L1ChainID, cfg.DeployConfig.L1BlockTime, l1Genesis, c,
Expand All @@ -529,8 +529,9 @@ func (cfg SystemConfig) Start(t *testing.T, _opts ...SystemConfigOption) (*Syste

for name := range cfg.Nodes {
var ethClient EthInstance
blobPoolPath := path.Join(cfg.BlobsPath, name)
if cfg.ExternalL2Shim == "" {
node, backend, err := geth.InitL2(name, big.NewInt(int64(cfg.DeployConfig.L2ChainID)), l2Genesis, cfg.JWTFilePath, cfg.GethOptions[name]...)
node, backend, err := geth.InitL2(name, big.NewInt(int64(cfg.DeployConfig.L2ChainID)), l2Genesis, cfg.JWTFilePath, blobPoolPath, cfg.GethOptions[name]...)
if err != nil {
return nil, err
}
Expand All @@ -548,10 +549,11 @@ func (cfg SystemConfig) Start(t *testing.T, _opts ...SystemConfigOption) (*Syste
t.Skip("External L2 nodes do not support configuration through GethOptions")
}
ethClient = (&ExternalRunner{
Name: name,
BinPath: cfg.ExternalL2Shim,
Genesis: l2Genesis,
JWTPath: cfg.JWTFilePath,
Name: name,
BinPath: cfg.ExternalL2Shim,
Genesis: l2Genesis,
JWTPath: cfg.JWTFilePath,
BlobPoolPath: blobPoolPath,
}).Run(t)
}
sys.EthInstances[name] = ethClient
Expand All @@ -562,7 +564,7 @@ func (cfg SystemConfig) Start(t *testing.T, _opts ...SystemConfigOption) (*Syste
// of only websockets (which are required for external eth client tests).
for name, rollupCfg := range cfg.Nodes {
configureL1(rollupCfg, sys.EthInstances["l1"])
configureL2(rollupCfg, sys.EthInstances[name], cfg.JWTSecret)
configureL2(rollupCfg, sys.EthInstances[name], cfg.JWTSecret, sys.L1BeaconAPIAddr)
}

// Geth Clients
Expand Down Expand Up @@ -865,7 +867,7 @@ type WSOrHTTPEndpoint interface {
HTTPAuthEndpoint() string
}

func configureL2(rollupNodeCfg *rollupNode.Config, l2Node WSOrHTTPEndpoint, jwtSecret [32]byte) {
func configureL2(rollupNodeCfg *rollupNode.Config, l2Node WSOrHTTPEndpoint, jwtSecret [32]byte, l1BeaconAPIAddr string) {
l2EndpointConfig := l2Node.WSAuthEndpoint()
if UseHTTP() {
l2EndpointConfig = l2Node.HTTPAuthEndpoint()
Expand All @@ -875,6 +877,7 @@ func configureL2(rollupNodeCfg *rollupNode.Config, l2Node WSOrHTTPEndpoint, jwtS
L2EngineAddr: l2EndpointConfig,
L2EngineJWTSecret: jwtSecret,
}
rollupNodeCfg.Beacon = &rollupNode.L1BeaconEndpointConfig{BeaconAddr: l1BeaconAPIAddr}
}

func (cfg SystemConfig) L1ChainIDBig() *big.Int {
Expand Down
4 changes: 2 additions & 2 deletions op-e2e/system_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -706,11 +706,11 @@ func TestSystemP2PAltSync(t *testing.T) {
},
}
configureL1(syncNodeCfg, sys.EthInstances["l1"])
syncerL2Engine, _, err := geth.InitL2("syncer", big.NewInt(int64(cfg.DeployConfig.L2ChainID)), sys.L2GenesisCfg, cfg.JWTFilePath)
syncerL2Engine, _, err := geth.InitL2("syncer", big.NewInt(int64(cfg.DeployConfig.L2ChainID)), sys.L2GenesisCfg, cfg.JWTFilePath, t.TempDir())
require.NoError(t, err)
require.NoError(t, syncerL2Engine.Start())

configureL2(syncNodeCfg, syncerL2Engine, cfg.JWTSecret)
configureL2(syncNodeCfg, syncerL2Engine, cfg.JWTSecret, sys.L1BeaconAPIAddr)

syncerNode, err := rollupNode.New(context.Background(), syncNodeCfg, cfg.Loggers["syncer"], snapLog, "", metrics.NewMetrics(""))
require.NoError(t, err)
Expand Down
Loading