Skip to content

Commit 670cc7b

Browse files
committed
feat: speed up gas estimation
1 parent 31eb579 commit 670cc7b

2 files changed

Lines changed: 47 additions & 3 deletions

File tree

runner/payload/simulator/simulatorstats/types.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package simulatorstats
22

33
import (
4+
"crypto/sha256"
5+
"encoding/json"
46
"fmt"
57
"maps"
68
"math"
@@ -222,6 +224,16 @@ type Stats struct {
222224
Precompiles OpcodeStats
223225
}
224226

227+
func (s *Stats) Hash() common.Hash {
228+
229+
data, err := json.Marshal(s)
230+
if err != nil {
231+
panic(err)
232+
}
233+
hash := sha256.Sum256(data)
234+
return common.Hash(hash[:])
235+
}
236+
225237
func (s *Stats) ToConfig() (*abi.SimulatorConfig, error) {
226238
rounded := s.Copy().Round()
227239
precompiles := make([]abi.PrecompileConfig, 0, len(rounded.Precompiles))

runner/payload/simulator/worker.go

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ type Contract struct {
3939
type SimulatorPayloadDefinition = simulatorstats.StatsConfig
4040

4141
type simulatorPayloadWorker struct {
42-
log log.Logger
42+
log log.Logger
43+
gasUsedCache map[common.Hash]uint64
4344

4445
params benchtypes.RunParams
4546
chainID *big.Int
@@ -139,12 +140,22 @@ func NewSimulatorPayloadWorker(ctx context.Context, log log.Logger, elRPCURL str
139140

140141
// Create transactors for each caller
141142
transactors := make([]*bind.TransactOpts, numCallers)
143+
142144
for i, key := range callerKeys {
143145
transactor, err := bind.NewKeyedTransactorWithChainID(key, chainID)
144146
if err != nil {
145147
return nil, errors.Wrapf(err, "failed to create transactor for caller %d", i)
146148
}
147149
transactor.NoSend = true
150+
nonce, err := client.PendingNonceAt(context.Background(), crypto.PubkeyToAddress(key.PublicKey))
151+
if err != nil {
152+
return nil, errors.Wrapf(err, "failed to get nonce for caller %d", i)
153+
}
154+
transactor.Nonce = big.NewInt(int64(nonce))
155+
156+
transactor.GasFeeCap = new(big.Int).Mul(big.NewInt(1e9), big.NewInt(1))
157+
transactor.GasTipCap = big.NewInt(1)
158+
148159
transactors[i] = transactor
149160
}
150161

@@ -192,6 +203,7 @@ func NewSimulatorPayloadWorker(ctx context.Context, log log.Logger, elRPCURL str
192203
scaleFactor: scaleFactor,
193204
actualNumConfig: simulatorstats.NewStats(),
194205
numCallers: numCallers,
206+
gasUsedCache: make(map[common.Hash]uint64),
195207
}
196208

197209
return t, nil
@@ -469,6 +481,11 @@ func (t *simulatorPayloadWorker) fundCallerAccounts(ctx context.Context) error {
469481
// If using just the prefunded account, no funding transfer needed
470482
if t.numCallers == 1 && t.callerAddrs[0] == prefundAddr {
471483
t.log.Info("Using single caller (prefunded account)", "address", prefundAddr.Hex())
484+
pendingNonce, err := t.client.PendingNonceAt(ctx, prefundAddr)
485+
if err != nil {
486+
return errors.Wrap(err, "failed to get pending nonce for prefunded account")
487+
}
488+
t.transactors[0].Nonce = big.NewInt(int64(pendingNonce))
472489
return nil
473490
}
474491

@@ -562,21 +579,34 @@ func (t *simulatorPayloadWorker) sendTxs(ctx context.Context) error {
562579

563580
gas := t.params.GasLimit - 100_000
564581

582+
sendTxsStartTime := time.Now()
583+
565584
for i := uint64(0); i < uint64(math.Ceil(float64(t.numCallsPerBlock)*t.scaleFactor)); i++ {
566585
actual := t.actualNumConfig
567586
expected := t.payloadParams.Mul(float64(t.numCalls+1) * t.scaleFactor)
568587

569588
// Round-robin across callers
570589
callerIdx := t.currCallerIdx
571590
t.currCallerIdx = (t.currCallerIdx + 1) % t.numCallers
572-
573591
blockCounts := expected.Sub(actual).Round()
592+
593+
expectedGas, ok := t.gasUsedCache[blockCounts.Hash()]
594+
if ok {
595+
t.transactors[callerIdx].GasLimit = expectedGas
596+
} else {
597+
t.transactors[callerIdx].GasLimit = 0
598+
}
599+
574600
transferTx, err := t.createCallTx(t.transactors[callerIdx], t.callerKeys[callerIdx], blockCounts)
575601
if err != nil {
576602
t.log.Error("Failed to create transfer transaction", "err", err)
577603
return err
578604
}
579605

606+
t.gasUsedCache[blockCounts.Hash()] = transferTx.Gas()
607+
608+
t.transactors[callerIdx].Nonce = t.transactors[callerIdx].Nonce.Add(t.transactors[callerIdx].Nonce, big.NewInt(1))
609+
580610
gasUsed := transferTx.Gas()
581611
if gasUsed > gas {
582612
t.log.Warn("Gas used is greater than gas limit, stopping tx sending", "gasUsed", gasUsed, "gasLimit", t.params.GasLimit)
@@ -594,11 +624,13 @@ func (t *simulatorPayloadWorker) sendTxs(ctx context.Context) error {
594624
}
595625

596626
t.mempool.AddTransactions(txs)
627+
sendTxsDuration := time.Since(sendTxsStartTime)
628+
log.Info("Send transactions duration", "duration", sendTxsDuration, "numCalls", uint64(math.Ceil(float64(t.numCallsPerBlock)*t.scaleFactor)))
597629
return nil
598630
}
599631

600632
func (t *simulatorPayloadWorker) createCallTx(transactor *bind.TransactOpts, fromPriv *ecdsa.PrivateKey, config *simulatorstats.Stats) (*types.Transaction, error) {
601-
simulator, err := abi.NewSimulator(t.contractAddr, t.contractBackend)
633+
simulator, err := abi.NewSimulatorTransactor(t.contractAddr, t.contractBackend)
602634
if err != nil {
603635
return nil, errors.Wrap(err, "failed to create simulator transactor")
604636
}

0 commit comments

Comments
 (0)