diff --git a/ud/addFact.go b/ud/addFact.go index f5174a0ed1dc928759ea14591e3e983b0c91bfc3..ba9fef240d7b26dc56d4eb89b41c23676a026ce1 100644 --- a/ud/addFact.go +++ b/ud/addFact.go @@ -49,7 +49,7 @@ func (m *Manager) addFact(inFact fact.Fact, myId *id.ID, if err != nil { return "", err } - stream := m.rng.GetStream() + stream := m.getRng().GetStream() defer stream.Close() fSig, err := rsa.Sign(stream, privKey, hash.CMixHash, fHash, nil) if err != nil { diff --git a/ud/lookup_test.go b/ud/lookup_test.go index 716f93460fe87b982e7f705ff6ebab59e7711a60..da300b7b4e778913d8c66b84a497d344e368c795 100644 --- a/ud/lookup_test.go +++ b/ud/lookup_test.go @@ -87,7 +87,7 @@ func TestManager_Lookup(t *testing.T) { } // Run the lookup - _, _, err = Lookup(m.network, prng, + _, _, err = Lookup(m.getCmix(), prng, grp, udContact, callback, uid, p) if err != nil { t.Errorf("Lookup() returned an error: %+v", err) diff --git a/ud/manager.go b/ud/manager.go index 757d2247331fdbc2f531039c72e6643306a4725c..026583cb43bbd2b000ca49a1b693b92e6bb2dfe4 100644 --- a/ud/manager.go +++ b/ud/manager.go @@ -26,18 +26,11 @@ const ( // Manager is the control structure for the contacting the user discovery service. type Manager struct { - // Network is a sub-interface of the cmix.Client interface. It - // allows the Manager to retrieve network state. - network CMix // e2e is a sub-interface of the e2e.Handler. It allows the Manager // to retrieve the client's E2E information. e2e E2E - // events allows the Manager to report events to the other - // levels of the client. - events event.Reporter - // store is an instantiation of this package's storage object. // It contains the facts that are in some state of being registered // with the UD service @@ -47,11 +40,6 @@ type Manager struct { // gRPC functions for registering and fact operations. comms Comms - // kv is a versioned key-value store used for isRegistered and - // setRegistered. This is separated from store operations as store's kv - // has a different prefix which breaks backwards compatibility. - kv *versioned.KV - // factMux is to be used for Add/Remove fact.Fact operations. // This prevents simultaneous calls to Add/Remove calls which // may cause unexpected behaviour. @@ -61,10 +49,6 @@ type Manager struct { // production. This is for testing with a separately deployed UD service. alternativeUd *alternateUd - // rng is a fastRNG.StreamGenerator which is used to generate random - // data. This is used for signatures for adding/removing facts. - rng *fastRNG.StreamGenerator - // registrationValidationSignature for the ReceptionID // Optional, depending on UD configuration registrationValidationSignature []byte @@ -85,12 +69,8 @@ func NewManager(e2e E2E, comms Comms, follower NetworkStatus, // Initialize manager m := &Manager{ - network: e2e.GetCmix(), e2e: e2e, - events: e2e.GetEventReporter(), comms: comms, - kv: e2e.GetStorage().GetKV(), - rng: e2e.GetRng(), registrationValidationSignature: registrationValidationSignature, } @@ -100,7 +80,7 @@ func NewManager(e2e E2E, comms Comms, follower NetworkStatus, // Initialize store var err error - m.store, err = store.NewOrLoadStore(m.kv) + m.store, err = store.NewOrLoadStore(m.getKv()) if err != nil { return nil, errors.Errorf("Failed to initialize store: %v", err) } @@ -113,7 +93,7 @@ func NewManager(e2e E2E, comms Comms, follower NetworkStatus, } // Register with user discovery - stream := m.rng.GetStream() + stream := m.getRng().GetStream() defer stream.Close() err = m.register(username, stream, m.comms, udHost) if err != nil { @@ -121,8 +101,8 @@ func NewManager(e2e E2E, comms Comms, follower NetworkStatus, } // Set storage to registered - if err = setRegistered(m.kv); err != nil && m.events != nil { - m.events.Report(1, "UserDiscovery", "Registration", + if err = setRegistered(m.getKv()); err != nil && m.getEventReporter() != nil { + m.getEventReporter().Report(1, "UserDiscovery", "Registration", fmt.Sprintf("User Registered with UD: %+v", username)) } @@ -144,17 +124,13 @@ func NewManagerFromBackup(e2e E2E, comms Comms, follower NetworkStatus, // Initialize manager m := &Manager{ - network: e2e.GetCmix(), - e2e: e2e, - events: e2e.GetEventReporter(), - comms: comms, - kv: e2e.GetStorage().GetKV(), - rng: e2e.GetRng(), + e2e: e2e, + comms: comms, } // Initialize our store var err error - m.store, err = store.NewOrLoadStore(m.kv) + m.store, err = store.NewOrLoadStore(m.getKv()) if err != nil { return nil, err } @@ -168,7 +144,7 @@ func NewManagerFromBackup(e2e E2E, comms Comms, follower NetworkStatus, // Set as registered. Since it's from a backup, // the client is already registered - if err = setRegistered(m.kv); err != nil { + if err = setRegistered(m.getKv()); err != nil { return nil, errors.WithMessage(err, "failed to set client as "+ "registered with user discovery.") } @@ -213,14 +189,9 @@ func InitStoreFromBackup(kv *versioned.KV, // from disk. This is meant to be called after any the first // instantiation of the manager by NewUserDiscovery. func LoadManager(e2e E2E, comms Comms) (*Manager, error) { - m := &Manager{ - network: e2e.GetCmix(), - e2e: e2e, - events: e2e.GetEventReporter(), - comms: comms, - rng: e2e.GetRng(), - kv: e2e.GetStorage().GetKV(), + e2e: e2e, + comms: comms, } if !m.isRegistered() { @@ -229,7 +200,7 @@ func LoadManager(e2e E2E, comms Comms) (*Manager, error) { } var err error - m.store, err = store.NewOrLoadStore(m.kv) + m.store, err = store.NewOrLoadStore(m.getKv()) if err != nil { return nil, errors.Errorf("Failed to initialize store: %v", err) } @@ -274,7 +245,7 @@ func (m *Manager) GetContact() (contact.Contact, error) { }, nil } - netDef := m.network.GetInstance().GetPartialNdf().Get() + netDef := m.getCmix().GetInstance().GetPartialNdf().Get() // Unmarshal UD ID from the NDF udID, err := id.Unmarshal(netDef.UDB.ID) @@ -307,7 +278,7 @@ func (m *Manager) getOrAddUdHost() (*connect.Host, error) { return m.alternativeUd.host, nil } - netDef := m.network.GetInstance().GetPartialNdf().Get() + netDef := m.getCmix().GetInstance().GetPartialNdf().Get() if netDef.UDB.Cert == "" { return nil, errors.New("NDF does not have User Discovery information, " + "is there network access?: Cert not present.") @@ -340,3 +311,32 @@ func (m *Manager) getOrAddUdHost() (*connect.Host, error) { return host, nil } + +///////////////////////////////////////////////////////////////////////////////////////// +// Internal getters ///////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////// + +// getCmix retrieve a sub-interface of cmix.Client. +// It allows the Manager to retrieve network state. +func (m *Manager) getCmix() CMix { + return m.e2e.GetCmix() +} + +// getKv returns a versioned.KV used for isRegistered and setRegistered. +// This is separated from store operations as store's kv +// has a different prefix which breaks backwards compatibility. +func (m *Manager) getKv() *versioned.KV { + return m.e2e.GetStorage().GetKV() +} + +// getEventReporter returns an event.Reporter. This allows +// the Manager to report events to the other levels of the client. +func (m *Manager) getEventReporter() event.Reporter { + return m.e2e.GetEventReporter() +} + +// getRng returns a fastRNG.StreamGenerator. This RNG is for +// generating signatures for adding/removing facts. +func (m *Manager) getRng() *fastRNG.StreamGenerator { + return m.e2e.GetRng() +} diff --git a/ud/mockE2e_test.go b/ud/mockE2e_test.go index 4341478526e251ff22b85a0ccfa458383137798b..103d7e1362eeebfdec403a741044f6610918cff0 100644 --- a/ud/mockE2e_test.go +++ b/ud/mockE2e_test.go @@ -12,6 +12,7 @@ import ( "gitlab.com/elixxir/client/event" "gitlab.com/elixxir/client/stoppable" "gitlab.com/elixxir/client/storage" + "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/client/xxdk" "gitlab.com/elixxir/crypto/cyclic" cryptoE2e "gitlab.com/elixxir/crypto/e2e" @@ -28,9 +29,13 @@ import ( /////////////////////////////////////////////////////////////////////////////// type mockE2e struct { - grp *cyclic.Group - t testing.TB - key *rsa.PrivateKey + grp *cyclic.Group + events event.Reporter + rng *fastRNG.StreamGenerator + kv *versioned.KV + network cmix.Client + t testing.TB + key *rsa.PrivateKey } func (m mockE2e) GetE2E() e2e.Handler { @@ -80,8 +85,7 @@ func (m mockE2e) GetEventReporter() event.Reporter { } func (m mockE2e) GetCmix() cmix.Client { - //TODO implement me - panic("implement me") + return m.network } func (m mockE2e) GetStorage() storage.Session { diff --git a/ud/networkManager_test.go b/ud/networkManager_test.go new file mode 100644 index 0000000000000000000000000000000000000000..8aaec9115ab25ee3870dbff16afe3aa62670bbe8 --- /dev/null +++ b/ud/networkManager_test.go @@ -0,0 +1,225 @@ +package ud + +import ( + "bytes" + "gitlab.com/elixxir/client/cmix" + "gitlab.com/elixxir/client/cmix/gateway" + "gitlab.com/elixxir/client/cmix/identity" + "gitlab.com/elixxir/client/cmix/identity/receptionID" + "gitlab.com/elixxir/client/cmix/message" + "gitlab.com/elixxir/client/cmix/rounds" + "gitlab.com/elixxir/client/stoppable" + "gitlab.com/elixxir/comms/network" + "gitlab.com/elixxir/crypto/contact" + "gitlab.com/elixxir/primitives/format" + "gitlab.com/xx_network/comms/connect" + "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/id/ephemeral" + "time" +) + +// testNetworkManager is a mock implementation of the CMix interface. +type testNetworkManager struct { + requestProcess message.Processor + instance *network.Instance + testingFace interface{} + c contact.Contact + responseProcessor message.Processor +} + +func (tnm *testNetworkManager) Send(recipient *id.ID, fingerprint format.Fingerprint, + service message.Service, + payload, mac []byte, cmixParams cmix.CMIXParams) (id.Round, ephemeral.Id, error) { + msg := format.NewMessage(tnm.instance.GetE2EGroup().GetP().ByteLen()) + // Build message. Will panic if inputs are not correct. + msg.SetKeyFP(fingerprint) + msg.SetContents(payload) + msg.SetMac(mac) + msg.SetSIH(service.Hash(msg.GetContents())) + // If the recipient for a call to Send is UD, then this + // is the request pathway. Call the UD processor to simulate + // the UD picking up the request + if bytes.Equal(tnm.instance.GetFullNdf(). + Get().UDB.ID, + recipient.Bytes()) { + tnm.responseProcessor.Process(msg, receptionID.EphemeralIdentity{}, rounds.Round{}) + + } else { + // This should happen when the mock UD service Sends back a response. + // Calling process mocks up the requester picking up the response. + tnm.requestProcess.Process(msg, receptionID.EphemeralIdentity{}, rounds.Round{}) + } + + return 0, ephemeral.Id{}, nil +} + +func (tnm *testNetworkManager) AddFingerprint(identity *id.ID, + fingerprint format.Fingerprint, mp message.Processor) error { + // AddFingerprint gets called in both the request and response + // code-paths. We only want to set in the code-path transmitting + // from UD + if !bytes.Equal(tnm.instance.GetFullNdf().Get().UDB.ID, + identity.Bytes()) { + tnm.requestProcess = mp + } + + return nil +} + +func (tnm *testNetworkManager) AddService(clientID *id.ID, + newService message.Service, + response message.Processor) { + tnm.responseProcessor = response + return +} + +func (tnm *testNetworkManager) CheckInProgressMessages() { + return +} + +func (tnm *testNetworkManager) GetMaxMessageLength() int { + return 700 +} + +func (tnm *testNetworkManager) AddIdentity(id *id.ID, validUntil time.Time, persistent bool) { + return +} + +func (tnm *testNetworkManager) DeleteClientFingerprints(identity *id.ID) { + return +} + +func (tnm *testNetworkManager) Process(ecrMsg format.Message, + receptionID receptionID.EphemeralIdentity, round rounds.Round) { + +} + +func (tnm *testNetworkManager) String() string { + return "mockPRocessor" +} + +func (tnm *testNetworkManager) DeleteService(clientID *id.ID, toDelete message.Service, processor message.Processor) { + return +} + +func (tnm *testNetworkManager) IsHealthy() bool { + return true +} + +func (tnm *testNetworkManager) GetAddressSpace() uint8 { + return 8 +} + +func (tnm *testNetworkManager) GetInstance() *network.Instance { + return tnm.instance +} + +func (tnm *testNetworkManager) Follow(report cmix.ClientErrorReport) (stoppable.Stoppable, error) { + //TODO implement me + panic("implement me") +} + +func (tnm *testNetworkManager) GetVerboseRounds() string { + //TODO implement me + panic("implement me") +} + +func (tnm *testNetworkManager) SendToAny(sendFunc func(host *connect.Host) (interface{}, error), stop *stoppable.Single) (interface{}, error) { + //TODO implement me + panic("implement me") +} + +func (tnm *testNetworkManager) SendMany(messages []cmix.TargetedCmixMessage, p cmix.CMIXParams) (id.Round, []ephemeral.Id, error) { + //TODO implement me + panic("implement me") +} + +func (tnm *testNetworkManager) RemoveIdentity(id *id.ID) { + //TODO implement me + panic("implement me") +} + +func (tnm *testNetworkManager) GetIdentity(get *id.ID) (identity.TrackedID, error) { + //TODO implement me + panic("implement me") +} + +func (tnm *testNetworkManager) DeleteFingerprint(identity *id.ID, fingerprint format.Fingerprint) { + //TODO implement me + panic("implement me") +} + +func (tnm *testNetworkManager) DeleteClientService(clientID *id.ID) { + //TODO implement me + panic("implement me") +} + +func (tnm *testNetworkManager) TrackServices(tracker message.ServicesTracker) { + //TODO implement me + panic("implement me") +} + +func (tnm *testNetworkManager) WasHealthy() bool { + //TODO implement me + panic("implement me") +} + +func (tnm *testNetworkManager) AddHealthCallback(f func(bool)) uint64 { + //TODO implement me + panic("implement me") +} + +func (tnm *testNetworkManager) RemoveHealthCallback(u uint64) { + //TODO implement me + panic("implement me") +} + +func (tnm *testNetworkManager) HasNode(nid *id.ID) bool { + //TODO implement me + panic("implement me") +} + +func (tnm *testNetworkManager) NumRegisteredNodes() int { + //TODO implement me + panic("implement me") +} + +func (tnm *testNetworkManager) TriggerNodeRegistration(nid *id.ID) { + //TODO implement me + panic("implement me") +} + +func (tnm *testNetworkManager) GetRoundResults(timeout time.Duration, roundCallback cmix.RoundEventCallback, roundList ...id.Round) error { + //TODO implement me + panic("implement me") +} + +func (tnm *testNetworkManager) LookupHistoricalRound(rid id.Round, callback rounds.RoundResultCallback) error { + //TODO implement me + panic("implement me") +} + +func (tnm *testNetworkManager) SendToPreferred(targets []*id.ID, sendFunc gateway.SendToPreferredFunc, stop *stoppable.Single, timeout time.Duration) (interface{}, error) { + //TODO implement me + panic("implement me") +} + +func (tnm *testNetworkManager) SetGatewayFilter(f gateway.Filter) { + //TODO implement me + panic("implement me") +} + +func (tnm *testNetworkManager) GetHostParams() connect.HostParams { + //TODO implement me + panic("implement me") +} + +func (tnm *testNetworkManager) RegisterAddressSpaceNotification(tag string) (chan uint8, error) { + //TODO implement me + panic("implement me") +} + +func (tnm *testNetworkManager) UnregisterAddressSpaceNotification(tag string) { + //TODO implement me + panic("implement me") +} diff --git a/ud/registered.go b/ud/registered.go index 71eab2a4e71ede3019c866c261dd818e325ebdaa..41eb6ccd3ec04c3046462048232dafceb93a3412 100644 --- a/ud/registered.go +++ b/ud/registered.go @@ -14,7 +14,7 @@ const isRegisteredVersion = 0 // isRegistered loads from storage if the client is registered with user // discovery. func (m *Manager) isRegistered() bool { - _, err := m.kv.Get(isRegisteredKey, isRegisteredVersion) + _, err := m.getKv().Get(isRegisteredKey, isRegisteredVersion) if err != nil { return false } diff --git a/ud/remove.go b/ud/remove.go index 97fbc8a192bea01066632717029bd07a69167733..bdaf1e66e682035df6c2d35fccbc864d25622c8a 100644 --- a/ud/remove.go +++ b/ud/remove.go @@ -50,7 +50,7 @@ func (m *Manager) removeFact(f fact.Fact, if err != nil { return err } - stream := m.rng.GetStream() + stream := m.getRng().GetStream() defer stream.Close() fSig, err := rsa.Sign(stream, privKey, hash.CMixHash, fHash, nil) if err != nil { @@ -113,7 +113,7 @@ func (m *Manager) permanentDeleteAccount(f fact.Fact, myId *id.ID, privateKey *r fHash := factID.Fingerprint(f) // Sign our inFact for putting into the request - stream := m.rng.GetStream() + stream := m.getRng().GetStream() defer stream.Close() fsig, err := rsa.Sign(stream, privateKey, hash.CMixHash, fHash, nil) if err != nil { diff --git a/ud/search_test.go b/ud/search_test.go index 49d9cbf7905bed838a9607098f1c5cd427b42ec3..cb9f77bbd8b175fccb56c82093cbe8c536ac60f5 100644 --- a/ud/search_test.go +++ b/ud/search_test.go @@ -71,7 +71,7 @@ func TestManager_Search(t *testing.T) { CmixParams: cmix.GetDefaultCMIXParams(), } - _, _, err = Search(m.network, m.events, prng, m.e2e.GetE2E().GetGroup(), + _, _, err = Search(m.getCmix(), m.getEventReporter(), prng, m.e2e.GetE2E().GetGroup(), udContact, callback, factList, p) if err != nil { t.Fatalf("Search() returned an error: %+v", err) diff --git a/ud/utils_test.go b/ud/utils_test.go index 5c65cb48f3d36d4d1589eaba85f86b16cc8d9176..8c3016a8680085cddf9bdd732a182a3624edef1a 100644 --- a/ud/utils_test.go +++ b/ud/utils_test.go @@ -8,15 +8,12 @@ package ud import ( - "bytes" "github.com/golang/protobuf/proto" "gitlab.com/elixxir/client/cmix" "gitlab.com/elixxir/client/cmix/identity/receptionID" - "gitlab.com/elixxir/client/cmix/message" "gitlab.com/elixxir/client/cmix/rounds" "gitlab.com/elixxir/client/event" "gitlab.com/elixxir/client/single" - "gitlab.com/elixxir/client/stoppable" "gitlab.com/elixxir/client/storage/user" "gitlab.com/elixxir/client/storage/versioned" store "gitlab.com/elixxir/client/ud/store" @@ -24,11 +21,9 @@ import ( "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/crypto/fastRNG" "gitlab.com/elixxir/ekv" - "gitlab.com/elixxir/primitives/format" "gitlab.com/xx_network/crypto/csprng" "gitlab.com/xx_network/crypto/large" "gitlab.com/xx_network/crypto/signature/rsa" - "gitlab.com/xx_network/primitives/id/ephemeral" "io" "math/rand" "testing" @@ -61,22 +56,22 @@ func newTestManager(t *testing.T) (*Manager, *testNetworkManager) { stream.Close() // Create our Manager object + tnm := newTestNetworkManager(t) m := &Manager{ e2e: mockE2e{ - grp: getGroup(), - t: t, - key: privKey, + grp: getGroup(), + events: event.NewEventManager(), + rng: rngGen, + kv: kv, + network: tnm, + t: t, + key: privKey, }, - events: event.NewEventManager(), - store: udStore, - comms: &mockComms{}, - rng: rngGen, - kv: kv, + store: udStore, + comms: &mockComms{}, } - tnm := newTestNetworkManager(t) - m.network = tnm - netDef := m.network.GetInstance().GetPartialNdf().Get() + netDef := m.getCmix().GetInstance().GetPartialNdf().Get() // Unmarshal UD ID from the NDF udID, err := id.Unmarshal(netDef.UDB.ID) if err != nil { @@ -225,107 +220,6 @@ func (receiver *mockReceiver) Callback(req *single.Request, } -// testNetworkManager is a mock implementation of the CMix interface. -type testNetworkManager struct { - requestProcess message.Processor - instance *network.Instance - testingFace interface{} - c contact.Contact - responseProcessor message.Processor -} - -func (tnm *testNetworkManager) Send(recipient *id.ID, fingerprint format.Fingerprint, - service message.Service, - payload, mac []byte, cmixParams cmix.CMIXParams) (id.Round, ephemeral.Id, error) { - msg := format.NewMessage(tnm.instance.GetE2EGroup().GetP().ByteLen()) - // Build message. Will panic if inputs are not correct. - msg.SetKeyFP(fingerprint) - msg.SetContents(payload) - msg.SetMac(mac) - msg.SetSIH(service.Hash(msg.GetContents())) - // If the recipient for a call to Send is UD, then this - // is the request pathway. Call the UD processor to simulate - // the UD picking up the request - if bytes.Equal(tnm.instance.GetFullNdf(). - Get().UDB.ID, - recipient.Bytes()) { - tnm.responseProcessor.Process(msg, receptionID.EphemeralIdentity{}, rounds.Round{}) - - } else { - // This should happen when the mock UD service Sends back a response. - // Calling process mocks up the requester picking up the response. - tnm.requestProcess.Process(msg, receptionID.EphemeralIdentity{}, rounds.Round{}) - } - - return 0, ephemeral.Id{}, nil -} - -func (tnm *testNetworkManager) AddFingerprint(identity *id.ID, - fingerprint format.Fingerprint, mp message.Processor) error { - // AddFingerprint gets called in both the request and response - // code-paths. We only want to set in the code-path transmitting - // from UD - if !bytes.Equal(tnm.instance.GetFullNdf().Get().UDB.ID, - identity.Bytes()) { - tnm.requestProcess = mp - } - - return nil -} - -func (tnm *testNetworkManager) AddService(clientID *id.ID, - newService message.Service, - response message.Processor) { - tnm.responseProcessor = response - return -} - -func (tnm *testNetworkManager) CheckInProgressMessages() { - return -} - -func (tnm *testNetworkManager) GetMaxMessageLength() int { - return 700 -} - -func (tnm *testNetworkManager) AddIdentity(id *id.ID, validUntil time.Time, persistent bool) { - return -} - -func (tnm *testNetworkManager) DeleteClientFingerprints(identity *id.ID) { - return -} - -func (tnm *testNetworkManager) Process(ecrMsg format.Message, - receptionID receptionID.EphemeralIdentity, round rounds.Round) { - -} - -func (tnm *testNetworkManager) String() string { - return "mockPRocessor" -} - -func (tnm *testNetworkManager) DeleteService(clientID *id.ID, toDelete message.Service, processor message.Processor) { - return -} - -func (tnm *testNetworkManager) IsHealthy() bool { - return true -} - -func (tnm *testNetworkManager) SendToAny(sendFunc func(host *connect.Host) (interface{}, error), stop *stoppable.Single) (interface{}, error) { - //TODO implement me - panic("implement me") -} - -func (tnm *testNetworkManager) GetAddressSpace() uint8 { - return 8 -} - -func (tnm *testNetworkManager) GetInstance() *network.Instance { - return tnm.instance -} - type mockReporter struct{} func (m mockReporter) Report(priority int, category, evtType, details string) {