[#851] util/rand: use single random source
It is much more convenient to skip source creation. Also fix some bugs: 1. `cryptoSource.Int63()` now returns number in [0, 1<<63) as required by `rand.Source` interface. 2. Replace `cryptoSource.Uint63()` with `cryptoSource.Uint64` to allow generate uint64 numbers directly (see rand.Source64 docs). Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
This commit is contained in:
parent
c35cdb3684
commit
5828f43e52
8 changed files with 56 additions and 66 deletions
|
@ -4,7 +4,6 @@ import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
|
||||||
|
|
||||||
"github.com/nspcc-dev/neo-go/cli/flags"
|
"github.com/nspcc-dev/neo-go/cli/flags"
|
||||||
"github.com/nspcc-dev/neo-go/cli/input"
|
"github.com/nspcc-dev/neo-go/cli/input"
|
||||||
|
@ -206,7 +205,7 @@ var cmdSubnetCreate = &cobra.Command{
|
||||||
)
|
)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
num = uint32(rand.Uint64(rand.New(), math.MaxUint32))
|
num = rand.Uint32()
|
||||||
|
|
||||||
id.SetNumber(num)
|
id.SetNumber(num)
|
||||||
|
|
||||||
|
|
|
@ -40,8 +40,7 @@ func initMorphComponents(c *cfg) {
|
||||||
fatalOnErr(errors.New("missing Neo RPC endpoints"))
|
fatalOnErr(errors.New("missing Neo RPC endpoints"))
|
||||||
}
|
}
|
||||||
|
|
||||||
crand := rand.New() // math/rand with cryptographic source
|
rand.Shuffle(len(addresses), func(i, j int) {
|
||||||
crand.Shuffle(len(addresses), func(i, j int) {
|
|
||||||
addresses[i], addresses[j] = addresses[j], addresses[i]
|
addresses[i], addresses[j] = addresses[j], addresses[i]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -185,8 +184,7 @@ func listenMorphNotifications(c *cfg) {
|
||||||
endpoints := morphconfig.NotificationEndpoint(c.appCfg)
|
endpoints := morphconfig.NotificationEndpoint(c.appCfg)
|
||||||
timeout := morphconfig.DialTimeout(c.appCfg)
|
timeout := morphconfig.DialTimeout(c.appCfg)
|
||||||
|
|
||||||
crand := rand.New() // math/rand with cryptographic source
|
rand.Shuffle(len(endpoints), func(i, j int) {
|
||||||
crand.Shuffle(len(endpoints), func(i, j int) {
|
|
||||||
endpoints[i], endpoints[j] = endpoints[j], endpoints[i]
|
endpoints[i], endpoints[j] = endpoints[j], endpoints[i]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -69,10 +69,9 @@ func (ap *Processor) processStartAudit(epoch uint64) {
|
||||||
}
|
}
|
||||||
|
|
||||||
n := nodes.Flatten()
|
n := nodes.Flatten()
|
||||||
crand := rand.New() // math/rand with cryptographic source
|
|
||||||
|
|
||||||
// shuffle nodes to ask a random one
|
// shuffle nodes to ask a random one
|
||||||
crand.Shuffle(len(n), func(i, j int) {
|
rand.Shuffle(len(n), func(i, j int) {
|
||||||
n[i], n[j] = n[j], n[i]
|
n[i], n[j] = n[j], n[i]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -361,9 +361,6 @@ func (c *Client) NotaryInvoke(contract util.Uint160, fee fixedn.Fixed8, nonce ui
|
||||||
return c.notaryInvoke(false, true, contract, nonce, vub, method, args...)
|
return c.notaryInvoke(false, true, contract, nonce, vub, method, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// randSource is a source of random numbers.
|
|
||||||
var randSource = rand.New()
|
|
||||||
|
|
||||||
// NotaryInvokeNotAlpha does the same as NotaryInvoke but does not use client's
|
// NotaryInvokeNotAlpha does the same as NotaryInvoke but does not use client's
|
||||||
// private key in Invocation script. It means that main TX of notary request is
|
// private key in Invocation script. It means that main TX of notary request is
|
||||||
// not expected to be signed by the current node.
|
// not expected to be signed by the current node.
|
||||||
|
@ -380,7 +377,7 @@ func (c *Client) NotaryInvokeNotAlpha(contract util.Uint160, fee fixedn.Fixed8,
|
||||||
return c.Invoke(contract, fee, method, args...)
|
return c.Invoke(contract, fee, method, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.notaryInvoke(false, false, contract, randSource.Uint32(), nil, method, args...)
|
return c.notaryInvoke(false, false, contract, rand.Uint32(), nil, method, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NotarySignAndInvokeTX signs and sends notary request that was received from
|
// NotarySignAndInvokeTX signs and sends notary request that was received from
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neofs-node/pkg/util/rand"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/netmap"
|
"github.com/nspcc-dev/neofs-sdk-go/netmap"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/object"
|
"github.com/nspcc-dev/neofs-sdk-go/object"
|
||||||
"github.com/nspcc-dev/tzhash/tz"
|
"github.com/nspcc-dev/tzhash/tz"
|
||||||
|
@ -88,16 +89,18 @@ func (c *Context) splitPayload(id *object.ID) []uint64 {
|
||||||
)
|
)
|
||||||
|
|
||||||
for i := uint64(0); i < hashRangeNumber; i++ {
|
for i := uint64(0); i < hashRangeNumber; i++ {
|
||||||
var nextLn uint64
|
|
||||||
if i < hashRangeNumber-1 {
|
if i < hashRangeNumber-1 {
|
||||||
nextLn = randUint64(size-prev-(hashRangeNumber-i)) + 1
|
max := size - prev - (hashRangeNumber - i)
|
||||||
|
if max == 0 {
|
||||||
|
prev++
|
||||||
|
} else {
|
||||||
|
prev += rand.Uint64()%max + 1
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
nextLn = size - prev
|
prev = size
|
||||||
}
|
}
|
||||||
|
|
||||||
notches = append(notches, prev+nextLn)
|
notches = append(notches, prev)
|
||||||
|
|
||||||
prev += nextLn
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return notches
|
return notches
|
||||||
|
@ -107,13 +110,16 @@ func (c *Context) collectHashes(p *gamePair) {
|
||||||
fn := func(n *netmap.Node, rngs []*object.Range, hashWriter func([]byte)) {
|
fn := func(n *netmap.Node, rngs []*object.Range, hashWriter func([]byte)) {
|
||||||
// TODO: add order randomization
|
// TODO: add order randomization
|
||||||
for i := range rngs {
|
for i := range rngs {
|
||||||
sleepDur := time.Duration(randUint64(c.maxPDPSleep))
|
var sleepDur time.Duration
|
||||||
|
if c.maxPDPSleep > 0 {
|
||||||
|
sleepDur = time.Duration(rand.Uint64() % c.maxPDPSleep)
|
||||||
|
}
|
||||||
|
|
||||||
c.log.Debug("sleep before get range hash",
|
c.log.Debug("sleep before get range hash",
|
||||||
zap.Stringer("interval", sleepDur),
|
zap.Stringer("interval", sleepDur),
|
||||||
)
|
)
|
||||||
|
|
||||||
time.Sleep(time.Duration(sleepDur))
|
time.Sleep(sleepDur)
|
||||||
|
|
||||||
h, err := c.cnrCom.GetRangeHash(c.task, n, p.id, rngs[i])
|
h, err := c.cnrCom.GetRangeHash(c.task, n, p.id, rngs[i])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -68,8 +68,7 @@ func (c *Context) checkStorageGroupPoR(ind int, sg *object.ID) {
|
||||||
|
|
||||||
flat := placement.FlattenNodes(objectPlacement)
|
flat := placement.FlattenNodes(objectPlacement)
|
||||||
|
|
||||||
crand := rand.New() // math/rand with cryptographic source
|
rand.Shuffle(len(flat), func(i, j int) {
|
||||||
crand.Shuffle(len(flat), func(i, j int) {
|
|
||||||
flat[i], flat[j] = flat[j], flat[i]
|
flat[i], flat[j] = flat[j], flat[i]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -4,12 +4,11 @@ import (
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/util/rand"
|
"github.com/nspcc-dev/neofs-node/pkg/util/rand"
|
||||||
)
|
)
|
||||||
|
|
||||||
// returns random uint64 number [0; n) outside exclude map.
|
// nextRandUint64 returns random uint64 number [0; n) outside exclude map.
|
||||||
// exclude must contain no more than n-1 elements [0; n)
|
// Panics if len(exclude) >= n.
|
||||||
func nextRandUint64(n uint64, exclude map[uint64]struct{}) uint64 {
|
func nextRandUint64(n uint64, exclude map[uint64]struct{}) uint64 {
|
||||||
ln := uint64(len(exclude))
|
ln := uint64(len(exclude))
|
||||||
|
ind := rand.Uint64() % (n - ln)
|
||||||
ind := randUint64(n - ln)
|
|
||||||
|
|
||||||
for i := ind; ; i++ {
|
for i := ind; ; i++ {
|
||||||
if _, ok := exclude[i]; !ok {
|
if _, ok := exclude[i]; !ok {
|
||||||
|
@ -17,8 +16,3 @@ func nextRandUint64(n uint64, exclude map[uint64]struct{}) uint64 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns random uint64 number [0, n).
|
|
||||||
func randUint64(n uint64) uint64 {
|
|
||||||
return rand.Uint64(rand.New(), int64(n))
|
|
||||||
}
|
|
||||||
|
|
|
@ -6,41 +6,39 @@ import (
|
||||||
mrand "math/rand"
|
mrand "math/rand"
|
||||||
)
|
)
|
||||||
|
|
||||||
type cryptoSource struct{}
|
var source = mrand.New(&cryptoSource{})
|
||||||
|
|
||||||
// Read is alias for crypto/rand.Read.
|
|
||||||
var Read = crand.Read
|
|
||||||
|
|
||||||
// New constructs the source of random numbers.
|
|
||||||
func New() *mrand.Rand {
|
|
||||||
return mrand.New(&cryptoSource{})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *cryptoSource) Seed(int64) {}
|
|
||||||
|
|
||||||
func (s *cryptoSource) Int63() int64 {
|
|
||||||
return int64(s.Uint63())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *cryptoSource) Uint63() uint64 {
|
|
||||||
buf := make([]byte, 8)
|
|
||||||
if _, err := crand.Read(buf); err != nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
return binary.BigEndian.Uint64(buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uint64 returns a random uint64 value.
|
// Uint64 returns a random uint64 value.
|
||||||
func Uint64(r *mrand.Rand, max int64) uint64 {
|
func Uint64() uint64 {
|
||||||
if max <= 0 {
|
return source.Uint64()
|
||||||
return 0
|
}
|
||||||
}
|
|
||||||
|
// Uint64 returns a random uint32 value.
|
||||||
var i int64 = -1
|
func Uint32() uint32 {
|
||||||
for i < 0 {
|
return source.Uint32()
|
||||||
i = r.Int63n(max)
|
}
|
||||||
}
|
|
||||||
|
// Shuffle randomizes the order of elements.
|
||||||
return uint64(i)
|
// n is the number of elements. Shuffle panics if n < 0.
|
||||||
|
// swap swaps the elements with indexes i and j.
|
||||||
|
func Shuffle(n int, swap func(i, j int)) {
|
||||||
|
source.Shuffle(n, swap)
|
||||||
|
}
|
||||||
|
|
||||||
|
// cryptoSource is math/rand.Source which takes entropy via crypto/rand.
|
||||||
|
type cryptoSource struct{}
|
||||||
|
|
||||||
|
// Seed implements math/rand.Source.
|
||||||
|
func (s *cryptoSource) Seed(int64) {}
|
||||||
|
|
||||||
|
// Int63 implements math/rand.Source.
|
||||||
|
func (s *cryptoSource) Int63() int64 {
|
||||||
|
return int64(s.Uint64() >> 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uint64 implements math/rand.Source64.
|
||||||
|
func (s *cryptoSource) Uint64() uint64 {
|
||||||
|
var buf [8]byte
|
||||||
|
_, _ = crand.Read(buf[:]) // always returns nil
|
||||||
|
return binary.BigEndian.Uint64(buf[:])
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue