diff --git a/groupChat/manager.go b/groupChat/manager.go index c5ec117c76ae0903487c7c6b7d015294bb616e33..c67aae9bcb9c677d05709634ae8aca95e000d95e 100644 --- a/groupChat/manager.go +++ b/groupChat/manager.go @@ -8,18 +8,25 @@ package groupChat import ( + "github.com/cloudflare/circl/dh/sidh" "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/catalog" "gitlab.com/elixxir/client/cmix" "gitlab.com/elixxir/client/cmix/message" "gitlab.com/elixxir/client/e2e" + "gitlab.com/elixxir/client/e2e/ratchet/partner" + "gitlab.com/elixxir/client/e2e/ratchet/partner/session" + "gitlab.com/elixxir/client/e2e/receive" gs "gitlab.com/elixxir/client/groupChat/groupStore" "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/crypto/cyclic" + crypto "gitlab.com/elixxir/crypto/e2e" "gitlab.com/elixxir/crypto/fastRNG" "gitlab.com/elixxir/crypto/group" "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/id/ephemeral" + "time" ) // Error messages. @@ -29,22 +36,50 @@ const ( leaveGroupErr = "failed to leave group %s: %+v" ) +// GroupCmix is a subset of the cmix.Client interface containing only the methods needed by GroupChat +type GroupCmix interface { + SendMany(messages []cmix.TargetedCmixMessage, p cmix.CMIXParams) ( + id.Round, []ephemeral.Id, error) + AddService(clientID *id.ID, newService message.Service, + response message.Processor) + DeleteService(clientID *id.ID, toDelete message.Service, + processor message.Processor) +} + +// GroupE2e is a subset of the e2e.Handler interface containing only the methods needed by GroupChat +type GroupE2e interface { + SendE2E(mt catalog.MessageType, recipient *id.ID, payload []byte, + params e2e.Params) ([]id.Round, crypto.MessageID, time.Time, error) + RegisterListener(senderID *id.ID, + messageType catalog.MessageType, + newListener receive.Listener) receive.ListenerID + AddService(tag string, processor message.Processor) error + AddPartner(partnerID *id.ID, + partnerPubKey, myPrivKey *cyclic.Int, + partnerSIDHPubKey *sidh.PublicKey, + mySIDHPrivKey *sidh.PrivateKey, sendParams, + receiveParams session.Params) (partner.Manager, error) + GetPartner(partnerID *id.ID) (partner.Manager, error) + GetHistoricalDHPubkey() *cyclic.Int + GetHistoricalDHPrivkey() *cyclic.Int +} + // Manager handles the list of groups a user is a part of. type Manager struct { - e2e e2e.Handler + e2e GroupE2e receptionId *id.ID rng *fastRNG.StreamGenerator grp *cyclic.Group gs *gs.Store - services cmix.Client + services GroupCmix requestFunc RequestCallback receiveFunc ReceiveCallback } // NewManager creates a new group chat manager -func NewManager(services cmix.Client, e2e e2e.Handler, receptionId *id.ID, +func NewManager(services GroupCmix, e2e GroupE2e, receptionId *id.ID, rng *fastRNG.StreamGenerator, grp *cyclic.Group, kv *versioned.KV, requestFunc RequestCallback, receiveFunc ReceiveCallback) (*Manager, error) { diff --git a/groupChat/receive.go b/groupChat/receive.go index 8555fafa98e39a73565a6c1c4975e3d83004f803..b559a0b0d4776cd70425f86c0744b3b6eac2b5f4 100644 --- a/groupChat/receive.go +++ b/groupChat/receive.go @@ -10,8 +10,8 @@ package groupChat import ( "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" - "gitlab.com/elixxir/client/cmix/rounds" "gitlab.com/elixxir/client/cmix/identity/receptionID" + "gitlab.com/elixxir/client/cmix/rounds" gs "gitlab.com/elixxir/client/groupChat/groupStore" "gitlab.com/elixxir/crypto/group" "gitlab.com/elixxir/primitives/format" @@ -25,7 +25,6 @@ const ( unmarshalInternalMsgErr = "failed to unmarshal group internal message: %+v" unmarshalSenderIdErr = "failed to unmarshal sender ID: %+v" unmarshalPublicMsgErr = "failed to unmarshal group cMix message contents: %+v" - findGroupKeyFpErr = "no group with key fingerprint %s" genCryptKeyMacErr = "failed to generate encryption key for group " + "cMix message because MAC verification failed (epoch %d could be off)" ) diff --git a/groupChat/utils_test.go b/groupChat/utils_test.go index e8e4ee7d84f271a980d5894ca0c46906914e55b8..4854e56500b3964a01628475f8e9a17d69a86264 100644 --- a/groupChat/utils_test.go +++ b/groupChat/utils_test.go @@ -13,19 +13,14 @@ import ( "github.com/pkg/errors" "gitlab.com/elixxir/client/catalog" "gitlab.com/elixxir/client/cmix" - "gitlab.com/elixxir/client/cmix/gateway" - "gitlab.com/elixxir/client/cmix/identity" "gitlab.com/elixxir/client/cmix/message" - "gitlab.com/elixxir/client/cmix/rounds" clientE2E "gitlab.com/elixxir/client/e2e" "gitlab.com/elixxir/client/e2e/ratchet/partner" "gitlab.com/elixxir/client/e2e/ratchet/partner/session" "gitlab.com/elixxir/client/e2e/receive" "gitlab.com/elixxir/client/event" gs "gitlab.com/elixxir/client/groupChat/groupStore" - "gitlab.com/elixxir/client/stoppable" "gitlab.com/elixxir/client/storage/versioned" - net "gitlab.com/elixxir/comms/network" "gitlab.com/elixxir/crypto/contact" "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/crypto/e2e" @@ -33,7 +28,6 @@ import ( "gitlab.com/elixxir/crypto/group" "gitlab.com/elixxir/ekv" "gitlab.com/elixxir/primitives/format" - "gitlab.com/xx_network/comms/connect" "gitlab.com/xx_network/crypto/csprng" "gitlab.com/xx_network/crypto/large" "gitlab.com/xx_network/primitives/id" @@ -221,7 +215,7 @@ func getGroup() *cyclic.Group { large.NewIntFromString(getNDF().E2E.Generator, 16)) } -func newTestNetworkManager(sendErr int, t *testing.T) cmix.Client { +func newTestNetworkManager(sendErr int, t *testing.T) GroupCmix { return &testNetworkManager{ receptionMessages: [][]format.Message{}, sendMessages: [][]cmix.TargetedCmixMessage{}, @@ -242,7 +236,8 @@ type testE2eMessage struct { Payload []byte } -func (tnm *testE2eManager) AddPartner(partnerID *id.ID, partnerPubKey, myPrivKey *cyclic.Int, partnerSIDHPubKey *sidh.PublicKey, mySIDHPrivKey *sidh.PrivateKey, sendParams, receiveParams session.Params) (partner.Manager, error) { +func (tnm *testE2eManager) AddPartner(partnerID *id.ID, partnerPubKey, myPrivKey *cyclic.Int, + partnerSIDHPubKey *sidh.PublicKey, mySIDHPrivKey *sidh.PrivateKey, sendParams, receiveParams session.Params) (partner.Manager, error) { return nil, nil } @@ -250,14 +245,6 @@ func (tnm *testE2eManager) GetPartner(partnerID *id.ID) (partner.Manager, error) return nil, nil } -func (tnm *testE2eManager) DeletePartner(partnerId *id.ID) error { - panic("implement me") -} - -func (tnm *testE2eManager) GetAllPartnerIDs() []*id.ID { - panic("implement me") -} - func (tnm *testE2eManager) GetHistoricalDHPubkey() *cyclic.Int { panic("implement me") } @@ -266,173 +253,6 @@ func (tnm *testE2eManager) GetHistoricalDHPrivkey() *cyclic.Int { panic("implement me") } -func (tnm *testE2eManager) GetReceptionID() *id.ID { - panic("implement me") -} - -// testNetworkManager is a test implementation of NetworkManager interface. -type testNetworkManager struct { - receptionMessages [][]format.Message - sendMessages [][]cmix.TargetedCmixMessage - errSkip int - sendErr int - sync.RWMutex -} - -func (tnm *testNetworkManager) Send(recipient *id.ID, fingerprint format.Fingerprint, service message.Service, payload, mac []byte, cmixParams cmix.CMIXParams) (id.Round, ephemeral.Id, error) { - panic("implement me") -} - -func (tnm *testNetworkManager) SendMany(messages []cmix.TargetedCmixMessage, p cmix.CMIXParams) (id.Round, []ephemeral.Id, error) { - if tnm.sendErr == 1 { - return 0, nil, errors.New("SendManyCMIX error") - } - - tnm.Lock() - defer tnm.Unlock() - - tnm.sendMessages = append(tnm.sendMessages, messages) - - receiveMessages := []format.Message{} - for _, msg := range messages { - receiveMsg := format.Message{} - receiveMsg.SetMac(msg.Mac) - receiveMsg.SetContents(msg.Payload) - receiveMsg.SetKeyFP(msg.Fingerprint) - receiveMessages = append(receiveMessages, receiveMsg) - } - tnm.receptionMessages = append(tnm.receptionMessages, receiveMessages) - return 0, nil, nil -} - -func (tnm *testNetworkManager) GetIdentity(get *id.ID) (identity.TrackedID, error) { - panic("implement me") -} - -func (tnm *testNetworkManager) GetInstance() *net.Instance { - panic("implement me") -} - -func (tnm *testNetworkManager) GetVerboseRounds() string { - panic("implement me") -} - -func (*testNetworkManager) Follow(report cmix.ClientErrorReport) (stoppable.Stoppable, error) { - panic("implement me") -} - -func (*testNetworkManager) GetMaxMessageLength() int { - panic("implement me") -} - -func (*testNetworkManager) AddIdentity(id *id.ID, validUntil time.Time, persistent bool) { - panic("implement me") -} - -func (*testNetworkManager) RemoveIdentity(id *id.ID) { - panic("implement me") -} - -func (*testNetworkManager) AddFingerprint(identity *id.ID, fingerprint format.Fingerprint, mp message.Processor) error { - panic("implement me") -} - -func (*testNetworkManager) DeleteFingerprint(identity *id.ID, fingerprint format.Fingerprint) { - panic("implement me") -} - -func (*testNetworkManager) DeleteClientFingerprints(identity *id.ID) { - panic("implement me") -} - -func (*testNetworkManager) AddService(clientID *id.ID, newService message.Service, response message.Processor) { - panic("implement me") -} - -func (*testNetworkManager) DeleteService(clientID *id.ID, toDelete message.Service, processor message.Processor) { - panic("implement me") -} - -func (*testNetworkManager) DeleteClientService(clientID *id.ID) { - panic("implement me") -} - -func (*testNetworkManager) TrackServices(tracker message.ServicesTracker) { - panic("implement me") -} - -func (*testNetworkManager) CheckInProgressMessages() { - panic("implement me") -} - -func (*testNetworkManager) IsHealthy() bool { - panic("implement me") -} - -func (*testNetworkManager) WasHealthy() bool { - panic("implement me") -} - -func (*testNetworkManager) AddHealthCallback(f func(bool)) uint64 { - panic("implement me") -} - -func (*testNetworkManager) RemoveHealthCallback(u uint64) { - panic("implement me") -} - -func (*testNetworkManager) HasNode(nid *id.ID) bool { - panic("implement me") -} - -func (*testNetworkManager) NumRegisteredNodes() int { - panic("implement me") -} - -func (*testNetworkManager) TriggerNodeRegistration(nid *id.ID) { - panic("implement me") -} - -func (*testNetworkManager) GetRoundResults(timeout time.Duration, roundCallback cmix.RoundEventCallback, roundList ...id.Round) error { - panic("implement me") -} - -func (*testNetworkManager) LookupHistoricalRound(rid id.Round, callback rounds.RoundResultCallback) error { - panic("implement me") -} - -func (*testNetworkManager) SendToAny(sendFunc func(host *connect.Host) (interface{}, error), stop *stoppable.Single) (interface{}, error) { - panic("implement me") -} - -func (*testNetworkManager) SendToPreferred(targets []*id.ID, sendFunc gateway.SendToPreferredFunc, stop *stoppable.Single, timeout time.Duration) (interface{}, error) { - panic("implement me") -} - -func (*testNetworkManager) SetGatewayFilter(f gateway.Filter) { - panic("implement me") -} - -func (*testNetworkManager) GetHostParams() connect.HostParams { - panic("implement me") -} - -func (*testNetworkManager) GetAddressSpace() uint8 { - panic("implement me") -} - -func (*testNetworkManager) RegisterAddressSpaceNotification(tag string) (chan uint8, error) { - panic("implement me") -} - -func (*testNetworkManager) UnregisterAddressSpaceNotification(tag string) { - panic("implement me") -} - -func (*testE2eManager) StartProcesses() (stoppable.Stoppable, error) { - panic("implement me") -} - func (tnm *testE2eManager) SendE2E(mt catalog.MessageType, recipient *id.ID, payload []byte, params clientE2E.Params) ([]id.Round, e2e.MessageID, time.Time, error) { tnm.Lock() defer tnm.Unlock() @@ -456,56 +276,63 @@ func (*testE2eManager) RegisterListener(user *id.ID, messageType catalog.Message panic("implement me") } -func (*testE2eManager) RegisterFunc(name string, user *id.ID, messageType catalog.MessageType, newListener receive.ListenerFunc) receive.ListenerID { +func (*testE2eManager) AddService(tag string, processor message.Processor) error { panic("implement me") } -func (*testE2eManager) RegisterChannel(name string, user *id.ID, messageType catalog.MessageType, newListener chan receive.Message) receive.ListenerID { +func (*testE2eManager) GetDefaultHistoricalDHPubkey() *cyclic.Int { panic("implement me") } -func (*testE2eManager) Unregister(listenerID receive.ListenerID) { +func (*testE2eManager) GetDefaultHistoricalDHPrivkey() *cyclic.Int { panic("implement me") } -func (*testE2eManager) AddService(tag string, processor message.Processor) error { - panic("implement me") +func (tnm *testE2eManager) GetE2eMsg(i int) testE2eMessage { + tnm.RLock() + defer tnm.RUnlock() + return tnm.e2eMessages[i] } -func (*testE2eManager) RemoveService(tag string) error { - panic("implement me") +// testNetworkManager is a test implementation of NetworkManager interface. +type testNetworkManager struct { + receptionMessages [][]format.Message + sendMessages [][]cmix.TargetedCmixMessage + errSkip int + sendErr int + sync.RWMutex } -func (*testE2eManager) SendUnsafe(mt catalog.MessageType, recipient *id.ID, payload []byte, params clientE2E.Params) ([]id.Round, time.Time, error) { - panic("implement me") -} +func (tnm *testNetworkManager) SendMany(messages []cmix.TargetedCmixMessage, p cmix.CMIXParams) (id.Round, []ephemeral.Id, error) { + if tnm.sendErr == 1 { + return 0, nil, errors.New("SendManyCMIX error") + } -func (*testE2eManager) EnableUnsafeReception() { - panic("implement me") -} + tnm.Lock() + defer tnm.Unlock() -func (*testE2eManager) GetGroup() *cyclic.Group { - panic("implement me") -} + tnm.sendMessages = append(tnm.sendMessages, messages) -func (*testE2eManager) GetDefaultHistoricalDHPubkey() *cyclic.Int { - panic("implement me") + receiveMessages := []format.Message{} + for _, msg := range messages { + receiveMsg := format.Message{} + receiveMsg.SetMac(msg.Mac) + receiveMsg.SetContents(msg.Payload) + receiveMsg.SetKeyFP(msg.Fingerprint) + receiveMessages = append(receiveMessages, receiveMsg) + } + tnm.receptionMessages = append(tnm.receptionMessages, receiveMessages) + return 0, nil, nil } -func (*testE2eManager) GetDefaultHistoricalDHPrivkey() *cyclic.Int { +func (*testNetworkManager) AddService(clientID *id.ID, newService message.Service, response message.Processor) { panic("implement me") } -func (*testE2eManager) GetDefaultID() *id.ID { +func (*testNetworkManager) DeleteService(clientID *id.ID, toDelete message.Service, processor message.Processor) { panic("implement me") } -func (tnm *testE2eManager) GetE2eMsg(i int) testE2eMessage { - tnm.RLock() - defer tnm.RUnlock() - return tnm.e2eMessages[i] -} - type dummyEventMgr struct{} func (d *dummyEventMgr) Report(int, string, string, string) {}