github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/core/tx_list.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 19:16:35</date>
    10  //</624450080795004928>
    11  
    12  
    13  package core
    14  
    15  import (
    16  	"container/heap"
    17  	"math"
    18  	"math/big"
    19  	"sort"
    20  
    21  	"github.com/ethereum/go-ethereum/common"
    22  	"github.com/ethereum/go-ethereum/core/types"
    23  	"github.com/ethereum/go-ethereum/log"
    24  )
    25  
    26  //nonceheap是堆。接口实现超过64位无符号整数
    27  //从可能有间隙的未来队列中检索已排序的事务。
    28  type nonceHeap []uint64
    29  
    30  func (h nonceHeap) Len() int           { return len(h) }
    31  func (h nonceHeap) Less(i, j int) bool { return h[i] < h[j] }
    32  func (h nonceHeap) Swap(i, j int)      { h[i], h[j] = h[j], h[i] }
    33  
    34  func (h *nonceHeap) Push(x interface{}) {
    35  	*h = append(*h, x.(uint64))
    36  }
    37  
    38  func (h *nonceHeap) Pop() interface{} {
    39  	old := *h
    40  	n := len(old)
    41  	x := old[n-1]
    42  	*h = old[0 : n-1]
    43  	return x
    44  }
    45  
    46  //txsortedmap是一个nonce->transaction哈希映射,具有基于堆的索引,允许
    47  //以非递增方式迭代内容。
    48  type txSortedMap struct {
    49  items map[uint64]*types.Transaction //存储事务数据的哈希图
    50  index *nonceHeap                    //所有存储事务的当前堆(非严格模式)
    51  cache types.Transactions            //缓存已排序的事务
    52  }
    53  
    54  //newtxsortedmap创建新的非ce排序事务映射。
    55  func newTxSortedMap() *txSortedMap {
    56  	return &txSortedMap{
    57  		items: make(map[uint64]*types.Transaction),
    58  		index: new(nonceHeap),
    59  	}
    60  }
    61  
    62  //get检索与给定nonce关联的当前事务。
    63  func (m *txSortedMap) Get(nonce uint64) *types.Transaction {
    64  	return m.items[nonce]
    65  }
    66  
    67  //在映射中插入新事务,同时更新映射的nonce
    68  //索引。如果已存在具有相同nonce的事务,则将覆盖该事务。
    69  func (m *txSortedMap) Put(tx *types.Transaction) {
    70  	nonce := tx.Nonce()
    71  	if m.items[nonce] == nil {
    72  		heap.Push(m.index, nonce)
    73  	}
    74  	m.items[nonce], m.cache = tx, nil
    75  }
    76  
    77  //forward从映射中删除所有事务,其中nonce小于
    78  //提供阈值。对于任何删除后的事务,都会返回每个已删除的事务。
    79  //维护。
    80  func (m *txSortedMap) Forward(threshold uint64) types.Transactions {
    81  	var removed types.Transactions
    82  
    83  //弹出堆项,直到达到阈值
    84  	for m.index.Len() > 0 && (*m.index)[0] < threshold {
    85  		nonce := heap.Pop(m.index).(uint64)
    86  		removed = append(removed, m.items[nonce])
    87  		delete(m.items, nonce)
    88  	}
    89  //如果我们有一个缓存的订单,转移前面
    90  	if m.cache != nil {
    91  		m.cache = m.cache[len(removed):]
    92  	}
    93  	return removed
    94  }
    95  
    96  //筛选器迭代事务列表并删除其中所有
    97  //指定函数的计算结果为true。
    98  func (m *txSortedMap) Filter(filter func(*types.Transaction) bool) types.Transactions {
    99  	var removed types.Transactions
   100  
   101  //收集所有事务以筛选出
   102  	for nonce, tx := range m.items {
   103  		if filter(tx) {
   104  			removed = append(removed, tx)
   105  			delete(m.items, nonce)
   106  		}
   107  	}
   108  //如果删除了事务,则会破坏堆和缓存
   109  	if len(removed) > 0 {
   110  		*m.index = make([]uint64, 0, len(m.items))
   111  		for nonce := range m.items {
   112  			*m.index = append(*m.index, nonce)
   113  		}
   114  		heap.Init(m.index)
   115  
   116  		m.cache = nil
   117  	}
   118  	return removed
   119  }
   120  
   121  //cap对项目数进行硬限制,返回所有事务
   122  //超过那个限度。
   123  func (m *txSortedMap) Cap(threshold int) types.Transactions {
   124  //项目数量低于限制时短路
   125  	if len(m.items) <= threshold {
   126  		return nil
   127  	}
   128  //否则,收集并删除最高的非ce'd事务
   129  	var drops types.Transactions
   130  
   131  	sort.Sort(*m.index)
   132  	for size := len(m.items); size > threshold; size-- {
   133  		drops = append(drops, m.items[(*m.index)[size-1]])
   134  		delete(m.items, (*m.index)[size-1])
   135  	}
   136  	*m.index = (*m.index)[:threshold]
   137  	heap.Init(m.index)
   138  
   139  //如果我们有一个缓存,把它移到后面
   140  	if m.cache != nil {
   141  		m.cache = m.cache[:len(m.cache)-len(drops)]
   142  	}
   143  	return drops
   144  }
   145  
   146  //移除从维护的映射中删除事务,返回
   147  //找到事务。
   148  func (m *txSortedMap) Remove(nonce uint64) bool {
   149  //无交易时短路
   150  	_, ok := m.items[nonce]
   151  	if !ok {
   152  		return false
   153  	}
   154  //否则,删除事务并修复堆索引
   155  	for i := 0; i < m.index.Len(); i++ {
   156  		if (*m.index)[i] == nonce {
   157  			heap.Remove(m.index, i)
   158  			break
   159  		}
   160  	}
   161  	delete(m.items, nonce)
   162  	m.cache = nil
   163  
   164  	return true
   165  }
   166  
   167  //Ready retrieves a sequentially increasing list of transactions starting at the
   168  //提供了一个准备好进行处理的nonce。返回的事务将
   169  //已从列表中删除。
   170  //
   171  //注意,所有非起始值低于起始值的事务也将返回到
   172  //防止进入无效状态。这不是应该有的事
   173  //发生但最好是自我纠正而不是失败!
   174  func (m *txSortedMap) Ready(start uint64) types.Transactions {
   175  //如果没有可用的交易,则短路
   176  	if m.index.Len() == 0 || (*m.index)[0] > start {
   177  		return nil
   178  	}
   179  //否则开始累积增量事务
   180  	var ready types.Transactions
   181  	for next := (*m.index)[0]; m.index.Len() > 0 && (*m.index)[0] == next; next++ {
   182  		ready = append(ready, m.items[next])
   183  		delete(m.items, next)
   184  		heap.Pop(m.index)
   185  	}
   186  	m.cache = nil
   187  
   188  	return ready
   189  }
   190  
   191  //len返回事务映射的长度。
   192  func (m *txSortedMap) Len() int {
   193  	return len(m.items)
   194  }
   195  
   196  //Flatten基于松散的
   197  //已排序的内部表示。排序结果缓存在
   198  //在对内容进行任何修改之前,需要再次修改。
   199  func (m *txSortedMap) Flatten() types.Transactions {
   200  //如果排序尚未缓存,请创建并缓存排序
   201  	if m.cache == nil {
   202  		m.cache = make(types.Transactions, 0, len(m.items))
   203  		for _, tx := range m.items {
   204  			m.cache = append(m.cache, tx)
   205  		}
   206  		sort.Sort(types.TxByNonce(m.cache))
   207  	}
   208  //复制缓存以防止意外修改
   209  	txs := make(types.Transactions, len(m.cache))
   210  	copy(txs, m.cache)
   211  	return txs
   212  }
   213  
   214  //txlist是属于一个账户的交易的“列表”,按账户排序。
   215  //临时的同一类型可用于存储
   216  //可执行/挂起队列;用于存储非-
   217  //可执行/将来的队列,有轻微的行为更改。
   218  type txList struct {
   219  strict bool         //是否严格连续
   220  txs    *txSortedMap //事务的堆索引排序哈希图
   221  
   222  costcap *big.Int //最高成本核算交易记录的价格(仅当超过余额时重置)
   223  gascap  uint64   //最高支出交易的气体限额(仅在超过区块限额时重置)
   224  }
   225  
   226  //newtxlist创建一个新的事务列表,用于快速维护非索引,
   227  //有间隙、可排序的事务列表。
   228  func newTxList(strict bool) *txList {
   229  	return &txList{
   230  		strict:  strict,
   231  		txs:     newTxSortedMap(),
   232  		costcap: new(big.Int),
   233  	}
   234  }
   235  
   236  //overlaps返回指定的事务是否与一个事务具有相同的nonce
   237  //已经包含在列表中。
   238  func (l *txList) Overlaps(tx *types.Transaction) bool {
   239  	return l.txs.Get(tx.Nonce()) != nil
   240  }
   241  
   242  //add尝试将新事务插入列表,返回
   243  //交易已被接受,如果是,则替换以前的任何交易。
   244  //
   245  //如果新交易被接受到清单中,清单的成本和天然气
   246  //阈值也可能更新。
   247  func (l *txList) Add(tx *types.Transaction, priceBump uint64) (bool, *types.Transaction) {
   248  //如果有旧的更好的事务,请中止
   249  	old := l.txs.Get(tx.Nonce())
   250  	if old != nil {
   251  		threshold := new(big.Int).Div(new(big.Int).Mul(old.GasPrice(), big.NewInt(100+int64(priceBump))), big.NewInt(100))
   252  //必须确保新的天然气价格高于旧的天然气价格
   253  //价格以及检查百分比阈值以确保
   254  //这对于低(wei级)天然气价格的替代品是准确的。
   255  		if old.GasPrice().Cmp(tx.GasPrice()) >= 0 || threshold.Cmp(tx.GasPrice()) > 0 {
   256  			return false, nil
   257  		}
   258  	}
   259  //否则,用当前事务覆盖旧事务
   260  	l.txs.Put(tx)
   261  	if cost := tx.Cost(); l.costcap.Cmp(cost) < 0 {
   262  		l.costcap = cost
   263  	}
   264  	if gas := tx.Gas(); l.gascap < gas {
   265  		l.gascap = gas
   266  	}
   267  	return true, old
   268  }
   269  
   270  //Forward从列表中删除所有事务,其中一个nonce低于
   271  //提供阈值。对于任何删除后的事务,都会返回每个已删除的事务。
   272  //维护。
   273  func (l *txList) Forward(threshold uint64) types.Transactions {
   274  	return l.txs.Forward(threshold)
   275  }
   276  
   277  //过滤器从列表中删除成本或气体限制更高的所有事务
   278  //超过提供的阈值。对于任何
   279  //拆卸后维护。严格模式失效的事务也
   280  //返回。
   281  //
   282  //此方法使用缓存的CostCap和GasCap快速确定
   283  //计算所有成本的一个点,或者如果余额覆盖了所有成本。如果门槛
   284  //低于costgas上限,移除后上限将重置为新的上限
   285  //新失效的交易。
   286  func (l *txList) Filter(costLimit *big.Int, gasLimit uint64) (types.Transactions, types.Transactions) {
   287  //如果所有事务低于阈值,则短路
   288  	if l.costcap.Cmp(costLimit) <= 0 && l.gascap <= gasLimit {
   289  		return nil, nil
   290  	}
   291  l.costcap = new(big.Int).Set(costLimit) //将上限降低到阈值
   292  	l.gascap = gasLimit
   293  
   294  //过滤掉账户资金上方的所有交易
   295  	removed := l.txs.Filter(func(tx *types.Transaction) bool { return tx.Cost().Cmp(costLimit) > 0 || tx.Gas() > gasLimit })
   296  
   297  //如果列表是严格的,则筛选高于最低当前值的任何内容
   298  	var invalids types.Transactions
   299  
   300  	if l.strict && len(removed) > 0 {
   301  		lowest := uint64(math.MaxUint64)
   302  		for _, tx := range removed {
   303  			if nonce := tx.Nonce(); lowest > nonce {
   304  				lowest = nonce
   305  			}
   306  		}
   307  		invalids = l.txs.Filter(func(tx *types.Transaction) bool { return tx.Nonce() > lowest })
   308  	}
   309  	return removed, invalids
   310  }
   311  
   312  //cap对项目数进行硬限制,返回所有事务
   313  //超过那个限度。
   314  func (l *txList) Cap(threshold int) types.Transactions {
   315  	return l.txs.Cap(threshold)
   316  }
   317  
   318  //移除从维护列表中删除事务,返回
   319  //找到交易,并返回因以下原因而失效的任何交易
   320  //删除(仅限严格模式)。
   321  func (l *txList) Remove(tx *types.Transaction) (bool, types.Transactions) {
   322  //从集合中移除事务
   323  	nonce := tx.Nonce()
   324  	if removed := l.txs.Remove(nonce); !removed {
   325  		return false, nil
   326  	}
   327  //在严格模式下,筛选出不可执行的事务
   328  	if l.strict {
   329  		return true, l.txs.Filter(func(tx *types.Transaction) bool { return tx.Nonce() > nonce })
   330  	}
   331  	return true, nil
   332  }
   333  
   334  //就绪检索从
   335  //提供了一个准备好进行处理的nonce。返回的事务将
   336  //已从列表中删除。
   337  //
   338  //注意,所有非起始值低于起始值的事务也将返回到
   339  //防止进入无效状态。这不是应该有的事
   340  //发生但最好是自我纠正而不是失败!
   341  func (l *txList) Ready(start uint64) types.Transactions {
   342  	return l.txs.Ready(start)
   343  }
   344  
   345  //len返回事务列表的长度。
   346  func (l *txList) Len() int {
   347  	return l.txs.Len()
   348  }
   349  
   350  //empty返回事务列表是否为空。
   351  func (l *txList) Empty() bool {
   352  	return l.Len() == 0
   353  }
   354  
   355  //Flatten基于松散的
   356  //已排序的内部表示。排序结果缓存在
   357  //在对内容进行任何修改之前,需要再次修改。
   358  func (l *txList) Flatten() types.Transactions {
   359  	return l.txs.Flatten()
   360  }
   361  
   362  //PriceHeap是一个堆。用于检索的事务的接口实现
   363  //池满时要丢弃的按价格排序的交易记录。
   364  type priceHeap []*types.Transaction
   365  
   366  func (h priceHeap) Len() int      { return len(h) }
   367  func (h priceHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
   368  
   369  func (h priceHeap) Less(i, j int) bool {
   370  //主要按价格排序,返回较便宜的
   371  	switch h[i].GasPrice().Cmp(h[j].GasPrice()) {
   372  	case -1:
   373  		return true
   374  	case 1:
   375  		return false
   376  	}
   377  //如果价格匹配,通过nonce稳定(高nonce更糟)
   378  	return h[i].Nonce() > h[j].Nonce()
   379  }
   380  
   381  func (h *priceHeap) Push(x interface{}) {
   382  	*h = append(*h, x.(*types.Transaction))
   383  }
   384  
   385  func (h *priceHeap) Pop() interface{} {
   386  	old := *h
   387  	n := len(old)
   388  	x := old[n-1]
   389  	*h = old[0 : n-1]
   390  	return x
   391  }
   392  
   393  //txPricedList是一个价格排序堆,允许对事务池进行操作
   394  //价格递增的内容。
   395  type txPricedList struct {
   396  all    *txLookup  //指向所有事务映射的指针
   397  items  *priceHeap //所有存储事务的价格堆
   398  stales int        //失效价格点的数目(重新堆触发器)
   399  }
   400  
   401  //newtxPricedList创建一个新的按价格排序的事务堆。
   402  func newTxPricedList(all *txLookup) *txPricedList {
   403  	return &txPricedList{
   404  		all:   all,
   405  		items: new(priceHeap),
   406  	}
   407  }
   408  
   409  //PUT向堆中插入新事务。
   410  func (l *txPricedList) Put(tx *types.Transaction) {
   411  	heap.Push(l.items, tx)
   412  }
   413  
   414  //已删除通知价格事务列表旧事务已删除
   415  //从游泳池。列表只保留过时对象的计数器并更新
   416  //如果足够大的事务比率过时,则为堆。
   417  func (l *txPricedList) Removed() {
   418  //撞击陈旧的计数器,但如果仍然过低(<25%),则退出。
   419  	l.stales++
   420  	if l.stales <= len(*l.items)/4 {
   421  		return
   422  	}
   423  //似乎我们已经达到了一个关键的陈旧的交易数量,reheap
   424  	reheap := make(priceHeap, 0, l.all.Count())
   425  
   426  	l.stales, l.items = 0, &reheap
   427  	l.all.Range(func(hash common.Hash, tx *types.Transaction) bool {
   428  		*l.items = append(*l.items, tx)
   429  		return true
   430  	})
   431  	heap.Init(l.items)
   432  }
   433  
   434  //cap查找低于给定价格阈值的所有交易,并将其删除
   435  //从定价列表中返回它们以便从整个池中进一步删除。
   436  func (l *txPricedList) Cap(threshold *big.Int, local *accountSet) types.Transactions {
   437  drop := make(types.Transactions, 0, 128) //要删除的远程低价交易
   438  save := make(types.Transactions, 0, 64)  //要保留的本地定价过低交易
   439  
   440  	for len(*l.items) > 0 {
   441  //如果在清理过程中发现过时的事务,则放弃这些事务
   442  		tx := heap.Pop(l.items).(*types.Transaction)
   443  		if l.all.Get(tx.Hash()) == nil {
   444  			l.stales--
   445  			continue
   446  		}
   447  //如果我们达到了临界值,就停止丢弃
   448  		if tx.GasPrice().Cmp(threshold) >= 0 {
   449  			save = append(save, tx)
   450  			break
   451  		}
   452  //找到未过期的事务,除非本地
   453  		if local.containsTx(tx) {
   454  			save = append(save, tx)
   455  		} else {
   456  			drop = append(drop, tx)
   457  		}
   458  	}
   459  	for _, tx := range save {
   460  		heap.Push(l.items, tx)
   461  	}
   462  	return drop
   463  }
   464  
   465  //低价检查交易是否比
   466  //当前正在跟踪的最低价格交易记录。
   467  func (l *txPricedList) Underpriced(tx *types.Transaction, local *accountSet) bool {
   468  //本地交易不能定价过低
   469  	if local.containsTx(tx) {
   470  		return false
   471  	}
   472  //如果在堆开始处找到过时的价格点,则丢弃它们
   473  	for len(*l.items) > 0 {
   474  		head := []*types.Transaction(*l.items)[0]
   475  		if l.all.Get(head.Hash()) == nil {
   476  			l.stales--
   477  			heap.Pop(l.items)
   478  			continue
   479  		}
   480  		break
   481  	}
   482  //检查交易是否定价过低
   483  	if len(*l.items) == 0 {
   484  log.Error("Pricing query for empty pool") //这不可能发生,打印以捕获编程错误
   485  		return false
   486  	}
   487  	cheapest := []*types.Transaction(*l.items)[0]
   488  	return cheapest.GasPrice().Cmp(tx.GasPrice()) >= 0
   489  }
   490  
   491  //Discard查找许多定价最低的事务,将它们从
   492  //并返回它们以便从整个池中进一步删除。
   493  func (l *txPricedList) Discard(count int, local *accountSet) types.Transactions {
   494  drop := make(types.Transactions, 0, count) //要删除的远程低价交易
   495  save := make(types.Transactions, 0, 64)    //要保留的本地定价过低交易
   496  
   497  	for len(*l.items) > 0 && count > 0 {
   498  //如果在清理过程中发现过时的事务,则放弃这些事务
   499  		tx := heap.Pop(l.items).(*types.Transaction)
   500  		if l.all.Get(tx.Hash()) == nil {
   501  			l.stales--
   502  			continue
   503  		}
   504  //找到未过期的事务,除非本地
   505  		if local.containsTx(tx) {
   506  			save = append(save, tx)
   507  		} else {
   508  			drop = append(drop, tx)
   509  			count--
   510  		}
   511  	}
   512  	for _, tx := range save {
   513  		heap.Push(l.items, tx)
   514  	}
   515  	return drop
   516  }
   517