Skip to content

Commit 5e8ea76

Browse files
committed
core/types: separate special transactions correctly
- Refactor NewTransactionsByPriceAndNonce to properly filter and separate special transactions (IsSpecialTransaction) - Remove account from txs map if it has no normal transactions left - Update comments for clarity
1 parent 292c050 commit 5e8ea76

File tree

2 files changed

+84
-8
lines changed

2 files changed

+84
-8
lines changed

core/types/transaction.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -785,19 +785,20 @@ func NewTransactionsByPriceAndNonce(signer Signer, txs map[common.Address]Transa
785785
for _, accTxs := range txs {
786786
from, _ := Sender(signer, accTxs[0])
787787
var normalTxs Transactions
788-
lastSpecialTx := -1
789-
if lastSpecialTx >= 0 {
790-
for i := 0; i <= lastSpecialTx; i++ {
791-
specialTxs = append(specialTxs, accTxs[i])
788+
for _, tx := range accTxs {
789+
if tx.IsSpecialTransaction() {
790+
specialTxs = append(specialTxs, tx)
791+
} else {
792+
normalTxs = append(normalTxs, tx)
792793
}
793-
normalTxs = accTxs[lastSpecialTx+1:]
794-
} else {
795-
normalTxs = accTxs
796794
}
797795
if len(normalTxs) > 0 {
798796
heads.txs = append(heads.txs, normalTxs[0])
799-
// Ensure the sender address is from the signer
797+
// Remove the first normal transaction for this sender
800798
txs[from] = normalTxs[1:]
799+
} else {
800+
// Remove the account if there are no normal transactions
801+
delete(txs, from)
801802
}
802803
}
803804
heap.Init(&heads)

core/types/transaction_test.go

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -718,3 +718,78 @@ func TestIsNonEVMTx(t *testing.T) {
718718
})
719719
}
720720
}
721+
722+
// TestNewTransactionsByPriceAndNonce_SpecialSeparation uses table-driven tests to verify separation of special and normal transactions.
723+
func TestNewTransactionsByPriceAndNonce_SpecialSeparation(t *testing.T) {
724+
signer := HomesteadSigner{}
725+
726+
genNormalTx := func(nonce uint64, key *ecdsa.PrivateKey) *Transaction {
727+
tx, _ := SignTx(NewTransaction(nonce, common.HexToAddress("0x1234567890123456789012345678901234567890"), big.NewInt(1), 21000, big.NewInt(1), nil), signer, key)
728+
return tx
729+
}
730+
genSpecialTx := func(nonce uint64, key *ecdsa.PrivateKey) *Transaction {
731+
tx, _ := SignTx(NewTransaction(nonce, common.BlockSignersBinary, big.NewInt(1), 21000, big.NewInt(1), nil), signer, key)
732+
return tx
733+
}
734+
735+
testCases := []struct {
736+
name string
737+
normalCount int
738+
specialCount int
739+
expectNormal int
740+
expectSpecial int
741+
}{
742+
{"no transactions", 0, 0, 0, 0},
743+
{"only 1 normal", 1, 0, 1, 0},
744+
{"only 2 normal", 2, 0, 2, 0},
745+
{"only 3 normal", 3, 0, 3, 0},
746+
{"only 1 special", 0, 1, 0, 1},
747+
{"only 2 special", 0, 2, 0, 2},
748+
{"only 3 special", 0, 3, 0, 3},
749+
{"1 normal, 1 special", 1, 1, 1, 1},
750+
{"2 normal, 2 special", 2, 2, 2, 2},
751+
{"3 normal, 3 special", 3, 3, 3, 3},
752+
}
753+
754+
for _, tc := range testCases {
755+
t.Run(tc.name, func(t *testing.T) {
756+
key, _ := crypto.GenerateKey()
757+
addr := crypto.PubkeyToAddress(key.PublicKey)
758+
txs := make(Transactions, 0, tc.normalCount+tc.specialCount)
759+
for i := 0; i < tc.normalCount; i++ {
760+
txs = append(txs, genNormalTx(uint64(i), key))
761+
}
762+
for i := 0; i < tc.specialCount; i++ {
763+
txs = append(txs, genSpecialTx(uint64(tc.normalCount+i), key))
764+
}
765+
group := map[common.Address]Transactions{}
766+
if len(txs) > 0 {
767+
group[addr] = txs
768+
}
769+
txset, specialTxs := NewTransactionsByPriceAndNonce(signer, group, map[common.Address]*big.Int{})
770+
771+
// Check special transactions
772+
if len(specialTxs) != tc.expectSpecial {
773+
t.Errorf("expected %d special txs, got %d", tc.expectSpecial, len(specialTxs))
774+
}
775+
for _, tx := range specialTxs {
776+
if tx.To() == nil || *tx.To() != common.BlockSignersBinary {
777+
t.Errorf("specialTxs contains non-special tx: %v", tx)
778+
}
779+
}
780+
781+
// Check normal transactions
782+
normalCount := 0
783+
for tx := txset.Peek(); tx != nil; tx = txset.Peek() {
784+
if tx.To() == nil || *tx.To() == common.BlockSignersBinary {
785+
t.Errorf("txset contains special or nil-to tx: %v", tx)
786+
}
787+
normalCount++
788+
txset.Shift()
789+
}
790+
if normalCount != tc.expectNormal {
791+
t.Errorf("expected %d normal txs, got %d", tc.expectNormal, normalCount)
792+
}
793+
})
794+
}
795+
}

0 commit comments

Comments
 (0)