mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-07 23:48:36 +00:00
core/types/bal: enforce strict tx index ordering in validation
Replace slices.IsSortedFunc checks with explicit ascending loops so duplicate consecutive indices are rejected. Add regression tests for balance, nonce, and code change lists.
This commit is contained in:
parent
aaa2b66285
commit
c195132aad
2 changed files with 77 additions and 12 deletions
|
|
@ -180,24 +180,24 @@ func (e *AccountAccess) validate(rules params.Rules) error {
|
|||
}
|
||||
|
||||
// Check the balance changes are sorted in order
|
||||
if !slices.IsSortedFunc(e.BalanceChanges, func(a, b encodingBalanceChange) int {
|
||||
return cmp.Compare[uint32](a.TxIdx, b.TxIdx)
|
||||
}) {
|
||||
return errors.New("balance changes not in ascending order by tx index")
|
||||
for i := 1; i < len(e.BalanceChanges); i++ {
|
||||
if e.BalanceChanges[i-1].TxIdx >= e.BalanceChanges[i].TxIdx {
|
||||
return errors.New("balance changes not in ascending order by tx index")
|
||||
}
|
||||
}
|
||||
|
||||
// Check the nonce changes are sorted in order
|
||||
if !slices.IsSortedFunc(e.NonceChanges, func(a, b encodingAccountNonce) int {
|
||||
return cmp.Compare[uint32](a.TxIdx, b.TxIdx)
|
||||
}) {
|
||||
return errors.New("nonce changes not in ascending order by tx index")
|
||||
for i := 1; i < len(e.NonceChanges); i++ {
|
||||
if e.NonceChanges[i-1].TxIdx >= e.NonceChanges[i].TxIdx {
|
||||
return errors.New("nonce changes not in ascending order by tx index")
|
||||
}
|
||||
}
|
||||
|
||||
// Check the code changes are sorted in order
|
||||
if !slices.IsSortedFunc(e.CodeChanges, func(a, b encodingCodeChange) int {
|
||||
return cmp.Compare[uint32](a.TxIndex, b.TxIndex)
|
||||
}) {
|
||||
return errors.New("code changes not in ascending order by tx index")
|
||||
for i := 1; i < len(e.CodeChanges); i++ {
|
||||
if e.CodeChanges[i-1].TxIndex >= e.CodeChanges[i].TxIndex {
|
||||
return errors.New("code changes not in ascending order by tx index")
|
||||
}
|
||||
}
|
||||
for _, change := range e.CodeChanges {
|
||||
var sizeLimit int
|
||||
|
|
|
|||
|
|
@ -231,6 +231,71 @@ func TestBlockAccessListCopy(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestBlockAccessListValidateDuplicateBalanceTxIdxRejects verifies that adjacent
|
||||
// balance changes with equal tx indices are rejected. Ordering used to rely on
|
||||
// slices.IsSortedFunc, which treats equal consecutive keys as sorted; the
|
||||
// explicit loop requires strict ascent (no duplicates).
|
||||
func TestBlockAccessListValidateDuplicateBalanceTxIdxRejects(t *testing.T) {
|
||||
list := BlockAccessList{
|
||||
{
|
||||
BalanceChanges: []encodingBalanceChange{
|
||||
{TxIdx: 1, Balance: uint256.NewInt(1)},
|
||||
{TxIdx: 1, Balance: uint256.NewInt(2)},
|
||||
},
|
||||
},
|
||||
}
|
||||
err := list.Validate(params.Rules{})
|
||||
if err == nil {
|
||||
t.Fatal("expected validation error for duplicate balance change tx indices")
|
||||
}
|
||||
want := "balance changes not in ascending order by tx index"
|
||||
if got := err.Error(); got != want {
|
||||
t.Fatalf("wrong error: got %q, want %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// TestBlockAccessListValidateDuplicateNonceTxIdxRejects is the nonce analogue of
|
||||
// TestBlockAccessListValidateDuplicateBalanceTxIdxRejects.
|
||||
func TestBlockAccessListValidateDuplicateNonceTxIdxRejects(t *testing.T) {
|
||||
list := BlockAccessList{
|
||||
{
|
||||
NonceChanges: []encodingAccountNonce{
|
||||
{TxIdx: 2, Nonce: 10},
|
||||
{TxIdx: 2, Nonce: 11},
|
||||
},
|
||||
},
|
||||
}
|
||||
err := list.Validate(params.Rules{})
|
||||
if err == nil {
|
||||
t.Fatal("expected validation error for duplicate nonce change tx indices")
|
||||
}
|
||||
want := "nonce changes not in ascending order by tx index"
|
||||
if got := err.Error(); got != want {
|
||||
t.Fatalf("wrong error: got %q, want %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// TestBlockAccessListValidateDuplicateCodeTxIndexRejects is the code-change
|
||||
// analogue of TestBlockAccessListValidateDuplicateBalanceTxIdxRejects.
|
||||
func TestBlockAccessListValidateDuplicateCodeTxIndexRejects(t *testing.T) {
|
||||
list := BlockAccessList{
|
||||
{
|
||||
CodeChanges: []encodingCodeChange{
|
||||
{TxIndex: 3, Code: nil},
|
||||
{TxIndex: 3, Code: []byte{0x00}},
|
||||
},
|
||||
},
|
||||
}
|
||||
err := list.Validate(params.Rules{})
|
||||
if err == nil {
|
||||
t.Fatal("expected validation error for duplicate code change tx indices")
|
||||
}
|
||||
want := "code changes not in ascending order by tx index"
|
||||
if got := err.Error(); got != want {
|
||||
t.Fatalf("wrong error: got %q, want %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBlockAccessListValidation(t *testing.T) {
|
||||
// Validate the block access list after RLP decoding
|
||||
enc := makeTestBAL(true)
|
||||
|
|
|
|||
Loading…
Reference in a new issue