diff --git a/Makefile b/Makefile
index bd6383ff69c75244eaf1b62ef3cc9c0fb91c5154..7cd635a516d953f796d6073610b0f4d6693e00db 100644
--- a/Makefile
+++ b/Makefile
@@ -20,12 +20,12 @@ build:
 	go mod tidy
 
 update_release:
-	GOFLAGS="" go get -u gitlab.com/xx_network/primitives@release
-	GOFLAGS="" go get -u gitlab.com/elixxir/primitives@release
-	GOFLAGS="" go get -u gitlab.com/xx_network/crypto@release
-	GOFLAGS="" go get -u gitlab.com/elixxir/crypto@release
-	GOFLAGS="" go get -u gitlab.com/xx_network/comms@release
-	GOFLAGS="" go get -u gitlab.com/elixxir/comms@release
+	GOFLAGS="" go get gitlab.com/xx_network/primitives@release
+	GOFLAGS="" go get gitlab.com/elixxir/primitives@release
+	GOFLAGS="" go get gitlab.com/xx_network/crypto@release
+	GOFLAGS="" go get gitlab.com/elixxir/crypto@release
+	GOFLAGS="" go get gitlab.com/xx_network/comms@release
+	GOFLAGS="" go get gitlab.com/elixxir/comms@release
 
 update_master:
 	GOFLAGS="" go get gitlab.com/xx_network/primitives@master
@@ -35,6 +35,6 @@ update_master:
 	GOFLAGS="" go get gitlab.com/xx_network/comms@master
 	GOFLAGS="" go get gitlab.com/elixxir/comms@master
 
-master: clean update_master build version
+master: update_master clean build version
 
-release: clean update_release build version
+release: update_release clean build version
diff --git a/README.md b/README.md
index 0cd7989af96e9851126932c253e8385c3f9ea8d7..3827baea0e49a5792e8bd230f6e90230bcccca9d 100644
--- a/README.md
+++ b/README.md
@@ -176,6 +176,9 @@ Flags:
                                   (default 500)
       --sendid uint               Use precanned user id (must be between 1 and
                                   40, inclusive)
+      --slowPolling bool          Enables polling for all network updates and RSA signed rounds.
+                                  Defaults to true (filtered updates with ECC signed rounds) if not set
+
   -s, --session string            Sets the initial directory for client storage
       --unsafe                    Send raw, unsafe messages without e2e
                                   encryption.
diff --git a/api/client.go b/api/client.go
index 9068708d01307030a811065b810588d8614b677c..118615bdcb7d4dc23b6a7fde682a3fdc224b4a6a 100644
--- a/api/client.go
+++ b/api/client.go
@@ -435,15 +435,16 @@ func (c *Client) StopNetworkFollower(timeout time.Duration) error {
 		return errors.WithMessage(err, "Failed to Stop the Network Follower")
 	}
 	err = c.runner.Close(timeout)
-	if err != nil {
-		return errors.WithMessage(err, "Failed to Stop the Network Follower")
-	}
 	c.runner = stoppable.NewMulti("client")
-	err = c.status.toStopped()
-	if err != nil {
-		return errors.WithMessage(err, "Failed to Stop the Network Follower")
+	err2 := c.status.toStopped()
+	if err2 != nil {
+		if err ==nil{
+			err = err2
+		}else{
+			err = errors.WithMessage(err,err2.Error())
+		}
 	}
-	return nil
+	return err
 }
 
 // NetworkFollowerStatus Gets the state of the network follower. Returns:
