Skip to content

Commit 9a29a1e

Browse files
authored
Merge pull request #3100 from OffchainLabs/override_inbox
batch_poster: override delayed inbox for gas estimation
2 parents 1836d0d + 2177b65 commit 9a29a1e

File tree

1 file changed

+90
-52
lines changed

1 file changed

+90
-52
lines changed

arbnode/batch_poster.go

Lines changed: 90 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1030,73 +1030,85 @@ type estimateGasParams struct {
10301030
BlobHashes []common.Hash `json:"blobVersionedHashes,omitempty"`
10311031
}
10321032

1033+
type OverrideAccount struct {
1034+
StateDiff map[common.Hash]common.Hash `json:"stateDiff"`
1035+
}
1036+
1037+
type StateOverride map[common.Address]OverrideAccount
1038+
10331039
func estimateGas(client rpc.ClientInterface, ctx context.Context, params estimateGasParams) (uint64, error) {
10341040
var gas hexutil.Uint64
10351041
err := client.CallContext(ctx, &gas, "eth_estimateGas", params)
10361042
return uint64(gas), err
10371043
}
10381044

1039-
func (b *BatchPoster) estimateGas(
1045+
func (b *BatchPoster) estimateGasSimple(
10401046
ctx context.Context,
1041-
sequencerMessage []byte,
1042-
delayedMessages uint64,
10431047
realData []byte,
10441048
realBlobs []kzg4844.Blob,
1045-
realNonce uint64,
10461049
realAccessList types.AccessList,
1047-
delayProof *bridgegen.DelayProof,
10481050
) (uint64, error) {
10491051

10501052
config := b.config()
10511053
rpcClient := b.l1Reader.Client()
10521054
rawRpcClient := rpcClient.Client()
1053-
useNormalEstimation := b.dataPoster.MaxMempoolTransactions() == 1
1054-
if !useNormalEstimation {
1055-
// Check if we can use normal estimation anyways because we're at the latest nonce
1056-
latestNonce, err := rpcClient.NonceAt(ctx, b.dataPoster.Sender(), nil)
1057-
if err != nil {
1058-
return 0, err
1059-
}
1060-
useNormalEstimation = latestNonce == realNonce
1061-
}
10621055
latestHeader, err := rpcClient.HeaderByNumber(ctx, nil)
10631056
if err != nil {
10641057
return 0, err
10651058
}
10661059
maxFeePerGas := arbmath.BigMulByUBips(latestHeader.BaseFee, config.GasEstimateBaseFeeMultipleBips)
1067-
if useNormalEstimation {
1068-
_, realBlobHashes, err := blobs.ComputeCommitmentsAndHashes(realBlobs)
1069-
if err != nil {
1070-
return 0, fmt.Errorf("failed to compute real blob commitments: %w", err)
1071-
}
1072-
// If we're at the latest nonce, we can skip the special future tx estimate stuff
1073-
gas, err := estimateGas(rawRpcClient, ctx, estimateGasParams{
1074-
From: b.dataPoster.Sender(),
1075-
To: &b.seqInboxAddr,
1076-
Data: realData,
1077-
MaxFeePerGas: (*hexutil.Big)(maxFeePerGas),
1078-
BlobHashes: realBlobHashes,
1079-
AccessList: realAccessList,
1080-
})
1081-
if err != nil {
1082-
return 0, fmt.Errorf("%w: %w", ErrNormalGasEstimationFailed, err)
1083-
}
1084-
return gas + config.ExtraBatchGas, nil
1060+
_, realBlobHashes, err := blobs.ComputeCommitmentsAndHashes(realBlobs)
1061+
if err != nil {
1062+
return 0, fmt.Errorf("failed to compute real blob commitments: %w", err)
10851063
}
1064+
// If we're at the latest nonce, we can skip the special future tx estimate stuff
1065+
gas, err := estimateGas(rawRpcClient, ctx, estimateGasParams{
1066+
From: b.dataPoster.Sender(),
1067+
To: &b.seqInboxAddr,
1068+
Data: realData,
1069+
MaxFeePerGas: (*hexutil.Big)(maxFeePerGas),
1070+
BlobHashes: realBlobHashes,
1071+
AccessList: realAccessList,
1072+
})
1073+
if err != nil {
1074+
return 0, fmt.Errorf("%w: %w", ErrNormalGasEstimationFailed, err)
1075+
}
1076+
return gas + config.ExtraBatchGas, nil
1077+
}
1078+
1079+
// This estimates gas for a batch with future nonce
1080+
// a prev. batch is already pending in the parent chain's mempool
1081+
func (b *BatchPoster) estimateGasForFutureTx(
1082+
ctx context.Context,
1083+
sequencerMessage []byte,
1084+
delayedMessagesBefore uint64,
1085+
delayedMessagesAfter uint64,
1086+
realAccessList types.AccessList,
1087+
usingBlobs bool,
1088+
delayProof *bridgegen.DelayProof,
1089+
) (uint64, error) {
1090+
config := b.config()
1091+
rpcClient := b.l1Reader.Client()
1092+
rawRpcClient := rpcClient.Client()
1093+
latestHeader, err := rpcClient.HeaderByNumber(ctx, nil)
1094+
if err != nil {
1095+
return 0, err
1096+
}
1097+
maxFeePerGas := arbmath.BigMulByUBips(latestHeader.BaseFee, config.GasEstimateBaseFeeMultipleBips)
10861098

10871099
// Here we set seqNum to MaxUint256, and prevMsgNum to 0, because it disables the smart contracts' consistency checks.
10881100
// However, we set nextMsgNum to 1 because it is necessary for a correct estimation for the final to be non-zero.
10891101
// Because we're likely estimating against older state, this might not be the actual next message,
10901102
// but the gas used should be the same.
1091-
data, kzgBlobs, err := b.encodeAddBatch(abi.MaxUint256, 0, 1, sequencerMessage, delayedMessages, len(realBlobs) > 0, delayProof)
1103+
data, kzgBlobs, err := b.encodeAddBatch(abi.MaxUint256, 0, 1, sequencerMessage, delayedMessagesAfter, usingBlobs, delayProof)
10921104
if err != nil {
10931105
return 0, err
10941106
}
10951107
_, blobHashes, err := blobs.ComputeCommitmentsAndHashes(kzgBlobs)
10961108
if err != nil {
10971109
return 0, fmt.Errorf("failed to compute blob commitments: %w", err)
10981110
}
1099-
gas, err := estimateGas(rawRpcClient, ctx, estimateGasParams{
1111+
gasParams := estimateGasParams{
11001112
From: b.dataPoster.Sender(),
11011113
To: &b.seqInboxAddr,
11021114
Data: data,
@@ -1105,7 +1117,22 @@ func (b *BatchPoster) estimateGas(
11051117
// This isn't perfect because we're probably estimating the batch at a different sequence number,
11061118
// but it should overestimate rather than underestimate which is fine.
11071119
AccessList: realAccessList,
1108-
})
1120+
}
1121+
// slot 0 in the SequencerInbox smart contract holds totalDelayedMessagesRead -
1122+
// This is the number of delayed messages that sequencer knows were processed
1123+
// SequencerInbox checks this value to make sure delayed inbox isn't going backward,
1124+
// And it makes it know if a delayProof is needed
1125+
// Both are required for successful batch posting
1126+
stateOverride := StateOverride{
1127+
b.seqInboxAddr: {
1128+
StateDiff: map[common.Hash]common.Hash{
1129+
// slot 0
1130+
{}: common.Hash(arbmath.Uint64ToU256Bytes(delayedMessagesBefore)),
1131+
},
1132+
},
1133+
}
1134+
var gas hexutil.Uint64
1135+
err = rawRpcClient.CallContext(ctx, &gas, "eth_estimateGas", gasParams, rpc.PendingBlockNumber, stateOverride)
11091136
if err != nil {
11101137
sequencerMessageHeader := sequencerMessage
11111138
if len(sequencerMessageHeader) > 33 {
@@ -1114,13 +1141,14 @@ func (b *BatchPoster) estimateGas(
11141141
log.Warn(
11151142
"error estimating gas for batch",
11161143
"err", err,
1117-
"delayedMessages", delayedMessages,
1144+
"delayedMessagesBefore", delayedMessagesBefore,
1145+
"delayedMessagesAfter", delayedMessagesAfter,
11181146
"sequencerMessageHeader", hex.EncodeToString(sequencerMessageHeader),
11191147
"sequencerMessageLen", len(sequencerMessage),
11201148
)
11211149
return 0, fmt.Errorf("error estimating gas for batch: %w", err)
11221150
}
1123-
return gas + config.ExtraBatchGas, nil
1151+
return uint64(gas) + config.ExtraBatchGas, nil
11241152
}
11251153

11261154
const ethPosBlockTime = 12 * time.Second
@@ -1205,11 +1233,6 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error)
12051233
return false, nil
12061234
}
12071235

1208-
lastPotentialMsg, err := b.streamer.GetMessage(msgCount - 1)
1209-
if err != nil {
1210-
return false, err
1211-
}
1212-
12131236
config := b.config()
12141237
forcePostBatch := config.MaxDelay <= 0
12151238

@@ -1489,21 +1512,36 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error)
14891512
return false, fmt.Errorf("produced %v blobs for batch but a block can only hold %v (compressed batch was %v bytes long)", len(kzgBlobs), params.MaxBlobGasPerBlock/params.BlobTxBlobGasPerBlob, len(sequencerMsg))
14901513
}
14911514
accessList := b.accessList(batchPosition.NextSeqNum, b.building.segments.delayedMsg)
1492-
// On restart, we may be trying to estimate gas for a batch whose successor has
1493-
// already made it into pending state, if not latest state.
1494-
// In that case, we might get a revert with `DelayedBackwards()`.
1495-
// To avoid that, we artificially increase the delayed messages to `lastPotentialMsg.DelayedMessagesRead`.
1496-
// In theory, this might reduce gas usage, but only by a factor that's already
1497-
// accounted for in `config.ExtraBatchGas`, as that same factor can appear if a user
1498-
// posts a new delayed message that we didn't see while gas estimating.
14991515
var gasLimit uint64
15001516
if b.config().Dangerous.FixedGasLimit != 0 {
15011517
gasLimit = b.config().Dangerous.FixedGasLimit
15021518
} else {
1503-
gasLimit, err = b.estimateGas(ctx, sequencerMsg, lastPotentialMsg.DelayedMessagesRead, data, kzgBlobs, nonce, accessList, delayProof)
1504-
if err != nil {
1505-
return false, err
1519+
useSimpleEstimation := b.dataPoster.MaxMempoolTransactions() == 1
1520+
if !useSimpleEstimation {
1521+
// Check if we can use normal estimation anyways because we're at the latest nonce
1522+
latestNonce, err := b.l1Reader.Client().NonceAt(ctx, b.dataPoster.Sender(), nil)
1523+
if err != nil {
1524+
return false, err
1525+
}
1526+
useSimpleEstimation = latestNonce == nonce
15061527
}
1528+
1529+
if useSimpleEstimation {
1530+
gasLimit, err = b.estimateGasSimple(ctx, data, kzgBlobs, accessList)
1531+
} else {
1532+
// When there are previous batches queued up in the dataPoster, we override the delayed message count in the sequencer inbox
1533+
// so it accepts the corresponding delay proof. Otherwise, the gas estimation would revert.
1534+
var delayedMsgBefore uint64
1535+
if b.building.firstDelayedMsg != nil {
1536+
delayedMsgBefore = b.building.firstDelayedMsg.DelayedMessagesRead - 1
1537+
} else if b.building.firstNonDelayedMsg != nil {
1538+
delayedMsgBefore = b.building.firstNonDelayedMsg.DelayedMessagesRead
1539+
}
1540+
gasLimit, err = b.estimateGasForFutureTx(ctx, sequencerMsg, delayedMsgBefore, b.building.segments.delayedMsg, accessList, len(kzgBlobs) > 0, delayProof)
1541+
}
1542+
}
1543+
if err != nil {
1544+
return false, err
15071545
}
15081546
newMeta, err := rlp.EncodeToBytes(batchPosterPosition{
15091547
MessageCount: b.building.msgCount,

0 commit comments

Comments
 (0)