Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
14eb119
handle unhandled errors. Comment in places we use math/rand so future…
Aug 21, 2020
1ba580a
added new sampling algos and optimized initializations
StephenButtolph Aug 23, 2020
f0cb44c
add a maximum timeout value to prevent extremely long timeouts
StephenButtolph Aug 23, 2020
a15dd9b
fixed timeout tests
StephenButtolph Aug 23, 2020
bc432df
Merge pull request #318 from StephenButtolph/max-reasonable-timeout
StephenButtolph Aug 23, 2020
16b6579
bumped version
StephenButtolph Aug 23, 2020
f6a26c6
Merge branch 'dev' into version-bump-0.6.3
StephenButtolph Aug 23, 2020
170716e
Merge pull request #320 from StephenButtolph/version-bump-0.6.3
StephenButtolph Aug 23, 2020
c6e95f0
Merge branch 'dev' into sampling
StephenButtolph Aug 23, 2020
053a094
Merge pull request #317 from StephenButtolph/sampling
StephenButtolph Aug 23, 2020
5d67d92
removed usage of sh
StephenButtolph Aug 24, 2020
eddd39f
standardized usage of path and filepath
StephenButtolph Aug 24, 2020
70c4da3
Merge branch 'dev' into win-c-chain
StephenButtolph Aug 24, 2020
e00a68b
Merge pull request #322 from StephenButtolph/win-c-chain
StephenButtolph Aug 24, 2020
7d968d7
merged
StephenButtolph Aug 24, 2020
74e667a
Added more detailed comments for non-crypto secure random sampling
StephenButtolph Aug 24, 2020
989dc53
Added more detailed comments in network.go around random number gener…
StephenButtolph Aug 24, 2020
f0facba
v0.6.4 version bump
StephenButtolph Aug 24, 2020
02cf513
Merge pull request #315 from ava-labs/handle-silent-errors
StephenButtolph Aug 24, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion api/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
4 changes: 2 additions & 2 deletions ipcs/chainipc.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ package ipcs

