func setupUPnP(r rand.Source) int { var externalPort = 0 if len(cfg.Options.ListenAddress) == 1 { _, portStr, err := net.SplitHostPort(cfg.Options.ListenAddress[0]) if err != nil { l.Warnln(err) } else { // Set up incoming port forwarding, if necessary and possible port, _ := strconv.Atoi(portStr) igd, err := upnp.Discover() if err == nil { for i := 0; i < 10; i++ { r := 1024 + int(r.Int63()%(65535-1024)) err := igd.AddPortMapping(upnp.TCP, r, port, "syncthing", 0) if err == nil { externalPort = r l.Infoln("Created UPnP port mapping - external port", externalPort) break } } if externalPort == 0 { l.Warnln("Failed to create UPnP port mapping") } } else { l.Infof("No UPnP gateway detected") if debugNet { l.Debugf("UPnP: %v", err) } } } } else { l.Warnln("Multiple listening addresses; not attempting UPnP port mapping") } return externalPort }
// randHash generates a "random" hash using a deterministic source. func randHash(r rand.Source) *chainhash.Hash { hash := new(chainhash.Hash) for i := 0; i < chainhash.HashSize/2; i++ { random := uint64(r.Int63()) randByte1 := random % 255 randByte2 := (random >> 8) % 255 hash[i] = uint8(randByte1) hash[i+1] = uint8(randByte2) } return hash }
// pickRandWinners picks tickets per block many random "winners" and returns // their indexes. func pickRandWinners(sz int, r rand.Source) []int { if sz == 0 { panic("bad sz!") } perBlock := int(chaincfg.MainNetParams.TicketsPerBlock) winners := make([]int, perBlock) for i := 0; i < perBlock; i++ { winners[i] = int(r.Int63() % int64(sz)) } return winners }
func newNodeWithSource(b *tierBase, others []*node, idSource rand.Source) *node { // The ids should be unique, non-zero, and random so others don't base // their node references on indexes. var id uint64 for id == 0 { id = (uint64(idSource.Int63()) << 63) | uint64(idSource.Int63()) for _, n := range others { if n.id == id { id = 0 break } } } return &node{tierBase: b, id: id} }
func randString(n int, src rand.Source) string { b := make([]byte, n) // A rand.Int63() generates 63 random bits, enough for letterIdxMax letters! for i, cache, remain := n-1, src.Int63(), letterIdxMax; i >= 0; { if remain == 0 { cache, remain = src.Int63(), letterIdxMax } if idx := int(cache & letterIdxMask); idx < len(letterBytes) { b[i] = letterBytes[idx] i-- } cache >>= letterIdxBits remain-- } return string(b[0:30]) }
// RandStringBytesMaskImprSrc source: http://stackoverflow.com/a/31832326 func randStringBytesMaskImprSrc(n int, src rand.Source) string { b := make([]byte, n) for i, cache, remain := n-1, src.Int63(), letterIdxMax; i >= 0; { if remain == 0 { cache, remain = src.Int63(), letterIdxMax } if idx := int(cache & letterIdxMask); idx < len(letterBytes) { b[i] = letterBytes[idx] i-- } cache >>= letterIdxBits remain-- } return string(b) }
// The probability that k out of n random integers have popcount x follows a // binomial distribution. func Popcount(r rand.Source) float64 { counts := [64]int64{} for i := 0; i < popcountN; i++ { x := r.Int63() // popcount_3() from http://en.wikipedia.org/wiki/Hamming_weight x -= x >> 1 & 0x5555555555555555 x = x&0x3333333333333333 + x>>2&0x3333333333333333 x = (x + x>>4) & 0x0f0f0f0f0f0f0f0f x = x * 0x0101010101010101 >> 56 // popcount counts[x]++ } var chi2 float64 for i, v := range counts { d := float64(v)*binomialBitScale - binomialBitPMF[i] chi2 += d * d / binomialBitPMF[i] } println(chi2) return 1 - LowerGamma(30, chi2/2)*1.13099628864477e-31 }
// The lagged survival test applies the survival test to an RNG, skipping N // iterates between each sample. func LaggedSurvival(r rand.Source, N int) float64 { // hax teh copypasta //TODO: prevent first iteration from matching consec := [63]int{} bits := [63]bool{} counts := make(map[int]int) for i := 0; i < laggedSurvN; i++ { x := r.Int63() for b := 0; b < 63; b++ { if ((x & (1 << uint(b))) != 0) == bits[b] { // bit survived consec[b]++ } else { // bit changed bits[b] = !bits[b] counts[consec[b]] = counts[consec[b]] + 1 consec[b] = 0 } } for n := 0; n < N; n++ { r.Int63() } } maximum := len(counts) for i := range counts { if i > maximum { maximum = i } } // If the source is truly random, then there should be half as many hits // for counts[n] as there were for counts[n-1], with counts[0] being the // maximum. //TODO: E should be calculated from the median E := float64(counts[0]) var chi2 float64 for i := 1; i < maximum; i++ { E /= 2 d := float64(counts[i]) - E chi2 += d * d / E } k_2 := float64(maximum-2) / 2 return 1 - LowerGamma(k_2, chi2/2)/math.Gamma(k_2) }
// Survival Parity applies Survival to the parity of the random values. func SurvivalParity(r rand.Source) float64 { consec := 0 var parity int64 = -1 // prevent the first iteration from matching counts := map[int]int{0: -1} for i := 0; i < survivalParityN; i++ { // software parity because I do not enjoy setting up asm to be used // http://www-graphics.stanford.edu/~seander/bithacks.html#ParityMultiply x := r.Int63() x ^= x >> 1 x ^= x >> 2 x = (x & 0x1111111111111111) * 0x1111111111111111 x = x >> 60 & 1 // parity complete if x == parity { consec++ } else { parity = x counts[consec] = counts[consec] + 1 consec = 0 } } // copypasta var maximum int for i := range counts { if i > maximum { maximum = i } } // If the source is truly random, then there should be half as many hits // for counts[n] as there were for counts[n-1], with counts[0] being the // maximum. //TODO: E should be calculated from the median. This is causing crc64-ecma to NaN. E := float64(counts[0]) var chi2 float64 for i := 1; i < maximum; i++ { E /= 2 d := float64(counts[i]) - E chi2 += d * d / E } k_2 := float64(maximum-2) / 2 return 1 - LowerGamma(k_2, chi2/2)/math.Gamma(k_2) }
// Generates a random string given the random source and the fixed length func NextString(src rand.Source, length int) string { const alphabet = "azertyuiopqsdfghjklmwxcvbn" result := make([]byte, length) offset := 0 for { val := src.Int63() for i := 0; i < 8; i++ { result[offset] = alphabet[val%int64(len(alphabet))] length-- if length == 0 { return string(result) } offset++ val >>= 8 } } panic("unreachable") }
func newNodeWithSource(b *Builder, tb *tierBase, others []*node, idSource rand.Source) (*node, error) { mask := uint64(math.MaxUint64) if b != nil { mask = (uint64(1) << uint64(b.idBits)) - 1 if uint64(len(others)) >= mask { return nil, fmt.Errorf("no more ID space; bits %d, nodes %d", b.idBits, len(others)) } } // The ids should be unique, non-zero, and random so others don't base // their node references on indexes. var id uint64 if mask == math.MaxUint64 { id = (uint64(idSource.Int63()) << 63) | uint64(idSource.Int63()) } else { id = uint64(idSource.Int63()) & mask } if id == 0 { id = 1 } sid := id L: for _, n := range others { if n.id == id { id++ if id == sid { // This shouldn't happen because the top of the func should've // caught that the ID space was used up; but, just in case. return nil, fmt.Errorf("no more ID space; bits %d, nodes %d, wrapped scan", b.idBits, len(others)) } if id > mask { id = 1 } goto L } } return &node{builder: b, tierBase: tb, id: id}, nil }
// The Hamming distances between the nth values of one RNG seeded with two // values with Hamming distance 1 should be binomially distributed. This test // derives its name from the bit avalanche effect. // // NOTE: ReaderSource RNGs (e.g. crypto-reader) will be incorrect. func Avalanche(r rand.Source) float64 { // hax teh copypasta from popcount counts := [64]int64{} v := r.Int63() var a, b int64 for i := 0; i < avalancheN; i++ { for j := uint(0); j < 63; j++ { r.Seed(v) for k := 0; k < avalancheFuse; k++ { r.Int63() } a = r.Int63() r.Seed(v ^ (1 << j)) for k := 0; k < avalancheFuse; k++ { r.Int63() } b = r.Int63() // Hamming distance from a to b is equal to popcount(a^b) x := a ^ b // popcount_3() from http://en.wikipedia.org/wiki/Hamming_weight x -= x >> 1 & 0x5555555555555555 x = x&0x3333333333333333 + x>>2&0x3333333333333333 x = (x + x>>4) & 0x0f0f0f0f0f0f0f0f x = x * 0x0101010101010101 >> 56 // popcount counts[x]++ } v = b // silly to use a^b because that depends upon what we're testing } var chi2 float64 for i, v := range counts { d := float64(v)*binomialBitScale - binomialBitPMF[i] chi2 += d * d / binomialBitPMF[i] } return 1 - LowerGamma(30, chi2/2)*1.13099628864477e-31 }