github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/core/tx_pool.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 //</624450080895668224> 11 12 13 package core 14 15 import ( 16 "errors" 17 "fmt" 18 "math" 19 "math/big" 20 "sort" 21 "sync" 22 "time" 23 24 "github.com/ethereum/go-ethereum/common" 25 "github.com/ethereum/go-ethereum/common/prque" 26 "github.com/ethereum/go-ethereum/core/state" 27 "github.com/ethereum/go-ethereum/core/types" 28 "github.com/ethereum/go-ethereum/event" 29 "github.com/ethereum/go-ethereum/log" 30 "github.com/ethereum/go-ethereum/metrics" 31 "github.com/ethereum/go-ethereum/params" 32 ) 33 34 const ( 35 //ChainHeadChansize是侦听ChainHeadEvent的通道的大小。 36 chainHeadChanSize = 10 37 ) 38 39 var ( 40 //如果事务包含无效签名,则返回errInvalidSender。 41 ErrInvalidSender = errors.New("invalid sender") 42 43 //如果事务的nonce低于 44 //一个存在于本地链中。 45 ErrNonceTooLow = errors.New("nonce too low") 46 47 //如果交易的天然气价格低于最低价格,则返回定价错误。 48 //为事务池配置。 49 ErrUnderpriced = errors.New("transaction underpriced") 50 51 //如果试图替换事务,则返回erreplaceCunderpriced 52 //另一个没有要求的价格上涨。 53 ErrReplaceUnderpriced = errors.New("replacement transaction underpriced") 54 55 //如果执行事务的总成本为 56 //高于用户帐户的余额。 57 ErrInsufficientFunds = errors.New("insufficient funds for gas * price + value") 58 59 //如果交易指定使用更少的气体,则返回errintrinsicgas 60 //启动调用所需的。 61 ErrIntrinsicGas = errors.New("intrinsic gas too low") 62 63 //如果交易请求的气体限制超过 64 //当前块的最大允许量。 65 ErrGasLimit = errors.New("exceeds block gas limit") 66 67 //errNegativeValue是一个健全的错误,用于确保没有人能够指定 68 //负值的交易记录。 69 ErrNegativeValue = errors.New("negative value") 70 71 //如果事务的输入数据大于 72 //而不是用户可能使用的一些有意义的限制。这不是共识错误 73 //使事务无效,而不是DoS保护。 74 ErrOversizedData = errors.New("oversized data") 75 ) 76 77 var ( 78 evictionInterval = time.Minute //检查可收回事务的时间间隔 79 statsReportInterval = 8 * time.Second //报告事务池统计的时间间隔 80 ) 81 82 var ( 83 //挂起池的指标 84 pendingDiscardCounter = metrics.NewRegisteredCounter("txpool/pending/discard", nil) 85 pendingReplaceCounter = metrics.NewRegisteredCounter("txpool/pending/replace", nil) 86 pendingRateLimitCounter = metrics.NewRegisteredCounter("txpool/pending/ratelimit", nil) //由于速率限制而下降 87 pendingNofundsCounter = metrics.NewRegisteredCounter("txpool/pending/nofunds", nil) //因资金不足而放弃 88 89 //排队池的指标 90 queuedDiscardCounter = metrics.NewRegisteredCounter("txpool/queued/discard", nil) 91 queuedReplaceCounter = metrics.NewRegisteredCounter("txpool/queued/replace", nil) 92 queuedRateLimitCounter = metrics.NewRegisteredCounter("txpool/queued/ratelimit", nil) //由于速率限制而下降 93 queuedNofundsCounter = metrics.NewRegisteredCounter("txpool/queued/nofunds", nil) //因资金不足而放弃 94 95 //一般Tx指标 96 invalidTxCounter = metrics.NewRegisteredCounter("txpool/invalid", nil) 97 underpricedTxCounter = metrics.NewRegisteredCounter("txpool/underpriced", nil) 98 ) 99 100 //txstatus是由池看到的事务的当前状态。 101 type TxStatus uint 102 103 const ( 104 TxStatusUnknown TxStatus = iota 105 TxStatusQueued 106 TxStatusPending 107 TxStatusIncluded 108 ) 109 110 //区块链提供区块链的状态和当前的天然气限制。 111 //Tx池和事件订阅服务器中的一些预检查。 112 type blockChain interface { 113 CurrentBlock() *types.Block 114 GetBlock(hash common.Hash, number uint64) *types.Block 115 StateAt(root common.Hash) (*state.StateDB, error) 116 117 SubscribeChainHeadEvent(ch chan<- ChainHeadEvent) event.Subscription 118 } 119 120 //TxPoolConfig是事务池的配置参数。 121 type TxPoolConfig struct { 122 Locals []common.Address //默认情况下应视为本地地址的地址 123 NoLocals bool //是否应禁用本地事务处理 124 Journal string //在节点重新启动后幸存的本地事务日志 125 Rejournal time.Duration //重新生成本地事务日记帐的时间间隔 126 127 PriceLimit uint64 //用于验收的最低天然气价格 128 PriceBump uint64 //替换已存在交易的最低价格波动百分比(nonce) 129 130 AccountSlots uint64 //每个帐户保证的可执行事务槽数 131 GlobalSlots uint64 //所有帐户的最大可执行事务槽数 132 AccountQueue uint64 //每个帐户允许的最大不可执行事务槽数 133 GlobalQueue uint64 //所有帐户的最大不可执行事务槽数 134 135 Lifetime time.Duration //非可执行事务排队的最长时间 136 } 137 138 //DefaultTxPoolConfig包含事务的默认配置 139 //池。 140 var DefaultTxPoolConfig = TxPoolConfig{ 141 Journal: "transactions.rlp", 142 Rejournal: time.Hour, 143 144 PriceLimit: 1, 145 PriceBump: 10, 146 147 AccountSlots: 16, 148 GlobalSlots: 4096, 149 AccountQueue: 64, 150 GlobalQueue: 1024, 151 152 Lifetime: 3 * time.Hour, 153 } 154 155 //清理检查提供的用户配置并更改 156 //不合理或不可行。 157 func (config *TxPoolConfig) sanitize() TxPoolConfig { 158 conf := *config 159 if conf.Rejournal < time.Second { 160 log.Warn("Sanitizing invalid txpool journal time", "provided", conf.Rejournal, "updated", time.Second) 161 conf.Rejournal = time.Second 162 } 163 if conf.PriceLimit < 1 { 164 log.Warn("Sanitizing invalid txpool price limit", "provided", conf.PriceLimit, "updated", DefaultTxPoolConfig.PriceLimit) 165 conf.PriceLimit = DefaultTxPoolConfig.PriceLimit 166 } 167 if conf.PriceBump < 1 { 168 log.Warn("Sanitizing invalid txpool price bump", "provided", conf.PriceBump, "updated", DefaultTxPoolConfig.PriceBump) 169 conf.PriceBump = DefaultTxPoolConfig.PriceBump 170 } 171 if conf.AccountSlots < 1 { 172 log.Warn("Sanitizing invalid txpool account slots", "provided", conf.AccountSlots, "updated", DefaultTxPoolConfig.AccountSlots) 173 conf.AccountSlots = DefaultTxPoolConfig.AccountSlots 174 } 175 if conf.GlobalSlots < 1 { 176 log.Warn("Sanitizing invalid txpool global slots", "provided", conf.GlobalSlots, "updated", DefaultTxPoolConfig.GlobalSlots) 177 conf.GlobalSlots = DefaultTxPoolConfig.GlobalSlots 178 } 179 if conf.AccountQueue < 1 { 180 log.Warn("Sanitizing invalid txpool account queue", "provided", conf.AccountQueue, "updated", DefaultTxPoolConfig.AccountQueue) 181 conf.AccountQueue = DefaultTxPoolConfig.AccountQueue 182 } 183 if conf.GlobalQueue < 1 { 184 log.Warn("Sanitizing invalid txpool global queue", "provided", conf.GlobalQueue, "updated", DefaultTxPoolConfig.GlobalQueue) 185 conf.GlobalQueue = DefaultTxPoolConfig.GlobalQueue 186 } 187 if conf.Lifetime < 1 { 188 log.Warn("Sanitizing invalid txpool lifetime", "provided", conf.Lifetime, "updated", DefaultTxPoolConfig.Lifetime) 189 conf.Lifetime = DefaultTxPoolConfig.Lifetime 190 } 191 return conf 192 } 193 194 //TxPool包含所有当前已知的事务。交易 195 //从网络接收或提交时输入池 196 //局部地。当它们包含在区块链中时,它们退出池。 197 // 198 //池将可处理的事务(可应用于 199 //当前状态)和未来交易。事务在这些事务之间移动 200 //两种状态随着时间的推移而被接收和处理。 201 type TxPool struct { 202 config TxPoolConfig 203 chainconfig *params.ChainConfig 204 chain blockChain 205 gasPrice *big.Int 206 txFeed event.Feed 207 scope event.SubscriptionScope 208 chainHeadCh chan ChainHeadEvent 209 chainHeadSub event.Subscription 210 signer types.Signer 211 mu sync.RWMutex 212 213 currentState *state.StateDB //区块链头中的当前状态 214 pendingState *state.ManagedState //挂起状态跟踪虚拟当前 215 currentMaxGas uint64 //交易上限的当前天然气限额 216 217 locals *accountSet //要免除逐出规则的本地事务集 218 journal *txJournal //备份到磁盘的本地事务日志 219 220 pending map[common.Address]*txList //所有当前可处理的事务 221 queue map[common.Address]*txList //排队但不可处理的事务 222 beats map[common.Address]time.Time //每个已知帐户的最后一个心跳 223 all *txLookup //允许查找的所有事务 224 priced *txPricedList //按价格排序的所有交易记录 225 226 wg sync.WaitGroup //用于关机同步 227 228 homestead bool 229 } 230 231 //newtxpool创建一个新的事务池来收集、排序和筛选入站事务 232 //来自网络的事务。 233 func NewTxPool(config TxPoolConfig, chainconfig *params.ChainConfig, chain blockChain) *TxPool { 234 //对输入进行消毒,以确保不设定脆弱的天然气价格。 235 config = (&config).sanitize() 236 237 //使用事务池的初始设置创建事务池 238 pool := &TxPool{ 239 config: config, 240 chainconfig: chainconfig, 241 chain: chain, 242 signer: types.NewEIP155Signer(chainconfig.ChainID), 243 pending: make(map[common.Address]*txList), 244 queue: make(map[common.Address]*txList), 245 beats: make(map[common.Address]time.Time), 246 all: newTxLookup(), 247 chainHeadCh: make(chan ChainHeadEvent, chainHeadChanSize), 248 gasPrice: new(big.Int).SetUint64(config.PriceLimit), 249 } 250 pool.locals = newAccountSet(pool.signer) 251 for _, addr := range config.Locals { 252 log.Info("Setting new local account", "address", addr) 253 pool.locals.add(addr) 254 } 255 pool.priced = newTxPricedList(pool.all) 256 pool.reset(nil, chain.CurrentBlock().Header()) 257 258 //如果启用了本地事务和日记,则从磁盘加载 259 if !config.NoLocals && config.Journal != "" { 260 pool.journal = newTxJournal(config.Journal) 261 262 if err := pool.journal.load(pool.AddLocals); err != nil { 263 log.Warn("Failed to load transaction journal", "err", err) 264 } 265 if err := pool.journal.rotate(pool.local()); err != nil { 266 log.Warn("Failed to rotate transaction journal", "err", err) 267 } 268 } 269 //从区块链订阅事件 270 pool.chainHeadSub = pool.chain.SubscribeChainHeadEvent(pool.chainHeadCh) 271 272 //启动事件循环并返回 273 pool.wg.Add(1) 274 go pool.loop() 275 276 return pool 277 } 278 279 //循环是事务池的主事件循环,等待并响应 280 //外部区块链事件以及各种报告和交易 281 //驱逐事件。 282 func (pool *TxPool) loop() { 283 defer pool.wg.Done() 284 285 //启动统计报告和事务逐出标记 286 var prevPending, prevQueued, prevStales int 287 288 report := time.NewTicker(statsReportInterval) 289 defer report.Stop() 290 291 evict := time.NewTicker(evictionInterval) 292 defer evict.Stop() 293 294 journal := time.NewTicker(pool.config.Rejournal) 295 defer journal.Stop() 296 297 //跟踪事务重新排序的前一个标题 298 head := pool.chain.CurrentBlock() 299 300 //持续等待并对各种事件作出反应 301 for { 302 select { 303 //处理ChainHeadEvent 304 case ev := <-pool.chainHeadCh: 305 if ev.Block != nil { 306 pool.mu.Lock() 307 if pool.chainconfig.IsHomestead(ev.Block.Number()) { 308 pool.homestead = true 309 } 310 pool.reset(head.Header(), ev.Block.Header()) 311 head = ev.Block 312 313 pool.mu.Unlock() 314 } 315 //由于系统停止而取消订阅 316 case <-pool.chainHeadSub.Err(): 317 return 318 319 //处理统计报告标记 320 case <-report.C: 321 pool.mu.RLock() 322 pending, queued := pool.stats() 323 stales := pool.priced.stales 324 pool.mu.RUnlock() 325 326 if pending != prevPending || queued != prevQueued || stales != prevStales { 327 log.Debug("Transaction pool status report", "executable", pending, "queued", queued, "stales", stales) 328 prevPending, prevQueued, prevStales = pending, queued, stales 329 } 330 331 //处理非活动帐户事务收回 332 case <-evict.C: 333 pool.mu.Lock() 334 for addr := range pool.queue { 335 //从逐出机制跳过本地事务 336 if pool.locals.contains(addr) { 337 continue 338 } 339 //任何年龄足够大的非本地人都应该被除名。 340 if time.Since(pool.beats[addr]) > pool.config.Lifetime { 341 for _, tx := range pool.queue[addr].Flatten() { 342 pool.removeTx(tx.Hash(), true) 343 } 344 } 345 } 346 pool.mu.Unlock() 347 348 //处理本地事务日记帐轮换 349 case <-journal.C: 350 if pool.journal != nil { 351 pool.mu.Lock() 352 if err := pool.journal.rotate(pool.local()); err != nil { 353 log.Warn("Failed to rotate local tx journal", "err", err) 354 } 355 pool.mu.Unlock() 356 } 357 } 358 } 359 } 360 361 //LockedReset是一个包装重置,允许在线程安全中调用它。 362 //态度。此方法仅在检测仪中使用! 363 func (pool *TxPool) lockedReset(oldHead, newHead *types.Header) { 364 pool.mu.Lock() 365 defer pool.mu.Unlock() 366 367 pool.reset(oldHead, newHead) 368 } 369 370 //重置检索区块链的当前状态并确保内容 371 //的事务池对于链状态有效。 372 func (pool *TxPool) reset(oldHead, newHead *types.Header) { 373 //如果要重新定位旧状态,请重新拒绝所有已删除的事务 374 var reinject types.Transactions 375 376 if oldHead != nil && oldHead.Hash() != newHead.ParentHash { 377 //如果REORG太深,请避免这样做(将在快速同步期间发生) 378 oldNum := oldHead.Number.Uint64() 379 newNum := newHead.Number.Uint64() 380 381 if depth := uint64(math.Abs(float64(oldNum) - float64(newNum))); depth > 64 { 382 log.Debug("Skipping deep transaction reorg", "depth", depth) 383 } else { 384 //REORG看起来很浅,足以将所有事务拉入内存 385 var discarded, included types.Transactions 386 387 var ( 388 rem = pool.chain.GetBlock(oldHead.Hash(), oldHead.Number.Uint64()) 389 add = pool.chain.GetBlock(newHead.Hash(), newHead.Number.Uint64()) 390 ) 391 for rem.NumberU64() > add.NumberU64() { 392 discarded = append(discarded, rem.Transactions()...) 393 if rem = pool.chain.GetBlock(rem.ParentHash(), rem.NumberU64()-1); rem == nil { 394 log.Error("Unrooted old chain seen by tx pool", "block", oldHead.Number, "hash", oldHead.Hash()) 395 return 396 } 397 } 398 for add.NumberU64() > rem.NumberU64() { 399 included = append(included, add.Transactions()...) 400 if add = pool.chain.GetBlock(add.ParentHash(), add.NumberU64()-1); add == nil { 401 log.Error("Unrooted new chain seen by tx pool", "block", newHead.Number, "hash", newHead.Hash()) 402 return 403 } 404 } 405 for rem.Hash() != add.Hash() { 406 discarded = append(discarded, rem.Transactions()...) 407 if rem = pool.chain.GetBlock(rem.ParentHash(), rem.NumberU64()-1); rem == nil { 408 log.Error("Unrooted old chain seen by tx pool", "block", oldHead.Number, "hash", oldHead.Hash()) 409 return 410 } 411 included = append(included, add.Transactions()...) 412 if add = pool.chain.GetBlock(add.ParentHash(), add.NumberU64()-1); add == nil { 413 log.Error("Unrooted new chain seen by tx pool", "block", newHead.Number, "hash", newHead.Hash()) 414 return 415 } 416 } 417 reinject = types.TxDifference(discarded, included) 418 } 419 } 420 //将内部状态初始化为当前头部 421 if newHead == nil { 422 newHead = pool.chain.CurrentBlock().Header() //测试过程中的特殊情况 423 } 424 statedb, err := pool.chain.StateAt(newHead.Root) 425 if err != nil { 426 log.Error("Failed to reset txpool state", "err", err) 427 return 428 } 429 pool.currentState = statedb 430 pool.pendingState = state.ManageState(statedb) 431 pool.currentMaxGas = newHead.GasLimit 432 433 //插入由于重新排序而丢弃的任何事务 434 log.Debug("Reinjecting stale transactions", "count", len(reinject)) 435 senderCacher.recover(pool.signer, reinject) 436 pool.addTxsLocked(reinject, false) 437 438 //验证挂起事务池,这将删除 439 //包含在块中的任何交易或 440 //已因另一个交易(例如 441 //更高的天然气价格) 442 pool.demoteUnexecutables() 443 444 //将所有帐户更新为最新的已知挂起的当前帐户 445 for addr, list := range pool.pending { 446 txs := list.Flatten() //很重,但会被缓存,矿工无论如何都需要它。 447 pool.pendingState.SetNonce(addr, txs[len(txs)-1].Nonce()+1) 448 } 449 //检查队列并尽可能将事务转移到挂起的 450 //或者去掉那些已经失效的 451 pool.promoteExecutables(nil) 452 } 453 454 //stop终止事务池。 455 func (pool *TxPool) Stop() { 456 //取消订阅从txpool注册的所有订阅 457 pool.scope.Close() 458 459 //取消订阅从区块链注册的订阅 460 pool.chainHeadSub.Unsubscribe() 461 pool.wg.Wait() 462 463 if pool.journal != nil { 464 pool.journal.close() 465 } 466 log.Info("Transaction pool stopped") 467 } 468 469 //subscripeWtxsEvent注册newtxSevent和的订阅 470 //开始向给定通道发送事件。 471 func (pool *TxPool) SubscribeNewTxsEvent(ch chan<- NewTxsEvent) event.Subscription { 472 return pool.scope.Track(pool.txFeed.Subscribe(ch)) 473 } 474 475 //Gasprice返回交易池强制执行的当前天然气价格。 476 func (pool *TxPool) GasPrice() *big.Int { 477 pool.mu.RLock() 478 defer pool.mu.RUnlock() 479 480 return new(big.Int).Set(pool.gasPrice) 481 } 482 483 //setgasprice更新交易池要求的 484 //新事务,并将所有事务降低到此阈值以下。 485 func (pool *TxPool) SetGasPrice(price *big.Int) { 486 pool.mu.Lock() 487 defer pool.mu.Unlock() 488 489 pool.gasPrice = price 490 for _, tx := range pool.priced.Cap(price, pool.locals) { 491 pool.removeTx(tx.Hash(), false) 492 } 493 log.Info("Transaction pool price threshold updated", "price", price) 494 } 495 496 //状态返回事务池的虚拟托管状态。 497 func (pool *TxPool) State() *state.ManagedState { 498 pool.mu.RLock() 499 defer pool.mu.RUnlock() 500 501 return pool.pendingState 502 } 503 504 //stats检索当前池的统计信息,即挂起的数目和 505 //排队(不可执行)的事务数。 506 func (pool *TxPool) Stats() (int, int) { 507 pool.mu.RLock() 508 defer pool.mu.RUnlock() 509 510 return pool.stats() 511 } 512 513 //stats检索当前池的统计信息,即挂起的数目和 514 //排队(不可执行)的事务数。 515 func (pool *TxPool) stats() (int, int) { 516 pending := 0 517 for _, list := range pool.pending { 518 pending += list.Len() 519 } 520 queued := 0 521 for _, list := range pool.queue { 522 queued += list.Len() 523 } 524 return pending, queued 525 } 526 527 //Content检索事务池的数据内容,并返回 528 //挂起的和排队的事务,按帐户分组并按nonce排序。 529 func (pool *TxPool) Content() (map[common.Address]types.Transactions, map[common.Address]types.Transactions) { 530 pool.mu.Lock() 531 defer pool.mu.Unlock() 532 533 pending := make(map[common.Address]types.Transactions) 534 for addr, list := range pool.pending { 535 pending[addr] = list.Flatten() 536 } 537 queued := make(map[common.Address]types.Transactions) 538 for addr, list := range pool.queue { 539 queued[addr] = list.Flatten() 540 } 541 return pending, queued 542 } 543 544 //挂起检索所有当前可处理的事务,按来源分组 545 //帐户并按nonce排序。返回的事务集是一个副本,可以 546 //通过调用代码自由修改。 547 func (pool *TxPool) Pending() (map[common.Address]types.Transactions, error) { 548 pool.mu.Lock() 549 defer pool.mu.Unlock() 550 551 pending := make(map[common.Address]types.Transactions) 552 for addr, list := range pool.pending { 553 pending[addr] = list.Flatten() 554 } 555 return pending, nil 556 } 557 558 //局部变量检索池当前认为是本地的帐户。 559 func (pool *TxPool) Locals() []common.Address { 560 pool.mu.Lock() 561 defer pool.mu.Unlock() 562 563 return pool.locals.flatten() 564 } 565 566 //本地检索所有当前已知的本地事务,按来源分组 567 //帐户并按nonce排序。返回的事务集是一个副本,可以 568 //通过调用代码自由修改。 569 func (pool *TxPool) local() map[common.Address]types.Transactions { 570 txs := make(map[common.Address]types.Transactions) 571 for addr := range pool.locals.accounts { 572 if pending := pool.pending[addr]; pending != nil { 573 txs[addr] = append(txs[addr], pending.Flatten()...) 574 } 575 if queued := pool.queue[addr]; queued != nil { 576 txs[addr] = append(txs[addr], queued.Flatten()...) 577 } 578 } 579 return txs 580 } 581 582 //validatetx根据共识检查交易是否有效 583 //规则并遵守本地节点的一些启发式限制(价格和大小)。 584 func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error { 585 //启发式限制,拒绝超过32KB的事务以防止DoS攻击 586 if tx.Size() > 32*1024 { 587 return ErrOversizedData 588 } 589 //交易记录不能为负数。使用RLP解码可能永远不会发生这种情况。 590 //但如果使用RPC创建事务,则可能发生事务。 591 if tx.Value().Sign() < 0 { 592 return ErrNegativeValue 593 } 594 //确保交易不超过当前区块限制天然气。 595 if pool.currentMaxGas < tx.Gas() { 596 return ErrGasLimit 597 } 598 //确保事务签名正确 599 from, err := types.Sender(pool.signer, tx) 600 if err != nil { 601 return ErrInvalidSender 602 } 603 //以我们自己接受的最低天然气价格取消非本地交易 604 local = local || pool.locals.contains(from) //即使事务从网络到达,帐户也可以是本地的 605 if !local && pool.gasPrice.Cmp(tx.GasPrice()) > 0 { 606 return ErrUnderpriced 607 } 608 //确保事务遵循非紧急排序 609 if pool.currentState.GetNonce(from) > tx.Nonce() { 610 return ErrNonceTooLow 611 } 612 //交易人应该有足够的资金来支付费用。 613 //成本==V+gp*gl 614 if pool.currentState.GetBalance(from).Cmp(tx.Cost()) < 0 { 615 return ErrInsufficientFunds 616 } 617 intrGas, err := IntrinsicGas(tx.Data(), tx.To() == nil, pool.homestead) 618 if err != nil { 619 return err 620 } 621 if tx.Gas() < intrGas { 622 return ErrIntrinsicGas 623 } 624 return nil 625 } 626 627 //添加验证事务并将其插入到的不可执行队列中 628 //稍后等待提升和执行。如果交易是 629 //一个已挂起或排队的,它将覆盖上一个并返回此 630 //所以外部代码不会毫无用处地调用promote。 631 // 632 //如果新添加的事务标记为本地,则其发送帐户将 633 //白名单,防止任何关联交易退出 634 //由于定价限制而形成的池。 635 func (pool *TxPool) add(tx *types.Transaction, local bool) (bool, error) { 636 //如果事务已经知道,则丢弃它 637 hash := tx.Hash() 638 if pool.all.Get(hash) != nil { 639 log.Trace("Discarding already known transaction", "hash", hash) 640 return false, fmt.Errorf("known transaction: %x", hash) 641 } 642 //如果事务未能通过基本验证,则放弃它 643 if err := pool.validateTx(tx, local); err != nil { 644 log.Trace("Discarding invalid transaction", "hash", hash, "err", err) 645 invalidTxCounter.Inc(1) 646 return false, err 647 } 648 //如果事务池已满,则放弃定价过低的事务 649 if uint64(pool.all.Count()) >= pool.config.GlobalSlots+pool.config.GlobalQueue { 650 //如果新交易定价过低,不要接受 651 if !local && pool.priced.Underpriced(tx, pool.locals) { 652 log.Trace("Discarding underpriced transaction", "hash", hash, "price", tx.GasPrice()) 653 underpricedTxCounter.Inc(1) 654 return false, ErrUnderpriced 655 } 656 //新的交易比我们糟糕的交易好,给它腾出空间。 657 drop := pool.priced.Discard(pool.all.Count()-int(pool.config.GlobalSlots+pool.config.GlobalQueue-1), pool.locals) 658 for _, tx := range drop { 659 log.Trace("Discarding freshly underpriced transaction", "hash", tx.Hash(), "price", tx.GasPrice()) 660 underpricedTxCounter.Inc(1) 661 pool.removeTx(tx.Hash(), false) 662 } 663 } 664 //如果事务正在替换已挂起的事务,请直接执行 665 from, _ := types.Sender(pool.signer, tx) //已验证 666 if list := pool.pending[from]; list != nil && list.Overlaps(tx) { 667 //一旦已经挂起,检查是否满足所需的价格上涨 668 inserted, old := list.Add(tx, pool.config.PriceBump) 669 if !inserted { 670 pendingDiscardCounter.Inc(1) 671 return false, ErrReplaceUnderpriced 672 } 673 //新交易更好,替换旧交易 674 if old != nil { 675 pool.all.Remove(old.Hash()) 676 pool.priced.Removed() 677 pendingReplaceCounter.Inc(1) 678 } 679 pool.all.Add(tx) 680 pool.priced.Put(tx) 681 pool.journalTx(from, tx) 682 683 log.Trace("Pooled new executable transaction", "hash", hash, "from", from, "to", tx.To()) 684 685 //我们直接注入了一个替换事务,通知子系统 686 go pool.txFeed.Send(NewTxsEvent{types.Transactions{tx}}) 687 688 return old != nil, nil 689 } 690 //新事务没有替换挂起的事务,请推入队列 691 replace, err := pool.enqueueTx(hash, tx) 692 if err != nil { 693 return false, err 694 } 695 //标记本地地址和日记帐本地交易记录 696 if local { 697 if !pool.locals.contains(from) { 698 log.Info("Setting new local account", "address", from) 699 pool.locals.add(from) 700 } 701 } 702 pool.journalTx(from, tx) 703 704 log.Trace("Pooled new future transaction", "hash", hash, "from", from, "to", tx.To()) 705 return replace, nil 706 } 707 708 //enqueuetx将新事务插入到不可执行的事务队列中。 709 // 710 //注意,此方法假定池锁被保持! 711 func (pool *TxPool) enqueueTx(hash common.Hash, tx *types.Transaction) (bool, error) { 712 //尝试将事务插入将来的队列 713 from, _ := types.Sender(pool.signer, tx) //已验证 714 if pool.queue[from] == nil { 715 pool.queue[from] = newTxList(false) 716 } 717 inserted, old := pool.queue[from].Add(tx, pool.config.PriceBump) 718 if !inserted { 719 //旧的交易更好,放弃这个 720 queuedDiscardCounter.Inc(1) 721 return false, ErrReplaceUnderpriced 722 } 723 //放弃任何以前的交易并标记此交易 724 if old != nil { 725 pool.all.Remove(old.Hash()) 726 pool.priced.Removed() 727 queuedReplaceCounter.Inc(1) 728 } 729 if pool.all.Get(hash) == nil { 730 pool.all.Add(tx) 731 pool.priced.Put(tx) 732 } 733 return old != nil, nil 734 } 735 736 //JournalTx将指定的事务添加到本地磁盘日志(如果是) 737 //视为从本地帐户发送。 738 func (pool *TxPool) journalTx(from common.Address, tx *types.Transaction) { 739 //只有启用了日记帐且事务是本地的 740 if pool.journal == nil || !pool.locals.contains(from) { 741 return 742 } 743 if err := pool.journal.insert(tx); err != nil { 744 log.Warn("Failed to journal local transaction", "err", err) 745 } 746 } 747 748 //promotetx将事务添加到挂起(可处理)的事务列表中 749 //并返回它是插入的还是旧的更好。 750 // 751 //注意,此方法假定池锁被保持! 752 func (pool *TxPool) promoteTx(addr common.Address, hash common.Hash, tx *types.Transaction) bool { 753 //尝试将事务插入挂起队列 754 if pool.pending[addr] == nil { 755 pool.pending[addr] = newTxList(true) 756 } 757 list := pool.pending[addr] 758 759 inserted, old := list.Add(tx, pool.config.PriceBump) 760 if !inserted { 761 //旧的交易更好,放弃这个 762 pool.all.Remove(hash) 763 pool.priced.Removed() 764 765 pendingDiscardCounter.Inc(1) 766 return false 767 } 768 //否则放弃任何以前的交易并标记此 769 if old != nil { 770 pool.all.Remove(old.Hash()) 771 pool.priced.Removed() 772 773 pendingReplaceCounter.Inc(1) 774 } 775 //故障保护以绕过直接挂起的插入(测试) 776 if pool.all.Get(hash) == nil { 777 pool.all.Add(tx) 778 pool.priced.Put(tx) 779 } 780 //设置潜在的新挂起nonce并通知新tx的任何子系统 781 pool.beats[addr] = time.Now() 782 pool.pendingState.SetNonce(addr, tx.Nonce()+1) 783 784 return true 785 } 786 787 //addlocal将单个事务排入池中(如果该事务有效),标记 788 //同时将发送方作为本地发送方,确保它绕过本地发送方 789 //定价限制。 790 func (pool *TxPool) AddLocal(tx *types.Transaction) error { 791 return pool.addTx(tx, !pool.config.NoLocals) 792 } 793 794 //如果单个事务有效,则addremote将其排入池中。如果 795 //发送方不属于本地跟踪的发送方,完全定价约束将 796 //申请。 797 func (pool *TxPool) AddRemote(tx *types.Transaction) error { 798 return pool.addTx(tx, false) 799 } 800 801 //addlocals将一批事务排队放入池中,如果它们有效, 802 //同时将发送者标记为本地发送者,确保他们四处走动 803 //本地定价限制。 804 func (pool *TxPool) AddLocals(txs []*types.Transaction) []error { 805 return pool.addTxs(txs, !pool.config.NoLocals) 806 } 807 808 //如果一批事务有效,addremotes会将其排队放入池中。 809 //如果发送方不在本地跟踪的发送方中,则完全定价约束 810 //将适用。 811 func (pool *TxPool) AddRemotes(txs []*types.Transaction) []error { 812 return pool.addTxs(txs, false) 813 } 814 815 //addtx将单个事务排队放入池中(如果该事务有效)。 816 func (pool *TxPool) addTx(tx *types.Transaction, local bool) error { 817 pool.mu.Lock() 818 defer pool.mu.Unlock() 819 820 //尝试插入事务并更新任何状态 821 replace, err := pool.add(tx, local) 822 if err != nil { 823 return err 824 } 825 //如果我们添加了一个新事务,运行提升检查并返回 826 if !replace { 827 from, _ := types.Sender(pool.signer, tx) //已验证 828 pool.promoteExecutables([]common.Address{from}) 829 } 830 return nil 831 } 832 833 //如果一批事务有效,addtx将尝试对其进行排队。 834 func (pool *TxPool) addTxs(txs []*types.Transaction, local bool) []error { 835 pool.mu.Lock() 836 defer pool.mu.Unlock() 837 838 return pool.addTxsLocked(txs, local) 839 } 840 841 //addtxtslocked尝试对一批事务进行排队,如果它们有效, 842 //同时假定事务池锁已被持有。 843 func (pool *TxPool) addTxsLocked(txs []*types.Transaction, local bool) []error { 844 //添加交易批次,跟踪接受的交易 845 dirty := make(map[common.Address]struct{}) 846 errs := make([]error, len(txs)) 847 848 for i, tx := range txs { 849 var replace bool 850 if replace, errs[i] = pool.add(tx, local); errs[i] == nil && !replace { 851 from, _ := types.Sender(pool.signer, tx) //已验证 852 dirty[from] = struct{}{} 853 } 854 } 855 //仅当实际添加了某些内容时才重新处理内部状态 856 if len(dirty) > 0 { 857 addrs := make([]common.Address, 0, len(dirty)) 858 for addr := range dirty { 859 addrs = append(addrs, addr) 860 } 861 pool.promoteExecutables(addrs) 862 } 863 return errs 864 } 865 866 //status返回一批事务的状态(未知/挂起/排队) 867 //通过散列标识。 868 func (pool *TxPool) Status(hashes []common.Hash) []TxStatus { 869 pool.mu.RLock() 870 defer pool.mu.RUnlock() 871 872 status := make([]TxStatus, len(hashes)) 873 for i, hash := range hashes { 874 if tx := pool.all.Get(hash); tx != nil { 875 from, _ := types.Sender(pool.signer, tx) //已验证 876 if pool.pending[from] != nil && pool.pending[from].txs.items[tx.Nonce()] != nil { 877 status[i] = TxStatusPending 878 } else { 879 status[i] = TxStatusQueued 880 } 881 } 882 } 883 return status 884 } 885 886 //get返回包含在池中的事务 887 //否则为零。 888 func (pool *TxPool) Get(hash common.Hash) *types.Transaction { 889 return pool.all.Get(hash) 890 } 891 892 //removetx从队列中删除单个事务,移动所有后续事务 893 //事务返回到未来队列。 894 func (pool *TxPool) removeTx(hash common.Hash, outofbound bool) { 895 //获取我们要删除的事务 896 tx := pool.all.Get(hash) 897 if tx == nil { 898 return 899 } 900 addr, _ := types.Sender(pool.signer, tx) //已在插入过程中验证 901 902 //将其从已知事务列表中删除 903 pool.all.Remove(hash) 904 if outofbound { 905 pool.priced.Removed() 906 } 907 //从挂起列表中删除该事务并立即重置帐户 908 if pending := pool.pending[addr]; pending != nil { 909 if removed, invalids := pending.Remove(tx); removed { 910 //如果没有剩余的挂起事务,请删除该列表 911 if pending.Empty() { 912 delete(pool.pending, addr) 913 delete(pool.beats, addr) 914 } 915 //推迟任何失效的交易 916 for _, tx := range invalids { 917 pool.enqueueTx(tx.Hash(), tx) 918 } 919 //如果需要,立即更新帐户 920 if nonce := tx.Nonce(); pool.pendingState.GetNonce(addr) > nonce { 921 pool.pendingState.SetNonce(addr, nonce) 922 } 923 return 924 } 925 } 926 //事务在将来的队列中 927 if future := pool.queue[addr]; future != nil { 928 future.Remove(tx) 929 if future.Empty() { 930 delete(pool.queue, addr) 931 } 932 } 933 } 934 935 //PromoteeExecutables将可从 936 //对一组挂起事务的未来队列。在此过程中,所有 937 //已删除失效的事务(低nonce、低余额)。 938 func (pool *TxPool) promoteExecutables(accounts []common.Address) { 939 //跟踪已提升的事务以立即广播它们 940 var promoted []*types.Transaction 941 942 //收集所有可能需要更新的帐户 943 if accounts == nil { 944 accounts = make([]common.Address, 0, len(pool.queue)) 945 for addr := range pool.queue { 946 accounts = append(accounts, addr) 947 } 948 } 949 //遍历所有帐户并升级任何可执行事务 950 for _, addr := range accounts { 951 list := pool.queue[addr] 952 if list == nil { 953 continue //以防有人用不存在的帐户打电话 954 } 955 //删除所有被认为太旧的事务(低nonce) 956 for _, tx := range list.Forward(pool.currentState.GetNonce(addr)) { 957 hash := tx.Hash() 958 log.Trace("Removed old queued transaction", "hash", hash) 959 pool.all.Remove(hash) 960 pool.priced.Removed() 961 } 962 //放弃所有成本过高的交易(低余额或无天然气) 963 drops, _ := list.Filter(pool.currentState.GetBalance(addr), pool.currentMaxGas) 964 for _, tx := range drops { 965 hash := tx.Hash() 966 log.Trace("Removed unpayable queued transaction", "hash", hash) 967 pool.all.Remove(hash) 968 pool.priced.Removed() 969 queuedNofundsCounter.Inc(1) 970 } 971 //收集所有可执行事务并升级它们 972 for _, tx := range list.Ready(pool.pendingState.GetNonce(addr)) { 973 hash := tx.Hash() 974 if pool.promoteTx(addr, hash, tx) { 975 log.Trace("Promoting queued transaction", "hash", hash) 976 promoted = append(promoted, tx) 977 } 978 } 979 //删除超过允许限制的所有交易记录 980 if !pool.locals.contains(addr) { 981 for _, tx := range list.Cap(int(pool.config.AccountQueue)) { 982 hash := tx.Hash() 983 pool.all.Remove(hash) 984 pool.priced.Removed() 985 queuedRateLimitCounter.Inc(1) 986 log.Trace("Removed cap-exceeding queued transaction", "hash", hash) 987 } 988 } 989 //如果整个队列条目变为空,则将其删除。 990 if list.Empty() { 991 delete(pool.queue, addr) 992 } 993 } 994 //为新升级的事务通知子系统。 995 if len(promoted) > 0 { 996 go pool.txFeed.Send(NewTxsEvent{promoted}) 997 } 998 //如果待定限额溢出,开始均衡限额 999 pending := uint64(0) 1000 for _, list := range pool.pending { 1001 pending += uint64(list.Len()) 1002 } 1003 if pending > pool.config.GlobalSlots { 1004 pendingBeforeCap := pending 1005 //首先收集一个垃圾邮件命令来惩罚大型交易对手 1006 spammers := prque.New(nil) 1007 for addr, list := range pool.pending { 1008 //仅从高收入者逐出交易 1009 if !pool.locals.contains(addr) && uint64(list.Len()) > pool.config.AccountSlots { 1010 spammers.Push(addr, int64(list.Len())) 1011 } 1012 } 1013 //逐步取消罪犯的交易 1014 offenders := []common.Address{} 1015 for pending > pool.config.GlobalSlots && !spammers.Empty() { 1016 //如果不是本地地址,则检索下一个罪犯 1017 offender, _ := spammers.Pop() 1018 offenders = append(offenders, offender.(common.Address)) 1019 1020 //平衡平衡直到所有相同或低于阈值 1021 if len(offenders) > 1 { 1022 //计算当前所有罪犯的均衡阈值 1023 threshold := pool.pending[offender.(common.Address)].Len() 1024 1025 //反复减少所有违规者,直至达到限额或阈值以下。 1026 for pending > pool.config.GlobalSlots && pool.pending[offenders[len(offenders)-2]].Len() > threshold { 1027 for i := 0; i < len(offenders)-1; i++ { 1028 list := pool.pending[offenders[i]] 1029 for _, tx := range list.Cap(list.Len() - 1) { 1030 //也从全局池中删除事务 1031 hash := tx.Hash() 1032 pool.all.Remove(hash) 1033 pool.priced.Removed() 1034 1035 //将当前帐户更新为删除的交易记录 1036 if nonce := tx.Nonce(); pool.pendingState.GetNonce(offenders[i]) > nonce { 1037 pool.pendingState.SetNonce(offenders[i], nonce) 1038 } 1039 log.Trace("Removed fairness-exceeding pending transaction", "hash", hash) 1040 } 1041 pending-- 1042 } 1043 } 1044 } 1045 } 1046 //如果仍高于临界值,则降低至极限或最小允许值 1047 if pending > pool.config.GlobalSlots && len(offenders) > 0 { 1048 for pending > pool.config.GlobalSlots && uint64(pool.pending[offenders[len(offenders)-1]].Len()) > pool.config.AccountSlots { 1049 for _, addr := range offenders { 1050 list := pool.pending[addr] 1051 for _, tx := range list.Cap(list.Len() - 1) { 1052 //也从全局池中删除事务 1053 hash := tx.Hash() 1054 pool.all.Remove(hash) 1055 pool.priced.Removed() 1056 1057 //将当前帐户更新为删除的交易记录 1058 if nonce := tx.Nonce(); pool.pendingState.GetNonce(addr) > nonce { 1059 pool.pendingState.SetNonce(addr, nonce) 1060 } 1061 log.Trace("Removed fairness-exceeding pending transaction", "hash", hash) 1062 } 1063 pending-- 1064 } 1065 } 1066 } 1067 pendingRateLimitCounter.Inc(int64(pendingBeforeCap - pending)) 1068 } 1069 //如果排队的事务超过了硬限制,请删除最旧的事务。 1070 queued := uint64(0) 1071 for _, list := range pool.queue { 1072 queued += uint64(list.Len()) 1073 } 1074 if queued > pool.config.GlobalQueue { 1075 //按心跳对所有具有排队事务的帐户排序 1076 addresses := make(addressesByHeartbeat, 0, len(pool.queue)) 1077 for addr := range pool.queue { 1078 if !pool.locals.contains(addr) { //不要删除本地变量 1079 addresses = append(addresses, addressByHeartbeat{addr, pool.beats[addr]}) 1080 } 1081 } 1082 sort.Sort(addresses) 1083 1084 //删除事务,直到总数低于限制或只保留局部变量 1085 for drop := queued - pool.config.GlobalQueue; drop > 0 && len(addresses) > 0; { 1086 addr := addresses[len(addresses)-1] 1087 list := pool.queue[addr.address] 1088 1089 addresses = addresses[:len(addresses)-1] 1090 1091 //如果小于溢出,则删除所有事务 1092 if size := uint64(list.Len()); size <= drop { 1093 for _, tx := range list.Flatten() { 1094 pool.removeTx(tx.Hash(), true) 1095 } 1096 drop -= size 1097 queuedRateLimitCounter.Inc(int64(size)) 1098 continue 1099 } 1100 //否则只删除最后几个事务 1101 txs := list.Flatten() 1102 for i := len(txs) - 1; i >= 0 && drop > 0; i-- { 1103 pool.removeTx(txs[i].Hash(), true) 1104 drop-- 1105 queuedRateLimitCounter.Inc(1) 1106 } 1107 } 1108 } 1109 } 1110 1111 //DemoteNextExecutables从池中删除无效和已处理的事务 1112 //可执行/挂起队列以及任何无法执行的后续事务 1113 //将移回将来的队列。 1114 func (pool *TxPool) demoteUnexecutables() { 1115 //迭代所有帐户并降级任何不可执行的事务 1116 for addr, list := range pool.pending { 1117 nonce := pool.currentState.GetNonce(addr) 1118 1119 //删除所有被认为太旧的事务(低nonce) 1120 for _, tx := range list.Forward(nonce) { 1121 hash := tx.Hash() 1122 log.Trace("Removed old pending transaction", "hash", hash) 1123 pool.all.Remove(hash) 1124 pool.priced.Removed() 1125 } 1126 //删除所有成本过高的事务(余额不足或没有汽油),并将任何无效的事务排队等待稍后处理。 1127 drops, invalids := list.Filter(pool.currentState.GetBalance(addr), pool.currentMaxGas) 1128 for _, tx := range drops { 1129 hash := tx.Hash() 1130 log.Trace("Removed unpayable pending transaction", "hash", hash) 1131 pool.all.Remove(hash) 1132 pool.priced.Removed() 1133 pendingNofundsCounter.Inc(1) 1134 } 1135 for _, tx := range invalids { 1136 hash := tx.Hash() 1137 log.Trace("Demoting pending transaction", "hash", hash) 1138 pool.enqueueTx(hash, tx) 1139 } 1140 //如果前面有空白,警告(不应该发生)并推迟所有交易 1141 if list.Len() > 0 && list.txs.Get(nonce) == nil { 1142 for _, tx := range list.Cap(0) { 1143 hash := tx.Hash() 1144 log.Error("Demoting invalidated transaction", "hash", hash) 1145 pool.enqueueTx(hash, tx) 1146 } 1147 } 1148 //如果整个队列条目变为空,则将其删除。 1149 if list.Empty() { 1150 delete(pool.pending, addr) 1151 delete(pool.beats, addr) 1152 } 1153 } 1154 } 1155 1156 //AddressByHeartbeat是用其最后一个活动时间戳标记的帐户地址。 1157 type addressByHeartbeat struct { 1158 address common.Address 1159 heartbeat time.Time 1160 } 1161 1162 type addressesByHeartbeat []addressByHeartbeat 1163 1164 func (a addressesByHeartbeat) Len() int { return len(a) } 1165 func (a addressesByHeartbeat) Less(i, j int) bool { return a[i].heartbeat.Before(a[j].heartbeat) } 1166 func (a addressesByHeartbeat) Swap(i, j int) { a[i], a[j] = a[j], a[i] } 1167 1168 //accountset只是检查是否存在的一组地址,以及一个签名者 1169 //能够从交易中获得地址。 1170 type accountSet struct { 1171 accounts map[common.Address]struct{} 1172 signer types.Signer 1173 cache *[]common.Address 1174 } 1175 1176 //newaccountset创建一个新地址集,其中包含发送者的关联签名者 1177 //导子。 1178 func newAccountSet(signer types.Signer) *accountSet { 1179 return &accountSet{ 1180 accounts: make(map[common.Address]struct{}), 1181 signer: signer, 1182 } 1183 } 1184 1185 //包含检查给定地址是否包含在集合中。 1186 func (as *accountSet) contains(addr common.Address) bool { 1187 _, exist := as.accounts[addr] 1188 return exist 1189 } 1190 1191 //containstx检查给定Tx的发送方是否在集合内。如果发送者 1192 //无法派生,此方法返回false。 1193 func (as *accountSet) containsTx(tx *types.Transaction) bool { 1194 if addr, err := types.Sender(as.signer, tx); err == nil { 1195 return as.contains(addr) 1196 } 1197 return false 1198 } 1199 1200 //添加在要跟踪的集合中插入新地址。 1201 func (as *accountSet) add(addr common.Address) { 1202 as.accounts[addr] = struct{}{} 1203 as.cache = nil 1204 } 1205 1206 //flatten返回此集合中的地址列表,并将其缓存以备以后使用 1207 //重新使用。The returned slice should not be changed! 1208 func (as *accountSet) flatten() []common.Address { 1209 if as.cache == nil { 1210 accounts := make([]common.Address, 0, len(as.accounts)) 1211 for account := range as.accounts { 1212 accounts = append(accounts, account) 1213 } 1214 as.cache = &accounts 1215 } 1216 return *as.cache 1217 } 1218 1219 //TXLoopUp在TXPLE内部用于跟踪事务,同时允许查找 1220 //互斥争用。 1221 // 1222 //注意,尽管此类型受到适当的保护,以防并发访问,但它 1223 //是**不是**类型,应该在 1224 //事务池,因为它的内部状态与池紧密耦合 1225 //内部机制。该类型的唯一目的是允许出界 1226 //偷看txpool中的池。无需获取范围广泛的 1227 //txpool.mutex。 1228 type txLookup struct { 1229 all map[common.Hash]*types.Transaction 1230 lock sync.RWMutex 1231 } 1232 1233 //new txlookup返回新的txlookup结构。 1234 func newTxLookup() *txLookup { 1235 return &txLookup{ 1236 all: make(map[common.Hash]*types.Transaction), 1237 } 1238 } 1239 1240 //范围对地图中的每个键和值调用f。 1241 func (t *txLookup) Range(f func(hash common.Hash, tx *types.Transaction) bool) { 1242 t.lock.RLock() 1243 defer t.lock.RUnlock() 1244 1245 for key, value := range t.all { 1246 if !f(key, value) { 1247 break 1248 } 1249 } 1250 } 1251 1252 //get返回查找中存在的事务,如果未找到则返回nil。 1253 func (t *txLookup) Get(hash common.Hash) *types.Transaction { 1254 t.lock.RLock() 1255 defer t.lock.RUnlock() 1256 1257 return t.all[hash] 1258 } 1259 1260 //count返回查找中的当前项目数。 1261 func (t *txLookup) Count() int { 1262 t.lock.RLock() 1263 defer t.lock.RUnlock() 1264 1265 return len(t.all) 1266 } 1267 1268 //添加将事务添加到查找中。 1269 func (t *txLookup) Add(tx *types.Transaction) { 1270 t.lock.Lock() 1271 defer t.lock.Unlock() 1272 1273 t.all[tx.Hash()] = tx 1274 } 1275 1276 //删除从查找中删除事务。 1277 func (t *txLookup) Remove(hash common.Hash) { 1278 t.lock.Lock() 1279 defer t.lock.Unlock() 1280 1281 delete(t.all, hash) 1282 } 1283