@@ -1030,73 +1030,85 @@ type estimateGasParams struct {
1030
1030
BlobHashes []common.Hash `json:"blobVersionedHashes,omitempty"`
1031
1031
}
1032
1032
1033
+ type OverrideAccount struct {
1034
+ StateDiff map [common.Hash ]common.Hash `json:"stateDiff"`
1035
+ }
1036
+
1037
+ type StateOverride map [common.Address ]OverrideAccount
1038
+
1033
1039
func estimateGas (client rpc.ClientInterface , ctx context.Context , params estimateGasParams ) (uint64 , error ) {
1034
1040
var gas hexutil.Uint64
1035
1041
err := client .CallContext (ctx , & gas , "eth_estimateGas" , params )
1036
1042
return uint64 (gas ), err
1037
1043
}
1038
1044
1039
- func (b * BatchPoster ) estimateGas (
1045
+ func (b * BatchPoster ) estimateGasSimple (
1040
1046
ctx context.Context ,
1041
- sequencerMessage []byte ,
1042
- delayedMessages uint64 ,
1043
1047
realData []byte ,
1044
1048
realBlobs []kzg4844.Blob ,
1045
- realNonce uint64 ,
1046
1049
realAccessList types.AccessList ,
1047
- delayProof * bridgegen.DelayProof ,
1048
1050
) (uint64 , error ) {
1049
1051
1050
1052
config := b .config ()
1051
1053
rpcClient := b .l1Reader .Client ()
1052
1054
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
- }
1062
1055
latestHeader , err := rpcClient .HeaderByNumber (ctx , nil )
1063
1056
if err != nil {
1064
1057
return 0 , err
1065
1058
}
1066
1059
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 )
1085
1063
}
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 )
1086
1098
1087
1099
// Here we set seqNum to MaxUint256, and prevMsgNum to 0, because it disables the smart contracts' consistency checks.
1088
1100
// However, we set nextMsgNum to 1 because it is necessary for a correct estimation for the final to be non-zero.
1089
1101
// Because we're likely estimating against older state, this might not be the actual next message,
1090
1102
// 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 )
1092
1104
if err != nil {
1093
1105
return 0 , err
1094
1106
}
1095
1107
_ , blobHashes , err := blobs .ComputeCommitmentsAndHashes (kzgBlobs )
1096
1108
if err != nil {
1097
1109
return 0 , fmt .Errorf ("failed to compute blob commitments: %w" , err )
1098
1110
}
1099
- gas , err := estimateGas ( rawRpcClient , ctx , estimateGasParams {
1111
+ gasParams := estimateGasParams {
1100
1112
From : b .dataPoster .Sender (),
1101
1113
To : & b .seqInboxAddr ,
1102
1114
Data : data ,
@@ -1105,7 +1117,22 @@ func (b *BatchPoster) estimateGas(
1105
1117
// This isn't perfect because we're probably estimating the batch at a different sequence number,
1106
1118
// but it should overestimate rather than underestimate which is fine.
1107
1119
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 )
1109
1136
if err != nil {
1110
1137
sequencerMessageHeader := sequencerMessage
1111
1138
if len (sequencerMessageHeader ) > 33 {
@@ -1114,13 +1141,14 @@ func (b *BatchPoster) estimateGas(
1114
1141
log .Warn (
1115
1142
"error estimating gas for batch" ,
1116
1143
"err" , err ,
1117
- "delayedMessages" , delayedMessages ,
1144
+ "delayedMessagesBefore" , delayedMessagesBefore ,
1145
+ "delayedMessagesAfter" , delayedMessagesAfter ,
1118
1146
"sequencerMessageHeader" , hex .EncodeToString (sequencerMessageHeader ),
1119
1147
"sequencerMessageLen" , len (sequencerMessage ),
1120
1148
)
1121
1149
return 0 , fmt .Errorf ("error estimating gas for batch: %w" , err )
1122
1150
}
1123
- return gas + config .ExtraBatchGas , nil
1151
+ return uint64 ( gas ) + config .ExtraBatchGas , nil
1124
1152
}
1125
1153
1126
1154
const ethPosBlockTime = 12 * time .Second
@@ -1205,11 +1233,6 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error)
1205
1233
return false , nil
1206
1234
}
1207
1235
1208
- lastPotentialMsg , err := b .streamer .GetMessage (msgCount - 1 )
1209
- if err != nil {
1210
- return false , err
1211
- }
1212
-
1213
1236
config := b .config ()
1214
1237
forcePostBatch := config .MaxDelay <= 0
1215
1238
@@ -1489,21 +1512,36 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error)
1489
1512
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 ))
1490
1513
}
1491
1514
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.
1499
1515
var gasLimit uint64
1500
1516
if b .config ().Dangerous .FixedGasLimit != 0 {
1501
1517
gasLimit = b .config ().Dangerous .FixedGasLimit
1502
1518
} 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
1506
1527
}
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
1507
1545
}
1508
1546
newMeta , err := rlp .EncodeToBytes (batchPosterPosition {
1509
1547
MessageCount : b .building .msgCount ,
0 commit comments