diff --git a/api/client.go b/api/client.go
index d053f66d7b4b0793946e164b64dbcbe5d71c9eed..2e5934be9b4db2784476bd7a8d87a44b2132edcf 100644
--- a/api/client.go
+++ b/api/client.go
@@ -7,38 +7,46 @@
 package api
 
 import (
+	"bufio"
+	"crypto"
+	"crypto/sha256"
+	"encoding/base64"
+	"github.com/pkg/errors"
+	jww "github.com/spf13/jwalterweatherman"
 	"gitlab.com/elixxir/client/context"
+	"gitlab.com/elixxir/client/context/stoppable"
 	"gitlab.com/elixxir/client/context/switchboard"
-	"gitlab.com/elixxir/client/network"
 	"gitlab.com/elixxir/client/storage"
+	pb "gitlab.com/elixxir/comms/mixmessages"
+	"gitlab.com/xx_network/crypto/signature/rsa"
+	"gitlab.com/xx_network/crypto/tls"
+	"gitlab.com/xx_network/primitives/id"
 	"gitlab.com/xx_network/primitives/ndf"
-
-	"github.com/pkg/errors"
-	jww "github.com/spf13/jwalterweatherman"
+	"strings"
 )
 
 type Client struct {
 	storage     *storage.Session
 	ctx         *context.Context
 	switchboard *switchboard.Switchboard
-	network     *network.Network
+	network     context.NetworkManager
 }
 
 // NewClient creates client storage, generates keys, connects, and registers
 // with the network. Note that this does not register a username/identity, but
 // merely creates a new cryptographic identity for adding such information
 // at a later date.
