common: no more relying on math/rand.DefaultSource

Fixes https://github.com/tendermint/tmlibs/issues/99
Updates https://github.com/tendermint/tendermint/issues/973

Removed usages of math/rand.DefaultSource in favour of our
own source that's seeded with a completely random source
and is safe for use in concurrent in multiple goroutines.
Also extend some functionality that the stdlib exposes such as
* RandPerm
* RandIntn
* RandInt31
* RandInt63

Also added an integration test whose purpose is to be run as
a consistency check to ensure that our results never repeat
hence that our internal PRNG is uniquely seeded each time.
This integration test can be triggered by setting environment variable:
`TENDERMINT_INTEGRATION_TESTS=true`
for example
```shell
TENDERMINT_INTEGRATION_TESTS=true go test
```
This commit is contained in:
Emmanuel Odeke
2017-12-13 22:53:02 -07:00
parent a80b66268f
commit 29471d75cb
3 changed files with 178 additions and 26 deletions

View File

@ -3,7 +3,6 @@ package common
import (
"encoding/binary"
"fmt"
"math/rand"
"strings"
"sync"
)
@ -212,12 +211,12 @@ func (bA *BitArray) PickRandom() (int, bool) {
if length == 0 {
return 0, false
}
randElemStart := rand.Intn(length)
randElemStart := RandIntn(length)
for i := 0; i < length; i++ {
elemIdx := ((i + randElemStart) % length)
if elemIdx < length-1 {
if bA.Elems[elemIdx] > 0 {
randBitStart := rand.Intn(64)
randBitStart := RandIntn(64)
for j := 0; j < 64; j++ {
bitIdx := ((j + randBitStart) % 64)
if (bA.Elems[elemIdx] & (uint64(1) << uint(bitIdx))) > 0 {
@ -232,7 +231,7 @@ func (bA *BitArray) PickRandom() (int, bool) {
if elemBits == 0 {
elemBits = 64
}
randBitStart := rand.Intn(elemBits)
randBitStart := RandIntn(elemBits)
for j := 0; j < elemBits; j++ {
bitIdx := ((j + randBitStart) % elemBits)
if (bA.Elems[elemIdx] & (uint64(1) << uint(bitIdx))) > 0 {