diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 5d5bbe80f56f1e601b59d1c2d15b1ee269e36c0a..4a344591818545dcf0ebccf75d15fe54874d8ee4 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -90,7 +90,7 @@ bindings-ios: - go get golang.org/x/mobile/bind - go install golang.org/x/mobile/cmd/gomobile@latest - gomobile init - - gomobile bind -target ios gitlab.com/elixxir/client/bindings + - gomobile bind -target ios,iossimulator,macos gitlab.com/elixxir/client/bindings - ls - zip -r iOS.zip Bindings.xcframework artifacts: diff --git a/auth/callbacks.go b/auth/callbacks.go index 273ff6b0b7af5b36ff53d44e265ebaeaab0183cd..787f15a0068c3e7a2547e8438785b45a8b461689 100644 --- a/auth/callbacks.go +++ b/auth/callbacks.go @@ -1,7 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2022 Privategrity Corporation / -// / -// All rights reserved. / +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package auth diff --git a/auth/confirm.go b/auth/confirm.go index 05c1bc136ac567749d1115b7e13d1c7091da1a6b..0b7278c6e1f08b8535384d729b95c46eba650b04 100644 --- a/auth/confirm.go +++ b/auth/confirm.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package auth @@ -132,7 +132,7 @@ func (s *state) confirm(partner contact.Contact, serviceTag string) ( /*send message*/ if err = s.store.StoreConfirmation(partner.ID, baseFmt.Marshal(), - mac, fp); err == nil { + mac, fp); err != nil { jww.WARN.Printf("Failed to store confirmation for replay "+ "for relationship between %s and %s, cannot be replayed: %+v", partner.ID, s.e2e.GetReceptionID(), err) @@ -171,8 +171,8 @@ func sendAuthConfirm(net cmixClient, partner *id.ID, } em := fmt.Sprintf("Confirm Request with %s (msgDigest: %s) sent on round %d", - partner, format.DigestContents(payload), sentRound) + partner, format.DigestContents(payload), sentRound.ID) jww.INFO.Print(em) event.Report(1, "Auth", "SendConfirm", em) - return sentRound, nil + return sentRound.ID, nil } diff --git a/auth/fmt.go b/auth/fmt.go index 6ec925c7efd8be0cbd1b48ff09b1766e0080bd03..6318b7474a0fe91c22fedbfd9ef2cc91c8a8d729 100644 --- a/auth/fmt.go +++ b/auth/fmt.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package auth diff --git a/auth/fmt_test.go b/auth/fmt_test.go index 59e63cba01f78904fa594947a40726b26492ff5d..0c045402062f0d4f7d3bda1ab2723aa5a9be6abd 100644 --- a/auth/fmt_test.go +++ b/auth/fmt_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package auth diff --git a/auth/interface.go b/auth/interface.go index b45ba36e9c7d4a135a0f7adf48416b1e1cbf1112..c515973886b9387d3442ee6f134aa47a428bb0ea 100644 --- a/auth/interface.go +++ b/auth/interface.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package auth import ( @@ -134,7 +141,7 @@ type cmixClient interface { DeleteFingerprint(identity *id.ID, fingerprint format.Fingerprint) Send(recipient *id.ID, fingerprint format.Fingerprint, service message.Service, payload, mac []byte, cmixParams cmix.CMIXParams) ( - id.Round, ephemeral.Id, error) + rounds.Round, ephemeral.Id, error) } // e2eHandler is a sub-interface of e2e.Handler containing diff --git a/auth/params.go b/auth/params.go index 907fa4ad825c3c6ef068d9dc7e6cd8b92d70a773..01fa5ba810e108dc72407fd0e0bf90bccbf54904 100644 --- a/auth/params.go +++ b/auth/params.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package auth import ( diff --git a/auth/receivedConfirm.go b/auth/receivedConfirm.go index ad30186d15c911dbc739495ccf58df4bdcf05818..0b1109cd9410fe19b75cc891cb7eac9604ed4da9 100644 --- a/auth/receivedConfirm.go +++ b/auth/receivedConfirm.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package auth import ( diff --git a/auth/receivedRequest.go b/auth/receivedRequest.go index 4e3325996a6ca5c558d3531a019c68c92f026bf3..e94b82598ad12a5bb2b24246074f9936040b6d04 100644 --- a/auth/receivedRequest.go +++ b/auth/receivedRequest.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package auth import ( diff --git a/auth/replayConfirm.go b/auth/replayConfirm.go index 09540fe298680ffbc1a2bfba522306b22bd8f781..4581479061d173f0327d42bdd5129c4fa67147bc 100644 --- a/auth/replayConfirm.go +++ b/auth/replayConfirm.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package auth import "gitlab.com/xx_network/primitives/id" diff --git a/auth/request.go b/auth/request.go index d37385815b55d2f6b1e87fabc5e1f167bb704360..17db1b2f64572d73a7601e606d72fa1d2fb5c2b1 100644 --- a/auth/request.go +++ b/auth/request.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package auth @@ -82,6 +82,11 @@ func (s *state) request(partner contact.Contact, myfacts fact.FactList, historicalDHPub := diffieHellman.GeneratePublicKey(historicalDHPriv, dhGrp) + if !dhGrp.Inside(partner.DhPubKey.GetLargeInt()) { + return 0, errors.Errorf("partner's DH public key is not in the E2E "+ + "group; E2E group fingerprint is %d and DH key has %d", + dhGrp.GetFingerprint(), partner.DhPubKey.GetGroupFingerprint()) + } ownership := cAuth.MakeOwnershipProof(historicalDHPriv, partner.DhPubKey, dhGrp) confirmFp := cAuth.MakeOwnershipProofFP(ownership) @@ -159,10 +164,10 @@ func (s *state) request(partner contact.Contact, myfacts fact.FactList, } em := fmt.Sprintf("Auth Request with %s (msgDigest: %s) sent"+ - " on round %d", partner.ID, format.DigestContents(contents), round) + " on round %d", partner.ID, format.DigestContents(contents), round.ID) jww.INFO.Print(em) s.event.Report(1, "Auth", "RequestSent", em) - return round, nil + return round.ID, nil } diff --git a/auth/reset.go b/auth/reset.go index 9f6114f466534efc6e27d2382d6caa71abb726f3..5521a6089ced2c8bb59ab4d599119cfdabaa06d7 100644 --- a/auth/reset.go +++ b/auth/reset.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package auth import ( diff --git a/auth/sentRequestHandler.go b/auth/sentRequestHandler.go index 5d336b90a31fb0b4d2f1fc62429442ec6065d37f..f0e40fffb5f2fe47f68252dbbb9dc3cac3349642 100644 --- a/auth/sentRequestHandler.go +++ b/auth/sentRequestHandler.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package auth import ( diff --git a/auth/state.go b/auth/state.go index e226a01e7bdf0cf2575e6f3d0ed13983ef38c0f7..a18baa7656ba4db4b812372f561732b3de172788 100644 --- a/auth/state.go +++ b/auth/state.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package auth diff --git a/auth/state_test.go b/auth/state_test.go index 34b670453b4a5052d71868ebeccd4d8030f1a511..5dc12aca17520550e4857647e40c32bed212fcc4 100644 --- a/auth/state_test.go +++ b/auth/state_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package auth @@ -69,8 +69,8 @@ func (mnm *mockNetManager) AddFingerprint(identity *id.ID, fingerprint format.Fi func (mnm *mockNetManager) DeleteFingerprint(identity *id.ID, fingerprint format.Fingerprint) {} func (mnm *mockNetManager) Send(recipient *id.ID, fingerprint format.Fingerprint, service message.Service, payload, mac []byte, cmixParams cmix.CMIXParams) ( - id.Round, ephemeral.Id, error) { - return id.Round(5), ephemeral.Id{}, nil + rounds.Round, ephemeral.Id, error) { + return rounds.Round{ID: 5}, ephemeral.Id{}, nil } type mockE2E struct { diff --git a/auth/store/confirmation.go b/auth/store/confirmation.go index c972fd8af974060824eaa735a9f6a371a56b12a8..a7619fb3bfea265e1790cd0c1dc3cb6d4c5964a9 100644 --- a/auth/store/confirmation.go +++ b/auth/store/confirmation.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package store @@ -48,8 +48,7 @@ func (s *Store) StoreConfirmation(partner *id.ID, Data: confirmBytes, } - return s.kv.Set(makeConfirmationKey(partner), - currentConfirmationVersion, obj) + return s.kv.Set(makeConfirmationKey(partner), obj) } // LoadConfirmation loads the confirmation for the given partner and fingerprint diff --git a/auth/store/confirmation_test.go b/auth/store/confirmation_test.go index 2bc188cd4429cf1ff27f5166dbbfc1c4457a13d5..570aeb0aa4077129ca429a7b8d27f0ae36c2ba32 100644 --- a/auth/store/confirmation_test.go +++ b/auth/store/confirmation_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package store diff --git a/auth/store/deletion.go b/auth/store/deletion.go index d5fb746a72fa9f02466a9ebe7a73da3b86499616..0da70d1d114530f78c9072d5bf7774ada489c056 100644 --- a/auth/store/deletion.go +++ b/auth/store/deletion.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package store import ( diff --git a/auth/store/fingerprint.go b/auth/store/fingerprint.go index 3a99453a985f02f86e0e54636cd55b1249dfebbc..4f0d71429c53d33c19efdf4037e7ad1e4a4594b5 100644 --- a/auth/store/fingerprint.go +++ b/auth/store/fingerprint.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package store diff --git a/auth/store/previousNegotiations.go b/auth/store/previousNegotiations.go index be8d701f082ef99de72cd67f9a1d4c0b01b6bd9f..6bc8931d78827ade1af9df355288ee761ca497d7 100644 --- a/auth/store/previousNegotiations.go +++ b/auth/store/previousNegotiations.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package store @@ -16,7 +16,6 @@ import ( jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/crypto/e2e/auth" - "gitlab.com/elixxir/ekv" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/netTime" ) @@ -112,7 +111,7 @@ func (s *Store) savePreviousNegotiations() error { Data: marshalPreviousNegotiations(s.previousNegotiations), } - return s.kv.Set(negotiationPartnersKey, negotiationPartnersVersion, obj) + return s.kv.Set(negotiationPartnersKey, obj) } // newOrLoadPreviousNegotiations loads the list of previousNegotiations partners @@ -122,7 +121,7 @@ func (s *Store) newOrLoadPreviousNegotiations() (map[id.ID]bool, error) { obj, err := s.kv.Get(negotiationPartnersKey, negotiationPartnersVersion) // V0 Upgrade Path - if !ekv.Exists(err) { + if !s.kv.Exists(err) { upgradeErr := upgradePreviousNegotiationsV0(s.kv) if upgradeErr != nil { return nil, errors.Wrapf(err, "%+v", upgradeErr) @@ -132,7 +131,7 @@ func (s *Store) newOrLoadPreviousNegotiations() (map[id.ID]bool, error) { } // Note: if it still doesn't exist, return an empty one. - if err != nil && !ekv.Exists(err) { + if err != nil && !s.kv.Exists(err) { newPreviousNegotiations := make(map[id.ID]bool) return newPreviousNegotiations, nil } else if err != nil { @@ -188,8 +187,7 @@ func saveNegotiationFingerprints( Data: marshalNegotiationFingerprints(fingerprints...), } - return kv.Set(makeNegotiationFingerprintsKey(partner), - currentNegotiationFingerprintsVersion, obj) + return kv.Set(makeNegotiationFingerprintsKey(partner), obj) } // loadNegotiationFingerprints loads the list of sentByFingerprints for the given @@ -272,7 +270,7 @@ func unmarshalPreviousNegotiationsV0(buf []byte) map[id.ID]struct{} { // to V1 func upgradePreviousNegotiationsV0(kv *versioned.KV) error { obj, err := kv.Get(negotiationPartnersKey, 0) - if !ekv.Exists(err) { + if !kv.Exists(err) { return nil } @@ -287,5 +285,5 @@ func upgradePreviousNegotiationsV0(kv *versioned.KV) error { Data: marshalPreviousNegotiations( newPrevNegotiations), } - return kv.Set(negotiationPartnersKey, negotiationPartnersVersion, obj) + return kv.Set(negotiationPartnersKey, obj) } diff --git a/auth/store/previousNegotiations_test.go b/auth/store/previousNegotiations_test.go index 2d8234a45adf372b5883eb7bade2714f6574619a..e99414f7f5a8fb271e90941a78796da84df3fbe5 100644 --- a/auth/store/previousNegotiations_test.go +++ b/auth/store/previousNegotiations_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package store diff --git a/auth/store/receivedRequest.go b/auth/store/receivedRequest.go index 4bb0c5216a6abd2b48d7fdc779c493d5a69b6597..63b338269f666f816b7d40e65db21417e7331b83 100644 --- a/auth/store/receivedRequest.go +++ b/auth/store/receivedRequest.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package store import ( @@ -10,7 +17,6 @@ import ( util "gitlab.com/elixxir/client/storage/utility" "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/crypto/contact" - "gitlab.com/elixxir/ekv" "gitlab.com/xx_network/primitives/id" ) @@ -27,7 +33,7 @@ type ReceivedRequest struct { round rounds.Round //lock to make sure only one operator at a time - mux *sync.Mutex + mux sync.Mutex } func newReceivedRequest(kv *versioned.KV, c contact.Contact, @@ -54,7 +60,6 @@ func newReceivedRequest(kv *versioned.KV, c contact.Contact, partner: c, theirSidHPubKeyA: key, round: round, - mux: &sync.Mutex{}, } } @@ -77,11 +82,11 @@ func loadReceivedRequest(kv *versioned.KV, partner *id.ID) ( } round, err := rounds.LoadRound(kv, makeRoundKey(partner)) - if err != nil && ekv.Exists(err) { + if err != nil && kv.Exists(err) { return nil, errors.WithMessagef(err, "Failed to Load "+ "round request was received on with %s", partner) - } else if err != nil && !ekv.Exists(err) { + } else if err != nil && !kv.Exists(err) { jww.WARN.Printf("No round info for partner %s", partner) } diff --git a/auth/store/request.go b/auth/store/request.go index 0678d9c5c220c29f88c49aa286dfd592454a95be..88c721fdd09b23c20e6bfd3b1922ec5518fd0b98 100644 --- a/auth/store/request.go +++ b/auth/store/request.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package store diff --git a/auth/store/sentRequest.go b/auth/store/sentRequest.go index 5f5b8a69e1e193ada63726e1f24c31e03a37973c..7b0283766b9b0359157261bb327a263f0e627ab2 100644 --- a/auth/store/sentRequest.go +++ b/auth/store/sentRequest.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package store @@ -19,7 +19,6 @@ import ( sidhinterface "gitlab.com/elixxir/client/interfaces/sidh" "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/crypto/cyclic" - "gitlab.com/elixxir/ekv" "gitlab.com/elixxir/primitives/format" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/netTime" @@ -77,7 +76,7 @@ func loadSentRequest(kv *versioned.KV, partner *id.ID, grp *cyclic.Group) (*Sent obj, err := kv.Get(srKey, currentSentRequestVersion) // V0 Upgrade Path - if !ekv.Exists(err) { + if !kv.Exists(err) { upgradeErr := upgradeSentRequestKeyV0(kv, partner) if upgradeErr != nil { return nil, errors.Wrapf(err, "%+v", upgradeErr) @@ -211,8 +210,7 @@ func (sr *SentRequest) save() error { Data: data, } - return sr.kv.Set(makeSentRequestKey(sr.partner), - currentSentRequestVersion, &obj) + return sr.kv.Set(makeSentRequestKey(sr.partner), &obj) } func (sr *SentRequest) delete() { @@ -296,7 +294,7 @@ func upgradeSentRequestKeyV0(kv *versioned.KV, partner *id.ID) error { // Note: uses same encoding, just different keys obj.Version = 1 - err = kv.Set(makeSentRequestKey(partner), 1, obj) + err = kv.Set(makeSentRequestKey(partner), obj) if err != nil { return err } diff --git a/auth/store/sentRequestHandler.go b/auth/store/sentRequestHandler.go index 4a8afac3ea867ea5eb2570f978ba6ff88be0f663..e0466210679b3f83d9256f528b9b309702c3629d 100644 --- a/auth/store/sentRequestHandler.go +++ b/auth/store/sentRequestHandler.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package store // SentRequestHandler allows the lower level to assign and remove services diff --git a/auth/store/store.go b/auth/store/store.go index e5496b2d7c88751b36250f814f397ba9ae97bcef..5a42a0aa9cf2d356c62a4d23189746c16ef90349 100644 --- a/auth/store/store.go +++ b/auth/store/store.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package store @@ -23,8 +23,6 @@ import ( "gitlab.com/xx_network/primitives/netTime" ) -const NoRequest = "Request Not Found" - const storePrefix = "requestMap" const requestMapKey = "map" @@ -149,7 +147,7 @@ func (s *Store) save() error { Data: data, } - return s.kv.Set(requestMapKey, requestMapVersion, &obj) + return s.kv.Set(requestMapKey, &obj) } // NewStore creates a new store. All passed in private keys are added as @@ -268,16 +266,15 @@ func (s *Store) HandleReceivedRequest(partner *id.ID, handler func(*ReceivedRequ //run the handler handleErr := handler(rr) - if handleErr != nil { return errors.WithMessage(handleErr, "Received error from handler") } delete(s.receivedByID, *partner) - s.save() + err := s.save() rr.delete() - return nil + return err } // HandleSentRequest handles the request singly, only a single operator @@ -311,16 +308,15 @@ func (s *Store) HandleSentRequest(partner *id.ID, handler func(request *SentRequ //run the handler handleErr := handler(sr) - if handleErr != nil { return errors.WithMessage(handleErr, "Received error from handler") } delete(s.sentByID, *partner) - s.save() + err := s.save() sr.delete() - return nil + return err } // GetReceivedRequest returns the contact representing the partner request diff --git a/auth/store/store_test.go b/auth/store/store_test.go index 4c88064c04acebb62281c108d69eeb66caac5182..acd6156c50ddca150e755826e8481fbb91c3d5f2 100644 --- a/auth/store/store_test.go +++ b/auth/store/store_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package store @@ -277,7 +277,7 @@ func TestStore_GetReceivedRequest_RequestDeleted(t *testing.T) { } // Check if the request's mutex is locked - if reflect.ValueOf(rr.mux).Elem().FieldByName("state").Int() != 0 { + if reflect.ValueOf(&rr.mux).Elem().FieldByName("state").Int() != 0 { t.Errorf("GetReceivedRequest() did not unlock mutex.") } } diff --git a/auth/utils_test.go b/auth/utils_test.go index 5f27a218e0651736ace0ca165ef44e0ef581b05d..aa4689e7ae5bc74d38470e8179fd79b1a43fac68 100644 --- a/auth/utils_test.go +++ b/auth/utils_test.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package auth import ( @@ -61,9 +68,8 @@ func (m mockE2eHandler) StartProcesses() (stoppable.Stoppable, error) { } func (m mockE2eHandler) SendE2E(mt catalog.MessageType, recipient *id.ID, - payload []byte, params e2e.Params) ([]id.Round, cryptoE2e.MessageID, - time.Time, error) { - return nil, cryptoE2e.MessageID{}, time.Time{}, nil + payload []byte, params e2e.Params) (cryptoE2e.SendReport, error) { + return cryptoE2e.SendReport{}, nil } func (m mockE2eHandler) RegisterListener(senderID *id.ID, diff --git a/auth/verify.go b/auth/verify.go index f86aad68db374043efbb41ffb9c19048d172598c..d9a3259ecbf68067e07df6bac5dd3892a0113fb0 100644 --- a/auth/verify.go +++ b/auth/verify.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package auth diff --git a/auth/verify_test.go b/auth/verify_test.go index 9f2a34642e241b870fa55d337c3bcf24efe519b5..81515c9732579ba7578082ee6e8b1325bc199d7f 100644 --- a/auth/verify_test.go +++ b/auth/verify_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package auth diff --git a/backup/backup.go b/backup/backup.go index c6debb0888faf7f4499a060d16f2f1fae09a2082..d4cc92a408a48cd809b30a93f25bb9ea93b02e59 100644 --- a/backup/backup.go +++ b/backup/backup.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package backup diff --git a/backup/backupRestore.go b/backup/backupRestore.go index c0a4e3ecc37c5b2ba99816d0b05c297b70884e19..6be4fd04620c011b8d3c318471e4aef04d86b700 100644 --- a/backup/backupRestore.go +++ b/backup/backupRestore.go @@ -1,7 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2022 Privategrity Corporation / -// / -// All rights reserved. / +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package backup diff --git a/backup/backup_test.go b/backup/backup_test.go index bcaf8cf35bb4c7d0044cbf7e2a79e445e0d9c207..900ed84ec9abfe99389f19b1d26a369048f6daae 100644 --- a/backup/backup_test.go +++ b/backup/backup_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package backup @@ -11,7 +11,6 @@ import ( "bytes" "gitlab.com/elixxir/client/xxdk" "reflect" - "strings" "testing" "time" @@ -151,7 +150,7 @@ func Test_resumeBackup_NoKeyError(t *testing.T) { rngGen := fastRNG.NewStreamGenerator(1000, 10, csprng.NewSystemRNG) _, err := ResumeBackup(nil, &xxdk.Container{}, newMockE2e(t), newMockSession(t), newMockUserDiscovery(), s.GetKV(), rngGen) - if err == nil || !strings.Contains(err.Error(), expectedErr) { + if err == nil || s.GetKV().Exists(err) { t.Errorf("ResumeBackup did not return the expected error when no "+ "password is present.\nexpected: %s\nreceived: %+v", expectedErr, err) } diff --git a/backup/jsonStorage.go b/backup/jsonStorage.go index 8ce778b56aff9c76847caf1953451d7cb6b39d5d..3e7b889f6bc2fc43ddbf14a95e01c325f39425f5 100644 --- a/backup/jsonStorage.go +++ b/backup/jsonStorage.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package backup import ( @@ -17,7 +24,7 @@ func storeJson(json string, kv *versioned.KV) error { Data: []byte(json), } - return kv.Set(jsonStorageKey, jsonStorageVersion, obj) + return kv.Set(jsonStorageKey, obj) } func loadJson(kv *versioned.KV) string { diff --git a/backup/jsonStorage_test.go b/backup/jsonStorage_test.go index 352f6d2d6e595fe8a6fe49da48deda570cee647c..a5eb3d2bb06ef942612fcc6b2c86992e2c9adad0 100644 --- a/backup/jsonStorage_test.go +++ b/backup/jsonStorage_test.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package backup import ( diff --git a/backup/keyStorage.go b/backup/keyStorage.go index 27437998775dc4a63cf4e3c996dd82f3aa68e56c..f3164957954fe1eddb24fe5eaf69133484d1b550 100644 --- a/backup/keyStorage.go +++ b/backup/keyStorage.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package backup @@ -38,7 +38,7 @@ func saveBackup(key, salt []byte, params backup.Params, kv *versioned.KV) error Data: marshalBackup(key, salt, params), } - return kv.Set(cryptoStorageKey, cryptoStorageVersion, obj) + return kv.Set(cryptoStorageKey, obj) } // loadBackup loads the key, salt, and params from storage. diff --git a/backup/utils_test.go b/backup/utils_test.go index 9a1d03976d8df5e71cfb7d87d1e5e32ce775caf8..beecea4a4c9c94fcd21acc78ced939ef919ab143 100644 --- a/backup/utils_test.go +++ b/backup/utils_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package backup diff --git a/bindings/authenticatedConnection.go b/bindings/authenticatedConnection.go index 33aac039b7bea7ff91e5f021103e22442bc615ba..70ef4cf4921658b45223a9b7f254c1c1c029b67b 100644 --- a/bindings/authenticatedConnection.go +++ b/bindings/authenticatedConnection.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package bindings @@ -34,7 +34,6 @@ func (_ *AuthenticatedConnection) IsAuthenticated() bool { // ConnectWithAuthentication is called by the client (i.e., the one establishing // connection with the server). Once a connect.Connection has been established // with the server, it then authenticates their identity to the server. -// accepts a marshalled ReceptionIdentity and contact.Contact object func (c *Cmix) ConnectWithAuthentication(e2eId int, recipientContact, e2eParamsJSON []byte) (*AuthenticatedConnection, error) { if len(e2eParamsJSON) == 0 { diff --git a/bindings/backup.go b/bindings/backup.go index 2c5c24560184fe5d1f121e05b8df5de98ce1fc23..50aaf5c29fb0aed49682fb582e158fb698ee9b9d 100644 --- a/bindings/backup.go +++ b/bindings/backup.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package bindings @@ -55,7 +55,7 @@ type UpdateBackupFunc interface { // backup. Users of this function should delete the storage directory on error. // Users of this function should call LoadCmix as normal once this call succeeds. // -// Params +// Parameters: // - ndfJSON - JSON of the NDF. // - storageDir - directory for the storage files. // - sessionPassword - password to decrypt the data in the storageDir. @@ -92,10 +92,11 @@ func NewCmixFromBackup(ndfJSON, storageDir, backupPassphrase string, // InitializeBackup creates a bindings-layer Backup object. // -// Params +// Parameters: // - e2eID - ID of the E2e object in the e2e tracker. // - udID - ID of the UserDiscovery object in the ud tracker. -// - backupPassPhrase - backup passphrase provided by the user. Used to decrypt backup. +// - backupPassPhrase - backup passphrase provided by the user. Used to decrypt +// backup. // - cb - the callback to be called when a backup is triggered. func InitializeBackup(e2eID, udID int, backupPassPhrase string, cb UpdateBackupFunc) (*Backup, error) { @@ -129,7 +130,7 @@ func InitializeBackup(e2eID, udID int, backupPassPhrase string, // To start the backup for the first time or to use a new password, use // InitializeBackup. // -// Params +// Parameters: // - e2eID - ID of the E2e object in the e2e tracker. // - udID - ID of the UserDiscovery object in the ud tracker. // - cb - the callback to be called when a backup is triggered. diff --git a/bindings/broadcast.go b/bindings/broadcast.go deleted file mode 100644 index 62cce68bc271509b19f92aa4c44dac6f2c9ff7d9..0000000000000000000000000000000000000000 --- a/bindings/broadcast.go +++ /dev/null @@ -1,199 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2022 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// - -package bindings - -import ( - "encoding/json" - "github.com/pkg/errors" - "gitlab.com/elixxir/client/broadcast" - "gitlab.com/elixxir/client/cmix" - "gitlab.com/elixxir/client/cmix/identity/receptionID" - "gitlab.com/elixxir/client/cmix/rounds" - cryptoBroadcast "gitlab.com/elixxir/crypto/broadcast" - "gitlab.com/xx_network/crypto/signature/rsa" - "gitlab.com/xx_network/primitives/id/ephemeral" -) - -// Channel is a bindings-level struct encapsulating the broadcast.Channel client object. -type Channel struct { - ch broadcast.Channel -} - -// ChannelDef is the bindings representation of an elixxir/crypto broadcast.Channel object. -// -// Example JSON: -// {"Name": "My broadcast channel", -// "Description":"A broadcast channel for me to test things", -// "Salt":"gpUqW7N22sffMXsvPLE7BA==", -// "PubKey":"LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1DZ0NJUUN2YkZVckJKRFpqT3Y0Y0MvUHZZdXNvQkFtUTFkb3Znb044aHRuUjA2T3F3SURBUUFCCi0tLS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS0=" -// } -type ChannelDef struct { - Name string - Description string - Salt []byte - PubKey []byte -} - -// BroadcastMessage is the bindings representation of a broadcast message. -// -// Example JSON: -// {"RoundID":42, -// "EphID":[0,0,0,0,0,0,24,61], -// "Payload":"SGVsbG8sIGJyb2FkY2FzdCBmcmllbmRzIQ==" -// } -type BroadcastMessage struct { - BroadcastReport - Payload []byte -} - -// BroadcastReport is the bindings representation of the info on how a broadcast message was sent -// -// Example JSON: -// {"RoundID":42, -// "EphID":[0,0,0,0,0,0,24,61] -// } -type BroadcastReport struct { - RoundsList - EphID ephemeral.Id -} - -// BroadcastListener is the public function type bindings can use to listen for -// broadcast messages. -// -// Parameters: -// - []byte - the JSON marshalled bytes of the BroadcastMessage object, which -// can be passed into WaitForRoundResult to see if the broadcast succeeded. -type BroadcastListener interface { - Callback([]byte, error) -} - -// NewBroadcastChannel creates a bindings-layer broadcast channel & starts listening for new messages -// -// Parameters: -// - cmixId - internal ID of cmix -// - channelDefinition - JSON marshalled ChannelDef object -func NewBroadcastChannel(cmixId int, channelDefinition []byte) (*Channel, error) { - c, err := cmixTrackerSingleton.get(cmixId) - if err != nil { - return nil, err - } - - def := &ChannelDef{} - err = json.Unmarshal(channelDefinition, def) - if err != nil { - return nil, errors.WithMessage(err, "Failed to unmarshal underlying channel definition") - } - - channelID, err := cryptoBroadcast.NewChannelID(def.Name, def.Description, def.Salt, def.PubKey) - if err != nil { - return nil, errors.WithMessage(err, "Failed to generate channel ID") - } - chanPubLoaded, err := rsa.LoadPublicKeyFromPem(def.PubKey) - if err != nil { - return nil, errors.WithMessage(err, "Failed to load public key") - } - - ch, err := broadcast.NewBroadcastChannel(cryptoBroadcast.Channel{ - ReceptionID: channelID, - Name: def.Name, - Description: def.Description, - Salt: def.Salt, - RsaPubKey: chanPubLoaded, - }, c.api.GetCmix(), c.api.GetRng()) - if err != nil { - return nil, errors.WithMessage(err, "Failed to create broadcast channel client") - } - - return &Channel{ch: ch}, nil -} - -// Listen registers a BroadcastListener for a given method. -// This allows users to handle incoming broadcast messages. -// -// Parameters: -// - l - BroadcastListener object -// - method - int corresponding to broadcast.Method constant, 0 for symmetric -// or 1 for asymmetric -func (c *Channel) Listen(l BroadcastListener, method int) error { - broadcastMethod := broadcast.Method(method) - listen := func(payload []byte, - receptionID receptionID.EphemeralIdentity, round rounds.Round) { - l.Callback(json.Marshal(&BroadcastMessage{ - BroadcastReport: BroadcastReport{ - RoundsList: makeRoundsList(round.ID), - EphID: receptionID.EphId, - }, - Payload: payload, - })) - } - return c.ch.RegisterListener(listen, broadcastMethod) -} - -// Broadcast sends a given payload over the broadcast channel using symmetric -// broadcast. -// -// Returns: -// - []byte - the JSON marshalled bytes of the BroadcastReport object, which -// can be passed into WaitForRoundResult to see if the broadcast succeeded. -func (c *Channel) Broadcast(payload []byte) ([]byte, error) { - rid, eid, err := c.ch.Broadcast(payload, cmix.GetDefaultCMIXParams()) - if err != nil { - return nil, err - } - return json.Marshal(BroadcastReport{ - RoundsList: makeRoundsList(rid), - EphID: eid, - }) -} - -// BroadcastAsymmetric sends a given payload over the broadcast channel using -// asymmetric broadcast. This mode of encryption requires a private key. -// -// Returns: -// - []byte - the JSON marshalled bytes of the BroadcastReport object, which -// can be passed into WaitForRoundResult to see if the broadcast succeeded. -func (c *Channel) BroadcastAsymmetric(payload, pk []byte) ([]byte, error) { - pkLoaded, err := rsa.LoadPrivateKeyFromPem(pk) - if err != nil { - return nil, err - } - rid, eid, err := c.ch.BroadcastAsymmetric(pkLoaded, payload, cmix.GetDefaultCMIXParams()) - if err != nil { - return nil, err - } - return json.Marshal(BroadcastReport{ - RoundsList: makeRoundsList(rid), - EphID: eid, - }) -} - -// MaxPayloadSize returns the maximum possible payload size which can be broadcast. -func (c *Channel) MaxPayloadSize() int { - return c.ch.MaxPayloadSize() -} - -// MaxAsymmetricPayloadSize returns the maximum possible payload size which can be broadcast. -func (c *Channel) MaxAsymmetricPayloadSize() int { - return c.ch.MaxAsymmetricPayloadSize() -} - -// Get returns the result of calling json.Marshal on a ChannelDef based on the underlying crypto broadcast.Channel. -func (c *Channel) Get() ([]byte, error) { - def := c.ch.Get() - return json.Marshal(&ChannelDef{ - Name: def.Name, - Description: def.Description, - Salt: def.Salt, - PubKey: rsa.CreatePublicKeyPem(def.RsaPubKey), - }) -} - -// Stop stops the channel from listening for more messages. -func (c *Channel) Stop() { - c.ch.Stop() -} diff --git a/bindings/broadcast_test.go b/bindings/broadcast_test.go deleted file mode 100644 index 5c12dff82a86193ab99cc839d57dc5d94ce93c1a..0000000000000000000000000000000000000000 --- a/bindings/broadcast_test.go +++ /dev/null @@ -1,68 +0,0 @@ -package bindings - -import ( - "encoding/json" - "gitlab.com/elixxir/crypto/cmix" - "gitlab.com/xx_network/crypto/csprng" - "gitlab.com/xx_network/crypto/signature/rsa" - "gitlab.com/xx_network/primitives/id" - "gitlab.com/xx_network/primitives/id/ephemeral" - "testing" - "time" -) - -func TestChannelDef_JSON(t *testing.T) { - rng := csprng.NewSystemRNG() - rng.SetSeed([]byte("rng")) - pk, _ := rsa.GenerateKey(rng, 256) - cd := ChannelDef{ - Name: "My broadcast channel", - Description: "A broadcast channel for me to test things", - Salt: cmix.NewSalt(rng, 16), - PubKey: rsa.CreatePublicKeyPem(pk.GetPublic()), - } - - cdJson, err := json.Marshal(cd) - if err != nil { - t.Errorf("Failed to marshal channel def: %+v", err) - } - t.Log(string(cdJson)) -} - -func TestBroadcastMessage_JSON(t *testing.T) { - uid := id.NewIdFromString("zezima", id.User, t) - eid, _, _, err := ephemeral.GetId(uid, 16, time.Now().UnixNano()) - if err != nil { - t.Errorf("Failed to form ephemeral ID: %+v", err) - } - bm := BroadcastMessage{ - BroadcastReport: BroadcastReport{ - RoundsList: makeRoundsList(42), - EphID: eid, - }, - Payload: []byte("Hello, broadcast friends!"), - } - bmJson, err := json.Marshal(bm) - if err != nil { - t.Errorf("Failed to marshal broadcast message: %+v", err) - } - t.Log(string(bmJson)) -} - -func TestBroadcastReport_JSON(t *testing.T) { - uid := id.NewIdFromString("zezima", id.User, t) - eid, _, _, err := ephemeral.GetId(uid, 16, time.Now().UnixNano()) - if err != nil { - t.Errorf("Failed to form ephemeral ID: %+v", err) - } - br := BroadcastReport{ - RoundsList: makeRoundsList(42), - EphID: eid, - } - - brJson, err := json.Marshal(br) - if err != nil { - t.Errorf("Failed to marshal broadcast report: %+v", err) - } - t.Log(string(brJson)) -} diff --git a/bindings/channels.go b/bindings/channels.go new file mode 100644 index 0000000000000000000000000000000000000000..78525cf20f8a7a9afe0773f65868b443a5e6d4a0 --- /dev/null +++ b/bindings/channels.go @@ -0,0 +1,1160 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx network SEZC // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file // +/////////////////////////////////////////////////////////////////////////////// + +package bindings + +import ( + "encoding/json" + "github.com/pkg/errors" + jww "github.com/spf13/jwalterweatherman" + "gitlab.com/elixxir/client/channels" + "gitlab.com/elixxir/client/cmix/rounds" + "gitlab.com/elixxir/client/xxdk" + cryptoBroadcast "gitlab.com/elixxir/crypto/broadcast" + cryptoChannel "gitlab.com/elixxir/crypto/channel" + "gitlab.com/elixxir/crypto/rsa" + "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/id/ephemeral" + "sync" + "time" +) + +//////////////////////////////////////////////////////////////////////////////// +// Singleton Tracker // +//////////////////////////////////////////////////////////////////////////////// + +// channelManagerTrackerSingleton is used to track ChannelsManager objects +// so that they can be referenced by ID back over the bindings. +var channelManagerTrackerSingleton = &channelManagerTracker{ + tracked: make(map[int]*ChannelsManager), + count: 0, +} + +// channelManagerTracker is a singleton used to keep track of extant +// ChannelsManager objects, preventing race conditions created by passing it +// over the bindings. +type channelManagerTracker struct { + tracked map[int]*ChannelsManager + count int + mux sync.RWMutex +} + +// make create a ChannelsManager from an [channels.Manager], assigns it a unique +// ID, and adds it to the channelManagerTracker. +func (cmt *channelManagerTracker) make(c channels.Manager) *ChannelsManager { + cmt.mux.Lock() + defer cmt.mux.Unlock() + + chID := cmt.count + cmt.count++ + + cmt.tracked[chID] = &ChannelsManager{ + api: c, + id: chID, + } + + return cmt.tracked[chID] +} + +// get an ChannelsManager from the channelManagerTracker given its ID. +func (cmt *channelManagerTracker) get(id int) (*ChannelsManager, error) { + cmt.mux.RLock() + defer cmt.mux.RUnlock() + + c, exist := cmt.tracked[id] + if !exist { + return nil, errors.Errorf( + "Cannot get ChannelsManager for ID %d, does not exist", id) + } + + return c, nil +} + +// delete removes a ChannelsManager from the channelManagerTracker. +func (cmt *channelManagerTracker) delete(id int) { + cmt.mux.Lock() + defer cmt.mux.Unlock() + + delete(cmt.tracked, id) +} + +//////////////////////////////////////////////////////////////////////////////// +// Basic Channel API // +//////////////////////////////////////////////////////////////////////////////// + +// ChannelsManager is a bindings-layer struct that wraps a [channels.Manager] +// interface. +type ChannelsManager struct { + api channels.Manager + id int +} + +// GetID returns the channelManagerTracker ID for the ChannelsManager object. +func (cm *ChannelsManager) GetID() int { + return cm.id +} + +// GenerateChannelIdentity creates a new private channel identity +// ([channel.PrivateIdentity]). The public component can be retrieved as JSON +// via [GetPublicChannelIdentityFromPrivate]. +// +// Parameters: +// - cmixID - The tracked cmix object ID. This can be retrieved using +// [Cmix.GetID]. +// +// Returns: +// - JSON of [channel.PrivateIdentity]. +func GenerateChannelIdentity(cmixID int) ([]byte, error) { + // Get user from singleton + user, err := cmixTrackerSingleton.get(cmixID) + if err != nil { + return nil, err + } + + rng := user.api.GetRng().GetStream() + defer rng.Close() + pi, err := cryptoChannel.GenerateIdentity(rng) + if err != nil { + return nil, err + } + return pi.Marshal(), nil +} + +// GetPublicChannelIdentity constructs a public identity ([channel.Identity]) +// from a bytes version and returns it JSON marshaled. +// +// Parameters: +// - marshaledPublic - Bytes of the public identity ([channel.Identity]). +// +// Returns: +// - JSON of the constructed [channel.Identity]. +func GetPublicChannelIdentity(marshaledPublic []byte) ([]byte, error) { + i, err := cryptoChannel.UnmarshalIdentity(marshaledPublic) + if err != nil { + return nil, err + } + return json.Marshal(&i) +} + +// GetPublicChannelIdentityFromPrivate returns the public identity +// ([channel.Identity]) contained in the given private identity +// ([channel.PrivateIdentity]). +// +// Parameters: +// - marshaledPrivate - Bytes of the private identity +// (channel.PrivateIdentity]). +// +// Returns: +// - JSON of the public [channel.Identity]. +func GetPublicChannelIdentityFromPrivate(marshaledPrivate []byte) ([]byte, error) { + pi, err := cryptoChannel.UnmarshalPrivateIdentity(marshaledPrivate) + if err != nil { + return nil, err + } + return json.Marshal(&pi.Identity) +} + +// NewChannelsManagerGoEventModel creates a new [ChannelsManager] from a new +// private identity ([channel.PrivateIdentity]). This is not compatible with +// GoMobile Bindings because it receives the go event model. +// +// This is for creating a manager for an identity for the first time. For +// generating a new one channel identity, use [GenerateChannelIdentity]. To +// reload this channel manager, use [LoadChannelsManagerGoEventModel], passing +// in the storage tag retrieved by [ChannelsManager.GetStorageTag]. +// +// Parameters: +// - cmixID - The tracked Cmix object ID. This can be retrieved using +// [Cmix.GetID]. +// - privateIdentity - Bytes of a private identity ([channel.PrivateIdentity]) +// that is generated by [GenerateChannelIdentity]. +// - goEvent - A function that initialises and returns the event model that is +// not compatible with GoMobile bindings. +func NewChannelsManagerGoEventModel(cmixID int, privateIdentity []byte, + goEventBuilder channels.EventModelBuilder) (*ChannelsManager, error) { + pi, err := cryptoChannel.UnmarshalPrivateIdentity(privateIdentity) + if err != nil { + return nil, err + } + + // Get user from singleton + user, err := cmixTrackerSingleton.get(cmixID) + if err != nil { + return nil, err + } + + // Construct new channels manager + m, err := channels.NewManager(pi, user.api.GetStorage().GetKV(), + user.api.GetCmix(), user.api.GetRng(), goEventBuilder) + if err != nil { + return nil, err + } + + // Add channel to singleton and return + return channelManagerTrackerSingleton.make(m), nil +} + +// LoadChannelsManagerGoEventModel loads an existing ChannelsManager. This is not +// compatible with GoMobile Bindings because it receives the go event model. +// This is for creating a manager for an identity for the first time. +// The channel manager should have first been created with +// NewChannelsManagerGoEventModel and then the storage tag can be retrieved +// with ChannelsManager.GetStorageTag +// +// Parameters: +// - cmixID - The tracked cmix object ID. This can be retrieved using +// [Cmix.GetID]. +// - storageTag - retrieved with ChannelsManager.GetStorageTag +// - goEvent - A function that initialises and returns the event model that is +// not compatible with GoMobile bindings. +func LoadChannelsManagerGoEventModel(cmixID int, storageTag string, + goEventBuilder channels.EventModelBuilder) (*ChannelsManager, error) { + + // Get user from singleton + user, err := cmixTrackerSingleton.get(cmixID) + if err != nil { + return nil, err + } + + // Construct new channels manager + m, err := channels.LoadManager(storageTag, user.api.GetStorage().GetKV(), + user.api.GetCmix(), user.api.GetRng(), goEventBuilder) + if err != nil { + return nil, err + } + + // Add channel to singleton and return + return channelManagerTrackerSingleton.make(m), nil +} + +// NewChannelsManager creates a new [ChannelsManager] from a new private +// identity ([channel.PrivateIdentity]). +// +// This is for creating a manager for an identity for the first time. For +// generating a new one channel identity, use [GenerateChannelIdentity]. To +// reload this channel manager, use [LoadChannelsManager], passing in the +// storage tag retrieved by [ChannelsManager.GetStorageTag]. +// +// Parameters: +// - cmixID - The tracked Cmix object ID. This can be retrieved using +// [Cmix.GetID]. +// - privateIdentity - Bytes of a private identity ([channel.PrivateIdentity]) +// that is generated by [GenerateChannelIdentity]. +// - event - An interface that contains a function that initialises and returns +// the event model that is bindings-compatible. +func NewChannelsManager(cmixID int, privateIdentity []byte, + eventBuilder EventModelBuilder) (*ChannelsManager, error) { + pi, err := cryptoChannel.UnmarshalPrivateIdentity(privateIdentity) + if err != nil { + return nil, err + } + + // Get user from singleton + user, err := cmixTrackerSingleton.get(cmixID) + if err != nil { + return nil, err + } + + eb := func(path string) (channels.EventModel, error) { + return NewEventModel(eventBuilder.Build(path)), nil + } + + // Construct new channels manager + m, err := channels.NewManager(pi, user.api.GetStorage().GetKV(), + user.api.GetCmix(), user.api.GetRng(), eb) + if err != nil { + return nil, err + } + + // Add channel to singleton and return + return channelManagerTrackerSingleton.make(m), nil +} + +// LoadChannelsManager loads an existing [ChannelsManager]. +// +// This is for loading a manager for an identity that has already been created. +// The channel manager should have previously been created with +// [NewChannelsManager] and the storage is retrievable with +// [ChannelsManager.GetStorageTag]. +// +// Parameters: +// - cmixID - The tracked cmix object ID. This can be retrieved using +// [Cmix.GetID]. +// - storageTag - The storage tag associated with the previously created +// channel manager and retrieved with [ChannelsManager.GetStorageTag]. +// - event - An interface that contains a function that initialises and returns +// the event model that is bindings-compatible. +func LoadChannelsManager(cmixID int, storageTag string, + eventBuilder EventModelBuilder) (*ChannelsManager, error) { + + // Get user from singleton + user, err := cmixTrackerSingleton.get(cmixID) + if err != nil { + return nil, err + } + + eb := func(path string) (channels.EventModel, error) { + return NewEventModel(eventBuilder.Build(path)), nil + } + + // Construct new channels manager + m, err := channels.LoadManager(storageTag, user.api.GetStorage().GetKV(), + user.api.GetCmix(), user.api.GetRng(), eb) + if err != nil { + return nil, err + } + + // Add channel to singleton and return + return channelManagerTrackerSingleton.make(m), nil +} + +type ChannelGeneration struct { + Channel string + PrivateKey string +} + +// GenerateChannel is used to create a channel a new channel of which you are +// the admin. It is only for making new channels, not joining existing ones. +// +// It returns a pretty print of the channel and the private key. +// +// The name cannot be longer that __ characters. The description cannot be +// longer than __ and can only use ______ characters. +// +// Parameters: +// - cmixID - The tracked cmix object ID. This can be retrieved using +// [Cmix.GetID]. +// - name - The name of the new channel. The name cannot be longer than __ +// characters and must contain only _____ characters. It cannot be changed +// once a channel is created. +// - description - The description of a channel. The description cannot be +// longer than __ characters and must contain only _____ characters. It +// cannot be changed once a channel is created. +// +// Returns: +// - []byte - ChannelGeneration describes a generated channel. It contains both +// the public channel info and the private key for the channel in PEM format. +// fixme: document json +func GenerateChannel(cmixID int, name, description string) ([]byte, error) { + // Get cmix from singleton so its rng can be used + cmix, err := cmixTrackerSingleton.get(cmixID) + if err != nil { + return nil, err + } + + stream := cmix.api.GetRng().GetStream() + defer stream.Close() + c, pk, err := cryptoBroadcast.NewChannel( + name, description, cmix.api.GetCmix().GetMaxMessageLength(), stream) + if err != nil { + return nil, err + } + + gen := ChannelGeneration{ + Channel: c.PrettyPrint(), + PrivateKey: string(pk.MarshalPem()), + } + + return json.Marshal(&gen) +} + +type ChannelInfo struct { + Name string + Description string + ChannelID string +} + +// GetChannelInfo returns the info about a channel from its public description. +// +// Parameters: +// - prettyPrint - The pretty print of the channel. +// +// The pretty print will be of the format: +// <XXChannel-v1:Test Channel,description:This is a test channel,secrets:pn0kIs6P1pHvAe7u8kUyf33GYVKmkoCX9LhCtvKJZQI=,3A5eB5pzSHyxN09w1kOVrTIEr5UyBbzmmd9Ga5Dx0XA=,0,0,/zChIlLr2p3Vsm2X4+3TiFapoapaTi8EJIisJSqwfGc=> +// +// Returns: +// - []byte - ChannelInfo describes all relevant channel info. +// fixme: document json +func GetChannelInfo(prettyPrint string) ([]byte, error) { + _, bytes, err := getChannelInfo(prettyPrint) + return bytes, err +} + +func getChannelInfo(prettyPrint string) (*cryptoBroadcast.Channel, []byte, error) { + c, err := cryptoBroadcast.NewChannelFromPrettyPrint(prettyPrint) + if err != nil { + return nil, nil, err + } + ci := &ChannelInfo{ + Name: c.Name, + Description: c.Description, + ChannelID: c.ReceptionID.String(), + } + bytes, err := json.Marshal(ci) + if err != nil { + return nil, nil, err + } + return c, bytes, nil +} + +// JoinChannel joins the given channel. It will fail if the channel has already +// been joined. +// +// Parameters: +// - channelPretty - A portable channel string. Should be received from +// another user or generated via GenerateChannel. +// +// The pretty print will be of the format: +// <XXChannel-v1:Test Channel,description:This is a test channel,secrets:pn0kIs6P1pHvAe7u8kUyf33GYVKmkoCX9LhCtvKJZQI=,3A5eB5pzSHyxN09w1kOVrTIEr5UyBbzmmd9Ga5Dx0XA=,0,0,/zChIlLr2p3Vsm2X4+3TiFapoapaTi8EJIisJSqwfGc=>" +// +// Returns: +// - []byte - ChannelInfo describes all relevant channel info. +// fixme: document json +func (cm *ChannelsManager) JoinChannel(channelPretty string) ([]byte, error) { + c, info, err := getChannelInfo(channelPretty) + if err != nil { + return nil, err + } + + // Join the channel using the API + err = cm.api.JoinChannel(c) + + return info, err +} + +// GetChannels returns the IDs of all channels that have been joined. +// +// Returns: +// - []byte - A JSON marshalled list of IDs. +// +// JSON Example: +// { +// "U4x/lrFkvxuXu59LtHLon1sUhPJSCcnZND6SugndnVID", +// "15tNdkKbYXoMn58NO6VbDMDWFEyIhTWEGsvgcJsHWAgD" +// } +func (cm *ChannelsManager) GetChannels() ([]byte, error) { + channelIds := cm.api.GetChannels() + return json.Marshal(channelIds) +} + +// LeaveChannel leaves the given channel. It will return an error if the +// channel was not previously joined. +// +// Parameters: +// - marshalledChanId - A JSON marshalled channel ID ([id.ID]). +func (cm *ChannelsManager) LeaveChannel(marshalledChanId []byte) error { + // Unmarshal channel ID + channelId, err := id.Unmarshal(marshalledChanId) + if err != nil { + return err + } + + // Leave the channel + return cm.api.LeaveChannel(channelId) +} + +// ReplayChannel replays all messages from the channel within the network's +// memory (~3 weeks) over the event model. +// +// Parameters: +// - marshalledChanId - A JSON marshalled channel ID ([id.ID]). +func (cm *ChannelsManager) ReplayChannel(marshalledChanId []byte) error { + + // Unmarshal channel ID + chanId, err := id.Unmarshal(marshalledChanId) + if err != nil { + return err + } + + // Replay channel + return cm.api.ReplayChannel(chanId) +} + +//////////////////////////////////////////////////////////////////////////////// +// Channel Sending Methods & Reports // +//////////////////////////////////////////////////////////////////////////////// + +// ChannelSendReport is the bindings' representation of the return values of +// ChannelsManager's Send operations. +// +// JSON Example: +// { +// "MessageId": "0kitNxoFdsF4q1VMSI/xPzfCnGB2l+ln2+7CTHjHbJw=", +// "Rounds":[1,5,9], +// "EphId": 0 +// } +type ChannelSendReport struct { + MessageId []byte + RoundsList + EphId int64 +} + +// SendGeneric is used to send a raw message over a channel. In general, it +// should be wrapped in a function that defines the wire protocol. If the final +// message, before being sent over the wire, is too long, this will return an +// error. Due to the underlying encoding using compression, it isn't possible to +// define the largest payload that can be sent, but it will always be possible +// to send a payload of 802 bytes at minimum. The meaning of validUntil depends +// on the use case. +// +// Parameters: +// - marshalledChanId - A JSON marshalled channel ID ([id.ID]). +// - messageType - The message type of the message. This will be a valid +// [channels.MessageType]. +// - message - The contents of the message. This need not be of data type +// string, as the message could be a specified format that the channel may +// recognize. +// - leaseTimeMS - The lease of the message. This will be how long the message +// is valid until, in milliseconds. As per the channels.Manager +// documentation, this has different meanings depending on the use case. +// These use cases may be generic enough that they will not be enumerated +// here. +// - cmixParamsJSON - A JSON marshalled [xxdk.CMIXParams]. This may be empty, +// and GetDefaultCMixParams will be used internally. +// +// Returns: +// - []byte - A JSON marshalled ChannelSendReport. +func (cm *ChannelsManager) SendGeneric(marshalledChanId []byte, + messageType int, message []byte, leaseTimeMS int64, + cmixParamsJSON []byte) ([]byte, error) { + + // Unmarshal channel ID and parameters + chanId, params, err := parseChannelsParameters( + marshalledChanId, cmixParamsJSON) + if err != nil { + return nil, err + } + + // Send message + chanMsgId, rnd, ephId, err := cm.api.SendGeneric(chanId, + channels.MessageType(messageType), message, + time.Duration(leaseTimeMS), params.CMIX) + if err != nil { + return nil, err + } + + // Construct send report + return constructChannelSendReport(chanMsgId, rnd.ID, ephId) +} + +// SendAdminGeneric is used to send a raw message over a channel encrypted with +// admin keys, identifying it as sent by the admin. In general, it should be +// wrapped in a function that defines the wire protocol. If the final message, +// before being sent over the wire, is too long, this will return an error. The +// message must be at most 510 bytes long. +// +// Parameters: +// - adminPrivateKey - The PEM-encoded admin RSA private key. +// - marshalledChanId - A JSON marshalled channel ID ([id.ID]). +// - messageType - The message type of the message. This will be a valid +// [channels.MessageType]. +// - message - The contents of the message. The message should be at most 510 +// bytes. This need not be of data type string, as the message could be a +// specified format that the channel may recognize. +// - leaseTimeMS - The lease of the message. This will be how long the message +// is valid until, in milliseconds. As per the channels.Manager +// documentation, this has different meanings depending on the use case. +// These use cases may be generic enough that they will not be enumerated +// here. +// - cmixParamsJSON - A JSON marshalled [xxdk.CMIXParams]. This may be empty, +// and GetDefaultCMixParams will be used internally. +// +// Returns: +// - []byte - A JSON marshalled ChannelSendReport. +func (cm *ChannelsManager) SendAdminGeneric(adminPrivateKey, + marshalledChanId []byte, + messageType int, message []byte, leaseTimeMS int64, + cmixParamsJSON []byte) ([]byte, error) { + + // Load private key from file + rsaPrivKey, err := rsa.GetScheme().UnmarshalPrivateKeyPEM(adminPrivateKey) + if err != nil { + return nil, err + } + + // Unmarshal channel ID and parameters + chanId, params, err := parseChannelsParameters( + marshalledChanId, cmixParamsJSON) + if err != nil { + return nil, err + } + + // Send admin message + chanMsgId, rnd, ephId, err := cm.api.SendAdminGeneric(rsaPrivKey, + chanId, channels.MessageType(messageType), message, + time.Duration(leaseTimeMS), params.CMIX) + + // Construct send report + return constructChannelSendReport(chanMsgId, rnd.ID, ephId) +} + +// SendMessage is used to send a formatted message over a channel. +// Due to the underlying encoding using compression, it isn't possible to define +// the largest payload that can be sent, but it will always be possible to send +// a payload of 798 bytes at minimum. +// +// The message will auto delete validUntil after the round it is sent in, +// lasting forever if [channels.ValidForever] is used. +// +// Parameters: +// - marshalledChanId - A JSON marshalled channel ID ([id.ID]). +// - message - The contents of the message. The message should be at most 510 +// bytes. This is expected to be Unicode, and thus a string data type is +// expected +// - leaseTimeMS - The lease of the message. This will be how long the message +// is valid until, in milliseconds. As per the channels.Manager +// documentation, this has different meanings depending on the use case. +// These use cases may be generic enough that they will not be enumerated +// here. +// - cmixParamsJSON - A JSON marshalled [xxdk.CMIXParams]. This may be +// empty, and GetDefaultCMixParams will be used internally. +// +// Returns: +// - []byte - A JSON marshalled ChannelSendReport +func (cm *ChannelsManager) SendMessage(marshalledChanId []byte, + message string, leaseTimeMS int64, cmixParamsJSON []byte) ([]byte, error) { + + // Unmarshal channel ID and parameters + chanId, params, err := parseChannelsParameters( + marshalledChanId, cmixParamsJSON) + if err != nil { + return nil, err + } + + // Send message + chanMsgId, rnd, ephId, err := cm.api.SendMessage(chanId, message, + time.Duration(leaseTimeMS), params.CMIX) + if err != nil { + return nil, err + } + + // Construct send report + return constructChannelSendReport(chanMsgId, rnd.ID, ephId) +} + +// SendReply is used to send a formatted message over a channel. Due to the +// underlying encoding using compression, it isn't possible to define the +// largest payload that can be sent, but it will always be possible to send a +// payload of 766 bytes at minimum. +// +// If the message ID the reply is sent to is nonexistent, the other side will +// post the message as a normal message and not a reply. The message will auto +// delete validUntil after the round it is sent in, lasting forever if +// [channels.ValidForever] is used. +// +// Parameters: +// - marshalledChanId - A JSON marshalled channel ID ([id.ID]). +// - message - The contents of the message. The message should be at most 510 +// bytes. This is expected to be Unicode, and thus a string data type is +// expected. +// - messageToReactTo - The marshalled [channel.MessageID] of the message you +// wish to reply to. This may be found in the ChannelSendReport if replying +// to your own. Alternatively, if reacting to another user's message, you may +// retrieve it via the ChannelMessageReceptionCallback registered using +// RegisterReceiveHandler. +// - leaseTimeMS - The lease of the message. This will be how long the message +// is valid until, in milliseconds. As per the channels.Manager +// documentation, this has different meanings depending on the use case. +// These use cases may be generic enough that they will not be enumerated +// here. +// - cmixParamsJSON - A JSON marshalled [xxdk.CMIXParams]. This may be empty, +// and GetDefaultCMixParams will be used internally. +// +// Returns: +// - []byte - A JSON marshalled ChannelSendReport +func (cm *ChannelsManager) SendReply(marshalledChanId []byte, + message string, messageToReactTo []byte, leaseTimeMS int64, + cmixParamsJSON []byte) ([]byte, error) { + + // Unmarshal channel ID and parameters + chanId, params, err := parseChannelsParameters( + marshalledChanId, cmixParamsJSON) + if err != nil { + return nil, err + } + + // Unmarshal message ID + msgId := cryptoChannel.MessageID{} + copy(msgId[:], messageToReactTo) + + // Send Reply + chanMsgId, rnd, ephId, err := cm.api.SendReply(chanId, message, + msgId, time.Duration(leaseTimeMS), params.CMIX) + if err != nil { + return nil, err + } + + // Construct send report + return constructChannelSendReport(chanMsgId, rnd.ID, ephId) +} + +// SendReaction is used to send a reaction to a message over a channel. +// The reaction must be a single emoji with no other characters, and will +// be rejected otherwise. +// Users will drop the reaction if they do not recognize the reactTo message. +// +// Parameters: +// - marshalledChanId - A JSON marshalled channel ID ([id.ID]). +// - reaction - The user's reaction. This should be a single emoji with no +// other characters. As such, a Unicode string is expected. +// - messageToReactTo - The marshalled [channel.MessageID] of the message you +// wish to reply to. This may be found in the ChannelSendReport if replying +// to your own. Alternatively, if reacting to another user's message, you may +// retrieve it via the ChannelMessageReceptionCallback registered using +// RegisterReceiveHandler. +// - cmixParamsJSON - A JSON marshalled [xxdk.CMIXParams]. This may be empty, +// and GetDefaultCMixParams will be used internally. +// +// Returns: +// - []byte - A JSON marshalled ChannelSendReport. +func (cm *ChannelsManager) SendReaction(marshalledChanId []byte, + reaction string, messageToReactTo []byte, + cmixParamsJSON []byte) ([]byte, error) { + + // Unmarshal channel ID and parameters + chanId, params, err := parseChannelsParameters( + marshalledChanId, cmixParamsJSON) + if err != nil { + return nil, err + } + + // Unmarshal message ID + msgId := cryptoChannel.MessageID{} + copy(msgId[:], messageToReactTo) + + // Send reaction + chanMsgId, rnd, ephId, err := cm.api.SendReaction(chanId, + reaction, msgId, params.CMIX) + if err != nil { + return nil, err + } + + // Construct send report + return constructChannelSendReport(chanMsgId, rnd.ID, ephId) +} + +// GetIdentity returns the marshaled public identity ([channel.Identity]) that +// the channel is using. +func (cm *ChannelsManager) GetIdentity() ([]byte, error) { + i := cm.api.GetIdentity() + return json.Marshal(&i) +} + +// GetStorageTag returns the storage tag needed to reload the manager. +func (cm *ChannelsManager) GetStorageTag() string { + return cm.api.GetStorageTag() +} + +// SetNickname sets the nickname for a given channel. The nickname must be valid +// according to [IsNicknameValid]. +func (cm *ChannelsManager) SetNickname(newNick string, ch []byte) error { + chid, err := id.Unmarshal(ch) + if err != nil { + return err + } + return cm.api.SetNickname(newNick, chid) +} + +// DeleteNickname deletes the nickname for a given channel. +func (cm *ChannelsManager) DeleteNickname(ch []byte) error { + chid, err := id.Unmarshal(ch) + if err != nil { + return err + } + return cm.api.DeleteNickname(chid) +} + +// GetNickname returns the nickname set for a given channel. Returns an error if +// there is no nickname set. +func (cm *ChannelsManager) GetNickname(ch []byte) (string, error) { + chid, err := id.Unmarshal(ch) + if err != nil { + return "", err + } + nick, exists := cm.api.GetNickname(chid) + if !exists { + return "", errors.New("no nickname found for the given channel") + } + + return nick, nil +} + +// IsNicknameValid checks if a nickname is valid. +// +// Rules: +// 1. A nickname must not be longer than 24 characters. +// 2. A nickname must not be shorter than 1 character. +func IsNicknameValid(nick string) error { + return channels.IsNicknameValid(nick) +} + +// parseChannelsParameters is a helper function for the Send functions. It +// parses the channel ID and the passed in parameters into their respective +// objects. These objects are passed into the API via the internal send +// functions. +func parseChannelsParameters(marshalledChanId, cmixParamsJSON []byte) ( + *id.ID, xxdk.CMIXParams, error) { + // Unmarshal channel ID + chanId, err := id.Unmarshal(marshalledChanId) + if err != nil { + return nil, xxdk.CMIXParams{}, err + } + + // Unmarshal cmix params + params, err := parseCMixParams(cmixParamsJSON) + if err != nil { + return nil, xxdk.CMIXParams{}, err + } + + return chanId, params, nil +} + +// constructChannelSendReport is a helper function which returns a JSON +// marshalled ChannelSendReport. +func constructChannelSendReport(channelMessageId cryptoChannel.MessageID, + roundId id.Round, ephId ephemeral.Id) ([]byte, error) { + // Construct send report + chanSendReport := ChannelSendReport{ + MessageId: channelMessageId.Bytes(), + RoundsList: makeRoundsList(roundId), + EphId: ephId.Int64(), + } + + // Marshal send report + return json.Marshal(chanSendReport) +} + +//////////////////////////////////////////////////////////////////////////////// +// Channel Receiving Logic and Callback Registration // +//////////////////////////////////////////////////////////////////////////////// + +// ReceivedChannelMessageReport is a report structure returned via the +// ChannelMessageReceptionCallback. This report gives the context for the +// channel the message was sent to and the message itself. This is returned via +// the callback as JSON marshalled bytes. +// +// JSON Example: +// { +// "ChannelId": "AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", +// "MessageId": "3S6DiVjWH9mLmjy1oaam/3x45bJQzOW6u2KgeUn59wA=", +// "ReplyTo":"cxMyGUFJ+Ff1Xp2X+XkIpOnNAQEZmv8SNP5eYH4tCik=", +// "MessageType": 42, +// "SenderUsername": "hunter2", +// "Content": "YmFuX2JhZFVTZXI=", +// "Timestamp": 1662502150335283000, +// "Lease": 25, +// "Rounds": [ 1, 4, 9], +// } +type ReceivedChannelMessageReport struct { + ChannelId []byte + MessageId []byte + MessageType int + Nickname string + Identity []byte + Content []byte + Timestamp int64 + Lease int64 + RoundsList +} + +// ChannelMessageReceptionCallback is the callback that returns the context for +// a channel message via the Callback. +// It must return a unique UUID for the message by which it can be referenced +// later +type ChannelMessageReceptionCallback interface { + Callback(receivedChannelMessageReport []byte, err error) int +} + +// RegisterReceiveHandler is used to register handlers for non-default message +// types. They can be processed by modules. It is important that such modules +// sync up with the event model implementation. +// +// There can only be one handler per [channels.MessageType], and this will +// return an error on any re-registration. +// +// Parameters: +// - messageType - represents the [channels.MessageType] which will have a +// registered listener. +// - listenerCb - the callback which will be executed when a channel message +// of messageType is received. +func (cm *ChannelsManager) RegisterReceiveHandler(messageType int, + listenerCb ChannelMessageReceptionCallback) error { + + // Wrap callback around backend interface + cb := channels.MessageTypeReceiveMessage( + func(channelID *id.ID, + messageID cryptoChannel.MessageID, messageType channels.MessageType, + nickname string, content []byte, identity cryptoChannel.Identity, + timestamp time.Time, lease time.Duration, round rounds.Round, + status channels.SentStatus) uint64 { + + idBytes, err := json.Marshal(&identity) + if err != nil { + jww.WARN.Printf("failed to marshal identity object: %+v", err) + return 0 + } + + rcm := ReceivedChannelMessageReport{ + ChannelId: channelID.Marshal(), + MessageId: messageID.Bytes(), + MessageType: int(messageType), + Nickname: nickname, + Identity: idBytes, + Content: content, + Timestamp: timestamp.UnixNano(), + Lease: int64(lease), + RoundsList: makeRoundsList(round.ID), + } + + return uint64(listenerCb.Callback(json.Marshal(rcm))) + }) + + // Register handler + return cm.api.RegisterReceiveHandler(channels.MessageType(messageType), cb) +} + +//////////////////////////////////////////////////////////////////////////////// +// Event Model Logic // +//////////////////////////////////////////////////////////////////////////////// + +// EventModelBuilder builds an event model +type EventModelBuilder interface { + Build(path string) EventModel +} + +// EventModel is an interface which an external party which uses the channels +// system passed an object which adheres to in order to get events on the +// channel. +type EventModel interface { + // JoinChannel is called whenever a channel is joined locally. + // + // Parameters: + // - channel - Returns the pretty print representation of a channel. + JoinChannel(channel string) + + // LeaveChannel is called whenever a channel is left locally. + // + // Parameters: + // - ChannelId - The marshalled channel [id.ID]. + LeaveChannel(channelID []byte) + + // ReceiveMessage is called whenever a message is received on a given + // channel. It may be called multiple times on the same message. It is + // incumbent on the user of the API to filter such called by message ID. + // + // Parameters: + // - channelID - The marshalled channel [id.ID]. + // - messageID - The bytes of the [channel.MessageID] of the received + // message. + // - nickname - The nickname of the sender of the message. + // - text - The content of the message. + // - timestamp - Time the message was received; represented as nanoseconds + // since unix epoch. + // - identity - the json of the identity of the sender + // - lease - The number of nanoseconds that the message is valid for. + // - roundId - The ID of the round that the message was received on. + // - mType - the type of the message, always 1 for this call + // - status - the [channels.SentStatus] of the message. + // + // Statuses will be enumerated as such: + // Sent = 0 + // Delivered = 1 + // Failed = 2 + // + // Returns a non-negative unique UUID for the message that it can be + // referenced by later with [EventModel.UpdateSentStatus]. + ReceiveMessage(channelID, messageID []byte, nickname, text string, + identity []byte, timestamp, lease, roundId, mType, + status int64) int64 + + // ReceiveReply is called whenever a message is received that is a reply on + // a given channel. It may be called multiple times on the same message. It + // is incumbent on the user of the API to filter such called by message ID. + // + // Messages may arrive our of order, so a reply in theory can arrive before + // the initial message. As a result, it may be important to buffer replies. + // + // Parameters: + // - channelID - The marshalled channel [id.ID]. + // - messageID - The bytes of the [channel.MessageID] of the received + // message. + // - reactionTo - The [channel.MessageID] for the message that received a + // reply. + // - nickname - The nickname of the sender of the message. + // - text - The content of the message. + // - identity - the json marshaled identity of the sender + // - timestamp - Time the message was received; represented as nanoseconds + // since unix epoch. + // - lease - The number of nanoseconds that the message is valid for. + // - roundId - The ID of the round that the message was received on. + // - mType - the type of the message, always 1 for this call + // - status - the [channels.SentStatus] of the message. + // + // Statuses will be enumerated as such: + // Sent = 0 + // Delivered = 1 + // Failed = 2 + // + // Returns a non-negative unique UUID for the message that it can be + // referenced by later with [EventModel.UpdateSentStatus]. + ReceiveReply(channelID, messageID, reactionTo []byte, + nickname, text string, identity []byte, + timestamp, lease, roundId, mType, status int64) int64 + + // ReceiveReaction is called whenever a reaction to a message is received + // on a given channel. It may be called multiple times on the same reaction. + // It is incumbent on the user of the API to filter such called by message + // ID. + // + // Messages may arrive our of order, so a reply in theory can arrive before + // the initial message. As a result, it may be important to buffer + // reactions. + // + // Parameters: + // - channelID - The marshalled channel [id.ID]. + // - messageID - The bytes of the [channel.MessageID] of the received + // message. + // - reactionTo - The [channel.MessageID] for the message that received a + // reply. + // - nickname - The nickname of the sender of the message. + // - reaction - The contents of the reaction message. + // - identity - The json marshal of the identity of the sender + // - timestamp - Time the message was received; represented as nanoseconds + // since unix epoch. + // - lease - The number of nanoseconds that the message is valid for. + // - roundId - The ID of the round that the message was received on. + // - mType - the type of the message, always 1 for this call + // - status - the [channels.SentStatus] of the message. + // + // Statuses will be enumerated as such: + // Sent = 0 + // Delivered = 1 + // Failed = 2 + // + // Returns a non-negative unique uuid for the message by which it can be + // referenced later with UpdateSentStatus + ReceiveReaction(channelID, messageID, reactionTo []byte, + nickname, reaction string, identity []byte, + timestamp, lease, roundId, mtype, status int64) int64 + + // UpdateSentStatus is called whenever the sent status of a message has + // changed. + // + // Parameters: + // - messageID - The bytes of the [channel.MessageID] of the received + // message. + // - status - the [channels.SentStatus] of the message. + // + // Statuses will be enumerated as such: + // Sent = 0 + // Delivered = 1 + // Failed = 2 + UpdateSentStatus( + uuid int64, messageID []byte, timestamp, roundID, status int64) + + // unimplemented + // IgnoreMessage(ChannelID *id.ID, MessageID cryptoChannel.MessageID) + // UnIgnoreMessage(ChannelID *id.ID, MessageID cryptoChannel.MessageID) + // PinMessage(ChannelID *id.ID, MessageID cryptoChannel.MessageID, end time.Time) + // UnPinMessage(ChannelID *id.ID, MessageID cryptoChannel.MessageID) +} + +// toEventModel is a wrapper which wraps an existing channels.EventModel object. +type toEventModel struct { + em EventModel +} + +// NewEventModel is a constructor for a toEventModel. This will take in an +// EventModel and wraps it around the toEventModel. +func NewEventModel(em EventModel) channels.EventModel { + return &toEventModel{em: em} +} + +// JoinChannel is called whenever a channel is joined locally. +func (tem *toEventModel) JoinChannel(channel *cryptoBroadcast.Channel) { + tem.em.JoinChannel(channel.PrettyPrint()) +} + +// LeaveChannel is called whenever a channel is left locally. +func (tem *toEventModel) LeaveChannel(channelID *id.ID) { + tem.em.LeaveChannel(channelID[:]) +} + +// ReceiveMessage is called whenever a message is received on a given channel. +// It may be called multiple times on the same message. It is incumbent on the +// user of the API to filter such called by message ID. +func (tem *toEventModel) ReceiveMessage(channelID *id.ID, messageID cryptoChannel.MessageID, + nickname, text string, identity cryptoChannel.Identity, + timestamp time.Time, lease time.Duration, round rounds.Round, + mType channels.MessageType, + status channels.SentStatus) uint64 { + + idBytes, err := json.Marshal(&identity) + if err != nil { + jww.WARN.Printf("failed to marshal identity object: %+v", err) + return 0 + } + + return uint64(tem.em.ReceiveMessage(channelID[:], messageID[:], nickname, + text, idBytes, timestamp.UnixNano(), int64(lease), int64(round.ID), int64(mType), + int64(status))) +} + +// ReceiveReply is called whenever a message is received that is a reply on a +// given channel. It may be called multiple times on the same message. It is +// incumbent on the user of the API to filter such called by message ID. +// +// Messages may arrive our of order, so a reply in theory can arrive before the +// initial message. As a result, it may be important to buffer replies. +func (tem *toEventModel) ReceiveReply(channelID *id.ID, messageID cryptoChannel.MessageID, + reactionTo cryptoChannel.MessageID, nickname, text string, + identity cryptoChannel.Identity, timestamp time.Time, + lease time.Duration, round rounds.Round, mType channels.MessageType, + status channels.SentStatus) uint64 { + + idBytes, err := json.Marshal(&identity) + if err != nil { + jww.WARN.Printf("failed to marshal identity object: %+v", err) + return 0 + } + + return uint64(tem.em.ReceiveReply(channelID[:], messageID[:], reactionTo[:], + nickname, text, idBytes, timestamp.UnixNano(), int64(lease), + int64(round.ID), int64(mType), int64(status))) + +} + +// ReceiveReaction is called whenever a reaction to a message is received on a +// given channel. It may be called multiple times on the same reaction. It is +// incumbent on the user of the API to filter such called by message ID. +// +// Messages may arrive our of order, so a reply in theory can arrive before the +// initial message. As a result, it may be important to buffer reactions. +func (tem *toEventModel) ReceiveReaction(channelID *id.ID, messageID cryptoChannel.MessageID, + reactionTo cryptoChannel.MessageID, nickname, reaction string, + identity cryptoChannel.Identity, timestamp time.Time, + lease time.Duration, round rounds.Round, mType channels.MessageType, + status channels.SentStatus) uint64 { + + idBytes, err := json.Marshal(&identity) + if err != nil { + jww.WARN.Printf("failed to marshal identity object: %+v", err) + return 0 + } + + return uint64(tem.em.ReceiveReaction(channelID[:], messageID[:], + reactionTo[:], nickname, reaction, idBytes, timestamp.UnixNano(), + int64(lease), int64(round.ID), int64(mType), int64(status))) +} + +// UpdateSentStatus is called whenever the sent status of a message has changed. +func (tem *toEventModel) UpdateSentStatus(uuid uint64, + messageID cryptoChannel.MessageID, timestamp time.Time, round rounds.Round, + status channels.SentStatus) { + tem.em.UpdateSentStatus(int64(uuid), messageID[:], timestamp.UnixNano(), + int64(round.ID), int64(status)) +} diff --git a/bindings/cmix.go b/bindings/cmix.go index 4b9d66cf31598178e56e387d429b390cb91356c4..5b5683f8aedb3e0e57f087de749c5e090823f0c0 100644 --- a/bindings/cmix.go +++ b/bindings/cmix.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package bindings @@ -35,10 +35,10 @@ type Cmix struct { id int } -// NewCmix creates user storage, generates keys, connects, and registers -// with the network. Note that this does not register a username/identity, but -// merely creates a new cryptographic identity for adding such information -// at a later date. +// NewCmix creates user storage, generates keys, connects, and registers with +// the network. Note that this does not register a username/identity, but merely +// creates a new cryptographic identity for adding such information at a later +// date. // // Users of this function should delete the storage directory on error. func NewCmix(ndfJSON, storageDir string, password []byte, registrationCode string) error { @@ -49,8 +49,9 @@ func NewCmix(ndfJSON, storageDir string, password []byte, registrationCode strin return nil } -// LoadCmix will load an existing user storage from the storageDir using the password. -// This will fail if the user storage does not exist or the password is incorrect. +// LoadCmix will load an existing user storage from the storageDir using the +// password. This will fail if the user storage does not exist or the password +// is incorrect. // // The password is passed as a byte array so that it can be cleared from memory // and stored as securely as possible using the MemGuard library. @@ -59,10 +60,6 @@ func NewCmix(ndfJSON, storageDir string, password []byte, registrationCode strin // subprocesses to perform network operations. func LoadCmix(storageDir string, password []byte, cmixParamsJSON []byte) (*Cmix, error) { - if len(cmixParamsJSON) == 0 { - jww.WARN.Printf("cMix params not specified, using defaults...") - cmixParamsJSON = GetDefaultCMixParams() - } params, err := parseCMixParams(cmixParamsJSON) if err != nil { @@ -82,6 +79,10 @@ func (c *Cmix) GetID() int { return c.id } +//////////////////////////////////////////////////////////////////////////////// +// cMix Tracker // +//////////////////////////////////////////////////////////////////////////////// + // cmixTracker is a singleton used to keep track of extant Cmix objects, // preventing race conditions created by passing it over the bindings. type cmixTracker struct { @@ -90,8 +91,8 @@ type cmixTracker struct { mux sync.RWMutex } -// make creates a Cmix from a xxdk.Cmix, assigns it a unique ID,and adds it to -// the cmixTracker. +// make creates a Cmix from a [xxdk.Cmix], assigns it a unique ID, and adds it +// to the cmixTracker. func (ct *cmixTracker) make(c *xxdk.Cmix) *Cmix { ct.mux.Lock() defer ct.mux.Unlock() diff --git a/bindings/connect.go b/bindings/connect.go index c097d0cb3a23c9366ff6057a690c2b92845bc2aa..df3d4ae46c7f7c0a016ecd75fb576e0e48c98e87 100644 --- a/bindings/connect.go +++ b/bindings/connect.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package bindings @@ -48,7 +48,7 @@ func (c *Connection) GetId() int { // Parameters: // - e2eId - ID of the E2E object in the e2e tracker // - recipientContact - marshalled contact.Contact object -// - myIdentity - marshalled ReceptionIdentity object +// - e2eParamsJSON - JSON marshalled byte of xxdk.E2EParams object func (c *Cmix) Connect(e2eId int, recipientContact, e2eParamsJSON []byte) ( *Connection, error) { if len(e2eParamsJSON) == 0 { @@ -83,9 +83,9 @@ func (c *Cmix) Connect(e2eId int, recipientContact, e2eParamsJSON []byte) ( // // Returns: // - []byte - the JSON marshalled bytes of the E2ESendReport object, which can -// be passed into WaitForRoundResult to see if the send succeeded. +// be passed into Cmix.WaitForRoundResult to see if the send succeeded. func (c *Connection) SendE2E(mt int, payload []byte) ([]byte, error) { - rounds, mid, ts, err := c.connection.SendE2E(catalog.MessageType(mt), payload, + sendReport, err := c.connection.SendE2E(catalog.MessageType(mt), payload, c.params.Base) if err != nil { @@ -93,9 +93,11 @@ func (c *Connection) SendE2E(mt int, payload []byte) ([]byte, error) { } sr := E2ESendReport{ - RoundsList: makeRoundsList(rounds...), - MessageID: mid.Marshal(), - Timestamp: ts.UnixNano(), + RoundsList: makeRoundsList(sendReport.RoundList...), + RoundURL: getRoundURL(sendReport.RoundList[0]), + MessageID: sendReport.MessageId.Marshal(), + Timestamp: sendReport.SentTime.UnixNano(), + KeyResidue: sendReport.KeyResidue.Marshal(), } return json.Marshal(&sr) diff --git a/bindings/connect_test.go b/bindings/connect_test.go index e0f8b38cd106e79c430a5e0b3a56484e87423d7d..5a58b4a715e97983bf9b4d79c560455346da958f 100644 --- a/bindings/connect_test.go +++ b/bindings/connect_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package bindings diff --git a/bindings/delivery.go b/bindings/delivery.go index 7d549ec7d397da9654ff5be8fccdd7122a6c3c2f..a645e9412dbbc99e49272843241f0dc22058c838 100644 --- a/bindings/delivery.go +++ b/bindings/delivery.go @@ -1,14 +1,15 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package bindings import ( "encoding/json" + "fmt" "time" "github.com/pkg/errors" @@ -17,15 +18,39 @@ import ( "gitlab.com/xx_network/primitives/id" ) +// dashboardBaseURL is the base of the xx network's round dashboard URL. +// This should be used by any type of send report's GetRoundURL method. +var dashboardBaseURL = "https://dashboard.xx.network" + +// SetDashboardURL is a function which modifies the base dashboard URL that is +// returned as part of any send report. Internally, this is defaulted to +// "https://dashboard.xx.network". This should only be called if the user +// explicitly wants to modify the dashboard URL. This function is not +// thread-safe, and as such should only be called on setup. +// +// Parameters: +// - newURL - A valid URL that will be used for round look up on any send +// report. +func SetDashboardURL(newURL string) { + dashboardBaseURL = newURL +} + +// getRoundURL is a helper function which returns the specific round +// within any type of send report, if they have a round in their RoundsList. +// This helper function is messenger specific. +func getRoundURL(round id.Round) string { + return fmt.Sprintf("%s/rounds/%d?xxmessenger=true", dashboardBaseURL, round) +} + // RoundsList contains a list of round IDs. // -// Example marshalled roundList object: +// JSON Example: // [1001,1003,1006] type RoundsList struct { Rounds []uint64 } -// makeRoundsList converts a list of id.Round into a binding-compatable +// makeRoundsList converts a list of id.Round into a binding-compatible // RoundsList. func makeRoundsList(rounds ...id.Round) RoundsList { rl := RoundsList{make([]uint64, len(rounds))} @@ -70,19 +95,21 @@ type MessageDeliveryCallback interface { EventCallback(delivered, timedOut bool, roundResults []byte) } -// WaitForRoundResult allows the caller to get notified if the rounds a -// message was sent in successfully completed. Under the hood, this uses an API -// that uses the internal round data, network historical round lookup, and -// waiting on network events to determine what has (or will) occur. -// -// The callbacks will return at timeoutMS if no state update occurs. +// WaitForRoundResult allows the caller to get notified if the rounds a message +// was sent in successfully completed. Under the hood, this uses an API that +// uses the internal round data, network historical round lookup, and waiting on +// network events to determine what has (or will) occur. // // This function takes the marshaled send report to ensure a memory leak does // not occur as a result of both sides of the bindings holding a reference to // the same pointer. // -// roundList is a JSON marshalled RoundsList or any JSON marshalled send report -// that inherits a RoundsList object. +// Parameters: +// - roundList - JSON marshalled bytes of RoundsList or JSON of any send report +// that inherits a [bindings.RoundsList] object +// - mdc - callback that adheres to the MessageDeliveryCallback interface +// - timeoutMS - timeout when the callback will return if no state update +// occurs, in milliseconds func (c *Cmix) WaitForRoundResult( roundList []byte, mdc MessageDeliveryCallback, timeoutMS int) error { jww.INFO.Printf("WaitForRoundResult(%s, _, %d)", roundList, timeoutMS) @@ -113,7 +140,7 @@ func (c *Cmix) WaitForRoundResult( timeout := time.Duration(timeoutMS) * time.Millisecond - err = c.api.GetCmix().GetRoundResults(timeout, f, rl...) + c.api.GetCmix().GetRoundResults(timeout, f, rl...) - return err + return nil } diff --git a/bindings/dummy.go b/bindings/dummy.go new file mode 100644 index 0000000000000000000000000000000000000000..e0915c6cf91022f8556a829787189f6bb0eaaf56 --- /dev/null +++ b/bindings/dummy.go @@ -0,0 +1,86 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + +package bindings + +import ( + "gitlab.com/elixxir/client/dummy" + "time" +) + +// DummyTraffic is the bindings-layer dummy (or "cover") traffic manager. T +// The manager can be used to set and get the status of the thread responsible for +// sending dummy messages. +type DummyTraffic struct { + m *dummy.Manager +} + +// NewDummyTrafficManager creates a DummyTraffic manager and initialises the +// dummy traffic sending thread. Note that the manager does not start sending +// dummy traffic until true is passed into DummyTraffic.SetStatus. The time +// duration between each sending operation and the amount of messages sent each +// interval are randomly generated values with bounds defined by the given +// parameters below. +// +// Parameters: +// - cmixId - a Cmix object ID in the tracker. +// - maxNumMessages - the upper bound of the random number of messages sent +// each sending cycle. Suggested value: 5. +// - avgSendDeltaMS - the average duration, in milliseconds, to wait between +// sends. Suggested value: 60000. +// - randomRangeMS - the upper bound of the interval between sending cycles, in +// milliseconds. Sends occur every avgSendDeltaMS +/- a random duration with +// an upper bound of randomRangeMS. Suggested value: 1000. +func NewDummyTrafficManager(cmixId, maxNumMessages, avgSendDeltaMS, + randomRangeMS int) (*DummyTraffic, error) { + + // Get user from singleton + net, err := cmixTrackerSingleton.get(cmixId) + if err != nil { + return nil, err + } + + avgSendDelta := time.Duration(avgSendDeltaMS) * time.Millisecond + randomRange := time.Duration(randomRangeMS) * time.Millisecond + + m := dummy.NewManager( + maxNumMessages, avgSendDelta, randomRange, net.api) + + return &DummyTraffic{m}, net.api.AddService(m.StartDummyTraffic) +} + +// SetStatus sets the state of the DummyTraffic manager's send thread by passing +// in a boolean parameter. There may be a small delay in between this call and +// the status of the sending thread to change accordingly. For example, passing +// false into this call while the sending thread is currently sending messages +// will not cancel nor halt the sending operation, but will pause the thread +// once that operation has completed. +// +// Parameters: +// - status - Input should be true if you want to send dummy messages and false +// if you want to pause dummy messages. +// +// Returns: +// - error - if the DummyTraffic.SetStatus is called too frequently, causing +// the internal status channel to fill. +func (dt *DummyTraffic) SetStatus(status bool) error { + return dt.m.SetStatus(status) +} + +// GetStatus returns the current state of the DummyTraffic manager's sending +// thread. Note that this function does not return the status set by the most +// recent call to SetStatus. Instead, this call returns the current status of +// the sending thread. This is due to the small delay that may occur between +// calling SetStatus and the sending thread taking into effect that status +// change. +// +// Returns: +// - bool - Returns true if sending thread is sending dummy messages and false +// if sending thread is paused/stopped and is not sending dummy messages. +func (dt *DummyTraffic) GetStatus() bool { + return dt.m.GetStatus() +} diff --git a/bindings/e2e.go b/bindings/e2e.go index 22438e73df9db897e20b785b871d78aadba73307..c072c5cb4e0d6393a27e790d2c6c3b0852d79502 100644 --- a/bindings/e2e.go +++ b/bindings/e2e.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package bindings @@ -26,20 +26,20 @@ var e2eTrackerSingleton = &e2eTracker{ count: 0, } -// E2e wraps the xxdk.E2e, implementing additional functions -// to support the bindings E2e interface. +// E2e wraps the xxdk.E2e, implementing additional functions to support the +// bindings E2e interface. type E2e struct { api *xxdk.E2e id int } -// GetID returns the e2eTracker ID for the E2e object. +// GetID returns the ID for this E2e in the e2eTracker. func (e *E2e) GetID() int { return e.id } // Login creates and returns a new E2e object and adds it to the -// e2eTrackerSingleton. identity should be created via +// e2eTrackerSingleton. Identity should be created via // Cmix.MakeReceptionIdentity and passed in here. If callbacks is left nil, a // default auth.Callbacks will be used. func Login(cmixId int, callbacks AuthCallbacks, identity, @@ -80,7 +80,7 @@ func Login(cmixId int, callbacks AuthCallbacks, identity, } // LoginEphemeral creates and returns a new ephemeral E2e object and adds it to -// the e2eTrackerSingleton. identity should be created via +// the e2eTrackerSingleton. Identity should be created via // Cmix.MakeReceptionIdentity or Cmix.MakeLegacyReceptionIdentity and passed in // here. If callbacks is left nil, a default auth.Callbacks will be used. func LoginEphemeral(cmixId int, callbacks AuthCallbacks, identity, @@ -126,13 +126,15 @@ func (e *E2e) GetContact() []byte { return e.api.GetReceptionIdentity().GetContact().Marshal() } -// GetUdAddressFromNdf retrieve the User Discovery's network address fom the NDF. +// GetUdAddressFromNdf retrieve the User Discovery's network address fom the +// NDF. func (e *E2e) GetUdAddressFromNdf() string { return e.api.GetCmix().GetInstance().GetPartialNdf(). Get().UDB.Address } -// GetUdCertFromNdf retrieves the User Discovery's TLS certificate from the NDF. +// GetUdCertFromNdf retrieves the User Discovery's TLS certificate (in PEM +// format) from the NDF. func (e *E2e) GetUdCertFromNdf() []byte { return []byte(e.api.GetCmix().GetInstance().GetPartialNdf().Get().UDB.Cert) } @@ -143,19 +145,26 @@ func (e *E2e) GetUdCertFromNdf() []byte { // Returns // - []byte - A byte marshalled contact.Contact. func (e *E2e) GetUdContactFromNdf() ([]byte, error) { - udIdData := e.api.GetCmix().GetInstance().GetPartialNdf().Get().UDB.ID + // Retrieve data from E2e + netDef := e.api.GetCmix().GetInstance().GetPartialNdf().Get() + e2eGroup := e.api.GetE2E().GetGroup() + + // Unmarshal UD ID + udIdData := netDef.UDB.ID udId, err := id.Unmarshal(udIdData) if err != nil { return nil, err } - udDhPubKeyData := e.api.GetCmix().GetInstance().GetPartialNdf().Get().UDB.DhPubKey - udDhPubKey := e.api.GetE2E().GetGroup().NewInt(1) + // Unmarshal DH pub key + udDhPubKeyData := netDef.UDB.DhPubKey + udDhPubKey := e2eGroup.NewInt(1) err = udDhPubKey.UnmarshalJSON(udDhPubKeyData) if err != nil { return nil, err } + // Construct contact udContact := contact.Contact{ ID: udId, DhPubKey: udDhPubKey, @@ -178,11 +187,11 @@ type authCallback struct { } // convertAuthCallbacks turns an auth.Callbacks into an AuthCallbacks. -func convertAuthCallbacks(requestor contact.Contact, +func convertAuthCallbacks(requester contact.Contact, receptionID receptionID.EphemeralIdentity, round rounds.Round) ( contact []byte, receptionId []byte, ephemeralId int64, roundId int64) { - contact = requestor.Marshal() + contact = requester.Marshal() receptionId = receptionID.Source.Marshal() ephemeralId = int64(receptionID.EphId.UInt64()) roundId = int64(round.ID) @@ -207,6 +216,10 @@ func (a *authCallback) Reset(partner contact.Contact, a.bindingsCbs.Reset(convertAuthCallbacks(partner, receptionID, round)) } +//////////////////////////////////////////////////////////////////////////////// +// E2E Tracker // +//////////////////////////////////////////////////////////////////////////////// + // e2eTracker is a singleton used to keep track of extant E2e objects, // preventing race conditions created by passing it over the bindings. type e2eTracker struct { @@ -222,15 +235,15 @@ func (ct *e2eTracker) make(c *xxdk.E2e) *E2e { ct.mux.Lock() defer ct.mux.Unlock() - id := ct.count + e2eID := ct.count ct.count++ - ct.tracked[id] = &E2e{ + ct.tracked[e2eID] = &E2e{ api: c, - id: id, + id: e2eID, } - return ct.tracked[id] + return ct.tracked[e2eID] } // get an E2e from the e2eTracker given its ID. diff --git a/bindings/e2eAuth.go b/bindings/e2eAuth.go index b2277eb3e3c77ae54ab933dae3b23c9edee9ef25..f7c01b53650eb210398cf6be27289a8ef3f6de18 100644 --- a/bindings/e2eAuth.go +++ b/bindings/e2eAuth.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package bindings @@ -35,12 +35,12 @@ import ( // // Parameters: // - partnerContact - the marshalled bytes of the contact.Contact object. -// - myFacts - stringified list of fact.FactList. +// - factsListJson - the JSON marshalled bytes of [fact.FactList]. // // Returns: // - int64 - ID of the round (convert to uint64) func (e *E2e) Request(partnerContact, factsListJson []byte) (int64, error) { - var factsList []Fact + var factsList fact.FactList err := json.Unmarshal(factsListJson, &factsList) if err != nil { return 0, err @@ -51,15 +51,7 @@ func (e *E2e) Request(partnerContact, factsListJson []byte) (int64, error) { return 0, err } - myFacts := fact.FactList{} - for _, f := range factsList { - myFacts = append(myFacts, fact.Fact{ - Fact: f.Fact, - T: fact.FactType(f.Type), - }) - } - - roundID, err := e.api.GetAuth().Request(partner, myFacts) + roundID, err := e.api.GetAuth().Request(partner, factsList) return int64(roundID), err } @@ -179,8 +171,7 @@ func (e *E2e) DeleteSentRequests() error { return e.api.GetAuth().DeleteSentRequests() } -// DeleteReceiveRequests clears all received requests from auth -// storage. +// DeleteReceiveRequests clears all received requests from auth storage. func (e *E2e) DeleteReceiveRequests() error { return e.api.GetAuth().DeleteReceiveRequests() } diff --git a/bindings/e2eHandler.go b/bindings/e2eHandler.go index 83ca76d62341b62162fa97d19be63b5537c517d2..4b63407520f8e1aa756f2e749e4b0971fc72fdd2 100644 --- a/bindings/e2eHandler.go +++ b/bindings/e2eHandler.go @@ -1,21 +1,21 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package bindings import ( "encoding/json" "fmt" + "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/catalog" "gitlab.com/elixxir/client/cmix/identity/receptionID" "gitlab.com/elixxir/client/cmix/rounds" - "gitlab.com/elixxir/client/e2e" "gitlab.com/elixxir/primitives/format" "gitlab.com/xx_network/primitives/id" ) @@ -23,14 +23,20 @@ import ( // E2ESendReport is the bindings' representation of the return values of // SendE2E. // -// Example E2ESendReport: -// {"Rounds":[1,5,9], -// "MessageID":"51Yy47uZbP0o2Y9B/kkreDLTB6opUol3M3mYiY2dcdQ=", -// "Timestamp":1653582683183384000} +// E2ESendReport Example JSON: +// { +// "Rounds": [ 1, 4, 9], +// "RoundURL":"https://dashboard.xx.network/rounds/25?xxmessenger=true", +// "MessageID": "iM34yCIr4Je8ZIzL9iAAG1UWAeDiHybxMTioMAaezvs=", +// "Timestamp": 1661532254302612000, +// "KeyResidue": "9q2/A69EAuFM1hFAT7Bzy5uGOQ4T6bPFF72h5PlgCWE=" +// } type E2ESendReport struct { RoundsList - MessageID []byte - Timestamp int64 + RoundURL string + MessageID []byte + Timestamp int64 + KeyResidue []byte } // GetReceptionID returns the marshalled default IDs. @@ -41,6 +47,19 @@ func (e *E2e) GetReceptionID() []byte { return e.api.GetE2E().GetReceptionID().Marshal() } +// DeleteContact removes a partner from E2e's storage. +// +// Parameters: +// - partnerID - the marshalled bytes of id.ID. +func (e *E2e) DeleteContact(partnerID []byte) error { + partner, err := id.Unmarshal(partnerID) + if err != nil { + return err + } + + return e.api.DeleteContact(partner) +} + // GetAllPartnerIDs returns a list of all partner IDs that the user has an E2E // relationship with. // @@ -117,30 +136,36 @@ func (e *E2e) RemoveService(tag string) error { // // Returns: // - []byte - the JSON marshalled bytes of the E2ESendReport object, which can -// be passed into WaitForRoundResult to see if the send succeeded. +// be passed into Cmix.WaitForRoundResult to see if the send succeeded. func (e *E2e) SendE2E(messageType int, recipientId, payload, - e2eParams []byte) ([]byte, error) { - // Note that specifically these are the Base params from xxdk.E2EParams - params := e2e.GetDefaultParams() - err := params.UnmarshalJSON(e2eParams) + e2eParamsJSON []byte) ([]byte, error) { + if len(e2eParamsJSON) == 0 { + jww.WARN.Printf("e2e params not specified, using defaults...") + e2eParamsJSON = GetDefaultE2EParams() + } + params, err := parseE2EParams(e2eParamsJSON) if err != nil { return nil, err } + recipient, err := id.Unmarshal(recipientId) if err != nil { return nil, err } - roundIds, messageId, ts, err := e.api.GetE2E().SendE2E( - catalog.MessageType(messageType), recipient, payload, params) + sendReport, err := e.api.GetE2E().SendE2E( + catalog.MessageType(messageType), recipient, payload, + params.Base) if err != nil { return nil, err } result := E2ESendReport{ - RoundsList: makeRoundsList(roundIds...), - MessageID: messageId.Marshal(), - Timestamp: ts.UnixNano(), + RoundsList: makeRoundsList(sendReport.RoundList...), + RoundURL: getRoundURL(sendReport.RoundList[0]), + MessageID: sendReport.MessageId.Marshal(), + Timestamp: sendReport.SentTime.UnixNano(), + KeyResidue: sendReport.KeyResidue.Marshal(), } return json.Marshal(result) } @@ -166,11 +191,9 @@ func (e *E2e) AddService(tag string, processor Processor) error { // - messageType - message type from the sender you want to listen for. // - newListener: A provider for a callback to hear a message. // Do not pass nil to this. -func (e *E2e) RegisterListener(senderID []byte, - messageType int, - newListener Listener) error { - jww.INFO.Printf("RegisterListener(%v, %d)", senderID, - messageType) +func (e *E2e) RegisterListener( + senderID []byte, messageType int, newListener Listener) error { + jww.INFO.Printf("RegisterListener(%v, %d)", senderID, messageType) // Convert senderID to id.Id object var uid *id.ID diff --git a/bindings/errors.go b/bindings/errors.go index 32c945c80c219626623b39ce12e3f299c1f73cef..4c15d28df9ae1fd4c6a748b3ed1b23bb317c7b4c 100644 --- a/bindings/errors.go +++ b/bindings/errors.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package bindings @@ -46,14 +46,14 @@ const ( UnrecognizedMessage = UnrecognizedCode + "Unrecognized error from XX backend, please report" ) -// CreateUserFriendlyErrorMessage will convert the passed in error string -// to an error string that is user-friendly if a substring match is -// found to a common error. Common errors is a map which can be updated -// using UpdateCommonErrors. If the error is not common, some simple parsing -// is done on the error message to make it more user-accessible, removing -// backend specific jargon. +// CreateUserFriendlyErrorMessage will convert the passed in error string to an +// error string that is user-friendly if a substring match is found to a +// common error. Common errors is a map that can be updated using +// UpdateCommonErrors. If the error is not common, some simple parsing is done +// on the error message to make it more user-accessible, removing backend +// specific jargon. // -// Parameters +// Parameters: // - errStr - an error returned from the backend. // // Returns @@ -97,16 +97,18 @@ func CreateUserFriendlyErrorMessage(errStr string) string { return fmt.Sprintf("%s: %v", UnrecognizedCode, errStr) } -// UpdateCommonErrors updates the internal error mapping DB. This internal database -// maps errors returned from the backend to user-friendly error messages. +// UpdateCommonErrors updates the internal error mapping database. This internal +// database maps errors returned from the backend to user-friendly error +// messages. // -// Parameters +// Parameters: // - jsonFile - contents of a JSON file whose format conforms to the example below. +// // Example Input: -// { -// "Failed to Unmarshal Conversation": "Could not retrieve conversation", -// "Failed to unmarshal SentRequestMap": "Failed to pull up friend requests", -// "cannot create username when network is not health": "Cannot create username, unable to connect to network", +// { +// "Failed to Unmarshal Conversation": "Could not retrieve conversation", +// "Failed to unmarshal SentRequestMap": "Failed to pull up friend requests", +// "cannot create username when network is not health": "Cannot create username, unable to connect to network", // } func UpdateCommonErrors(jsonFile string) error { errorMux.Lock() diff --git a/bindings/errors_test.go b/bindings/errors_test.go index 0dbcf0220e1232aa450d0884363e4c461fe42c66..fdb6539d0489e753196cfb89f50b29e0dffa45c0 100644 --- a/bindings/errors_test.go +++ b/bindings/errors_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package bindings diff --git a/bindings/fileTransfer.go b/bindings/fileTransfer.go index b0182ed6e2cb9c018a54ee716946e60cbb74f328..2a25aa4a7829c0fdd576c9c660709261dd23997c 100644 --- a/bindings/fileTransfer.go +++ b/bindings/fileTransfer.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package bindings @@ -32,12 +32,12 @@ type FileTransfer struct { // // Example JSON: // { -// "TransferID":"B4Z9cwU18beRoGbk5xBjbcd5Ryi9ZUFA2UBvi8FOHWo=", -// "SenderID":"emV6aW1hAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD", -// "Preview":"aXQncyBtZSBhIHByZXZpZXc=", -// "Name":"testfile.txt", -// "Type":"text file", -// "Size":2048 +// "TransferID":"B4Z9cwU18beRoGbk5xBjbcd5Ryi9ZUFA2UBvi8FOHWo=", +// "SenderID":"emV6aW1hAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD", +// "Preview":"aXQncyBtZSBhIHByZXZpZXc=", +// "Name":"testfile.txt", +// "Type":"text file", +// "Size":2048 // } type ReceivedFile struct { TransferID []byte // ID of the file transfer @@ -51,10 +51,10 @@ type ReceivedFile struct { // FileSend is a public struct that contains the file contents and its name, // type, and preview. // { -// "Name":"testfile.txt", -// "Type":"text file", -// "Preview":"aXQncyBtZSBhIHByZXZpZXc=", -// "Contents":"VGhpcyBpcyB0aGUgZnVsbCBjb250ZW50cyBvZiB0aGUgZmlsZSBpbiBieXRlcw==" +// "Name":"testfile.txt", +// "Type":"text file", +// "Preview":"aXQncyBtZSBhIHByZXZpZXc=", +// "Contents":"VGhpcyBpcyB0aGUgZnVsbCBjb250ZW50cyBvZiB0aGUgZmlsZSBpbiBieXRlcw==" // } type FileSend struct { Name string // Name of the file @@ -68,10 +68,10 @@ type FileSend struct { // // Example JSON: // { -// "Completed":false, -// "Transmitted":128, -// "Total":2048, -// "Err":null +// "Completed":false, +// "Transmitted":128, +// "Total":2048, +// "Err":null // } type Progress struct { Completed bool // Status of transfer (true if done) @@ -179,23 +179,23 @@ func InitFileTransfer(e2eID int, receiveFileCallback ReceiveFileCallback, // Parameters: // - payload - JSON marshalled FileSend // - recipientID - marshalled recipient id.ID -// - paramsJSON - JSON marshalled e2e.Params // - retry - number of retries allowed // - callback - callback that reports file sending progress -// - period - duration to wait between progress callbacks triggering +// - period - Duration (in ms) to wait between progress callbacks triggering. +// This value should depend on how frequently you want to receive updates, +// and should be tuned to your implementation. // // Returns: // - []byte - unique file transfer ID func (f *FileTransfer) Send(payload, recipientID []byte, retry float32, - callback FileTransferSentProgressCallback, period string) ([]byte, error) { + callback FileTransferSentProgressCallback, period int) ([]byte, error) { // Unmarshal recipient ID recipient, err := id.Unmarshal(recipientID) if err != nil { return nil, err } - // Parse duration to time.Duration - p, err := time.ParseDuration(period) + p := time.Millisecond * time.Duration(period) // Wrap transfer progress callback to be passed to fileTransfer layer cb := func(completed bool, arrived, total uint16, @@ -269,9 +269,11 @@ func (f *FileTransfer) CloseSend(tidBytes []byte) error { // Parameters: // - tidBytes - file transfer ID // - callback - callback that reports file reception progress -// - period - duration to wait between progress callbacks triggering +// - period - Duration (in ms) to wait between progress callbacks triggering. +// This value should depend on how frequently you want to receive updates, +// and should be tuned to your implementation. func (f *FileTransfer) RegisterSentProgressCallback(tidBytes []byte, - callback FileTransferSentProgressCallback, period string) error { + callback FileTransferSentProgressCallback, period int) error { cb := func(completed bool, arrived, total uint16, st fileTransfer.SentTransfer, t fileTransfer.FilePartTracker, err error) { prog := &Progress{ @@ -283,10 +285,7 @@ func (f *FileTransfer) RegisterSentProgressCallback(tidBytes []byte, pm, err := json.Marshal(prog) callback.Callback(pm, &FilePartTracker{t}, err) } - p, err := time.ParseDuration(period) - if err != nil { - return err - } + p := time.Millisecond * time.Duration(period) tid := ftCrypto.UnmarshalTransferID(tidBytes) return f.w.RegisterSentProgressCallback(&tid, cb, p) @@ -300,9 +299,11 @@ func (f *FileTransfer) RegisterSentProgressCallback(tidBytes []byte, // Parameters: // - tidBytes - file transfer ID // - callback - callback that reports file reception progress -// - period - duration to wait between progress callbacks triggering +// - period - Duration (in ms) to wait between progress callbacks triggering. +// This value should depend on how frequently you want to receive updates, +// and should be tuned to your implementation. func (f *FileTransfer) RegisterReceivedProgressCallback(tidBytes []byte, - callback FileTransferReceiveProgressCallback, period string) error { + callback FileTransferReceiveProgressCallback, period int) error { cb := func(completed bool, received, total uint16, rt fileTransfer.ReceivedTransfer, t fileTransfer.FilePartTracker, err error) { prog := &Progress{ @@ -314,10 +315,8 @@ func (f *FileTransfer) RegisterReceivedProgressCallback(tidBytes []byte, pm, err := json.Marshal(prog) callback.Callback(pm, &FilePartTracker{t}, err) } - p, err := time.ParseDuration(period) - if err != nil { - return err - } + p := time.Millisecond * time.Duration(period) + tid := ftCrypto.UnmarshalTransferID(tidBytes) return f.w.RegisterReceivedProgressCallback(&tid, cb, p) } diff --git a/bindings/fileTransfer_test.go b/bindings/fileTransfer_test.go index 10d49d9b81cbea043d281de9f4377508a6e2063f..81a0679e0a9737e4db9465e23d8d3519d70b9b9b 100644 --- a/bindings/fileTransfer_test.go +++ b/bindings/fileTransfer_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package bindings diff --git a/bindings/follow.go b/bindings/follow.go index 482bbd9cd83ab254ee2677a494d8e720df67c88d..503aa5e1a5301ab1cd0124044e7a57a87fe28eea 100644 --- a/bindings/follow.go +++ b/bindings/follow.go @@ -1,15 +1,16 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package bindings import ( "encoding/json" "fmt" + "gitlab.com/elixxir/client/cmix/message" "time" "github.com/pkg/errors" @@ -26,29 +27,28 @@ import ( // they are stopped if there is no internet access. // // Threads Started: -// - Network Follower (/network/follow.go) -// tracks the network events and hands them off to workers for handling. -// - Historical Round Retrieval (/network/rounds/historical.go) -// retrieves data about rounds that are too old to be stored by the client. -// - Message Retrieval Worker Group (/network/rounds/retrieve.go) -// requests all messages in a given round from the gateway of the last -// nodes. -// - Message Handling Worker Group (/network/message/handle.go) -// decrypts and partitions messages when signals via the Switchboard. -// - Health Tracker (/network/health), -// via the network instance, tracks the state of the network. -// - Garbled Messages (/network/message/garbled.go) -// can be signaled to check all recent messages that could be decoded. It -// uses a message store on disk for persistence. -// - Critical Messages (/network/message/critical.go) -// ensures all protocol layer mandatory messages are sent. It uses a -// message store on disk for persistence. -// - KeyExchange Trigger (/keyExchange/trigger.go) -// responds to sent rekeys and executes them. -// - KeyExchange Confirm (/keyExchange/confirm.go) -// responds to confirmations of successful rekey operations. -// - Auth Callback (/auth/callback.go) -// handles both auth confirm and requests. +// - Network Follower (/network/follow.go) +// tracks the network events and hands them off to workers for handling. +// - Historical Round Retrieval (/network/rounds/historical.go) +// retrieves data about rounds that are too old to be stored by the client. +// - Message Retrieval Worker Group (/network/rounds/retrieve.go) +// requests all messages in a given round from the gateway of the last nodes. +// - Message Handling Worker Group (/network/message/handle.go) +// decrypts and partitions messages when signals via the Switchboard. +// - Health Tracker (/network/health), +// via the network instance, tracks the state of the network. +// - Garbled Messages (/network/message/garbled.go) +// can be signaled to check all recent messages that could be decoded. It +// uses a message store on disk for persistence. +// - Critical Messages (/network/message/critical.go) +// ensures all protocol layer mandatory messages are sent. It uses a message +// store on disk for persistence. +// - KeyExchange Trigger (/keyExchange/trigger.go) +// responds to sent rekeys and executes them. +// - KeyExchange Confirm (/keyExchange/confirm.go) +// responds to confirmations of successful rekey operations. +// - Auth Callback (/auth/callback.go) +// handles both auth confirm and requests. func (c *Cmix) StartNetworkFollower(timeoutMS int) error { timeout := time.Duration(timeoutMS) * time.Millisecond return c.api.StartNetworkFollower(timeout) @@ -58,7 +58,7 @@ func (c *Cmix) StartNetworkFollower(timeoutMS int) error { // an error if the follower is in the wrong state to stop or if it fails to stop // it. // -// if the network follower is running and this fails, the Cmix object will +// If the network follower is running and this fails, the Cmix object will // most likely be in an unrecoverable state and need to be trashed. func (c *Cmix) StopNetworkFollower() error { if err := c.api.StopNetworkFollower(); err != nil { @@ -84,11 +84,9 @@ func (c *Cmix) WaitForNetwork(timeoutMS int) bool { // NetworkFollowerStatus gets the state of the network follower. It returns a // status with the following values: -// -// Status: -// - Stopped - 0 -// - Running - 2000 -// - Stopping - 3000 +// Stopped - 0 +// Running - 2000 +// Stopping - 3000 func (c *Cmix) NetworkFollowerStatus() int { return int(c.api.NetworkFollowerStatus()) } @@ -103,10 +101,11 @@ type NodeRegistrationReport struct { // GetNodeRegistrationStatus returns the current state of node registration. // // Returns: -// - []bye - A marshalled NodeRegistrationReport containing the number of -// nodes the user is registered with and the number of nodes present in the NDF. -// - An error if it cannot get the node registration status. The most likely cause -// is that the network is unhealthy. +// - []byte - A marshalled NodeRegistrationReport containing the number of +// nodes the user is registered with and the number of nodes present in the +// NDF. +// - An error if it cannot get the node registration status. The most likely +// cause is that the network is unhealthy. func (c *Cmix) GetNodeRegistrationStatus() ([]byte, error) { numNodesRegistered, numNodes, err := c.api.GetNodeRegistrationStatus() if err != nil { @@ -137,6 +136,22 @@ func (c *Cmix) IsHealthy() bool { return c.api.GetCmix().IsHealthy() } +// GetRunningProcesses returns the names of all running processes at the time +// of this call. Note that this list may change and is subject to race +// conditions if multiple threads are in the process of starting or stopping. +// +// Returns: +// - []byte - A JSON marshalled list of all running processes. +// +// JSON Example: +// { +// "FileTransfer{BatchBuilderThread, FilePartSendingThread#0, FilePartSendingThread#1, FilePartSendingThread#2, FilePartSendingThread#3}", +// "MessageReception Worker 0" +// } +func (c *Cmix) GetRunningProcesses() ([]byte, error) { + return json.Marshal(c.api.GetRunningProcesses()) +} + // NetworkHealthCallback contains a callback that is used to receive // notification if network health changes. type NetworkHealthCallback interface { @@ -169,3 +184,54 @@ func (c *Cmix) RegisterClientErrorCallback(clientError ClientError) { } }() } + +// TrackServicesCallback is the callback for [Cmix.TrackServices]. +// This will pass to the user a JSON-marshalled list of backend services. +// If there was an error retrieving or marshalling the service list, +// there is an error for the second parameter which will be non-null. +// +// Parameters: +// - marshalData - JSON marshalled bytes of [message.ServiceList], which is an +// array of [id.ID] and [message.Service]. +// - err - JSON unmarshalling error +// +// Example JSON: +// [ +// { +// "Id": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD", // bytes of id.ID encoded as base64 string +// "Services": [ +// { +// "Identifier": "AQID", // bytes encoded as base64 string +// "Tag": "TestTag 1", // string +// "Metadata": "BAUG" // bytes encoded as base64 string +// } +// ] +// }, +// { +// "Id": "AAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD", +// "Services": [ +// { +// "Identifier": "AQID", +// "Tag": "TestTag 2", +// "Metadata": "BAUG" +// } +// ] +// }, +// ] +type TrackServicesCallback interface { + Callback(marshalData []byte, err error) +} + +// TrackServices will return via a callback the list of services the +// backend keeps track of, which is formally referred to as a +// [message.ServiceList]. This may be passed into other bindings call which +// may need context on the available services for this client. +// +// Parameters: +// - cb - A TrackServicesCallback, which will be passed the marshalled +// message.ServiceList. +func (c *Cmix) TrackServices(cb TrackServicesCallback) { + c.api.GetCmix().TrackServices(func(list message.ServiceList) { + cb.Callback(json.Marshal(list)) + }) +} diff --git a/bindings/group.go b/bindings/group.go index 00951c269e43843fd3bd05609f1bddc9562cb844..ddb6f12b985ebfaf7e6d7c1df0c2c3b86cae3c45 100644 --- a/bindings/group.go +++ b/bindings/group.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package bindings @@ -17,68 +17,9 @@ import ( gs "gitlab.com/elixxir/client/groupChat/groupStore" "gitlab.com/elixxir/primitives/format" "gitlab.com/xx_network/primitives/id" - "sync" "time" ) -//////////////////////////////////////////////////////////////////////////////// -// Group Singleton Tracker // -//////////////////////////////////////////////////////////////////////////////// - -// groupTrackerSingleton is used to track Group objects so that they can be -// referenced by ID back over the bindings. -var groupTrackerSingleton = &groupTracker{ - tracked: make(map[int]*Group), - count: 0, -} - -// groupTracker is a singleton used to keep track of extant Group objects, -// preventing race conditions created by passing it over the bindings. -type groupTracker struct { - tracked map[int]*Group - count int - mux sync.RWMutex -} - -// make create a Group from a groupStore.Group, assigns it a unique ID, and -// adds it to the groupChatTracker. -func (ut *groupTracker) make(g gs.Group) *Group { - ut.mux.Lock() - defer ut.mux.Unlock() - - id := ut.count - ut.count++ - - ut.tracked[id] = &Group{ - g: g, - id: id, - } - - return ut.tracked[id] -} - -// get a Group from the groupChatTracker given its ID. -func (ut *groupTracker) get(id int) (*Group, error) { - ut.mux.RLock() - defer ut.mux.RUnlock() - - g, exist := ut.tracked[id] - if !exist { - return nil, errors.Errorf( - "Cannot get Group for ID %d, does not exist", id) - } - - return g, nil -} - -// delete removes a Group from the groupTracker. -func (ut *groupTracker) delete(id int) { - ut.mux.Lock() - defer ut.mux.Unlock() - - delete(ut.tracked, id) -} - //////////////////////////////////////////////////////////////////////////////// // Group Chat // //////////////////////////////////////////////////////////////////////////////// @@ -105,8 +46,7 @@ func NewGroupChat(e2eID int, // Construct a wrapper for the request callback requestCb := func(g gs.Group) { - newGroup := groupTrackerSingleton.make(g) - requestFunc.Callback(newGroup) + requestFunc.Callback(&Group{g: g}) } // Construct a group chat manager @@ -129,16 +69,16 @@ func NewGroupChat(e2eID int, // IDs of members the user wants to add to the group. // - message - the initial message sent to all members in the group. This is an // optional parameter and may be nil. -// - tag - the name of the group decided by the creator. This is an optional +// - name - the name of the group decided by the creator. This is an optional // parameter and may be nil. If nil the group will be assigned the default // name. // // Returns: // - []byte - the JSON marshalled bytes of the GroupReport object, which can be -// passed into WaitForRoundResult to see if the group request message send -// succeeded. -func (g *GroupChat) MakeGroup(membershipBytes []byte, message, name []byte) ( - []byte, error) { +// passed into Cmix.WaitForRoundResult to see if the group request message +// send succeeded. +func (g *GroupChat) MakeGroup( + membershipBytes, message, name []byte) ([]byte, error) { // Unmarshal membership list into a list of []*id.Id var members []*id.ID @@ -148,7 +88,7 @@ func (g *GroupChat) MakeGroup(membershipBytes []byte, message, name []byte) ( } // Construct group - grp, rounds, status, err := g.m.MakeGroup(members, name, message) + grp, roundIDs, status, err := g.m.MakeGroup(members, name, message) if err != nil { return nil, err } @@ -156,7 +96,8 @@ func (g *GroupChat) MakeGroup(membershipBytes []byte, message, name []byte) ( // Construct the group report report := GroupReport{ Id: grp.ID.Bytes(), - RoundsList: makeRoundsList(rounds...), + RoundsList: makeRoundsList(roundIDs...), + RoundURL: getRoundURL(roundIDs[0]), Status: int(status), } @@ -199,6 +140,7 @@ func (g *GroupChat) ResendRequest(groupId []byte) ([]byte, error) { report := &GroupReport{ Id: grp.ID.Bytes(), RoundsList: makeRoundsList(rnds...), + RoundURL: getRoundURL(rnds[0]), Status: int(status), } @@ -211,22 +153,14 @@ func (g *GroupChat) ResendRequest(groupId []byte) ([]byte, error) { // with the same trackedGroupId. // // Parameters: -// - trackedGroupId - the ID to retrieve the Group object within the backend's -// tracking system. This is received by GroupRequest.Callback. -func (g *GroupChat) JoinGroup(trackedGroupId int) error { - // Retrieve group from singleton - grp, err := groupTrackerSingleton.get(trackedGroupId) +// - serializedGroupData - the result of calling Group.Serialize() on +// any Group object returned over the bindings +func (g *GroupChat) JoinGroup(serializedGroupData []byte) error { + grp, err := DeserializeGroup(serializedGroupData) if err != nil { return err } - - // Join group - err = g.m.JoinGroup(grp.g) - if err != nil { - return err - } - - return nil + return g.m.JoinGroup(grp.g) } // LeaveGroup deletes a group so a user no longer has access. @@ -246,17 +180,16 @@ func (g *GroupChat) LeaveGroup(groupId []byte) error { // Send is the bindings-level function for sending to a group. // // Parameters: -// - groupId - the byte data representing a group ID. -// This can be pulled from a marshalled GroupReport. +// - groupId - the byte data representing a group ID. This can be pulled from +// marshalled GroupReport. // - message - the message that the user wishes to send to the group. // - tag - the tag associated with the message. This tag may be empty. // // Returns: // - []byte - the JSON marshalled bytes of the GroupSendReport object, which -// can be passed into WaitForRoundResult to see if the group message send -// succeeded. -func (g *GroupChat) Send(groupId, - message []byte, tag string) ([]byte, error) { +// can be passed into Cmix.WaitForRoundResult to see if the group message +// send succeeded. +func (g *GroupChat) Send(groupId, message []byte, tag string) ([]byte, error) { groupID, err := id.Unmarshal(groupId) if err != nil { return nil, errors.Errorf("Failed to unmarshal group ID: %+v", err) @@ -270,7 +203,8 @@ func (g *GroupChat) Send(groupId, // Construct send report sendReport := &GroupSendReport{ - RoundsList: makeRoundsList(round), + RoundURL: getRoundURL(round.ID), + RoundsList: makeRoundsList(round.ID), Timestamp: timestamp.UnixNano(), MessageID: msgID.Bytes(), } @@ -291,7 +225,7 @@ func (g *GroupChat) GetGroups() ([]byte, error) { // // Parameters: // - groupId - The byte data representing a group ID (a byte marshalled id.ID). -// This can be pulled from a marshalled GroupReport. +// This can be pulled from a marshalled GroupReport. // Returns: // - Group - The bindings-layer representation of a group. func (g *GroupChat) GetGroup(groupId []byte) (*Group, error) { @@ -308,7 +242,7 @@ func (g *GroupChat) GetGroup(groupId []byte) (*Group, error) { } // Add to tracker and return Group object - return groupTrackerSingleton.make(grp), nil + return &Group{g: grp}, nil } // NumGroups returns the number of groups the user is a part of. @@ -317,14 +251,13 @@ func (g *GroupChat) NumGroups() int { } //////////////////////////////////////////////////////////////////////////////// -// Group Structure +// Group Structure // //////////////////////////////////////////////////////////////////////////////// // Group structure contains the identifying and membership information of a // group chat. type Group struct { - g gs.Group - id int + g gs.Group } // GetName returns the name set by the user for the group. @@ -332,16 +265,11 @@ func (g *Group) GetName() []byte { return g.g.Name } -// GetID return the 33-byte unique group ID. This represents the id.ID object +// GetID return the 33-byte unique group ID. This represents the id.ID object. func (g *Group) GetID() []byte { return g.g.ID.Bytes() } -// GetTrackedID returns the tracked ID of the Group object. This is used by the backend tracker. -func (g *Group) GetTrackedID() int { - return g.id -} - // GetInitMessage returns initial message sent with the group request. func (g *Group) GetInitMessage() []byte { return g.g.InitMessage @@ -365,7 +293,26 @@ func (g *Group) GetCreatedMS() int64 { // All subsequent members are ordered by their ID. // // Returns: -// - []byte - a JSON marshalled version of the member list. +// - []byte - JSON marshalled [group.Membership], which is an array of +// [group.Member]. +// +// Example JSON [group.Membership] return: +// [ +// { +// "ID": "U4x/lrFkvxuXu59LtHLon1sUhPJSCcnZND6SugndnVID", +// "DhKey": { +// "Value": 3534334367214237261, +// "Fingerprint": 16801541511233098363 +// } +// }, +// { +// "ID": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD", +// "DhKey": { +// "Value": 7497468244883513247, +// "Fingerprint": 16801541511233098363 +// } +// } +// ] func (g *Group) GetMembership() ([]byte, error) { return json.Marshal(g.g.Members) } @@ -375,19 +322,30 @@ func (g *Group) Serialize() []byte { return g.g.Serialize() } -////////////////////////////////////////////////////////////////////////////////// -// Callbacks -////////////////////////////////////////////////////////////////////////////////// +// DeserializeGroup converts the results of Group.Serialize into a Group +// so that its methods can be called. +func DeserializeGroup(serializedGroupData []byte) (*Group, error) { + grp, err := gs.DeserializeGroup(serializedGroupData) + if err != nil { + return nil, err + } + return &Group{g: grp}, nil +} + +//////////////////////////////////////////////////////////////////////////////// +// Callbacks // +//////////////////////////////////////////////////////////////////////////////// // GroupRequest is a bindings-layer interface that handles a group reception. // // Parameters: -// - trackedGroupId - a bindings layer Group object. +// - g - a bindings layer Group object. type GroupRequest interface { Callback(g *Group) } // GroupChatProcessor manages the handling of received group chat messages. +// The decryptedMessage field will be a JSON marshalled GroupChatMessage. type GroupChatProcessor interface { Process(decryptedMessage, msg, receptionId []byte, ephemeralId, roundId int64, err error) @@ -400,13 +358,53 @@ type groupChatProcessor struct { bindingsCb GroupChatProcessor } +// GroupChatMessage is the bindings layer representation of the +// [groupChat.MessageReceive]. +// +// GroupChatMessage Example JSON: +// { +// "GroupId": "AAAAAAAJlasAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE", +// "SenderId": "AAAAAAAAB8gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD", +// "MessageId": "Zm9ydHkgZml2ZQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=", +// "Payload": "Zm9ydHkgZml2ZQ==", +// "Timestamp": 1663009269474079000 +// } +type GroupChatMessage struct { + // GroupId is the ID of the group that this message was sent on. + GroupId []byte + + // SenderId is the ID of the sender of this message. + SenderId []byte + + // MessageId is the ID of this group message. + MessageId []byte + + // Payload is the content of the message. + Payload []byte + + // Timestamp is the time this message was sent on. + Timestamp int64 +} + +// convertMessageReceive is a helper function which converts a +// [groupChat.MessageReceive] to the bindings-layer representation GroupChatMessage. +func convertMessageReceive(decryptedMsg gc.MessageReceive) GroupChatMessage { + return GroupChatMessage{ + GroupId: decryptedMsg.GroupID.Bytes(), + SenderId: decryptedMsg.SenderID.Bytes(), + MessageId: decryptedMsg.ID.Bytes(), + Payload: decryptedMsg.Payload, + Timestamp: decryptedMsg.Timestamp.UnixNano(), + } +} + // convertProcessor turns the input of a groupChat.Processor to the // binding-layer primitives equivalents within the GroupChatProcessor.Process. func convertGroupChatProcessor(decryptedMsg gc.MessageReceive, msg format.Message, receptionID receptionID.EphemeralIdentity, round rounds.Round) ( decryptedMessage, message, receptionId []byte, ephemeralId, roundId int64, err error) { - decryptedMessage, err = json.Marshal(decryptedMsg) + decryptedMessage, err = json.Marshal(convertMessageReceive(decryptedMsg)) message = msg.Marshal() receptionId = receptionID.Source.Marshal() ephemeralId = receptionID.EphId.Int64() @@ -432,16 +430,34 @@ func (gcp *groupChatProcessor) String() string { // GroupReport is returned when creating a new group and contains the ID of // the group, a list of rounds that the group requests were sent on, and the // status of the send operation. +// +// Example GroupReport JSON: +// { +// "Id": "AAAAAAAAAM0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE", +// "Rounds": [25, 64], +// "RoundURL": "https://dashboard.xx.network/rounds/25?xxmessenger=true", +// "Status": 1 +// } type GroupReport struct { Id []byte RoundsList - Status int + RoundURL string + Status int } // GroupSendReport is returned when sending a group message. It contains the // round ID sent on and the timestamp of the send operation. +// +// Example GroupSendReport JSON: +// { +// "Rounds": [25, 64], +// "RoundURL": "https://dashboard.xx.network/rounds/25?xxmessenger=true", +// "Timestamp": 1662577352813112000, +// "MessageID": "69ug6FA50UT2q6MWH3hne9PkHQ+H9DnEDsBhc0m0Aww=" +// } type GroupSendReport struct { RoundsList + RoundURL string Timestamp int64 MessageID []byte } diff --git a/bindings/identity.go b/bindings/identity.go index f1b56803184de8491f3c93ad43d89008f6227bd4..c48bd0d18814ae65037ed0a0cfd715fb7b8210ee 100644 --- a/bindings/identity.go +++ b/bindings/identity.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package bindings @@ -26,16 +26,18 @@ import ( // "RSAPrivatePem":"LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcFFJQkFBS0NBUUVBNU15dTdhYjBJOS9UL1BFUUxtd2x3ejZHV3FjMUNYemVIVXhoVEc4bmg1WWRWSXMxCmJ2THpBVjNOMDJxdXN6K2s4TVFEWjBtejMzdkswUmhPczZIY0NUSFdzTEpXRkE5WWpzWWlCRi9qTDd1bmd1ckIKL2tvK1JJSnNrWGFWaEZaazRGdERoRXhTNWY4RnR0Qmk1NmNLZmdJQlVKT3ozZi9qQllTMkxzMlJ6cWV5YXM3SApjV2RaME9TclBTT3BiYlViU1FPbS9LWnlweGZHU21yZ2oxRUZuU1dZZ2xGZTdUOTRPbHF5MG14QTV5clVXbHorCk9sK3hHbXpCNUp4WUFSMU9oMFQrQTk4RWMrTUZHNm43L1MraDdzRDgybGRnVnJmbStFTzRCdmFKeTRESGZGMWgKNnp6QnVnY25NUVFGc0dLeDFYWC9COTVMdUpPVjdyeXlDbzZGbHdJREFRQUJBb0lCQVFDaUh6OGNlcDZvQk9RTAphUzBVRitHeU5VMnlVcVRNTWtTWThoUkh1c09CMmFheXoybHZVb3RLUHBPbjZRSWRWVTJrcE4vY2dtY0lSb2x5CkhBMDRUOHJBWVNaRlVqaVlRajkzKzRFREpJYXd2Z0YyVEs1bFoyb3oxVTdreStncU82V0RMR2Z0Q0wvODVQWEIKa210aXhnUXpRV3g1RWcvemtHdm03eURBalQxeDloNytsRjJwNFlBam5kT2xTS0dmQjFZeTR1RXBQd0kwc1lWdgpKQWc0MEFxbllZUmt4emJPbmQxWGNjdEJFN2Z1VDdrWXhoeSs3WXYrUTJwVy9BYmh6NGlHOEY1MW9GMGZwV0czCmlISDhsVXZFTkp2SUZEVHZ0UEpESlFZalBRN3lUbGlGZUdrMXZUQkcyQkpQNExzVzhpbDZOeUFuRktaY1hOQ24KeHVCendiSlJBb0dCQVBUK0dGTVJGRHRHZVl6NmwzZmg3UjJ0MlhrMysvUmpvR3BDUWREWDhYNERqR1pVd1RGVQpOS2tQTTNjS29ia2RBYlBDb3FpL0tOOVBibk9QVlZ3R3JkSE9vSnNibFVHYmJGamFTUzJQMFZnNUVhTC9rT2dUCmxMMUdoVFpIUWk1VUlMM0p4M1Z3T0ZRQ3RQOU1UQlQ0UEQvcEFLbDg3VTJXN3JTY1dGV1ZGbFNkQW9HQkFPOFUKVmhHWkRpVGFKTWVtSGZIdVYrNmtzaUlsam9aUVVzeGpmTGNMZ2NjV2RmTHBqS0ZWTzJNN3NqcEJEZ0w4NmFnegorVk14ZkQzZ1l0SmNWN01aMVcwNlZ6TlNVTHh3a1dRY1hXUWdDaXc5elpyYlhCUmZRNUVjMFBlblVoWWVwVzF5CkpkTC8rSlpQeDJxSzVrQytiWU5EdmxlNWdpcjlDSGVzTlR5enVyckRBb0dCQUl0cTJnN1RaazhCSVFUUVNrZ24Kb3BkRUtzRW4wZExXcXlBdENtVTlyaWpHL2l2eHlXczMveXZDQWNpWm5VVEp0QUZISHVlbXVTeXplQ2g5QmRkegoyWkRPNUdqQVBxVHlQS3NudFlNZkY4UDczZ1NES1VSWWVFbHFDejdET0c5QzRzcitPK3FoN1B3cCtqUmFoK1ZiCkNuWllNMDlBVDQ3YStJYUJmbWRkaXpLbEFvR0JBSmo1dkRDNmJIQnNISWlhNUNJL1RZaG5YWXUzMkVCYytQM0sKMHF3VThzOCtzZTNpUHBla2Y4RjVHd3RuUU4zc2tsMk1GQWFGYldmeVFZazBpUEVTb0p1cGJzNXA1enNNRkJ1bwpncUZrVnQ0RUZhRDJweTVwM2tQbDJsZjhlZXVwWkZScGE0WmRQdVIrMjZ4eWYrNEJhdlZJeld3NFNPL1V4Q3crCnhqbTNEczRkQW9HQWREL0VOa1BjU004c1BCM3JSWW9MQ2twcUV2U0MzbVZSbjNJd3c1WFAwcDRRVndhRmR1ckMKYUhtSE1EekNrNEUvb0haQVhFdGZ2S2tRaUI4MXVYM2c1aVo4amdYUVhXUHRteTVIcVVhcWJYUTlENkxWc3B0egpKL3R4SWJLMXp5c1o2bk9IY1VoUUwyVVF6SlBBRThZNDdjYzVzTThEN3kwZjJ0QURTQUZNMmN3PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ==", // "Salt":"4kk02v0NIcGtlobZ/xkxqWz8uH/ams/gjvQm14QT0dI=", // "DHKeyPrivate":"eyJWYWx1ZSI6NDU2MDgzOTEzMjA0OTIyODA5Njg2MDI3MzQ0MzM3OTA0MzAyODYwMjM2NDk2NDM5NDI4NTcxMTMwNDMzOTQwMzgyMTIyMjY4OTQzNTMyMjIyMzc1MTkzNTEzMjU4MjA4MDA0NTczMDY4MjEwNzg2NDI5NjA1MjA0OTA3MjI2ODI5OTc3NTczMDkxODY0NTY3NDExMDExNjQxNCwiRmluZ2VycHJpbnQiOjE2ODAxNTQxNTExMjMzMDk4MzYzfQ==" -// } +// "E2eGrp": "eyJnZW4iOiIyIiwicHJpbWUiOiJlMmVlOTgzZDAzMWRjMWRiNmYxYTdhNjdkZjBlOWE4ZTU1NjFkYjhlOGQ0OTQxMzM5NGMwNDliN2E4YWNjZWRjMjk4NzA4ZjEyMTk1MWQ5Y2Y5MjBlYzVkMTQ2NzI3YWE0YWU1MzViMDkyMmM2ODhiNTViM2RkMmFlZGY2YzAxYzk0NzY0ZGFiOTM3OTM1YWE4M2JlMzZlNjc3NjA3MTNhYjQ0YTYzMzdjMjBlNzg2MTU3NWU3NDVkMzFmOGI5ZTlhZDg0MTIxMThjNjJhM2UyZTI5ZGY0NmIwODY0ZDBjOTUxYzM5NGE1Y2JiZGM2YWRjNzE4ZGQyYTNlMDQxMDIzZGJiNWFiMjNlYmI0NzQyZGU5YzE2ODdiNWIzNGZhNDhjMzUyMTYzMmM0YTUzMGU4ZmZiMWJjNTFkYWRkZjQ1M2IwYjI3MTdjMmJjNjY2OWVkNzZiNGJkZDVjOWZmNTU4ZTg4ZjI2ZTU3ODUzMDJiZWRiY2EyM2VhYzVhY2U5MjA5NmVlOGE2MDY0MmZiNjFlOGYzZDI0OTkwYjhjYjEyZWU0NDhlZWY3OGUxODRjNzI0MmRkMTYxYzc3MzhmMzJiZjI5YTg0MTY5ODk3ODgyNWI0MTExYjRiYzNlMWUxOTg0NTUwOTU5NTgzMzNkNzc2ZDhiMmJlZWVkM2ExYTFhMjIxYTZlMzdlNjY0YTY0YjgzOTgxYzQ2ZmZkZGMxYTQ1ZTNkNTIxMWFhZjhiZmJjMDcyNzY4YzRmNTBkN2Q3ODAzZDJkNGYyNzhkZTgwMTRhNDczMjM2MzFkN2UwNjRkZTgxYzBjNmJmYTQzZWYwZTY5OTg4NjBmMTM5MGI1ZDNmZWFjYWYxNjk2MDE1Y2I3OWMzZjljMmQ5M2Q5NjExMjBjZDBlNWYxMmNiYjY4N2VhYjA0NTI0MWY5Njc4OWMzOGU4OWQ3OTYxMzhlNjMxOWJlNjJlMzVkODdiMTA0OGNhMjhiZTM4OWI1NzVlOTk0ZGNhNzU1NDcxNTg0YTA5ZWM3MjM3NDJkYzM1ODczODQ3YWVmNDlmNjZlNDM4NzMifQ==" +// } type ReceptionIdentity struct { ID []byte // User ID (base64) RSAPrivatePem []byte // RSA Private key (PEM format) Salt []byte // Salt for identity (base64) DHKeyPrivate []byte // DH Private key + E2eGrp []byte } // StoreReceptionIdentity stores the given identity in Cmix storage with the -// given key. This is the ideal way to securely store identities, as the caller +// given key. This is the ideal way to securely store identities, as the caller // of this function is only required to store the given key separately rather // than the keying material. func StoreReceptionIdentity(key string, identity []byte, cmixId int) error { @@ -77,7 +79,8 @@ func (c *Cmix) MakeReceptionIdentity() ([]byte, error) { } // MakeLegacyReceptionIdentity generates the legacy identity for receiving -// messages. +// messages. As with all legacy calls, this should primarily be used +// for the xx messenger team. func (c *Cmix) MakeLegacyReceptionIdentity() ([]byte, error) { ident, err := xxdk.MakeLegacyReceptionIdentity(c.api) if err != nil { @@ -90,17 +93,23 @@ func (c *Cmix) MakeLegacyReceptionIdentity() ([]byte, error) { // GetReceptionRegistrationValidationSignature returns the signature provided by // the xx network. func (c *Cmix) GetReceptionRegistrationValidationSignature() []byte { - return c.api.GetStorage().GetReceptionRegistrationValidationSignature() + regSig := c.api.GetStorage().GetReceptionRegistrationValidationSignature() + return regSig } //////////////////////////////////////////////////////////////////////////////// // Contact Functions // //////////////////////////////////////////////////////////////////////////////// -// GetIDFromContact accepts a marshalled contact.Contact object and returns a -// marshalled id.ID object. -func GetIDFromContact(marshaled []byte) ([]byte, error) { - cnt, err := contact.Unmarshal(marshaled) +// GetIDFromContact returns the ID in the [contact.Contact] object. +// +// Parameters: +// - marshaledContact - JSON marshalled bytes of [contact.Contact] +// +// Returns: +// - []byte - bytes of the [id.ID] object +func GetIDFromContact(marshaledContact []byte) ([]byte, error) { + cnt, err := contact.Unmarshal(marshaledContact) if err != nil { return nil, err } @@ -108,10 +117,16 @@ func GetIDFromContact(marshaled []byte) ([]byte, error) { return cnt.ID.Marshal(), nil } -// GetPubkeyFromContact accepts a marshalled contact.Contact object and returns -// a JSON marshalled large.Int DH public key. -func GetPubkeyFromContact(marshaled []byte) ([]byte, error) { - cnt, err := contact.Unmarshal(marshaled) +// GetPubkeyFromContact returns the DH public key in the [contact.Contact] +// object. +// +// Parameters: +// - marshaledContact - JSON marshalled bytes of [contact.Contact] +// +// Returns: +// - []byte - JSON marshalled bytes of the [cyclic.Int] object +func GetPubkeyFromContact(marshaledContact []byte) ([]byte, error) { + cnt, err := contact.Unmarshal(marshaledContact) if err != nil { return nil, err } @@ -123,67 +138,44 @@ func GetPubkeyFromContact(marshaled []byte) ([]byte, error) { // Fact Functions // //////////////////////////////////////////////////////////////////////////////// -// Fact is an internal fact type for use in the bindings layer. -// -// JSON example: -// { -// "Fact": "Zezima", -// "Type": 0 -// } -type Fact struct { - Fact string - Type int -} - // SetFactsOnContact replaces the facts on the contact with the passed in facts // pass in empty facts in order to clear the facts. // // Parameters: -// - marshaled - JSON marshalled contact.Contact object -// - facts - JSON marshalled Fact object. -func SetFactsOnContact(marshaled []byte, facts []byte) ([]byte, error) { - cnt, err := contact.Unmarshal(marshaled) +// - marshaledContact - the JSON marshalled bytes of [contact.Contact] +// - factListJSON - the JSON marshalled bytes of [fact.FactList] +// +// Returns: +// - []byte - marshalled bytes of the modified [contact.Contact] +func SetFactsOnContact(marshaledContact []byte, factListJSON []byte) ([]byte, error) { + cnt, err := contact.Unmarshal(marshaledContact) if err != nil { return nil, err } - factsList := make([]Fact, 0) - err = json.Unmarshal(facts, &factsList) + var factsList fact.FactList + err = json.Unmarshal(factListJSON, &factsList) if err != nil { return nil, err } - realFactList := make(fact.FactList, 0, len(factsList)) - for i := range factsList { - realFactList = append(realFactList, fact.Fact{ - Fact: factsList[i].Fact, - T: fact.FactType(factsList[i].Type), - }) - } + cnt.Facts = factsList - cnt.Facts = realFactList return cnt.Marshal(), nil } -// GetFactsFromContact accepts a marshalled contact.Contact object and returns -// its marshalled list of Fact objects. -func GetFactsFromContact(marshaled []byte) ([]byte, error) { - cnt, err := contact.Unmarshal(marshaled) +// GetFactsFromContact returns the fact list in the [contact.Contact] object. +// +// Parameters: +// - marshaledContact - the JSON marshalled bytes of [contact.Contact] +// +// Returns: +// - []byte - the JSON marshalled bytes of [fact.FactList] +func GetFactsFromContact(marshaledContact []byte) ([]byte, error) { + cnt, err := contact.Unmarshal(marshaledContact) if err != nil { return nil, err } - factsList := make([]Fact, len(cnt.Facts)) - for i := range cnt.Facts { - factsList = append(factsList, Fact{ - Fact: cnt.Facts[i].Fact, - Type: int(cnt.Facts[i].T), - }) - } - - factsListMarshaled, err := json.Marshal(&factsList) - if err != nil { - return nil, err - } - return factsListMarshaled, nil + return json.Marshal(&cnt.Facts) } diff --git a/bindings/identity_test.go b/bindings/identity_test.go index 662f1f5c000021def40a17a50d9c9646b8a78779..eeff0b1a83edb91a79526f4b7e4fb225fe9174a0 100644 --- a/bindings/identity_test.go +++ b/bindings/identity_test.go @@ -1,16 +1,14 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package bindings import ( "encoding/json" - "testing" - "gitlab.com/elixxir/crypto/cmix" "gitlab.com/elixxir/crypto/cyclic" dh "gitlab.com/elixxir/crypto/diffieHellman" @@ -18,6 +16,7 @@ import ( "gitlab.com/xx_network/crypto/large" "gitlab.com/xx_network/crypto/signature/rsa" "gitlab.com/xx_network/primitives/id" + "testing" ) func TestIdentity_JSON(t *testing.T) { @@ -29,34 +28,21 @@ func TestIdentity_JSON(t *testing.T) { dhpk := dh.GeneratePrivateKey(64, grp, rng) dhpkJson, _ := dhpk.MarshalJSON() op := make([]byte, 64) + e2eGrp, _ := getGroup().MarshalJSON() _, _ = rng.Read(op) identity := ReceptionIdentity{ ID: uid.Marshal(), RSAPrivatePem: rsa.CreatePrivateKeyPem(pk), Salt: salt, DHKeyPrivate: dhpkJson, + E2eGrp: e2eGrp, } + im, _ := json.Marshal(identity) t.Log("Marshalled ReceptionIdentity object") t.Log(string(im)) } -func TestFacts_JSON(t *testing.T) { - fl := []Fact{ - { - Fact: "Zezima", - Type: 0, - }, - { - Fact: "Zezima@osrs.org", - Type: 2, - }, - } - flm, _ := json.Marshal(fl) - t.Log("Marshalled []Fact") - t.Log(string(flm)) -} - func getGroup() *cyclic.Group { return cyclic.NewGroup( large.NewIntFromString("E2EE983D031DC1DB6F1A7A67DF0E9A8E5561DB8E8D4941"+ diff --git a/bindings/listener.go b/bindings/listener.go index c19bca2fd3d1dfa72608f51b60c474f64cfa7b24..8eaf0faff2e58bb188a9451f624d2eae1926bd9c 100644 --- a/bindings/listener.go +++ b/bindings/listener.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package bindings @@ -62,6 +62,7 @@ type Message struct { Encrypted bool RoundId int + RoundURL string } // Hear is called to receive a message in the UI. @@ -76,6 +77,7 @@ func (l listener) Hear(item receive.Message) { Timestamp: item.Timestamp.UnixNano(), Encrypted: item.Encrypted, RoundId: int(item.Round.ID), + RoundURL: getRoundURL(item.Round.ID), } result, err := json.Marshal(&m) if err != nil { diff --git a/bindings/listener_test.go b/bindings/listener_test.go index 92276c186e1d30ac8d91785df3a1ab8839cf0746..e06dd2b549a84ec650129158575ede3966036fa7 100644 --- a/bindings/listener_test.go +++ b/bindings/listener_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package bindings diff --git a/bindings/logging.go b/bindings/logging.go index 6783d4b546f293862863110a85b16791dbf88baa..9b609f103e8d59e79b7ac5e8e2099d5cd1056b1b 100644 --- a/bindings/logging.go +++ b/bindings/logging.go @@ -1,16 +1,15 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// // logging.go contains bindings log control functions package bindings import ( - "fmt" "log" "github.com/pkg/errors" @@ -34,7 +33,7 @@ import ( // The default log level without updates is INFO. func LogLevel(level int) error { if level < 0 || level > 6 { - return errors.New(fmt.Sprintf("log level is not valid: log level: %d", level)) + return errors.Errorf("log level is not valid: log level: %d", level) } threshold := jww.Threshold(level) diff --git a/bindings/ndf.go b/bindings/ndf.go index eb6a5c87d7c33ee968c6d005cb10ab96e7026968..605d5fa7ec6abdab136410893c14f5f06ff034f3 100644 --- a/bindings/ndf.go +++ b/bindings/ndf.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package bindings diff --git a/bindings/ndf_test.go b/bindings/ndf_test.go index c453582b5d7eccee053de6f4d60cae5a345af3ed..5c565bb4b3965567b553bfd393b1a8fab8a102be 100644 --- a/bindings/ndf_test.go +++ b/bindings/ndf_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package bindings diff --git a/bindings/notifications.go b/bindings/notifications.go new file mode 100644 index 0000000000000000000000000000000000000000..217accf1163a6d12d426a0ebd90f6902f9e05244 --- /dev/null +++ b/bindings/notifications.go @@ -0,0 +1,171 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + +package bindings + +import ( + "encoding/json" + "gitlab.com/elixxir/client/cmix/message" + "gitlab.com/elixxir/primitives/notifications" +) + +// NotificationReports is a list of [NotificationReport]s. This will be returned +// via GetNotificationsReport as a JSON marshalled byte data. +// +// Example JSON: +// [ +// { +// "ForMe": true, // boolean +// "Type": "e2e", // string +// "Source": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD" // bytes of id.ID encoded as base64 string +// }, +// { +// "ForMe": true, +// "Type": "e2e", +// "Source": "AAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD" +// }, +// { +// "ForMe": true, +// "Type": "e2e", +// "Source": "AAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD" +// } +// ] +type NotificationReports []NotificationReport + +// TODO: The table in the docstring below needs to be checked for completeness +// and/or accuracy to ensure descriptions/sources are still accurate (they are +// from the old implementation). + +// NotificationReport is the bindings' representation for notifications for +// this user. +// +// Example NotificationReport JSON: +// { +// "ForMe": true, +// "Type": "e2e", +// "Source": "dGVzdGVyMTIzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +// } +// +// Given the Type, the Source value will have specific contextual meanings. +// Below is a table that will define the contextual meaning of the Source field +// given all possible Type fields. +// +// TYPE | SOURCE | DESCRIPTION +// ----------+--------------------+-------------------------------------------------------- +// "default" | recipient user ID | A message with no association. +// "request" | sender user ID | A channel request has been received, from Source. +// "reset" | sender user ID | A channel reset has been received. +// "confirm" | sender user ID | A channel request has been accepted. +// "silent" | sender user ID | A message where the user should not be notified. +// "e2e" | sender user ID | A reception of an E2E message. +// "group" | group ID | A reception of a group chat message. +// "endFT" | sender user ID | The last message sent confirming end of file transfer. +// "groupRQ" | sender user ID | A request from Source to join a group chat. +type NotificationReport struct { + // ForMe determines whether this value is for the user. If it is + // false, this report may be ignored. + ForMe bool + // Type is the type of notification. The list can be seen + Type string + // Source is the source of the notification. + Source []byte +} + +// GetNotificationsReport parses the received notification data to determine which +// notifications are for this user. // This returns the JSON-marshalled +// NotificationReports. +// +// Parameters: +// - e2eID - e2e object ID in the tracker +// - notificationCSV - the notification data received from the +// notifications' server. +// - marshalledServices - the JSON-marshalled list of services the backend +// keeps track of. Refer to Cmix.TrackServices for information about this. +// +// Returns: +// - []byte - A JSON marshalled NotificationReports. Some NotificationReport's +// within in this structure may have their NotificationReport.ForMe +// set to false. These may be ignored. +func GetNotificationsReport(e2eId int, notificationCSV string, + marshalledServices []byte) ([]byte, error) { + // Retrieve user + user, err := e2eTrackerSingleton.get(e2eId) + if err != nil { + return nil, err + } + + serviceList := message.ServiceList{} + err = json.Unmarshal(marshalledServices, &serviceList) + if err != nil { + return nil, err + } + + // Retrieve the services for this user + services := serviceList[*user.api.GetReceptionIdentity().ID] + + // Decode notifications' server data + notificationList, err := notifications.DecodeNotificationsCSV(notificationCSV) + if err != nil { + return nil, err + } + + // Construct a report list + reportList := make([]*NotificationReport, len(notificationList)) + + // Iterate over data provided by server + for i := range notificationList { + notifData := notificationList[i] + + // Iterate over all services + for j := range services { + // Pull data from services and from notification data + service := services[j] + messageHash := notifData.MessageHash + hash := service.HashFromMessageHash(notifData.MessageHash) + + // Check if this notification data is recognized by + // this service, ie "ForMe" + if service.ForMeFromMessageHash(messageHash, hash) { + // Fill report list with service data + reportList[i] = &NotificationReport{ + ForMe: true, + Type: service.Tag, + Source: service.Identifier, + } + } + } + } + + return json.Marshal(reportList) +} + +// RegisterForNotifications allows a client to register for push notifications. +// The token is a firebase messaging token. +// +// Parameters: +// - e2eId - ID of the E2E object in the E2E tracker +func RegisterForNotifications(e2eId int, token string) error { + user, err := e2eTrackerSingleton.get(e2eId) + if err != nil { + return err + } + + return user.api.RegisterForNotifications(token) +} + +// UnregisterForNotifications turns off notifications for this client. +// +// Parameters: +// - e2eId - ID of the E2E object in the E2E tracker +func UnregisterForNotifications(e2eId int) error { + user, err := e2eTrackerSingleton.get(e2eId) + if err != nil { + return err + } + + return user.api.UnregisterForNotifications() +} diff --git a/bindings/notifications_test.go b/bindings/notifications_test.go new file mode 100644 index 0000000000000000000000000000000000000000..91d2974593719c9094def579d34b74a01325ac74 --- /dev/null +++ b/bindings/notifications_test.go @@ -0,0 +1,35 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + +package bindings + +import ( + "encoding/json" + "fmt" + "gitlab.com/elixxir/client/e2e/ratchet" + "gitlab.com/xx_network/primitives/id" + "testing" +) + +func TestNotificationReport(t *testing.T) { + reports := []NotificationReport{} + + for i := 0; i < 3; i++ { + nr := NotificationReport{ + ForMe: true, + Type: ratchet.E2e, + Source: id.NewIdFromUInt(uint64(i), id.User, t).Bytes(), + } + + reports = append(reports, nr) + } + + nrs := NotificationReports(reports) + + marshal, _ := json.Marshal(nrs) + fmt.Printf("%s\n", marshal) +} diff --git a/bindings/params.go b/bindings/params.go index 2b0cdd18c82d16c2a7a3f0b5570532d26bf87b23..f44c71edd2a13c0ae59a928f276619c43a2c1a2e 100644 --- a/bindings/params.go +++ b/bindings/params.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// // params.go provides functions for getting and setting parameters in bindings. @@ -66,8 +66,8 @@ func GetDefaultSingleUseParams() []byte { } // GetDefaultE2eFileTransferParams returns a JSON serialized object with all the -// e2e file transfer parameters and their default values. Call this function and modify -// the JSON to change single use settings. +// E2E file transfer parameters and their default values. Call this function and +// modify the JSON to change single use settings. func GetDefaultE2eFileTransferParams() []byte { defaultParams := e2eFileTransfer.DefaultParams() data, err := defaultParams.MarshalJSON() @@ -77,27 +77,42 @@ func GetDefaultE2eFileTransferParams() []byte { return data } +// parseE2eFileTransferParams is a helper function which parses a JSON +// marshalled [e2eFileTransfer.Params]. func parseE2eFileTransferParams(data []byte) (e2eFileTransfer.Params, error) { p := &e2eFileTransfer.Params{} return *p, p.UnmarshalJSON(data) } +// parseSingleUseParams is a helper function which parses a JSON marshalled +// [single.RequestParams]. func parseSingleUseParams(data []byte) (single.RequestParams, error) { p := &single.RequestParams{} return *p, p.UnmarshalJSON(data) } +// parseFileTransferParams is a helper function which parses a JSON marshalled +// [fileTransfer.Params]. func parseFileTransferParams(data []byte) (fileTransfer.Params, error) { p := &fileTransfer.Params{} return *p, p.UnmarshalJSON(data) } +// parseCMixParams is a helper function which parses a JSON marshalled +// [xxdk.CMIXParams]. func parseCMixParams(data []byte) (xxdk.CMIXParams, error) { + if len(data) == 0 { + jww.WARN.Printf("cMix params not specified, using defaults...") + data = GetDefaultCMixParams() + } + p := &xxdk.CMIXParams{} err := p.Unmarshal(data) return *p, err } +// parseE2EParams is a helper function which parses a JSON marshalled +// [xxdk.E2EParams]. func parseE2EParams(data []byte) (xxdk.E2EParams, error) { p := &xxdk.E2EParams{} err := p.Unmarshal(data) diff --git a/bindings/restlike.go b/bindings/restlike.go index e3c87e1d8279f60833ae91a8e49f32597fcf8352..bebe90bc88fe54f8d8f35c652f67830b3259562d 100644 --- a/bindings/restlike.go +++ b/bindings/restlike.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package bindings @@ -107,7 +107,7 @@ func RestlikeRequest( // // Returns: // - []byte - JSON marshalled RestlikeMessage -func RestlikeRequestAuth(cmixId int, authConnectionID int, request, +func RestlikeRequestAuth(cmixId, authConnectionID int, request, e2eParamsJSON []byte) ([]byte, error) { if len(e2eParamsJSON) == 0 { jww.WARN.Printf("restlike params unspecified, using defaults") diff --git a/bindings/restlikeSingle.go b/bindings/restlikeSingle.go index 76431501a3f9393b8e954ca81ac0d9f004653ba9..c71d0e05b4c02f74354957671e40f0f642565bdb 100644 --- a/bindings/restlikeSingle.go +++ b/bindings/restlikeSingle.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package bindings diff --git a/bindings/secrets.go b/bindings/secrets.go index 6086282de043b535a769a6c5e5a5c788a156a081..41f16598dc7b283c59bf1da2a6d1189c5b49fc94 100644 --- a/bindings/secrets.go +++ b/bindings/secrets.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package bindings diff --git a/bindings/secrets_test.go b/bindings/secrets_test.go index 60b03a2d42b8b564e4dbf134aab92c4cf189e401..41e590ec756bc1f4eb2981a2df44995d10b2c861 100644 --- a/bindings/secrets_test.go +++ b/bindings/secrets_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package bindings diff --git a/bindings/single.go b/bindings/single.go index bb1efe57b0821fb1f1445c0fbf06ae7ce8ec666a..d6625cd71d8fe027fa2a64ca1b146d30e6f6eef0 100644 --- a/bindings/single.go +++ b/bindings/single.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package bindings @@ -62,14 +62,15 @@ func TransmitSingleUse(e2eID int, recipient []byte, tag string, payload, } sr := SingleUseSendReport{ EphID: eid.EphId.Int64(), - ReceptionID: eid.Source.Marshal(), + ReceptionID: eid.Source, RoundsList: makeRoundsList(rids...), + RoundURL: getRoundURL(rids[0]), } return json.Marshal(sr) } -// Listen starts a single-use listener on a given tag using the passed in e2e object -// and SingleUseCallback func. +// Listen starts a single-use listener on a given tag using the passed in E2e +// object and SingleUseCallback func. // // Parameters: // - e2eID - ID of the e2e object in the tracker @@ -85,11 +86,11 @@ func Listen(e2eID int, tag string, cb SingleUseCallback) (Stopper, error) { } suListener := singleUseListener{scb: cb} - dhpk, err := e2eCl.api.GetReceptionIdentity().GetDHKeyPrivate() + dhPk, err := e2eCl.api.GetReceptionIdentity().GetDHKeyPrivate() if err != nil { return nil, err } - l := single.Listen(tag, e2eCl.api.GetReceptionIdentity().ID, dhpk, + l := single.Listen(tag, e2eCl.api.GetReceptionIdentity().ID, dhPk, e2eCl.api.GetCmix(), e2eCl.api.GetStorage().GetE2EGroup(), suListener) return &stopper{l: l}, nil } @@ -99,15 +100,17 @@ func Listen(e2eID int, tag string, cb SingleUseCallback) (Stopper, error) { // SingleUseSendReport is the bindings-layer struct used to represent // information returned by single.TransmitRequest. // -// JSON example: +// SingleUseSendReport JSON example: // { // "Rounds":[1,5,9], -// "EphID":{"EphId":[0,0,0,0,0,0,3,89], -// "Source":"emV6aW1hAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD"} +// "RoundURL": "https://dashboard.xx.network/rounds/25?xxmessenger=true", +// "EphID":1655533, +// "ReceptionID":"emV6aW1hAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD"} // } type SingleUseSendReport struct { RoundsList - ReceptionID []byte + RoundURL string + ReceptionID *id.ID EphID int64 } @@ -115,18 +118,20 @@ type SingleUseSendReport struct { // information passed to the single.Response callback interface in response to // single.TransmitRequest. // -// JSON example: +// SingleUseResponseReport JSON example: // { // "Rounds":[1,5,9], +// "RoundURL": "https://dashboard.xx.network/rounds/25?xxmessenger=true", // "Payload":"rSuPD35ELWwm5KTR9ViKIz/r1YGRgXIl5792SF8o8piZzN6sT4Liq4rUU/nfOPvQEjbfWNh/NYxdJ72VctDnWw==", -// "ReceptionID":{"EphId":[0,0,0,0,0,0,3,89], -// "Source":"emV6aW1hAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD"}, -// "Err":null +// "EphID":1655533, +// "ReceptionID":"emV6aW1hAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD"}, +// "Err":"", // } type SingleUseResponseReport struct { RoundsList + RoundURL string Payload []byte - ReceptionID []byte + ReceptionID *id.ID EphID int64 Err error } @@ -134,27 +139,30 @@ type SingleUseResponseReport struct { // SingleUseCallbackReport is the bindings-layer struct used to represent // single -use messages received by a callback passed into single.Listen. // -// JSON example: -// { -// "Rounds":[1,5,9], -// "Payload":"rSuPD35ELWwm5KTR9ViKIz/r1YGRgXIl5792SF8o8piZzN6sT4Liq4rUU/nfOPvQEjbfWNh/NYxdJ72VctDnWw==", -// "Partner":"emV6aW1hAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD", -// "EphID":{"EphId":[0,0,0,0,0,0,3,89], -// "Source":"emV6aW1hAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD"} -// } +// SingleUseCallbackReport JSON example: +// { +// "Rounds":[1,5,9], +// "RoundURL": "https://dashboard.xx.network/rounds/25?xxmessenger=true", +// "Payload":"rSuPD35ELWwm5KTR9ViKIz/r1YGRgXIl5792SF8o8piZzN6sT4Liq4rUU/nfOPvQEjbfWNh/NYxdJ72VctDnWw==", +// "Partner":"emV6aW1hAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD", +// "EphID":1655533, +// "ReceptionID":"emV6aW1hAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD"} +// } type SingleUseCallbackReport struct { RoundsList + RoundURL string Payload []byte Partner *id.ID EphID int64 - ReceptionID []byte + ReceptionID *id.ID } //////////////////////////////////////////////////////////////////////////////// // Function Types // //////////////////////////////////////////////////////////////////////////////// -// Stopper is a public interface returned by Listen, allowing users to stop the registered listener. +// Stopper is a public interface returned by Listen, allowing users to stop the +// registered listener. type Stopper interface { Stop() } @@ -164,8 +172,8 @@ type Stopper interface { // // Parameters: // - callbackReport - the JSON marshalled bytes of the SingleUseCallbackReport -// object, which can be passed into WaitForRoundResult to see if the send -// succeeded. +// object, which can be passed into Cmix.WaitForRoundResult to see if the +// send operation succeeded. type SingleUseCallback interface { Callback(callbackReport []byte, err error) } @@ -175,8 +183,8 @@ type SingleUseCallback interface { // // Parameters: // - callbackReport - the JSON marshalled bytes of the SingleUseResponseReport -// object, which can be passed into WaitForRoundResult to see if the send -// succeeded. +// object, which can be passed into Cmix.WaitForRoundResult to see if the +// send operation succeeded. type SingleUseResponse interface { Callback(responseReport []byte, err error) } @@ -207,9 +215,10 @@ func (sl singleUseListener) Callback( scr := SingleUseCallbackReport{ Payload: req.GetPayload(), RoundsList: makeRoundsList(rids...), + RoundURL: getRoundURL(rids[0]), Partner: req.GetPartner(), EphID: eid.EphId.Int64(), - ReceptionID: eid.Source.Marshal(), + ReceptionID: eid.Source, } sl.scb.Callback(json.Marshal(scr)) @@ -245,7 +254,8 @@ func (sr singleUseResponse) Callback(payload []byte, } sendReport := SingleUseResponseReport{ RoundsList: makeRoundsList(rids...), - ReceptionID: receptionID.Source.Marshal(), + RoundURL: getRoundURL(rids[0]), + ReceptionID: receptionID.Source, EphID: receptionID.EphId.Int64(), Payload: payload, Err: err, diff --git a/bindings/single_test.go b/bindings/single_test.go index a262a40738afe4ce73fc565ddaf259663f9d3a2e..1f34d616f3af0e447b472e6675472f800131babf 100644 --- a/bindings/single_test.go +++ b/bindings/single_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package bindings @@ -36,7 +36,7 @@ func TestSingleUseJsonMarshals(t *testing.T) { sendReport := SingleUseSendReport{ RoundsList: rl, EphID: ephId.EphId.Int64(), - ReceptionID: ephId.Source.Marshal(), + ReceptionID: ephId.Source, } srm, err := json.Marshal(sendReport) if err != nil { @@ -48,7 +48,7 @@ func TestSingleUseJsonMarshals(t *testing.T) { responseReport := SingleUseResponseReport{ RoundsList: rl, Payload: payload, - ReceptionID: ephId.Source.Marshal(), + ReceptionID: ephId.Source, EphID: ephId.EphId.Int64(), Err: nil, } @@ -64,7 +64,7 @@ func TestSingleUseJsonMarshals(t *testing.T) { Payload: payload, Partner: rid, EphID: ephId.EphId.Int64(), - ReceptionID: ephId.Source.Marshal(), + ReceptionID: ephId.Source, } crm, err := json.Marshal(callbackReport) if err != nil { diff --git a/bindings/ud.go b/bindings/ud.go index 6ce8f8b3af073057e210675ff3203ef5ba364746..976321c5b33b5fd964b37dfd4c3aa5e97be66cac 100644 --- a/bindings/ud.go +++ b/bindings/ud.go @@ -1,14 +1,15 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package bindings import ( "encoding/json" + "fmt" "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/single" @@ -105,34 +106,77 @@ type UdNetworkStatus interface { // Manager functions // //////////////////////////////////////////////////////////////////////////////// -// NewOrLoadUd loads an existing Manager from storage or creates a -// new one if there is no extant storage information. Parameters need be provided -// to specify how to connect to the User Discovery service. These parameters may be used -// to contact either the UD server hosted by the xx network team or a custom -// third-party operated server. For the former, all the information may be pulled from the -// NDF using the bindings. +// IsRegisteredWithUD is a function which checks the internal state +// files to determine if a user has registered with UD in the past. +// +// Parameters: +// - e2eID - REQUIRED. The tracked e2e object ID. This can be retrieved using [E2e.GetID]. +// +// Returns: +// - bool - A boolean representing true if the user has been registered with UD already +// or false if it has not been registered already. +// - error - An error should only be returned if the internal tracker failed to retrieve an +// E2e object given the e2eId. If an error was returned, the registration state check +// was not performed properly, and the boolean returned should be ignored. +func IsRegisteredWithUD(e2eId int) (bool, error) { + + // Get user from singleton + user, err := e2eTrackerSingleton.get(e2eId) + if err != nil { + return false, err + } + + return ud.IsRegistered(user.api.GetStorage().GetKV()), nil +} + +// NewOrLoadUd loads an existing UserDiscovery from storage or creates a new +// UserDiscovery if there is no storage data. Regardless of storage state, +// the UserDiscovery object returned will be registered with the +// User Discovery service. If the user is not already registered, a call +// to register will occur internally. If the user is already registered, +// this call will simply load state and return to you a UserDiscovery object. +// Some parameters are required for registering with the service, but are not required +// if the user is already registered. These will be noted in the parameters section as +// "SEMI-REQUIRED". +// +// Certain parameters are required every call to this function. These parameters are listed below +// as "REQUIRED". For example, parameters need be provided to specify how to connect to the +// User Discovery service. These parameters specifically may be used to contact either the UD +// server hosted by the xx network team or a custom third-party operated server. For the former, +// all the information may be fetched from the NDF using the bindings. These fetch +// methods are detailed in the parameters section. // // Params -// - e2eID - e2e object ID in the tracker -// - follower - network follower func wrapped in UdNetworkStatus -// - username - the username the user wants to register with UD. -// If the user is already registered, this field may be blank -// - networkValidationSig is a signature provided by the network (i.e. the client registrar). -// This may be nil, however UD may return an error in some cases (e.g. in a production level -// environment). -// - cert is the TLS certificate for the UD server this call will connect with. -// You may use the UD server run by the xx network team by using E2e.GetUdCertFromNdf. -// - contactFile is the data within a marshalled contact.Contact. This represents the +// - e2eID - REQUIRED. The tracked e2e object ID. This is returned by [E2e.GetID]. +// - follower - REQUIRED. Network follower function. This will check if the network +// follower is running. +// - username - SEMI-REQUIRED. The username the user wants to register with UD. +// If the user is already registered, this field may be blank. If the user is not +// already registered, these field must be populated with a username that meets the +// requirements of the UD service. For example, in the xx network's UD service, +// the username must not be registered by another user. +// - registrationValidationSignature - SEMI-REQUIRED. A signature provided by the xx network +// (i.e. the client registrar). If the user is not already registered, this field is required +// in order to register with the xx network. This may be nil if the user is already registered +// or connecting to a third-party UD service unassociated with the xx network. +// - cert - REQUIRED. The TLS certificate for the UD server this call will connect with. +// If this is nil, you may not contact the UD server hosted by the xx network. +// Third-party services may vary. +// You may use the UD server run by the xx network team by using [E2e.GetUdCertFromNdf]. +// - contactFile - REQUIRED. The data within a marshalled [contact.Contact]. This represents the // contact file of the server this call will connect with. -// You may use the UD server run by the xx network team by using E2e.GetUdContactFromNdf. -// - address is the IP address of the UD server this call will connect with. -// You may use the UD server run by the xx network team by using E2e.GetUdAddressFromNdf. +// If this is nil, you may not contact the UD server hosted by the xx network. +// Third-party services may vary. +// You may use the UD server run by the xx network team by using [E2e.GetUdContactFromNdf]. +// - address - REQUIRED. The IP address of the UD server this call will connect with. +// You may use the UD server run by the xx network team by using [E2e.GetUdAddressFromNdf]. +// If this is nil, you may not contact the UD server hosted by the xx network. +// Third-party services may vary. // // Returns // - A Manager object which is registered to the specified UD service. -func NewOrLoadUd(e2eID int, follower UdNetworkStatus, - username string, registrationValidationSignature, - cert, contactFile []byte, address string) ( +func NewOrLoadUd(e2eID int, follower UdNetworkStatus, username string, + registrationValidationSignature, cert, contactFile []byte, address string) ( *UserDiscovery, error) { // Get user from singleton @@ -165,17 +209,24 @@ func NewOrLoadUd(e2eID int, follower UdNetworkStatus, // Parameters: // - e2eID - e2e object ID in the tracker // - follower - network follower func wrapped in UdNetworkStatus -// - emailFactJson - nullable JSON marshalled email fact.Fact -// - phoneFactJson - nullable JSON marshalled phone fact.Fact -// - cert is the TLS certificate for the UD server this call will connect with. -// You may use the UD server run by the xx network team by using E2e.GetUdCertFromNdf. -// - contactFile is the data within a marshalled contact.Contact. This represents the -// contact file of the server this call will connect with. -// You may use the UD server run by the xx network team by using E2e.GetUdContactFromNdf. -// - address is the IP address of the UD server this call will connect with. -// You may use the UD server run by the xx network team by using E2e.GetUdAddressFromNdf. -func NewUdManagerFromBackup(e2eID int, follower UdNetworkStatus, emailFactJson, - phoneFactJson []byte, cert, contactFile []byte, address string) (*UserDiscovery, error) { +// - username - The username this user registered with initially. This should +// not be nullable, and be JSON marshalled as retrieved from +// UserDiscovery.GetFacts(). +// - emailFactJson - nullable JSON marshalled email [fact.Fact] +// - phoneFactJson - nullable JSON marshalled phone [fact.Fact] +// - cert - the TLS certificate for the UD server this call will connect with. +// You may use the UD server run by the xx network team by using +// E2e.GetUdCertFromNdf. +// - contactFile - the data within a marshalled contact.Contact. This +// represents the contact file of the server this call will connect with. You +// may use the UD server run by the xx network team by using +// E2e.GetUdContactFromNdf. +// - address - the IP address of the UD server this call will connect with. You +// may use the UD server run by the xx network team by using +// E2e.GetUdAddressFromNdf. +func NewUdManagerFromBackup(e2eID int, follower UdNetworkStatus, + usernameJson, emailFactJson, phoneFactJson, + cert, contactFile []byte, address string) (*UserDiscovery, error) { // Get user from singleton user, err := e2eTrackerSingleton.get(e2eID) @@ -183,7 +234,9 @@ func NewUdManagerFromBackup(e2eID int, follower UdNetworkStatus, emailFactJson, return nil, err } - var email, phone fact.Fact + var email, phone, username fact.Fact + + // Parse email if non-nil if emailFactJson != nil { err = json.Unmarshal(emailFactJson, &email) if err != nil { @@ -191,6 +244,7 @@ func NewUdManagerFromBackup(e2eID int, follower UdNetworkStatus, emailFactJson, } } + // Parse phone if non-nil if phoneFactJson != nil { err = json.Unmarshal(phoneFactJson, &phone) if err != nil { @@ -198,13 +252,19 @@ func NewUdManagerFromBackup(e2eID int, follower UdNetworkStatus, emailFactJson, } } + // Parse username + err = json.Unmarshal(usernameJson, &username) + if err != nil { + return nil, err + } + UdNetworkStatusFn := func() xxdk.Status { return xxdk.Status(follower.UdNetworkStatus()) } u, err := ud.NewManagerFromBackup( user.api, user.api.GetComms(), UdNetworkStatusFn, - email, phone, + username, email, phone, cert, contactFile, address) if err != nil { return nil, err @@ -213,7 +273,7 @@ func NewUdManagerFromBackup(e2eID int, follower UdNetworkStatus, emailFactJson, return udTrackerSingleton.make(u), nil } -// GetFacts returns a JSON marshalled list of fact.Fact objects that exist +// GetFacts returns a JSON marshalled list of [fact.Fact] objects that exist // within the Store's registeredFacts map. func (ud *UserDiscovery) GetFacts() []byte { jsonData, err := json.Marshal(ud.api.GetFacts()) @@ -229,9 +289,9 @@ func (ud *UserDiscovery) GetContact() ([]byte, error) { return ud.api.GetContact().Marshal(), nil } -// ConfirmFact confirms a fact first registered via AddFact. The confirmation ID -// comes from AddFact while the code will come over the associated -// communications system. +// ConfirmFact confirms a fact first registered via SendRegisterFact. The +// confirmation ID comes from SendRegisterFact while the code will come over the +// associated communications system. func (ud *UserDiscovery) ConfirmFact(confirmationID, code string) error { return ud.api.ConfirmFact(confirmationID, code) } @@ -246,7 +306,7 @@ func (ud *UserDiscovery) ConfirmFact(confirmationID, code string) error { // along with the code to finalize the fact. // // Parameters: -// - factJson - a JSON marshalled fact.Fact +// - factJson - a JSON marshalled [fact.Fact] func (ud *UserDiscovery) SendRegisterFact(factJson []byte) (string, error) { var f fact.Fact err := json.Unmarshal(factJson, &f) @@ -262,7 +322,7 @@ func (ud *UserDiscovery) SendRegisterFact(factJson []byte) (string, error) { // be associated with this user. // // Parameters: -// - factJson - a JSON marshalled fact.Fact +// - factJson - a JSON marshalled [fact.Fact] func (ud *UserDiscovery) PermanentDeleteAccount(factJson []byte) error { var f fact.Fact err := json.Unmarshal(factJson, &f) @@ -277,7 +337,7 @@ func (ud *UserDiscovery) PermanentDeleteAccount(factJson []byte) error { // passed in is not UD service does not associate this fact with this user. // // Parameters: -// - factJson - a JSON marshalled fact.Fact +// - factJson - a JSON marshalled [fact.Fact] func (ud *UserDiscovery) RemoveFact(factJson []byte) error { var f fact.Fact err := json.Unmarshal(factJson, &f) @@ -309,13 +369,14 @@ type UdLookupCallback interface { // Parameters: // - e2eID - e2e object ID in the tracker // - udContact - the marshalled bytes of the contact.Contact object -// - lookupId - the marshalled bytes of the id.ID object for the user -// that LookupUD will look up. +// - lookupId - the marshalled bytes of the id.ID object for the user that +// LookupUD will look up. // - singleRequestParams - the JSON marshalled bytes of single.RequestParams // // Returns: // - []byte - the JSON marshalled bytes of the SingleUseSendReport object, -// which can be passed into WaitForRoundResult to see if the send succeeded. +// which can be passed into Cmix.WaitForRoundResult to see if the send +// succeeded. func LookupUD(e2eID int, udContact []byte, cb UdLookupCallback, lookupId []byte, singleRequestParamsJSON []byte) ([]byte, error) { @@ -352,13 +413,141 @@ func LookupUD(e2eID int, udContact []byte, cb UdLookupCallback, sr := SingleUseSendReport{ EphID: eid.EphId.Int64(), - ReceptionID: eid.Source.Marshal(), + ReceptionID: eid.Source, RoundsList: makeRoundsList(rids...), + RoundURL: getRoundURL(rids[0]), } return json.Marshal(sr) } +//////////////////////////////////////////////////////////////////////////////// +// User Discovery MultiLookup // +//////////////////////////////////////////////////////////////////////////////// + +// UdMultiLookupCallback contains the callback called by MultiLookupUD that returns the +// contacts which match the passed in IDs. +// +// Parameters: +// - contactListJSON - the JSON marshalled bytes of []contact.Contact, or nil +// if an error occurs. +// +// JSON Example: +// { +// "<xxc(2)F8dL9EC6gy+RMJuk3R+Au6eGExo02Wfio5cacjBcJRwDEgB7Ugdw/BAr6RkCABkWAFV1c2VybmFtZTA7c4LzV05sG+DMt+rFB0NIJg==xxc>", +// "<xxc(2)eMhAi/pYkW5jCmvKE5ZaTglQb+fTo1D8NxVitr5CCFADEgB7Ugdw/BAr6RoCABkWAFV1c2VybmFtZTE7fElAa7z3IcrYrrkwNjMS2w==xxc>", +// "<xxc(2)d7RJTu61Vy1lDThDMn8rYIiKSe1uXA/RCvvcIhq5Yg4DEgB7Ugdw/BAr6RsCABkWAFV1c2VybmFtZTI7N3XWrxIUpR29atpFMkcR6A==xxc>" +// } +// - failedIDs - JSON marshalled list of []*id.ID objects which failed lookup +// - err - any errors that occurred in the multilookup. +type UdMultiLookupCallback interface { + Callback(contactListJSON []byte, failedIDs []byte, err error) +} + +type lookupResp struct { + id *id.ID + contact contact.Contact + err error +} + +// MultiLookupUD returns the public key of all passed in IDs as known by the +// user discovery system or returns by the timeout. +// +// Parameters: +// - e2eID - e2e object ID in the tracker +// - udContact - the marshalled bytes of the contact.Contact object +// - lookupIds - JSON marshalled list of []*id.ID object for the users that +// MultiLookupUD will look up. +// - singleRequestParams - the JSON marshalled bytes of single.RequestParams +// +// Returns: +// - []byte - the JSON marshalled bytes of the SingleUseSendReport object, +// which can be passed into Cmix.WaitForRoundResult to see if the send +// succeeded. +func MultiLookupUD(e2eID int, udContact []byte, cb UdMultiLookupCallback, + lookupIds []byte, singleRequestParamsJSON []byte) error { + + // Get user from singleton + user, err := e2eTrackerSingleton.get(e2eID) + if err != nil { + return err + } + + c, err := contact.Unmarshal(udContact) + if err != nil { + return err + } + + var idList []*id.ID + err = json.Unmarshal(lookupIds, &idList) + if err != nil { + return err + } + + var p single.RequestParams + err = json.Unmarshal(singleRequestParamsJSON, &p) + if err != nil { + return err + } + + respCh := make(chan lookupResp, len(idList)) + for _, uid := range idList { + localID := uid.DeepCopy() + callback := func(c contact.Contact, err error) { + respCh <- lookupResp{ + id: localID, + contact: c, + err: err, + } + } + go func() { + _, _, err := ud.Lookup(user.api, c, callback, localID, p) + if err != nil { + respCh <- lookupResp{ + id: localID, + contact: contact.Contact{}, + err: err, + } + } + }() + + } + + go func() { + marshaledContactList := make([][]byte, 0) + var failedIDs []*id.ID + var errorString string + for numReturned := 0; numReturned < len(idList); numReturned++ { + response := <-respCh + if response.err != nil { + failedIDs = append(failedIDs, response.id) + marshaledContactList = append( + marshaledContactList, response.contact.Marshal()) + } else { + errorString = errorString + + fmt.Sprintf("Failed to lookup id %s: %+v", + response.id, response.err) + } + } + + marshalledFailedIds, err := json.Marshal(failedIDs) + if err != nil { + cb.Callback(nil, nil, + errors.WithMessage(err, + "Failed to marshal failed IDs")) + } + + contactListJSON, err := json.Marshal(marshaledContactList) + if err != nil { + jww.FATAL.Panicf( + "Failed to marshal list of contact.Contact: %+v", err) + } + cb.Callback(contactListJSON, marshalledFailedIds, errors.New(errorString)) + }() + + return nil +} + //////////////////////////////////////////////////////////////////////////////// // User Discovery Search // //////////////////////////////////////////////////////////////////////////////// @@ -369,8 +558,15 @@ func LookupUD(e2eID int, udContact []byte, cb UdLookupCallback, // // Parameters: // - contactListJSON - the JSON marshalled bytes of []contact.Contact, or nil -// if an error occurs -// - err - any errors that occurred in the search +// if an error occurs. +// +// JSON Example: +// { +// "<xxc(2)F8dL9EC6gy+RMJuk3R+Au6eGExo02Wfio5cacjBcJRwDEgB7Ugdw/BAr6RkCABkWAFV1c2VybmFtZTA7c4LzV05sG+DMt+rFB0NIJg==xxc>", +// "<xxc(2)eMhAi/pYkW5jCmvKE5ZaTglQb+fTo1D8NxVitr5CCFADEgB7Ugdw/BAr6RoCABkWAFV1c2VybmFtZTE7fElAa7z3IcrYrrkwNjMS2w==xxc>", +// "<xxc(2)d7RJTu61Vy1lDThDMn8rYIiKSe1uXA/RCvvcIhq5Yg4DEgB7Ugdw/BAr6RsCABkWAFV1c2VybmFtZTI7N3XWrxIUpR29atpFMkcR6A==xxc>" +// } +// - err - any errors that occurred in the search. type UdSearchCallback interface { Callback(contactListJSON []byte, err error) } @@ -385,14 +581,15 @@ type UdSearchCallback interface { // - e2eID - e2e object ID in the tracker // - udContact - the marshalled bytes of the contact.Contact for the user // discovery server -// - factListJSON - the JSON marshalled bytes of fact.FactList +// - factListJSON - the JSON marshalled bytes of [fact.FactList] // - singleRequestParams - the JSON marshalled bytes of single.RequestParams // // Returns: // - []byte - the JSON marshalled bytes of the SingleUseSendReport object, -// which can be passed into WaitForRoundResult to see if the send succeeded. +// which can be passed into Cmix.WaitForRoundResult to see if the send +// operation succeeded. func SearchUD(e2eID int, udContact []byte, cb UdSearchCallback, - factListJSON []byte, singleRequestParamsJSON []byte) ([]byte, error) { + factListJSON, singleRequestParamsJSON []byte) ([]byte, error) { // Get user from singleton user, err := e2eTrackerSingleton.get(e2eID) @@ -418,7 +615,20 @@ func SearchUD(e2eID int, udContact []byte, cb UdSearchCallback, } callback := func(contactList []contact.Contact, err error) { - contactListJSON, err2 := json.Marshal(contactList) + marshaledContactList := make([][]byte, 0) + // fixme: it may be wiser to change this callback interface + // to simply do the work below when parsing the response from UD. + // that would change ud/search.go in two places: + // - searchCallback + // - parseContacts + // I avoid doing that as it changes interfaces w/o approval + for i := range contactList { + con := contactList[i] + marshaledContactList = append( + marshaledContactList, con.Marshal()) + } + + contactListJSON, err2 := json.Marshal(marshaledContactList) if err2 != nil { jww.FATAL.Panicf( "Failed to marshal list of contact.Contact: %+v", err2) @@ -434,8 +644,9 @@ func SearchUD(e2eID int, udContact []byte, cb UdSearchCallback, sr := SingleUseSendReport{ EphID: eid.EphId.Int64(), - ReceptionID: eid.Source.Marshal(), + ReceptionID: eid.Source, RoundsList: makeRoundsList(rids...), + RoundURL: getRoundURL(rids[0]), } return json.Marshal(sr) diff --git a/bindings/version.go b/bindings/version.go index e0571df8f1f22855f504b021fe869111781f724b..1dae09cc111915e2b0556d386f041f73c7dc9b62 100644 --- a/bindings/version.go +++ b/bindings/version.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// // version.go contains functions to report the client version. diff --git a/broadcast/asymmetric.go b/broadcast/asymmetric.go deleted file mode 100644 index 2b263cad705cadcfd0f9fb5a819a1c019cb8bb4b..0000000000000000000000000000000000000000 --- a/broadcast/asymmetric.go +++ /dev/null @@ -1,74 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -//////////////////////////////////////////////////////////////////////////////// - -package broadcast - -import ( - "encoding/binary" - "github.com/pkg/errors" - "gitlab.com/elixxir/client/cmix" - "gitlab.com/elixxir/client/cmix/message" - "gitlab.com/xx_network/crypto/multicastRSA" - "gitlab.com/xx_network/primitives/id" - "gitlab.com/xx_network/primitives/id/ephemeral" -) - -const ( - asymmetricBroadcastServiceTag = "AsymmBcast" - asymmCMixSendTag = "AsymmetricBroadcast" - internalPayloadSizeLength = 2 -) - -// BroadcastAsymmetric broadcasts the payload to the channel. Requires a healthy network state to send -// Payload must be equal to bc.MaxAsymmetricPayloadSize, and the channel PrivateKey must be passed in -func (bc *broadcastClient) BroadcastAsymmetric(pk multicastRSA.PrivateKey, payload []byte, cMixParams cmix.CMIXParams) ( - id.Round, ephemeral.Id, error) { - // Confirm network health - if !bc.net.IsHealthy() { - return 0, ephemeral.Id{}, errors.New(errNetworkHealth) - } - - // Check payload size - if len(payload) > bc.MaxAsymmetricPayloadSize() { - return 0, ephemeral.Id{}, - errors.Errorf(errPayloadSize, len(payload), bc.MaxAsymmetricPayloadSize()) - } - payloadLength := uint16(len(payload)) - - finalPayload := make([]byte, bc.maxAsymmetricPayloadSizeRaw()) - binary.BigEndian.PutUint16(finalPayload[:internalPayloadSizeLength], payloadLength) - copy(finalPayload[internalPayloadSizeLength:], payload) - - // Encrypt payload - encryptedPayload, mac, fp, err := bc.channel.EncryptAsymmetric(finalPayload, pk, bc.rng.GetStream()) - if err != nil { - return 0, ephemeral.Id{}, errors.WithMessage(err, "Failed to encrypt asymmetric broadcast message") - } - - // Create service using asymmetric broadcast service tag & channel reception ID - // Allows anybody with this info to listen for messages on this channel - service := message.Service{ - Identifier: bc.channel.ReceptionID.Bytes(), - Tag: asymmetricBroadcastServiceTag, - } - - if cMixParams.DebugTag == cmix.DefaultDebugTag { - cMixParams.DebugTag = asymmCMixSendTag - } - - // Create payload sized for sending over cmix - sizedPayload := make([]byte, bc.net.GetMaxMessageLength()) - // Read random data into sized payload - _, err = bc.rng.GetStream().Read(sizedPayload) - if err != nil { - return 0, ephemeral.Id{}, errors.WithMessage(err, "Failed to add random data to sized broadcast") - } - copy(sizedPayload[:len(encryptedPayload)], encryptedPayload) - - return bc.net.Send( - bc.channel.ReceptionID, fp, service, sizedPayload, mac, cMixParams) -} diff --git a/broadcast/broadcastClient.go b/broadcast/client.go similarity index 53% rename from broadcast/broadcastClient.go rename to broadcast/client.go index 6e1c7391cc6f97ed429cfd4164508444ac3eb0b3..1b4891a00bdf4d8ae9ce6bf31c2b020b356fa114 100644 --- a/broadcast/broadcastClient.go +++ b/broadcast/client.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package broadcast @@ -14,25 +14,30 @@ import ( "gitlab.com/elixxir/client/cmix/message" crypto "gitlab.com/elixxir/crypto/broadcast" "gitlab.com/elixxir/crypto/fastRNG" - "gitlab.com/xx_network/crypto/signature/rsa" ) -// broadcastClient implements the Channel interface for sending/receiving asymmetric or symmetric broadcast messages +// broadcastClient implements the [broadcast.Channel] interface for sending/ +// receiving asymmetric or symmetric broadcast messages. type broadcastClient struct { - channel crypto.Channel + channel *crypto.Channel net Client rng *fastRNG.StreamGenerator } -// NewBroadcastChannel creates a channel interface based on crypto.Channel, accepts net client connection & callback for received messages -func NewBroadcastChannel(channel crypto.Channel, net Client, rng *fastRNG.StreamGenerator) (Channel, error) { +type NewBroadcastChannelFunc func(channel *crypto.Channel, net Client, + rng *fastRNG.StreamGenerator) (Channel, error) + +// NewBroadcastChannel creates a channel interface based on [broadcast.Channel]. +// It accepts a Cmix client connection. +func NewBroadcastChannel(channel *crypto.Channel, net Client, + rng *fastRNG.StreamGenerator) (Channel, error) { bc := &broadcastClient{ channel: channel, net: net, rng: rng, } - if !bc.verifyID() { + if !channel.Verify() { return nil, errors.New("Failed ID verification for broadcast channel") } @@ -45,20 +50,21 @@ func NewBroadcastChannel(channel crypto.Channel, net Client, rng *fastRNG.Stream return bc, nil } -// RegisterListener adds a service to hear broadcast messages of a given type via the passed in callback +// RegisterListener registers a listener for broadcast messages. func (bc *broadcastClient) RegisterListener(listenerCb ListenerFunc, method Method) error { var tag string switch method { case Symmetric: tag = symmetricBroadcastServiceTag - case Asymmetric: - tag = asymmetricBroadcastServiceTag + case RSAToPublic: + tag = asymmetricRSAToPublicBroadcastServiceTag default: - return errors.Errorf("Cannot register listener for broadcast method %s", method) + return errors.Errorf( + "Cannot register listener for broadcast method %s", method) } p := &processor{ - c: &bc.channel, + c: bc.channel, cb: listenerCb, method: method, } @@ -72,8 +78,8 @@ func (bc *broadcastClient) RegisterListener(listenerCb ListenerFunc, method Meth return nil } -// Stop unregisters the listener callback and stops the channel's identity -// from being tracked. +// Stop unregisters the listener callback and stops the channel's identity from +// being tracked. func (bc *broadcastClient) Stop() { // Removes currently tracked identity bc.net.RemoveIdentity(bc.channel.ReceptionID) @@ -82,29 +88,27 @@ func (bc *broadcastClient) Stop() { bc.net.DeleteClientService(bc.channel.ReceptionID) } -// Get returns the underlying crypto.Channel object -func (bc *broadcastClient) Get() crypto.Channel { +// Get returns the underlying [broadcast.Channel] object. +func (bc *broadcastClient) Get() *crypto.Channel { return bc.channel } -// verifyID generates a symmetric ID based on the info in the channel & compares it to the one passed in -func (bc *broadcastClient) verifyID() bool { - gen, err := crypto.NewChannelID(bc.channel.Name, bc.channel.Description, bc.channel.Salt, rsa.CreatePublicKeyPem(bc.channel.RsaPubKey)) - if err != nil { - jww.FATAL.Panicf("[verifyID] Failed to generate verified channel ID") - return false - } - return bc.channel.ReceptionID.Cmp(gen) -} - +// MaxPayloadSize returns the maximum size for a symmetric broadcast payload. func (bc *broadcastClient) MaxPayloadSize() int { return bc.maxSymmetricPayload() } -func (bc *broadcastClient) MaxAsymmetricPayloadSize() int { - return bc.maxAsymmetricPayloadSizeRaw() - internalPayloadSizeLength +func (bc *broadcastClient) maxSymmetricPayload() int { + return bc.channel.GetMaxSymmetricPayloadSize(bc.net.GetMaxMessageLength()) +} + +// MaxRSAToPublicPayloadSize return the maximum payload size for a +// [broadcast.RSAToPublic] asymmetric payload. +func (bc *broadcastClient) MaxRSAToPublicPayloadSize() int { + return bc.maxRSAToPublicPayloadSizeRaw() - internalPayloadSizeLength } -func (bc *broadcastClient) maxAsymmetricPayloadSizeRaw() int { - return bc.channel.MaxAsymmetricPayloadSize() +func (bc *broadcastClient) maxRSAToPublicPayloadSizeRaw() int { + size, _, _ := bc.channel.GetRSAToPublicMessageLength() + return size } diff --git a/broadcast/interface.go b/broadcast/interface.go index bd464945549ba67b4800dcef5c1f4f9d339d061d..3c674c0db3438862296e8980afcb8177eb3d2a9a 100644 --- a/broadcast/interface.go +++ b/broadcast/interface.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package broadcast @@ -13,40 +13,69 @@ import ( "gitlab.com/elixxir/client/cmix/message" "gitlab.com/elixxir/client/cmix/rounds" crypto "gitlab.com/elixxir/crypto/broadcast" - "gitlab.com/elixxir/primitives/format" - "gitlab.com/xx_network/crypto/multicastRSA" + "gitlab.com/elixxir/crypto/rsa" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/id/ephemeral" "time" ) -// ListenerFunc is registered when creating a new broadcasting channel -// and receives all new broadcast messages for the channel. +// ListenerFunc is registered when creating a new broadcasting channel and +// receives all new broadcast messages for the channel. type ListenerFunc func(payload []byte, receptionID receptionID.EphemeralIdentity, round rounds.Round) -// Channel is the public-facing interface to interact with broadcast channels +// Channel is the public-facing interface to interact with broadcast channels. type Channel interface { - // MaxPayloadSize returns the maximum size for a symmetric broadcast payload + // MaxPayloadSize returns the maximum size for a symmetric broadcast + // payload. MaxPayloadSize() int - // MaxAsymmetricPayloadSize returns the maximum size for an asymmetric broadcast payload - MaxAsymmetricPayloadSize() int + // MaxRSAToPublicPayloadSize returns the maximum size for an asymmetric + // broadcast payload. + MaxRSAToPublicPayloadSize() int - // Get returns the underlying crypto.Channel - Get() crypto.Channel + // Get returns the underlying [broadcast.Channel] object. + Get() *crypto.Channel - // Broadcast broadcasts the payload to the channel. The payload size must be - // equal to MaxPayloadSize. + // Broadcast broadcasts a payload to the channel. The payload must be of the + // size [Channel.MaxPayloadSize] or smaller. + // + // The network must be healthy to send. Broadcast(payload []byte, cMixParams cmix.CMIXParams) ( - id.Round, ephemeral.Id, error) + rounds.Round, ephemeral.Id, error) - // BroadcastAsymmetric broadcasts an asymmetric payload to the channel. The payload size must be - // equal to MaxPayloadSize & private key for channel must be passed in - BroadcastAsymmetric(pk multicastRSA.PrivateKey, payload []byte, cMixParams cmix.CMIXParams) ( - id.Round, ephemeral.Id, error) + // BroadcastWithAssembler broadcasts a payload over a channel with a payload + // assembled after the round is selected, allowing the round info to be + // included in the payload. + // + // The payload must be of the size [Channel.MaxPayloadSize] or smaller. + // + // The network must be healthy to send. + BroadcastWithAssembler(assembler Assembler, cMixParams cmix.CMIXParams) ( + rounds.Round, ephemeral.Id, error) - // RegisterListener registers a listener for broadcast messages + // BroadcastRSAtoPublic broadcasts the payload to the channel. + // + // The payload must be of the size [Channel.MaxRSAToPublicPayloadSize] or + // smaller and the channel [rsa.PrivateKey] must be passed in. + // + // The network must be healthy to send. + BroadcastRSAtoPublic(pk rsa.PrivateKey, payload []byte, + cMixParams cmix.CMIXParams) (rounds.Round, ephemeral.Id, error) + + // BroadcastRSAToPublicWithAssembler broadcasts the payload to the channel + // with a function that builds the payload based upon the ID of the selected + // round. + // + // The payload must be of the size [Channel.MaxRSAToPublicPayloadSize] or + // smaller and the channel [rsa.PrivateKey] must be passed in. + // + // The network must be healthy to send. + BroadcastRSAToPublicWithAssembler( + pk rsa.PrivateKey, assembler Assembler, + cMixParams cmix.CMIXParams) (rounds.Round, ephemeral.Id, error) + + // RegisterListener registers a listener for broadcast messages. RegisterListener(listenerCb ListenerFunc, method Method) error // Stop unregisters the listener callback and stops the channel's identity @@ -54,17 +83,19 @@ type Channel interface { Stop() } -// Client contains the methods from cmix.Client that are required by -// symmetricClient. +// Assembler is a function which allows a bre +type Assembler func(rid id.Round) (payload []byte, err error) + +// Client contains the methods from [cmix.Client] that are required by +// broadcastClient. type Client interface { - GetMaxMessageLength() int - Send(recipient *id.ID, fingerprint format.Fingerprint, - service message.Service, payload, mac []byte, - cMixParams cmix.CMIXParams) (id.Round, ephemeral.Id, error) + SendWithAssembler(recipient *id.ID, assembler cmix.MessageAssembler, + cmixParams cmix.CMIXParams) (rounds.Round, ephemeral.Id, error) IsHealthy() bool AddIdentity(id *id.ID, validUntil time.Time, persistent bool) AddService(clientID *id.ID, newService message.Service, response message.Processor) DeleteClientService(clientID *id.ID) RemoveIdentity(id *id.ID) + GetMaxMessageLength() int } diff --git a/broadcast/method.go b/broadcast/method.go index e493151504b00fabf320429b5da52a474f23efed..c154fc027b81a55f600c5f54fa3847aa7616ea89 100644 --- a/broadcast/method.go +++ b/broadcast/method.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package broadcast @@ -12,15 +12,18 @@ type Method uint8 const ( Symmetric Method = iota - Asymmetric + RSAToPublic + RSAToPrivate ) func (m Method) String() string { switch m { case Symmetric: return "Symmetric" - case Asymmetric: - return "Asymmetric" + case RSAToPublic: + return "RSAToPublic" + case RSAToPrivate: + return "RSAToPrivate" default: return "Unknown" } diff --git a/broadcast/processor.go b/broadcast/processor.go index 651974c4cb648aba5df3e56fa8f46901cc1a2899..8ee1f85d07ad093337711ef15e7f6e3ced3dd1f8 100644 --- a/broadcast/processor.go +++ b/broadcast/processor.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package broadcast @@ -35,10 +35,8 @@ func (p *processor) Process(msg format.Message, var payload []byte var err error switch p.method { - case Asymmetric: - encPartSize := p.c.RsaPubKey.Size() // Size returned by multicast RSA encryption - encodedMessage := msg.GetContents()[:encPartSize] // Only one message is encoded, rest of it is random data - decodedMessage, decryptErr := p.c.DecryptAsymmetric(encodedMessage) + case RSAToPublic: + decodedMessage, decryptErr := p.c.DecryptRSAToPublic(msg.GetContents(), msg.GetMac(), msg.GetKeyFP()) if decryptErr != nil { jww.ERROR.Printf(errDecrypt, p.c.ReceptionID, p.c.Name, decryptErr) return @@ -53,10 +51,10 @@ func (p *processor) Process(msg format.Message, return } default: - jww.ERROR.Printf("Unrecognized broadcast method %d", p.method) + jww.FATAL.Panicf("Unrecognized broadcast method %d", p.method) } - go p.cb(payload, receptionID, round) + p.cb(payload, receptionID, round) } // String returns a string identifying the symmetricProcessor for debugging purposes. diff --git a/broadcast/processor_test.go b/broadcast/processor_test.go index 9e48f372e92663eea061a8a7d72e0fbe13d58eee..b758c20dbfa8756a31cc554671ab884d6b312a56 100644 --- a/broadcast/processor_test.go +++ b/broadcast/processor_test.go @@ -1,26 +1,13 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package broadcast -import ( - "bytes" - "gitlab.com/elixxir/client/cmix/identity/receptionID" - "gitlab.com/elixxir/client/cmix/rounds" - crypto "gitlab.com/elixxir/crypto/broadcast" - "gitlab.com/elixxir/crypto/cmix" - "gitlab.com/elixxir/primitives/format" - "gitlab.com/xx_network/crypto/csprng" - "gitlab.com/xx_network/crypto/signature/rsa" - "gitlab.com/xx_network/primitives/id" - "testing" - "time" -) - +/* // Tests that process.Process properly decrypts the payload and passes it to the // callback. func Test_processor_Process(t *testing.T) { @@ -37,7 +24,7 @@ func Test_processor_Process(t *testing.T) { RsaPubKey: rsaPrivKey.GetPublic(), } - cbChan := make(chan []byte) + cbChan := make(chan []byte, 1) cb := func(payload []byte, _ receptionID.EphemeralIdentity, _ rounds.Round) { cbChan <- payload } @@ -67,4 +54,4 @@ func Test_processor_Process(t *testing.T) { case <-time.After(15 * time.Millisecond): t.Error("Timed out waiting for listener channel to be called.") } -} +}*/ diff --git a/broadcast/rsaToPublic.go b/broadcast/rsaToPublic.go new file mode 100644 index 0000000000000000000000000000000000000000..26c4d0924af04c6464610f20fe8040ac1aa7b082 --- /dev/null +++ b/broadcast/rsaToPublic.go @@ -0,0 +1,121 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + +package broadcast + +import ( + "encoding/binary" + "github.com/pkg/errors" + "gitlab.com/elixxir/client/cmix" + "gitlab.com/elixxir/client/cmix/message" + "gitlab.com/elixxir/client/cmix/rounds" + "gitlab.com/elixxir/crypto/rsa" + "gitlab.com/elixxir/primitives/format" + "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/id/ephemeral" +) + +const ( + asymmetricRSAToPublicBroadcastServiceTag = "AsymmToPublicBcast" + asymmCMixSendTag = "AsymmetricBroadcast" + internalPayloadSizeLength = 2 +) + +// BroadcastRSAtoPublic broadcasts the payload to the channel. Requires a +// healthy network state to send Payload length less than or equal to +// bc.MaxRSAToPublicPayloadSize, and the channel PrivateKey must be passed in +// +// BroadcastRSAtoPublic broadcasts the payload to the channel. +// +// The payload must be of the size [broadcastClient.MaxRSAToPublicPayloadSize] +// or smaller and the channel [rsa.PrivateKey] must be passed in. +// +// The network must be healthy to send. +func (bc *broadcastClient) BroadcastRSAtoPublic(pk rsa.PrivateKey, + payload []byte, cMixParams cmix.CMIXParams) (rounds.Round, ephemeral.Id, error) { + // Confirm network health + + assemble := func(rid id.Round) ([]byte, error) { + return payload, nil + } + return bc.BroadcastRSAToPublicWithAssembler(pk, assemble, cMixParams) +} + +// BroadcastRSAToPublicWithAssembler broadcasts the payload to the channel +// with a function that builds the payload based upon the ID of the selected +// round. +// +// The payload must be of the size [broadcastClient.MaxRSAToPublicPayloadSize] +// or smaller and the channel [rsa.PrivateKey] must be passed in. +// +// The network must be healthy to send. +func (bc *broadcastClient) BroadcastRSAToPublicWithAssembler( + pk rsa.PrivateKey, assembler Assembler, + cMixParams cmix.CMIXParams) (rounds.Round, ephemeral.Id, error) { + // Confirm network health + if !bc.net.IsHealthy() { + return rounds.Round{}, ephemeral.Id{}, errors.New(errNetworkHealth) + } + + assemble := func(rid id.Round) (fp format.Fingerprint, + service message.Service, encryptedPayload, mac []byte, err error) { + payload, err := assembler(rid) + if err != nil { + return format.Fingerprint{}, message.Service{}, nil, + nil, err + } + // Check payload size + if len(payload) > bc.MaxRSAToPublicPayloadSize() { + return format.Fingerprint{}, message.Service{}, nil, + nil, errors.Errorf(errPayloadSize, len(payload), + bc.MaxRSAToPublicPayloadSize()) + } + payloadLength := uint16(len(payload)) + + finalPayload := make([]byte, bc.maxRSAToPublicPayloadSizeRaw()) + binary.BigEndian.PutUint16(finalPayload[:internalPayloadSizeLength], + payloadLength) + copy(finalPayload[internalPayloadSizeLength:], payload) + + // Encrypt payload + encryptedPayload, mac, fp, err = + bc.channel.EncryptRSAToPublic(finalPayload, pk, bc.net.GetMaxMessageLength(), + bc.rng.GetStream()) + if err != nil { + return format.Fingerprint{}, message.Service{}, nil, + nil, errors.WithMessage(err, "Failed to encrypt "+ + "asymmetric broadcast message") + } + + // Create service using asymmetric broadcast service tag & channel + // reception ID allows anybody with this info to listen for messages on + // this channel + service = message.Service{ + Identifier: bc.channel.ReceptionID.Bytes(), + Tag: asymmetricRSAToPublicBroadcastServiceTag, + } + + if cMixParams.DebugTag == cmix.DefaultDebugTag { + cMixParams.DebugTag = asymmCMixSendTag + } + + // Create payload sized for sending over cmix + sizedPayload := make([]byte, bc.net.GetMaxMessageLength()) + // Read random data into sized payload + _, err = bc.rng.GetStream().Read(sizedPayload) + if err != nil { + return format.Fingerprint{}, message.Service{}, nil, + nil, errors.WithMessage(err, "Failed to add "+ + "random data to sized broadcast") + } + copy(sizedPayload[:len(encryptedPayload)], encryptedPayload) + + return + } + + return bc.net.SendWithAssembler(bc.channel.ReceptionID, assemble, cMixParams) +} diff --git a/broadcast/asymmetric_test.go b/broadcast/rsaToPublic_test.go similarity index 51% rename from broadcast/asymmetric_test.go rename to broadcast/rsaToPublic_test.go index 776879127b040946b8147c184341cc4860de3296..159f9d1016ead09866c8db1bd3f15faedfc94404 100644 --- a/broadcast/asymmetric_test.go +++ b/broadcast/rsaToPublic_test.go @@ -1,58 +1,80 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package broadcast import ( "bytes" "fmt" + "reflect" + "sync" + "testing" + "time" + + "gitlab.com/xx_network/crypto/csprng" + "gitlab.com/elixxir/client/cmix" "gitlab.com/elixxir/client/cmix/identity/receptionID" + "gitlab.com/elixxir/client/cmix/message" "gitlab.com/elixxir/client/cmix/rounds" crypto "gitlab.com/elixxir/crypto/broadcast" - cMixCrypto "gitlab.com/elixxir/crypto/cmix" "gitlab.com/elixxir/crypto/fastRNG" - "gitlab.com/xx_network/crypto/csprng" - "gitlab.com/xx_network/crypto/signature/rsa" - "reflect" - "sync" - "testing" - "time" + "gitlab.com/elixxir/primitives/format" ) -// Tests that symmetricClient adheres to the Symmetric interface. +// Tests that broadcastClient adheres to the Channel interface. var _ Channel = (*broadcastClient)(nil) -// Tests that symmetricClient adheres to the Symmetric interface. +// Tests that cmix.Client adheres to the Client interface. var _ Client = (cmix.Client)(nil) +// Tests that mockProcessor adheres to the message.Processor interface. +var _ message.Processor = (*mockProcessor)(nil) + +// mockProcessor adheres to the message.Processor interface. +type mockProcessor struct { + messages []format.Message +} + +func newMockProcessor() *mockProcessor { + m := new(mockProcessor) + m.messages = make([]format.Message, 0) + return m +} +func (p *mockProcessor) Process(message format.Message, + _ receptionID.EphemeralIdentity, _ rounds.Round) { + p.messages = append(p.messages, message) +} +func (p *mockProcessor) String() string { return "hello" } + func Test_asymmetricClient_Smoke(t *testing.T) { cMixHandler := newMockCmixHandler() rngGen := fastRNG.NewStreamGenerator(1000, 10, csprng.NewSystemRNG) - pk, err := rsa.GenerateKey(rngGen.GetStream(), 4096) - if err != nil { - t.Fatalf("Failed to generate priv key: %+v", err) - } - cname := "MyChannel" - cdesc := "This is my channel about stuff." - csalt := cMixCrypto.NewSalt(csprng.NewSystemRNG(), 32) - cpubkey := pk.GetPublic() - cid, err := crypto.NewChannelID(cname, cdesc, csalt, rsa.CreatePublicKeyPem(cpubkey)) - if err != nil { - t.Errorf("Failed to create channel ID: %+v", err) - } - channel := crypto.Channel{ - ReceptionID: cid, - Name: cname, - Description: cdesc, - Salt: csalt, - RsaPubKey: cpubkey, - } + cName := "MyChannel" + cDesc := "This is my channel about stuff." + packetPayloadLength := newMockCmix(cMixHandler).GetMaxMessageLength() + + channel, pk, _ := crypto.NewChannel( + cName, cDesc, packetPayloadLength, rngGen.GetStream()) + cid := channel.ReceptionID + + // Must mutate cMixHandler such that it's processorMap contains a + // message.Processor + mockProc := newMockProcessor() + cMixHandler.processorMap[*cid] = make(map[string][]message.Processor) + cMixHandler.processorMap[*cid]["AsymmBcast"] = []message.Processor{mockProc} - const n = 5 + const n = 1 cbChans := make([]chan []byte, n) clients := make([]Channel, n) for i := range clients { cbChan := make(chan []byte, 10) - cb := func(payload []byte, _ receptionID.EphemeralIdentity, - _ rounds.Round) { + cb := func( + payload []byte, _ receptionID.EphemeralIdentity, _ rounds.Round) { cbChan <- payload } @@ -61,7 +83,7 @@ func Test_asymmetricClient_Smoke(t *testing.T) { t.Errorf("Failed to create broadcast channel: %+v", err) } - err = s.RegisterListener(cb, Asymmetric) + err = s.RegisterListener(cb, RSAToPublic) if err != nil { t.Errorf("Failed to register listener: %+v", err) } @@ -69,7 +91,7 @@ func Test_asymmetricClient_Smoke(t *testing.T) { cbChans[i] = cbChan clients[i] = s - // Test that Get returns the expected channel + // Test that Channel.Get returns the expected channel if !reflect.DeepEqual(s.Get(), channel) { t.Errorf("Cmix %d returned wrong channel."+ "\nexpected: %+v\nreceived: %+v", i, channel, s.Get()) @@ -78,7 +100,7 @@ func Test_asymmetricClient_Smoke(t *testing.T) { // Send broadcast from each client for i := range clients { - payload := make([]byte, clients[i].MaxAsymmetricPayloadSize()) + payload := make([]byte, clients[i].MaxRSAToPublicPayloadSize()) copy(payload, fmt.Sprintf("Hello from client %d of %d.", i, len(clients))) @@ -91,9 +113,9 @@ func Test_asymmetricClient_Smoke(t *testing.T) { select { case r := <-cbChan: if !bytes.Equal(payload, r) { - t.Errorf("Cmix %d failed to receive expected "+ - "payload from client %d."+ - "\nexpected: %q\nreceived: %q", j, i, payload, r) + t.Errorf("Cmix %d failed to receive expected payload "+ + "from client %d.\nexpected: %q\nreceived: %q", + j, i, payload, r) } case <-time.After(time.Second): t.Errorf("Cmix %d timed out waiting for broadcast "+ @@ -103,7 +125,8 @@ func Test_asymmetricClient_Smoke(t *testing.T) { } // Broadcast payload - _, _, err := clients[i].BroadcastAsymmetric(pk, payload, cmix.GetDefaultCMIXParams()) + _, _, err := clients[i].BroadcastRSAtoPublic( + pk, payload, cmix.GetDefaultCMIXParams()) if err != nil { t.Errorf("Cmix %d failed to send broadcast: %+v", i, err) } @@ -117,7 +140,7 @@ func Test_asymmetricClient_Smoke(t *testing.T) { clients[i].Stop() } - payload := make([]byte, clients[0].MaxAsymmetricPayloadSize()) + payload := make([]byte, clients[0].MaxRSAToPublicPayloadSize()) copy(payload, "This message should not get through.") // Start waiting on channels and error if anything is received @@ -135,7 +158,7 @@ func Test_asymmetricClient_Smoke(t *testing.T) { } // Broadcast payload - _, _, err = clients[0].BroadcastAsymmetric(pk, payload, cmix.GetDefaultCMIXParams()) + _, _, err := clients[0].BroadcastRSAtoPublic(pk, payload, cmix.GetDefaultCMIXParams()) if err != nil { t.Errorf("Cmix 0 failed to send broadcast: %+v", err) } diff --git a/broadcast/sizedBroadcast.go b/broadcast/sizedBroadcast.go deleted file mode 100644 index d05effe1bcf93b07a0f3cd3533c28df8136c3a46..0000000000000000000000000000000000000000 --- a/broadcast/sizedBroadcast.go +++ /dev/null @@ -1,83 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -//////////////////////////////////////////////////////////////////////////////// - -package broadcast - -import ( - "encoding/binary" - "github.com/pkg/errors" -) - -// Message field sizes. -const ( - sizeSize = 2 - sizedBroadcastMinSize = sizeSize -) - -// Error messages. -const ( - // NewSizedBroadcast - errNewSizedBroadcastMaxSize = "size of payload and its size %d too large to fit in max payload size %d" - - // DecodeSizedBroadcast - errDecodeSizedBroadcastDataLen = "size of data %d must be greater than %d" - errDecodeSizedBroadcastSize = "stated payload size %d larger than provided data %d" -) - -/* -+---------------------------+ -| cMix Message Contents | -+---------+-----------------+ -| Size | Payload | -| 2 bytes | remaining space | -+---------+-----------------+ -*/ - -// NewSizedBroadcast creates a new broadcast payload of size maxPayloadSize that -// contains the given payload so that it fits completely inside a broadcasted -// cMix message payload. The length of the payload is stored internally and used -// to strip extraneous padding when decoding the payload. -// The maxPayloadSize is the maximum size of the resulting payload. Returns an -// error when the provided payload cannot fit in the max payload size. -func NewSizedBroadcast(maxPayloadSize int, payload []byte) ([]byte, error) { - if len(payload)+sizedBroadcastMinSize > maxPayloadSize { - return nil, errors.Errorf(errNewSizedBroadcastMaxSize, - len(payload)+sizedBroadcastMinSize, maxPayloadSize) - } - - b := make([]byte, sizeSize) - binary.LittleEndian.PutUint16(b, uint16(len(payload))) - - sizedPayload := make([]byte, maxPayloadSize) - copy(sizedPayload, append(b, payload...)) - - return sizedPayload, nil -} - -// DecodeSizedBroadcast decodes the data into its original payload stripping off -// extraneous padding. -func DecodeSizedBroadcast(data []byte) ([]byte, error) { - if len(data) < sizedBroadcastMinSize { - return nil, errors.Errorf( - errDecodeSizedBroadcastDataLen, len(data), sizedBroadcastMinSize) - } - - size := binary.LittleEndian.Uint16(data[:sizeSize]) - if int(size) > len(data[sizeSize:]) { - return nil, errors.Errorf( - errDecodeSizedBroadcastSize, size, len(data[sizeSize:])) - } - - return data[sizeSize : size+sizeSize], nil -} - -// MaxSizedBroadcastPayloadSize returns the maximum size of a payload that can -// fit in a sized broadcast message for the given maximum cMix message payload -// size. -func MaxSizedBroadcastPayloadSize(maxPayloadSize int) int { - return maxPayloadSize - sizedBroadcastMinSize -} diff --git a/broadcast/sizedBroadcast_test.go b/broadcast/sizedBroadcast_test.go deleted file mode 100644 index a065101498b5bb6fe22ba66804f85190b8aab887..0000000000000000000000000000000000000000 --- a/broadcast/sizedBroadcast_test.go +++ /dev/null @@ -1,115 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -//////////////////////////////////////////////////////////////////////////////// - -package broadcast - -import ( - "bytes" - "fmt" - "testing" -) - -// Tests that a payload smaller than the max payload size encoded via -// NewSizedBroadcast and decoded via DecodeSizedBroadcast matches the original. -func TestNewSizedBroadcast_DecodeSizedBroadcast_SmallPayload(t *testing.T) { - const maxPayloadSize = 512 - payload := []byte("This is my payload message.") - - data, err := NewSizedBroadcast(maxPayloadSize, payload) - if err != nil { - t.Errorf("NewSizedBroadcast returned an error: %+v", err) - } - - decodedPayload, err := DecodeSizedBroadcast(data) - if err != nil { - t.Errorf("DecodeSizedBroadcast returned an error: %+v", err) - } - - if !bytes.Equal(payload, decodedPayload) { - t.Errorf("Decoded payload does not match original."+ - "\nexpected: %q\nreceived: %q", payload, decodedPayload) - } -} - -// Tests that a payload the same size as the max payload size encoded via -// NewSizedBroadcast and decoded via DecodeSizedBroadcast matches the original. -func TestNewSizedBroadcast_DecodeSizedBroadcast_FullSizesPayload(t *testing.T) { - payload := []byte("This is my payload message.") - maxPayloadSize := len(payload) + sizeSize - - data, err := NewSizedBroadcast(maxPayloadSize, payload) - if err != nil { - t.Errorf("NewSizedBroadcast returned an error: %+v", err) - } - - decodedPayload, err := DecodeSizedBroadcast(data) - if err != nil { - t.Errorf("DecodeSizedBroadcast returned an error: %+v", err) - } - - if !bytes.Equal(payload, decodedPayload) { - t.Errorf("Decoded payload does not match original."+ - "\nexpected: %q\nreceived: %q", payload, decodedPayload) - } -} - -// Error path: tests that NewSizedBroadcast returns an error when the payload is -// larger than the max payload size. -func TestNewSizedBroadcast_MaxPayloadSizeError(t *testing.T) { - payload := []byte("This is my payload message.") - maxPayloadSize := len(payload) - expectedErr := fmt.Sprintf(errNewSizedBroadcastMaxSize, - len(payload)+sizedBroadcastMinSize, maxPayloadSize) - - _, err := NewSizedBroadcast(maxPayloadSize, payload) - if err == nil || err.Error() != expectedErr { - t.Errorf("NewSizedBroadcast did not return the expected error when "+ - "the payload is too large.\nexpected: %s\nreceived: %+v", - expectedErr, err) - } -} - -// Error path: tests that DecodeSizedBroadcast returns an error when the length -// of the data is shorter than the minimum length of a sized broadcast. -func TestDecodeSizedBroadcast_DataTooShortError(t *testing.T) { - data := []byte{0} - expectedErr := fmt.Sprintf( - errDecodeSizedBroadcastDataLen, len(data), sizedBroadcastMinSize) - - _, err := DecodeSizedBroadcast(data) - if err == nil || err.Error() != expectedErr { - t.Errorf("DecodeSizedBroadcast did not return the expected error "+ - "when the data is too small.\nexpected: %s\nreceived: %+v", - expectedErr, err) - } -} - -// Error path: tests that DecodeSizedBroadcast returns an error when the payload -// size is larger than the actual payload contained in the data. -func TestDecodeSizedBroadcast_SizeMismatchError(t *testing.T) { - data := []byte{255, 0, 10} - expectedErr := fmt.Sprintf( - errDecodeSizedBroadcastSize, data[0], len(data[sizeSize:])) - - _, err := DecodeSizedBroadcast(data) - if err == nil || err.Error() != expectedErr { - t.Errorf("DecodeSizedBroadcast did not return the expected error "+ - "when the size is too large.\nexpected: %s\nreceived: %+v", - expectedErr, err) - } -} - -// Tests that MaxSizedBroadcastPayloadSize returns the correct max size. -func TestMaxSizedBroadcastPayloadSize(t *testing.T) { - maxPayloadSize := 512 - expectedSize := maxPayloadSize - sizedBroadcastMinSize - receivedSize := MaxSizedBroadcastPayloadSize(maxPayloadSize) - if receivedSize != expectedSize { - t.Errorf("Incorrect max paylaod size.\nexpected: %d\nreceived: %d", - expectedSize, receivedSize) - } -} diff --git a/broadcast/symmetric.go b/broadcast/symmetric.go index 601c2bebec39f7c00c1e389a9f2d0d8ccc5122f3..432c53c8cab2ae80ea16f915d0142136a0d1532d 100644 --- a/broadcast/symmetric.go +++ b/broadcast/symmetric.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package broadcast @@ -11,13 +11,15 @@ import ( "github.com/pkg/errors" "gitlab.com/elixxir/client/cmix" "gitlab.com/elixxir/client/cmix/message" + "gitlab.com/elixxir/client/cmix/rounds" + "gitlab.com/elixxir/primitives/format" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/id/ephemeral" ) // Error messages. const ( - // symmetricClient.Broadcast + // broadcastClient.Broadcast errNetworkHealth = "cannot send broadcast when the network is not healthy" errPayloadSize = "size of payload %d must be less than %d" errBroadcastMethodType = "cannot call %s broadcast using %s channel" @@ -29,41 +31,68 @@ const ( symmetricBroadcastServiceTag = "SymmetricBroadcast" ) -// MaxSymmetricPayloadSize returns the maximum size for a broadcasted payload. -func (bc *broadcastClient) maxSymmetricPayload() int { - return bc.net.GetMaxMessageLength() +// Broadcast broadcasts a payload to a symmetric channel. The payload must be of +// size [broadcastClient.MaxPayloadSize] or smaller. +// +// The network must be healthy to send. +func (bc *broadcastClient) Broadcast(payload []byte, cMixParams cmix.CMIXParams) ( + rounds.Round, ephemeral.Id, error) { + assemble := func(rid id.Round) ([]byte, error) { + return payload, nil + } + return bc.BroadcastWithAssembler(assemble, cMixParams) } -// Broadcast broadcasts a payload over a symmetric channel. -// Network must be healthy to send -// Requires a payload of size bc.MaxSymmetricPayloadSize() -func (bc *broadcastClient) Broadcast(payload []byte, cMixParams cmix.CMIXParams) ( - id.Round, ephemeral.Id, error) { +// BroadcastWithAssembler broadcasts a payload over a symmetric channel with a +// payload assembled after the round is selected, allowing the round info to be +// included in the payload. +// +// The payload must be of the size [Channel.MaxPayloadSize] or smaller. +// +// The network must be healthy to send. +func (bc *broadcastClient) BroadcastWithAssembler(assembler Assembler, cMixParams cmix.CMIXParams) ( + rounds.Round, ephemeral.Id, error) { if !bc.net.IsHealthy() { - return 0, ephemeral.Id{}, errors.New(errNetworkHealth) + return rounds.Round{}, ephemeral.Id{}, errors.New(errNetworkHealth) } - if len(payload) != bc.maxSymmetricPayload() { - return 0, ephemeral.Id{}, - errors.Errorf(errPayloadSize, len(payload), bc.maxSymmetricPayload()) - } + assemble := func(rid id.Round) (fp format.Fingerprint, + service message.Service, encryptedPayload, mac []byte, err error) { - // Encrypt payload - rng := bc.rng.GetStream() - encryptedPayload, mac, fp := bc.channel.EncryptSymmetric(payload, rng) - rng.Close() + //assemble the passed payload + payload, err := assembler(rid) + if err != nil { + return format.Fingerprint{}, message.Service{}, nil, nil, err + } - // Create service using symmetric broadcast service tag & channel reception ID - // Allows anybody with this info to listen for messages on this channel - service := message.Service{ - Identifier: bc.channel.ReceptionID.Bytes(), - Tag: symmetricBroadcastServiceTag, - } + if len(payload) > bc.maxSymmetricPayload() { + return format.Fingerprint{}, message.Service{}, nil, nil, + errors.Errorf(errPayloadSize, len(payload), bc.maxSymmetricPayload()) + } + + // Encrypt payload + rng := bc.rng.GetStream() + defer rng.Close() + encryptedPayload, mac, fp, err = bc.channel.EncryptSymmetric(payload, + bc.net.GetMaxMessageLength(), rng) + if err != nil { + return format.Fingerprint{}, message.Service{}, + nil, nil, err + } + + // Create service using symmetric broadcast service tag & channel reception ID + // Allows anybody with this info to listen for messages on this channel + service = message.Service{ + Identifier: bc.channel.ReceptionID.Bytes(), + Tag: symmetricBroadcastServiceTag, + } - if cMixParams.DebugTag == cmix.DefaultDebugTag { - cMixParams.DebugTag = symmCMixSendTag + if cMixParams.DebugTag == cmix.DefaultDebugTag { + cMixParams.DebugTag = symmCMixSendTag + } + return } - return bc.net.Send( - bc.channel.ReceptionID, fp, service, encryptedPayload, mac, cMixParams) + return bc.net.SendWithAssembler(bc.channel.ReceptionID, assemble, + cMixParams) } diff --git a/broadcast/symmetric_test.go b/broadcast/symmetric_test.go index 2eb26d29eb3b56db1e894ad5b3da3aaabadf114f..3386a71ead8fb2ffada89329017975216be91507 100644 --- a/broadcast/symmetric_test.go +++ b/broadcast/symmetric_test.go @@ -1,12 +1,13 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package broadcast +/* import ( "bytes" "fmt" @@ -14,10 +15,9 @@ import ( "gitlab.com/elixxir/client/cmix/identity/receptionID" "gitlab.com/elixxir/client/cmix/rounds" crypto "gitlab.com/elixxir/crypto/broadcast" - cMixCrypto "gitlab.com/elixxir/crypto/cmix" + "gitlab.com/elixxir/crypto/fastRNG" "gitlab.com/xx_network/crypto/csprng" - "gitlab.com/xx_network/crypto/signature/rsa" "reflect" "sync" "testing" @@ -38,19 +38,10 @@ func Test_symmetricClient_Smoke(t *testing.T) { rngGen := fastRNG.NewStreamGenerator(1000, 10, csprng.NewSystemRNG) cname := "MyChannel" cdesc := "This is my channel about stuff." - csalt := cMixCrypto.NewSalt(csprng.NewSystemRNG(), 32) - cpubkey := newRsaPubKey(64, t) - cid, err := crypto.NewChannelID(cname, cdesc, csalt, rsa.CreatePublicKeyPem(cpubkey)) - if err != nil { - t.Errorf("Failed to create channel ID: %+v", err) - } - channel := crypto.Channel{ - ReceptionID: cid, - Name: cname, - Description: cdesc, - Salt: csalt, - RsaPubKey: cpubkey, - } + mCmix := newMockCmix(cMixHandler) + channel,_,_ := crypto.NewChannel(cname, cdesc, + mCmix.GetMaxMessageLength(), + rngGen.GetStream()) // Set up callbacks, callback channels, and the symmetric clients const n = 5 @@ -85,7 +76,7 @@ func Test_symmetricClient_Smoke(t *testing.T) { // Send broadcast from each client for i := range clients { - payload := make([]byte, newMockCmix(cMixHandler).GetMaxMessageLength()) + payload := make([]byte, clients[i].MaxPayloadSize()) copy(payload, fmt.Sprintf("Hello from client %d of %d.", i, len(clients))) @@ -142,10 +133,10 @@ func Test_symmetricClient_Smoke(t *testing.T) { } // Broadcast payload - _, _, err = clients[0].Broadcast(payload, cmix.GetDefaultCMIXParams()) + _, _, err := clients[0].Broadcast(payload, cmix.GetDefaultCMIXParams()) if err != nil { t.Errorf("Cmix 0 failed to send broadcast: %+v", err) } wg.Wait() -} +}*/ diff --git a/broadcast/utils_test.go b/broadcast/utils_test.go index 7bd4ac341a47f98359c76c7a06a5adb70f85f05f..ee1dfebc264c208e037bcbd45385bac6160fa154 100644 --- a/broadcast/utils_test.go +++ b/broadcast/utils_test.go @@ -1,40 +1,28 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package broadcast import ( + "sync" + "time" + + "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/id/ephemeral" + "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/primitives/format" - "gitlab.com/xx_network/crypto/signature/rsa" - "gitlab.com/xx_network/primitives/id" - "gitlab.com/xx_network/primitives/id/ephemeral" - "math/rand" - "sync" - "testing" - "time" ) -// newRsaPubKey generates a new random RSA public key for testing. -func newRsaPubKey(seed int64, t *testing.T) *rsa.PublicKey { - prng := rand.New(rand.NewSource(seed)) - privKey, err := rsa.GenerateKey(prng, 64) - if err != nil { - t.Errorf("Failed to generate new RSA key: %+v", err) - } - - return privKey.GetPublic() -} - //////////////////////////////////////////////////////////////////////////////// -// Mock cMix // +// Mock cMix // //////////////////////////////////////////////////////////////////////////////// type mockCmixHandler struct { @@ -56,7 +44,7 @@ type mockCmix struct { func newMockCmix(handler *mockCmixHandler) *mockCmix { return &mockCmix{ - numPrimeBytes: 4096, + numPrimeBytes: 4096 / 8, health: true, handler: handler, } @@ -66,6 +54,30 @@ func (m *mockCmix) GetMaxMessageLength() int { return format.NewMessage(m.numPrimeBytes).ContentsSize() } +func (m *mockCmix) SendWithAssembler(recipient *id.ID, + assembler cmix.MessageAssembler, _ cmix.CMIXParams) ( + rounds.Round, ephemeral.Id, error) { + + fingerprint, service, payload, mac, err := assembler(42) + if err != nil { + panic(err) + } + + msg := format.NewMessage(m.numPrimeBytes) + msg.SetContents(payload) + msg.SetMac(mac) + msg.SetKeyFP(fingerprint) + + m.handler.Lock() + defer m.handler.Unlock() + + for _, p := range m.handler.processorMap[*recipient][service.Tag] { + p.Process(msg, receptionID.EphemeralIdentity{}, rounds.Round{}) + } + + return rounds.Round{}, ephemeral.Id{}, nil +} + func (m *mockCmix) Send(recipient *id.ID, fingerprint format.Fingerprint, service message.Service, payload, mac []byte, _ cmix.CMIXParams) ( id.Round, ephemeral.Id, error) { diff --git a/catalog/messageTypes.go b/catalog/messageTypes.go index 9ab1244631e1c6265e2f8a4a205022f35d943ac0..acadac652c0777e1d58c805a753084547c8f36de 100644 --- a/catalog/messageTypes.go +++ b/catalog/messageTypes.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package catalog import "fmt" diff --git a/catalog/services.go b/catalog/services.go index 24ab74a466f6499654267861760b72cbc2d6472e..cb5ce516d3bc8cc5babbd8461da161ec23c5d72d 100644 --- a/catalog/services.go +++ b/catalog/services.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package catalog import "gitlab.com/elixxir/crypto/sih" diff --git a/channels/adminListener.go b/channels/adminListener.go new file mode 100644 index 0000000000000000000000000000000000000000..d9e203f1c0c4bab8be5fa14220130c773fd74ee5 --- /dev/null +++ b/channels/adminListener.go @@ -0,0 +1,68 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file // +//////////////////////////////////////////////////////////////////////////////// + +package channels + +import ( + "github.com/golang/protobuf/proto" + jww "github.com/spf13/jwalterweatherman" + "gitlab.com/elixxir/client/cmix/identity/receptionID" + "gitlab.com/elixxir/client/cmix/rounds" + "gitlab.com/elixxir/crypto/channel" + "gitlab.com/elixxir/primitives/states" + "gitlab.com/xx_network/primitives/id" +) + +// adminListener adheres to the [broadcast.ListenerFunc] interface and is used +// when admin messages are received on the channel. +type adminListener struct { + chID *id.ID + trigger triggerAdminEventFunc + checkSent messageReceiveFunc +} + +// Listen is called when a message is received for the admin listener +func (al *adminListener) Listen(payload []byte, + receptionID receptionID.EphemeralIdentity, round rounds.Round) { + // Get the message ID + msgID := channel.MakeMessageID(payload, al.chID) + + // Decode the message as a channel message + cm := &ChannelMessage{} + if err := proto.Unmarshal(payload, cm); err != nil { + jww.WARN.Printf("Failed to unmarshal Channel Message from Admin on "+ + "channel %s", al.chID) + return + } + + //check if we sent the message, ignore triggering if we sent + if al.checkSent(msgID, round) { + return + } + + /* CRYPTOGRAPHICALLY RELEVANT CHECKS */ + + // Check the round to ensure that the message is not a replay + if id.Round(cm.RoundID) != round.ID { + jww.WARN.Printf("The round message %s send on %s referenced "+ + "(%d) was not the same as the round the message was found on (%d)", + msgID, al.chID, cm.RoundID, round.ID) + return + } + + // Modify the timestamp to reduce the chance message order will be ambiguous + ts := mutateTimestamp(round.Timestamps[states.QUEUED], msgID) + + // Submit the message to the event model for listening + if uuid, err := al.trigger(al.chID, cm, ts, msgID, receptionID, + round, Delivered); err != nil { + jww.WARN.Printf("Error in passing off trigger for admin "+ + "message (UUID: %d): %+v", uuid, err) + } + + return +} diff --git a/channels/adminListener_test.go b/channels/adminListener_test.go new file mode 100644 index 0000000000000000000000000000000000000000..cb571d5724dcd7318d7ab4dec78bd2c0fe14866c --- /dev/null +++ b/channels/adminListener_test.go @@ -0,0 +1,231 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file // +//////////////////////////////////////////////////////////////////////////////// + +package channels + +import ( + "bytes" + "gitlab.com/xx_network/primitives/netTime" + "testing" + "time" + + "github.com/golang/protobuf/proto" + + "gitlab.com/elixxir/client/cmix/identity/receptionID" + "gitlab.com/elixxir/client/cmix/rounds" + cryptoChannel "gitlab.com/elixxir/crypto/channel" + "gitlab.com/elixxir/primitives/states" + "gitlab.com/xx_network/primitives/id" +) + +type triggerAdminEventDummy struct { + gotData bool + + chID *id.ID + cm *ChannelMessage + msgID cryptoChannel.MessageID + receptionID receptionID.EphemeralIdentity + round rounds.Round +} + +func (taed *triggerAdminEventDummy) triggerAdminEvent(chID *id.ID, + cm *ChannelMessage, ts time.Time, messageID cryptoChannel.MessageID, + receptionID receptionID.EphemeralIdentity, round rounds.Round, + status SentStatus) (uint64, error) { + taed.gotData = true + + taed.chID = chID + taed.cm = cm + taed.msgID = messageID + taed.receptionID = receptionID + taed.round = round + + return 0, nil +} + +// Tests the happy path. +func TestAdminListener_Listen(t *testing.T) { + + // Build inputs + chID := &id.ID{} + chID[0] = 1 + + r := rounds.Round{ID: 420, Timestamps: make(map[states.Round]time.Time)} + r.Timestamps[states.QUEUED] = netTime.Now() + + cm := &ChannelMessage{ + Lease: int64(time.Hour), + RoundID: uint64(r.ID), + PayloadType: 42, + Payload: []byte("blarg"), + } + + cmSerial, err := proto.Marshal(cm) + if err != nil { + t.Fatalf("Failed to marshal proto: %+v", err) + } + + msgID := cryptoChannel.MakeMessageID(cmSerial, chID) + + // Build the listener + dummy := &triggerAdminEventDummy{} + + al := adminListener{ + chID: chID, + trigger: dummy.triggerAdminEvent, + checkSent: func(messageID cryptoChannel.MessageID, r rounds.Round) bool { return false }, + } + + // Call the listener + al.Listen(cmSerial, receptionID.EphemeralIdentity{}, r) + + // Check the results + if !dummy.gotData { + t.Fatalf("No data returned after valid listen") + } + + if !dummy.chID.Cmp(chID) { + t.Errorf("Channel ID not correct: %s vs %s", dummy.chID, chID) + } + + if !bytes.Equal(cm.Payload, dummy.cm.Payload) { + t.Errorf("payload not correct: %s vs %s", cm.Payload, + dummy.cm.Payload) + } + + if !msgID.Equals(dummy.msgID) { + t.Errorf("messageIDs not correct: %s vs %s", msgID, + dummy.msgID) + } + + if r.ID != dummy.round.ID { + t.Errorf("rounds not correct: %s vs %s", r.ID, + dummy.round.ID) + } +} + +// Tests that the message is rejected when the round it came on doesn't match +// the round in the channel message. +func TestAdminListener_Listen_BadRound(t *testing.T) { + + // build inputs + chID := &id.ID{} + chID[0] = 1 + + r := rounds.Round{ID: 420, Timestamps: make(map[states.Round]time.Time)} + r.Timestamps[states.QUEUED] = netTime.Now() + + cm := &ChannelMessage{ + Lease: int64(time.Hour), + // Different from the round above + RoundID: 69, + PayloadType: 42, + Payload: []byte("blarg"), + } + + cmSerial, err := proto.Marshal(cm) + if err != nil { + t.Fatalf("Failed to marshal proto: %+v", err) + } + + // Build the listener + dummy := &triggerAdminEventDummy{} + + al := adminListener{ + chID: chID, + trigger: dummy.triggerAdminEvent, + checkSent: func(messageID cryptoChannel.MessageID, r rounds.Round) bool { return false }, + } + + // Call the listener + al.Listen(cmSerial, receptionID.EphemeralIdentity{}, r) + + // check the results + if dummy.gotData { + t.Fatalf("payload handled when it should have failed due to " + + "a round issue") + } + +} + +// Tests that the message is rejected when the channel message is malformed. +func TestAdminListener_Listen_BadChannelMessage(t *testing.T) { + + // Build inputs + chID := &id.ID{} + chID[0] = 1 + + r := rounds.Round{ID: 420, Timestamps: make(map[states.Round]time.Time)} + r.Timestamps[states.QUEUED] = netTime.Now() + + cmSerial := []byte("blarg") + + // Build the listener + dummy := &triggerAdminEventDummy{} + + al := adminListener{ + chID: chID, + trigger: dummy.triggerAdminEvent, + checkSent: func(messageID cryptoChannel.MessageID, r rounds.Round) bool { return false }, + } + + // Call the listener + al.Listen(cmSerial, receptionID.EphemeralIdentity{}, r) + + // Check the results + if dummy.gotData { + t.Fatalf("payload handled when it should have failed due to " + + "a malformed channel message") + } + +} + +// Tests that the message is rejected when the sized broadcast message is +// malformed. +func TestAdminListener_Listen_BadSizedBroadcast(t *testing.T) { + + // build inputs + chID := &id.ID{} + chID[0] = 1 + + r := rounds.Round{ID: 420, Timestamps: make(map[states.Round]time.Time)} + r.Timestamps[states.QUEUED] = netTime.Now() + + cm := &ChannelMessage{ + Lease: int64(time.Hour), + // Different from the round above + RoundID: 69, + PayloadType: 42, + Payload: []byte("blarg"), + } + + cmSerial, err := proto.Marshal(cm) + if err != nil { + t.Fatalf("Failed to marshal proto: %+v", err) + } + + // Remove half the sized broadcast to make it malformed + chMsgSerialSized := cmSerial[:len(cmSerial)/2] + + // Build the listener + dummy := &triggerAdminEventDummy{} + + al := adminListener{ + chID: chID, + trigger: dummy.triggerAdminEvent, + checkSent: func(messageID cryptoChannel.MessageID, r rounds.Round) bool { return false }, + } + + // Call the listener + al.Listen(chMsgSerialSized, receptionID.EphemeralIdentity{}, r) + + // Check the results + if dummy.gotData { + t.Fatalf("payload handled when it should have failed due to " + + "a malformed sized broadcast") + } +} diff --git a/channels/channelMessages.pb.go b/channels/channelMessages.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..911c35da9cfb33b1e319f64233c174f81f1c25d6 --- /dev/null +++ b/channels/channelMessages.pb.go @@ -0,0 +1,305 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file // +//////////////////////////////////////////////////////////////////////////////// + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.27.1 +// protoc v3.15.6 +// source: channelMessages.proto + +package channels + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// ChannelMessage is transmitted by the channel. Effectively it is a command for +// the channel sent by a user with admin access of the channel. +type ChannelMessage struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Lease is the length that this channel message will take effect. + Lease int64 `protobuf:"varint,1,opt,name=Lease,proto3" json:"Lease,omitempty"` + // The round this message was sent on. + RoundID uint64 `protobuf:"varint,2,opt,name=RoundID,proto3" json:"RoundID,omitempty"` + // The type the below payload is. This may be some form of channel command, + // such as BAN<username1>. + PayloadType uint32 `protobuf:"varint,3,opt,name=PayloadType,proto3" json:"PayloadType,omitempty"` + // Payload is the actual message payload. It will be processed differently + // based on the PayloadType. + Payload []byte `protobuf:"bytes,4,opt,name=Payload,proto3" json:"Payload,omitempty"` + // nickname is the name which the user is using for this message + // it will not be longer than 24 characters + Nickname string `protobuf:"bytes,5,opt,name=Nickname,proto3" json:"Nickname,omitempty"` + // Nonce is 32 bits of randomness to ensure that two messages in the same + // round with that have the same nickname, payload, and lease will not have + // the same message ID. + Nonce []byte `protobuf:"bytes,6,opt,name=Nonce,proto3" json:"Nonce,omitempty"` +} + +func (x *ChannelMessage) Reset() { + *x = ChannelMessage{} + if protoimpl.UnsafeEnabled { + mi := &file_channelMessages_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ChannelMessage) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ChannelMessage) ProtoMessage() {} + +func (x *ChannelMessage) ProtoReflect() protoreflect.Message { + mi := &file_channelMessages_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ChannelMessage.ProtoReflect.Descriptor instead. +func (*ChannelMessage) Descriptor() ([]byte, []int) { + return file_channelMessages_proto_rawDescGZIP(), []int{0} +} + +func (x *ChannelMessage) GetLease() int64 { + if x != nil { + return x.Lease + } + return 0 +} + +func (x *ChannelMessage) GetRoundID() uint64 { + if x != nil { + return x.RoundID + } + return 0 +} + +func (x *ChannelMessage) GetPayloadType() uint32 { + if x != nil { + return x.PayloadType + } + return 0 +} + +func (x *ChannelMessage) GetPayload() []byte { + if x != nil { + return x.Payload + } + return nil +} + +func (x *ChannelMessage) GetNickname() string { + if x != nil { + return x.Nickname + } + return "" +} + +func (x *ChannelMessage) GetNonce() []byte { + if x != nil { + return x.Nonce + } + return nil +} + +// UserMessage is a message sent by a user who is a member within the channel. +type UserMessage struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Message contains the contents of the message. This is typically what the + // end-user has submitted to the channel. This is a serialization of the + // ChannelMessage. + Message []byte `protobuf:"bytes,1,opt,name=Message,proto3" json:"Message,omitempty"` + // Signature is the signature proving this message has been sent by the + // owner of this user's public key. + // + // Signature = Sig(User_ECCPublicKey, Message) + Signature []byte `protobuf:"bytes,3,opt,name=Signature,proto3" json:"Signature,omitempty"` + // ECCPublicKey is the user's EC Public key. This is provided by the + // network. + ECCPublicKey []byte `protobuf:"bytes,5,opt,name=ECCPublicKey,proto3" json:"ECCPublicKey,omitempty"` +} + +func (x *UserMessage) Reset() { + *x = UserMessage{} + if protoimpl.UnsafeEnabled { + mi := &file_channelMessages_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UserMessage) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UserMessage) ProtoMessage() {} + +func (x *UserMessage) ProtoReflect() protoreflect.Message { + mi := &file_channelMessages_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UserMessage.ProtoReflect.Descriptor instead. +func (*UserMessage) Descriptor() ([]byte, []int) { + return file_channelMessages_proto_rawDescGZIP(), []int{1} +} + +func (x *UserMessage) GetMessage() []byte { + if x != nil { + return x.Message + } + return nil +} + +func (x *UserMessage) GetSignature() []byte { + if x != nil { + return x.Signature + } + return nil +} + +func (x *UserMessage) GetECCPublicKey() []byte { + if x != nil { + return x.ECCPublicKey + } + return nil +} + +var File_channelMessages_proto protoreflect.FileDescriptor + +var file_channelMessages_proto_rawDesc = []byte{ + 0x0a, 0x15, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x08, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, + 0x73, 0x22, 0xae, 0x01, 0x0a, 0x0e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x4c, 0x65, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x05, 0x4c, 0x65, 0x61, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x52, 0x6f, + 0x75, 0x6e, 0x64, 0x49, 0x44, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x52, 0x6f, 0x75, + 0x6e, 0x64, 0x49, 0x44, 0x12, 0x20, 0x0a, 0x0b, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x54, + 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x50, 0x61, 0x79, 0x6c, 0x6f, + 0x61, 0x64, 0x54, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, + 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, + 0x12, 0x1a, 0x0a, 0x08, 0x4e, 0x69, 0x63, 0x6b, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x4e, 0x69, 0x63, 0x6b, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, + 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x4e, 0x6f, 0x6e, + 0x63, 0x65, 0x22, 0x69, 0x0a, 0x0b, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x12, 0x18, 0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x53, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, + 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x45, 0x43, 0x43, + 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x0c, 0x45, 0x43, 0x43, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x42, 0x24, 0x5a, + 0x22, 0x67, 0x69, 0x74, 0x6c, 0x61, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x6c, 0x69, 0x78, + 0x78, 0x69, 0x72, 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2f, 0x63, 0x68, 0x61, 0x6e, 0x6e, + 0x65, 0x6c, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_channelMessages_proto_rawDescOnce sync.Once + file_channelMessages_proto_rawDescData = file_channelMessages_proto_rawDesc +) + +func file_channelMessages_proto_rawDescGZIP() []byte { + file_channelMessages_proto_rawDescOnce.Do(func() { + file_channelMessages_proto_rawDescData = protoimpl.X.CompressGZIP(file_channelMessages_proto_rawDescData) + }) + return file_channelMessages_proto_rawDescData +} + +var file_channelMessages_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_channelMessages_proto_goTypes = []interface{}{ + (*ChannelMessage)(nil), // 0: channels.ChannelMessage + (*UserMessage)(nil), // 1: channels.UserMessage +} +var file_channelMessages_proto_depIdxs = []int32{ + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_channelMessages_proto_init() } +func file_channelMessages_proto_init() { + if File_channelMessages_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_channelMessages_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ChannelMessage); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_channelMessages_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UserMessage); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_channelMessages_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_channelMessages_proto_goTypes, + DependencyIndexes: file_channelMessages_proto_depIdxs, + MessageInfos: file_channelMessages_proto_msgTypes, + }.Build() + File_channelMessages_proto = out.File + file_channelMessages_proto_rawDesc = nil + file_channelMessages_proto_goTypes = nil + file_channelMessages_proto_depIdxs = nil +} diff --git a/channels/channelMessages.proto b/channels/channelMessages.proto new file mode 100644 index 0000000000000000000000000000000000000000..548cfc67c9e8f02a750f12fff45bb27b8b613b4b --- /dev/null +++ b/channels/channelMessages.proto @@ -0,0 +1,57 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file // +//////////////////////////////////////////////////////////////////////////////// + +syntax = "proto3"; + +option go_package = "gitlab.com/elixxir/client/channels"; + +package channels; + +// ChannelMessage is transmitted by the channel. Effectively it is a command for +// the channel sent by a user with admin access of the channel. +message ChannelMessage{ + // Lease is the length that this channel message will take effect. + int64 Lease = 1; + + // The round this message was sent on. + uint64 RoundID = 2; + + // The type the below payload is. This may be some form of channel command, + // such as BAN<username1>. + uint32 PayloadType = 3; + + // Payload is the actual message payload. It will be processed differently + // based on the PayloadType. + bytes Payload = 4; + + // nickname is the name which the user is using for this message + // it will not be longer than 24 characters + string Nickname = 5; + + // Nonce is 32 bits of randomness to ensure that two messages in the same + // round with that have the same nickname, payload, and lease will not have + // the same message ID. + bytes Nonce = 6; +} + +// UserMessage is a message sent by a user who is a member within the channel. +message UserMessage { + // Message contains the contents of the message. This is typically what the + // end-user has submitted to the channel. This is a serialization of the + // ChannelMessage. + bytes Message = 1; + + // Signature is the signature proving this message has been sent by the + // owner of this user's public key. + // + // Signature = Sig(User_ECCPublicKey, Message) + bytes Signature = 3; + + // ECCPublicKey is the user's EC Public key. This is provided by the + // network. + bytes ECCPublicKey = 5; +} \ No newline at end of file diff --git a/channels/compileProtobuf.sh b/channels/compileProtobuf.sh new file mode 100644 index 0000000000000000000000000000000000000000..dff697ecd9976fa8330d7c45052f7b3ca8eef382 --- /dev/null +++ b/channels/compileProtobuf.sh @@ -0,0 +1,15 @@ +#!/bin/bash +################################################################################ +## Copyright © 2022 xx foundation ## +## ## +## Use of this source code is governed by a license that can be found in the ## +## LICENSE file. ## +################################################################################ + +# This script will compile the Protobuf file to a Go file (pb.go). +# This is meant to be called from the top level of the repo. + +cd ./channels/ || return + +protoc --go_out=. --go_opt=paths=source_relative ./channelMessages.proto +protoc --go_out=. --go_opt=paths=source_relative ./text.proto diff --git a/channels/dummyNameServer.go b/channels/dummyNameServer.go new file mode 100644 index 0000000000000000000000000000000000000000..8c14e40279d8091bf34f29a5a881246715c27c34 --- /dev/null +++ b/channels/dummyNameServer.go @@ -0,0 +1,109 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + +package channels + +import ( + "crypto/ed25519" + jww "github.com/spf13/jwalterweatherman" + "gitlab.com/elixxir/crypto/channel" + "gitlab.com/xx_network/primitives/netTime" + "io" + "time" +) + +// NewDummyNameService returns a dummy object adhering to the name service +// This neither produces valid signatures nor validates passed signatures. +// +// THIS IS FOR DEVELOPMENT AND DEBUGGING PURPOSES ONLY. +func NewDummyNameService(username string, rng io.Reader) (NameService, error) { + jww.WARN.Printf("Creating a Dummy Name Service. This is for " + + "development and debugging only. It does not produce valid " + + "signatures or verify passed signatures. YOU SHOULD NEVER SEE THIS " + + "MESSAGE IN PRODUCTION") + + dns := &dummyNameService{ + username: username, + lease: netTime.Now().Add(35 * 24 * time.Hour), + } + + //generate the private key + var err error + dns.public, dns.private, err = ed25519.GenerateKey(rng) + if err != nil { + return nil, err + } + + //generate a dummy user discover identity to produce a validation signature + //just sign with our own key, it wont be evaluated anyhow + dns.validationSig = channel.SignChannelLease(dns.public, dns.username, + dns.lease, dns.private) + + return dns, nil +} + +// dummyNameService is a dummy NameService implementation. This is NOT meant +// for use in production +type dummyNameService struct { + private ed25519.PrivateKey + public ed25519.PublicKey + username string + validationSig []byte + lease time.Time +} + +// GetUsername returns the username for the dummyNameService. This is what was +// passed in through NewDummyNameService. +// +// THIS IS FOR DEVELOPMENT AND DEBUGGING PURPOSES ONLY. +func (dns *dummyNameService) GetUsername() string { + return dns.username +} + +// GetChannelValidationSignature will return the dummy validation signature +// generated in through the constructor, NewDummyNameService. +// +// THIS IS FOR DEVELOPMENT AND DEBUGGING PURPOSES ONLY. +func (dns *dummyNameService) GetChannelValidationSignature() ([]byte, time.Time) { + jww.WARN.Printf("GetChannelValidationSignature called on Dummy Name " + + "Service, dummy signature from a random key returned - identity not " + + "proven. YOU SHOULD NEVER SEE THIS MESSAGE IN PRODUCTION") + return dns.validationSig, dns.lease +} + +// GetChannelPubkey returns the ed25519.PublicKey generates in the constructor, +// NewDummyNameService. +func (dns *dummyNameService) GetChannelPubkey() ed25519.PublicKey { + return dns.public +} + +// SignChannelMessage will sign the passed in message using the +// dummyNameService's private key. +// +// THIS IS FOR DEVELOPMENT AND DEBUGGING PURPOSES ONLY. +func (dns *dummyNameService) SignChannelMessage(message []byte) ( + signature []byte, err error) { + jww.WARN.Printf("SignChannelMessage called on Dummy Name Service, " + + "signature from a random key - identity not proven. YOU SHOULD " + + "NEVER SEE THIS MESSAGE IN PRODUCTION") + sig := ed25519.Sign(dns.private, message) + return sig, nil +} + +// ValidateChannelMessage will always return true, indicating the the channel +// message is valid. This will ignore the passed in arguments. As a result, +// these values may be dummy or precanned. +// +// THIS IS FOR DEVELOPMENT AND DEBUGGING PURPOSES ONLY. +func (dns *dummyNameService) ValidateChannelMessage(username string, lease time.Time, + pubKey ed25519.PublicKey, authorIDSignature []byte) bool { + //ignore the authorIDSignature + jww.WARN.Printf("ValidateChannelMessage called on Dummy Name Service, " + + "no validation done - identity not validated. YOU SHOULD NEVER SEE " + + "THIS MESSAGE IN PRODUCTION") + return true +} diff --git a/channels/dummyNameServer_test.go b/channels/dummyNameServer_test.go new file mode 100644 index 0000000000000000000000000000000000000000..183da2abaa10cbd811048023c6447f61f3261ae4 --- /dev/null +++ b/channels/dummyNameServer_test.go @@ -0,0 +1,126 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + +package channels + +import ( + "crypto/ed25519" + "gitlab.com/xx_network/crypto/csprng" + "gitlab.com/xx_network/primitives/netTime" + "testing" +) + +const numTests = 10 + +// Smoke test. +func TestNewDummyNameService(t *testing.T) { + rng := csprng.NewSystemRNG() + username := "floridaMan" + _, err := NewDummyNameService(username, rng) + if err != nil { + t.Fatalf("NewDummyNameService error: %+v", err) + } + +} + +// Smoke test. +func TestDummyNameService_GetUsername(t *testing.T) { + rng := csprng.NewSystemRNG() + username := "floridaMan" + ns, err := NewDummyNameService(username, rng) + if err != nil { + t.Fatalf("NewDummyNameService error: %+v", err) + } + + if username != ns.GetUsername() { + t.Fatalf("GetUsername did not return expected value."+ + "\nExpected: %s"+ + "\nReceived: %s", username, ns.GetUsername()) + } + +} + +// Smoke test. +func TestDummyNameService_SignChannelMessage(t *testing.T) { + rng := csprng.NewSystemRNG() + username := "floridaMan" + ns, err := NewDummyNameService(username, rng) + if err != nil { + t.Fatalf("NewDummyNameService error: %+v", err) + } + + message := []byte("the secret is in the sauce.") + + signature, err := ns.SignChannelMessage(message) + if err != nil { + t.Fatalf("SignChannelMessage error: %v", err) + } + + if len(signature) != ed25519.SignatureSize { + t.Errorf("DummyNameService's SignChannelMessage did not return a "+ + "signature of expected size, according to ed25519 specifications."+ + "\nExpected: %d"+ + "\nReceived: %d", ed25519.SignatureSize, len(signature)) + } + +} + +// Smoke test. +func TestDummyNameService_GetChannelValidationSignature(t *testing.T) { + rng := csprng.NewSystemRNG() + username := "floridaMan" + ns, err := NewDummyNameService(username, rng) + if err != nil { + t.Fatalf("NewDummyNameService error: %+v", err) + } + + validationSig, _ := ns.GetChannelValidationSignature() + + if len(validationSig) != ed25519.SignatureSize { + t.Errorf("DummyNameService's GetChannelValidationSignature did not "+ + "return a validation signature of expected size, according to "+ + "ed25519 specifications."+ + "\nExpected: %d"+ + "\nReceived: %d", ed25519.SignatureSize, len(validationSig)) + } + +} + +// Smoke test. +func TestDummyNameService_ValidateChannelMessage(t *testing.T) { + rng := csprng.NewSystemRNG() + username := "floridaMan" + ns, err := NewDummyNameService(username, rng) + if err != nil { + t.Fatalf("NewDummyNameService error: %+v", err) + } + + for i := 0; i < numTests; i++ { + if !ns.ValidateChannelMessage(username, netTime.Now(), nil, nil) { + t.Errorf("ValidateChannelMessage returned false. This should " + + "only ever return true.") + } + } +} + +// Smoke test. +func TestDummyNameService_GetChannelPubkey(t *testing.T) { + rng := csprng.NewSystemRNG() + username := "floridaMan" + ns, err := NewDummyNameService(username, rng) + if err != nil { + t.Fatalf("NewDummyNameService error: %+v", err) + } + + if len(ns.GetChannelPubkey()) != ed25519.PublicKeySize { + t.Errorf("DummyNameService's GetChannelPubkey did not "+ + "return a validation signature of expected size, according to "+ + "ed25519 specifications."+ + "\nExpected: %d"+ + "\nReceived: %d", ed25519.PublicKeySize, ns.GetChannelPubkey()) + } +} diff --git a/channels/emoji.go b/channels/emoji.go new file mode 100644 index 0000000000000000000000000000000000000000..71c7ae4f66dd6b96e812521056f44a548fbf74c6 --- /dev/null +++ b/channels/emoji.go @@ -0,0 +1,37 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file // +//////////////////////////////////////////////////////////////////////////////// + +package channels + +import ( + "bytes" + "regexp" +) + +//based on emojis found at https://unicode.org/emoji/charts/full-emoji-list.html +const findEmoji = `[\xA9\xAE\x{2000}-\x{3300}\x{1F000}-\x{1FBFF}]` + +var compiledFindEmoji = regexp.MustCompile(findEmoji) + +// ValidateReaction checks that the reaction only contains a single emoji. +func ValidateReaction(reaction string) error { + + //make sure it is only only character + reactRunes := []rune(reaction) + if len(reactRunes) > 1 { + return InvalidReaction + } + + reader := bytes.NewReader([]byte(reaction)) + + // make sure it has emojis + if !compiledFindEmoji.MatchReader(reader) { + return InvalidReaction + } + + return nil +} diff --git a/channels/emoji_test.go b/channels/emoji_test.go new file mode 100644 index 0000000000000000000000000000000000000000..d320b05a6b0a404f23d3412aca8fb6a1fea393ef --- /dev/null +++ b/channels/emoji_test.go @@ -0,0 +1,35 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file // +//////////////////////////////////////////////////////////////////////////////// + +package channels + +import ( + "testing" +) + +func TestValidateReaction(t *testing.T) { + + testReactions := []string{"🍆", "😂", "❤", "🤣", "👍", "😭", "🙏", "😘", "🥰", + "😍", "😊", "☺", "A", "b", "AA", "1", "🍆🍆", "🍆A", "👍👍👍", "👍😘A", + "O", "\u0000", "\u0011", "\u001F", "\u007F", "\u0080", "\u008A", + "\u009F"} + + expected := []error{ + nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, + InvalidReaction, InvalidReaction, InvalidReaction, InvalidReaction, + InvalidReaction, InvalidReaction, InvalidReaction, InvalidReaction, + InvalidReaction, InvalidReaction, InvalidReaction, InvalidReaction, + InvalidReaction, InvalidReaction, InvalidReaction, InvalidReaction} + + for i, r := range testReactions { + err := ValidateReaction(r) + if err != expected[i] { + t.Errorf("Got incorrect response for `%s` (%d): "+ + "`%s` vs `%s`", r, i, err, expected[i]) + } + } +} diff --git a/channels/errors.go b/channels/errors.go new file mode 100644 index 0000000000000000000000000000000000000000..319f065966a899f5a64c05b41eda84caa887fd02 --- /dev/null +++ b/channels/errors.go @@ -0,0 +1,25 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file // +//////////////////////////////////////////////////////////////////////////////// + +package channels + +import "github.com/pkg/errors" + +var ( + ChannelAlreadyExistsErr = errors.New( + "the channel cannot be added because it already exists") + ChannelDoesNotExistsErr = errors.New( + "the channel cannot be found") + MessageTooLongErr = errors.New( + "the passed message is too long") + WrongPrivateKey = errors.New( + "the passed private key does not match the channel") + MessageTypeAlreadyRegistered = errors.New("the given message type has " + + "already been registered") + InvalidReaction = errors.New( + "The reaction is not valid, it must be a single emoji") +) diff --git a/channels/eventModel.go b/channels/eventModel.go new file mode 100644 index 0000000000000000000000000000000000000000..26db7539a4b8b5635b7dbfdb39b1714fa180199d --- /dev/null +++ b/channels/eventModel.go @@ -0,0 +1,358 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file // +//////////////////////////////////////////////////////////////////////////////// + +package channels + +import ( + "errors" + "fmt" + "github.com/golang/protobuf/proto" + jww "github.com/spf13/jwalterweatherman" + "gitlab.com/elixxir/client/cmix/identity/receptionID" + "sync" + "time" + + "gitlab.com/elixxir/client/cmix/rounds" + cryptoBroadcast "gitlab.com/elixxir/crypto/broadcast" + cryptoChannel "gitlab.com/elixxir/crypto/channel" + "gitlab.com/xx_network/primitives/id" +) + +// AdminUsername defines the displayed username of admin messages, which are +// unique users for every channel defined by the channel's private key. +const AdminUsername = "Admin" + +type SentStatus uint8 + +const ( + Unsent SentStatus = iota + Sent + Delivered + Failed +) + +// EventModel is an interface which an external party which uses the channels +// system passed an object which adheres to in order to get events on the +// channel. +type EventModel interface { + // JoinChannel is called whenever a channel is joined locally. + JoinChannel(channel *cryptoBroadcast.Channel) + + // LeaveChannel is called whenever a channel is left locally. + LeaveChannel(channelID *id.ID) + + // ReceiveMessage is called whenever a message is received on a given + // channel. It may be called multiple times on the same message. It is + // incumbent on the user of the API to filter such called by message ID. + // + // the api needs to return a uuid of the message which it may be + // referenced at a later time + // + // messageID, timestamp, and round are all nillable and may be updated + // based upon the UUID at a later date. A time of time.Time{} will be + // passed for a nilled timestamp. + // + // Nickname may be empty, in which case the UI is expected to display + // the codename + // + // Message type is included in the call, it will always be Text (1) + // for this call, but it may be required in downstream databases + ReceiveMessage(channelID *id.ID, messageID cryptoChannel.MessageID, + nickname, text string, identity cryptoChannel.Identity, + timestamp time.Time, lease time.Duration, round rounds.Round, + mType MessageType, status SentStatus) uint64 + + // ReceiveReply is called whenever a message is received that is a reply on + // a given channel. It may be called multiple times on the same message. It + // is incumbent on the user of the API to filter such called by message ID. + // + // Messages may arrive our of order, so a reply in theory can arrive before + // the initial message. As a result, it may be important to buffer replies. + // + // the api needs to return a uuid of the message which it may be + // referenced at a later time + // + // messageID, timestamp, and round are all nillable and may be updated + // based upon the UUID at a later date. A time of time.Time{} will be + // passed for a nilled timestamp. + // + // Nickname may be empty, in which case the UI is expected to display + // the codename + // + // Message type is included in the call, it will always be Text (1) for + // this call, but it may be required in downstream databases + ReceiveReply(channelID *id.ID, messageID cryptoChannel.MessageID, + reactionTo cryptoChannel.MessageID, nickname, text string, + identity cryptoChannel.Identity, timestamp time.Time, + lease time.Duration, round rounds.Round, mType MessageType, + status SentStatus) uint64 + + // ReceiveReaction is called whenever a reaction to a message is received + // on a given channel. It may be called multiple times on the same reaction. + // It is incumbent on the user of the API to filter such called by message + // ID. + // + // Messages may arrive our of order, so a reply in theory can arrive before + // the initial message. As a result, it may be important to buffer + // reactions. + // + // the api needs to return a uuid of the message which it may be + // referenced at a later time + // + // messageID, timestamp, and round are all nillable and may be updated + // based upon the UUID at a later date. A time of time.Time{} will be + // passed for a nilled timestamp. + // + // Nickname may be empty, in which case the UI is expected to display + // the codename + // + // Message type is included in the call, it will always be Reaction (3) for + // this call, but it may be required in downstream databases + ReceiveReaction(channelID *id.ID, messageID cryptoChannel.MessageID, + reactionTo cryptoChannel.MessageID, nickname, reaction string, + identity cryptoChannel.Identity, timestamp time.Time, + lease time.Duration, round rounds.Round, mType MessageType, + status SentStatus) uint64 + + // UpdateSentStatus is called whenever the sent status of a message has + // changed. + // + // messageID, timestamp, and round are all nillable and may be updated + // based upon the UUID at a later date. A time of time.Time{} will be + // passed for a nilled timestamp. If a nil value is passed, make no update + UpdateSentStatus(uuid uint64, messageID cryptoChannel.MessageID, + timestamp time.Time, round rounds.Round, status SentStatus) + + // unimplemented + // IgnoreMessage(ChannelID *id.ID, MessageID cryptoChannel.MessageID) + // UnIgnoreMessage(ChannelID *id.ID, MessageID cryptoChannel.MessageID) + // PinMessage(ChannelID *id.ID, MessageID cryptoChannel.MessageID, end time.Time) + // UnPinMessage(ChannelID *id.ID, MessageID cryptoChannel.MessageID) +} + +// MessageTypeReceiveMessage defines handlers for messages of various message +// types. Default ones for Text, Reaction, and AdminText. +// A unique uuid must be returned by which the message can be referenced later +// via UpdateSentStatus +// It must return a unique UUID for the message by which it can be referenced +// later +type MessageTypeReceiveMessage func(channelID *id.ID, + messageID cryptoChannel.MessageID, messageType MessageType, + nickname string, content []byte, identity cryptoChannel.Identity, + timestamp time.Time, lease time.Duration, round rounds.Round, + status SentStatus) uint64 + +// updateStatusFunc is a function type for EventModel.UpdateSentStatus so it can +// be mocked for testing where used. +type updateStatusFunc func(uuid uint64, messageID cryptoChannel.MessageID, + timestamp time.Time, round rounds.Round, status SentStatus) + +// events is an internal structure that processes events and stores the handlers +// for those events. +type events struct { + model EventModel + registered map[MessageType]MessageTypeReceiveMessage + mux sync.RWMutex +} + +// initEvents initializes the event model and registers default message type +// handlers. +func initEvents(model EventModel) *events { + e := &events{ + model: model, + registered: make(map[MessageType]MessageTypeReceiveMessage), + mux: sync.RWMutex{}, + } + + // set up default message types + e.registered[Text] = e.receiveTextMessage + e.registered[AdminText] = e.receiveTextMessage + e.registered[Reaction] = e.receiveReaction + return e +} + +// RegisterReceiveHandler is used to register handlers for non default message +// types s they can be processed by modules. It is important that such modules +// sync up with the event model implementation. +// +// There can only be one handler per message type, and this will return an error +// on a multiple registration. +func (e *events) RegisterReceiveHandler(messageType MessageType, + listener MessageTypeReceiveMessage) error { + e.mux.Lock() + defer e.mux.Unlock() + + // check if the type is already registered + if _, exists := e.registered[messageType]; exists { + return MessageTypeAlreadyRegistered + } + + // register the message type + e.registered[messageType] = listener + jww.INFO.Printf("Registered Listener for Message Type %s", messageType) + return nil +} + +type triggerEventFunc func(chID *id.ID, umi *userMessageInternal, ts time.Time, + receptionID receptionID.EphemeralIdentity, round rounds.Round, + status SentStatus) (uint64, error) + +// triggerEvent is an internal function that is used to trigger message +// reception on a message received from a user (symmetric encryption). +// +// It will call the appropriate MessageTypeHandler assuming one exists. +func (e *events) triggerEvent(chID *id.ID, umi *userMessageInternal, ts time.Time, + receptionID receptionID.EphemeralIdentity, round rounds.Round, + status SentStatus) (uint64, error) { + um := umi.GetUserMessage() + cm := umi.GetChannelMessage() + messageType := MessageType(cm.PayloadType) + + identity := cryptoChannel.ConstructIdentity(um.ECCPublicKey) + + // Check if the type is already registered + e.mux.RLock() + listener, exists := e.registered[messageType] + e.mux.RUnlock() + if !exists { + errStr := fmt.Sprintf("Received message from %s on channel %s in "+ + "round %d which could not be handled due to unregistered message "+ + "type %s; Contents: %v", identity.Codename, chID, round.ID, messageType, + cm.Payload) + jww.WARN.Printf(errStr) + return 0, errors.New(errStr) + } + + // Call the listener. This is already in an instanced event, no new thread needed. + uuid := listener(chID, umi.GetMessageID(), messageType, cm.Nickname, cm.Payload, identity, + ts, time.Duration(cm.Lease), round, status) + return uuid, nil +} + +type triggerAdminEventFunc func(chID *id.ID, cm *ChannelMessage, ts time.Time, + messageID cryptoChannel.MessageID, receptionID receptionID.EphemeralIdentity, + round rounds.Round, status SentStatus) (uint64, error) + +// triggerAdminEvent is an internal function that is used to trigger message +// reception on a message received from the admin (asymmetric encryption). +// +// It will call the appropriate MessageTypeHandler assuming one exists. +func (e *events) triggerAdminEvent(chID *id.ID, cm *ChannelMessage, + ts time.Time, messageID cryptoChannel.MessageID, + receptionID receptionID.EphemeralIdentity, round rounds.Round, + status SentStatus) (uint64, error) { + messageType := MessageType(cm.PayloadType) + + // check if the type is already registered + e.mux.RLock() + listener, exists := e.registered[messageType] + e.mux.RUnlock() + if !exists { + errStr := fmt.Sprintf("Received Admin message from %s on channel %s in "+ + "round %d which could not be handled due to unregistered message "+ + "type %s; Contents: %v", AdminUsername, chID, round.ID, messageType, + cm.Payload) + jww.WARN.Printf(errStr) + return 0, errors.New(errStr) + } + + // Call the listener. This is already in an instanced event, no new thread needed. + uuid := listener(chID, messageID, messageType, AdminUsername, cm.Payload, + cryptoChannel.Identity{Codename: AdminUsername}, ts, + time.Duration(cm.Lease), round, status) + return uuid, nil +} + +// receiveTextMessage is the internal function that handles the reception of +// text messages. It handles both messages and replies and calls the correct +// function on the event model. +// +// If the message has a reply, but it is malformed, it will drop the reply and +// write to the log. +func (e *events) receiveTextMessage(channelID *id.ID, + messageID cryptoChannel.MessageID, messageType MessageType, + nickname string, content []byte, identity cryptoChannel.Identity, + timestamp time.Time, lease time.Duration, round rounds.Round, + status SentStatus) uint64 { + txt := &CMIXChannelText{} + + if err := proto.Unmarshal(content, txt); err != nil { + jww.ERROR.Printf("Failed to text unmarshal message %s from %s on "+ + "channel %s, type %s, ts: %s, lease: %s, round: %d: %+v", + messageID, identity.Codename, channelID, messageType, timestamp, lease, + round.ID, err) + return 0 + } + + if txt.ReplyMessageID != nil { + + if len(txt.ReplyMessageID) == cryptoChannel.MessageIDLen { + var replyTo cryptoChannel.MessageID + copy(replyTo[:], txt.ReplyMessageID) + return e.model.ReceiveReply(channelID, messageID, replyTo, + nickname, txt.Text, identity, timestamp, lease, round, Text, status) + + } else { + jww.ERROR.Printf("Failed process reply to for message %s from %s on "+ + "channel %s, type %s, ts: %s, lease: %s, round: %d, returning "+ + "without reply", + messageID, identity.Codename, channelID, messageType, timestamp, lease, + round.ID) + // Still process the message, but drop the reply because it is + // malformed + } + } + + return e.model.ReceiveMessage(channelID, messageID, nickname, txt.Text, identity, + timestamp, lease, round, Text, status) +} + +// receiveReaction is the internal function that handles the reception of +// Reactions. +// +// It does edge checking to ensure the received reaction is just a single emoji. +// If the received reaction is not, the reaction is dropped. +// If the messageID for the message the reaction is to is malformed, the +// reaction is dropped. +func (e *events) receiveReaction(channelID *id.ID, + messageID cryptoChannel.MessageID, messageType MessageType, + nickname string, content []byte, identity cryptoChannel.Identity, + timestamp time.Time, lease time.Duration, round rounds.Round, + status SentStatus) uint64 { + react := &CMIXChannelReaction{} + if err := proto.Unmarshal(content, react); err != nil { + jww.ERROR.Printf("Failed to text unmarshal message %s from %s on "+ + "channel %s, type %s, ts: %s, lease: %s, round: %d: %+v", + messageID, identity.Codename, channelID, messageType, timestamp, lease, + round.ID, err) + return 0 + } + + // check that the reaction is a single emoji and ignore if it isn't + if err := ValidateReaction(react.Reaction); err != nil { + jww.ERROR.Printf("Failed process reaction %s from %s on channel "+ + "%s, type %s, ts: %s, lease: %s, round: %d, due to malformed "+ + "reaction (%s), ignoring reaction", + messageID, identity.Codename, channelID, messageType, timestamp, lease, + round.ID, err) + return 0 + } + + if react.ReactionMessageID != nil && len(react.ReactionMessageID) == cryptoChannel.MessageIDLen { + var reactTo cryptoChannel.MessageID + copy(reactTo[:], react.ReactionMessageID) + return e.model.ReceiveReaction(channelID, messageID, reactTo, nickname, + react.Reaction, identity, timestamp, lease, round, Reaction, status) + } else { + jww.ERROR.Printf("Failed process reaction %s from %s on channel "+ + "%s, type %s, ts: %s, lease: %s, round: %d, reacting to "+ + "invalid message, ignoring reaction", + messageID, identity.Codename, channelID, messageType, timestamp, lease, + round.ID) + } + return 0 +} diff --git a/channels/eventModel_test.go b/channels/eventModel_test.go new file mode 100644 index 0000000000000000000000000000000000000000..89f30f3ef36a5362a94eb33746d76a6c976e339d --- /dev/null +++ b/channels/eventModel_test.go @@ -0,0 +1,905 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file // +//////////////////////////////////////////////////////////////////////////////// + +package channels + +import ( + "bytes" + "fmt" + "github.com/golang/protobuf/proto" + "gitlab.com/elixxir/client/cmix/identity/receptionID" + "gitlab.com/elixxir/client/cmix/rounds" + cryptoBroadcast "gitlab.com/elixxir/crypto/broadcast" + cryptoChannel "gitlab.com/elixxir/crypto/channel" + "gitlab.com/elixxir/primitives/states" + "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/netTime" + "math/rand" + "reflect" + "runtime" + "testing" + "time" +) + +type eventReceive struct { + channelID *id.ID + messageID cryptoChannel.MessageID + reactionTo cryptoChannel.MessageID + nickname string + content []byte + timestamp time.Time + lease time.Duration + round rounds.Round +} + +type MockEvent struct { + uuid uint64 + eventReceive +} + +func (m *MockEvent) getUUID() uint64 { + old := m.uuid + m.uuid++ + return old +} + +func (m *MockEvent) UpdateSentStatus(uuid uint64, messageID cryptoChannel.MessageID, + timestamp time.Time, round rounds.Round, status SentStatus) { + //TODO implement me + panic("implement me") +} + +func (*MockEvent) JoinChannel(channel *cryptoBroadcast.Channel) {} +func (*MockEvent) LeaveChannel(channelID *id.ID) {} +func (m *MockEvent) ReceiveMessage(channelID *id.ID, messageID cryptoChannel.MessageID, + nickname, text string, identity cryptoChannel.Identity, + timestamp time.Time, lease time.Duration, round rounds.Round, + mType MessageType, status SentStatus) uint64 { + m.eventReceive = eventReceive{ + channelID: channelID, + messageID: messageID, + reactionTo: cryptoChannel.MessageID{}, + nickname: nickname, + content: []byte(text), + timestamp: timestamp, + lease: lease, + round: round, + } + return m.getUUID() +} +func (m *MockEvent) ReceiveReply(channelID *id.ID, messageID cryptoChannel.MessageID, + reactionTo cryptoChannel.MessageID, nickname, text string, + identity cryptoChannel.Identity, timestamp time.Time, + lease time.Duration, round rounds.Round, mType MessageType, status SentStatus) uint64 { + fmt.Println(reactionTo) + m.eventReceive = eventReceive{ + channelID: channelID, + messageID: messageID, + reactionTo: reactionTo, + nickname: nickname, + content: []byte(text), + timestamp: timestamp, + lease: lease, + round: round, + } + return m.getUUID() +} +func (m *MockEvent) ReceiveReaction(channelID *id.ID, messageID cryptoChannel.MessageID, + reactionTo cryptoChannel.MessageID, nickname, reaction string, + identity cryptoChannel.Identity, timestamp time.Time, + lease time.Duration, round rounds.Round, mType MessageType, status SentStatus) uint64 { + m.eventReceive = eventReceive{ + channelID: channelID, + messageID: messageID, + reactionTo: reactionTo, + nickname: nickname, + content: []byte(reaction), + timestamp: timestamp, + lease: lease, + round: round, + } + return m.getUUID() +} + +func Test_initEvents(t *testing.T) { + + me := &MockEvent{} + + e := initEvents(me) + + // verify the model is registered + if e.model != me { + t.Errorf("Event model is not registered") + } + + // check registered channels was created + if e.registered == nil { + t.Fatalf("Registered handlers is not registered") + } + + // check that all the default callbacks are registered + if len(e.registered) != 3 { + t.Errorf("The correct number of default handlers are not "+ + "registered; %d vs %d", len(e.registered), 3) + //If this fails, is means the default handlers have changed. edit the + //number here and add tests below. be suspicious if it goes down. + } + + if getFuncName(e.registered[Text]) != getFuncName(e.receiveTextMessage) { + t.Errorf("Text does not have recieveTextMessageRegistred") + } + + if getFuncName(e.registered[AdminText]) != getFuncName(e.receiveTextMessage) { + t.Errorf("AdminText does not have recieveTextMessageRegistred") + } + + if getFuncName(e.registered[Reaction]) != getFuncName(e.receiveReaction) { + t.Errorf("Reaction does not have recieveReaction") + } +} + +func TestEvents_RegisterReceiveHandler(t *testing.T) { + me := &MockEvent{} + + e := initEvents(me) + + //test that a new receive handler can be registered. + mt := MessageType(42) + err := e.RegisterReceiveHandler(mt, e.receiveReaction) + if err != nil { + t.Fatalf("Failed to register '%s' when it should be "+ + "sucesfull: %+v", mt, err) + } + + //check that it is written + returnedHandler, exists := e.registered[mt] + if !exists { + t.Fatalf("Failed to get handler '%s' after registration", mt) + } + + //check that the correct function is written + if getFuncName(e.receiveReaction) != getFuncName(returnedHandler) { + t.Fatalf("Failed to get correct handler for '%s' after "+ + "registration, %s vs %s", mt, getFuncName(e.receiveReaction), + getFuncName(returnedHandler)) + } + + //test that writing to the same receive handler fails + err = e.RegisterReceiveHandler(mt, e.receiveTextMessage) + if err == nil { + t.Fatalf("Failed to register '%s' when it should be "+ + "sucesfull: %+v", mt, err) + } else if err != MessageTypeAlreadyRegistered { + t.Fatalf("Wrong error returned when reregierting message "+ + "tyle '%s': %+v", mt, err) + } + + //check that it is still written + returnedHandler, exists = e.registered[mt] + if !exists { + t.Fatalf("Failed to get handler '%s' after second "+ + "registration", mt) + } + + //check that the correct function is written + if getFuncName(e.receiveReaction) != getFuncName(returnedHandler) { + t.Fatalf("Failed to get correct handler for '%s' after "+ + "second registration, %s vs %s", mt, getFuncName(e.receiveReaction), + getFuncName(returnedHandler)) + } +} + +type dummyMessageTypeHandler struct { + triggered bool + channelID *id.ID + messageID cryptoChannel.MessageID + messageType MessageType + nickname string + content []byte + timestamp time.Time + lease time.Duration + round rounds.Round +} + +func (dmth *dummyMessageTypeHandler) dummyMessageTypeReceiveMessage(channelID *id.ID, + messageID cryptoChannel.MessageID, messageType MessageType, + nickname string, content []byte, identity cryptoChannel.Identity, + timestamp time.Time, lease time.Duration, round rounds.Round, + status SentStatus) uint64 { + dmth.triggered = true + dmth.channelID = channelID + dmth.messageID = messageID + dmth.messageType = messageType + dmth.nickname = nickname + dmth.content = content + dmth.timestamp = timestamp + dmth.lease = lease + dmth.round = round + return rand.Uint64() +} + +func TestEvents_triggerEvents(t *testing.T) { + me := &MockEvent{} + + e := initEvents(me) + + dummy := &dummyMessageTypeHandler{} + + //register the handler + mt := MessageType(42) + err := e.RegisterReceiveHandler(mt, dummy.dummyMessageTypeReceiveMessage) + if err != nil { + t.Fatalf("Error on registration, should not have happened: "+ + "%+v", err) + } + + //craft the input for the event + chID := &id.ID{} + chID[0] = 1 + + umi, _, _ := builtTestUMI(t, mt) + + r := rounds.Round{ID: 420, Timestamps: make(map[states.Round]time.Time)} + r.Timestamps[states.QUEUED] = netTime.Now() + + //call the trigger + _, err = e.triggerEvent(chID, umi, netTime.Now(), receptionID.EphemeralIdentity{}, r, Delivered) + if err != nil { + t.Fatalf(err.Error()) + } + //check that the event was triggered + if !dummy.triggered { + t.Errorf("The event was not triggered") + } + + //check the data is stored in the dummy + if !dummy.channelID.Cmp(chID) { + t.Errorf("The channel IDs do not match %s vs %s", + dummy.channelID, chID) + } + + if !dummy.messageID.Equals(umi.GetMessageID()) { + t.Errorf("The message IDs do not match %s vs %s", + dummy.messageID, umi.GetMessageID()) + } + + if dummy.messageType != mt { + t.Errorf("The message types do not match %s vs %s", + dummy.messageType, mt) + } + + if dummy.nickname != umi.channelMessage.Nickname { + t.Errorf("The usernames do not match %s vs %s", + dummy.nickname, umi.channelMessage.Nickname) + } + + if !bytes.Equal(dummy.content, umi.GetChannelMessage().Payload) { + t.Errorf("The payloads do not match %s vs %s", + dummy.content, umi.GetChannelMessage().Payload) + } + + if !withinMutationWindow(r.Timestamps[states.QUEUED], dummy.timestamp) { + t.Errorf("The timestamps do not match %s vs %s", + dummy.timestamp, r.Timestamps[states.QUEUED]) + } + + if dummy.lease != time.Duration(umi.GetChannelMessage().Lease) { + t.Errorf("The messge lease durations do not match %s vs %s", + dummy.lease, time.Duration(umi.GetChannelMessage().Lease)) + } + + if dummy.round.ID != r.ID { + t.Errorf("The messge round does not match %s vs %s", + dummy.round.ID, r.ID) + } +} + +func TestEvents_triggerEvents_noChannel(t *testing.T) { + me := &MockEvent{} + + e := initEvents(me) + + dummy := &dummyMessageTypeHandler{} + + //skip handler registration + mt := MessageType(1) + + //craft the input for the event + chID := &id.ID{} + chID[0] = 1 + + umi, _, _ := builtTestUMI(t, mt) + + r := rounds.Round{ID: 420, Timestamps: make(map[states.Round]time.Time)} + r.Timestamps[states.QUEUED] = netTime.Now() + + //call the trigger + _, err := e.triggerEvent(chID, umi, netTime.Now(), receptionID.EphemeralIdentity{}, r, Delivered) + if err != nil { + t.Fatalf(err.Error()) + } + + //check that the event was triggered + if dummy.triggered { + t.Errorf("The event was triggered when it is unregistered") + } +} + +func TestEvents_triggerAdminEvents(t *testing.T) { + me := &MockEvent{} + + e := initEvents(me) + + dummy := &dummyMessageTypeHandler{} + + //register the handler + mt := MessageType(42) + err := e.RegisterReceiveHandler(mt, dummy.dummyMessageTypeReceiveMessage) + if err != nil { + t.Fatalf("Error on registration, should not have happened: "+ + "%+v", err) + } + + //craft the input for the event + chID := &id.ID{} + chID[0] = 1 + + u, _, cm := builtTestUMI(t, mt) + + r := rounds.Round{ID: 420, Timestamps: make(map[states.Round]time.Time)} + r.Timestamps[states.QUEUED] = netTime.Now() + + msgID := cryptoChannel.MakeMessageID(u.userMessage.Message, chID) + + //call the trigger + _, err = e.triggerAdminEvent(chID, cm, netTime.Now(), msgID, receptionID.EphemeralIdentity{}, r, + Delivered) + if err != nil { + t.Fatalf(err.Error()) + } + + //check that the event was triggered + if !dummy.triggered { + t.Errorf("The admin event was not triggered") + } + + //check the data is stored in the dummy + if !dummy.channelID.Cmp(chID) { + t.Errorf("The channel IDs do not match %s vs %s", + dummy.channelID, chID) + } + + if !dummy.messageID.Equals(msgID) { + t.Errorf("The message IDs do not match %s vs %s", + dummy.messageID, msgID) + } + + if dummy.messageType != mt { + t.Errorf("The message types do not match %s vs %s", + dummy.messageType, mt) + } + + if dummy.nickname != AdminUsername { + t.Errorf("The usernames do not match %s vs %s", + dummy.nickname, AdminUsername) + } + + if !bytes.Equal(dummy.content, cm.Payload) { + t.Errorf("The payloads do not match %s vs %s", + dummy.content, cm.Payload) + } + + if !withinMutationWindow(r.Timestamps[states.QUEUED], dummy.timestamp) { + t.Errorf("The timestamps do not match %s vs %s", + dummy.timestamp, r.Timestamps[states.QUEUED]) + } + + if dummy.lease != time.Duration(cm.Lease) { + t.Errorf("The messge lease durations do not match %s vs %s", + dummy.lease, time.Duration(cm.Lease)) + } + + if dummy.round.ID != r.ID { + t.Errorf("The messge round does not match %s vs %s", + dummy.round.ID, r.ID) + } +} + +func TestEvents_triggerAdminEvents_noChannel(t *testing.T) { + me := &MockEvent{} + + e := initEvents(me) + + dummy := &dummyMessageTypeHandler{} + + mt := MessageType(1) + //skip handler registration + + //craft the input for the event + chID := &id.ID{} + chID[0] = 1 + + u, _, cm := builtTestUMI(t, mt) + + r := rounds.Round{ID: 420, Timestamps: make(map[states.Round]time.Time)} + r.Timestamps[states.QUEUED] = netTime.Now() + + msgID := cryptoChannel.MakeMessageID(u.userMessage.Message, chID) + + //call the trigger + _, err := e.triggerAdminEvent(chID, cm, netTime.Now(), msgID, receptionID.EphemeralIdentity{}, r, + Delivered) + if err != nil { + t.Fatalf(err.Error()) + } + + //check that the event was triggered + if dummy.triggered { + t.Errorf("The admin event was triggered when unregistered") + } +} + +func TestEvents_receiveTextMessage_Message(t *testing.T) { + me := &MockEvent{} + + e := initEvents(me) + + //craft the input for the event + chID := &id.ID{} + chID[0] = 1 + + textPayload := &CMIXChannelText{ + Version: 0, + Text: "They Don't Think It Be Like It Is, But It Do", + ReplyMessageID: nil, + } + + textMarshaled, err := proto.Marshal(textPayload) + if err != nil { + t.Fatalf("failed to marshael the message proto: %+v", err) + } + + msgID := cryptoChannel.MakeMessageID(textMarshaled, chID) + + rng := rand.New(rand.NewSource(64)) + + pi, err := cryptoChannel.GenerateIdentity(rng) + if err != nil { + t.Fatalf(err.Error()) + } + + senderNickname := "Alice" + ts := netTime.Now() + + lease := 69 * time.Minute + + r := rounds.Round{ID: 420, Timestamps: make(map[states.Round]time.Time)} + r.Timestamps[states.QUEUED] = netTime.Now() + + //call the handler + e.receiveTextMessage(chID, msgID, 0, senderNickname, + textMarshaled, pi.Identity, ts, lease, r, Delivered) + + //check the results on the model + if !me.eventReceive.channelID.Cmp(chID) { + t.Errorf("Channel ID did not propogate correctly, %s vs %s", + me.eventReceive.channelID, chID) + } + + if !me.eventReceive.messageID.Equals(msgID) { + t.Errorf("Message ID did not propogate correctly, %s vs %s", + me.eventReceive.messageID, msgID) + } + + if !me.eventReceive.reactionTo.Equals(cryptoChannel.MessageID{}) { + t.Errorf("Reaction ID is not blank, %s", + me.eventReceive.reactionTo) + } + + if me.eventReceive.nickname != senderNickname { + t.Errorf("SenderID propogate correctly, %s vs %s", + me.eventReceive.nickname, senderNickname) + } + + if me.eventReceive.timestamp != ts { + t.Errorf("Message timestamp did not propogate correctly, %s vs %s", + me.eventReceive.timestamp, ts) + } + + if me.eventReceive.lease != lease { + t.Errorf("Message lease did not propogate correctly, %s vs %s", + me.eventReceive.lease, lease) + } + + if me.eventReceive.round.ID != r.ID { + t.Errorf("Message round did not propogate correctly, %d vs %d", + me.eventReceive.round.ID, r.ID) + } +} + +func TestEvents_receiveTextMessage_Reply(t *testing.T) { + me := &MockEvent{} + + e := initEvents(me) + + //craft the input for the event + chID := &id.ID{} + chID[0] = 1 + + replyMsgId := cryptoChannel.MakeMessageID([]byte("blarg"), chID) + + textPayload := &CMIXChannelText{ + Version: 0, + Text: "They Don't Think It Be Like It Is, But It Do", + ReplyMessageID: replyMsgId[:], + } + + textMarshaled, err := proto.Marshal(textPayload) + if err != nil { + t.Fatalf("failed to marshael the message proto: %+v", err) + } + + msgID := cryptoChannel.MakeMessageID(textMarshaled, chID) + + senderUsername := "Alice" + ts := netTime.Now() + + lease := 69 * time.Minute + + r := rounds.Round{ID: 420, Timestamps: make(map[states.Round]time.Time)} + r.Timestamps[states.QUEUED] = netTime.Now() + + rng := rand.New(rand.NewSource(64)) + + pi, err := cryptoChannel.GenerateIdentity(rng) + if err != nil { + t.Fatalf(err.Error()) + } + + //call the handler + e.receiveTextMessage(chID, msgID, Text, senderUsername, + textMarshaled, pi.Identity, ts, lease, r, Delivered) + + //check the results on the model + if !me.eventReceive.channelID.Cmp(chID) { + t.Errorf("Channel ID did not propogate correctly, %s vs %s", + me.eventReceive.channelID, chID) + } + + if !me.eventReceive.messageID.Equals(msgID) { + t.Errorf("Message ID did not propogate correctly, %s vs %s", + me.eventReceive.messageID, msgID) + } + + if !me.eventReceive.reactionTo.Equals(replyMsgId) { + t.Errorf("Reaction ID is not equal to what was passed in, "+ + "%s vs %s", me.eventReceive.reactionTo, replyMsgId) + } + + if me.eventReceive.nickname != senderUsername { + t.Errorf("SenderID propogate correctly, %s vs %s", + me.eventReceive.nickname, senderUsername) + } + + if me.eventReceive.timestamp != ts { + t.Errorf("Message timestamp did not propogate correctly, "+ + "%s vs %s", me.eventReceive.timestamp, ts) + } + + if me.eventReceive.lease != lease { + t.Errorf("Message lease did not propogate correctly, %s vs %s", + me.eventReceive.lease, lease) + } + + if me.eventReceive.round.ID != r.ID { + t.Errorf("Message round did not propogate correctly, %d vs %d", + me.eventReceive.round.ID, r.ID) + } +} + +func TestEvents_receiveTextMessage_Reply_BadReply(t *testing.T) { + me := &MockEvent{} + + e := initEvents(me) + + //craft the input for the event + chID := &id.ID{} + chID[0] = 1 + + replyMsgId := []byte("blarg") + + textPayload := &CMIXChannelText{ + Version: 0, + Text: "They Don't Think It Be Like It Is, But It Do", + ReplyMessageID: replyMsgId[:], + } + + textMarshaled, err := proto.Marshal(textPayload) + if err != nil { + t.Fatalf("failed to marshael the message proto: %+v", err) + } + + msgID := cryptoChannel.MakeMessageID(textMarshaled, chID) + + senderUsername := "Alice" + ts := netTime.Now() + + lease := 69 * time.Minute + + r := rounds.Round{ID: 420, Timestamps: make(map[states.Round]time.Time)} + r.Timestamps[states.QUEUED] = netTime.Now() + + rng := rand.New(rand.NewSource(64)) + + pi, err := cryptoChannel.GenerateIdentity(rng) + if err != nil { + t.Fatalf(err.Error()) + } + + //call the handler + e.receiveTextMessage(chID, msgID, 0, senderUsername, + textMarshaled, pi.Identity, ts, lease, r, Delivered) + + //check the results on the model + if !me.eventReceive.channelID.Cmp(chID) { + t.Errorf("Channel ID did not propogate correctly, %s vs %s", + me.eventReceive.channelID, chID) + } + + if !me.eventReceive.messageID.Equals(msgID) { + t.Errorf("Message ID did not propogate correctly, %s vs %s", + me.eventReceive.messageID, msgID) + } + + if !me.eventReceive.reactionTo.Equals(cryptoChannel.MessageID{}) { + t.Errorf("Reaction ID is not blank, %s", + me.eventReceive.reactionTo) + } + + if me.eventReceive.nickname != senderUsername { + t.Errorf("SenderID propogate correctly, %s vs %s", + me.eventReceive.nickname, senderUsername) + } + + if me.eventReceive.timestamp != ts { + t.Errorf("Message timestamp did not propogate correctly, "+ + "%s vs %s", me.eventReceive.timestamp, ts) + } + + if me.eventReceive.lease != lease { + t.Errorf("Message lease did not propogate correctly, %s vs %s", + me.eventReceive.lease, lease) + } + + if me.eventReceive.round.ID != r.ID { + t.Errorf("Message round did not propogate correctly, %d vs %d", + me.eventReceive.round.ID, r.ID) + } +} + +func TestEvents_receiveReaction(t *testing.T) { + me := &MockEvent{} + + e := initEvents(me) + + //craft the input for the event + chID := &id.ID{} + chID[0] = 1 + + replyMsgId := cryptoChannel.MakeMessageID([]byte("blarg"), chID) + + textPayload := &CMIXChannelReaction{ + Version: 0, + Reaction: "🍆", + ReactionMessageID: replyMsgId[:], + } + + textMarshaled, err := proto.Marshal(textPayload) + if err != nil { + t.Fatalf("failed to marshael the message proto: %+v", err) + } + + msgID := cryptoChannel.MakeMessageID(textMarshaled, chID) + + senderUsername := "Alice" + ts := netTime.Now() + + lease := 69 * time.Minute + + r := rounds.Round{ID: 420, Timestamps: make(map[states.Round]time.Time)} + r.Timestamps[states.QUEUED] = netTime.Now() + + rng := rand.New(rand.NewSource(64)) + + pi, err := cryptoChannel.GenerateIdentity(rng) + if err != nil { + t.Fatalf(err.Error()) + } + + //call the handler + e.receiveReaction(chID, msgID, 0, senderUsername, + textMarshaled, pi.Identity, ts, lease, r, Delivered) + + //check the results on the model + if !me.eventReceive.channelID.Cmp(chID) { + t.Errorf("Channel ID did not propogate correctly, %s vs %s", + me.eventReceive.channelID, chID) + } + + if !me.eventReceive.messageID.Equals(msgID) { + t.Errorf("Message ID did not propogate correctly, %s vs %s", + me.eventReceive.messageID, msgID) + } + + if !me.eventReceive.reactionTo.Equals(replyMsgId) { + t.Errorf("Reaction ID is not equal to what was passed in, "+ + "%s vs %s", me.eventReceive.reactionTo, replyMsgId) + } + + if me.eventReceive.nickname != senderUsername { + t.Errorf("SenderID propogate correctly, %s vs %s", + me.eventReceive.nickname, senderUsername) + } + + if me.eventReceive.timestamp != ts { + t.Errorf("Message timestamp did not propogate correctly, "+ + "%s vs %s", me.eventReceive.timestamp, ts) + } + + if me.eventReceive.lease != lease { + t.Errorf("Message lease did not propogate correctly, %s vs %s", + me.eventReceive.lease, lease) + } + + if me.eventReceive.round.ID != r.ID { + t.Errorf("Message round did not propogate correctly, %d vs %d", + me.eventReceive.round.ID, r.ID) + } +} + +func TestEvents_receiveReaction_InvalidReactionMessageID(t *testing.T) { + me := &MockEvent{} + + e := initEvents(me) + + //craft the input for the event + chID := &id.ID{} + chID[0] = 1 + + replyMsgId := []byte("blarg") + + textPayload := &CMIXChannelReaction{ + Version: 0, + Reaction: "🍆", + ReactionMessageID: replyMsgId[:], + } + + textMarshaled, err := proto.Marshal(textPayload) + if err != nil { + t.Fatalf("failed to marshael the message proto: %+v", err) + } + + msgID := cryptoChannel.MakeMessageID(textMarshaled, chID) + + senderUsername := "Alice" + ts := netTime.Now() + + lease := 69 * time.Minute + + r := rounds.Round{ID: 420, Timestamps: make(map[states.Round]time.Time)} + r.Timestamps[states.QUEUED] = netTime.Now() + + rng := rand.New(rand.NewSource(64)) + + pi, err := cryptoChannel.GenerateIdentity(rng) + if err != nil { + t.Fatalf(err.Error()) + } + + //call the handler + e.receiveReaction(chID, msgID, 0, senderUsername, + textMarshaled, pi.Identity, ts, lease, r, Delivered) + + //check the results on the model + if me.eventReceive.channelID != nil { + t.Errorf("Channel ID did propogated correctly when the reaction " + + "is bad") + } + + if me.eventReceive.messageID.Equals(msgID) { + t.Errorf("Message ID propogated correctly when the reaction is " + + "bad") + } + + if !me.eventReceive.reactionTo.Equals(cryptoChannel.MessageID{}) { + t.Errorf("Reaction ID propogated correctly when the reaction " + + "is bad") + } + + if me.eventReceive.nickname != "" { + t.Errorf("SenderID propogated correctly when the reaction " + + "is bad") + } + + if me.eventReceive.lease != 0 { + t.Errorf("Message lease propogated correctly when the " + + "reaction is bad") + } +} + +func TestEvents_receiveReaction_InvalidReactionContent(t *testing.T) { + me := &MockEvent{} + + e := initEvents(me) + + //craft the input for the event + chID := &id.ID{} + chID[0] = 1 + + replyMsgId := cryptoChannel.MakeMessageID([]byte("blarg"), chID) + + textPayload := &CMIXChannelReaction{ + Version: 0, + Reaction: "I'm not a reaction", + ReactionMessageID: replyMsgId[:], + } + + textMarshaled, err := proto.Marshal(textPayload) + if err != nil { + t.Fatalf("failed to marshael the message proto: %+v", err) + } + + msgID := cryptoChannel.MakeMessageID(textMarshaled, chID) + + senderUsername := "Alice" + ts := netTime.Now() + + lease := 69 * time.Minute + + r := rounds.Round{ID: 420, Timestamps: make(map[states.Round]time.Time)} + r.Timestamps[states.QUEUED] = netTime.Now() + + rng := rand.New(rand.NewSource(64)) + + pi, err := cryptoChannel.GenerateIdentity(rng) + if err != nil { + t.Fatalf(err.Error()) + } + //call the handler + e.receiveReaction(chID, msgID, 0, senderUsername, + textMarshaled, pi.Identity, ts, lease, r, Delivered) + + //check the results on the model + if me.eventReceive.channelID != nil { + t.Errorf("Channel ID did propogated correctly when the reaction " + + "is bad") + } + + if me.eventReceive.messageID.Equals(msgID) { + t.Errorf("Message ID propogated correctly when the reaction is " + + "bad") + } + + if !me.eventReceive.reactionTo.Equals(cryptoChannel.MessageID{}) { + t.Errorf("Reaction ID propogated correctly when the reaction " + + "is bad") + } + + if me.eventReceive.nickname != "" { + t.Errorf("SenderID propogated correctly when the reaction " + + "is bad") + } + + if me.eventReceive.lease != 0 { + t.Errorf("Message lease propogated correctly when the " + + "reaction is bad") + } +} + +func getFuncName(i interface{}) string { + return runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name() +} diff --git a/channels/identityStore.go b/channels/identityStore.go new file mode 100644 index 0000000000000000000000000000000000000000..2432a86c8ee10449502319ae443e32a88c74a908 --- /dev/null +++ b/channels/identityStore.go @@ -0,0 +1,31 @@ +package channels + +import ( + "gitlab.com/elixxir/client/storage/versioned" + cryptoChannel "gitlab.com/elixxir/crypto/channel" + "gitlab.com/xx_network/primitives/netTime" +) + +const ( + identityStoreStorageKey = "identityStoreStorageKey" + identityStoreStorageVersion = 0 +) + +func storeIdentity(kv *versioned.KV, ident cryptoChannel.PrivateIdentity) error { + data := ident.Marshal() + obj := &versioned.Object{ + Version: identityStoreStorageVersion, + Timestamp: netTime.Now(), + Data: data, + } + + return kv.Set(identityStoreStorageKey, obj) +} + +func loadIdentity(kv *versioned.KV) (cryptoChannel.PrivateIdentity, error) { + obj, err := kv.Get(identityStoreStorageKey, identityStoreStorageVersion) + if err != nil { + return cryptoChannel.PrivateIdentity{}, err + } + return cryptoChannel.UnmarshalPrivateIdentity(obj.Data) +} diff --git a/channels/identityStore_test.go b/channels/identityStore_test.go new file mode 100644 index 0000000000000000000000000000000000000000..ec2d72f9b90d77accb42d757682fa83f333689f2 --- /dev/null +++ b/channels/identityStore_test.go @@ -0,0 +1,46 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file // +//////////////////////////////////////////////////////////////////////////////// + +package channels + +import ( + "bytes" + "encoding/base64" + "gitlab.com/elixxir/client/storage/versioned" + cryptoChannel "gitlab.com/elixxir/crypto/channel" + "gitlab.com/elixxir/ekv" + "gitlab.com/xx_network/crypto/csprng" + "testing" +) + +func TestStoreLoadIdentity(t *testing.T) { + rng := &csprng.SystemRNG{} + privIdentity, err := cryptoChannel.GenerateIdentity(rng) + if err != nil { + t.Fatalf("GenerateIdentity error: %+v", err) + } + + kv := versioned.NewKV(ekv.MakeMemstore()) + err = storeIdentity(kv, privIdentity) + if err != nil { + t.Fatalf("storeIdentity error: %+v", err) + } + + loadedIdentity, err := loadIdentity(kv) + if err != nil { + t.Fatalf("loadIdentity error: %+v", err) + } + + if !bytes.Equal(loadedIdentity.Marshal(), privIdentity.Marshal()) { + t.Fatalf("Failed to load private identity."+ + "\nExpected: %s"+ + "\nReceived: %s", + base64.StdEncoding.EncodeToString(privIdentity.Marshal()), + base64.StdEncoding.EncodeToString(loadedIdentity.Marshal())) + } + +} \ No newline at end of file diff --git a/channels/interface.go b/channels/interface.go new file mode 100644 index 0000000000000000000000000000000000000000..1d1874693d0aa80f4a5a1810b790436d2da58240 --- /dev/null +++ b/channels/interface.go @@ -0,0 +1,131 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file // +//////////////////////////////////////////////////////////////////////////////// + +package channels + +import ( + "gitlab.com/elixxir/client/cmix" + "gitlab.com/elixxir/client/cmix/rounds" + cryptoBroadcast "gitlab.com/elixxir/crypto/broadcast" + cryptoChannel "gitlab.com/elixxir/crypto/channel" + "gitlab.com/elixxir/crypto/rsa" + "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/id/ephemeral" + "math" + "time" +) + +// ValidForever is used as a validUntil lease when sending to denote the +// message or operation never expires. Note: A message relay must be +// present to enforce this otherwise things expire after 3 weeks due to +// network retention. +var ValidForever = time.Duration(math.MaxInt64) + +type Manager interface { + + // GetIdentity returns the public identity associated with this channel manager + GetIdentity() cryptoChannel.Identity + + // GetStorageTag returns the tag at which this manager is store for loading + // it is derived from the public key + GetStorageTag() string + + // JoinChannel joins the given channel. It will fail if the channel has + // already been joined. + JoinChannel(channel *cryptoBroadcast.Channel) error + + // LeaveChannel leaves the given channel. It will return an error if the + // channel was not previously joined. + LeaveChannel(channelID *id.ID) error + + // SendGeneric is used to send a raw message over a channel. In general, it + // should be wrapped in a function which defines the wire protocol + // If the final message, before being sent over the wire, is too long, this will + // return an error. Due to the underlying encoding using compression, it isn't + // possible to define the largest payload that can be sent, but + // it will always be possible to send a payload of 802 bytes at minimum + // Them meaning of validUntil depends on the use case. + SendGeneric(channelID *id.ID, messageType MessageType, + msg []byte, validUntil time.Duration, params cmix.CMIXParams) ( + cryptoChannel.MessageID, rounds.Round, ephemeral.Id, error) + + // SendAdminGeneric is used to send a raw message over a channel encrypted + // with admin keys, identifying it as sent by the admin. In general, it + // should be wrapped in a function which defines the wire protocol + // If the final message, before being sent over the wire, is too long, this will + // return an error. The message must be at most 510 bytes long. + SendAdminGeneric(privKey rsa.PrivateKey, channelID *id.ID, + messageType MessageType, msg []byte, validUntil time.Duration, + params cmix.CMIXParams) (cryptoChannel.MessageID, rounds.Round, + ephemeral.Id, error) + + // SendMessage is used to send a formatted message over a channel. + // Due to the underlying encoding using compression, it isn't + // possible to define the largest payload that can be sent, but + // it will always be possible to send a payload of 798 bytes at minimum + // The message will auto delete validUntil after the round it is sent in, + // lasting forever if ValidForever is used + SendMessage(channelID *id.ID, msg string, validUntil time.Duration, + params cmix.CMIXParams) ( + cryptoChannel.MessageID, rounds.Round, ephemeral.Id, error) + + // SendReply is used to send a formatted message over a channel. + // Due to the underlying encoding using compression, it isn't + // possible to define the largest payload that can be sent, but + // it will always be possible to send a payload of 766 bytes at minimum. + // If the message ID the reply is sent to doesnt exist, the other side will + // post the message as a normal message and not a reply. + // The message will auto delete validUntil after the round it is sent in, + // lasting forever if ValidForever is used + SendReply(channelID *id.ID, msg string, replyTo cryptoChannel.MessageID, + validUntil time.Duration, params cmix.CMIXParams) ( + cryptoChannel.MessageID, rounds.Round, ephemeral.Id, error) + + // SendReaction is used to send a reaction to a message over a channel. The + // reaction must be a single emoji with no other characters, and will be + // rejected otherwise. + // + // Clients will drop the reaction if they do not recognize the reactTo + // message. + SendReaction(channelID *id.ID, reaction string, + reactTo cryptoChannel.MessageID, params cmix.CMIXParams) ( + cryptoChannel.MessageID, rounds.Round, ephemeral.Id, error) + + // RegisterReceiveHandler is used to register handlers for non default + // message types so that they can be processed by modules. It is important + // that such modules sync up with the event model implementation. + // + // There can only be one handler per message type, and this will return an + // error on a multiple registration. + RegisterReceiveHandler(messageType MessageType, + listener MessageTypeReceiveMessage) error + + // GetChannels returns the IDs of all channels that have been joined. Use + // getChannelsUnsafe if you already have taken the mux. + GetChannels() []*id.ID + + // GetChannel returns the underlying cryptographic structure for a given + // channel. + GetChannel(chID *id.ID) (*cryptoBroadcast.Channel, error) + + // ReplayChannel replays all messages from the channel within the network's + // memory (~3 weeks) over the event model. It does this by wiping the + // underlying state tracking for message pickup for the channel, causing all + // messages to be re-retrieved from the network + ReplayChannel(chID *id.ID) error + + // SetNickname sets the nickname for a channel after checking that the + // nickname is valid using IsNicknameValid. + SetNickname(newNick string, ch *id.ID) error + + // DeleteNickname removes the nickname for a given channel, using the + // codename for that channel instead. + DeleteNickname(ch *id.ID) error + + // GetNickname returns the nickname for the given channel if it exists. + GetNickname(ch *id.ID) (nickname string, exists bool) +} diff --git a/channels/joinedChannel.go b/channels/joinedChannel.go new file mode 100644 index 0000000000000000000000000000000000000000..1b6aa53e7f9b2539b983c418eab52368d7c129c0 --- /dev/null +++ b/channels/joinedChannel.go @@ -0,0 +1,271 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file // +//////////////////////////////////////////////////////////////////////////////// + +package channels + +import ( + "encoding/json" + jww "github.com/spf13/jwalterweatherman" + "gitlab.com/elixxir/client/broadcast" + "gitlab.com/elixxir/client/storage/versioned" + cryptoBroadcast "gitlab.com/elixxir/crypto/broadcast" + "gitlab.com/elixxir/crypto/fastRNG" + "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/netTime" +) + +const ( + joinedChannelsVersion = 0 + joinedChannelsKey = "JoinedChannelsKey" + joinedChannelVersion = 0 + joinedChannelKey = "JoinedChannelKey-" +) + +// store stores the list of joined channels to disk while taking the read lock. +func (m *manager) store() error { + m.mux.RLock() + defer m.mux.RUnlock() + return m.storeUnsafe() +} + +// storeUnsafe stores the list of joined channels to disk without taking the +// read lock. It must be used by another function that has already taken the +// read lock. +func (m *manager) storeUnsafe() error { + channelsList := m.getChannelsUnsafe() + + data, err := json.Marshal(&channelsList) + if err != nil { + return err + } + + obj := &versioned.Object{ + Version: joinedChannelsVersion, + Timestamp: netTime.Now(), + Data: data, + } + + return m.kv.Set(joinedChannelsKey, obj) +} + +// loadChannels loads all currently joined channels from disk and registers them +// for message reception. +func (m *manager) loadChannels() { + obj, err := m.kv.Get(joinedChannelsKey, joinedChannelsVersion) + if !m.kv.Exists(err) { + m.channels = make(map[id.ID]*joinedChannel) + return + } else if err != nil { + jww.FATAL.Panicf("Failed to load channels: %+v", err) + } + + chList := make([]*id.ID, 0, len(m.channels)) + if err = json.Unmarshal(obj.Data, &chList); err != nil { + jww.FATAL.Panicf("Failed to load channels: %+v", err) + } + + chMap := make(map[id.ID]*joinedChannel) + + for i := range chList { + jc, err := loadJoinedChannel( + chList[i], m.kv, m.net, m.rng, m.events, m.broadcastMaker, + m.st.MessageReceive) + if err != nil { + jww.FATAL.Panicf("Failed to load channel %s: %+v", chList[i], err) + } + chMap[*chList[i]] = jc + } + + m.channels = chMap +} + +// addChannel adds a channel. +func (m *manager) addChannel(channel *cryptoBroadcast.Channel) error { + m.mux.Lock() + defer m.mux.Unlock() + if _, exists := m.channels[*channel.ReceptionID]; exists { + return ChannelAlreadyExistsErr + } + + b, err := m.broadcastMaker(channel, m.net, m.rng) + if err != nil { + return err + } + + jc := &joinedChannel{b} + if err = jc.Store(m.kv); err != nil { + go b.Stop() + return err + } + + m.channels[*jc.broadcast.Get().ReceptionID] = jc + + if err = m.storeUnsafe(); err != nil { + go b.Stop() + return err + } + + // Connect to listeners + err = b.RegisterListener((&userListener{ + chID: channel.ReceptionID, + trigger: m.events.triggerEvent, + checkSent: m.st.MessageReceive, + }).Listen, broadcast.Symmetric) + if err != nil { + return err + } + + err = b.RegisterListener((&adminListener{ + chID: channel.ReceptionID, + trigger: m.events.triggerAdminEvent, + checkSent: m.st.MessageReceive, + }).Listen, broadcast.RSAToPublic) + if err != nil { + return err + } + + return nil +} + +// removeChannel deletes the channel with the given ID from the channel list and +// stops it from broadcasting. Returns ChannelDoesNotExistsErr error if the +// channel does not exist. +func (m *manager) removeChannel(channelID *id.ID) error { + m.mux.Lock() + defer m.mux.Unlock() + + ch, exists := m.channels[*channelID] + if !exists { + return ChannelDoesNotExistsErr + } + + ch.broadcast.Stop() + + delete(m.channels, *channelID) + + err := m.storeUnsafe() + if err != nil { + return err + } + + return ch.delete(m.kv) +} + +// getChannel returns the given channel. Returns ChannelDoesNotExistsErr error +// if the channel does not exist. +func (m *manager) getChannel(channelID *id.ID) (*joinedChannel, error) { + m.mux.RLock() + defer m.mux.RUnlock() + + jc, exists := m.channels[*channelID] + if !exists { + return nil, ChannelDoesNotExistsErr + } + + return jc, nil +} + +// getChannelsUnsafe returns the IDs of all channels that have been joined. This +// function is unsafe because it does not take the mux; only use this function +// when under a lock. +func (m *manager) getChannelsUnsafe() []*id.ID { + list := make([]*id.ID, 0, len(m.channels)) + for chID := range m.channels { + list = append(list, chID.DeepCopy()) + } + return list +} + +// joinedChannel holds channel info. It will expand to include admin data, so it +// will be treated as a struct for now. +type joinedChannel struct { + broadcast broadcast.Channel +} + +// joinedChannelDisk is the representation of joinedChannel for storage. +type joinedChannelDisk struct { + Broadcast *cryptoBroadcast.Channel +} + +// Store writes the given channel to a unique storage location within the EKV. +func (jc *joinedChannel) Store(kv *versioned.KV) error { + jcd := joinedChannelDisk{jc.broadcast.Get()} + data, err := json.Marshal(&jcd) + if err != nil { + return err + } + + obj := &versioned.Object{ + Version: joinedChannelVersion, + Timestamp: netTime.Now(), + Data: data, + } + + return kv.Set(makeJoinedChannelKey(jc.broadcast.Get().ReceptionID), obj) +} + +// loadJoinedChannel loads a given channel from ekv storage. +func loadJoinedChannel(chId *id.ID, kv *versioned.KV, net broadcast.Client, + rngGen *fastRNG.StreamGenerator, e *events, + broadcastMaker broadcast.NewBroadcastChannelFunc, mr messageReceiveFunc) (*joinedChannel, error) { + obj, err := kv.Get(makeJoinedChannelKey(chId), joinedChannelVersion) + if err != nil { + return nil, err + } + + jcd := &joinedChannelDisk{} + + err = json.Unmarshal(obj.Data, jcd) + if err != nil { + return nil, err + } + + b, err := initBroadcast(jcd.Broadcast, e, net, broadcastMaker, rngGen, mr) + + jc := &joinedChannel{broadcast: b} + return jc, nil +} + +// delete removes the channel from the kv. +func (jc *joinedChannel) delete(kv *versioned.KV) error { + return kv.Delete(makeJoinedChannelKey(jc.broadcast.Get().ReceptionID), + joinedChannelVersion) +} + +func makeJoinedChannelKey(chId *id.ID) string { + return joinedChannelKey + chId.HexEncode() +} + +func initBroadcast(c *cryptoBroadcast.Channel, + e *events, net broadcast.Client, + broadcastMaker broadcast.NewBroadcastChannelFunc, + rngGen *fastRNG.StreamGenerator, mr messageReceiveFunc) (broadcast.Channel, error) { + b, err := broadcastMaker(c, net, rngGen) + if err != nil { + return nil, err + } + + err = b.RegisterListener((&userListener{ + chID: c.ReceptionID, + trigger: e.triggerEvent, + checkSent: mr, + }).Listen, broadcast.Symmetric) + if err != nil { + return nil, err + } + + err = b.RegisterListener((&adminListener{ + chID: c.ReceptionID, + trigger: e.triggerAdminEvent, + checkSent: mr, + }).Listen, broadcast.RSAToPublic) + if err != nil { + return nil, err + } + + return b, nil +} diff --git a/channels/joinedChannel_test.go b/channels/joinedChannel_test.go new file mode 100644 index 0000000000000000000000000000000000000000..e3bee24de606711cc0a0cffcd24e6a6c9b42001d --- /dev/null +++ b/channels/joinedChannel_test.go @@ -0,0 +1,643 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2020 xx network SEZC // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file // +//////////////////////////////////////////////////////////////////////////////// + +package channels + +import ( + "bytes" + "encoding/binary" + "gitlab.com/elixxir/client/broadcast" + clientCmix "gitlab.com/elixxir/client/cmix" + "gitlab.com/elixxir/client/cmix/message" + "gitlab.com/elixxir/client/cmix/rounds" + "gitlab.com/elixxir/client/storage/versioned" + cryptoBroadcast "gitlab.com/elixxir/crypto/broadcast" + cryptoChannel "gitlab.com/elixxir/crypto/channel" + "gitlab.com/elixxir/crypto/fastRNG" + "gitlab.com/elixxir/crypto/rsa" + "gitlab.com/elixxir/ekv" + "gitlab.com/xx_network/crypto/csprng" + "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/id/ephemeral" + "math/rand" + "reflect" + "sort" + "strconv" + "testing" + "time" +) + +// Tests that manager.store stores the channel list in the ekv. +func Test_manager_store(t *testing.T) { + rng := rand.New(rand.NewSource(64)) + + pi, err := cryptoChannel.GenerateIdentity(rng) + if err != nil { + t.Fatalf(err.Error()) + } + + mFace, err := NewManager(pi, versioned.NewKV(ekv.MakeMemstore()), + new(mockBroadcastClient), + fastRNG.NewStreamGenerator(1, 1, csprng.NewSystemRNG), + mockEventModelBuilder) + if err != nil { + t.Errorf(err.Error()) + } + + m := mFace.(*manager) + + for i := 0; i < 10; i++ { + ch, _, err := newTestChannel("name_"+strconv.Itoa(i), + "description_"+strconv.Itoa(i), m.rng.GetStream()) + if err != nil { + t.Errorf("Failed to create new channel %d: %+v", i, err) + } + + b, err := broadcast.NewBroadcastChannel(ch, m.net, m.rng) + if err != nil { + t.Errorf("Failed to make new broadcast channel: %+v", err) + } + + m.channels[*ch.ReceptionID] = &joinedChannel{b} + } + + err = m.store() + if err != nil { + t.Errorf("Error storing channels: %+v", err) + } + + _, err = m.kv.Get(joinedChannelsKey, joinedChannelsVersion) + if !ekv.Exists(err) { + t.Errorf("channel list not found in KV: %+v", err) + } +} + +// Tests that the manager.loadChannels loads all the expected channels from the +// ekv. +func Test_manager_loadChannels(t *testing.T) { + rng := rand.New(rand.NewSource(64)) + + pi, err := cryptoChannel.GenerateIdentity(rng) + if err != nil { + t.Fatalf(err.Error()) + } + + mFace, err := NewManager(pi, versioned.NewKV(ekv.MakeMemstore()), + new(mockBroadcastClient), + fastRNG.NewStreamGenerator(1, 1, csprng.NewSystemRNG), + mockEventModelBuilder) + if err != nil { + t.Errorf(err.Error()) + } + + m := mFace.(*manager) + + expected := make([]*joinedChannel, 10) + + for i := range expected { + ch, _, err := newTestChannel("name_"+strconv.Itoa(i), + "description_"+strconv.Itoa(i), m.rng.GetStream()) + if err != nil { + t.Errorf("Failed to create new channel %d: %+v", i, err) + } + + b, err := broadcast.NewBroadcastChannel(ch, m.net, m.rng) + if err != nil { + t.Errorf("Failed to make new broadcast channel: %+v", err) + } + + jc := &joinedChannel{b} + if err = jc.Store(m.kv); err != nil { + t.Errorf("Failed to store joinedChannel %d: %+v", i, err) + } + + chID := *ch.ReceptionID + m.channels[chID] = jc + expected[i] = jc + } + + err = m.store() + if err != nil { + t.Errorf("Error storing channels: %+v", err) + } + + newManager := &manager{ + channels: make(map[id.ID]*joinedChannel), + kv: m.kv, + net: m.net, + rng: m.rng, + broadcastMaker: m.broadcastMaker, + } + + newManager.loadChannels() + + for chID, loadedCh := range newManager.channels { + ch, exists := m.channels[chID] + if !exists { + t.Errorf("Channel %s does not exist.", &chID) + } + + if !reflect.DeepEqual(ch.broadcast, loadedCh.broadcast) { + t.Errorf("Channel %s does not match loaded channel."+ + "\nexpected: %+v\nreceived: %+v", &chID, ch.broadcast, loadedCh.broadcast) + } + } +} + +// Tests that manager.addChannel adds the channel to the map and stores it in +// the kv. +func Test_manager_addChannel(t *testing.T) { + rng := rand.New(rand.NewSource(64)) + + pi, err := cryptoChannel.GenerateIdentity(rng) + if err != nil { + t.Fatalf(err.Error()) + } + + mFace, err := NewManager(pi, versioned.NewKV(ekv.MakeMemstore()), + new(mockBroadcastClient), + fastRNG.NewStreamGenerator(1, 1, csprng.NewSystemRNG), + mockEventModelBuilder) + if err != nil { + t.Errorf(err.Error()) + } + + m := mFace.(*manager) + + ch, _, err := newTestChannel("name", "description", m.rng.GetStream()) + if err != nil { + t.Errorf("Failed to create new channel: %+v", err) + } + + err = m.addChannel(ch) + if err != nil { + t.Errorf("Failed to add new channel: %+v", err) + } + + if _, exists := m.channels[*ch.ReceptionID]; !exists { + t.Errorf("Channel %s not added to channel map.", ch.Name) + } + + _, err = m.kv.Get(makeJoinedChannelKey(ch.ReceptionID), joinedChannelVersion) + if err != nil { + t.Errorf("Failed to get joinedChannel from kv: %+v", err) + } + + _, err = m.kv.Get(joinedChannelsKey, joinedChannelsVersion) + if err != nil { + t.Errorf("Failed to get channels from kv: %+v", err) + } +} + +// Error path: tests that manager.addChannel returns ChannelAlreadyExistsErr +// when the channel was already added. +func Test_manager_addChannel_ChannelAlreadyExistsErr(t *testing.T) { + rng := rand.New(rand.NewSource(64)) + + pi, err := cryptoChannel.GenerateIdentity(rng) + if err != nil { + t.Fatalf(err.Error()) + } + + mFace, err := NewManager(pi, versioned.NewKV(ekv.MakeMemstore()), + new(mockBroadcastClient), + fastRNG.NewStreamGenerator(1, 1, csprng.NewSystemRNG), + mockEventModelBuilder) + if err != nil { + t.Errorf(err.Error()) + } + + m := mFace.(*manager) + + ch, _, err := newTestChannel("name", "description", m.rng.GetStream()) + if err != nil { + t.Errorf("Failed to create new channel: %+v", err) + } + + err = m.addChannel(ch) + if err != nil { + t.Errorf("Failed to add new channel: %+v", err) + } + + err = m.addChannel(ch) + if err == nil || err != ChannelAlreadyExistsErr { + t.Errorf("Received incorrect error when adding a channel that already "+ + "exists.\nexpected: %s\nreceived: %+v", ChannelAlreadyExistsErr, err) + } +} + +// Tests the manager.removeChannel deletes the channel from the map. +func Test_manager_removeChannel(t *testing.T) { + rng := rand.New(rand.NewSource(64)) + + pi, err := cryptoChannel.GenerateIdentity(rng) + if err != nil { + t.Fatalf(err.Error()) + } + + mFace, err := NewManager(pi, versioned.NewKV(ekv.MakeMemstore()), + new(mockBroadcastClient), + fastRNG.NewStreamGenerator(1, 1, csprng.NewSystemRNG), + mockEventModelBuilder) + if err != nil { + t.Errorf(err.Error()) + } + + m := mFace.(*manager) + + ch, _, err := newTestChannel("name", "description", m.rng.GetStream()) + if err != nil { + t.Errorf("Failed to create new channel: %+v", err) + } + + err = m.addChannel(ch) + if err != nil { + t.Errorf("Failed to add new channel: %+v", err) + } + + err = m.removeChannel(ch.ReceptionID) + if err != nil { + t.Errorf("Error removing channel: %+v", err) + } + + if _, exists := m.channels[*ch.ReceptionID]; exists { + t.Errorf("Channel %s was not remove from the channel map.", ch.Name) + } + + _, err = m.kv.Get(makeJoinedChannelKey(ch.ReceptionID), joinedChannelVersion) + if ekv.Exists(err) { + t.Errorf("joinedChannel not removed from kv: %+v", err) + } +} + +// Error path: tests that manager.removeChannel returns ChannelDoesNotExistsErr +// when the channel was never added. +func Test_manager_removeChannel_ChannelDoesNotExistsErr(t *testing.T) { + rng := rand.New(rand.NewSource(64)) + + pi, err := cryptoChannel.GenerateIdentity(rng) + if err != nil { + t.Fatalf(err.Error()) + } + + mFace, err := NewManager(pi, versioned.NewKV(ekv.MakeMemstore()), + new(mockBroadcastClient), + fastRNG.NewStreamGenerator(1, 1, csprng.NewSystemRNG), + mockEventModelBuilder) + if err != nil { + t.Errorf(err.Error()) + } + + m := mFace.(*manager) + + ch, _, err := newTestChannel("name", "description", m.rng.GetStream()) + if err != nil { + t.Errorf("Failed to create new channel: %+v", err) + } + + err = m.removeChannel(ch.ReceptionID) + if err == nil || err != ChannelDoesNotExistsErr { + t.Errorf("Received incorrect error when removing a channel that does "+ + "not exists.\nexpected: %s\nreceived: %+v", + ChannelDoesNotExistsErr, err) + } +} + +// Tests the manager.getChannel returns the expected channel. +func Test_manager_getChannel(t *testing.T) { + rng := rand.New(rand.NewSource(64)) + + pi, err := cryptoChannel.GenerateIdentity(rng) + if err != nil { + t.Fatalf(err.Error()) + } + + mFace, err := NewManager(pi, versioned.NewKV(ekv.MakeMemstore()), + new(mockBroadcastClient), + fastRNG.NewStreamGenerator(1, 1, csprng.NewSystemRNG), + mockEventModelBuilder) + if err != nil { + t.Errorf(err.Error()) + } + + m := mFace.(*manager) + + ch, _, err := newTestChannel("name", "description", m.rng.GetStream()) + if err != nil { + t.Errorf("Failed to create new channel: %+v", err) + } + + err = m.addChannel(ch) + if err != nil { + t.Errorf("Failed to add new channel: %+v", err) + } + + jc, err := m.getChannel(ch.ReceptionID) + if err != nil { + t.Errorf("Error getting channel: %+v", err) + } + + if !reflect.DeepEqual(ch, jc.broadcast.Get()) { + t.Errorf("Received unexpected channel.\nexpected: %+v\nreceived: %+v", + ch, jc.broadcast.Get()) + } +} + +// Error path: tests that manager.getChannel returns ChannelDoesNotExistsErr +// when the channel was never added. +func Test_manager_getChannel_ChannelDoesNotExistsErr(t *testing.T) { + rng := rand.New(rand.NewSource(64)) + + pi, err := cryptoChannel.GenerateIdentity(rng) + if err != nil { + t.Fatalf(err.Error()) + } + + mFace, err := NewManager(pi, versioned.NewKV(ekv.MakeMemstore()), + new(mockBroadcastClient), + fastRNG.NewStreamGenerator(1, 1, csprng.NewSystemRNG), + mockEventModelBuilder) + if err != nil { + t.Errorf(err.Error()) + } + + m := mFace.(*manager) + + ch, _, err := newTestChannel("name", "description", m.rng.GetStream()) + if err != nil { + t.Errorf("Failed to create new channel: %+v", err) + } + + _, err = m.getChannel(ch.ReceptionID) + if err == nil || err != ChannelDoesNotExistsErr { + t.Errorf("Received incorrect error when getting a channel that does "+ + "not exists.\nexpected: %s\nreceived: %+v", + ChannelDoesNotExistsErr, err) + } +} + +// Tests that manager.getChannels returns all the channels that were added to +// the map. +func Test_manager_getChannels(t *testing.T) { + rng := rand.New(rand.NewSource(64)) + + pi, err := cryptoChannel.GenerateIdentity(rng) + if err != nil { + t.Fatalf(err.Error()) + } + + mFace, err := NewManager(pi, versioned.NewKV(ekv.MakeMemstore()), + new(mockBroadcastClient), + fastRNG.NewStreamGenerator(1, 1, csprng.NewSystemRNG), + mockEventModelBuilder) + if err != nil { + t.Errorf(err.Error()) + } + + m := mFace.(*manager) + + expected := make([]*id.ID, 10) + + for i := range expected { + ch, _, err := newTestChannel("name_"+strconv.Itoa(i), + "description_"+strconv.Itoa(i), m.rng.GetStream()) + if err != nil { + t.Errorf("Failed to create new channel %d: %+v", i, err) + } + expected[i] = ch.ReceptionID + + err = m.addChannel(ch) + if err != nil { + t.Errorf("Failed to add new channel %d: %+v", i, err) + } + } + + channelIDs := m.getChannelsUnsafe() + + sort.SliceStable(expected, func(i, j int) bool { + return bytes.Compare(expected[i][:], expected[j][:]) == -1 + }) + sort.SliceStable(channelIDs, func(i, j int) bool { + return bytes.Compare(channelIDs[i][:], channelIDs[j][:]) == -1 + }) + + if !reflect.DeepEqual(expected, channelIDs) { + t.Errorf("ID list does not match expected.\nexpected: %v\nreceived: %v", + expected, channelIDs) + } +} + +// Tests that joinedChannel.Store saves the joinedChannel to the expected place +// in the ekv. +func Test_joinedChannel_Store(t *testing.T) { + kv := versioned.NewKV(ekv.MakeMemstore()) + rng := fastRNG.NewStreamGenerator(1, 1, csprng.NewSystemRNG) + ch, _, err := newTestChannel("name", "description", rng.GetStream()) + if err != nil { + t.Errorf("Failed to create new channel: %+v", err) + } + + b, err := broadcast.NewBroadcastChannel(ch, new(mockBroadcastClient), rng) + if err != nil { + t.Errorf("Failed to create new broadcast channel: %+v", err) + } + + jc := &joinedChannel{b} + + err = jc.Store(kv) + if err != nil { + t.Errorf("Error storing joinedChannel: %+v", err) + } + + _, err = kv.Get(makeJoinedChannelKey(ch.ReceptionID), joinedChannelVersion) + if !ekv.Exists(err) { + t.Errorf("joinedChannel not found in KV: %+v", err) + } +} + +// Tests that loadJoinedChannel returns a joinedChannel from storage that +// matches the original. +func Test_loadJoinedChannel(t *testing.T) { + rng := rand.New(rand.NewSource(64)) + + pi, err := cryptoChannel.GenerateIdentity(rng) + if err != nil { + t.Fatalf(err.Error()) + } + + mFace, err := NewManager(pi, versioned.NewKV(ekv.MakeMemstore()), + new(mockBroadcastClient), + fastRNG.NewStreamGenerator(1, 1, csprng.NewSystemRNG), + mockEventModelBuilder) + if err != nil { + t.Errorf(err.Error()) + } + + m := mFace.(*manager) + + ch, _, err := newTestChannel("name", "description", m.rng.GetStream()) + if err != nil { + t.Errorf("Failed to create new channel: %+v", err) + } + + err = m.addChannel(ch) + if err != nil { + t.Errorf("Failed to add channel: %+v", err) + } + + loadedJc, err := loadJoinedChannel(ch.ReceptionID, m.kv, m.net, m.rng, + m.events, m.broadcastMaker, func(messageID cryptoChannel.MessageID, r rounds.Round) bool { + return false + }) + if err != nil { + t.Errorf("Failed to load joinedChannel: %+v", err) + } + + if !reflect.DeepEqual(ch, loadedJc.broadcast.Get()) { + t.Errorf("Loaded joinedChannel does not match original."+ + "\nexpected: %+v\nreceived: %+v", ch, loadedJc.broadcast.Get()) + } +} + +// Tests that joinedChannel.delete deletes the stored joinedChannel from the +// ekv. +func Test_joinedChannel_delete(t *testing.T) { + kv := versioned.NewKV(ekv.MakeMemstore()) + rng := fastRNG.NewStreamGenerator(1, 1, csprng.NewSystemRNG) + ch, _, err := newTestChannel("name", "description", rng.GetStream()) + if err != nil { + t.Errorf("Failed to create new channel: %+v", err) + } + + b, err := broadcast.NewBroadcastChannel(ch, new(mockBroadcastClient), rng) + if err != nil { + t.Errorf("Failed to create new broadcast channel: %+v", err) + } + + jc := &joinedChannel{b} + + err = jc.Store(kv) + if err != nil { + t.Errorf("Error storing joinedChannel: %+v", err) + } + + err = jc.delete(kv) + if err != nil { + t.Errorf("Error deleting joinedChannel: %+v", err) + } + + _, err = kv.Get(makeJoinedChannelKey(ch.ReceptionID), joinedChannelVersion) + if ekv.Exists(err) { + t.Errorf("joinedChannel found in KV: %+v", err) + } +} + +// Consistency test of makeJoinedChannelKey. +func Test_makeJoinedChannelKey_Consistency(t *testing.T) { + values := map[*id.ID]string{ + id.NewIdFromUInt(0, id.User, t): "JoinedChannelKey-0x0000000000000000000000000000000000000000000000000000000000000000", + id.NewIdFromUInt(1, id.User, t): "JoinedChannelKey-0x0000000000000001000000000000000000000000000000000000000000000000", + id.NewIdFromUInt(2, id.User, t): "JoinedChannelKey-0x0000000000000002000000000000000000000000000000000000000000000000", + id.NewIdFromUInt(3, id.User, t): "JoinedChannelKey-0x0000000000000003000000000000000000000000000000000000000000000000", + id.NewIdFromUInt(4, id.User, t): "JoinedChannelKey-0x0000000000000004000000000000000000000000000000000000000000000000", + id.NewIdFromUInt(5, id.User, t): "JoinedChannelKey-0x0000000000000005000000000000000000000000000000000000000000000000", + id.NewIdFromUInt(6, id.User, t): "JoinedChannelKey-0x0000000000000006000000000000000000000000000000000000000000000000", + id.NewIdFromUInt(7, id.User, t): "JoinedChannelKey-0x0000000000000007000000000000000000000000000000000000000000000000", + id.NewIdFromUInt(8, id.User, t): "JoinedChannelKey-0x0000000000000008000000000000000000000000000000000000000000000000", + id.NewIdFromUInt(9, id.User, t): "JoinedChannelKey-0x0000000000000009000000000000000000000000000000000000000000000000", + } + + for chID, expected := range values { + key := makeJoinedChannelKey(chID) + + if expected != key { + t.Errorf("Unexpected key for ID %d.\nexpected: %s\nreceived: %s", + binary.BigEndian.Uint64(chID[:8]), expected, key) + } + } + +} + +// newTestChannel creates a new cryptoBroadcast.Channel in the same way that +// cryptoBroadcast.NewChannel does but with a smaller RSA key and salt to make +// tests run quicker. +func newTestChannel(name, description string, rng csprng.Source) ( + *cryptoBroadcast.Channel, rsa.PrivateKey, error) { + c, pk, err := cryptoBroadcast.NewChannelVariableKeyUnsafe(name, description, 1000, 512, rng) + return c, pk, err +} + +//////////////////////////////////////////////////////////////////////////////// +// Mock Broadcast Client // +//////////////////////////////////////////////////////////////////////////////// + +// mockBroadcastClient adheres to the broadcast.Client interface. +type mockBroadcastClient struct{} + +func (m *mockBroadcastClient) GetMaxMessageLength() int { return 123 } + +func (m *mockBroadcastClient) SendWithAssembler(*id.ID, + clientCmix.MessageAssembler, clientCmix.CMIXParams) ( + rounds.Round, ephemeral.Id, error) { + return rounds.Round{ID: id.Round(567)}, ephemeral.Id{}, nil +} + +func (m *mockBroadcastClient) IsHealthy() bool { return true } +func (m *mockBroadcastClient) AddIdentity(*id.ID, time.Time, bool) {} +func (m *mockBroadcastClient) AddService(*id.ID, message.Service, message.Processor) {} +func (m *mockBroadcastClient) DeleteClientService(*id.ID) {} +func (m *mockBroadcastClient) RemoveIdentity(*id.ID) {} +func (m *mockBroadcastClient) GetRoundResults(timeout time.Duration, + roundCallback clientCmix.RoundEventCallback, roundList ...id.Round) { +} +func (m *mockBroadcastClient) AddHealthCallback(f func(bool)) uint64 { return 0 } +func (m *mockBroadcastClient) RemoveHealthCallback(uint64) {} + +//////////////////////////////////////////////////////////////////////////////// +// Mock EventModel // +//////////////////////////////////////////////////////////////////////////////// + +func mockEventModelBuilder(string) (EventModel, error) { + return &mockEventModel{}, nil +} + +// mockEventModel adheres to the EventModel interface. +type mockEventModel struct { + joinedCh *cryptoBroadcast.Channel + leftCh *id.ID +} + +func (m *mockEventModel) UpdateSentStatus(uuid uint64, messageID cryptoChannel.MessageID, + timestamp time.Time, round rounds.Round, status SentStatus) { + //TODO implement me + panic("implement me") +} + +func (m *mockEventModel) JoinChannel(c *cryptoBroadcast.Channel) { + m.joinedCh = c +} +func (m *mockEventModel) LeaveChannel(c *id.ID) { + m.leftCh = c +} +func (m *mockEventModel) ReceiveMessage(channelID *id.ID, messageID cryptoChannel.MessageID, + nickname, text string, identity cryptoChannel.Identity, + timestamp time.Time, lease time.Duration, round rounds.Round, + mType MessageType, status SentStatus) uint64 { + return 0 +} +func (m *mockEventModel) ReceiveReply(channelID *id.ID, messageID cryptoChannel.MessageID, + reactionTo cryptoChannel.MessageID, nickname, text string, + identity cryptoChannel.Identity, timestamp time.Time, + lease time.Duration, round rounds.Round, mType MessageType, status SentStatus) uint64 { + return 0 +} +func (m *mockEventModel) ReceiveReaction(channelID *id.ID, messageID cryptoChannel.MessageID, + reactionTo cryptoChannel.MessageID, nickname, reaction string, + identity cryptoChannel.Identity, timestamp time.Time, + lease time.Duration, round rounds.Round, mType MessageType, status SentStatus) uint64 { + return 0 +} diff --git a/channels/manager.go b/channels/manager.go new file mode 100644 index 0000000000000000000000000000000000000000..f3de1b863b589c23f50f04e2f78f9f14c88924d0 --- /dev/null +++ b/channels/manager.go @@ -0,0 +1,243 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file // +//////////////////////////////////////////////////////////////////////////////// + +// Package channels provides a channels implementation on top of broadcast +// which is capable of handing the user facing features of channels, including +// replies, reactions, and eventually admin commands. +package channels + +import ( + "crypto/ed25519" + "encoding/base64" + "fmt" + "github.com/pkg/errors" + jww "github.com/spf13/jwalterweatherman" + "gitlab.com/elixxir/client/broadcast" + "gitlab.com/elixxir/client/cmix" + "gitlab.com/elixxir/client/cmix/message" + "gitlab.com/elixxir/client/cmix/rounds" + "gitlab.com/elixxir/client/storage/versioned" + cryptoBroadcast "gitlab.com/elixxir/crypto/broadcast" + cryptoChannel "gitlab.com/elixxir/crypto/channel" + "gitlab.com/elixxir/crypto/fastRNG" + "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/id/ephemeral" + "sync" + "time" +) + +const storageTagFormat = "channelManagerStorageTag-%s" + +type manager struct { + // Sender Identity + me cryptoChannel.PrivateIdentity + + // List of all channels + channels map[id.ID]*joinedChannel + mux sync.RWMutex + + // External references + kv *versioned.KV + net Client + rng *fastRNG.StreamGenerator + + // Events model + *events + + // Nicknames + *nicknameManager + + // Send tracker + st *sendTracker + + // Makes the function that is used to create broadcasts be a pointer so that + // it can be replaced in tests + broadcastMaker broadcast.NewBroadcastChannelFunc +} + +// Client contains the methods from cmix.Client that are required by the +// [Manager]. +type Client interface { + GetMaxMessageLength() int + SendWithAssembler(recipient *id.ID, assembler cmix.MessageAssembler, + cmixParams cmix.CMIXParams) (rounds.Round, ephemeral.Id, error) + IsHealthy() bool + AddIdentity(id *id.ID, validUntil time.Time, persistent bool) + AddService(clientID *id.ID, newService message.Service, + response message.Processor) + DeleteClientService(clientID *id.ID) + RemoveIdentity(id *id.ID) + GetRoundResults(timeout time.Duration, roundCallback cmix.RoundEventCallback, + roundList ...id.Round) + AddHealthCallback(f func(bool)) uint64 + RemoveHealthCallback(uint64) +} + +// EventModelBuilder initialises the event model using the given path. +type EventModelBuilder func(path string) (EventModel, error) + +// NewManager creates a new channel Manager from a [channel.PrivateIdentity]. It +// prefixes the KV with a tag derived from the public key that can be retried +// for reloading using [Manager.GetStorageTag]. +func NewManager(identity cryptoChannel.PrivateIdentity, kv *versioned.KV, + net Client, rng *fastRNG.StreamGenerator, modelBuilder EventModelBuilder) ( + Manager, error) { + + // Prefix the kv with the username so multiple can be run + storageTag := getStorageTag(identity.PubKey) + kv = kv.Prefix(storageTag) + + if err := storeIdentity(kv, identity); err != nil { + return nil, err + } + + model, err := modelBuilder(storageTag) + if err != nil { + return nil, errors.Errorf("Failed to build event model: %+v", err) + } + + m := setupManager(identity, kv, net, rng, model) + + return m, nil +} + +// LoadManager restores a channel Manager from disk stored at the given storage +// tag. +func LoadManager(storageTag string, kv *versioned.KV, net Client, + rng *fastRNG.StreamGenerator, modelBuilder EventModelBuilder) (Manager, error) { + + // Prefix the kv with the username so multiple can be run + kv = kv.Prefix(storageTag) + + // Load the identity + identity, err := loadIdentity(kv) + if err != nil { + return nil, err + } + + model, err := modelBuilder(storageTag) + if err != nil { + return nil, errors.Errorf("Failed to build event model: %+v", err) + } + + m := setupManager(identity, kv, net, rng, model) + + return m, nil +} + +func setupManager(identity cryptoChannel.PrivateIdentity, kv *versioned.KV, + net Client, rng *fastRNG.StreamGenerator, model EventModel) *manager { + + m := manager{ + me: identity, + kv: kv, + net: net, + rng: rng, + broadcastMaker: broadcast.NewBroadcastChannel, + } + + m.events = initEvents(model) + + m.st = loadSendTracker(net, kv, m.events.triggerEvent, + m.events.triggerAdminEvent, model.UpdateSentStatus, rng) + + m.loadChannels() + + m.nicknameManager = loadOrNewNicknameManager(kv) + + return &m +} + +// JoinChannel joins the given channel. It will fail if the channel has already +// been joined. +func (m *manager) JoinChannel(channel *cryptoBroadcast.Channel) error { + err := m.addChannel(channel) + if err != nil { + return err + } + + go m.events.model.JoinChannel(channel) + + return nil +} + +// LeaveChannel leaves the given channel. It will return an error if the channel +// was not previously joined. +func (m *manager) LeaveChannel(channelID *id.ID) error { + err := m.removeChannel(channelID) + if err != nil { + return err + } + + go m.events.model.LeaveChannel(channelID) + + return nil +} + +// GetChannels returns the IDs of all channels that have been joined. Use +// getChannelsUnsafe if you already have taken the mux. +func (m *manager) GetChannels() []*id.ID { + m.mux.Lock() + defer m.mux.Unlock() + return m.getChannelsUnsafe() +} + +// GetChannel returns the underlying cryptographic structure for a given channel. +func (m *manager) GetChannel(chID *id.ID) (*cryptoBroadcast.Channel, error) { + jc, err := m.getChannel(chID) + if err != nil { + return nil, err + } + return jc.broadcast.Get(), nil +} + +// ReplayChannel replays all messages from the channel within the network's +// memory (~3 weeks) over the event model. It does this by wiping the +// underlying state tracking for message pickup for the channel, causing all +// messages to be re-retrieved from the network +func (m *manager) ReplayChannel(chID *id.ID) error { + jww.INFO.Printf("Replaying messages on channel %s", chID) + m.mux.RLock() + defer m.mux.RUnlock() + + jc, exists := m.channels[*chID] + if !exists { + return ChannelDoesNotExistsErr + } + + c := jc.broadcast.Get() + + // Stop the broadcast that will completely wipe it from the underlying cmix + // object + jc.broadcast.Stop() + + // Re-instantiate the broadcast, re-registering it from scratch + b, err := initBroadcast(c, m.events, m.net, m.broadcastMaker, m.rng, + m.st.MessageReceive) + if err != nil { + return err + } + jc.broadcast = b + + return nil + +} + +// GetStorageTag returns the tag at which this manager is store for loading +// it is derived from the public key +func (m *manager) GetStorageTag() string { + return getStorageTag(m.me.PubKey) +} + +// GetIdentity returns the public identity associated with this channel manager +func (m *manager) GetIdentity() cryptoChannel.Identity { + return m.me.Identity +} + +func getStorageTag(pub ed25519.PublicKey) string { + return fmt.Sprintf(storageTagFormat, base64.StdEncoding.EncodeToString(pub)) +} diff --git a/channels/manager_test.go b/channels/manager_test.go new file mode 100644 index 0000000000000000000000000000000000000000..6f07e2013d222e10d8c93bce7beeabbfd59ef8b1 --- /dev/null +++ b/channels/manager_test.go @@ -0,0 +1,222 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file // +//////////////////////////////////////////////////////////////////////////////// + +package channels + +import ( + "fmt" + "gitlab.com/elixxir/client/broadcast" + "gitlab.com/elixxir/client/storage/versioned" + cryptoChannel "gitlab.com/elixxir/crypto/channel" + "gitlab.com/elixxir/crypto/fastRNG" + "gitlab.com/elixxir/ekv" + "gitlab.com/xx_network/crypto/csprng" + "gitlab.com/xx_network/primitives/id" + "math/rand" + "os" + "sync" + "testing" + "time" + + jww "github.com/spf13/jwalterweatherman" +) + +func TestMain(m *testing.M) { + // Many tests trigger WARN prints;, set the out threshold so the WARN prints + // can be seen in the logs + jww.SetStdoutThreshold(jww.LevelWarn) + os.Exit(m.Run()) +} + +func TestManager_JoinChannel(t *testing.T) { + rng := rand.New(rand.NewSource(64)) + + pi, err := cryptoChannel.GenerateIdentity(rng) + if err != nil { + t.Fatalf(err.Error()) + } + + mFace, err := NewManager(pi, versioned.NewKV(ekv.MakeMemstore()), + new(mockBroadcastClient), + fastRNG.NewStreamGenerator(1, 1, csprng.NewSystemRNG), + mockEventModelBuilder) + if err != nil { + t.Errorf(err.Error()) + } + + m := mFace.(*manager) + mem := m.events.model.(*mockEventModel) + + ch, _, err := newTestChannel("name", "description", m.rng.GetStream()) + if err != nil { + t.Errorf("Failed to create new channel: %+v", err) + } + + err = m.JoinChannel(ch) + if err != nil { + t.Fatalf("Join Channel Errored: %s", err) + } + + if _, exists := m.channels[*ch.ReceptionID]; !exists { + t.Errorf("Channel %s not added to channel map.", ch.Name) + } + + //wait because the event model is called in another thread + time.Sleep(1 * time.Second) + + if mem.joinedCh == nil { + t.Errorf("the channel join call was not propogated to the event " + + "model") + } +} + +func TestManager_LeaveChannel(t *testing.T) { + + rng := rand.New(rand.NewSource(64)) + + pi, err := cryptoChannel.GenerateIdentity(rng) + if err != nil { + t.Fatalf(err.Error()) + } + + mFace, err := NewManager(pi, versioned.NewKV(ekv.MakeMemstore()), + new(mockBroadcastClient), + fastRNG.NewStreamGenerator(1, 1, csprng.NewSystemRNG), + mockEventModelBuilder) + if err != nil { + t.Errorf(err.Error()) + } + + m := mFace.(*manager) + mem := m.events.model.(*mockEventModel) + + ch, _, err := newTestChannel("name", "description", m.rng.GetStream()) + if err != nil { + t.Errorf("Failed to create new channel: %+v", err) + } + + err = m.JoinChannel(ch) + if err != nil { + t.Fatalf("Join Channel Errored: %s", err) + } + + err = m.LeaveChannel(ch.ReceptionID) + if err != nil { + t.Fatalf("Leave Channel Errored: %s", err) + } + + if _, exists := m.channels[*ch.ReceptionID]; exists { + t.Errorf("Channel %s still in map.", ch.Name) + } + + //wait because the event model is called in another thread + time.Sleep(1 * time.Second) + + if mem.leftCh == nil { + t.Errorf("the channel join call was not propogated to the event " + + "model") + } +} + +func TestManager_GetChannels(t *testing.T) { + m := &manager{ + channels: make(map[id.ID]*joinedChannel), + mux: sync.RWMutex{}, + } + + rng := fastRNG.NewStreamGenerator(1, 1, csprng.NewSystemRNG) + + numtests := 10 + + chList := make(map[id.ID]interface{}) + + for i := 0; i < 10; i++ { + name := fmt.Sprintf("testChannel %d", numtests) + s := rng.GetStream() + tc, _, err := newTestChannel(name, "blarg", s) + s.Close() + if err != nil { + t.Fatalf("failed to generate channel %s", name) + } + bc, err := broadcast.NewBroadcastChannel(tc, new(mockBroadcastClient), rng) + if err != nil { + t.Fatalf("failed to generate broadcast %s", name) + } + m.channels[*tc.ReceptionID] = &joinedChannel{broadcast: bc} + chList[*tc.ReceptionID] = nil + } + + receivedChList := m.GetChannels() + + for _, receivedCh := range receivedChList { + if _, exists := chList[*receivedCh]; !exists { + t.Errorf("Channel was not returned") + } + } +} + +func TestManager_GetChannel(t *testing.T) { + m := &manager{ + channels: make(map[id.ID]*joinedChannel), + mux: sync.RWMutex{}, + } + + rng := fastRNG.NewStreamGenerator(1, 1, csprng.NewSystemRNG) + + numtests := 10 + + chList := make([]*id.ID, 0, numtests) + + for i := 0; i < 10; i++ { + name := fmt.Sprintf("testChannel %d", numtests) + s := rng.GetStream() + tc, _, err := newTestChannel(name, "blarg", s) + s.Close() + if err != nil { + t.Fatalf("failed to generate channel %s", name) + } + bc, err := broadcast.NewBroadcastChannel(tc, new(mockBroadcastClient), rng) + if err != nil { + t.Fatalf("failed to generate broadcast %s", name) + } + m.channels[*tc.ReceptionID] = &joinedChannel{broadcast: bc} + chList = append(chList, tc.ReceptionID) + } + + for i, receivedCh := range chList { + ch, err := m.GetChannel(receivedCh) + if err != nil { + t.Errorf("Channel %d failed to be gotten", i) + } else if !ch.ReceptionID.Cmp(receivedCh) { + t.Errorf("Channel %d Get returned wrong channel", i) + } + } +} + +func TestManager_GetChannel_BadChannel(t *testing.T) { + m := &manager{ + channels: make(map[id.ID]*joinedChannel), + mux: sync.RWMutex{}, + } + + numtests := 10 + + chList := make([]*id.ID, 0, numtests) + + for i := 0; i < 10; i++ { + chId := &id.ID{} + chId[0] = byte(i) + chList = append(chList, chId) + } + + for i, receivedCh := range chList { + _, err := m.GetChannel(receivedCh) + if err == nil { + t.Errorf("Channel %d returned when it doesnt exist", i) + } + } +} diff --git a/channels/messageTypes.go b/channels/messageTypes.go new file mode 100644 index 0000000000000000000000000000000000000000..5ac6e2de3c914131655e484599171c5ac6114d90 --- /dev/null +++ b/channels/messageTypes.go @@ -0,0 +1,31 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file // +//////////////////////////////////////////////////////////////////////////////// + +package channels + +import "fmt" + +type MessageType uint32 + +const ( + Text = MessageType(1) + AdminText = MessageType(2) + Reaction = MessageType(3) +) + +func (mt MessageType) String() string { + switch mt { + case Text: + return "Text" + case AdminText: + return "AdminText" + case Reaction: + return "Reaction" + default: + return fmt.Sprintf("Unknown messageType %d", mt) + } +} diff --git a/channels/messageTypes_test.go b/channels/messageTypes_test.go new file mode 100644 index 0000000000000000000000000000000000000000..170ebf0542de153bb23c2f2135c66ff597d633f7 --- /dev/null +++ b/channels/messageTypes_test.go @@ -0,0 +1,25 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file // +//////////////////////////////////////////////////////////////////////////////// + +package channels + +import "testing" + +func TestMessageType_String(t *testing.T) { + expected := []string{"Text", "AdminText", "Reaction", "Unknown messageType 4", + "Unknown messageType 5", "Unknown messageType 6", "Unknown messageType 7", + "Unknown messageType 8", "Unknown messageType 9", + "Unknown messageType 10"} + + for i := 1; i <= 10; i++ { + mt := MessageType(i) + if mt.String() != expected[i-1] { + t.Errorf("Stringer failed on test %d, %s vs %s", i, + mt.String(), expected[i-1]) + } + } +} diff --git a/channels/messages.go b/channels/messages.go new file mode 100644 index 0000000000000000000000000000000000000000..0162c3c62f62c10c7c652d206e405e7a2383327b --- /dev/null +++ b/channels/messages.go @@ -0,0 +1,75 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file // +//////////////////////////////////////////////////////////////////////////////// + +package channels + +import ( + "github.com/golang/protobuf/proto" + "gitlab.com/elixxir/crypto/channel" + "gitlab.com/xx_network/primitives/id" +) + +// userMessageInternal is the internal structure of a UserMessage protobuf. +type userMessageInternal struct { + userMessage *UserMessage + channelMessage *ChannelMessage + messageID channel.MessageID +} + +func newUserMessageInternal(ursMsg *UserMessage, chid *id.ID) (*userMessageInternal, error) { + chanMessage := &ChannelMessage{} + err := proto.Unmarshal(ursMsg.Message, chanMessage) + if err != nil { + return nil, err + } + + channelMessage := chanMessage + return &userMessageInternal{ + userMessage: ursMsg, + channelMessage: channelMessage, + messageID: channel.MakeMessageID(ursMsg.Message, chid), + }, nil +} + +func unmarshalUserMessageInternal(usrMsg []byte, chid *id.ID) (*userMessageInternal, error) { + + um := &UserMessage{} + if err := proto.Unmarshal(usrMsg, um); err != nil { + return nil, err + } + + chanMessage := &ChannelMessage{} + err := proto.Unmarshal(um.Message, chanMessage) + if err != nil { + return nil, err + } + + channelMessage := chanMessage + + return &userMessageInternal{ + userMessage: um, + channelMessage: channelMessage, + messageID: channel.MakeMessageID(um.Message, chid), + }, nil +} + +// GetUserMessage retrieves the UserMessage within +// userMessageInternal. +func (umi *userMessageInternal) GetUserMessage() *UserMessage { + return umi.userMessage +} + +// GetChannelMessage retrieves the ChannelMessage within +// userMessageInternal. +func (umi *userMessageInternal) GetChannelMessage() *ChannelMessage { + return umi.channelMessage +} + +// GetMessageID retrieves the messageID for the message. +func (umi *userMessageInternal) GetMessageID() channel.MessageID { + return umi.messageID +} diff --git a/channels/messages_test.go b/channels/messages_test.go new file mode 100644 index 0000000000000000000000000000000000000000..b5109bd30a535156edc2e80556b9db51d55313e4 --- /dev/null +++ b/channels/messages_test.go @@ -0,0 +1,166 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file // +//////////////////////////////////////////////////////////////////////////////// + +package channels + +import ( + "github.com/golang/protobuf/proto" + "gitlab.com/elixxir/crypto/channel" + "gitlab.com/xx_network/primitives/id" + "reflect" + "testing" +) + +func TestUnmarshalUserMessageInternal(t *testing.T) { + internal, usrMsg, _ := builtTestUMI(t, 7) + + chID := &id.ID{} + + usrMsgMarshaled, err := proto.Marshal(usrMsg) + if err != nil { + t.Fatalf("Failed to marshal user message: %+v", err) + } + + umi, err := unmarshalUserMessageInternal(usrMsgMarshaled, chID) + if err != nil { + t.Fatalf("Failed to unmarshal user message: %+v", err) + } + + if !umi.GetMessageID().Equals(internal.messageID) { + t.Errorf("Message IDs were changed in the unmarshal "+ + "process, %s vs %s", internal.messageID, umi.GetMessageID()) + } +} + +func TestUnmarshalUserMessageInternal_BadUserMessage(t *testing.T) { + chID := &id.ID{} + _, err := unmarshalUserMessageInternal([]byte("Malformed"), chID) + if err == nil { + t.Fatalf("Error not returned on unmarshaling a bad user " + + "message") + } +} + +func TestUnmarshalUserMessageInternal_BadChannelMessage(t *testing.T) { + _, usrMsg, _ := builtTestUMI(t, 7) + + usrMsg.Message = []byte("Malformed") + + chID := &id.ID{} + + usrMsgMarshaled, err := proto.Marshal(usrMsg) + if err != nil { + t.Fatalf("Failed to marshal user message: %+v", err) + } + + _, err = unmarshalUserMessageInternal(usrMsgMarshaled, chID) + if err == nil { + t.Fatalf("Error not returned on unmarshaling a user message " + + "with a bad channel message") + } +} + +func TestNewUserMessageInternal_BadChannelMessage(t *testing.T) { + _, usrMsg, _ := builtTestUMI(t, 7) + + usrMsg.Message = []byte("Malformed") + + chID := &id.ID{} + + _, err := newUserMessageInternal(usrMsg, chID) + + if err == nil { + t.Fatalf("failed to produce error with malformed user message") + } +} + +func TestUserMessageInternal_GetChannelMessage(t *testing.T) { + internal, _, channelMsg := builtTestUMI(t, 7) + received := internal.GetChannelMessage() + + if !reflect.DeepEqual(received.Payload, channelMsg.Payload) || + received.Lease != channelMsg.Lease || + received.RoundID != channelMsg.RoundID || + received.PayloadType != channelMsg.PayloadType { + t.Fatalf("GetChannelMessage did not return expected data."+ + "\nExpected: %v"+ + "\nReceived: %v", channelMsg, received) + } +} + +func TestUserMessageInternal_GetUserMessage(t *testing.T) { + internal, usrMsg, _ := builtTestUMI(t, 7) + received := internal.GetUserMessage() + + if !reflect.DeepEqual(received.Message, usrMsg.Message) || + !reflect.DeepEqual(received.Signature, usrMsg.Signature) || + !reflect.DeepEqual(received.ECCPublicKey, usrMsg.ECCPublicKey) { + t.Fatalf("GetUserMessage did not return expected data."+ + "\nExpected: %v"+ + "\nReceived: %v", usrMsg, received) + } +} + +func TestUserMessageInternal_GetMessageID(t *testing.T) { + internal, usrMsg, _ := builtTestUMI(t, 7) + received := internal.GetMessageID() + + chID := &id.ID{} + + expected := channel.MakeMessageID(usrMsg.Message, chID) + + if !reflect.DeepEqual(expected, received) { + t.Fatalf("GetMessageID did not return expected data."+ + "\nExpected: %v"+ + "\nReceived: %v", expected, received) + } +} + +// Ensures the serialization hasn't changed, changing the message IDs. The +// protocol is tolerant of this because only the sender seralizes, but +// it would be good to know when this changes. If this test breaks, report it, +// but it should be safe to update the expected +func TestUserMessageInternal_GetMessageID_Consistency(t *testing.T) { + expected := "ChMsgID-LrGYLFCaPamZk44X+c/b08qtmJIorgNnoE68v1HYrf8=" + + internal, _, _ := builtTestUMI(t, 7) + + received := internal.GetMessageID() + + if expected != received.String() { + t.Fatalf("GetMessageID did not return expected data."+ + "\nExpected: %v"+ + "\nReceived: %v", expected, received) + } +} + +func builtTestUMI(t *testing.T, mt MessageType) (*userMessageInternal, *UserMessage, *ChannelMessage) { + channelMsg := &ChannelMessage{ + Lease: 69, + RoundID: 42, + PayloadType: uint32(mt), + Payload: []byte("ban_badUSer"), + Nickname: "paul", + } + + serialized, err := proto.Marshal(channelMsg) + if err != nil { + t.Fatalf("Marshal error: %v", err) + } + + usrMsg := &UserMessage{ + Message: serialized, + Signature: []byte("sig2"), + ECCPublicKey: []byte("key"), + } + + chID := &id.ID{} + + internal, _ := newUserMessageInternal(usrMsg, chID) + + return internal, usrMsg, channelMsg +} diff --git a/channels/mutateTimestamp.go b/channels/mutateTimestamp.go new file mode 100644 index 0000000000000000000000000000000000000000..47c2bf1f02da14eaf829f37cb5b77970aaebf394 --- /dev/null +++ b/channels/mutateTimestamp.go @@ -0,0 +1,58 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file // +//////////////////////////////////////////////////////////////////////////////// + +package channels + +import ( + "gitlab.com/elixxir/crypto/channel" + "gitlab.com/xx_network/crypto/large" + "time" +) + +const ( + // tenMsInNs is a prime close to one million to ensure patterns dont + // arise due to cofactors with the message ID when doing the modulo + tenMsInNs = 10000019 + halfTenMsInNs = tenMsInNs / 2 +) + +var tenMsInNsLargeInt = large.NewInt(tenMsInNs) + +// mutateTimestamp is used to modify the the timestamps on all messages in a +// deterministic manner. This is because message ordering is done by timestamp +// and the timestamps come from the rounds, which means multiple messages can +// have the same timestamp due to being in the same round. The meaning of +// conversations can change depending on order, so while no explicit order +// can be discovered because to do so can leak potential ordering info for the +// mix, choosing an arbitrary order and having all clients agree will at least +// ensure that misunderstandings due to disagreements in order cannot occur +// +// In order to do this, this function mutates the timestamp of the round within +// +/- 5ms seeded based upon the message ID. +// It should be noted that this is only a reasonable assumption when the number +// of messages in a channel isn't too much. For example, under these conditions +// the birthday paradox of getting a collision if there are 10 messages for the +// channel in the same round is ~4*10^-6, but the chance if there are 50 +// messages is 10^-4, and if the entire round is full of messages for the +// channel (1000 messages), .0487. +func mutateTimestamp(ts time.Time, msgID channel.MessageID) time.Time { + + // Treat the message ID as a number and mod it by the number of ns in an ms + // to get an offset factor. Use a prime close to 1000000 to make sure there + // are no patterns in the output and reduce the chance of collision. While + // the fields do not align, so there is some bias towards some parts of the + // output field, that bias is too small to matter because log2(10000019) ~23 + // while the input field is 256. + offsetLarge := large.NewIntFromBytes(msgID.Bytes()) + offsetLarge.Mod(offsetLarge, tenMsInNsLargeInt) + + // subtract half the field size so on average (across many runs) the message + // timestamps are not changed + offset := offsetLarge.Int64() - halfTenMsInNs + + return time.Unix(0, ts.UnixNano()+offset) +} diff --git a/channels/mutateTimestamp_test.go b/channels/mutateTimestamp_test.go new file mode 100644 index 0000000000000000000000000000000000000000..120fd44156c2c1616a876d60db27725caebd6eaf --- /dev/null +++ b/channels/mutateTimestamp_test.go @@ -0,0 +1,55 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file // +//////////////////////////////////////////////////////////////////////////////// + +package channels + +import ( + "gitlab.com/xx_network/primitives/netTime" + "math/rand" + "testing" + "time" + + "gitlab.com/elixxir/crypto/channel" +) + +// withinMutationWindow is a utility test function to check if a mutated +// timestamp is within the allowable window +func withinMutationWindow(raw, mutated time.Time) bool { + lowerBound := raw.Add(-time.Duration(halfTenMsInNs)) + upperBound := raw.Add(time.Duration(halfTenMsInNs)) + + return mutated.After(lowerBound) && mutated.Before(upperBound) +} + +func abs(n int64) int64 { + if n < 0 { + return -n + } + return n +} + +func TestMutateTimestampDeltaAverage(t *testing.T) { + samples := 10000 + t1 := netTime.Now() + sum := int64(0) + + rng := rand.New(rand.NewSource(netTime.Now().UnixNano())) + + for i := 0; i < samples; i++ { + var msgID channel.MessageID + rng.Read(msgID[:]) + t2 := mutateTimestamp(t1, msgID) + delta := t2.Sub(t1) + sum += abs(int64(delta)) + } + + avg := sum / int64(samples) + diff := abs(avg - 2502865) + if diff > 30000 { + t.Fatal() + } +} diff --git a/channels/nameService.go b/channels/nameService.go new file mode 100644 index 0000000000000000000000000000000000000000..d77fa9414a4f0fe1d8a32fae130936187f2fcf92 --- /dev/null +++ b/channels/nameService.go @@ -0,0 +1,38 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file // +//////////////////////////////////////////////////////////////////////////////// + +package channels + +import ( + "crypto/ed25519" + "time" +) + +// NameService is an interface which encapsulates +// the user identity channel tracking service. +// NameService is currently unused +type NameService interface { + + // GetUsername returns the username. + GetUsername() string + + // GetChannelValidationSignature returns the validation + // signature and the time it was signed. + GetChannelValidationSignature() ([]byte, time.Time) + + // GetChannelPubkey returns the user's public key. + GetChannelPubkey() ed25519.PublicKey + + // SignChannelMessage returns the signature of the + // given message. + SignChannelMessage(message []byte) (signature []byte, err error) + + // ValidateChannelMessage validates that a received channel message's + // username lease is signed by the NameService + ValidateChannelMessage(username string, lease time.Time, + pubKey ed25519.PublicKey, authorIDSignature []byte) bool +} diff --git a/channels/nickname.go b/channels/nickname.go new file mode 100644 index 0000000000000000000000000000000000000000..5116b597f754c09ce1b6bae06ec878c5192debfe --- /dev/null +++ b/channels/nickname.go @@ -0,0 +1,146 @@ +package channels + +import ( + "encoding/json" + "errors" + jww "github.com/spf13/jwalterweatherman" + "gitlab.com/elixxir/client/storage/versioned" + "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/netTime" + "sync" +) + +const ( + nicknameStoreStorageKey = "nicknameStoreStorageKey" + nicknameStoreStorageVersion = 0 +) + +type nicknameManager struct { + byChannel map[id.ID]string + + mux sync.RWMutex + + kv *versioned.KV +} + +// loadOrNewNicknameManager returns the stored nickname manager if there is +// one or returns a new one +func loadOrNewNicknameManager(kv *versioned.KV) *nicknameManager { + nm := &nicknameManager{ + byChannel: make(map[id.ID]string), + kv: kv, + } + err := nm.load() + if err != nil && nm.kv.Exists(err) { + jww.FATAL.Panicf("Failed to load nicknameManager: %+v", err) + } + + return nm + +} + +// GetNickname returns the nickname for the given channel if it exists +func (nm *nicknameManager) GetNickname(ch *id.ID) ( + nickname string, exists bool) { + nm.mux.RLock() + defer nm.mux.RUnlock() + + nickname, exists = nm.byChannel[*ch] + return +} + +// SetNickname sets the nickname for a channel after checking that the nickname +// is valid using IsNicknameValid +func (nm *nicknameManager) SetNickname(newNick string, ch *id.ID) error { + nm.mux.Lock() + defer nm.mux.Unlock() + + if err := IsNicknameValid(newNick); err != nil { + return err + } + + nm.byChannel[*ch] = newNick + return nm.save() +} + +// DeleteNickname removes the nickname for a given channel, using the codename +// for that channel instead +func (nm *nicknameManager) DeleteNickname(ch *id.ID) error { + nm.mux.Lock() + defer nm.mux.Unlock() + + delete(nm.byChannel, *ch) + + return nm.save() +} + +// channelIDToNickname is a serialization structure. This is used by the save +// and load functions to serialize the nicknameManager's byChannel map. +type channelIDToNickname struct { + ChannelId id.ID + Nickname string +} + +// save stores the nickname manager to disk. The caller of this must +// hold the mux. +func (nm *nicknameManager) save() error { + list := make([]channelIDToNickname, 0) + for chId, nickname := range nm.byChannel { + list = append(list, channelIDToNickname{ + ChannelId: chId, + Nickname: nickname, + }) + } + + data, err := json.Marshal(list) + if err != nil { + return err + } + obj := &versioned.Object{ + Version: nicknameStoreStorageVersion, + Timestamp: netTime.Now(), + Data: data, + } + + return nm.kv.Set(nicknameStoreStorageKey, obj) +} + +// load restores the nickname manager from disk. +func (nm *nicknameManager) load() error { + obj, err := nm.kv.Get(nicknameStoreStorageKey, nicknameStoreStorageVersion) + if err != nil { + return err + } + + list := make([]channelIDToNickname, 0) + err = json.Unmarshal(obj.Data, &list) + if err != nil { + return err + } + + for i := range list { + current := list[i] + nm.byChannel[current.ChannelId] = current.Nickname + } + + return nil +} + +// IsNicknameValid checks if a nickname is valid +// +// rules +// - a nickname must not be longer than 24 characters +// - a nickname must not be shorter than 1 character +// todo: add character filtering +func IsNicknameValid(nick string) error { + runeNick := []rune(nick) + if len(runeNick) > 24 { + return errors.New("nicknames must be 24 characters in length or less") + } + + if len(runeNick) < 1 { + return errors.New("nicknames must be at least 1 character in length") + } + + return nil +} diff --git a/channels/nickname_test.go b/channels/nickname_test.go new file mode 100644 index 0000000000000000000000000000000000000000..cf535245f82bb1e4b5c4caf5ac0b65f6355b4653 --- /dev/null +++ b/channels/nickname_test.go @@ -0,0 +1,108 @@ +package channels + +import ( + "gitlab.com/elixxir/client/storage/versioned" + "gitlab.com/elixxir/ekv" + "gitlab.com/xx_network/primitives/id" + "strconv" + "testing" +) + +// Unit test. Tests that once you set a nickname with SetNickname, you can +// retrieve the nickname using GetNickname. +func TestNicknameManager_SetGetNickname(t *testing.T) { + kv := versioned.NewKV(ekv.MakeMemstore()) + nm := loadOrNewNicknameManager(kv) + + for i := 0; i < numTests; i++ { + chId := id.NewIdFromUInt(uint64(i), id.User, t) + nickname := "nickname#" + strconv.Itoa(i) + err := nm.SetNickname(nickname, chId) + if err != nil { + t.Fatalf("SetNickname error when setting %s: %+v", nickname, err) + } + + received, _ := nm.GetNickname(chId) + if received != nickname { + t.Fatalf("GetNickname did not return expected values."+ + "\nExpected: %s"+ + "\nReceived: %s", nickname, received) + } + } +} + +// Unit test. Tests that once you set a nickname with SetNickname, you can +// retrieve the nickname using GetNickname after a reload. +func TestNicknameManager_SetGetNickname_Reload(t *testing.T) { + kv := versioned.NewKV(ekv.MakeMemstore()) + nm := loadOrNewNicknameManager(kv) + + for i := 0; i < numTests; i++ { + chId := id.NewIdFromUInt(uint64(i), id.User, t) + nickname := "nickname#" + strconv.Itoa(i) + err := nm.SetNickname(nickname, chId) + if err != nil { + t.Fatalf("SetNickname error when setting %s: %+v", nickname, err) + } + } + + nm2 := loadOrNewNicknameManager(kv) + + for i := 0; i < numTests; i++ { + chId := id.NewIdFromUInt(uint64(i), id.User, t) + nick, exists := nm2.GetNickname(chId) + if !exists { + t.Fatalf("Nickname %d not found ", i) + } + expected := "nickname#" + strconv.Itoa(i) + if nick != expected { + t.Fatalf("Nickname %d not found, expected: %s, received: %s ", i, expected, nick) + } + } +} + +// Error case: Tests that nicknameManager.GetNickname returns a false boolean +// if no nickname has been set with the channel ID. +func TestNicknameManager_GetNickname_Error(t *testing.T) { + kv := versioned.NewKV(ekv.MakeMemstore()) + nm := loadOrNewNicknameManager(kv) + + for i := 0; i < numTests; i++ { + chId := id.NewIdFromUInt(uint64(i), id.User, t) + _, exists := nm.GetNickname(chId) + if exists { + t.Fatalf("GetNickname expected error case: " + + "This should not retrieve nicknames for channel IDs " + + "that are not set.") + } + } +} + +// Unit test. Check that once you SetNickname and DeleteNickname, +// GetNickname returns a false boolean. +func TestNicknameManager_DeleteNickname(t *testing.T) { + kv := versioned.NewKV(ekv.MakeMemstore()) + nm := loadOrNewNicknameManager(kv) + + for i := 0; i < numTests; i++ { + chId := id.NewIdFromUInt(uint64(i), id.User, t) + nickname := "nickname#" + strconv.Itoa(i) + err := nm.SetNickname(nickname, chId) + if err != nil { + t.Fatalf("SetNickname error when setting %s: %+v", nickname, err) + } + + err = nm.DeleteNickname(chId) + if err != nil { + t.Fatalf("DeleteNickname error: %+v", err) + } + + _, exists := nm.GetNickname(chId) + if exists { + t.Fatalf("GetNickname expected error case: " + + "This should not retrieve nicknames for channel IDs " + + "that are not set.") + } + } + +} diff --git a/channels/readme.md b/channels/readme.md new file mode 100644 index 0000000000000000000000000000000000000000..9327e9635afd9c109054bf7b486d24c97a53c0bc --- /dev/null +++ b/channels/readme.md @@ -0,0 +1,21 @@ +Channels provides a channels implementation on top of broadcast which is capable of handing the user facing features of +channels, including replies, reactions, and eventually admin commands. + +on sending, data propagates as follows: +Send function (Example: SendMessage) - > SendGeneric -> +Broadcast.BroadcastWithAssembler -> cmix.SendWithAssembler + +on receiving messages propagate as follows: +cmix message pickup (by service)- > broadcast.Processor -> +userListener -> events.triggerEvent -> +messageTypeHandler (example: Text) -> +eventModel (example: ReceiveMessage) + +on sendingAdmin, data propagates as follows: +Send function - > SendAdminGeneric -> +Broadcast.BroadcastAsymmetricWithAssembler -> cmix.SendWithAssembler + +on receiving admin messages propagate as follows: +cmix message pickup (by service)- > broadcast.Processor -> adminListener -> +events.triggerAdminEvent -> messageTypeHandler (example: Text) -> +eventModel (example: ReceiveMessage) \ No newline at end of file diff --git a/channels/send.go b/channels/send.go new file mode 100644 index 0000000000000000000000000000000000000000..7b46152bb07b801fcd23fcd649829065d4e654db --- /dev/null +++ b/channels/send.go @@ -0,0 +1,287 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file // +//////////////////////////////////////////////////////////////////////////////// + +package channels + +import ( + "crypto/ed25519" + "github.com/pkg/errors" + jww "github.com/spf13/jwalterweatherman" + "gitlab.com/elixxir/client/cmix" + "gitlab.com/elixxir/client/cmix/rounds" + cryptoChannel "gitlab.com/elixxir/crypto/channel" + "gitlab.com/elixxir/crypto/rsa" + "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/id/ephemeral" + "google.golang.org/protobuf/proto" + "time" +) + +const ( + cmixChannelTextVersion = 0 + cmixChannelReactionVersion = 0 +) + +// The size of the nonce used in the message ID. +const messageNonceSize = 4 + +// SendGeneric is used to send a raw message over a channel. In general, it +// should be wrapped in a function which defines the wire protocol +// If the final message, before being sent over the wire, is too long, this will +// return an error. Due to the underlying encoding using compression, it isn't +// possible to define the largest payload that can be sent, but +// it will always be possible to send a payload of 802 bytes at minimum +func (m *manager) SendGeneric(channelID *id.ID, messageType MessageType, + msg []byte, validUntil time.Duration, params cmix.CMIXParams) ( + cryptoChannel.MessageID, rounds.Round, ephemeral.Id, error) { + + //find the channel + ch, err := m.getChannel(channelID) + if err != nil { + return cryptoChannel.MessageID{}, rounds.Round{}, ephemeral.Id{}, err + } + + nickname, _ := m.nicknameManager.GetNickname(channelID) + + var msgId cryptoChannel.MessageID + + chMsg := &ChannelMessage{ + Lease: validUntil.Nanoseconds(), + PayloadType: uint32(messageType), + Payload: msg, + Nickname: nickname, + Nonce: make([]byte, messageNonceSize), + } + + // Generate random nonce to be used for message ID generation. This makes it + // so two identical messages sent on the same round have different message IDs + rng := m.rng.GetStream() + n, err := rng.Read(chMsg.Nonce) + rng.Close() + if err != nil { + return cryptoChannel.MessageID{}, rounds.Round{}, ephemeral.Id{}, + errors.Errorf("Failed to generate nonce: %+v", err) + } else if n != messageNonceSize { + return cryptoChannel.MessageID{}, rounds.Round{}, ephemeral.Id{}, + errors.Errorf( + "Generated %d bytes for %-byte nonce", n, messageNonceSize) + } + + usrMsg := &UserMessage{ + ECCPublicKey: m.me.PubKey, + } + + //Note: we are not checking check if message is too long before trying to + //find a round + + //Build the function pointer that will build the message + assemble := func(rid id.Round) ([]byte, error) { + + //Build the message + chMsg.RoundID = uint64(rid) + + //Serialize the message + chMsgSerial, err := proto.Marshal(chMsg) + if err != nil { + return nil, err + } + + //make the messageID + msgId = cryptoChannel.MakeMessageID(chMsgSerial, channelID) + + //Sign the message + messageSig := ed25519.Sign(*m.me.Privkey, chMsgSerial) + + usrMsg.Message = chMsgSerial + usrMsg.Signature = messageSig + + //Serialize the user message + usrMsgSerial, err := proto.Marshal(usrMsg) + if err != nil { + return nil, err + } + + return usrMsgSerial, nil + } + + uuid, err := m.st.denotePendingSend(channelID, &userMessageInternal{ + userMessage: usrMsg, + channelMessage: chMsg, + messageID: msgId, + }) + + r, ephid, err := ch.broadcast.BroadcastWithAssembler(assemble, params) + if err != nil { + errDenote := m.st.failedSend(uuid) + if errDenote != nil { + jww.ERROR.Printf("Failed to update for a failed send to "+ + "%s: %+v", channelID, err) + } + return cryptoChannel.MessageID{}, rounds.Round{}, ephemeral.Id{}, err + } + err = m.st.send(uuid, msgId, r) + return msgId, r, ephid, err +} + +// SendAdminGeneric is used to send a raw message over a channel encrypted +// with admin keys, identifying it as sent by the admin. In general, it +// should be wrapped in a function which defines the wire protocol +// If the final message, before being sent over the wire, is too long, this will +// return an error. The message must be at most 510 bytes long. +func (m *manager) SendAdminGeneric(privKey rsa.PrivateKey, channelID *id.ID, + messageType MessageType, msg []byte, validUntil time.Duration, + params cmix.CMIXParams) (cryptoChannel.MessageID, rounds.Round, ephemeral.Id, + error) { + + //find the channel + ch, err := m.getChannel(channelID) + if err != nil { + return cryptoChannel.MessageID{}, rounds.Round{}, ephemeral.Id{}, err + } + + var msgId cryptoChannel.MessageID + chMsg := &ChannelMessage{ + Lease: validUntil.Nanoseconds(), + PayloadType: uint32(messageType), + Payload: msg, + Nickname: AdminUsername, + Nonce: make([]byte, messageNonceSize), + } + + // Generate random nonce to be used for message ID generation. This makes it + // so two identical messages sent on the same round have different message IDs + rng := m.rng.GetStream() + n, err := rng.Read(chMsg.Nonce) + rng.Close() + if err != nil { + return cryptoChannel.MessageID{}, rounds.Round{}, ephemeral.Id{}, + errors.Errorf("Failed to generate nonce: %+v", err) + } else if n != messageNonceSize { + return cryptoChannel.MessageID{}, rounds.Round{}, ephemeral.Id{}, + errors.Errorf( + "Generated %d bytes for %-byte nonce", n, messageNonceSize) + } + + // Note: we are not checking if message is too long before trying to + // find a round + + //Build the function pointer that will build the message + assemble := func(rid id.Round) ([]byte, error) { + + //Build the message + chMsg.RoundID = uint64(rid) + + //Serialize the message + chMsgSerial, err := proto.Marshal(chMsg) + if err != nil { + return nil, err + } + + msgId = cryptoChannel.MakeMessageID(chMsgSerial, channelID) + + //check if the message is too long + if len(chMsgSerial) > ch.broadcast.MaxRSAToPublicPayloadSize() { + return nil, MessageTooLongErr + } + + return chMsgSerial, nil + } + + uuid, err := m.st.denotePendingAdminSend(channelID, chMsg) + if err != nil { + return cryptoChannel.MessageID{}, rounds.Round{}, ephemeral.Id{}, err + } + + r, ephid, err := ch.broadcast.BroadcastRSAToPublicWithAssembler(privKey, + assemble, params) + if err != nil { + errDenote := m.st.failedSend(uuid) + if errDenote != nil { + jww.ERROR.Printf("Failed to update for a failed send to "+ + "%s: %+v", channelID, err) + } + return cryptoChannel.MessageID{}, rounds.Round{}, ephemeral.Id{}, err + } + + err = m.st.send(uuid, msgId, r) + if err != nil { + return cryptoChannel.MessageID{}, rounds.Round{}, ephemeral.Id{}, err + } + return msgId, r, ephid, err +} + +// SendMessage is used to send a formatted message over a channel. +// Due to the underlying encoding using compression, it isn't +// possible to define the largest payload that can be sent, but +// it will always be possible to send a payload of 798 bytes at minimum +func (m *manager) SendMessage(channelID *id.ID, msg string, + validUntil time.Duration, params cmix.CMIXParams) ( + cryptoChannel.MessageID, rounds.Round, ephemeral.Id, error) { + txt := &CMIXChannelText{ + Version: cmixChannelTextVersion, + Text: msg, + ReplyMessageID: nil, + } + + txtMarshaled, err := proto.Marshal(txt) + if err != nil { + return cryptoChannel.MessageID{}, rounds.Round{}, ephemeral.Id{}, err + } + + return m.SendGeneric(channelID, Text, txtMarshaled, validUntil, params) +} + +// SendReply is used to send a formatted message over a channel. +// Due to the underlying encoding using compression, it isn't +// possible to define the largest payload that can be sent, but +// it will always be possible to send a payload of 766 bytes at minimum. +// If the message ID the reply is sent to doesnt exist, the other side will +// post the message as a normal message and not a reply. +func (m *manager) SendReply(channelID *id.ID, msg string, + replyTo cryptoChannel.MessageID, validUntil time.Duration, + params cmix.CMIXParams) (cryptoChannel.MessageID, rounds.Round, + ephemeral.Id, error) { + txt := &CMIXChannelText{ + Version: cmixChannelTextVersion, + Text: msg, + ReplyMessageID: replyTo[:], + } + + txtMarshaled, err := proto.Marshal(txt) + if err != nil { + return cryptoChannel.MessageID{}, rounds.Round{}, ephemeral.Id{}, err + } + + return m.SendGeneric(channelID, Text, txtMarshaled, validUntil, params) +} + +// SendReaction is used to send a reaction to a message over a channel. +// The reaction must be a single emoji with no other characters, and will +// be rejected otherwise. +// Clients will drop the reaction if they do not recognize the reactTo message +func (m *manager) SendReaction(channelID *id.ID, reaction string, + reactTo cryptoChannel.MessageID, params cmix.CMIXParams) ( + cryptoChannel.MessageID, rounds.Round, ephemeral.Id, error) { + + if err := ValidateReaction(reaction); err != nil { + return cryptoChannel.MessageID{}, rounds.Round{}, ephemeral.Id{}, err + } + + react := &CMIXChannelReaction{ + Version: cmixChannelReactionVersion, + Reaction: reaction, + ReactionMessageID: reactTo[:], + } + + reactMarshaled, err := proto.Marshal(react) + if err != nil { + return cryptoChannel.MessageID{}, rounds.Round{}, ephemeral.Id{}, err + } + + return m.SendGeneric(channelID, Reaction, reactMarshaled, ValidForever, + params) +} diff --git a/channels/sendTracker.go b/channels/sendTracker.go new file mode 100644 index 0000000000000000000000000000000000000000..023785fa7f4063b6dc30e509419cd79f7978fab4 --- /dev/null +++ b/channels/sendTracker.go @@ -0,0 +1,497 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file // +//////////////////////////////////////////////////////////////////////////////// + +package channels + +import ( + "encoding/json" + "errors" + jww "github.com/spf13/jwalterweatherman" + "gitlab.com/elixxir/client/cmix" + "gitlab.com/elixxir/client/cmix/identity/receptionID" + "gitlab.com/elixxir/client/cmix/rounds" + "gitlab.com/elixxir/client/storage/versioned" + cryptoChannel "gitlab.com/elixxir/crypto/channel" + "gitlab.com/elixxir/crypto/fastRNG" + "gitlab.com/elixxir/primitives/states" + "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/netTime" + "sync" + "time" +) + +const ( + sendTrackerStorageKey = "sendTrackerStorageKey" + sendTrackerStorageVersion = 0 + + sendTrackerUnsentStorageKey = "sendTrackerUnsentStorageKey" + sendTrackerUnsentStorageVersion = 0 + + getRoundResultsTimeout = 60 * time.Second + // number of times it will attempt to get round status before the round + // is assumed to have failed. Tracking per round does not persist across + // runs + maxChecks = 3 + + oneSecond = 1000 * time.Millisecond +) + +type tracked struct { + MsgID cryptoChannel.MessageID + ChannelID *id.ID + RoundID id.Round + UUID uint64 +} + +// the sendTracker tracks outbound messages and denotes when they are delivered +// to the event model. It also captures incoming messages and in the event they +// were sent by this user diverts them as status updates on the previously sent +// messages +type sendTracker struct { + byRound map[id.Round][]*tracked + + byMessageID map[cryptoChannel.MessageID]*tracked + + unsent map[uint64]*tracked + + mux sync.RWMutex + + trigger triggerEventFunc + adminTrigger triggerAdminEventFunc + updateStatus updateStatusFunc + + net Client + + kv *versioned.KV + + rngSrc *fastRNG.StreamGenerator +} + +// messageReceiveFunc is a function type for sendTracker.MessageReceive so it +// can be mocked for testing where used +type messageReceiveFunc func(messageID cryptoChannel.MessageID, r rounds.Round) bool + +// loadSendTracker loads a sent tracker, restoring from disk. It will register a +// function with the cmix client, delayed on when the network goes healthy, +// which will attempt to discover the status of all rounds that are outstanding. +func loadSendTracker(net Client, kv *versioned.KV, trigger triggerEventFunc, + adminTrigger triggerAdminEventFunc, updateStatus updateStatusFunc, + rngSource *fastRNG.StreamGenerator) *sendTracker { + st := &sendTracker{ + byRound: make(map[id.Round][]*tracked), + byMessageID: make(map[cryptoChannel.MessageID]*tracked), + unsent: make(map[uint64]*tracked), + trigger: trigger, + adminTrigger: adminTrigger, + updateStatus: updateStatus, + net: net, + kv: kv, + rngSrc: rngSource, + } + + /*if err := st.load(); !kv.Exists(err){ + jww.FATAL.Panicf("failed to load sent tracker: %+v", err) + }*/ + st.load() + + //denote all unsent messages as failed and clear + for uuid, t := range st.unsent { + updateStatus(uuid, t.MsgID, + time.Time{}, rounds.Round{}, Failed) + } + st.unsent = make(map[uint64]*tracked) + + //register to check all outstanding rounds when the network becomes healthy + /*var callBackID uint64 + callBackID = net.AddHealthCallback(func(f bool) { + if !f { + return + } + net.RemoveHealthCallback(callBackID) + for rid := range st.byRound { + + rr := &roundResults{ + round: rid, + st: st, + } + st.net.GetRoundResults(getRoundResultsTimeout, rr.callback, rr.round) + } + })*/ + + return st +} + +// store writes the list of rounds that have been +func (st *sendTracker) store() error { + + if err := st.storeSent(); err != nil { + return err + } + + return st.storeUnsent() +} + +func (st *sendTracker) storeSent() error { + + //save sent messages + data, err := json.Marshal(&st.byRound) + if err != nil { + return err + } + return st.kv.Set(sendTrackerStorageKey, &versioned.Object{ + Version: sendTrackerStorageVersion, + Timestamp: netTime.Now(), + Data: data, + }) +} + +// store writes the list of rounds that have been +func (st *sendTracker) storeUnsent() error { + //save unsent messages + data, err := json.Marshal(&st.unsent) + if err != nil { + return err + } + + return st.kv.Set(sendTrackerUnsentStorageKey, &versioned.Object{ + Version: sendTrackerUnsentStorageVersion, + Timestamp: netTime.Now(), + Data: data, + }) +} + +// load will get the stored rounds to be checked from disk and builds +// internal datastructures +func (st *sendTracker) load() error { + obj, err := st.kv.Get(sendTrackerStorageKey, sendTrackerStorageVersion) + if err != nil { + return err + } + + err = json.Unmarshal(obj.Data, &st.byRound) + if err != nil { + return err + } + + for rid := range st.byRound { + roundList := st.byRound[rid] + for j := range roundList { + st.byMessageID[roundList[j].MsgID] = roundList[j] + } + } + + obj, err = st.kv.Get(sendTrackerUnsentStorageKey, sendTrackerUnsentStorageVersion) + if err != nil { + return err + } + + err = json.Unmarshal(obj.Data, &st.unsent) + if err != nil { + return err + } + + return nil +} + +// denotePendingSend is called before the pending send. It tracks the send +// internally and notifies the UI of the send +func (st *sendTracker) denotePendingSend(channelID *id.ID, + umi *userMessageInternal) (uint64, error) { + // for a timestamp for the message, use 1 second from now to + // approximate the lag due to round submission + ts := netTime.Now().Add(oneSecond) + + // create a random message id so there will not be collisions in a database + // that requires a unique message ID + stream := st.rngSrc.GetStream() + umi.messageID = cryptoChannel.MessageID{} + num, err := stream.Read(umi.messageID[:]) + if num != len(umi.messageID[:]) || err != nil { + jww.FATAL.Panicf("failed to get a random message ID, read "+ + "len: %d, err: %+v", num, err) + } + stream.Close() + + // submit the message to the UI + uuid, err := st.trigger(channelID, umi, ts, receptionID.EphemeralIdentity{}, + rounds.Round{}, Unsent) + if err != nil { + return 0, err + } + + // track the message on disk + st.handleDenoteSend(uuid, channelID, umi.messageID, + rounds.Round{}) + return uuid, nil +} + +// denotePendingAdminSend is called before the pending admin send. It tracks the +// send internally and notifies the UI of the send +func (st *sendTracker) denotePendingAdminSend(channelID *id.ID, + cm *ChannelMessage) (uint64, error) { + // for a timestamp for the message, use 1 second from now to + // approximate the lag due to round submission + ts := netTime.Now().Add(oneSecond) + + // create a random message id so there will not be collisions in a database + // that requires a unique message ID + stream := st.rngSrc.GetStream() + randMid := cryptoChannel.MessageID{} + num, err := stream.Read(randMid[:]) + if num != len(randMid[:]) || err != nil { + jww.FATAL.Panicf("failed to get a random message ID, read "+ + "len: %d, err: %+v", num, err) + } + stream.Close() + + // submit the message to the UI + uuid, err := st.adminTrigger(channelID, cm, ts, randMid, + receptionID.EphemeralIdentity{}, + rounds.Round{}, Unsent) + + if err != nil { + return 0, err + } + + // track the message on disk + st.handleDenoteSend(uuid, channelID, randMid, + rounds.Round{}) + return uuid, nil +} + +// handleDenoteSend does the nity gritty of editing internal structures +func (st *sendTracker) handleDenoteSend(uuid uint64, channelID *id.ID, + messageID cryptoChannel.MessageID, round rounds.Round) { + st.mux.Lock() + defer st.mux.Unlock() + + //skip if already added + _, existsMessage := st.unsent[uuid] + if existsMessage { + return + } + + st.unsent[uuid] = &tracked{messageID, channelID, round.ID, uuid} + + err := st.storeUnsent() + if err != nil { + jww.FATAL.Panicf(err.Error()) + } +} + +// send tracks a generic send message +func (st *sendTracker) send(uuid uint64, msgID cryptoChannel.MessageID, + round rounds.Round) error { + + // update the on disk message status + t, err := st.handleSend(uuid, msgID, round) + if err != nil { + return err + } + + // Modify the timestamp to reduce the chance message order will be ambiguous + ts := mutateTimestamp(round.Timestamps[states.QUEUED], msgID) + + //update the message on the UI + go st.updateStatus(t.UUID, msgID, ts, round, Sent) + return nil +} + +// send tracks a generic send message +func (st *sendTracker) failedSend(uuid uint64) error { + + // update the on disk message status + t, err := st.handleSendFailed(uuid) + if err != nil { + return err + } + + //update the message on the UI + go st.updateStatus(t.UUID, cryptoChannel.MessageID{}, time.Time{}, rounds.Round{}, Failed) + return nil +} + +// handleSend does the nity gritty of editing internal structures +func (st *sendTracker) handleSend(uuid uint64, + messageID cryptoChannel.MessageID, round rounds.Round) (*tracked, error) { + st.mux.Lock() + defer st.mux.Unlock() + + //check if in unsent + t, exists := st.unsent[uuid] + if !exists { + return nil, errors.New("cannot handle send on an unprepared message") + } + + _, existsMessage := st.byMessageID[messageID] + if existsMessage { + return nil, errors.New("cannot handle send on a message which was " + + "already sent") + } + + t.MsgID = messageID + t.RoundID = round.ID + + //add the roundID + roundsList, _ := st.byRound[round.ID] + st.byRound[round.ID] = append(roundsList, t) + + //add the round + st.byMessageID[messageID] = t + + /*if !existsRound { + rr := &roundResults{ + round: round.ID, + st: st, + } + st.net.GetRoundResults(getRoundResultsTimeout, rr.callback, rr.round) + }*/ + + delete(st.unsent, uuid) + + //store the changed list to disk + err := st.store() + if err != nil { + jww.FATAL.Panicf(err.Error()) + } + + return t, nil +} + +// handleSendFailed does the nity gritty of editing internal structures +func (st *sendTracker) handleSendFailed(uuid uint64) (*tracked, error) { + st.mux.Lock() + defer st.mux.Unlock() + + //check if in unsent + t, exists := st.unsent[uuid] + if !exists { + return nil, errors.New("cannot handle send on an unprepared message") + } + + delete(st.unsent, uuid) + + //store the changed list to disk + err := st.storeUnsent() + if err != nil { + jww.FATAL.Panicf(err.Error()) + } + + return t, nil +} + +// MessageReceive is used when a message is received to check if the message +// was sent by this user. If it was, the correct signal is sent to the event +// model and the function returns true, notifying the caller to not process +// the message +func (st *sendTracker) MessageReceive(messageID cryptoChannel.MessageID, round rounds.Round) bool { + st.mux.RLock() + + //skip if already added + _, existsMessage := st.byMessageID[messageID] + st.mux.RUnlock() + if !existsMessage { + return false + } + + st.mux.Lock() + defer st.mux.Unlock() + msgData, existsMessage := st.byMessageID[messageID] + if !existsMessage { + return false + } + + delete(st.byMessageID, messageID) + + roundList := st.byRound[msgData.RoundID] + if len(roundList) == 1 { + delete(st.byRound, msgData.RoundID) + } else { + newRoundList := make([]*tracked, 0, len(roundList)-1) + for i := range roundList { + if !roundList[i].MsgID.Equals(messageID) { + newRoundList = append(newRoundList, roundList[i]) + } + } + st.byRound[msgData.RoundID] = newRoundList + } + + ts := mutateTimestamp(round.Timestamps[states.QUEUED], messageID) + go st.updateStatus(msgData.UUID, messageID, ts, + round, Delivered) + + if err := st.storeSent(); err != nil { + jww.FATAL.Panicf("failed to store the updated sent list: %+v", err) + } + + return true +} + +// roundResults represents a round which results are waiting on from the cmix layer +type roundResults struct { + round id.Round + st *sendTracker + numChecks uint +} + +// callback is called when results are known about a round. it will re-trigger +// the wait if it fails up to 'maxChecks' times. +func (rr *roundResults) callback(allRoundsSucceeded, timedOut bool, results map[id.Round]cmix.RoundResult) { + + rr.st.mux.Lock() + + //if the message was already handled, do nothing + registered, existsRound := rr.st.byRound[rr.round] + if !existsRound { + rr.st.mux.Unlock() + return + } + + status := Delivered + if !allRoundsSucceeded { + status = Failed + } + + if timedOut { + if rr.numChecks >= maxChecks { + jww.WARN.Printf("Channel messages sent on %d assumed to "+ + "have failed after %d attempts to get round status", rr.round, + maxChecks) + status = Failed + } else { + rr.numChecks++ + + rr.st.mux.Unlock() + + //retry if timed out + go rr.st.net.GetRoundResults(getRoundResultsTimeout, rr.callback, []id.Round{rr.round}...) + return + } + + } + + delete(rr.st.byRound, rr.round) + + for i := range registered { + delete(rr.st.byMessageID, registered[i].MsgID) + } + + if err := rr.st.store(); err != nil { + jww.FATAL.Panicf("failed to store update after "+ + "finalizing delivery of sent messages: %+v", err) + } + + rr.st.mux.Unlock() + + for i := range registered { + round := results[rr.round].Round + ts := mutateTimestamp(round.Timestamps[states.QUEUED], registered[i].MsgID) + go rr.st.updateStatus(registered[i].UUID, registered[i].MsgID, ts, + round, status) + } + +} diff --git a/channels/sendTracker_test.go b/channels/sendTracker_test.go new file mode 100644 index 0000000000000000000000000000000000000000..c2062c6d8c514983b2ab8950fb7b7dc41567a0f6 --- /dev/null +++ b/channels/sendTracker_test.go @@ -0,0 +1,351 @@ +package channels + +import ( + "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/storage/versioned" + cryptoChannel "gitlab.com/elixxir/crypto/channel" + "gitlab.com/elixxir/crypto/fastRNG" + "gitlab.com/elixxir/ekv" + "gitlab.com/elixxir/primitives/states" + "gitlab.com/xx_network/crypto/csprng" + "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/id/ephemeral" + "gitlab.com/xx_network/primitives/netTime" + "testing" + "time" +) + +type mockClient struct{} + +func (mc *mockClient) GetMaxMessageLength() int { + return 2048 +} +func (mc *mockClient) SendWithAssembler(recipient *id.ID, assembler cmix.MessageAssembler, + cmixParams cmix.CMIXParams) (rounds.Round, ephemeral.Id, error) { + return rounds.Round{}, ephemeral.Id{}, nil +} +func (mc *mockClient) IsHealthy() bool { + return true +} +func (mc *mockClient) AddIdentity(id *id.ID, validUntil time.Time, persistent bool) {} +func (mc *mockClient) AddService(clientID *id.ID, newService message.Service, + response message.Processor) { +} +func (mc *mockClient) DeleteClientService(clientID *id.ID) {} +func (mc *mockClient) RemoveIdentity(id *id.ID) {} +func (mc *mockClient) GetRoundResults(timeout time.Duration, roundCallback cmix.RoundEventCallback, + roundList ...id.Round) { +} +func (mc *mockClient) AddHealthCallback(f func(bool)) uint64 { + return 0 +} +func (mc *mockClient) RemoveHealthCallback(uint64) {} + +// Test MessageReceive basic logic +func TestSendTracker_MessageReceive(t *testing.T) { + kv := versioned.NewKV(ekv.MakeMemstore()) + uuidNum := uint64(0) + rid := id.Round(2) + + r := rounds.Round{ + ID: rid, + Timestamps: make(map[states.Round]time.Time), + } + r.Timestamps[states.QUEUED] = time.Now() + trigger := func(chID *id.ID, umi *userMessageInternal, ts time.Time, + receptionID receptionID.EphemeralIdentity, round rounds.Round, + status SentStatus) (uint64, error) { + oldUUID := uuidNum + uuidNum++ + return oldUUID, nil + } + + updateStatus := func(uuid uint64, messageID cryptoChannel.MessageID, + timestamp time.Time, round rounds.Round, status SentStatus) { + } + + cid := id.NewIdFromString("channel", id.User, t) + + crng := fastRNG.NewStreamGenerator(100, 5, csprng.NewSystemRNG) + + st := loadSendTracker(&mockClient{}, kv, trigger, nil, updateStatus, crng) + + mid := cryptoChannel.MakeMessageID([]byte("hello"), cid) + process := st.MessageReceive(mid, r) + if process { + t.Fatalf("Did not receive expected result from MessageReceive") + } + + uuid, err := st.denotePendingSend(cid, &userMessageInternal{ + userMessage: &UserMessage{}, + channelMessage: &ChannelMessage{ + Lease: netTime.Now().UnixNano(), + RoundID: uint64(rid), + PayloadType: 0, + Payload: []byte("hello"), + }}) + if err != nil { + t.Fatalf(err.Error()) + } + + err = st.send(uuid, mid, rounds.Round{ + ID: rid, + State: 1, + }) + if err != nil { + t.Fatalf(err.Error()) + } + process = st.MessageReceive(mid, r) + if !process { + t.Fatalf("Did not receive expected result from MessageReceive") + } + + cid2 := id.NewIdFromString("channel two", id.User, t) + uuid2, err := st.denotePendingSend(cid2, &userMessageInternal{ + userMessage: &UserMessage{}, + channelMessage: &ChannelMessage{ + Lease: netTime.Now().UnixNano(), + RoundID: uint64(rid), + PayloadType: 0, + Payload: []byte("hello again"), + }}) + if err != nil { + t.Fatalf(err.Error()) + } + + err = st.send(uuid2, mid, rounds.Round{ + ID: rid, + State: 1, + }) + process = st.MessageReceive(mid, r) + if !process { + t.Fatalf("Did not receive expected result from MessageReceive") + } +} + +// Test failedSend function, confirming that data is stored appropriately +// and callbacks are called +func TestSendTracker_failedSend(t *testing.T) { + triggerCh := make(chan SentStatus) + + kv := versioned.NewKV(ekv.MakeMemstore()) + + adminTrigger := func(chID *id.ID, cm *ChannelMessage, ts time.Time, + messageID cryptoChannel.MessageID, receptionID receptionID.EphemeralIdentity, + round rounds.Round, status SentStatus) (uint64, error) { + return 0, nil + } + + updateStatus := func(uuid uint64, messageID cryptoChannel.MessageID, + timestamp time.Time, round rounds.Round, status SentStatus) { + triggerCh <- status + } + + crng := fastRNG.NewStreamGenerator(100, 5, csprng.NewSystemRNG) + + st := loadSendTracker(&mockClient{}, kv, nil, adminTrigger, updateStatus, crng) + + cid := id.NewIdFromString("channel", id.User, t) + mid := cryptoChannel.MakeMessageID([]byte("hello"), cid) + rid := id.Round(2) + uuid, err := st.denotePendingAdminSend(cid, &ChannelMessage{ + Lease: 0, + RoundID: uint64(rid), + PayloadType: 0, + Payload: []byte("hello"), + }) + if err != nil { + t.Fatalf(err.Error()) + } + + err = st.failedSend(uuid) + if err != nil { + t.Fatalf(err.Error()) + } + + timeout := time.NewTicker(time.Second * 5) + select { + case s := <-triggerCh: + if s != Failed { + t.Fatalf("Did not receive failed from failed message") + } + t.Log("Received over trigger chan") + case <-timeout.C: + t.Fatal("Timed out waiting for trigger chan") + } + + trackedRound, ok := st.byRound[rid] + if ok { + t.Fatal("Should not have found a tracked round") + } + if len(trackedRound) != 0 { + t.Fatal("Did not find expected number of trackedRounds") + } + + _, ok = st.byMessageID[mid] + if ok { + t.Error("Should not have found tracked message") + } + + _, ok = st.unsent[uuid] + if ok { + t.Fatal("Should not have found an unsent") + } +} + +// Test send tracker send function, confirming that data is stored appropriately +//// and callbacks are called +func TestSendTracker_send(t *testing.T) { + triggerCh := make(chan bool) + + kv := versioned.NewKV(ekv.MakeMemstore()) + trigger := func(chID *id.ID, umi *userMessageInternal, ts time.Time, + receptionID receptionID.EphemeralIdentity, round rounds.Round, status SentStatus) (uint64, error) { + return 0, nil + } + + updateStatus := func(uuid uint64, messageID cryptoChannel.MessageID, + timestamp time.Time, round rounds.Round, status SentStatus) { + triggerCh <- true + } + + crng := fastRNG.NewStreamGenerator(100, 5, csprng.NewSystemRNG) + + st := loadSendTracker(&mockClient{}, kv, trigger, nil, updateStatus, crng) + + cid := id.NewIdFromString("channel", id.User, t) + mid := cryptoChannel.MakeMessageID([]byte("hello"), cid) + rid := id.Round(2) + uuid, err := st.denotePendingSend(cid, &userMessageInternal{ + userMessage: &UserMessage{}, + channelMessage: &ChannelMessage{ + Lease: 0, + RoundID: uint64(rid), + PayloadType: 0, + Payload: []byte("hello"), + }, + messageID: mid, + }) + if err != nil { + t.Fatalf(err.Error()) + } + + err = st.send(uuid, mid, rounds.Round{ + ID: rid, + State: 2, + }) + if err != nil { + t.Fatalf(err.Error()) + } + + timeout := time.NewTicker(time.Second * 5) + select { + case <-triggerCh: + t.Log("Received over trigger chan") + case <-timeout.C: + t.Fatal("Timed out waiting for trigger chan") + } + + trackedRound, ok := st.byRound[rid] + if !ok { + t.Fatal("Should have found a tracked round") + } + if len(trackedRound) != 1 { + t.Fatal("Did not find expected number of trackedRounds") + } + if trackedRound[0].MsgID != mid { + t.Fatalf("Did not find expected message ID in trackedRounds") + } + + trackedMsg, ok := st.byMessageID[mid] + if !ok { + t.Error("Should have found tracked message") + } + if trackedMsg.MsgID != mid { + t.Fatalf("Did not find expected message ID in byMessageID") + } +} + +// Test loading stored byRound map from storage +func TestSendTracker_load_store(t *testing.T) { + kv := versioned.NewKV(ekv.MakeMemstore()) + + crng := fastRNG.NewStreamGenerator(100, 5, csprng.NewSystemRNG) + + st := loadSendTracker(&mockClient{}, kv, nil, nil, nil, crng) + cid := id.NewIdFromString("channel", id.User, t) + mid := cryptoChannel.MakeMessageID([]byte("hello"), cid) + rid := id.Round(2) + st.byRound[rid] = []*tracked{{MsgID: mid, ChannelID: cid, RoundID: rid}} + err := st.store() + if err != nil { + t.Fatalf("Failed to store byRound: %+v", err) + } + + st2 := loadSendTracker(&mockClient{}, kv, nil, nil, nil, crng) + if len(st2.byRound) != len(st.byRound) { + t.Fatalf("byRound was not properly loaded") + } +} + +func TestRoundResult_callback(t *testing.T) { + kv := versioned.NewKV(ekv.MakeMemstore()) + triggerCh := make(chan bool) + update := func(uuid uint64, messageID cryptoChannel.MessageID, + timestamp time.Time, round rounds.Round, status SentStatus) { + triggerCh <- true + } + trigger := func(chID *id.ID, umi *userMessageInternal, ts time.Time, + receptionID receptionID.EphemeralIdentity, round rounds.Round, + status SentStatus) (uint64, error) { + return 0, nil + } + + crng := fastRNG.NewStreamGenerator(100, 5, csprng.NewSystemRNG) + + st := loadSendTracker(&mockClient{}, kv, trigger, nil, update, crng) + + cid := id.NewIdFromString("channel", id.User, t) + mid := cryptoChannel.MakeMessageID([]byte("hello"), cid) + rid := id.Round(2) + uuid, err := st.denotePendingSend(cid, &userMessageInternal{ + userMessage: &UserMessage{}, + channelMessage: &ChannelMessage{ + Lease: 0, + RoundID: uint64(rid), + PayloadType: 0, + Payload: []byte("hello"), + }, + messageID: mid, + }) + if err != nil { + t.Fatalf(err.Error()) + } + + err = st.send(uuid, mid, rounds.Round{ + ID: rid, + State: 2, + }) + + rr := roundResults{ + round: rid, + st: st, + numChecks: 0, + } + + rr.callback(true, false, map[id.Round]cmix.RoundResult{rid: {cmix.Succeeded, rounds.Round{ + ID: rid, + State: 0, + }}}) + + timeout := time.NewTicker(time.Second * 5) + select { + case <-triggerCh: + t.Log("Received trigger") + case <-timeout.C: + t.Fatal("Did not receive update") + } +} diff --git a/channels/send_test.go b/channels/send_test.go new file mode 100644 index 0000000000000000000000000000000000000000..c3c8114c85d69193216c04bf903991f69129917e --- /dev/null +++ b/channels/send_test.go @@ -0,0 +1,616 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file // +//////////////////////////////////////////////////////////////////////////////// + +package channels + +import ( + "bytes" + "crypto/ed25519" + "github.com/golang/protobuf/proto" + "gitlab.com/elixxir/client/cmix/identity/receptionID" + "gitlab.com/elixxir/client/cmix/rounds" + "gitlab.com/elixxir/client/storage/versioned" + cryptoChannel "gitlab.com/elixxir/crypto/channel" + "gitlab.com/elixxir/crypto/fastRNG" + "gitlab.com/elixxir/crypto/rsa" + "gitlab.com/elixxir/ekv" + "gitlab.com/xx_network/crypto/csprng" + "gitlab.com/xx_network/primitives/netTime" + "math/rand" + "sync" + "testing" + "time" + + "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/id/ephemeral" + + "gitlab.com/elixxir/client/broadcast" + "gitlab.com/elixxir/client/cmix" + cryptoBroadcast "gitlab.com/elixxir/crypto/broadcast" +) + +const returnedRound = 42 + +type mockBroadcastChannel struct { + hasRun bool + + payload []byte + params cmix.CMIXParams + + pk rsa.PrivateKey + + crypto *cryptoBroadcast.Channel +} + +func (m *mockBroadcastChannel) MaxPayloadSize() int { + return 1024 +} + +func (m *mockBroadcastChannel) MaxRSAToPublicPayloadSize() int { + return 512 +} + +func (m *mockBroadcastChannel) Get() *cryptoBroadcast.Channel { + return m.crypto +} + +func (m *mockBroadcastChannel) Broadcast(payload []byte, cMixParams cmix.CMIXParams) ( + rounds.Round, ephemeral.Id, error) { + + m.hasRun = true + + m.payload = payload + m.params = cMixParams + + return rounds.Round{ID: 123}, ephemeral.Id{}, nil +} + +func (m *mockBroadcastChannel) BroadcastWithAssembler(assembler broadcast.Assembler, cMixParams cmix.CMIXParams) ( + rounds.Round, ephemeral.Id, error) { + m.hasRun = true + + var err error + + m.payload, err = assembler(returnedRound) + m.params = cMixParams + + return rounds.Round{ID: 123}, ephemeral.Id{}, err +} + +func (m *mockBroadcastChannel) BroadcastRSAtoPublic(pk rsa.PrivateKey, payload []byte, + cMixParams cmix.CMIXParams) (rounds.Round, ephemeral.Id, error) { + m.hasRun = true + + m.payload = payload + m.params = cMixParams + + m.pk = pk + return rounds.Round{ID: 123}, ephemeral.Id{}, nil +} + +func (m *mockBroadcastChannel) BroadcastRSAToPublicWithAssembler( + pk rsa.PrivateKey, assembler broadcast.Assembler, + cMixParams cmix.CMIXParams) (rounds.Round, ephemeral.Id, error) { + + m.hasRun = true + + var err error + + m.payload, err = assembler(returnedRound) + m.params = cMixParams + + m.pk = pk + + return rounds.Round{ID: 123}, ephemeral.Id{}, err +} + +func (m *mockBroadcastChannel) RegisterListener(listenerCb broadcast.ListenerFunc, method broadcast.Method) error { + return nil +} + +func (m *mockBroadcastChannel) Stop() { +} + +type mockNameService struct { + validChMsg bool +} + +func (m *mockNameService) GetUsername() string { + return "Alice" +} + +func (m *mockNameService) GetChannelValidationSignature() (signature []byte, lease time.Time) { + return []byte("fake validation sig"), netTime.Now() +} + +func (m *mockNameService) GetChannelPubkey() ed25519.PublicKey { + return []byte("fake pubkey") +} + +func (m *mockNameService) SignChannelMessage(message []byte) (signature []byte, err error) { + return []byte("fake sig"), nil +} + +func (m *mockNameService) ValidateChannelMessage(username string, lease time.Time, + pubKey ed25519.PublicKey, authorIDSignature []byte) bool { + return m.validChMsg +} + +func TestSendGeneric(t *testing.T) { + + nameService := new(mockNameService) + nameService.validChMsg = true + + rng := rand.New(rand.NewSource(64)) + + pi, err := cryptoChannel.GenerateIdentity(rng) + if err != nil { + t.Fatalf(err.Error()) + } + + crng := fastRNG.NewStreamGenerator(100, 5, csprng.NewSystemRNG) + + m := &manager{ + me: pi, + channels: make(map[id.ID]*joinedChannel), + mux: sync.RWMutex{}, + rng: fastRNG.NewStreamGenerator(1000, 10, csprng.NewSystemRNG), + nicknameManager: &nicknameManager{ + byChannel: make(map[id.ID]string), + kv: nil, + }, + st: loadSendTracker(&mockBroadcastClient{}, + versioned.NewKV(ekv.MakeMemstore()), func(chID *id.ID, + umi *userMessageInternal, ts time.Time, + receptionID receptionID.EphemeralIdentity, + round rounds.Round, status SentStatus) (uint64, error) { + return 0, nil + }, func(chID *id.ID, cm *ChannelMessage, ts time.Time, + messageID cryptoChannel.MessageID, receptionID receptionID.EphemeralIdentity, + round rounds.Round, status SentStatus) (uint64, error) { + return 0, nil + }, func(uuid uint64, messageID cryptoChannel.MessageID, + timestamp time.Time, round rounds.Round, status SentStatus) { + }, crng), + } + + channelID := new(id.ID) + messageType := Text + msg := []byte("hello world") + validUntil := time.Hour + params := new(cmix.CMIXParams) + + mbc := &mockBroadcastChannel{} + + m.channels[*channelID] = &joinedChannel{ + broadcast: mbc, + } + + messageId, roundId, ephemeralId, err := m.SendGeneric( + channelID, + messageType, + msg, + validUntil, + *params) + if err != nil { + t.Logf("ERROR %v", err) + t.Fail() + } + t.Logf("messageId %v, roundId %v, ephemeralId %v", messageId, roundId, ephemeralId) + + // verify the message was handled correctly + + // decode the user message + umi, err := unmarshalUserMessageInternal(mbc.payload, channelID) + if err != nil { + t.Fatalf("Failed to decode the user message: %s", err) + } + + // do checks of the data + if !umi.GetMessageID().Equals(messageId) { + t.Errorf("The message IDs do not match. %s vs %s ", + umi.messageID, messageId) + } + + if !bytes.Equal(umi.GetChannelMessage().Payload, msg) { + t.Errorf("The payload does not match. %s vs %s ", + umi.GetChannelMessage().Payload, msg) + } + + if MessageType(umi.GetChannelMessage().PayloadType) != messageType { + t.Fatalf("Message types do not match, %s vs %s", + MessageType(umi.GetChannelMessage().PayloadType), messageType) + } + + if umi.GetChannelMessage().RoundID != returnedRound { + t.Errorf("The returned round is incorrect, %d vs %d", + umi.GetChannelMessage().RoundID, returnedRound) + } + +} + +func TestAdminGeneric(t *testing.T) { + + prng := rand.New(rand.NewSource(64)) + + pi, err := cryptoChannel.GenerateIdentity(prng) + if err != nil { + t.Fatalf(err.Error()) + } + + crng := fastRNG.NewStreamGenerator(100, 5, csprng.NewSystemRNG) + + m := &manager{ + channels: make(map[id.ID]*joinedChannel), + nicknameManager: &nicknameManager{ + byChannel: make(map[id.ID]string), + kv: nil, + }, + me: pi, + rng: fastRNG.NewStreamGenerator(1000, 10, csprng.NewSystemRNG), + st: loadSendTracker(&mockBroadcastClient{}, + versioned.NewKV(ekv.MakeMemstore()), func(chID *id.ID, + umi *userMessageInternal, ts time.Time, + receptionID receptionID.EphemeralIdentity, + round rounds.Round, status SentStatus) (uint64, error) { + return 0, nil + }, func(chID *id.ID, cm *ChannelMessage, ts time.Time, + messageID cryptoChannel.MessageID, receptionID receptionID.EphemeralIdentity, + round rounds.Round, status SentStatus) (uint64, error) { + return 0, nil + }, func(uuid uint64, messageID cryptoChannel.MessageID, + timestamp time.Time, round rounds.Round, status SentStatus) { + }, crng), + } + + messageType := Text + msg := []byte("hello world") + validUntil := time.Hour + + rng := &csprng.SystemRNG{} + ch, priv, err := cryptoBroadcast.NewChannel("test", "test", + 1000, rng) + if err != nil { + t.Fatalf("Failed to generate channel: %+v", err) + } + + mbc := &mockBroadcastChannel{crypto: ch} + + m.channels[*ch.ReceptionID] = &joinedChannel{ + broadcast: mbc, + } + + messageId, roundId, ephemeralId, err := m.SendAdminGeneric(priv, + ch.ReceptionID, messageType, msg, validUntil, cmix.GetDefaultCMIXParams()) + if err != nil { + t.Fatalf("Failed to SendAdminGeneric: %v", err) + } + t.Logf("messageId %v, roundId %v, ephemeralId %v", messageId, roundId, ephemeralId) + + // verify the message was handled correctly + + msgID := cryptoChannel.MakeMessageID(mbc.payload, ch.ReceptionID) + + if !msgID.Equals(messageId) { + t.Errorf("The message IDs do not match. %s vs %s ", + msgID, messageId) + } + + // decode the channel message + chMgs := &ChannelMessage{} + err = proto.Unmarshal(mbc.payload, chMgs) + if err != nil { + t.Fatalf("Failed to decode the channel message: %s", err) + } + + if !bytes.Equal(chMgs.Payload, msg) { + t.Errorf("Messages do not match, %s vs %s", chMgs.Payload, msg) + } + + if MessageType(chMgs.PayloadType) != messageType { + t.Errorf("Message types do not match, %s vs %s", + MessageType(chMgs.PayloadType), messageType) + } + + if chMgs.RoundID != returnedRound { + t.Errorf("The returned round is incorrect, %d vs %d", + chMgs.RoundID, returnedRound) + } +} + +func TestSendMessage(t *testing.T) { + + nameService := new(mockNameService) + nameService.validChMsg = true + + prng := rand.New(rand.NewSource(64)) + + pi, err := cryptoChannel.GenerateIdentity(prng) + if err != nil { + t.Fatalf(err.Error()) + } + + crng := fastRNG.NewStreamGenerator(100, 5, csprng.NewSystemRNG) + + m := &manager{ + me: pi, + channels: make(map[id.ID]*joinedChannel), + nicknameManager: &nicknameManager{ + byChannel: make(map[id.ID]string), + kv: nil, + }, + rng: fastRNG.NewStreamGenerator(1000, 10, csprng.NewSystemRNG), + st: loadSendTracker(&mockBroadcastClient{}, + versioned.NewKV(ekv.MakeMemstore()), func(chID *id.ID, + umi *userMessageInternal, ts time.Time, + receptionID receptionID.EphemeralIdentity, + round rounds.Round, status SentStatus) (uint64, error) { + return 0, nil + }, func(chID *id.ID, cm *ChannelMessage, ts time.Time, + messageID cryptoChannel.MessageID, receptionID receptionID.EphemeralIdentity, + round rounds.Round, status SentStatus) (uint64, error) { + return 0, nil + }, func(uuid uint64, messageID cryptoChannel.MessageID, + timestamp time.Time, round rounds.Round, status SentStatus) { + }, crng), + } + + channelID := new(id.ID) + messageType := Text + msg := "hello world" + validUntil := time.Hour + params := new(cmix.CMIXParams) + + mbc := &mockBroadcastChannel{} + + m.channels[*channelID] = &joinedChannel{ + broadcast: mbc, + } + + messageId, roundId, ephemeralId, err := m.SendMessage( + channelID, + msg, + validUntil, + *params) + if err != nil { + t.Logf("ERROR %v", err) + t.Fail() + } + t.Logf("messageId %v, roundId %v, ephemeralId %v", messageId, roundId, ephemeralId) + + // verify the message was handled correctly + + // decode the user message + umi, err := unmarshalUserMessageInternal(mbc.payload, channelID) + if err != nil { + t.Fatalf("Failed to decode the user message: %s", err) + } + + // do checks of the data + if !umi.GetMessageID().Equals(messageId) { + t.Errorf("The message IDs do not match. %s vs %s ", + umi.messageID, messageId) + } + + if MessageType(umi.GetChannelMessage().PayloadType) != messageType { + t.Fatalf("Message types do not match, %s vs %s", + MessageType(umi.GetChannelMessage().PayloadType), messageType) + } + + if umi.GetChannelMessage().RoundID != returnedRound { + t.Errorf("The returned round is incorrect, %d vs %d", + umi.GetChannelMessage().RoundID, returnedRound) + } + + // decode the text message + txt := &CMIXChannelText{} + err = proto.Unmarshal(umi.GetChannelMessage().Payload, txt) + if err != nil { + t.Fatalf("Could not decode cmix channel text: %s", err) + } + + if txt.Text != msg { + t.Errorf("Content of message is incorrect: %s vs %s", txt.Text, msg) + } + + if txt.ReplyMessageID != nil { + t.Errorf("Reply ID on a text message is not nil") + } +} + +func TestSendReply(t *testing.T) { + + prng := rand.New(rand.NewSource(64)) + + pi, err := cryptoChannel.GenerateIdentity(prng) + if err != nil { + t.Fatalf(err.Error()) + } + + crng := fastRNG.NewStreamGenerator(100, 5, csprng.NewSystemRNG) + + m := &manager{ + me: pi, + channels: make(map[id.ID]*joinedChannel), + nicknameManager: &nicknameManager{ + byChannel: make(map[id.ID]string), + kv: nil, + }, + rng: fastRNG.NewStreamGenerator(1000, 10, csprng.NewSystemRNG), + st: loadSendTracker(&mockBroadcastClient{}, + versioned.NewKV(ekv.MakeMemstore()), func(chID *id.ID, + umi *userMessageInternal, ts time.Time, + receptionID receptionID.EphemeralIdentity, + round rounds.Round, status SentStatus) (uint64, error) { + return 0, nil + }, func(chID *id.ID, cm *ChannelMessage, ts time.Time, + messageID cryptoChannel.MessageID, receptionID receptionID.EphemeralIdentity, + round rounds.Round, status SentStatus) (uint64, error) { + return 0, nil + }, func(uuid uint64, messageID cryptoChannel.MessageID, + timestamp time.Time, round rounds.Round, status SentStatus) { + }, crng), + } + + channelID := new(id.ID) + messageType := Text + msg := "hello world" + validUntil := time.Hour + params := new(cmix.CMIXParams) + + replyMsgID := cryptoChannel.MessageID{} + replyMsgID[0] = 69 + + mbc := &mockBroadcastChannel{} + + m.channels[*channelID] = &joinedChannel{ + broadcast: mbc, + } + + messageId, roundId, ephemeralId, err := m.SendReply( + channelID, msg, replyMsgID, validUntil, *params) + if err != nil { + t.Logf("ERROR %v", err) + t.Fail() + } + t.Logf("messageId %v, roundId %v, ephemeralId %v", messageId, roundId, ephemeralId) + + // verify the message was handled correctly + + // decode the user message + umi, err := unmarshalUserMessageInternal(mbc.payload, channelID) + if err != nil { + t.Fatalf("Failed to decode the user message: %s", err) + } + + // do checks of the data + if !umi.GetMessageID().Equals(messageId) { + t.Errorf("The message IDs do not match. %s vs %s ", + umi.messageID, messageId) + } + + if MessageType(umi.GetChannelMessage().PayloadType) != messageType { + t.Fatalf("Message types do not match, %s vs %s", + MessageType(umi.GetChannelMessage().PayloadType), messageType) + } + + if umi.GetChannelMessage().RoundID != returnedRound { + t.Errorf("The returned round is incorrect, %d vs %d", + umi.GetChannelMessage().RoundID, returnedRound) + } + + // decode the text message + txt := &CMIXChannelText{} + err = proto.Unmarshal(umi.GetChannelMessage().Payload, txt) + if err != nil { + t.Fatalf("Could not decode cmix channel text: %s", err) + } + + if txt.Text != msg { + t.Errorf("Content of message is incorrect: %s vs %s", txt.Text, msg) + } + + if !bytes.Equal(txt.ReplyMessageID, replyMsgID[:]) { + t.Errorf("The reply message ID is not what was passed in") + } +} + +func TestSendReaction(t *testing.T) { + + prng := rand.New(rand.NewSource(64)) + + pi, err := cryptoChannel.GenerateIdentity(prng) + if err != nil { + t.Fatalf(err.Error()) + } + + crng := fastRNG.NewStreamGenerator(100, 5, csprng.NewSystemRNG) + + m := &manager{ + me: pi, + nicknameManager: &nicknameManager{ + byChannel: make(map[id.ID]string), + kv: nil, + }, + rng: fastRNG.NewStreamGenerator(1000, 10, csprng.NewSystemRNG), + channels: make(map[id.ID]*joinedChannel), + st: loadSendTracker(&mockBroadcastClient{}, + versioned.NewKV(ekv.MakeMemstore()), func(chID *id.ID, + umi *userMessageInternal, ts time.Time, + receptionID receptionID.EphemeralIdentity, + round rounds.Round, status SentStatus) (uint64, error) { + return 0, nil + }, func(chID *id.ID, cm *ChannelMessage, ts time.Time, + messageID cryptoChannel.MessageID, receptionID receptionID.EphemeralIdentity, + round rounds.Round, status SentStatus) (uint64, error) { + return 0, nil + }, func(uuid uint64, messageID cryptoChannel.MessageID, + timestamp time.Time, round rounds.Round, status SentStatus) { + }, crng), + } + + channelID := new(id.ID) + messageType := Reaction + msg := "🍆" + params := new(cmix.CMIXParams) + + replyMsgID := cryptoChannel.MessageID{} + replyMsgID[0] = 69 + + mbc := &mockBroadcastChannel{} + + m.channels[*channelID] = &joinedChannel{ + broadcast: mbc, + } + + messageId, roundId, ephemeralId, err := m.SendReaction( + channelID, msg, replyMsgID, *params) + if err != nil { + t.Logf("ERROR %v", err) + t.Fail() + } + t.Logf("messageId %v, roundId %v, ephemeralId %v", messageId, roundId, ephemeralId) + + // verify the message was handled correctly + + // decode the user message + umi, err := unmarshalUserMessageInternal(mbc.payload, channelID) + if err != nil { + t.Fatalf("Failed to decode the user message: %s", err) + } + + // do checks of the data + if !umi.GetMessageID().Equals(messageId) { + t.Errorf("The message IDs do not match. %s vs %s ", + umi.messageID, messageId) + } + + if MessageType(umi.GetChannelMessage().PayloadType) != messageType { + t.Fatalf("Message types do not match, %s vs %s", + MessageType(umi.GetChannelMessage().PayloadType), messageType) + } + + if umi.GetChannelMessage().RoundID != returnedRound { + t.Errorf("The returned round is incorrect, %d vs %d", + umi.GetChannelMessage().RoundID, returnedRound) + } + + // decode the text message + txt := &CMIXChannelReaction{} + err = proto.Unmarshal(umi.GetChannelMessage().Payload, txt) + if err != nil { + t.Fatalf("Could not decode cmix channel text: %s", err) + } + + if txt.Reaction != msg { + t.Errorf("Content of message is incorrect: %s vs %s", txt.Reaction, msg) + } + + if !bytes.Equal(txt.ReactionMessageID, replyMsgID[:]) { + t.Errorf("The reply message ID is not what was passed in") + } +} diff --git a/channels/text.pb.go b/channels/text.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..5eea7e0ed48b0a5decd88d14d002fbf24c03b39a --- /dev/null +++ b/channels/text.pb.go @@ -0,0 +1,259 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file // +//////////////////////////////////////////////////////////////////////////////// + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.27.1 +// protoc v3.15.6 +// source: text.proto + +package channels + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// CMIXChannelText is the payload for sending normal text messages to channels +// the replyMessageID is nil when it is not a reply +type CMIXChannelText struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` + Text string `protobuf:"bytes,2,opt,name=text,proto3" json:"text,omitempty"` + ReplyMessageID []byte `protobuf:"bytes,3,opt,name=replyMessageID,proto3" json:"replyMessageID,omitempty"` +} + +func (x *CMIXChannelText) Reset() { + *x = CMIXChannelText{} + if protoimpl.UnsafeEnabled { + mi := &file_text_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CMIXChannelText) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CMIXChannelText) ProtoMessage() {} + +func (x *CMIXChannelText) ProtoReflect() protoreflect.Message { + mi := &file_text_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CMIXChannelText.ProtoReflect.Descriptor instead. +func (*CMIXChannelText) Descriptor() ([]byte, []int) { + return file_text_proto_rawDescGZIP(), []int{0} +} + +func (x *CMIXChannelText) GetVersion() uint32 { + if x != nil { + return x.Version + } + return 0 +} + +func (x *CMIXChannelText) GetText() string { + if x != nil { + return x.Text + } + return "" +} + +func (x *CMIXChannelText) GetReplyMessageID() []byte { + if x != nil { + return x.ReplyMessageID + } + return nil +} + +// CMIXChannelReaction is the payload for reactions. The reaction must be a +// single emoji and the reactionMessageID must be non nil and a real message +// in the channel +type CMIXChannelReaction struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` + Reaction string `protobuf:"bytes,2,opt,name=reaction,proto3" json:"reaction,omitempty"` + ReactionMessageID []byte `protobuf:"bytes,3,opt,name=reactionMessageID,proto3" json:"reactionMessageID,omitempty"` +} + +func (x *CMIXChannelReaction) Reset() { + *x = CMIXChannelReaction{} + if protoimpl.UnsafeEnabled { + mi := &file_text_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CMIXChannelReaction) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CMIXChannelReaction) ProtoMessage() {} + +func (x *CMIXChannelReaction) ProtoReflect() protoreflect.Message { + mi := &file_text_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CMIXChannelReaction.ProtoReflect.Descriptor instead. +func (*CMIXChannelReaction) Descriptor() ([]byte, []int) { + return file_text_proto_rawDescGZIP(), []int{1} +} + +func (x *CMIXChannelReaction) GetVersion() uint32 { + if x != nil { + return x.Version + } + return 0 +} + +func (x *CMIXChannelReaction) GetReaction() string { + if x != nil { + return x.Reaction + } + return "" +} + +func (x *CMIXChannelReaction) GetReactionMessageID() []byte { + if x != nil { + return x.ReactionMessageID + } + return nil +} + +var File_text_proto protoreflect.FileDescriptor + +var file_text_proto_rawDesc = []byte{ + 0x0a, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x08, 0x63, 0x68, + 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x22, 0x67, 0x0a, 0x0f, 0x43, 0x4d, 0x49, 0x58, 0x43, 0x68, + 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x54, 0x65, 0x78, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x78, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x74, 0x65, 0x78, 0x74, 0x12, 0x26, 0x0a, 0x0e, 0x72, 0x65, 0x70, 0x6c, 0x79, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x44, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x0e, 0x72, 0x65, 0x70, 0x6c, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x44, 0x22, + 0x79, 0x0a, 0x13, 0x43, 0x4d, 0x49, 0x58, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x52, 0x65, + 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2c, 0x0a, 0x11, + 0x72, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, + 0x44, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x11, 0x72, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x44, 0x42, 0x24, 0x5a, 0x22, 0x67, 0x69, + 0x74, 0x6c, 0x61, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x6c, 0x69, 0x78, 0x78, 0x69, 0x72, + 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2f, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_text_proto_rawDescOnce sync.Once + file_text_proto_rawDescData = file_text_proto_rawDesc +) + +func file_text_proto_rawDescGZIP() []byte { + file_text_proto_rawDescOnce.Do(func() { + file_text_proto_rawDescData = protoimpl.X.CompressGZIP(file_text_proto_rawDescData) + }) + return file_text_proto_rawDescData +} + +var file_text_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_text_proto_goTypes = []interface{}{ + (*CMIXChannelText)(nil), // 0: channels.CMIXChannelText + (*CMIXChannelReaction)(nil), // 1: channels.CMIXChannelReaction +} +var file_text_proto_depIdxs = []int32{ + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_text_proto_init() } +func file_text_proto_init() { + if File_text_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_text_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CMIXChannelText); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_text_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CMIXChannelReaction); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_text_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_text_proto_goTypes, + DependencyIndexes: file_text_proto_depIdxs, + MessageInfos: file_text_proto_msgTypes, + }.Build() + File_text_proto = out.File + file_text_proto_rawDesc = nil + file_text_proto_goTypes = nil + file_text_proto_depIdxs = nil +} diff --git a/channels/text.proto b/channels/text.proto new file mode 100644 index 0000000000000000000000000000000000000000..26cc59ca76ed8b888b9969730ad9fe2e1fe80d8b --- /dev/null +++ b/channels/text.proto @@ -0,0 +1,29 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file // +//////////////////////////////////////////////////////////////////////////////// + +syntax = "proto3"; + +option go_package = "gitlab.com/elixxir/client/channels"; + +package channels; + +// CMIXChannelText is the payload for sending normal text messages to channels +// the replyMessageID is nil when it is not a reply +message CMIXChannelText { + uint32 version = 1; + string text = 2; + bytes replyMessageID = 3; +} + +// CMIXChannelReaction is the payload for reactions. The reaction must be a +// single emoji and the reactionMessageID must be non nil and a real message +// in the channel +message CMIXChannelReaction { + uint32 version = 1; + string reaction = 2; + bytes reactionMessageID = 3; +} \ No newline at end of file diff --git a/channels/userListener.go b/channels/userListener.go new file mode 100644 index 0000000000000000000000000000000000000000..dad5075fd08daf0a46f2a221108df2b90dc45a91 --- /dev/null +++ b/channels/userListener.go @@ -0,0 +1,80 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file // +//////////////////////////////////////////////////////////////////////////////// + +package channels + +import ( + "crypto/ed25519" + jww "github.com/spf13/jwalterweatherman" + "gitlab.com/elixxir/client/cmix/identity/receptionID" + "gitlab.com/elixxir/client/cmix/rounds" + "gitlab.com/elixxir/primitives/states" + "gitlab.com/xx_network/primitives/id" +) + +// the userListener adheres to the [broadcast.ListenerFunc] interface and is +// used when user messages are received on the channel +type userListener struct { + name NameService + chID *id.ID + trigger triggerEventFunc + checkSent messageReceiveFunc +} + +// Listen is called when a message is received for the user listener +func (ul *userListener) Listen(payload []byte, + receptionID receptionID.EphemeralIdentity, round rounds.Round) { + + //Decode the message as a user message + umi, err := unmarshalUserMessageInternal(payload, ul.chID) + if err != nil { + jww.WARN.Printf("Failed to unmarshal User Message on "+ + "channel %s", ul.chID) + return + } + + um := umi.GetUserMessage() + cm := umi.GetChannelMessage() + msgID := umi.GetMessageID() + + //check if we sent the message, ignore triggering if we sent + if ul.checkSent(msgID, round) { + return + } + + /*CRYPTOGRAPHICALLY RELEVANT CHECKS*/ + + // check the round to ensure the message is not a replay + if id.Round(cm.RoundID) != round.ID { + jww.WARN.Printf("The round message %s send on %d referenced "+ + "(%d) was not the same as the round the message was found on (%d)", + msgID, ul.chID, cm.RoundID, round.ID) + return + } + + // check that the user properly signed the message + if !ed25519.Verify(um.ECCPublicKey, um.Message, um.Signature) { + jww.WARN.Printf("Message %s on channel %s purportedly from %s "+ + "failed its user signature with signature %v", msgID, + ul.chID, cm.Nickname, um.Signature) + return + } + + // Modify the timestamp to reduce the chance message order will be ambiguous + ts := mutateTimestamp(round.Timestamps[states.QUEUED], msgID) + + //TODO: Processing of the message relative to admin commands will be here + + //Submit the message to the event model for listening + if uuid, err := ul.trigger(ul.chID, umi, ts, receptionID, round, + Delivered); err != nil { + jww.WARN.Printf("Error in passing off trigger for "+ + "message (UUID: %d): %+v", uuid, err) + } + + return +} diff --git a/channels/userListener_test.go b/channels/userListener_test.go new file mode 100644 index 0000000000000000000000000000000000000000..23d8ae8c1188ef7c717680f4b6a980dace81e0cc --- /dev/null +++ b/channels/userListener_test.go @@ -0,0 +1,358 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file // +//////////////////////////////////////////////////////////////////////////////// + +package channels + +import ( + "bytes" + "crypto/ed25519" + "gitlab.com/xx_network/primitives/netTime" + "math/rand" + "testing" + "time" + + "github.com/golang/protobuf/proto" + + "gitlab.com/elixxir/client/cmix/identity/receptionID" + "gitlab.com/elixxir/client/cmix/rounds" + cryptoChannel "gitlab.com/elixxir/crypto/channel" + "gitlab.com/elixxir/primitives/states" + "gitlab.com/xx_network/primitives/id" +) + +type triggerEventDummy struct { + gotData bool + + chID *id.ID + umi *userMessageInternal + msgID cryptoChannel.MessageID + receptionID receptionID.EphemeralIdentity + round rounds.Round +} + +func (ted *triggerEventDummy) triggerEvent(chID *id.ID, umi *userMessageInternal, + ts time.Time, receptionID receptionID.EphemeralIdentity, round rounds.Round, + sent SentStatus) (uint64, error) { + ted.gotData = true + + ted.chID = chID + ted.umi = umi + ted.receptionID = receptionID + ted.round = round + ted.msgID = umi.GetMessageID() + + return 0, nil +} + +// Tests the happy path +func TestUserListener_Listen(t *testing.T) { + + //build inputs + chID := &id.ID{} + chID[0] = 1 + + r := rounds.Round{ID: 420, Timestamps: make(map[states.Round]time.Time)} + r.Timestamps[states.QUEUED] = netTime.Now() + + rng := rand.New(rand.NewSource(42)) + pub, priv, err := ed25519.GenerateKey(rng) + if err != nil { + t.Fatalf("failed to generate ed25519 keypair, cant run test") + } + + cm := &ChannelMessage{ + Lease: int64(time.Hour), + RoundID: uint64(r.ID), + PayloadType: 42, + Payload: []byte("blarg"), + } + + cmSerial, err := proto.Marshal(cm) + if err != nil { + t.Fatalf("Failed to marshal proto: %+v", err) + } + + msgID := cryptoChannel.MakeMessageID(cmSerial, chID) + + sig := ed25519.Sign(priv, cmSerial) + ns := &mockNameService{validChMsg: true} + + um := &UserMessage{ + Message: cmSerial, + Signature: sig, + ECCPublicKey: pub, + } + + umSerial, err := proto.Marshal(um) + if err != nil { + t.Fatalf("Failed to marshal proto: %+v", err) + } + + //build the listener + dummy := &triggerEventDummy{} + + al := userListener{ + chID: chID, + name: ns, + trigger: dummy.triggerEvent, + checkSent: func(messageID cryptoChannel.MessageID, r rounds.Round) bool { return false }, + } + + //call the listener + al.Listen(umSerial, receptionID.EphemeralIdentity{}, r) + + //check the results + if !dummy.gotData { + t.Fatalf("No data returned after valid listen") + } + + if !dummy.chID.Cmp(chID) { + t.Errorf("Channel ID not correct: %s vs %s", dummy.chID, chID) + } + + if !bytes.Equal(um.Message, dummy.umi.userMessage.Message) { + t.Errorf("message not correct: %s vs %s", um.Message, + dummy.umi.userMessage.Message) + } + + if !msgID.Equals(dummy.msgID) { + t.Errorf("messageIDs not correct: %s vs %s", msgID, + dummy.msgID) + } + + if r.ID != dummy.round.ID { + t.Errorf("rounds not correct: %s vs %s", r.ID, + dummy.round.ID) + } +} + +//tests that the message is rejected when the user signature is invalid +func TestUserListener_Listen_BadUserSig(t *testing.T) { + + //build inputs + chID := &id.ID{} + chID[0] = 1 + + r := rounds.Round{ID: 420, Timestamps: make(map[states.Round]time.Time)} + r.Timestamps[states.QUEUED] = netTime.Now() + + rng := rand.New(rand.NewSource(42)) + pub, _, err := ed25519.GenerateKey(rng) + if err != nil { + t.Fatalf("failed to generate ed25519 keypair, cant run test") + } + + cm := &ChannelMessage{ + Lease: int64(time.Hour), + RoundID: uint64(r.ID), + PayloadType: 42, + Payload: []byte("blarg"), + } + + cmSerial, err := proto.Marshal(cm) + if err != nil { + t.Fatalf("Failed to marshal proto: %+v", err) + } + + _, badpriv, err := ed25519.GenerateKey(rng) + if err != nil { + t.Fatalf("failed to generate ed25519 keypair, cant run test") + } + + sig := ed25519.Sign(badpriv, cmSerial) + ns := &mockNameService{validChMsg: true} + + um := &UserMessage{ + Message: cmSerial, + Signature: sig, + ECCPublicKey: pub, + } + + umSerial, err := proto.Marshal(um) + if err != nil { + t.Fatalf("Failed to marshal proto: %+v", err) + } + + //build the listener + dummy := &triggerEventDummy{} + + al := userListener{ + chID: chID, + name: ns, + trigger: dummy.triggerEvent, + checkSent: func(messageID cryptoChannel.MessageID, r rounds.Round) bool { return false }, + } + + //call the listener + al.Listen(umSerial, receptionID.EphemeralIdentity{}, r) + + //check the results + if dummy.gotData { + t.Fatalf("Data returned after invalid listen") + } +} + +//tests that the message is rejected when the round in the message does not +//match the round passed in +func TestUserListener_Listen_BadRound(t *testing.T) { + + //build inputs + chID := &id.ID{} + chID[0] = 1 + + r := rounds.Round{ID: 420, Timestamps: make(map[states.Round]time.Time)} + r.Timestamps[states.QUEUED] = netTime.Now() + + rng := rand.New(rand.NewSource(42)) + pub, priv, err := ed25519.GenerateKey(rng) + if err != nil { + t.Fatalf("failed to generate ed25519 keypair, cant run test") + } + + cm := &ChannelMessage{ + Lease: int64(time.Hour), + //make the round not match + RoundID: 69, + PayloadType: 42, + Payload: []byte("blarg"), + } + + cmSerial, err := proto.Marshal(cm) + if err != nil { + t.Fatalf("Failed to marshal proto: %+v", err) + } + + sig := ed25519.Sign(priv, cmSerial) + ns := &mockNameService{validChMsg: true} + + um := &UserMessage{ + Message: cmSerial, + Signature: sig, + ECCPublicKey: pub, + } + + umSerial, err := proto.Marshal(um) + if err != nil { + t.Fatalf("Failed to marshal proto: %+v", err) + } + + //build the listener + dummy := &triggerEventDummy{} + + al := userListener{ + chID: chID, + name: ns, + trigger: dummy.triggerEvent, + checkSent: func(messageID cryptoChannel.MessageID, r rounds.Round) bool { return false }, + } + + //call the listener + al.Listen(umSerial, receptionID.EphemeralIdentity{}, r) + + //check the results + if dummy.gotData { + t.Fatalf("Data returned after invalid listen") + } +} + +//tests that the message is rejected when the user message is malformed +func TestUserListener_Listen_BadMessage(t *testing.T) { + + //build inputs + chID := &id.ID{} + chID[0] = 1 + + r := rounds.Round{ID: 420, Timestamps: make(map[states.Round]time.Time)} + r.Timestamps[states.QUEUED] = netTime.Now() + + ns := &mockNameService{validChMsg: true} + + umSerial := []byte("malformed") + + //build the listener + dummy := &triggerEventDummy{} + + al := userListener{ + chID: chID, + name: ns, + trigger: dummy.triggerEvent, + checkSent: func(messageID cryptoChannel.MessageID, r rounds.Round) bool { return false }, + } + + //call the listener + al.Listen(umSerial, receptionID.EphemeralIdentity{}, r) + + //check the results + if dummy.gotData { + t.Fatalf("Data returned after invalid listen") + } +} + +//tests that the message is rejected when the sized broadcast is malformed +func TestUserListener_Listen_BadSizedBroadcast(t *testing.T) { + + //build inputs + chID := &id.ID{} + chID[0] = 1 + + r := rounds.Round{ID: 420, Timestamps: make(map[states.Round]time.Time)} + r.Timestamps[states.QUEUED] = netTime.Now() + + rng := rand.New(rand.NewSource(42)) + pub, priv, err := ed25519.GenerateKey(rng) + if err != nil { + t.Fatalf("failed to generate ed25519 keypair, cant run test") + } + + cm := &ChannelMessage{ + Lease: int64(time.Hour), + //make the round not match + RoundID: 69, + PayloadType: 42, + Payload: []byte("blarg"), + } + + cmSerial, err := proto.Marshal(cm) + if err != nil { + t.Fatalf("Failed to marshal proto: %+v", err) + } + + sig := ed25519.Sign(priv, cmSerial) + ns := &mockNameService{validChMsg: true} + + um := &UserMessage{ + Message: cmSerial, + Signature: sig, + ECCPublicKey: pub, + } + + umSerial, err := proto.Marshal(um) + if err != nil { + t.Fatalf("Failed to marshal proto: %+v", err) + } + + //remove half the sized broadcast to make it malformed + umSerial = umSerial[:len(umSerial)/2] + + //build the listener + dummy := &triggerEventDummy{} + + al := userListener{ + chID: chID, + name: ns, + trigger: dummy.triggerEvent, + checkSent: func(messageID cryptoChannel.MessageID, r rounds.Round) bool { return false }, + } + + //call the listener + al.Listen(umSerial, receptionID.EphemeralIdentity{}, r) + + //check the results + if dummy.gotData { + t.Fatalf("Data returned after invalid listen") + } +} diff --git a/cmd/backup.go b/cmd/backup.go index a102a56570c4cce0256de12d2c29f4d2d8814a14..91cc194d71596ce22601dddb333fff6f24742bfd 100644 --- a/cmd/backup.go +++ b/cmd/backup.go @@ -1,7 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2022 Privategrity Corporation / -// / -// All rights reserved. / +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package cmd diff --git a/cmd/broadcast.go b/cmd/broadcast.go index f6487332c36daab637b48435717ef2b65255c9ee..7b0e7c9183ae1311bf7f2478640309723ca824e4 100644 --- a/cmd/broadcast.go +++ b/cmd/broadcast.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package cmd import ( @@ -13,7 +20,7 @@ import ( "gitlab.com/elixxir/client/cmix/identity/receptionID" "gitlab.com/elixxir/client/cmix/rounds" crypto "gitlab.com/elixxir/crypto/broadcast" - "gitlab.com/xx_network/crypto/signature/rsa" + rsa2 "gitlab.com/elixxir/crypto/rsa" "gitlab.com/xx_network/primitives/utils" "sync" ) @@ -49,7 +56,7 @@ var broadcastCmd = &cobra.Command{ waitUntilConnected(connected) /* Set up underlying crypto broadcast.Channel */ var channel *crypto.Channel - var pk *rsa.PrivateKey + var pk rsa2.PrivateKey keyPath := viper.GetString(broadcastKeyPathFlag) path, err := utils.ExpandPath(viper.GetString(broadcastChanPathFlag)) if utils.Exists(path) { @@ -74,23 +81,25 @@ var broadcastCmd = &cobra.Command{ if viper.GetBool(broadcastNewFlag) { // Create a new broadcast channel - channel, pk, err = crypto.NewChannel(name, desc, user.GetRng().GetStream()) + channel, pk, err = crypto.NewChannel(name, desc, user.GetCmix().GetMaxMessageLength(), user.GetRng().GetStream()) if err != nil { jww.FATAL.Panicf("Failed to create new channel: %+v", err) } if keyPath != "" { - err = utils.WriteFile(keyPath, rsa.CreatePrivateKeyPem(pk), os.ModePerm, os.ModeDir) + err = utils.WriteFile(keyPath, pk.MarshalPem(), os.ModePerm, os.ModeDir) if err != nil { jww.ERROR.Printf("Failed to write private key to path %s: %+v", path, err) } } else { - fmt.Printf("Private key generated for channel: %+v", rsa.CreatePrivateKeyPem(pk)) + fmt.Printf("Private key generated for channel: %+v", pk.MarshalPem()) } fmt.Printf("New broadcast channel generated") } else { + //fixme: redo channels, should be using pretty print over cli + // Read rest of info from config & build object manually - pubKeyBytes := []byte(viper.GetString(broadcastRsaPubFlag)) + /*pubKeyBytes := []byte(viper.GetString(broadcastRsaPubFlag)) pubKey, err := rsa.LoadPublicKeyFromPem(pubKeyBytes) if err != nil { jww.FATAL.Panicf("Failed to load public key at path: %+v", err) @@ -108,7 +117,7 @@ var broadcastCmd = &cobra.Command{ Description: desc, Salt: salt, RsaPubKey: pubKey, - } + }*/ } // Save channel to disk @@ -135,7 +144,8 @@ var broadcastCmd = &cobra.Command{ if err != nil { jww.ERROR.Printf("Failed to read private key from %s: %+v", ep, err) } - pk, err = rsa.LoadPrivateKeyFromPem(keyBytes) + + pk, err = rsa2.GetScheme().UnmarshalPrivateKeyPEM(keyBytes) if err != nil { jww.ERROR.Printf("Failed to load private key %+v: %+v", keyBytes, err) } @@ -151,7 +161,7 @@ var broadcastCmd = &cobra.Command{ asymmetric := viper.GetString(broadcastAsymmetricFlag) // Connect to broadcast channel - bcl, err := broadcast.NewBroadcastChannel(*channel, user.GetCmix(), user.GetRng()) + bcl, err := broadcast.NewBroadcastChannel(channel, user.GetCmix(), user.GetRng()) // Create & register symmetric receiver callback receiveChan := make(chan []byte, 100) @@ -172,7 +182,7 @@ var broadcastCmd = &cobra.Command{ jww.INFO.Printf("Received asymmetric message from %s over round %d", receptionID, round.ID) asymmetricReceiveChan <- payload } - err = bcl.RegisterListener(acb, broadcast.Asymmetric) + err = bcl.RegisterListener(acb, broadcast.RSAToPublic) if err != nil { jww.FATAL.Panicf("Failed to register asymmetric listener: %+v", err) } @@ -198,39 +208,30 @@ var broadcastCmd = &cobra.Command{ /* Send symmetric broadcast */ if symmetric != "" { - // Create properly sized broadcast message - broadcastMessage, err := broadcast.NewSizedBroadcast(bcl.MaxPayloadSize(), []byte(symmetric)) - if err != nil { - jww.FATAL.Panicf("Failed to create sized broadcast: %+v", err) - } - rid, eid, err := bcl.Broadcast(broadcastMessage, cmix.GetDefaultCMIXParams()) + rid, eid, err := bcl.Broadcast([]byte(symmetric), cmix.GetDefaultCMIXParams()) if err != nil { jww.ERROR.Printf("Failed to send symmetric broadcast message: %+v", err) retries++ continue } fmt.Printf("Sent symmetric broadcast message: %s", symmetric) - jww.INFO.Printf("Sent symmetric broadcast message to %s over round %d", eid, rid) + jww.INFO.Printf("Sent symmetric broadcast message to %s over round %d", eid, rid.ID) } /* Send asymmetric broadcast */ if asymmetric != "" { // Create properly sized broadcast message - broadcastMessage, err := broadcast.NewSizedBroadcast(bcl.MaxAsymmetricPayloadSize(), []byte(asymmetric)) - if err != nil { - jww.FATAL.Panicf("Failed to create sized broadcast: %+v", err) - } if pk == nil { jww.FATAL.Panicf("CANNOT SEND ASYMMETRIC BROADCAST WITHOUT PRIVATE KEY") } - rid, eid, err := bcl.BroadcastAsymmetric(pk, broadcastMessage, cmix.GetDefaultCMIXParams()) + rid, eid, err := bcl.BroadcastRSAtoPublic(pk, []byte(asymmetric), cmix.GetDefaultCMIXParams()) if err != nil { jww.ERROR.Printf("Failed to send asymmetric broadcast message: %+v", err) retries++ continue } fmt.Printf("Sent asymmetric broadcast message: %s", asymmetric) - jww.INFO.Printf("Sent asymmetric broadcast message to %s over round %d", eid, rid) + jww.INFO.Printf("Sent asymmetric broadcast message to %s over round %d", eid, rid.ID) } wg.Done() @@ -254,23 +255,13 @@ var broadcastCmd = &cobra.Command{ select { case receivedPayload := <-asymmetricReceiveChan: receivedCount++ - receivedBroadcast, err := broadcast.DecodeSizedBroadcast(receivedPayload) - if err != nil { - jww.ERROR.Printf("Failed to decode sized broadcast: %+v", err) - continue - } - fmt.Printf("Asymmetric broadcast message received: %s\n", string(receivedBroadcast)) + fmt.Printf("Asymmetric broadcast message received: %s\n", string(receivedPayload)) if receivedCount == expectedCnt { done = true } case receivedPayload := <-receiveChan: receivedCount++ - receivedBroadcast, err := broadcast.DecodeSizedBroadcast(receivedPayload) - if err != nil { - jww.ERROR.Printf("Failed to decode sized broadcast: %+v", err) - continue - } - fmt.Printf("Symmetric broadcast message received: %s\n", string(receivedBroadcast)) + fmt.Printf("Symmetric broadcast message received: %s\n", string(receivedPayload)) if receivedCount == expectedCnt { done = true } diff --git a/cmd/callbacks.go b/cmd/callbacks.go index df834ca48f115eeecb34350e5897caa8bb79fa0a..058c79dd0430b81243a4077f167694b37a909c3d 100644 --- a/cmd/callbacks.go +++ b/cmd/callbacks.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// // callbacks.go implements all of the required api callbacks for the cli package cmd @@ -27,6 +27,7 @@ import ( type authCallbacks struct { autoConfirm bool confCh chan *id.ID + reqCh chan *id.ID params xxdk.E2EParams } @@ -34,6 +35,7 @@ func makeAuthCallbacks(autoConfirm bool, params xxdk.E2EParams) *authCallbacks { return &authCallbacks{ autoConfirm: autoConfirm, confCh: make(chan *id.ID, 10), + reqCh: make(chan *id.ID, 10), params: params, } } @@ -44,7 +46,7 @@ func (a *authCallbacks) Request(requestor contact.Contact, msg := fmt.Sprintf("Authentication channel request from: %s\n", requestor.ID) jww.INFO.Printf(msg) - fmt.Printf(msg) + fmt.Print(msg) if a.autoConfirm { jww.INFO.Printf("Channel Request: %s", requestor.ID) @@ -55,8 +57,9 @@ func (a *authCallbacks) Request(requestor contact.Contact, } a.confCh <- requestor.ID + } else { + a.reqCh <- requestor.ID } - } func (a *authCallbacks) Confirm(requestor contact.Contact, @@ -72,7 +75,7 @@ func (a *authCallbacks) Reset(requestor contact.Contact, msg := fmt.Sprintf("Authentication channel reset from: %s\n", requestor.ID) jww.INFO.Printf(msg) - fmt.Printf(msg) + fmt.Print(msg) } func registerMessageListener(user *xxdk.E2e) chan receive.Message { diff --git a/cmd/connect.go b/cmd/connect.go index e8697dc60b8f0b5181df175274e12e881ce12b78..67059fc616f6f05658b180ef68142e08421abbdf 100644 --- a/cmd/connect.go +++ b/cmd/connect.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2022 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package cmd @@ -486,7 +486,7 @@ func miscConnectionFunctions(user *xxdk.E2e, conn connect.Connection) { conn.GetPartner().PartnerId()) payload := []byte(msgBody) for { - roundIDs, _, _, err := conn.SendE2E(catalog.XxMessage, payload, + sendReport, err := conn.SendE2E(catalog.XxMessage, payload, paramsE2E) if err != nil { jww.FATAL.Panicf("[CONN] Failed to send E2E message: %v", err) @@ -494,7 +494,7 @@ func miscConnectionFunctions(user *xxdk.E2e, conn connect.Connection) { // Verify message sends were successful when verifySendFlag is present if viper.GetBool(verifySendFlag) { - if !verifySendSuccess(user, paramsE2E, roundIDs, + if !verifySendSuccess(user, paramsE2E, sendReport.RoundList, conn.GetPartner().PartnerId(), payload) { continue } diff --git a/cmd/deployment.go b/cmd/deployment.go index f5350d516b2beff594fae0d0f70568c3318c2484..8e22630ee0d11da8737910859165683da0004e6c 100644 --- a/cmd/deployment.go +++ b/cmd/deployment.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2022 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package cmd diff --git a/cmd/dumpRounds.go b/cmd/dumpRounds.go index 88743972921640bc169fd7213122e07254af77b0..b7e8daf14ef5d7be1f67a7c8ab2f2d2e5f1f11e7 100644 --- a/cmd/dumpRounds.go +++ b/cmd/dumpRounds.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// // Package cmd initializes the CLI and config parsers as well as the logger. package cmd diff --git a/cmd/fileTransfer.go b/cmd/fileTransfer.go index 1b0e2fe5c79da6c8f5d8494e7b9d2b618a0f83d0..dbe42e5cdea1bfe94bed39090f08e37f297386c8 100644 --- a/cmd/fileTransfer.go +++ b/cmd/fileTransfer.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package cmd diff --git a/cmd/flags.go b/cmd/flags.go index 93b5d505d77f4846f80d1cda6b32bfa29a0ad3cf..5406561ba70cade7dd1cd260ee5d12c4d55b8283 100644 --- a/cmd/flags.go +++ b/cmd/flags.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2022 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package cmd @@ -80,7 +80,9 @@ const ( // Misc sendIdFlag = "sendid" profileCpuFlag = "profile-cpu" + profileMemFlag = "profile-mem" userIdPrefixFlag = "userid-prefix" + legacyFlag = "legacy" ///////////////// Broadcast subcommand flags ////////////////////////////// broadcastNameFlag = "name" diff --git a/cmd/getndf.go b/cmd/getndf.go index 8a107960597d96e163e2d5d0963b3c6291e51113..b94540bbdfb6b3ad6a74ff86d5ffa0f6384aad32 100644 --- a/cmd/getndf.go +++ b/cmd/getndf.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// // Package cmd initializes the CLI and config parsers as well as the logger. package cmd diff --git a/cmd/group.go b/cmd/group.go index 1c1b1f72159371aaf85851acb627184dfb2abcfd..0cf296b4cca2bdc8f2206eb40b4a15367df3a167 100644 --- a/cmd/group.go +++ b/cmd/group.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// // The group subcommand allows creation and sending messages to groups @@ -237,7 +237,7 @@ func sendGroup(groupIdString string, msg []byte, gm groupChat.GroupChat) { } jww.INFO.Printf("[GC] Sent to group %s on round %d at %s", - groupID, rid, timestamp) + groupID, rid.ID, timestamp) fmt.Printf("Sent message %q to group.\n", msg) } diff --git a/cmd/init.go b/cmd/init.go index e78ef22bb78387d64210e9d7365bc76fa765fd94..deef974a0a0a4a98069dfbd26a8a01fecb73437d 100644 --- a/cmd/init.go +++ b/cmd/init.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// // Package cmd initializes the CLI and config parsers as well as the logger. package cmd @@ -45,16 +45,27 @@ var initCmd = &cobra.Command{ jww.FATAL.Panicf("%+v", err) } - identity, err := xxdk.MakeReceptionIdentity(net) + // Generate identity + var identity xxdk.ReceptionIdentity + if viper.GetBool(legacyFlag) { + identity, err = xxdk.MakeLegacyReceptionIdentity(net) + } else { + identity, err = xxdk.MakeReceptionIdentity(net) + + } + + // Panic if conditional branch fails if err != nil { jww.FATAL.Panicf("%+v", err) } + // Store identity err = xxdk.StoreReceptionIdentity(identityStorageKey, identity, net) if err != nil { jww.FATAL.Panicf("%+v", err) } + // Write contact to file jww.INFO.Printf("User: %s", identity.ID) writeContact(identity.GetContact()) @@ -68,6 +79,11 @@ func init() { "Desired prefix of userID to brute force when running init command. Prepend (?i) for case-insensitive. Only Base64 characters are valid.") bindFlagHelper(userIdPrefixFlag, initCmd) + initCmd.Flags().BoolP(legacyFlag, "", false, + "Generates a legacy identity if set. "+ + "If this flag is absent, a standard identity will be generated.") + bindFlagHelper(legacyFlag, initCmd) + rootCmd.AddCommand(initCmd) } diff --git a/cmd/pickup.go b/cmd/pickup.go index ee4afbe53c923e9ec864e6a5b20536fe91b78a01..d1171e7a4e044bca1fc55450c8c304019c269ede 100644 --- a/cmd/pickup.go +++ b/cmd/pickup.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// // Package cmd initializes the CLI and config parsers as well as the logger. package cmd diff --git a/cmd/precan.go b/cmd/precan.go index 4f607c6b110321da890c6d23851f23b235cb452c..824b17d3a838caa05dfee5a794ee0d0bfa5a90ee 100644 --- a/cmd/precan.go +++ b/cmd/precan.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// // precan.go handles functions for precan users, which are not usable // unless you are on a localized test network. diff --git a/cmd/proto.go b/cmd/proto.go index 129ff1b0884eed4b4eacad6454f80c515eb2d53c..0203d1e5f49d81f71204c1ceafdb1c31900a38df 100644 --- a/cmd/proto.go +++ b/cmd/proto.go @@ -1,7 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2022 Privategrity Corporation / -// / -// All rights reserved. / +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package cmd diff --git a/cmd/root.go b/cmd/root.go index 837b68e1af7d13f8476844c3bb0f525be4bcbd63..81d197451d72494298a87613c71ec24a44c86d5f 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// // Package cmd initializes the CLI and config parsers as well as the logger. package cmd @@ -17,7 +17,11 @@ import ( "io/ioutil" "log" "os" - "runtime/pprof" + + cryptoE2e "gitlab.com/elixxir/crypto/e2e" + + "github.com/pkg/profile" + "strconv" "strings" "sync" @@ -58,19 +62,28 @@ var rootCmd = &cobra.Command{ Short: "Runs a client for cMix anonymous communication platform", Args: cobra.NoArgs, Run: func(cmd *cobra.Command, args []string) { - profileOut := viper.GetString(profileCpuFlag) - if profileOut != "" { - f, err := os.Create(profileOut) - if err != nil { - jww.FATAL.Panicf("%+v", err) - } - pprof.StartCPUProfile(f) + cpuProfileOut := viper.GetString(profileCpuFlag) + if cpuProfileOut != "" { + defer profile.Start(profile.CPUProfile, + profile.ProfilePath(cpuProfileOut), + profile.NoShutdownHook).Stop() + } + memProfileOut := viper.GetString(profileMemFlag) + if memProfileOut != "" { + defer profile.Start(profile.MemProfile, + profile.ProfilePath(memProfileOut), + profile.NoShutdownHook).Stop() } cmixParams, e2eParams := initParams() - authCbs := makeAuthCallbacks( - viper.GetBool(unsafeChannelCreationFlag), e2eParams) + autoConfirm := viper.GetBool(unsafeChannelCreationFlag) + acceptChannels := viper.GetBool(acceptChannelFlag) + if acceptChannels { + autoConfirm = false + } + + authCbs := makeAuthCallbacks(autoConfirm, e2eParams) user := initE2e(cmixParams, e2eParams, authCbs) jww.INFO.Printf("Client Initialized...") @@ -89,12 +102,14 @@ var rootCmd = &cobra.Command{ recipientContact = readContact(destFile) recipientID = recipientContact.ID } else if destId == "0" || sendId == destId { - jww.INFO.Printf("Sending message to self") + jww.INFO.Printf("Sending message to self, " + + "this will timeout unless authrequest is sent") recipientID = receptionIdentity.ID recipientContact = receptionIdentity.GetContact() } else { recipientID = parseRecipient(destId) - jww.INFO.Printf("destId: %v\nrecipientId: %v", destId, recipientID) + jww.INFO.Printf("destId: %v\nrecipientId: %v", destId, + recipientID) } isPrecanPartner := isPrecanID(recipientID) @@ -144,11 +159,42 @@ var rootCmd = &cobra.Command{ // Send Messages msgBody := viper.GetString(messageFlag) + hasMsgs := true + if msgBody == "" { + hasMsgs = false + } time.Sleep(10 * time.Second) // Accept auth request for this recipient + authSecs := viper.GetUint(authTimeoutFlag) authConfirmed := false - if viper.GetBool(acceptChannelFlag) { + jww.INFO.Printf("Preexisting E2e partners: %+v", user.GetE2E().GetAllPartnerIDs()) + if user.GetE2E().HasAuthenticatedChannel(recipientID) { + jww.INFO.Printf("Authenticated channel already in "+ + "place for %s", recipientID) + authConfirmed = true + } else { + jww.INFO.Printf("No authenticated channel in "+ + "place for %s", recipientID) + } + + if acceptChannels && !authConfirmed { + for reqDone := false; !reqDone; { + select { + case reqID := <-authCbs.reqCh: + if recipientID.Cmp(reqID) { + reqDone = true + } else { + fmt.Printf( + "unexpected request:"+ + " %s", reqID) + } + case <-time.After(time.Duration(authSecs) * + time.Second): + fmt.Print("timed out on auth request") + reqDone = true + } + } // Verify that the confirmation message makes it to the // original sender if viper.GetBool(verifySendFlag) { @@ -164,16 +210,6 @@ var rootCmd = &cobra.Command{ authConfirmed = true } - jww.INFO.Printf("Preexisting E2e partners: %+v", user.GetE2E().GetAllPartnerIDs()) - if user.GetE2E().HasAuthenticatedChannel(recipientID) { - jww.INFO.Printf("Authenticated channel already in "+ - "place for %s", recipientID) - authConfirmed = true - } else { - jww.INFO.Printf("No authenticated channel in "+ - "place for %s", recipientID) - } - // Send unsafe messages or not? unsafe := viper.GetBool(unsafeFlag) sendAuthReq := viper.GetBool(sendAuthRequestFlag) @@ -193,7 +229,7 @@ var rootCmd = &cobra.Command{ authConfirmed = false } - if !unsafe && !authConfirmed { + if !unsafe && !authConfirmed && hasMsgs { // Signal for authConfirm callback in a separate thread go func() { for { @@ -209,16 +245,15 @@ var rootCmd = &cobra.Command{ scnt := uint(0) // Wait until authConfirmed - waitSecs := viper.GetUint(authTimeoutFlag) - for !authConfirmed && scnt < waitSecs { + for !authConfirmed && scnt < authSecs { time.Sleep(1 * time.Second) scnt++ } - if scnt == waitSecs { + if scnt == authSecs { jww.FATAL.Panicf("Could not confirm "+ "authentication channel for %s, "+ "waited %d seconds.", recipientID, - waitSecs) + authSecs) } jww.INFO.Printf("Authentication channel confirmation"+ " took %d seconds", scnt) @@ -271,6 +306,13 @@ var rootCmd = &cobra.Command{ wg := &sync.WaitGroup{} sendCnt := int(viper.GetUint(sendCountFlag)) + if !hasMsgs && sendCnt != 0 { + msg := "No message to send, please set your message" + + "or set sendCount to 0 to suppress this warning" + jww.WARN.Printf(msg) + fmt.Print(msg) + sendCnt = 0 + } wg.Add(sendCnt) go func() { sendDelay := time.Duration(viper.GetUint(sendDelayFlag)) @@ -288,8 +330,10 @@ var rootCmd = &cobra.Command{ e2eParams.Base) } else { e2eParams.Base.DebugTag = "cmd.E2E" - roundIDs, _, _, err = user.GetE2E().SendE2E(mt, + var sendReport cryptoE2e.SendReport + sendReport, err = user.GetE2E().SendE2E(mt, recipient, payload, e2eParams.Base) + roundIDs = sendReport.RoundList } if err != nil { jww.FATAL.Panicf("%+v", err) @@ -382,9 +426,6 @@ var rootCmd = &cobra.Command{ "Failed to cleanly close threads: %+v\n", err) } - if profileOut != "" { - pprof.StopCPUProfile() - } jww.INFO.Printf("Client exiting!") }, } @@ -550,7 +591,7 @@ func addAuthenticatedChannel(user *xxdk.E2e, recipientID *id.ID, msg := fmt.Sprintf("Adding authenticated channel for: %s\n", recipientID) jww.INFO.Printf(msg) - fmt.Printf(msg) + fmt.Print(msg) recipientContact := recipient @@ -630,14 +671,8 @@ func acceptChannelVerified(user *xxdk.E2e, recipientID *id.ID, rid := acceptChannel(user, recipientID) // Monitor rounds for results - err := user.GetCmix().GetRoundResults(roundTimeout, + user.GetCmix().GetRoundResults(roundTimeout, makeVerifySendsCallback(retryChan, done), rid) - if err != nil { - jww.DEBUG.Printf("Could not verify "+ - "confirmation message for relationship with %s were sent "+ - "successfully, resending messages...", recipientID) - continue - } select { case <-retryChan: @@ -671,14 +706,9 @@ func requestChannelVerified(user *xxdk.E2e, } // Monitor rounds for results - err = user.GetCmix().GetRoundResults(roundTimeout, + user.GetCmix().GetRoundResults(roundTimeout, makeVerifySendsCallback(retryChan, done), rid) - if err != nil { - jww.DEBUG.Printf("Could not verify auth request was sent " + - "successfully, resending...") - continue - } select { case <-retryChan: @@ -710,14 +740,9 @@ func resetChannelVerified(user *xxdk.E2e, recipientContact contact.Contact, } // Monitor rounds for results - err = user.GetCmix().GetRoundResults(roundTimeout, + user.GetCmix().GetRoundResults(roundTimeout, makeVerifySendsCallback(retryChan, done), rid) - if err != nil { - jww.DEBUG.Printf("Could not verify auth request was sent " + - "successfully, resending...") - continue - } select { case <-retryChan: @@ -1101,6 +1126,10 @@ func init() { "Enable cpu profiling to this file") viper.BindPFlag(profileCpuFlag, rootCmd.Flags().Lookup(profileCpuFlag)) + rootCmd.Flags().String(profileMemFlag, "", + "Enable memory profiling to this file") + viper.BindPFlag(profileMemFlag, rootCmd.Flags().Lookup(profileMemFlag)) + // Proto user flags rootCmd.Flags().String(protoUserPathFlag, "", "Path to proto user JSON file containing cryptographic primitives "+ diff --git a/cmd/single.go b/cmd/single.go index 9493840752aa2e9fc97f8fb416d189c43d72e8c9..a8d45e57bb143497ff179d9d9d78f167e7f7fcc4 100644 --- a/cmd/single.go +++ b/cmd/single.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// // Package cmd initializes the CLI and config parsers as well as the logger. package cmd diff --git a/cmd/ud.go b/cmd/ud.go index 73a47f02d60e32f588fa1e0f24395a082c23d689..2877615046282534aa506b569c5ea5cc9de066ce 100644 --- a/cmd/ud.go +++ b/cmd/ud.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// // Package cmd initializes the CLI and config parsers as well as the logger. package cmd @@ -11,7 +11,6 @@ package cmd import ( "fmt" "gitlab.com/elixxir/client/xxdk" - "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/xx_network/primitives/id" "time" @@ -252,8 +251,7 @@ var udCmd = &cobra.Command{ // to contact UD. func getUdContactInfo(user *xxdk.E2e) (cert, contactFile []byte, address string, err error) { // Retrieve address - address = string([]byte(user.GetCmix().GetInstance().GetPartialNdf(). - Get().UDB.Address)) + address = user.GetCmix().GetInstance().GetPartialNdf().Get().UDB.Address // Retrieve certificate cert = []byte(user.GetCmix().GetInstance().GetPartialNdf().Get().UDB.Cert) @@ -267,7 +265,7 @@ func getUdContactInfo(user *xxdk.E2e) (cert, contactFile []byte, address string, // Retrieve DH Pub Key udDhPubKeyData := user.GetCmix().GetInstance().GetPartialNdf().Get().UDB.DhPubKey - var udDhPubKey *cyclic.Int + udDhPubKey := user.GetE2E().GetGroup().NewInt(1) err = udDhPubKey.UnmarshalJSON(udDhPubKeyData) if err != nil { return nil, nil, "", err diff --git a/cmd/utils.go b/cmd/utils.go index 80c9471f4b2124ab2743cf11b72da0d6e41d57e5..ad6de14de40c1b265dca23bb9b996c0e8f4b5e9d 100644 --- a/cmd/utils.go +++ b/cmd/utils.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package cmd import ( @@ -46,13 +53,8 @@ func verifySendSuccess(user *xxdk.E2e, paramsE2E e2e.Params, } // Monitor rounds for results - err := user.GetCmix().GetRoundResults( + user.GetCmix().GetRoundResults( paramsE2E.CMIXParams.Timeout, f, roundIDs...) - if err != nil { - jww.DEBUG.Printf("Could not verify messages were sent " + - "successfully, resending messages...") - return false - } select { case <-retryChan: diff --git a/cmd/version.go b/cmd/version.go index 41055fef35186085ee0747b89bc17332b13a95df..328c9cb0e5bd41b410b01bf498bf0f59997e041c 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// // Handles command-line version functionality @@ -21,7 +21,7 @@ import ( const currentVersion = "4.2.0" func Version() string { - out := fmt.Sprintf("Elixxir Cmix v%s -- %s\n\n", xxdk.SEMVER, + out := fmt.Sprintf("Elixxir Client v%s -- %s\n\n", xxdk.SEMVER, xxdk.GITVERSION) out += fmt.Sprintf("Dependencies:\n\n%s\n", xxdk.DEPENDENCIES) return out diff --git a/cmix/address/addressSpace.go b/cmix/address/addressSpace.go index be6cd94abdfc1cabc9bc58ede4516dbe6a773f88..500797fa0a69ca58c10dc11973d539567fe092c8 100644 --- a/cmix/address/addressSpace.go +++ b/cmix/address/addressSpace.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package address import ( diff --git a/cmix/address/addressSpace_test.go b/cmix/address/addressSpace_test.go index 62b23793efe9dff74f5e6297d0d529d9da68bf29..aed3e9f9c950e1cc7da2039638745e639f72ee73 100644 --- a/cmix/address/addressSpace_test.go +++ b/cmix/address/addressSpace_test.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package address import ( diff --git a/cmix/check.go b/cmix/check.go index 899fe10db2a7420f493bf70e23d12065245ffd16..ed010a7625cafae25ed8bc7f87520529099b2ed1 100644 --- a/cmix/check.go +++ b/cmix/check.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package cmix import ( diff --git a/cmix/check_test.go b/cmix/check_test.go index 5ab2aaf943aac5645d224e07d2e7bca3620caf21..e828e4c1d64a981b5d878ff98b267c050f14829f 100644 --- a/cmix/check_test.go +++ b/cmix/check_test.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package cmix import ( diff --git a/cmix/client.go b/cmix/client.go index d164b4d2a60620176fe7fee12c5a26e95e351c99..71b2c3c206431c3c98eaac08098a36a444d30db0 100644 --- a/cmix/client.go +++ b/cmix/client.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package cmix @@ -188,14 +188,14 @@ func (c *client) initialize(ndf *ndf.NetworkDefinition) error { // Set up critical message tracking (sendCmix only) critSender := func(msg format.Message, recipient *id.ID, params CMIXParams, - ) (id.Round, ephemeral.Id, error) { + ) (rounds.Round, ephemeral.Id, error) { compiler := func(round id.Round) (format.Message, error) { return msg, nil } - rid, eid, _, sendErr := sendCmixHelper(c.Sender, compiler, recipient, params, c.instance, + r, eid, _, sendErr := sendCmixHelper(c.Sender, compiler, recipient, params, c.instance, c.session.GetCmixGroup(), c.Registrar, c.rng, c.events, c.session.GetTransmissionID(), c.comms) - return rid, eid, sendErr + return r, eid, sendErr } @@ -251,6 +251,9 @@ func (c *client) Follow(report ClientErrorReport) (stoppable.Stoppable, error) { // Start the processes for the identity handler multi.Add(c.Tracker.StartProcesses()) + //Start the critical processing thread + multi.Add(c.crit.startProcessies()) + return multi, nil } diff --git a/cmix/cmixMessageBuffer.go b/cmix/cmixMessageBuffer.go index 54ba624ab9a203559de9bfcb6340adf1bddec8a6..0b4ac483889a938cee6335a888e3a122dd1fe4bb 100644 --- a/cmix/cmixMessageBuffer.go +++ b/cmix/cmixMessageBuffer.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package cmix @@ -52,7 +52,7 @@ func (cmh *cmixMessageHandler) SaveMessage( } // Save versioned object - return kv.Set(key, currentCmixMessageVersion, &obj) + return kv.Set(key, &obj) } // LoadMessage returns the message with the specified key from the key value diff --git a/cmix/cmixMessageBuffer_test.go b/cmix/cmixMessageBuffer_test.go index 1a9189a689726d2a4eec07a1d629d622e66b4d10..1318b3544c7fb393c23cac8593106649cccc111b 100644 --- a/cmix/cmixMessageBuffer_test.go +++ b/cmix/cmixMessageBuffer_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package cmix diff --git a/cmix/critical.go b/cmix/critical.go index 03ebfc7b56429b0fd0e8f588fa5ca2fe2e809491..6e9dd64e5a30d95a0933818c9b79e763ec67fe05 100644 --- a/cmix/critical.go +++ b/cmix/critical.go @@ -1,6 +1,16 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package cmix import ( + "gitlab.com/elixxir/client/cmix/rounds" + "time" + jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/cmix/health" "gitlab.com/elixxir/client/stoppable" @@ -10,7 +20,6 @@ import ( "gitlab.com/elixxir/primitives/states" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/id/ephemeral" - "time" ) const criticalRawMessagesKey = "RawCriticalMessages" @@ -27,7 +36,7 @@ type roundEventRegistrar interface { // anonymous function to include the structures from client that critical is // not aware of. type criticalSender func(msg format.Message, recipient *id.ID, - params CMIXParams) (id.Round, ephemeral.Id, error) + params CMIXParams) (rounds.Round, ephemeral.Id, error) // critical is a structure that allows the auto resending of messages that must // be received. @@ -58,6 +67,12 @@ func newCritical(kv *versioned.KV, hm health.Monitor, return c } +func (c *critical) startProcessies() *stoppable.Single { + stop := stoppable.NewSingle("criticalStopper") + go c.runCriticalMessages(stop) + return stop +} + func (c *critical) runCriticalMessages(stop *stoppable.Single) { for { select { @@ -120,7 +135,7 @@ func (c *critical) evaluate(stop *stoppable.Single) { round, _, err := c.send(msg, recipient, params) // Pass to the handler - c.handle(msg, recipient, round, err) + c.handle(msg, recipient, round.ID, err) }(msg, localRid, params) } diff --git a/cmix/critical_test.go b/cmix/critical_test.go index 4126c57714955cbf446c4fab02c532eb0b159fd7..4b09fff7e44c281873b774833999514999c5e5f0 100644 --- a/cmix/critical_test.go +++ b/cmix/critical_test.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package cmix import ( diff --git a/cmix/follow.go b/cmix/follow.go index 29eb9035a252a00b3af8cc80a0768b54d8e528b1..4d8688369fc250805f4e35b47aa21179e9177ed6 100644 --- a/cmix/follow.go +++ b/cmix/follow.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package cmix @@ -26,6 +26,8 @@ import ( "bytes" "encoding/binary" "fmt" + "gitlab.com/elixxir/client/cmix/identity/receptionID" + "sync" "sync/atomic" "time" @@ -68,7 +70,10 @@ func (c *client) followNetwork(report ClientErrorReport, TrackTicker := time.NewTicker(debugTrackPeriod) rng := c.rng.GetStream() + // abandon tracks rounds which data was not found out about in + // the verbose rounds debugging mode abandon := func(round id.Round) { return } + dummyAbandon := func(round id.Round) { return } if c.verboseRounds != nil { abandon = func(round id.Round) { c.verboseRounds.denote(round, Abandoned) @@ -82,7 +87,50 @@ func (c *client) followNetwork(report ClientErrorReport, stop.ToStopped() return case <-ticker.C: - c.follow(report, rng, c.comms, stop, abandon) + + operator := func(toTrack []receptionID.IdentityUse) error { + + // set up tracking tools + wg := &sync.WaitGroup{} + wg.Add(len(toTrack)) + + // trigger the first separately because it will get network state + // updates + go func() { + c.follow(toTrack[0], report, rng, c.comms, stop, abandon, + true) + wg.Done() + }() + + //trigger all others without getting network state updates + for i := 1; i < len(toTrack); i++ { + go func(index int) { + c.follow(toTrack[index], report, rng, c.comms, stop, + dummyAbandon, false) + wg.Done() + }(i) + } + + //wait for all to complete + wg.Wait() + return nil + } + + // get the list of identities to track + stream := c.rng.GetStream() + err := c.Tracker.ForEach( + int(c.param.MaxParallelIdentityTracks), + stream, + c.Space.GetAddressSpaceWithoutWait(), + operator) + stream.Close() + + if err != nil { + jww.ERROR.Printf("failed to operate on identities to "+ + "track: %s", err) + continue + } + case <-TrackTicker.C: numPolls := atomic.SwapUint64(c.tracker, 0) if c.numLatencies != 0 { @@ -108,18 +156,10 @@ func (c *client) followNetwork(report ClientErrorReport, } } -// follow executes each iteration of the follower. -func (c *client) follow(report ClientErrorReport, rng csprng.Source, - comms followNetworkComms, stop *stoppable.Single, - abandon func(round id.Round)) { - - // Get the identity we will poll for - identity, err := c.GetEphemeralIdentity( - rng, c.Space.GetAddressSpaceWithoutWait()) - if err != nil { - jww.FATAL.Panicf( - "Failed to get an identity, this should be impossible: %+v", err) - } +// follow executes an iteration of the follower for a specific identity +func (c *client) follow(identity receptionID.IdentityUse, + report ClientErrorReport, rng csprng.Source, comms followNetworkComms, + stop *stoppable.Single, abandon func(round id.Round), getUpdates bool) { // While polling with a fake identity, it is necessary to have populated // earliestRound data. However, as with fake identities, we want the values @@ -147,6 +187,7 @@ func (c *client) follow(report ClientErrorReport, rng csprng.Source, ClientVersion: []byte(version.String()), FastPolling: c.param.FastPolling, LastRound: uint64(identity.ER.Get()), + DisableUpdates: !getUpdates, } result, err := c.SendToAny(func(host *connect.Host) (interface{}, error) { @@ -299,6 +340,7 @@ func (c *client) follow(report ClientErrorReport, rng csprng.Source, if !hasMessage && c.verboseRounds != nil { c.verboseRounds.denote(rid, RoundState(NoMessageAvailable)) } + //jww.INFO.Printf("[LOOKUP] round %d checked for %d, has message: %s", rid, identity.EphId.Int64(), hasMessage) return hasMessage } @@ -349,10 +391,10 @@ func (c *client) follow(report ClientErrorReport, rng csprng.Source, gwRoundsState.RangeUnchecked( updatedEarliestRound, c.param.KnownRoundsThreshold, roundChecker) - jww.DEBUG.Printf("Processed RangeUnchecked, Oldest: %d, "+ + jww.DEBUG.Printf("Processed RangeUnchecked for %d, Oldest: %d, "+ "firstUnchecked: %d, last Checked: %d, threshold: %d, "+ "NewEarliestRemaining: %d, NumWithMessages: %d, NumUnknown: %d", - updatedEarliestRound, gwRoundsState.GetFirstUnchecked(), + identity.EphId.Int64(), updatedEarliestRound, gwRoundsState.GetFirstUnchecked(), gwRoundsState.GetLastChecked(), c.param.KnownRoundsThreshold, earliestRemaining, len(roundsWithMessages), len(roundsUnknown)) diff --git a/cmix/follow_test.go b/cmix/follow_test.go index ed81b15896d3d8c32b3aca6714550af48b7537f7..7b887cc1e874f49c2ae0226cfa28a4736956e689 100644 --- a/cmix/follow_test.go +++ b/cmix/follow_test.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package cmix //func TestClient_Follow(t *testing.T) { diff --git a/cmix/gateway/hostPool.go b/cmix/gateway/hostPool.go index c90a825fafa8b9b4a9fee9988fe5ab94d1b347dc..c37dbdf2fdcda4b8f9f8fac7f9339640809e40fe 100644 --- a/cmix/gateway/hostPool.go +++ b/cmix/gateway/hostPool.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// // Package gateway Handles functionality related to providing Gateway // connect.Host objects for message sending to the rest of the client @@ -247,7 +247,7 @@ func newHostPool(poolParams PoolParams, rng *fastRNG.StreamGenerator, } } else { jww.WARN.Printf( - "Building new HostPool because no HostList stored: %+v", err) + "Building new HostPool because no HostList stored: %s", err.Error()) } // Build the initial HostPool and return diff --git a/cmix/gateway/hostpool_test.go b/cmix/gateway/hostpool_test.go index f5a49cc4e9c0d052ac704d901976da4635069c3c..8f35e91f41d508806469a5f4f274f61d1a0c2adf 100644 --- a/cmix/gateway/hostpool_test.go +++ b/cmix/gateway/hostpool_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package gateway diff --git a/cmix/gateway/sender.go b/cmix/gateway/sender.go index 1ccff1fb8b0c18550cfad2dd7db48d04aaae89d0..98dffa6a2de35328d4b42f27d920144663de4095 100644 --- a/cmix/gateway/sender.go +++ b/cmix/gateway/sender.go @@ -1,7 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2021 Privategrity Corporation / -// / -// All rights reserved. / +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// // Contains gateway message sending wrappers diff --git a/cmix/gateway/sender_test.go b/cmix/gateway/sender_test.go index b6de48005f188dadc6e1f4053d80f84c53af291d..b891940d13983a8dc314757c11ecc6580d520e63 100644 --- a/cmix/gateway/sender_test.go +++ b/cmix/gateway/sender_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package gateway diff --git a/cmix/gateway/storeHostList.go b/cmix/gateway/storeHostList.go index d71d17b53e235ad5eb02860d8951794304ed59cc..d227111f7319a67963bbc14d511f25d6b228b025 100644 --- a/cmix/gateway/storeHostList.go +++ b/cmix/gateway/storeHostList.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package gateway @@ -36,7 +36,7 @@ func saveHostList(kv *versioned.KV, list []*id.ID) error { Timestamp: netTime.Now(), } - return kv.Set(hostListKey, hostListVersion, obj) + return kv.Set(hostListKey, obj) } // getHostList returns the host list from storage. diff --git a/cmix/gateway/storeHostList_test.go b/cmix/gateway/storeHostList_test.go index 6dddef1f25f0737cda09b8b53802d4431806bd0b..54757ab5cbeaac6a680274729b32529e7e6c3f7a 100644 --- a/cmix/gateway/storeHostList_test.go +++ b/cmix/gateway/storeHostList_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package gateway diff --git a/cmix/gateway/utils_test.go b/cmix/gateway/utils_test.go index d9dc77cf5674127e3e30a3ecd0896dcdba16816f..7846da5d89547e66ccd8996e24c3d3fe4bb0c7e0 100644 --- a/cmix/gateway/utils_test.go +++ b/cmix/gateway/utils_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package gateway diff --git a/cmix/health/tracker.go b/cmix/health/tracker.go index 3f2a932e9a1b82efdeff5f8ca2bcd1c1c5e3f8fd..537ec320cae8341b341653e4af07c93fc37c50ce 100644 --- a/cmix/health/tracker.go +++ b/cmix/health/tracker.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// // Contains functionality related to the event model driven network health // tracker. diff --git a/cmix/health/tracker_test.go b/cmix/health/tracker_test.go index 1c2a44aa71d4cc6a4ae30d15575c83113601edcf..1f74c7b4688037e90f9c9cf5d0147e1990a7e35a 100644 --- a/cmix/health/tracker_test.go +++ b/cmix/health/tracker_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package health diff --git a/cmix/identity/receptionID/IdentityUse.go b/cmix/identity/receptionID/IdentityUse.go index 7255a65faafb0d73a4d4d7f44e80e92173d34894..de9ade02301a5a9a84c7363e3582b4228a70ae62 100644 --- a/cmix/identity/receptionID/IdentityUse.go +++ b/cmix/identity/receptionID/IdentityUse.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package receptionID import ( diff --git a/cmix/identity/receptionID/fake.go b/cmix/identity/receptionID/fake.go index 5462690d531fdeeee1b0c2a9e7d60981af8f95aa..45dd72e5f29e80709a7acd41e9cadfd2d78a4ae4 100644 --- a/cmix/identity/receptionID/fake.go +++ b/cmix/identity/receptionID/fake.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package receptionID import ( diff --git a/cmix/identity/receptionID/fake_test.go b/cmix/identity/receptionID/fake_test.go index 27134207200732d3cdecb943f29a1ecb259a3b42..14940f7f60c8e057273f2f2559e346505fe89690 100644 --- a/cmix/identity/receptionID/fake_test.go +++ b/cmix/identity/receptionID/fake_test.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package receptionID import ( diff --git a/cmix/identity/receptionID/identity.go b/cmix/identity/receptionID/identity.go index 96767b8a7a7dfa8813e2b50298f00c04b98beb66..bba7823789480636710b520d79d4deeadbfa1dbd 100644 --- a/cmix/identity/receptionID/identity.go +++ b/cmix/identity/receptionID/identity.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package receptionID import ( @@ -73,7 +80,7 @@ func (i Identity) store(kv *versioned.KV) error { } // Store the data - err = kv.Set(identityStorageKey, identityStorageVersion, obj) + err = kv.Set(identityStorageKey, obj) if err != nil { return errors.WithMessage(err, "Failed to store Identity") } diff --git a/cmix/identity/receptionID/identity_test.go b/cmix/identity/receptionID/identity_test.go index d1f26598684daad8550cf5476ba04b163023f956..c893a7dbd87fd3d559801f8be7007cf4535fcc6a 100644 --- a/cmix/identity/receptionID/identity_test.go +++ b/cmix/identity/receptionID/identity_test.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package receptionID import ( diff --git a/cmix/identity/receptionID/registration.go b/cmix/identity/receptionID/registration.go index 2655eee3a864558365e1cf2e1d8c6ea81ce2c4a0..9f25f54097a72448825e44452f3411f829237844 100644 --- a/cmix/identity/receptionID/registration.go +++ b/cmix/identity/receptionID/registration.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package receptionID import ( diff --git a/cmix/identity/receptionID/registration_test.go b/cmix/identity/receptionID/registration_test.go index cd8d608ac725c1750c99b723c3528f46719020fe..7206df57b4788dee47712662e4d373e33591df0f 100644 --- a/cmix/identity/receptionID/registration_test.go +++ b/cmix/identity/receptionID/registration_test.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package receptionID import ( diff --git a/cmix/identity/receptionID/store.go b/cmix/identity/receptionID/store.go index e13eddfac252e4fd9daf2032f920f0e110a75dfe..967c22e034270d726b2c4e216d460dc767e0dbd2 100644 --- a/cmix/identity/receptionID/store.go +++ b/cmix/identity/receptionID/store.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package receptionID import ( @@ -6,6 +13,7 @@ import ( jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/xx_network/crypto/large" + "gitlab.com/xx_network/crypto/shuffle" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/id/ephemeral" "gitlab.com/xx_network/primitives/netTime" @@ -21,6 +29,8 @@ const ( receptionStoreStorageVersion = 0 ) +var InvalidRequestedNumIdentities = errors.New("cannot get less than one identity(s)") + type Store struct { // Identities which are being actively checked active []*registration @@ -54,7 +64,7 @@ func NewOrLoadStore(kv *versioned.KV) *Store { s, err := loadStore(kv) if err != nil { jww.WARN.Printf( - "ReceptionID store not found, creating a new one: %+v", err) + "ReceptionID store not found, creating a new one: %s", err.Error()) s = &Store{ active: []*registration{}, @@ -122,7 +132,7 @@ func (s *Store) save() error { Data: data, } - err = s.kv.Set(receptionStoreStorageKey, receptionStoreStorageVersion, obj) + err = s.kv.Set(receptionStoreStorageKey, obj) if err != nil { return errors.WithMessage(err, "Failed to store reception store") } @@ -150,7 +160,15 @@ func (s *Store) makeStoredReferences() []storedReference { return identities[:i] } -func (s *Store) GetIdentity(rng io.Reader, addressSize uint8) (IdentityUse, error) { +// ForEach operates on 'n' identities randomly in a random order. +// if no identities exist, it will operate on a single fake identity +func (s *Store) ForEach(n int, rng io.Reader, + addressSize uint8, operate func([]IdentityUse) error) error { + + if n < 1 { + return InvalidRequestedNumIdentities + } + s.mux.Lock() defer s.mux.Unlock() @@ -159,26 +177,29 @@ func (s *Store) GetIdentity(rng io.Reader, addressSize uint8) (IdentityUse, erro // Remove any now expired identities s.prune(now) - var identity IdentityUse - var err error + var identities []IdentityUse // If the list is empty, then return a randomly generated identity to poll // with so that we can continue tracking the network and to further // obfuscate network identities. if len(s.active) == 0 { - identity, err = generateFakeIdentity(rng, addressSize, now) + fakeIdentity, err := generateFakeIdentity(rng, addressSize, now) if err != nil { jww.FATAL.Panicf( "Failed to generate a new ID when none available: %+v", err) } + identities = append(identities, fakeIdentity) + // otherwise, select identities to return using a fisher-yates } else { - identity, err = s.selectIdentity(rng, now) + var err error + identities, err = s.selectIdentities(n, rng, now) if err != nil { - jww.FATAL.Panicf("Failed to select an ID: %+v", err) + jww.FATAL.Panicf("Failed to select a list of IDs: %+v", err) } } - return identity, nil + // do the passed operation on all identities + return operate(identities) } func (s *Store) AddIdentity(identity Identity) error { @@ -221,10 +242,11 @@ func (s *Store) RemoveIdentity(ephID ephemeral.Id) { s.mux.Lock() defer s.mux.Unlock() - for i, inQuestion := range s.active { + for i := 0; i < len(s.active); i++ { + inQuestion := s.active[i] if inQuestion.EphId == ephID { s.active = append(s.active[:i], s.active[i+1:]...) - + delete(s.present, makeIdHash(inQuestion.EphId, inQuestion.Source)) err := inQuestion.Delete() if err != nil { jww.FATAL.Panicf("Failed to delete identity: %+v", err) @@ -237,6 +259,8 @@ func (s *Store) RemoveIdentity(ephID ephemeral.Id) { } } + i-- + return } } @@ -247,16 +271,20 @@ func (s *Store) RemoveIdentities(source *id.ID) { defer s.mux.Unlock() doSave := false - for i, inQuestion := range s.active { + for i := 0; i < len(s.active); i++ { + inQuestion := s.active[i] if inQuestion.Source.Cmp(source) { s.active = append(s.active[:i], s.active[i+1:]...) - + delete(s.present, makeIdHash(inQuestion.EphId, inQuestion.Source)) + jww.INFO.Printf("Removing Identity %s:%d from tracker", + inQuestion.Source, inQuestion.EphId.Int64()) err := inQuestion.Delete() if err != nil { jww.FATAL.Panicf("Failed to delete identity: %+v", err) } doSave = doSave || !inQuestion.Ephemeral + i-- } } if doSave { @@ -298,6 +326,7 @@ func (s *Store) prune(now time.Time) { pruned = append(pruned, inQuestion.EphId.Int64()) s.active = append(s.active[:i], s.active[i+1:]...) + delete(s.present, makeIdHash(inQuestion.EphId, inQuestion.Source)) i-- } @@ -313,6 +342,8 @@ func (s *Store) prune(now time.Time) { } } +// selectIdentity returns a random identity in an IdentityUse object and +// increments its usage if necessary func (s *Store) selectIdentity(rng io.Reader, now time.Time) (IdentityUse, error) { // Choose a member from the list var selected *registration @@ -320,7 +351,7 @@ func (s *Store) selectIdentity(rng io.Reader, now time.Time) (IdentityUse, error if len(s.active) == 1 { selected = s.active[0] } else { - seed := make([]byte, 32) + seed := make([]byte, 32) //use 256 bits of entropy for the seed if _, err := rng.Read(seed); err != nil { return IdentityUse{}, errors.WithMessage(err, "Failed to choose "+ "ID due to RNG failure") @@ -334,10 +365,6 @@ func (s *Store) selectIdentity(rng io.Reader, now time.Time) (IdentityUse, error selected = s.active[selectedNum.Uint64()] } - if now.After(selected.End) { - selected.ExtraChecks-- - } - jww.TRACE.Printf("Selected identity: EphId: %d ID: %s End: %s "+ "StartValid: %s EndValid: %s", selected.EphId.Int64(), selected.Source, @@ -345,11 +372,64 @@ func (s *Store) selectIdentity(rng io.Reader, now time.Time) (IdentityUse, error selected.StartValid.Format("01/02/06 03:04:05 pm"), selected.EndValid.Format("01/02/06 03:04:05 pm")) + return useIdentity(selected, now), nil +} + +// selectIdentities returns up to 'n' identities in an IdentityUse object +// selected via fisher-yates and increments their usage if necessary +func (s *Store) selectIdentities(n int, rng io.Reader, now time.Time) ([]IdentityUse, error) { + // Choose a member from the list + selected := make([]IdentityUse, 0, n) + + if len(s.active) == 1 { + selected = append(selected, useIdentity(s.active[0], now)) + } else { + + // make the seed + seed := make([]byte, 32) //use 256 bits of entropy for the seed + if _, err := rng.Read(seed); err != nil { + return nil, errors.WithMessage(err, "Failed to choose "+ + "ID due to RNG failure") + } + + // make the list to shuffle + registered := make([]*registration, 0, len(s.active)) + for i := 0; i < len(s.active); i++ { + registered = append(registered, s.active[i]) + } + + //shuffle the list via fisher-yates + registeredProxy := shuffle.SeededShuffle(len(s.active), seed) + + //convert the list to identity use + for i := 0; i < len(registered) && (i < n); i++ { + selected = append(selected, + useIdentity(registered[registeredProxy[i]], now)) + } + + } + + jww.TRACE.Printf("Selected %d identities, first identity: EphId: %d ID: %s End: %s "+ + "StartValid: %s EndValid: %s", len(selected), + selected[0].EphId.Int64(), selected[0].Source, + selected[0].End.Format("01/02/06 03:04:05 pm"), + selected[0].StartValid.Format("01/02/06 03:04:05 pm"), + selected[0].EndValid.Format("01/02/06 03:04:05 pm")) + + return selected, nil +} + +// useIdentity makes the public IdentityUse object from a private *registration +// and deals with denoting the usage in the *registration if nessessay +func useIdentity(selected *registration, now time.Time) IdentityUse { + if now.After(selected.End) { + selected.ExtraChecks-- + } return IdentityUse{ Identity: selected.Identity, Fake: false, UR: selected.UR, ER: selected.ER, CR: selected.CR, - }, nil + } } diff --git a/cmix/identity/receptionID/store/checkedRounds.go b/cmix/identity/receptionID/store/checkedRounds.go index 3ef3a61c07c131c5671fc0729e22df9f85715b49..b117f0e06a58664094f78a3bee3325c3a30f5239 100644 --- a/cmix/identity/receptionID/store/checkedRounds.go +++ b/cmix/identity/receptionID/store/checkedRounds.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package store import ( diff --git a/cmix/identity/receptionID/store/checkedRounds_test.go b/cmix/identity/receptionID/store/checkedRounds_test.go index 5ddc5984d10dab0502982d0a1c98761bc13801ce..1f9f623785c13167167b81655023152eb02b0870 100644 --- a/cmix/identity/receptionID/store/checkedRounds_test.go +++ b/cmix/identity/receptionID/store/checkedRounds_test.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package store import ( diff --git a/cmix/identity/receptionID/store/earliestRound.go b/cmix/identity/receptionID/store/earliestRound.go index fe1b60abd17932382d92f1df6d03ca480727d817..3d2ea3272b88bfe1764501897eb810c302f62ae5 100644 --- a/cmix/identity/receptionID/store/earliestRound.go +++ b/cmix/identity/receptionID/store/earliestRound.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package store import ( @@ -65,8 +72,7 @@ func (ur *EarliestRound) save() { Data: urStr, } - err = ur.kv.Set(earliestRoundStorageKey, - earliestRoundStorageVersion, obj) + err = ur.kv.Set(earliestRoundStorageKey, obj) if err != nil { jww.FATAL.Panicf("Failed to store the earliest round: %+v", err) } diff --git a/cmix/identity/receptionID/store/unknownRounds.go b/cmix/identity/receptionID/store/unknownRounds.go index b14c939abdd27e72a284bf37ba71e763b6bd0536..da9fead7e48c774c7a866626a2000e13e90a2aab 100644 --- a/cmix/identity/receptionID/store/unknownRounds.go +++ b/cmix/identity/receptionID/store/unknownRounds.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package store @@ -223,7 +223,7 @@ func (urs *UnknownRounds) save() error { } // Save to disk - return urs.kv.Set(unknownRoundsStorageKey, unknownRoundsStorageVersion, obj) + return urs.kv.Set(unknownRoundsStorageKey, obj) } func (urs *UnknownRounds) Delete() { diff --git a/cmix/identity/receptionID/store/unknownRounds_test.go b/cmix/identity/receptionID/store/unknownRounds_test.go index f8beea3a7adbdd8c6fc52514ffb6950280014982..ac0c85da6efdf74c847f87676c29eb645951487c 100644 --- a/cmix/identity/receptionID/store/unknownRounds_test.go +++ b/cmix/identity/receptionID/store/unknownRounds_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package store diff --git a/cmix/identity/receptionID/store_test.go b/cmix/identity/receptionID/store_test.go index 19a53f97b11a9e7abaef0ecf3c2c0c1698602105..5161469cfd7c044eddade131e8f76b90c6c30678 100644 --- a/cmix/identity/receptionID/store_test.go +++ b/cmix/identity/receptionID/store_test.go @@ -1,11 +1,21 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package receptionID import ( "bytes" + "encoding/binary" "encoding/json" "gitlab.com/elixxir/client/storage/versioned" + "gitlab.com/elixxir/crypto/hash" "gitlab.com/elixxir/ekv" "gitlab.com/xx_network/primitives/netTime" + "math" "math/rand" "reflect" "testing" @@ -141,27 +151,226 @@ func TestStore_makeStoredReferences(t *testing.T) { } } -func TestStore_GetIdentity(t *testing.T) { +func TestStore_GetIdentities(t *testing.T) { kv := versioned.NewKV(ekv.MakeMemstore()) s := NewOrLoadStore(kv) prng := rand.New(rand.NewSource(42)) - testID, err := generateFakeIdentity(prng, 15, netTime.Now()) + + numToTest := 100 + + idsGenerated := make(map[uint64]interface{}) + + for i := 0; i < numToTest; i++ { + testID, err := generateFakeIdentity(prng, 15, netTime.Now()) + if err != nil { + t.Fatalf("Failed to generate fake ID: %+v", err) + } + testID.Fake = false + if s.AddIdentity(testID.Identity) != nil { + t.Errorf("AddIdentity() produced an error: %+v", err) + } + + idsGenerated[getIDFp(testID.EphemeralIdentity)] = nil + + } + + //get one + var idu []IdentityUse + o := func(a []IdentityUse) error { + idu = a + return nil + } + err := s.ForEach(1, prng, 15, o) if err != nil { - t.Fatalf("Failed to generate fake ID: %+v", err) + t.Errorf("GetIdentity() produced an error: %+v", err) } - if s.AddIdentity(testID.Identity) != nil { - t.Errorf("AddIdentity() produced an error: %+v", err) + + if _, exists := idsGenerated[getIDFp(idu[0].EphemeralIdentity)]; !exists || + idu[0].Fake { + t.Errorf("An unknown or fake identity was returned") + } + + //get three + err = s.ForEach(3, prng, 15, o) + if err != nil { + t.Errorf("GetIdentity() produced an error: %+v", err) + } + + if len(idu) != 3 { + t.Errorf("the wrong number of identities was returned") + } + + for i := 0; i < len(idu); i++ { + if _, exists := idsGenerated[getIDFp(idu[i].EphemeralIdentity)]; !exists || + idu[i].Fake { + t.Errorf("An unknown or fake identity was returned") + } + } + + //get ten + err = s.ForEach(10, prng, 15, o) + if err != nil { + t.Errorf("GetIdentity() produced an error: %+v", err) + } + + if len(idu) != 10 { + t.Errorf("the wrong number of identities was returned") + } + + for i := 0; i < len(idu); i++ { + if _, exists := idsGenerated[getIDFp(idu[i].EphemeralIdentity)]; !exists || + idu[i].Fake { + t.Errorf("An unknown or fake identity was returned") + } + } + + //get fifty + err = s.ForEach(50, prng, 15, o) + if err != nil { + t.Errorf("GetIdentity() produced an error: %+v", err) + } + + if len(idu) != 50 { + t.Errorf("the wrong number of identities was returned") + } + + for i := 0; i < len(idu); i++ { + if _, exists := idsGenerated[getIDFp(idu[i].EphemeralIdentity)]; !exists || + idu[i].Fake { + t.Errorf("An unknown or fake identity was returned") + } + } + + //get 100 + err = s.ForEach(100, prng, 15, o) + if err != nil { + t.Errorf("GetIdentity() produced an error: %+v", err) + } + + if len(idu) != 100 { + t.Errorf("the wrong number of identities was returned") + } + + for i := 0; i < len(idu); i++ { + if _, exists := idsGenerated[getIDFp(idu[i].EphemeralIdentity)]; !exists || + idu[i].Fake { + t.Errorf("An unknown or fake identity was returned") + } + } + + //get 1000, should only return 100 + err = s.ForEach(1000, prng, 15, o) + if err != nil { + t.Errorf("GetIdentity() produced an error: %+v", err) + } + + if len(idu) != 100 { + t.Errorf("the wrong number of identities was returned") + } + + for i := 0; i < len(idu); i++ { + if _, exists := idsGenerated[getIDFp(idu[i].EphemeralIdentity)]; !exists || + idu[i].Fake { + t.Errorf("An unknown or fake identity was returned") + } } - idu, err := s.GetIdentity(prng, 15) + // get 100 a second time and make sure the order is not the same as a + // smoke test that the shuffle is working + var idu2 []IdentityUse + o2 := func(a []IdentityUse) error { + idu2 = a + return nil + } + + err = s.ForEach(1000, prng, 15, o2) if err != nil { t.Errorf("GetIdentity() produced an error: %+v", err) } - if !testID.Equal(idu.Identity) { - t.Errorf("GetIdentity() did not return the expected Identity."+ - "\nexpected: %s\nreceived: %s", testID, idu) + diferent := false + for i := 0; i < len(idu); i++ { + if !idu[i].Source.Cmp(idu2[i].Source) { + diferent = true + break + } + } + + if !diferent { + t.Errorf("The 2 100 shuffels retruned the same result, shuffling" + + " is likley not occuring") + } + +} + +func TestStore_GetIdentities_NoIdentities(t *testing.T) { + kv := versioned.NewKV(ekv.MakeMemstore()) + s := NewOrLoadStore(kv) + prng := rand.New(rand.NewSource(42)) + + var idu []IdentityUse + o := func(a []IdentityUse) error { + idu = a + return nil + } + + err := s.ForEach(5, prng, 15, o) + if err != nil { + t.Errorf("GetIdentities() produced an error: %+v", err) + } + + if len(idu) != 1 { + t.Errorf("GetIdenties() did not return only one identity " + + "when looking for a fake") + } + + if !idu[0].Fake { + t.Errorf("GetIdenties() did not return a fake identity " + + "when only one is avalible") + } +} + +func TestStore_GetIdentities_BadNum(t *testing.T) { + kv := versioned.NewKV(ekv.MakeMemstore()) + s := NewOrLoadStore(kv) + prng := rand.New(rand.NewSource(42)) + + o := func(a []IdentityUse) error { + return nil + } + + err := s.ForEach(0, prng, 15, o) + if err == nil { + t.Errorf("GetIdentities() shoud error with bad num value") + } + + err = s.ForEach(-1, prng, 15, o) + if err == nil { + t.Errorf("GetIdentities() shoud error with bad num value") + } + + err = s.ForEach(-100, prng, 15, o) + if err == nil { + t.Errorf("GetIdentities() shoud error with bad num value") } + + err = s.ForEach(-1000000, prng, 15, o) + if err == nil { + t.Errorf("GetIdentities() shoud error with bad num value") + } + + err = s.ForEach(math.MinInt64, prng, 15, o) + if err == nil { + t.Errorf("GetIdentities() shoud error with bad num value") + } +} + +func getIDFp(identity EphemeralIdentity) uint64 { + h, _ := hash.NewCMixHash() + h.Write(identity.EphId[:]) + h.Write(identity.Source.Bytes()) + r := h.Sum(nil) + return binary.BigEndian.Uint64(r) } func TestStore_AddIdentity(t *testing.T) { diff --git a/cmix/identity/tracker.go b/cmix/identity/tracker.go index 961aac77627f0f5ef15ed35b839c2c5eaafa9b4b..7ab08da034fbdd1dbbbfd35ff54b7fc72c273929 100644 --- a/cmix/identity/tracker.go +++ b/cmix/identity/tracker.go @@ -1,16 +1,15 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package identity import ( "encoding/json" "io" - "io/fs" "sync" "time" @@ -50,12 +49,13 @@ type Tracker interface { StartProcesses() stoppable.Stoppable AddIdentity(id *id.ID, validUntil time.Time, persistent bool) RemoveIdentity(id *id.ID) - GetEphemeralIdentity(rng io.Reader, addressSize uint8) (receptionID.IdentityUse, error) + ForEach(n int, rng io.Reader, addressSize uint8, + operator func([]receptionID.IdentityUse) error) error GetIdentity(get *id.ID) (TrackedID, error) } type manager struct { - tracked []TrackedID + tracked []*TrackedID ephemeral *receptionID.Store session storage.Session newIdentity chan TrackedID @@ -76,7 +76,7 @@ type TrackedID struct { func NewOrLoadTracker(session storage.Session, addrSpace address.Space) *manager { // Initialization t := &manager{ - tracked: make([]TrackedID, 0), + tracked: make([]*TrackedID, 0), session: session, newIdentity: make(chan TrackedID, trackedIDChanSize), deleteIdentity: make(chan *id.ID, deleteIDChanSize), @@ -86,13 +86,13 @@ func NewOrLoadTracker(session storage.Session, addrSpace address.Space) *manager // Load this structure err := t.load() - if err != nil && errors.Is(err, fs.ErrNotExist) { + if err != nil && !t.session.GetKV().Exists(err) { oldTimestamp, err2 := getOldTimestampStore(t.session) if err2 == nil { jww.WARN.Printf("No tracked identities found, creating a new " + "tracked identity from legacy stored timestamp.") - t.tracked = append(t.tracked, TrackedID{ + t.tracked = append(t.tracked, &TrackedID{ // Make the next generation now so a generation triggers on // first run NextGeneration: netTime.Now(), @@ -143,10 +143,14 @@ func (t *manager) RemoveIdentity(id *id.ID) { t.deleteIdentity <- id } -// GetEphemeralIdentity returns an ephemeral Identity to poll the network with. -func (t *manager) GetEphemeralIdentity(rng io.Reader, addressSize uint8) ( - receptionID.IdentityUse, error) { - return t.ephemeral.GetIdentity(rng, addressSize) +// ForEach passes a fisher-yates shuffled list of up to 'num' +// ephemeral identities into the operation function. It will pass a +// fake identity if none are available +// and less than 'num' if less than 'num' are available. +// 'num' must be positive non-zero +func (t *manager) ForEach(n int, rng io.Reader, addressSize uint8, + operator func([]receptionID.IdentityUse) error) error { + return t.ephemeral.ForEach(n, rng, addressSize, operator) } // GetIdentity returns a currently tracked identity @@ -155,7 +159,7 @@ func (t *manager) GetIdentity(get *id.ID) (TrackedID, error) { defer t.mux.Unlock() for i := range t.tracked { if get.Cmp(t.tracked[i].Source) { - return t.tracked[i], nil + return *t.tracked[i], nil } } return TrackedID{}, errors.Errorf("could not find id %s", get) @@ -201,16 +205,18 @@ func (t *manager) track(stop *stoppable.Single) { if !isOld { jww.DEBUG.Printf("Tracking new identity %s", newIdentity.Source) // Otherwise, add it to the list and run - t.tracked = append(t.tracked, newIdentity) + t.tracked = append(t.tracked, &newIdentity) } t.save() continue case deleteID := <-t.deleteIdentity: + removed := false for i := range t.tracked { inQuestion := t.tracked[i] if inQuestion.Source.Cmp(deleteID) { + removed = true t.tracked = append(t.tracked[:i], t.tracked[i+1:]...) t.save() // Requires manual deletion in case identity is deleted before expiration @@ -218,6 +224,9 @@ func (t *manager) track(stop *stoppable.Single) { break } } + if !removed { + jww.WARN.Printf("Identity %s failed to be removed from tracker", deleteID) + } case <-stop.Quit(): t.addrSpace.UnregisterAddressSpaceNotification(addressSpaceSizeChanTag) stop.ToStopped() @@ -236,7 +245,8 @@ func (t *manager) processIdentities(addressSize uint8) time.Time { nextEvent := netTime.Now().Add(time.Duration(ephemeral.Period)) // Loop through every tracked ID and see if any operations are needed - for i, inQuestion := range t.tracked { + for i := range t.tracked { + inQuestion := t.tracked[i] // Generate new ephemeral if is time for it if netTime.Now().After(inQuestion.NextGeneration) { nextGeneration := t.generateIdentitiesOverRange(inQuestion, addressSize) @@ -267,7 +277,7 @@ func (t *manager) processIdentities(addressSize uint8) time.Time { // Process any deletions if len(toRemove) > 0 { - newTracked := make([]TrackedID, 0, len(t.tracked)) + newTracked := make([]*TrackedID, 0, len(t.tracked)) for i := range t.tracked { if _, remove := toRemove[i]; !remove { newTracked = append(newTracked, t.tracked[i]) @@ -305,7 +315,7 @@ func unmarshalTimestamp(lastTimestampObj *versioned.Object) (time.Time, error) { // generateIdentitiesOverRange generates and adds all not yet existing ephemeral Ids // and returns the timestamp of the next generation for the given TrackedID -func (t *manager) generateIdentitiesOverRange(inQuestion TrackedID, +func (t *manager) generateIdentitiesOverRange(inQuestion *TrackedID, addressSize uint8) time.Time { // Ensure that ephemeral IDs will not be generated after the // identity is invalid @@ -374,7 +384,7 @@ func (t *manager) save() { for i := range t.tracked { if t.tracked[i].Persistent { - persistent = append(persistent, t.tracked[i]) + persistent = append(persistent, *t.tracked[i]) } } @@ -393,7 +403,7 @@ func (t *manager) save() { Data: data, } - err = t.session.GetKV().Set(TrackerListKey, TrackerListVersion, obj) + err = t.session.GetKV().Set(TrackerListKey, obj) if err != nil { jww.FATAL.Panicf("Unable to save TrackedID list: %+v", err) } diff --git a/cmix/identity/tracker_test.go b/cmix/identity/tracker_test.go index d16f64b5526f30e2d9719974ad1f82560b7f6b1f..d1d75b078e5d21c326d1658247177aa10a2d4d2d 100644 --- a/cmix/identity/tracker_test.go +++ b/cmix/identity/tracker_test.go @@ -1,7 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2022 Privategrity Corporation / -// / -// All rights reserved. / +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package identity @@ -67,7 +68,7 @@ func TestManager_processIdentities(t *testing.T) { addrSpace.UpdateAddressSpace(18) session := storage.InitTestingSession(t) m := &manager{ - tracked: make([]TrackedID, 0), + tracked: make([]*TrackedID, 0), session: session, newIdentity: make(chan TrackedID, trackedIDChanSize), deleteIdentity: make(chan *id.ID, deleteIDChanSize), @@ -79,7 +80,7 @@ func TestManager_processIdentities(t *testing.T) { // Add some expired test IDs testId := id.NewIdFromUInt(0, id.User, t) validUntil := netTime.Now().Add(time.Minute) - m.tracked = append(m.tracked, TrackedID{ + m.tracked = append(m.tracked, &TrackedID{ NextGeneration: netTime.Now(), LastGeneration: time.Time{}, Source: testId, diff --git a/cmix/interface.go b/cmix/interface.go index 717dbb0bbe8b26a288aaa79427bc6d2ed07a30a6..f6572fb1dbdf6811052cb5d541e05286288c20cb 100644 --- a/cmix/interface.go +++ b/cmix/interface.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package cmix import ( @@ -51,7 +58,7 @@ type Client interface { // WARNING: Do not roll your own crypto. Send(recipient *id.ID, fingerprint format.Fingerprint, service message.Service, payload, mac []byte, cmixParams CMIXParams) ( - id.Round, ephemeral.Id, error) + rounds.Round, ephemeral.Id, error) // SendMany sends many "raw" cMix message payloads to the provided // recipients all in the same round. @@ -78,7 +85,25 @@ type Client interface { // (along with the reason). Blocks until successful send or err. // WARNING: Do not roll your own crypto. SendMany(messages []TargetedCmixMessage, p CMIXParams) ( - id.Round, []ephemeral.Id, error) + rounds.Round, []ephemeral.Id, error) + + // SendWithAssembler sends a variable cmix payload to the provided recipient. + // The payload sent is based on the Complier function passed in, which accepts + // a round ID and returns the necessary payload data. + // Returns the round ID of the round the payload was sent or an error if it + // fails. + // This does not have end-to-end encryption on it and is used exclusively as + // a send for higher order cryptographic protocols. Do not use unless + // implementing a protocol on top. + // recipient - cMix ID of the recipient. + // assembler - MessageAssembler function, accepting round ID and returning + // fingerprint + // format.Fingerprint, service message.Service, payload, mac []byte + // Will return an error if the network is unhealthy or if it fails to send + // (along with the reason). Blocks until successful sends or errors. + // WARNING: Do not roll your own crypto. + SendWithAssembler(recipient *id.ID, assembler MessageAssembler, + cmixParams CMIXParams) (rounds.Round, ephemeral.Id, error) /* === Message Reception ================================================ */ /* Identities are all network identities which the client is currently @@ -229,7 +254,7 @@ type Client interface { // GetRoundResults adjudicates on the rounds requested. Checks if they are // older rounds or in progress rounds. GetRoundResults(timeout time.Duration, roundCallback RoundEventCallback, - roundList ...id.Round) error + roundList ...id.Round) // LookupHistoricalRound looks up the passed historical round on the network. // GetRoundResults does this lookup when needed, generally that is @@ -290,12 +315,15 @@ type Client interface { type ClientErrorReport func(source, message, trace string) -// MessageAssembler func accepts a round ID, returning fingerprint, service, payload & mac. -// This allows users to pass in a paylaod which will contain the round ID over which the message is sent. -type MessageAssembler func(rid id.Round) (fingerprint format.Fingerprint, service message.Service, payload, mac []byte) +// MessageAssembler func accepts a round ID, returning fingerprint, service, +// payload & mac. This allows users to pass in a paylaod which will contain the +// round ID over which the message is sent. +type MessageAssembler func(rid id.Round) (fingerprint format.Fingerprint, + service message.Service, payload, mac []byte, err error) -// messageAssembler is an internal wrapper around MessageAssembler which returns a format.message -// This is necessary to preserve the interaction between sendCmixHelper and critical messages +// messageAssembler is an internal wrapper around MessageAssembler which +// returns a format.message This is necessary to preserve the interaction +// between sendCmixHelper and critical messages type messageAssembler func(rid id.Round) (format.Message, error) type clientCommsInterface interface { diff --git a/cmix/message/bundle.go b/cmix/message/bundle.go index 887148285243b4eaa96c1d4b3ef2cdd74a137c0f..7e8b20fb943988e00e39e27bbc9dc68ed3145b14 100644 --- a/cmix/message/bundle.go +++ b/cmix/message/bundle.go @@ -1,15 +1,15 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package message import ( - "gitlab.com/elixxir/client/cmix/rounds" "gitlab.com/elixxir/client/cmix/identity/receptionID" + "gitlab.com/elixxir/client/cmix/rounds" "gitlab.com/elixxir/primitives/format" "gitlab.com/xx_network/primitives/id" ) diff --git a/cmix/message/fingerprints.go b/cmix/message/fingerprints.go index bf6235b9711e6fe9930785ae6f941ab6290c30a5..656ab60e7942aa27f911ac0bd7d1845832c4494d 100644 --- a/cmix/message/fingerprints.go +++ b/cmix/message/fingerprints.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package message diff --git a/cmix/message/fingerprints_test.go b/cmix/message/fingerprints_test.go index 813e48a5a4123dbff0995fbc1f51e1aa38b0848b..582480bd90973ce4e62102fa5f5319eeb1c55ca3 100644 --- a/cmix/message/fingerprints_test.go +++ b/cmix/message/fingerprints_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package message diff --git a/cmix/message/handler.go b/cmix/message/handler.go index 6a5baf55486860b3d14d5d2960acaa861dc18ba0..45b693c5aba110a8c910148d59d75096b5d17fc6 100644 --- a/cmix/message/handler.go +++ b/cmix/message/handler.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package message diff --git a/cmix/message/handler_test.go b/cmix/message/handler_test.go index 99dfb9f199d0ea3ced7341e0ae7282e73930feaf..33247a786a64b5fcadb01e7c62c5d5f88c2137cd 100644 --- a/cmix/message/handler_test.go +++ b/cmix/message/handler_test.go @@ -1,7 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2022 Privategrity Corporation / -// / -// All rights reserved. / +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package message diff --git a/cmix/message/inProgress.go b/cmix/message/inProgress.go index 83cc22fe27041c352bdfb73545e7113a9e5adb38..91760e5865ba99944e4d0b3b5ca78a4b393c34f1 100644 --- a/cmix/message/inProgress.go +++ b/cmix/message/inProgress.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package message diff --git a/cmix/message/inProgress_test.go b/cmix/message/inProgress_test.go index be0dd901c40191e3523defc02457e016555cbf8e..c85dc5d0971324c43f502ed337ac6bd6d356e37b 100644 --- a/cmix/message/inProgress_test.go +++ b/cmix/message/inProgress_test.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package message import ( diff --git a/cmix/message/meteredCmixMessageBuffer.go b/cmix/message/meteredCmixMessageBuffer.go index 0c456e7c1c5846f63f3630778da8c2e109db614c..826f8cab50f4e645652229830a56afd459fd70ad 100644 --- a/cmix/message/meteredCmixMessageBuffer.go +++ b/cmix/message/meteredCmixMessageBuffer.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package message @@ -24,8 +24,6 @@ import ( "golang.org/x/crypto/blake2b" ) -const currentMeteredCmixMessageVersion = 0 - type meteredCmixMessageHandler struct{} type meteredCmixMessage struct { @@ -49,13 +47,13 @@ func (*meteredCmixMessageHandler) SaveMessage(kv *versioned.KV, m interface{}, // Create versioned object obj := versioned.Object{ - Version: currentMeteredCmixMessageVersion, + Version: utility.CurrentMessageBufferVersion, Timestamp: netTime.Now(), Data: marshaled, } // Save versioned object - return kv.Set(key, utility.CurrentMessageBufferVersion, &obj) + return kv.Set(key, &obj) } // LoadMessage returns the message with the specified key from the key value @@ -64,7 +62,7 @@ func (*meteredCmixMessageHandler) SaveMessage(kv *versioned.KV, m interface{}, func (*meteredCmixMessageHandler) LoadMessage(kv *versioned.KV, key string) ( interface{}, error) { // Load the versioned object - vo, err := kv.Get(key, currentMeteredCmixMessageVersion) + vo, err := kv.Get(key, utility.CurrentMessageBufferVersion) if err != nil { return nil, err } @@ -83,7 +81,7 @@ func (*meteredCmixMessageHandler) LoadMessage(kv *versioned.KV, key string) ( // DeleteMessage deletes the message with the specified key from the key value // store. func (*meteredCmixMessageHandler) DeleteMessage(kv *versioned.KV, key string) error { - return kv.Delete(key, currentMeteredCmixMessageVersion) + return kv.Delete(key, utility.CurrentMessageBufferVersion) } // HashMessage generates a hash of the message. diff --git a/cmix/message/meteredCmixMessageBuffer_test.go b/cmix/message/meteredCmixMessageBuffer_test.go index 3dbb7a65d2cb39232fd34abedf5a505b90056450..ec1d6f76e30265a988150e84e72dec012afa7010 100644 --- a/cmix/message/meteredCmixMessageBuffer_test.go +++ b/cmix/message/meteredCmixMessageBuffer_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package message diff --git a/cmix/message/params.go b/cmix/message/params.go index cd2e6675bff9ad8eb6303b40c32a01f80ba152ea..61bc149c329f920e8afe523c7d0c3779b282d1fd 100644 --- a/cmix/message/params.go +++ b/cmix/message/params.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package message diff --git a/cmix/message/processor.go b/cmix/message/processor.go index 1601189b65e1c6c8ea74c263e4e77e7531e76b8d..b59ef05bf593b56935cdd2e96e2c2bdc1eafad3c 100644 --- a/cmix/message/processor.go +++ b/cmix/message/processor.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package message import ( diff --git a/cmix/message/serviceGenerators.go b/cmix/message/serviceGenerators.go index 374e37ba17500c7ac59e25f5d3b6c9a9e7247136..b222063cdd01a7c51cd8825af12c012bbfaa0f97 100644 --- a/cmix/message/serviceGenerators.go +++ b/cmix/message/serviceGenerators.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package message import ( diff --git a/cmix/message/serviceInterface.go b/cmix/message/serviceInterface.go index 346ff4b7f3f05e5902912bd00ad450e2e5e9ff75..e596d6a67939665d0d74e18b519e85b6d4d8f720 100644 --- a/cmix/message/serviceInterface.go +++ b/cmix/message/serviceInterface.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package message import ( diff --git a/cmix/message/serviceTracker.go b/cmix/message/serviceTracker.go index 616f6dfda392ba4cb65c8d02179bbae493fe26ec..1b7d42ce7ef8aa16de2c2496aee1a3b3727ed5d4 100644 --- a/cmix/message/serviceTracker.go +++ b/cmix/message/serviceTracker.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package message import ( @@ -26,7 +33,6 @@ func (sm *ServicesManager) triggerServiceTracking() { if len(sm.trackers) == 0 { return } - services := make(ServiceList) for uid, tmap := range sm.tmap { tList := make([]Service, 0, len(tmap)) diff --git a/cmix/message/serviceTracker_test.go b/cmix/message/serviceTracker_test.go index c7b06b46a853bcc23e267830c9e2cda925385b3a..27a3ac5cb3bcbf51397a074bdedd44f93e68a235 100644 --- a/cmix/message/serviceTracker_test.go +++ b/cmix/message/serviceTracker_test.go @@ -1,7 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2022 Privategrity Corporation / -// / -// All rights reserved. / +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package message @@ -13,7 +14,7 @@ import ( func TestServiceList_Marshal_UnmarshalJSON(t *testing.T) { var sl ServiceList = make(map[id.ID][]Service) - numServices := 10 + numServices := 3 testString := "test" for i := 0; i < numServices; i++ { uid := id.NewIdFromUInt(uint64(i), id.User, t) @@ -24,6 +25,8 @@ func TestServiceList_Marshal_UnmarshalJSON(t *testing.T) { t.Errorf(err.Error()) } + t.Logf("%s", jsonResult) + sl = make(map[id.ID][]Service) err = sl.UnmarshalJSON(jsonResult) if err != nil { diff --git a/cmix/message/services.go b/cmix/message/services.go index 9ede26311cff79aca197228ed51ce3c388b1f7ae..665c4f858dfb2b0af472cd08a4fbdb436df000f0 100644 --- a/cmix/message/services.go +++ b/cmix/message/services.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package message diff --git a/cmix/message/services_test.go b/cmix/message/services_test.go index e3cad7bed0e9ef7d2e21a1561d8cf977213bfb1b..d2082c63ce32dad5c689892457d4e42a9f3e1923 100644 --- a/cmix/message/services_test.go +++ b/cmix/message/services_test.go @@ -1,7 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2022 Privategrity Corporation / -// / -// All rights reserved. / +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package message diff --git a/cmix/nodes/interfaces.go b/cmix/nodes/interfaces.go index ba5809881cf9a7cddc658176b8898eb9f6378bd2..5d08e6db9a6c97712621ed02ced970e8344e1f00 100644 --- a/cmix/nodes/interfaces.go +++ b/cmix/nodes/interfaces.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package nodes diff --git a/cmix/nodes/mixCypher.go b/cmix/nodes/mixCypher.go index 7afc8f23de227e170e6ef5d3f0d797b5dbbff5f5..ab3a554cc9dc39c27cc63e0893e3e26dcf2bd0fb 100644 --- a/cmix/nodes/mixCypher.go +++ b/cmix/nodes/mixCypher.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package nodes diff --git a/cmix/nodes/mixCypher_test.go b/cmix/nodes/mixCypher_test.go index 941ee5532b07edcb84f89888600322e8822555f5..491ef481dfec6422a3f269b31c4bfd2f9911e78b 100644 --- a/cmix/nodes/mixCypher_test.go +++ b/cmix/nodes/mixCypher_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package nodes diff --git a/cmix/nodes/register.go b/cmix/nodes/register.go index 000b5751501b8120c35f099f3a2db59257a8fb07..5d2249ec617e7d39af16bcdd58cc0bd0d7879558 100644 --- a/cmix/nodes/register.go +++ b/cmix/nodes/register.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package nodes diff --git a/cmix/nodes/register_test.go b/cmix/nodes/register_test.go index 6f87c165af189030f5414adc6f61275af3f0add7..8ed9e6c897869e8ad9b5142b20a0e66e992b5621 100644 --- a/cmix/nodes/register_test.go +++ b/cmix/nodes/register_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package nodes @@ -88,4 +88,3 @@ func TestRegisterWithNode(t *testing.T) { t.Fatalf("registerWithNode error: %+v", err) } } - diff --git a/cmix/nodes/registrar.go b/cmix/nodes/registrar.go index 2bfa2cb5df2d982e650658ce15e938d3e31c4624..dc61852f183937b5f4f9eadcda2cdfacd28d20a9 100644 --- a/cmix/nodes/registrar.go +++ b/cmix/nodes/registrar.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package nodes import ( diff --git a/cmix/nodes/registrar_test.go b/cmix/nodes/registrar_test.go index ded004b220cf4e394d2290b842fb2187eb81459b..922adfad68bc2b52f999a92561c834803be4f16b 100644 --- a/cmix/nodes/registrar_test.go +++ b/cmix/nodes/registrar_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package nodes diff --git a/cmix/nodes/request.go b/cmix/nodes/request.go index 4a99c358427314446ccd557afe9596f15ffd7440..499acb4550b2ff31ebf2e4a2d4a8f8c0ef1c707b 100644 --- a/cmix/nodes/request.go +++ b/cmix/nodes/request.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package nodes import ( diff --git a/cmix/nodes/store.go b/cmix/nodes/store.go index ff4511934e02bf57c78834de19c1bc99ea3ac0b1..8ec0e706b1e637d8272fac785c68f5905f98a23e 100644 --- a/cmix/nodes/store.go +++ b/cmix/nodes/store.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package nodes @@ -67,12 +67,12 @@ func (r *registrar) save() error { } obj := versioned.Object{ - Version: currentStoreVersion, + Version: currentKeyVersion, Timestamp: now, Data: data, } - return r.kv.Set(storeKey, currentKeyVersion, &obj) + return r.kv.Set(storeKey, &obj) } // marshal builds a byte representation of the registrar. diff --git a/cmix/nodes/storeKey.go b/cmix/nodes/storeKey.go index 98b6e18cac27c1611bf6f6e2f01a2cf38551a3d2..19f9a636c69102926966ec2f3a53f759d2df4032 100644 --- a/cmix/nodes/storeKey.go +++ b/cmix/nodes/storeKey.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package nodes @@ -84,7 +84,7 @@ func (k *key) save() error { Data: data, } - return k.kv.Set(k.storeKey, currentKeyVersion, &obj) + return k.kv.Set(k.storeKey, &obj) } // delete deletes the key from the versioned keystore. diff --git a/cmix/nodes/store_test.go b/cmix/nodes/store_test.go index 58ecbd9e602896816e0ff3023b826eb957478693..05bc38b2060bbfbd7ff32ad0f132d793aadb525b 100644 --- a/cmix/nodes/store_test.go +++ b/cmix/nodes/store_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package nodes diff --git a/cmix/nodes/utils_test.go b/cmix/nodes/utils_test.go index 5370705a4a72e11638a98b5f54d7aaa15800f9d5..96eacda72794e3f66c1b4513e7f359624cf0cbe1 100644 --- a/cmix/nodes/utils_test.go +++ b/cmix/nodes/utils_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package nodes diff --git a/cmix/params.go b/cmix/params.go index 73ec67dd10f47bb5969164e8593687cac5cf0e16..8eb6c6c3c96d7edd28dac004bfc57df0a1d0d2f3 100644 --- a/cmix/params.go +++ b/cmix/params.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package cmix @@ -58,6 +58,10 @@ type Params struct { // times. ReplayRequests bool + // MaxParallelIdentityTracks is the maximum number of parallel identities + // the system will poll in one iteration of the follower + MaxParallelIdentityTracks uint + Rounds rounds.Params Pickup pickup.Params Message message.Params @@ -80,6 +84,7 @@ type paramsDisk struct { Pickup pickup.Params Message message.Params Historical rounds.Params + MaxParallelIdentityTracks uint } // GetDefaultParams returns a Params object containing the @@ -96,6 +101,7 @@ func GetDefaultParams() Params { VerboseRoundTracking: false, RealtimeOnly: false, ReplayRequests: true, + MaxParallelIdentityTracks: 20, } n.Rounds = rounds.GetDefaultParams() n.Pickup = pickup.GetDefaultParams() @@ -135,6 +141,7 @@ func (p Params) MarshalJSON() ([]byte, error) { Pickup: p.Pickup, Message: p.Message, Historical: p.Historical, + MaxParallelIdentityTracks: p.MaxParallelIdentityTracks, } return json.Marshal(&pDisk) @@ -163,6 +170,7 @@ func (p *Params) UnmarshalJSON(data []byte) error { Pickup: pDisk.Pickup, Message: pDisk.Message, Historical: pDisk.Historical, + MaxParallelIdentityTracks: pDisk.MaxParallelIdentityTracks, } return nil diff --git a/cmix/params_test.go b/cmix/params_test.go index 90ece9d5f6ff0dbf23a528832a0adc297425818e..a6eec124db47ec5a981dba499283708bc8cfcb40 100644 --- a/cmix/params_test.go +++ b/cmix/params_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package cmix diff --git a/cmix/pickup/get.go b/cmix/pickup/get.go index f7a503b1d9fbc360a547f56a877372800db3a545..a31fb36300a2b116ef17ceec9d7eb7e401aef644 100644 --- a/cmix/pickup/get.go +++ b/cmix/pickup/get.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package pickup diff --git a/cmix/pickup/params.go b/cmix/pickup/params.go index 99ec4cb835557f411d3d88cdf07acc23e40dba14..84754d38f4f741350da8c37d0a6f708e3e41bcee 100644 --- a/cmix/pickup/params.go +++ b/cmix/pickup/params.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package pickup diff --git a/cmix/pickup/pickup.go b/cmix/pickup/pickup.go index 649ab4ae0dcdac73615ef501831c67146d327c08..581aeaf285553f55586a5c6006a93dc64f941203 100644 --- a/cmix/pickup/pickup.go +++ b/cmix/pickup/pickup.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package pickup diff --git a/cmix/pickup/retrieve.go b/cmix/pickup/retrieve.go index a855e1e8a641a98cc99a62827caf9be15ca95347..45c8a7e3f66c2d321fbd3882acb40f4ed8e3c9ea 100644 --- a/cmix/pickup/retrieve.go +++ b/cmix/pickup/retrieve.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package pickup diff --git a/cmix/pickup/retrieve_test.go b/cmix/pickup/retrieve_test.go index cf580ec420dfb8d0e3f6a2c62b774f7e5f637479..a14b34a4cadce84b4b73b0447f163355b6138cc1 100644 --- a/cmix/pickup/retrieve_test.go +++ b/cmix/pickup/retrieve_test.go @@ -1,9 +1,10 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package pickup import ( diff --git a/cmix/pickup/roundGetter.go b/cmix/pickup/roundGetter.go index 9f01fa4971fb7a02fa9176bed730c47fa66e2d2f..1c265b286c66df0921d41174a594a37d74a35a7d 100644 --- a/cmix/pickup/roundGetter.go +++ b/cmix/pickup/roundGetter.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package pickup import ( diff --git a/cmix/pickup/store/roundIdentity.go b/cmix/pickup/store/roundIdentity.go index a5c64b021d999a7ab78437e5b190c715e4620696..c9fc5df6cebdecee740ceb4cce079d34782fbe12 100644 --- a/cmix/pickup/store/roundIdentity.go +++ b/cmix/pickup/store/roundIdentity.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package store import ( diff --git a/cmix/pickup/store/store.go b/cmix/pickup/store/store.go index 4a1f83006a2dce8fead22551dcebfabb2127ad61..88a300494aaa2003c3181c60cec46b6c6e884821 100644 --- a/cmix/pickup/store/store.go +++ b/cmix/pickup/store/store.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package store import ( @@ -218,7 +225,7 @@ func (s *UncheckedRoundStore) save() error { } // Save to storage - err = s.kv.Set(uncheckedRoundKey, uncheckedRoundVersion, obj) + err = s.kv.Set(uncheckedRoundKey, obj) if err != nil { return errors.WithMessagef(err, "Could not store data for unchecked rounds") diff --git a/cmix/pickup/store/uncheckedRounds.go b/cmix/pickup/store/uncheckedRounds.go index b15cc5b803cc9d3139746833c60b6baf14e5ac35..bc62d8a1d64583c44ca690af23aa733ee2e742e8 100644 --- a/cmix/pickup/store/uncheckedRounds.go +++ b/cmix/pickup/store/uncheckedRounds.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package store @@ -147,7 +147,7 @@ func storeRoundInfo(kv *versioned.KV, info *pb.RoundInfo, recipient *id.ID, } return kv.Set( - roundKey(id.Round(info.ID), recipient, ephID), roundInfoVersion, &obj) + roundKey(id.Round(info.ID), recipient, ephID), &obj) } func loadRoundInfo(kv *versioned.KV, id id.Round, recipient *id.ID, diff --git a/cmix/pickup/store/uncheckedRounds_test.go b/cmix/pickup/store/uncheckedRounds_test.go index 8e4dbe052e75d5eb98fb98863be92d91200c54b4..2f8354b09e6df0fa244d6299c34ca96ce160da4e 100644 --- a/cmix/pickup/store/uncheckedRounds_test.go +++ b/cmix/pickup/store/uncheckedRounds_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package store diff --git a/cmix/pickup/unchecked.go b/cmix/pickup/unchecked.go index 22afaa5658b79604b1feebadf2a73312b41d952a..ca289a1ee390bfb7dd9df3c634590d8a54be7752 100644 --- a/cmix/pickup/unchecked.go +++ b/cmix/pickup/unchecked.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package pickup diff --git a/cmix/pickup/unchecked_test.go b/cmix/pickup/unchecked_test.go index 339826469fc28b0797788db62e63e4a7f110cb5a..6db1b9ec67c2f767cf04e0d170325173622f0c52 100644 --- a/cmix/pickup/unchecked_test.go +++ b/cmix/pickup/unchecked_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package pickup diff --git a/cmix/pickup/utils_test.go b/cmix/pickup/utils_test.go index d25491d283b2ec59fc17834d8101f193e9f6ff53..2b325987ac6fab5a1bcfd205a10ba25837f53a2e 100644 --- a/cmix/pickup/utils_test.go +++ b/cmix/pickup/utils_test.go @@ -1,9 +1,10 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package pickup import ( diff --git a/cmix/polltracker.go b/cmix/polltracker.go index 835a820c548137965d0566178f22cc397c862881..1e0bdcb453c8374b199392c3941910b5108071da 100644 --- a/cmix/polltracker.go +++ b/cmix/polltracker.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package cmix import ( diff --git a/cmix/polltracker_test.go b/cmix/polltracker_test.go index 8fb6d96860d70c94f48f51843a03df44f84694be..1c10c9f9dba590a67b7213b89b13b1f26d93aae9 100644 --- a/cmix/polltracker_test.go +++ b/cmix/polltracker_test.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package cmix import ( diff --git a/cmix/remoteFilters.go b/cmix/remoteFilters.go index 37cf100e60396c612df73e85b31e5d07c5688d2f..4610697fec850387eb15f49c89024336d187e973 100644 --- a/cmix/remoteFilters.go +++ b/cmix/remoteFilters.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package cmix diff --git a/cmix/remoteFilters_test.go b/cmix/remoteFilters_test.go index b33daa8b4904ec557857724609433b8baf33b8e2..97b8b9040e67d5a611b6ba2c26c6bdc5fab7d9dd 100644 --- a/cmix/remoteFilters_test.go +++ b/cmix/remoteFilters_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package cmix diff --git a/cmix/results.go b/cmix/results.go index a6f8c4ad8834925dd54af6a8f151b750d0f092e8..916bdb206610fc2c98ed0509acba705d6c9c1a33 100644 --- a/cmix/results.go +++ b/cmix/results.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package cmix @@ -65,19 +65,19 @@ type RoundEventCallback func(allRoundsSucceeded, timedOut bool, rounds map[id.Ro // GetRoundResults adjudicates on the rounds requested. Checks if they are // older rounds or in progress rounds. func (c *client) GetRoundResults(timeout time.Duration, - roundCallback RoundEventCallback, roundList ...id.Round) error { + roundCallback RoundEventCallback, roundList ...id.Round) { jww.INFO.Printf("GetRoundResults(%v, %s)", roundList, timeout) sendResults := make(chan ds.EventReturn, len(roundList)) - return c.getRoundResults(roundList, timeout, roundCallback, + c.getRoundResults(roundList, timeout, roundCallback, sendResults) } // Helper function which does all the logic for GetRoundResults func (c *client) getRoundResults(roundList []id.Round, timeout time.Duration, - roundCallback RoundEventCallback, sendResults chan ds.EventReturn) error { + roundCallback RoundEventCallback, sendResults chan ds.EventReturn) { networkInstance := c.GetInstance() @@ -221,6 +221,4 @@ func (c *client) getRoundResults(roundList []id.Round, timeout time.Duration, } }() - - return nil } diff --git a/cmix/results_test.go b/cmix/results_test.go index eaa2edb2b8de79d4caf49cada4c8e95123ca5c03..d0de5e992a2cc5657a299648644248cd7cb234d7 100644 --- a/cmix/results_test.go +++ b/cmix/results_test.go @@ -1,9 +1,10 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package cmix const numRounds = 10 diff --git a/cmix/roundTracking.go b/cmix/roundTracking.go index 56b327d17b309bc700af2dcc2f05a6d005eb37dd..674538a1a405dd02b335a59474cce7afd5bcc739 100644 --- a/cmix/roundTracking.go +++ b/cmix/roundTracking.go @@ -1,7 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2021 Privategrity Corporation / -// / -// All rights reserved. / +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// // This is an in-memory track of rounds that have been processed in this run of diff --git a/cmix/roundTracking_test.go b/cmix/roundTracking_test.go index c6219228a6e6df2c3d2c39a69440fa43e20e9013..9e7760458a429fac91bc1090876e47da2d91064d 100644 --- a/cmix/roundTracking_test.go +++ b/cmix/roundTracking_test.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package cmix import ( diff --git a/cmix/rounds/historical.go b/cmix/rounds/historical.go index 6b4ffbcd727c9b2e8c70b53769fb44c46761dca7..165ce22817fd2e9e01dda3de8c410ab0c174f40c 100644 --- a/cmix/rounds/historical.go +++ b/cmix/rounds/historical.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package rounds diff --git a/cmix/rounds/historical_test.go b/cmix/rounds/historical_test.go index 807386a2557bcc84392e024d99d1ca0aedc30e1d..7fec1ae6629ba7bbb6640d4d17acddc96a480fc9 100644 --- a/cmix/rounds/historical_test.go +++ b/cmix/rounds/historical_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package rounds diff --git a/cmix/rounds/params.go b/cmix/rounds/params.go index dd9596c2fcf6809010ceb9fbeda609f2ef3b6645..78a407a75193f54be463ba08eb557f5215cb0a79 100644 --- a/cmix/rounds/params.go +++ b/cmix/rounds/params.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package rounds diff --git a/cmix/rounds/round.go b/cmix/rounds/round.go index 6f4f48183ca2c2f0eb0e473f4a91a752fa381b11..850cfb99e2b1ad2ac2a407b287c273ffa4211a20 100644 --- a/cmix/rounds/round.go +++ b/cmix/rounds/round.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package rounds import ( diff --git a/cmix/rounds/roundStorage.go b/cmix/rounds/roundStorage.go index 2b92c819f9b6279dd30d4b8b37a503b146168501..f05914ba2918612c1cb382e95e870f7c6fc7157c 100644 --- a/cmix/rounds/roundStorage.go +++ b/cmix/rounds/roundStorage.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package rounds import ( @@ -25,7 +32,7 @@ func StoreRound(kv *versioned.KV, round Round, key string) error { Data: marshaled, } - return kv.Set(key, currentRoundVersion, &obj) + return kv.Set(key, &obj) } // LoadRound stores the round using the key. diff --git a/cmix/rounds/round_test.go b/cmix/rounds/round_test.go index b0198c9acf473e2c70eae144ff71cdc3b9d96412..e903a5968e0874900296ee7211706d87afb216c3 100644 --- a/cmix/rounds/round_test.go +++ b/cmix/rounds/round_test.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package rounds import ( diff --git a/cmix/sendCmix.go b/cmix/sendCmix.go index 648e1ef1c8691211f40bf11fc76e86bc17e5dfe7..bc9891a4abfea507ebe4f18672fbd72ab8270a3c 100644 --- a/cmix/sendCmix.go +++ b/cmix/sendCmix.go @@ -1,14 +1,15 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package cmix import ( "fmt" + "gitlab.com/elixxir/client/cmix/rounds" "strings" "time" @@ -56,10 +57,11 @@ import ( // WARNING: Do not roll your own crypto. func (c *client) Send(recipient *id.ID, fingerprint format.Fingerprint, service message.Service, payload, mac []byte, cmixParams CMIXParams) ( - id.Round, ephemeral.Id, error) { + rounds.Round, ephemeral.Id, error) { // create an internal assembler function to pass to sendWithAssembler - assembler := func(rid id.Round) (format.Fingerprint, message.Service, []byte, []byte) { - return fingerprint, service, payload, mac + assembler := func(rid id.Round) (format.Fingerprint, message.Service, + []byte, []byte, error) { + return fingerprint, service, payload, mac, nil } return c.sendWithAssembler(recipient, assembler, cmixParams) } @@ -79,10 +81,10 @@ func (c *client) Send(recipient *id.ID, fingerprint format.Fingerprint, // (along with the reason). Blocks until successful sends or errors. // WARNING: Do not roll your own crypto. func (c *client) SendWithAssembler(recipient *id.ID, assembler MessageAssembler, cmixParams CMIXParams) ( - id.Round, ephemeral.Id, error) { + rounds.Round, ephemeral.Id, error) { // Critical messaging and assembler-based message payloads are not compatible if cmixParams.Critical { - return 0, ephemeral.Id{}, errors.New("Cannot send critical messages with a message assembler") + return rounds.Round{}, ephemeral.Id{}, errors.New("Cannot send critical messages with a message assembler") } return c.sendWithAssembler(recipient, assembler, cmixParams) } @@ -90,15 +92,19 @@ func (c *client) SendWithAssembler(recipient *id.ID, assembler MessageAssembler, // sendWithAssembler wraps the passed in MessageAssembler in a messageAssembler for sendCmixHelper, // and sets up critical message handling where applicable. func (c *client) sendWithAssembler(recipient *id.ID, assembler MessageAssembler, cmixParams CMIXParams) ( - id.Round, ephemeral.Id, error) { + rounds.Round, ephemeral.Id, error) { if !c.Monitor.IsHealthy() { - return 0, ephemeral.Id{}, errors.New( + return rounds.Round{}, ephemeral.Id{}, errors.New( "Cannot send cmix message when the network is not healthy") } // Create an internal messageAssembler which returns a format.Message assemblerFunc := func(rid id.Round) (format.Message, error) { - fingerprint, service, payload, mac := assembler(rid) + fingerprint, service, payload, mac, err := assembler(rid) + + if err != nil { + return format.Message{}, err + } if len(payload) != c.maxMsgLen { return format.Message{}, errors.Errorf( @@ -123,15 +129,15 @@ func (c *client) sendWithAssembler(recipient *id.ID, assembler MessageAssembler, return msg, nil } - rid, ephID, msg, rtnErr := sendCmixHelper(c.Sender, assemblerFunc, recipient, cmixParams, + r, ephID, msg, rtnErr := sendCmixHelper(c.Sender, assemblerFunc, recipient, cmixParams, c.instance, c.session.GetCmixGroup(), c.Registrar, c.rng, c.events, c.session.GetTransmissionID(), c.comms) if cmixParams.Critical { - c.crit.handle(msg, recipient, rid, rtnErr) + c.crit.handle(msg, recipient, r.ID, rtnErr) } - return rid, ephID, rtnErr + return r, ephID, rtnErr } // sendCmixHelper is a helper function for client.SendCMIX. @@ -147,7 +153,13 @@ func (c *client) sendWithAssembler(recipient *id.ID, assembler MessageAssembler, func sendCmixHelper(sender gateway.Sender, assembler messageAssembler, recipient *id.ID, cmixParams CMIXParams, instance *network.Instance, grp *cyclic.Group, nodes nodes.Registrar, rng *fastRNG.StreamGenerator, events event.Reporter, - senderId *id.ID, comms SendCmixCommsInterface) (id.Round, ephemeral.Id, format.Message, error) { + senderId *id.ID, comms SendCmixCommsInterface) (rounds.Round, ephemeral.Id, format.Message, error) { + + if cmixParams.RoundTries == 0 { + return rounds.Round{}, ephemeral.Id{}, format.Message{}, + errors.Errorf("invalid parameter set, "+ + "RoundTries cannot be 0: %+v", cmixParams) + } timeStart := netTime.Now() maxTimeout := sender.GetHostParams().SendTimeout @@ -165,7 +177,8 @@ func sendCmixHelper(sender gateway.Sender, assembler messageAssembler, recipient stream := rng.GetStream() defer stream.Close() - for numRoundTries := uint(0); numRoundTries < cmixParams.RoundTries; numRoundTries++ { + for numRoundTries := uint( + 0); numRoundTries < cmixParams.RoundTries; numRoundTries++ { elapsed := netTime.Since(timeStart) jww.TRACE.Printf("[Send-%s] try %d, elapsed: %s", cmixParams.DebugTag, numRoundTries, elapsed) @@ -174,7 +187,7 @@ func sendCmixHelper(sender gateway.Sender, assembler messageAssembler, recipient jww.INFO.Printf("[Send-%s] No rounds to send to %s "+ "were found before timeout %s", cmixParams.DebugTag, recipient, cmixParams.Timeout) - return 0, ephemeral.Id{}, format.Message{}, errors.New("Sending cmix message timed out") + return rounds.Round{}, ephemeral.Id{}, format.Message{}, errors.New("Sending cmix message timed out") } if numRoundTries > 0 { @@ -185,30 +198,34 @@ func sendCmixHelper(sender gateway.Sender, assembler messageAssembler, recipient // Find the best round to send to, excluding attempted rounds remainingTime := cmixParams.Timeout - elapsed - bestRound, err := instance.GetWaitingRounds().GetUpcomingRealtime( + waitingRounds := instance.GetWaitingRounds() + bestRound, err := waitingRounds.GetUpcomingRealtime( remainingTime, attempted, sendTimeBuffer) if err != nil { - jww.WARN.Printf("[Send-%s] Failed to GetUpcomingRealtime: "+ + jww.WARN.Printf("[Send-%s] failed to GetUpcomingRealtime: "+ "%+v", cmixParams.DebugTag, err) } if bestRound == nil { jww.WARN.Printf( - "[Send-%s] Best round on send is nil", cmixParams.DebugTag) + "[Send-%s] Best round on send is nil", + cmixParams.DebugTag) continue } jww.TRACE.Printf("[Send-%s] Best round found: %+v", cmixParams.DebugTag, bestRound) - // Determine whether the selected round contains any nodes that are - // blacklisted by the CMIXParams object + // Determine whether the selected round contains any + // nodes that are blacklisted by the CMIXParams object containsBlacklisted := false if cmixParams.BlacklistedNodes != nil { + blacklist := cmixParams.BlacklistedNodes for _, nodeId := range bestRound.Topology { var nid id.ID copy(nid[:], nodeId) - if _, isBlacklisted := cmixParams.BlacklistedNodes[nid]; isBlacklisted { + _, isBlacklisted := blacklist[nid] + if isBlacklisted { containsBlacklisted = true break } @@ -216,15 +233,17 @@ func sendCmixHelper(sender gateway.Sender, assembler messageAssembler, recipient } if containsBlacklisted { - jww.WARN.Printf("[Send-%s] Round %d contains blacklisted "+ - "nodes, skipping...", cmixParams.DebugTag, bestRound.ID) + jww.WARN.Printf("[Send-%s] Round %d "+ + "contains blacklisted nodes, skipping...", + cmixParams.DebugTag, + bestRound.ID) continue } msg, err := assembler(id.Round(bestRound.ID)) if err != nil { jww.ERROR.Printf("Failed to compile message: %+v", err) - return 0, ephemeral.Id{}, format.Message{}, err + return rounds.Round{}, ephemeral.Id{}, format.Message{}, err } // Flip leading bits randomly to thwart a tagging attack. @@ -247,7 +266,7 @@ func sendCmixHelper(sender gateway.Sender, assembler messageAssembler, recipient wrappedMsg, encMsg, ephID, err := buildSlotMessage(msg, recipient, firstGateway, stream, senderId, bestRound, roundKeys) if err != nil { - return 0, ephemeral.Id{}, format.Message{}, err + return rounds.Round{}, ephemeral.Id{}, format.Message{}, err } jww.INFO.Printf("[Send-%s] Sending to EphID %d (%s), on round %d "+ @@ -297,7 +316,7 @@ func sendCmixHelper(sender gateway.Sender, assembler messageAssembler, recipient // Exit if the thread has been stopped if stoppable.CheckErr(err) { - return 0, ephemeral.Id{}, format.Message{}, err + return rounds.Round{}, ephemeral.Id{}, format.Message{}, err } // If the comm errors or the message fails to send, continue retrying @@ -306,7 +325,7 @@ func sendCmixHelper(sender gateway.Sender, assembler messageAssembler, recipient jww.ERROR.Printf("[Send-%s] SendCmix failed to send to "+ "EphID %d (%s) on round %d: %+v", cmixParams.DebugTag, ephID.Int64(), recipient, bestRound.ID, err) - return 0, ephemeral.Id{}, format.Message{}, err + return rounds.Round{}, ephemeral.Id{}, format.Message{}, err } jww.ERROR.Printf("[Send-%s] SendCmix failed to send to "+ @@ -326,7 +345,7 @@ func sendCmixHelper(sender gateway.Sender, assembler messageAssembler, recipient jww.INFO.Print(m) events.Report(1, "MessageSend", "Metric", m) - return id.Round(bestRound.ID), ephID, msg, nil + return rounds.MakeRound(bestRound), ephID, msg, nil } else { jww.FATAL.Panicf("[Send-%s] Gateway %s returned no error, "+ "but failed to accept message when sending to EphID %d (%s) "+ @@ -335,6 +354,6 @@ func sendCmixHelper(sender gateway.Sender, assembler messageAssembler, recipient } } - return 0, ephemeral.Id{}, format.Message{}, - errors.New("failed to send the message, unknown error") + return rounds.Round{}, ephemeral.Id{}, format.Message{}, + errors.New("failed to send the message, out of round retries") } diff --git a/cmix/sendCmixUtils.go b/cmix/sendCmixUtils.go index e1db33471e869d36e60369813746c59c8bb44b11..146e63117d5cde18c1ee8d9dc794156eded72ad1 100644 --- a/cmix/sendCmixUtils.go +++ b/cmix/sendCmixUtils.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package cmix diff --git a/cmix/sendCmix_test.go b/cmix/sendCmix_test.go index 67ec64ef857f9220adb3d23998aef44442631ba3..9b08c71f703729d983c2efdbbdac38b3017ac04d 100644 --- a/cmix/sendCmix_test.go +++ b/cmix/sendCmix_test.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package cmix // func TestClient_SendCMIX(t *testing.T) { diff --git a/cmix/sendManyCmix.go b/cmix/sendManyCmix.go index 01e39d34e881167e224ae78fe65a8bbc18aacee0..b9700c0d813a15754713a322b96422e484c24f3e 100644 --- a/cmix/sendManyCmix.go +++ b/cmix/sendManyCmix.go @@ -1,14 +1,15 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package cmix import ( "fmt" + "gitlab.com/elixxir/client/cmix/rounds" "strings" "time" @@ -67,9 +68,9 @@ type TargetedCmixMessage struct { // (along with the reason). Blocks until successful send or err. // WARNING: Do not roll your own crypto func (c *client) SendMany(messages []TargetedCmixMessage, - p CMIXParams) (id.Round, []ephemeral.Id, error) { + p CMIXParams) (rounds.Round, []ephemeral.Id, error) { if !c.Monitor.IsHealthy() { - return 0, []ephemeral.Id{}, errors.New( + return rounds.Round{}, []ephemeral.Id{}, errors.New( "Cannot send cMix message when the network is not healthy") } @@ -113,7 +114,7 @@ func sendManyCmixHelper(sender gateway.Sender, grp *cyclic.Group, registrar nodes.Registrar, rng *fastRNG.StreamGenerator, events event.Reporter, senderId *id.ID, comms SendCmixCommsInterface) ( - id.Round, []ephemeral.Id, error) { + rounds.Round, []ephemeral.Id, error) { timeStart := netTime.Now() var attempted excludedRounds.ExcludedRounds @@ -147,7 +148,7 @@ func sendManyCmixHelper(sender gateway.Sender, jww.INFO.Printf("[SendMany-%s] No rounds to send to %s "+ "(msgDigest: %s) were found before timeout %s", param.DebugTag, recipientString, msgDigests, param.Timeout) - return 0, []ephemeral.Id{}, + return rounds.Round{}, []ephemeral.Id{}, errors.New("sending cMix message timed out") } @@ -210,7 +211,7 @@ func sendManyCmixHelper(sender gateway.Sender, stream.Close() jww.INFO.Printf("[SendMany-%s] Error building slot "+ "received: %v", param.DebugTag, err) - return 0, []ephemeral.Id{}, errors.Errorf("failed to build "+ + return rounds.Round{}, []ephemeral.Id{}, errors.Errorf("failed to build "+ "slot message for %s: %+v", msg.Recipient, err) } } @@ -259,7 +260,7 @@ func sendManyCmixHelper(sender gateway.Sender, // Exit if the thread has been stopped if stoppable.CheckErr(err) { - return 0, []ephemeral.Id{}, err + return rounds.Round{}, []ephemeral.Id{}, err } // If the comm errors or the message fails to send, continue retrying @@ -276,7 +277,7 @@ func sendManyCmixHelper(sender gateway.Sender, jww.INFO.Printf("[SendMany-%s] Error received: %v", param.DebugTag, err) } - return 0, []ephemeral.Id{}, err + return rounds.Round{}, []ephemeral.Id{}, err } // Return if it sends properly @@ -288,7 +289,7 @@ func sendManyCmixHelper(sender gateway.Sender, bestRound.ID, msgDigests) jww.INFO.Print(m) events.Report(1, "MessageSendMany", "Metric", m) - return id.Round(bestRound.ID), ephemeralIDs, nil + return rounds.MakeRound(bestRound), ephemeralIDs, nil } else { jww.FATAL.Panicf("[SendMany-%s] Gateway %s returned no "+ "error, but failed to accept message when sending to EphIDs "+ @@ -297,6 +298,6 @@ func sendManyCmixHelper(sender gateway.Sender, } } - return 0, []ephemeral.Id{}, + return rounds.Round{}, []ephemeral.Id{}, errors.New("failed to send the message, unknown error") } diff --git a/cmix/sendManyCmix_test.go b/cmix/sendManyCmix_test.go index 845dcd5981d49ca56112d1394041968cb8a3b0ee..a127154e56110a1ff1f78590102919d3e2a44277 100644 --- a/cmix/sendManyCmix_test.go +++ b/cmix/sendManyCmix_test.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package cmix // func TestClient_SendMany_SendManyCMIX(t *testing.T) { diff --git a/cmix/trackResults.go b/cmix/trackResults.go index c27b259408fe814d9fc1218b0f49047bc3ad4564..412c38974f38991f05e7ee2d146a37d7ef4438e2 100644 --- a/cmix/trackResults.go +++ b/cmix/trackResults.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package cmix diff --git a/cmix/utils_test.go b/cmix/utils_test.go index 9d7b20d3df65c8dd77b4e464ac1898e6c1eaae5d..0a0cb6d2264412e767de7840fc73f07230e0b2c6 100644 --- a/cmix/utils_test.go +++ b/cmix/utils_test.go @@ -1,12 +1,14 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package cmix import ( + "gitlab.com/elixxir/client/cmix/rounds" "time" "github.com/pkg/errors" @@ -191,14 +193,14 @@ func (mrr *mockRoundEventRegistrar) AddRoundEventChan(rid id.Round, eventChan ch // mockCriticalSender func mockCriticalSender(msg format.Message, recipient *id.ID, - params CMIXParams) (id.Round, ephemeral.Id, error) { - return id.Round(1), ephemeral.Id{}, nil + params CMIXParams) (rounds.Round, ephemeral.Id, error) { + return rounds.Round{ID: 1}, ephemeral.Id{}, nil } // mockFailCriticalSender func mockFailCriticalSender(msg format.Message, recipient *id.ID, - params CMIXParams) (id.Round, ephemeral.Id, error) { - return id.Round(1), ephemeral.Id{}, errors.New("Test error") + params CMIXParams) (rounds.Round, ephemeral.Id, error) { + return rounds.Round{ID: 1}, ephemeral.Id{}, errors.New("Test error") } // func newTestClient(t *testing.T) (*client, error) { diff --git a/connect/authCallbacks.go b/connect/authCallbacks.go index 4588557b0a58fbb89623d4a46f988b4c495d4362..ab1ff7b0a2138e7fbea34486425759dd37b28c1c 100644 --- a/connect/authCallbacks.go +++ b/connect/authCallbacks.go @@ -1,7 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2022 Privategrity Corporation / -// / -// All rights reserved. / +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package connect diff --git a/connect/authenticated.go b/connect/authenticated.go index 6a311978d78333ec9709151e7528c7da7f55657f..c5493deb0da13d227017e6695789f9317da2c830 100644 --- a/connect/authenticated.go +++ b/connect/authenticated.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package connect @@ -67,7 +67,7 @@ func ConnectWithAuthentication(recipient contact.Contact, user *xxdk.E2e, // Build the authenticated connection and return identity := user.GetReceptionIdentity() - privKey, err := identity.GetRSAPrivatePem() + privKey, err := identity.GetRSAPrivateKey() if err != nil { return nil, err } @@ -98,7 +98,7 @@ func connectWithAuthentication(conn Connection, timeStart time.Time, } // Send message to server - rids, _, _, err := conn.SendE2E(catalog.ConnectionAuthenticationRequest, + sendReport, err := conn.SendE2E(catalog.ConnectionAuthenticationRequest, payload, clientE2e.GetDefaultParams()) if err != nil { // Close connection on an error @@ -138,12 +138,8 @@ func connectWithAuthentication(conn Connection, timeStart time.Time, // Track the result of the round(s) we sent the // identity authentication message on - err = net.GetRoundResults(remainingTime, - roundCb, rids...) - if err != nil { - return nil, errors.Errorf("could not track rounds for successful " + - "identity confirmation message delivery") - } + net.GetRoundResults(remainingTime, + roundCb, sendReport.RoundList...) // Block waiting for confirmation of the round(s) success (or timeout jww.DEBUG.Printf("AuthenticatedConnection waiting for authenticated "+ "connection with %s to be established...", recipient.ID.String()) diff --git a/connect/authenticated.pb.go b/connect/authenticated.pb.go index a12961650fe8a763a5b07be50163f4b4ef496acc..f78d97c7c552b5e888f61a7cbe89aa4f908cb1f0 100644 --- a/connect/authenticated.pb.go +++ b/connect/authenticated.pb.go @@ -1,100 +1,174 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// source: connect/authenticated/authenticated.proto +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// -package connect // import "gitlab.com/elixxir/client/connect/authenticated" +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.27.1 +// protoc v3.15.6 +// source: authenticated.proto -import proto "github.com/golang/protobuf/proto" -import fmt "fmt" -import math "math" +package connect -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) // Sent by the receiver of the authenticated connection request. type IdentityAuthentication struct { - Signature []byte `protobuf:"bytes,1,opt,name=Signature,proto3" json:"Signature,omitempty"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Signature []byte `protobuf:"bytes,1,opt,name=Signature,proto3" json:"Signature,omitempty"` // Signature of the connection fingerprint // established between the two partners - RsaPubKey []byte `protobuf:"bytes,2,opt,name=RsaPubKey,proto3" json:"RsaPubKey,omitempty"` + RsaPubKey []byte `protobuf:"bytes,2,opt,name=RsaPubKey,proto3" json:"RsaPubKey,omitempty"` // The RSA public key of the sender of this message, // PEM-encoded - Salt []byte `protobuf:"bytes,3,opt,name=Salt,proto3" json:"Salt,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + Salt []byte `protobuf:"bytes,3,opt,name=Salt,proto3" json:"Salt,omitempty"` // Salt used to generate the network ID of the client } -func (m *IdentityAuthentication) Reset() { *m = IdentityAuthentication{} } -func (m *IdentityAuthentication) String() string { return proto.CompactTextString(m) } -func (*IdentityAuthentication) ProtoMessage() {} -func (*IdentityAuthentication) Descriptor() ([]byte, []int) { - return fileDescriptor_authenticated_9ed9358e4abe7a3a, []int{0} -} -func (m *IdentityAuthentication) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_IdentityAuthentication.Unmarshal(m, b) -} -func (m *IdentityAuthentication) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_IdentityAuthentication.Marshal(b, m, deterministic) -} -func (dst *IdentityAuthentication) XXX_Merge(src proto.Message) { - xxx_messageInfo_IdentityAuthentication.Merge(dst, src) +func (x *IdentityAuthentication) Reset() { + *x = IdentityAuthentication{} + if protoimpl.UnsafeEnabled { + mi := &file_authenticated_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *IdentityAuthentication) XXX_Size() int { - return xxx_messageInfo_IdentityAuthentication.Size(m) + +func (x *IdentityAuthentication) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *IdentityAuthentication) XXX_DiscardUnknown() { - xxx_messageInfo_IdentityAuthentication.DiscardUnknown(m) + +func (*IdentityAuthentication) ProtoMessage() {} + +func (x *IdentityAuthentication) ProtoReflect() protoreflect.Message { + mi := &file_authenticated_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -var xxx_messageInfo_IdentityAuthentication proto.InternalMessageInfo +// Deprecated: Use IdentityAuthentication.ProtoReflect.Descriptor instead. +func (*IdentityAuthentication) Descriptor() ([]byte, []int) { + return file_authenticated_proto_rawDescGZIP(), []int{0} +} -func (m *IdentityAuthentication) GetSignature() []byte { - if m != nil { - return m.Signature +func (x *IdentityAuthentication) GetSignature() []byte { + if x != nil { + return x.Signature } return nil } -func (m *IdentityAuthentication) GetRsaPubKey() []byte { - if m != nil { - return m.RsaPubKey +func (x *IdentityAuthentication) GetRsaPubKey() []byte { + if x != nil { + return x.RsaPubKey } return nil } -func (m *IdentityAuthentication) GetSalt() []byte { - if m != nil { - return m.Salt +func (x *IdentityAuthentication) GetSalt() []byte { + if x != nil { + return x.Salt } return nil } -func init() { - proto.RegisterType((*IdentityAuthentication)(nil), "authenticatedConnectionMessages.IdentityAuthentication") +var File_authenticated_proto protoreflect.FileDescriptor + +var file_authenticated_proto_rawDesc = []byte{ + 0x0a, 0x13, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x07, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x22, 0x68, + 0x0a, 0x16, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, + 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x53, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x53, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x52, 0x73, 0x61, 0x50, 0x75, 0x62, + 0x4b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x52, 0x73, 0x61, 0x50, 0x75, + 0x62, 0x4b, 0x65, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x53, 0x61, 0x6c, 0x74, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x04, 0x53, 0x61, 0x6c, 0x74, 0x42, 0x23, 0x5a, 0x21, 0x67, 0x69, 0x74, 0x6c, + 0x61, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x6c, 0x69, 0x78, 0x78, 0x69, 0x72, 0x2f, 0x63, + 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_authenticated_proto_rawDescOnce sync.Once + file_authenticated_proto_rawDescData = file_authenticated_proto_rawDesc +) + +func file_authenticated_proto_rawDescGZIP() []byte { + file_authenticated_proto_rawDescOnce.Do(func() { + file_authenticated_proto_rawDescData = protoimpl.X.CompressGZIP(file_authenticated_proto_rawDescData) + }) + return file_authenticated_proto_rawDescData } -func init() { - proto.RegisterFile("connect/authenticated/authenticated.proto", fileDescriptor_authenticated_9ed9358e4abe7a3a) +var file_authenticated_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_authenticated_proto_goTypes = []interface{}{ + (*IdentityAuthentication)(nil), // 0: connect.IdentityAuthentication +} +var file_authenticated_proto_depIdxs = []int32{ + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name } -var fileDescriptor_authenticated_9ed9358e4abe7a3a = []byte{ - // 180 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xd2, 0x4d, 0xce, 0xcf, 0xcb, - 0x4b, 0x4d, 0x2e, 0xc9, 0xcc, 0xcf, 0x2b, 0xd6, 0x4f, 0x2c, 0x2d, 0xc9, 0x48, 0xcd, 0x2b, 0xc9, - 0x4c, 0x4e, 0x2c, 0x49, 0x4d, 0x41, 0xe5, 0xe9, 0x15, 0x14, 0xe5, 0x97, 0xe4, 0x0b, 0xc9, 0xa3, - 0x08, 0x3a, 0xc3, 0xf5, 0xfa, 0xa6, 0x16, 0x17, 0x27, 0xa6, 0xa7, 0x16, 0x2b, 0x65, 0x70, 0x89, - 0x79, 0xa6, 0x80, 0x14, 0x94, 0x54, 0x3a, 0x22, 0x94, 0x66, 0xe6, 0xe7, 0x09, 0xc9, 0x70, 0x71, - 0x06, 0x67, 0xa6, 0xe7, 0x25, 0x96, 0x94, 0x16, 0xa5, 0x4a, 0x30, 0x2a, 0x30, 0x6a, 0xf0, 0x04, - 0x21, 0x04, 0x40, 0xb2, 0x41, 0xc5, 0x89, 0x01, 0xa5, 0x49, 0xde, 0xa9, 0x95, 0x12, 0x4c, 0x10, - 0x59, 0xb8, 0x80, 0x90, 0x10, 0x17, 0x4b, 0x70, 0x62, 0x4e, 0x89, 0x04, 0x33, 0x58, 0x02, 0xcc, - 0x76, 0x32, 0x8d, 0x32, 0x4e, 0xcf, 0x2c, 0xc9, 0x49, 0x4c, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, - 0xcd, 0xc9, 0xac, 0xa8, 0xc8, 0x2c, 0xd2, 0x4f, 0xce, 0xc9, 0x4c, 0xcd, 0x2b, 0xd1, 0xc7, 0xe9, - 0xab, 0x24, 0x36, 0xb0, 0x47, 0x8c, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0x71, 0x89, 0x27, 0xcf, - 0xf9, 0x00, 0x00, 0x00, +func init() { file_authenticated_proto_init() } +func file_authenticated_proto_init() { + if File_authenticated_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_authenticated_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*IdentityAuthentication); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_authenticated_proto_rawDesc, + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_authenticated_proto_goTypes, + DependencyIndexes: file_authenticated_proto_depIdxs, + MessageInfos: file_authenticated_proto_msgTypes, + }.Build() + File_authenticated_proto = out.File + file_authenticated_proto_rawDesc = nil + file_authenticated_proto_goTypes = nil + file_authenticated_proto_depIdxs = nil } diff --git a/connect/authenticated.proto b/connect/authenticated.proto index 926ca845e35c6a25e91ff4b1d4f477c2eaea5c2d..4a8e8c87b6b8c33cf684d8e8f4c810690e07d643 100644 --- a/connect/authenticated.proto +++ b/connect/authenticated.proto @@ -1,21 +1,24 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// syntax = "proto3"; -package authenticatedConnectionMessages; -option go_package = "gitlab.com/elixxir/client/connect/authenticated"; + +package connect; + +option go_package = "gitlab.com/elixxir/client/connect"; + // Sent by the receiver of the authenticated connection request. message IdentityAuthentication { - bytes Signature = 1; // Signature of the connection fingerprint - // established between the two partners - bytes RsaPubKey = 2; // The RSA public key of the sender of this message, - // PEM-encoded - bytes Salt = 3; // Salt used to generate the network ID of the client + bytes Signature = 1; // Signature of the connection fingerprint + // established between the two partners + bytes RsaPubKey = 2; // The RSA public key of the sender of this message, + // PEM-encoded + bytes Salt = 3; // Salt used to generate the network ID of the client } diff --git a/connect/authenticated_test.go b/connect/authenticated_test.go index d4f5be3d2875ff0841ce91a6f81c4f5ef846c204..2a40522904027498015e3e56eec9d8deebb30e35 100644 --- a/connect/authenticated_test.go +++ b/connect/authenticated_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package connect diff --git a/connect/client.go b/connect/client.go index 809c5da3017ba707dd9037ce624ae1045f3f252f..3c335f3d02398c2b118d00b43fde388b4bd936c1 100644 --- a/connect/client.go +++ b/connect/client.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package connect diff --git a/connect/compileProtobuf.sh b/connect/compileProtobuf.sh new file mode 100644 index 0000000000000000000000000000000000000000..e29b74cf9c8b8e989146d728f9c4a07d4a76d745 --- /dev/null +++ b/connect/compileProtobuf.sh @@ -0,0 +1,14 @@ +#!/bin/bash +################################################################################ +## Copyright © 2022 xx foundation ## +## ## +## Use of this source code is governed by a license that can be found in the ## +## LICENSE file. ## +################################################################################ + +# This script will compile the Protobuf file to a Go file (pb.go). +# This is meant to be called from the top level of the repo. + +cd ./connect/ || return + +protoc --go_out=. --go_opt=paths=source_relative ./authenticated.proto diff --git a/connect/connect.go b/connect/connect.go index ba87dc91873e5d3153e38c60474d42b2f3e23cbc..d786676958b11edc0dd4137e492039c8fa37707e 100644 --- a/connect/connect.go +++ b/connect/connect.go @@ -1,12 +1,14 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2022 Privategrity Corporation / -// / -// All rights reserved. / +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package connect import ( + cryptoE2e "gitlab.com/elixxir/crypto/e2e" "io" "sync/atomic" "time" @@ -22,8 +24,6 @@ import ( "gitlab.com/elixxir/client/e2e/ratchet/partner" "gitlab.com/elixxir/client/e2e/receive" "gitlab.com/elixxir/crypto/contact" - "gitlab.com/elixxir/crypto/e2e" - "gitlab.com/xx_network/primitives/id" ) var alreadyClosedErr = errors.New("connection is closed") @@ -43,7 +43,7 @@ type Connection interface { // SendE2E is a wrapper for sending specifically to the Connection's // partner.Manager SendE2E(mt catalog.MessageType, payload []byte, params clientE2e.Params) ( - []id.Round, e2e.MessageID, time.Time, error) + cryptoE2e.SendReport, error) // RegisterListener is used for E2E reception // and allows for reading data sent from the partner.Manager @@ -221,9 +221,9 @@ func (h *handler) GetPartner() partner.Manager { // SendE2E is a wrapper for sending specifically to the Connection's // partner.Manager. func (h *handler) SendE2E(mt catalog.MessageType, payload []byte, - params clientE2e.Params) ([]id.Round, e2e.MessageID, time.Time, error) { + params clientE2e.Params) (cryptoE2e.SendReport, error) { if h.isClosed() { - return nil, e2e.MessageID{}, time.Time{}, alreadyClosedErr + return cryptoE2e.SendReport{}, alreadyClosedErr } h.updateLastUse(netTime.Now()) diff --git a/connect/connectionList.go b/connect/connectionList.go index fab3404126334ce4c3e0b29f46f9e307a751894e..4d35bd2338f5742961f37c6883de9050feb619c4 100644 --- a/connect/connectionList.go +++ b/connect/connectionList.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package connect diff --git a/connect/connectionList_test.go b/connect/connectionList_test.go index b76c6b35876ee6656b099a46b663a75820db08e5..5a97e78c4509565e4d6e50ce21d732bc0875bddc 100644 --- a/connect/connectionList_test.go +++ b/connect/connectionList_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package connect diff --git a/connect/crypto.go b/connect/crypto.go index 391aa1b2778dd936754182f78f57e5fa80854f39..61714203fb05c659a65ee2517196cc4f583dc080 100644 --- a/connect/crypto.go +++ b/connect/crypto.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package connect import ( diff --git a/connect/crypto_test.go b/connect/crypto_test.go index 633e47a700e98034df89df6f51192a4c6117a790..0d3c163757257a038e309adb4a0e13b8b6aa183f 100644 --- a/connect/crypto_test.go +++ b/connect/crypto_test.go @@ -1,8 +1,9 @@ -//////////////////////////////////////////////////////////////////////////////////////////// -// Copyright © 2022 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the LICENSE file // -//////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package connect diff --git a/connect/generateProto.sh b/connect/generateProto.sh deleted file mode 100755 index b27e351d7d0c5784e9564cfc2b1e6b2ba7889aa6..0000000000000000000000000000000000000000 --- a/connect/generateProto.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash - -# This script will generate the protobuf Golang file (pb.go) out of the protobuf file (.proto). -# This is meant to be called from the top level of the repo. - -protoc --go_out=paths=source_relative:. connections/authenticated/authenticated.proto diff --git a/connect/listenerTracker.go b/connect/listenerTracker.go index 875598dfe53d314cf0052c2ab592ceff425b032c..07f926ba591f0cbe0c384cdf865754d479a09976 100644 --- a/connect/listenerTracker.go +++ b/connect/listenerTracker.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package connect diff --git a/connect/listenerTracker_test.go b/connect/listenerTracker_test.go index 1cab220ad7955c6b25be5b716fc41197eefc055b..f0c69253464c469e8a760b42c71c044f70c07f1b 100644 --- a/connect/listenerTracker_test.go +++ b/connect/listenerTracker_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package connect diff --git a/connect/params_test.go b/connect/params_test.go index 98bb5e2953b5ec570639c0601e78924b7e39c6ec..6d84c7699cd5389850b6725da85fafd49ad6ea77 100644 --- a/connect/params_test.go +++ b/connect/params_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package connect diff --git a/connect/server.go b/connect/server.go index b9f77b28b05b5f9af692fce2f532808a82b02e99..96eb01294a6afb75516bad22026186c933ecdb9c 100644 --- a/connect/server.go +++ b/connect/server.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package connect diff --git a/connect/utils_test.go b/connect/utils_test.go index 6e4be5173d00cd8ba4b671d6abee3a8669e1c77c..86f190808b95d44e80cff854d87be643339f2f0c 100644 --- a/connect/utils_test.go +++ b/connect/utils_test.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package connect import ( @@ -115,8 +122,7 @@ func (m *mockConnection) Close() error { func (m *mockConnection) GetPartner() partner.Manager { return m.partner } func (m *mockConnection) SendE2E( - mt catalog.MessageType, payload []byte, _ e2e.Params) ( - []id.Round, cryptoE2e.MessageID, time.Time, error) { + mt catalog.MessageType, payload []byte, _ e2e.Params) (cryptoE2e.SendReport, error) { m.payloadChan <- payload m.listener.Hear(receive.Message{ MessageType: mt, @@ -124,7 +130,7 @@ func (m *mockConnection) SendE2E( Sender: m.partner.myID, RecipientID: m.partner.partnerId, }) - return nil, cryptoE2e.MessageID{}, time.Time{}, nil + return cryptoE2e.SendReport{}, nil } func (m *mockConnection) RegisterListener( @@ -154,11 +160,17 @@ func (m *mockCmix) Follow(cmix.ClientErrorReport) (stoppable.Stoppable, error) { func (m *mockCmix) GetMaxMessageLength() int { return 4096 } func (m *mockCmix) Send(*id.ID, format.Fingerprint, message.Service, []byte, - []byte, cmix.CMIXParams) (id.Round, ephemeral.Id, error) { - return 0, ephemeral.Id{}, nil + []byte, cmix.CMIXParams) (rounds.Round, ephemeral.Id, error) { + return rounds.Round{}, ephemeral.Id{}, nil } -func (m *mockCmix) SendMany([]cmix.TargetedCmixMessage, cmix.CMIXParams) (id.Round, []ephemeral.Id, error) { - return 0, []ephemeral.Id{}, nil + +func (m *mockCmix) SendWithAssembler(recipient *id.ID, assembler cmix.MessageAssembler, + cmixParams cmix.CMIXParams) (rounds.Round, ephemeral.Id, error) { + return rounds.Round{}, ephemeral.Id{}, nil +} + +func (m *mockCmix) SendMany([]cmix.TargetedCmixMessage, cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error) { + return rounds.Round{}, []ephemeral.Id{}, nil } func (m *mockCmix) AddIdentity(*id.ID, time.Time, bool) {} func (m *mockCmix) RemoveIdentity(*id.ID) {} @@ -183,9 +195,8 @@ func (m *mockCmix) HasNode(*id.ID) bool func (m *mockCmix) NumRegisteredNodes() int { return 24 } func (m *mockCmix) TriggerNodeRegistration(*id.ID) {} -func (m *mockCmix) GetRoundResults(_ time.Duration, roundCallback cmix.RoundEventCallback, _ ...id.Round) error { +func (m *mockCmix) GetRoundResults(_ time.Duration, roundCallback cmix.RoundEventCallback, _ ...id.Round) { roundCallback(true, false, nil) - return nil } func (m *mockCmix) LookupHistoricalRound(id.Round, rounds.RoundResultCallback) error { return nil } diff --git a/dummy/manager.go b/dummy/manager.go index 4832f3ef505ea37114c2f4d202c82604ddd7eab0..83feb81d324b560dc3850469f0a1acc2c852e52c 100644 --- a/dummy/manager.go +++ b/dummy/manager.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// // Package dummy allows for the sending of dummy messages to dummy recipients @@ -12,7 +12,7 @@ package dummy import ( "github.com/pkg/errors" - "gitlab.com/elixxir/client/interfaces" + "gitlab.com/elixxir/client/cmix" "gitlab.com/elixxir/client/stoppable" "gitlab.com/elixxir/client/storage" "gitlab.com/elixxir/client/xxdk" @@ -21,20 +21,25 @@ import ( "time" ) +// Manager related thread handling constants. const ( + // The name of the Manager's stoppable.Stoppable dummyTrafficStoppableName = "DummyTraffic" - statusChanLen = 100 + + // The amount of statuses in queue that can be placed + // by Manager.SetStatus. + statusChanLen = 100 ) -// Thread status. +// The thread status values. const ( - notStarted uint32 = iota - running - paused - stopped + notStarted uint32 = iota // Sending thread has not been started + running // Sending thread is currently operating + paused // Sending thread is temporarily halted. + stopped // Sending thread is halted. ) -// Error messages. +// Error messages for Manager. const ( setStatusErr = "Failed to change status of dummy traffic send thread to %t: channel full" ) @@ -56,27 +61,41 @@ type Manager struct { // Pauses/Resumes the dummy send thread when triggered statusChan chan bool - // Cmix interfaces - net *xxdk.Cmix - store *storage.Session - networkManager interfaces.NetworkManager - rng *fastRNG.StreamGenerator + // Interfaces + net cmix.Client + store storage.Session + + // Generates + rng *fastRNG.StreamGenerator } -// NewManager creates a new dummy Manager with the specified average send delta -// and the range used for generating random durations. -func NewManager(maxNumMessages int, avgSendDelta, randomRange time.Duration, - net *xxdk.Cmix, manager interfaces.NetworkManager) *Manager { - clientStorage := net.GetStorage() - return newManager(maxNumMessages, avgSendDelta, randomRange, net, - &clientStorage, manager, net.GetRng()) +// NewManager creates a Manager object and initialises the +// dummy traffic sending thread. Note that the Manager does not start sending dummy +// traffic until `True` is passed into Manager.SetStatus. The time duration +// between each sending operation and the amount of messages sent each interval +// are randomly generated values with bounds defined by the +// given parameters below. +// +// Params: +// - maxNumMessages - the upper bound of the random number of messages sent +// each sending cycle. +// - avgSendDeltaMS - the average duration, in milliseconds, to wait +// between sends. +// - randomRangeMS - the upper bound of the interval between sending cycles, +// in milliseconds. Sends occur every avgSendDeltaMS +/- a random duration +// with an upper bound of randomRangeMS. +func NewManager(maxNumMessages int, + avgSendDelta, randomRange time.Duration, + net *xxdk.Cmix) *Manager { + + return newManager(maxNumMessages, avgSendDelta, randomRange, net.GetCmix(), + net.GetStorage(), net.GetRng()) } // newManager builds a new dummy Manager from fields explicitly passed in. This -// function is a helper function for NewManager to make it easier to test. +// function is a helper function for NewManager. func newManager(maxNumMessages int, avgSendDelta, randomRange time.Duration, - net *xxdk.Cmix, store *storage.Session, networkManager interfaces.NetworkManager, - rng *fastRNG.StreamGenerator) *Manager { + net cmix.Client, store storage.Session, rng *fastRNG.StreamGenerator) *Manager { return &Manager{ maxNumMessages: maxNumMessages, avgSendDelta: avgSendDelta, @@ -85,13 +104,12 @@ func newManager(maxNumMessages int, avgSendDelta, randomRange time.Duration, statusChan: make(chan bool, statusChanLen), net: net, store: store, - networkManager: networkManager, rng: rng, } } // StartDummyTraffic starts the process of sending dummy traffic. This function -// matches the xxdk.Service type. +// adheres to xxdk.Service. func (m *Manager) StartDummyTraffic() (stoppable.Stoppable, error) { stop := stoppable.NewSingle(dummyTrafficStoppableName) go m.sendThread(stop) @@ -99,13 +117,19 @@ func (m *Manager) StartDummyTraffic() (stoppable.Stoppable, error) { return stop, nil } -// SetStatus sets the state of the dummy traffic send thread, which determines -// if the thread is running or paused. The possible statuses are: -// true = send thread is sending dummy messages -// false = send thread is paused/stopped and not sending dummy messages -// Returns an error if the channel is full. -// Note that this function cannot change the status of the send thread if it has -// yet to be started via StartDummyTraffic or if it has been stopped. +// SetStatus sets the state of the dummy traffic send thread by passing in +// a boolean parameter. There may be a small delay in between this call +// and the status of the sending thread to change accordingly. For example, +// passing False into this call while the sending thread is currently sending messages +// will not cancel nor halt the sending operation, but will pause the thread once that +// operation has completed. +// +// Params: +// - boolean - Input should be true if you want to send dummy messages. +// Input should be false if you want to pause dummy messages. +// Returns: +// - error - if the Manager.SetStatus is called too frequently, causing the +// internal status channel to fill. func (m *Manager) SetStatus(status bool) error { select { case m.statusChan <- status: @@ -115,13 +139,16 @@ func (m *Manager) SetStatus(status bool) error { } } -// GetStatus returns the current state of the dummy traffic send thread. It has -// the following return values: -// true = send thread is sending dummy messages -// false = send thread is paused/stopped and not sending dummy messages -// Note that this function does not return the status set by SetStatus directly; -// it returns the current status of the send thread, which means any call to -// SetStatus will have a small delay before it is returned by GetStatus. +// GetStatus returns the current state of the Manager's sending thread. +// Note that this function does not return the status set by the most recent call to +// SetStatus. Instead, this call returns the current status of the sending thread. +// This is due to the small delay that may occur between calling SetStatus and the +// sending thread taking into effect that status change. +// +// Returns: +// - boolean - Returns true if sending thread is sending dummy messages. +// Returns false if sending thread is paused/stopped and is +// not sending dummy messages. func (m *Manager) GetStatus() bool { switch atomic.LoadUint32(&m.status) { case running: diff --git a/dummy/manager_test.go b/dummy/manager_test.go index 6a49bcc6a597ebf476ee8bbfb8f45a79045a4488..c36b2a596292f35104e69be797ef999f3f3ada3e 100644 --- a/dummy/manager_test.go +++ b/dummy/manager_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package dummy @@ -27,7 +27,7 @@ func Test_newManager(t *testing.T) { } received := newManager(expected.maxNumMessages, expected.avgSendDelta, - expected.randomRange, nil, nil, nil, nil) + expected.randomRange, nil, nil, nil) if statusChanLen != cap(received.statusChan) { t.Errorf("Capacity of status channel unexpected."+ @@ -45,7 +45,7 @@ func Test_newManager(t *testing.T) { // Tests that Manager.StartDummyTraffic sends dummy messages and that it stops // when the stoppable is closed. func TestManager_StartDummyTraffic(t *testing.T) { - m := newTestManager(10, 50*time.Millisecond, 10*time.Millisecond, false, t) + m := newTestManager(10, 50*time.Millisecond, 10*time.Millisecond, t) err := m.SetStatus(true) if err != nil { @@ -59,7 +59,7 @@ func TestManager_StartDummyTraffic(t *testing.T) { msgChan := make(chan bool) go func() { - for m.networkManager.(*testNetworkManager).GetMsgListLen() == 0 { + for m.net.(*mockCmix).GetMsgListLen() == 0 { time.Sleep(5 * time.Millisecond) } msgChan <- true @@ -71,7 +71,7 @@ func TestManager_StartDummyTraffic(t *testing.T) { t.Errorf("Timed out after %s waiting for messages to be sent.", 3*m.avgSendDelta) case <-msgChan: - numReceived += m.networkManager.(*testNetworkManager).GetMsgListLen() + numReceived += m.net.(*mockCmix).GetMsgListLen() } err = stop.Close() @@ -86,7 +86,7 @@ func TestManager_StartDummyTraffic(t *testing.T) { msgChan = make(chan bool) go func() { - for m.networkManager.(*testNetworkManager).GetMsgListLen() == numReceived { + for m.net.(*mockCmix).GetMsgListLen() == numReceived { time.Sleep(5 * time.Millisecond) } msgChan <- true @@ -104,7 +104,7 @@ func TestManager_StartDummyTraffic(t *testing.T) { // can be called multiple times with the same status without it affecting // anything. Also tests that the thread quits even when paused. func TestManager_SetStatus(t *testing.T) { - m := newTestManager(10, 50*time.Millisecond, 10*time.Millisecond, false, t) + m := newTestManager(10, 50*time.Millisecond, 10*time.Millisecond, t) err := m.SetStatus(false) if err != nil { @@ -118,10 +118,10 @@ func TestManager_SetStatus(t *testing.T) { go func() { var numReceived int for i := 0; i < 2; i++ { - for m.networkManager.(*testNetworkManager).GetMsgListLen() == numReceived { + for m.net.(*mockCmix).GetMsgListLen() == numReceived { time.Sleep(5 * time.Millisecond) } - numReceived = m.networkManager.(*testNetworkManager).GetMsgListLen() + numReceived = m.net.(*mockCmix).GetMsgListLen() msgChan <- true } }() @@ -161,7 +161,7 @@ func TestManager_SetStatus(t *testing.T) { t.Errorf("Timed out after %s waiting for messages to be sent.", 3*m.avgSendDelta) case <-msgChan: - numReceived += m.networkManager.(*testNetworkManager).GetMsgListLen() + numReceived += m.net.(*mockCmix).GetMsgListLen() } // Setting status to true multiple times does not interrupt sending @@ -177,10 +177,10 @@ func TestManager_SetStatus(t *testing.T) { t.Errorf("Timed out after %s waiting for messages to be sent.", 3*m.avgSendDelta) case <-msgChan: - if m.networkManager.(*testNetworkManager).GetMsgListLen() <= numReceived { + if m.net.(*mockCmix).GetMsgListLen() <= numReceived { t.Errorf("Failed to receive second send."+ "\nmessages on last receive: %d\nmessages on this receive: %d", - numReceived, m.networkManager.(*testNetworkManager).GetMsgListLen()) + numReceived, m.net.(*mockCmix).GetMsgListLen()) } } @@ -213,7 +213,7 @@ func TestManager_SetStatus(t *testing.T) { // Error path: tests that Manager.SetStatus returns an error if the status // cannot be set. func TestManager_SetStatus_ChannelError(t *testing.T) { - m := newTestManager(10, 50*time.Millisecond, 10*time.Millisecond, false, t) + m := newTestManager(10, 50*time.Millisecond, 10*time.Millisecond, t) // Send the max number of status changes on the channel for i := 0; i < statusChanLen; i++ { @@ -236,7 +236,7 @@ func TestManager_SetStatus_ChannelError(t *testing.T) { // Tests that Manager.GetStatus gets the correct status before the send thread // starts, while sending, while paused, and after it is stopped. func TestManager_GetStatus(t *testing.T) { - m := newTestManager(10, 50*time.Millisecond, 10*time.Millisecond, false, t) + m := newTestManager(10, 50*time.Millisecond, 10*time.Millisecond, t) err := m.SetStatus(false) if err != nil { @@ -254,10 +254,10 @@ func TestManager_GetStatus(t *testing.T) { go func() { var numReceived int for i := 0; i < 2; i++ { - for m.networkManager.(*testNetworkManager).GetMsgListLen() == numReceived { + for m.net.(*mockCmix).GetMsgListLen() == numReceived { time.Sleep(5 * time.Millisecond) } - numReceived = m.networkManager.(*testNetworkManager).GetMsgListLen() + numReceived = m.net.(*mockCmix).GetMsgListLen() msgChan <- true } }() @@ -292,7 +292,7 @@ func TestManager_GetStatus(t *testing.T) { t.Errorf("Timed out after %s waiting for messages to be sent.", 3*m.avgSendDelta) case <-msgChan: - numReceived += m.networkManager.(*testNetworkManager).GetMsgListLen() + numReceived += m.net.(*mockCmix).GetMsgListLen() } // Setting status to true multiple times does not interrupt sending @@ -311,10 +311,10 @@ func TestManager_GetStatus(t *testing.T) { t.Errorf("Timed out after %s waiting for messages to be sent.", 3*m.avgSendDelta) case <-msgChan: - if m.networkManager.(*testNetworkManager).GetMsgListLen() <= numReceived { + if m.net.(*mockCmix).GetMsgListLen() <= numReceived { t.Errorf("Failed to receive second send."+ "\nmessages on last receive: %d\nmessages on this receive: %d", - numReceived, m.networkManager.(*testNetworkManager).GetMsgListLen()) + numReceived, m.net.(*mockCmix).GetMsgListLen()) } } diff --git a/dummy/mockCmix_test.go b/dummy/mockCmix_test.go new file mode 100644 index 0000000000000000000000000000000000000000..96bab83384e0d57d84d50c5cac95ce71bc9fb7df --- /dev/null +++ b/dummy/mockCmix_test.go @@ -0,0 +1,233 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + +package dummy + +import ( + "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" + "gitlab.com/elixxir/client/stoppable" + "gitlab.com/elixxir/comms/network" + "gitlab.com/elixxir/primitives/format" + "gitlab.com/xx_network/comms/connect" + "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/id/ephemeral" + "sync" + "time" +) + +// mockCmix is a testing structure that adheres to cmix.Client. +type mockCmix struct { + messages map[id.ID]format.Message + sync.RWMutex + payloadSize int +} + +func newMockCmix(payloadSize int) cmix.Client { + + return &mockCmix{ + messages: make(map[id.ID]format.Message), + payloadSize: payloadSize, + } +} + +func (m *mockCmix) Send(recipient *id.ID, fingerprint format.Fingerprint, service message.Service, payload, mac []byte, cmixParams cmix.CMIXParams) (rounds.Round, ephemeral.Id, error) { + m.Lock() + defer m.Unlock() + m.messages[*recipient] = generateMessage(m.payloadSize, fingerprint, service, payload, mac) + + return rounds.Round{}, ephemeral.Id{}, nil +} + +func (m *mockCmix) SendWithAssembler(recipient *id.ID, assembler cmix.MessageAssembler, + cmixParams cmix.CMIXParams) (rounds.Round, ephemeral.Id, error) { + m.Lock() + defer m.Unlock() + + fingerprint, service, payload, mac, err := assembler(42) + if err != nil { + return rounds.Round{}, ephemeral.Id{}, err + } + m.messages[*recipient] = generateMessage(m.payloadSize, fingerprint, service, payload, mac) + + return rounds.Round{}, ephemeral.Id{}, nil +} + +func (m *mockCmix) GetMsgListLen() int { + m.RLock() + defer m.RUnlock() + return len(m.messages) +} + +func (m *mockCmix) GetMsgList() map[id.ID]format.Message { + m.RLock() + defer m.RUnlock() + return m.messages +} + +func (m mockCmix) Follow(report cmix.ClientErrorReport) (stoppable.Stoppable, error) { + //TODO implement me + panic("implement me") +} + +func (m mockCmix) GetMaxMessageLength() int { + //TODO implement me + panic("implement me") +} + +func (m *mockCmix) SendMany(messages []cmix.TargetedCmixMessage, p cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error) { + //TODO implement me + panic("implement me") +} + +func (m *mockCmix) AddIdentity(id *id.ID, validUntil time.Time, persistent bool) { + //TODO implement me + panic("implement me") +} + +func (m *mockCmix) RemoveIdentity(id *id.ID) { + //TODO implement me + panic("implement me") +} + +func (m mockCmix) GetIdentity(get *id.ID) (identity.TrackedID, error) { + //TODO implement me + panic("implement me") +} + +func (m mockCmix) AddFingerprint(identity *id.ID, fingerprint format.Fingerprint, mp message.Processor) error { + //TODO implement me + panic("implement me") +} + +func (m mockCmix) DeleteFingerprint(identity *id.ID, fingerprint format.Fingerprint) { + //TODO implement me + panic("implement me") +} + +func (m mockCmix) DeleteClientFingerprints(identity *id.ID) { + //TODO implement me + panic("implement me") +} + +func (m mockCmix) AddService(clientID *id.ID, newService message.Service, response message.Processor) { + //TODO implement me + panic("implement me") +} + +func (m mockCmix) DeleteService(clientID *id.ID, toDelete message.Service, processor message.Processor) { + //TODO implement me + panic("implement me") +} + +func (m mockCmix) DeleteClientService(clientID *id.ID) { + //TODO implement me + panic("implement me") +} + +func (m mockCmix) TrackServices(tracker message.ServicesTracker) { + //TODO implement me + panic("implement me") +} + +func (m mockCmix) CheckInProgressMessages() { + //TODO implement me + panic("implement me") +} + +func (m mockCmix) IsHealthy() bool { + //TODO implement me + panic("implement me") +} + +func (m mockCmix) WasHealthy() bool { + //TODO implement me + panic("implement me") +} + +func (m mockCmix) AddHealthCallback(f func(bool)) uint64 { + //TODO implement me + panic("implement me") +} + +func (m mockCmix) RemoveHealthCallback(u uint64) { + //TODO implement me + panic("implement me") +} + +func (m mockCmix) HasNode(nid *id.ID) bool { + //TODO implement me + panic("implement me") +} + +func (m mockCmix) NumRegisteredNodes() int { + //TODO implement me + panic("implement me") +} + +func (m mockCmix) TriggerNodeRegistration(nid *id.ID) { + //TODO implement me + panic("implement me") +} + +func (m mockCmix) GetRoundResults(timeout time.Duration, roundCallback cmix.RoundEventCallback, roundList ...id.Round) { + //TODO implement me + panic("implement me") +} + +func (m mockCmix) LookupHistoricalRound(rid id.Round, callback rounds.RoundResultCallback) error { + //TODO implement me + panic("implement me") +} + +func (m mockCmix) SendToAny(sendFunc func(host *connect.Host) (interface{}, error), stop *stoppable.Single) (interface{}, error) { + //TODO implement me + panic("implement me") +} + +func (m mockCmix) SendToPreferred(targets []*id.ID, sendFunc gateway.SendToPreferredFunc, stop *stoppable.Single, timeout time.Duration) (interface{}, error) { + //TODO implement me + panic("implement me") +} + +func (m mockCmix) SetGatewayFilter(f gateway.Filter) { + //TODO implement me + panic("implement me") +} + +func (m mockCmix) GetHostParams() connect.HostParams { + //TODO implement me + panic("implement me") +} + +func (m mockCmix) GetAddressSpace() uint8 { + //TODO implement me + panic("implement me") +} + +func (m mockCmix) RegisterAddressSpaceNotification(tag string) (chan uint8, error) { + //TODO implement me + panic("implement me") +} + +func (m mockCmix) UnregisterAddressSpaceNotification(tag string) { + //TODO implement me + panic("implement me") +} + +func (m mockCmix) GetInstance() *network.Instance { + //TODO implement me + panic("implement me") +} + +func (m mockCmix) GetVerboseRounds() string { + //TODO implement me + panic("implement me") +} diff --git a/dummy/random.go b/dummy/random.go index 8c8a87a6cc0328f136f2444125cde62c92972a0b..2a41d8243decc43ae56ae93068c5106a8f9371e7 100644 --- a/dummy/random.go +++ b/dummy/random.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package dummy @@ -10,42 +10,77 @@ package dummy import ( "encoding/binary" "github.com/pkg/errors" + "gitlab.com/elixxir/client/cmix/message" "gitlab.com/elixxir/primitives/format" "gitlab.com/xx_network/crypto/csprng" + "gitlab.com/xx_network/primitives/id" "time" ) // Error messages. +// Error constants for Manager.newRandomCmixMessage and it's helper functions.. const ( payloadSizeRngErr = "failed to generate random payload size: %+v" + payloadRngErr = "failed to generate random payload: %+v" + fingerprintRngErr = "failed to generate random fingerprint: %+v" + macRngErr = "failed to generate random MAC: %+v" + recipientRngErr = "failed to generate random recipient: %+v" ) -// intRng returns, as an int, a non-negative, non-zero random number in [1, n) -// from the csprng.Source. -func intRng(n int, rng csprng.Source) (int, error) { - v, err := csprng.Generate(8, rng) +// newRandomCmixMessage returns random format.Message data. +// +// Returns in order a: +// - Recipient (id.ID) +// - Message fingerprint (format.Fingerprint) +// - Message service (message.Service) +// - Payload ([]byte) +// - MAC ([]byte) +// - Error if there was an issue randomly generating any of the above data. +// The error will specify which of the above failed to be randomly generated. +func (m *Manager) newRandomCmixMessage(rng csprng.Source) ( + recipient *id.ID, fingerprint format.Fingerprint, + service message.Service, + payload, mac []byte, err error) { + + // Generate random recipient + recipient, err = id.NewRandomID(rng, id.User) if err != nil { - return 0, err + return nil, format.Fingerprint{}, message.Service{}, nil, nil, + errors.Errorf(recipientRngErr, err) } - return int(binary.LittleEndian.Uint64(v)%uint64(n-1)) + 1, nil -} + // Generate random message payload + payloadSize := m.store.GetCmixGroup().GetP().ByteLen() + payload, err = newRandomPayload(payloadSize, rng) + if err != nil { + return nil, format.Fingerprint{}, message.Service{}, nil, nil, + errors.Errorf(payloadRngErr, err) + } -// durationRng returns a duration that is the base duration plus or minus a -// random duration of max randomRange. -func durationRng(base, randomRange time.Duration, rng csprng.Source) ( - time.Duration, error) { - delta, err := intRng(int(2*randomRange), rng) + // Generate random fingerprint + fingerprint, err = newRandomFingerprint(rng) if err != nil { - return 0, err + return nil, format.Fingerprint{}, message.Service{}, nil, nil, + errors.Errorf(fingerprintRngErr, err) } - return base + randomRange - time.Duration(delta), nil + // Generate random MAC + mac, err = newRandomMAC(rng) + if err != nil { + return nil, format.Fingerprint{}, message.Service{}, nil, nil, + errors.Errorf(macRngErr, err) + } + + // Generate random service + service = message.GetRandomService(rng) + + return } -// newRandomPayload generates a random payload of a random length. +// newRandomPayload generates a random payload of a random length +// within the maxPayloadSize. func newRandomPayload(maxPayloadSize int, rng csprng.Source) ([]byte, error) { // Generate random payload size - randomPayloadSize, err := intRng(maxPayloadSize, rng) + randomPayloadSize, err := randomInt(maxPayloadSize, rng) if err != nil { return nil, errors.Errorf(payloadSizeRngErr, err) } @@ -86,3 +121,32 @@ func newRandomMAC(rng csprng.Source) ([]byte, error) { return mac, nil } + +////////////////////////////////////////////////////////////////////////////////// +// Miscellaneous +////////////////////////////////////////////////////////////////////////////////// + +// randomDuration returns a duration that is the base duration plus or minus a +// random duration of max randomRange. +func randomDuration(base, randomRange time.Duration, rng csprng.Source) ( + time.Duration, error) { + + // Generate a random duration + delta, err := randomInt(int(2*randomRange), rng) + if err != nil { + return 0, err + } + + return base + randomRange - time.Duration(delta), nil +} + +// randomInt returns, as an int, a non-negative, non-zero random number in [1, n) +// from the csprng.Source. +func randomInt(n int, rng csprng.Source) (int, error) { + v, err := csprng.Generate(8, rng) + if err != nil { + return 0, err + } + + return int(binary.LittleEndian.Uint64(v)%uint64(n-1)) + 1, nil +} diff --git a/dummy/random_test.go b/dummy/random_test.go index 661986a0416993e211209d009a023c451dd3ff60..fab84c22fc0e552931026ec0f27cc0c07e511b32 100644 --- a/dummy/random_test.go +++ b/dummy/random_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package dummy @@ -13,7 +13,7 @@ import ( "time" ) -// Consistency test: tests that intRng returns the expected int when using a +// Consistency test: tests that randomInt returns the expected int when using a // PRNG and that the result is not larger than the max. func Test_intRng_Consistency(t *testing.T) { expectedInts := []int{15, 1, 35, 13, 42, 52, 57, 3, 48} @@ -22,9 +22,9 @@ func Test_intRng_Consistency(t *testing.T) { max := 64 for i, expected := range expectedInts { - v, err := intRng(max, prng) + v, err := randomInt(max, prng) if err != nil { - t.Errorf("intRng returned an error (%d): %+v", i, err) + t.Errorf("randomInt returned an error (%d): %+v", i, err) } if v != expected { @@ -40,7 +40,7 @@ func Test_intRng_Consistency(t *testing.T) { } } -// Consistency test: tests that durationRng returns the expected int when using +// Consistency test: tests that randomDuration returns the expected int when using // a PRNG and that the result is within the allowed range. func Test_durationRng_Consistency(t *testing.T) { expectedDurations := []time.Duration{ @@ -52,9 +52,9 @@ func Test_durationRng_Consistency(t *testing.T) { base, randomRange := time.Minute, 15*time.Second for i, expected := range expectedDurations { - v, err := durationRng(base, randomRange, prng) + v, err := randomDuration(base, randomRange, prng) if err != nil { - t.Errorf("durationRng returned an error (%d): %+v", i, err) + t.Errorf("randomDuration returned an error (%d): %+v", i, err) } if v != expected { diff --git a/dummy/send.go b/dummy/send.go index 84271b67ea4310bf91af057a58ffe2256520460a..ac6b39796add64bbfed8be9ed8c3e3f8687904f8 100644 --- a/dummy/send.go +++ b/dummy/send.go @@ -1,199 +1,144 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package dummy import ( + "gitlab.com/elixxir/client/cmix" + "gitlab.com/xx_network/crypto/csprng" "sync" "sync/atomic" "time" "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" - "gitlab.com/elixxir/client/cmix" "gitlab.com/elixxir/client/stoppable" - "gitlab.com/elixxir/primitives/format" - "gitlab.com/xx_network/crypto/csprng" - "gitlab.com/xx_network/primitives/id" ) -// Error messages. +// Error messages for the Manager.sendThread and its helper functions. const ( - numMsgsRngErr = "failed to generate random number of messages to send: %+v" - payloadRngErr = "failed to generate random payload: %+v" - recipientRngErr = "failed to generate random recipient: %+v" - fingerprintRngErr = "failed to generate random fingerprint: %+v" - macRngErr = "failed to generate random MAC: %+v" + numMsgsRngErr = "failed to generate random number of messages to send: %+v" ) // sendThread is a thread that sends the dummy messages at random intervals. func (m *Manager) sendThread(stop *stoppable.Single) { - jww.DEBUG.Print("Starting dummy traffic sending thread.") + jww.INFO.Print("Starting dummy traffic sending thread.") nextSendChan := make(<-chan time.Time) nextSendChanPtr := &(nextSendChan) for { select { - case <-stop.Quit(): - m.stopSendThread(stop) - return case status := <-m.statusChan: if status { atomic.StoreUint32(&m.status, running) - nextSendChanPtr = &(m.randomTimer().C) + // Generate random duration + rng := m.rng.GetStream() + duration, err := randomDuration(m.avgSendDelta, m.randomRange, rng) + if err != nil { + rng.Close() + jww.FATAL.Panicf("Failed to generate random sending interval: %+v", err) + } + rng.Close() + + // Create timer + nextSendChanPtr = &(time.NewTimer(duration).C) + } else { atomic.StoreUint32(&m.status, paused) nextSendChan = make(<-chan time.Time) nextSendChanPtr = &nextSendChan } case <-*nextSendChanPtr: - nextSendChanPtr = &(m.randomTimer().C) - - go func() { - // get list of random messages and recipients - rng := m.rng.GetStream() - msgs, err := m.newRandomMessages(rng) - if err != nil { - jww.FATAL.Panicf("Failed to generate dummy messages: %+v", err) - } + // Generate random duration + rng := m.rng.GetStream() + duration, err := randomDuration(m.avgSendDelta, m.randomRange, rng) + if err != nil { rng.Close() + jww.FATAL.Panicf("Failed to generate random sending interval: %+v", err) + } + rng.Close() + + // Create timer + nextSendChanPtr = &(time.NewTimer(duration).C) - err = m.sendMessages(msgs) + // Send messages + go func() { + err := m.sendMessages() if err != nil { - jww.FATAL.Panicf("Failed to send dummy messages: %+v", err) + jww.ERROR.Printf("Failed to send dummy messages: %+v", err) } }() + case <-stop.Quit(): + m.stopSendThread(stop) + return } } } -// stopSendThread is triggered when the stoppable is triggered. It prints a -// debug message, sets the thread status to stopped, and sets the status of the -// stoppable to stopped. -func (m *Manager) stopSendThread(stop *stoppable.Single) { - jww.DEBUG.Print( - "Stopping dummy traffic sending thread: stoppable triggered") - atomic.StoreUint32(&m.status, stopped) - stop.ToStopped() -} - // sendMessages generates and sends random messages. -func (m *Manager) sendMessages(msgs map[id.ID]format.Message) error { - var sent, i int64 +func (m *Manager) sendMessages() error { + var sent int64 var wg sync.WaitGroup - for recipient, msg := range msgs { - wg.Add(1) + // Randomly generate amount of messages to send + rng := m.rng.GetStream() + defer rng.Close() + numMessages, err := randomInt(m.maxNumMessages+1, rng) + if err != nil { + return errors.Errorf(numMsgsRngErr, err) + } - go func(i int64, recipient id.ID, msg format.Message) { + for i := 0; i < numMessages; i++ { + wg.Add(1) + go func(localIndex, totalMessages int) { defer wg.Done() - // Fill the preimage with random data to ensure it is not repeatable - p := cmix.GetDefaultParams() - // FIXME: these fields no longer available - // through these params objects - // p.IdentityPreimage = make([]byte, 32) - // rng := m.rng.GetStream() - // if _, err := rng.Read(p.IdentityPreimage); err != nil { - // jww.FATAL.Panicf("Failed to generate data for random identity "+ - // "preimage in e2e send: %+v", err) - // } - // rng.Close() - // p.DebugTag = "dummy" - _, _, err := m.networkManager.SendCMIX(msg, &recipient, p) + err = m.sendMessage(localIndex, totalMessages, rng) if err != nil { - jww.WARN.Printf("Failed to send dummy message %d/%d via "+ - "Send: %+v", i, len(msgs), err) - } else { - atomic.AddInt64(&sent, 1) + jww.ERROR.Printf("Failed to send message %d/%d: %+v", + localIndex, numMessages, err) } - }(i, recipient, msg) - - i++ + // Add to counter of successful sends + atomic.AddInt64(&sent, 1) + }(i, numMessages) } wg.Wait() - - jww.INFO.Printf("Sent %d/%d dummy messages.", sent, len(msgs)) - + jww.INFO.Printf("Sent %d/%d dummy messages.", sent, numMessages) return nil } -// newRandomMessages returns a map of a random recipients and random messages of -// a randomly generated length in [1, Manager.maxNumMessages]. -func (m *Manager) newRandomMessages(rng csprng.Source) ( - map[id.ID]format.Message, error) { - numMessages, err := intRng(m.maxNumMessages+1, rng) - if err != nil { - return nil, errors.Errorf(numMsgsRngErr, err) - } - - msgs := make(map[id.ID]format.Message, numMessages) - - for i := 0; i < numMessages; i++ { - // Generate random recipient - recipient, err := id.NewRandomID(rng, id.User) - if err != nil { - return nil, errors.Errorf(recipientRngErr, err) - } - - msgs[*recipient], err = m.newRandomCmixMessage(rng) - if err != nil { - return nil, err - } - } - - return msgs, nil -} - -// newRandomCmixMessage returns a new cMix message filled with a randomly -// generated payload, fingerprint, and MAC. -func (m *Manager) newRandomCmixMessage(rng csprng.Source) (format.Message, error) { - // Create new empty cMix message - clientStorage := *m.store - cMixMsg := format.NewMessage(clientStorage.GetCmixGroup().GetP().ByteLen()) - - // Generate random message - randomMsg, err := newRandomPayload(cMixMsg.ContentsSize(), rng) +// sendMessage is a helper function which generates a sends a single random format.Message +// to a random recipient. +func (m *Manager) sendMessage(index, totalMessages int, rng csprng.Source) error { + // Generate message data + recipient, fp, service, payload, mac, err := m.newRandomCmixMessage(rng) if err != nil { - return format.Message{}, errors.Errorf(payloadRngErr, err) + return errors.Errorf("Failed to create random data: %+v", err) } - // Generate random fingerprint - fingerprint, err := newRandomFingerprint(rng) + // Send message + p := cmix.GetDefaultCMIXParams() + _, _, err = m.net.Send(recipient, fp, service, payload, mac, p) if err != nil { - return format.Message{}, errors.Errorf(fingerprintRngErr, err) + return errors.Errorf("Failed to send message: %+v", err) } - // Generate random MAC - mac, err := newRandomMAC(rng) - if err != nil { - return format.Message{}, errors.Errorf(macRngErr, err) - } - - // Set contents, fingerprint, and MAC, of the cMix message - cMixMsg.SetContents(randomMsg) - cMixMsg.SetKeyFP(fingerprint) - cMixMsg.SetMac(mac) - - return cMixMsg, nil + return nil } -// randomTimer generates a timer that will trigger after a random duration. -func (m *Manager) randomTimer() *time.Timer { - rng := m.rng.GetStream() - - duration, err := durationRng(m.avgSendDelta, m.randomRange, rng) - if err != nil { - jww.FATAL.Panicf("Failed to generate random duration to wait to send "+ - "dummy messages: %+v", err) - } - - return time.NewTimer(duration) +// stopSendThread is triggered when the stoppable is triggered. It prints a +// debug message, sets the thread status to stopped, and sets the status of the +// stoppable to stopped. +func (m *Manager) stopSendThread(stop *stoppable.Single) { + jww.DEBUG.Print( + "Stopping dummy traffic sending thread: stoppable triggered") + atomic.StoreUint32(&m.status, stopped) + stop.ToStopped() } diff --git a/dummy/send_test.go b/dummy/send_test.go index 9af8ee8796e4d76faa7d45188c60db271d772335..edc4b4e2f83f41da04dfe12c2111fc553fc528c9 100644 --- a/dummy/send_test.go +++ b/dummy/send_test.go @@ -1,15 +1,14 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package dummy import ( "bytes" - "encoding/base64" "gitlab.com/elixxir/client/stoppable" "gitlab.com/elixxir/primitives/format" "gitlab.com/xx_network/primitives/id" @@ -21,7 +20,7 @@ import ( // Tests that Manager.sendThread sends multiple sets of messages. func TestManager_sendThread(t *testing.T) { - m := newTestManager(10, 50*time.Millisecond, 10*time.Millisecond, false, t) + m := newTestManager(10, 50*time.Millisecond, 10*time.Millisecond, t) stop := stoppable.NewSingle("sendThreadTest") go m.sendThread(stop) @@ -40,10 +39,10 @@ func TestManager_sendThread(t *testing.T) { go func() { var numReceived int for i := 0; i < 2; i++ { - for m.networkManager.(*testNetworkManager).GetMsgListLen() == numReceived { + for m.net.(*mockCmix).GetMsgListLen() == numReceived { time.Sleep(5 * time.Millisecond) } - numReceived = m.networkManager.(*testNetworkManager).GetMsgListLen() + numReceived = m.net.(*mockCmix).GetMsgListLen() msgChan <- true } }() @@ -54,7 +53,7 @@ func TestManager_sendThread(t *testing.T) { t.Errorf("Timed out after %s waiting for messages to be sent.", 3*m.avgSendDelta) case <-msgChan: - numReceived += m.networkManager.(*testNetworkManager).GetMsgListLen() + numReceived += m.net.(*mockCmix).GetMsgListLen() } select { @@ -62,10 +61,10 @@ func TestManager_sendThread(t *testing.T) { t.Errorf("Timed out after %s waiting for messages to be sent.", 3*m.avgSendDelta) case <-msgChan: - if m.networkManager.(*testNetworkManager).GetMsgListLen() <= numReceived { + if m.net.(*mockCmix).GetMsgListLen() <= numReceived { t.Errorf("Failed to receive second send."+ "\nmessages on last receive: %d\nmessages on this receive: %d", - numReceived, m.networkManager.(*testNetworkManager).GetMsgListLen()) + numReceived, m.net.(*mockCmix).GetMsgListLen()) } } @@ -86,36 +85,37 @@ func TestManager_sendThread(t *testing.T) { } -// Tests that Manager.sendMessages sends all the messages with the correct -// recipient. -func TestManager_sendMessages(t *testing.T) { - m := newTestManager(100, 0, 0, false, t) - prng := NewPrng(42) +// Tests that sendMessage generates random message data using pseudo-RNGs. +func TestManager_sendMessage(t *testing.T) { + m := newTestManager(100, 0, 0, t) + + // Generate two identical RNGs, one for generating expected data (newRandomCmixMessage) + // and one for received data (sendMessage) + prngOne := NewPrng(42) + prngTwo := NewPrng(42) // Generate map of recipients and messages msgs := make(map[id.ID]format.Message, m.maxNumMessages) for i := 0; i < m.maxNumMessages; i++ { - recipient, err := id.NewRandomID(prng, id.User) + // Generate random data + recipient, fp, service, payload, mac, err := m.newRandomCmixMessage(prngOne) if err != nil { - t.Errorf("Failed to generate random recipient ID (%d): %+v", i, err) + t.Fatalf("Failed to generate random cMix message (%d): %+v", i, err) } - msg, err := m.newRandomCmixMessage(prng) + payloadSize := m.store.GetCmixGroup().GetP().ByteLen() + msgs[*recipient] = generateMessage(payloadSize, fp, service, payload, mac) + + // Send the messages + err = m.sendMessage(i, m.maxNumMessages, prngTwo) if err != nil { - t.Errorf("Failed to generate random cMix message (%d): %+v", i, err) + t.Errorf("sendMessages returned an error: %+v", err) } - msgs[*recipient] = msg - } - - // Send the messages - err := m.sendMessages(msgs) - if err != nil { - t.Errorf("sendMessages returned an error: %+v", err) } // get sent messages - receivedMsgs := m.networkManager.(*testNetworkManager).GetMsgList() + receivedMsgs := m.net.(*mockCmix).GetMsgList() // Test that all messages were received if len(receivedMsgs) != len(msgs) { @@ -127,60 +127,46 @@ func TestManager_sendMessages(t *testing.T) { for recipient, msg := range msgs { receivedMsg, exists := receivedMsgs[recipient] if !exists { - t.Errorf("Failed to receive message from %s: %+v", &recipient, msg) - } else if !reflect.DeepEqual(msg, receivedMsg) { + t.Errorf("Failed to receive message from %s: %+v", &recipient, msg.Marshal()) + } else if !reflect.DeepEqual(msg.Marshal(), receivedMsg.Marshal()) { + // In mockCmix.Send, we map recipientId to the passed fingerprint. t.Errorf("Received unexpected message for recipient %s."+ "\nexpected: %+v\nreceived: %+v", &recipient, msg, receivedMsg) } } } -// Tests that Manager.newRandomMessages creates a non-empty map of messages and -// that each message is unique. -func TestManager_newRandomMessages(t *testing.T) { - m := newTestManager(10, 0, 0, false, t) +// Tests that newRandomCmixMessage generates cMix message data with +// populated recipient, payload, fingerprint, and MAC. +func TestManager_newRandomCmixMessage(t *testing.T) { + m := newTestManager(0, 0, 0, t) prng := NewPrng(42) - msgMap, err := m.newRandomMessages(prng) + // Generate data + recipient, fp, _, payload, mac, err := m.newRandomCmixMessage(prng) if err != nil { - t.Errorf("newRandomMessages returned an error: %+v", err) - } - - if len(msgMap) == 0 { - t.Error("Message map is empty.") + t.Fatalf("newRandomCmixMessage returned an error: %+v", err) } - marshalledMsgs := make(map[string]format.Message, len(msgMap)) - for _, msg := range msgMap { - msgString := base64.StdEncoding.EncodeToString(msg.Marshal()) - if _, exists := marshalledMsgs[msgString]; exists { - t.Errorf("Message not unique.") - } else { - marshalledMsgs[msgString] = msg - } + // Check that recipient is not empty data + if bytes.Equal(recipient.Bytes(), make([]byte, id.ArrIDLen)) { + t.Errorf("Recipient ID not set") } -} - -// Tests that Manager.newRandomCmixMessage generates a cMix message with -// populated contents, fingerprint, and MAC. -func TestManager_newRandomCmixMessage(t *testing.T) { - m := newTestManager(0, 0, 0, false, t) - prng := NewPrng(42) - cMixMsg, err := m.newRandomCmixMessage(prng) - if err != nil { - t.Errorf("newRandomCmixMessage returned an error: %+v", err) - } - - if bytes.Equal(cMixMsg.GetContents(), make([]byte, len(cMixMsg.GetContents()))) { + // Check that payload is not empty data + payloadSize := m.store.GetCmixGroup().GetP().ByteLen() + if bytes.Equal(payload, make([]byte, payloadSize)) { t.Error("cMix message contents not set.") } - if cMixMsg.GetKeyFP() == (format.Fingerprint{}) { + // Check that fingerprint is not empty data + if fp == (format.Fingerprint{}) { t.Error("cMix message fingerprint not set.") } - if bytes.Equal(cMixMsg.GetMac(), make([]byte, format.MacLen)) { + // Check that mac is not empty data + if bytes.Equal(mac, make([]byte, format.MacLen)) { t.Error("cMix message MAC not set.") } + } diff --git a/dummy/utils_test.go b/dummy/utils_test.go index bc838731f5f42b345c4fbdfd849750b4551c0ef5..4ddccebf7cf5ccb4371fa31f6811bb319612fac1 100644 --- a/dummy/utils_test.go +++ b/dummy/utils_test.go @@ -1,34 +1,20 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package dummy import ( - "github.com/pkg/errors" - "gitlab.com/elixxir/client/cmix" - "gitlab.com/elixxir/client/cmix/gateway" "gitlab.com/elixxir/client/cmix/message" - "gitlab.com/elixxir/client/event" - "gitlab.com/elixxir/client/interfaces" - "gitlab.com/elixxir/client/stoppable" "gitlab.com/elixxir/client/storage" - "gitlab.com/elixxir/comms/mixmessages" - "gitlab.com/elixxir/comms/network" - "gitlab.com/elixxir/crypto/e2e" "gitlab.com/elixxir/crypto/fastRNG" "gitlab.com/elixxir/primitives/format" - "gitlab.com/xx_network/comms/connect" "gitlab.com/xx_network/crypto/csprng" - "gitlab.com/xx_network/primitives/id" - "gitlab.com/xx_network/primitives/id/ephemeral" - "gitlab.com/xx_network/primitives/ndf" "io" "math/rand" - "sync" "testing" "time" ) @@ -51,201 +37,35 @@ func (s *Prng) SetSeed([]byte) error { return nil } // newTestManager creates a new Manager that has groups stored for testing. One // of the groups in the list is also returned. func newTestManager(maxNumMessages int, avgSendDelta, randomRange time.Duration, - sendErr bool, t *testing.T) *Manager { + t *testing.T) *Manager { store := storage.InitTestingSession(t) + payloadSize := store.GetCmixGroup().GetP().ByteLen() m := &Manager{ maxNumMessages: maxNumMessages, avgSendDelta: avgSendDelta, randomRange: randomRange, statusChan: make(chan bool, statusChanLen), - store: &store, - networkManager: newTestNetworkManager(sendErr, t), + store: store, + net: newMockCmix(payloadSize), rng: fastRNG.NewStreamGenerator(1000, 10, csprng.NewSystemRNG), } return m } -// //////////////////////////////////////////////////////////////////////////////// -// // Test Network State // -// //////////////////////////////////////////////////////////////////////////////// - -// // testNetworkManager is a test implementation of NetworkManager interface. -type testNetworkManager struct { - instance *network.Instance - messages map[id.ID]format.Message - sendErr bool - sync.RWMutex -} - -func newTestNetworkManager(sendErr bool, t *testing.T) interfaces.NetworkManager { - instanceComms := &connect.ProtoComms{ - Manager: connect.NewManagerTesting(t), - } - - thisInstance, err := network.NewInstanceTesting(instanceComms, getNDF(), - getNDF(), nil, nil, t) - if err != nil { - t.Fatalf("Failed to create new test instance: %v", err) - } - - return &testNetworkManager{ - instance: thisInstance, - messages: make(map[id.ID]format.Message), - sendErr: sendErr, - } -} - -func (tnm *testNetworkManager) GetMsgListLen() int { - tnm.RLock() - defer tnm.RUnlock() - return len(tnm.messages) -} - -func (tnm *testNetworkManager) GetMsgList() map[id.ID]format.Message { - tnm.RLock() - defer tnm.RUnlock() - return tnm.messages -} - -func (tnm *testNetworkManager) GetMsg(recipient id.ID) format.Message { - tnm.RLock() - defer tnm.RUnlock() - return tnm.messages[recipient] -} - -// TEST -func (tnm *testNetworkManager) SendE2E() ( - []id.Round, e2e.MessageID, time.Time, error) { - return nil, e2e.MessageID{}, time.Time{}, nil -} - -// TEST -func (tnm *testNetworkManager) SendUnsafe() ([]id.Round, error) { - return []id.Round{}, nil -} - -func (tnm *testNetworkManager) SendCMIX(message format.Message, - recipient *id.ID, _ cmix.Params) (id.Round, ephemeral.Id, error) { - tnm.Lock() - defer tnm.Unlock() - - if tnm.sendErr { - return 0, ephemeral.Id{}, errors.New("Send error") - } +// generateMessage is a utility function which generates a format.Message +// given message data. +func generateMessage(payloadSize int, + fingerprint format.Fingerprint, + service message.Service, + payload, mac []byte) format.Message { - tnm.messages[*recipient] = message + // Build message. Will panic if inputs are not correct. + msg := format.NewMessage(payloadSize) + msg.SetContents(payload) + msg.SetKeyFP(fingerprint) + msg.SetSIH(service.Hash(msg.GetContents())) + msg.SetMac(mac) - return 0, ephemeral.Id{}, nil -} - -func (tnm *testNetworkManager) SendManyCMIX([]cmix.TargetedCmixMessage, cmix.Params) ( - id.Round, []ephemeral.Id, error) { - return 0, nil, nil -} - -type dummyEventMgr struct{} - -func (d *dummyEventMgr) Report(int, string, string, string) {} -func (tnm *testNetworkManager) GetEventManager() event.Reporter { - return &dummyEventMgr{} -} - -func (tnm *testNetworkManager) GetInstance() *network.Instance { return tnm.instance } -func (tnm *testNetworkManager) GetAddressSpace() uint8 { return 0 } -func (tnm *testNetworkManager) GetHostParams() connect.HostParams { return connect.HostParams{} } -func (tnm *testNetworkManager) GetHealthTracker() interfaces.HealthTracker { return nil } -func (tnm *testNetworkManager) Follow(interfaces.ClientErrorReport) (stoppable.Stoppable, error) { - return nil, nil -} -func (tnm *testNetworkManager) CheckGarbledMessages() {} -func (tnm *testNetworkManager) CheckInProgressMessages() {} -func (tnm *testNetworkManager) InProgressRegistrations() int { return 0 } -func (tnm *testNetworkManager) GetSender() *gateway.Sender { return nil } -func (tnm *testNetworkManager) GetAddressSize() uint8 { return 0 } -func (tnm *testNetworkManager) RegisterAddressSizeNotification(string) (chan uint8, error) { - return nil, nil -} -func (tnm *testNetworkManager) UnregisterAddressSizeNotification(string) {} -func (tnm *testNetworkManager) SetPoolFilter(gateway.Filter) {} -func (tnm *testNetworkManager) GetVerboseRounds() string { return "" } -func (tnm *testNetworkManager) HasNode(*id.ID) bool { return false } -func (tnm *testNetworkManager) LookupHistoricalRound(id.Round, func(*mixmessages.RoundInfo, bool)) error { - return nil -} -func (tnm *testNetworkManager) NumRegisteredNodes() int { return 0 } -func (tnm *testNetworkManager) RegisterAddressSpaceNotification(string) (chan uint8, error) { - return nil, nil -} -func (tnm *testNetworkManager) SendToAny(func(*connect.Host) (interface{}, error), *stoppable.Single) (interface{}, error) { - return nil, nil -} -func (tnm *testNetworkManager) SendToPreferred([]*id.ID, func(*connect.Host, *id.ID, time.Duration) (interface{}, error), *stoppable.Single, time.Duration) (interface{}, error) { - return nil, nil -} -func (tnm *testNetworkManager) SetGatewayFilter(func(map[id.ID]int, *ndf.NetworkDefinition) map[id.ID]int) { -} -func (tnm *testNetworkManager) TrackServices(message.ServicesTracker) {} -func (tnm *testNetworkManager) TriggerNodeRegistration(*id.ID) {} -func (tnm *testNetworkManager) UnregisterAddressSpaceNotification(string) {} - -func (tnm *testNetworkManager) AddFingerprint(*id.ID, format.Fingerprint, message.Processor) error { - return nil -} -func (tnm *testNetworkManager) DeleteFingerprint(*id.ID, format.Fingerprint) {} -func (tnm *testNetworkManager) DeleteClientFingerprints(*id.ID) {} - -func (tnm *testNetworkManager) AddIdentity(*id.ID, time.Time, bool) error { return nil } -func (tnm *testNetworkManager) RemoveIdentity(*id.ID) {} - -func (tnm *testNetworkManager) AddTrigger(*id.ID, message.Service, message.Processor) {} -func (tnm *testNetworkManager) DeleteTrigger(*id.ID, interfaces.Preimage, message.Processor) error { - return nil -} -func (tnm *testNetworkManager) DeleteClientTriggers(*id.ID) {} - -// //////////////////////////////////////////////////////////////////////////////// -// // NDF Primes // -// //////////////////////////////////////////////////////////////////////////////// - -func getNDF() *ndf.NetworkDefinition { - return &ndf.NetworkDefinition{ - E2E: ndf.Group{ - Prime: "E2EE983D031DC1DB6F1A7A67DF0E9A8E5561DB8E8D49413394C049B7A" + - "8ACCEDC298708F121951D9CF920EC5D146727AA4AE535B0922C688B55B3D" + - "D2AEDF6C01C94764DAB937935AA83BE36E67760713AB44A6337C20E78615" + - "75E745D31F8B9E9AD8412118C62A3E2E29DF46B0864D0C951C394A5CBBDC" + - "6ADC718DD2A3E041023DBB5AB23EBB4742DE9C1687B5B34FA48C3521632C" + - "4A530E8FFB1BC51DADDF453B0B2717C2BC6669ED76B4BDD5C9FF558E88F2" + - "6E5785302BEDBCA23EAC5ACE92096EE8A60642FB61E8F3D24990B8CB12EE" + - "448EEF78E184C7242DD161C7738F32BF29A841698978825B4111B4BC3E1E" + - "198455095958333D776D8B2BEEED3A1A1A221A6E37E664A64B83981C46FF" + - "DDC1A45E3D5211AAF8BFBC072768C4F50D7D7803D2D4F278DE8014A47323" + - "631D7E064DE81C0C6BFA43EF0E6998860F1390B5D3FEACAF1696015CB79C" + - "3F9C2D93D961120CD0E5F12CBB687EAB045241F96789C38E89D796138E63" + - "19BE62E35D87B1048CA28BE389B575E994DCA755471584A09EC723742DC3" + - "5873847AEF49F66E43873", - Generator: "2", - }, - CMIX: ndf.Group{ - Prime: "9DB6FB5951B66BB6FE1E140F1D2CE5502374161FD6538DF1648218642" + - "F0B5C48C8F7A41AADFA187324B87674FA1822B00F1ECF8136943D7C55757" + - "264E5A1A44FFE012E9936E00C1D3E9310B01C7D179805D3058B2A9F4BB6F" + - "9716BFE6117C6B5B3CC4D9BE341104AD4A80AD6C94E005F4B993E14F091E" + - "B51743BF33050C38DE235567E1B34C3D6A5C0CEAA1A0F368213C3D19843D" + - "0B4B09DCB9FC72D39C8DE41F1BF14D4BB4563CA28371621CAD3324B6A2D3" + - "92145BEBFAC748805236F5CA2FE92B871CD8F9C36D3292B5509CA8CAA77A" + - "2ADFC7BFD77DDA6F71125A7456FEA153E433256A2261C6A06ED3693797E7" + - "995FAD5AABBCFBE3EDA2741E375404AE25B", - Generator: "5C7FF6B06F8F143FE8288433493E4769C4D988ACE5BE25A0E2480" + - "9670716C613D7B0CEE6932F8FAA7C44D2CB24523DA53FBE4F6EC3595892D" + - "1AA58C4328A06C46A15662E7EAA703A1DECF8BBB2D05DBE2EB956C142A33" + - "8661D10461C0D135472085057F3494309FFA73C611F78B32ADBB5740C361" + - "C9F35BE90997DB2014E2EF5AA61782F52ABEB8BD6432C4DD097BC5423B28" + - "5DAFB60DC364E8161F4A2A35ACA3A10B1C4D203CC76A470A33AFDCBDD929" + - "59859ABD8B56E1725252D78EAC66E71BA9AE3F1DD2487199874393CD4D83" + - "2186800654760E1E34C09E4D155179F9EC0DC4473F996BDCE6EED1CABED8" + - "B6F116F7AD9CF505DF0F998E34AB27514B0FFE7", - }, - } + return msg } diff --git a/e2e/callbacks.go b/e2e/callbacks.go index 915229bd040440511c21caa0666dea6a68f5950d..8f4655a277a3ed8280bb513e7fc7475fe75ba47c 100644 --- a/e2e/callbacks.go +++ b/e2e/callbacks.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package e2e diff --git a/e2e/callbacks_test.go b/e2e/callbacks_test.go index 327020f04304e6b960f3bc72e7c6916f9c61ad7c..ab93edae6fc38556ac12e45b920e91a8a310fe09 100644 --- a/e2e/callbacks_test.go +++ b/e2e/callbacks_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package e2e diff --git a/e2e/critical.go b/e2e/critical.go index 9a803886ff81faeded4e546a8462af9e78c73dc9..ddad76743d756a225d65122a2e8fdc285d497169 100644 --- a/e2e/critical.go +++ b/e2e/critical.go @@ -1,6 +1,14 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package e2e import ( + "gitlab.com/elixxir/crypto/e2e" "time" jww "github.com/spf13/jwalterweatherman" @@ -9,7 +17,6 @@ import ( "gitlab.com/elixxir/client/stoppable" "gitlab.com/elixxir/client/storage/versioned" ds "gitlab.com/elixxir/comms/network/dataStructures" - "gitlab.com/elixxir/crypto/e2e" "gitlab.com/elixxir/primitives/format" "gitlab.com/elixxir/primitives/states" "gitlab.com/xx_network/primitives/id" @@ -29,7 +36,7 @@ type roundEventRegistrar interface { // anonymous function to include the structures from manager that critical is // not aware of. type criticalSender func(mt catalog.MessageType, recipient *id.ID, - payload []byte, params Params) ([]id.Round, e2e.MessageID, time.Time, error) + payload []byte, params Params) (e2e.SendReport, error) // critical is a structure that allows the auto resending of messages that must // be received. @@ -138,11 +145,11 @@ func (c *critical) evaluate(stop *stoppable.Single) { format.DigestContents(payload)) // Send the message - round, _, _, err := c.send(mt, recipient, payload, + sendReport, err := c.send(mt, recipient, payload, params) // Pass to the handler - c.handle(mt, recipient, payload, round, err) + c.handle(mt, recipient, payload, sendReport.RoundList, err) }(mt, recipient, payload, params) } diff --git a/e2e/e2eMessageBuffer.go b/e2e/e2eMessageBuffer.go index 00b196d6bd70d9c5dafe7e3915e1786d89581b61..3b47ed10b9d5d31fb0d086228e941cb9c6c6f981 100644 --- a/e2e/e2eMessageBuffer.go +++ b/e2e/e2eMessageBuffer.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package e2e @@ -51,7 +51,7 @@ func (emh *e2eMessageHandler) SaveMessage(kv *versioned.KV, m interface{}, } // Save versioned object - return kv.Set(key, currentE2EMessageVersion, &obj) + return kv.Set(key, &obj) } // LoadMessage returns the e2eMessage with the specified key from the key value diff --git a/e2e/e2eMessageBuffer_test.go b/e2e/e2eMessageBuffer_test.go index 37826cfcff8dee48b705ad4f0efa7b2bd83bd6ac..782f3beeef774f6e2503c6152b40926395ca65b7 100644 --- a/e2e/e2eMessageBuffer_test.go +++ b/e2e/e2eMessageBuffer_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package e2e diff --git a/e2e/fpGenerator.go b/e2e/fpGenerator.go index 5e89dd8016e3c231fd968c54bdb4824f9ceeac9c..22c77222f9c5c5f8590eb4ddd89c05a91d331013 100644 --- a/e2e/fpGenerator.go +++ b/e2e/fpGenerator.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package e2e import ( diff --git a/e2e/fpGenerator_test.go b/e2e/fpGenerator_test.go index ebd2d7cc381a3d3ccc908b9118b697226bb0af59..249dc5bba79fc07fb38439a64b4266a658215ee0 100644 --- a/e2e/fpGenerator_test.go +++ b/e2e/fpGenerator_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package e2e @@ -16,6 +16,7 @@ import ( "gitlab.com/elixxir/client/e2e/ratchet/partner/session" "gitlab.com/elixxir/client/stoppable" "gitlab.com/elixxir/comms/network" + "gitlab.com/elixxir/crypto/e2e" "gitlab.com/elixxir/primitives/format" "gitlab.com/xx_network/comms/connect" "gitlab.com/xx_network/primitives/id" @@ -90,11 +91,15 @@ type mockSessionCypher struct { fp format.Fingerprint } -func (m mockSessionCypher) GetSession() *session.Session { return nil } -func (m mockSessionCypher) Fingerprint() format.Fingerprint { return m.fp } -func (m mockSessionCypher) Encrypt([]byte) (ecrContents, mac []byte) { return nil, nil } -func (m mockSessionCypher) Decrypt(format.Message) ([]byte, error) { return nil, nil } -func (m mockSessionCypher) Use() {} +func (m mockSessionCypher) GetSession() *session.Session { return nil } +func (m mockSessionCypher) Fingerprint() format.Fingerprint { return m.fp } +func (m mockSessionCypher) Encrypt([]byte) (ecrContents, mac []byte, residue e2e.KeyResidue) { + return nil, nil, e2e.KeyResidue{} +} +func (m mockSessionCypher) Decrypt(format.Message) ([]byte, e2e.KeyResidue, error) { + return nil, e2e.KeyResidue{}, nil +} +func (m mockSessionCypher) Use() {} //////////////////////////////////////////////////////////////////////////////// // Mock cMix // @@ -113,11 +118,15 @@ func newMockFpgCmix() *mockFpgCmix { func (m *mockFpgCmix) Follow(cmix.ClientErrorReport) (stoppable.Stoppable, error) { return nil, nil } func (m *mockFpgCmix) GetMaxMessageLength() int { return 0 } -func (m *mockFpgCmix) Send(*id.ID, format.Fingerprint, message.Service, []byte, []byte, cmix.CMIXParams) (id.Round, ephemeral.Id, error) { - return 0, ephemeral.Id{}, nil +func (m *mockFpgCmix) Send(*id.ID, format.Fingerprint, message.Service, []byte, []byte, cmix.CMIXParams) (rounds.Round, ephemeral.Id, error) { + return rounds.Round{}, ephemeral.Id{}, nil } -func (m *mockFpgCmix) SendMany([]cmix.TargetedCmixMessage, cmix.CMIXParams) (id.Round, []ephemeral.Id, error) { - return 0, nil, nil +func (m *mockFpgCmix) SendWithAssembler(recipient *id.ID, assembler cmix.MessageAssembler, + cmixParams cmix.CMIXParams) (rounds.Round, ephemeral.Id, error) { + return rounds.Round{}, ephemeral.Id{}, nil +} +func (m *mockFpgCmix) SendMany([]cmix.TargetedCmixMessage, cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error) { + return rounds.Round{}, nil, nil } func (m *mockFpgCmix) AddIdentity(*id.ID, time.Time, bool) {} func (m *mockFpgCmix) RemoveIdentity(*id.ID) {} @@ -161,8 +170,7 @@ func (m *mockFpgCmix) RemoveHealthCallback(uint64) func (m *mockFpgCmix) HasNode(*id.ID) bool { return false } func (m *mockFpgCmix) NumRegisteredNodes() int { return 0 } func (m *mockFpgCmix) TriggerNodeRegistration(*id.ID) {} -func (m *mockFpgCmix) GetRoundResults(time.Duration, cmix.RoundEventCallback, ...id.Round) error { - return nil +func (m *mockFpgCmix) GetRoundResults(time.Duration, cmix.RoundEventCallback, ...id.Round) { } func (m *mockFpgCmix) LookupHistoricalRound(id.Round, rounds.RoundResultCallback) error { return nil } func (m *mockFpgCmix) SendToAny(func(host *connect.Host) (interface{}, error), *stoppable.Single) (interface{}, error) { diff --git a/e2e/interface.go b/e2e/interface.go index 0578bbc719731f5d1c83a7e16330506aac8bac66..05731802b42446c49c06796a066c1bec3d74ffbd 100644 --- a/e2e/interface.go +++ b/e2e/interface.go @@ -1,7 +1,15 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package e2e import ( "gitlab.com/elixxir/client/cmix/rounds" + "gitlab.com/elixxir/crypto/e2e" "time" "github.com/cloudflare/circl/dh/sidh" @@ -12,7 +20,6 @@ import ( "gitlab.com/elixxir/client/e2e/receive" "gitlab.com/elixxir/client/stoppable" "gitlab.com/elixxir/crypto/cyclic" - "gitlab.com/elixxir/crypto/e2e" "gitlab.com/xx_network/primitives/id" ) @@ -35,7 +42,7 @@ type Handler interface { // Will return an error if the network is not healthy or in // the event of a failed send SendE2E(mt catalog.MessageType, recipient *id.ID, payload []byte, - params Params) ([]id.Round, e2e.MessageID, time.Time, error) + params Params) (e2e.SendReport, error) /* === Reception ==================================================== */ diff --git a/e2e/legacyGen_test.go b/e2e/legacyGen_test.go index 80b5da30fbcad3bb93651e29568f2a089a4fd364..836d750f675b51a22b523bb412391c312509bf59 100644 --- a/e2e/legacyGen_test.go +++ b/e2e/legacyGen_test.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package e2e // legacyGen_test.go contains the code for generating e2e relationships diff --git a/e2e/manager.go b/e2e/manager.go index bd7c313811a792ddc5535f8e4ab0f00cd97406b0..72197eb40c645bbc4e55a5d7485fcab4240203f4 100644 --- a/e2e/manager.go +++ b/e2e/manager.go @@ -1,13 +1,19 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package e2e import ( "bytes" "encoding/base64" "encoding/json" - "sync" - "time" - jww "github.com/spf13/jwalterweatherman" + "gitlab.com/elixxir/crypto/e2e" + "sync" "gitlab.com/xx_network/primitives/netTime" @@ -23,7 +29,6 @@ import ( "gitlab.com/elixxir/client/stoppable" "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/crypto/cyclic" - "gitlab.com/elixxir/crypto/e2e" "gitlab.com/elixxir/crypto/fastRNG" "gitlab.com/xx_network/primitives/id" ) @@ -70,7 +75,7 @@ func initE2E(kv *versioned.KV, myID *id.ID, privKey *cyclic.Int, if err != nil { return errors.WithMessage(err, "Failed to marshal rekeyParams") } - err = kv.Set(e2eRekeyParamsKey, e2eRekeyParamsVer, &versioned.Object{ + err = kv.Set(e2eRekeyParamsKey, &versioned.Object{ Version: e2eRekeyParamsVer, Timestamp: netTime.Now(), Data: rekeyParamsData, @@ -123,7 +128,7 @@ func LoadLegacy(kv *versioned.KV, net cmix.Client, myID *id.ID, } // Store the rekey params to disk/memory - err = kv.Set(e2eRekeyParamsKey, e2eRekeyParamsVer, &versioned.Object{ + err = kv.Set(e2eRekeyParamsKey, &versioned.Object{ Version: e2eRekeyParamsVer, Timestamp: netTime.Now(), Data: rekeyParamsData, @@ -131,7 +136,7 @@ func LoadLegacy(kv *versioned.KV, net cmix.Client, myID *id.ID, if err != nil { return nil, err } - err = kv.Set(legacyE2EKey, e2eRekeyParamsVer, &versioned.Object{ + err = kv.Set(legacyE2EKey, &versioned.Object{ Version: e2eRekeyParamsVer, Timestamp: netTime.Now(), Data: []byte{1}, @@ -214,8 +219,7 @@ func (m *manager) StartProcesses() (stoppable.Stoppable, error) { rekeySendFunc := func(mt catalog.MessageType, recipient *id.ID, payload []byte, - cmixParams cmix.CMIXParams) ( - []id.Round, e2e.MessageID, time.Time, error) { + cmixParams cmix.CMIXParams) (e2e.SendReport, error) { // FIXME: we should have access to the e2e params here... par := GetDefaultParams() par.CMIXParams = cmixParams @@ -284,14 +288,15 @@ func (m *manager) DeletePartnerNotify(partnerId *id.ID, params Params) error { m.DeletePartnerCallbacks(partnerId) // Send closing E2E message - rounds, msgID, timestamp, err := sendFunc() + + sendReport, err := sendFunc() if err != nil { jww.ERROR.Printf("Failed to send %s E2E message to %s: %+v", catalog.E2eClose, partnerId, err) } else { jww.INFO.Printf( "Sent %s E2E message to %s on rounds %v with message ID %s at %s", - catalog.E2eClose, partnerId, rounds, msgID, timestamp) + catalog.E2eClose, partnerId, sendReport.RoundList, sendReport.MessageId, sendReport.SentTime) } return nil diff --git a/e2e/manager_test.go b/e2e/manager_test.go index 55fe430796c406a95b7f6a89268a29caa51bf6ff..46bd718658c97466b19f7a671eebcc9f7122d63b 100644 --- a/e2e/manager_test.go +++ b/e2e/manager_test.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package e2e import ( diff --git a/e2e/params.go b/e2e/params.go index 2702d490656342e975883177b115f63dbf2df961..1e5cbcb5f852740fc20ce1e38268e6cb700bd3d4 100644 --- a/e2e/params.go +++ b/e2e/params.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package e2e import ( @@ -100,3 +107,9 @@ func (p *Params) UnmarshalJSON(data []byte) error { return nil } + +// String implements stringer interface by returning a json string +func (p *Params) String() string { + json, _ := p.MarshalJSON() + return string(json) +} diff --git a/e2e/parse/conversation/message.go b/e2e/parse/conversation/message.go index bc7f92aa3f4bee6b2decd98a85f19e0c020be16e..82a6770827e6fc12b91c44f7c54d323b1fee84f4 100644 --- a/e2e/parse/conversation/message.go +++ b/e2e/parse/conversation/message.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package conversation diff --git a/e2e/parse/conversation/message_test.go b/e2e/parse/conversation/message_test.go index 35cc9403604caeb40f4932cee3ed52a058520945..6c220fd9b789835d4ac83a66188efc5a9dd282d5 100644 --- a/e2e/parse/conversation/message_test.go +++ b/e2e/parse/conversation/message_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package conversation diff --git a/e2e/parse/conversation/partner.go b/e2e/parse/conversation/partner.go index 06155c697b6674c16261cb84af74ccb714feb69c..03158a059eb85b8e27c30ae3302740e2f239bdfd 100644 --- a/e2e/parse/conversation/partner.go +++ b/e2e/parse/conversation/partner.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package conversation @@ -14,9 +14,7 @@ import ( "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/netTime" - "io/fs" "math" - "strings" "sync" ) @@ -51,7 +49,7 @@ type conversationDisk struct { // saved to KV, and returned. func LoadOrMakeConversation(kv *versioned.KV, partner *id.ID) *Conversation { c, err := loadConversation(kv, partner) - if err != nil && !(errors.Is(err, fs.ErrNotExist) || strings.Contains(err.Error(), "object not found")) { + if err != nil && kv.Exists(err) { jww.FATAL.Panicf("Failed to load conversation from storage: %+v", err) } else if c == nil { // Create new conversation and save to KV if one does not exist @@ -163,7 +161,7 @@ func (c *Conversation) save() error { } key := makeConversationKey(c.partner) - return c.kv.Set(key, currentConversationVersion, &obj) + return c.kv.Set(key, &obj) } // delete removes the Conversation from KV storage. diff --git a/e2e/parse/conversation/partner_test.go b/e2e/parse/conversation/partner_test.go index 41dd638ca5a04fefc125c2a4977715c5c4493f5c..0d7e9883c30bee788126abb67d3b591007427902 100644 --- a/e2e/parse/conversation/partner_test.go +++ b/e2e/parse/conversation/partner_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package conversation diff --git a/e2e/parse/conversation/ring.go b/e2e/parse/conversation/ring.go index 7e255451bae9eae4fbada051fc85ea4a1bb4067f..88304e97c61662af209edf81a64de540236b569c 100644 --- a/e2e/parse/conversation/ring.go +++ b/e2e/parse/conversation/ring.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package conversation @@ -231,7 +231,7 @@ func (b *Buff) saveBuff() error { Data: b.marshal(), } - return b.kv.Set(ringBuffKey, ringBuffVersion, obj) + return b.kv.Set(ringBuffKey, obj) } // marshal creates a byte buffer containing serialized information on the Buff. @@ -293,7 +293,7 @@ func (b *Buff) saveMessage(msg *Message) error { } return b.kv.Set( - makeMessageKey(msg.MessageId.truncate()), messageVersion, obj) + makeMessageKey(msg.MessageId.truncate()), obj) } diff --git a/e2e/parse/conversation/ring_test.go b/e2e/parse/conversation/ring_test.go index 1d1db1983fbe265d6841b22c1f969b21119806f7..fd70ef07fa260e68edd7ac8c28fde2ded6ce2e41 100644 --- a/e2e/parse/conversation/ring_test.go +++ b/e2e/parse/conversation/ring_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package conversation diff --git a/e2e/parse/conversation/store.go b/e2e/parse/conversation/store.go index 288e87674fa1cd6789bdacc538052cbc2173ae57..b1fc1f08e8deb91bae8ef1d2ddb1392daa60dfe6 100644 --- a/e2e/parse/conversation/store.go +++ b/e2e/parse/conversation/store.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package conversation diff --git a/e2e/parse/conversation/store_test.go b/e2e/parse/conversation/store_test.go index 176d251be7085dba1baa22e9038aeef10efb58fc..b7f8ab5f5a00d4e912ce13256a1cce3952b67d1f 100644 --- a/e2e/parse/conversation/store_test.go +++ b/e2e/parse/conversation/store_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package conversation diff --git a/e2e/parse/firstMessagePart.go b/e2e/parse/firstMessagePart.go index ae907af3d2b921f69a3770f1ad0aa8e1da72541d..f44007ad32ee2190ee75a2572082d120ea6bedae 100644 --- a/e2e/parse/firstMessagePart.go +++ b/e2e/parse/firstMessagePart.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package parse diff --git a/e2e/parse/firstMessagePart_test.go b/e2e/parse/firstMessagePart_test.go index cfe419be245d7f73e730ba142a827daf3ebac942..9d895ee89aff09bdd552df7c61613a6257ee1f7c 100644 --- a/e2e/parse/firstMessagePart_test.go +++ b/e2e/parse/firstMessagePart_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package parse diff --git a/e2e/parse/messagePart.go b/e2e/parse/messagePart.go index b1c3a9dfe2d4ef65ca247d8f940db165d5679070..e5908cf117c9079bde3a99f04b88eec229d4a356 100644 --- a/e2e/parse/messagePart.go +++ b/e2e/parse/messagePart.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package parse diff --git a/e2e/parse/messagePart_test.go b/e2e/parse/messagePart_test.go index adede5571164836de7c493f045767f03315eea9a..837765d7ab3f53c201af6725c2ae16a78e2865e3 100644 --- a/e2e/parse/messagePart_test.go +++ b/e2e/parse/messagePart_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package parse diff --git a/e2e/parse/partition.go b/e2e/parse/partition.go index da7628381175971f748d456761ccc836345bd227..b951df9f6f3e5f8d54b80e16a04484249afb3821 100644 --- a/e2e/parse/partition.go +++ b/e2e/parse/partition.go @@ -1,13 +1,14 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package parse import ( + "gitlab.com/elixxir/crypto/e2e" "time" "github.com/pkg/errors" @@ -78,7 +79,8 @@ func (p *Partitioner) Partition(recipient *id.ID, mt catalog.MessageType, } func (p *Partitioner) HandlePartition(sender *id.ID, - contents []byte, relationshipFingerprint []byte) (receive.Message, bool) { + contents []byte, relationshipFingerprint []byte, + residue e2e.KeyResidue) (receive.Message, e2e.KeyResidue, bool) { if isFirst(contents) { // If it is the first message in a set, then handle it as so @@ -92,7 +94,7 @@ func (p *Partitioner) HandlePartition(sender *id.ID, storageTimestamp := netTime.Now() return p.partition.AddFirst(sender, fm.getType(), messageID, fm.getPart(), fm.getNumParts(), fm.getTimestamp(), storageTimestamp, - fm.getSizedContents(), relationshipFingerprint) + fm.getSizedContents(), relationshipFingerprint, residue) } else { // If it is a subsequent message part, handle it as so mp := messagePartFromBytes(contents) diff --git a/e2e/parse/partition/multiPartMessage.go b/e2e/parse/partition/multiPartMessage.go index d067248d2a792fe846a9cb2e42c92ba001d5b3d5..e716cdbc2f6180e5cfc464e6ca432eb64f276d67 100644 --- a/e2e/parse/partition/multiPartMessage.go +++ b/e2e/parse/partition/multiPartMessage.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package partition @@ -15,7 +15,6 @@ import ( "gitlab.com/elixxir/client/e2e/receive" "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/crypto/e2e" - "gitlab.com/elixxir/ekv" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/netTime" "strconv" @@ -41,6 +40,8 @@ type multiPartMessage struct { StorageTimestamp time.Time MessageType catalog.MessageType + KeyResidue e2e.KeyResidue + parts [][]byte kv *versioned.KV mux sync.Mutex @@ -55,7 +56,7 @@ func loadOrCreateMultiPartMessage(sender *id.ID, messageID uint64, obj, err := kv.Get(messageKey, currentMultiPartMessageVersion) if err != nil { - if !ekv.Exists(err) { + if !kv.Exists(err) { mpm := &multiPartMessage{ Sender: sender, MessageID: messageID, @@ -100,7 +101,7 @@ func (mpm *multiPartMessage) save() error { Data: data, } - return mpm.kv.Set(messageKey, currentMultiPartMessageVersion, &obj) + return mpm.kv.Set(messageKey, &obj) } func (mpm *multiPartMessage) Add(partNumber uint8, part []byte) { diff --git a/e2e/parse/partition/multiPartMessage_test.go b/e2e/parse/partition/multiPartMessage_test.go index 616b7dda8d3bcae9799b78ac595f4a6fe3f123ad..2a2da3064140e123cb9f7305a4d1cf8fdd0b1fbd 100644 --- a/e2e/parse/partition/multiPartMessage_test.go +++ b/e2e/parse/partition/multiPartMessage_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package partition @@ -264,7 +264,7 @@ func TestMultiPartMessage_delete(t *testing.T) { mpm.delete() obj, err := kv.Get(messageKey, 0) - if ekv.Exists(err) { + if kv.Exists(err) { t.Errorf("delete did not properly delete key %s."+ "\n\tobject received: %+v", messageKey, obj) } diff --git a/e2e/parse/partition/part.go b/e2e/parse/partition/part.go index 25b0e2566abe28ef39d5605ab1cdc90d5f2542f9..78b3a8e4b337d98657fba68273de01f57f7b04d1 100644 --- a/e2e/parse/partition/part.go +++ b/e2e/parse/partition/part.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package partition @@ -30,12 +30,11 @@ func savePart(kv *versioned.KV, partNum uint8, part []byte) error { key := makeMultiPartMessagePartKey(partNum) obj := versioned.Object{ - Version: currentMultiPartMessagePartVersion, + Version: currentMultiPartMessageVersion, Timestamp: netTime.Now(), Data: part, } - - return kv.Set(key, currentMultiPartMessageVersion, &obj) + return kv.Set(key, &obj) } func deletePart(kv *versioned.KV, partNum uint8) error { diff --git a/e2e/parse/partition/part_test.go b/e2e/parse/partition/part_test.go index 53366fdb6d211a74e531e21cf8b4f0a9665079c3..9556771c022bc9615948d082c9e369a49f1596be 100644 --- a/e2e/parse/partition/part_test.go +++ b/e2e/parse/partition/part_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package partition @@ -57,7 +57,7 @@ func Test_loadPart(t *testing.T) { // Save part to key value store err := rootKv.Set( - key, 0, &versioned.Object{Timestamp: netTime.Now(), Data: part}) + key, &versioned.Object{Timestamp: netTime.Now(), Data: part}) if err != nil { t.Errorf("Failed to set object: %+v", err) } @@ -87,7 +87,7 @@ func Test_loadPart_NotFoundError(t *testing.T) { // Load part from key value store data, err := loadPart(kv, partNum) - if ekv.Exists(err) { + if kv.Exists(err) { t.Errorf("loadPart found an item for the key: %v", err) } @@ -121,7 +121,7 @@ func TestDeletePart(t *testing.T) { // Check if part was deleted _, err = loadPart(kv, partNum) - if ekv.Exists(err) { + if kv.Exists(err) { t.Errorf("part was found in key value store: %+v", err) } } diff --git a/e2e/parse/partition/store.go b/e2e/parse/partition/store.go index 7774e3187b90235d79f2ce4082024e8f4a547dec..713fc291a9bb530994c3598b26e595eea52a6b03 100644 --- a/e2e/parse/partition/store.go +++ b/e2e/parse/partition/store.go @@ -1,19 +1,21 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package partition import ( + "bytes" "encoding/binary" "encoding/json" jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/catalog" "gitlab.com/elixxir/client/e2e/receive" "gitlab.com/elixxir/client/storage/versioned" + "gitlab.com/elixxir/crypto/e2e" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/netTime" "golang.org/x/crypto/blake2b" @@ -49,47 +51,60 @@ func NewOrLoad(kv *versioned.KV) *Store { return partitionStore } +// AddFirst adds the first partition message to the Store object. func (s *Store) AddFirst(partner *id.ID, mt catalog.MessageType, messageID uint64, partNum, numParts uint8, senderTimestamp, - storageTimestamp time.Time, part []byte, relationshipFingerprint []byte) ( - receive.Message, bool) { + storageTimestamp time.Time, part []byte, relationshipFingerprint []byte, + residue e2e.KeyResidue) ( + receive.Message, e2e.KeyResidue, bool) { mpm := s.load(partner, messageID) - mpm.AddFirst(mt, partNum, numParts, senderTimestamp, storageTimestamp, part) + if bytes.Equal(residue.Marshal(), []byte{}) { + // fixme: should this error or crash? + jww.WARN.Printf("Key reside from first message " + + "is empty, continuing...") + } + + mpm.KeyResidue = residue msg, ok := mpm.IsComplete(relationshipFingerprint) s.mux.Lock() defer s.mux.Unlock() + keyRes := e2e.KeyResidue{} if !ok { s.activeParts[mpm] = true s.saveActiveParts() } else { + keyRes = mpm.KeyResidue mpID := getMultiPartID(mpm.Sender, mpm.MessageID) delete(s.multiParts, mpID) } - return msg, ok + return msg, keyRes, ok } func (s *Store) Add(partner *id.ID, messageID uint64, partNum uint8, - part []byte, relationshipFingerprint []byte) (receive.Message, bool) { + part []byte, relationshipFingerprint []byte) ( + receive.Message, e2e.KeyResidue, bool) { mpm := s.load(partner, messageID) mpm.Add(partNum, part) msg, ok := mpm.IsComplete(relationshipFingerprint) + keyRes := e2e.KeyResidue{} if !ok { s.activeParts[mpm] = true s.saveActiveParts() } else { + keyRes = mpm.KeyResidue mpID := getMultiPartID(mpm.Sender, mpm.MessageID) delete(s.multiParts, mpID) } - return msg, ok + return msg, keyRes, ok } // prune clears old messages on it's stored timestamp. @@ -145,7 +160,7 @@ func (s *Store) saveActiveParts() { Data: data, } - err = s.kv.Set(activePartitions, activePartitionVersion, &obj) + err = s.kv.Set(activePartitions, &obj) if err != nil { jww.FATAL.Panicf("Could not save active partitions: %+v", err) } @@ -156,7 +171,7 @@ func (s *Store) loadActivePartitions() { defer s.mux.Unlock() obj, err := s.kv.Get(activePartitions, activePartitionVersion) if err != nil { - jww.DEBUG.Printf("Could not load active partitions: %+v", err) + jww.DEBUG.Printf("Could not load active partitions: %s", err.Error()) return } diff --git a/e2e/parse/partition/store_test.go b/e2e/parse/partition/store_test.go index 909de9b829d54e7b07fc4936ed82bdd2337ccc5f..9ef6fcfd1b2a847e8d17aec4064923630fb57496 100644 --- a/e2e/parse/partition/store_test.go +++ b/e2e/parse/partition/store_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package partition @@ -11,6 +11,7 @@ import ( "bytes" "gitlab.com/elixxir/client/catalog" "gitlab.com/elixxir/client/storage/versioned" + "gitlab.com/elixxir/crypto/e2e" "gitlab.com/elixxir/ekv" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/netTime" @@ -39,15 +40,27 @@ func TestNewOrLoad(t *testing.T) { func TestStore_AddFirst(t *testing.T) { part := []byte("Test message.") s := NewOrLoad(versioned.NewKV(ekv.MakeMemstore())) + b := make([]byte, e2e.KeyResidueLength) + kr, err := e2e.UnmarshalKeyResidue(b) + if err != nil { + t.Fatalf("Failed to unmarshal key residue: %+v", err) + } - msg, complete := s.AddFirst(id.NewIdFromString("User", id.User, t), + msg, receivedKr, complete := s.AddFirst(id.NewIdFromString("User", id.User, t), catalog.XxMessage, 5, 0, 1, netTime.Now(), netTime.Now(), part, - []byte{0}) + []byte{0}, kr) if !complete { t.Errorf("AddFirst returned that the message was not complete.") } + if !bytes.Equal(receivedKr[:], kr[:]) { + t.Fatalf("Key residue returned from complete partition did not "+ + "match first key signature."+ + "\nExpected: %v"+ + "\nReceived: %v", kr, receivedKr) + } + if !bytes.Equal(part, msg.Payload) { t.Errorf("AddFirst returned message with invalid payload."+ "\nexpected: %v\nreceived: %v", part, msg.Payload) @@ -59,21 +72,33 @@ func TestStore_Add(t *testing.T) { part1 := []byte("Test message.") part2 := []byte("Second Sentence.") s := NewOrLoad(versioned.NewKV(ekv.MakeMemstore())) + b := make([]byte, e2e.KeyResidueLength) + kr, err := e2e.UnmarshalKeyResidue(b) + if err != nil { + t.Fatalf("Failed to unmarshal key residue: %+v", err) + } - msg, complete := s.AddFirst(id.NewIdFromString("User", id.User, t), + msg, _, complete := s.AddFirst(id.NewIdFromString("User", id.User, t), catalog.XxMessage, 5, 0, 2, netTime.Now(), netTime.Now(), part1, - []byte{0}) + []byte{0}, kr) if complete { t.Errorf("AddFirst returned that the message was complete.") } - msg, complete = s.Add(id.NewIdFromString("User", id.User, t), + msg, receivedKr, complete := s.Add(id.NewIdFromString("User", id.User, t), 5, 1, part2, []byte{0}) if !complete { t.Errorf("AddFirst returned that the message was not complete.") } + if !bytes.Equal(receivedKr[:], kr[:]) { + t.Fatalf("Key residue returned from complete partition did not "+ + "match first key signature."+ + "\nExpected: %v"+ + "\nReceived: %v", kr, receivedKr) + } + part := append(part1, part2...) if !bytes.Equal(part, msg.Payload) { t.Errorf("AddFirst returned message with invalid payload."+ @@ -92,10 +117,15 @@ func TestStore_prune(t *testing.T) { partner1 := id.NewIdFromString("User", id.User, t) messageId1 := uint64(5) oldTimestamp := netTime.Now().Add(-2 * clearPartitionThreshold) + b := make([]byte, e2e.KeyResidueLength) + kr, err := e2e.UnmarshalKeyResidue(b) + if err != nil { + t.Fatalf("Failed to unmarshal key residue: %+v", err) + } s.AddFirst(partner1, catalog.XxMessage, messageId1, 0, 2, netTime.Now(), oldTimestamp, part1, - []byte{0}) + []byte{0}, kr) s.Add(partner1, messageId1, 1, part2, []byte{0}) partner2 := id.NewIdFromString("User1", id.User, t) @@ -103,7 +133,7 @@ func TestStore_prune(t *testing.T) { newTimestamp := netTime.Now() s.AddFirst(partner2, catalog.XxMessage, messageId2, 0, 2, netTime.Now(), newTimestamp, part1, - []byte{0}) + []byte{0}, kr) // Call clear messages s.prune() diff --git a/e2e/parse/partition_test.go b/e2e/parse/partition_test.go index 22c1f238eda4b2f2f0be5575e68143c28970a749..2f1c41418805b0f6f31d267023c4b602802c04d4 100644 --- a/e2e/parse/partition_test.go +++ b/e2e/parse/partition_test.go @@ -1,13 +1,14 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package parse import ( + "gitlab.com/elixxir/crypto/e2e" "testing" "gitlab.com/elixxir/client/catalog" @@ -72,10 +73,11 @@ func TestPartitioner_HandlePartition(t *testing.T) { p := NewPartitioner(versioned.NewKV(ekv.MakeMemstore()), len(ipsumTestStr)) m := newMessagePart(1107, 1, []byte(ipsumTestStr), len(ipsumTestStr)+headerLen) - _, _ = p.HandlePartition( + _, _, _ = p.HandlePartition( &id.DummyUser, m.bytes(), []byte{'t', 'e', 's', 't', 'i', 'n', 'g', 's', 't', 'r', 'i', 'n', 'g'}, + e2e.KeyResidue{}, ) } @@ -85,9 +87,10 @@ func TestPartitioner_HandleFirstPartition(t *testing.T) { m := newFirstMessagePart( catalog.XxMessage, 1107, 1, netTime.Now(), []byte(ipsumTestStr), len([]byte(ipsumTestStr))+firstHeaderLen) - _, _ = p.HandlePartition( + _, _, _ = p.HandlePartition( &id.DummyUser, m.bytes(), []byte{'t', 'e', 's', 't', 'i', 'n', 'g', 's', 't', 'r', 'i', 'n', 'g'}, + e2e.KeyResidue{}, ) } diff --git a/e2e/processor.go b/e2e/processor.go index 17e2293401209f84783f4855182f607cc8f6bd0e..86673f81f235b905eaae31df7a2e786415584f3b 100644 --- a/e2e/processor.go +++ b/e2e/processor.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package e2e import ( @@ -23,7 +30,7 @@ func (p *processor) Process(ecrMsg format.Message, // ensure the key will be marked used before returning defer p.cy.Use() - contents, err := p.cy.Decrypt(ecrMsg) + contents, residue, err := p.cy.Decrypt(ecrMsg) if err != nil { jww.ERROR.Printf("decrypt failed of %s (fp: %s), dropping: %+v", ecrMsg.Digest(), p.cy.Fingerprint(), err) @@ -31,8 +38,9 @@ func (p *processor) Process(ecrMsg format.Message, } sess := p.cy.GetSession() - message, done := p.m.partitioner.HandlePartition(sess.GetPartner(), - contents, sess.GetRelationshipFingerprint()) + // todo: handle residue here + message, _, done := p.m.partitioner.HandlePartition(sess.GetPartner(), + contents, sess.GetRelationshipFingerprint(), residue) if done { message.RecipientID = receptionID.Source message.EphemeralID = receptionID.EphId diff --git a/e2e/ratchet/partner/interface.go b/e2e/ratchet/partner/interface.go index 1074893e8ead14f8280133bd59a5276723b69339..c0fa978410da820c2b3f7d800bd2525375b913d3 100644 --- a/e2e/ratchet/partner/interface.go +++ b/e2e/ratchet/partner/interface.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package partner import ( diff --git a/e2e/ratchet/partner/manager.go b/e2e/ratchet/partner/manager.go index ec7799363f2a107da4a49d42f8b2404d0dc0ac85..42169477dc2a5749c14de2e102f36b37f54eb40e 100644 --- a/e2e/ratchet/partner/manager.go +++ b/e2e/ratchet/partner/manager.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package partner diff --git a/e2e/ratchet/partner/manager_test.go b/e2e/ratchet/partner/manager_test.go index dab364dec3727cc926d2aa1cabb46e5c445cc330..78ae006db5251246110e90892d2694a712ad6df6 100644 --- a/e2e/ratchet/partner/manager_test.go +++ b/e2e/ratchet/partner/manager_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package partner diff --git a/e2e/ratchet/partner/relationship.go b/e2e/ratchet/partner/relationship.go index bd6f60ccef05edaaa526a01288b7905f4e351829..c7eb260f78f79f22847a45e653e0110873caeeb6 100644 --- a/e2e/ratchet/partner/relationship.go +++ b/e2e/ratchet/partner/relationship.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package partner @@ -161,7 +161,7 @@ func (r *relationship) save() error { Data: data, } - return r.kv.Set(relationshipKey, currentRelationshipVersion, &obj) + return r.kv.Set(relationshipKey, &obj) } //ekv functions diff --git a/e2e/ratchet/partner/relationshipFingerprint.go b/e2e/ratchet/partner/relationshipFingerprint.go index 9380b9a5051e9d82f76d3043e880350600425d6b..3bad30633b9556df8e5fe0e4ba97a07dc5254089 100644 --- a/e2e/ratchet/partner/relationshipFingerprint.go +++ b/e2e/ratchet/partner/relationshipFingerprint.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package partner @@ -40,13 +40,12 @@ func makeRelationshipFingerprint(t session2.RelationshipType, grp *cyclic.Group, func storeRelationshipFingerprint(fp []byte, kv *versioned.KV) error { now := netTime.Now() obj := versioned.Object{ - Version: currentRelationshipFingerprintVersion, + Version: currentRelationshipVersion, Timestamp: now, Data: fp, } - return kv.Set(relationshipFingerprintKey, currentRelationshipVersion, - &obj) + return kv.Set(relationshipFingerprintKey, &obj) } func loadRelationshipFingerprint(kv *versioned.KV) []byte { diff --git a/e2e/ratchet/partner/relationship_test.go b/e2e/ratchet/partner/relationship_test.go index 5160844daf0c6c3dcc6e4ea2844065f42f2b612b..3df242bcbfeb5612412420746177bc234471fd13 100644 --- a/e2e/ratchet/partner/relationship_test.go +++ b/e2e/ratchet/partner/relationship_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package partner diff --git a/e2e/ratchet/partner/session/cypher.go b/e2e/ratchet/partner/session/cypher.go index ef4094a40f0967f199dd4f89786fd6a2dcda5459..1a607a290fdd476a940dc77cbc89683e9387fb69 100644 --- a/e2e/ratchet/partner/session/cypher.go +++ b/e2e/ratchet/partner/session/cypher.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package session @@ -63,13 +63,15 @@ type Cypher interface { // Encrypt uses the E2E key to encrypt the message to its intended // recipient. It also properly populates the associated data, including the - // MAC, fingerprint, and encrypted timestamp. - Encrypt(contents []byte) (ecrContents, mac []byte) + // MAC, fingerprint, and encrypted timestamp. It generates a residue of the + // key used to encrypt the contents. + Encrypt(contents []byte) (ecrContents, mac []byte, residue e2eCrypto.KeyResidue) // Decrypt uses the E2E key to decrypt the message. It returns an error in // case of HMAC verification failure or in case of a decryption error - // (related to padding). - Decrypt(msg format.Message) ([]byte, error) + // (related to padding). It generates a residue of the + // key used to encrypt the contents. + Decrypt(msg format.Message) (decryptedPayload []byte, residue e2eCrypto.KeyResidue, err error) // Use sets the key as used. It cannot be used again. Use() @@ -110,11 +112,13 @@ func (k *cypher) Fingerprint() format.Fingerprint { // Encrypt uses the E2E key to encrypt the message to its intended recipient. It // also properly populates the associated data, including the MAC, fingerprint, -// and encrypted timestamp. -func (k *cypher) Encrypt(contents []byte) (ecrContents, mac []byte) { +// and encrypted timestamp. It generates a residue of the key used to encrypt the contents. +func (k *cypher) Encrypt(contents []byte) (ecrContents, mac []byte, residue e2eCrypto.KeyResidue) { fp := k.Fingerprint() key := k.generateKey() + residue = e2eCrypto.NewKeyResidue(key) + // encrypt the payload ecrContents = e2eCrypto.Crypt(key, fp, contents) @@ -122,25 +126,28 @@ func (k *cypher) Encrypt(contents []byte) (ecrContents, mac []byte) { // Currently, the MAC doesn't include any of the associated data mac = hash.CreateHMAC(ecrContents, key[:]) - return ecrContents, mac + return ecrContents, mac, residue } // Decrypt uses the E2E key to decrypt the message. It returns an error in case // of HMAC verification failure or in case of a decryption error (related to -// padding). -func (k *cypher) Decrypt(msg format.Message) ([]byte, error) { +// padding). It generates a residue of the key used to encrypt the contents +func (k *cypher) Decrypt(msg format.Message) (decryptedPayload []byte, residue e2eCrypto.KeyResidue, err error) { fp := k.Fingerprint() key := k.generateKey() // Verify the MAC is correct if !hash.VerifyHMAC(msg.GetContents(), msg.GetMac(), key[:]) { - return nil, errors.New("HMAC verification failed for E2E message") + return nil, e2eCrypto.KeyResidue{}, errors.New("HMAC verification failed for E2E message") } // Decrypt the payload - decryptedPayload := e2eCrypto.Crypt(key, fp, msg.GetContents()) + decryptedPayload = e2eCrypto.Crypt(key, fp, msg.GetContents()) + + // Construct residue + residue = e2eCrypto.NewKeyResidue(key) - return decryptedPayload, nil + return decryptedPayload, residue, nil } // Use sets the key as used. It cannot be used again. diff --git a/e2e/ratchet/partner/session/cypherHandler.go b/e2e/ratchet/partner/session/cypherHandler.go index 9bba56fec7c40ab1d0103cceb21aa0ab542d042a..d3124804aeb1d7cca17dea38897ab1dfa0d350c8 100644 --- a/e2e/ratchet/partner/session/cypherHandler.go +++ b/e2e/ratchet/partner/session/cypherHandler.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package session type CypherHandler interface { diff --git a/e2e/ratchet/partner/session/cypher_test.go b/e2e/ratchet/partner/session/cypher_test.go index b6c92de98bc3dcaf1b6e18237df418ad246dbe5b..470d6f2174540c0fcbec0482be983e2425eb5f8d 100644 --- a/e2e/ratchet/partner/session/cypher_test.go +++ b/e2e/ratchet/partner/session/cypher_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package session @@ -153,7 +153,7 @@ func Test_cypher_EncryptDecrypt(t *testing.T) { msg.SetContents(contents) // Encrypt - contentsEnc, mac := cy.Encrypt(msg.GetContents()) + contentsEnc, mac, _ := cy.Encrypt(msg.GetContents()) // Make the encrypted message ecrMsg := format.NewMessage(grp.GetP().ByteLen()) @@ -162,7 +162,7 @@ func Test_cypher_EncryptDecrypt(t *testing.T) { ecrMsg.SetMac(mac) // Decrypt - contentsDecr, err := cy.Decrypt(ecrMsg) + contentsDecr, _, err := cy.Decrypt(ecrMsg) if err != nil { t.Fatalf("Decrypt error: %+v", err) } diff --git a/e2e/ratchet/partner/session/negotiation.go b/e2e/ratchet/partner/session/negotiation.go index 267bf2d1e42804a34676abbbefb300c36655cecb..1f8b4ffec5043249e59d6d19cf2a0874fd7d4edc 100644 --- a/e2e/ratchet/partner/session/negotiation.go +++ b/e2e/ratchet/partner/session/negotiation.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package session diff --git a/e2e/ratchet/partner/session/params.go b/e2e/ratchet/partner/session/params.go index 2782578e9e605d117d2bb872f40822816c0fde2f..47e103f6d9a4b375c357a40338a1230f87ed604d 100644 --- a/e2e/ratchet/partner/session/params.go +++ b/e2e/ratchet/partner/session/params.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package session import ( diff --git a/e2e/ratchet/partner/session/relationshipType.go b/e2e/ratchet/partner/session/relationshipType.go index cb2220ad40f01a6508184ac520dd980d7f0c4cf8..3545a55596c40758e37cc79bedf0d6e959c181d9 100644 --- a/e2e/ratchet/partner/session/relationshipType.go +++ b/e2e/ratchet/partner/session/relationshipType.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package session diff --git a/e2e/ratchet/partner/session/session.go b/e2e/ratchet/partner/session/session.go index d0ee6ca19b1e233699ca6d7869e7e88420046b19..1ab3c1e771b64e2e5edd2d65aa0ace8a8abcbd89 100644 --- a/e2e/ratchet/partner/session/session.go +++ b/e2e/ratchet/partner/session/session.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package session @@ -239,7 +239,7 @@ func (s *Session) Save() error { jww.WARN.Printf("saving with KV: %v", s.kv) - return s.kv.Set(sessionKey, currentSessionVersion, &obj) + return s.kv.Set(sessionKey, &obj) } /*METHODS*/ diff --git a/e2e/ratchet/partner/session/sessionID.go b/e2e/ratchet/partner/session/sessionID.go index 82f0bf4f62699a8a53a2564282d837e32c825eaa..294c17e97e2d753e8074708bd79e7969826df195 100644 --- a/e2e/ratchet/partner/session/sessionID.go +++ b/e2e/ratchet/partner/session/sessionID.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package session diff --git a/e2e/ratchet/partner/session/session_test.go b/e2e/ratchet/partner/session/session_test.go index cd72eee94c90ab559435e8dded5ecc0dbf346094..ed7e7d0b5ff09e4dcf9ba5e1c90e7531c6ff656f 100644 --- a/e2e/ratchet/partner/session/session_test.go +++ b/e2e/ratchet/partner/session/session_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package session diff --git a/e2e/ratchet/partner/session/status.go b/e2e/ratchet/partner/session/status.go index 6494e31deafa043fa3bcf433fce5fea80cf772b4..294a0c9515550db475260bc9b5e75d06614a69e8 100644 --- a/e2e/ratchet/partner/session/status.go +++ b/e2e/ratchet/partner/session/status.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package session diff --git a/e2e/ratchet/partner/session/status_test.go b/e2e/ratchet/partner/session/status_test.go index 738db5260e63c0396613a3543475e38a4edc8392..7fe85d11fc2dc80212cfa1dc363a5940d5d1d432 100644 --- a/e2e/ratchet/partner/session/status_test.go +++ b/e2e/ratchet/partner/session/status_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package session diff --git a/e2e/ratchet/partner/session/testUtils.go b/e2e/ratchet/partner/session/testUtils.go index 61d82ea1f651820f0a9d76bcec396f094c820d4e..300d5e764d4fd8766fec9ee7c03d9bdb7ee73c1c 100644 --- a/e2e/ratchet/partner/session/testUtils.go +++ b/e2e/ratchet/partner/session/testUtils.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package session import ( diff --git a/e2e/ratchet/partner/utils.go b/e2e/ratchet/partner/utils.go index aa4c7d90e267848c50d53ce32ae87c63cb6febc9..ff0eef555cfda79fcc3fc8275375fb2e742f9388 100644 --- a/e2e/ratchet/partner/utils.go +++ b/e2e/ratchet/partner/utils.go @@ -1,13 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2022 Privategrity Corporation / -// / -// All rights reserved. / -//////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////// -// Copyright © 2022 Privategrity Corporation / -// / -// All rights reserved. / +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package partner diff --git a/e2e/ratchet/partner/utils_test.go b/e2e/ratchet/partner/utils_test.go index 17d28200b7c79868c7ca3f156b2d8f897b635e02..1aac1087aca130b60a0002da12f744f4cff2df6d 100644 --- a/e2e/ratchet/partner/utils_test.go +++ b/e2e/ratchet/partner/utils_test.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package partner import ( diff --git a/e2e/ratchet/ratchet.go b/e2e/ratchet/ratchet.go index 9995ba4eba11052ced441d53b897a1e310bccc60..b2421805ed9c3e0adac8971ed7959049589a735f 100644 --- a/e2e/ratchet/ratchet.go +++ b/e2e/ratchet/ratchet.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package ratchet diff --git a/e2e/ratchet/ratchet_test.go b/e2e/ratchet/ratchet_test.go index a1cdbcb881b893dd5ebb4ce470078236e62b9f40..45f0c3ed822ec0d491dc3bf82fde5ce8f4f46619 100644 --- a/e2e/ratchet/ratchet_test.go +++ b/e2e/ratchet/ratchet_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package ratchet diff --git a/e2e/ratchet/serviceList.go b/e2e/ratchet/serviceList.go index b382b5aced663ae8384b497052c29d57eb0ba71e..857a5be18218644bb58ec0d3746b8930daf76074 100644 --- a/e2e/ratchet/serviceList.go +++ b/e2e/ratchet/serviceList.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package ratchet import ( diff --git a/e2e/ratchet/serviceList_test.go b/e2e/ratchet/serviceList_test.go index 420d6c2756d43b1a468444005535852921b89ac1..522068190fa1a32fb023916517fdffd10f71c009 100644 --- a/e2e/ratchet/serviceList_test.go +++ b/e2e/ratchet/serviceList_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package ratchet diff --git a/e2e/ratchet/standardServices.go b/e2e/ratchet/standardServices.go index 0d28c336b789e6ba182fcbb7c85a04fceed06f2e..21ed8cccd1399be95f9ec88bfb052f1cff1616be 100644 --- a/e2e/ratchet/standardServices.go +++ b/e2e/ratchet/standardServices.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package ratchet const Silent = "silent" diff --git a/e2e/ratchet/storage.go b/e2e/ratchet/storage.go index 999938dc7ec1784743163acfd34a550a24134544..7db9c13a7c2ee1aa16e34ab55f70536f708230d4 100644 --- a/e2e/ratchet/storage.go +++ b/e2e/ratchet/storage.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package ratchet import ( @@ -92,7 +99,7 @@ func (r *Ratchet) save() error { Data: data, } - return r.kv.Set(storeKey, currentStoreVersion, &obj) + return r.kv.Set(storeKey, &obj) } // ekv functions diff --git a/e2e/ratchet/utils_test.go b/e2e/ratchet/utils_test.go index 27e735c9ed2c4b7b150b6c988884a79c1916407f..4444dd3a95df0f567c4239bd2f253e27633ff458 100644 --- a/e2e/ratchet/utils_test.go +++ b/e2e/ratchet/utils_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package ratchet diff --git a/e2e/receive/any.go b/e2e/receive/any.go index fddafa55cdf6cfda3b679129c5ca9a26e2ded07d..e849ef5924b42e4963db0e034e77368a026d3cf1 100644 --- a/e2e/receive/any.go +++ b/e2e/receive/any.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package receive diff --git a/e2e/receive/any_test.go b/e2e/receive/any_test.go index 9f554c1adc8faea4f410ac35ae5c3f41b89b7d8e..3cadcbffd7ec987140bcb52aa0f946abe15b46d1 100644 --- a/e2e/receive/any_test.go +++ b/e2e/receive/any_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package receive diff --git a/e2e/receive/byID.go b/e2e/receive/byID.go index 425cd036e6b7c0bccc307621a709b08098b5ba2e..39b128d6fb5c5b792f4a9b0dd51d7e711659cfa4 100644 --- a/e2e/receive/byID.go +++ b/e2e/receive/byID.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package receive diff --git a/e2e/receive/byID_test.go b/e2e/receive/byID_test.go index e8aebd2777242ff1e910876d0f2d964f493c3bc7..da58460a099e80f324f16096a176419abf55023c 100644 --- a/e2e/receive/byID_test.go +++ b/e2e/receive/byID_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package receive diff --git a/e2e/receive/byType.go b/e2e/receive/byType.go index 183e2da360b5c03fceba294bcc578b6c73f6fb86..f43badcd32d6f0b58c00508b88e610af14243b0b 100644 --- a/e2e/receive/byType.go +++ b/e2e/receive/byType.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package receive diff --git a/e2e/receive/byType_test.go b/e2e/receive/byType_test.go index 3ca6127d222f2b7b9038c7fbe7d2ac389c833969..140a7d2c3a99a558b7ee3a6744ae2ba260038e64 100644 --- a/e2e/receive/byType_test.go +++ b/e2e/receive/byType_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package receive diff --git a/e2e/receive/listener.go b/e2e/receive/listener.go index 5e1d34067c5b7709509c18de6000103d73107687..e30365a9e6ce23a6608108f3ac2e0ae5809f5858 100644 --- a/e2e/receive/listener.go +++ b/e2e/receive/listener.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package receive diff --git a/e2e/receive/listener_test.go b/e2e/receive/listener_test.go index e548ea7a488774b7b6be94182cda506a7484b23c..00b63beb6f00ab50314bba16b1a019d421af73c7 100644 --- a/e2e/receive/listener_test.go +++ b/e2e/receive/listener_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package receive diff --git a/e2e/receive/message.go b/e2e/receive/message.go index 673b1e6ae0f8d2a72bdfc1ee6076f011a8b96088..bdde788c0cc6dba4304842e2adb29ce141a1013a 100644 --- a/e2e/receive/message.go +++ b/e2e/receive/message.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package receive import ( diff --git a/e2e/receive/switchboard.go b/e2e/receive/switchboard.go index 3f6122df73beeafd49129e1ab0d859e32e3a8ea5..99b6bf170ddfd57f125873b390ed91f17b7c906c 100644 --- a/e2e/receive/switchboard.go +++ b/e2e/receive/switchboard.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package receive diff --git a/e2e/receive/switchboard_test.go b/e2e/receive/switchboard_test.go index 7d2f8c4ceff37b2be6a6abe09675d0e50a6822dc..9edc9526f82df58c37e5a69c07ff7ffd943d63e1 100644 --- a/e2e/receive/switchboard_test.go +++ b/e2e/receive/switchboard_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package receive diff --git a/e2e/rekey/compileProtobuf.sh b/e2e/rekey/compileProtobuf.sh new file mode 100644 index 0000000000000000000000000000000000000000..cdead4cfb3925ddd4acc58fab7d8436f76e58206 --- /dev/null +++ b/e2e/rekey/compileProtobuf.sh @@ -0,0 +1,14 @@ +#!/bin/bash +################################################################################ +## Copyright © 2022 xx foundation ## +## ## +## Use of this source code is governed by a license that can be found in the ## +## LICENSE file. ## +################################################################################ + +# This script will compile the Protobuf file to a Go file (pb.go). +# This is meant to be called from the top level of the repo. + +cd ./e2e/rekey/ || return + +protoc --go_out=. --go_opt=paths=source_relative ./xchange.proto diff --git a/e2e/rekey/confirm.go b/e2e/rekey/confirm.go index 449aefddbbd2bd3723545ad03c1df5f9424757f9..4e399584a95bf26ff3db3909f920fae43e256b1a 100644 --- a/e2e/rekey/confirm.go +++ b/e2e/rekey/confirm.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package rekey diff --git a/e2e/rekey/confirm_test.go b/e2e/rekey/confirm_test.go index 24de5fda04353b367d1d222d1517f48c09fb7cde..28623e1a97d58193b24ed4f840c96c48d35d181f 100644 --- a/e2e/rekey/confirm_test.go +++ b/e2e/rekey/confirm_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package rekey diff --git a/e2e/rekey/exchange.go b/e2e/rekey/exchange.go index 30345ca1a28cf7b30ea8db9fd6587289e4092aec..f90baf0f0909b76ecb6bb64cca4526c7a00e4132 100644 --- a/e2e/rekey/exchange.go +++ b/e2e/rekey/exchange.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package rekey @@ -16,12 +16,10 @@ import ( "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/crypto/e2e" "gitlab.com/xx_network/primitives/id" - "time" ) type E2eSender func(mt catalog.MessageType, recipient *id.ID, payload []byte, - cmixParams cmix.CMIXParams) ( - []id.Round, e2e.MessageID, time.Time, error) + cmixParams cmix.CMIXParams) (e2e.SendReport, error) func Start(switchboard *receive.Switchboard, ratchet *ratchet.Ratchet, sender E2eSender, net cmix.Client, grp *cyclic.Group, params Params) (stoppable.Stoppable, error) { diff --git a/e2e/rekey/exchange_test.go b/e2e/rekey/exchange_test.go index 2967d81cbf2cea380ae1c0e64393fbe493fa1851..a6b2f7fa1e87070ba102a94bbc585fa29437fb95 100644 --- a/e2e/rekey/exchange_test.go +++ b/e2e/rekey/exchange_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package rekey diff --git a/e2e/rekey/generate.sh b/e2e/rekey/generate.sh deleted file mode 100644 index cc5d530cece9c8a16123c820cc249f5db7216686..0000000000000000000000000000000000000000 --- a/e2e/rekey/generate.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -protoc --go_out=. -I../ -I$PWD --go_opt=paths=source_relative xchange.proto diff --git a/e2e/rekey/params.go b/e2e/rekey/params.go index 274770c112329cb552a85df55c6abc6d273cf67c..988526e7a7f4bf18ad3e16ce29063ca22113c52b 100644 --- a/e2e/rekey/params.go +++ b/e2e/rekey/params.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package rekey import ( diff --git a/e2e/rekey/rekey.go b/e2e/rekey/rekey.go index 960df918f20e3aee3e87a77ac4959668fc5db87c..c66e3c241637ae4d3984fc69002f74445337d141 100644 --- a/e2e/rekey/rekey.go +++ b/e2e/rekey/rekey.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package rekey @@ -125,7 +125,8 @@ func negotiate(instance *commsNetwork.Instance, grp *cyclic.Group, sendE2E E2eSe params := cmix.GetDefaultCMIXParams() params.DebugTag = "kx.Request" - rounds, msgID, _, err := sendE2E(param.Trigger, sess.GetPartner(), + // fixme: should this use the key residue? + sendReport, err := sendE2E(param.Trigger, sess.GetPartner(), payload, params) // If the send fails, returns the error so it can be handled. The caller // should ensure the calling session is in a state where the Rekey will @@ -137,18 +138,18 @@ func negotiate(instance *commsNetwork.Instance, grp *cyclic.Group, sendE2E E2eSe } //create the runner which will handle the result of sending the messages - sendResults := make(chan ds.EventReturn, len(rounds)) + sendResults := make(chan ds.EventReturn, len(sendReport.RoundList)) //Register the event for all rounds roundEvents := instance.GetRoundEvents() - for _, r := range rounds { + for _, r := range sendReport.RoundList { roundEvents.AddRoundEventChan(r, sendResults, sendTimeout, states.COMPLETED, states.FAILED) } //Wait until the result tracking responds success, numRoundFail, numTimeOut := cmix.TrackResults(sendResults, - len(rounds)) + len(sendReport.RoundList)) // If a single partition of the Key Negotiation request does not // transmit, the partner cannot read the result. Log the error and set @@ -157,14 +158,14 @@ func negotiate(instance *commsNetwork.Instance, grp *cyclic.Group, sendE2E E2eSe _ = sess.TrySetNegotiationStatus(session.Unconfirmed) return errors.Errorf("[REKEY] Key Negotiation rekey for %s failed to "+ "transmit %v/%v paritions: %v round failures, %v timeouts, msgID: %s", - sess, numRoundFail+numTimeOut, len(rounds), numRoundFail, - numTimeOut, msgID) + sess, numRoundFail+numTimeOut, len(sendReport.RoundList), numRoundFail, + numTimeOut, sendReport.MessageId) } // otherwise, the transmission is a success and this should be denoted // in the session and the log jww.INFO.Printf("[REKEY] Key Negotiation rekey transmission for %s, msgID %s successful", - sess, msgID) + sess, sendReport.MessageId) err = sess.TrySetNegotiationStatus(session.Sent) if err != nil { if sess.NegotiationStatus() == session.NewSessionTriggered { diff --git a/e2e/rekey/rekey_test.go b/e2e/rekey/rekey_test.go index ac5afe5fd8b9feb256e7b47c7dccc1efd85500be..58769e9acb197b39ca90e1202e2a503333f98909 100644 --- a/e2e/rekey/rekey_test.go +++ b/e2e/rekey/rekey_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package rekey diff --git a/e2e/rekey/trigger.go b/e2e/rekey/trigger.go index 80d2cd2b62a8a1840e8605aa79bc7d4e501cbb2d..0567c3c341f6b9f35b1b8d239dc3b65658a2c2b1 100644 --- a/e2e/rekey/trigger.go +++ b/e2e/rekey/trigger.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package rekey @@ -127,7 +127,8 @@ func handleTrigger(ratchet *ratchet.Ratchet, sender E2eSender, params := cmix.GetDefaultCMIXParams() params.Critical = true //ignore results, the passed sender interface makes it a critical message - _, _, _, _ = sender(param.Confirm, request.Sender, payload, + // fixme: should this ignore the error as well? + _, _ = sender(param.Confirm, request.Sender, payload, params) return nil diff --git a/e2e/rekey/trigger_test.go b/e2e/rekey/trigger_test.go index 8e9ab6658eb627babb1dd9acacd0150222f1a71c..0384d1b6a70c732bda30fd628cd16870142432cb 100644 --- a/e2e/rekey/trigger_test.go +++ b/e2e/rekey/trigger_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package rekey @@ -119,7 +119,8 @@ func TestHandleTrigger(t *testing.T) { rekeyParams := GetDefaultParams() stop := stoppable.NewSingle("stoppable") rekeyParams.RoundTimeout = 0 * time.Second - err = handleTrigger(r, testSendE2E, &mockNetManager{}, grp, receiveMsg, rekeyParams, stop) + err = handleTrigger(r, testSendE2E, &mockNetManager{}, grp, receiveMsg, + rekeyParams, stop) if err != nil { t.Errorf("Handle trigger error: %v", err) } diff --git a/e2e/rekey/utils_test.go b/e2e/rekey/utils_test.go index 3e1f77f1dcdc80a760498da5ea6b1905b90cec84..0b9fd388668ff77f9cbfed8bc7dc6dc6572d3eeb 100644 --- a/e2e/rekey/utils_test.go +++ b/e2e/rekey/utils_test.go @@ -1,13 +1,14 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package rekey import ( + "gitlab.com/elixxir/crypto/e2e" "math/rand" "testing" "time" @@ -27,7 +28,6 @@ import ( network2 "gitlab.com/elixxir/comms/network" ds "gitlab.com/elixxir/comms/network/dataStructures" "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" @@ -73,7 +73,8 @@ func genSidhKeys() (*sidh.PrivateKey, *sidh.PublicKey, *sidh.PrivateKey, *sidh.P } func testSendE2E(mt catalog.MessageType, recipient *id.ID, - payload []byte, cmixParams cmix.CMIXParams) ([]id.Round, e2e.MessageID, time.Time, error) { + payload []byte, cmixParams cmix.CMIXParams) ( + e2e.SendReport, error) { rounds := []id.Round{id.Round(0), id.Round(1), id.Round(2)} alicePartner, err := r.GetPartner(aliceID) if err != nil { @@ -109,7 +110,9 @@ func testSendE2E(mt catalog.MessageType, recipient *id.ID, bobSwitchboard.Speak(confirmMessage) - return rounds, e2e.MessageID{}, time.Time{}, nil + return e2e.SendReport{ + RoundList: rounds, + }, nil } var pub = "-----BEGIN CERTIFICATE-----\nMIIGHTCCBAWgAwIBAgIUOcAn9cpH+hyRH8/UfqtbFDoSxYswDQYJKoZIhvcNAQEL\nBQAwgZIxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTESMBAGA1UEBwwJQ2xhcmVt\nb250MRAwDgYDVQQKDAdFbGl4eGlyMRQwEgYDVQQLDAtEZXZlbG9wbWVudDEZMBcG\nA1UEAwwQZ2F0ZXdheS5jbWl4LnJpcDEfMB0GCSqGSIb3DQEJARYQYWRtaW5AZWxp\neHhpci5pbzAeFw0xOTA4MTYwMDQ4MTNaFw0yMDA4MTUwMDQ4MTNaMIGSMQswCQYD\nVQQGEwJVUzELMAkGA1UECAwCQ0ExEjAQBgNVBAcMCUNsYXJlbW9udDEQMA4GA1UE\nCgwHRWxpeHhpcjEUMBIGA1UECwwLRGV2ZWxvcG1lbnQxGTAXBgNVBAMMEGdhdGV3\nYXkuY21peC5yaXAxHzAdBgkqhkiG9w0BCQEWEGFkbWluQGVsaXh4aXIuaW8wggIi\nMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC7Dkb6VXFn4cdpU0xh6ji0nTDQ\nUyT9DSNW9I3jVwBrWfqMc4ymJuonMZbuqK+cY2l+suS2eugevWZrtzujFPBRFp9O\n14Jl3fFLfvtjZvkrKbUMHDHFehascwzrp3tXNryiRMmCNQV55TfITVCv8CLE0t1i\nbiyOGM9ZWYB2OjXt59j76lPARYww5qwC46vS6+3Cn2Yt9zkcrGeskWEFa2VttHqF\n910TP+DZk2R5C7koAh6wZYK6NQ4S83YQurdHAT51LKGrbGehFKXq6/OAXCU1JLi3\nkW2PovTb6MZuvxEiRmVAONsOcXKu7zWCmFjuZZwfRt2RhnpcSgzfrarmsGM0LZh6\nJY3MGJ9YdPcVGSz+Vs2E4zWbNW+ZQoqlcGeMKgsIiQ670g0xSjYICqldpt79gaET\n9PZsoXKEmKUaj6pq1d4qXDk7s63HRQazwVLGBdJQK8qX41eCdR8VMKbrCaOkzD5z\ngnEu0jBBAwdMtcigkMIk1GRv91j7HmqwryOBHryLi6NWBY3tjb4So9AppDQB41SH\n3SwNenAbNO1CXeUqN0hHX6I1bE7OlbjqI7tXdrTllHAJTyVVjenPel2ApMXp+LVR\ndDbKtwBiuM6+n+z0I7YYerxN1gfvpYgcXm4uye8dfwotZj6H2J/uSALsU2v9UHBz\nprdrLSZk2YpozJb+CQIDAQABo2kwZzAdBgNVHQ4EFgQUDaTvG7SwgRQ3wcYx4l+W\nMcZjX7owHwYDVR0jBBgwFoAUDaTvG7SwgRQ3wcYx4l+WMcZjX7owDwYDVR0TAQH/\nBAUwAwEB/zAUBgNVHREEDTALgglmb28uY28udWswDQYJKoZIhvcNAQELBQADggIB\nADKz0ST0uS57oC4rT9zWhFqVZkEGh1x1XJ28bYtNUhozS8GmnttV9SnJpq0EBCm/\nr6Ub6+Wmf60b85vCN5WDYdoZqGJEBjGGsFzl4jkYEE1eeMfF17xlNUSdt1qLCE8h\nU0glr32uX4a6nsEkvw1vo1Liuyt+y0cOU/w4lgWwCqyweu3VuwjZqDoD+3DShVzX\n8f1p7nfnXKitrVJt9/uE+AtAk2kDnjBFbRxCfO49EX4Cc5rADUVXMXm0itquGBYp\nMbzSgFmsMp40jREfLYRRzijSZj8tw14c2U9z0svvK9vrLCrx9+CZQt7cONGHpr/C\n/GIrP/qvlg0DoLAtjea73WxjSCbdL3Nc0uNX/ymXVHdQ5husMCZbczc9LYdoT2VP\nD+GhkAuZV9g09COtRX4VP09zRdXiiBvweiq3K78ML7fISsY7kmc8KgVH22vcXvMX\nCgGwbrxi6QbQ80rWjGOzW5OxNFvjhvJ3vlbOT6r9cKZGIPY8IdN/zIyQxHiim0Jz\noavr9CPDdQefu9onizsmjsXFridjG/ctsJxcUEqK7R12zvaTxu/CVYZbYEUFjsCe\nq6ZAACiEJGvGeKbb/mSPvGs2P1kS70/cGp+P5kBCKqrm586FB7BcafHmGFrWhT3E\nLOUYkOV/gADT2hVDCrkPosg7Wb6ND9/mhCVVhf4hLGRh\n-----END CERTIFICATE-----\n" @@ -233,13 +236,18 @@ func (m *mockNetManager) GetMaxMessageLength() int { func (m *mockNetManager) Send(recipient *id.ID, fingerprint format.Fingerprint, service message.Service, payload, mac []byte, cmixParams cmix.CMIXParams) ( - id.Round, ephemeral.Id, error) { - return id.Round(0), ephemeral.Id{}, nil + rounds.Round, ephemeral.Id, error) { + return rounds.Round{}, ephemeral.Id{}, nil +} + +func (m *mockNetManager) SendWithAssembler(recipient *id.ID, assembler cmix.MessageAssembler, + cmixParams cmix.CMIXParams) (rounds.Round, ephemeral.Id, error) { + return rounds.Round{}, ephemeral.Id{}, nil } func (m *mockNetManager) SendMany(messages []cmix.TargetedCmixMessage, p cmix.CMIXParams) ( - id.Round, []ephemeral.Id, error) { - return id.Round(0), nil, nil + rounds.Round, []ephemeral.Id, error) { + return rounds.Round{}, nil, nil } func (m *mockNetManager) AddIdentity(id *id.ID, validUntil time.Time, persistent bool) {} @@ -294,8 +302,7 @@ func (m *mockNetManager) NumRegisteredNodes() int { func (m *mockNetManager) TriggerNodeRegistration(nid *id.ID) {} func (m *mockNetManager) GetRoundResults(timeout time.Duration, roundCallback cmix.RoundEventCallback, - roundList ...id.Round) error { - return nil + roundList ...id.Round) { } func (m *mockNetManager) LookupHistoricalRound( diff --git a/e2e/rekey/xchange.pb.go b/e2e/rekey/xchange.pb.go index a9b5f46ef0202e6b9e442b10f52c4298cf561489..48b98f7823388a708a2de226046bbf11bdb44ee2 100644 --- a/e2e/rekey/xchange.pb.go +++ b/e2e/rekey/xchange.pb.go @@ -1,15 +1,13 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// - -// Call ./generate.sh to generate the protocol buffer code +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.26.0 +// protoc-gen-go v1.27.1 // protoc v3.15.6 // source: xchange.proto @@ -147,7 +145,7 @@ var File_xchange_proto protoreflect.FileDescriptor var file_xchange_proto_rawDesc = []byte{ 0x0a, 0x0d, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, - 0x05, 0x70, 0x61, 0x72, 0x73, 0x65, 0x22, 0x70, 0x0a, 0x0c, 0x52, 0x65, 0x6b, 0x65, 0x79, 0x54, + 0x05, 0x72, 0x65, 0x6b, 0x65, 0x79, 0x22, 0x70, 0x0a, 0x0c, 0x52, 0x65, 0x6b, 0x65, 0x79, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x24, 0x0a, 0x0d, 0x73, 0x69, 0x64, 0x68, 0x50, 0x75, 0x62, 0x6c, @@ -157,10 +155,10 @@ var file_xchange_proto_rawDesc = []byte{ 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x22, 0x2c, 0x0a, 0x0c, 0x52, 0x65, 0x6b, 0x65, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x65, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x42, 0x27, 0x5a, 0x25, 0x67, 0x69, 0x74, 0x6c, 0x61, 0x62, + 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x42, 0x25, 0x5a, 0x23, 0x67, 0x69, 0x74, 0x6c, 0x61, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x6c, 0x69, 0x78, 0x78, 0x69, 0x72, 0x2f, 0x63, 0x6c, 0x69, - 0x65, 0x6e, 0x74, 0x2f, 0x6b, 0x65, 0x79, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x6e, 0x74, 0x2f, 0x65, 0x32, 0x65, 0x2f, 0x72, 0x65, 0x6b, 0x65, 0x79, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -177,8 +175,8 @@ func file_xchange_proto_rawDescGZIP() []byte { var file_xchange_proto_msgTypes = make([]protoimpl.MessageInfo, 2) var file_xchange_proto_goTypes = []interface{}{ - (*RekeyTrigger)(nil), // 0: parse.RekeyTrigger - (*RekeyConfirm)(nil), // 1: parse.RekeyConfirm + (*RekeyTrigger)(nil), // 0: rekey.RekeyTrigger + (*RekeyConfirm)(nil), // 1: rekey.RekeyConfirm } var file_xchange_proto_depIdxs = []int32{ 0, // [0:0] is the sub-list for method output_type diff --git a/e2e/rekey/xchange.proto b/e2e/rekey/xchange.proto index 48fda885b39d7a4368e96286f0e4dc95787482db..efd3fe49f5c6d8cbb2677d7cc03a1949b123a1f1 100644 --- a/e2e/rekey/xchange.proto +++ b/e2e/rekey/xchange.proto @@ -1,17 +1,15 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// - -// Call ./generate.sh to generate the protocol buffer code +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// syntax = "proto3"; -package parse; -option go_package = "gitlab.com/elixxir/client/keyExchange"; +package rekey; +option go_package = "gitlab.com/elixxir/client/e2e/rekey"; message RekeyTrigger { // PublicKey used in the rekey diff --git a/e2e/sendE2E.go b/e2e/sendE2E.go index 284008a92d92988b56abb6f6e81fd49381be94e0..c05700842e7264a04358be6803e8ac4ed038afb9 100644 --- a/e2e/sendE2E.go +++ b/e2e/sendE2E.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package e2e import ( @@ -19,11 +26,24 @@ import ( "gitlab.com/xx_network/primitives/netTime" ) +// SendE2E send a message containing the payload to the +// recipient of the passed message type, per the given +// parameters - encrypted with end-to-end encryption. +// Default parameters can be retrieved through +// GetDefaultParams() +// If too long, it will chunk a message up into its messages +// and send each as a separate cmix message. It will return +// the list of all rounds sent on, a unique ID for the +// message, and the timestamp sent on. +// the recipient must already have an e2e relationship, +// otherwise an error will be returned. +// Will return an error if the network is not healthy or in +// the event of a failed send func (m *manager) SendE2E(mt catalog.MessageType, recipient *id.ID, - payload []byte, params Params) ([]id.Round, e2e.MessageID, time.Time, error) { + payload []byte, params Params) (e2e.SendReport, error) { if !m.net.IsHealthy() { - return nil, e2e.MessageID{}, time.Time{}, + return e2e.SendReport{}, errors.New("cannot sendE2E when network is not healthy") } @@ -35,18 +55,18 @@ func (m *manager) SendE2E(mt catalog.MessageType, recipient *id.ID, params.Critical = false } - rounds, msgID, t, err := m.sendE2E(mt, recipient, payload, params) + sendReport, err := m.sendE2E(mt, recipient, payload, params) if handleCritical { - m.crit.handle(mt, recipient, payload, rounds, err) + m.crit.handle(mt, recipient, payload, sendReport.RoundList, err) } - return rounds, msgID, t, err + return sendReport, err } // sendE2eFn contains a prepared sendE2E operation and sends an E2E message when // called, returning the results of the send. -type sendE2eFn func() ([]id.Round, e2e.MessageID, time.Time, error) +type sendE2eFn func() (e2e.SendReport, error) // prepareSendE2E makes a prepared function that does the e2e send. // This is so that when doing deletePartner we can prepare the send before @@ -63,41 +83,46 @@ func (m *manager) prepareSendE2E(mt catalog.MessageType, recipient *id.ID, partitions, internalMsgId, err := m.partitioner.Partition(recipient, mt, ts, payload) if err != nil { - return nil, errors.WithMessage(err, "failed to send unsafe message") + return nil, errors.WithMessage(err, + "failed to send unsafe message") } - jww.INFO.Printf("E2E sending %d messages to %s", len(partitions), recipient) + jww.INFO.Printf("E2E sending %d messages to %s", + len(partitions), recipient) - // When sending E2E messages, we first partition into cMix packets and then - // send each partition over cMix + // When sending E2E messages, we first partition into cMix + // packets and then send each partition over cMix roundIds := make([]id.Round, len(partitions)) errCh := make(chan error, len(partitions)) - // The Key manager for the partner (recipient) ensures single use of each - // key negotiated for the ratchet + // The Key manager for the partner (recipient) ensures single + // use of each key negotiated for the ratchet partner, err := m.Ratchet.GetPartner(recipient) if err != nil { return nil, errors.WithMessagef(err, - "cannot send E2E message no relationship found with %s", recipient) + "cannot send E2E message no relationship found with %s", + recipient) } msgID := e2e.NewMessageID( partner.SendRelationshipFingerprint(), internalMsgId) wg := sync.WaitGroup{} - + var keyResidue e2e.KeyResidue for i, p := range partitions { if mt != catalog.KeyExchangeTrigger { // Check if any rekeys need to happen and trigger them - rekeySendFunc := func(mt catalog.MessageType, recipient *id.ID, + rekeySendFunc := func(mt catalog.MessageType, + recipient *id.ID, payload []byte, cmixParams cmix.CMIXParams) ( - []id.Round, e2e.MessageID, time.Time, error) { + e2e.SendReport, error) { par := params par.CMIXParams = cmixParams return m.SendE2E(mt, recipient, payload, par) } - rekey.CheckKeyExchanges(m.net.GetInstance(), m.grp, rekeySendFunc, - m.events, partner, m.rekeyParams, 1*time.Minute) + rekey.CheckKeyExchanges(m.net.GetInstance(), m.grp, + rekeySendFunc, m.events, partner, + m.rekeyParams, 1*time.Minute) } var keyGetter func() (session.Cypher, error) @@ -107,23 +132,29 @@ func (m *manager) prepareSendE2E(mt catalog.MessageType, recipient *id.ID, keyGetter = partner.PopSendCypher } - // FIXME: remove this wait, it is weird. Why is it here? we cant remember. + // FIXME: remove this wait, it is weird. Why is it + // here? we cant remember. key, err := waitForKey( - keyGetter, params.KeyGetRetryCount, params.KeyGeRetryDelay, + keyGetter, params.KeyGetRetryCount, + params.KeyGeRetryDelay, params.Stop, recipient, format.DigestContents(p), i) if err != nil { return nil, errors.WithMessagef(err, "Failed to get key for end-to-end encryption") } - // This does not encrypt for cMix but instead end-to-end encrypts the - // cMix message - contentsEnc, mac := key.Encrypt(p) + // This does not encrypt for cMix but instead + // end-to-end encrypts the cMix message + contentsEnc, mac, residue := key.Encrypt(p) + // Carry the first key residue to the top level + if i == 0 { + keyResidue = residue + } - jww.INFO.Printf( - "E2E sending %d/%d to %s with key fp: %s, msgID: %s (msgDigest %s)", - i+i, len(partitions), recipient, key.Fingerprint(), msgID, - format.DigestContents(p)) + jww.INFO.Printf("E2E sending %d/%d to %s with key fp: %s, "+ + "msgID: %s (msgDigest %s)", + i+i, len(partitions), recipient, key.Fingerprint(), + msgID, format.DigestContents(p)) var s message.Service if i == len(partitions)-1 { @@ -132,25 +163,29 @@ func (m *manager) prepareSendE2E(mt catalog.MessageType, recipient *id.ID, s = partner.MakeService(params.ServiceTag) } - // We send each partition in its own thread here; some may send in round - // X, others in X+1 or X+2, and so on + // We send each partition in its own thread here; some + // may send in round X, others in X+1 or X+2, and so + // on localI := i thisSendFunc := func() { wg.Add(1) go func(i int) { - var err error - roundIds[i], _, err = m.net.Send(recipient, - key.Fingerprint(), s, contentsEnc, mac, params.CMIXParams) + r, _, err := m.net.Send(recipient, + key.Fingerprint(), s, contentsEnc, mac, + params.CMIXParams) if err != nil { + jww.DEBUG.Printf("[E2E] cMix error on "+ + "Send: %+v", err) errCh <- err } + roundIds[i] = r.ID wg.Done() }(localI) } sendFuncs = append(sendFuncs, thisSendFunc) } - sendE2E = func() ([]id.Round, e2e.MessageID, time.Time, error) { + sendE2E = func() (e2e.SendReport, error) { for i := range sendFuncs { sendFuncs[i]() } @@ -161,27 +196,33 @@ func (m *manager) prepareSendE2E(mt catalog.MessageType, recipient *id.ID, if numFail > 0 { jww.INFO.Printf("Failed to E2E send %d/%d to %s", numFail, len(partitions), recipient) - return nil, e2e.MessageID{}, time.Time{}, errors.Errorf( + return e2e.SendReport{}, errors.Errorf( "Failed to E2E send %v/%v sub payloads: %s", numFail, len(partitions), errRtn) } else { jww.INFO.Printf("Successfully E2E sent %d/%d to %s", - len(partitions)-numFail, len(partitions), recipient) + len(partitions)-numFail, len(partitions), + recipient) } - jww.INFO.Printf("Successful E2E Send of %d messages to %s with msgID %s", - len(partitions), recipient, msgID) + jww.INFO.Printf("Successful E2E Send of %d messages to %s "+ + "with msgID %s", len(partitions), recipient, msgID) - return roundIds, msgID, ts, nil + return e2e.SendReport{ + RoundList: roundIds, + MessageId: msgID, + SentTime: ts, + KeyResidue: keyResidue, + }, nil } return sendE2E, nil } func (m *manager) sendE2E(mt catalog.MessageType, recipient *id.ID, - payload []byte, params Params) ([]id.Round, e2e.MessageID, time.Time, error) { + payload []byte, params Params) (e2e.SendReport, error) { sendFunc, err := m.prepareSendE2E(mt, recipient, payload, params) if err != nil { - return nil, e2e.MessageID{}, time.Time{}, err + return e2e.SendReport{}, err } return sendFunc() } diff --git a/e2e/sendE2E_test.go b/e2e/sendE2E_test.go index d316b90c79a388ac32c405542e49d882089138d1..58afc0e9c3062ee0b768deff58004cb6f45bfdbf 100644 --- a/e2e/sendE2E_test.go +++ b/e2e/sendE2E_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package e2e @@ -22,6 +22,7 @@ import ( "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/crypto/cyclic" dh "gitlab.com/elixxir/crypto/diffieHellman" + "gitlab.com/elixxir/crypto/e2e" "gitlab.com/elixxir/crypto/fastRNG" "gitlab.com/elixxir/ekv" "gitlab.com/elixxir/primitives/format" @@ -106,7 +107,7 @@ func Test_manager_SendE2E_Smoke(t *testing.T) { payload := []byte("My Payload") p := GetDefaultParams() - _, _, _, err = m1.SendE2E(catalog.NoType, partnerID, payload, p) + _, err = m1.SendE2E(catalog.NoType, partnerID, payload, p) if err != nil { t.Errorf("SendE2E failed: %+v", err) } @@ -221,11 +222,15 @@ type mockWaitForKeyCypher struct { cypherNum int } -func (m *mockWaitForKeyCypher) GetSession() *session.Session { return nil } -func (m *mockWaitForKeyCypher) Fingerprint() format.Fingerprint { return format.Fingerprint{} } -func (m *mockWaitForKeyCypher) Encrypt([]byte) ([]byte, []byte) { return nil, nil } -func (m *mockWaitForKeyCypher) Decrypt(format.Message) ([]byte, error) { return nil, nil } -func (m *mockWaitForKeyCypher) Use() {} +func (m *mockWaitForKeyCypher) GetSession() *session.Session { return nil } +func (m *mockWaitForKeyCypher) Fingerprint() format.Fingerprint { return format.Fingerprint{} } +func (m *mockWaitForKeyCypher) Encrypt([]byte) ([]byte, []byte, e2e.KeyResidue) { + return nil, nil, e2e.KeyResidue{} +} +func (m *mockWaitForKeyCypher) Decrypt(format.Message) ([]byte, e2e.KeyResidue, error) { + return nil, e2e.KeyResidue{}, nil +} +func (m *mockWaitForKeyCypher) Use() {} // Tests that getSendErrors returns all the errors on the channel. func Test_getSendErrors(t *testing.T) { diff --git a/e2e/sendUnsafe.go b/e2e/sendUnsafe.go index 4451f16c4f12062dee8ee883ccc10de83f225e69..b59bd3243bfb6a9208c302761580cf6f90417983 100644 --- a/e2e/sendUnsafe.go +++ b/e2e/sendUnsafe.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package e2e import ( @@ -65,13 +72,13 @@ func (m *manager) sendUnsafe(mt catalog.MessageType, recipient *id.ID, jww.TRACE.Printf("sendUnsafe contents: %v, fp: %v, mac: %v", payload, fp, unencryptedMAC) - var err error - roundIds[i], _, err = m.net.Send(recipient, fp, + r, _, err := m.net.Send(recipient, fp, srvc, payload, unencryptedMAC, params.CMIXParams) if err != nil { errCh <- err } + roundIds[i] = r.ID wg.Done() }(i, p) } diff --git a/e2e/sendUnsafe_test.go b/e2e/sendUnsafe_test.go index d30e6e15f9c2f6e8673e2f790c83199045d0c9c2..0df0532e61a3035c8e6ea6a4e2bc0355beeb911f 100644 --- a/e2e/sendUnsafe_test.go +++ b/e2e/sendUnsafe_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package e2e diff --git a/e2e/unsafeProcessor.go b/e2e/unsafeProcessor.go index 3cd173d525244ea2bdb15cd1c28fe4af1847ce58..5f1c7fb3eb7094e49d00b49b426f093e25745a60 100644 --- a/e2e/unsafeProcessor.go +++ b/e2e/unsafeProcessor.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package e2e import ( @@ -33,8 +40,9 @@ func (up *UnsafeProcessor) Process(ecrMsg format.Message, } //Parse - message, done := up.m.partitioner.HandlePartition(sender, - ecrMsg.GetContents(), nil) + // todo: handle residue here + message, _, done := up.m.partitioner.HandlePartition(sender, + ecrMsg.GetContents(), nil, e2e.KeyResidue{}) if done { message.RecipientID = receptionID.Source diff --git a/e2e/util.go b/e2e/util.go index dad7da4702ad53ac2ee1a4c4fed55dfd5814b9e7..f8fc28c2a3e4b2efbaf8a5ed7d72e141883bd802 100644 --- a/e2e/util.go +++ b/e2e/util.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package e2e import ( diff --git a/e2e/utils_test.go b/e2e/utils_test.go index 72bcfb3402d76c2d22b8351f1283a367ba771fc9..6d8835b8c51edaf47ca2821521e9e55de95f5db3 100644 --- a/e2e/utils_test.go +++ b/e2e/utils_test.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package e2e import ( @@ -174,7 +181,7 @@ func (m *mockCmix) GetMaxMessageLength() int { } func (m *mockCmix) Send(_ *id.ID, fp format.Fingerprint, srv message.Service, - payload, mac []byte, _ cmix.CMIXParams) (id.Round, ephemeral.Id, error) { + payload, mac []byte, _ cmix.CMIXParams) (rounds.Round, ephemeral.Id, error) { m.handler.Lock() defer m.handler.Unlock() @@ -186,21 +193,26 @@ func (m *mockCmix) Send(_ *id.ID, fp format.Fingerprint, srv message.Service, if m.handler.processorMap[fp] != nil { m.handler.processorMap[fp].Process( msg, receptionID.EphemeralIdentity{}, rounds.Round{}) - return 0, ephemeral.Id{}, nil + return rounds.Round{}, ephemeral.Id{}, nil } else if m.handler.serviceMap[srv.Tag] != nil { m.handler.serviceMap[srv.Tag].Process( msg, receptionID.EphemeralIdentity{}, rounds.Round{}) - return 0, ephemeral.Id{}, nil + return rounds.Round{}, ephemeral.Id{}, nil } m.t.Errorf("No processor found for fingerprint %s", fp) - return 0, ephemeral.Id{}, + return rounds.Round{}, ephemeral.Id{}, errors.Errorf("No processor found for fingerprint %s", fp) } -func (m *mockCmix) SendMany([]cmix.TargetedCmixMessage, cmix.CMIXParams) (id.Round, []ephemeral.Id, error) { - return 0, nil, nil +func (m *mockCmix) SendWithAssembler(recipient *id.ID, assembler cmix.MessageAssembler, + cmixParams cmix.CMIXParams) (rounds.Round, ephemeral.Id, error) { + panic("implement me") +} + +func (m *mockCmix) SendMany([]cmix.TargetedCmixMessage, cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error) { + return rounds.Round{}, nil, nil } func (m *mockCmix) AddIdentity(*id.ID, time.Time, bool) {} func (m *mockCmix) RemoveIdentity(*id.ID) {} @@ -238,8 +250,7 @@ func (m *mockCmix) RemoveHealthCallback(uint64) {} func (m *mockCmix) HasNode(*id.ID) bool { return true } func (m *mockCmix) NumRegisteredNodes() int { return 0 } func (m *mockCmix) TriggerNodeRegistration(*id.ID) {} -func (m *mockCmix) GetRoundResults(time.Duration, cmix.RoundEventCallback, ...id.Round) error { - return nil +func (m *mockCmix) GetRoundResults(time.Duration, cmix.RoundEventCallback, ...id.Round) { } func (m *mockCmix) LookupHistoricalRound(id.Round, rounds.RoundResultCallback) error { return nil } func (m *mockCmix) SendToAny(func(host *connect.Host) (interface{}, error), *stoppable.Single) (interface{}, error) { diff --git a/event/event.go b/event/event.go index 1b017009e991c089bd9b7be930759bd2a1d3ffec..441fa394413d66d87259a744cf51ec7a595451d2 100644 --- a/event/event.go +++ b/event/event.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package event diff --git a/event/event_test.go b/event/event_test.go index d657206bac2cbf2ed761ab454e6728484931a6f6..5ee6080ce8aff0ff2cabb0a11cc26c715fa9fa81 100644 --- a/event/event_test.go +++ b/event/event_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package event diff --git a/event/interface.go b/event/interface.go index 867e4dd9c11760474240c27a3661b910b8fe061d..2ef24fd6d607508104c34f8b7cef7d34aae27950 100644 --- a/event/interface.go +++ b/event/interface.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package event diff --git a/fileTransfer/batchBuilder.go b/fileTransfer/batchBuilder.go index 24749e77ad9c16deff40c2e489fd4a7f3f34ce08..6b529d5ba187394b85e207fb53024a733bd9ea12 100644 --- a/fileTransfer/batchBuilder.go +++ b/fileTransfer/batchBuilder.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package fileTransfer diff --git a/fileTransfer/callbackTracker/callbackTracker.go b/fileTransfer/callbackTracker/callbackTracker.go index 441ee157ea0cd9296bd5424f2d026ee6df217489..40728d9b6437f88636a6621045862df969587a8d 100644 --- a/fileTransfer/callbackTracker/callbackTracker.go +++ b/fileTransfer/callbackTracker/callbackTracker.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package callbackTracker diff --git a/fileTransfer/callbackTracker/callbackTracker_test.go b/fileTransfer/callbackTracker/callbackTracker_test.go index 7ffbe6636f3bc8abd56db36befbc699bfba22181..ad6882cc3833d42fe7133212945bab5b13a0ebcd 100644 --- a/fileTransfer/callbackTracker/callbackTracker_test.go +++ b/fileTransfer/callbackTracker/callbackTracker_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package callbackTracker diff --git a/fileTransfer/callbackTracker/manager.go b/fileTransfer/callbackTracker/manager.go index e6c4cf437ad0d625454667950d2a136baa8f20d2..4f03b0e3e26d25ce0cf4c9adde5766b272244907 100644 --- a/fileTransfer/callbackTracker/manager.go +++ b/fileTransfer/callbackTracker/manager.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package callbackTracker diff --git a/fileTransfer/callbackTracker/manager_test.go b/fileTransfer/callbackTracker/manager_test.go index 4226807f18a728345fc4907758bd27ae21b6dcc1..920fb2f9eb165e4731d91b243d91ad56b811e6c1 100644 --- a/fileTransfer/callbackTracker/manager_test.go +++ b/fileTransfer/callbackTracker/manager_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package callbackTracker diff --git a/fileTransfer/compileProtobuf.sh b/fileTransfer/compileProtobuf.sh new file mode 100644 index 0000000000000000000000000000000000000000..1aea86bde01d7493ccec94c6e2138236eff834ed --- /dev/null +++ b/fileTransfer/compileProtobuf.sh @@ -0,0 +1,14 @@ +#!/bin/bash +################################################################################ +## Copyright © 2022 xx foundation ## +## ## +## Use of this source code is governed by a license that can be found in the ## +## LICENSE file. ## +################################################################################ + +# This script will compile the Protobuf file to a Go file (pb.go). +# This is meant to be called from the top level of the repo. + +cd ./fileTransfer/ || return + +protoc --go_out=. --go_opt=paths=source_relative ./ftMessages.proto diff --git a/fileTransfer/connect/listener.go b/fileTransfer/connect/listener.go index 6eadbe4bc2222476d945e5aa23d4124a51b0f4db..12b64eb0f5f125cefaaa9b5dbda9ff52018e66ec 100644 --- a/fileTransfer/connect/listener.go +++ b/fileTransfer/connect/listener.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package connect diff --git a/fileTransfer/connect/params.go b/fileTransfer/connect/params.go index bd36ef4f6addca4c0f7f6de98f9e7224bb725187..5382603ffc0c486b6b6e4951ee6d6fdb43781c24 100644 --- a/fileTransfer/connect/params.go +++ b/fileTransfer/connect/params.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package connect diff --git a/fileTransfer/connect/send.go b/fileTransfer/connect/send.go index 2b00c8ba71cc8817a2764025ae34f8e4bdcc3438..dadd7b4d23f64035a17f2efc2db47a9146d74c51 100644 --- a/fileTransfer/connect/send.go +++ b/fileTransfer/connect/send.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package connect @@ -45,7 +45,7 @@ func sendNewFileTransferMessage( params.LastServiceTag = catalog.Silent params.DebugTag = initialMessageDebugTag - _, _, _, err := connectionHandler.SendE2E( + _, err := connectionHandler.SendE2E( catalog.NewFileTransfer, transferInfo, params) if err != nil { return errors.Errorf(errNewFtSendE2e, err) @@ -65,7 +65,7 @@ func sendEndFileTransferMessage(cmix ft.Cmix, connectionHandler connection) { params.LastServiceTag = catalog.EndFT params.DebugTag = lastMessageDebugTag - _, _, _, err := connectionHandler.SendE2E( + _, err := connectionHandler.SendE2E( catalog.EndFileTransfer, nil, params) if err != nil { jww.ERROR.Printf(errEndFtSendE2e, err) diff --git a/fileTransfer/connect/utils_test.go b/fileTransfer/connect/utils_test.go index 7d0fb6aeba668c2fcccf89cd881746007a84a101..83d75d020beccafe57c72331b0595a05253c0470 100644 --- a/fileTransfer/connect/utils_test.go +++ b/fileTransfer/connect/utils_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package connect @@ -26,7 +26,7 @@ import ( "gitlab.com/elixxir/client/xxdk" "gitlab.com/elixxir/comms/network" "gitlab.com/elixxir/crypto/cyclic" - e2eCrypto "gitlab.com/elixxir/crypto/e2e" + cryptoE2e "gitlab.com/elixxir/crypto/e2e" "gitlab.com/elixxir/crypto/fastRNG" "gitlab.com/elixxir/ekv" "gitlab.com/elixxir/primitives/format" @@ -38,7 +38,6 @@ import ( "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/id/ephemeral" "gitlab.com/xx_network/primitives/ndf" - "gitlab.com/xx_network/primitives/netTime" "sync" "testing" "time" @@ -116,12 +115,17 @@ func (m *mockCmix) GetMaxMessageLength() int { } func (m *mockCmix) Send(*id.ID, format.Fingerprint, message.Service, []byte, - []byte, cmix.CMIXParams) (id.Round, ephemeral.Id, error) { + []byte, cmix.CMIXParams) (rounds.Round, ephemeral.Id, error) { + panic("implement me") +} + +func (m *mockCmix) SendWithAssembler(recipient *id.ID, assembler cmix.MessageAssembler, + cmixParams cmix.CMIXParams) (rounds.Round, ephemeral.Id, error) { panic("implement me") } func (m *mockCmix) SendMany(messages []cmix.TargetedCmixMessage, - _ cmix.CMIXParams) (id.Round, []ephemeral.Id, error) { + _ cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error) { m.handler.Lock() for _, targetedMsg := range messages { msg := format.NewMessage(m.numPrimeBytes) @@ -133,7 +137,7 @@ func (m *mockCmix) SendMany(messages []cmix.TargetedCmixMessage, rounds.Round{ID: 42}) } m.handler.Unlock() - return 42, []ephemeral.Id{}, nil + return rounds.Round{ID: 42}, []ephemeral.Id{}, nil } func (m *mockCmix) AddIdentity(*id.ID, time.Time, bool) { panic("implement me") } @@ -185,9 +189,8 @@ func (m *mockCmix) NumRegisteredNodes() int { panic("implement me") } func (m *mockCmix) TriggerNodeRegistration(*id.ID) { panic("implement me") } func (m *mockCmix) GetRoundResults(_ time.Duration, - roundCallback cmix.RoundEventCallback, _ ...id.Round) error { + roundCallback cmix.RoundEventCallback, _ ...id.Round) { go roundCallback(true, false, map[id.Round]cmix.RoundResult{42: {}}) - return nil } func (m *mockCmix) LookupHistoricalRound(id.Round, rounds.RoundResultCallback) error { @@ -268,7 +271,7 @@ func (m *mockConnection) GetPartner() partner.Manager { // SendE2E adds the message to the e2e handler map. func (m *mockConnection) SendE2E(mt catalog.MessageType, payload []byte, - _ e2e.Params) ([]id.Round, e2eCrypto.MessageID, time.Time, error) { + _ e2e.Params) (cryptoE2e.SendReport, error) { m.handler.Lock() defer m.handler.Unlock() @@ -278,7 +281,7 @@ func (m *mockConnection) SendE2E(mt catalog.MessageType, payload []byte, Sender: m.myID, }) - return []id.Round{42}, e2eCrypto.MessageID{}, netTime.Now(), nil + return cryptoE2e.SendReport{RoundList: []id.Round{42}}, nil } func (m *mockConnection) RegisterListener(mt catalog.MessageType, diff --git a/fileTransfer/connect/wrapper.go b/fileTransfer/connect/wrapper.go index 60a3f6641da53aad60d53a29feb533180738556b..135985d0bdcb4613e4f5db7a183e32b2637c4519 100644 --- a/fileTransfer/connect/wrapper.go +++ b/fileTransfer/connect/wrapper.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package connect @@ -13,9 +13,8 @@ import ( "gitlab.com/elixxir/client/e2e/ratchet/partner" "gitlab.com/elixxir/client/e2e/receive" ft "gitlab.com/elixxir/client/fileTransfer" - e2eCrypto "gitlab.com/elixxir/crypto/e2e" + cryptoE2e "gitlab.com/elixxir/crypto/e2e" ftCrypto "gitlab.com/elixxir/crypto/fileTransfer" - "gitlab.com/xx_network/primitives/id" "time" ) @@ -41,7 +40,7 @@ type Wrapper struct { type connection interface { GetPartner() partner.Manager SendE2E(mt catalog.MessageType, payload []byte, params e2e.Params) ( - []id.Round, e2eCrypto.MessageID, time.Time, error) + cryptoE2e.SendReport, error) RegisterListener(messageType catalog.MessageType, newListener receive.Listener) (receive.ListenerID, error) } diff --git a/fileTransfer/connect/wrapper_test.go b/fileTransfer/connect/wrapper_test.go index a9b7552044d439c31c25a15e1cfb01be13f886bf..a8f38730cb7885d81713e6c9713bfd348f144075 100644 --- a/fileTransfer/connect/wrapper_test.go +++ b/fileTransfer/connect/wrapper_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package connect diff --git a/fileTransfer/delayedTimer.go b/fileTransfer/delayedTimer.go index e07af67d67bf92fcb8807ca0cee48bcdd631beb1..085852e609f79130f5f905c813fa90834bca1eaf 100644 --- a/fileTransfer/delayedTimer.go +++ b/fileTransfer/delayedTimer.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package fileTransfer diff --git a/fileTransfer/e2e/listener.go b/fileTransfer/e2e/listener.go index 4a07ed9d0682bc9e3af37d67e9e4dcc8902971dc..f2adcf2e2ecc5091a7b4eb1882ad94b90f43435a 100644 --- a/fileTransfer/e2e/listener.go +++ b/fileTransfer/e2e/listener.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package e2e diff --git a/fileTransfer/e2e/params.go b/fileTransfer/e2e/params.go index 819e963f5fd9efc3d058b5a953e87c7aa8874f1f..07377414d0d8e084dc39a1a05fead9b40cf987d6 100644 --- a/fileTransfer/e2e/params.go +++ b/fileTransfer/e2e/params.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package e2e diff --git a/fileTransfer/e2e/send.go b/fileTransfer/e2e/send.go index a073d0afe841a04026081b9033e0e1cc5c164062..2aa2b5a9bf84b528071f0540b8d076c6db26afd0 100644 --- a/fileTransfer/e2e/send.go +++ b/fileTransfer/e2e/send.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package e2e @@ -46,7 +46,7 @@ func sendNewFileTransferMessage( params.LastServiceTag = catalog.Silent params.DebugTag = initialMessageDebugTag - _, _, _, err := e2eHandler.SendE2E( + _, err := e2eHandler.SendE2E( catalog.NewFileTransfer, recipient, transferInfo, params) if err != nil { return errors.Errorf(errNewFtSendE2e, err) @@ -66,7 +66,7 @@ func sendEndFileTransferMessage(recipient *id.ID, cmix ft.Cmix, e2eHandler e2eHa params.LastServiceTag = catalog.EndFT params.DebugTag = lastMessageDebugTag - _, _, _, err := e2eHandler.SendE2E( + _, err := e2eHandler.SendE2E( catalog.EndFileTransfer, recipient, nil, params) if err != nil { jww.ERROR.Printf(errEndFtSendE2e, err) diff --git a/fileTransfer/e2e/utils_test.go b/fileTransfer/e2e/utils_test.go index 164d155740c789916f1ff5a96b3bd3c89079c61f..a9e17b912810dbf24bf640d518bf2c434e95181b 100644 --- a/fileTransfer/e2e/utils_test.go +++ b/fileTransfer/e2e/utils_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package e2e @@ -28,7 +28,7 @@ import ( "gitlab.com/elixxir/client/xxdk" "gitlab.com/elixxir/comms/network" "gitlab.com/elixxir/crypto/cyclic" - e "gitlab.com/elixxir/crypto/e2e" + cryptoE2e "gitlab.com/elixxir/crypto/e2e" "gitlab.com/elixxir/crypto/fastRNG" "gitlab.com/elixxir/ekv" "gitlab.com/elixxir/primitives/format" @@ -40,7 +40,6 @@ import ( "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/id/ephemeral" "gitlab.com/xx_network/primitives/ndf" - "gitlab.com/xx_network/primitives/netTime" "sync" "time" ) @@ -118,12 +117,17 @@ func (m *mockCmix) GetMaxMessageLength() int { } func (m *mockCmix) Send(*id.ID, format.Fingerprint, message.Service, []byte, - []byte, cmix.CMIXParams) (id.Round, ephemeral.Id, error) { + []byte, cmix.CMIXParams) (rounds.Round, ephemeral.Id, error) { + panic("implement me") +} + +func (m *mockCmix) SendWithAssembler(recipient *id.ID, assembler cmix.MessageAssembler, + cmixParams cmix.CMIXParams) (rounds.Round, ephemeral.Id, error) { panic("implement me") } func (m *mockCmix) SendMany(messages []cmix.TargetedCmixMessage, - _ cmix.CMIXParams) (id.Round, []ephemeral.Id, error) { + _ cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error) { m.handler.Lock() for _, targetedMsg := range messages { msg := format.NewMessage(m.numPrimeBytes) @@ -135,7 +139,7 @@ func (m *mockCmix) SendMany(messages []cmix.TargetedCmixMessage, rounds.Round{ID: 42}) } m.handler.Unlock() - return 42, []ephemeral.Id{}, nil + return rounds.Round{ID: 42}, []ephemeral.Id{}, nil } func (m *mockCmix) AddIdentity(*id.ID, time.Time, bool) { panic("implement me") } @@ -187,9 +191,8 @@ func (m *mockCmix) NumRegisteredNodes() int { panic("implement me") } func (m *mockCmix) TriggerNodeRegistration(*id.ID) { panic("implement me") } func (m *mockCmix) GetRoundResults(_ time.Duration, - roundCallback cmix.RoundEventCallback, _ ...id.Round) error { + roundCallback cmix.RoundEventCallback, _ ...id.Round) { go roundCallback(true, false, map[id.Round]cmix.RoundResult{42: {}}) - return nil } func (m *mockCmix) LookupHistoricalRound(id.Round, rounds.RoundResultCallback) error { @@ -259,7 +262,7 @@ func (m *mockE2e) StartProcesses() (stoppable.Stoppable, error) { panic("impleme // SendE2E adds the message to the e2e handler map. func (m *mockE2e) SendE2E(mt catalog.MessageType, recipient *id.ID, - payload []byte, _ e2e.Params) ([]id.Round, e.MessageID, time.Time, error) { + payload []byte, _ e2e.Params) (cryptoE2e.SendReport, error) { m.handler.listeners[mt].Hear(receive.Message{ MessageType: mt, @@ -268,7 +271,7 @@ func (m *mockE2e) SendE2E(mt catalog.MessageType, recipient *id.ID, RecipientID: recipient, }) - return []id.Round{42}, e.MessageID{}, netTime.Now(), nil + return cryptoE2e.SendReport{RoundList: []id.Round{42}}, nil } func (m *mockE2e) RegisterListener(_ *id.ID, mt catalog.MessageType, diff --git a/fileTransfer/e2e/wrapper.go b/fileTransfer/e2e/wrapper.go index e27c281c9dfc490d271b3d225b73643b9e75cfa2..ac575583b6ecb817dfdccad3aed61abc6db3fe5b 100644 --- a/fileTransfer/e2e/wrapper.go +++ b/fileTransfer/e2e/wrapper.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package e2e @@ -12,7 +12,7 @@ import ( "gitlab.com/elixxir/client/e2e" "gitlab.com/elixxir/client/e2e/receive" ft "gitlab.com/elixxir/client/fileTransfer" - e2eCrypto "gitlab.com/elixxir/crypto/e2e" + cryptoE2e "gitlab.com/elixxir/crypto/e2e" ftCrypto "gitlab.com/elixxir/crypto/fileTransfer" "gitlab.com/xx_network/primitives/id" "time" @@ -39,7 +39,7 @@ type Wrapper struct { // for easier testing. type e2eHandler interface { SendE2E(mt catalog.MessageType, recipient *id.ID, payload []byte, - params e2e.Params) ([]id.Round, e2eCrypto.MessageID, time.Time, error) + params e2e.Params) (cryptoE2e.SendReport, error) RegisterListener(senderID *id.ID, messageType catalog.MessageType, newListener receive.Listener) receive.ListenerID } diff --git a/fileTransfer/e2e/wrapper_test.go b/fileTransfer/e2e/wrapper_test.go index 9ea7b46b5b586c95a1bcb0b92bf5e7412c229b02..c1924066a91828feafc071683b4ca21961158036 100644 --- a/fileTransfer/e2e/wrapper_test.go +++ b/fileTransfer/e2e/wrapper_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package e2e diff --git a/fileTransfer/ftMessages.pb.go b/fileTransfer/ftMessages.pb.go index 7990ffe025c93eb8a97dd303bcd2e85bbeec2b24..3bde058fbcd1d3bab95d9ee4545f7e0616928a4f 100644 --- a/fileTransfer/ftMessages.pb.go +++ b/fileTransfer/ftMessages.pb.go @@ -1,149 +1,222 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// // Code generated by protoc-gen-go. DO NOT EDIT. -// source: fileTransfer/ftMessages.proto +// versions: +// protoc-gen-go v1.27.1 +// protoc v3.15.6 +// source: ftMessages.proto package fileTransfer import ( - fmt "fmt" - proto "github.com/golang/protobuf/proto" - math "math" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" ) -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) // NewFileTransfer is transmitted first on the initialization of a file transfer // to inform the receiver about the incoming file. type NewFileTransfer struct { - FileName string `protobuf:"bytes,1,opt,name=fileName,proto3" json:"fileName,omitempty"` - FileType string `protobuf:"bytes,2,opt,name=fileType,proto3" json:"fileType,omitempty"` - TransferKey []byte `protobuf:"bytes,3,opt,name=transferKey,proto3" json:"transferKey,omitempty"` - TransferMac []byte `protobuf:"bytes,4,opt,name=transferMac,proto3" json:"transferMac,omitempty"` - NumParts uint32 `protobuf:"varint,5,opt,name=numParts,proto3" json:"numParts,omitempty"` - Size uint32 `protobuf:"varint,6,opt,name=size,proto3" json:"size,omitempty"` - Retry float32 `protobuf:"fixed32,7,opt,name=retry,proto3" json:"retry,omitempty"` - Preview []byte `protobuf:"bytes,8,opt,name=preview,proto3" json:"preview,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *NewFileTransfer) Reset() { *m = NewFileTransfer{} } -func (m *NewFileTransfer) String() string { return proto.CompactTextString(m) } -func (*NewFileTransfer) ProtoMessage() {} -func (*NewFileTransfer) Descriptor() ([]byte, []int) { - return fileDescriptor_9d574f363dd34365, []int{0} + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + FileName string `protobuf:"bytes,1,opt,name=fileName,proto3" json:"fileName,omitempty"` // Name of the file + FileType string `protobuf:"bytes,2,opt,name=fileType,proto3" json:"fileType,omitempty"` // String that indicates type of file + TransferKey []byte `protobuf:"bytes,3,opt,name=transferKey,proto3" json:"transferKey,omitempty"` // 256-bit encryption key + TransferMac []byte `protobuf:"bytes,4,opt,name=transferMac,proto3" json:"transferMac,omitempty"` // 256-bit MAC of the entire file + NumParts uint32 `protobuf:"varint,5,opt,name=numParts,proto3" json:"numParts,omitempty"` // Number of file parts + Size uint32 `protobuf:"varint,6,opt,name=size,proto3" json:"size,omitempty"` // The size of the file, in bytes + Retry float32 `protobuf:"fixed32,7,opt,name=retry,proto3" json:"retry,omitempty"` // Determines how many times to retry sending + Preview []byte `protobuf:"bytes,8,opt,name=preview,proto3" json:"preview,omitempty"` // A preview of the file +} + +func (x *NewFileTransfer) Reset() { + *x = NewFileTransfer{} + if protoimpl.UnsafeEnabled { + mi := &file_ftMessages_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *NewFileTransfer) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_NewFileTransfer.Unmarshal(m, b) -} -func (m *NewFileTransfer) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_NewFileTransfer.Marshal(b, m, deterministic) -} -func (m *NewFileTransfer) XXX_Merge(src proto.Message) { - xxx_messageInfo_NewFileTransfer.Merge(m, src) +func (x *NewFileTransfer) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *NewFileTransfer) XXX_Size() int { - return xxx_messageInfo_NewFileTransfer.Size(m) -} -func (m *NewFileTransfer) XXX_DiscardUnknown() { - xxx_messageInfo_NewFileTransfer.DiscardUnknown(m) + +func (*NewFileTransfer) ProtoMessage() {} + +func (x *NewFileTransfer) ProtoReflect() protoreflect.Message { + mi := &file_ftMessages_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -var xxx_messageInfo_NewFileTransfer proto.InternalMessageInfo +// Deprecated: Use NewFileTransfer.ProtoReflect.Descriptor instead. +func (*NewFileTransfer) Descriptor() ([]byte, []int) { + return file_ftMessages_proto_rawDescGZIP(), []int{0} +} -func (m *NewFileTransfer) GetFileName() string { - if m != nil { - return m.FileName +func (x *NewFileTransfer) GetFileName() string { + if x != nil { + return x.FileName } return "" } -func (m *NewFileTransfer) GetFileType() string { - if m != nil { - return m.FileType +func (x *NewFileTransfer) GetFileType() string { + if x != nil { + return x.FileType } return "" } -func (m *NewFileTransfer) GetTransferKey() []byte { - if m != nil { - return m.TransferKey +func (x *NewFileTransfer) GetTransferKey() []byte { + if x != nil { + return x.TransferKey } return nil } -func (m *NewFileTransfer) GetTransferMac() []byte { - if m != nil { - return m.TransferMac +func (x *NewFileTransfer) GetTransferMac() []byte { + if x != nil { + return x.TransferMac } return nil } -func (m *NewFileTransfer) GetNumParts() uint32 { - if m != nil { - return m.NumParts +func (x *NewFileTransfer) GetNumParts() uint32 { + if x != nil { + return x.NumParts } return 0 } -func (m *NewFileTransfer) GetSize() uint32 { - if m != nil { - return m.Size +func (x *NewFileTransfer) GetSize() uint32 { + if x != nil { + return x.Size } return 0 } -func (m *NewFileTransfer) GetRetry() float32 { - if m != nil { - return m.Retry +func (x *NewFileTransfer) GetRetry() float32 { + if x != nil { + return x.Retry } return 0 } -func (m *NewFileTransfer) GetPreview() []byte { - if m != nil { - return m.Preview +func (x *NewFileTransfer) GetPreview() []byte { + if x != nil { + return x.Preview } return nil } -func init() { - proto.RegisterType((*NewFileTransfer)(nil), "parse.NewFileTransfer") -} - -func init() { proto.RegisterFile("fileTransfer/ftMessages.proto", fileDescriptor_9d574f363dd34365) } - -var fileDescriptor_9d574f363dd34365 = []byte{ - // 213 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x54, 0x90, 0xbd, 0x4a, 0xc7, 0x30, - 0x14, 0xc5, 0xc9, 0xdf, 0x7e, 0x19, 0xab, 0x42, 0x70, 0xb8, 0x08, 0x42, 0x70, 0xca, 0xa4, 0x83, - 0x6f, 0xe0, 0xe0, 0x22, 0x2d, 0x12, 0x3a, 0xb9, 0xc5, 0x72, 0x2b, 0x05, 0xdb, 0x86, 0x9b, 0x68, - 0xa9, 0xef, 0xec, 0x3b, 0x48, 0xa3, 0xad, 0x71, 0xcb, 0xef, 0x9c, 0x93, 0x73, 0xe1, 0xf0, 0xab, - 0xae, 0x7f, 0xc3, 0x86, 0xcc, 0xe8, 0x3a, 0xa4, 0xdb, 0xce, 0x57, 0xe8, 0x9c, 0x79, 0x45, 0x77, - 0x63, 0x69, 0xf2, 0x93, 0x48, 0xad, 0x21, 0x87, 0xd7, 0x5f, 0x8c, 0x9f, 0xd7, 0x38, 0x3f, 0x44, - 0x59, 0x71, 0xc9, 0x8b, 0xf5, 0x6f, 0x6d, 0x06, 0x04, 0x26, 0x99, 0x3a, 0xd6, 0x3b, 0x6f, 0x5e, - 0xb3, 0x58, 0x84, 0xc3, 0x9f, 0xb7, 0xb2, 0x90, 0xfc, 0xc4, 0xff, 0x76, 0x3c, 0xe2, 0x02, 0x47, - 0x92, 0xa9, 0x52, 0xc7, 0x52, 0x9c, 0xa8, 0x4c, 0x0b, 0xc9, 0xff, 0x44, 0x65, 0xda, 0xb5, 0x7f, - 0x7c, 0x1f, 0x9e, 0x0c, 0x79, 0x07, 0xa9, 0x64, 0xea, 0x54, 0xef, 0x2c, 0x04, 0x4f, 0x5c, 0xff, - 0x89, 0x90, 0x05, 0x3d, 0xbc, 0xc5, 0x05, 0x4f, 0x09, 0x3d, 0x2d, 0x90, 0x4b, 0xa6, 0x0e, 0xfa, - 0x07, 0x04, 0xf0, 0xdc, 0x12, 0x7e, 0xf4, 0x38, 0x43, 0x11, 0x6e, 0x6c, 0x78, 0x7f, 0xf6, 0x5c, - 0xc6, 0xbb, 0xbc, 0x64, 0x61, 0x8d, 0xbb, 0xef, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcd, 0x93, 0x73, - 0x01, 0x2e, 0x01, 0x00, 0x00, +var File_ftMessages_proto protoreflect.FileDescriptor + +var file_ftMessages_proto_rawDesc = []byte{ + 0x0a, 0x10, 0x66, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x12, 0x0c, 0x66, 0x69, 0x6c, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, + 0x22, 0xed, 0x01, 0x0a, 0x0f, 0x4e, 0x65, 0x77, 0x46, 0x69, 0x6c, 0x65, 0x54, 0x72, 0x61, 0x6e, + 0x73, 0x66, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, + 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x20, 0x0a, 0x0b, + 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x0b, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x12, 0x20, + 0x0a, 0x0b, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x4d, 0x61, 0x63, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x4d, 0x61, 0x63, + 0x12, 0x1a, 0x0a, 0x08, 0x6e, 0x75, 0x6d, 0x50, 0x61, 0x72, 0x74, 0x73, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x08, 0x6e, 0x75, 0x6d, 0x50, 0x61, 0x72, 0x74, 0x73, 0x12, 0x12, 0x0a, 0x04, + 0x73, 0x69, 0x7a, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, + 0x12, 0x14, 0x0a, 0x05, 0x72, 0x65, 0x74, 0x72, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x02, 0x52, + 0x05, 0x72, 0x65, 0x74, 0x72, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x65, 0x76, 0x69, 0x65, + 0x77, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, + 0x42, 0x28, 0x5a, 0x26, 0x67, 0x69, 0x74, 0x6c, 0x61, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, + 0x6c, 0x69, 0x78, 0x78, 0x69, 0x72, 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2f, 0x66, 0x69, + 0x6c, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, +} + +var ( + file_ftMessages_proto_rawDescOnce sync.Once + file_ftMessages_proto_rawDescData = file_ftMessages_proto_rawDesc +) + +func file_ftMessages_proto_rawDescGZIP() []byte { + file_ftMessages_proto_rawDescOnce.Do(func() { + file_ftMessages_proto_rawDescData = protoimpl.X.CompressGZIP(file_ftMessages_proto_rawDescData) + }) + return file_ftMessages_proto_rawDescData +} + +var file_ftMessages_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_ftMessages_proto_goTypes = []interface{}{ + (*NewFileTransfer)(nil), // 0: fileTransfer.NewFileTransfer +} +var file_ftMessages_proto_depIdxs = []int32{ + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_ftMessages_proto_init() } +func file_ftMessages_proto_init() { + if File_ftMessages_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_ftMessages_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NewFileTransfer); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_ftMessages_proto_rawDesc, + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_ftMessages_proto_goTypes, + DependencyIndexes: file_ftMessages_proto_depIdxs, + MessageInfos: file_ftMessages_proto_msgTypes, + }.Build() + File_ftMessages_proto = out.File + file_ftMessages_proto_rawDesc = nil + file_ftMessages_proto_goTypes = nil + file_ftMessages_proto_depIdxs = nil } diff --git a/fileTransfer/ftMessages.proto b/fileTransfer/ftMessages.proto index 80547f782b1bb38886c34bc13ed7cf7ebefa8449..f1799036dc31c2e8dae63cf495150cf9a0cd73ce 100644 --- a/fileTransfer/ftMessages.proto +++ b/fileTransfer/ftMessages.proto @@ -1,14 +1,15 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// syntax = "proto3"; -package parse; -option go_package = "fileTransfer"; +package fileTransfer; + +option go_package = "gitlab.com/elixxir/client/fileTransfer"; // NewFileTransfer is transmitted first on the initialization of a file transfer // to inform the receiver about the incoming file. diff --git a/fileTransfer/generateProto.sh b/fileTransfer/generateProto.sh deleted file mode 100644 index 45c407448f50766cccb1e8adfee2be839bbf4c4d..0000000000000000000000000000000000000000 --- a/fileTransfer/generateProto.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -#/////////////////////////////////////////////////////////////////////////////// -#/ Copyright © 2020 xx network SEZC // -#/ // -#/ Use of this source code is governed by a license that can be found in the // -#/ LICENSE file // -#/////////////////////////////////////////////////////////////////////////////// - -protoc --go_out=paths=source_relative:. fileTransfer/ftMessages.proto diff --git a/fileTransfer/groupChat/processor.go b/fileTransfer/groupChat/processor.go index bccc2a6d3f1ff684be8b23fda776e65c71a2e41c..178c774c2eee9e72e8bb5abd11b822e49b7be91e 100644 --- a/fileTransfer/groupChat/processor.go +++ b/fileTransfer/groupChat/processor.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package groupChat diff --git a/fileTransfer/groupChat/send.go b/fileTransfer/groupChat/send.go index b8d5edaf5fb80811c9a9f0606e430aab812fb727..c57acd848d1862fb51abc1de23e2e4caf66278c4 100644 --- a/fileTransfer/groupChat/send.go +++ b/fileTransfer/groupChat/send.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package groupChat diff --git a/fileTransfer/groupChat/utils_test.go b/fileTransfer/groupChat/utils_test.go index 38604350816258fbb6e9c85ac882525f78ec3909..76b2ba1285a05381f719089e03bca00248182218 100644 --- a/fileTransfer/groupChat/utils_test.go +++ b/fileTransfer/groupChat/utils_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package groupChat @@ -112,12 +112,17 @@ func (m *mockCmix) GetMaxMessageLength() int { } func (m *mockCmix) Send(*id.ID, format.Fingerprint, message.Service, []byte, - []byte, cmix.CMIXParams) (id.Round, ephemeral.Id, error) { + []byte, cmix.CMIXParams) (rounds.Round, ephemeral.Id, error) { + panic("implement me") +} + +func (m *mockCmix) SendWithAssembler(recipient *id.ID, assembler cmix.MessageAssembler, + cmixParams cmix.CMIXParams) (rounds.Round, ephemeral.Id, error) { panic("implement me") } func (m *mockCmix) SendMany(messages []cmix.TargetedCmixMessage, - _ cmix.CMIXParams) (id.Round, []ephemeral.Id, error) { + _ cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error) { m.handler.Lock() for _, targetedMsg := range messages { msg := format.NewMessage(m.numPrimeBytes) @@ -129,7 +134,7 @@ func (m *mockCmix) SendMany(messages []cmix.TargetedCmixMessage, rounds.Round{ID: 42}) } m.handler.Unlock() - return 42, []ephemeral.Id{}, nil + return rounds.Round{ID: 42}, []ephemeral.Id{}, nil } func (m *mockCmix) AddIdentity(*id.ID, time.Time, bool) { panic("implement me") } @@ -181,9 +186,8 @@ func (m *mockCmix) NumRegisteredNodes() int { panic("implement me") } func (m *mockCmix) TriggerNodeRegistration(*id.ID) { panic("implement me") } func (m *mockCmix) GetRoundResults(_ time.Duration, - roundCallback cmix.RoundEventCallback, _ ...id.Round) error { + roundCallback cmix.RoundEventCallback, _ ...id.Round) { go roundCallback(true, false, map[id.Round]cmix.RoundResult{42: {}}) - return nil } func (m *mockCmix) LookupHistoricalRound(id.Round, rounds.RoundResultCallback) error { @@ -230,14 +234,14 @@ func newMockGC(handler *mockGcHandler) *mockGC { } func (m *mockGC) Send(groupID *id.ID, tag string, message []byte) ( - id.Round, time.Time, group.MessageID, error) { + rounds.Round, time.Time, group.MessageID, error) { m.handler.Lock() defer m.handler.Unlock() m.handler.services[tag].Process(groupChat.MessageReceive{ GroupID: groupID, Payload: message, }, format.Message{}, receptionID.EphemeralIdentity{}, rounds.Round{}) - return 0, time.Time{}, group.MessageID{}, nil + return rounds.Round{}, time.Time{}, group.MessageID{}, nil } func (m *mockGC) AddService(tag string, p groupChat.Processor) error { diff --git a/fileTransfer/groupChat/wrapper.go b/fileTransfer/groupChat/wrapper.go index 63741b74296bc0c6ed6b0a3271324132a06cc8e8..183b6bcde6f88f4326ae6852221156b95915ec63 100644 --- a/fileTransfer/groupChat/wrapper.go +++ b/fileTransfer/groupChat/wrapper.go @@ -1,14 +1,15 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package groupChat import ( "github.com/pkg/errors" + "gitlab.com/elixxir/client/cmix/rounds" ft "gitlab.com/elixxir/client/fileTransfer" "gitlab.com/elixxir/client/groupChat" ftCrypto "gitlab.com/elixxir/crypto/fileTransfer" @@ -44,7 +45,7 @@ type Wrapper struct { // by the Wrapper for easier testing. type gcManager interface { Send(groupID *id.ID, tag string, message []byte) ( - id.Round, time.Time, group.MessageID, error) + rounds.Round, time.Time, group.MessageID, error) AddService(tag string, p groupChat.Processor) error } diff --git a/fileTransfer/groupChat/wrapper_test.go b/fileTransfer/groupChat/wrapper_test.go index f5cfcca4d30e44ec6f1289d3fa87b628869f824e..c6c8f3950441f760a1541a33aacb65cbdf4e96a8 100644 --- a/fileTransfer/groupChat/wrapper_test.go +++ b/fileTransfer/groupChat/wrapper_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package groupChat diff --git a/fileTransfer/info.go b/fileTransfer/info.go index 034acf5327c41540dd80c0b084cb9c84b83a9001..3d840924bc3af3db6de3ae7a0fa50c3dfae9f8e2 100644 --- a/fileTransfer/info.go +++ b/fileTransfer/info.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package fileTransfer diff --git a/fileTransfer/info_test.go b/fileTransfer/info_test.go index f388eef9d32f6d90ac3d110e2548b80a7752e546..c76c1a5fe2541d37f9e7d15d5733c0176cac8e06 100644 --- a/fileTransfer/info_test.go +++ b/fileTransfer/info_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package fileTransfer diff --git a/fileTransfer/interface.go b/fileTransfer/interface.go index a0f3ed1b142254ab40070ea4b281a2fa1847bfd7..37f7dbf0c85b6bac1ac8e07722f9d71a84788ddb 100644 --- a/fileTransfer/interface.go +++ b/fileTransfer/interface.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package fileTransfer diff --git a/fileTransfer/manager.go b/fileTransfer/manager.go index a586bad235c4145b1f2042e65511546c951ff284..923218fcd2315dae4541de13dc75827f498b98d7 100644 --- a/fileTransfer/manager.go +++ b/fileTransfer/manager.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package fileTransfer @@ -13,6 +13,7 @@ import ( jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/cmix" "gitlab.com/elixxir/client/cmix/message" + "gitlab.com/elixxir/client/cmix/rounds" "gitlab.com/elixxir/client/e2e" "gitlab.com/elixxir/client/fileTransfer/callbackTracker" "gitlab.com/elixxir/client/fileTransfer/store" @@ -145,7 +146,7 @@ type FtE2e interface { // transfer manager for easier testing. type Cmix interface { GetMaxMessageLength() int - SendMany(messages []cmix.TargetedCmixMessage, p cmix.CMIXParams) (id.Round, + SendMany(messages []cmix.TargetedCmixMessage, p cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error) AddFingerprint(identity *id.ID, fingerprint format.Fingerprint, mp message.Processor) error @@ -155,7 +156,7 @@ type Cmix interface { AddHealthCallback(f func(bool)) uint64 RemoveHealthCallback(uint64) GetRoundResults(timeout time.Duration, - roundCallback cmix.RoundEventCallback, roundList ...id.Round) error + roundCallback cmix.RoundEventCallback, roundList ...id.Round) } // Storage interface matches a subset of the storage.Session methods used by the @@ -215,16 +216,21 @@ func NewManager(params Params, user FtE2e) (FileTransfer, error) { // StartProcesses starts the sending threads. Adheres to the xxdk.Service type. func (m *manager) StartProcesses() (stoppable.Stoppable, error) { // Construct stoppables - multiStop := stoppable.NewMulti(workerPoolStoppable) + senderPoolStop := stoppable.NewMulti(workerPoolStoppable) batchBuilderStop := stoppable.NewSingle(batchBuilderThreadStoppable) // Start sending threads - go m.startSendingWorkerPool(multiStop) + // Note that the startSendingWorkerPool already creates thread for every + // worker. As a result, there is no need to run it asynchronously. In fact, + // running this asynchronously could result in a race condition where + // some worker threads are not added to senderPoolStop before that stoppable + // is added to the multiStoppable. + m.startSendingWorkerPool(senderPoolStop) go m.batchBuilderThread(batchBuilderStop) // Create a multi stoppable multiStoppable := stoppable.NewMulti(fileTransferStoppable) - multiStoppable.Add(multiStop) + multiStoppable.Add(senderPoolStop) multiStoppable.Add(batchBuilderStop) return multiStoppable, nil diff --git a/fileTransfer/manager_test.go b/fileTransfer/manager_test.go index 425e26ad03448690d98a7b31d200634960fb7fca..c2bee63b482f66b057625c06d2c53a601f1f6620 100644 --- a/fileTransfer/manager_test.go +++ b/fileTransfer/manager_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package fileTransfer diff --git a/fileTransfer/params.go b/fileTransfer/params.go index fd756a6c8f1318df7200ee149ce17e24457dfe34..e0ecffed8ed3d040cc4c2f4a54d04f4b34f26b83 100644 --- a/fileTransfer/params.go +++ b/fileTransfer/params.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package fileTransfer diff --git a/fileTransfer/params_test.go b/fileTransfer/params_test.go index 965ff70f98185c6fb6b686d967c91d5e0610f28d..e60c9a6381c75881c049d6b538f4b3587aac4ece 100644 --- a/fileTransfer/params_test.go +++ b/fileTransfer/params_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package fileTransfer diff --git a/fileTransfer/partTracker.go b/fileTransfer/partTracker.go index 1288c7a16482fecec864a5cfa236b373c1020d3e..1d432c50fe5756b1a1ce7af3e9440888bcde2396 100644 --- a/fileTransfer/partTracker.go +++ b/fileTransfer/partTracker.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package fileTransfer diff --git a/fileTransfer/processor.go b/fileTransfer/processor.go index a1bb17db81a04c8dec2ab894e17a9f91fa82f6de..adcf474a77ffebc499abbbceeb759ba0b909ca64 100644 --- a/fileTransfer/processor.go +++ b/fileTransfer/processor.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package fileTransfer diff --git a/fileTransfer/send.go b/fileTransfer/send.go index 708bbf32e755779457dcc28d3fc54754f425a819..fb4bbddb36c66d5a7f5ebd0bfff9d7b160bbdc91 100644 --- a/fileTransfer/send.go +++ b/fileTransfer/send.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package fileTransfer @@ -62,9 +62,10 @@ func (m *manager) startSendingWorkerPool(multiStop *stoppable.Multi) { for i := 0; i < workerPoolThreads; i++ { stop := stoppable.NewSingle(sendThreadStoppableName + strconv.Itoa(i)) - multiStop.Add(stop) go m.sendingThread(stop) + multiStop.Add(stop) } + } // sendingThread sends part packets that become available oin the send queue. @@ -74,8 +75,8 @@ func (m *manager) sendingThread(stop *stoppable.Single) { for { select { case <-stop.Quit(): - jww.DEBUG.Printf("[FT] Stopping file part sending thread: " + - "stoppable triggered.") + jww.DEBUG.Printf("[FT] Stopping file part sending thread (%s): "+ + "stoppable triggered.", stop.Name()) m.cmix.RemoveHealthCallback(healthChanID) stop.ToStopped() return @@ -134,8 +135,8 @@ func (m *manager) sendCmix(packet []store.Part) { } } - err = m.cmix.GetRoundResults( - roundResultsTimeout, m.roundResultsCallback(validParts), rid) + m.cmix.GetRoundResults( + roundResultsTimeout, m.roundResultsCallback(validParts), rid.ID) } // roundResultsCallback generates a network.RoundEventCallback that handles diff --git a/fileTransfer/sentRoundTracker/sentRoundTracker.go b/fileTransfer/sentRoundTracker/sentRoundTracker.go index 68511497dad8fbb2d7f3a3417c4d3873997a7c58..6b1a8667d01f19fa2151d536dd872304d55d6978 100644 --- a/fileTransfer/sentRoundTracker/sentRoundTracker.go +++ b/fileTransfer/sentRoundTracker/sentRoundTracker.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package sentRoundTracker diff --git a/fileTransfer/sentRoundTracker/sentRoundTracker_test.go b/fileTransfer/sentRoundTracker/sentRoundTracker_test.go index 90876842d6408cee151bf9d8cdb38598e276135c..3485da2c19af89995183cae3a253fb6d90284e9d 100644 --- a/fileTransfer/sentRoundTracker/sentRoundTracker_test.go +++ b/fileTransfer/sentRoundTracker/sentRoundTracker_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package sentRoundTracker diff --git a/fileTransfer/store/cypher/cypher.go b/fileTransfer/store/cypher/cypher.go index c1926c9be6f9c79b9af0b7b05d8f9010d53efdcb..1a37c427342da0deb76ff1ba1d1e16fcba44b063 100644 --- a/fileTransfer/store/cypher/cypher.go +++ b/fileTransfer/store/cypher/cypher.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package cypher diff --git a/fileTransfer/store/cypher/cypher_test.go b/fileTransfer/store/cypher/cypher_test.go index b3700090322106e817e6c30c1bcceb69eca1df4e..6bf07b1e036cb8054789a5fbc9aa472b722e4df2 100644 --- a/fileTransfer/store/cypher/cypher_test.go +++ b/fileTransfer/store/cypher/cypher_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package cypher diff --git a/fileTransfer/store/cypher/manager.go b/fileTransfer/store/cypher/manager.go index be1662d2da1dd4eb7062e990b31dc341fa3eae92..88d67d7c4488b2b0122ccb9808ed52e2a4fc97b0 100644 --- a/fileTransfer/store/cypher/manager.go +++ b/fileTransfer/store/cypher/manager.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package cypher @@ -164,7 +164,7 @@ func saveKey(key *ftCrypto.TransferKey, kv *versioned.KV) error { Data: key.Bytes(), } - return kv.Set(cypherManagerKeyStoreKey, cypherManagerKeyStoreVersion, obj) + return kv.Set(cypherManagerKeyStoreKey, obj) } // loadKey loads the transfer key from storage. diff --git a/fileTransfer/store/cypher/manager_test.go b/fileTransfer/store/cypher/manager_test.go index c1857b7ae4920b0c26decdfb98752b0fc59acf74..f88bc48390f09fc22472529e972daebae5c63860 100644 --- a/fileTransfer/store/cypher/manager_test.go +++ b/fileTransfer/store/cypher/manager_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package cypher diff --git a/fileTransfer/store/fileMessage/fileMessage.go b/fileTransfer/store/fileMessage/fileMessage.go index d1d0e107b33d6fe9c08e685461d1269e0bcc7753..c14bf742d34ea7c7e007c400b9fd7c7972324d6d 100644 --- a/fileTransfer/store/fileMessage/fileMessage.go +++ b/fileTransfer/store/fileMessage/fileMessage.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package fileMessage diff --git a/fileTransfer/store/fileMessage/fileMessage_test.go b/fileTransfer/store/fileMessage/fileMessage_test.go index b7ac5e0e60d50f4f5be80bf2522db1e010e2de4f..240ae1af5fd0b5a175df91f1d7d2a2173422a14a 100644 --- a/fileTransfer/store/fileMessage/fileMessage_test.go +++ b/fileTransfer/store/fileMessage/fileMessage_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package fileMessage diff --git a/fileTransfer/store/part.go b/fileTransfer/store/part.go index c382699695cda68c24ae417721660baae162757d..742d5a391c4b38ac2cfbb6998598d606ae0d1e50 100644 --- a/fileTransfer/store/part.go +++ b/fileTransfer/store/part.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package store diff --git a/fileTransfer/store/part_test.go b/fileTransfer/store/part_test.go index ea71d299e44fbf66f0309e646dbba4f8e14a6596..871e3d10bd9b6acdd5e5b0f122fae449e0326e50 100644 --- a/fileTransfer/store/part_test.go +++ b/fileTransfer/store/part_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package store diff --git a/fileTransfer/store/received.go b/fileTransfer/store/received.go index 8522f6a86abad452e0c49e871e64d54ce139c8e7..189025a711b89537022a99ec72d19eaf98e63c91 100644 --- a/fileTransfer/store/received.go +++ b/fileTransfer/store/received.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package store @@ -13,7 +13,6 @@ import ( jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/storage/versioned" ftCrypto "gitlab.com/elixxir/crypto/fileTransfer" - "gitlab.com/elixxir/ekv" "gitlab.com/xx_network/primitives/netTime" "sync" ) @@ -56,7 +55,7 @@ func NewOrLoadReceived(kv *versioned.KV) (*Received, []*ReceivedTransfer, error) obj, err := s.kv.Get(receivedTransfersStoreKey, receivedTransfersStoreVersion) if err != nil { - if ekv.Exists(err) { + if kv.Exists(err) { return nil, nil, errors.Errorf(errLoadReceived, err) } else { return s, nil, nil @@ -157,7 +156,7 @@ func (r *Received) save() error { Data: data, } - return r.kv.Set(receivedTransfersStoreKey, receivedTransfersStoreVersion, obj) + return r.kv.Set(receivedTransfersStoreKey, obj) } // marshalReceivedTransfersMap serialises the list of transfer IDs from a diff --git a/fileTransfer/store/receivedTransfer.go b/fileTransfer/store/receivedTransfer.go index db6f54264a4094e22b53b32e7f763b700adc3827..5ae7a07d52e1ecc73ba9fb6582ee2e3094730fcb 100644 --- a/fileTransfer/store/receivedTransfer.go +++ b/fileTransfer/store/receivedTransfer.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package store @@ -339,7 +339,7 @@ func (rt *ReceivedTransfer) save() error { } // Save versioned object - return rt.kv.Set(receivedTransferStoreKey, receivedTransferStoreVersion, vo) + return rt.kv.Set(receivedTransferStoreKey, vo) } // receivedTransferDisk structure is used to marshal and unmarshal @@ -385,7 +385,7 @@ func savePart(part []byte, partNum int, kv *versioned.KV) error { Data: part, } - return kv.Set(makeReceivedPartKey(partNum), receivedPartStoreVersion, obj) + return kv.Set(makeReceivedPartKey(partNum), obj) } // loadPart loads the part with the given part number from storage. diff --git a/fileTransfer/store/receivedTransfer_test.go b/fileTransfer/store/receivedTransfer_test.go index e1a32e74db61be43052b8dae03a358ec9c014c5c..b68e0b071480d9e84569c745a0024e42d07838b8 100644 --- a/fileTransfer/store/receivedTransfer_test.go +++ b/fileTransfer/store/receivedTransfer_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package store diff --git a/fileTransfer/store/received_test.go b/fileTransfer/store/received_test.go index 4aa468f84055ed50f6b8272a858697273f20efd3..3bcba24b6e32847945ce6d10961517aa14dded3a 100644 --- a/fileTransfer/store/received_test.go +++ b/fileTransfer/store/received_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package store @@ -204,8 +204,8 @@ func TestReceived_save(t *testing.T) { kv := versioned.NewKV(ekv.MakeMemstore()) r, _, _ := NewOrLoadReceived(kv) r.transfers = map[ftCrypto.TransferID]*ReceivedTransfer{ - ftCrypto.TransferID{0}: nil, ftCrypto.TransferID{1}: nil, - ftCrypto.TransferID{2}: nil, ftCrypto.TransferID{3}: nil, + {0}: nil, {1}: nil, + {2}: nil, {3}: nil, } err := r.save() diff --git a/fileTransfer/store/sent.go b/fileTransfer/store/sent.go index 7873d5b469bafc8666b0951d55d7852aff0c1ae6..a7f89a598dd79ec14b421b0101d0dae5ab7e05cf 100644 --- a/fileTransfer/store/sent.go +++ b/fileTransfer/store/sent.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package store @@ -13,7 +13,6 @@ import ( jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/storage/versioned" ftCrypto "gitlab.com/elixxir/crypto/fileTransfer" - "gitlab.com/elixxir/ekv" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/netTime" "sync" @@ -58,7 +57,7 @@ func NewOrLoadSent(kv *versioned.KV) (*Sent, []Part, error) { obj, err := s.kv.Get(sentTransfersStoreKey, sentTransfersStoreVersion) if err != nil { - if !ekv.Exists(err) { + if !kv.Exists(err) { // Return the new Sent if none exists in storage return s, nil, nil } else { @@ -165,7 +164,7 @@ func (s *Sent) save() error { Data: data, } - return s.kv.Set(sentTransfersStoreKey, sentTransfersStoreVersion, obj) + return s.kv.Set(sentTransfersStoreKey, obj) } // marshalSentTransfersMap serialises the list of transfer IDs from a diff --git a/fileTransfer/store/sentTransfer.go b/fileTransfer/store/sentTransfer.go index 83b9594fb0a6764ace36514d86e38cfcb0b985b8..39e826ccb7bd3c4f47e4c9c7fbc436fdc8cc46e7 100644 --- a/fileTransfer/store/sentTransfer.go +++ b/fileTransfer/store/sentTransfer.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package store @@ -346,7 +346,7 @@ func (st *SentTransfer) save() error { Data: data, } - return st.kv.Set(sentTransferStoreKey, sentTransferStoreVersion, obj) + return st.kv.Set(sentTransferStoreKey, obj) } // sentTransferDisk structure is used to marshal and unmarshal SentTransfer diff --git a/fileTransfer/store/sentTransfer_test.go b/fileTransfer/store/sentTransfer_test.go index a9366ce8057dbaac8641bcd9132d54e2dfcb41f4..20f1428a57759e94f86c22e811f25b2c4dfd5eff 100644 --- a/fileTransfer/store/sentTransfer_test.go +++ b/fileTransfer/store/sentTransfer_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package store diff --git a/fileTransfer/store/sent_test.go b/fileTransfer/store/sent_test.go index f07a5996c2ba9844faeeffecaed6c171eecb4851..f3f24e43e4670b3d317d43d3e88a6c21c2ae4ace 100644 --- a/fileTransfer/store/sent_test.go +++ b/fileTransfer/store/sent_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package store @@ -225,8 +225,8 @@ func TestSent_save(t *testing.T) { kv := versioned.NewKV(ekv.MakeMemstore()) s, _, _ := NewOrLoadSent(kv) s.transfers = map[ftCrypto.TransferID]*SentTransfer{ - ftCrypto.TransferID{0}: nil, ftCrypto.TransferID{1}: nil, - ftCrypto.TransferID{2}: nil, ftCrypto.TransferID{3}: nil, + {0}: nil, {1}: nil, + {2}: nil, {3}: nil, } err := s.save() diff --git a/fileTransfer/store/transferStatus.go b/fileTransfer/store/transferStatus.go index 4055f622a58bb1daac519c103abf9315e439acc4..7f49e0612ac9556c77f47634056ccb80e12ead7b 100644 --- a/fileTransfer/store/transferStatus.go +++ b/fileTransfer/store/transferStatus.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package store diff --git a/fileTransfer/store/transferStatus_test.go b/fileTransfer/store/transferStatus_test.go index a54878295b992b7faefecd3f9e66f1c78561d976..4fbcb69cb3951536a4bdee55800bf576a3277d29 100644 --- a/fileTransfer/store/transferStatus_test.go +++ b/fileTransfer/store/transferStatus_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package store diff --git a/fileTransfer/utils_test.go b/fileTransfer/utils_test.go index df51d90ddaa113ce471244217d567fa3868a1883..96c400a9dfdaa63cb84242b083e41325c25606d1 100644 --- a/fileTransfer/utils_test.go +++ b/fileTransfer/utils_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package fileTransfer @@ -166,12 +166,17 @@ func (m *mockCmix) GetMaxMessageLength() int { } func (m *mockCmix) Send(*id.ID, format.Fingerprint, message.Service, []byte, - []byte, cmix.CMIXParams) (id.Round, ephemeral.Id, error) { + []byte, cmix.CMIXParams) (rounds.Round, ephemeral.Id, error) { + panic("implement me") +} + +func (m *mockCmix) SendWithAssembler(recipient *id.ID, assembler cmix.MessageAssembler, + cmixParams cmix.CMIXParams) (rounds.Round, ephemeral.Id, error) { panic("implement me") } func (m *mockCmix) SendMany(messages []cmix.TargetedCmixMessage, - _ cmix.CMIXParams) (id.Round, []ephemeral.Id, error) { + _ cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error) { m.handler.Lock() defer m.handler.Unlock() round := m.round @@ -185,7 +190,7 @@ func (m *mockCmix) SendMany(messages []cmix.TargetedCmixMessage, receptionID.EphemeralIdentity{Source: targetedMsg.Recipient}, rounds.Round{ID: round}) } - return round, []ephemeral.Id{}, nil + return rounds.Round{ID: round}, []ephemeral.Id{}, nil } func (m *mockCmix) AddIdentity(*id.ID, time.Time, bool) { panic("implement me") } @@ -237,9 +242,8 @@ func (m *mockCmix) NumRegisteredNodes() int { panic("implement me") } func (m *mockCmix) TriggerNodeRegistration(*id.ID) { panic("implement me") } func (m *mockCmix) GetRoundResults(_ time.Duration, - roundCallback cmix.RoundEventCallback, rids ...id.Round) error { + roundCallback cmix.RoundEventCallback, rids ...id.Round) { go roundCallback(true, false, map[id.Round]cmix.RoundResult{rids[0]: {}}) - return nil } func (m *mockCmix) LookupHistoricalRound(id.Round, rounds.RoundResultCallback) error { diff --git a/go.mod b/go.mod index 372fb69b5f827d9103636d2aaf5d5f42724216a3..227defa233b7142edb35eda25b490b34b146281f 100644 --- a/go.mod +++ b/go.mod @@ -8,38 +8,50 @@ require ( github.com/golang/protobuf v1.5.2 github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 github.com/pkg/errors v0.9.1 + github.com/pkg/profile v1.6.0 github.com/spf13/cobra v1.5.0 github.com/spf13/jwalterweatherman v1.1.0 github.com/spf13/viper v1.12.0 + github.com/stretchr/testify v1.8.0 gitlab.com/elixxir/bloomfilter v0.0.0-20211222005329-7d931ceead6f - gitlab.com/elixxir/comms v0.0.4-0.20220805121030-b95005ac4528 - gitlab.com/elixxir/crypto v0.0.7-0.20220808171640-473891de4c46 - gitlab.com/elixxir/ekv v0.1.7 - gitlab.com/elixxir/primitives v0.0.3-0.20220606195757-40f7a589347f - gitlab.com/xx_network/comms v0.0.4-0.20220630163702-f3d372ef6acd - gitlab.com/xx_network/crypto v0.0.5-0.20220729193517-1e5e96f39f6e - gitlab.com/xx_network/primitives v0.0.4-0.20221010192422-3479f09b7769 + gitlab.com/elixxir/comms v0.0.4-0.20221005205938-10f2defa5b33 + gitlab.com/elixxir/crypto v0.0.7-0.20221003185354-b091598d2322 + gitlab.com/elixxir/ekv v0.2.1 + gitlab.com/elixxir/primitives v0.0.3-0.20220901220638-1acc75fabdc6 + gitlab.com/xx_network/comms v0.0.4-0.20221005205845-b34d538ffd85 + gitlab.com/xx_network/crypto v0.0.5-0.20220913213008-98764f5b3287 + gitlab.com/xx_network/primitives v0.0.4-0.20220809193445-9fc0a5209548 go.uber.org/ratelimit v0.2.0 golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa - golang.org/x/net v0.0.0-20220802222814-0bcc04d9c69b - google.golang.org/grpc v1.48.0 + golang.org/x/net v0.0.0-20220822230855-b0a4917ee28c + google.golang.org/grpc v1.49.0 google.golang.org/protobuf v1.28.1 ) require ( + git.xx.network/elixxir/grpc-web-go-client v0.0.0-20220908170150-ef04339ffe65 // indirect github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 // indirect github.com/badoux/checkmail v1.2.1 // indirect + github.com/cenkalti/backoff/v4 v4.1.3 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect github.com/elliotchance/orderedmap v1.4.0 // indirect github.com/fsnotify/fsnotify v1.5.4 // indirect + github.com/gorilla/websocket v1.5.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect + github.com/improbable-eng/grpc-web v0.15.0 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect + github.com/klauspost/compress v1.11.7 // indirect github.com/klauspost/cpuid/v2 v2.1.0 // indirect github.com/magiconair/properties v1.8.6 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/pelletier/go-toml v1.9.5 // indirect github.com/pelletier/go-toml/v2 v2.0.2 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/rs/cors v1.8.2 // indirect github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e // indirect + github.com/soheilhy/cmux v0.1.5 // indirect github.com/spf13/afero v1.9.2 // indirect github.com/spf13/cast v1.5.0 // indirect github.com/spf13/pflag v1.0.5 // indirect @@ -49,10 +61,12 @@ require ( github.com/tyler-smith/go-bip39 v1.1.0 // indirect github.com/zeebo/blake3 v0.2.3 // indirect gitlab.com/xx_network/ring v0.0.3-0.20220222211904-da613960ad93 // indirect + go.uber.org/atomic v1.10.0 // indirect golang.org/x/sys v0.0.0-20220731174439-a90be440212d // indirect golang.org/x/text v0.3.7 // indirect - google.golang.org/genproto v0.0.0-20220802133213-ce4fa296bf78 // indirect + google.golang.org/genproto v0.0.0-20220822174746-9e6da59bd2fc // indirect gopkg.in/ini.v1 v1.66.6 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect + nhooyr.io/websocket v1.8.7 // indirect ) diff --git a/go.sum b/go.sum index 2e2ecf7e928609c7877100b0f1597c23f6a16bb3..398547585158c8b9af50df15e192eba16eca6239 100644 --- a/go.sum +++ b/go.sum @@ -54,10 +54,17 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +git.xx.network/elixxir/grpc-web-go-client v0.0.0-20220908170150-ef04339ffe65 h1:ksB3ZiMeFplqlaCjMDqKegbGzDZdS5pU0Z5GgFeBdZ0= +git.xx.network/elixxir/grpc-web-go-client v0.0.0-20220908170150-ef04339ffe65/go.mod h1:uFKw2wmgtlYMdiIm08dM0Vj4XvX9ZKVCj71c8O7SAPo= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= +github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -66,11 +73,17 @@ github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk5 github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 h1:MzBOUgng9orim59UnfUTLRjMpd09C5uEVQ6RPGeCaVI= github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129/go.mod h1:rFgpPQZYZ8vdbc+48xibu8ALc3yeyd64IhHS+PU6Yyg= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= +github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= +github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/badoux/checkmail v1.2.1 h1:TzwYx5pnsV6anJweMx2auXdekBwGr/yt1GgalIx9nBQ= github.com/badoux/checkmail v1.2.1/go.mod h1:XroCOBU5zzZJcLvgwU15I+2xXyCdTWXyR9MGfRhBYy0= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -79,6 +92,12 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= github.com/bwesterb/go-ristretto v1.2.1/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= +github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= +github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= +github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= +github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= +github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= +github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -87,6 +106,7 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= +github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudflare/circl v1.1.0/go.mod h1:prBCrKB9DV4poKZY1l9zBXg2QJY7mvgRvtMxxK7fi4I= github.com/cloudflare/circl v1.2.0 h1:NheeISPSUcYftKlfrLuOo4T62FkmD4t4jviLfFFYaec= @@ -100,16 +120,32 @@ github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= 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/desertbit/timer v0.0.0-20180107155436-c41aec40b27f h1:U5y3Y5UE0w7amNe7Z5G/twsBW0KEalRQXZzf8ufSh9I= +github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/elliotchance/orderedmap v1.4.0 h1:wZtfeEONCbx6in1CZyE6bELEt/vFayMvsxqI5SgsR+A= github.com/elliotchance/orderedmap v1.4.0/go.mod h1:wsDwEaX5jEoyhbs7x93zk2H/qv0zwuhg4inXhDkYqys= +github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -123,28 +159,54 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7 github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= +github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14= +github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= +github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= +github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= +github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= +github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY= +github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= +github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0= +github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= +github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8= +github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo= +github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3 h1:zN2lZNZRflqFyxVaTIU61KNKQ9C0055u9CAfpmqUvo4= github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3/go.mod h1:nPpo7qLxd6XL3hWJG/O60sR8ZKfMCiIoNap5GvD12KU= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -176,6 +238,7 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -215,6 +278,7 @@ github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= @@ -224,9 +288,22 @@ github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/Oth github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM= github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= github.com/hashicorp/consul/api v1.12.0/go.mod h1:6pVBMo0ebnYdt2S3H87XhekM/HHrUoTD2XXb/VrZVy0= +github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= @@ -240,37 +317,63 @@ github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iP github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.0.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= 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/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= github.com/hashicorp/serf v0.9.7/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/improbable-eng/grpc-web v0.12.0/go.mod h1:6hRR09jOEG81ADP5wCQju1z71g6OL4eEvELdran/3cs= +github.com/improbable-eng/grpc-web v0.14.1/go.mod h1:zEjGHa8DAlkoOXmswrNvhUGEYQA9UI7DhrGeHR1DMGU= +github.com/improbable-eng/grpc-web v0.15.0 h1:BN+7z6uNXZ1tQGcNAuaU1YjsLTApzkjt2tzCixLaUPQ= +github.com/improbable-eng/grpc-web v0.15.0/go.mod h1:1sy9HKV4Jt9aEs9JSnkWlRJPuPtwNr0l57L4f878wP8= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +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/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.11.7 h1:0hzRabrMN4tSTvMfnL3SCv1ZGeAP23ynzodBgaHeMeg= +github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= github.com/klauspost/cpuid/v2 v2.1.0 h1:eyi1Ad2aNJMW95zcSbmGg7Cg6cq3ADwLpMAP96d8rF0= github.com/klauspost/cpuid/v2 v2.1.0/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= @@ -287,8 +390,21 @@ 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/ktr0731/dept v0.1.3/go.mod h1:b1EtCEjbjGShAfhZue+BrFKTG7sQmK7aSD7Q6VcGvO0= +github.com/ktr0731/go-multierror v0.0.0-20171204182908-b7773ae21874/go.mod h1:ZWayuE/hCzOD96CJizvcYnqrbmTC7RAG332yNtlKj6w= +github.com/ktr0731/grpc-test v0.1.4/go.mod h1:v47616grayBYXQveGWxO3OwjLB3nEEnHsZuMTc73FM0= +github.com/ktr0731/grpc-test v0.1.12 h1:Yha+zH2hB48huOfbsEMfyG7FeHCrVWq4fYmHfr3iH3U= +github.com/ktr0731/grpc-test v0.1.12/go.mod h1:AP4+ZrqSzdDaUNhAsp2fye06MXO2fdYY6YQJifb588M= +github.com/ktr0731/grpc-web-go-client v0.2.8 h1:nUf9p+YWirmFwmH0mwtAWhuXvzovc+/3C/eAY2Fshnk= +github.com/ktr0731/grpc-web-go-client v0.2.8/go.mod h1:1Iac8gFJvC/DRfZoGnFZsfEbEq/wQFK+2Ve1o3pHkCQ= +github.com/ktr0731/modfile v1.11.2/go.mod h1:LzNwnHJWHbuDh3BO17lIqzqDldXqGu1HCydWH3SinE0= +github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= +github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= +github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= +github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= github.com/liyue201/goqr v0.0.0-20200803022322-df443203d4ea h1:uyJ13zfy6l79CM3HnVhDalIyZ4RJAyVfDrbnfFeJoC4= github.com/liyue201/goqr v0.0.0-20200803022322-df443203d4ea/go.mod h1:w4pGU9PkiX2hAWyF0yuHEHmYTQFAd6WHzp6+IY7JVjE= +github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= @@ -297,96 +413,176 @@ github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= +github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= +github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/multiformats/go-multihash v0.2.1/go.mod h1:WxoMcYG85AZVQUyRyo9s4wULvW5qrI9vb2Lt6evduFc= +github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/grpc-proxy v0.0.0-20181017164139-0f1106ef9c76/go.mod h1:x5OoJHDHqxHS801UIuhqGl6QdSAEJvtausosHSdazIo= +github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= +github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= +github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= +github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= +github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= +github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= +github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= +github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= github.com/pelletier/go-toml/v2 v2.0.2 h1:+jQXlF3scKIcSEKkdHzXhCTDLPFi5r1wnK6yPS+49Gw= github.com/pelletier/go-toml/v2 v2.0.2/go.mod h1:MovirKjgVRESsAvNZlAjtFwV867yGuwRkXbG66OzopI= +github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= +github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= +github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/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/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= +github.com/pkg/profile v1.6.0 h1:hUDfIISABYI59DyeB3OTay/HxSRwTQ8rB/H83k6r5dM= +github.com/pkg/profile v1.6.0/go.mod h1:qBsxPvzyUincmltOk6iyRVxHYg4adc0OFOv72ZdLa18= github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= 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/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/rakyll/statik v0.1.6/go.mod h1:OEi9wJV/fMUAGx1eNjq75DKDsJVuEv1U0oYdX6GX8Zs= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U= +github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sagikazarmark/crypt v0.6.0/go.mod h1:U8+INwJo3nBv1m6A/8OBXAq7Jnpspk5AxSgDyEQcea8= +github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0= github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/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/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= +github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= +github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo= github.com/spf13/afero v1.9.2 h1:j49Hj62F0n+DaZ1dDCvhABaPNSGNkt32oRFxI33IEMw= github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU= github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.12.0 h1:CZ7eSOd3kZoaYDLbXnmzgQI5RlciuXBMA+18HwHRfZQ= github.com/spf13/viper v1.12.0/go.mod h1:b6COn30jlNxbm/V2IqWiNWkJ+vZNiMNksliPCiuKtSI= +github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= 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/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -394,11 +590,13 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= +github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/subosito/gotenv v1.3.0/go.mod h1:YzJjq/33h7nrwdY+iHMhEOEEbW0ovIz0tB6t6PwAXzs= github.com/subosito/gotenv v1.4.0 h1:yAzM1+SmVcz5R4tXGsNMu1jUl2aOJXoiWUCEwwnGrvs= github.com/subosito/gotenv v1.4.0/go.mod h1:mZd6rFysKEcUhUHXJk0C/08wAgyDBFuwEYL7vWWGaGo= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ttacon/builder v0.0.0-20170518171403-c099f663e1c2 h1:5u+EJUQiosu3JFX0XS0qTf5FznsMOzTjGqavBGuCbo0= github.com/ttacon/builder v0.0.0-20170518171403-c099f663e1c2/go.mod h1:4kyMkleCiLkgY6z8gK5BkI01ChBtxR0ro3I1ZDcGM3w= github.com/ttacon/libphonenumber v1.2.1 h1:fzOfY5zUADkCkbIafAed11gL1sW+bJ26p6zWLBMElR4= @@ -406,6 +604,13 @@ github.com/ttacon/libphonenumber v1.2.1/go.mod h1:E0TpmdVMq5dyVlQ7oenAkhsLu86OkU github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= +github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= +github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= +github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= +github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -424,51 +629,61 @@ github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo= github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4= gitlab.com/elixxir/bloomfilter v0.0.0-20211222005329-7d931ceead6f h1:yXGvNBqzZwAhDYlSnxPRbgor6JWoOt1Z7s3z1O9JR40= gitlab.com/elixxir/bloomfilter v0.0.0-20211222005329-7d931ceead6f/go.mod h1:H6jztdm0k+wEV2QGK/KYA+MY9nj9Zzatux/qIvDDv3k= -gitlab.com/elixxir/comms v0.0.4-0.20220805121030-b95005ac4528 h1:1js4QzrDI5djjIVkj1mZiWkxh7K2h5/Od/X/lyftILA= -gitlab.com/elixxir/comms v0.0.4-0.20220805121030-b95005ac4528/go.mod h1:Zi1O21+pKwSNNvQ7akyVRnppR79z+4CzJs6njIRaJCA= +gitlab.com/elixxir/comms v0.0.4-0.20220913220502-eed192f654bd h1:2nHE7EoptSTBFjCxMeAveKT6urbguCwgg8Jx7XYEVe4= +gitlab.com/elixxir/comms v0.0.4-0.20220913220502-eed192f654bd/go.mod h1:AO6XkMhaHJW8eXlgL5m3UUcJqsSP8F5Wm1GX+wyq/rw= +gitlab.com/elixxir/comms v0.0.4-0.20220916185715-f1e9a5eda939 h1:+VRx2ULHKs040bBhDAOKNCZnbcXxUk3jD9JoKQzQpLk= +gitlab.com/elixxir/comms v0.0.4-0.20220916185715-f1e9a5eda939/go.mod h1:AO6XkMhaHJW8eXlgL5m3UUcJqsSP8F5Wm1GX+wyq/rw= +gitlab.com/elixxir/comms v0.0.4-0.20221005205938-10f2defa5b33 h1:mtn/b+/+cMoZNSEo6293U48uqz+aE0si90mPwlhh08w= +gitlab.com/elixxir/comms v0.0.4-0.20221005205938-10f2defa5b33/go.mod h1:oRteMH+R5t1j/FZ+KJJnZUcqJO2sLXnWksN5HPkZUIo= gitlab.com/elixxir/crypto v0.0.0-20200804182833-984246dea2c4/go.mod h1:ucm9SFKJo+K0N2GwRRpaNr+tKXMIOVWzmyUD0SbOu2c= gitlab.com/elixxir/crypto v0.0.3/go.mod h1:ZNgBOblhYToR4m8tj4cMvJ9UsJAUKq+p0gCp07WQmhA= -gitlab.com/elixxir/crypto v0.0.7-0.20220317172048-3de167bd9406/go.mod h1:tD6XjtQh87T2nKZL5I/pYPck5M2wLpkZ1Oz7H/LqO10= -gitlab.com/elixxir/crypto v0.0.7-0.20220808171640-473891de4c46 h1:C8nAiMnL8IOGjQ5qErbpzAjRMVFMoB1GunYk8pGOEz8= -gitlab.com/elixxir/crypto v0.0.7-0.20220808171640-473891de4c46/go.mod h1:Oy+VWQ2Sa0Ybata3oTV+Yc46hkaDwAsuIMW0wJ01z2M= -gitlab.com/elixxir/ekv v0.1.7 h1:OW2z+N4QCqqMFzouAwFTWWMKz0Y/PDhyYReN7gQ5NiQ= -gitlab.com/elixxir/ekv v0.1.7/go.mod h1:e6WPUt97taFZe5PFLPb1Dupk7tqmDCTQu1kkstqJvw4= +gitlab.com/elixxir/crypto v0.0.7-0.20220913220142-ab0771bad0af/go.mod h1:QF8SzsrYh9Elip9EUYUDAhPjqO9DGrrrQxYHvn+VXok= +gitlab.com/elixxir/crypto v0.0.7-0.20220920002307-5541473e9aa7 h1:9IsBtL8zcUG86XcfNUVIKcnlL5tyKlyQt1cJ5nogr1U= +gitlab.com/elixxir/crypto v0.0.7-0.20220920002307-5541473e9aa7/go.mod h1:QF8SzsrYh9Elip9EUYUDAhPjqO9DGrrrQxYHvn+VXok= +gitlab.com/elixxir/crypto v0.0.7-0.20220923135535-fb10d313632a h1:n12oIGF9GzfA/0ZTggCjubTxOZPF8p9WINfkdko9e7E= +gitlab.com/elixxir/crypto v0.0.7-0.20220923135535-fb10d313632a/go.mod h1:QF8SzsrYh9Elip9EUYUDAhPjqO9DGrrrQxYHvn+VXok= +gitlab.com/elixxir/crypto v0.0.7-0.20220923164228-3f5620181081 h1:xrTNr42Id8rvq6zH+pkoxxCrLhFMpkMC3f34y5mUfQE= +gitlab.com/elixxir/crypto v0.0.7-0.20220923164228-3f5620181081/go.mod h1:QF8SzsrYh9Elip9EUYUDAhPjqO9DGrrrQxYHvn+VXok= +gitlab.com/elixxir/crypto v0.0.7-0.20220923233816-0364f1b203c6 h1:ZCMqzKB86nrs9ldIoF2ZHvcExrkXIIIeH2RlNVwZx2A= +gitlab.com/elixxir/crypto v0.0.7-0.20220923233816-0364f1b203c6/go.mod h1:QF8SzsrYh9Elip9EUYUDAhPjqO9DGrrrQxYHvn+VXok= +gitlab.com/elixxir/crypto v0.0.7-0.20221003185354-b091598d2322 h1:8unQE70BDNRXTWUbjOO9d4kWyh19LySlTZo0Jqx0gPE= +gitlab.com/elixxir/crypto v0.0.7-0.20221003185354-b091598d2322/go.mod h1:QF8SzsrYh9Elip9EUYUDAhPjqO9DGrrrQxYHvn+VXok= +gitlab.com/elixxir/ekv v0.2.1 h1:dtwbt6KmAXG2Tik5d60iDz2fLhoFBgWwST03p7T+9Is= +gitlab.com/elixxir/ekv v0.2.1/go.mod h1:USLD7xeDnuZEavygdrgzNEwZXeLQJK/w1a+htpN+JEU= gitlab.com/elixxir/primitives v0.0.0-20200731184040-494269b53b4d/go.mod h1:OQgUZq7SjnE0b+8+iIAT2eqQF+2IFHn73tOo+aV11mg= gitlab.com/elixxir/primitives v0.0.0-20200804170709-a1896d262cd9/go.mod h1:p0VelQda72OzoUckr1O+vPW0AiFe0nyKQ6gYcmFSuF8= gitlab.com/elixxir/primitives v0.0.0-20200804182913-788f47bded40/go.mod h1:tzdFFvb1ESmuTCOl1z6+yf6oAICDxH2NPUemVgoNLxc= gitlab.com/elixxir/primitives v0.0.1/go.mod h1:kNp47yPqja2lHSiS4DddTvFpB/4D9dB2YKnw5c+LJCE= -gitlab.com/elixxir/primitives v0.0.3-0.20220222212109-d412a6e46623/go.mod h1:MtFIyJUQn9P7djzVlBpEYkPNnnWFTjZvw89swoXY+QM= -gitlab.com/elixxir/primitives v0.0.3-0.20220323183834-b98f255361b8/go.mod h1:MtFIyJUQn9P7djzVlBpEYkPNnnWFTjZvw89swoXY+QM= -gitlab.com/elixxir/primitives v0.0.3-0.20220606195757-40f7a589347f h1:CTf2+ewHWYrzp5Ar3RwNvHePfTHyFniJTVjFW4zqoaE= gitlab.com/elixxir/primitives v0.0.3-0.20220606195757-40f7a589347f/go.mod h1:9Bb2+u+CDSwsEU5Droo6saDAXuBDvLRjexpBhPAYxhA= +gitlab.com/elixxir/primitives v0.0.3-0.20220810173935-592f34a88326/go.mod h1:9Bb2+u+CDSwsEU5Droo6saDAXuBDvLRjexpBhPAYxhA= +gitlab.com/elixxir/primitives v0.0.3-0.20220901220638-1acc75fabdc6 h1:/cxxZBP5jTPDpC3zgOx9vV1ojmJyG8pYtkl3IbcewNQ= +gitlab.com/elixxir/primitives v0.0.3-0.20220901220638-1acc75fabdc6/go.mod h1:9Bb2+u+CDSwsEU5Droo6saDAXuBDvLRjexpBhPAYxhA= gitlab.com/xx_network/comms v0.0.0-20200805174823-841427dd5023/go.mod h1:owEcxTRl7gsoM8c3RQ5KAm5GstxrJp5tn+6JfQ4z5Hw= -gitlab.com/xx_network/comms v0.0.4-0.20220315161313-76acb14429ac/go.mod h1:isHnwem0v4rTcwwHP455FhVlFyPcHkHiVz+N3s/uCSI= -gitlab.com/xx_network/comms v0.0.4-0.20220630163702-f3d372ef6acd h1:qYR2V/8KliGyJ2clWpVYhpgwpnfS1MXGpAbrFoOkSWk= -gitlab.com/xx_network/comms v0.0.4-0.20220630163702-f3d372ef6acd/go.mod h1:TraR4sW+YxK/2CV+IQUNaAV61+ElrBV0kXd5HLEjM7M= +gitlab.com/xx_network/comms v0.0.4-0.20220913215811-c4bf83b27de3 h1:7mReTvEUVoI5Qpltcmbodc/j6rdPPHDIvenY4ZmWP7o= +gitlab.com/xx_network/comms v0.0.4-0.20220913215811-c4bf83b27de3/go.mod h1:E2QKOKyPKLRjLUwMxgZpTKueEsHDEqshfqOHJ54ttxU= +gitlab.com/xx_network/comms v0.0.4-0.20220916185248-8a984b8594de h1:44VKuVgT6X1l+MX8/oNmYORA+pa4nkOWV8hYxi4SCzc= +gitlab.com/xx_network/comms v0.0.4-0.20220916185248-8a984b8594de/go.mod h1:E2QKOKyPKLRjLUwMxgZpTKueEsHDEqshfqOHJ54ttxU= +gitlab.com/xx_network/comms v0.0.4-0.20221005205845-b34d538ffd85/go.mod h1:E2QKOKyPKLRjLUwMxgZpTKueEsHDEqshfqOHJ54ttxU= gitlab.com/xx_network/crypto v0.0.3/go.mod h1:DF2HYvvCw9wkBybXcXAgQMzX+MiGbFPjwt3t17VRqRE= gitlab.com/xx_network/crypto v0.0.4/go.mod h1:+lcQEy+Th4eswFgQDwT0EXKp4AXrlubxalwQFH5O0Mk= -gitlab.com/xx_network/crypto v0.0.5-0.20220222212031-750f7e8a01f4/go.mod h1:6apvsoHCQJDjO0J4E3uhR3yO9tTz/Mq5be5rjB3tQPU= -gitlab.com/xx_network/crypto v0.0.5-0.20220317171841-084640957d71/go.mod h1:/SJf+R75E+QepdTLh0H1/udsovxx2Q5ru34q1v0umKk= -gitlab.com/xx_network/crypto v0.0.5-0.20220606200528-3f886fe49e81/go.mod h1:/SJf+R75E+QepdTLh0H1/udsovxx2Q5ru34q1v0umKk= -gitlab.com/xx_network/crypto v0.0.5-0.20220729193517-1e5e96f39f6e h1:k+M0zo9eyL2mGaduggdQnwxzOIqOIBV9WIt1QCq92sA= -gitlab.com/xx_network/crypto v0.0.5-0.20220729193517-1e5e96f39f6e/go.mod h1:/SJf+R75E+QepdTLh0H1/udsovxx2Q5ru34q1v0umKk= +gitlab.com/xx_network/crypto v0.0.5-0.20220913213008-98764f5b3287 h1:Jd71F8f/8rieWybMqkxpKKZVVyGkeCNZWZcviGGnQ9A= +gitlab.com/xx_network/crypto v0.0.5-0.20220913213008-98764f5b3287/go.mod h1:/SJf+R75E+QepdTLh0H1/udsovxx2Q5ru34q1v0umKk= gitlab.com/xx_network/primitives v0.0.0-20200803231956-9b192c57ea7c/go.mod h1:wtdCMr7DPePz9qwctNoAUzZtbOSHSedcK++3Df3psjA= gitlab.com/xx_network/primitives v0.0.0-20200804183002-f99f7a7284da/go.mod h1:OK9xevzWCaPO7b1wiluVJGk7R5ZsuC7pHY5hteZFQug= gitlab.com/xx_network/primitives v0.0.2/go.mod h1:cs0QlFpdMDI6lAo61lDRH2JZz+3aVkHy+QogOB6F/qc= gitlab.com/xx_network/primitives v0.0.4-0.20220222211843-901fa4a2d72b/go.mod h1:9imZHvYwNFobxueSvVtHneZLk9wTK7HQTzxPm+zhFhE= -gitlab.com/xx_network/primitives v0.0.4-0.20220317172007-4d2a53e6e669/go.mod h1:AXVVFt7dDAeIUpOGPiStCcUIKsBXLWbmV/BgZ4T+tOo= -gitlab.com/xx_network/primitives v0.0.4-0.20220324193139-b292d1ae6e7e/go.mod h1:AXVVFt7dDAeIUpOGPiStCcUIKsBXLWbmV/BgZ4T+tOo= -gitlab.com/xx_network/primitives v0.0.4-0.20220630163313-7890038258c6/go.mod h1:AXVVFt7dDAeIUpOGPiStCcUIKsBXLWbmV/BgZ4T+tOo= -gitlab.com/xx_network/primitives v0.0.4-0.20220712193914-aebd8544396e h1:zRRo/v3KUo3MtpjNJaB03LR+Zi2g1afYF8yKWl1t19o= -gitlab.com/xx_network/primitives v0.0.4-0.20220712193914-aebd8544396e/go.mod h1:AXVVFt7dDAeIUpOGPiStCcUIKsBXLWbmV/BgZ4T+tOo= -gitlab.com/xx_network/primitives v0.0.4-0.20221010192422-3479f09b7769 h1:BBYSog3VSKudey4rhWnCw54PcGcD4YRjTrnwzOhJ/GE= -gitlab.com/xx_network/primitives v0.0.4-0.20221010192422-3479f09b7769/go.mod h1:AXVVFt7dDAeIUpOGPiStCcUIKsBXLWbmV/BgZ4T+tOo= +gitlab.com/xx_network/primitives v0.0.4-0.20220809193445-9fc0a5209548 h1:6orM1nSt9H/uN/oqbF8RYmwZ/OuWU6h79Fp+tWeHIPY= +gitlab.com/xx_network/primitives v0.0.4-0.20220809193445-9fc0a5209548/go.mod h1:AXVVFt7dDAeIUpOGPiStCcUIKsBXLWbmV/BgZ4T+tOo= gitlab.com/xx_network/ring v0.0.3-0.20220222211904-da613960ad93 h1:eJZrXqHsMmmejEPWw8gNAt0I8CGAMNO/7C339Zco3TM= gitlab.com/xx_network/ring v0.0.3-0.20220222211904-da613960ad93/go.mod h1:aLzpP2TiZTQut/PVHR40EJAomzugDdHXetbieRClXIM= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= go.etcd.io/etcd/api/v3 v3.5.4/go.mod h1:5GB2vv4A4AOn3yk7MftYGHkUfGtDHnEraIjym4dYz5A= go.etcd.io/etcd/client/pkg/v3 v3.5.4/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= go.etcd.io/etcd/client/v2 v2.305.4/go.mod h1:Ud+VUwIi9/uQHOMA+4ekToJ12lTxlv0zB/+DHwTGEbU= go.etcd.io/etcd/client/v3 v3.5.4/go.mod h1:ZaRkVgBZC+L+dLCjTcF1hRXpgZXQPOvnA/Ak/gq3kiY= +go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -477,30 +692,44 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= +go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +go.uber.org/goleak v0.10.0/go.mod h1:VCZuO8V8mFPlL0F5J5GK1rtHV3DrFcQ1R8ryq7FK0aI= +go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/ratelimit v0.2.0 h1:UQE2Bgi7p2B85uP5dC2bbRtig0C+OeNRnNEafLjsLPA= go.uber.org/ratelimit v0.2.0/go.mod h1:YYBV4e4naJvhpitQrWJu1vCpgB7CboMe0qhltKt6mUg= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/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-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 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/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220128200615-198e4374d7ed/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220518034528-6f7dac969898/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -513,6 +742,7 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -540,8 +770,13 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 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= @@ -552,6 +787,7 @@ golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -560,6 +796,7 @@ golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= @@ -570,6 +807,7 @@ golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= @@ -578,7 +816,7 @@ golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLd golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= @@ -586,8 +824,8 @@ golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220802222814-0bcc04d9c69b h1:3ogNYyK4oIQdIKzTu68hQrr4iuVxF3AxKl9Aj/eDrw0= -golang.org/x/net v0.0.0-20220802222814-0bcc04d9c69b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.0.0-20220822230855-b0a4917ee28c h1:JVAXQ10yGGVbSyoer5VILysz6YKjdNT2bsvlayjqhes= +golang.org/x/net v0.0.0-20220822230855-b0a4917ee28c/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -623,7 +861,11 @@ golang.org/x/sync v0.0.0-20220513210516-0976fa681c29/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -634,6 +876,7 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -641,6 +884,7 @@ golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -653,6 +897,7 @@ golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/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/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -662,7 +907,6 @@ golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200917073148-efd3b9a0ff20/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201014080544-cc95f250f6bc/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -689,6 +933,7 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -721,15 +966,19 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/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-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= @@ -740,6 +989,9 @@ golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -747,6 +999,7 @@ golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= @@ -785,6 +1038,7 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -825,6 +1079,7 @@ google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69 google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw= google.golang.org/api v0.81.0/go.mod h1:FA6Mb/bZxj706H2j+j2d6mHEEaHBmbbWnkfvmorOCko= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= @@ -836,6 +1091,7 @@ google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= @@ -846,12 +1102,14 @@ google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvx google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200204235621-fb4a7afc5178/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= @@ -867,6 +1125,7 @@ google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= @@ -909,12 +1168,17 @@ google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220802133213-ce4fa296bf78 h1:QntLWYqZeuBtJkth3m/6DLznnI0AHJr+AgJXvVh/izw= -google.golang.org/genproto v0.0.0-20220802133213-ce4fa296bf78/go.mod h1:iHe1svFLAZg9VWz891+QbRMwUv9O/1Ww+/mngYeThbc= +google.golang.org/genproto v0.0.0-20220822174746-9e6da59bd2fc h1:Nf+EdcTLHR8qDNN/KfkQL0u0ssxt9OhbaWCl5C0ucEI= +google.golang.org/genproto v0.0.0-20220822174746-9e6da59bd2fc/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= @@ -924,6 +1188,7 @@ google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3Iji google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= @@ -941,8 +1206,9 @@ google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ5 google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.48.0 h1:rQOsyJ/8+ufEDJd/Gdsz7HG220Mh9HAhFHRGnIjda0w= google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.49.0 h1:WTLtQzmQori5FUH25Pq4WT22oCsv8USpQ+F6rqtsmxw= +google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= 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= @@ -967,10 +1233,17 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/ini.v1 v1.66.4/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.66.6 h1:LATuAqN/shcYAOkv3wl2L4rkaKqkcgTBQjOyYDvcPKI= gopkg.in/ini.v1 v1.66.6/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= 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.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -986,6 +1259,7 @@ gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -993,7 +1267,13 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +lukechampine.com/blake3 v1.1.6/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA= +nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= +nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g= +nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= +sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/groupChat/compileProtobuf.sh b/groupChat/compileProtobuf.sh new file mode 100644 index 0000000000000000000000000000000000000000..f8039748c3b3add0a501215214ee9ea6e53c75a9 --- /dev/null +++ b/groupChat/compileProtobuf.sh @@ -0,0 +1,14 @@ +#!/bin/bash +################################################################################ +## Copyright © 2022 xx foundation ## +## ## +## Use of this source code is governed by a license that can be found in the ## +## LICENSE file. ## +################################################################################ + +# This script will compile the Protobuf file to a Go file (pb.go). +# This is meant to be called from the top level of the repo. + +cd ./groupChat/ || return + +protoc --go_out=. --go_opt=paths=source_relative ./gcMessages.proto diff --git a/groupChat/e2eManager_test.go b/groupChat/e2eManager_test.go index 37e4019cb8442cf95c8537cbb412d2d4a5d1e585..2d89504277be61b03a78908a61a7391d5f61efa5 100644 --- a/groupChat/e2eManager_test.go +++ b/groupChat/e2eManager_test.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package groupChat import ( @@ -11,7 +18,7 @@ import ( "gitlab.com/elixxir/client/e2e/receive" "gitlab.com/elixxir/client/stoppable" "gitlab.com/elixxir/crypto/cyclic" - "gitlab.com/elixxir/crypto/e2e" + cryptoE2e "gitlab.com/elixxir/crypto/e2e" "gitlab.com/xx_network/primitives/id" "sync" "testing" @@ -65,16 +72,15 @@ func (tnm *testE2eManager) GetE2eMsg(i int) testE2eMessage { } func (tnm *testE2eManager) SendE2E(_ catalog.MessageType, recipient *id.ID, - payload []byte, _ clientE2E.Params) ([]id.Round, e2e.MessageID, time.Time, - error) { + payload []byte, _ clientE2E.Params) (cryptoE2e.SendReport, error) { tnm.Lock() defer tnm.Unlock() tnm.errSkip++ if tnm.sendErr == 1 { - return nil, e2e.MessageID{}, time.Time{}, errors.New("SendE2E error") + return cryptoE2e.SendReport{}, errors.New("SendE2E error") } else if tnm.sendErr == 2 && tnm.errSkip%2 == 0 { - return nil, e2e.MessageID{}, time.Time{}, errors.New("SendE2E error") + return cryptoE2e.SendReport{}, errors.New("SendE2E error") } tnm.e2eMessages = append(tnm.e2eMessages, testE2eMessage{ @@ -82,7 +88,7 @@ func (tnm *testE2eManager) SendE2E(_ catalog.MessageType, recipient *id.ID, Payload: payload, }) - return []id.Round{0, 1, 2, 3}, e2e.MessageID{}, time.Time{}, nil + return cryptoE2e.SendReport{RoundList: []id.Round{0, 1, 2, 3}}, nil } func (*testE2eManager) RegisterListener(*id.ID, catalog.MessageType, receive.Listener) receive.ListenerID { diff --git a/groupChat/gcMessages.pb.go b/groupChat/gcMessages.pb.go index d31c3001125f286af67fb1eacf6986b193513e7c..17cdd83d6f1ab07b2f0b44ed1a33ee017ccb63ed 100644 --- a/groupChat/gcMessages.pb.go +++ b/groupChat/gcMessages.pb.go @@ -1,15 +1,15 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.26.0 -// protoc v3.17.3 -// source: groupChat/gcMessages.proto +// protoc-gen-go v1.27.1 +// protoc v3.15.6 +// source: gcMessages.proto package groupChat @@ -44,7 +44,7 @@ type Request struct { func (x *Request) Reset() { *x = Request{} if protoimpl.UnsafeEnabled { - mi := &file_groupChat_gcMessages_proto_msgTypes[0] + mi := &file_gcMessages_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -57,7 +57,7 @@ func (x *Request) String() string { func (*Request) ProtoMessage() {} func (x *Request) ProtoReflect() protoreflect.Message { - mi := &file_groupChat_gcMessages_proto_msgTypes[0] + mi := &file_gcMessages_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -70,7 +70,7 @@ func (x *Request) ProtoReflect() protoreflect.Message { // Deprecated: Use Request.ProtoReflect.Descriptor instead. func (*Request) Descriptor() ([]byte, []int) { - return file_groupChat_gcMessages_proto_rawDescGZIP(), []int{0} + return file_gcMessages_proto_rawDescGZIP(), []int{0} } func (x *Request) GetName() []byte { @@ -115,45 +115,44 @@ func (x *Request) GetCreated() int64 { return 0 } -var File_groupChat_gcMessages_proto protoreflect.FileDescriptor - -var file_groupChat_gcMessages_proto_rawDesc = []byte{ - 0x0a, 0x1a, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x43, 0x68, 0x61, 0x74, 0x2f, 0x67, 0x63, 0x4d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x11, 0x67, 0x63, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x22, - 0xad, 0x01, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, - 0x1e, 0x0a, 0x0a, 0x69, 0x64, 0x50, 0x72, 0x65, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x69, 0x64, 0x50, 0x72, 0x65, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x12, - 0x20, 0x0a, 0x0b, 0x6b, 0x65, 0x79, 0x50, 0x72, 0x65, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x6b, 0x65, 0x79, 0x50, 0x72, 0x65, 0x69, 0x6d, 0x61, 0x67, - 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x6d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x42, - 0x25, 0x5a, 0x23, 0x67, 0x69, 0x74, 0x6c, 0x61, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x6c, - 0x69, 0x78, 0x78, 0x69, 0x72, 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2f, 0x67, 0x72, 0x6f, - 0x75, 0x70, 0x43, 0x68, 0x61, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +var File_gcMessages_proto protoreflect.FileDescriptor + +var file_gcMessages_proto_rawDesc = []byte{ + 0x0a, 0x10, 0x67, 0x63, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x12, 0x09, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x43, 0x68, 0x61, 0x74, 0x22, 0xad, 0x01, + 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1e, 0x0a, + 0x0a, 0x69, 0x64, 0x50, 0x72, 0x65, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x0a, 0x69, 0x64, 0x50, 0x72, 0x65, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x20, 0x0a, + 0x0b, 0x6b, 0x65, 0x79, 0x50, 0x72, 0x65, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x0b, 0x6b, 0x65, 0x79, 0x50, 0x72, 0x65, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x12, + 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x42, 0x25, 0x5a, + 0x23, 0x67, 0x69, 0x74, 0x6c, 0x61, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x6c, 0x69, 0x78, + 0x78, 0x69, 0x72, 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2f, 0x67, 0x72, 0x6f, 0x75, 0x70, + 0x43, 0x68, 0x61, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( - file_groupChat_gcMessages_proto_rawDescOnce sync.Once - file_groupChat_gcMessages_proto_rawDescData = file_groupChat_gcMessages_proto_rawDesc + file_gcMessages_proto_rawDescOnce sync.Once + file_gcMessages_proto_rawDescData = file_gcMessages_proto_rawDesc ) -func file_groupChat_gcMessages_proto_rawDescGZIP() []byte { - file_groupChat_gcMessages_proto_rawDescOnce.Do(func() { - file_groupChat_gcMessages_proto_rawDescData = protoimpl.X.CompressGZIP(file_groupChat_gcMessages_proto_rawDescData) +func file_gcMessages_proto_rawDescGZIP() []byte { + file_gcMessages_proto_rawDescOnce.Do(func() { + file_gcMessages_proto_rawDescData = protoimpl.X.CompressGZIP(file_gcMessages_proto_rawDescData) }) - return file_groupChat_gcMessages_proto_rawDescData + return file_gcMessages_proto_rawDescData } -var file_groupChat_gcMessages_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_groupChat_gcMessages_proto_goTypes = []interface{}{ - (*Request)(nil), // 0: gcRequestMessages.Request +var file_gcMessages_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_gcMessages_proto_goTypes = []interface{}{ + (*Request)(nil), // 0: groupChat.Request } -var file_groupChat_gcMessages_proto_depIdxs = []int32{ +var file_gcMessages_proto_depIdxs = []int32{ 0, // [0:0] is the sub-list for method output_type 0, // [0:0] is the sub-list for method input_type 0, // [0:0] is the sub-list for extension type_name @@ -161,13 +160,13 @@ var file_groupChat_gcMessages_proto_depIdxs = []int32{ 0, // [0:0] is the sub-list for field type_name } -func init() { file_groupChat_gcMessages_proto_init() } -func file_groupChat_gcMessages_proto_init() { - if File_groupChat_gcMessages_proto != nil { +func init() { file_gcMessages_proto_init() } +func file_gcMessages_proto_init() { + if File_gcMessages_proto != nil { return } if !protoimpl.UnsafeEnabled { - file_groupChat_gcMessages_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + file_gcMessages_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Request); i { case 0: return &v.state @@ -184,18 +183,18 @@ func file_groupChat_gcMessages_proto_init() { out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_groupChat_gcMessages_proto_rawDesc, + RawDescriptor: file_gcMessages_proto_rawDesc, NumEnums: 0, NumMessages: 1, NumExtensions: 0, NumServices: 0, }, - GoTypes: file_groupChat_gcMessages_proto_goTypes, - DependencyIndexes: file_groupChat_gcMessages_proto_depIdxs, - MessageInfos: file_groupChat_gcMessages_proto_msgTypes, + GoTypes: file_gcMessages_proto_goTypes, + DependencyIndexes: file_gcMessages_proto_depIdxs, + MessageInfos: file_gcMessages_proto_msgTypes, }.Build() - File_groupChat_gcMessages_proto = out.File - file_groupChat_gcMessages_proto_rawDesc = nil - file_groupChat_gcMessages_proto_goTypes = nil - file_groupChat_gcMessages_proto_depIdxs = nil + File_gcMessages_proto = out.File + file_gcMessages_proto_rawDesc = nil + file_gcMessages_proto_goTypes = nil + file_gcMessages_proto_depIdxs = nil } diff --git a/groupChat/gcMessages.proto b/groupChat/gcMessages.proto index cc417505c71d9158a7e5e82fcc71ad25c8e3170f..46299a91d34c568f9d1590cbf87faae430f97ae3 100644 --- a/groupChat/gcMessages.proto +++ b/groupChat/gcMessages.proto @@ -1,14 +1,15 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// syntax = "proto3"; -package gcRequestMessages; -option go_package = "gitlab.com/elixxir/client/groupChat"; +package groupChat; + +option go_package = "gitlab.com/elixxir/client/groupChat"; // Request to join the group sent from leader to all members. message Request { diff --git a/groupChat/generateProto.sh b/groupChat/generateProto.sh deleted file mode 100644 index 43968a4aa112270ffb38ea9a2c5da91e309871f1..0000000000000000000000000000000000000000 --- a/groupChat/generateProto.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -protoc --go_out=paths=source_relative:. groupChat/gcMessages.proto diff --git a/groupChat/groupStore/dhKeyList.go b/groupChat/groupStore/dhKeyList.go index 5319cd33eb964f8e4027f0a13357f6ae806d0c84..a00aa39b122aa82dbe9667891c318f2898c2652b 100644 --- a/groupChat/groupStore/dhKeyList.go +++ b/groupChat/groupStore/dhKeyList.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package groupStore diff --git a/groupChat/groupStore/dhKeyList_test.go b/groupChat/groupStore/dhKeyList_test.go index e6b7a9e6965703d5ae3b7c9a5272597a173ac355..e7f37cc7c544cc52c7aeb92997154f44bb265681 100644 --- a/groupChat/groupStore/dhKeyList_test.go +++ b/groupChat/groupStore/dhKeyList_test.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package groupStore import ( diff --git a/groupChat/groupStore/group.go b/groupChat/groupStore/group.go index 2c7d3e91739af0494f74316fac517b937cd86e86..6a9ac4192f4939a8dcbf0c7d54b7c8c6dedb9b9d 100644 --- a/groupChat/groupStore/group.go +++ b/groupChat/groupStore/group.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package groupStore @@ -105,7 +105,7 @@ func (g Group) store(kv *versioned.KV) error { Data: g.Serialize(), } - return kv.Set(groupStoreKey(g.ID), groupStoreVersion, obj) + return kv.Set(groupStoreKey(g.ID), obj) } // loadGroup returns the group with the corresponding ID from storage. diff --git a/groupChat/groupStore/group_test.go b/groupChat/groupStore/group_test.go index 047df74bc3981ef0b3f7b107c5c57fe87dac3ed6..a45be564da007da3164f2f3dc4e6853b3bcce773 100644 --- a/groupChat/groupStore/group_test.go +++ b/groupChat/groupStore/group_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package groupStore diff --git a/groupChat/groupStore/store.go b/groupChat/groupStore/store.go index f2372be86f92e454dcd06320658d4beb11d69e4e..74140e19f91c1711f05b0f5c7f91abcee6ee0631 100644 --- a/groupChat/groupStore/store.go +++ b/groupChat/groupStore/store.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package groupStore @@ -126,7 +126,7 @@ func (s *Store) saveGroupList() error { } // Save to storage - return s.kv.Set(groupListStorageKey, groupListVersion, obj) + return s.kv.Set(groupListStorageKey, obj) } // serializeGroupIdList serializes the list of group IDs. diff --git a/groupChat/groupStore/store_test.go b/groupChat/groupStore/store_test.go index e5549f06b1afadeceb44dd3a8bb3d2ac3c0ce7d1..aaeaebe7eff15e4d51c566359d50ff22ae31b99c 100644 --- a/groupChat/groupStore/store_test.go +++ b/groupChat/groupStore/store_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package groupStore diff --git a/groupChat/groupStore/utils_test.go b/groupChat/groupStore/utils_test.go index 8aff7c8400183aa61b352d1e4f44f4056f591de5..0ffefb6bf8538e76ee09994d568e106460c4f2d1 100644 --- a/groupChat/groupStore/utils_test.go +++ b/groupChat/groupStore/utils_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package groupStore diff --git a/groupChat/interface.go b/groupChat/interface.go index 0355c90943797cb7ab98d7e02e648ba946f1692b..e9b14c911abe56c1072e571d552dca6047d35cbd 100644 --- a/groupChat/interface.go +++ b/groupChat/interface.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// // Group chat is used to communicate the same content with multiple clients over // cMix. A group chat is controlled by a group leader who creates the group, @@ -24,6 +24,7 @@ import ( "gitlab.com/elixxir/client/catalog" "gitlab.com/elixxir/client/cmix" "gitlab.com/elixxir/client/cmix/message" + "gitlab.com/elixxir/client/cmix/rounds" "gitlab.com/elixxir/client/e2e" "gitlab.com/elixxir/client/e2e/ratchet/partner" sessionImport "gitlab.com/elixxir/client/e2e/ratchet/partner/session" @@ -32,7 +33,7 @@ import ( "gitlab.com/elixxir/client/storage" "gitlab.com/elixxir/client/xxdk" "gitlab.com/elixxir/crypto/cyclic" - crypto "gitlab.com/elixxir/crypto/e2e" + cryptoE2e "gitlab.com/elixxir/crypto/e2e" "gitlab.com/elixxir/crypto/fastRNG" "gitlab.com/elixxir/crypto/group" "gitlab.com/xx_network/primitives/id" @@ -68,7 +69,7 @@ type GroupChat interface { // The send fails if the message is too long. Returns the ID of the round // sent on and the timestamp of the message send. Send(groupID *id.ID, tag string, message []byte) ( - id.Round, time.Time, group.MessageID, error) + rounds.Round, time.Time, group.MessageID, error) // GetGroups returns a list of all registered GroupChat IDs. GetGroups() []*id.ID @@ -114,7 +115,7 @@ type groupE2e interface { // methods needed by GroupChat type groupCmix interface { SendMany(messages []cmix.TargetedCmixMessage, p cmix.CMIXParams) ( - id.Round, []ephemeral.Id, error) + rounds.Round, []ephemeral.Id, error) AddService( clientID *id.ID, newService message.Service, response message.Processor) DeleteService( @@ -126,7 +127,7 @@ type groupCmix interface { // needed by GroupChat type groupE2eHandler interface { SendE2E(mt catalog.MessageType, recipient *id.ID, payload []byte, - params e2e.Params) ([]id.Round, crypto.MessageID, time.Time, error) + params e2e.Params) (cryptoE2e.SendReport, error) RegisterListener(senderID *id.ID, messageType catalog.MessageType, newListener receive.Listener) receive.ListenerID AddService(tag string, processor message.Processor) error diff --git a/groupChat/internalFormat.go b/groupChat/internalFormat.go index e8fd69df643856b49a217a7ae0602ce7e741e363..51e98eb6960125334c05aa7f00e771b86da14386 100644 --- a/groupChat/internalFormat.go +++ b/groupChat/internalFormat.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package groupChat diff --git a/groupChat/internalFormat_test.go b/groupChat/internalFormat_test.go index 7c2d415ee68e041842d127293ccdf97b2506d1cf..2a717aa5302dc507c60e9708e132c4c634e01faa 100644 --- a/groupChat/internalFormat_test.go +++ b/groupChat/internalFormat_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package groupChat diff --git a/groupChat/makeGroup.go b/groupChat/makeGroup.go index b7db0a1033a848009ac63e58f0357920382136fa..aeaea8efc6de93e130204137bf9096d56f8eead0 100644 --- a/groupChat/makeGroup.go +++ b/groupChat/makeGroup.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package groupChat diff --git a/groupChat/makeGroup_test.go b/groupChat/makeGroup_test.go index 737ca52cae289725ccd264abe90020e5b0c64ea2..34596d71e8c38d5a5ee28a17c7e7edfe606a1f25 100644 --- a/groupChat/makeGroup_test.go +++ b/groupChat/makeGroup_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package groupChat diff --git a/groupChat/manager.go b/groupChat/manager.go index 0e8fb03645afbe26e4de93dd3e19fa9bf7221342..82b7d432636713788d8e33a4d4e9a3b9db0034fb 100644 --- a/groupChat/manager.go +++ b/groupChat/manager.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package groupChat diff --git a/groupChat/manager_test.go b/groupChat/manager_test.go index c5edaeedf6763e33e3193827ec163e07f179e086..7cb7d2f59d3b4550286531d458921c3d9f96f08a 100644 --- a/groupChat/manager_test.go +++ b/groupChat/manager_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package groupChat diff --git a/groupChat/messageReceive.go b/groupChat/messageReceive.go index c605d7860b096d82411ef5d1ba2b3c9e1604968e..82cbc37d30123496353a4311e986206b47b65642 100644 --- a/groupChat/messageReceive.go +++ b/groupChat/messageReceive.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package groupChat diff --git a/groupChat/messageReceive_test.go b/groupChat/messageReceive_test.go index 701890bcedd5476d529f3dd1d2e42a31e0e979ce..4ba6ece72aab9e4c92a36b84fc4dd3ae3ea86eff 100644 --- a/groupChat/messageReceive_test.go +++ b/groupChat/messageReceive_test.go @@ -1,9 +1,10 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package groupChat import ( diff --git a/groupChat/messenger_test.go b/groupChat/messenger_test.go index 56436ad65481bc4520d76770604cbd13364e9b8a..1ebf8d4d696cf05881c317ffafa3a5f4fd03cc5d 100644 --- a/groupChat/messenger_test.go +++ b/groupChat/messenger_test.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package groupChat import ( diff --git a/groupChat/networkManager_test.go b/groupChat/networkManager_test.go index a6df5a6427d976a21a652d89db81e8941348f34e..e87b3f655bca1e2d5ccbf3d6547a25c1b1ac471d 100644 --- a/groupChat/networkManager_test.go +++ b/groupChat/networkManager_test.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package groupChat import ( @@ -37,9 +44,9 @@ func newTestNetworkManager(sendErr int) cmix.Client { } } -func (tnm *testNetworkManager) SendMany(messages []cmix.TargetedCmixMessage, _ cmix.CMIXParams) (id.Round, []ephemeral.Id, error) { +func (tnm *testNetworkManager) SendMany(messages []cmix.TargetedCmixMessage, _ cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error) { if tnm.sendErr == 1 { - return 0, nil, errors.New("SendManyCMIX error") + return rounds.Round{}, nil, errors.New("SendManyCMIX error") } tnm.Lock() @@ -56,7 +63,7 @@ func (tnm *testNetworkManager) SendMany(messages []cmix.TargetedCmixMessage, _ c receiveMessages = append(receiveMessages, receiveMsg) } tnm.receptionMessages = append(tnm.receptionMessages, receiveMessages) - return 0, nil, nil + return rounds.Round{}, nil, nil } func (*testNetworkManager) AddService(*id.ID, message.Service, message.Processor) {} @@ -71,7 +78,14 @@ func (tnm *testNetworkManager) Follow(report cmix.ClientErrorReport) (stoppable. panic("implement me") } -func (tnm *testNetworkManager) Send(recipient *id.ID, fingerprint format.Fingerprint, service message.Service, payload, mac []byte, cmixParams cmix.CMIXParams) (id.Round, ephemeral.Id, error) { +func (tnm *testNetworkManager) SendWithAssembler(recipient *id.ID, + assembler cmix.MessageAssembler, cmixParams cmix.CMIXParams) (rounds.Round, + ephemeral.Id, error) { + //TODO implement me + panic("implement me") +} + +func (tnm *testNetworkManager) Send(recipient *id.ID, fingerprint format.Fingerprint, service message.Service, payload, mac []byte, cmixParams cmix.CMIXParams) (rounds.Round, ephemeral.Id, error) { //TODO implement me panic("implement me") } @@ -156,7 +170,7 @@ func (tnm *testNetworkManager) TriggerNodeRegistration(nid *id.ID) { panic("implement me") } -func (tnm *testNetworkManager) GetRoundResults(timeout time.Duration, roundCallback cmix.RoundEventCallback, roundList ...id.Round) error { +func (tnm *testNetworkManager) GetRoundResults(timeout time.Duration, roundCallback cmix.RoundEventCallback, roundList ...id.Round) { //TODO implement me panic("implement me") } diff --git a/groupChat/processor.go b/groupChat/processor.go index fa115755751a6e5d6a989c9456895220ec5336ef..f397046a924b66808b115b35f1f41221f876d175 100644 --- a/groupChat/processor.go +++ b/groupChat/processor.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package groupChat diff --git a/groupChat/publicFormat.go b/groupChat/publicFormat.go index ab88d9e09f9c7e5110404fca5fc473070b45c088..eb72300f480c57701149b1211df546a9916f95de 100644 --- a/groupChat/publicFormat.go +++ b/groupChat/publicFormat.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package groupChat diff --git a/groupChat/publicFormat_test.go b/groupChat/publicFormat_test.go index ceb1ba2ec32ea0f6112b33a53218af557c0c2706..8c734de5a0223747e3dfa44938ec19fd1185684e 100644 --- a/groupChat/publicFormat_test.go +++ b/groupChat/publicFormat_test.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package groupChat import ( diff --git a/groupChat/receive.go b/groupChat/receive.go index aecbfad2ee37d9242a70e3e5f1a8d21773854340..004f7f370224c7df6368705f86b5f33eb4a3e2fd 100644 --- a/groupChat/receive.go +++ b/groupChat/receive.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package groupChat diff --git a/groupChat/receiveRequest.go b/groupChat/receiveRequest.go index 104a326f1101f966510daea00db75a0c613efa67..e88aa858210d7bab639c672caf3e69cf0e2a9e2e 100644 --- a/groupChat/receiveRequest.go +++ b/groupChat/receiveRequest.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package groupChat diff --git a/groupChat/receiveRequest_test.go b/groupChat/receiveRequest_test.go index d1283b8955f319e526322882d5b609e96282c3c2..e3611bab8193e2b87001578d4df640101c71b2dc 100644 --- a/groupChat/receiveRequest_test.go +++ b/groupChat/receiveRequest_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package groupChat diff --git a/groupChat/receive_test.go b/groupChat/receive_test.go index bc35aee1d8280ebfbf261485b58a6a28476d04fc..be3a3bbff5c56c38a9ef3f910a47c18c1e0eddfe 100644 --- a/groupChat/receive_test.go +++ b/groupChat/receive_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package groupChat diff --git a/groupChat/send.go b/groupChat/send.go index efa0e11639c261256fd200cbaac31389b9d7168f..2f1b17c167b13f5c06dbbc3fd3223dc6c1ef4e0f 100644 --- a/groupChat/send.go +++ b/groupChat/send.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package groupChat @@ -12,6 +12,7 @@ import ( jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/cmix" "gitlab.com/elixxir/client/cmix/message" + "gitlab.com/elixxir/client/cmix/rounds" gs "gitlab.com/elixxir/client/groupChat/groupStore" "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/crypto/group" @@ -46,7 +47,7 @@ const ( // Send sends a message to all group members using Cmix.SendMany. // The send fails if the message is too long. func (m *manager) Send(groupID *id.ID, tag string, message []byte) ( - id.Round, time.Time, group.MessageID, error) { + rounds.Round, time.Time, group.MessageID, error) { if tag == "" { tag = defaultServiceTag @@ -55,7 +56,7 @@ func (m *manager) Send(groupID *id.ID, tag string, message []byte) ( // Get the relevant group g, exists := m.GetGroup(groupID) if !exists { - return 0, time.Time{}, group.MessageID{}, + return rounds.Round{}, time.Time{}, group.MessageID{}, errors.Errorf(newNoGroupErr, groupID) } @@ -65,7 +66,7 @@ func (m *manager) Send(groupID *id.ID, tag string, message []byte) ( // Create a cMix message for each group member groupMessages, err := m.newMessages(g, tag, message, timeNow) if err != nil { - return 0, time.Time{}, group.MessageID{}, + return rounds.Round{}, time.Time{}, group.MessageID{}, errors.Errorf(newCmixMsgErr, g.Name, g.ID, err) } @@ -73,7 +74,7 @@ func (m *manager) Send(groupID *id.ID, tag string, message []byte) ( msgId, err := getGroupMessageId( m.getE2eGroup(), groupID, m.getReceptionIdentity().ID, timeNow, message) if err != nil { - return 0, time.Time{}, group.MessageID{}, err + return rounds.Round{}, time.Time{}, group.MessageID{}, err } // Send all the groupMessages @@ -81,7 +82,7 @@ func (m *manager) Send(groupID *id.ID, tag string, message []byte) ( param.DebugTag = "group.Message" rid, _, err := m.getCMix().SendMany(groupMessages, param) if err != nil { - return 0, time.Time{}, group.MessageID{}, + return rounds.Round{}, time.Time{}, group.MessageID{}, errors.Errorf(sendManyCmixErr, m.getReceptionIdentity().ID, g.Name, g.ID, err) } diff --git a/groupChat/sendRequests.go b/groupChat/sendRequests.go index b28985361e09183b6b4d807e10c770b454386bda..36046527379d67151a69f588e773b03f6758f87d 100644 --- a/groupChat/sendRequests.go +++ b/groupChat/sendRequests.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package groupChat @@ -120,13 +120,13 @@ func (m *manager) sendRequest(memberID *id.ID, request []byte) ([]id.Round, erro p.LastServiceTag = catalog.GroupRq p.DebugTag = "group.Request" - rounds, _, _, err := m.getE2eHandler().SendE2E( + sendReport, err := m.getE2eHandler().SendE2E( catalog.GroupCreationRequest, memberID, request, p) if err != nil { return nil, errors.Errorf(sendE2eErr, memberID, err) } - return rounds, nil + return sendReport.RoundList, nil } // roundIdMap2List converts the map of round IDs to a list of round IDs. diff --git a/groupChat/sendRequests_test.go b/groupChat/sendRequests_test.go index bb2589689e40f70b997ddd250da33c50f0c2c99a..3878e52a4d81e80523c41d3bdc2baf41281ab39c 100644 --- a/groupChat/sendRequests_test.go +++ b/groupChat/sendRequests_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package groupChat diff --git a/groupChat/send_test.go b/groupChat/send_test.go index be68cb2e8bccca341785038e8596302ba63ba9d5..5ecaa63efdca7f1d461fb59c67908988370accc5 100644 --- a/groupChat/send_test.go +++ b/groupChat/send_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package groupChat @@ -56,7 +56,7 @@ func Test_manager_Send(t *testing.T) { reception.Process(msg, receptionID.EphemeralIdentity{ EphId: ephemeral.Id{1, 2, 3}, Source: &id.ID{4, 5, 6}, }, - rounds.Round{ID: roundId, Timestamps: timestamps}) + rounds.Round{ID: roundId.ID, Timestamps: timestamps}) select { case result := <-msgChan: if !result.SenderID.Cmp(m.getReceptionIdentity().ID) { diff --git a/groupChat/service.go b/groupChat/service.go index d2a5916aaa7975a8d20065f88ce0a9047bbbed74..eb57bc38f39c010fd1525a48e69720bd9b82b033 100644 --- a/groupChat/service.go +++ b/groupChat/service.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package groupChat diff --git a/groupChat/session_test.go b/groupChat/session_test.go index 15877e7af4c0afcb9a7b8276810ebdd21b91eb26..a61cf8b510ed05b1d7fee252e31dd314f03097d0 100644 --- a/groupChat/session_test.go +++ b/groupChat/session_test.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package groupChat import ( diff --git a/groupChat/utils_test.go b/groupChat/utils_test.go index 024d4c02446fd632937bc87f5d626a20ae5161de..98e63bcf98fa3a658a95b28c16b626c3411ccbcc 100644 --- a/groupChat/utils_test.go +++ b/groupChat/utils_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package groupChat diff --git a/groupChat/wrapper.go b/groupChat/wrapper.go index 6a3e91220d29cef35769f7aff86cef5899a619cc..462811c8d20f606353c419f61bd079e2a8480875 100644 --- a/groupChat/wrapper.go +++ b/groupChat/wrapper.go @@ -1,13 +1,14 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package groupChat import ( + "gitlab.com/elixxir/client/cmix/rounds" gs "gitlab.com/elixxir/client/groupChat/groupStore" "gitlab.com/elixxir/crypto/group" "gitlab.com/xx_network/primitives/id" @@ -53,7 +54,7 @@ func (w *Wrapper) LeaveGroup(groupID *id.ID) error { // Send calls GroupChat.Send. func (w *Wrapper) Send(groupID *id.ID, message []byte, tag string) ( - id.Round, time.Time, group.MessageID, error) { + rounds.Round, time.Time, group.MessageID, error) { return w.gc.Send(groupID, tag, message) } diff --git a/interfaces/auth.go b/interfaces/auth.go index 60ba0d311342b154238caf251d2eb0c22f339d53..fe022dfe471a8696adc56f765ff6a6e96db2418b 100644 --- a/interfaces/auth.go +++ b/interfaces/auth.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package interfaces diff --git a/interfaces/clientError.go b/interfaces/clientError.go index 39c6706c7fb83b1df657c46d46f733c55c9b562d..86b55ac9f959abc6bef07c5870c71a94a78fa0a8 100644 --- a/interfaces/clientError.go +++ b/interfaces/clientError.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package interfaces type ClientError struct { diff --git a/interfaces/ephemeral.go b/interfaces/ephemeral.go index 4d0e7f926f5a3a863a49a51e499dbde5146d7f94..57523cb5e123322a41f551d4d6aab3c68b00f042 100644 --- a/interfaces/ephemeral.go +++ b/interfaces/ephemeral.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package interfaces diff --git a/interfaces/healthTracker.go b/interfaces/healthTracker.go index 0d746d50f73bc1215201c413e5d6d83e54bbbb55..995df5ce21933c8228becc225a8fcd800a6511cf 100644 --- a/interfaces/healthTracker.go +++ b/interfaces/healthTracker.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package interfaces diff --git a/interfaces/networkManager.go b/interfaces/networkManager.go deleted file mode 100644 index 2139e9597c6a4cdc51714e47308d6aa91d3481c5..0000000000000000000000000000000000000000 --- a/interfaces/networkManager.go +++ /dev/null @@ -1,244 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// - -package interfaces - -import ( - "time" - - "gitlab.com/elixxir/comms/network" - "gitlab.com/xx_network/comms/connect" - "gitlab.com/xx_network/primitives/ndf" - - "gitlab.com/elixxir/client/cmix" - "gitlab.com/elixxir/client/cmix/message" - "gitlab.com/elixxir/client/stoppable" - "gitlab.com/elixxir/comms/mixmessages" - "gitlab.com/elixxir/primitives/format" - "gitlab.com/xx_network/primitives/id" - "gitlab.com/xx_network/primitives/id/ephemeral" -) - -type NetworkManager interface { - // Follow starts the tracking of the network in a new thread. - // Errors that occur are reported on the ClientErrorReport function if - // passed. The returned stopable can be used to stop the follower. - // Only one follower may run at a time. - Follow(report ClientErrorReport) (stoppable.Stoppable, error) - - /*===Sending==========================================================*/ - - // SendCMIX sends a "raw" CMIX message payload to the provided - // recipient. Returns the round ID of the round the payload - // was sent or an error if it fails. - SendCMIX(message format.Message, recipient *id.ID, p cmix.Params) ( - id.Round, ephemeral.Id, error) - - // SendManyCMIX sends many "raw" cMix message payloads to each - // of the provided recipients. Used to send messages in group - // chats. Metadata is NOT as well protected with this call and - // can leak data about yourself. Should be replaced with - // multiple uses of SendCmix in most cases. Returns the round - // ID of the round the payload was sent or an error if it - // fails. - // WARNING: Potentially Unsafe - SendManyCMIX(messages []cmix.TargetedCmixMessage, p cmix.Params) ( - id.Round, []ephemeral.Id, error) - - /*===Message Reception================================================*/ - /* Identities are all network identities which the client is currently - trying to pick up message on. An identity must be added - to receive messages, fake ones will be used to poll the network - if none are present. On creation of the network handler, the identity in - session storage will be automatically added*/ - - // AddIdentity adds an identity to be tracked - // If persistent is false, the identity will not be stored to disk and - // will be dropped on reload. - AddIdentity(id *id.ID, validUntil time.Time, persistent bool) error - // RemoveIdentity removes a currently tracked identity. - RemoveIdentity(id *id.ID) - - /* Fingerprints are the primary mechanism of identifying a - picked up message over cMix. They are a unique one time use - 255 bit vector generally associated with a specific encryption - key, but can be used for an alternative protocol.When - registering a fingerprint, a MessageProcessor is registered to - handle the message.*/ - - // AddFingerprint - Adds a fingerprint which will be handled by a - // specific processor for messages received by the given identity - AddFingerprint(identity *id.ID, fingerprint format.Fingerprint, - mp message.Processor) error - - // DeleteFingerprint deletes a single fingerprint associated - // with the given identity if it exists - - DeleteFingerprint(identity *id.ID, fingerprint format.Fingerprint) - // DeleteClientFingerprints deletes al fingerprint associated - // with the given identity if it exists - DeleteClientFingerprints(identity *id.ID) - - /* trigger - predefined hash based tags appended to all cMix messages - which, though trial hashing, are used to determine if a message applies - to this client - - Triggers are used for 2 purposes - They can be processed by the - notifications system, or can be used to implement custom non fingerprint - processing of payloads. I.E. key negotiation, broadcast negotiation - - A tag is appended to the message of the format tag = - H(H(messageContents), preimage) and trial hashing is used to - determine if a message adheres to a tag. - - WARNING: If a preimage is known by an adversary, they can - determine which messages are for the client on reception - (which is normally hidden due to collision between ephemeral - IDs. - - Due to the extra overhead of trial hashing, triggers are - processed after fingerprints. If a fingerprint match occurs - on the message, triggers will not be handled. - - Triggers are address to the session. When starting a new - client, all triggers must be re-added before - StartNetworkFollower is called. - */ - - // AddTrigger - Adds a trigger which can call a message - // handing function or be used for notifications. Multiple - // triggers can be registered for the same preimage. - // preimage - the preimage which is triggered on - // type - a descriptive string of the trigger. Generally - // used in notifications - // source - a byte buffer of related data. Generally used in - // notifications. - // Example: Sender ID - AddTrigger(identity *id.ID, newTrigger message.Service, - response message.Processor) - - // DeleteTrigger - If only a single response is associated with the - // preimage, the entire preimage is removed. If there is more than one - // response, only the given response is removed if nil is passed in for - // response, all triggers for the preimage will be removed - DeleteTrigger(identity *id.ID, preimage Preimage, - response message.Processor) error - - // DeleteClientTriggers - deletes all triggers assoseated with - // the given identity - DeleteClientTriggers(identity *id.ID) - - // TrackServices - Registers a callback which will get called - // every time triggers change. - // It will receive the triggers list every time it is modified. - // Will only get callbacks while the Network Follower is running. - // Multiple trackTriggers can be registered - TrackServices(message.ServicesTracker) - - /* In inProcess */ - // it is possible to receive a message over cMix before the - // fingerprints or triggers are registered. As a result, when - // handling fails, messages are put in the inProcess que for a - // set number of retries. - - // CheckInProgressMessages - retry processing all messages in check in - // progress messages. Call this after adding fingerprints or triggers - //while the follower is running. - CheckInProgressMessages() - - /*===Nodes============================================================*/ - /* Keys must be registed with nodes in order to send messages - throug them. this process is in general automatically handled - by the Network Manager*/ - - // HasNode can be used to determine if a keying relationship - // exists with a node. - HasNode(nid *id.ID) bool - - // NumRegisteredNodes Returns the total number of nodes we have a keying - // relationship with - NumRegisteredNodes() int - - // TriggerNodeRegistration triggers the generation of a keying - // relationship with a given node - TriggerNodeRegistration(nid *id.ID) - - /*===Historical Rounds================================================*/ - /* A complete set of round info is not kept on the client, and sometimes - the network will need to be queried to get round info. Historical rounds - is the system internal to the Network Manager to do this. - It can be used externally as well.*/ - - // LookupHistoricalRound - looks up the passed historical round on the - // network - LookupHistoricalRound(rid id.Round, - callback func(info *mixmessages.RoundInfo, - success bool)) error - - /*===Sender===========================================================*/ - /* The sender handles sending comms to the network. It tracks - connections to gateways and handles proxying to gateways for - targeted comms. It can be used externally to contact gateway - directly, bypassing the majority of the network package*/ - - // SendToAny can be used to send the comm to any gateway in the network. - SendToAny(sendFunc func(host *connect.Host) (interface{}, error), - stop *stoppable.Single) (interface{}, error) - - // SendToPreferred sends to a specific gateway, doing so through another - // gateway as a proxy if not directly connected. - SendToPreferred(targets []*id.ID, sendFunc func(host *connect.Host, - target *id.ID, timeout time.Duration) (interface{}, error), - stop *stoppable.Single, timeout time.Duration) (interface{}, - error) - - // SetGatewayFilter sets a function which will be used to - // filter gateways before connecting. - SetGatewayFilter(f func(map[id.ID]int, - *ndf.NetworkDefinition) map[id.ID]int) - - // GetHostParams - returns the host params used when - // connectign to gateways - GetHostParams() connect.HostParams - - /*===Address Space====================================================*/ - // The network compasses identities into a smaller address - // space to cause collisions and hide the actual recipient of - // messages. These functions allow for the tracking of this - // addresses space. In general, address space issues are - // completely handled by the network package - - // GetAddressSpace GetAddressSize returns the current address - // size of IDs. Blocks until an address size is known. - GetAddressSpace() uint8 - - // RegisterAddressSpaceNotification returns a channel that - // will trigger for every address space size update. The - // provided tag is the unique ID for the channel. Returns an - // error if the tag is already used. - RegisterAddressSpaceNotification(tag string) (chan uint8, error) - - // UnregisterAddressSpaceNotification stops broadcasting - // address space size updates on the channel with the - // specified tag. - UnregisterAddressSpaceNotification(tag string) - - /*===Accessors========================================================*/ - - // GetInstance returns the network instance object, which tracks the - // state of the network - GetInstance() *network.Instance - - // GetHealthTracker returns the health tracker, which using a polling or - // event api lets you determine if network following is functioning - GetHealthTracker() HealthTracker - - // GetVerboseRounds returns stringification of verbose round info - GetVerboseRounds() string -} - -type Preimage [32]byte diff --git a/interfaces/restoreContacts.go b/interfaces/restoreContacts.go index defc6877b4310d964425b6f2555df64a2a5a28d9..82ca65b825d5081baff773519d6d0c0eced6a39c 100644 --- a/interfaces/restoreContacts.go +++ b/interfaces/restoreContacts.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package interfaces diff --git a/interfaces/roundEvents.go b/interfaces/roundEvents.go index 7228649def38a6199a7650df1b811373ad7f0307..a2113d6f5fe86959aa365729eac5c8ae2bd8f3e1 100644 --- a/interfaces/roundEvents.go +++ b/interfaces/roundEvents.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package interfaces diff --git a/interfaces/sidh/sidh.go b/interfaces/sidh/sidh.go index 81468e4be1f4e48ee50cd20713cd08eab5be3f0a..ff1ad9c4f63a063ce54bf67e2759e56b374054d8 100644 --- a/interfaces/sidh/sidh.go +++ b/interfaces/sidh/sidh.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package interfaces import "github.com/cloudflare/circl/dh/sidh" diff --git a/main.go b/main.go index 47a38ce28d8f06cb2c16d1aba035b3a9c393caad..ac80eb9a1fc5411c091bd1f3bad27b89e90114d7 100644 --- a/main.go +++ b/main.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package main diff --git a/registration/permissioning.go b/registration/permissioning.go index cab953a8472df368a6bc7dd72218a5e49796c2c8..293c39010e2074c3297d306303d9d4b163f8d3f3 100644 --- a/registration/permissioning.go +++ b/registration/permissioning.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package registration diff --git a/registration/permissioning_test.go b/registration/permissioning_test.go index 616ab9393b868bf4da25e69976a3d316adc23d84..94d2bacf0cfa75789016efaca3b629c26bf6cac1 100644 --- a/registration/permissioning_test.go +++ b/registration/permissioning_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package registration diff --git a/registration/register.go b/registration/register.go index 57b6cf8f2003b0323d96d9b53aff9dc6e0f1ac2c..56986c809660edcf23fadf0947afa2f8aa5fc485 100644 --- a/registration/register.go +++ b/registration/register.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package registration @@ -62,14 +62,6 @@ func register(comms registrationMessageSender, host *connect.Host, "reception confirmation message") } - transmissionConfirmation := &pb.ClientRegistrationConfirmation{} - err = proto.Unmarshal(response.GetClientReceptionConfirmation(). - ClientRegistrationConfirmation, transmissionConfirmation) - if err != nil { - return nil, nil, 0, errors.WithMessage(err, "Failed to unmarshal "+ - "transmission confirmation message") - } - // Verify reception signature receptionSignature := response.GetClientReceptionConfirmation(). GetRegistrarSignature().Signature @@ -80,6 +72,15 @@ func register(comms registrationMessageSender, host *connect.Host, return nil, nil, 0, errors.WithMessage(err, "Failed to verify reception signature") } + // Unmarshal transmission confirmation + transmissionConfirmation := &pb.ClientRegistrationConfirmation{} + err = proto.Unmarshal(response.GetClientTransmissionConfirmation(). + ClientRegistrationConfirmation, transmissionConfirmation) + if err != nil { + return nil, nil, 0, errors.WithMessage(err, "Failed to unmarshal "+ + "transmission confirmation message") + } + // Verify transmission signature transmissionSignature := response.GetClientTransmissionConfirmation(). GetRegistrarSignature().Signature diff --git a/registration/register_test.go b/registration/register_test.go index d7b95baf4e4581ca96f56605e43eb043a628e46e..8cec2bfb92f215640de1206141d473a47eea9601 100644 --- a/registration/register_test.go +++ b/registration/register_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package registration diff --git a/restlike/compileProtobuf.sh b/restlike/compileProtobuf.sh new file mode 100644 index 0000000000000000000000000000000000000000..1e6fda1ef503db58983b3756bc578760e7ddaaec --- /dev/null +++ b/restlike/compileProtobuf.sh @@ -0,0 +1,14 @@ +#!/bin/bash +################################################################################ +## Copyright © 2022 xx foundation ## +## ## +## Use of this source code is governed by a license that can be found in the ## +## LICENSE file. ## +################################################################################ + +# This script will compile the Protobuf file to a Go file (pb.go). +# This is meant to be called from the top level of the repo. + +cd ./restlike/ || return + +protoc --go_out=. --go_opt=paths=source_relative ./restLikeMessages.proto diff --git a/restlike/connect/receiver.go b/restlike/connect/receiver.go index d6e87c57489a4235cd0e225fb38c4c87dad4afc3..20ad79df76dd9003ac6d7e43cbae18185faa8217 100644 --- a/restlike/connect/receiver.go +++ b/restlike/connect/receiver.go @@ -1,7 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2022 Privategrity Corporation / -// / -// All rights reserved. / +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package connect @@ -55,7 +56,7 @@ func respond(response *restlike.Message, conn connect.Connection) error { } // TODO: Parameterize params - _, _, _, err = conn.SendE2E(catalog.XxMessage, payload, e2e.GetDefaultParams()) + _, err = conn.SendE2E(catalog.XxMessage, payload, e2e.GetDefaultParams()) if err != nil { return errors.Errorf("unable to send restlike response message: %+v", err) } diff --git a/restlike/connect/receiver_test.go b/restlike/connect/receiver_test.go index 723ec019fbedf4532b4f2a3d2bf3f66be51d36b1..409dcd9e3814892c229b097677f849bd038ad36d 100644 --- a/restlike/connect/receiver_test.go +++ b/restlike/connect/receiver_test.go @@ -1,7 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2022 Privategrity Corporation / -// / -// All rights reserved. / +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package connect diff --git a/restlike/connect/request.go b/restlike/connect/request.go index 4ea32656a2f3716481153e1955d0435311b61244..bd2ac8d978b1dcc89cd301f8a058c44c72ae76f9 100644 --- a/restlike/connect/request.go +++ b/restlike/connect/request.go @@ -1,7 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2022 Privategrity Corporation / -// / -// All rights reserved. / +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package connect @@ -49,7 +50,8 @@ func (s *Request) Request(method restlike.Method, path restlike.URI, s.Net.RegisterListener(catalog.XxMessage, &response{responseCallback: cb}) // Transmit the Message - _, _, _, err = s.Net.SendE2E(catalog.XxMessage, msg, e2eParams) + // fixme: should this use the key residue? + _, err = s.Net.SendE2E(catalog.XxMessage, msg, e2eParams) if err != nil { return nil, err } @@ -84,6 +86,6 @@ func (s *Request) AsyncRequest(method restlike.Method, path restlike.URI, s.Net.RegisterListener(catalog.XxMessage, &response{responseCallback: cb}) // Transmit the Message - _, _, _, err = s.Net.SendE2E(catalog.XxMessage, msg, e2eParams) + _, err = s.Net.SendE2E(catalog.XxMessage, msg, e2eParams) return err } diff --git a/restlike/connect/response.go b/restlike/connect/response.go index 99042d7c4bd4947a2f2eed560f4fef8114998d9d..83d55ddea39ed9e051953dd2c1b4a3f8910ef39b 100644 --- a/restlike/connect/response.go +++ b/restlike/connect/response.go @@ -1,7 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2022 Privategrity Corporation / -// / -// All rights reserved. / +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package connect diff --git a/restlike/connect/response_test.go b/restlike/connect/response_test.go index f3db1ba40f2024b83522c2d9a5c840d5e4691da4..d82947861901dcf3039dbd1628b948d5c44baea5 100644 --- a/restlike/connect/response_test.go +++ b/restlike/connect/response_test.go @@ -1,7 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2022 Privategrity Corporation / -// / -// All rights reserved. / +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package connect diff --git a/restlike/connect/server.go b/restlike/connect/server.go index 7438b41d7ffaa5edb99e7d3f99913a0250921ee9..47d3955b4d0d33763ae63c2f9a733f7678dce8c6 100644 --- a/restlike/connect/server.go +++ b/restlike/connect/server.go @@ -1,7 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2022 Privategrity Corporation / -// / -// All rights reserved. / +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package connect diff --git a/restlike/generateProto.sh b/restlike/generateProto.sh deleted file mode 100755 index 67b6d293f6f4e6a68eff4162a42acb242129cd18..0000000000000000000000000000000000000000 --- a/restlike/generateProto.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -protoc --go_out=paths=source_relative:. restlike/restLikeMessages.proto diff --git a/restlike/restLikeMessages.pb.go b/restlike/restLikeMessages.pb.go index c6666a5d08dd3c0a086a100a19ca0a74f630af79..674580e375c72f057883a4e6f27a7a5466d3749e 100644 --- a/restlike/restLikeMessages.pb.go +++ b/restlike/restLikeMessages.pb.go @@ -1,15 +1,15 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.1 -// protoc v3.19.1 -// source: restlike/restLikeMessages.proto +// protoc v3.15.6 +// source: restLikeMessages.proto package restlike @@ -43,7 +43,7 @@ type Message struct { func (x *Message) Reset() { *x = Message{} if protoimpl.UnsafeEnabled { - mi := &file_restlike_restLikeMessages_proto_msgTypes[0] + mi := &file_restLikeMessages_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -56,7 +56,7 @@ func (x *Message) String() string { func (*Message) ProtoMessage() {} func (x *Message) ProtoReflect() protoreflect.Message { - mi := &file_restlike_restLikeMessages_proto_msgTypes[0] + mi := &file_restLikeMessages_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -69,7 +69,7 @@ func (x *Message) ProtoReflect() protoreflect.Message { // Deprecated: Use Message.ProtoReflect.Descriptor instead. func (*Message) Descriptor() ([]byte, []int) { - return file_restlike_restLikeMessages_proto_rawDescGZIP(), []int{0} + return file_restLikeMessages_proto_rawDescGZIP(), []int{0} } func (x *Message) GetContent() []byte { @@ -124,7 +124,7 @@ type Headers struct { func (x *Headers) Reset() { *x = Headers{} if protoimpl.UnsafeEnabled { - mi := &file_restlike_restLikeMessages_proto_msgTypes[1] + mi := &file_restLikeMessages_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -137,7 +137,7 @@ func (x *Headers) String() string { func (*Headers) ProtoMessage() {} func (x *Headers) ProtoReflect() protoreflect.Message { - mi := &file_restlike_restLikeMessages_proto_msgTypes[1] + mi := &file_restLikeMessages_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -150,7 +150,7 @@ func (x *Headers) ProtoReflect() protoreflect.Message { // Deprecated: Use Headers.ProtoReflect.Descriptor instead. func (*Headers) Descriptor() ([]byte, []int) { - return file_restlike_restLikeMessages_proto_rawDescGZIP(), []int{1} + return file_restLikeMessages_proto_rawDescGZIP(), []int{1} } func (x *Headers) GetHeaders() []byte { @@ -167,50 +167,49 @@ func (x *Headers) GetVersion() uint32 { return 0 } -var File_restlike_restLikeMessages_proto protoreflect.FileDescriptor +var File_restLikeMessages_proto protoreflect.FileDescriptor -var file_restlike_restLikeMessages_proto_rawDesc = []byte{ - 0x0a, 0x1f, 0x72, 0x65, 0x73, 0x74, 0x6c, 0x69, 0x6b, 0x65, 0x2f, 0x72, 0x65, 0x73, 0x74, 0x4c, - 0x69, 0x6b, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x12, 0x10, 0x72, 0x65, 0x73, 0x74, 0x4c, 0x69, 0x6b, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x73, 0x22, 0x98, 0x01, 0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, - 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x33, 0x0a, 0x07, 0x68, 0x65, 0x61, - 0x64, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x72, 0x65, 0x73, - 0x74, 0x4c, 0x69, 0x6b, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x48, 0x65, - 0x61, 0x64, 0x65, 0x72, 0x73, 0x52, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x16, - 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, - 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x69, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x69, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, - 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x3d, - 0x0a, 0x07, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x68, 0x65, 0x61, - 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x68, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x24, 0x5a, - 0x22, 0x67, 0x69, 0x74, 0x6c, 0x61, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x6c, 0x69, 0x78, - 0x78, 0x69, 0x72, 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2f, 0x72, 0x65, 0x73, 0x74, 0x6c, - 0x69, 0x6b, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +var file_restLikeMessages_proto_rawDesc = []byte{ + 0x0a, 0x16, 0x72, 0x65, 0x73, 0x74, 0x4c, 0x69, 0x6b, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x08, 0x72, 0x65, 0x73, 0x74, 0x6c, 0x69, + 0x6b, 0x65, 0x22, 0x90, 0x01, 0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x18, + 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x2b, 0x0a, 0x07, 0x68, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x72, 0x65, 0x73, 0x74, + 0x6c, 0x69, 0x6b, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x52, 0x07, 0x68, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x10, 0x0a, + 0x03, 0x75, 0x72, 0x69, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x69, 0x12, + 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x3d, 0x0a, 0x07, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, + 0x12, 0x18, 0x0a, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x24, 0x5a, 0x22, 0x67, 0x69, 0x74, 0x6c, 0x61, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x65, 0x6c, 0x69, 0x78, 0x78, 0x69, 0x72, 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, + 0x74, 0x2f, 0x72, 0x65, 0x73, 0x74, 0x6c, 0x69, 0x6b, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( - file_restlike_restLikeMessages_proto_rawDescOnce sync.Once - file_restlike_restLikeMessages_proto_rawDescData = file_restlike_restLikeMessages_proto_rawDesc + file_restLikeMessages_proto_rawDescOnce sync.Once + file_restLikeMessages_proto_rawDescData = file_restLikeMessages_proto_rawDesc ) -func file_restlike_restLikeMessages_proto_rawDescGZIP() []byte { - file_restlike_restLikeMessages_proto_rawDescOnce.Do(func() { - file_restlike_restLikeMessages_proto_rawDescData = protoimpl.X.CompressGZIP(file_restlike_restLikeMessages_proto_rawDescData) +func file_restLikeMessages_proto_rawDescGZIP() []byte { + file_restLikeMessages_proto_rawDescOnce.Do(func() { + file_restLikeMessages_proto_rawDescData = protoimpl.X.CompressGZIP(file_restLikeMessages_proto_rawDescData) }) - return file_restlike_restLikeMessages_proto_rawDescData + return file_restLikeMessages_proto_rawDescData } -var file_restlike_restLikeMessages_proto_msgTypes = make([]protoimpl.MessageInfo, 2) -var file_restlike_restLikeMessages_proto_goTypes = []interface{}{ - (*Message)(nil), // 0: restLikeMessages.Message - (*Headers)(nil), // 1: restLikeMessages.Headers +var file_restLikeMessages_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_restLikeMessages_proto_goTypes = []interface{}{ + (*Message)(nil), // 0: restlike.Message + (*Headers)(nil), // 1: restlike.Headers } -var file_restlike_restLikeMessages_proto_depIdxs = []int32{ - 1, // 0: restLikeMessages.Message.headers:type_name -> restLikeMessages.Headers +var file_restLikeMessages_proto_depIdxs = []int32{ + 1, // 0: restlike.Message.headers:type_name -> restlike.Headers 1, // [1:1] is the sub-list for method output_type 1, // [1:1] is the sub-list for method input_type 1, // [1:1] is the sub-list for extension type_name @@ -218,13 +217,13 @@ var file_restlike_restLikeMessages_proto_depIdxs = []int32{ 0, // [0:1] is the sub-list for field type_name } -func init() { file_restlike_restLikeMessages_proto_init() } -func file_restlike_restLikeMessages_proto_init() { - if File_restlike_restLikeMessages_proto != nil { +func init() { file_restLikeMessages_proto_init() } +func file_restLikeMessages_proto_init() { + if File_restLikeMessages_proto != nil { return } if !protoimpl.UnsafeEnabled { - file_restlike_restLikeMessages_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + file_restLikeMessages_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Message); i { case 0: return &v.state @@ -236,7 +235,7 @@ func file_restlike_restLikeMessages_proto_init() { return nil } } - file_restlike_restLikeMessages_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + file_restLikeMessages_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Headers); i { case 0: return &v.state @@ -253,18 +252,18 @@ func file_restlike_restLikeMessages_proto_init() { out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_restlike_restLikeMessages_proto_rawDesc, + RawDescriptor: file_restLikeMessages_proto_rawDesc, NumEnums: 0, NumMessages: 2, NumExtensions: 0, NumServices: 0, }, - GoTypes: file_restlike_restLikeMessages_proto_goTypes, - DependencyIndexes: file_restlike_restLikeMessages_proto_depIdxs, - MessageInfos: file_restlike_restLikeMessages_proto_msgTypes, + GoTypes: file_restLikeMessages_proto_goTypes, + DependencyIndexes: file_restLikeMessages_proto_depIdxs, + MessageInfos: file_restLikeMessages_proto_msgTypes, }.Build() - File_restlike_restLikeMessages_proto = out.File - file_restlike_restLikeMessages_proto_rawDesc = nil - file_restlike_restLikeMessages_proto_goTypes = nil - file_restlike_restLikeMessages_proto_depIdxs = nil + File_restLikeMessages_proto = out.File + file_restLikeMessages_proto_rawDesc = nil + file_restLikeMessages_proto_goTypes = nil + file_restLikeMessages_proto_depIdxs = nil } diff --git a/restlike/restLikeMessages.proto b/restlike/restLikeMessages.proto index 00156d5443904383deb89f64c391e0009741dc78..c0b37ee7652a1da6df2cca0a16deb4bf36c3e35f 100644 --- a/restlike/restLikeMessages.proto +++ b/restlike/restLikeMessages.proto @@ -1,12 +1,14 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// syntax = "proto3"; -package restLikeMessages; + +package restlike; + option go_package = "gitlab.com/elixxir/client/restlike"; // Message are used for sending to and receiving from a RestServer diff --git a/restlike/single/receiver.go b/restlike/single/receiver.go index f25268f8160d2d257121af560619c87997d87111..381bd923ebb120d7c1eb7c98c07de2ed18461a9f 100644 --- a/restlike/single/receiver.go +++ b/restlike/single/receiver.go @@ -1,7 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2022 Privategrity Corporation / -// / -// All rights reserved. / +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package single diff --git a/restlike/single/receiver_test.go b/restlike/single/receiver_test.go index 3b06c4c15691c049b1adcf684e9d29893baef121..7fe2bc6c02eddffc910b40f0728f00cc791dd136 100644 --- a/restlike/single/receiver_test.go +++ b/restlike/single/receiver_test.go @@ -1,7 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2022 Privategrity Corporation / -// / -// All rights reserved. / +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package single diff --git a/restlike/single/request.go b/restlike/single/request.go index 8a0b550867b5d2ebdaa43333fcf529940c701982..53dfcbce8a69a4811cc0f4cd6d91c49ae93f2451 100644 --- a/restlike/single/request.go +++ b/restlike/single/request.go @@ -1,7 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2022 Privategrity Corporation / -// / -// All rights reserved. / +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package single diff --git a/restlike/single/response.go b/restlike/single/response.go index edc4833226d0372ae6816f4a190772127aaf6e7e..a0e0314677890b017c093738e1597624fc303b25 100644 --- a/restlike/single/response.go +++ b/restlike/single/response.go @@ -1,7 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2022 Privategrity Corporation / -// / -// All rights reserved. / +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package single diff --git a/restlike/single/response_test.go b/restlike/single/response_test.go index b5e11bf81acca0a91cd9342390b7e712125a4518..da2aedcea8035c8a2189dc0f63fa1a3ed8004256 100644 --- a/restlike/single/response_test.go +++ b/restlike/single/response_test.go @@ -1,7 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2022 Privategrity Corporation / -// / -// All rights reserved. / +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package single diff --git a/restlike/single/server.go b/restlike/single/server.go index 99c2bc08b6327d372ade95711a2a0c945ce33795..607de3e1193f3d99d864cd44b5a675650b1b2ab5 100644 --- a/restlike/single/server.go +++ b/restlike/single/server.go @@ -1,7 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2022 Privategrity Corporation / -// / -// All rights reserved. / +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package single diff --git a/restlike/types.go b/restlike/types.go index 8937575ed720bb14634bf34e6d02908988a28b13..b9158b4a761a318a20701f51e69cad2f57f9af90 100644 --- a/restlike/types.go +++ b/restlike/types.go @@ -1,7 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2022 Privategrity Corporation / -// / -// All rights reserved. / +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package restlike diff --git a/restlike/types_test.go b/restlike/types_test.go index 7b5b1a9d5b1bdaebc556ee4521379e48478019cb..554988050427aeb9f46f75f64f3b17b8c9b316d3 100644 --- a/restlike/types_test.go +++ b/restlike/types_test.go @@ -1,7 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2022 Privategrity Corporation / -// / -// All rights reserved. / +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package restlike diff --git a/single/cypher.go b/single/cypher.go index 6776c0cc673c5d768bf18935ea7c5f66e0ce0de4..ab5c1dce7d6ad0d08e4f5ee8a583f97bdf5b5c2a 100644 --- a/single/cypher.go +++ b/single/cypher.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package single diff --git a/single/cypher_test.go b/single/cypher_test.go index 13a47e354db61d1c96f913b6d10a7bf97f029744..113cc7e4c0f807e03317654a796e7dcd63bf0bca 100644 --- a/single/cypher_test.go +++ b/single/cypher_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package single diff --git a/single/interfaces.go b/single/interfaces.go index da28ef80a682b5d6d9ed9a5149972b269892d16b..8a6f965e8728b05b26a09c9f99fe8c248c19cc52 100644 --- a/single/interfaces.go +++ b/single/interfaces.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package single import ( @@ -37,7 +44,7 @@ type RequestCmix interface { GetMaxMessageLength() int Send(recipient *id.ID, fingerprint format.Fingerprint, service cMixMsg.Service, payload, mac []byte, - cmixParams cmix.CMIXParams) (id.Round, ephemeral.Id, error) + cmixParams cmix.CMIXParams) (rounds.Round, ephemeral.Id, error) GetInstance() *network.Instance } @@ -65,7 +72,7 @@ type Cmix interface { AddIdentity(id *id.ID, validUntil time.Time, persistent bool) Send(recipient *id.ID, fingerprint format.Fingerprint, service message.Service, payload, mac []byte, cmixParams cmix.CMIXParams) ( - id.Round, ephemeral.Id, error) + rounds.Round, ephemeral.Id, error) AddService(clientID *id.ID, newService message.Service, response message.Processor) DeleteService(clientID *id.ID, toDelete message.Service, diff --git a/single/listener.go b/single/listener.go index 01604b1e03839b8ecf23a0fbaa21501122d7d9f8..c13ca7a2a9a92bd0bb4af7e570bd66f3b9f94b1b 100644 --- a/single/listener.go +++ b/single/listener.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package single import ( diff --git a/single/listener_test.go b/single/listener_test.go index b7125f217866dbbefdd9e57757944a828da6f2ab..43006ae979f8a9801921566ebff95ac27ca73fec 100644 --- a/single/listener_test.go +++ b/single/listener_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package single @@ -255,7 +255,7 @@ func (m mockListenCmix) GetMaxMessageLength() int { func (m mockListenCmix) Send(recipient *id.ID, fingerprint format.Fingerprint, service cMixMsg.Service, payload, mac []byte, _ cmix.CMIXParams) ( - id.Round, ephemeral.Id, error) { + rounds.Round, ephemeral.Id, error) { msg := format.NewMessage(m.numPrimeBytes) msg.SetContents(payload) msg.SetMac(mac) @@ -270,7 +270,7 @@ func (m mockListenCmix) Send(recipient *id.ID, fingerprint format.Fingerprint, p.Process(msg, receptionID.EphemeralIdentity{}, rounds.Round{}) } - return 0, ephemeral.Id{}, nil + return rounds.Round{}, ephemeral.Id{}, nil } func (m mockListenCmix) GetInstance() *network.Instance { diff --git a/single/message/collator.go b/single/message/collator.go index 9e59eb9e95f00b5b4ec8b0550bf403523e130cec..c5e71cee465960abb7cf87e5d4b73504fc05a475 100644 --- a/single/message/collator.go +++ b/single/message/collator.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package message import ( diff --git a/single/message/collator_test.go b/single/message/collator_test.go index e45d169741e9b510164157cbaee2835ca53157de..cd18eb30eb60f7fb83c7e08cb129fc24905b4a50 100644 --- a/single/message/collator_test.go +++ b/single/message/collator_test.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package message import ( diff --git a/single/message/request.go b/single/message/request.go index f20c36a7fe025bd0ec0a8490a31f4e5bfa38b426..c77689aa8c3e34378f46b816d7c9c3210fbbb939 100644 --- a/single/message/request.go +++ b/single/message/request.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package message diff --git a/single/message/requestPart.go b/single/message/requestPart.go index 11d9f27b663cd15d500d7bf3321427c08f70c5d9..fedbed513dad6e220921f9dae34dd18535ebd356 100644 --- a/single/message/requestPart.go +++ b/single/message/requestPart.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package message diff --git a/single/message/requestPart_test.go b/single/message/requestPart_test.go index 8f3bbdf8e7cafee33432674fdaad8786dbfad5da..b285af119dd4dd762f90a9692649a097ff9de011 100644 --- a/single/message/requestPart_test.go +++ b/single/message/requestPart_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package message diff --git a/single/message/request_test.go b/single/message/request_test.go index 3a9120f11883fd19af2630e14cb8a0603a0a2aa0..b0be57400bd9f5bbd204d6ef1aba5d663bf208b9 100644 --- a/single/message/request_test.go +++ b/single/message/request_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package message diff --git a/single/message/responsePart.go b/single/message/responsePart.go index 02b80cb95fc96f2ab80be204e83ea8bbf0bb233d..03c5154dd904197e1aebcaa3f2bfaba346a41796 100644 --- a/single/message/responsePart.go +++ b/single/message/responsePart.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package message diff --git a/single/message/responsePart_test.go b/single/message/responsePart_test.go index 45c06773f113fb64f3e67db2cbeaba4d3bef6bb7..cab9cef67c45c872634d24f8a2bb0da2a1f1e11e 100644 --- a/single/message/responsePart_test.go +++ b/single/message/responsePart_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package message diff --git a/single/params.go b/single/params.go index 8895818449ba626ea69a112226a8afd182cdc5f3..928938384bc5a24c09d35b9c8a7911a62a65fd21 100644 --- a/single/params.go +++ b/single/params.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package single diff --git a/single/params_test.go b/single/params_test.go index 7d8224c6127366af542baecb2e755475311967a0..e9c4c49dcd22a2baf482263f97bdf09a2611820f 100644 --- a/single/params_test.go +++ b/single/params_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package single diff --git a/single/receivedRequest.go b/single/receivedRequest.go index b571ef1db60580ecc2f25c47543ce18dff77d226..cc05610088cca70c26539b5df5a0a090616b67cc 100644 --- a/single/receivedRequest.go +++ b/single/receivedRequest.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package single import ( @@ -97,11 +104,11 @@ func (r *Request) Respond(payload []byte, cMixParams cmix.CMIXParams, jww.DEBUG.Printf("[SU] Sent single-use response cMix message part "+ "%d of %d on round %d to %s (eph ID %d) (%s).", - i, len(parts), round, r.sender, ephID.Int64(), r.tag) - rounds[i] = round + i, len(parts), round.ID, r.sender, ephID.Int64(), r.tag) + rounds[i] = round.ID r.net.GetInstance().GetRoundEvents().AddRoundEventChan( - round, sendResults, timeout, states.COMPLETED, states.FAILED) + round.ID, sendResults, timeout, states.COMPLETED, states.FAILED) }(i, parts[i].Marshal()) } diff --git a/single/receivedRequest_test.go b/single/receivedRequest_test.go index fc7f64f4fc398a5ad3407690d40a269410e1d8c0..4d5762828038be1ba058cc7e59a4bc1dd8490fca 100644 --- a/single/receivedRequest_test.go +++ b/single/receivedRequest_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package single @@ -11,6 +11,7 @@ import ( "bytes" "gitlab.com/elixxir/client/cmix" cmixMsg "gitlab.com/elixxir/client/cmix/message" + "gitlab.com/elixxir/client/cmix/rounds" "gitlab.com/elixxir/client/single/message" "gitlab.com/elixxir/comms/network" "gitlab.com/elixxir/crypto/cyclic" @@ -186,14 +187,14 @@ func (m *mockRequestCmix) GetMaxMessageLength() int { func (m *mockRequestCmix) Send(_ *id.ID, fp format.Fingerprint, _ cmixMsg.Service, payload, mac []byte, _ cmix.CMIXParams) ( - id.Round, ephemeral.Id, error) { + rounds.Round, ephemeral.Id, error) { msg := format.NewMessage(m.numPrimeBytes) msg.SetMac(mac) msg.SetKeyFP(fp) msg.SetContents(payload) m.sendPayload <- msg - return 0, ephemeral.Id{}, nil + return rounds.Round{}, ephemeral.Id{}, nil } func (m *mockRequestCmix) GetInstance() *network.Instance { diff --git a/single/request.go b/single/request.go index 08e78c6effd39046fada90042fd04efd8472855a..16429e835021a6eb5b570ba7d60362ae5ba0dca6 100644 --- a/single/request.go +++ b/single/request.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package single import ( @@ -204,14 +211,14 @@ func TransmitRequest(recipient contact.Contact, tag string, payload []byte, jww.DEBUG.Printf("[SU] Sent single-use request cMix message part "+ "%d of %d on round %d to %s (eph ID %d) (%s).", - 0, len(parts)+1, rid, recipient.ID, ephID.Int64(), tag) + 0, len(parts)+1, rid.ID, recipient.ID, ephID.Int64(), tag) var wg sync.WaitGroup wg.Add(len(parts)) failed := uint32(0) roundIDs := make([]id.Round, len(parts)+1) - roundIDs[0] = rid + roundIDs[0] = rid.ID for i, part := range parts { go func(i int, part []byte) { defer wg.Done() @@ -224,9 +231,7 @@ func TransmitRequest(recipient contact.Contact, tag string, payload []byte, encryptedPayload := auth.Crypt(key, fp[:24], requestPart.Marshal()) mac := singleUse.MakeMAC(key, encryptedPayload) - var ephID ephemeral.Id - var err error - roundIDs[i], ephID, err = net.Send(recipient.ID, fp, + r, ephID, err := net.Send(recipient.ID, fp, cmixMsg.Service{}, encryptedPayload, mac, params.CmixParams) if err != nil { atomic.AddUint32(&failed, 1) @@ -235,6 +240,7 @@ func TransmitRequest(recipient contact.Contact, tag string, payload []byte, i, len(part)+1, recipient.ID, tag, err) return } + roundIDs[i] = r.ID jww.DEBUG.Printf("[SU] Sent single-use request cMix message part "+ "%d of %d on round %d to %s (eph ID %d) (%s).", i, @@ -256,7 +262,7 @@ func TransmitRequest(recipient contact.Contact, tag string, payload []byte, remainingTimeout := params.Timeout - netTime.Since(timeStart) go waitForTimeout(timeoutKillChan, wrapper, remainingTimeout) - return []id.Round{rid}, sendingID, nil + return []id.Round{rid.ID}, sendingID, nil } // generateDhKeys generates a new public key and DH key. diff --git a/single/requestPartProcessor.go b/single/requestPartProcessor.go index 8649237e539e6892c3e7fcdea9bc13c961b71fa4..34293282ed87f4ab323336ea364db3b169275b90 100644 --- a/single/requestPartProcessor.go +++ b/single/requestPartProcessor.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package single diff --git a/single/request_test.go b/single/request_test.go index 7e2847324e140fba5e36320c6a22c01650cfac04..4da6d4833e17eb15f2bfa428549739b6cb675bb8 100644 --- a/single/request_test.go +++ b/single/request_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package single diff --git a/single/responseProcessor.go b/single/responseProcessor.go index 942a8443cb32a3b9ea40d357f5e9b3277c59123a..4351900dc228ef09b3deb58e381ab4b920436aa3 100644 --- a/single/responseProcessor.go +++ b/single/responseProcessor.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package single import ( diff --git a/single/roundCollector.go b/single/roundCollector.go index 4d48b8e32c0f3e458457502481dd69344c510ee1..d1f7c5d84f59100ebeb4492e5b51421140690a19 100644 --- a/single/roundCollector.go +++ b/single/roundCollector.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package single diff --git a/single/utils_test.go b/single/utils_test.go index 66e7f0e6d670bfc0e19e8ef237d4e2277abb43ec..003d68e54cf6ca822918d07ca77985323ea8e70a 100644 --- a/single/utils_test.go +++ b/single/utils_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package single @@ -118,7 +118,7 @@ func (m *mockCmix) AddIdentity(*id.ID, time.Time, bool) {} func (m *mockCmix) Send(recipient *id.ID, fp format.Fingerprint, ms message.Service, payload, mac []byte, _ cmix.CMIXParams) ( - id.Round, ephemeral.Id, error) { + rounds.Round, ephemeral.Id, error) { msg := format.NewMessage(m.numPrimeBytes) msg.SetMac(mac) @@ -155,7 +155,7 @@ func (m *mockCmix) Send(recipient *id.ID, fp format.Fingerprint, }) } - return 0, ephemeral.Id{}, nil + return rounds.Round{}, ephemeral.Id{}, nil } func serviceKey(ms message.Service) string { diff --git a/stoppable/multi.go b/stoppable/multi.go index 60d1c8530300f2d52babf469d923627f236a6f1d..3ac77c7507fb058af1deac2b098121b16d3569b0 100644 --- a/stoppable/multi.go +++ b/stoppable/multi.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package stoppable @@ -61,10 +61,13 @@ func (m *Multi) GetStatus() Status { lowestStatus := Stopped m.mux.RLock() - for _, s := range m.stoppables { + for i := range m.stoppables { + s := m.stoppables[i] status := s.GetStatus() if status < lowestStatus { lowestStatus = status + jww.TRACE.Printf("Stoppable %s has status %s", + s.Name(), status.String()) } } @@ -73,6 +76,26 @@ func (m *Multi) GetStatus() Status { return lowestStatus } +// GetRunningProcesses returns the names of all running processes at the time +// of this call. Note that this list may change and is subject to race +// conditions if multiple threads are in the process of starting or stopping. +func (m *Multi) GetRunningProcesses() []string { + m.mux.RLock() + + runningProcesses := make([]string, 0) + for i := range m.stoppables { + s := m.stoppables[i] + status := s.GetStatus() + if status < Stopped { + runningProcesses = append(runningProcesses, s.Name()) + } + } + + m.mux.RUnlock() + + return runningProcesses +} + // IsRunning returns true if Stoppable is marked as running. func (m *Multi) IsRunning() bool { return m.GetStatus() == Running @@ -90,7 +113,7 @@ func (m *Multi) IsStopped() bool { // Close issues a close signal to all child stoppables and marks the status of // the Multi Stoppable as stopping. Returns an error if one or more child -// stoppables failed to close but it does not return their specific errors and +// stoppables failed to close, but it does not return their specific errors and // assumes they print them to the log. func (m *Multi) Close() error { var numErrors uint32 diff --git a/stoppable/multi_test.go b/stoppable/multi_test.go index 4a7eaf0873019d7ab9bd89e4f6aac2ba8f1661c9..af88627451dbd5ce17d19b2f789098d310f6f8bc 100644 --- a/stoppable/multi_test.go +++ b/stoppable/multi_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package stoppable diff --git a/stoppable/single.go b/stoppable/single.go index dfde7242ed83f0af975efa0656933b56d0b8145a..ea11ab42b586c3c1543509b5f575cda75f0cfca5 100644 --- a/stoppable/single.go +++ b/stoppable/single.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package stoppable diff --git a/stoppable/single_test.go b/stoppable/single_test.go index c93a1ebfcc1815b2d5c82e7f2e2dc43ff96a076c..3384396e4c7c80158aeb05ef3de4dc55a2fa720f 100644 --- a/stoppable/single_test.go +++ b/stoppable/single_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package stoppable diff --git a/stoppable/status.go b/stoppable/status.go index 1b306bd69a13394d8321c52b742ef5ecf82a83a9..089516de1f86fdcd656536b0654eec9bd26c13fd 100644 --- a/stoppable/status.go +++ b/stoppable/status.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package stoppable diff --git a/stoppable/status_test.go b/stoppable/status_test.go index c2f4bcd05f106e1f0bc6e6083a88096a3cdde1f7..5c44b45870ff1082d3d90125a4a57d9a9339e4e8 100644 --- a/stoppable/status_test.go +++ b/stoppable/status_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package stoppable diff --git a/stoppable/stoppable.go b/stoppable/stoppable.go index b5b072d1424feddf97cd029fa08d519ef2998c01..65df5267197e7ea761ee7d4a7c33b9ead2e16ba3 100644 --- a/stoppable/stoppable.go +++ b/stoppable/stoppable.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package stoppable diff --git a/stoppable/stoppable_test.go b/stoppable/stoppable_test.go index 0f070317aedef9fca29a0b66d023b4e7d151517f..1c5098cf2713979f27d24c53ca4385ac8852564d 100644 --- a/stoppable/stoppable_test.go +++ b/stoppable/stoppable_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package stoppable diff --git a/storage/clientVersion/store.go b/storage/clientVersion/store.go index 5b6e951ef6c0bf5b86049b636606fa015f9d4062..f1ae712d873b3d73004826c231aec0b5fa9fc341 100644 --- a/storage/clientVersion/store.go +++ b/storage/clientVersion/store.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package clientVersion @@ -113,5 +113,5 @@ func (s *Store) save() error { Data: []byte(s.version.String()), } - return s.kv.Set(storeKey, storeVersion, &obj) + return s.kv.Set(storeKey, &obj) } diff --git a/storage/clientVersion/store_test.go b/storage/clientVersion/store_test.go index 0e8cae86f2822b5ea9d3cb09e1bc71cd0c682884..9da1b75ef38491e6405e9c86f9cdf4a77cf48755 100644 --- a/storage/clientVersion/store_test.go +++ b/storage/clientVersion/store_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package clientVersion @@ -71,7 +71,7 @@ func TestLoadStore_ParseVersionError(t *testing.T) { Data: []byte("invalid version"), } - err := kv.Prefix(prefix).Set(storeKey, storeVersion, &obj) + err := kv.Prefix(prefix).Set(storeKey, &obj) if err != nil { t.Fatalf("Failed to save Store: %+v", err) } diff --git a/storage/ndf.go b/storage/ndf.go index 46df6a07161880e15fb75107c692fddaadf45a05..7bac8db591a15c2a76a2428e8ed47f176dfe637f 100644 --- a/storage/ndf.go +++ b/storage/ndf.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package storage diff --git a/storage/ndf_test.go b/storage/ndf_test.go index 4d48ab2d28d7330511f8474a9a335ef023505eb6..d628f0a19534b50777390c7f174c4e43c4226a39 100644 --- a/storage/ndf_test.go +++ b/storage/ndf_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package storage diff --git a/storage/regCode.go b/storage/regCode.go index 2a7d15f34895e0e7d1a7581c18e5a5e50033de7c..83647179c4237d3e09607af6e4bcc89f42181ab3 100644 --- a/storage/regCode.go +++ b/storage/regCode.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package storage diff --git a/storage/regStatus.go b/storage/regStatus.go index 90b355e75a3b17cdf90e15f413b816f83d47d279..5ff8cdd4d35a1b9be90a3c07653e62cf07d63dbd 100644 --- a/storage/regStatus.go +++ b/storage/regStatus.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package storage diff --git a/storage/session.go b/storage/session.go index d181f07428b1178b83a7b0121c980882c79d1c37..e982415a1ed6523a3ad99d6a4711c6a4a31fe514 100644 --- a/storage/session.go +++ b/storage/session.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// // Session object definition @@ -195,9 +195,10 @@ func (s *session) Get(key string) (*versioned.Object, error) { return s.kv.Get(key, currentSessionVersion) } -// Set a value in the session +// Set a value in the session. If you wish to maintain versioning, +// the [versioned.Object]'s Version field must be set. func (s *session) Set(key string, object *versioned.Object) error { - return s.kv.Set(key, currentSessionVersion, object) + return s.kv.Set(key, object) } // Delete a value in the session diff --git a/storage/session_test.go b/storage/session_test.go index 27a09e603ab719071a8265e4ae96a03a92517c7a..fd72d302adfc418602a1480245547bb8262a862d 100644 --- a/storage/session_test.go +++ b/storage/session_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package storage diff --git a/storage/user/cryptographic.go b/storage/user/cryptographic.go index 8c245fc70ac257dc9eef14d9848be007c7831343..54fc60f864c7c602c676a3de38c647777645c895 100644 --- a/storage/user/cryptographic.go +++ b/storage/user/cryptographic.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package user @@ -216,8 +216,7 @@ func (ci *CryptographicIdentity) save(kv *versioned.KV) error { Data: enc, } - return kv.Set(cryptographicIdentityKey, - currentCryptographicIdentityVersion, obj) + return kv.Set(cryptographicIdentityKey, obj) } func (ci *CryptographicIdentity) GetTransmissionID() *id.ID { diff --git a/storage/user/cryptographic_test.go b/storage/user/cryptographic_test.go index 0b9f92d9525600ad66c7746dbda12fa06fc6a318..7fb9f6c3b9e4f3c770db0b7fc6cecc95cb25afcd 100644 --- a/storage/user/cryptographic_test.go +++ b/storage/user/cryptographic_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package user diff --git a/storage/user/info.go b/storage/user/info.go index fc272cb0fe134b767e399b4bb9fca2a8cd3411e4..a16b4b754a625c386f0dc569f911188b22e742a7 100644 --- a/storage/user/info.go +++ b/storage/user/info.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package user diff --git a/storage/user/registation.go b/storage/user/registation.go index 4da19b4cd0faf8e83fe22ad2e177afb8d8109897..aa144ef7f957a54205a95910ff272a82f9a46a36 100644 --- a/storage/user/registation.go +++ b/storage/user/registation.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package user @@ -95,8 +95,7 @@ func (u *User) SetTransmissionRegistrationValidationSignature(b []byte) { Data: b, } - err := u.kv.Set(transmissionRegValidationSigKey, - currentRegValidationSigVersion, obj) + err := u.kv.Set(transmissionRegValidationSigKey, obj) if err != nil { jww.FATAL.Panicf("Failed to store the transmission Identity Validation "+ "Signature: %s", err) @@ -122,8 +121,7 @@ func (u *User) SetReceptionRegistrationValidationSignature(b []byte) { Data: b, } - err := u.kv.Set(receptionRegValidationSigKey, - currentRegValidationSigVersion, obj) + err := u.kv.Set(receptionRegValidationSigKey, obj) if err != nil { jww.FATAL.Panicf("Failed to store the reception Identity Validation "+ "Signature: %s", err) @@ -148,13 +146,12 @@ func (u *User) SetRegistrationTimestamp(tsNano int64) { binary.BigEndian.PutUint64(tsBytes, uint64(tsNano)) obj := &versioned.Object{ - Version: currentRegValidationSigVersion, + Version: registrationTimestampVersion, Timestamp: netTime.Now(), Data: tsBytes, } - err := u.kv.Set(registrationTimestampKey, - registrationTimestampVersion, obj) + err := u.kv.Set(registrationTimestampKey, obj) if err != nil { jww.FATAL.Panicf("Failed to store the reception timestamp: %s", err) } diff --git a/storage/user/registation_test.go b/storage/user/registation_test.go index 346e662758223a755e13c5e19186002ae6b9ec6f..4ada8cf0a9ce106956f36428c416d146853b5dbb 100644 --- a/storage/user/registation_test.go +++ b/storage/user/registation_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package user @@ -137,7 +137,7 @@ func TestUser_loadRegistrationValidationSignature(t *testing.T) { sig := []byte("transmissionsignature") err = kv.Set(transmissionRegValidationSigKey, - currentRegValidationSigVersion, &versioned.Object{ + &versioned.Object{ Version: currentRegValidationSigVersion, Timestamp: netTime.Now(), Data: sig, @@ -153,7 +153,7 @@ func TestUser_loadRegistrationValidationSignature(t *testing.T) { sig = []byte("receptionsignature") err = kv.Set(receptionRegValidationSigKey, - currentRegValidationSigVersion, &versioned.Object{ + &versioned.Object{ Version: currentRegValidationSigVersion, Timestamp: netTime.Now(), Data: sig, @@ -252,12 +252,12 @@ func TestUser_loadRegistrationTimestamp(t *testing.T) { data := make([]byte, 8) binary.BigEndian.PutUint64(data, uint64(testTime.UnixNano())) vo := &versioned.Object{ - Version: currentRegValidationSigVersion, + Version: registrationTimestampVersion, Timestamp: netTime.Now(), Data: data, } - err = kv.Set(registrationTimestampKey, - registrationTimestampVersion, vo) + + err = kv.Set(registrationTimestampKey, vo) if err != nil { t.Errorf("Failed to set reg validation sig key in kv store: %+v", err) } diff --git a/storage/user/user.go b/storage/user/user.go index 5b84321a97cc169df474ab2ebd602bfb2769c0b1..b2db39a4e53f3dd15a5d457654b28327a41be613 100644 --- a/storage/user/user.go +++ b/storage/user/user.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package user diff --git a/storage/user/user_test.go b/storage/user/user_test.go index 9198e48f607e3c25d79d74242f7607819a83efd1..b55de9534c4eeeaac3369fa6a25d2e3b29a12bcf 100644 --- a/storage/user/user_test.go +++ b/storage/user/user_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package user diff --git a/storage/user/username.go b/storage/user/username.go index c36e0eba99883f5d735d4aeb2e557848f8ff4180..7a0b939da475473602480d2390ecabcebaefd2c0 100644 --- a/storage/user/username.go +++ b/storage/user/username.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package user @@ -39,7 +39,7 @@ func (u *User) SetUsername(username string) error { Data: []byte(username), } - err := u.kv.Set(usernameKey, currentUsernameVersion, obj) + err := u.kv.Set(usernameKey, obj) if err != nil { jww.FATAL.Panicf("Failed to store the username: %s", err) } diff --git a/storage/user/username_test.go b/storage/user/username_test.go index a52b20ac003d692c38ba632299354bb8ce698faf..91f8b64a30db6862e98888e7e9dd25ecfcb69404 100644 --- a/storage/user/username_test.go +++ b/storage/user/username_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package user @@ -120,7 +120,7 @@ func TestUser_loadUsername(t *testing.T) { u1 := "zezima" - err = u.kv.Set(usernameKey, currentUsernameVersion, &versioned.Object{ + err = u.kv.Set(usernameKey, &versioned.Object{ Version: currentUsernameVersion, Timestamp: netTime.Now(), Data: []byte(u1), diff --git a/storage/utility/NDF.go b/storage/utility/NDF.go index e4e6281b26ed92c6466a8afaa9cbec7375ed5107..c01485f26856e0ad111dab4614992045d7d585e4 100644 --- a/storage/utility/NDF.go +++ b/storage/utility/NDF.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package utility @@ -43,5 +43,5 @@ func SaveNDF(kv *versioned.KV, key string, ndf *ndf.NetworkDefinition) error { Data: marshaled, } - return kv.Set(key, currentNDFVersion, &obj) + return kv.Set(key, &obj) } diff --git a/storage/utility/blockStore.go b/storage/utility/blockStore.go index 053e015dd2171e41755afeb6c0e9674d4a2daf78..d81e0fbf363d500d051638c866ade4cbbd777d2f 100644 --- a/storage/utility/blockStore.go +++ b/storage/utility/blockStore.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package utility import ( @@ -155,7 +162,7 @@ func (bs *BlockStore) saveBlock() error { } // Save to storage - err = bs.kv.Set(bs.getKey(bs.lastSaved), blockVersion, &obj) + err = bs.kv.Set(bs.getKey(bs.lastSaved), &obj) if err != nil { return errors.Errorf(bKvSaveErr, bs.lastSaved, err) } @@ -214,7 +221,7 @@ func (bs *BlockStore) save() error { } // Save to storage - err := bs.kv.Set(blockStoreKey, blockStoreVersion, &obj) + err := bs.kv.Set(blockStoreKey, &obj) if err != nil { return errors.Errorf(bsKvSaveErr, err) } diff --git a/storage/utility/blockStore_test.go b/storage/utility/blockStore_test.go index 3f13417858d38cb5d7b94667f17c0d17535bf29b..217089bbd0916cf26f3de65468c0ab05dacd20fc 100644 --- a/storage/utility/blockStore_test.go +++ b/storage/utility/blockStore_test.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package utility import ( @@ -208,7 +215,7 @@ func TestBlockStore_loadBlock_UnmarshalError(t *testing.T) { } // Save to storage - err := bs.kv.Set(bs.getKey(bs.lastSaved), blockVersion, &obj) + err := bs.kv.Set(bs.getKey(bs.lastSaved), &obj) if err != nil { t.Errorf("Failed to save data to KV: %+v", err) } @@ -338,7 +345,7 @@ func TestBlockStore_load_UnmarshalError(t *testing.T) { } // Save to storage - err := kv.Set(blockStoreKey, blockStoreVersion, &obj) + err := kv.Set(blockStoreKey, &obj) if err != nil { t.Fatalf("failed to save object to storage: %+v", err) } diff --git a/storage/utility/bucket.go b/storage/utility/bucket.go index 46b3da9a9d7733b0ce2abb5812a451ea9ae8e419..fd3061e8f5f311f55a0a7e47648c46fa9114de37 100644 --- a/storage/utility/bucket.go +++ b/storage/utility/bucket.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package utility @@ -68,7 +68,7 @@ func (s *BucketStore) save(inBucket uint32, timestamp int64) { Data: data, } - err = s.kv.Set(bucketStoreKey, bucketStoreVersion, &obj) + err = s.kv.Set(bucketStoreKey, &obj) if err != nil { jww.ERROR.Printf("Failed to store %s bucket data: %v", diff --git a/storage/utility/bucketParams.go b/storage/utility/bucketParams.go index 756666fa353628fabbb5dee9e4077510cf6666a9..90708af650febc99ab6f6e18f7bb58a51a995ba7 100644 --- a/storage/utility/bucketParams.go +++ b/storage/utility/bucketParams.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package utility @@ -99,7 +99,7 @@ func (s *BucketParamStore) save() error { } // Store object into storage - return s.kv.Set(bucketParamsKey, bucketParamsVersion, object) + return s.kv.Set(bucketParamsKey, object) } // load extracts the bucket params from store and loads it into the diff --git a/storage/utility/bucketParams_test.go b/storage/utility/bucketParams_test.go index d908ac99ad964b35a345fbfde6af92c642b072c4..dc961eb5f2ff719ad2580fef95e53f0319f1802d 100644 --- a/storage/utility/bucketParams_test.go +++ b/storage/utility/bucketParams_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package utility diff --git a/storage/utility/contact.go b/storage/utility/contact.go index 2050efd8a2664a41bb34c557c807f73d94879a57..98268e686b51cd30f54ad017682f542998ebc8a1 100644 --- a/storage/utility/contact.go +++ b/storage/utility/contact.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package utility @@ -35,7 +35,7 @@ func StoreContact(kv *versioned.KV, c contact.Contact) error { Data: c.Marshal(), } - return kv.Set(makeContactKey(c.ID), currentContactVersion, &obj) + return kv.Set(makeContactKey(c.ID), &obj) } // LoadContact reads a contact from a versioned.KV vie their contact ID. diff --git a/storage/utility/dh.go b/storage/utility/dh.go index 6295e446d3563127c4c1262733eb3abf8ac8b91e..de697130ae7bf68f41dc88567346992cc181d164 100644 --- a/storage/utility/dh.go +++ b/storage/utility/dh.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package utility @@ -29,7 +29,7 @@ func StoreCyclicKey(kv *versioned.KV, cy *cyclic.Int, key string) error { Data: data, } - return kv.Set(key, currentCyclicVersion, &obj) + return kv.Set(key, &obj) } func LoadCyclicKey(kv *versioned.KV, key string) (*cyclic.Int, error) { diff --git a/storage/utility/dh_test.go b/storage/utility/dh_test.go index bea2f2448d14a80c3319871f78edf7f1edad90e9..4f25a4768c1dd3e1fa1ed7bc0e52f010ad0e936e 100644 --- a/storage/utility/dh_test.go +++ b/storage/utility/dh_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package utility diff --git a/storage/utility/group.go b/storage/utility/group.go index 531a31ae4beb24a31cc1aa1ee4d13889e32436b3..769e0fc0fa682e1dafac61fe24fe69c6f16bd930 100644 --- a/storage/utility/group.go +++ b/storage/utility/group.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package utility @@ -29,7 +29,7 @@ func StoreGroup(kv *versioned.KV, grp *cyclic.Group, key string) error { Data: data, } - return kv.Set(key, currentGroupVersion, &obj) + return kv.Set(key, &obj) } func LoadGroup(kv *versioned.KV, key string) (*cyclic.Group, error) { diff --git a/storage/utility/group_test.go b/storage/utility/group_test.go index 02e6504be687d1e7b331ad63d6c139d9d6963f22..09542e392ed40bb426d055da7c6af2854077fb28 100644 --- a/storage/utility/group_test.go +++ b/storage/utility/group_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package utility diff --git a/storage/utility/id.go b/storage/utility/id.go index 08472b53e36da3d4912886ca3b19931d0120f78d..6046627b374ebd6f9093452c72cc0cade334cfe5 100644 --- a/storage/utility/id.go +++ b/storage/utility/id.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package utility import ( @@ -22,7 +29,7 @@ func StoreID(kv *versioned.KV, sid *id.ID, key string) error { Data: data, } - return kv.Set(key, currentIDVersion, &obj) + return kv.Set(key, &obj) } func LoadID(kv *versioned.KV, key string) (*id.ID, error) { diff --git a/storage/utility/knownRounds.go b/storage/utility/knownRounds.go index 0f8057ce6a21be2023a4b6bff4198e157acfcc3e..d75d094c1e99e7e73781abf3eae89e799a30d8d1 100644 --- a/storage/utility/knownRounds.go +++ b/storage/utility/knownRounds.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package utility diff --git a/storage/utility/knownRounds_test.go b/storage/utility/knownRounds_test.go index e7a3a25f8ec33b7d11886b457863e90f48819109..c5e9a565bdcafdd6c728cf3b0186cc4432760674 100644 --- a/storage/utility/knownRounds_test.go +++ b/storage/utility/knownRounds_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package utility diff --git a/storage/utility/messageBuffer.go b/storage/utility/messageBuffer.go index 4e5a5d32fb1f6695965cd97d1d28a64512eb0ba0..15c3296673f17bcf7a08869e6fef305dc5219031 100644 --- a/storage/utility/messageBuffer.go +++ b/storage/utility/messageBuffer.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package utility @@ -146,7 +146,7 @@ func (mb *MessageBuffer) save() error { } // Save versioned object - return mb.kv.Set(mb.key, CurrentMessageBufferVersion, &obj) + return mb.kv.Set(mb.key, &obj) } // getMessageList returns a list of all message hashes stored in messages and diff --git a/storage/utility/messageBuffer_test.go b/storage/utility/messageBuffer_test.go index fc7f39a7c8fba2acdb6f8eb2efe395afcc7ce814..065c1d6cf099996b4638a88dc7eda180a3bb625c 100644 --- a/storage/utility/messageBuffer_test.go +++ b/storage/utility/messageBuffer_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package utility diff --git a/storage/utility/multiStateVector.go b/storage/utility/multiStateVector.go index caeeb347f0593852be4ea3bcbdc4c0c2fb558ced..e12b6caff9fbbc262ee679df1399960495fdbffa 100644 --- a/storage/utility/multiStateVector.go +++ b/storage/utility/multiStateVector.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package utility @@ -502,7 +502,7 @@ func (msv *MultiStateVector) save() error { Data: data, } - return msv.kv.Set(msv.key, multiStateVectorVersion, obj) + return msv.kv.Set(msv.key, obj) } // Delete removes the MultiStateVector from storage. diff --git a/storage/utility/multiStateVector_test.go b/storage/utility/multiStateVector_test.go index 38085804b5bf11adbf35e21d240863b84b2a2a0c..e198da67087e19b070dcc235a407d5b97345a607 100644 --- a/storage/utility/multiStateVector_test.go +++ b/storage/utility/multiStateVector_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package utility @@ -890,7 +890,7 @@ func TestLoadMultiStateVector_UnmarshalError(t *testing.T) { expectedErr := strings.Split(loadUnmarshalMsvErr, "%")[0] // Save invalid data to storage - err := kv.Set(makeMultiStateVectorKey(key), multiStateVectorVersion, + err := kv.Set(makeMultiStateVectorKey(key), &versioned.Object{ Version: multiStateVectorVersion, Timestamp: netTime.Now(), diff --git a/storage/utility/sidh.go b/storage/utility/sidh.go index d8082d872944fa2a24e9f04142e53aff8944f0e7..03599f79dd58d1daef38f3a062c7541b932b8477 100644 --- a/storage/utility/sidh.go +++ b/storage/utility/sidh.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package utility @@ -93,7 +93,7 @@ func StoreSIDHPublicKey(kv *versioned.KV, sidH *sidh.PublicKey, key string) erro Data: sidHBytes, } - return kv.Set(key, currentSIDHPubKeyVersion, &obj) + return kv.Set(key, &obj) } // LoadSIDHPubKeyA loads a public key from storage. @@ -138,7 +138,7 @@ func StoreSIDHPrivateKey(kv *versioned.KV, sidH *sidh.PrivateKey, key string) er Data: sidHBytes, } - return kv.Set(key, currentSIDHPrivKeyVersion, &obj) + return kv.Set(key, &obj) } // LoadSIDHPrivateKeyA loads a public key from storage. diff --git a/storage/utility/sidh_test.go b/storage/utility/sidh_test.go index d547011d3ef6860e685204ce013dd437675215e5..b20b1310aeea6fe3c3b3eeb16d3259bb748a43cc 100644 --- a/storage/utility/sidh_test.go +++ b/storage/utility/sidh_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package utility diff --git a/storage/utility/stateVector.go b/storage/utility/stateVector.go index 2ed89e2faef5fe3ebcc591e0ca0c933bcd71faf3..f3ed4da6d4612365ea5b564ef5742976a1368626 100644 --- a/storage/utility/stateVector.go +++ b/storage/utility/stateVector.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package utility @@ -388,7 +388,7 @@ func (sv *StateVector) save() error { Data: data, } - return sv.kv.Set(sv.key, currentStateVectorVersion, &obj) + return sv.kv.Set(sv.key, &obj) } // Delete remove the StateVector from storage. diff --git a/storage/utility/stateVector_test.go b/storage/utility/stateVector_test.go index 4b2188b25c6dd41689aea9cbe003ea0ba8443b7a..586f31dc3492f06a56198c683c4a624140e6d220 100644 --- a/storage/utility/stateVector_test.go +++ b/storage/utility/stateVector_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package utility @@ -563,7 +563,7 @@ func TestLoadStateVector_GetError(t *testing.T) { expectedErr := "object not found" _, err := LoadStateVector(kv, key) - if err == nil || err.Error() != expectedErr { + if err == nil || kv.Exists(err) { t.Fatalf("LoadStateVector did not return the expected error when no "+ "object exists in storage.\nexpected: %s\nreceived: %+v", expectedErr, err) @@ -582,7 +582,7 @@ func TestLoadStateVector_UnmarshalError(t *testing.T) { Timestamp: netTime.Now(), Data: []byte("invalidStateVector"), } - err := kv.Set(makeStateVectorKey(key), currentStateVectorVersion, &obj) + err := kv.Set(makeStateVectorKey(key), &obj) if err != nil { t.Errorf("Failed to save invalid StateVector to storage: %+v", err) } diff --git a/storage/utils_test.go b/storage/utils_test.go index 6e9cc93343c47ea97587b76bb0951bc9e3e8ac94..fbabefb2e1325b6673f72feac256089704289732 100644 --- a/storage/utils_test.go +++ b/storage/utils_test.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package storage import ( diff --git a/storage/versioned/kv.go b/storage/versioned/kv.go index 2b8b7ae2129d5a67fdf576297a4318e229c91ff8..4b0179fa3e8cc764263a3d6f305bfafa6a5e9522 100644 --- a/storage/versioned/kv.go +++ b/storage/versioned/kv.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package versioned @@ -131,8 +131,10 @@ func (v *KV) Delete(key string, version uint64) error { // Set upserts new data into the storage // When calling this, you are responsible for prefixing the key with the correct // type optionally unique id! Call MakeKeyWithPrefix() to do so. -func (v *KV) Set(key string, version uint64, object *Object) error { - key = v.makeKey(key, version) +// The [Object] should contain the versioning if you are maintaining such +// a functionality. +func (v *KV) Set(key string, object *Object) error { + key = v.makeKey(key, object.Version) jww.TRACE.Printf("Set %p with key %v", v.r.data, key) return v.r.data.Set(key, object) } @@ -164,3 +166,9 @@ func (v *KV) GetFullKey(key string, version uint64) string { func (v *KV) makeKey(key string, version uint64) string { return fmt.Sprintf("%s%s_%d", v.prefix, key, version) } + +// Exists returns false if the error indicates the element doesn't +// exist. +func (v *KV) Exists(err error) bool { + return ekv.Exists(err) +} diff --git a/storage/versioned/kv_test.go b/storage/versioned/kv_test.go index cd34474ed2fe18942286a88db17ccce3f71295c1..deb7eacf20a7d67dd274ee6e59337a6cb9610fb4 100644 --- a/storage/versioned/kv_test.go +++ b/storage/versioned/kv_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package versioned @@ -188,7 +188,7 @@ func TestVersionedKV_Set(t *testing.T) { Timestamp: netTime.Now(), Data: []byte("not upgraded"), } - err := vkv.Set("test", originalVersion, &original) + err := vkv.Set("test", &original) if err != nil { t.Fatal(err) } diff --git a/storage/versioned/object.go b/storage/versioned/object.go index 8cdec88c27c59dc99284089996fbcd2e2c6394a0..bd7d43730571aa743a907f6419dcdca7b0d9f2f5 100644 --- a/storage/versioned/object.go +++ b/storage/versioned/object.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package versioned diff --git a/storage/versioned/object_test.go b/storage/versioned/object_test.go index 4ba12575a327269b2094ff7c73d90fa2a7873f2c..94ac4ec41123609591ff84fc2195d660653e4da4 100644 --- a/storage/versioned/object_test.go +++ b/storage/versioned/object_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package versioned diff --git a/ud/addFact.go b/ud/addFact.go index 719e7d137ab1f9c3e5ce4d414c9db08876d668a4..069a4f4251800b92d12751a45cdaa24dbd73008b 100644 --- a/ud/addFact.go +++ b/ud/addFact.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package ud import ( @@ -40,7 +47,7 @@ func (m *Manager) addFact(inFact fact.Fact, myId *id.ID, fHash := factID.Fingerprint(f) // Sign our inFact for putting into the request - privKey, err := m.user.GetReceptionIdentity().GetRSAPrivatePem() + privKey, err := m.user.GetReceptionIdentity().GetRSAPrivateKey() if err != nil { return "", err } diff --git a/ud/addFact_test.go b/ud/addFact_test.go index 1a1a38cdcd75f6b416786f76742bfe92ca990d64..7f5bc06f5e2b63f056a86b7d1e120b4d50860a90 100644 --- a/ud/addFact_test.go +++ b/ud/addFact_test.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package ud import ( diff --git a/ud/channelIDTracking.go b/ud/channelIDTracking.go new file mode 100644 index 0000000000000000000000000000000000000000..e40f4a1e33cbfb5519f7f0bc4964df04c9cd01b8 --- /dev/null +++ b/ud/channelIDTracking.go @@ -0,0 +1,380 @@ +package ud + +import ( + "crypto/ed25519" + "encoding/json" + "errors" + "gitlab.com/xx_network/primitives/netTime" + "sync" + "time" + + jww "github.com/spf13/jwalterweatherman" + + "gitlab.com/elixxir/client/channels" + "gitlab.com/elixxir/client/stoppable" + "gitlab.com/elixxir/client/storage/versioned" + "gitlab.com/elixxir/client/xxdk" + "gitlab.com/elixxir/comms/mixmessages" + "gitlab.com/elixxir/crypto/channel" + "gitlab.com/elixxir/crypto/fastRNG" + "gitlab.com/xx_network/comms/connect" +) + +const ( + registrationDiskKey = "registrationDiskKey" + registrationDiskVersion = 0 + graceDuration = time.Hour +) + +var ErrChannelLeaseSignature = errors.New("failure to validate lease signature") + +// loadRegistrationDisk loads a registrationDisk from the kv +// and returns the registrationDisk. +func loadRegistrationDisk(kv *versioned.KV) (registrationDisk, error) { + obj, err := kv.Get(registrationDiskKey, registrationDiskVersion) + if err != nil { + return registrationDisk{}, err + } + return UnmarshallRegistrationDisk(obj.Data) +} + +// saveRegistrationDisk saves the given saveRegistrationDisk to +// the given kv. +func saveRegistrationDisk(kv *versioned.KV, reg registrationDisk) error { + regBytes, err := reg.Marshall() + if err != nil { + return err + } + obj := versioned.Object{ + Version: registrationDiskVersion, + Timestamp: netTime.Now(), + Data: regBytes, + } + return kv.Set(registrationDiskKey, &obj) +} + +// registrationDisk is used to encapsulate the channel user's key pair, +// lease and lease signature. +type registrationDisk struct { + rwmutex sync.RWMutex + + Registered bool + PublicKey ed25519.PublicKey + PrivateKey ed25519.PrivateKey + Lease int64 + Signature []byte +} + +// newRegistrationDisk creates a new newRegistrationDisk. +func newRegistrationDisk(publicKey ed25519.PublicKey, privateKey ed25519.PrivateKey, + lease time.Time, signature []byte) registrationDisk { + return registrationDisk{ + Lease: lease.UnixNano(), + PublicKey: publicKey, + PrivateKey: privateKey, + Signature: signature, + } +} + +func (r registrationDisk) IsRegistered() bool { + r.rwmutex.RLock() + defer r.rwmutex.RUnlock() + + return r.Registered +} + +// Update updates the registrationDisk that is currently +// stored on the kv with a new lease and lease signature. +func (r registrationDisk) Update(lease int64, signature []byte) { + r.rwmutex.Lock() + defer r.rwmutex.Unlock() + + r.Registered = true + r.Lease = lease + r.Signature = signature +} + +// Marshall marshalls the registrationDisk. +func (r registrationDisk) Marshall() ([]byte, error) { + r.rwmutex.RLock() + defer r.rwmutex.RUnlock() + + return json.Marshal(&r) +} + +// UnmarshallRegistrationDisk unmarshalls a registrationDisk +func UnmarshallRegistrationDisk(data []byte) (registrationDisk, error) { + var r registrationDisk + err := json.Unmarshal(data, &r) + if err != nil { + return registrationDisk{}, err + } + return r, nil +} + +// GetLease returns the current registrationDisk lease. +func (r registrationDisk) GetLease() time.Time { + r.rwmutex.RLock() + defer r.rwmutex.RUnlock() + + return time.Unix(0, r.Lease) +} + +// GetPublicKey returns the current public key. +func (r registrationDisk) GetPublicKey() ed25519.PublicKey { + r.rwmutex.RLock() + defer r.rwmutex.RUnlock() + + pubkey := make([]byte, ed25519.PublicKeySize) + copy(pubkey, r.PublicKey) + return pubkey +} + +// GetPrivateKey returns the current private key. +func (r registrationDisk) getPrivateKey() ed25519.PrivateKey { + r.rwmutex.RLock() + defer r.rwmutex.RUnlock() + + return r.PrivateKey +} + +// GetLeaseSignature returns the currentl signature and lease time. +func (r registrationDisk) GetLeaseSignature() ([]byte, time.Time) { + r.rwmutex.RLock() + defer r.rwmutex.RUnlock() + + return r.Signature, time.Unix(0, r.Lease) +} + +// clientIDTracker encapsulates the client channel lease and the +// repetitive scheduling of new lease registrations when the +// current lease expires. +type clientIDTracker struct { + kv *versioned.KV + + username string + + registrationDisk *registrationDisk + receptionIdentity *xxdk.ReceptionIdentity + + rngSource *fastRNG.StreamGenerator + + host *connect.Host + comms channelLeaseComms + udPubKey ed25519.PublicKey +} + +// clientIDTracker implements the NameService interface. +var _ channels.NameService = (*clientIDTracker)(nil) + +// newclientIDTracker creates a new clientIDTracker. +func newclientIDTracker(comms channelLeaseComms, host *connect.Host, username string, kv *versioned.KV, + receptionIdentity xxdk.ReceptionIdentity, udPubKey ed25519.PublicKey, rngSource *fastRNG.StreamGenerator) *clientIDTracker { + + reg, err := loadRegistrationDisk(kv) + if !kv.Exists(err) { + rng := rngSource.GetStream() + defer rng.Close() + + publicKey, privateKey, err := ed25519.GenerateKey(rng) + if err != nil { + jww.FATAL.Panic(err) + } + + reg = registrationDisk{ + PublicKey: publicKey, + PrivateKey: privateKey, + Lease: 0, + } + err = saveRegistrationDisk(kv, reg) + if err != nil { + jww.FATAL.Panic(err) + } + } else if err != nil { + jww.FATAL.Panic(err) + } + + c := &clientIDTracker{ + kv: kv, + rngSource: rngSource, + registrationDisk: ®, + receptionIdentity: &receptionIdentity, + username: username, + comms: comms, + host: host, + udPubKey: udPubKey, + } + + if !reg.IsRegistered() { + err = c.register() + if err != nil { + jww.FATAL.Panic(err) + } + } + + return c +} + +// Start starts the registration worker. +func (c *clientIDTracker) Start() (stoppable.Stoppable, error) { + stopper := stoppable.NewSingle("ud.ClientIDTracker") + go c.registrationWorker(stopper) + return stopper, nil +} + +func pow(base, exponent int) int { + if exponent == 0 { + return 1 + } + result := base + for i := 2; i <= exponent; i++ { + result *= base + } + return result +} + +// registrationWorker is meant to run in it's own goroutine +// periodically registering, getting a new lease. +func (c *clientIDTracker) registrationWorker(stopper *stoppable.Single) { + // start backoff at 32 seconds + base := 2 + exponent := 5 + waitTime := time.Second + maxBackoff := 300 + for { + if netTime.Now().After(c.registrationDisk.GetLease().Add(-graceDuration)) { + err := c.register() + if err != nil { + backoffSeconds := pow(base, exponent) + if backoffSeconds > maxBackoff { + backoffSeconds = maxBackoff + } else { + exponent += 1 + } + waitTime = time.Second * time.Duration(backoffSeconds) + } else { + waitTime = time.Second + } + } + + select { + case <-stopper.Quit(): + return + case <-time.After(c.registrationDisk.GetLease().Add(-graceDuration).Sub(netTime.Now())): + } + + // Avoid spamming the server in the event that it's service is down. + select { + case <-stopper.Quit(): + return + case <-time.After(waitTime): + } + } +} + +// GetUsername returns the username. +func (c *clientIDTracker) GetUsername() string { + return c.username +} + +// GetChannelValidationSignature returns the validation +// signature and the time it was signed. +func (c *clientIDTracker) GetChannelValidationSignature() ([]byte, time.Time) { + return c.registrationDisk.GetLeaseSignature() +} + +// GetChannelPubkey returns the user's public key. +func (c *clientIDTracker) GetChannelPubkey() ed25519.PublicKey { + return c.registrationDisk.GetPublicKey() +} + +// SignChannelMessage returns the signature of the given +// message. The ed25519 private key stored in the registrationDisk on the +// kv is used for signing. +func (c *clientIDTracker) SignChannelMessage(message []byte) ([]byte, error) { + privateKey := c.registrationDisk.getPrivateKey() + return ed25519.Sign(privateKey, message), nil +} + +// ValidateoChannelMessage +func (c *clientIDTracker) ValidateChannelMessage(username string, lease time.Time, pubKey ed25519.PublicKey, authorIDSignature []byte) bool { + return channel.VerifyChannelLease(authorIDSignature, pubKey, username, lease, c.udPubKey) +} + +// register causes a request for a new channel lease to be sent to +// the user discovery server. If successful in procuration of a new lease +// then it is written to the registrationDisk on the kv. +func (c *clientIDTracker) register() error { + lease, signature, err := c.requestChannelLease() + if err != nil { + return err + } + + c.registrationDisk.Update(lease, signature) + + return nil +} + +// requestChannelLease requests a new channel lease +// from the user discovery server. +func (c *clientIDTracker) requestChannelLease() (int64, []byte, error) { + ts := netTime.Now().UnixNano() + privKey, err := c.receptionIdentity.GetRSAPrivateKey() + if err != nil { + return 0, nil, err + } + + rng := c.rngSource.GetStream() + userPubKey := c.registrationDisk.GetPublicKey() + fSig, err := channel.SignChannelIdentityRequest(userPubKey, time.Unix(0, ts), privKey, rng) + if err != nil { + return 0, nil, err + } + rng.Close() + + msg := &mixmessages.ChannelLeaseRequest{ + UserID: c.receptionIdentity.ID.Marshal(), + UserEd25519PubKey: userPubKey, + Timestamp: ts, + UserPubKeyRSASignature: fSig, + } + + resp, err := c.comms.SendChannelLeaseRequest(c.host, msg) + if err != nil { + return 0, nil, err + } + + ok := channel.VerifyChannelLease(resp.UDLeaseEd25519Signature, + userPubKey, c.username, time.Unix(0, resp.Lease), c.udPubKey) + if !ok { + return 0, nil, ErrChannelLeaseSignature + } + + return resp.Lease, resp.UDLeaseEd25519Signature, err +} + +// StartChannelNameService creates a new clientIDTracker +// and returns a reference to it's type as the NameService interface. +// However, it's scheduler thread isn't started until it's Start +// method is called. +func (m *Manager) StartChannelNameService() (channels.NameService, error) { + + if m.nameService == nil { + udPubKeyBytes := m.user.GetCmix().GetInstance().GetPartialNdf().Get().UDB.DhPubKey + username, err := m.store.GetUsername() + if err != nil { + return nil, err + } + m.nameService = newclientIDTracker( + m.comms, + m.ud.host, + username, + m.getKv(), + m.user.GetReceptionIdentity(), + udPubKeyBytes, + m.getRng()) + + } + + return m.nameService, nil +} diff --git a/ud/channelIDTracking_test.go b/ud/channelIDTracking_test.go new file mode 100644 index 0000000000000000000000000000000000000000..52c4c9826949856a363f04c315a2fd5dc7449637 --- /dev/null +++ b/ud/channelIDTracking_test.go @@ -0,0 +1,137 @@ +package ud + +import ( + "crypto/ed25519" + "crypto/rand" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "gitlab.com/xx_network/comms/connect" + "gitlab.com/xx_network/crypto/csprng" + "gitlab.com/xx_network/crypto/signature/rsa" + "gitlab.com/xx_network/primitives/id" + + "gitlab.com/elixxir/client/event" + "gitlab.com/elixxir/client/storage/versioned" + store "gitlab.com/elixxir/client/ud/store" + "gitlab.com/elixxir/crypto/fastRNG" + "gitlab.com/elixxir/ekv" +) + +func TestSignChannelMessage(t *testing.T) { + publicKey, privateKey, err := ed25519.GenerateKey(rand.Reader) + require.NoError(t, err) + + reg := registrationDisk{ + PublicKey: publicKey, + PrivateKey: privateKey, + Lease: 0, + } + c := &clientIDTracker{ + registrationDisk: ®, + } + + message := []byte("hello world") + sig, err := c.SignChannelMessage(message) + require.NoError(t, err) + + require.True(t, ed25519.Verify(publicKey, message, sig)) +} + +func TestNewRegistrationDisk(t *testing.T) { + publicKey, privateKey, err := ed25519.GenerateKey(rand.Reader) + require.NoError(t, err) + lease := time.Now().UnixNano() + + signature := make([]byte, 64) + reg := newRegistrationDisk(publicKey, privateKey, time.Unix(0, lease), signature) + require.Equal(t, reg.PublicKey, publicKey) + require.Equal(t, reg.PrivateKey, privateKey) + require.Equal(t, reg.Signature, signature) + require.Equal(t, reg.Lease, lease) +} + +func TestLoadSaveRegistration(t *testing.T) { + publicKey, privateKey, err := ed25519.GenerateKey(rand.Reader) + require.NoError(t, err) + lease := time.Now() + signature := make([]byte, 64) + reg := newRegistrationDisk(publicKey, privateKey, lease, signature) + + kv := versioned.NewKV(ekv.MakeMemstore()) + + registrationDisk, err := loadRegistrationDisk(kv) + require.Error(t, err) + require.False(t, kv.Exists(err)) + + err = saveRegistrationDisk(kv, reg) + require.NoError(t, err) + + registrationDisk, err = loadRegistrationDisk(kv) + require.NoError(t, err) + require.Equal(t, registrationDisk, reg) +} + +func TestChannelIDTracking(t *testing.T) { + rngGen := fastRNG.NewStreamGenerator(1000, 10, csprng.NewSystemRNG) + + // comms AddHost + stream := rngGen.GetStream() + privKey, err := rsa.GenerateKey(stream, 1024) + require.NoError(t, err) + + tnm := newTestNetworkManager(t) + managerkv := versioned.NewKV(ekv.MakeMemstore()) + udStore, err := store.NewOrLoadStore(managerkv) + m := &Manager{ + user: mockE2e{ + grp: getGroup(), + events: event.NewEventManager(), + rng: rngGen, + kv: managerkv, + network: tnm, + t: t, + key: privKey, + }, + store: udStore, + comms: &mockComms{}, + } + + netDef := m.getCmix().GetInstance().GetPartialNdf().Get() + udID, err := id.Unmarshal(netDef.UDB.ID) + require.NoError(t, err) + + params := connect.GetDefaultHostParams() + params.AuthEnabled = false + params.SendTimeout = 20 * time.Second + + host, err := m.comms.AddHost(udID, netDef.UDB.Address, + []byte(netDef.UDB.Cert), params) + require.NoError(t, err) + + // register + + kv := versioned.NewKV(ekv.MakeMemstore()) + comms := new(mockComms) + username := "Alice" + + udPubKey, udPrivKey, err := ed25519.GenerateKey(rand.Reader) + require.NoError(t, err) + + rsaPrivKey, err := m.user.GetReceptionIdentity().GetRSAPrivateKey() + require.NoError(t, err) + + comms.SetUserRSAPubKey(rsaPrivKey.GetPublic()) + comms.SetUDEd25519PrivateKey(&udPrivKey) + comms.SetUsername(username) + + myTestClientIDTracker := newclientIDTracker( + comms, host, username, + kv, m.user.GetReceptionIdentity(), + udPubKey, rngGen) + + err = myTestClientIDTracker.register() + require.NoError(t, err) +} diff --git a/ud/comms.go b/ud/comms.go index 07a450a405a98750fb6a2bd9dd3424c5c6f5e478..df993f608cc1ccc08a5f3e670a8322e4d97ff819 100644 --- a/ud/comms.go +++ b/ud/comms.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package ud import ( @@ -37,6 +44,8 @@ type Comms interface { // object. This will be used to send to the UD service on the above // gRPC send functions. GetHost(hostId *id.ID) (*connect.Host, bool) + + channelLeaseComms } // removeFactComms is a sub-interface of the Comms interface for the @@ -68,3 +77,7 @@ type registerUserComms interface { type addFactComms interface { SendRegisterFact(host *connect.Host, message *pb.FactRegisterRequest) (*pb.FactRegisterResponse, error) } + +type channelLeaseComms interface { + SendChannelLeaseRequest(host *connect.Host, message *pb.ChannelLeaseRequest) (*pb.ChannelLeaseResponse, error) +} diff --git a/ud/compileProtobuf.sh b/ud/compileProtobuf.sh new file mode 100644 index 0000000000000000000000000000000000000000..ff4554cda302477db4d22715d3975d97f80268ac --- /dev/null +++ b/ud/compileProtobuf.sh @@ -0,0 +1,14 @@ +#!/bin/bash +################################################################################ +## Copyright © 2022 xx foundation ## +## ## +## Use of this source code is governed by a license that can be found in the ## +## LICENSE file. ## +################################################################################ + +# This script will compile the Protobuf file to a Go file (pb.go). +# This is meant to be called from the top level of the repo. + +cd ./ud/ || return + +protoc --go_out=. --go_opt=paths=source_relative ./udMessages.proto diff --git a/ud/confirmFact.go b/ud/confirmFact.go index a55da37566945a03b5c0a276f92b7e30ec220f4d..8fdafc24af9a52ac4b664e56dfe99aec3e95996e 100644 --- a/ud/confirmFact.go +++ b/ud/confirmFact.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package ud import ( @@ -6,8 +13,8 @@ import ( pb "gitlab.com/elixxir/comms/mixmessages" ) -// ConfirmFact confirms a fact first registered via AddFact. The -// confirmation ID comes from AddFact while the code will come over the +// ConfirmFact confirms a fact first registered via SendRegisterFact. The +// confirmation ID comes from SendRegisterFact while the code will come over the // associated communications system. func (m *Manager) ConfirmFact(confirmationID, code string) error { jww.INFO.Printf("ud.ConfirmFact(%s, %s)", confirmationID, code) diff --git a/ud/confirmFact_test.go b/ud/confirmFact_test.go index b59a3c385a499ff9685c5520056ac3c59cb0c9b0..72c72260557f92e1c611e0073fd47407b41e5d40 100644 --- a/ud/confirmFact_test.go +++ b/ud/confirmFact_test.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package ud import ( diff --git a/ud/generate.sh b/ud/generate.sh deleted file mode 100755 index f8e0ec99843d0d39bf12b63f145d81a8df1bc99d..0000000000000000000000000000000000000000 --- a/ud/generate.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -protoc --go_out=. udMessages.proto diff --git a/ud/interfaces.go b/ud/interfaces.go index addd3a5303c42f7d6e3ce5ddd075e6a43e14ed6d..9439d365c56441356477ee34c76fb5371c032c63 100644 --- a/ud/interfaces.go +++ b/ud/interfaces.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package ud import ( diff --git a/ud/lookup.go b/ud/lookup.go index cce461a9d0cb4676cb4f35cf9fdb4e175b9fd00c..569dc5b99578e9487c350028eb5e4649cbf8efc1 100644 --- a/ud/lookup.go +++ b/ud/lookup.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package ud import ( diff --git a/ud/lookup_test.go b/ud/lookup_test.go index 2b168e4a30c3b04e9840225c43b5e1aab039759c..4b4d61d65e4154cb94b831fe5c4bee44d1a01d11 100644 --- a/ud/lookup_test.go +++ b/ud/lookup_test.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package ud import ( @@ -43,7 +50,7 @@ func TestManager_Lookup(t *testing.T) { DhPubKey: publicKey, } - contacts := []*Contact{&Contact{ + contacts := []*Contact{{ UserID: expectedContact.ID.Bytes(), PubKey: expectedContact.DhPubKey.Bytes(), }} diff --git a/ud/manager.go b/ud/manager.go index 0a4247fb809d876b4c0659639827bc2929ba3b83..fd57a886b7046c09cfb33bf6a58adc0d752730e5 100644 --- a/ud/manager.go +++ b/ud/manager.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package ud import ( @@ -37,6 +44,10 @@ type Manager struct { // ud is the tracker for the contact information of the specified UD server. // This information is specified in Manager's constructors (NewOrLoad and NewManagerFromBackup). ud *userDiscovery + + // nameService adheres to the channels.NameService interface. This is + // implemented using the clientIDTracker. + nameService *clientIDTracker } // NewOrLoad loads an existing Manager from storage or creates a @@ -66,18 +77,34 @@ func NewOrLoad(user udE2e, comms Comms, follower udNetworkStatus, jww.INFO.Println("ud.NewOrLoad()") - // Construct manager - m, err := loadOrNewManager(user, comms, follower) - if err != nil { - return nil, err + if follower() != xxdk.Running { + return nil, errors.New( + "cannot start UD Manager when network follower is not running.") + } + + // Initialize manager + m := &Manager{ + user: user, + comms: comms, } // Set user discovery - err = m.setUserDiscovery(cert, contactFile, address) + err := m.setUserDiscovery(cert, contactFile, address) if err != nil { return nil, err } + // Initialize store + m.store, err = store.NewOrLoadStore(m.getKv()) + if err != nil { + return nil, errors.Errorf("Failed to initialize store: %v", err) + } + + // If already registered, return + if IsRegistered(m.getKv()) { + return m, nil + } + // Register manager rng := m.getRng().GetStream() defer rng.Close() @@ -86,7 +113,12 @@ func NewOrLoad(user udE2e, comms Comms, follower udNetworkStatus, return nil, err } - return m, nil + usernameFact, err := fact.NewFact(fact.Username, username) + if err != nil { + return nil, err + } + + return m, m.store.StoreUsername(usernameFact) } // NewManagerFromBackup builds a new user discover manager from a backup. @@ -111,7 +143,8 @@ func NewOrLoad(user udE2e, comms Comms, follower udNetworkStatus, // Returns // - A Manager object which is registered to the specified UD service. func NewManagerFromBackup(user udE2e, comms Comms, follower udNetworkStatus, - email, phone fact.Fact, cert, contactFile []byte, address string) (*Manager, error) { + username, email, phone fact.Fact, + cert, contactFile []byte, address string) (*Manager, error) { jww.INFO.Println("ud.NewManagerFromBackup()") if follower() != xxdk.Running { return nil, errors.New( @@ -133,7 +166,7 @@ func NewManagerFromBackup(user udE2e, comms Comms, follower udNetworkStatus, } // Put any passed in missing facts into store - err = m.store.BackUpMissingFacts(email, phone) + err = m.store.BackUpMissingFacts(username, email, phone) if err != nil { return nil, errors.WithMessage(err, "Failed to restore UD store "+ "from backup") @@ -164,7 +197,7 @@ func InitStoreFromBackup(kv *versioned.KV, } // Put any passed in missing facts into store - err = udStore.BackUpMissingFacts(email, phone) + err = udStore.BackUpMissingFacts(username, email, phone) if err != nil { return errors.WithMessage(err, "Failed to restore UD store "+ "from backup") @@ -197,41 +230,6 @@ func (m *Manager) GetContact() contact.Contact { return m.ud.contact } -// loadOrNewManager is a helper function which loads from storage or -// creates a new Manager object. -func loadOrNewManager(user udE2e, comms Comms, - follower udNetworkStatus) (*Manager, error) { - if follower() != xxdk.Running { - return nil, errors.New( - "cannot start UD Manager when network follower is not running.") - } - - // Initialize manager - m := &Manager{ - user: user, - comms: comms, - } - - if m.isRegistered() { - // Load manager if already registered - var err error - m.store, err = store.NewOrLoadStore(m.getKv()) - if err != nil { - return nil, errors.Errorf("Failed to initialize store: %v", err) - } - return m, nil - } - - // Initialize store - var err error - m.store, err = store.NewOrLoadStore(m.getKv()) - if err != nil { - return nil, errors.Errorf("Failed to initialize store: %v", err) - } - - return m, nil -} - //////////////////////////////////////////////////////////////////////////////// // Internal Getters // //////////////////////////////////////////////////////////////////////////////// @@ -242,7 +240,7 @@ func (m *Manager) getCmix() udCmix { return m.user.GetCmix() } -// getKv returns a versioned.KV used for isRegistered and setRegistered. +// 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 { diff --git a/ud/manager_test.go b/ud/manager_test.go index b214c9600302170cc0822b8806ac8c8fe6de943b..c54e17977c2dbdeb047208ff0fd0d94b8784e1ba 100644 --- a/ud/manager_test.go +++ b/ud/manager_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package ud diff --git a/ud/mockComms_test.go b/ud/mockComms_test.go index 542469eac332d27589dc6c40a27ef824f60a6cab..b77efc11a502e72036b343708e993ede522f46ba 100644 --- a/ud/mockComms_test.go +++ b/ud/mockComms_test.go @@ -1,14 +1,31 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package ud import ( - pb "gitlab.com/elixxir/comms/mixmessages" + "crypto/ed25519" + "time" + "gitlab.com/xx_network/comms/connect" "gitlab.com/xx_network/comms/messages" + "gitlab.com/xx_network/crypto/signature/rsa" "gitlab.com/xx_network/primitives/id" + + pb "gitlab.com/elixxir/comms/mixmessages" + "gitlab.com/elixxir/crypto/channel" ) type mockComms struct { - udHost *connect.Host + udHost *connect.Host + userRsaPub *rsa.PublicKey + userEd25519PubKey []byte + udPrivKey *ed25519.PrivateKey + username string } func (m mockComms) SendRegisterUser(host *connect.Host, message *pb.UDBUserRegistration) (*messages.Ack, error) { @@ -44,3 +61,44 @@ func (m *mockComms) AddHost(hid *id.ID, address string, cert []byte, params conn func (m mockComms) GetHost(hostId *id.ID) (*connect.Host, bool) { return m.udHost, true } + +func (m *mockComms) SetUDEd25519PrivateKey(key *ed25519.PrivateKey) { + m.udPrivKey = key +} + +func (m *mockComms) SetUserRSAPubKey(userRsaPub *rsa.PublicKey) { + m.userRsaPub = userRsaPub +} + +func (m *mockComms) SetUsername(u string) { + m.username = u +} + +func (m mockComms) SendChannelLeaseRequest(host *connect.Host, message *pb.ChannelLeaseRequest) (*pb.ChannelLeaseResponse, error) { + + err := channel.VerifyChannelIdentityRequest(message.UserPubKeyRSASignature, + message.UserEd25519PubKey, + time.Now(), + time.Unix(0, message.Timestamp), + m.userRsaPub) + if err != nil { + panic(err) + } + + d, _ := time.ParseDuration("4h30m") + lease := time.Now().Add(d).UnixNano() + signature := channel.SignChannelLease(message.UserEd25519PubKey, m.username, + time.Unix(0, lease), *m.udPrivKey) + + if err != nil { + panic(err) + } + + response := &pb.ChannelLeaseResponse{ + Lease: lease, + UserEd25519PubKey: m.userEd25519PubKey, + UDLeaseEd25519Signature: signature, + } + + return response, nil +} diff --git a/ud/mockE2e_test.go b/ud/mockE2e_test.go index c57e148fe6a63845a480bebb1aa939789b600bfc..e903d7eb59819ddb0445a7167cd4ebfd45c2361a 100644 --- a/ud/mockE2e_test.go +++ b/ud/mockE2e_test.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package ud import ( @@ -109,7 +116,7 @@ func (m mockE2eHandler) StartProcesses() (stoppable.Stoppable, error) { panic("implement me") } -func (m mockE2eHandler) SendE2E(mt catalog.MessageType, recipient *id.ID, payload []byte, params e2e.Params) ([]id.Round, cryptoE2e.MessageID, time.Time, error) { +func (m mockE2eHandler) SendE2E(mt catalog.MessageType, recipient *id.ID, payload []byte, params e2e.Params) (cryptoE2e.SendReport, error) { //TODO implement me panic("implement me") } diff --git a/ud/mockStore_test.go b/ud/mockStore_test.go index 5031f491bbfa8b8f24ca35c9f57d3b5dd6df0575..6e1b336d9e25246f5bc76bae47c5ebddfd2db96a 100644 --- a/ud/mockStore_test.go +++ b/ud/mockStore_test.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package ud import ( diff --git a/ud/networkManager_test.go b/ud/networkManager_test.go index 3af69d9efaab5db21c45ea17f46c21313bb4e197..bd3630ebf9016e37535dbba6ea332c5676da4a1a 100644 --- a/ud/networkManager_test.go +++ b/ud/networkManager_test.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package ud import ( @@ -27,9 +34,44 @@ type testNetworkManager struct { responseProcessor message.Processor } +func (tnm *testNetworkManager) SendWithAssembler(recipient *id.ID, assembler cmix.MessageAssembler, + cmixParams cmix.CMIXParams) (rounds.Round, ephemeral.Id, error) { + + msg := format.NewMessage(tnm.instance.GetE2EGroup().GetP().ByteLen()) + + var rid id.Round = 123 + ephemeralId := new(ephemeral.Id) + + fingerprint, service, payload, mac, err := assembler(rid) + if err != nil { + return rounds.Round{ID: rid}, *ephemeralId, err + } + + // 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 rounds.Round{}, ephemeral.Id{}, nil +} + func (tnm *testNetworkManager) Send(recipient *id.ID, fingerprint format.Fingerprint, service message.Service, - payload, mac []byte, cmixParams cmix.CMIXParams) (id.Round, ephemeral.Id, error) { + payload, mac []byte, cmixParams cmix.CMIXParams) (rounds.Round, ephemeral.Id, error) { msg := format.NewMessage(tnm.instance.GetE2EGroup().GetP().ByteLen()) // Build message. Will panic if inputs are not correct. msg.SetKeyFP(fingerprint) @@ -50,7 +92,7 @@ func (tnm *testNetworkManager) Send(recipient *id.ID, fingerprint format.Fingerp tnm.requestProcess.Process(msg, receptionID.EphemeralIdentity{}, rounds.Round{}) } - return 0, ephemeral.Id{}, nil + return rounds.Round{}, ephemeral.Id{}, nil } func (tnm *testNetworkManager) AddFingerprint(identity *id.ID, @@ -129,7 +171,7 @@ func (tnm *testNetworkManager) SendToAny(sendFunc func(host *connect.Host) (inte panic("implement me") } -func (tnm *testNetworkManager) SendMany(messages []cmix.TargetedCmixMessage, p cmix.CMIXParams) (id.Round, []ephemeral.Id, error) { +func (tnm *testNetworkManager) SendMany(messages []cmix.TargetedCmixMessage, p cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error) { //TODO implement me panic("implement me") } @@ -189,7 +231,7 @@ func (tnm *testNetworkManager) TriggerNodeRegistration(nid *id.ID) { panic("implement me") } -func (tnm *testNetworkManager) GetRoundResults(timeout time.Duration, roundCallback cmix.RoundEventCallback, roundList ...id.Round) error { +func (tnm *testNetworkManager) GetRoundResults(timeout time.Duration, roundCallback cmix.RoundEventCallback, roundList ...id.Round) { //TODO implement me panic("implement me") } diff --git a/ud/register.go b/ud/register.go index 495d50da5e1fb51dd0e9d0e9d0211547d3314946..d70eaf0e2c71e80e859be942e19b3e6aa1196383 100644 --- a/ud/register.go +++ b/ud/register.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package ud import ( @@ -19,7 +26,7 @@ func (m *Manager) register(username string, networkSignature []byte, // Retrieve data used for registration identity := m.user.GetReceptionIdentity() - privKey, err := identity.GetRSAPrivatePem() + privKey, err := identity.GetRSAPrivateKey() if err != nil { return err } diff --git a/ud/register_test.go b/ud/register_test.go index f5c4f57828f27826ebd025354bc91a13cb81ec49..3d89b7245493e493a20974c990f45fb2cd49cc4f 100644 --- a/ud/register_test.go +++ b/ud/register_test.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package ud import ( diff --git a/ud/registered.go b/ud/registered.go index 06dba95886e3d92717ae9d8143fbd3ca8bd3189c..f19bcc03e63adebe5b3992131e61af1cc91008e1 100644 --- a/ud/registered.go +++ b/ud/registered.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package ud import ( @@ -11,10 +18,10 @@ import ( const isRegisteredKey = "isRegisteredKey" const isRegisteredVersion = 0 -// isRegistered loads from storage if the user is registered with user +// IsRegistered loads from storage if the user is registered with user // discovery. -func (m *Manager) isRegistered() bool { - _, err := m.getKv().Get(isRegisteredKey, isRegisteredVersion) +func IsRegistered(kv *versioned.KV) bool { + _, err := kv.Get(isRegisteredKey, isRegisteredVersion) if err != nil { return false } @@ -32,7 +39,7 @@ func setRegistered(kv *versioned.KV) error { Data: data, } - if err := kv.Set(isRegisteredKey, isRegisteredVersion, obj); err != nil { + if err := kv.Set(isRegisteredKey, obj); err != nil { jww.FATAL.Panicf("Failed to store that the client is "+ "registered: %+v", err) } diff --git a/ud/remove.go b/ud/remove.go index ebb809c0022ab0bbc81237c092c106bcbf946bd2..71db207ed6c263e8024f3df6cd1e56aba3cb8a29 100644 --- a/ud/remove.go +++ b/ud/remove.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package ud import ( @@ -40,7 +47,7 @@ func (m *Manager) removeFact(f fact.Fact, // Sign our inFact for putting into the request identity := m.user.GetReceptionIdentity() - privKey, err := identity.GetRSAPrivatePem() + privKey, err := identity.GetRSAPrivateKey() if err != nil { return err } @@ -78,7 +85,7 @@ func (m *Manager) PermanentDeleteAccount(f fact.Fact) error { "a username. Cannot remove fact %q", f.Fact)) } identity := m.user.GetReceptionIdentity() - privKey, err := identity.GetRSAPrivatePem() + privKey, err := identity.GetRSAPrivateKey() if err != nil { return err } diff --git a/ud/remove_test.go b/ud/remove_test.go index 53b61b3fae3070c08dad9d5d9d8c9d69503b0371..211bff6ae3516908e5b93efbd831cb3378ee7278 100644 --- a/ud/remove_test.go +++ b/ud/remove_test.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package ud //type testRFC struct{} diff --git a/ud/search.go b/ud/search.go index dee22789df5cd285bd31835f00c134eac8bdbee3..43bf08518350929df2c652724bf8706e1ac74b38 100644 --- a/ud/search.go +++ b/ud/search.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package ud import ( diff --git a/ud/search_test.go b/ud/search_test.go index 3130e4f9b524a0cd79360a1bbcd42c4430052e8d..596d7768d191a05368f50e663f4d23dd04765cf4 100644 --- a/ud/search_test.go +++ b/ud/search_test.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package ud import ( diff --git a/ud/store/facts.go b/ud/store/facts.go index 202d8814bf5748ad5c7f8bf77c68ca26344fa842..4721b864ead28fb44a6e2a3c7bd7b87196d4c9f8 100644 --- a/ud/store/facts.go +++ b/ud/store/facts.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package ud @@ -42,6 +42,42 @@ func (s *Store) RestoreFromBackUp(backupData fact.FactList) error { return s.save() } +// StoreUsername forces the storage of a username fact.Fact into the +// Store's confirmedFacts map. The passed in fact.Fact must be of +// type fact.Username or this will not store the username. +func (s *Store) StoreUsername(f fact.Fact) error { + s.mux.Lock() + defer s.mux.Unlock() + + if f.T != fact.Username { + return errors.Errorf("Fact (%s) is not of type username", f.Stringify()) + } + + s.confirmedFacts[f] = struct{}{} + + return s.saveConfirmedFacts() +} + +// GetUsername retrieves the username from the Store object. +// If it is not directly in the Store's username field, it is +// searched for in the map. +func (s *Store) GetUsername() (string, error) { + s.mux.RLock() + defer s.mux.RUnlock() + + // todo: refactor this in the future so that + // it's an O(1) lookup (place this object in another map + // or have it's own field) + for f := range s.confirmedFacts { + if f.T == fact.Username { + return f.Fact, nil + } + } + + return "", errors.New("Could not find username in store") + +} + // StoreUnconfirmedFact stores a fact that has been added to UD but has not been // confirmed by the user. It is keyed on the confirmation ID given by UD. func (s *Store) StoreUnconfirmedFact(confirmationId string, f fact.Fact) error { @@ -84,11 +120,11 @@ func (s *Store) ConfirmFact(confirmationId string) error { // If you attempt to back up a fact type that has already been backed up, // an error will be returned and nothing will be backed up. // Otherwise, it adds the fact and returns whether the Store saved successfully. -func (s *Store) BackUpMissingFacts(email, phone fact.Fact) error { +func (s *Store) BackUpMissingFacts(username, email, phone fact.Fact) error { s.mux.Lock() defer s.mux.Unlock() - modifiedEmail, modifiedPhone := false, false + modified := false // Handle email if it is not zero (empty string) if !isFactZero(email) { @@ -102,10 +138,12 @@ func (s *Store) BackUpMissingFacts(email, phone fact.Fact) error { // If an email exists in memory, return an error return errors.Errorf(factTypeExistsErr, email, fact.Email) } else { - modifiedEmail = true + s.confirmedFacts[email] = struct{}{} + modified = true } } + // Handle phone if it is not an empty string if !isFactZero(phone) { // check if fact is expected type if phone.T != fact.Phone { @@ -117,19 +155,24 @@ func (s *Store) BackUpMissingFacts(email, phone fact.Fact) error { // If a phone exists in memory, return an error return errors.Errorf(factTypeExistsErr, phone, fact.Phone) } else { - modifiedPhone = true + s.confirmedFacts[phone] = struct{}{} + modified = true } } - if modifiedPhone || modifiedEmail { - if modifiedEmail { - s.confirmedFacts[email] = struct{}{} - } - - if modifiedPhone { - s.confirmedFacts[phone] = struct{}{} + if !isFactZero(username) { + // Check if fact type is already in map. You should not be able to + // overwrite your username. + if isFactTypeInMap(fact.Username, s.confirmedFacts) { + // If a username exists in memory, return an error + return errors.Errorf(factTypeExistsErr, username, fact.Username) + } else { + s.confirmedFacts[username] = struct{}{} + modified = true } + } + if modified { return s.saveConfirmedFacts() } diff --git a/ud/store/facts_test.go b/ud/store/facts_test.go index 332b5289da335390d76df7f41adbb49f2bd2d975..3155d383b36e7eb95d218f3389fa62e0ba9be0b6 100644 --- a/ud/store/facts_test.go +++ b/ud/store/facts_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package ud @@ -20,9 +20,9 @@ func TestNewStore(t *testing.T) { kv := versioned.NewKV(ekv.MakeMemstore()) - _, err := NewStore(kv) + _, err := newStore(kv) if err != nil { - t.Errorf("NewStore() produced an error: %v", err) + t.Errorf("newStore() produced an error: %v", err) } } @@ -32,9 +32,9 @@ func TestStore_RestoreFromBackUp(t *testing.T) { kv := versioned.NewKV(ekv.MakeMemstore()) - s, err := NewStore(kv) + s, err := newStore(kv) if err != nil { - t.Errorf("NewStore() produced an error: %v", err) + t.Errorf("newStore() produced an error: %v", err) } expected := fact.Fact{ @@ -61,9 +61,9 @@ func TestStore_RestoreFromBackUp_StatefulStore(t *testing.T) { kv := versioned.NewKV(ekv.MakeMemstore()) - s, err := NewStore(kv) + s, err := newStore(kv) if err != nil { - t.Errorf("NewStore() produced an error: %v", err) + t.Errorf("newStore() produced an error: %v", err) } confirmId := "confirm" @@ -90,9 +90,9 @@ func TestStore_RestoreFromBackUp_StatefulStore(t *testing.T) { func TestStore_ConfirmFact(t *testing.T) { kv := versioned.NewKV(ekv.MakeMemstore()) - expectedStore, err := NewStore(kv) + expectedStore, err := newStore(kv) if err != nil { - t.Errorf("NewStore() produced an error: %v", err) + t.Errorf("newStore() produced an error: %v", err) } confirmId := "confirm" @@ -128,9 +128,9 @@ func TestStore_ConfirmFact(t *testing.T) { func TestStore_StoreUnconfirmedFact(t *testing.T) { kv := versioned.NewKV(ekv.MakeMemstore()) - expectedStore, err := NewStore(kv) + expectedStore, err := newStore(kv) if err != nil { - t.Errorf("NewStore() produced an error: %v", err) + t.Errorf("newStore() produced an error: %v", err) } confirmId := "confirm" @@ -156,9 +156,9 @@ func TestStore_StoreUnconfirmedFact(t *testing.T) { func TestStore_DeleteFact(t *testing.T) { kv := versioned.NewKV(ekv.MakeMemstore()) - expectedStore, err := NewStore(kv) + expectedStore, err := newStore(kv) if err != nil { - t.Errorf("NewStore() produced an error: %v", err) + t.Errorf("newStore() produced an error: %v", err) } expected := fact.Fact{ @@ -188,9 +188,9 @@ func TestStore_DeleteFact(t *testing.T) { func TestStore_BackUpMissingFacts(t *testing.T) { kv := versioned.NewKV(ekv.MakeMemstore()) - expectedStore, err := NewStore(kv) + expectedStore, err := newStore(kv) if err != nil { - t.Errorf("NewStore() produced an error: %v", err) + t.Errorf("newStore() produced an error: %v", err) } email := fact.Fact{ @@ -203,7 +203,12 @@ func TestStore_BackUpMissingFacts(t *testing.T) { T: fact.Phone, } - err = expectedStore.BackUpMissingFacts(email, phone) + username := fact.Fact{ + Fact: "admin", + T: fact.Username, + } + + err = expectedStore.BackUpMissingFacts(username, email, phone) if err != nil { t.Fatalf("BackUpMissingFacts() produced an error: %v", err) } @@ -223,9 +228,9 @@ func TestStore_BackUpMissingFacts(t *testing.T) { func TestStore_BackUpMissingFacts_DuplicateFactType(t *testing.T) { kv := versioned.NewKV(ekv.MakeMemstore()) - expectedStore, err := NewStore(kv) + expectedStore, err := newStore(kv) if err != nil { - t.Errorf("NewStore() produced an error: %v", err) + t.Errorf("newStore() produced an error: %v", err) } email := fact.Fact{ @@ -238,18 +243,23 @@ func TestStore_BackUpMissingFacts_DuplicateFactType(t *testing.T) { T: fact.Phone, } - err = expectedStore.BackUpMissingFacts(email, phone) + username := fact.Fact{ + Fact: "admin", + T: fact.Username, + } + + err = expectedStore.BackUpMissingFacts(username, email, phone) if err != nil { t.Fatalf("BackUpMissingFacts() produced an error: %v", err) } - err = expectedStore.BackUpMissingFacts(email, fact.Fact{}) + err = expectedStore.BackUpMissingFacts(username, email, fact.Fact{}) if err == nil { t.Fatalf("BackUpMissingFacts() should not allow backing up an "+ "email when an email has already been backed up: %v", err) } - err = expectedStore.BackUpMissingFacts(fact.Fact{}, phone) + err = expectedStore.BackUpMissingFacts(username, fact.Fact{}, phone) if err == nil { t.Fatalf("BackUpMissingFacts() should not allow backing up a "+ "phone number when a phone number has already been backed up: %v", err) @@ -260,9 +270,9 @@ func TestStore_BackUpMissingFacts_DuplicateFactType(t *testing.T) { func TestStore_GetFacts(t *testing.T) { kv := versioned.NewKV(ekv.MakeMemstore()) - testStore, err := NewStore(kv) + testStore, err := newStore(kv) if err != nil { - t.Errorf("NewStore() produced an error: %v", err) + t.Errorf("newStore() produced an error: %v", err) } emailFact := fact.Fact{ @@ -272,7 +282,12 @@ func TestStore_GetFacts(t *testing.T) { emptyFact := fact.Fact{} - err = testStore.BackUpMissingFacts(emailFact, emptyFact) + username := fact.Fact{ + Fact: "admin", + T: fact.Username, + } + + err = testStore.BackUpMissingFacts(username, emailFact, emptyFact) if err != nil { t.Fatalf("Faild to add fact %v: %v", emailFact, err) } @@ -282,12 +297,12 @@ func TestStore_GetFacts(t *testing.T) { T: fact.Phone, } - err = testStore.BackUpMissingFacts(emptyFact, phoneFact) + err = testStore.BackUpMissingFacts(emptyFact, emptyFact, phoneFact) if err != nil { t.Fatalf("Faild to add fact %v: %v", phoneFact, err) } - expectedFacts := []fact.Fact{emailFact, phoneFact} + expectedFacts := []fact.Fact{username, emailFact, phoneFact} receivedFacts := testStore.GetFacts() @@ -309,19 +324,23 @@ func TestStore_GetFacts(t *testing.T) { func TestStore_GetFactStrings(t *testing.T) { kv := versioned.NewKV(ekv.MakeMemstore()) - testStore, err := NewStore(kv) + testStore, err := newStore(kv) if err != nil { - t.Errorf("NewStore() produced an error: %v", err) + t.Errorf("newStore() produced an error: %v", err) } emailFact := fact.Fact{ Fact: "josh@elixxir.io", T: fact.Email, } + username := fact.Fact{ + Fact: "admin", + T: fact.Username, + } emptyFact := fact.Fact{} - err = testStore.BackUpMissingFacts(emailFact, emptyFact) + err = testStore.BackUpMissingFacts(username, emailFact, emptyFact) if err != nil { t.Fatalf("Faild to add fact %v: %v", emailFact, err) } @@ -331,12 +350,12 @@ func TestStore_GetFactStrings(t *testing.T) { T: fact.Phone, } - err = testStore.BackUpMissingFacts(emptyFact, phoneFact) + err = testStore.BackUpMissingFacts(emptyFact, emptyFact, phoneFact) if err != nil { t.Fatalf("Faild to add fact %v: %v", phoneFact, err) } - expectedFacts := []string{emailFact.Stringify(), phoneFact.Stringify()} + expectedFacts := []string{username.Stringify(), emailFact.Stringify(), phoneFact.Stringify()} receivedFacts := testStore.GetStringifiedFacts() sort.SliceStable(receivedFacts, func(i, j int) bool { diff --git a/ud/store/store.go b/ud/store/store.go index 0cf274add91a8d08791e7b0c189b8d190d0f7962..5e5cfaaa8af245e9467e08bd4fa8d809c4b77b10 100644 --- a/ud/store/store.go +++ b/ud/store/store.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package ud // This file handles the storage operations on facts. @@ -8,8 +15,6 @@ import ( "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/primitives/fact" "gitlab.com/xx_network/primitives/netTime" - "io/fs" - "strings" "sync" ) @@ -23,8 +28,7 @@ const ( // Error constants const ( - malformedFactErr = "Failed to load due to " + - "malformed fact" + malformedFactErr = "Failed to load due to malformed fact %s" loadConfirmedFactErr = "Failed to load confirmed facts" loadUnconfirmedFactErr = "Failed to load unconfirmed facts" saveUnconfirmedFactErr = "Failed to save unconfirmed facts" @@ -43,13 +47,13 @@ type Store struct { mux sync.RWMutex } -// NewStore creates a new, empty Store object. -func NewStore(kv *versioned.KV) (*Store, error) { +// newStore creates a new, empty Store object. +func newStore(kv *versioned.KV) (*Store, error) { kv = kv.Prefix(prefix) s := &Store{ - confirmedFacts: make(map[fact.Fact]struct{}, 0), - unconfirmedFacts: make(map[string]fact.Fact, 0), + confirmedFacts: make(map[fact.Fact]struct{}), + unconfirmedFacts: make(map[string]fact.Fact), kv: kv, } @@ -94,7 +98,7 @@ func (s *Store) saveConfirmedFacts() error { } // Save to storage - return s.kv.Set(confirmedFactKey, version, &obj) + return s.kv.Set(confirmedFactKey, &obj) } // saveUnconfirmedFacts saves all data within Store.unconfirmedFacts into storage. @@ -113,7 +117,7 @@ func (s *Store) saveUnconfirmedFacts() error { } // Save to storage - return s.kv.Set(unconfirmedFactKey, version, &obj) + return s.kv.Set(unconfirmedFactKey, &obj) } @@ -125,15 +129,13 @@ func (s *Store) saveUnconfirmedFacts() error { func NewOrLoadStore(kv *versioned.KV) (*Store, error) { s := &Store{ - confirmedFacts: make(map[fact.Fact]struct{}, 0), - unconfirmedFacts: make(map[string]fact.Fact, 0), - kv: kv.Prefix(prefix), + kv: kv.Prefix(prefix), } - if err := s.load(); err != nil { - if strings.Contains(err.Error(), "object not found") || - errors.Is(err, fs.ErrNotExist) { - return s, s.save() + if !s.kv.Exists(err) { + return newStore(kv) + } else { + return nil, err } } @@ -199,11 +201,11 @@ func (s *Store) loadUnconfirmedFacts() error { ///////////////////////////////////////////////////////////////// // unconfirmedFactDisk is an object used to store the data of an unconfirmed fact. -// It combines the key (confirmationId) and fact data (stringifiedFact) into a +// It combines the key (ConfirmationId) and fact data (StringifiedFact) into a // single JSON-able object. type unconfirmedFactDisk struct { - confirmationId string - stringifiedFact string + ConfirmationId string + StringifiedFact string } // marshalConfirmedFacts is a marshaller which serializes the data @@ -223,8 +225,8 @@ func (s *Store) marshalUnconfirmedFacts() ([]byte, error) { ufdList := make([]unconfirmedFactDisk, 0, len(s.unconfirmedFacts)) for confirmationId, f := range s.unconfirmedFacts { ufd := unconfirmedFactDisk{ - confirmationId: confirmationId, - stringifiedFact: f.Stringify(), + ConfirmationId: confirmationId, + StringifiedFact: f.Stringify(), } ufdList = append(ufdList, ufd) } @@ -244,10 +246,12 @@ func (s *Store) unmarshalConfirmedFacts(data []byte) (map[fact.Fact]struct{}, er // Deserialize the list into a map confirmedFacts := make(map[fact.Fact]struct{}, 0) - for _, fStr := range fStrings { + for i := range fStrings { + fStr := fStrings[i] f, err := fact.UnstringifyFact(fStr) if err != nil { - return nil, errors.WithMessage(err, malformedFactErr) + return confirmedFacts, errors.WithMessagef(err, + malformedFactErr, string(data)) } confirmedFacts[f] = struct{}{} @@ -268,13 +272,15 @@ func (s *Store) unmarshalUnconfirmedFacts(data []byte) (map[string]fact.Fact, er // Deserialize the list into a map unconfirmedFacts := make(map[string]fact.Fact, 0) - for _, ufd := range ufdList { - f, err := fact.UnstringifyFact(ufd.stringifiedFact) + for i := range ufdList { + ufd := ufdList[i] + f, err := fact.UnstringifyFact(ufd.StringifiedFact) if err != nil { - return nil, errors.WithMessage(err, malformedFactErr) + return unconfirmedFacts, errors.WithMessagef(err, + malformedFactErr, string(data)) } - unconfirmedFacts[ufd.confirmationId] = f + unconfirmedFacts[ufd.ConfirmationId] = f } return unconfirmedFacts, nil diff --git a/ud/store/store_test.go b/ud/store/store_test.go index ed56cb67c2a320cea8073e3baa8287998a65763f..a319d81284e122e420c89efc3a3828826c95ae3a 100644 --- a/ud/store/store_test.go +++ b/ud/store/store_test.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package ud import ( @@ -13,9 +20,9 @@ import ( func TestNewOrLoadStore_LoadStore(t *testing.T) { kv := versioned.NewKV(ekv.MakeMemstore()) - expectedStore, err := NewStore(kv) + expectedStore, err := newStore(kv) if err != nil { - t.Errorf("NewStore() produced an error: %v", err) + t.Errorf("newStore() produced an error: %v", err) } receivedStore, err := NewOrLoadStore(kv) @@ -59,9 +66,9 @@ func TestNewOrLoadStore_NewStore(t *testing.T) { func TestStore_MarshalUnmarshal_ConfirmedFacts(t *testing.T) { kv := versioned.NewKV(ekv.MakeMemstore()) - expectedStore, err := NewStore(kv) + expectedStore, err := newStore(kv) if err != nil { - t.Errorf("NewStore() produced an error: %v", err) + t.Errorf("newStore() produced an error: %v", err) } data, err := expectedStore.kv.Get(confirmedFactKey, version) @@ -75,7 +82,7 @@ func TestStore_MarshalUnmarshal_ConfirmedFacts(t *testing.T) { } if !bytes.Equal(expectedData, data.Data) { - t.Errorf("NewStore() returned incorrect Store."+ + t.Errorf("newStore() returned incorrect Store."+ "\nexpected: %+v\nreceived: %+v", expectedData, data.Data) } @@ -95,9 +102,9 @@ func TestStore_MarshalUnmarshal_ConfirmedFacts(t *testing.T) { func TestStore_MarshalUnmarshal_UnconfirmedFacts(t *testing.T) { kv := versioned.NewKV(ekv.MakeMemstore()) - expectedStore, err := NewStore(kv) + expectedStore, err := newStore(kv) if err != nil { - t.Errorf("NewStore() produced an error: %v", err) + t.Errorf("newStore() produced an error: %v", err) } data, err := expectedStore.kv.Get(unconfirmedFactKey, version) @@ -111,7 +118,7 @@ func TestStore_MarshalUnmarshal_UnconfirmedFacts(t *testing.T) { } if !bytes.Equal(expectedData, data.Data) { - t.Errorf("NewStore() returned incorrect Store."+ + t.Errorf("newStore() returned incorrect Store."+ "\nexpected: %+v\nreceived: %+v", expectedData, data.Data) } diff --git a/ud/ud.go b/ud/ud.go index 5fb27e619de9d5196b24022b35277f1f26c37837..6788b9e99388b16cd64b0d91b50d9f43f26b642f 100644 --- a/ud/ud.go +++ b/ud/ud.go @@ -1,10 +1,16 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package ud import ( "github.com/pkg/errors" "gitlab.com/elixxir/crypto/contact" "gitlab.com/xx_network/comms/connect" - "gitlab.com/xx_network/primitives/id" "time" ) @@ -23,35 +29,26 @@ func (m *Manager) setUserDiscovery(cert, params.AuthEnabled = false params.SendTimeout = 20 * time.Second - udIdBytes, dhPubKeyBytes, err := contact.ReadContactFromFile(contactFile) - if err != nil { - return err - } - - udID, err := id.Unmarshal(udIdBytes) + // Unmarshal the new contact + con, err := contact.Unmarshal(contactFile) if err != nil { return err } // Add a new host and return it if it does not already exist - host, err := m.comms.AddHost(udID, address, + host, err := m.comms.AddHost(con.ID, address, cert, params) if err != nil { return errors.WithMessage(err, "User Discovery host object could "+ "not be constructed.") } - dhPubKey := m.user.GetE2E().GetGroup().NewInt(1) - err = dhPubKey.UnmarshalJSON(dhPubKeyBytes) - if err != nil { - return err - } - + // Set the user discovery object within the manager m.ud = &userDiscovery{ host: host, contact: contact.Contact{ - ID: udID, - DhPubKey: dhPubKey, + ID: con.ID, + DhPubKey: con.DhPubKey, }, } diff --git a/ud/udMessages.pb.go b/ud/udMessages.pb.go index 0aae2063325f57b73c42ff53e30020225aefcd7e..8a4745c74317c8934d10f2943af4cc79c0d8dc6d 100644 --- a/ud/udMessages.pb.go +++ b/ud/udMessages.pb.go @@ -1,69 +1,84 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + // Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.27.1 +// protoc v3.15.6 // source: udMessages.proto package ud import ( - fmt "fmt" - proto "github.com/golang/protobuf/proto" - math "math" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" ) -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) // Contains the Hash and its Type type HashFact struct { - Hash []byte `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` - Type int32 `protobuf:"varint,2,opt,name=type,proto3" json:"type,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields -func (m *HashFact) Reset() { *m = HashFact{} } -func (m *HashFact) String() string { return proto.CompactTextString(m) } -func (*HashFact) ProtoMessage() {} -func (*HashFact) Descriptor() ([]byte, []int) { - return fileDescriptor_9e0cfdc16fb09bb6, []int{0} + Hash []byte `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` + Type int32 `protobuf:"varint,2,opt,name=type,proto3" json:"type,omitempty"` } -func (m *HashFact) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_HashFact.Unmarshal(m, b) -} -func (m *HashFact) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_HashFact.Marshal(b, m, deterministic) -} -func (m *HashFact) XXX_Merge(src proto.Message) { - xxx_messageInfo_HashFact.Merge(m, src) +func (x *HashFact) Reset() { + *x = HashFact{} + if protoimpl.UnsafeEnabled { + mi := &file_udMessages_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *HashFact) XXX_Size() int { - return xxx_messageInfo_HashFact.Size(m) + +func (x *HashFact) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *HashFact) XXX_DiscardUnknown() { - xxx_messageInfo_HashFact.DiscardUnknown(m) + +func (*HashFact) ProtoMessage() {} + +func (x *HashFact) ProtoReflect() protoreflect.Message { + mi := &file_udMessages_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -var xxx_messageInfo_HashFact proto.InternalMessageInfo +// Deprecated: Use HashFact.ProtoReflect.Descriptor instead. +func (*HashFact) Descriptor() ([]byte, []int) { + return file_udMessages_proto_rawDescGZIP(), []int{0} +} -func (m *HashFact) GetHash() []byte { - if m != nil { - return m.Hash +func (x *HashFact) GetHash() []byte { + if x != nil { + return x.Hash } return nil } -func (m *HashFact) GetType() int32 { - if m != nil { - return m.Type +func (x *HashFact) GetType() int32 { + if x != nil { + return x.Type } return 0 } @@ -71,285 +86,458 @@ func (m *HashFact) GetType() int32 { // Describes a user lookup result. The ID, public key, and the // facts inputted that brought up this user. type Contact struct { - UserID []byte `protobuf:"bytes,1,opt,name=userID,proto3" json:"userID,omitempty"` - PubKey []byte `protobuf:"bytes,2,opt,name=pubKey,proto3" json:"pubKey,omitempty"` - Username string `protobuf:"bytes,3,opt,name=username,proto3" json:"username,omitempty"` - TrigFacts []*HashFact `protobuf:"bytes,4,rep,name=trigFacts,proto3" json:"trigFacts,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *Contact) Reset() { *m = Contact{} } -func (m *Contact) String() string { return proto.CompactTextString(m) } -func (*Contact) ProtoMessage() {} -func (*Contact) Descriptor() ([]byte, []int) { - return fileDescriptor_9e0cfdc16fb09bb6, []int{1} + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + UserID []byte `protobuf:"bytes,1,opt,name=userID,proto3" json:"userID,omitempty"` + PubKey []byte `protobuf:"bytes,2,opt,name=pubKey,proto3" json:"pubKey,omitempty"` + Username string `protobuf:"bytes,3,opt,name=username,proto3" json:"username,omitempty"` + TrigFacts []*HashFact `protobuf:"bytes,4,rep,name=trigFacts,proto3" json:"trigFacts,omitempty"` +} + +func (x *Contact) Reset() { + *x = Contact{} + if protoimpl.UnsafeEnabled { + mi := &file_udMessages_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *Contact) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Contact.Unmarshal(m, b) -} -func (m *Contact) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Contact.Marshal(b, m, deterministic) -} -func (m *Contact) XXX_Merge(src proto.Message) { - xxx_messageInfo_Contact.Merge(m, src) +func (x *Contact) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *Contact) XXX_Size() int { - return xxx_messageInfo_Contact.Size(m) -} -func (m *Contact) XXX_DiscardUnknown() { - xxx_messageInfo_Contact.DiscardUnknown(m) + +func (*Contact) ProtoMessage() {} + +func (x *Contact) ProtoReflect() protoreflect.Message { + mi := &file_udMessages_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -var xxx_messageInfo_Contact proto.InternalMessageInfo +// Deprecated: Use Contact.ProtoReflect.Descriptor instead. +func (*Contact) Descriptor() ([]byte, []int) { + return file_udMessages_proto_rawDescGZIP(), []int{1} +} -func (m *Contact) GetUserID() []byte { - if m != nil { - return m.UserID +func (x *Contact) GetUserID() []byte { + if x != nil { + return x.UserID } return nil } -func (m *Contact) GetPubKey() []byte { - if m != nil { - return m.PubKey +func (x *Contact) GetPubKey() []byte { + if x != nil { + return x.PubKey } return nil } -func (m *Contact) GetUsername() string { - if m != nil { - return m.Username +func (x *Contact) GetUsername() string { + if x != nil { + return x.Username } return "" } -func (m *Contact) GetTrigFacts() []*HashFact { - if m != nil { - return m.TrigFacts +func (x *Contact) GetTrigFacts() []*HashFact { + if x != nil { + return x.TrigFacts } return nil } // Message sent to UDB to search for users type SearchSend struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + // PublicKey used in the registration - Fact []*HashFact `protobuf:"bytes,1,rep,name=fact,proto3" json:"fact,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + Fact []*HashFact `protobuf:"bytes,1,rep,name=fact,proto3" json:"fact,omitempty"` } -func (m *SearchSend) Reset() { *m = SearchSend{} } -func (m *SearchSend) String() string { return proto.CompactTextString(m) } -func (*SearchSend) ProtoMessage() {} -func (*SearchSend) Descriptor() ([]byte, []int) { - return fileDescriptor_9e0cfdc16fb09bb6, []int{2} +func (x *SearchSend) Reset() { + *x = SearchSend{} + if protoimpl.UnsafeEnabled { + mi := &file_udMessages_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *SearchSend) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_SearchSend.Unmarshal(m, b) +func (x *SearchSend) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *SearchSend) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_SearchSend.Marshal(b, m, deterministic) -} -func (m *SearchSend) XXX_Merge(src proto.Message) { - xxx_messageInfo_SearchSend.Merge(m, src) -} -func (m *SearchSend) XXX_Size() int { - return xxx_messageInfo_SearchSend.Size(m) -} -func (m *SearchSend) XXX_DiscardUnknown() { - xxx_messageInfo_SearchSend.DiscardUnknown(m) + +func (*SearchSend) ProtoMessage() {} + +func (x *SearchSend) ProtoReflect() protoreflect.Message { + mi := &file_udMessages_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -var xxx_messageInfo_SearchSend proto.InternalMessageInfo +// Deprecated: Use SearchSend.ProtoReflect.Descriptor instead. +func (*SearchSend) Descriptor() ([]byte, []int) { + return file_udMessages_proto_rawDescGZIP(), []int{2} +} -func (m *SearchSend) GetFact() []*HashFact { - if m != nil { - return m.Fact +func (x *SearchSend) GetFact() []*HashFact { + if x != nil { + return x.Fact } return nil } // Message sent from UDB to client in response to a search type SearchResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + // ID of the session created - Contacts []*Contact `protobuf:"bytes,1,rep,name=contacts,proto3" json:"contacts,omitempty"` - Error string `protobuf:"bytes,3,opt,name=error,proto3" json:"error,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + Contacts []*Contact `protobuf:"bytes,1,rep,name=contacts,proto3" json:"contacts,omitempty"` + Error string `protobuf:"bytes,3,opt,name=error,proto3" json:"error,omitempty"` } -func (m *SearchResponse) Reset() { *m = SearchResponse{} } -func (m *SearchResponse) String() string { return proto.CompactTextString(m) } -func (*SearchResponse) ProtoMessage() {} -func (*SearchResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_9e0cfdc16fb09bb6, []int{3} +func (x *SearchResponse) Reset() { + *x = SearchResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_udMessages_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *SearchResponse) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_SearchResponse.Unmarshal(m, b) -} -func (m *SearchResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_SearchResponse.Marshal(b, m, deterministic) -} -func (m *SearchResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_SearchResponse.Merge(m, src) -} -func (m *SearchResponse) XXX_Size() int { - return xxx_messageInfo_SearchResponse.Size(m) +func (x *SearchResponse) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *SearchResponse) XXX_DiscardUnknown() { - xxx_messageInfo_SearchResponse.DiscardUnknown(m) + +func (*SearchResponse) ProtoMessage() {} + +func (x *SearchResponse) ProtoReflect() protoreflect.Message { + mi := &file_udMessages_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -var xxx_messageInfo_SearchResponse proto.InternalMessageInfo +// Deprecated: Use SearchResponse.ProtoReflect.Descriptor instead. +func (*SearchResponse) Descriptor() ([]byte, []int) { + return file_udMessages_proto_rawDescGZIP(), []int{3} +} -func (m *SearchResponse) GetContacts() []*Contact { - if m != nil { - return m.Contacts +func (x *SearchResponse) GetContacts() []*Contact { + if x != nil { + return x.Contacts } return nil } -func (m *SearchResponse) GetError() string { - if m != nil { - return m.Error +func (x *SearchResponse) GetError() string { + if x != nil { + return x.Error } return "" } // Message sent to UDB for looking up a user type LookupSend struct { - UserID []byte `protobuf:"bytes,1,opt,name=userID,proto3" json:"userID,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields -func (m *LookupSend) Reset() { *m = LookupSend{} } -func (m *LookupSend) String() string { return proto.CompactTextString(m) } -func (*LookupSend) ProtoMessage() {} -func (*LookupSend) Descriptor() ([]byte, []int) { - return fileDescriptor_9e0cfdc16fb09bb6, []int{4} + UserID []byte `protobuf:"bytes,1,opt,name=userID,proto3" json:"userID,omitempty"` } -func (m *LookupSend) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_LookupSend.Unmarshal(m, b) -} -func (m *LookupSend) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_LookupSend.Marshal(b, m, deterministic) -} -func (m *LookupSend) XXX_Merge(src proto.Message) { - xxx_messageInfo_LookupSend.Merge(m, src) +func (x *LookupSend) Reset() { + *x = LookupSend{} + if protoimpl.UnsafeEnabled { + mi := &file_udMessages_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *LookupSend) XXX_Size() int { - return xxx_messageInfo_LookupSend.Size(m) + +func (x *LookupSend) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *LookupSend) XXX_DiscardUnknown() { - xxx_messageInfo_LookupSend.DiscardUnknown(m) + +func (*LookupSend) ProtoMessage() {} + +func (x *LookupSend) ProtoReflect() protoreflect.Message { + mi := &file_udMessages_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -var xxx_messageInfo_LookupSend proto.InternalMessageInfo +// Deprecated: Use LookupSend.ProtoReflect.Descriptor instead. +func (*LookupSend) Descriptor() ([]byte, []int) { + return file_udMessages_proto_rawDescGZIP(), []int{4} +} -func (m *LookupSend) GetUserID() []byte { - if m != nil { - return m.UserID +func (x *LookupSend) GetUserID() []byte { + if x != nil { + return x.UserID } return nil } // Message sent from UDB for looking up a user type LookupResponse struct { - PubKey []byte `protobuf:"bytes,1,opt,name=pubKey,proto3" json:"pubKey,omitempty"` - Username string `protobuf:"bytes,2,opt,name=username,proto3" json:"username,omitempty"` - Error string `protobuf:"bytes,3,opt,name=error,proto3" json:"error,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields -func (m *LookupResponse) Reset() { *m = LookupResponse{} } -func (m *LookupResponse) String() string { return proto.CompactTextString(m) } -func (*LookupResponse) ProtoMessage() {} -func (*LookupResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_9e0cfdc16fb09bb6, []int{5} + PubKey []byte `protobuf:"bytes,1,opt,name=pubKey,proto3" json:"pubKey,omitempty"` + Username string `protobuf:"bytes,2,opt,name=username,proto3" json:"username,omitempty"` + Error string `protobuf:"bytes,3,opt,name=error,proto3" json:"error,omitempty"` } -func (m *LookupResponse) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_LookupResponse.Unmarshal(m, b) -} -func (m *LookupResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_LookupResponse.Marshal(b, m, deterministic) -} -func (m *LookupResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_LookupResponse.Merge(m, src) +func (x *LookupResponse) Reset() { + *x = LookupResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_udMessages_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *LookupResponse) XXX_Size() int { - return xxx_messageInfo_LookupResponse.Size(m) + +func (x *LookupResponse) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *LookupResponse) XXX_DiscardUnknown() { - xxx_messageInfo_LookupResponse.DiscardUnknown(m) + +func (*LookupResponse) ProtoMessage() {} + +func (x *LookupResponse) ProtoReflect() protoreflect.Message { + mi := &file_udMessages_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -var xxx_messageInfo_LookupResponse proto.InternalMessageInfo +// Deprecated: Use LookupResponse.ProtoReflect.Descriptor instead. +func (*LookupResponse) Descriptor() ([]byte, []int) { + return file_udMessages_proto_rawDescGZIP(), []int{5} +} -func (m *LookupResponse) GetPubKey() []byte { - if m != nil { - return m.PubKey +func (x *LookupResponse) GetPubKey() []byte { + if x != nil { + return x.PubKey } return nil } -func (m *LookupResponse) GetUsername() string { - if m != nil { - return m.Username +func (x *LookupResponse) GetUsername() string { + if x != nil { + return x.Username } return "" } -func (m *LookupResponse) GetError() string { - if m != nil { - return m.Error +func (x *LookupResponse) GetError() string { + if x != nil { + return x.Error } return "" } -func init() { - proto.RegisterType((*HashFact)(nil), "parse.HashFact") - proto.RegisterType((*Contact)(nil), "parse.Contact") - proto.RegisterType((*SearchSend)(nil), "parse.SearchSend") - proto.RegisterType((*SearchResponse)(nil), "parse.SearchResponse") - proto.RegisterType((*LookupSend)(nil), "parse.LookupSend") - proto.RegisterType((*LookupResponse)(nil), "parse.LookupResponse") -} - -func init() { - proto.RegisterFile("udMessages.proto", fileDescriptor_9e0cfdc16fb09bb6) -} - -var fileDescriptor_9e0cfdc16fb09bb6 = []byte{ - // 283 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x91, 0x41, 0x4b, 0xc3, 0x40, - 0x10, 0x85, 0xd9, 0x36, 0xad, 0xe9, 0x58, 0xa2, 0x2c, 0x22, 0xc1, 0x53, 0x58, 0x3d, 0x04, 0xc1, - 0x80, 0xf5, 0x1f, 0xa8, 0x88, 0xa2, 0x5e, 0xb6, 0xb7, 0xde, 0xb6, 0xc9, 0xd8, 0x88, 0x98, 0x5d, - 0x76, 0x36, 0x87, 0xde, 0xfd, 0xe1, 0x92, 0xcd, 0x9a, 0x82, 0xb4, 0xb7, 0x79, 0x33, 0xf3, 0xb1, - 0x6f, 0xde, 0xc2, 0x69, 0x5b, 0xbd, 0x23, 0x91, 0xda, 0x20, 0x15, 0xc6, 0x6a, 0xa7, 0xf9, 0xc4, - 0x28, 0x4b, 0x28, 0x16, 0x10, 0x3f, 0x2b, 0xaa, 0x9f, 0x54, 0xe9, 0x38, 0x87, 0xa8, 0x56, 0x54, - 0xa7, 0x2c, 0x63, 0xf9, 0x5c, 0xfa, 0xba, 0xeb, 0xb9, 0xad, 0xc1, 0x74, 0x94, 0xb1, 0x7c, 0x22, - 0x7d, 0x2d, 0x7e, 0x18, 0x1c, 0x3d, 0xe8, 0xc6, 0x75, 0xcc, 0x39, 0x4c, 0x5b, 0x42, 0xfb, 0xf2, - 0x18, 0xa8, 0xa0, 0xba, 0xbe, 0x69, 0xd7, 0xaf, 0xb8, 0xf5, 0xe4, 0x5c, 0x06, 0xc5, 0x2f, 0x20, - 0xee, 0x36, 0x1a, 0xf5, 0x8d, 0xe9, 0x38, 0x63, 0xf9, 0x4c, 0x0e, 0x9a, 0xdf, 0xc0, 0xcc, 0xd9, - 0xcf, 0x4d, 0xe7, 0x85, 0xd2, 0x28, 0x1b, 0xe7, 0xc7, 0x8b, 0x93, 0xc2, 0xdb, 0x2c, 0xfe, 0x3c, - 0xca, 0xdd, 0x86, 0xb8, 0x05, 0x58, 0xa2, 0xb2, 0x65, 0xbd, 0xc4, 0xa6, 0xe2, 0x97, 0x10, 0x7d, - 0xa8, 0xd2, 0xa5, 0x6c, 0x3f, 0xe7, 0x87, 0x42, 0x42, 0xd2, 0x23, 0x12, 0xc9, 0xe8, 0x86, 0x90, - 0x5f, 0x43, 0x5c, 0xf6, 0xa7, 0x50, 0x40, 0x93, 0x80, 0x86, 0x0b, 0xe5, 0x30, 0xe7, 0x67, 0x30, - 0x41, 0x6b, 0xb5, 0x0d, 0xc6, 0x7b, 0x21, 0xae, 0x00, 0xde, 0xb4, 0xfe, 0x6a, 0x8d, 0xb7, 0x71, - 0x20, 0x0f, 0xb1, 0x82, 0xa4, 0xdf, 0x1a, 0x5e, 0xde, 0x25, 0xc4, 0x0e, 0x26, 0x34, 0xfa, 0x97, - 0xd0, 0x5e, 0x07, 0xf7, 0xd1, 0x6a, 0xd4, 0x56, 0xeb, 0xa9, 0xff, 0xd7, 0xbb, 0xdf, 0x00, 0x00, - 0x00, 0xff, 0xff, 0x5a, 0xee, 0x38, 0xba, 0xeb, 0x01, 0x00, 0x00, +var File_udMessages_proto protoreflect.FileDescriptor + +var file_udMessages_proto_rawDesc = []byte{ + 0x0a, 0x10, 0x75, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x12, 0x02, 0x75, 0x64, 0x22, 0x32, 0x0a, 0x08, 0x48, 0x61, 0x73, 0x68, 0x46, 0x61, + 0x63, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0x81, 0x01, 0x0a, 0x07, 0x43, + 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x12, 0x16, + 0x0a, 0x06, 0x70, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, + 0x70, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, + 0x6d, 0x65, 0x12, 0x2a, 0x0a, 0x09, 0x74, 0x72, 0x69, 0x67, 0x46, 0x61, 0x63, 0x74, 0x73, 0x18, + 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x75, 0x64, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x46, + 0x61, 0x63, 0x74, 0x52, 0x09, 0x74, 0x72, 0x69, 0x67, 0x46, 0x61, 0x63, 0x74, 0x73, 0x22, 0x2e, + 0x0a, 0x0a, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x53, 0x65, 0x6e, 0x64, 0x12, 0x20, 0x0a, 0x04, + 0x66, 0x61, 0x63, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x75, 0x64, 0x2e, + 0x48, 0x61, 0x73, 0x68, 0x46, 0x61, 0x63, 0x74, 0x52, 0x04, 0x66, 0x61, 0x63, 0x74, 0x22, 0x4f, + 0x0a, 0x0e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x27, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x75, 0x64, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x52, + 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, + 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, + 0x24, 0x0a, 0x0a, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x53, 0x65, 0x6e, 0x64, 0x12, 0x16, 0x0a, + 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x75, + 0x73, 0x65, 0x72, 0x49, 0x44, 0x22, 0x5a, 0x0a, 0x0e, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x4b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x70, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x12, + 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, + 0x72, 0x72, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, + 0x72, 0x42, 0x1e, 0x5a, 0x1c, 0x67, 0x69, 0x74, 0x6c, 0x61, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x65, 0x6c, 0x69, 0x78, 0x78, 0x69, 0x72, 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2f, 0x75, + 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_udMessages_proto_rawDescOnce sync.Once + file_udMessages_proto_rawDescData = file_udMessages_proto_rawDesc +) + +func file_udMessages_proto_rawDescGZIP() []byte { + file_udMessages_proto_rawDescOnce.Do(func() { + file_udMessages_proto_rawDescData = protoimpl.X.CompressGZIP(file_udMessages_proto_rawDescData) + }) + return file_udMessages_proto_rawDescData +} + +var file_udMessages_proto_msgTypes = make([]protoimpl.MessageInfo, 6) +var file_udMessages_proto_goTypes = []interface{}{ + (*HashFact)(nil), // 0: ud.HashFact + (*Contact)(nil), // 1: ud.Contact + (*SearchSend)(nil), // 2: ud.SearchSend + (*SearchResponse)(nil), // 3: ud.SearchResponse + (*LookupSend)(nil), // 4: ud.LookupSend + (*LookupResponse)(nil), // 5: ud.LookupResponse +} +var file_udMessages_proto_depIdxs = []int32{ + 0, // 0: ud.Contact.trigFacts:type_name -> ud.HashFact + 0, // 1: ud.SearchSend.fact:type_name -> ud.HashFact + 1, // 2: ud.SearchResponse.contacts:type_name -> ud.Contact + 3, // [3:3] is the sub-list for method output_type + 3, // [3:3] is the sub-list for method input_type + 3, // [3:3] is the sub-list for extension type_name + 3, // [3:3] is the sub-list for extension extendee + 0, // [0:3] is the sub-list for field type_name +} + +func init() { file_udMessages_proto_init() } +func file_udMessages_proto_init() { + if File_udMessages_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_udMessages_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*HashFact); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_udMessages_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Contact); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_udMessages_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SearchSend); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_udMessages_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SearchResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_udMessages_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LookupSend); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_udMessages_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LookupResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_udMessages_proto_rawDesc, + NumEnums: 0, + NumMessages: 6, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_udMessages_proto_goTypes, + DependencyIndexes: file_udMessages_proto_depIdxs, + MessageInfos: file_udMessages_proto_msgTypes, + }.Build() + File_udMessages_proto = out.File + file_udMessages_proto_rawDesc = nil + file_udMessages_proto_goTypes = nil + file_udMessages_proto_depIdxs = nil } diff --git a/ud/udMessages.proto b/ud/udMessages.proto index e6905f8359be96a7f331561495d44b20c7e1ab17..e80f56242b6efd85613dcaa1fff760de422b4df6 100644 --- a/ud/udMessages.proto +++ b/ud/udMessages.proto @@ -1,16 +1,15 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// - -// Call ./generate.sh to generate the protocol buffer code +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// syntax = "proto3"; -package parse; -option go_package = "ud"; +package ud; + +option go_package = "gitlab.com/elixxir/client/ud"; // Contains the Hash and its Type message HashFact { diff --git a/ud/utils_test.go b/ud/utils_test.go index 8a1fb7f826ddea93ebbaca272260a018eedef4d3..23de7e4c9eaa26c167f55eeaae452f9e48850e27 100644 --- a/ud/utils_test.go +++ b/ud/utils_test.go @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // +// Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package ud diff --git a/xxdk/backup.go b/xxdk/backup.go index f6bbf690545e94ac15fc04670cf0cd02af9101da..301bb48ba0c64368ad4fba0b64b7777f7dccb1d1 100644 --- a/xxdk/backup.go +++ b/xxdk/backup.go @@ -1,7 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2022 Privategrity Corporation / -// / -// All rights reserved. / +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package xxdk diff --git a/xxdk/cmix.go b/xxdk/cmix.go index 539c2610d55f23f3b26ed7aad70e0f563148cc39..a2b8b8b9ad3c6e7cc77c6eb325fabba17084cff0 100644 --- a/xxdk/cmix.go +++ b/xxdk/cmix.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package xxdk @@ -340,29 +340,28 @@ func (c *Cmix) GetErrorsChannel() <-chan interfaces.ClientError { // they are stopped if there is no internet access. // // Threads Started: -// - Network Follower (/network/follow.go) -// tracks the network events and hands them off to workers for handling. -// - Historical Round Retrieval (/network/rounds/historical.go) -// retrieves data about rounds that are too old to be stored by the client. -// - Message Retrieval Worker Group (/network/rounds/retrieve.go) -// requests all messages in a given round from the gateway of the last -// nodes. -// - Message Handling Worker Group (/network/message/handle.go) -// decrypts and partitions messages when signals via the Switchboard. -// - Health Tracker (/network/health), -// via the network instance, tracks the state of the network. -// - Garbled Messages (/network/message/garbled.go) -// can be signaled to check all recent messages that could be decoded. It -// uses a message store on disk for persistence. -// - Critical Messages (/network/message/critical.go) -// ensures all protocol layer mandatory messages are sent. It uses a -// message store on disk for persistence. -// - KeyExchange Trigger (/keyExchange/trigger.go) -// responds to sent rekeys and executes them. -// - KeyExchange Confirm (/keyExchange/confirm.go) -// responds to confirmations of successful rekey operations. -// - Auth Callback (/auth/callback.go) -// handles both auth confirm and requests. +// - Network Follower (/network/follow.go) +// tracks the network events and hands them off to workers for handling. +// - Historical Round Retrieval (/network/rounds/historical.go) +// retrieves data about rounds that are too old to be stored by the client. +// - Message Retrieval Worker Group (/network/rounds/retrieve.go) +// requests all messages in a given round from the gateway of the last nodes. +// - Message Handling Worker Group (/network/message/handle.go) +// decrypts and partitions messages when signals via the Switchboard. +// - Health Tracker (/network/health), +// via the network instance, tracks the state of the network. +// - Garbled Messages (/network/message/garbled.go) +// can be signaled to check all recent messages that could be decoded. It +// uses a message store on disk for persistence. +// - Critical Messages (/network/message/critical.go) +// ensures all protocol layer mandatory messages are sent. It uses a message +// store on disk for persistence. +// - KeyExchange Trigger (/keyExchange/trigger.go) +// responds to sent rekeys and executes them. +// - KeyExchange Confirm (/keyExchange/confirm.go) +// responds to confirmations of successful rekey operations. +// - Auth Callback (/auth/callback.go) +// handles both auth confirm and requests. func (c *Cmix) StartNetworkFollower(timeout time.Duration) error { jww.INFO.Printf( "StartNetworkFollower() \n\tTransmissionID: %s \n\tReceptionID: %s", @@ -375,7 +374,7 @@ func (c *Cmix) StartNetworkFollower(timeout time.Duration) error { // an error if the follower is in the wrong state to stop or if it fails to stop // it. // -// if the network follower is running and this fails, the client object will +// If the network follower is running and this fails, the client object will // most likely be in an unrecoverable state and need to be trashed. func (c *Cmix) StopNetworkFollower() error { jww.INFO.Printf("StopNetworkFollower()") @@ -398,6 +397,13 @@ func (c *Cmix) HasRunningProcessies() bool { return !c.followerServices.stoppable.IsStopped() } +// GetRunningProcesses returns the names of all running processes at the time +// of this call. Note that this list may change and is subject to race +// conditions if multiple threads are in the process of starting or stopping. +func (c *Cmix) GetRunningProcesses() []string { + return c.followerServices.stoppable.GetRunningProcesses() +} + // GetRoundEvents registers a callback for round events. func (c *Cmix) GetRoundEvents() interfaces.RoundEvents { jww.INFO.Printf("GetRoundEvents()") diff --git a/xxdk/compress_test.go b/xxdk/compress_test.go index 3361115fb8dca117c27e94dfa5dff4a6854955ad..abc64cc52fcfbf73ff9bb7e64f08fd6efa342240 100644 --- a/xxdk/compress_test.go +++ b/xxdk/compress_test.go @@ -1,7 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2022 Privategrity Corporation / -// / -// All rights reserved. / +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package xxdk diff --git a/xxdk/e2e.go b/xxdk/e2e.go index 4c2b9e22ca2e800e77489f69690092e13f6db6bc..a137abca793ecb00267571fc6a4ade03d374a1e3 100644 --- a/xxdk/e2e.go +++ b/xxdk/e2e.go @@ -1,7 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2022 Privategrity Corporation / -// / -// All rights reserved. / +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package xxdk @@ -102,7 +103,7 @@ func loginLegacy(net *Cmix, callbacks AuthCallbacks, return nil, err } - rsaKey, err := identity.GetRSAPrivatePem() + rsaKey, err := identity.GetRSAPrivateKey() if err != nil { return nil, err } @@ -116,7 +117,7 @@ func login(net *Cmix, callbacks AuthCallbacks, identity ReceptionIdentity, kv *versioned.KV, params E2EParams) (m *E2e, err error) { // Verify the passed-in ReceptionIdentity matches its properties - privatePem, err := identity.GetRSAPrivatePem() + privatePem, err := identity.GetRSAPrivateKey() if err != nil { return nil, err } @@ -246,7 +247,7 @@ func (m *E2e) ConstructProtoUserFile() ([]byte, error) { transIdentity := m.Cmix.GetTransmissionIdentity() receptionIdentity := m.GetReceptionIdentity() - privatePem, err := receptionIdentity.GetRSAPrivatePem() + privatePem, err := receptionIdentity.GetRSAPrivateKey() if err != nil { return nil, err } diff --git a/xxdk/event.go b/xxdk/event.go index d65f88c3519aa5ec8b4c5c832e95192180a84bf9..5eccd2d479e940a15c22437938d1e14d5be19d8c 100644 --- a/xxdk/event.go +++ b/xxdk/event.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package xxdk import ( diff --git a/xxdk/identity.go b/xxdk/identity.go index 9d646785fd71c713398036fd4dc8ae66ecbbc447..d0dee696806b356350ce9a6a7c095e3099ace67e 100644 --- a/xxdk/identity.go +++ b/xxdk/identity.go @@ -1,7 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2022 Privategrity Corporation / -// / -// All rights reserved. / +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package xxdk @@ -80,8 +81,8 @@ func (r ReceptionIdentity) GetDHKeyPrivate() (*cyclic.Int, error) { return dhKeyPriv, err } -// GetRSAPrivatePem returns the RSAPrivatePem. -func (r ReceptionIdentity) GetRSAPrivatePem() (*rsa.PrivateKey, error) { +// GetRSAPrivateKey returns the RSAPrivatePem. +func (r ReceptionIdentity) GetRSAPrivateKey() (*rsa.PrivateKey, error) { return rsa.LoadPrivateKeyFromPem(r.RSAPrivatePem) } diff --git a/xxdk/mnemonic.go b/xxdk/mnemonic.go index 3a2e2051b9485d225704c2896caa6da6319b5dc0..eee9abb936e3a630abb731c163638023045e9e74 100644 --- a/xxdk/mnemonic.go +++ b/xxdk/mnemonic.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package xxdk diff --git a/xxdk/mnemonic_test.go b/xxdk/mnemonic_test.go index 326e16dc22f36ee6b6d9e91ba189fba19cb5e5cd..d247fc2f393e06cd1a9f0710310bdc6076ef2508 100644 --- a/xxdk/mnemonic_test.go +++ b/xxdk/mnemonic_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package xxdk diff --git a/xxdk/ndf.go b/xxdk/ndf.go index 4cdccb6a23e853c68a5987d6f54624e65ae0dba9..6c0009cf6c7062ecd570c4590bd1043394b7915e 100644 --- a/xxdk/ndf.go +++ b/xxdk/ndf.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package xxdk diff --git a/xxdk/notifications.go b/xxdk/notifications.go index 17cfb113826b6caa3e2741919abbd455cfde5eb7..f5a9ce96b3cb34765aad2dd2311f0bfec59ded95 100644 --- a/xxdk/notifications.go +++ b/xxdk/notifications.go @@ -1,7 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2022 Privategrity Corporation / -// / -// All rights reserved. / +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package xxdk diff --git a/xxdk/params.go b/xxdk/params.go index 3313b265d1e3263140cc0a7672e8c12b26672835..7fe436a2c17eea97dd773fdc0ebadc3ee146917b 100644 --- a/xxdk/params.go +++ b/xxdk/params.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package xxdk diff --git a/xxdk/params_test.go b/xxdk/params_test.go index 2386b2c99c9b3a93cac29e1a2bc1d10b9c820c8d..93a6334b6b2de2001afa99704d24058e2ab6ffb5 100644 --- a/xxdk/params_test.go +++ b/xxdk/params_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package xxdk diff --git a/xxdk/permissioning.go b/xxdk/permissioning.go index e5f4032e24ff5b226e855fb9f3a9bf0fba8d6140..54429182de52454d36de0b93faac8f428af72e82 100644 --- a/xxdk/permissioning.go +++ b/xxdk/permissioning.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package xxdk diff --git a/xxdk/precan.go b/xxdk/precan.go index 12e7bee315825fa524ffb1079182395a4870348c..3e1a58256b1d1ed316ab5718d0d5248c71d64d13 100644 --- a/xxdk/precan.go +++ b/xxdk/precan.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package xxdk diff --git a/xxdk/services.go b/xxdk/services.go index 104362102a3fd6e35483df7208924c83b0a37d2c..840215dc1d3998ebc301766b6232ebef10384d39 100644 --- a/xxdk/services.go +++ b/xxdk/services.go @@ -1,3 +1,10 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package xxdk import ( diff --git a/xxdk/services_test.go b/xxdk/services_test.go index 580df8f5ad21ab015c281d4a9e2b4d51d4e6af66..18846b9c0c2d5d7d3ac63b98fa5ab378b691108c 100644 --- a/xxdk/services_test.go +++ b/xxdk/services_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package xxdk diff --git a/xxdk/status.go b/xxdk/status.go index 92e1475de1d6bd3f43676ab90554dfc5665b524b..6b63a523b069fdd1a9614324a4fcc427fe52fa6c 100644 --- a/xxdk/status.go +++ b/xxdk/status.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package xxdk diff --git a/xxdk/user.go b/xxdk/user.go index fbf9d339fe5b39b9cde45fa4231e37724222be49..b9fe69e58d529d76f2623880c0fdcef764a246e2 100644 --- a/xxdk/user.go +++ b/xxdk/user.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package xxdk diff --git a/xxdk/utils.go b/xxdk/utils.go index 869d9529d111817805fe424c598c07fe5beb6d59..ccb6e3373274e2669a63238b9a34fdfecf0ea0ec 100644 --- a/xxdk/utils.go +++ b/xxdk/utils.go @@ -1,7 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2022 Privategrity Corporation / -// / -// All rights reserved. / +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // //////////////////////////////////////////////////////////////////////////////// // Provides various utility functions for access over the bindings diff --git a/xxdk/utilsInterfaces_test.go b/xxdk/utilsInterfaces_test.go index 29317d133e3031c8af10eb945ad6fc726d174c1e..4fbf3852387c7c095934c2fbf65f388cfa046e2f 100644 --- a/xxdk/utilsInterfaces_test.go +++ b/xxdk/utilsInterfaces_test.go @@ -1,9 +1,10 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + package xxdk import ( @@ -108,13 +109,20 @@ func (t *testNetworkManagerGeneric) AddFingerprint(identity *id.ID, fingerprint } func (t *testNetworkManagerGeneric) Send(*id.ID, format.Fingerprint, - message.Service, []byte, []byte, cmix.CMIXParams) (id.Round, + message.Service, []byte, []byte, cmix.CMIXParams) (rounds.Round, ephemeral.Id, error) { - return id.Round(0), ephemeral.Id{}, nil + return rounds.Round{}, ephemeral.Id{}, nil +} + +func (t *testNetworkManagerGeneric) SendWithAssembler(recipient *id.ID, assembler cmix.MessageAssembler, + cmixParams cmix.CMIXParams) (rounds.Round, ephemeral.Id, error) { + + return rounds.Round{}, ephemeral.Id{}, nil } + func (t *testNetworkManagerGeneric) SendMany(messages []cmix.TargetedCmixMessage, - p cmix.CMIXParams) (id.Round, []ephemeral.Id, error) { - return 0, []ephemeral.Id{}, nil + p cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error) { + return rounds.Round{}, []ephemeral.Id{}, nil } func (t *testNetworkManagerGeneric) GetInstance() *network.Instance { return t.instance @@ -175,8 +183,7 @@ func (t *testNetworkManagerGeneric) GetIdentity(get *id.ID) ( return identity.TrackedID{}, nil } func (t *testNetworkManagerGeneric) GetRoundResults(timeout time.Duration, - roundCallback cmix.RoundEventCallback, roundList ...id.Round) error { - return nil + roundCallback cmix.RoundEventCallback, roundList ...id.Round) { } func (t *testNetworkManagerGeneric) HasNode(nid *id.ID) bool { return false } func (t *testNetworkManagerGeneric) IsHealthy() bool { return true } diff --git a/xxdk/utils_test.go b/xxdk/utils_test.go index f5ca8f965078da696a3aadbe0dd1578595339a98..40098e5beb2abf5b05bc1556e232e373a032c1dd 100644 --- a/xxdk/utils_test.go +++ b/xxdk/utils_test.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package xxdk diff --git a/xxdk/version_vars.go b/xxdk/version_vars.go index 1107c2c1141673d1bbe3b35aafb509177bac1cb8..61bd87da81f93ce196ac84a628a11107357ecb24 100644 --- a/xxdk/version_vars.go +++ b/xxdk/version_vars.go @@ -1,10 +1,10 @@ // Code generated by go generate; DO NOT EDIT. // This file was generated by robots at -// 2022-08-03 11:29:24.178017 -0500 CDT m=+0.037661773 +// 2022-09-15 10:52:12.1953796 -0700 PDT m=+0.451573601 package xxdk -const GITVERSION = `97f2ad74 Merge branch 'feature/roundpickup' into 'release'` +const GITVERSION = `55b66f6b Update proto files` const SEMVER = "4.2.0" const DEPENDENCIES = `module gitlab.com/elixxir/client @@ -16,17 +16,18 @@ require ( github.com/golang/protobuf v1.5.2 github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 github.com/pkg/errors v0.9.1 + github.com/pkg/profile v1.6.0 github.com/spf13/cobra v1.5.0 github.com/spf13/jwalterweatherman v1.1.0 github.com/spf13/viper v1.12.0 gitlab.com/elixxir/bloomfilter v0.0.0-20211222005329-7d931ceead6f - gitlab.com/elixxir/comms v0.0.4-0.20220603231314-e47e4af13326 - gitlab.com/elixxir/crypto v0.0.7-0.20220606201132-c370d5039cea - gitlab.com/elixxir/ekv v0.1.7 - gitlab.com/elixxir/primitives v0.0.3-0.20220606195757-40f7a589347f - gitlab.com/xx_network/comms v0.0.4-0.20220630163702-f3d372ef6acd - gitlab.com/xx_network/crypto v0.0.5-0.20220729193517-1e5e96f39f6e - gitlab.com/xx_network/primitives v0.0.4-0.20220712193914-aebd8544396e + gitlab.com/elixxir/comms v0.0.4-0.20220914220142-601071b77d78 + gitlab.com/elixxir/crypto v0.0.7-0.20220901215826-1ceaeb59081f + gitlab.com/elixxir/ekv v0.2.1 + gitlab.com/elixxir/primitives v0.0.3-0.20220901220638-1acc75fabdc6 + gitlab.com/xx_network/comms v0.0.4-0.20220914220351-2e461edbfe48 + gitlab.com/xx_network/crypto v0.0.5-0.20220902182733-69aad094b487 + gitlab.com/xx_network/primitives v0.0.4-0.20220902183448-319596e2fec8 go.uber.org/ratelimit v0.2.0 golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa golang.org/x/net v0.0.0-20220802222814-0bcc04d9c69b diff --git a/xxmutils/restoreContacts.go b/xxmutils/restoreContacts.go index 9f43d294e35b7f6d601ba780b93b69bb0966a002..0ee9363130c1d302a822d1509447f52cd5ae1e56 100644 --- a/xxmutils/restoreContacts.go +++ b/xxmutils/restoreContacts.go @@ -1,9 +1,9 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// package xxmutils