diff --git a/api/server.go b/api/server.go index dda480b4cf48..4527f3a23fe0 100644 --- a/api/server.go +++ b/api/server.go @@ -156,7 +156,8 @@ func rejectMiddleware(handler http.Handler, ctx *snow.Context) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // If chain isn't done bootstrapping, ignore API calls if !ctx.IsBootstrapped() { w.WriteHeader(http.StatusServiceUnavailable) - w.Write([]byte("API call rejected because chain is not done bootstrapping")) + // Doesn't matter if there's an error while writing. They'll get the StatusServiceUnavailable code. + _, _ = w.Write([]byte("API call rejected because chain is not done bootstrapping")) } else { handler.ServeHTTP(w, r) } diff --git a/network/network.go b/network/network.go index 4de789f1b5a5..ea99eec0013c 100644 --- a/network/network.go +++ b/network/network.go @@ -47,6 +47,8 @@ const ( defaultPingFrequency = 3 * defaultPingPongTimeout / 4 ) +func init() { rand.Seed(time.Now().UnixNano()) } + // Network defines the functionality of the networking library. type Network interface { // All consensus messages can be sent through this interface. Thread safety @@ -225,19 +227,22 @@ func NewNetwork( pingFrequency time.Duration, ) Network { netw := &network{ - log: log, - id: id, - ip: ip, - networkID: networkID, - version: version, - parser: parser, - listener: listener, - dialer: dialer, - serverUpgrader: serverUpgrader, - clientUpgrader: clientUpgrader, - vdrs: vdrs, - beacons: beacons, - router: router, + log: log, + id: id, + ip: ip, + networkID: networkID, + version: version, + parser: parser, + listener: listener, + dialer: dialer, + serverUpgrader: serverUpgrader, + clientUpgrader: clientUpgrader, + vdrs: vdrs, + beacons: beacons, + router: router, + // This field just makes sure we don't connect to ourselves when TLS is + // disabled. So, cryptographically secure random number generation isn't + // used here. nodeID: rand.Uint32(), initialReconnectDelay: initialReconnectDelay, maxReconnectDelay: maxReconnectDelay, @@ -883,8 +888,9 @@ func (n *network) connectTo(ip utils.IPDesc) { delay = n.initialReconnectDelay } - // Ignore weak randomness warnings in calculating timeouts because true - // randomness is unnecessary here + // Randomization is only performed here to distribute reconnection + // attempts to a node that previously shut down. This doesn't require + // cryptographically secure random number generation. delay = time.Duration(float64(delay) * (1 + rand.Float64())) if delay > n.maxReconnectDelay { // set the timeout to [.75, 1) * maxReconnectDelay diff --git a/node/node.go b/node/node.go index c5d378bfa086..95acaa0cc108 100644 --- a/node/node.go +++ b/node/node.go @@ -63,7 +63,7 @@ var ( genesisHashKey = []byte("genesisID") // Version is the version of this code - Version = version.NewDefaultVersion("avalanche", 0, 6, 3) + Version = version.NewDefaultVersion("avalanche", 0, 6, 4) versionParser = version.NewDefaultParser() ) @@ -443,7 +443,9 @@ func (n *Node) initChainManager(avaxAssetID ids.ID) error { // to its own local validator manager (which isn't used for sampling) if !n.Config.EnableStaking { defaultSubnetValidators := validators.NewSet() - defaultSubnetValidators.Add(validators.NewValidator(n.ID, 1)) + if err := defaultSubnetValidators.Add(validators.NewValidator(n.ID, 1)); err != nil { + return fmt.Errorf("couldn't add validator to Default Subnet: %w", err) + } vdrs = validators.NewManager() vdrs.PutValidatorSet(constants.DefaultSubnetID, defaultSubnetValidators) } diff --git a/utils/sampler/uniform_replacer.go b/utils/sampler/uniform_replacer.go index 33414e28e43a..816181ba83c4 100644 --- a/utils/sampler/uniform_replacer.go +++ b/utils/sampler/uniform_replacer.go @@ -51,6 +51,8 @@ func (s *uniformReplacer) Sample(count int) ([]uint64, error) { drawn := make(defaultMap, count) results := make([]uint64, count) for i := 0; i < count; i++ { + // We don't use a cryptographically secure source of randomness here, as + // there's no need to ensure a truly random sampling. draw := uint64(rand.Int63n(int64(s.length-uint64(i)))) + uint64(i) ret := drawn.get(draw, draw) diff --git a/utils/sampler/uniform_resample.go b/utils/sampler/uniform_resample.go index 8912c0383c5c..751d577718d3 100644 --- a/utils/sampler/uniform_resample.go +++ b/utils/sampler/uniform_resample.go @@ -39,15 +39,17 @@ func (s *uniformResample) Sample(count int) ([]uint64, error) { drawn := make(map[uint64]struct{}, count) results := make([]uint64, count) - for i := 0; i < count; i++ { + for i := 0; i < count; { + // We don't use a cryptographically secure source of randomness here, as + // there's no need to ensure a truly random sampling. draw := uint64(rand.Int63n(int64(s.length))) if _, ok := drawn[draw]; ok { - i-- continue } drawn[draw] = struct{}{} results[i] = draw + i++ } return results, nil diff --git a/utils/sampler/weighted_best.go b/utils/sampler/weighted_best.go index 47851d519ba9..587c7e6f61c7 100644 --- a/utils/sampler/weighted_best.go +++ b/utils/sampler/weighted_best.go @@ -52,12 +52,18 @@ func (s *weightedBest) Initialize(weights []uint64) error { if totalWeight > 0 { samples = make([]uint64, s.benchmarkIterations) for i := range samples { + // We don't need cryptographically secure random number generation + // here, as the generated numbers are only used to perform an + // optimistic benchmark. Which means the results could be arbitrary + // and the correctness of the implementation wouldn't be effected. samples[i] = uint64(rand.Int63n(int64(totalWeight))) } } s.Weighted = nil bestDuration := time.Duration(math.MaxInt64) + +samplerLoop: for _, sampler := range s.samplers { if err := sampler.Initialize(weights); err != nil { continue @@ -66,7 +72,7 @@ func (s *weightedBest) Initialize(weights []uint64) error { start := s.clock.Time() for _, sample := range samples { if _, err := sampler.Sample(sample); err != nil { - continue + continue samplerLoop } } end := s.clock.Time() diff --git a/vms/platformvm/common_blocks.go b/vms/platformvm/common_blocks.go index 67d53f847965..b62f92d57552 100644 --- a/vms/platformvm/common_blocks.go +++ b/vms/platformvm/common_blocks.go @@ -270,11 +270,11 @@ func (ddb *DoubleDecisionBlock) Accept() error { // Update the state of the chain in the database if err := ddb.onAcceptDB.Commit(); err != nil { - ddb.vm.Ctx.Log.Warn("unable to commit onAcceptDB") + ddb.vm.Ctx.Log.Warn("unable to commit onAcceptDB: %s", err) return err } if err := ddb.vm.DB.Commit(); err != nil { - ddb.vm.Ctx.Log.Warn("unable to commit vm's DB") + ddb.vm.Ctx.Log.Warn("unable to commit vm's DB: %s", err) return err } @@ -282,7 +282,10 @@ func (ddb *DoubleDecisionBlock) Accept() error { child.setBaseDatabase(ddb.vm.DB) } if ddb.onAcceptFunc != nil { - ddb.onAcceptFunc() + if err := ddb.onAcceptFunc(); err != nil { + ddb.vm.Ctx.Log.Warn("error executing OnAcceptFunc(): %s", err) + return err + } } // remove this block and its parent from memory