diff --git a/api/notifications.go b/api/notifications.go
index 99ab1d89c79faa1c955d4c2e8f587f20e2f48d60..6be89c87670c88002f921d872c603104892c5a36 100644
--- a/api/notifications.go
+++ b/api/notifications.go
@@ -46,6 +46,7 @@ func (c *Client) RegisterForNotifications(token string) error {
 			TransmissionRsaSig:    sig,
 			TransmissionSalt:      c.GetUser().TransmissionSalt,
 			IIDTransmissionRsaSig: []byte("temp"),
+			RegistrationTimestamp: c.GetUser().RegistrationTimestamp.UnixNano(),
 		})
 	if err != nil {
 		err := errors.Errorf(
diff --git a/api/permissioning.go b/api/permissioning.go
index b4691291befcb12e7b28b06948980ecc76143c78..cf0d3cb89a9de3dc37bcee689c2a23dc8f06d855 100644
--- a/api/permissioning.go
+++ b/api/permissioning.go
@@ -27,7 +27,8 @@ func (c *Client) registerWithPermissioning() error {
 	}
 
 	//register with permissioning
-	transmissionRegValidationSignature, receptionRegValidationSignature, err := c.permissioning.Register(transmissionPubKey, receptionPubKey, regCode)
+	transmissionRegValidationSignature, receptionRegValidationSignature,
+		registrationTimestamp, err := c.permissioning.Register(transmissionPubKey, receptionPubKey, regCode)
 	if err != nil {
 		return errors.WithMessage(err, "failed to register with "+
 			"permissioning")
@@ -36,6 +37,7 @@ func (c *Client) registerWithPermissioning() error {
 	//store the signature
 	userData.SetTransmissionRegistrationValidationSignature(transmissionRegValidationSignature)
 	userData.SetReceptionRegistrationValidationSignature(receptionRegValidationSignature)
+	userData.SetRegistrationTimestamp(registrationTimestamp)
 
 	//update the registration status
 	err = c.storage.ForwardRegistrationStatus(storage.PermissioningComplete)
diff --git a/api/results_test.go b/api/results_test.go
index 54433f2e9b8bcfd91e3d83e5745bdc1d3ceecc75..68e21e9aca1a317bada3ea1497c90166b1b4289c 100644
--- a/api/results_test.go
+++ b/api/results_test.go
@@ -40,7 +40,7 @@ func TestClient_GetRoundResults(t *testing.T) {
 	// Create a new copy of the test client for this test
 	client, err := newTestingClient(t)
 	if err != nil {
-		t.Errorf("Failed in setup: %v", err)
+		t.Fatalf("Failed in setup: %v", err)
 	}
 
 	// Construct the round call back function signature
@@ -103,7 +103,7 @@ func TestClient_GetRoundResults_FailedRounds(t *testing.T) {
 	// Create a new copy of the test client for this test
 	client, err := newTestingClient(t)
 	if err != nil {
-		t.Errorf("Failed in setup: %v", err)
+		t.Fatalf("Failed in setup: %v", err)
 	}
 
 	// Construct the round call back function signature
@@ -161,7 +161,7 @@ func TestClient_GetRoundResults_HistoricalRounds(t *testing.T) {
 	// Create a new copy of the test client for this test
 	client, err := newTestingClient(t)
 	if err != nil {
-		t.Errorf("Failed in setup: %v", err)
+		t.Fatalf("Failed in setup: %v", err)
 	}
 
 	// Overpopulate the round buffer, ensuring a circle back of the ring buffer
@@ -219,7 +219,7 @@ func TestClient_GetRoundResults_Timeout(t *testing.T) {
 	// Create a new copy of the test client for this test
 	client, err := newTestingClient(t)
 	if err != nil {
-		t.Errorf("Failed in setup: %v", err)
+		t.Fatalf("Failed in setup: %v", err)
 	}
 
 	// Construct the round call back function signature
diff --git a/api/utils_test.go b/api/utils_test.go
index 9b9fccac0225438387907c405efbcc023fa0e5a6..a20f1e0bf64a0da34935d467ac483caccd742dce 100644
--- a/api/utils_test.go
+++ b/api/utils_test.go
@@ -62,7 +62,7 @@ func newTestingClient(face interface{}) (*Client, error) {
 
 	thisInstance, err := network.NewInstanceTesting(instanceComms, def, def, nil, nil, face)
 	if err != nil {
-		return nil, nil
+		return nil, err
 	}
 
 	p := gateway.DefaultPoolParams()
@@ -87,6 +87,7 @@ func getNDF(face interface{}) *ndf.NetworkDefinition {
 	return &ndf.NetworkDefinition{
 		Registration: ndf.Registration{
 			TlsCertificate: string(cert),
+			EllipticPubKey: "/WRtT+mDZGC3FXQbvuQgfqOonAjJ47IKE0zhaGTQQ70=",
 		},
 		Nodes: []ndf.Node{
 			{
@@ -151,6 +152,6 @@ func signRoundInfo(ri *pb.RoundInfo) error {
 
 	ourPrivateKey := &rsa.PrivateKey{PrivateKey: *pk}
 
-	return signature.Sign(ri, ourPrivateKey)
+	return signature.SignRsa(ri, ourPrivateKey)
 
 }
diff --git a/api/version_vars.go b/api/version_vars.go
index 7a6a80ad7afc287095b1f57d7b6f7f975171495d..7ca866b7d96c690d27065573c80a38bd52916839 100644
--- a/api/version_vars.go
+++ b/api/version_vars.go
@@ -1,10 +1,10 @@
 // Code generated by go generate; DO NOT EDIT.
 // This file was generated by robots at
-// 2021-05-05 15:53:47.443011 -0500 CDT m=+0.014473892
+// 2021-05-14 10:40:35.967865 -0700 PDT m=+0.035901934
 package api
 
-const GITVERSION = `b6f474ae fixed sendCmix time delay and the interface for bindings time now`
-const SEMVER = "2.4.0"
+const GITVERSION = `7db53dd8 update go mod`
+const SEMVER = "2.6.0"
 const DEPENDENCIES = `module gitlab.com/elixxir/client
 
 go 1.13
@@ -24,17 +24,18 @@ require (
 	github.com/spf13/jwalterweatherman v1.1.0
 	github.com/spf13/viper v1.7.1
 	gitlab.com/elixxir/bloomfilter v0.0.0-20200930191214-10e9ac31b228
-	gitlab.com/elixxir/comms v0.0.4-0.20210505205202-1d4c18a7fcb2
-	gitlab.com/elixxir/crypto v0.0.7-0.20210504210535-3077ddf9984d
+	gitlab.com/elixxir/comms v0.0.4-0.20210506164842-7a132fdd895a
+	gitlab.com/elixxir/crypto v0.0.7-0.20210514172618-7745b6e1c865
 	gitlab.com/elixxir/ekv v0.1.5
-	gitlab.com/elixxir/primitives v0.0.3-0.20210504210415-34cf31c2816e
-	gitlab.com/xx_network/comms v0.0.4-0.20210505205155-48daa8448ad7
+	gitlab.com/elixxir/primitives v0.0.3-0.20210514171434-8ec71ecbb058
+	gitlab.com/xx_network/comms v0.0.4-0.20210507215532-38ed97bd9365
 	gitlab.com/xx_network/crypto v0.0.5-0.20210504210244-9ddabbad25fd
 	gitlab.com/xx_network/primitives v0.0.4-0.20210504205835-db68f11de78a
 	golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2
-	golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57 // indirect
-	google.golang.org/genproto v0.0.0-20210105202744-fe13368bc0e1 // indirect
-	google.golang.org/grpc v1.34.0 // indirect
+	golang.org/x/net v0.0.0-20210505214959-0714010a04ed
+	golang.org/x/sys v0.0.0-20210503173754-0981d6026fa6 // indirect
+	google.golang.org/genproto v0.0.0-20201030142918-24207fddd1c3 // indirect
+	google.golang.org/grpc v1.37.0 // indirect
 	google.golang.org/protobuf v1.26.0-rc.1
 	gopkg.in/ini.v1 v1.62.0 // indirect
 )
diff --git a/auth/request.go b/auth/request.go
index c43707904f835b19d1e64ba53cb4ec9fe550355f..76af994787f8e1658e13345bf14883e091e7790d 100644
--- a/auth/request.go
+++ b/auth/request.go
@@ -55,17 +55,20 @@ func RequestAuth(partner, me contact.Contact, message string, rng io.Reader,
 	//lookup if an ongoing request is occurring
 	rqType, sr, _, err := storage.Auth().GetRequest(partner.ID)
 
-	if err != nil && !strings.Contains(err.Error(), auth.NoRequest){
+	if err == nil {
 		if rqType == auth.Receive {
-			return 0, errors.WithMessage(err,
-				"Cannot send a request after receiving a request")
+			return 0, errors.Errorf("Cannot send a request after " +
+				"receiving a request")
 		} else if rqType == auth.Sent {
 			resend = true
 		}else{
-			return 0, errors.WithMessage(err,
-				"Cannot send a request after receiving unknown error " +
-				"on requesting contact status")
+			return 0, errors.Errorf("Cannot send a request after " +
+				" a stored request with unknown rqType: %d", rqType)
 		}
+	}else if !strings.Contains(err.Error(), auth.NoRequest){
+		return 0, errors.WithMessage(err,
+			"Cannot send a request after receiving unknown error " +
+				"on requesting contact status")
 	}
 
 	grp := storage.E2e().GetGroup()
diff --git a/cmd/root.go b/cmd/root.go
index 5379cc08411e557fcc39e2d05996632eddfa259e..9b11cfc79d7c1beadd311add7455f39ba8d1aa48 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -347,6 +347,7 @@ func createClient() *api.Client {
 	netParams.E2EParams.NumRekeys = uint16(
 		viper.GetUint("e2eNumReKeys"))
 	netParams.ForceHistoricalRounds = viper.GetBool("forceHistoricalRounds")
+	netParams.FastPolling = !viper.GetBool("slowPolling")
 
 	client, err := api.OpenClient(storeDir, []byte(pass), netParams)
 	if err != nil {
@@ -367,6 +368,7 @@ func initClient() *api.Client {
 	netParams.E2EParams.NumRekeys = uint16(
 		viper.GetUint("e2eNumReKeys"))
 	netParams.ForceHistoricalRounds = viper.GetBool("forceHistoricalRounds")
+	netParams.FastPolling = viper.GetBool(" slowPolling")
 
 	//load the client
 	client, err := api.Login(storeDir, []byte(pass), netParams)
@@ -762,6 +764,12 @@ func init() {
 	viper.BindPFlag("forceHistoricalRounds",
 		rootCmd.Flags().Lookup("forceHistoricalRounds"))
 
+	// Network params
+	rootCmd.Flags().BoolP("slowPolling", "", false,
+		"Enables polling for unfiltered network updates with RSA signatures")
+	viper.BindPFlag("slowPolling",
+		rootCmd.Flags().Lookup("slowPolling"))
+
 	// E2E Params
 	defaultE2EParams := params.GetDefaultE2ESessionParams()
 	rootCmd.Flags().UintP("e2eMinKeys",
diff --git a/cmd/version.go b/cmd/version.go
index b781e502cb97afc8edd8c90300c8a9f1e5816969..68e3f78210a7de2e059d35d4a877204fc1c56f38 100644
--- a/cmd/version.go
+++ b/cmd/version.go
@@ -18,7 +18,7 @@ import (
 )
 
 // Change this value to set the version for this build
-const currentVersion = "2.4.0"
+const currentVersion = "2.6.0"
 
 func Version() string {
 	out := fmt.Sprintf("Elixxir Client v%s -- %s\n\n", api.SEMVER,
diff --git a/go.mod b/go.mod
index c6234ea8322579e76604ee872b1410839c3b6eb0..7a92658fb62ce53e579b87f58cd3799a3990d7f0 100644
--- a/go.mod
+++ b/go.mod
@@ -17,14 +17,15 @@ require (
 	github.com/spf13/jwalterweatherman v1.1.0
 	github.com/spf13/viper v1.7.1
 	gitlab.com/elixxir/bloomfilter v0.0.0-20200930191214-10e9ac31b228
-	gitlab.com/elixxir/comms v0.0.4-0.20210506161214-6371db79ce6f
-	gitlab.com/elixxir/crypto v0.0.7-0.20210504210535-3077ddf9984d
+	gitlab.com/elixxir/comms v0.0.4-0.20210518184731-e69b40dd792a
+	gitlab.com/elixxir/crypto v0.0.7-0.20210518184523-674e0e2a0f6d
 	gitlab.com/elixxir/ekv v0.1.5
-	gitlab.com/elixxir/primitives v0.0.3-0.20210504210415-34cf31c2816e
-	gitlab.com/xx_network/comms v0.0.4-0.20210505205155-48daa8448ad7
-	gitlab.com/xx_network/crypto v0.0.5-0.20210504210244-9ddabbad25fd
-	gitlab.com/xx_network/primitives v0.0.4-0.20210504205835-db68f11de78a
+	gitlab.com/elixxir/primitives v0.0.3-0.20210518183904-7f91a38578ac
+	gitlab.com/xx_network/comms v0.0.4-0.20210517205649-06ddfa8d2a75
+	gitlab.com/xx_network/crypto v0.0.5-0.20210517205543-4ae99cbb9063
+	gitlab.com/xx_network/primitives v0.0.4-0.20210517202253-c7b4bd0087ea
 	golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2
+	golang.org/x/net v0.0.0-20210226172049-e18ecbb05110
 	golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57 // indirect
 	google.golang.org/genproto v0.0.0-20210105202744-fe13368bc0e1 // indirect
 	google.golang.org/grpc v1.34.0 // indirect
diff --git a/go.sum b/go.sum
index e07685770c61db52aa8e701d5040959f292fcbf5..c1976de656364df37a0c47cdc0db87a9aad41da9 100644
--- a/go.sum
+++ b/go.sum
@@ -84,6 +84,8 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
 github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
 github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
 github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
 github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
@@ -245,6 +247,7 @@ github.com/zeebo/assert v1.1.0 h1:hU1L1vLTHsnO8x8c9KAR5GmM5QscxHg5RNU5z5qbUWY=
 github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
 github.com/zeebo/blake3 v0.0.4 h1:vtZ4X8B2lKXZFg2Xyg6Wo36mvmnJvc2VQYTtA4RDCkI=
 github.com/zeebo/blake3 v0.0.4/go.mod h1:YOZo8A49yNqM0X/Y+JmDUZshJWLt1laHsNSn5ny2i34=
+github.com/zeebo/blake3 v0.1.0/go.mod h1:YOZo8A49yNqM0X/Y+JmDUZshJWLt1laHsNSn5ny2i34=
 github.com/zeebo/blake3 v0.1.1 h1:Nbsts7DdKThRHHd+YNlqiGlRqGEF2bE2eXN+xQ1hsEs=
 github.com/zeebo/blake3 v0.1.1/go.mod h1:G9pM4qQwjRzF1/v7+vabMj/c5mWpGZ2Wzo3Eb4z0pb4=
 github.com/zeebo/pcg v0.0.0-20181207190024-3cdc6b625a05 h1:4pW5fMvVkrgkMXdvIsVRRTs69DWYA8uNNQsu1stfVKU=
@@ -253,16 +256,46 @@ github.com/zeebo/pcg v1.0.0 h1:dt+dx+HvX8g7Un32rY9XWoYnd0NmKmrIzpHF7qiTDj0=
 github.com/zeebo/pcg v1.0.0/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4=
 gitlab.com/elixxir/bloomfilter v0.0.0-20200930191214-10e9ac31b228 h1:Gi6rj4mAlK0BJIk1HIzBVMjWNjIUfstrsXC2VqLYPcA=
 gitlab.com/elixxir/bloomfilter v0.0.0-20200930191214-10e9ac31b228/go.mod h1:H6jztdm0k+wEV2QGK/KYA+MY9nj9Zzatux/qIvDDv3k=
+gitlab.com/elixxir/comms v0.0.3/go.mod h1:5p7oz4yFrK037rPap6ooaWrloJrzuVZ4jnzOdvgyqnU=
 gitlab.com/elixxir/comms v0.0.4-0.20210505205202-1d4c18a7fcb2 h1:8aL4V7FaKkDb5iPdJ1rlFFhrHrLWUtbmBjw4BysXzEA=
 gitlab.com/elixxir/comms v0.0.4-0.20210505205202-1d4c18a7fcb2/go.mod h1:VN0fNE7GFMrkZwRGnqA7fNNRAXDA4CCP6su/FQQ68RI=
 gitlab.com/elixxir/comms v0.0.4-0.20210506161214-6371db79ce6f h1:0hvU+6Y+JGFnBu8ZSMk0ukNuYg+GAnVKD8Yo4VwSdao=
 gitlab.com/elixxir/comms v0.0.4-0.20210506161214-6371db79ce6f/go.mod h1:7ff+A4Nom55mKiRW7qWsN7LDjGay4OZwiaaIVXZ4hdk=
+gitlab.com/elixxir/comms v0.0.4-0.20210506182024-53912623ddd7 h1:8FEszwKqPYQJWyY4l3YFrW2ZqhJY96YFA7vS6Uh+0W8=
+gitlab.com/elixxir/comms v0.0.4-0.20210506182024-53912623ddd7/go.mod h1:7ff+A4Nom55mKiRW7qWsN7LDjGay4OZwiaaIVXZ4hdk=
+gitlab.com/elixxir/comms v0.0.4-0.20210506225017-37485f5ba063 h1:9A2FT1IDzb9E0HaEEcRMAZEVRM4SMXpklYvS6owSyIk=
+gitlab.com/elixxir/comms v0.0.4-0.20210506225017-37485f5ba063/go.mod h1:KHV+lNKhcsXoor1KQizUHhCuHugnquldrAR8UU5PNKU=
+gitlab.com/elixxir/comms v0.0.4-0.20210510215231-525cc566ee11 h1:yetSThrWUS5wFxCYXxSfLbeqU++KwdsSkhEO/9VZeMg=
+gitlab.com/elixxir/comms v0.0.4-0.20210510215231-525cc566ee11/go.mod h1:YhYFU6bXA628iJmHKV+Nuzvzh11cJNd5REU6Grb7jAY=
+gitlab.com/elixxir/comms v0.0.4-0.20210517210053-819dc80aa1c9 h1:cX0ANMa1c+JeoTApnd0uaWaHf2B4gNPfYd/8e0wGEwU=
+gitlab.com/elixxir/comms v0.0.4-0.20210517210053-819dc80aa1c9/go.mod h1:OSkqULTkOZCrtqLd8AS6+eJza48Kqj05uflUIpJHPj4=
+gitlab.com/elixxir/comms v0.0.4-0.20210517210902-9371047df8c9 h1:y3ihcqFZ7ee69ANvPOsNce4Hp1LOoZVUxhVQE5D0hOo=
+gitlab.com/elixxir/comms v0.0.4-0.20210517210902-9371047df8c9/go.mod h1:irmsXl1YGTcQcco6IV+Oc/JikiVqwczII0AD2YlsD18=
+gitlab.com/elixxir/comms v0.0.4-0.20210517211849-c6cbb2b9bddd h1:kxccdDU23xxfBeUCZfsJaE0NAL3oaEgnDG0QiLUBBwo=
+gitlab.com/elixxir/comms v0.0.4-0.20210517211849-c6cbb2b9bddd/go.mod h1:1z9NwwUwyLD6t0M39ki+8IEM46F5CR7yg2qjmxIt3Fw=
+gitlab.com/elixxir/comms v0.0.4-0.20210518161840-7267c066aec6 h1:9U+iwxqHEkee0+H/DKC8nxYiDwRYcBa9MZjaqQHSCy0=
+gitlab.com/elixxir/comms v0.0.4-0.20210518161840-7267c066aec6/go.mod h1:REyIHJwFbn+/QY5ODq/irfhvaTd+DP2tCQ5WyRHftwg=
+gitlab.com/elixxir/comms v0.0.4-0.20210518184731-e69b40dd792a h1:TkLZ/OZegdiQ03ZQHPGFVjHAEWZLS9kYLbbU25tFNlE=
+gitlab.com/elixxir/comms v0.0.4-0.20210518184731-e69b40dd792a/go.mod h1:upqVavLKeL5+WqkhXM8JNrIQmz9MjlAc5ZAgfcD0+U4=
 gitlab.com/elixxir/crypto v0.0.0-20200804182833-984246dea2c4 h1:28ftZDeYEko7xptCZzeFWS1Iam95dj46TWFVVlKmw6A=
 gitlab.com/elixxir/crypto v0.0.0-20200804182833-984246dea2c4/go.mod h1:ucm9SFKJo+K0N2GwRRpaNr+tKXMIOVWzmyUD0SbOu2c=
 gitlab.com/elixxir/crypto v0.0.3 h1:znCt/x2bL4y8czTPaaFkwzdgSgW3BJc/1+dxyf1jqVw=
 gitlab.com/elixxir/crypto v0.0.3/go.mod h1:ZNgBOblhYToR4m8tj4cMvJ9UsJAUKq+p0gCp07WQmhA=
+gitlab.com/elixxir/crypto v0.0.4/go.mod h1:ZNgBOblhYToR4m8tj4cMvJ9UsJAUKq+p0gCp07WQmhA=
 gitlab.com/elixxir/crypto v0.0.7-0.20210504210535-3077ddf9984d h1:E16E+gM2jJosFc8YmT2ISGxcfBThG2KAgsAcQXtxSIc=
 gitlab.com/elixxir/crypto v0.0.7-0.20210504210535-3077ddf9984d/go.mod h1:pbq80k+R7XXvjyWDqanD2eCJi1ClfESdKS0K8NndoLs=
+gitlab.com/elixxir/crypto v0.0.7-0.20210506212855-370e7ae2fe9d h1:hVwIoronyjco+Snfn8UbFdG9tAlpb4ZanZvfkB8ES30=
+gitlab.com/elixxir/crypto v0.0.7-0.20210506212855-370e7ae2fe9d/go.mod h1:pbq80k+R7XXvjyWDqanD2eCJi1ClfESdKS0K8NndoLs=
+gitlab.com/elixxir/crypto v0.0.7-0.20210506223047-3196e4301110 h1:4KWUbx1RI5TABBM2omWl5MLW16dwySglz895X2rhSFQ=
+gitlab.com/elixxir/crypto v0.0.7-0.20210506223047-3196e4301110/go.mod h1:pbq80k+R7XXvjyWDqanD2eCJi1ClfESdKS0K8NndoLs=
+gitlab.com/elixxir/crypto v0.0.7-0.20210511170437-f96ba33308f5 h1:MdabB2Rk4yd/VutWXzHQXgeC7EpwktH6P60eND8xSpc=
+gitlab.com/elixxir/crypto v0.0.7-0.20210511170437-f96ba33308f5/go.mod h1:pbq80k+R7XXvjyWDqanD2eCJi1ClfESdKS0K8NndoLs=
+gitlab.com/elixxir/crypto v0.0.7-0.20210517205836-5930e34ed931 h1:JgmhHdatdPvE9SMCjI5+0RGkQI071L6oFDsWl0vfhB8=
+gitlab.com/elixxir/crypto v0.0.7-0.20210517205836-5930e34ed931/go.mod h1:k2rXhBcvIasA+nGyPw0Lr/9GuFb26+sdxvyYAFLpDHw=
+gitlab.com/elixxir/crypto v0.0.7-0.20210517212824-4df0efda837f h1:mkkzCAH81FwPMo9Jxwa68D7MN0ogWsLchrLv23EvtfI=
+gitlab.com/elixxir/crypto v0.0.7-0.20210517212824-4df0efda837f/go.mod h1:k2rXhBcvIasA+nGyPw0Lr/9GuFb26+sdxvyYAFLpDHw=
+gitlab.com/elixxir/crypto v0.0.7-0.20210518184523-674e0e2a0f6d h1:zTArb08axZlm2zCiVcFr7dbldimNHGiV4HohPq91Q08=
+gitlab.com/elixxir/crypto v0.0.7-0.20210518184523-674e0e2a0f6d/go.mod h1:oGbNQBQQ+Yk3xAdfKinEm+8H7Tr1PJZTPwVVfMJmm2I=
 gitlab.com/elixxir/ekv v0.1.5 h1:R8M1PA5zRU1HVnTyrtwybdABh7gUJSCvt1JZwUSeTzk=
 gitlab.com/elixxir/ekv v0.1.5/go.mod h1:e6WPUt97taFZe5PFLPb1Dupk7tqmDCTQu1kkstqJvw4=
 gitlab.com/elixxir/primitives v0.0.0-20200731184040-494269b53b4d/go.mod h1:OQgUZq7SjnE0b+8+iIAT2eqQF+2IFHn73tOo+aV11mg=
@@ -270,17 +303,29 @@ gitlab.com/elixxir/primitives v0.0.0-20200804170709-a1896d262cd9/go.mod h1:p0Vel
 gitlab.com/elixxir/primitives v0.0.0-20200804182913-788f47bded40/go.mod h1:tzdFFvb1ESmuTCOl1z6+yf6oAICDxH2NPUemVgoNLxc=
 gitlab.com/elixxir/primitives v0.0.1 h1:q61anawANlNAExfkeQEE1NCsNih6vNV1FFLoUQX6txQ=
 gitlab.com/elixxir/primitives v0.0.1/go.mod h1:kNp47yPqja2lHSiS4DddTvFpB/4D9dB2YKnw5c+LJCE=
+gitlab.com/elixxir/primitives v0.0.2/go.mod h1:3fxFHSlQhkV4vs+S0dZEz3Om3m+40WX8L806yvSnNFc=
 gitlab.com/elixxir/primitives v0.0.3-0.20210504210415-34cf31c2816e h1:6Z5qAqI/xoWYPMVcItUDYEkOe84YWS1FJa+qjWGcJ2c=
 gitlab.com/elixxir/primitives v0.0.3-0.20210504210415-34cf31c2816e/go.mod h1:4pNgiFEQQ11hHCXBRQJN1w9AIuKa1HTlPTxs9UYOXFA=
+gitlab.com/elixxir/primitives v0.0.3-0.20210517205719-63f209b4255b h1:VRdg8ZqJUvbDIh2BTRcydbvgZhG2kVsPS3v0mtOG6F4=
+gitlab.com/elixxir/primitives v0.0.3-0.20210517205719-63f209b4255b/go.mod h1:TR4FpK1b+IE4IlDmvMnCAM0qqtrF1aYNUd+bnhRiAKI=
+gitlab.com/elixxir/primitives v0.0.3-0.20210518183904-7f91a38578ac h1:hhWkVvGEbIJyDREmVxdcCnuhpj8d8fkUd0Ocri1VcHU=
+gitlab.com/elixxir/primitives v0.0.3-0.20210518183904-7f91a38578ac/go.mod h1:TR4FpK1b+IE4IlDmvMnCAM0qqtrF1aYNUd+bnhRiAKI=
 gitlab.com/xx_network/comms v0.0.0-20200805174823-841427dd5023/go.mod h1:owEcxTRl7gsoM8c3RQ5KAm5GstxrJp5tn+6JfQ4z5Hw=
+gitlab.com/xx_network/comms v0.0.3/go.mod h1:YViGbRj7FjJYoaO4NpALGEd9dK/l8uUT000FEBbUTL8=
 gitlab.com/xx_network/comms v0.0.4-0.20210505204621-a93ded09b1ff/go.mod h1:RkNZ0CjeXKRhEFdUeAdCAF6QuK8sO1j2bUg9oqK0OEA=
 gitlab.com/xx_network/comms v0.0.4-0.20210505205155-48daa8448ad7 h1:0oQfe8YZ51kYKEj1w9UN2ls0Kp2AHRO6CUbkF/T/UH4=
 gitlab.com/xx_network/comms v0.0.4-0.20210505205155-48daa8448ad7/go.mod h1:RkNZ0CjeXKRhEFdUeAdCAF6QuK8sO1j2bUg9oqK0OEA=
+gitlab.com/xx_network/comms v0.0.4-0.20210507215532-38ed97bd9365 h1:VjeUUy4hcc2uTOO5qZ0roJlGHySWJxN/G7bf1VnLfFM=
+gitlab.com/xx_network/comms v0.0.4-0.20210507215532-38ed97bd9365/go.mod h1:RkNZ0CjeXKRhEFdUeAdCAF6QuK8sO1j2bUg9oqK0OEA=
+gitlab.com/xx_network/comms v0.0.4-0.20210517205649-06ddfa8d2a75 h1:l5szLkEfBQMa2eEt1mQf0B+Dp2pckT2y37at1MWfNj4=
+gitlab.com/xx_network/comms v0.0.4-0.20210517205649-06ddfa8d2a75/go.mod h1:qxX3x7yCATvaK8hhFibl2Rnnb+xvLior/AJlx2dk1UM=
 gitlab.com/xx_network/crypto v0.0.3/go.mod h1:DF2HYvvCw9wkBybXcXAgQMzX+MiGbFPjwt3t17VRqRE=
 gitlab.com/xx_network/crypto v0.0.4 h1:lpKOL5mTJ2awWMfgBy30oD/UvJVrWZzUimSHlOdZZxo=
 gitlab.com/xx_network/crypto v0.0.4/go.mod h1:+lcQEy+Th4eswFgQDwT0EXKp4AXrlubxalwQFH5O0Mk=
 gitlab.com/xx_network/crypto v0.0.5-0.20210504210244-9ddabbad25fd h1:jSY1ogxa2/MXthD8jadGr7IYBL4vXQID3VZp1g0GWec=
 gitlab.com/xx_network/crypto v0.0.5-0.20210504210244-9ddabbad25fd/go.mod h1:bAqc5+q2K9OXWceHkZX+VnneSKlsSeg+G98O5S4Y2cA=
+gitlab.com/xx_network/crypto v0.0.5-0.20210517205543-4ae99cbb9063 h1:BW6kQCHP5dySBWuaKjfU6gP+Wbw5Dnr8GTRzaEbF1zU=
+gitlab.com/xx_network/crypto v0.0.5-0.20210517205543-4ae99cbb9063/go.mod h1:AOUw4RJfBrKDXbe9nY/8bM3ID1czcooefUbVd82zrCY=
 gitlab.com/xx_network/primitives v0.0.0-20200803231956-9b192c57ea7c/go.mod h1:wtdCMr7DPePz9qwctNoAUzZtbOSHSedcK++3Df3psjA=
 gitlab.com/xx_network/primitives v0.0.0-20200804183002-f99f7a7284da h1:CCVslUwNC7Ul7NG5nu3ThGTSVUt1TxNRX+47f5TUwnk=
 gitlab.com/xx_network/primitives v0.0.0-20200804183002-f99f7a7284da/go.mod h1:OK9xevzWCaPO7b1wiluVJGk7R5ZsuC7pHY5hteZFQug=
@@ -288,6 +333,8 @@ gitlab.com/xx_network/primitives v0.0.2 h1:r45yKenJ9e7PylI1ZXJ1Es09oYNaYXjxVy9+u
 gitlab.com/xx_network/primitives v0.0.2/go.mod h1:cs0QlFpdMDI6lAo61lDRH2JZz+3aVkHy+QogOB6F/qc=
 gitlab.com/xx_network/primitives v0.0.4-0.20210504205835-db68f11de78a h1:Op+Dfm/Swtrs6Lgo/ro28SrCrftrfQtK9a3/EOoXYAo=
 gitlab.com/xx_network/primitives v0.0.4-0.20210504205835-db68f11de78a/go.mod h1:9imZHvYwNFobxueSvVtHneZLk9wTK7HQTzxPm+zhFhE=
+gitlab.com/xx_network/primitives v0.0.4-0.20210517202253-c7b4bd0087ea h1:yiFyOC+qhTLO/AjCOuL7hNNkD4VdPnnSmeYXXQwmGYE=
+gitlab.com/xx_network/primitives v0.0.4-0.20210517202253-c7b4bd0087ea/go.mod h1:9imZHvYwNFobxueSvVtHneZLk9wTK7HQTzxPm+zhFhE=
 gitlab.com/xx_network/ring v0.0.2 h1:TlPjlbFdhtJrwvRgIg4ScdngMTaynx/ByHBRZiXCoL0=
 gitlab.com/xx_network/ring v0.0.2/go.mod h1:aLzpP2TiZTQut/PVHR40EJAomzugDdHXetbieRClXIM=
 go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
@@ -311,6 +358,7 @@ golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de h1:ikNHVSjEfnvz6sxdSPCaPt
 golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a h1:vclmkQCjlDX5OydZ9wv8rBCcS0QyQY66Mpf/7BZbInM=
 golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY=
 golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
 golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w=
@@ -378,6 +426,7 @@ golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20200917073148-efd3b9a0ff20/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20201014080544-cc95f250f6bc/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201029080932-201ba4db2418/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210319071255-635bc2c9138d h1:jbzgAvDZn8aEnytae+4ou0J0GwFZoHR0hOrTg4qH8GA=
 golang.org/x/sys v0.0.0-20210319071255-635bc2c9138d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -434,6 +483,7 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98
 google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
 google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
 google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
+google.golang.org/genproto v0.0.0-20201030142918-24207fddd1c3/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
 google.golang.org/genproto v0.0.0-20210105202744-fe13368bc0e1 h1:Zk6zlGXdtYdcY5TL+VrbTfmifvk3VvsXopCpszsHPBA=
 google.golang.org/genproto v0.0.0-20210105202744-fe13368bc0e1/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
@@ -448,6 +498,7 @@ google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyz
 google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
 google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
 google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
+google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
 google.golang.org/protobuf v1.26.0-rc.1 h1:7QnIQpGRHE5RnLKnESfDoxm2dTapTZua5a0kS0A+VXQ=
 google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
 gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
@@ -455,6 +506,7 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
 gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
 gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
diff --git a/interfaces/IsRunning.go b/interfaces/IsRunning.go
new file mode 100644
index 0000000000000000000000000000000000000000..950b842864712858b3d1dcf769f4765e5af86159
--- /dev/null
+++ b/interfaces/IsRunning.go
@@ -0,0 +1,8 @@
+package interfaces
+
+// this interface is used to allow the follower to to be stopped later if it
+// fails
+
+type Running interface{
+	IsRunning()bool
+}
diff --git a/interfaces/params/message.go b/interfaces/params/message.go
index fbf9779829b939145cf7bc1277fa79b5617b826a..acecde4ef9861ab722ff05c7e645272f20d21694 100644
--- a/interfaces/params/message.go
+++ b/interfaces/params/message.go
@@ -16,6 +16,8 @@ type Messages struct {
 	MessageReceptionWorkerPoolSize uint
 	MaxChecksGarbledMessage        uint
 	GarbledMessageWait             time.Duration
+	// Use proxied (rather than direct) message sending
+	ProxySending bool
 }
 
 func GetDefaultMessage() Messages {
@@ -24,5 +26,6 @@ func GetDefaultMessage() Messages {
 		MessageReceptionWorkerPoolSize: 4,
 		MaxChecksGarbledMessage:        10,
 		GarbledMessageWait:             15 * time.Minute,
+		ProxySending:                   false,
 	}
 }
diff --git a/interfaces/params/network.go b/interfaces/params/network.go
index 24af3d540f2e7824328641c07ddf325c37e86dfc..2f11441ea0b6ceb50924dbb163421051912d1bab 100644
--- a/interfaces/params/network.go
+++ b/interfaces/params/network.go
@@ -25,6 +25,10 @@ type Network struct {
 	ParallelNodeRegistrations uint
 	//How far back in rounds the network should actually check
 	KnownRoundsThreshold uint
+	// Determines verbosity of network updates while polling
+	// If true, client receives a filtered set of updates
+	// If false, client receives the full list of network updates
+	FastPolling bool
 
 	Rounds
 	Messages
@@ -42,6 +46,7 @@ func GetDefaultNetwork() Network {
 		E2EParams:                 GetDefaultE2ESessionParams(),
 		ParallelNodeRegistrations: 8,
 		KnownRoundsThreshold:      1500, //5 rounds/sec * 60 sec/min * 5 min
+		FastPolling:               true,
 	}
 	n.Rounds = GetDefaultRounds()
 	n.Messages = GetDefaultMessage()
diff --git a/interfaces/user/user.go b/interfaces/user/user.go
index 7d480700e0e1c048b4ac9fcd98edb6fb25112b51..8788856b494cf386dbd903510680935f2b320daa 100644
--- a/interfaces/user/user.go
+++ b/interfaces/user/user.go
@@ -13,6 +13,7 @@ import (
 	"gitlab.com/elixxir/primitives/fact"
 	"gitlab.com/xx_network/crypto/signature/rsa"
 	"gitlab.com/xx_network/primitives/id"
+	"time"
 )
 
 type User struct {
@@ -24,6 +25,8 @@ type User struct {
 	ReceptionSalt    []byte
 	ReceptionRSA     *rsa.PrivateKey
 	Precanned        bool
+	// Timestamp in which user has registered with the network
+	RegistrationTimestamp time.Time
 
 	//cmix Identity
 	CmixDhPrivateKey *cyclic.Int
diff --git a/keyExchange/confirm_test.go b/keyExchange/confirm_test.go
index 8cef6f6f60488568614208f751914332ca5267f9..10c5ab525f3bf266f8548a6503bf14ee4c011266 100644
--- a/keyExchange/confirm_test.go
+++ b/keyExchange/confirm_test.go
@@ -20,8 +20,14 @@ import (
 // Smoke test for handleTrigger
 func TestHandleConfirm(t *testing.T) {
 	// Generate alice and bob's session
-	aliceSession, _ := InitTestingContextGeneric(t)
-	bobSession, _ := InitTestingContextGeneric(t)
+	aliceSession, _, err := InitTestingContextGeneric(t)
+	if err != nil {
+		t.Fatalf("Failed to create alice session: %v", err)
+	}
+	bobSession, _, err := InitTestingContextGeneric(t)
+	if err != nil {
+		t.Fatalf("Failed to create bob session: %v", err)
+	}
 
 	// Maintain an ID for bob
 	bobID := id.NewIdFromBytes([]byte("test"), t)
diff --git a/keyExchange/rekey.go b/keyExchange/rekey.go
index f37e2e679715a3750ec40a8f9deed924476c32ad..f2aab4c42ebedebd258e83168461b719821e1ef2 100644
--- a/keyExchange/rekey.go
+++ b/keyExchange/rekey.go
@@ -137,7 +137,7 @@ func negotiate(instance *network.Instance, sendE2E interfaces.SendE2E,
 
 	// otherwise, the transmission is a success and this should be denoted
 	// in the session and the log
-	jww.INFO.Printf("Key Negotiation transmission for %s sucesful",
+	jww.INFO.Printf("Key Negotiation transmission for %s successful",
 		session)
 	session.SetNegotiationStatus(e2e.Sent)
 
diff --git a/keyExchange/trigger.go b/keyExchange/trigger.go
index a72da7b110c92e0065a5f9acaf79698565f8815c..e22dd76f0b30974254de9fb6bd356e8e3f69d88e 100644
--- a/keyExchange/trigger.go
+++ b/keyExchange/trigger.go
@@ -153,7 +153,7 @@ func handleTrigger(sess *storage.Session, net interfaces.NetworkManager,
 	// otherwise, the transmission is a success and this should be denoted
 	// in the session and the log
 	sess.GetCriticalMessages().Succeeded(m)
-	jww.INFO.Printf("Key Negotiation transmission for %s sucesfull",
+	jww.INFO.Printf("Key Negotiation transmission for %s successfully",
 		session)
 
 	return nil
diff --git a/keyExchange/trigger_test.go b/keyExchange/trigger_test.go
index 430bba91a0ba734541b03a61260493caa03237e0..5dce2d6a7c50c8e774c3ecd88dd00f5e3db1cacc 100644
--- a/keyExchange/trigger_test.go
+++ b/keyExchange/trigger_test.go
@@ -23,9 +23,14 @@ import (
 // Smoke test for handleTrigger
 func TestHandleTrigger(t *testing.T) {
 	// Generate alice and bob's session
-	aliceSession, aliceManager := InitTestingContextGeneric(t)
-	bobSession, _ := InitTestingContextGeneric(t)
-
+	aliceSession, aliceManager, err := InitTestingContextGeneric(t)
+	if err != nil {
+		t.Fatalf("Failed to create alice session: %v", err)
+	}
+	bobSession, _, err := InitTestingContextGeneric(t)
+	if err != nil {
+		t.Fatalf("Failed to create bob session: %v", err)
+	}
 	// Pull the keys for Alice and Bob
 	alicePrivKey := aliceSession.E2e().GetDHPrivateKey()
 	bobPubKey := bobSession.E2e().GetDHPublicKey()
@@ -62,7 +67,7 @@ func TestHandleTrigger(t *testing.T) {
 	// Handle the trigger and check for an error
 	rekeyParams := params.GetDefaultRekey()
 	rekeyParams.RoundTimeout = 0 * time.Second
-	err := handleTrigger(aliceSession, aliceManager, receiveMsg, rekeyParams)
+	err = handleTrigger(aliceSession, aliceManager, receiveMsg, rekeyParams)
 	if err != nil {
 		t.Errorf("Handle trigger error: %v", err)
 	}
diff --git a/keyExchange/utils_test.go b/keyExchange/utils_test.go
index a23e673f3a258164e4e2c407defbb5dabd5394d9..58c21e7fef3e722ce5377217e36edc72248ffb31 100644
--- a/keyExchange/utils_test.go
+++ b/keyExchange/utils_test.go
@@ -108,7 +108,7 @@ func (t *testNetworkManagerGeneric) GetSender() *gateway.Sender {
 	return nil
 }
 
-func InitTestingContextGeneric(i interface{}) (*storage.Session, interfaces.NetworkManager) {
+func InitTestingContextGeneric(i interface{}) (*storage.Session, interfaces.NetworkManager, error) {
 	switch i.(type) {
 	case *testing.T, *testing.M, *testing.B, *testing.PB:
 		break
@@ -125,12 +125,12 @@ func InitTestingContextGeneric(i interface{}) (*storage.Session, interfaces.Netw
 
 	thisInstance, err := network.NewInstanceTesting(instanceComms, def, def, nil, nil, i)
 	if err != nil {
-		return nil, nil
+		return nil, nil, err
 	}
 
 	thisManager := &testNetworkManagerGeneric{instance: thisInstance}
 
-	return thisSession, thisManager
+	return thisSession, thisManager, nil
 
 }
 
@@ -304,5 +304,8 @@ func getNDF() *ndf.NetworkDefinition {
 				"BA9AE3F1DD2487199874393CD4D832186800654760E1E34C09E4D155179F9EC0" +
 				"DC4473F996BDCE6EED1CABED8B6F116F7AD9CF505DF0F998E34AB27514B0FFE7",
 		},
+		Registration: ndf.Registration{
+			EllipticPubKey: "/WRtT+mDZGC3FXQbvuQgfqOonAjJ47IKE0zhaGTQQ70=",
+		},
 	}
 }
diff --git a/network/ephemeral/tracker_test.go b/network/ephemeral/tracker_test.go
index aa4589ebe7650ab55d4d04ab97fb98cfb9d1c008..e6c3e11f8fd3b8a9e120f3634cac636b385f66c6 100644
--- a/network/ephemeral/tracker_test.go
+++ b/network/ephemeral/tracker_test.go
@@ -105,7 +105,7 @@ func setupInstance(instance interfaces.NetworkManager) error {
 	if err != nil {
 		return errors.Errorf("Failed to load cert from from file: %v", err)
 	}
-	if err = signature.Sign(ri, testCert); err != nil {
+	if err = signature.SignRsa(ri, testCert); err != nil {
 		return errors.Errorf("Failed to sign round info: %v", err)
 	}
 	if err = instance.GetInstance().RoundUpdate(ri); err != nil {
@@ -115,7 +115,7 @@ func setupInstance(instance interfaces.NetworkManager) error {
 	ri = &mixmessages.RoundInfo{
 		ID: 2,
 	}
-	if err = signature.Sign(ri, testCert); err != nil {
+	if err = signature.SignRsa(ri, testCert); err != nil {
 		return errors.Errorf("Failed to sign round info: %v", err)
 	}
 	if err = instance.GetInstance().RoundUpdate(ri); err != nil {
diff --git a/network/follow.go b/network/follow.go
index 259e9b2a0390f9f78fee741c1ba32f75e23dd660..ff3b5ba0a52420ec42a0986c087462baaee06997 100644
--- a/network/follow.go
+++ b/network/follow.go
@@ -23,12 +23,14 @@ package network
 //		instance
 
 import (
+	"bytes"
 	"fmt"
 	jww "github.com/spf13/jwalterweatherman"
 	"gitlab.com/elixxir/client/interfaces"
 	"gitlab.com/elixxir/client/network/rounds"
 	pb "gitlab.com/elixxir/comms/mixmessages"
 	"gitlab.com/elixxir/primitives/knownRounds"
+	"gitlab.com/elixxir/primitives/states"
 	"gitlab.com/xx_network/comms/connect"
 	"gitlab.com/xx_network/crypto/csprng"
 	"gitlab.com/xx_network/primitives/id"
@@ -46,7 +48,7 @@ type followNetworkComms interface {
 
 // followNetwork polls the network to get updated on the state of nodes, the
 // round status, and informs the client when messages can be retrieved.
-func (m *manager) followNetwork(report interfaces.ClientErrorReport, quitCh <-chan struct{}) {
+func (m *manager) followNetwork(report interfaces.ClientErrorReport, quitCh <-chan struct{}, isRunning interfaces.Running) {
 	ticker := time.NewTicker(m.param.TrackNetworkPeriod)
 	TrackTicker := time.NewTicker(debugTrackPeriod)
 	rng := m.Rng.GetStream()
@@ -58,17 +60,23 @@ func (m *manager) followNetwork(report interfaces.ClientErrorReport, quitCh <-ch
 			rng.Close()
 			done = true
 		case <-ticker.C:
-			m.follow(report, rng, m.Comms)
+			m.follow(report, rng, m.Comms, isRunning)
 		case <-TrackTicker.C:
 			numPolls := atomic.SwapUint64(m.tracker, 0)
 			jww.INFO.Printf("Polled the network %d times in the "+
 				"last %s", numPolls, debugTrackPeriod)
 		}
+		if !isRunning.IsRunning(){
+			jww.ERROR.Printf("Killing network follower " +
+				"due to failed exit")
+			return
+		}
 	}
 }
 
 // executes each iteration of the follower
-func (m *manager) follow(report interfaces.ClientErrorReport, rng csprng.Source, comms followNetworkComms) {
+func (m *manager) follow(report interfaces.ClientErrorReport, rng csprng.Source,
+	comms followNetworkComms, isRunning interfaces.Running) {
 
 	//get the identity we will poll for
 	identity, err := m.Session.Reception().GetIdentity(rng)
@@ -92,26 +100,29 @@ func (m *manager) follow(report interfaces.ClientErrorReport, rng csprng.Source,
 		StartTimestamp: identity.StartRequest.UnixNano(),
 		EndTimestamp:   identity.EndRequest.UnixNano(),
 		ClientVersion:  []byte(version.String()),
+		FastPolling:    m.param.FastPolling,
 	}
 
 	result, err := m.GetSender().SendToAny(func(host *connect.Host) (interface{}, error) {
 		jww.DEBUG.Printf("Executing poll for %v(%s) range: %s-%s(%s) from %s",
 			identity.EphId.Int64(), identity.Source, identity.StartRequest,
 			identity.EndRequest, identity.EndRequest.Sub(identity.StartRequest), host.GetId())
-		result, err := comms.SendPoll(host, &pollReq)
-		if err != nil {
-			if report != nil {
-				report(
-					"NetworkFollower",
-					fmt.Sprintf("Failed to poll network, \"%s\", Gateway: %s", err.Error(), host.String()),
-					fmt.Sprintf("%+v", err),
-				)
-			}
-			jww.ERROR.Printf("Unable to poll %s for NDF: %+v", host, err)
-		}
-		return result, err
+		return comms.SendPoll(host, &pollReq)
 	})
+	if !isRunning.IsRunning(){
+		jww.ERROR.Printf("Killing network follower " +
+			"due to failed exit")
+		return
+	}
 	if err != nil {
+		if report != nil {
+			report(
+				"NetworkFollower",
+				fmt.Sprintf("Failed to poll network, \"%s\":", err.Error()),
+				fmt.Sprintf("%+v", err),
+			)
+		}
+		jww.ERROR.Printf("Unable to poll gateways: %+v", err)
 		return
 	}
 
@@ -154,50 +165,49 @@ func (m *manager) follow(report interfaces.ClientErrorReport, rng csprng.Source,
 
 		// TODO: ClientErr needs to know the source of the error and it doesn't yet
 		// Iterate over ClientErrors for each RoundUpdate
-		//for _, update := range pollResp.Updates {
-		//
-		//	// Ignore irrelevant updates
-		//	if update.State != uint32(states.COMPLETED) && update.State != uint32(states.FAILED) {
-		//		continue
-		//	}
-		//
-		//	for _, clientErr := range update.ClientErrors {
-		//		// If this Client appears in the ClientError
-		//		if bytes.Equal(clientErr.ClientId, m.Session.GetUser().TransmissionID.Marshal()) {
-		//
-		//			// Obtain relevant NodeGateway information
-		//			// TODO ???
-		//			nGw, err := m.Instance.GetNodeAndGateway(gwHost.GetId())
-		//			if err != nil {
-		//				jww.ERROR.Printf("Unable to get NodeGateway: %+v", err)
-		//				return
-		//			}
-		//			nid, err := nGw.Node.GetNodeId()
-		//			if err != nil {
-		//				jww.ERROR.Printf("Unable to get NodeID: %+v", err)
-		//				return
-		//			}
-		//
-		//			// FIXME: Should be able to trigger proper type of round event
-		//			// FIXME: without mutating the RoundInfo. Signature also needs verified
-		//			// FIXME: before keys are deleted
-		//			update.State = uint32(states.FAILED)
-		//			rnd, err := m.Instance.GetWrappedRound(id.Round(update.ID))
-		//			if err != nil {
-		//				jww.ERROR.Printf("Failed to report client error: "+
-		//					"Could not get round for event triggering: "+
-		//					"Unable to get round %d from instance: %+v",
-		//					id.Round(update.ID), err)
-		//				break
-		//			}
-		//			m.Instance.GetRoundEvents().TriggerRoundEvent(rnd)
-		//
-		//			// delete all existing keys and trigger a re-registration with the relevant Node
-		//			m.Session.Cmix().Remove(nid)
-		//			m.Instance.GetAddGatewayChan() <- nGw
-		//		}
-		//	}
-		//}
+		for _, update := range pollResp.Updates {
+
+			// Ignore irrelevant updates
+			if update.State != uint32(states.COMPLETED) && update.State != uint32(states.FAILED) {
+				continue
+			}
+
+			for _, clientErr := range update.ClientErrors {
+				// If this Client appears in the ClientError
+				if bytes.Equal(clientErr.ClientId, m.Session.GetUser().TransmissionID.Marshal()) {
+
+					// Obtain relevant NodeGateway information
+					nid, err := id.Unmarshal(clientErr.Source)
+					if err != nil {
+						jww.ERROR.Printf("Unable to get NodeID: %+v", err)
+						return
+					}
+					nGw, err := m.Instance.GetNodeAndGateway(nid)
+					if err != nil {
+						jww.ERROR.Printf("Unable to get gateway: %+v", err)
+						return
+					}
+
+					// FIXME: Should be able to trigger proper type of round event
+					// FIXME: without mutating the RoundInfo. Signature also needs verified
+					// FIXME: before keys are deleted
+					update.State = uint32(states.FAILED)
+					rnd, err := m.Instance.GetWrappedRound(id.Round(update.ID))
+					if err != nil {
+						jww.ERROR.Printf("Failed to report client error: "+
+							"Could not get round for event triggering: "+
+							"Unable to get round %d from instance: %+v",
+							id.Round(update.ID), err)
+						break
+					}
+					m.Instance.GetRoundEvents().TriggerRoundEvent(rnd)
+
+					// delete all existing keys and trigger a re-registration with the relevant Node
+					m.Session.Cmix().Remove(nid)
+					m.Instance.GetAddGatewayChan() <- nGw
+				}
+			}
+		}
 	}
 
 	// ---- Identity Specific Round Processing -----
diff --git a/network/gateway/hostPool.go b/network/gateway/hostPool.go
index 305cc4ea1d111a7cf9c01eff94814ff59c98a2a0..ba8198da839c4e9d2693d866be165f6afaf08d47 100644
--- a/network/gateway/hostPool.go
+++ b/network/gateway/hostPool.go
@@ -22,6 +22,7 @@ import (
 	"gitlab.com/xx_network/comms/connect"
 	"gitlab.com/xx_network/primitives/id"
 	"gitlab.com/xx_network/primitives/ndf"
+	"golang.org/x/net/context"
 	"io"
 	"math"
 	"strings"
@@ -30,7 +31,7 @@ import (
 )
 
 // List of errors that initiate a Host replacement
-var errorsList = []string{"context deadline exceeded", "connection refused", "host disconnected",
+var errorsList = []string{context.DeadlineExceeded.Error(), "connection refused", "host disconnected",
 	"transport is closing", "all SubConns are in TransientFailure", "Last try to connect",
 	ndf.NO_NDF, "Host is in cool down"}
 
@@ -80,7 +81,7 @@ func DefaultPoolParams() PoolParams {
 	p.HostParams.EnableCoolOff = true
 	p.HostParams.NumSendsBeforeCoolOff = 1
 	p.HostParams.CoolOffTimeout = 5 * time.Minute
-	p.HostParams.SendTimeout = 3500*time.Millisecond
+	p.HostParams.SendTimeout = 3500 * time.Millisecond
 	return p
 }
 
@@ -224,7 +225,9 @@ func (h *HostPool) getPreferred(targets []*id.ID) []*connect.Host {
 }
 
 // Replaces the given hostId in the HostPool if the given hostErr is in errorList
-func (h *HostPool) checkReplace(hostId *id.ID, hostErr error) error {
+// Returns whether the host was replaced
+func (h *HostPool) checkReplace(hostId *id.ID, hostErr error) (bool, error) {
+	var err error
 	// Check if Host should be replaced
 	doReplace := false
 	if hostErr != nil {
@@ -238,19 +241,17 @@ func (h *HostPool) checkReplace(hostId *id.ID, hostErr error) error {
 	}
 
 	if doReplace {
-		h.hostMux.Lock()
-		defer h.hostMux.Unlock()
-
 		// If the Host is still in the pool
+		h.hostMux.Lock()
 		if oldPoolIndex, ok := h.hostMap[*hostId]; ok {
 			// Replace it
 			h.ndfMux.RLock()
-			err := h.forceReplace(oldPoolIndex)
+			err = h.forceReplace(oldPoolIndex)
 			h.ndfMux.RUnlock()
-			return err
 		}
+		h.hostMux.Unlock()
 	}
-	return nil
+	return doReplace, err
 }
 
 // Replace given Host index with a new, randomly-selected Host from the NDF
diff --git a/network/gateway/hostpool_test.go b/network/gateway/hostpool_test.go
index 8181e6d49f0ea5522e8ae33eb6ac143516c45a26..49dcacf6b8231647b8c0cbc0ab6e6f84b0c7d126 100644
--- a/network/gateway/hostpool_test.go
+++ b/network/gateway/hostpool_test.go
@@ -359,10 +359,13 @@ func TestHostPool_CheckReplace(t *testing.T) {
 	oldGatewayIndex := 0
 	oldHost := testPool.hostList[oldGatewayIndex]
 	expectedError := fmt.Errorf(errorsList[0])
-	err = testPool.checkReplace(oldHost.GetId(), expectedError)
+	wasReplaced, err := testPool.checkReplace(oldHost.GetId(), expectedError)
 	if err != nil {
 		t.Errorf("Failed to check replace: %v", err)
 	}
+	if !wasReplaced {
+		t.Errorf("Expected to replace")
+	}
 
 	// Ensure that old gateway has been removed from the map
 	if _, ok := testPool.hostMap[*oldHost.GetId()]; ok {
@@ -378,10 +381,13 @@ func TestHostPool_CheckReplace(t *testing.T) {
 	goodGatewayIndex := 0
 	goodGateway := testPool.hostList[goodGatewayIndex]
 	unexpectedErr := fmt.Errorf("not in global error list")
-	err = testPool.checkReplace(oldHost.GetId(), unexpectedErr)
+	wasReplaced, err = testPool.checkReplace(oldHost.GetId(), unexpectedErr)
 	if err != nil {
 		t.Errorf("Failed to check replace: %v", err)
 	}
+	if wasReplaced {
+		t.Errorf("Expected not to replace")
+	}
 
 	// Ensure that gateway with an unexpected error was not modified
 	if _, ok := testPool.hostMap[*goodGateway.GetId()]; !ok {
diff --git a/network/gateway/sender.go b/network/gateway/sender.go
index dcfcdbb5b88a0be02b67f4f61dfcaa01c1169489..619581cd7c9d4289ef3a88faeff48eff2a67bb6d 100644
--- a/network/gateway/sender.go
+++ b/network/gateway/sender.go
@@ -14,6 +14,7 @@ import (
 	"gitlab.com/elixxir/client/storage"
 	"gitlab.com/elixxir/comms/network"
 	"gitlab.com/elixxir/crypto/fastRNG"
+	"gitlab.com/elixxir/crypto/shuffle"
 	"gitlab.com/xx_network/comms/connect"
 	"gitlab.com/xx_network/primitives/id"
 	"gitlab.com/xx_network/primitives/ndf"
@@ -63,7 +64,7 @@ func (s *Sender) SendToSpecific(target *id.ID,
 					host.GetId().String())
 			}
 			jww.WARN.Printf("Unable to SendToSpecific proxy %s: %s", proxies[i].GetId().String(), err)
-			err = s.checkReplace(proxies[i].GetId(), err)
+			_, err = s.checkReplace(proxies[i].GetId(), err)
 			if err != nil {
 				jww.ERROR.Printf("Unable to checkReplace: %+v", err)
 			}
@@ -83,7 +84,7 @@ func (s *Sender) SendToAny(sendFunc func(host *connect.Host) (interface{}, error
 			return result, nil
 		} else {
 			jww.WARN.Printf("Unable to SendToAny %s: %s", proxies[i].GetId().String(), err)
-			err = s.checkReplace(proxies[i].GetId(), err)
+			_, err = s.checkReplace(proxies[i].GetId(), err)
 			if err != nil {
 				jww.ERROR.Printf("Unable to checkReplace: %+v", err)
 			}
@@ -97,7 +98,20 @@ func (s *Sender) SendToAny(sendFunc func(host *connect.Host) (interface{}, error
 func (s *Sender) SendToPreferred(targets []*id.ID,
 	sendFunc func(host *connect.Host, target *id.ID) (interface{}, error)) (interface{}, error) {
 
+	// Get the hosts and shuffle randomly
 	targetHosts := s.getPreferred(targets)
+	var rndBytes [32]byte
+	stream := s.rng.GetStream()
+	_, err := stream.Read(rndBytes[:])
+	stream.Close()
+	if err != nil {
+		return nil, err
+	}
+	shuffle.ShuffleSwap(rndBytes[:], len(targetHosts), func(i, j int) {
+		targetHosts[i], targetHosts[j] = targetHosts[j], targetHosts[i]
+	})
+
+	// Attempt to send directly to targets if they are in the HostPool
 	for i := range targetHosts {
 		result, err := sendFunc(targetHosts[i], targets[i])
 		if err == nil {
@@ -105,25 +119,48 @@ func (s *Sender) SendToPreferred(targets []*id.ID,
 		} else {
 			jww.WARN.Printf("Unable to SendToPreferred %s via %s: %s",
 				targets[i], targetHosts[i].GetId(), err)
-			err = s.checkReplace(targetHosts[i].GetId(), err)
+			_, err = s.checkReplace(targetHosts[i].GetId(), err)
 			if err != nil {
 				jww.ERROR.Printf("Unable to checkReplace: %+v", err)
 			}
 		}
 	}
 
-	proxies := s.getAny(s.poolParams.ProxyAttempts, targets)
-	for i := range proxies {
-		target := targets[i%len(targets)].DeepCopy()
-		result, err := sendFunc(proxies[i], target)
-		if err == nil {
-			return result, nil
-		} else {
-			jww.WARN.Printf("Unable to SendToPreferred %s via proxy "+
-				"%s: %s", target, proxies[i].GetId(), err)
-			err = s.checkReplace(proxies[i].GetId(), err)
-			if err != nil {
-				jww.ERROR.Printf("Unable to checkReplace: %+v", err)
+	// Build a list of proxies for every target
+	proxies := make([][]*connect.Host, len(targets))
+	for i := 0; i < len(targets); i++ {
+		proxies[i] = s.getAny(s.poolParams.ProxyAttempts, targets)
+	}
+
+	// Build a map of bad proxies
+	badProxies := make(map[string]interface{})
+
+	// Iterate between each target's list of proxies, using the next target for each proxy
+	for proxyIdx := uint32(0); proxyIdx < s.poolParams.ProxyAttempts; proxyIdx++ {
+		for targetIdx := range proxies {
+			target := targets[targetIdx]
+			targetProxies := proxies[targetIdx]
+			proxy := targetProxies[proxyIdx]
+
+			// Skip bad proxies
+			if _, ok := badProxies[proxy.String()]; ok {
+				continue
+			}
+
+			result, err := sendFunc(targetProxies[proxyIdx], target)
+			if err == nil {
+				return result, nil
+			} else {
+				jww.WARN.Printf("Unable to SendToPreferred %s via proxy "+
+					"%s: %s", target, proxy.GetId(), err)
+				wasReplaced, err := s.checkReplace(proxy.GetId(), err)
+				if err != nil {
+					jww.ERROR.Printf("Unable to checkReplace: %+v", err)
+				}
+				// If the proxy was replaced, add as a bad proxy
+				if wasReplaced {
+					badProxies[proxy.String()] = nil
+				}
 			}
 		}
 	}
diff --git a/network/manager.go b/network/manager.go
index 31adb444767b544e7c6a62da9489631293dbdd8a..0426d7a980d558c44a8de5dddd697724cb31a01e 100644
--- a/network/manager.go
+++ b/network/manager.go
@@ -56,7 +56,7 @@ func NewManager(session *storage.Session, switchboard *switchboard.Switchboard,
 	params params.Network, ndf *ndf.NetworkDefinition) (interfaces.NetworkManager, error) {
 
 	//start network instance
-	instance, err := network.NewInstance(comms.ProtoComms, ndf, nil, nil, network.None)
+	instance, err := network.NewInstance(comms.ProtoComms, ndf, nil, nil, network.None, params.FastPolling)
 	if err != nil {
 		return nil, errors.WithMessage(err, "failed to create"+
 			" client network manager")
@@ -130,7 +130,7 @@ func (m *manager) Follow(report interfaces.ClientErrorReport) (stoppable.Stoppab
 
 	// Start the Network Tracker
 	trackNetworkStopper := stoppable.NewSingle("TrackNetwork")
-	go m.followNetwork(report, trackNetworkStopper.Quit())
+	go m.followNetwork(report, trackNetworkStopper.Quit(), trackNetworkStopper)
 	multi.Add(trackNetworkStopper)
 
 	// Message reception
diff --git a/network/message/critical.go b/network/message/critical.go
index 1dad92c821e756e3c89c6d013c5d78c9e09a1015..384ac9981f1dec0471b72aa3083880c26fc56382 100644
--- a/network/message/critical.go
+++ b/network/message/critical.go
@@ -80,7 +80,7 @@ func (m *Manager) criticalMessages() {
 				return
 			}
 
-			jww.INFO.Printf("Sucesfull resend of critical message "+
+			jww.INFO.Printf("Successful resend of critical message "+
 				"to %s on rounds %d", msg.Recipient, rounds)
 			critMsgs.Succeeded(msg)
 		}(msg, param)
@@ -128,7 +128,7 @@ func (m *Manager) criticalMessages() {
 				return
 			}
 
-			jww.INFO.Printf("Sucesfull resend of critical raw message "+
+			jww.INFO.Printf("Successful resend of critical raw message "+
 				"to %s (msgDigest: %s) on round %d", rid, msg.Digest(), round)
 
 			critRawMsgs.Succeeded(msg, rid)
diff --git a/network/message/garbled_test.go b/network/message/garbled_test.go
index 9d021ae488ed26717aade2d76d87ba688c7f9001..ab4919f16d674ea10a609ca6d0e46a442259789f 100644
--- a/network/message/garbled_test.go
+++ b/network/message/garbled_test.go
@@ -105,6 +105,7 @@ func TestManager_CheckGarbledMessages(t *testing.T) {
 	contents := make([]byte, msg.ContentsSize())
 	prng := rand.New(rand.NewSource(42))
 	prng.Read(contents)
+	contents[len(contents)-1] = 0
 	fmp := parse.FirstMessagePartFromBytes(contents)
 	binary.BigEndian.PutUint32(fmp.Type, uint32(message.Raw))
 	fmp.NumParts[0] = uint8(1)
diff --git a/network/message/parse/firstMessagePart.go b/network/message/parse/firstMessagePart.go
index 958a386992f161f007921476f52eb9749ea628bf..fa67b64411e0f2272178452eeb0a8deb91612271 100644
--- a/network/message/parse/firstMessagePart.go
+++ b/network/message/parse/firstMessagePart.go
@@ -9,92 +9,123 @@ package parse
 
 import (
 	"encoding/binary"
-	jww "github.com/spf13/jwalterweatherman"
 	"gitlab.com/elixxir/client/interfaces/message"
 	"time"
 )
 
-const numPartsLen = 1
-const typeLen = message.TypeLen
-const timestampLen = 15
-const firstHeaderLen = headerLen + numPartsLen + typeLen + timestampLen
+// Sizes of message parts, in bytes.
+const (
+	numPartsLen     = 1
+	typeLen         = message.TypeLen
+	timestampLen    = 8
+	firstPartVerLen = 1
+	firstHeaderLen  = headerLen + numPartsLen + typeLen + timestampLen + firstPartVerLen
+)
+
+// The current version of the firstMessagePart message format.
+const firstMessagePartCurrentVersion = 0
 
 type firstMessagePart struct {
 	messagePart
 	NumParts  []byte
 	Type      []byte
 	Timestamp []byte
+	Version   []byte // Version of the message format; always the last bit
 }
 
-//creates a new first message part for the passed in contents. Does no length checks
+// newFirstMessagePart creates a new firstMessagePart for the passed in
+// contents. Does no length checks.
 func newFirstMessagePart(mt message.Type, id uint32, numParts uint8,
 	timestamp time.Time, contents []byte) firstMessagePart {
-	//create the message structure
-	data := make([]byte, len(contents)+firstHeaderLen)
-	m := FirstMessagePartFromBytes(data)
 
-	//Put the message type in the message
+	// Create the message structure
+	m := FirstMessagePartFromBytes(make([]byte, len(contents)+firstHeaderLen))
+
+	// Set the message type
 	binary.BigEndian.PutUint32(m.Type, uint32(mt))
 
-	//Add the message ID
+	// Set the message ID
 	binary.BigEndian.PutUint32(m.Id, id)
 
-	// Add the part number to the message, its always zero because this is the
-	// first part. Because the default is zero this step could be skipped, but\
-	// keep it in the code for clarity
+	// Set the part number. It is always zero because this is the first part.
+	// Because the default is zero this step could be skipped, but keep it in
+	// the code for clarity.
 	m.Part[0] = 0
 
-	// Add the number of parts to the message
+	// Set the number of parts to the message
 	m.NumParts[0] = numParts
 
-	//Serialize and add the timestamp to the payload
-	timestampBytes, err := timestamp.MarshalBinary()
-	if err != nil {
-		jww.FATAL.Panicf("Failed to create firstMessagePart: %s", err.Error())
-	}
-	copy(m.Timestamp, timestampBytes)
+	// Set the timestamp as unix nano
+	binary.BigEndian.PutUint64(m.Timestamp, uint64(timestamp.UnixNano()))
 
-	//set the contents length
+	// Set the length of the contents
 	binary.BigEndian.PutUint16(m.Len, uint16(len(contents)))
 
-	//add the contents to the payload
+	// Set the contents
 	copy(m.Contents[:len(contents)], contents)
 
+	// Set the version number
+	m.Version[0] = firstMessagePartCurrentVersion
+
 	return m
 }
 
-// Builds a first message part mapped to the passed in data slice. Mapped by
-// reference, a copy is not made.
+// Map of firstMessagePart encoding version numbers to their map functions.
+var firstMessagePartFromBytesVersions = map[uint8]func([]byte) firstMessagePart{
+	firstMessagePartCurrentVersion: firstMessagePartFromBytesVer0,
+}
+
+// FirstMessagePartFromBytes builds a firstMessagePart mapped to the passed in
+// data slice. Mapped by reference; a copy is not made.
 func FirstMessagePartFromBytes(data []byte) firstMessagePart {
-	m := firstMessagePart{
+
+	// Map the data according to its version
+	version := data[len(data)-1]
+	mapFunc, exists := firstMessagePartFromBytesVersions[version]
+	if exists {
+		return mapFunc(data)
+	}
+
+	return firstMessagePart{}
+}
+
+func firstMessagePartFromBytesVer0(data []byte) firstMessagePart {
+	return firstMessagePart{
 		messagePart: messagePart{
 			Data:     data,
 			Id:       data[:idLen],
 			Part:     data[idLen : idLen+partLen],
 			Len:      data[idLen+partLen : idLen+partLen+lenLen],
-			Contents: data[idLen+partLen+numPartsLen+typeLen+timestampLen+lenLen:],
+			Contents: data[idLen+partLen+lenLen+numPartsLen+typeLen+timestampLen : len(data)-firstPartVerLen-1],
 		},
-		NumParts:  data[idLen+partLen+lenLen : idLen+partLen+numPartsLen+lenLen],
-		Type:      data[idLen+partLen+numPartsLen+lenLen : idLen+partLen+numPartsLen+typeLen+lenLen],
-		Timestamp: data[idLen+partLen+numPartsLen+typeLen+lenLen : idLen+partLen+numPartsLen+typeLen+timestampLen+lenLen],
+		NumParts:  data[idLen+partLen+lenLen : idLen+partLen+lenLen+numPartsLen],
+		Type:      data[idLen+partLen+lenLen+numPartsLen : idLen+partLen+lenLen+numPartsLen+typeLen],
+		Timestamp: data[idLen+partLen+lenLen+numPartsLen+typeLen : idLen+partLen+lenLen+numPartsLen+typeLen+timestampLen],
+		Version:   data[len(data)-firstPartVerLen:],
 	}
-	return m
 }
 
+// GetType returns the message type.
 func (m firstMessagePart) GetType() message.Type {
 	return message.Type(binary.BigEndian.Uint32(m.Type))
 }
 
+// GetNumParts returns the number of message parts.
 func (m firstMessagePart) GetNumParts() uint8 {
 	return m.NumParts[0]
 }
 
-func (m firstMessagePart) GetTimestamp() (time.Time, error) {
-	var t time.Time
-	err := t.UnmarshalBinary(m.Timestamp)
-	return t, err
+// GetTimestamp returns the timestamp as a time.Time.
+func (m firstMessagePart) GetTimestamp() time.Time {
+	return time.Unix(0, int64(binary.BigEndian.Uint64(m.Timestamp)))
+}
+
+// GetVersion returns the version number of the data encoding.
+func (m firstMessagePart) GetVersion() uint8 {
+	return m.Version[0]
 }
 
+// Bytes returns the serialised message data.
 func (m firstMessagePart) Bytes() []byte {
 	return m.Data
 }
diff --git a/network/message/parse/firstMessagePart_test.go b/network/message/parse/firstMessagePart_test.go
index 676723247fec562607d43f9a29dec827890c76a8..2411dd4a6896453f08d2fd02ae2dd15946f0f76c 100644
--- a/network/message/parse/firstMessagePart_test.go
+++ b/network/message/parse/firstMessagePart_test.go
@@ -18,16 +18,19 @@ import (
 // Expected firstMessagePart for checking against, generated by fmp in TestNewFirstMessagePart
 var efmp = firstMessagePart{
 	messagePart: messagePart{
-		Data: []byte{0, 0, 4, 53, 0, 0, 13, 2, 0, 0, 0, 2, 1, 0, 0, 0, 14, 215, 133, 90, 117, 0, 0, 0, 0, 255, 255,
-			116, 101, 115, 116, 105, 110, 103, 115, 116, 114, 105, 110, 103},
-		Id:       []byte{0, 0, 4, 53},
-		Part:     []byte{0},
-		Len:      []byte{0, 13},
-		Contents: []byte{116, 101, 115, 116, 105, 110, 103, 115, 116, 114, 105, 110, 103},
+		Data: []byte{0, 0, 4, 53, 0, 0, 13, 2, 0, 0, 0, 2, 22, 87, 28, 11, 215,
+			220, 82, 0, 116, 101, 115, 116, 105, 110, 103, 115, 116, 114, 105,
+			110, 103, 0, firstMessagePartCurrentVersion},
+		Id:   []byte{0, 0, 4, 53},
+		Part: []byte{0},
+		Len:  []byte{0, 13},
+		Contents: []byte{116, 101, 115, 116, 105, 110, 103, 115, 116, 114, 105,
+			110, 103},
 	},
 	NumParts:  []byte{2},
 	Type:      []byte{0, 0, 0, 2},
-	Timestamp: []byte{1, 0, 0, 0, 14, 215, 133, 90, 117, 0, 0, 0, 0, 255, 255},
+	Timestamp: []byte{22, 87, 28, 11, 215, 220, 82, 0},
+	Version:   []byte{firstMessagePartCurrentVersion},
 }
 
 // Test that newFirstMessagePart returns a correctly made firstMessagePart
@@ -37,24 +40,19 @@ func TestNewFirstMessagePart(t *testing.T) {
 		1077,
 		2,
 		time.Unix(1609786229, 0).UTC(),
-		[]byte{'t', 'e', 's', 't', 'i', 'n', 'g',
-			's', 't', 'r', 'i', 'n', 'g'},
+		[]byte{'t', 'e', 's', 't', 'i', 'n', 'g', 's', 't', 'r', 'i', 'n', 'g'},
 	)
 
-	gotTime, err := fmp.GetTimestamp()
-	if err != nil {
-		t.Error(err)
-	}
-	expectedTime, err := fmp.GetTimestamp()
-	if err != nil {
-		t.Error(err)
-	}
+	gotTime := fmp.GetTimestamp()
+	expectedTime := time.Unix(1609786229, 0).UTC()
 	if !gotTime.Equal(expectedTime) {
-		t.Errorf("Got time: %v, expected time: %v", gotTime, expectedTime)
+		t.Errorf("Failed to get expected timestamp."+
+			"\nexpected: %s\nreceived: %s", expectedTime, gotTime)
 	}
 
 	if !reflect.DeepEqual(fmp, efmp) {
-		t.Errorf("Expected and got firstMessagePart did not match.\n\tGot: %#v\n\tExpected: %#v", fmp, efmp)
+		t.Errorf("Expected and got firstMessagePart did not match."+
+			"\nexpected: %+v\nrecieved: %+v", efmp, fmp)
 	}
 }
 
@@ -83,10 +81,7 @@ func TestFirstMessagePart_GetNumParts(t *testing.T) {
 
 // Test that GetTimestamp returns the correct timestamp for a firstMessagePart
 func TestFirstMessagePart_GetTimestamp(t *testing.T) {
-	et, err := efmp.GetTimestamp()
-	if err != nil {
-		t.Error(err)
-	}
+	et := efmp.GetTimestamp()
 	if !time.Unix(1609786229, 0).Equal(et) {
 		t.Errorf("Got %v, expected %v", et, time.Unix(1609786229, 0))
 	}
diff --git a/network/message/parse/messagePart.go b/network/message/parse/messagePart.go
index 815544be80370e2c4f66482c903ae0cbe9e9ad92..01c514d7c33fe1654534a67aeaf8671744d93982 100644
--- a/network/message/parse/messagePart.go
+++ b/network/message/parse/messagePart.go
@@ -11,10 +11,17 @@ import (
 	"encoding/binary"
 )
 
-const idLen = 4
-const partLen = 1
-const lenLen = 2
-const headerLen = idLen + partLen + lenLen
+// Sizes of message parts, in bytes.
+const (
+	idLen      = 4
+	partLen    = 1
+	lenLen     = 2
+	partVerLen = 1
+	headerLen  = idLen + partLen + lenLen + partVerLen
+)
+
+// The current version of the messagePart message format.
+const messagePartCurrentVersion = 0
 
 type messagePart struct {
 	Data     []byte
@@ -22,62 +29,90 @@ type messagePart struct {
 	Part     []byte
 	Len      []byte
 	Contents []byte
+	Version  []byte // Version of the message format; always the last bit
 }
 
-//creates a new message part for the passed in contents. Does no length checks
+// newMessagePart creates a new messagePart for the passed in contents. Does no
+// length checks.
 func newMessagePart(id uint32, part uint8, contents []byte) messagePart {
-	//create the message structure
+	// Create the message structure
 	data := make([]byte, len(contents)+headerLen)
-	m := MessagePartFromBytes(data)
+	m := messagePartFromBytes(data)
 
-	//add the message ID to the message
+	// Set the message ID
 	binary.BigEndian.PutUint32(m.Id, id)
 
-	//set the message part number
+	// Set the message part number
 	m.Part[0] = part
 
-	//set the contents length
+	// Set the contents length
 	binary.BigEndian.PutUint16(m.Len, uint16(len(contents)))
 
-	//copy the contents into the message
+	// Copy the contents into the message
 	copy(m.Contents[:len(contents)], contents)
+
+	// Set the version number
+	m.Version[0] = messagePartCurrentVersion
+
 	return m
 }
 
-// Builds a Message part mapped to the passed in data slice. Mapped by
-// reference, a copy is not made.
-func MessagePartFromBytes(data []byte) messagePart {
-	m := messagePart{
+// Map of messagePart encoding version numbers to their map functions.
+var messagePartFromBytesVersions = map[uint8]func([]byte) messagePart{
+	messagePartCurrentVersion: messagePartFromBytesVer0,
+}
+
+// messagePartFromBytes builds a messagePart mapped to the passed in data slice.
+// Mapped by reference; a copy is not made.
+func messagePartFromBytes(data []byte) messagePart {
+
+	// Map the data according to its version
+	version := data[len(data)-1]
+	mapFunc, exists := messagePartFromBytesVersions[version]
+	if exists {
+		return mapFunc(data)
+	}
+
+	return messagePart{}
+}
+
+func messagePartFromBytesVer0(data []byte) messagePart {
+	return messagePart{
 		Data:     data,
 		Id:       data[:idLen],
 		Part:     data[idLen : idLen+partLen],
 		Len:      data[idLen+partLen : idLen+partLen+lenLen],
-		Contents: data[idLen+partLen+lenLen:],
+		Contents: data[idLen+partLen+lenLen : len(data)-partVerLen],
+		Version:  data[len(data)-partVerLen:],
 	}
-	return m
 }
 
+// GetID returns the message ID.
 func (m messagePart) GetID() uint32 {
 	return binary.BigEndian.Uint32(m.Id)
 }
 
+// GetPart returns the message part number.
 func (m messagePart) GetPart() uint8 {
 	return m.Part[0]
 }
 
+// GetContents returns the entire contents slice.
 func (m messagePart) GetContents() []byte {
 	return m.Contents
 }
 
+// GetSizedContents returns the contents truncated to include only stored data.
 func (m messagePart) GetSizedContents() []byte {
-	size := m.GetContentsLength()
-	return m.Contents[:size]
+	return m.Contents[:m.GetContentsLength()]
 }
 
+// GetContentsLength returns the length of the data in the contents.
 func (m messagePart) GetContentsLength() int {
 	return int(binary.BigEndian.Uint16(m.Len))
 }
 
+// Bytes returns the serialised message data.
 func (m messagePart) Bytes() []byte {
 	return m.Data
 }
diff --git a/network/message/parse/messagePart_test.go b/network/message/parse/messagePart_test.go
index 5ab1db0213c05a18f7615a836e627350a5879616..61ecc7467ff5c95dd2cf89830cacbb319cf9660f 100644
--- a/network/message/parse/messagePart_test.go
+++ b/network/message/parse/messagePart_test.go
@@ -15,17 +15,19 @@ import (
 
 // Expected messagePart for checking against, generated by gotmp in Test_newMessagePart
 var emp = messagePart{
-	Data: []uint8{0x0, 0x0, 0x0, 0x20, 0x6, 0x0, 0x7, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67},
+	Data: []uint8{0x0, 0x0, 0x0, 0x20, 0x6, 0x0, 0x7, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, messagePartCurrentVersion},
 	Id:   []uint8{0x0, 0x0, 0x0, 0x20}, Part: []uint8{0x6},
 	Len:      []uint8{0x0, 0x7},
 	Contents: []uint8{0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67},
+	Version:  []uint8{messagePartCurrentVersion},
 }
 
 // This tests that a new function part is successfully created
 func Test_newMessagePart(t *testing.T) {
 	gotmp := newMessagePart(32, 6, []byte{'t', 'e', 's', 't', 'i', 'n', 'g'})
 	if !reflect.DeepEqual(gotmp, emp) {
-		t.Errorf("MessagePart received and MessagePart expected do not match.\n\tGot: %#v\n\tExpected: %#v", gotmp, emp)
+		t.Errorf("MessagePart received and MessagePart expected do not match."+
+			"\nexpected: %#v\nreceived: %#v", emp, gotmp)
 	}
 }
 
diff --git a/network/message/parse/partition.go b/network/message/parse/partition.go
index 0b690a5bef804dd269cd62cbcc0ecac6d2667439..e7fbbfd313379570d3ec522d23053fbd025456cf 100644
--- a/network/message/parse/partition.go
+++ b/network/message/parse/partition.go
@@ -9,7 +9,6 @@ package parse
 
 import (
 	"github.com/pkg/errors"
-	jww "github.com/spf13/jwalterweatherman"
 	"gitlab.com/elixxir/client/interfaces/message"
 	"gitlab.com/elixxir/client/storage"
 	"gitlab.com/xx_network/primitives/id"
@@ -44,23 +43,23 @@ func (p Partitioner) Partition(recipient *id.ID, mt message.Type,
 
 	if len(payload) > p.maxSize {
 		return nil, 0, errors.Errorf("Payload is too long, max payload "+
-			"length is %v, received %v", p.maxSize, len(payload))
+			"length is %d, received %d", p.maxSize, len(payload))
 	}
 
-	//Get the ID of the sent message
+	// Get the ID of the sent message
 	fullMessageID, messageID := p.session.Conversations().Get(recipient).GetNextSendID()
 
-	// get the number of parts of the message. This equates to just a linear
+	// Get the number of parts of the message; this equates to just a linear
 	// equation
 	numParts := uint8((len(payload) + p.deltaFirstPart + p.partContentsSize - 1) / p.partContentsSize)
 	parts := make([][]byte, numParts)
 
-	//Create the first message part
+	// Create the first message part
 	var sub []byte
 	sub, payload = splitPayload(payload, p.firstContentsSize)
 	parts[0] = newFirstMessagePart(mt, messageID, numParts, timestamp, sub).Bytes()
 
-	//create all subsiquent message parts
+	// Create all subsequent message parts
 	for i := uint8(1); i < numParts; i++ {
 		sub, payload = splitPayload(payload, p.partContentsSize)
 		parts[i] = newMessagePart(messageID, i, sub).Bytes()
@@ -69,31 +68,25 @@ func (p Partitioner) Partition(recipient *id.ID, mt message.Type,
 	return parts, fullMessageID, nil
 }
 
-func (p Partitioner) HandlePartition(sender *id.ID, e message.EncryptionType,
+func (p Partitioner) HandlePartition(sender *id.ID, _ message.EncryptionType,
 	contents []byte, relationshipFingerprint []byte) (message.Receive, bool) {
 
-	//If it is the first message in a set, handle it as so
 	if isFirst(contents) {
-		//decode the message structure
+		// If it is the first message in a set, then handle it as so
+
+		// Decode the message structure
 		fm := FirstMessagePartFromBytes(contents)
-		timestamp, err := fm.GetTimestamp()
-		if err != nil {
-			jww.FATAL.Panicf("Failed Handle Partition, failed to get "+
-				"timestamp message from %s messageID %v: %s", sender,
-				fm.Timestamp, err)
-		}
-
-		//Handle the message ID
+
+		// Handle the message ID
 		messageID := p.session.Conversations().Get(sender).
 			ProcessReceivedMessageID(fm.GetID())
 
-		//Return the
 		return p.session.Partition().AddFirst(sender, fm.GetType(),
-			messageID, fm.GetPart(), fm.GetNumParts(), timestamp,
+			messageID, fm.GetPart(), fm.GetNumParts(), fm.GetTimestamp(),
 			fm.GetSizedContents(), relationshipFingerprint)
-		//If it is a subsiquent message part, handle it as so
 	} else {
-		mp := MessagePartFromBytes(contents)
+		// If it is a subsequent message part, handle it as so
+		mp := messagePartFromBytes(contents)
 		messageID := p.session.Conversations().Get(sender).
 			ProcessReceivedMessageID(mp.GetID())
 
diff --git a/network/message/parse/partition_test.go b/network/message/parse/partition_test.go
index 933db1a01d4e95605d44d7cf5f5dce4429f2a9b5..9351a1e77b7e80dfc74938fefe01203dd4f0b705 100644
--- a/network/message/parse/partition_test.go
+++ b/network/message/parse/partition_test.go
@@ -32,28 +32,28 @@ func TestNewPartitioner(t *testing.T) {
 			4096, p.baseMessageSize)
 	}
 
-	if p.deltaFirstPart != 20 {
+	if p.deltaFirstPart != firstHeaderLen-headerLen {
 		t.Errorf("deltaFirstPart content mismatch"+
 			"\n\texpected: %v\n\treceived: %v",
-			20, p.deltaFirstPart)
+			firstHeaderLen-headerLen, p.deltaFirstPart)
 	}
 
-	if p.firstContentsSize != 4069 {
+	if p.firstContentsSize != 4096-firstHeaderLen {
 		t.Errorf("firstContentsSize content mismatch"+
 			"\n\texpected: %v\n\treceived: %v",
-			4069, p.firstContentsSize)
+			4096-firstHeaderLen, p.firstContentsSize)
 	}
 
-	if p.maxSize != 1042675 {
+	if p.maxSize != (4096-firstHeaderLen)+(MaxMessageParts-1)*(4096-headerLen) {
 		t.Errorf("maxSize content mismatch"+
 			"\n\texpected: %v\n\treceived: %v",
-			1042675, p.maxSize)
+			(4096-firstHeaderLen)+(MaxMessageParts-1)*(4096-headerLen), p.maxSize)
 	}
 
-	if p.partContentsSize != 4089 {
+	if p.partContentsSize != 4088 {
 		t.Errorf("partContentsSize content mismatch"+
 			"\n\texpected: %v\n\treceived: %v",
-			4089, p.partContentsSize)
+			4088, p.partContentsSize)
 	}
 
 	if p.session != storeSession {
diff --git a/network/message/sendCmix.go b/network/message/sendCmix.go
index 1b4f0e109ad3ea67078778c651856d299d2eb68b..8f55fcf56305a239a985bf5834a398b4b3d5ebf1 100644
--- a/network/message/sendCmix.go
+++ b/network/message/sendCmix.go
@@ -34,13 +34,13 @@ type sendCmixCommsInterface interface {
 }
 
 // 1.5 seconds
-const sendTimeBuffer = 1500 * time.Millisecond
+const sendTimeBuffer = 2500 * time.Millisecond
 
 // WARNING: Potentially Unsafe
 // Public manager function to send a message over CMIX
 func (m *Manager) SendCMIX(sender *gateway.Sender, msg format.Message, recipient *id.ID, param params.CMIX) (id.Round, ephemeral.Id, error) {
 	msgCopy := msg.Copy()
-	return sendCmixHelper(sender, msgCopy, recipient, param, m.Instance, m.Session, m.nodeRegistration, m.Rng, m.TransmissionID, m.Comms)
+	return sendCmixHelper(sender, msgCopy, recipient, m.param, param, m.Instance, m.Session, m.nodeRegistration, m.Rng, m.TransmissionID, m.Comms)
 }
 
 // Payloads send are not End to End encrypted, MetaData is NOT protected with
@@ -51,7 +51,7 @@ func (m *Manager) SendCMIX(sender *gateway.Sender, msg format.Message, recipient
 // If the message is successfully sent, the id of the round sent it is returned,
 // which can be registered with the network instance to get a callback on
 // its status
-func sendCmixHelper(sender *gateway.Sender, msg format.Message, recipient *id.ID, param params.CMIX, instance *network.Instance,
+func sendCmixHelper(sender *gateway.Sender, msg format.Message, recipient *id.ID, messageParams params.Messages, cmixParams params.CMIX, instance *network.Instance,
 	session *storage.Session, nodeRegistration chan network.NodeGateway, rng *fastRNG.StreamGenerator, senderId *id.ID,
 	comms sendCmixCommsInterface) (id.Round, ephemeral.Id, error) {
 
@@ -61,13 +61,13 @@ func sendCmixHelper(sender *gateway.Sender, msg format.Message, recipient *id.ID
 	jww.INFO.Printf("Looking for round to send cMix message to %s "+
 		"(msgDigest: %s)", recipient, msg.Digest())
 
-	for numRoundTries := uint(0); numRoundTries < param.RoundTries; numRoundTries++ {
+	for numRoundTries := uint(0); numRoundTries < cmixParams.RoundTries; numRoundTries++ {
 		elapsed := netTime.Now().Sub(timeStart)
 
-		if elapsed > param.Timeout {
+		if elapsed > cmixParams.Timeout {
 			jww.INFO.Printf("No rounds to send to %s (msgDigest: %s) "+
 				"were found before timeout %s", recipient, msg.Digest(),
-				param.Timeout)
+				cmixParams.Timeout)
 			return 0, ephemeral.Id{}, errors.New("Sending cmix message timed out")
 		}
 		if numRoundTries > 0 {
@@ -76,7 +76,7 @@ func sendCmixHelper(sender *gateway.Sender, msg format.Message, recipient *id.ID
 				msg.Digest())
 		}
 
-		remainingTime := param.Timeout - elapsed
+		remainingTime := cmixParams.Timeout - elapsed
 		//find the best round to send to, excluding attempted rounds
 		bestRound, _ := instance.GetWaitingRounds().GetUpcomingRealtime(remainingTime, attempted, sendTimeBuffer)
 		if bestRound == nil {
@@ -128,7 +128,7 @@ func sendCmixHelper(sender *gateway.Sender, msg format.Message, recipient *id.ID
 				"(msgDigest: %s) due to missing relationships with nodes: %s",
 				bestRound.ID, recipient, msg.Digest(), missingKeys)
 			go handleMissingNodeKeys(instance, nodeRegistration, missingKeys)
-			time.Sleep(param.RetryDelay)
+			time.Sleep(cmixParams.RetryDelay)
 			continue
 		}
 
@@ -175,7 +175,7 @@ func sendCmixHelper(sender *gateway.Sender, msg format.Message, recipient *id.ID
 			encMsg.Digest(), firstGateway.String())
 
 		// Send the payload
-		result, err := sender.SendToSpecific(firstGateway, func(host *connect.Host, target *id.ID) (interface{}, bool, error) {
+		sendFunc := func(host *connect.Host, target *id.ID) (interface{}, bool, error) {
 			wrappedMsg.Target = target.Marshal()
 			result, err := comms.SendPutMessage(host, wrappedMsg)
 			if err != nil {
@@ -203,7 +203,13 @@ func sendCmixHelper(sender *gateway.Sender, msg format.Message, recipient *id.ID
 				}
 			}
 			return result, false, err
-		})
+		}
+		var result interface{}
+		if messageParams.ProxySending {
+			result, err = sender.SendToSpecific(firstGateway, sendFunc)
+		} else {
+			result, err = sender.SendToSpecific(firstGateway, sendFunc)
+		}
 
 		//if the comm errors or the message fails to send, continue retrying.
 		//return if it sends properly
@@ -217,7 +223,7 @@ func sendCmixHelper(sender *gateway.Sender, msg format.Message, recipient *id.ID
 		gwSlotResp := result.(*pb.GatewaySlotResponse)
 		if gwSlotResp.Accepted {
 			jww.INFO.Printf("Successfully sent to EphID %v (source: %s) "+
-				"in round %d", ephID.Int64(), recipient, bestRound.ID)
+				"in round %d (msgDigest: %s)", ephID.Int64(), recipient, bestRound.ID, msg.Digest())
 			return id.Round(bestRound.ID), ephID, nil
 		} else {
 			jww.FATAL.Panicf("Gateway %s returned no error, but failed "+
diff --git a/network/message/sendCmix_test.go b/network/message/sendCmix_test.go
index 04da108426dda151bec4777338fe4a0036366832..f3182a8a2407c4f29c1c615160a28fd793ab4ee6 100644
--- a/network/message/sendCmix_test.go
+++ b/network/message/sendCmix_test.go
@@ -107,7 +107,7 @@ func Test_attemptSendCmix(t *testing.T) {
 		AddressSpaceSize:           4,
 	}
 
-	if err = testutils.SignRoundInfo(ri, t); err != nil {
+	if err = testutils.SignRoundInfoRsa(ri, t); err != nil {
 		t.Errorf("Failed to sign mock round info: %v", err)
 	}
 
@@ -115,7 +115,7 @@ func Test_attemptSendCmix(t *testing.T) {
 	if err != nil {
 		t.Errorf("Failed to load a key for testing: %v", err)
 	}
-	rnd := ds.NewRound(ri, pubKey)
+	rnd := ds.NewRound(ri, pubKey, nil)
 	inst.GetWaitingRounds().Insert(rnd)
 	i := internal.Internal{
 		Session:          sess1,
@@ -143,7 +143,7 @@ func Test_attemptSendCmix(t *testing.T) {
 	msgCmix := format.NewMessage(m.Session.Cmix().GetGroup().GetP().ByteLen())
 	msgCmix.SetContents([]byte("test"))
 	e2e.SetUnencrypted(msgCmix, m.Session.User().GetCryptographicIdentity().GetTransmissionID())
-	_, _, err = sendCmixHelper(sender, msgCmix, sess2.GetUser().ReceptionID, params.GetDefaultCMIX(),
+	_, _, err = sendCmixHelper(sender, msgCmix, sess2.GetUser().ReceptionID, params.GetDefaultMessage(), params.GetDefaultCMIX(),
 		m.Instance, m.Session, m.nodeRegistration, m.Rng,
 		m.TransmissionID, &MockSendCMIXComms{t: t})
 	if err != nil {
diff --git a/network/message/sendE2E.go b/network/message/sendE2E.go
index 16c14701d47ead025dae9758fa4697ce6c5ea007..b09e96c4a19598e7724ccf0bd5781ff60745b3d1 100644
--- a/network/message/sendE2E.go
+++ b/network/message/sendE2E.go
@@ -114,7 +114,7 @@ func (m *Manager) SendE2E(msg message.Send, param params.E2E) ([]id.Round, e2e.M
 		return nil, e2e.MessageID{}, errors.Errorf("Failed to E2E send %v/%v sub payloads:"+
 			" %s", numFail, len(partitions), errRtn)
 	} else {
-		jww.INFO.Printf("Sucesfully E2E sent %d/%d to %s",
+		jww.INFO.Printf("Successfully E2E sent %d/%d to %s",
 			len(partitions)-numFail, len(partitions), msg.Recipient)
 	}
 
diff --git a/network/message/sendUnsafe.go b/network/message/sendUnsafe.go
index df7f05cb8df4ba368f3a3a19368dcb13214f7d49..19f7d5d5ce0bfe6dd14df77b76f0a21c824b2404 100644
--- a/network/message/sendUnsafe.go
+++ b/network/message/sendUnsafe.go
@@ -82,7 +82,7 @@ func (m *Manager) SendUnsafe(msg message.Send, param params.Unsafe) ([]id.Round,
 		return nil, errors.Errorf("Failed to send %v/%v sub payloads:"+
 			" %s", numFail, len(partitions), errRtn)
 	} else {
-		jww.INFO.Printf("Sucesfully Unsafe sent %d/%d to %s",
+		jww.INFO.Printf("Successfully Unsafe sent %d/%d to %s",
 			len(partitions)-numFail, len(partitions), msg.Recipient)
 	}
 
diff --git a/network/node/register.go b/network/node/register.go
index c89d2dd55371bef074a3d417f5ca05ae66d4e550..82ab2cc3d937245adbc63812d6e875bc63657845 100644
--- a/network/node/register.go
+++ b/network/node/register.go
@@ -59,6 +59,8 @@ func registerNodes(sender *gateway.Sender, session *storage.Session, rngGen *fas
 	stop *stoppable.Single, c chan network.NodeGateway) {
 	u := session.User()
 	regSignature := u.GetTransmissionRegistrationValidationSignature()
+	// Timestamp in which user has registered with permissioning
+	regTimestamp := u.GetRegistrationTimestamp().UnixNano()
 	uci := u.GetCryptographicIdentity()
 	cmix := session.Cmix()
 
@@ -71,7 +73,7 @@ func registerNodes(sender *gateway.Sender, session *storage.Session, rngGen *fas
 			t.Stop()
 			return
 		case gw := <-c:
-			err := registerWithNode(sender, comms, gw, regSignature, uci, cmix, rng)
+			err := registerWithNode(sender, comms, gw, regSignature, regTimestamp, uci, cmix, rng)
 			if err != nil {
 				jww.ERROR.Printf("Failed to register node: %+v", err)
 			}
@@ -82,8 +84,10 @@ func registerNodes(sender *gateway.Sender, session *storage.Session, rngGen *fas
 
 //registerWithNode serves as a helper for RegisterWithNodes
 // It registers a user with a specific in the client's ndf.
-func registerWithNode(sender *gateway.Sender, comms RegisterNodeCommsInterface, ngw network.NodeGateway, regSig []byte,
-	uci *user.CryptographicIdentity, store *cmix.Store, rng csprng.Source) error {
+func registerWithNode(sender *gateway.Sender, comms RegisterNodeCommsInterface, ngw network.NodeGateway,
+	regSig []byte, registrationTimestampNano int64, uci *user.CryptographicIdentity,
+	store *cmix.Store, rng csprng.Source) error {
+
 	nodeID, err := ngw.Node.GetNodeId()
 	if err != nil {
 		jww.ERROR.Println("registerWithNode() failed to decode nodeId")
@@ -118,7 +122,7 @@ func registerWithNode(sender *gateway.Sender, comms RegisterNodeCommsInterface,
 		// keys
 		transmissionHash, _ := hash.NewCMixHash()
 
-		nonce, dhPub, err := requestNonce(sender, comms, gatewayID, regSig, uci, store, rng)
+		nonce, dhPub, err := requestNonce(sender, comms, gatewayID, regSig, registrationTimestampNano, uci, store, rng)
 		if err != nil {
 			return errors.Errorf("Failed to request nonce: %+v", err)
 		}
@@ -145,8 +149,10 @@ func registerWithNode(sender *gateway.Sender, comms RegisterNodeCommsInterface,
 	return nil
 }
 
-func requestNonce(sender *gateway.Sender, comms RegisterNodeCommsInterface, gwId *id.ID, regHash []byte,
-	uci *user.CryptographicIdentity, store *cmix.Store, rng csprng.Source) ([]byte, []byte, error) {
+func requestNonce(sender *gateway.Sender, comms RegisterNodeCommsInterface, gwId *id.ID,
+	regSig []byte, registrationTimestampNano int64, uci *user.CryptographicIdentity,
+	store *cmix.Store, rng csprng.Source) ([]byte, []byte, error) {
+
 	dhPub := store.GetDHPublicKey().Bytes()
 	opts := rsa.NewDefaultOptions()
 	opts.Hash = hash.CMixHash
@@ -170,13 +176,15 @@ func requestNonce(sender *gateway.Sender, comms RegisterNodeCommsInterface, gwId
 				Salt:            uci.GetTransmissionSalt(),
 				ClientRSAPubKey: string(rsa.CreatePublicKeyPem(uci.GetTransmissionRSA().GetPublic())),
 				ClientSignedByServer: &messages.RSASignature{
-					Signature: regHash,
+					Signature: regSig,
 				},
 				ClientDHPubKey: dhPub,
 				RequestSignature: &messages.RSASignature{
 					Signature: clientSig,
 				},
 				Target: gwId.Marshal(),
+				// Timestamp in which user has registered with permissioning
+				TimeStamp: registrationTimestampNano,
 			})
 		if err != nil {
 			errMsg := fmt.Sprintf("Register: Failed requesting nonce from gateway: %+v", err)
diff --git a/permissioning/permissioning_test.go b/permissioning/permissioning_test.go
index 7f691f3a419f5a43109206da5a802b3bb2029be3..dc3e73c2e73a1872a812fb54f7ab374c8d37cf85 100644
--- a/permissioning/permissioning_test.go
+++ b/permissioning/permissioning_test.go
@@ -22,7 +22,9 @@ func TestInit(t *testing.T) {
 		t.Fatal(err)
 	}
 	def := &ndf.NetworkDefinition{
-		Registration: ndf.Registration{},
+		Registration: ndf.Registration{
+			EllipticPubKey: "MqaJJ3GjFisNRM6LRedRnooi14gepMaQxyWctXVU",
+		},
 	}
 	reg, err := Init(comms, def)
 	if err != nil {
diff --git a/permissioning/register.go b/permissioning/register.go
index 1a64e54798560b270ab0d62267f7b2704a2c8ae1..e332152573c112c5e7cf5f32608f6aa3f2a8c60b 100644
--- a/permissioning/register.go
+++ b/permissioning/register.go
@@ -14,7 +14,8 @@ import (
 	"gitlab.com/xx_network/crypto/signature/rsa"
 )
 
-func (perm *Permissioning) Register(transmissionPublicKey, receptionPublicKey *rsa.PublicKey, registrationCode string) ([]byte, []byte, error) {
+func (perm *Permissioning) Register(transmissionPublicKey, receptionPublicKey *rsa.PublicKey,
+	registrationCode string) ([]byte, []byte, int64, error) {
 	return register(perm.comms, perm.host, transmissionPublicKey, receptionPublicKey, registrationCode)
 }
 
@@ -26,7 +27,7 @@ type registrationMessageSender interface {
 //register registers the user with optional registration code
 // Returns an error if registration fails.
 func register(comms registrationMessageSender, host *connect.Host,
-	transmissionPublicKey, receptionPublicKey *rsa.PublicKey, registrationCode string) ([]byte, []byte, error) {
+	transmissionPublicKey, receptionPublicKey *rsa.PublicKey, registrationCode string) ([]byte, []byte, int64, error) {
 
 	response, err := comms.
 		SendRegistrationMessage(host,
@@ -37,10 +38,12 @@ func register(comms registrationMessageSender, host *connect.Host,
 			})
 	if err != nil {
 		err = errors.Wrap(err, "sendRegistrationMessage: Unable to contact Identity Server!")
-		return nil, nil, err
+		return nil, nil, 0, err
 	}
 	if response.Error != "" {
-		return nil, nil, errors.Errorf("sendRegistrationMessage: error handling message: %s", response.Error)
+		return nil, nil, 0, errors.Errorf("sendRegistrationMessage: error handling message: %s", response.Error)
 	}
-	return response.ClientSignedByServer.Signature, response.ClientReceptionSignedByServer.Signature, nil
+
+	return response.ClientSignedByServer.Signature, 
+	response.ClientReceptionSignedByServer.Signature, response.Timestamp, nil
 }
diff --git a/permissioning/register_test.go b/permissioning/register_test.go
index 52dcb46e948b42fdd54a8f45ca6e2f751bf8a85e..02dd58b41c77ebe7a89f8cead15dc9b144b6c7dc 100644
--- a/permissioning/register_test.go
+++ b/permissioning/register_test.go
@@ -68,7 +68,7 @@ func TestRegisterWithPermissioning(t *testing.T) {
 	}
 
 	regCode := "flooble doodle"
-	sig1, sig2, err := register(&sender, sender.getHost, key.GetPublic(), key.GetPublic(), regCode)
+	sig1, sig2, _, err := register(&sender, sender.getHost, key.GetPublic(), key.GetPublic(), regCode)
 	if err != nil {
 		t.Error(err)
 	}
@@ -105,7 +105,7 @@ func TestRegisterWithPermissioning_ResponseErr(t *testing.T) {
 	var sender MockRegistrationSender
 	sender.succeedGetHost = true
 	sender.errInReply = "failure occurred on permissioning"
-	_, _, err = register(&sender, nil, key.GetPublic(), key.GetPublic(), "")
+	_, _, _, err = register(&sender, nil, key.GetPublic(), key.GetPublic(), "")
 	if err == nil {
 		t.Error("no error if registration fails on permissioning")
 	}
@@ -122,7 +122,7 @@ func TestRegisterWithPermissioning_ConnectionErr(t *testing.T) {
 	var sender MockRegistrationSender
 	sender.succeedGetHost = true
 	sender.errSendRegistration = errors.New("connection problem")
-	_, _, err = register(&sender, nil, key.GetPublic(), key.GetPublic(), "")
+	_, _, _, err = register(&sender, nil, key.GetPublic(), key.GetPublic(), "")
 	if err == nil {
 		t.Error("no error if e.g. context deadline exceeded")
 	}
diff --git a/stoppable/single.go b/stoppable/single.go
index 8821db88eb4934a06db4f96484ef700b2c6beeff..2e8fa78a2a1c3f4f12752f045cb93c541da8412b 100644
--- a/stoppable/single.go
+++ b/stoppable/single.go
@@ -52,7 +52,6 @@ func (s *Single) Name() string {
 func (s *Single) Close(timeout time.Duration) error {
 	var err error
 	s.once.Do(func() {
-		atomic.StoreUint32(&s.running, 0)
 		timer := time.NewTimer(timeout)
 		select {
 		case <-timer.C:
@@ -61,6 +60,7 @@ func (s *Single) Close(timeout time.Duration) error {
 			err = errors.Errorf("%s failed to close", s.name)
 		case s.quit <- struct{}{}:
 		}
+		atomic.StoreUint32(&s.running, 0)
 	})
 	return err
 }
diff --git a/storage/partition/store.go b/storage/partition/store.go
index de601693828ccd159dbdaefad11139942df2c15c..52f7f330f06aa4887c64d991f3f384714073b3cb 100644
--- a/storage/partition/store.go
+++ b/storage/partition/store.go
@@ -8,11 +8,11 @@
 package partition
 
 import (
-	"crypto/md5"
 	"encoding/binary"
 	"gitlab.com/elixxir/client/interfaces/message"
 	"gitlab.com/elixxir/client/storage/versioned"
 	"gitlab.com/xx_network/primitives/id"
+	"golang.org/x/crypto/blake2b"
 	"sync"
 	"time"
 )
@@ -69,7 +69,15 @@ func (s *Store) load(partner *id.ID, messageID uint64) *multiPartMessage {
 }
 
 func getMultiPartID(partner *id.ID, messageID uint64) multiPartID {
+	h, _ := blake2b.New256(nil)
+
+	h.Write(partner.Bytes())
 	b := make([]byte, 8)
 	binary.BigEndian.PutUint64(b, messageID)
-	return md5.Sum(append(partner[:], b...))
+	h.Write(b)
+
+	var mpID multiPartID
+	copy(mpID[:], h.Sum(nil))
+
+	return mpID
 }
diff --git a/storage/reception/store.go b/storage/reception/store.go
index bd78f0b7682d3c06c2b47211f518729cb63cbfc1..08498aa5c0aa856727fe60c989419f2aeb18616a 100644
--- a/storage/reception/store.go
+++ b/storage/reception/store.go
@@ -2,7 +2,6 @@ package reception
 
 import (
 	"bytes"
-	"crypto/md5"
 	"encoding/json"
 	"github.com/pkg/errors"
 	jww "github.com/spf13/jwalterweatherman"
@@ -11,6 +10,7 @@ import (
 	"gitlab.com/xx_network/primitives/id"
 	"gitlab.com/xx_network/primitives/id/ephemeral"
 	"gitlab.com/xx_network/primitives/netTime"
+	"golang.org/x/crypto/blake2b"
 	"io"
 	"strconv"
 	"sync"
@@ -46,12 +46,11 @@ type storedReference struct {
 type idHash [16]byte
 
 func makeIdHash(ephID ephemeral.Id, source *id.ID) idHash {
-	h := md5.New()
+	h, _ := blake2b.New256(nil)
 	h.Write(ephID[:])
 	h.Write(source.Bytes())
-	idHashBytes := h.Sum(nil)
 	idH := idHash{}
-	copy(idH[:], idHashBytes)
+	copy(idH[:], h.Sum(nil))
 	return idH
 }
 
diff --git a/storage/session.go b/storage/session.go
index d4fc432b32d86b651cd3dfb9aa350c0b785a4b2d..0277166a98b9dd51f06509efb6f35e514aae249d 100644
--- a/storage/session.go
+++ b/storage/session.go
@@ -13,6 +13,7 @@ import (
 	"gitlab.com/elixxir/client/storage/rounds"
 	"sync"
 	"testing"
+	"time"
 
 	"github.com/pkg/errors"
 	jww "github.com/spf13/jwalterweatherman"
@@ -335,6 +336,14 @@ func InitTestingSession(i interface{}) *Session {
 	}
 	u.SetTransmissionRegistrationValidationSignature([]byte("sig"))
 	u.SetReceptionRegistrationValidationSignature([]byte("sig"))
+	testTime, err := time.Parse(time.RFC3339,
+		"2012-12-21T22:08:41+00:00")
+	if err != nil {
+		jww.FATAL.Panicf("Could not parse precanned time: %v", err.Error())
+	}
+	u.SetRegistrationTimestamp(testTime.UnixNano())
+
+
 	s.user = u
 	cmixGrp := cyclic.NewGroup(
 		large.NewIntFromString("9DB6FB5951B66BB6FE1E140F1D2CE5502374161FD6538DF1648218642F0B5C48"+
diff --git a/storage/user.go b/storage/user.go
index df1d9055e3490a3290d9ad378b3857bc16ca7cc4..a236f22d35e618d77c75277c9ece5999712832a3 100644
--- a/storage/user.go
+++ b/storage/user.go
@@ -18,6 +18,7 @@ func (s *Session) GetUser() user.User {
 		TransmissionSalt: copySlice(ci.GetTransmissionSalt()),
 		TransmissionRSA:  ci.GetReceptionRSA(),
 		ReceptionID:      ci.GetReceptionID().DeepCopy(),
+		RegistrationTimestamp: s.user.GetRegistrationTimestamp(),
 		ReceptionSalt:    copySlice(ci.GetReceptionSalt()),
 		ReceptionRSA:     ci.GetReceptionRSA(),
 		Precanned:        ci.IsPrecanned(),
diff --git a/storage/user/regValidationSig.go b/storage/user/registation.go
similarity index 70%
rename from storage/user/regValidationSig.go
rename to storage/user/registation.go
index 7440500fc680e2aee821ac761f47c8d9b201f40a..4da19b4cd0faf8e83fe22ad2e177afb8d8109897 100644
--- a/storage/user/regValidationSig.go
+++ b/storage/user/registation.go
@@ -8,14 +8,18 @@
 package user
 
 import (
+	"encoding/binary"
 	jww "github.com/spf13/jwalterweatherman"
 	"gitlab.com/elixxir/client/storage/versioned"
 	"gitlab.com/xx_network/primitives/netTime"
+	"time"
 )
 
 const currentRegValidationSigVersion = 0
+const registrationTimestampVersion = 0
 const transmissionRegValidationSigKey = "transmissionRegistrationValidationSignature"
 const receptionRegValidationSigKey = "receptionRegistrationValidationSignature"
+const registrationTimestampKey = "registrationTimestamp"
 
 // Returns the transmission Identity Validation Signature stored in RAM. May return
 // nil of no signature is stored
@@ -33,6 +37,13 @@ func (u *User) GetReceptionRegistrationValidationSignature() []byte {
 	return u.receptionRegValidationSig
 }
 
+// Returns the registration timestamp stored in RAM as
+func (u *User) GetRegistrationTimestamp() time.Time {
+	u.rvsMux.RLock()
+	defer u.rvsMux.RUnlock()
+	return u.registrationTimestamp
+}
+
 // Loads the transmission Identity Validation Signature if it exists in the ekv
 func (u *User) loadTransmissionRegistrationValidationSignature() {
 	u.rvsMux.Lock()
@@ -55,6 +66,18 @@ func (u *User) loadReceptionRegistrationValidationSignature() {
 	u.rvsMux.Unlock()
 }
 
+// Loads the registration timestamp if it exists in the ekv
+func (u *User) loadRegistrationTimestamp() {
+	u.rvsMux.Lock()
+	obj, err := u.kv.Get(registrationTimestampKey,
+		registrationTimestampVersion)
+	if err == nil {
+		tsNano := binary.BigEndian.Uint64(obj.Data)
+		u.registrationTimestamp = time.Unix(0, int64(tsNano))
+	}
+	u.rvsMux.Unlock()
+}
+
 // Sets the Identity Validation Signature if it is not set and stores it in
 // the ekv
 func (u *User) SetTransmissionRegistrationValidationSignature(b []byte) {
@@ -108,3 +131,34 @@ func (u *User) SetReceptionRegistrationValidationSignature(b []byte) {
 
 	u.receptionRegValidationSig = b
 }
+
+// Sets the Registration Timestamp if it is not set and stores it in
+// the ekv
+func (u *User) SetRegistrationTimestamp(tsNano int64) {
+	u.rvsMux.Lock()
+	defer u.rvsMux.Unlock()
+
+	//check if the signature already exists
+	if !u.registrationTimestamp.IsZero() {
+		jww.FATAL.Panicf("cannot overwrite existing registration timestamp")
+	}
+
+	// Serialize the timestamp
+	tsBytes := make([]byte, 8)
+	binary.BigEndian.PutUint64(tsBytes, uint64(tsNano))
+
+	obj := &versioned.Object{
+		Version:   currentRegValidationSigVersion,
+		Timestamp: netTime.Now(),
+		Data:      tsBytes,
+	}
+
+	err := u.kv.Set(registrationTimestampKey,
+		registrationTimestampVersion, obj)
+	if err != nil {
+		jww.FATAL.Panicf("Failed to store the reception timestamp: %s", err)
+	}
+
+	u.registrationTimestamp = time.Unix(0, tsNano)
+
+}
diff --git a/storage/user/regValidationSig_test.go b/storage/user/registation_test.go
similarity index 64%
rename from storage/user/regValidationSig_test.go
rename to storage/user/registation_test.go
index 68a69f60c8a8dca24161a4ec8bc9721d096aa6a9..31c6d3d1ee67f4e81fddd4a5822a18d0ad4d7ccf 100644
--- a/storage/user/regValidationSig_test.go
+++ b/storage/user/registation_test.go
@@ -9,12 +9,14 @@ package user
 
 import (
 	"bytes"
+	"encoding/binary"
 	"gitlab.com/elixxir/client/storage/versioned"
 	"gitlab.com/elixxir/ekv"
 	"gitlab.com/xx_network/crypto/signature/rsa"
 	"gitlab.com/xx_network/primitives/id"
 	"gitlab.com/xx_network/primitives/netTime"
 	"testing"
+	"time"
 )
 
 // Test User GetRegistrationValidationSignature function
@@ -137,3 +139,88 @@ func TestUser_loadRegistrationValidationSignature(t *testing.T) {
 		t.Errorf("Expected sig did not match loaded.  Expected: %+v, Received: %+v", sig, u.receptionRegValidationSig)
 	}
 }
+
+// Test User's getter/setter functions for TimeStamp
+func TestUser_GetRegistrationTimestamp(t *testing.T) {
+	kv := versioned.NewKV(make(ekv.Memstore))
+	uid := id.NewIdFromString("test", id.User, t)
+	salt := []byte("salt")
+	u, err := NewUser(kv, uid, uid, salt, salt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false)
+	if err != nil || u == nil {
+		t.Errorf("Failed to create new user: %+v", err)
+	}
+
+	testTime, err := time.Parse(time.RFC3339,
+		"2012-12-21T22:08:41+00:00")
+	if err != nil {
+		t.Fatalf("Could not parse precanned time: %v", err.Error())
+	}
+
+	// Test that User has been modified for timestamp
+	u.SetRegistrationTimestamp(testTime.UnixNano())
+	if !testTime.Equal(u.registrationTimestamp) {
+		t.Errorf("SetRegistrationTimestamp did not set user's timestamp value."+
+			"\n\tExpected: %s\n\tReceieved: %s", testTime.String(), u.registrationTimestamp)
+	}
+
+	// Pull timestamp from kv
+	obj, err := u.kv.Get(registrationTimestampKey, registrationTimestampVersion)
+	if err != nil {
+		t.Errorf("Failed to get reg vaildation signature key: %+v", err)
+	}
+
+	// Check if kv data is expected
+	unixNano := binary.BigEndian.Uint64(obj.Data)
+	if testTime.UnixNano() != int64(unixNano) {
+		t.Errorf("Timestamp pulled from kv was not expected."+
+			"\n\tExpected: %d\n\tReceieved: %d", testTime.UnixNano(), unixNano)
+	}
+
+	if testTime.UnixNano() != u.GetRegistrationTimestamp().UnixNano() {
+		t.Errorf("Timestamp from GetRegistrationTimestampNano was not expected."+
+			"\n\tExpected: %d\n\tReceieved: %d", testTime.UnixNano(), u.GetRegistrationTimestamp().UnixNano())
+	}
+
+	if !testTime.Equal(u.GetRegistrationTimestamp()) {
+		t.Errorf("Timestamp from GetRegistrationTimestamp was not expected."+
+			"\n\tExpected: %s\n\tReceieved: %s", testTime, u.GetRegistrationTimestamp())
+
+	}
+
+}
+
+// Test loading registrationTimestamp from the KV store
+func TestUser_loadRegistrationTimestamp(t *testing.T) {
+	kv := versioned.NewKV(make(ekv.Memstore))
+	uid := id.NewIdFromString("test", id.User, t)
+	salt := []byte("salt")
+	u, err := NewUser(kv, uid, uid, salt, salt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false)
+	if err != nil || u == nil {
+		t.Errorf("Failed to create new user: %+v", err)
+	}
+
+	testTime, err := time.Parse(time.RFC3339,
+		"2012-12-21T22:08:41+00:00")
+	if err != nil {
+		t.Fatalf("Could not parse precanned time: %v", err.Error())
+	}
+
+	data := make([]byte, 8)
+	binary.BigEndian.PutUint64(data, uint64(testTime.UnixNano()))
+	vo := &versioned.Object{
+		Version:   currentRegValidationSigVersion,
+		Timestamp: netTime.Now(),
+		Data:      data,
+	}
+	err = kv.Set(registrationTimestampKey,
+		registrationTimestampVersion, vo)
+	if err != nil {
+		t.Errorf("Failed to set reg validation sig key in kv store: %+v", err)
+	}
+
+	u.loadRegistrationTimestamp()
+	if !testTime.Equal(u.registrationTimestamp) {
+		t.Errorf("SetRegistrationTimestamp did not set user's timestamp value."+
+			"\n\tExpected: %s\n\tReceieved: %s", testTime.String(), u.registrationTimestamp)
+	}
+}
diff --git a/storage/user/user.go b/storage/user/user.go
index a55830ff131620f7f9f499b2a6932d616675ccda..c1779524245cd729df731243837d772ddf7b2c03 100644
--- a/storage/user/user.go
+++ b/storage/user/user.go
@@ -13,6 +13,7 @@ import (
 	"gitlab.com/xx_network/crypto/signature/rsa"
 	"gitlab.com/xx_network/primitives/id"
 	"sync"
+	"time"
 )
 
 type User struct {
@@ -20,7 +21,9 @@ type User struct {
 
 	transmissionRegValidationSig []byte
 	receptionRegValidationSig    []byte
-	rvsMux                       sync.RWMutex
+	// Time in which user registered with the network
+	registrationTimestamp time.Time
+	rvsMux                sync.RWMutex
 
 	username    string
 	usernameMux sync.RWMutex
@@ -48,6 +51,7 @@ func LoadUser(kv *versioned.KV) (*User, error) {
 	u.loadTransmissionRegistrationValidationSignature()
 	u.loadReceptionRegistrationValidationSignature()
 	u.loadUsername()
+	u.loadRegistrationTimestamp()
 
 	return u, nil
 }
diff --git a/storage/utility/blockStore.go b/storage/utility/blockStore.go
index a405e9b966175b77f8a9803e2efbe72bf2cf27af..b29dcd12d56037d6e7d0622b1fbc47f8faea62b9 100644
--- a/storage/utility/blockStore.go
+++ b/storage/utility/blockStore.go
@@ -21,6 +21,7 @@ const (
 const (
 	bsBuffLengthErr   = "length of buffer %d != %d expected"
 	bsKvSaveErr       = "failed to save blockStore to KV: %+v"
+	bsKvInitSaveErr   = "failed to save initial block: %+v"
 	bsKvLoadErr       = "failed to get BlockStore from storage: %+v"
 	bsKvUnmarshalErr  = "failed to unmarshal BlockStore loaded from storage: %+v"
 	bJsonMarshalErr   = "failed to JSON marshal block %d: %+v"
@@ -218,6 +219,12 @@ func (bs *BlockStore) save() error {
 		return errors.Errorf(bsKvSaveErr, err)
 	}
 
+	// Save initial block
+	err = bs.saveBlock()
+	if err != nil {
+		return errors.Errorf(bsKvInitSaveErr, err)
+	}
+
 	return nil
 }
 
diff --git a/storage/utility/cmixMessageBuffer.go b/storage/utility/cmixMessageBuffer.go
index 6091c65bc59ee0836384d4a475a15f8c8f7a940e..8c67658932ab64e75d91e2272f3b94c9c90f6314 100644
--- a/storage/utility/cmixMessageBuffer.go
+++ b/storage/utility/cmixMessageBuffer.go
@@ -8,7 +8,6 @@
 package utility
 
 import (
-	"crypto/md5"
 	"encoding/json"
 	"github.com/pkg/errors"
 	jww "github.com/spf13/jwalterweatherman"
@@ -16,6 +15,7 @@ import (
 	"gitlab.com/elixxir/primitives/format"
 	"gitlab.com/xx_network/primitives/id"
 	"gitlab.com/xx_network/primitives/netTime"
+	"golang.org/x/crypto/blake2b"
 )
 
 const currentCmixMessageVersion = 0
@@ -80,8 +80,14 @@ func (cmh *cmixMessageHandler) DeleteMessage(kv *versioned.KV, key string) error
 
 // HashMessage generates a hash of the message.
 func (cmh *cmixMessageHandler) HashMessage(m interface{}) MessageHash {
-	sm := m.(storedMessage)
-	return md5.Sum(sm.Marshal())
+	h, _ := blake2b.New256(nil)
+
+	h.Write(m.(storedMessage).Marshal())
+
+	var messageHash MessageHash
+	copy(messageHash[:], h.Sum(nil))
+
+	return messageHash
 }
 
 // CmixMessageBuffer wraps the message buffer to store and load raw cmix
diff --git a/storage/utility/e2eMessageBuffer.go b/storage/utility/e2eMessageBuffer.go
index b8de8f65d3219f662df87680d174aec47743b97f..259c6407a2c08c45b4f2e486182964031669b98c 100644
--- a/storage/utility/e2eMessageBuffer.go
+++ b/storage/utility/e2eMessageBuffer.go
@@ -8,7 +8,6 @@
 package utility
 
 import (
-	"crypto/md5"
 	"encoding/binary"
 	"encoding/json"
 	jww "github.com/spf13/jwalterweatherman"
@@ -17,6 +16,7 @@ import (
 	"gitlab.com/elixxir/client/storage/versioned"
 	"gitlab.com/xx_network/primitives/id"
 	"gitlab.com/xx_network/primitives/netTime"
+	"golang.org/x/crypto/blake2b"
 )
 
 const currentE2EMessageVersion = 0
@@ -80,17 +80,19 @@ func (emh *e2eMessageHandler) DeleteMessage(kv *versioned.KV, key string) error
 // Do not include the params in the hash so it is not needed to resubmit the
 // message into succeeded or failed
 func (emh *e2eMessageHandler) HashMessage(m interface{}) MessageHash {
-	msg := m.(e2eMessage)
-
-	var digest []byte
-	digest = append(digest, msg.Recipient...)
-	digest = append(digest, msg.Payload...)
+	h, _ := blake2b.New256(nil)
 
+	msg := m.(e2eMessage)
+	h.Write(msg.Recipient)
+	h.Write(msg.Payload)
 	mtBytes := make([]byte, 4)
 	binary.BigEndian.PutUint32(mtBytes, msg.MessageType)
-	digest = append(digest, mtBytes...)
+	h.Write(mtBytes)
+
+	var messageHash MessageHash
+	copy(messageHash[:], h.Sum(nil))
 
-	return md5.Sum(digest)
+	return messageHash
 }
 
 // E2eMessageBuffer wraps the message buffer to store and load raw e2eMessages.
diff --git a/storage/utility/messageBuffer_test.go b/storage/utility/messageBuffer_test.go
index fc4de8be8dd5573520d02c9a35fae07593bb6a90..5e30960f9ccc3ad7060a876b7924fd3f0d8f3016 100644
--- a/storage/utility/messageBuffer_test.go
+++ b/storage/utility/messageBuffer_test.go
@@ -9,11 +9,11 @@ package utility
 
 import (
 	"bytes"
-	"crypto/md5"
 	"encoding/json"
 	"gitlab.com/elixxir/client/storage/versioned"
 	"gitlab.com/elixxir/ekv"
 	"gitlab.com/xx_network/primitives/netTime"
+	"golang.org/x/crypto/blake2b"
 	"math/rand"
 	"os"
 	"reflect"
@@ -48,10 +48,14 @@ func (th *testHandler) DeleteMessage(kv *versioned.KV, key string) error {
 }
 
 func (th *testHandler) HashMessage(m interface{}) MessageHash {
-	mBytes := m.([]byte)
-	// Sum returns a array that is the exact same size as the MessageHash and Go
-	// apparently automatically casts it
-	return md5.Sum(mBytes)
+	h, _ := blake2b.New256(nil)
+
+	h.Write(m.([]byte))
+
+	var messageHash MessageHash
+	copy(messageHash[:], h.Sum(nil))
+
+	return messageHash
 }
 
 func newTestHandler() *testHandler {
@@ -343,7 +347,13 @@ func makeTestMessages(n int) ([][]byte, map[MessageHash]struct{}) {
 	for i := range msgs {
 		msgs[i] = make([]byte, 256)
 		prng.Read(msgs[i])
-		mh[md5.Sum(msgs[i])] = struct{}{}
+
+		h, _ := blake2b.New256(nil)
+		h.Write(msgs[i])
+		var messageHash MessageHash
+		copy(messageHash[:], h.Sum(nil))
+
+		mh[messageHash] = struct{}{}
 	}
 
 	return msgs, mh
diff --git a/storage/utility/meteredCmixMessageBuffer.go b/storage/utility/meteredCmixMessageBuffer.go
index 719faa3883ebf6d47e5abf86931c3e9e1b8e0143..dd5ade5a31a51469587c4dd8a32d67f07b9c515e 100644
--- a/storage/utility/meteredCmixMessageBuffer.go
+++ b/storage/utility/meteredCmixMessageBuffer.go
@@ -8,13 +8,13 @@
 package utility
 
 import (
-	"crypto/md5"
 	"encoding/json"
 	"github.com/pkg/errors"
 	jww "github.com/spf13/jwalterweatherman"
 	"gitlab.com/elixxir/client/storage/versioned"
 	"gitlab.com/elixxir/primitives/format"
 	"gitlab.com/xx_network/primitives/netTime"
+	"golang.org/x/crypto/blake2b"
 	"time"
 )
 
@@ -77,9 +77,14 @@ func (*meteredCmixMessageHandler) DeleteMessage(kv *versioned.KV, key string) er
 
 // HashMessage generates a hash of the message.
 func (*meteredCmixMessageHandler) HashMessage(m interface{}) MessageHash {
-	msg := m.(meteredCmixMessage)
+	h, _ := blake2b.New256(nil)
+
+	h.Write(m.(meteredCmixMessage).M)
+
+	var messageHash MessageHash
+	copy(messageHash[:], h.Sum(nil))
 
-	return md5.Sum(msg.M)
+	return messageHash
 }
 
 // CmixMessageBuffer wraps the message buffer to store and load raw cmix
diff --git a/ud/register.go b/ud/register.go
index 764b8a2b96ee03e75b3eba91e44a2f31f4590f3b..c2dd6a0adc1db8f9e61495c9b989309657f6d891 100644
--- a/ud/register.go
+++ b/ud/register.go
@@ -49,6 +49,7 @@ func (m *Manager) register(username string, comm registerUserComms) error {
 			Salt:     cryptoUser.GetReceptionSalt(),
 		},
 		UID: cryptoUser.GetReceptionID().Marshal(),
+		Timestamp: user.GetRegistrationTimestamp().UnixNano(),
 	}
 
 	// Sign the identity data and add to user registration message