import (
"fmt"
"path"
"path/filepath"

"github.com/ava-labs/gecko/ids"
"github.com/ava-labs/gecko/snow/triggers"
Expand Down Expand Up @@ -87,5 +87,5 @@ func (cipcs *ChainIPCs) Unpublish(chainID ids.ID) (bool, error) {
}

func ipcURL(ctx context, chainID ids.ID, eventType string) string {
return path.Join(ctx.path, fmt.Sprintf("%d-%s-%s", ctx.networkID, chainID.String(), eventType))
return filepath.Join(ctx.path, fmt.Sprintf("%d-%s-%s", ctx.networkID, chainID.String(), eventType))
}
4 changes: 2 additions & 2 deletions main/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ package main

import (
"fmt"
"path"
"path/filepath"

"github.com/ava-labs/gecko/nat"
"github.com/ava-labs/gecko/node"
Expand All @@ -22,7 +22,7 @@ func main() {
}

config := Config.LoggingConfig
config.Directory = path.Join(config.Directory, "node")
config.Directory = filepath.Join(config.Directory, "node")
factory := logging.NewFactory(config)
defer factory.Close()

Expand Down
36 changes: 21 additions & 15 deletions network/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down
10 changes: 6 additions & 4 deletions node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
"io/ioutil"
"net"
"os"
"path"
"path/filepath"
"sync"
"time"

Expand Down Expand Up @@ -63,7 +63,7 @@ var (
genesisHashKey = []byte("genesisID")

// Version is the version of this code
Version = version.NewDefaultVersion("avalanche", 0, 6, 2)
Version = version.NewDefaultVersion("avalanche", 0, 6, 4)
versionParser = version.NewDefaultParser()
)

Expand Down Expand Up @@ -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)
}
Expand All @@ -461,7 +463,7 @@ func (n *Node) initChainManager(avaxAssetID ids.ID) error {
Fee: n.Config.TxFee,
}),
n.vmManager.RegisterVMFactory(genesis.EVMID, &rpcchainvm.Factory{
Path: path.Join(n.Config.PluginDir, "evm"),
Path: filepath.Join(n.Config.PluginDir, "evm"),
}),
n.vmManager.RegisterVMFactory(spdagvm.ID, &spdagvm.Factory{
TxFee: n.Config.TxFee,
Expand Down
3 changes: 2 additions & 1 deletion snow/networking/timeout/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ func (m *Manager) Initialize(
return m.tm.Initialize(
time.Second,
500*time.Millisecond,
2,
10*time.Second,
1.1,
time.Millisecond,
namespace,
registerer,
Expand Down
8 changes: 8 additions & 0 deletions snow/validators/set.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,14 @@ func NewSet() Set {
}
}

// NewBestSet returns a new, empty set of validators.
func NewBestSet(expectedSampleSize int) Set {
return &set{
vdrMap: make(map[[20]byte]int),
sampler: sampler.NewBestWeightedWithoutReplacement(expectedSampleSize),
}
}

// set of validators. Validator function results are cached. Therefore, to
// update a validators weight, one should ensure to call add with the updated
// validator.
Expand Down
8 changes: 3 additions & 5 deletions utils/logging/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@

package logging

import (
"path"
)
import "path/filepath"

// Factory ...
type Factory interface {
Expand Down Expand Up @@ -42,7 +40,7 @@ func (f *factory) Make() (Logger, error) {
func (f *factory) MakeChain(chainID string, subdir string) (Logger, error) {
config := f.config
config.MsgPrefix = chainID + " Chain"
config.Directory = path.Join(config.Directory, "chain", chainID, subdir)
config.Directory = filepath.Join(config.Directory, "chain", chainID, subdir)

log, err := New(config)
if err == nil {
Expand All @@ -54,7 +52,7 @@ func (f *factory) MakeChain(chainID string, subdir string) (Logger, error) {
// MakeSubdir ...
func (f *factory) MakeSubdir(subdir string) (Logger, error) {
config := f.config
config.Directory = path.Join(config.Directory, subdir)
config.Directory = filepath.Join(config.Directory, subdir)

log, err := New(config)
if err == nil {
Expand Down
4 changes: 2 additions & 2 deletions utils/logging/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"bufio"
"fmt"
"os"
"path"
"path/filepath"
"runtime"
"strings"
"sync"
Expand Down Expand Up @@ -351,7 +351,7 @@ func (fw *fileWriter) Rotate() error {
}

func (fw *fileWriter) create(fileIndex int) (*bufio.Writer, *os.File, error) {
filename := path.Join(fw.config.Directory, fmt.Sprintf("%d.log", fw.fileIndex))
filename := filepath.Join(fw.config.Directory, fmt.Sprintf("%d.log", fw.fileIndex))
file, err := os.Create(filename)
if err != nil {
return nil, nil, err
Expand Down
3 changes: 3 additions & 0 deletions utils/sampler/uniform.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,6 @@ type Uniform interface {
Initialize(sampleRange uint64) error
Sample(length int) ([]uint64, error)
}

// NewUniform returns a new sampler
func NewUniform() Uniform { return &uniformReplacer{} }
15 changes: 7 additions & 8 deletions utils/sampler/uniform_benchmark_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,17 @@ import (

// BenchmarkAllUniform
func BenchmarkAllUniform(b *testing.B) {
sizes := []int{
1,
5,
25,
50,
75,
100,
sizes := []uint64{
30,
35,
500,
10000,
100000,
}
for _, s := range uniformSamplers {
for _, size := range sizes {
b.Run(fmt.Sprintf("sampler %s with %d elements uniformly", s.name, size), func(b *testing.B) {
UniformBenchmark(b, s.sampler, 1000000, size)
UniformBenchmark(b, s.sampler, size, 30)
})
}
}
Expand Down
81 changes: 81 additions & 0 deletions utils/sampler/uniform_best.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package sampler

import (
"errors"
"math"
"math/rand"
"time"

"github.com/ava-labs/gecko/utils/timer"
)

var (
errNoValidUniformSamplers = errors.New("no valid uniform samplers found")
)

func init() { rand.Seed(time.Now().UnixNano()) }

// uniformBest implements the Uniform interface.
//
// Sampling is performed by using another implementation of the Uniform
// interface.
//
// Initialization attempts to find the best sampling algorithm given the dataset
// by performing a benchmark of the provided implementations.
type uniformBest struct {
Uniform
samplers []Uniform
maxSampleSize int
benchmarkIterations int
clock timer.Clock
}

// NewBestUniform returns a new sampler
func NewBestUniform(expectedSampleSize int) Uniform {
return &uniformBest{
samplers: []Uniform{
&uniformReplacer{},
&uniformResample{},
},
maxSampleSize: expectedSampleSize,
benchmarkIterations: 100,
}
}

func (s *uniformBest) Initialize(length uint64) error {
s.Uniform = nil
bestDuration := time.Duration(math.MaxInt64)

sampleSize := s.maxSampleSize
if length < uint64(sampleSize) {
sampleSize = int(length)
}

samplerLoop:
for _, sampler := range s.samplers {
if err := sampler.Initialize(length); err != nil {
continue
}

start := s.clock.Time()
for i := 0; i < s.benchmarkIterations; i++ {
if _, err := sampler.Sample(sampleSize); err != nil {
continue samplerLoop
}
}
end := s.clock.Time()
duration := end.Sub(start)
if duration < bestDuration {
bestDuration = duration
s.Uniform = sampler
}
}

if s.Uniform == nil {
return errNoValidUniformSamplers
}
return nil
}
5 changes: 2 additions & 3 deletions utils/sampler/uniform_replacer.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,6 @@ type uniformReplacer struct {
length uint64
}

// NewUniform returns a new sampler
func NewUniform() Uniform { return &uniformReplacer{} }

func (s *uniformReplacer) Initialize(length uint64) error {
if length > math.MaxInt64 {
return errOutOfRange
Expand All @@ -54,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)
Expand Down
Loading