github.com/FusionFoundation/efsn/v4@v4.2.0/core/tx_pool.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 core 18 19 import ( 20 "bytes" 21 "errors" 22 "fmt" 23 "github.com/FusionFoundation/efsn/v4/consensus/misc" 24 "math" 25 "math/big" 26 "sort" 27 "sync" 28 "time" 29 30 "github.com/FusionFoundation/efsn/v4/common" 31 "github.com/FusionFoundation/efsn/v4/common/prque" 32 "github.com/FusionFoundation/efsn/v4/consensus/datong" 33 "github.com/FusionFoundation/efsn/v4/core/state" 34 "github.com/FusionFoundation/efsn/v4/core/types" 35 "github.com/FusionFoundation/efsn/v4/event" 36 "github.com/FusionFoundation/efsn/v4/log" 37 "github.com/FusionFoundation/efsn/v4/metrics" 38 "github.com/FusionFoundation/efsn/v4/params" 39 "github.com/FusionFoundation/efsn/v4/rlp" 40 ) 41 42 const ( 43 // chainHeadChanSize is the size of channel listening to ChainHeadEvent. 44 chainHeadChanSize = 10 45 46 // txSlotSize is used to calculate how many data slots a single transaction 47 // takes up based on its size. The slots are used as DoS protection, ensuring 48 // that validating a new transaction remains a constant operation (in reality 49 // O(maxslots), where max slots are 4 currently). 50 txSlotSize = 32 * 1024 51 52 // txMaxSize is the maximum size a single transaction can have. This field has 53 // non-trivial consequences: larger transactions are significantly harder and 54 // more expensive to propagate; larger transactions also take more resources 55 // to validate whether they fit into the pool or not. 56 txMaxSize = 4 * txSlotSize // 128KB 57 ) 58 59 var ( 60 // ErrAlreadyKnown is returned if the transactions is already contained 61 // within the pool. 62 ErrAlreadyKnown = errors.New("already known") 63 64 // ErrInvalidSender is returned if the transaction contains an invalid signature. 65 ErrInvalidSender = errors.New("invalid sender") 66 67 // ErrUnderpriced is returned if a transaction's gas price is below the minimum 68 // configured for the transaction pool. 69 ErrUnderpriced = errors.New("transaction underpriced") 70 71 // ErrTxPoolOverflow is returned if the transaction pool is full and can't accpet 72 // another remote transaction. 73 ErrTxPoolOverflow = errors.New("txpool is full") 74 75 // ErrReplaceUnderpriced is returned if a transaction is attempted to be replaced 76 // with a different one without the required price bump. 77 ErrReplaceUnderpriced = errors.New("replacement transaction underpriced") 78 79 // ErrGasLimit is returned if a transaction's requested gas limit exceeds the 80 // maximum allowance of the current block. 81 ErrGasLimit = errors.New("exceeds block gas limit") 82 83 // ErrNegativeValue is a sanity error to ensure noone is able to specify a 84 // transaction with a negative value. 85 ErrNegativeValue = errors.New("negative value") 86 87 // ErrOversizedData is returned if the input data of a transaction is greater 88 // than some meaningful limit a user might use. This is not a consensus error 89 // making the transaction invalid, rather a DOS protection. 90 ErrOversizedData = errors.New("oversized data") 91 92 // ErrBlackList is returned if a transaction's from address appear in the blacklist 93 ErrBlackList = errors.New("transaction blacklist") 94 ) 95 96 var ( 97 evictionInterval = time.Minute // Time interval to check for evictable transactions 98 statsReportInterval = 8 * time.Second // Time interval to report transaction pool stats 99 ) 100 101 var ( 102 // Metrics for the pending pool 103 pendingDiscardMeter = metrics.NewRegisteredMeter("txpool/pending/discard", nil) 104 pendingReplaceMeter = metrics.NewRegisteredMeter("txpool/pending/replace", nil) 105 pendingRateLimitMeter = metrics.NewRegisteredMeter("txpool/pending/ratelimit", nil) // Dropped due to rate limiting 106 pendingNofundsMeter = metrics.NewRegisteredMeter("txpool/pending/nofunds", nil) // Dropped due to out-of-funds 107 108 // Metrics for the queued pool 109 queuedDiscardMeter = metrics.NewRegisteredMeter("txpool/queued/discard", nil) 110 queuedReplaceMeter = metrics.NewRegisteredMeter("txpool/queued/replace", nil) 111 queuedRateLimitMeter = metrics.NewRegisteredMeter("txpool/queued/ratelimit", nil) // Dropped due to rate limiting 112 queuedNofundsMeter = metrics.NewRegisteredMeter("txpool/queued/nofunds", nil) // Dropped due to out-of-funds 113 queuedEvictionMeter = metrics.NewRegisteredMeter("txpool/queued/eviction", nil) // Dropped due to lifetime 114 115 // General tx metrics 116 knownTxMeter = metrics.NewRegisteredMeter("txpool/known", nil) 117 validTxMeter = metrics.NewRegisteredMeter("txpool/valid", nil) 118 invalidTxMeter = metrics.NewRegisteredMeter("txpool/invalid", nil) 119 underpricedTxMeter = metrics.NewRegisteredMeter("txpool/underpriced", nil) 120 overflowedTxMeter = metrics.NewRegisteredMeter("txpool/overflowed", nil) 121 122 pendingGauge = metrics.NewRegisteredGauge("txpool/pending", nil) 123 queuedGauge = metrics.NewRegisteredGauge("txpool/queued", nil) 124 localGauge = metrics.NewRegisteredGauge("txpool/local", nil) 125 slotsGauge = metrics.NewRegisteredGauge("txpool/slots", nil) 126 127 reheapTimer = metrics.NewRegisteredTimer("txpool/reheap", nil) 128 ) 129 130 // TxStatus is the current status of a transaction as seen by the pool. 131 type TxStatus uint 132 133 const ( 134 TxStatusUnknown TxStatus = iota 135 TxStatusQueued 136 TxStatusPending 137 TxStatusIncluded 138 ) 139 140 // blockChain provides the state of blockchain and current gas limit to do 141 // some pre checks in tx pool and event subscribers. 142 type blockChain interface { 143 CurrentBlock() *types.Block 144 GetBlock(hash common.Hash, number uint64) *types.Block 145 StateAt(root common.Hash, mixDigest common.Hash) (*state.StateDB, error) 146 147 SubscribeChainHeadEvent(ch chan<- ChainHeadEvent) event.Subscription 148 } 149 150 // TxPoolConfig are the configuration parameters of the transaction pool. 151 type TxPoolConfig struct { 152 Locals []common.Address // Addresses that should be treated by default as local 153 NoLocals bool // Whether local transaction handling should be disabled 154 Journal string // Journal of local transactions to survive node restarts 155 Rejournal time.Duration // Time interval to regenerate the local transaction journal 156 157 PriceLimit uint64 // Minimum gas price to enforce for acceptance into the pool 158 PriceBump uint64 // Minimum price bump percentage to replace an already existing transaction (nonce) 159 160 AccountSlots uint64 // Number of executable transaction slots guaranteed per account 161 GlobalSlots uint64 // Maximum number of executable transaction slots for all accounts 162 AccountQueue uint64 // Maximum number of non-executable transaction slots permitted per account 163 GlobalQueue uint64 // Maximum number of non-executable transaction slots for all accounts 164 165 Lifetime time.Duration // Maximum amount of time non-executable transaction are queued 166 TicketTxLifetime time.Duration // Maximum amount of time buy ticket transaction are queued 167 } 168 169 // DefaultTxPoolConfig contains the default configurations for the transaction 170 // pool. 171 var DefaultTxPoolConfig = TxPoolConfig{ 172 Journal: "transactions.rlp", 173 Rejournal: time.Hour, 174 175 PriceLimit: 1, 176 PriceBump: 10, 177 178 AccountSlots: 16, 179 GlobalSlots: 4096 + 1024, // urgent + floating queue capacity with 4:1 ratio 180 AccountQueue: 64, 181 GlobalQueue: 1024, 182 183 Lifetime: 3 * time.Hour, 184 TicketTxLifetime: 10 * time.Minute, 185 } 186 187 // sanitize checks the provided user configurations and changes anything that's 188 // unreasonable or unworkable. 189 func (config *TxPoolConfig) sanitize() TxPoolConfig { 190 conf := *config 191 if conf.Rejournal < time.Second { 192 log.Warn("Sanitizing invalid txpool journal time", "provided", conf.Rejournal, "updated", time.Second) 193 conf.Rejournal = time.Second 194 } 195 if conf.PriceLimit < 1 { 196 log.Warn("Sanitizing invalid txpool price limit", "provided", conf.PriceLimit, "updated", DefaultTxPoolConfig.PriceLimit) 197 conf.PriceLimit = DefaultTxPoolConfig.PriceLimit 198 } 199 if conf.PriceBump < 1 { 200 log.Warn("Sanitizing invalid txpool price bump", "provided", conf.PriceBump, "updated", DefaultTxPoolConfig.PriceBump) 201 conf.PriceBump = DefaultTxPoolConfig.PriceBump 202 } 203 if conf.AccountSlots < 1 { 204 log.Warn("Sanitizing invalid txpool account slots", "provided", conf.AccountSlots, "updated", DefaultTxPoolConfig.AccountSlots) 205 conf.AccountSlots = DefaultTxPoolConfig.AccountSlots 206 } 207 if conf.GlobalSlots < 1 { 208 log.Warn("Sanitizing invalid txpool global slots", "provided", conf.GlobalSlots, "updated", DefaultTxPoolConfig.GlobalSlots) 209 conf.GlobalSlots = DefaultTxPoolConfig.GlobalSlots 210 } 211 if conf.AccountQueue < 1 { 212 log.Warn("Sanitizing invalid txpool account queue", "provided", conf.AccountQueue, "updated", DefaultTxPoolConfig.AccountQueue) 213 conf.AccountQueue = DefaultTxPoolConfig.AccountQueue 214 } 215 if conf.GlobalQueue < 1 { 216 log.Warn("Sanitizing invalid txpool global queue", "provided", conf.GlobalQueue, "updated", DefaultTxPoolConfig.GlobalQueue) 217 conf.GlobalQueue = DefaultTxPoolConfig.GlobalQueue 218 } 219 if conf.Lifetime < 1 { 220 log.Warn("Sanitizing invalid txpool lifetime", "provided", conf.Lifetime, "updated", DefaultTxPoolConfig.Lifetime) 221 conf.Lifetime = DefaultTxPoolConfig.Lifetime 222 } 223 return conf 224 } 225 226 // TxPool contains all currently known transactions. Transactions 227 // enter the pool when they are received from the network or submitted 228 // locally. They exit the pool when they are included in the blockchain. 229 // 230 // The pool separates processable transactions (which can be applied to the 231 // current state) and future transactions. Transactions move between those 232 // two states over time as they are received and processed. 233 type TxPool struct { 234 config TxPoolConfig 235 chainconfig *params.ChainConfig 236 chain blockChain 237 gasPrice *big.Int 238 txFeed event.Feed 239 scope event.SubscriptionScope 240 signer types.Signer 241 mu sync.RWMutex 242 243 istanbul bool // Fork indicator whether we are in the istanbul stage. 244 eip2718 bool // Fork indicator whether we are using EIP-2718 type transactions. 245 eip1559 bool // Fork indicator whether we are using EIP-1559 type transactions. 246 247 currentState *state.StateDB // Current state in the blockchain head 248 pendingNonces *txNoncer // Pending state tracking virtual nonces 249 currentMaxGas uint64 // Current gas limit for transaction caps 250 251 locals *accountSet // Set of local transaction to exempt from eviction rules 252 journal *txJournal // Journal of local transaction to back up to disk 253 254 pending map[common.Address]*txList // All currently processable transactions 255 queue map[common.Address]*txList // Queued but non-processable transactions 256 beats map[common.Address]time.Time // Last heartbeat from each known account 257 all *txLookup // All transactions to allow lookups 258 priced *txPricedList // All transactions sorted by price 259 260 chainHeadCh chan ChainHeadEvent 261 chainHeadSub event.Subscription 262 reqResetCh chan *txpoolResetRequest 263 reqPromoteCh chan *accountSet 264 queueTxEventCh chan *types.Transaction 265 reorgDoneCh chan chan struct{} 266 reorgShutdownCh chan struct{} // requests shutdown of scheduleReorgLoop 267 wg sync.WaitGroup // tracks loop, scheduleReorgLoop 268 269 // Fusion Feature 270 blacklist map[common.Address]struct{} // All Black List Address, reject in the txpool 271 } 272 273 type txpoolResetRequest struct { 274 oldHead, newHead *types.Header 275 } 276 277 // NewTxPool creates a new transaction pool to gather, sort and filter inbound 278 // transactions from the network. 279 func NewTxPool(config TxPoolConfig, chainconfig *params.ChainConfig, chain blockChain) *TxPool { 280 // Sanitize the input to ensure no vulnerable gas prices are set 281 config = (&config).sanitize() 282 283 // Create the transaction pool with its initial settings 284 pool := &TxPool{ 285 config: config, 286 chainconfig: chainconfig, 287 chain: chain, 288 signer: types.LatestSigner(chainconfig), 289 pending: make(map[common.Address]*txList), 290 queue: make(map[common.Address]*txList), 291 beats: make(map[common.Address]time.Time), 292 all: newTxLookup(), 293 chainHeadCh: make(chan ChainHeadEvent, chainHeadChanSize), 294 reqResetCh: make(chan *txpoolResetRequest), 295 reqPromoteCh: make(chan *accountSet), 296 queueTxEventCh: make(chan *types.Transaction), 297 reorgDoneCh: make(chan chan struct{}), 298 reorgShutdownCh: make(chan struct{}), 299 gasPrice: new(big.Int).SetUint64(config.PriceLimit), 300 301 blacklist: make(map[common.Address]struct{}), 302 } 303 pool.locals = newAccountSet(pool.signer) 304 for _, addr := range config.Locals { 305 log.Info("Setting new local account", "address", addr) 306 pool.locals.add(addr) 307 } 308 pool.priced = newTxPricedList(pool.all) 309 pool.reset(nil, chain.CurrentBlock().Header()) 310 311 // Start the reorg loop early so it can handle requests generated during journal loading. 312 pool.wg.Add(1) 313 go pool.scheduleReorgLoop() 314 315 // If local transactions and journaling is enabled, load from disk 316 if !config.NoLocals && config.Journal != "" { 317 pool.journal = newTxJournal(config.Journal) 318 319 if err := pool.journal.load(pool.AddLocals); err != nil { 320 log.Warn("Failed to load transaction journal", "err", err) 321 } 322 if err := pool.journal.rotate(pool.local()); err != nil { 323 log.Warn("Failed to rotate transaction journal", "err", err) 324 } 325 } 326 327 // Subscribe events from blockchain and start the main event loop. 328 pool.chainHeadSub = pool.chain.SubscribeChainHeadEvent(pool.chainHeadCh) 329 pool.wg.Add(1) 330 go pool.loop() 331 332 return pool 333 } 334 335 // loop is the transaction pool's main event loop, waiting for and reacting to 336 // outside blockchain events as well as for various reporting and transaction 337 // eviction events. 338 func (pool *TxPool) loop() { 339 defer pool.wg.Done() 340 341 var ( 342 prevPending, prevQueued, prevStales int 343 // Start the stats reporting and transaction eviction tickers 344 report = time.NewTicker(statsReportInterval) 345 evict = time.NewTicker(evictionInterval) 346 journal = time.NewTicker(pool.config.Rejournal) 347 // Track the previous head headers for transaction reorgs 348 head = pool.chain.CurrentBlock() 349 ) 350 351 defer report.Stop() 352 defer evict.Stop() 353 defer journal.Stop() 354 355 // Keep waiting for and reacting to the various events 356 for { 357 select { 358 // Handle ChainHeadEvent 359 case ev := <-pool.chainHeadCh: 360 if ev.Block != nil { 361 pool.requestReset(head.Header(), ev.Block.Header()) 362 head = ev.Block 363 } 364 // System shutdown. 365 case <-pool.chainHeadSub.Err(): 366 close(pool.reorgShutdownCh) 367 return 368 369 // Handle stats reporting ticks 370 case <-report.C: 371 pool.mu.RLock() 372 pending, queued := pool.stats() 373 stales := pool.priced.stales 374 pool.mu.RUnlock() 375 376 if pending != prevPending || queued != prevQueued || stales != prevStales { 377 log.Debug("Transaction pool status report", "executable", pending, "queued", queued, "stales", stales) 378 prevPending, prevQueued, prevStales = pending, queued, stales 379 } 380 381 // Handle inactive account transaction eviction 382 case <-evict.C: 383 pool.mu.Lock() 384 for addr := range pool.queue { 385 // Skip local transactions from the eviction mechanism 386 if pool.locals.contains(addr) { 387 continue 388 } 389 // Any non-locals old enough should be removed 390 if time.Since(pool.beats[addr]) > pool.config.Lifetime { 391 list := pool.queue[addr].Flatten() 392 for _, tx := range list { 393 pool.removeTx(tx.Hash(), true) 394 } 395 queuedEvictionMeter.Mark(int64(len(list))) 396 } 397 } 398 for hash, receiveTime := range pool.all.ticketTxBeats { 399 tx := pool.all.Get(hash) 400 if tx == nil { 401 delete(pool.all.ticketTxBeats, hash) 402 continue 403 } 404 // Any buy ticket tx old enough should be removed 405 if time.Since(receiveTime) > pool.config.TicketTxLifetime { 406 log.Info("remove buy ticket tx old enough", 407 "hash", hash, 408 "receive", receiveTime, 409 "passed", time.Since(receiveTime)) 410 pool.removeTx(hash, true) 411 delete(pool.all.ticketTxBeats, hash) 412 } 413 } 414 pool.mu.Unlock() 415 416 // Handle local transaction journal rotation 417 case <-journal.C: 418 if pool.journal != nil { 419 pool.mu.Lock() 420 if err := pool.journal.rotate(pool.local()); err != nil { 421 log.Warn("Failed to rotate local tx journal", "err", err) 422 } 423 pool.mu.Unlock() 424 } 425 } 426 } 427 } 428 429 // Stop terminates the transaction pool. 430 func (pool *TxPool) Stop() { 431 // Unsubscribe all subscriptions registered from txpool 432 pool.scope.Close() 433 434 // Unsubscribe subscriptions registered from blockchain 435 pool.chainHeadSub.Unsubscribe() 436 pool.wg.Wait() 437 438 if pool.journal != nil { 439 pool.journal.close() 440 } 441 log.Info("Transaction pool stopped") 442 } 443 444 // SubscribeNewTxsEvent registers a subscription of NewTxsEvent and 445 // starts sending event to the given channel. 446 func (pool *TxPool) SubscribeNewTxsEvent(ch chan<- NewTxsEvent) event.Subscription { 447 return pool.scope.Track(pool.txFeed.Subscribe(ch)) 448 } 449 450 // GasPrice returns the current gas price enforced by the transaction pool. 451 func (pool *TxPool) GasPrice() *big.Int { 452 pool.mu.RLock() 453 defer pool.mu.RUnlock() 454 455 return new(big.Int).Set(pool.gasPrice) 456 } 457 458 // SetGasPrice updates the minimum price required by the transaction pool for a 459 // new transaction, and drops all transactions below this threshold. 460 func (pool *TxPool) SetGasPrice(price *big.Int) { 461 pool.mu.Lock() 462 defer pool.mu.Unlock() 463 464 old := pool.gasPrice 465 pool.gasPrice = price 466 // if the min miner fee increased, remove transactions below the new threshold 467 if price.Cmp(old) > 0 { 468 // pool.priced is sorted by GasFeeCap, so we have to iterate through pool.all instead 469 drop := pool.all.RemotesBelowTip(price) 470 for _, tx := range drop { 471 pool.removeTx(tx.Hash(), false) 472 } 473 pool.priced.Removed(len(drop)) 474 } 475 476 log.Info("Transaction pool price threshold updated", "price", price) 477 } 478 479 // Nonce returns the next nonce of an account, with all transactions executable 480 // by the pool already applied on top. 481 func (pool *TxPool) Nonce(addr common.Address) uint64 { 482 pool.mu.RLock() 483 defer pool.mu.RUnlock() 484 485 return pool.pendingNonces.get(addr) 486 } 487 488 // Stats retrieves the current pool stats, namely the number of pending and the 489 // number of queued (non-executable) transactions. 490 func (pool *TxPool) Stats() (int, int) { 491 pool.mu.RLock() 492 defer pool.mu.RUnlock() 493 494 return pool.stats() 495 } 496 497 // stats retrieves the current pool stats, namely the number of pending and the 498 // number of queued (non-executable) transactions. 499 func (pool *TxPool) stats() (int, int) { 500 pending := 0 501 for _, list := range pool.pending { 502 pending += list.Len() 503 } 504 queued := 0 505 for _, list := range pool.queue { 506 queued += list.Len() 507 } 508 return pending, queued 509 } 510 511 // Content retrieves the data content of the transaction pool, returning all the 512 // pending as well as queued transactions, grouped by account and sorted by nonce. 513 func (pool *TxPool) Content() (map[common.Address]types.Transactions, map[common.Address]types.Transactions) { 514 pool.mu.Lock() 515 defer pool.mu.Unlock() 516 517 pending := make(map[common.Address]types.Transactions) 518 for addr, list := range pool.pending { 519 pending[addr] = list.Flatten() 520 } 521 queued := make(map[common.Address]types.Transactions) 522 for addr, list := range pool.queue { 523 queued[addr] = list.Flatten() 524 } 525 return pending, queued 526 } 527 528 // Pending retrieves all currently processable transactions, grouped by origin 529 // account and sorted by nonce. The returned transaction set is a copy and can be 530 // freely modified by calling code. 531 // 532 // The enforceTips parameter can be used to do an extra filtering on the pending 533 // transactions and only return those whose **effective** tip is large enough in 534 // the next pending execution environment. 535 func (pool *TxPool) Pending(enforceTips bool) map[common.Address]types.Transactions { 536 pool.mu.Lock() 537 defer pool.mu.Unlock() 538 539 pending := make(map[common.Address]types.Transactions) 540 for addr, list := range pool.pending { 541 txs := list.Flatten() 542 543 // If the miner requests tip enforcement, cap the lists now 544 if enforceTips && !pool.locals.contains(addr) { 545 for i, tx := range txs { 546 // Fusion will give the base fee back to miner, so no need to minus the base fee when enforceTips is true 547 if tx.EffectiveGasTipIntCmp(pool.gasPrice, nil) < 0 { 548 txs = txs[:i] 549 break 550 } 551 } 552 } 553 if len(txs) > 0 { 554 pending[addr] = txs 555 } 556 } 557 return pending 558 } 559 560 // Locals retrieves the accounts currently considered local by the pool. 561 func (pool *TxPool) Locals() []common.Address { 562 pool.mu.Lock() 563 defer pool.mu.Unlock() 564 565 return pool.locals.flatten() 566 } 567 568 // local retrieves all currently known local transactions, grouped by origin 569 // account and sorted by nonce. The returned transaction set is a copy and can be 570 // freely modified by calling code. 571 func (pool *TxPool) local() map[common.Address]types.Transactions { 572 txs := make(map[common.Address]types.Transactions) 573 for addr := range pool.locals.accounts { 574 if pending := pool.pending[addr]; pending != nil { 575 txs[addr] = append(txs[addr], pending.Flatten()...) 576 } 577 if queued := pool.queue[addr]; queued != nil { 578 txs[addr] = append(txs[addr], queued.Flatten()...) 579 } 580 } 581 return txs 582 } 583 584 // validateTx checks whether a transaction is valid according to the consensus 585 // rules and adheres to some heuristic limits of the local node (price and size). 586 func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error { 587 // Accept only legacy transactions until EIP-2718/2930 activates. 588 if !pool.eip2718 && tx.Type() != types.LegacyTxType { 589 return ErrTxTypeNotSupported 590 } 591 // Reject dynamic fee transactions until EIP-1559 activates. 592 if !pool.eip1559 && tx.Type() == types.DynamicFeeTxType { 593 return ErrTxTypeNotSupported 594 } 595 // Reject transactions over defined size to prevent DOS attacks 596 if uint64(tx.Size()) > txMaxSize { 597 return ErrOversizedData 598 } 599 // Transactions can't be negative. This may never happen using RLP decoded 600 // transactions but may occur if you create a transaction using the RPC. 601 if tx.Value().Sign() < 0 { 602 return ErrNegativeValue 603 } 604 // Ensure the transaction doesn't exceed the current block limit gas. 605 if pool.currentMaxGas < tx.Gas() { 606 return ErrGasLimit 607 } 608 // Sanity check for extremely large numbers 609 if tx.GasFeeCap().BitLen() > 256 { 610 return ErrFeeCapVeryHigh 611 } 612 if tx.GasTipCap().BitLen() > 256 { 613 return ErrTipVeryHigh 614 } 615 // Ensure gasFeeCap is greater than or equal to gasTipCap. 616 if tx.GasFeeCapIntCmp(tx.GasTipCap()) < 0 { 617 return ErrTipAboveFeeCap 618 } 619 // Make sure the transaction is signed properly 620 from, err := types.Sender(pool.signer, tx) 621 if err != nil { 622 return ErrInvalidSender 623 } 624 // Drop the tx if in the blacklist 625 if _, has := pool.blacklist[from]; has { 626 return ErrBlackList 627 } else { 628 to := tx.To() 629 if to != nil { 630 if _, has := pool.blacklist[*to]; has { 631 return ErrBlackList 632 } 633 } 634 } 635 636 // Drop non-local transactions under our own minimal accepted gas price 637 if !local && tx.GasTipCapIntCmp(pool.gasPrice) < 0 { 638 return ErrUnderpriced 639 } 640 // Ensure the transaction adheres to nonce ordering 641 if pool.currentState.GetNonce(from) > tx.Nonce() { 642 return ErrNonceTooLow 643 } 644 // Transactor should have enough funds to cover the costs 645 // cost == V + GP * GL 646 if pool.currentState.GetBalance(common.SystemAssetID, from).Cmp(tx.Cost()) < 0 { 647 return ErrInsufficientFunds 648 } 649 intrGas, err := IntrinsicGas(tx.Data(), tx.AccessList(), tx.To() == nil, true, pool.istanbul) 650 if err != nil { 651 return err 652 } 653 if tx.Gas() < intrGas { 654 return ErrIntrinsicGas 655 } 656 return nil 657 } 658 659 // add validates a transaction and inserts it into the non-executable queue for 660 // later pending promotion and execution. If the transaction is a replacement for 661 // an already pending or queued one, it overwrites the previous and returns this 662 // so outer code doesn't uselessly call promote. 663 // 664 // If a newly added transaction is marked as local, its sending account will be 665 // whitelisted, preventing any associated transaction from being dropped out of 666 // the pool due to pricing constraints. 667 func (pool *TxPool) add(tx *types.Transaction, local bool) (bool, error) { 668 // If the transaction is already known, discard it 669 hash := tx.Hash() 670 if pool.all.Get(hash) != nil { 671 log.Trace("Discarding already known transaction", "hash", hash) 672 knownTxMeter.Mark(1) 673 return false, ErrAlreadyKnown 674 } 675 // Make the local flag. If it's from local source or it's from the network but 676 // the sender is marked as local previously, treat it as the local transaction. 677 isLocal := local || pool.locals.containsTx(tx) 678 679 // If the transaction fails basic validation, discard it 680 if err := pool.validateTx(tx, isLocal); err != nil { 681 log.Trace("Discarding invalid transaction", "hash", hash, "err", err) 682 invalidTxMeter.Mark(1) 683 return false, err 684 } 685 // If the transaction is an invalid FsnCall tx, discard it 686 if err := pool.validateAddFsnCallTx(tx); err != nil { 687 invalidTxMeter.Mark(1) 688 return false, err 689 } 690 // If the transaction pool is full, discard underpriced transactions 691 if uint64(pool.all.Slots()+numSlots(tx)) >= pool.config.GlobalSlots+pool.config.GlobalQueue { 692 // If the new transaction is underpriced, don't accept it 693 if !local && pool.priced.Underpriced(tx) { 694 log.Trace("Discarding underpriced transaction", "hash", hash, "gasTipCap", tx.GasTipCap(), "gasFeeCap", tx.GasFeeCap()) 695 underpricedTxMeter.Mark(1) 696 return false, ErrUnderpriced 697 } 698 // New transaction is better than our worse ones, make room for it. 699 // If it's a local transaction, forcibly discard all available transactions. 700 // Otherwise if we can't make enough room for new one, abort the operation. 701 drop, success := pool.priced.Discard(pool.all.Slots()-int(pool.config.GlobalSlots+pool.config.GlobalQueue)+numSlots(tx), isLocal) 702 703 // Special case, we still can't make the room for the new remote one. 704 if !isLocal && !success { 705 log.Trace("Discarding overflown transaction", "hash", hash) 706 overflowedTxMeter.Mark(1) 707 return false, ErrTxPoolOverflow 708 } 709 // Kick out the underpriced remote transactions. 710 for _, tx := range drop { 711 log.Trace("Discarding freshly underpriced transaction", "hash", tx.Hash(), "gasTipCap", tx.GasTipCap(), "gasFeeCap", tx.GasFeeCap()) 712 underpricedTxMeter.Mark(1) 713 pool.removeTx(tx.Hash(), false) 714 } 715 } 716 // Try to replace an existing transaction in the pending pool 717 from, _ := types.Sender(pool.signer, tx) // already validated 718 if list := pool.pending[from]; list != nil && list.Overlaps(tx) { 719 // Nonce already pending, check if required price bump is met 720 inserted, old := list.Add(tx, pool.config.PriceBump) 721 if !inserted { 722 pendingDiscardMeter.Mark(1) 723 return false, ErrReplaceUnderpriced 724 } 725 // New transaction is better, replace old one 726 if old != nil { 727 pool.all.Remove(old.Hash()) 728 pool.priced.Removed(1) 729 pendingReplaceMeter.Mark(1) 730 } 731 pool.all.Add(tx, isLocal) 732 pool.priced.Put(tx, isLocal) 733 pool.journalTx(from, tx) 734 pool.queueTxEvent(tx) 735 log.Trace("Pooled new executable transaction", "hash", hash, "from", from, "to", tx.To()) 736 737 // Successful promotion, bump the heartbeat 738 pool.beats[from] = time.Now() 739 return old != nil, nil 740 } 741 // New transaction isn't replacing a pending one, push into queue 742 replace, err := pool.enqueueTx(hash, tx, isLocal, true) 743 if err != nil { 744 return false, err 745 } 746 // Mark local addresses and journal local transactions 747 if local && !pool.locals.contains(from) { 748 log.Info("Setting new local account", "address", from) 749 pool.locals.add(from) 750 pool.priced.Removed(pool.all.RemoteToLocals(pool.locals)) // Migrate the remotes if it's marked as local first time. 751 } 752 if isLocal { 753 localGauge.Inc(1) 754 } 755 pool.journalTx(from, tx) 756 757 log.Trace("Pooled new future transaction", "hash", hash, "from", from, "to", tx.To()) 758 return replace, nil 759 } 760 761 // enqueueTx inserts a new transaction into the non-executable transaction queue. 762 // 763 // Note, this method assumes the pool lock is held! 764 func (pool *TxPool) enqueueTx(hash common.Hash, tx *types.Transaction, local bool, addAll bool) (bool, error) { 765 // Try to insert the transaction into the future queue 766 from, _ := types.Sender(pool.signer, tx) // already validated 767 if pool.queue[from] == nil { 768 pool.queue[from] = newTxList(false) 769 } 770 inserted, old := pool.queue[from].Add(tx, pool.config.PriceBump) 771 if !inserted { 772 // An older transaction was better, discard this 773 queuedDiscardMeter.Mark(1) 774 return false, ErrReplaceUnderpriced 775 } 776 // Discard any previous transaction and mark this 777 if old != nil { 778 pool.all.Remove(old.Hash()) 779 pool.priced.Removed(1) 780 queuedReplaceMeter.Mark(1) 781 } else { 782 // Nothing was replaced, bump the queued counter 783 queuedGauge.Inc(1) 784 } 785 // If the transaction isn't in lookup set but it's expected to be there, 786 // show the error log. 787 if pool.all.Get(hash) == nil && !addAll { 788 log.Error("Missing transaction in lookup set, please report the issue", "hash", hash) 789 } 790 if addAll { 791 pool.all.Add(tx, local) 792 pool.priced.Put(tx, local) 793 } 794 // If we never record the heartbeat, do it right now. 795 if _, exist := pool.beats[from]; !exist { 796 pool.beats[from] = time.Now() 797 } 798 return old != nil, nil 799 } 800 801 // journalTx adds the specified transaction to the local disk journal if it is 802 // deemed to have been sent from a local account. 803 func (pool *TxPool) journalTx(from common.Address, tx *types.Transaction) { 804 // Only journal if it's enabled and the transaction is local 805 if pool.journal == nil || !pool.locals.contains(from) { 806 return 807 } 808 if err := pool.journal.insert(tx); err != nil { 809 log.Warn("Failed to journal local transaction", "err", err) 810 } 811 } 812 813 // promoteTx adds a transaction to the pending (processable) list of transactions 814 // and returns whether it was inserted or an older was better. 815 // 816 // Note, this method assumes the pool lock is held! 817 func (pool *TxPool) promoteTx(addr common.Address, hash common.Hash, tx *types.Transaction) bool { 818 // Try to insert the transaction into the pending queue 819 if pool.pending[addr] == nil { 820 pool.pending[addr] = newTxList(true) 821 } 822 list := pool.pending[addr] 823 824 inserted, old := list.Add(tx, pool.config.PriceBump) 825 if !inserted { 826 // An older transaction was better, discard this 827 pool.all.Remove(hash) 828 pool.priced.Removed(1) 829 pendingDiscardMeter.Mark(1) 830 return false 831 } 832 // Otherwise discard any previous transaction and mark this 833 if old != nil { 834 pool.all.Remove(old.Hash()) 835 pool.priced.Removed(1) 836 pendingReplaceMeter.Mark(1) 837 } else { 838 // Nothing was replaced, bump the pending counter 839 pendingGauge.Inc(1) 840 } 841 // Set the potentially new pending nonce and notify any subsystems of the new tx 842 pool.pendingNonces.set(addr, tx.Nonce()+1) 843 844 // Successful promotion, bump the heartbeat 845 pool.beats[addr] = time.Now() 846 return true 847 } 848 849 // AddLocals enqueues a batch of transactions into the pool if they are valid, marking the 850 // senders as a local ones, ensuring they go around the local pricing constraints. 851 // 852 // This method is used to add transactions from the RPC API and performs synchronous pool 853 // reorganization and event propagation. 854 func (pool *TxPool) AddLocals(txs []*types.Transaction) []error { 855 return pool.addTxs(txs, !pool.config.NoLocals, true) 856 } 857 858 // AddLocal enqueues a single local transaction into the pool if it is valid. This is 859 // a convenience wrapper aroundd AddLocals. 860 func (pool *TxPool) AddLocal(tx *types.Transaction) error { 861 errs := pool.AddLocals([]*types.Transaction{tx}) 862 return errs[0] 863 } 864 865 // AddRemotes enqueues a batch of transactions into the pool if they are valid. If the 866 // senders are not among the locally tracked ones, full pricing constraints will apply. 867 // 868 // This method is used to add transactions from the p2p network and does not wait for pool 869 // reorganization and internal event propagation. 870 func (pool *TxPool) AddRemotes(txs []*types.Transaction) []error { 871 return pool.addTxs(txs, false, false) 872 } 873 874 // AddRemote enqueues a single transaction into the pool if it is valid. This is a convenience 875 // wrapper around AddRemotes. 876 // 877 // Deprecated: use AddRemotes 878 func (pool *TxPool) AddRemote(tx *types.Transaction) error { 879 errs := pool.AddRemotes([]*types.Transaction{tx}) 880 return errs[0] 881 } 882 883 // addTxs attempts to queue a batch of transactions if they are valid. 884 func (pool *TxPool) addTxs(txs []*types.Transaction, local, sync bool) []error { 885 // Filter out known ones without obtaining the pool lock or recovering signatures 886 var ( 887 errs = make([]error, len(txs)) 888 news = make([]*types.Transaction, 0, len(txs)) 889 ) 890 for i, tx := range txs { 891 // If the transaction is known, pre-set the error slot 892 if pool.all.Get(tx.Hash()) != nil { 893 errs[i] = ErrAlreadyKnown 894 knownTxMeter.Mark(1) 895 continue 896 } 897 // Exclude transactions with invalid signatures as soon as 898 // possible and cache senders in transactions before 899 // obtaining lock 900 _, err := types.Sender(pool.signer, tx) 901 if err != nil { 902 errs[i] = ErrInvalidSender 903 invalidTxMeter.Mark(1) 904 continue 905 } 906 // Accumulate all unknown transactions for deeper processing 907 news = append(news, tx) 908 } 909 if len(news) == 0 { 910 return errs 911 } 912 913 // Process all the new transaction and merge any errors into the original slice 914 pool.mu.Lock() 915 newErrs, dirtyAddrs := pool.addTxsLocked(news, local) 916 pool.mu.Unlock() 917 918 var nilSlot = 0 919 for _, err := range newErrs { 920 for errs[nilSlot] != nil { 921 nilSlot++ 922 } 923 errs[nilSlot] = err 924 nilSlot++ 925 } 926 // Reorg the pool internals if needed and return 927 done := pool.requestPromoteExecutables(dirtyAddrs) 928 if sync { 929 <-done 930 } 931 return errs 932 } 933 934 // addTxsLocked attempts to queue a batch of transactions if they are valid. 935 // The transaction pool lock must be held. 936 func (pool *TxPool) addTxsLocked(txs []*types.Transaction, local bool) ([]error, *accountSet) { 937 dirty := newAccountSet(pool.signer) 938 errs := make([]error, len(txs)) 939 for i, tx := range txs { 940 replaced, err := pool.add(tx, local) 941 errs[i] = err 942 if err == nil && !replaced { 943 dirty.addTx(tx) 944 } 945 } 946 validTxMeter.Mark(int64(len(dirty.accounts))) 947 return errs, dirty 948 } 949 950 // Status returns the status (unknown/pending/queued) of a batch of transactions 951 // identified by their hashes. 952 func (pool *TxPool) Status(hashes []common.Hash) []TxStatus { 953 status := make([]TxStatus, len(hashes)) 954 for i, hash := range hashes { 955 tx := pool.Get(hash) 956 if tx == nil { 957 continue 958 } 959 from, _ := types.Sender(pool.signer, tx) // already validated 960 pool.mu.RLock() 961 if txList := pool.pending[from]; txList != nil && txList.txs.items[tx.Nonce()] != nil { 962 status[i] = TxStatusPending 963 } else if txList := pool.queue[from]; txList != nil && txList.txs.items[tx.Nonce()] != nil { 964 status[i] = TxStatusQueued 965 } 966 // implicit else: the tx may have been included into a block between 967 // checking pool.Get and obtaining the lock. In that case, TxStatusUnknown is correct 968 pool.mu.RUnlock() 969 } 970 return status 971 } 972 973 // Get returns a transaction if it is contained in the pool 974 // and nil otherwise. 975 func (pool *TxPool) Get(hash common.Hash) *types.Transaction { 976 return pool.all.Get(hash) 977 } 978 979 // Has returns an indicator whether txpool has a transaction cached with the 980 // given hash. 981 func (pool *TxPool) Has(hash common.Hash) bool { 982 return pool.all.Get(hash) != nil 983 } 984 985 func (pool *TxPool) GetByPredicate(predicate func(*types.Transaction) bool) *types.Transaction { 986 return pool.all.GetByPredicate(predicate) 987 } 988 989 // removeTx removes a single transaction from the queue, moving all subsequent 990 // transactions back to the future queue. 991 func (pool *TxPool) removeTx(hash common.Hash, outofbound bool) { 992 // Fetch the transaction we wish to delete 993 tx := pool.all.Get(hash) 994 if tx == nil { 995 return 996 } 997 addr, _ := types.Sender(pool.signer, tx) // already validated during insertion 998 999 // Remove it from the list of known transactions 1000 pool.all.Remove(hash) 1001 if outofbound { 1002 pool.priced.Removed(1) 1003 } 1004 if pool.locals.contains(addr) { 1005 localGauge.Dec(1) 1006 } 1007 // Remove the transaction from the pending lists and reset the account nonce 1008 if pending := pool.pending[addr]; pending != nil { 1009 if removed, invalids := pending.Remove(tx); removed { 1010 // If no more pending transactions are left, remove the list 1011 if pending.Empty() { 1012 delete(pool.pending, addr) 1013 } 1014 // Postpone any invalidated transactions 1015 for _, tx := range invalids { 1016 // Internal shuffle shouldn't touch the lookup set. 1017 pool.enqueueTx(tx.Hash(), tx, false, false) 1018 } 1019 // Update the account nonce if needed 1020 pool.pendingNonces.setIfLower(addr, tx.Nonce()) 1021 // Reduce the pending counter 1022 pendingGauge.Dec(int64(1 + len(invalids))) 1023 return 1024 } 1025 } 1026 // Transaction is in the future queue 1027 if future := pool.queue[addr]; future != nil { 1028 if removed, _ := future.Remove(tx); removed { 1029 // Reduce the queued counter 1030 queuedGauge.Dec(1) 1031 } 1032 if future.Empty() { 1033 delete(pool.queue, addr) 1034 delete(pool.beats, addr) 1035 } 1036 } 1037 } 1038 1039 // requestReset requests a pool reset to the new head block. 1040 // The returned channel is closed when the reset has occurred. 1041 func (pool *TxPool) requestReset(oldHead *types.Header, newHead *types.Header) chan struct{} { 1042 select { 1043 case pool.reqResetCh <- &txpoolResetRequest{oldHead, newHead}: 1044 return <-pool.reorgDoneCh 1045 case <-pool.reorgShutdownCh: 1046 return pool.reorgShutdownCh 1047 } 1048 } 1049 1050 // requestPromoteExecutables requests transaction promotion checks for the given addresses. 1051 // The returned channel is closed when the promotion checks have occurred. 1052 func (pool *TxPool) requestPromoteExecutables(set *accountSet) chan struct{} { 1053 select { 1054 case pool.reqPromoteCh <- set: 1055 return <-pool.reorgDoneCh 1056 case <-pool.reorgShutdownCh: 1057 return pool.reorgShutdownCh 1058 } 1059 } 1060 1061 // queueTxEvent enqueues a transaction event to be sent in the next reorg run. 1062 func (pool *TxPool) queueTxEvent(tx *types.Transaction) { 1063 select { 1064 case pool.queueTxEventCh <- tx: 1065 case <-pool.reorgShutdownCh: 1066 } 1067 } 1068 1069 // scheduleReorgLoop schedules runs of reset and promoteExecutables. Code above should not 1070 // call those methods directly, but request them being run using requestReset and 1071 // requestPromoteExecutables instead. 1072 func (pool *TxPool) scheduleReorgLoop() { 1073 defer pool.wg.Done() 1074 1075 var ( 1076 curDone chan struct{} // non-nil while runReorg is active 1077 nextDone = make(chan struct{}) 1078 launchNextRun bool 1079 reset *txpoolResetRequest 1080 dirtyAccounts *accountSet 1081 queuedEvents = make(map[common.Address]*txSortedMap) 1082 ) 1083 for { 1084 // Launch next background reorg if needed 1085 if curDone == nil && launchNextRun { 1086 // Run the background reorg and announcements 1087 go pool.runReorg(nextDone, reset, dirtyAccounts, queuedEvents) 1088 1089 // Prepare everything for the next round of reorg 1090 curDone, nextDone = nextDone, make(chan struct{}) 1091 launchNextRun = false 1092 1093 reset, dirtyAccounts = nil, nil 1094 queuedEvents = make(map[common.Address]*txSortedMap) 1095 } 1096 1097 select { 1098 case req := <-pool.reqResetCh: 1099 // Reset request: update head if request is already pending. 1100 if reset == nil { 1101 reset = req 1102 } else { 1103 reset.newHead = req.newHead 1104 } 1105 launchNextRun = true 1106 pool.reorgDoneCh <- nextDone 1107 1108 case req := <-pool.reqPromoteCh: 1109 // Promote request: update address set if request is already pending. 1110 if dirtyAccounts == nil { 1111 dirtyAccounts = req 1112 } else { 1113 dirtyAccounts.merge(req) 1114 } 1115 launchNextRun = true 1116 pool.reorgDoneCh <- nextDone 1117 1118 case tx := <-pool.queueTxEventCh: 1119 // Queue up the event, but don't schedule a reorg. It's up to the caller to 1120 // request one later if they want the events sent. 1121 addr, _ := types.Sender(pool.signer, tx) 1122 if _, ok := queuedEvents[addr]; !ok { 1123 queuedEvents[addr] = newTxSortedMap() 1124 } 1125 queuedEvents[addr].Put(tx) 1126 1127 case <-curDone: 1128 curDone = nil 1129 1130 case <-pool.reorgShutdownCh: 1131 // Wait for current run to finish. 1132 if curDone != nil { 1133 <-curDone 1134 } 1135 close(nextDone) 1136 return 1137 } 1138 } 1139 } 1140 1141 // runReorg runs reset and promoteExecutables on behalf of scheduleReorgLoop. 1142 func (pool *TxPool) runReorg(done chan struct{}, reset *txpoolResetRequest, dirtyAccounts *accountSet, events map[common.Address]*txSortedMap) { 1143 defer close(done) 1144 1145 var promoteAddrs []common.Address 1146 if dirtyAccounts != nil && reset == nil { 1147 // Only dirty accounts need to be promoted, unless we're resetting. 1148 // For resets, all addresses in the tx queue will be promoted and 1149 // the flatten operation can be avoided. 1150 promoteAddrs = dirtyAccounts.flatten() 1151 } 1152 pool.mu.Lock() 1153 if reset != nil { 1154 // Reset from the old head to the new, rescheduling any reorged transactions 1155 pool.reset(reset.oldHead, reset.newHead) 1156 1157 // Nonces were reset, discard any events that became stale 1158 for addr := range events { 1159 events[addr].Forward(pool.pendingNonces.get(addr)) 1160 if events[addr].Len() == 0 { 1161 delete(events, addr) 1162 } 1163 } 1164 // Reset needs promote for all addresses 1165 promoteAddrs = make([]common.Address, 0, len(pool.queue)) 1166 for addr := range pool.queue { 1167 promoteAddrs = append(promoteAddrs, addr) 1168 } 1169 } 1170 // Check for pending transactions for every account that sent new ones 1171 promoted := pool.promoteExecutables(promoteAddrs) 1172 1173 // If a new block appeared, validate the pool of pending transactions. This will 1174 // remove any transaction that has been included in the block or was invalidated 1175 // because of another transaction (e.g. higher gas price). 1176 if reset != nil { 1177 pool.demoteUnexecutables() 1178 if reset.newHead != nil && pool.chainconfig.IsLondon(new(big.Int).Add(reset.newHead.Number, big.NewInt(1))) { 1179 pendingBaseFee := misc.CalcBaseFee(pool.chainconfig, reset.newHead) 1180 pool.priced.SetBaseFee(pendingBaseFee) 1181 } 1182 } 1183 // Ensure pool.queue and pool.pending sizes stay within the configured limits. 1184 pool.truncatePending() 1185 pool.truncateQueue() 1186 1187 // Update all accounts to the latest known pending nonce 1188 for addr, list := range pool.pending { 1189 highestPending := list.LastElement() 1190 pool.pendingNonces.set(addr, highestPending.Nonce()+1) 1191 } 1192 pool.mu.Unlock() 1193 1194 // Notify subsystems for newly added transactions 1195 for _, tx := range promoted { 1196 addr, _ := types.Sender(pool.signer, tx) 1197 if _, ok := events[addr]; !ok { 1198 events[addr] = newTxSortedMap() 1199 } 1200 events[addr].Put(tx) 1201 } 1202 if len(events) > 0 { 1203 var txs []*types.Transaction 1204 for _, set := range events { 1205 txs = append(txs, set.Flatten()...) 1206 } 1207 pool.txFeed.Send(NewTxsEvent{txs}) 1208 } 1209 } 1210 1211 // reset retrieves the current state of the blockchain and ensures the content 1212 // of the transaction pool is valid with regard to the chain state. 1213 func (pool *TxPool) reset(oldHead, newHead *types.Header) { 1214 // If we're reorging an old state, reinject all dropped transactions 1215 var reinject types.Transactions 1216 1217 if oldHead != nil && oldHead.Hash() != newHead.ParentHash { 1218 // If the reorg is too deep, avoid doing it (will happen during fast sync) 1219 oldNum := oldHead.Number.Uint64() 1220 newNum := newHead.Number.Uint64() 1221 1222 if depth := uint64(math.Abs(float64(oldNum) - float64(newNum))); depth > 64 { 1223 log.Debug("Skipping deep transaction reorg", "depth", depth) 1224 } else { 1225 // Reorg seems shallow enough to pull in all transactions into memory 1226 var discarded, included types.Transactions 1227 var ( 1228 rem = pool.chain.GetBlock(oldHead.Hash(), oldHead.Number.Uint64()) 1229 add = pool.chain.GetBlock(newHead.Hash(), newHead.Number.Uint64()) 1230 ) 1231 if rem == nil { 1232 // This can happen if a setHead is performed, where we simply discard the old 1233 // head from the chain. 1234 // If that is the case, we don't have the lost transactions any more, and 1235 // there's nothing to add 1236 if newNum >= oldNum { 1237 // If we reorged to a same or higher number, then it's not a case of setHead 1238 log.Warn("Transaction pool reset with missing oldhead", 1239 "old", oldHead.Hash(), "oldnum", oldNum, "new", newHead.Hash(), "newnum", newNum) 1240 return 1241 } 1242 // If the reorg ended up on a lower number, it's indicative of setHead being the cause 1243 log.Debug("Skipping transaction reset caused by setHead", 1244 "old", oldHead.Hash(), "oldnum", oldNum, "new", newHead.Hash(), "newnum", newNum) 1245 // We still need to update the current state s.th. the lost transactions can be readded by the user 1246 } else { 1247 for rem.NumberU64() > add.NumberU64() { 1248 discarded = append(discarded, rem.Transactions()...) 1249 if rem = pool.chain.GetBlock(rem.ParentHash(), rem.NumberU64()-1); rem == nil { 1250 log.Error("Unrooted old chain seen by tx pool", "block", oldHead.Number, "hash", oldHead.Hash()) 1251 return 1252 } 1253 } 1254 for add.NumberU64() > rem.NumberU64() { 1255 included = append(included, add.Transactions()...) 1256 if add = pool.chain.GetBlock(add.ParentHash(), add.NumberU64()-1); add == nil { 1257 log.Error("Unrooted new chain seen by tx pool", "block", newHead.Number, "hash", newHead.Hash()) 1258 return 1259 } 1260 } 1261 for rem.Hash() != add.Hash() { 1262 discarded = append(discarded, rem.Transactions()...) 1263 if rem = pool.chain.GetBlock(rem.ParentHash(), rem.NumberU64()-1); rem == nil { 1264 log.Error("Unrooted old chain seen by tx pool", "block", oldHead.Number, "hash", oldHead.Hash()) 1265 return 1266 } 1267 included = append(included, add.Transactions()...) 1268 if add = pool.chain.GetBlock(add.ParentHash(), add.NumberU64()-1); add == nil { 1269 log.Error("Unrooted new chain seen by tx pool", "block", newHead.Number, "hash", newHead.Hash()) 1270 return 1271 } 1272 } 1273 reinject = types.TxDifference(discarded, included) 1274 } 1275 } 1276 } 1277 // Initialize the internal state to the current head 1278 if newHead == nil { 1279 newHead = pool.chain.CurrentBlock().Header() // Special case during testing 1280 } 1281 statedb, err := pool.chain.StateAt(newHead.Root, newHead.MixDigest) 1282 if err != nil { 1283 log.Error("Failed to reset txpool state", "err", err) 1284 return 1285 } 1286 pool.currentState = statedb 1287 pool.pendingNonces = newTxNoncer(statedb) 1288 pool.currentMaxGas = newHead.GasLimit 1289 1290 // Inject any transactions discarded due to reorgs 1291 log.Debug("Reinjecting stale transactions", "count", len(reinject)) 1292 senderCacher.recover(pool.signer, reinject) 1293 pool.addTxsLocked(reinject, false) 1294 1295 // Update all fork indicator by next pending block number. 1296 next := new(big.Int).Add(newHead.Number, big.NewInt(1)) 1297 pool.istanbul = pool.chainconfig.IsIstanbul(next) 1298 pool.eip2718 = pool.chainconfig.IsBerlin(next) 1299 pool.eip1559 = pool.chainconfig.IsLondon(next) 1300 } 1301 1302 // promoteExecutables moves transactions that have become processable from the 1303 // future queue to the set of pending transactions. During this process, all 1304 // invalidated transactions (low nonce, low balance) are deleted. 1305 func (pool *TxPool) promoteExecutables(accounts []common.Address) []*types.Transaction { 1306 // Track the promoted transactions to broadcast them at once 1307 var promoted []*types.Transaction 1308 1309 // Iterate over all accounts and promote any executable transactions 1310 for _, addr := range accounts { 1311 list := pool.queue[addr] 1312 if list == nil { 1313 continue // Just in case someone calls with a non existing account 1314 } 1315 // Drop all transactions that are deemed too old (low nonce) 1316 forwards := list.Forward(pool.currentState.GetNonce(addr)) 1317 for _, tx := range forwards { 1318 hash := tx.Hash() 1319 pool.all.Remove(hash) 1320 } 1321 log.Trace("Removed old queued transactions", "count", len(forwards)) 1322 // Drop all transactions that are too costly (low balance or out of gas) 1323 drops, _ := list.Filter(pool.currentState.GetBalance(common.SystemAssetID, addr), pool.currentMaxGas) 1324 for _, tx := range drops { 1325 hash := tx.Hash() 1326 pool.all.Remove(hash) 1327 } 1328 log.Trace("Removed unpayable queued transactions", "count", len(drops)) 1329 queuedNofundsMeter.Mark(int64(len(drops))) 1330 // Drop all FsnCall transactions that are invalid 1331 filter := func(tx *types.Transaction) bool { 1332 return pool.validateFsnCallTx(tx) != nil 1333 } 1334 removes, _ := list.FilterInvalid(filter) 1335 for _, tx := range removes { 1336 hash := tx.Hash() 1337 log.Trace("Removed invalid pending transaction", "hash", hash) 1338 pool.all.Remove(hash) 1339 } 1340 1341 // Gather all executable transactions and promote them 1342 readies := list.Ready(pool.pendingNonces.get(addr)) 1343 for _, tx := range readies { 1344 hash := tx.Hash() 1345 if pool.promoteTx(addr, hash, tx) { 1346 promoted = append(promoted, tx) 1347 } 1348 } 1349 log.Trace("Promoted queued transactions", "count", len(promoted)) 1350 queuedGauge.Dec(int64(len(readies))) 1351 1352 // Drop all transactions over the allowed limit 1353 var caps types.Transactions 1354 if !pool.locals.contains(addr) { 1355 caps = list.Cap(int(pool.config.AccountQueue)) 1356 for _, tx := range caps { 1357 hash := tx.Hash() 1358 pool.all.Remove(hash) 1359 log.Trace("Removed cap-exceeding queued transaction", "hash", hash) 1360 } 1361 queuedRateLimitMeter.Mark(int64(len(caps))) 1362 } 1363 // Mark all the items dropped as removed 1364 pool.priced.Removed(len(forwards) + len(drops) + len(caps)) 1365 queuedGauge.Dec(int64(len(forwards) + len(drops) + len(caps))) 1366 if pool.locals.contains(addr) { 1367 localGauge.Dec(int64(len(forwards) + len(drops) + len(caps))) 1368 } 1369 // Delete the entire queue entry if it became empty. 1370 if list.Empty() { 1371 delete(pool.queue, addr) 1372 delete(pool.beats, addr) 1373 } 1374 } 1375 return promoted 1376 } 1377 1378 // truncatePending removes transactions from the pending queue if the pool is above the 1379 // pending limit. The algorithm tries to reduce transaction counts by an approximately 1380 // equal number for all for accounts with many pending transactions. 1381 func (pool *TxPool) truncatePending() { 1382 pending := uint64(0) 1383 for _, list := range pool.pending { 1384 pending += uint64(list.Len()) 1385 } 1386 if pending <= pool.config.GlobalSlots { 1387 return 1388 } 1389 1390 pendingBeforeCap := pending 1391 // Assemble a spam order to penalize large transactors first 1392 spammers := prque.New(nil) 1393 for addr, list := range pool.pending { 1394 // Only evict transactions from high rollers 1395 if !pool.locals.contains(addr) && uint64(list.Len()) > pool.config.AccountSlots { 1396 spammers.Push(addr, int64(list.Len())) 1397 } 1398 } 1399 // Gradually drop transactions from offenders 1400 offenders := []common.Address{} 1401 for pending > pool.config.GlobalSlots && !spammers.Empty() { 1402 // Retrieve the next offender if not local address 1403 offender, _ := spammers.Pop() 1404 offenders = append(offenders, offender.(common.Address)) 1405 1406 // Equalize balances until all the same or below threshold 1407 if len(offenders) > 1 { 1408 // Calculate the equalization threshold for all current offenders 1409 threshold := pool.pending[offender.(common.Address)].Len() 1410 1411 // Iteratively reduce all offenders until below limit or threshold reached 1412 for pending > pool.config.GlobalSlots && pool.pending[offenders[len(offenders)-2]].Len() > threshold { 1413 for i := 0; i < len(offenders)-1; i++ { 1414 list := pool.pending[offenders[i]] 1415 1416 caps := list.Cap(list.Len() - 1) 1417 for _, tx := range caps { 1418 // Drop the transaction from the global pools too 1419 hash := tx.Hash() 1420 pool.all.Remove(hash) 1421 1422 // Update the account nonce to the dropped transaction 1423 pool.pendingNonces.setIfLower(offenders[i], tx.Nonce()) 1424 log.Trace("Removed fairness-exceeding pending transaction", "hash", hash) 1425 } 1426 pool.priced.Removed(len(caps)) 1427 pendingGauge.Dec(int64(len(caps))) 1428 if pool.locals.contains(offenders[i]) { 1429 localGauge.Dec(int64(len(caps))) 1430 } 1431 pending-- 1432 } 1433 } 1434 } 1435 } 1436 1437 // If still above threshold, reduce to limit or min allowance 1438 if pending > pool.config.GlobalSlots && len(offenders) > 0 { 1439 for pending > pool.config.GlobalSlots && uint64(pool.pending[offenders[len(offenders)-1]].Len()) > pool.config.AccountSlots { 1440 for _, addr := range offenders { 1441 list := pool.pending[addr] 1442 1443 caps := list.Cap(list.Len() - 1) 1444 for _, tx := range caps { 1445 // Drop the transaction from the global pools too 1446 hash := tx.Hash() 1447 pool.all.Remove(hash) 1448 1449 // Update the account nonce to the dropped transaction 1450 pool.pendingNonces.setIfLower(addr, tx.Nonce()) 1451 log.Trace("Removed fairness-exceeding pending transaction", "hash", hash) 1452 } 1453 pool.priced.Removed(len(caps)) 1454 pendingGauge.Dec(int64(len(caps))) 1455 if pool.locals.contains(addr) { 1456 localGauge.Dec(int64(len(caps))) 1457 } 1458 pending-- 1459 } 1460 } 1461 } 1462 pendingRateLimitMeter.Mark(int64(pendingBeforeCap - pending)) 1463 } 1464 1465 // truncateQueue drops the oldes transactions in the queue if the pool is above the global queue limit. 1466 func (pool *TxPool) truncateQueue() { 1467 queued := uint64(0) 1468 for _, list := range pool.queue { 1469 queued += uint64(list.Len()) 1470 } 1471 if queued <= pool.config.GlobalQueue { 1472 return 1473 } 1474 1475 // Sort all accounts with queued transactions by heartbeat 1476 addresses := make(addressesByHeartbeat, 0, len(pool.queue)) 1477 for addr := range pool.queue { 1478 if !pool.locals.contains(addr) { // don't drop locals 1479 addresses = append(addresses, addressByHeartbeat{addr, pool.beats[addr]}) 1480 } 1481 } 1482 sort.Sort(addresses) 1483 1484 // Drop transactions until the total is below the limit or only locals remain 1485 for drop := queued - pool.config.GlobalQueue; drop > 0 && len(addresses) > 0; { 1486 addr := addresses[len(addresses)-1] 1487 list := pool.queue[addr.address] 1488 1489 addresses = addresses[:len(addresses)-1] 1490 1491 // Drop all transactions if they are less than the overflow 1492 if size := uint64(list.Len()); size <= drop { 1493 for _, tx := range list.Flatten() { 1494 pool.removeTx(tx.Hash(), true) 1495 } 1496 drop -= size 1497 queuedRateLimitMeter.Mark(int64(size)) 1498 continue 1499 } 1500 // Otherwise drop only last few transactions 1501 txs := list.Flatten() 1502 for i := len(txs) - 1; i >= 0 && drop > 0; i-- { 1503 pool.removeTx(txs[i].Hash(), true) 1504 drop-- 1505 queuedRateLimitMeter.Mark(1) 1506 } 1507 } 1508 } 1509 1510 // demoteUnexecutables removes invalid and processed transactions from the pools 1511 // executable/pending queue and any subsequent transactions that become unexecutable 1512 // are moved back into the future queue. 1513 // 1514 // Note: transactions are not marked as removed in the priced list because re-heaping 1515 // is always explicitly triggered by SetBaseFee and it would be unnecessary and wasteful 1516 // to trigger a re-heap is this function 1517 func (pool *TxPool) demoteUnexecutables() { 1518 // Iterate over all accounts and demote any non-executable transactions 1519 for addr, list := range pool.pending { 1520 nonce := pool.currentState.GetNonce(addr) 1521 1522 // Drop all transactions that are deemed too old (low nonce) 1523 olds := list.Forward(nonce) 1524 for _, tx := range olds { 1525 hash := tx.Hash() 1526 pool.all.Remove(hash) 1527 log.Trace("Removed old pending transaction", "hash", hash) 1528 } 1529 // Drop all FsnCall transactions that are invalid 1530 filter := func(tx *types.Transaction) bool { 1531 return pool.validateFsnCallTx(tx) != nil 1532 } 1533 removes, adjusts := list.FilterInvalid(filter) 1534 for _, tx := range removes { 1535 hash := tx.Hash() 1536 pool.all.Remove(hash) 1537 log.Trace("Removed invalid pending transaction", "hash", hash) 1538 } 1539 // Drop all transactions that are too costly (low balance or out of gas), and queue any invalids back for later 1540 drops, invalids := list.Filter(pool.currentState.GetBalance(common.SystemAssetID, addr), pool.currentMaxGas) 1541 for _, tx := range drops { 1542 hash := tx.Hash() 1543 log.Trace("Removed unpayable pending transaction", "hash", hash) 1544 pool.all.Remove(hash) 1545 } 1546 pendingNofundsMeter.Mark(int64(len(drops))) 1547 1548 for _, tx := range invalids { 1549 hash := tx.Hash() 1550 log.Trace("Demoting pending transaction", "hash", hash) 1551 1552 // Internal shuffle shouldn't touch the lookup set. 1553 pool.enqueueTx(hash, tx, false, false) 1554 } 1555 pendingGauge.Dec(int64(len(olds) + len(drops) + len(invalids))) 1556 if pool.locals.contains(addr) { 1557 localGauge.Dec(int64(len(olds) + len(drops) + len(invalids))) 1558 } 1559 if adjusts.Len() > 0 { 1560 adjusts = types.TxDifference(adjusts, drops) 1561 adjusts = types.TxDifference(adjusts, invalids) 1562 for _, tx := range adjusts { 1563 hash := tx.Hash() 1564 log.Trace("Demoting pending transaction", "hash", hash) 1565 pool.enqueueTx(hash, tx, false, false) 1566 } 1567 } 1568 // If there's a gap in front, alert (should never happen) and postpone all transactions 1569 if list.Len() > 0 && list.txs.Get(nonce) == nil { 1570 gapped := list.Cap(0) 1571 for _, tx := range gapped { 1572 hash := tx.Hash() 1573 log.Error("Demoting invalidated transaction", "hash", hash) 1574 1575 // Internal shuffle shouldn't touch the lookup set. 1576 pool.enqueueTx(hash, tx, false, false) 1577 } 1578 pendingGauge.Dec(int64(len(gapped))) 1579 // This might happen in a reorg, so log it to the metering 1580 blockReorgInvalidatedTx.Mark(int64(len(gapped))) 1581 } 1582 // Delete the entire queue entry if it became empty. 1583 if list.Empty() { 1584 delete(pool.pending, addr) 1585 } 1586 } 1587 } 1588 1589 // addressByHeartbeat is an account address tagged with its last activity timestamp. 1590 type addressByHeartbeat struct { 1591 address common.Address 1592 heartbeat time.Time 1593 } 1594 1595 type addressesByHeartbeat []addressByHeartbeat 1596 1597 func (a addressesByHeartbeat) Len() int { return len(a) } 1598 func (a addressesByHeartbeat) Less(i, j int) bool { return a[i].heartbeat.Before(a[j].heartbeat) } 1599 func (a addressesByHeartbeat) Swap(i, j int) { a[i], a[j] = a[j], a[i] } 1600 1601 // accountSet is simply a set of addresses to check for existence, and a signer 1602 // capable of deriving addresses from transactions. 1603 type accountSet struct { 1604 accounts map[common.Address]struct{} 1605 signer types.Signer 1606 cache *[]common.Address 1607 } 1608 1609 // newAccountSet creates a new address set with an associated signer for sender 1610 // derivations. 1611 func newAccountSet(signer types.Signer, addrs ...common.Address) *accountSet { 1612 as := &accountSet{ 1613 accounts: make(map[common.Address]struct{}), 1614 signer: signer, 1615 } 1616 for _, addr := range addrs { 1617 as.add(addr) 1618 } 1619 return as 1620 } 1621 1622 // contains checks if a given address is contained within the set. 1623 func (as *accountSet) contains(addr common.Address) bool { 1624 _, exist := as.accounts[addr] 1625 return exist 1626 } 1627 1628 func (as *accountSet) empty() bool { 1629 return len(as.accounts) == 0 1630 } 1631 1632 // containsTx checks if the sender of a given tx is within the set. If the sender 1633 // cannot be derived, this method returns false. 1634 func (as *accountSet) containsTx(tx *types.Transaction) bool { 1635 if addr, err := types.Sender(as.signer, tx); err == nil { 1636 return as.contains(addr) 1637 } 1638 return false 1639 } 1640 1641 // add inserts a new address into the set to track. 1642 func (as *accountSet) add(addr common.Address) { 1643 as.accounts[addr] = struct{}{} 1644 as.cache = nil 1645 } 1646 1647 // addTx adds the sender of tx into the set. 1648 func (as *accountSet) addTx(tx *types.Transaction) { 1649 if addr, err := types.Sender(as.signer, tx); err == nil { 1650 as.add(addr) 1651 } 1652 } 1653 1654 // flatten returns the list of addresses within this set, also caching it for later 1655 // reuse. The returned slice should not be changed! 1656 func (as *accountSet) flatten() []common.Address { 1657 if as.cache == nil { 1658 accounts := make([]common.Address, 0, len(as.accounts)) 1659 for account := range as.accounts { 1660 accounts = append(accounts, account) 1661 } 1662 as.cache = &accounts 1663 } 1664 return *as.cache 1665 } 1666 1667 // merge adds all addresses from the 'other' set into 'as'. 1668 func (as *accountSet) merge(other *accountSet) { 1669 for addr := range other.accounts { 1670 as.accounts[addr] = struct{}{} 1671 } 1672 as.cache = nil 1673 } 1674 1675 // txLookup is used internally by TxPool to track transactions while allowing 1676 // lookup without mutex contention. 1677 // 1678 // Note, although this type is properly protected against concurrent access, it 1679 // is **not** a type that should ever be mutated or even exposed outside of the 1680 // transaction pool, since its internal state is tightly coupled with the pools 1681 // internal mechanisms. The sole purpose of the type is to permit out-of-bound 1682 // peeking into the pool in TxPool.Get without having to acquire the widely scoped 1683 // TxPool.mu mutex. 1684 // 1685 // This lookup set combines the notion of "local transactions", which is useful 1686 // to build upper-level structure. 1687 type txLookup struct { 1688 slots int 1689 lock sync.RWMutex 1690 locals map[common.Hash]*types.Transaction 1691 remotes map[common.Hash]*types.Transaction 1692 1693 ticketTxBeats map[common.Hash]time.Time // heartbeat from each buy ticket transactions 1694 } 1695 1696 // newTxLookup returns a new txLookup structure. 1697 func newTxLookup() *txLookup { 1698 return &txLookup{ 1699 locals: make(map[common.Hash]*types.Transaction), 1700 remotes: make(map[common.Hash]*types.Transaction), 1701 ticketTxBeats: make(map[common.Hash]time.Time), 1702 } 1703 } 1704 1705 // Range calls f on each key and value present in the map. The callback passed 1706 // should return the indicator whether the iteration needs to be continued. 1707 // Callers need to specify which set (or both) to be iterated. 1708 func (t *txLookup) Range(f func(hash common.Hash, tx *types.Transaction, local bool) bool, local bool, remote bool) { 1709 t.lock.RLock() 1710 defer t.lock.RUnlock() 1711 1712 if local { 1713 for key, value := range t.locals { 1714 if !f(key, value, true) { 1715 return 1716 } 1717 } 1718 } 1719 if remote { 1720 for key, value := range t.remotes { 1721 if !f(key, value, false) { 1722 return 1723 } 1724 } 1725 } 1726 } 1727 1728 // Get returns a transaction if it exists in the lookup, or nil if not found. 1729 func (t *txLookup) Get(hash common.Hash) *types.Transaction { 1730 t.lock.RLock() 1731 defer t.lock.RUnlock() 1732 1733 if tx := t.locals[hash]; tx != nil { 1734 return tx 1735 } 1736 return t.remotes[hash] 1737 } 1738 1739 // GetLocal returns a transaction if it exists in the lookup, or nil if not found. 1740 func (t *txLookup) GetLocal(hash common.Hash) *types.Transaction { 1741 t.lock.RLock() 1742 defer t.lock.RUnlock() 1743 1744 return t.locals[hash] 1745 } 1746 1747 // GetRemote returns a transaction if it exists in the lookup, or nil if not found. 1748 func (t *txLookup) GetRemote(hash common.Hash) *types.Transaction { 1749 t.lock.RLock() 1750 defer t.lock.RUnlock() 1751 1752 return t.remotes[hash] 1753 } 1754 1755 func (t *txLookup) GetByPredicate(predicate func(*types.Transaction) bool) *types.Transaction { 1756 t.lock.RLock() 1757 defer t.lock.RUnlock() 1758 1759 for _, tx := range t.locals { 1760 if predicate(tx) { 1761 return tx 1762 } 1763 } 1764 for _, tx := range t.remotes { 1765 if predicate(tx) { 1766 return tx 1767 } 1768 } 1769 return nil 1770 } 1771 1772 // Count returns the current number of items in the lookup. 1773 func (t *txLookup) Count() int { 1774 t.lock.RLock() 1775 defer t.lock.RUnlock() 1776 1777 return len(t.locals) + len(t.remotes) 1778 } 1779 1780 // LocalCount returns the current number of local transactions in the lookup. 1781 func (t *txLookup) LocalCount() int { 1782 t.lock.RLock() 1783 defer t.lock.RUnlock() 1784 1785 return len(t.locals) 1786 } 1787 1788 // RemoteCount returns the current number of remote transactions in the lookup. 1789 func (t *txLookup) RemoteCount() int { 1790 t.lock.RLock() 1791 defer t.lock.RUnlock() 1792 1793 return len(t.remotes) 1794 } 1795 1796 // Slots returns the current number of slots used in the lookup. 1797 func (t *txLookup) Slots() int { 1798 t.lock.RLock() 1799 defer t.lock.RUnlock() 1800 1801 return t.slots 1802 } 1803 1804 // Add adds a transaction to the lookup. 1805 func (t *txLookup) Add(tx *types.Transaction, local bool) { 1806 t.lock.Lock() 1807 defer t.lock.Unlock() 1808 1809 t.slots += numSlots(tx) 1810 slotsGauge.Update(int64(t.slots)) 1811 1812 if local { 1813 t.locals[tx.Hash()] = tx 1814 } else { 1815 t.remotes[tx.Hash()] = tx 1816 } 1817 1818 if tx.IsBuyTicketTx() { 1819 t.ticketTxBeats[tx.Hash()] = time.Now() 1820 } 1821 } 1822 1823 // Remove removes a transaction from the lookup. 1824 func (t *txLookup) Remove(hash common.Hash) { 1825 t.lock.Lock() 1826 defer t.lock.Unlock() 1827 1828 tx, ok := t.locals[hash] 1829 if !ok { 1830 tx, ok = t.remotes[hash] 1831 } 1832 if !ok { 1833 log.Error("No transaction found to be deleted", "hash", hash) 1834 return 1835 } 1836 t.slots -= numSlots(tx) 1837 slotsGauge.Update(int64(t.slots)) 1838 1839 delete(t.locals, hash) 1840 delete(t.remotes, hash) 1841 } 1842 1843 // RemoteToLocals migrates the transactions belongs to the given locals to locals 1844 // set. The assumption is held the locals set is thread-safe to be used. 1845 func (t *txLookup) RemoteToLocals(locals *accountSet) int { 1846 t.lock.Lock() 1847 defer t.lock.Unlock() 1848 1849 var migrated int 1850 for hash, tx := range t.remotes { 1851 if locals.containsTx(tx) { 1852 t.locals[hash] = tx 1853 delete(t.remotes, hash) 1854 migrated += 1 1855 } 1856 } 1857 return migrated 1858 } 1859 1860 // RemotesBelowTip finds all remote transactions below the given tip threshold. 1861 func (t *txLookup) RemotesBelowTip(threshold *big.Int) types.Transactions { 1862 found := make(types.Transactions, 0, 128) 1863 t.Range(func(hash common.Hash, tx *types.Transaction, local bool) bool { 1864 if tx.GasTipCapIntCmp(threshold) < 0 { 1865 found = append(found, tx) 1866 } 1867 return true 1868 }, false, true) // Only iterate remotes 1869 return found 1870 } 1871 1872 // numSlots calculates the number of slots needed for a single transaction. 1873 func numSlots(tx *types.Transaction) int { 1874 return int((tx.Size() + txSlotSize - 1) / txSlotSize) 1875 } 1876 1877 func (pool *TxPool) validateAddFsnCallTx(tx *types.Transaction) error { 1878 if err := pool.validateFsnCallTx(tx); err != nil { 1879 return err 1880 } 1881 if tx.IsBuyTicketTx() { 1882 from, _ := types.Sender(pool.signer, tx) // already validated 1883 found := false 1884 var oldTxHash common.Hash 1885 pool.all.Range(func(hash common.Hash, tx1 *types.Transaction, local bool) bool { 1886 if hash == tx.Hash() { 1887 found = true 1888 return false 1889 } else if tx1.IsBuyTicketTx() { 1890 sender, _ := types.Sender(pool.signer, tx1) 1891 if from == sender { 1892 // always choose latest buy ticket tx 1893 oldTxHash = hash 1894 return false 1895 } 1896 } 1897 return true 1898 }, true, true) 1899 if found == true { 1900 return fmt.Errorf("%v has already bought a ticket in txpool", from.String()) 1901 } 1902 if oldTxHash != (common.Hash{}) { 1903 pool.removeTx(oldTxHash, true) 1904 } 1905 } 1906 return nil 1907 } 1908 1909 func (pool *TxPool) validateReceiveAssetPayableTx(tx *types.Transaction, from common.Address) error { 1910 header := pool.chain.CurrentBlock().Header() 1911 height := new(big.Int).Add(header.Number, big.NewInt(1)) 1912 input := tx.Data() 1913 if !common.IsReceiveAssetPayableTx(height, input) { 1914 return nil 1915 } 1916 if pool.currentState.GetCodeSize(*tx.To()) == 0 { 1917 return fmt.Errorf("receiveAsset tx receiver must be contract") 1918 } 1919 timestamp := uint64(time.Now().Unix()) 1920 p := &common.TransferTimeLockParam{} 1921 // use `timestamp+600` here to ensure timelock tx with minimum lifetime of 10 minutes, 1922 // that is endtime of timelock must be greater than or equal to `now + 600 seconds`. 1923 if err := common.ParseReceiveAssetPayableTxInput(p, input, timestamp+600); err != nil { 1924 return err 1925 } 1926 p.Value = tx.Value() 1927 p.GasValue = new(big.Int).Mul(new(big.Int).SetUint64(tx.Gas()), tx.GasPrice()) 1928 if !CanTransferTimeLock(pool.currentState, from, p) { 1929 return ErrInsufficientFunds 1930 } 1931 return nil 1932 } 1933 1934 func (pool *TxPool) validateFsnCallTx(tx *types.Transaction) error { 1935 from, err := types.Sender(pool.signer, tx) 1936 if err != nil { 1937 return fmt.Errorf("validateFsnCallTx err:%v", err) 1938 } 1939 to := tx.To() 1940 1941 if !common.IsFsnCall(to) { 1942 if to == nil { 1943 return nil 1944 } 1945 if err := pool.validateReceiveAssetPayableTx(tx, from); err != nil { 1946 return err 1947 } 1948 return nil 1949 } 1950 1951 currBlockHeader := pool.chain.CurrentBlock().Header() 1952 nextBlockNumber := new(big.Int).Add(currBlockHeader.Number, big.NewInt(1)) 1953 1954 state := pool.currentState 1955 height := common.BigMaxUint64 1956 timestamp := uint64(time.Now().Unix()) 1957 1958 param := common.FSNCallParam{} 1959 if err := rlp.DecodeBytes(tx.Data(), ¶m); err != nil { 1960 return fmt.Errorf("decode FSNCallParam error") 1961 } 1962 1963 fee := common.GetFsnCallFee(to, param.Func) 1964 fsnValue := big.NewInt(0) 1965 1966 switch param.Func { 1967 case common.GenNotationFunc: 1968 if n := state.GetNotation(from); n != 0 { 1969 return fmt.Errorf("Account %s has a notation:%d", from.String(), n) 1970 } 1971 1972 case common.GenAssetFunc: 1973 genAssetParam := common.GenAssetParam{} 1974 rlp.DecodeBytes(param.Data, &genAssetParam) 1975 if err := genAssetParam.Check(height); err != nil { 1976 return err 1977 } 1978 assetID := tx.GetAssetId() 1979 if _, err := state.GetAsset(assetID); err == nil { 1980 return fmt.Errorf("%s asset exists", assetID.String()) 1981 } 1982 1983 case common.SendAssetFunc: 1984 sendAssetParam := common.SendAssetParam{} 1985 rlp.DecodeBytes(param.Data, &sendAssetParam) 1986 if err := sendAssetParam.Check(height); err != nil { 1987 return err 1988 } 1989 if sendAssetParam.AssetID == common.SystemAssetID { 1990 fsnValue = sendAssetParam.Value 1991 } else if state.GetBalance(sendAssetParam.AssetID, from).Cmp(sendAssetParam.Value) < 0 { 1992 return fmt.Errorf("not enough asset") 1993 } 1994 1995 case common.TimeLockFunc: 1996 timeLockParam := common.TimeLockParam{} 1997 rlp.DecodeBytes(param.Data, &timeLockParam) 1998 if timeLockParam.Type == common.TimeLockToAsset { 1999 if timeLockParam.StartTime > timestamp { 2000 return fmt.Errorf("TimeLockToAsset: Start time must be less than now") 2001 } 2002 timeLockParam.EndTime = common.TimeLockForever 2003 } 2004 if timeLockParam.To == (common.Address{}) { 2005 return fmt.Errorf("receiver address must be set and not zero address") 2006 } 2007 if err := timeLockParam.Check(height, timestamp); err != nil { 2008 return err 2009 } 2010 2011 start := timeLockParam.StartTime 2012 end := timeLockParam.EndTime 2013 if start < timestamp { 2014 start = timestamp 2015 } 2016 needValue := common.NewTimeLock(&common.TimeLockItem{ 2017 StartTime: start, 2018 EndTime: end, 2019 Value: new(big.Int).SetBytes(timeLockParam.Value.Bytes()), 2020 }) 2021 if err := needValue.IsValid(); err != nil { 2022 return err 2023 } 2024 switch timeLockParam.Type { 2025 case common.AssetToTimeLock: 2026 if timeLockParam.AssetID == common.SystemAssetID { 2027 fsnValue = timeLockParam.Value 2028 } else if state.GetBalance(timeLockParam.AssetID, from).Cmp(timeLockParam.Value) < 0 { 2029 return fmt.Errorf("AssetToTimeLock: not enough asset") 2030 } 2031 case common.TimeLockToTimeLock: 2032 if state.GetTimeLockBalance(timeLockParam.AssetID, from).Cmp(needValue) < 0 { 2033 return fmt.Errorf("TimeLockToTimeLock: not enough time lock balance") 2034 } 2035 case common.TimeLockToAsset: 2036 if state.GetTimeLockBalance(timeLockParam.AssetID, from).Cmp(needValue) < 0 { 2037 return fmt.Errorf("TimeLockToAsset: not enough time lock balance") 2038 } 2039 case common.SmartTransfer: 2040 if !common.IsSmartTransferEnabled(nextBlockNumber) { 2041 return fmt.Errorf("SendTimeLock not enabled") 2042 } 2043 timeLockBalance := state.GetTimeLockBalance(timeLockParam.AssetID, from) 2044 if timeLockBalance.Cmp(needValue) < 0 { 2045 timeLockValue := timeLockBalance.GetSpendableValue(start, end) 2046 assetBalance := state.GetBalance(timeLockParam.AssetID, from) 2047 if new(big.Int).Add(timeLockValue, assetBalance).Cmp(timeLockParam.Value) < 0 { 2048 return fmt.Errorf("SendTimeLock: not enough balance") 2049 } 2050 fsnValue = new(big.Int).Sub(timeLockParam.Value, timeLockValue) 2051 } 2052 } 2053 2054 case common.BuyTicketFunc: 2055 buyTicketParam := common.BuyTicketParam{} 2056 rlp.DecodeBytes(param.Data, &buyTicketParam) 2057 if err := buyTicketParam.Check(height, currBlockHeader.Time); err != nil { 2058 return err 2059 } 2060 2061 start := buyTicketParam.Start 2062 end := buyTicketParam.End 2063 value := common.TicketPrice(height) 2064 needValue := common.NewTimeLock(&common.TimeLockItem{ 2065 StartTime: common.MaxUint64(start, timestamp), 2066 EndTime: end, 2067 Value: value, 2068 }) 2069 if err := needValue.IsValid(); err != nil { 2070 return err 2071 } 2072 2073 if state.GetTimeLockBalance(common.SystemAssetID, from).Cmp(needValue) < 0 { 2074 fsnValue = value 2075 } 2076 2077 case common.AssetValueChangeFunc: 2078 assetValueChangeParamEx := common.AssetValueChangeExParam{} 2079 rlp.DecodeBytes(param.Data, &assetValueChangeParamEx) 2080 2081 if err := assetValueChangeParamEx.Check(height); err != nil { 2082 return err 2083 } 2084 2085 asset, err := state.GetAsset(assetValueChangeParamEx.AssetID) 2086 if err != nil { 2087 return fmt.Errorf("asset not found") 2088 } 2089 2090 if !asset.CanChange { 2091 return fmt.Errorf("asset can't inc or dec") 2092 } 2093 2094 if asset.Owner != from { 2095 return fmt.Errorf("can only be changed by owner") 2096 } 2097 2098 if asset.Owner != assetValueChangeParamEx.To && !assetValueChangeParamEx.IsInc { 2099 err := fmt.Errorf("decrement can only happen to asset's own account") 2100 return err 2101 } 2102 2103 if !assetValueChangeParamEx.IsInc { 2104 if state.GetBalance(assetValueChangeParamEx.AssetID, assetValueChangeParamEx.To).Cmp(assetValueChangeParamEx.Value) < 0 { 2105 return fmt.Errorf("not enough asset") 2106 } 2107 } 2108 2109 case common.EmptyFunc: 2110 2111 case common.MakeSwapFunc, common.MakeSwapFuncExt: 2112 makeSwapParam := common.MakeSwapParam{} 2113 rlp.DecodeBytes(param.Data, &makeSwapParam) 2114 swapId := tx.GetAssetId() 2115 2116 if _, err := state.GetSwap(swapId); err == nil { 2117 return fmt.Errorf("MakeSwap: %v Swap already exist", swapId.String()) 2118 } 2119 2120 if err := makeSwapParam.Check(height, timestamp); err != nil { 2121 return err 2122 } 2123 2124 if _, err := state.GetAsset(makeSwapParam.ToAssetID); err != nil { 2125 return fmt.Errorf("ToAssetID asset %v not found", makeSwapParam.ToAssetID.String()) 2126 } 2127 2128 if makeSwapParam.FromAssetID == common.OwnerUSANAssetID { 2129 notation := state.GetNotation(from) 2130 if notation == 0 { 2131 return fmt.Errorf("the from address does not have a notation") 2132 } 2133 } else { 2134 total := new(big.Int).Mul(makeSwapParam.MinFromAmount, makeSwapParam.SwapSize) 2135 start := makeSwapParam.FromStartTime 2136 end := makeSwapParam.FromEndTime 2137 useAsset := start == common.TimeLockNow && end == common.TimeLockForever 2138 2139 if useAsset == true { 2140 if makeSwapParam.FromAssetID == common.SystemAssetID { 2141 fsnValue = total 2142 } else if state.GetBalance(makeSwapParam.FromAssetID, from).Cmp(total) < 0 { 2143 return fmt.Errorf("not enough from asset") 2144 } 2145 } else { 2146 needValue := common.NewTimeLock(&common.TimeLockItem{ 2147 StartTime: common.MaxUint64(start, timestamp), 2148 EndTime: end, 2149 Value: total, 2150 }) 2151 if err := needValue.IsValid(); err != nil { 2152 return err 2153 } 2154 available := state.GetTimeLockBalance(makeSwapParam.FromAssetID, from) 2155 if available.Cmp(needValue) < 0 { 2156 if param.Func == common.MakeSwapFunc { 2157 // this was the legacy swap do not do 2158 // time lock and just return an error 2159 return fmt.Errorf("not enough time lock balance") 2160 } 2161 2162 if makeSwapParam.FromAssetID == common.SystemAssetID { 2163 fsnValue = total 2164 } else if state.GetBalance(makeSwapParam.FromAssetID, from).Cmp(total) < 0 { 2165 return fmt.Errorf("not enough time lock or asset balance") 2166 } 2167 } 2168 } 2169 } 2170 2171 case common.RecallSwapFunc: 2172 recallSwapParam := common.RecallSwapParam{} 2173 rlp.DecodeBytes(param.Data, &recallSwapParam) 2174 2175 swap, err := state.GetSwap(recallSwapParam.SwapID) 2176 if err != nil { 2177 return fmt.Errorf("RecallSwap: %v Swap not found", recallSwapParam.SwapID.String()) 2178 } 2179 2180 if swap.Owner != from { 2181 return fmt.Errorf("Must be swap onwer can recall") 2182 } 2183 2184 if err := recallSwapParam.Check(height, &swap); err != nil { 2185 return err 2186 } 2187 2188 case common.TakeSwapFunc, common.TakeSwapFuncExt: 2189 takeSwapParam := common.TakeSwapParam{} 2190 rlp.DecodeBytes(param.Data, &takeSwapParam) 2191 2192 swap, err := state.GetSwap(takeSwapParam.SwapID) 2193 if err != nil { 2194 return fmt.Errorf("TakeSwap: %v Swap not found", takeSwapParam.SwapID.String()) 2195 } 2196 2197 if err := takeSwapParam.Check(height, &swap, timestamp); err != nil { 2198 return err 2199 } 2200 2201 if err := common.CheckSwapTargets(swap.Targes, from); err != nil { 2202 return err 2203 } 2204 2205 if swap.FromAssetID == common.OwnerUSANAssetID { 2206 notation := state.GetNotation(swap.Owner) 2207 if notation == 0 || notation != swap.Notation { 2208 return fmt.Errorf("notation in swap is no longer valid") 2209 } 2210 } 2211 2212 toTotal := new(big.Int).Mul(swap.MinToAmount, takeSwapParam.Size) 2213 toStart := swap.ToStartTime 2214 toEnd := swap.ToEndTime 2215 toUseAsset := toStart == common.TimeLockNow && toEnd == common.TimeLockForever 2216 2217 if toUseAsset == true { 2218 if swap.ToAssetID == common.SystemAssetID { 2219 fsnValue = toTotal 2220 } else if state.GetBalance(swap.ToAssetID, from).Cmp(toTotal) < 0 { 2221 return fmt.Errorf("not enough from asset") 2222 } 2223 } else { 2224 toNeedValue := common.NewTimeLock(&common.TimeLockItem{ 2225 StartTime: common.MaxUint64(toStart, timestamp), 2226 EndTime: toEnd, 2227 Value: toTotal, 2228 }) 2229 isValid := true 2230 if err := toNeedValue.IsValid(); err != nil { 2231 isValid = false 2232 } 2233 if isValid && state.GetTimeLockBalance(swap.ToAssetID, from).Cmp(toNeedValue) < 0 { 2234 if param.Func == common.TakeSwapFunc { 2235 // this was the legacy swap do not do 2236 // time lock and just return an error 2237 return fmt.Errorf("not enough time lock balance") 2238 } 2239 2240 if swap.ToAssetID == common.SystemAssetID { 2241 fsnValue = toTotal 2242 } else if state.GetBalance(swap.ToAssetID, from).Cmp(toTotal) < 0 { 2243 return fmt.Errorf("not enough time lock or asset balance") 2244 } 2245 } 2246 } 2247 2248 case common.RecallMultiSwapFunc: 2249 recallSwapParam := common.RecallMultiSwapParam{} 2250 rlp.DecodeBytes(param.Data, &recallSwapParam) 2251 2252 swap, err := state.GetMultiSwap(recallSwapParam.SwapID) 2253 if err != nil { 2254 return fmt.Errorf("Swap not found") 2255 } 2256 2257 if swap.Owner != from { 2258 return fmt.Errorf("Must be swap onwer can recall") 2259 } 2260 2261 if err := recallSwapParam.Check(height, &swap); err != nil { 2262 return err 2263 } 2264 2265 case common.MakeMultiSwapFunc: 2266 makeSwapParam := common.MakeMultiSwapParam{} 2267 rlp.DecodeBytes(param.Data, &makeSwapParam) 2268 swapID := tx.GetAssetId() 2269 2270 _, err := state.GetSwap(swapID) 2271 if err == nil { 2272 return fmt.Errorf("Swap already exist") 2273 } 2274 2275 if err := makeSwapParam.Check(height, timestamp); err != nil { 2276 return err 2277 } 2278 2279 for _, toAssetID := range makeSwapParam.ToAssetID { 2280 if _, err := state.GetAsset(toAssetID); err != nil { 2281 return fmt.Errorf("ToAssetID asset %v not found", toAssetID.String()) 2282 } 2283 } 2284 2285 ln := len(makeSwapParam.FromAssetID) 2286 2287 useAsset := make([]bool, ln) 2288 total := make([]*big.Int, ln) 2289 needValue := make([]*common.TimeLock, ln) 2290 2291 accountBalances := make(map[common.Hash]*big.Int) 2292 accountTimeLockBalances := make(map[common.Hash]*common.TimeLock) 2293 2294 for i := 0; i < ln; i++ { 2295 if _, exist := accountBalances[makeSwapParam.FromAssetID[i]]; !exist { 2296 balance := state.GetBalance(makeSwapParam.FromAssetID[i], from) 2297 timelock := state.GetTimeLockBalance(makeSwapParam.FromAssetID[i], from) 2298 accountBalances[makeSwapParam.FromAssetID[i]] = new(big.Int).Set(balance) 2299 accountTimeLockBalances[makeSwapParam.FromAssetID[i]] = timelock.Clone() 2300 } 2301 2302 total[i] = new(big.Int).Mul(makeSwapParam.MinFromAmount[i], makeSwapParam.SwapSize) 2303 start := makeSwapParam.FromStartTime[i] 2304 end := makeSwapParam.FromEndTime[i] 2305 useAsset[i] = start == common.TimeLockNow && end == common.TimeLockForever 2306 if useAsset[i] == false { 2307 needValue[i] = common.NewTimeLock(&common.TimeLockItem{ 2308 StartTime: common.MaxUint64(start, timestamp), 2309 EndTime: end, 2310 Value: total[i], 2311 }) 2312 if err := needValue[i].IsValid(); err != nil { 2313 return err 2314 } 2315 } 2316 } 2317 2318 ln = len(makeSwapParam.FromAssetID) 2319 // check balances first 2320 for i := 0; i < ln; i++ { 2321 balance := accountBalances[makeSwapParam.FromAssetID[i]] 2322 timeLockBalance := accountTimeLockBalances[makeSwapParam.FromAssetID[i]] 2323 if useAsset[i] == true { 2324 if balance.Cmp(total[i]) < 0 { 2325 return fmt.Errorf("not enough from asset") 2326 } 2327 balance.Sub(balance, total[i]) 2328 if makeSwapParam.FromAssetID[i] == common.SystemAssetID { 2329 fsnValue.Add(fsnValue, total[i]) 2330 } 2331 } else { 2332 if timeLockBalance.Cmp(needValue[i]) < 0 { 2333 if balance.Cmp(total[i]) < 0 { 2334 return fmt.Errorf("not enough time lock or asset balance") 2335 } 2336 2337 balance.Sub(balance, total[i]) 2338 if makeSwapParam.FromAssetID[i] == common.SystemAssetID { 2339 fsnValue.Add(fsnValue, total[i]) 2340 } 2341 totalValue := common.NewTimeLock(&common.TimeLockItem{ 2342 StartTime: timestamp, 2343 EndTime: common.TimeLockForever, 2344 Value: total[i], 2345 }) 2346 timeLockBalance.Add(timeLockBalance, totalValue) 2347 } 2348 timeLockBalance.Sub(timeLockBalance, needValue[i]) 2349 } 2350 } 2351 2352 case common.TakeMultiSwapFunc: 2353 takeSwapParam := common.TakeMultiSwapParam{} 2354 rlp.DecodeBytes(param.Data, &takeSwapParam) 2355 2356 swap, err := state.GetMultiSwap(takeSwapParam.SwapID) 2357 if err != nil { 2358 return fmt.Errorf("Swap not found") 2359 } 2360 2361 if err := takeSwapParam.Check(height, &swap, timestamp); err != nil { 2362 return err 2363 } 2364 2365 if err := common.CheckSwapTargets(swap.Targes, from); err != nil { 2366 return err 2367 } 2368 2369 lnTo := len(swap.ToAssetID) 2370 2371 toUseAsset := make([]bool, lnTo) 2372 toTotal := make([]*big.Int, lnTo) 2373 toStart := make([]uint64, lnTo) 2374 toEnd := make([]uint64, lnTo) 2375 toNeedValue := make([]*common.TimeLock, lnTo) 2376 2377 accountBalances := make(map[common.Hash]*big.Int) 2378 accountTimeLockBalances := make(map[common.Hash]*common.TimeLock) 2379 2380 for i := 0; i < lnTo; i++ { 2381 if _, exist := accountBalances[swap.ToAssetID[i]]; !exist { 2382 balance := state.GetBalance(swap.ToAssetID[i], from) 2383 timelock := state.GetTimeLockBalance(swap.ToAssetID[i], from) 2384 accountBalances[swap.ToAssetID[i]] = new(big.Int).Set(balance) 2385 accountTimeLockBalances[swap.ToAssetID[i]] = timelock.Clone() 2386 } 2387 2388 toTotal[i] = new(big.Int).Mul(swap.MinToAmount[i], takeSwapParam.Size) 2389 toStart[i] = swap.ToStartTime[i] 2390 toEnd[i] = swap.ToEndTime[i] 2391 toUseAsset[i] = toStart[i] == common.TimeLockNow && toEnd[i] == common.TimeLockForever 2392 if toUseAsset[i] == false { 2393 toNeedValue[i] = common.NewTimeLock(&common.TimeLockItem{ 2394 StartTime: common.MaxUint64(toStart[i], timestamp), 2395 EndTime: toEnd[i], 2396 Value: toTotal[i], 2397 }) 2398 } 2399 } 2400 2401 // check to account balances 2402 for i := 0; i < lnTo; i++ { 2403 balance := accountBalances[swap.ToAssetID[i]] 2404 timeLockBalance := accountTimeLockBalances[swap.ToAssetID[i]] 2405 if toUseAsset[i] == true { 2406 if balance.Cmp(toTotal[i]) < 0 { 2407 return fmt.Errorf("not enough from asset") 2408 } 2409 balance.Sub(balance, toTotal[i]) 2410 if swap.ToAssetID[i] == common.SystemAssetID { 2411 fsnValue.Add(fsnValue, toTotal[i]) 2412 } 2413 } else { 2414 if err := toNeedValue[i].IsValid(); err != nil { 2415 continue 2416 } 2417 if timeLockBalance.Cmp(toNeedValue[i]) < 0 { 2418 if balance.Cmp(toTotal[i]) < 0 { 2419 return fmt.Errorf("not enough time lock or asset balance") 2420 } 2421 2422 balance.Sub(balance, toTotal[i]) 2423 if swap.ToAssetID[i] == common.SystemAssetID { 2424 fsnValue.Add(fsnValue, toTotal[i]) 2425 } 2426 totalValue := common.NewTimeLock(&common.TimeLockItem{ 2427 StartTime: timestamp, 2428 EndTime: common.TimeLockForever, 2429 Value: toTotal[i], 2430 }) 2431 timeLockBalance.Add(timeLockBalance, totalValue) 2432 } 2433 timeLockBalance.Sub(timeLockBalance, toNeedValue[i]) 2434 } 2435 } 2436 2437 case common.ReportIllegalFunc: 2438 if _, _, err := datong.CheckAddingReport(state, param.Data, nil); err != nil { 2439 return err 2440 } 2441 oldtx := pool.GetByPredicate(func(trx *types.Transaction) bool { 2442 if trx == tx { 2443 return false 2444 } 2445 p := common.FSNCallParam{} 2446 rlp.DecodeBytes(trx.Data(), &p) 2447 return param.Func == common.ReportIllegalFunc && bytes.Equal(p.Data, param.Data) 2448 }) 2449 if oldtx != nil { 2450 return fmt.Errorf("already reported in pool") 2451 } 2452 2453 default: 2454 return fmt.Errorf("Unsupported FsnCall func '%v'", param.Func.Name()) 2455 } 2456 // check gas, fee and value 2457 mgval := new(big.Int).Mul(new(big.Int).SetUint64(tx.Gas()), tx.GasPrice()) 2458 mgval.Add(mgval, fee) 2459 mgval.Add(mgval, fsnValue) 2460 if balance := state.GetBalance(common.SystemAssetID, from); balance.Cmp(mgval) < 0 { 2461 return fmt.Errorf("insufficient balance(%v), need %v = (gas:%v * price:%v + value:%v + fee:%v)", balance, mgval, tx.Gas(), tx.GasPrice(), fsnValue, fee) 2462 } 2463 return nil 2464 } 2465 2466 // AddBlacklistAddress Add black list address to the txpool 2467 func (pool *TxPool) AddBlacklistAddress(from common.Address) { 2468 pool.mu.Lock() 2469 defer pool.mu.Unlock() 2470 2471 pool.blacklist[from] = struct{}{} 2472 } 2473 2474 // RemoveBlacklistAddress remove black list address from the txpool 2475 func (pool *TxPool) RemoveBlacklistAddress(from common.Address) { 2476 pool.mu.Lock() 2477 defer pool.mu.Unlock() 2478 2479 delete(pool.blacklist, from) 2480 } 2481 2482 // GetBlacklistAddress return a list of black list address in txpool 2483 func (pool *TxPool) GetBlacklistAddress() []common.Address { 2484 pool.mu.RLock() 2485 defer pool.mu.RUnlock() 2486 2487 list := make([]common.Address, 0, len(pool.blacklist)) 2488 for k := range pool.blacklist { 2489 list = append(list, k) 2490 } 2491 return list 2492 }