Skip to content

Commit

Permalink
modify DetailTxError impl to be usable for batchposter checkReverts
Browse files Browse the repository at this point in the history
  • Loading branch information
ganeshvanahalli committed Mar 25, 2024
1 parent 9bfb92f commit cc5ec18
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 33 deletions.
29 changes: 19 additions & 10 deletions arbnode/batch_poster.go
Original file line number Diff line number Diff line change
Expand Up @@ -431,19 +431,27 @@ func AccessList(opts *AccessListOpts) types.AccessList {
return l
}

type txData struct {
Hash common.Hash `json:"hash"`
Nonce hexutil.Uint64 `json:"nonce"`
From common.Address `json:"from"`
type txInfo struct {
Hash common.Hash `json:"hash"`
Nonce hexutil.Uint64 `json:"nonce"`
From common.Address `json:"from"`
To *common.Address `json:"to"`
Gas hexutil.Uint64 `json:"gas"`
GasPrice *hexutil.Big `json:"gasPrice"`
GasFeeCap *hexutil.Big `json:"maxFeePerGas,omitempty"`
GasTipCap *hexutil.Big `json:"maxPriorityFeePerGas,omitempty"`
Input hexutil.Bytes `json:"input"`
Value *hexutil.Big `json:"value"`
Accesses *types.AccessList `json:"accessList,omitempty"`
}

// getTxsDataByBlock fetches all the transactions inside block of id 'number' using json rpc
// and returns an array of txData which has fields that are necessary in checking for batch reverts
func (b *BatchPoster) getTxsDataByBlock(ctx context.Context, number int64) ([]txData, error) {
// getTxsInfoByBlock fetches all the transactions inside block of id 'number' using json rpc
// and returns an array of txInfo which has fields that are necessary in checking for batch reverts
func (b *BatchPoster) getTxsInfoByBlock(ctx context.Context, number int64) ([]txInfo, error) {
blockNrStr := rpc.BlockNumber(number).String()
rawRpcClient := b.l1Reader.Client().Client()
var blk struct {
Transactions []txData `json:"transactions"`
Transactions []txInfo `json:"transactions"`
}
err := rawRpcClient.CallContext(ctx, &blk, "eth_getBlockByNumber", blockNrStr, true)
if err != nil {
Expand All @@ -461,7 +469,7 @@ func (b *BatchPoster) checkReverts(ctx context.Context, to int64) (bool, error)
return false, fmt.Errorf("wrong range, from: %d > to: %d", b.nextRevertCheckBlock, to)
}
for ; b.nextRevertCheckBlock <= to; b.nextRevertCheckBlock++ {
txs, err := b.getTxsDataByBlock(ctx, b.nextRevertCheckBlock)
txs, err := b.getTxsInfoByBlock(ctx, b.nextRevertCheckBlock)
if err != nil {
return false, fmt.Errorf("error getting transactions data of block %d: %w", b.nextRevertCheckBlock, err)
}
Expand All @@ -477,7 +485,8 @@ func (b *BatchPoster) checkReverts(ctx context.Context, to int64) (bool, error)
if shouldHalt {
logLevel = log.Error
}
logLevel("Transaction from batch poster reverted", "nonce", tx.Nonce, "txHash", tx.Hash, "blockNumber", r.BlockNumber, "blockHash", r.BlockHash)
txErr := arbutil.DetailTxErrorForTxInfo(ctx, b.l1Reader.Client(), tx.Hash, r, tx.From, tx.To, tx.GasPrice.ToInt(), tx.GasFeeCap.ToInt(), tx.GasTipCap.ToInt(), tx.Value.ToInt(), tx.Input, *tx.Accesses, uint64(tx.Gas))
logLevel("Transaction from batch poster reverted", "nonce", tx.Nonce, "txHash", tx.Hash, "blockNumber", r.BlockNumber, "blockHash", r.BlockHash, "txErr", txErr)
return shouldHalt, nil
}
}
Expand Down
46 changes: 23 additions & 23 deletions arbutil/wait_for_l1.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/rpc"
)

Expand All @@ -30,23 +29,20 @@ type L1Interface interface {
Client() rpc.ClientInterface
}

func SendTxAsCall(ctx context.Context, client L1Interface, tx *types.Transaction, from common.Address, blockNum *big.Int, unlimitedGas bool) ([]byte, error) {
var gas uint64
func SendTxAsCall(ctx context.Context, client L1Interface, from common.Address, to *common.Address, gasPrice, gasFeeCap, gasTipCap, value, blockNum *big.Int, data []byte, accessList types.AccessList, gas uint64, unlimitedGas bool) ([]byte, error) {
if unlimitedGas {
gas = 0
} else {
gas = tx.Gas()
}
callMsg := ethereum.CallMsg{
From: from,
To: tx.To(),
To: to,
Gas: gas,
GasPrice: tx.GasPrice(),
GasFeeCap: tx.GasFeeCap(),
GasTipCap: tx.GasTipCap(),
Value: tx.Value(),
Data: tx.Data(),
AccessList: tx.AccessList(),
GasPrice: gasPrice,
GasFeeCap: gasFeeCap,
GasTipCap: gasTipCap,
Value: value,
Data: data,
AccessList: accessList,
}
return client.CallContract(ctx, callMsg, blockNum)
}
Expand All @@ -72,6 +68,15 @@ func GetPendingCallBlockNumber(ctx context.Context, client L1Interface) (*big.In
}

func DetailTxError(ctx context.Context, client L1Interface, tx *types.Transaction, txRes *types.Receipt) error {
// Re-execute the transaction as a call to get a better error
from, err := client.TransactionSender(ctx, tx, txRes.BlockHash, txRes.TransactionIndex)
if err != nil {
return fmt.Errorf("TransactionSender got: %w for tx %v", err, tx.Hash())
}
return DetailTxErrorForTxInfo(ctx, client, tx.Hash(), txRes, from, tx.To(), tx.GasPrice(), tx.GasFeeCap(), tx.GasTipCap(), tx.Value(), tx.Data(), tx.AccessList(), tx.Gas())
}

func DetailTxErrorForTxInfo(ctx context.Context, client L1Interface, txHash common.Hash, txRes *types.Receipt, from common.Address, to *common.Address, gasPrice, gasFeeCap, gasTipCap, value *big.Int, data []byte, accessList types.AccessList, gas uint64) error {
// Re-execute the transaction as a call to get a better error
if ctx.Err() != nil {
return ctx.Err()
Expand All @@ -82,17 +87,12 @@ func DetailTxError(ctx context.Context, client L1Interface, tx *types.Transactio
if txRes.Status == types.ReceiptStatusSuccessful {
return nil
}
from, err := client.TransactionSender(ctx, tx, txRes.BlockHash, txRes.TransactionIndex)
if err != nil {
return fmt.Errorf("TransactionSender got: %w for tx %v", err, tx.Hash())
}
_, err = SendTxAsCall(ctx, client, tx, from, txRes.BlockNumber, false)
if err == nil {
return fmt.Errorf("tx failed but call succeeded for tx hash %v", tx.Hash())
var err error
if _, err = SendTxAsCall(ctx, client, from, to, gasPrice, gasFeeCap, gasTipCap, value, txRes.BlockNumber, data, accessList, gas, false); err == nil {
return fmt.Errorf("tx failed but call succeeded for tx hash %v", txHash)
}
_, err = SendTxAsCall(ctx, client, tx, from, txRes.BlockNumber, true)
if err == nil {
return fmt.Errorf("%w for tx hash %v", vm.ErrOutOfGas, tx.Hash())
if _, err = SendTxAsCall(ctx, client, from, to, gasPrice, gasFeeCap, gasTipCap, value, txRes.BlockNumber, data, accessList, gas, true); err == nil {
return fmt.Errorf("tx failed but call succeeded for tx hash %v", txHash)
}
return fmt.Errorf("SendTxAsCall got: %w for tx hash %v", err, tx.Hash())
return fmt.Errorf("SendTxAsCall got: %w for tx hash %v", err, txHash)
}

0 comments on commit cc5ec18

Please sign in to comment.