From b37b8d0aa8862f4c229d90059cd75d14d00de455 Mon Sep 17 00:00:00 2001
From: "Richard T. Carback III" <rick.carback@gmail.com>
Date: Wed, 20 Apr 2022 01:54:00 +0000
Subject: [PATCH] Updates to make single use compile

---
 api/auth.go                  |   2 +-
 api/client.go                |   7 +
 cmd/root.go                  | 126 +++++-----
 cmd/single.go                | 172 ++++++++------
 cmd/ud.go                    | 446 +++++++++++++++++------------------
 cmd/utils.go                 |  10 +-
 e2e/ratchet/partner/utils.go |   5 +-
 7 files changed, 402 insertions(+), 366 deletions(-)

diff --git a/api/auth.go b/api/auth.go
index 550b6ebfa..f7451941a 100644
--- a/api/auth.go
+++ b/api/auth.go
@@ -178,5 +178,5 @@ func (c *Client) GetRelationshipFingerprint(partner *id.ID) (string, error) {
 			partner)
 	}
 
-	return m.ConnectionFingerprint(), nil
+	return m.ConnectionFingerprint().String(), nil
 }
diff --git a/api/client.go b/api/client.go
index 21d8cefad..99149d542 100644
--- a/api/client.go
+++ b/api/client.go
@@ -762,6 +762,13 @@ func (c *Client) GetBackup() *backup.Backup {
 	return c.backup
 }
 
+func (c *Client) InitializeBackup(backupPass string,
+	updateBackupCb backup.UpdateBackupFn) (*backup.Backup, error) {
+	container := &backup.Container{}
+	return backup.InitializeBackup(backupPass, updateBackupCb, container,
+		c.e2e, c.storage, nil, c.storage.GetKV(), c.rng)
+}
+
 // GetNodeRegistrationStatus gets the current state of nodes registration. It
 // returns the total number of nodes in the NDF and the number of those which
 // are currently registers with. An error is returned if the network is not
