diff --git a/api/send.go b/api/send.go
index 758f0f553b409b5baea58bd2ea023e21bf06e7aa..0ada32a74d256b47e2bb345d1157f04ce548a6eb 100644
--- a/api/send.go
+++ b/api/send.go
@@ -4,6 +4,7 @@ import (
 	jww "github.com/spf13/jwalterweatherman"
 	"gitlab.com/elixxir/client/interfaces/message"
 	"gitlab.com/elixxir/client/interfaces/params"
+	"gitlab.com/elixxir/crypto/e2e"
 	"gitlab.com/elixxir/primitives/format"
 	"gitlab.com/xx_network/primitives/id"
 )
@@ -13,7 +14,8 @@ import (
 // SendE2E sends an end-to-end payload to the provided recipient with
 // the provided msgType. Returns the list of rounds in which parts of
 // the message were sent or an error if it fails.
-func (c *Client) SendE2E(m message.Send, param params.E2E) ([]id.Round, error) {
+func (c *Client) SendE2E(m message.Send, param params.E2E) ([]id.Round,
+	e2e.MessageID, error) {
 	jww.INFO.Printf("SendE2E(%s, %d. %v)", m.Recipient,
 		m.MessageType, m.Payload)
 	return c.network.SendE2E(m, param)
diff --git a/go.mod b/go.mod
index a880cd60b6926158e127e13186990479a0d30aa7..144136f94e7be7d43485a72de706bd3c77fc9c36 100644
--- a/go.mod
+++ b/go.mod
@@ -14,7 +14,7 @@ require (
 	github.com/spf13/jwalterweatherman v1.1.0
 	github.com/spf13/viper v1.7.1
 	gitlab.com/elixxir/comms v0.0.0-20200924225440-76e02f95fb92
-	gitlab.com/elixxir/crypto v0.0.0-20201002151111-280700c6e774
+	gitlab.com/elixxir/crypto v0.0.0-20201002231238-e43c62b70517
 	gitlab.com/elixxir/ekv v0.1.3
 	gitlab.com/elixxir/primitives v0.0.0-20200915190719-f4586ec93f50
 	gitlab.com/xx_network/comms v0.0.0-20200924225518-0c867207b1e6
diff --git a/go.sum b/go.sum
index 78e7367fc2b229e1870cae6bcac38473466206f4..366777efc25d2c2a320e4266999425fe7d423b1d 100644
--- a/go.sum
+++ b/go.sum
@@ -326,6 +326,8 @@ gitlab.com/elixxir/crypto v0.0.0-20201001175928-ce7312789eb7 h1:bmi0wc0m9qq+5aEi
 gitlab.com/elixxir/crypto v0.0.0-20201001175928-ce7312789eb7/go.mod h1:1P3IMJ6i3L+5si0PiMvoo/qQXMsEhNVjn0yMUrm3eiA=
 gitlab.com/elixxir/crypto v0.0.0-20201002151111-280700c6e774 h1:Ph3OiDgRQJ5Ac9VnFiv/Dk4COw2+jUjGnF7Cal5Q5W4=
 gitlab.com/elixxir/crypto v0.0.0-20201002151111-280700c6e774/go.mod h1:1P3IMJ6i3L+5si0PiMvoo/qQXMsEhNVjn0yMUrm3eiA=
+gitlab.com/elixxir/crypto v0.0.0-20201002231238-e43c62b70517 h1:T0eBNlAmJ+MD03SXUlr1/Fk7OVXlJb5ZS2tB0Hay0Fk=
+gitlab.com/elixxir/crypto v0.0.0-20201002231238-e43c62b70517/go.mod h1:1P3IMJ6i3L+5si0PiMvoo/qQXMsEhNVjn0yMUrm3eiA=
 gitlab.com/elixxir/ekv v0.0.0-20200729182028-159355ea5842 h1:m1zDQ6UadpuMnV7nvnyR+DUXE3AisRnVjajTb1xZE4c=
 gitlab.com/elixxir/ekv v0.0.0-20200729182028-159355ea5842/go.mod h1:bXY0kgbV5BHYda4YY5/hiG5bjimGK+R3PYub5yM9C/s=
 gitlab.com/elixxir/ekv v0.1.1 h1:Em3rF8sv+tNbQGXbcpYzAS2blWRAP708JGhYlkN74Kg=
diff --git a/interfaces/message/receiveMessage.go b/interfaces/message/receiveMessage.go
index d562e0528b738cc219ccf270932fdf9a993716f6..e36a15c1eb072c13c50736d2c7f3336082291825 100644
--- a/interfaces/message/receiveMessage.go
+++ b/interfaces/message/receiveMessage.go
@@ -1,6 +1,7 @@
 package message
 
 import (
+	"gitlab.com/elixxir/crypto/e2e"
 	"gitlab.com/xx_network/primitives/id"
 	"time"
 )
@@ -11,4 +12,5 @@ type Receive struct {
 	Sender      *id.ID
 	Timestamp   time.Time
 	Encryption  EncryptionType
+	ID          e2e.MessageID
 }
diff --git a/interfaces/networkManager.go b/interfaces/networkManager.go
index e684cfdc9dc1415e8a9c1945c2ad63a77c391928..90fa41485906c7cb76495843077e2dda9118b549 100644
--- a/interfaces/networkManager.go
+++ b/interfaces/networkManager.go
@@ -5,12 +5,13 @@ import (
 	"gitlab.com/elixxir/client/interfaces/params"
 	"gitlab.com/elixxir/client/stoppable"
 	"gitlab.com/elixxir/comms/network"
+	"gitlab.com/elixxir/crypto/e2e"
 	"gitlab.com/elixxir/primitives/format"
 	"gitlab.com/xx_network/primitives/id"
 )
 
 type NetworkManager interface {
-	SendE2E(m message.Send, p params.E2E) ([]id.Round, error)
+	SendE2E(m message.Send, p params.E2E) ([]id.Round, e2e.MessageID, error)
 	SendUnsafe(m message.Send, p params.Unsafe) ([]id.Round, error)
 	SendCMIX(message format.Message, p params.CMIX) (id.Round, error)
 	GetInstance() *network.Instance
@@ -20,4 +21,4 @@ type NetworkManager interface {
 }
 
 //for use in key exchange which needs to be callable inside of network
-type SendE2E func(m message.Send, p params.E2E) ([]id.Round, error)
+type SendE2E func(m message.Send, p params.E2E) ([]id.Round, e2e.MessageID, error)
diff --git a/keyExchange/rekey.go b/keyExchange/rekey.go
index 342712fe85bf94a286dd27d37db28c1b9c2ff589..e214ac81731e41dbc5b2ce011a2a3ea7ab6b6a4f 100644
--- a/keyExchange/rekey.go
+++ b/keyExchange/rekey.go
@@ -98,7 +98,7 @@ func negotiate(instance *network.Instance, sendE2E interfaces.SendE2E,
 	e2eParams := params.GetDefaultE2E()
 	e2eParams.Type = params.KeyExchange
 
-	rounds, err := sendE2E(m, e2eParams)
+	rounds, _, err := sendE2E(m, e2eParams)
 	// If the send fails, returns the error so it can be handled. The caller
 	// should ensure the calling session is in a state where the Rekey will
 	// be triggered next time a key is used
diff --git a/keyExchange/trigger.go b/keyExchange/trigger.go
index 60fb18d2ea48a525619884ff3ec283a4481bf37a..ceaf85564338ca9dd475318627cca95119f9641e 100644
--- a/keyExchange/trigger.go
+++ b/keyExchange/trigger.go
@@ -115,7 +115,7 @@ func handleTrigger(sess *storage.Session, net interfaces.NetworkManager,
 	// send fails
 	sess.GetCriticalMessages().AddProcessing(m, e2eParams)
 
-	rounds, err := net.SendE2E(m, e2eParams)
+	rounds, _, err := net.SendE2E(m, e2eParams)
 
 	//Register the event for all rounds
 	sendResults := make(chan ds.EventReturn, len(rounds))
diff --git a/keyExchange/utils_test.go b/keyExchange/utils_test.go
index da439420b22bccbf6fdade6b3d77a71308e549ec..722bad806762d18ed927c85a4ebd646b066a5cff 100644
--- a/keyExchange/utils_test.go
+++ b/keyExchange/utils_test.go
@@ -13,6 +13,7 @@ import (
 	"gitlab.com/elixxir/comms/network"
 	"gitlab.com/elixxir/crypto/cyclic"
 	dh "gitlab.com/elixxir/crypto/diffieHellman"
+	cE2e "gitlab.com/elixxir/crypto/e2e"
 	"gitlab.com/elixxir/crypto/hash"
 	"gitlab.com/elixxir/crypto/large"
 	"gitlab.com/elixxir/primitives/format"
@@ -56,9 +57,10 @@ func (t *testNetworkManagerGeneric) CheckGarbledMessages() {
 	return
 }
 
-func (t *testNetworkManagerGeneric) SendE2E(m message.Send, p params.E2E) ([]id.Round, error) {
+func (t *testNetworkManagerGeneric) SendE2E(m message.Send, p params.E2E) (
+	[]id.Round, cE2e.MessageID, error) {
 	rounds := []id.Round{id.Round(0), id.Round(1), id.Round(2)}
-	return rounds, nil
+	return rounds, cE2e.MessageID{}, nil
 
 }
 
@@ -144,7 +146,9 @@ func (t *testNetworkManagerFullExchange) CheckGarbledMessages() {
 
 // Intended for alice to send to bob. Trigger's Bob's confirmation, chaining the operation
 // together
-func (t *testNetworkManagerFullExchange) SendE2E(m message.Send, p params.E2E) ([]id.Round, error) {
+func (t *testNetworkManagerFullExchange) SendE2E(m message.Send, p params.E2E) (
+	[]id.Round, cE2e.MessageID, error) {
+
 	rounds := []id.Round{id.Round(0), id.Round(1), id.Round(2)}
 	alicePrivKey := aliceSession.E2e().GetDHPrivateKey()
 	bobPubKey := bobSession.E2e().GetDHPublicKey()
@@ -167,7 +171,7 @@ func (t *testNetworkManagerFullExchange) SendE2E(m message.Send, p params.E2E) (
 
 	bobSwitchboard.Speak(confirmMessage)
 
-	return rounds, nil
+	return rounds, cE2e.MessageID{}, nil
 
 }
 
diff --git a/network/message/critical.go b/network/message/critical.go
index 238d94c90549ba1c3344f62debe2e819a6c275ba..e2a06de29fcfaa52219331092dd5596404fb11f7 100644
--- a/network/message/critical.go
+++ b/network/message/critical.go
@@ -39,7 +39,7 @@ func (m *Manager) criticalMessages() {
 	for msg, param, has := critMsgs.Next(); has; msg, param, has = critMsgs.Next() {
 		go func(msg message.Send, param params.E2E) {
 			//send the message
-			rounds, err := m.SendE2E(msg, param)
+			rounds, _, err := m.SendE2E(msg, param)
 			//if the message fail to send, notify the buffer so it can be handled
 			//in the future and exit
 			if err != nil {
diff --git a/network/message/garbled.go b/network/message/garbled.go
index cfc644f5504025c417dc2a99e1d72a4cf3e71222..56d20bd27f3d63bfd6782753a40c51a3a90b31de 100644
--- a/network/message/garbled.go
+++ b/network/message/garbled.go
@@ -52,7 +52,8 @@ func (m *Manager) handleGarbledMessages() {
 				garbledMsgs.Remove(grbldMsg)
 				//handle the successfully decrypted message
 				xxMsg, ok := m.partitioner.HandlePartition(sender, message.E2E,
-					msg.GetContents())
+					msg.GetContents(),
+					key.GetSession().GetRelationshipFingerprint())
 				if ok {
 					m.Switchboard.Speak(xxMsg)
 					continue
diff --git a/network/message/handler.go b/network/message/handler.go
index 66eb7ad268a7791dfa8e1ef0f66d4413d64381eb..4adde968543487b45a523b1578ff6b0e56947053 100644
--- a/network/message/handler.go
+++ b/network/message/handler.go
@@ -35,6 +35,7 @@ func (m *Manager) handleMessage(ecrMsg format.Message) {
 	var msg format.Message
 	var encTy message.EncryptionType
 	var err error
+	var relationshipFingerprint []byte
 
 	// try to get the key fingerprint, process as e2e encryption if
 	// the fingerprint is found
@@ -43,6 +44,7 @@ func (m *Manager) handleMessage(ecrMsg format.Message) {
 		msg, err = key.Decrypt(ecrMsg)
 		// get the sender
 		sender = key.GetSession().GetPartner()
+		relationshipFingerprint = key.GetSession().GetRelationshipFingerprint()
 
 		//drop the message is decryption failed
 		if err != nil {
@@ -76,7 +78,8 @@ func (m *Manager) handleMessage(ecrMsg format.Message) {
 
 	// Process the decrypted/unencrypted message partition, to see if
 	// we get a full message
-	xxMsg, ok := m.partitioner.HandlePartition(sender, encTy, msg.GetContents())
+	xxMsg, ok := m.partitioner.HandlePartition(sender, encTy, msg.GetContents(),
+		relationshipFingerprint)
 	// If the reception completed a message, hear it on the switchboard
 	if ok {
 		m.Switchboard.Speak(xxMsg)
diff --git a/network/message/parse/partition.go b/network/message/parse/partition.go
index b785e166c3014dc130e31a91518679bff2ac2701..6f77165d654133faef8c1ceead63cbbad73f62bc 100644
--- a/network/message/parse/partition.go
+++ b/network/message/parse/partition.go
@@ -33,15 +33,15 @@ func NewPartitioner(messageSize int, session *storage.Session) Partitioner {
 }
 
 func (p Partitioner) Partition(recipient *id.ID, mt message.Type,
-	timestamp time.Time, payload []byte) ([][]byte, error) {
+	timestamp time.Time, payload []byte) ([][]byte, uint64, error) {
 
 	if len(payload) > p.maxSize {
-		return nil, errors.Errorf("Payload is too long, max payload "+
+		return nil, 0, errors.Errorf("Payload is too long, max payload "+
 			"length is %v, received %v", p.maxSize, len(payload))
 	}
 
 	//Get the ID of the sent message
-	_, messageID := p.session.Conversations().Get(recipient).GetNextSendID()
+	fullMessageID, messageID := p.session.Conversations().Get(recipient).GetNextSendID()
 
 	// get the number of parts of the message. This equates to just a linear
 	// equation
@@ -59,11 +59,11 @@ func (p Partitioner) Partition(recipient *id.ID, mt message.Type,
 		parts[i] = newMessagePart(messageID, i, sub).Bytes()
 	}
 
-	return parts, nil
+	return parts, fullMessageID, nil
 }
 
 func (p Partitioner) HandlePartition(sender *id.ID, e message.EncryptionType,
-	contents []byte) (message.Receive, bool) {
+	contents []byte, relationshipFingerprint []byte) (message.Receive, bool) {
 
 	//If it is the first message in a set, handle it as so
 	if isFirst(contents) {
@@ -83,7 +83,7 @@ func (p Partitioner) HandlePartition(sender *id.ID, e message.EncryptionType,
 		//Return the
 		return p.session.Partition().AddFirst(sender, fm.GetType(),
 			messageID, fm.GetPart(), fm.GetNumParts(), timestamp,
-			fm.GetSizedContents())
+			fm.GetSizedContents(), relationshipFingerprint)
 		//If it is a subsiquent message part, handle it as so
 	} else {
 		mp := MessagePartFromBytes(contents)
@@ -91,7 +91,7 @@ func (p Partitioner) HandlePartition(sender *id.ID, e message.EncryptionType,
 			ProcessReceivedMessageID(mp.GetID())
 
 		return p.session.Partition().Add(sender, messageID, mp.GetPart(),
-			mp.GetSizedContents())
+			mp.GetSizedContents(), relationshipFingerprint)
 	}
 }
 
diff --git a/network/message/sendE2E.go b/network/message/sendE2E.go
index f33d0126736546876e821bce905f8c3a3220f8c8..e728cdf14453e1bec0a4e95c17a866d29bbb3fe1 100644
--- a/network/message/sendE2E.go
+++ b/network/message/sendE2E.go
@@ -11,22 +11,23 @@ import (
 	"gitlab.com/elixxir/client/interfaces/message"
 	"gitlab.com/elixxir/client/interfaces/params"
 	"gitlab.com/elixxir/client/keyExchange"
+	"gitlab.com/elixxir/crypto/e2e"
 	"gitlab.com/elixxir/primitives/format"
 	"gitlab.com/xx_network/primitives/id"
 	"sync"
 	"time"
 )
 
-func (m *Manager) SendE2E(msg message.Send, param params.E2E) ([]id.Round, error) {
+func (m *Manager) SendE2E(msg message.Send, param params.E2E) ([]id.Round, e2e.MessageID, error) {
 
 	//timestamp the message
 	ts := time.Now()
 
 	//partition the message
-	partitions, err := m.partitioner.Partition(msg.Recipient, msg.MessageType, ts,
+	partitions, internalMsgId, err := m.partitioner.Partition(msg.Recipient, msg.MessageType, ts,
 		msg.Payload)
 	if err != nil {
-		return nil, errors.WithMessage(err, "failed to send unsafe message")
+		return nil, e2e.MessageID{}, errors.WithMessage(err, "failed to send unsafe message")
 	}
 
 	//encrypt then send the partitions over cmix
@@ -36,7 +37,7 @@ func (m *Manager) SendE2E(msg message.Send, param params.E2E) ([]id.Round, error
 	// get the key manager for the partner
 	partner, err := m.Session.E2e().GetPartner(msg.Recipient)
 	if err != nil {
-		return nil, errors.WithMessagef(err, "Could not send End to End encrypted "+
+		return nil, e2e.MessageID{}, errors.WithMessagef(err, "Could not send End to End encrypted "+
 			"message, no relationship found with %v", partner)
 	}
 
@@ -50,7 +51,7 @@ func (m *Manager) SendE2E(msg message.Send, param params.E2E) ([]id.Round, error
 		//get a key to end to end encrypt
 		key, err := partner.GetKeyForSending(param.Type)
 		if err != nil {
-			return nil, errors.WithMessagef(err, "Failed to get key "+
+			return nil, e2e.MessageID{}, errors.WithMessagef(err, "Failed to get key "+
 				"for end to end encryption")
 		}
 
@@ -79,10 +80,11 @@ func (m *Manager) SendE2E(msg message.Send, param params.E2E) ([]id.Round, error
 	//see if any parts failed to send
 	numFail, errRtn := getSendErrors(errCh)
 	if numFail > 0 {
-		return nil, errors.Errorf("Failed to E2E send %v/%v sub payloads:"+
+		return nil, e2e.MessageID{}, errors.Errorf("Failed to E2E send %v/%v sub payloads:"+
 			" %s", numFail, len(partitions), errRtn)
 	}
 
 	//return the rounds if everything send successfully
-	return roundIds, nil
+	msgID := e2e.NewMessageID(partner.GetSendRelationshipFingerprint(), internalMsgId)
+	return roundIds, msgID, nil
 }
diff --git a/network/message/sendUnsafe.go b/network/message/sendUnsafe.go
index 92c3fbbf29f9cff68aaf585c4eca268184733d60..a51c72226c733bc9021ae4b65adc533f186013e3 100644
--- a/network/message/sendUnsafe.go
+++ b/network/message/sendUnsafe.go
@@ -26,7 +26,7 @@ func (m *Manager) SendUnsafe(msg message.Send, param params.Unsafe) ([]id.Round,
 	ts := time.Now()
 
 	//partition the message
-	partitions, err := m.partitioner.Partition(msg.Recipient, msg.MessageType, ts,
+	partitions, _, err := m.partitioner.Partition(msg.Recipient, msg.MessageType, ts,
 		msg.Payload)
 
 	if err != nil {
diff --git a/network/send.go b/network/send.go
index 904776c9dceca9af15e6814ce16ccd0162e66382..68a4aee4399dbe2c97067ac4261b0971be429af6 100644
--- a/network/send.go
+++ b/network/send.go
@@ -5,6 +5,7 @@ import (
 	jww "github.com/spf13/jwalterweatherman"
 	"gitlab.com/elixxir/client/interfaces/message"
 	"gitlab.com/elixxir/client/interfaces/params"
+	"gitlab.com/elixxir/crypto/e2e"
 	"gitlab.com/elixxir/primitives/format"
 	"gitlab.com/xx_network/primitives/id"
 )
@@ -44,11 +45,11 @@ func (m *manager) SendUnsafe(msg message.Send, param params.Unsafe) ([]id.Round,
 // the provided msgType. Returns the list of rounds in which parts of
 // the message were sent or an error if it fails.
 func (m *manager) SendE2E(msg message.Send, e2eP params.E2E) (
-	[]id.Round, error) {
+	[]id.Round, e2e.MessageID, error) {
 
 	if !m.Health.IsHealthy() {
-		return nil, errors.New("Cannot send e2e message when the " +
-			"network is not healthy")
+		return nil, e2e.MessageID{}, errors.New("Cannot send e2e " +
+			"message when the network is not healthy")
 	}
 
 	return m.message.SendE2E(msg, e2eP)
diff --git a/storage/e2e/manager.go b/storage/e2e/manager.go
index 2770b7d12bf07d30727aa50d34305de70961c10a..d395de5bed1f9a9888d5a2f03410294706b1c10a 100644
--- a/storage/e2e/manager.go
+++ b/storage/e2e/manager.go
@@ -168,6 +168,13 @@ func (m *Manager) GetSendSession(sid SessionID) *Session {
 	return m.send.GetByID(sid)
 }
 
+// GetSendSession gets the Send session of the passed ID. Returns nil if no
+// session is found.
+func (m *Manager) GetSendRelationshipFingerprint() []byte {
+	return m.send.fingerprint
+}
+
+
 // GetReceiveSession gets the Receive session of the passed ID. Returns nil if
 // no session is found.
 func (m *Manager) GetReceiveSession(sid SessionID) *Session {
diff --git a/storage/partition/multiPartMessage.go b/storage/partition/multiPartMessage.go
index 28907664049a63110347cdae002b64d408a188a2..f6cdb54937e01b853425b1252a22e4e4bffc1eeb 100644
--- a/storage/partition/multiPartMessage.go
+++ b/storage/partition/multiPartMessage.go
@@ -7,6 +7,7 @@ import (
 	jww "github.com/spf13/jwalterweatherman"
 	"gitlab.com/elixxir/client/interfaces/message"
 	"gitlab.com/elixxir/client/storage/versioned"
+	"gitlab.com/elixxir/crypto/e2e"
 	"gitlab.com/elixxir/ekv"
 	"gitlab.com/xx_network/primitives/id"
 	"sync"
@@ -138,7 +139,7 @@ func (mpm *multiPartMessage) AddFirst(mt message.Type, partNumber uint8,
 	}
 }
 
-func (mpm *multiPartMessage) IsComplete() (message.Receive, bool) {
+func (mpm *multiPartMessage) IsComplete(relationshipFingerprint []byte) (message.Receive, bool) {
 	mpm.mux.Lock()
 	if mpm.NumParts == 0 || mpm.NumParts != mpm.PresentParts {
 		mpm.mux.Unlock()
@@ -181,6 +182,12 @@ func (mpm *multiPartMessage) IsComplete() (message.Receive, bool) {
 		partOffset += len(part)
 	}
 
+	var mid e2e.MessageID
+	if len(relationshipFingerprint) != 0 {
+		mid = e2e.NewMessageID(relationshipFingerprint, mpm.MessageID)
+	}
+
+
 	// Return the message
 	m := message.Receive{
 		Payload:     reconstructed,
@@ -189,6 +196,7 @@ func (mpm *multiPartMessage) IsComplete() (message.Receive, bool) {
 		Timestamp:   time.Time{},
 		// Encryption will be set externally
 		Encryption: 0,
+		ID:         mid,
 	}
 
 	return m, true
diff --git a/storage/partition/multiPartMessage_test.go b/storage/partition/multiPartMessage_test.go
index c5577e4ec8f6862e324b072a71439e66ad2aeae3..5c546e9e90c30f2a4b3c9d496f432be95161edc1 100644
--- a/storage/partition/multiPartMessage_test.go
+++ b/storage/partition/multiPartMessage_test.go
@@ -3,9 +3,9 @@ package partition
 import (
 	"bytes"
 	"encoding/json"
-	jww "github.com/spf13/jwalterweatherman"
 	"gitlab.com/elixxir/client/interfaces/message"
 	"gitlab.com/elixxir/client/storage/versioned"
+	"gitlab.com/elixxir/crypto/e2e"
 	"gitlab.com/elixxir/ekv"
 	"gitlab.com/xx_network/primitives/id"
 	"math/rand"
@@ -16,7 +16,6 @@ import (
 
 // Tests the creation part of loadOrCreateMultiPartMessage().
 func Test_loadOrCreateMultiPartMessage_Create(t *testing.T) {
-	jww.SetStdoutThreshold(jww.LevelTrace)
 	// Set up expected test value
 	prng := rand.New(rand.NewSource(time.Now().UnixNano()))
 	expectedMpm := &multiPartMessage{
@@ -185,12 +184,13 @@ func TestMultiPartMessage_AddFirst(t *testing.T) {
 func TestMultiPartMessage_IsComplete(t *testing.T) {
 	// Create multiPartMessage and fill with random parts
 	prng := rand.New(rand.NewSource(time.Now().UnixNano()))
+	mid := prng.Uint64()
 	mpm := loadOrCreateMultiPartMessage(id.NewIdFromUInt(prng.Uint64(), id.User, t),
-		prng.Uint64(), versioned.NewKV(make(ekv.Memstore)))
+		mid, versioned.NewKV(make(ekv.Memstore)))
 	partNums, parts := generateParts(prng, 75)
 
 	// Check that IsComplete() is false where there are no parts
-	msg, complete := mpm.IsComplete()
+	msg, complete := mpm.IsComplete([]byte{0})
 	if complete {
 		t.Error("IsComplete() returned true when NumParts == 0.")
 	}
@@ -202,7 +202,7 @@ func TestMultiPartMessage_IsComplete(t *testing.T) {
 		}
 	}
 
-	msg, complete = mpm.IsComplete()
+	msg, complete = mpm.IsComplete([]byte{0})
 	if !complete {
 		t.Error("IsComplete() returned false when the message should be complete.")
 	}
@@ -218,6 +218,7 @@ func TestMultiPartMessage_IsComplete(t *testing.T) {
 		Sender:      mpm.Sender,
 		Timestamp:   time.Time{},
 		Encryption:  0,
+		ID:          e2e.NewMessageID([]byte{0}, mid),
 	}
 
 	if !reflect.DeepEqual(expectedMsg, msg) {
diff --git a/storage/partition/part_test.go b/storage/partition/part_test.go
index d83d528fb4e962d3b2f23f8ae13b1b25c1da33a2..a7929e61bb4e684d6303ef648c186d125247f068 100644
--- a/storage/partition/part_test.go
+++ b/storage/partition/part_test.go
@@ -2,7 +2,6 @@ package partition
 
 import (
 	"bytes"
-	jww "github.com/spf13/jwalterweatherman"
 	"gitlab.com/elixxir/client/storage/versioned"
 	"gitlab.com/elixxir/ekv"
 	"math/rand"
@@ -41,7 +40,6 @@ func Test_savePart(t *testing.T) {
 
 // Tests happy path of loadPart().
 func Test_loadPart(t *testing.T) {
-	jww.SetStdoutThreshold(jww.LevelTrace)
 	// Set up test values
 	prng := rand.New(rand.NewSource(time.Now().UnixNano()))
 	rootKv := versioned.NewKV(make(ekv.Memstore))
diff --git a/storage/partition/store.go b/storage/partition/store.go
index 2b23d2834e905c94b6d11e3ffab764e18d94154e..46b26229095e31f16c0f44a7a0f95b3d8d4303d7 100644
--- a/storage/partition/store.go
+++ b/storage/partition/store.go
@@ -29,23 +29,23 @@ func New(kv *versioned.KV) *Store {
 
 func (s *Store) AddFirst(partner *id.ID, mt message.Type, messageID uint64,
 	partNum, numParts uint8, timestamp time.Time,
-	part []byte) (message.Receive, bool) {
+	part []byte, relationshipFingerprint []byte) (message.Receive, bool) {
 
 	mpm := s.load(partner, messageID)
 
 	mpm.AddFirst(mt, partNum, numParts, timestamp, part)
 
-	return mpm.IsComplete()
+	return mpm.IsComplete(relationshipFingerprint)
 }
 
 func (s *Store) Add(partner *id.ID, messageID uint64, partNum uint8,
-	part []byte) (message.Receive, bool) {
+	part []byte, relationshipFingerprint []byte) (message.Receive, bool) {
 
 	mpm := s.load(partner, messageID)
 
 	mpm.Add(partNum, part)
 
-	return mpm.IsComplete()
+	return mpm.IsComplete(relationshipFingerprint)
 }
 
 func (s *Store) load(partner *id.ID, messageID uint64) *multiPartMessage {
diff --git a/storage/partition/store_test.go b/storage/partition/store_test.go
index fab54bcd6bc38f6c4c031460cf6c006d6dc1e213..251b64702a065117fcad392e8d036998f46a4803 100644
--- a/storage/partition/store_test.go
+++ b/storage/partition/store_test.go
@@ -2,7 +2,6 @@ package partition
 
 import (
 	"bytes"
-	jww "github.com/spf13/jwalterweatherman"
 	"gitlab.com/elixxir/client/interfaces/message"
 	"gitlab.com/elixxir/client/storage/versioned"
 	"gitlab.com/elixxir/ekv"
@@ -30,12 +29,12 @@ func TestNew(t *testing.T) {
 
 // Tests happy path of Store.AddFirst().
 func TestStore_AddFirst(t *testing.T) {
-	jww.SetStdoutThreshold(jww.LevelTrace)
 	part := []byte("Test message.")
 	s := New(versioned.NewKV(ekv.Memstore{}))
 
 	msg, complete := s.AddFirst(id.NewIdFromString("User", id.User, t),
-		message.Text, 5, 0, 1, time.Now(), part)
+		message.Text, 5, 0, 1, time.Now(), part,
+		[]byte{0})
 
 	if !complete {
 		t.Errorf("AddFirst() returned that the message was not complete.")
@@ -54,13 +53,15 @@ func TestStore_Add(t *testing.T) {
 	s := New(versioned.NewKV(ekv.Memstore{}))
 
 	msg, complete := s.AddFirst(id.NewIdFromString("User", id.User, t),
-		message.Text, 5, 0, 2, time.Now(), part1)
+		message.Text, 5, 0, 2, time.Now(), part1,
+		[]byte{0})
 
 	if complete {
 		t.Errorf("AddFirst() returned that the message was complete.")
 	}
 
-	msg, complete = s.Add(id.NewIdFromString("User", id.User, t), 5, 1, part2)
+	msg, complete = s.Add(id.NewIdFromString("User", id.User, t),
+		5, 1, part2, []byte{0})
 	if !complete {
 		t.Errorf("AddFirst() returned that the message was not complete.")
 	}