github.com/vipernet-xyz/tendermint-core@v0.32.0/libs/rand/random.go (about) 1 package rand 2 3 import ( 4 crand "crypto/rand" 5 mrand "math/rand" 6 "sync" 7 "time" 8 ) 9 10 const ( 11 strChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" // 62 characters 12 ) 13 14 // Rand is a prng, that is seeded with OS randomness. 15 // The OS randomness is obtained from crypto/rand, however none of the provided 16 // methods are suitable for cryptographic usage. 17 // They all utilize math/rand's prng internally. 18 // 19 // All of the methods here are suitable for concurrent use. 20 // This is achieved by using a mutex lock on all of the provided methods. 21 type Rand struct { 22 sync.Mutex 23 rand *mrand.Rand 24 } 25 26 var grand *Rand 27 28 func init() { 29 grand = NewRand() 30 grand.init() 31 } 32 33 func NewRand() *Rand { 34 rand := &Rand{} 35 rand.init() 36 return rand 37 } 38 39 func (r *Rand) init() { 40 bz := cRandBytes(8) 41 var seed uint64 42 for i := 0; i < 8; i++ { 43 seed |= uint64(bz[i]) 44 seed <<= 8 45 } 46 r.reset(int64(seed)) 47 } 48 49 func (r *Rand) reset(seed int64) { 50 r.rand = mrand.New(mrand.NewSource(seed)) 51 } 52 53 //---------------------------------------- 54 // Global functions 55 56 func Seed(seed int64) { 57 grand.Seed(seed) 58 } 59 60 func Str(length int) string { 61 return grand.Str(length) 62 } 63 64 func Uint16() uint16 { 65 return grand.Uint16() 66 } 67 68 func Uint32() uint32 { 69 return grand.Uint32() 70 } 71 72 func Uint64() uint64 { 73 return grand.Uint64() 74 } 75 76 func Uint() uint { 77 return grand.Uint() 78 } 79 80 func Int16() int16 { 81 return grand.Int16() 82 } 83 84 func Int32() int32 { 85 return grand.Int32() 86 } 87 88 func Int64() int64 { 89 return grand.Int64() 90 } 91 92 func Int() int { 93 return grand.Int() 94 } 95 96 func Int31() int32 { 97 return grand.Int31() 98 } 99 100 func Int31n(n int32) int32 { 101 return grand.Int31n(n) 102 } 103 104 func Int63() int64 { 105 return grand.Int63() 106 } 107 108 func Int63n(n int64) int64 { 109 return grand.Int63n(n) 110 } 111 112 func Bool() bool { 113 return grand.Bool() 114 } 115 116 func Float32() float32 { 117 return grand.Float32() 118 } 119 120 func Float64() float64 { 121 return grand.Float64() 122 } 123 124 func Time() time.Time { 125 return grand.Time() 126 } 127 128 func Bytes(n int) []byte { 129 return grand.Bytes(n) 130 } 131 132 func Intn(n int) int { 133 return grand.Intn(n) 134 } 135 136 func Perm(n int) []int { 137 return grand.Perm(n) 138 } 139 140 //---------------------------------------- 141 // Rand methods 142 143 func (r *Rand) Seed(seed int64) { 144 r.Lock() 145 r.reset(seed) 146 r.Unlock() 147 } 148 149 // Str constructs a random alphanumeric string of given length. 150 func (r *Rand) Str(length int) string { 151 chars := []byte{} 152 MAIN_LOOP: 153 for { 154 val := r.Int63() 155 for i := 0; i < 10; i++ { 156 v := int(val & 0x3f) // rightmost 6 bits 157 if v >= 62 { // only 62 characters in strChars 158 val >>= 6 159 continue 160 } else { 161 chars = append(chars, strChars[v]) 162 if len(chars) == length { 163 break MAIN_LOOP 164 } 165 val >>= 6 166 } 167 } 168 } 169 170 return string(chars) 171 } 172 173 func (r *Rand) Uint16() uint16 { 174 return uint16(r.Uint32() & (1<<16 - 1)) 175 } 176 177 func (r *Rand) Uint32() uint32 { 178 r.Lock() 179 u32 := r.rand.Uint32() 180 r.Unlock() 181 return u32 182 } 183 184 func (r *Rand) Uint64() uint64 { 185 return uint64(r.Uint32())<<32 + uint64(r.Uint32()) 186 } 187 188 func (r *Rand) Uint() uint { 189 r.Lock() 190 i := r.rand.Int() 191 r.Unlock() 192 return uint(i) 193 } 194 195 func (r *Rand) Int16() int16 { 196 return int16(r.Uint32() & (1<<16 - 1)) 197 } 198 199 func (r *Rand) Int32() int32 { 200 return int32(r.Uint32()) 201 } 202 203 func (r *Rand) Int64() int64 { 204 return int64(r.Uint64()) 205 } 206 207 func (r *Rand) Int() int { 208 r.Lock() 209 i := r.rand.Int() 210 r.Unlock() 211 return i 212 } 213 214 func (r *Rand) Int31() int32 { 215 r.Lock() 216 i31 := r.rand.Int31() 217 r.Unlock() 218 return i31 219 } 220 221 func (r *Rand) Int31n(n int32) int32 { 222 r.Lock() 223 i31n := r.rand.Int31n(n) 224 r.Unlock() 225 return i31n 226 } 227 228 func (r *Rand) Int63() int64 { 229 r.Lock() 230 i63 := r.rand.Int63() 231 r.Unlock() 232 return i63 233 } 234 235 func (r *Rand) Int63n(n int64) int64 { 236 r.Lock() 237 i63n := r.rand.Int63n(n) 238 r.Unlock() 239 return i63n 240 } 241 242 func (r *Rand) Float32() float32 { 243 r.Lock() 244 f32 := r.rand.Float32() 245 r.Unlock() 246 return f32 247 } 248 249 func (r *Rand) Float64() float64 { 250 r.Lock() 251 f64 := r.rand.Float64() 252 r.Unlock() 253 return f64 254 } 255 256 func (r *Rand) Time() time.Time { 257 return time.Unix(int64(r.Uint64()), 0) 258 } 259 260 // Bytes returns n random bytes generated from the internal 261 // prng. 262 func (r *Rand) Bytes(n int) []byte { 263 // cRandBytes isn't guaranteed to be fast so instead 264 // use random bytes generated from the internal PRNG 265 bs := make([]byte, n) 266 for i := 0; i < len(bs); i++ { 267 bs[i] = byte(r.Int() & 0xFF) 268 } 269 return bs 270 } 271 272 // Intn returns, as an int, a uniform pseudo-random number in the range [0, n). 273 // It panics if n <= 0. 274 func (r *Rand) Intn(n int) int { 275 r.Lock() 276 i := r.rand.Intn(n) 277 r.Unlock() 278 return i 279 } 280 281 // Bool returns a uniformly random boolean 282 func (r *Rand) Bool() bool { 283 // See https://github.com/golang/go/issues/23804#issuecomment-365370418 284 // for reasoning behind computing like this 285 return r.Int63()%2 == 0 286 } 287 288 // Perm returns a pseudo-random permutation of n integers in [0, n). 289 func (r *Rand) Perm(n int) []int { 290 r.Lock() 291 perm := r.rand.Perm(n) 292 r.Unlock() 293 return perm 294 } 295 296 // NOTE: This relies on the os's random number generator. 297 // For real security, we should salt that with some seed. 298 // See github.com/tendermint/tendermint/crypto for a more secure reader. 299 func cRandBytes(numBytes int) []byte { 300 b := make([]byte, numBytes) 301 _, err := crand.Read(b) 302 if err != nil { 303 panic(err) 304 } 305 return b 306 }