diff --git a/bindings/channels.go b/bindings/channels.go
index 2838fc10ec4109f6b813fd2b4f3a01dd62fdd455..3c0dfdfd53372c59cfdcd5688baa2aa5c3d43f20 100644
--- a/bindings/channels.go
+++ b/bindings/channels.go
@@ -10,6 +10,7 @@ package bindings
 import (
 	"encoding/json"
 	"github.com/pkg/errors"
+	jww "github.com/spf13/jwalterweatherman"
 	"gitlab.com/elixxir/client/channels"
 	"gitlab.com/elixxir/client/cmix/rounds"
 	"gitlab.com/elixxir/client/xxdk"
@@ -97,104 +98,186 @@ func (cm *ChannelsManager) GetID() int {
 	return cm.id
 }
 
-// NewChannelsManager constructs a ChannelsManager.
-// FIXME: This is a work in progress and should not be used an event model is
-//  implemented in the style of the bindings layer's AuthCallbacks. Remove this
-//  note when that has been done.
-//
-// Parameters:
-//  - e2eID - The tracked e2e object ID. This can be retrieved using
-//    [E2e.GetID].
-//  - udID - The tracked UD object ID. This can be retrieved using
-//    [UserDiscovery.GetID].
-func NewChannelsManager(e2eID, udID int) (*ChannelsManager, error) {
+// GenerateChannelIdentity creates and returns a marshal for a private
+// channel Identity. The public component can be read as json via
+// [GetPublicChannelIdentityFromPrivate]
+func GenerateChannelIdentity(cmixID int) ([]byte, error) {
 	// Get user from singleton
-	user, err := e2eTrackerSingleton.get(e2eID)
+	user, err := cmixTrackerSingleton.get(cmixID)
+	if err != nil {
+		return nil, err
+	}
+
+	rng := user.api.GetRng().GetStream()
+	defer rng.Close()
+	pi, err := cryptoChannel.GenerateIdentity(rng)
+	if err != nil {
+		return nil, err
+	}
+	return pi.Marshal(), nil
+}
+
+// GetPublicChannelIdentity returns a json marshal of the public
+// identity related to the given marshaled public identity
+func GetPublicChannelIdentity(marshaledPublic []byte) ([]byte, error) {
+	i, err := cryptoChannel.UnmarshalIdentity(marshaledPublic)
 	if err != nil {
 		return nil, err
 	}
+	return json.Marshal(&i)
+}
 
-	udMan, err := udTrackerSingleton.get(udID)
+// GetPublicChannelIdentityFromPrivate returns a json marshal of the public
+// identity related to the given private identity
+func GetPublicChannelIdentityFromPrivate(marshaledPrivate []byte) ([]byte, error) {
+	pi, err := cryptoChannel.UnmarshalPrivateIdentity(marshaledPrivate)
 	if err != nil {
 		return nil, err
 	}
+	return json.Marshal(&pi.Identity)
+}
 
-	nameService, err := udMan.api.StartChannelNameService()
+// NewChannelsManagerGoEventModel creates a new ChannelsManager from a new
+// identity. This is not compatible with GoMobile Bindings because it
+// receives the go event model. This is for creating a manager for an identity
+// for the first time.
+// for generating a new one channel identity, please use
+// GenerateChannelIdentity
+// To reload this channel manager, use LoadChannelsManagerGoEventModel, passing
+// in the storageTag retrieved by
+//
+// Parameters:
+//  - cmixID - The tracked cmix object ID. This can be retrieved using
+//    [Cmix.GetID].
+//  - privateIdentity - a private identity generated by GenerateChannelIdentity
+//  - goEvent the event model which is not compatible with GoMobile bindings
+func NewChannelsManagerGoEventModel(cmixID int, privateIdentity []byte,
+	goEvent channels.EventModel) (*ChannelsManager, error) {
+	pi, err := cryptoChannel.UnmarshalPrivateIdentity(privateIdentity)
+	if err != nil {
+		return nil, err
+	}
+
+	// Get user from singleton
+	user, err := cmixTrackerSingleton.get(cmixID)
 	if err != nil {
 		return nil, err
 	}
 
 	// Construct new channels manager
-	// TODO: Implement a bindings layer event model, pass that in as a parameter
-	//  or the function and pass that into here.
-	m := channels.NewManager(user.api.GetStorage().GetKV(), user.api.GetCmix(),
-		user.api.GetRng(), nameService, nil)
+	m, err := channels.NewManager(pi, user.api.GetStorage().GetKV(), user.api.GetCmix(),
+		user.api.GetRng(), goEvent)
+	if err != nil {
+		return nil, err
+	}
 
 	// Add channel to singleton and return
 	return channelManagerTrackerSingleton.make(m), nil
 }
 
-// NewChannelsManagerGoEventModel constructs a ChannelsManager. This is not
+// LoadChannelsManagerGoEventModel loads an existing ChannelsManager. This is not
 // compatible with GoMobile Bindings because it receives the go event model.
+// This is for creating a manager for an identity for the first time.
+// The channel manager should have first been created with
+// NewChannelsManagerGoEventModel and then the storage tag can be retrieved
+// with ChannelsManager.GetStorageTag
 //
 // Parameters:
-//  - e2eID - The tracked e2e object ID. This can be retrieved using
-//    [E2e.GetID].
-//  - udID - The tracked UD object ID. This can be retrieved using
-//    [UserDiscovery.GetID].
-func NewChannelsManagerGoEventModel(e2eID, udID int,
+//  - cmixID - The tracked cmix object ID. This can be retrieved using
+//    [Cmix.GetID].
+//  - storageTag - retrieved with ChannelsManager.GetStorageTag
+//  - goEvent the event model which is not compatible with GoMobile bindings
+func LoadChannelsManagerGoEventModel(cmixID int, storageTag string,
 	goEvent channels.EventModel) (*ChannelsManager, error) {
+
 	// Get user from singleton
-	user, err := e2eTrackerSingleton.get(e2eID)
+	user, err := cmixTrackerSingleton.get(cmixID)
 	if err != nil {
 		return nil, err
 	}
 
-	udMan, err := udTrackerSingleton.get(udID)
+	// Construct new channels manager
+	m, err := channels.LoadManager(storageTag, user.api.GetStorage().GetKV(),
+		user.api.GetCmix(),
+		user.api.GetRng(), goEvent)
 	if err != nil {
 		return nil, err
 	}
 
-	nameService, err := udMan.api.StartChannelNameService()
+	// Add channel to singleton and return
+	return channelManagerTrackerSingleton.make(m), nil
+}
+
+// NewChannelsManager creates a new ChannelsManager from a new
+// identity. This is for creating a manager for an identity
+// for the first time.
+// for generating a new one channel identity, please use
+// GenerateChannelIdentity
+// To reload this channel manager, use LoadChannelsManagerGoEventModel, passing
+// in the storageTag retrieved by
+//
+// Parameters:
+//  - cmixID - The tracked cmix object ID. This can be retrieved using
+//    [Cmix.GetID].
+//  - privateIdentity - a private identity generated by GenerateChannelIdentity
+//  - event - the event model, compatible over the bindings
+func NewChannelsManager(cmixID int, privateIdentity []byte,
+	event EventModel) (*ChannelsManager, error) {
+	pi, err := cryptoChannel.UnmarshalPrivateIdentity(privateIdentity)
+	if err != nil {
+		return nil, err
+	}
+
+	// Get user from singleton
+	user, err := cmixTrackerSingleton.get(cmixID)
 	if err != nil {
 		return nil, err
 	}
 
+	// wrap the event model to make it compatible
+	goEvent := NewEventModel(event)
+
 	// Construct new channels manager
-	m := channels.NewManager(user.api.GetStorage().GetKV(), user.api.GetCmix(),
-		user.api.GetRng(), nameService, goEvent)
+	m, err := channels.NewManager(pi, user.api.GetStorage().GetKV(), user.api.GetCmix(),
+		user.api.GetRng(), goEvent)
+	if err != nil {
+		return nil, err
+	}
 
 	// Add channel to singleton and return
 	return channelManagerTrackerSingleton.make(m), nil
 }
 
-// NewChannelsManagerGoEventModelDummyNameService constructs a
-// ChannelsManager. This is not compatible with GoMobile Bindings because
-// it receives the go event model. This uses the dummy name service
-// and is for debugging only.
+// LoadChannelsManager loads an existing ChannelsManager.
+// This is for creating a manager for an identity for the first time.
+// The channel manager should have first been created with
+// NewChannelsManagerGoEventModel and then the storage tag can be retrieved
+// with ChannelsManager.GetStorageTag
+//
 // Parameters:
 //  - cmixID - The tracked cmix object ID. This can be retrieved using
 //    [Cmix.GetID].
-//  - username - the username the user wants.
-//  - goEvent - the channels event model
-func NewChannelsManagerGoEventModelDummyNameService(cmixID int, username string,
-	goEvent channels.EventModel) (*ChannelsManager, error) {
+//  - storageTag - retrieved with ChannelsManager.GetStorageTag
+//  - event - the event model, compatible over the bindings
+func LoadChannelsManager(cmixID int, storageTag string,
+	event EventModel) (*ChannelsManager, error) {
+
 	// Get user from singleton
 	user, err := cmixTrackerSingleton.get(cmixID)
 	if err != nil {
 		return nil, err
 	}
 
-	rng := user.api.GetRng().GetStream()
-	defer rng.Close()
+	// wrap the event model to make it compatible
+	goEvent := NewEventModel(event)
 
-	nameService, err := channels.NewDummyNameService(username, rng)
+	// Construct new channels manager
+	m, err := channels.LoadManager(storageTag, user.api.GetStorage().GetKV(),
+		user.api.GetCmix(),
+		user.api.GetRng(), goEvent)
 	if err != nil {
 		return nil, err
 	}
-	// Construct new channels manager
-	m := channels.NewManager(user.api.GetStorage().GetKV(), user.api.GetCmix(),
-		user.api.GetRng(), nameService, goEvent)
 
 	// Add channel to singleton and return
 	return channelManagerTrackerSingleton.make(m), nil
@@ -626,6 +709,60 @@ func (cm *ChannelsManager) SendReaction(marshalledChanId []byte,
 	return constructChannelSendReport(chanMsgId, rnd.ID, ephId)
 }
 
+// GetIdentity returns the marshaled public identity that the channel is
+// using
+func (cm *ChannelsManager) GetIdentity() ([]byte, error) {
+	i := cm.api.GetIdentity()
+	return json.Marshal(&i)
+}
+
+// GetStorageTag returns the storage tag needed to reload the manager
+func (cm *ChannelsManager) GetStorageTag() string {
+	return cm.api.GetStorageTag()
+}
+
+// SetNickname sets the nickname for a given channel
+func (cm *ChannelsManager) SetNickname(newNick string, ch []byte) error {
+	chid, err := id.Unmarshal(ch)
+	if err != nil {
+		return err
+	}
+	return cm.api.SetNickname(newNick, chid)
+}
+
+// DeleteNickname deletes the nickname for a given channel
+func (cm *ChannelsManager) DeleteNickname(ch []byte) error {
+	chid, err := id.Unmarshal(ch)
+	if err != nil {
+		return err
+	}
+	return cm.api.DeleteNickname(chid)
+}
+
+// GetNickname returns the nickname for a given channel. Returns an error if
+// there is no nickname
+func (cm *ChannelsManager) GetNickname(ch []byte) (string, error) {
+	chid, err := id.Unmarshal(ch)
+	if err != nil {
+		return "", err
+	}
+	nick, exists := cm.api.GetNickname(chid)
+	if !exists {
+		return "", errors.New("no nickname found for the given channel")
+	}
+
+	return nick, nil
+}
+
+// IsNicknameValid checks if a nickname is valid
+//
+// rules
+//   - a nickname must not be longer than 24 characters
+//   - a nickname must not be shorter than 1 character
+func IsNicknameValid(nick string) error {
+	return channels.IsNicknameValid(nick)
+}
+
 // parseChannelsParameters is a helper function for the Send functions. It
 // parses the channel ID and the passed in parameters into their respective
 // objects. These objects are passed into the API via the internal send
@@ -684,20 +821,23 @@ func constructChannelSendReport(channelMessageId cryptoChannel.MessageID,
 //    "Rounds": [ 1, 4, 9],
 //  }
 type ReceivedChannelMessageReport struct {
-	ChannelId      []byte
-	MessageId      []byte
-	MessageType    int
-	SenderUsername string
-	Content        []byte
-	Timestamp      int64
-	Lease          int64
+	ChannelId   []byte
+	MessageId   []byte
+	MessageType int
+	Nickname    string
+	Identity    []byte
+	Content     []byte
+	Timestamp   int64
+	Lease       int64
 	RoundsList
 }
 
 // ChannelMessageReceptionCallback is the callback that returns the context for
 // a channel message via the Callback.
+// It must return a unique UUID for the message by which it can be referenced
+// later
 type ChannelMessageReceptionCallback interface {
-	Callback(receivedChannelMessageReport []byte, err error)
+	Callback(receivedChannelMessageReport []byte, err error) int
 }
 
 // RegisterReceiveHandler is used to register handlers for non-default message
@@ -719,21 +859,29 @@ func (cm *ChannelsManager) RegisterReceiveHandler(messageType int,
 	cb := channels.MessageTypeReceiveMessage(
 		func(channelID *id.ID,
 			messageID cryptoChannel.MessageID, messageType channels.MessageType,
-			senderUsername string, content []byte, timestamp time.Time,
-			lease time.Duration, round rounds.Round, status channels.SentStatus) {
+			nickname string, content []byte, identity cryptoChannel.Identity,
+			timestamp time.Time, lease time.Duration, round rounds.Round,
+			status channels.SentStatus) uint64 {
+
+			idBytes, err := json.Marshal(&identity)
+			if err != nil {
+				jww.WARN.Printf("failed to marshal identity object: %+v", err)
+				return 0
+			}
 
 			rcm := ReceivedChannelMessageReport{
-				ChannelId:      channelID.Marshal(),
-				MessageId:      messageID.Bytes(),
-				MessageType:    int(messageType),
-				SenderUsername: senderUsername,
-				Content:        content,
-				Timestamp:      timestamp.UnixNano(),
-				Lease:          int64(lease),
-				RoundsList:     makeRoundsList(round.ID),
+				ChannelId:   channelID.Marshal(),
+				MessageId:   messageID.Bytes(),
+				MessageType: int(messageType),
+				Nickname:    nickname,
+				Identity:    idBytes,
+				Content:     content,
+				Timestamp:   timestamp.UnixNano(),
+				Lease:       int64(lease),
+				RoundsList:  makeRoundsList(round.ID),
 			}
 
-			listenerCb.Callback(json.Marshal(rcm))
+			return uint64(listenerCb.Callback(json.Marshal(rcm)))
 		})
 
 	// Register handler
@@ -768,10 +916,11 @@ type EventModel interface {
 	//  - channelID - The marshalled channel [id.ID].
 	//  - messageID - The bytes of the [channel.MessageID] of the received
 	//    message.
-	//  - senderUsername - The username of the sender of the message.
+	//  - nickname - The nickname of the sender of the message.
 	//  - text - The content of the message.
 	//  - timestamp - Time the message was received; represented as nanoseconds
 	//    since unix epoch.
+	//  - identity - the json of the identity of the sender
 	//  - lease - The number of nanoseconds that the message is valid for.
 	//  - roundId - The ID of the round that the message was received on.
 	//  - status - the [channels.SentStatus] of the message.
@@ -780,8 +929,11 @@ type EventModel interface {
 	//  Sent      =  0
 	//  Delivered =  1
 	//  Failed    =  2
-	ReceiveMessage(channelID, messageID []byte, senderUsername, text string,
-		timestamp, lease, roundId, status int64)
+	//
+	// Returns a non-negative unique uuid for the message by which it can be
+	// referenced later with UpdateSentStatus
+	ReceiveMessage(channelID, messageID []byte, nickname, text string,
+		identity []byte, timestamp, lease, roundId, status int64) int64
 
 	// ReceiveReply is called whenever a message is received that is a reply on
 	// a given channel. It may be called multiple times on the same message. It
@@ -796,8 +948,9 @@ type EventModel interface {
 	//    message.
 	//  - reactionTo - The [channel.MessageID] for the message that received a
 	//    reply.
-	//  - senderUsername - The username of the sender of the message.
+	//  - nickname - The nickname of the sender of the message.
 	//  - text - The content of the message.
+	//  - identity - the json marshaled identity of the sender
 	//  - timestamp - Time the message was received; represented as nanoseconds
 	//    since unix epoch.
 	//  - lease - The number of nanoseconds that the message is valid for.
@@ -808,9 +961,12 @@ type EventModel interface {
 	//  Sent      =  0
 	//  Delivered =  1
 	//  Failed    =  2
+	//
+	// Returns a non-negative unique uuid for the message by which it can be
+	// referenced later with UpdateSentStatus
 	ReceiveReply(channelID, messageID, reactionTo []byte,
-		senderUsername, text string,
-		timestamp, lease, roundId, status int64)
+		nickname, text string, identity []byte,
+		timestamp, lease, roundId, status int64) int64
 
 	// ReceiveReaction is called whenever a reaction to a message is received
 	// on a given channel. It may be called multiple times on the same reaction.
@@ -827,8 +983,9 @@ type EventModel interface {
 	//    message.
 	//  - reactionTo - The [channel.MessageID] for the message that received a
 	//    reply.
-	//  - senderUsername - The username of the sender of the message.
+	//  - nickname - The nickname of the sender of the message.
 	//  - reaction - The contents of the reaction message.
+	//  - identity - The json marshal of the identity of the sender
 	//  - timestamp - Time the message was received; represented as nanoseconds
 	//    since unix epoch.
 	//  - lease - The number of nanoseconds that the message is valid for.
@@ -839,9 +996,12 @@ type EventModel interface {
 	//  Sent      =  0
 	//  Delivered =  1
 	//  Failed    =  2
+	//
+	// Returns a non-negative unique uuid for the message by which it can be
+	// referenced later with UpdateSentStatus
 	ReceiveReaction(channelID, messageID, reactionTo []byte,
-		senderUsername, reaction string,
-		timestamp, lease, roundId, status int64)
+		nickname, reaction string, identity []byte,
+		timestamp, lease, roundId, status int64) int64
 
 	// UpdateSentStatus is called whenever the sent status of a message has
 	// changed.
@@ -855,7 +1015,8 @@ type EventModel interface {
 	//  Sent      =  0
 	//  Delivered =  1
 	//  Failed    =  2
-	UpdateSentStatus(messageID []byte, status int64)
+	UpdateSentStatus(uuint int64, messageID []byte, timestamp, roundid,
+		status int64)
 
 	// unimplemented
 	// IgnoreMessage(ChannelID *id.ID, MessageID cryptoChannel.MessageID)
@@ -871,7 +1032,7 @@ type toEventModel struct {
 
 // NewEventModel is a constructor for a toEventModel. This will take in an
 // EventModel and wraps it around the toEventModel.
-func NewEventModel(em EventModel) *toEventModel {
+func NewEventModel(em EventModel) channels.EventModel {
 	return &toEventModel{em: em}
 }
 
@@ -888,13 +1049,20 @@ func (tem *toEventModel) LeaveChannel(channelID *id.ID) {
 // ReceiveMessage is called whenever a message is received on a given channel.
 // It may be called multiple times on the same message. It is incumbent on the
 // user of the API to filter such called by message ID.
-func (tem *toEventModel) ReceiveMessage(channelID *id.ID,
-	messageID cryptoChannel.MessageID, senderUsername string, text string,
+func (tem *toEventModel) ReceiveMessage(channelID *id.ID, messageID cryptoChannel.MessageID,
+	nickname, text string, identity cryptoChannel.Identity,
 	timestamp time.Time, lease time.Duration, round rounds.Round,
-	status channels.SentStatus) {
+	status channels.SentStatus) uint64 {
 
-	tem.em.ReceiveMessage(channelID[:], messageID[:], senderUsername, text,
-		timestamp.UnixNano(), int64(lease), int64(round.ID), int64(status))
+	idBytes, err := json.Marshal(&identity)
+	if err != nil {
+		jww.WARN.Printf("failed to marshal identity object: %+v", err)
+		return 0
+	}
+
+	return uint64(tem.em.ReceiveMessage(channelID[:], messageID[:], nickname,
+		text, idBytes, timestamp.UnixNano(), int64(lease), int64(round.ID),
+		int64(status)))
 }
 
 // ReceiveReply is called whenever a message is received that is a reply on a
@@ -903,15 +1071,20 @@ func (tem *toEventModel) ReceiveMessage(channelID *id.ID,
 //
 // Messages may arrive our of order, so a reply in theory can arrive before the
 // initial message. As a result, it may be important to buffer replies.
-func (tem *toEventModel) ReceiveReply(channelID *id.ID,
-	messageID cryptoChannel.MessageID,
-	reactionTo cryptoChannel.MessageID, senderUsername string,
-	text string, timestamp time.Time, lease time.Duration,
-	round rounds.Round, status channels.SentStatus) {
-
-	tem.em.ReceiveReply(channelID[:], messageID[:], reactionTo[:],
-		senderUsername, text, timestamp.UnixNano(), int64(lease),
-		int64(round.ID), int64(status))
+func (tem *toEventModel) ReceiveReply(channelID *id.ID, messageID cryptoChannel.MessageID,
+	reactionTo cryptoChannel.MessageID, nickname, text string,
+	identity cryptoChannel.Identity, timestamp time.Time,
+	lease time.Duration, round rounds.Round, status channels.SentStatus) uint64 {
+
+	idBytes, err := json.Marshal(&identity)
+	if err != nil {
+		jww.WARN.Printf("failed to marshal identity object: %+v", err)
+		return 0
+	}
+
+	return uint64(tem.em.ReceiveReply(channelID[:], messageID[:], reactionTo[:],
+		nickname, text, idBytes, timestamp.UnixNano(), int64(lease),
+		int64(round.ID), int64(status)))
 
 }
 
@@ -921,18 +1094,26 @@ func (tem *toEventModel) ReceiveReply(channelID *id.ID,
 //
 // Messages may arrive our of order, so a reply in theory can arrive before the
 // initial message. As a result, it may be important to buffer reactions.
-func (tem *toEventModel) ReceiveReaction(channelID *id.ID,
-	messageID cryptoChannel.MessageID, reactionTo cryptoChannel.MessageID,
-	senderUsername string, reaction string, timestamp time.Time,
-	lease time.Duration, round rounds.Round, status channels.SentStatus) {
+func (tem *toEventModel) ReceiveReaction(channelID *id.ID, messageID cryptoChannel.MessageID,
+	reactionTo cryptoChannel.MessageID, nickname, reaction string,
+	identity cryptoChannel.Identity, timestamp time.Time,
+	lease time.Duration, round rounds.Round, status channels.SentStatus) uint64 {
 
-	tem.em.ReceiveReaction(channelID[:], messageID[:], reactionTo[:],
-		senderUsername, reaction, timestamp.UnixNano(), int64(lease),
-		int64(round.ID), int64(status))
+	idBytes, err := json.Marshal(&identity)
+	if err != nil {
+		jww.WARN.Printf("failed to marshal identity object: %+v", err)
+		return 0
+	}
+
+	return uint64(tem.em.ReceiveReaction(channelID[:], messageID[:],
+		reactionTo[:], nickname, reaction, idBytes, timestamp.UnixNano(),
+		int64(lease), int64(round.ID), int64(status)))
 }
 
 // UpdateSentStatus is called whenever the sent status of a message has changed.
-func (tem *toEventModel) UpdateSentStatus(messageID cryptoChannel.MessageID,
+func (tem *toEventModel) UpdateSentStatus(uuid uint64,
+	messageID cryptoChannel.MessageID, timestamp time.Time, round rounds.Round,
 	status channels.SentStatus) {
-	tem.em.UpdateSentStatus(messageID[:], int64(status))
+	tem.em.UpdateSentStatus(int64(uuid), messageID[:], timestamp.UnixNano(),
+		int64(round.ID), int64(status))
 }
diff --git a/channels/adminListener.go b/channels/adminListener.go
index 1c53be04bd0b33f0feb79675dcd3dbb62a32d272..0f5b6630e6c2bbb0c68a72b029c46882789a9d09 100644
--- a/channels/adminListener.go
+++ b/channels/adminListener.go
@@ -13,6 +13,7 @@ import (
 	"gitlab.com/elixxir/client/cmix/identity/receptionID"
 	"gitlab.com/elixxir/client/cmix/rounds"
 	"gitlab.com/elixxir/crypto/channel"
+	"gitlab.com/elixxir/primitives/states"
 	"gitlab.com/xx_network/primitives/id"
 )
 
@@ -53,8 +54,15 @@ func (al *adminListener) Listen(payload []byte,
 		return
 	}
 
+	// Modify the timestamp to reduce the chance message order will be ambiguous
+	ts := mutateTimestamp(round.Timestamps[states.QUEUED], msgID)
+
 	// Submit the message to the event model for listening
-	al.trigger(al.chID, cm, msgID, receptionID, round, Delivered)
+	if uuid, err := al.trigger(al.chID, cm, ts, msgID, receptionID,
+		round, Delivered); err != nil {
+		jww.WARN.Printf("Error in passing off trigger for admin "+
+			"message (UUID: %d): %+v", uuid, err)
+	}
 
 	return
 }
diff --git a/channels/eventModel.go b/channels/eventModel.go
index a87016e1dc648e47d8c637e3b6194a8d38ec3fc7..9dbd9b4cfef3385814cb49289ddea16b032a0043 100644
--- a/channels/eventModel.go
+++ b/channels/eventModel.go
@@ -13,7 +13,6 @@ import (
 	"github.com/golang/protobuf/proto"
 	jww "github.com/spf13/jwalterweatherman"
 	"gitlab.com/elixxir/client/cmix/identity/receptionID"
-	"gitlab.com/elixxir/primitives/states"
 	"sync"
 	"time"
 
@@ -128,6 +127,8 @@ type EventModel interface {
 // types. Default ones for Text, Reaction, and AdminText.
 // A unique uuid must be returned by which the message can be referenced later
 // via UpdateSentStatus
+// It must return a unique UUID for the message by which it can be referenced
+// later
 type MessageTypeReceiveMessage func(channelID *id.ID,
 	messageID cryptoChannel.MessageID, messageType MessageType,
 	nickname string, content []byte, identity cryptoChannel.Identity,
@@ -221,18 +222,18 @@ func (e *events) triggerEvent(chID *id.ID, umi *userMessageInternal, ts time.Tim
 	return uuid, nil
 }
 
-type triggerAdminEventFunc func(chID *id.ID, cm *ChannelMessage,
+type triggerAdminEventFunc func(chID *id.ID, cm *ChannelMessage, ts time.Time,
 	messageID cryptoChannel.MessageID, receptionID receptionID.EphemeralIdentity,
-	round rounds.Round, status SentStatus)
+	round rounds.Round, status SentStatus) (uint64, error)
 
 // triggerAdminEvent is an internal function that is used to trigger message
 // reception on a message received from the admin (asymmetric encryption).
 //
 // It will call the appropriate MessageTypeHandler assuming one exists.
 func (e *events) triggerAdminEvent(chID *id.ID, cm *ChannelMessage,
-	messageID cryptoChannel.MessageID,
+	ts time.Time, messageID cryptoChannel.MessageID,
 	receptionID receptionID.EphemeralIdentity, round rounds.Round,
-	status SentStatus) {
+	status SentStatus) (uint64, error) {
 	messageType := MessageType(cm.PayloadType)
 
 	// check if the type is already registered
@@ -240,21 +241,19 @@ func (e *events) triggerAdminEvent(chID *id.ID, cm *ChannelMessage,
 	listener, exists := e.registered[messageType]
 	e.mux.RUnlock()
 	if !exists {
-		jww.WARN.Printf("Received Admin message from %s on channel %s in "+
+		errStr := fmt.Sprintf("Received Admin message from %s on channel %s in "+
 			"round %d which could not be handled due to unregistered message "+
 			"type %s; Contents: %v", AdminUsername, chID, round.ID, messageType,
 			cm.Payload)
-		return
+		jww.WARN.Printf(errStr)
+		return 0, errors.New(errStr)
 	}
 
-	// Modify the timestamp to reduce the chance message order will be ambiguous
-	ts := mutateTimestamp(round.Timestamps[states.QUEUED], messageID)
-
 	// Call the listener. This is already in an instanced event, no new thread needed.
-	listener(chID, messageID, messageType, AdminUsername, cm.Payload,
+	uuid := listener(chID, messageID, messageType, AdminUsername, cm.Payload,
 		cryptoChannel.Identity{Codename: AdminUsername}, ts,
 		time.Duration(cm.Lease), round, status)
-	return
+	return uuid, nil
 }
 
 // receiveTextMessage is the internal function that handles the reception of
diff --git a/channels/interface.go b/channels/interface.go
index fd029b16ec6404f93c3b45df65a29d0ea522fc46..fd22d6426a4bd77d26e22dc51042cfba070ecbf5 100644
--- a/channels/interface.go
+++ b/channels/interface.go
@@ -9,7 +9,6 @@ package channels
 
 import (
 	"gitlab.com/elixxir/client/cmix"
-	"gitlab.com/elixxir/client/cmix/pickup/store"
 	"gitlab.com/elixxir/client/cmix/rounds"
 	cryptoBroadcast "gitlab.com/elixxir/crypto/broadcast"
 	cryptoChannel "gitlab.com/elixxir/crypto/channel"
@@ -29,7 +28,7 @@ var ValidForever = time.Duration(math.MaxInt64)
 type Manager interface {
 
 	// GetIdentity returns the public identity associated with this channel manager
-	GetIdentity() store.Identity
+	GetIdentity() cryptoChannel.Identity
 
 	// GetStorageTag returns the tag at which this manager is store for loading
 	// it is derived from the public key
@@ -121,7 +120,7 @@ type Manager interface {
 
 	// DeleteNickname removes the nickname for a given channel, using the codename
 	// for that channel instead
-	DeleteNickname(ch *id.ID)
+	DeleteNickname(ch *id.ID) error
 
 	// GetNickname returns the nickname for the given channel if it exists
 	GetNickname(ch *id.ID) (nickname string, exists bool)
diff --git a/channels/joinedChannel.go b/channels/joinedChannel.go
index f3ff927bd0a9249df2ffd5fec246b00d63aef3aa..1b6aa53e7f9b2539b983c418eab52368d7c129c0 100644
--- a/channels/joinedChannel.go
+++ b/channels/joinedChannel.go
@@ -72,7 +72,7 @@ func (m *manager) loadChannels() {
 
 	for i := range chList {
 		jc, err := loadJoinedChannel(
-			chList[i], m.kv, m.net, m.rng, m.name, m.events, m.broadcastMaker,
+			chList[i], m.kv, m.net, m.rng, m.events, m.broadcastMaker,
 			m.st.MessageReceive)
 		if err != nil {
 			jww.FATAL.Panicf("Failed to load channel %s: %+v", chList[i], err)
@@ -111,7 +111,6 @@ func (m *manager) addChannel(channel *cryptoBroadcast.Channel) error {
 
 	// Connect to listeners
 	err = b.RegisterListener((&userListener{
-		name:      m.name,
 		chID:      channel.ReceptionID,
 		trigger:   m.events.triggerEvent,
 		checkSent: m.st.MessageReceive,
@@ -211,7 +210,7 @@ func (jc *joinedChannel) Store(kv *versioned.KV) error {
 
 // loadJoinedChannel loads a given channel from ekv storage.
 func loadJoinedChannel(chId *id.ID, kv *versioned.KV, net broadcast.Client,
-	rngGen *fastRNG.StreamGenerator, name NameService, e *events,
+	rngGen *fastRNG.StreamGenerator, e *events,
 	broadcastMaker broadcast.NewBroadcastChannelFunc, mr messageReceiveFunc) (*joinedChannel, error) {
 	obj, err := kv.Get(makeJoinedChannelKey(chId), joinedChannelVersion)
 	if err != nil {
@@ -225,7 +224,7 @@ func loadJoinedChannel(chId *id.ID, kv *versioned.KV, net broadcast.Client,
 		return nil, err
 	}
 
-	b, err := initBroadcast(jcd.Broadcast, name, e, net, broadcastMaker, rngGen, mr)
+	b, err := initBroadcast(jcd.Broadcast, e, net, broadcastMaker, rngGen, mr)
 
 	jc := &joinedChannel{broadcast: b}
 	return jc, nil
@@ -242,7 +241,7 @@ func makeJoinedChannelKey(chId *id.ID) string {
 }
 
 func initBroadcast(c *cryptoBroadcast.Channel,
-	name NameService, e *events, net broadcast.Client,
+	e *events, net broadcast.Client,
 	broadcastMaker broadcast.NewBroadcastChannelFunc,
 	rngGen *fastRNG.StreamGenerator, mr messageReceiveFunc) (broadcast.Channel, error) {
 	b, err := broadcastMaker(c, net, rngGen)
@@ -251,7 +250,6 @@ func initBroadcast(c *cryptoBroadcast.Channel,
 	}
 
 	err = b.RegisterListener((&userListener{
-		name:      name,
 		chID:      c.ReceptionID,
 		trigger:   e.triggerEvent,
 		checkSent: mr,
diff --git a/channels/manager.go b/channels/manager.go
index 71181eec14d26208b41c5f65a5e13fa89ec6ff91..ddbdb04f377457d0b10670ab1754dc2083a8a692 100644
--- a/channels/manager.go
+++ b/channels/manager.go
@@ -90,14 +90,13 @@ func NewManager(identity cryptoChannel.PrivateIdentity, kv *versioned.KV,
 
 	m := setupManager(identity, kv, net, rng, model)
 
-	return &m, nil
+	return m, nil
 }
 
 // LoadManager restores a channel.Manager from disk stored at the given
 //storage tag.
 func LoadManager(storageTag string, kv *versioned.KV, net Client,
-	rng *fastRNG.StreamGenerator, name NameService, model EventModel) (Manager,
-	error) {
+	rng *fastRNG.StreamGenerator, model EventModel) (Manager, error) {
 
 	// Prefix the kv with the username so multiple can be run
 	kv = kv.Prefix(storageTag)
@@ -110,7 +109,7 @@ func LoadManager(storageTag string, kv *versioned.KV, net Client,
 
 	m := setupManager(identity, kv, net, rng, model)
 
-	return &m
+	return m, nil
 }
 
 func setupManager(identity cryptoChannel.PrivateIdentity, kv *versioned.KV,
@@ -199,7 +198,7 @@ func (m *manager) ReplayChannel(chID *id.ID) error {
 	jc.broadcast.Stop()
 
 	//re-instantiate the broadcast, re-registering it from scratch
-	b, err := initBroadcast(c, m.name, m.events, m.net, m.broadcastMaker, m.rng,
+	b, err := initBroadcast(c, m.events, m.net, m.broadcastMaker, m.rng,
 		m.st.MessageReceive)
 	if err != nil {
 		return err
diff --git a/channels/nickname.go b/channels/nickname.go
index 71523d87e0df4933c41289ab3d306ed109fb8725..13dc43d074263018f12fbf6c2d2aab6dd62ab53d 100644
--- a/channels/nickname.go
+++ b/channels/nickname.go
@@ -129,12 +129,18 @@ func (nm *nicknameManager) load() error {
 // IsNicknameValid checks if a nickname is valid
 //
 // rules
-//   - a Nickname must not be longer than 24 characters
+//   - a nickname must not be longer than 24 characters
+//   - a nickname must not be shorter than 1 character
 // todo: add character filtering
-func IsNicknameValid(nm string) error {
-	if len([]rune(nm)) > 24 {
+func IsNicknameValid(nick string) error {
+	runeNick := []rune(nick)
+	if len(runeNick) > 24 {
 		return errors.New("nicknames must be 24 characters in length or less")
 	}
 
+	if len(runeNick) < 1 {
+		return errors.New("nicknames must be at least 1 character in length")
+	}
+
 	return nil
 }
diff --git a/channels/send.go b/channels/send.go
index 978c66e925d79691c9a6986c57b084f1ac99f70e..6d17fdab0b4e5634c2f97159e5235dee6a2bc52c 100644
--- a/channels/send.go
+++ b/channels/send.go
@@ -8,6 +8,7 @@
 package channels
 
 import (
+	"crypto/ed25519"
 	"gitlab.com/elixxir/client/cmix"
 	"gitlab.com/elixxir/client/cmix/rounds"
 	cryptoChannel "gitlab.com/elixxir/crypto/channel"
@@ -39,9 +40,21 @@ func (m *manager) SendGeneric(channelID *id.ID, messageType MessageType,
 		return cryptoChannel.MessageID{}, rounds.Round{}, ephemeral.Id{}, err
 	}
 
+	nickname, _ := m.nicknameManager.GetNickname(channelID)
+
 	var msgId cryptoChannel.MessageID
-	var usrMsg *UserMessage
-	var chMsg *ChannelMessage
+
+	chMsg := &ChannelMessage{
+		Lease:       validUntil.Nanoseconds(),
+		PayloadType: uint32(messageType),
+		Payload:     msg,
+		Nickname:    nickname,
+	}
+
+	usrMsg := &UserMessage{
+		ECCPublicKey: m.me.PubKey,
+	}
+
 	//Note: we are not checking check if message is too long before trying to
 	//find a round
 
@@ -49,12 +62,7 @@ func (m *manager) SendGeneric(channelID *id.ID, messageType MessageType,
 	assemble := func(rid id.Round) ([]byte, error) {
 
 		//Build the message
-		chMsg = &ChannelMessage{
-			Lease:       validUntil.Nanoseconds(),
-			RoundID:     uint64(rid),
-			PayloadType: uint32(messageType),
-			Payload:     msg,
-		}
+		chMsg.RoundID = uint64(rid)
 
 		//Serialize the message
 		chMsgSerial, err := proto.Marshal(chMsg)
@@ -66,22 +74,10 @@ func (m *manager) SendGeneric(channelID *id.ID, messageType MessageType,
 		msgId = cryptoChannel.MakeMessageID(chMsgSerial)
 
 		//Sign the message
-		messageSig, err := m.name.SignChannelMessage(chMsgSerial)
-		if err != nil {
-			return nil, err
-		}
+		messageSig := ed25519.Sign(*m.me.Privkey, chMsgSerial)
 
-		//Build the user message
-		validationSig, unameLease := m.name.GetChannelValidationSignature()
-
-		usrMsg = &UserMessage{
-			Message:             chMsgSerial,
-			ValidationSignature: validationSig,
-			Signature:           messageSig,
-			Username:            m.name.GetUsername(),
-			ECCPublicKey:        m.name.GetChannelPubkey(),
-			UsernameLease:       unameLease.UnixNano(),
-		}
+		usrMsg.Message = chMsgSerial
+		usrMsg.Signature = messageSig
 
 		//Serialize the user message
 		usrMsgSerial, err := proto.Marshal(usrMsg)
@@ -92,15 +88,17 @@ func (m *manager) SendGeneric(channelID *id.ID, messageType MessageType,
 		return usrMsgSerial, nil
 	}
 
+	uuid, err := m.st.denotePendingSend(channelID, &userMessageInternal{
+		userMessage:    usrMsg,
+		channelMessage: chMsg,
+		messageID:      msgId,
+	})
+
 	r, ephid, err := ch.broadcast.BroadcastWithAssembler(assemble, params)
 	if err != nil {
 		return cryptoChannel.MessageID{}, rounds.Round{}, ephemeral.Id{}, err
 	}
-	m.st.send(channelID, &userMessageInternal{
-		userMessage:    usrMsg,
-		channelMessage: chMsg,
-		messageID:      msgId,
-	}, r)
+	err = m.st.send(uuid, msgId, r)
 	return msgId, r, ephid, err
 }
 
@@ -121,7 +119,12 @@ func (m *manager) SendAdminGeneric(privKey rsa.PrivateKey, channelID *id.ID,
 	}
 
 	var msgId cryptoChannel.MessageID
-	var chMsg *ChannelMessage
+	chMsg := &ChannelMessage{
+		Lease:       validUntil.Nanoseconds(),
+		PayloadType: uint32(messageType),
+		Payload:     msg,
+		Nickname:    AdminUsername,
+	}
 	//Note: we are not checking check if message is too long before trying to
 	//find a round
 
@@ -129,12 +132,7 @@ func (m *manager) SendAdminGeneric(privKey rsa.PrivateKey, channelID *id.ID,
 	assemble := func(rid id.Round) ([]byte, error) {
 
 		//Build the message
-		chMsg = &ChannelMessage{
-			Lease:       validUntil.Nanoseconds(),
-			RoundID:     uint64(rid),
-			PayloadType: uint32(messageType),
-			Payload:     msg,
-		}
+		chMsg.RoundID = uint64(rid)
 
 		//Serialize the message
 		chMsgSerial, err := proto.Marshal(chMsg)
@@ -152,10 +150,18 @@ func (m *manager) SendAdminGeneric(privKey rsa.PrivateKey, channelID *id.ID,
 		return chMsgSerial, nil
 	}
 
+	uuid, err := m.st.denotePendingAdminSend(channelID, chMsg)
+	if err != nil {
+		return cryptoChannel.MessageID{}, rounds.Round{}, ephemeral.Id{}, err
+	}
+
 	r, ephid, err := ch.broadcast.BroadcastRSAToPublicWithAssembler(privKey,
 		assemble, params)
 
-	m.st.sendAdmin(channelID, chMsg, msgId, r)
+	err = m.st.sendAdmin(uuid, msgId, r)
+	if err != nil {
+		return cryptoChannel.MessageID{}, rounds.Round{}, ephemeral.Id{}, err
+	}
 	return msgId, r, ephid, err
 }
 
diff --git a/channels/sendTracker.go b/channels/sendTracker.go
index bc2205916823aa04ad70ef27642da18971eedee1..69fe04a1968d3c9157e47df2a257fe4e02f9dfb7 100644
--- a/channels/sendTracker.go
+++ b/channels/sendTracker.go
@@ -9,12 +9,14 @@ package channels
 
 import (
 	"encoding/json"
+	"errors"
 	jww "github.com/spf13/jwalterweatherman"
 	"gitlab.com/elixxir/client/cmix"
 	"gitlab.com/elixxir/client/cmix/identity/receptionID"
 	"gitlab.com/elixxir/client/cmix/rounds"
 	"gitlab.com/elixxir/client/storage/versioned"
 	cryptoChannel "gitlab.com/elixxir/crypto/channel"
+	"gitlab.com/elixxir/primitives/states"
 	"gitlab.com/xx_network/primitives/id"
 	"sync"
 	"time"
@@ -33,7 +35,7 @@ const (
 	// runs
 	maxChecks = 3
 
-	onePointFiveSeconds = 15000 * time.Millisecond
+	oneSecond = 1000 * time.Millisecond
 )
 
 type tracked struct {
@@ -190,11 +192,47 @@ func (st *sendTracker) load() error {
 	return nil
 }
 
+// denotePendingSend is called before the pending send. It tracks the send
+// internally and notifies the UI of the send
 func (st *sendTracker) denotePendingSend(channelID *id.ID,
-	umi *userMessageInternal, nickname string) {
-	ts := time.Now().Add(onePointFiveSeconds)
-	uuid := st.trigger(channelID, umi, ts, receptionID.EphemeralIdentity{},
+	umi *userMessageInternal) (uint64, error) {
+	// for a timestamp for the message, use 1 second from now to
+	// approximate the lag due to round submission
+	ts := time.Now().Add(oneSecond)
+
+	// submit the message to the UI
+	uuid, err := st.trigger(channelID, umi, ts, receptionID.EphemeralIdentity{},
+		rounds.Round{}, Unsent)
+	if err != nil {
+		return 0, err
+	}
+
+	// track the message on disk
+	st.handleDenoteSend(uuid, channelID, cryptoChannel.MessageID{},
+		rounds.Round{})
+	return uuid, nil
+}
+
+// denotePendingAdminSend is called before the pending admin send. It tracks the
+// send internally and notifies the UI of the send
+func (st *sendTracker) denotePendingAdminSend(channelID *id.ID,
+	cm *ChannelMessage) (uint64, error) {
+	// for a timestamp for the message, use 1 second from now to
+	// approximate the lag due to round submission
+	ts := time.Now().Add(oneSecond)
+
+	// submit the message to the UI
+	uuid, err := st.adminTrigger(channelID, cm, ts, cryptoChannel.MessageID{},
+		receptionID.EphemeralIdentity{},
 		rounds.Round{}, Unsent)
+
+	// track the message on disk
+	if err != nil {
+		return 0, err
+	}
+	st.handleDenoteSend(uuid, channelID, cryptoChannel.MessageID{},
+		rounds.Round{})
+	return uuid, nil
 }
 
 // handleDenoteSend does the nity gritty of editing internal structures
@@ -218,34 +256,62 @@ func (st *sendTracker) handleDenoteSend(uuid uint64, channelID *id.ID,
 }
 
 // send tracks a generic send message
-func (st *sendTracker) send(channelID *id.ID,
-	umi *userMessageInternal, round rounds.Round) {
-	st.handleSend(channelID, umi.GetMessageID(), round)
-	go st.trigger(channelID, umi,
-		receptionID.EphemeralIdentity{}, round, Sent)
+func (st *sendTracker) send(uuid uint64, msgID cryptoChannel.MessageID,
+	round rounds.Round) error {
+
+	// update the on disk message status
+	t, err := st.handleSend(uuid, msgID, round)
+	if err != nil {
+		return err
+	}
+
+	// Modify the timestamp to reduce the chance message order will be ambiguous
+	ts := mutateTimestamp(round.Timestamps[states.QUEUED], msgID)
+
+	//update the message on the UI
+	go st.updateStatus(t.UUID, msgID, ts, round, Sent)
+	return nil
 }
 
 // sendAdmin tracks a generic sendAdmin message
-func (st *sendTracker) sendAdmin(channelID *id.ID,
-	cm *ChannelMessage, msgID cryptoChannel.MessageID, round rounds.Round) {
-	st.handleSend(channelID, msgID, round)
-	go st.adminTrigger(channelID, cm, msgID,
-		receptionID.EphemeralIdentity{}, round, Sent)
+func (st *sendTracker) sendAdmin(uuid uint64, msgID cryptoChannel.MessageID,
+	round rounds.Round) error {
+
+	// update the on disk message status
+	t, err := st.handleSend(uuid, msgID, round)
+	if err != nil {
+		return err
+	}
+
+	// Modify the timestamp to reduce the chance message order will be ambiguous
+	ts := mutateTimestamp(round.Timestamps[states.QUEUED], msgID)
+
+	//update the message on the UI
+	go st.updateStatus(t.UUID, msgID, ts, round, Sent)
+
+	return nil
 }
 
 // handleSend does the nity gritty of editing internal structures
-func (st *sendTracker) handleSend(channelID *id.ID,
-	messageID cryptoChannel.MessageID, round rounds.Round) {
+func (st *sendTracker) handleSend(uuid uint64,
+	messageID cryptoChannel.MessageID, round rounds.Round) (*tracked, error) {
 	st.mux.Lock()
 	defer st.mux.Unlock()
 
-	//skip if already added
+	//check if in unsent
+	t, exists := st.unsent[uuid]
+	if !exists {
+		return nil, errors.New("cannot handle send on an unprepared message")
+	}
+
 	_, existsMessage := st.byMessageID[messageID]
 	if existsMessage {
-		return
+		return nil, errors.New("cannot handle send on a message which was " +
+			"already sent")
 	}
 
-	t := &tracked{messageID, channelID, round.ID}
+	t.MsgID = messageID
+	t.RoundID = round.ID
 
 	//add the roundID
 	roundsList, existsRound := st.byRound[round.ID]
@@ -263,10 +329,12 @@ func (st *sendTracker) handleSend(channelID *id.ID,
 	}
 
 	//store the changed list to disk
-	err := st.store()
+	err := st.storeSent()
 	if err != nil {
 		jww.FATAL.Panicf(err.Error())
 	}
+
+	return t, nil
 }
 
 // MessageReceive is used when a message is received to check if the message
@@ -317,7 +385,7 @@ type roundResults struct {
 
 // callback is called when results are known about a round. it will re-trigger
 // the wait if it fails up to 'maxChecks' times.
-func (rr *roundResults) callback(allRoundsSucceeded, timedOut bool, rounds map[id.Round]cmix.RoundResult) {
+func (rr *roundResults) callback(allRoundsSucceeded, timedOut bool, _ map[id.Round]cmix.RoundResult) {
 
 	rr.st.mux.Lock()
 
@@ -360,6 +428,7 @@ func (rr *roundResults) callback(allRoundsSucceeded, timedOut bool, rounds map[i
 	rr.st.mux.Unlock()
 
 	for i := range registered {
-		go rr.st.updateStatus(registered[i].MsgID, status)
+		go rr.st.updateStatus(registered[i].UUID, registered[i].MsgID, time.Time{},
+			rounds.Round{}, status)
 	}
 }
diff --git a/channels/userListener.go b/channels/userListener.go
index 575c05e54d5810a717610fff64b7b81ad754bc99..5e56121f9bb6c07007a61e4535e4ddc1c0bde84f 100644
--- a/channels/userListener.go
+++ b/channels/userListener.go
@@ -14,7 +14,6 @@ import (
 	"gitlab.com/elixxir/client/cmix/rounds"
 	"gitlab.com/elixxir/primitives/states"
 	"gitlab.com/xx_network/primitives/id"
-	"time"
 )
 
 // the userListener adheres to the [broadcast.ListenerFunc] interface and is
@@ -57,37 +56,25 @@ func (ul *userListener) Listen(payload []byte,
 		return
 	}
 
-	// check that the username lease is valid
-	usernameLeaseEnd := time.Unix(0, um.UsernameLease)
-	if !usernameLeaseEnd.After(round.Timestamps[states.QUEUED]) {
-		jww.WARN.Printf("Message %s on channel %s purportedly from %s "+
-			"has an expired lease, ended %s, round %d was sent at %s", msgID,
-			ul.chID, um.Username, usernameLeaseEnd, round.ID,
-			round.Timestamps[states.QUEUED])
-		return
-	}
-
-	// check that the signature from the nameserver is valid
-	if !ul.name.ValidateChannelMessage(um.Username,
-		time.Unix(0, um.UsernameLease), um.ECCPublicKey, um.ValidationSignature) {
-		jww.WARN.Printf("Message %s on channel %s purportedly from %s "+
-			"failed the check of its Name Server with signature %v", msgID,
-			ul.chID, um.Username, um.ValidationSignature)
-		return
-	}
-
 	// check that the user properly signed the message
 	if !ed25519.Verify(um.ECCPublicKey, um.Message, um.Signature) {
 		jww.WARN.Printf("Message %s on channel %s purportedly from %s "+
 			"failed its user signature with signature %v", msgID,
-			ul.chID, um.Username, um.Signature)
+			ul.chID, cm.Nickname, um.Signature)
 		return
 	}
 
+	// Modify the timestamp to reduce the chance message order will be ambiguous
+	ts := mutateTimestamp(round.Timestamps[states.QUEUED], msgID)
+
 	//TODO: Processing of the message relative to admin commands will be here
 
 	//Submit the message to the event model for listening
-	ul.trigger(ul.chID, umi, receptionID, round, Delivered)
+	if uuid, err := ul.trigger(ul.chID, umi, ts, receptionID, round,
+		Delivered); err != nil {
+		jww.WARN.Printf("Error in passing off trigger for "+
+			"message (UUID: %d): %+v", uuid, err)
+	}
 
 	return
 }
diff --git a/cmix/identity/receptionID/store.go b/cmix/identity/receptionID/store.go
index 78400d30f9d1bd15e1ef03c22a01f096c091abbe..967c22e034270d726b2c4e216d460dc767e0dbd2 100644
--- a/cmix/identity/receptionID/store.go
+++ b/cmix/identity/receptionID/store.go
@@ -29,7 +29,8 @@ const (
 	receptionStoreStorageVersion = 0
 )
 
-var InvalidRequestedNumIdentities = errors.New("cannot get less than one identity(s)")code
+var InvalidRequestedNumIdentities = errors.New("cannot get less than one identity(s)")
+
 type Store struct {
 	// Identities which are being actively checked
 	active  []*registration