github.1485827954.workers.dev/ethereum/go-ethereum@v1.14.3/miner/ordering.go (about) 1 // Copyright 2014 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package miner 18 19 import ( 20 "container/heap" 21 "math/big" 22 23 "github.com/ethereum/go-ethereum/common" 24 "github.com/ethereum/go-ethereum/core/txpool" 25 "github.com/ethereum/go-ethereum/core/types" 26 "github.com/holiman/uint256" 27 ) 28 29 // txWithMinerFee wraps a transaction with its gas price or effective miner gasTipCap 30 type txWithMinerFee struct { 31 tx *txpool.LazyTransaction 32 from common.Address 33 fees *uint256.Int 34 } 35 36 // newTxWithMinerFee creates a wrapped transaction, calculating the effective 37 // miner gasTipCap if a base fee is provided. 38 // Returns error in case of a negative effective miner gasTipCap. 39 func newTxWithMinerFee(tx *txpool.LazyTransaction, from common.Address, baseFee *uint256.Int) (*txWithMinerFee, error) { 40 tip := new(uint256.Int).Set(tx.GasTipCap) 41 if baseFee != nil { 42 if tx.GasFeeCap.Cmp(baseFee) < 0 { 43 return nil, types.ErrGasFeeCapTooLow 44 } 45 tip = new(uint256.Int).Sub(tx.GasFeeCap, baseFee) 46 if tip.Gt(tx.GasTipCap) { 47 tip = tx.GasTipCap 48 } 49 } 50 return &txWithMinerFee{ 51 tx: tx, 52 from: from, 53 fees: tip, 54 }, nil 55 } 56 57 // txByPriceAndTime implements both the sort and the heap interface, making it useful 58 // for all at once sorting as well as individually adding and removing elements. 59 type txByPriceAndTime []*txWithMinerFee 60 61 func (s txByPriceAndTime) Len() int { return len(s) } 62 func (s txByPriceAndTime) Less(i, j int) bool { 63 // If the prices are equal, use the time the transaction was first seen for 64 // deterministic sorting 65 cmp := s[i].fees.Cmp(s[j].fees) 66 if cmp == 0 { 67 return s[i].tx.Time.Before(s[j].tx.Time) 68 } 69 return cmp > 0 70 } 71 func (s txByPriceAndTime) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 72 73 func (s *txByPriceAndTime) Push(x interface{}) { 74 *s = append(*s, x.(*txWithMinerFee)) 75 } 76 77 func (s *txByPriceAndTime) Pop() interface{} { 78 old := *s 79 n := len(old) 80 x := old[n-1] 81 old[n-1] = nil 82 *s = old[0 : n-1] 83 return x 84 } 85 86 // transactionsByPriceAndNonce represents a set of transactions that can return 87 // transactions in a profit-maximizing sorted order, while supporting removing 88 // entire batches of transactions for non-executable accounts. 89 type transactionsByPriceAndNonce struct { 90 txs map[common.Address][]*txpool.LazyTransaction // Per account nonce-sorted list of transactions 91 heads txByPriceAndTime // Next transaction for each unique account (price heap) 92 signer types.Signer // Signer for the set of transactions 93 baseFee *uint256.Int // Current base fee 94 } 95 96 // newTransactionsByPriceAndNonce creates a transaction set that can retrieve 97 // price sorted transactions in a nonce-honouring way. 98 // 99 // Note, the input map is reowned so the caller should not interact any more with 100 // if after providing it to the constructor. 101 func newTransactionsByPriceAndNonce(signer types.Signer, txs map[common.Address][]*txpool.LazyTransaction, baseFee *big.Int) *transactionsByPriceAndNonce { 102 // Convert the basefee from header format to uint256 format 103 var baseFeeUint *uint256.Int 104 if baseFee != nil { 105 baseFeeUint = uint256.MustFromBig(baseFee) 106 } 107 // Initialize a price and received time based heap with the head transactions 108 heads := make(txByPriceAndTime, 0, len(txs)) 109 for from, accTxs := range txs { 110 wrapped, err := newTxWithMinerFee(accTxs[0], from, baseFeeUint) 111 if err != nil { 112 delete(txs, from) 113 continue 114 } 115 heads = append(heads, wrapped) 116 txs[from] = accTxs[1:] 117 } 118 heap.Init(&heads) 119 120 // Assemble and return the transaction set 121 return &transactionsByPriceAndNonce{ 122 txs: txs, 123 heads: heads, 124 signer: signer, 125 baseFee: baseFeeUint, 126 } 127 } 128 129 // Peek returns the next transaction by price. 130 func (t *transactionsByPriceAndNonce) Peek() (*txpool.LazyTransaction, *uint256.Int) { 131 if len(t.heads) == 0 { 132 return nil, nil 133 } 134 return t.heads[0].tx, t.heads[0].fees 135 } 136 137 // Shift replaces the current best head with the next one from the same account. 138 func (t *transactionsByPriceAndNonce) Shift() { 139 acc := t.heads[0].from 140 if txs, ok := t.txs[acc]; ok && len(txs) > 0 { 141 if wrapped, err := newTxWithMinerFee(txs[0], acc, t.baseFee); err == nil { 142 t.heads[0], t.txs[acc] = wrapped, txs[1:] 143 heap.Fix(&t.heads, 0) 144 return 145 } 146 } 147 heap.Pop(&t.heads) 148 } 149 150 // Pop removes the best transaction, *not* replacing it with the next one from 151 // the same account. This should be used when a transaction cannot be executed 152 // and hence all subsequent ones should be discarded from the same account. 153 func (t *transactionsByPriceAndNonce) Pop() { 154 heap.Pop(&t.heads) 155 } 156 157 // Empty returns if the price heap is empty. It can be used to check it simpler 158 // than calling peek and checking for nil return. 159 func (t *transactionsByPriceAndNonce) Empty() bool { 160 return len(t.heads) == 0 161 } 162 163 // Clear removes the entire content of the heap. 164 func (t *transactionsByPriceAndNonce) Clear() { 165 t.heads, t.txs = nil, nil 166 }