// checkQueue moves transactions that have become processable to main pool. func (pool *TxPool) checkQueue() { state := pool.pendingState var addq txQueue for address, txs := range pool.queue { // guessed nonce is the nonce currently kept by the tx pool (pending state) guessedNonce := state.GetNonce(address) // true nonce is the nonce known by the last state trueNonce := pool.currentState().GetNonce(address) addq := addq[:0] for hash, tx := range txs { if tx.Nonce() < trueNonce { // Drop queued transactions whose nonce is lower than // the account nonce because they have been processed. delete(txs, hash) } else { // Collect the remaining transactions for the next pass. addq = append(addq, txQueueEntry{hash, address, tx}) } } // Find the next consecutive nonce range starting at the // current account nonce. sort.Sort(addq) for i, e := range addq { // start deleting the transactions from the queue if they exceed the limit if i > maxQueued { delete(pool.queue[address], e.hash) continue } if e.Nonce() > guessedNonce { if len(addq)-i > maxQueued { if glog.V(logger.Debug) { glog.Infof("Queued tx limit exceeded for %s. Tx %s removed\n", common.PP(address[:]), common.PP(e.hash[:])) } for j := i + maxQueued; j < len(addq); j++ { delete(txs, addq[j].hash) } } break } delete(txs, e.hash) pool.addTx(e.hash, address, e.Transaction) } // Delete the entire queue entry if it became empty. if len(txs) == 0 { delete(pool.queue, address) } } }
// WriteBlock writes a block to the database func WriteBlock(db common.Database, block *types.Block) error { tstart := time.Now() enc, _ := rlp.EncodeToBytes((*types.StorageBlock)(block)) key := append(blockHashPre, block.Hash().Bytes()...) err := db.Put(key, enc) if err != nil { glog.Fatal("db write fail:", err) return err } if glog.V(logger.Debug) { glog.Infof("wrote block #%v %s. Took %v\n", block.Number(), common.PP(block.Hash().Bytes()), time.Since(tstart)) } return nil }
// checkQueue moves transactions that have become processable to main pool. func (pool *TxPool) checkQueue() { // init delayed since tx pool could have been started before any state sync if pool.pendingState == nil { pool.resetState() } var promote txQueue for address, txs := range pool.queue { currentState, err := pool.currentState() if err != nil { glog.Errorf("could not get current state: %v", err) return } balance := currentState.GetBalance(address) var ( guessedNonce = pool.pendingState.GetNonce(address) // nonce currently kept by the tx pool (pending state) trueNonce = currentState.GetNonce(address) // nonce known by the last state ) promote = promote[:0] for hash, tx := range txs { // Drop processed or out of fund transactions if tx.Nonce() < trueNonce || balance.Cmp(tx.Cost()) < 0 { if glog.V(logger.Core) { glog.Infof("removed tx (%v) from pool queue: low tx nonce or out of funds\n", tx) } delete(txs, hash) continue } // Collect the remaining transactions for the next pass. promote = append(promote, txQueueEntry{hash, address, tx}) } // Find the next consecutive nonce range starting at the current account nonce, // pushing the guessed nonce forward if we add consecutive transactions. sort.Sort(promote) for i, entry := range promote { // If we reached a gap in the nonces, enforce transaction limit and stop if entry.Nonce() > guessedNonce { if len(promote)-i > maxQueued { if glog.V(logger.Debug) { glog.Infof("Queued tx limit exceeded for %s. Tx %s removed\n", common.PP(address[:]), common.PP(entry.hash[:])) } for _, drop := range promote[i+maxQueued:] { delete(txs, drop.hash) } } break } // Otherwise promote the transaction and move the guess nonce if needed pool.addTx(entry.hash, address, entry.Transaction) delete(txs, entry.hash) if entry.Nonce() == guessedNonce { guessedNonce++ } } // Delete the entire queue entry if it became empty. if len(txs) == 0 { delete(pool.queue, address) } } }