Commit 22ef8dbc authored by protolambda's avatar protolambda Committed by GitHub

op-e2e: 4844 DA support action-tests (#9104)

* op-e2e: 4844 DA support action-tests

* op-service: MakeSidecar unit-test

* op-e2e: implement fixes for reviews

* op-e2e: action test default batcher config update
parent 1a94b1dc
package actions
import (
"testing"
"github.com/stretchr/testify/require"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
batcherFlags "github.com/ethereum-optimism/optimism/op-batcher/flags"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
"github.com/ethereum-optimism/optimism/op-node/rollup/sync"
"github.com/ethereum-optimism/optimism/op-service/testlog"
)
func setupEIP4844Test(t Testing, log log.Logger) (*e2eutils.SetupData, *e2eutils.DeployParams, *L1Miner, *L2Sequencer, *L2Engine, *L2Verifier, *L2Engine) {
dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams)
genesisActivation := hexutil.Uint64(0)
dp.DeployConfig.L1CancunTimeOffset = &genesisActivation
dp.DeployConfig.L2GenesisCanyonTimeOffset = &genesisActivation
dp.DeployConfig.L2GenesisDeltaTimeOffset = &genesisActivation
dp.DeployConfig.L2GenesisEcotoneTimeOffset = &genesisActivation
sd := e2eutils.Setup(t, dp, defaultAlloc)
miner, seqEngine, sequencer := setupSequencerTest(t, sd, log)
miner.ActL1SetFeeRecipient(common.Address{'A'})
sequencer.ActL2PipelineFull(t)
verifEngine, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{})
return sd, dp, miner, sequencer, seqEngine, verifier, verifEngine
}
func setupBatcher(t Testing, log log.Logger, sd *e2eutils.SetupData, dp *e2eutils.DeployParams, miner *L1Miner,
sequencer *L2Sequencer, engine *L2Engine, daType batcherFlags.DataAvailabilityType) *L2Batcher {
return NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{
MinL1TxSize: 0,
MaxL1TxSize: 128_000,
BatcherKey: dp.Secrets.Batcher,
DataAvailabilityType: daType,
}, sequencer.RollupClient(), miner.EthClient(), engine.EthClient(), engine.EngineClient(t, sd.RollupCfg))
}
func TestEIP4844DataAvailability(gt *testing.T) {
t := NewDefaultTesting(gt)
log := testlog.Logger(t, log.LvlDebug)
sd, dp, miner, sequencer, seqEngine, verifier, _ := setupEIP4844Test(t, log)
batcher := setupBatcher(t, log, sd, dp, miner, sequencer, seqEngine, batcherFlags.BlobsType)
sequencer.ActL2PipelineFull(t)
verifier.ActL2PipelineFull(t)
// build empty L1 block
miner.ActEmptyBlock(t)
// finalize it, so the L1 geth blob pool doesn't log errors about missing finality
miner.ActL1SafeNext(t)
miner.ActL1FinalizeNext(t)
// Create L2 blocks, and reference the L1 head as origin
sequencer.ActL1HeadSignal(t)
sequencer.ActBuildToL1Head(t)
// submit all new L2 blocks
batcher.ActSubmitAll(t)
batchTx := batcher.LastSubmitted
// new L1 block with L2 batch
miner.ActL1StartBlock(12)(t)
miner.ActL1IncludeTxByHash(batchTx.Hash())(t)
miner.ActL1EndBlock(t)
require.Equal(t, uint8(types.BlobTxType), batchTx.Type(), "batch tx must be blob-tx")
// verifier picks up the L2 chain that was submitted
verifier.ActL1HeadSignal(t)
verifier.ActL2PipelineFull(t)
require.Equal(t, verifier.L2Safe(), sequencer.L2Unsafe(), "verifier syncs from sequencer via L1")
require.NotEqual(t, sequencer.L2Safe(), sequencer.L2Unsafe(), "sequencer has not processed L1 yet")
}
func TestEIP4844DataAvailabilitySwitch(gt *testing.T) {
t := NewDefaultTesting(gt)
log := testlog.Logger(t, log.LvlDebug)
sd, dp, miner, sequencer, seqEngine, verifier, _ := setupEIP4844Test(t, log)
oldBatcher := setupBatcher(t, log, sd, dp, miner, sequencer, seqEngine, batcherFlags.CalldataType)
sequencer.ActL2PipelineFull(t)
verifier.ActL2PipelineFull(t)
// build empty L1 block
miner.ActEmptyBlock(t)
// finalize it, so the L1 geth blob pool doesn't log errors about missing finality
miner.ActL1SafeNext(t)
miner.ActL1FinalizeNext(t)
// Create L2 blocks, and reference the L1 head as origin
sequencer.ActL1HeadSignal(t)
sequencer.ActBuildToL1Head(t)
// submit all new L2 blocks, with legacy calldata DA
oldBatcher.ActSubmitAll(t)
batchTx := oldBatcher.LastSubmitted
// new L1 block with L2 batch
miner.ActL1StartBlock(12)(t)
miner.ActL1IncludeTxByHash(batchTx.Hash())(t)
miner.ActL1EndBlock(t)
require.Equal(t, uint8(types.DynamicFeeTxType), batchTx.Type(), "batch tx must be eip1559 tx")
// verifier picks up the L2 chain that was submitted
verifier.ActL1HeadSignal(t)
verifier.ActL2PipelineFull(t)
require.Equal(t, verifier.L2Safe(), sequencer.L2Unsafe(), "verifier syncs from sequencer via L1")
require.NotEqual(t, sequencer.L2Safe(), sequencer.L2Unsafe(), "sequencer has not processed L1 yet")
newBatcher := setupBatcher(t, log, sd, dp, miner, sequencer, seqEngine, batcherFlags.BlobsType)
// build empty L1 block
miner.ActEmptyBlock(t)
// Create L2 blocks, and reference the L1 head as origin
sequencer.ActL1HeadSignal(t)
sequencer.ActBuildToL1Head(t)
// submit all new L2 blocks, now with Blobs DA!
newBatcher.ActSubmitAll(t)
batchTx = newBatcher.LastSubmitted
// new L1 block with L2 batch
miner.ActL1StartBlock(12)(t)
miner.ActL1IncludeTxByHash(batchTx.Hash())(t)
miner.ActL1EndBlock(t)
require.Equal(t, uint8(types.BlobTxType), batchTx.Type(), "batch tx must be blob-tx")
// verifier picks up the L2 chain that was submitted
verifier.ActL1HeadSignal(t)
verifier.ActL2PipelineFull(t)
require.Equal(t, verifier.L2Safe(), sequencer.L2Unsafe(), "verifier syncs from sequencer via L1")
require.NotEqual(t, sequencer.L2Safe(), sequencer.L2Unsafe(), "sequencer has not processed L1 yet")
}
...@@ -3,20 +3,28 @@ package actions ...@@ -3,20 +3,28 @@ package actions
import ( import (
"math/big" "math/big"
"github.com/stretchr/testify/require"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus/misc/eip1559" "github.com/ethereum/go-ethereum/consensus/misc/eip1559"
"github.com/ethereum/go-ethereum/consensus/misc/eip4844"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/trie"
"github.com/stretchr/testify/require"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
"github.com/ethereum-optimism/optimism/op-node/rollup/derive"
"github.com/ethereum-optimism/optimism/op-service/eth"
) )
// L1Miner wraps a L1Replica with instrumented block building ability. // L1Miner wraps a L1Replica with instrumented block building ability.
type L1Miner struct { type L1Miner struct {
L1Replica L1Replica
blobStore *e2eutils.BlobsStore
// L1 block building preferences // L1 block building preferences
prefCoinbase common.Address prefCoinbase common.Address
...@@ -29,6 +37,8 @@ type L1Miner struct { ...@@ -29,6 +37,8 @@ type L1Miner struct {
l1Receipts []*types.Receipt // collect receipts of ongoing building l1Receipts []*types.Receipt // collect receipts of ongoing building
l1Building bool l1Building bool
l1TxFailed []*types.Transaction // log of failed transactions which could not be included l1TxFailed []*types.Transaction // log of failed transactions which could not be included
// sidecars that come with the transactions
l1BuildingBlobSidecars []*types.BlobTxSidecar
} }
// NewL1Miner creates a new L1Replica that can also build blocks. // NewL1Miner creates a new L1Replica that can also build blocks.
...@@ -36,9 +46,14 @@ func NewL1Miner(t Testing, log log.Logger, genesis *core.Genesis) *L1Miner { ...@@ -36,9 +46,14 @@ func NewL1Miner(t Testing, log log.Logger, genesis *core.Genesis) *L1Miner {
rep := NewL1Replica(t, log, genesis) rep := NewL1Replica(t, log, genesis)
return &L1Miner{ return &L1Miner{
L1Replica: *rep, L1Replica: *rep,
blobStore: e2eutils.NewBlobStore(),
} }
} }
func (s *L1Miner) BlobStore() derive.L1BlobsFetcher {
return s.blobStore
}
// ActL1StartBlock returns an action to build a new L1 block on top of the head block, // ActL1StartBlock returns an action to build a new L1 block on top of the head block,
// with timeDelta added to the head block time. // with timeDelta added to the head block time.
func (s *L1Miner) ActL1StartBlock(timeDelta uint64) Action { func (s *L1Miner) ActL1StartBlock(timeDelta uint64) Action {
...@@ -77,11 +92,9 @@ func (s *L1Miner) ActL1StartBlock(timeDelta uint64) Action { ...@@ -77,11 +92,9 @@ func (s *L1Miner) ActL1StartBlock(timeDelta uint64) Action {
header.WithdrawalsHash = &types.EmptyWithdrawalsHash header.WithdrawalsHash = &types.EmptyWithdrawalsHash
} }
if s.l1Cfg.Config.IsCancun(header.Number, header.Time) { if s.l1Cfg.Config.IsCancun(header.Number, header.Time) {
var root common.Hash header.BlobGasUsed = new(uint64)
var zero uint64 header.ExcessBlobGas = new(uint64)
header.BlobGasUsed = &zero header.ParentBeaconRoot = new(common.Hash)
header.ExcessBlobGas = &zero
header.ParentBeaconRoot = &root
} }
s.l1Building = true s.l1Building = true
...@@ -90,6 +103,7 @@ func (s *L1Miner) ActL1StartBlock(timeDelta uint64) Action { ...@@ -90,6 +103,7 @@ func (s *L1Miner) ActL1StartBlock(timeDelta uint64) Action {
s.l1Receipts = make([]*types.Receipt, 0) s.l1Receipts = make([]*types.Receipt, 0)
s.l1Transactions = make([]*types.Transaction, 0) s.l1Transactions = make([]*types.Transaction, 0)
s.pendingIndices = make(map[common.Address]uint64) s.pendingIndices = make(map[common.Address]uint64)
s.l1BuildingBlobSidecars = make([]*types.BlobTxSidecar, 0)
s.l1GasPool = new(core.GasPool).AddGas(header.GasLimit) s.l1GasPool = new(core.GasPool).AddGas(header.GasLimit)
} }
...@@ -111,6 +125,22 @@ func (s *L1Miner) ActL1IncludeTx(from common.Address) Action { ...@@ -111,6 +125,22 @@ func (s *L1Miner) ActL1IncludeTx(from common.Address) Action {
} }
} }
// ActL1IncludeTxByHash tries to include a tx by tx-hash.
func (s *L1Miner) ActL1IncludeTxByHash(txHash common.Hash) Action {
return func(t Testing) {
if !s.l1Building {
t.InvalidAction("no tx inclusion when not building l1 block")
return
}
tx := s.eth.TxPool().Get(txHash)
require.NotNil(t, tx, "cannot find tx %s", txHash)
s.IncludeTx(t, tx)
from, err := s.l1Signer.Sender(tx)
require.NoError(t, err)
s.pendingIndices[from] = s.pendingIndices[from] + 1 // won't retry the tx
}
}
func (s *L1Miner) IncludeTx(t Testing, tx *types.Transaction) { func (s *L1Miner) IncludeTx(t Testing, tx *types.Transaction) {
from, err := s.l1Signer.Sender(tx) from, err := s.l1Signer.Sender(tx)
require.NoError(t, err) require.NoError(t, err)
...@@ -124,13 +154,21 @@ func (s *L1Miner) IncludeTx(t Testing, tx *types.Transaction) { ...@@ -124,13 +154,21 @@ func (s *L1Miner) IncludeTx(t Testing, tx *types.Transaction) {
} }
s.l1BuildingState.SetTxContext(tx.Hash(), len(s.l1Transactions)) s.l1BuildingState.SetTxContext(tx.Hash(), len(s.l1Transactions))
receipt, err := core.ApplyTransaction(s.l1Cfg.Config, s.l1Chain, &s.l1BuildingHeader.Coinbase, receipt, err := core.ApplyTransaction(s.l1Cfg.Config, s.l1Chain, &s.l1BuildingHeader.Coinbase,
s.l1GasPool, s.l1BuildingState, s.l1BuildingHeader, tx, &s.l1BuildingHeader.GasUsed, *s.l1Chain.GetVMConfig()) s.l1GasPool, s.l1BuildingState, s.l1BuildingHeader, tx.WithoutBlobTxSidecar(), &s.l1BuildingHeader.GasUsed, *s.l1Chain.GetVMConfig())
if err != nil { if err != nil {
s.l1TxFailed = append(s.l1TxFailed, tx) s.l1TxFailed = append(s.l1TxFailed, tx)
t.Fatalf("failed to apply transaction to L1 block (tx %d): %v", len(s.l1Transactions), err) t.Fatalf("failed to apply transaction to L1 block (tx %d): %v", len(s.l1Transactions), err)
} }
s.l1Receipts = append(s.l1Receipts, receipt) s.l1Receipts = append(s.l1Receipts, receipt)
s.l1Transactions = append(s.l1Transactions, tx) s.l1Transactions = append(s.l1Transactions, tx.WithoutBlobTxSidecar())
if tx.Type() == types.BlobTxType {
require.True(t, s.l1Cfg.Config.IsCancun(s.l1BuildingHeader.Number, s.l1BuildingHeader.Time), "L1 must be cancun to process blob tx")
sidecar := tx.BlobTxSidecar()
if sidecar != nil {
s.l1BuildingBlobSidecars = append(s.l1BuildingBlobSidecars, sidecar)
}
*s.l1BuildingHeader.BlobGasUsed += receipt.BlobGasUsed
}
} }
func (s *L1Miner) ActL1SetFeeRecipient(coinbase common.Address) { func (s *L1Miner) ActL1SetFeeRecipient(coinbase common.Address) {
...@@ -154,6 +192,19 @@ func (s *L1Miner) ActL1EndBlock(t Testing) { ...@@ -154,6 +192,19 @@ func (s *L1Miner) ActL1EndBlock(t Testing) {
if s.l1Cfg.Config.IsShanghai(s.l1BuildingHeader.Number, s.l1BuildingHeader.Time) { if s.l1Cfg.Config.IsShanghai(s.l1BuildingHeader.Number, s.l1BuildingHeader.Time) {
block = block.WithWithdrawals(make([]*types.Withdrawal, 0)) block = block.WithWithdrawals(make([]*types.Withdrawal, 0))
} }
if s.l1Cfg.Config.IsCancun(s.l1BuildingHeader.Number, s.l1BuildingHeader.Time) {
parent := s.l1Chain.GetHeaderByHash(s.l1BuildingHeader.ParentHash)
var (
parentExcessBlobGas uint64
parentBlobGasUsed uint64
)
if parent.ExcessBlobGas != nil {
parentExcessBlobGas = *parent.ExcessBlobGas
parentBlobGasUsed = *parent.BlobGasUsed
}
excessBlobGas := eip4844.CalcExcessBlobGas(parentExcessBlobGas, parentBlobGasUsed)
s.l1BuildingHeader.ExcessBlobGas = &excessBlobGas
}
// Write state changes to db // Write state changes to db
root, err := s.l1BuildingState.Commit(s.l1BuildingHeader.Number.Uint64(), s.l1Cfg.Config.IsEIP158(s.l1BuildingHeader.Number)) root, err := s.l1BuildingState.Commit(s.l1BuildingHeader.Number.Uint64(), s.l1Cfg.Config.IsEIP158(s.l1BuildingHeader.Number))
...@@ -163,7 +214,13 @@ func (s *L1Miner) ActL1EndBlock(t Testing) { ...@@ -163,7 +214,13 @@ func (s *L1Miner) ActL1EndBlock(t Testing) {
if err := s.l1BuildingState.Database().TrieDB().Commit(root, false); err != nil { if err := s.l1BuildingState.Database().TrieDB().Commit(root, false); err != nil {
t.Fatalf("l1 trie write error: %v", err) t.Fatalf("l1 trie write error: %v", err)
} }
// now that the blob txs are in a canonical block, flush them to the blob store
for _, sidecar := range s.l1BuildingBlobSidecars {
for i, h := range sidecar.BlobHashes() {
blob := (*eth.Blob)(&sidecar.Blobs[i])
s.blobStore.StoreBlob(block.Hash(), h, blob)
}
}
_, err = s.l1Chain.InsertChain(types.Blocks{block}) _, err = s.l1Chain.InsertChain(types.Blocks{block})
if err != nil { if err != nil {
t.Fatalf("failed to insert block into l1 chain") t.Fatalf("failed to insert block into l1 chain")
......
...@@ -8,18 +8,24 @@ import ( ...@@ -8,18 +8,24 @@ import (
"io" "io"
"math/big" "math/big"
"github.com/holiman/uint256"
"github.com/stretchr/testify/require"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus/misc/eip4844"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/stretchr/testify/require"
"github.com/ethereum-optimism/optimism/op-batcher/compressor" "github.com/ethereum-optimism/optimism/op-batcher/compressor"
batcherFlags "github.com/ethereum-optimism/optimism/op-batcher/flags"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
"github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-node/rollup/derive" "github.com/ethereum-optimism/optimism/op-node/rollup/derive"
"github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
) )
type SyncStatusAPI interface { type SyncStatusAPI interface {
...@@ -47,6 +53,17 @@ type BatcherCfg struct { ...@@ -47,6 +53,17 @@ type BatcherCfg struct {
ForceSubmitSingularBatch bool ForceSubmitSingularBatch bool
ForceSubmitSpanBatch bool ForceSubmitSpanBatch bool
DataAvailabilityType batcherFlags.DataAvailabilityType
}
func DefaultBatcherCfg(dp *e2eutils.DeployParams) *BatcherCfg {
return &BatcherCfg{
MinL1TxSize: 0,
MaxL1TxSize: 128_000,
BatcherKey: dp.Secrets.Batcher,
DataAvailabilityType: batcherFlags.CalldataType,
}
} }
type L2BlockRefs interface { type L2BlockRefs interface {
...@@ -76,6 +93,8 @@ type L2Batcher struct { ...@@ -76,6 +93,8 @@ type L2Batcher struct {
l2SubmittedBlock eth.L2BlockRef l2SubmittedBlock eth.L2BlockRef
l2BatcherCfg *BatcherCfg l2BatcherCfg *BatcherCfg
batcherAddr common.Address batcherAddr common.Address
LastSubmitted *types.Transaction
} }
func NewL2Batcher(log log.Logger, rollupCfg *rollup.Config, batcherCfg *BatcherCfg, api SyncStatusAPI, l1 L1TxAPI, l2 BlocksAPI, engCl L2BlockRefs) *L2Batcher { func NewL2Batcher(log log.Logger, rollupCfg *rollup.Config, batcherCfg *BatcherCfg, api SyncStatusAPI, l1 L1TxAPI, l2 BlocksAPI, engCl L2BlockRefs) *L2Batcher {
...@@ -220,26 +239,58 @@ func (s *L2Batcher) ActL2BatchSubmit(t Testing, txOpts ...func(tx *types.Dynamic ...@@ -220,26 +239,58 @@ func (s *L2Batcher) ActL2BatchSubmit(t Testing, txOpts ...func(tx *types.Dynamic
require.NoError(t, err, "need l1 pending header for gas price estimation") require.NoError(t, err, "need l1 pending header for gas price estimation")
gasFeeCap := new(big.Int).Add(gasTipCap, new(big.Int).Mul(pendingHeader.BaseFee, big.NewInt(2))) gasFeeCap := new(big.Int).Add(gasTipCap, new(big.Int).Mul(pendingHeader.BaseFee, big.NewInt(2)))
rawTx := &types.DynamicFeeTx{ var txData types.TxData
ChainID: s.rollupCfg.L1ChainID, if s.l2BatcherCfg.DataAvailabilityType == batcherFlags.CalldataType {
Nonce: nonce, rawTx := &types.DynamicFeeTx{
To: &s.rollupCfg.BatchInboxAddress, ChainID: s.rollupCfg.L1ChainID,
GasTipCap: gasTipCap, Nonce: nonce,
GasFeeCap: gasFeeCap, To: &s.rollupCfg.BatchInboxAddress,
Data: data.Bytes(), GasTipCap: gasTipCap,
} GasFeeCap: gasFeeCap,
for _, opt := range txOpts { Data: data.Bytes(),
opt(rawTx) }
for _, opt := range txOpts {
opt(rawTx)
}
gas, err := core.IntrinsicGas(rawTx.Data, nil, false, true, true, false)
require.NoError(t, err, "need to compute intrinsic gas")
rawTx.Gas = gas
txData = rawTx
} else if s.l2BatcherCfg.DataAvailabilityType == batcherFlags.BlobsType {
var b eth.Blob
require.NoError(t, b.FromData(data.Bytes()), "must turn data into blob")
sidecar, blobHashes, err := txmgr.MakeSidecar([]*eth.Blob{&b})
require.NoError(t, err)
require.NotNil(t, pendingHeader.ExcessBlobGas, "need L1 header with 4844 properties")
blobBaseFee := eip4844.CalcBlobFee(*pendingHeader.ExcessBlobGas)
blobFeeCap := new(uint256.Int).Mul(uint256.NewInt(2), uint256.MustFromBig(blobBaseFee))
if blobFeeCap.Lt(uint256.NewInt(params.GWei)) { // ensure we meet 1 gwei geth tx-pool minimum
blobFeeCap = uint256.NewInt(params.GWei)
}
txData = &types.BlobTx{
To: s.rollupCfg.BatchInboxAddress,
Data: nil,
Gas: params.TxGas, // intrinsic gas only
BlobHashes: blobHashes,
Sidecar: sidecar,
ChainID: uint256.MustFromBig(s.rollupCfg.L1ChainID),
GasTipCap: uint256.MustFromBig(gasTipCap),
GasFeeCap: uint256.MustFromBig(gasFeeCap),
BlobFeeCap: blobFeeCap,
Value: uint256.NewInt(0),
Nonce: nonce,
}
} else {
t.Fatalf("unrecognized DA type: %q", string(s.l2BatcherCfg.DataAvailabilityType))
} }
gas, err := core.IntrinsicGas(rawTx.Data, nil, false, true, true, false)
require.NoError(t, err, "need to compute intrinsic gas")
rawTx.Gas = gas
tx, err := types.SignNewTx(s.l2BatcherCfg.BatcherKey, s.l1Signer, rawTx) tx, err := types.SignNewTx(s.l2BatcherCfg.BatcherKey, s.l1Signer, txData)
require.NoError(t, err, "need to sign tx") require.NoError(t, err, "need to sign tx")
err = s.l1.SendTransaction(t.Ctx(), tx) err = s.l1.SendTransaction(t.Ctx(), tx)
require.NoError(t, err, "need to send tx") require.NoError(t, err, "need to send tx")
s.LastSubmitted = tx
} }
// ActL2BatchSubmitGarbage constructs a malformed channel frame and submits it to the // ActL2BatchSubmitGarbage constructs a malformed channel frame and submits it to the
......
...@@ -14,6 +14,7 @@ import ( ...@@ -14,6 +14,7 @@ import (
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
batcherFlags "github.com/ethereum-optimism/optimism/op-batcher/flags"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
"github.com/ethereum-optimism/optimism/op-node/rollup/derive" "github.com/ethereum-optimism/optimism/op-node/rollup/derive"
"github.com/ethereum-optimism/optimism/op-node/rollup/sync" "github.com/ethereum-optimism/optimism/op-node/rollup/sync"
...@@ -84,14 +85,11 @@ func NormalBatcher(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { ...@@ -84,14 +85,11 @@ func NormalBatcher(gt *testing.T, deltaTimeOffset *hexutil.Uint64) {
sd := e2eutils.Setup(t, dp, defaultAlloc) sd := e2eutils.Setup(t, dp, defaultAlloc)
log := testlog.Logger(t, log.LvlDebug) log := testlog.Logger(t, log.LvlDebug)
miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) miner, seqEngine, sequencer := setupSequencerTest(t, sd, log)
verifEngine, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), &sync.Config{}) verifEngine, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{})
rollupSeqCl := sequencer.RollupClient() rollupSeqCl := sequencer.RollupClient()
batcher := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{ batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp),
MinL1TxSize: 0, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg))
MaxL1TxSize: 128_000,
BatcherKey: dp.Secrets.Batcher,
}, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg))
// Alice makes a L2 tx // Alice makes a L2 tx
cl := seqEngine.EthClient() cl := seqEngine.EthClient()
...@@ -186,11 +184,8 @@ func L2Finalization(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { ...@@ -186,11 +184,8 @@ func L2Finalization(gt *testing.T, deltaTimeOffset *hexutil.Uint64) {
require.Equal(t, uint64(1), sequencer.SyncStatus().FinalizedL1.Number) require.Equal(t, uint64(1), sequencer.SyncStatus().FinalizedL1.Number)
require.Equal(t, uint64(0), sequencer.SyncStatus().FinalizedL2.Number, "L2 block has to be included on L1 before it can be finalized") require.Equal(t, uint64(0), sequencer.SyncStatus().FinalizedL2.Number, "L2 block has to be included on L1 before it can be finalized")
batcher := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{ batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp),
MinL1TxSize: 0, sequencer.RollupClient(), miner.EthClient(), engine.EthClient(), engine.EngineClient(t, sd.RollupCfg))
MaxL1TxSize: 128_000,
BatcherKey: dp.Secrets.Batcher,
}, sequencer.RollupClient(), miner.EthClient(), engine.EthClient(), engine.EngineClient(t, sd.RollupCfg))
heightToSubmit := sequencer.SyncStatus().UnsafeL2.Number heightToSubmit := sequencer.SyncStatus().UnsafeL2.Number
...@@ -273,11 +268,8 @@ func L2FinalizationWithSparseL1(gt *testing.T, deltaTimeOffset *hexutil.Uint64) ...@@ -273,11 +268,8 @@ func L2FinalizationWithSparseL1(gt *testing.T, deltaTimeOffset *hexutil.Uint64)
startStatus := sequencer.SyncStatus() startStatus := sequencer.SyncStatus()
require.Less(t, startStatus.SafeL2.Number, startStatus.UnsafeL2.Number, "sequencer has unsafe L2 block") require.Less(t, startStatus.SafeL2.Number, startStatus.UnsafeL2.Number, "sequencer has unsafe L2 block")
batcher := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{ batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp),
MinL1TxSize: 0, sequencer.RollupClient(), miner.EthClient(), engine.EthClient(), engine.EngineClient(t, sd.RollupCfg))
MaxL1TxSize: 128_000,
BatcherKey: dp.Secrets.Batcher,
}, sequencer.RollupClient(), miner.EthClient(), engine.EthClient(), engine.EngineClient(t, sd.RollupCfg))
batcher.ActSubmitAll(t) batcher.ActSubmitAll(t)
// include in L1 // include in L1
...@@ -325,13 +317,9 @@ func GarbageBatch(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { ...@@ -325,13 +317,9 @@ func GarbageBatch(gt *testing.T, deltaTimeOffset *hexutil.Uint64) {
log := testlog.Logger(t, log.LvlError) log := testlog.Logger(t, log.LvlError)
miner, engine, sequencer := setupSequencerTest(t, sd, log) miner, engine, sequencer := setupSequencerTest(t, sd, log)
_, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), &sync.Config{}) _, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{})
batcherCfg := &BatcherCfg{ batcherCfg := DefaultBatcherCfg(dp)
MinL1TxSize: 0,
MaxL1TxSize: 128_000,
BatcherKey: dp.Secrets.Batcher,
}
if garbageKind == MALFORM_RLP || garbageKind == INVALID_COMPRESSION { if garbageKind == MALFORM_RLP || garbageKind == INVALID_COMPRESSION {
// If the garbage kind is `INVALID_COMPRESSION` or `MALFORM_RLP`, use the `actions` packages // If the garbage kind is `INVALID_COMPRESSION` or `MALFORM_RLP`, use the `actions` packages
...@@ -409,13 +397,10 @@ func ExtendedTimeWithoutL1Batches(gt *testing.T, deltaTimeOffset *hexutil.Uint64 ...@@ -409,13 +397,10 @@ func ExtendedTimeWithoutL1Batches(gt *testing.T, deltaTimeOffset *hexutil.Uint64
log := testlog.Logger(t, log.LvlError) log := testlog.Logger(t, log.LvlError)
miner, engine, sequencer := setupSequencerTest(t, sd, log) miner, engine, sequencer := setupSequencerTest(t, sd, log)
_, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), &sync.Config{}) _, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{})
batcher := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{ batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp),
MinL1TxSize: 0, sequencer.RollupClient(), miner.EthClient(), engine.EthClient(), engine.EngineClient(t, sd.RollupCfg))
MaxL1TxSize: 128_000,
BatcherKey: dp.Secrets.Batcher,
}, sequencer.RollupClient(), miner.EthClient(), engine.EthClient(), engine.EngineClient(t, sd.RollupCfg))
sequencer.ActL2PipelineFull(t) sequencer.ActL2PipelineFull(t)
verifier.ActL2PipelineFull(t) verifier.ActL2PipelineFull(t)
...@@ -468,12 +453,13 @@ func BigL2Txs(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { ...@@ -468,12 +453,13 @@ func BigL2Txs(gt *testing.T, deltaTimeOffset *hexutil.Uint64) {
log := testlog.Logger(t, log.LvlInfo) log := testlog.Logger(t, log.LvlInfo)
miner, engine, sequencer := setupSequencerTest(t, sd, log) miner, engine, sequencer := setupSequencerTest(t, sd, log)
_, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), &sync.Config{}) _, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{})
batcher := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{ batcher := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{
MinL1TxSize: 0, MinL1TxSize: 0,
MaxL1TxSize: 40_000, // try a small batch size, to force the data to be split between more frames MaxL1TxSize: 40_000, // try a small batch size, to force the data to be split between more frames
BatcherKey: dp.Secrets.Batcher, BatcherKey: dp.Secrets.Batcher,
DataAvailabilityType: batcherFlags.CalldataType,
}, sequencer.RollupClient(), miner.EthClient(), engine.EthClient(), engine.EngineClient(t, sd.RollupCfg)) }, sequencer.RollupClient(), miner.EthClient(), engine.EthClient(), engine.EngineClient(t, sd.RollupCfg))
sequencer.ActL2PipelineFull(t) sequencer.ActL2PipelineFull(t)
......
...@@ -48,11 +48,8 @@ func RunProposerTest(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { ...@@ -48,11 +48,8 @@ func RunProposerTest(gt *testing.T, deltaTimeOffset *hexutil.Uint64) {
miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) miner, seqEngine, sequencer := setupSequencerTest(t, sd, log)
rollupSeqCl := sequencer.RollupClient() rollupSeqCl := sequencer.RollupClient()
batcher := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{ batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp),
MinL1TxSize: 0, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg))
MaxL1TxSize: 128_000,
BatcherKey: dp.Secrets.Batcher,
}, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg))
proposer := NewL2Proposer(t, log, &ProposerCfg{ proposer := NewL2Proposer(t, log, &ProposerCfg{
OutputOracleAddr: &sd.DeploymentsL1.L2OutputOracleProxy, OutputOracleAddr: &sd.DeploymentsL1.L2OutputOracleProxy,
......
...@@ -30,18 +30,6 @@ func (m *MockL1OriginSelector) FindL1Origin(ctx context.Context, l2Head eth.L2Bl ...@@ -30,18 +30,6 @@ func (m *MockL1OriginSelector) FindL1Origin(ctx context.Context, l2Head eth.L2Bl
return m.actual.FindL1Origin(ctx, l2Head) return m.actual.FindL1Origin(ctx, l2Head)
} }
// emptyL1BlobsFetcher is a no-op blobs provider. The actions test batcher currently only supports using calldata.
type emptyL1BlobsFetcher struct {
t Testing
}
var _ derive.L1BlobsFetcher = &emptyL1BlobsFetcher{}
func (e *emptyL1BlobsFetcher) GetBlobs(ctx context.Context, ref eth.L1BlockRef, hashes []eth.IndexedBlobHash) ([]*eth.Blob, error) {
e.t.Fatal("actions test do not support blobs")
return nil, nil
}
// L2Sequencer is an actor that functions like a rollup node, // L2Sequencer is an actor that functions like a rollup node,
// without the full P2P/API/Node stack, but just the derivation state, and simplified driver with sequencing ability. // without the full P2P/API/Node stack, but just the derivation state, and simplified driver with sequencing ability.
type L2Sequencer struct { type L2Sequencer struct {
...@@ -54,9 +42,9 @@ type L2Sequencer struct { ...@@ -54,9 +42,9 @@ type L2Sequencer struct {
mockL1OriginSelector *MockL1OriginSelector mockL1OriginSelector *MockL1OriginSelector
} }
func NewL2Sequencer(t Testing, log log.Logger, l1 derive.L1Fetcher, eng L2API, cfg *rollup.Config, seqConfDepth uint64) *L2Sequencer { func NewL2Sequencer(t Testing, log log.Logger, l1 derive.L1Fetcher, blobSrc derive.L1BlobsFetcher,
mockBlobFetcher := &emptyL1BlobsFetcher{t: t} eng L2API, cfg *rollup.Config, seqConfDepth uint64) *L2Sequencer {
ver := NewL2Verifier(t, log, l1, mockBlobFetcher, eng, cfg, &sync.Config{}) ver := NewL2Verifier(t, log, l1, blobSrc, eng, cfg, &sync.Config{})
attrBuilder := derive.NewFetchingAttributesBuilder(cfg, l1, eng) attrBuilder := derive.NewFetchingAttributesBuilder(cfg, l1, eng)
seqConfDepthL1 := driver.NewConfDepth(seqConfDepth, ver.l1State.L1Head, l1) seqConfDepthL1 := driver.NewConfDepth(seqConfDepth, ver.l1State.L1Head, l1)
l1OriginSelector := &MockL1OriginSelector{ l1OriginSelector := &MockL1OriginSelector{
......
...@@ -47,7 +47,7 @@ func setupSequencerTest(t Testing, sd *e2eutils.SetupData, log log.Logger) (*L1M ...@@ -47,7 +47,7 @@ func setupSequencerTest(t Testing, sd *e2eutils.SetupData, log log.Logger) (*L1M
l2Cl, err := sources.NewEngineClient(engine.RPCClient(), log, nil, sources.EngineClientDefaultConfig(sd.RollupCfg)) l2Cl, err := sources.NewEngineClient(engine.RPCClient(), log, nil, sources.EngineClientDefaultConfig(sd.RollupCfg))
require.NoError(t, err) require.NoError(t, err)
sequencer := NewL2Sequencer(t, log, l1F, l2Cl, sd.RollupCfg, 0) sequencer := NewL2Sequencer(t, log, l1F, miner.BlobStore(), l2Cl, sd.RollupCfg, 0)
return miner, engine, sequencer return miner, engine, sequencer
} }
......
...@@ -13,19 +13,18 @@ import ( ...@@ -13,19 +13,18 @@ import (
"github.com/ethereum-optimism/optimism/op-service/testlog" "github.com/ethereum-optimism/optimism/op-service/testlog"
) )
func setupVerifier(t Testing, sd *e2eutils.SetupData, log log.Logger, l1F derive.L1Fetcher, syncCfg *sync.Config) (*L2Engine, *L2Verifier) { func setupVerifier(t Testing, sd *e2eutils.SetupData, log log.Logger, l1F derive.L1Fetcher, blobSrc derive.L1BlobsFetcher, syncCfg *sync.Config) (*L2Engine, *L2Verifier) {
jwtPath := e2eutils.WriteDefaultJWT(t) jwtPath := e2eutils.WriteDefaultJWT(t)
engine := NewL2Engine(t, log, sd.L2Cfg, sd.RollupCfg.Genesis.L1, jwtPath, EngineWithP2P()) engine := NewL2Engine(t, log, sd.L2Cfg, sd.RollupCfg.Genesis.L1, jwtPath, EngineWithP2P())
engCl := engine.EngineClient(t, sd.RollupCfg) engCl := engine.EngineClient(t, sd.RollupCfg)
mockBlobFetcher := &emptyL1BlobsFetcher{t: t} verifier := NewL2Verifier(t, log, l1F, blobSrc, engCl, sd.RollupCfg, syncCfg)
verifier := NewL2Verifier(t, log, l1F, mockBlobFetcher, engCl, sd.RollupCfg, syncCfg)
return engine, verifier return engine, verifier
} }
func setupVerifierOnlyTest(t Testing, sd *e2eutils.SetupData, log log.Logger) (*L1Miner, *L2Engine, *L2Verifier) { func setupVerifierOnlyTest(t Testing, sd *e2eutils.SetupData, log log.Logger) (*L1Miner, *L2Engine, *L2Verifier) {
miner := NewL1Miner(t, log, sd.L1Cfg) miner := NewL1Miner(t, log, sd.L1Cfg)
l1Cl := miner.L1Client(t, sd.RollupCfg) l1Cl := miner.L1Client(t, sd.RollupCfg)
engine, verifier := setupVerifier(t, sd, log, l1Cl, &sync.Config{}) engine, verifier := setupVerifier(t, sd, log, l1Cl, miner.BlobStore(), &sync.Config{})
return miner, engine, verifier return miner, engine, verifier
} }
......
...@@ -36,13 +36,10 @@ func setupReorgTestActors(t Testing, dp *e2eutils.DeployParams, sd *e2eutils.Set ...@@ -36,13 +36,10 @@ func setupReorgTestActors(t Testing, dp *e2eutils.DeployParams, sd *e2eutils.Set
miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) miner, seqEngine, sequencer := setupSequencerTest(t, sd, log)
miner.ActL1SetFeeRecipient(common.Address{'A'}) miner.ActL1SetFeeRecipient(common.Address{'A'})
sequencer.ActL2PipelineFull(t) sequencer.ActL2PipelineFull(t)
verifEngine, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), &sync.Config{}) verifEngine, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{})
rollupSeqCl := sequencer.RollupClient() rollupSeqCl := sequencer.RollupClient()
batcher := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{ batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp),
MinL1TxSize: 0, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg))
MaxL1TxSize: 128_000,
BatcherKey: dp.Secrets.Batcher,
}, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg))
return sd, dp, miner, sequencer, seqEngine, verifier, verifEngine, batcher return sd, dp, miner, sequencer, seqEngine, verifier, verifEngine, batcher
} }
...@@ -620,13 +617,10 @@ func RestartOpGeth(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { ...@@ -620,13 +617,10 @@ func RestartOpGeth(gt *testing.T, deltaTimeOffset *hexutil.Uint64) {
engRpc := &rpcWrapper{seqEng.RPCClient()} engRpc := &rpcWrapper{seqEng.RPCClient()}
l2Cl, err := sources.NewEngineClient(engRpc, log, nil, sources.EngineClientDefaultConfig(sd.RollupCfg)) l2Cl, err := sources.NewEngineClient(engRpc, log, nil, sources.EngineClientDefaultConfig(sd.RollupCfg))
require.NoError(t, err) require.NoError(t, err)
sequencer := NewL2Sequencer(t, log, l1F, l2Cl, sd.RollupCfg, 0) sequencer := NewL2Sequencer(t, log, l1F, miner.BlobStore(), l2Cl, sd.RollupCfg, 0)
batcher := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{ batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp),
MinL1TxSize: 0, sequencer.RollupClient(), miner.EthClient(), seqEng.EthClient(), seqEng.EngineClient(t, sd.RollupCfg))
MaxL1TxSize: 128_000,
BatcherKey: dp.Secrets.Batcher,
}, sequencer.RollupClient(), miner.EthClient(), seqEng.EthClient(), seqEng.EngineClient(t, sd.RollupCfg))
// start // start
sequencer.ActL2PipelineFull(t) sequencer.ActL2PipelineFull(t)
...@@ -711,12 +705,9 @@ func ConflictingL2Blocks(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { ...@@ -711,12 +705,9 @@ func ConflictingL2Blocks(gt *testing.T, deltaTimeOffset *hexutil.Uint64) {
require.NoError(t, err) require.NoError(t, err)
l1F, err := sources.NewL1Client(miner.RPCClient(), log, nil, sources.L1ClientDefaultConfig(sd.RollupCfg, false, sources.RPCKindStandard)) l1F, err := sources.NewL1Client(miner.RPCClient(), log, nil, sources.L1ClientDefaultConfig(sd.RollupCfg, false, sources.RPCKindStandard))
require.NoError(t, err) require.NoError(t, err)
altSequencer := NewL2Sequencer(t, log, l1F, altSeqEngCl, sd.RollupCfg, 0) altSequencer := NewL2Sequencer(t, log, l1F, miner.BlobStore(), altSeqEngCl, sd.RollupCfg, 0)
altBatcher := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{ altBatcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp),
MinL1TxSize: 0, altSequencer.RollupClient(), miner.EthClient(), altSeqEng.EthClient(), altSeqEng.EngineClient(t, sd.RollupCfg))
MaxL1TxSize: 128_000,
BatcherKey: dp.Secrets.Batcher,
}, altSequencer.RollupClient(), miner.EthClient(), altSeqEng.EthClient(), altSeqEng.EngineClient(t, sd.RollupCfg))
// And set up user Alice, using the alternative sequencer endpoint // And set up user Alice, using the alternative sequencer endpoint
l2Cl := altSeqEng.EthClient() l2Cl := altSeqEng.EthClient()
......
...@@ -8,9 +8,8 @@ import ( ...@@ -8,9 +8,8 @@ import (
"math/rand" "math/rand"
"testing" "testing"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils" "github.com/stretchr/testify/require"
"github.com/ethereum-optimism/optimism/op-node/rollup/sync"
"github.com/ethereum-optimism/optimism/op-service/testlog"
"github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
...@@ -20,7 +19,11 @@ import ( ...@@ -20,7 +19,11 @@ import (
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/stretchr/testify/require"
batcherFlags "github.com/ethereum-optimism/optimism/op-batcher/flags"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
"github.com/ethereum-optimism/optimism/op-node/rollup/sync"
"github.com/ethereum-optimism/optimism/op-service/testlog"
) )
// TestDropSpanBatchBeforeHardfork tests behavior of op-node before Delta hardfork. // TestDropSpanBatchBeforeHardfork tests behavior of op-node before Delta hardfork.
...@@ -39,7 +42,7 @@ func TestDropSpanBatchBeforeHardfork(gt *testing.T) { ...@@ -39,7 +42,7 @@ func TestDropSpanBatchBeforeHardfork(gt *testing.T) {
sd := e2eutils.Setup(t, dp, defaultAlloc) sd := e2eutils.Setup(t, dp, defaultAlloc)
log := testlog.Logger(t, log.LvlError) log := testlog.Logger(t, log.LvlError)
miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) miner, seqEngine, sequencer := setupSequencerTest(t, sd, log)
verifEngine, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), &sync.Config{}) verifEngine, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{})
rollupSeqCl := sequencer.RollupClient() rollupSeqCl := sequencer.RollupClient()
// Force batcher to submit SpanBatches to L1. // Force batcher to submit SpanBatches to L1.
...@@ -48,6 +51,7 @@ func TestDropSpanBatchBeforeHardfork(gt *testing.T) { ...@@ -48,6 +51,7 @@ func TestDropSpanBatchBeforeHardfork(gt *testing.T) {
MaxL1TxSize: 128_000, MaxL1TxSize: 128_000,
BatcherKey: dp.Secrets.Batcher, BatcherKey: dp.Secrets.Batcher,
ForceSubmitSpanBatch: true, ForceSubmitSpanBatch: true,
DataAvailabilityType: batcherFlags.CalldataType,
}, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) }, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg))
// Alice makes a L2 tx // Alice makes a L2 tx
...@@ -129,7 +133,7 @@ func TestHardforkMiddleOfSpanBatch(gt *testing.T) { ...@@ -129,7 +133,7 @@ func TestHardforkMiddleOfSpanBatch(gt *testing.T) {
sd := e2eutils.Setup(t, dp, defaultAlloc) sd := e2eutils.Setup(t, dp, defaultAlloc)
log := testlog.Logger(t, log.LvlError) log := testlog.Logger(t, log.LvlError)
miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) miner, seqEngine, sequencer := setupSequencerTest(t, sd, log)
verifEngine, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), &sync.Config{}) verifEngine, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{})
minerCl := miner.EthClient() minerCl := miner.EthClient()
rollupSeqCl := sequencer.RollupClient() rollupSeqCl := sequencer.RollupClient()
...@@ -139,6 +143,7 @@ func TestHardforkMiddleOfSpanBatch(gt *testing.T) { ...@@ -139,6 +143,7 @@ func TestHardforkMiddleOfSpanBatch(gt *testing.T) {
MaxL1TxSize: 128_000, MaxL1TxSize: 128_000,
BatcherKey: dp.Secrets.Batcher, BatcherKey: dp.Secrets.Batcher,
ForceSubmitSpanBatch: true, ForceSubmitSpanBatch: true,
DataAvailabilityType: batcherFlags.CalldataType,
}, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) }, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg))
// Alice makes a L2 tx // Alice makes a L2 tx
...@@ -236,7 +241,7 @@ func TestAcceptSingularBatchAfterHardfork(gt *testing.T) { ...@@ -236,7 +241,7 @@ func TestAcceptSingularBatchAfterHardfork(gt *testing.T) {
sd := e2eutils.Setup(t, dp, defaultAlloc) sd := e2eutils.Setup(t, dp, defaultAlloc)
log := testlog.Logger(t, log.LvlError) log := testlog.Logger(t, log.LvlError)
miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) miner, seqEngine, sequencer := setupSequencerTest(t, sd, log)
verifEngine, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), &sync.Config{}) verifEngine, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{})
rollupSeqCl := sequencer.RollupClient() rollupSeqCl := sequencer.RollupClient()
// Force batcher to submit SingularBatches to L1. // Force batcher to submit SingularBatches to L1.
...@@ -245,6 +250,7 @@ func TestAcceptSingularBatchAfterHardfork(gt *testing.T) { ...@@ -245,6 +250,7 @@ func TestAcceptSingularBatchAfterHardfork(gt *testing.T) {
MaxL1TxSize: 128_000, MaxL1TxSize: 128_000,
BatcherKey: dp.Secrets.Batcher, BatcherKey: dp.Secrets.Batcher,
ForceSubmitSingularBatch: true, ForceSubmitSingularBatch: true,
DataAvailabilityType: batcherFlags.CalldataType,
}, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) }, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg))
// Alice makes a L2 tx // Alice makes a L2 tx
...@@ -321,7 +327,7 @@ func TestMixOfBatchesAfterHardfork(gt *testing.T) { ...@@ -321,7 +327,7 @@ func TestMixOfBatchesAfterHardfork(gt *testing.T) {
sd := e2eutils.Setup(t, dp, defaultAlloc) sd := e2eutils.Setup(t, dp, defaultAlloc)
log := testlog.Logger(t, log.LvlError) log := testlog.Logger(t, log.LvlError)
miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) miner, seqEngine, sequencer := setupSequencerTest(t, sd, log)
verifEngine, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), &sync.Config{}) verifEngine, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{})
rollupSeqCl := sequencer.RollupClient() rollupSeqCl := sequencer.RollupClient()
seqEngCl := seqEngine.EthClient() seqEngCl := seqEngine.EthClient()
...@@ -361,6 +367,7 @@ func TestMixOfBatchesAfterHardfork(gt *testing.T) { ...@@ -361,6 +367,7 @@ func TestMixOfBatchesAfterHardfork(gt *testing.T) {
BatcherKey: dp.Secrets.Batcher, BatcherKey: dp.Secrets.Batcher,
ForceSubmitSpanBatch: i%2 == 0, // Submit SpanBatch for odd numbered batches ForceSubmitSpanBatch: i%2 == 0, // Submit SpanBatch for odd numbered batches
ForceSubmitSingularBatch: i%2 == 1, // Submit SingularBatch for even numbered batches ForceSubmitSingularBatch: i%2 == 1, // Submit SingularBatch for even numbered batches
DataAvailabilityType: batcherFlags.CalldataType,
} }
batcher := NewL2Batcher(log, sd.RollupCfg, &batcherCfg, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) batcher := NewL2Batcher(log, sd.RollupCfg, &batcherCfg, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg))
// Submit all new blocks // Submit all new blocks
...@@ -410,14 +417,11 @@ func TestSpanBatchEmptyChain(gt *testing.T) { ...@@ -410,14 +417,11 @@ func TestSpanBatchEmptyChain(gt *testing.T) {
sd := e2eutils.Setup(t, dp, defaultAlloc) sd := e2eutils.Setup(t, dp, defaultAlloc)
log := testlog.Logger(t, log.LvlError) log := testlog.Logger(t, log.LvlError)
miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) miner, seqEngine, sequencer := setupSequencerTest(t, sd, log)
_, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), &sync.Config{}) _, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{})
rollupSeqCl := sequencer.RollupClient() rollupSeqCl := sequencer.RollupClient()
batcher := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{ batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp),
MinL1TxSize: 0, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg))
MaxL1TxSize: 128_000,
BatcherKey: dp.Secrets.Batcher,
}, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg))
sequencer.ActL2PipelineFull(t) sequencer.ActL2PipelineFull(t)
verifier.ActL2PipelineFull(t) verifier.ActL2PipelineFull(t)
...@@ -476,14 +480,11 @@ func TestSpanBatchLowThroughputChain(gt *testing.T) { ...@@ -476,14 +480,11 @@ func TestSpanBatchLowThroughputChain(gt *testing.T) {
sd := e2eutils.Setup(t, dp, defaultAlloc) sd := e2eutils.Setup(t, dp, defaultAlloc)
log := testlog.Logger(t, log.LvlError) log := testlog.Logger(t, log.LvlError)
miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) miner, seqEngine, sequencer := setupSequencerTest(t, sd, log)
_, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), &sync.Config{}) _, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{})
rollupSeqCl := sequencer.RollupClient() rollupSeqCl := sequencer.RollupClient()
batcher := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{ batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp),
MinL1TxSize: 0, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg))
MaxL1TxSize: 128_000,
BatcherKey: dp.Secrets.Batcher,
}, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg))
cl := seqEngine.EthClient() cl := seqEngine.EthClient()
const numTestUsers = 5 const numTestUsers = 5
...@@ -604,10 +605,10 @@ func TestBatchEquivalence(gt *testing.T) { ...@@ -604,10 +605,10 @@ func TestBatchEquivalence(gt *testing.T) {
seqEngCl := seqEngine.EthClient() seqEngCl := seqEngine.EthClient()
// Setup Delta activated spanVerifier // Setup Delta activated spanVerifier
_, spanVerifier := setupVerifier(t, sdDeltaActivated, log, miner.L1Client(t, sdDeltaActivated.RollupCfg), &sync.Config{}) _, spanVerifier := setupVerifier(t, sdDeltaActivated, log, miner.L1Client(t, sdDeltaActivated.RollupCfg), miner.BlobStore(), &sync.Config{})
// Setup Delta deactivated spanVerifier // Setup Delta deactivated spanVerifier
_, singularVerifier := setupVerifier(t, sdDeltaDeactivated, log, miner.L1Client(t, sdDeltaDeactivated.RollupCfg), &sync.Config{}) _, singularVerifier := setupVerifier(t, sdDeltaDeactivated, log, miner.L1Client(t, sdDeltaDeactivated.RollupCfg), miner.BlobStore(), &sync.Config{})
// Setup SpanBatcher // Setup SpanBatcher
spanBatcher := NewL2Batcher(log, sdDeltaActivated.RollupCfg, &BatcherCfg{ spanBatcher := NewL2Batcher(log, sdDeltaActivated.RollupCfg, &BatcherCfg{
...@@ -615,6 +616,7 @@ func TestBatchEquivalence(gt *testing.T) { ...@@ -615,6 +616,7 @@ func TestBatchEquivalence(gt *testing.T) {
MaxL1TxSize: 128_000, MaxL1TxSize: 128_000,
BatcherKey: dp.Secrets.Batcher, BatcherKey: dp.Secrets.Batcher,
ForceSubmitSpanBatch: true, ForceSubmitSpanBatch: true,
DataAvailabilityType: batcherFlags.CalldataType,
}, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sdDeltaActivated.RollupCfg)) }, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sdDeltaActivated.RollupCfg))
// Setup SingularBatcher // Setup SingularBatcher
...@@ -623,6 +625,7 @@ func TestBatchEquivalence(gt *testing.T) { ...@@ -623,6 +625,7 @@ func TestBatchEquivalence(gt *testing.T) {
MaxL1TxSize: 128_000, MaxL1TxSize: 128_000,
BatcherKey: dp.Secrets.Batcher, BatcherKey: dp.Secrets.Batcher,
ForceSubmitSingularBatch: true, ForceSubmitSingularBatch: true,
DataAvailabilityType: batcherFlags.CalldataType,
}, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sdDeltaDeactivated.RollupCfg)) }, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sdDeltaDeactivated.RollupCfg))
const numTestUsers = 5 const numTestUsers = 5
......
...@@ -172,7 +172,7 @@ func TestELSync(gt *testing.T) { ...@@ -172,7 +172,7 @@ func TestELSync(gt *testing.T) {
miner, seqEng, sequencer := setupSequencerTest(t, sd, log) miner, seqEng, sequencer := setupSequencerTest(t, sd, log)
// Enable engine P2P sync // Enable engine P2P sync
verEng, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), &sync.Config{SyncMode: sync.ELSync}) verEng, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{SyncMode: sync.ELSync})
seqEng.AddPeers(verEng.Enode()) seqEng.AddPeers(verEng.Enode())
verEng.AddPeers(seqEng.Enode()) verEng.AddPeers(seqEng.Enode())
......
...@@ -59,22 +59,18 @@ func BatcherKeyRotation(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { ...@@ -59,22 +59,18 @@ func BatcherKeyRotation(gt *testing.T, deltaTimeOffset *hexutil.Uint64) {
miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) miner, seqEngine, sequencer := setupSequencerTest(t, sd, log)
miner.ActL1SetFeeRecipient(common.Address{'A'}) miner.ActL1SetFeeRecipient(common.Address{'A'})
sequencer.ActL2PipelineFull(t) sequencer.ActL2PipelineFull(t)
_, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), &sync.Config{}) _, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{})
rollupSeqCl := sequencer.RollupClient() rollupSeqCl := sequencer.RollupClient()
// the default batcher // the default batcher
batcherA := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{ batcherA := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp),
MinL1TxSize: 0, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg))
MaxL1TxSize: 128_000,
BatcherKey: dp.Secrets.Batcher,
}, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg))
// a batcher with a new key // a batcher with a new key
batcherB := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{ altCfg := *DefaultBatcherCfg(dp)
MinL1TxSize: 0, altCfg.BatcherKey = dp.Secrets.Bob
MaxL1TxSize: 128_000, batcherB := NewL2Batcher(log, sd.RollupCfg, &altCfg,
BatcherKey: dp.Secrets.Bob, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg))
}, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg))
sequencer.ActL2PipelineFull(t) sequencer.ActL2PipelineFull(t)
verifier.ActL2PipelineFull(t) verifier.ActL2PipelineFull(t)
...@@ -235,11 +231,8 @@ func GPOParamsChange(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { ...@@ -235,11 +231,8 @@ func GPOParamsChange(gt *testing.T, deltaTimeOffset *hexutil.Uint64) {
sd := e2eutils.Setup(t, dp, defaultAlloc) sd := e2eutils.Setup(t, dp, defaultAlloc)
log := testlog.Logger(t, log.LvlDebug) log := testlog.Logger(t, log.LvlDebug)
miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) miner, seqEngine, sequencer := setupSequencerTest(t, sd, log)
batcher := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{ batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp),
MinL1TxSize: 0, sequencer.RollupClient(), miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg))
MaxL1TxSize: 128_000,
BatcherKey: dp.Secrets.Batcher,
}, sequencer.RollupClient(), miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg))
alice := NewBasicUser[any](log, dp.Secrets.Alice, rand.New(rand.NewSource(1234))) alice := NewBasicUser[any](log, dp.Secrets.Alice, rand.New(rand.NewSource(1234)))
alice.SetUserEnv(&BasicUserEnv[any]{ alice.SetUserEnv(&BasicUserEnv[any]{
...@@ -365,11 +358,8 @@ func GasLimitChange(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { ...@@ -365,11 +358,8 @@ func GasLimitChange(gt *testing.T, deltaTimeOffset *hexutil.Uint64) {
sd := e2eutils.Setup(t, dp, defaultAlloc) sd := e2eutils.Setup(t, dp, defaultAlloc)
log := testlog.Logger(t, log.LvlDebug) log := testlog.Logger(t, log.LvlDebug)
miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) miner, seqEngine, sequencer := setupSequencerTest(t, sd, log)
batcher := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{ batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp),
MinL1TxSize: 0, sequencer.RollupClient(), miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg))
MaxL1TxSize: 128_000,
BatcherKey: dp.Secrets.Batcher,
}, sequencer.RollupClient(), miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg))
sequencer.ActL2PipelineFull(t) sequencer.ActL2PipelineFull(t)
miner.ActEmptyBlock(t) miner.ActEmptyBlock(t)
...@@ -412,7 +402,7 @@ func GasLimitChange(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { ...@@ -412,7 +402,7 @@ func GasLimitChange(gt *testing.T, deltaTimeOffset *hexutil.Uint64) {
miner.ActL1IncludeTx(dp.Addresses.Batcher)(t) miner.ActL1IncludeTx(dp.Addresses.Batcher)(t)
miner.ActL1EndBlock(t) miner.ActL1EndBlock(t)
_, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), &sync.Config{}) _, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{})
verifier.ActL2PipelineFull(t) verifier.ActL2PipelineFull(t)
require.Equal(t, sequencer.L2Unsafe(), verifier.L2Safe(), "verifier stays in sync, even with gaslimit changes") require.Equal(t, sequencer.L2Unsafe(), verifier.L2Safe(), "verifier stays in sync, even with gaslimit changes")
......
...@@ -129,11 +129,8 @@ func runCrossLayerUserTest(gt *testing.T, test hardforkScheduledTest) { ...@@ -129,11 +129,8 @@ func runCrossLayerUserTest(gt *testing.T, test hardforkScheduledTest) {
require.Equal(t, dp.Secrets.Addresses().Proposer, dp.DeployConfig.L2OutputOracleProposer) require.Equal(t, dp.Secrets.Addresses().Proposer, dp.DeployConfig.L2OutputOracleProposer)
miner, seqEngine, seq := setupSequencerTest(t, sd, log) miner, seqEngine, seq := setupSequencerTest(t, sd, log)
batcher := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{ batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp),
MinL1TxSize: 0, seq.RollupClient(), miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg))
MaxL1TxSize: 128_000,
BatcherKey: dp.Secrets.Batcher,
}, seq.RollupClient(), miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg))
proposer := NewL2Proposer(t, log, &ProposerCfg{ proposer := NewL2Proposer(t, log, &ProposerCfg{
OutputOracleAddr: &sd.DeploymentsL1.L2OutputOracleProxy, OutputOracleAddr: &sd.DeploymentsL1.L2OutputOracleProxy,
ProposerKey: dp.Secrets.Proposer, ProposerKey: dp.Secrets.Proposer,
......
package e2eutils
import (
"context"
"fmt"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum-optimism/optimism/op-node/rollup/derive"
"github.com/ethereum-optimism/optimism/op-service/eth"
)
// BlobsStore is a simple in-memory store of blobs, for testing purposes
type BlobsStore struct {
// blockhash -> blob versioned hash -> blob
blobs map[common.Hash]map[common.Hash]*eth.Blob
}
func NewBlobStore() *BlobsStore {
return &BlobsStore{blobs: make(map[common.Hash]map[common.Hash]*eth.Blob)}
}
func (store *BlobsStore) StoreBlob(blockHash common.Hash, versionedHash common.Hash, blob *eth.Blob) {
m, ok := store.blobs[blockHash]
if !ok {
m = make(map[common.Hash]*eth.Blob)
store.blobs[blockHash] = m
}
m[versionedHash] = blob
}
func (store *BlobsStore) GetBlobs(ctx context.Context, ref eth.L1BlockRef, hashes []eth.IndexedBlobHash) ([]*eth.Blob, error) {
out := make([]*eth.Blob, 0, len(hashes))
m, ok := store.blobs[ref.Hash]
if !ok {
return nil, fmt.Errorf("no blobs known with given time: %w", ethereum.NotFound)
}
for _, h := range hashes {
b, ok := m[h.Hash]
if !ok {
return nil, fmt.Errorf("blob %d %s is not in store: %w", h.Index, h.Hash, ethereum.NotFound)
}
out = append(out, b)
}
return out, nil
}
var _ derive.L1BlobsFetcher = (*BlobsStore)(nil)
...@@ -277,7 +277,7 @@ func (m *SimpleTxManager) craftTx(ctx context.Context, candidate TxCandidate) (* ...@@ -277,7 +277,7 @@ func (m *SimpleTxManager) craftTx(ctx context.Context, candidate TxCandidate) (*
if candidate.To == nil { if candidate.To == nil {
return nil, errors.New("blob txs cannot deploy contracts") return nil, errors.New("blob txs cannot deploy contracts")
} }
if sidecar, blobHashes, err = makeSidecar(candidate.Blobs); err != nil { if sidecar, blobHashes, err = MakeSidecar(candidate.Blobs); err != nil {
return nil, fmt.Errorf("failed to make sidecar: %w", err) return nil, fmt.Errorf("failed to make sidecar: %w", err)
} }
} }
...@@ -314,9 +314,9 @@ func (m *SimpleTxManager) craftTx(ctx context.Context, candidate TxCandidate) (* ...@@ -314,9 +314,9 @@ func (m *SimpleTxManager) craftTx(ctx context.Context, candidate TxCandidate) (*
} }
// makeSidecar builds & returns the BlobTxSidecar and corresponding blob hashes from the raw blob // MakeSidecar builds & returns the BlobTxSidecar and corresponding blob hashes from the raw blob
// data. // data.
func makeSidecar(blobs []*eth.Blob) (*types.BlobTxSidecar, []common.Hash, error) { func MakeSidecar(blobs []*eth.Blob) (*types.BlobTxSidecar, []common.Hash, error) {
sidecar := &types.BlobTxSidecar{} sidecar := &types.BlobTxSidecar{}
blobHashes := []common.Hash{} blobHashes := []common.Hash{}
for i, blob := range blobs { for i, blob := range blobs {
......
...@@ -2,6 +2,7 @@ package txmgr ...@@ -2,6 +2,7 @@ package txmgr
import ( import (
"context" "context"
"crypto/rand"
"errors" "errors"
"fmt" "fmt"
"math/big" "math/big"
...@@ -1403,3 +1404,24 @@ func TestCloseWaitingForConfirmation(t *testing.T) { ...@@ -1403,3 +1404,24 @@ func TestCloseWaitingForConfirmation(t *testing.T) {
require.True(t, h.mgr.closed.Load()) require.True(t, h.mgr.closed.Load())
require.NoError(t, err) require.NoError(t, err)
} }
func TestMakeSidecar(t *testing.T) {
var blob eth.Blob
_, err := rand.Read(blob[:])
require.NoError(t, err)
// get the field-elements into a valid range
for i := 0; i < 4096; i++ {
blob[32*i] &= 0b0011_1111
}
sidecar, hashes, err := MakeSidecar([]*eth.Blob{&blob})
require.NoError(t, err)
require.Equal(t, len(hashes), 1)
require.Equal(t, len(sidecar.Blobs), len(hashes))
require.Equal(t, len(sidecar.Proofs), len(hashes))
require.Equal(t, len(sidecar.Commitments), len(hashes))
for i, commit := range sidecar.Commitments {
require.NoError(t, eth.VerifyBlobProof((*eth.Blob)(&sidecar.Blobs[i]), commit, sidecar.Proofs[i]), "proof must be valid")
require.Equal(t, hashes[i], eth.KZGToVersionedHash(commit))
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment