*: use slices package for sorting and searching

Signed-off-by: Roman Khimov <roman@nspcc.ru>
This commit is contained in:
Roman Khimov 2024-08-26 20:28:35 +03:00
parent 6581bd47fc
commit a1a7e3d708
30 changed files with 158 additions and 181 deletions

View file

@ -2,9 +2,10 @@ package query
import (
"bytes"
"cmp"
"encoding/base64"
"fmt"
"sort"
"slices"
"strconv"
"strings"
"text/tabwriter"
@ -192,14 +193,18 @@ func queryCandidates(ctx *cli.Context) error {
return cli.Exit(err, 1)
}
sort.Slice(vals, func(i, j int) bool {
if vals[i].Active != vals[j].Active {
return vals[i].Active
slices.SortFunc(vals, func(a, b result.Candidate) int {
if a.Active && !b.Active {
return 1
}
if vals[i].Votes != vals[j].Votes {
return vals[i].Votes > vals[j].Votes
if !a.Active && b.Active {
return -1
}
return vals[i].PublicKey.Cmp(&vals[j].PublicKey) == -1
res := cmp.Compare(a.Votes, b.Votes)
if res != 0 {
return res
}
return a.PublicKey.Cmp(&b.PublicKey)
})
var res []byte
res = fmt.Appendf(res, "Key\tVotes\tCommittee\tConsensus\n")

View file

@ -1,6 +1,7 @@
package compiler
import (
"cmp"
"encoding/binary"
"errors"
"fmt"
@ -10,7 +11,7 @@ import (
"go/types"
"math"
"math/big"
"sort"
"slices"
"strings"
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
@ -2253,7 +2254,7 @@ func (c *codegen) compile(info *buildInfo, pkg *packages.Package) error {
for _, p := range info.program {
keys = append(keys, p.Types)
}
sort.Slice(keys, func(i, j int) bool { return keys[i].Path() < keys[j].Path() })
slices.SortFunc(keys, func(a, b *types.Package) int { return cmp.Compare(a.Path(), b.Path()) })
// Generate the code for the program.
c.ForEachFile(func(f *ast.File, pkg *types.Package) {
@ -2535,9 +2536,7 @@ func removeNOPs(b []byte, nopOffsets []int, sequencePoints map[string][]DebugSeq
func calcOffsetCorrection(ip, target int, offsets []int) int {
cnt := 0
start := sort.Search(len(offsets), func(i int) bool {
return offsets[i] >= ip || offsets[i] >= target
})
start, _ := slices.BinarySearch(offsets, min(ip, target))
for i := start; i < len(offsets) && (offsets[i] < target || offsets[i] <= ip); i++ {
ind := offsets[i]
if ip <= ind && ind < target || target <= ind && ind < ip {

View file

@ -1,11 +1,11 @@
package config
import (
"cmp"
"errors"
"fmt"
"maps"
"slices"
"sort"
"time"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
@ -168,9 +168,7 @@ func (p *ProtocolConfiguration) Validate() error {
// sortCheckZero sorts heightNumber array and checks for zero height presence.
func sortCheckZero(arr []heightNumber, field string) error {
sort.Slice(arr, func(i, j int) bool {
return arr[i].h < arr[j].h
})
slices.SortFunc(arr, func(a, b heightNumber) int { return cmp.Compare(a.h, b.h) })
if arr[0].h != 0 {
return fmt.Errorf("invalid %s: no height 0 specified", field)
}

View file

@ -7,7 +7,6 @@ import (
"fmt"
"math"
"math/big"
"sort"
"slices"
"sync"
"sync/atomic"
@ -1839,9 +1838,7 @@ func (bc *Blockchain) updateExtensibleWhitelist(height uint32) error {
bc.updateExtensibleList(&newList, stateVals)
}
sort.Slice(newList, func(i, j int) bool {
return newList[i].Less(newList[j])
})
slices.SortFunc(newList, util.Uint160.Compare)
bc.extensible.Store(newList)
return nil
}
@ -2786,7 +2783,7 @@ func (bc *Blockchain) PoolTxWithData(t *transaction.Transaction, data any, mp *m
// GetCommittee returns the sorted list of public keys of nodes in committee.
func (bc *Blockchain) GetCommittee() (keys.PublicKeys, error) {
pubs := bc.contracts.NEO.GetCommitteeMembers(bc.dao)
sort.Sort(pubs)
slices.SortFunc(pubs, (*keys.PublicKey).Cmp)
return pubs, nil
}

View file

@ -6,7 +6,7 @@ import (
"fmt"
"math/big"
"path/filepath"
"sort"
"slices"
"strings"
"testing"
"time"
@ -334,7 +334,7 @@ func TestBlockchain_InitializeNeoCache_Bug3424(t *testing.T) {
standBySorted, err := keys.NewPublicKeysFromStrings(e.Chain.GetConfig().StandbyCommittee)
require.NoError(t, err)
standBySorted = standBySorted[:validatorsCount]
sort.Sort(standBySorted)
slices.SortFunc(standBySorted, (*keys.PublicKey).Cmp)
pubs := e.Chain.ComputeNextBlockValidators()
require.Equal(t, standBySorted, keys.PublicKeys(pubs))
@ -384,7 +384,7 @@ func TestBlockchain_InitializeNeoCache_Bug3424(t *testing.T) {
for i := range candidates[:validatorsCount] {
sortedCandidates[i] = candidates[i].(neotest.SingleSigner).Account().PublicKey()
}
sort.Sort(sortedCandidates)
slices.SortFunc(sortedCandidates, (*keys.PublicKey).Cmp)
require.EqualValues(t, sortedCandidates, keys.PublicKeys(pubs))
// Move to the last block in the epoch and restart the node.

View file

@ -1,11 +1,11 @@
package interop
import (
"cmp"
"context"
"encoding/binary"
"errors"
"fmt"
"sort"
"slices"
"strings"
@ -362,12 +362,12 @@ func (c *ContractMD) AddMethod(md *MethodAndPrice, desc *manifest.Method) {
md.MD = desc
desc.Safe = md.RequiredFlags&(callflag.All^callflag.ReadOnly) == 0
index := sort.Search(len(c.methods), func(i int) bool {
md := c.methods[i].MD
if md.Name != desc.Name {
return md.Name >= desc.Name
index, _ := slices.BinarySearchFunc(c.methods, *md, func(e, t MethodAndPrice) int {
res := cmp.Compare(e.MD.Name, t.MD.Name)
if res != 0 {
return res
}
return len(md.Parameters) > len(desc.Parameters)
return cmp.Compare(len(e.MD.Parameters), len(t.MD.Parameters))
})
c.methods = slices.Insert(c.methods, index, *md)
@ -392,21 +392,18 @@ func (c *HFSpecificContractMD) GetMethodByOffset(offset int) (HFSpecificMethodAn
// GetMethod returns method `name` with the specified number of parameters.
func (c *HFSpecificContractMD) GetMethod(name string, paramCount int) (HFSpecificMethodAndPrice, bool) {
index := sort.Search(len(c.Methods), func(i int) bool {
md := c.Methods[i]
res := strings.Compare(name, md.MD.Name)
switch res {
case -1, 1:
return res == -1
default:
return paramCount <= len(md.MD.Parameters)
index, ok := slices.BinarySearchFunc(c.Methods, HFSpecificMethodAndPrice{}, func(a, _ HFSpecificMethodAndPrice) int {
res := strings.Compare(a.MD.Name, name)
if res != 0 {
return res
}
return cmp.Compare(len(a.MD.Parameters), paramCount)
})
if index < len(c.Methods) {
md := c.Methods[index]
if md.MD.Name == name && (paramCount == -1 || len(md.MD.Parameters) == paramCount) {
return md, true
}
// Exact match is possible only for specific paramCount, but if we're
// searching for _some_ method with this name (-1) we're taking the
// first one.
if ok || (index < len(c.Methods) && c.Methods[index].MD.Name == name && paramCount == -1) {
return c.Methods[index], true
}
return HFSpecificMethodAndPrice{}, false
}
@ -425,7 +422,7 @@ func (c *ContractMD) AddEvent(md Event) {
// Sort sorts interop functions by id.
func Sort(fs []Function) {
sort.Slice(fs, func(i, j int) bool { return fs[i].ID < fs[j].ID })
slices.SortFunc(fs, func(a, b Function) int { return cmp.Compare(a.ID, b.ID) })
}
// GetContract returns a contract by its hash in the current interop context.
@ -435,13 +432,13 @@ func (ic *Context) GetContract(hash util.Uint160) (*state.Contract, error) {
// GetFunction returns metadata for interop with the specified id.
func (ic *Context) GetFunction(id uint32) *Function {
n := sort.Search(len(ic.Functions), func(i int) bool {
return ic.Functions[i].ID >= id
n, ok := slices.BinarySearchFunc(ic.Functions, Function{}, func(a, _ Function) int {
return cmp.Compare(a.ID, id)
})
if n < len(ic.Functions) && ic.Functions[n].ID == id {
return &ic.Functions[n]
if !ok {
return nil
}
return nil
return &ic.Functions[n]
}
// BaseExecFee represents factor to multiply syscall prices with.

View file

@ -3,7 +3,7 @@ package mempool
import (
"fmt"
"math/big"
"sort"
"slices"
"strings"
"testing"
"time"
@ -116,6 +116,10 @@ func TestOverCapacity(t *testing.T) {
const mempoolSize = 10
mp := New(mempoolSize, 0, false, nil)
var checkPoolIsSorted = func() {
require.True(t, slices.IsSortedFunc(mp.verifiedTxes, func(a, b item) int { return -a.CompareTo(b) }))
}
for i := 0; i < mempoolSize; i++ {
tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0)
tx.Nonce = uint32(i)
@ -124,7 +128,7 @@ func TestOverCapacity(t *testing.T) {
}
txcnt := uint32(mempoolSize)
require.Equal(t, mempoolSize, mp.Count())
require.Equal(t, true, sort.IsSorted(sort.Reverse(mp.verifiedTxes)))
checkPoolIsSorted()
require.Equal(t, *uint256.NewInt(0), mp.fees[acc].feeSum)
bigScript := make([]byte, 64)
@ -140,7 +144,7 @@ func TestOverCapacity(t *testing.T) {
// size is ~90, networkFee is 10000 => feePerByte is 119
require.NoError(t, mp.Add(tx, fs))
require.Equal(t, mempoolSize, mp.Count())
require.Equal(t, true, sort.IsSorted(sort.Reverse(mp.verifiedTxes)))
checkPoolIsSorted()
}
require.Equal(t, *uint256.NewInt(10 * 10000), mp.fees[acc].feeSum)
@ -155,7 +159,7 @@ func TestOverCapacity(t *testing.T) {
require.Equal(t, mempoolSize, len(mp.verifiedMap))
require.Equal(t, mempoolSize, len(mp.verifiedTxes))
require.False(t, mp.containsKey(tx.Hash()))
require.Equal(t, true, sort.IsSorted(sort.Reverse(mp.verifiedTxes)))
checkPoolIsSorted()
require.Equal(t, *uint256.NewInt(100000), mp.fees[acc].feeSum)
// Low net fee, but higher per-byte fee is still a better combination.
@ -168,7 +172,7 @@ func TestOverCapacity(t *testing.T) {
// => feePerByte is 137 (>119)
require.NoError(t, mp.Add(tx, fs))
require.Equal(t, mempoolSize, mp.Count())
require.Equal(t, true, sort.IsSorted(sort.Reverse(mp.verifiedTxes)))
checkPoolIsSorted()
require.Equal(t, *uint256.NewInt(9*10000 + 7000), mp.fees[acc].feeSum)
// High priority always wins over low priority.
@ -180,7 +184,7 @@ func TestOverCapacity(t *testing.T) {
txcnt++
require.NoError(t, mp.Add(tx, fs))
require.Equal(t, mempoolSize, mp.Count())
require.Equal(t, true, sort.IsSorted(sort.Reverse(mp.verifiedTxes)))
checkPoolIsSorted()
}
require.Equal(t, *uint256.NewInt(10 * 8000), mp.fees[acc].feeSum)
// Good luck with low priority now.
@ -190,7 +194,7 @@ func TestOverCapacity(t *testing.T) {
tx.Signers = []transaction.Signer{{Account: acc}}
require.Error(t, mp.Add(tx, fs))
require.Equal(t, mempoolSize, mp.Count())
require.Equal(t, true, sort.IsSorted(sort.Reverse(mp.verifiedTxes)))
checkPoolIsSorted()
}
func TestGetVerified(t *testing.T) {

View file

@ -2,7 +2,7 @@ package mpt
import (
"bytes"
"sort"
"slices"
)
// Batch is a batch of storage changes.
@ -25,8 +25,8 @@ func MapToMPTBatch(m map[string][]byte) Batch {
for k, v := range m {
b.kv = append(b.kv, keyValue{strToNibbles(k), v}) // Strip storage prefix.
}
sort.Slice(b.kv, func(i, j int) bool {
return bytes.Compare(b.kv[i].key, b.kv[j].key) < 0
slices.SortFunc(b.kv, func(a, b keyValue) int {
return bytes.Compare(a.key, b.key)
})
return b
}

View file

@ -6,7 +6,7 @@ import (
"fmt"
"math"
"math/big"
"sort"
"slices"
"sync/atomic"
"github.com/nspcc-dev/neo-go/pkg/config"
@ -397,7 +397,7 @@ func (s *Designate) DesignateAsRole(ic *interop.Context, r noderoles.Role, pubs
if si != nil {
return ErrAlreadyDesignated
}
sort.Sort(pubs)
slices.SortFunc(pubs, (*keys.PublicKey).Cmp)
nl := NodeList(pubs)
err := putConvertibleToDAO(s.ID, ic.DAO, key, &nl)

View file

@ -9,7 +9,6 @@ import (
"maps"
"math/big"
"slices"
"sort"
"strings"
"github.com/nspcc-dev/neo-go/pkg/config"
@ -405,7 +404,7 @@ func (n *NEO) updateCache(cache *NeoCache, cvs keysWithVotes, blockHeight uint32
cache.committeeHash = hash.Hash160(script)
nextVals := committee[:n.cfg.GetNumOfCNs(blockHeight+1)].Copy()
sort.Sort(nextVals)
slices.SortFunc(nextVals, (*keys.PublicKey).Cmp)
cache.nextValidators = nextVals
return nil
}
@ -430,7 +429,7 @@ func (n *NEO) updateCachedNewEpochValues(d *dao.Simple, cache *NeoCache, blockHe
cache.newEpochCommitteeHash = hash.Hash160(script)
nextVals := committee[:numOfCNs].Copy()
sort.Sort(nextVals)
slices.SortFunc(nextVals, (*keys.PublicKey).Cmp)
cache.newEpochNextValidators = nextVals
return nil
}
@ -1028,23 +1027,23 @@ func (n *NEO) getCandidates(d *dao.Simple, sortByKey bool, maxNum int) ([]keyWit
// sortByKey assumes to sort by serialized key bytes (that's the way keys
// are stored and retrieved from the storage by default). Otherwise, need
// to sort using big.Int comparator.
sort.Slice(arr, func(i, j int) bool {
slices.SortFunc(arr, func(a, b keyWithVotes) int {
// The most-voted validators should end up in the front of the list.
cmp := arr[i].Votes.Cmp(arr[j].Votes)
cmp := b.Votes.Cmp(a.Votes)
if cmp != 0 {
return cmp > 0
return cmp
}
// Ties are broken with deserialized public keys.
// Sort by ECPoint's (X, Y) components: compare X first, and then compare Y.
cmpX := strings.Compare(arr[i].Key[1:], arr[j].Key[1:])
cmpX := strings.Compare(a.Key[1:], b.Key[1:])
if cmpX != 0 {
return cmpX == -1
return cmpX
}
// The case when X components are the same is extremely rare, thus we perform
// key deserialization only if needed. No error can occur.
ki, _ := keys.NewPublicKeyFromBytes([]byte(arr[i].Key), elliptic.P256())
kj, _ := keys.NewPublicKeyFromBytes([]byte(arr[j].Key), elliptic.P256())
return ki.Y.Cmp(kj.Y) == -1
ka, _ := keys.NewPublicKeyFromBytes([]byte(a.Key), elliptic.P256())
kb, _ := keys.NewPublicKeyFromBytes([]byte(b.Key), elliptic.P256())
return ka.Y.Cmp(kb.Y)
})
}
return arr, nil
@ -1172,7 +1171,7 @@ func (n *NEO) ComputeNextBlockValidators(d *dao.Simple) keys.PublicKeys {
func (n *NEO) getCommittee(ic *interop.Context, _ []stackitem.Item) stackitem.Item {
pubs := n.GetCommitteeMembers(ic.DAO)
sort.Sort(pubs)
slices.SortFunc(pubs, (*keys.PublicKey).Cmp)
return pubsToArray(pubs)
}

View file

@ -2,7 +2,7 @@ package native_test
import (
"math/big"
"sort"
"slices"
"testing"
"github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames"
@ -602,9 +602,7 @@ func TestCryptoLib_KoblitzMultisigVerificationScript(t *testing.T) {
require.NoError(t, err)
}
// Sort private keys by their public keys.
sort.Slice(pks, func(i, j int) bool {
return pks[i].PublicKey().Cmp(pks[j].PublicKey()) < 0
})
slices.SortFunc(pks, func(a, b *keys.PrivateKey) int { return a.PublicKey().Cmp(b.PublicKey()) })
// Firstly, we need to build the N3 multisig account address based on the users' public keys.
// Pubs must be sorted, exactly like for the standard CheckMultisig.

View file

@ -1,7 +1,7 @@
package native_test
import (
"sort"
"slices"
"testing"
"github.com/nspcc-dev/neo-go/pkg/config"
@ -157,6 +157,6 @@ func TestDesignate_GenesisRolesExtension(t *testing.T) {
c := e.CommitteeInvoker(e.NativeHash(t, nativenames.Designation))
// Check designated node in a separate block.
sort.Sort(pubs)
slices.SortFunc(pubs, (*keys.PublicKey).Cmp)
checkNodeRoles(t, c, true, noderoles.StateValidator, e.Chain.BlockHeight()+1, pubs)
}

View file

@ -6,7 +6,7 @@ import (
"fmt"
"math"
"math/big"
"sort"
"slices"
"strings"
"testing"
@ -204,7 +204,7 @@ func TestNEO_Vote(t *testing.T) {
standBySorted, err := keys.NewPublicKeysFromStrings(e.Chain.GetConfig().StandbyCommittee)
require.NoError(t, err)
standBySorted = standBySorted[:validatorsCount]
sort.Sort(standBySorted)
slices.SortFunc(standBySorted, (*keys.PublicKey).Cmp)
pubs := e.Chain.ComputeNextBlockValidators()
require.Equal(t, standBySorted, keys.PublicKeys(pubs))
@ -269,7 +269,7 @@ func TestNEO_Vote(t *testing.T) {
for i := range candidates[:validatorsCount] {
sortedCandidates[i] = candidates[i].(neotest.SingleSigner).Account().PublicKey()
}
sort.Sort(sortedCandidates)
slices.SortFunc(sortedCandidates, (*keys.PublicKey).Cmp)
require.EqualValues(t, sortedCandidates, keys.PublicKeys(pubs))
pubs, err = neoCommitteeInvoker.Chain.GetNextBlockValidators()
@ -403,7 +403,7 @@ func TestNEO_GetCommitteeAddress(t *testing.T) {
e := neoValidatorInvoker.Executor
standByCommitteePublicKeys, err := keys.NewPublicKeysFromStrings(e.Chain.GetConfig().StandbyCommittee)
require.NoError(t, err)
sort.Sort(standByCommitteePublicKeys)
slices.SortFunc(standByCommitteePublicKeys, (*keys.PublicKey).Cmp)
expectedCommitteeAddress, err := smartcontract.CreateMajorityMultiSigRedeemScript(standByCommitteePublicKeys)
require.NoError(t, err)
stack, err := neoValidatorInvoker.TestInvoke(t, "getCommitteeAddress")
@ -811,8 +811,8 @@ func TestNEO_GetCandidates(t *testing.T) {
})
neoCommitteeInvoker.Invoke(t, v, "getCandidateVote", pub)
}
sort.Slice(expected, func(i, j int) bool {
return bytes.Compare(expected[i].Value().([]stackitem.Item)[0].Value().([]byte), expected[j].Value().([]stackitem.Item)[0].Value().([]byte)) < 0
slices.SortFunc(expected, func(a, b stackitem.Item) int {
return bytes.Compare(a.Value().([]stackitem.Item)[0].Value().([]byte), b.Value().([]stackitem.Item)[0].Value().([]byte))
})
neoCommitteeInvoker.Invoke(t, stackitem.NewArray(expected), "getCandidates")

View file

@ -6,7 +6,6 @@ import (
"maps"
"math/big"
"slices"
"sort"
"github.com/nspcc-dev/neo-go/pkg/config"
"github.com/nspcc-dev/neo-go/pkg/core/dao"
@ -327,14 +326,7 @@ func (p *Policy) IsBlocked(dao *dao.Simple, hash util.Uint160) bool {
// of the blocked account in the blocked accounts list (or the position it should be
// put at).
func (p *Policy) isBlockedInternal(roCache *PolicyCache, hash util.Uint160) (int, bool) {
length := len(roCache.blockedAccounts)
i := sort.Search(length, func(i int) bool {
return !roCache.blockedAccounts[i].Less(hash)
})
if length != 0 && i != length && roCache.blockedAccounts[i].Equals(hash) {
return i, true
}
return i, false
return slices.BinarySearchFunc(roCache.blockedAccounts, hash, util.Uint160.Compare)
}
func (p *Policy) getStoragePrice(ic *interop.Context, _ []stackitem.Item) stackitem.Item {

View file

@ -3,7 +3,7 @@ package storage
import (
"bytes"
"context"
"sort"
"slices"
"strings"
"sync"
)
@ -230,13 +230,11 @@ func (s *MemCachedStore) prepareSeekMemSnapshot(rng SeekRange) (Store, []KeyValu
// seeking from some point is supported with corresponding `rng` field set.
func performSeek(ctx context.Context, ps Store, memRes []KeyValueExists, rng SeekRange, cutPrefix bool, f func(k, v []byte) bool) {
lPrefix := len(string(rng.Prefix))
less := func(k1, k2 []byte) bool {
res := bytes.Compare(k1, k2)
return res != 0 && rng.Backwards == (res > 0)
}
var cmpFunc = getCmpFunc(rng.Backwards)
// Sort memRes items for further comparison with ps items.
sort.Slice(memRes, func(i, j int) bool {
return less(memRes[i].Key, memRes[j].Key)
slices.SortFunc(memRes, func(a, b KeyValueExists) int {
return cmpFunc(a.Key, b.Key)
})
var (
@ -266,7 +264,7 @@ func performSeek(ctx context.Context, ps Store, memRes []KeyValueExists, rng See
done = true
return false
default:
var isMem = haveMem && less(kvMem.Key, kvPs.Key)
var isMem = haveMem && cmpFunc(kvMem.Key, kvPs.Key) < 0
if isMem {
if kvMem.Exists {
if cutPrefix {

View file

@ -3,7 +3,7 @@ package storage
import (
"bytes"
"fmt"
"sort"
"slices"
"testing"
"github.com/nspcc-dev/neo-go/internal/random"
@ -424,8 +424,8 @@ func TestCachedSeekSorting(t *testing.T) {
})
assert.Equal(t, len(foundKVs), len(lowerKVs)+len(updatedKVs))
expected := append(lowerKVs, updatedKVs...)
sort.Slice(expected, func(i, j int) bool {
return bytes.Compare(expected[i].Key, expected[j].Key) < 0
slices.SortFunc(expected, func(a, b KeyValue) int {
return bytes.Compare(a.Key, b.Key)
})
require.Equal(t, expected, foundKVs)
}

View file

@ -2,7 +2,7 @@ package storage
import (
"bytes"
"sort"
"slices"
"strings"
"sync"
)
@ -107,10 +107,7 @@ func (s *MemoryStore) seek(rng SeekRange, f func(k, v []byte) bool, lock func(),
return strings.HasPrefix(key, sPrefix) && (lStart == 0 || strings.Compare(key[lPrefix:], sStart) <= 0)
}
}
less := func(k1, k2 []byte) bool {
res := bytes.Compare(k1, k2)
return res != 0 && rng.Backwards == (res > 0)
}
var cmpFunc = getCmpFunc(rng.Backwards)
lock()
m := s.chooseMap(rng.Prefix)
@ -123,8 +120,8 @@ func (s *MemoryStore) seek(rng SeekRange, f func(k, v []byte) bool, lock func(),
}
}
unlock()
sort.Slice(memList, func(i, j int) bool {
return less(memList[i].Key, memList[j].Key)
slices.SortFunc(memList, func(a, b KeyValue) int {
return cmpFunc(a.Key, b.Key)
})
for _, kv := range memList {
if !f(kv.Key, kv.Value) {
@ -133,6 +130,13 @@ func (s *MemoryStore) seek(rng SeekRange, f func(k, v []byte) bool, lock func(),
}
}
func getCmpFunc(backwards bool) func(a, b []byte) int {
if !backwards {
return bytes.Compare
}
return func(a, b []byte) int { return -bytes.Compare(a, b) }
}
// Close implements Store interface and clears up memory. Never returns an
// error.
func (s *MemoryStore) Close() error {

View file

@ -4,7 +4,7 @@ import (
"bytes"
"reflect"
"runtime"
"sort"
"slices"
"testing"
"github.com/stretchr/testify/assert"
@ -49,15 +49,10 @@ func testStoreSeek(t *testing.T, s Store) {
kvs := pushSeekDataSet(t, s)
check := func(t *testing.T, goodprefix, start []byte, goodkvs []KeyValue, backwards bool, cont func(k, v []byte) bool) {
// Seek result expected to be sorted in an ascending (for forwards seeking) or descending (for backwards seeking) way.
cmpFunc := func(i, j int) bool {
return bytes.Compare(goodkvs[i].Key, goodkvs[j].Key) < 0
}
if backwards {
cmpFunc = func(i, j int) bool {
return bytes.Compare(goodkvs[i].Key, goodkvs[j].Key) > 0
}
}
sort.Slice(goodkvs, cmpFunc)
var cmpFunc = getCmpFunc(backwards)
slices.SortFunc(goodkvs, func(a, b KeyValue) int {
return cmpFunc(a.Key, b.Key)
})
rng := SeekRange{
Prefix: goodprefix,

View file

@ -2,7 +2,7 @@ package chain
import (
"encoding/hex"
"sort"
"slices"
"testing"
"time"
@ -103,12 +103,12 @@ func init() {
standByCommittee[5] = pubs[5].StringCompressed()
multiValidatorAcc = make([]*wallet.Account, 4)
sort.Sort(pubs[:4])
slices.SortFunc(pubs[:4], (*keys.PublicKey).Cmp)
sort.Slice(accs[:4], func(i, j int) bool {
p1 := accs[i].PublicKey()
p2 := accs[j].PublicKey()
return p1.Cmp(p2) == -1
slices.SortFunc(accs[:4], func(a, b *wallet.Account) int {
pa := a.PublicKey()
pb := b.PublicKey()
return pa.Cmp(pb)
})
for i := range multiValidatorAcc {
multiValidatorAcc[i] = wallet.NewAccountFromPrivateKey(accs[i].PrivateKey())
@ -119,12 +119,12 @@ func init() {
}
multiCommitteeAcc = make([]*wallet.Account, len(committeeWIFs))
sort.Sort(pubs)
slices.SortFunc(pubs, (*keys.PublicKey).Cmp)
sort.Slice(accs, func(i, j int) bool {
p1 := accs[i].PublicKey()
p2 := accs[j].PublicKey()
return p1.Cmp(p2) == -1
slices.SortFunc(accs, func(a, b *wallet.Account) int {
pa := a.PublicKey()
pb := b.PublicKey()
return pa.Cmp(pb)
})
for i := range multiCommitteeAcc {
multiCommitteeAcc[i] = wallet.NewAccountFromPrivateKey(accs[i].PrivateKey())

View file

@ -3,7 +3,7 @@ package neotest
import (
"bytes"
"fmt"
"sort"
"slices"
"testing"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
@ -106,10 +106,10 @@ func NewMultiSigner(accs ...*wallet.Account) MultiSigner {
panic(fmt.Sprintf("verification script requires %d signatures, "+
"but only %d accounts were provided", m, len(accs)))
}
sort.Slice(accs, func(i, j int) bool {
p1 := accs[i].PublicKey()
p2 := accs[j].PublicKey()
return p1.Cmp(p2) == -1
slices.SortFunc(accs, func(a, b *wallet.Account) int {
pa := a.PublicKey()
pb := b.PublicKey()
return pa.Cmp(pb)
})
for _, acc := range accs {
if !bytes.Equal(script, acc.Contract.Script) {

View file

@ -1,7 +1,7 @@
package neotest
import (
"sort"
"slices"
"testing"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
@ -31,7 +31,7 @@ func TestMultiSigner(t *testing.T) {
pubs[i] = a.PublicKey()
}
sort.Sort(pubs)
slices.SortFunc(pubs, (*keys.PublicKey).Cmp)
m := smartcontract.GetDefaultHonestNodeCount(size)
for i := range accs {
require.NoError(t, accs[i].ConvertMultisig(m, pubs))

View file

@ -11,7 +11,6 @@ import (
"net"
"runtime"
"slices"
"sort"
"strconv"
"sync"
"sync/atomic"
@ -1170,10 +1169,8 @@ txloop:
var cbList = s.txCbList.Load()
if cbList != nil {
var list = cbList.([]util.Uint256)
var i = sort.Search(len(list), func(i int) bool {
return list[i].CompareTo(tx.Hash()) >= 0
})
if i < len(list) && list[i].Equals(tx.Hash()) {
_, found := slices.BinarySearchFunc(list, tx.Hash(), util.Uint256.CompareTo)
if found {
txCallback(tx)
}
}
@ -1487,10 +1484,7 @@ func (s *Server) RequestTx(hashes ...util.Uint256) {
}
var sorted = slices.Clone(hashes)
sort.Slice(sorted, func(i, j int) bool {
return sorted[i].CompareTo(sorted[j]) < 0
})
slices.SortFunc(sorted, util.Uint256.CompareTo)
s.txCbList.Store(sorted)
for i := 0; i <= len(hashes)/payload.MaxHashesCount; i++ {

View file

@ -1,11 +1,13 @@
package neo_test
import (
"cmp"
"context"
"math/big"
"sort"
"slices"
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/neorpc/result"
"github.com/nspcc-dev/neo-go/pkg/rpcclient"
"github.com/nspcc-dev/neo-go/pkg/rpcclient/actor"
"github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker"
@ -76,7 +78,7 @@ func ExampleContract() {
cands, _ := neoToken.GetCandidates()
// Sort by votes.
sort.Slice(cands, func(i, j int) bool { return cands[i].Votes < cands[j].Votes })
slices.SortFunc(cands, func(a, b result.Validator) int { return cmp.Compare(a.Votes, b.Votes) })
// Get the extended NEO-specific balance data.
bNeo, _ := neoToken.GetAccountState(a.Sender())

View file

@ -10,7 +10,7 @@ import (
"math/big"
"net/http"
"net/http/httptest"
"sort"
"slices"
"strings"
"sync"
"testing"
@ -154,7 +154,7 @@ func TestClientRoleManagement(t *testing.T) {
_, err = c.SubmitBlock(*bl)
require.NoError(t, err)
sort.Sort(testKeys)
slices.SortFunc(testKeys, (*keys.PublicKey).Cmp)
ks, err = rm.GetDesignatedByRole(noderoles.Oracle, height+1)
require.NoError(t, err)
require.Equal(t, testKeys, ks)
@ -1458,11 +1458,11 @@ func TestClient_IteratorSessions(t *testing.T) {
for i := 0; i < storageItemsCount; i++ {
expected[i] = stackitem.NewBigInteger(big.NewInt(int64(i))).Bytes()
}
sort.Slice(expected, func(i, j int) bool {
if len(expected[i]) != len(expected[j]) {
return len(expected[i]) < len(expected[j])
slices.SortFunc(expected, func(a, b []byte) int {
if len(a) != len(b) {
return len(a) - len(b)
}
return bytes.Compare(expected[i], expected[j]) < 0
return bytes.Compare(a, b)
})
prepareSession := func(t *testing.T) (uuid.UUID, uuid.UUID) {
@ -1699,11 +1699,11 @@ func TestClient_Iterator_SessionConfigVariations(t *testing.T) {
for i := 0; i < storageItemsCount; i++ {
expected[i] = stackitem.NewBigInteger(big.NewInt(int64(i))).Bytes()
}
sort.Slice(expected, func(i, j int) bool {
if len(expected[i]) != len(expected[j]) {
return len(expected[i]) < len(expected[j])
slices.SortFunc(expected, func(a, b []byte) int {
if len(a) != len(b) {
return len(a) - len(b)
}
return bytes.Compare(expected[i], expected[j]) < 0
return bytes.Compare(a, b)
})
checkSessionEnabled(t, c)
})

View file

@ -14,7 +14,7 @@ import (
"net/http"
"net/http/httptest"
"reflect"
"sort"
"slices"
"strconv"
"strings"
"sync/atomic"
@ -1174,7 +1174,7 @@ var rpcTestCases = map[string][]rpcTestCase{
params: "[]",
result: func(e *executor) any {
expected, _ := e.chain.GetCommittee()
sort.Sort(expected)
slices.SortFunc(expected, (*keys.PublicKey).Cmp)
return &expected
},
},

View file

@ -3,7 +3,7 @@ package stateroot_test
import (
"crypto/elliptic"
"path/filepath"
"sort"
"slices"
"sync/atomic"
"testing"
"time"
@ -63,10 +63,10 @@ func newMajorityMultisigWithGAS(t *testing.T, n int) (util.Uint160, keys.PublicK
require.NoError(t, err)
accs[i] = acc
}
sort.Slice(accs, func(i, j int) bool {
pi := accs[i].PublicKey()
pj := accs[j].PublicKey()
return pi.Cmp(pj) == -1
slices.SortFunc(accs, func(a, b *wallet.Account) int {
pa := a.PublicKey()
pb := b.PublicKey()
return pa.Cmp(pb)
})
pubs := make(keys.PublicKeys, n)
for i := range pubs {

View file

@ -7,7 +7,6 @@ import (
"errors"
"fmt"
"slices"
"sort"
"strings"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
@ -133,8 +132,8 @@ func (c *ParameterContext) AddSignature(h util.Uint160, ctr *wallet.Contract, pu
break
}
}
sort.Slice(sigs, func(i, j int) bool {
return sigs[i].index < sigs[j].index
slices.SortFunc(sigs, func(a, b sigWithIndex) int {
return a.index - b.index
})
for i := range sigs {
item.Parameters[i] = smartcontract.Parameter{

View file

@ -2,7 +2,7 @@ package smartcontract
import (
"fmt"
"sort"
"slices"
"github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
@ -26,7 +26,7 @@ func CreateMultiSigRedeemScript(m int, publicKeys keys.PublicKeys) ([]byte, erro
buf := io.NewBufBinWriter()
emit.Int(buf.BinWriter, int64(m))
sort.Sort(publicKeys)
slices.SortFunc(publicKeys, (*keys.PublicKey).Cmp)
for _, pubKey := range publicKeys {
emit.Bytes(buf.BinWriter, pubKey.Bytes())
}

View file

@ -3,7 +3,6 @@ package rpcbinding
import (
"fmt"
"slices"
"sort"
"strings"
"text/template"
"unicode"
@ -434,9 +433,7 @@ func Generate(cfg binding.Config) error {
for k := range cfg.NamedTypes {
ctr.NamedTypes = append(ctr.NamedTypes, cfg.NamedTypes[k])
}
sort.Slice(ctr.NamedTypes, func(i, j int) bool {
return strings.Compare(ctr.NamedTypes[i].Name, ctr.NamedTypes[j].Name) < 0
})
slices.SortFunc(ctr.NamedTypes, func(a, b binding.ExtendedType) int { return strings.Compare(a.Name, b.Name) })
// Check resulting named types and events don't have duplicating field names.
for _, t := range ctr.NamedTypes {

View file

@ -2,6 +2,7 @@ package main
import (
"bytes"
"cmp"
"encoding/base64"
"encoding/binary"
"encoding/hex"
@ -10,7 +11,7 @@ import (
"fmt"
"os"
"path/filepath"
"sort"
"slices"
"github.com/urfave/cli/v2"
)
@ -61,9 +62,7 @@ func (d dump) normalize() {
}
newStorage = append(newStorage, d[i].Storage[j])
}
sort.Slice(newStorage, func(k, l int) bool {
return newStorage[k].Key < newStorage[l].Key
})
slices.SortFunc(newStorage, func(a, b storageOp) int { return cmp.Compare(a.Key, b.Key) })
d[i].Storage = newStorage
}
// assume that d is already sorted by Block