diff --git a/cmd/root.go b/cmd/root.go
index 8243071ce..569fda287 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -28,12 +28,12 @@ import (
 	"gitlab.com/elixxir/client/catalog"
 	"gitlab.com/elixxir/client/cmix"
 	"gitlab.com/elixxir/client/e2e"
+	"gitlab.com/elixxir/client/e2e/ratchet/partner/session"
 
 	"github.com/spf13/cobra"
 	jww "github.com/spf13/jwalterweatherman"
 	"github.com/spf13/viper"
 	"gitlab.com/elixxir/client/api"
-	"gitlab.com/elixxir/client/backup"
 	backupCrypto "gitlab.com/elixxir/crypto/backup"
 	"gitlab.com/elixxir/crypto/contact"
 	"gitlab.com/elixxir/primitives/excludedRounds"
@@ -212,18 +212,7 @@ var rootCmd = &cobra.Command{
 			recipientContact = user.GetContact()
 		}
 
-		confCh, recvCh := initClientCallbacks(client)
-
-		// The following block is used to check if the request from
-		// a channel authorization is from the recipient we intend in
-		// this run.
-		authConfirmed := false
-		go func() {
-			for {
-				requestor := <-confCh
-				authConfirmed = recipientID.Cmp(requestor)
-			}
-		}()
+		recvCh := registerMessageListener(client)
 
 		err := client.StartNetworkFollower(5 * time.Second)
 		if err != nil {
@@ -262,6 +251,7 @@ var rootCmd = &cobra.Command{
 		time.Sleep(10 * time.Second)
 
 		// Accept auth request for this recipient
+		authConfirmed := false
 		if viper.GetBool("accept-channel") {
 			acceptChannel(client, recipientID)
 			// Do not wait for channel confirmations if we
@@ -335,14 +325,14 @@ var rootCmd = &cobra.Command{
 			client.DeleteRequest(recipientID)
 		}
 
-		mt := catalog.XxMessage
+		mt := catalog.MessageType(catalog.XxMessage)
 		payload := []byte(msgBody)
 		recipient := recipientID
 		paramsE2E := e2e.GetDefaultParams()
 		wg := &sync.WaitGroup{}
 		sendCnt := int(viper.GetUint("sendCount"))
 		if viper.GetBool("splitSends") {
-			paramsE2E.ExcludedRounds = excludedRounds.NewSet()
+			paramsE2E.CMIX.ExcludedRounds = excludedRounds.NewSet()
 		}
 		wg.Add(sendCnt)
 		go func() {
@@ -356,16 +346,16 @@ var rootCmd = &cobra.Command{
 						var roundIDs []id.Round
 						var roundTimeout time.Duration
 						if unsafe {
-							paramsE2E.DebugTag = "cmd.Unsafe"
+							paramsE2E.CMIX.DebugTag = "cmd.Unsafe"
 							roundIDs, _, err = client.SendUnsafe(
 								mt, recipient, payload,
 								paramsE2E)
-							roundTimeout = paramsE2E.Timeout
+							roundTimeout = paramsE2E.CMIX.Timeout
 						} else {
-							paramsE2E.DebugTag = "cmd.E2E"
+							paramsE2E.CMIX.DebugTag = "cmd.E2E"
 							roundIDs, _, _, err = client.SendE2E(mt,
 								recipient, payload, paramsE2E)
-							roundTimeout = paramsE2E.Timeout
+							roundTimeout = paramsE2E.CMIX.Timeout
 						}
 						if err != nil {
 							jww.FATAL.Panicf("%+v", err)
@@ -377,9 +367,8 @@ var rootCmd = &cobra.Command{
 
 							// Construct the callback function which
 							// verifies successful message send or retries
-							f := func(allRoundsSucceeded, timedOut bool,
-								rounds map[id.Round]cmix.RoundLookupStatus) {
-								printRoundResults(allRoundsSucceeded, timedOut, rounds, roundIDs, msg)
+							f := func(allRoundsSucceeded, timedOut bool, rounds map[id.Round]cmix.RoundResult) {
+								printRoundResults(allRoundsSucceeded, timedOut, rounds, roundIDs, payload, recipientID)
 								if !allRoundsSucceeded {
 									retryChan <- struct{}{}
 								} else {
@@ -564,16 +553,24 @@ func createClient() *api.Client {
 		}
 	}
 
-	netParams := cmix.GetDefaultParams()
-	netParams.E2EParams.MinKeys = uint16(viper.GetUint("e2eMinKeys"))
-	netParams.E2EParams.MaxKeys = uint16(viper.GetUint("e2eMaxKeys"))
-	netParams.E2EParams.NumRekeys = uint16(
-		viper.GetUint("e2eNumReKeys"))
-	netParams.E2EParams.RekeyThreshold = viper.GetFloat64("e2eRekeyThreshold")
-	netParams.ForceHistoricalRounds = viper.GetBool("forceHistoricalRounds")
-	netParams.FastPolling = !viper.GetBool("slowPolling")
-	netParams.ForceMessagePickupRetry = viper.GetBool("forceMessagePickupRetry")
-	netParams.VerboseRoundTracking = viper.GetBool("verboseRoundTracking")
+	netParams := e2e.GetDefaultParams()
+	sessParams := session.GetDefaultParams()
+	sessParams.MinKeys = uint16(viper.GetUint("e2eMinKeys"))
+	sessParams.MaxKeys = uint16(viper.GetUint("e2eMaxKeys"))
+	sessParams.NumRekeys = uint16(viper.GetUint("e2eNumReKeys"))
+	sessParams.RekeyThreshold = viper.GetFloat64("e2eRekeyThreshold")
+	netParams.Network.Pickup.ForceHistoricalRounds = viper.GetBool(
+		"forceHistoricalRounds")
+	netParams.Network.FastPolling = !viper.GetBool("slowPolling")
+	netParams.Network.Pickup.ForceMessagePickupRetry = viper.GetBool(
+		"forceMessagePickupRetry")
+	if netParams.Network.Pickup.ForceMessagePickupRetry {
+		period := 3 * time.Second
+		jww.INFO.Printf("Setting Uncheck Round Period to %v", period)
+		netParams.Network.Pickup.UncheckRoundPeriod = period
+	}
+	netParams.Network.VerboseRoundTracking = viper.GetBool(
+		"verboseRoundTracking")
 
 	client, err := api.OpenClient(storeDir, pass, netParams)
 	if err != nil {
@@ -588,38 +585,46 @@ func initClient() *api.Client {
 	pass := parsePassword(viper.GetString("password"))
 	storeDir := viper.GetString("session")
 	jww.DEBUG.Printf("sessionDur: %v", storeDir)
-	netParams := cmix.GetDefaultParams()
-	netParams.E2EParams.MinKeys = uint16(viper.GetUint("e2eMinKeys"))
-	netParams.E2EParams.MaxKeys = uint16(viper.GetUint("e2eMaxKeys"))
-	netParams.E2EParams.NumRekeys = uint16(
-		viper.GetUint("e2eNumReKeys"))
-	netParams.E2EParams.RekeyThreshold = viper.GetFloat64("e2eRekeyThreshold")
-	netParams.ForceHistoricalRounds = viper.GetBool("forceHistoricalRounds")
-	netParams.FastPolling = !viper.GetBool("slowPolling")
-	netParams.ForceMessagePickupRetry = viper.GetBool("forceMessagePickupRetry")
-	if netParams.ForceMessagePickupRetry {
+	netParams := e2e.GetDefaultParams()
+	sessParams := session.GetDefaultParams()
+	sessParams.MinKeys = uint16(viper.GetUint("e2eMinKeys"))
+	sessParams.MaxKeys = uint16(viper.GetUint("e2eMaxKeys"))
+	sessParams.NumRekeys = uint16(viper.GetUint("e2eNumReKeys"))
+	sessParams.RekeyThreshold = viper.GetFloat64("e2eRekeyThreshold")
+	netParams.Network.Pickup.ForceHistoricalRounds = viper.GetBool(
+		"forceHistoricalRounds")
+	netParams.Network.FastPolling = !viper.GetBool("slowPolling")
+	netParams.Network.Pickup.ForceMessagePickupRetry = viper.GetBool(
+		"forceMessagePickupRetry")
+	if netParams.Network.Pickup.ForceMessagePickupRetry {
 		period := 3 * time.Second
 		jww.INFO.Printf("Setting Uncheck Round Period to %v", period)
-		netParams.UncheckRoundPeriod = period
+		netParams.Network.Pickup.UncheckRoundPeriod = period
 	}
-	netParams.VerboseRoundTracking = viper.GetBool("verboseRoundTracking")
+	netParams.Network.VerboseRoundTracking = viper.GetBool(
+		"verboseRoundTracking")
 
 	// load the client
-	client, err := api.Login(storeDir, pass, netParams)
+	authCbs := makeAuthCallbacks(nil,
+		viper.GetBool("unsafe-channel-creation"))
+	client, err := api.Login(storeDir, pass, authCbs, netParams)
+	authCbs.client = client
 	if err != nil {
 		jww.FATAL.Panicf("%+v", err)
 	}
 
 	if protoUser := viper.GetString("protoUserOut"); protoUser != "" {
 
-		jsonBytes, err := client.ConstructProtoUerFile()
+		jsonBytes, err := client.ConstructProtoUserFile()
 		if err != nil {
-			jww.FATAL.Panicf("Failed to construct proto user file: %v", err)
+			jww.FATAL.Panicf("cannot construct proto user file: %v",
+				err)
 		}
 
 		err = utils.WriteFileDef(protoUser, jsonBytes)
 		if err != nil {
-			jww.FATAL.Panicf("Failed to write proto user to file: %v", err)
+			jww.FATAL.Panicf("cannot write proto user to file: %v",
+				err)
 		}
 
 	}
@@ -627,11 +632,13 @@ func initClient() *api.Client {
 	if backupOut := viper.GetString("backupOut"); backupOut != "" {
 		backupPass := viper.GetString("backupPass")
 		updateBackupCb := func(encryptedBackup []byte) {
-			jww.INFO.Printf("Backup update received, size %d", len(encryptedBackup))
+			jww.INFO.Printf("Backup update received, size %d",
+				len(encryptedBackup))
 			fmt.Println("Backup update received.")
 			err = utils.WriteFileDef(backupOut, encryptedBackup)
 			if err != nil {
-				jww.FATAL.Panicf("Failed to write backup to file: %+v", err)
+				jww.FATAL.Panicf("cannot write backup: %+v",
+					err)
 			}
 
 			backupJsonPath := viper.GetString("backupJsonOut")
@@ -640,7 +647,7 @@ func initClient() *api.Client {
 				var b backupCrypto.Backup
 				err = b.Decrypt(backupPass, encryptedBackup)
 				if err != nil {
-					jww.ERROR.Printf("Failed to decrypt backup: %+v", err)
+					jww.ERROR.Printf("cannot decrypt backup: %+v", err)
 				}
 
 				backupJson, err := json.Marshal(b)
@@ -654,7 +661,8 @@ func initClient() *api.Client {
 				}
 			}
 		}
-		_, err = backup.InitializeBackup(backupPass, updateBackupCb, client)
+
+		_, err = client.InitializeBackup(backupPass, updateBackupCb)
 		if err != nil {
 			jww.FATAL.Panicf("Failed to initialize backup with key %q: %+v",
 				backupPass, err)
@@ -944,16 +952,18 @@ func initRoundLog(logPath string) {
 	if err != nil {
 		jww.FATAL.Panicf(err.Error())
 	}
-	roundsNotepad = jww.NewNotepad(jww.LevelInfo, jww.LevelInfo, ioutil.Discard, logOutput, "", log.Ldate|log.Ltime)
+	roundsNotepad = jww.NewNotepad(jww.LevelInfo, jww.LevelInfo,
+		ioutil.Discard, logOutput, "", log.Ldate|log.Ltime)
 }
 
 // init is the initialization function for Cobra which defines commands
 // and flags.
 func init() {
-	// NOTE: The point of init() is to be declarative.
-	// There is one init in each sub command. Do not put variable declarations
-	// here, and ensure all the Flags are of the *P variety, unless there's a
-	// very good reason not to have them as local params to sub command."
+	// NOTE: The point of init() is to be declarative.  There is
+	// one init in each sub command. Do not put variable
+	// declarations here, and ensure all the Flags are of the *P
+	// variety, unless there's a very good reason not to have them
+	// as local params to sub command."
 	cobra.OnInitialize(initConfig)
 
 	// Here you will define your flags and configuration settings.
@@ -1104,7 +1114,7 @@ func init() {
 		rootCmd.Flags().Lookup("forceMessagePickupRetry"))
 
 	// E2E Params
-	defaultE2EParams := e2e.GetDefaultParams()
+	defaultE2EParams := session.GetDefaultParams()
 	rootCmd.Flags().UintP("e2eMinKeys",
 		"", uint(defaultE2EParams.MinKeys),
 		"Minimum number of keys used before requesting rekey")
diff --git a/cmd/single.go b/cmd/single.go
index 42eb4d844..3c72ec96b 100644
--- a/cmd/single.go
+++ b/cmd/single.go
@@ -11,15 +11,18 @@ package cmd
 import (
 	"bytes"
 	"fmt"
+	"time"
+
 	"github.com/spf13/cobra"
 	jww "github.com/spf13/jwalterweatherman"
 	"github.com/spf13/viper"
-	"gitlab.com/elixxir/client/interfaces/message"
-	"gitlab.com/elixxir/client/single/old"
-	"gitlab.com/elixxir/client/switchboard"
+	"gitlab.com/elixxir/client/api"
+	"gitlab.com/elixxir/client/cmix"
+	"gitlab.com/elixxir/client/cmix/identity/receptionID"
+	"gitlab.com/elixxir/client/cmix/rounds"
+	"gitlab.com/elixxir/client/single"
 	"gitlab.com/elixxir/crypto/contact"
 	"gitlab.com/xx_network/primitives/utils"
-	"time"
 )
 
 // singleCmd is the single-use subcommand that allows for sending and responding
@@ -38,30 +41,6 @@ var singleCmd = &cobra.Command{
 		jww.INFO.Printf("User Transmission: %s", user.TransmissionID)
 		writeContact(user.GetContact())
 
-		// Set up reception handler
-		swBoard := client.GetSwitchboard()
-		recvCh := make(chan message.Receive, 10000)
-		listenerID := swBoard.RegisterChannel("DefaultCLIReceiver",
-			switchboard.AnyUser(), message.XxMessage, recvCh)
-		jww.INFO.Printf("Message ListenerID: %v", listenerID)
-
-		// Set up auth request handler, which simply prints the user ID of the
-		// requester
-		authMgr := client.GetAuthRegistrar()
-		authMgr.AddGeneralRequestCallback(printChanRequest)
-
-		// If unsafe channels, then add auto-acceptor
-		if viper.GetBool("unsafe-channel-creation") {
-			authMgr.AddGeneralRequestCallback(func(
-				requester contact.Contact) {
-				jww.INFO.Printf("Got request: %s", requester.ID)
-				_, err := client.ConfirmAuthenticatedChannel(requester)
-				if err != nil {
-					jww.FATAL.Panicf("%+v", err)
-				}
-			})
-		}
-
 		err := client.StartNetworkFollower(5 * time.Second)
 		if err != nil {
 			jww.FATAL.Panicf("%+v", err)
@@ -72,23 +51,25 @@ var singleCmd = &cobra.Command{
 		client.GetHealth().AddChannel(connected)
 		waitUntilConnected(connected)
 
-		// Make single-use manager and start receiving process
-		singleMng := old.NewManager(client)
-
 		// get the tag
 		tag := viper.GetString("tag")
 
 		// Register the callback
-		callbackChan := make(chan responseCallbackChan)
-		callback := func(payload []byte, c old.Contact) {
-			callbackChan <- responseCallbackChan{payload, c}
-		}
-		singleMng.RegisterCallback(tag, callback)
-		err = client.AddService(singleMng.StartProcesses)
-		if err != nil {
-			jww.FATAL.Panicf("Could not add single use process: %+v", err)
+		receiver := &Receiver{
+			recvCh: make(chan struct {
+				request *single.Request
+				ephID   receptionID.EphemeralIdentity
+				round   rounds.Round
+			}),
 		}
 
+		myID := client.GetUser().ReceptionID
+		listener := single.Listen(tag, myID,
+			client.GetUser().E2eDhPrivateKey,
+			client.GetNetworkInterface(),
+			client.GetStorage().GetE2EGroup(),
+			receiver)
+
 		for numReg, total := 1, 100; numReg < (total*3)/4; {
 			time.Sleep(1 * time.Second)
 			numReg, total, err = client.GetNodeRegistrationStatus()
@@ -108,14 +89,16 @@ var singleCmd = &cobra.Command{
 			partner := readSingleUseContact("contact")
 			maxMessages := uint8(viper.GetUint("maxMessages"))
 
-			sendSingleUse(singleMng, partner, payload, maxMessages, timeout, tag)
+			sendSingleUse(client, partner, payload,
+				maxMessages, timeout, tag)
 		}
 
-		// If the reply flag is set, then start waiting for a message and reply
-		// when it is received
+		// If the reply flag is set, then start waiting for a
+		// message and reply when it is received
 		if viper.GetBool("reply") {
-			replySingleUse(singleMng, timeout, callbackChan)
+			replySingleUse(client, timeout, receiver)
 		}
+		listener.Stop()
 	},
 }
 
@@ -148,19 +131,32 @@ func init() {
 	rootCmd.AddCommand(singleCmd)
 }
 
+type Response struct {
+	callbackChan chan struct {
+		payload []byte
+		err     error
+	}
+}
+
+func (r *Response) Callback(payload []byte, receptionID receptionID.EphemeralIdentity,
+	round rounds.Round, err error) {
+	jww.DEBUG.Printf("Payload: %v, receptionID: %v, round: %v, err: %v",
+		payload, receptionID, round, err)
+	r.callbackChan <- struct {
+		payload []byte
+		err     error
+	}{payload: payload, err: err}
+}
+
 // sendSingleUse sends a single use message.
-func sendSingleUse(m *old.Manager, partner contact.Contact, payload []byte,
+func sendSingleUse(m *api.Client, partner contact.Contact, payload []byte,
 	maxMessages uint8, timeout time.Duration, tag string) {
 	// Construct callback
-	callbackChan := make(chan struct {
-		payload []byte
-		err     error
-	})
-	callback := func(payload []byte, err error) {
-		callbackChan <- struct {
+	callback := &Response{
+		callbackChan: make(chan struct {
 			payload []byte
 			err     error
-		}{payload: payload, err: err}
+		}),
 	}
 
 	jww.INFO.Printf("Sending single-use message to contact: %+v", partner)
@@ -170,15 +166,25 @@ func sendSingleUse(m *old.Manager, partner contact.Contact, payload []byte,
 
 	// Send single-use message
 	fmt.Printf("Sending single-use transmission message: %s\n", payload)
-	jww.DEBUG.Printf("Sending single-use transmission to %s: %s", partner.ID, payload)
-	err := m.TransmitSingleUse(partner, payload, tag, maxMessages, callback, timeout)
+	jww.DEBUG.Printf("Sending single-use transmission to %s: %s",
+		partner.ID, payload)
+	params := single.GetDefaultRequestParams()
+	rng := m.GetRng().GetStream()
+	defer rng.Close()
+
+	e2eGrp := m.GetStorage().GetE2EGroup()
+	rnd, ephID, err := single.TransmitRequest(partner, tag, payload, callback, params,
+		m.GetNetworkInterface(), rng, e2eGrp)
 	if err != nil {
 		jww.FATAL.Panicf("Failed to transmit single-use message: %+v", err)
 	}
 
+	jww.INFO.Printf("Single Use request sent on round %v with id %v", rnd,
+		ephID)
+
 	// Wait for callback to be called
 	fmt.Println("Waiting for response.")
-	results := <-callbackChan
+	results := <-callback.callbackChan
 	if results.payload != nil {
 		fmt.Printf("Message received: %s\n", results.payload)
 		jww.DEBUG.Printf("Received single-use reply payload: %s", results.payload)
@@ -193,53 +199,73 @@ func sendSingleUse(m *old.Manager, partner contact.Contact, payload []byte,
 
 // replySingleUse responds to any single-use message it receives by replying\
 // with the same payload.
-func replySingleUse(m *old.Manager, timeout time.Duration, callbackChan chan responseCallbackChan) {
-
+func replySingleUse(m *api.Client, timeout time.Duration, receiver *Receiver) {
 	// Wait to receive a message or stop after timeout occurs
 	fmt.Println("Waiting for single-use message.")
 	timer := time.NewTimer(timeout)
 	select {
-	case results := <-callbackChan:
-		if results.payload != nil {
-			fmt.Printf("Single-use transmission received: %s\n", results.payload)
+	case results := <-receiver.recvCh:
+		payload := results.request.GetPayload()
+		if payload != nil {
+			fmt.Printf("Single-use transmission received: %s\n", payload)
 			jww.DEBUG.Printf("Received single-use transmission from %s: %s",
-				results.c.GetPartner(), results.payload)
+				results.request.GetPartner(), payload)
 		} else {
 			jww.ERROR.Print("Failed to receive single-use payload.")
 		}
 
 		// Create new payload from repeated received payloads so that each
 		// message part contains the same payload
-		payload := makeResponsePayload(m, results.payload, results.c.GetMaxParts())
+		resPayload := makeResponsePayload(payload, results.request.GetMaxParts(),
+			results.request.GetMaxResponseLength())
 
 		fmt.Printf("Sending single-use response message: %s\n", payload)
-		jww.DEBUG.Printf("Sending single-use response to %s: %s", results.c.GetPartner(), payload)
-		err := m.RespondSingleUse(results.c, payload, timeout)
+		jww.DEBUG.Printf("Sending single-use response to %s: %s",
+			results.request.GetPartner(), payload)
+		roundId, err := results.request.Respond(resPayload, cmix.GetDefaultCMIXParams(),
+			30*time.Second)
 		if err != nil {
 			jww.FATAL.Panicf("Failed to send response: %+v", err)
 		}
 
+		jww.INFO.Printf("response sent on roundID: %v", roundId)
+
 	case <-timer.C:
 		fmt.Println("Timed out!")
 		jww.FATAL.Panicf("Failed to receive transmission after %s.", timeout)
 	}
 }
 
-// responseCallbackChan structure used to collect information sent to the
-// response callback.
-type responseCallbackChan struct {
-	payload []byte
-	c       old.Contact
+type Receiver struct {
+	recvCh chan struct {
+		request *single.Request
+		ephID   receptionID.EphemeralIdentity
+		round   rounds.Round
+	}
+}
+
+func (r *Receiver) Callback(req *single.Request, ephID receptionID.EphemeralIdentity,
+	round rounds.Round) {
+	r.recvCh <- struct {
+		request *single.Request
+		ephID   receptionID.EphemeralIdentity
+		round   rounds.Round
+	}{
+		request: req,
+		ephID:   ephID,
+		round:   round,
+	}
+
 }
 
 // makeResponsePayload generates a new payload that will span the max number of
 // message parts in the contact. Each resulting message payload will contain a
 // copy of the supplied payload with spaces taking up any remaining data.
-func makeResponsePayload(m *old.Manager, payload []byte, maxParts uint8) []byte {
+func makeResponsePayload(payload []byte, maxParts uint8, maxSize int) []byte {
 	payloads := make([][]byte, maxParts)
-	payloadPart := makeResponsePayloadPart(m, payload)
+	payloadPart := makeResponsePayloadPart(payload, maxSize)
 	for i := range payloads {
-		payloads[i] = make([]byte, m.GetMaxResponsePayloadSize())
+		payloads[i] = make([]byte, maxSize)
 		copy(payloads[i], payloadPart)
 	}
 	return bytes.Join(payloads, []byte{})
@@ -247,8 +273,8 @@ func makeResponsePayload(m *old.Manager, payload []byte, maxParts uint8) []byte
 
 // makeResponsePayloadPart creates a single response payload by coping the given
 // payload and filling the rest with spaces.
-func makeResponsePayloadPart(m *old.Manager, payload []byte) []byte {
-	payloadPart := make([]byte, m.GetMaxResponsePayloadSize())
+func makeResponsePayloadPart(payload []byte, maxSize int) []byte {
+	payloadPart := make([]byte, maxSize)
 	for i := range payloadPart {
 		payloadPart[i] = ' '
 	}
diff --git a/cmd/ud.go b/cmd/ud.go
index 10271f53b..9a7466373 100644
--- a/cmd/ud.go
+++ b/cmd/ud.go
@@ -10,19 +10,11 @@ package cmd
 
 import (
 	"fmt"
-	"gitlab.com/elixxir/client/single/old"
-	"time"
 
 	"github.com/spf13/cobra"
 	jww "github.com/spf13/jwalterweatherman"
 	"github.com/spf13/viper"
-	"gitlab.com/elixxir/client/interfaces/message"
-	"gitlab.com/elixxir/client/switchboard"
-	"gitlab.com/elixxir/client/ud"
-	"gitlab.com/elixxir/client/xxmutils"
 	"gitlab.com/elixxir/crypto/contact"
-	"gitlab.com/elixxir/primitives/fact"
-	"gitlab.com/xx_network/primitives/utils"
 )
 
 // udCmd is the user discovery subcommand, which allows for user lookup,
@@ -34,225 +26,225 @@ var udCmd = &cobra.Command{
 	Short: "Register for and search users using the xx network user discovery service.",
 	Args:  cobra.NoArgs,
 	Run: func(cmd *cobra.Command, args []string) {
-		client := initClient()
-
-		// get user and save contact to file
-		user := client.GetUser()
-		jww.INFO.Printf("User: %s", user.ReceptionID)
-		writeContact(user.GetContact())
-
-		// Set up reception handler
-		swBoard := client.GetSwitchboard()
-		recvCh := make(chan message.Receive, 10000)
-		listenerID := swBoard.RegisterChannel("DefaultCLIReceiver",
-			switchboard.AnyUser(), message.XxMessage, recvCh)
-		jww.INFO.Printf("Message ListenerID: %v", listenerID)
-
-		// Set up auth request handler, which simply prints the user ID of the
-		// requester
-		authMgr := client.GetAuthRegistrar()
-		authMgr.AddGeneralRequestCallback(printChanRequest)
-
-		// If unsafe channels, add auto-acceptor
-		if viper.GetBool("unsafe-channel-creation") {
-			authMgr.AddGeneralRequestCallback(func(
-				requester contact.Contact) {
-				jww.INFO.Printf("Got Request: %s", requester.ID)
-				_, err := client.ConfirmAuthenticatedChannel(requester)
-				if err != nil {
-					jww.FATAL.Panicf("%+v", err)
-				}
-			})
-		}
-
-		err := client.StartNetworkFollower(50 * time.Millisecond)
-		if err != nil {
-			jww.FATAL.Panicf("%+v", err)
-		}
-
-		// Wait until connected or crash on timeout
-		connected := make(chan bool, 10)
-		client.GetHealth().AddChannel(connected)
-		waitUntilConnected(connected)
-
-		// Make single-use manager and start receiving process
-		singleMng := old.NewManager(client)
-		err = client.AddService(singleMng.StartProcesses)
-		if err != nil {
-			jww.FATAL.Panicf("Failed to add single use process: %+v", err)
-		}
-
-		// Make user discovery manager
-		userDiscoveryMgr, err := ud.NewManager(client, singleMng)
-		if err != nil {
-			jww.FATAL.Panicf("Failed to create new UD manager: %+v", err)
-		}
-
-		userToRegister := viper.GetString("register")
-		if userToRegister != "" {
-			err = userDiscoveryMgr.Register(userToRegister)
-			if err != nil {
-				fmt.Printf("Failed to register user %s: %s\n",
-					userToRegister, err.Error())
-				jww.FATAL.Panicf("Failed to register user %s: %+v", userToRegister, err)
-			}
-		}
-
-		var newFacts fact.FactList
-		phone := viper.GetString("addphone")
-		if phone != "" {
-			f, err := fact.NewFact(fact.Phone, phone)
-			if err != nil {
-				jww.FATAL.Panicf("Failed to create new fact: %+v", err)
-			}
-			newFacts = append(newFacts, f)
-		}
-
-		email := viper.GetString("addemail")
-		if email != "" {
-			f, err := fact.NewFact(fact.Email, email)
-			if err != nil {
-				jww.FATAL.Panicf("Failed to create new fact: %+v", err)
-			}
-			newFacts = append(newFacts, f)
-		}
-
-		for i := 0; i < len(newFacts); i++ {
-			r, err := userDiscoveryMgr.SendRegisterFact(newFacts[i])
-			if err != nil {
-				fmt.Printf("Failed to register fact: %s\n",
-					newFacts[i])
-				jww.FATAL.Panicf("Failed to send register fact: %+v", err)
-			}
-			// TODO Store the code?
-			jww.INFO.Printf("Fact Add Response: %+v", r)
-		}
-
-		confirmID := viper.GetString("confirm")
-		if confirmID != "" {
-			err = userDiscoveryMgr.SendConfirmFact(confirmID, confirmID)
-			if err != nil {
-				fmt.Printf("Couldn't confirm fact: %s\n",
-					err.Error())
-				jww.FATAL.Panicf("%+v", err)
-			}
-		}
-
-		// Handle lookup (verification) process
-		// Note: Cryptographic verification occurs above the bindings layer
-		lookupIDStr := viper.GetString("lookup")
-		if lookupIDStr != "" {
-			lookupID, _ := parseRecipient(lookupIDStr)
-			//if !ok {
-			//	jww.FATAL.Panicf("Could not parse recipient: %s", lookupIDStr)
-			//}
-			err = userDiscoveryMgr.Lookup(lookupID,
-				func(newContact contact.Contact, err error) {
-					if err != nil {
-						jww.FATAL.Panicf("UserDiscovery Lookup error: %+v", err)
-					}
-					printContact(newContact)
-				}, 30*time.Second)
-
-			if err != nil {
-				jww.WARN.Printf("Failed UD lookup: %+v", err)
-			}
-
-			time.Sleep(31 * time.Second)
-		}
-
-		if viper.GetString("batchadd") != "" {
-			idListFile, err := utils.ReadFile(viper.GetString("batchadd"))
-			if err != nil {
-				fmt.Printf("BATCHADD: Couldn't read file: %s\n",
-					err.Error())
-				jww.FATAL.Panicf("BATCHADD: Couldn't read file: %+v", err)
-			}
-			restored, _, _, err := xxmutils.RestoreContactsFromBackup(
-				idListFile, client, userDiscoveryMgr, nil)
-			if err != nil {
-				jww.FATAL.Panicf("%+v", err)
-			}
-			for i := 0; i < len(restored); i++ {
-				uid := restored[i]
-				for !client.HasAuthenticatedChannel(uid) {
-					time.Sleep(time.Second)
-				}
-				jww.INFO.Printf("Authenticated channel established for %s", uid)
-			}
-		}
-		usernameSearchStr := viper.GetString("searchusername")
-		emailSearchStr := viper.GetString("searchemail")
-		phoneSearchStr := viper.GetString("searchphone")
-
-		var facts fact.FactList
-		if usernameSearchStr != "" {
-			f, err := fact.NewFact(fact.Username, usernameSearchStr)
-			if err != nil {
-				jww.FATAL.Panicf("Failed to create new fact: %+v", err)
-			}
-			facts = append(facts, f)
-		}
-		if emailSearchStr != "" {
-			f, err := fact.NewFact(fact.Email, emailSearchStr)
-			if err != nil {
-				jww.FATAL.Panicf("Failed to create new fact: %+v", err)
-			}
-			facts = append(facts, f)
-		}
-		if phoneSearchStr != "" {
-			f, err := fact.NewFact(fact.Phone, phoneSearchStr)
-			if err != nil {
-				jww.FATAL.Panicf("Failed to create new fact: %+v", err)
-			}
-			facts = append(facts, f)
-		}
-
-		userToRemove := viper.GetString("remove")
-		if userToRemove != "" {
-			f, err := fact.NewFact(fact.Username, userToRemove)
-			if err != nil {
-				jww.FATAL.Panicf(
-					"Failed to create new fact: %+v", err)
-			}
-			err = userDiscoveryMgr.RemoveUser(f)
-			if err != nil {
-				fmt.Printf("Couldn't remove user %s\n",
-					userToRemove)
-				jww.FATAL.Panicf(
-					"Failed to remove user %s: %+v",
-					userToRemove, err)
-			}
-			fmt.Printf("Removed user from discovery: %s\n",
-				userToRemove)
-		}
-
-		if len(facts) == 0 {
-			err = client.StopNetworkFollower()
-			if err != nil {
-				jww.WARN.Print(err)
-			}
-			return
-		}
-
-		err = userDiscoveryMgr.Search(facts,
-			func(contacts []contact.Contact, err error) {
-				if err != nil {
-					jww.FATAL.Panicf("%+v", err)
-				}
-				for _, c := range contacts {
-					printContact(c)
-				}
-			}, 90*time.Second)
-		if err != nil {
-			jww.FATAL.Panicf("%+v", err)
-		}
-
-		time.Sleep(91 * time.Second)
-		err = client.StopNetworkFollower()
-		if err != nil {
-			jww.WARN.Print(err)
-		}
+		// client := initClient()
+
+		// // get user and save contact to file
+		// user := client.GetUser()
+		// jww.INFO.Printf("User: %s", user.ReceptionID)
+		// writeContact(user.GetContact())
+
+		// // Set up reception handler
+		// swBoard := client.GetSwitchboard()
+		// recvCh := make(chan message.Receive, 10000)
+		// listenerID := swBoard.RegisterChannel("DefaultCLIReceiver",
+		// 	switchboard.AnyUser(), message.XxMessage, recvCh)
+		// jww.INFO.Printf("Message ListenerID: %v", listenerID)
+
+		// // Set up auth request handler, which simply prints the user ID of the
+		// // requester
+		// authMgr := client.GetAuthRegistrar()
+		// authMgr.AddGeneralRequestCallback(printChanRequest)
+
+		// // If unsafe channels, add auto-acceptor
+		// if viper.GetBool("unsafe-channel-creation") {
+		// 	authMgr.AddGeneralRequestCallback(func(
+		// 		requester contact.Contact) {
+		// 		jww.INFO.Printf("Got Request: %s", requester.ID)
+		// 		_, err := client.ConfirmAuthenticatedChannel(requester)
+		// 		if err != nil {
+		// 			jww.FATAL.Panicf("%+v", err)
+		// 		}
+		// 	})
+		// }
+
+		// err := client.StartNetworkFollower(50 * time.Millisecond)
+		// if err != nil {
+		// 	jww.FATAL.Panicf("%+v", err)
+		// }
+
+		// // Wait until connected or crash on timeout
+		// connected := make(chan bool, 10)
+		// client.GetHealth().AddChannel(connected)
+		// waitUntilConnected(connected)
+
+		// // Make single-use manager and start receiving process
+		// singleMng := old.NewManager(client)
+		// err = client.AddService(singleMng.StartProcesses)
+		// if err != nil {
+		// 	jww.FATAL.Panicf("Failed to add single use process: %+v", err)
+		// }
+
+		// // Make user discovery manager
+		// userDiscoveryMgr, err := ud.NewManager(client, singleMng)
+		// if err != nil {
+		// 	jww.FATAL.Panicf("Failed to create new UD manager: %+v", err)
+		// }
+
+		// userToRegister := viper.GetString("register")
+		// if userToRegister != "" {
+		// 	err = userDiscoveryMgr.Register(userToRegister)
+		// 	if err != nil {
+		// 		fmt.Printf("Failed to register user %s: %s\n",
+		// 			userToRegister, err.Error())
+		// 		jww.FATAL.Panicf("Failed to register user %s: %+v", userToRegister, err)
+		// 	}
+		// }
+
+		// var newFacts fact.FactList
+		// phone := viper.GetString("addphone")
+		// if phone != "" {
+		// 	f, err := fact.NewFact(fact.Phone, phone)
+		// 	if err != nil {
+		// 		jww.FATAL.Panicf("Failed to create new fact: %+v", err)
+		// 	}
+		// 	newFacts = append(newFacts, f)
+		// }
+
+		// email := viper.GetString("addemail")
+		// if email != "" {
+		// 	f, err := fact.NewFact(fact.Email, email)
+		// 	if err != nil {
+		// 		jww.FATAL.Panicf("Failed to create new fact: %+v", err)
+		// 	}
+		// 	newFacts = append(newFacts, f)
+		// }
+
+		// for i := 0; i < len(newFacts); i++ {
+		// 	r, err := userDiscoveryMgr.SendRegisterFact(newFacts[i])
+		// 	if err != nil {
+		// 		fmt.Printf("Failed to register fact: %s\n",
+		// 			newFacts[i])
+		// 		jww.FATAL.Panicf("Failed to send register fact: %+v", err)
+		// 	}
+		// 	// TODO Store the code?
+		// 	jww.INFO.Printf("Fact Add Response: %+v", r)
+		// }
+
+		// confirmID := viper.GetString("confirm")
+		// if confirmID != "" {
+		// 	err = userDiscoveryMgr.SendConfirmFact(confirmID, confirmID)
+		// 	if err != nil {
+		// 		fmt.Printf("Couldn't confirm fact: %s\n",
+		// 			err.Error())
+		// 		jww.FATAL.Panicf("%+v", err)
+		// 	}
+		// }
+
+		// // Handle lookup (verification) process
+		// // Note: Cryptographic verification occurs above the bindings layer
+		// lookupIDStr := viper.GetString("lookup")
+		// if lookupIDStr != "" {
+		// 	lookupID, _ := parseRecipient(lookupIDStr)
+		// 	//if !ok {
+		// 	//	jww.FATAL.Panicf("Could not parse recipient: %s", lookupIDStr)
+		// 	//}
+		// 	err = userDiscoveryMgr.Lookup(lookupID,
+		// 		func(newContact contact.Contact, err error) {
+		// 			if err != nil {
+		// 				jww.FATAL.Panicf("UserDiscovery Lookup error: %+v", err)
+		// 			}
+		// 			printContact(newContact)
+		// 		}, 30*time.Second)
+
+		// 	if err != nil {
+		// 		jww.WARN.Printf("Failed UD lookup: %+v", err)
+		// 	}
+
+		// 	time.Sleep(31 * time.Second)
+		// }
+
+		// if viper.GetString("batchadd") != "" {
+		// 	idListFile, err := utils.ReadFile(viper.GetString("batchadd"))
+		// 	if err != nil {
+		// 		fmt.Printf("BATCHADD: Couldn't read file: %s\n",
+		// 			err.Error())
+		// 		jww.FATAL.Panicf("BATCHADD: Couldn't read file: %+v", err)
+		// 	}
+		// 	restored, _, _, err := xxmutils.RestoreContactsFromBackup(
+		// 		idListFile, client, userDiscoveryMgr, nil)
+		// 	if err != nil {
+		// 		jww.FATAL.Panicf("%+v", err)
+		// 	}
+		// 	for i := 0; i < len(restored); i++ {
+		// 		uid := restored[i]
+		// 		for !client.HasAuthenticatedChannel(uid) {
+		// 			time.Sleep(time.Second)
+		// 		}
+		// 		jww.INFO.Printf("Authenticated channel established for %s", uid)
+		// 	}
+		// }
+		// usernameSearchStr := viper.GetString("searchusername")
+		// emailSearchStr := viper.GetString("searchemail")
+		// phoneSearchStr := viper.GetString("searchphone")
+
+		// var facts fact.FactList
+		// if usernameSearchStr != "" {
+		// 	f, err := fact.NewFact(fact.Username, usernameSearchStr)
+		// 	if err != nil {
+		// 		jww.FATAL.Panicf("Failed to create new fact: %+v", err)
+		// 	}
+		// 	facts = append(facts, f)
+		// }
+		// if emailSearchStr != "" {
+		// 	f, err := fact.NewFact(fact.Email, emailSearchStr)
+		// 	if err != nil {
+		// 		jww.FATAL.Panicf("Failed to create new fact: %+v", err)
+		// 	}
+		// 	facts = append(facts, f)
+		// }
+		// if phoneSearchStr != "" {
+		// 	f, err := fact.NewFact(fact.Phone, phoneSearchStr)
+		// 	if err != nil {
+		// 		jww.FATAL.Panicf("Failed to create new fact: %+v", err)
+		// 	}
+		// 	facts = append(facts, f)
+		// }
+
+		// userToRemove := viper.GetString("remove")
+		// if userToRemove != "" {
+		// 	f, err := fact.NewFact(fact.Username, userToRemove)
+		// 	if err != nil {
+		// 		jww.FATAL.Panicf(
+		// 			"Failed to create new fact: %+v", err)
+		// 	}
+		// 	err = userDiscoveryMgr.RemoveUser(f)
+		// 	if err != nil {
+		// 		fmt.Printf("Couldn't remove user %s\n",
+		// 			userToRemove)
+		// 		jww.FATAL.Panicf(
+		// 			"Failed to remove user %s: %+v",
+		// 			userToRemove, err)
+		// 	}
+		// 	fmt.Printf("Removed user from discovery: %s\n",
+		// 		userToRemove)
+		// }
+
+		// if len(facts) == 0 {
+		// 	err = client.StopNetworkFollower()
+		// 	if err != nil {
+		// 		jww.WARN.Print(err)
+		// 	}
+		// 	return
+		// }
+
+		// err = userDiscoveryMgr.Search(facts,
+		// 	func(contacts []contact.Contact, err error) {
+		// 		if err != nil {
+		// 			jww.FATAL.Panicf("%+v", err)
+		// 		}
+		// 		for _, c := range contacts {
+		// 			printContact(c)
+		// 		}
+		// 	}, 90*time.Second)
+		// if err != nil {
+		// 	jww.FATAL.Panicf("%+v", err)
+		// }
+
+		// time.Sleep(91 * time.Second)
+		// err = client.StopNetworkFollower()
+		// if err != nil {
+		// 	jww.WARN.Print(err)
+		// }
 	},
 }
 
diff --git a/cmd/utils.go b/cmd/utils.go
index d881e4f0f..16bf5ea68 100644
--- a/cmd/utils.go
+++ b/cmd/utils.go
@@ -8,7 +8,6 @@ import (
 	jww "github.com/spf13/jwalterweatherman"
 	"github.com/spf13/viper"
 	"gitlab.com/elixxir/client/cmix"
-	"gitlab.com/elixxir/client/interfaces/message"
 	backupCrypto "gitlab.com/elixxir/crypto/backup"
 	"gitlab.com/elixxir/crypto/contact"
 	"gitlab.com/xx_network/primitives/id"
@@ -39,7 +38,8 @@ func loadBackup(backupPath, backupPass string) (backupCrypto.Backup, []byte) {
 
 // Helper function which prints the round resuls
 func printRoundResults(allRoundsSucceeded, timedOut bool,
-	rounds map[id.Round]cmix.RoundLookupStatus, roundIDs []id.Round, msg message.Send) {
+	rounds map[id.Round]cmix.RoundResult, roundIDs []id.Round,
+	payload []byte, recipient *id.ID) {
 
 	// Done as string slices for easy and human readable printing
 	successfulRounds := make([]string, 0)
@@ -50,9 +50,9 @@ func printRoundResults(allRoundsSucceeded, timedOut bool,
 		// Group all round reports into a category based on their
 		// result (successful, failed, or timed out)
 		if result, exists := rounds[r]; exists {
-			if result == cmix.Succeeded {
+			if result.Status == cmix.Succeeded {
 				successfulRounds = append(successfulRounds, strconv.Itoa(int(r)))
-			} else if result == cmix.Failed {
+			} else if result.Status == cmix.Failed {
 				failedRounds = append(failedRounds, strconv.Itoa(int(r)))
 			} else {
 				timedOutRounds = append(timedOutRounds, strconv.Itoa(int(r)))
@@ -61,7 +61,7 @@ func printRoundResults(allRoundsSucceeded, timedOut bool,
 	}
 
 	jww.INFO.Printf("Result of sending message \"%s\" to \"%v\":",
-		msg.Payload, msg.Recipient)
+		payload, recipient)
 
 	// Print out all rounds results, if they are populated
 	if len(successfulRounds) > 0 {
diff --git a/e2e/ratchet/partner/utils.go b/e2e/ratchet/partner/utils.go
index 656a847fc..ffd95db26 100644
--- a/e2e/ratchet/partner/utils.go
+++ b/e2e/ratchet/partner/utils.go
@@ -13,13 +13,14 @@
 package partner
 
 import (
+	"testing"
+
 	"github.com/cloudflare/circl/dh/sidh"
 	"gitlab.com/elixxir/client/cmix/message"
 	"gitlab.com/elixxir/client/e2e/ratchet/partner/session"
 	"gitlab.com/elixxir/crypto/contact"
 	"gitlab.com/elixxir/crypto/cyclic"
 	"gitlab.com/xx_network/primitives/id"
-	"testing"
 )
 
 // Test implementation of the Manager interface
@@ -64,7 +65,7 @@ func (p *testManager) ConnectionFingerprintBytes() []byte {
 	panic("implement me")
 }
 
-func (p *testManager) ConnectionFingerprint() string {
+func (p *testManager) ConnectionFingerprint() ConnectionFp {
 	panic("implement me")
 }
 
-- 
GitLab