core/types, miner: avoid tx sender miscaching (#14773)

This commit is contained in:
Mark 2017-09-07 16:22:27 -05:00 committed by Felix Lange
parent e3db1236de
commit c1740e4540
3 changed files with 15 additions and 13 deletions

View File

@ -383,18 +383,21 @@ func (s *TxByPrice) Pop() interface{} {
type TransactionsByPriceAndNonce struct { type TransactionsByPriceAndNonce struct {
txs map[common.Address]Transactions // Per account nonce-sorted list of transactions txs map[common.Address]Transactions // Per account nonce-sorted list of transactions
heads TxByPrice // Next transaction for each unique account (price heap) heads TxByPrice // Next transaction for each unique account (price heap)
signer Signer // Signer for the set of transactions
} }
// NewTransactionsByPriceAndNonce creates a transaction set that can retrieve // NewTransactionsByPriceAndNonce creates a transaction set that can retrieve
// price sorted transactions in a nonce-honouring way. // price sorted transactions in a nonce-honouring way.
// //
// Note, the input map is reowned so the caller should not interact any more with // Note, the input map is reowned so the caller should not interact any more with
// if after providng it to the constructor. // if after providing it to the constructor.
func NewTransactionsByPriceAndNonce(txs map[common.Address]Transactions) *TransactionsByPriceAndNonce { func NewTransactionsByPriceAndNonce(signer Signer, txs map[common.Address]Transactions) *TransactionsByPriceAndNonce {
// Initialize a price based heap with the head transactions // Initialize a price based heap with the head transactions
heads := make(TxByPrice, 0, len(txs)) heads := make(TxByPrice, 0, len(txs))
for acc, accTxs := range txs { for _, accTxs := range txs {
heads = append(heads, accTxs[0]) heads = append(heads, accTxs[0])
// Ensure the sender address is from the signer
acc, _ := Sender(signer, accTxs[0])
txs[acc] = accTxs[1:] txs[acc] = accTxs[1:]
} }
heap.Init(&heads) heap.Init(&heads)
@ -403,6 +406,7 @@ func NewTransactionsByPriceAndNonce(txs map[common.Address]Transactions) *Transa
return &TransactionsByPriceAndNonce{ return &TransactionsByPriceAndNonce{
txs: txs, txs: txs,
heads: heads, heads: heads,
signer: signer,
} }
} }
@ -416,9 +420,7 @@ func (t *TransactionsByPriceAndNonce) Peek() *Transaction {
// Shift replaces the current best head with the next one from the same account. // Shift replaces the current best head with the next one from the same account.
func (t *TransactionsByPriceAndNonce) Shift() { func (t *TransactionsByPriceAndNonce) Shift() {
signer := deriveSigner(t.heads[0].data.V) acc, _ := Sender(t.signer, t.heads[0])
// derive signer but don't cache.
acc, _ := Sender(signer, t.heads[0]) // we only sort valid txs so this cannot fail
if txs, ok := t.txs[acc]; ok && len(txs) > 0 { if txs, ok := t.txs[acc]; ok && len(txs) > 0 {
t.heads[0], t.txs[acc] = txs[0], txs[1:] t.heads[0], t.txs[acc] = txs[0], txs[1:]
heap.Fix(&t.heads, 0) heap.Fix(&t.heads, 0)

View File

@ -143,7 +143,7 @@ func TestTransactionPriceNonceSort(t *testing.T) {
} }
} }
// Sort the transactions and cross check the nonce ordering // Sort the transactions and cross check the nonce ordering
txset := NewTransactionsByPriceAndNonce(groups) txset := NewTransactionsByPriceAndNonce(signer, groups)
txs := Transactions{} txs := Transactions{}
for { for {

View File

@ -268,7 +268,7 @@ func (self *worker) update() {
self.currentMu.Lock() self.currentMu.Lock()
acc, _ := types.Sender(self.current.signer, ev.Tx) acc, _ := types.Sender(self.current.signer, ev.Tx)
txs := map[common.Address]types.Transactions{acc: {ev.Tx}} txs := map[common.Address]types.Transactions{acc: {ev.Tx}}
txset := types.NewTransactionsByPriceAndNonce(txs) txset := types.NewTransactionsByPriceAndNonce(self.current.signer, txs)
self.current.commitTransactions(self.mux, txset, self.chain, self.coinbase) self.current.commitTransactions(self.mux, txset, self.chain, self.coinbase)
self.currentMu.Unlock() self.currentMu.Unlock()
@ -471,7 +471,7 @@ func (self *worker) commitNewWork() {
log.Error("Failed to fetch pending transactions", "err", err) log.Error("Failed to fetch pending transactions", "err", err)
return return
} }
txs := types.NewTransactionsByPriceAndNonce(pending) txs := types.NewTransactionsByPriceAndNonce(self.current.signer, pending)
work.commitTransactions(self.mux, txs, self.chain, self.coinbase) work.commitTransactions(self.mux, txs, self.chain, self.coinbase)
// compute uncles for the new block. // compute uncles for the new block.