diff --git a/Makefile b/Makefile index 4e24281ae9bafbb7b0c5ea639f2ca85f7d9d502b..700a0b2f4a2b4bdfe2ca541d9b78a1dcbdfefce3 100644 --- a/Makefile +++ b/Makefile @@ -5,8 +5,8 @@ setup: version: go run main.go generate - sed -i.bak 's/package\ cmd/package\ globals/g' version_vars.go - mv version_vars.go globals/version_vars.go + sed -i.bak 's/package\ cmd/package\ api/g' version_vars.go + mv version_vars.go api/version_vars.go clean: rm -rf vendor/ diff --git a/api/results.go b/api/results.go index 2c87dd27a4a98ceecfbe8e5704bd9984d4a7814b..885458fe2974d22b16592ba9e3f3ce2f5d4154a2 100644 --- a/api/results.go +++ b/api/results.go @@ -8,8 +8,9 @@ package api import ( "fmt" + "time" + jww "github.com/spf13/jwalterweatherman" - "gitlab.com/elixxir/client/globals" "gitlab.com/elixxir/client/network/gateway" pb "gitlab.com/elixxir/comms/mixmessages" "gitlab.com/elixxir/comms/network" @@ -17,7 +18,6 @@ import ( "gitlab.com/elixxir/primitives/states" "gitlab.com/xx_network/comms/connect" "gitlab.com/xx_network/primitives/id" - "time" ) // Enum of possible round results to pass back @@ -186,7 +186,7 @@ func (c *Client) getHistoricalRounds(msg *pb.HistoricalRounds, // Find a gateway to request about the roundRequests gwHost, err := gateway.Get(instance.GetPartialNdf().Get(), comms, c.rng.GetStream()) if err != nil { - globals.Log.FATAL.Panicf("Failed to track network, NDF has corrupt "+ + jww.FATAL.Panicf("Failed to track network, NDF has corrupt "+ "data: %s", err) } diff --git a/api/utils_test.go b/api/utils_test.go index 74360610803c2107181f87efa0f29363d6da3f80..31e09e2d4f5b87a16e434ef1c6eef58423a903b3 100644 --- a/api/utils_test.go +++ b/api/utils_test.go @@ -8,8 +8,10 @@ package api import ( + "testing" + "github.com/pkg/errors" - "gitlab.com/elixxir/client/globals" + jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/interfaces/params" pb "gitlab.com/elixxir/comms/mixmessages" "gitlab.com/elixxir/comms/network" @@ -21,7 +23,6 @@ import ( "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/ndf" "gitlab.com/xx_network/primitives/utils" - "testing" ) func newTestingClient(face interface{}) (*Client, error) { @@ -29,7 +30,7 @@ func newTestingClient(face interface{}) (*Client, error) { case *testing.T, *testing.M, *testing.B, *testing.PB: break default: - globals.Log.FATAL.Panicf("InitTestingSession is restricted to testing only. Got %T", face) + jww.FATAL.Panicf("InitTestingSession is restricted to testing only. Got %T", face) } def := getNDF(face) @@ -50,7 +51,7 @@ func newTestingClient(face interface{}) (*Client, error) { cert, err := utils.ReadFile(testkeys.GetNodeCertPath()) if err != nil { - globals.Log.FATAL.Panicf("Failed to create new test Instance: %v", err) + jww.FATAL.Panicf("Failed to create new test Instance: %v", err) } commsManager.AddHost(&id.Permissioning, "", cert, connect.GetDefaultHostParams()) @@ -74,7 +75,7 @@ func getNDF(face interface{}) *ndf.NetworkDefinition { case *testing.T, *testing.M, *testing.B, *testing.PB: break default: - globals.Log.FATAL.Panicf("InitTestingSession is restricted to testing only. Got %T", face) + jww.FATAL.Panicf("InitTestingSession is restricted to testing only. Got %T", face) } cert, _ := utils.ReadFile(testkeys.GetNodeCertPath()) diff --git a/api/version_vars.go b/api/version_vars.go index 157aee200d3d2502207ae1ed7dbcb66a20db02ba..dc333c8a688faddebc96c5de0f589d9137801308 100644 --- a/api/version_vars.go +++ b/api/version_vars.go @@ -1,36 +1,43 @@ // Code generated by go generate; DO NOT EDIT. // This file was generated by robots at -// 2020-08-10 10:46:23.193662 -0700 PDT m=+0.042594188 +// 2021-03-10 14:16:47.093264 -0800 PST m=+0.046129936 package api -const GITVERSION = `4ddf4b3 Merge branch 'XX-2471/XXPrimitives' into 'release'` -const SEMVER = "1.4.0" +const GITVERSION = `2096d6ae Merge branch 'Anne/v2' into 'release'` +const SEMVER = "2.0.0" const DEPENDENCIES = `module gitlab.com/elixxir/client go 1.13 require ( github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3 - github.com/golang/protobuf v1.4.2 + github.com/golang/protobuf v1.4.3 github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00 // indirect - github.com/pelletier/go-toml v1.6.0 // indirect + github.com/magiconair/properties v1.8.4 // indirect + github.com/mitchellh/mapstructure v1.4.0 // indirect + github.com/pelletier/go-toml v1.8.1 // indirect github.com/pkg/errors v0.9.1 github.com/smartystreets/assertions v1.0.1 // indirect - github.com/spf13/afero v1.2.2 // indirect + github.com/spf13/afero v1.5.1 // indirect github.com/spf13/cast v1.3.1 // indirect - github.com/spf13/cobra v1.0.0 + github.com/spf13/cobra v1.1.1 github.com/spf13/jwalterweatherman v1.1.0 - github.com/spf13/pflag v1.0.5 // indirect - github.com/spf13/viper v1.6.2 - gitlab.com/elixxir/comms v0.0.0-20200810165153-3039323b5656 - gitlab.com/elixxir/crypto v0.0.0-20200806211835-b8ce4472f399 - gitlab.com/elixxir/ekv v0.0.0-20200729182028-159355ea5842 - gitlab.com/elixxir/primitives v0.0.0-20200805174810-86b366d1dd2d - gitlab.com/xx_network/comms v0.0.0-20200806235452-3a82720833ba - gitlab.com/xx_network/crypto v0.0.0-20200806235322-ede3c15881ce - gitlab.com/xx_network/primitives v0.0.0-20200804183002-f99f7a7284da - golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de - gopkg.in/ini.v1 v1.52.0 // indirect + github.com/spf13/viper v1.7.1 + gitlab.com/elixxir/bloomfilter v0.0.0-20200930191214-10e9ac31b228 + gitlab.com/elixxir/comms v0.0.4-0.20210310191636-1bca0ddac665 + gitlab.com/elixxir/crypto v0.0.7-0.20210309193114-8a6225c667e2 + gitlab.com/elixxir/ekv v0.1.4 + gitlab.com/elixxir/primitives v0.0.3-0.20210309193003-ef42ebb4800b + gitlab.com/xx_network/comms v0.0.4-0.20210309192940-6b7fb39b4d01 + gitlab.com/xx_network/crypto v0.0.5-0.20210309192854-cf32117afb96 + gitlab.com/xx_network/primitives v0.0.4-0.20210309173740-eb8cd411334a + golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad + golang.org/x/net v0.0.0-20201224014010-6772e930b67b // indirect + golang.org/x/sys v0.0.0-20210105210732-16f7687f5001 // indirect + google.golang.org/genproto v0.0.0-20210105202744-fe13368bc0e1 // indirect + google.golang.org/grpc v1.34.0 // indirect + google.golang.org/protobuf v1.25.0 + gopkg.in/ini.v1 v1.62.0 // indirect ) replace google.golang.org/grpc => github.com/grpc/grpc-go v1.27.1 diff --git a/cmd/root.go b/cmd/root.go index 1910ce9566b4ca404962d9099227aade0c81a590..fb1efae75e8475ef671c9fbddd5b94bba61f0d9f 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -96,6 +96,20 @@ var rootCmd = &cobra.Command{ client.GetHealth().AddChannel(connected) waitUntilConnected(connected) + // After connection, make sure we have registered with at least + // 85% of the nodes + numReg := 1 + numNotReg := 100 + for numReg < 3*numNotReg { + time.Sleep(1 * time.Second) + numReg, numNotReg, err = client.GetNodeRegistrationStatus() + if err != nil { + jww.FATAL.Panicf("%+v", err) + } + jww.INFO.Printf("Registering with nodes (%d/%d)...", + numReg, (numReg + numNotReg)) + } + // Send Messages msgBody := viper.GetString("message") diff --git a/cmd/version.go b/cmd/version.go index bf0017c5806c652f5bec660b6c02cef246064e45..99af5a4c68449110c4b9281285596caf305b2e78 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -18,7 +18,7 @@ import ( ) // Change this value to set the version for this build -const currentVersion = "1.4.0" +const currentVersion = "2.0.0" func Version() string { out := fmt.Sprintf("Elixxir Client v%s -- %s\n\n", api.SEMVER, diff --git a/globals/log.go b/globals/log.go deleted file mode 100644 index cbcdce07b2ed6a47f49bdf5368508b75e65c3ccf..0000000000000000000000000000000000000000 --- a/globals/log.go +++ /dev/null @@ -1,55 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// - -package globals - -import ( - jww "github.com/spf13/jwalterweatherman" - "io" - "io/ioutil" - "log" - "os" -) - -// Log is logging everything to this notepad so that the CUI can replace it -// with its own notepad and get logging statements from the client -var Log = jww.NewNotepad(jww.LevelInfo, jww.LevelInfo, os.Stdout, - ioutil.Discard, "CLIENT", log.Ldate|log.Ltime) - -// InitLog initializes logging thresholds and the log path. -// verbose turns on debug logging, setting the log path to nil -// uses std out. -func InitLog(verbose bool, logPath string) *jww.Notepad { - logLevel := jww.LevelInfo - logFlags := (log.Ldate | log.Ltime) - stdOut := io.Writer(os.Stdout) - logFile := ioutil.Discard - - // If the verbose flag is set, print all logs and - // print microseconds as well - if verbose { - logLevel = jww.LevelDebug - logFlags = (log.Ldate | log.Ltime | log.Lmicroseconds) - } - // If the logpath is empty or not set to - (stdout), - // set up the log file and do not log to stdout - if logPath != "" && logPath != "-" { - // Create log file, overwrites if existing - lF, err := os.OpenFile(logPath, - os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) - if err != nil { - Log.WARN.Println("Invalid or missing log path," + - " stdout used.") - } else { - logFile = io.Writer(lF) - stdOut = ioutil.Discard - } - } - - return jww.NewNotepad(logLevel, logLevel, stdOut, logFile, - "CLIENT", logFlags) -} diff --git a/globals/statusEvents.go b/globals/statusEvents.go deleted file mode 100644 index fdf8d6ff99f6ac0c5cbc155eebe1a9c645c0ab8f..0000000000000000000000000000000000000000 --- a/globals/statusEvents.go +++ /dev/null @@ -1,25 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// - -package globals - -//Identity -const REG_KEYGEN = 1 //Generating Cryptographic Keys -const REG_PRECAN = 2 //Doing a Precanned Identity (Not Secure) -const REG_UID_GEN = 3 //Generating User ID -const REG_PERM = 4 //Validating User Identity With Permissioning Server -const REG_NODE = 5 //Registering with Nodes -const REG_FAIL = 6 //Failed to Register with Nodes -const REG_SECURE_STORE = 7 //Creating Local Secure Session -const REG_SAVE = 8 //Storing Session -//UDB registration -const UDB_REG_PUSHKEY = 9 //Pushing Cryptographic Material to the User Discovery Bot -const UDB_REG_PUSHUSER = 10 //Registering User with the User Discovery Bot -//UDB Search -const UDB_SEARCH_LOOK = 11 //Searching for User in User Discovery -const UDB_SEARCH_GETKEY = 12 //Getting Keying Material From User Discovery -const UDB_SEARCH_BUILD_CREDS = 13 //Building secure end to end relationship diff --git a/globals/storage.go b/globals/storage.go deleted file mode 100644 index 63f5b2b360b7842cbbb435cf5495568b80c48549..0000000000000000000000000000000000000000 --- a/globals/storage.go +++ /dev/null @@ -1,203 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// - -package globals - -import ( - "os" - "sync" -) - -const ( - NoSave uint8 = iota - LocationA - LocationB -) - -type Storage interface { - SetLocation(string, string) error - GetLocation() (string, string) - SaveA([]byte) error - SaveB([]byte) error - LoadA() []byte - LoadB() []byte - IsEmpty() bool -} - -type DefaultStorage struct { - locationA string - locationB string - sync.Mutex -} - -func (ds *DefaultStorage) SetLocation(locationA, locationB string) error { - ds.Lock() - ds.locationA = locationA - ds.locationB = locationB - ds.Unlock() - return nil -} - -func (ds *DefaultStorage) GetLocation() (string, string) { - ds.Lock() - defer ds.Unlock() - return ds.locationA, ds.locationB -} - -func (ds *DefaultStorage) IsEmpty() bool { - _, err := os.Stat(ds.locationA) - firstEmpty := err != nil && os.IsNotExist(err) - _, err = os.Stat(ds.locationB) - secondEmpty := err != nil && os.IsNotExist(err) - return firstEmpty && secondEmpty -} - -func (ds *DefaultStorage) SaveA(data []byte) error { - return dsSaveHelper(ds.locationA, data) -} - -func (ds *DefaultStorage) LoadA() []byte { - return dsLoadHelper(ds.locationA) -} - -func (ds *DefaultStorage) SaveB(data []byte) error { - return dsSaveHelper(ds.locationB, data) -} - -func (ds *DefaultStorage) LoadB() []byte { - return dsLoadHelper(ds.locationB) -} - -type RamStorage struct { - DataA []byte - DataB []byte -} - -func (rs *RamStorage) SetLocation(string, string) error { - return nil -} - -func (rs *RamStorage) GetLocation() (string, string) { - return "", "" -} - -func (rs *RamStorage) SaveA(data []byte) error { - rs.DataA = make([]byte, len(data)) - copy(rs.DataA, data) - return nil -} - -func (rs *RamStorage) SaveB(data []byte) error { - rs.DataB = make([]byte, len(data)) - copy(rs.DataB, data) - return nil -} - -func (rs *RamStorage) LoadA() []byte { - b := make([]byte, len(rs.DataA)) - copy(b, rs.DataA) - - return b -} - -func (rs *RamStorage) LoadB() []byte { - b := make([]byte, len(rs.DataB)) - copy(b, rs.DataB) - - return b -} - -func (rs *RamStorage) IsEmpty() bool { - return (rs.DataA == nil || len(rs.DataA) == 0) && (rs.DataB == nil || len(rs.DataB) == 0) -} - -func dsLoadHelper(loc string) []byte { - // Check if the file exists, return nil if it does not - finfo, err1 := os.Stat(loc) - - if err1 != nil { - Log.ERROR.Printf("Default Storage Load: Unknown Error Occurred on"+ - " file check: \n %v", err1.Error()) - return nil - } - - b := make([]byte, finfo.Size()) - - // Open the file, return nil if it cannot be opened - f, err2 := os.Open(loc) - - defer func() { - if f != nil { - f.Close() - } else { - Log.WARN.Println("Could not close file, file is nil") - } - }() - - if err2 != nil { - Log.ERROR.Printf("Default Storage Load: Unknown Error Occurred on"+ - " file open: \n %v", err2.Error()) - return nil - } - - // Read the data from the file, return nil if read fails - _, err3 := f.Read(b) - - if err3 != nil { - Log.ERROR.Printf("Default Storage Load: Unknown Error Occurred on"+ - " file read: \n %v", err3.Error()) - return nil - } - - return b - -} - -func dsSaveHelper(loc string, data []byte) error { - //check if the file exists, delete if it does - _, err1 := os.Stat(loc) - - if err1 == nil { - errRmv := os.Remove(loc) - if errRmv != nil { - Log.WARN.Printf("Could not remove Storage File B: %s", errRmv) - } - } else if !os.IsNotExist(err1) { - Log.ERROR.Printf("Default Storage Save: Unknown Error Occurred on"+ - " file check: \n %v", - err1.Error()) - return err1 - } - - //create new file - f, err2 := os.Create(loc) - - defer func() { - if f != nil { - f.Close() - } else { - Log.WARN.Println("Could not close file, file is nil") - } - }() - - if err2 != nil { - Log.ERROR.Printf("Default Storage Save: Unknown Error Occurred on"+ - " file creation: \n %v", err2.Error()) - return err2 - } - - //Save to file - _, err3 := f.Write(data) - - if err3 != nil { - Log.ERROR.Printf("Default Storage Save: Unknown Error Occurred on"+ - " file write: \n %v", err3.Error()) - return err3 - } - - return nil -} diff --git a/globals/storage_test.go b/globals/storage_test.go deleted file mode 100644 index f7bd60f34ce90f1a474faf83b0918cb7a4b9eae3..0000000000000000000000000000000000000000 --- a/globals/storage_test.go +++ /dev/null @@ -1,145 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// - -package globals - -import ( - "os" - "reflect" - "testing" -) - -func TestInitStorage(t *testing.T) { - TestDataA := []byte{12, 14, 54} - TestDataB := []byte{69, 42, 32} - TestSaveLocA := "testStorageA.data" - TestSaveLocB := "testStorageB.data" - - // Test DefaultStorage initialization without existing storage - storage := &DefaultStorage{} - //Check that storage is empty prior to any Save calls - if !storage.IsEmpty() { - t.Errorf("ds.IsEmpty failed to detect an empty storage") - } - - storage.SetLocation(TestSaveLocA, TestSaveLocB) - - // Test DS saveA - err := storage.SaveA(TestDataA) - if err != nil { - t.Errorf("ds.Save failed to create a save file A at: %v", - TestSaveLocA) - } - // Check that save file was made - if !exists(TestSaveLocA) { - t.Errorf("ds.Save failed to create a save file A at: %v", - TestSaveLocA) - } - //Check that the storage is not empty after a saveA call - if storage.IsEmpty() { - t.Errorf("ds.IsEmpty failed to detect a non-empty storage") - } - - // Test DS loadA - actualData := storage.LoadA() - if reflect.DeepEqual(actualData, TestDataA) != true { - t.Errorf("ds.Load failed to load expected data on A. Expected:%v Actual:%v", - TestDataA, actualData) - } - - // Test DS saveB - err = storage.SaveB(TestDataB) - if err != nil { - t.Errorf("ds.Save failed to create a save file B at: %v", - TestSaveLocB) - } - // Check that save file was made - if !exists(TestSaveLocB) { - t.Errorf("ds.Save failed to create a save file B at: %v", - TestSaveLocB) - } - - // Test DS loadA - actualData = storage.LoadB() - if reflect.DeepEqual(actualData, TestDataB) != true { - t.Errorf("ds.Load failed to load expected data on B. Expected:%v Actual:%v", - TestDataB, actualData) - } - - // Test RamStorage - store := RamStorage{} - actualData = nil - // Test A - store.SaveA(TestDataA) - actualData = store.LoadA() - if reflect.DeepEqual(actualData, TestDataA) != true { - t.Errorf("rs.Load failed to load expected data A. Expected:%v Actual:%v", - TestDataA, actualData) - } - //Test B - store.SaveB(TestDataB) - actualData = store.LoadB() - if reflect.DeepEqual(actualData, TestDataB) != true { - t.Errorf("rs.Load failed to load expected data B. Expected:%v Actual:%v", - TestDataB, actualData) - } - os.Remove(TestSaveLocA) - os.Remove(TestSaveLocB) -} - -// exists returns whether the given file or directory exists or not -func exists(path string) bool { - _, err := os.Stat(path) - if err == nil { - return true - } - if os.IsNotExist(err) { - return false - } - return true -} - -func TestDefaultStorage_GetLocation(t *testing.T) { - locationA := "hi" - locationB := "hi2" - - ds := DefaultStorage{locationA: locationA, locationB: locationB} - - recievedLocA, recievedLocB := ds.GetLocation() - - if recievedLocA != locationA { - t.Errorf("defaultStorage.GetLocation returned incorrect location A. Expected:%v Actual:%v", - locationA, recievedLocA) - } - - if recievedLocB != locationB { - t.Errorf("defaultStorage.GetLocation returned incorrect location B. Expected:%v Actual:%v", - locationB, recievedLocB) - } -} - -func TestRamStorage_GetLocation(t *testing.T) { - - ds := RamStorage{} - - a, b := ds.GetLocation() - - if a != "" && b != "" { - t.Errorf("RamStorage.GetLocation returned incorrect location. Actual: '', ''; Expected:'%v','%v'", - a, b) - } -} - -func Test_dsLoadHelper_LocError(t *testing.T) { - testLoc := "~a/test" - - result := dsLoadHelper(testLoc) - - if result != nil { - t.Errorf("dsLoadHelper() did not error on invalid path.") - } -} diff --git a/globals/terminator.go b/globals/terminator.go deleted file mode 100644 index 0b3155e19db73add793dad56fa45abc43a924724..0000000000000000000000000000000000000000 --- a/globals/terminator.go +++ /dev/null @@ -1,48 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// - -package globals - -import ( - "time" -) - -type ThreadTerminator chan chan bool - -func NewThreadTerminator() ThreadTerminator { - t := make(chan chan bool, 1) - return t -} - -func (t ThreadTerminator) Terminate() { - t <- nil -} - -// Try's to kill a thread controlled by a termination channel for the length of -// the timeout, returns its success. pass 0 for no timeout -func (t ThreadTerminator) BlockingTerminate(timeout uint64) bool { - - killNotify := make(chan bool) - defer close(killNotify) - - if timeout != 0 { - timer := time.NewTimer(time.Duration(timeout) * time.Millisecond) - defer timer.Stop() - - t <- killNotify - - select { - case _ = <-killNotify: - return true - case <-timer.C: - return false - } - } else { - _ = <-killNotify - return true - } -} diff --git a/globals/terminator_test.go b/globals/terminator_test.go deleted file mode 100644 index 8d18841de618d2f66407aae3e6fdd96bdc9688f9..0000000000000000000000000000000000000000 --- a/globals/terminator_test.go +++ /dev/null @@ -1,70 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// - -package globals - -import ( - "testing" - "time" -) - -func TestNewThreadTerminator(t *testing.T) { - - term := NewThreadTerminator() - - var success bool - - go func(term ThreadTerminator) { - term <- nil - }(term) - - timer := time.NewTimer(time.Duration(1000) * time.Millisecond) - defer timer.Stop() - - select { - case _ = <-term: - success = true - case <-timer.C: - success = false - } - - if !success { - t.Errorf("NewThreadTerminator: Could not use the ThreadTerminator to" + - " stop a thread") - } - -} - -func TestBlockingTerminate(t *testing.T) { - - term := NewThreadTerminator() - - go func(term ThreadTerminator) { - var killNotify chan<- bool - - q := false - - for !q { - select { - case killNotify = <-term: - q = true - } - - close(term) - - killNotify <- true - - } - }(term) - - success := term.BlockingTerminate(1000) - - if !success { - t.Errorf("BlockingTerminate: Thread did not terminate in time") - } - -} diff --git a/globals/version_vars.go b/globals/version_vars.go deleted file mode 100644 index dd88debfef2a3612496bef795f5e60ef06bcfd1a..0000000000000000000000000000000000000000 --- a/globals/version_vars.go +++ /dev/null @@ -1,44 +0,0 @@ -// Code generated by go generate; DO NOT EDIT. -// This file was generated by robots at -// 2021-03-09 09:42:42.079202 -0800 PST m=+0.041021439 -package globals - -const GITVERSION = `b7ed6d75 Merge branch 'release' into 'XX-3118/ClientVersion'` -const SEMVER = "1.4.0" -const DEPENDENCIES = `module gitlab.com/elixxir/client - -go 1.13 - -require ( - github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3 - github.com/golang/protobuf v1.4.3 - github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00 // indirect - github.com/magiconair/properties v1.8.4 // indirect - github.com/mitchellh/mapstructure v1.4.0 // indirect - github.com/pelletier/go-toml v1.8.1 // indirect - github.com/pkg/errors v0.9.1 - github.com/smartystreets/assertions v1.0.1 // indirect - github.com/spf13/afero v1.5.1 // indirect - github.com/spf13/cast v1.3.1 // indirect - github.com/spf13/cobra v1.1.1 - github.com/spf13/jwalterweatherman v1.1.0 - github.com/spf13/viper v1.7.1 - gitlab.com/elixxir/bloomfilter v0.0.0-20200930191214-10e9ac31b228 - gitlab.com/elixxir/comms v0.0.4-0.20210308190443-cc7781473650 - gitlab.com/elixxir/crypto v0.0.7-0.20210308214444-5ff53d20fcfc - gitlab.com/elixxir/ekv v0.1.4 - gitlab.com/elixxir/primitives v0.0.3-0.20210305221357-0b3f19cc3c8a - gitlab.com/xx_network/comms v0.0.4-0.20210305221336-a7e28febdbf6 - gitlab.com/xx_network/crypto v0.0.5-0.20210305221255-f0ef174f5135 - gitlab.com/xx_network/primitives v0.0.4-0.20210308175329-436b0c8753ea - golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad - golang.org/x/net v0.0.0-20201224014010-6772e930b67b // indirect - golang.org/x/sys v0.0.0-20210105210732-16f7687f5001 // indirect - google.golang.org/genproto v0.0.0-20210105202744-fe13368bc0e1 // indirect - google.golang.org/grpc v1.34.0 // indirect - google.golang.org/protobuf v1.25.0 - gopkg.in/ini.v1 v1.62.0 // indirect -) - -replace google.golang.org/grpc => github.com/grpc/grpc-go v1.27.1 -` diff --git a/go.mod b/go.mod index 06725cf2cb1d5b599f102b16646401d8ecca4f96..cbd7c3d26f28e77fded7b281126283cacffa2857 100644 --- a/go.mod +++ b/go.mod @@ -17,13 +17,13 @@ require ( github.com/spf13/jwalterweatherman v1.1.0 github.com/spf13/viper v1.7.1 gitlab.com/elixxir/bloomfilter v0.0.0-20200930191214-10e9ac31b228 - gitlab.com/elixxir/comms v0.0.4-0.20210309195247-fc17eb8560cf - gitlab.com/elixxir/crypto v0.0.7-0.20210308214444-5ff53d20fcfc + gitlab.com/elixxir/comms v0.0.4-0.20210311180506-28ae742c5e35 + gitlab.com/elixxir/crypto v0.0.7-0.20210309193114-8a6225c667e2 gitlab.com/elixxir/ekv v0.1.4 - gitlab.com/elixxir/primitives v0.0.3-0.20210305221357-0b3f19cc3c8a - gitlab.com/xx_network/comms v0.0.4-0.20210305221336-a7e28febdbf6 - gitlab.com/xx_network/crypto v0.0.5-0.20210305221255-f0ef174f5135 - gitlab.com/xx_network/primitives v0.0.4-0.20210308175329-436b0c8753ea + gitlab.com/elixxir/primitives v0.0.3-0.20210309193003-ef42ebb4800b + gitlab.com/xx_network/comms v0.0.4-0.20210309192940-6b7fb39b4d01 + gitlab.com/xx_network/crypto v0.0.5-0.20210309192854-cf32117afb96 + gitlab.com/xx_network/primitives v0.0.4-0.20210309173740-eb8cd411334a golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad golang.org/x/net v0.0.0-20201224014010-6772e930b67b // indirect golang.org/x/sys v0.0.0-20210105210732-16f7687f5001 // indirect diff --git a/go.sum b/go.sum index 32417a23e4d4a2a2ed4d7a4cb3bc69f6e1abb41b..15bdda0ba26fa5f23d7aa3c5993d95b458cf8a7d 100644 --- a/go.sum +++ b/go.sum @@ -251,20 +251,20 @@ github.com/zeebo/pcg v1.0.0 h1:dt+dx+HvX8g7Un32rY9XWoYnd0NmKmrIzpHF7qiTDj0= github.com/zeebo/pcg v1.0.0/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4= gitlab.com/elixxir/bloomfilter v0.0.0-20200930191214-10e9ac31b228 h1:Gi6rj4mAlK0BJIk1HIzBVMjWNjIUfstrsXC2VqLYPcA= gitlab.com/elixxir/bloomfilter v0.0.0-20200930191214-10e9ac31b228/go.mod h1:H6jztdm0k+wEV2QGK/KYA+MY9nj9Zzatux/qIvDDv3k= -gitlab.com/elixxir/comms v0.0.4-0.20210308190443-cc7781473650 h1:OAUlZT0kw51DZARSUzR4eEpQKigbafZ0faWGcsDXFD0= -gitlab.com/elixxir/comms v0.0.4-0.20210308190443-cc7781473650/go.mod h1:DNJES7GZaGZnXsIDDP0nNS3lk21mhN27byQlODA+5fA= -gitlab.com/elixxir/comms v0.0.4-0.20210309184509-e92f830c628b h1:+uPaSUaDIRG639c55WK6b16+fZnOygjDiqcx+ylzV8s= -gitlab.com/elixxir/comms v0.0.4-0.20210309184509-e92f830c628b/go.mod h1:DNJES7GZaGZnXsIDDP0nNS3lk21mhN27byQlODA+5fA= -gitlab.com/elixxir/comms v0.0.4-0.20210309195247-fc17eb8560cf h1:/VDBO0GxcpqGVOFBFeuk/yKxWOKC6j7A2gLnOc1Syuc= -gitlab.com/elixxir/comms v0.0.4-0.20210309195247-fc17eb8560cf/go.mod h1:DNJES7GZaGZnXsIDDP0nNS3lk21mhN27byQlODA+5fA= +gitlab.com/elixxir/comms v0.0.4-0.20210310191320-05cba0d1a468 h1:EnfzSAdV+3WwWJ6cGY5xENrHwafy8tIUtz5qvDEZ4sw= +gitlab.com/elixxir/comms v0.0.4-0.20210310191320-05cba0d1a468/go.mod h1:96cMuVVlarB+I6nuFKdq4zCagQkbhVK/MUzRk3yOymI= +gitlab.com/elixxir/comms v0.0.4-0.20210310191636-1bca0ddac665 h1:2tWjyhX21DBXeAjiHJTFL/MCpb9L9mg7NE09sS8tb2k= +gitlab.com/elixxir/comms v0.0.4-0.20210310191636-1bca0ddac665/go.mod h1:96cMuVVlarB+I6nuFKdq4zCagQkbhVK/MUzRk3yOymI= +gitlab.com/elixxir/comms v0.0.4-0.20210310223853-60622bd841a8 h1:jhka79rXEc7hHn6uDbAjY7NhhKYWwtQ+iHtsa/Jfw1w= +gitlab.com/elixxir/comms v0.0.4-0.20210310223853-60622bd841a8/go.mod h1:96cMuVVlarB+I6nuFKdq4zCagQkbhVK/MUzRk3yOymI= +gitlab.com/elixxir/comms v0.0.4-0.20210311180506-28ae742c5e35 h1:t/ILeoWel5Im+zLQUX2FIroZvrfAkxOaL3DCA8enKcE= +gitlab.com/elixxir/comms v0.0.4-0.20210311180506-28ae742c5e35/go.mod h1:96cMuVVlarB+I6nuFKdq4zCagQkbhVK/MUzRk3yOymI= gitlab.com/elixxir/crypto v0.0.0-20200804182833-984246dea2c4 h1:28ftZDeYEko7xptCZzeFWS1Iam95dj46TWFVVlKmw6A= gitlab.com/elixxir/crypto v0.0.0-20200804182833-984246dea2c4/go.mod h1:ucm9SFKJo+K0N2GwRRpaNr+tKXMIOVWzmyUD0SbOu2c= gitlab.com/elixxir/crypto v0.0.3 h1:znCt/x2bL4y8czTPaaFkwzdgSgW3BJc/1+dxyf1jqVw= gitlab.com/elixxir/crypto v0.0.3/go.mod h1:ZNgBOblhYToR4m8tj4cMvJ9UsJAUKq+p0gCp07WQmhA= -gitlab.com/elixxir/crypto v0.0.7-0.20210305221450-c94429c34886 h1:Jt1PV/plsHrb/mK92HVgu+OF9PBDamp8GdbsGj0OexY= -gitlab.com/elixxir/crypto v0.0.7-0.20210305221450-c94429c34886/go.mod h1:ugRjIGSOJJvVKGfIDpS/k62yeG4cTIrS/YNLqmpEIDM= -gitlab.com/elixxir/crypto v0.0.7-0.20210308214444-5ff53d20fcfc h1:xFMx+2WSvyYS9VNdrUIm7BJQZKwYRR4+anv2XkhfTHo= -gitlab.com/elixxir/crypto v0.0.7-0.20210308214444-5ff53d20fcfc/go.mod h1:ugRjIGSOJJvVKGfIDpS/k62yeG4cTIrS/YNLqmpEIDM= +gitlab.com/elixxir/crypto v0.0.7-0.20210309193114-8a6225c667e2 h1:JMbUxcOjFpdCBUMZS5g8CWfNdPJ6pP8xsAZbnLj66jc= +gitlab.com/elixxir/crypto v0.0.7-0.20210309193114-8a6225c667e2/go.mod h1:TMZMB24OsjF6y3LCyBMzDucbOx1cGQCCeuKV9lJA/DU= gitlab.com/elixxir/ekv v0.1.4 h1:NLVMwsFEKArWcsDHu2DbXlm9374iSgn7oIA3rVSsvjc= gitlab.com/elixxir/ekv v0.1.4/go.mod h1:e6WPUt97taFZe5PFLPb1Dupk7tqmDCTQu1kkstqJvw4= gitlab.com/elixxir/primitives v0.0.0-20200731184040-494269b53b4d/go.mod h1:OQgUZq7SjnE0b+8+iIAT2eqQF+2IFHn73tOo+aV11mg= @@ -272,25 +272,23 @@ gitlab.com/elixxir/primitives v0.0.0-20200804170709-a1896d262cd9/go.mod h1:p0Vel gitlab.com/elixxir/primitives v0.0.0-20200804182913-788f47bded40/go.mod h1:tzdFFvb1ESmuTCOl1z6+yf6oAICDxH2NPUemVgoNLxc= gitlab.com/elixxir/primitives v0.0.1 h1:q61anawANlNAExfkeQEE1NCsNih6vNV1FFLoUQX6txQ= gitlab.com/elixxir/primitives v0.0.1/go.mod h1:kNp47yPqja2lHSiS4DddTvFpB/4D9dB2YKnw5c+LJCE= -gitlab.com/elixxir/primitives v0.0.3-0.20210305221357-0b3f19cc3c8a h1:NxCES61c3ycIAG76/dAKDTZvzxvh8szcL+RTX+6Wldw= -gitlab.com/elixxir/primitives v0.0.3-0.20210305221357-0b3f19cc3c8a/go.mod h1:7o0Gcvq6tE2by2hZyd0CDueOLUQGfbcuStnQEtLc56Y= +gitlab.com/elixxir/primitives v0.0.3-0.20210309193003-ef42ebb4800b h1:TswWfqiZqsdPLeWsfe7VJHMlV01W792kRHGYfYwb2Lk= +gitlab.com/elixxir/primitives v0.0.3-0.20210309193003-ef42ebb4800b/go.mod h1:/e3a4KPqmA9V22qKSZ9prfYYNzIzvLI8xh7noVV091w= gitlab.com/xx_network/comms v0.0.0-20200805174823-841427dd5023/go.mod h1:owEcxTRl7gsoM8c3RQ5KAm5GstxrJp5tn+6JfQ4z5Hw= -gitlab.com/xx_network/comms v0.0.4-0.20210305221336-a7e28febdbf6 h1:poMXjv5/r9TAQ2l0c1HfpMAoG6ASjitUbeS/FZnf3JI= -gitlab.com/xx_network/comms v0.0.4-0.20210305221336-a7e28febdbf6/go.mod h1:bs4GLnnL1UqInyjT4MbHamgTpiTLNtdC5e61CCnVapo= +gitlab.com/xx_network/comms v0.0.4-0.20210309192940-6b7fb39b4d01 h1:f93iz7mTHt3r37O97vaQD8otohihLN3OnAEEbDGQdVs= +gitlab.com/xx_network/comms v0.0.4-0.20210309192940-6b7fb39b4d01/go.mod h1:aNPRHmPssXc1JMJ83DAknT2C2iMgKL1wH3//AqQrhQc= gitlab.com/xx_network/crypto v0.0.3/go.mod h1:DF2HYvvCw9wkBybXcXAgQMzX+MiGbFPjwt3t17VRqRE= gitlab.com/xx_network/crypto v0.0.4 h1:lpKOL5mTJ2awWMfgBy30oD/UvJVrWZzUimSHlOdZZxo= gitlab.com/xx_network/crypto v0.0.4/go.mod h1:+lcQEy+Th4eswFgQDwT0EXKp4AXrlubxalwQFH5O0Mk= -gitlab.com/xx_network/crypto v0.0.5-0.20210305221255-f0ef174f5135 h1:2QuO+5VZerO5hLNNdU9N9jX4Xa20aHs1h15RMNbgONY= -gitlab.com/xx_network/crypto v0.0.5-0.20210305221255-f0ef174f5135/go.mod h1:Kg4EgRbpzHjxavzuKP9E1JEgYBT0ez80rFtB7Bwuw+g= +gitlab.com/xx_network/crypto v0.0.5-0.20210309192854-cf32117afb96 h1:VZGJNhuU6YunKyK4MbNZf25UxQsmU1bH5SnbK93tI7Q= +gitlab.com/xx_network/crypto v0.0.5-0.20210309192854-cf32117afb96/go.mod h1:TtaHpuX0lcuTTtcq+pz+lMusjyTgvSohIHFOlVwN1uU= gitlab.com/xx_network/primitives v0.0.0-20200803231956-9b192c57ea7c/go.mod h1:wtdCMr7DPePz9qwctNoAUzZtbOSHSedcK++3Df3psjA= gitlab.com/xx_network/primitives v0.0.0-20200804183002-f99f7a7284da h1:CCVslUwNC7Ul7NG5nu3ThGTSVUt1TxNRX+47f5TUwnk= gitlab.com/xx_network/primitives v0.0.0-20200804183002-f99f7a7284da/go.mod h1:OK9xevzWCaPO7b1wiluVJGk7R5ZsuC7pHY5hteZFQug= gitlab.com/xx_network/primitives v0.0.2 h1:r45yKenJ9e7PylI1ZXJ1Es09oYNaYXjxVy9+uYlwo7Y= gitlab.com/xx_network/primitives v0.0.2/go.mod h1:cs0QlFpdMDI6lAo61lDRH2JZz+3aVkHy+QogOB6F/qc= -gitlab.com/xx_network/primitives v0.0.4-0.20210303180604-1ee442e6463f h1:nC87BCbInkGS2iG5Z1g5PJC7gNKGgLlJmcMVYmsf7mo= -gitlab.com/xx_network/primitives v0.0.4-0.20210303180604-1ee442e6463f/go.mod h1:9imZHvYwNFobxueSvVtHneZLk9wTK7HQTzxPm+zhFhE= -gitlab.com/xx_network/primitives v0.0.4-0.20210308175329-436b0c8753ea h1:ljUr+XDu+8aD0ua7Q8ffd/ibEmyxDS6/+FqkHBoeb9U= -gitlab.com/xx_network/primitives v0.0.4-0.20210308175329-436b0c8753ea/go.mod h1:9imZHvYwNFobxueSvVtHneZLk9wTK7HQTzxPm+zhFhE= +gitlab.com/xx_network/primitives v0.0.4-0.20210309173740-eb8cd411334a h1:Ume9QbJ4GoJh7v5yg/YVDjowJHx/VFeOC/A4PJZUm9g= +gitlab.com/xx_network/primitives v0.0.4-0.20210309173740-eb8cd411334a/go.mod h1:9imZHvYwNFobxueSvVtHneZLk9wTK7HQTzxPm+zhFhE= gitlab.com/xx_network/ring v0.0.2 h1:TlPjlbFdhtJrwvRgIg4ScdngMTaynx/ByHBRZiXCoL0= gitlab.com/xx_network/ring v0.0.2/go.mod h1:aLzpP2TiZTQut/PVHR40EJAomzugDdHXetbieRClXIM= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= diff --git a/interfaces/params/network.go b/interfaces/params/network.go index f3de8ea10ee17e5408c2b72d335e8b2ea884e428..b73efc7a3ee56c5d2f24d18643194a22852dbc92 100644 --- a/interfaces/params/network.go +++ b/interfaces/params/network.go @@ -21,6 +21,8 @@ type Network struct { // Longest delay between network events for Health tracker to denote that // the network is in a bad state NetworkHealthTimeout time.Duration + //Number of parallel node registration the client is capable of + ParallelNodeRegistrations uint Rounds Messages @@ -36,6 +38,7 @@ func GetDefaultNetwork() Network { RegNodesBufferLen: 500, NetworkHealthTimeout: 30 * time.Second, E2EParams: GetDefaultE2ESessionParams(), + ParallelNodeRegistrations: 8, } n.Rounds = GetDefaultRounds() n.Messages = GetDefaultMessage() diff --git a/keyExchange/utils_test.go b/keyExchange/utils_test.go index 16bd2f4ec7d224ebed1e44b58ecc077b50e01e44..162db4728cec9ddfa0b91d0f0ae3acc6e0c7c522 100644 --- a/keyExchange/utils_test.go +++ b/keyExchange/utils_test.go @@ -8,8 +8,11 @@ package keyExchange import ( + "testing" + "time" + "github.com/golang/protobuf/proto" - "gitlab.com/elixxir/client/globals" + jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/interfaces" "gitlab.com/elixxir/client/interfaces/message" "gitlab.com/elixxir/client/interfaces/params" @@ -28,8 +31,6 @@ import ( "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/id/ephemeral" "gitlab.com/xx_network/primitives/ndf" - "testing" - "time" ) // Generate partner ID for two people, used for smoke tests @@ -108,7 +109,7 @@ func InitTestingContextGeneric(i interface{}) (*storage.Session, interfaces.Netw case *testing.T, *testing.M, *testing.B, *testing.PB: break default: - globals.Log.FATAL.Panicf("InitTestingSession is restricted to testing only. Got %T", i) + jww.FATAL.Panicf("InitTestingSession is restricted to testing only. Got %T", i) } thisSession := storage.InitTestingSession(i) @@ -215,7 +216,7 @@ func InitTestingContextFullExchange(i interface{}) (*storage.Session, *switchboa case *testing.T, *testing.M, *testing.B, *testing.PB: break default: - globals.Log.FATAL.Panicf("InitTestingSession is restricted to testing only. Got %T", i) + jww.FATAL.Panicf("InitTestingSession is restricted to testing only. Got %T", i) } thisSession := storage.InitTestingSession(i) diff --git a/network/ephemeral/testutil.go b/network/ephemeral/testutil.go index 94df38ab2700eb1699b28db62ddf8b1d57e57745..fbcc4e3e8d031097f4d9447c0904f537451b3d40 100644 --- a/network/ephemeral/testutil.go +++ b/network/ephemeral/testutil.go @@ -8,7 +8,9 @@ package ephemeral import ( - "gitlab.com/elixxir/client/globals" + "testing" + + jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/interfaces" "gitlab.com/elixxir/client/interfaces/message" "gitlab.com/elixxir/client/interfaces/params" @@ -22,7 +24,6 @@ import ( "gitlab.com/xx_network/primitives/id/ephemeral" "gitlab.com/xx_network/primitives/ndf" "gitlab.com/xx_network/primitives/utils" - "testing" ) // testNetworkManager is a test implementation of NetworkManager interface. @@ -83,7 +84,7 @@ func NewTestNetworkManager(i interface{}) interfaces.NetworkManager { case *testing.T, *testing.M, *testing.B: break default: - globals.Log.FATAL.Panicf("initTesting is restricted to testing only."+ + jww.FATAL.Panicf("initTesting is restricted to testing only."+ "Got %T", i) } @@ -91,7 +92,7 @@ func NewTestNetworkManager(i interface{}) interfaces.NetworkManager { cert, err := utils.ReadFile(testkeys.GetNodeCertPath()) if err != nil { - globals.Log.FATAL.Panicf("Failed to create new test Instance: %v", err) + jww.FATAL.Panicf("Failed to create new test Instance: %v", err) } commsManager.AddHost(&id.Permissioning, "", cert, connect.GetDefaultHostParams()) @@ -101,7 +102,7 @@ func NewTestNetworkManager(i interface{}) interfaces.NetworkManager { thisInstance, err := network.NewInstanceTesting(instanceComms, getNDF(), getNDF(), nil, nil, i) if err != nil { - globals.Log.FATAL.Panicf("Failed to create new test Instance: %v", err) + jww.FATAL.Panicf("Failed to create new test Instance: %v", err) } thisManager := &testNetworkManager{instance: thisInstance} diff --git a/network/gateway/gateway.go b/network/gateway/gateway.go index 2af245821076802716ffd2bd1412f5a3fdc43540..f4a16cf2e78a5be6fe9cadbcd496b2cd7bb95b79 100644 --- a/network/gateway/gateway.go +++ b/network/gateway/gateway.go @@ -12,6 +12,7 @@ import ( "fmt" "github.com/pkg/errors" "gitlab.com/elixxir/comms/mixmessages" + "gitlab.com/elixxir/crypto/shuffle" "gitlab.com/xx_network/comms/connect" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/ndf" @@ -44,20 +45,42 @@ func Get(ndf *ndf.NetworkDefinition, hg HostGetter, rng io.Reader) (*connect.Hos return gwHost, nil } -// Get the last gateway Host from the given RoundInfo -func GetLast(hg HostGetter, ri *mixmessages.RoundInfo) (*connect.Host, error) { +// GetAllShuffled returns a shufled list of gateway hosts from the specified round +func GetAllShuffled(hg HostGetter, ri *mixmessages.RoundInfo) ([]*connect.Host, error) { roundTop := ri.GetTopology() - lastGw, err := id.Unmarshal(roundTop[len(roundTop)-1]) - if err != nil { - return nil, err + hosts := make([]*connect.Host, 0) + shuffledList := make([]uint64, 0) + + // Collect all host information from the round + for index, _ := range roundTop { + selectedId, err := id.Unmarshal(roundTop[index]) + if err != nil { + return nil, err + } + + selectedId.SetType(id.Gateway) + + gwHost, ok := hg.GetHost(selectedId) + if !ok { + return nil, errors.Errorf("Could not find host for gateway %s", selectedId) + } + hosts = append(hosts, gwHost) + shuffledList = append(shuffledList, uint64(index)) } - lastGw.SetType(id.Gateway) - gwHost, ok := hg.GetHost(lastGw) - if !ok { - return nil, errors.Errorf("Could not find host for gateway %s", lastGw) + returnHosts := make([]*connect.Host, len(hosts)) + + // Shuffle a list corresponding to the valid gateway hosts + shuffle.Shuffle(&shuffledList) + + // Index through the shuffled list, building a list + // of shuffled gateways from the round + for index, shuffledIndex := range shuffledList { + returnHosts[index] = hosts[shuffledIndex] } - return gwHost, nil + + return returnHosts, nil + } // ReadUint32 reads an integer from an io.Reader (which should be a CSPRNG) diff --git a/network/manager.go b/network/manager.go index 61b86d350a17811452a11740ed288f0abc9d15c5..4693b0a2cfeeb851d53ee39942e64296b09037ea 100644 --- a/network/manager.go +++ b/network/manager.go @@ -91,6 +91,10 @@ func NewManager(session *storage.Session, switchboard *switchboard.Switchboard, ReceptionID: session.User().GetCryptographicIdentity().GetReceptionID(), } + // register the node registration channel early so login connection updates + // get triggered for registration if necessary + instance.SetAddGatewayChan(m.NodeRegistration) + //create sub managers m.message = message.NewManager(m.Internal, m.param.Messages, m.NodeRegistration) m.round = rounds.NewManager(m.Internal, m.param.Rounds, m.message.GetMessageReceptionChannel()) @@ -124,7 +128,7 @@ func (m *manager) Follow(report interfaces.ClientErrorReport) (stoppable.Stoppab // Node Updates multi.Add(node.StartRegistration(m.Instance, m.Session, m.Rng, - m.Comms, m.NodeRegistration)) // Adding/Keys + m.Comms, m.NodeRegistration, m.param.ParallelNodeRegistrations)) // Adding/Keys //TODO-remover //m.runners.Add(StartNodeRemover(m.Context)) // Removing @@ -169,7 +173,8 @@ func (m *manager) CheckGarbledMessages() { m.message.CheckGarbledMessages() } -// InProgressRegistrations returns the number of in progress node registrations. +// InProgressRegistrations returns an approximation of the number of in progress +// node registrations. func (m *manager) InProgressRegistrations() int { - return len(m.Internal.NodeRegistration) + 1 + return len(m.Internal.NodeRegistration) } diff --git a/network/message/sendCmix.go b/network/message/sendCmix.go index 3994b2084074f5f3b2f4713bd6731201716f27f3..2a5892da077268b3ca9b5881e037fad7842480e3 100644 --- a/network/message/sendCmix.go +++ b/network/message/sendCmix.go @@ -80,6 +80,10 @@ func sendCmixHelper(msg format.Message, recipient *id.ID, param params.CMIX, ins continue } + //add the round on to the list of attempted so it is not tried again + attempted.Insert(bestRound) + + //compute if the round is too close to send to roundCutoffTime := time.Unix(0, int64(bestRound.Timestamps[states.QUEUED])) roundCutoffTime.Add(sendTimeBuffer) @@ -93,7 +97,6 @@ func sendCmixHelper(msg format.Message, recipient *id.ID, param params.CMIX, ins "received which has already started realtime: \n\t started: "+ "%s \n\t now: %s", bestRound.ID, recipient, msg.Digest(), roundCutoffTime, now) - attempted.Insert(bestRound) continue } @@ -195,9 +198,6 @@ func sendCmixHelper(msg format.Message, recipient *id.ID, param params.CMIX, ins wrappedMsg.MAC = roundKeys.MakeClientGatewayKey(salt, network.GenerateSlotDigest(wrappedMsg)) - //add the round on to the list of attempted so it is not tried again - attempted.Insert(bestRound) - jww.INFO.Printf("Sending to EphID %d (%s) on round %d, "+ "(msgDigest: %s, ecrMsgDigest: %s) via gateway %s", ephID.Int64(), recipient, bestRound.ID, msg.Digest(), @@ -210,9 +210,24 @@ func sendCmixHelper(msg format.Message, recipient *id.ID, param params.CMIX, ins if strings.Contains(err.Error(), "try a different round.") { jww.WARN.Printf("Failed to send to %s (msgDigest: %s) "+ - "due to round error with rougn %d, retrying: %+v", + "due to round error with round %d, retrying: %+v", recipient, msg.Digest(), bestRound.ID, err) continue + }else if strings.Contains(err.Error(), + "Could not authenticate client. Is the client registered " + + "with this node?"){ + jww.WARN.Printf("Failed to send to %s (msgDigest: %s) "+ + "via %s due to failed authentication: %s", + recipient, msg.Digest(), transmitGateway.GetId(), err) + //if we failed to send due to the gateway not recognizing our + // authorization, renegotiate with the node to refresh it + nodeID := transmitGateway.GetId().DeepCopy() + nodeID.SetType(id.Node) + //delete the keys + session.Cmix().Remove(nodeID) + //trigger + go handleMissingNodeKeys(instance, nodeRegistration, []*id.ID{nodeID}) + continue } jww.ERROR.Printf("Failed to send to EphID %d (%s) on "+ "round %d, bailing: %+v", ephID.Int64(), recipient, diff --git a/network/node/register.go b/network/node/register.go index 9393ec97e3508e1db5b10dc3fae53ac20269e0de..2b59d1e7ffd23853705541c46eb14242e8c3ca76 100644 --- a/network/node/register.go +++ b/network/node/register.go @@ -41,14 +41,18 @@ type RegisterNodeCommsInterface interface { } func StartRegistration(instance *network.Instance, session *storage.Session, rngGen *fastRNG.StreamGenerator, comms RegisterNodeCommsInterface, - c chan network.NodeGateway) stoppable.Stoppable { - stop := stoppable.NewSingle("NodeRegistration") + c chan network.NodeGateway, numParallel uint) stoppable.Stoppable { - instance.SetAddGatewayChan(c) + multi := stoppable.NewMulti("NodeRegistrations") - go registerNodes(session, rngGen, comms, stop, c) + for i:=uint(0);i<numParallel;i++{ + stop := stoppable.NewSingle(fmt.Sprintf("NodeRegistration %d", i)) - return stop + go registerNodes(session, rngGen, comms, stop, c) + multi.Add(stop) + } + + return multi } func registerNodes(session *storage.Session, rngGen *fastRNG.StreamGenerator, comms RegisterNodeCommsInterface, @@ -74,7 +78,6 @@ func registerNodes(session *storage.Session, rngGen *fastRNG.StreamGenerator, co case <-t.C: } } - } //registerWithNode serves as a helper for RegisterWithNodes @@ -94,12 +97,12 @@ func registerWithNode(comms RegisterNodeCommsInterface, ngw network.NodeGateway, return err } - jww.INFO.Printf("registerWithNode() begin registration with node: %s", nodeID) - if store.IsRegistered(nodeID) { return nil } + jww.INFO.Printf("registerWithNode() begin registration with node: %s", nodeID) + var transmissionKey *cyclic.Int // TODO: should move this to a precanned user initialization if uci.IsPrecanned() { diff --git a/network/rounds/retrieve.go b/network/rounds/retrieve.go index e19b1d5f3491b0b6d75e7283632398fd11a5329e..5269357776e9be37984cacfbe31a2208dda912d2 100644 --- a/network/rounds/retrieve.go +++ b/network/rounds/retrieve.go @@ -30,6 +30,10 @@ type roundLookup struct { identity reception.IdentityUse } +const noRoundError = "does not have round" + +// processMessageRetrieval received a roundLookup request and pings the gateways +// of that round for messages for the requested identity in the roundLookup func (m *Manager) processMessageRetrieval(comms messageRetrievalComms, quitCh <-chan struct{}) { @@ -40,14 +44,50 @@ func (m *Manager) processMessageRetrieval(comms messageRetrievalComms, done = true case rl := <-m.lookupRoundMessages: ri := rl.roundInfo - bundle, err := m.getMessagesFromGateway(ri, comms, rl.identity) + var bundle message.Bundle + + // Get a shuffled list of gateways in the round + gwHosts, err := gateway.GetAllShuffled(comms, ri) if err != nil { - jww.WARN.Printf("Failed to get messages for round %v: %s", - ri.ID, err) + jww.WARN.Printf("Failed to get gateway hosts from "+ + "round %v, not requesting from them", + ri.ID) + break + } + + // Attempt to request messages for every gateway in the list. + // If we retrieve without error, then we exit. If we error, then + // we retry with the next gateway in the list until we exhaust the list + for i, gwHost := range gwHosts { + // Attempt to request for this gateway + bundle, err = m.getMessagesFromGateway(id.Round(ri.ID), rl.identity, comms, gwHost) + if err != nil { + + jww.WARN.Printf("Failed on gateway [%d/%d] to get messages for round %v", + i, len(gwHosts), ri.ID) + + // Retry for the next gateway in the list + continue + } + + // If a non-error request, no longer retry break + + } + gwIDs := make([]*id.ID, 0) + for _, gwHost := range gwHosts { + gwIDs = append(gwIDs, gwHost.GetId()) } - if len(bundle.Messages) != 0 { + // After trying all gateways, if none returned we mark the round as a + // failure and print out the last error + if err != nil { + m.p.Fail(id.Round(ri.ID), rl.identity.EphId, rl.identity.Source) + jww.ERROR.Printf("Failed to get pickup round %d "+ + "from all gateways (%v): final gateway %s returned : %s", + id.Round(ri.ID), gwIDs, gwHosts[len(gwHosts)-1].GetId(), err) + } else if len(bundle.Messages) != 0 { + // If successful and there are messages, we send them to another thread bundle.Identity = rl.identity m.messageBundles <- bundle } @@ -55,38 +95,29 @@ func (m *Manager) processMessageRetrieval(comms messageRetrievalComms, } } -func (m *Manager) getMessagesFromGateway(roundInfo *pb.RoundInfo, - comms messageRetrievalComms, identity reception.IdentityUse) (message.Bundle, error) { - - rid := id.Round(roundInfo.ID) +// getMessagesFromGateway attempts to get messages from their assigned +// gateway host in the round specified. If successful +func (m *Manager) getMessagesFromGateway(roundID id.Round, identity reception.IdentityUse, + comms messageRetrievalComms, gwHost *connect.Host) (message.Bundle, error) { - //Get the host object for the gateway to send to - gwHost, err := gateway.GetLast(comms, roundInfo) - if err != nil { - return message.Bundle{}, errors.WithMessage(err, "Failed to get Gateway "+ - "to request from") - } - - jww.INFO.Printf("Getting messages for RoundID %v for EphID %d "+ - "via Gateway: %s", rid, identity.EphId, gwHost.GetId()) + jww.DEBUG.Printf("Trying to get messages for round %v for ephmeralID %d (%v) "+ + "via Gateway: %s", roundID, identity.EphId.Int64(), identity.Source.String(), gwHost.GetId()) // send the request msgReq := &pb.GetMessages{ ClientID: identity.EphId[:], - RoundID: uint64(rid), + RoundID: uint64(roundID), } msgResp, err := comms.RequestMessages(gwHost, msgReq) // Fail the round if an error occurs so it can be tried again later if err != nil { - m.p.Fail(id.Round(roundInfo.ID), identity.EphId, identity.Source) return message.Bundle{}, errors.WithMessagef(err, "Failed to "+ - "request messages from %s for round %d", gwHost.GetId(), rid) + "request messages from %s for round %d", gwHost.GetId(), roundID) } // if the gateway doesnt have the round, return an error if !msgResp.GetHasRound() { - m.p.Done(id.Round(roundInfo.ID), identity.EphId, identity.Source) - return message.Bundle{}, errors.Errorf("host %s does not have "+ - "roundID: %d", gwHost.String(), rid) + m.p.Done(roundID, identity.EphId, identity.Source) + return message.Bundle{}, errors.Errorf(noRoundError) } // If there are no messages print a warning. Due to the probabilistic nature @@ -96,19 +127,19 @@ func (m *Manager) getMessagesFromGateway(roundInfo *pb.RoundInfo, jww.WARN.Printf("host %s has no messages for client %s "+ " in round %d. This happening every once in a while is normal,"+ " but can be indicitive of a problem if it is consistant", gwHost, - m.TransmissionID, rid) + m.TransmissionID, roundID) return message.Bundle{}, nil } jww.INFO.Printf("Received %d messages in Round %v via Gateway %s for %d (%s)", - len(msgs), rid, gwHost.GetId(), identity.EphId.Int64(), identity.Source) + len(msgs), roundID, gwHost.GetId(), identity.EphId.Int64(), identity.Source) //build the bundle of messages to send to the message processor bundle := message.Bundle{ - Round: rid, + Round: roundID, Messages: make([]format.Message, len(msgs)), Finish: func() { - m.p.Done(rid, identity.EphId, identity.Source) + m.p.Done(roundID, identity.EphId, identity.Source) }, } @@ -120,4 +151,5 @@ func (m *Manager) getMessagesFromGateway(roundInfo *pb.RoundInfo, } return bundle, nil + } diff --git a/network/rounds/retrieve_test.go b/network/rounds/retrieve_test.go new file mode 100644 index 0000000000000000000000000000000000000000..2efd2c89c6865ba335d2e167cab343bb786370db --- /dev/null +++ b/network/rounds/retrieve_test.go @@ -0,0 +1,383 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright © 2020 xx network SEZC // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file // +/////////////////////////////////////////////////////////////////////////////// +package rounds + +import ( + "bytes" + "gitlab.com/elixxir/client/network/message" + "gitlab.com/elixxir/client/storage/reception" + pb "gitlab.com/elixxir/comms/mixmessages" + "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/id/ephemeral" + "reflect" + "testing" + "time" +) + +// Happy path +func TestManager_ProcessMessageRetrieval(t *testing.T) { + // General initializations + testManager := newManager(t) + roundId := id.Round(5) + mockComms := &mockMessageRetrievalComms{testingSignature: t} + quitChan := make(chan struct{}) + + // Create a local channel so reception is possible (testManager.messageBundles is + // send only via newManager call above) + messageBundleChan := make(chan message.Bundle) + testManager.messageBundles = messageBundleChan + + // Initialize the message retrieval + go testManager.processMessageRetrieval(mockComms, quitChan) + + // Construct expected values for checking + expectedEphID := ephemeral.Id{1, 2, 3, 4, 5, 6, 7, 8} + payloadMsg := []byte(PayloadMessage) + expectedPayload := make([]byte, 256) + copy(expectedPayload, payloadMsg) + + go func() { + requestGateway := id.NewIdFromString(ReturningGateway, id.Gateway, t) + + // Construct the round lookup + iu := reception.IdentityUse{ + Identity: reception.Identity{ + EphId: expectedEphID, + Source: requestGateway, + }, + } + + idList := [][]byte{requestGateway.Bytes()} + + roundInfo := &pb.RoundInfo{ + ID: uint64(roundId), + Topology: idList, + } + + // Send a round look up request + testManager.lookupRoundMessages <- roundLookup{ + roundInfo: roundInfo, + identity: iu, + } + + }() + + var testBundle message.Bundle + go func() { + // Receive the bundle over the channel + time.Sleep(1 * time.Second) + testBundle = <-messageBundleChan + + // Close the process + quitChan <- struct{}{} + + }() + + // Ensure bundle received and has expected values + time.Sleep(2 * time.Second) + if reflect.DeepEqual(testBundle, message.Bundle{}) { + t.Errorf("Did not receive a message bundle over the channel") + t.FailNow() + } + + if testBundle.Identity.EphId.Int64() != expectedEphID.Int64() { + t.Errorf("Unexpected ephemeral ID in bundle."+ + "\n\tExpected: %v"+ + "\n\tReceived: %v", expectedEphID, testBundle.Identity.EphId) + } + + if !bytes.Equal(expectedPayload, testBundle.Messages[0].GetPayloadA()) { + t.Errorf("Unexpected ephemeral ID in bundle."+ + "\n\tExpected: %v"+ + "\n\tReceived: %v", expectedPayload, testBundle.Messages[0].GetPayloadA()) + + } + +} + +// Utilize the mockComms to construct a gateway which does not have the round +func TestManager_ProcessMessageRetrieval_NoRound(t *testing.T) { + // General initializations + testManager := newManager(t) + roundId := id.Round(5) + mockComms := &mockMessageRetrievalComms{testingSignature: t} + quitChan := make(chan struct{}) + + // Create a local channel so reception is possible (testManager.messageBundles is + // send only via newManager call above) + messageBundleChan := make(chan message.Bundle) + testManager.messageBundles = messageBundleChan + + // Initialize the message retrieval + go testManager.processMessageRetrieval(mockComms, quitChan) + + expectedEphID := ephemeral.Id{1, 2, 3, 4, 5, 6, 7, 8} + + // Construct a gateway without keyword ID in utils_test.go + // ie mockComms does not return a round + dummyGateway := id.NewIdFromString("Sauron", id.Gateway, t) + + go func() { + // Construct the round lookup + iu := reception.IdentityUse{ + Identity: reception.Identity{ + EphId: expectedEphID, + Source: dummyGateway, + }, + } + + idList := [][]byte{dummyGateway.Bytes()} + + roundInfo := &pb.RoundInfo{ + ID: uint64(roundId), + Topology: idList, + } + + // Send a round look up request + testManager.lookupRoundMessages <- roundLookup{ + roundInfo: roundInfo, + identity: iu, + } + + }() + + var testBundle message.Bundle + go func() { + // Receive the bundle over the channel + time.Sleep(1 * time.Second) + testBundle = <-messageBundleChan + + // Close the process + quitChan <- struct{}{} + + }() + + time.Sleep(2 * time.Second) + if !reflect.DeepEqual(testBundle, message.Bundle{}) { + t.Errorf("Should not receive a message bundle, mock gateway should not return round."+ + "\n\tExpected: %v"+ + "\n\tReceived: %v", message.Bundle{}, testBundle) + } +} + +// Test the path where there are no messages, +// simulating a false positive in a bloom filter +func TestManager_ProcessMessageRetrieval_FalsePositive(t *testing.T) { + // General initializations + testManager := newManager(t) + roundId := id.Round(5) + mockComms := &mockMessageRetrievalComms{testingSignature: t} + quitChan := make(chan struct{}) + + // Create a local channel so reception is possible (testManager.messageBundles is + // send only via newManager call above) + messageBundleChan := make(chan message.Bundle) + testManager.messageBundles = messageBundleChan + + // Initialize the message retrieval + go testManager.processMessageRetrieval(mockComms, quitChan) + + // Construct expected values for checking + expectedEphID := ephemeral.Id{1, 2, 3, 4, 5, 6, 7, 8} + payloadMsg := []byte(PayloadMessage) + expectedPayload := make([]byte, 256) + copy(expectedPayload, payloadMsg) + + go func() { + // Construct the round lookup + iu := reception.IdentityUse{ + Identity: reception.Identity{ + EphId: expectedEphID, + Source: id.NewIdFromString("Source", id.User, t), + }, + } + + requestGateway := id.NewIdFromString(FalsePositive, id.Gateway, t) + + idList := [][]byte{requestGateway.Bytes()} + + roundInfo := &pb.RoundInfo{ + ID: uint64(roundId), + Topology: idList, + } + + // Send a round look up request + testManager.lookupRoundMessages <- roundLookup{ + roundInfo: roundInfo, + identity: iu, + } + + }() + + var testBundle message.Bundle + go func() { + // Receive the bundle over the channel + time.Sleep(1 * time.Second) + testBundle = <-messageBundleChan + + // Close the process + quitChan <- struct{}{} + + }() + + // Ensure no bundle was received due to false positive test + time.Sleep(2 * time.Second) + if !reflect.DeepEqual(testBundle, message.Bundle{}) { + t.Errorf("Received a message bundle over the channel, should receive empty message list") + t.FailNow() + } + +} + +// Ensure that the quit chan closes the program, on an otherwise happy path +func TestManager_ProcessMessageRetrieval_Quit(t *testing.T) { + // General initializations + testManager := newManager(t) + roundId := id.Round(5) + mockComms := &mockMessageRetrievalComms{testingSignature: t} + quitChan := make(chan struct{}) + + // Create a local channel so reception is possible (testManager.messageBundles is + // send only via newManager call above) + messageBundleChan := make(chan message.Bundle) + testManager.messageBundles = messageBundleChan + + // Initialize the message retrieval + go testManager.processMessageRetrieval(mockComms, quitChan) + + // Close the process early, before any logic below can be completed + quitChan <- struct{}{} + + // Construct expected values for checking + expectedEphID := ephemeral.Id{1, 2, 3, 4, 5, 6, 7, 8} + payloadMsg := []byte(PayloadMessage) + expectedPayload := make([]byte, 256) + copy(expectedPayload, payloadMsg) + + go func() { + // Construct the round lookup + iu := reception.IdentityUse{ + Identity: reception.Identity{ + EphId: expectedEphID, + }, + } + + requestGateway := id.NewIdFromString(ReturningGateway, id.Gateway, t) + + idList := [][]byte{requestGateway.Bytes()} + + roundInfo := &pb.RoundInfo{ + ID: uint64(roundId), + Topology: idList, + } + + // Send a round look up request + testManager.lookupRoundMessages <- roundLookup{ + roundInfo: roundInfo, + identity: iu, + } + + }() + + var testBundle message.Bundle + go func() { + // Receive the bundle over the channel + testBundle = <-messageBundleChan + + }() + + time.Sleep(1 * time.Second) + // Ensure no bundle was received due to quiting process early + if !reflect.DeepEqual(testBundle, message.Bundle{}) { + t.Errorf("Received a message bundle over the channel, process should have quit before reception") + t.FailNow() + } + +} + +// Path in which multiple error comms are encountered before a happy path comms +func TestManager_ProcessMessageRetrieval_MultipleGateways(t *testing.T) { + // General initializations + testManager := newManager(t) + roundId := id.Round(5) + mockComms := &mockMessageRetrievalComms{testingSignature: t} + quitChan := make(chan struct{}) + + // Create a local channel so reception is possible (testManager.messageBundles is + // send only via newManager call above) + messageBundleChan := make(chan message.Bundle) + testManager.messageBundles = messageBundleChan + + // Initialize the message retrieval + go testManager.processMessageRetrieval(mockComms, quitChan) + + // Construct expected values for checking + expectedEphID := ephemeral.Id{1, 2, 3, 4, 5, 6, 7, 8} + payloadMsg := []byte(PayloadMessage) + expectedPayload := make([]byte, 256) + copy(expectedPayload, payloadMsg) + + go func() { + requestGateway := id.NewIdFromString(ReturningGateway, id.Gateway, t) + errorGateway := id.NewIdFromString(ErrorGateway, id.Gateway, t) + // Construct the round lookup + iu := reception.IdentityUse{ + Identity: reception.Identity{ + EphId: expectedEphID, + Source: requestGateway, + }, + } + + // Create a list of ID's in which some error gateways must be contacted before the happy path + idList := [][]byte{errorGateway.Bytes(), errorGateway.Bytes(), requestGateway.Bytes()} + + roundInfo := &pb.RoundInfo{ + ID: uint64(roundId), + Topology: idList, + } + + // Send a round look up request + testManager.lookupRoundMessages <- roundLookup{ + roundInfo: roundInfo, + identity: iu, + } + + }() + + var testBundle message.Bundle + go func() { + // Receive the bundle over the channel + time.Sleep(1 * time.Second) + testBundle = <-messageBundleChan + + // Close the process + quitChan <- struct{}{} + + }() + + // Ensure that expected bundle is still received from happy comm + // despite initial errors + time.Sleep(2 * time.Second) + if reflect.DeepEqual(testBundle, message.Bundle{}) { + t.Errorf("Did not receive a message bundle over the channel") + t.FailNow() + } + + if testBundle.Identity.EphId.Int64() != expectedEphID.Int64() { + t.Errorf("Unexpected ephemeral ID in bundle."+ + "\n\tExpected: %v"+ + "\n\tReceived: %v", expectedEphID, testBundle.Identity.EphId) + } + + if !bytes.Equal(expectedPayload, testBundle.Messages[0].GetPayloadA()) { + t.Errorf("Unexpected ephemeral ID in bundle."+ + "\n\tExpected: %v"+ + "\n\tReceived: %v", expectedPayload, testBundle.Messages[0].GetPayloadA()) + + } + +} diff --git a/network/rounds/utils_test.go b/network/rounds/utils_test.go new file mode 100644 index 0000000000000000000000000000000000000000..f8f14e32778574850519b02fcd73da6d2171e2e5 --- /dev/null +++ b/network/rounds/utils_test.go @@ -0,0 +1,94 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright © 2020 xx network SEZC // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file // +/////////////////////////////////////////////////////////////////////////////// +package rounds + +import ( + "github.com/pkg/errors" + "gitlab.com/elixxir/client/network/internal" + "gitlab.com/elixxir/client/network/message" + "gitlab.com/elixxir/client/storage" + pb "gitlab.com/elixxir/comms/mixmessages" + "gitlab.com/xx_network/comms/connect" + "gitlab.com/xx_network/primitives/id" + "testing" +) + +func newManager(face interface{}) *Manager { + sess1 := storage.InitTestingSession(face) + + testManager := &Manager{ + lookupRoundMessages: make(chan roundLookup), + messageBundles: make(chan message.Bundle), + p: newProcessingRounds(), + Internal: internal.Internal{ + Session: sess1, + TransmissionID: sess1.GetUser().TransmissionID, + }, + } + + return testManager +} + +// Build ID off of this string for expected gateway +// which will return on over mock comm +const ReturningGateway = "GetMessageRequest" +const FalsePositive = "FalsePositive" +const PayloadMessage = "Payload" +const ErrorGateway = "Error" +type mockMessageRetrievalComms struct { + testingSignature *testing.T +} + +func (mmrc *mockMessageRetrievalComms) GetHost(hostId *id.ID) (*connect.Host, bool) { + h, _ := connect.NewHost(hostId, "0.0.0.0", []byte(""), connect.HostParams{ + MaxRetries: 0, + AuthEnabled: false, + }) + return h, true +} + +// Mock comm which returns differently based on the host ID +// ReturningGateway returns a happy path response, in which there is a message +// FalsePositive returns a response in which there were no messages in the round +// ErrorGateway returns an error on the mock comm +// Any other ID returns default no round errors +func (mmrc *mockMessageRetrievalComms) RequestMessages(host *connect.Host, + message *pb.GetMessages) (*pb.GetMessagesResponse, error) { + payloadMsg := []byte(PayloadMessage) + payload := make([]byte, 256) + copy(payload, payloadMsg) + testSlot := &pb.Slot{ + PayloadA: payload, + PayloadB: payload, + } + + // If we are the requesting on the returning gateway, return a mock response + returningGateway := id.NewIdFromString(ReturningGateway, id.Gateway, mmrc.testingSignature) + if host.GetId().Cmp(returningGateway) { + return &pb.GetMessagesResponse{ + Messages: []*pb.Slot{testSlot}, + HasRound: true, + }, nil + } + + // Return an empty message structure (ie a false positive in the bloom filter) + falsePositive := id.NewIdFromString(FalsePositive, id.Gateway, mmrc.testingSignature) + if host.GetId().Cmp(falsePositive) { + return &pb.GetMessagesResponse{ + Messages: []*pb.Slot{}, + HasRound: true, + }, nil + } + + // Return a mock error + errorGateway := id.NewIdFromString(ErrorGateway, id.Gateway, mmrc.testingSignature) + if host.GetId().Cmp(errorGateway) { + return &pb.GetMessagesResponse{}, errors.Errorf("Connection error") + } + + return nil, nil +} diff --git a/storage/e2e/session.go b/storage/e2e/session.go index fbfe0d0bd68b0bad85e97bcf94a5632bb2f7f8a5..76c614861f663ff834e22cc53e7e54c72f58d3ff 100644 --- a/storage/e2e/session.go +++ b/storage/e2e/session.go @@ -10,9 +10,13 @@ package e2e import ( "encoding/json" "fmt" + "math/big" + "sync" + "testing" + "time" + "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" - "gitlab.com/elixxir/client/globals" "gitlab.com/elixxir/client/interfaces/params" "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/crypto/cyclic" @@ -20,10 +24,6 @@ import ( "gitlab.com/elixxir/crypto/hash" "gitlab.com/xx_network/crypto/randomness" "gitlab.com/xx_network/primitives/id" - "math/big" - "sync" - "testing" - "time" ) const currentSessionVersion = 0 @@ -250,7 +250,7 @@ func GetSessionIDFromBaseKeyForTesting(baseKey *cyclic.Int, i interface{}) Sessi case *testing.T, *testing.M, *testing.B, *testing.PB: break default: - globals.Log.FATAL.Panicf("GetSessionIDFromBaseKeyForTesting is restricted to testing only. Got %T", i) + jww.FATAL.Panicf("GetSessionIDFromBaseKeyForTesting is restricted to testing only. Got %T", i) } return getSessionIDFromBaseKey(baseKey) } diff --git a/storage/session.go b/storage/session.go index 2eb8652c501d957683f8c72947e3586848c13a11..be1837de7fb32adf9d13549c8f42bfe00683c05f 100644 --- a/storage/session.go +++ b/storage/session.go @@ -10,8 +10,11 @@ package storage import ( + "sync" + "testing" + "github.com/pkg/errors" - "gitlab.com/elixxir/client/globals" + jww "github.com/spf13/jwalterweatherman" userInterface "gitlab.com/elixxir/client/interfaces/user" "gitlab.com/elixxir/client/storage/auth" "gitlab.com/elixxir/client/storage/clientVersion" @@ -32,8 +35,6 @@ import ( "gitlab.com/xx_network/crypto/signature/rsa" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/ndf" - "sync" - "testing" ) // Number of rounds to store in the CheckedRound buffer @@ -303,7 +304,7 @@ func InitTestingSession(i interface{}) *Session { case *testing.T, *testing.M, *testing.B, *testing.PB: break default: - globals.Log.FATAL.Panicf("InitTestingSession is restricted to testing only. Got %T", i) + jww.FATAL.Panicf("InitTestingSession is restricted to testing only. Got %T", i) } privKey, _ := rsa.LoadPrivateKeyFromPem([]byte("-----BEGIN PRIVATE KEY-----\n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\nOaRA5ZbdE7g7vxKRV36jT3wvD7W+\n-----END PRIVATE KEY-----\n")) @@ -313,7 +314,7 @@ func InitTestingSession(i interface{}) *Session { uid := id.NewIdFromString("zezima", id.User, i) u, err := user.NewUser(kv, uid, uid, []byte("salt"), []byte("salt"), privKey, privKey, false) if err != nil { - globals.Log.FATAL.Panicf("InitTestingSession failed to create dummy user: %+v", err) + jww.FATAL.Panicf("InitTestingSession failed to create dummy user: %+v", err) } u.SetTransmissionRegistrationValidationSignature([]byte("sig")) u.SetReceptionRegistrationValidationSignature([]byte("sig")) @@ -337,25 +338,25 @@ func InitTestingSession(i interface{}) *Session { "DC4473F996BDCE6EED1CABED8B6F116F7AD9CF505DF0F998E34AB27514B0FFE7", 16)) cmixStore, err := cmix.NewStore(cmixGrp, kv, cmixGrp.NewInt(2)) if err != nil { - globals.Log.FATAL.Panicf("InitTestingSession failed to create dummy cmix session: %+v", err) + jww.FATAL.Panicf("InitTestingSession failed to create dummy cmix session: %+v", err) } s.cmix = cmixStore e2eStore, err := e2e.NewStore(cmixGrp, kv, cmixGrp.NewInt(2), uid, fastRNG.NewStreamGenerator(7, 3, csprng.NewSystemRNG)) if err != nil { - globals.Log.FATAL.Panicf("InitTestingSession failed to create dummy cmix session: %+v", err) + jww.FATAL.Panicf("InitTestingSession failed to create dummy cmix session: %+v", err) } s.e2e = e2eStore s.criticalMessages, err = utility.NewE2eMessageBuffer(s.kv, criticalMessagesKey) if err != nil { - globals.Log.FATAL.Panicf("InitTestingSession failed to create dummy critical messages: %+v", err) + jww.FATAL.Panicf("InitTestingSession failed to create dummy critical messages: %+v", err) } s.garbledMessages, err = utility.NewMeteredCmixMessageBuffer(s.kv, garbledMessagesKey) if err != nil { - globals.Log.FATAL.Panicf("Failed to create garbledMessages buffer: %+v", err) + jww.FATAL.Panicf("Failed to create garbledMessages buffer: %+v", err) } s.conversations = conversation.NewStore(s.kv)