-func NewClient(network, storageDir string, password []byte) (Client, error) {
+func NewClient(network, storageDir string, password []byte) (*Client, error) {
 	if clientStorageExists(storageDir) {
-		return errors.New("client already exists at %s",
+		return nil, errors.Errorf("client already exists at %s",
 			storageDir)
 	}
 
 	// Parse the NDF
-	ndf, err := parseNDF(network)
-	if err != nil {
-		return nil, err
-	}
+	//ndf, err := parseNDF(network)
+	//if err != nil {
+	//	return nil, err
+	//}
 
 	// Create Storage
 
@@ -48,7 +56,7 @@ func NewClient(network, storageDir string, password []byte) (Client, error) {
 
 	// Register with network
 
-	client = Client{
+	client := &Client{
 		storage:     nil,
 		ctx:         nil,
 		switchboard: nil,
@@ -58,9 +66,9 @@ func NewClient(network, storageDir string, password []byte) (Client, error) {
 }
 
 // LoadClient initalizes a client object from existing storage.
-func LoadClient(storageDir string, password []byte) (Client, error) {
+func LoadClient(storageDir string, password []byte) (*Client, error) {
 	if !clientStorageExists(storageDir) {
-		return errors.New("client does not exist at %s",
+		return nil, errors.Errorf("client does not exist at %s",
 			storageDir)
 	}
 
@@ -68,7 +76,7 @@ func LoadClient(storageDir string, password []byte) (Client, error) {
 
 	// Load and create network, context, switchboard
 
-	client = Client{
+	client := &Client{
 		storage:     nil,
 		ctx:         nil,
 		switchboard: nil,
@@ -81,16 +89,16 @@ func LoadClient(storageDir string, password []byte) (Client, error) {
 
 // RegisterListener registers a listener callback function that is called
 // every time a new message matches the specified parameters.
-func (c Client) RegisterListener(uid id.ID, msgType int, username string,
+func (c *Client) RegisterListenerCb(uid id.ID, msgType int, username string,
 	listenerCb func(msg Message)) {
-	jww.INFO.Printf("RegisterListener(%s, %d, %s, %v)", uid, msgType,
-		username, listenerCb)
+	jww.INFO.Printf("RegisterListener(%s, %d, %s, func())", uid, msgType,
+		username)
 }
 
 // SendE2E sends an end-to-end payload to the provided recipient with
 // the provided msgType. Returns the list of rounds in which parts of
 // the message were sent or an error if it fails.
-func (c Client) SendE2E(payload []byte, recipient id.ID, msgType int) (
+func (c *Client) SendE2E(payload []byte, recipient id.ID, msgType int) (
 	[]int, error) {
 	jww.INFO.Printf("SendE2E(%s, %s, %d)", payload, recipient,
 		msgType)
@@ -102,7 +110,7 @@ func (c Client) SendE2E(payload []byte, recipient id.ID, msgType int) (
 // of the message were sent or an error if it fails.
 // NOTE: Do not use this function unless you know what you are doing.
 // This function always produces an error message in client logging.
-func (c Client) SendUnsafe(payload []byte, recipient id.ID, msgType int) ([]int,
+func (c *Client) SendUnsafe(payload []byte, recipient id.ID, msgType int) ([]int,
 	error) {
 	jww.INFO.Printf("SendUnsafe(%s, %s, %d)", payload, recipient,
 		msgType)
@@ -113,9 +121,8 @@ func (c Client) SendUnsafe(payload []byte, recipient id.ID, msgType int) ([]int,
 // recipient. Note that both SendE2E and SendUnsafe call SendCMIX.
 // Returns the round ID of the round the payload was sent or an error
 // if it fails.
-func (c Client) SendCMIX(payload []byte, recipient id.ID) (int, error) {
-	jww.INFO.Printf("SendCMIX(%s, %s)", payload, recipient,
-		msgType)
+func (c *Client) SendCMIX(payload []byte, recipient id.ID) (int, error) {
+	jww.INFO.Printf("SendCMIX(%s, %s)", payload, recipient)
 	return 0, nil
 }
 
@@ -125,14 +132,45 @@ func (c Client) SendCMIX(payload []byte, recipient id.ID) (int, error) {
 // especially as these rely on third parties (i.e., Firebase *cough*
 // *cough* google's palantir *cough*) that may represent a security
 // risk to the user.
-func (c Client) RegisterForNotifications(token []byte) error {
+func (c *Client) RegisterForNotifications(token []byte) error {
 	jww.INFO.Printf("RegisterForNotifications(%s)", token)
+	// // Pull the host from the manage
+	// notificationBotHost, ok := cl.receptionManager.Comms.GetHost(&id.NotificationBot)
+	// if !ok {
+	// 	return errors.New("Failed to retrieve host for notification bot")
+	// }
+
+	// // Send the register message
+	// _, err := cl.receptionManager.Comms.RegisterForNotifications(notificationBotHost,
+	// 	&mixmessages.NotificationToken{
+	// 		Token: notificationToken,
+	// 	})
+	// if err != nil {
+	// 	err := errors.Errorf(
+	// 		"RegisterForNotifications: Unable to register for notifications! %s", err)
+	// 	return err
+	// }
+
 	return nil
 }
 
 // UnregisterForNotifications turns of notifications for this client
-func (c Client) UnregisterForNotifications() error {
+func (c *Client) UnregisterForNotifications() error {
 	jww.INFO.Printf("UnregisterForNotifications()")
+	// // Pull the host from the manage
+	// notificationBotHost, ok := cl.receptionManager.Comms.GetHost(&id.NotificationBot)
+	// if !ok {
+	// 	return errors.New("Failed to retrieve host for notification bot")
+	// }
+
+	// // Send the unregister message
+	// _, err := cl.receptionManager.Comms.UnregisterForNotifications(notificationBotHost)
+	// if err != nil {
+	// 	err := errors.Errorf(
+	// 		"RegisterForNotifications: Unable to register for notifications! %s", err)
+	// 	return err
+	// }
+
 	return nil
 }
 
@@ -142,16 +180,15 @@ func (c Client) UnregisterForNotifications() error {
 // out of band methods to exchange cryptographic identities
 // (e.g., QR codes), but failing to be registered precludes usage
 // of the user discovery mechanism (this may be preferred by user).
-func (c Client) IsRegistered() bool {
-	jww.INFO.Printf("IsRegistered(%s, %s, %d)", payload, recipient,
-		msgType)
+func (c *Client) IsRegistered() bool {
+	jww.INFO.Printf("IsRegistered()")
 	return false
 }
 
 // RegisterIdentity registers an arbitrary username with the user
 // discovery protocol. Returns an error when it cannot connect or
 // the username is already registered.
-func (c Client) RegisterIdentity(username string) error {
+func (c *Client) RegisterIdentity(username string) error {
 	jww.INFO.Printf("RegisterIdentity(%s)", username)
 	return nil
 }
@@ -159,7 +196,7 @@ func (c Client) RegisterIdentity(username string) error {
 // RegisterEmail makes the users email searchable after confirmation.
 // It returns a registration confirmation token to be used with
 // ConfirmRegistration or an error on failure.
-func (c Client) RegisterEmail(email string) ([]byte, error) {
+func (c *Client) RegisterEmail(email string) ([]byte, error) {
 	jww.INFO.Printf("RegisterEmail(%s)", email)
 	return nil, nil
 }
@@ -167,7 +204,7 @@ func (c Client) RegisterEmail(email string) ([]byte, error) {
 // RegisterPhone makes the users phone searchable after confirmation.
 // It returns a registration confirmation token to be used with
 // ConfirmRegistration or an error on failure.
-func (c Client) RegisterPhone(phone string) ([]byte, error) {
+func (c *Client) RegisterPhone(phone string) ([]byte, error) {
 	jww.INFO.Printf("RegisterPhone(%s)", phone)
 	return nil, nil
 }
@@ -175,28 +212,28 @@ func (c Client) RegisterPhone(phone string) ([]byte, error) {
 // ConfirmRegistration sends the user discovery agent a confirmation
 // token (from Register Email/Phone) and code (string sent via Email
 // or SMS to confirm ownership) to confirm ownership.
-func (c Client) ConfirmRegistration(token, code []byte) error {
+func (c *Client) ConfirmRegistration(token, code []byte) error {
 	jww.INFO.Printf("ConfirmRegistration(%s, %s)", token, code)
 	return nil
 }
 
 // GetUser returns the current user Identity for this client. This
 // can be serialized into a byte stream for out-of-band sharing.
-func (c Client) GetUser() (Contact, error) {
+func (c *Client) GetUser() (Contact, error) {
 	jww.INFO.Printf("GetUser()")
 	return Contact{}, nil
 }
 
 // MakeContact creates a contact from a byte stream (i.e., unmarshal's a
 // Contact object), allowing out-of-band import of identities.
-func (c Client) MakeContact(contactBytes []byte) (Contact, error) {
+func (c *Client) MakeContact(contactBytes []byte) (Contact, error) {
 	jww.INFO.Printf("MakeContact(%s)", contactBytes)
 	return Contact{}, nil
 }
 
 // GetContact returns a Contact object for the given user id, or
 // an error
-func (c Client) GetContact(uid []byte) (Contact, error) {
+func (c *Client) GetContact(uid []byte) (Contact, error) {
 	jww.INFO.Printf("GetContact(%s)", uid)
 	return Contact{}, nil
 }
@@ -204,19 +241,19 @@ func (c Client) GetContact(uid []byte) (Contact, error) {
 // Search accepts a "separator" separated list of search elements with
 // an associated list of searchTypes. It returns a ContactList which
 // allows you to iterate over the found contact objects.
-func (c Client) Search(data, separator string, searchTypes []byte) []Contact {
+func (c *Client) Search(data, separator string, searchTypes []byte) []Contact {
 	jww.INFO.Printf("Search(%s, %s, %s)", data, separator, searchTypes)
 	return nil
 }
 
 // SearchWithHandler is a non-blocking search that also registers
 // a callback interface for user disovery events.
-func (c Client) SearchWithCallback(data, separator string, searchTypes []byte,
+func (c *Client) SearchWithCallback(data, separator string, searchTypes []byte,
 	cb func(results []Contact)) {
 	resultCh := make(chan []Contact, 1)
 	go func(out chan []Contact, data, separator string, srchTypes []byte) {
 		out <- c.Search(data, separator, srchTypes)
-		out.Close()
+		close(out)
 	}(resultCh, data, separator, searchTypes)
 
 	go func(in chan []Contact, cb func(results []Contact)) {
@@ -232,23 +269,23 @@ func (c Client) SearchWithCallback(data, separator string, searchTypes []byte,
 // so this user can send messages to the desired recipient Contact.
 // To receive confirmation from the remote user, clients must
 // register a listener to do that.
-func (c Client) CreateAuthenticatedChannel(recipient Contact,
+func (c *Client) CreateAuthenticatedChannel(recipient Contact,
 	payload []byte) error {
-	jww.INFO.Printf("CreateAuthenticatedChannel(%s, %s)",
+	jww.INFO.Printf("CreateAuthenticatedChannel(%v, %v)",
 		recipient, payload)
 	return nil
 }
 
 // RegisterAuthConfirmationCb registers a callback for channel
 // authentication confirmation events.
-func (c Client) RegisterAuthConfirmationCb(cb func(contact Contact,
+func (c *Client) RegisterAuthConfirmationCb(cb func(contact Contact,
 	payload []byte)) {
 	jww.INFO.Printf("RegisterAuthConfirmationCb(...)")
 }
 
 // RegisterAuthRequestCb registers a callback for channel
 // authentication request events.
-func (c Client) RegisterAuthRequestCb(cb func(contact Contact,
+func (c *Client) RegisterAuthRequestCb(cb func(contact Contact,
 	payload []byte)) {
 	jww.INFO.Printf("RegisterAuthRequestCb(...)")
 }
@@ -257,13 +294,15 @@ func (c Client) RegisterAuthRequestCb(cb func(contact Contact,
 // and returns an object for checking state and stopping those threads.
 // Call this when returning from sleep and close when going back to
 // sleep.
-func (c Client) StartNetworkRunner() NetworkRunner {
+func (c *Client) StartNetworkRunner() stoppable.Stoppable {
 	jww.INFO.Printf("StartNetworkRunner()")
+	return nil
 }
 
 // RegisterRoundEventsCb registers a callback for round
 // events.
-func (c Client) RegisterRoundEventsCb(cb func(re RoundEvent)) {
+func (c *Client) RegisterRoundEventsCb(
+	cb func(re *pb.RoundInfo, timedOut bool)) {
 	jww.INFO.Printf("RegisterRoundEventsCb(...)")
 }
 
@@ -314,19 +353,19 @@ func parseNDF(ndfString string) (*ndf.NetworkDefinition, error) {
 	}
 
 	// Load the TLS cert given to us, and from that get the RSA public key
-	cert, err := tls.LoadCertificate(ndf.NdfPub)
+	cert, err := tls.LoadCertificate(ndf.Registration.TlsCertificate)
 	if err != nil {
 		return nil, err
 	}
-	pubKey := &rsa.PublicKey{PublicKey: *cert.PublicKey.(*gorsa.PublicKey)}
+	pubKey := cert.PublicKey.(*rsa.PublicKey)
 
 	// Hash NDF JSON
 	rsaHash := sha256.New()
 	rsaHash.Write(ndfData)
 
 	// Verify signature
-	err = rsa.Verify(
-		pubKey, crypto.SHA256, rsaHash.Sum(nil), ndfSignature, nil)
+	err = rsa.Verify(pubKey, crypto.SHA256,
+		rsaHash.Sum(nil), ndfSignature, nil)
 	if err != nil {
 		return nil, err
 	}
diff --git a/api/contact.go b/api/contact.go
index b0604b743854a7538bff45a6ea2f25b488af123c..07f3e6ec0463e08d738cfceb8ce6881b66264d2f 100644
--- a/api/contact.go
+++ b/api/contact.go
@@ -6,6 +6,11 @@
 
 package api
 
+import (
+	"gitlab.com/xx_network/crypto/signature/rsa"
+	"gitlab.com/xx_network/primitives/id"
+)
+
 // Contact implements the Contact interface defined in bindings/interfaces.go,
 type Contact struct {
 	ID            id.ID
@@ -22,7 +27,7 @@ func (c Contact) GetID() []byte {
 
 // GetPublicKey returns the publickey bytes for this user.
 func (c Contact) GetPublicKey() []byte {
-	return c.PubKey.Bytes()
+	return rsa.CreatePublicKeyPem(&c.PubKey)
 }
 
 // GetSalt returns the salt used to initiate an authenticated channel
diff --git a/api/interfaces.go b/api/interfaces.go
new file mode 100644
index 0000000000000000000000000000000000000000..5d8c04419cde6972ac3e253bcce8924a7f6d6e68
--- /dev/null
+++ b/api/interfaces.go
@@ -0,0 +1,45 @@
+////////////////////////////////////////////////////////////////////////////////
+// Copyright © 2020 Privategrity Corporation                                   /
+//                                                                             /
+// All rights reserved.                                                        /
+////////////////////////////////////////////////////////////////////////////////
+
+package api
+
+import (
+	"gitlab.com/xx_network/primitives/id"
+)
+
+// Message is a message received from the cMix network in the clear
+// or that has been decrypted using established E2E keys.
+type Message interface {
+	// Returns the message's sender ID, if available
+	GetSender() id.ID
+	GetSenderBytes() []byte
+
+	// Returns the message payload/contents
+	// Parse this with protobuf/whatever according to the message type
+	GetPayload() []byte
+
+	// Returns the message's recipient ID
+	// This is usually your userID but could be an ephemeral/group ID
+	GetRecipient() id.ID
+	GetRecipientBytes() []byte
+
+	// Returns the message's type
+	GetMessageType() int32
+
+	// Returns the message's timestamp in seconds since unix epoc
+	GetTimestamp() int64
+	// Returns the message's timestamp in ns since unix epoc
+	GetTimestampNano() int64
+}
+
+// RoundEvent contains event information for a given round.
+// TODO: This is a half-baked interface and will be filled out later.
+type RoundEvent interface {
+	// GetID returns the round ID for this round.
+	GetID() int
+	// GetStatus returns the status of this round.
+	GetStatus() int
+}
diff --git a/api/ndf_test.go b/api/ndf_test.go
deleted file mode 100644
index 82be0622881d5f778263e1516389fa8ab77627ef..0000000000000000000000000000000000000000
--- a/api/ndf_test.go
+++ /dev/null
@@ -1,159 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-// Copyright © 2019 Privategrity Corporation                                    /
-//                                                                             /
-// All rights reserved.                                                        /
-////////////////////////////////////////////////////////////////////////////////
-
-package api
-
-import (
-	"crypto"
-	"crypto/rand"
-	"encoding/base64"
-	"fmt"
-	"gitlab.com/xx_network/crypto/signature/rsa"
-	"gitlab.com/xx_network/primitives/ndf"
-	"reflect"
-	"testing"
-)
-
-var ExampleJSON = `{"Timestamp": "2019-06-04T20:48:48-07:00", "gateways": [{"Address": "52.25.135.52", "Tls_certificate": "-----BEGIN CERTIFICATE-----\nMIIDgTCCAmmgAwIBAgIJAKLdZ8UigIAeMA0GCSqGSIb3DQEBBQUAMG8xCzAJBgNV\nBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQHDAlDbGFyZW1vbnQx\nGzAZBgNVBAoMElByaXZhdGVncml0eSBDb3JwLjEaMBgGA1UEAwwRZ2F0ZXdheSou\nY21peC5yaXAwHhcNMTkwMzA1MTgzNTU0WhcNMjkwMzAyMTgzNTU0WjBvMQswCQYD\nVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJQ2xhcmVtb250\nMRswGQYDVQQKDBJQcml2YXRlZ3JpdHkgQ29ycC4xGjAYBgNVBAMMEWdhdGV3YXkq\nLmNtaXgucmlwMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA9+AaxwDP\nxHbhLmn4HoZu0oUM48Qufc6T5XEZTrpMrqJAouXk+61Jc0EFH96/sbj7VyvnXPRo\ngIENbk2Y84BkB9SkRMIXya/gh9dOEDSgnvj/yg24l3bdKFqBMKiFg00PYB30fU+A\nbe3OI/le0I+v++RwH2AV0BMq+T6PcAGjCC1Q1ZB0wP9/VqNMWq5lbK9wD46IQiSi\n+SgIQeE7HoiAZXrGO0Y7l9P3+VRoXjRQbqfn3ETNL9ZvQuarwAYC9Ix5MxUrS5ag\nOmfjc8bfkpYDFAXRXmdKNISJmtCebX2kDrpP8Bdasx7Fzsx59cEUHCl2aJOWXc7R\n5m3juOVL1HUxjQIDAQABoyAwHjAcBgNVHREEFTATghFnYXRld2F5Ki5jbWl4LnJp\ncDANBgkqhkiG9w0BAQUFAAOCAQEAMu3xoc2LW2UExAAIYYWEETggLNrlGonxteSu\njuJjOR+ik5SVLn0lEu22+z+FCA7gSk9FkWu+v9qnfOfm2Am+WKYWv3dJ5RypW/hD\nNXkOYxVJNYFxeShnHohNqq4eDKpdqSxEcuErFXJdLbZP1uNs4WIOKnThgzhkpuy7\ntZRosvOF1X5uL1frVJzHN5jASEDAa7hJNmQ24kh+ds/Ge39fGD8pK31CWhnIXeDo\nvKD7wivi/gSOBtcRWWLvU8SizZkS3hgTw0lSOf5geuzvasCEYlqrKFssj6cTzbCB\nxy3ra3WazRTNTW4TmkHlCUC9I3oWTTxw5iQxF/I2kQQnwR7L3w==\n-----END CERTIFICATE-----"}, {"Address": "52.25.219.38", "Tls_certificate": "-----BEGIN CERTIFICATE-----\nMIIDgTCCAmmgAwIBAgIJAKLdZ8UigIAeMA0GCSqGSIb3DQEBBQUAMG8xCzAJBgNV\nBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQHDAlDbGFyZW1vbnQx\nGzAZBgNVBAoMElByaXZhdGVncml0eSBDb3JwLjEaMBgGA1UEAwwRZ2F0ZXdheSou\nY21peC5yaXAwHhcNMTkwMzA1MTgzNTU0WhcNMjkwMzAyMTgzNTU0WjBvMQswCQYD\nVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJQ2xhcmVtb250\nMRswGQYDVQQKDBJQcml2YXRlZ3JpdHkgQ29ycC4xGjAYBgNVBAMMEWdhdGV3YXkq\nLmNtaXgucmlwMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA9+AaxwDP\nxHbhLmn4HoZu0oUM48Qufc6T5XEZTrpMrqJAouXk+61Jc0EFH96/sbj7VyvnXPRo\ngIENbk2Y84BkB9SkRMIXya/gh9dOEDSgnvj/yg24l3bdKFqBMKiFg00PYB30fU+A\nbe3OI/le0I+v++RwH2AV0BMq+T6PcAGjCC1Q1ZB0wP9/VqNMWq5lbK9wD46IQiSi\n+SgIQeE7HoiAZXrGO0Y7l9P3+VRoXjRQbqfn3ETNL9ZvQuarwAYC9Ix5MxUrS5ag\nOmfjc8bfkpYDFAXRXmdKNISJmtCebX2kDrpP8Bdasx7Fzsx59cEUHCl2aJOWXc7R\n5m3juOVL1HUxjQIDAQABoyAwHjAcBgNVHREEFTATghFnYXRld2F5Ki5jbWl4LnJp\ncDANBgkqhkiG9w0BAQUFAAOCAQEAMu3xoc2LW2UExAAIYYWEETggLNrlGonxteSu\njuJjOR+ik5SVLn0lEu22+z+FCA7gSk9FkWu+v9qnfOfm2Am+WKYWv3dJ5RypW/hD\nNXkOYxVJNYFxeShnHohNqq4eDKpdqSxEcuErFXJdLbZP1uNs4WIOKnThgzhkpuy7\ntZRosvOF1X5uL1frVJzHN5jASEDAa7hJNmQ24kh+ds/Ge39fGD8pK31CWhnIXeDo\nvKD7wivi/gSOBtcRWWLvU8SizZkS3hgTw0lSOf5geuzvasCEYlqrKFssj6cTzbCB\nxy3ra3WazRTNTW4TmkHlCUC9I3oWTTxw5iQxF/I2kQQnwR7L3w==\n-----END CERTIFICATE-----"}, {"Address": "52.41.80.104", "Tls_certificate": "-----BEGIN CERTIFICATE-----\nMIIDgTCCAmmgAwIBAgIJAKLdZ8UigIAeMA0GCSqGSIb3DQEBBQUAMG8xCzAJBgNV\nBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQHDAlDbGFyZW1vbnQx\nGzAZBgNVBAoMElByaXZhdGVncml0eSBDb3JwLjEaMBgGA1UEAwwRZ2F0ZXdheSou\nY21peC5yaXAwHhcNMTkwMzA1MTgzNTU0WhcNMjkwMzAyMTgzNTU0WjBvMQswCQYD\nVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJQ2xhcmVtb250\nMRswGQYDVQQKDBJQcml2YXRlZ3JpdHkgQ29ycC4xGjAYBgNVBAMMEWdhdGV3YXkq\nLmNtaXgucmlwMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA9+AaxwDP\nxHbhLmn4HoZu0oUM48Qufc6T5XEZTrpMrqJAouXk+61Jc0EFH96/sbj7VyvnXPRo\ngIENbk2Y84BkB9SkRMIXya/gh9dOEDSgnvj/yg24l3bdKFqBMKiFg00PYB30fU+A\nbe3OI/le0I+v++RwH2AV0BMq+T6PcAGjCC1Q1ZB0wP9/VqNMWq5lbK9wD46IQiSi\n+SgIQeE7HoiAZXrGO0Y7l9P3+VRoXjRQbqfn3ETNL9ZvQuarwAYC9Ix5MxUrS5ag\nOmfjc8bfkpYDFAXRXmdKNISJmtCebX2kDrpP8Bdasx7Fzsx59cEUHCl2aJOWXc7R\n5m3juOVL1HUxjQIDAQABoyAwHjAcBgNVHREEFTATghFnYXRld2F5Ki5jbWl4LnJp\ncDANBgkqhkiG9w0BAQUFAAOCAQEAMu3xoc2LW2UExAAIYYWEETggLNrlGonxteSu\njuJjOR+ik5SVLn0lEu22+z+FCA7gSk9FkWu+v9qnfOfm2Am+WKYWv3dJ5RypW/hD\nNXkOYxVJNYFxeShnHohNqq4eDKpdqSxEcuErFXJdLbZP1uNs4WIOKnThgzhkpuy7\ntZRosvOF1X5uL1frVJzHN5jASEDAa7hJNmQ24kh+ds/Ge39fGD8pK31CWhnIXeDo\nvKD7wivi/gSOBtcRWWLvU8SizZkS3hgTw0lSOf5geuzvasCEYlqrKFssj6cTzbCB\nxy3ra3WazRTNTW4TmkHlCUC9I3oWTTxw5iQxF/I2kQQnwR7L3w==\n-----END CERTIFICATE-----"}], "nodes": [{"Id": [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], "Dsa_public_key": "-----BEGIN PUBLIC KEY-----\nMIIDNDCCAiwCggEBAJ22+1lRtmu2/h4UDx0s5VAjdBYf1lON8WSCGGQvC1xIyPek\nGq36GHMkuHZ0+hgisA8ez4E2lD18VXVyZOWhpE/+AS6ZNuAMHT6TELAcfReYBdMF\niyqfS7b5cWv+YRfGtbPMTZvjQRBK1KgK1slOAF9LmT4U8JHrUXQ78zBQw43iNVZ+\nGzTD1qXAzqoaDzaCE8PRmEPQtLCdy5/HLTnI3kHxvxTUu0Vjyig3FiHK0zJLai05\nIUW+v6x0iAUjb1yi/pK4cc2PnDbTKStVCcqMqneirfx7/XfdpvcRJadFb+oVPkMy\nVqImHGoG7TaTeX55lfrVqrvPvj7aJ0HjdUBK4lsCIQDywxGTdM52yTVpkLRlN0oX\n8j+e01CJvZafYcbd6ZmMHwKCAQBcf/awb48UP+gohDNJPkdpxNmIrOW+JaDiSAln\nBxbGE9ewzuaTL4+qfETSyyRSPaU/vk9uw1lYktGqWMQyigbEahVmLn6qcDod7Pi7\nstBdvi65VsFCozhmHRBGHA0TVHIIUFfzSUMJ/6c8YR94syrbtXQMNhyfNb6QmX2y\nAU4u9apheC9Sq+uL1kMsTdCXvFQjsoXa+2DcNk6BYfSio1rKOhCxxNIDzHakcKM6\n/cvdkpWYWavYtW4XJSUteOrGbnG6muPx3SSHGZh0OTzU2DIYaABlR2Dh40wJ5NFV\nF5+ewNxEc/mWvc5u7Ryr7YtvEW962c9QXfD5mONKsnUUsP/nAoIBAERwUmUlL9YP\nq6MSn+bUr6qNZPsVYoQAo8nTjZWiuSjJa2XWnh7sftnISWkwkiiRxo7qfq3sAiD5\nB8+tM6kONeICBXukldXJerxoVBspYa+RiPuDWy2pwGRDBpfty3QqJOpu5g2ThYFJ\nD5Xu0yCuX8ZJRj33nliI8dQgKdQQva6p2VuXzyRT8LwXMfRwLuSB6Schc9mF8C\nkWCb4m0ujlEKe1xKoKt2zG9b1o7XyaVhxguSUAuEznifMzsEUfuONJOy+XoQELex\nF0wvLzNzABcyxkM3lx52uG41mKgJiV6Z0ZyuBRvt+V3VL/38tPn9lsTaFi8N6/IH\nRyy0bWP5s44=\n-----END PUBLIC KEY-----\n", "Address": "18.237.147.105", "Tls_certificate": "-----BEGIN CERTIFICATE-----MIIDbDCCAlSgAwIBAgIJAOUNtZneIYECMA0GCSqGSIb3DQEBBQUAMGgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQHDAlDbGFyZW1vbnQxGzAZBgNVBAoMElByaXZhdGVncml0eSBDb3JwLjETMBEGA1UEAwwKKi5jbWl4LnJpcDAeFwOTAzMDUxODM1NDNaFw0yOTAzMDIxODM1NDNaMGgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQHDAlDbGFyZW1vbnQxGzAZBgNVBAoMElByaXZhdGVncml0eSBDb3JwLjETMBEGA1UEAwwKKi5jbWl4LnJpcDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPP0WyVkfZA/CEd2DgKpcudn0oDhDwsjmx8LBDWsUgQzyLrFiVigfUmUefknUH3dTJjmiJtGqLsayCnWdqWLHPJYvFfsWYW0IGF93UG/4N5UAWO4okC3CYgKSi4ekpfw2zgZq0gmbzTnXcHF9gfmQ7jJUKSEtJPSNzXq+PZeJTC9zJAb4Lj8QzH18rDM8DaL2y1ns0Y2Hu0edBFn/OqavBJKb/uAm3AEjqeOhC7EQUjVamWlTBPt40+B/6aFJX5BYm2JFkRsGBIyBVL46MvC02MgzTT9bJIJfwqmBaTruwemNgzGu7Jk03hqqS1TUEvSI6/x8bVoba3orcKkf9HsDjECAwEAAaMZMBcwFQYDVR0RBA4wDIIKKi5jbWl4LnJpcDANBgkqhkiG9w0BAQUFAAOCAQEAneUocN4AbcQAC1+b3To8u5UGdaGxhcGyZBlAoenRVdjXK3lTjsMdMWb4QctgNfIfU/zuUn2mxTmF/ekP0gCCgtleZr9+DYKU5hlXk8K10uKxGD6EvoiXZzlfeUuotgp2qvI3ysOm/hvCfyEkqhfHtbxjV7j7v7eQFPbvNaXbLa0yr4C4vMK/Z09Ui9JrZ/Z4cyIkxfC6/rOqAirSdIp09EGiw7GM8guHyggE4IiZrDslT8V3xIl985cbCxSxeW1RtgH4rdEXuVe9+31oJhmXOE9ux2jCop9tEJMgWg7HStrJ5plPbb+HmjoX3nBO04E56m52PyzMNV+2N21IPppKwA==-----END CERTIFICATE-----"}, {"Id": [2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], "Dsa_public_key": "-----BEGIN PUBLIC KEY-----\nMIIDNDCCAiwCggEBAJ22+1lRtmu2/h4UDx0s5VAjdBYf1lON8WSCGGQvC1xIyPek\nGq36GHMkuHZ0+hgisA8ez4E2lD18VXVyZOWhpE/+AS6ZNuAMHT6TELAcfReYBdMF\niyqfS7b5cWv+YRfGtbPMTZvjQRBK1KgK1slOAF9LmT4U8JHrUXQ78zBQw43iNVZ+\nGzTD1qXAzqoaDzaCE8PRmEPQtLCdy5/HLTnI3kHxvxTUu0Vjyig3FiHK0zJLai05\nIUW+v6x0iAUjb1yi/pK4cc2PnDbTKStVCcqMqneirfx7/XfdpvcRJadFb+oVPkMy\nVqImHGoG7TaTeX55lfrVqrvPvj7aJ0HjdUBK4lsCIQDywxGTdM52yTVpkLRlN0oX\n8j+e01CJvZafYcbd6ZmMHwKCAQBcf/awb48UP+gohDNJPkdpxNmIrOW+JaDiSAln\nBxbGE9ewzuaTL4+qfETSyyRSPaU/vk9uw1lYktGqWMQyigbEahVmLn6qcDod7Pi7\nstBdvi65VsFCozhmHRBGHA0TVHIIUFfzSUMJ/6c8YR94syrbtXQMNhyfNb6QmX2y\nAU4u9apheC9Sq+uL1kMsTdCXvFQjsoXa+2DcNk6BYfSio1rKOhCxxNIDzHakcKM6\n/cvdkpWYWavYtW4XJSUteOrGbnG6muPx3SSHGZh0OTzU2DIYaABlR2Dh40wJ5NFV\nF5+ewNxEc/mWvc5u7Ryr7YtvEW962c9QXfD5mONKsnUUsP/nAoIBAFbADcqA8KQh\nxzgylW6VS1dYYelO5DjPZVVSjfdcbj1twu4ZHDNZLOexpv4nGY8xS6vesELXcVOR\n/CHXgh/3byBZYm0zkrBi/FsJJ3nP2uZ1+QCRldI2KzqcLOWH/CAYj8koork9k1Dp\nFq7rMSDgw4pktqvFj9Eev8dSZuRnoCfZbt/6vxi1r30AYAjDYOwcysqcVyUa1tPa\nLEh3JksttXUCd5cvfqatWedTs5Vxo7ICW1toGBHABYvSJkwK0YFfi5RLw+Oda1sA\njJ+aLcIxQjrpoRC2alXCdwmZXVb+O6zluQctw6LJjt4J704ueSvR4VNNhr0uLYGW\nk7e+WoQCS98=\n-----END PUBLIC KEY-----\n", "Address": "52.11.136.238", "Tls_certificate": "-----BEGIN CERTIFICATE-----MIIDbDCCAlSgAwIBAgIJAOUNtZneIYECMA0GCSqGSIb3DQEBBQUAMGgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQHDAlDbGFyZW1vbnQxGzAZBgNVBAoMElByaXZhdGVncml0eSBDb3JwLjETMBEGA1UEAwwKKi5jbWl4LnJpcDAeFwOTAzMDUxODM1NDNaFw0yOTAzMDIxODM1NDNaMGgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQHDAlDbGFyZW1vbnQxGzAZBgNVBAoMElByaXZhdGVncml0eSBDb3JwLjETMBEGA1UEAwwKKi5jbWl4LnJpcDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPP0WyVkfZA/CEd2DgKpcudn0oDhDwsjmx8LBDWsUgQzyLrFiVigfUmUefknUH3dTJjmiJtGqLsayCnWdqWLHPJYvFfsWYW0IGF93UG/4N5UAWO4okC3CYgKSi4ekpfw2zgZq0gmbzTnXcHF9gfmQ7jJUKSEtJPSNzXq+PZeJTC9zJAb4Lj8QzH18rDM8DaL2y1ns0Y2Hu0edBFn/OqavBJKb/uAm3AEjqeOhC7EQUjVamWlTBPt40+B/6aFJX5BYm2JFkRsGBIyBVL46MvC02MgzTT9bJIJfwqmBaTruwemNgzGu7Jk03hqqS1TUEvSI6/x8bVoba3orcKkf9HsDjECAwEAAaMZMBcwFQYDVR0RBA4wDIIKKi5jbWl4LnJpcDANBgkqhkiG9w0BAQUFAAOCAQEAneUocN4AbcQAC1+b3To8u5UGdaGxhcGyZBlAoenRVdjXK3lTjsMdMWb4QctgNfIfU/zuUn2mxTmF/ekP0gCCgtleZr9+DYKU5hlXk8K10uKxGD6EvoiXZzlfeUuotgp2qvI3ysOm/hvCfyEkqhfHtbxjV7j7v7eQFPbvNaXbLa0yr4C4vMK/Z09Ui9JrZ/Z4cyIkxfC6/rOqAirSdIp09EGiw7GM8guHyggE4IiZrDslT8V3xIl985cbCxSxeW1RtgH4rdEXuVe9+31oJhmXOE9ux2jCop9tEJMgWg7HStrJ5plPbb+HmjoX3nBO04E56m52PyzMNV+2N21IPppKwA==-----END CERTIFICATE-----"}, {"Id": [3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], "Dsa_public_key": "-----BEGIN PUBLIC KEY-----\nMIIDNTCCAiwCggEBAJ22+1lRtmu2/h4UDx0s5VAjdBYf1lON8WSCGGQvC1xIyPek\nGq36GHMkuHZ0+hgisA8ez4E2lD18VXVyZOWhpE/+AS6ZNuAMHT6TELAcfReYBdMF\niyqfS7b5cWv+YRfGtbPMTZvjQRBK1KgK1slOAF9LmT4U8JHrUXQ78zBQw43iNVZ+\nGzTD1qXAzqoaDzaCE8PRmEPQtLCdy5/HLTnI3kHxvxTUu0Vjyig3FiHK0zJLai05\nIUW+v6x0iAUjb1yi/pK4cc2PnDbTKStVCcqMqneirfx7/XfdpvcRJadFb+oVPkMy\nVqImHGoG7TaTeX55lfrVqrvPvj7aJ0HjdUBK4lsCIQDywxGTdM52yTVpkLRlN0oX\n8j+e01CJvZafYcbd6ZmMHwKCAQBcf/awb48UP+gohDNJPkdpxNmIrOW+JaDiSAln\nBxbGE9ewzuaTL4+qfETSyyRSPaU/vk9uw1lYktGqWMQyigbEahVmLn6qcDod7Pi7\nstBdvi65VsFCozhmHRBGHA0TVHIIUFfzSUMJ/6c8YR94syrbtXQMNhyfNb6QmX2y\nAU4u9apheC9Sq+uL1kMsTdCXvFQjsoXa+2DcNk6BYfSio1rKOhCxxNIDzHakcKM6\n/cvdkpWYWavYtW4XJSUteOrGbnG6muPx3SSHGZh0OTzU2DIYaABlR2Dh40wJ5NFV\nF5+ewNxEc/mWvc5u7Ryr7YtvEW962c9QXfD5mONKsnUUsP/nAoIBAQCN19tTnkS3\nitBQXXR/h8OKl+rliFBLgO6h6GvZL4yQDZFtBAOmkrs3wLoDroJRGCeqz/IUb+JF\njslEr/mpm2kcmK77hr535dq7HsWz1fFl9YyGTaOH055FLSV9QEPAV9j3zWADdQ1v\nuSQll+QfWi6lIibWV4HNQ2ywRFoOY8OBLCJB90UXLeJpaPanpqiM8hjda2VGRDbi\nIixEE2lCOWITydiz2DmvXrLhVGF49+g5MDwbWO65dmasCe//Ff6Z4bJ6n049xv\nVtac8nX6FO3eBsV5d+rG6HZXSG3brCKRCSKYCTX1IkTSiutYxYqvwaluoCjOakh0\nKkqvQ8IeVZ+B\n-----END PUBLIC KEY-----\n", "Address": "34.213.79.31", "Tls_certificate": "-----BEGIN CERTIFICATE-----MIIDbDCCAlSgAwIBAgIJAOUNtZneIYECMA0GCSqGSIb3DQEBBQUAMGgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQHDAlDbGFyZW1vbnQxGzAZBgNVBAoMElByaXZhdGVncml0eSBDb3JwLjETMBEGA1UEAwwKKi5jbWl4LnJpcDAeFwOTAzMDUxODM1NDNaFw0yOTAzMDIxODM1NDNaMGgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQHDAlDbGFyZW1vbnQxGzAZBgNVBAoMElByaXZhdGVncml0eSBDb3JwLjETMBEGA1UEAwwKKi5jbWl4LnJpcDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPP0WyVkfZA/CEd2DgKpcudn0oDhDwsjmx8LBDWsUgQzyLrFiVigfUmUefknUH3dTJjmiJtGqLsayCnWdqWLHPJYvFfsWYW0IGF93UG/4N5UAWO4okC3CYgKSi4ekpfw2zgZq0gmbzTnXcHF9gfmQ7jJUKSEtJPSNzXq+PZeJTC9zJAb4Lj8QzH18rDM8DaL2y1ns0Y2Hu0edBFn/OqavBJKb/uAm3AEjqeOhC7EQUjVamWlTBPt40+B/6aFJX5BYm2JFkRsGBIyBVL46MvC02MgzTT9bJIJfwqmBaTruwemNgzGu7Jk03hqqS1TUEvSI6/x8bVoba3orcKkf9HsDjECAwEAAaMZMBcwFQYDVR0RBA4wDIIKKi5jbWl4LnJpcDANBgkqhkiG9w0BAQUFAAOCAQEAneUocN4AbcQAC1+b3To8u5UGdaGxhcGyZBlAoenRVdjXK3lTjsMdMWb4QctgNfIfU/zuUn2mxTmF/ekP0gCCgtleZr9+DYKU5hlXk8K10uKxGD6EvoiXZzlfeUuotgp2qvI3ysOm/hvCfyEkqhfHtbxjV7j7v7eQFPbvNaXbLa0yr4C4vMK/Z09Ui9JrZ/Z4cyIkxfC6/rOqAirSdIp09EGiw7GM8guHyggE4IiZrDslT8V3xIl985cbCxSxeW1RtgH4rdEXuVe9+31oJhmXOE9ux2jCop9tEJMgWg7HStrJ5plPbb+HmjoX3nBO04E56m52PyzMNV+2N21IPppKwA==-----END CERTIFICATE-----"}], "registration": {"Dsa_public_key": "-----BEGIN PUBLIC KEY-----\nMIIDNDCCAiwCggEBAJ22+1lRtmu2/h4UDx0s5VAjdBYf1lON8WSCGGQvC1xIyPek\nGq36GHMkuHZ0+hgisA8ez4E2lD18VXVyZOWhpE/+AS6ZNuAMHT6TELAcfReYBdMF\niyqfS7b5cWv+YRfGtbPMTZvjQRBK1KgK1slOAF9LmT4U8JHrUXQ78zBQw43iNVZ+\nGzTD1qXAzqoaDzaCE8PRmEPQtLCdy5/HLTnI3kHxvxTUu0Vjyig3FiHK0zJLai05\nIUW+v6x0iAUjb1yi/pK4cc2PnDbTKStVCcqMqneirfx7/XfdpvcRJadFb+oVPkMy\nVqImHGoG7TaTeX55lfrVqrvPvj7aJ0HjdUBK4lsCIQDywxGTdM52yTVpkLRlN0oX\n8j+e01CJvZafYcbd6ZmMHwKCAQBcf/awb48UP+gohDNJPkdpxNmIrOW+JaDiSAln\nBxbGE9ewzuaTL4+qfETSyyRSPaU/vk9uw1lYktGqWMQyigbEahVmLn6qcDod7Pi7\nstBdvi65VsFCozhmHRBGHA0TVHIIUFfzSUMJ/6c8YR94syrbtXQMNhyfNb6QmX2y\nAU4u9apheC9Sq+uL1kMsTdCXvFQjsoXa+2DcNk6BYfSio1rKOhCxxNIDzHakcKM6\n/cvdkpWYWavYtW4XJSUteOrGbnG6muPx3SSHGZh0OTzU2DIYaABlR2Dh40wJ5NFV\nF5+ewNxEc/mWvc5u7Ryr7YtvEW962c9QXfD5mONKsnUUsP/nAoIBAAlELnrXLG0s\n4yAAn7IsVWwY7swDnbBcsIF2cnef4tjm/nNwrFKp5AxYqgeXCiJM8VkyJrotWG50\nnXQwMCR6BsvYrlVt/RmQvR8BSrir62uSLK7hMKm7dXnFvtyFtjp91UwTRbIjxhUQ\nGYnhAzrkCDWo1m54ysqXEGlrVwvRXrCAXiLKPiTEIS+B4GFH9W26SwBxhFLNYSUk\nZZ7+4qwMf9aTu7kIpXTP3hNIyRCjtuZvo5SnymtbLARwTP943hW8MOj0+Ege+m1P\ntey6rkMUGQ86cgK9/7+7Jb+EwW5UxdQtFPUFeNKdQ6zDPS6qbliecUrsc12tdgeg\nhQyuMbyKUuo=\n-----END PUBLIC KEY-----\n", "Address": "registration.default.cmix.rip", "Tls_certificate": "-----BEGIN CERTIFICATE-----MIIDkDCCAnigAwIBAgIJAJnjosuSsP7gMA0GCSqGSIb3DQEBBQUAMHQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQHDAlDbGFyZW1vbnQxGzAZBgNVBAoMElByaXZhdGVncml0eSBDb3JwLjEfMB0GA1UEAwwWcmVnaXN0cmF0aW9uKi5jbWl4LnJpcDAeFwOTAzMDUyMTQ5NTZaFw0yOTAzMDIyMTQ5NTZaMHQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQHDAlDbGFyZW1vbnQxGzAZBgNVBAoMElByaXZhdGVncml0eSBDb3JwLjEfMB0GA1UEAwwWcmVnaXN0cmF0aW9uKi5jbWl4LnJpcDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOQKvqjdh35o+MECBhCwopJzPlQNmq2iPbewRNtI02bUNK3kLQUbFlYdzNGZS4GYXGc5O+jdi8Slx82r1kdjz5PPCNFBARIsOP/L8r3DGeW+yeJdgBZjm1s3ylkamt4Ajiq/bNjysS6L/WSOp+sVumDxtBEzO/UTU1O6QRnzUphLaiWENmErGvsH0CZVq38Ia58k/QjCAzpUcYi4j2l1fb07xqFcQD8H6SmUM297UyQosDrp8ukdIo31Koxr4XDnnNNsYStC26tzHMeKuJ2Wl+3YzsSyflfM2YEcKE31sqB9DS36UkJ8J84eLsHNImGg3WodFAviDB67+jXDbB30NkMCAwEAAaMlMCMwIQYDVR0RBBowGIIWcmVnaXN0cmF0aW9uKi5jbWl4LnJpcDANBgkqhkiG9w0BAQUFAAOCAQEAF9mNzk+g+o626Rllt3f3/1qIyYQrYJ0BjSWCKYEFMCgZ4JibAJjAvIajhVYERtltffM+YKcdE2kTpdzJ0YJuUnRfuv6sVnXlVVugUUnd4IOigmjbCdM32k170CYMm0aiwGxl4FrNa8ei7AIax/s1n+sqWq3HeW5LXjnoVb+s3HeCWIuLfcgrurfye8FnNhy14HFzxVYYefIKmL+DPlcGGGm/PPYt3u4a2+rP3xaihc65dTa0u5tf/XPXtPxTDPFj2JeQDFxo7QRREbPD89CtYnwuP937CrkvCKrL0GkW1FViXKqZY9F5uhxrvLIpzhbNrs/EbtweY35XGLDCCMkg==-----END CERTIFICATE-----"}, "udb": {"Id": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3], "Dsa_public_key": "-----BEGIN PUBLIC KEY-----\nMIIDNDCCAiwCggEBAJ22+1lRtmu2/h4UDx0s5VAjdBYf1lON8WSCGGQvC1xIyPek\nGq36GHMkuHZ0+hgisA8ez4E2lD18VXVyZOWhpE/+AS6ZNuAMHT6TELAcfReYBdMF\niyqfS7b5cWv+YRfGtbPMTZvjQRBK1KgK1slOAF9LmT4U8JHrUXQ78zBQw43iNVZ+\nGzTD1qXAzqoaDzaCE8PRmEPQtLCdy5/HLTnI3kHxvxTUu0Vjyig3FiHK0zJLai05\nIUW+v6x0iAUjb1yi/pK4cc2PnDbTKStVCcqMqneirfx7/XfdpvcRJadFb+oVPkMy\nVqImHGoG7TaTeX55lfrVqrvPvj7aJ0HjdUBK4lsCIQDywxGTdM52yTVpkLRlN0oX\n8j+e01CJvZafYcbd6ZmMHwKCAQBcf/awb48UP+gohDNJPkdpxNmIrOW+JaDiSAln\nBxbGE9ewzuaTL4+qfETSyyRSPaU/vk9uw1lYktGqWMQyigbEahVmLn6qcDod7Pi7\nstBdvi65VsFCozhmHRBGHA0TVHIIUFfzSUMJ/6c8YR94syrbtXQMNhyfNb6QmX2y\nAU4u9apheC9Sq+uL1kMsTdCXvFQjsoXa+2DcNk6BYfSio1rKOhCxxNIDzHakcKM6\n/cvdkpWYWavYtW4XJSUteOrGbnG6muPx3SSHGZh0OTzU2DIYaABlR2Dh40wJ5NFV\nF5+ewNxEc/mWvc5u7Ryr7YtvEW962c9QXfD5mONKsnUUsP/nAoIBACvR2lUslz3D\nB/MUo0rHVIHVkhVJCxNjtgTOYgJ9ckArSXQbYzr/fcigcNGjUO2LbK5NFp9GK43C\nrLxMUnJ9nkyIVPaWvquJFZItjcDK3NiNGyD4XyM0eRj4dYeSxQM48hvFbmtbjlXn\n9SQTnGIlr1XnTI4RVHZSQOL6kFJIaLw6wYrQ4w08Ng+p45brp5ercAHnLiftNUWP\nqROhQkdSEpS9LEwfotUSY1jP2AhQfaIMxaeXsZuTU1IYvdhMFRL3DR0r5Ww2Upf8\ng0Ace0mtnsUQ2OG+7MTh2jYIEWRjvuoe3RCz603ujW6g7BfQ1H7f4YFwc5xOOJ3u\nr4dj49dCCjc=\n-----END PUBLIC KEY-----\n"}, "E2e": {"Prime": "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", "Small_prime": "7FFFFFFFFFFFFFFFE487ED5110B4611A62633145C06E0E68948127044533E63A0105DF531D89CD9128A5043CC71A026EF7CA8CD9E69D218D98158536F92F8A1BA7F09AB6B6A8E122F242DABB312F3F637A262174D31BF6B585FFAE5B7A035BF6F71C35FDAD44CFD2D74F9208BE258FF324943328F6722D9EE1003E5C50B1DF82CC6D241B0E2AE9CD348B1FD47E9267AFC1B2AE91EE51D6CB0E3179AB1042A95DCF6A9483B84B4B36B3861AA7255E4C0278BA3604650C10BE19482F23171B671DF1CF3B960C074301CD93C1D17603D147DAE2AEF837A62964EF15E5FB4AAC0B8C1CCAA4BE754AB5728AE9130C4C7D02880AB9472D455655347FFFFFFFFFFFFFFF", "Generator": "02"}, "CMIX": {"Prime": "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", "Small_prime": "7FFFFFFFFFFFFFFFE487ED5110B4611A62633145C06E0E68948127044533E63A0105DF531D89CD9128A5043CC71A026EF7CA8CD9E69D218D98158536F92F8A1BA7F09AB6B6A8E122F242DABB312F3F637A262174D31BF6B585FFAE5B7A035BF6F71C35FDAD44CFD2D74F9208BE258FF324943328F6722D9EE1003E5C50B1DF82CC6D241B0E2AE9CD348B1FD47E9267AFC1B2AE91EE51D6CB0E3179AB1042A95DCF6A9483B84B4B36B3861AA7255E4C0278BA3604650C10BE19482F23171B671DF1CF3B960C074301CD93C1D17603D147DAE2AEF837A62964EF15E5FB4AAC0B8C1CCAA4BE754AB5728AE9130C4C7D02880AB9472D455655347FFFFFFFFFFFFFFF", "Generator": "02"}}`
-
-// FIXME: This test is breaking grep in turn breaking our pipeline. we need to write a ticket to fix this.
-// Tests that VerifyNDF() correctly verifies the NDF signature.
-func TestVerifyNDF(t *testing.T) {
-	// Load tls private key
-	privKey, err := rsa.LoadPrivateKeyFromPem([]byte("-----BEGIN PRIVATE KEY-----\n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\nOaRA5ZbdE7g7vxKRV36jT3wvD7W+\n-----END PRIVATE KEY-----\n"))
-	if err != nil || privKey == nil {
-		t.Error("Failed to load privKey\n")
-	}
-	// Sign the NDF
-	ndfJSON, _, _ := ndf.DecodeNDF(ExampleJSON + "\n")
-	rsaHash := crypto.SHA256.New()
-	rsaHash.Write([]byte(ExampleJSON))
-	signature, _ := rsa.Sign(
-		rand.Reader, privKey, crypto.SHA256, rsaHash.Sum(nil), nil)
-
-	// Print error on panic
-	defer func() {
-		if r := recover(); r != nil {
-			t.Errorf("VerifyNDF() panicked when it was not supposed to"+
-				"\n\treceived: %#v\n\texpected: %#v", r, nil)
-		}
-	}()
-
-	// Compose network definition string
-	ndfString := ExampleJSON + "\n" + base64.StdEncoding.EncodeToString(signature) + "\n"
-
-	// Run VerifyNDF()
-	fmt.Println(ndfString)
-	ndfJSONOutput := VerifyNDF(ndfString, "-----BEGIN CERTIFICATE-----\n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\n-----END CERTIFICATE-----\n")
-
-	// Check that the output is the expected NetworkDefinition structure
-	if !reflect.DeepEqual(ndfJSONOutput, ndfJSON) {
-		t.Errorf("VerifyNDF() did not output the correct "+
-			"NetworkDefinition structure"+
-			"\n\treceived: %#v\n\texpected: %#v",
-			ndfJSONOutput, ndfJSON)
-	}
-}
-
-// Tests that VerifyNDF() panics when given the incorrect RSA public key.
-func TestVerifyNDF_ErrPublicKey(t *testing.T) {
-	// Generate RSA private key and fake RSA public key
-	// Size of 768 is unsafe, but allows the test to run faster
-	privateKey, _ := rsa.GenerateKey(rand.Reader, 768)
-
-	privateKey2, _ := rsa.GenerateKey(rand.Reader, 768)
-	publicKey := &rsa.PublicKey{PublicKey: privateKey2.PublicKey}
-	publicKeyBytes := rsa.CreatePublicKeyPem(publicKey)
-
-	// Sign the NDF
-	ndfJSON, _, _ := ndf.DecodeNDF(ExampleJSON + "\n")
-	opts := rsa.NewDefaultOptions()
-	rsaHash := opts.Hash.New()
-	rsaHash.Write(ndfJSON.Serialize())
-	signature, _ := rsa.Sign(
-		rand.Reader, privateKey, opts.Hash, rsaHash.Sum(nil), nil)
-
-	// Print error on no panic
-	defer func() {
-		if r := recover(); r == nil {
-			t.Errorf("VerifyNDF() did not panic when expected when the "+
-				"public key is invalid"+
-				"\n\treceived: %#v\n\texpected: %#v",
-				r, "Could not verify NDF: crypto/rsa: verification error")
-		}
-	}()
-
-	// Compose network definition string
-	ndfString := ExampleJSON + "\n" + base64.StdEncoding.EncodeToString(signature)
-
-	// Run VerifyNDF()
-	VerifyNDF(ndfString, string(publicKeyBytes))
-}
-
-// Tests that VerifyNDF() panics when given an invalid NDF string.
-func TestVerifyNDF_ErrInvalidNDF(t *testing.T) {
-	// Generate RSA private key and fake RSA public key
-	// Size of 768 is unsafe, but allows the test to run faster
-	privateKey, _ := rsa.GenerateKey(rand.Reader, 768)
-
-	privateKey2, _ := rsa.GenerateKey(rand.Reader, 768)
-	publicKey := &rsa.PublicKey{PublicKey: privateKey2.PublicKey}
-	publicKeyBytes := rsa.CreatePublicKeyPem(publicKey)
-
-	// Sign the NDF
-	ndfJSON, _, _ := ndf.DecodeNDF(ExampleJSON + "\n")
-	opts := rsa.NewDefaultOptions()
-	rsaHash := opts.Hash.New()
-	rsaHash.Write(ndfJSON.Serialize())
-	signature, _ := rsa.Sign(
-		rand.Reader, privateKey, opts.Hash, rsaHash.Sum(nil), nil)
-
-	// Print error on no panic
-	defer func() {
-		if r := recover(); r == nil {
-			t.Errorf("VerifyNDF() did not panic when expected when given "+
-				"invalid NDF"+
-				"\n\treceived: %#v\n\texpected: %#v",
-				r, "Could not decode NDF: unexpected end of JSON input")
-		}
-	}()
-
-	// Compose network definition string
-	ndfString := "   \n" + base64.StdEncoding.EncodeToString(signature)
-
-	// Run VerifyNDF()
-	VerifyNDF(ndfString, string(publicKeyBytes))
-}
-
-// Tests that VerifyNDF() correctly outputs a NetworkDefinition structure and
-// skips verifying the signature when the public key is empty.
-func TestVerifyNDF_EmptyPublicKey(t *testing.T) {
-	// Generate RSA private and public keys
-	// Size of 768 is unsafe, but allows the test to run faster
-	privateKey, _ := rsa.GenerateKey(rand.Reader, 768)
-
-	// Sign the NDF
-	ndfJSON, _, _ := ndf.DecodeNDF(ExampleJSON + "\n")
-	opts := rsa.NewDefaultOptions()
-	rsaHash := opts.Hash.New()
-	rsaHash.Write(ndfJSON.Serialize())
-	signature, _ := rsa.Sign(
-		rand.Reader, privateKey, opts.Hash, rsaHash.Sum(nil), nil)
-
-	// Compose network definition string
-	ndfString := ExampleJSON + "\n" + base64.StdEncoding.EncodeToString(signature)
-
-	// Run VerifyNDF()
-	ndfJSONOutput := VerifyNDF(ndfString, "")
-
-	// Check that the output is the expected NetworkDefinition structure
-	if !reflect.DeepEqual(ndfJSONOutput, ndfJSON) {
-		t.Errorf("VerifyNDF() did not output the correct "+
-			"NetworkDefinition structure"+
-			"\n\treceived: %#v\n\texpected: %#v",
-			ndfJSONOutput, ndfJSON)
-	}
-}
diff --git a/api/notifications.go b/api/notifications.go
deleted file mode 100644
index a7587f4f80c632995dd0cb4c885a5a6189bc7d2e..0000000000000000000000000000000000000000
--- a/api/notifications.go
+++ /dev/null
@@ -1,52 +0,0 @@
-package api
-
-import (
-	"github.com/pkg/errors"
-	"gitlab.com/elixxir/comms/mixmessages"
-	"gitlab.com/xx_network/primitives/id"
-)
-
-// RegisterForNotifications sends a message to notification bot indicating it
-// is registering for notifications
-func (cl *Client) RegisterForNotifications(notificationToken []byte) error {
-	// Pull the host from the manage
-	notificationBotHost, ok := cl.receptionManager.Comms.GetHost(&id.NotificationBot)
-	if !ok {
-		return errors.New("Failed to retrieve host for notification bot")
-	}
-
-	// Send the register message
-	_, err := cl.receptionManager.Comms.RegisterForNotifications(notificationBotHost,
-		&mixmessages.NotificationToken{
-			Token: notificationToken,
-		})
-	if err != nil {
-		err := errors.Errorf(
-			"RegisterForNotifications: Unable to register for notifications! %s", err)
-		return err
-	}
-
-	return nil
-
-}
-
-// UnregisterForNotifications sends a message to notification bot indicating it
-// no longer wants to be registered for notifications
-func (cl *Client) UnregisterForNotifications() error {
-	// Pull the host from the manage
-	notificationBotHost, ok := cl.receptionManager.Comms.GetHost(&id.NotificationBot)
-	if !ok {
-		return errors.New("Failed to retrieve host for notification bot")
-	}
-
-	// Send the unregister message
-	_, err := cl.receptionManager.Comms.UnregisterForNotifications(notificationBotHost)
-	if err != nil {
-		err := errors.Errorf(
-			"RegisterForNotifications: Unable to register for notifications! %s", err)
-		return err
-	}
-
-	return nil
-
-}
diff --git a/api/notifications_test.go b/api/notifications_test.go
deleted file mode 100644
index f283f7e558fc28d41a0749a97ba2a5794d707b09..0000000000000000000000000000000000000000
--- a/api/notifications_test.go
+++ /dev/null
@@ -1,126 +0,0 @@
-package api
-
-import (
-	"gitlab.com/xx_network/crypto/signature/rsa"
-	"testing"
-)
-
-var dummy_key = `-----BEGIN PRIVATE KEY-----
-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
-jR+QSAa9eEozCngV6LUagC0YYWDZ
------END PRIVATE KEY-----`
-
-// Happy path
-func TestClient_RegisterForNotifications(t *testing.T) {
-	// Initialize client with dummy storage
-	storage := DummyStorage{LocationA: ".ekv-registernotifications/a", StoreA: []byte{'a', 'b', 'c'}}
-	client, err := NewClient(&storage, ".ekv-registernotifications/a", "", def)
-	if err != nil {
-		t.Errorf("Failed to initialize dummy client: %s", err.Error())
-		return
-	}
-
-	privKey, err := rsa.LoadPrivateKeyFromPem([]byte(dummy_key))
-	if err != nil {
-		t.Errorf("Failed to load private key: %+v", err)
-	}
-
-	// InitNetwork to gateways and reg server
-	err = client.InitNetwork()
-
-	if err != nil {
-		t.Errorf("Client failed of connect: %+v", err)
-	}
-
-	err = client.GenerateKeys(privKey, "test")
-	if err != nil {
-		t.Errorf("Failed to properly set up keys: %+v", err)
-	}
-
-	token := make([]byte, 32)
-
-	err = client.RegisterForNotifications(token)
-	if err != nil {
-		t.Errorf("Expected happy path, received error: %+v", err)
-	}
-}
-
-// Happy path
-func TestClient_UnregisterForNotifications(t *testing.T) {
-	// Initialize client with dummy storage
-	storage := DummyStorage{LocationA: ".ekv-unregisternotifications/a", StoreA: []byte{'a', 'b', 'c'}}
-	client, err := NewClient(&storage, ".ekv-unregisternotifications/a", "", def)
-	if err != nil {
-		t.Errorf("Failed to initialize dummy client: %s", err.Error())
-	}
-
-	privKey, err := rsa.LoadPrivateKeyFromPem([]byte(dummy_key))
-	if err != nil {
-		t.Errorf("Failed to load private key: %+v", err)
-		return
-	}
-	err = client.GenerateKeys(privKey, "test")
-	if err != nil {
-		t.Errorf("Failed to properly set up keys: %+v", err)
-		return
-	}
-	// InitNetwork to gateways and reg server
-	err = client.InitNetwork()
-
-	if err != nil {
-		t.Errorf("Client failed of connect: %+v", err)
-	}
-
-	err = client.UnregisterForNotifications()
-	if err != nil {
-		t.Errorf("Expected happy path, received error: %+v", err)
-	}
-}
diff --git a/api/permissioning.go b/api/permissioning.go
index 8573366306087791f71ea806bd3110691037ce77..2a7444d7e94421e59ac510a493b00a82f3e28456 100644
--- a/api/permissioning.go
+++ b/api/permissioning.go
@@ -8,17 +8,14 @@ package api
 
 import (
 	"github.com/pkg/errors"
-	"gitlab.com/elixxir/client/context"
 	"gitlab.com/elixxir/client/globals"
-	"gitlab.com/elixxir/client/network/permissioning"
 	"gitlab.com/elixxir/client/storage"
-	"gitlab.com/elixxir/comms/client"
 )
 
 // Returns an error if registration fails.
 func (c *Client) RegisterWithPermissioning(registrationCode string) error {
-	instance := ctx.Manager.GetInstance()
-	instance.GetPartialNdf()
+	ctx := c.ctx
+	netman := ctx.Manager
 
 	//Check the regState is in proper state for registration
 	regState := c.storage.GetRegistrationStatus()
@@ -29,8 +26,8 @@ func (c *Client) RegisterWithPermissioning(registrationCode string) error {
 	userData := ctx.Session.User()
 
 	// Register with the permissioning server and generate user information
-	regValidationSignature, err := permissioning.RegisterWithPermissioning(&comms,
-		userData.GetCryptographicIdentity().GetRSA().GetPublic(), registrationCode)
+	regValidationSignature, err := netman.RegisterWithPermissioning(
+		registrationCode)
 	if err != nil {
 		globals.Log.INFO.Printf(err.Error())
 		return err
diff --git a/bindings/api.go b/bindings/api.go
index d0a0fc133d6f6c769009cc3ad82fe940e4cdf611..b8351406a78d4b37e6b10553e7bf30384fbfe553 100644
--- a/bindings/api.go
+++ b/bindings/api.go
@@ -10,6 +10,12 @@ import (
 	"gitlab.com/elixxir/client/api"
 )
 
+// BindingsClient wraps the api.Client, implementing additional functions
+// to support the gomobile Client interface
+type BindingsClient struct {
+	api.Client
+}
+
 // NewClient connects and registers to the network using a json encoded
 // network information string and then creates a new client at the specified
 // storageDir using the specified password. This function will fail
@@ -29,7 +35,12 @@ import (
 // Users of this function should delete the storage directory on error.
 func NewClient(network, storageDir string, password []byte) (Client, error) {
 	// TODO: This should wrap the bindings ClientImpl, when available.
-	return api.NewClient(network, storageDir, password)
+	client, err := api.NewClient(network, storageDir, password)
+	if err != nil {
+		return nil, err
+	}
+	bindingsClient := &BindingsClient{*client}
+	return bindingsClient, nil
 }
 
 // LoadClient will load an existing client from the storageDir
@@ -41,5 +52,66 @@ func NewClient(network, storageDir string, password []byte) (Client, error) {
 // starts subprocesses to perform network operations.
 func LoadClient(storageDir string, password []byte) (Client, error) {
 	// TODO: This should wrap the bindings ClientImpl, when available.
-	return api.LoadClient(storageDir, password)
+	client, err := api.LoadClient(storageDir, password)
+	if err != nil {
+		return nil, err
+	}
+	bindingsClient := &BindingsClient{*client}
+	return bindingsClient, nil
+}
+
+// RegisterListener records and installs a listener for messages
+// matching specific uid, msgType, and/or username
+func (b *BindingsClient) RegisterListener(uid []byte, msgType int,
+	username string, listener Listener) {
+}
+
+// SearchWithHandler is a non-blocking search that also registers
+// a callback interface for user disovery events.
+func (b *BindingsClient) SearchWithHandler(data, separator string,
+	searchTypes []byte, hdlr UserDiscoveryHandler) {
+}
+
+// RegisterAuthEventsHandler registers a callback interface for channel
+// authentication events.
+func (b *BindingsClient) RegisterAuthEventsHandler(hdlr AuthEventHandler) {
+}
+
+// RegisterRoundEventsHandler registers a callback interface for round
+// events.
+func (b *BindingsClient) RegisterRoundEventsHandler(hdlr RoundEventHandler) {
+}
+
+// SendE2E sends an end-to-end payload to the provided recipient with
+// the provided msgType. Returns the list of rounds in which parts of
+// the message were sent or an error if it fails.
+func (b *BindingsClient) SendE2E(payload, recipient []byte,
+	msgType int) (RoundList, error) {
+	return nil, nil
+}
+
+// SendUnsafe sends an unencrypted payload to the provided recipient
+// with the provided msgType. Returns the list of rounds in which parts
+// of the message were sent or an error if it fails.
+// NOTE: Do not use this function unless you know what you are doing.
+// This function always produces an error message in client logging.
+func (b *BindingsClient) SendUnsafe(payload, recipient []byte,
+	msgType int) (RoundList, error) {
+	return nil, nil
+}
+
+// SendCMIX sends a "raw" CMIX message payload to the provided
+// recipient. Note that both SendE2E and SendUnsafe call SendCMIX.
+// Returns the round ID of the round the payload was sent or an error
+// if it fails.
+func (b *BindingsClient) SendCMIX(payload, recipient []byte) (int, error) {
+	return 0, nil
+}
+
+// Search accepts a "separator" separated list of search elements with
+// an associated list of searchTypes. It returns a ContactList which
+// allows you to iterate over the found contact objects.
+func (b *BindingsClient) Search(data, separator string,
+	searchTypes []byte) ContactList {
+	return nil
 }
diff --git a/bindings/interfaces.go b/bindings/interfaces.go
index a3300b2d711b468f95c7b1d45b77adce65f3a3f9..5156dd6b896f10a18637b23e9929f80100c5f982 100644
--- a/bindings/interfaces.go
+++ b/bindings/interfaces.go
@@ -7,7 +7,8 @@
 package bindings
 
 import (
-	"gitlab.com/elixxir/primitives/switchboard"
+	"gitlab.com/elixxir/client/api"
+	"gitlab.com/elixxir/client/context/stoppable"
 )
 
 // Client is defined inside the api package. At minimum, it implements all of
@@ -84,13 +85,13 @@ type Client interface {
 
 	// GetUser returns the current user Identity for this client. This
 	// can be serialized into a byte stream for out-of-band sharing.
-	GetUser() (Contact, error)
+	GetUser() (api.Contact, error)
 	// MakeContact creates a contact from a byte stream (i.e., unmarshal's a
 	// Contact object), allowing out-of-band import of identities.
-	MakeContact(contactBytes []byte) (Contact, error)
+	MakeContact(contactBytes []byte) (api.Contact, error)
 	// GetContact returns a Contact object for the given user id, or
 	// an error
-	GetContact(uid []byte) (Contact, error)
+	GetContact(uid []byte) (api.Contact, error)
 
 	// ----- User Discovery -----
 
@@ -109,7 +110,7 @@ type Client interface {
 	// so this user can send messages to the desired recipient Contact.
 	// To receive confirmation from the remote user, clients must
 	// register a listener to do that.
-	CreateAuthenticatedChannel(recipient Contact, payload []byte) error
+	CreateAuthenticatedChannel(recipient api.Contact, payload []byte) error
 	// RegierAuthEventsHandler registers a callback interface for channel
 	// authentication events.
 	RegisterAuthEventsHandler(hdlr AuthEventHandler)
@@ -120,68 +121,19 @@ type Client interface {
 	// and returns an object for checking state and stopping those threads.
 	// Call this when returning from sleep and close when going back to
 	// sleep.
-	StartNetworkRunner() NetworkRunner
+	StartNetworkRunner() stoppable.Stoppable
 
 	// RegisterRoundEventsHandler registers a callback interface for round
 	// events.
 	RegisterRoundEventsHandler(hdlr RoundEventHandler)
 }
 
-// Message is a message received from the cMix network in the clear
-// or that has been decrypted using established E2E keys.
-type Message interface {
-	// Returns the message's sender ID, if available
-	GetSender() []byte
-	// Returns the message payload/contents
-	// Parse this with protobuf/whatever according to the message type
-	GetPayload() []byte
-	// Returns the message's recipient ID
-	// This is usually your userID but could be an ephemeral/group ID
-	GetRecipient() []byte
-	// Returns the message's type
-	GetMessageType() int32
-	// Returns the message's timestamp in seconds since unix epoc
-	GetTimestamp() int64
-	// Returns the message's timestamp in ns since unix epoc
-	GetTimestampNano() int64
-}
-
-// RoundEvent contains event information for a given round.
-// TODO: This is a half-baked interface and will be filled out later.
-type RoundEvent interface {
-	// GetID returns the round ID for this round.
-	GetID() int
-	// GetStatus returns the status of this round.
-	GetStatus() int
-}
-
 // ContactList contains a list of contacts
 type ContactList interface {
 	// GetLen returns the number of contacts in the list
 	GetLen() int
 	// GetContact returns the contact at index i
-	GetContact(i int) Contact
-}
-
-// Contact contains the contacts information. Note that this object
-// is a copy of the contact at the time it was generated, so api users
-// cannot rely on this object being updated once it has been received.
-type Contact interface {
-	// GetID returns the user ID for this user.
-	GetID() []byte
-	// GetPublicKey returns the publickey bytes for this user.
-	GetPublicKey() []byte
-	// GetSalt returns the salt used to initiate an authenticated channel
-	GetSalt() []byte
-	// IsAuthenticated returns true if an authenticated channel exists for
-	// this user so we can begin to send messages.
-	IsAuthenticated() bool
-	// IsConfirmed returns true if the user has confirmed the authenticated
-	// channel on their end.
-	IsConfirmed() bool
-	// Marshal creates a serialized representation of a contact for
-	// out-of-band contact exchange.
-	Marshal() ([]byte, error)
+	GetContact(i int) api.Contact
 }
 
 // ----- Callback interfaces -----
@@ -192,7 +144,7 @@ type Contact interface {
 // time.
 type Listener interface {
 	// Hear is called to receive a message in the UI
-	Hear(msg Message)
+	Hear(msg api.Message)
 }
 
 // AuthEventHandler handles authentication requests initiated by
@@ -202,13 +154,30 @@ type AuthEventHandler interface {
 	// the client has called CreateAuthenticatedChannel for
 	// the provided contact. Payload is typically empty but
 	// may include a small introductory message.
-	HandleConfirmation(contact Contact, payload []byte)
+	HandleConfirmation(contact api.Contact, payload []byte)
 	// HandleRequest handles AuthEvents received before
 	// the client has called CreateAuthenticatedChannel for
 	// the provided contact. It should prompt the user to accept
 	// the channel creation "request" and, if approved,
 	// call CreateAuthenticatedChannel for this Contact.
-	HandleRequest(contact Contact, payload []byte)
+	HandleRequest(contact api.Contact, payload []byte)
+}
+
+// RoundList contains a list of contacts
+type RoundList interface {
+	// GetLen returns the number of contacts in the list
+	GetLen() int
+	// GetRoundID returns the round ID at index i
+	GetRoundID(i int) int
+}
+
+// RoundEvent contains event information for a given round.
+// TODO: This is a half-baked interface and will be filled out later.
+type RoundEvent interface {
+	// GetID returns the round ID for this round.
+	GetID() int
+	// GetStatus returns the status of this round.
+	GetStatus() int
 }
 
 // RoundEventHandler handles round events happening on the cMix network.
diff --git a/cmd/root.go b/cmd/root.go
index 4fe59246c05ee9ac47df68cff958e0c3b22e0fb5..fb328b155b826d8433cc0b990927041aa0ab6a7d 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -8,23 +8,15 @@
 package cmd
 
 import (
-	"encoding/base64"
 	"encoding/binary"
 	"fmt"
-	"github.com/golang/protobuf/proto"
 	"github.com/spf13/cobra"
 	jww "github.com/spf13/jwalterweatherman"
 	"github.com/spf13/viper"
-	"gitlab.com/elixxir/primitives/switchboard"
-	"gitlab.com/elixxir/primitives/utils"
-	"gitlab.com/xx_network/crypto/signature/rsa"
 	"gitlab.com/xx_network/primitives/id"
 	"io/ioutil"
 	"os"
 	"strconv"
-	"strings"
-	"sync/atomic"
-	"time"
 )
 
 var verbose bool
@@ -63,319 +55,116 @@ func Execute() {
 	}
 }
 
-func sessionInitialization() (*id.ID, string, *api.Client) {
-	var err error
-	register := false
-
-	var client *api.Client
-
-	// Read in the network definition file and save as string
-	ndfBytes, err := utils.ReadFile(ndfPath)
-	if err != nil {
-		globals.Log.FATAL.Panicf("Could not read network definition file: %v", err)
-	}
-
-	// Check if the NDF verify flag is set
-	if skipNDFVerification {
-		ndfPubKey = ""
-		globals.Log.WARN.Println("Skipping NDF verification")
-	} else {
-		pkFile, err := os.Open(ndfPubKey)
-		if err != nil {
-			globals.Log.FATAL.Panicf("Could not open cert file: %v",
-				err)
-		}
-
-		pkBytes, err := ioutil.ReadAll(pkFile)
-		if err != nil {
-			globals.Log.FATAL.Panicf("Could not read cert file: %v",
-				err)
-		}
-		ndfPubKey = string(pkBytes)
-	}
-
-	// Verify the signature
-	globals.Log.DEBUG.Println("Verifying NDF...")
-	ndfJSON := api.VerifyNDF(string(ndfBytes), ndfPubKey)
-	globals.Log.DEBUG.Printf("   NDF Verified")
-
-	//If no session file is passed initialize with RAM Storage
-	if sessionFile == "" {
-		client, err = api.NewClient(&globals.RamStorage{}, "", "", ndfJSON)
-		if err != nil {
-			globals.Log.ERROR.Printf("Could Not Initialize Ram Storage: %s\n",
-				err.Error())
-			return &id.ZeroUser, "", nil
-		}
-		globals.Log.INFO.Println("Initialized Ram Storage")
-		register = true
-	} else {
-
-		var sessionA, sessionB string
-
-		locs := strings.Split(sessionFile, ",")
-
-		if len(locs) == 2 {
-			sessionA = locs[0]
-			sessionB = locs[1]
-		} else {
-			sessionA = sessionFile
-			sessionB = sessionFile + "-2"
-		}
-
-		//If a session file is passed, check if it's valid
-		_, err1 := os.Stat(sessionA)
-		_, err2 := os.Stat(sessionB)
-
-		if err1 != nil && err2 != nil {
-			//If the file does not exist, register a new user
-			if os.IsNotExist(err1) && os.IsNotExist(err2) {
-				register = true
-			} else {
-				//Fail if any other error is received
-				globals.Log.ERROR.Printf("Error with file paths: %s %s",
-					err1, err2)
-				return &id.ZeroUser, "", nil
-			}
-		}
-		//Initialize client with OS Storage
-		client, err = api.NewClient(nil, sessionA, sessionB, ndfJSON)
-		if err != nil {
-			globals.Log.ERROR.Printf("Could Not Initialize OS Storage: %s\n", err.Error())
-			return &id.ZeroUser, "", nil
-		}
-		globals.Log.INFO.Println("Initialized OS Storage")
-
-	}
-
-	if noBlockingTransmission {
-		globals.Log.INFO.Println("Disabling Blocking Transmissions")
-		client.DisableBlockingTransmission()
-	}
-
-	// Handle parsing gateway addresses from the config file
-
-	//REVIEWER NOTE: Possibly need to remove/rearrange this,
-	// now that client may not know gw's upon client creation
-	/*gateways := client.GetNDF().Gateways
-	// If gwAddr was not passed via command line, check config file
-	if len(gateways) < 1 {
-		// No gateways in config file or passed via command line
-		globals.Log.ERROR.Printf("Error: No gateway specified! Add to" +
-			" configuration file or pass via command line using -g!\n")
-		return &id.ZeroUser, "", nil
-	}*/
-
-	if noTLS {
-		client.DisableTls()
-	}
-
-	// InitNetwork to gateways, notificationBot and reg server
-	err = client.InitNetwork()
-	if err != nil {
-		globals.Log.FATAL.Panicf("Could not call connect on client: %+v", err)
-	}
-
-	client.SetRateLimiting(rateLimiting)
-
-	// Holds the User ID
-	var uid *id.ID
-
-	// Register a new user if requested
-	if register {
-		globals.Log.INFO.Println("Registering...")
-
-		regCode := registrationCode
-		// If precanned user, use generated code instead
-		if userId != 0 {
-			precanned = true
-			uid := new(id.ID)
-			binary.BigEndian.PutUint64(uid[:], userId)
-			uid.SetType(id.User)
-			regCode = userRegistry.RegistrationCode(uid)
-		}
-
-		globals.Log.INFO.Printf("Building keys...")
-
-		var privKey *rsa.PrivateKey
-
-		if privateKeyPath != "" {
-			privateKeyBytes, err := utils.ReadFile(privateKeyPath)
-			if err != nil {
-				globals.Log.FATAL.Panicf("Could not load user private key PEM from "+
-					"path %s: %+v", privateKeyPath, err)
-			}
-
-			privKey, err = rsa.LoadPrivateKeyFromPem(privateKeyBytes)
-			if err != nil {
-				globals.Log.FATAL.Panicf("Could not load private key from PEM bytes: %+v", err)
-			}
-		}
-
-		//Generate keys for registration
-		err := client.GenerateKeys(privKey, sessFilePassword)
-		if err != nil {
-			globals.Log.FATAL.Panicf("%+v", err)
-		}
-
-		globals.Log.INFO.Printf("Attempting to register with code %s...", regCode)
-
-		errRegister := fmt.Errorf("")
-
-		//Attempt to register user with same keys until a success occurs
-		for errRegister != nil {
-			_, errRegister = client.RegisterWithPermissioning(precanned, regCode)
-			if errRegister != nil {
-				globals.Log.FATAL.Panicf("Could Not Register User: %s",
-					errRegister.Error())
-			}
-		}
-
-		err = client.RegisterWithNodes()
-		if err != nil {
-			globals.Log.FATAL.Panicf("Could Not Register User with nodes: %s",
-				err.Error())
-		}
-
-		uid = client.GetCurrentUser()
-
-		userbase64 := base64.StdEncoding.EncodeToString(uid[:])
-		globals.Log.INFO.Printf("Registered as user (uid, the var) %v", uid)
-		globals.Log.INFO.Printf("Registered as user (userID, the global) %v", userId)
-		globals.Log.INFO.Printf("Successfully registered user %s!", userbase64)
-
-	} else {
-		// hack for session persisting with cmd line
-		// doesn't support non pre canned users
-		uid := new(id.ID)
-		binary.BigEndian.PutUint64(uid[:], userId)
-		uid.SetType(id.User)
-		globals.Log.INFO.Printf("Skipped Registration, user: %v", uid)
-	}
-
-	if !precanned {
-		// If we are sending to a non precanned user we retrieve the uid from the session returned by client.login
-		uid, err = client.Login(sessFilePassword)
-	} else {
-		_, err = client.Login(sessFilePassword)
-	}
-
-	if err != nil {
-		globals.Log.FATAL.Panicf("Could not login: %v", err)
-	}
-	return uid, client.GetUsername(), client
-}
-
-func setKeyParams(client *api.Client) {
-	globals.Log.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
-	}
-
-	globals.Log.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 FallbackListener struct {
-	MessagesReceived int64
-}
-
-func (l *FallbackListener) Hear(item switchboard.Item, isHeardElsewhere bool, i ...interface{}) {
-	if !isHeardElsewhere {
-		message := item.(*parse.Message)
-		sender, ok := userRegistry.Users.GetUser(message.Sender)
-		var senderNick string
-		if !ok {
-			globals.Log.ERROR.Printf("Couldn't get sender %v", message.Sender)
-		} else {
-			senderNick = sender.Username
-		}
-		atomic.AddInt64(&l.MessagesReceived, 1)
-		globals.Log.INFO.Printf("Message of type %v from %q, %v received with fallback: %s\n",
-			message.MessageType, printIDNice(message.Sender), senderNick,
-			string(message.Body))
-	}
-}
-
-type TextListener struct {
-	MessagesReceived int64
-}
-
-func (l *TextListener) Hear(item switchboard.Item, isHeardElsewhere bool, i ...interface{}) {
-	message := item.(*parse.Message)
-	globals.Log.INFO.Println("Hearing a text message")
-	result := cmixproto.TextMessage{}
-	err := proto.Unmarshal(message.Body, &result)
-	if err != nil {
-		globals.Log.ERROR.Printf("Error unmarshaling text message: %v\n",
-			err.Error())
-	}
-
-	sender, ok := userRegistry.Users.GetUser(message.Sender)
-	var senderNick string
-	if !ok {
-		globals.Log.INFO.Printf("First message from sender %v", printIDNice(message.Sender))
-		u := userRegistry.Users.NewUser(message.Sender, base64.StdEncoding.EncodeToString(message.Sender[:]))
-		userRegistry.Users.UpsertUser(u)
-		senderNick = u.Username
-	} else {
-		senderNick = sender.Username
-	}
-	logMsg := fmt.Sprintf("Message from %v, %v Received: %s\n",
-		printIDNice(message.Sender),
-		senderNick, result.Message)
-	globals.Log.INFO.Printf("%s -- Timestamp: %s\n", logMsg,
-		message.Timestamp.String())
-	fmt.Printf(logMsg)
-
-	atomic.AddInt64(&l.MessagesReceived, 1)
-}
-
-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 {
-		globals.Log.ERROR.Printf("Could not find searched user: %+v", err)
-	} else {
-		us.foundUserChan <- userID
-	}
-}
+// 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 FallbackListener struct {
+// 	MessagesReceived int64
+// }
+
+// func (l *FallbackListener) Hear(item switchboard.Item, isHeardElsewhere bool, i ...interface{}) {
+// 	if !isHeardElsewhere {
+// 		message := item.(*parse.Message)
+// 		sender, ok := userRegistry.Users.GetUser(message.Sender)
+// 		var senderNick string
+// 		if !ok {
+// 			jww.ERROR.Printf("Couldn't get sender %v", message.Sender)
+// 		} else {
+// 			senderNick = sender.Username
+// 		}
+// 		atomic.AddInt64(&l.MessagesReceived, 1)
+// 		jww.INFO.Printf("Message of type %v from %q, %v received with fallback: %s\n",
+// 			message.MessageType, printIDNice(message.Sender), senderNick,
+// 			string(message.Body))
+// 	}
+// }
+
+// type TextListener struct {
+// 	MessagesReceived int64
+// }
+
+// func (l *TextListener) Hear(item switchboard.Item, isHeardElsewhere bool, i ...interface{}) {
+// 	message := item.(*parse.Message)
+// 	jww.INFO.Println("Hearing a text message")
+// 	result := cmixproto.TextMessage{}
+// 	err := proto.Unmarshal(message.Body, &result)
+// 	if err != nil {
+// 		jww.ERROR.Printf("Error unmarshaling text message: %v\n",
+// 			err.Error())
+// 	}
+
+// 	sender, ok := userRegistry.Users.GetUser(message.Sender)
+// 	var senderNick string
+// 	if !ok {
+// 		jww.INFO.Printf("First message from sender %v", printIDNice(message.Sender))
+// 		u := userRegistry.Users.NewUser(message.Sender, base64.StdEncoding.EncodeToString(message.Sender[:]))
+// 		userRegistry.Users.UpsertUser(u)
+// 		senderNick = u.Username
+// 	} else {
+// 		senderNick = sender.Username
+// 	}
+// 	logMsg := fmt.Sprintf("Message from %v, %v Received: %s\n",
+// 		printIDNice(message.Sender),
+// 		senderNick, result.Message)
+// 	jww.INFO.Printf("%s -- Timestamp: %s\n", logMsg,
+// 		message.Timestamp.String())
+// 	fmt.Printf(logMsg)
+
+// 	atomic.AddInt64(&l.MessagesReceived, 1)
+// }
+
+// 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{
@@ -399,7 +188,7 @@ var rootCmd = &cobra.Command{
 		}
 		jww.SetLogOutput(logOutput)
 		if verbose {
-			jww.SetLogThreshold(verbose)
+			jww.SetLogThreshold(jww.LevelTrace)
 		}
 	},
 }
@@ -412,7 +201,7 @@ func isValidUser(usr []byte) (bool, *id.ID) {
 		if b != 0 {
 			uid, err := id.Unmarshal(usr)
 			if err != nil {
-				globals.Log.WARN.Printf("Could not unmarshal user: %s", err)
+				jww.WARN.Printf("Could not unmarshal user: %s", err)
 				return false, nil
 			}
 			return true, uid
diff --git a/cmd/udb.go b/cmd/udb.go
index 9935a5382ce96f36434576c641a4a18f25aa11de..8a3ffd4d8ef1e6d512df4dd6f7169ada6b7c1258 100644
--- a/cmd/udb.go
+++ b/cmd/udb.go
@@ -11,7 +11,7 @@ import (
 	"gitlab.com/elixxir/client/globals"
 	"gitlab.com/xx_network/primitives/id"
 	"strings"
-	"time"
+	//"time"
 )
 
 type callbackSearch struct{}
@@ -46,7 +46,7 @@ func parseUdbMessage(msg string, client *api.Client) {
 	keyword := args[0]
 	// Case-insensitive match the keyword to a command
 	if strings.EqualFold(keyword, "SEARCH") {
-		client.SearchForUser(args[2], searchCallback, 2*time.Minute)
+		//client.SearchForUser(args[2], searchCallback, 2*time.Minute)
 	} else if strings.EqualFold(keyword, "REGISTER") {
 		globals.Log.ERROR.Printf("UDB REGISTER not allowed, it is already done during user registration")
 	} else {
diff --git a/network/message/sendE2E.go b/network/message/sendE2E.go
index 840595e09f504c88d5cb215de8b9f62f0f59f412..76370c30262cffc2f9f158c6d2be62e09c00eaa4 100644
--- a/network/message/sendE2E.go
+++ b/network/message/sendE2E.go
@@ -37,7 +37,7 @@ func (m *Manager) SendE2E(msg message.Send, param params.E2E) ([]id.Round, error
 	partner, err := m.Session.E2e().GetPartner(msg.Recipient)
 	if err != nil {
 		return nil, errors.WithMessagef(err, "Could not send End to End encrypted "+
-			"message, no relationship found with %s", partner)
+			"message, no relationship found with %v", partner)
 	}
 
 	wg := sync.WaitGroup{}
diff --git a/network/node/register_test.go b/network/node/register_test.go
index 48709d252b0153a324bed017b25812de0aacb70d..c2bb1a538e83a09ae280ffccee3b62b1dab4da40 100644
--- a/network/node/register_test.go
+++ b/network/node/register_test.go
@@ -41,6 +41,18 @@ func (nm *MockNetworkManager) GetHealthTracker() context.HealthTracker {
 	return nil
 }
 
+func (nm *MockNetworkManager) GetRemoteVersion() (string, error) {
+	return "", nil
+}
+
+func (nm *MockNetworkManager) GetStoppable() stoppable.Stoppable {
+	return nil
+}
+
+func (nm *MockNetworkManager) RegisterWithPermissioning(string) ([]byte, error) {
+	return nil, nil
+}
+
 // Mock client comms object
 type MockClientComms struct {
 	request chan bool
diff --git a/network/rounds/retreive.go b/network/rounds/retreive.go
index dcb08c525f7560425de26bc424409dc3dbe4ee68..b6b45e7a35383e9f3dabe116733c77de12887db4 100644
--- a/network/rounds/retreive.go
+++ b/network/rounds/retreive.go
@@ -1,14 +1,15 @@
 package rounds
 
 import (
+	"encoding/binary"
 	"github.com/pkg/errors"
+	jww "github.com/spf13/jwalterweatherman"
 	"gitlab.com/elixxir/client/network/gateway"
 	"gitlab.com/elixxir/client/network/message"
+	pb "gitlab.com/elixxir/comms/mixmessages"
 	"gitlab.com/elixxir/primitives/format"
 	"gitlab.com/xx_network/comms/connect"
 	"gitlab.com/xx_network/primitives/id"
-	pb "gitlab.com/elixxir/comms/mixmessages"
-	jww "github.com/spf13/jwalterweatherman"
 )
 
 type messageRetrievalComms interface {
@@ -39,6 +40,13 @@ func (m *Manager) processMessageRetrieval(comms messageRetrievalComms,
 	}
 }
 
+// TODO: remove me when api fixed
+func uint64ToBytes(i uint64) []byte {
+	bs := make([]byte, 8)
+	binary.LittleEndian.PutUint64(bs, 31415926)
+	return bs
+}
+
 func (m *Manager) getMessagesFromGateway(roundInfo *pb.RoundInfo,
 	comms messageRetrievalComms) (message.Bundle, error) {
 
@@ -55,7 +63,7 @@ func (m *Manager) getMessagesFromGateway(roundInfo *pb.RoundInfo,
 	msgReq := &pb.GetMessages{
 		ClientID: m.Uid.Marshal(),
 		//TODO: fix this, should not be a byte slice
-		RoundID: uint64(rid),
+		RoundID: uint64ToBytes(uint64(rid)),
 	}
 	msgResp, err := comms.RequestMessages(gwHost, msgReq)
 	// Fail the round if an error occurs so it can be tried again later