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(&notificationToken, "nbRegistration", "x", "",
diff --git a/go.mod b/go.mod
index 80036c5f95502d32484917358f32ef83f915f415..84ed766a410405b2465dc08a5aac8068b2034814 100644
--- a/go.mod
+++ b/go.mod
@@ -17,13 +17,14 @@ 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.20201116233755-b476dea10095
-	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.3-0.20201116234927-44e42fc91e7c
+	gitlab.com/xx_network/primitives v0.0.2
 	golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897
 	google.golang.org/protobuf v1.25.0
 	gopkg.in/ini.v1 v1.61.0 // indirect
diff --git a/go.sum b/go.sum
index cee607cb4a69b94fd55e8494a2d575e567810cbd..5e5de048d2a894d2bb57d6dcccd3d2cbc5501294 100644
--- a/go.sum
+++ b/go.sum
@@ -250,24 +250,18 @@ github.com/zeebo/pcg v0.0.0-20181207190024-3cdc6b625a05 h1:4pW5fMvVkrgkMXdvIsVRR
 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/comms v0.0.4-0.20201103220934-c476c9282f30 h1:9q+xVbu5m7XDvT1CVz8s1S/SOVpasWJOx7V/3rAY/pE=
-gitlab.com/elixxir/comms v0.0.4-0.20201103220934-c476c9282f30/go.mod h1:5p7oz4yFrK037rPap6ooaWrloJrzuVZ4jnzOdvgyqnU=
-gitlab.com/elixxir/comms v0.0.4-0.20201111205457-b073b28c367a h1:GnZLdgn5ZSDtPFsiCUPgqQk2D+e7LmzVOZ9Rq/B8hCY=
-gitlab.com/elixxir/comms v0.0.4-0.20201111205457-b073b28c367a/go.mod h1:5p7oz4yFrK037rPap6ooaWrloJrzuVZ4jnzOdvgyqnU=
-gitlab.com/elixxir/comms v0.0.4-0.20201112000135-4147e270e129 h1:d4s9JGimUVmqdKlK4NhICayzWBUSM2XmKta821ZJTF0=
-gitlab.com/elixxir/comms v0.0.4-0.20201112000135-4147e270e129/go.mod h1:5p7oz4yFrK037rPap6ooaWrloJrzuVZ4jnzOdvgyqnU=
-gitlab.com/elixxir/comms v0.0.4-0.20201116233755-b476dea10095 h1:YptJAYLxqy5CAJIcM9kOwfxmJ2D2A8uXWTT8rgXYG+E=
-gitlab.com/elixxir/comms v0.0.4-0.20201116233755-b476dea10095/go.mod h1:spFKl7jsMy8M6NDvhJ27IJ+CnZ/07JHJCYpYsG8JQ4o=
+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.20201109203841-ba162a25be6e h1:rkT8Pzjgo9oF3uS8ExHGNUQoJX/22qK3lU+vU8QsOCY=
-gitlab.com/elixxir/crypto v0.0.5-0.20201109203841-ba162a25be6e/go.mod h1:ZNgBOblhYToR4m8tj4cMvJ9UsJAUKq+p0gCp07WQmhA=
-gitlab.com/elixxir/crypto v0.0.5-0.20201110193609-6b5e881867b4 h1:1a1zZDuqZ56qU1EPgpc+Sqny1YFl0kAKJgQbsVc0WJQ=
-gitlab.com/elixxir/crypto v0.0.5-0.20201110193609-6b5e881867b4/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=
@@ -282,8 +276,6 @@ gitlab.com/elixxir/primitives v0.0.3-0.20201116174806-97f190989704/go.mod h1:3fx
 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/comms v0.0.4-0.20201110022115-4a6171cad07d h1:wPsoqWNusbFJxvPB1Rvzu+TLZxth3G+ay8qkNrpAuzM=
-gitlab.com/xx_network/comms v0.0.4-0.20201110022115-4a6171cad07d/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=
@@ -292,8 +284,6 @@ gitlab.com/xx_network/primitives v0.0.0-20200804183002-f99f7a7284da h1:CCVslUwNC
 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/primitives v0.0.3-0.20201116234927-44e42fc91e7c h1:mYId667WIN97E6KhPw4HDYyCjWzsG7gCM/HLTNTCXZQ=
-gitlab.com/xx_network/primitives v0.0.3-0.20201116234927-44e42fc91e7c/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=
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))