diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ec567c930ca36acff12a23f223f1bcc45dd5e4d6..939c429d956d80ba7afb9d650f9b4cacf6d4df3d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -4,7 +4,7 @@ variables: REPO_DIR: gitlab.com/elixxir REPO_NAME: client DOCKER_IMAGE: elixxirlabs/cuda-go:latest - MIN_CODE_COVERAGE: "75" + MIN_CODE_COVERAGE: "74" before_script: ## @@ -21,7 +21,7 @@ before_script: - ssh-keyscan -t rsa gitlab.com > ~/.ssh/known_hosts - git config --global url."git@gitlab.com:".insteadOf "https://gitlab.com/" - export PATH=$HOME/go/bin:$PATH - - export GOPRIVATE=gitlab.com/elixxir/* + - export GOPRIVATE=gitlab.com/elixxir/*,gitlab.com/xx_network/* stages: diff --git a/Makefile b/Makefile index a2a6eef59836c1a6ee6de3b4447ca40ae9a943d9..b8d85b2d4b167ff0347162df66cc69dda12755e3 100644 --- a/Makefile +++ b/Makefile @@ -1,11 +1,18 @@ -.PHONY: update master release setup update_master update_release build +.PHONY: update master release setup update_master update_release build clean version setup: git config --global --add url."git@gitlab.com:".insteadOf "https://gitlab.com/" -update: +version: + go run main.go generate + sed -i.bak 's/package\ cmd/package\ globals/g' version_vars.go + mv version_vars.go globals/version_vars.go + +clean: rm -rf vendor/ go mod vendor + +update: -GOFLAGS="" go get -u all build: @@ -16,12 +23,14 @@ update_release: GOFLAGS="" go get -u gitlab.com/elixxir/primitives@release GOFLAGS="" go get -u gitlab.com/elixxir/crypto@release GOFLAGS="" go get -u gitlab.com/elixxir/comms@release + GOFLAGS="" go get -u gitlab.com/xx_network/comms@release update_master: GOFLAGS="" go get -u gitlab.com/elixxir/primitives@master GOFLAGS="" go get -u gitlab.com/elixxir/crypto@master GOFLAGS="" go get -u gitlab.com/elixxir/comms@master + GOFLAGS="" go get -u gitlab.com/xx_network/comms@master -master: update update_master build +master: clean update_master build version -release: update update_release build +release: clean update_release build version diff --git a/api/client.go b/api/client.go index b5639a701870805f53a884949d3cc5306f83f61e..820c3457a9e3ffc7b5627b867580592cd8df483e 100644 --- a/api/client.go +++ b/api/client.go @@ -23,7 +23,6 @@ import ( "gitlab.com/elixxir/client/parse" "gitlab.com/elixxir/client/rekey" "gitlab.com/elixxir/client/user" - "gitlab.com/elixxir/comms/connect" "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/crypto/large" "gitlab.com/elixxir/crypto/signature/rsa" @@ -31,6 +30,7 @@ import ( "gitlab.com/elixxir/primitives/id" "gitlab.com/elixxir/primitives/ndf" "gitlab.com/elixxir/primitives/switchboard" + "gitlab.com/xx_network/comms/connect" goio "io" "strings" "testing" @@ -121,7 +121,7 @@ func newClient(s globals.Storage, locA, locB string, ndfJSON *ndf.NetworkDefinit } // LoadSession loads the session object for the UID -func (cl *Client) Login(password string) (*id.User, error) { +func (cl *Client) Login(password string) (*id.ID, error) { var session user.Session var err error @@ -158,7 +158,7 @@ func (cl *Client) Login(password string) (*id.User, error) { } cl.session = session - newRm, err := io.NewReceptionManager(cl.rekeyChan, cl.session.GetCurrentUser().User.String(), + newRm, err := io.NewReceptionManager(cl.rekeyChan, cl.session.GetCurrentUser().User, rsa.CreatePrivateKeyPem(cl.session.GetRSAPrivateKey()), rsa.CreatePublicKeyPem(cl.session.GetRSAPublicKey()), cl.session.GetSalt()) @@ -306,14 +306,19 @@ var sessionFileError = errors.New("Session file cannot be loaded and " + "is possibly corrupt. Please contact support@xxmessenger.io") func (cl *Client) InitListeners() error { - transmitGateway := id.NewNodeFromBytes(cl.ndf.Nodes[0].ID).NewGateway() - transmissionHost, ok := cl.receptionManager.Comms.GetHost(transmitGateway.String()) + transmitGateway, err := id.Unmarshal(cl.ndf.Gateways[0].ID) + if err != nil { + globals.Log.DEBUG.Printf("%s: Gateways are: %+v", err.Error(), + cl.ndf.Gateways) + return err + } + transmissionHost, ok := cl.receptionManager.Comms.GetHost(transmitGateway) if !ok { return errors.New("Failed to retrieve host for transmission") } // Initialize UDB and nickname "bot" stuff here - bots.InitBots(cl.session, cl.receptionManager, cl.topology, id.NewUserFromBytes(cl.ndf.UDB.ID), transmissionHost) + bots.InitBots(cl.session, cl.receptionManager, cl.topology, transmissionHost) // Initialize Rekey listeners rekey.InitRekey(cl.session, cl.receptionManager, cl.topology, transmissionHost, cl.rekeyChan) return nil @@ -325,8 +330,11 @@ func (cl *Client) StartMessageReceiver(callback func(error)) error { pollWaitTimeMillis := 500 * time.Millisecond // TODO Don't start the message receiver if it's already started. // Should be a pretty rare occurrence except perhaps for mobile. - receptionGateway := id.NewNodeFromBytes(cl.ndf.Nodes[len(cl.ndf.Nodes)-1].ID).NewGateway() - receptionHost, ok := cl.receptionManager.Comms.GetHost(receptionGateway.String()) + receptionGateway, err := id.Unmarshal(cl.ndf.Gateways[len(cl.ndf.Gateways)-1].ID) + if err != nil { + return err + } + receptionHost, ok := cl.receptionManager.Comms.GetHost(receptionGateway) if !ok { return errors.New("Failed to retrieve host for transmission") } @@ -349,8 +357,12 @@ func (cl *Client) StartMessageReceiver(callback func(error)) error { // Default send function, can be overridden for testing func (cl *Client) Send(message parse.MessageInterface) error { - transmitGateway := id.NewNodeFromBytes(cl.ndf.Nodes[0].ID).NewGateway() - host, ok := cl.receptionManager.Comms.GetHost(transmitGateway.String()) + transmitGateway, err := id.Unmarshal(cl.ndf.Gateways[0].ID) + if err != nil { + return err + } + transmitGateway.SetType(id.Gateway) + host, ok := cl.receptionManager.Comms.GetHost(transmitGateway) if !ok { return errors.New("Failed to retrieve host for transmission") } @@ -377,7 +389,7 @@ func (cl *Client) SetRateLimiting(limit uint32) { cl.receptionManager.SetRateLimit(time.Duration(limit) * time.Millisecond) } -func (cl *Client) Listen(user *id.User, messageType int32, newListener switchboard.Listener) string { +func (cl *Client) Listen(user *id.ID, messageType int32, newListener switchboard.Listener) string { listenerId := cl.session.GetSwitchboard(). Register(user, messageType, newListener) globals.Log.INFO.Printf("Listening now: user %v, message type %v, id %v", @@ -393,7 +405,7 @@ func (cl *Client) GetSwitchboard() *switchboard.Switchboard { return cl.session.GetSwitchboard() } -func (cl *Client) GetCurrentUser() *id.User { +func (cl *Client) GetCurrentUser() *id.ID { return cl.session.GetCurrentUser().User } @@ -467,7 +479,7 @@ type NickLookupCallback interface { Callback(nick string, err error) } -func (cl *Client) DeleteUser(u *id.User) (string, error) { +func (cl *Client) DeleteUser(u *id.ID) (string, error) { //delete from session v, err1 := cl.session.DeleteContact(u) @@ -499,7 +511,7 @@ func (cl *Client) DeleteUser(u *id.User) (string, error) { // Nickname lookup API // Non-blocking, once the API call completes, the callback function // passed as argument is called -func (cl *Client) LookupNick(user *id.User, +func (cl *Client) LookupNick(user *id.ID, cb NickLookupCallback) { go func() { nick, err := bots.LookupNick(user) diff --git a/api/client_test.go b/api/client_test.go index b77ea2c6fe1709a1b115a8e8a8166c35df98b2cd..bebd23da966c191ed8c45900a0626f25c54b4932 100644 --- a/api/client_test.go +++ b/api/client_test.go @@ -128,8 +128,8 @@ func TestParse(t *testing.T) { ms := parse.Message{} ms.Body = []byte{0, 1, 2} ms.MessageType = int32(cmixproto.Type_NO_TYPE) - ms.Receiver = id.ZeroID - ms.Sender = id.ZeroID + ms.Receiver = &id.ZeroUser + ms.Sender = &id.ZeroUser messagePacked := ms.Pack() @@ -158,8 +158,8 @@ func TestRegisterUserE2E(t *testing.T) { rng := csprng.NewSystemRNG() cmixGrp, e2eGrp := getGroups() - userID := id.NewUserFromUint(18, t) - partner := id.NewUserFromUint(14, t) + userID := id.NewIdFromUInt(18, id.User, t) + partner := id.NewIdFromUInt(14, id.User, t) myPrivKeyCyclic := e2eGrp.RandomCoprime(e2eGrp.NewMaxInt()) myPubKeyCyclic := e2eGrp.ExpG(myPrivKeyCyclic, e2eGrp.NewMaxInt()) @@ -247,8 +247,8 @@ func TestRegisterUserE2E_CheckAllKeys(t *testing.T) { } cmixGrp, e2eGrp := getGroups() - userID := id.NewUserFromUint(18, t) - partner := id.NewUserFromUint(14, t) + userID := id.NewIdFromUInt(18, id.User, t) + partner := id.NewIdFromUInt(14, id.User, t) rng := csprng.NewSystemRNG() myPrivKeyCyclic := e2eGrp.RandomCoprime(e2eGrp.NewMaxInt()) @@ -401,7 +401,7 @@ func TestClient_precannedRegister(t *testing.T) { t.Error(err) } - _, _, _, err = testClient.precannedRegister("UAV6IWD6") + _, _, _, err = testClient.precannedRegister("WTROXJ33") if err != nil { t.Errorf("Error during precannedRegister: %+v", err) } @@ -428,7 +428,7 @@ func TestClient_sendRegistrationMessage(t *testing.T) { privateKeyRSA, _ := rsa.GenerateKey(rng, TestKeySize) publicKeyRSA := rsa.PublicKey{PublicKey: privateKeyRSA.PublicKey} - _, err = testClient.sendRegistrationMessage("UAV6IWD6", &publicKeyRSA) + _, err = testClient.sendRegistrationMessage("WTROXJ33", &publicKeyRSA) if err != nil { t.Errorf("Error during sendRegistrationMessage: %+v", err) } @@ -462,7 +462,11 @@ func TestClient_requestNonce(t *testing.T) { t.Errorf("Unable to generate salt! %s", err) } - gwID := id.NewNodeFromBytes(testClient.ndf.Nodes[0].ID).NewGateway() + gwID, err := id.Unmarshal(testClient.ndf.Gateways[0].ID) + if err != nil { + t.Fatal(err) + } + gwID.SetType(id.Gateway) _, _, err = testClient.requestNonce(salt, []byte("test"), publicKeyDH, &publicKeyRSA, privateKeyRSA, gwID) if err != nil { t.Errorf("Error during requestNonce: %+v", err) @@ -485,7 +489,11 @@ func TestClient_confirmNonce(t *testing.T) { } rng := csprng.NewSystemRNG() privateKeyRSA, _ := rsa.GenerateKey(rng, TestKeySize) - gwID := id.NewNodeFromBytes(testClient.ndf.Nodes[0].ID).NewGateway() + gwID, err := id.Unmarshal(testClient.ndf.Gateways[0].ID) + if err != nil { + t.Fatal(err) + } + gwID.SetType(id.Gateway) err = testClient.confirmNonce([]byte("user"), []byte("test"), privateKeyRSA, gwID) if err != nil { t.Errorf("Error during confirmNonce: %+v", err) @@ -567,7 +575,8 @@ func TestClient_LogoutHappyPath(t *testing.T) { d := DummyStorage{LocationA: "Blah", StoreA: []byte{'a', 'b', 'c'}} tc, _ := NewClient(&d, "", "", def) - tc.receptionManager, _ = io.NewReceptionManager(tc.rekeyChan, "kk", nil, nil, nil) + uid := id.NewIdFromString("kk", id.User, t) + tc.receptionManager, _ = io.NewReceptionManager(tc.rekeyChan, uid, nil, nil, nil) err := tc.InitNetwork() if err != nil { @@ -642,7 +651,8 @@ func TestClient_LogoutTimeout(t *testing.T) { d := DummyStorage{LocationA: "Blah", StoreA: []byte{'a', 'b', 'c'}} tc, _ := NewClient(&d, "", "", def) - tc.receptionManager, _ = io.NewReceptionManager(tc.rekeyChan, "kk", nil, nil, nil) + uid := id.NewIdFromString("kk", id.User, t) + tc.receptionManager, _ = io.NewReceptionManager(tc.rekeyChan, uid, nil, nil, nil) err := tc.InitNetwork() if err != nil { @@ -705,7 +715,8 @@ func TestClient_LogoutAndLoginAgain(t *testing.T) { storage := globals.RamStorage{} tc, initialId := NewClient(&storage, "", "", def) - tc.receptionManager, _ = io.NewReceptionManager(tc.rekeyChan, "kk", nil, nil, nil) + uid := id.NewIdFromString("kk", id.User, t) + tc.receptionManager, _ = io.NewReceptionManager(tc.rekeyChan, uid, nil, nil, nil) err := tc.InitNetwork() if err != nil { diff --git a/api/connect.go b/api/connect.go index 5feebdb09b2262f04e04a205ce7558b1d92ba126..578ee3e05f6250bf69fc5d40ad8085317eb7131a 100644 --- a/api/connect.go +++ b/api/connect.go @@ -11,9 +11,10 @@ import ( "github.com/pkg/errors" "gitlab.com/elixxir/client/globals" "gitlab.com/elixxir/client/io" - "gitlab.com/elixxir/comms/connect" "gitlab.com/elixxir/primitives/id" "gitlab.com/elixxir/primitives/ndf" + "gitlab.com/elixxir/primitives/version" + "gitlab.com/xx_network/comms/connect" ) var ErrNoPermissioning = errors.New("No Permissioning In NDF") @@ -24,7 +25,8 @@ var ErrNoPermissioning = errors.New("No Permissioning In NDF") func (cl *Client) InitNetwork() error { var err error if cl.receptionManager == nil { - cl.receptionManager, err = io.NewReceptionManager(cl.rekeyChan, "client", nil, nil, nil) + // Start reception manager with a dummy user, so we can connect to things + cl.receptionManager, err = io.NewReceptionManager(cl.rekeyChan, &id.DummyUser, nil, nil, nil) if err != nil { return errors.Wrap(err, "Failed to create reception manager") } @@ -53,7 +55,10 @@ func (cl *Client) InitNetwork() error { } // InitNetwork to nodes - cl.topology = BuildNodeTopology(cl.ndf) + cl.topology, err = BuildNodeTopology(cl.ndf) + if err != nil { + return err + } err = addNotificationBotHost(cl.receptionManager, cl.ndf) if err != nil { @@ -66,7 +71,7 @@ func (cl *Client) InitNetwork() error { // AddNotificationBotHost adds notification bot as a host within the reception manager func addNotificationBotHost(rm *io.ReceptionManager, definition *ndf.NetworkDefinition) error { - err := addHost(rm, id.NOTIFICATION_BOT, definition.Notification.Address, + err := addHost(rm, &id.NotificationBot, definition.Notification.Address, definition.Notification.TlsCertificate, false, true) if err != nil { return errors.Errorf("Failed to connect to notification bot at %+v", @@ -77,14 +82,18 @@ func addNotificationBotHost(rm *io.ReceptionManager, definition *ndf.NetworkDefi // BuildNodeTopology is a helper function which goes through the ndf and // builds a circuit for all the node's in the definition -func BuildNodeTopology(definition *ndf.NetworkDefinition) *connect.Circuit { +func BuildNodeTopology(definition *ndf.NetworkDefinition) (*connect.Circuit, error) { //build the topology - nodeIDs := make([]*id.Node, len(definition.Nodes)) + nodeIDs := make([]*id.ID, len(definition.Nodes)) + var err error for i, node := range definition.Nodes { - nodeIDs[i] = id.NewNodeFromBytes(node.ID) + nodeIDs[i], err = id.Unmarshal(node.ID) + if err != nil { + return nil, err + } } - return connect.NewCircuit(nodeIDs) + return connect.NewCircuit(nodeIDs), nil } // DisableTls disables tls for communications @@ -119,10 +128,19 @@ func (cl *Client) setupPermissioning() error { // Only check the version if we got a remote version // The remote version won't have been populated if we didn't connect to permissioning if cl.GetRegistrationVersion() != "" { - ok, err := globals.CheckVersion(cl.GetRegistrationVersion()) + // Parse client version + clientVersion, err := version.ParseVersion(globals.SEMVER) + if err != nil { + return err + } + + // Parse the permissioning version + regVersion, err := version.ParseVersion(cl.GetRegistrationVersion()) if err != nil { return err } + + ok := version.IsCompatible(regVersion, clientVersion) if !ok { return errors.Errorf("Couldn't connect to gateways: Versions"+ " incompatible; Local version: %v; remote version: %v", globals.SEMVER, @@ -148,8 +166,18 @@ func addGatewayHosts(rm *io.ReceptionManager, definition *ndf.NetworkDefinition) // connect to all gateways var errs error = nil for i, gateway := range definition.Gateways { - gwID := id.NewNodeFromBytes(definition.Nodes[i].ID).NewGateway() - err := addHost(rm, gwID.String(), gateway.Address, gateway.TlsCertificate, false, false) + gwID, err := id.Unmarshal(definition.Gateways[i].ID) + if err != nil { + err = errors.Errorf("Failed to unmarshal gateway ID %s at index %v: %+v", + definition.Gateways[i].ID, i, err) + if errs != nil { + errs = err + } else { + errs = errors.Wrap(errs, err.Error()) + } + continue + } + err = addHost(rm, gwID, gateway.Address, gateway.TlsCertificate, false, false) if err != nil { err = errors.Errorf("Failed to create host for gateway %s at %s: %+v", gwID.String(), gateway.Address, err) @@ -163,7 +191,7 @@ func addGatewayHosts(rm *io.ReceptionManager, definition *ndf.NetworkDefinition) return errs } -func addHost(rm *io.ReceptionManager, id, address, cert string, disableTimeout, enableAuth bool) error { +func addHost(rm *io.ReceptionManager, id *id.ID, address, cert string, disableTimeout, enableAuth bool) error { var creds []byte if cert != "" && rm.Tls { creds = []byte(cert) @@ -180,7 +208,7 @@ func addHost(rm *io.ReceptionManager, id, address, cert string, disableTimeout, // to permissioning is needed func addPermissioningHost(rm *io.ReceptionManager, definition *ndf.NetworkDefinition) error { if definition.Registration.Address != "" { - err := addHost(rm, PermissioningAddrID, definition.Registration.Address, + err := addHost(rm, &id.Permissioning, definition.Registration.Address, definition.Registration.TlsCertificate, false, false) if err != nil { return errors.New(fmt.Sprintf( diff --git a/api/mockserver.go b/api/mockserver.go index c77de57be32e75d6b8c73fbb5c4d1d2a49cde249..ca0d86e8e580d6c0890331111940f2e68bfea0df 100644 --- a/api/mockserver.go +++ b/api/mockserver.go @@ -14,7 +14,6 @@ import ( "gitlab.com/elixxir/client/cmixproto" "gitlab.com/elixxir/client/globals" "gitlab.com/elixxir/client/parse" - "gitlab.com/elixxir/comms/connect" pb "gitlab.com/elixxir/comms/mixmessages" "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/crypto/e2e" @@ -22,6 +21,8 @@ import ( "gitlab.com/elixxir/primitives/format" "gitlab.com/elixxir/primitives/id" "gitlab.com/elixxir/primitives/ndf" + "gitlab.com/xx_network/comms/connect" + "gitlab.com/xx_network/comms/messages" "sync" "time" ) @@ -37,15 +38,15 @@ const BatchSize = 10 // easy to use from Go type APIMessage struct { Payload []byte - SenderID *id.User - RecipientID *id.User + SenderID *id.ID + RecipientID *id.ID } -func (m APIMessage) GetSender() *id.User { +func (m APIMessage) GetSender() *id.ID { return m.SenderID } -func (m APIMessage) GetRecipient() *id.User { +func (m APIMessage) GetRecipient() *id.ID { return m.RecipientID } @@ -141,7 +142,7 @@ type MockRegistration struct { //LastReceivedMessage pb.CmixMessage } -func (s *MockRegistration) RegisterNode(ID []byte, +func (s *MockRegistration) RegisterNode(ID *id.ID, NodeTLSCert, GatewayTLSCert, RegistrationCode, Addr, Addr2 string) error { return nil } @@ -153,7 +154,7 @@ func (s *MockRegistration) PollNdf(clientNdfHash []byte, auth *connect.Auth) ([] return ndfJson, nil } -func (s *MockRegistration) Poll(*pb.PermissioningPoll, *connect.Auth) (*pb.PermissionPollResponse, error) { +func (s *MockRegistration) Poll(*pb.PermissioningPoll, *connect.Auth, string) (*pb.PermissionPollResponse, error) { return nil, nil } @@ -167,6 +168,10 @@ func (s *MockRegistration) GetCurrentClientVersion() (version string, err error) return globals.SEMVER, nil } +func (i *MockRegistration) CheckRegistration(msg *pb.RegisteredNodeCheck) (*pb.RegisteredNodeConfirmation, error) { + return nil, nil +} + //registration handler for getUpdatedNDF error case type MockPermNdfErrorCase struct { } @@ -265,7 +270,7 @@ type GatewayHandler struct { LastReceivedMessage pb.Slot } -func (m *GatewayHandler) PollForNotifications(auth *connect.Auth) ([]string, error) { +func (m *GatewayHandler) PollForNotifications(auth *connect.Auth) ([]*id.ID, error) { return nil, nil } @@ -276,13 +281,13 @@ func (m *GatewayHandler) Poll(*pb.GatewayPoll) (*pb.GatewayPollResponse, error) // Returns message contents for MessageID, or a null/randomized message // if that ID does not exist of the same size as a regular message -func (m *GatewayHandler) GetMessage(userId *id.User, +func (m *GatewayHandler) GetMessage(userId *id.ID, msgId, ipaddr string) (*pb.Slot, error) { return &pb.Slot{}, nil } // Return any MessageIDs in the globals for this User -func (m *GatewayHandler) CheckMessages(userId *id.User, +func (m *GatewayHandler) CheckMessages(userId *id.ID, messageID, ipAddress string) ([]string, error) { return make([]string, 0), nil } @@ -296,7 +301,7 @@ func (m *GatewayHandler) PutMessage(msg *pb.Slot, ipaddr string) error { func (m *GatewayHandler) ConfirmNonce(message *pb.RequestRegistrationConfirmation, ipaddr string) (*pb.RegistrationConfirmation, error) { regConfirmation := &pb.RegistrationConfirmation{ - ClientSignedByServer: &pb.RSASignature{}, + ClientSignedByServer: &messages.RSASignature{}, } return regConfirmation, nil @@ -315,7 +320,7 @@ type GatewayHandlerMultipleMessages struct { LastReceivedMessage []pb.Slot } -func (m *GatewayHandlerMultipleMessages) GetMessage(userId *id.User, +func (m *GatewayHandlerMultipleMessages) GetMessage(userId *id.ID, msgId, ipaddr string) (*pb.Slot, error) { msg := []byte("Hello") payload, err := e2e.Pad(msg, format.PayloadLen) @@ -328,7 +333,7 @@ func (m *GatewayHandlerMultipleMessages) GetMessage(userId *id.User, }, nil } -func (m *GatewayHandlerMultipleMessages) PollForNotifications(auth *connect.Auth) ([]string, error) { +func (m *GatewayHandlerMultipleMessages) PollForNotifications(auth *connect.Auth) ([]*id.ID, error) { return nil, nil } @@ -337,7 +342,7 @@ func (s *GatewayHandlerMultipleMessages) Poll(*pb.GatewayPoll) (*pb.GatewayPollR } // Return any MessageIDs in the globals for this User -func (m *GatewayHandlerMultipleMessages) CheckMessages(userId *id.User, +func (m *GatewayHandlerMultipleMessages) CheckMessages(userId *id.ID, messageID, ipaddr string) ([]string, error) { msgs := []string{"a", "b", "c", "d", "e", "f", "g"} return msgs, nil diff --git a/api/mockserver_test.go b/api/mockserver_test.go index a407aa3b8b18e1ebaa1e55b60721d850b0e5fe3f..86a26bf01b7db1641ea79003bdfbb33e6782a86f 100644 --- a/api/mockserver_test.go +++ b/api/mockserver_test.go @@ -38,7 +38,7 @@ var RegComms *registration.Comms var NDFErrorReg = MockPermNdfErrorCase{} var ErrorDef *ndf.NetworkDefinition -const ValidRegCode = "UAV6IWD6" +const ValidRegCode = "WTROXJ33" const InvalidRegCode = "INVALID_REG_CODE_" var RegGWHandlers [3]*GatewayHandler = [NumGWs]*GatewayHandler{ @@ -67,11 +67,13 @@ func TestClient_StartMessageReceiver_MultipleMessages(t *testing.T) { // Initialize client with dummy storage testDef := getNDF() for i := 0; i < NumNodes; i++ { + gwID := id.NewIdFromString("testGateway", id.Gateway, t) gw := ndf.Gateway{ Address: string(fmtAddress(GWErrorPort + i)), + ID: gwID.Marshal(), } testDef.Gateways = append(testDef.Gateways, gw) - GWErrComms[i] = gateway.StartGateway("testGateway", gw.Address, + GWErrComms[i] = gateway.StartGateway(gwID, gw.Address, &GatewayHandlerMultipleMessages{}, nil, nil) } @@ -163,7 +165,7 @@ func TestRegister_ValidPrecannedRegCodeReturnsZeroID(t *testing.T) { t.Errorf("Registration failed: %s", err.Error()) } - if *regRes == *id.ZeroID { + if regRes.Cmp(&id.ZeroUser) { t.Errorf("Invalid registration number received: %v", *regRes) } disconnectServers() @@ -254,8 +256,8 @@ func TestRegister_DeletedUserReturnsErr(t *testing.T) { } // ... - tempUser, _ := user.Users.GetUser(id.NewUserFromUint(5, t)) - user.Users.DeleteUser(id.NewUserFromUint(5, t)) + tempUser, _ := user.Users.GetUser(id.NewIdFromUInt(5, id.User, t)) + user.Users.DeleteUser(id.NewIdFromUInt(5, id.User, t)) err = client.GenerateKeys(nil, "") if err != nil { t.Errorf("Could not generate Keys: %+v", err) @@ -327,7 +329,7 @@ func TestSend(t *testing.T) { // Test send with invalid sender ID err = client.Send( APIMessage{ - SenderID: id.NewUserFromUint(12, t), + SenderID: id.NewIdFromUInt(12, id.User, t), Payload: []byte("test"), RecipientID: userID, }, @@ -447,10 +449,11 @@ func testMainWrapper(m *testing.M) int { } for i := 0; i < NumNodes; i++ { - nIdBytes := make([]byte, id.NodeIdLen) - nIdBytes[0] = byte(i) + nId := new(id.ID) + nId[0] = byte(i) + nId.SetType(id.Node) n := ndf.Node{ - ID: nIdBytes, + ID: nId[:], } def.Nodes = append(def.Nodes, n) ErrorDef.Nodes = append(ErrorDef.Nodes, n) @@ -512,22 +515,28 @@ func getNDF() *ndf.NetworkDefinition { } func startServers() { - //func StartRegistrationServer(id, localServer string, handler Handler, certPEMblock, keyPEMblock []byte) *Comms { - RegComms = registration.StartRegistrationServer("testServer", def.Registration.Address, &RegHandler, nil, nil) + regId := new(id.ID) + copy(regId[:], "testServer") + regId.SetType(id.Generic) + RegComms = registration.StartRegistrationServer(regId, def.Registration.Address, &RegHandler, nil, nil) def.Gateways = make([]ndf.Gateway, 0) //Start up gateways for i, handler := range RegGWHandlers { + gwID := new(id.ID) + copy(gwID[:], "testGateway") + gwID.SetType(id.Gateway) gw := ndf.Gateway{ Address: fmtAddress(GWsStartPort + i), + ID: gwID.Marshal(), } def.Gateways = append(def.Gateways, gw) - GWComms[i] = gateway.StartGateway("testGateway", gw.Address, handler, nil, nil) + GWComms[i] = gateway.StartGateway(gwID, gw.Address, handler, nil, nil) } - NotificationBotComms = notificationBot.StartNotificationBot(id.NOTIFICATION_BOT, def.Notification.Address, &NotificationBotHandler, nil, nil) + NotificationBotComms = notificationBot.StartNotificationBot(&id.NotificationBot, def.Notification.Address, &NotificationBotHandler, nil, nil) } diff --git a/api/notifications.go b/api/notifications.go index 663daa315379e88496d186f027377978dda0c80f..5d27bf73d22387c378b66f738478dfb927c6ba0f 100644 --- a/api/notifications.go +++ b/api/notifications.go @@ -10,7 +10,7 @@ import ( // is registering for notifications func (cl *Client) RegisterForNotifications(notificationToken []byte) error { // Pull the host from the manage - notificationBotHost, ok := cl.receptionManager.Comms.GetHost(id.NOTIFICATION_BOT) + notificationBotHost, ok := cl.receptionManager.Comms.GetHost(&id.NotificationBot) if !ok { return errors.New("Failed to retrieve host for notification bot") } @@ -34,7 +34,7 @@ func (cl *Client) RegisterForNotifications(notificationToken []byte) error { // no longer wants to be registered for notifications func (cl *Client) UnregisterForNotifications() error { // Pull the host from the manage - notificationBotHost, ok := cl.receptionManager.Comms.GetHost(id.NOTIFICATION_BOT) + notificationBotHost, ok := cl.receptionManager.Comms.GetHost(&id.NotificationBot) if !ok { return errors.New("Failed to retrieve host for notification bot") } diff --git a/api/private.go b/api/private.go index 2e6dcb6a9e950a3d6e8a5fc69dc9aecb62dfaa05..bc76f0f36d6f02080c16698ceab5c73a6f6b7caa 100644 --- a/api/private.go +++ b/api/private.go @@ -20,23 +20,24 @@ import ( "gitlab.com/elixxir/crypto/diffieHellman" "gitlab.com/elixxir/crypto/e2e" "gitlab.com/elixxir/crypto/large" - "gitlab.com/elixxir/crypto/registration" "gitlab.com/elixxir/crypto/signature/rsa" + "gitlab.com/elixxir/crypto/xx" "gitlab.com/elixxir/primitives/id" "gitlab.com/elixxir/primitives/ndf" + "gitlab.com/xx_network/comms/messages" ) const PermissioningAddrID = "Permissioning" // precannedRegister is a helper function for Register // It handles the precanned registration case -func (cl *Client) precannedRegister(registrationCode string) (*user.User, *id.User, map[id.Node]user.NodeKeys, error) { +func (cl *Client) precannedRegister(registrationCode string) (*user.User, *id.ID, map[id.ID]user.NodeKeys, error) { var successLook bool - var UID *id.User + var UID *id.ID var u *user.User var err error - nk := make(map[id.Node]user.NodeKeys) + nk := make(map[id.ID]user.NodeKeys) UID, successLook = user.Users.LookupUser(registrationCode) @@ -82,7 +83,7 @@ func (cl *Client) sendRegistrationMessage(registrationCode string, regValidationSignature := make([]byte, 0) // Send registration code and public key to RegistrationServer - host, ok := cl.receptionManager.Comms.GetHost(PermissioningAddrID) + host, ok := cl.receptionManager.Comms.GetHost(&id.Permissioning) if !ok { return nil, errors.New("Failed to find permissioning host") } @@ -110,7 +111,7 @@ func (cl *Client) sendRegistrationMessage(registrationCode string, // Returns nonce if successful func (cl *Client) requestNonce(salt, regHash []byte, publicKeyDH *cyclic.Int, publicKeyRSA *rsa.PublicKey, - privateKeyRSA *rsa.PrivateKey, gwID *id.Gateway) ([]byte, []byte, error) { + privateKeyRSA *rsa.PrivateKey, gwID *id.ID) ([]byte, []byte, error) { dhPub := publicKeyDH.Bytes() sha := crypto.SHA256 opts := rsa.NewDefaultOptions() @@ -127,7 +128,7 @@ func (cl *Client) requestNonce(salt, regHash []byte, } // Send signed public key and salt for UserID to Server - host, ok := cl.receptionManager.Comms.GetHost(gwID.String()) + host, ok := cl.receptionManager.Comms.GetHost(gwID) if !ok { return nil, nil, errors.Errorf("Failed to find host with ID %s", gwID.String()) } @@ -137,11 +138,11 @@ func (cl *Client) requestNonce(salt, regHash []byte, &pb.NonceRequest{ Salt: salt, ClientRSAPubKey: string(rsa.CreatePublicKeyPem(publicKeyRSA)), - ClientSignedByServer: &pb.RSASignature{ + ClientSignedByServer: &messages.RSASignature{ Signature: regHash, }, ClientDHPubKey: publicKeyDH.Bytes(), - RequestSignature: &pb.RSASignature{ + RequestSignature: &messages.RSASignature{ Signature: signed, }, }) // TODO: modify this to return server DH @@ -163,7 +164,7 @@ func (cl *Client) requestNonce(salt, regHash []byte, // It signs a nonce and sends it for confirmation // Returns nil if successful, error otherwise func (cl *Client) confirmNonce(UID, nonce []byte, - privateKeyRSA *rsa.PrivateKey, gwID *id.Gateway) error { + privateKeyRSA *rsa.PrivateKey, gwID *id.ID) error { sha := crypto.SHA256 opts := rsa.NewDefaultOptions() opts.Hash = sha @@ -183,12 +184,12 @@ func (cl *Client) confirmNonce(UID, nonce []byte, // TODO: This returns a receipt that can be used to speed up registration msg := &pb.RequestRegistrationConfirmation{ UserID: UID, - NonceSignedByClient: &pb.RSASignature{ + NonceSignedByClient: &messages.RSASignature{ Signature: sig, }, } - host, ok := cl.receptionManager.Comms.GetHost(gwID.String()) + host, ok := cl.receptionManager.Comms.GetHost(gwID) if !ok { return errors.Errorf("Failed to find host with ID %s", gwID.String()) } @@ -207,7 +208,7 @@ func (cl *Client) confirmNonce(UID, nonce []byte, return nil } -func (cl *Client) registerUserE2E(partnerID *id.User, +func (cl *Client) registerUserE2E(partnerID *id.ID, partnerPubKey []byte) error { // Check that the returned user is valid @@ -303,7 +304,7 @@ func (cl *Client) GenerateKeys(rsaPrivKey *rsa.PrivateKey, cl.session = user.NewSession(cl.storage, usr, pubKey, privKey, cmixPubKey, cmixPrivKey, e2ePubKey, e2ePrivKey, salt, cmixGrp, e2eGrp, password) - newRm, err := io.NewReceptionManager(cl.rekeyChan, cl.session.GetCurrentUser().User.String(), + newRm, err := io.NewReceptionManager(cl.rekeyChan, cl.session.GetCurrentUser().User, rsa.CreatePrivateKeyPem(privKey), rsa.CreatePublicKeyPem(pubKey), salt) if err != nil { return errors.Wrap(err, "Failed to create new reception manager") @@ -392,7 +393,7 @@ func generateE2eKeys(cmixGrp, e2eGrp *cyclic.Group) (e2ePrivateKey, e2ePublicKey //generateUserInformation serves as a helper function for RegisterUser. // It generates a salt s.t. it can create a user and their ID -func generateUserInformation(publicKeyRSA *rsa.PublicKey) ([]byte, *id.User, *user.User, error) { +func generateUserInformation(publicKeyRSA *rsa.PublicKey) ([]byte, *id.ID, *user.User, error) { //Generate salt for UserID salt := make([]byte, SaltSize) _, err := csprng.NewSystemRNG().Read(salt) @@ -402,7 +403,10 @@ func generateUserInformation(publicKeyRSA *rsa.PublicKey) ([]byte, *id.User, *us } //Generate UserID by hashing salt and public key - userId := registration.GenUserID(publicKeyRSA, salt) + userId, err := xx.NewID(publicKeyRSA, salt, id.User) + if err != nil { + return nil, nil, nil, err + } usr := user.Users.NewUser(userId, "") user.Users.UpsertUser(usr) diff --git a/api/register.go b/api/register.go index afbefd0ad10d5f27783712877328913fb0314b5a..921738be22150f4fa06a187a0f375a622ce2aaa7 100644 --- a/api/register.go +++ b/api/register.go @@ -24,11 +24,11 @@ import ( "time" ) -const SaltSize = 256 +const SaltSize = 32 //RegisterWithPermissioning registers the user and returns the User ID. // Returns an error if registration fails. -func (cl *Client) RegisterWithPermissioning(preCan bool, registrationCode string) (*id.User, error) { +func (cl *Client) RegisterWithPermissioning(preCan bool, registrationCode string) (*id.ID, error) { //Check the regState is in proper state for registration if cl.session.GetRegState() != user.KeyGenComplete { return nil, errors.Errorf("Attempting to register before key generation!") @@ -45,11 +45,11 @@ func (cl *Client) RegisterWithPermissioning(preCan bool, registrationCode string // Either perform a precanned registration for a precanned user cl.opStatus(globals.REG_PRECAN) globals.Log.INFO.Printf("Registering precanned user...") - var nodeKeyMap map[id.Node]user.NodeKeys + var nodeKeyMap map[id.ID]user.NodeKeys usr, UID, nodeKeyMap, err = cl.precannedRegister(registrationCode) if err != nil { globals.Log.ERROR.Printf("Unable to complete precanned registration: %+v", err) - return id.ZeroID, err + return &id.ZeroUser, err } //overwrite the user object @@ -70,7 +70,7 @@ func (cl *Client) RegisterWithPermissioning(preCan bool, registrationCode string regValidationSignature, err = cl.registerWithPermissioning(registrationCode, cl.session.GetRSAPublicKey()) if err != nil { globals.Log.INFO.Printf(err.Error()) - return id.ZeroID, err + return &id.ZeroUser, err } //update the session with the registration err = cl.session.RegisterPermissioningSignature(regValidationSignature) @@ -217,9 +217,12 @@ func (cl *Client) RegisterWithNodes() error { for i := range cl.ndf.Gateways { localI := i - nodeID := *id.NewNodeFromBytes(cl.ndf.Nodes[i].ID) + nodeID, err := id.Unmarshal(cl.ndf.Nodes[i].ID) + if err != nil { + return err + } //Register with node if the node has not been registered with already - if _, ok := registeredNodes[nodeID]; !ok { + if _, ok := registeredNodes[*nodeID]; !ok { wg.Add(1) newRegistrations = true go func() { @@ -264,12 +267,16 @@ func (cl *Client) RegisterWithNodes() error { //registerWithNode serves as a helper for RegisterWithNodes // It registers a user with a specific in the client's ndf. -func (cl *Client) registerWithNode(index int, salt, registrationValidationSignature []byte, UID *id.User, +func (cl *Client) registerWithNode(index int, salt, registrationValidationSignature []byte, UID *id.ID, publicKeyRSA *rsa.PublicKey, privateKeyRSA *rsa.PrivateKey, cmixPublicKeyDH, cmixPrivateKeyDH *cyclic.Int, cmixGrp *cyclic.Group, errorChan chan error) { - gatewayID := id.NewNodeFromBytes(cl.ndf.Nodes[index].ID).NewGateway() + gatewayID, err := id.Unmarshal(cl.ndf.Gateways[index].ID) + if err != nil { + errorChan <- err + return + } // Initialise blake2b hash for transmission keys and sha256 for reception // keys diff --git a/api/register_test.go b/api/register_test.go index b36b0f93c39b0fa4e793f52594730f47ec0a98a1..5c0ab24a56d6029c89c04e737dfc2e39dc4641eb 100644 --- a/api/register_test.go +++ b/api/register_test.go @@ -9,9 +9,8 @@ import ( "crypto/sha256" "gitlab.com/elixxir/client/globals" "gitlab.com/elixxir/client/user" - "gitlab.com/elixxir/comms/connect" "gitlab.com/elixxir/primitives/id" - "reflect" + "gitlab.com/xx_network/comms/connect" "testing" ) @@ -33,7 +32,7 @@ func TestRegistrationGob(t *testing.T) { } // populate a gob in the store - _, err = testClient.RegisterWithPermissioning(true, "UAV6IWD6") + _, err = testClient.RegisterWithPermissioning(true, "WTROXJ33") if err != nil { t.Error(err) } @@ -76,7 +75,7 @@ func TestClient_Register(t *testing.T) { } // populate a gob in the store - _, err = testClient.RegisterWithPermissioning(true, "UAV6IWD6") + _, err = testClient.RegisterWithPermissioning(true, "WTROXJ33") if err != nil { t.Error(err) } @@ -102,10 +101,10 @@ func TestClient_Register(t *testing.T) { //Verify the user from the session make in the registration above matches expected user func VerifyRegisterGobUser(session user.Session, t *testing.T) { - expectedUser := id.NewUserFromUint(5, t) + expectedUser := id.NewIdFromUInt(5, id.User, t) - if reflect.DeepEqual(session.GetCurrentUser().User, &expectedUser) { - t.Errorf("Incorrect User ID; \n expected %q \n recieved: %q", + if !session.GetCurrentUser().User.Cmp(expectedUser) { + t.Errorf("Incorrect User ID; \n expected: %q \n recieved: %q", expectedUser, session.GetCurrentUser().User) } } @@ -153,7 +152,7 @@ func TestRegister_ValidRegParams___(t *testing.T) { t.Errorf("Registration failed: %s", err.Error()) } - if *regRes == *id.ZeroID { + if *regRes == *&id.ZeroUser { t.Errorf("Invalid registration number received: %+v", *regRes) } err = client.RegisterWithNodes() diff --git a/bindings/client.go b/bindings/client.go index 746843b824a3c0e42c8f192adbc92d93ab91ef77..480a55fe8ec810be1e112cb91265b90f8e99d13f 100644 --- a/bindings/client.go +++ b/bindings/client.go @@ -35,12 +35,15 @@ type Client struct { // messages sent from all users. // If you pass the zero type (just zero) to Listen() you will hear messages of // all types. -func (cl *Client) Listen(userId []byte, messageType int32, newListener Listener) string { - typedUserId := id.NewUserFromBytes(userId) +func (cl *Client) Listen(userId []byte, messageType int32, newListener Listener) (string, error) { + typedUserId, err := id.Unmarshal(userId) + if err != nil { + return "", err + } listener := &listenerProxy{proxy: newListener} - return cl.client.Listen(typedUserId, messageType, listener) + return cl.client.Listen(typedUserId, messageType, listener), nil } // Pass the listener handle that Listen() returned to delete the listener @@ -132,7 +135,7 @@ func (cl *Client) RegisterWithPermissioning(preCan bool, registrationCode string UID, err := cl.client.RegisterWithPermissioning(preCan, registrationCode) if err != nil { - return id.ZeroID[:], err + return id.ZeroUser[:], err } return UID[:], nil @@ -285,8 +288,14 @@ func (cl *Client) Send(m Message, encrypt bool) (int64, error) { "MessageTye: %v", m.GetSender(), m.GetPayload(), m.GetRecipient(), m.GetMessageType()) - sender := id.NewUserFromBytes(m.GetSender()) - recipient := id.NewUserFromBytes(m.GetRecipient()) + sender, err := id.Unmarshal(m.GetSender()) + if err != nil { + return 0, err + } + recipient, err := id.Unmarshal(m.GetRecipient()) + if err != nil { + return 0, err + } var cryptoType parse.CryptoType if encrypt { @@ -370,7 +379,10 @@ func (cl *Client) SearchForUser(username string, func (cl *Client) DeleteContact(uid []byte) (string, error) { globals.Log.INFO.Printf("Binding call: DeleteContact()\n"+ " uid: %v\n", uid) - u := id.NewUserFromBytes(uid) + u, err := id.Unmarshal(uid) + if err != nil { + return "", err + } return cl.client.DeleteUser(u) } @@ -379,10 +391,14 @@ func (cl *Client) DeleteContact(uid []byte) (string, error) { // Non-blocking, once the API call completes, the callback function // passed as argument is called func (cl *Client) LookupNick(user []byte, - cb NickLookupCallback) { + cb NickLookupCallback) error { proxy := &nickCallbackProxy{cb} - userID := id.NewUserFromBytes(user) + userID, err := id.Unmarshal(user) + if err != nil { + return err + } cl.client.LookupNick(userID, proxy) + return nil } // Parses a passed message. Allows a message to be parsed using the internal parser diff --git a/bindings/client_test.go b/bindings/client_test.go index d578702bd67f978fbfc4ea34c139556086720b7b..f59ee64034c0b680752c0133cd9adf84eb00eca0 100644 --- a/bindings/client_test.go +++ b/bindings/client_test.go @@ -17,13 +17,13 @@ import ( "gitlab.com/elixxir/client/globals" "gitlab.com/elixxir/client/parse" "gitlab.com/elixxir/client/user" - "gitlab.com/elixxir/comms/connect" "gitlab.com/elixxir/comms/gateway" pb "gitlab.com/elixxir/comms/mixmessages" "gitlab.com/elixxir/comms/registration" "gitlab.com/elixxir/crypto/signature/rsa" "gitlab.com/elixxir/primitives/id" "gitlab.com/elixxir/primitives/ndf" + "gitlab.com/xx_network/comms/connect" "math/rand" "os" "reflect" @@ -36,7 +36,7 @@ const NumNodes = 3 const NumGWs = NumNodes const GWsStartPort = 7950 const RegPort = 5100 -const ValidRegCode = "UAV6IWD6" +const ValidRegCode = "WTROXJ33" var RegHandler = MockRegistration{} var RegComms *registration.Comms @@ -52,7 +52,7 @@ func (i *MockRegistration) RegisterUser(registrationCode, test string) (hash []b return nil, nil } -func (i *MockRegistration) RegisterNode(ID []byte, ServerAddr, ServerTlsCert, +func (i *MockRegistration) RegisterNode(ID *id.ID, ServerAddr, ServerTlsCert, GatewayAddr, GatewayTlsCert, RegistrationCode string) error { return nil } @@ -68,7 +68,11 @@ func (i *MockRegistration) PollNdf(clientNdfHash []byte, return ndfJson, nil } -func (i *MockRegistration) Poll(*pb.PermissioningPoll, *connect.Auth) (*pb.PermissionPollResponse, error) { +func (i *MockRegistration) Poll(*pb.PermissioningPoll, *connect.Auth, string) (*pb.PermissionPollResponse, error) { + return nil, nil +} + +func (i *MockRegistration) CheckRegistration(msg *pb.RegisteredNodeCheck) (*pb.RegisteredNodeConfirmation, error) { return nil, nil } @@ -358,12 +362,14 @@ func TestClient_Send(t *testing.T) { t.Errorf("Could not start message reception: %+v", err) } + receiverID := id.NewIdFromBytes(userID, t) + receiverID.SetType(id.User) // Test send with invalid sender ID _, err = testClient.Send( mockMesssage{ - Sender: id.NewUserFromUint(12, t), + Sender: id.NewIdFromUInt(12, id.User, t), TypedBody: parse.TypedBody{Body: []byte("test")}, - Receiver: id.NewUserFromBytes(userID), + Receiver: receiverID, }, false) if err != nil { @@ -375,7 +381,7 @@ func TestClient_Send(t *testing.T) { // Test send with valid inputs _, err = testClient.Send( mockMesssage{ - Sender: id.NewUserFromBytes(userID), + Sender: id.NewIdFromBytes(userID, t), TypedBody: parse.TypedBody{Body: []byte("test")}, Receiver: testClient.client.GetCurrentUser(), }, false) @@ -468,13 +474,13 @@ func TestListen(t *testing.T) { } listener := MockListener(false) - client.Listen(id.ZeroID[:], int32(cmixproto.Type_NO_TYPE), &listener) + client.Listen(id.ZeroUser[:], int32(cmixproto.Type_NO_TYPE), &listener) client.client.GetSwitchboard().Speak(&parse.Message{ TypedBody: parse.TypedBody{ MessageType: 0, Body: []byte("stuff"), }, - Sender: id.ZeroID, + Sender: &id.ZeroUser, Receiver: client.client.GetCurrentUser(), }) time.Sleep(time.Second) @@ -513,15 +519,18 @@ func TestStopListening(t *testing.T) { } listener := MockListener(false) - handle := client.Listen(id.ZeroID[:], int32(cmixproto.Type_NO_TYPE), &listener) + handle, err := client.Listen(id.ZeroUser[:], int32(cmixproto.Type_NO_TYPE), &listener) + if err != nil { + t.Fatal(err) + } client.StopListening(handle) client.client.GetSwitchboard().Speak(&parse.Message{ TypedBody: parse.TypedBody{ MessageType: 0, Body: []byte("stuff"), }, - Sender: id.ZeroID, - Receiver: id.ZeroID, + Sender: &id.ZeroUser, + Receiver: &id.ZeroUser, }) if listener { t.Error("Message was received after we stopped listening for it") @@ -551,8 +560,8 @@ func TestParse(t *testing.T) { ms := parse.Message{} ms.Body = []byte{0, 1, 2} ms.MessageType = int32(cmixproto.Type_NO_TYPE) - ms.Receiver = id.ZeroID - ms.Sender = id.ZeroID + ms.Receiver = &id.ZeroUser + ms.Sender = &id.ZeroUser messagePacked := ms.Pack() @@ -604,20 +613,29 @@ func testMainWrapper(m *testing.M) int { def = getNDF() // Initialize permissioning server + // TODO(nan) We shouldn't need to start registration servers twice, right? pAddr := def.Registration.Address - RegComms = registration.StartRegistrationServer("testRegServer", pAddr, &RegHandler, nil, nil) + regId := new(id.ID) + copy(regId[:], "testRegServer") + regId.SetType(id.Generic) + RegComms = registration.StartRegistrationServer(regId, pAddr, + &RegHandler, nil, nil) // Start mock gateways used by registration and defer their shutdown (may not be needed) //the ports used are colliding between tests in GoLand when running full suite, this is a dumb fix bump := rand.Intn(10) * 10 for i := 0; i < NumGWs; i++ { + gwId := new(id.ID) + copy(gwId[:], "testGateway") + gwId.SetType(id.Gateway) gw := ndf.Gateway{ + ID: gwId.Marshal(), Address: fmtAddress(GWsStartPort + i + bump), } def.Gateways = append(def.Gateways, gw) - GWComms[i] = gateway.StartGateway("testGateway", gw.Address, + GWComms[i] = gateway.StartGateway(gwId, gw.Address, gateway.NewImplementation(), nil, nil) } @@ -625,14 +643,15 @@ func testMainWrapper(m *testing.M) int { def.Registration = ndf.Registration{ Address: fmtAddress(RegPort), } - RegComms = registration.StartRegistrationServer("testRegServer", def.Registration.Address, + RegComms = registration.StartRegistrationServer(regId, def.Registration.Address, &RegHandler, nil, nil) for i := 0; i < NumNodes; i++ { - nIdBytes := make([]byte, id.NodeIdLen) - nIdBytes[0] = byte(i) + nId := new(id.ID) + nId[0] = byte(i) + nId.SetType(id.Node) n := ndf.Node{ - ID: nIdBytes, + ID: nId[:], } def.Nodes = append(def.Nodes, n) } @@ -749,8 +768,8 @@ type mockMesssage struct { parse.TypedBody // The crypto type is inferred from the message's contents InferredType parse.CryptoType - Sender *id.User - Receiver *id.User + Sender *id.ID + Receiver *id.ID Nonce []byte Timestamp time.Time } diff --git a/bots/bots.go b/bots/bots.go index b40537aa4beba5ad0f60caa04fff2a2ab57e600b..6cf0bdc3cee88b91aa0bc11a279cf0789a3a39ce 100644 --- a/bots/bots.go +++ b/bots/bots.go @@ -6,9 +6,9 @@ import ( "gitlab.com/elixxir/client/io" "gitlab.com/elixxir/client/parse" "gitlab.com/elixxir/client/user" - "gitlab.com/elixxir/comms/connect" "gitlab.com/elixxir/primitives/id" "gitlab.com/elixxir/primitives/switchboard" + "gitlab.com/xx_network/comms/connect" ) var session user.Session @@ -16,9 +16,6 @@ var topology *connect.Circuit var comms io.Communications var transmissionHost *connect.Host -// UdbID is the ID of the user discovery bot, which is always 3 -var UdbID *id.User - type channelResponseListener chan string func (l *channelResponseListener) Hear(msg switchboard.Item, isHeardElsewhere bool, i ...interface{}) { @@ -50,9 +47,7 @@ func (l *nickReqListener) Hear(msg switchboard.Item, isHeardElsewhere bool, i .. var nicknameRequestListener nickReqListener // InitBots is called internally by the Login API -func InitBots(s user.Session, m io.Communications, top *connect.Circuit, udbID *id.User, host *connect.Host) { - UdbID = udbID - +func InitBots(s user.Session, m io.Communications, top *connect.Circuit, host *connect.Host) { // FIXME: these all need to be used in non-blocking threads if we are // going to do it this way... msgBufSize := 100 @@ -70,30 +65,30 @@ func InitBots(s user.Session, m io.Communications, top *connect.Circuit, udbID * l := session.GetSwitchboard() - l.Register(UdbID, int32(cmixproto.Type_UDB_PUSH_KEY_RESPONSE), + l.Register(&id.UDB, int32(cmixproto.Type_UDB_PUSH_KEY_RESPONSE), &pushKeyResponseListener) - l.Register(UdbID, int32(cmixproto.Type_UDB_GET_KEY_RESPONSE), + l.Register(&id.UDB, int32(cmixproto.Type_UDB_GET_KEY_RESPONSE), &getKeyResponseListener) - l.Register(UdbID, int32(cmixproto.Type_UDB_REGISTER_RESPONSE), + l.Register(&id.UDB, int32(cmixproto.Type_UDB_REGISTER_RESPONSE), ®isterResponseListener) - l.Register(UdbID, int32(cmixproto.Type_UDB_SEARCH_RESPONSE), + l.Register(&id.UDB, int32(cmixproto.Type_UDB_SEARCH_RESPONSE), &searchResponseListener) - l.Register(id.ZeroID, + l.Register(&id.ZeroUser, int32(cmixproto.Type_NICKNAME_REQUEST), &nicknameRequestListener) - l.Register(id.ZeroID, + l.Register(&id.ZeroUser, int32(cmixproto.Type_NICKNAME_RESPONSE), &nicknameResponseListener) } // sendCommand sends a command to the udb. This doesn't block. // Callers that need to wait on a response should implement waiting with a // listener. -func sendCommand(botID *id.User, command []byte) error { +func sendCommand(botID *id.ID, command []byte) error { return comms.SendMessage(session, topology, botID, parse.Unencrypted, command, transmissionHost) } // Nickname Lookup function -func LookupNick(user *id.User) (string, error) { +func LookupNick(user *id.ID) (string, error) { globals.Log.DEBUG.Printf("Sending nickname request to user %v", *user) msg := parse.Pack(&parse.TypedBody{ MessageType: int32(cmixproto.Type_NICKNAME_REQUEST), diff --git a/bots/bots_test.go b/bots/bots_test.go index c6628b29a78cb425298a2c25b60df832a40f9b52..6f0c7edba4e04504b780cf8039028940a7e25986 100644 --- a/bots/bots_test.go +++ b/bots/bots_test.go @@ -9,6 +9,7 @@ package bots import ( "encoding/base64" + "encoding/binary" "fmt" "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" @@ -16,11 +17,11 @@ import ( "gitlab.com/elixxir/client/globals" "gitlab.com/elixxir/client/parse" "gitlab.com/elixxir/client/user" - "gitlab.com/elixxir/comms/connect" "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/crypto/large" "gitlab.com/elixxir/primitives/format" "gitlab.com/elixxir/primitives/id" + "gitlab.com/xx_network/comms/connect" "os" "strings" "testing" @@ -36,7 +37,7 @@ type dummyMessaging struct { // SendMessage to the server func (d *dummyMessaging) SendMessage(sess user.Session, topology *connect.Circuit, - recipientID *id.User, + recipientID *id.ID, cryptoType parse.CryptoType, message []byte, transmissionHost *connect.Host) error { jww.INFO.Printf("Sending: %s", string(message)) @@ -46,7 +47,7 @@ func (d *dummyMessaging) SendMessage(sess user.Session, // SendMessage without partitions to the server func (d *dummyMessaging) SendMessageNoPartition(sess user.Session, topology *connect.Circuit, - recipientID *id.User, + recipientID *id.ID, cryptoType parse.CryptoType, message []byte, transmissionHost *connect.Host) error { jww.INFO.Printf("Sending: %s", string(message)) @@ -64,9 +65,11 @@ var pubKey []byte func TestMain(m *testing.M) { u := &user.User{ - User: id.NewUserFromUints(&[4]uint64{0, 0, 0, 18}), + User: new(id.ID), Username: "Bernie", } + binary.BigEndian.PutUint64(u.User[:], 18) + u.User.SetType(id.User) cmixGrp, e2eGrp := getGroups() @@ -78,9 +81,11 @@ func TestMain(m *testing.M) { listener: ListenCh, } h := connect.Host{} - topology := connect.NewCircuit([]*id.Node{id.NewNodeFromBytes(make([]byte, id.NodeIdLen))}) + nodeID := new(id.ID) + nodeID.SetType(id.Node) + topology := connect.NewCircuit([]*id.ID{nodeID}) - InitBots(fakeSession, fakeComm, topology, id.NewUserFromBytes([]byte("testid")), &h) + InitBots(fakeSession, fakeComm, topology, &h) // Make the reception channels buffered for this test // which overwrites the channels registered in InitBots @@ -121,9 +126,14 @@ func TestRegister(t *testing.T) { // TestSearch smoke tests the search function func TestSearch(t *testing.T) { publicKeyString := base64.StdEncoding.EncodeToString(pubKey) + //uid := id.NewIdFromUInt(26, id.User, t) + //serRetUid := base64.StdEncoding.EncodeToString(uid[:]) + //result, _ := base64.StdEncoding.DecodeString(serRetUid) + //t.Fatal(serRetUid) + //t.Fatal(len(result)) // Send response messages from fake UDB in advance - searchResponseListener <- "blah@elixxir.io FOUND UR69db14ZyicpZVqJ1HFC5rk9UZ8817aV6+VHmrJpGc= AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABo= 8oKh7TYG4KxQcBAymoXPBHSD/uga9pX3Mn/jKhvcD8M=" + searchResponseListener <- "blah@elixxir.io FOUND UR69db14ZyicpZVqJ1HFC5rk9UZ8817aV6+VHmrJpGc= AAAAAAAAABoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD 8oKh7TYG4KxQcBAymoXPBHSD/uga9pX3Mn/jKhvcD8M=" getKeyResponseListener <- fmt.Sprintf("GETKEY %s %s", keyFingerprint, publicKeyString) @@ -136,8 +146,8 @@ func TestSearch(t *testing.T) { if err != nil { t.Errorf("Error on Search: %s", err.Error()) } - if *searchedUser != *id.NewUserFromUint(26, t) { - t.Errorf("Search did not return user ID 26! returned %v", string(searchedUser.Bytes())) + if !searchedUser.Cmp(id.NewIdFromUInt(26, id.User, t)) { + t.Errorf("Search did not return user ID 26! returned %s", searchedUser) } //Test the timeout capabilities searchedUser, _, err = Search("EMAIL", "blah@elixxir.io", dummySearchState, 1*time.Millisecond) @@ -190,7 +200,7 @@ type errorMessaging struct{} // SendMessage that just errors out func (e *errorMessaging) SendMessage(sess user.Session, topology *connect.Circuit, - recipientID *id.User, + recipientID *id.ID, cryptoType parse.CryptoType, message []byte, transmissionHost *connect.Host) error { return errors.New("This is an error") @@ -199,7 +209,7 @@ func (e *errorMessaging) SendMessage(sess user.Session, // SendMessage no partition that just errors out func (e *errorMessaging) SendMessageNoPartition(sess user.Session, topology *connect.Circuit, - recipientID *id.User, + recipientID *id.ID, cryptoType parse.CryptoType, message []byte, transmissionHost *connect.Host) error { return errors.New("This is an error") diff --git a/bots/userDiscovery.go b/bots/userDiscovery.go index 35cd3970051e04839b5fb406536147f804d18b90..d84976c955d24e3814939419a7d3c8541dae07fc 100644 --- a/bots/userDiscovery.go +++ b/bots/userDiscovery.go @@ -46,7 +46,7 @@ func Register(valueType, value string, publicKey []byte, regStatus func(int), ti regStatus(globals.UDB_REG_PUSHKEY) // push key and error if it already exists - err = pushKey(UdbID, keyFP, publicKey) + err = pushKey(keyFP, publicKey) if err != nil { return errors.Wrap(err, "Could not PUSHKEY") @@ -84,7 +84,7 @@ func Register(valueType, value string, publicKey []byte, regStatus func(int), ti // Send register command // Send register command - err = sendCommand(UdbID, msgBody) + err = sendCommand(&id.UDB, msgBody) if err != nil { return errors.Wrap(err, "Could not Push User") } @@ -114,7 +114,7 @@ func Register(valueType, value string, publicKey []byte, regStatus func(int), ti // Search returns a userID and public key based on the search criteria // it accepts a valueType of EMAIL and value of an e-mail address, and // returns a map of userid -> public key -func Search(valueType, value string, searchStatus func(int), timeout time.Duration) (*id.User, []byte, error) { +func Search(valueType, value string, searchStatus func(int), timeout time.Duration) (*id.ID, []byte, error) { globals.Log.DEBUG.Printf("Running search for %v, %v", valueType, value) searchTimeout := time.NewTimer(timeout) @@ -133,7 +133,7 @@ func Search(valueType, value string, searchStatus func(int), timeout time.Durati MessageType: int32(cmixproto.Type_UDB_SEARCH), Body: []byte(fmt.Sprintf("%s %s", valueType, value)), }) - err = sendCommand(UdbID, msgBody) + err = sendCommand(&id.UDB, msgBody) if err != nil { return nil, nil, err } @@ -160,9 +160,9 @@ func Search(valueType, value string, searchStatus func(int), timeout time.Durati } // While search returns more than 1 result, we only process the first - cMixUID, keyFP := parseSearch(response) - if *cMixUID == *id.ZeroID { - return nil, nil, fmt.Errorf("%s", keyFP) + cMixUID, keyFP, err := parseSearch(response) + if err != nil { + return nil, nil, err } searchStatus(globals.UDB_SEARCH_GETKEY) @@ -172,7 +172,7 @@ func Search(valueType, value string, searchStatus func(int), timeout time.Durati MessageType: int32(cmixproto.Type_UDB_GET_KEY), Body: []byte(keyFP), }) - err = sendCommand(UdbID, msgBody) + err = sendCommand(&id.UDB, msgBody) if err != nil { return nil, nil, err } @@ -221,20 +221,23 @@ func hashAndEncode(s string) (string, error) { // parseSearch parses the responses from SEARCH. It returns the user's id and // the user's public key fingerprint -func parseSearch(msg string) (*id.User, string) { +func parseSearch(msg string) (*id.ID, string, error) { globals.Log.DEBUG.Printf("Parsing search response: %v", msg) resParts := strings.Split(msg, " ") if len(resParts) != 5 { - return id.ZeroID, fmt.Sprintf("Invalid response from search: %s", msg) + return &id.ZeroUser, "", errors.WithMessagef(errors.New("Invalid response from search"), ": %s", msg) } cMixUIDBytes, err := base64.StdEncoding.DecodeString(resParts[3]) if err != nil { - return id.ZeroID, fmt.Sprintf("Couldn't parse search cMix UID: %s", msg) + return &id.ZeroUser, "", errors.WithMessagef(errors.New("Couldn't parse search cMix UID"), ": %s", msg) + } + cMixUID, err := id.Unmarshal(cMixUIDBytes) + if err != nil { + return &id.ZeroUser, "", err } - cMixUID := id.NewUserFromBytes(cMixUIDBytes) - return cMixUID, resParts[4] + return cMixUID, resParts[4], nil } // parseGetKey parses the responses from GETKEY. It returns the @@ -254,14 +257,14 @@ func parseGetKey(msg string) []byte { } // pushKey uploads the users' public key -func pushKey(udbID *id.User, keyFP string, publicKey []byte) error { +func pushKey(keyFP string, publicKey []byte) error { publicKeyString := base64.StdEncoding.EncodeToString(publicKey) - globals.Log.DEBUG.Printf("Running pushkey for %q, %v, %v", *udbID, keyFP, + globals.Log.DEBUG.Printf("Running pushkey for %v, %v, %v", id.UDB, keyFP, publicKeyString) pushKeyMsg := fmt.Sprintf("%s %s", keyFP, publicKeyString) - return sendCommand(udbID, parse.Pack(&parse.TypedBody{ + return sendCommand(&id.UDB, parse.Pack(&parse.TypedBody{ MessageType: int32(cmixproto.Type_UDB_PUSH_KEY), Body: []byte(pushKeyMsg), })) diff --git a/cmd/root.go b/cmd/root.go index cb96a47e6beb53eab7f7a32220b25040a8f4bdc2..c61e825a24dcb4eae57cae5fd6c61eca64955142 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -9,18 +9,17 @@ package cmd import ( "encoding/base64" + "encoding/binary" "fmt" "github.com/golang/protobuf/proto" "github.com/spf13/cobra" jww "github.com/spf13/jwalterweatherman" "github.com/spf13/viper" "gitlab.com/elixxir/client/api" - "gitlab.com/elixxir/client/bots" "gitlab.com/elixxir/client/cmixproto" "gitlab.com/elixxir/client/globals" "gitlab.com/elixxir/client/parse" "gitlab.com/elixxir/client/user" - "gitlab.com/elixxir/crypto/large" "gitlab.com/elixxir/crypto/signature/rsa" "gitlab.com/elixxir/primitives/id" "gitlab.com/elixxir/primitives/switchboard" @@ -69,7 +68,7 @@ func Execute() { } } -func sessionInitialization() (*id.User, string, *api.Client) { +func sessionInitialization() (*id.ID, string, *api.Client) { var err error register := false @@ -111,7 +110,7 @@ func sessionInitialization() (*id.User, string, *api.Client) { if err != nil { globals.Log.ERROR.Printf("Could Not Initialize Ram Storage: %s\n", err.Error()) - return id.ZeroID, "", nil + return &id.ZeroUser, "", nil } globals.Log.INFO.Println("Initialized Ram Storage") register = true @@ -141,14 +140,14 @@ func sessionInitialization() (*id.User, string, *api.Client) { //Fail if any other error is received globals.Log.ERROR.Printf("Error with file paths: %s %s", err1, err2) - return id.ZeroID, "", nil + return &id.ZeroUser, "", nil } } //Initialize client with OS Storage client, err = api.NewClient(nil, sessionA, sessionB, ndfJSON) if err != nil { globals.Log.ERROR.Printf("Could Not Initialize OS Storage: %s\n", err.Error()) - return id.ZeroID, "", nil + return &id.ZeroUser, "", nil } globals.Log.INFO.Println("Initialized OS Storage") @@ -169,7 +168,7 @@ func sessionInitialization() (*id.User, string, *api.Client) { // No gateways in config file or passed via command line globals.Log.ERROR.Printf("Error: No gateway specified! Add to" + " configuration file or pass via command line using -g!\n") - return id.ZeroID, "", nil + return &id.ZeroUser, "", nil }*/ if noTLS { @@ -185,7 +184,7 @@ func sessionInitialization() (*id.User, string, *api.Client) { client.SetRateLimiting(rateLimiting) // Holds the User ID - var uid *id.User + var uid *id.ID // Register a new user if requested if register { @@ -195,7 +194,10 @@ func sessionInitialization() (*id.User, string, *api.Client) { // If precanned user, use generated code instead if userId != 0 { precanned = true - regCode = id.NewUserFromUints(&[4]uint64{0, 0, 0, userId}).RegistrationCode() + uid := new(id.ID) + binary.BigEndian.PutUint64(uid[:], userId) + uid.SetType(id.User) + regCode = user.RegistrationCode(uid) } globals.Log.INFO.Printf("Building keys...") @@ -224,10 +226,10 @@ func sessionInitialization() (*id.User, string, *api.Client) { globals.Log.INFO.Printf("Attempting to register with code %s...", regCode) errRegister := fmt.Errorf("") - uid = client.GetCurrentUser() + //Attempt to register user with same keys until a success occurs for errRegister != nil { - _, errRegister = client.RegisterWithPermissioning(userId != 0, regCode) + _, errRegister = client.RegisterWithPermissioning(precanned, regCode) if errRegister != nil { globals.Log.FATAL.Panicf("Could Not Register User: %s", errRegister.Error()) @@ -240,6 +242,8 @@ func sessionInitialization() (*id.User, string, *api.Client) { err.Error()) } + uid = client.GetCurrentUser() + userbase64 := base64.StdEncoding.EncodeToString(uid[:]) globals.Log.INFO.Printf("Registered as user (uid, the var) %v", uid) globals.Log.INFO.Printf("Registered as user (userID, the global) %v", userId) @@ -248,7 +252,9 @@ func sessionInitialization() (*id.User, string, *api.Client) { } else { // hack for session persisting with cmd line // doesn't support non pre canned users - uid = id.NewUserFromUints(&[4]uint64{0, 0, 0, userId}) + uid := new(id.ID) + binary.BigEndian.PutUint64(uid[:], userId) + uid.SetType(id.User) globals.Log.INFO.Printf("Skipped Registration, user: %v", uid) } @@ -319,7 +325,7 @@ func (l *FallbackListener) Hear(item switchboard.Item, isHeardElsewhere bool, i } atomic.AddInt64(&l.MessagesReceived, 1) globals.Log.INFO.Printf("Message of type %v from %q, %v received with fallback: %s\n", - message.MessageType, *message.Sender, senderNick, + message.MessageType, printIDNice(message.Sender), senderNick, string(message.Body)) } } @@ -341,7 +347,7 @@ func (l *TextListener) Hear(item switchboard.Item, isHeardElsewhere bool, i ...i sender, ok := user.Users.GetUser(message.Sender) var senderNick string if !ok { - globals.Log.INFO.Printf("First message from sender %v", message.Sender) + globals.Log.INFO.Printf("First message from sender %v", printIDNice(message.Sender)) u := user.Users.NewUser(message.Sender, base64.StdEncoding.EncodeToString(message.Sender[:])) user.Users.UpsertUser(u) senderNick = u.Username @@ -349,7 +355,7 @@ func (l *TextListener) Hear(item switchboard.Item, isHeardElsewhere bool, i ...i senderNick = sender.Username } logMsg := fmt.Sprintf("Message from %v, %v Received: %s\n", - large.NewIntFromBytes(message.Sender[:]).Text(10), + printIDNice(message.Sender), senderNick, result.Message) globals.Log.INFO.Printf("%s -- Timestamp: %s\n", logMsg, message.Timestamp.String()) @@ -406,11 +412,11 @@ var rootCmd = &cobra.Command{ // the integration test // Normal text messages text := TextListener{} - client.Listen(id.ZeroID, int32(cmixproto.Type_TEXT_MESSAGE), + client.Listen(&id.ZeroUser, int32(cmixproto.Type_TEXT_MESSAGE), &text) // All other messages fallback := FallbackListener{} - client.Listen(id.ZeroID, int32(cmixproto.Type_NO_TYPE), + client.Listen(&id.ZeroUser, int32(cmixproto.Type_NO_TYPE), &fallback) // Log the user in, for now using the first gateway specified @@ -422,7 +428,7 @@ var rootCmd = &cobra.Command{ err = client.InitListeners() if err != nil { - globals.Log.FATAL.Panicf("Could not initialize receivers: %s\n", err) + globals.Log.FATAL.Panicf("Could not initialize receivers: %+v\n", err) } err = client.StartMessageReceiver(cb) @@ -447,7 +453,7 @@ var rootCmd = &cobra.Command{ cryptoType = parse.E2E } - var recipientId *id.User + var recipientId *id.ID if destinationUserId != 0 && destinationUserIDBase64 != "" { globals.Log.FATAL.Panicf("Two destiantions set for the message, can only have one") @@ -460,10 +466,15 @@ var rootCmd = &cobra.Command{ if err != nil { globals.Log.FATAL.Panic("Could not decode the destination user ID") } - recipientId = id.NewUserFromBytes(recipientIdBytes) - + recipientId, err = id.Unmarshal(recipientIdBytes) + if err != nil { + // Destination user ID must be 33 bytes and include the id type + globals.Log.FATAL.Panicf("Could not unmarshal destination user ID: %v", err) + } } else { - recipientId = id.NewUserFromUints(&[4]uint64{0, 0, 0, destinationUserId}) + recipientId = new(id.ID) + binary.BigEndian.PutUint64(recipientId[:], destinationUserId) + recipientId.SetType(id.User) } if message != "" { @@ -475,7 +486,7 @@ var rootCmd = &cobra.Command{ } // Handle sending to UDB - if *recipientId == *bots.UdbID { + if recipientId.Cmp(&id.UDB) { parseUdbMessage(message, client) } else { // Handle sending to any other destination @@ -484,10 +495,7 @@ var rootCmd = &cobra.Command{ for i := uint(0); i < messageCnt; i++ { logMsg := fmt.Sprintf( "Sending Message to "+ - "%s, %v: %s\n", - large.NewIntFromBytes( - recipientId[:]).Text( - 10), + "%s, %v: %s\n", printIDNice(recipientId), recipientNick, message) globals.Log.INFO.Printf(logMsg) fmt.Printf(logMsg) @@ -551,10 +559,9 @@ var rootCmd = &cobra.Command{ if searchForUser != "" { foundUser := <-udbLister.(*userSearcher).foundUserChan - if isValidUser(foundUser) { - userIDBase64 := base64.StdEncoding.EncodeToString(foundUser) + if isValid, uid := isValidUser(foundUser); isValid { globals.Log.INFO.Printf("Found User %s at ID: %s", - searchForUser, userIDBase64) + searchForUser, printIDNice(uid)) } else { globals.Log.INFO.Printf("Found User %s is invalid", searchForUser) } @@ -578,16 +585,21 @@ var rootCmd = &cobra.Command{ }, } -func isValidUser(usr []byte) bool { - if len(usr) != id.UserLen { - return false +func isValidUser(usr []byte) (bool, *id.ID) { + if len(usr) != id.ArrIDLen { + return false, nil } for _, b := range usr { if b != 0 { - return true + uid, err := id.Unmarshal(usr) + if err != nil { + globals.Log.WARN.Printf("Could not unmarshal user: %s", err) + return false, nil + } + return true, uid } } - return false + return false, nil } // init is the initialization function for Cobra which defines commands @@ -703,3 +715,34 @@ func init() { // initConfig reads in config file and ENV variables if set. func initConfig() {} + +// returns a simple numerical id if the user is a precanned user, otherwise +// returns the normal string of the userID +func printIDNice(uid *id.ID) string { + + for index, puid := range precannedIDList { + if uid.Cmp(puid) { + return strconv.Itoa(index + 1) + } + } + + return uid.String() +} + +// build a list of precanned ids to use for comparision for nicer user id output +var precannedIDList = buildPrecannedIDList() + +func buildPrecannedIDList() []*id.ID { + + idList := make([]*id.ID, 40) + + for i := 0; i < 40; i++ { + uid := new(id.ID) + binary.BigEndian.PutUint64(uid[:], uint64(i+1)) + uid.SetType(id.User) + idList[i] = uid + } + + return idList +} + diff --git a/cmd/udb.go b/cmd/udb.go index 3b234d6e06ff687e219ccfff9c4c22e4ab1a1e83..ed39e5d8be21880cc3b3540c64d214c8f6e87b12 100644 --- a/cmd/udb.go +++ b/cmd/udb.go @@ -22,8 +22,12 @@ func (cs callbackSearch) Callback(userID, pubKey []byte, err error) { } else if len(pubKey) == 0 { globals.Log.INFO.Printf("Public Key returned is empty\n") } else { + userID, err := id.Unmarshal(userID) + if err != nil { + globals.Log.ERROR.Printf("Malformed user ID from successful UDB search: %v", err) + } globals.Log.INFO.Printf("UDB search successful. Returned user %v\n", - *id.NewUserFromBytes(userID)) + userID) } } diff --git a/cmd/version.go b/cmd/version.go index 1555261dad8260e5e020855e618913007b478341..364bd0f0856c10212984bac2abdc64d38f57cd84 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -16,7 +16,7 @@ import ( ) // Change this value to set the version for this build -const currentVersion = "1.3.0" +const currentVersion = "1.4.0" func printVersion() { fmt.Printf("Elixxir Client v%s -- %s\n\n", globals.SEMVER, globals.GITVERSION) diff --git a/crypto/encrypt.go b/crypto/encrypt.go index 7cfe6fe504820f8943b49507a286e1af567a2ac2..7686521401474733e45bc47b508e90501d4ef8ea 100644 --- a/crypto/encrypt.go +++ b/crypto/encrypt.go @@ -9,12 +9,12 @@ package crypto import ( "gitlab.com/elixxir/client/globals" "gitlab.com/elixxir/client/user" - "gitlab.com/elixxir/comms/connect" "gitlab.com/elixxir/crypto/cmix" "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/crypto/e2e" "gitlab.com/elixxir/crypto/hash" "gitlab.com/elixxir/primitives/format" + "gitlab.com/xx_network/comms/connect" ) // CMIX Encrypt performs the encryption diff --git a/crypto/encryptdecrypt_test.go b/crypto/encryptdecrypt_test.go index b94d74a3d5b720ca85259f8e9eaf1fcbbd3a31c3..7cc9ad2c852126e10e63b560486946d7864f3066 100644 --- a/crypto/encryptdecrypt_test.go +++ b/crypto/encryptdecrypt_test.go @@ -8,8 +8,8 @@ package crypto import ( "bytes" + "encoding/binary" "gitlab.com/elixxir/client/user" - "gitlab.com/elixxir/comms/connect" pb "gitlab.com/elixxir/comms/mixmessages" "gitlab.com/elixxir/crypto/cmix" "gitlab.com/elixxir/crypto/cyclic" @@ -17,6 +17,7 @@ import ( "gitlab.com/elixxir/crypto/large" "gitlab.com/elixxir/primitives/format" "gitlab.com/elixxir/primitives/id" + "gitlab.com/xx_network/comms/connect" "golang.org/x/crypto/blake2b" "os" "testing" @@ -40,16 +41,21 @@ func setup() { user.InitUserRegistry(cmixGrp) - UID := id.NewUserFromUints(&[4]uint64{0, 0, 0, 18}) - u, _ := user.Users.GetUser(UID) + UID := new(id.ID) + binary.BigEndian.PutUint64(UID[:], 18) + UID.SetType(id.User) + u, ok := user.Users.GetUser(UID) + if !ok { + panic("Didn't get user 18 from registry") + } - var nodeSlice []*id.Node + var nodeSlice []*id.ID //build topology for i := 0; i < numNodes; i++ { - nodeBytes := make([]byte, id.NodeIdLen) - nodeBytes[0] = byte(i) - nodeId := id.NewNodeFromBytes(nodeBytes) + nodeId := new(id.ID) + nodeId[0] = byte(i) + nodeId.SetType(id.Node) nodeSlice = append(nodeSlice, nodeId) } @@ -93,8 +99,8 @@ func TestMain(m *testing.M) { func TestFullEncryptDecrypt(t *testing.T) { cmixGrp, e2eGrp := getGroups() - sender := id.NewUserFromUint(38, t) - recipient := id.NewUserFromUint(29, t) + sender := id.NewIdFromUInt(38, id.User, t) + recipient := id.NewIdFromUInt(29, id.User, t) msg := format.NewMessage() msg.SetRecipient(recipient) msgPayload := []byte("help me, i'm stuck in an" + @@ -141,9 +147,14 @@ func TestFullEncryptDecrypt(t *testing.T) { t.Errorf("E2EDecrypt returned error: %v", err.Error()) } - if *decMsg.GetRecipient() != *recipient { + decryptedRecipient, err := decMsg.GetRecipient() + if err != nil { + t.Fatal(err) + } + + if !decryptedRecipient.Cmp(recipient) { t.Errorf("Recipient differed from expected: Got %q, expected %q", - decMsg.GetRecipient(), sender) + decryptedRecipient, sender) } if !bytes.Equal(decMsg.Contents.GetRightAligned(), msgPayload) { t.Errorf("Decrypted payload differed from expected: Got %q, "+ @@ -155,8 +166,8 @@ func TestFullEncryptDecrypt(t *testing.T) { // to be sent occupies the whole payload structure, i.e. 256 bytes func TestFullEncryptDecrypt_Unsafe(t *testing.T) { cmixGrp, e2eGrp := getGroups() - sender := id.NewUserFromUint(38, t) - recipient := id.NewUserFromUint(29, t) + sender := id.NewIdFromUInt(38, id.User, t) + recipient := id.NewIdFromUInt(29, id.User, t) msg := format.NewMessage() msg.SetRecipient(recipient) msgPayload := []byte( @@ -212,9 +223,14 @@ func TestFullEncryptDecrypt_Unsafe(t *testing.T) { t.Errorf("E2EDecryptUnsafe returned error: %v", err.Error()) } - if *decMsg.GetRecipient() != *recipient { + decryptedRecipient, err := decMsg.GetRecipient() + if err != nil { + t.Fatal(err) + } + + if !decryptedRecipient.Cmp(recipient) { t.Errorf("Recipient differed from expected: Got %q, expected %q", - decMsg.GetRecipient(), sender) + decryptedRecipient, sender) } if !bytes.Equal(decMsg.Contents.Get(), msgPayload[:format.ContentsLen]) { t.Errorf("Decrypted payload differed from expected: Got %q, "+ @@ -225,7 +241,7 @@ func TestFullEncryptDecrypt_Unsafe(t *testing.T) { // Test that E2EEncrypt panics if the payload is too big (can't be padded) func TestE2EEncrypt_Panic(t *testing.T) { _, e2eGrp := getGroups() - recipient := id.NewUserFromUint(29, t) + recipient := id.NewIdFromUInt(29, id.User, t) msg := format.NewMessage() msg.SetRecipient(recipient) msgPayload := []byte("help me, i'm stuck in an" + @@ -258,7 +274,7 @@ func TestE2EEncrypt_Panic(t *testing.T) { // Test that E2EDecrypt and E2EDecryptUnsafe handle errors correctly func TestE2EDecrypt_Errors(t *testing.T) { _, e2eGrp := getGroups() - recipient := id.NewUserFromUint(29, t) + recipient := id.NewIdFromUInt(29, id.User, t) msg := format.NewMessage() msg.SetRecipient(recipient) msgPayload := []byte("help me, i'm stuck in an EnterpriseTextLabelDescriptorSetPipelineStateFactoryBeanFactory ") diff --git a/globals/checkVersion.go b/globals/checkVersion.go deleted file mode 100644 index a9517bacdf154906be194753f66c82904837bf88..0000000000000000000000000000000000000000 --- a/globals/checkVersion.go +++ /dev/null @@ -1,87 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 Privategrity Corporation / -// / -// All rights reserved. / -//////////////////////////////////////////////////////////////////////////////// - -package globals - -import ( - "github.com/pkg/errors" - "strconv" - "strings" -) - -type clientVersion struct { - major int - minor int - patch string -} - -func (v *clientVersion) String() string { - return strconv.Itoa(v.major) + "." + strconv.Itoa(v.minor) + "." + v.patch -} - -func parseClientVersion(versionString string) (*clientVersion, error) { - versions := strings.SplitN(versionString, ".", 3) - if len(versions) != 3 { - return nil, errors.New("Client version string must contain a major, minor, and patch version separated by \".\"") - } - major, err := strconv.Atoi(versions[0]) - if err != nil { - return nil, errors.New("Major client version couldn't be parsed as integer") - } - minor, err := strconv.Atoi(versions[1]) - if err != nil { - return nil, errors.New("Minor client version couldn't be parsed as integer") - } - return &clientVersion{ - major: major, - minor: minor, - patch: versions[2], - }, nil -} - -// Handle client version check -// Example valid version strings: -// 0.1.0 -// 1.3.0-ff81cdae -// Major and minor versions should both be numbers, and patch versions can be -// anything, but they must be present -// receiver is the version from the registration server -func (v *clientVersion) isCompatible(theirVersion *clientVersion) bool { - // Compare major version: must be equal to be deemed compatible - if theirVersion.major != v.major { - return false - } - // Compare minor version: our version must be greater than or equal to their version to be deemed compatible - if theirVersion.minor > v.minor { - return false - } - // Patch versions aren't supposed to affect compatibility, so they're ignored for the check - - return true -} - -// Parse both versions and ensure they're compatible -// Ours is the local version of the client library, theirs is the version on the -// registration server -func checkVersion(ours string, theirs string) (ok bool, err error) { - theirVersion, err := parseClientVersion(theirs) - if err != nil { - return false, errors.Wrapf(err, - "Error parsing permissioning's version (%v)", theirs) - } - ourVersion, err := parseClientVersion(ours) - if err != nil { - return false, errors.Wrapf(err, - "Error parsing our version (%v)", ours) - } - return ourVersion.isCompatible(theirVersion), nil -} - -// Utility method, returns whether the local version and remote version are -// compatible -func CheckVersion(ver string) (bool, error) { // again, version stuff, move to globals - return checkVersion(SEMVER, ver) -} diff --git a/globals/checkVersion_test.go b/globals/checkVersion_test.go deleted file mode 100644 index d59999671f96237b6c92393e081ff81ba4027fc0..0000000000000000000000000000000000000000 --- a/globals/checkVersion_test.go +++ /dev/null @@ -1,179 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// Copyright © 2019 Privategrity Corporation / -// / -// All rights reserved. / -//////////////////////////////////////////////////////////////////////////////// - -package globals - -import ( - "testing" -) - -func TestParseClientVersion_Success(t *testing.T) { - version, err := parseClientVersion("1.2.3456") - expectedVersion := clientVersion{ - major: 1, - minor: 2, - patch: "3456", - } - if err != nil { - t.Error(err) - } - if version.minor != expectedVersion.minor { - t.Errorf("Expected %+v for minor version, got %+v", - expectedVersion.minor, version.minor) - } - if version.major != expectedVersion.major { - t.Errorf("Expected %+v for major version, got %+v", - expectedVersion.major, version.major) - } - if version.patch != expectedVersion.patch { - t.Errorf("Expected %+v for patch version, got %+v", - expectedVersion.patch, version.patch) - } -} - -func TestParseClientVersion_Failure(t *testing.T) { - _, err := parseClientVersion("") - if err == nil { - t.Error("Expected error for empty version string") - } - _, err = parseClientVersion("0") - if err == nil { - t.Error("Expected error for version string with one number") - } - _, err = parseClientVersion("0.0") - if err == nil { - t.Error("Expected error for version string with two numbers") - } - _, err = parseClientVersion("a.4.0") - if err == nil { - t.Error("Expected error for version string with non-numeric major version") - } - _, err = parseClientVersion("4.a.0") - if err == nil { - t.Error("Expected error for version string with non-numeric minor version") - } -} - -// If the registration version starts with zeroes, anything with major version 0 -// should be compatible, with any (positive) minor version and any patch -func TestClientVersion_IsCompatible_Zero(t *testing.T) { - theirVersion := &clientVersion{ - major: 0, - minor: 0, - patch: "stuff", - } - ourVersion_compatible := &clientVersion{ - major: 0, - minor: 1, - patch: "even more stuff", - } - if !ourVersion_compatible.isCompatible(theirVersion) { - t.Errorf("Our version %v should have been compatible with their version %v", - ourVersion_compatible, theirVersion) - } - ourVersion_incompatible := &clientVersion{ - major: 1, - minor: 0, - patch: "other stuff", - } - if ourVersion_incompatible.isCompatible(theirVersion) { - t.Errorf("Our version %v shouldn't have been compatible with their version %v", - ourVersion_incompatible, theirVersion) - } -} - -// If the registration version is a real version (non-zero), the boundaries -// of compatibility should be enforced. That is, the major version should be the -// same, and the client's minor version should be greater than or equal to the -// registration server's minor version to be deemed compatible. -func TestClientVersion_IsCompatible_Nonzero(t *testing.T) { - theirVersion := &clientVersion{ - major: 1, - minor: 4, - patch: "51", - } - ourVersion_compatible := []*clientVersion{{ - major: 1, - minor: 4, - patch: "50", - }, { - major: 1, - minor: 4, - patch: "52", - }, { - major: 1, - minor: 4, - patch: "51", - }, { - major: 1, - minor: 10, - patch: "50", - }, { - major: 1, - minor: 10, - patch: "52", - }, { - major: 1, - minor: 10, - patch: "51", - }} - for i := 0; i < len(ourVersion_compatible); i++ { - if !ourVersion_compatible[i].isCompatible(theirVersion) { - t.Errorf("Versions (ours) %v (and theirs) %v were incorrectly incompatible at index %v.", - ourVersion_compatible[i], theirVersion, i) - } - } - - ourVersion_incompatible := []*clientVersion{{ - major: 0, - minor: 0, - patch: "0", - }, { - major: 2, - minor: 0, - patch: "1", - }, { - major: 1, - minor: 3, - patch: "9", - }, { - major: 2, - minor: 5, - patch: "9", - }} - for i := 0; i < len(ourVersion_incompatible); i++ { - if ourVersion_incompatible[i].isCompatible(theirVersion) { - t.Errorf("Versions (ours) %v (and theirs) %v were incorrectly compatible at index %v.", - ourVersion_incompatible[i], theirVersion, i) - } - } -} - -func TestClientVersion_String(t *testing.T) { - cv := clientVersion{5, 10, "test"} - - testString := "5.10.test" - - if cv.String() != testString { - t.Errorf("String() did not return the correct string"+ - "\n\texpected: %s\n\treceived: %s", cv.String(), testString) - } -} - -func TestCommManager_CheckVersion(t *testing.T) { - _, err := checkVersion("ours", "theirs") - - if err == nil { - t.Errorf("checkVersion() did not return an error"+ - "\n\t%v", err) - } - _, err = checkVersion("ours", "1.2.3456") - - if err == nil { - t.Errorf("checkVersion() did not return an error"+ - "\n\t%v", err) - } -} diff --git a/globals/storage_test.go b/globals/storage_test.go index 23cbf077c49c528a3038b8e5e85cbd5a29f0d9a3..96abc9532bd258097ffd73da5c4430def403fe5d 100644 --- a/globals/storage_test.go +++ b/globals/storage_test.go @@ -132,3 +132,13 @@ func TestRamStorage_GetLocation(t *testing.T) { a, b) } } + +func Test_dsLoadHelper_LocError(t *testing.T) { + testLoc := "~a/test" + + result := dsLoadHelper(testLoc) + + if result != nil { + t.Errorf("dsLoadHelper() did not error on invalid path.") + } +} diff --git a/globals/version_vars.go b/globals/version_vars.go index 03a571a0a00133fa71fb81ea137cd7814d60babe..adb16b83a9a4d441e85e282929bd7d9d59a0409e 100644 --- a/globals/version_vars.go +++ b/globals/version_vars.go @@ -1,17 +1,17 @@ // Code generated by go generate; DO NOT EDIT. // This file was generated by robots at -// 2020-05-12 21:02:57.275479486 +0000 UTC m=+0.003920070 +// 2020-07-30 15:27:18.7064291 -0700 PDT m=+0.065083001 package globals -const GITVERSION = `daeebfe disable stdout on the global jww logger` -const SEMVER = "1.3.0" +const GITVERSION = `4ef845a Merge branch 'hotfix/integrateekv' into 'release'` +const SEMVER = "1.4.0" const DEPENDENCIES = `module gitlab.com/elixxir/client go 1.13 require ( github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3 - github.com/golang/protobuf v1.4.0 + github.com/golang/protobuf v1.4.2 github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00 // indirect github.com/pelletier/go-toml v1.6.0 // indirect github.com/pkg/errors v0.9.1 @@ -22,10 +22,12 @@ require ( github.com/spf13/jwalterweatherman v1.1.0 github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.6.2 - gitlab.com/elixxir/comms v0.0.0-20200415204952-6d63dd94a0ea - gitlab.com/elixxir/crypto v0.0.0-20200410231849-90e859940f5d - gitlab.com/elixxir/primitives v0.0.0-20200410231944-a57d71d577c9 - golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 + gitlab.com/elixxir/comms v0.0.0-20200730220537-60dbe58afe94 + gitlab.com/elixxir/crypto v0.0.0-20200707005343-97f868cbd930 + gitlab.com/elixxir/ekv v0.0.0-20200729182028-159355ea5842 + gitlab.com/elixxir/primitives v0.0.0-20200706165052-9fe7a4fb99a3 + gitlab.com/xx_network/comms v0.0.0-20200730220144-eea32e8b696d + golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899 gopkg.in/ini.v1 v1.52.0 // indirect ) ` diff --git a/go.mod b/go.mod index 66bd3d8f52c113ae6b159c607bc9083ec9911673..f483175c4086c6414c15f9cd2f863fc10c680e0e 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.13 require ( github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3 - github.com/golang/protobuf v1.4.1 + github.com/golang/protobuf v1.4.2 github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00 // indirect github.com/pelletier/go-toml v1.6.0 // indirect github.com/pkg/errors v0.9.1 @@ -15,9 +15,11 @@ require ( github.com/spf13/jwalterweatherman v1.1.0 github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.6.2 - gitlab.com/elixxir/comms v0.0.0-20200513163847-4975a4118ac6 - gitlab.com/elixxir/crypto v0.0.0-20200513163659-38b6079db0b2 - gitlab.com/elixxir/primitives v0.0.0-20200513162412-ef77445c0ab7 - golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37 + gitlab.com/elixxir/comms v0.0.0-20200730220537-60dbe58afe94 + gitlab.com/elixxir/crypto v0.0.0-20200707005343-97f868cbd930 + gitlab.com/elixxir/ekv v0.0.0-20200729182028-159355ea5842 + gitlab.com/elixxir/primitives v0.0.0-20200706165052-9fe7a4fb99a3 + gitlab.com/xx_network/comms v0.0.0-20200730220144-eea32e8b696d + golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899 gopkg.in/ini.v1 v1.52.0 // indirect ) diff --git a/go.sum b/go.sum index b54504a99cf65ac325e04fe1b1d731412f212dd7..0222d5381d5434a6707b9200622d02e3c7197de4 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,5 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -18,6 +19,7 @@ github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfc github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= @@ -45,7 +47,6 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -54,12 +55,18 @@ github.com/golang/protobuf v1.4.0 h1:oOuy+ugB+P/kBdUnG5QaMXSIyJ1q38wWSojYCb3z5VQ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1 h1:ZFgWrT+bLgsYPirOnRfKLYJLvssAegOj/hgyMFdJZe0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 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/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00 h1:l5lAOZEym3oK3SQ2HBHWsJUfbNBiTXJDeW2QDxw9AQ0= github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= @@ -67,8 +74,10 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= @@ -76,9 +85,9 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 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/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= @@ -89,6 +98,7 @@ github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= @@ -97,6 +107,7 @@ github.com/pelletier/go-toml v1.6.0/go.mod h1:5N711Q9dKgbdkxHL+MEfF31hpT7l0S0s/t github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= @@ -113,7 +124,9 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD 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/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= +github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= @@ -137,39 +150,40 @@ github.com/spf13/viper v1.6.2/go.mod h1:t3iDnF5Jlj76alVNuyFBk5oUMCvsrkbvZK0WQdfD github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -gitlab.com/elixxir/comms v0.0.0-20200415204952-6d63dd94a0ea h1:LVQuXjq26hjnuw2isxSpYHFBql80VLnhcrNQ+IJ4QH0= -gitlab.com/elixxir/comms v0.0.0-20200415204952-6d63dd94a0ea/go.mod h1:EeRHiSIfVYqTaMZGb6eE2kz1Rw5zGXuuBow4Pi2VFg0= -gitlab.com/elixxir/comms v0.0.0-20200513163847-4975a4118ac6 h1:k+loYgTu4fN12Dmypu8OSZ8mQCBUxJQI29In5gaDHo4= -gitlab.com/elixxir/comms v0.0.0-20200513163847-4975a4118ac6/go.mod h1:zuYjqakP4b5rYtgeAra5SAHV87FRym9eEa8dwDVdNuU= -gitlab.com/elixxir/crypto v0.0.0-20200410231849-90e859940f5d h1:+g7tGMO3g20Su3pdTJg30n5XhEGZ3avEd4ccN33CtdU= -gitlab.com/elixxir/crypto v0.0.0-20200410231849-90e859940f5d/go.mod h1:QPClJr3F90ejz6iHaCZuhexytd6PP97dDnt93iRCTDo= -gitlab.com/elixxir/crypto v0.0.0-20200513163659-38b6079db0b2 h1:dqWdpifXovXXk2egHeh3FQFqB3IlcIurL+A+ziFFbU0= -gitlab.com/elixxir/crypto v0.0.0-20200513163659-38b6079db0b2/go.mod h1:9BCEQtgddrCHt/QONWD+nU1n6iZ+qfc89GnzSVHA97I= -gitlab.com/elixxir/primitives v0.0.0-20200218211222-4193179f359c/go.mod h1:REJMcwIcyxh74VSHqy4S9yYiaEsQYObOPglRExDpk14= -gitlab.com/elixxir/primitives v0.0.0-20200410231944-a57d71d577c9 h1:KP/BQqOrLcoCah24VHzQBY8EbQHvBcsrhz/Yjs6vn4Y= -gitlab.com/elixxir/primitives v0.0.0-20200410231944-a57d71d577c9/go.mod h1:nqC90Tt1jLDd2e35hVWCmTynTXBBEt3UfaSsIhHevmc= -gitlab.com/elixxir/primitives v0.0.0-20200513162412-ef77445c0ab7 h1:XY7jcsaqkM60c0TFrPyxfPam1hlM1oYGq/wlCk1GKUM= -gitlab.com/elixxir/primitives v0.0.0-20200513162412-ef77445c0ab7/go.mod h1:uc1rmOIN/Cg6WsTtIz7vu/ezxHqqFRiDEvBeFM/tMjM= +gitlab.com/elixxir/comms v0.0.0-20200707210150-b8ebd0951d23/go.mod h1:OsWMZ1O/R9fOkm+PoHnR3rkXfFtipGoPs73FuKuurHY= +gitlab.com/elixxir/comms v0.0.0-20200730220537-60dbe58afe94 h1:AY3Nm9QXAh8jRUyKdX0jsay4A4j4z7/ofJgJKbvIFmc= +gitlab.com/elixxir/comms v0.0.0-20200730220537-60dbe58afe94/go.mod h1:rlB+AA0mNMRq9GIR587cNw5RX4Cr8VOiVpZkFTTcukQ= +gitlab.com/elixxir/crypto v0.0.0-20200707005343-97f868cbd930 h1:9qzfwyR12OYgn3j30qcHZHHVfWshWnH54lcAHppEROQ= +gitlab.com/elixxir/crypto v0.0.0-20200707005343-97f868cbd930/go.mod h1:LHBAaEf48a0/AjU118rjoworH0LgXifhAqmNX3ZRvME= +gitlab.com/elixxir/ekv v0.0.0-20200729182028-159355ea5842 h1:m1zDQ6UadpuMnV7nvnyR+DUXE3AisRnVjajTb1xZE4c= +gitlab.com/elixxir/ekv v0.0.0-20200729182028-159355ea5842/go.mod h1:bXY0kgbV5BHYda4YY5/hiG5bjimGK+R3PYub5yM9C/s= +gitlab.com/elixxir/primitives v0.0.0-20200706165052-9fe7a4fb99a3 h1:GTfflZBNLeBq3UApYog0J3+hytdkoRsDduGQji2wyEU= +gitlab.com/elixxir/primitives v0.0.0-20200706165052-9fe7a4fb99a3/go.mod h1:OQgUZq7SjnE0b+8+iIAT2eqQF+2IFHn73tOo+aV11mg= +gitlab.com/xx_network/comms v0.0.0-20200730220144-eea32e8b696d h1:P4ceawldsxuwQ6LZHnUnemtiOJI9/QquYi8QkFuUbtI= +gitlab.com/xx_network/comms v0.0.0-20200730220144-eea32e8b696d/go.mod h1:76OCijGBxYOBV5Kt7z6K7vNg3n9I57aCQMmI8GTpoEM= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20200117160349-530e935923ad/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 h1:3zb4D3T4G8jdExgVU/95+vQXfpEPiMdCaZgmGVxjNHM= -golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37 h1:cg5LA/zNPRzIXIWSCxQW10Rvpy94aQh3LT/ShoCpkHw= golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200707235045-ab33eee955e0 h1:eIYIE7EC5/Wv5Kbz8bJPaq+TN3kq3W8S+LSm62vM0DY= +golang.org/x/crypto v0.0.0-20200707235045-ab33eee955e0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899 h1:DZhuSZLsGlFL4CmhA8BcRA0mnthyA/nZ00AqCUo7vHg= +golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -182,10 +196,10 @@ golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a h1:GuSPYbZzB5/dcLNCwLQLsg3obCJtX9IJhpXkvY7kzk0= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0 h1:Jcxah/M+oLZ/R4/z5RzfPzGbPXnVDPkEDtf2JnuxN+U= -golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120 h1:EZ3cVSzKOlJxAd8e8YAJ7no8nNypTxexh/YE/xW3ZEY= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +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/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -198,16 +212,16 @@ golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d h1:nc5K6ox/4lTFbMVSL9WRR81ixkcwXThoiF6yf+R9scA= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f h1:mOhmO9WsBaJCNmaZHPtHs9wOcdqdKCjF6OPJlmDM3KI= -golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299 h1:DYfZAGf2WMFjMxbgTjaC+2HC7NkNAQs+6Q8b9WEB/F4= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae h1:Ih9Yo4hSPImZOpfGuA4bR/ORKTAbhZo2AbWNRCnevdo= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -216,24 +230,26 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200309141739-5b75447e413d h1:VQ0pz4dAUaMWcQLM7tGY8Nk691kSrlGPyF5nSgAIw2g= -google.golang.org/genproto v0.0.0-20200309141739-5b75447e413d/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200428115010-c45acf45369a h1:ykRcNp3dotYGpAEIYeWCGaefklVjVy/rnSvM3zNh6j8= -google.golang.org/genproto v0.0.0-20200428115010-c45acf45369a/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200514193133-8feb7f20f2a2 h1:RwW6+LxyOQJ7oeoZ76GIJlwt/O0J5cN2fk+q/jK27kQ= +google.golang.org/genproto v0.0.0-20200514193133-8feb7f20f2a2/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200709005830-7a2ca40e9dc3 h1:JwLN1jVnmIsfE4HkDVe2AblFAbo0Z+4cjteDSOnv6oE= +google.golang.org/genproto v0.0.0-20200709005830-7a2ca40e9dc3/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1 h1:zvIju4sqAGvwKspUQOhwnpcqSbzi7/H6QomNNjTL4sk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.29.1 h1:EC2SB8S04d2r73uptxphDSUG+kTKVgjRPF+N3xpxRB4= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0 h1:M5a8xTlYTxwMn5ZFkwhRabsygDY5G8TYLyQDBxJNAxE= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -242,10 +258,16 @@ google.golang.org/protobuf v1.21.0 h1:qdOKuR/EIArgaWNjetjgTzgVTAZ+S/WXVrq9HW9zim google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.22.0 h1:cJv5/xdbk1NnMPR1VP9+HU6gupuG9MLBoH1r6RHZ2MY= google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM= +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= 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= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.52.0 h1:j+Lt/M1oPPejkniCg1TkWE2J3Eh1oZTsHSXzMTzUXn4= @@ -255,8 +277,10 @@ gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bl gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/io/collate.go b/io/collate.go index 0f4ec1e49cdbe270b03538719e8ee94412b613a9..c2d74635ed915576f807767f4f17d065e5b928aa 100644 --- a/io/collate.go +++ b/io/collate.go @@ -47,16 +47,19 @@ func NewCollator() *Collator { // TODO this takes too many types. i should split it up. // This method returns a byte slice with the assembled message if it's // received a completed message. -func (mb *Collator) AddMessage(message *format.Message, sender *id.User, - timeout time.Duration) *parse.Message { +func (mb *Collator) AddMessage(message *format.Message, sender *id.ID, + timeout time.Duration) (*parse.Message, error) { payload := message.Contents.GetRightAligned() - recipient := message.GetRecipient() + recipient, err := message.GetRecipient() + if err != nil { + return nil, err + } //get the time timestamp := time.Time{} - err := timestamp.UnmarshalBinary(message.GetTimestamp()[:len(message.GetTimestamp())-1]) + err = timestamp.UnmarshalBinary(message.GetTimestamp()[:len(message.GetTimestamp())-1]) if err != nil { globals.Log.WARN.Printf("Failed to parse timestamp for message %v: %+v", @@ -65,15 +68,16 @@ func (mb *Collator) AddMessage(message *format.Message, sender *id.User, partition, err := parse.ValidatePartition(payload) - if err == nil { + if err != nil { + return nil, errors.WithMessage(err, "Received an invalid partition: ") + } else { if partition.MaxIndex == 0 { //this is the only part of the message. we should take the fast //path and skip putting it in the map typedBody, err := parse.Parse(partition.Body) // Log an error if the message is malformed and return nothing if err != nil { - globals.Log.ERROR.Printf("Malformed message received") - return nil + return nil, errors.WithMessage(err, "Malformed message received") } msg := parse.Message{ @@ -84,7 +88,7 @@ func (mb *Collator) AddMessage(message *format.Message, sender *id.User, Timestamp: timestamp, } - return &msg + return &msg, nil } else { // assemble the map key into a new chunk of memory var key PendingMessageKey @@ -95,6 +99,7 @@ func (mb *Collator) AddMessage(message *format.Message, sender *id.User, copy(key[:], keyHash[:PendingMessageKeyLen]) mb.mux.Lock() + defer mb.mux.Unlock() message, ok := mb.pendingMessages[key] if !ok { // this is a multi-part message we haven't seen before. @@ -113,11 +118,11 @@ func (mb *Collator) AddMessage(message *format.Message, sender *id.User, // TODO vary timeout depending on number of messages? time.AfterFunc(timeout, func() { mb.mux.Lock() + defer mb.mux.Unlock() _, ok := mb.pendingMessages[key] if ok { delete(mb.pendingMessages, key) } - mb.mux.Unlock() }) } else { // append to array for this key @@ -129,17 +134,13 @@ func (mb *Collator) AddMessage(message *format.Message, sender *id.User, fullMsg, err := parse.Assemble(message.parts) if err != nil { delete(mb.pendingMessages, key) - mb.mux.Unlock() - globals.Log.ERROR.Printf("Malformed message: Padding error, %v", err.Error()) - return nil + return nil, errors.WithMessage(err, "Malformed message: padding error, ") } typedBody, err := parse.Parse(fullMsg) // Log an error if the message is malformed and return nothing if err != nil { delete(mb.pendingMessages, key) - mb.mux.Unlock() - globals.Log.ERROR.Printf("Malformed message Received") - return nil + return nil, errors.WithMessage(err, "Malformed message received") } msg := parse.Message{ @@ -151,16 +152,13 @@ func (mb *Collator) AddMessage(message *format.Message, sender *id.User, } delete(mb.pendingMessages, key) - mb.mux.Unlock() - return &msg + return &msg, nil + } else { + // need more parts + return nil, nil } - mb.mux.Unlock() } - } else { - globals.Log.ERROR.Printf("Received an invalid partition: %v\n", err.Error()) } - globals.Log.DEBUG.Printf("Message collator: %v", mb.dump()) - return nil } // Debug: dump all messages that are currently in the map diff --git a/io/collate_test.go b/io/collate_test.go index 6bf301fb530803bc1586639ab798bb07b4584220..274497f2519a478511de3c8f24ceffd1d2bb5195 100644 --- a/io/collate_test.go +++ b/io/collate_test.go @@ -19,7 +19,7 @@ import ( func TestCollator_AddMessage(t *testing.T) { - uid := id.NewUserFromUint(69, t) + uid := id.NewIdFromUInt(69, id.User, t) collator := &Collator{ pendingMessages: make(map[PendingMessageKey]*multiPartMessage), @@ -44,10 +44,13 @@ func TestCollator_AddMessage(t *testing.T) { for j := range partitions { fm := format.NewMessage() - fm.SetRecipient(id.NewUserFromUint(6, t)) + fm.SetRecipient(id.NewIdFromUInt(6, id.User, t)) fm.Contents.SetRightAligned(partitions[j]) - result = collator.AddMessage(fm, uid, time.Minute) + result, err = collator.AddMessage(fm, uid, time.Minute) + if err != nil { + t.Fatal(err) + } } typedBody, err := parse.Parse(bodies[i]) @@ -66,7 +69,7 @@ func TestCollator_AddMessage(t *testing.T) { func TestCollator_AddMessage_Timeout(t *testing.T) { - uid := id.NewUserFromUint(69, t) + uid := id.NewIdFromUInt(69, id.User, t) collator := &Collator{ pendingMessages: make(map[PendingMessageKey]*multiPartMessage), @@ -84,10 +87,13 @@ func TestCollator_AddMessage_Timeout(t *testing.T) { nowBytes, _ := now.MarshalBinary() nowBytes = append(nowBytes, make([]byte, format.TimestampLen-len(nowBytes))...) fm.SetTimestamp(nowBytes) - fm.SetRecipient(id.NewUserFromUint(6, t)) + fm.SetRecipient(id.NewIdFromUInt(6, id.User, t)) fm.Contents.SetRightAligned(partitions[i]) - result = collator.AddMessage(fm, uid, 80*time.Millisecond) + result, err = collator.AddMessage(fm, uid, 80*time.Millisecond) + if err != nil { + t.Fatal(err) + } if result != nil { t.Error("Got a result from collator when it should be timing out" + " submessages") diff --git a/io/interface.go b/io/interface.go index 1aaf3ce3b57bec5b6ba485da40fe69e906c0e591..3352147ee359249751df963abe00487a6fd579e1 100644 --- a/io/interface.go +++ b/io/interface.go @@ -9,8 +9,8 @@ package io import ( "gitlab.com/elixxir/client/parse" "gitlab.com/elixxir/client/user" - "gitlab.com/elixxir/comms/connect" "gitlab.com/elixxir/primitives/id" + "gitlab.com/xx_network/comms/connect" "time" ) @@ -20,12 +20,12 @@ type Communications interface { // TODO(nen) Can we get rid of the crypto type param here? SendMessage(session user.Session, topology *connect.Circuit, - recipientID *id.User, cryptoType parse.CryptoType, message []byte, + recipientID *id.ID, cryptoType parse.CryptoType, message []byte, transmissionHost *connect.Host) error // SendMessage without partitions to the server // This is used to send rekey messages SendMessageNoPartition(session user.Session, topology *connect.Circuit, - recipientID *id.User, cryptoType parse.CryptoType, message []byte, + recipientID *id.ID, cryptoType parse.CryptoType, message []byte, transmissionHost *connect.Host) error // MessageReceiver thread to get new messages MessageReceiver(session user.Session, delay time.Duration, diff --git a/io/receive.go b/io/receive.go index 49c1cddd7f888bc3785a27aa64eeb0adbec425ad..ef5c5dbcba7c66037efa0d67935e762916c3cd07 100644 --- a/io/receive.go +++ b/io/receive.go @@ -14,12 +14,12 @@ import ( "gitlab.com/elixxir/client/globals" "gitlab.com/elixxir/client/parse" "gitlab.com/elixxir/client/user" - "gitlab.com/elixxir/comms/connect" pb "gitlab.com/elixxir/comms/mixmessages" "gitlab.com/elixxir/crypto/e2e" "gitlab.com/elixxir/primitives/format" "gitlab.com/elixxir/primitives/id" "gitlab.com/elixxir/primitives/switchboard" + "gitlab.com/xx_network/comms/connect" "strings" "time" ) @@ -100,8 +100,11 @@ func (rm *ReceptionManager) MessageReceiver(session user.Session, delay time.Dur if decryptedMessages != nil { for i := range decryptedMessages { // TODO Handle messages that do not need partitioning - assembledMessage := rm.collator.AddMessage(decryptedMessages[i], + assembledMessage, err := rm.collator.AddMessage(decryptedMessages[i], senders[i], time.Minute) + if err != nil { + go callback(err) + } if assembledMessage != nil { // we got a fully assembled message. let's broadcast it broadcastMessageReception(assembledMessage, session.GetSwitchboard()) @@ -113,7 +116,7 @@ func (rm *ReceptionManager) MessageReceiver(session user.Session, delay time.Dur } func handleE2EReceiving(session user.Session, - message *format.Message) (*id.User, bool, error) { + message *format.Message) (*id.ID, bool, error) { keyFingerprint := message.GetKeyFP() // Lookup reception key @@ -249,11 +252,11 @@ func (rm *ReceptionManager) receiveMessagesFromGateway(session user.Session, } func (rm *ReceptionManager) decryptMessages(session user.Session, - encryptedMessages []*format.Message) ([]*format.Message, []*id.User, + encryptedMessages []*format.Message) ([]*format.Message, []*id.ID, []*format.Message) { messages := make([]*format.Message, len(encryptedMessages)) - senders := make([]*id.User, len(encryptedMessages)) + senders := make([]*id.ID, len(encryptedMessages)) messagesSendersLoc := 0 garbledMessages := make([]*format.Message, len(encryptedMessages)) @@ -263,7 +266,7 @@ func (rm *ReceptionManager) decryptMessages(session user.Session, var err error = nil var rekey bool var unpadded []byte - var sender *id.User + var sender *id.ID garbled := false // If message is E2E, handle decryption @@ -275,7 +278,7 @@ func (rm *ReceptionManager) decryptMessages(session user.Session, } keyFP := msg.AssociatedData.GetKeyFP() - sender = id.NewUserFromBytes(keyFP[:]) + sender, err = makeUserID(keyFP[:]) } else { sender, rekey, err = handleE2EReceiving(session, msg) @@ -311,6 +314,17 @@ func broadcastMessageReception(message *parse.Message, listeners.Speak(message) } +// Put a sender ID in a byte slice and set its type to user +func makeUserID(senderID []byte) (*id.ID, error) { + senderIDBytes := make([]byte, id.ArrIDLen) + copy(senderIDBytes, senderID[:]) + userID, err := id.Unmarshal(senderIDBytes) + if userID != nil { + userID.SetType(id.User) + } + return userID, err +} + // skipErrChecker checks checks if the error is fatal or should be ignored func skipErrChecker(err error) bool { if strings.Contains(err.Error(), "Could not find any message IDs for this user") { diff --git a/io/receptionManager.go b/io/receptionManager.go index 53b70ee3ba7fb8949f6db4fe25785afe14b53b40..467ab0ebd069c22dcad1600d90e5e9967afd1205 100644 --- a/io/receptionManager.go +++ b/io/receptionManager.go @@ -13,12 +13,11 @@ import ( "github.com/pkg/errors" "gitlab.com/elixxir/client/parse" "gitlab.com/elixxir/comms/client" + "gitlab.com/elixxir/primitives/id" "sync" "time" ) -const PermissioningAddrID = "Permissioning" - type ConnAddr string func (a ConnAddr) String() string { @@ -51,7 +50,7 @@ type ReceptionManager struct { } // Build a new reception manager object using inputted key fields -func NewReceptionManager(rekeyChan chan struct{}, uid string, privKey, pubKey, salt []byte) (*ReceptionManager, error) { +func NewReceptionManager(rekeyChan chan struct{}, uid *id.ID, privKey, pubKey, salt []byte) (*ReceptionManager, error) { comms, err := client.NewClientComms(uid, pubKey, privKey, salt) if err != nil { return nil, errors.Wrap(err, "Failed to get client comms using constructor: %+v") @@ -74,9 +73,9 @@ func NewReceptionManager(rekeyChan chan struct{}, uid string, privKey, pubKey, s // Connects to the permissioning server, if we know about it, to get the latest // version from it func (rm *ReceptionManager) GetRemoteVersion() (string, error) { - permissioningHost, ok := rm.Comms.GetHost(PermissioningAddrID) + permissioningHost, ok := rm.Comms.GetHost(&id.Permissioning) if !ok { - return "", errors.Errorf("Failed to find permissioning host with id %s", PermissioningAddrID) + return "", errors.Errorf("Failed to find permissioning host with id %s", id.Permissioning) } registrationVersion, err := rm.Comms. SendGetCurrentClientVersionMessage(permissioningHost) diff --git a/io/send.go b/io/send.go index 1d0821e9e94814ade332ce1995bcca33963904a4..f4d5fc97507ce718c6bdf66704facc797746a143 100644 --- a/io/send.go +++ b/io/send.go @@ -15,13 +15,13 @@ import ( "gitlab.com/elixxir/client/keyStore" "gitlab.com/elixxir/client/parse" "gitlab.com/elixxir/client/user" - "gitlab.com/elixxir/comms/connect" pb "gitlab.com/elixxir/comms/mixmessages" "gitlab.com/elixxir/crypto/cmix" "gitlab.com/elixxir/crypto/csprng" "gitlab.com/elixxir/crypto/e2e" "gitlab.com/elixxir/primitives/format" "gitlab.com/elixxir/primitives/id" + "gitlab.com/xx_network/comms/connect" "time" ) @@ -31,7 +31,7 @@ import ( // TODO This method would be cleaner if it took a parse.Message (particularly // w.r.t. generating message IDs for multi-part messages.) func (rm *ReceptionManager) SendMessage(session user.Session, topology *connect.Circuit, - recipientID *id.User, cryptoType parse.CryptoType, + recipientID *id.ID, cryptoType parse.CryptoType, message []byte, transmissionHost *connect.Host) error { // FIXME: We should really bring the plaintext parts of the NewMessage logic // into this module, then have an EncryptedMessage type that is sent to/from @@ -77,7 +77,7 @@ func (rm *ReceptionManager) SendMessage(session user.Session, topology *connect. // This function will be needed for example to send a Rekey // message, where a new public key will take up the whole message func (rm *ReceptionManager) SendMessageNoPartition(session user.Session, - topology *connect.Circuit, recipientID *id.User, cryptoType parse.CryptoType, + topology *connect.Circuit, recipientID *id.ID, cryptoType parse.CryptoType, message []byte, transmissionHost *connect.Host) error { size := len(message) if size > format.TotalLen { @@ -132,14 +132,14 @@ func (rm *ReceptionManager) send(session user.Session, topology *connect.Circuit } message.Contents.Set(padded) e2e.SetUnencrypted(message) - message.SetKeyFP(*format.NewFingerprint(session.GetCurrentUser().User.Bytes())) + message.SetKeyFP(*format.NewFingerprint(session.GetCurrentUser().User.Marshal()[:32])) } // CMIX Encryption salt := cmix.NewSalt(csprng.Source(&csprng.SystemRNG{}), 32) encMsg, kmacs := crypto.CMIXEncrypt(session, topology, salt, message) msgPacket := &pb.Slot{ - SenderID: session.GetCurrentUser().User.Bytes(), + SenderID: session.GetCurrentUser().User.Marshal(), PayloadA: encMsg.GetPayloadA(), PayloadB: encMsg.GetPayloadB(), Salt: salt, @@ -152,7 +152,10 @@ func (rm *ReceptionManager) send(session user.Session, topology *connect.Circuit func handleE2ESending(session user.Session, message *format.Message, rekey bool) { - recipientID := message.GetRecipient() + recipientID, err := message.GetRecipient() + if err != nil { + globals.Log.ERROR.Panic(err) + } var key *keyStore.E2EKey var action keyStore.Action diff --git a/keyStore/keyManager.go b/keyStore/keyManager.go index d6d58634521ac62aea3e8c8865a971cd7ca4043e..a6938702fa624f69145c159f74a883ae46da1e7e 100644 --- a/keyStore/keyManager.go +++ b/keyStore/keyManager.go @@ -34,7 +34,7 @@ type KeyManager struct { pubKey *cyclic.Int // Designates end-to-end partner - partner *id.User + partner *id.ID // True if key manager tracks send keys, false if receive keys sendOrRecv bool @@ -76,7 +76,7 @@ type KeyManager struct { // All internal states are forced to 0 for safety purposes func NewManager(baseKey *cyclic.Int, privKey *cyclic.Int, pubKey *cyclic.Int, - partner *id.User, sendOrRecv bool, + partner *id.ID, sendOrRecv bool, numKeys uint32, ttl uint16, numReKeys uint16) *KeyManager { km := new(KeyManager) @@ -117,7 +117,7 @@ func (km *KeyManager) GetPubKey() *cyclic.Int { } // Get the partner ID from the Key Manager -func (km *KeyManager) GetPartner() *id.User { +func (km *KeyManager) GetPartner() *id.ID { return km.partner } @@ -263,7 +263,7 @@ func (km *KeyManager) checkRecvStateBit(rekey bool, keyNum uint32) bool { // E2E relationship is established, and also to generate all previously // unused keys based on KeyManager state, when reloading an user session // The function returns modifications that need to be independently made to the keystore. -func (km *KeyManager) GenerateKeys(grp *cyclic.Group, userID *id.User) []*E2EKey { +func (km *KeyManager) GenerateKeys(grp *cyclic.Group, userID *id.ID) []*E2EKey { var recE2EKeys []*E2EKey if km.sendOrRecv { @@ -538,6 +538,12 @@ func (km *KeyManager) GobDecode(in []byte) error { return err } + partner, err := id.Unmarshal(s.Partner) + if err != nil { + return err + } + km.partner = partner + // Convert decoded bytes and put into key manager structure km.baseKey = new(cyclic.Int) err = km.baseKey.GobDecode(s.BaseKey) @@ -566,7 +572,6 @@ func (km *KeyManager) GobDecode(in []byte) error { km.sendOrRecv = false } - km.partner = id.NewUserFromBytes(s.Partner) km.sendState = new(uint64) *km.sendState = binary.BigEndian.Uint64(s.State) km.ttl = binary.BigEndian.Uint16(s.TTL) diff --git a/keyStore/keyManager_test.go b/keyStore/keyManager_test.go index 72fc65533ac1ed3588724a9aba4ea8ab7fefa1ff..3851e03e3e978539768f1d759ada70c3017b5ca0 100644 --- a/keyStore/keyManager_test.go +++ b/keyStore/keyManager_test.go @@ -47,7 +47,7 @@ func initGroup() *cyclic.Group { func TestKeyManager_New(t *testing.T) { grp := cyclic.NewGroup(large.NewInt(107), large.NewInt(2)) baseKey := grp.NewInt(57) - partner := id.NewUserFromUint(14, t) + partner := id.NewIdFromUInt(14, id.User, t) km := NewManager(baseKey, nil, nil, partner, true, 12, 10, 10) @@ -63,7 +63,7 @@ func TestKeyManager_GetBaseKey(t *testing.T) { baseKey := grp.NewInt(57) privKey := grp.NewInt(5) pubKey := grp.NewInt(42) - partner := id.NewUserFromUint(14, t) + partner := id.NewIdFromUInt(14, id.User, t) km := NewManager(baseKey, privKey, pubKey, partner, true, 12, 10, 10) @@ -83,7 +83,7 @@ func TestKeyManager_GetPrivKey(t *testing.T) { baseKey := grp.NewInt(57) privKey := grp.NewInt(5) pubKey := grp.NewInt(42) - partner := id.NewUserFromUint(14, t) + partner := id.NewIdFromUInt(14, id.User, t) km := NewManager(baseKey, privKey, pubKey, partner, true, 12, 10, 10) @@ -103,7 +103,7 @@ func TestKeyManager_GetPubKey(t *testing.T) { baseKey := grp.NewInt(57) privKey := grp.NewInt(5) pubKey := grp.NewInt(42) - partner := id.NewUserFromUint(14, t) + partner := id.NewIdFromUInt(14, id.User, t) km := NewManager(baseKey, privKey, pubKey, partner, true, 12, 10, 10) @@ -123,7 +123,7 @@ func TestKeyManager_GetPartner(t *testing.T) { baseKey := grp.NewInt(57) privKey := grp.NewInt(5) pubKey := grp.NewInt(42) - partner := id.NewUserFromUint(14, t) + partner := id.NewIdFromUInt(14, id.User, t) km := NewManager(baseKey, privKey, pubKey, partner, true, 12, 10, 10) @@ -141,7 +141,7 @@ func TestKeyManager_GetPartner(t *testing.T) { func TestKeyManager_Rekey(t *testing.T) { grp := cyclic.NewGroup(large.NewInt(107), large.NewInt(2)) baseKey := grp.NewInt(57) - partner := id.NewUserFromUint(14, t) + partner := id.NewIdFromUInt(14, id.User, t) km := NewManager(baseKey, nil, nil, partner, true, 12, 10, 10) @@ -166,7 +166,7 @@ func TestKeyManager_Rekey(t *testing.T) { func TestKeyManager_Purge(t *testing.T) { grp := cyclic.NewGroup(large.NewInt(107), large.NewInt(2)) baseKey := grp.NewInt(57) - partner := id.NewUserFromUint(14, t) + partner := id.NewIdFromUInt(14, id.User, t) km := NewManager(baseKey, nil, nil, partner, true, 12, 10, 10) @@ -198,7 +198,7 @@ func TestKeyManager_Purge(t *testing.T) { func TestKeyManager_UpdateRecvState(t *testing.T) { grp := cyclic.NewGroup(large.NewInt(107), large.NewInt(2)) baseKey := grp.NewInt(57) - partner := id.NewUserFromUint(14, t) + partner := id.NewIdFromUInt(14, id.User, t) km := NewManager(baseKey, nil, nil, partner, false, 12, 10, 10) @@ -230,8 +230,8 @@ func TestKeyManager_UpdateRecvState(t *testing.T) { func TestKeyManager_GenerateKeys(t *testing.T) { grp := initGroup() baseKey := grp.NewInt(57) - partner := id.NewUserFromUint(14, t) - userID := id.NewUserFromUint(18, t) + partner := id.NewIdFromUInt(14, id.User, t) + userID := id.NewIdFromUInt(18, id.User, t) ks := NewStore() kmSend := NewManager(baseKey, nil, nil, @@ -291,8 +291,8 @@ func TestKeyManager_GenerateKeys(t *testing.T) { func TestKeyManager_Destroy(t *testing.T) { grp := initGroup() baseKey := grp.NewInt(57) - partner := id.NewUserFromUint(14, t) - userID := id.NewUserFromUint(18, t) + partner := id.NewIdFromUInt(14, id.User, t) + userID := id.NewIdFromUInt(18, id.User, t) ks := NewStore() km := NewManager(baseKey, nil, nil, @@ -365,7 +365,7 @@ func TestKeyManager_GobSimple(t *testing.T) { baseKey := grp.NewInt(57) privKey := grp.NewInt(5) pubKey := grp.NewInt(42) - partner := id.NewUserFromUint(14, t) + partner := id.NewIdFromUInt(14, id.User, t) var byteBuf bytes.Buffer @@ -471,8 +471,8 @@ func TestKeyManager_Gob(t *testing.T) { baseKey := grp.NewInt(57) privKey := grp.NewInt(5) pubKey := grp.NewInt(42) - partner := id.NewUserFromUint(14, t) - userID := id.NewUserFromUint(18, t) + partner := id.NewIdFromUInt(14, id.User, t) + userID := id.NewIdFromUInt(18, id.User, t) ks := NewStore() km := NewManager(baseKey, privKey, pubKey, diff --git a/keyStore/keyStore.go b/keyStore/keyStore.go index a08a9938d450955d735427245cae614d8f4ab96c..8256cbde527b7025ea1842974b6c62df2b9de427 100644 --- a/keyStore/keyStore.go +++ b/keyStore/keyStore.go @@ -18,12 +18,12 @@ type keyManMap sync.Map type inKeyMap sync.Map // Stores a KeyManager entry for given user -func (m *keyManMap) Store(user *id.User, km *KeyManager) { +func (m *keyManMap) Store(user *id.ID, km *KeyManager) { (*sync.Map)(m).Store(*user, km) } // Loads a KeyManager entry for given user -func (m *keyManMap) Load(user *id.User) *KeyManager { +func (m *keyManMap) Load(user *id.ID) *KeyManager { val, ok := (*sync.Map)(m).Load(*user) if !ok { return nil @@ -33,7 +33,7 @@ func (m *keyManMap) Load(user *id.User) *KeyManager { } // Deletes a KeyManager entry for given user -func (m *keyManMap) Delete(user *id.User) { +func (m *keyManMap) Delete(user *id.ID) { (*sync.Map)(m).Delete(*user) } @@ -50,10 +50,10 @@ func (m *keyManMap) values() []*KeyManager { // Internal helper function to get a list of all keys // contained in a KeyManMap -func (m *keyManMap) keys() []id.User { - keyList := make([]id.User, 0) +func (m *keyManMap) keys() []id.ID { + keyList := make([]id.ID, 0) (*sync.Map)(m).Range(func(key, value interface{}) bool { - keyList = append(keyList, key.(id.User)) + keyList = append(keyList, key.(id.ID)) return true }) return keyList @@ -114,7 +114,7 @@ type KeyStore struct { params *KeyParams // Transmission Keys map - // Maps id.User to *KeyManager + // Maps id.ID to *KeyManager sendKeyManagers *keyManMap // Reception Keys map @@ -122,7 +122,7 @@ type KeyStore struct { receptionKeys *inKeyMap // Reception Key Managers map - recvKeyManagers map[id.User]*ReceptionKeyManagerBuffer + recvKeyManagers map[id.ID]*ReceptionKeyManagerBuffer lock sync.Mutex } @@ -140,11 +140,11 @@ func NewStore() *KeyStore { } ks.sendKeyManagers = new(keyManMap) ks.receptionKeys = new(inKeyMap) - ks.recvKeyManagers = make(map[id.User]*ReceptionKeyManagerBuffer) + ks.recvKeyManagers = make(map[id.ID]*ReceptionKeyManagerBuffer) return ks } -func (ks *KeyStore) DeleteContactKeys(id *id.User) error { +func (ks *KeyStore) DeleteContactKeys(id *id.ID) error { ks.lock.Lock() defer ks.lock.Unlock() @@ -177,18 +177,18 @@ func (ks *KeyStore) AddSendManager(km *KeyManager) { // Get a Send KeyManager from respective map in KeyStore // based on partner ID -func (ks *KeyStore) GetSendManager(partner *id.User) *KeyManager { +func (ks *KeyStore) GetSendManager(partner *id.ID) *KeyManager { return ks.sendKeyManagers.Load(partner) } // GetPartners returns the list of partners we have keys for -func (ks *KeyStore) GetPartners() []id.User { +func (ks *KeyStore) GetPartners() []id.ID { return ks.sendKeyManagers.keys() } // Delete a Send KeyManager from respective map in KeyStore // based on partner ID -func (ks *KeyStore) DeleteSendManager(partner *id.User) { +func (ks *KeyStore) DeleteSendManager(partner *id.ID) { ks.sendKeyManagers.Delete(partner) } @@ -225,14 +225,14 @@ func (ks *KeyStore) AddRecvManager(km *KeyManager) { // Gets the Key manager at the current location on the ReceptionKeyManagerBuffer // based on partner ID -func (ks *KeyStore) GetRecvManager(partner *id.User) *KeyManager { +func (ks *KeyStore) GetRecvManager(partner *id.ID) *KeyManager { ks.lock.Lock() defer ks.lock.Unlock() return ks.recvKeyManagers[*partner].getCurrentReceptionKeyManager() } // Delete a Receive KeyManager based on partner ID from respective map in KeyStore -func (ks *KeyStore) DeleteRecvManager(partner *id.User) { +func (ks *KeyStore) DeleteRecvManager(partner *id.ID) { ks.lock.Lock() defer ks.lock.Unlock() delete(ks.recvKeyManagers, *partner) @@ -316,7 +316,7 @@ func (ks *KeyStore) GobDecode(in []byte) error { // ReconstructKeys loops through all key managers and // calls GenerateKeys on each of them, in order to rebuild // the key maps -func (ks *KeyStore) ReconstructKeys(grp *cyclic.Group, userID *id.User) { +func (ks *KeyStore) ReconstructKeys(grp *cyclic.Group, userID *id.ID) { kmList := ks.sendKeyManagers.values() for _, km := range kmList { diff --git a/keyStore/keyStore_test.go b/keyStore/keyStore_test.go index 35077a3817b679626172ea162f827fa1424e40c3..ee334ff3ad7147cb1d6ba2f02423f4f5f1705b4a 100644 --- a/keyStore/keyStore_test.go +++ b/keyStore/keyStore_test.go @@ -40,8 +40,8 @@ func TestKeyStore_Gob(t *testing.T) { baseKey := grp.NewInt(57) privKey := grp.NewInt(5) pubKey := grp.NewInt(42) - partner := id.NewUserFromUint(14, t) - userID := id.NewUserFromUint(18, t) + partner := id.NewIdFromUInt(14, id.User, t) + userID := id.NewIdFromUInt(18, id.User, t) ks := NewStore() km := NewManager(baseKey, privKey, pubKey, @@ -126,8 +126,8 @@ func TestKeyStore_DeleteContactKeys(t *testing.T) { baseKey := grp.NewInt(57) privKey := grp.NewInt(5) pubKey := grp.NewInt(42) - partner := id.NewUserFromUint(14, t) - userID := id.NewUserFromUint(18, t) + partner := id.NewIdFromUInt(14, id.User, t) + userID := id.NewIdFromUInt(18, id.User, t) ks := NewStore() km := NewManager(baseKey, privKey, pubKey, diff --git a/keyStore/recieveKeyManagerBuffer_test.go b/keyStore/recieveKeyManagerBuffer_test.go index 18b7bdbe02569cd56d0c492f2e068588f3e6a45a..a9caec7d1dba38af6a53253a26b64b518df0688b 100644 --- a/keyStore/recieveKeyManagerBuffer_test.go +++ b/keyStore/recieveKeyManagerBuffer_test.go @@ -13,8 +13,8 @@ func TestPush(t *testing.T) { grp := initGroup() baseKey := grp.NewInt(57) - partner := id.NewUserFromUint(14, t) - userID := id.NewUserFromUint(18, t) + partner := id.NewIdFromUInt(14, id.User, t) + userID := id.NewIdFromUInt(18, id.User, t) //Generate twice the amount of keymanagers so we can test the circularness of the buffer as well kmArray := []KeyManager{} @@ -110,8 +110,8 @@ func TestReceptionKeyManagerBuffer_Gob(t *testing.T) { aBuffer := NewReceptionKeyManagerBuffer() grp := initGroup() baseKey := grp.NewInt(57) - partner := id.NewUserFromUint(14, t) - userID := id.NewUserFromUint(18, t) + partner := id.NewIdFromUInt(14, id.User, t) + userID := id.NewIdFromUInt(18, id.User, t) newKm := *NewManager(baseKey, nil, nil, partner, diff --git a/keyStore/rekeyManager.go b/keyStore/rekeyManager.go index f83ace69887ad9fd5fb2a6db5a87e07ca5cb26ef..cfb0442141a2ac3f93c871d1d35decb953e4afb0 100644 --- a/keyStore/rekeyManager.go +++ b/keyStore/rekeyManager.go @@ -29,51 +29,51 @@ func (k *RekeyKeys) RotateKeysIfReady() { } type RekeyManager struct { - Ctxs map[id.User]*RekeyContext - Keys map[id.User]*RekeyKeys + Ctxs map[id.ID]*RekeyContext + Keys map[id.ID]*RekeyKeys lock sync.Mutex } func NewRekeyManager() *RekeyManager { return &RekeyManager{ - Ctxs: make(map[id.User]*RekeyContext), - Keys: make(map[id.User]*RekeyKeys), + Ctxs: make(map[id.ID]*RekeyContext), + Keys: make(map[id.ID]*RekeyKeys), } } -func (rkm *RekeyManager) AddCtx(partner *id.User, +func (rkm *RekeyManager) AddCtx(partner *id.ID, ctx *RekeyContext) { rkm.lock.Lock() defer rkm.lock.Unlock() rkm.Ctxs[*partner] = ctx } -func (rkm *RekeyManager) GetCtx(partner *id.User) *RekeyContext { +func (rkm *RekeyManager) GetCtx(partner *id.ID) *RekeyContext { rkm.lock.Lock() defer rkm.lock.Unlock() return rkm.Ctxs[*partner] } -func (rkm *RekeyManager) DeleteCtx(partner *id.User) { +func (rkm *RekeyManager) DeleteCtx(partner *id.ID) { rkm.lock.Lock() defer rkm.lock.Unlock() delete(rkm.Ctxs, *partner) } -func (rkm *RekeyManager) AddKeys(partner *id.User, +func (rkm *RekeyManager) AddKeys(partner *id.ID, keys *RekeyKeys) { rkm.lock.Lock() defer rkm.lock.Unlock() rkm.Keys[*partner] = keys } -func (rkm *RekeyManager) GetKeys(partner *id.User) *RekeyKeys { +func (rkm *RekeyManager) GetKeys(partner *id.ID) *RekeyKeys { rkm.lock.Lock() defer rkm.lock.Unlock() return rkm.Keys[*partner] } -func (rkm *RekeyManager) DeleteKeys(partner *id.User) { +func (rkm *RekeyManager) DeleteKeys(partner *id.ID) { rkm.lock.Lock() defer rkm.lock.Unlock() delete(rkm.Keys, *partner) diff --git a/keyStore/rekeyManager_test.go b/keyStore/rekeyManager_test.go index 648b0d6a08d23f80c7c7daaa15a27d77602ea329..87072da6f788bbc5c7e6aae38fea5e7e0c8d6b96 100644 --- a/keyStore/rekeyManager_test.go +++ b/keyStore/rekeyManager_test.go @@ -22,8 +22,8 @@ func TestRekeyManager_Ctx(t *testing.T) { baseKey := grp.NewInt(57) privKey := grp.NewInt(5) pubKey := grp.NewInt(42) - partner := id.NewUserFromUint(14, t) - userID := id.NewUserFromUint(18, t) + partner := id.NewIdFromUInt(14, id.User, t) + userID := id.NewIdFromUInt(18, id.User, t) rkm := NewRekeyManager() val := &RekeyContext{ @@ -70,8 +70,8 @@ func TestRekeyManager_Keys(t *testing.T) { grp := cyclic.NewGroup(large.NewInt(107), large.NewInt(2)) privKey := grp.NewInt(5) pubKey := grp.NewInt(42) - partner := id.NewUserFromUint(14, t) - userID := id.NewUserFromUint(18, t) + partner := id.NewIdFromUInt(14, id.User, t) + userID := id.NewIdFromUInt(18, id.User, t) rkm := NewRekeyManager() val := &RekeyKeys{ diff --git a/parse/message.go b/parse/message.go index 898d7e5e77244eccecfcf7cd96dd803cefeb84df..9e626dc2c524e9660275ee74854769b0852cd689 100644 --- a/parse/message.go +++ b/parse/message.go @@ -21,8 +21,8 @@ type Message struct { TypedBody // The crypto type is inferred from the message's contents InferredType CryptoType - Sender *id.User - Receiver *id.User + Sender *id.ID + Receiver *id.ID Nonce []byte Timestamp time.Time } @@ -46,12 +46,12 @@ func (ct CryptoType) String() string { type MessageInterface interface { // Returns the message's sender ID // (uint64) BigEndian serialized into a byte slice - GetSender() *id.User + GetSender() *id.ID // Returns the message payload, without packed type GetPayload() []byte // Returns the message's recipient ID // (uint64) BigEndian serialized into a byte slice - GetRecipient() *id.User + GetRecipient() *id.ID // Return the message's inner type GetMessageType() int32 // Returns the message's outer type @@ -81,11 +81,11 @@ func (m Message) Hash() MessageHash { return mh } -func (m *Message) GetSender() *id.User { +func (m *Message) GetSender() *id.ID { return m.Sender } -func (m *Message) GetRecipient() *id.User { +func (m *Message) GetRecipient() *id.ID { return m.Receiver } diff --git a/parse/message_test.go b/parse/message_test.go index 92746eff493349b1fa6a4d0c3e252040aeabce91..15933f84cfa7c526a2b4cf1dd33af1c63eca751f 100644 --- a/parse/message_test.go +++ b/parse/message_test.go @@ -18,8 +18,8 @@ func TestMessage_Hash(t *testing.T) { m := Message{} m.MessageType = 0 m.Body = []byte{0, 0} - m.Sender = id.ZeroID - m.Receiver = id.ZeroID + m.Sender = &id.ZeroUser + m.Receiver = &id.ZeroUser m.Nonce = []byte{0, 0} baseHash := m.Hash() @@ -44,7 +44,7 @@ func TestMessage_Hash(t *testing.T) { m.Body = []byte{0, 0} - newID := id.NewUserFromUint(1, t) + newID := id.NewIdFromUInt(1, id.User, t) oldID := m.Sender m.Sender = newID diff --git a/rekey/rekey.go b/rekey/rekey.go index 710cd6e658a4f2e9d37fc30620648eb88c7a2699..b013ad245f9b5d53994e4466756d81eb525ef831 100644 --- a/rekey/rekey.go +++ b/rekey/rekey.go @@ -9,7 +9,6 @@ import ( "gitlab.com/elixxir/client/keyStore" "gitlab.com/elixxir/client/parse" "gitlab.com/elixxir/client/user" - "gitlab.com/elixxir/comms/connect" "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/crypto/diffieHellman" "gitlab.com/elixxir/crypto/e2e" @@ -17,6 +16,7 @@ import ( "gitlab.com/elixxir/primitives/format" "gitlab.com/elixxir/primitives/id" "gitlab.com/elixxir/primitives/switchboard" + "gitlab.com/xx_network/comms/connect" ) var session user.Session @@ -110,10 +110,10 @@ func InitRekey(s user.Session, m io.Communications, t *connect.Circuit, host *co // messages that have a type that includes the outer type if that's not // possible // in short, switchboard should be the package that includes outer - l.Register(id.ZeroID, + l.Register(&id.ZeroUser, int32(cmixproto.Type_NO_TYPE), &rekeyList) - l.Register(id.ZeroID, + l.Register(&id.ZeroUser, int32(cmixproto.Type_REKEY_CONFIRM), &rekeyConfirmList) } @@ -127,7 +127,7 @@ const ( RekeyConfirm ) -func rekeyProcess(rt rekeyType, partner *id.User, data []byte) error { +func rekeyProcess(rt rekeyType, partner *id.ID, data []byte) error { rkm := session.GetRekeyManager() e2egrp := session.GetE2EGroup() diff --git a/rekey/rekey_test.go b/rekey/rekey_test.go index 9c217871d430bdc524c957b7f3152e15874f424a..cd9019f5f82024a89e7fb1da845745effdbfd892 100644 --- a/rekey/rekey_test.go +++ b/rekey/rekey_test.go @@ -2,13 +2,13 @@ package rekey import ( "bytes" + "encoding/binary" "fmt" "gitlab.com/elixxir/client/cmixproto" "gitlab.com/elixxir/client/globals" "gitlab.com/elixxir/client/keyStore" "gitlab.com/elixxir/client/parse" "gitlab.com/elixxir/client/user" - "gitlab.com/elixxir/comms/connect" "gitlab.com/elixxir/crypto/csprng" "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/crypto/diffieHellman" @@ -17,6 +17,7 @@ import ( "gitlab.com/elixxir/crypto/large" "gitlab.com/elixxir/crypto/signature/rsa" "gitlab.com/elixxir/primitives/id" + "gitlab.com/xx_network/comms/connect" "os" "testing" "time" @@ -31,7 +32,7 @@ type dummyMessaging struct { // SendMessage to the server func (d *dummyMessaging) SendMessage(sess user.Session, topology *connect.Circuit, - recipientID *id.User, + recipientID *id.ID, cryptoType parse.CryptoType, message []byte, transmissionHost *connect.Host) error { d.listener <- message @@ -41,7 +42,7 @@ func (d *dummyMessaging) SendMessage(sess user.Session, // SendMessage without partitions to the server func (d *dummyMessaging) SendMessageNoPartition(sess user.Session, topology *connect.Circuit, - recipientID *id.User, + recipientID *id.ID, cryptoType parse.CryptoType, message []byte, transmissionHost *connect.Host) error { d.listener <- message @@ -59,14 +60,18 @@ func TestMain(m *testing.M) { user.InitUserRegistry(grp) rng := csprng.NewSystemRNG() u := &user.User{ - User: id.NewUserFromUints(&[4]uint64{0, 0, 0, 18}), + User: new(id.ID), Username: "Bernie", } + binary.BigEndian.PutUint64(u.User[:], 18) + u.User.SetType(id.User) myPrivKeyCyclicCMIX := grp.RandomCoprime(grp.NewMaxInt()) myPubKeyCyclicCMIX := grp.ExpG(myPrivKeyCyclicCMIX, grp.NewInt(1)) myPrivKeyCyclicE2E := e2eGrp.RandomCoprime(e2eGrp.NewMaxInt()) myPubKeyCyclicE2E := e2eGrp.ExpG(myPrivKeyCyclicE2E, e2eGrp.NewInt(1)) - partnerID := id.NewUserFromUints(&[4]uint64{0, 0, 0, 12}) + partnerID := new(id.ID) + binary.BigEndian.PutUint64(partnerID[:], 12) + partnerID.SetType(id.User) partnerPubKeyCyclic := e2eGrp.RandomCoprime(e2eGrp.NewMaxInt()) @@ -83,7 +88,9 @@ func TestMain(m *testing.M) { } rekeyChan2 := make(chan struct{}, 50) - InitRekey(session, fakeComm, connect.NewCircuit([]*id.Node{id.NewNodeFromBytes(make([]byte, id.NodeIdLen))}), nil, rekeyChan2) + nodeID := new(id.ID) + nodeID.SetType(id.Node) + InitRekey(session, fakeComm, connect.NewCircuit([]*id.ID{nodeID}), nil, rekeyChan2) // Create E2E relationship with partner // Generate baseKey @@ -129,7 +136,9 @@ func TestMain(m *testing.M) { // Test RekeyTrigger func TestRekeyTrigger(t *testing.T) { - partnerID := id.NewUserFromUints(&[4]uint64{0, 0, 0, 12}) + partnerID := new(id.ID) + binary.BigEndian.PutUint64(partnerID[:], 12) + partnerID.SetType(id.User) km := session.GetKeyStore().GetRecvManager(partnerID) partnerPubKey := km.GetPubKey() // Test receiving a RekeyTrigger message @@ -185,7 +194,9 @@ func TestRekeyTrigger(t *testing.T) { // Test RekeyConfirm func TestRekeyConfirm(t *testing.T) { - partnerID := id.NewUserFromUints(&[4]uint64{0, 0, 0, 12}) + partnerID := new(id.ID) + binary.BigEndian.PutUint64(partnerID[:], 12) + partnerID.SetType(id.User) rekeyCtx := session.GetRekeyManager().GetCtx(partnerID) baseKey := rekeyCtx.BaseKey // Test receiving a RekeyConfirm message with wrong H(baseKey) @@ -253,7 +264,9 @@ func TestRekeyConfirm(t *testing.T) { // Test Rekey func TestRekey(t *testing.T) { - partnerID := id.NewUserFromUints(&[4]uint64{0, 0, 0, 12}) + partnerID := new(id.ID) + binary.BigEndian.PutUint64(partnerID[:], 12) + partnerID.SetType(id.User) km := session.GetKeyStore().GetSendManager(partnerID) // Generate new partner public key _, grp := getGroups() @@ -312,7 +325,9 @@ func TestRekey(t *testing.T) { // Test Rekey errors func TestRekey_Errors(t *testing.T) { - partnerID := id.NewUserFromUints(&[4]uint64{0, 0, 0, 12}) + partnerID := new(id.ID) + binary.BigEndian.PutUint64(partnerID[:], 12) + partnerID.SetType(id.User) km := session.GetKeyStore().GetRecvManager(partnerID) partnerPubKey := km.GetPubKey() // Delete RekeyKeys so that RekeyTrigger and rekey error out diff --git a/storage/versionedkv.go b/storage/versionedkv.go new file mode 100644 index 0000000000000000000000000000000000000000..edd315658655e27a0c4a278ed9781615db5ce9d0 --- /dev/null +++ b/storage/versionedkv.go @@ -0,0 +1,121 @@ +package storage + +import ( + "encoding/json" + "fmt" + "gitlab.com/elixxir/ekv" + "strconv" + "strings" +) + +// MakeKeyPrefix provides a helper with a data type and a version +// TODO: We might need a separator string here, or a fixed number of +// digits available to the version string +// Otherwise version 10 could be mistaken for version 1! Bad news +// For now, let's hope a semicolon won't be part of the rest of the key +// It's not in base64, so maybe it will be fine +func MakeKeyPrefix(dataType string, version uint64) string { + return dataType + strconv.FormatUint(version, 10) + ";" +} + +// VersionedObject is used by VersionedKeyValue to keep track of +// versioning and time of storage +type VersionedObject struct { + // Used to determine version upgrade, if any + Version uint64 + + // Marshal to/from time.Time using Time.MarshalText and + // Time.UnmarshalText + Timestamp []byte + + // Serialized version of original object + Data []byte +} + +// Unmarshal deserializes a VersionedObject from a byte slice. It's used to +// make these storable in a KeyValue. +// VersionedObject exports all fields and they have simple types, so +// json.Unmarshal works fine. +func (v *VersionedObject) Unmarshal(data []byte) error { + return json.Unmarshal(data, v) +} + +// Marshal serializes a VersionedObject into a byte slice. It's used to +// make these storable in a KeyValue. +// VersionedObject exports all fields and they have simple types, so +// json.Marshal works fine. +func (v *VersionedObject) Marshal() []byte { + d, err := json.Marshal(v) + // Not being to marshal this simple object means something is really + // wrong + if err != nil { + panic(fmt.Sprintf("Could not marshal: %+v", v)) + } + return d +} + +// Upgrade functions must be of this type +type upgrade func(key string, oldObject *VersionedObject) (*VersionedObject, + error) + +// VersionedKV stores versioned data and upgrade functions +type VersionedKV struct { + upgradeTable map[string]upgrade + data ekv.KeyValue +} + +// Create a versioned key/value store backed by something implementing KeyValue +func NewVersionedKV(data ekv.KeyValue) *VersionedKV { + newKV := new(VersionedKV) + // Add new upgrade functions to this upgrade table + newKV.upgradeTable = make(map[string]upgrade) + // All upgrade functions should upgrade to the latest version. You can + // call older upgrade functions if you need to. Upgrade functions don't + // change the key or store the upgraded version of the data in the + // key/value store. There's no mechanism built in for this -- users + // should always make the key prefix before calling Set, and if they + // want the upgraded data persisted they should call Set with the + // upgraded data. + newKV.upgradeTable[MakeKeyPrefix("test", 0)] = func(key string, + oldObject *VersionedObject) (*VersionedObject, error) { + return &VersionedObject{ + Version: 1, + // Upgrade functions don't need to update the timestamp + Timestamp: oldObject.Timestamp, + Data: []byte("this object was upgraded from v0" + + " to v1"), + }, nil + } + newKV.data = data + return newKV +} + +// Get gets and upgrades data stored in the key/value store +// Make sure to inspect the version returned in the versioned object +func (v *VersionedKV) Get(key string) (*VersionedObject, error) { + // Get raw data + result := VersionedObject{} + err := v.data.Get(key, &result) + if err != nil { + return nil, err + } + // If the key starts with a version tag that we can find in the table, + // we should call that function to upgrade it + for version, upgrade := range v.upgradeTable { + if strings.HasPrefix(key, version) { + // We should run this upgrade function + // The user of this function must update the key + // based on the version returned in this + // versioned object! + return upgrade(key, &result) + } + } + return &result, nil +} + +// Set upserts new data into the storage +// When calling this, you are responsible for prefixing the key with the correct +// type and version! Call MakeKeyPrefix() to do so. +func (v *VersionedKV) Set(key string, object *VersionedObject) error { + return v.data.Set(key, object) +} diff --git a/storage/versionedkv_test.go b/storage/versionedkv_test.go new file mode 100644 index 0000000000000000000000000000000000000000..4a7ccb8754bd6b70df058bc2a3c20707f9c2a5e4 --- /dev/null +++ b/storage/versionedkv_test.go @@ -0,0 +1,146 @@ +package storage + +import ( + "bytes" + "gitlab.com/elixxir/ekv" + "reflect" + "testing" + "time" +) + +// Shows that all fields can be serialized/deserialized correctly using json +func TestVersionedObject_MarshalUnmarshal(t *testing.T) { + sometime, err := time.Date(1, 2, 3, 4, 5, 6, 7, time.UTC).MarshalText() + if err != nil { + // Should never happen + t.Fatal(err) + } + + original := VersionedObject{ + Version: 8, + Timestamp: sometime, + Data: []byte("original text"), + } + + marshalled := original.Marshal() + + unmarshalled := VersionedObject{} + err = unmarshalled.Unmarshal(marshalled) + if err != nil { + // Should never happen + t.Fatal(err) + } + + if !reflect.DeepEqual(original, unmarshalled) { + t.Error("Original and serialized/deserialized objects not equal") + } + t.Logf("%+v", unmarshalled) +} + +// VersionedKV Get should call the upgrade function when it's available +func TestVersionedKV_Get_Err(t *testing.T) { + kv := make(ekv.Memstore) + vkv := NewVersionedKV(kv) + key := MakeKeyPrefix("test", 0) + "12345" + result, err := vkv.Get(key) + if err == nil { + t.Error("Getting a key that didn't exist should have returned an error") + } + if result != nil { + t.Error("Getting a key that didn't exist shouldn't have returned data") + } +} + +// Test versioned KV upgrade path +func TestVersionedKV_Get_Upgrade(t *testing.T) { + // Set up a dummy KV with the required data + kv := make(ekv.Memstore) + vkv := NewVersionedKV(kv) + key := MakeKeyPrefix("test", 0) + "12345" + now := time.Now() + nowText, err := now.MarshalText() + if err != nil { + //Should never happen + t.Fatal(err) + } + original := VersionedObject{ + Version: 0, + Timestamp: nowText, + Data: []byte("not upgraded"), + } + originalSerialized := original.Marshal() + if err != nil { + t.Fatal(err) + } + kv[key] = originalSerialized + + result, err := vkv.Get(key) + if err != nil { + t.Fatalf("Error getting something that should have been in: %v", err) + } + if !bytes.Equal(result.Data, []byte("this object was upgraded from v0 to v1")) { + t.Errorf("upgrade should have overwritten data. result data: %q", result.Data) + } +} + +// Test Get without upgrade path +func TestVersionedKV_Get(t *testing.T) { + // Set up a dummy KV with the required data + kv := make(ekv.Memstore) + vkv := NewVersionedKV(kv) + originalVersion := uint64(1) + key := MakeKeyPrefix("test", originalVersion) + "12345" + now := time.Now() + nowText, err := now.MarshalText() + if err != nil { + //Should never happen + t.Fatal(err) + } + original := VersionedObject{ + Version: originalVersion, + Timestamp: nowText, + Data: []byte("not upgraded"), + } + originalSerialized := original.Marshal() + if err != nil { + t.Fatal(err) + } + kv[key] = originalSerialized + + result, err := vkv.Get(key) + if err != nil { + t.Fatalf("Error getting something that should have been in: %v", err) + } + if !bytes.Equal(result.Data, []byte("not upgraded")) { + t.Errorf("upgrade should not have overwritten data. result data: %q", result.Data) + } +} + +// Test that Set puts data in the store +func TestVersionedKV_Set(t *testing.T) { + kv := make(ekv.Memstore) + vkv := NewVersionedKV(kv) + originalVersion := uint64(1) + key := MakeKeyPrefix("test", originalVersion) + "12345" + now := time.Now() + nowText, err := now.MarshalText() + if err != nil { + //Should never happen + t.Fatal(err) + } + original := VersionedObject{ + Version: originalVersion, + Timestamp: nowText, + Data: []byte("not upgraded"), + } + err = vkv.Set(key, &original) + if err != nil { + t.Fatal(err) + } + + // Store should now have data in it at that key + _, ok := kv[key] + if !ok { + t.Error("data store didn't have anything in the key") + } +} diff --git a/user/regCode.go b/user/regCode.go new file mode 100644 index 0000000000000000000000000000000000000000..65094ad616ef680f8ea7a193d505c45e00cc1dc8 --- /dev/null +++ b/user/regCode.go @@ -0,0 +1,21 @@ +package user + +import ( + "encoding/base32" + "gitlab.com/elixxir/primitives/id" + "golang.org/x/crypto/blake2b" +) + +const RegCodeLen = 5 + +func RegistrationCode(id *id.ID) string { + return base32.StdEncoding.EncodeToString(userHash(id)) +} + +func userHash(id *id.ID) []byte { + h, _ := blake2b.New256(nil) + h.Write(id.Marshal()) + huid := h.Sum(nil) + huid = huid[len(huid)-RegCodeLen:] + return huid +} diff --git a/user/session.go b/user/session.go index 325db8c2db4c2eb13658903d8e69b67859f42a85..04665d6579c272144b08d222d7d7e911c882881b 100644 --- a/user/session.go +++ b/user/session.go @@ -17,12 +17,12 @@ import ( "github.com/pkg/errors" "gitlab.com/elixxir/client/globals" "gitlab.com/elixxir/client/keyStore" - "gitlab.com/elixxir/comms/connect" "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/crypto/signature/rsa" "gitlab.com/elixxir/primitives/format" "gitlab.com/elixxir/primitives/id" "gitlab.com/elixxir/primitives/switchboard" + "gitlab.com/xx_network/comms/connect" "io" "sync" "sync/atomic" @@ -36,7 +36,7 @@ var ErrQuery = errors.New("element not in map") type Session interface { GetCurrentUser() (currentUser *User) GetNodeKeys(topology *connect.Circuit) []NodeKeys - PushNodeKey(id *id.Node, key NodeKeys) + PushNodeKey(id *id.ID, key NodeKeys) GetRSAPrivateKey() *rsa.PrivateKey GetRSAPublicKey() *rsa.PublicKey GetCMIXDHPrivateKey() *cyclic.Int @@ -60,7 +60,7 @@ type Session interface { UnlockStorage() GetSessionData() ([]byte, error) GetRegistrationValidationSignature() []byte - GetNodes() map[id.Node]int + GetNodes() map[id.ID]int AppendGarbledMessage(messages ...*format.Message) PopGarbledMessages() []*format.Message GetSalt() []byte @@ -68,9 +68,9 @@ type Session interface { GetRegState() uint32 ChangeUsername(string) error StorageIsEmpty() bool - GetContactByValue(string) (*id.User, []byte) - StoreContactByValue(string, *id.User, []byte) - DeleteContact(*id.User) (string, error) + GetContactByValue(string) (*id.ID, []byte) + StoreContactByValue(string, *id.ID, []byte) + DeleteContact(*id.ID) (string, error) GetSessionLocation() uint8 LoadEncryptedSession(store globals.Storage) ([]byte, error) RegisterPermissioningSignature(sig []byte) error @@ -96,7 +96,7 @@ func NewSession(store globals.Storage, regState := uint32(KeyGenComplete) // With an underlying Session data structure return Session(&SessionObj{ - NodeKeys: make(map[id.Node]NodeKeys), + NodeKeys: make(map[id.ID]NodeKeys), CurrentUser: u, RSAPublicKey: publicKeyRSA, RSAPrivateKey: privateKeyRSA, @@ -173,7 +173,7 @@ func LoadSession(store globals.Storage, password string) (Session, error) { session.password = password if session.NodeKeys == nil { - session.NodeKeys = make(map[id.Node]NodeKeys) + session.NodeKeys = make(map[id.ID]NodeKeys) } return &session, nil @@ -246,7 +246,7 @@ type SessionObj struct { // Currently authenticated user CurrentUser *User - NodeKeys map[id.Node]NodeKeys + NodeKeys map[id.ID]NodeKeys RSAPrivateKey *rsa.PrivateKey RSAPublicKey *rsa.PublicKey CMIXDHPrivateKey *cyclic.Int @@ -325,7 +325,7 @@ func (s *SessionObj) LoadEncryptedSession(store globals.Storage) ([]byte, error) } type SearchedUserRecord struct { - Id id.User + Id id.ID Pk []byte } @@ -348,10 +348,10 @@ func (s *SessionObj) SetLastMessageID(id string) { s.UnlockStorage() } -func (s *SessionObj) GetNodes() map[id.Node]int { +func (s *SessionObj) GetNodes() map[id.ID]int { s.LockStorage() defer s.UnlockStorage() - nodes := make(map[id.Node]int, 0) + nodes := make(map[id.ID]int, 0) for node := range s.NodeKeys { nodes[node] = 1 } @@ -379,7 +379,7 @@ func (s *SessionObj) GetNodeKeys(topology *connect.Circuit) []NodeKeys { return keys } -func (s *SessionObj) PushNodeKey(id *id.Node, key NodeKeys) { +func (s *SessionObj) PushNodeKey(id *id.ID, key NodeKeys) { s.LockStorage() defer s.UnlockStorage() @@ -731,7 +731,7 @@ func (s *SessionObj) PopGarbledMessages() []*format.Message { return tempBuffer } -func (s *SessionObj) GetContactByValue(v string) (*id.User, []byte) { +func (s *SessionObj) GetContactByValue(v string) (*id.ID, []byte) { s.LockStorage() defer s.UnlockStorage() u, ok := s.ContactsByValue[v] @@ -741,7 +741,7 @@ func (s *SessionObj) GetContactByValue(v string) (*id.User, []byte) { return &(u.Id), u.Pk } -func (s *SessionObj) StoreContactByValue(v string, uid *id.User, pk []byte) { +func (s *SessionObj) StoreContactByValue(v string, uid *id.ID, pk []byte) { s.LockStorage() defer s.UnlockStorage() u, ok := s.ContactsByValue[v] @@ -756,7 +756,7 @@ func (s *SessionObj) StoreContactByValue(v string, uid *id.User, pk []byte) { } } -func (s *SessionObj) DeleteContact(uid *id.User) (string, error) { +func (s *SessionObj) DeleteContact(uid *id.ID) (string, error) { s.LockStorage() defer s.UnlockStorage() diff --git a/user/session_test.go b/user/session_test.go index 59068c9a7fa83d9668bb9502ce85eed2a30d42b3..ddf7201574ec3eb66bd06c5bb87c8932d4ccd5e5 100644 --- a/user/session_test.go +++ b/user/session_test.go @@ -11,12 +11,12 @@ import ( "crypto/sha256" "encoding/gob" "gitlab.com/elixxir/client/globals" - "gitlab.com/elixxir/comms/connect" "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/crypto/large" "gitlab.com/elixxir/crypto/signature/rsa" "gitlab.com/elixxir/primitives/format" "gitlab.com/elixxir/primitives/id" + "gitlab.com/xx_network/comms/connect" "math/rand" "reflect" "testing" @@ -34,14 +34,14 @@ func TestUserSession(t *testing.T) { // sure that the gob contains the user ID UID := uint64(65) - u.User = id.NewUserFromUint(UID, t) + u.User = id.NewIdFromUInt(UID, id.User, t) u.Username = "Mario" grp := cyclic.NewGroup(large.NewInt(107), large.NewInt(2)) - nodeID := id.NewNodeFromUInt(1, t) + nodeID := id.NewIdFromUInt(1, id.Node, t) - topology := connect.NewCircuit([]*id.Node{nodeID}) + topology := connect.NewCircuit([]*id.ID{nodeID}) // Storage storage := &globals.RamStorage{} @@ -220,12 +220,12 @@ func TestSessionObj_DeleteContact(t *testing.T) { // sure that the gob contains the user ID UID := uint64(65) - u.User = id.NewUserFromUint(UID, t) + u.User = id.NewIdFromUInt(UID, id.User, t) u.Username = "Mario" grp := cyclic.NewGroup(large.NewInt(107), large.NewInt(2)) - nodeID := id.NewNodeFromUInt(1, t) + nodeID := id.NewIdFromUInt(1, id.Node, t) // Storage storage := &globals.RamStorage{} @@ -261,9 +261,10 @@ func TestSessionObj_DeleteContact(t *testing.T) { ReceptionKey: grp.NewInt(2), }) - ses.StoreContactByValue("test", id.NewUserFromBytes([]byte("test")), []byte("test")) + testContact := id.NewIdFromString("test", id.User, t) + ses.StoreContactByValue("test", testContact, []byte("test")) - _, err = ses.DeleteContact(id.NewUserFromBytes([]byte("test"))) + _, err = ses.DeleteContact(testContact) if err != nil { t.Errorf("Failed to delete contact: %+v", err) } @@ -271,7 +272,7 @@ func TestSessionObj_DeleteContact(t *testing.T) { func TestGetPubKey(t *testing.T) { u := new(User) - UID := id.NewUserFromUint(1, t) + UID := id.NewIdFromUInt(1, id.User, t) u.User = UID u.Username = "Mario" @@ -304,7 +305,7 @@ func TestGetPubKey(t *testing.T) { err.Error()) } - ses.PushNodeKey(id.NewNodeFromUInt(1, t), NodeKeys{ + ses.PushNodeKey(id.NewIdFromUInt(1, id.Node, t), NodeKeys{ TransmissionKey: grp.NewInt(2), ReceptionKey: grp.NewInt(2), }) @@ -323,12 +324,12 @@ func TestSessionObj_StorageIsEmpty(t *testing.T) { // sure that the gob contains the user ID UID := uint64(65) - u.User = id.NewUserFromUint(UID, t) + u.User = id.NewIdFromUInt(UID, id.User, t) u.Username = "Mario" grp := cyclic.NewGroup(large.NewInt(107), large.NewInt(2)) - nodeID := id.NewNodeFromUInt(1, t) + nodeID := id.NewIdFromUInt(1, id.Node, t) // Storage storage := &globals.RamStorage{} @@ -381,12 +382,12 @@ func TestSessionObj_GetContactByValue(t *testing.T) { // sure that the gob contains the user ID UID := uint64(65) - u.User = id.NewUserFromUint(UID, t) + u.User = id.NewIdFromUInt(UID, id.User, t) u.Username = "Mario" grp := cyclic.NewGroup(large.NewInt(107), large.NewInt(2)) - nodeID := id.NewNodeFromUInt(1, t) + nodeID := id.NewIdFromUInt(1, id.Node, t) // Storage storage := &globals.RamStorage{} @@ -420,7 +421,9 @@ func TestSessionObj_GetContactByValue(t *testing.T) { ReceptionKey: grp.NewInt(2), }) - ses.StoreContactByValue("value", id.NewUserFromBytes([]byte("test")), []byte("test")) + userId := id.NewIdFromBytes([]byte("test"), t) + + ses.StoreContactByValue("value", userId, []byte("test")) observedUser, observedPk := ses.GetContactByValue("value") @@ -429,7 +432,7 @@ func TestSessionObj_GetContactByValue(t *testing.T) { "Expected: %+v\n\tRecieved: %+v", privateKey.PublicKey.N.Bytes(), observedPk) } - if !observedUser.Cmp(id.NewUserFromBytes([]byte("test"))) { + if !observedUser.Cmp(userId) { t.Errorf("Failed to retrieve user using GetContactByValue;"+ "Expected: %+v\n\tRecieved: %+v", u.User, observedUser) } @@ -437,7 +440,7 @@ func TestSessionObj_GetContactByValue(t *testing.T) { func TestGetPrivKey(t *testing.T) { u := new(User) - UID := id.NewUserFromUint(1, t) + UID := id.NewIdFromUInt(1, id.User, t) u.User = UID u.Username = "Mario" @@ -470,7 +473,7 @@ func TestGetPrivKey(t *testing.T) { err.Error()) } - ses.PushNodeKey(id.NewNodeFromUInt(1, t), NodeKeys{ + ses.PushNodeKey(id.NewIdFromUInt(1, id.Node, t), NodeKeys{ TransmissionKey: grp.NewInt(2), ReceptionKey: grp.NewInt(2), }) @@ -637,7 +640,7 @@ func GenerateTestMessages(size int) []*format.Message { // Happy path func TestConvertSessionV1toV2(t *testing.T) { u := new(User) - UID := id.NewUserFromUint(1, t) + UID := id.NewIdFromUInt(1, id.Node, t) u.User = UID u.Username = "Bernie" diff --git a/user/sessionv1.go b/user/sessionv1.go index 0496913de013df8972cc45d0c5fb7dc88e785bb5..3f470aa558447c8edf0aad156db45e6a23d52d21 100644 --- a/user/sessionv1.go +++ b/user/sessionv1.go @@ -20,7 +20,7 @@ type SessionObjV1 struct { // Currently authenticated user CurrentUser *UserV1 - Keys map[id.Node]NodeKeys + Keys map[id.ID]NodeKeys RSAPrivateKey *rsa.PrivateKey RSAPublicKey *rsa.PublicKey CMIXDHPrivateKey *cyclic.Int @@ -73,7 +73,7 @@ type SessionObjV1 struct { // Struct representing a User in the system type UserV1 struct { - User *id.User + User *id.ID Nick string Email string } diff --git a/user/user.go b/user/user.go index 209f039c94751cb6a11d8d8b42ba877d6fd4daac..45e0bc65cf265247df30e08c830ee87d958f006c 100644 --- a/user/user.go +++ b/user/user.go @@ -8,6 +8,7 @@ package user import ( "crypto/sha256" + "encoding/binary" "gitlab.com/elixxir/client/globals" "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/primitives/id" @@ -31,25 +32,25 @@ func InitUserRegistry(grp *cyclic.Group) { // Interface for User Registry operations type Registry interface { - NewUser(id *id.User, nickname string) *User - DeleteUser(id *id.User) - GetUser(id *id.User) (user *User, ok bool) + NewUser(id *id.ID, nickname string) *User + DeleteUser(id *id.ID) + GetUser(id *id.ID) (user *User, ok bool) UpsertUser(user *User) CountUsers() int - LookupUser(hid string) (uid *id.User, ok bool) - LookupKeys(uid *id.User) (*NodeKeys, bool) + LookupUser(hid string) (uid *id.ID, ok bool) + LookupKeys(uid *id.ID) (*NodeKeys, bool) } type UserMap struct { // Map acting as the User Registry containing User -> ID mapping - userCollection map[id.User]*User + userCollection map[id.ID]*User // Increments sequentially for User.ID values idCounter uint64 // Temporary map acting as a lookup table for demo user registration codes // Key type is string because keys must implement == and []byte doesn't - userLookup map[string]*id.User + userLookup map[string]*id.ID //Temporary placed to store the keys for each user - keysLookup map[id.User]*NodeKeys + keysLookup map[id.ID]*NodeKeys } // newRegistry creates a new Registry interface @@ -57,21 +58,22 @@ func newRegistry(grp *cyclic.Group) Registry { if len(DemoChannelNames) > 10 || len(DemoUserNicks) > 30 { globals.Log.ERROR.Print("Not enough demo users have been hardcoded.") } - userUserIdMap := make(map[id.User]*User) - userRegCodeMap := make(map[string]*id.User) - nk := make(map[id.User]*NodeKeys) + userUserIdMap := make(map[id.ID]*User) + userRegCodeMap := make(map[string]*id.ID) + nk := make(map[id.ID]*NodeKeys) // Deterministically create NumDemoUsers users // TODO Replace this with real user registration/discovery for i := uint64(1); i <= NumDemoUsers; i++ { - currentID := id.NewUserFromUints(&[4]uint64{0, 0, 0, i}) + currentID := new(id.ID) + binary.BigEndian.PutUint64(currentID[:], i) + currentID.SetType(id.User) newUsr := new(User) nodeKey := new(NodeKeys) // Generate user parameters newUsr.User = currentID newUsr.Precan = true - currentID.RegistrationCode() // TODO We need a better way to generate base/recursive keys h := sha256.New() h.Write([]byte(string(40000 + i))) @@ -83,23 +85,27 @@ func newRegistry(grp *cyclic.Group) Registry { // Add user to collection and lookup table userUserIdMap[*newUsr.User] = newUsr // Detect collisions in the registration code - if _, ok := userRegCodeMap[newUsr.User.RegistrationCode()]; ok { + if _, ok := userRegCodeMap[RegistrationCode(newUsr.User)]; ok { globals.Log.ERROR.Printf( "Collision in demo user list creation at %v. "+ "Please fix ASAP (include more bits to the reg code.", i) } - userRegCodeMap[newUsr.User.RegistrationCode()] = newUsr.User + userRegCodeMap[RegistrationCode(newUsr.User)] = newUsr.User nk[*newUsr.User] = nodeKey } // Channels have been hardcoded to users starting with 31 for i := 0; i < len(DemoUserNicks); i++ { - currentID := id.NewUserFromUints(&[4]uint64{0, 0, 0, uint64(i) + 1}) + currentID := new(id.ID) + binary.BigEndian.PutUint64(currentID[:], uint64(i)+1) + currentID.SetType(id.User) userUserIdMap[*currentID].Username = DemoUserNicks[i] } for i := 0; i < len(DemoChannelNames); i++ { - currentID := id.NewUserFromUints(&[4]uint64{0, 0, 0, uint64(i) + 31}) + currentID := new(id.ID) + binary.BigEndian.PutUint64(currentID[:], uint64(i)+31) + currentID.SetType(id.User) userUserIdMap[*currentID].Username = DemoChannelNames[i] } @@ -112,7 +118,7 @@ func newRegistry(grp *cyclic.Group) Registry { // Struct representing a User in the system type User struct { - User *id.User + User *id.ID Username string Precan bool } @@ -130,20 +136,20 @@ func (u *User) DeepCopy() *User { } // NewUser creates a new User object with default fields and given address. -func (m *UserMap) NewUser(id *id.User, username string) *User { +func (m *UserMap) NewUser(id *id.ID, username string) *User { return &User{User: id, Username: username} } // GetUser returns a user with the given ID from userCollection // and a boolean for whether the user exists -func (m *UserMap) GetUser(id *id.User) (user *User, ok bool) { +func (m *UserMap) GetUser(id *id.ID) (user *User, ok bool) { user, ok = m.userCollection[*id] user = user.DeepCopy() return } // DeleteContactKeys deletes a user with the given ID from userCollection. -func (m *UserMap) DeleteUser(id *id.User) { +func (m *UserMap) DeleteUser(id *id.ID) { // If key does not exist, do nothing delete(m.userCollection, *id) } @@ -160,13 +166,13 @@ func (m *UserMap) CountUsers() int { } // LookupUser returns the user id corresponding to the demo registration code -func (m *UserMap) LookupUser(hid string) (*id.User, bool) { +func (m *UserMap) LookupUser(hid string) (*id.ID, bool) { uid, ok := m.userLookup[hid] return uid, ok } // LookupKeys returns the keys for the given user from the temporary key map -func (m *UserMap) LookupKeys(uid *id.User) (*NodeKeys, bool) { +func (m *UserMap) LookupKeys(uid *id.ID) (*NodeKeys, bool) { nk, t := m.keysLookup[*uid] return nk, t } diff --git a/user/user_test.go b/user/user_test.go index fd2a0cfe78c38c60de115d574128805049495cb4..52d303e432c7c0a686b30406db2b130a7b46ce73 100644 --- a/user/user_test.go +++ b/user/user_test.go @@ -24,16 +24,16 @@ func TestUserRegistry(t *testing.T) { } // Test the integration of the LookupUser, UserHash and GetUser functions for i := 0; i < len(DemoUserNicks); i++ { - currentID := id.NewUserFromUint(uint64(i+1), t) - reg, ok := Users.LookupUser(currentID.RegistrationCode()) + currentID := id.NewIdFromUInt(uint64(i+1), id.User, t) + reg, ok := Users.LookupUser(RegistrationCode(currentID)) if !ok { t.Errorf("Couldn't lookup user %q with code %v", *currentID, - currentID.RegistrationCode()) + RegistrationCode(currentID)) } usr, ok := Users.GetUser(reg) if !ok { - t.Logf("Reg codes of both: %v, %v", reg.RegistrationCode(), - currentID.RegistrationCode()) + t.Logf("Reg codes of both: %v, %v", RegistrationCode(reg), + RegistrationCode(currentID)) t.Errorf("Couldn't get user %q corresponding to user %q", *reg, *currentID) } @@ -43,7 +43,7 @@ func TestUserRegistry(t *testing.T) { } } // Test the NewUser function - newID := id.NewUserFromUint(2002, t) + newID := id.NewIdFromUInt(2002, id.User, t) usr := Users.NewUser(newID, "Will I am") if usr.Username != "Will I am" { @@ -71,7 +71,7 @@ func TestUserRegistry(t *testing.T) { grp := InitGroup() // Test LookupKeys - keys, suc := Users.LookupKeys(id.NewUserFromUint(1, t)) + keys, suc := Users.LookupKeys(id.NewIdFromUInt(1, id.User, t)) if !suc { t.Errorf("LookupKeys failed to find a valid user.") } @@ -85,9 +85,9 @@ func TestUserRegistry(t *testing.T) { } // Test delete user - Users.DeleteUser(id.NewUserFromUint(2, t)) + Users.DeleteUser(id.NewIdFromUInt(2, id.User, t)) - _, ok := Users.GetUser(id.NewUserFromUint(2, t)) + _, ok := Users.GetUser(id.NewIdFromUInt(2, id.User, t)) if ok { t.Errorf("User %v has not been deleted succesfully!", usr.Username) } @@ -97,8 +97,8 @@ func TestUserRegistry(t *testing.T) { // the first several users func TestPrintRegCodes(t *testing.T) { for i := 1; i <= NumDemoUsers; i++ { - currentID := id.NewUserFromUint(uint64(i), t) - t.Logf("%v:\t%v", i, currentID.RegistrationCode()) + currentID := id.NewIdFromUInt(uint64(i), id.User, t) + t.Logf("%v:\t%v", i, RegistrationCode(currentID)) } } diff --git a/version_vars.go.bak b/version_vars.go.bak new file mode 100644 index 0000000000000000000000000000000000000000..67620a0b3f330cea5051e878a2c07ceea175125d --- /dev/null +++ b/version_vars.go.bak @@ -0,0 +1,33 @@ +// Code generated by go generate; DO NOT EDIT. +// This file was generated by robots at +// 2020-07-30 15:27:18.7064291 -0700 PDT m=+0.065083001 +package cmd + +const GITVERSION = `4ef845a Merge branch 'hotfix/integrateekv' into 'release'` +const SEMVER = "1.4.0" +const DEPENDENCIES = `module gitlab.com/elixxir/client + +go 1.13 + +require ( + github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3 + github.com/golang/protobuf v1.4.2 + github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00 // indirect + github.com/pelletier/go-toml v1.6.0 // indirect + github.com/pkg/errors v0.9.1 + github.com/smartystreets/assertions v1.0.1 // indirect + github.com/spf13/afero v1.2.2 // indirect + github.com/spf13/cast v1.3.1 // indirect + github.com/spf13/cobra v1.0.0 + github.com/spf13/jwalterweatherman v1.1.0 + github.com/spf13/pflag v1.0.5 // indirect + github.com/spf13/viper v1.6.2 + gitlab.com/elixxir/comms v0.0.0-20200730220537-60dbe58afe94 + gitlab.com/elixxir/crypto v0.0.0-20200707005343-97f868cbd930 + gitlab.com/elixxir/ekv v0.0.0-20200729182028-159355ea5842 + gitlab.com/elixxir/primitives v0.0.0-20200706165052-9fe7a4fb99a3 + gitlab.com/xx_network/comms v0.0.0-20200730220144-eea32e8b696d + golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899 + gopkg.in/ini.v1 v1.52.0 // indirect +) +`