core: reset txpool state on sethead (#22247)

fixes an issue where local transactions that were included in the chain before a SetHead were rejected if resubmitted, since the txpool had not reset the state to the current (older) state.
This commit is contained in:
Marius van der Wijden 2021-02-03 11:02:35 +01:00 committed by GitHub
parent 83e4c49e2b
commit 3512b41c5c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1137,44 +1137,45 @@ func (pool *TxPool) reset(oldHead, newHead *types.Header) {
// head from the chain. // head from the chain.
// If that is the case, we don't have the lost transactions any more, and // If that is the case, we don't have the lost transactions any more, and
// there's nothing to add // there's nothing to add
if newNum < oldNum { if newNum >= oldNum {
// If the reorg ended up on a lower number, it's indicative of setHead being the cause
log.Debug("Skipping transaction reset caused by setHead",
"old", oldHead.Hash(), "oldnum", oldNum, "new", newHead.Hash(), "newnum", newNum)
} else {
// If we reorged to a same or higher number, then it's not a case of setHead // If we reorged to a same or higher number, then it's not a case of setHead
log.Warn("Transaction pool reset with missing oldhead", log.Warn("Transaction pool reset with missing oldhead",
"old", oldHead.Hash(), "oldnum", oldNum, "new", newHead.Hash(), "newnum", newNum) "old", oldHead.Hash(), "oldnum", oldNum, "new", newHead.Hash(), "newnum", newNum)
}
return
}
for rem.NumberU64() > add.NumberU64() {
discarded = append(discarded, rem.Transactions()...)
if rem = pool.chain.GetBlock(rem.ParentHash(), rem.NumberU64()-1); rem == nil {
log.Error("Unrooted old chain seen by tx pool", "block", oldHead.Number, "hash", oldHead.Hash())
return return
} }
} // If the reorg ended up on a lower number, it's indicative of setHead being the cause
for add.NumberU64() > rem.NumberU64() { log.Debug("Skipping transaction reset caused by setHead",
included = append(included, add.Transactions()...) "old", oldHead.Hash(), "oldnum", oldNum, "new", newHead.Hash(), "newnum", newNum)
if add = pool.chain.GetBlock(add.ParentHash(), add.NumberU64()-1); add == nil { // We still need to update the current state s.th. the lost transactions can be readded by the user
log.Error("Unrooted new chain seen by tx pool", "block", newHead.Number, "hash", newHead.Hash()) } else {
return for rem.NumberU64() > add.NumberU64() {
discarded = append(discarded, rem.Transactions()...)
if rem = pool.chain.GetBlock(rem.ParentHash(), rem.NumberU64()-1); rem == nil {
log.Error("Unrooted old chain seen by tx pool", "block", oldHead.Number, "hash", oldHead.Hash())
return
}
} }
} for add.NumberU64() > rem.NumberU64() {
for rem.Hash() != add.Hash() { included = append(included, add.Transactions()...)
discarded = append(discarded, rem.Transactions()...) if add = pool.chain.GetBlock(add.ParentHash(), add.NumberU64()-1); add == nil {
if rem = pool.chain.GetBlock(rem.ParentHash(), rem.NumberU64()-1); rem == nil { log.Error("Unrooted new chain seen by tx pool", "block", newHead.Number, "hash", newHead.Hash())
log.Error("Unrooted old chain seen by tx pool", "block", oldHead.Number, "hash", oldHead.Hash()) return
return }
} }
included = append(included, add.Transactions()...) for rem.Hash() != add.Hash() {
if add = pool.chain.GetBlock(add.ParentHash(), add.NumberU64()-1); add == nil { discarded = append(discarded, rem.Transactions()...)
log.Error("Unrooted new chain seen by tx pool", "block", newHead.Number, "hash", newHead.Hash()) if rem = pool.chain.GetBlock(rem.ParentHash(), rem.NumberU64()-1); rem == nil {
return log.Error("Unrooted old chain seen by tx pool", "block", oldHead.Number, "hash", oldHead.Hash())
return
}
included = append(included, add.Transactions()...)
if add = pool.chain.GetBlock(add.ParentHash(), add.NumberU64()-1); add == nil {
log.Error("Unrooted new chain seen by tx pool", "block", newHead.Number, "hash", newHead.Hash())
return
}
} }
reinject = types.TxDifference(discarded, included)
} }
reinject = types.TxDifference(discarded, included)
} }
} }
// Initialize the internal state to the current head // Initialize the internal state to the current head