Commit 235c7af1 authored by Matthew Slipper's avatar Matthew Slipper Committed by GitHub

Merge pull request #2008 from cfromknecht/bss-craft-then-send-tx

bss: split up SubmitBatchTx method in Driver iface
parents e5ba9b1d 961dfe25
...@@ -5,7 +5,7 @@ import ( ...@@ -5,7 +5,7 @@ import (
"crypto/ecdsa" "crypto/ecdsa"
"fmt" "fmt"
"math/big" "math/big"
"time" "strings"
"github.com/ethereum-optimism/optimism/go/batch-submitter/bindings/ctc" "github.com/ethereum-optimism/optimism/go/batch-submitter/bindings/ctc"
"github.com/ethereum-optimism/optimism/go/batch-submitter/bindings/scc" "github.com/ethereum-optimism/optimism/go/batch-submitter/bindings/scc"
...@@ -14,6 +14,8 @@ import ( ...@@ -14,6 +14,8 @@ import (
"github.com/ethereum-optimism/optimism/go/batch-submitter/txmgr" "github.com/ethereum-optimism/optimism/go/batch-submitter/txmgr"
l2ethclient "github.com/ethereum-optimism/optimism/l2geth/ethclient" l2ethclient "github.com/ethereum-optimism/optimism/l2geth/ethclient"
"github.com/ethereum-optimism/optimism/l2geth/log" "github.com/ethereum-optimism/optimism/l2geth/log"
"github.com/ethereum-optimism/optimism/l2geth/params"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
...@@ -41,6 +43,7 @@ type Config struct { ...@@ -41,6 +43,7 @@ type Config struct {
type Driver struct { type Driver struct {
cfg Config cfg Config
sccContract *scc.StateCommitmentChain sccContract *scc.StateCommitmentChain
rawSccContract *bind.BoundContract
ctcContract *ctc.CanonicalTransactionChain ctcContract *ctc.CanonicalTransactionChain
walletAddr common.Address walletAddr common.Address
metrics *metrics.Metrics metrics *metrics.Metrics
...@@ -61,11 +64,23 @@ func NewDriver(cfg Config) (*Driver, error) { ...@@ -61,11 +64,23 @@ func NewDriver(cfg Config) (*Driver, error) {
return nil, err return nil, err
} }
parsed, err := abi.JSON(strings.NewReader(
scc.StateCommitmentChainABI,
))
if err != nil {
return nil, err
}
rawSccContract := bind.NewBoundContract(
cfg.SCCAddr, parsed, cfg.L1Client, cfg.L1Client, cfg.L1Client,
)
walletAddr := crypto.PubkeyToAddress(cfg.PrivKey.PublicKey) walletAddr := crypto.PubkeyToAddress(cfg.PrivKey.PublicKey)
return &Driver{ return &Driver{
cfg: cfg, cfg: cfg,
sccContract: sccContract, sccContract: sccContract,
rawSccContract: rawSccContract,
ctcContract: ctcContract, ctcContract: ctcContract,
walletAddr: walletAddr, walletAddr: walletAddr,
metrics: metrics.NewMetrics(cfg.Name), metrics: metrics.NewMetrics(cfg.Name),
...@@ -136,16 +151,20 @@ func (d *Driver) GetBatchBlockRange( ...@@ -136,16 +151,20 @@ func (d *Driver) GetBatchBlockRange(
return start, end, nil return start, end, nil
} }
// SubmitBatchTx transforms the L2 blocks between start and end into a batch // CraftBatchTx transforms the L2 blocks between start and end into a batch
// transaction using the given nonce and gasPrice. The final transaction is // transaction using the given nonce. A dummy gas price is used in the resulting
// published and returned to the call. // transaction to use for size estimation.
func (d *Driver) SubmitBatchTx( //
// NOTE: This method SHOULD NOT publish the resulting transaction.
func (d *Driver) CraftBatchTx(
ctx context.Context, ctx context.Context,
start, end, nonce, gasPrice *big.Int) (*types.Transaction, error) { start, end, nonce *big.Int,
) (*types.Transaction, error) {
name := d.cfg.Name name := d.cfg.Name
batchTxBuildStart := time.Now() log.Info(name+" crafting batch tx", "start", start, "end", end,
"nonce", nonce)
var ( var (
stateRoots [][stateRootSize]byte stateRoots [][stateRootSize]byte
...@@ -166,8 +185,6 @@ func (d *Driver) SubmitBatchTx( ...@@ -166,8 +185,6 @@ func (d *Driver) SubmitBatchTx(
stateRoots = append(stateRoots, block.Root()) stateRoots = append(stateRoots, block.Root())
} }
batchTxBuildTime := float64(time.Since(batchTxBuildStart) / time.Millisecond)
d.metrics.BatchTxBuildTime.Set(batchTxBuildTime)
d.metrics.NumElementsPerBatch.Observe(float64(len(stateRoots))) d.metrics.NumElementsPerBatch.Observe(float64(len(stateRoots)))
log.Info(name+" batch constructed", "num_state_roots", len(stateRoots)) log.Info(name+" batch constructed", "num_state_roots", len(stateRoots))
...@@ -178,12 +195,35 @@ func (d *Driver) SubmitBatchTx( ...@@ -178,12 +195,35 @@ func (d *Driver) SubmitBatchTx(
if err != nil { if err != nil {
return nil, err return nil, err
} }
opts.Nonce = nonce
opts.Context = ctx opts.Context = ctx
opts.GasPrice = gasPrice opts.Nonce = nonce
opts.GasPrice = big.NewInt(params.GWei) // dummy
opts.NoSend = true
blockOffset := new(big.Int).SetUint64(d.cfg.BlockOffset) blockOffset := new(big.Int).SetUint64(d.cfg.BlockOffset)
offsetStartsAtIndex := new(big.Int).Sub(start, blockOffset) offsetStartsAtIndex := new(big.Int).Sub(start, blockOffset)
return d.sccContract.AppendStateBatch(opts, stateRoots, offsetStartsAtIndex) return d.sccContract.AppendStateBatch(opts, stateRoots, offsetStartsAtIndex)
} }
// SubmitBatchTx using the passed transaction as a template, signs and publishes
// an otherwise identical transaction after setting the provided gas price. The
// final transaction is returned to the caller.
func (d *Driver) SubmitBatchTx(
ctx context.Context,
tx *types.Transaction,
gasPrice *big.Int,
) (*types.Transaction, error) {
opts, err := bind.NewKeyedTransactorWithChainID(
d.cfg.PrivKey, d.cfg.ChainID,
)
if err != nil {
return nil, err
}
opts.Context = ctx
opts.Nonce = new(big.Int).SetUint64(tx.Nonce())
opts.GasPrice = gasPrice
return d.rawSccContract.RawTransact(opts, tx.Data())
}
...@@ -6,13 +6,13 @@ import ( ...@@ -6,13 +6,13 @@ import (
"fmt" "fmt"
"math/big" "math/big"
"strings" "strings"
"time"
"github.com/ethereum-optimism/optimism/go/batch-submitter/bindings/ctc" "github.com/ethereum-optimism/optimism/go/batch-submitter/bindings/ctc"
"github.com/ethereum-optimism/optimism/go/batch-submitter/drivers" "github.com/ethereum-optimism/optimism/go/batch-submitter/drivers"
"github.com/ethereum-optimism/optimism/go/batch-submitter/metrics" "github.com/ethereum-optimism/optimism/go/batch-submitter/metrics"
"github.com/ethereum-optimism/optimism/go/batch-submitter/txmgr" "github.com/ethereum-optimism/optimism/go/batch-submitter/txmgr"
l2ethclient "github.com/ethereum-optimism/optimism/l2geth/ethclient" l2ethclient "github.com/ethereum-optimism/optimism/l2geth/ethclient"
"github.com/ethereum-optimism/optimism/l2geth/params"
"github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
...@@ -148,19 +148,20 @@ func (d *Driver) GetBatchBlockRange( ...@@ -148,19 +148,20 @@ func (d *Driver) GetBatchBlockRange(
return start, end, nil return start, end, nil
} }
// SubmitBatchTx transforms the L2 blocks between start and end into a batch // CraftBatchTx transforms the L2 blocks between start and end into a batch
// transaction using the given nonce and gasPrice. The final transaction is // transaction using the given nonce. A dummy gas price is used in the resulting
// published and returned to the call. // transaction to use for size estimation.
func (d *Driver) SubmitBatchTx( //
// NOTE: This method SHOULD NOT publish the resulting transaction.
func (d *Driver) CraftBatchTx(
ctx context.Context, ctx context.Context,
start, end, nonce, gasPrice *big.Int) (*types.Transaction, error) { start, end, nonce *big.Int,
) (*types.Transaction, error) {
name := d.cfg.Name name := d.cfg.Name
log.Info(name+" submitting batch tx", "start", start, "end", end, log.Info(name+" crafting batch tx", "start", start, "end", end,
"gasPrice", gasPrice) "nonce", nonce)
batchTxBuildStart := time.Now()
var ( var (
batchElements []BatchElement batchElements []BatchElement
...@@ -219,9 +220,6 @@ func (d *Driver) SubmitBatchTx( ...@@ -219,9 +220,6 @@ func (d *Driver) SubmitBatchTx(
continue continue
} }
// Record the batch_tx_build_time.
batchTxBuildTime := float64(time.Since(batchTxBuildStart) / time.Millisecond)
d.metrics.BatchTxBuildTime.Set(batchTxBuildTime)
d.metrics.NumElementsPerBatch.Observe(float64(len(batchElements))) d.metrics.NumElementsPerBatch.Observe(float64(len(batchElements)))
d.metrics.BatchPruneCount.Set(float64(pruneCount)) d.metrics.BatchPruneCount.Set(float64(pruneCount))
...@@ -233,10 +231,33 @@ func (d *Driver) SubmitBatchTx( ...@@ -233,10 +231,33 @@ func (d *Driver) SubmitBatchTx(
if err != nil { if err != nil {
return nil, err return nil, err
} }
opts.Nonce = nonce
opts.Context = ctx opts.Context = ctx
opts.GasPrice = gasPrice opts.Nonce = nonce
opts.GasPrice = big.NewInt(params.GWei) // dummy
opts.NoSend = true
return d.rawCtcContract.RawTransact(opts, batchCallData) return d.rawCtcContract.RawTransact(opts, batchCallData)
} }
} }
// SubmitBatchTx using the passed transaction as a template, signs and publishes
// an otherwise identical transaction after setting the provided gas price. The
// final transaction is returned to the caller.
func (d *Driver) SubmitBatchTx(
ctx context.Context,
tx *types.Transaction,
gasPrice *big.Int,
) (*types.Transaction, error) {
opts, err := bind.NewKeyedTransactorWithChainID(
d.cfg.PrivKey, d.cfg.ChainID,
)
if err != nil {
return nil, err
}
opts.Context = ctx
opts.Nonce = new(big.Int).SetUint64(tx.Nonce())
opts.GasPrice = gasPrice
return d.rawCtcContract.RawTransact(opts, tx.Data())
}
package batchsubmitter package batchsubmitter
import ( import (
"bytes"
"context" "context"
"math/big" "math/big"
"sync" "sync"
...@@ -43,12 +44,23 @@ type Driver interface { ...@@ -43,12 +44,23 @@ type Driver interface {
// processed. // processed.
GetBatchBlockRange(ctx context.Context) (*big.Int, *big.Int, error) GetBatchBlockRange(ctx context.Context) (*big.Int, *big.Int, error)
// SubmitBatchTx transforms the L2 blocks between start and end into a // CraftBatchTx transforms the L2 blocks between start and end into a batch
// batch transaction using the given nonce and gasPrice. The final // transaction using the given nonce. A dummy gas price is used in the
// transaction is published and returned to the call. // resulting transaction to use for size estimation.
//
// NOTE: This method SHOULD NOT publish the resulting transaction.
CraftBatchTx(
ctx context.Context,
start, end, nonce *big.Int,
) (*types.Transaction, error)
// SubmitBatchTx using the passed transaction as a template, signs and
// publishes an otherwise identical transaction after setting the provided
// gas price. The final transaction is returned to the caller.
SubmitBatchTx( SubmitBatchTx(
ctx context.Context, ctx context.Context,
start, end, nonce, gasPrice *big.Int, tx *types.Transaction,
gasPrice *big.Int,
) (*types.Transaction, error) ) (*types.Transaction, error)
} }
...@@ -160,6 +172,26 @@ func (s *Service) eventLoop() { ...@@ -160,6 +172,26 @@ func (s *Service) eventLoop() {
} }
nonce := new(big.Int).SetUint64(nonce64) nonce := new(big.Int).SetUint64(nonce64)
batchTxBuildStart := time.Now()
tx, err := s.cfg.Driver.CraftBatchTx(
s.ctx, start, end, nonce,
)
if err != nil {
log.Error(name+" unable to craft batch tx",
"err", err)
continue
}
batchTxBuildTime := time.Since(batchTxBuildStart) / time.Millisecond
s.metrics.BatchTxBuildTime.Set(float64(batchTxBuildTime))
// Record the size of the batch transaction.
var txBuf bytes.Buffer
if err := tx.EncodeRLP(&txBuf); err != nil {
log.Error(name+" unable to encode batch tx", "err", err)
continue
}
s.metrics.BatchSizeInBytes.Observe(float64(len(txBuf.Bytes())))
// Construct the transaction submission clousure that will attempt // Construct the transaction submission clousure that will attempt
// to send the next transaction at the given nonce and gas price. // to send the next transaction at the given nonce and gas price.
sendTx := func( sendTx := func(
...@@ -170,9 +202,7 @@ func (s *Service) eventLoop() { ...@@ -170,9 +202,7 @@ func (s *Service) eventLoop() {
"end", end, "nonce", nonce, "end", end, "nonce", nonce,
"gasPrice", gasPrice) "gasPrice", gasPrice)
tx, err := s.cfg.Driver.SubmitBatchTx( tx, err := s.cfg.Driver.SubmitBatchTx(ctx, tx, gasPrice)
ctx, start, end, nonce, gasPrice,
)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -186,8 +216,6 @@ func (s *Service) eventLoop() { ...@@ -186,8 +216,6 @@ func (s *Service) eventLoop() {
"gasPrice", gasPrice, "gasPrice", gasPrice,
) )
s.metrics.BatchSizeInBytes.Observe(float64(tx.Size()))
return tx, nil return tx, nil
} }
......
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