diff --git a/api/authenticatedChannel.go b/api/authenticatedChannel.go index 01d486c577d8c50752f19e706511fd71455eaba7..a9125a0306b5f4bcbb0229320dd495c25bffb103 100644 --- a/api/authenticatedChannel.go +++ b/api/authenticatedChannel.go @@ -7,6 +7,7 @@ import ( "gitlab.com/elixxir/client/interfaces" "gitlab.com/elixxir/client/interfaces/contact" "gitlab.com/elixxir/client/storage/e2e" + "gitlab.com/elixxir/primitives/fact" "gitlab.com/xx_network/primitives/id" ) @@ -110,6 +111,6 @@ func (c *Client) MakePrecannedContact(precannedID uint) contact.Contact { ID: precanned.ID, DhPubKey: partnerPubKey, OwnershipProof: nil, - Facts: make([]contact.Fact, 0), + Facts: make([]fact.Fact, 0), } } \ No newline at end of file diff --git a/api/version.go b/api/version.go index d8a8e2a056308b8a6f02f3b20f37bf68fa37d339..30ddb01b686346e1f3d28442ded20f2ad3ab6294 100644 --- a/api/version.go +++ b/api/version.go @@ -32,7 +32,7 @@ func (c *Client) checkVersion() error { "\tClient: %s", netVersion.String(), clientVersion.String()) } } else { - jww.WARN.Printf("Network requires no minnimim version") + jww.INFO.Printf("Network requires no minimum version") } return nil diff --git a/auth/callback.go b/auth/callback.go index f7c522e3d22911a835f9ef2694cfea717a182743..060d74030f73fdf7e91e23827635b3ec3e8dfcd0 100644 --- a/auth/callback.go +++ b/auth/callback.go @@ -9,7 +9,9 @@ import ( "gitlab.com/elixxir/client/storage/auth" "gitlab.com/elixxir/client/storage/e2e" "gitlab.com/elixxir/crypto/cyclic" + "gitlab.com/elixxir/crypto/diffieHellman" cAuth "gitlab.com/elixxir/crypto/e2e/auth" + "gitlab.com/elixxir/primitives/fact" "gitlab.com/elixxir/primitives/format" "strings" ) @@ -28,11 +30,13 @@ func (m *Manager) StartProcessies() stoppable.Stoppable { //lookup the message, check if it is an auth request cmixMsg := format.Unmarshal(msg.Payload) fp := cmixMsg.GetKeyFP() + jww.INFO.Printf("RAW AUTH FP: %v", fp) // this takes the request lock if it is a specific fp, // all exits after this need to call fail or Delete if it is // specific fpType, sr, myHistoricalPrivKey, err := authStore.GetFingerprint(fp) if err != nil { + jww.INFO.Printf("FINGERPRINT FAILURE: %s", err.Error()) // if the lookup fails, ignore the message. It is likely // garbled or for a different protocol break @@ -64,6 +68,11 @@ func (m *Manager) handleRequest(cmixMsg format.Message, return } + myPubKey := diffieHellman.GeneratePublicKey(myHistoricalPrivKey, grp) + + jww.INFO.Printf("handleRequest MYPUBKEY: %v", myPubKey.Bytes()) + jww.INFO.Printf("handleRequest PARTNERPUBKEY: %v", partnerPubKey.Bytes()) + //decrypt the message success, payload := cAuth.Decrypt(myHistoricalPrivKey, partnerPubKey, baseFmt.GetSalt(), baseFmt.GetEcrPayload(), @@ -112,7 +121,7 @@ func (m *Manager) handleRequest(cmixMsg format.Message, //check if the relationship already exists, rType, sr2, _, err := m.storage.Auth().GetRequest(partnerID) if err != nil && !strings.Contains(err.Error(), auth.NoRequest) { - // if another error is recieved, print it and exist + // if another error is recieved, print it and exit jww.WARN.Printf("Recieved new Auth request for %s, "+ "internal lookup produced bad result: %+v", partnerID, err) @@ -140,7 +149,7 @@ func (m *Manager) handleRequest(cmixMsg format.Message, } //process the inner payload - facts, msg, err := contact.UnstringifyFactList( + facts, msg, err := fact.UnstringifyFactList( string(requestFmt.msgPayload)) if err != nil { jww.WARN.Printf("failed to parse facts and message "+ @@ -193,6 +202,9 @@ func (m *Manager) handleConfirm(cmixMsg format.Message, sr *auth.SentRequest, return } + jww.INFO.Printf("handleConfirm PARTNERPUBKEY: %v", partnerPubKey.Bytes()) + jww.INFO.Printf("handleConfirm SRMYPUBKEY: %v", sr.GetMyPubKey().Bytes()) + // decrypt the payload success, payload := cAuth.Decrypt(sr.GetMyPrivKey(), partnerPubKey, baseFmt.GetSalt(), baseFmt.GetEcrPayload(), @@ -253,7 +265,7 @@ func (m *Manager) doConfirm(sr *auth.SentRequest, grp *cyclic.Group, ID: sr.GetPartner().DeepCopy(), DhPubKey: partnerPubKey.DeepCopy(), OwnershipProof: copySlice(ownershipProof), - Facts: make([]contact.Fact, 0), + Facts: make([]fact.Fact, 0), } // fixme: if a crash occurs before or during the calls, the notification @@ -291,4 +303,4 @@ func handleBaseFormat(cmixMsg format.Message, grp *cyclic.Group) (baseFormat, } partnerPubKey := grp.NewIntFromBytes(baseFmt.pubkey) return baseFmt, partnerPubKey, nil -} \ No newline at end of file +} diff --git a/auth/callbacks.go b/auth/callbacks.go index ab6a2ead168f2ba363373371e6d9c43a61707cb0..6eb758af2a1aad2030387e238ca6ca8f98d1958d 100644 --- a/auth/callbacks.go +++ b/auth/callbacks.go @@ -63,7 +63,7 @@ func (cm *callbackMap) Get(id *id.ID) []interface{} { if specific, ok := cm.specificCallback[*id]; ok { cbList = append(cbList, specific) } else { - cbList = append(cbList, cm.generalCallback) + cbList = append(cbList, cm.generalCallback...) } return cbList diff --git a/auth/confirm.go b/auth/confirm.go index 57b230e171fe1356aa048a23b3ada37bdff0944e..2ffa7a979f3c547c16928c08ca692eab85fda8bd 100644 --- a/auth/confirm.go +++ b/auth/confirm.go @@ -79,7 +79,7 @@ func ConfirmRequestAuth(partner contact.Contact, rng io.Reader, //encrypt the payload ecrPayload, mac := cAuth.Encrypt(newPrivKey, partner.DhPubKey, - salt, ecrFmt.payload, grp) + salt, ecrFmt.data, grp) //get the fingerprint from the old ownership proof fp := cAuth.MakeOwnershipProofFP(storedContact.OwnershipProof) @@ -92,6 +92,7 @@ func ConfirmRequestAuth(partner contact.Contact, rng io.Reader, cmixMsg.SetKeyFP(fp) cmixMsg.SetMac(mac) cmixMsg.SetContents(baseFmt.Marshal()) + cmixMsg.SetRecipientID(partner.ID) // fixme: channel can get into a bricked state if the first save occurs and // the second does not or the two occur and the storage into critical @@ -123,7 +124,7 @@ func ConfirmRequestAuth(partner contact.Contact, rng io.Reader, if err != nil { // if the send fails just set it to failed, it will but automatically // retried - jww.ERROR.Printf("request failed to transmit, will be "+ + jww.ERROR.Printf("auth confirm failed to transmit, will be "+ "handled on reconnect: %+v", err) storage.GetCriticalRawMessages().Failed(cmixMsg) } @@ -137,7 +138,7 @@ func ConfirmRequestAuth(partner contact.Contact, rng io.Reader, success, _, _ := utility.TrackResults(sendResults, 1) if !success { - jww.ERROR.Printf("request failed to transmit, will be " + + jww.ERROR.Printf("auth confirm failed to transmit, will be " + "handled on reconnect") storage.GetCriticalRawMessages().Failed(cmixMsg) } else { diff --git a/auth/fmt.go b/auth/fmt.go index 5ee0c4874a28a63edbd0b66f74fed704ec3d5797..04605c95772077de79b2392763330991424e7335 100644 --- a/auth/fmt.go +++ b/auth/fmt.go @@ -177,7 +177,7 @@ func newRequestFormat(ecrFmt ecrFormat) (requestFormat, error) { } rf.id = rf.payload[:id.ArrIDLen] - rf.id = rf.payload[id.ArrIDLen:] + rf.msgPayload = rf.payload[id.ArrIDLen:] return rf, nil } diff --git a/auth/manager.go b/auth/manager.go index 4fbfd6bed3ae20db24badf4ff76fb3f8533a61d2..16222cbbb65aa2ee38106a18d0e3635330189eec 100644 --- a/auth/manager.go +++ b/auth/manager.go @@ -4,6 +4,7 @@ import ( "gitlab.com/elixxir/client/interfaces" "gitlab.com/elixxir/client/interfaces/message" "gitlab.com/elixxir/client/storage" + "gitlab.com/elixxir/client/switchboard" "gitlab.com/xx_network/primitives/id" ) @@ -27,7 +28,7 @@ func NewManager(sw interfaces.Switchboard, storage *storage.Session, net: net, } - sw.RegisterChannel("Auth", &id.ID{}, message.Raw, m.rawMessages) + sw.RegisterChannel("Auth", switchboard.AnyUser(), message.Raw, m.rawMessages) return m } diff --git a/auth/request.go b/auth/request.go index ba231d297821e97f3e06c819bb109867cd585078..ff2811c493a4be0df86c72df69e21241a1dab1e7 100644 --- a/auth/request.go +++ b/auth/request.go @@ -1,8 +1,8 @@ package auth import ( - ds "gitlab.com/elixxir/comms/network/dataStructures" "github.com/pkg/errors" + jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/interfaces" "gitlab.com/elixxir/client/interfaces/contact" "gitlab.com/elixxir/client/interfaces/params" @@ -10,6 +10,7 @@ import ( "gitlab.com/elixxir/client/storage" "gitlab.com/elixxir/client/storage/auth" "gitlab.com/elixxir/client/storage/e2e" + ds "gitlab.com/elixxir/comms/network/dataStructures" "gitlab.com/elixxir/crypto/diffieHellman" cAuth "gitlab.com/elixxir/crypto/e2e/auth" "gitlab.com/elixxir/primitives/format" @@ -17,10 +18,9 @@ import ( "io" "strings" "time" - jww "github.com/spf13/jwalterweatherman" ) -const eol = string(0x0a) +const terminator = ";" func RequestAuth(partner, me contact.Contact, message string, rng io.Reader, storage *storage.Session, net interfaces.NetworkManager) error { @@ -46,21 +46,25 @@ func RequestAuth(partner, me contact.Contact, message string, rng io.Reader, } // check that the message is properly formed - if strings.Contains(message, eol) { - return errors.Errorf("Message cannot contain 'EOL'") + if strings.Contains(message, terminator) { + return errors.Errorf("Message cannot contain '%s'", terminator) } //lookup if an ongoing request is occurring rqType, _, _, err := storage.Auth().GetRequest(partner.ID) - if err != nil && !strings.Contains(err.Error(), auth.NoRequest) { - return errors.WithMessage(err, "Error on lookup of potential "+ - "existing request") - } else if rqType == auth.Receive { - return errors.WithMessage(err, "Cannot send a request after"+ - "receiving a request") - } else if rqType == auth.Sent { - return errors.WithMessage(err, "Cannot send a request after"+ - "already sending one") + if err != nil && strings.Contains(err.Error(), auth.NoRequest) { + err = nil + } + if err != nil { + if rqType == auth.Receive { + return errors.WithMessage(err, + "Cannot send a request after "+ + "receiving a request") + } else if rqType == auth.Sent { + return errors.WithMessage(err, + "Cannot send a request after "+ + "already sending one") + } } grp := storage.E2e().GetGroup() @@ -76,7 +80,7 @@ func RequestAuth(partner, me contact.Contact, message string, rng io.Reader, //check the payload fits facts := me.Facts.Stringify() - msgPayload := facts + message + eol + msgPayload := facts + message + terminator msgPayloadBytes := []byte(msgPayload) if len(msgPayloadBytes) > requestFmt.MsgPayloadLen() { @@ -101,28 +105,34 @@ func RequestAuth(partner, me contact.Contact, message string, rng io.Reader, newPrivKey := diffieHellman.GeneratePrivateKey(256, grp, rng) newPubKey := diffieHellman.GeneratePublicKey(newPrivKey, grp) + jww.INFO.Printf("RequestAuth MYPUBKEY: %v", newPubKey.Bytes()) + jww.INFO.Printf("RequestAuth THEIRPUBKEY: %v", partner.DhPubKey.Bytes()) + /*encrypt payload*/ requestFmt.SetID(storage.GetUser().ID) requestFmt.SetMsgPayload(msgPayloadBytes) ecrFmt.SetOwnership(ownership) ecrPayload, mac := cAuth.Encrypt(newPrivKey, partner.DhPubKey, - salt, ecrFmt.payload, grp) - fp := cAuth.MakeOwnershipProofFP(ownership) + salt, ecrFmt.data, grp) + confirmFp := cAuth.MakeOwnershipProofFP(ownership) + requestfp := cAuth.MakeRequestFingerprint(partner.DhPubKey) /*construct message*/ baseFmt.SetEcrPayload(ecrPayload) baseFmt.SetSalt(salt) baseFmt.SetPubKey(newPubKey) - cmixMsg.SetKeyFP(fp) + cmixMsg.SetKeyFP(requestfp) cmixMsg.SetMac(mac) cmixMsg.SetContents(baseFmt.Marshal()) + cmixMsg.SetRecipientID(partner.ID) + jww.INFO.Printf("PARTNER ID: %s", partner.ID) /*store state*/ //fixme: channel is bricked if the first store succedes but the second fails //store the in progress auth err = storage.Auth().AddSent(partner.ID, partner.DhPubKey, newPrivKey, - newPrivKey, fp) + newPrivKey, confirmFp) if err != nil { return errors.Errorf("Failed to store auth request: %s", err) } @@ -130,12 +140,17 @@ func RequestAuth(partner, me contact.Contact, message string, rng io.Reader, //store the message as a critical message so it will always be sent storage.GetCriticalRawMessages().AddProcessing(cmixMsg) + //jww.INFO.Printf("CMIX MESSAGE 1: %s, %v, %v, %v", cmixMsg.GetRecipientID(), + // cmixMsg.GetKeyFP(), cmixMsg.GetMac(), cmixMsg.GetContents()) + jww.INFO.Printf("CMIX MESSAGE FP: %s, %v", cmixMsg.GetRecipientID(), + cmixMsg.GetKeyFP()) + /*send message*/ round, err := net.SendCMIX(cmixMsg, params.GetDefaultCMIX()) if err != nil { // if the send fails just set it to failed, it will but automatically // retried - jww.ERROR.Printf("request failed to transmit, will be "+ + jww.ERROR.Printf("auth request failed to transmit, will be "+ "handled on reconnect: %+v", err) storage.GetCriticalRawMessages().Failed(cmixMsg) } @@ -149,7 +164,7 @@ func RequestAuth(partner, me contact.Contact, message string, rng io.Reader, success, _, _ := utility.TrackResults(sendResults, 1) if !success { - jww.ERROR.Printf("request failed to transmit, will be " + + jww.ERROR.Printf("auth request failed to transmit, will be " + "handled on reconnect") storage.GetCriticalRawMessages().Failed(cmixMsg) } else { diff --git a/bindings/contact.go b/bindings/contact.go index 012eada71c84fc1a196cfc95acb24268b6a2f8f9..2bcc1d2b9c627a27ef0f091709fb4d458efe669e 100644 --- a/bindings/contact.go +++ b/bindings/contact.go @@ -3,11 +3,12 @@ package bindings import ( "errors" "gitlab.com/elixxir/client/interfaces/contact" + "gitlab.com/elixxir/primitives/fact" ) /* fact object*/ type Fact struct { - f *contact.Fact + f *fact.Fact } func (f *Fact) Get() string { @@ -61,13 +62,13 @@ func (fl *FactList) Get(i int) Fact { return Fact{f: &(fl.c.Facts)[i]} } -func (fl *FactList) Add(fact string, factType int) error { - ft := contact.FactType(factType) +func (fl *FactList) Add(factData string, factType int) error { + ft := fact.FactType(factType) if !ft.IsValid() { return errors.New("Invalid fact type") } - fl.c.Facts = append(fl.c.Facts, contact.Fact{ - Fact: fact, + fl.c.Facts = append(fl.c.Facts, fact.Fact{ + Fact: factData, T: ft, }) return nil diff --git a/cmd/root.go b/cmd/root.go index d20a4845d2e4f8e875f7b74a87e7d3b4dbeab5f6..eef8d776d18f773bf9e97b78c38aabe99437edd6 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -16,6 +16,7 @@ import ( jww "github.com/spf13/jwalterweatherman" "github.com/spf13/viper" "gitlab.com/elixxir/client/api" + "gitlab.com/elixxir/client/interfaces/contact" "gitlab.com/elixxir/client/interfaces/message" "gitlab.com/elixxir/client/interfaces/params" "gitlab.com/elixxir/client/switchboard" @@ -37,62 +38,6 @@ func Execute() { } } -// func setKeyParams(client *api.Client) { -// jww.DEBUG.Printf("Trying to parse key parameters...") -// minKeys, err := strconv.Atoi(keyParams[0]) -// if err != nil { -// return -// } - -// maxKeys, err := strconv.Atoi(keyParams[1]) -// if err != nil { -// return -// } - -// numRekeys, err := strconv.Atoi(keyParams[2]) -// if err != nil { -// return -// } - -// ttlScalar, err := strconv.ParseFloat(keyParams[3], 64) -// if err != nil { -// return -// } - -// minNumKeys, err := strconv.Atoi(keyParams[4]) -// if err != nil { -// return -// } - -// jww.DEBUG.Printf("Setting key generation parameters: %d, %d, %d, %f, %d", -// minKeys, maxKeys, numRekeys, ttlScalar, minNumKeys) - -// params := client.GetKeyParams() -// params.MinKeys = uint16(minKeys) -// params.MaxKeys = uint16(maxKeys) -// params.NumRekeys = uint16(numRekeys) -// params.TTLScalar = ttlScalar -// params.MinNumKeys = uint16(minNumKeys) -// } - -// type userSearcher struct { -// foundUserChan chan []byte -// } - -// func newUserSearcher() api.SearchCallback { -// us := userSearcher{} -// us.foundUserChan = make(chan []byte) -// return &us -// } - -// func (us *userSearcher) Callback(userID, pubKey []byte, err error) { -// if err != nil { -// jww.ERROR.Printf("Could not find searched user: %+v", err) -// } else { -// us.foundUserChan <- userID -// } -// } - // rootCmd represents the base command when called without any subcommands var rootCmd = &cobra.Command{ Use: "client", @@ -137,6 +82,7 @@ var rootCmd = &cobra.Command{ user := client.GetUser() jww.INFO.Printf("User: %s", user.ID) + writeContact(user.GetContact()) // Set up reception handler swboard := client.GetSwitchboard() @@ -145,6 +91,24 @@ var rootCmd = &cobra.Command{ switchboard.AnyUser(), message.Text, recvCh) jww.INFO.Printf("Message ListenerID: %v", listenerID) + // Set up auth request handler, which simply prints the + // user id of the requestor. + authMgr := client.GetAuthRegistrar() + authMgr.AddGeneralRequestCallback(printChanRequest) + + // If unsafe channels, add auto-acceptor + if viper.GetBool("unsafe-channel-creation") { + authMgr.AddGeneralRequestCallback(func( + requestor contact.Contact, message string) { + jww.INFO.Printf("Got Request: %s", requestor.ID) + err := client.ConfirmAuthenticatedChannel( + requestor) + if err != nil { + jww.FATAL.Panicf("%+v", err) + } + }) + } + err = client.StartNetworkFollower() if err != nil { jww.FATAL.Panicf("%+v", err) @@ -157,19 +121,36 @@ var rootCmd = &cobra.Command{ // Send Messages msgBody := viper.GetString("message") - recipientID, isPrecanPartner := parseRecipient( - viper.GetString("destid")) - // Send unsafe messages or not? - unsafe := viper.GetBool("unsafe") - if !unsafe { - addAuthenticatedChannel(client, recipientID, - isPrecanPartner) + isPrecanPartner := false + recipientContact := readContact() + recipientID := recipientContact.ID + + // Try to get recipientID from destid + if recipientID == nil { + recipientID, isPrecanPartner = parseRecipient( + viper.GetString("destid")) } + // Set it to myself if recipientID == nil { jww.INFO.Printf("sending message to self") recipientID = user.ID + recipientContact = user.GetContact() + } + + time.Sleep(10 * time.Second) + + // Accept auth request for this recipient + if viper.GetBool("accept-channel") { + acceptChannel(client, recipientID) + } + + // Send unsafe messages or not? + unsafe := viper.GetBool("unsafe") + if !unsafe { + addAuthenticatedChannel(client, recipientID, + recipientContact, isPrecanPartner) } msg := message.Send{ @@ -215,6 +196,7 @@ var rootCmd = &cobra.Command{ case m := <-recvCh: fmt.Printf("Message received: %s\n", string( m.Payload)) + //fmt.Printf("%s", m.Timestamp) receiveCnt++ if receiveCnt == expectedCnt { done = true @@ -226,8 +208,62 @@ var rootCmd = &cobra.Command{ }, } +func writeContact(c contact.Contact) { + outfilePath := viper.GetString("writeContact") + if outfilePath == "" { + return + } + cBytes, err := c.Marshal() + if err != nil { + jww.FATAL.Panicf("%+v", err) + } + err = ioutil.WriteFile(outfilePath, cBytes, 0644) + if err != nil { + jww.FATAL.Panicf("%+v", err) + } +} + +func readContact() contact.Contact { + inputFilePath := viper.GetString("destfile") + if inputFilePath == "" { + return contact.Contact{} + } + data, err := ioutil.ReadFile(inputFilePath) + if err != nil { + jww.FATAL.Panicf("%+v", err) + } + c, err := contact.Unmarshal(data) + if err != nil { + jww.FATAL.Panicf("%+v", err) + } + return c +} + +func acceptChannel(client *api.Client, recipientID *id.ID) { + recipientContact, err := client.GetAuthenticatedChannelRequest( + recipientID) + if err != nil { + jww.FATAL.Panicf("%+v", err) + } + err = client.ConfirmAuthenticatedChannel( + recipientContact) + if err != nil { + jww.FATAL.Panicf("%+v", err) + } +} + +func printChanRequest(requestor contact.Contact, message string) { + msg := fmt.Sprintf("Authentication channel request from: %s\n", + requestor.ID) + jww.INFO.Printf(msg) + fmt.Printf(msg) + msg = fmt.Sprintf("Authentication channel request message: %s", message) + jww.INFO.Printf(msg) + fmt.Printf(msg) +} + func addAuthenticatedChannel(client *api.Client, recipientID *id.ID, - isPrecanPartner bool) { + recipient contact.Contact, isPrecanPartner bool) { if client.HasAuthenticatedChannel(recipientID) { jww.INFO.Printf("Authenticated channel already in place for %s", recipientID) @@ -247,7 +283,22 @@ func addAuthenticatedChannel(client *api.Client, recipientID *id.ID, jww.FATAL.Panicf("User did not allow channel creation!") } - msg := fmt.Sprintf("Adding authenticated channel for: %s\n", + // Check if a channel exists for this recipientID + recipientContact, err := client.GetAuthenticatedChannelRequest( + recipientID) + if err == nil { + jww.INFO.Printf("Accepting existing channel request for %s", + recipientID) + err := client.ConfirmAuthenticatedChannel(recipientContact) + if err != nil { + jww.FATAL.Panicf("%+v", err) + } + return + } else { + recipientContact = recipient + } + + msg := fmt.Sprintf("Adding authenticated channel for: %s", recipientID) jww.INFO.Printf(msg) fmt.Printf(msg) @@ -269,8 +320,18 @@ func addAuthenticatedChannel(client *api.Client, recipientID *id.ID, preBytes, idBytes) } } + } else if recipientContact.ID != nil && recipientContact.DhPubKey != nil { + me := client.GetUser().GetContact() + jww.INFO.Printf("Requesting auth channel from: %s", + recipientID) + err := client.RequestAuthenticatedChannel(recipientContact, + me, msg) + if err != nil { + jww.FATAL.Panicf("%+v", err) + } } else { - jww.FATAL.Panicf("e2e unimplemented") + jww.ERROR.Printf("Could not add auth channel for %s", + recipientID) } } @@ -282,7 +343,7 @@ func waitUntilConnected(connected chan bool) { for !isConnected { select { case isConnected = <-connected: - jww.INFO.Printf("health status: %v\n", + jww.INFO.Printf("Network Status: %v\n", isConnected) break case <-timeoutTimer.C: @@ -300,7 +361,7 @@ func waitUntilConnected(connected chan bool) { if isConnected != prev { prev = isConnected jww.INFO.Printf( - "health status changed: %v\n", + "Network Status Changed: %v\n", isConnected) } break @@ -461,6 +522,10 @@ func init() { "client storage") viper.BindPFlag("session", rootCmd.Flags().Lookup("session")) + rootCmd.Flags().StringP("writeContact", "w", + "", "Write the contact file for this user to this file") + viper.BindPFlag("writeContact", rootCmd.Flags().Lookup("writeContact")) + rootCmd.Flags().StringP("password", "p", "", "Password to the session file") viper.BindPFlag("password", rootCmd.Flags().Lookup("password")) @@ -489,6 +554,10 @@ func init() { "'0x' or 'b64:' for hex and base64 representations)") viper.BindPFlag("destid", rootCmd.Flags().Lookup("destid")) + rootCmd.Flags().StringP("destfile", "", + "", "Read this contact file for the destination id") + viper.BindPFlag("destfile", rootCmd.Flags().Lookup("destfile")) + rootCmd.Flags().UintP("sendCount", "", 1, "The number of times to send the message") viper.BindPFlag("sendCount", rootCmd.Flags().Lookup("sendCount")) @@ -510,11 +579,15 @@ func init() { rootCmd.Flags().BoolP("unsafe-channel-creation", "", false, "Turns off the user identity authenticated channel check, "+ - "which prompts the user to answer yes or no "+ - "to approve authenticated channels") + "automatically approving authenticated channels") viper.BindPFlag("unsafe-channel-creation", rootCmd.Flags().Lookup("unsafe-channel-creation")) + rootCmd.Flags().BoolP("accept-channel", "", false, + "Accept the channel request for the corresponding recipient ID") + viper.BindPFlag("accept-channel", + rootCmd.Flags().Lookup("accept-channel")) + // Cobra also supports local flags, which will only run // when this action is called directly. // rootCmd.Flags().StringVarP(¬ificationToken, "nbRegistration", "x", "", diff --git a/go.mod b/go.mod index f1c2cc7ad37025d48fba7a0776e5107926cde051..84ed766a410405b2465dc08a5aac8068b2034814 100644 --- a/go.mod +++ b/go.mod @@ -17,11 +17,12 @@ require ( github.com/spf13/jwalterweatherman v1.1.0 github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.7.1 - gitlab.com/elixxir/comms v0.0.4-0.20201111205457-b073b28c367a - gitlab.com/elixxir/crypto v0.0.5-0.20201110193609-6b5e881867b4 + gitlab.com/elixxir/bloomfilter v0.0.0-20200930191214-10e9ac31b228 + gitlab.com/elixxir/comms v0.0.3 + gitlab.com/elixxir/crypto v0.0.5-0.20201109234712-7e64de16970d gitlab.com/elixxir/ekv v0.1.3 gitlab.com/elixxir/primitives v0.0.3-0.20201116174806-97f190989704 - gitlab.com/xx_network/comms v0.0.4-0.20201110022115-4a6171cad07d + gitlab.com/xx_network/comms v0.0.3 gitlab.com/xx_network/crypto v0.0.4 gitlab.com/xx_network/primitives v0.0.2 golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000000000000000000000000000000000000..5e5de048d2a894d2bb57d6dcccd3d2cbc5501294 --- /dev/null +++ b/go.sum @@ -0,0 +1,466 @@ +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= +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/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +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/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +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-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +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-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +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 h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0 h1:oOuy+ugB+P/kBdUnG5QaMXSIyJ1q38wWSojYCb3z5VQ= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1 h1:ZFgWrT+bLgsYPirOnRfKLYJLvssAegOj/hgyMFdJZe0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +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= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +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= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00 h1:l5lAOZEym3oK3SQ2HBHWsJUfbNBiTXJDeW2QDxw9AQ0= +github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc/grpc-go v1.27.1 h1:EluyjU5nlbuNJSEktNl600PIpzbO2OcvZWfWV1jFvKM= +github.com/grpc/grpc-go v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= +github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +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.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/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/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= +github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.4 h1:8KGKTcQQGm0Kv7vEbKFErAoAOFyyacLStRtQSeYtvkY= +github.com/magiconair/properties v1.8.4/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +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/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +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 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.3.3 h1:SzB1nHZ2Xi+17FP0zVQBHIZqvwRN9408fJO8h+eeNA8= +github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNCRM= +github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= +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/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= +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/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/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/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +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/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/assertions v1.0.1 h1:voD4ITNjPL5jjBfgR/r8fPIIBrliWrWHeiJApdr3r4w= +github.com/smartystreets/assertions v1.0.1/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= +github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/afero v1.4.0 h1:jsLTaI1zwYO3vjrzHalkVcIHXTNmdQFepW4OI8H3+x8= +github.com/spf13/afero v1.4.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= +github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8= +github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +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.3/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.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= +github.com/spf13/viper v1.7.1 h1:pM5oEahlgWv/WnHXpgbKz7iLIxRf65tye2Ci+XFK5sk= +github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= +github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/zeebo/assert v0.0.0-20181109011804-10f827ce2ed6/go.mod h1:yssERNPivllc1yU3BvpjYI5BUW+zglcz6QWqeVRL5t0= +github.com/zeebo/assert v1.1.0 h1:hU1L1vLTHsnO8x8c9KAR5GmM5QscxHg5RNU5z5qbUWY= +github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= +github.com/zeebo/blake3 v0.0.4 h1:vtZ4X8B2lKXZFg2Xyg6Wo36mvmnJvc2VQYTtA4RDCkI= +github.com/zeebo/blake3 v0.0.4/go.mod h1:YOZo8A49yNqM0X/Y+JmDUZshJWLt1laHsNSn5ny2i34= +github.com/zeebo/blake3 v0.1.0 h1:sP3n5SxSbzU8x4Svc4ZcQv7SmQOqCkiKBeAZWP+hePo= +github.com/zeebo/blake3 v0.1.0/go.mod h1:YOZo8A49yNqM0X/Y+JmDUZshJWLt1laHsNSn5ny2i34= +github.com/zeebo/pcg v0.0.0-20181207190024-3cdc6b625a05 h1:4pW5fMvVkrgkMXdvIsVRRTs69DWYA8uNNQsu1stfVKU= +github.com/zeebo/pcg v0.0.0-20181207190024-3cdc6b625a05/go.mod h1:Gr+78ptB0MwXxm//LBaEvBiaXY7hXJ6KGe2V32X2F6E= +github.com/zeebo/pcg v1.0.0 h1:dt+dx+HvX8g7Un32rY9XWoYnd0NmKmrIzpHF7qiTDj0= +github.com/zeebo/pcg v1.0.0/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4= +gitlab.com/elixxir/bloomfilter v0.0.0-20200930191214-10e9ac31b228 h1:Gi6rj4mAlK0BJIk1HIzBVMjWNjIUfstrsXC2VqLYPcA= +gitlab.com/elixxir/bloomfilter v0.0.0-20200930191214-10e9ac31b228/go.mod h1:H6jztdm0k+wEV2QGK/KYA+MY9nj9Zzatux/qIvDDv3k= +gitlab.com/elixxir/comms v0.0.3 h1:7cFvBZddX/8JSY5MvfPpg21niV88IpeqQkoKs15erZM= +gitlab.com/elixxir/comms v0.0.3/go.mod h1:5p7oz4yFrK037rPap6ooaWrloJrzuVZ4jnzOdvgyqnU= +gitlab.com/elixxir/crypto v0.0.0-20200804182833-984246dea2c4 h1:28ftZDeYEko7xptCZzeFWS1Iam95dj46TWFVVlKmw6A= +gitlab.com/elixxir/crypto v0.0.0-20200804182833-984246dea2c4/go.mod h1:ucm9SFKJo+K0N2GwRRpaNr+tKXMIOVWzmyUD0SbOu2c= +gitlab.com/elixxir/crypto v0.0.3 h1:znCt/x2bL4y8czTPaaFkwzdgSgW3BJc/1+dxyf1jqVw= +gitlab.com/elixxir/crypto v0.0.3/go.mod h1:ZNgBOblhYToR4m8tj4cMvJ9UsJAUKq+p0gCp07WQmhA= +gitlab.com/elixxir/crypto v0.0.4 h1:8eWjvUepCU2PiqZM2NFYo6rFg1w8KWO1hMDwMNFEqoI= +gitlab.com/elixxir/crypto v0.0.4/go.mod h1:ZNgBOblhYToR4m8tj4cMvJ9UsJAUKq+p0gCp07WQmhA= +gitlab.com/elixxir/crypto v0.0.5-0.20201109234712-7e64de16970d h1:9Peb/peftTVeO5gYqi37sZycMEiu05+2VZ/j8d5lldI= +gitlab.com/elixxir/crypto v0.0.5-0.20201109234712-7e64de16970d/go.mod h1:ZNgBOblhYToR4m8tj4cMvJ9UsJAUKq+p0gCp07WQmhA= +gitlab.com/elixxir/ekv v0.1.3 h1:OE+LBMIhjGUMwc6hHJzYvEPNJQV7t1vMnJyIgxUMUo8= +gitlab.com/elixxir/ekv v0.1.3/go.mod h1:e6WPUt97taFZe5PFLPb1Dupk7tqmDCTQu1kkstqJvw4= +gitlab.com/elixxir/primitives v0.0.0-20200731184040-494269b53b4d/go.mod h1:OQgUZq7SjnE0b+8+iIAT2eqQF+2IFHn73tOo+aV11mg= +gitlab.com/elixxir/primitives v0.0.0-20200804170709-a1896d262cd9/go.mod h1:p0VelQda72OzoUckr1O+vPW0AiFe0nyKQ6gYcmFSuF8= +gitlab.com/elixxir/primitives v0.0.0-20200804182913-788f47bded40/go.mod h1:tzdFFvb1ESmuTCOl1z6+yf6oAICDxH2NPUemVgoNLxc= +gitlab.com/elixxir/primitives v0.0.1 h1:q61anawANlNAExfkeQEE1NCsNih6vNV1FFLoUQX6txQ= +gitlab.com/elixxir/primitives v0.0.1/go.mod h1:kNp47yPqja2lHSiS4DddTvFpB/4D9dB2YKnw5c+LJCE= +gitlab.com/elixxir/primitives v0.0.2 h1:PvyOOp/A6tCtmU7YnGhCCPRdmEogEzCi0Li/WfiVjGo= +gitlab.com/elixxir/primitives v0.0.2/go.mod h1:3fxFHSlQhkV4vs+S0dZEz3Om3m+40WX8L806yvSnNFc= +gitlab.com/elixxir/primitives v0.0.3-0.20201116174806-97f190989704 h1:JkFREumz8skDqkCjjzZnlf5tg+PBiMB9kfVn9z0VEfE= +gitlab.com/elixxir/primitives v0.0.3-0.20201116174806-97f190989704/go.mod h1:3fxFHSlQhkV4vs+S0dZEz3Om3m+40WX8L806yvSnNFc= +gitlab.com/xx_network/comms v0.0.0-20200805174823-841427dd5023/go.mod h1:owEcxTRl7gsoM8c3RQ5KAm5GstxrJp5tn+6JfQ4z5Hw= +gitlab.com/xx_network/comms v0.0.3 h1:ch1eJI4WXUE/Kz0Kp9uDWX16B+hfVFmdHY+EOai4Wzc= +gitlab.com/xx_network/comms v0.0.3/go.mod h1:YViGbRj7FjJYoaO4NpALGEd9dK/l8uUT000FEBbUTL8= +gitlab.com/xx_network/crypto v0.0.3/go.mod h1:DF2HYvvCw9wkBybXcXAgQMzX+MiGbFPjwt3t17VRqRE= +gitlab.com/xx_network/crypto v0.0.4 h1:lpKOL5mTJ2awWMfgBy30oD/UvJVrWZzUimSHlOdZZxo= +gitlab.com/xx_network/crypto v0.0.4/go.mod h1:+lcQEy+Th4eswFgQDwT0EXKp4AXrlubxalwQFH5O0Mk= +gitlab.com/xx_network/primitives v0.0.0-20200803231956-9b192c57ea7c/go.mod h1:wtdCMr7DPePz9qwctNoAUzZtbOSHSedcK++3Df3psjA= +gitlab.com/xx_network/primitives v0.0.0-20200804183002-f99f7a7284da h1:CCVslUwNC7Ul7NG5nu3ThGTSVUt1TxNRX+47f5TUwnk= +gitlab.com/xx_network/primitives v0.0.0-20200804183002-f99f7a7284da/go.mod h1:OK9xevzWCaPO7b1wiluVJGk7R5ZsuC7pHY5hteZFQug= +gitlab.com/xx_network/primitives v0.0.2 h1:r45yKenJ9e7PylI1ZXJ1Es09oYNaYXjxVy9+uYlwo7Y= +gitlab.com/xx_network/primitives v0.0.2/go.mod h1:cs0QlFpdMDI6lAo61lDRH2JZz+3aVkHy+QogOB6F/qc= +gitlab.com/xx_network/ring v0.0.2 h1:TlPjlbFdhtJrwvRgIg4ScdngMTaynx/ByHBRZiXCoL0= +gitlab.com/xx_network/ring v0.0.2/go.mod h1:aLzpP2TiZTQut/PVHR40EJAomzugDdHXetbieRClXIM= +go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-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-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37 h1:cg5LA/zNPRzIXIWSCxQW10Rvpy94aQh3LT/ShoCpkHw= +golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200707235045-ab33eee955e0 h1:eIYIE7EC5/Wv5Kbz8bJPaq+TN3kq3W8S+LSm62vM0DY= +golang.org/x/crypto v0.0.0-20200707235045-ab33eee955e0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de h1:ikNHVSjEfnvz6sxdSPCaPt572qowuyMDMJLLm3Db3ig= +golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a h1:vclmkQCjlDX5OydZ9wv8rBCcS0QyQY66Mpf/7BZbInM= +golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E= +golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +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-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/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-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= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201029221708-28c70e62bb1d h1:dOiJ2n2cMwGLce/74I/QHMbnpk5GfY7InR8rczoMqRM= +golang.org/x/net v0.0.0-20201029221708-28c70e62bb1d/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +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= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/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-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-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +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-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299 h1:DYfZAGf2WMFjMxbgTjaC+2HC7NkNAQs+6Q8b9WEB/F4= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200917073148-efd3b9a0ff20/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201029080932-201ba4db2418 h1:HlFl4V6pEMziuLXyRkm5BIYq1y1GAbb02pRlWvI54OM= +golang.org/x/sys v0.0.0-20201029080932-201ba4db2418/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +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/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +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= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/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-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +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= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +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= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +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-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= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20201030142918-24207fddd1c3 h1:sg8vLDNIxFPHTchfhH1E3AI32BL3f23oie38xUWnJM8= +google.golang.org/genproto v0.0.0-20201030142918-24207fddd1c3/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0 h1:qdOKuR/EIArgaWNjetjgTzgVTAZ+S/WXVrq9HW9zimw= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0 h1:cJv5/xdbk1NnMPR1VP9+HU6gupuG9MLBoH1r6RHZ2MY= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.61.0 h1:LBCdW4FmFYL4s/vDZD1RQYX7oAR6IjujCYgMdbHBR10= +gopkg.in/ini.v1 v1.61.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +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.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= diff --git a/interfaces/contact/contact.go b/interfaces/contact/contact.go index 2579f7a0501c1e6633c81fe2a8f147b6ab73b024..6c6e070d055a093c71f796cf284ffc5558c71e17 100644 --- a/interfaces/contact/contact.go +++ b/interfaces/contact/contact.go @@ -4,6 +4,7 @@ import ( "encoding/json" "github.com/pkg/errors" "gitlab.com/elixxir/crypto/cyclic" + "gitlab.com/elixxir/primitives/fact" "gitlab.com/xx_network/primitives/id" ) @@ -18,7 +19,7 @@ type Contact struct { ID *id.ID DhPubKey *cyclic.Int OwnershipProof []byte - Facts FactList + Facts fact.FactList } func (c Contact) Marshal() ([]byte, error) { diff --git a/interfaces/contact/fact.go b/interfaces/contact/fact.go deleted file mode 100644 index bc838160dc33f6952d9b21ab6de8af2fb5c03cad..0000000000000000000000000000000000000000 --- a/interfaces/contact/fact.go +++ /dev/null @@ -1,28 +0,0 @@ -package contact - -type Fact struct { - Fact string - T FactType -} - -func NewFact(ft FactType, fact string) (Fact, error) { - //todo: filter the fact string - return Fact{ - Fact: fact, - T: ft, - }, nil -} - -// marshal is for transmission for UDB, not a part of the fact interface -func (f Fact) Stringify() string { - return f.T.Stringify() + f.Fact -} - -func UnstringifyFact(s string) (Fact, error) { - ft, err := UnstringifyFactType(s) - if err != nil { - return Fact{}, err - } - - return NewFact(ft, s) -} diff --git a/interfaces/contact/factList.go b/interfaces/contact/factList.go deleted file mode 100644 index ad2b7c09627d530a9de0cb29f9b217bdf319d062..0000000000000000000000000000000000000000 --- a/interfaces/contact/factList.go +++ /dev/null @@ -1,43 +0,0 @@ -package contact - -import ( - "github.com/pkg/errors" - jww "github.com/spf13/jwalterweatherman" - "strings" -) - -type FactList []Fact - -func (fl FactList) Stringify() string { - stringList := make([]string, len(fl)) - for index, f := range fl { - stringList[index] = f.Stringify() - } - - return strings.Join(stringList, factDelimiter) + factBreak -} - -// unstrignifys facts followed by a facts break and with arbatrary data -// atttached at the end -func UnstringifyFactList(s string) ([]Fact, string, error) { - parts := strings.SplitN(s, factBreak, 1) - if len(parts) == 1{ - return nil, parts[0], nil - }else if len(parts) != 2 { - return nil, "", errors.New("Invalid fact string passed") - } - factStrings := strings.Split(parts[0], factDelimiter) - - var factList []Fact - for _, fString := range factStrings { - fact, err := UnstringifyFact(fString) - if err != nil { - jww.WARN.Printf("Fact failed to unstringify, dropped: %s", - err) - } else { - factList = append(factList, fact) - } - - } - return factList, parts[1], nil -} \ No newline at end of file diff --git a/interfaces/contact/type.go b/interfaces/contact/type.go deleted file mode 100644 index cc7263d5ffd0b4cc7714c3b18ecce674c8b31996..0000000000000000000000000000000000000000 --- a/interfaces/contact/type.go +++ /dev/null @@ -1,57 +0,0 @@ -package contact - -import ( - "fmt" - "github.com/pkg/errors" - jww "github.com/spf13/jwalterweatherman" -) - -type FactType uint8 - -const ( - Username FactType = 0 - Email FactType = 1 - Phone FactType = 2 -) - -func (t FactType) String() string { - switch t { - case Username: - return "Username" - case Email: - return "Email" - case Phone: - return "Phone" - default: - return fmt.Sprintf("Unknown Fact FactType: %d", t) - } -} - -func (t FactType) Stringify() string { - switch t { - case Username: - return "U" - case Email: - return "E" - case Phone: - return "P" - } - jww.FATAL.Panicf("Unknown Fact FactType: %d", t) - return "error" -} - -func UnstringifyFactType(s string) (FactType, error) { - switch s { - case "U": - return Username, nil - case "E": - return Email, nil - case "P": - return Phone, nil - } - return 3, errors.Errorf("Unknown Fact FactType: %s", s) -} - -func (t FactType) IsValid() bool { - return t == Username || t == Email || t == Phone -} diff --git a/interfaces/params/CMIX.go b/interfaces/params/CMIX.go index 0413b418ddd545319dc4ceb6f10d740a6c15b8ac..dc8658ea7a0d4b01c224ba071ffb96198ae17395 100644 --- a/interfaces/params/CMIX.go +++ b/interfaces/params/CMIX.go @@ -11,8 +11,8 @@ type CMIX struct { func GetDefaultCMIX() CMIX { return CMIX{ - RoundTries: 3, + RoundTries: 10, Timeout: 25 * time.Second, - RetryDelay: 2 * time.Second, + RetryDelay: 1 * time.Second, } } diff --git a/interfaces/params/CMIX_test.go b/interfaces/params/CMIX_test.go index 9b0a3bdffd9465a3181975632c9b4e939df443ae..5af967495b140e43fa102d2f1dd074192e1c8b96 100644 --- a/interfaces/params/CMIX_test.go +++ b/interfaces/params/CMIX_test.go @@ -7,7 +7,7 @@ import ( func TestGetDefaultCMIX(t *testing.T) { c := GetDefaultCMIX() - if c.RoundTries != 3 || c.Timeout != 25*time.Second { + if c.RoundTries != 10 || c.Timeout != 25*time.Second { t.Errorf("GetDefaultCMIX did not return expected values") } } diff --git a/interfaces/user/user.go b/interfaces/user/user.go index a4fdb7d86e6e6f82ed4b5572bf70d7f379554836..094f9386abcd5298ce9cb09da1ea8f378783d3f9 100644 --- a/interfaces/user/user.go +++ b/interfaces/user/user.go @@ -3,6 +3,7 @@ package user import ( "gitlab.com/elixxir/client/interfaces/contact" "gitlab.com/elixxir/crypto/cyclic" + "gitlab.com/elixxir/primitives/fact" "gitlab.com/xx_network/crypto/signature/rsa" "gitlab.com/xx_network/primitives/id" ) @@ -23,10 +24,10 @@ type User struct { E2eDhPublicKey *cyclic.Int } -func (u *User) GetContact() contact.Contact { +func (u User) GetContact() contact.Contact { return contact.Contact{ ID: u.ID.DeepCopy(), DhPubKey: u.E2eDhPublicKey, - Facts: make([]contact.Fact, 0), + Facts: make([]fact.Fact, 0), } -} \ No newline at end of file +} diff --git a/network/follow.go b/network/follow.go index ddb7cd96a1a4bea4b387f8981cf07ab5d469cb75..a52eff6923bb4d03ef09034608cdacbe783da807 100644 --- a/network/follow.go +++ b/network/follow.go @@ -24,16 +24,19 @@ package network import ( "gitlab.com/elixxir/client/network/gateway" //"gitlab.com/elixxir/client/storage" + jww "github.com/spf13/jwalterweatherman" + bloom "gitlab.com/elixxir/bloomfilter" + pb "gitlab.com/elixxir/comms/mixmessages" "gitlab.com/elixxir/primitives/knownRounds" "gitlab.com/xx_network/comms/connect" "gitlab.com/xx_network/crypto/csprng" - - jww "github.com/spf13/jwalterweatherman" - pb "gitlab.com/elixxir/comms/mixmessages" "gitlab.com/xx_network/primitives/id" "time" ) +const bloomFilterSize = 71888 // In Bits +const bloomFilterHashes = 8 + //comms interface makes testing easier type followNetworkComms interface { GetHost(hostId *id.ID) (*connect.Host, bool) @@ -96,6 +99,20 @@ func (m *manager) follow(rng csprng.Source, comms followNetworkComms) { jww.ERROR.Printf("Failed to unmartial: %+v", err) return } + var filterList []*bloom.Ring + for _, f := range pollResp.BloomFilters { + jww.INFO.Printf("Bloom Filter received: %v", f) + filter, err := bloom.InitByParameters(bloomFilterSize, bloomFilterHashes) + if err != nil { + jww.FATAL.Panicf("Unable to create a bloom filter: %v", err) + } + if err := filter.UnmarshalBinary(f); err != nil { + jww.WARN.Printf("Failed to unmarshal filter: %+v", err) + continue + } + filterList = append(filterList, filter) + } + jww.INFO.Printf("Bloom filters found in response: %d", len(filterList)) // ---- Node Events ---- // NOTE: this updates the structure, AND sends events over the node @@ -130,7 +147,7 @@ func (m *manager) follow(rng csprng.Source, comms followNetworkComms) { // are messages waiting in rounds and then sends signals to the appropriate // handling threads roundChecker := func(rid id.Round) bool { - return m.round.Checker(rid) + return m.round.Checker(rid, filterList) } // get the bit vector of rounds that have been checked diff --git a/network/message/critical.go b/network/message/critical.go index 2720b84f41a2dd835d6a7db9bf585da4efb522e2..f4e7971de759a855af68834ab069c67e47edfc14 100644 --- a/network/message/critical.go +++ b/network/message/critical.go @@ -47,11 +47,12 @@ func (m *Manager) criticalMessages() { //if the message fail to send, notify the buffer so it can be handled //in the future and exit if err != nil { - jww.ERROR.Printf("Failed to send critical message on " + - "notification of healthy network") + jww.ERROR.Printf("Failed to send critical message on "+ + "notification of healthy network: %+v", err) critMsgs.Failed(msg) return } + jww.INFO.Printf("critical RoundIDs: %v", rounds) //wait on the results to make sure the rounds were sucesfull sendResults := make(chan ds.EventReturn, len(rounds)) roundEvents := m.Instance.GetRoundEvents() @@ -81,11 +82,13 @@ func (m *Manager) criticalMessages() { //if the message fail to send, notify the buffer so it can be handled //in the future and exit if err != nil { - jww.ERROR.Printf("Failed to send critical message on " + - "notification of healthy network") + jww.ERROR.Printf("Failed to send critical message on "+ + "notification of healthy network: %+v", err) critRawMsgs.Failed(msg) return } + jww.INFO.Printf("critical healthy RoundIDs: %v", round) + //wait on the results to make sure the rounds were sucesfull sendResults := make(chan ds.EventReturn, 1) roundEvents := m.Instance.GetRoundEvents() @@ -105,6 +108,4 @@ func (m *Manager) criticalMessages() { }(msg) } - - } diff --git a/network/message/handler.go b/network/message/handler.go index 8e3b34f30de7502844daebc01b057b62810802ac..9018e36f847d1fb5364f12d51e45f0a7c1e06353 100644 --- a/network/message/handler.go +++ b/network/message/handler.go @@ -72,6 +72,7 @@ func (m *Manager) handleMessage(ecrMsg format.Message) { Timestamp: time.Time{}, Encryption: message.None, } + jww.INFO.Printf("Garbled/RAW Message: %v", msg.GetKeyFP()) m.Session.GetGarbledMessages().Add(msg) m.Switchboard.Speak(raw) return diff --git a/network/message/sendCmix.go b/network/message/sendCmix.go index 25e93f33dda8d3e7b9060e68471baf9451c8dd86..162ff37ce868c5670dc727f9b3c0faad97a09894 100644 --- a/network/message/sendCmix.go +++ b/network/message/sendCmix.go @@ -8,12 +8,15 @@ import ( "gitlab.com/elixxir/comms/mixmessages" "gitlab.com/elixxir/comms/network" "gitlab.com/elixxir/primitives/format" + "gitlab.com/elixxir/primitives/states" "gitlab.com/xx_network/comms/connect" "gitlab.com/xx_network/primitives/id" "strings" "time" ) +const sendTimeBuffer = uint64(100*time.Millisecond) + // WARNING: Potentially Unsafe // Payloads send are not End to End encrypted, MetaData is NOT protected with // this call, see SendE2E for End to End encryption and full privacy protection @@ -39,6 +42,13 @@ func (m *Manager) SendCMIX(msg format.Message, param params.CMIX) (id.Round, err //find the best round to send to, excluding attempted rounds bestRound, _ := m.Instance.GetWaitingRounds().GetUpcomingRealtime(remainingTime, attempted) + if (bestRound.Timestamps[states.REALTIME]+sendTimeBuffer)> + uint64(time.Now().UnixNano()){ + jww.WARN.Println("Round received which has already started" + + " realtime") + continue + } + //build the topology idList, err := id.NewIDListFromBytes(bestRound.Topology) if err != nil { @@ -77,6 +87,7 @@ func (m *Manager) SendCMIX(msg format.Message, param params.CMIX) (id.Round, err return 0, errors.WithMessage(err, "Failed to generate "+ "salt, this should never happen") } + jww.INFO.Printf("RECIPIENTIDPRE_ENCRYPT: %s", msg.GetRecipientID()) encMsg, kmacs := roundKeys.Encrypt(msg, salt) //build the message payload diff --git a/network/rounds/check.go b/network/rounds/check.go index bfdf1579b6f7fe23b8efd17616ba1047ea30e735..d6ddf537e3f43b651d3615d78dce24cc0acfdeb0 100644 --- a/network/rounds/check.go +++ b/network/rounds/check.go @@ -1,7 +1,9 @@ package rounds import ( + "encoding/binary" jww "github.com/spf13/jwalterweatherman" + bloom "gitlab.com/elixxir/bloomfilter" "gitlab.com/xx_network/primitives/id" ) @@ -16,8 +18,8 @@ import ( // if the information about that round is already present, if it is the data is // sent to Message Retrieval Workers, otherwise it is sent to Historical Round // Retrieval -func (m *Manager) Checker(roundID id.Round) bool { - jww.INFO.Printf("Checking round ID: %d", roundID) +func (m *Manager) Checker(roundID id.Round, filters []*bloom.Ring) bool { + jww.DEBUG.Printf("Checker(roundID: %d)", roundID) // Set round to processing, if we can processing, count := m.p.Process(roundID) if !processing { @@ -34,19 +36,41 @@ func (m *Manager) Checker(roundID id.Round) bool { return true } - // TODO: Bloom filter lookup -- return true when we don't have + //check if the round is in the bloom filters + hasRound := false + serialRid := serializeRound(roundID) + + for _, filter := range filters { + hasRound = filter.Test(serialRid) + if hasRound { + break + } + } + + //if it is not present, set the round as checked + //that means no messages are available for the user in the round + if !hasRound { + m.p.Done(roundID) + return true + } // Go get the round from the round infos, if it exists ri, err := m.Instance.GetRound(roundID) if err != nil { - jww.INFO.Printf("Historical Round: %d", roundID) + jww.DEBUG.Printf("HistoricalRound <- %d", roundID) // If we didn't find it, send to Historical Rounds Retrieval m.historicalRounds <- roundID } else { - jww.INFO.Printf("Looking up Round: %d", roundID) + jww.DEBUG.Printf("lookupRoundMessages <- %d", roundID) // IF found, send to Message Retrieval Workers m.lookupRoundMessages <- ri } return false } + +func serializeRound(roundId id.Round) []byte { + b := make([]byte, 8) + binary.LittleEndian.PutUint64(b, uint64(roundId)) + return b +} diff --git a/storage/auth/request.go b/storage/auth/request.go index 421fbc714bc6598877aaeb984bca6275d7b0fff5..e54632c2b806d3b68a6662a86844be2410003911 100644 --- a/storage/auth/request.go +++ b/storage/auth/request.go @@ -8,8 +8,8 @@ import ( type RequestType uint const ( - Sent RequestType = 0 - Receive RequestType = 1 + Sent RequestType = 1 + Receive RequestType = 2 ) type request struct { diff --git a/storage/auth/sentRequest.go b/storage/auth/sentRequest.go index aefd76dc6f9413fdb456d1eb268ecbe05904ef69..94a7a6ed36c976c9223eff6d17aae26789d0cd40 100644 --- a/storage/auth/sentRequest.go +++ b/storage/auth/sentRequest.go @@ -7,7 +7,6 @@ import ( "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/primitives/format" "gitlab.com/xx_network/primitives/id" - "sync" "time" ) @@ -21,7 +20,6 @@ type SentRequest struct { myPrivKey *cyclic.Int myPubKey *cyclic.Int fingerprint format.Fingerprint - sentMux sync.Mutex } type sentRequestDisk struct { diff --git a/storage/auth/store.go b/storage/auth/store.go index bf0e8830a325509d660c96c089f059243cff9baa..11eac13f3471887d629f626ae0c6669166765f10 100644 --- a/storage/auth/store.go +++ b/storage/auth/store.go @@ -42,7 +42,8 @@ func NewStore(kv *versioned.KV, grp *cyclic.Group, privKeys []*cyclic.Int) (*Sto } for _, key := range privKeys { - fp := auth.MakeRequestFingerprint(key) + pubkey := grp.ExpG(key, grp.NewInt(1)) + fp := auth.MakeRequestFingerprint(pubkey) s.fingerprints[fp] = fingerprint{ Type: General, PrivKey: key, @@ -70,7 +71,8 @@ func LoadStore(kv *versioned.KV, grp *cyclic.Group, privKeys []*cyclic.Int) (*St } for _, key := range privKeys { - fp := auth.MakeRequestFingerprint(key) + pubkey := grp.ExpG(key, grp.NewInt(1)) + fp := auth.MakeRequestFingerprint(pubkey) s.fingerprints[fp] = fingerprint{ Type: General, PrivKey: key, @@ -89,6 +91,8 @@ func LoadStore(kv *versioned.KV, grp *cyclic.Group, privKeys []*cyclic.Int) (*St rt: RequestType(rDisk.T), } + var rid *id.ID + partner, err := id.Unmarshal(rDisk.ID) if err != nil { jww.FATAL.Panicf("Failed to load stored id: %+v", err) @@ -107,17 +111,24 @@ func LoadStore(kv *versioned.KV, grp *cyclic.Group, privKeys []*cyclic.Int) (*St Request: r, } + rid = sr.partner + r.sent = sr + case Receive: c, err := utility.LoadContact(kv, partner) if err != nil { jww.FATAL.Panicf("Failed to load stored contact for: %+v", err) } + rid = c.ID r.receive = &c default: jww.FATAL.Panicf("Unknown request type: %d", r.rt) } + + //store in the request map + s.requests[*rid] = r } return s, nil @@ -186,6 +197,9 @@ func (s *Store) AddSent(partner *id.ID, partnerHistoricalPubKey, myPrivKey, "partern %s", partner) } + jww.INFO.Printf("AddSent PUBKEY FINGERPRINT: %v", sr.fingerprint) + jww.INFO.Printf("AddSent PUBKEY: %v", sr.myPubKey.Bytes()) + s.fingerprints[sr.fingerprint] = fingerprint{ Type: Specific, PrivKey: nil, @@ -252,8 +266,8 @@ func (s *Store) GetFingerprint(fp format.Fingerprint) (FingerprintType, _, ok := s.requests[*r.Request.sent.partner] s.mux.RUnlock() if !ok { - return 0, nil, nil, errors.Errorf("Fingerprint cannot be "+ - "found: %s", fp) + return 0, nil, nil, errors.Errorf("request associated with " + + "fingerprint cannot be found: %s", fp) } // Return the request return Specific, r.Request.sent, nil, nil diff --git a/storage/auth/store_test.go b/storage/auth/store_test.go index fb85f92b625def200f0604b2bb8dfa427113992f..dc938688e091f524bc46c6fac3a70659e8a82cc5 100644 --- a/storage/auth/store_test.go +++ b/storage/auth/store_test.go @@ -18,10 +18,12 @@ import ( // Happy path. func TestNewStore(t *testing.T) { kv := versioned.NewKV(make(ekv.Memstore)) - grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(0)) + grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(2)) privKeys := make([]*cyclic.Int, 10) + pubKeys := make([]*cyclic.Int, 10) for i := range privKeys { privKeys[i] = grp.NewInt(rand.Int63n(172)) + pubKeys[i] = grp.ExpG(privKeys[i],grp.NewInt(1)) } store, err := NewStore(kv, grp, privKeys) @@ -30,8 +32,12 @@ func TestNewStore(t *testing.T) { } for i, key := range privKeys { - if store.fingerprints[auth.MakeRequestFingerprint(key)].PrivKey != key { - t.Errorf("Key not found in map (%d): %s", i, key.Text(10)) + rq, ok := store.fingerprints[auth.MakeRequestFingerprint(pubKeys[i])] + if !ok { + t.Errorf("Key not found in map (%d): %s", i, pubKeys[i].Text(16)) + }else if rq.PrivKey.Cmp(key)!=0{ + t.Errorf("Key found in map (%d) does not match private: " + + "%s vs %s", i, key.Text(10), rq.PrivKey.Text(10)) } } } @@ -64,15 +70,6 @@ func TestLoadStore(t *testing.T) { t.Errorf("LoadStore() returned an error: %+v", err) } - s.requests = map[id.ID]*request{} - s.fingerprints[sr.fingerprint] = fingerprint{ - Type: Specific, - Request: &request{ - rt: Sent, - sent: sr, - }, - } - if !reflect.DeepEqual(s, store) { t.Errorf("LoadStore() returned incorrect Store."+ "\n\texpected: %+v\n\treceived: %+v", s, store) @@ -181,7 +178,8 @@ func TestStore_AddReceived_PartnerAlreadyExistsError(t *testing.T) { func TestStore_GetFingerprint_GeneralFingerprintType(t *testing.T) { s, _, privKeys := makeTestStore(t) - fp := auth.MakeRequestFingerprint(privKeys[0]) + pubkey := s.grp.ExpG(privKeys[0],s.grp.NewInt(1)) + fp := auth.MakeRequestFingerprint(pubkey) fpType, request, key, err := s.GetFingerprint(fp) if err != nil { t.Errorf("GetFingerprint() returned an error: %+v", err) @@ -194,6 +192,7 @@ func TestStore_GetFingerprint_GeneralFingerprintType(t *testing.T) { t.Errorf("GetFingerprint() returned incorrect request."+ "\n\texpected: %+v\n\treceived: %+v", nil, request) } + if key.Cmp(privKeys[0]) == -2 { t.Errorf("GetFingerprint() returned incorrect key."+ "\n\texpected: %s\n\treceived: %s", privKeys[0].Text(10), key.Text(10)) diff --git a/storage/e2e/key.go b/storage/e2e/key.go index 6e046afd24eb8192ca21bfbd05014e1da0ddc39a..ead73ff230cabde2efb177bda5714552de9e0855 100644 --- a/storage/e2e/key.go +++ b/storage/e2e/key.go @@ -36,7 +36,8 @@ func (k *Key) Fingerprint() format.Fingerprint { if k.fp != nil { return *k.fp } - return e2eCrypto.DeriveKeyFingerprint(k.session.baseKey, k.keyNum) + return e2eCrypto.DeriveKeyFingerprint(k.session.baseKey, k.keyNum, + k.session.relationshipFingerprint) } // the E2E key to encrypt msg to its intended recipient diff --git a/storage/e2e/session.go b/storage/e2e/session.go index 09e33c17b7c33d9e9530c50e01eef0816a882541..7cad5b163fbf8e2046e57c109ad9abc9d77131e4 100644 --- a/storage/e2e/session.go +++ b/storage/e2e/session.go @@ -115,6 +115,17 @@ func newSession(ship *relationship, t RelationshipType, myPrivKey, partnerPubKey session.kv = session.generate(ship.kv) + jww.INFO.Printf("New Session with Partner %s:\n\tType: %s" + + "\n\tBaseKey: %s\n\tRelationship Fingerprint: %v\n\tNumKeys: %d" + + "\n\tMy Private Key: %s\n\tPartner Public Key: %s", + ship.manager.partner, + t, + session.baseKey.TextVerbose(16, 0), + session.relationshipFingerprint, + session.ttl, + session.myPrivKey.TextVerbose(16,0), + session.partnerPubKey.TextVerbose(16,0)) + err := session.save() if err != nil { jww.FATAL.Printf("Failed to make new session for Partner %s: %s", diff --git a/storage/e2e/store.go b/storage/e2e/store.go index ee6cacbf3193aeb83f89d4301406f45eaed3fa15..6b38d2e0641605ed57ee214afac52f743b1f2981 100644 --- a/storage/e2e/store.go +++ b/storage/e2e/store.go @@ -158,11 +158,17 @@ func (s *Store) AddPartner(partnerID *id.ID, partnerPubKey, myPrivKey *cyclic.In s.mux.Lock() defer s.mux.Unlock() + jww.INFO.Printf("Adding Partner %s:\n\tMy Private Key: %s" + + "\n\tPartner Public Key: %s", + partnerID, + myPrivKey.TextVerbose(16, 0), + partnerPubKey.TextVerbose(16, 0)) + if _, ok := s.managers[*partnerID]; ok { return errors.New("Cannot overwrite existing partner") } - m := newManager(s.context, s.kv, partnerID, s.dhPrivateKey, partnerPubKey, + m := newManager(s.context, s.kv, partnerID, myPrivKey, partnerPubKey, sendParams, receiveParams) s.managers[*partnerID] = m diff --git a/storage/partition/multiPartMessage.go b/storage/partition/multiPartMessage.go index f6cdb54937e01b853425b1252a22e4e4bffc1eeb..b43f0d39978454aa0227403d6a87d61d27e56dad 100644 --- a/storage/partition/multiPartMessage.go +++ b/storage/partition/multiPartMessage.go @@ -193,7 +193,7 @@ func (mpm *multiPartMessage) IsComplete(relationshipFingerprint []byte) (message Payload: reconstructed, MessageType: mpm.MessageType, Sender: mpm.Sender, - Timestamp: time.Time{}, + Timestamp: mpm.Timestamp, // Encryption will be set externally Encryption: 0, ID: mid, diff --git a/storage/partition/multiPartMessage_test.go b/storage/partition/multiPartMessage_test.go index 5c546e9e90c30f2a4b3c9d496f432be95161edc1..35e5b02772477ca7f91b47124565a0d5a0c805ba 100644 --- a/storage/partition/multiPartMessage_test.go +++ b/storage/partition/multiPartMessage_test.go @@ -216,7 +216,7 @@ func TestMultiPartMessage_IsComplete(t *testing.T) { Payload: payload, MessageType: mpm.MessageType, Sender: mpm.Sender, - Timestamp: time.Time{}, + Timestamp: msg.Timestamp, Encryption: 0, ID: e2e.NewMessageID([]byte{0}, mid), } diff --git a/storage/session.go b/storage/session.go index 9db8fc9cbe54761434255fa667a15a9422cbf260..25145a2a59a53247c400584200eda7aeae4767c6 100644 --- a/storage/session.go +++ b/storage/session.go @@ -167,7 +167,7 @@ func Load(baseDir, password string, rng *fastRNG.StreamGenerator) (*Session, err return nil, errors.WithMessage(err, "Failed to load Session") } - s.auth, err = auth.NewStore(s.kv, s.e2e.GetGroup(), + s.auth, err = auth.LoadStore(s.kv, s.e2e.GetGroup(), []*cyclic.Int{s.e2e.GetDHPrivateKey()}) if err != nil { return nil, errors.WithMessage(err, "Failed to load auth store") diff --git a/storage/utility/messageBuffer.go b/storage/utility/messageBuffer.go index 197e669c4af6436544f3d90c25c0c903fafa809f..b6bcde652dffa2dbb4938bf066a355e1e791ea0e 100644 --- a/storage/utility/messageBuffer.go +++ b/storage/utility/messageBuffer.go @@ -270,6 +270,7 @@ func (mb *MessageBuffer) Succeeded(m interface{}) { // Done message from buffer delete(mb.processingMessages, h) + delete(mb.messages, h) // Done message from key value store err := mb.handler.DeleteMessage(mb.kv, makeStoredMessageKey(mb.key, h)) diff --git a/ud/commID.go b/ud/commID.go new file mode 100644 index 0000000000000000000000000000000000000000..712ef213b8e16087da859c78bc34aaaee59b9632 --- /dev/null +++ b/ud/commID.go @@ -0,0 +1,52 @@ +package ud + +import ( + "encoding/binary" + jww "github.com/spf13/jwalterweatherman" + "gitlab.com/elixxir/client/storage/versioned" + "time" +) + +const commIDKey = "commIDKey" +const commIDVersion = 0 + +// getCommID returns the ID for the next comm. IDs are generated sequentially. +func (m *Manager) getCommID() uint64 { + + m.commIDLock.Lock() + defer m.commIDLock.Unlock() + returnedID := m.commID + + // Increment ID for next get + m.commID++ + + // Save ID storage + data := make([]byte, 8) + binary.BigEndian.PutUint64(data, m.commID) + + obj := &versioned.Object{ + Version: commIDVersion, + Timestamp: time.Now(), + Data: data, + } + + if err := m.storage.Set(commIDKey, obj); err != nil { + jww.FATAL.Panicf("Failed to store the next commID: %+v", err) + } + + return returnedID +} + +// loadCommID retrieves the next comm ID from storage. +func (m *Manager) loadCommID() { + m.commIDLock.Lock() + defer m.commIDLock.Unlock() + + obj, err := m.storage.Get(commIDKey) + if err != nil { + jww.WARN.Printf("Failed to get the commID; restarting at zero: %+v", err) + return + } + + m.commID = binary.BigEndian.Uint64(obj.Data) +} diff --git a/ud/lookup.go b/ud/lookup.go index 1032c6a3e2af5446a0f376bf3f32fc7c6092c823..c75c52e83f7e55c55207a32429736eba6564ecfd 100644 --- a/ud/lookup.go +++ b/ud/lookup.go @@ -3,82 +3,75 @@ package ud import ( "github.com/golang/protobuf/proto" "github.com/pkg/errors" + jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/interfaces/contact" "gitlab.com/elixxir/client/interfaces/message" "gitlab.com/elixxir/client/interfaces/params" - "gitlab.com/elixxir/client/interfaces/utility" "gitlab.com/elixxir/comms/network/dataStructures" "gitlab.com/elixxir/primitives/states" "gitlab.com/xx_network/primitives/id" - "google.golang.org/protobuf/runtime/protoimpl" "time" - jww "github.com/spf13/jwalterweatherman" ) type lookupCallback func(contact.Contact, error) - -func (m *Manager)lookupProcess(c chan message.Receive, quitCh <-chan struct{}){ +func (m *Manager) lookupProcess(c chan message.Receive, quitCh <-chan struct{}) { for true { select { case <-quitCh: return case response := <-c: - // edge check the encryption - if response.Encryption!=message.E2E{ + // Edge check the encryption + if response.Encryption != message.E2E { jww.WARN.Printf("Dropped a lookup response from user " + "discovery due to incorrect encryption") } - // unmarshal the message + // Unmarshal the message lookupResponse := &LookupResponse{} - if err :=proto.Unmarshal(response.Payload, lookupResponse); err!=nil{ - jww.WARN.Printf("Dropped a lookup response from user " + + if err := proto.Unmarshal(response.Payload, lookupResponse); err != nil { + jww.WARN.Printf("Dropped a lookup response from user "+ "discovery due to failed unmarshal: %s", err) } - // get the appropriate channel from the lookup + // Get the appropriate channel from the lookup m.inProgressMux.RLock() ch, ok := m.inProgressLookup[lookupResponse.CommID] m.inProgressMux.RUnlock() - if !ok{ - jww.WARN.Printf("Dropped a lookup response from user " + + if !ok { + jww.WARN.Printf("Dropped a lookup response from user "+ "discovery due to unknown comm ID: %d", lookupResponse.CommID) } - // send the response on the correct channel - // drop if the send cannot be completed - select{ - case ch<-lookupResponse: - default: - jww.WARN.Printf("Dropped a lookup response from user " + - "discovery due failure to transmit to handling thread: " + - "commID: %d", lookupResponse.CommID) + // Send the response on the correct channel + // Drop if the send cannot be completed + select { + case ch <- lookupResponse: + default: + jww.WARN.Printf("Dropped a lookup response from user "+ + "discovery due to failure to transmit to handling thread: "+ + "commID: %d", lookupResponse.CommID) } } } } +// Lookup returns the public key of the passed ID as known by the user discovery +// system or returns by the timeout. +func (m *Manager) Lookup(uid *id.ID, callback lookupCallback, timeout time.Duration) error { -// returns the public key of the passed id as known by the user discovery system -// or returns by the timeout -func (m *Manager)Lookup(id *id.ID, callback lookupCallback, timeout time.Duration)error{ - - //get the id of this comm so it can be connected to its responce - commID, err := m.getCommID() - if err!=nil{ - return errors.WithMessage(err, "Random generation failed") - } + // Get the ID of this comm so it can be connected to its response + commID := m.getCommID() - //build the request + // Build the request request := &LookupSend{ - UserID: id.Marshal(), - CommID: commID, + UserID: uid.Marshal(), + CommID: commID, } requestMarshaled, err := proto.Marshal(request) - if err!=nil{ + if err != nil { return errors.WithMessage(err, "Failed to form outgoing request") } @@ -88,68 +81,70 @@ func (m *Manager)Lookup(id *id.ID, callback lookupCallback, timeout time.Duratio MessageType: message.UdLookup, } - //register the request in the responce map so it can be procesed on return + // Register the request in the response map so it can be processed on return responseChan := make(chan *LookupResponse, 1) m.inProgressMux.Lock() m.inProgressLookup[commID] = responseChan m.inProgressMux.Unlock() - //send the request + // Send the request rounds, _, err := m.net.SendE2E(msg, params.GetDefaultE2E()) - - if err!=nil{ - return errors.WithMessage(err, "Failed to send the lookup " + - "request") + if err != nil { + return errors.WithMessage(err, "Failed to send the lookup request") } - //register the round event to capture if the round fails + // Register the round event to capture if the round fails roundFailChan := make(chan dataStructures.EventReturn, len(rounds)) - for _, round := range rounds{ - //subtract a millisecond to ensure this timeout will trigger before - // the one below + for _, round := range rounds { + // Subtract a millisecond to ensure this timeout will trigger before the + // one below m.net.GetInstance().GetRoundEvents().AddRoundEventChan(round, roundFailChan, timeout-1*time.Millisecond, states.FAILED) } - //start the go routine which will trigger the callback - go func(){ + // Start the go routine which will trigger the callback + go func() { timer := time.NewTimer(timeout) var err error var c contact.Contact - select{ - //return an error if the round fails - case <-roundFailChan: - err= errors.New("One or more rounds failed to " + - "resolve, lookup not delivered") - //return an error if the timeout is reached - case <-timer.C: - err= errors.New("Response from User Discovery" + - " did not come before timeout") - //return the contact if one is returned - case response := <-responseChan: - if response.Error!=""{ - err = errors.Errorf("User Discovery returned an " + - "error on Lookup: %s", response.Error) - }else{ - pubkey := m.grp.NewIntFromBytes(response.PubKey) - c = contact.Contact{ - ID: id, - DhPubKey: pubkey, - OwnershipProof: nil, - Facts: nil, - } + select { + // Return an error if the round fails + case <-roundFailChan: + err = errors.New("One or more rounds failed to resolved; " + + "lookup not delivered") + + // Return an error if the timeout is reached + case <-timer.C: + err = errors.New("Response from User Discovery did not come " + + "before timeout") + + // Return the contact if one is returned + case response := <-responseChan: + if response.Error != "" { + err = errors.Errorf("User Discovery returned an error on "+ + "lookup: %s", response.Error) + } else { + pubkey := m.grp.NewIntFromBytes(response.PubKey) + c = contact.Contact{ + ID: uid, + DhPubKey: pubkey, + OwnershipProof: nil, + Facts: nil, } + } } - //delete the response channel from the map + + // Delete the response channel from the map m.inProgressMux.Lock() delete(m.inProgressLookup, commID) m.inProgressMux.Unlock() - //call the callback last in case it is blocking + + // Call the callback last in case it is blocking callback(c, err) }() return nil -} \ No newline at end of file +} diff --git a/ud/lookup_test.go b/ud/lookup_test.go new file mode 100644 index 0000000000000000000000000000000000000000..6b18671f7c862f3796834270c80b65b9ac3d630b --- /dev/null +++ b/ud/lookup_test.go @@ -0,0 +1,415 @@ +package ud + +import ( + "github.com/golang/protobuf/proto" + "gitlab.com/elixxir/client/globals" + "gitlab.com/elixxir/client/interfaces" + "gitlab.com/elixxir/client/interfaces/contact" + "gitlab.com/elixxir/client/interfaces/message" + "gitlab.com/elixxir/client/interfaces/params" + "gitlab.com/elixxir/client/stoppable" + "gitlab.com/elixxir/client/storage" + "gitlab.com/elixxir/comms/network" + "gitlab.com/elixxir/crypto/cyclic" + "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/crypto/large" + "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/ndf" + "math/rand" + "reflect" + "testing" + "time" +) + +// Happy path. +func TestManager_Lookup(t *testing.T) { + // Set up manager + m := Manager{ + rng: fastRNG.NewStreamGenerator(12, 3, csprng.NewSystemRNG), + grp: cyclic.NewGroup(large.NewInt(107), large.NewInt(2)), + storage: storage.InitTestingSession(t), + udID: id.NewIdFromUInt(rand.Uint64(), id.User, t), + inProgressLookup: map[uint64]chan *LookupResponse{}, + net: newTestNetworkManager(t), + } + + // Generate callback function + callbackChan := make(chan struct { + c contact.Contact + err error + }) + callback := func(c contact.Contact, err error) { + callbackChan <- struct { + c contact.Contact + err error + }{c: c, err: err} + } + + // Trigger lookup response chan + go func() { + time.Sleep(1 * time.Millisecond) + m.inProgressLookup[0] <- &LookupResponse{ + PubKey: []byte{5}, + Error: "", + } + }() + + uid := id.NewIdFromUInt(rand.Uint64(), id.User, t) + + // Run the lookup + err := m.Lookup(uid, callback, 10*time.Millisecond) + if err != nil { + t.Errorf("Lookup() returned an error: %+v", err) + } + + // Generate expected Send message + payload, err := proto.Marshal(&LookupSend{ + UserID: uid.Marshal(), + CommID: m.commID - 1, + }) + if err != nil { + t.Fatalf("Failed to marshal LookupSend: %+v", err) + } + expectedMsg := message.Send{ + Recipient: m.udID, + Payload: payload, + MessageType: message.UdLookup, + } + + // Verify the message is correct + if !reflect.DeepEqual(expectedMsg, m.net.(*testNetworkManager).msg) { + t.Errorf("Failed to send correct message."+ + "\n\texpected: %+v\n\treceived: %+v", + expectedMsg, m.net.(*testNetworkManager).msg) + } + + // Verify the callback is called + select { + case cb := <-callbackChan: + if cb.err != nil { + t.Errorf("Callback returned an error: %+v", cb.err) + } + + expectedContact := contact.Contact{ + ID: uid, + DhPubKey: m.grp.NewIntFromBytes([]byte{5}), + } + if !reflect.DeepEqual(expectedContact, cb.c) { + t.Errorf("Failed to get expected Contact."+ + "\n\texpected: %v\n\treceived: %v", expectedContact, cb.c) + } + case <-time.After(100 * time.Millisecond): + t.Error("Callback not called.") + } + + if _, exists := m.inProgressLookup[m.commID-1]; exists { + t.Error("Failed to delete LookupResponse from inProgressLookup.") + } +} + +// Error path: the LookupResponse returns an error. +func TestManager_Lookup_LookupResponseError(t *testing.T) { + // Set up manager + m := Manager{ + rng: fastRNG.NewStreamGenerator(12, 3, csprng.NewSystemRNG), + grp: cyclic.NewGroup(large.NewInt(107), large.NewInt(2)), + storage: storage.InitTestingSession(t), + udID: id.NewIdFromUInt(rand.Uint64(), id.User, t), + inProgressLookup: map[uint64]chan *LookupResponse{}, + net: newTestNetworkManager(t), + } + + // Generate callback function + callbackChan := make(chan struct { + c contact.Contact + err error + }) + callback := func(c contact.Contact, err error) { + callbackChan <- struct { + c contact.Contact + err error + }{c: c, err: err} + } + + // Trigger lookup response chan + go func() { + time.Sleep(1 * time.Millisecond) + m.inProgressLookup[0] <- &LookupResponse{ + PubKey: nil, + Error: "Error", + } + }() + + uid := id.NewIdFromUInt(rand.Uint64(), id.User, t) + + // Run the lookup + err := m.Lookup(uid, callback, 10*time.Millisecond) + if err != nil { + t.Errorf("Lookup() returned an error: %+v", err) + } + + // Verify the callback is called + select { + case cb := <-callbackChan: + if cb.err == nil { + t.Error("Callback did not return an expected error.") + } + + if !reflect.DeepEqual(contact.Contact{}, cb.c) { + t.Errorf("Failed to get expected Contact."+ + "\n\texpected: %v\n\treceived: %v", contact.Contact{}, cb.c) + } + case <-time.After(100 * time.Millisecond): + t.Error("Callback not called.") + } + + if _, exists := m.inProgressLookup[m.commID-1]; exists { + t.Error("Failed to delete LookupResponse from inProgressLookup.") + } +} + +// Error path: the round event chan times out. +func TestManager_Lookup_EventChanTimeout(t *testing.T) { + // Set up manager + m := Manager{ + rng: fastRNG.NewStreamGenerator(12, 3, csprng.NewSystemRNG), + grp: cyclic.NewGroup(large.NewInt(107), large.NewInt(2)), + storage: storage.InitTestingSession(t), + udID: id.NewIdFromUInt(rand.Uint64(), id.User, t), + inProgressLookup: map[uint64]chan *LookupResponse{}, + net: newTestNetworkManager(t), + } + + // Generate callback function + callbackChan := make(chan struct { + c contact.Contact + err error + }) + callback := func(c contact.Contact, err error) { + callbackChan <- struct { + c contact.Contact + err error + }{c: c, err: err} + } + + uid := id.NewIdFromUInt(rand.Uint64(), id.User, t) + + // Run the lookup + err := m.Lookup(uid, callback, 10*time.Millisecond) + if err != nil { + t.Errorf("Lookup() returned an error: %+v", err) + } + + // Verify the callback is called + select { + case cb := <-callbackChan: + if cb.err == nil { + t.Error("Callback did not return an expected error.") + } + + if !reflect.DeepEqual(contact.Contact{}, cb.c) { + t.Errorf("Failed to get expected Contact."+ + "\n\texpected: %v\n\treceived: %v", contact.Contact{}, cb.c) + } + case <-time.After(100 * time.Millisecond): + t.Error("Callback not called.") + } + + if _, exists := m.inProgressLookup[m.commID-1]; exists { + t.Error("Failed to delete LookupResponse from inProgressLookup.") + } +} + +// Happy path. +func TestManager_lookupProcess(t *testing.T) { + m := Manager{ + rng: fastRNG.NewStreamGenerator(12, 3, csprng.NewSystemRNG), + grp: cyclic.NewGroup(large.NewInt(107), large.NewInt(2)), + storage: storage.InitTestingSession(t), + udID: id.NewIdFromUInt(rand.Uint64(), id.User, t), + inProgressLookup: map[uint64]chan *LookupResponse{}, + net: newTestNetworkManager(t), + } + + c := make(chan message.Receive) + quitCh := make(chan struct{}) + + // Generate expected Send message + payload, err := proto.Marshal(&LookupSend{ + UserID: id.NewIdFromUInt(rand.Uint64(), id.User, t).Marshal(), + CommID: m.commID, + }) + if err != nil { + t.Fatalf("Failed to marshal LookupSend: %+v", err) + } + + m.inProgressLookup[m.commID] = make(chan *LookupResponse, 1) + + // Trigger response chan + go func() { + time.Sleep(1 * time.Millisecond) + c <- message.Receive{ + Payload: payload, + Encryption: message.E2E, + } + time.Sleep(1 * time.Millisecond) + quitCh <- struct{}{} + }() + + m.lookupProcess(c, quitCh) + + select { + case response := <-m.inProgressLookup[m.commID]: + expectedResponse := &LookupResponse{} + if err := proto.Unmarshal(payload, expectedResponse); err != nil { + t.Fatalf("Failed to unmarshal payload: %+v", err) + } + + if !reflect.DeepEqual(expectedResponse, response) { + t.Errorf("Recieved unexpected response."+ + "\n\texpected: %+v\n\trecieved: %+v", expectedResponse, response) + } + case <-time.After(100 * time.Millisecond): + t.Error("Response not sent.") + } +} + +// Error path: dropped lookup response due to incorrect message.Receive. +func TestManager_lookupProcess_NoLookupResponse(t *testing.T) { + m := Manager{ + rng: fastRNG.NewStreamGenerator(12, 3, csprng.NewSystemRNG), + grp: cyclic.NewGroup(large.NewInt(107), large.NewInt(2)), + storage: storage.InitTestingSession(t), + udID: id.NewIdFromUInt(rand.Uint64(), id.User, t), + inProgressLookup: map[uint64]chan *LookupResponse{}, + net: newTestNetworkManager(t), + } + + c := make(chan message.Receive) + quitCh := make(chan struct{}) + + // Trigger response chan + go func() { + time.Sleep(1 * time.Millisecond) + c <- message.Receive{} + time.Sleep(1 * time.Millisecond) + quitCh <- struct{}{} + }() + + m.lookupProcess(c, quitCh) + + select { + case response := <-m.inProgressLookup[m.commID]: + t.Errorf("Received unexpected response: %+v", response) + case <-time.After(10 * time.Millisecond): + return + } +} + +// testNetworkManager is a test implementation of NetworkManager interface. +type testNetworkManager struct { + instance *network.Instance + msg message.Send +} + +func (t *testNetworkManager) SendE2E(m message.Send, _ params.E2E) ([]id.Round, + e2e.MessageID, error) { + rounds := []id.Round{ + id.Round(0), + id.Round(1), + id.Round(2), + } + + t.msg = m + + return rounds, e2e.MessageID{}, nil +} + +func (t *testNetworkManager) SendUnsafe(message.Send, params.Unsafe) ([]id.Round, error) { + return nil, nil +} + +func (t *testNetworkManager) SendCMIX(format.Message, params.CMIX) (id.Round, error) { + return 0, nil +} + +func (t *testNetworkManager) GetInstance() *network.Instance { + return t.instance +} + +func (t *testNetworkManager) GetHealthTracker() interfaces.HealthTracker { + return nil +} + +func (t *testNetworkManager) Follow() (stoppable.Stoppable, error) { + return nil, nil +} + +func (t *testNetworkManager) CheckGarbledMessages() {} + +func newTestNetworkManager(i interface{}) interfaces.NetworkManager { + switch i.(type) { + case *testing.T, *testing.M, *testing.B: + break + default: + globals.Log.FATAL.Panicf("initTesting is restricted to testing only."+ + "Got %T", i) + } + + commsManager := connect.NewManagerTesting(i) + instanceComms := &connect.ProtoComms{ + Manager: commsManager, + } + + thisInstance, err := network.NewInstanceTesting(instanceComms, getNDF(), getNDF(), nil, nil, i) + if err != nil { + globals.Log.FATAL.Panicf("Failed to create new test Instance: %v", err) + } + + thisManager := &testNetworkManager{instance: thisInstance} + + return thisManager +} + +func getNDF() *ndf.NetworkDefinition { + return &ndf.NetworkDefinition{ + E2E: ndf.Group{ + Prime: "E2EE983D031DC1DB6F1A7A67DF0E9A8E5561DB8E8D49413394C049B" + + "7A8ACCEDC298708F121951D9CF920EC5D146727AA4AE535B0922C688B55B3DD2AE" + + "DF6C01C94764DAB937935AA83BE36E67760713AB44A6337C20E7861575E745D31F" + + "8B9E9AD8412118C62A3E2E29DF46B0864D0C951C394A5CBBDC6ADC718DD2A3E041" + + "023DBB5AB23EBB4742DE9C1687B5B34FA48C3521632C4A530E8FFB1BC51DADDF45" + + "3B0B2717C2BC6669ED76B4BDD5C9FF558E88F26E5785302BEDBCA23EAC5ACE9209" + + "6EE8A60642FB61E8F3D24990B8CB12EE448EEF78E184C7242DD161C7738F32BF29" + + "A841698978825B4111B4BC3E1E198455095958333D776D8B2BEEED3A1A1A221A6E" + + "37E664A64B83981C46FFDDC1A45E3D5211AAF8BFBC072768C4F50D7D7803D2D4F2" + + "78DE8014A47323631D7E064DE81C0C6BFA43EF0E6998860F1390B5D3FEACAF1696" + + "015CB79C3F9C2D93D961120CD0E5F12CBB687EAB045241F96789C38E89D796138E" + + "6319BE62E35D87B1048CA28BE389B575E994DCA755471584A09EC723742DC35873" + + "847AEF49F66E43873", + Generator: "2", + }, + CMIX: ndf.Group{ + Prime: "9DB6FB5951B66BB6FE1E140F1D2CE5502374161FD6538DF1648218642F0B5C48" + + "C8F7A41AADFA187324B87674FA1822B00F1ECF8136943D7C55757264E5A1A44F" + + "FE012E9936E00C1D3E9310B01C7D179805D3058B2A9F4BB6F9716BFE6117C6B5" + + "B3CC4D9BE341104AD4A80AD6C94E005F4B993E14F091EB51743BF33050C38DE2" + + "35567E1B34C3D6A5C0CEAA1A0F368213C3D19843D0B4B09DCB9FC72D39C8DE41" + + "F1BF14D4BB4563CA28371621CAD3324B6A2D392145BEBFAC748805236F5CA2FE" + + "92B871CD8F9C36D3292B5509CA8CAA77A2ADFC7BFD77DDA6F71125A7456FEA15" + + "3E433256A2261C6A06ED3693797E7995FAD5AABBCFBE3EDA2741E375404AE25B", + Generator: "5C7FF6B06F8F143FE8288433493E4769C4D988ACE5BE25A0E24809670716C613" + + "D7B0CEE6932F8FAA7C44D2CB24523DA53FBE4F6EC3595892D1AA58C4328A06C4" + + "6A15662E7EAA703A1DECF8BBB2D05DBE2EB956C142A338661D10461C0D135472" + + "085057F3494309FFA73C611F78B32ADBB5740C361C9F35BE90997DB2014E2EF5" + + "AA61782F52ABEB8BD6432C4DD097BC5423B285DAFB60DC364E8161F4A2A35ACA" + + "3A10B1C4D203CC76A470A33AFDCBDD92959859ABD8B56E1725252D78EAC66E71" + + "BA9AE3F1DD2487199874393CD4D832186800654760E1E34C09E4D155179F9EC0" + + "DC4473F996BDCE6EED1CABED8B6F116F7AD9CF505DF0F998E34AB27514B0FFE7", + }, + } +} diff --git a/ud/manager.go b/ud/manager.go index a12e5f1fc1e7e698f0492575181525e02e948056..10dcc2a8131fb64b6ad4bcc5dbc76922cf6f30cd 100644 --- a/ud/manager.go +++ b/ud/manager.go @@ -1,10 +1,10 @@ package ud import ( - "encoding/binary" "gitlab.com/elixxir/client/interfaces" "gitlab.com/elixxir/client/interfaces/message" "gitlab.com/elixxir/client/stoppable" + "gitlab.com/elixxir/client/storage" "gitlab.com/elixxir/comms/client" "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/crypto/fastRNG" @@ -18,40 +18,30 @@ type Manager struct { comms *client.Comms host *connect.Host privKey *rsa.PrivateKey - rng *fastRNG.StreamGenerator - grp *cyclic.Group - sw interfaces.Switchboard + rng *fastRNG.StreamGenerator + grp *cyclic.Group + sw interfaces.Switchboard + storage *storage.Session udID *id.ID - inProgressLookup map[uint64]chan *LookupResponse - inProgressMux sync.RWMutex + inProgressMux sync.RWMutex net interfaces.NetworkManager -} - -func (m *Manager)getCommID()(uint64, error){ - //fixme: this should use incremenetation - stream := m.rng.GetStream() - idBytes := make([]byte, 8) - if _, err := stream.Read(idBytes); err!=nil{ - return 0, err - } - - return binary.BigEndian.Uint64(idBytes), nil + commID uint64 + commIDLock sync.Mutex } -func (m *Manager)StartProcessies()stoppable.Stoppable{ +func (m *Manager) StartProcesses() stoppable.Stoppable { lookupStop := stoppable.NewSingle("UDLookup") lookupChan := make(chan message.Receive, 100) m.sw.RegisterChannel("UDLookupResponse", m.udID, message.UdLookupResponse, lookupChan) go m.lookupProcess(lookupChan, lookupStop.Quit()) - udMulti := stoppable.NewMulti("UD") udMulti.Add(lookupStop) return lookupStop -} \ No newline at end of file +} diff --git a/ud/register.go b/ud/register.go index 6fdd2b54e1203bb3f82814f94f14f3101bfa8307..84aec1a9277078b2a50ae7ba6d7f75a794a25d98 100644 --- a/ud/register.go +++ b/ud/register.go @@ -1,24 +1,25 @@ package ud import ( - "gitlab.com/xx_network/comms/messages" + pb "gitlab.com/elixxir/comms/mixmessages" "gitlab.com/xx_network/primitives/id" ) -func (m *Manager)Register(myID *id.ID, username string)error{ +func (m *Manager) Register(myID *id.ID, username string) error { - msg := &messages.AuthenticatedMessage{ - ID: myID.Bytes(), - Signature: nil, - Token: nil, - Client: nil, - Message: nil, - XXX_NoUnkeyedLiteral: struct{}{}, - XXX_unrecognized: nil, - XXX_sizecache: 0, + msg := &pb.UDBUserRegistration{ + PermissioningSignature: nil, + RSAPublicPem: "", + IdentityRegistration: nil, + IdentitySignature: nil, + Frs: nil, + UID: myID.Bytes(), + XXX_NoUnkeyedLiteral: struct{}{}, + XXX_unrecognized: nil, + XXX_sizecache: 0, } - m.comms.SendRegisterUser(m.host) + _, _ = m.comms.SendRegisterUser(m.host, msg) - -} \ No newline at end of file + return nil +} diff --git a/ud/remove.go b/ud/remove.go index eaa06f27d6451d6237b5a753942f16b47f5bc4af..ad918c972c4180a247ee29ce8f3e133e1b02ffc8 100644 --- a/ud/remove.go +++ b/ud/remove.go @@ -12,7 +12,7 @@ type removeFactComms interface { } func (m *Manager) RemoveFact(fact contact.Fact) error { - return m.removeFact(fact, m.comms) + return m.removeFact(fact, nil) } func (m *Manager) removeFact(fact contact.Fact, rFC removeFactComms) error {