Commit b4a52513 authored by Péter Szilágyi's avatar Péter Szilágyi

core: abstract out a sorted transaction hash map

parent a183ea29
This diff is collapsed.
...@@ -41,18 +41,12 @@ func TestStrictTxListAdd(t *testing.T) { ...@@ -41,18 +41,12 @@ func TestStrictTxListAdd(t *testing.T) {
list.Add(txs[v]) list.Add(txs[v])
} }
// Verify internal state // Verify internal state
if list.first != 0 { if len(list.txs.items) != len(txs) {
t.Errorf("lowest nonce mismatch: have %d, want %d", list.first, 0) t.Errorf("transaction count mismatch: have %d, want %d", len(list.txs.items), len(txs))
}
if int(list.last) != len(txs)-1 {
t.Errorf("highest nonce mismatch: have %d, want %d", list.last, len(txs)-1)
}
if len(list.items) != len(txs) {
t.Errorf("transaction count mismatch: have %d, want %d", len(list.items), len(txs))
} }
for i, tx := range txs { for i, tx := range txs {
if list.items[tx.Nonce()] != tx { if list.txs.items[tx.Nonce()] != tx {
t.Errorf("item %d: transaction mismatch: have %v, want %v", i, list.items[tx.Nonce()], tx) t.Errorf("item %d: transaction mismatch: have %v, want %v", i, list.txs.items[tx.Nonce()], tx)
} }
} }
} }
...@@ -154,7 +154,8 @@ func (pool *TxPool) resetState() { ...@@ -154,7 +154,8 @@ func (pool *TxPool) resetState() {
// Update all accounts to the latest known pending nonce // Update all accounts to the latest known pending nonce
for addr, list := range pool.pending { for addr, list := range pool.pending {
pool.pendingState.SetNonce(addr, list.last+1) txs := list.Flatten() // Heavy but will be cached and is needed by the miner anyway
pool.pendingState.SetNonce(addr, txs[len(txs)-1].Nonce()+1)
} }
// Check the queue and move transactions over to the pending if possible // Check the queue and move transactions over to the pending if possible
// or remove those that have become invalid // or remove those that have become invalid
...@@ -366,7 +367,7 @@ func (pool *TxPool) promoteTx(addr common.Address, hash common.Hash, tx *types.T ...@@ -366,7 +367,7 @@ func (pool *TxPool) promoteTx(addr common.Address, hash common.Hash, tx *types.T
// Set the potentially new pending nonce and notify any subsystems of the new tx // Set the potentially new pending nonce and notify any subsystems of the new tx
pool.beats[addr] = time.Now() pool.beats[addr] = time.Now()
pool.pendingState.SetNonce(addr, list.last+1) pool.pendingState.SetNonce(addr, tx.Nonce()+1)
go pool.eventMux.Post(TxPreEvent{tx}) go pool.eventMux.Post(TxPreEvent{tx})
} }
...@@ -439,19 +440,20 @@ func (pool *TxPool) removeTx(hash common.Hash) { ...@@ -439,19 +440,20 @@ func (pool *TxPool) removeTx(hash common.Hash) {
// Remove the transaction from the pending lists and reset the account nonce // Remove the transaction from the pending lists and reset the account nonce
if pending := pool.pending[addr]; pending != nil { if pending := pool.pending[addr]; pending != nil {
if removed, invalids := pending.Remove(tx); removed { if removed, invalids := pending.Remove(tx); removed {
// If no more transactions are left, remove the list and reset the nonce // If no more transactions are left, remove the list
if pending.Empty() { if pending.Empty() {
delete(pool.pending, addr) delete(pool.pending, addr)
delete(pool.beats, addr) delete(pool.beats, addr)
pool.pendingState.SetNonce(addr, tx.Nonce())
} else { } else {
// Otherwise update the nonce and postpone any invalidated transactions // Otherwise postpone any invalidated transactions
pool.pendingState.SetNonce(addr, pending.last)
for _, tx := range invalids { for _, tx := range invalids {
pool.enqueueTx(tx.Hash(), tx) pool.enqueueTx(tx.Hash(), tx)
} }
} }
// Update the account nonce if needed
if nonce := tx.Nonce(); pool.pendingState.GetNonce(addr) > nonce {
pool.pendingState.SetNonce(addr, tx.Nonce())
}
} }
} }
// Transaction is in the future queue // Transaction is in the future queue
......
...@@ -105,7 +105,7 @@ func TestTransactionQueue(t *testing.T) { ...@@ -105,7 +105,7 @@ func TestTransactionQueue(t *testing.T) {
currentState.SetNonce(from, 2) currentState.SetNonce(from, 2)
pool.enqueueTx(tx.Hash(), tx) pool.enqueueTx(tx.Hash(), tx)
pool.promoteExecutables() pool.promoteExecutables()
if _, ok := pool.pending[from].items[tx.Nonce()]; ok { if _, ok := pool.pending[from].txs.items[tx.Nonce()]; ok {
t.Error("expected transaction to be in tx pool") t.Error("expected transaction to be in tx pool")
} }
...@@ -224,7 +224,7 @@ func TestTransactionDoubleNonce(t *testing.T) { ...@@ -224,7 +224,7 @@ func TestTransactionDoubleNonce(t *testing.T) {
if pool.pending[addr].Len() != 1 { if pool.pending[addr].Len() != 1 {
t.Error("expected 1 pending transactions, got", pool.pending[addr].Len()) t.Error("expected 1 pending transactions, got", pool.pending[addr].Len())
} }
if tx := pool.pending[addr].items[0]; tx.Hash() != tx2.Hash() { if tx := pool.pending[addr].txs.items[0]; tx.Hash() != tx2.Hash() {
t.Errorf("transaction mismatch: have %x, want %x", tx.Hash(), tx2.Hash()) t.Errorf("transaction mismatch: have %x, want %x", tx.Hash(), tx2.Hash())
} }
// Add the thid transaction and ensure it's not saved (smaller price) // Add the thid transaction and ensure it's not saved (smaller price)
...@@ -235,7 +235,7 @@ func TestTransactionDoubleNonce(t *testing.T) { ...@@ -235,7 +235,7 @@ func TestTransactionDoubleNonce(t *testing.T) {
if pool.pending[addr].Len() != 1 { if pool.pending[addr].Len() != 1 {
t.Error("expected 1 pending transactions, got", pool.pending[addr].Len()) t.Error("expected 1 pending transactions, got", pool.pending[addr].Len())
} }
if tx := pool.pending[addr].items[0]; tx.Hash() != tx2.Hash() { if tx := pool.pending[addr].txs.items[0]; tx.Hash() != tx2.Hash() {
t.Errorf("transaction mismatch: have %x, want %x", tx.Hash(), tx2.Hash()) t.Errorf("transaction mismatch: have %x, want %x", tx.Hash(), tx2.Hash())
} }
// Ensure the total transaction count is correct // Ensure the total transaction count is correct
...@@ -346,16 +346,16 @@ func TestTransactionDropping(t *testing.T) { ...@@ -346,16 +346,16 @@ func TestTransactionDropping(t *testing.T) {
state.AddBalance(account, big.NewInt(-750)) state.AddBalance(account, big.NewInt(-750))
pool.resetState() pool.resetState()
if _, ok := pool.pending[account].items[tx0.Nonce()]; !ok { if _, ok := pool.pending[account].txs.items[tx0.Nonce()]; !ok {
t.Errorf("funded pending transaction missing: %v", tx0) t.Errorf("funded pending transaction missing: %v", tx0)
} }
if _, ok := pool.pending[account].items[tx1.Nonce()]; ok { if _, ok := pool.pending[account].txs.items[tx1.Nonce()]; ok {
t.Errorf("out-of-fund pending transaction present: %v", tx1) t.Errorf("out-of-fund pending transaction present: %v", tx1)
} }
if _, ok := pool.queue[account].items[tx10.Nonce()]; !ok { if _, ok := pool.queue[account].txs.items[tx10.Nonce()]; !ok {
t.Errorf("funded queued transaction missing: %v", tx10) t.Errorf("funded queued transaction missing: %v", tx10)
} }
if _, ok := pool.queue[account].items[tx11.Nonce()]; ok { if _, ok := pool.queue[account].txs.items[tx11.Nonce()]; ok {
t.Errorf("out-of-fund queued transaction present: %v", tx11) t.Errorf("out-of-fund queued transaction present: %v", tx11)
} }
if len(pool.all) != 2 { if len(pool.all) != 2 {
...@@ -410,25 +410,25 @@ func TestTransactionPostponing(t *testing.T) { ...@@ -410,25 +410,25 @@ func TestTransactionPostponing(t *testing.T) {
state.AddBalance(account, big.NewInt(-750)) state.AddBalance(account, big.NewInt(-750))
pool.resetState() pool.resetState()
if _, ok := pool.pending[account].items[txns[0].Nonce()]; !ok { if _, ok := pool.pending[account].txs.items[txns[0].Nonce()]; !ok {
t.Errorf("tx %d: valid and funded transaction missing from pending pool: %v", 0, txns[0]) t.Errorf("tx %d: valid and funded transaction missing from pending pool: %v", 0, txns[0])
} }
if _, ok := pool.queue[account].items[txns[0].Nonce()]; ok { if _, ok := pool.queue[account].txs.items[txns[0].Nonce()]; ok {
t.Errorf("tx %d: valid and funded transaction present in future queue: %v", 0, txns[0]) t.Errorf("tx %d: valid and funded transaction present in future queue: %v", 0, txns[0])
} }
for i, tx := range txns[1:] { for i, tx := range txns[1:] {
if i%2 == 1 { if i%2 == 1 {
if _, ok := pool.pending[account].items[tx.Nonce()]; ok { if _, ok := pool.pending[account].txs.items[tx.Nonce()]; ok {
t.Errorf("tx %d: valid but future transaction present in pending pool: %v", i+1, tx) t.Errorf("tx %d: valid but future transaction present in pending pool: %v", i+1, tx)
} }
if _, ok := pool.queue[account].items[tx.Nonce()]; !ok { if _, ok := pool.queue[account].txs.items[tx.Nonce()]; !ok {
t.Errorf("tx %d: valid but future transaction missing from future queue: %v", i+1, tx) t.Errorf("tx %d: valid but future transaction missing from future queue: %v", i+1, tx)
} }
} else { } else {
if _, ok := pool.pending[account].items[tx.Nonce()]; ok { if _, ok := pool.pending[account].txs.items[tx.Nonce()]; ok {
t.Errorf("tx %d: out-of-fund transaction present in pending pool: %v", i+1, tx) t.Errorf("tx %d: out-of-fund transaction present in pending pool: %v", i+1, tx)
} }
if _, ok := pool.queue[account].items[tx.Nonce()]; ok { if _, ok := pool.queue[account].txs.items[tx.Nonce()]; ok {
t.Errorf("tx %d: out-of-fund transaction present in future queue: %v", i+1, tx) t.Errorf("tx %d: out-of-fund transaction present in future queue: %v", i+1, tx)
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment