diff --git a/api/authenticatedChannel.go b/api/authenticatedChannel.go index 0debb583f3496b945f3601118a5940d69683a3bd..88682af983c107345b6415648bec9558f2eb4d6b 100644 --- a/api/authenticatedChannel.go +++ b/api/authenticatedChannel.go @@ -12,7 +12,7 @@ import ( jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/auth" "gitlab.com/elixxir/client/interfaces" - "gitlab.com/elixxir/client/interfaces/contact" + "gitlab.com/elixxir/crypto/contact" "gitlab.com/elixxir/primitives/fact" "gitlab.com/xx_network/primitives/id" ) @@ -20,16 +20,17 @@ import ( // RequestAuthenticatedChannel sends a request to another party to establish an // authenticated channel // It will not run if the network status is not healthy -// An error will be returned if a channel already exists, if a request was -// already received, or if a request was already sent +// An error will be returned if a channel already exists or if a request was +// already received // When a confirmation occurs, the channel will be created and the callback // will be called +// Can be retried. func (c *Client) RequestAuthenticatedChannel(recipient, me contact.Contact, - message string) error { + message string) (id.Round, error) { jww.INFO.Printf("RequestAuthenticatedChannel(%s)", recipient.ID) if !c.network.GetHealthTracker().IsHealthy() { - return errors.New("Cannot request authenticated channel " + + return 0, errors.New("Cannot request authenticated channel " + "creation when the network is not healthy") } @@ -60,11 +61,12 @@ func (c *Client) GetAuthenticatedChannelRequest(partner *id.ID) (contact.Contact // An error will be returned if a channel already exists, if a request doest // exist, or if the passed in contact does not exactly match the received // request -func (c *Client) ConfirmAuthenticatedChannel(recipient contact.Contact) error { +// Can be retried. +func (c *Client) ConfirmAuthenticatedChannel(recipient contact.Contact) (id.Round, error) { jww.INFO.Printf("ConfirmAuthenticatedChannel(%s)", recipient.ID) if !c.network.GetHealthTracker().IsHealthy() { - return errors.New("Cannot request authenticated channel " + + return 0, errors.New("Cannot request authenticated channel " + "creation when the network is not healthy") } diff --git a/api/client.go b/api/client.go index 31a81017e4d6825f5f3d64f79d4844685ef1b110..ae87fdc6dc36a974875f5a73ddea87ed52fbded1 100644 --- a/api/client.go +++ b/api/client.go @@ -8,6 +8,7 @@ package api import ( + "gitlab.com/xx_network/primitives/id" "time" "github.com/pkg/errors" @@ -83,33 +84,12 @@ func NewClient(ndfJSON, storageDir string, password []byte, registrationCode str protoUser := createNewUser(rngStream, cmixGrp, e2eGrp) - // Get current client version - currentVersion, err := version.ParseVersion(SEMVER) - if err != nil { - return errors.WithMessage(err, "Could not parse version string.") - } - - // Create Storage - passwordStr := string(password) - storageSess, err := storage.New(storageDir, passwordStr, protoUser, - currentVersion, cmixGrp, e2eGrp, rngStreamGen) + err = checkVersionAndSetupStorage(def, storageDir, password, protoUser, + cmixGrp, e2eGrp, rngStreamGen, false, registrationCode) if err != nil { return err } - // Save NDF to be used in the future - storageSess.SetBaseNDF(def) - - //store the registration code for later use - storageSess.SetRegCode(registrationCode) - - //move the registration state to keys generated - err = storageSess.ForwardRegistrationStatus(storage.KeyGenComplete) - if err != nil { - return errors.WithMessage(err, "Failed to denote state "+ - "change in session") - } - //TODO: close the session return nil } @@ -134,29 +114,39 @@ func NewPrecannedClient(precannedID uint, defJSON, storageDir string, password [ protoUser := createPrecannedUser(precannedID, rngStream, cmixGrp, e2eGrp) - // Get current client version - currentVersion, err := version.ParseVersion(SEMVER) + err = checkVersionAndSetupStorage(def, storageDir, password, protoUser, + cmixGrp, e2eGrp, rngStreamGen, true, "") if err != nil { - return errors.WithMessage(err, "Could not parse version string.") + return err } + //TODO: close the session + return nil +} - // Create Storage - passwordStr := string(password) - storageSess, err := storage.New(storageDir, passwordStr, protoUser, - currentVersion, cmixGrp, e2eGrp, rngStreamGen) +// NewVanityClient creates a user with a receptionID that starts with the supplied prefix +// It creates client storage, generates keys, connects, and registers +// with the network. Note that this does not register a username/identity, but +// merely creates a new cryptographic identity for adding such information +// at a later date. +func NewVanityClient(ndfJSON, storageDir string, password []byte, registrationCode string, userIdPrefix string) error { + jww.INFO.Printf("NewVanityClient()") + // Use fastRNG for RNG ops (AES fortuna based RNG using system RNG) + rngStreamGen := fastRNG.NewStreamGenerator(12, 3, csprng.NewSystemRNG) + rngStream := rngStreamGen.GetStream() + + // Parse the NDF + def, err := parseNDF(ndfJSON) if err != nil { return err } + cmixGrp, e2eGrp := decodeGroups(def) - // Save NDF to be used in the future - storageSess.SetBaseNDF(def) + protoUser := createNewVanityUser(rngStream, cmixGrp, e2eGrp, userIdPrefix) - //move the registration state to indicate registered with permissioning - err = storageSess.ForwardRegistrationStatus( - storage.PermissioningComplete) + err = checkVersionAndSetupStorage(def, storageDir, password, protoUser, + cmixGrp, e2eGrp, rngStreamGen, false, registrationCode) if err != nil { - return errors.WithMessage(err, "Failed to denote state "+ - "change in session") + return err } //TODO: close the session @@ -204,11 +194,14 @@ func Login(storageDir string, password []byte, parameters params.Network) (*Clie //Open the client c, err := OpenClient(storageDir, password, parameters) - if err != nil { return nil, err } + u := c.storage.GetUser() + jww.INFO.Printf("Client Logged in: \n\tTransmisstionID: %s " + + "\n\tReceptionID: %s", u.TransmissionID, u.ReceptionID) + //Attach the services interface c.services = newServiceProcessiesList(c.runner) @@ -387,7 +380,9 @@ func (c *Client) initPermissioning(def *ndf.NetworkDefinition) error { // - Auth Callback (/auth/callback.go) // Handles both auth confirm and requests func (c *Client) StartNetworkFollower() (<-chan interfaces.ClientError, error) { - jww.INFO.Printf("StartNetworkFollower()") + u := c.GetUser() + jww.INFO.Printf("StartNetworkFollower() \n\tTransmisstionID: %s " + + "\n\tReceptionID: %s", u.TransmissionID, u.ReceptionID) c.clientErrorChannel = make(chan interfaces.ClientError, 1000) @@ -440,7 +435,6 @@ func (c *Client) StopNetworkFollower(timeout time.Duration) error { if err != nil { return errors.WithMessage(err, "Failed to Stop the Network Follower") } - close(c.clientErrorChannel) err = c.runner.Close(timeout) if err != nil { return errors.WithMessage(err, "Failed to Stop the Network Follower") @@ -517,9 +511,9 @@ func (c *Client) GetNetworkInterface() interfaces.NetworkManager { } // GetNodeRegistrationStatus gets the current status of node registration. It -// returns the number of nodes that the client is registered and the number of -// in progress node registrations. An error is returned if the network is not -// healthy. +// returns the the total number of nodes in the NDF and the number of those +// which are currently registers with. An error is returned if the network is +// not healthy. func (c *Client) GetNodeRegistrationStatus() (int, int, error) { // Return an error if the network is not healthy if !c.GetHealth().IsHealthy() { @@ -527,13 +521,24 @@ func (c *Client) GetNodeRegistrationStatus() (int, int, error) { "network is not healthy") } - // Get the number of nodes that client is registered with - registeredNodes := c.storage.Cmix().Count() + nodes := c.GetNetworkInterface().GetInstance().GetPartialNdf().Get().Nodes - // Get the number of in progress node registrations - inProgress := c.network.InProgressRegistrations() + cmixStore := c.storage.Cmix() - return registeredNodes, inProgress, nil + var numRegistered int + for i, n := range nodes{ + nid, err := id.Unmarshal(n.ID) + if err!=nil{ + return 0,0, errors.Errorf("Failed to unmarshal node ID %v " + + "(#%d): %s", n.ID, i, err.Error()) + } + if cmixStore.Has(nid){ + numRegistered++ + } + } + + // Get the number of in progress node registrations + return numRegistered, len(nodes), nil } // ----- Utility Functions ----- @@ -567,3 +572,43 @@ func decodeGroups(ndf *ndf.NetworkDefinition) (cmixGrp, e2eGrp *cyclic.Group) { return cmixGrp, e2eGrp } + +// checkVersionAndSetupStorage is common code shared by NewClient, NewPrecannedClient and NewVanityClient +// it checks client version and creates a new storage for user data +func checkVersionAndSetupStorage(def *ndf.NetworkDefinition, storageDir string, password []byte, + protoUser user.User, cmixGrp, e2eGrp *cyclic.Group, rngStreamGen *fastRNG.StreamGenerator, + isPrecanned bool, registrationCode string) error { + // Get current client version + currentVersion, err := version.ParseVersion(SEMVER) + if err != nil { + return errors.WithMessage(err, "Could not parse version string.") + } + + // Create Storage + passwordStr := string(password) + storageSess, err := storage.New(storageDir, passwordStr, protoUser, + currentVersion, cmixGrp, e2eGrp, rngStreamGen) + if err != nil { + return err + } + + // Save NDF to be used in the future + storageSess.SetBaseNDF(def) + + if !isPrecanned { + //store the registration code for later use + storageSess.SetRegCode(registrationCode) + //move the registration state to keys generated + err = storageSess.ForwardRegistrationStatus(storage.KeyGenComplete) + } else { + //move the registration state to indicate registered with permissioning + err = storageSess.ForwardRegistrationStatus(storage.PermissioningComplete) + } + + if err != nil { + return errors.WithMessage(err, "Failed to denote state "+ + "change in session") + } + + return nil +} diff --git a/api/user.go b/api/user.go index 892d84c63c8fb0e29001774c6c645f351b3d00b8..48d7f992dfa32b48a3905752c55459ddc710e701 100644 --- a/api/user.go +++ b/api/user.go @@ -17,6 +17,10 @@ import ( "gitlab.com/xx_network/crypto/xx" "gitlab.com/xx_network/primitives/id" "math/rand" + "regexp" + "runtime" + "strings" + "sync" ) const ( @@ -134,3 +138,126 @@ func createPrecannedUser(precannedID uint, rng csprng.Source, cmix, e2e *cyclic. ReceptionRSA: rsaKey, } } + +// createNewVanityUser generates an identity for cMix +// The identity's ReceptionID is not random but starts with the supplied prefix +func createNewVanityUser(rng csprng.Source, cmix, e2e *cyclic.Group, prefix string) user.User { + // CMIX Keygen + // FIXME: Why 256 bits? -- this is spec but not explained, it has + // to do with optimizing operations on one side and still preserves + // decent security -- cite this. + cMixKeyBytes, err := csprng.GenerateInGroup(cmix.GetPBytes(), 256, rng) + if err != nil { + jww.FATAL.Panicf(err.Error()) + } + + // DH Keygen + // FIXME: Why 256 bits? -- this is spec but not explained, it has + // to do with optimizing operations on one side and still preserves + // decent security -- cite this. Why valid for BOTH e2e and cmix? + e2eKeyBytes, err := csprng.GenerateInGroup(e2e.GetPBytes(), 256, rng) + if err != nil { + jww.FATAL.Panicf(err.Error()) + } + + // RSA Keygen (4096 bit defaults) + transmissionRsaKey, err := rsa.GenerateKey(rng, rsa.DefaultRSABitLen) + if err != nil { + jww.FATAL.Panicf(err.Error()) + } + + // Salt, UID, etc gen + transmissionSalt := make([]byte, SaltSize) + n, err := csprng.NewSystemRNG().Read(transmissionSalt) + if err != nil { + jww.FATAL.Panicf(err.Error()) + } + if n != SaltSize { + jww.FATAL.Panicf("transmissionSalt size too small: %d", n) + } + transmissionID, err := xx.NewID(transmissionRsaKey.GetPublic(), transmissionSalt, id.User) + if err != nil { + jww.FATAL.Panicf(err.Error()) + } + + receptionRsaKey, err := rsa.GenerateKey(rng, rsa.DefaultRSABitLen) + if err != nil { + jww.FATAL.Panicf(err.Error()) + } + + var mu sync.Mutex // just in case more than one go routine tries to access receptionSalt and receptionID + done := make(chan struct{}) + found:= make(chan bool) + wg:= &sync.WaitGroup{} + cores := runtime.NumCPU() + + var receptionSalt []byte + var receptionID *id.ID + + pref := prefix + ignoreCase := false + // check if case-insensitivity is enabled + if strings.HasPrefix(prefix, "(?i)") { + pref = strings.ToLower(pref[4:]) + ignoreCase = true + } + // Check if prefix contains valid Base64 characters + match, _ := regexp.MatchString("^[A-Za-z0-9+/]+$", pref) + if match == false { + jww.FATAL.Panicf("Prefix contains non-Base64 characters") + } + jww.INFO.Printf("Vanity userID generation started. Prefix: %s Ignore-Case: %v NumCPU: %d", pref, ignoreCase, cores) + for w := 0; w < cores; w++{ + wg.Add(1) + go func() { + rSalt := make([]byte, SaltSize) + for { + select { + case <- done: + defer wg.Done() + return + default: + n, err = csprng.NewSystemRNG().Read(rSalt) + if err != nil { + jww.FATAL.Panicf(err.Error()) + } + if n != SaltSize { + jww.FATAL.Panicf("receptionSalt size too small: %d", n) + } + rID, err := xx.NewID(receptionRsaKey.GetPublic(), rSalt, id.User) + if err != nil { + jww.FATAL.Panicf(err.Error()) + } + id := rID.String() + if ignoreCase { + id = strings.ToLower(id) + } + if strings.HasPrefix(id, pref) { + mu.Lock() + receptionID = rID + receptionSalt = rSalt + mu.Unlock() + found <- true + defer wg.Done() + return + } + } + } + }() + } + // wait for a solution then close the done channel to signal the workers to exit + <- found + close(done) + wg.Wait() + return user.User{ + TransmissionID: transmissionID.DeepCopy(), + TransmissionSalt: transmissionSalt, + TransmissionRSA: transmissionRsaKey, + ReceptionID: receptionID.DeepCopy(), + ReceptionSalt: receptionSalt, + ReceptionRSA: receptionRsaKey, + Precanned: false, + CmixDhPrivateKey: cmix.NewIntFromBytes(cMixKeyBytes), + E2eDhPrivateKey: e2e.NewIntFromBytes(e2eKeyBytes), + } +} diff --git a/api/version.go b/api/version.go deleted file mode 100644 index 57d607b585497d1c4e73ef104536e19b8ab82ed2..0000000000000000000000000000000000000000 --- a/api/version.go +++ /dev/null @@ -1,42 +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 api - -/* -func (c *Client) Version() version.Version { - v, err := version.ParseVersion(SEMVER) - if err != nil { - jww.FATAL.Panicf("Failed to parse the client version: %s", err) - } - return v -} - -func (c *Client) checkVersion() error { - clientVersion := c.Version() - jww.INFO.Printf("Client Version: %s", clientVersion.String()) - - has, netVersion, err := c.permissioning.GetNetworkVersion() - if err != nil { - return errors.WithMessage(err, "failed to get check "+ - "version compatibility") - } - if has { - jww.INFO.Printf("Minimum Network Version: %v", netVersion) - if !version.IsCompatible(netVersion, clientVersion) { - return errors.Errorf("Client and Minimum Network Version are "+ - "incompatible\n"+ - "\tMinimum Network: %s\n"+ - "\tClient: %s", netVersion.String(), clientVersion.String()) - } - } else { - jww.INFO.Printf("Network requires no minimum version") - } - - return nil -} -*/ diff --git a/api/version_vars.go b/api/version_vars.go index dc333c8a688faddebc96c5de0f589d9137801308..1a4ed3b5336c44eeed1cf474d589c1175808c16a 100644 --- a/api/version_vars.go +++ b/api/version_vars.go @@ -1,10 +1,10 @@ // Code generated by go generate; DO NOT EDIT. // This file was generated by robots at -// 2021-03-10 14:16:47.093264 -0800 PST m=+0.046129936 +// 2021-04-02 08:56:27.8657223 -0700 PDT m=+0.054483401 package api -const GITVERSION = `2096d6ae Merge branch 'Anne/v2' into 'release'` -const SEMVER = "2.0.0" +const GITVERSION = `6020ab79 removed an extranious print` +const SEMVER = "2.3.0" const DEPENDENCIES = `module gitlab.com/elixxir/client go 1.13 @@ -13,10 +13,12 @@ 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/liyue201/goqr v0.0.0-20200803022322-df443203d4ea 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/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e github.com/smartystreets/assertions v1.0.1 // indirect github.com/spf13/afero v1.5.1 // indirect github.com/spf13/cast v1.3.1 // indirect @@ -24,19 +26,18 @@ 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.20210310191636-1bca0ddac665 - gitlab.com/elixxir/crypto v0.0.7-0.20210309193114-8a6225c667e2 + gitlab.com/elixxir/comms v0.0.4-0.20210401210158-6053ad2e224c + gitlab.com/elixxir/crypto v0.0.7-0.20210401210040-b7f1da24ef13 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 + gitlab.com/elixxir/primitives v0.0.3-0.20210401175645-9b7b92f74ec4 + gitlab.com/xx_network/comms v0.0.4-0.20210401160731-7b8890cdd8ad + gitlab.com/xx_network/crypto v0.0.5-0.20210401160648-4f06cace9123 + gitlab.com/xx_network/primitives v0.0.4-0.20210331161816-ed23858bdb93 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 + google.golang.org/protobuf v1.26.0-rc.1 gopkg.in/ini.v1 v1.62.0 // indirect ) diff --git a/auth/callback.go b/auth/callback.go index a304905f4bef5e6177d04d1b9bb7693fe36be24d..ef21512f88a06c19322c03518bc262d7d2e94ebe 100644 --- a/auth/callback.go +++ b/auth/callback.go @@ -11,9 +11,10 @@ import ( "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/interfaces" - "gitlab.com/elixxir/client/interfaces/contact" + "gitlab.com/elixxir/client/interfaces/message" "gitlab.com/elixxir/client/stoppable" "gitlab.com/elixxir/client/storage/auth" + "gitlab.com/elixxir/crypto/contact" "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/crypto/diffieHellman" cAuth "gitlab.com/elixxir/crypto/e2e/auth" @@ -25,48 +26,55 @@ import ( func (m *Manager) StartProcessies() stoppable.Stoppable { stop := stoppable.NewSingle("Auth") - authStore := m.storage.Auth() - grp := m.storage.E2e().GetGroup() go func() { - select { - case <-stop.Quit(): - return - case msg := <-m.rawMessages: - //lookup the message, check if it is an auth request - cmixMsg := format.Unmarshal(msg.Payload) - fp := cmixMsg.GetKeyFP() - jww.INFO.Printf("RAW AUTH FP: %v", fp) - // this takes the request lock if it is a specific fp, - // all exits after this need to call fail or delete if it is - // specific - fpType, sr, myHistoricalPrivKey, err := authStore.GetFingerprint(fp) - if err != nil { - jww.TRACE.Printf("FINGERPRINT FAILURE: %s", err.Error()) - // if the lookup fails, ignore the message. It is likely - // garbled or for a different protocol - break - } - - //denote that the message is not garbled - m.storage.GetGarbledMessages().Remove(cmixMsg) - - switch fpType { - // if it is general, that means a new request has been received - case auth.General: - m.handleRequest(cmixMsg, myHistoricalPrivKey, grp) - // if it is specific, that means the original request was sent - // by this users and a confirmation has been received - case auth.Specific: - jww.INFO.Printf("Received AutConfirm from %s,"+ - " msgDigest: %s", sr.GetPartner(), cmixMsg.Digest()) - m.handleConfirm(cmixMsg, sr, grp) + for { + select { + case <-stop.Quit(): + return + case msg := <-m.rawMessages: + m.processAuthMessage(msg) } } }() return stop } +func (m *Manager) processAuthMessage(msg message.Receive) { + authStore := m.storage.Auth() + //lookup the message, check if it is an auth request + cmixMsg := format.Unmarshal(msg.Payload) + fp := cmixMsg.GetKeyFP() + jww.INFO.Printf("RAW AUTH FP: %v", fp) + // this takes the request lock if it is a specific fp, all + // exits after this need to call fail or delete if it is + // specific + fpType, sr, myHistoricalPrivKey, err := authStore.GetFingerprint(fp) + if err != nil { + jww.TRACE.Printf("FINGERPRINT FAILURE: %s", err.Error()) + // if the lookup fails, ignore the message. It is + // likely garbled or for a different protocol + return + } + + //denote that the message is not garbled + m.storage.GetGarbledMessages().Remove(cmixMsg) + grp := m.storage.E2e().GetGroup() + + switch fpType { + case auth.General: + // if it is general, that means a new request has + // been received + m.handleRequest(cmixMsg, myHistoricalPrivKey, grp) + case auth.Specific: + // if it is specific, that means the original request was sent + // by this users and a confirmation has been received + jww.INFO.Printf("Received AutConfirm from %s, msgDigest: %s", + sr.GetPartner(), cmixMsg.Digest()) + m.handleConfirm(cmixMsg, sr, grp) + } +} + func (m *Manager) handleRequest(cmixMsg format.Message, myHistoricalPrivKey *cyclic.Int, grp *cyclic.Group) { //decode the outer format @@ -152,8 +160,8 @@ func (m *Manager) handleRequest(cmixMsg format.Message, " msgDigest: %s which has been requested, auto-confirming", partnerID, cmixMsg.Digest()) // do the confirmation - if err := m.doConfirm(sr2, grp, partnerPubKey, myPubKey, - ecrFmt.GetOwnership()); err != nil { + if err := m.doConfirm(sr2, grp, partnerPubKey, m.storage.E2e().GetDHPrivateKey(), + sr2.GetPartnerHistoricalPubKey(), ecrFmt.GetOwnership()); err != nil { jww.WARN.Printf("Auto Confirmation with %s failed: %s", partnerID, err) } @@ -241,8 +249,8 @@ func (m *Manager) handleConfirm(cmixMsg format.Message, sr *auth.SentRequest, } // finalize the confirmation - if err := m.doConfirm(sr, grp, partnerPubKey, sr.GetPartnerHistoricalPubKey(), - ecrFmt.GetOwnership()); err != nil { + if err := m.doConfirm(sr, grp, partnerPubKey, sr.GetMyPrivKey(), + sr.GetPartnerHistoricalPubKey(), ecrFmt.GetOwnership()); err != nil { jww.WARN.Printf("Confirmation failed: %s", err) m.storage.Auth().Fail(sr.GetPartner()) return @@ -250,10 +258,10 @@ func (m *Manager) handleConfirm(cmixMsg format.Message, sr *auth.SentRequest, } func (m *Manager) doConfirm(sr *auth.SentRequest, grp *cyclic.Group, - partnerPubKey, myPubKeyOwnershipProof *cyclic.Int, ownershipProof []byte) error { + partnerPubKey, myPrivateKeyOwnershipProof, partnerPubKeyOwnershipProof *cyclic.Int, ownershipProof []byte) error { // verify the message came from the intended recipient - if !cAuth.VerifyOwnershipProof(sr.GetMyPrivKey(), - myPubKeyOwnershipProof, grp, ownershipProof) { + if !cAuth.VerifyOwnershipProof(myPrivateKeyOwnershipProof, + partnerPubKeyOwnershipProof, grp, ownershipProof) { return errors.Errorf("Failed authenticate identity for auth "+ "confirmation of %s", sr.GetPartner()) } diff --git a/auth/confirm.go b/auth/confirm.go index d1b88bf99d9a1fe2871850b5d7c810ea39f7f6a6..d91f81e33e9e1d52aac5136e620ec405842ccd24 100644 --- a/auth/confirm.go +++ b/auth/confirm.go @@ -11,27 +11,24 @@ import ( "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/interfaces" - "gitlab.com/elixxir/client/interfaces/contact" "gitlab.com/elixxir/client/interfaces/params" - "gitlab.com/elixxir/client/interfaces/utility" "gitlab.com/elixxir/client/storage" - ds "gitlab.com/elixxir/comms/network/dataStructures" + "gitlab.com/xx_network/primitives/id" + "gitlab.com/elixxir/crypto/contact" "gitlab.com/elixxir/crypto/diffieHellman" cAuth "gitlab.com/elixxir/crypto/e2e/auth" "gitlab.com/elixxir/primitives/format" - "gitlab.com/elixxir/primitives/states" "io" - "time" ) func ConfirmRequestAuth(partner contact.Contact, rng io.Reader, - storage *storage.Session, net interfaces.NetworkManager) error { + storage *storage.Session, net interfaces.NetworkManager) (id.Round, error) { /*edge checking*/ // check that messages can be sent over the network if !net.GetHealthTracker().IsHealthy() { - return errors.New("Cannot confirm authenticated message " + + return 0, errors.New("Cannot confirm authenticated message " + "when the network is not healthy") } @@ -40,14 +37,14 @@ func ConfirmRequestAuth(partner contact.Contact, rng io.Reader, // the lock storedContact, err := storage.Auth().GetReceivedRequest(partner.ID) if err != nil { - return errors.Errorf("failed to find a pending Auth Request: %s", + return 0, errors.Errorf("failed to find a pending Auth Request: %s", err) } // verify the passed contact matches what is stored if storedContact.DhPubKey.Cmp(partner.DhPubKey) != 0 { storage.Auth().Fail(partner.ID) - return errors.WithMessage(err, "Pending Auth Request has different "+ + return 0, errors.WithMessage(err, "Pending Auth Request has different "+ "pubkey than stored") } @@ -68,7 +65,7 @@ func ConfirmRequestAuth(partner contact.Contact, rng io.Reader, _, err = rng.Read(salt) if err != nil { storage.Auth().Fail(partner.ID) - return errors.Wrap(err, "Failed to generate salt for "+ + return 0, errors.Wrap(err, "Failed to generate salt for "+ "confirmation") } @@ -108,21 +105,19 @@ func ConfirmRequestAuth(partner contact.Contact, rng io.Reader, if err := storage.E2e().AddPartner(partner.ID, partner.DhPubKey, newPrivKey, p, p); err != nil { storage.Auth().Fail(partner.ID) - return errors.Errorf("Failed to create channel with partner (%s) "+ + return 0, errors.Errorf("Failed to create channel with partner (%s) "+ "on confirmation: %+v", partner.ID, err) } // delete the in progress negotiation // this unlocks the request lock - if err := storage.Auth().Delete(partner.ID); err != nil { - return errors.Errorf("UNRECOVERABLE! Failed to delete in "+ + //fixme - do these deletes at a later date + /*if err := storage.Auth().Delete(partner.ID); err != nil { + return 0, errors.Errorf("UNRECOVERABLE! Failed to delete in "+ "progress negotiation with partner (%s) after creating confirmation: %+v", partner.ID, err) - } - - //store the message as a critical message so it will always be sent - storage.GetCriticalRawMessages().AddProcessing(cmixMsg, partner.ID) + }*/ jww.INFO.Printf("Confirming Auth with %s, msgDigest: %s", partner.ID, cmixMsg.Digest()) @@ -134,39 +129,11 @@ func ConfirmRequestAuth(partner contact.Contact, rng io.Reader, // retried jww.INFO.Printf("Auth Confirm with %s (msgDigest: %s) failed "+ "to transmit: %+v", partner.ID, cmixMsg.Digest(), err) - storage.GetCriticalRawMessages().Failed(cmixMsg, partner.ID) - return errors.WithMessage(err, "Auth Confirm Failed to transmit") + return 0, errors.WithMessage(err, "Auth Confirm Failed to transmit") } jww.INFO.Printf("Confirm Request with %s (msgDigest: %s) sent on round %d", partner.ID, cmixMsg.Digest(), round) - /*check message delivery*/ - sendResults := make(chan ds.EventReturn, 1) - roundEvents := net.GetInstance().GetRoundEvents() - - roundEvents.AddRoundEventChan(round, sendResults, 1*time.Minute, - states.COMPLETED, states.FAILED) - - success, numFailed, _ := utility.TrackResults(sendResults, 1) - if !success { - if numFailed > 0 { - jww.INFO.Printf("Auth Confirm with %s (msgDigest: %s) failed "+ - "delivery due to round failure, will retry on reconnect", - partner.ID, cmixMsg.Digest()) - } else { - jww.INFO.Printf("Auth Confirm with %s (msgDigest: %s) failed "+ - "delivery due to timeout, will retry on reconnect", - partner.ID, cmixMsg.Digest()) - } - jww.ERROR.Printf("auth confirm failed to transmit, will be " + - "handled on reconnect") - storage.GetCriticalRawMessages().Failed(cmixMsg, partner.ID) - } else { - jww.INFO.Printf("Auth Confirm with %s (msgDigest: %s) delivered "+ - "sucesfully", partner.ID, cmixMsg.Digest()) - storage.GetCriticalRawMessages().Succeeded(cmixMsg, partner.ID) - } - - return nil + return round, nil } diff --git a/auth/request.go b/auth/request.go index 8e9c1c58e206bfb51ca952cbec66227497f593f7..c43707904f835b19d1e64ba53cb4ec9fe550355f 100644 --- a/auth/request.go +++ b/auth/request.go @@ -11,66 +11,60 @@ import ( "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/interfaces" - "gitlab.com/elixxir/client/interfaces/contact" "gitlab.com/elixxir/client/interfaces/params" - "gitlab.com/elixxir/client/interfaces/utility" "gitlab.com/elixxir/client/storage" "gitlab.com/elixxir/client/storage/auth" "gitlab.com/elixxir/client/storage/e2e" - ds "gitlab.com/elixxir/comms/network/dataStructures" + "gitlab.com/elixxir/crypto/contact" + "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/crypto/diffieHellman" cAuth "gitlab.com/elixxir/crypto/e2e/auth" "gitlab.com/elixxir/primitives/format" - "gitlab.com/elixxir/primitives/states" + "gitlab.com/xx_network/primitives/id" "io" "strings" - "time" ) const terminator = ";" func RequestAuth(partner, me contact.Contact, message string, rng io.Reader, - storage *storage.Session, net interfaces.NetworkManager) error { + storage *storage.Session, net interfaces.NetworkManager) (id.Round, error) { /*edge checks generation*/ - // check that messages can be sent over the network - if !net.GetHealthTracker().IsHealthy() { - return errors.New("Cannot create authenticated message " + - "when the network is not healthy") - } - // check that an authenticated channel does not already exists if _, err := storage.E2e().GetPartner(partner.ID); err == nil || !strings.Contains(err.Error(), e2e.NoPartnerErrorStr) { - return errors.Errorf("Authenticated channel already " + + return 0, errors.Errorf("Authenticated channel already " + "established with partner") } // check that the request is being sent from the proper ID if !me.ID.Cmp(storage.GetUser().ReceptionID) { - return errors.Errorf("Authenticated channel request " + + return 0, errors.Errorf("Authenticated channel request " + "can only be sent from user's identity") } // check that the message is properly formed if strings.Contains(message, terminator) { - return errors.Errorf("Message cannot contain '%s'", terminator) + return 0, errors.Errorf("Message cannot contain '%s'", terminator) } + //denote if this is a resend of an old request + resend := false + //lookup if an ongoing request is occurring - rqType, _, _, err := storage.Auth().GetRequest(partner.ID) - if err != nil && strings.Contains(err.Error(), auth.NoRequest) { - err = nil - } - if err != nil { + rqType, sr, _, err := storage.Auth().GetRequest(partner.ID) + + if err != nil && !strings.Contains(err.Error(), auth.NoRequest){ if rqType == auth.Receive { - return errors.WithMessage(err, - "Cannot send a request after "+ - "receiving a request") + return 0, errors.WithMessage(err, + "Cannot send a request after receiving a request") } else if rqType == auth.Sent { - return errors.WithMessage(err, - "Cannot send a request after "+ - "already sending one") + resend = true + }else{ + return 0, errors.WithMessage(err, + "Cannot send a request after receiving unknown error " + + "on requesting contact status") } } @@ -82,7 +76,7 @@ func RequestAuth(partner, me contact.Contact, message string, rng io.Reader, ecrFmt := newEcrFormat(baseFmt.GetEcrPayloadLen()) requestFmt, err := newRequestFormat(ecrFmt) if err != nil { - return errors.Errorf("failed to make request format: %+v", err) + return 0, errors.Errorf("failed to make request format: %+v", err) } //check the payload fits @@ -91,7 +85,7 @@ func RequestAuth(partner, me contact.Contact, message string, rng io.Reader, msgPayloadBytes := []byte(msgPayload) if len(msgPayloadBytes) > requestFmt.MsgPayloadLen() { - return errors.Errorf("Combined message longer than space "+ + return 0, errors.Errorf("Combined message longer than space "+ "available in payload; available: %v, length: %v", requestFmt.MsgPayloadLen(), len(msgPayloadBytes)) } @@ -101,17 +95,27 @@ func RequestAuth(partner, me contact.Contact, message string, rng io.Reader, salt := make([]byte, saltSize) _, err = rng.Read(salt) if err != nil { - return errors.Wrap(err, "Failed to generate salt") + return 0, errors.Wrap(err, "Failed to generate salt") + } + + var newPrivKey, newPubKey *cyclic.Int + + // in this case we have an ongoing request so we can resend the extant + // request + if resend{ + newPrivKey = sr.GetMyPrivKey() + newPubKey = sr.GetMyPubKey() + //in this case it is a new request and we must generate new keys + }else{ + //generate new keypair + newPrivKey = diffieHellman.GeneratePrivateKey(256, grp, rng) + newPubKey = diffieHellman.GeneratePublicKey(newPrivKey, grp) } //generate ownership proof ownership := cAuth.MakeOwnershipProof(storage.E2e().GetDHPrivateKey(), partner.DhPubKey, storage.E2e().GetGroup()) - //generate new keypair - newPrivKey := diffieHellman.GeneratePrivateKey(256, grp, rng) - newPubKey := diffieHellman.GeneratePublicKey(newPrivKey, grp) - jww.TRACE.Printf("RequestAuth MYPUBKEY: %v", newPubKey.Bytes()) jww.TRACE.Printf("RequestAuth THEIRPUBKEY: %v", partner.DhPubKey.Bytes()) @@ -136,56 +140,30 @@ func RequestAuth(partner, me contact.Contact, message string, rng io.Reader, /*store state*/ //fixme: channel is bricked if the first store succedes but the second fails //store the in progress auth - err = storage.Auth().AddSent(partner.ID, partner.DhPubKey, newPrivKey, - newPrivKey, confirmFp) - if err != nil { - return errors.Errorf("Failed to store auth request: %s", err) + if !resend{ + err = storage.Auth().AddSent(partner.ID, partner.DhPubKey, newPrivKey, + newPrivKey, confirmFp) + if err != nil { + return 0, errors.Errorf("Failed to store auth request: %s", err) + } } - //store the message as a critical message so it will always be sent - storage.GetCriticalRawMessages().AddProcessing(cmixMsg, partner.ID) - jww.INFO.Printf("Requesting Auth with %s, msgDigest: %s", partner.ID, cmixMsg.Digest()) /*send message*/ - round, _, err := net.SendCMIX(cmixMsg, partner.ID, params.GetDefaultCMIX()) + round, _, err := net.SendCMIX(cmixMsg, partner.ID, + params.GetDefaultCMIX()) if err != nil { - // if the send fails just set it to failed, it will but automatically - // retried - jww.INFO.Printf("Auth Request with %s (msgDigest: %s) failed "+ - "to transmit: %+v", partner.ID, cmixMsg.Digest(), err) - storage.GetCriticalRawMessages().Failed(cmixMsg, partner.ID) - return errors.WithMessage(err, "Auth Request Failed to transmit") + // if the send fails just set it to failed, it will + // but automatically retried + return 0, errors.WithMessagef(err, "Auth Request with %s " + + "(msgDigest: %s) failed to transmit: %+v", partner.ID, + cmixMsg.Digest(), err) } - jww.INFO.Printf("Auth Request with %s (msgDigest: %s) sent on round %d", - partner.ID, cmixMsg.Digest(), round) - - /*check message delivery*/ - sendResults := make(chan ds.EventReturn, 1) - roundEvents := net.GetInstance().GetRoundEvents() - - roundEvents.AddRoundEventChan(round, sendResults, 1*time.Minute, - states.COMPLETED, states.FAILED) - - success, numFailed, _ := utility.TrackResults(sendResults, 1) - if !success { - if numFailed > 0 { - jww.INFO.Printf("Auth Request with %s (msgDigest: %s) failed "+ - "delivery due to round failure, will retry on reconnect", - partner.ID, cmixMsg.Digest()) - } else { - jww.INFO.Printf("Auth Request with %s (msgDigest: %s) failed "+ - "delivery due to timeout, will retry on reconnect", - partner.ID, cmixMsg.Digest()) - } - storage.GetCriticalRawMessages().Failed(cmixMsg, partner.ID) - } else { - jww.INFO.Printf("Auth Request with %s (msgDigest: %s) delivered "+ - "sucesfully", partner.ID, cmixMsg.Digest()) - storage.GetCriticalRawMessages().Succeeded(cmixMsg, partner.ID) - } + jww.INFO.Printf("Auth Request with %s (msgDigest: %s) sent"+ + " on round %d", partner.ID, cmixMsg.Digest(), round) - return nil + return round, nil } diff --git a/auth/verify.go b/auth/verify.go index 76850a17dfc6728c10b5c7304e04d7f2437f2545..66a86df6f125bb0abe7c28be4ecbb408603b0a98 100644 --- a/auth/verify.go +++ b/auth/verify.go @@ -8,8 +8,8 @@ package auth import ( - "gitlab.com/elixxir/client/interfaces/contact" "gitlab.com/elixxir/client/storage" + "gitlab.com/elixxir/crypto/contact" cAuth "gitlab.com/elixxir/crypto/e2e/auth" ) diff --git a/bindings/authenticatedChannels.go b/bindings/authenticatedChannels.go index 70ff0285173740f5ef302e1a678ffe127318a002..30b12f0a1b3039fba5b18eafeff874cc7a438a60 100644 --- a/bindings/authenticatedChannels.go +++ b/bindings/authenticatedChannels.go @@ -10,7 +10,7 @@ package bindings import ( "errors" "fmt" - "gitlab.com/elixxir/client/interfaces/contact" + "gitlab.com/elixxir/crypto/contact" ) // Create an insecure e2e relationship with a precanned user @@ -27,19 +27,20 @@ func (c *Client) MakePrecannedAuthenticatedChannel(precannedID int) (*Contact, e // authenticated channel // It will not run if the network status is not healthy // An error will be returned if a channel already exists, if a request was -// already received, or if a request was already sent +// already received. // When a confirmation occurs, the channel will be created and the callback // will be called +// This can be called many times and retried. // // This function takes the marshaled send report to ensure a memory leak does // not occur as a result of both sides of the bindings holding a refrence to // the same pointer. func (c *Client) RequestAuthenticatedChannel(recipientMarshaled, - meMarshaled []byte, message string) error { + meMarshaled []byte, message string) (int, error) { recipent, err := contact.Unmarshal(recipientMarshaled) if err != nil { - return errors.New(fmt.Sprintf("Failed to "+ + return 0, errors.New(fmt.Sprintf("Failed to "+ "RequestAuthenticatedChannel: Failed to Unmarshal Recipent: "+ "%+v", err)) } @@ -47,11 +48,13 @@ func (c *Client) RequestAuthenticatedChannel(recipientMarshaled, me, err := contact.Unmarshal(meMarshaled) if err != nil { - return errors.New(fmt.Sprintf("Failed to "+ + return 0, errors.New(fmt.Sprintf("Failed to "+ "RequestAuthenticatedChannel: Failed to Unmarshal Me: %+v", err)) } - return c.api.RequestAuthenticatedChannel(recipent, me, message) + rid, err := c.api.RequestAuthenticatedChannel(recipent, me, message) + + return int(rid), err } // RegisterAuthCallbacks registers both callbacks for authenticated channels. @@ -79,19 +82,26 @@ func (c *Client) RegisterAuthCallbacks(request AuthRequestCallback, // received request and sends a message to the requestor that the request has // been confirmed // It will not run if the network status is not healthy -// An error will be returned if a channel already exists, if a request doest +// An error will be returned if a request doest // exist, or if the passed in contact does not exactly match the received -// request -func (c *Client) ConfirmAuthenticatedChannel(recipientMarshaled []byte) error { +// request. +// This can be called many times and retried. +// +// This function takes the marshaled send report to ensure a memory leak does +// not occur as a result of both sides of the bindings holding a refrence to +// the same pointer. +func (c *Client) ConfirmAuthenticatedChannel(recipientMarshaled []byte) (int, error) { recipent, err := contact.Unmarshal(recipientMarshaled) if err != nil { - return errors.New(fmt.Sprintf("Failed to "+ + return 0, errors.New(fmt.Sprintf("Failed to "+ "ConfirmAuthenticatedChannel: Failed to Unmarshal Recipient: "+ "%+v", err)) } - return c.api.ConfirmAuthenticatedChannel(recipent) + rid, err := c.api.ConfirmAuthenticatedChannel(recipent) + + return int(rid), err } // VerifyOwnership checks if the ownership proof on a passed contact matches the diff --git a/bindings/callback.go b/bindings/callback.go index 1237e7fcf981f763fcf8dcb3be233d37e48741fd..a14cb5151358933f2f0bd6af6cdb04156ff4ac37 100644 --- a/bindings/callback.go +++ b/bindings/callback.go @@ -31,12 +31,19 @@ type NetworkHealthCallback interface { Callback(bool) } -// RoundEventHandler handles round events happening on the cMix network. +// RoundEventCallback handles waiting on the exact state of a round on +// the cMix network. type RoundEventCallback interface { EventCallback(rid, state int, timedOut bool) } -// RoundEventHandler handles round events happening on the cMix network. +// RoundCompletionCallback is returned when the completion of a round is known. +type RoundCompletionCallback interface { + EventCallback(rid int, success, timedOut bool) +} + +// MessageDeliveryCallback gets called on the determination if all events +// related to a message send were successful. type MessageDeliveryCallback interface { EventCallback(msgID []byte, delivered, timedOut bool, roundResults []byte) } @@ -96,3 +103,17 @@ func newRoundListUnregister(rounds []id.Round, ec []*dataStructures.EventCallbac type ClientError interface { Report(source, message, trace string) } + + +type LogWriter interface{ + Log(string) +} + +type writerAdapter struct{ + lw LogWriter +} + +func (wa *writerAdapter)Write(p []byte) (n int, err error){ + wa.lw.Log(string(p)) + return len(p), nil +} diff --git a/bindings/client.go b/bindings/client.go index 04e2eba6e55645dfe1cd9f7fb7a14378dde5486d..b2c94fa95f46926ae891a8e9a41cb794cbdb28c8 100644 --- a/bindings/client.go +++ b/bindings/client.go @@ -13,15 +13,19 @@ import ( "fmt" jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/api" - "gitlab.com/elixxir/client/interfaces/contact" "gitlab.com/elixxir/client/interfaces/message" "gitlab.com/elixxir/client/interfaces/params" "gitlab.com/elixxir/comms/mixmessages" + "gitlab.com/elixxir/crypto/contact" "gitlab.com/elixxir/primitives/states" "gitlab.com/xx_network/primitives/id" + "sync" "time" ) +var extantClient bool +var loginMux sync.Mutex + // sets the log level func init() { jww.SetLogThreshold(jww.LevelInfo) @@ -75,6 +79,14 @@ func NewPrecannedClient(precannedID int, network, storageDir string, password [] // Login does not block on network connection, and instead loads and // starts subprocesses to perform network operations. func Login(storageDir string, password []byte, parameters string) (*Client, error) { + loginMux.Lock() + defer loginMux.Unlock() + + if extantClient { + return nil, errors.New("cannot login when another session " + + "already exists") + } + // check if a client is already logged in, refuse to login if one is p, err := params.GetNetworkParameters(parameters) if err != nil { return nil, errors.New(fmt.Sprintf("Failed to login: %+v", err)) @@ -84,7 +96,8 @@ func Login(storageDir string, password []byte, parameters string) (*Client, erro if err != nil { return nil, errors.New(fmt.Sprintf("Failed to login: %+v", err)) } - return &Client{*client}, nil + extantClient = true + return &Client{api: *client}, nil } // sets level of logging. All logs the set level and above will be displayed @@ -126,6 +139,11 @@ func LogLevel(level int) error { return nil } +//RegisterLogWriter registers a callback on which logs are written. +func RegisterLogWriter(writer LogWriter) { + jww.SetLogOutput(&writerAdapter{lw: writer}) +} + //Unmarshals a marshaled contact object, returns an error if it fails func UnmarshalContact(b []byte) (*Contact, error) { c, err := contact.Unmarshal(b) @@ -203,6 +221,20 @@ func (c *Client) StopNetworkFollower(timeoutMS int) error { return nil } +// WaitForNewtwork will block until either the network is healthy or the +// passed timeout. It will return true if the network is healthy +func (c *Client) WaitForNetwork(timeoutMS int) bool { + start := time.Now() + timeout := time.Duration(timeoutMS) * time.Millisecond + for time.Now().Sub(start) < timeout { + if c.api.GetHealth().IsHealthy() { + return true + } + time.Sleep(250 * time.Millisecond) + } + return false +} + // Gets the state of the network follower. Returns: // Stopped - 0 // Starting - 1000 @@ -301,18 +333,35 @@ func (c *Client) RegisterRoundEventsHandler(rid int, cb RoundEventCallback, return newRoundUnregister(roundID, ec, c.api.GetRoundEvents()) } -// RegisterMessageDeliveryCB allows the caller to get notified if the rounds a -// message was sent in successfully completed. Under the hood, this uses the same -// interface as RegisterRoundEventsHandler, but provides a convenient way to use -// the interface in its most common form, looking up the result of message -// retrieval +// WaitForRoundCompletion allows the caller to get notified if a round +// has completed (or failed). Under the hood, this uses an API which uses the internal +// round data, network historical round lookup, and waiting on network events +// to determine what has (or will) occur. +// +// The callbacks will return at timeoutMS if no state update occurs +func (c *Client) WaitForRoundCompletion(roundID int, + rec RoundCompletionCallback, timeoutMS int) error { + + f := func(allRoundsSucceeded, timedOut bool, rounds map[id.Round]api.RoundResult) { + rec.EventCallback(roundID, allRoundsSucceeded, timedOut) + } + + timeout := time.Duration(timeoutMS) * time.Millisecond + + return c.api.GetRoundResults([]id.Round{id.Round(roundID)}, timeout, f) +} + +// WaitForMessageDelivery allows the caller to get notified if the rounds a +// message was sent in successfully completed. Under the hood, this uses an API +// which uses the internal round data, network historical round lookup, and +// waiting on network events to determine what has (or will) occur. // // The callbacks will return at timeoutMS if no state update occurs // // This function takes the marshaled send report to ensure a memory leak does // not occur as a result of both sides of the bindings holding a reference to // the same pointer. -func (c *Client) WaitForRoundCompletion(marshaledSendReport []byte, +func (c *Client) WaitForMessageDelivery(marshaledSendReport []byte, mdc MessageDeliveryCallback, timeoutMS int) error { sr, err := UnmarshalSendReport(marshaledSendReport) @@ -346,11 +395,11 @@ func (c *Client) GetUser() *User { } // GetNodeRegistrationStatus returns a struct with the number of nodes the -// client is registered with and the number of in progress registrations. +// client is registered with and the number total. func (c *Client) GetNodeRegistrationStatus() (*NodeRegistrationsStatus, error) { - registered, inProgress, err := c.api.GetNodeRegistrationStatus() + registered, total, err := c.api.GetNodeRegistrationStatus() - return &NodeRegistrationsStatus{registered, inProgress}, err + return &NodeRegistrationsStatus{registered, total}, err } /* diff --git a/bindings/contact.go b/bindings/contact.go index daa45aa357095fa243c1a8b699198265e027a7f8..47a7a7290e4fec3684523d54312d359643fc3dbb 100644 --- a/bindings/contact.go +++ b/bindings/contact.go @@ -8,7 +8,7 @@ package bindings import ( - "gitlab.com/elixxir/client/interfaces/contact" + "gitlab.com/elixxir/crypto/contact" "gitlab.com/elixxir/primitives/fact" ) diff --git a/bindings/list.go b/bindings/list.go index 3fc31382636507aa32ec8423c1ac04d7a4c13092..c44fb1679fc0e6492c7c711e7d610bab01198c78 100644 --- a/bindings/list.go +++ b/bindings/list.go @@ -9,7 +9,7 @@ package bindings import ( "errors" - "gitlab.com/elixxir/client/interfaces/contact" + "gitlab.com/elixxir/crypto/contact" "gitlab.com/elixxir/primitives/fact" "gitlab.com/xx_network/primitives/id" ) @@ -99,8 +99,8 @@ func (fl *FactList) Num() int { return len(fl.c.Facts) } -func (fl *FactList) Get(i int) Fact { - return Fact{f: &(fl.c.Facts)[i]} +func (fl *FactList) Get(i int) *Fact { + return &Fact{f: &(fl.c.Facts)[i]} } func (fl *FactList) Add(factData string, factType int) error { diff --git a/bindings/message.go b/bindings/message.go index 978a62743dbd823062f1c4a961e20d74f386c496..efe899de839473e304a3d57d4bc149e8aba2df2f 100644 --- a/bindings/message.go +++ b/bindings/message.go @@ -37,7 +37,7 @@ func (m *Message) GetMessageType() int { // Returns the message's timestamp in ms func (m *Message) GetTimestampMS() int { - return int(m.r.Timestamp.Unix()) + return int(m.r.Timestamp.UnixNano()/1000000) } func (m *Message) GetTimestampNano() int { diff --git a/bindings/registrationStatus.go b/bindings/registrationStatus.go index 22446376436a0a8145c97e20e868073e1984d0a0..5d33cbd6e2031b39455363e096153afcf6c38833 100644 --- a/bindings/registrationStatus.go +++ b/bindings/registrationStatus.go @@ -11,7 +11,7 @@ package bindings // for bindings. type NodeRegistrationsStatus struct { registered int - inProgress int + total int } // GetRegistered returns the number of nodes registered with the client. @@ -19,7 +19,7 @@ func (nrs *NodeRegistrationsStatus) GetRegistered() int { return nrs.registered } -// GetInProgress return the number of nodes currently registering. -func (nrs *NodeRegistrationsStatus) GetInProgress() int { - return nrs.inProgress +// GetTotal return the total of nodes currently in the network. +func (nrs *NodeRegistrationsStatus) GetTotal() int { + return nrs.total } diff --git a/bindings/timeNow.go b/bindings/timeNow.go new file mode 100644 index 0000000000000000000000000000000000000000..dbeda1696669f98b9a489990ced0f66f51c9757b --- /dev/null +++ b/bindings/timeNow.go @@ -0,0 +1,24 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright © 2020 xx network SEZC // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file // +/////////////////////////////////////////////////////////////////////////////// + +package bindings + +import ( + "gitlab.com/xx_network/primitives/netTime" + "time" +) + +type TimeSource interface { + NowMs() int +} + +// SetTimeSource sets the network time to a custom source. +func SetTimeSource(timeNow TimeSource) { + netTime.Now = func() time.Time { + return time.Unix(0, int64(timeNow.NowMs()*int(time.Millisecond))) + } +} diff --git a/bindings/ud.go b/bindings/ud.go index a4c3cb5babca0236b546e5cb10fc74b10a98f0f3..91a700d3b5e94316418699396dccf2f68ab00d5a 100644 --- a/bindings/ud.go +++ b/bindings/ud.go @@ -9,9 +9,9 @@ package bindings import ( "github.com/pkg/errors" - "gitlab.com/elixxir/client/interfaces/contact" "gitlab.com/elixxir/client/single" "gitlab.com/elixxir/client/ud" + "gitlab.com/elixxir/crypto/contact" "gitlab.com/elixxir/primitives/fact" "gitlab.com/xx_network/primitives/id" "time" diff --git a/cmd/getndf.go b/cmd/getndf.go index e794fb4d38b6f3d7e0ca82b2b3a2576afef0d6d6..7ac150020c911d695f646993e3a409c18d6cb8da 100644 --- a/cmd/getndf.go +++ b/cmd/getndf.go @@ -13,16 +13,18 @@ import ( "github.com/spf13/cobra" jww "github.com/spf13/jwalterweatherman" "github.com/spf13/viper" - // "gitlab.com/elixxir/client/interfaces/contact" + // "gitlab.com/elixxir/crypto/contact" // "gitlab.com/elixxir/client/interfaces/message" // "gitlab.com/elixxir/client/switchboard" // "gitlab.com/elixxir/client/ud" // "gitlab.com/elixxir/primitives/fact" + "gitlab.com/elixxir/client/api" "gitlab.com/elixxir/comms/client" "gitlab.com/xx_network/comms/connect" //"time" pb "gitlab.com/elixxir/comms/mixmessages" "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/id/ephemeral" "gitlab.com/xx_network/primitives/utils" ) @@ -63,12 +65,14 @@ var getNDFCmd = &cobra.Command{ if gwHost != "" { host, _ := connect.NewHost(&id.TempGateway, gwHost, cert, params) + dummyID := ephemeral.ReservedIDs[0] pollMsg := &pb.GatewayPoll{ Partial: &pb.NDFHash{ Hash: nil, }, LastUpdate: uint64(0), - ReceptionID: id.DummyUser.Marshal(), + ReceptionID: dummyID[:], + ClientVersion: []byte(api.SEMVER), } resp, err := comms.SendPoll(host, pollMsg) if err != nil { diff --git a/cmd/init.go b/cmd/init.go index cf19521f066d1e9e878524a7ee75fd3471cf6b7c..b00f215475bfba0c513752b1d2fd01fd13cea5c8 100644 --- a/cmd/init.go +++ b/cmd/init.go @@ -11,6 +11,7 @@ package cmd import ( "fmt" "github.com/spf13/cobra" + "github.com/spf13/viper" jww "github.com/spf13/jwalterweatherman" ) @@ -29,5 +30,9 @@ var initCmd = &cobra.Command{ } func init() { + initCmd.Flags().StringP("userid-prefix", "", "", + "Desired prefix of userID to brute force when running init command. Prepend (?i) for case-insensitive. Only Base64 characters are valid.") + _ = viper.BindPFlag("userid-prefix", initCmd.Flags().Lookup("userid-prefix")) + rootCmd.AddCommand(initCmd) } diff --git a/cmd/root.go b/cmd/root.go index fb1efae75e8475ef671c9fbddd5b94bba61f0d9f..9ff887dad0dbb4d3d6e22a649f4ca43e5039a32e 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -17,10 +17,10 @@ import ( jww "github.com/spf13/jwalterweatherman" "github.com/spf13/viper" "gitlab.com/elixxir/client/api" - "gitlab.com/elixxir/client/interfaces/contact" "gitlab.com/elixxir/client/interfaces/message" "gitlab.com/elixxir/client/interfaces/params" "gitlab.com/elixxir/client/switchboard" + "gitlab.com/elixxir/crypto/contact" "gitlab.com/xx_network/primitives/id" "io/ioutil" "os" @@ -52,6 +52,24 @@ var rootCmd = &cobra.Command{ jww.INFO.Printf("User: %s", user.ReceptionID) writeContact(user.GetContact()) + // Get Recipient and/or set it to myself + isPrecanPartner := false + recipientContact := readContact() + recipientID := recipientContact.ID + + // Try to get recipientID from destid + if recipientID == nil { + recipientID, isPrecanPartner = parseRecipient( + viper.GetString("destid")) + } + + // Set it to myself + if recipientID == nil { + jww.INFO.Printf("sending message to self") + recipientID = user.ReceptionID + recipientContact = user.GetContact() + } + // Set up reception handler swboard := client.GetSwitchboard() recvCh := make(chan message.Receive, 10000) @@ -65,24 +83,25 @@ var rootCmd = &cobra.Command{ authMgr.AddGeneralRequestCallback(printChanRequest) // If unsafe channels, add auto-acceptor - num_channels_confirmed := 0 + authConfirmed := false authMgr.AddGeneralConfirmCallback(func( partner contact.Contact) { jww.INFO.Printf("Channel Confirmed: %s", partner.ID) - num_channels_confirmed++ + authConfirmed = recipientID.Cmp(partner.ID) }) if viper.GetBool("unsafe-channel-creation") { authMgr.AddGeneralRequestCallback(func( requestor contact.Contact, message string) { jww.INFO.Printf("Channel Request: %s", requestor.ID) - err := client.ConfirmAuthenticatedChannel( + _, err := client.ConfirmAuthenticatedChannel( requestor) if err != nil { jww.FATAL.Panicf("%+v", err) } - num_channels_confirmed++ + authConfirmed = recipientID.Cmp( + requestor.ID) }) } @@ -99,53 +118,67 @@ var rootCmd = &cobra.Command{ // After connection, make sure we have registered with at least // 85% of the nodes numReg := 1 - numNotReg := 100 - for numReg < 3*numNotReg { + total := 100 + for numReg < (total*3)/4 { time.Sleep(1 * time.Second) - numReg, numNotReg, err = client.GetNodeRegistrationStatus() + numReg, total, err = client.GetNodeRegistrationStatus() if err != nil { jww.FATAL.Panicf("%+v", err) } jww.INFO.Printf("Registering with nodes (%d/%d)...", - numReg, (numReg + numNotReg)) + numReg, total) } // Send Messages msgBody := viper.GetString("message") - isPrecanPartner := false - recipientContact := readContact() - recipientID := recipientContact.ID - - // Try to get recipientID from destid - if recipientID == nil { - recipientID, isPrecanPartner = parseRecipient( - viper.GetString("destid")) - } - - // Set it to myself - if recipientID == nil { - jww.INFO.Printf("sending message to self") - recipientID = user.ReceptionID - recipientContact = user.GetContact() - } - time.Sleep(10 * time.Second) // Accept auth request for this recipient if viper.GetBool("accept-channel") { acceptChannel(client, recipientID) + // Do not wait for channel confirmations if we + // accepted one + authConfirmed = true + } + + if client.HasAuthenticatedChannel(recipientID) { + jww.INFO.Printf("Authenticated channel already in "+ + "place for %s", recipientID) + authConfirmed = true } // Send unsafe messages or not? unsafe := viper.GetBool("unsafe") - assumeAuth := viper.GetBool("assume-auth-channel") - if !unsafe && !assumeAuth { + + sendAuthReq := viper.GetBool("send-auth-request") + if !unsafe && !authConfirmed && !isPrecanPartner && + sendAuthReq { addAuthenticatedChannel(client, recipientID, - recipientContact, isPrecanPartner) - // Do not wait for channel confirmations if we - // tried to add a channel - num_channels_confirmed++ + recipientContact) + } else if !unsafe && !authConfirmed && isPrecanPartner { + addPrecanAuthenticatedChannel(client, + recipientID, recipientContact) + authConfirmed = true + } + + if !unsafe && !authConfirmed { + jww.INFO.Printf("Waiting for authentication channel "+ + " confirmation with partner %s", recipientID) + scnt := uint(0) + waitSecs := viper.GetUint("auth-timeout") + for !authConfirmed && scnt < waitSecs { + time.Sleep(1 * time.Second) + scnt++ + } + if scnt == waitSecs { + jww.FATAL.Panicf("Could not confirm "+ + "authentication channel for %s, "+ + "waited %d seconds.", recipientID, + waitSecs) + } + jww.INFO.Printf("Authentication channel confirmation"+ + " took %d seconds", scnt) } msg := message.Send{ @@ -187,7 +220,6 @@ var rootCmd = &cobra.Command{ jww.FATAL.Panicf("%+v", err) } - jww.INFO.Printf("RoundIDs: %+v\n", roundIDs) time.Sleep(sendDelay * time.Millisecond) } @@ -197,9 +229,9 @@ var rootCmd = &cobra.Command{ receiveCnt := uint(0) waitSecs := viper.GetUint("waitTimeout") waitTimeout := time.Duration(waitSecs) - timeoutTimer := time.NewTimer(waitTimeout * time.Second) done := false for !done && expectedCnt != 0 { + timeoutTimer := time.NewTimer(waitTimeout * time.Second) select { case <-timeoutTimer.C: fmt.Println("Timed out!") @@ -217,13 +249,6 @@ var rootCmd = &cobra.Command{ } } fmt.Printf("Received %d\n", receiveCnt) - if receiveCnt == 0 && sendCnt == 0 { - scnt := uint(0) - for num_channels_confirmed == 0 && scnt < waitSecs { - time.Sleep(1 * time.Second) - scnt++ - } - } err = client.StopNetworkFollower(5 * time.Second) if err != nil { jww.WARN.Printf( @@ -281,7 +306,7 @@ func createClient() *api.Client { storeDir := viper.GetString("session") regCode := viper.GetString("regcode") precannedID := viper.GetUint("sendid") - + userIDprefix := viper.GetString("userid-prefix") //create a new client if none exist if _, err := os.Stat(storeDir); os.IsNotExist(err) { // Load NDF @@ -295,8 +320,14 @@ func createClient() *api.Client { err = api.NewPrecannedClient(precannedID, string(ndfJSON), storeDir, []byte(pass)) } else { - err = api.NewClient(string(ndfJSON), storeDir, + if userIDprefix != "" { + err = api.NewVanityClient(string(ndfJSON), storeDir, + []byte(pass), regCode, userIDprefix) + } else { + err = api.NewClient(string(ndfJSON), storeDir, []byte(pass), regCode) + } + } if err != nil { @@ -374,7 +405,7 @@ func acceptChannel(client *api.Client, recipientID *id.ID) { if err != nil { jww.FATAL.Panicf("%+v", err) } - err = client.ConfirmAuthenticatedChannel( + _, err = client.ConfirmAuthenticatedChannel( recipientContact) if err != nil { jww.FATAL.Panicf("%+v", err) @@ -391,14 +422,27 @@ func printChanRequest(requestor contact.Contact, message string) { //fmt.Printf(msg) } -func addAuthenticatedChannel(client *api.Client, recipientID *id.ID, - recipient contact.Contact, isPrecanPartner bool) { - if client.HasAuthenticatedChannel(recipientID) { - jww.INFO.Printf("Authenticated channel already in place for %s", - recipientID) - return +func addPrecanAuthenticatedChannel(client *api.Client, recipientID *id.ID, + recipient contact.Contact) { + jww.WARN.Printf("Precanned user id detected: %s", recipientID) + preUsr, err := client.MakePrecannedAuthenticatedChannel( + getPrecanID(recipientID)) + if err != nil { + jww.FATAL.Panicf("%+v", err) + } + // Sanity check, make sure user id's haven't changed + preBytes := preUsr.ID.Bytes() + idBytes := recipientID.Bytes() + for i := 0; i < len(preBytes); i++ { + if idBytes[i] != preBytes[i] { + jww.FATAL.Panicf("no id match: %v %v", + preBytes, idBytes) + } } +} +func addAuthenticatedChannel(client *api.Client, recipientID *id.ID, + recipient contact.Contact) { var allowed bool if viper.GetBool("unsafe-channel-creation") { msg := "unsafe channel creation enabled\n" @@ -419,28 +463,11 @@ func addAuthenticatedChannel(client *api.Client, recipientID *id.ID, recipientContact := recipient - if isPrecanPartner { - jww.WARN.Printf("Precanned user id detected: %s", - recipientID) - preUsr, err := client.MakePrecannedAuthenticatedChannel( - getPrecanID(recipientID)) - if err != nil { - jww.FATAL.Panicf("%+v", err) - } - // Sanity check, make sure user id's haven't changed - preBytes := preUsr.ID.Bytes() - idBytes := recipientID.Bytes() - for i := 0; i < len(preBytes); i++ { - if idBytes[i] != preBytes[i] { - jww.FATAL.Panicf("no id match: %v %v", - preBytes, idBytes) - } - } - } else if recipientContact.ID != nil && recipientContact.DhPubKey != nil { + if recipientContact.ID != nil && recipientContact.DhPubKey != nil { me := client.GetUser().GetContact() jww.INFO.Printf("Requesting auth channel from: %s", recipientID) - err := client.RequestAuthenticatedChannel(recipientContact, + _, err := client.RequestAuthenticatedChannel(recipientContact, me, msg) if err != nil { jww.FATAL.Panicf("%+v", err) @@ -708,16 +735,22 @@ func init() { viper.BindPFlag("unsafe-channel-creation", rootCmd.Flags().Lookup("unsafe-channel-creation")) - rootCmd.Flags().BoolP("assume-auth-channel", "", false, - "Do not check for an authentication channel for this user") - viper.BindPFlag("assume-auth-channel", - rootCmd.Flags().Lookup("assume-auth-channel")) - rootCmd.Flags().BoolP("accept-channel", "", false, "Accept the channel request for the corresponding recipient ID") viper.BindPFlag("accept-channel", rootCmd.Flags().Lookup("accept-channel")) + rootCmd.Flags().BoolP("send-auth-request", "", false, + "Send an auth request to the specified destination and wait"+ + "for confirmation") + viper.BindPFlag("send-auth-request", + rootCmd.Flags().Lookup("send-auth-request")) + rootCmd.Flags().UintP("auth-timeout", "", 120, + "The number of seconds to wait for an authentication channel"+ + "to confirm") + viper.BindPFlag("auth-timeout", + rootCmd.Flags().Lookup("auth-timeout")) + rootCmd.Flags().BoolP("forceHistoricalRounds", "", false, "Force all rounds to be sent to historical round retrieval") viper.BindPFlag("forceHistoricalRounds", diff --git a/cmd/single.go b/cmd/single.go index cf2b07f78cdc6cbcd64181d84f4bc63dd53a4f67..15f803b11bec0f775845fdfdfb9f8292c75ea2a7 100644 --- a/cmd/single.go +++ b/cmd/single.go @@ -14,10 +14,10 @@ import ( "github.com/spf13/cobra" jww "github.com/spf13/jwalterweatherman" "github.com/spf13/viper" - "gitlab.com/elixxir/client/interfaces/contact" "gitlab.com/elixxir/client/interfaces/message" "gitlab.com/elixxir/client/single" "gitlab.com/elixxir/client/switchboard" + "gitlab.com/elixxir/crypto/contact" "gitlab.com/xx_network/primitives/utils" "time" ) @@ -55,7 +55,7 @@ var singleCmd = &cobra.Command{ authMgr.AddGeneralRequestCallback(func( requester contact.Contact, message string) { jww.INFO.Printf("Got request: %s", requester.ID) - err := client.ConfirmAuthenticatedChannel(requester) + _, err := client.ConfirmAuthenticatedChannel(requester) if err != nil { jww.FATAL.Panicf("%+v", err) } @@ -75,12 +75,15 @@ var singleCmd = &cobra.Command{ // Make single-use manager and start receiving process singleMng := single.NewManager(client) + // Get the tag + tag := viper.GetString("tag") + // Register the callback callbackChan := make(chan responseCallbackChan) callback := func(payload []byte, c single.Contact) { callbackChan <- responseCallbackChan{payload, c} } - singleMng.RegisterCallback("tag", callback) + singleMng.RegisterCallback(tag, callback) client.AddService(singleMng.StartProcesses) timeout := viper.GetDuration("timeout") @@ -92,7 +95,7 @@ var singleCmd = &cobra.Command{ partner := readSingleUseContact("contact") maxMessages := uint8(viper.GetUint("maxMessages")) - sendSingleUse(singleMng, partner, payload, maxMessages, timeout) + sendSingleUse(singleMng, partner, payload, maxMessages, timeout, tag) } // If the reply flag is set, then start waiting for a message and reply @@ -117,6 +120,10 @@ func init() { "Path to contact file to send message to.") _ = viper.BindPFlag("contact", singleCmd.Flags().Lookup("contact")) + singleCmd.Flags().StringP("tag", "", "testTag", + "The tag that specifies the callback to trigger on reception.") + _ = viper.BindPFlag("tag", singleCmd.Flags().Lookup("tag")) + singleCmd.Flags().Uint8("maxMessages", 1, "The max number of single-use response messages.") _ = viper.BindPFlag("maxMessages", singleCmd.Flags().Lookup("maxMessages")) @@ -130,7 +137,7 @@ func init() { // sendSingleUse sends a single use message. func sendSingleUse(m *single.Manager, partner contact.Contact, payload []byte, - maxMessages uint8, timeout time.Duration) { + maxMessages uint8, timeout time.Duration, tag string) { // Construct callback callbackChan := make(chan struct { payload []byte @@ -151,7 +158,7 @@ func sendSingleUse(m *single.Manager, partner contact.Contact, payload []byte, // Send single-use message fmt.Printf("Sending single-use transmission message: %s\n", payload) jww.DEBUG.Printf("Sending single-use transmission to %s: %s", partner.ID, payload) - err := m.TransmitSingleUse(partner, payload, "tag", maxMessages, callback, timeout) + err := m.TransmitSingleUse(partner, payload, tag, maxMessages, callback, timeout) if err != nil { jww.FATAL.Panicf("Failed to transmit single-use message: %+v", err) } diff --git a/cmd/ud.go b/cmd/ud.go index fb9603dd52b18eb096bd3699c87b398dbcc8a7a5..38cbecb2cd1c6572cd140b158f435fe4291500cd 100644 --- a/cmd/ud.go +++ b/cmd/ud.go @@ -13,11 +13,11 @@ import ( "github.com/spf13/cobra" jww "github.com/spf13/jwalterweatherman" "github.com/spf13/viper" - "gitlab.com/elixxir/client/interfaces/contact" "gitlab.com/elixxir/client/interfaces/message" "gitlab.com/elixxir/client/single" "gitlab.com/elixxir/client/switchboard" "gitlab.com/elixxir/client/ud" + "gitlab.com/elixxir/crypto/contact" "gitlab.com/elixxir/primitives/fact" "time" ) @@ -55,7 +55,7 @@ var udCmd = &cobra.Command{ authMgr.AddGeneralRequestCallback(func( requester contact.Contact, message string) { jww.INFO.Printf("Got Request: %s", requester.ID) - err := client.ConfirmAuthenticatedChannel(requester) + _, err := client.ConfirmAuthenticatedChannel(requester) if err != nil { jww.FATAL.Panicf("%+v", err) } diff --git a/cmd/version.go b/cmd/version.go index 99af5a4c68449110c4b9281285596caf305b2e78..2a7eca16517f8e7f3d5c547ea35dbc472d4607c5 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 = "2.0.0" +const currentVersion = "2.3.0" func Version() string { out := fmt.Sprintf("Elixxir Client v%s -- %s\n\n", api.SEMVER, diff --git a/go.mod b/go.mod index cbd7c3d26f28e77fded7b281126283cacffa2857..c0ce181a7926d457116daa6b0a14bef1801bed98 100644 --- a/go.mod +++ b/go.mod @@ -17,19 +17,18 @@ 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.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.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 + gitlab.com/elixxir/comms v0.0.4-0.20210413160356-853e51fc18e5 + gitlab.com/elixxir/crypto v0.0.7-0.20210412231025-6f75c577f803 + gitlab.com/elixxir/ekv v0.1.5 + gitlab.com/elixxir/primitives v0.0.3-0.20210409190923-7bf3cd8d97e7 + gitlab.com/xx_network/comms v0.0.4-0.20210409202820-eb3dca6571d3 + gitlab.com/xx_network/crypto v0.0.5-0.20210405224157-2b1f387b42c1 + gitlab.com/xx_network/primitives v0.0.4-0.20210402222416-37c1c4d3fac4 + golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 + golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57 // 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 + google.golang.org/protobuf v1.26.0-rc.1 gopkg.in/ini.v1 v1.62.0 // indirect ) diff --git a/go.sum b/go.sum index 15bdda0ba26fa5f23d7aa3c5993d95b458cf8a7d..2c9ea3fd15a1237eb861a5d9eda5b25d0d4a42db 100644 --- a/go.sum +++ b/go.sum @@ -84,10 +84,8 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -144,6 +142,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/liyue201/goqr v0.0.0-20200803022322-df443203d4ea h1:uyJ13zfy6l79CM3HnVhDalIyZ4RJAyVfDrbnfFeJoC4= +github.com/liyue201/goqr v0.0.0-20200803022322-df443203d4ea/go.mod h1:w4pGU9PkiX2hAWyF0yuHEHmYTQFAd6WHzp6+IY7JVjE= github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.4 h1:8KGKTcQQGm0Kv7vEbKFErAoAOFyyacLStRtQSeYtvkY= @@ -201,6 +201,8 @@ github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0= +github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v1.0.1 h1:voD4ITNjPL5jjBfgR/r8fPIIBrliWrWHeiJApdr3r4w= github.com/smartystreets/assertions v1.0.1/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= @@ -243,52 +245,56 @@ github.com/zeebo/assert v1.1.0 h1:hU1L1vLTHsnO8x8c9KAR5GmM5QscxHg5RNU5z5qbUWY= github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= github.com/zeebo/blake3 v0.0.4 h1:vtZ4X8B2lKXZFg2Xyg6Wo36mvmnJvc2VQYTtA4RDCkI= github.com/zeebo/blake3 v0.0.4/go.mod h1:YOZo8A49yNqM0X/Y+JmDUZshJWLt1laHsNSn5ny2i34= -github.com/zeebo/blake3 v0.1.0 h1:sP3n5SxSbzU8x4Svc4ZcQv7SmQOqCkiKBeAZWP+hePo= -github.com/zeebo/blake3 v0.1.0/go.mod h1:YOZo8A49yNqM0X/Y+JmDUZshJWLt1laHsNSn5ny2i34= +github.com/zeebo/blake3 v0.1.1 h1:Nbsts7DdKThRHHd+YNlqiGlRqGEF2bE2eXN+xQ1hsEs= +github.com/zeebo/blake3 v0.1.1/go.mod h1:G9pM4qQwjRzF1/v7+vabMj/c5mWpGZ2Wzo3Eb4z0pb4= github.com/zeebo/pcg v0.0.0-20181207190024-3cdc6b625a05 h1:4pW5fMvVkrgkMXdvIsVRRTs69DWYA8uNNQsu1stfVKU= github.com/zeebo/pcg v0.0.0-20181207190024-3cdc6b625a05/go.mod h1:Gr+78ptB0MwXxm//LBaEvBiaXY7hXJ6KGe2V32X2F6E= 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.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/comms v0.0.4-0.20210409192302-249b5af3dbc8 h1:k9BLWNw7CHwH4H3gNWA0Q/BXNg7923AFflWJtYZr5z4= +gitlab.com/elixxir/comms v0.0.4-0.20210409192302-249b5af3dbc8/go.mod h1:/y5QIivolXMa6TO+ZqFWAV49wxlXXxUCqZH9Zi82kXU= +gitlab.com/elixxir/comms v0.0.4-0.20210413160356-853e51fc18e5 h1:Q/+lhZpIDQdIKy9aXNCLkCk8AavFE7HAuaila0sv5mw= +gitlab.com/elixxir/comms v0.0.4-0.20210413160356-853e51fc18e5/go.mod h1:0XsJ63n7knUeSX9BDKQG7xGtX6w0l5WsfplSsMbP9iM= 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.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/crypto v0.0.7-0.20210409192145-eab67f2f8931 h1:kY/qBfjrZTFHJnvM1IcxB03+ZQL4+ESUjV4I4kCxoE8= +gitlab.com/elixxir/crypto v0.0.7-0.20210409192145-eab67f2f8931/go.mod h1:ZktO3MT3oNo+g2Nq0GuC3ebJWJphh7t5KwwDDGBegnY= +gitlab.com/elixxir/crypto v0.0.7-0.20210412193049-f3718fa4facb h1:9CT5f+nV4sisutLx8Z3BAEiqjktcCL2ZpEqcpmgzyqA= +gitlab.com/elixxir/crypto v0.0.7-0.20210412193049-f3718fa4facb/go.mod h1:ZktO3MT3oNo+g2Nq0GuC3ebJWJphh7t5KwwDDGBegnY= +gitlab.com/elixxir/crypto v0.0.7-0.20210412195114-be927031747a h1:DSYIXSCWrwkyHUs2fJMliI4+Bd9h+WA5PXI78uvhCj4= +gitlab.com/elixxir/crypto v0.0.7-0.20210412195114-be927031747a/go.mod h1:HMMRBuv/yMqB5c31G9OPlOAifOOqGypCyD5v6py+4vo= +gitlab.com/elixxir/crypto v0.0.7-0.20210412231025-6f75c577f803 h1:8sLODlAYRT0Y9NA+uoMoF1qBrBRrW5TikyKAOvyCd+E= +gitlab.com/elixxir/crypto v0.0.7-0.20210412231025-6f75c577f803/go.mod h1:HMMRBuv/yMqB5c31G9OPlOAifOOqGypCyD5v6py+4vo= +gitlab.com/elixxir/ekv v0.1.5 h1:R8M1PA5zRU1HVnTyrtwybdABh7gUJSCvt1JZwUSeTzk= +gitlab.com/elixxir/ekv v0.1.5/go.mod h1:e6WPUt97taFZe5PFLPb1Dupk7tqmDCTQu1kkstqJvw4= gitlab.com/elixxir/primitives v0.0.0-20200731184040-494269b53b4d/go.mod h1:OQgUZq7SjnE0b+8+iIAT2eqQF+2IFHn73tOo+aV11mg= gitlab.com/elixxir/primitives v0.0.0-20200804170709-a1896d262cd9/go.mod h1:p0VelQda72OzoUckr1O+vPW0AiFe0nyKQ6gYcmFSuF8= 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.20210309193003-ef42ebb4800b h1:TswWfqiZqsdPLeWsfe7VJHMlV01W792kRHGYfYwb2Lk= -gitlab.com/elixxir/primitives v0.0.3-0.20210309193003-ef42ebb4800b/go.mod h1:/e3a4KPqmA9V22qKSZ9prfYYNzIzvLI8xh7noVV091w= +gitlab.com/elixxir/primitives v0.0.3-0.20210409190923-7bf3cd8d97e7 h1:q3cw7WVtD6hDqTi8ydky+yiqJ4RkWp/hkTSNirr9Z6Y= +gitlab.com/elixxir/primitives v0.0.3-0.20210409190923-7bf3cd8d97e7/go.mod h1:h0QHrjrixLNaP24ZXAgDOZXP4eegrQ24BCZPGitg8Jg= gitlab.com/xx_network/comms v0.0.0-20200805174823-841427dd5023/go.mod h1:owEcxTRl7gsoM8c3RQ5KAm5GstxrJp5tn+6JfQ4z5Hw= -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/comms v0.0.4-0.20210406210737-45d1e87d294a h1:r0mvBjHPBCYEVmhEe6JhLQDc0+dCORf1ejtuZ8IbyKY= +gitlab.com/xx_network/comms v0.0.4-0.20210406210737-45d1e87d294a/go.mod h1:7ciuA+LTE0GC7upviGbyyb2hrpJG9Pnq2cc5oz2N5Ss= +gitlab.com/xx_network/comms v0.0.4-0.20210409202820-eb3dca6571d3 h1:0o9kveRSEQ9ykRh/hd+z9Iq53YNvFArW1RQ6ICdAG5g= +gitlab.com/xx_network/comms v0.0.4-0.20210409202820-eb3dca6571d3/go.mod h1:7ciuA+LTE0GC7upviGbyyb2hrpJG9Pnq2cc5oz2N5Ss= 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.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/crypto v0.0.5-0.20210405224157-2b1f387b42c1 h1:4Hrphjtqn3vO8LI872YwVKy5dCFJdD5u0dE4O2QCZqU= +gitlab.com/xx_network/crypto v0.0.5-0.20210405224157-2b1f387b42c1/go.mod h1:CUhRpioyLaKIylg+LIyZX1rhOmFaEXQQ6esNycx9dcA= 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.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/primitives v0.0.4-0.20210402222416-37c1c4d3fac4 h1:YPYTKF0zQf08y0eQrjQP01C/EWQTypdqawjZPr5c6rc= +gitlab.com/xx_network/primitives v0.0.4-0.20210402222416-37c1c4d3fac4/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= @@ -314,6 +320,8 @@ golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a h1:vclmkQCjlDX5OydZ9wv8rB golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -347,8 +355,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201029221708-28c70e62bb1d/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201224014010-6772e930b67b h1:iFwSg7t5GZmB/Q5TjiEAsdoLDrdJRC1RiF2WhuV29Qw= -golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -376,10 +384,12 @@ golang.org/x/sys v0.0.0-20200519105757-fe76b779f299 h1:DYfZAGf2WMFjMxbgTjaC+2HC7 golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200917073148-efd3b9a0ff20/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201029080932-201ba4db2418/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201014080544-cc95f250f6bc/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210105210732-16f7687f5001 h1:/dSxr6gT0FNI1MO5WLJo8mTmItROeOKTkDn+7OwWBos= -golang.org/x/sys v0.0.0-20210105210732-16f7687f5001/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210319071255-635bc2c9138d h1:jbzgAvDZn8aEnytae+4ou0J0GwFZoHR0hOrTg4qH8GA= +golang.org/x/sys v0.0.0-20210319071255-635bc2c9138d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57 h1:F5Gozwx4I1xtr/sr/8CFbb57iKi3297KFs0QDbGN60A= +golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -431,7 +441,6 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98 google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20201030142918-24207fddd1c3/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210105202744-fe13368bc0e1 h1:Zk6zlGXdtYdcY5TL+VrbTfmifvk3VvsXopCpszsHPBA= google.golang.org/genproto v0.0.0-20210105202744-fe13368bc0e1/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -446,8 +455,8 @@ google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyz google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1 h1:7QnIQpGRHE5RnLKnESfDoxm2dTapTZua5a0kS0A+VXQ= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/interfaces/auth.go b/interfaces/auth.go index 68e18be6fc51bb90a67b082f396582bb79b88625..bb3cae74d0a37f0fda2c34e8ce0623af6f8a789f 100644 --- a/interfaces/auth.go +++ b/interfaces/auth.go @@ -8,7 +8,7 @@ package interfaces import ( - "gitlab.com/elixxir/client/interfaces/contact" + "gitlab.com/elixxir/crypto/contact" "gitlab.com/xx_network/primitives/id" ) diff --git a/interfaces/contact/contact.go b/interfaces/contact/contact.go deleted file mode 100644 index 498500b039a72da3ba9336e2815d34706bf86dbd..0000000000000000000000000000000000000000 --- a/interfaces/contact/contact.go +++ /dev/null @@ -1,160 +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 contact - -import ( - "bytes" - "crypto" - "encoding/base64" - "encoding/binary" - "github.com/pkg/errors" - "gitlab.com/elixxir/crypto/cyclic" - "gitlab.com/elixxir/primitives/fact" - "gitlab.com/xx_network/primitives/id" -) - -const sizeByteLength = 2 -const fingerprintLength = 15 - -// Contact implements the Contact interface defined in interface/contact.go, -// in go, the structure is meant to be edited directly, the functions are for -// bindings compatibility -type Contact struct { - ID *id.ID - DhPubKey *cyclic.Int - OwnershipProof []byte - Facts fact.FactList -} - -// Marshal saves the Contact in a compact byte slice. The byte slice has -// the following structure (not to scale). -// -// +----------+----------------+---------+----------+----------+----------------+----------+ -// | DhPubKey | OwnershipProof | Facts | ID | | | | -// | size | size | size | | DhPubKey | OwnershipProof | FactList | -// | 2 bytes | 2 bytes | 2 bytes | 33 bytes | | | | -// +----------+----------------+---------+----------+----------+----------------+----------+ -func (c Contact) Marshal() []byte { - var buff bytes.Buffer - b := make([]byte, sizeByteLength) - - // Write size of DhPubKey - var dhPubKey []byte - if c.DhPubKey != nil { - dhPubKey = c.DhPubKey.BinaryEncode() - binary.PutVarint(b, int64(len(dhPubKey))) - } - buff.Write(b) - - // Write size of OwnershipProof - binary.PutVarint(b, int64(len(c.OwnershipProof))) - buff.Write(b) - - // Write length of Facts - factList := c.Facts.Stringify() - binary.PutVarint(b, int64(len(factList))) - buff.Write(b) - - // Write ID - if c.ID != nil { - buff.Write(c.ID.Marshal()) - } else { - // Handle nil ID - buff.Write(make([]byte, id.ArrIDLen)) - } - - // Write DhPubKey - buff.Write(dhPubKey) - - // Write OwnershipProof - buff.Write(c.OwnershipProof) - - // Write fact list - buff.Write([]byte(factList)) - - return buff.Bytes() -} - -// Unmarshal decodes the byte slice produced by Contact.Marshal into a Contact. -func Unmarshal(b []byte) (Contact, error) { - if len(b) < sizeByteLength*3+id.ArrIDLen { - return Contact{}, errors.Errorf("Length of provided buffer (%d) too "+ - "short; length must be at least %d.", - len(b), sizeByteLength*3+id.ArrIDLen) - } - - c := Contact{DhPubKey: &cyclic.Int{}} - var err error - buff := bytes.NewBuffer(b) - - // Get size of each field - dhPubKeySize, _ := binary.Varint(buff.Next(sizeByteLength)) - ownershipProofSize, _ := binary.Varint(buff.Next(sizeByteLength)) - factsSize, _ := binary.Varint(buff.Next(sizeByteLength)) - - // Get and unmarshal ID - c.ID, err = id.Unmarshal(buff.Next(id.ArrIDLen)) - if err != nil { - return Contact{}, errors.Errorf("Failed to unmarshal Contact ID: %+v", err) - } - - // Handle nil ID - if bytes.Equal(c.ID.Marshal(), make([]byte, id.ArrIDLen)) { - c.ID = nil - } - - // Get and decode DhPubKey - if dhPubKeySize == 0 { - // Handle nil key - c.DhPubKey = nil - } else { - if err = c.DhPubKey.BinaryDecode(buff.Next(int(dhPubKeySize))); err != nil { - return Contact{}, errors.Errorf("Failed to binary decode Contact DhPubKey: %+v", err) - } - } - - // Get OwnershipProof - if ownershipProofSize == 0 { - // Handle nil OwnershipProof - c.OwnershipProof = nil - } else { - c.OwnershipProof = buff.Next(int(ownershipProofSize)) - } - - // Get and unstringify fact list - c.Facts, _, err = fact.UnstringifyFactList(string(buff.Next(int(factsSize)))) - if err != nil { - return Contact{}, errors.Errorf("Failed to unstringify Contact fact list: %+v", err) - } - - return c, nil -} - -// GetFingerprint creates a 15 character long fingerprint of the contact off of -// the ID and DH public key. -func (c Contact) GetFingerprint() string { - // Generate hash - sha := crypto.SHA256 - h := sha.New() - - // Hash ID and DH public key - h.Write(c.ID.Bytes()) - h.Write(c.DhPubKey.Bytes()) - data := h.Sum(nil) - - // Base64 encode hash and truncate it - return base64.StdEncoding.EncodeToString(data)[:fingerprintLength] -} - -// Equal determines if the two contacts have the same values. -func Equal(a, b Contact) bool { - return a.ID.Cmp(b.ID) && - a.DhPubKey.Cmp(b.DhPubKey) == 0 && - bytes.Equal(a.OwnershipProof, b.OwnershipProof) && - a.Facts.Stringify() == b.Facts.Stringify() -} diff --git a/interfaces/contact/contact_test.go b/interfaces/contact/contact_test.go deleted file mode 100644 index 2d43f1818986c26f81ad5f389dce028e88ec10cd..0000000000000000000000000000000000000000 --- a/interfaces/contact/contact_test.go +++ /dev/null @@ -1,232 +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 contact - -import ( - "crypto" - "encoding/base64" - "encoding/json" - "gitlab.com/elixxir/crypto/cyclic" - "gitlab.com/elixxir/primitives/fact" - "gitlab.com/xx_network/crypto/csprng" - "gitlab.com/xx_network/crypto/large" - "gitlab.com/xx_network/primitives/id" - "math/rand" - "reflect" - "strings" - "testing" -) - -// Tests marshaling and unmarshalling of a common Contact. -func TestContact_Marshal_Unmarshal(t *testing.T) { - expectedContact := Contact{ - ID: id.NewIdFromUInt(rand.Uint64(), id.User, t), - DhPubKey: getCycInt(256), - Facts: fact.FactList{ - {Fact: "myUsername", T: fact.Username}, - {Fact: "devinputvalidation@elixxir.io", T: fact.Email}, - {Fact: "6502530000US", T: fact.Phone}, - {Fact: "6502530001US", T: fact.Phone}, - }, - } - - buff := expectedContact.Marshal() - - testContact, err := Unmarshal(buff) - if err != nil { - t.Errorf("Unmarshal() produced an error: %+v", err) - } - - if !reflect.DeepEqual(expectedContact, testContact) { - t.Errorf("Unmarshaled Contact does not match expected."+ - "\nexpected: %#v\nreceived: %#v", expectedContact, testContact) - } -} - -// Tests marshaling and unmarshalling of a Contact with nil fields. -func TestContact_Marshal_Unmarshal_Nil(t *testing.T) { - expectedContact := Contact{} - - buff := expectedContact.Marshal() - - testContact, err := Unmarshal(buff) - if err != nil { - t.Errorf("Unmarshal() produced an error: %+v", err) - } - - if !reflect.DeepEqual(expectedContact, testContact) { - t.Errorf("Unmarshaled Contact does not match expected."+ - "\nexpected: %#v\nreceived: %#v", expectedContact, testContact) - } -} - -// Tests the size of marshaling and JSON marshaling of a Contact with a large -// amount of data. -func TestContact_Marshal_Size(t *testing.T) { - expectedContact := Contact{ - ID: id.NewIdFromUInt(rand.Uint64(), id.User, t), - DhPubKey: getCycInt(512), - OwnershipProof: make([]byte, 1024), - Facts: fact.FactList{ - {Fact: "myVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongUsername", T: fact.Username}, - {Fact: "myVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongEmail@elixxir.io", T: fact.Email}, - {Fact: "6502530000US", T: fact.Phone}, - }, - } - rand.Read(expectedContact.OwnershipProof) - - buff := expectedContact.Marshal() - - marshalBuff, err := json.Marshal(expectedContact) - if err != nil { - t.Errorf("Marshal() produced an error: %+v", err) - } - - t.Logf("size of buff: %d", len(buff)) - t.Logf("size of marshalBuff: %d", len(marshalBuff)) - t.Logf("ratio: %.2f%%", float32(len(buff))/float32(len(marshalBuff))*100) - t.Logf("%s", marshalBuff) - - if len(marshalBuff) < len(buff) { - t.Errorf("JSON Contact smaller than marshaled contact."+ - "\nJSON: %d\nmarshal: %d", len(marshalBuff), len(buff)) - } -} - -// Unit test of GetFingerprint. -func TestContact_GetFingerprint(t *testing.T) { - c := Contact{ - ID: id.NewIdFromString("Samwise", id.User, t), - DhPubKey: getCycInt(512), - } - - testFP := c.GetFingerprint() - if len(testFP) != fingerprintLength { - t.Errorf("GetFingerprint() returned fingerprint with unexpected length."+ - "\nexpected length: %d\nreceived length: %d", - fingerprintLength, len(testFP)) - } - - // Generate expected fingerprint - h := crypto.SHA256.New() - h.Write(c.ID.Bytes()) - h.Write(c.DhPubKey.Bytes()) - expectedFP := base64.StdEncoding.EncodeToString(h.Sum(nil))[:fingerprintLength] - - if strings.Compare(expectedFP, testFP) != 0 { - t.Errorf("GetFingerprint() returned expected fingerprint."+ - "\nexpected: %s\nreceived: %s", expectedFP, testFP) - } - -} - -// Consistency test for changes in underlying dependencies. -func TestContact_GetFingerprint_Consistency(t *testing.T) { - expected := []string{ - "rBUw1n4jtH4uEYq", "Z/Jm1OUwDaql5cd", "+vHLzY+yH96zAiy", - "cZm5Iz78ViOIlnh", "9LqrcbFEIV4C4LX", "ll4eykGpMWYlxw+", - "6YQshWJhdPL6ajx", "Y6gTPVEzow4IHOm", "6f/rT2vWxDC9tdt", - "rwqbDT+PoeA6Iww", "YN4IFijP/GZ172O", "ScbHVQc2T9SXQ2m", - "50mfbCXQ+LIqiZn", "cyRYdMKXByiFdtC", "7g6ujy7iIbJVl4F", - } - - for i := range expected { - c := Contact{ - ID: id.NewIdFromUInt(uint64(i), id.User, t), - DhPubKey: getGroup().NewInt(25), - } - - fp := c.GetFingerprint() - if expected[i] != fp { - t.Errorf("GetFingerprint() did not output the expected fingerprint (%d)."+ - "\nexpected: %s\nreceived: %s", i, expected[i], fp) - } - } -} - -// Happy path. -func TestEqual(t *testing.T) { - a := Contact{ - ID: id.NewIdFromUInt(rand.Uint64(), id.User, t), - DhPubKey: getCycInt(512), - OwnershipProof: make([]byte, 1024), - Facts: fact.FactList{ - {Fact: "myUsername", T: fact.Username}, - {Fact: "devinputvalidation@elixxir.io", T: fact.Email}, - }, - } - rand.Read(a.OwnershipProof) - b := Contact{ - ID: a.ID, - DhPubKey: a.DhPubKey, - OwnershipProof: a.OwnershipProof, - Facts: a.Facts, - } - c := Contact{ - ID: id.NewIdFromUInt(rand.Uint64(), id.User, t), - DhPubKey: getCycInt(512), - OwnershipProof: make([]byte, 1024), - } - - if !Equal(a, b) { - t.Errorf("Equal reported two equal contacts as different."+ - "\na: %+v\nb: +%v", a, b) - } - - if Equal(a, c) { - t.Errorf("Equal reported two unequal contacts as the same."+ - "\na: %+v\nc: +%v", a, c) - } -} - -func getCycInt(size int) *cyclic.Int { - var primeString = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E0" + - "88A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F" + - "14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDE" + - "E386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48" + - "361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED52907709" + - "6966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E8603" + - "9B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D22" + - "61898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458" + - "DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619" + - "DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE1" + - "17577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A" + - "92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150B" + - "DA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B" + - "2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127" + - "D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199FFFFFFFFFFFFF" + - "FFF" - - buff, err := csprng.GenerateInGroup([]byte(primeString), size, csprng.NewSystemRNG()) - if err != nil { - panic(err) - } - - grp := cyclic.NewGroup(large.NewIntFromString(primeString, 16), - large.NewInt(2)).NewIntFromBytes(buff) - - return grp -} - -func getGroup() *cyclic.Group { - return cyclic.NewGroup( - large.NewIntFromString("E2EE983D031DC1DB6F1A7A67DF0E9A8E5561DB8E8D4941"+ - "3394C049B7A8ACCEDC298708F121951D9CF920EC5D146727AA4AE535B0922C688"+ - "B55B3DD2AEDF6C01C94764DAB937935AA83BE36E67760713AB44A6337C20E7861"+ - "575E745D31F8B9E9AD8412118C62A3E2E29DF46B0864D0C951C394A5CBBDC6ADC"+ - "718DD2A3E041023DBB5AB23EBB4742DE9C1687B5B34FA48C3521632C4A530E8FF"+ - "B1BC51DADDF453B0B2717C2BC6669ED76B4BDD5C9FF558E88F26E5785302BEDBC"+ - "A23EAC5ACE92096EE8A60642FB61E8F3D24990B8CB12EE448EEF78E184C7242DD"+ - "161C7738F32BF29A841698978825B4111B4BC3E1E198455095958333D776D8B2B"+ - "EEED3A1A1A221A6E37E664A64B83981C46FFDDC1A45E3D5211AAF8BFBC072768C"+ - "4F50D7D7803D2D4F278DE8014A47323631D7E064DE81C0C6BFA43EF0E6998860F"+ - "1390B5D3FEACAF1696015CB79C3F9C2D93D961120CD0E5F12CBB687EAB045241F"+ - "96789C38E89D796138E6319BE62E35D87B1048CA28BE389B575E994DCA7554715"+ - "84A09EC723742DC35873847AEF49F66E43873", 16), - large.NewIntFromString("2", 16)) -} diff --git a/interfaces/params/network.go b/interfaces/params/network.go index b73efc7a3ee56c5d2f24d18643194a22852dbc92..b84c38a09310f13d13a5cd74d4ddfb83c62fc717 100644 --- a/interfaces/params/network.go +++ b/interfaces/params/network.go @@ -23,6 +23,8 @@ type Network struct { NetworkHealthTimeout time.Duration //Number of parallel node registration the client is capable of ParallelNodeRegistrations uint + //How far back in rounds the network should actually check + KnownRoundsThreshold uint Rounds Messages @@ -39,6 +41,7 @@ func GetDefaultNetwork() Network { NetworkHealthTimeout: 30 * time.Second, E2EParams: GetDefaultE2ESessionParams(), ParallelNodeRegistrations: 8, + KnownRoundsThreshold: 1500, //5 rounds/sec * 60 sec/min * 5 min } n.Rounds = GetDefaultRounds() n.Messages = GetDefaultMessage() diff --git a/interfaces/params/rounds.go b/interfaces/params/rounds.go index dbf0d5a00fdbb07ad813244f75f84eda34ddcd57..87fa53fc04517b8262ffbc8be624b3989dddeb91 100644 --- a/interfaces/params/rounds.go +++ b/interfaces/params/rounds.go @@ -12,9 +12,6 @@ import ( ) type Rounds struct { - // Maximum number of times to attempt to retrieve a round from a gateway - // before giving up on it - MaxAttemptsCheckingARound uint // Number of historical rounds required to automatically send a historical // rounds query MaxHistoricalRounds uint @@ -31,11 +28,13 @@ type Rounds struct { // Toggles if historical rounds should always be used ForceHistoricalRounds bool + + // Maximum number of times a historical round lookup will be attempted + MaxHistoricalRoundsRetries uint } func GetDefaultRounds() Rounds { return Rounds{ - MaxAttemptsCheckingARound: 5, MaxHistoricalRounds: 100, HistoricalRoundsPeriod: 100 * time.Millisecond, NumMessageRetrievalWorkers: 8, @@ -43,5 +42,6 @@ func GetDefaultRounds() Rounds { HistoricalRoundsBufferLen: 1000, LookupRoundsBufferLen: 2000, ForceHistoricalRounds: false, + MaxHistoricalRoundsRetries: 3, } } diff --git a/interfaces/user/user.go b/interfaces/user/user.go index 1aaea8a31d67d0dd1facb50cbb7170a0055abf92..7d480700e0e1c048b4ac9fcd98edb6fb25112b51 100644 --- a/interfaces/user/user.go +++ b/interfaces/user/user.go @@ -8,7 +8,7 @@ package user import ( - "gitlab.com/elixxir/client/interfaces/contact" + "gitlab.com/elixxir/crypto/contact" "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/primitives/fact" "gitlab.com/xx_network/crypto/signature/rsa" diff --git a/keyExchange/confirm.go b/keyExchange/confirm.go index ce31c0c6fa933b3fccd203bf6b0bfdbd968818c5..01c43c5d42dd602fb314815d993b20ab7d16e401 100644 --- a/keyExchange/confirm.go +++ b/keyExchange/confirm.go @@ -18,10 +18,11 @@ import ( ) func startConfirm(sess *storage.Session, c chan message.Receive, - stop *stoppable.Single) { + stop *stoppable.Single, cleanup func()) { for true { select { case <-stop.Quit(): + cleanup() return case confirmation := <-c: handleConfirm(sess, confirmation) diff --git a/keyExchange/confirm_test.go b/keyExchange/confirm_test.go index b2e619c684c0985ded4887178113ade1d489af1d..8cef6f6f60488568614208f751914332ca5267f9 100644 --- a/keyExchange/confirm_test.go +++ b/keyExchange/confirm_test.go @@ -13,8 +13,8 @@ import ( "gitlab.com/elixxir/client/interfaces/params" "gitlab.com/elixxir/client/storage/e2e" "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/netTime" "testing" - "time" ) // Smoke test for handleTrigger @@ -57,7 +57,7 @@ func TestHandleConfirm(t *testing.T) { Payload: rekey, MessageType: message.KeyExchangeConfirm, Sender: bobID, - Timestamp: time.Now(), + Timestamp: netTime.Now(), Encryption: message.E2E, } diff --git a/keyExchange/exchange.go b/keyExchange/exchange.go index caf7c7a596762c95ea9da22e1cb5825dc80d566f..d94e8800f60d440c3c0c8b41564c04f4ada32ba7 100644 --- a/keyExchange/exchange.go +++ b/keyExchange/exchange.go @@ -15,7 +15,6 @@ import ( "gitlab.com/elixxir/client/storage" "gitlab.com/elixxir/client/switchboard" "gitlab.com/xx_network/primitives/id" - "time" ) const keyExchangeTriggerName = "KeyExchangeTrigger" @@ -32,14 +31,13 @@ func Start(switchboard *switchboard.Switchboard, sess *storage.Session, net inte // create the trigger stoppable triggerStop := stoppable.NewSingle(keyExchangeTriggerName) - triggerStopCleanup := stoppable.NewCleanup(triggerStop, - func(duration time.Duration) error { - switchboard.Unregister(triggerID) - return nil - }) + + cleanupTrigger := func(){ + switchboard.Unregister(triggerID) + } // start the trigger thread - go startTrigger(sess, net, triggerCh, triggerStop.Quit(), params) + go startTrigger(sess, net, triggerCh, triggerStop, params, cleanupTrigger) //register the rekey confirm thread confirmCh := make(chan message.Receive, 100) @@ -48,18 +46,16 @@ func Start(switchboard *switchboard.Switchboard, sess *storage.Session, net inte // register the confirm stoppable confirmStop := stoppable.NewSingle(keyExchangeConfirmName) - confirmStopCleanup := stoppable.NewCleanup(confirmStop, - func(duration time.Duration) error { - switchboard.Unregister(confirmID) - return nil - }) + cleanupConfirm := func(){ + switchboard.Unregister(confirmID) + } // start the confirm thread - go startConfirm(sess, confirmCh, confirmStop) + go startConfirm(sess, confirmCh, confirmStop, cleanupConfirm) //bundle the stoppables and return exchangeStop := stoppable.NewMulti(keyExchangeMulti) - exchangeStop.Add(triggerStopCleanup) - exchangeStop.Add(confirmStopCleanup) + exchangeStop.Add(triggerStop) + exchangeStop.Add(confirmStop) return exchangeStop } diff --git a/keyExchange/exchange_test.go b/keyExchange/exchange_test.go index 2c1729995c28d528c19ffe88a92ae425d2b57e0d..4fd98b3e650a191d6facf40d0e1321bfdc84a031 100644 --- a/keyExchange/exchange_test.go +++ b/keyExchange/exchange_test.go @@ -19,6 +19,7 @@ import ( dh "gitlab.com/elixxir/crypto/diffieHellman" "gitlab.com/xx_network/crypto/csprng" "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/netTime" "testing" "time" ) @@ -74,7 +75,7 @@ func TestFullExchange(t *testing.T) { Payload: rekeyTrigger, MessageType: message.KeyExchangeTrigger, Sender: exchangeBobId, - Timestamp: time.Now(), + Timestamp: netTime.Now(), Encryption: message.E2E, } diff --git a/keyExchange/trigger.go b/keyExchange/trigger.go index 544cde8eee82c1979568f639cc0d454f6d205d06..a72da7b110c92e0065a5f9acaf79698565f8815c 100644 --- a/keyExchange/trigger.go +++ b/keyExchange/trigger.go @@ -16,6 +16,7 @@ import ( "gitlab.com/elixxir/client/interfaces/message" "gitlab.com/elixxir/client/interfaces/params" "gitlab.com/elixxir/client/interfaces/utility" + "gitlab.com/elixxir/client/stoppable" "gitlab.com/elixxir/client/storage" "gitlab.com/elixxir/client/storage/e2e" ds "gitlab.com/elixxir/comms/network/dataStructures" @@ -26,20 +27,23 @@ import ( const ( errBadTrigger = "non-e2e trigger from partner %s" errUnknown = "unknown trigger from partner %s" + errFailed = "Failed to handle rekey trigger: %s" ) func startTrigger(sess *storage.Session, net interfaces.NetworkManager, - c chan message.Receive, quitCh <-chan struct{}, params params.Rekey) { + c chan message.Receive, stop *stoppable.Single, params params.Rekey, cleanup func()) { for true { select { - case <-quitCh: + case <-stop.Quit(): + cleanup() return case request := <-c: - err := handleTrigger(sess, net, request, params) - if err != nil { - jww.ERROR.Printf("Failed to handle rekey trigger: %s", - err) - } + go func() { + err := handleTrigger(sess, net, request, params) + if err != nil { + jww.ERROR.Printf(errFailed, err) + } + }() } } } diff --git a/keyExchange/trigger_test.go b/keyExchange/trigger_test.go index c69e09562bd10bbe998855c33f3c765b7f0ed085..430bba91a0ba734541b03a61260493caa03237e0 100644 --- a/keyExchange/trigger_test.go +++ b/keyExchange/trigger_test.go @@ -14,6 +14,7 @@ import ( dh "gitlab.com/elixxir/crypto/diffieHellman" "gitlab.com/xx_network/crypto/csprng" "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/netTime" "google.golang.org/protobuf/proto" "testing" "time" @@ -54,7 +55,7 @@ func TestHandleTrigger(t *testing.T) { Payload: rekey, MessageType: message.NoType, Sender: bobID, - Timestamp: time.Now(), + Timestamp: netTime.Now(), Encryption: message.E2E, } diff --git a/keyExchange/utils_test.go b/keyExchange/utils_test.go index 162db4728cec9ddfa0b91d0f0ae3acc6e0c7c522..a1447b990744f92b063420888ea1c96e1d9fb5dd 100644 --- a/keyExchange/utils_test.go +++ b/keyExchange/utils_test.go @@ -8,9 +8,6 @@ package keyExchange import ( - "testing" - "time" - "github.com/golang/protobuf/proto" jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/interfaces" @@ -31,6 +28,8 @@ import ( "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/id/ephemeral" "gitlab.com/xx_network/primitives/ndf" + "gitlab.com/xx_network/primitives/netTime" + "testing" ) // Generate partner ID for two people, used for smoke tests @@ -170,7 +169,7 @@ func (t *testNetworkManagerFullExchange) SendE2E(m message.Send, p params.E2E) ( Payload: payload, MessageType: message.KeyExchangeConfirm, Sender: exchangeAliceId, - Timestamp: time.Now(), + Timestamp: netTime.Now(), Encryption: message.E2E, } diff --git a/network/checkedRounds.go b/network/checkedRounds.go new file mode 100644 index 0000000000000000000000000000000000000000..8ffa9ba39804fd70017123859cf60137f12f8e78 --- /dev/null +++ b/network/checkedRounds.go @@ -0,0 +1,75 @@ +package network + +import ( + "container/list" + "crypto/md5" + "gitlab.com/elixxir/client/storage/reception" + "gitlab.com/xx_network/primitives/id" +) + + +type idFingerprint [16]byte + +type checkedRounds struct{ + lookup map[idFingerprint]*checklist +} + +type checklist struct{ + m map[id.Round]interface{} + l *list.List +} + +func newCheckedRounds()*checkedRounds{ + return &checkedRounds{ + lookup: make(map[idFingerprint]*checklist), + } +} + +func (cr *checkedRounds)Check(identity reception.IdentityUse, rid id.Round)bool{ + idFp := getIdFingerprint(identity) + cl, exists := cr.lookup[idFp] + if !exists{ + cl = &checklist{ + m: make(map[id.Round]interface{}), + l: list.New().Init(), + } + cr.lookup[idFp]=cl + } + + if _, exists := cl.m[rid]; !exists{ + cl.m[rid] = nil + cl.l.PushBack(rid) + return true + } + return false +} + +func (cr *checkedRounds)Prune(identity reception.IdentityUse, earliestAllowed id.Round){ + idFp := getIdFingerprint(identity) + cl, exists := cr.lookup[idFp] + if !exists { + return + } + + e := cl.l.Front() + for e!=nil { + if e.Value.(id.Round)<earliestAllowed{ + delete(cl.m,e.Value.(id.Round)) + lastE := e + e = e.Next() + cl.l.Remove(lastE) + }else{ + break + } + } +} + +func getIdFingerprint(identity reception.IdentityUse)idFingerprint{ + h := md5.New() + h.Write(identity.EphId[:]) + h.Write(identity.Source[:]) + + fp := idFingerprint{} + copy(fp[:], h.Sum(nil)) + return fp +} \ No newline at end of file diff --git a/network/ephemeral/tracker.go b/network/ephemeral/tracker.go index f158e337521ffddb5bcd6267e69e0e048e89f9de..2f19604c49faea57cb58b5cf7caf3476af4d9eab 100644 --- a/network/ephemeral/tracker.go +++ b/network/ephemeral/tracker.go @@ -16,6 +16,7 @@ import ( "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/id/ephemeral" + "gitlab.com/xx_network/primitives/netTime" "time" ) @@ -59,7 +60,7 @@ func track(session *storage.Session, ourId *id.ID, stop *stoppable.Single) { receptionStore.WaitForIdSizeUpdate() for true { - now := time.Now() + now := netTime.Now() // Generates the IDs since the last track protoIds, err := ephemeral.GetIdsByRange(ourId, receptionStore.GetIDSize(), now, now.Sub(lastCheck)) @@ -148,7 +149,7 @@ func checkTimestampStore(session *storage.Session) error { if _, err := session.Get(TimestampKey); err != nil { // only generate from the last hour because this is a new id, it // couldn't receive messages yet - now, err := marshalTimestamp(time.Now().Add(-1 * time.Hour)) + now, err := marshalTimestamp(netTime.Now().Add(-1 * time.Hour)) if err != nil { return errors.Errorf("Could not marshal new timestamp for storage: %v", err) } @@ -161,7 +162,7 @@ func checkTimestampStore(session *storage.Session) error { // Takes the stored timestamp and unmarshal into a time object func unmarshalTimestamp(lastTimestampObj *versioned.Object) (time.Time, error) { if lastTimestampObj == nil || lastTimestampObj.Data == nil { - return time.Now(), nil + return netTime.Now(), nil } lastTimestamp := time.Time{} @@ -175,7 +176,7 @@ func marshalTimestamp(timeToStore time.Time) (*versioned.Object, error) { return &versioned.Object{ Version: 0, - Timestamp: time.Now(), + Timestamp: netTime.Now(), Data: data, }, err } diff --git a/network/ephemeral/tracker_test.go b/network/ephemeral/tracker_test.go index 1d01511f5b03be3b08a2084b92548cae62f84ff7..aa4589ebe7650ab55d4d04ab97fb98cfb9d1c008 100644 --- a/network/ephemeral/tracker_test.go +++ b/network/ephemeral/tracker_test.go @@ -17,6 +17,7 @@ import ( "gitlab.com/xx_network/comms/signature" "gitlab.com/xx_network/crypto/signature/rsa" "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/netTime" "gitlab.com/xx_network/primitives/utils" "testing" "time" @@ -31,7 +32,7 @@ func TestCheck(t *testing.T) { } /// Store a mock initial timestamp the store - now := time.Now() + now := netTime.Now() twoDaysAgo := now.Add(-2 * 24 * time.Hour) twoDaysTimestamp, err := marshalTimestamp(twoDaysAgo) if err != nil { @@ -65,7 +66,7 @@ func TestCheck_Thread(t *testing.T) { stop := stoppable.NewSingle(ephemeralStoppable) /// Store a mock initial timestamp the store - now := time.Now() + now := netTime.Now() yesterday := now.Add(-24 * time.Hour) yesterdayTimestamp, err := marshalTimestamp(yesterday) if err != nil { diff --git a/network/follow.go b/network/follow.go index 7ac859229780c4c80396eb28b0e18d4352e2bf48..752476ea1e7b821d942ca88d3b36dba19d87c5a0 100644 --- a/network/follow.go +++ b/network/follow.go @@ -41,7 +41,6 @@ import ( ) const debugTrackPeriod = 1 * time.Minute -const maxChecked = 100000 //comms interface makes testing easier type followNetworkComms interface { @@ -187,7 +186,15 @@ func (m *manager) follow(report interfaces.ClientErrorReport, rng csprng.Source, // FIXME: without mutating the RoundInfo. Signature also needs verified // FIXME: before keys are deleted update.State = uint32(states.FAILED) - m.Instance.GetRoundEvents().TriggerRoundEvent(update) + rnd, err := m.Instance.GetWrappedRound(id.Round(update.ID)) + if err != nil { + jww.ERROR.Printf("Failed to report client error: " + + "Could not get round for event triggering: " + + "Unable to get round %d from instance: %+v", + id.Round(update.ID), err) + break + } + m.Instance.GetRoundEvents().TriggerRoundEvent(rnd) // delete all existing keys and trigger a re-registration with the relevant Node m.Session.Cmix().Remove(nid) @@ -238,28 +245,53 @@ func (m *manager) follow(report interfaces.ClientErrorReport, rng csprng.Source, // are messages waiting in rounds and then sends signals to the appropriate // handling threads roundChecker := func(rid id.Round) bool { - return m.round.Checker(rid, filterList, identity) + return rounds.Checker(rid, filterList) } // move the earliest unknown round tracker forward to the earliest // tracked round if it is behind earliestTrackedRound := id.Round(pollResp.EarliestRound) - updated := identity.UR.Set(earliestTrackedRound) - + updated, _ := identity.ER.Set(earliestTrackedRound) // loop through all rounds the client does not know about and the gateway // does, checking the bloom filter for the user to see if there are // messages for the user (bloom not implemented yet) - earliestRemaining := gwRoundsState.RangeUnchecked(updated, - maxChecked, roundChecker) - identity.UR.Set(earliestRemaining) - jww.INFO.Printf("Earliest Remaining: %d", earliestRemaining) + //threshold is the earliest round that will not be excluded from earliest remaining + earliestRemaining, roundsWithMessages, roundsUnknown := gwRoundsState.RangeUnchecked(updated, + m.param.KnownRoundsThreshold, roundChecker) + _, changed := identity.ER.Set(earliestRemaining) + if changed{ + jww.TRACE.Printf("External returns of RangeUnchecked: %d, %v, %v", earliestRemaining, roundsWithMessages, roundsUnknown) + jww.DEBUG.Printf("New Earliest Remaining: %d", earliestRemaining) + } + roundsWithMessages2 := identity.UR.Iterate(func(rid id.Round)bool{ + if gwRoundsState.Checked(rid){ + return rounds.Checker(rid, filterList) + } + return false + }, roundsUnknown) - //delete any old rounds from processing - if earliestRemaining>updated{ - for i:=updated;i<=earliestRemaining;i++{ - m.round.DeleteProcessingRoundDelete(i, identity.EphId, identity.Source) + for _, rid := range roundsWithMessages{ + if m.checked.Check(identity, rid){ + m.round.GetMessagesFromRound(rid, identity) } } + for _, rid := range roundsWithMessages2{ + m.round.GetMessagesFromRound(rid, identity) + } + + earliestToKeep := getEarliestToKeep(m.param.KnownRoundsThreshold, + gwRoundsState.GetLastChecked()) + + m.checked.Prune(identity, earliestToKeep) + +} + + +func getEarliestToKeep(delta uint, lastchecked id.Round)id.Round{ + if uint(lastchecked)<delta{ + return 0 + } + return lastchecked - id.Round(delta) } diff --git a/network/health/tracker.go b/network/health/tracker.go index 8e9837165a33982f6dcf7387e7c42388b4c276bd..ff53904f2015fe81af4938efd9ca8222fd68eba1 100644 --- a/network/health/tracker.go +++ b/network/health/tracker.go @@ -103,7 +103,6 @@ func (t *Tracker) setHealth(h bool) { func (t *Tracker) Start() (stoppable.Stoppable, error) { t.mux.Lock() - defer t.mux.Unlock() if t.running { return nil, errors.New("cannot start Health tracker threads, " + "they are already running") @@ -111,20 +110,13 @@ func (t *Tracker) Start() (stoppable.Stoppable, error) { t.running = true t.isHealthy = false + t.mux.Unlock() stop := stoppable.NewSingle("Health Tracker") - stopCleanup := stoppable.NewCleanup(stop, func(duration time.Duration) error { - t.mux.Lock() - defer t.mux.Unlock() - t.isHealthy = false - t.transmit(false) - t.running = false - return nil - }) go t.start(stop.Quit()) - return stopCleanup, nil + return stop, nil } // Long-running thread used to monitor and report on network health @@ -135,7 +127,11 @@ func (t *Tracker) start(quitCh <-chan struct{}) { var heartbeat network.Heartbeat select { case <-quitCh: - // Handle thread kill + t.mux.Lock() + t.isHealthy = false + t.running = false + t.mux.Unlock() + t.transmit(false) break case heartbeat = <-t.heartbeat: if healthy(heartbeat) { @@ -163,7 +159,7 @@ func (t *Tracker) transmit(health bool) { select { case c <- health: default: - jww.WARN.Printf("Unable to send Health event") + jww.DEBUG.Printf("Unable to send Health event") } } diff --git a/network/manager.go b/network/manager.go index 9cdb4bb33a063cc53168dbae553e81e506b8c7c7..b62bb1d007953db87ea63c010f4090c081c9e4b7 100644 --- a/network/manager.go +++ b/network/manager.go @@ -11,10 +11,6 @@ package network // and intraclient state are accessible through the context object. import ( - "sync/atomic" - - "time" - "github.com/pkg/errors" "gitlab.com/elixxir/client/interfaces" "gitlab.com/elixxir/client/interfaces/params" @@ -46,11 +42,12 @@ type manager struct { //sub-managers round *rounds.Manager message *message.Manager - //atomic denotes if the network is running - running *uint32 //map of polls for debugging tracker *pollTracker + + //tracks already checked rounds + checked *checkedRounds } // NewManager builds a new reception manager object using inputted key fields @@ -59,14 +56,12 @@ func NewManager(session *storage.Session, switchboard *switchboard.Switchboard, params params.Network, ndf *ndf.NetworkDefinition) (interfaces.NetworkManager, error) { //start network instance - instance, err := network.NewInstance(comms.ProtoComms, ndf, nil, nil) + instance, err := network.NewInstance(comms.ProtoComms, ndf, nil, nil, network.None) if err != nil { return nil, errors.WithMessage(err, "failed to create"+ " client network manager") } - running := uint32(0) - // Note: These are not loaded/stored in E2E Store, but the // E2E Session Params are a part of the network parameters, so we // set them here when they are needed on startup @@ -74,9 +69,9 @@ func NewManager(session *storage.Session, switchboard *switchboard.Switchboard, //create manager object m := manager{ - param: params, - running: &running, - tracker: newPollTracker(), + param: params, + tracker: newPollTracker(), + checked: newCheckedRounds(), } m.Internal = internal.Internal{ @@ -113,10 +108,6 @@ func NewManager(session *storage.Session, switchboard *switchboard.Switchboard, // - Critical Messages (/network/message/critical.go) // - Ephemeral ID tracking (network/ephemeral/tracker.go) func (m *manager) Follow(report interfaces.ClientErrorReport) (stoppable.Stoppable, error) { - if !atomic.CompareAndSwapUint32(m.running, 0, 1) { - return nil, errors.Errorf("network routines are already running") - } - multi := stoppable.NewMulti("networkManager") // health tracker @@ -145,15 +136,7 @@ func (m *manager) Follow(report interfaces.ClientErrorReport) (stoppable.Stoppab multi.Add(ephemeral.Track(m.Session, m.ReceptionID)) - //set the running status back to 0 so it can be started again - closer := stoppable.NewCleanup(multi, func(time.Duration) error { - if !atomic.CompareAndSwapUint32(m.running, 1, 0) { - return errors.Errorf("network routines are already stopped") - } - return nil - }) - - return closer, nil + return multi, nil } // GetHealthTracker returns the health tracker diff --git a/network/message/garbled.go b/network/message/garbled.go index 70bab27f42eab90b759494ce2912d3d13a864660..d9e1ac6be427f2ca0e9c8e89572fb6eed2285483 100644 --- a/network/message/garbled.go +++ b/network/message/garbled.go @@ -27,6 +27,8 @@ func (m *Manager) CheckGarbledMessages() { select { case m.triggerGarbled <- struct{}{}: default: + jww.WARN.Println("Failed to check garbled messages " + + "due to full channel") } } diff --git a/network/message/garbled_test.go b/network/message/garbled_test.go index 21098b72bef9a6408c6131c275c021471e79565d..0f5c3a074641af02ef3e156372bd7957eedba5aa 100644 --- a/network/message/garbled_test.go +++ b/network/message/garbled_test.go @@ -12,6 +12,7 @@ import ( "gitlab.com/elixxir/crypto/fastRNG" "gitlab.com/elixxir/primitives/format" "gitlab.com/xx_network/crypto/csprng" + "gitlab.com/xx_network/primitives/netTime" "math/rand" "testing" "time" @@ -102,7 +103,7 @@ func TestManager_CheckGarbledMessages(t *testing.T) { fmp.NumParts[0] = uint8(1) binary.BigEndian.PutUint16(fmp.Len, 256) fmp.Part[0] = 0 - ts, err := time.Now().MarshalBinary() + ts, err := netTime.Now().MarshalBinary() if err != nil { t.Errorf("failed to martial ts: %+v", err) } diff --git a/network/message/handler.go b/network/message/handler.go index 95606c8a7a204afe27d67903af41e511a2b102a1..88484e6fb98672520bf3e39af0cd3175597b53b4 100644 --- a/network/message/handler.go +++ b/network/message/handler.go @@ -37,6 +37,7 @@ func (m *Manager) handleMessages(quitCh <-chan struct{}) { func (m *Manager) handleMessage(ecrMsg format.Message, identity reception.IdentityUse) { // We've done all the networking, now process the message fingerprint := ecrMsg.GetKeyFP() + msgDigest := ecrMsg.Digest() e2eKv := m.Session.E2e() @@ -113,7 +114,7 @@ func (m *Manager) handleMessage(ecrMsg format.Message, identity reception.Identi } jww.INFO.Printf("Received message of type %s from %s,"+ - " msgDigest: %s", encTy, sender, ecrMsg.Digest()) + " msgDigest: %s", encTy, sender, msgDigest) // Process the decrypted/unencrypted message partition, to see if // we get a full message diff --git a/network/message/manager.go b/network/message/manager.go index ca4a1c0f40bbc57e54925b0c742063df59f34218..807ccc07066cf2281e557b6e07d09dd4180d3c15 100644 --- a/network/message/manager.go +++ b/network/message/manager.go @@ -36,7 +36,7 @@ func NewManager(internal internal.Internal, param params.Messages, partitioner: parse.NewPartitioner(dummyMessage.ContentsSize(), internal.Session), messageReception: make(chan Bundle, param.MessageReceptionBuffLen), networkIsHealthy: make(chan bool, 1), - triggerGarbled: make(chan struct{}, 1), + triggerGarbled: make(chan struct{}, 100), nodeRegistration: nodeRegistration, } m.Internal = internal diff --git a/network/message/parse/partition_test.go b/network/message/parse/partition_test.go index 59963cfefc57ab70d8d76e07fd384d8aae293a40..933db1a01d4e95605d44d7cf5f5dce4429f2a9b5 100644 --- a/network/message/parse/partition_test.go +++ b/network/message/parse/partition_test.go @@ -11,8 +11,8 @@ import ( "gitlab.com/elixxir/client/interfaces/message" "gitlab.com/elixxir/client/storage" "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/netTime" "testing" - "time" ) var ipsumTestStr = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras sit amet euismod est. Donec dolor " + @@ -67,7 +67,7 @@ func TestPartitioner_Partition(t *testing.T) { p := NewPartitioner(len(ipsumTestStr), storeSession) _, _, err := p.Partition(&id.DummyUser, message.Text, - time.Now(), []byte(ipsumTestStr)) + netTime.Now(), []byte(ipsumTestStr)) if err != nil { t.Error(err) } @@ -94,7 +94,7 @@ func TestPartitioner_HandleFirstPartition(t *testing.T) { storeSession := storage.InitTestingSession(t) p := NewPartitioner(len(ipsumTestStr), storeSession) - m := newFirstMessagePart(message.Text, 1107, 1, time.Now(), []byte(ipsumTestStr)) + m := newFirstMessagePart(message.Text, 1107, 1, netTime.Now(), []byte(ipsumTestStr)) _, _ = p.HandlePartition( &id.DummyUser, diff --git a/network/message/sendCmix.go b/network/message/sendCmix.go index 2a5892da077268b3ca9b5881e037fad7842480e3..1aced6efe44eaef52f17a08392d4c52a8d6eae7c 100644 --- a/network/message/sendCmix.go +++ b/network/message/sendCmix.go @@ -22,6 +22,7 @@ import ( "gitlab.com/xx_network/comms/connect" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/id/ephemeral" + "gitlab.com/xx_network/primitives/netTime" "strings" "time" ) @@ -32,12 +33,14 @@ type sendCmixCommsInterface interface { SendPutMessage(host *connect.Host, message *pb.GatewaySlot) (*pb.GatewaySlotResponse, error) } -const sendTimeBuffer = 100 * time.Millisecond +// 1.5 seconds +const sendTimeBuffer = 2500 * time.Millisecond // WARNING: Potentially Unsafe // Public manager function to send a message over CMIX func (m *Manager) SendCMIX(msg format.Message, recipient *id.ID, param params.CMIX) (id.Round, ephemeral.Id, error) { - return sendCmixHelper(msg, recipient, param, m.Instance, m.Session, m.nodeRegistration, m.Rng, m.TransmissionID, m.Comms) + msgCopy := msg.Copy() + return sendCmixHelper(msgCopy, recipient, param, m.Instance, m.Session, m.nodeRegistration, m.Rng, m.TransmissionID, m.Comms) } // Payloads send are not End to End encrypted, MetaData is NOT protected with @@ -52,14 +55,14 @@ func sendCmixHelper(msg format.Message, recipient *id.ID, param params.CMIX, ins session *storage.Session, nodeRegistration chan network.NodeGateway, rng *fastRNG.StreamGenerator, senderId *id.ID, comms sendCmixCommsInterface) (id.Round, ephemeral.Id, error) { - timeStart := time.Now() + timeStart := netTime.Now() attempted := set.New() jww.INFO.Printf("Looking for round to send cMix message to %s "+ "(msgDigest: %s)", recipient, msg.Digest()) for numRoundTries := uint(0); numRoundTries < param.RoundTries; numRoundTries++ { - elapsed := time.Now().Sub(timeStart) + elapsed := netTime.Now().Sub(timeStart) if elapsed > param.Timeout { jww.INFO.Printf("No rounds to send to %s (msgDigest: %s) "+ @@ -75,7 +78,7 @@ func sendCmixHelper(msg format.Message, recipient *id.ID, param params.CMIX, ins remainingTime := param.Timeout - elapsed //find the best round to send to, excluding attempted rounds - bestRound, _ := instance.GetWaitingRounds().GetUpcomingRealtime(remainingTime, attempted) + bestRound, _ := instance.GetWaitingRounds().GetUpcomingRealtime(remainingTime, attempted, sendTimeBuffer) if bestRound == nil { continue } @@ -83,23 +86,6 @@ func sendCmixHelper(msg format.Message, recipient *id.ID, param params.CMIX, ins //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) - now := time.Now() - - jww.DEBUG.Printf("Found round %d to send to %s (msgDigest: %s)", - bestRound.ID, recipient, msg.Digest()) - - if now.After(roundCutoffTime) { - jww.WARN.Printf("Round %d for sending to %s (msgDigest: %s) "+ - "received which has already started realtime: \n\t started: "+ - "%s \n\t now: %s", bestRound.ID, recipient, msg.Digest(), - roundCutoffTime, now) - continue - } - //set the ephemeral ID ephID, _, _, err := ephemeral.GetId(recipient, uint(bestRound.AddressSpaceSize), @@ -213,9 +199,9 @@ func sendCmixHelper(msg format.Message, recipient *id.ID, param params.CMIX, ins "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?"){ + } 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) diff --git a/network/message/sendCmix_test.go b/network/message/sendCmix_test.go index 7ea83223a809ed5e58a1e5a4e1ec6961b1755776..82b3ebcb2c3cfa87a72f62519f68541ae78bd06d 100644 --- a/network/message/sendCmix_test.go +++ b/network/message/sendCmix_test.go @@ -9,6 +9,8 @@ import ( "gitlab.com/elixxir/comms/client" "gitlab.com/elixxir/comms/mixmessages" "gitlab.com/elixxir/comms/network" + ds "gitlab.com/elixxir/comms/network/dataStructures" + "gitlab.com/elixxir/comms/testutils" "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/crypto/e2e" "gitlab.com/elixxir/crypto/fastRNG" @@ -19,6 +21,7 @@ import ( "gitlab.com/xx_network/crypto/large" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/ndf" + "gitlab.com/xx_network/primitives/netTime" "testing" "time" ) @@ -62,7 +65,7 @@ func Test_attemptSendCmix(t *testing.T) { if err != nil { t.Errorf("Failed to start instance: %+v", err) } - now := time.Now() + now := netTime.Now() nid1 := id.NewIdFromString("zezima", id.Node, t) nid2 := id.NewIdFromString("jakexx360", id.Node, t) nid3 := id.NewIdFromString("westparkhome", id.Node, t) @@ -78,7 +81,7 @@ func Test_attemptSendCmix(t *testing.T) { uint64(now.Add(5 * time.Second).UnixNano()), //QUEUED 0} //REALTIME - inst.GetWaitingRounds().Insert(&mixmessages.RoundInfo{ + ri := &mixmessages.RoundInfo{ ID: 3, UpdateID: 0, State: uint32(states.QUEUED), @@ -90,7 +93,18 @@ func Test_attemptSendCmix(t *testing.T) { ResourceQueueTimeoutMillis: 0, Signature: nil, AddressSpaceSize: 4, - }) + } + + if err = testutils.SignRoundInfo(ri, t); err != nil { + t.Errorf("Failed to sign mock round info: %v", err) + } + + pubKey, err := testutils.LoadPublicKeyTesting(t) + if err != nil { + t.Errorf("Failed to load a key for testing: %v", err) + } + rnd := ds.NewRound(ri, pubKey) + inst.GetWaitingRounds().Insert(rnd) i := internal.Internal{ Session: sess1, Switchboard: sw, diff --git a/network/message/sendE2E.go b/network/message/sendE2E.go index 14e6708cf83d05268ad27d738598b4f76d002229..78061232830f167adf91d21f5805fa2e00b58916 100644 --- a/network/message/sendE2E.go +++ b/network/message/sendE2E.go @@ -16,6 +16,7 @@ import ( "gitlab.com/elixxir/crypto/e2e" "gitlab.com/elixxir/primitives/format" "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/netTime" "sync" "time" ) @@ -26,7 +27,7 @@ func (m *Manager) SendE2E(msg message.Send, param params.E2E) ([]id.Round, e2e.M "message type", msg.MessageType) } //timestamp the message - ts := time.Now() + ts := netTime.Now() //partition the message partitions, internalMsgId, err := m.partitioner.Partition(msg.Recipient, msg.MessageType, ts, @@ -42,8 +43,9 @@ func (m *Manager) SendE2E(msg message.Send, param params.E2E) ([]id.Round, e2e.M // get the key manager for the partner partner, err := m.Session.E2e().GetPartner(msg.Recipient) if err != nil { - return nil, e2e.MessageID{}, errors.WithMessagef(err, "Could not send End to End encrypted "+ - "message, no relationship found with %s", msg.Recipient) + return nil, e2e.MessageID{}, errors.WithMessagef(err, + "Could not send End to End encrypted "+ + "message, no relationship found with %s", msg.Recipient) } wg := sync.WaitGroup{} @@ -52,8 +54,16 @@ func (m *Manager) SendE2E(msg message.Send, param params.E2E) ([]id.Round, e2e.M len(partitions), msg.Recipient) for i, p := range partitions { + + if msg.MessageType != message.KeyExchangeTrigger { + // check if any rekeys need to happen and trigger them + keyExchange.CheckKeyExchanges(m.Instance, m.SendE2E, + m.Session, partner, 1*time.Minute) + } + //create the cmix message - msgCmix := format.NewMessage(m.Session.Cmix().GetGroup().GetP().ByteLen()) + msgLen := m.Session.Cmix().GetGroup().GetP().ByteLen() + msgCmix := format.NewMessage(msgLen) msgCmix.SetContents(p) //get a key to end to end encrypt @@ -71,8 +81,8 @@ func (m *Manager) SendE2E(msg message.Send, param params.E2E) ([]id.Round, e2e.M key, err = partner.GetKeyForSending(param.Type) } if err != nil { - return nil, e2e.MessageID{}, errors.WithMessagef(err, "Failed to get key "+ - "for end to end encryption") + return nil, e2e.MessageID{}, errors.WithMessagef(err, + "Failed to get key for end to end encryption") } //end to end encrypt the cmix message @@ -85,7 +95,8 @@ func (m *Manager) SendE2E(msg message.Send, param params.E2E) ([]id.Round, e2e.M wg.Add(1) go func(i int) { var err error - roundIds[i], _, err = m.SendCMIX(msgEnc, msg.Recipient, param.CMIX) + roundIds[i], _, err = m.SendCMIX(msgEnc, msg.Recipient, + param.CMIX) if err != nil { errCh <- err } @@ -93,11 +104,6 @@ func (m *Manager) SendE2E(msg message.Send, param params.E2E) ([]id.Round, e2e.M }(i) } - // while waiting check if any rekeys need to happen and trigger them. This - // can happen now because the key popping happens in this thread, - // only the sending is parallelized - keyExchange.CheckKeyExchanges(m.Instance, m.SendE2E, m.Session, partner, 1*time.Minute) - wg.Wait() //see if any parts failed to send diff --git a/network/message/sendUnsafe.go b/network/message/sendUnsafe.go index d039b18724af24efbf3c60c711e55092b1fe40b8..ef28cf2d789d1f5f0a097413046b5a0c50b0a230 100644 --- a/network/message/sendUnsafe.go +++ b/network/message/sendUnsafe.go @@ -14,8 +14,8 @@ import ( "gitlab.com/elixxir/crypto/e2e" "gitlab.com/elixxir/primitives/format" "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/netTime" "sync" - "time" ) // WARNING: Unsafe @@ -33,7 +33,7 @@ func (m *Manager) SendUnsafe(msg message.Send, param params.Unsafe) ([]id.Round, msg.MessageType) } //timestamp the message - ts := time.Now() + ts := netTime.Now() //partition the message partitions, _, err := m.partitioner.Partition(msg.Recipient, msg.MessageType, ts, diff --git a/network/polltracker.go b/network/polltracker.go index 497539e94ec9d6aa8cb013bd0ee40678e1360731..48574c7d8e19eb4e1d73090af0c017e3c9b8187b 100644 --- a/network/polltracker.go +++ b/network/polltracker.go @@ -17,9 +17,9 @@ func newPollTracker() *pollTracker { func (pt *pollTracker) Track(ephID ephemeral.Id, source *id.ID) { if _, exists := (*pt)[*source]; !exists { (*pt)[*source] = make(map[int64]uint) - (*pt)[*source][ephID.Int64()] = 0 + (*pt)[*source][ephID.Int64()] = 1 } else if _, exists := (*pt)[*source][ephID.Int64()]; !exists { - (*pt)[*source][ephID.Int64()] = 0 + (*pt)[*source][ephID.Int64()] = 1 } else { (*pt)[*source][ephID.Int64()] = (*pt)[*source][ephID.Int64()] + 1 } diff --git a/network/rounds/check.go b/network/rounds/check.go index f8b1c64dd419bc8d349c04bc69db39c61637cbbd..9deb3ec6c16fb227a6406c9fd6181ffcf6e4d8b1 100644 --- a/network/rounds/check.go +++ b/network/rounds/check.go @@ -25,53 +25,31 @@ import ( // if the information about that round is already present, if it is the data is // sent to Message Retrieval Workers, otherwise it is sent to Historical Round // Retrieval -func (m *Manager) Checker(roundID id.Round, filters []*RemoteFilter, identity reception.IdentityUse) bool { - // Set round to processing, if we can - status, count := m.p.Process(roundID, identity.EphId, identity.Source) - jww.INFO.Printf("checking: %d, status: %s", roundID, status) - - switch status{ - case Processing: - return false - case Done: - return true - } - - //if the number of times the round has been checked has hit the max, drop it - if count == m.params.MaxAttemptsCheckingARound { - jww.ERROR.Printf("Looking up Round %v for %d (%s) failed "+ - "the maximum number of times (%v), stopping retrval attempt", - roundID, identity.EphId, identity.Source, - m.params.MaxAttemptsCheckingARound) - m.p.Done(roundID, identity.EphId, identity.Source) - return true - } - - hasRound := false +// false: no message +// true: message +func Checker(roundID id.Round, filters []*RemoteFilter) bool { //find filters that could have the round and check them serialRid := serializeRound(roundID) for _, filter := range filters { if filter != nil && filter.FirstRound() <= roundID && filter.LastRound() >= roundID { if filter.GetFilter().Test(serialRid) { - hasRound = true - break + return true } } } + return false +} - //if it is not present, set the round as checked - //that means no messages are available for the user in the round - if !hasRound { - jww.DEBUG.Printf("No messages found for %d (%s) in round %d, "+ - "will not check again", identity.EphId.Int64(), identity.Source, roundID) - m.p.Done(roundID, identity.EphId, identity.Source) - return true - } +func serializeRound(roundId id.Round) []byte { + b := make([]byte, 8) + binary.LittleEndian.PutUint64(b, uint64(roundId)) + return b +} - // Go get the round from the round infos, if it exists +func (m *Manager) GetMessagesFromRound(roundID id.Round, identity reception.IdentityUse){ ri, err := m.Instance.GetRound(roundID) - if err != nil || m.params.ForceHistoricalRounds { + if err !=nil || m.params.ForceHistoricalRounds { if m.params.ForceHistoricalRounds { jww.WARN.Printf("Forcing use of historical rounds for round ID %d.", roundID) @@ -83,9 +61,10 @@ func (m *Manager) Checker(roundID id.Round, filters []*RemoteFilter, identity re m.historicalRounds <- historicalRoundRequest{ rid: roundID, identity: identity, + numAttempts: 0, } } else { - jww.INFO.Printf("Messages found in round %d for %d (%s), looking " + + jww.INFO.Printf("Messages found in round %d for %d (%s), looking "+ "up messages via in ram lookup", roundID, identity.EphId.Int64(), identity.Source) // If found, send to Message Retrieval Workers @@ -95,11 +74,4 @@ func (m *Manager) Checker(roundID id.Round, filters []*RemoteFilter, identity re } } - return false -} - -func serializeRound(roundId id.Round) []byte { - b := make([]byte, 8) - binary.LittleEndian.PutUint64(b, uint64(roundId)) - return b -} +} \ No newline at end of file diff --git a/network/rounds/historical.go b/network/rounds/historical.go index 1a0f5c100697044ebdbdaf7975b5019e87be0356..d5451989c4f3092652943d308d37c4a21bbf0524 100644 --- a/network/rounds/historical.go +++ b/network/rounds/historical.go @@ -36,6 +36,7 @@ type historicalRoundsComms interface { type historicalRoundRequest struct { rid id.Round identity reception.IdentityUse + numAttempts uint } // Long running thread which process historical rounds @@ -62,7 +63,6 @@ func (m *Manager) processHistoricalRounds(comm historicalRoundsComms, quitCh <-c select { case m.historicalRounds <- r: default: - m.p.NotProcessing(r.rid, r.identity.EphId, r.identity.Source) } } done = true @@ -123,9 +123,23 @@ func (m *Manager) processHistoricalRounds(comm historicalRoundsComms, quitCh <-c // need be be removes as processing so the network follower will // pick them up in the future. if roundInfo == nil { - jww.ERROR.Printf("Failed to retreive "+ - "historical round %d", roundRequests[i].rid) - m.p.Fail(roundRequests[i].rid, roundRequests[i].identity.EphId, roundRequests[i].identity.Source) + roundRequests[i].numAttempts++ + if roundRequests[i].numAttempts==m.params.MaxHistoricalRoundsRetries{ + jww.ERROR.Printf("Failed to retreive historical " + + "round %d on last attempt, will not try again", + roundRequests[i].rid) + }else{ + select { + case m.historicalRounds <-roundRequests[i]: + jww.WARN.Printf("Failed to retreive historical " + + "round %d, will try up to %d more times", + roundRequests[i].rid, m.params.MaxHistoricalRoundsRetries-roundRequests[i].numAttempts) + default: + jww.WARN.Printf("Failed to retreive historical " + + "round %d, failed to try again, round will not be " + + "retreived", roundRequests[i].rid) + } + } continue } // Successfully retrieved roundRequests are sent to the Message diff --git a/network/rounds/manager.go b/network/rounds/manager.go index c2a3a37b2acf611d73d7e190525bf4d25fd84620..177c1c318b4807be0f17ccbb36bbe8720104deb4 100644 --- a/network/rounds/manager.go +++ b/network/rounds/manager.go @@ -13,15 +13,11 @@ import ( "gitlab.com/elixxir/client/network/internal" "gitlab.com/elixxir/client/network/message" "gitlab.com/elixxir/client/stoppable" - "gitlab.com/xx_network/primitives/id" - "gitlab.com/xx_network/primitives/id/ephemeral" ) type Manager struct { params params.Rounds - p *processing - internal.Internal historicalRounds chan historicalRoundRequest @@ -33,7 +29,6 @@ func NewManager(internal internal.Internal, params params.Rounds, bundles chan<- message.Bundle) *Manager { m := &Manager{ params: params, - p: newProcessingRounds(), historicalRounds: make(chan historicalRoundRequest, params.HistoricalRoundsBufferLen), lookupRoundMessages: make(chan roundLookup, params.LookupRoundsBufferLen), @@ -60,9 +55,4 @@ func (m *Manager) StartProcessors() stoppable.Stoppable { multi.Add(stopper) } return multi -} - -func (m *Manager) DeleteProcessingRoundDelete(round id.Round, eph ephemeral.Id, source *id.ID) { - - m.p.Delete(round, eph, source) -} +} \ No newline at end of file diff --git a/network/rounds/processingRounds.go b/network/rounds/processingRounds.go deleted file mode 100644 index 954773201bcf7f270d9bab1674320be6da860a3b..0000000000000000000000000000000000000000 --- a/network/rounds/processingRounds.go +++ /dev/null @@ -1,156 +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 rounds - -// File for storing info about which rounds are processing - -import ( - "crypto/md5" - "encoding/binary" - "fmt" - "gitlab.com/xx_network/primitives/id" - "gitlab.com/xx_network/primitives/id/ephemeral" - "sync" -) - -type Status uint8 - -const ( - NotProcessing Status = iota - Processing - Done -) - -func (s Status)String()string{ - switch s{ - case NotProcessing: - return "NotProcessing" - case Processing: - return "Processing" - case Done: - return "Done" - default: - return fmt.Sprintf("Unknown Status: %d", s) - } -} - - -type status struct { - failCount uint - Status -} - -// processing struct with a lock so it can be managed with concurrent threads. -type processing struct { - rounds map[hashID]*status - sync.RWMutex -} - -type hashID [16]byte - -func makeHashID(round id.Round, eph ephemeral.Id, source *id.ID) hashID { - h := md5.New() - ridbytes := make([]byte, 8) - binary.BigEndian.PutUint64(ridbytes, uint64(round)) - h.Write(ridbytes) - h.Write(eph[:]) - h.Write(source.Bytes()) - - hBytes := h.Sum(nil) - hid := hashID{} - copy(hid[:], hBytes) - return hid -} - -// newProcessingRounds returns a new processing rounds object. -func newProcessingRounds() *processing { - return &processing{ - rounds: make(map[hashID]*status), - } -} - -// Process adds a round to the list of processing rounds. The returned boolean -// is true when the round changes from "not processing" to "processing". The -// returned count is the number of times the round has been processed. -func (pr *processing) Process(round id.Round, eph ephemeral.Id, source *id.ID) (Status, uint) { - hid := makeHashID(round, eph, source) - - pr.Lock() - defer pr.Unlock() - - var rs *status - var ok bool - - if rs, ok = pr.rounds[hid]; ok && rs.Status == NotProcessing { - rs.Status = Processing - return NotProcessing, rs.failCount - }else if !ok{ - rs = &status{ - failCount: 0, - Status: Processing, - } - pr.rounds[hid] = rs - return NotProcessing, rs.failCount - } - - return rs.Status, rs.failCount -} - -// IsProcessing determines if a round ID is marked as processing. -func (pr *processing) IsProcessing(round id.Round, eph ephemeral.Id, source *id.ID) bool { - hid := makeHashID(round, eph, source) - pr.RLock() - defer pr.RUnlock() - - if rs, ok := pr.rounds[hid]; ok { - return rs.Status == Processing - } - - return false -} - -// Fail sets a round's processing status to failed and increments its fail -// counter so that it can be retried. -func (pr *processing) Fail(round id.Round, eph ephemeral.Id, source *id.ID) { - hid := makeHashID(round, eph, source) - pr.Lock() - defer pr.Unlock() - if rs, ok := pr.rounds[hid]; ok { - rs.Status = NotProcessing - rs.failCount++ - } -} - -// Done deletes a round from the processing list. -func (pr *processing) Done(round id.Round, eph ephemeral.Id, source *id.ID) { - hid := makeHashID(round, eph, source) - pr.Lock() - defer pr.Unlock() - if rs, ok := pr.rounds[hid]; ok { - rs.Status = Done - } -} - -// NotProcessing sets a round's processing status to failed so that it can be -// retried but does not increment its fail counter. -func (pr *processing) NotProcessing(round id.Round, eph ephemeral.Id, source *id.ID) { - hid := makeHashID(round, eph, source) - pr.Lock() - defer pr.Unlock() - if rs, ok := pr.rounds[hid]; ok { - rs.Status = NotProcessing - } -} - -// Done deletes a round from the processing list. -func (pr *processing) Delete(round id.Round, eph ephemeral.Id, source *id.ID) { - hid := makeHashID(round, eph, source) - pr.Lock() - defer pr.Unlock() - delete(pr.rounds, hid) -} diff --git a/network/rounds/processingRounds_test.go b/network/rounds/processingRounds_test.go deleted file mode 100644 index ce186dfbedb0ea84b55fca15b1109d49349fc1b3..0000000000000000000000000000000000000000 --- a/network/rounds/processingRounds_test.go +++ /dev/null @@ -1,124 +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 rounds - -import ( - "gitlab.com/xx_network/primitives/id" - "gitlab.com/xx_network/primitives/id/ephemeral" - "reflect" - "testing" -) - -// Testing functions for Processing Round structure - -// Tests happy path of newProcessingRounds. -func Test_newProcessingRounds(t *testing.T) { - expectedPr := &processing{ - rounds: make(map[hashID]*status), - } - - pr := newProcessingRounds() - - if !reflect.DeepEqual(expectedPr, pr) { - t.Errorf("Did not get expected processing."+ - "\n\texpected: %v\n\trecieved: %v", expectedPr, pr) - } -} - -// Tests happy path of Process. -func TestProcessing_Process(t *testing.T) { - pr := newProcessingRounds() - - ephID := ephemeral.Id{} - source := &id.ID{} - - testData := []struct { - rid id.Round - status Status - count uint - }{ - {10, NotProcessing, 0}, - {10, NotProcessing, 0}, - {10, Processing, 0}, - {100, NotProcessing, 0}, - {100, NotProcessing, 0}, - {100, Processing, 0}, - } - - for i, d := range testData { - hid := makeHashID(d.rid, ephID, source) - if _, exists := pr.rounds[hid]; exists { - pr.rounds[hid].Status = d.status - } - status, count := pr.Process(d.rid, ephID, source) - if status != d.status { - t.Errorf("Process() did not return the correct boolean for round "+ - "ID %d (%d).\nexpected: %s\nrecieved: %s", - d.rid, i, d.status, status) - } - if count != d.count { - t.Errorf("Process did not return the expected count for round ID "+ - "%d (%d).\n\texpected: %d\n\trecieved: %d", - d.rid, i, d.count, count) - } - - if _, ok := pr.rounds[hid]; !ok { - t.Errorf("Process() did not add round ID %d to the map (%d).", - d.rid, i) - } - } - -} - -// Tests happy path of IsProcessing. -func TestProcessing_IsProcessing(t *testing.T) { - pr := newProcessingRounds() - ephID := ephemeral.Id{} - source := &id.ID{} - rid := id.Round(10) - hid := makeHashID(rid, ephID, source) - pr.rounds[hid] = &status{0, Processing} - if !pr.IsProcessing(rid, ephID, source) { - t.Errorf("IsProcessing() should have returned %s for round ID %d.", Processing, rid) - } - pr.rounds[hid].Status = NotProcessing - if pr.IsProcessing(rid, ephID, source) { - t.Errorf("IsProcessing() should have returned %s for round ID %d.", NotProcessing, rid) - } -} - -// Tests happy path of Fail. -func TestProcessing_Fail(t *testing.T) { - pr := newProcessingRounds() - rid := id.Round(10) - ephID := ephemeral.Id{} - source := &id.ID{} - hid := makeHashID(rid, ephID, source) - pr.rounds[hid] = &status{0, Processing} - pr.Fail(rid, ephID, source) - if pr.rounds[hid].Status == Processing { - t.Errorf("Fail() did not mark processing as false for round id %d.", rid) - } - if pr.rounds[hid].failCount != 1 { - t.Errorf("Fail() did not increment the fail count of round id %d.", rid) - } -} - -// Tests happy path of Done. -func TestProcessing_Done(t *testing.T) { - pr := newProcessingRounds() - rid := id.Round(10) - ephID := ephemeral.Id{} - source := &id.ID{} - hid := makeHashID(rid, ephID, source) - pr.rounds[hid] = &status{0, Processing} - pr.Done(rid, ephID, source) - if s, _ := pr.rounds[hid]; s.Status != Done { - t.Errorf("Done() failed to flag round ID %d.", rid) - } -} diff --git a/network/rounds/retrieve.go b/network/rounds/retrieve.go index 5269357776e9be37984cacfbe31a2208dda912d2..effd66b7fcac84db95255cc458c997a36d134f2b 100644 --- a/network/rounds/retrieve.go +++ b/network/rounds/retrieve.go @@ -82,7 +82,6 @@ func (m *Manager) processMessageRetrieval(comms messageRetrievalComms, // 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) @@ -116,7 +115,6 @@ func (m *Manager) getMessagesFromGateway(roundID id.Round, identity reception.Id } // if the gateway doesnt have the round, return an error if !msgResp.GetHasRound() { - m.p.Done(roundID, identity.EphId, identity.Source) return message.Bundle{}, errors.Errorf(noRoundError) } @@ -139,7 +137,7 @@ func (m *Manager) getMessagesFromGateway(roundID id.Round, identity reception.Id Round: roundID, Messages: make([]format.Message, len(msgs)), Finish: func() { - m.p.Done(roundID, identity.EphId, identity.Source) + return }, } diff --git a/network/rounds/utils_test.go b/network/rounds/utils_test.go index f8f14e32778574850519b02fcd73da6d2171e2e5..69c5925ed5e5b787f2440169d5da9a24d373b219 100644 --- a/network/rounds/utils_test.go +++ b/network/rounds/utils_test.go @@ -23,7 +23,6 @@ func newManager(face interface{}) *Manager { testManager := &Manager{ lookupRoundMessages: make(chan roundLookup), messageBundles: make(chan message.Bundle), - p: newProcessingRounds(), Internal: internal.Internal{ Session: sess1, TransmissionID: sess1.GetUser().TransmissionID, diff --git a/single/manager_test.go b/single/manager_test.go index ff09e8ecd8ed9faa67f3339c283ea365c7899c5c..5ee50ed606ff203253729aae941e248c224df533 100644 --- a/single/manager_test.go +++ b/single/manager_test.go @@ -12,7 +12,6 @@ import ( "errors" "gitlab.com/elixxir/client/api" "gitlab.com/elixxir/client/interfaces" - contact2 "gitlab.com/elixxir/client/interfaces/contact" "gitlab.com/elixxir/client/interfaces/message" "gitlab.com/elixxir/client/interfaces/params" "gitlab.com/elixxir/client/stoppable" @@ -21,6 +20,7 @@ import ( "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/client/switchboard" "gitlab.com/elixxir/comms/network" + contact2 "gitlab.com/elixxir/crypto/contact" "gitlab.com/elixxir/crypto/e2e" "gitlab.com/elixxir/crypto/e2e/singleUse" "gitlab.com/elixxir/crypto/fastRNG" @@ -31,6 +31,7 @@ import ( "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/id/ephemeral" "gitlab.com/xx_network/primitives/ndf" + "gitlab.com/xx_network/primitives/netTime" "math/rand" "reflect" "sync" @@ -67,7 +68,7 @@ func TestManager_StartProcesses(t *testing.T) { callback, callbackChan := createReceiveComm() transmitMsg, _, rid, _, err := m.makeTransmitCmixMessage(partner, payload, - tag, 8, 32, 30*time.Second, time.Now(), rand.New(rand.NewSource(42))) + tag, 8, 32, 30*time.Second, netTime.Now(), rand.New(rand.NewSource(42))) if err != nil { t.Fatalf("Failed to create tranmission CMIX message: %+v", err) } @@ -107,7 +108,7 @@ func TestManager_StartProcesses(t *testing.T) { m.p.Lock() m.p.singleUse[*rid] = newState(sender.dhKey, sender.maxParts, callbackFunc) m.p.Unlock() - eid, _, _, _ := ephemeral.GetId(partner.ID, id.ArrIDLen, time.Now().UnixNano()) + eid, _, _, _ := ephemeral.GetId(partner.ID, id.ArrIDLen, netTime.Now().UnixNano()) replyMsg := message.Receive{ Payload: replyMsgs[0].Marshal(), MessageType: message.Raw, @@ -153,7 +154,7 @@ func TestManager_StartProcesses_Stop(t *testing.T) { callback, callbackChan := createReceiveComm() transmitMsg, _, rid, _, err := m.makeTransmitCmixMessage(partner, payload, - tag, 8, 32, 30*time.Second, time.Now(), rand.New(rand.NewSource(42))) + tag, 8, 32, 30*time.Second, netTime.Now(), rand.New(rand.NewSource(42))) if err != nil { t.Fatalf("Failed to create tranmission CMIX message: %+v", err) } @@ -199,7 +200,7 @@ func TestManager_StartProcesses_Stop(t *testing.T) { m.p.Lock() m.p.singleUse[*rid] = newState(sender.dhKey, sender.maxParts, callbackFunc) m.p.Unlock() - eid, _, _, _ := ephemeral.GetId(partner.ID, id.ArrIDLen, time.Now().UnixNano()) + eid, _, _, _ := ephemeral.GetId(partner.ID, id.ArrIDLen, netTime.Now().UnixNano()) replyMsg := message.Receive{ Payload: replyMsgs[0].Marshal(), MessageType: message.Raw, diff --git a/single/receiveResponse_test.go b/single/receiveResponse_test.go index 2782bc6fc1ad6d74eab2c0c2d51bf9988066734d..4e7e8c352e8196f0ff24d5a0d60633f78439e8dd 100644 --- a/single/receiveResponse_test.go +++ b/single/receiveResponse_test.go @@ -15,6 +15,7 @@ import ( "gitlab.com/elixxir/primitives/format" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/id/ephemeral" + "gitlab.com/xx_network/primitives/netTime" "math/rand" "strings" "testing" @@ -29,7 +30,7 @@ func TestManager_ReceiveResponseHandler(t *testing.T) { partner := NewContact(id.NewIdFromString("recipientID", id.User, t), m.store.E2e().GetGroup().NewInt(43), m.store.E2e().GetGroup().NewInt(42), singleUse.TagFP{}, 8) - ephID, _, _, err := ephemeral.GetId(partner.partner, id.ArrIDLen, time.Now().UnixNano()) + ephID, _, _, err := ephemeral.GetId(partner.partner, id.ArrIDLen, netTime.Now().UnixNano()) payload := make([]byte, 2000) rand.New(rand.NewSource(42)).Read(payload) callback, callbackChan := createReplyComm() @@ -88,7 +89,7 @@ func TestManager_ReceiveResponseHandler_CmixMessageError(t *testing.T) { partner := NewContact(id.NewIdFromString("recipientID", id.User, t), m.store.E2e().GetGroup().NewInt(43), m.store.E2e().GetGroup().NewInt(42), singleUse.TagFP{}, 8) - ephID, _, _, _ := ephemeral.GetId(partner.partner, id.ArrIDLen, time.Now().UnixNano()) + ephID, _, _, _ := ephemeral.GetId(partner.partner, id.ArrIDLen, netTime.Now().UnixNano()) payload := make([]byte, 2000) rand.New(rand.NewSource(42)).Read(payload) callback, callbackChan := createReplyComm() @@ -130,7 +131,7 @@ func TestManager_ReceiveResponseHandler_CmixMessageError(t *testing.T) { func TestManager_processesResponse(t *testing.T) { m := newTestManager(0, false, t) rid := id.NewIdFromString("test RID", id.User, t) - ephID, _, _, err := ephemeral.GetId(rid, id.ArrIDLen, time.Now().UnixNano()) + ephID, _, _, err := ephemeral.GetId(rid, id.ArrIDLen, netTime.Now().UnixNano()) if err != nil { t.Fatalf("Failed to create ephemeral ID: %+v", err) } diff --git a/single/reception_test.go b/single/reception_test.go index 6989406621f2300e2f78c057defaf55d2e5858e1..3266d9904b2fb51dd592c766b61a9c40409e0925 100644 --- a/single/reception_test.go +++ b/single/reception_test.go @@ -2,11 +2,12 @@ package single import ( "bytes" - contact2 "gitlab.com/elixxir/client/interfaces/contact" "gitlab.com/elixxir/client/interfaces/message" + contact2 "gitlab.com/elixxir/crypto/contact" "gitlab.com/elixxir/crypto/e2e/singleUse" "gitlab.com/elixxir/primitives/format" "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/netTime" "math/rand" "testing" "time" @@ -27,7 +28,7 @@ func TestManager_receiveTransmissionHandler(t *testing.T) { callback, callbackChan := createReceiveComm() msg, _, _, _, err := m.makeTransmitCmixMessage(partner, payload, tag, 8, 32, - 30*time.Second, time.Now(), rand.New(rand.NewSource(42))) + 30*time.Second, netTime.Now(), rand.New(rand.NewSource(42))) if err != nil { t.Fatalf("Failed to create tranmission CMIX message: %+v", err) } @@ -92,7 +93,7 @@ func TestManager_receiveTransmissionHandler_FingerPrintError(t *testing.T) { callback, callbackChan := createReceiveComm() msg, _, _, _, err := m.makeTransmitCmixMessage(partner, payload, tag, 8, 32, - 30*time.Second, time.Now(), rand.New(rand.NewSource(42))) + 30*time.Second, netTime.Now(), rand.New(rand.NewSource(42))) if err != nil { t.Fatalf("Failed to create tranmission CMIX message: %+v", err) } @@ -129,7 +130,7 @@ func TestManager_receiveTransmissionHandler_ProcessMessageError(t *testing.T) { callback, callbackChan := createReceiveComm() msg, _, _, _, err := m.makeTransmitCmixMessage(partner, payload, tag, 8, 32, - 30*time.Second, time.Now(), rand.New(rand.NewSource(42))) + 30*time.Second, netTime.Now(), rand.New(rand.NewSource(42))) if err != nil { t.Fatalf("Failed to create tranmission CMIX message: %+v", err) } @@ -167,7 +168,7 @@ func TestManager_receiveTransmissionHandler_TagFpError(t *testing.T) { rand.New(rand.NewSource(42)).Read(payload) msg, _, _, _, err := m.makeTransmitCmixMessage(partner, payload, tag, 8, 32, - 30*time.Second, time.Now(), rand.New(rand.NewSource(42))) + 30*time.Second, netTime.Now(), rand.New(rand.NewSource(42))) if err != nil { t.Fatalf("Failed to create tranmission CMIX message: %+v", err) } @@ -189,7 +190,7 @@ func TestManager_processTransmission(t *testing.T) { payload := []byte("This is the payload.") maxMsgs := uint8(6) cmixMsg, dhKey, rid, _, err := m.makeTransmitCmixMessage(partner, payload, - tag, maxMsgs, 32, 30*time.Second, time.Now(), rand.New(rand.NewSource(42))) + tag, maxMsgs, 32, 30*time.Second, netTime.Now(), rand.New(rand.NewSource(42))) if err != nil { t.Fatalf("Failed to generate expected CMIX message: %+v", err) } @@ -240,7 +241,7 @@ func TestManager_processTransmission_MacVerifyError(t *testing.T) { DhPubKey: m.store.E2e().GetDHPublicKey(), } cmixMsg, _, _, _, err := m.makeTransmitCmixMessage(partner, []byte{}, "", 6, - 32, 30*time.Second, time.Now(), rand.New(rand.NewSource(42))) + 32, 30*time.Second, netTime.Now(), rand.New(rand.NewSource(42))) if err != nil { t.Fatalf("Failed to generate expected CMIX message: %+v", err) } diff --git a/single/transmission.go b/single/transmission.go index 13abe66dbd753c5f1b2e6a3036c0c6efa8f0c9b4..d5289f339b1120c87256228d87fd7b7514c0a9d7 100644 --- a/single/transmission.go +++ b/single/transmission.go @@ -11,11 +11,11 @@ import ( "fmt" "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" - contact2 "gitlab.com/elixxir/client/interfaces/contact" "gitlab.com/elixxir/client/interfaces/params" "gitlab.com/elixxir/client/interfaces/utility" "gitlab.com/elixxir/client/storage/reception" ds "gitlab.com/elixxir/comms/network/dataStructures" + contact2 "gitlab.com/elixxir/crypto/contact" "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/crypto/e2e/auth" "gitlab.com/elixxir/crypto/e2e/singleUse" @@ -24,6 +24,7 @@ import ( "gitlab.com/xx_network/crypto/csprng" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/id/ephemeral" + "gitlab.com/xx_network/primitives/netTime" "io" "sync/atomic" "time" @@ -72,7 +73,7 @@ func (m *Manager) transmitSingleUse(partner contact2.Contact, payload []byte, // Create new CMIX message containing the transmission payload cmixMsg, dhKey, rid, ephID, err := m.makeTransmitCmixMessage(partner, - payload, tag, MaxMsgs, addressSize, timeout, time.Now(), rng) + payload, tag, MaxMsgs, addressSize, timeout, netTime.Now(), rng) if err != nil { return errors.Errorf("failed to create new CMIX message: %+v", err) } @@ -80,7 +81,7 @@ func (m *Manager) transmitSingleUse(partner contact2.Contact, payload []byte, jww.DEBUG.Printf("Created single-use transmission CMIX message with new ID "+ "%s and ephemeral ID %d", rid, ephID.Int64()) - timeStart := time.Now() + timeStart := netTime.Now() // Add message state to map quitChan, quit, err := m.p.addState(rid, dhKey, MaxMsgs, callback, timeout) @@ -139,7 +140,7 @@ func (m *Manager) transmitSingleUse(partner contact2.Contact, payload []byte, } // Update the timeout for the elapsed time - roundEventTimeout := timeout - time.Now().Sub(timeStart) - time.Millisecond + roundEventTimeout := timeout - netTime.Now().Sub(timeStart) - time.Millisecond // Check message delivery sendResults := make(chan ds.EventReturn, 1) diff --git a/single/transmission_test.go b/single/transmission_test.go index fe6df60ba188ef5abe88e06ab4434c0d289618b5..367a8b3bfa4bd07df0e266045281624934ea3ee3 100644 --- a/single/transmission_test.go +++ b/single/transmission_test.go @@ -2,9 +2,9 @@ package single import ( "bytes" - contact2 "gitlab.com/elixxir/client/interfaces/contact" pb "gitlab.com/elixxir/comms/mixmessages" ds "gitlab.com/elixxir/comms/network/dataStructures" + contact2 "gitlab.com/elixxir/crypto/contact" "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/crypto/e2e/auth" "gitlab.com/elixxir/crypto/e2e/singleUse" @@ -12,6 +12,7 @@ import ( "gitlab.com/elixxir/primitives/states" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/id/ephemeral" + "gitlab.com/xx_network/primitives/netTime" "math/rand" "reflect" "strings" @@ -60,7 +61,7 @@ func TestManager_transmitSingleUse(t *testing.T) { } expectedMsg, _, _, _, err := m.makeTransmitCmixMessage(partner, payload, - tag, maxMsgs, 32, 30*time.Second, time.Now(), rand.New(rand.NewSource(42))) + tag, maxMsgs, 32, 30*time.Second, netTime.Now(), rand.New(rand.NewSource(42))) if err != nil { t.Fatalf("Failed to make expected message: %+v", err) } @@ -204,7 +205,7 @@ func TestManager_transmitSingleUse_AddStateError(t *testing.T) { // Create new CMIX and add a state _, dhKey, rid, _, err := m.makeTransmitCmixMessage(partner, payload, tag, - maxMsgs, 32, 30*time.Second, time.Now(), rand.New(rand.NewSource(42))) + maxMsgs, 32, 30*time.Second, netTime.Now(), rand.New(rand.NewSource(42))) if err != nil { t.Fatalf("Failed to create new CMIX message: %+v", err) } @@ -262,7 +263,7 @@ func TestManager_makeTransmitCmixMessage(t *testing.T) { payload := make([]byte, 132) rand.New(rand.NewSource(42)).Read(payload) maxMsgs := uint8(8) - timeNow := time.Now() + timeNow := netTime.Now() msg, dhKey, rid, _, err := m.makeTransmitCmixMessage(partner, payload, tag, maxMsgs, 32, 30*time.Second, timeNow, prng) @@ -325,7 +326,7 @@ func TestManager_makeTransmitCmixMessage_PayloadTooLargeError(t *testing.T) { rand.New(rand.NewSource(42)).Read(payload) _, _, _, _, err := m.makeTransmitCmixMessage(contact2.Contact{}, payload, "", 8, 32, - 30*time.Second, time.Now(), prng) + 30*time.Second, netTime.Now(), prng) if !check(err, "too long for message payload capacity") { t.Errorf("makeTransmitCmixMessage() failed to error when the payload is too "+ @@ -343,7 +344,7 @@ func TestManager_makeTransmitCmixMessage_KeyGenerationError(t *testing.T) { } _, _, _, _, err := m.makeTransmitCmixMessage(partner, nil, "", 8, 32, - 30*time.Second, time.Now(), prng) + 30*time.Second, netTime.Now(), prng) if !check(err, "failed to generate key in group") { t.Errorf("makeTransmitCmixMessage() failed to error when key "+ @@ -377,7 +378,7 @@ func Test_makeIDs_Consistency(t *testing.T) { t.Fatalf("Failed to set nonce: %+v", err) } - timeNow := time.Now() + timeNow := netTime.Now() rid, ephID, err := makeIDs(&msgPayload, publicKey, addressSize, 30*time.Second, timeNow, rand.New(rand.NewSource(42))) @@ -412,7 +413,7 @@ func Test_makeIDs_NonceError(t *testing.T) { msgPayload := newTransmitMessagePayload(transmitPlMinSize) _, _, err := makeIDs(&msgPayload, &cyclic.Int{}, 32, 30*time.Second, - time.Now(), strings.NewReader("")) + netTime.Now(), strings.NewReader("")) if !check(err, "failed to generate nonce") { t.Errorf("makeIDs() did not return an error when failing to make nonce: %+v", err) } diff --git a/stoppable/cleanup.go b/stoppable/cleanup.go index c721f3605aa6d5ef1323a9e01dc2b80b7cb3684c..8111abe206492d4e22cfaffe31195acab58b77c5 100644 --- a/stoppable/cleanup.go +++ b/stoppable/cleanup.go @@ -9,6 +9,8 @@ package stoppable import ( "github.com/pkg/errors" + jww "github.com/spf13/jwalterweatherman" + "gitlab.com/xx_network/primitives/netTime" "sync" "sync/atomic" "time" @@ -55,7 +57,7 @@ func (c *Cleanup) Close(timeout time.Duration) error { c.once.Do( func() { defer atomic.StoreUint32(&c.running, 0) - start := time.Now() + start := netTime.Now() // Run the stoppable if err := c.stop.Close(timeout); err != nil { @@ -85,5 +87,9 @@ func (c *Cleanup) Close(timeout time.Duration) error { } }) + if err!=nil{ + jww.ERROR.Printf(err.Error()) + } + return err } diff --git a/storage/auth/request.go b/storage/auth/request.go index c33d9b02cbe2477725438903052102fdf18d11ff..b6088352d29a3d0dc584f635ac7d0d26db021bad 100644 --- a/storage/auth/request.go +++ b/storage/auth/request.go @@ -8,7 +8,7 @@ package auth import ( - "gitlab.com/elixxir/client/interfaces/contact" + "gitlab.com/elixxir/crypto/contact" "sync" ) diff --git a/storage/auth/sentRequest.go b/storage/auth/sentRequest.go index 09251401cbe1433d917a6d3912ab68aaf2873002..77901412056ca674b8756d9e661edff7bd4d8076 100644 --- a/storage/auth/sentRequest.go +++ b/storage/auth/sentRequest.go @@ -14,7 +14,7 @@ import ( "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/primitives/format" "gitlab.com/xx_network/primitives/id" - "time" + "gitlab.com/xx_network/primitives/netTime" ) const currentSentRequestVersion = 0 @@ -112,7 +112,7 @@ func (sr *SentRequest) save() error { obj := versioned.Object{ Version: currentSentRequestVersion, - Timestamp: time.Now(), + Timestamp: netTime.Now(), Data: data, } diff --git a/storage/auth/store.go b/storage/auth/store.go index 1d8f074436461f7c7a3e198bbbbc772d54804388..a03dee9eaced47223f597f14d78c6c093ede6cfd 100644 --- a/storage/auth/store.go +++ b/storage/auth/store.go @@ -11,15 +11,15 @@ import ( "encoding/json" "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" - "gitlab.com/elixxir/client/interfaces/contact" "gitlab.com/elixxir/client/storage/utility" "gitlab.com/elixxir/client/storage/versioned" + "gitlab.com/elixxir/crypto/contact" "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/crypto/e2e/auth" "gitlab.com/elixxir/primitives/format" "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/netTime" "sync" - "time" ) const NoRequest = "Request Not Found" @@ -161,7 +161,7 @@ func (s *Store) save() error { obj := versioned.Object{ Version: requestMapVersion, - Timestamp: time.Now(), + Timestamp: netTime.Now(), Data: data, } @@ -405,6 +405,5 @@ func (s *Store) Delete(partner *id.ID) error { "deletion: %+v", err) } - r.mux.Unlock() return nil } diff --git a/storage/auth/store_test.go b/storage/auth/store_test.go index 591cc31b483e05fcee8bb8084416d3dc71b61c0d..94d0318f3d702cd7f9fb58860ada31a1b6f54b17 100644 --- a/storage/auth/store_test.go +++ b/storage/auth/store_test.go @@ -8,8 +8,8 @@ package auth import ( - "gitlab.com/elixxir/client/interfaces/contact" "gitlab.com/elixxir/client/storage/versioned" + "gitlab.com/elixxir/crypto/contact" "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/crypto/e2e/auth" "gitlab.com/elixxir/ekv" diff --git a/storage/clientVersion/store.go b/storage/clientVersion/store.go index 3f1eca48aca688113ba8c240ad8e747029947a90..5b6e951ef6c0bf5b86049b636606fa015f9d4062 100644 --- a/storage/clientVersion/store.go +++ b/storage/clientVersion/store.go @@ -12,8 +12,8 @@ import ( jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/primitives/version" + "gitlab.com/xx_network/primitives/netTime" "sync" - "time" ) const ( @@ -105,7 +105,7 @@ func (s *Store) update(newVersion version.Version) error { // save stores the clientVersion store. Note that this function does not take // a lock. func (s *Store) save() error { - timeNow := time.Now() + timeNow := netTime.Now() obj := versioned.Object{ Version: storeVersion, diff --git a/storage/clientVersion/store_test.go b/storage/clientVersion/store_test.go index 22da1257c04f0b7780d63b46c0cf28a86bd6143d..72098cffa061ac63ac375f92e533312272e5d3bf 100644 --- a/storage/clientVersion/store_test.go +++ b/storage/clientVersion/store_test.go @@ -11,10 +11,10 @@ import ( "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/ekv" "gitlab.com/elixxir/primitives/version" + "gitlab.com/xx_network/primitives/netTime" "reflect" "strings" "testing" - "time" ) // Happy path. @@ -67,7 +67,7 @@ func TestLoadStore_ParseVersionError(t *testing.T) { kv := versioned.NewKV(make(ekv.Memstore)) obj := versioned.Object{ Version: storeVersion, - Timestamp: time.Now(), + Timestamp: netTime.Now(), Data: []byte("invalid version"), } diff --git a/storage/cmix/key.go b/storage/cmix/key.go index 3a7f6400e238f84a481a08449aaa05c02374a48a..3ab6fc084cff007e879cd541afc44dbf910ea10d 100644 --- a/storage/cmix/key.go +++ b/storage/cmix/key.go @@ -12,7 +12,7 @@ import ( "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/xx_network/primitives/id" - "time" + "gitlab.com/xx_network/primitives/netTime" ) const currentKeyVersion = 0 @@ -65,7 +65,7 @@ func loadKey(kv *versioned.KV, id *id.ID) (*key, error) { // saves the key as the key for the given node ID in the passed keystore func (k *key) save() error { - now := time.Now() + now := netTime.Now() data, err := k.marshal() if err != nil { diff --git a/storage/cmix/roundKeys_test.go b/storage/cmix/roundKeys_test.go index de839aa2a382d7713fd72ddb8873aa05eae1a583..6f69bd6628cdbe2e7bbda3a58b42adcdc01f2bce 100644 --- a/storage/cmix/roundKeys_test.go +++ b/storage/cmix/roundKeys_test.go @@ -58,23 +58,21 @@ func TestRoundKeys_Encrypt_Consistency(t *testing.T) { 208, 149, 24, 135, 165, 106, 249, 164, 122, 139, 169, 193, 39, 209, 132, 238, 23, 153, 115, 200, 104, 31} - - expectedKmacs := [][]byte{{110, 235, 79, 128, 16, 94, 181, 95, 101, - 152, 187, 204, 87, 236, 211, 102, 88, 130, 191, 103, 23, 229, - 48, 142, 155, 167, 200, 108, 66, 172, 178, 209}, - {48, 74, 148, 205, 235, 46, 172, 128, 28, 42, 116, 27, 64, 83, 122, - 5, 51, 162, 200, 198, 234, 92, 77, 131, 136, 108, 57, 97, 193, - 208, 148, 217}, - {202, 163, 19, 179, 175, 100, 71, 176, 241, 80, 85, 174, 120, 45, - 152, 117, 82, 193, 203, 188, 158, 60, 111, 217, 64, 47, 219, - 169, 100, 177, 42, 159}, - {66, 121, 20, 21, 206, 142, 3, 75, 229, 94, 197, 4, 117, 223, 245, - 117, 14, 17, 158, 138, 176, 106, 93, 55, 247, 155, 250, 232, - 41, 169, 197, 150}, - {65, 74, 222, 172, 217, 13, 56, 208, 111, 98, 199, 205, 74, 141, 30, - 109, 51, 20, 186, 9, 234, 197, 6, 200, 139, 86, 139, 130, 8, 15, - 32, 209}} - + expectedKmacs := [][]byte{{110, 235, 79, 128, 16, 94, 181, 95, 101, + 152, 187, 204, 87, 236, 211, 102, 88, 130, 191, 103, 23, 229, + 48, 142, 155, 167, 200, 108, 66, 172, 178, 209}, + {48, 74, 148, 205, 235, 46, 172, 128, 28, 42, 116, 27, 64, 83, 122, + 5, 51, 162, 200, 198, 234, 92, 77, 131, 136, 108, 57, 97, 193, + 208, 148, 217}, + {202, 163, 19, 179, 175, 100, 71, 176, 241, 80, 85, 174, 120, 45, + 152, 117, 82, 193, 203, 188, 158, 60, 111, 217, 64, 47, 219, + 169, 100, 177, 42, 159}, + {66, 121, 20, 21, 206, 142, 3, 75, 229, 94, 197, 4, 117, 223, 245, + 117, 14, 17, 158, 138, 176, 106, 93, 55, 247, 155, 250, 232, + 41, 169, 197, 150}, + {65, 74, 222, 172, 217, 13, 56, 208, 111, 98, 199, 205, 74, 141, 30, + 109, 51, 20, 186, 9, 234, 197, 6, 200, 139, 86, 139, 130, 8, 15, + 32, 209}} cmixGrp := cyclic.NewGroup( large.NewIntFromString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"+ diff --git a/storage/cmix/store.go b/storage/cmix/store.go index ad0a10cd0995abca38207dd1ea77ff5d0dc905ae..95a67d7789c3f8f35642e96ef9d81cc864f4b0cb 100644 --- a/storage/cmix/store.go +++ b/storage/cmix/store.go @@ -17,8 +17,8 @@ import ( "gitlab.com/elixxir/crypto/diffieHellman" "gitlab.com/xx_network/comms/connect" "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/netTime" "sync" - "time" ) const prefix = "cmix" @@ -110,6 +110,14 @@ func (s *Store) Add(nid *id.ID, k *cyclic.Int) { } } +// Returns if the store has the node +func (s *Store) Has(nid *id.ID) bool { + s.mux.RLock() + _, exists := s.nodes[*nid] + s.mux.RUnlock() + return exists +} + // Remove removes a node key from the nodes map and saves. func (s *Store) Remove(nid *id.ID) { s.mux.Lock() @@ -194,7 +202,7 @@ func (s *Store) Count() int { // save stores the cMix store. func (s *Store) save() error { - now := time.Now() + now := netTime.Now() data, err := s.marshal() if err != nil { diff --git a/storage/cmix/store_test.go b/storage/cmix/store_test.go index 8e05e0c39438f1b22b63ea6ff1d3f3b3648b2b73..f4dfc3a7af59ee29511a2172779c6b919ef6ec6b 100644 --- a/storage/cmix/store_test.go +++ b/storage/cmix/store_test.go @@ -70,6 +70,41 @@ func TestStore_AddRemove(t *testing.T) { } } + +// Happy path Add/Has test +func TestStore_AddHas(t *testing.T) { + // Uncomment to print keys that Set and Get are called on + // jww.SetStdoutThreshold(jww.LevelTrace) + + testStore, _ := makeTestStore() + + nodeId := id.NewIdFromString("test", id.Node, t) + key := testStore.grp.NewInt(5) + + testStore.Add(nodeId, key) + if _, exists := testStore.nodes[*nodeId]; !exists { + t.Fatal("Failed to add node key") + } + + if !testStore.Has(nodeId) { + t.Fatal("cannot find the node id that that was added") + } +} + +// Tests that has returns false when it doesnt have +func TestStore_DoesntHave(t *testing.T) { + // Uncomment to print keys that Set and Get are called on + // jww.SetStdoutThreshold(jww.LevelTrace) + + testStore, _ := makeTestStore() + + nodeId := id.NewIdFromString("test", id.Node, t) + + if testStore.Has(nodeId) { + t.Fatal("found the node when it shouldnt have been found") + } +} + // Happy path func TestLoadStore(t *testing.T) { // Uncomment to print keys that Set and Get are called on diff --git a/storage/conversation/partner.go b/storage/conversation/partner.go index 0fef58be68864181ccd18a7282f6be627b26c29f..8bad184d3c1791d2751003f692651ae7112b0854 100644 --- a/storage/conversation/partner.go +++ b/storage/conversation/partner.go @@ -13,10 +13,10 @@ import ( jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/netTime" "math" "strings" "sync" - "time" ) const ( @@ -159,7 +159,7 @@ func (c *Conversation) save() error { obj := versioned.Object{ Version: currentConversationVersion, - Timestamp: time.Now(), + Timestamp: netTime.Now(), Data: data, } diff --git a/storage/e2e/key_test.go b/storage/e2e/key_test.go index d74f53e174685483666c37150be86aef2d3a69a9..0f93e69a2818967cbfd53caaf26d034a8c224296 100644 --- a/storage/e2e/key_test.go +++ b/storage/e2e/key_test.go @@ -17,10 +17,10 @@ import ( "gitlab.com/elixxir/primitives/format" "gitlab.com/xx_network/crypto/csprng" "gitlab.com/xx_network/crypto/large" + "gitlab.com/xx_network/primitives/netTime" "math/rand" "reflect" "testing" - "time" ) // Happy path of newKey(). @@ -212,7 +212,7 @@ func getSession(t *testing.T) *Session { } func getFingerprint() *format.Fingerprint { - rand.Seed(time.Now().UnixNano()) + rand.Seed(netTime.Now().UnixNano()) fp := format.Fingerprint{} rand.Read(fp[:]) diff --git a/storage/e2e/manager.go b/storage/e2e/manager.go index b1feb294761730105b5fa70fa9f27b669c79f78a..802e81ebe2329f5bd3714500e0229071eaea3bd3 100644 --- a/storage/e2e/manager.go +++ b/storage/e2e/manager.go @@ -159,8 +159,7 @@ func (m *Manager) GetKeyForSending(st params.SendType) (*Key, error) { // GetPartnerID returns a copy of the ID of the partner. func (m *Manager) GetPartnerID() *id.ID { - p := m.partner - return p + return m.partner.DeepCopy() } // GetSendSession gets the Send session of the passed ID. Returns nil if no diff --git a/storage/e2e/manager_test.go b/storage/e2e/manager_test.go index 58b0ca6bb6c5b846abc994b8c5f43e90819be664..907bbff91b561d2267b71371356ae7bf6f332b86 100644 --- a/storage/e2e/manager_test.go +++ b/storage/e2e/manager_test.go @@ -14,10 +14,10 @@ import ( "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/ekv" "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/netTime" "math/rand" "reflect" "testing" - "time" ) // Tests happy path of newManager. @@ -234,7 +234,7 @@ func TestManager_TriggerNegotiations(t *testing.T) { // newTestManager returns a new relationship for testing. func newTestManager(t *testing.T) (*Manager, *versioned.KV) { - prng := rand.New(rand.NewSource(time.Now().UnixNano())) + prng := rand.New(rand.NewSource(netTime.Now().UnixNano())) s, ctx := makeTestSession() kv := versioned.NewKV(make(ekv.Memstore)) partnerID := id.NewIdFromUInts([4]uint64{prng.Uint64(), prng.Uint64(), diff --git a/storage/e2e/relationship.go b/storage/e2e/relationship.go index 0ff938ab6431084f70f26ba2689ed8f928f46660..6efd7081b133fae3845c83e1fbc5ecf3997da1ae 100644 --- a/storage/e2e/relationship.go +++ b/storage/e2e/relationship.go @@ -14,8 +14,8 @@ import ( "gitlab.com/elixxir/client/interfaces/params" "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/crypto/cyclic" + "gitlab.com/xx_network/primitives/netTime" "sync" - "time" ) const maxUnconfirmed uint = 3 @@ -111,7 +111,7 @@ func LoadRelationship(manager *Manager, t RelationshipType) (*relationship, erro func (r *relationship) save() error { - now := time.Now() + now := netTime.Now() data, err := r.marshal() if err != nil { @@ -219,9 +219,13 @@ func (r *relationship) getSessionForSending() *Session { var unconfirmedActive []*Session var unconfirmedRekey []*Session + jww.TRACE.Printf("[REKEY] Sessions Available: %d", len(sessions)) + for _, s := range sessions { status := s.Status() confirmed := s.IsConfirmed() + jww.TRACE.Printf("[REKEY] Session Status/Confirmed: %v, %v", + status, confirmed) if status == Active && confirmed { //always return the first confirmed active, happy path return s @@ -243,12 +247,13 @@ func (r *relationship) getSessionForSending() *Session { return unconfirmedRekey[0] } - jww.INFO.Printf("Details about %v sessions which are invalid:", len(sessions)) + jww.INFO.Printf("[REKEY] Details about %v sessions which are invalid:", len(sessions)) for i, s := range sessions { if s == nil { - jww.INFO.Printf("\tSession %v is nil", i) + jww.INFO.Printf("[REKEY]\tSession %v is nil", i) } else { - jww.INFO.Printf("\tSession %v: status: %v, confimred: %v", i, s.Status(), s.IsConfirmed()) + jww.INFO.Printf("[REKEY]\tSession %v: status: %v,"+ + " confirmed: %v", i, s.Status(), s.IsConfirmed()) } } @@ -288,17 +293,24 @@ func (r *relationship) getNewestRekeyableSession() *Session { if len(sessions) == 0 { return nil } + + var unconfirmed *Session + for _, s := range r.sessions { //fmt.Println(i) // This looks like it might not be thread safe, I think it is because // the failure mode is it skips to a lower key to rekey with, which is // always valid. It isn't clear it can fail though because we are // accessing the data in the same order it would be written (i think) - if s.Status() != RekeyEmpty && s.IsConfirmed() { - return s + if s.Status() != RekeyEmpty { + if s.IsConfirmed(){ + return s + }else if unconfirmed == nil{ + unconfirmed = s + } } } - return nil + return unconfirmed } func (r *relationship) GetByID(id SessionID) *Session { diff --git a/storage/e2e/relationshipFingerprint.go b/storage/e2e/relationshipFingerprint.go index f071e5ffb0dcf4e90e40e461338eedbf9c78fc51..a3702655319ccf0f14323d31f5b32b3fe59cb825 100644 --- a/storage/e2e/relationshipFingerprint.go +++ b/storage/e2e/relationshipFingerprint.go @@ -13,7 +13,7 @@ import ( "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/crypto/e2e" "gitlab.com/xx_network/primitives/id" - "time" + "gitlab.com/xx_network/primitives/netTime" ) func makeRelationshipFingerprint(t RelationshipType, grp *cyclic.Group, @@ -36,7 +36,7 @@ func makeRelationshipFingerprint(t RelationshipType, grp *cyclic.Group, } func storeRelationshipFingerprint(fp []byte, kv *versioned.KV) error { - now := time.Now() + now := netTime.Now() obj := versioned.Object{ Version: currentRelationshipFingerprintVersion, Timestamp: now, diff --git a/storage/e2e/relationship_test.go b/storage/e2e/relationship_test.go index df9e7be0ecc120ab445ab055808e05dcc4cbc884..49fa51de4abe7df24421ae8c91b24c09f8c10b45 100644 --- a/storage/e2e/relationship_test.go +++ b/storage/e2e/relationship_test.go @@ -14,6 +14,7 @@ import ( "gitlab.com/elixxir/ekv" "gitlab.com/xx_network/primitives/id" "reflect" + "sync" "testing" ) @@ -196,8 +197,8 @@ func TestRelationship_GetNewestRekeyableSession(t *testing.T) { sb.sessions[0].negotiationStatus = Unconfirmed // no available rekeyable sessions: nil session2 := sb.getNewestRekeyableSession() - if session2 != nil { - t.Error("newest rekeyable session should be nil") + if session2 != sb.sessions[0] { + t.Error("newest rekeyable session should be the unconfired session") } // add a rekeyable session: that session @@ -534,3 +535,40 @@ func relationshipsEqual(buff *relationship, buff2 *relationship) bool { } return true } + +func Test_relationship_getNewestRekeyableSession(t *testing.T) { + type fields struct { + manager *Manager + t RelationshipType + kv *versioned.KV + sessions []*Session + sessionByID map[SessionID]*Session + fingerprint []byte + mux sync.RWMutex + sendMux sync.Mutex + } + tests := []struct { + name string + fields fields + want *Session + }{ + // TODO: Add test cases. + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + r := &relationship{ + manager: tt.fields.manager, + t: tt.fields.t, + kv: tt.fields.kv, + sessions: tt.fields.sessions, + sessionByID: tt.fields.sessionByID, + fingerprint: tt.fields.fingerprint, + mux: tt.fields.mux, + sendMux: tt.fields.sendMux, + } + if got := r.getNewestRekeyableSession(); !reflect.DeepEqual(got, tt.want) { + t.Errorf("getNewestRekeyableSession() = %v, want %v", got, tt.want) + } + }) + } +} \ No newline at end of file diff --git a/storage/e2e/session.go b/storage/e2e/session.go index 76c614861f663ff834e22cc53e7e54c72f58d3ff..5f0344378ae7f106edd4c447904dd89cb2b6ca94 100644 --- a/storage/e2e/session.go +++ b/storage/e2e/session.go @@ -10,11 +10,6 @@ package e2e import ( "encoding/json" "fmt" - "math/big" - "sync" - "testing" - "time" - "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/interfaces/params" @@ -24,6 +19,10 @@ import ( "gitlab.com/elixxir/crypto/hash" "gitlab.com/xx_network/crypto/randomness" "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/netTime" + "math/big" + "sync" + "testing" ) const currentSessionVersion = 0 @@ -38,6 +37,8 @@ type Session struct { //params e2eParams params.E2ESessionParams + partner *id.ID + //type t RelationshipType @@ -93,6 +94,8 @@ type SessionDisk struct { // Number of keys usable before rekey RekeyThreshold uint32 + + Partner []byte } /*CONSTRUCTORS*/ @@ -116,6 +119,7 @@ func newSession(ship *relationship, t RelationshipType, myPrivKey, partnerPubKey relationshipFingerprint: relationshipFingerprint, negotiationStatus: negotiationStatus, partnerSource: trigger, + partner: ship.manager.partner.DeepCopy(), } session.kv = session.generate(ship.kv) @@ -169,12 +173,17 @@ func loadSession(ship *relationship, kv *versioned.KV, } session.relationshipFingerprint = relationshipFingerprint + if !session.partner.Cmp(ship.manager.partner){ + return nil, errors.Errorf("Stored partner (%s) did not match " + + "relationship partner (%s)", session.partner, ship.manager.partner) + } + return &session, nil } func (s *Session) save() error { - now := time.Now() + now := netTime.Now() data, err := s.marshal() if err != nil { @@ -263,7 +272,7 @@ func (s *Session) GetID() SessionID { // returns the ID of the partner for this session func (s *Session) GetPartner() *id.ID { if s.relationship != nil { - return s.relationship.manager.partner + return s.relationship.manager.partner.DeepCopy() } else { return nil } @@ -280,6 +289,7 @@ func (s *Session) marshal() ([]byte, error) { sd.PartnerPubKey = s.partnerPubKey.Bytes() sd.Trigger = s.partnerSource[:] sd.RelationshipFingerprint = s.relationshipFingerprint + sd.Partner = s.partner.Bytes() // assume in progress confirmations and session creations have failed on // reset, therefore do not store their pending progress @@ -316,6 +326,7 @@ func (s *Session) unmarshal(b []byte) error { s.negotiationStatus = Negotiation(sd.Confirmation) s.rekeyThreshold = sd.RekeyThreshold s.relationshipFingerprint = sd.RelationshipFingerprint + s.partner, _ = id.Unmarshal(sd.Partner) copy(s.partnerSource[:], sd.Trigger) s.keyState, err = loadStateVector(s.kv, "") @@ -390,12 +401,13 @@ func (s *Session) Status() Status { // from this function var legalStateChanges = [][]bool{ - {false, false, false, false, false, false}, - {true, false, true, true, false, false}, - {false, false, false, true, false, false}, - {false, false, false, false, true, false}, - {false, false, false, true, false, true}, - {false, false, false, false, false, false}, + // Unconf Sending Sent Confi NewTrig NewCreat + {false, false, false, false, false, false}, // Unc + {true, false, true, true, false, false}, // Sending + {false, false, false, true, false, false}, // Sent + {false, false, false, false, true, false}, // Confi + {false, false, false, true, false, true}, // NewTrig + {false, false, true, false, false, false}, // NewCreat } func (s *Session) SetNegotiationStatus(status Negotiation) { @@ -455,10 +467,12 @@ func (s *Session) triggerNegotiation() bool { // the checked cases will turn out to be false. s.mux.RLock() // If we've used more keys than the RekeyThreshold, it's time for a rekey - if s.keyState.GetNumUsed() >= s.rekeyThreshold && s.negotiationStatus == Confirmed { + if s.keyState.GetNumUsed() >= s.rekeyThreshold && + s.negotiationStatus < NewSessionTriggered { s.mux.RUnlock() s.mux.Lock() - if s.keyState.GetNumUsed() >= s.rekeyThreshold && s.negotiationStatus == Confirmed { + if s.keyState.GetNumUsed() >= s.rekeyThreshold && + s.negotiationStatus < NewSessionTriggered { //partnerSource a rekey to create a new session s.negotiationStatus = NewSessionTriggered // no save is make after the update because we do not want this state diff --git a/storage/e2e/session_test.go b/storage/e2e/session_test.go index 495dc39095218506a1bbe427a746b971d0998164..800cac5410e8b5236d9c89aa5ed90c36a49bc654 100644 --- a/storage/e2e/session_test.go +++ b/storage/e2e/session_test.go @@ -16,6 +16,7 @@ import ( "gitlab.com/elixxir/ekv" "gitlab.com/xx_network/crypto/csprng" "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/netTime" "reflect" "testing" "time" @@ -460,7 +461,7 @@ func TestSession_SetNegotiationStatus(t *testing.T) { // Normal paths: SetNegotiationStatus should not fail // Use timestamps to determine whether a save has occurred s.negotiationStatus = Sending - now := time.Now() + now := netTime.Now() time.Sleep(time.Millisecond) s.SetNegotiationStatus(Sent) if s.negotiationStatus != Sent { @@ -474,7 +475,7 @@ func TestSession_SetNegotiationStatus(t *testing.T) { t.Errorf("save didn't occur after switching Sending to Sent") } - now = time.Now() + now = netTime.Now() time.Sleep(time.Millisecond) s.SetNegotiationStatus(Confirmed) if s.negotiationStatus != Confirmed { @@ -488,7 +489,7 @@ func TestSession_SetNegotiationStatus(t *testing.T) { t.Errorf("save didn't occur after switching Sent to Confirmed") } - now = time.Now() + now = netTime.Now() time.Sleep(time.Millisecond) s.negotiationStatus = NewSessionTriggered s.SetNegotiationStatus(NewSessionCreated) @@ -505,7 +506,7 @@ func TestSession_SetNegotiationStatus(t *testing.T) { // Reverting paths: SetNegotiationStatus should not fail, and a save should not take place time.Sleep(time.Millisecond) - now = time.Now() + now = netTime.Now() time.Sleep(time.Millisecond) s.negotiationStatus = Sending s.SetNegotiationStatus(Unconfirmed) @@ -629,6 +630,7 @@ func makeTestSession() (*Session, *context) { manager: &Manager{ ctx: ctx, kv: kv, + partner: &id.ID{}, }, kv: kv, }, @@ -636,6 +638,7 @@ func makeTestSession() (*Session, *context) { t: Receive, negotiationStatus: Confirmed, rekeyThreshold: 5, + partner: &id.ID{}, } var err error s.keyState, err = newStateVector(s.kv, diff --git a/storage/e2e/stateVector.go b/storage/e2e/stateVector.go index 4a2e6271c0f42f65060f4416bfd7603f2a3d4d5d..10306ae562bde79a5d6382d167f83b823ccbc8df 100644 --- a/storage/e2e/stateVector.go +++ b/storage/e2e/stateVector.go @@ -13,8 +13,8 @@ import ( "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/storage/versioned" + "gitlab.com/xx_network/primitives/netTime" "sync" - "time" ) const currentStateVectorVersion = 0 @@ -79,7 +79,7 @@ func loadStateVector(kv *versioned.KV, key string) (*stateVector, error) { } func (sv *stateVector) save() error { - now := time.Now() + now := netTime.Now() data, err := sv.marshal() if err != nil { diff --git a/storage/e2e/store.go b/storage/e2e/store.go index ae06cb56b5112fa39c2812de23d69b00966e8f18..a0a427e0abbff557514b6d4197335cc75c427a69 100644 --- a/storage/e2e/store.go +++ b/storage/e2e/store.go @@ -19,8 +19,8 @@ import ( "gitlab.com/elixxir/crypto/fastRNG" "gitlab.com/elixxir/primitives/format" "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/netTime" "sync" - "time" ) const ( @@ -144,7 +144,7 @@ func LoadStore(kv *versioned.KV, myID *id.ID, rng *fastRNG.StreamGenerator) (*St } func (s *Store) save() error { - now := time.Now() + now := netTime.Now() data, err := s.marshal() if err != nil { @@ -249,16 +249,24 @@ func (s *Store) unmarshal(b []byte) error { return err } - for _, partnerID := range contacts { + for i := range contacts { + //load the contact separately to ensure pointers do not get swapped + partnerID := (&contacts[i]).DeepCopy() // Load the relationship. The relationship handles adding the fingerprints via the // context object - manager, err := loadManager(s.context, s.kv, &partnerID) + manager, err := loadManager(s.context, s.kv, partnerID) if err != nil { jww.FATAL.Panicf("Failed to load relationship for partner %s: %s", - &partnerID, err.Error()) + partnerID, err.Error()) } - s.managers[partnerID] = manager + if !manager.GetPartnerID().Cmp(partnerID){ + jww.FATAL.Panicf("Loaded a manager with the wrong partner " + + "ID: \n\t loaded: %s \n\t present: %s", + partnerID, manager.GetPartnerID()) + } + + s.managers[*partnerID] = manager } s.dhPrivateKey, err = utility.LoadCyclicKey(s.kv, privKeyKey) diff --git a/storage/partition/multiPartMessage.go b/storage/partition/multiPartMessage.go index 7dc6cbb886136577caee703337485cab0367369f..754c524702498c2c6586d54a42adedf3351a7cc5 100644 --- a/storage/partition/multiPartMessage.go +++ b/storage/partition/multiPartMessage.go @@ -17,6 +17,7 @@ import ( "gitlab.com/elixxir/crypto/e2e" "gitlab.com/elixxir/ekv" "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/netTime" "sync" "time" ) @@ -85,7 +86,7 @@ func (mpm *multiPartMessage) save() error { obj := versioned.Object{ Version: currentMultiPartMessageVersion, - Timestamp: time.Now(), + Timestamp: netTime.Now(), Data: data, } diff --git a/storage/partition/multiPartMessage_test.go b/storage/partition/multiPartMessage_test.go index ec871783b1e935a0653283102a29b7b8e7b9b939..dff3c0fabb41cffd20f714497b487ea8bcbd4644 100644 --- a/storage/partition/multiPartMessage_test.go +++ b/storage/partition/multiPartMessage_test.go @@ -15,6 +15,7 @@ import ( "gitlab.com/elixxir/crypto/e2e" "gitlab.com/elixxir/ekv" "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/netTime" "math/rand" "reflect" "testing" @@ -24,7 +25,7 @@ import ( // Tests the creation part of loadOrCreateMultiPartMessage(). func Test_loadOrCreateMultiPartMessage_Create(t *testing.T) { // Set up expected test value - prng := rand.New(rand.NewSource(time.Now().UnixNano())) + prng := rand.New(rand.NewSource(netTime.Now().UnixNano())) expectedMpm := &multiPartMessage{ Sender: id.NewIdFromUInt(prng.Uint64(), id.User, t), MessageID: prng.Uint64(), @@ -60,7 +61,7 @@ func Test_loadOrCreateMultiPartMessage_Create(t *testing.T) { // Tests the loading part of loadOrCreateMultiPartMessage(). func Test_loadOrCreateMultiPartMessage_Load(t *testing.T) { // Set up expected test value - prng := rand.New(rand.NewSource(time.Now().UnixNano())) + prng := rand.New(rand.NewSource(netTime.Now().UnixNano())) expectedMpm := &multiPartMessage{ Sender: id.NewIdFromUInt(prng.Uint64(), id.User, t), MessageID: prng.Uint64(), @@ -115,7 +116,7 @@ func CheckMultiPartMessages(expectedMpm *multiPartMessage, mpm *multiPartMessage // Tests happy path of multiPartMessage.Add(). func TestMultiPartMessage_Add(t *testing.T) { // Generate test values - prng := rand.New(rand.NewSource(time.Now().UnixNano())) + prng := rand.New(rand.NewSource(netTime.Now().UnixNano())) mpm := loadOrCreateMultiPartMessage(id.NewIdFromUInt(prng.Uint64(), id.User, t), prng.Uint64(), versioned.NewKV(make(ekv.Memstore))) partNums, parts := generateParts(prng, 0) @@ -156,13 +157,13 @@ func TestMultiPartMessage_Add(t *testing.T) { // Tests happy path of multiPartMessage.AddFirst(). func TestMultiPartMessage_AddFirst(t *testing.T) { // Generate test values - prng := rand.New(rand.NewSource(time.Now().UnixNano())) + prng := rand.New(rand.NewSource(netTime.Now().UnixNano())) expectedMpm := &multiPartMessage{ Sender: id.NewIdFromUInt(prng.Uint64(), id.User, t), MessageID: prng.Uint64(), NumParts: uint8(prng.Uint32()), PresentParts: 1, - Timestamp: time.Now(), + Timestamp: netTime.Now(), MessageType: message.NoType, parts: make([][]byte, 3), kv: versioned.NewKV(make(ekv.Memstore)), @@ -190,7 +191,7 @@ func TestMultiPartMessage_AddFirst(t *testing.T) { // Tests happy path of multiPartMessage.IsComplete(). func TestMultiPartMessage_IsComplete(t *testing.T) { // Create multiPartMessage and fill with random parts - prng := rand.New(rand.NewSource(time.Now().UnixNano())) + prng := rand.New(rand.NewSource(netTime.Now().UnixNano())) mid := prng.Uint64() mpm := loadOrCreateMultiPartMessage(id.NewIdFromUInt(prng.Uint64(), id.User, t), mid, versioned.NewKV(make(ekv.Memstore))) @@ -202,7 +203,7 @@ func TestMultiPartMessage_IsComplete(t *testing.T) { t.Error("IsComplete() returned true when NumParts == 0.") } - mpm.AddFirst(message.Text, partNums[0], 75, time.Now(), parts[0]) + mpm.AddFirst(message.Text, partNums[0], 75, netTime.Now(), parts[0]) for i := range partNums { if i > 0 { mpm.Add(partNums[i], parts[i]) @@ -237,7 +238,7 @@ func TestMultiPartMessage_IsComplete(t *testing.T) { // Tests happy path of multiPartMessage.delete(). func TestMultiPartMessage_delete(t *testing.T) { - prng := rand.New(rand.NewSource(time.Now().UnixNano())) + prng := rand.New(rand.NewSource(netTime.Now().UnixNano())) kv := versioned.NewKV(make(ekv.Memstore)) mpm := loadOrCreateMultiPartMessage(id.NewIdFromUInt(prng.Uint64(), id.User, t), prng.Uint64(), kv) diff --git a/storage/partition/part.go b/storage/partition/part.go index 66206fd4345d19ba233cfbd185f4251fb4bd74a6..9c24861ff83e732606341e1130bf041cc344c75a 100644 --- a/storage/partition/part.go +++ b/storage/partition/part.go @@ -10,7 +10,7 @@ package partition import ( "fmt" "gitlab.com/elixxir/client/storage/versioned" - "time" + "gitlab.com/xx_network/primitives/netTime" ) const currentMultiPartMessagePartVersion = 0 @@ -31,7 +31,7 @@ func savePart(kv *versioned.KV, partNum uint8, part []byte) error { obj := versioned.Object{ Version: currentMultiPartMessagePartVersion, - Timestamp: time.Now(), + Timestamp: netTime.Now(), Data: part, } diff --git a/storage/partition/part_test.go b/storage/partition/part_test.go index 22dfa11156024976b1d96c50988c464f1ec00612..b1db602f7932a505a877e8c34a54ed61173cf1ab 100644 --- a/storage/partition/part_test.go +++ b/storage/partition/part_test.go @@ -11,15 +11,15 @@ import ( "bytes" "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/ekv" + "gitlab.com/xx_network/primitives/netTime" "math/rand" "testing" - "time" ) // Tests happy path of savePart(). func Test_savePart(t *testing.T) { // Set up test values - prng := rand.New(rand.NewSource(time.Now().UnixNano())) + prng := rand.New(rand.NewSource(netTime.Now().UnixNano())) kv := versioned.NewKV(make(ekv.Memstore)) partNum := uint8(prng.Uint32()) part := make([]byte, prng.Int31n(500)) @@ -48,7 +48,7 @@ func Test_savePart(t *testing.T) { // Tests happy path of loadPart(). func Test_loadPart(t *testing.T) { // Set up test values - prng := rand.New(rand.NewSource(time.Now().UnixNano())) + prng := rand.New(rand.NewSource(netTime.Now().UnixNano())) rootKv := versioned.NewKV(make(ekv.Memstore)) partNum := uint8(prng.Uint32()) part := make([]byte, prng.Int31n(500)) @@ -56,7 +56,7 @@ func Test_loadPart(t *testing.T) { key := makeMultiPartMessagePartKey(partNum) // Save part to key value store - err := rootKv.Set(key, 0, &versioned.Object{Timestamp: time.Now(), Data: part}) + err := rootKv.Set(key, 0, &versioned.Object{Timestamp: netTime.Now(), Data: part}) if err != nil { t.Fatalf("Failed to set object: %v", err) } @@ -78,7 +78,7 @@ func Test_loadPart(t *testing.T) { // key. func Test_loadPart_NotFoundError(t *testing.T) { // Set up test values - prng := rand.New(rand.NewSource(time.Now().UnixNano())) + prng := rand.New(rand.NewSource(netTime.Now().UnixNano())) kv := versioned.NewKV(make(ekv.Memstore)) partNum := uint8(prng.Uint32()) part := make([]byte, prng.Int31n(500)) @@ -100,7 +100,7 @@ func Test_loadPart_NotFoundError(t *testing.T) { // Test happy path of deletePart(). func TestDeletePart(t *testing.T) { // Set up test values - prng := rand.New(rand.NewSource(time.Now().UnixNano())) + prng := rand.New(rand.NewSource(netTime.Now().UnixNano())) kv := versioned.NewKV(make(ekv.Memstore)) partNum := uint8(prng.Uint32()) part := make([]byte, prng.Int31n(500)) diff --git a/storage/partition/store_test.go b/storage/partition/store_test.go index c150d026d55389793dd32952b2fe209a29192e8b..9de6327d989d032e6ed987db0aff891d6be0fa3b 100644 --- a/storage/partition/store_test.go +++ b/storage/partition/store_test.go @@ -13,9 +13,9 @@ import ( "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/ekv" "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/netTime" "reflect" "testing" - "time" ) // Tests happy path of New(). @@ -40,7 +40,7 @@ func TestStore_AddFirst(t *testing.T) { s := New(versioned.NewKV(ekv.Memstore{})) msg, complete := s.AddFirst(id.NewIdFromString("User", id.User, t), - message.Text, 5, 0, 1, time.Now(), part, + message.Text, 5, 0, 1, netTime.Now(), part, []byte{0}) if !complete { @@ -60,7 +60,7 @@ func TestStore_Add(t *testing.T) { s := New(versioned.NewKV(ekv.Memstore{})) msg, complete := s.AddFirst(id.NewIdFromString("User", id.User, t), - message.Text, 5, 0, 2, time.Now(), part1, + message.Text, 5, 0, 2, netTime.Now(), part1, []byte{0}) if complete { diff --git a/storage/reception/IdentityUse.go b/storage/reception/IdentityUse.go index 37432d9d1e8ea40b6da4e92a723ae99b96353f73..93fc6b8d6c374cbf166d1a55e3c302a46192704f 100644 --- a/storage/reception/IdentityUse.go +++ b/storage/reception/IdentityUse.go @@ -2,6 +2,7 @@ package reception import ( "github.com/pkg/errors" + "gitlab.com/elixxir/client/storage/rounds" "gitlab.com/elixxir/crypto/hash" "gitlab.com/xx_network/crypto/randomness" "io" @@ -19,8 +20,8 @@ type IdentityUse struct { // Denotes if the identity is fake, in which case we do not process messages Fake bool - // rounds data - UR *UnknownRound + UR *rounds.UnknownRounds + ER *rounds.EarliestRound } // setSamplingPeriod add the Request mask as a random buffer around the sampling diff --git a/storage/reception/fake_test.go b/storage/reception/fake_test.go index 1327f84a03f6f779a63f652584fdb4e17c2cb72b..35ff0e1727a76645ef350b8d1e4a7cd5a76691e9 100644 --- a/storage/reception/fake_test.go +++ b/storage/reception/fake_test.go @@ -24,7 +24,7 @@ func Test_generateFakeIdentity(t *testing.T) { "\"EndValid\":" + string(endValid) + "," + "\"RequestMask\":86400000000000,\"Ephemeral\":true," + "\"StartRequest\":\"0001-01-01T00:00:00Z\"," + - "\"EndRequest\":\"0001-01-01T00:00:00Z\",\"Fake\":true,\"UR\":null}" + "\"EndRequest\":\"0001-01-01T00:00:00Z\",\"Fake\":true,\"UR\":null,\"ER\":null}" timestamp := time.Date(2009, 11, 17, 20, 34, 58, 651387237, time.UTC) diff --git a/storage/reception/identity.go b/storage/reception/identity.go index e4fa2556c6564226c7226689b30478e9a693493c..4c65d9696ba4a6d0fd567395a4d86e8bd9145b45 100644 --- a/storage/reception/identity.go +++ b/storage/reception/identity.go @@ -6,6 +6,7 @@ import ( "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/id/ephemeral" + "gitlab.com/xx_network/primitives/netTime" "strconv" "time" ) @@ -44,6 +45,7 @@ func loadIdentity(kv *versioned.KV) (Identity, error) { if err != nil { return Identity{}, errors.WithMessage(err, "Failed to unmarshal Identity") } + return r, nil } @@ -57,7 +59,7 @@ func (i Identity) store(kv *versioned.KV) error { // Create versioned object with data obj := &versioned.Object{ Version: identityStorageVersion, - Timestamp: time.Now(), + Timestamp: netTime.Now(), Data: regStr, } diff --git a/storage/reception/identity_test.go b/storage/reception/identity_test.go index 8499050e9e988b1a48b9e59ad8501ddd211a74c6..d80b9501486c94045209da5c99dc0b77a07306f8 100644 --- a/storage/reception/identity_test.go +++ b/storage/reception/identity_test.go @@ -5,6 +5,7 @@ import ( "gitlab.com/elixxir/ekv" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/id/ephemeral" + "gitlab.com/xx_network/primitives/netTime" "math/rand" "testing" "time" @@ -15,10 +16,10 @@ func TestIdentity_EncodeDecode(t *testing.T) { r := Identity{ EphId: ephemeral.Id{}, Source: &id.Permissioning, - End: time.Now().Round(0), + End: netTime.Now().Round(0), ExtraChecks: 12, - StartValid: time.Now().Round(0), - EndValid: time.Now().Round(0), + StartValid: netTime.Now().Round(0), + EndValid: netTime.Now().Round(0), RequestMask: 2 * time.Hour, Ephemeral: false, } @@ -44,10 +45,10 @@ func TestIdentity_Delete(t *testing.T) { r := Identity{ EphId: ephemeral.Id{}, Source: &id.Permissioning, - End: time.Now().Round(0), + End: netTime.Now().Round(0), ExtraChecks: 12, - StartValid: time.Now().Round(0), - EndValid: time.Now().Round(0), + StartValid: netTime.Now().Round(0), + EndValid: netTime.Now().Round(0), RequestMask: 2 * time.Hour, Ephemeral: false, } @@ -85,7 +86,7 @@ func TestIdentity_Equal(t *testing.T) { timestamp := time.Date(2009, 11, 17, 20, 34, 58, 651387237, time.UTC) a, _ := generateFakeIdentity(rand.New(rand.NewSource(42)), 15, timestamp) b, _ := generateFakeIdentity(rand.New(rand.NewSource(42)), 15, timestamp) - c, _ := generateFakeIdentity(rand.New(rand.NewSource(42)), 15, time.Now()) + c, _ := generateFakeIdentity(rand.New(rand.NewSource(42)), 15, netTime.Now()) if !a.Identity.Equal(b.Identity) { t.Errorf("Equal() found two equal identities as unequal."+ diff --git a/storage/reception/registration.go b/storage/reception/registration.go index 2365cdea68701671620ffe9b86eddef8e901c7a7..70647129c7c621b9a757b9d42ec82ef66f3c1bd3 100644 --- a/storage/reception/registration.go +++ b/storage/reception/registration.go @@ -2,9 +2,11 @@ package reception import ( "github.com/pkg/errors" + "gitlab.com/elixxir/client/storage/rounds" "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/id/ephemeral" + "gitlab.com/xx_network/primitives/netTime" "strconv" "time" ) @@ -13,7 +15,8 @@ const knownRoundsStorageKey = "krStorage" type registration struct { Identity - ur *UnknownRound + UR *rounds.UnknownRounds + ER *rounds.EarliestRound kv *versioned.KV } @@ -23,7 +26,7 @@ func newRegistration(reg Identity, kv *versioned.KV) (*registration, error) { reg.EndValid = reg.EndValid.Round(0) reg.End = reg.End.Round(0) - now := time.Now() + now := netTime.Now() // Do edge checks to determine if the identity is valid if now.After(reg.End) && reg.ExtraChecks < 1 { @@ -36,10 +39,14 @@ func newRegistration(reg Identity, kv *versioned.KV) (*registration, error) { r := ®istration{ Identity: reg, - ur: NewUnknownRound(!reg.Ephemeral, kv), kv: kv, } + urParams := rounds.DefaultUnknownRoundsParams() + urParams.Stored = !reg.Ephemeral + r.UR = rounds.NewUnknownRounds(kv, urParams) + r.ER = rounds.NewEarliestRound(!reg.Ephemeral, kv) + // If this is not ephemeral, then store everything if !reg.Ephemeral { // Store known rounds @@ -64,12 +71,11 @@ func loadRegistration(EphId ephemeral.Id, Source *id.ID, startValid time.Time, "for %s", regPrefix(EphId, Source, startValid)) } - ur := LoadUnknownRound(kv) - r := ®istration{ Identity: reg, - ur: ur, kv: kv, + UR: rounds.LoadUnknownRounds(kv, rounds.DefaultUnknownRoundsParams()), + ER: rounds.LoadEarliestRound(kv), } return r, nil @@ -77,7 +83,7 @@ func loadRegistration(EphId ephemeral.Id, Source *id.ID, startValid time.Time, func (r *registration) Delete() error { if !r.Ephemeral { - r.ur.delete() + r.UR.Delete() if err := r.delete(r.kv); err != nil { return errors.WithMessagef(err, "Failed to delete registration "+ "public data %s", r) diff --git a/storage/reception/registration_test.go b/storage/reception/registration_test.go index 77475258af4ef6030b222b5b58523bc82e2e530b..8e9024c46d9fdb60726498b9fb103cb2b1beddbb 100644 --- a/storage/reception/registration_test.go +++ b/storage/reception/registration_test.go @@ -3,6 +3,7 @@ package reception import ( "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/ekv" + "gitlab.com/xx_network/primitives/netTime" "math/rand" "strings" "testing" @@ -34,7 +35,7 @@ func TestNewRegistration_Ephemeral(t *testing.T) { id := idu.Identity kv := versioned.NewKV(make(ekv.Memstore)) - id.End = time.Now().Add(1 * time.Hour) + id.End = netTime.Now().Add(1 * time.Hour) id.ExtraChecks = 2 id.Ephemeral = true @@ -44,10 +45,6 @@ func TestNewRegistration_Ephemeral(t *testing.T) { "succeeded: %+v", err) } - if reg.ur == nil { - t.Error("Ephemeral identity does not have a known rounds.") - } - if _, err = reg.kv.Get(identityStorageKey, 0); err == nil { t.Error("Ephemeral identity stored the identity when it should not have.") } @@ -61,7 +58,7 @@ func TestNewRegistration_Persistent(t *testing.T) { id := idu.Identity kv := versioned.NewKV(make(ekv.Memstore)) - id.End = time.Now().Add(1 * time.Hour) + id.End = netTime.Now().Add(1 * time.Hour) id.ExtraChecks = 2 id.Ephemeral = false @@ -71,14 +68,6 @@ func TestNewRegistration_Persistent(t *testing.T) { "succeeded: %+v", err) } - if reg.ur == nil { - t.Error("Persistent identity does not have a known rounds.") - } - - // Check if the known rounds is stored, it should not be. this will panic - // if it isnt - LoadUnknownRound(reg.kv) - if _, err = reg.kv.Get(identityStorageKey, 0); err != nil { t.Errorf("Persistent identity did not store the identity when "+ "it should: %+v.", err) @@ -93,7 +82,7 @@ func TestLoadRegistration(t *testing.T) { id := idu.Identity kv := versioned.NewKV(make(ekv.Memstore)) - id.End = time.Now().Add(1 * time.Hour) + id.End = netTime.Now().Add(1 * time.Hour) id.ExtraChecks = 2 id.Ephemeral = false @@ -103,15 +92,11 @@ func TestLoadRegistration(t *testing.T) { "succeeded: %+v", err) } - reg, err := loadRegistration(idu.EphId, idu.Source, idu.StartValid, kv) + _, err = loadRegistration(idu.EphId, idu.Source, idu.StartValid, kv) if err != nil { t.Fatalf("Registration loading failed: %+v", err) } - if reg.ur == nil { - t.Error("Loading should have a UR.") - } - } // TODO: finish @@ -123,7 +108,7 @@ func Test_registration_Delete(t *testing.T) { id := idu.Identity kv := versioned.NewKV(make(ekv.Memstore)) - id.End = time.Now().Add(1 * time.Hour) + id.End = netTime.Now().Add(1 * time.Hour) id.ExtraChecks = 2 id.Ephemeral = false diff --git a/storage/reception/store.go b/storage/reception/store.go index dcf7dcb796bd1a4232d877cad825cd4b197c6939..f87ee416abaecd01e3955549080e462b3ae1e3ad 100644 --- a/storage/reception/store.go +++ b/storage/reception/store.go @@ -10,6 +10,7 @@ import ( "gitlab.com/xx_network/crypto/large" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/id/ephemeral" + "gitlab.com/xx_network/primitives/netTime" "io" "strconv" "sync" @@ -133,7 +134,7 @@ func (s *Store) save() error { // Create versioned object with data obj := &versioned.Object{ Version: receptionStoreStorageVersion, - Timestamp: time.Now(), + Timestamp: netTime.Now(), Data: data, } @@ -169,7 +170,7 @@ func (s *Store) GetIdentity(rng io.Reader) (IdentityUse, error) { s.mux.Lock() defer s.mux.Unlock() - now := time.Now() + now := netTime.Now() // Remove any now expired identities s.prune(now) @@ -307,7 +308,7 @@ func (s *Store) UpdateIdSize(idSize uint) { // Store the ID size obj := &versioned.Object{ Version: receptionIDSizeStorageVersion, - Timestamp: time.Now(), + Timestamp: netTime.Now(), Data: []byte(strconv.Itoa(s.idSize)), } @@ -379,6 +380,7 @@ func (s *Store) selectIdentity(rng io.Reader, now time.Time) (IdentityUse, error return IdentityUse{ Identity: selected.Identity, Fake: false, - UR: selected.ur, + UR: selected.UR, + ER: selected.ER, }, nil } diff --git a/storage/reception/store_test.go b/storage/reception/store_test.go index 7f5dcd089127db9939a205e2d8e6ea4733c65bf0..8779e8f54cedacd24ae9e4c892fb3b19c279b814 100644 --- a/storage/reception/store_test.go +++ b/storage/reception/store_test.go @@ -5,6 +5,7 @@ import ( "encoding/json" "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/ekv" + "gitlab.com/xx_network/primitives/netTime" "math/rand" "reflect" "testing" @@ -49,7 +50,7 @@ func TestLoadStore(t *testing.T) { // Fill active registration with fake identities for i := 0; i < 10; i++ { - testID, err := generateFakeIdentity(prng, 15, time.Now()) + testID, err := generateFakeIdentity(prng, 15, netTime.Now()) if err != nil { t.Fatalf("Failed to generate fake ID: %+v", err) } @@ -66,7 +67,6 @@ func TestLoadStore(t *testing.T) { testStore := LoadStore(kv) for i, active := range testStore.active { - s.active[i].ur = nil if !s.active[i].Equal(active.Identity) { t.Errorf("Failed to generate expected Store."+ "\nexpected: %#v\nreceived: %#v", s.active[i], active) @@ -81,7 +81,7 @@ func TestStore_save(t *testing.T) { // Fill active registration with fake identities for i := 0; i < 10; i++ { - testID, err := generateFakeIdentity(prng, 15, time.Now()) + testID, err := generateFakeIdentity(prng, 15, netTime.Now()) if err != nil { t.Fatalf("Failed to generate fake ID: %+v", err) } @@ -120,7 +120,7 @@ func TestStore_makeStoredReferences(t *testing.T) { // Fill active registration with fake identities for i := 0; i < 10; i++ { - testID, err := generateFakeIdentity(prng, 15, time.Now()) + testID, err := generateFakeIdentity(prng, 15, netTime.Now()) if err != nil { t.Fatalf("Failed to generate fake ID: %+v", err) } @@ -146,7 +146,7 @@ func TestStore_GetIdentity(t *testing.T) { kv := versioned.NewKV(make(ekv.Memstore)) s := NewStore(kv) prng := rand.New(rand.NewSource(42)) - testID, err := generateFakeIdentity(prng, 15, time.Now()) + testID, err := generateFakeIdentity(prng, 15, netTime.Now()) if err != nil { t.Fatalf("Failed to generate fake ID: %+v", err) } @@ -169,7 +169,7 @@ func TestStore_AddIdentity(t *testing.T) { kv := versioned.NewKV(make(ekv.Memstore)) s := NewStore(kv) prng := rand.New(rand.NewSource(42)) - testID, err := generateFakeIdentity(prng, 15, time.Now()) + testID, err := generateFakeIdentity(prng, 15, netTime.Now()) if err != nil { t.Fatalf("Failed to generate fake ID: %+v", err) } @@ -189,7 +189,7 @@ func TestStore_RemoveIdentity(t *testing.T) { kv := versioned.NewKV(make(ekv.Memstore)) s := NewStore(kv) prng := rand.New(rand.NewSource(42)) - testID, err := generateFakeIdentity(prng, 15, time.Now()) + testID, err := generateFakeIdentity(prng, 15, netTime.Now()) if err != nil { t.Fatalf("Failed to generate fake ID: %+v", err) } @@ -225,7 +225,7 @@ func TestStore_prune(t *testing.T) { expected := make([]*registration, runs/2) for i := 0; i < runs; i++ { - timestamp := time.Now() + timestamp := netTime.Now() if i%2 == 0 { timestamp = timestamp.Add(24 * time.Hour) } @@ -242,7 +242,7 @@ func TestStore_prune(t *testing.T) { } } - s.prune(time.Now().Add(24 * time.Hour)) + s.prune(netTime.Now().Add(24 * time.Hour)) for i, reg := range s.active { if !reg.Equal(expected[i].Identity) { @@ -260,7 +260,7 @@ func TestStore_selectIdentity(t *testing.T) { expectedReg := make([]*registration, runs) for i := 0; i < runs; i++ { - testID, err := generateFakeIdentity(prng, 15, time.Now()) + testID, err := generateFakeIdentity(prng, 15, netTime.Now()) if err != nil { t.Fatalf("Failed to generate fake ID: %+v", err) } @@ -272,7 +272,7 @@ func TestStore_selectIdentity(t *testing.T) { } for i := 0; i < runs; i++ { - idu, err := s.selectIdentity(prng, time.Now()) + idu, err := s.selectIdentity(prng, netTime.Now()) if err != nil { t.Errorf("selectIdentity() produced an error: %+v", err) } diff --git a/storage/reception/unknownRound.go b/storage/reception/unknownRound.go deleted file mode 100644 index 94feb079bf41ad2b770fa9688cf56267612a4e9a..0000000000000000000000000000000000000000 --- a/storage/reception/unknownRound.go +++ /dev/null @@ -1,97 +0,0 @@ -package reception - -import ( - "encoding/json" - jww "github.com/spf13/jwalterweatherman" - "gitlab.com/elixxir/client/storage/versioned" - "gitlab.com/xx_network/primitives/id" - "sync" - "time" -) - -const unknownRoundStorageKey = "unknownRoundStorage" -const unknownRoundStorageVersion = 0 - -type UnknownRound struct { - stored bool - kv *versioned.KV - rid id.Round - mux sync.Mutex -} - -func NewUnknownRound(stored bool, kv *versioned.KV) *UnknownRound { - ur := &UnknownRound{ - stored: stored, - kv: kv, - rid: 0, - } - ur.save() - return ur -} - -func LoadUnknownRound(kv *versioned.KV) *UnknownRound { - ur := &UnknownRound{ - stored: true, - kv: kv, - rid: 0, - } - - obj, err := kv.Get(unknownRoundStorageKey, unknownRoundStorageVersion) - if err != nil { - jww.FATAL.Panicf("Failed to get the unknown round: %+v", err) - } - - err = json.Unmarshal(obj.Data, &ur.rid) - if err != nil { - jww.FATAL.Panicf("Failed to unmarshal the unknown round: %+v", err) - } - return ur -} - -func (ur *UnknownRound) save() { - if ur.stored { - urStr, err := json.Marshal(&ur.rid) - if err != nil { - jww.FATAL.Panicf("Failed to marshal the unknown round: %+v", err) - } - - // Create versioned object with data - obj := &versioned.Object{ - Version: unknownRoundStorageVersion, - Timestamp: time.Now(), - Data: urStr, - } - - err = ur.kv.Set(unknownRoundStorageKey, - unknownRoundStorageVersion, obj) - if err != nil { - jww.FATAL.Panicf("Failed to store the unknown round: %+v", err) - } - - } -} - -func (ur *UnknownRound) Set(rid id.Round) id.Round { - ur.mux.Lock() - defer ur.mux.Unlock() - if rid > ur.rid { - ur.rid = rid - ur.save() - } - return ur.rid -} - -func (ur *UnknownRound) Get() id.Round { - ur.mux.Lock() - defer ur.mux.Unlock() - return ur.rid -} - -func (ur *UnknownRound) delete() { - ur.mux.Lock() - defer ur.mux.Unlock() - err := ur.kv.Delete(unknownRoundStorageKey, unknownRoundStorageVersion) - if err != nil { - jww.FATAL.Panicf("Failed to delete unknownRound storage: %+v", err) - } -} diff --git a/storage/regCode.go b/storage/regCode.go index 8e9533395ede948ca495b6660e8d9c4a17cdb212..da0a306d78537f1baee90e193230146f4053753d 100644 --- a/storage/regCode.go +++ b/storage/regCode.go @@ -11,7 +11,7 @@ import ( "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/storage/versioned" - "time" + "gitlab.com/xx_network/primitives/netTime" ) const regCodeKey = "regCode" @@ -23,7 +23,7 @@ func (s *Session) SetRegCode(regCode string) { &versioned.Object{ Version: regCodeVersion, Data: []byte(regCode), - Timestamp: time.Now(), + Timestamp: netTime.Now(), }); err != nil { jww.FATAL.Panicf("Failed to set the registration code: %s", err) } diff --git a/storage/regStatus.go b/storage/regStatus.go index ec18a0cfcb92aaa9c154f23528a40a96f202273f..dfb2619c810920269be39c91b2aa642bcba002ab 100644 --- a/storage/regStatus.go +++ b/storage/regStatus.go @@ -12,7 +12,7 @@ import ( "fmt" "github.com/pkg/errors" "gitlab.com/elixxir/client/storage/versioned" - "time" + "gitlab.com/xx_network/primitives/netTime" ) const currentRegistrationStatusVersion = 0 @@ -59,7 +59,7 @@ func (rs RegistrationStatus) marshalBinary() []byte { func (s *Session) newRegStatus() error { s.regStatus = NotStarted - now := time.Now() + now := netTime.Now() obj := versioned.Object{ Version: currentRegistrationStatusVersion, @@ -98,7 +98,7 @@ func (s *Session) ForwardRegistrationStatus(regStatus RegistrationStatus) error s.regStatus, regStatus) } - now := time.Now() + now := netTime.Now() obj := versioned.Object{ Version: currentRegistrationStatusVersion, diff --git a/storage/rounds/earliestRound.go b/storage/rounds/earliestRound.go new file mode 100644 index 0000000000000000000000000000000000000000..456e11c146e1998e45c3e9b814d5f718ddf99807 --- /dev/null +++ b/storage/rounds/earliestRound.go @@ -0,0 +1,99 @@ +package rounds + +import ( + "encoding/json" + jww "github.com/spf13/jwalterweatherman" + "gitlab.com/elixxir/client/storage/versioned" + "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/netTime" + "sync" +) + +const earliestRoundStorageKey = "unknownRoundStorage" +const earliestRoundStorageVersion = 0 + +type EarliestRound struct { + stored bool + kv *versioned.KV + rid id.Round + mux sync.Mutex +} + +func NewEarliestRound(stored bool, kv *versioned.KV) *EarliestRound { + ur := &EarliestRound{ + stored: stored, + kv: kv, + rid: 0, + } + ur.save() + return ur +} + +func LoadEarliestRound(kv *versioned.KV) *EarliestRound { + ur := &EarliestRound{ + stored: true, + kv: kv, + rid: 0, + } + + obj, err := kv.Get(earliestRoundStorageKey, earliestRoundStorageVersion) + if err != nil { + jww.FATAL.Panicf("Failed to get the earlest round: %+v", err) + } + + err = json.Unmarshal(obj.Data, &ur.rid) + if err != nil { + jww.FATAL.Panicf("Failed to unmarshal the earliest round: %+v", err) + } + return ur +} + +func (ur *EarliestRound) save() { + if ur.stored { + urStr, err := json.Marshal(&ur.rid) + if err != nil { + jww.FATAL.Panicf("Failed to marshal the earliest round: %+v", err) + } + + // Create versioned object with data + obj := &versioned.Object{ + Version: earliestRoundStorageVersion, + Timestamp: netTime.Now(), + Data: urStr, + } + + err = ur.kv.Set(earliestRoundStorageKey, + earliestRoundStorageVersion, obj) + if err != nil { + jww.FATAL.Panicf("Failed to store the earliest round: %+v", err) + } + + } +} + +func (ur *EarliestRound) Set(rid id.Round) (id.Round, bool) { + ur.mux.Lock() + defer ur.mux.Unlock() + changed := false + if rid > ur.rid { + changed = true + ur.rid = rid + ur.save() + } + return ur.rid, changed +} + +func (ur *EarliestRound) Get() id.Round { + ur.mux.Lock() + defer ur.mux.Unlock() + return ur.rid +} + +func (ur *EarliestRound) delete() { + ur.mux.Lock() + defer ur.mux.Unlock() + err := ur.kv.Delete(earliestRoundStorageKey, earliestRoundStorageVersion) + if err != nil { + jww.FATAL.Panicf("Failed to delete earliest storage: %+v", err) + } +} diff --git a/storage/rounds/unknownRounds.go b/storage/rounds/unknownRounds.go new file mode 100644 index 0000000000000000000000000000000000000000..3711b8787f530633a360bb91ab7911d9f8cc6830 --- /dev/null +++ b/storage/rounds/unknownRounds.go @@ -0,0 +1,199 @@ +/////////////////////////////////////////////////////////////////////////////// +// 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 ( + "encoding/json" + jww "github.com/spf13/jwalterweatherman" + "gitlab.com/elixxir/client/storage/versioned" + "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/netTime" + "sync" + "sync/atomic" +) + +const ( + unknownRoundsStorageKey = "UnknownRoundsKey" + unknownRoundsStorageVersion = 0 + unknownRoundPrefix = "UnknownRoundPrefix" + defaultMaxCheck = 3 +) + +// UnknownRounds tracks data for unknown rounds +// Should adhere to UnknownRounds interface +type UnknownRounds struct { + // Maps an unknown round to how many times the round + // has been checked + rounds map[id.Round]*uint64 + // Configurations of UnknownRoundStore + params UnknownRoundsParams + + // Key Value store to save data to disk + kv *versioned.KV + + mux sync.Mutex +} + +// Allows configuration of UnknownRounds parameters +type UnknownRoundsParams struct { + // Maximum amount of checks of a round + // before that round gets discarded + MaxChecks uint64 + //Determines if the unknown rounds is stored to disk + Stored bool +} + +// Returns a default set of UnknownRoundsParams +func DefaultUnknownRoundsParams() UnknownRoundsParams { + return UnknownRoundsParams{ + MaxChecks: defaultMaxCheck, + Stored: true, + } +} + +// Build and return new UnknownRounds object +func NewUnknownRounds(kv *versioned.KV, + params UnknownRoundsParams) *UnknownRounds { + + urs := newUnknownRounds(kv, params) + + if err := urs.save(); err != nil { + jww.FATAL.Printf("Failed to store New Unknown Rounds: %+v", err) + } + + return urs +} + +func newUnknownRounds(kv *versioned.KV, + params UnknownRoundsParams) *UnknownRounds { + // Build the UnmixedMessagesMap + // Modify the prefix of the KV + kv = kv.Prefix(unknownRoundPrefix) + + urs := &UnknownRounds{ + rounds: make(map[id.Round]*uint64), + params: params, + kv: kv, + } + + return urs +} + +// LoadUnknownRounds loads the data for a UnknownRoundStore from disk into an object +func LoadUnknownRounds(kv *versioned.KV, + params UnknownRoundsParams) *UnknownRounds { + kv = kv.Prefix(unknownRoundPrefix) + + urs := newUnknownRounds(kv, params) + + // Get the versioned data from the kv + obj, err := kv.Get(unknownRoundsStorageKey, unknownRoundsStorageVersion) + if err != nil { + jww.FATAL.Panicf("Failed to load UnknownRounds: %+v", err) + } + + // Process the data into the object + err = urs.unmarshal(obj.Data) + if err != nil { + jww.FATAL.Panicf("Failed to unmarshal UnknownRounds: %+v", err) + } + + return urs +} + +// Iterate iterates over all rounds. First it runs the +// checker function on the stored rounds: +// If true, it removes from the map and adds to the return slice +// If false, it increments the counter and if it has passed the maxChecks +// in params, it removes from the map +// Afterwards it adds the roundToAdd to the map if an entry isn't present +// Finally it saves the modified map to disk. +func (urs *UnknownRounds) Iterate(checker func(rid id.Round) bool, + roundsToAdd []id.Round) []id.Round { + returnSlice := make([]id.Round, 0) + urs.mux.Lock() + defer urs.mux.Unlock() + // Check the rounds stored + for rnd := range urs.rounds { + ok := checker(rnd) + if ok { + // If true, Append to the return list and remove from the map + returnSlice = append(returnSlice, rnd) + delete(urs.rounds, rnd) + } else { + // If false, we increment the check counter for that round + totalChecks := atomic.AddUint64(urs.rounds[rnd], 1) + + // If the round has been checked the maximum amount, + // the rond is removed from the map + if totalChecks > urs.params.MaxChecks { + delete(urs.rounds, rnd) + } + } + + } + + // Iterate over all rounds passed in + for _, rnd := range roundsToAdd { + // Process non-tracked rounds into map + if _, ok := urs.rounds[rnd]; !ok { + newCheck := uint64(0) + urs.rounds[rnd] = &newCheck + } + } + + if err := urs.save(); err != nil { + jww.FATAL.Panicf("Failed to save unknown reounds after "+ + "edit: %+v", err) + } + + return returnSlice +} + +// save stores the unknown rounds store. +func (urs *UnknownRounds) save() error { + if !urs.params.Stored { + return nil + } + now := netTime.Now() + + // Serialize the map + data, err := json.Marshal(urs.rounds) + if err != nil { + return err + } + + // Construct versioning object + obj := versioned.Object{ + Version: unknownRoundsStorageVersion, + Timestamp: now, + Data: data, + } + + // Save to disk + return urs.kv.Set(unknownRoundsStorageKey, unknownRoundsStorageVersion, &obj) +} + +// save stores the unknown rounds store. +func (urs *UnknownRounds) Delete() { + urs.mux.Lock() + defer urs.mux.Unlock() + if urs.params.Stored { + if err := urs.kv.Delete(unknownRoundPrefix, unknownRoundsStorageVersion); err != nil { + jww.FATAL.Panicf("Failed to delete unknown rounds: %+v", err) + } + } + + urs.kv = nil + urs.rounds = nil +} + +// unmarshal loads the serialized round data into the UnknownRounds map +func (urs *UnknownRounds) unmarshal(b []byte) error { + return json.Unmarshal(b, &urs.rounds) +} diff --git a/storage/rounds/unknownRounds_test.go b/storage/rounds/unknownRounds_test.go new file mode 100644 index 0000000000000000000000000000000000000000..ffc9bdd46a74060948a7a06d724cf2590d203da4 --- /dev/null +++ b/storage/rounds/unknownRounds_test.go @@ -0,0 +1,203 @@ +/////////////////////////////////////////////////////////////////////////////// +// 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" + "encoding/json" + "gitlab.com/elixxir/client/storage/versioned" + "gitlab.com/elixxir/ekv" + "gitlab.com/xx_network/primitives/id" + "reflect" + "sync/atomic" + "testing" +) + +// Happy path +func TestNewUnknownRoundsStore(t *testing.T) { + kv := versioned.NewKV(make(ekv.Memstore)) + expectedStore := &UnknownRounds{ + rounds: make(map[id.Round]*uint64), + kv: kv.Prefix(unknownRoundPrefix), + params: DefaultUnknownRoundsParams(), + } + + store := NewUnknownRounds(kv, DefaultUnknownRoundsParams()) + + // Compare manually created object with NewUnknownRoundsStore + if !reflect.DeepEqual(expectedStore, store) { + t.Errorf("NewUnknownRoundsStore() returned incorrect Store."+ + "\n\texpected: %+v\n\treceived: %+v", expectedStore, store) + } + + if err := store.save(); err != nil { + t.Fatalf("save() could not write to disk: %v", err) + } + + expectedData, err := json.Marshal(store.rounds) + if err != nil { + t.Fatalf("json.Marshal() produced an error: %v", err) + } + + key, err := store.kv.Get(unknownRoundsStorageKey, unknownRoundsStorageVersion) + if err != nil { + t.Fatalf("Get() encoutnered an error when getting Store from KV: %v", err) + } + + // Check that the stored data is the data outputted by marshal + if !bytes.Equal(expectedData, key.Data) { + t.Errorf("NewUnknownRoundsStore() returned incorrect Store."+ + "\n\texpected: %+v\n\treceived: %+v", expectedData, key.Data) + } + +} + +// Full test +func TestUnknownRoundsStore_Iterate(t *testing.T) { + kv := versioned.NewKV(make(ekv.Memstore)) + store := NewUnknownRounds(kv, DefaultUnknownRoundsParams()) + + // Return true only for rounds that are even + mockChecker := func(rid id.Round) bool { + return uint64(rid)%2 == 0 + } + + // Construct 3 lists of round IDs + roundListLen := 25 + unknownRounds := make([]id.Round, roundListLen) + roundListEven := make([]id.Round, roundListLen) + for i := 0; i < roundListLen; i++ { + // Will contain a list of round Ids in range [0,25) + unknownRounds[i] = id.Round(i) + // Will contain even round Id's in range [50,100) + roundListEven[i] = id.Round((i + roundListLen) * 2) + + } + + // Add unknown rounds to map + for _, rnd := range unknownRounds { + roundVal := uint64(0) + store.rounds[rnd] = &roundVal + } + + // Iterate over initial map + received := store.Iterate(mockChecker, nil) + + // Check the received list for 2 conditions: + // a) that returned rounds are no longer in the map + // b) that returned round Ids are even (as per our checker) + for _, rnd := range received { + // Our returned list should contain only even rounds. + if uint64(rnd)%2 != 0 { + t.Errorf("Unexpected result from iterate(). "+ + "Round %d should not be in received list", rnd) + } + // Elements in the returned list should be deleted from the map. + if _, ok := store.rounds[rnd]; ok { + t.Errorf("Returned rounds from iterate should be removed from map"+ + "\n\tFound round %d in map", rnd) + } + + } + + // Add even round list to map + received = store.Iterate(mockChecker, roundListEven) + + if len(received) != 0 { + t.Errorf("Second iteration should return an empty list (no even rounds are left)."+ + "\n\tReturned: %v", received) + } + + // Iterate over map until all rounds have checks incremented over + // maxCheck + for i := 0; i < defaultMaxCheck+1; i++ { + _ = store.Iterate(mockChecker,[]id.Round{}) + + } + + // Check map has been cleared out + if len(store.rounds) != 0 { + t.Errorf("Map should be empty after %d iterations", defaultMaxCheck) + } +} + +// Unit test +func TestLoadUnknownRoundsStore(t *testing.T) { + kv := versioned.NewKV(make(ekv.Memstore)) + store := NewUnknownRounds(kv, DefaultUnknownRoundsParams()) + + // Construct 3 lists of round IDs + roundListLen := 25 + expectedRounds := make([]id.Round, roundListLen) + for i := 0; i < roundListLen; i++ { + // Will contain a list of round Ids in range [0,25) + expectedRounds[i] = id.Round(i) + + } + + // Add unknown rounds to map + expectedCheckVal := 0 + for _, rnd := range expectedRounds { + roundVal := uint64(expectedCheckVal) + store.rounds[rnd] = &roundVal + } + + if err := store.save(); err != nil { + t.Fatalf("save produced an error: %v", err) + } + + // Load the store from kv + receivedStore := LoadUnknownRounds(kv, DefaultUnknownRoundsParams()) + + // Check the state of the map of the loaded store + for _, rnd := range expectedRounds { + check, ok := receivedStore.rounds[rnd] + if !ok { + t.Fatalf("Expected round %d in loaded store", rnd) + } + + if atomic.LoadUint64(check) != 0 { + t.Fatalf("Loaded value in map is unexpected."+ + "\n\tExpected: %v"+ + "\n\tReceived: %v", expectedCheckVal, atomic.LoadUint64(check)) + } + } + + /* Check save used in iterate call */ + + // Check that LoadStore works after iterate call (which implicitly saves) + mockChecker := func(round id.Round) bool { return false } + received := store.Iterate(mockChecker, nil) + + // Iterate is being called as a dummy, should not return anything + if len(received) != 0 { + t.Fatalf("Returned list from iterate should not return any rounds."+ + "\n\tReceived: %v", received) + } + + // Increment check value (iterate will increment all rounds' checked value) + expectedCheckVal++ + + // Load the store from kv + receivedStore = LoadUnknownRounds(kv, DefaultUnknownRoundsParams()) + + // Check the state of the map of the loaded store + for _, rnd := range expectedRounds { + check, ok := receivedStore.rounds[rnd] + if !ok { + t.Fatalf("Expected round %d in loaded store", rnd) + } + + if atomic.LoadUint64(check) != uint64(expectedCheckVal) { + t.Fatalf("Loaded value in map is unexpected."+ + "\n\tExpected: %v"+ + "\n\tReceived: %v", expectedCheckVal, atomic.LoadUint64(check)) + } + } + +} diff --git a/storage/session.go b/storage/session.go index be1837de7fb32adf9d13549c8f42bfe00683c05f..608068472b49517922d6a84a8a57d90f9dc0054f 100644 --- a/storage/session.go +++ b/storage/session.go @@ -363,5 +363,6 @@ func InitTestingSession(i interface{}) *Session { s.partition = partition.New(s.kv) s.reception = reception.NewStore(s.kv) + return s } diff --git a/storage/session_test.go b/storage/session_test.go index 7b0d5ebc78c3f888d800d0506169f65a64c289f4..73fe66a252cabc444a9c6c325f9c582dff7d1705 100644 --- a/storage/session_test.go +++ b/storage/session_test.go @@ -27,7 +27,7 @@ func TestSession_Smoke(t *testing.T) { err := s.Set("testkey", &versioned.Object{ Version: 0, - Timestamp: time.Now(), + Timestamp: netTime.Now(), Data: []byte("test"), }) if err != nil { diff --git a/storage/user/cryptographic.go b/storage/user/cryptographic.go index c01b6ffa1bc1e835f2cae169f678de566b572778..592fc9c2322d3f8552d3e0ebc5f721cd292ed384 100644 --- a/storage/user/cryptographic.go +++ b/storage/user/cryptographic.go @@ -15,7 +15,7 @@ import ( "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/xx_network/crypto/signature/rsa" "gitlab.com/xx_network/primitives/id" - "time" + "gitlab.com/xx_network/primitives/netTime" ) const currentCryptographicIdentityVersion = 0 @@ -112,7 +112,7 @@ func (ci *CryptographicIdentity) save(kv *versioned.KV) error { obj := &versioned.Object{ Version: currentCryptographicIdentityVersion, - Timestamp: time.Now(), + Timestamp: netTime.Now(), Data: userDataBuffer.Bytes(), } diff --git a/storage/user/regValidationSig.go b/storage/user/regValidationSig.go index 4b5e09957e1597c899628fcecc58b0913afb575a..7440500fc680e2aee821ac761f47c8d9b201f40a 100644 --- a/storage/user/regValidationSig.go +++ b/storage/user/regValidationSig.go @@ -10,7 +10,7 @@ package user import ( jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/storage/versioned" - "time" + "gitlab.com/xx_network/primitives/netTime" ) const currentRegValidationSigVersion = 0 @@ -68,7 +68,7 @@ func (u *User) SetTransmissionRegistrationValidationSignature(b []byte) { obj := &versioned.Object{ Version: currentRegValidationSigVersion, - Timestamp: time.Now(), + Timestamp: netTime.Now(), Data: b, } @@ -95,7 +95,7 @@ func (u *User) SetReceptionRegistrationValidationSignature(b []byte) { obj := &versioned.Object{ Version: currentRegValidationSigVersion, - Timestamp: time.Now(), + Timestamp: netTime.Now(), Data: b, } diff --git a/storage/user/regValidationSig_test.go b/storage/user/regValidationSig_test.go index c824ad8891075f71a7d9bbd5e90ab1ac91bb1263..68a69f60c8a8dca24161a4ec8bc9721d096aa6a9 100644 --- a/storage/user/regValidationSig_test.go +++ b/storage/user/regValidationSig_test.go @@ -13,8 +13,8 @@ import ( "gitlab.com/elixxir/ekv" "gitlab.com/xx_network/crypto/signature/rsa" "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/netTime" "testing" - "time" ) // Test User GetRegistrationValidationSignature function @@ -109,7 +109,7 @@ func TestUser_loadRegistrationValidationSignature(t *testing.T) { err = kv.Set(transmissionRegValidationSigKey, currentRegValidationSigVersion, &versioned.Object{ Version: currentRegValidationSigVersion, - Timestamp: time.Now(), + Timestamp: netTime.Now(), Data: sig, }) if err != nil { @@ -125,7 +125,7 @@ func TestUser_loadRegistrationValidationSignature(t *testing.T) { err = kv.Set(receptionRegValidationSigKey, currentRegValidationSigVersion, &versioned.Object{ Version: currentRegValidationSigVersion, - Timestamp: time.Now(), + Timestamp: netTime.Now(), Data: sig, }) if err != nil { diff --git a/storage/user/username.go b/storage/user/username.go index 268025e2ea728645a3124165c0cd30f368a93942..c36e0eba99883f5d735d4aeb2e557848f8ff4180 100644 --- a/storage/user/username.go +++ b/storage/user/username.go @@ -11,7 +11,7 @@ import ( "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/storage/versioned" - "time" + "gitlab.com/xx_network/primitives/netTime" ) const currentUsernameVersion = 0 @@ -35,7 +35,7 @@ func (u *User) SetUsername(username string) error { obj := &versioned.Object{ Version: currentUsernameVersion, - Timestamp: time.Now(), + Timestamp: netTime.Now(), Data: []byte(username), } diff --git a/storage/user/username_test.go b/storage/user/username_test.go index 1da1ce0eb9dc96a8d85b965bbdb867bdc36846fe..7571d3804136b560f5730b76d69b5672cd6d5c48 100644 --- a/storage/user/username_test.go +++ b/storage/user/username_test.go @@ -12,8 +12,8 @@ import ( "gitlab.com/elixxir/ekv" "gitlab.com/xx_network/crypto/signature/rsa" "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/netTime" "testing" - "time" ) // Test normal function and errors for User's SetUsername function @@ -94,7 +94,7 @@ func TestUser_loadUsername(t *testing.T) { err = u.kv.Set(usernameKey, currentUsernameVersion, &versioned.Object{ Version: currentUsernameVersion, - Timestamp: time.Now(), + Timestamp: netTime.Now(), Data: []byte(u1), }) u.loadUsername() diff --git a/storage/utility/NDF.go b/storage/utility/NDF.go index 728ec90c9fcf12db993e25b5566203c98783dbf4..e4e6281b26ed92c6466a8afaa9cbec7375ed5107 100644 --- a/storage/utility/NDF.go +++ b/storage/utility/NDF.go @@ -10,7 +10,7 @@ package utility import ( "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/xx_network/primitives/ndf" - "time" + "gitlab.com/xx_network/primitives/netTime" ) const currentNDFVersion = 0 @@ -35,7 +35,7 @@ func SaveNDF(kv *versioned.KV, key string, ndf *ndf.NetworkDefinition) error { return err } - now := time.Now() + now := netTime.Now() obj := versioned.Object{ Version: currentNDFVersion, diff --git a/storage/utility/cmixMessageBuffer.go b/storage/utility/cmixMessageBuffer.go index 367d4fd534bad871472590ecf5ecf4fd7c017f95..6091c65bc59ee0836384d4a475a15f8c8f7a940e 100644 --- a/storage/utility/cmixMessageBuffer.go +++ b/storage/utility/cmixMessageBuffer.go @@ -15,7 +15,7 @@ import ( "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/primitives/format" "gitlab.com/xx_network/primitives/id" - "time" + "gitlab.com/xx_network/primitives/netTime" ) const currentCmixMessageVersion = 0 @@ -45,7 +45,7 @@ func (cmh *cmixMessageHandler) SaveMessage(kv *versioned.KV, m interface{}, key // Create versioned object obj := versioned.Object{ Version: currentCmixMessageVersion, - Timestamp: time.Now(), + Timestamp: netTime.Now(), Data: sm.Marshal(), } diff --git a/storage/utility/cmixMessageBuffer_test.go b/storage/utility/cmixMessageBuffer_test.go index f884d73d78629dbc51e88ce5443dfee8f3bde66e..b015cb2c66f028be8472b3281603f0b9e026b335 100644 --- a/storage/utility/cmixMessageBuffer_test.go +++ b/storage/utility/cmixMessageBuffer_test.go @@ -13,10 +13,10 @@ import ( "gitlab.com/elixxir/ekv" "gitlab.com/elixxir/primitives/format" "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/netTime" "math/rand" "reflect" "testing" - "time" ) // Test happy path of cmixMessageHandler.SaveMessage(). @@ -159,7 +159,7 @@ func TestCmixMessageBuffer_Smoke(t *testing.T) { // expected map after they are added to the buffer. func makeTestCmixMessages(n int) ([]format.Message, []*id.ID, map[MessageHash]struct{}) { cmh := &cmixMessageHandler{} - prng := rand.New(rand.NewSource(time.Now().UnixNano())) + prng := rand.New(rand.NewSource(netTime.Now().UnixNano())) mh := map[MessageHash]struct{}{} msgs := make([]format.Message, n) ids := make([]*id.ID, n) diff --git a/storage/utility/contact.go b/storage/utility/contact.go index cef79e2ffc8748798908cfcedd87a3e96c0c0e7e..cccfef3483c47fc83579563e29b18e0578a17610 100644 --- a/storage/utility/contact.go +++ b/storage/utility/contact.go @@ -9,16 +9,16 @@ package utility import ( "fmt" - "gitlab.com/elixxir/client/interfaces/contact" "gitlab.com/elixxir/client/storage/versioned" + "gitlab.com/elixxir/crypto/contact" "gitlab.com/xx_network/primitives/id" - "time" + "gitlab.com/xx_network/primitives/netTime" ) const currentContactVersion = 0 func StoreContact(kv *versioned.KV, c contact.Contact) error { - now := time.Now() + now := netTime.Now() obj := versioned.Object{ Version: currentContactVersion, diff --git a/storage/utility/dh.go b/storage/utility/dh.go index ea2f6296d1289378189c4e4d85e6c344b9715aa1..9b0280ed1ef4bd96e71d15fcc788b5633c51fe03 100644 --- a/storage/utility/dh.go +++ b/storage/utility/dh.go @@ -10,13 +10,13 @@ package utility import ( "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/crypto/cyclic" - "time" + "gitlab.com/xx_network/primitives/netTime" ) const currentCyclicVersion = 0 func StoreCyclicKey(kv *versioned.KV, cy *cyclic.Int, key string) error { - now := time.Now() + now := netTime.Now() data, err := cy.GobEncode() if err != nil { diff --git a/storage/utility/e2eMessageBuffer.go b/storage/utility/e2eMessageBuffer.go index 9f0d3f417e6fd9c84e66c71dc324d13df31cf0ac..b8de8f65d3219f662df87680d174aec47743b97f 100644 --- a/storage/utility/e2eMessageBuffer.go +++ b/storage/utility/e2eMessageBuffer.go @@ -16,8 +16,7 @@ import ( "gitlab.com/elixxir/client/interfaces/params" "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/xx_network/primitives/id" - - "time" + "gitlab.com/xx_network/primitives/netTime" ) const currentE2EMessageVersion = 0 @@ -44,7 +43,7 @@ func (emh *e2eMessageHandler) SaveMessage(kv *versioned.KV, m interface{}, key s // Create versioned object obj := versioned.Object{ Version: currentE2EMessageVersion, - Timestamp: time.Now(), + Timestamp: netTime.Now(), Data: b, } diff --git a/storage/utility/e2eMessageBuffer_test.go b/storage/utility/e2eMessageBuffer_test.go index aa7366ced5e5964fc666b67b3015f34a46433d4c..0aca79126fe53903957780f298e26ae1434597db 100644 --- a/storage/utility/e2eMessageBuffer_test.go +++ b/storage/utility/e2eMessageBuffer_test.go @@ -14,10 +14,10 @@ import ( "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/ekv" "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/netTime" "math/rand" "reflect" "testing" - "time" ) // Test happy path of e2eMessageHandler.SaveMessage(). @@ -155,7 +155,7 @@ func TestE2EMessageHandler_Smoke(t *testing.T) { // makeTestE2EMessages creates a list of messages with random data and the // expected map after they are added to the buffer. func makeTestE2EMessages(n int, t *testing.T) ([]e2eMessage, []message.Send) { - prng := rand.New(rand.NewSource(time.Now().UnixNano())) + prng := rand.New(rand.NewSource(netTime.Now().UnixNano())) msgs := make([]e2eMessage, n) send := make([]message.Send, n) for i := range msgs { diff --git a/storage/utility/group.go b/storage/utility/group.go index 20a05e8378fde158a0ec6b1b6009a6f9f68ebc55..2b2e40678cbdd7f7f004ce86a15965c346d7e042 100644 --- a/storage/utility/group.go +++ b/storage/utility/group.go @@ -10,13 +10,13 @@ package utility import ( "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/crypto/cyclic" - "time" + "gitlab.com/xx_network/primitives/netTime" ) const currentGroupVersion = 0 func StoreGroup(kv *versioned.KV, grp *cyclic.Group, key string) error { - now := time.Now() + now := netTime.Now() data, err := grp.GobEncode() if err != nil { diff --git a/storage/utility/knownRounds.go b/storage/utility/knownRounds.go index 5b57c29484b91570abd93d7149ed0e91ccd9e651..85203145b7fead0131b3c861539c2c89cabd475b 100644 --- a/storage/utility/knownRounds.go +++ b/storage/utility/knownRounds.go @@ -61,7 +61,7 @@ func LoadKnownRounds(kv *versioned.KV, key string, size int) (*KnownRounds, erro // save saves the round buffer as a versioned object to the key value store. func (kr *KnownRounds) save() error { - now := time.Now() + now := netTime.Now() // Marshal list of rounds data, err := kr.rounds.Marshal() diff --git a/storage/utility/messageBuffer.go b/storage/utility/messageBuffer.go index 59743c855072ec9343ecd6460c4e1044af2d45f5..31af9f7f2a9b472873d476a686321a33145b2b42 100644 --- a/storage/utility/messageBuffer.go +++ b/storage/utility/messageBuffer.go @@ -8,12 +8,13 @@ package utility import ( + "encoding/base64" "encoding/json" jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/primitives/format" + "gitlab.com/xx_network/primitives/netTime" "sync" - "time" ) // MessageHash stores the hash of a message, which is used as the key for each @@ -105,7 +106,7 @@ func LoadMessageBuffer(kv *versioned.KV, handler MessageHandler, // are in the "not processed" or "processing" state are stored together and // considered "not processed". func (mb *MessageBuffer) save() error { - now := time.Now() + now := netTime.Now() // Build a combined list of message hashes in messages + processingMessages allMessages := mb.getMessageList() @@ -207,6 +208,8 @@ func (mb *MessageBuffer) Add(m interface{}) { // Add adds a message to the buffer in "processing" state. func (mb *MessageBuffer) AddProcessing(m interface{}) { h := mb.handler.HashMessage(m) + jww.TRACE.Printf("Critical Messages AddProcessing(%s)", + base64.StdEncoding.EncodeToString(h[:])) mb.mux.Lock() defer mb.mux.Unlock() @@ -247,6 +250,9 @@ func (mb *MessageBuffer) Next() (interface{}, bool) { // Pop the next MessageHash from the "not processing" list h := next(mb.messages) + jww.TRACE.Printf("Critical Messages Next returned %s", + base64.StdEncoding.EncodeToString(h[:])) + delete(mb.messages, h) // Add message to list of processing messages @@ -272,6 +278,8 @@ func next(msgMap map[MessageHash]struct{}) MessageHash { // Remove sets a messaged as processed and removed it from the buffer. func (mb *MessageBuffer) Succeeded(m interface{}) { h := mb.handler.HashMessage(m) + jww.TRACE.Printf("Critical Messages Succeeded(%s)", + base64.StdEncoding.EncodeToString((h[:]))) mb.mux.Lock() defer mb.mux.Unlock() @@ -297,6 +305,8 @@ func (mb *MessageBuffer) Succeeded(m interface{}) { // the "not processed" state. func (mb *MessageBuffer) Failed(m interface{}) { h := mb.handler.HashMessage(m) + jww.TRACE.Printf("Critical Messages Failed(%s)", + base64.StdEncoding.EncodeToString(h[:])) mb.mux.Lock() defer mb.mux.Unlock() diff --git a/storage/utility/messageBuffer_test.go b/storage/utility/messageBuffer_test.go index f331078fd5429a81c317620caf28802932617ba6..fc4de8be8dd5573520d02c9a35fae07593bb6a90 100644 --- a/storage/utility/messageBuffer_test.go +++ b/storage/utility/messageBuffer_test.go @@ -13,11 +13,11 @@ import ( "encoding/json" "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/ekv" + "gitlab.com/xx_network/primitives/netTime" "math/rand" "os" "reflect" "testing" - "time" ) type testHandler struct { @@ -294,7 +294,7 @@ func TestMessageBuffer_Failed(t *testing.T) { // addTestMessages adds random messages to the buffer. func addTestMessages(mb *MessageBuffer, n int) []MessageHash { - prng := rand.New(rand.NewSource(time.Now().UnixNano())) + prng := rand.New(rand.NewSource(netTime.Now().UnixNano())) msgs := make([]MessageHash, n) for i := 0; i < n; i++ { keyData := make([]byte, 16) @@ -337,7 +337,7 @@ func cmpMessageHash(arrA, arrB []MessageHash) bool { // makeTestMessages creates a list of messages with random data and the expected // map after they are added to the buffer. func makeTestMessages(n int) ([][]byte, map[MessageHash]struct{}) { - prng := rand.New(rand.NewSource(time.Now().UnixNano())) + prng := rand.New(rand.NewSource(netTime.Now().UnixNano())) mh := map[MessageHash]struct{}{} msgs := make([][]byte, n) for i := range msgs { diff --git a/storage/utility/meteredCmixMessageBuffer.go b/storage/utility/meteredCmixMessageBuffer.go index e4b7ab4fbce6e5e97cf00c8fcadb0d130f13167e..719faa3883ebf6d47e5abf86931c3e9e1b8e0143 100644 --- a/storage/utility/meteredCmixMessageBuffer.go +++ b/storage/utility/meteredCmixMessageBuffer.go @@ -14,6 +14,7 @@ import ( jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/primitives/format" + "gitlab.com/xx_network/primitives/netTime" "time" ) @@ -40,7 +41,7 @@ func (*meteredCmixMessageHandler) SaveMessage(kv *versioned.KV, m interface{}, k // Create versioned object obj := versioned.Object{ Version: currentMeteredCmixMessageVersion, - Timestamp: time.Now(), + Timestamp: netTime.Now(), Data: marshaled, } @@ -111,7 +112,7 @@ func (mcmb *MeteredCmixMessageBuffer) Add(m format.Message) { msg := meteredCmixMessage{ M: m.Marshal(), Count: 0, - Timestamp: time.Now(), + Timestamp: netTime.Now(), } mcmb.mb.Add(msg) } @@ -120,7 +121,7 @@ func (mcmb *MeteredCmixMessageBuffer) AddProcessing(m format.Message) { msg := meteredCmixMessage{ M: m.Marshal(), Count: 0, - Timestamp: time.Now(), + Timestamp: netTime.Now(), } mcmb.mb.AddProcessing(msg) } diff --git a/storage/utility/meteredCmixMessageBuffer_test.go b/storage/utility/meteredCmixMessageBuffer_test.go index bd2edcd259cb1bff0b04068d6c5fa8600fb16d82..a8116a7235dd7f64c701d04d3e655bef2237bc5a 100644 --- a/storage/utility/meteredCmixMessageBuffer_test.go +++ b/storage/utility/meteredCmixMessageBuffer_test.go @@ -13,6 +13,7 @@ import ( "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/ekv" "gitlab.com/elixxir/primitives/format" + "gitlab.com/xx_network/primitives/netTime" "math/rand" "testing" "time" @@ -188,7 +189,7 @@ func Test_meteredCmixMessageHandler_Smoke(t *testing.T) { // expected map after they are added to the buffer. func makeTestMeteredCmixMessage(n int) ([]meteredCmixMessage, map[MessageHash]struct{}) { mcmh := &meteredCmixMessageHandler{} - prng := rand.New(rand.NewSource(time.Now().UnixNano())) + prng := rand.New(rand.NewSource(netTime.Now().UnixNano())) mh := map[MessageHash]struct{}{} msgs := make([]meteredCmixMessage, n) for i := range msgs { @@ -207,7 +208,7 @@ func makeTestMeteredCmixMessage(n int) ([]meteredCmixMessage, map[MessageHash]st // makeTestFormatMessages creates a list of messages with random data. func makeTestFormatMessages(n int) []format.Message { - prng := rand.New(rand.NewSource(time.Now().UnixNano())) + prng := rand.New(rand.NewSource(netTime.Now().UnixNano())) msgs := make([]format.Message, n) for i := range msgs { msgs[i] = format.NewMessage(128) diff --git a/storage/versioned/kv_test.go b/storage/versioned/kv_test.go index 58ec70ad4f77972a326d089df74263e7aeae80fb..393078152ab91f82045108c0eee3fa5f4706ed66 100644 --- a/storage/versioned/kv_test.go +++ b/storage/versioned/kv_test.go @@ -10,10 +10,9 @@ package versioned import ( "bytes" "errors" - "testing" - "time" - "gitlab.com/elixxir/ekv" + "gitlab.com/xx_network/primitives/netTime" + "testing" ) // KV Get should call the Upgrade function when it's available @@ -40,7 +39,7 @@ func TestVersionedKV_GetUpgrade(t *testing.T) { key := vkv.GetFullKey("test", 0) original := Object{ Version: 0, - Timestamp: time.Now(), + Timestamp: netTime.Now(), Data: []byte("not upgraded"), } originalSerialized := original.Marshal() @@ -49,7 +48,7 @@ func TestVersionedKV_GetUpgrade(t *testing.T) { upgrade := []Upgrade{func(oldObject *Object) (*Object, error) { return &Object{ Version: 1, - Timestamp: time.Now(), + Timestamp: netTime.Now(), Data: []byte("this object was upgraded from v0 to v1"), }, nil }} @@ -77,7 +76,7 @@ func TestVersionedKV_GetUpgrade_KeyNotFound(t *testing.T) { upgrade := []Upgrade{func(oldObject *Object) (*Object, error) { return &Object{ Version: 1, - Timestamp: time.Now(), + Timestamp: netTime.Now(), Data: []byte("this object was upgraded from v0 to v1"), }, nil }} @@ -97,7 +96,7 @@ func TestVersionedKV_GetUpgrade_UpgradeReturnsError(t *testing.T) { key := vkv.GetFullKey("test", 0) original := Object{ Version: 0, - Timestamp: time.Now(), + Timestamp: netTime.Now(), Data: []byte("not upgraded"), } originalSerialized := original.Marshal() @@ -125,7 +124,7 @@ func TestVersionedKV_Delete(t *testing.T) { key := vkv.GetFullKey("test", 0) original := Object{ Version: 0, - Timestamp: time.Now(), + Timestamp: netTime.Now(), Data: []byte("not upgraded"), } originalSerialized := original.Marshal() @@ -151,7 +150,7 @@ func TestVersionedKV_Get(t *testing.T) { key := vkv.GetFullKey("test", originalVersion) original := Object{ Version: originalVersion, - Timestamp: time.Now(), + Timestamp: netTime.Now(), Data: []byte("not upgraded"), } originalSerialized := original.Marshal() @@ -176,7 +175,7 @@ func TestVersionedKV_Set(t *testing.T) { key := vkv.GetFullKey("test", originalVersion) original := Object{ Version: originalVersion, - Timestamp: time.Now(), + Timestamp: netTime.Now(), Data: []byte("not upgraded"), } err := vkv.Set("test", originalVersion, &original) diff --git a/ud/lookup.go b/ud/lookup.go index d7ce0fa69f2addc3bb09419f98ec60b3a6cc2985..e7bdb0da0c0ed10bc8ccaa15c79bc6b9c30b8a9e 100644 --- a/ud/lookup.go +++ b/ud/lookup.go @@ -5,7 +5,7 @@ import ( "github.com/golang/protobuf/proto" "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" - "gitlab.com/elixxir/client/interfaces/contact" + "gitlab.com/elixxir/crypto/contact" "gitlab.com/xx_network/primitives/id" "time" ) diff --git a/ud/lookup_test.go b/ud/lookup_test.go index 413b85f9d0443411977557937dfd74cee8833d63..8bdb21a1ae0d347b8561da54a52d4c9dcf7bb33e 100644 --- a/ud/lookup_test.go +++ b/ud/lookup_test.go @@ -3,9 +3,9 @@ package ud import ( "github.com/golang/protobuf/proto" "github.com/pkg/errors" - "gitlab.com/elixxir/client/interfaces/contact" "gitlab.com/elixxir/client/single" "gitlab.com/elixxir/client/stoppable" + "gitlab.com/elixxir/crypto/contact" "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/xx_network/crypto/large" "gitlab.com/xx_network/primitives/id" diff --git a/ud/manager.go b/ud/manager.go index d38c5aa5b7f2490e75fc502dd89c131c2faad94a..842d8d353a6d05ab523db2f887c2036d169f976c 100644 --- a/ud/manager.go +++ b/ud/manager.go @@ -5,11 +5,11 @@ import ( jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/api" "gitlab.com/elixxir/client/interfaces" - "gitlab.com/elixxir/client/interfaces/contact" "gitlab.com/elixxir/client/single" "gitlab.com/elixxir/client/stoppable" "gitlab.com/elixxir/client/storage" "gitlab.com/elixxir/comms/client" + "gitlab.com/elixxir/crypto/contact" "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/crypto/fastRNG" "gitlab.com/xx_network/comms/connect" diff --git a/ud/registered.go b/ud/registered.go index 8191f2667246b8936a098eac688c49d2c2ae2be5..d81e615894e6928f5e7a529cf10c2ca288f21e04 100644 --- a/ud/registered.go +++ b/ud/registered.go @@ -5,8 +5,8 @@ import ( "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/storage/versioned" + "gitlab.com/xx_network/primitives/netTime" "sync/atomic" - "time" ) const isRegisteredKey = "isRegisteredKey" @@ -44,7 +44,7 @@ func (m *Manager) setRegistered() error { obj := &versioned.Object{ Version: isRegisteredVersion, - Timestamp: time.Now(), + Timestamp: netTime.Now(), Data: data, } diff --git a/ud/search.go b/ud/search.go index 5367fe10c5d65b22814a799f6071584ffeca8e24..8624c778d1be0d6f8443b6fe0ca13153ac82c429 100644 --- a/ud/search.go +++ b/ud/search.go @@ -4,7 +4,7 @@ import ( "github.com/golang/protobuf/proto" "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" - "gitlab.com/elixxir/client/interfaces/contact" + "gitlab.com/elixxir/crypto/contact" "gitlab.com/elixxir/crypto/factID" "gitlab.com/elixxir/primitives/fact" "gitlab.com/xx_network/primitives/id" diff --git a/ud/search_test.go b/ud/search_test.go index bbbb65c0d517f8abaa09df06628a5acecd663e27..ac14e1a63243fc4d0296768c23420cf1adc03f16 100644 --- a/ud/search_test.go +++ b/ud/search_test.go @@ -4,9 +4,9 @@ import ( "fmt" "github.com/golang/protobuf/proto" errors "github.com/pkg/errors" - "gitlab.com/elixxir/client/interfaces/contact" "gitlab.com/elixxir/client/single" "gitlab.com/elixxir/client/stoppable" + "gitlab.com/elixxir/crypto/contact" "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/crypto/factID" "gitlab.com/elixxir/primitives/fact"