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