diff options
author | Daniel Olshansky <olshansky.daniel@gmail.com> | 2022-02-04 14:55:37 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-02-04 14:55:37 -0500 |
commit | c765903e0d75c86490d3060db842cc3a013e6da0 (patch) | |
tree | fee0487caea2939763a915024a7362db728066da | |
parent | f0b85f69e73fd136eafbc68884781ffb0c4505dd (diff) |
Removed hard-coded constant in `sortition.go`. (#3558)
## Summary
Remove a hardcoded constant in sortition.go which was
used as the denominator in determining the selection ratio.
This clarifies what the maximum possible output size is of
the output VRF based on the SHA algorithm used to generate it.
## Purpose
This is simply a code quality change to make it easier to read and
understand without any focus on new functionality or performance.
It is unlikely that the VRF SHA length used by Algorand will changed,
so the generalization to a dynamic length based on the length of the
Crypto digest is only for the reader.
The use of an `init` function to initialize the `maxFloat` once rather than
anytime `sortition` runs is a minor optimization, but likely to be neglibile
in the grand scheme of things.
## Test Plan
Due to the usage of C src code, a simple `go test -v ./data/committee/sortition/`
cannot be executed without the proper configurations. However, circle CI
should be able to execute the unit tests automatically and verify the changes.
Recommendation: Running the recommended make targets to test the changes
did not automatically due to missing dependencies, so potentially a Dockerfile
could help resolve this for future contributors.
-rw-r--r-- | data/committee/sortition/sortition.go | 26 |
1 files changed, 19 insertions, 7 deletions
diff --git a/data/committee/sortition/sortition.go b/data/committee/sortition/sortition.go index f8a38179d..5b8300add 100644 --- a/data/committee/sortition/sortition.go +++ b/data/committee/sortition/sortition.go @@ -22,12 +22,19 @@ package sortition // #include <stdlib.h> // #include "sortition.h" import "C" + import ( + "fmt" "math/big" + "strings" "github.com/algorand/go-algorand/crypto" ) +const precision = uint(8 * (crypto.DigestSize + 1)) + +var maxFloat *big.Float + // Select runs the sortition function and returns the number of time the key was selected func Select(money uint64, totalMoney uint64, expectedSize float64, vrfOutput crypto.Digest) uint64 { binomialN := float64(money) @@ -36,18 +43,23 @@ func Select(money uint64, totalMoney uint64, expectedSize float64, vrfOutput cry t := &big.Int{} t.SetBytes(vrfOutput[:]) - precision := uint(8 * (len(vrfOutput) + 1)) - max, b, err := big.ParseFloat("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 0, precision, big.ToNearestEven) - if b != 16 || err != nil { - panic("failed to parse big float constant in sortition") - } - h := big.Float{} h.SetPrec(precision) h.SetInt(t) ratio := big.Float{} - cratio, _ := ratio.Quo(&h, max).Float64() + cratio, _ := ratio.Quo(&h, maxFloat).Float64() return uint64(C.sortition_binomial_cdf_walk(C.double(binomialN), C.double(binomialP), C.double(cratio), C.uint64_t(money))) } + +func init() { + var b int + var err error + maxFloatString := fmt.Sprintf("0x%s", strings.Repeat("ff", crypto.DigestSize)) + maxFloat, b, err = big.ParseFloat(maxFloatString, 0, precision, big.ToNearestEven) + if b != 16 || err != nil { + err = fmt.Errorf("failed to parse big float constant in sortition : %w", err) + panic(err) + } +} |