diff --git a/core/state_processor.go b/core/state_processor.go index 9f679baeb7..983ee44233 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -314,6 +314,8 @@ func (p *StateProcessor) Process(block *types.WorkObject, batch ethdb.Batch) (ty totalQiProcessTimes := make(map[string]time.Duration) firstQiTx := true + nonEtxExists := false + primeTerminus := p.hc.GetHeaderByHash(header.PrimeTerminusHash()) if primeTerminus == nil { return nil, nil, nil, nil, 0, 0, nil, fmt.Errorf("could not find prime terminus header %032x", header.PrimeTerminusHash()) @@ -322,7 +324,7 @@ func (p *StateProcessor) Process(block *types.WorkObject, batch ethdb.Batch) (ty // value is not the basefee mentioned in the block, the block is invalid In // the case of the Qi transactions, its converted into Quai at the rate // defined in the prime terminus - minGasPrice := big.NewInt(0) + var minGasPrice *big.Int for i, tx := range block.Transactions() { startProcess := time.Now() @@ -350,7 +352,7 @@ func (p *StateProcessor) Process(block *types.WorkObject, batch ethdb.Batch) (ty qiTxFeeInQuai := misc.QiToQuai(primeTerminus.WorkObjectHeader(), qiTxFee) // get the gas price by dividing the fee by qiTxGas qiGasPrice := new(big.Int).Div(qiTxFeeInQuai, big.NewInt(int64(types.CalculateBlockQiTxGas(tx, p.hc.NodeLocation())))) - if minGasPrice.Cmp(big.NewInt(0)) == 0 { + if minGasPrice == nil { minGasPrice = new(big.Int).Set(qiGasPrice) } else { if minGasPrice.Cmp(qiGasPrice) > 0 { @@ -366,6 +368,8 @@ func (p *StateProcessor) Process(block *types.WorkObject, batch ethdb.Batch) (ty totalQiProcessTimes["Fee Verification"] += timing["Fee Verification"] totalQiProcessTimes["Signature Check"] += timing["Signature Check"] + nonEtxExists = true + continue } @@ -573,7 +577,7 @@ func (p *StateProcessor) Process(block *types.WorkObject, batch ethdb.Batch) (ty // update the min gas price if the gas price in the tx is less than // the min gas price - if minGasPrice.Cmp(big.NewInt(0)) == 0 { + if minGasPrice == nil { minGasPrice = new(big.Int).Set(tx.GasPrice()) } else { if minGasPrice.Cmp(tx.GasPrice()) > 0 { @@ -596,8 +600,11 @@ func (p *StateProcessor) Process(block *types.WorkObject, batch ethdb.Batch) (ty i++ } - if block.BaseFee().Cmp(minGasPrice) != 0 { - log.Global.Error("length of transactions", len(block.Transactions())) + if nonEtxExists && block.BaseFee().Cmp(big.NewInt(0)) == 0 { + return nil, nil, nil, nil, 0, 0, nil, fmt.Errorf("block base fee is nil though non etx transactions exist") + } + + if minGasPrice != nil && block.BaseFee().Cmp(minGasPrice) != 0 { return nil, nil, nil, nil, 0, 0, nil, fmt.Errorf("invalid base fee used (remote: %d local: %d)", block.BaseFee(), minGasPrice) } diff --git a/core/tx_pool.go b/core/tx_pool.go index 1e049cfbbe..d68f0b6b66 100644 --- a/core/tx_pool.go +++ b/core/tx_pool.go @@ -711,7 +711,7 @@ func (pool *TxPool) TxPoolPending(enforceTips bool) (map[common.AddressBytes]typ "gasPrice": tx.GasPrice().String(), "poolGasPrice": pool.gasPrice.String(), "baseFee": pool.priced.urgent.baseFee.String(), - }).Debug("TX has incorrect or low miner tip") + }).Debug("TX has incorrect or low gas price") txs = txs[:i] break } diff --git a/core/worker.go b/core/worker.go index 7080d38d3e..81400d4155 100644 --- a/core/worker.go +++ b/core/worker.go @@ -740,6 +740,10 @@ func (w *worker) OrderTransactionSet(txs []*types.Transaction, gasUsedAfterTrans } else { gasPrice = new(big.Int).Set(tx.GasPrice()) } + if gasPrice.Cmp(big.NewInt(0)) == 0 { + w.logger.Error("found tx with zero gas price in order transaction set") + continue + } txInfos = append(txInfos, TransactionInfo{ Tx: tx, GasPrice: gasPrice, @@ -1674,6 +1678,10 @@ func (w *worker) fillTransactions(env *environment, primeTerminus *types.WorkObj txByPriceAndNonce := types.TransactionsByPriceAndNonce{} txByPriceAndNonce.SetHead(orderedTxs) + if baseFee.Cmp(big.NewInt(0)) == 0 { + return errors.New("ordered txs had min gas price of zero") + } + env.wo.Header().SetBaseFee(baseFee) err := w.commitTransactions(env, primeTerminus, block, &txByPriceAndNonce, false) if err != nil { @@ -1708,6 +1716,10 @@ func (w *worker) fillTransactions(env *environment, primeTerminus *types.WorkObj // update the fee qiFeeInQuai := misc.QiToQuai(primeTerminus, tx.MinerFee()) minerFeeInQuai := new(big.Int).Div(qiFeeInQuai, big.NewInt(int64(types.CalculateBlockQiTxGas(tx.Tx(), w.hc.NodeLocation())))) + if minerFeeInQuai.Cmp(big.NewInt(0)) == 0 { + w.logger.Error("rejecting qi tx that has zero gas price") + continue + } qiTx, err := types.NewTxWithMinerFee(tx.Tx(), minerFeeInQuai, time.Now()) if err != nil { w.logger.WithField("err", err).Error("Error created new tx with miner Fee for Qi TX", tx.Tx().Hash()) @@ -1732,6 +1744,9 @@ func (w *worker) fillTransactions(env *environment, primeTerminus *types.WorkObj // read the gas price of the lowest fee transaction and set the base // fee for the pending header on each iteration baseFee = lowestFeeTx.PeekAndGetFee().MinerFee() + if baseFee.Cmp(big.NewInt(0)) == 0 { + continue + } env.wo.Header().SetBaseFee(baseFee) w.commitTransactions(env, primeTerminus, block, lowestFeeTx, etxIncluded) // After the first run the etxs are included diff --git a/internal/quaiapi/api.go b/internal/quaiapi/api.go index f67fe98f19..4fccd08028 100644 --- a/internal/quaiapi/api.go +++ b/internal/quaiapi/api.go @@ -990,8 +990,8 @@ type RPCTransaction struct { MinerTip *hexutil.Big `json:"minerTip,omitempty"` GasPrice *hexutil.Big `json:"gasPrice,omitempty"` Hash common.Hash `json:"hash,omitempty"` - Input hexutil.Bytes `json:"input,omitempty"` - Nonce hexutil.Uint64 `json:"nonce,omitempty"` + Input hexutil.Bytes `json:"input"` + Nonce hexutil.Uint64 `json:"nonce"` To *common.MixedcaseAddress `json:"to,omitempty"` TransactionIndex *hexutil.Uint64 `json:"transactionIndex"` Value *hexutil.Big `json:"value,omitempty"` @@ -1061,12 +1061,14 @@ func newRPCTransaction(tx *types.Transaction, blockHash common.Hash, blockNumber Hash: tx.Hash(), Input: hexutil.Bytes(tx.Data()), Nonce: hexutil.Uint64(tx.Nonce()), - To: tx.To().MixedcaseAddressPtr(), Value: (*hexutil.Big)(tx.Value()), ChainID: (*hexutil.Big)(tx.ChainId()), GasPrice: (*hexutil.Big)(tx.GasPrice()), MinerTip: (*hexutil.Big)(tx.MinerTip()), } + if tx.To() != nil { + result.To = tx.To().MixedcaseAddressPtr() + } case types.ExternalTxType: result = &RPCTransaction{ Type: hexutil.Uint64(tx.Type()),