summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Olshansky <olshansky.daniel@gmail.com>2022-02-04 14:55:37 -0500
committerGitHub <noreply@github.com>2022-02-04 14:55:37 -0500
commitc765903e0d75c86490d3060db842cc3a013e6da0 (patch)
treefee0487caea2939763a915024a7362db728066da
parentf0b85f69e73fd136eafbc68884781ffb0c4505dd (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.go26
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)
+ }
+}