github.com/theQRL/go-zond@v0.1.1/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/theQRL/go-zond/common" 24 "github.com/theQRL/go-zond/common/math" 25 "github.com/theQRL/go-zond/core/txpool" 26 "github.com/theQRL/go-zond/core/types" 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 *big.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 *big.Int) (*txWithMinerFee, error) { 40 tip := new(big.Int).Set(tx.GasTipCap) 41 if baseFee != nil { 42 if tx.GasFeeCap.Cmp(baseFee) < 0 { 43 return nil, types.ErrGasFeeCapTooLow 44 } 45 tip = math.BigMin(tx.GasTipCap, new(big.Int).Sub(tx.GasFeeCap, baseFee)) 46 } 47 return &txWithMinerFee{ 48 tx: tx, 49 from: from, 50 fees: tip, 51 }, nil 52 } 53 54 // txByPriceAndTime implements both the sort and the heap interface, making it useful 55 // for all at once sorting as well as individually adding and removing elements. 56 type txByPriceAndTime []*txWithMinerFee 57 58 func (s txByPriceAndTime) Len() int { return len(s) } 59 func (s txByPriceAndTime) Less(i, j int) bool { 60 // If the prices are equal, use the time the transaction was first seen for 61 // deterministic sorting 62 cmp := s[i].fees.Cmp(s[j].fees) 63 if cmp == 0 { 64 return s[i].tx.Time.Before(s[j].tx.Time) 65 } 66 return cmp > 0 67 } 68 func (s txByPriceAndTime) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 69 70 func (s *txByPriceAndTime) Push(x interface{}) { 71 *s = append(*s, x.(*txWithMinerFee)) 72 } 73 74 func (s *txByPriceAndTime) Pop() interface{} { 75 old := *s 76 n := len(old) 77 x := old[n-1] 78 old[n-1] = nil 79 *s = old[0 : n-1] 80 return x 81 } 82 83 // transactionsByPriceAndNonce represents a set of transactions that can return 84 // transactions in a profit-maximizing sorted order, while supporting removing 85 // entire batches of transactions for non-executable accounts. 86 type transactionsByPriceAndNonce struct { 87 txs map[common.Address][]*txpool.LazyTransaction // Per account nonce-sorted list of transactions 88 heads txByPriceAndTime // Next transaction for each unique account (price heap) 89 signer types.Signer // Signer for the set of transactions 90 baseFee *big.Int // Current base fee 91 } 92 93 // newTransactionsByPriceAndNonce creates a transaction set that can retrieve 94 // price sorted transactions in a nonce-honouring way. 95 // 96 // Note, the input map is reowned so the caller should not interact any more with 97 // if after providing it to the constructor. 98 func newTransactionsByPriceAndNonce(signer types.Signer, txs map[common.Address][]*txpool.LazyTransaction, baseFee *big.Int) *transactionsByPriceAndNonce { 99 // Initialize a price and received time based heap with the head transactions 100 heads := make(txByPriceAndTime, 0, len(txs)) 101 for from, accTxs := range txs { 102 wrapped, err := newTxWithMinerFee(accTxs[0], from, baseFee) 103 if err != nil { 104 delete(txs, from) 105 continue 106 } 107 heads = append(heads, wrapped) 108 txs[from] = accTxs[1:] 109 } 110 heap.Init(&heads) 111 112 // Assemble and return the transaction set 113 return &transactionsByPriceAndNonce{ 114 txs: txs, 115 heads: heads, 116 signer: signer, 117 baseFee: baseFee, 118 } 119 } 120 121 // Peek returns the next transaction by price. 122 func (t *transactionsByPriceAndNonce) Peek() *txpool.LazyTransaction { 123 if len(t.heads) == 0 { 124 return nil 125 } 126 return t.heads[0].tx 127 } 128 129 // Shift replaces the current best head with the next one from the same account. 130 func (t *transactionsByPriceAndNonce) Shift() { 131 acc := t.heads[0].from 132 if txs, ok := t.txs[acc]; ok && len(txs) > 0 { 133 if wrapped, err := newTxWithMinerFee(txs[0], acc, t.baseFee); err == nil { 134 t.heads[0], t.txs[acc] = wrapped, txs[1:] 135 heap.Fix(&t.heads, 0) 136 return 137 } 138 } 139 heap.Pop(&t.heads) 140 } 141 142 // Pop removes the best transaction, *not* replacing it with the next one from 143 // the same account. This should be used when a transaction cannot be executed 144 // and hence all subsequent ones should be discarded from the same account. 145 func (t *transactionsByPriceAndNonce) Pop() { 146 heap.Pop(&t.heads) 147 }